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
reset_scanner(const char * fname)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
scanc(void)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
unscanc(int c)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
scan_hex_byte(void)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
scan_dec_byte(void)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
scan_oct_byte(void)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
add_tok(int c)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
add_wcs(wchar_t c)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 *
get_wcs(void)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
get_byte(void)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
get_escaped(int c)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
get_wide(void)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
get_symbol(void)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
get_category(void)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
consume_token(void)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
scan_to_eol(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
yylex(void)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
yyerror(const char * msg)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
errf(const char * fmt,...)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
warn(const char * fmt,...)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