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.
142da1cd3aSGarrett 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
1667262c8a6SYuri Pankov * Solaris originally 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,
1962da1cd3aSGarrett 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) {
249*1a90c98dSToomas Soome (void) 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)) {
261*1a90c98dSToomas Soome (void) yyerror(_("malformed hex digit"));
2626b5e5868SGarrett D'Amore }
2636b5e5868SGarrett D'Amore c2 = scanc();
2646b5e5868SGarrett D'Amore if (!isxdigit(c2)) {
265*1a90c98dSToomas Soome (void) yyerror(_("malformed hex digit"));
2666b5e5868SGarrett D'Amore }
2676b5e5868SGarrett D'Amore v = ((hex(c1) << 4) | hex(c2));
2686b5e5868SGarrett D'Amore return (v);
2696b5e5868SGarrett D'Amore }
2706b5e5868SGarrett D'Amore
2716b5e5868SGarrett D'Amore static int
scan_dec_byte(void)2726b5e5868SGarrett D'Amore scan_dec_byte(void)
2736b5e5868SGarrett D'Amore {
2746b5e5868SGarrett D'Amore int c1, c2, c3;
2756b5e5868SGarrett D'Amore int b;
2766b5e5868SGarrett D'Amore
2776b5e5868SGarrett D'Amore c1 = scanc();
2786b5e5868SGarrett D'Amore if (!isdigit(c1)) {
279*1a90c98dSToomas Soome (void) yyerror(_("malformed decimal digit"));
2806b5e5868SGarrett D'Amore }
2816b5e5868SGarrett D'Amore b = c1 - '0';
2826b5e5868SGarrett D'Amore c2 = scanc();
2836b5e5868SGarrett D'Amore if (!isdigit(c2)) {
284*1a90c98dSToomas Soome (void) yyerror(_("malformed decimal digit"));
2856b5e5868SGarrett D'Amore }
2866b5e5868SGarrett D'Amore b *= 10;
2876b5e5868SGarrett D'Amore b += (c2 - '0');
2886b5e5868SGarrett D'Amore c3 = scanc();
2896b5e5868SGarrett D'Amore if (!isdigit(c3)) {
2906b5e5868SGarrett D'Amore unscanc(c3);
2916b5e5868SGarrett D'Amore } else {
2926b5e5868SGarrett D'Amore b *= 10;
2936b5e5868SGarrett D'Amore b += (c3 - '0');
2946b5e5868SGarrett D'Amore }
2956b5e5868SGarrett D'Amore return (b);
2966b5e5868SGarrett D'Amore }
2976b5e5868SGarrett D'Amore
2986b5e5868SGarrett D'Amore static int
scan_oct_byte(void)2996b5e5868SGarrett D'Amore scan_oct_byte(void)
3006b5e5868SGarrett D'Amore {
3016b5e5868SGarrett D'Amore int c1, c2, c3;
3026b5e5868SGarrett D'Amore int b;
3036b5e5868SGarrett D'Amore
3046b5e5868SGarrett D'Amore b = 0;
3056b5e5868SGarrett D'Amore
3066b5e5868SGarrett D'Amore c1 = scanc();
3076b5e5868SGarrett D'Amore if (!isodigit(c1)) {
308*1a90c98dSToomas Soome (void) yyerror(_("malformed octal digit"));
3096b5e5868SGarrett D'Amore }
3106b5e5868SGarrett D'Amore b = c1 - '0';
3116b5e5868SGarrett D'Amore c2 = scanc();
3126b5e5868SGarrett D'Amore if (!isodigit(c2)) {
313*1a90c98dSToomas Soome (void) yyerror(_("malformed octal digit"));
3146b5e5868SGarrett D'Amore }
3156b5e5868SGarrett D'Amore b *= 8;
3166b5e5868SGarrett D'Amore b += (c2 - '0');
3176b5e5868SGarrett D'Amore c3 = scanc();
3186b5e5868SGarrett D'Amore if (!isodigit(c3)) {
3196b5e5868SGarrett D'Amore unscanc(c3);
3206b5e5868SGarrett D'Amore } else {
3216b5e5868SGarrett D'Amore b *= 8;
3226b5e5868SGarrett D'Amore b += (c3 - '0');
3236b5e5868SGarrett D'Amore }
3246b5e5868SGarrett D'Amore return (b);
3256b5e5868SGarrett D'Amore }
3266b5e5868SGarrett D'Amore
3276b5e5868SGarrett D'Amore void
add_tok(int c)3286b5e5868SGarrett D'Amore add_tok(int c)
3296b5e5868SGarrett D'Amore {
3306b5e5868SGarrett D'Amore if ((tokidx + 1) >= toksz) {
3316b5e5868SGarrett D'Amore toksz += 64;
3326b5e5868SGarrett D'Amore if ((token = realloc(token, toksz)) == NULL) {
333*1a90c98dSToomas Soome (void) yyerror(_("out of memory"));
3346b5e5868SGarrett D'Amore }
3356b5e5868SGarrett D'Amore }
3366b5e5868SGarrett D'Amore
3376b5e5868SGarrett D'Amore token[tokidx++] = (char)c;
3386b5e5868SGarrett D'Amore token[tokidx] = 0;
3396b5e5868SGarrett D'Amore }
3406b5e5868SGarrett D'Amore void
add_wcs(wchar_t c)3416b5e5868SGarrett D'Amore add_wcs(wchar_t c)
3426b5e5868SGarrett D'Amore {
3436b5e5868SGarrett D'Amore if ((wideidx + 1) >= widesz) {
3446b5e5868SGarrett D'Amore widesz += 64;
3456b5e5868SGarrett D'Amore widestr = realloc(widestr, (widesz * sizeof (wchar_t)));
3466b5e5868SGarrett D'Amore if (widestr == NULL) {
347*1a90c98dSToomas Soome (void) yyerror(_("out of memory"));
3486b5e5868SGarrett D'Amore }
3496b5e5868SGarrett D'Amore }
3506b5e5868SGarrett D'Amore
3516b5e5868SGarrett D'Amore widestr[wideidx++] = c;
3526b5e5868SGarrett D'Amore widestr[wideidx] = 0;
3536b5e5868SGarrett D'Amore }
3546b5e5868SGarrett D'Amore
3556b5e5868SGarrett D'Amore wchar_t *
get_wcs(void)3566b5e5868SGarrett D'Amore get_wcs(void)
3576b5e5868SGarrett D'Amore {
3586b5e5868SGarrett D'Amore wchar_t *ws = widestr;
3596b5e5868SGarrett D'Amore wideidx = 0;
3606b5e5868SGarrett D'Amore widestr = NULL;
3616b5e5868SGarrett D'Amore widesz = 0;
3626b5e5868SGarrett D'Amore if (ws == NULL) {
3636b5e5868SGarrett D'Amore if ((ws = wsdup(L"")) == NULL) {
364*1a90c98dSToomas Soome (void) yyerror(_("out of memory"));
3656b5e5868SGarrett D'Amore }
3666b5e5868SGarrett D'Amore }
3676b5e5868SGarrett D'Amore return (ws);
3686b5e5868SGarrett D'Amore }
3696b5e5868SGarrett D'Amore
3706b5e5868SGarrett D'Amore static int
get_byte(void)3716b5e5868SGarrett D'Amore get_byte(void)
3726b5e5868SGarrett D'Amore {
3736b5e5868SGarrett D'Amore int c;
3746b5e5868SGarrett D'Amore
3756b5e5868SGarrett D'Amore if ((c = scanc()) != esc_char) {
3766b5e5868SGarrett D'Amore unscanc(c);
3776b5e5868SGarrett D'Amore return (EOF);
3786b5e5868SGarrett D'Amore }
3796b5e5868SGarrett D'Amore c = scanc();
3806b5e5868SGarrett D'Amore
3816b5e5868SGarrett D'Amore switch (c) {
3826b5e5868SGarrett D'Amore case 'd':
3836b5e5868SGarrett D'Amore case 'D':
3846b5e5868SGarrett D'Amore return (scan_dec_byte());
3856b5e5868SGarrett D'Amore case 'x':
3866b5e5868SGarrett D'Amore case 'X':
3876b5e5868SGarrett D'Amore return (scan_hex_byte());
3886b5e5868SGarrett D'Amore case '0':
3896b5e5868SGarrett D'Amore case '1':
3906b5e5868SGarrett D'Amore case '2':
3916b5e5868SGarrett D'Amore case '3':
3926b5e5868SGarrett D'Amore case '4':
3936b5e5868SGarrett D'Amore case '5':
3946b5e5868SGarrett D'Amore case '6':
3956b5e5868SGarrett D'Amore case '7':
3966b5e5868SGarrett D'Amore /* put the character back so we can get it */
3976b5e5868SGarrett D'Amore unscanc(c);
3986b5e5868SGarrett D'Amore return (scan_oct_byte());
3996b5e5868SGarrett D'Amore default:
4006b5e5868SGarrett D'Amore unscanc(c);
4016b5e5868SGarrett D'Amore unscanc(esc_char);
4026b5e5868SGarrett D'Amore return (EOF);
4036b5e5868SGarrett D'Amore }
4046b5e5868SGarrett D'Amore }
4056b5e5868SGarrett D'Amore
4066b5e5868SGarrett D'Amore int
get_escaped(int c)4076b5e5868SGarrett D'Amore get_escaped(int c)
4086b5e5868SGarrett D'Amore {
4096b5e5868SGarrett D'Amore switch (c) {
4106b5e5868SGarrett D'Amore case 'n':
4116b5e5868SGarrett D'Amore return ('\n');
4126b5e5868SGarrett D'Amore case 'r':
4136b5e5868SGarrett D'Amore return ('\r');
4146b5e5868SGarrett D'Amore case 't':
4156b5e5868SGarrett D'Amore return ('\t');
4166b5e5868SGarrett D'Amore case 'f':
4176b5e5868SGarrett D'Amore return ('\f');
4186b5e5868SGarrett D'Amore case 'v':
4196b5e5868SGarrett D'Amore return ('\v');
4206b5e5868SGarrett D'Amore case 'b':
4216b5e5868SGarrett D'Amore return ('\b');
4226b5e5868SGarrett D'Amore case 'a':
4236b5e5868SGarrett D'Amore return ('\a');
4246b5e5868SGarrett D'Amore default:
4256b5e5868SGarrett D'Amore return (c);
4266b5e5868SGarrett D'Amore }
4276b5e5868SGarrett D'Amore }
4286b5e5868SGarrett D'Amore
4296b5e5868SGarrett D'Amore int
get_wide(void)4306b5e5868SGarrett D'Amore get_wide(void)
4316b5e5868SGarrett D'Amore {
4326b5e5868SGarrett D'Amore static char mbs[MB_LEN_MAX + 1] = "";
4336b5e5868SGarrett D'Amore static int mbi = 0;
4346b5e5868SGarrett D'Amore int c;
4356b5e5868SGarrett D'Amore wchar_t wc;
4366b5e5868SGarrett D'Amore
4376b5e5868SGarrett D'Amore if (mb_cur_max >= sizeof (mbs)) {
438*1a90c98dSToomas Soome (void) yyerror(_("max multibyte character size too big"));
4396b5e5868SGarrett D'Amore }
4406b5e5868SGarrett D'Amore for (;;) {
4416b5e5868SGarrett D'Amore if ((mbi == mb_cur_max) || ((c = get_byte()) == EOF)) {
4426b5e5868SGarrett D'Amore /*
4436b5e5868SGarrett D'Amore * end of the byte sequence reached, but no
4446b5e5868SGarrett D'Amore * valid wide decoding. fatal error.
4456b5e5868SGarrett D'Amore */
4466b5e5868SGarrett D'Amore mbi = 0;
447*1a90c98dSToomas Soome (void) yyerror(_("not a valid character encoding"));
4486b5e5868SGarrett D'Amore }
4496b5e5868SGarrett D'Amore mbs[mbi++] = c;
4506b5e5868SGarrett D'Amore mbs[mbi] = 0;
4516b5e5868SGarrett D'Amore
4526b5e5868SGarrett D'Amore /* does it decode? */
4536b5e5868SGarrett D'Amore if (to_wide(&wc, mbs) >= 0) {
4546b5e5868SGarrett D'Amore break;
4556b5e5868SGarrett D'Amore }
4566b5e5868SGarrett D'Amore }
4576b5e5868SGarrett D'Amore
4586b5e5868SGarrett D'Amore mbi = 0;
4592da1cd3aSGarrett D'Amore if ((category != T_CHARMAP) && (category != T_WIDTH)) {
4606b5e5868SGarrett D'Amore if (check_charmap(wc) < 0) {
461*1a90c98dSToomas Soome (void) yyerror(_("no symbolic name for character"));
4626b5e5868SGarrett D'Amore }
4636b5e5868SGarrett D'Amore }
4646b5e5868SGarrett D'Amore
4656b5e5868SGarrett D'Amore yylval.wc = wc;
4666b5e5868SGarrett D'Amore return (T_CHAR);
4676b5e5868SGarrett D'Amore }
4686b5e5868SGarrett D'Amore
4696b5e5868SGarrett D'Amore int
get_symbol(void)4706b5e5868SGarrett D'Amore get_symbol(void)
4716b5e5868SGarrett D'Amore {
4726b5e5868SGarrett D'Amore int c;
4736b5e5868SGarrett D'Amore
4746b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) {
4756b5e5868SGarrett D'Amore if (escaped) {
4766b5e5868SGarrett D'Amore escaped = 0;
4776b5e5868SGarrett D'Amore if (c == '\n')
4786b5e5868SGarrett D'Amore continue;
4796b5e5868SGarrett D'Amore add_tok(get_escaped(c));
4806b5e5868SGarrett D'Amore continue;
4816b5e5868SGarrett D'Amore }
4826b5e5868SGarrett D'Amore if (c == esc_char) {
4836b5e5868SGarrett D'Amore escaped = 1;
4846b5e5868SGarrett D'Amore continue;
4856b5e5868SGarrett D'Amore }
4866b5e5868SGarrett D'Amore if (c == '\n') { /* well that's strange! */
487*1a90c98dSToomas Soome (void) yyerror(_("unterminated symbolic name"));
4886b5e5868SGarrett D'Amore }
4896b5e5868SGarrett D'Amore if (c == '>') { /* end of symbol */
4906b5e5868SGarrett D'Amore
4916b5e5868SGarrett D'Amore /*
4926b5e5868SGarrett D'Amore * This restarts the token from the beginning
4936b5e5868SGarrett D'Amore * the next time we scan a character. (This
4946b5e5868SGarrett D'Amore * token is complete.)
4956b5e5868SGarrett D'Amore */
4966b5e5868SGarrett D'Amore
4976b5e5868SGarrett D'Amore if (token == NULL) {
498*1a90c98dSToomas Soome (void) yyerror(_("missing symbolic name"));
4996b5e5868SGarrett D'Amore }
5006b5e5868SGarrett D'Amore tokidx = 0;
5016b5e5868SGarrett D'Amore
5026b5e5868SGarrett D'Amore /*
5036b5e5868SGarrett D'Amore * A few symbols are handled as keywords outside
5046b5e5868SGarrett D'Amore * of the normal categories.
5056b5e5868SGarrett D'Amore */
5066b5e5868SGarrett D'Amore if (category == T_END) {
5076b5e5868SGarrett D'Amore int i;
5086b5e5868SGarrett D'Amore for (i = 0; symwords[i].name != 0; i++) {
5096b5e5868SGarrett D'Amore if (strcmp(token, symwords[i].name) ==
5106b5e5868SGarrett D'Amore 0) {
5116b5e5868SGarrett D'Amore last_kw = symwords[i].id;
5126b5e5868SGarrett D'Amore return (last_kw);
5136b5e5868SGarrett D'Amore }
5146b5e5868SGarrett D'Amore }
5156b5e5868SGarrett D'Amore }
5166b5e5868SGarrett D'Amore /*
5176b5e5868SGarrett D'Amore * Contextual rule: Only literal characters are
5186b5e5868SGarrett D'Amore * permitted in CHARMAP. Anywhere else the symbolic
5196b5e5868SGarrett D'Amore * forms are fine.
5206b5e5868SGarrett D'Amore */
5216b5e5868SGarrett D'Amore if ((category != T_CHARMAP) &&
5226b5e5868SGarrett D'Amore (lookup_charmap(token, &yylval.wc)) != -1) {
5236b5e5868SGarrett D'Amore return (T_CHAR);
5246b5e5868SGarrett D'Amore }
5256b5e5868SGarrett D'Amore if ((yylval.collsym = lookup_collsym(token)) != NULL) {
5266b5e5868SGarrett D'Amore return (T_COLLSYM);
5276b5e5868SGarrett D'Amore }
5286b5e5868SGarrett D'Amore if ((yylval.collelem = lookup_collelem(token)) !=
5296b5e5868SGarrett D'Amore NULL) {
5306b5e5868SGarrett D'Amore return (T_COLLELEM);
5316b5e5868SGarrett D'Amore }
5326b5e5868SGarrett D'Amore /* its an undefined symbol */
5336b5e5868SGarrett D'Amore yylval.token = strdup(token);
5346b5e5868SGarrett D'Amore token = NULL;
5356b5e5868SGarrett D'Amore toksz = 0;
5366b5e5868SGarrett D'Amore tokidx = 0;
5376b5e5868SGarrett D'Amore return (T_SYMBOL);
5386b5e5868SGarrett D'Amore }
5396b5e5868SGarrett D'Amore add_tok(c);
5406b5e5868SGarrett D'Amore }
5416b5e5868SGarrett D'Amore
542*1a90c98dSToomas Soome (void) yyerror(_("unterminated symbolic name"));
5436b5e5868SGarrett D'Amore return (EOF);
5446b5e5868SGarrett D'Amore }
5456b5e5868SGarrett D'Amore
5466b5e5868SGarrett D'Amore int
get_category(void)5476b5e5868SGarrett D'Amore get_category(void)
5486b5e5868SGarrett D'Amore {
5496b5e5868SGarrett D'Amore return (category);
5506b5e5868SGarrett D'Amore }
5516b5e5868SGarrett D'Amore
5526b5e5868SGarrett D'Amore static int
consume_token(void)5536b5e5868SGarrett D'Amore consume_token(void)
5546b5e5868SGarrett D'Amore {
5556b5e5868SGarrett D'Amore int len = tokidx;
5566b5e5868SGarrett D'Amore int i;
5576b5e5868SGarrett D'Amore
5586b5e5868SGarrett D'Amore tokidx = 0;
5596b5e5868SGarrett D'Amore if (token == NULL)
5606b5e5868SGarrett D'Amore return (T_NULL);
5616b5e5868SGarrett D'Amore
5626b5e5868SGarrett D'Amore /*
5636b5e5868SGarrett D'Amore * this one is special, because we don't want it to alter the
5646b5e5868SGarrett D'Amore * last_kw field.
5656b5e5868SGarrett D'Amore */
5666b5e5868SGarrett D'Amore if (strcmp(token, "...") == 0) {
5676b5e5868SGarrett D'Amore return (T_ELLIPSIS);
5686b5e5868SGarrett D'Amore }
5696b5e5868SGarrett D'Amore
5706b5e5868SGarrett D'Amore /* search for reserved words first */
5716b5e5868SGarrett D'Amore for (i = 0; keywords[i].name; i++) {
5726b5e5868SGarrett D'Amore int j;
5736b5e5868SGarrett D'Amore if (strcmp(keywords[i].name, token) != 0) {
5746b5e5868SGarrett D'Amore continue;
5756b5e5868SGarrett D'Amore }
5766b5e5868SGarrett D'Amore
5776b5e5868SGarrett D'Amore last_kw = keywords[i].id;
5786b5e5868SGarrett D'Amore
5796b5e5868SGarrett D'Amore /* clear the top level category if we're done with it */
5806b5e5868SGarrett D'Amore if (last_kw == T_END) {
5816b5e5868SGarrett D'Amore category = T_END;
5826b5e5868SGarrett D'Amore }
5836b5e5868SGarrett D'Amore
5846b5e5868SGarrett D'Amore /* set the top level category if we're changing */
5856b5e5868SGarrett D'Amore for (j = 0; categories[j]; j++) {
5866b5e5868SGarrett D'Amore if (categories[j] != last_kw)
5876b5e5868SGarrett D'Amore continue;
5886b5e5868SGarrett D'Amore category = last_kw;
5896b5e5868SGarrett D'Amore }
5906b5e5868SGarrett D'Amore
5916b5e5868SGarrett D'Amore return (keywords[i].id);
5926b5e5868SGarrett D'Amore }
5936b5e5868SGarrett D'Amore
5946b5e5868SGarrett D'Amore /* maybe its a numeric constant? */
5956b5e5868SGarrett D'Amore if (isdigit(*token) || (*token == '-' && isdigit(token[1]))) {
5966b5e5868SGarrett D'Amore char *eptr;
5976b5e5868SGarrett D'Amore yylval.num = strtol(token, &eptr, 10);
5986b5e5868SGarrett D'Amore if (*eptr != 0)
599*1a90c98dSToomas Soome (void) yyerror(_("malformed number"));
6006b5e5868SGarrett D'Amore return (T_NUMBER);
6016b5e5868SGarrett D'Amore }
6026b5e5868SGarrett D'Amore
6036b5e5868SGarrett D'Amore /*
6046b5e5868SGarrett D'Amore * A single lone character is treated as a character literal.
6056b5e5868SGarrett D'Amore * To avoid duplication of effort, we stick in the charmap.
6066b5e5868SGarrett D'Amore */
6076b5e5868SGarrett D'Amore if (len == 1) {
6086b5e5868SGarrett D'Amore yylval.wc = token[0];
6096b5e5868SGarrett D'Amore return (T_CHAR);
6106b5e5868SGarrett D'Amore }
6116b5e5868SGarrett D'Amore
6126b5e5868SGarrett D'Amore /* anything else is treated as a symbolic name */
6136b5e5868SGarrett D'Amore yylval.token = strdup(token);
6146b5e5868SGarrett D'Amore token = NULL;
6156b5e5868SGarrett D'Amore toksz = 0;
6166b5e5868SGarrett D'Amore tokidx = 0;
6176b5e5868SGarrett D'Amore return (T_NAME);
6186b5e5868SGarrett D'Amore }
6196b5e5868SGarrett D'Amore
6206b5e5868SGarrett D'Amore void
scan_to_eol(void)6216b5e5868SGarrett D'Amore scan_to_eol(void)
6226b5e5868SGarrett D'Amore {
6236b5e5868SGarrett D'Amore int c;
6246b5e5868SGarrett D'Amore while ((c = scanc()) != '\n') {
6256b5e5868SGarrett D'Amore if (c == EOF) {
6266b5e5868SGarrett D'Amore /* end of file without newline! */
6276b5e5868SGarrett D'Amore errf(_("missing newline"));
6286b5e5868SGarrett D'Amore return;
6296b5e5868SGarrett D'Amore }
6306b5e5868SGarrett D'Amore }
6316b5e5868SGarrett D'Amore assert(c == '\n');
6326b5e5868SGarrett D'Amore }
6336b5e5868SGarrett D'Amore
6346b5e5868SGarrett D'Amore int
yylex(void)6356b5e5868SGarrett D'Amore yylex(void)
6366b5e5868SGarrett D'Amore {
6376b5e5868SGarrett D'Amore int c;
6386b5e5868SGarrett D'Amore
6396b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) {
6406b5e5868SGarrett D'Amore
6416b5e5868SGarrett D'Amore /* special handling for quoted string */
6426b5e5868SGarrett D'Amore if (instring) {
6436b5e5868SGarrett D'Amore if (escaped) {
6446b5e5868SGarrett D'Amore escaped = 0;
6456b5e5868SGarrett D'Amore
6466b5e5868SGarrett D'Amore /* if newline, just eat and forget it */
6476b5e5868SGarrett D'Amore if (c == '\n')
6486b5e5868SGarrett D'Amore continue;
6496b5e5868SGarrett D'Amore
6506b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) {
6516b5e5868SGarrett D'Amore unscanc(c);
6526b5e5868SGarrett D'Amore unscanc(esc_char);
6536b5e5868SGarrett D'Amore return (get_wide());
6546b5e5868SGarrett D'Amore }
6556b5e5868SGarrett D'Amore yylval.wc = get_escaped(c);
6566b5e5868SGarrett D'Amore return (T_CHAR);
6576b5e5868SGarrett D'Amore }
6586b5e5868SGarrett D'Amore if (c == esc_char) {
6596b5e5868SGarrett D'Amore escaped = 1;
6606b5e5868SGarrett D'Amore continue;
6616b5e5868SGarrett D'Amore }
6626b5e5868SGarrett D'Amore switch (c) {
6636b5e5868SGarrett D'Amore case '<':
6646b5e5868SGarrett D'Amore return (get_symbol());
6656b5e5868SGarrett D'Amore case '>':
6666b5e5868SGarrett D'Amore /* oops! should generate syntax error */
6676b5e5868SGarrett D'Amore return (T_GT);
6686b5e5868SGarrett D'Amore case '"':
6696b5e5868SGarrett D'Amore instring = 0;
6706b5e5868SGarrett D'Amore return (T_QUOTE);
6716b5e5868SGarrett D'Amore default:
6726b5e5868SGarrett D'Amore yylval.wc = c;
6736b5e5868SGarrett D'Amore return (T_CHAR);
6746b5e5868SGarrett D'Amore }
6756b5e5868SGarrett D'Amore }
6766b5e5868SGarrett D'Amore
6776b5e5868SGarrett D'Amore /* escaped characters first */
6786b5e5868SGarrett D'Amore if (escaped) {
6796b5e5868SGarrett D'Amore escaped = 0;
6806b5e5868SGarrett D'Amore if (c == '\n') {
6816b5e5868SGarrett D'Amore /* eat the newline */
6826b5e5868SGarrett D'Amore continue;
6836b5e5868SGarrett D'Amore }
6846b5e5868SGarrett D'Amore hadtok = 1;
6856b5e5868SGarrett D'Amore if (tokidx) {
6866b5e5868SGarrett D'Amore /* an escape mid-token is nonsense */
6876b5e5868SGarrett D'Amore return (T_NULL);
6886b5e5868SGarrett D'Amore }
6896b5e5868SGarrett D'Amore
6906b5e5868SGarrett D'Amore /* numeric escapes are treated as wide characters */
6916b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) {
6926b5e5868SGarrett D'Amore unscanc(c);
6936b5e5868SGarrett D'Amore unscanc(esc_char);
6946b5e5868SGarrett D'Amore return (get_wide());
6956b5e5868SGarrett D'Amore }
6966b5e5868SGarrett D'Amore
6976b5e5868SGarrett D'Amore add_tok(get_escaped(c));
6986b5e5868SGarrett D'Amore continue;
6996b5e5868SGarrett D'Amore }
7006b5e5868SGarrett D'Amore
7016b5e5868SGarrett D'Amore /* if it is the escape charter itself note it */
7026b5e5868SGarrett D'Amore if (c == esc_char) {
7036b5e5868SGarrett D'Amore escaped = 1;
7046b5e5868SGarrett D'Amore continue;
7056b5e5868SGarrett D'Amore }
7066b5e5868SGarrett D'Amore
7076b5e5868SGarrett D'Amore /* remove from the comment char to end of line */
7086b5e5868SGarrett D'Amore if (c == com_char) {
7096b5e5868SGarrett D'Amore while (c != '\n') {
7106b5e5868SGarrett D'Amore if ((c = scanc()) == EOF) {
7116b5e5868SGarrett D'Amore /* end of file without newline! */
7126b5e5868SGarrett D'Amore return (EOF);
7136b5e5868SGarrett D'Amore }
7146b5e5868SGarrett D'Amore }
7156b5e5868SGarrett D'Amore assert(c == '\n');
7166b5e5868SGarrett D'Amore if (!hadtok) {
7176b5e5868SGarrett D'Amore /*
7186b5e5868SGarrett D'Amore * If there were no tokens on this line,
7196b5e5868SGarrett D'Amore * then just pretend it didn't exist at all.
7206b5e5868SGarrett D'Amore */
7216b5e5868SGarrett D'Amore continue;
7226b5e5868SGarrett D'Amore }
7236b5e5868SGarrett D'Amore hadtok = 0;
7246b5e5868SGarrett D'Amore return (T_NL);
7256b5e5868SGarrett D'Amore }
7266b5e5868SGarrett D'Amore
7276b5e5868SGarrett D'Amore if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) {
7286b5e5868SGarrett D'Amore /*
7296b5e5868SGarrett D'Amore * These are all token delimiters. If there
7306b5e5868SGarrett D'Amore * is a token already in progress, we need to
7316b5e5868SGarrett D'Amore * process it.
7326b5e5868SGarrett D'Amore */
7336b5e5868SGarrett D'Amore unscanc(c);
7346b5e5868SGarrett D'Amore return (consume_token());
7356b5e5868SGarrett D'Amore }
7366b5e5868SGarrett D'Amore
7376b5e5868SGarrett D'Amore switch (c) {
7386b5e5868SGarrett D'Amore case '\n':
7396b5e5868SGarrett D'Amore if (!hadtok) {
7406b5e5868SGarrett D'Amore /*
7416b5e5868SGarrett D'Amore * If the line was completely devoid of tokens,
7426b5e5868SGarrett D'Amore * then just ignore it.
7436b5e5868SGarrett D'Amore */
7446b5e5868SGarrett D'Amore continue;
7456b5e5868SGarrett D'Amore }
7466b5e5868SGarrett D'Amore /* we're starting a new line, reset the token state */
7476b5e5868SGarrett D'Amore hadtok = 0;
7486b5e5868SGarrett D'Amore return (T_NL);
7496b5e5868SGarrett D'Amore case ',':
7506b5e5868SGarrett D'Amore hadtok = 1;
7516b5e5868SGarrett D'Amore return (T_COMMA);
7526b5e5868SGarrett D'Amore case ';':
7536b5e5868SGarrett D'Amore hadtok = 1;
7546b5e5868SGarrett D'Amore return (T_SEMI);
7556b5e5868SGarrett D'Amore case '(':
7566b5e5868SGarrett D'Amore hadtok = 1;
7576b5e5868SGarrett D'Amore return (T_LPAREN);
7586b5e5868SGarrett D'Amore case ')':
7596b5e5868SGarrett D'Amore hadtok = 1;
7606b5e5868SGarrett D'Amore return (T_RPAREN);
7616b5e5868SGarrett D'Amore case '>':
7626b5e5868SGarrett D'Amore hadtok = 1;
7636b5e5868SGarrett D'Amore return (T_GT);
7646b5e5868SGarrett D'Amore case '<':
7656b5e5868SGarrett D'Amore /* symbol start! */
7666b5e5868SGarrett D'Amore hadtok = 1;
7676b5e5868SGarrett D'Amore return (get_symbol());
7686b5e5868SGarrett D'Amore case ' ':
7696b5e5868SGarrett D'Amore case '\t':
7706b5e5868SGarrett D'Amore /* whitespace, just ignore it */
7716b5e5868SGarrett D'Amore continue;
7726b5e5868SGarrett D'Amore case '"':
7736b5e5868SGarrett D'Amore hadtok = 1;
7746b5e5868SGarrett D'Amore instring = 1;
7756b5e5868SGarrett D'Amore return (T_QUOTE);
7766b5e5868SGarrett D'Amore default:
7776b5e5868SGarrett D'Amore hadtok = 1;
7786b5e5868SGarrett D'Amore add_tok(c);
7796b5e5868SGarrett D'Amore continue;
7806b5e5868SGarrett D'Amore }
7816b5e5868SGarrett D'Amore }
7826b5e5868SGarrett D'Amore return (EOF);
7836b5e5868SGarrett D'Amore }
7846b5e5868SGarrett D'Amore
785*1a90c98dSToomas Soome int
yyerror(const char * msg)7866b5e5868SGarrett D'Amore yyerror(const char *msg)
7876b5e5868SGarrett D'Amore {
7886b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"),
7896b5e5868SGarrett D'Amore filename, lineno, msg);
7906b5e5868SGarrett D'Amore exit(4);
7916b5e5868SGarrett D'Amore }
7926b5e5868SGarrett D'Amore
7936b5e5868SGarrett D'Amore void
errf(const char * fmt,...)7946b5e5868SGarrett D'Amore errf(const char *fmt, ...)
7956b5e5868SGarrett D'Amore {
7966b5e5868SGarrett D'Amore char *msg;
7976b5e5868SGarrett D'Amore
7986b5e5868SGarrett D'Amore va_list va;
7996b5e5868SGarrett D'Amore va_start(va, fmt);
8006b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va);
8016b5e5868SGarrett D'Amore va_end(va);
8026b5e5868SGarrett D'Amore
8036b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"),
8046b5e5868SGarrett D'Amore filename, lineno, msg);
8056b5e5868SGarrett D'Amore free(msg);
8066b5e5868SGarrett D'Amore exit(4);
8076b5e5868SGarrett D'Amore }
8086b5e5868SGarrett D'Amore
8096b5e5868SGarrett D'Amore void
warn(const char * fmt,...)8106b5e5868SGarrett D'Amore warn(const char *fmt, ...)
8116b5e5868SGarrett D'Amore {
8126b5e5868SGarrett D'Amore char *msg;
8136b5e5868SGarrett D'Amore
8146b5e5868SGarrett D'Amore va_list va;
8156b5e5868SGarrett D'Amore va_start(va, fmt);
8166b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va);
8176b5e5868SGarrett D'Amore va_end(va);
8186b5e5868SGarrett D'Amore
8196b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: warning: %s\n"),
8206b5e5868SGarrett D'Amore filename, lineno, msg);
8216b5e5868SGarrett D'Amore free(msg);
8226b5e5868SGarrett D'Amore warnings++;
8236b5e5868SGarrett D'Amore if (!warnok)
8246b5e5868SGarrett D'Amore exit(4);
8256b5e5868SGarrett D'Amore }
826