Mercurial > hg > xemacs-beta
comparison lib-src/mule/mulelib.c @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 #include <stdio.h> | |
2 #include <sys/param.h> | |
3 #include "mulelib.h" | |
4 | |
5 #ifdef STDC_HEADERS | |
6 #include <stdlib.h> | |
7 #endif | |
8 | |
9 #ifdef USG | |
10 #include <string.h> | |
11 #else | |
12 #include <strings.h> | |
13 #endif | |
14 | |
15 #include <ctype.h> | |
16 | |
17 char *mule_library_version = "2.2"; | |
18 | |
19 int mule_error; | |
20 char mule_error_msg[256]; | |
21 | |
22 static int mulelib_initialized = 0; | |
23 | |
24 #ifdef MSDOS | |
25 #define READ_TEXT "rt" | |
26 #else /* not MSDOS */ | |
27 #define READ_TEXT "r" | |
28 #endif /* not MSDOS */ | |
29 | |
30 /******************** | |
31 * General routines * | |
32 ********************/ | |
33 | |
34 #define LINE_SIZE 4096 | |
35 | |
36 FILE * | |
37 open_file(dirs, file) | |
38 char *dirs, *file; | |
39 { | |
40 char path[MAXPATHLEN], *tail; | |
41 int len; | |
42 FILE *fp; | |
43 | |
44 if (file[0] == '/' | |
45 #ifdef MSDOS | |
46 || file[0] && file[1] == ':' | |
47 #endif | |
48 ) | |
49 return fopen(file, READ_TEXT); | |
50 | |
51 while (*dirs) { | |
52 (tail = index(dirs, ',')) | |
53 #ifdef MSDOS | |
54 || (tail = index(dirs, ';')) | |
55 #else | |
56 || (tail = index(dirs, ':')) | |
57 #endif | |
58 || (tail = index(dirs, '\0')); | |
59 | |
60 len = tail - dirs; | |
61 strncpy(path, dirs, len); | |
62 while (path[--len] == '/'); /* back to non-slash */ | |
63 path[++len] = '/'; | |
64 strcpy(&path[++len], file); | |
65 | |
66 fp = fopen (path, READ_TEXT); | |
67 if (fp || *tail == '\0') return fp; | |
68 | |
69 dirs = tail + 1; | |
70 } | |
71 } | |
72 | |
73 get_line(buf, size, fp) | |
74 char *buf; | |
75 int size; | |
76 FILE *fp; | |
77 { | |
78 int len; | |
79 | |
80 if (fgets(buf, size, fp) != NULL) { | |
81 len = strlen(buf); | |
82 if (buf[len - 1] == '\n') | |
83 buf[--len] = '\0'; | |
84 return len; | |
85 } else | |
86 return -1; | |
87 } | |
88 | |
89 #define PROCEED_CHAR(c) \ | |
90 if (!(p1 = (char *)index(p0, c))) goto invalid_entry | |
91 | |
92 warning1(format, arg1) | |
93 char *format; | |
94 int arg1; | |
95 { | |
96 fprintf(stderr, format, arg1); | |
97 } | |
98 | |
99 warning2(format, arg1, arg2) | |
100 char *format; | |
101 int arg1, arg2; | |
102 { | |
103 fprintf(stderr, format, arg1, arg2); | |
104 } | |
105 | |
106 warning3(format, arg1, arg2, arg3) | |
107 char *format; | |
108 int arg1, arg2, arg3; | |
109 { | |
110 fprintf(stderr, format, arg1, arg2, arg3); | |
111 } | |
112 | |
113 fatal1(arg) | |
114 char *arg; | |
115 { | |
116 fprintf(stderr, "%s", arg); | |
117 exit(1); | |
118 } | |
119 | |
120 /***************************** | |
121 * Reading CHARSETS database * | |
122 *****************************/ | |
123 | |
124 /* extra information table */ | |
125 char *font_name[128]; | |
126 int font_encoding[128]; | |
127 | |
128 set_charsets_param(line) | |
129 char *line; | |
130 { | |
131 char *p0 = line, *p1; | |
132 int len; | |
133 unsigned char lc, bytes, clm, type, graphic, final, direction; | |
134 char *doc; | |
135 | |
136 lc = atoi(p0); | |
137 | |
138 PROCEED_CHAR(':'); | |
139 p0 = p1 + 1; | |
140 bytes = atoi(p0); | |
141 | |
142 PROCEED_CHAR(':'); | |
143 p0 = p1 + 1; | |
144 clm = atoi(p0); | |
145 | |
146 PROCEED_CHAR(':'); | |
147 p0 = p1 + 1; | |
148 type = atoi(p0); | |
149 | |
150 PROCEED_CHAR(':'); | |
151 p0 = p1 + 1; | |
152 graphic = atoi(p0); | |
153 | |
154 PROCEED_CHAR(':'); | |
155 p0 = p1 + 1; | |
156 final = atoi(p0); | |
157 | |
158 PROCEED_CHAR(':'); | |
159 p0 = p1 + 1; | |
160 direction = atoi(p0); | |
161 | |
162 PROCEED_CHAR(':'); | |
163 p0 = p1 + 1; | |
164 (p1 = index(p0, ':')) || (p1 = index(p0, '\0')); | |
165 len = p1 - p0; | |
166 doc = (char *)malloc(len + 1); | |
167 bcopy(p0, doc, len); | |
168 doc[len] = '\0'; | |
169 | |
170 update_mc_table(lc, bytes, clm, type, graphic, final, direction, doc); | |
171 | |
172 if (*p1) { | |
173 p0 = p1 + 1; | |
174 (p1 = index(p0, ':')) || (p1 = index(p0, '\0')); | |
175 len = p1 - p0; | |
176 font_name[lc & 0x7F] = (char *)malloc(len + 1); | |
177 bcopy(p0, font_name[lc & 0x7F], len); | |
178 font_name[lc & 0x7F][len] = '\0'; | |
179 | |
180 font_encoding[lc & 0x7F] = *p1 ? atoi(p1) : 0; | |
181 } | |
182 | |
183 return 0; | |
184 | |
185 invalid_entry: | |
186 mule_error = MULE_ERROR_INVALID_CHARSETS; | |
187 sprintf(mule_error_msg, "Invalid line in CHARSETS file: %s", line); | |
188 return -1; | |
189 } | |
190 | |
191 set_ccl_program_param(line) | |
192 char *line; | |
193 { | |
194 int lc, len, i, j; | |
195 char *p, *p1; | |
196 Lisp_Object ccl; | |
197 | |
198 lc = atoi(line) & 0x7F; | |
199 p = p1 = index(line, ':') + 1; | |
200 if (!p) return -1; | |
201 len = 0; | |
202 while (*p1) if (*p1++ == ' ') len++; | |
203 ccl = make_vector(len); | |
204 for (i = 0; i < len; i++) { | |
205 sscanf(p, "%x", XVECTOR (ccl)->contents + i); | |
206 p = index(p + 1, ' '); | |
207 } | |
208 x_ccl_programs[lc] = (CCL_PROGRAM *)malloc(sizeof (CCL_PROGRAM)); | |
209 set_ccl_program(x_ccl_programs[lc], ccl); | |
210 return 0; | |
211 } | |
212 | |
213 charsets_initialize(charsets) | |
214 char *charsets; | |
215 { | |
216 FILE *fp; | |
217 char line[LINE_SIZE]; | |
218 int i, status; | |
219 | |
220 if (!charsets) charsets = CHARSETS; | |
221 fp = open_file(PATH_DATA, charsets); | |
222 if (!fp) { | |
223 mule_error = MULE_ERROR_NO_CHARSETS; | |
224 sprintf(mule_error_msg, "File %s not in the path %s", charsets, PATH_DATA); | |
225 return -1; | |
226 } | |
227 init_charset_once(); | |
228 for (i = 0; i < 128; i++) | |
229 x_ccl_programs[i] = NULL; | |
230 | |
231 status = 0; | |
232 while (get_line(line, sizeof line, fp) >= 0) { | |
233 if (line[0] == '#') { | |
234 if (status > 0) status++; | |
235 continue; | |
236 } | |
237 if (status <= 1) { | |
238 status = 1; | |
239 if (set_charsets_param(line) < 0) return -1; | |
240 } else { | |
241 if (set_ccl_program_param(line) < 0) return -1; | |
242 } | |
243 } | |
244 return 0; | |
245 } | |
246 | |
247 /***************************** | |
248 * Reading CODINGS database * | |
249 *****************************/ | |
250 | |
251 coding_type coding_system_table[CODING_SYSTEM_COUNT]; | |
252 int n_base_coding_system = 0; | |
253 int n_coding_system; | |
254 | |
255 set_coding_system_param(line, cs) | |
256 char *line; | |
257 coding_type *cs; | |
258 { | |
259 char *p0 = line, *p1; | |
260 int len, i; | |
261 | |
262 PROCEED_CHAR(':'); | |
263 len = p1 - p0; | |
264 cs->name = (char *)malloc(len + 1); | |
265 bcopy(p0, cs->name, len); | |
266 cs->name[len] = '\0'; | |
267 | |
268 p0 = p1 + 1; | |
269 i = atoi(p0); | |
270 CODE_TYPE_SET(cs, i); | |
271 | |
272 PROCEED_CHAR(':'); | |
273 p0 = p1 + 1; | |
274 cs->mnemonic = *p0; | |
275 | |
276 PROCEED_CHAR(':'); | |
277 p0 = p1 + 1; | |
278 i = atoi(p0); | |
279 CODE_FORM (cs) | |
280 = (i==0) ? CODE_EOL_AUTO : (i==1) ? CODE_EOL_LF | |
281 : (i==2) ? CODE_EOL_CRLF : CODE_EOL_CR; | |
282 CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; | |
283 | |
284 PROCEED_CHAR(':'); | |
285 p0 = p1 + 1; | |
286 if (CODE_TYPE (cs) == ISO2022) { | |
287 int flags[12]; | |
288 for (i = 0; i < 11; i++) { | |
289 if (!(flags[i] = atoi(p0))) flags[i] = Qnil; | |
290 PROCEED_CHAR(','); | |
291 p0 = p1 + 1; | |
292 } | |
293 flags[i] = atoi(p0); | |
294 CODE_LC_SET(cs, flags[0], flags[1], flags[2], flags[3]); | |
295 CODE_FORM_SET(cs, (Lisp_Object)flags[4], (Lisp_Object)flags[5], | |
296 (Lisp_Object)flags[6], (Lisp_Object)flags[7], | |
297 (Lisp_Object)flags[8], (Lisp_Object)flags[9], | |
298 (Lisp_Object)flags[10], (Lisp_Object)flags[11]); | |
299 } else if (CODE_TYPE (cs) == BIG5) { | |
300 CODE_FORM_SET(cs, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil); | |
301 } else if (CODE_TYPE (cs) == CCL) { | |
302 int len; | |
303 char *start = p0, c; | |
304 Lisp_Object ccl; | |
305 | |
306 len = 0; | |
307 while ((c = *p0++) != ',') if (c == ' ') len++; | |
308 ccl = make_vector (len); | |
309 for (i = 0; i < len; i++) { | |
310 sscanf(start, "%x", XVECTOR (ccl)->contents + i); | |
311 start = index (start + 1, ' '); | |
312 } | |
313 set_ccl_program (&CODE_CCL_ENCODE (cs), ccl); | |
314 | |
315 start = p0; | |
316 len = 0; | |
317 while ((c = *p0++) != ':') if (c == ' ') len++; | |
318 ccl = make_vector (len); | |
319 for (i = 0; i < len; i++) { | |
320 sscanf(start, "%x", XVECTOR (ccl)->contents + i); | |
321 start = index (start + 1, ' '); | |
322 } | |
323 set_ccl_program (&CODE_CCL_DECODE (cs), ccl); | |
324 p0 -= 2; | |
325 } | |
326 | |
327 PROCEED_CHAR(':'); | |
328 p0 = p1 + 1; | |
329 len = strlen(p0); | |
330 cs->doc = (char *)malloc(len + 1); | |
331 bcopy(p0, cs->doc, len + 1); | |
332 return 0; | |
333 | |
334 invalid_entry: | |
335 mule_error = MULE_ERROR_INVALID_CODING; | |
336 sprintf(mule_error_msg, "Invalid line in CODINGS file: %s", line); | |
337 return -1; | |
338 } | |
339 | |
340 char *coding_category_names[IDX_BIN + 1] = { | |
341 "*coding-category-internal*", | |
342 "*coding-category-sjis*", | |
343 "*coding-category-iso-7*", | |
344 "*coding-category-iso-8-1*", | |
345 "*coding-category-iso-8-2*", | |
346 "*coding-category-iso-else*", | |
347 "*coding-category-big5*", | |
348 "*coding-category-bin*"}; | |
349 | |
350 set_coding_category(line, priority) | |
351 char *line; | |
352 int priority; | |
353 { | |
354 char *p0 = line, *p1; | |
355 int i, len; | |
356 | |
357 PROCEED_CHAR(':'); | |
358 len = p1 - p0; | |
359 for (i = 0; i <= IDX_BIN; i++) { | |
360 if (!strncmp(p0, XSYMBOL (code_category[i])->name, len)) | |
361 break; | |
362 } | |
363 if (i <= IDX_BIN) { | |
364 code_priority_category[priority] = i; | |
365 p0 = p1 + 1; | |
366 XSYMBOL (code_category[i])->value = make_symbol(p0); | |
367 return 0; | |
368 } | |
369 | |
370 invalid_entry: | |
371 mule_error = MULE_ERROR_INVALID_CODING; | |
372 sprintf(mule_error_msg, "Invalid line in CODINGS file: %s", line); | |
373 return -1; | |
374 } | |
375 | |
376 codings_initialize(codings) | |
377 char *codings; | |
378 { | |
379 FILE *fp; | |
380 char line[LINE_SIZE]; | |
381 char *coding_category_header = "## LIST OF CODING CATEGORIES"; | |
382 coding_type *cs; | |
383 int i; | |
384 | |
385 if (!codings) codings = CODINGS; | |
386 fp = open_file(PATH_DATA, codings); | |
387 if (!fp) { | |
388 mule_error = MULE_ERROR_NO_CODING; | |
389 sprintf(mule_error_msg, "File %s not in the path %s!", codings, PATH_DATA); | |
390 return -1; | |
391 } | |
392 n_coding_system = 0; | |
393 while (get_line(line, sizeof line, fp) >= 0 | |
394 && strncmp(line, coding_category_header, | |
395 strlen(coding_category_header))) { | |
396 if (line[0] != '#') { | |
397 if (set_coding_system_param(line, coding_system_table + n_coding_system) | |
398 < 0) | |
399 return -1; | |
400 n_coding_system++; | |
401 } | |
402 } | |
403 | |
404 n_base_coding_system = n_coding_system; | |
405 | |
406 for (i = 0; i < n_base_coding_system; i++) { | |
407 if (CODE_TYPE (&coding_system_table[i]) != CCL) { | |
408 sprintf(line, "%sunix", coding_system_table[i].name); | |
409 coding_system_table[i].eol_lf = make_symbol(line); | |
410 cs = &coding_system_table[n_coding_system++]; | |
411 *cs = coding_system_table[i]; | |
412 cs->name = XSYMBOL (coding_system_table[i].eol_lf)->name; | |
413 CODE_FORM (cs) |= CODE_EOL_LF; | |
414 CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; | |
415 | |
416 sprintf(line, "%sdos", coding_system_table[i].name); | |
417 coding_system_table[i].eol_crlf = make_symbol(line); | |
418 cs = &coding_system_table[n_coding_system++]; | |
419 *cs = coding_system_table[i]; | |
420 cs->name = XSYMBOL (coding_system_table[i].eol_crlf)->name; | |
421 CODE_FORM (cs) |= CODE_EOL_CRLF; | |
422 CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; | |
423 | |
424 sprintf(line, "%smac", coding_system_table[i].name); | |
425 coding_system_table[i].eol_cr = make_symbol(line); | |
426 cs = &coding_system_table[n_coding_system++]; | |
427 *cs = coding_system_table[i]; | |
428 cs->name = XSYMBOL (coding_system_table[i].eol_cr)->name; | |
429 CODE_FORM (cs) |= CODE_EOL_CR; | |
430 CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; | |
431 } | |
432 } | |
433 | |
434 for (i = 0; i <= IDX_BIN; i++) | |
435 code_category[i] = make_symbol(coding_category_names[i]); | |
436 i = 0; | |
437 while (get_line(line, sizeof line, fp) >= 0) { | |
438 if (line[0] && line[0] != '#') { | |
439 if (set_coding_category(line, i) < 0) | |
440 return -1; | |
441 i++; | |
442 } | |
443 } | |
444 return 0; | |
445 } | |
446 | |
447 static | |
448 find_coding(str) | |
449 char *str; | |
450 { | |
451 int i; | |
452 | |
453 if (*str == '*') { | |
454 for (i = 0; i < n_coding_system; i++) | |
455 if (!strcmp(str, coding_system_table[i].name)) return i; | |
456 } else { | |
457 unsigned int eol_type; | |
458 switch (str[1]) { | |
459 case '\0': eol_type = CODE_EOL_AUTO; break; | |
460 case '.': eol_type = CODE_EOL_LF; break; | |
461 case ':': eol_type = CODE_EOL_CRLF; break; | |
462 case '\'': eol_type = CODE_EOL_CR; break; | |
463 default: return -1; | |
464 } | |
465 for (i = 0; i < n_coding_system; i++) | |
466 if (coding_system_table[i].mnemonic == *str | |
467 && (CODE_FORM (&coding_system_table[i]) & CODE_EOL_MASK) == eol_type) | |
468 return i; | |
469 } | |
470 return -1; | |
471 } | |
472 | |
473 encode_code(code, mccode) | |
474 Lisp_Object code; | |
475 coding_type *mccode; | |
476 { | |
477 int i; | |
478 | |
479 if ((i = find_coding(XSYMBOL (code)->name)) >= 0) | |
480 *mccode = coding_system_table[i]; | |
481 else | |
482 CODE_TYPE_SET (mccode, NOCONV); | |
483 } | |
484 | |
485 set_coding_system(inname, incode, outname, outcode) | |
486 char *inname, *outname; | |
487 coding_type *incode, *outcode; | |
488 { | |
489 int i; | |
490 | |
491 if (inname == NULL) inname = "*autoconv*"; | |
492 if ((i = find_coding(inname)) < 0) { | |
493 mule_error = MULE_ERROR_UNKNOWN_CODE; | |
494 sprintf(mule_error_msg, "Unknown code: %s", inname); | |
495 return -1; | |
496 } | |
497 *incode = coding_system_table[i]; | |
498 | |
499 if (outname == NULL) outname = "*internal*"; | |
500 if ((i = find_coding(outname)) < 0) { | |
501 mule_error = MULE_ERROR_UNKNOWN_CODE; | |
502 sprintf(mule_error_msg, "Unknown code: %s", outname); | |
503 return -1; | |
504 } | |
505 *outcode = coding_system_table[i]; | |
506 | |
507 return 0; | |
508 } | |
509 | |
510 code_conversion(incode, inbuf, insize, outcode, outbuf, outsize) | |
511 coding_type *incode, *outcode; | |
512 char *inbuf, *outbuf; | |
513 int insize, outsize; | |
514 { | |
515 Lisp_Object found = Qnil; | |
516 char *buf1, *buf2; | |
517 int buf1_used = 0, buf2_used = 0, n; | |
518 | |
519 if (insize > 0) { | |
520 if (CODE_TYPE (incode) == ITNCODE) { | |
521 buf1 = inbuf; | |
522 n = insize; | |
523 } else { | |
524 buf1 = (char *)malloc(ENCODE_BUF_SIZE(insize, incode)); | |
525 buf1_used = 1; | |
526 n = encode(incode, inbuf, buf1, insize, &found); | |
527 if (found != Qnil) | |
528 incode->name = (char *)XSYMBOL (found)->name; | |
529 } | |
530 } else { | |
531 buf1 = inbuf; | |
532 n = 0; | |
533 CODE_CNTL(outcode) |= CC_END; | |
534 } | |
535 | |
536 if (CODE_TYPE (outcode) == ITNCODE) { | |
537 buf2 = buf1; | |
538 } else { | |
539 if ((CODE_FORM (outcode) & CODE_EOL_MASK) == CODE_EOL_AUTO | |
540 && (CODE_FORM (incode) & CODE_EOL_MASK) != CODE_EOL_AUTO) { | |
541 unsigned int eol = CODE_FORM (incode) & CODE_EOL_MASK; | |
542 | |
543 CODE_FORM (outcode) |= eol; | |
544 switch (eol) { | |
545 case CODE_EOL_LF: | |
546 outcode->name = (char *)XSYMBOL (outcode->eol_lf)->name; break; | |
547 case CODE_EOL_CRLF: | |
548 outcode->name = (char *)XSYMBOL (outcode->eol_crlf)->name; break; | |
549 case CODE_EOL_CR: | |
550 outcode->name = (char *)XSYMBOL (outcode->eol_cr)->name; break; | |
551 } | |
552 } | |
553 buf2 = (char *)malloc(DECODE_BUF_SIZE(n, outcode)); | |
554 buf2_used = 1; | |
555 n = decode(outcode, buf1, buf2, n); | |
556 } | |
557 | |
558 if (n <= outsize) { | |
559 bcopy(buf2, outbuf, n); | |
560 } else { | |
561 bcopy(buf2, outbuf, outsize); | |
562 mule_error = MULE_ERROR_OVERFLOW; | |
563 sprintf(mule_error_msg, "Output buffer overflow"); | |
564 } | |
565 | |
566 if (buf2_used) free(buf2); | |
567 if (buf1_used) free(buf1); | |
568 return (n <= outsize ? n : -1); | |
569 } | |
570 | |
571 /**************** | |
572 * MSDOS staffs * | |
573 ****************/ | |
574 | |
575 #ifdef MSDOS | |
576 | |
577 static char emacsroot[MAXPATHLEN]; | |
578 | |
579 void | |
580 init_environment (argc, argv, skip_args) | |
581 int argc; | |
582 char **argv; | |
583 int skip_args; | |
584 { | |
585 char *s, *t, *root; | |
586 int len; | |
587 | |
588 /* Find our root from argv[0]. Assuming argv[0] is, say, | |
589 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */ | |
590 len = strlen (argv[0]); | |
591 root = alloca (len + 10); /* A little extra space for the stuff below. */ | |
592 strcpy (root, argv[0]); | |
593 while (len > 0 && root[len] != '/' && root[len] != ':') | |
594 len--; | |
595 root[len] = '\0'; | |
596 if (len > 4 && strcmp (root + len - 4, "/bin") == 0) | |
597 root[len - 4] = '\0'; | |
598 else | |
599 strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */ | |
600 len = strlen (root); | |
601 strcpy (emacsroot, root); | |
602 } | |
603 | |
604 char * | |
605 rootrelativepath (rel) | |
606 char *rel; | |
607 { | |
608 static char result[MAXPATHLEN + 10]; | |
609 | |
610 strcpy (result, emacsroot); | |
611 strcat (result, "/"); | |
612 strcat (result, rel); | |
613 return result; | |
614 } | |
615 | |
616 #endif /* MSDOS */ | |
617 | |
618 /*************** | |
619 * INITIALIZER * | |
620 ***************/ | |
621 | |
622 mulelib_initialize(argc, argv, charsets, codings) | |
623 int argc; | |
624 char **argv, *charsets, *codings; | |
625 { | |
626 if (!mulelib_initialized) { | |
627 int i; | |
628 | |
629 #ifdef MSDOS | |
630 init_environment(argc, argv, 0); | |
631 #endif | |
632 | |
633 for (i = 0; i < 128; i++) { | |
634 font_name[i] = NULL; | |
635 font_encoding[i] = 0; | |
636 } | |
637 | |
638 if (charsets_initialize(charsets) < 0) return -1; | |
639 if (codings_initialize(codings) < 0) return -1; | |
640 mulelib_initialized = 1; | |
641 } | |
642 return 0; | |
643 } |