Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib-src/mule/mulelib.c Mon Aug 13 09:02:59 2007 +0200 @@ -0,0 +1,643 @@ +#include <stdio.h> +#include <sys/param.h> +#include "mulelib.h" + +#ifdef STDC_HEADERS +#include <stdlib.h> +#endif + +#ifdef USG +#include <string.h> +#else +#include <strings.h> +#endif + +#include <ctype.h> + +char *mule_library_version = "2.2"; + +int mule_error; +char mule_error_msg[256]; + +static int mulelib_initialized = 0; + +#ifdef MSDOS +#define READ_TEXT "rt" +#else /* not MSDOS */ +#define READ_TEXT "r" +#endif /* not MSDOS */ + +/******************** + * General routines * + ********************/ + +#define LINE_SIZE 4096 + +FILE * +open_file(dirs, file) + char *dirs, *file; +{ + char path[MAXPATHLEN], *tail; + int len; + FILE *fp; + + if (file[0] == '/' +#ifdef MSDOS + || file[0] && file[1] == ':' +#endif + ) + return fopen(file, READ_TEXT); + + while (*dirs) { + (tail = index(dirs, ',')) +#ifdef MSDOS + || (tail = index(dirs, ';')) +#else + || (tail = index(dirs, ':')) +#endif + || (tail = index(dirs, '\0')); + + len = tail - dirs; + strncpy(path, dirs, len); + while (path[--len] == '/'); /* back to non-slash */ + path[++len] = '/'; + strcpy(&path[++len], file); + + fp = fopen (path, READ_TEXT); + if (fp || *tail == '\0') return fp; + + dirs = tail + 1; + } +} + +get_line(buf, size, fp) + char *buf; + int size; + FILE *fp; +{ + int len; + + if (fgets(buf, size, fp) != NULL) { + len = strlen(buf); + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + return len; + } else + return -1; +} + +#define PROCEED_CHAR(c) \ + if (!(p1 = (char *)index(p0, c))) goto invalid_entry + +warning1(format, arg1) + char *format; + int arg1; +{ + fprintf(stderr, format, arg1); +} + +warning2(format, arg1, arg2) + char *format; + int arg1, arg2; +{ + fprintf(stderr, format, arg1, arg2); +} + +warning3(format, arg1, arg2, arg3) + char *format; + int arg1, arg2, arg3; +{ + fprintf(stderr, format, arg1, arg2, arg3); +} + +fatal1(arg) + char *arg; +{ + fprintf(stderr, "%s", arg); + exit(1); +} + +/***************************** + * Reading CHARSETS database * + *****************************/ + +/* extra information table */ +char *font_name[128]; +int font_encoding[128]; + +set_charsets_param(line) + char *line; +{ + char *p0 = line, *p1; + int len; + unsigned char lc, bytes, clm, type, graphic, final, direction; + char *doc; + + lc = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + bytes = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + clm = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + type = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + graphic = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + final = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + direction = atoi(p0); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + (p1 = index(p0, ':')) || (p1 = index(p0, '\0')); + len = p1 - p0; + doc = (char *)malloc(len + 1); + bcopy(p0, doc, len); + doc[len] = '\0'; + + update_mc_table(lc, bytes, clm, type, graphic, final, direction, doc); + + if (*p1) { + p0 = p1 + 1; + (p1 = index(p0, ':')) || (p1 = index(p0, '\0')); + len = p1 - p0; + font_name[lc & 0x7F] = (char *)malloc(len + 1); + bcopy(p0, font_name[lc & 0x7F], len); + font_name[lc & 0x7F][len] = '\0'; + + font_encoding[lc & 0x7F] = *p1 ? atoi(p1) : 0; + } + + return 0; + + invalid_entry: + mule_error = MULE_ERROR_INVALID_CHARSETS; + sprintf(mule_error_msg, "Invalid line in CHARSETS file: %s", line); + return -1; +} + +set_ccl_program_param(line) + char *line; +{ + int lc, len, i, j; + char *p, *p1; + Lisp_Object ccl; + + lc = atoi(line) & 0x7F; + p = p1 = index(line, ':') + 1; + if (!p) return -1; + len = 0; + while (*p1) if (*p1++ == ' ') len++; + ccl = make_vector(len); + for (i = 0; i < len; i++) { + sscanf(p, "%x", XVECTOR (ccl)->contents + i); + p = index(p + 1, ' '); + } + x_ccl_programs[lc] = (CCL_PROGRAM *)malloc(sizeof (CCL_PROGRAM)); + set_ccl_program(x_ccl_programs[lc], ccl); + return 0; +} + +charsets_initialize(charsets) + char *charsets; +{ + FILE *fp; + char line[LINE_SIZE]; + int i, status; + + if (!charsets) charsets = CHARSETS; + fp = open_file(PATH_DATA, charsets); + if (!fp) { + mule_error = MULE_ERROR_NO_CHARSETS; + sprintf(mule_error_msg, "File %s not in the path %s", charsets, PATH_DATA); + return -1; + } + init_charset_once(); + for (i = 0; i < 128; i++) + x_ccl_programs[i] = NULL; + + status = 0; + while (get_line(line, sizeof line, fp) >= 0) { + if (line[0] == '#') { + if (status > 0) status++; + continue; + } + if (status <= 1) { + status = 1; + if (set_charsets_param(line) < 0) return -1; + } else { + if (set_ccl_program_param(line) < 0) return -1; + } + } + return 0; +} + +/***************************** + * Reading CODINGS database * + *****************************/ + +coding_type coding_system_table[CODING_SYSTEM_COUNT]; +int n_base_coding_system = 0; +int n_coding_system; + +set_coding_system_param(line, cs) + char *line; + coding_type *cs; +{ + char *p0 = line, *p1; + int len, i; + + PROCEED_CHAR(':'); + len = p1 - p0; + cs->name = (char *)malloc(len + 1); + bcopy(p0, cs->name, len); + cs->name[len] = '\0'; + + p0 = p1 + 1; + i = atoi(p0); + CODE_TYPE_SET(cs, i); + + PROCEED_CHAR(':'); + p0 = p1 + 1; + cs->mnemonic = *p0; + + PROCEED_CHAR(':'); + p0 = p1 + 1; + i = atoi(p0); + CODE_FORM (cs) + = (i==0) ? CODE_EOL_AUTO : (i==1) ? CODE_EOL_LF + : (i==2) ? CODE_EOL_CRLF : CODE_EOL_CR; + CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; + + PROCEED_CHAR(':'); + p0 = p1 + 1; + if (CODE_TYPE (cs) == ISO2022) { + int flags[12]; + for (i = 0; i < 11; i++) { + if (!(flags[i] = atoi(p0))) flags[i] = Qnil; + PROCEED_CHAR(','); + p0 = p1 + 1; + } + flags[i] = atoi(p0); + CODE_LC_SET(cs, flags[0], flags[1], flags[2], flags[3]); + CODE_FORM_SET(cs, (Lisp_Object)flags[4], (Lisp_Object)flags[5], + (Lisp_Object)flags[6], (Lisp_Object)flags[7], + (Lisp_Object)flags[8], (Lisp_Object)flags[9], + (Lisp_Object)flags[10], (Lisp_Object)flags[11]); + } else if (CODE_TYPE (cs) == BIG5) { + CODE_FORM_SET(cs, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil); + } else if (CODE_TYPE (cs) == CCL) { + int len; + char *start = p0, c; + Lisp_Object ccl; + + len = 0; + while ((c = *p0++) != ',') if (c == ' ') len++; + ccl = make_vector (len); + for (i = 0; i < len; i++) { + sscanf(start, "%x", XVECTOR (ccl)->contents + i); + start = index (start + 1, ' '); + } + set_ccl_program (&CODE_CCL_ENCODE (cs), ccl); + + start = p0; + len = 0; + while ((c = *p0++) != ':') if (c == ' ') len++; + ccl = make_vector (len); + for (i = 0; i < len; i++) { + sscanf(start, "%x", XVECTOR (ccl)->contents + i); + start = index (start + 1, ' '); + } + set_ccl_program (&CODE_CCL_DECODE (cs), ccl); + p0 -= 2; + } + + PROCEED_CHAR(':'); + p0 = p1 + 1; + len = strlen(p0); + cs->doc = (char *)malloc(len + 1); + bcopy(p0, cs->doc, len + 1); + return 0; + + invalid_entry: + mule_error = MULE_ERROR_INVALID_CODING; + sprintf(mule_error_msg, "Invalid line in CODINGS file: %s", line); + return -1; +} + +char *coding_category_names[IDX_BIN + 1] = { + "*coding-category-internal*", + "*coding-category-sjis*", + "*coding-category-iso-7*", + "*coding-category-iso-8-1*", + "*coding-category-iso-8-2*", + "*coding-category-iso-else*", + "*coding-category-big5*", + "*coding-category-bin*"}; + +set_coding_category(line, priority) + char *line; + int priority; +{ + char *p0 = line, *p1; + int i, len; + + PROCEED_CHAR(':'); + len = p1 - p0; + for (i = 0; i <= IDX_BIN; i++) { + if (!strncmp(p0, XSYMBOL (code_category[i])->name, len)) + break; + } + if (i <= IDX_BIN) { + code_priority_category[priority] = i; + p0 = p1 + 1; + XSYMBOL (code_category[i])->value = make_symbol(p0); + return 0; + } + + invalid_entry: + mule_error = MULE_ERROR_INVALID_CODING; + sprintf(mule_error_msg, "Invalid line in CODINGS file: %s", line); + return -1; +} + +codings_initialize(codings) + char *codings; +{ + FILE *fp; + char line[LINE_SIZE]; + char *coding_category_header = "## LIST OF CODING CATEGORIES"; + coding_type *cs; + int i; + + if (!codings) codings = CODINGS; + fp = open_file(PATH_DATA, codings); + if (!fp) { + mule_error = MULE_ERROR_NO_CODING; + sprintf(mule_error_msg, "File %s not in the path %s!", codings, PATH_DATA); + return -1; + } + n_coding_system = 0; + while (get_line(line, sizeof line, fp) >= 0 + && strncmp(line, coding_category_header, + strlen(coding_category_header))) { + if (line[0] != '#') { + if (set_coding_system_param(line, coding_system_table + n_coding_system) + < 0) + return -1; + n_coding_system++; + } + } + + n_base_coding_system = n_coding_system; + + for (i = 0; i < n_base_coding_system; i++) { + if (CODE_TYPE (&coding_system_table[i]) != CCL) { + sprintf(line, "%sunix", coding_system_table[i].name); + coding_system_table[i].eol_lf = make_symbol(line); + cs = &coding_system_table[n_coding_system++]; + *cs = coding_system_table[i]; + cs->name = XSYMBOL (coding_system_table[i].eol_lf)->name; + CODE_FORM (cs) |= CODE_EOL_LF; + CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; + + sprintf(line, "%sdos", coding_system_table[i].name); + coding_system_table[i].eol_crlf = make_symbol(line); + cs = &coding_system_table[n_coding_system++]; + *cs = coding_system_table[i]; + cs->name = XSYMBOL (coding_system_table[i].eol_crlf)->name; + CODE_FORM (cs) |= CODE_EOL_CRLF; + CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; + + sprintf(line, "%smac", coding_system_table[i].name); + coding_system_table[i].eol_cr = make_symbol(line); + cs = &coding_system_table[n_coding_system++]; + *cs = coding_system_table[i]; + cs->name = XSYMBOL (coding_system_table[i].eol_cr)->name; + CODE_FORM (cs) |= CODE_EOL_CR; + CODE_LF (cs) = CODE_CRLF (cs) = CODE_CR (cs) = Qnil; + } + } + + for (i = 0; i <= IDX_BIN; i++) + code_category[i] = make_symbol(coding_category_names[i]); + i = 0; + while (get_line(line, sizeof line, fp) >= 0) { + if (line[0] && line[0] != '#') { + if (set_coding_category(line, i) < 0) + return -1; + i++; + } + } + return 0; +} + +static +find_coding(str) + char *str; +{ + int i; + + if (*str == '*') { + for (i = 0; i < n_coding_system; i++) + if (!strcmp(str, coding_system_table[i].name)) return i; + } else { + unsigned int eol_type; + switch (str[1]) { + case '\0': eol_type = CODE_EOL_AUTO; break; + case '.': eol_type = CODE_EOL_LF; break; + case ':': eol_type = CODE_EOL_CRLF; break; + case '\'': eol_type = CODE_EOL_CR; break; + default: return -1; + } + for (i = 0; i < n_coding_system; i++) + if (coding_system_table[i].mnemonic == *str + && (CODE_FORM (&coding_system_table[i]) & CODE_EOL_MASK) == eol_type) + return i; + } + return -1; +} + +encode_code(code, mccode) + Lisp_Object code; + coding_type *mccode; +{ + int i; + + if ((i = find_coding(XSYMBOL (code)->name)) >= 0) + *mccode = coding_system_table[i]; + else + CODE_TYPE_SET (mccode, NOCONV); +} + +set_coding_system(inname, incode, outname, outcode) + char *inname, *outname; + coding_type *incode, *outcode; +{ + int i; + + if (inname == NULL) inname = "*autoconv*"; + if ((i = find_coding(inname)) < 0) { + mule_error = MULE_ERROR_UNKNOWN_CODE; + sprintf(mule_error_msg, "Unknown code: %s", inname); + return -1; + } + *incode = coding_system_table[i]; + + if (outname == NULL) outname = "*internal*"; + if ((i = find_coding(outname)) < 0) { + mule_error = MULE_ERROR_UNKNOWN_CODE; + sprintf(mule_error_msg, "Unknown code: %s", outname); + return -1; + } + *outcode = coding_system_table[i]; + + return 0; +} + +code_conversion(incode, inbuf, insize, outcode, outbuf, outsize) + coding_type *incode, *outcode; + char *inbuf, *outbuf; + int insize, outsize; +{ + Lisp_Object found = Qnil; + char *buf1, *buf2; + int buf1_used = 0, buf2_used = 0, n; + + if (insize > 0) { + if (CODE_TYPE (incode) == ITNCODE) { + buf1 = inbuf; + n = insize; + } else { + buf1 = (char *)malloc(ENCODE_BUF_SIZE(insize, incode)); + buf1_used = 1; + n = encode(incode, inbuf, buf1, insize, &found); + if (found != Qnil) + incode->name = (char *)XSYMBOL (found)->name; + } + } else { + buf1 = inbuf; + n = 0; + CODE_CNTL(outcode) |= CC_END; + } + + if (CODE_TYPE (outcode) == ITNCODE) { + buf2 = buf1; + } else { + if ((CODE_FORM (outcode) & CODE_EOL_MASK) == CODE_EOL_AUTO + && (CODE_FORM (incode) & CODE_EOL_MASK) != CODE_EOL_AUTO) { + unsigned int eol = CODE_FORM (incode) & CODE_EOL_MASK; + + CODE_FORM (outcode) |= eol; + switch (eol) { + case CODE_EOL_LF: + outcode->name = (char *)XSYMBOL (outcode->eol_lf)->name; break; + case CODE_EOL_CRLF: + outcode->name = (char *)XSYMBOL (outcode->eol_crlf)->name; break; + case CODE_EOL_CR: + outcode->name = (char *)XSYMBOL (outcode->eol_cr)->name; break; + } + } + buf2 = (char *)malloc(DECODE_BUF_SIZE(n, outcode)); + buf2_used = 1; + n = decode(outcode, buf1, buf2, n); + } + + if (n <= outsize) { + bcopy(buf2, outbuf, n); + } else { + bcopy(buf2, outbuf, outsize); + mule_error = MULE_ERROR_OVERFLOW; + sprintf(mule_error_msg, "Output buffer overflow"); + } + + if (buf2_used) free(buf2); + if (buf1_used) free(buf1); + return (n <= outsize ? n : -1); +} + +/**************** + * MSDOS staffs * + ****************/ + +#ifdef MSDOS + +static char emacsroot[MAXPATHLEN]; + +void +init_environment (argc, argv, skip_args) + int argc; + char **argv; + int skip_args; +{ + char *s, *t, *root; + int len; + + /* Find our root from argv[0]. Assuming argv[0] is, say, + "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */ + len = strlen (argv[0]); + root = alloca (len + 10); /* A little extra space for the stuff below. */ + strcpy (root, argv[0]); + while (len > 0 && root[len] != '/' && root[len] != ':') + len--; + root[len] = '\0'; + if (len > 4 && strcmp (root + len - 4, "/bin") == 0) + root[len - 4] = '\0'; + else + strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */ + len = strlen (root); + strcpy (emacsroot, root); +} + +char * +rootrelativepath (rel) + char *rel; +{ + static char result[MAXPATHLEN + 10]; + + strcpy (result, emacsroot); + strcat (result, "/"); + strcat (result, rel); + return result; +} + +#endif /* MSDOS */ + +/*************** + * INITIALIZER * + ***************/ + +mulelib_initialize(argc, argv, charsets, codings) + int argc; + char **argv, *charsets, *codings; +{ + if (!mulelib_initialized) { + int i; + +#ifdef MSDOS + init_environment(argc, argv, 0); +#endif + + for (i = 0; i < 128; i++) { + font_name[i] = NULL; + font_encoding[i] = 0; + } + + if (charsets_initialize(charsets) < 0) return -1; + if (codings_initialize(codings) < 0) return -1; + mulelib_initialized = 1; + } + return 0; +}