char.c 40 KB

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