/***************************************************************************** * * $Id$ * Purpose ...............: Characterset Compiler * Author ................: Martin Junius, for Fidogate * ***************************************************************************** * Copyright (C) 1997-2004 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * MBSE BBS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ /***************************************************************************** * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail * * Charset mapping table compiler * ***************************************************************************** * Copyright (C) 1990-2002 * _____ _____ * | |___ | Martin Junius * | | | | | | Radiumstr. 18 * |_|_|_|@home| D-51069 Koeln, Germany * * This file is part of FIDOGATE. * * FIDOGATE is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * FIDOGATE is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FIDOGATE; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************/ #include "../config.h" #include "mbselib.h" #include "mbcharsetc.h" char *str_copy(char *, size_t, char *); #define strieq(a,b) (strcasecmp ((a),(b)) == 0) #define PROGRAM "mbcharsetc" #define BUFFERSIZE (32*1024) /* Global buffer */ #define BUF_COPY(d,s) str_copy (d,sizeof(d),s) char buffer[BUFFERSIZE]; /* * Prototypes */ int charset_parse_c (char *); int charset_do_file (char *); int compile_map (char *, char *); void usage (void); /* * Check for hex digits, signed char-safe version of isxdigit() */ int is_xdigit(int c) { /* * Some implementation only accept a parameter value range * of [-1,255]. This may lead to problems, because we're quite often * passing *p's to is_digit() with a char *p variable. The default * char type is signed in most C implementation. */ return isxdigit((c & 0xff)); } /* * Check for octal digits */ int is_odigit(int c) { return c>='0' && c<'8'; } /* * isspace() replacement, checking for SPACE, TAB, CR, LF */ int is_space(int c) { return c==' ' || c=='\t' || c=='\r' || c=='\n'; } /* * Read line from config file. Strip `\n', leading spaces, * comments (starting with `#'), and empty lines. cf_getline() returns * a pointer to the first non-whitespace in buffer. */ static long cf_lineno = 0; long cf_lineno_get(void) { return cf_lineno; } long cf_lineno_set(long n) { long old; old = cf_lineno; cf_lineno = n; return old; } char *cf_getline(char *cbuffer, int len, FILE *fp) { char *p; while (fgets(cbuffer, len, fp)) { cf_lineno++; Striplf(cbuffer); for(p = cbuffer; *p && is_space(*p); p++) ; /* Skip white spaces */ if (*p != '#') return p; } return NULL; } /* * Parse character */ int charset_parse_c(char *s) { int val, n; if(s[0] == '\\') { /* Special: \NNN or \xNN */ s++; val = 0; n = 0; if(s[0]=='x' || s[0]=='X') { /* Hex */ s++; while (is_xdigit(s[0]) && n<2) { s[0] = toupper(s[0]); val = val * 16 + s[0] - (s[0]>'9' ? 'A'-10 : '0'); s++; n++; } if(*s) return ERROR; } else { /* Octal */ while(is_odigit(s[0]) && n<3) { val = val * 8 + s[0] - '0'; s++; n++; } if(*s) return ERROR; } } else { if(s[1] == 0) /* Single char */ val = s[0] & 0xff; else return ERROR; } return val & 0xff; } /* * Process one line from charset.map file */ int charset_do_line(char *line) { static CharsetTable *pt = NULL; char *key, *w1, *w2; CharsetAlias *pa; int i, c1, c2; key = strtok(line, " \t"); if(!key) return TRUE; if (strieq(key, "include")) { w1 = strtok(NULL, " \t"); if (charset_do_file(w1) == FALSE) return FALSE; } /* Define alias */ else if (strieq(key, "alias")) { w1 = strtok(NULL, " \t"); w2 = strtok(NULL, " \t"); if(!w1 || !w2) { fprintf(stderr, "%s:%ld: argument(s) for alias missing\n", PROGRAM, cf_lineno_get()); return FALSE; } pa = charset_alias_new(); BUF_COPY(pa->alias, w1); BUF_COPY(pa->name, w2); } /* Define table */ else if (strieq(key, "table")) { w1 = strtok(NULL, " \t"); w2 = strtok(NULL, " \t"); if(!w1 || !w2) { fprintf(stderr, "%s:%ld: argument(s) for table missing\n", PROGRAM, cf_lineno_get()); return FALSE; } pt = charset_table_new(); BUF_COPY(pt->in, w1); BUF_COPY(pt->out, w2); } /* Define mapping for character(s) in table */ else if (strieq(key, "map")) { w1 = strtok(NULL, " \t"); if (!w1) { fprintf(stderr, "%s:%ld: argument for map missing\n", PROGRAM, cf_lineno_get()); return FALSE; } /* 1:1 mapping */ if (strieq(w1, "1:1")) { for(i=0; imap[i][0] == 0) { pt->map[i][0] = 0x80 + i; pt->map[i][1] = 0; } } } /* 1:1 mapping, but not for 0x80...0x9f */ if(strieq(w1, "1:1-noctrl")) { for(i=0x20; imap[i][0] == 0) { pt->map[i][0] = 0x80 + i; pt->map[i][1] = 0; } } } /* Mapping for undefined characters */ else if(strieq(w1, "default")) { /**FIXME: not yet implemented**/ } /* Normal mapping */ else { if ((c1 = charset_parse_c(w1)) == ERROR) { fprintf(stderr, "%s:%ld: illegal char %s\n", PROGRAM, cf_lineno_get(), w1); return FALSE; } if (c1 < 0x80) { fprintf(stderr, "%s:%ld: illegal char %s, must be >= 0x80\n", PROGRAM, cf_lineno_get(), w1); return FALSE; } for (i=0; imap[c1 & 0x7f][i] = c2; } for (; imap[c1 & 0x7f][i] = 0; } } /* Error */ else { fprintf(stderr, "%s:%ld: illegal key word %s\n", PROGRAM, cf_lineno_get(), key); return FALSE; } return TRUE; } /* * Process charset.map file */ int charset_do_file(char *name) { FILE *fp; char *p; long oldn; if(!name) return FALSE; oldn = cf_lineno_set(0); fp = fopen(name, "r"); if(!fp) return FALSE; while ((p = cf_getline(buffer, BUFFERSIZE, fp))) charset_do_line(p); fclose(fp); cf_lineno_set(oldn); return TRUE; } /* * Compile charset.map */ int compile_map(char *in, char *out) { /* Read charset.map and compile */ if(charset_do_file(in) == FALSE) { fprintf(stderr, "%s: compiling map file %s failed", PROGRAM, in); return MBERR_GENERAL; } /* Write binary output file */ if (charset_write_bin(out) == ERROR) { fprintf(stderr, "%s: writing binary map file %s failed", PROGRAM, out); return MBERR_GENERAL; } return MBERR_OK; } void usage(void) { fprintf(stderr, "\n%s: MBSE BBS %s Character Map Compiler\n", PROGRAM, VERSION); fprintf(stderr, " %s\n\n", COPYRIGHT); fprintf(stderr, "usage: %s charset.map charset.bin\n\n", PROGRAM); exit(MBERR_OK); } int main(int argc, char **argv) { int ret = MBERR_OK; char *name_in, *name_out; if (argc != 3) usage(); name_in = argv[1]; name_out = argv[2]; ret = compile_map(name_in, name_out); exit(ret); }