char.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. /* char.c Copyright (C) 1989-99 Codemist Ltd */
  2. /*
  3. * Character handling.
  4. */
  5. /* Signature: 786dda9c 18-Feb-1999 */
  6. #include <stdarg.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <math.h>
  10. #include "machine.h"
  11. #include "tags.h"
  12. #include "cslerror.h"
  13. #include "externs.h"
  14. #include "entries.h"
  15. #include "read.h"
  16. #ifdef TIMEOUT
  17. #include "timeout.h"
  18. #endif
  19. #ifdef Kanji
  20. #define ISalpha(a) iswalpha(a)
  21. #define ISdigit(a) iswdigit(a)
  22. #define ISalnum(a) iswalnum(a)
  23. #define ISspace(a) iswspace(a)
  24. #define ISgraph(a) iswgraph(a)
  25. #define ISupper(a) iswupper(a)
  26. #define ISlower(a) iswlower(a)
  27. #define TOupper(a) towupper(a)
  28. #define TOlower(a) towlower(a)
  29. int first_char(Lisp_Object ch)
  30. { /* ch is a symbol. Get the first character of its name. */
  31. int n;
  32. ch = qpname(ch);
  33. n = celt(ch, 0);
  34. if (is2byte(n) && length_of_header(vechdr(ch)) != CELL)
  35. n = (n << 8) + ucelt(ch, 1);
  36. return n;
  37. }
  38. #else /* Kanji */
  39. #define ISalpha(a) isalpha(a)
  40. #define ISdigit(a) isdigit(a)
  41. #define ISalnum(a) isalnum(a)
  42. #define ISspace(a) isspace(a)
  43. #define ISgraph(a) isgraph(a)
  44. #define ISupper(a) isupper(a)
  45. #define ISlower(a) islower(a)
  46. #define TOupper(a) toupper(a)
  47. #define TOlower(a) tolower(a)
  48. #define first_char(a) celt(qpname(a), 0)
  49. #endif /* Kanji */
  50. /*
  51. * For many character functions I will permit the argument to be either
  52. * a character object (Common Lisp syntax #\x) or a symbol. If it is a
  53. * symbol the "character" tested will be the first one in the print-name,
  54. * and (of course) very often I will just use the symbols 'a, 'b, 'c etc
  55. * to stand for the characters #\a, #\b, #\c....
  56. * Common Lisp seens to say that character functions ought to be handed
  57. * real character objects - so extending this to permit symbols as well
  58. * is probably safe. If it were not I could just redefine this macro as
  59. * a null expansion in Common Lisp mode.
  60. * NB gensyms are OK here since I only need the 1st char of the base-name
  61. */
  62. #ifdef Kanji
  63. #define characterify(c) \
  64. if (is_symbol(c)) c = pack_char(0,0, \
  65. is2byte(celt(qpname(c), 0)) ? \
  66. (ucelt(qpname(c),0)<<8) + ucelt(qpname(c),1) : \
  67. celt(qpname(c), 0) \
  68. )
  69. #else
  70. #define characterify(c) \
  71. if (is_symbol(c)) c = pack_char(0,0, ucelt(qpname(c), 0))
  72. #endif
  73. #ifndef COMMON
  74. static Lisp_Object char_to_id(int ch)
  75. {
  76. Lisp_Object nil = C_nil;
  77. Lisp_Object w;
  78. #ifdef Kanji
  79. if (iswchar(c))
  80. { celt(boffo, 0) = c>>8;
  81. celt(boffo, 1) = c;
  82. w = iintern(boffo, 2, lisp_package, 0);
  83. errexit();
  84. return onevalue(w);
  85. }
  86. #endif
  87. w = elt(charvec, ch & 0xff);
  88. if (w == nil)
  89. { celt(boffo, 0) = ch;
  90. w = iintern(boffo, 1, lisp_package, 0);
  91. errexit();
  92. elt(charvec, ch & 0xff) = w;
  93. }
  94. return onevalue(w);
  95. }
  96. #endif
  97. /*
  98. * Characters have 8 bits of BITS, then 8 of FONT, then 8 of CODE.
  99. * The BITS and FONT information is only used in COMMON mode.
  100. * Even though Common Lisp refers to the components of a character
  101. * in the order BITS/FONT/CODE I store them as FONT/BITS/CODE so it
  102. * is then easy to store international characters as FONT/CODE16. The
  103. * option "Kanji" enables some use of this.
  104. */
  105. static Lisp_Object Lchar_downcase(Lisp_Object nil, Lisp_Object a)
  106. {
  107. int cc;
  108. CSL_IGNORE(nil);
  109. characterify(a);
  110. if (!is_char(a)) return aerror("char-downcase");
  111. cc = code_of_char(a);
  112. if (ISupper(cc)) /* Caution to help non-ANSI libraries */
  113. cc = TOlower(cc);
  114. #ifdef COMMON
  115. #ifdef Kanji
  116. #define insert_code(old, new) \
  117. (((old) & 0xff0000ff) | ((((int32)(new)) & 0xffff) << 8))
  118. #else
  119. #define insert_code(old, new) \
  120. (((old) & 0xffff00ff) | ((((int32)(new)) & 0xff) << 8))
  121. #endif
  122. return onevalue(insert_code(a, cc));
  123. #else
  124. return char_to_id(cc);
  125. #endif
  126. }
  127. #ifdef COMMON
  128. Lisp_Object Lcharacter(Lisp_Object nil, Lisp_Object a)
  129. {
  130. if (is_char(a)) return onevalue(a);
  131. else if (is_vector(a))
  132. { Header h = vechdr(a);
  133. if (type_of_header(h) == TYPE_STRING)
  134. { if (length_of_header(h) > 4)
  135. { int c0 = celt(a, 0);
  136. #ifdef Kanji
  137. if (length_of_header(h) > 5 && iswchar(c0))
  138. c0 = (c0 << 8) + ucelt(a, 1);
  139. #endif
  140. return onevalue(pack_char(0,0,c0));
  141. else return aerror1("character", a);
  142. }
  143. /*
  144. * The issue of strings (especially non-simple ones) and the ELT function
  145. * and wide characters has NOT BEEN THOUGHT THROUGH.
  146. */
  147. else if (stringp(a))
  148. { Lisp_Object w = Lelt(nil, a, fixnum_of_int(0));
  149. errexit();
  150. return onevalue(w);
  151. }
  152. else return aerror1("character", a);
  153. }
  154. else if (is_fixnum(a))
  155. #ifdef Kanji
  156. return onevalue(pack_char(0, 0, int_of_fixnum(a) & 0xffff));
  157. #else
  158. return onevalue(pack_char(0, 0, int_of_fixnum(a) & 0xff));
  159. #endif
  160. else if (is_symbol(a)) return Lcharacter(nil, qpname(a));
  161. else return aerror1("character", a);
  162. }
  163. static Lisp_Object Lcharacterp(Lisp_Object nil, Lisp_Object a)
  164. {
  165. return onevalue(Lispify_predicate(is_char(a)));
  166. }
  167. static Lisp_Object Lchar_bits(Lisp_Object nil, Lisp_Object a)
  168. {
  169. CSL_IGNORE(nil);
  170. characterify(a);
  171. if (!is_char(a)) return aerror("char-bits");
  172. return onevalue(fixnum_of_int(bits_of_char(a)));
  173. }
  174. static Lisp_Object Lchar_font(Lisp_Object nil, Lisp_Object a)
  175. {
  176. CSL_IGNORE(nil);
  177. characterify(a);
  178. if (!is_char(a)) return aerror("char-font");
  179. return onevalue(fixnum_of_int(font_of_char(a)));
  180. }
  181. #endif
  182. static Lisp_Object Lchar_upcase(Lisp_Object nil, Lisp_Object a)
  183. {
  184. int cc;
  185. CSL_IGNORE(nil);
  186. characterify(a);
  187. if (!is_char(a)) return aerror("char-upcase");
  188. cc = code_of_char(a);
  189. if (ISlower(cc))
  190. cc = TOupper(cc);
  191. #ifdef COMMON
  192. return onevalue(insert_code(a, cc));
  193. #else
  194. return char_to_id(cc);
  195. #endif
  196. }
  197. Lisp_Object Lwhitespace_char_p(Lisp_Object nil, Lisp_Object a)
  198. {
  199. int cc;
  200. characterify(a);
  201. if (!is_char(a)) return onevalue(nil);
  202. if (a == CHAR_EOF
  203. #ifndef Kanji
  204. || bits_of_char(a) != 0
  205. #endif
  206. ) return onevalue(nil);
  207. /* BITS present => not whitespace (unless Kanji) */
  208. cc = code_of_char(a);
  209. return onevalue(Lispify_predicate(ISspace(cc)));
  210. }
  211. Lisp_Object Lalpha_char_p(Lisp_Object nil, Lisp_Object a)
  212. {
  213. int cc;
  214. characterify(a);
  215. if (!is_char(a)) return onevalue(nil);
  216. #ifndef Kanji
  217. if (bits_of_char(a) != 0) return onevalue(nil); /* BITS present */
  218. #endif
  219. cc = code_of_char(a);
  220. return onevalue(Lispify_predicate(ISalpha(cc)));
  221. }
  222. #ifdef COMMON
  223. static Lisp_Object Lgraphic_char_p(Lisp_Object nil, Lisp_Object a)
  224. {
  225. int cc;
  226. characterify(a);
  227. if (!is_char(a)) return onevalue(nil);
  228. #ifndef Kanji
  229. if (bits_of_char(a) != 0) return onevalue(nil); /* BITS present */
  230. #endif
  231. cc = code_of_char(a);
  232. return onevalue(Lispify_predicate(ISgraph(cc) || cc==' '));
  233. }
  234. static Lisp_Object Lupper_case_p(Lisp_Object nil, Lisp_Object a)
  235. {
  236. int cc;
  237. characterify(a);
  238. if (!is_char(a)) return onevalue(nil);
  239. #ifndef Kanji
  240. if (bits_of_char(a) != 0) return onevalue(nil);
  241. #endif
  242. cc = code_of_char(a);
  243. return onevalue(Lispify_predicate(ISupper(cc)));
  244. }
  245. static Lisp_Object Llower_case_p(Lisp_Object nil, Lisp_Object a)
  246. {
  247. int cc;
  248. characterify(a);
  249. if (!is_char(a)) return onevalue(nil);
  250. #ifndef Kanji
  251. if (bits_of_char(a) != 0) return onevalue(nil);
  252. #endif
  253. cc = code_of_char(a);
  254. return onevalue(Lispify_predicate(ISlower(cc)));
  255. }
  256. #endif
  257. #ifdef COMMON
  258. Lisp_Object Ldigit_char_p_2(Lisp_Object nil, Lisp_Object a, Lisp_Object radix)
  259. {
  260. int cc;
  261. Lisp_Object r = radix;
  262. if (!is_fixnum(r) || r < fixnum_of_int(2) ||
  263. r >= fixnum_of_int(36)) return aerror("digit-char-p");
  264. characterify(a);
  265. if (!is_char(a)) return onevalue(nil);
  266. #ifndef Kanji
  267. if (bits_of_char(a) != 0) return onevalue(nil);
  268. #endif
  269. cc = code_of_char(a);
  270. if (!ISalnum(cc)) return onevalue(nil);
  271. if (ISupper(cc))
  272. cc = TOlower(cc);
  273. /*
  274. * The following code is intended to cope with EBCDIC as well as ASCII
  275. * character codes. The effect is still notionally not portable in that
  276. * a yet further character code (with 'a' to 'i' non-consecutive, say)
  277. * would defeat it!
  278. */
  279. if ('0' <= cc && cc <= '9') cc = cc - '0';
  280. else if ('a' <= cc && cc <= 'i') cc = cc - 'a' + 10;
  281. else if ('j' <= cc && cc <= 'r') cc = cc - 'j' + 19;
  282. else if ('s' <= cc && cc <= 'z') cc = cc - 's' + 28;
  283. else cc = 255;
  284. if (cc >= int_of_fixnum(r)) return onevalue(nil);
  285. else return onevalue(fixnum_of_int((int32)cc));
  286. }
  287. Lisp_Object Ldigit_char_p_1(Lisp_Object nil, Lisp_Object a)
  288. {
  289. return Ldigit_char_p_2(nil, a, fixnum_of_int(10));
  290. }
  291. #endif
  292. Lisp_Object Ldigitp(Lisp_Object nil, Lisp_Object a)
  293. {
  294. int cc;
  295. characterify(a);
  296. if (!is_char(a)) return onevalue(nil);
  297. #ifndef Kanji
  298. if (bits_of_char(a) != 0) return onevalue(nil);
  299. #endif
  300. cc = code_of_char(a);
  301. return onevalue(Lispify_predicate(ISdigit(cc)));
  302. }
  303. #ifdef COMMON
  304. static Lisp_Object MS_CDECL Ldigit_char_n(Lisp_Object nil, int nargs, ...)
  305. {
  306. va_list aa;
  307. Lisp_Object a, r, f;
  308. if (nargs != 3) return aerror("digit-char");
  309. va_start(aa, nargs);
  310. a = va_arg(aa, Lisp_Object);
  311. r = va_arg(aa, Lisp_Object);
  312. f = va_arg(aa, Lisp_Object);
  313. va_end(aa);
  314. if (!is_fixnum(a) || !is_fixnum(r) || !is_fixnum(f) ||
  315. a < 0 || r < fixnum_of_int(2) || f < 0 ||
  316. a >= r || r > fixnum_of_int(36) ||
  317. f > fixnum_of_int(255)) return onevalue(nil);
  318. /*
  319. * The following code is intended to cope with EBCDIC as well as ASCII
  320. * character codes. See comment in digit_char_p().
  321. */
  322. a = int_of_fixnum(a);
  323. if (a <= 9) a = a + '0';
  324. else if (a <= 18) a = a + ('A' - 10);
  325. else if (a <= 27) a = a + ('J' - 19);
  326. else a = a + ('S' - 28);
  327. return onevalue(pack_char(0, int_of_fixnum(f) & 0xff, a & 0xff));
  328. }
  329. static Lisp_Object Ldigit_char_2(Lisp_Object nil, Lisp_Object a,
  330. Lisp_Object r1)
  331. {
  332. return Ldigit_char_n(nil, 3, a, r1, fixnum_of_int(0));
  333. }
  334. static Lisp_Object Ldigit_char_1(Lisp_Object nil, Lisp_Object a)
  335. {
  336. return Ldigit_char_n(nil, 3, a, fixnum_of_int(10), fixnum_of_int(0));
  337. }
  338. #endif
  339. Lisp_Object Lspecial_char(Lisp_Object nil, Lisp_Object a)
  340. {
  341. CSL_IGNORE(nil);
  342. if (!is_fixnum(a)) return aerror("special-char");
  343. switch (int_of_fixnum(a))
  344. {
  345. case 0: /* space */
  346. a = pack_char(0, 0, ' ');
  347. break;
  348. case 1: /* newline */
  349. a = pack_char(0, 0, '\n');
  350. break;
  351. case 2: /* backspace */
  352. a = pack_char(0, 0, '\b');
  353. break;
  354. case 3: /* tab */
  355. a = pack_char(0, 0, '\t');
  356. break;
  357. case 4: /* linefeed (well, I use VT, '\v' in C terms) */
  358. a = pack_char(0, 0, '\v');
  359. break;
  360. case 5: /* page */
  361. a = pack_char(0, 0, '\f');
  362. break;
  363. case 6: /* return */
  364. a = pack_char(0, 0, '\r');
  365. break;
  366. case 7: /* rubout: not available in EBCDIC, sorry */
  367. a = pack_char(0, 0, 0x7fL);
  368. break;
  369. case 8: /* end of file character */
  370. a = CHAR_EOF;
  371. break;
  372. case 9: /* 'attention', typically ctrl-G */
  373. a = pack_char(0, 0, '\a');
  374. break;
  375. case 10: /* 'ESC', not available on all computers! */
  376. a = pack_char(0, 0, 0x1b);
  377. break;
  378. default:
  379. return aerror("special-char");
  380. }
  381. /*
  382. * What about this and Standard Lisp mode??? Well it still hands back
  383. * a "character object", and these are generally not at all useful in
  384. * Standard Lisp. Two exceptions occur - first character objects are
  385. * valid in lists handed to compress, and secondly the character object
  386. * for end-of-file is used for that in Standard Lisp mode.
  387. */
  388. return onevalue(a);
  389. }
  390. Lisp_Object Lchar_code(Lisp_Object nil, Lisp_Object a)
  391. {
  392. CSL_IGNORE(nil);
  393. characterify(a);
  394. if (!is_char(a)) return aerror("char-code");
  395. return onevalue(fixnum_of_int(code_of_char(a)));
  396. }
  397. static Lisp_Object MS_CDECL Lcode_charn(Lisp_Object nil, int nargs, ...)
  398. {
  399. va_list aa;
  400. Lisp_Object a, bits, font;
  401. int32 av;
  402. argcheck(nargs, 3, "code-char");
  403. va_start(aa, nargs);
  404. a = va_arg(aa, Lisp_Object);
  405. bits = va_arg(aa, Lisp_Object);
  406. font = va_arg(aa, Lisp_Object);
  407. va_end(aa);
  408. CSL_IGNORE(nil);
  409. if ((int32)bits < 0 || (int32)bits >= (int32)fixnum_of_int(16L) ||
  410. (int32)font < 0 || (int32)font >= (int32)fixnum_of_int(256L) ||
  411. #ifdef Kanji
  412. (int32)a < 0 || (int32)a >= (int32)fixnum_of_int(65536L)
  413. #else
  414. (int32)a < 0 || (int32)a >= (int32)fixnum_of_int(256L)
  415. #endif
  416. )
  417. return aerror("code-char");
  418. #ifdef Kanji
  419. av = int_of_fixnum(a) & 0xffff;
  420. #else
  421. av = int_of_fixnum(a) & 0xff;
  422. #endif
  423. #ifdef COMMON
  424. return onevalue(pack_char(int_of_fixnum(bits),
  425. int_of_fixnum(font) & 0xff,
  426. av));
  427. #else
  428. return char_to_id(av);
  429. #endif
  430. }
  431. static Lisp_Object Lcode_char1(Lisp_Object nil, Lisp_Object a)
  432. {
  433. return Lcode_charn(nil, 3, a, fixnum_of_int(0), fixnum_of_int(0));
  434. }
  435. static Lisp_Object Lcode_char2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  436. {
  437. return Lcode_charn(nil, 3, a, b, fixnum_of_int(0));
  438. }
  439. #ifdef COMMON
  440. static Lisp_Object Lchar_int(Lisp_Object nil, Lisp_Object a)
  441. {
  442. CSL_IGNORE(nil);
  443. characterify(a);
  444. if (!is_char(a)) return aerror("char-int");
  445. return onevalue(fixnum_of_int(((unsigned32)a) >> 8));
  446. }
  447. static Lisp_Object Lint_char(Lisp_Object nil, Lisp_Object a)
  448. {
  449. if (!is_fixnum(a) || (a & 0xff000000L) != 0) return nil;
  450. return onevalue(TAG_CHAR + (int_of_fixnum(a) << 8));
  451. }
  452. static Lisp_Object MS_CDECL Lmake_char(Lisp_Object nil, int nargs, ...)
  453. {
  454. va_list aa;
  455. Lisp_Object a, bits, font;
  456. CSL_IGNORE(nil);
  457. if (nargs == 0 || nargs > 3) return aerror("make-char");
  458. va_start(aa, nargs);
  459. a = va_arg(aa, Lisp_Object);
  460. if (nargs > 1) bits = va_arg(aa, Lisp_Object);
  461. else bits = fixnum_of_int(0);
  462. if (nargs > 2) font = va_arg(aa, Lisp_Object);
  463. else font = fixnum_of_int(0);
  464. va_end(aa);
  465. if (bits < 0 || bits >= fixnum_of_int(16L) ||
  466. font < 0 || font >= fixnum_of_int(256L) ||
  467. !is_char(a)) return aerror("make-char");
  468. return onevalue(pack_char(int_of_fixnum(bits),
  469. int_of_fixnum(font) & 0xff,
  470. #ifdef Kanji
  471. code_of_char(a) & 0xffff));
  472. #else
  473. code_of_char(a) & 0xff));
  474. #endif
  475. }
  476. /*
  477. * Character comparisons are VERY like the arithmetic ones, but need
  478. * only deal with character objects, which are immediate data and
  479. * in general terms nicer.
  480. */
  481. static bool chartest(Lisp_Object c)
  482. {
  483. if (!is_char(c))
  484. { aerror1("Character object expected", c);
  485. return YES;
  486. }
  487. else return NO;
  488. }
  489. static Lisp_Object MS_CDECL Lchar_eqn(Lisp_Object nil, int nargs, ...)
  490. {
  491. va_list a;
  492. Lisp_Object r;
  493. int i;
  494. if (nargs < 2) return onevalue(lisp_true);
  495. if (nargs > ARG_CUT_OFF)
  496. return aerror("too many args for character comparison");
  497. va_start(a, nargs);
  498. r = va_arg(a, Lisp_Object);
  499. if (chartest(r)) { va_end(a); return nil; }
  500. for (i = 1; i<nargs; i++)
  501. { Lisp_Object s = va_arg(a, Lisp_Object);
  502. if (chartest(s)) { va_end(a); return nil; }
  503. if (r != s)
  504. { va_end(a);
  505. return onevalue(nil);
  506. }
  507. r = s;
  508. }
  509. va_end(a);
  510. return onevalue(lisp_true);
  511. }
  512. static Lisp_Object Lchar_eqn_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  513. {
  514. return Lchar_eqn(nil, 2, a, b);
  515. }
  516. static Lisp_Object Lchar_eqn_1(Lisp_Object nil, Lisp_Object a)
  517. {
  518. return Lchar_eqn(nil, 1, a);
  519. }
  520. static Lisp_Object MS_CDECL Lchar_lessp(Lisp_Object nil, int nargs, ...)
  521. {
  522. va_list a;
  523. Lisp_Object r;
  524. int i;
  525. if (nargs < 2) return onevalue(lisp_true);
  526. if (nargs > ARG_CUT_OFF)
  527. return aerror("too many args for character comparison");
  528. va_start(a, nargs);
  529. r = va_arg(a, Lisp_Object);
  530. if (chartest(r)) { va_end(a); return nil; }
  531. for (i = 1; i<nargs; i++)
  532. { Lisp_Object s = va_arg(a, Lisp_Object);
  533. if (chartest(s)) { va_end(a); return nil; }
  534. if ((unsigned32)r >= (unsigned32)s)
  535. { va_end(a);
  536. return onevalue(nil);
  537. }
  538. r = s;
  539. }
  540. va_end(a);
  541. return onevalue(lisp_true);
  542. }
  543. static Lisp_Object Lchar_lessp_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  544. {
  545. return Lchar_lessp(nil, 2, a, b);
  546. }
  547. static Lisp_Object Lchar_lessp_1(Lisp_Object nil, Lisp_Object a)
  548. {
  549. return Lchar_lessp(nil, 1, a);
  550. }
  551. static Lisp_Object MS_CDECL Lchar_greaterp(Lisp_Object nil, int nargs, ...)
  552. {
  553. va_list a;
  554. Lisp_Object r;
  555. int i;
  556. if (nargs < 2) return onevalue(lisp_true);
  557. if (nargs > ARG_CUT_OFF)
  558. return aerror("too many args for character comparison");
  559. va_start(a, nargs);
  560. r = va_arg(a, Lisp_Object);
  561. if (chartest(r)) { va_end(a); return nil; }
  562. for (i = 1; i<nargs; i++)
  563. { Lisp_Object s = va_arg(a, Lisp_Object);
  564. if (chartest(s)) { va_end(a); return nil; }
  565. if ((unsigned32)r <= (unsigned32)s)
  566. { va_end(a);
  567. return onevalue(nil);
  568. }
  569. r = s;
  570. }
  571. va_end(a);
  572. return onevalue(lisp_true);
  573. }
  574. static Lisp_Object Lchar_greaterp_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  575. {
  576. return Lchar_greaterp(nil, 2, a, b);
  577. }
  578. static Lisp_Object Lchar_greaterp_1(Lisp_Object nil, Lisp_Object a)
  579. {
  580. return Lchar_greaterp(nil, 1, a);
  581. }
  582. static Lisp_Object MS_CDECL Lchar_neq_n(Lisp_Object nil, int nargs, ...)
  583. /*
  584. * /= is supposed to check that NO pair of args match.
  585. * Because this involves multiple scanning of the vector of args it seems
  586. * necessary to copy the arge into a vector that I can scan more directly
  587. * than va_args lets me scan the arg list.
  588. */
  589. {
  590. int i, j;
  591. va_list a;
  592. Lisp_Object *r;
  593. if (nargs < 2) return onevalue(lisp_true);
  594. if (nargs > ARG_CUT_OFF)
  595. return aerror("too many args for character comparison");
  596. r = (Lisp_Object *)&work_1;
  597. va_start(a, nargs);
  598. for (i=0; i<nargs; i++) r[i] = va_arg(a, Lisp_Object);
  599. va_end(a);
  600. if (chartest(r[0])) return nil;
  601. for (i = 1; i<nargs; i++)
  602. { Lisp_Object n1 = r[i];
  603. if (chartest(n1)) return nil;
  604. for (j=0; j<i; j++)
  605. { Lisp_Object n2 = r[j];
  606. if (n1 == n2) return onevalue(nil);
  607. }
  608. }
  609. return onevalue(lisp_true);
  610. }
  611. static Lisp_Object Lchar_neq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  612. {
  613. return Lchar_neq_n(nil, 2, a, b);
  614. }
  615. static Lisp_Object Lchar_neq_1(Lisp_Object nil, Lisp_Object a)
  616. {
  617. return Lchar_neq_n(nil, 1, a);
  618. }
  619. static Lisp_Object MS_CDECL Lchar_geq(Lisp_Object nil, int nargs, ...)
  620. {
  621. va_list a;
  622. Lisp_Object r;
  623. int i;
  624. if (nargs < 2) return onevalue(lisp_true);
  625. if (nargs > ARG_CUT_OFF)
  626. return aerror("too many args for character comparison");
  627. va_start(a, nargs);
  628. r = va_arg(a, Lisp_Object);
  629. if (chartest(r)) { va_end(a); return nil; }
  630. for (i = 1; i<nargs; i++)
  631. { Lisp_Object s = va_arg(a, Lisp_Object);
  632. if (chartest(s)) { va_end(a); return nil; }
  633. if ((unsigned32)r < (unsigned32)s)
  634. { va_end(a);
  635. return onevalue(nil);
  636. }
  637. r = s;
  638. }
  639. va_end(a);
  640. return onevalue(lisp_true);
  641. }
  642. static Lisp_Object Lchar_geq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  643. {
  644. return Lchar_geq(nil, 2, a, b);
  645. }
  646. static Lisp_Object Lchar_geq_1(Lisp_Object nil, Lisp_Object a)
  647. {
  648. return Lchar_geq(nil, 1, a);
  649. }
  650. static Lisp_Object MS_CDECL Lchar_leq(Lisp_Object nil, int nargs, ...)
  651. {
  652. va_list a;
  653. Lisp_Object r;
  654. int i;
  655. if (nargs < 2) return onevalue(lisp_true);
  656. if (nargs > ARG_CUT_OFF)
  657. return aerror("too many args for character comparison");
  658. va_start(a, nargs);
  659. r = va_arg(a, Lisp_Object);
  660. if (chartest(r)) { va_end(a); return nil; }
  661. for (i = 1; i<nargs; i++)
  662. { Lisp_Object s = va_arg(a, Lisp_Object);
  663. if (chartest(s)) { va_end(a); return nil; }
  664. if ((unsigned32)r > (unsigned32)s)
  665. { va_end(a);
  666. return onevalue(nil);
  667. }
  668. r = s;
  669. }
  670. va_end(a);
  671. return onevalue(lisp_true);
  672. }
  673. static Lisp_Object Lchar_leq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  674. {
  675. return Lchar_leq(nil, 2, a, b);
  676. }
  677. static Lisp_Object Lchar_leq_1(Lisp_Object nil, Lisp_Object a)
  678. {
  679. return Lchar_leq(nil, 1, a);
  680. }
  681. /*
  682. * Character comparisons are VERY like the arithmetic ones, but need
  683. * only deal with character objects, which are immediate data and
  684. * in general terms nicer. These versions look only at the code, not
  685. * at the case or the bits attributes.
  686. */
  687. static Lisp_Object casefold(Lisp_Object c)
  688. {
  689. int cc;
  690. if (!is_char(c)) return aerror("Character object expected");
  691. cc = code_of_char(c); /* Character in the C sense */
  692. cc = TOupper(cc);
  693. return insert_code(c, cc);
  694. }
  695. static Lisp_Object MS_CDECL Lcharacter_eqn(Lisp_Object nil, int nargs, ...)
  696. {
  697. va_list a;
  698. Lisp_Object r;
  699. int i;
  700. if (nargs < 2) return onevalue(lisp_true);
  701. if (nargs > ARG_CUT_OFF)
  702. return aerror("too many args for character comparison");
  703. va_start(a, nargs);
  704. r = va_arg(a, Lisp_Object);
  705. r = casefold(r);
  706. nil = C_nil;
  707. if (exception_pending()) { va_end(a); return nil; }
  708. for (i = 1; i<nargs; i++)
  709. { Lisp_Object s = va_arg(a, Lisp_Object);
  710. s = casefold(s);
  711. nil = C_nil;
  712. if (exception_pending()) { va_end(a); return nil; }
  713. if (r != s)
  714. { va_end(a);
  715. return onevalue(nil);
  716. }
  717. r = s;
  718. }
  719. va_end(a);
  720. return onevalue(lisp_true);
  721. }
  722. static Lisp_Object Lcharacter_eqn_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  723. {
  724. return Lcharacter_eqn(nil, 2, a, b);
  725. }
  726. static Lisp_Object Lcharacter_eqn_1(Lisp_Object nil, Lisp_Object a)
  727. {
  728. return Lcharacter_eqn(nil, 1, a);
  729. }
  730. static Lisp_Object MS_CDECL Lcharacter_lessp(Lisp_Object nil, int nargs, ...)
  731. {
  732. va_list a;
  733. Lisp_Object r;
  734. int i;
  735. if (nargs < 2) return onevalue(lisp_true);
  736. if (nargs > ARG_CUT_OFF)
  737. return aerror("too many args for character comparison");
  738. va_start(a, nargs);
  739. r = va_arg(a, Lisp_Object);
  740. r = casefold(r);
  741. nil = C_nil;
  742. if (exception_pending()) { va_end(a); return nil; }
  743. for (i = 1; i<nargs; i++)
  744. { Lisp_Object s = va_arg(a, Lisp_Object);
  745. s = casefold(s);
  746. nil = C_nil;
  747. if (exception_pending()) { va_end(a); return nil; }
  748. if ((unsigned32)r >= (unsigned32)s)
  749. { va_end(a);
  750. return onevalue(nil);
  751. }
  752. r = s;
  753. }
  754. va_end(a);
  755. return onevalue(lisp_true);
  756. }
  757. static Lisp_Object Lcharacter_lessp_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  758. {
  759. return Lcharacter_lessp(nil, 2, a, b);
  760. }
  761. static Lisp_Object Lcharacter_lessp_1(Lisp_Object nil, Lisp_Object a)
  762. {
  763. return Lcharacter_lessp(nil, 1, a);
  764. }
  765. static Lisp_Object MS_CDECL Lcharacter_greaterp(Lisp_Object nil, int nargs, ...)
  766. {
  767. va_list a;
  768. Lisp_Object r;
  769. int i;
  770. if (nargs < 2) return onevalue(lisp_true);
  771. if (nargs > ARG_CUT_OFF)
  772. return aerror("too many args for character comparison");
  773. va_start(a, nargs);
  774. r = va_arg(a, Lisp_Object);
  775. r = casefold(r);
  776. nil = C_nil;
  777. if (exception_pending()) { va_end(a); return nil; }
  778. for (i = 1; i<nargs; i++)
  779. { Lisp_Object s = va_arg(a, Lisp_Object);
  780. s = casefold(s);
  781. nil = C_nil;
  782. if (exception_pending()) { va_end(a); return nil; }
  783. if ((unsigned32)r <= (unsigned32)s)
  784. { va_end(a);
  785. return onevalue(nil);
  786. }
  787. r = s;
  788. }
  789. va_end(a);
  790. return onevalue(lisp_true);
  791. }
  792. static Lisp_Object Lcharacter_greaterp_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  793. {
  794. return Lcharacter_greaterp(nil, 2, a, b);
  795. }
  796. static Lisp_Object Lcharacter_greaterp_1(Lisp_Object nil, Lisp_Object a)
  797. {
  798. return Lcharacter_greaterp(nil, 1, a);
  799. }
  800. static Lisp_Object MS_CDECL Lcharacter_neq_n(Lisp_Object nil, int nargs, ...)
  801. /*
  802. * /= is supposed to check that NO pair of args match.
  803. * Because this involves multiple scanning of the vector of args it seems
  804. * necessary to copy the arge into a vector that I can scan more directly
  805. * than va_args lets me scan the arg list.
  806. */
  807. {
  808. int i, j;
  809. va_list a;
  810. Lisp_Object *r;
  811. if (nargs < 2) return onevalue(lisp_true);
  812. if (nargs > ARG_CUT_OFF)
  813. return aerror("too many args for character comparison");
  814. r = (Lisp_Object *)&work_1;
  815. va_start(a, nargs);
  816. for (i=0; i<nargs; i++) r[i] = va_arg(a, Lisp_Object);
  817. va_end(a);
  818. if (chartest(r[0])) return nil;
  819. for (i = 1; i<nargs; i++)
  820. { Lisp_Object n1 = r[i];
  821. n1 = casefold(n1);
  822. errexit();
  823. for (j=0; j<i; j++)
  824. { Lisp_Object n2 = r[j];
  825. n2 = casefold(n2); /* can not fail - this arg tested earlier */
  826. if (n1 == n2) return onevalue(nil);
  827. }
  828. }
  829. return onevalue(lisp_true);
  830. }
  831. static Lisp_Object Lcharacter_neq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  832. {
  833. return Lcharacter_neq_n(nil, 2, a, b);
  834. }
  835. static Lisp_Object Lcharacter_neq_1(Lisp_Object nil, Lisp_Object a)
  836. {
  837. return Lcharacter_neq_n(nil, 1, a);
  838. }
  839. static Lisp_Object MS_CDECL Lcharacter_geq(Lisp_Object nil, int nargs, ...)
  840. {
  841. va_list a;
  842. Lisp_Object r;
  843. int i;
  844. if (nargs < 2) return onevalue(lisp_true);
  845. if (nargs > ARG_CUT_OFF)
  846. return aerror("too many args for character comparison");
  847. va_start(a, nargs);
  848. r = va_arg(a, Lisp_Object);
  849. r = casefold(r);
  850. nil = C_nil;
  851. if (exception_pending()) { va_end(a); return nil; }
  852. for (i = 1; i<nargs; i++)
  853. { Lisp_Object s = va_arg(a, Lisp_Object);
  854. s = casefold(s);
  855. nil = C_nil;
  856. if (exception_pending()) { va_end(a); return nil; }
  857. if ((unsigned32)r < (unsigned32)s)
  858. { va_end(a);
  859. return onevalue(nil);
  860. }
  861. r = s;
  862. }
  863. va_end(a);
  864. return onevalue(lisp_true);
  865. }
  866. static Lisp_Object Lcharacter_geq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  867. {
  868. return Lcharacter_geq(nil, 2, a, b);
  869. }
  870. static Lisp_Object Lcharacter_geq_1(Lisp_Object nil, Lisp_Object a)
  871. {
  872. return Lcharacter_geq(nil, 1, a);
  873. }
  874. static Lisp_Object MS_CDECL Lcharacter_leq(Lisp_Object nil, int nargs, ...)
  875. {
  876. va_list a;
  877. Lisp_Object r;
  878. int i;
  879. if (nargs < 2) return onevalue(lisp_true);
  880. if (nargs > ARG_CUT_OFF)
  881. return aerror("too many args for character comparison");
  882. va_start(a, nargs);
  883. r = va_arg(a, Lisp_Object);
  884. r = casefold(r);
  885. nil = C_nil;
  886. if (exception_pending()) { va_end(a); return nil; }
  887. for (i = 1; i<nargs; i++)
  888. { Lisp_Object s = va_arg(a, Lisp_Object);
  889. s = casefold(s);
  890. nil = C_nil;
  891. if (exception_pending()) { va_end(a); return nil; }
  892. if ((unsigned32)r > (unsigned32)s)
  893. { va_end(a);
  894. return onevalue(nil);
  895. }
  896. r = s;
  897. }
  898. va_end(a);
  899. return onevalue(lisp_true);
  900. }
  901. static Lisp_Object Lcharacter_leq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  902. {
  903. return Lcharacter_leq(nil, 2, a, b);
  904. }
  905. static Lisp_Object Lcharacter_leq_1(Lisp_Object nil, Lisp_Object a)
  906. {
  907. return Lcharacter_leq(nil, 1, a);
  908. }
  909. #endif
  910. #ifdef COMMON
  911. /*
  912. * I will also put some versions of string comparisons here - the versions
  913. * implemented this way will have no keyword args.
  914. */
  915. /*
  916. * get_char_vec(v, &high, &offset) is used in places where v is expected
  917. * to be a string or symbol. It returns a simple vector, which the celt()
  918. * macro can access, and sets high & offset. The string will then
  919. * have characters with index 0 <= n < high, but to access them the offset
  920. * value needs to be added. If the input is not a proper string then nil
  921. * will be returned.
  922. */
  923. static Lisp_Object get_char_vec(Lisp_Object v, int32 *high, int32 *offset)
  924. {
  925. Header h;
  926. Lisp_Object nil = C_nil, w;
  927. if (symbolp(v)) v = qpname(v);
  928. if (!is_vector(v)) return nil;
  929. h = vechdr(v);
  930. if (type_of_header(h) == TYPE_STRING)
  931. { *high = length_of_header(h) - 4;
  932. *offset = 0;
  933. return v;
  934. }
  935. if (!is_vector(v)) return nil;
  936. h = vechdr(v);
  937. if (type_of_header(h) != TYPE_ARRAY) return nil;
  938. w = elt(v, 1); /* The list of dimensions */
  939. if (w == nil || qcdr(w) != nil) return nil;
  940. *high = int_of_fixnum(qcar(w));
  941. *offset = int_of_fixnum(elt(v, 3));
  942. v = elt(v, 2);
  943. h = vechdr(v);
  944. if (type_of_header(h) != TYPE_STRING) return nil;
  945. else return v;
  946. }
  947. static Lisp_Object Lstring_greaterp_2(Lisp_Object nil,
  948. Lisp_Object a, Lisp_Object b)
  949. {
  950. int32 la, oa, lb, ob, i;
  951. int ca, cb;
  952. Lisp_Object w;
  953. w = get_char_vec(a, &la, &oa);
  954. if (w == nil) return aerror1("string>", a);
  955. a = w;
  956. w = get_char_vec(b, &lb, &ob);
  957. if (w == nil) return aerror1("string>", b);
  958. b = w;
  959. for (i=0;;i++)
  960. { if (i == lb)
  961. { if (i == la) return onevalue(nil);
  962. else return onevalue(fixnum_of_int(i));
  963. }
  964. else if (i == la) return onevalue(nil);
  965. ca = ucelt(a, i+oa);
  966. cb = ucelt(b, i+ob);
  967. if (ca == cb) continue;
  968. if (ca > cb) return onevalue(fixnum_of_int(i));
  969. else return onevalue(nil);
  970. }
  971. }
  972. static Lisp_Object Lstring_lessp_2(Lisp_Object nil,
  973. Lisp_Object a, Lisp_Object b)
  974. {
  975. return Lstring_greaterp_2(nil, b, a);
  976. }
  977. static Lisp_Object Lstring_not_equal_2(Lisp_Object nil,
  978. Lisp_Object a, Lisp_Object b)
  979. {
  980. int32 la, oa, lb, ob, i;
  981. int ca, cb;
  982. Lisp_Object w;
  983. w = get_char_vec(a, &la, &oa);
  984. if (w == nil) return aerror1("string/=", a);
  985. a = w;
  986. w = get_char_vec(b, &lb, &ob);
  987. if (w == nil) return aerror1("string/=", b);
  988. b = w;
  989. for (i=0;;i++)
  990. { if (i == lb)
  991. { if (i == la) return onevalue(nil);
  992. else return onevalue(fixnum_of_int(i));
  993. }
  994. else if (i == la) return onevalue(fixnum_of_int(i));
  995. ca = ucelt(a, i+oa);
  996. cb = ucelt(b, i+ob);
  997. if (ca == cb) continue;
  998. return onevalue(fixnum_of_int(i));
  999. }
  1000. }
  1001. static Lisp_Object Lstring_equal_2(Lisp_Object nil,
  1002. Lisp_Object a, Lisp_Object b)
  1003. {
  1004. int32 la, oa, lb, ob, i;
  1005. int ca, cb;
  1006. Lisp_Object w;
  1007. w = get_char_vec(a, &la, &oa);
  1008. if (w == nil) return aerror1("string=", a);
  1009. a = w;
  1010. w = get_char_vec(b, &lb, &ob);
  1011. if (w == nil) return aerror1("string=", b);
  1012. b = w;
  1013. for (i=0;;i++)
  1014. { if (i == lb)
  1015. { if (i == la) return onevalue(lisp_true);
  1016. else return onevalue(nil);
  1017. }
  1018. else if (i == la) return onevalue(nil);
  1019. ca = ucelt(a, i+oa);
  1020. cb = ucelt(b, i+ob);
  1021. if (ca == cb) continue;
  1022. else return onevalue(nil);
  1023. }
  1024. }
  1025. static Lisp_Object Lstring_not_greaterp_2(Lisp_Object nil,
  1026. Lisp_Object a, Lisp_Object b)
  1027. {
  1028. int32 la, oa, lb, ob, i;
  1029. int ca, cb;
  1030. Lisp_Object w;
  1031. w = get_char_vec(a, &la, &oa);
  1032. if (w == nil) return aerror1("string<=", a);
  1033. a = w;
  1034. w = get_char_vec(b, &lb, &ob);
  1035. if (w == nil) return aerror1("string<=", b);
  1036. b = w;
  1037. for (i=0;;i++)
  1038. { if (i == la) return onevalue(fixnum_of_int(i));
  1039. else if (i == lb) return onevalue(nil);
  1040. ca = ucelt(a, i+oa);
  1041. cb = ucelt(b, i+ob);
  1042. if (ca == cb) continue;
  1043. if (ca < cb) return onevalue(fixnum_of_int(i));
  1044. else return onevalue(nil);
  1045. }
  1046. }
  1047. static Lisp_Object Lstring_not_lessp_2(Lisp_Object nil,
  1048. Lisp_Object a, Lisp_Object b)
  1049. {
  1050. return Lstring_not_greaterp_2(nil, b, a);
  1051. }
  1052. static Lisp_Object L_string_greaterp_2(Lisp_Object nil,
  1053. Lisp_Object a, Lisp_Object b)
  1054. {
  1055. int32 la, oa, lb, ob, i;
  1056. int ca, cb;
  1057. Lisp_Object w;
  1058. w = get_char_vec(a, &la, &oa);
  1059. if (w == nil) return aerror1("string>", a);
  1060. a = w;
  1061. w = get_char_vec(b, &lb, &ob);
  1062. if (w == nil) return aerror1("string>", b);
  1063. b = w;
  1064. for (i=0;;i++)
  1065. { if (i == lb)
  1066. { if (i == la) return onevalue(nil);
  1067. else return onevalue(fixnum_of_int(i));
  1068. }
  1069. else if (i == la) return onevalue(nil);
  1070. ca = toupper(celt(a, i+oa));
  1071. cb = toupper(celt(b, i+ob));
  1072. if (ca == cb) continue;
  1073. if (ca > cb) return onevalue(fixnum_of_int(i));
  1074. else return onevalue(nil);
  1075. }
  1076. }
  1077. static Lisp_Object L_string_lessp_2(Lisp_Object nil,
  1078. Lisp_Object a, Lisp_Object b)
  1079. {
  1080. return L_string_greaterp_2(nil, b, a);
  1081. }
  1082. static Lisp_Object L_string_not_equal_2(Lisp_Object nil,
  1083. Lisp_Object a, Lisp_Object b)
  1084. {
  1085. int32 la, oa, lb, ob, i;
  1086. int ca, cb;
  1087. Lisp_Object w;
  1088. w = get_char_vec(a, &la, &oa);
  1089. if (w == nil) return aerror1("string/=", a);
  1090. a = w;
  1091. w = get_char_vec(b, &lb, &ob);
  1092. if (w == nil) return aerror1("string/=", b);
  1093. b = w;
  1094. for (i=0;;i++)
  1095. { if (i == lb)
  1096. { if (i == la) return onevalue(nil);
  1097. else return onevalue(fixnum_of_int(i));
  1098. }
  1099. else if (i == la) return onevalue(fixnum_of_int(i));
  1100. ca = toupper(celt(a, i+oa));
  1101. cb = toupper(celt(b, i+ob));
  1102. if (ca == cb) continue;
  1103. return onevalue(fixnum_of_int(i));
  1104. }
  1105. }
  1106. static Lisp_Object L_string_equal_2(Lisp_Object nil,
  1107. Lisp_Object a, Lisp_Object b)
  1108. {
  1109. int32 la, oa, lb, ob, i;
  1110. int ca, cb;
  1111. Lisp_Object w;
  1112. w = get_char_vec(a, &la, &oa);
  1113. if (w == nil) return aerror1("string=", a);
  1114. a = w;
  1115. w = get_char_vec(b, &lb, &ob);
  1116. if (w == nil) return aerror1("string=", b);
  1117. b = w;
  1118. for (i=0;;i++)
  1119. { if (i == lb)
  1120. { if (i == la) return onevalue(lisp_true);
  1121. else return onevalue(nil);
  1122. }
  1123. else if (i == la) return onevalue(nil);
  1124. ca = toupper(celt(a, i+oa));
  1125. cb = toupper(celt(b, i+ob));
  1126. if (ca == cb) continue;
  1127. else return onevalue(nil);
  1128. }
  1129. }
  1130. static Lisp_Object L_string_not_greaterp_2(Lisp_Object nil,
  1131. Lisp_Object a, Lisp_Object b)
  1132. {
  1133. int32 la, oa, lb, ob, i;
  1134. int ca, cb;
  1135. Lisp_Object w;
  1136. w = get_char_vec(a, &la, &oa);
  1137. if (w == nil) return aerror1("string<=", a);
  1138. a = w;
  1139. w = get_char_vec(b, &lb, &ob);
  1140. if (w == nil) return aerror1("string<=", b);
  1141. b = w;
  1142. for (i=0;;i++)
  1143. { if (i == la) return onevalue(fixnum_of_int(i));
  1144. else if (i == lb) return onevalue(nil);
  1145. ca = toupper(celt(a, i+oa));
  1146. cb = toupper(celt(b, i+ob));
  1147. if (ca == cb) continue;
  1148. if (ca < cb) return onevalue(fixnum_of_int(i));
  1149. else return onevalue(nil);
  1150. }
  1151. }
  1152. static Lisp_Object L_string_not_lessp_2(Lisp_Object nil,
  1153. Lisp_Object a, Lisp_Object b)
  1154. {
  1155. return L_string_not_greaterp_2(nil, b, a);
  1156. }
  1157. #endif
  1158. setup_type const char_setup[] =
  1159. {
  1160. {"char-code", Lchar_code, too_many_1, wrong_no_1},
  1161. {"char-downcase", Lchar_downcase, too_many_1, wrong_no_1},
  1162. {"char-upcase", Lchar_upcase, too_many_1, wrong_no_1},
  1163. {"code-char", Lcode_char1, Lcode_char2, Lcode_charn},
  1164. {"digit", Ldigitp, too_many_1, wrong_no_1},
  1165. {"special-char", Lspecial_char, too_many_1, wrong_no_1},
  1166. #ifdef COMMON
  1167. {"alpha-char-p", Lalpha_char_p, too_many_1, wrong_no_1},
  1168. {"both-case-p", Lalpha_char_p, too_many_1, wrong_no_1},
  1169. {"char-bits", Lchar_bits, too_many_1, wrong_no_1},
  1170. {"char-equal", Lcharacter_eqn_1, Lcharacter_eqn_2, Lcharacter_eqn},
  1171. {"char-font", Lchar_font, too_many_1, wrong_no_1},
  1172. {"char-greaterp", Lcharacter_greaterp_1, Lcharacter_greaterp_2, Lcharacter_greaterp},
  1173. {"char-int", Lchar_int, too_many_1, wrong_no_1},
  1174. {"char-lessp", Lcharacter_lessp_1, Lcharacter_lessp_2, Lcharacter_lessp},
  1175. {"char-not-equal", Lcharacter_neq_1, Lcharacter_neq_2, Lcharacter_neq_n},
  1176. {"char-not-greaterp", Lcharacter_leq_1, Lcharacter_leq_2, Lcharacter_leq},
  1177. {"char-not-lessp", Lcharacter_geq_1, Lcharacter_geq_2, Lcharacter_geq},
  1178. {"char/=", Lchar_neq_1, Lchar_neq_2, Lchar_neq_n},
  1179. {"char<", Lchar_lessp_1, Lchar_lessp_2, Lchar_lessp},
  1180. {"char<=", Lchar_leq_1, Lchar_leq_2, Lchar_leq},
  1181. {"char=", Lchar_eqn_1, Lchar_eqn_2, Lchar_eqn},
  1182. {"char>", Lchar_greaterp_1, Lchar_greaterp_2, Lchar_greaterp},
  1183. {"char>=", Lchar_geq_1, Lchar_geq_2, Lchar_geq},
  1184. {"character", Lcharacter, too_many_1, wrong_no_1},
  1185. {"characterp", Lcharacterp, too_many_1, wrong_no_1},
  1186. {"digit-char", Ldigit_char_1, Ldigit_char_2, Ldigit_char_n},
  1187. {"digit-char-p", Ldigit_char_p_1, Ldigit_char_p_2, wrong_no_1},
  1188. {"graphic-char-p", Lgraphic_char_p, too_many_1, wrong_no_1},
  1189. {"int-char", Lint_char, too_many_1, wrong_no_1},
  1190. {"lower-case-p", Llower_case_p, too_many_1, wrong_no_1},
  1191. {"make-char", wrong_no_na, wrong_no_nb, Lmake_char},
  1192. {"upper-case-p", Lupper_case_p, too_many_1, wrong_no_1},
  1193. {"whitespace-char-p", Lwhitespace_char_p, too_many_1, wrong_no_1},
  1194. {"string<2", too_few_2, Lstring_lessp_2, wrong_no_2},
  1195. {"string>2", too_few_2, Lstring_greaterp_2, wrong_no_2},
  1196. {"string=2", too_few_2, Lstring_equal_2, wrong_no_2},
  1197. {"string/=2", too_few_2, Lstring_not_equal_2, wrong_no_2},
  1198. {"string<=2", too_few_2, Lstring_not_greaterp_2, wrong_no_2},
  1199. {"string>=2", too_few_2, Lstring_not_lessp_2, wrong_no_2},
  1200. {"string-lessp2", too_few_2, L_string_lessp_2, wrong_no_2},
  1201. {"string-greaterp2", too_few_2, L_string_greaterp_2, wrong_no_2},
  1202. {"string-equal2", too_few_2, L_string_equal_2, wrong_no_2},
  1203. {"string-not-equal2", too_few_2, L_string_not_equal_2, wrong_no_2},
  1204. {"string-not-greaterp2", too_few_2, L_string_not_greaterp_2, wrong_no_2},
  1205. {"string-not-lessp2", too_few_2, L_string_not_lessp_2, wrong_no_2},
  1206. #else
  1207. {"liter", Lalpha_char_p, too_many_1, wrong_no_1},
  1208. {"seprp", Lwhitespace_char_p, too_many_1, wrong_no_1},
  1209. #endif
  1210. {NULL, 0, 0, 0}
  1211. };
  1212. /* end of char.c */