16b5e5868SGarrett D'Amore /* 26b5e5868SGarrett D'Amore * This file and its contents are supplied under the terms of the 36b5e5868SGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 45aec55ebSGarrett D'Amore * You may only use this file in accordance with the terms of version 55aec55ebSGarrett D'Amore * 1.0 of the CDDL. 66b5e5868SGarrett D'Amore * 76b5e5868SGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 86b5e5868SGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 96b5e5868SGarrett D'Amore * http://www.illumos.org/license/CDDL. 106b5e5868SGarrett D'Amore */ 116b5e5868SGarrett D'Amore 126b5e5868SGarrett D'Amore /* 136b5e5868SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 14*2da1cd3aSGarrett D'Amore * Copyright 2013 DEY Storage Systems, Inc. 156b5e5868SGarrett D'Amore */ 166b5e5868SGarrett D'Amore 176b5e5868SGarrett D'Amore /* 186b5e5868SGarrett D'Amore * This file contains the "scanner", which tokenizes the input files 196b5e5868SGarrett D'Amore * for localedef for processing by the higher level grammar processor. 206b5e5868SGarrett D'Amore */ 216b5e5868SGarrett D'Amore 226b5e5868SGarrett D'Amore #include <stdio.h> 236b5e5868SGarrett D'Amore #include <stdlib.h> 246b5e5868SGarrett D'Amore #include <ctype.h> 256b5e5868SGarrett D'Amore #include <limits.h> 266b5e5868SGarrett D'Amore #include <string.h> 276b5e5868SGarrett D'Amore #include <widec.h> 286b5e5868SGarrett D'Amore #include <sys/types.h> 296b5e5868SGarrett D'Amore #include <assert.h> 306b5e5868SGarrett D'Amore #include "localedef.h" 316b5e5868SGarrett D'Amore #include "parser.tab.h" 326b5e5868SGarrett D'Amore 336b5e5868SGarrett D'Amore int com_char = '#'; 346b5e5868SGarrett D'Amore int esc_char = '\\'; 356b5e5868SGarrett D'Amore int mb_cur_min = 1; 366b5e5868SGarrett D'Amore int mb_cur_max = 1; 376b5e5868SGarrett D'Amore int lineno = 1; 386b5e5868SGarrett D'Amore int warnings = 0; 396b5e5868SGarrett D'Amore static int nextline; 406b5e5868SGarrett D'Amore static FILE *input = stdin; 416b5e5868SGarrett D'Amore static const char *filename = "<stdin>"; 426b5e5868SGarrett D'Amore static int instring = 0; 436b5e5868SGarrett D'Amore static int escaped = 0; 446b5e5868SGarrett D'Amore 456b5e5868SGarrett D'Amore /* 466b5e5868SGarrett D'Amore * Token space ... grows on demand. 476b5e5868SGarrett D'Amore */ 486b5e5868SGarrett D'Amore static char *token = NULL; 496b5e5868SGarrett D'Amore static int tokidx; 506b5e5868SGarrett D'Amore static int toksz = 0; 516b5e5868SGarrett D'Amore static int hadtok = 0; 526b5e5868SGarrett D'Amore 536b5e5868SGarrett D'Amore /* 546b5e5868SGarrett D'Amore * Wide string space ... grows on demand. 556b5e5868SGarrett D'Amore */ 566b5e5868SGarrett D'Amore static wchar_t *widestr = NULL; 576b5e5868SGarrett D'Amore static int wideidx = 0; 586b5e5868SGarrett D'Amore static int widesz = 0; 596b5e5868SGarrett D'Amore 606b5e5868SGarrett D'Amore /* 616b5e5868SGarrett D'Amore * The last keyword seen. This is useful to trigger the special lexer rules 626b5e5868SGarrett D'Amore * for "copy" and also collating symbols and elements. 636b5e5868SGarrett D'Amore */ 646b5e5868SGarrett D'Amore int last_kw = 0; 656b5e5868SGarrett D'Amore static int category = T_END; 666b5e5868SGarrett D'Amore 676b5e5868SGarrett D'Amore static struct token { 686b5e5868SGarrett D'Amore int id; 696b5e5868SGarrett D'Amore const char *name; 706b5e5868SGarrett D'Amore } keywords[] = { 716b5e5868SGarrett D'Amore { T_COM_CHAR, "comment_char" }, 726b5e5868SGarrett D'Amore { T_ESC_CHAR, "escape_char" }, 736b5e5868SGarrett D'Amore { T_END, "END" }, 746b5e5868SGarrett D'Amore { T_COPY, "copy" }, 756b5e5868SGarrett D'Amore { T_MESSAGES, "LC_MESSAGES" }, 766b5e5868SGarrett D'Amore { T_YESSTR, "yesstr" }, 776b5e5868SGarrett D'Amore { T_YESEXPR, "yesexpr" }, 786b5e5868SGarrett D'Amore { T_NOSTR, "nostr" }, 796b5e5868SGarrett D'Amore { T_NOEXPR, "noexpr" }, 806b5e5868SGarrett D'Amore { T_MONETARY, "LC_MONETARY" }, 816b5e5868SGarrett D'Amore { T_INT_CURR_SYMBOL, "int_curr_symbol" }, 826b5e5868SGarrett D'Amore { T_CURRENCY_SYMBOL, "currency_symbol" }, 836b5e5868SGarrett D'Amore { T_MON_DECIMAL_POINT, "mon_decimal_point" }, 846b5e5868SGarrett D'Amore { T_MON_THOUSANDS_SEP, "mon_thousands_sep" }, 856b5e5868SGarrett D'Amore { T_POSITIVE_SIGN, "positive_sign" }, 866b5e5868SGarrett D'Amore { T_NEGATIVE_SIGN, "negative_sign" }, 876b5e5868SGarrett D'Amore { T_MON_GROUPING, "mon_grouping" }, 886b5e5868SGarrett D'Amore { T_INT_FRAC_DIGITS, "int_frac_digits" }, 896b5e5868SGarrett D'Amore { T_FRAC_DIGITS, "frac_digits" }, 906b5e5868SGarrett D'Amore { T_P_CS_PRECEDES, "p_cs_precedes" }, 916b5e5868SGarrett D'Amore { T_P_SEP_BY_SPACE, "p_sep_by_space" }, 926b5e5868SGarrett D'Amore { T_N_CS_PRECEDES, "n_cs_precedes" }, 936b5e5868SGarrett D'Amore { T_N_SEP_BY_SPACE, "n_sep_by_space" }, 946b5e5868SGarrett D'Amore { T_P_SIGN_POSN, "p_sign_posn" }, 956b5e5868SGarrett D'Amore { T_N_SIGN_POSN, "n_sign_posn" }, 966b5e5868SGarrett D'Amore { T_INT_P_CS_PRECEDES, "int_p_cs_precedes" }, 976b5e5868SGarrett D'Amore { T_INT_N_CS_PRECEDES, "int_n_cs_precedes" }, 986b5e5868SGarrett D'Amore { T_INT_P_SEP_BY_SPACE, "int_p_sep_by_space" }, 996b5e5868SGarrett D'Amore { T_INT_N_SEP_BY_SPACE, "int_n_sep_by_space" }, 1006b5e5868SGarrett D'Amore { T_INT_P_SIGN_POSN, "int_p_sign_posn" }, 1016b5e5868SGarrett D'Amore { T_INT_N_SIGN_POSN, "int_n_sign_posn" }, 1026b5e5868SGarrett D'Amore { T_COLLATE, "LC_COLLATE" }, 1036b5e5868SGarrett D'Amore { T_COLLATING_SYMBOL, "collating-symbol" }, 1046b5e5868SGarrett D'Amore { T_COLLATING_ELEMENT, "collating-element" }, 1056b5e5868SGarrett D'Amore { T_FROM, "from" }, 1066b5e5868SGarrett D'Amore { T_ORDER_START, "order_start" }, 1076b5e5868SGarrett D'Amore { T_ORDER_END, "order_end" }, 1086b5e5868SGarrett D'Amore { T_FORWARD, "forward" }, 1096b5e5868SGarrett D'Amore { T_BACKWARD, "backward" }, 1106b5e5868SGarrett D'Amore { T_POSITION, "position" }, 1116b5e5868SGarrett D'Amore { T_IGNORE, "IGNORE" }, 1126b5e5868SGarrett D'Amore { T_UNDEFINED, "UNDEFINED" }, 1136b5e5868SGarrett D'Amore { T_NUMERIC, "LC_NUMERIC" }, 1146b5e5868SGarrett D'Amore { T_DECIMAL_POINT, "decimal_point" }, 1156b5e5868SGarrett D'Amore { T_THOUSANDS_SEP, "thousands_sep" }, 1166b5e5868SGarrett D'Amore { T_GROUPING, "grouping" }, 1176b5e5868SGarrett D'Amore { T_TIME, "LC_TIME" }, 1186b5e5868SGarrett D'Amore { T_ABDAY, "abday" }, 1196b5e5868SGarrett D'Amore { T_DAY, "day" }, 1206b5e5868SGarrett D'Amore { T_ABMON, "abmon" }, 1216b5e5868SGarrett D'Amore { T_MON, "mon" }, 1226b5e5868SGarrett D'Amore { T_D_T_FMT, "d_t_fmt" }, 1236b5e5868SGarrett D'Amore { T_D_FMT, "d_fmt" }, 1246b5e5868SGarrett D'Amore { T_T_FMT, "t_fmt" }, 1256b5e5868SGarrett D'Amore { T_AM_PM, "am_pm" }, 1266b5e5868SGarrett D'Amore { T_T_FMT_AMPM, "t_fmt_ampm" }, 1276b5e5868SGarrett D'Amore { T_ERA, "era" }, 1286b5e5868SGarrett D'Amore { T_ERA_D_FMT, "era_d_fmt" }, 1296b5e5868SGarrett D'Amore { T_ERA_T_FMT, "era_t_fmt" }, 1306b5e5868SGarrett D'Amore { T_ERA_D_T_FMT, "era_d_t_fmt" }, 1316b5e5868SGarrett D'Amore { T_ALT_DIGITS, "alt_digits" }, 1326b5e5868SGarrett D'Amore { T_CTYPE, "LC_CTYPE" }, 1336b5e5868SGarrett D'Amore { T_ISUPPER, "upper" }, 1346b5e5868SGarrett D'Amore { T_ISLOWER, "lower" }, 1356b5e5868SGarrett D'Amore { T_ISALPHA, "alpha" }, 1366b5e5868SGarrett D'Amore { T_ISDIGIT, "digit" }, 1376b5e5868SGarrett D'Amore { T_ISPUNCT, "punct" }, 1386b5e5868SGarrett D'Amore { T_ISXDIGIT, "xdigit" }, 1396b5e5868SGarrett D'Amore { T_ISSPACE, "space" }, 1406b5e5868SGarrett D'Amore { T_ISPRINT, "print" }, 1416b5e5868SGarrett D'Amore { T_ISGRAPH, "graph" }, 1426b5e5868SGarrett D'Amore { T_ISBLANK, "blank" }, 1436b5e5868SGarrett D'Amore { T_ISCNTRL, "cntrl" }, 1446b5e5868SGarrett D'Amore /* 1456b5e5868SGarrett D'Amore * These entries are local additions, and not specified by 1466b5e5868SGarrett D'Amore * TOG. Note that they are not guaranteed to be accurate for 1476b5e5868SGarrett D'Amore * all locales, and so applications should not depend on them. 1486b5e5868SGarrett D'Amore */ 1496b5e5868SGarrett D'Amore { T_ISSPECIAL, "special" }, 1506b5e5868SGarrett D'Amore { T_ISENGLISH, "english" }, 1516b5e5868SGarrett D'Amore { T_ISPHONOGRAM, "phonogram" }, 1526b5e5868SGarrett D'Amore { T_ISIDEOGRAM, "ideogram" }, 1536b5e5868SGarrett D'Amore { T_ISNUMBER, "number" }, 1546b5e5868SGarrett D'Amore /* 1556b5e5868SGarrett D'Amore * We have to support this in the grammar, but it would be a 1566b5e5868SGarrett D'Amore * syntax error to define a character as one of these without 1576b5e5868SGarrett D'Amore * also defining it as an alpha or digit. We ignore it in our 1586b5e5868SGarrett D'Amore * parsing. 1596b5e5868SGarrett D'Amore */ 1606b5e5868SGarrett D'Amore { T_ISALNUM, "alnum" }, 1616b5e5868SGarrett D'Amore { T_TOUPPER, "toupper" }, 1626b5e5868SGarrett D'Amore { T_TOLOWER, "tolower" }, 1636b5e5868SGarrett D'Amore 1646b5e5868SGarrett D'Amore /* 1656b5e5868SGarrett D'Amore * These are keywords used in the charmap file. Note that 1666b5e5868SGarrett D'Amore * Solaris orginally used angle brackets to wrap some of them, 1676b5e5868SGarrett D'Amore * but we removed that to simplify our parser. The first of these 1686b5e5868SGarrett D'Amore * items are "global items." 1696b5e5868SGarrett D'Amore */ 1706b5e5868SGarrett D'Amore { T_CHARMAP, "CHARMAP" }, 1716b5e5868SGarrett D'Amore { T_WIDTH, "WIDTH" }, 1726b5e5868SGarrett D'Amore 1736b5e5868SGarrett D'Amore { -1, NULL }, 1746b5e5868SGarrett D'Amore }; 1756b5e5868SGarrett D'Amore 1766b5e5868SGarrett D'Amore /* 1776b5e5868SGarrett D'Amore * These special words are only used in a charmap file, enclosed in <>. 1786b5e5868SGarrett D'Amore */ 1796b5e5868SGarrett D'Amore static struct token symwords[] = { 1806b5e5868SGarrett D'Amore { T_COM_CHAR, "comment_char" }, 1816b5e5868SGarrett D'Amore { T_ESC_CHAR, "escape_char" }, 1826b5e5868SGarrett D'Amore { T_CODE_SET, "code_set_name" }, 1836b5e5868SGarrett D'Amore { T_MB_CUR_MAX, "mb_cur_max" }, 1846b5e5868SGarrett D'Amore { T_MB_CUR_MIN, "mb_cur_min" }, 1856b5e5868SGarrett D'Amore { -1, NULL }, 1866b5e5868SGarrett D'Amore }; 1876b5e5868SGarrett D'Amore 1886b5e5868SGarrett D'Amore static int categories[] = { 1896b5e5868SGarrett D'Amore T_CHARMAP, 1906b5e5868SGarrett D'Amore T_CTYPE, 1916b5e5868SGarrett D'Amore T_COLLATE, 1926b5e5868SGarrett D'Amore T_MESSAGES, 1936b5e5868SGarrett D'Amore T_MONETARY, 1946b5e5868SGarrett D'Amore T_NUMERIC, 1956b5e5868SGarrett D'Amore T_TIME, 196*2da1cd3aSGarrett D'Amore T_WIDTH, 1976b5e5868SGarrett D'Amore 0 1986b5e5868SGarrett D'Amore }; 1996b5e5868SGarrett D'Amore 2006b5e5868SGarrett D'Amore void 2016b5e5868SGarrett D'Amore reset_scanner(const char *fname) 2026b5e5868SGarrett D'Amore { 2036b5e5868SGarrett D'Amore if (fname == NULL) { 2046b5e5868SGarrett D'Amore filename = "<stdin>"; 2056b5e5868SGarrett D'Amore input = stdin; 2066b5e5868SGarrett D'Amore } else { 2076b5e5868SGarrett D'Amore if (input != stdin) 2086b5e5868SGarrett D'Amore (void) fclose(input); 2096b5e5868SGarrett D'Amore if ((input = fopen(fname, "r")) == NULL) { 2106b5e5868SGarrett D'Amore perror("fopen"); 2116b5e5868SGarrett D'Amore exit(4); 2126b5e5868SGarrett D'Amore } 2136b5e5868SGarrett D'Amore filename = fname; 2146b5e5868SGarrett D'Amore } 2156b5e5868SGarrett D'Amore com_char = '#'; 2166b5e5868SGarrett D'Amore esc_char = '\\'; 2176b5e5868SGarrett D'Amore instring = 0; 2186b5e5868SGarrett D'Amore escaped = 0; 2196b5e5868SGarrett D'Amore lineno = 1; 2206b5e5868SGarrett D'Amore nextline = 1; 2216b5e5868SGarrett D'Amore tokidx = 0; 2226b5e5868SGarrett D'Amore wideidx = 0; 2236b5e5868SGarrett D'Amore } 2246b5e5868SGarrett D'Amore 2256b5e5868SGarrett D'Amore #define hex(x) \ 2266b5e5868SGarrett D'Amore (isdigit(x) ? (x - '0') : ((islower(x) ? (x - 'a') : (x - 'A')) + 10)) 2276b5e5868SGarrett D'Amore #define isodigit(x) ((x >= '0') && (x <= '7')) 2286b5e5868SGarrett D'Amore 2296b5e5868SGarrett D'Amore static int 2306b5e5868SGarrett D'Amore scanc(void) 2316b5e5868SGarrett D'Amore { 2326b5e5868SGarrett D'Amore int c; 2336b5e5868SGarrett D'Amore 2346b5e5868SGarrett D'Amore c = getc(input); 2356b5e5868SGarrett D'Amore lineno = nextline; 2366b5e5868SGarrett D'Amore if (c == '\n') { 2376b5e5868SGarrett D'Amore nextline++; 2386b5e5868SGarrett D'Amore } 2396b5e5868SGarrett D'Amore return (c); 2406b5e5868SGarrett D'Amore } 2416b5e5868SGarrett D'Amore 2426b5e5868SGarrett D'Amore static void 2436b5e5868SGarrett D'Amore unscanc(int c) 2446b5e5868SGarrett D'Amore { 2456b5e5868SGarrett D'Amore if (c == '\n') { 2466b5e5868SGarrett D'Amore nextline--; 2476b5e5868SGarrett D'Amore } 2486b5e5868SGarrett D'Amore if (ungetc(c, input) < 0) { 2496b5e5868SGarrett D'Amore yyerror(_("ungetc failed")); 2506b5e5868SGarrett D'Amore } 2516b5e5868SGarrett D'Amore } 2526b5e5868SGarrett D'Amore 2536b5e5868SGarrett D'Amore static int 2546b5e5868SGarrett D'Amore scan_hex_byte(void) 2556b5e5868SGarrett D'Amore { 2566b5e5868SGarrett D'Amore int c1, c2; 2576b5e5868SGarrett D'Amore int v; 2586b5e5868SGarrett D'Amore 2596b5e5868SGarrett D'Amore c1 = scanc(); 2606b5e5868SGarrett D'Amore if (!isxdigit(c1)) { 2616b5e5868SGarrett D'Amore yyerror(_("malformed hex digit")); 2626b5e5868SGarrett D'Amore return (0); 2636b5e5868SGarrett D'Amore } 2646b5e5868SGarrett D'Amore c2 = scanc(); 2656b5e5868SGarrett D'Amore if (!isxdigit(c2)) { 2666b5e5868SGarrett D'Amore yyerror(_("malformed hex digit")); 2676b5e5868SGarrett D'Amore return (0); 2686b5e5868SGarrett D'Amore } 2696b5e5868SGarrett D'Amore v = ((hex(c1) << 4) | hex(c2)); 2706b5e5868SGarrett D'Amore return (v); 2716b5e5868SGarrett D'Amore } 2726b5e5868SGarrett D'Amore 2736b5e5868SGarrett D'Amore static int 2746b5e5868SGarrett D'Amore scan_dec_byte(void) 2756b5e5868SGarrett D'Amore { 2766b5e5868SGarrett D'Amore int c1, c2, c3; 2776b5e5868SGarrett D'Amore int b; 2786b5e5868SGarrett D'Amore 2796b5e5868SGarrett D'Amore c1 = scanc(); 2806b5e5868SGarrett D'Amore if (!isdigit(c1)) { 2816b5e5868SGarrett D'Amore yyerror(_("malformed decimal digit")); 2826b5e5868SGarrett D'Amore return (0); 2836b5e5868SGarrett D'Amore } 2846b5e5868SGarrett D'Amore b = c1 - '0'; 2856b5e5868SGarrett D'Amore c2 = scanc(); 2866b5e5868SGarrett D'Amore if (!isdigit(c2)) { 2876b5e5868SGarrett D'Amore yyerror(_("malformed decimal digit")); 2886b5e5868SGarrett D'Amore return (0); 2896b5e5868SGarrett D'Amore } 2906b5e5868SGarrett D'Amore b *= 10; 2916b5e5868SGarrett D'Amore b += (c2 - '0'); 2926b5e5868SGarrett D'Amore c3 = scanc(); 2936b5e5868SGarrett D'Amore if (!isdigit(c3)) { 2946b5e5868SGarrett D'Amore unscanc(c3); 2956b5e5868SGarrett D'Amore } else { 2966b5e5868SGarrett D'Amore b *= 10; 2976b5e5868SGarrett D'Amore b += (c3 - '0'); 2986b5e5868SGarrett D'Amore } 2996b5e5868SGarrett D'Amore return (b); 3006b5e5868SGarrett D'Amore } 3016b5e5868SGarrett D'Amore 3026b5e5868SGarrett D'Amore static int 3036b5e5868SGarrett D'Amore scan_oct_byte(void) 3046b5e5868SGarrett D'Amore { 3056b5e5868SGarrett D'Amore int c1, c2, c3; 3066b5e5868SGarrett D'Amore int b; 3076b5e5868SGarrett D'Amore 3086b5e5868SGarrett D'Amore b = 0; 3096b5e5868SGarrett D'Amore 3106b5e5868SGarrett D'Amore c1 = scanc(); 3116b5e5868SGarrett D'Amore if (!isodigit(c1)) { 3126b5e5868SGarrett D'Amore yyerror(_("malformed octal digit")); 3136b5e5868SGarrett D'Amore return (0); 3146b5e5868SGarrett D'Amore } 3156b5e5868SGarrett D'Amore b = c1 - '0'; 3166b5e5868SGarrett D'Amore c2 = scanc(); 3176b5e5868SGarrett D'Amore if (!isodigit(c2)) { 3186b5e5868SGarrett D'Amore yyerror(_("malformed octal digit")); 3196b5e5868SGarrett D'Amore return (0); 3206b5e5868SGarrett D'Amore } 3216b5e5868SGarrett D'Amore b *= 8; 3226b5e5868SGarrett D'Amore b += (c2 - '0'); 3236b5e5868SGarrett D'Amore c3 = scanc(); 3246b5e5868SGarrett D'Amore if (!isodigit(c3)) { 3256b5e5868SGarrett D'Amore unscanc(c3); 3266b5e5868SGarrett D'Amore } else { 3276b5e5868SGarrett D'Amore b *= 8; 3286b5e5868SGarrett D'Amore b += (c3 - '0'); 3296b5e5868SGarrett D'Amore } 3306b5e5868SGarrett D'Amore return (b); 3316b5e5868SGarrett D'Amore } 3326b5e5868SGarrett D'Amore 3336b5e5868SGarrett D'Amore void 3346b5e5868SGarrett D'Amore add_tok(int c) 3356b5e5868SGarrett D'Amore { 3366b5e5868SGarrett D'Amore if ((tokidx + 1) >= toksz) { 3376b5e5868SGarrett D'Amore toksz += 64; 3386b5e5868SGarrett D'Amore if ((token = realloc(token, toksz)) == NULL) { 3396b5e5868SGarrett D'Amore yyerror(_("out of memory")); 3406b5e5868SGarrett D'Amore tokidx = 0; 3416b5e5868SGarrett D'Amore toksz = 0; 3426b5e5868SGarrett D'Amore return; 3436b5e5868SGarrett D'Amore } 3446b5e5868SGarrett D'Amore } 3456b5e5868SGarrett D'Amore 3466b5e5868SGarrett D'Amore token[tokidx++] = (char)c; 3476b5e5868SGarrett D'Amore token[tokidx] = 0; 3486b5e5868SGarrett D'Amore } 3496b5e5868SGarrett D'Amore void 3506b5e5868SGarrett D'Amore add_wcs(wchar_t c) 3516b5e5868SGarrett D'Amore { 3526b5e5868SGarrett D'Amore if ((wideidx + 1) >= widesz) { 3536b5e5868SGarrett D'Amore widesz += 64; 3546b5e5868SGarrett D'Amore widestr = realloc(widestr, (widesz * sizeof (wchar_t))); 3556b5e5868SGarrett D'Amore if (widestr == NULL) { 3566b5e5868SGarrett D'Amore yyerror(_("out of memory")); 3576b5e5868SGarrett D'Amore wideidx = 0; 3586b5e5868SGarrett D'Amore widesz = 0; 3596b5e5868SGarrett D'Amore return; 3606b5e5868SGarrett D'Amore } 3616b5e5868SGarrett D'Amore } 3626b5e5868SGarrett D'Amore 3636b5e5868SGarrett D'Amore widestr[wideidx++] = c; 3646b5e5868SGarrett D'Amore widestr[wideidx] = 0; 3656b5e5868SGarrett D'Amore } 3666b5e5868SGarrett D'Amore 3676b5e5868SGarrett D'Amore wchar_t * 3686b5e5868SGarrett D'Amore get_wcs(void) 3696b5e5868SGarrett D'Amore { 3706b5e5868SGarrett D'Amore wchar_t *ws = widestr; 3716b5e5868SGarrett D'Amore wideidx = 0; 3726b5e5868SGarrett D'Amore widestr = NULL; 3736b5e5868SGarrett D'Amore widesz = 0; 3746b5e5868SGarrett D'Amore if (ws == NULL) { 3756b5e5868SGarrett D'Amore if ((ws = wsdup(L"")) == NULL) { 3766b5e5868SGarrett D'Amore yyerror(_("out of memory")); 3776b5e5868SGarrett D'Amore } 3786b5e5868SGarrett D'Amore } 3796b5e5868SGarrett D'Amore return (ws); 3806b5e5868SGarrett D'Amore } 3816b5e5868SGarrett D'Amore 3826b5e5868SGarrett D'Amore static int 3836b5e5868SGarrett D'Amore get_byte(void) 3846b5e5868SGarrett D'Amore { 3856b5e5868SGarrett D'Amore int c; 3866b5e5868SGarrett D'Amore 3876b5e5868SGarrett D'Amore if ((c = scanc()) != esc_char) { 3886b5e5868SGarrett D'Amore unscanc(c); 3896b5e5868SGarrett D'Amore return (EOF); 3906b5e5868SGarrett D'Amore } 3916b5e5868SGarrett D'Amore c = scanc(); 3926b5e5868SGarrett D'Amore 3936b5e5868SGarrett D'Amore switch (c) { 3946b5e5868SGarrett D'Amore case 'd': 3956b5e5868SGarrett D'Amore case 'D': 3966b5e5868SGarrett D'Amore return (scan_dec_byte()); 3976b5e5868SGarrett D'Amore case 'x': 3986b5e5868SGarrett D'Amore case 'X': 3996b5e5868SGarrett D'Amore return (scan_hex_byte()); 4006b5e5868SGarrett D'Amore case '0': 4016b5e5868SGarrett D'Amore case '1': 4026b5e5868SGarrett D'Amore case '2': 4036b5e5868SGarrett D'Amore case '3': 4046b5e5868SGarrett D'Amore case '4': 4056b5e5868SGarrett D'Amore case '5': 4066b5e5868SGarrett D'Amore case '6': 4076b5e5868SGarrett D'Amore case '7': 4086b5e5868SGarrett D'Amore /* put the character back so we can get it */ 4096b5e5868SGarrett D'Amore unscanc(c); 4106b5e5868SGarrett D'Amore return (scan_oct_byte()); 4116b5e5868SGarrett D'Amore default: 4126b5e5868SGarrett D'Amore unscanc(c); 4136b5e5868SGarrett D'Amore unscanc(esc_char); 4146b5e5868SGarrett D'Amore return (EOF); 4156b5e5868SGarrett D'Amore } 4166b5e5868SGarrett D'Amore } 4176b5e5868SGarrett D'Amore 4186b5e5868SGarrett D'Amore int 4196b5e5868SGarrett D'Amore get_escaped(int c) 4206b5e5868SGarrett D'Amore { 4216b5e5868SGarrett D'Amore switch (c) { 4226b5e5868SGarrett D'Amore case 'n': 4236b5e5868SGarrett D'Amore return ('\n'); 4246b5e5868SGarrett D'Amore case 'r': 4256b5e5868SGarrett D'Amore return ('\r'); 4266b5e5868SGarrett D'Amore case 't': 4276b5e5868SGarrett D'Amore return ('\t'); 4286b5e5868SGarrett D'Amore case 'f': 4296b5e5868SGarrett D'Amore return ('\f'); 4306b5e5868SGarrett D'Amore case 'v': 4316b5e5868SGarrett D'Amore return ('\v'); 4326b5e5868SGarrett D'Amore case 'b': 4336b5e5868SGarrett D'Amore return ('\b'); 4346b5e5868SGarrett D'Amore case 'a': 4356b5e5868SGarrett D'Amore return ('\a'); 4366b5e5868SGarrett D'Amore default: 4376b5e5868SGarrett D'Amore return (c); 4386b5e5868SGarrett D'Amore } 4396b5e5868SGarrett D'Amore } 4406b5e5868SGarrett D'Amore 4416b5e5868SGarrett D'Amore int 4426b5e5868SGarrett D'Amore get_wide(void) 4436b5e5868SGarrett D'Amore { 4446b5e5868SGarrett D'Amore static char mbs[MB_LEN_MAX + 1] = ""; 4456b5e5868SGarrett D'Amore static int mbi = 0; 4466b5e5868SGarrett D'Amore int c; 4476b5e5868SGarrett D'Amore wchar_t wc; 4486b5e5868SGarrett D'Amore 4496b5e5868SGarrett D'Amore if (mb_cur_max >= sizeof (mbs)) { 4506b5e5868SGarrett D'Amore yyerror(_("max multibyte character size too big")); 4516b5e5868SGarrett D'Amore mbi = 0; 4526b5e5868SGarrett D'Amore return (T_NULL); 4536b5e5868SGarrett D'Amore } 4546b5e5868SGarrett D'Amore for (;;) { 4556b5e5868SGarrett D'Amore if ((mbi == mb_cur_max) || ((c = get_byte()) == EOF)) { 4566b5e5868SGarrett D'Amore /* 4576b5e5868SGarrett D'Amore * end of the byte sequence reached, but no 4586b5e5868SGarrett D'Amore * valid wide decoding. fatal error. 4596b5e5868SGarrett D'Amore */ 4606b5e5868SGarrett D'Amore mbi = 0; 4616b5e5868SGarrett D'Amore yyerror(_("not a valid character encoding")); 4626b5e5868SGarrett D'Amore return (T_NULL); 4636b5e5868SGarrett D'Amore } 4646b5e5868SGarrett D'Amore mbs[mbi++] = c; 4656b5e5868SGarrett D'Amore mbs[mbi] = 0; 4666b5e5868SGarrett D'Amore 4676b5e5868SGarrett D'Amore /* does it decode? */ 4686b5e5868SGarrett D'Amore if (to_wide(&wc, mbs) >= 0) { 4696b5e5868SGarrett D'Amore break; 4706b5e5868SGarrett D'Amore } 4716b5e5868SGarrett D'Amore } 4726b5e5868SGarrett D'Amore 4736b5e5868SGarrett D'Amore mbi = 0; 474*2da1cd3aSGarrett D'Amore if ((category != T_CHARMAP) && (category != T_WIDTH)) { 4756b5e5868SGarrett D'Amore if (check_charmap(wc) < 0) { 4766b5e5868SGarrett D'Amore yyerror(_("no symbolic name for character")); 4776b5e5868SGarrett D'Amore return (T_NULL); 4786b5e5868SGarrett D'Amore } 4796b5e5868SGarrett D'Amore } 4806b5e5868SGarrett D'Amore 4816b5e5868SGarrett D'Amore yylval.wc = wc; 4826b5e5868SGarrett D'Amore return (T_CHAR); 4836b5e5868SGarrett D'Amore } 4846b5e5868SGarrett D'Amore 4856b5e5868SGarrett D'Amore int 4866b5e5868SGarrett D'Amore get_symbol(void) 4876b5e5868SGarrett D'Amore { 4886b5e5868SGarrett D'Amore int c; 4896b5e5868SGarrett D'Amore 4906b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) { 4916b5e5868SGarrett D'Amore if (escaped) { 4926b5e5868SGarrett D'Amore escaped = 0; 4936b5e5868SGarrett D'Amore if (c == '\n') 4946b5e5868SGarrett D'Amore continue; 4956b5e5868SGarrett D'Amore add_tok(get_escaped(c)); 4966b5e5868SGarrett D'Amore continue; 4976b5e5868SGarrett D'Amore } 4986b5e5868SGarrett D'Amore if (c == esc_char) { 4996b5e5868SGarrett D'Amore escaped = 1; 5006b5e5868SGarrett D'Amore continue; 5016b5e5868SGarrett D'Amore } 5026b5e5868SGarrett D'Amore if (c == '\n') { /* well that's strange! */ 5036b5e5868SGarrett D'Amore yyerror(_("unterminated symbolic name")); 5046b5e5868SGarrett D'Amore continue; 5056b5e5868SGarrett D'Amore } 5066b5e5868SGarrett D'Amore if (c == '>') { /* end of symbol */ 5076b5e5868SGarrett D'Amore 5086b5e5868SGarrett D'Amore /* 5096b5e5868SGarrett D'Amore * This restarts the token from the beginning 5106b5e5868SGarrett D'Amore * the next time we scan a character. (This 5116b5e5868SGarrett D'Amore * token is complete.) 5126b5e5868SGarrett D'Amore */ 5136b5e5868SGarrett D'Amore 5146b5e5868SGarrett D'Amore if (token == NULL) { 5156b5e5868SGarrett D'Amore yyerror(_("missing symbolic name")); 5166b5e5868SGarrett D'Amore return (T_NULL); 5176b5e5868SGarrett D'Amore } 5186b5e5868SGarrett D'Amore tokidx = 0; 5196b5e5868SGarrett D'Amore 5206b5e5868SGarrett D'Amore /* 5216b5e5868SGarrett D'Amore * A few symbols are handled as keywords outside 5226b5e5868SGarrett D'Amore * of the normal categories. 5236b5e5868SGarrett D'Amore */ 5246b5e5868SGarrett D'Amore if (category == T_END) { 5256b5e5868SGarrett D'Amore int i; 5266b5e5868SGarrett D'Amore for (i = 0; symwords[i].name != 0; i++) { 5276b5e5868SGarrett D'Amore if (strcmp(token, symwords[i].name) == 5286b5e5868SGarrett D'Amore 0) { 5296b5e5868SGarrett D'Amore last_kw = symwords[i].id; 5306b5e5868SGarrett D'Amore return (last_kw); 5316b5e5868SGarrett D'Amore } 5326b5e5868SGarrett D'Amore } 5336b5e5868SGarrett D'Amore } 5346b5e5868SGarrett D'Amore /* 5356b5e5868SGarrett D'Amore * Contextual rule: Only literal characters are 5366b5e5868SGarrett D'Amore * permitted in CHARMAP. Anywhere else the symbolic 5376b5e5868SGarrett D'Amore * forms are fine. 5386b5e5868SGarrett D'Amore */ 5396b5e5868SGarrett D'Amore if ((category != T_CHARMAP) && 5406b5e5868SGarrett D'Amore (lookup_charmap(token, &yylval.wc)) != -1) { 5416b5e5868SGarrett D'Amore return (T_CHAR); 5426b5e5868SGarrett D'Amore } 5436b5e5868SGarrett D'Amore if ((yylval.collsym = lookup_collsym(token)) != NULL) { 5446b5e5868SGarrett D'Amore return (T_COLLSYM); 5456b5e5868SGarrett D'Amore } 5466b5e5868SGarrett D'Amore if ((yylval.collelem = lookup_collelem(token)) != 5476b5e5868SGarrett D'Amore NULL) { 5486b5e5868SGarrett D'Amore return (T_COLLELEM); 5496b5e5868SGarrett D'Amore } 5506b5e5868SGarrett D'Amore /* its an undefined symbol */ 5516b5e5868SGarrett D'Amore yylval.token = strdup(token); 5526b5e5868SGarrett D'Amore token = NULL; 5536b5e5868SGarrett D'Amore toksz = 0; 5546b5e5868SGarrett D'Amore tokidx = 0; 5556b5e5868SGarrett D'Amore return (T_SYMBOL); 5566b5e5868SGarrett D'Amore } 5576b5e5868SGarrett D'Amore add_tok(c); 5586b5e5868SGarrett D'Amore } 5596b5e5868SGarrett D'Amore 5606b5e5868SGarrett D'Amore yyerror(_("unterminated symbolic name")); 5616b5e5868SGarrett D'Amore return (EOF); 5626b5e5868SGarrett D'Amore } 5636b5e5868SGarrett D'Amore 5646b5e5868SGarrett D'Amore int 5656b5e5868SGarrett D'Amore get_category(void) 5666b5e5868SGarrett D'Amore { 5676b5e5868SGarrett D'Amore return (category); 5686b5e5868SGarrett D'Amore } 5696b5e5868SGarrett D'Amore 5706b5e5868SGarrett D'Amore static int 5716b5e5868SGarrett D'Amore consume_token(void) 5726b5e5868SGarrett D'Amore { 5736b5e5868SGarrett D'Amore int len = tokidx; 5746b5e5868SGarrett D'Amore int i; 5756b5e5868SGarrett D'Amore 5766b5e5868SGarrett D'Amore tokidx = 0; 5776b5e5868SGarrett D'Amore if (token == NULL) 5786b5e5868SGarrett D'Amore return (T_NULL); 5796b5e5868SGarrett D'Amore 5806b5e5868SGarrett D'Amore /* 5816b5e5868SGarrett D'Amore * this one is special, because we don't want it to alter the 5826b5e5868SGarrett D'Amore * last_kw field. 5836b5e5868SGarrett D'Amore */ 5846b5e5868SGarrett D'Amore if (strcmp(token, "...") == 0) { 5856b5e5868SGarrett D'Amore return (T_ELLIPSIS); 5866b5e5868SGarrett D'Amore } 5876b5e5868SGarrett D'Amore 5886b5e5868SGarrett D'Amore /* search for reserved words first */ 5896b5e5868SGarrett D'Amore for (i = 0; keywords[i].name; i++) { 5906b5e5868SGarrett D'Amore int j; 5916b5e5868SGarrett D'Amore if (strcmp(keywords[i].name, token) != 0) { 5926b5e5868SGarrett D'Amore continue; 5936b5e5868SGarrett D'Amore } 5946b5e5868SGarrett D'Amore 5956b5e5868SGarrett D'Amore last_kw = keywords[i].id; 5966b5e5868SGarrett D'Amore 5976b5e5868SGarrett D'Amore /* clear the top level category if we're done with it */ 5986b5e5868SGarrett D'Amore if (last_kw == T_END) { 5996b5e5868SGarrett D'Amore category = T_END; 6006b5e5868SGarrett D'Amore } 6016b5e5868SGarrett D'Amore 6026b5e5868SGarrett D'Amore /* set the top level category if we're changing */ 6036b5e5868SGarrett D'Amore for (j = 0; categories[j]; j++) { 6046b5e5868SGarrett D'Amore if (categories[j] != last_kw) 6056b5e5868SGarrett D'Amore continue; 6066b5e5868SGarrett D'Amore category = last_kw; 6076b5e5868SGarrett D'Amore } 6086b5e5868SGarrett D'Amore 6096b5e5868SGarrett D'Amore return (keywords[i].id); 6106b5e5868SGarrett D'Amore } 6116b5e5868SGarrett D'Amore 6126b5e5868SGarrett D'Amore /* maybe its a numeric constant? */ 6136b5e5868SGarrett D'Amore if (isdigit(*token) || (*token == '-' && isdigit(token[1]))) { 6146b5e5868SGarrett D'Amore char *eptr; 6156b5e5868SGarrett D'Amore yylval.num = strtol(token, &eptr, 10); 6166b5e5868SGarrett D'Amore if (*eptr != 0) 6176b5e5868SGarrett D'Amore yyerror(_("malformed number")); 6186b5e5868SGarrett D'Amore return (T_NUMBER); 6196b5e5868SGarrett D'Amore } 6206b5e5868SGarrett D'Amore 6216b5e5868SGarrett D'Amore /* 6226b5e5868SGarrett D'Amore * A single lone character is treated as a character literal. 6236b5e5868SGarrett D'Amore * To avoid duplication of effort, we stick in the charmap. 6246b5e5868SGarrett D'Amore */ 6256b5e5868SGarrett D'Amore if (len == 1) { 6266b5e5868SGarrett D'Amore yylval.wc = token[0]; 6276b5e5868SGarrett D'Amore return (T_CHAR); 6286b5e5868SGarrett D'Amore } 6296b5e5868SGarrett D'Amore 6306b5e5868SGarrett D'Amore /* anything else is treated as a symbolic name */ 6316b5e5868SGarrett D'Amore yylval.token = strdup(token); 6326b5e5868SGarrett D'Amore token = NULL; 6336b5e5868SGarrett D'Amore toksz = 0; 6346b5e5868SGarrett D'Amore tokidx = 0; 6356b5e5868SGarrett D'Amore return (T_NAME); 6366b5e5868SGarrett D'Amore } 6376b5e5868SGarrett D'Amore 6386b5e5868SGarrett D'Amore void 6396b5e5868SGarrett D'Amore scan_to_eol(void) 6406b5e5868SGarrett D'Amore { 6416b5e5868SGarrett D'Amore int c; 6426b5e5868SGarrett D'Amore while ((c = scanc()) != '\n') { 6436b5e5868SGarrett D'Amore if (c == EOF) { 6446b5e5868SGarrett D'Amore /* end of file without newline! */ 6456b5e5868SGarrett D'Amore errf(_("missing newline")); 6466b5e5868SGarrett D'Amore return; 6476b5e5868SGarrett D'Amore } 6486b5e5868SGarrett D'Amore } 6496b5e5868SGarrett D'Amore assert(c == '\n'); 6506b5e5868SGarrett D'Amore } 6516b5e5868SGarrett D'Amore 6526b5e5868SGarrett D'Amore int 6536b5e5868SGarrett D'Amore yylex(void) 6546b5e5868SGarrett D'Amore { 6556b5e5868SGarrett D'Amore int c; 6566b5e5868SGarrett D'Amore 6576b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) { 6586b5e5868SGarrett D'Amore 6596b5e5868SGarrett D'Amore /* special handling for quoted string */ 6606b5e5868SGarrett D'Amore if (instring) { 6616b5e5868SGarrett D'Amore if (escaped) { 6626b5e5868SGarrett D'Amore escaped = 0; 6636b5e5868SGarrett D'Amore 6646b5e5868SGarrett D'Amore /* if newline, just eat and forget it */ 6656b5e5868SGarrett D'Amore if (c == '\n') 6666b5e5868SGarrett D'Amore continue; 6676b5e5868SGarrett D'Amore 6686b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) { 6696b5e5868SGarrett D'Amore unscanc(c); 6706b5e5868SGarrett D'Amore unscanc(esc_char); 6716b5e5868SGarrett D'Amore return (get_wide()); 6726b5e5868SGarrett D'Amore } 6736b5e5868SGarrett D'Amore yylval.wc = get_escaped(c); 6746b5e5868SGarrett D'Amore return (T_CHAR); 6756b5e5868SGarrett D'Amore } 6766b5e5868SGarrett D'Amore if (c == esc_char) { 6776b5e5868SGarrett D'Amore escaped = 1; 6786b5e5868SGarrett D'Amore continue; 6796b5e5868SGarrett D'Amore } 6806b5e5868SGarrett D'Amore switch (c) { 6816b5e5868SGarrett D'Amore case '<': 6826b5e5868SGarrett D'Amore return (get_symbol()); 6836b5e5868SGarrett D'Amore case '>': 6846b5e5868SGarrett D'Amore /* oops! should generate syntax error */ 6856b5e5868SGarrett D'Amore return (T_GT); 6866b5e5868SGarrett D'Amore case '"': 6876b5e5868SGarrett D'Amore instring = 0; 6886b5e5868SGarrett D'Amore return (T_QUOTE); 6896b5e5868SGarrett D'Amore default: 6906b5e5868SGarrett D'Amore yylval.wc = c; 6916b5e5868SGarrett D'Amore return (T_CHAR); 6926b5e5868SGarrett D'Amore } 6936b5e5868SGarrett D'Amore } 6946b5e5868SGarrett D'Amore 6956b5e5868SGarrett D'Amore /* escaped characters first */ 6966b5e5868SGarrett D'Amore if (escaped) { 6976b5e5868SGarrett D'Amore escaped = 0; 6986b5e5868SGarrett D'Amore if (c == '\n') { 6996b5e5868SGarrett D'Amore /* eat the newline */ 7006b5e5868SGarrett D'Amore continue; 7016b5e5868SGarrett D'Amore } 7026b5e5868SGarrett D'Amore hadtok = 1; 7036b5e5868SGarrett D'Amore if (tokidx) { 7046b5e5868SGarrett D'Amore /* an escape mid-token is nonsense */ 7056b5e5868SGarrett D'Amore return (T_NULL); 7066b5e5868SGarrett D'Amore } 7076b5e5868SGarrett D'Amore 7086b5e5868SGarrett D'Amore /* numeric escapes are treated as wide characters */ 7096b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) { 7106b5e5868SGarrett D'Amore unscanc(c); 7116b5e5868SGarrett D'Amore unscanc(esc_char); 7126b5e5868SGarrett D'Amore return (get_wide()); 7136b5e5868SGarrett D'Amore } 7146b5e5868SGarrett D'Amore 7156b5e5868SGarrett D'Amore add_tok(get_escaped(c)); 7166b5e5868SGarrett D'Amore continue; 7176b5e5868SGarrett D'Amore } 7186b5e5868SGarrett D'Amore 7196b5e5868SGarrett D'Amore /* if it is the escape charter itself note it */ 7206b5e5868SGarrett D'Amore if (c == esc_char) { 7216b5e5868SGarrett D'Amore escaped = 1; 7226b5e5868SGarrett D'Amore continue; 7236b5e5868SGarrett D'Amore } 7246b5e5868SGarrett D'Amore 7256b5e5868SGarrett D'Amore /* remove from the comment char to end of line */ 7266b5e5868SGarrett D'Amore if (c == com_char) { 7276b5e5868SGarrett D'Amore while (c != '\n') { 7286b5e5868SGarrett D'Amore if ((c = scanc()) == EOF) { 7296b5e5868SGarrett D'Amore /* end of file without newline! */ 7306b5e5868SGarrett D'Amore return (EOF); 7316b5e5868SGarrett D'Amore } 7326b5e5868SGarrett D'Amore } 7336b5e5868SGarrett D'Amore assert(c == '\n'); 7346b5e5868SGarrett D'Amore if (!hadtok) { 7356b5e5868SGarrett D'Amore /* 7366b5e5868SGarrett D'Amore * If there were no tokens on this line, 7376b5e5868SGarrett D'Amore * then just pretend it didn't exist at all. 7386b5e5868SGarrett D'Amore */ 7396b5e5868SGarrett D'Amore continue; 7406b5e5868SGarrett D'Amore } 7416b5e5868SGarrett D'Amore hadtok = 0; 7426b5e5868SGarrett D'Amore return (T_NL); 7436b5e5868SGarrett D'Amore } 7446b5e5868SGarrett D'Amore 7456b5e5868SGarrett D'Amore if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) { 7466b5e5868SGarrett D'Amore /* 7476b5e5868SGarrett D'Amore * These are all token delimiters. If there 7486b5e5868SGarrett D'Amore * is a token already in progress, we need to 7496b5e5868SGarrett D'Amore * process it. 7506b5e5868SGarrett D'Amore */ 7516b5e5868SGarrett D'Amore unscanc(c); 7526b5e5868SGarrett D'Amore return (consume_token()); 7536b5e5868SGarrett D'Amore } 7546b5e5868SGarrett D'Amore 7556b5e5868SGarrett D'Amore switch (c) { 7566b5e5868SGarrett D'Amore case '\n': 7576b5e5868SGarrett D'Amore if (!hadtok) { 7586b5e5868SGarrett D'Amore /* 7596b5e5868SGarrett D'Amore * If the line was completely devoid of tokens, 7606b5e5868SGarrett D'Amore * then just ignore it. 7616b5e5868SGarrett D'Amore */ 7626b5e5868SGarrett D'Amore continue; 7636b5e5868SGarrett D'Amore } 7646b5e5868SGarrett D'Amore /* we're starting a new line, reset the token state */ 7656b5e5868SGarrett D'Amore hadtok = 0; 7666b5e5868SGarrett D'Amore return (T_NL); 7676b5e5868SGarrett D'Amore case ',': 7686b5e5868SGarrett D'Amore hadtok = 1; 7696b5e5868SGarrett D'Amore return (T_COMMA); 7706b5e5868SGarrett D'Amore case ';': 7716b5e5868SGarrett D'Amore hadtok = 1; 7726b5e5868SGarrett D'Amore return (T_SEMI); 7736b5e5868SGarrett D'Amore case '(': 7746b5e5868SGarrett D'Amore hadtok = 1; 7756b5e5868SGarrett D'Amore return (T_LPAREN); 7766b5e5868SGarrett D'Amore case ')': 7776b5e5868SGarrett D'Amore hadtok = 1; 7786b5e5868SGarrett D'Amore return (T_RPAREN); 7796b5e5868SGarrett D'Amore case '>': 7806b5e5868SGarrett D'Amore hadtok = 1; 7816b5e5868SGarrett D'Amore return (T_GT); 7826b5e5868SGarrett D'Amore case '<': 7836b5e5868SGarrett D'Amore /* symbol start! */ 7846b5e5868SGarrett D'Amore hadtok = 1; 7856b5e5868SGarrett D'Amore return (get_symbol()); 7866b5e5868SGarrett D'Amore case ' ': 7876b5e5868SGarrett D'Amore case '\t': 7886b5e5868SGarrett D'Amore /* whitespace, just ignore it */ 7896b5e5868SGarrett D'Amore continue; 7906b5e5868SGarrett D'Amore case '"': 7916b5e5868SGarrett D'Amore hadtok = 1; 7926b5e5868SGarrett D'Amore instring = 1; 7936b5e5868SGarrett D'Amore return (T_QUOTE); 7946b5e5868SGarrett D'Amore default: 7956b5e5868SGarrett D'Amore hadtok = 1; 7966b5e5868SGarrett D'Amore add_tok(c); 7976b5e5868SGarrett D'Amore continue; 7986b5e5868SGarrett D'Amore } 7996b5e5868SGarrett D'Amore } 8006b5e5868SGarrett D'Amore return (EOF); 8016b5e5868SGarrett D'Amore } 8026b5e5868SGarrett D'Amore 8036b5e5868SGarrett D'Amore void 8046b5e5868SGarrett D'Amore yyerror(const char *msg) 8056b5e5868SGarrett D'Amore { 8066b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"), 8076b5e5868SGarrett D'Amore filename, lineno, msg); 8086b5e5868SGarrett D'Amore exit(4); 8096b5e5868SGarrett D'Amore } 8106b5e5868SGarrett D'Amore 8116b5e5868SGarrett D'Amore void 8126b5e5868SGarrett D'Amore errf(const char *fmt, ...) 8136b5e5868SGarrett D'Amore { 8146b5e5868SGarrett D'Amore char *msg; 8156b5e5868SGarrett D'Amore 8166b5e5868SGarrett D'Amore va_list va; 8176b5e5868SGarrett D'Amore va_start(va, fmt); 8186b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va); 8196b5e5868SGarrett D'Amore va_end(va); 8206b5e5868SGarrett D'Amore 8216b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"), 8226b5e5868SGarrett D'Amore filename, lineno, msg); 8236b5e5868SGarrett D'Amore free(msg); 8246b5e5868SGarrett D'Amore exit(4); 8256b5e5868SGarrett D'Amore } 8266b5e5868SGarrett D'Amore 8276b5e5868SGarrett D'Amore void 8286b5e5868SGarrett D'Amore warn(const char *fmt, ...) 8296b5e5868SGarrett D'Amore { 8306b5e5868SGarrett D'Amore char *msg; 8316b5e5868SGarrett D'Amore 8326b5e5868SGarrett D'Amore va_list va; 8336b5e5868SGarrett D'Amore va_start(va, fmt); 8346b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va); 8356b5e5868SGarrett D'Amore va_end(va); 8366b5e5868SGarrett D'Amore 8376b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: warning: %s\n"), 8386b5e5868SGarrett D'Amore filename, lineno, msg); 8396b5e5868SGarrett D'Amore free(msg); 8406b5e5868SGarrett D'Amore warnings++; 8416b5e5868SGarrett D'Amore if (!warnok) 8426b5e5868SGarrett D'Amore exit(4); 8436b5e5868SGarrett D'Amore } 844