Index: head/usr.bin/colldef/parse.y =================================================================== --- head/usr.bin/colldef/parse.y (revision 174964) +++ head/usr.bin/colldef/parse.y (revision 174965) @@ -1,383 +1,384 @@ %{ /*- * Copyright (c) 1995 Alex Tatmanjants * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include +#include #include #include #include #include #include #include #include "collate.h" #include "common.h" extern FILE *yyin; void yyerror(const char *fmt, ...) __printflike(1, 2); int yyparse(void); int yylex(void); static void usage(void); static void collate_print_tables(void); char map_name[FILENAME_MAX] = "."; char curr_chain[STR_LEN]; char __collate_version[STR_LEN]; u_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN]; #undef __collate_substitute_table u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; #undef __collate_char_pri_table struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; struct __collate_st_chain_pri *__collate_chain_pri_table; int chain_index = 0; int prim_pri = 1, sec_pri = 1; #ifdef COLLATE_DEBUG int debug; #endif const char *out_file = "LC_COLLATE"; %} %union { u_char ch; u_char str[BUFSIZE]; } %token SUBSTITUTE WITH ORDER RANGE %token STRING %token DEFN %token CHAR %% collate : statment_list ; statment_list : statment | statment_list '\n' statment ; statment : | charmap | substitute | order ; charmap : DEFN CHAR { if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN) yyerror("Charmap symbol name '%s' is too long", $1); strcpy(charmap_table[$2], $1); } ; substitute : SUBSTITUTE CHAR WITH STRING { if ($2 == '\0') yyerror("NUL character can't be substituted"); if (strchr($4, $2) != NULL) yyerror("Char 0x%02x substitution is recursive", $2); if (strlen($4) + 1 > STR_LEN) yyerror("Char 0x%02x substitution is too long", $2); strcpy(__collate_substitute_table[$2], $4); } ; order : ORDER order_list { FILE *fp; int ch, substed, ordered; uint32_t u32; for (ch = 0; ch < UCHAR_MAX + 1; ch++) { substed = (__collate_substitute_table[ch][0] != ch); ordered = !!__collate_char_pri_table[ch].prim; if (!ordered && !substed) yyerror("Char 0x%02x not found", ch); if (substed && ordered) yyerror("Char 0x%02x can't be ordered since substituted", ch); } if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) yyerror("can't grow chain table"); (void)memset(&__collate_chain_pri_table[chain_index], 0, sizeof(__collate_chain_pri_table[0])); chain_index++; #ifdef COLLATE_DEBUG if (debug) collate_print_tables(); #endif if ((fp = fopen(out_file, "w")) == NULL) err(EX_UNAVAILABLE, "can't open destination file %s", out_file); strcpy(__collate_version, COLLATE_VERSION1_2); if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1) err(EX_IOERR, "IO error writting collate version to destination file %s", out_file); u32 = htonl(chain_index); if (fwrite(&u32, sizeof(u32), 1, fp) != 1) err(EX_IOERR, "IO error writting chains number to destination file %s", out_file); if (fwrite(__collate_substitute_table, sizeof(__collate_substitute_table), 1, fp) != 1) err(EX_IOERR, "IO error writting substitute table to destination file %s", out_file); for (ch = 0; ch < UCHAR_MAX + 1; ch++) { __collate_char_pri_table[ch].prim = htonl(__collate_char_pri_table[ch].prim); __collate_char_pri_table[ch].sec = htonl(__collate_char_pri_table[ch].sec); } if (fwrite(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, fp) != 1) err(EX_IOERR, "IO error writting char table to destination file %s", out_file); for (ch = 0; ch < chain_index; ch++) { __collate_chain_pri_table[ch].prim = htonl(__collate_chain_pri_table[ch].prim); __collate_chain_pri_table[ch].sec = htonl(__collate_chain_pri_table[ch].sec); } if (fwrite(__collate_chain_pri_table, sizeof(*__collate_chain_pri_table), chain_index, fp) != (size_t)chain_index) err(EX_IOERR, "IO error writting chain table to destination file %s", out_file); if (fclose(fp) != 0) err(EX_IOERR, "IO error closing destination file %s", out_file); exit(EX_OK); } ; order_list : item | order_list ';' item ; chain : CHAR CHAR { curr_chain[0] = $1; curr_chain[1] = $2; if (curr_chain[0] == '\0' || curr_chain[1] == '\0') yyerror("\\0 can't be chained"); curr_chain[2] = '\0'; } | chain CHAR { static char tb[2]; tb[0] = $2; if (tb[0] == '\0') yyerror("\\0 can't be chained"); if (strlen(curr_chain) + 2 > STR_LEN) yyerror("Chain '%s' grows too long", curr_chain); (void)strcat(curr_chain, tb); } ; item : CHAR { if (__collate_char_pri_table[$1].prim) yyerror("Char 0x%02x duplicated", $1); __collate_char_pri_table[$1].prim = prim_pri++; } | chain { if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) yyerror("can't grow chain table"); (void)memset(&__collate_chain_pri_table[chain_index], 0, sizeof(__collate_chain_pri_table[0])); (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); __collate_chain_pri_table[chain_index].prim = prim_pri++; chain_index++; } | CHAR RANGE CHAR { u_int i; if ($3 <= $1) yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); for (i = $1; i <= $3; i++) { if (__collate_char_pri_table[(u_char)i].prim) yyerror("Char 0x%02x duplicated", (u_char)i); __collate_char_pri_table[(u_char)i].prim = prim_pri++; } } | '{' prim_order_list '}' { prim_pri++; } | '(' sec_order_list ')' { prim_pri++; sec_pri = 1; } ; prim_order_list : prim_sub_item | prim_order_list ',' prim_sub_item ; sec_order_list : sec_sub_item | sec_order_list ',' sec_sub_item ; prim_sub_item : CHAR { if (__collate_char_pri_table[$1].prim) yyerror("Char 0x%02x duplicated", $1); __collate_char_pri_table[$1].prim = prim_pri; } | CHAR RANGE CHAR { u_int i; if ($3 <= $1) yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); for (i = $1; i <= $3; i++) { if (__collate_char_pri_table[(u_char)i].prim) yyerror("Char 0x%02x duplicated", (u_char)i); __collate_char_pri_table[(u_char)i].prim = prim_pri; } } | chain { if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) yyerror("can't grow chain table"); (void)memset(&__collate_chain_pri_table[chain_index], 0, sizeof(__collate_chain_pri_table[0])); (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); __collate_chain_pri_table[chain_index].prim = prim_pri; chain_index++; } ; sec_sub_item : CHAR { if (__collate_char_pri_table[$1].prim) yyerror("Char 0x%02x duplicated", $1); __collate_char_pri_table[$1].prim = prim_pri; __collate_char_pri_table[$1].sec = sec_pri++; } | CHAR RANGE CHAR { u_int i; if ($3 <= $1) yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); for (i = $1; i <= $3; i++) { if (__collate_char_pri_table[(u_char)i].prim) yyerror("Char 0x%02x duplicated", (u_char)i); __collate_char_pri_table[(u_char)i].prim = prim_pri; __collate_char_pri_table[(u_char)i].sec = sec_pri++; } } | chain { if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) yyerror("can't grow chain table"); (void)memset(&__collate_chain_pri_table[chain_index], 0, sizeof(__collate_chain_pri_table[0])); (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); __collate_chain_pri_table[chain_index].prim = prim_pri; __collate_chain_pri_table[chain_index].sec = sec_pri++; chain_index++; } ; %% int main(int ac, char **av) { int ch; #ifdef COLLATE_DEBUG while((ch = getopt(ac, av, ":do:I:")) != -1) { #else while((ch = getopt(ac, av, ":o:I:")) != -1) { #endif switch (ch) { #ifdef COLLATE_DEBUG case 'd': debug++; break; #endif case 'o': out_file = optarg; break; case 'I': strlcpy(map_name, optarg, sizeof(map_name)); break; default: usage(); } } ac -= optind; av += optind; if (ac > 0) { if ((yyin = fopen(*av, "r")) == NULL) err(EX_UNAVAILABLE, "can't open source file %s", *av); } for (ch = 0; ch <= UCHAR_MAX; ch++) __collate_substitute_table[ch][0] = ch; yyparse(); return 0; } static void usage(void) { fprintf(stderr, "usage: colldef [-I map_dir] [-o out_file] [filename]\n"); exit(EX_USAGE); } void yyerror(const char *fmt, ...) { va_list ap; char msg[128]; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no); } #ifdef COLLATE_DEBUG static void collate_print_tables(void) { int i; printf("Substitute table:\n"); for (i = 0; i < UCHAR_MAX + 1; i++) if (i != *__collate_substitute_table[i]) printf("\t'%c' --> \"%s\"\n", i, __collate_substitute_table[i]); printf("Chain priority table:\n"); for (i = 0; i < chain_index - 1; i++) printf("\t\"%s\" : %d %d\n", __collate_chain_pri_table[i].str, __collate_chain_pri_table[i].prim, __collate_chain_pri_table[i].sec); printf("Char priority table:\n"); for (i = 0; i < UCHAR_MAX + 1; i++) printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, __collate_char_pri_table[i].sec); } #endif Index: head/usr.bin/colldef/scan.l =================================================================== --- head/usr.bin/colldef/scan.l (revision 174964) +++ head/usr.bin/colldef/scan.l (revision 174965) @@ -1,286 +1,287 @@ %x string name charmap defn nchar subs subs2 %{ /*- * Copyright (c) 1995 Alex Tatmanjants * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include +#include #include "common.h" #include "y.tab.h" int line_no = 1, save_no, fromsubs; u_char buf[BUFSIZE], *ptr; FILE *map_fp; YY_BUFFER_STATE main_buf, map_buf; #ifdef FLEX_DEBUG YYSTYPE yylval; #endif /* FLEX_DEBUG */ int yylex(void); %} %% [ \t]+ ; \" { ptr = buf; BEGIN(string); } \< { ptr = buf; fromsubs = 1; BEGIN(name); } \< { ptr = buf; fromsubs = 0; BEGIN(name); } ^#.*\n line_no++; ^\n line_no++; \\\n line_no++; \\t { yylval.ch = '\t'; return CHAR; } \\n { yylval.ch = '\n'; return CHAR; } \\b { yylval.ch = '\b'; return CHAR; } \\f { yylval.ch = '\f'; return CHAR; } \\v { yylval.ch = '\v'; return CHAR; } \\r { yylval.ch = '\r'; return CHAR; } \\a { yylval.ch = '\a'; return CHAR; } \n { line_no++; BEGIN(INITIAL); return '\n'; } \n { line_no++; if (map_fp != NULL) { ptr = buf; BEGIN(defn); } return '\n'; } [;,{}()] return *yytext; substitute { BEGIN(subs); return SUBSTITUTE; } with { BEGIN(subs2); return WITH; } order return ORDER; charmap BEGIN(charmap); ;[ \t]*\.\.\.[ \t]*; return RANGE; \\[0-7]{3} { u_int v; sscanf(&yytext[1], "%o", &v); yylval.ch = (u_char)v; return CHAR; } \\x[0-9a-fA-F]{2} { u_int v; sscanf(&yytext[2], "%x", &v); yylval.ch = (u_char)v; return CHAR; } \\. { yylval.ch = yytext[1]; return CHAR; } . { yylval.ch = *yytext; return CHAR; } ^#.*\n line_no++; [ \t]+ { if (ptr == buf) errx(EX_UNAVAILABLE, "map expected near line %u of %s", line_no, map_name); *ptr = '\0'; strcpy(yylval.str, buf); BEGIN(nchar); return DEFN; } \/\/ { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", line_no); *ptr++ = '/'; } \/\> { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", line_no); *ptr++ = '>'; } \\\" { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", line_no); *ptr++ = '"'; } \> { u_int i; if (ptr == buf) errx(EX_UNAVAILABLE, "non-empty name expected near line %u", line_no); *ptr = '\0'; for (i = 0; i <= UCHAR_MAX; i++) { if (strcmp(charmap_table[i], buf) == 0) goto findit; } errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u", buf, line_no); findit: yylval.ch = i; if (fromsubs) BEGIN(subs); else BEGIN(INITIAL); return CHAR; } \" { *ptr = '\0'; strcpy(yylval.str, buf); BEGIN(subs2); return STRING; } . { const char *s = (map_fp != NULL) ? map_name : "input"; if (!isascii(*yytext) || !isprint(*yytext)) errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", *yytext, line_no, s); if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", line_no, s, *yytext); *ptr++ = *yytext; } \\t { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", line_no); *ptr++ = '\t'; } \\b { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", line_no); *ptr++ = '\b'; } \\f { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", line_no); *ptr++ = '\f'; } \\v { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", line_no); *ptr++ = '\v'; } \\n { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", line_no); *ptr++ = '\n'; } \\r { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", line_no); *ptr++ = '\r'; } \\a { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", line_no); *ptr++ = '\a'; } \n { const char *s = (map_fp != NULL) ? map_name : "input"; errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); } <> { const char *s = (map_fp != NULL) ? map_name : "input"; errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); } \\x[0-9a-f]{2} { u_int v; sscanf(&yytext[2], "%x", &v); *ptr++ = (u_char)v; } \\[0-7]{3} { u_int v; sscanf(&yytext[1], "%o", &v); *ptr++ = (u_char)v; } \\. { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", line_no, yytext[1]); *ptr++ = yytext[1]; } . { if(ptr >= buf + sizeof(buf) - 1) errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", line_no, *yytext); *ptr++ = *yytext; } [^ \t\n]+ { strcat(map_name, "/"); strcat(map_name, yytext); if((map_fp = fopen(map_name, "r")) == NULL) err(EX_UNAVAILABLE, "can't open 'charmap' file %s", map_name); save_no = line_no; line_no = 1; map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); main_buf = YY_CURRENT_BUFFER; yy_switch_to_buffer(map_buf); ptr = buf; BEGIN(defn); } \n { errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", line_no); } <> { errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", line_no); } <> { if(map_fp != NULL) { if (ptr != buf) errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); yy_switch_to_buffer(main_buf); yy_delete_buffer(map_buf); fclose(map_fp); map_fp = NULL; line_no = save_no; BEGIN(INITIAL); } else yyterminate(); } %% #ifdef FLEX_DEBUG main() { while(yylex()) ; return 0; } #endif /* FLEX_DEBUG */