xref: /illumos-gate/usr/src/cmd/localedef/scanner.c (revision 7262c8a6)
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
166*7262c8a6SYuri 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) {
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;
4742da1cd3aSGarrett 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