xref: /titanic_54/usr/src/cmd/localedef/scanner.c (revision 6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648)
1*6b5e5868SGarrett D'Amore /*
2*6b5e5868SGarrett D'Amore  * This file and its contents are supplied under the terms of the
3*6b5e5868SGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
4*6b5e5868SGarrett D'Amore  * You may only use this file in accordance with the terms version 1.0
5*6b5e5868SGarrett D'Amore  * of the CDDL.
6*6b5e5868SGarrett D'Amore  *
7*6b5e5868SGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
8*6b5e5868SGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
9*6b5e5868SGarrett D'Amore  * http://www.illumos.org/license/CDDL.
10*6b5e5868SGarrett D'Amore  */
11*6b5e5868SGarrett D'Amore 
12*6b5e5868SGarrett D'Amore /*
13*6b5e5868SGarrett D'Amore  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
14*6b5e5868SGarrett D'Amore  */
15*6b5e5868SGarrett D'Amore 
16*6b5e5868SGarrett D'Amore /*
17*6b5e5868SGarrett D'Amore  * This file contains the "scanner", which tokenizes the input files
18*6b5e5868SGarrett D'Amore  * for localedef for processing by the higher level grammar processor.
19*6b5e5868SGarrett D'Amore  */
20*6b5e5868SGarrett D'Amore 
21*6b5e5868SGarrett D'Amore #include <stdio.h>
22*6b5e5868SGarrett D'Amore #include <stdlib.h>
23*6b5e5868SGarrett D'Amore #include <ctype.h>
24*6b5e5868SGarrett D'Amore #include <limits.h>
25*6b5e5868SGarrett D'Amore #include <string.h>
26*6b5e5868SGarrett D'Amore #include <widec.h>
27*6b5e5868SGarrett D'Amore #include <sys/types.h>
28*6b5e5868SGarrett D'Amore #include <assert.h>
29*6b5e5868SGarrett D'Amore #include "localedef.h"
30*6b5e5868SGarrett D'Amore #include "parser.tab.h"
31*6b5e5868SGarrett D'Amore 
32*6b5e5868SGarrett D'Amore int			com_char = '#';
33*6b5e5868SGarrett D'Amore int			esc_char = '\\';
34*6b5e5868SGarrett D'Amore int			mb_cur_min = 1;
35*6b5e5868SGarrett D'Amore int			mb_cur_max = 1;
36*6b5e5868SGarrett D'Amore int			lineno = 1;
37*6b5e5868SGarrett D'Amore int			warnings = 0;
38*6b5e5868SGarrett D'Amore static int		nextline;
39*6b5e5868SGarrett D'Amore static FILE		*input = stdin;
40*6b5e5868SGarrett D'Amore static const char	*filename = "<stdin>";
41*6b5e5868SGarrett D'Amore static int		instring = 0;
42*6b5e5868SGarrett D'Amore static int		escaped = 0;
43*6b5e5868SGarrett D'Amore 
44*6b5e5868SGarrett D'Amore /*
45*6b5e5868SGarrett D'Amore  * Token space ... grows on demand.
46*6b5e5868SGarrett D'Amore  */
47*6b5e5868SGarrett D'Amore static char *token = NULL;
48*6b5e5868SGarrett D'Amore static int tokidx;
49*6b5e5868SGarrett D'Amore static int toksz = 0;
50*6b5e5868SGarrett D'Amore static int hadtok = 0;
51*6b5e5868SGarrett D'Amore 
52*6b5e5868SGarrett D'Amore /*
53*6b5e5868SGarrett D'Amore  * Wide string space ... grows on demand.
54*6b5e5868SGarrett D'Amore  */
55*6b5e5868SGarrett D'Amore static wchar_t *widestr = NULL;
56*6b5e5868SGarrett D'Amore static int wideidx = 0;
57*6b5e5868SGarrett D'Amore static int widesz = 0;
58*6b5e5868SGarrett D'Amore 
59*6b5e5868SGarrett D'Amore /*
60*6b5e5868SGarrett D'Amore  * The last keyword seen.  This is useful to trigger the special lexer rules
61*6b5e5868SGarrett D'Amore  * for "copy" and also collating symbols and elements.
62*6b5e5868SGarrett D'Amore  */
63*6b5e5868SGarrett D'Amore int	last_kw = 0;
64*6b5e5868SGarrett D'Amore static int	category = T_END;
65*6b5e5868SGarrett D'Amore 
66*6b5e5868SGarrett D'Amore static struct token {
67*6b5e5868SGarrett D'Amore 	int id;
68*6b5e5868SGarrett D'Amore 	const char *name;
69*6b5e5868SGarrett D'Amore } keywords[] = {
70*6b5e5868SGarrett D'Amore 	{ T_COM_CHAR,		"comment_char" },
71*6b5e5868SGarrett D'Amore 	{ T_ESC_CHAR,		"escape_char" },
72*6b5e5868SGarrett D'Amore 	{ T_END,		"END" },
73*6b5e5868SGarrett D'Amore 	{ T_COPY,		"copy" },
74*6b5e5868SGarrett D'Amore 	{ T_MESSAGES,		"LC_MESSAGES" },
75*6b5e5868SGarrett D'Amore 	{ T_YESSTR,		"yesstr" },
76*6b5e5868SGarrett D'Amore 	{ T_YESEXPR,		"yesexpr" },
77*6b5e5868SGarrett D'Amore 	{ T_NOSTR,		"nostr" },
78*6b5e5868SGarrett D'Amore 	{ T_NOEXPR,		"noexpr" },
79*6b5e5868SGarrett D'Amore 	{ T_MONETARY,		"LC_MONETARY" },
80*6b5e5868SGarrett D'Amore 	{ T_INT_CURR_SYMBOL,	"int_curr_symbol" },
81*6b5e5868SGarrett D'Amore 	{ T_CURRENCY_SYMBOL,	"currency_symbol" },
82*6b5e5868SGarrett D'Amore 	{ T_MON_DECIMAL_POINT,	"mon_decimal_point" },
83*6b5e5868SGarrett D'Amore 	{ T_MON_THOUSANDS_SEP,	"mon_thousands_sep" },
84*6b5e5868SGarrett D'Amore 	{ T_POSITIVE_SIGN,	"positive_sign" },
85*6b5e5868SGarrett D'Amore 	{ T_NEGATIVE_SIGN,	"negative_sign" },
86*6b5e5868SGarrett D'Amore 	{ T_MON_GROUPING,	"mon_grouping" },
87*6b5e5868SGarrett D'Amore 	{ T_INT_FRAC_DIGITS,	"int_frac_digits" },
88*6b5e5868SGarrett D'Amore 	{ T_FRAC_DIGITS,	"frac_digits" },
89*6b5e5868SGarrett D'Amore 	{ T_P_CS_PRECEDES,	"p_cs_precedes" },
90*6b5e5868SGarrett D'Amore 	{ T_P_SEP_BY_SPACE,	"p_sep_by_space" },
91*6b5e5868SGarrett D'Amore 	{ T_N_CS_PRECEDES,	"n_cs_precedes" },
92*6b5e5868SGarrett D'Amore 	{ T_N_SEP_BY_SPACE,	"n_sep_by_space" },
93*6b5e5868SGarrett D'Amore 	{ T_P_SIGN_POSN,	"p_sign_posn" },
94*6b5e5868SGarrett D'Amore 	{ T_N_SIGN_POSN,	"n_sign_posn" },
95*6b5e5868SGarrett D'Amore 	{ T_INT_P_CS_PRECEDES,	"int_p_cs_precedes" },
96*6b5e5868SGarrett D'Amore 	{ T_INT_N_CS_PRECEDES,	"int_n_cs_precedes" },
97*6b5e5868SGarrett D'Amore 	{ T_INT_P_SEP_BY_SPACE,	"int_p_sep_by_space" },
98*6b5e5868SGarrett D'Amore 	{ T_INT_N_SEP_BY_SPACE,	"int_n_sep_by_space" },
99*6b5e5868SGarrett D'Amore 	{ T_INT_P_SIGN_POSN,	"int_p_sign_posn" },
100*6b5e5868SGarrett D'Amore 	{ T_INT_N_SIGN_POSN,	"int_n_sign_posn" },
101*6b5e5868SGarrett D'Amore 	{ T_COLLATE,		"LC_COLLATE" },
102*6b5e5868SGarrett D'Amore 	{ T_COLLATING_SYMBOL,	"collating-symbol" },
103*6b5e5868SGarrett D'Amore 	{ T_COLLATING_ELEMENT,	"collating-element" },
104*6b5e5868SGarrett D'Amore 	{ T_FROM,		"from" },
105*6b5e5868SGarrett D'Amore 	{ T_ORDER_START,	"order_start" },
106*6b5e5868SGarrett D'Amore 	{ T_ORDER_END,		"order_end" },
107*6b5e5868SGarrett D'Amore 	{ T_FORWARD,		"forward" },
108*6b5e5868SGarrett D'Amore 	{ T_BACKWARD,		"backward" },
109*6b5e5868SGarrett D'Amore 	{ T_POSITION,		"position" },
110*6b5e5868SGarrett D'Amore 	{ T_IGNORE,		"IGNORE" },
111*6b5e5868SGarrett D'Amore 	{ T_UNDEFINED,		"UNDEFINED" },
112*6b5e5868SGarrett D'Amore 	{ T_NUMERIC,		"LC_NUMERIC" },
113*6b5e5868SGarrett D'Amore 	{ T_DECIMAL_POINT,	"decimal_point" },
114*6b5e5868SGarrett D'Amore 	{ T_THOUSANDS_SEP,	"thousands_sep" },
115*6b5e5868SGarrett D'Amore 	{ T_GROUPING,		"grouping" },
116*6b5e5868SGarrett D'Amore 	{ T_TIME,		"LC_TIME" },
117*6b5e5868SGarrett D'Amore 	{ T_ABDAY,		"abday" },
118*6b5e5868SGarrett D'Amore 	{ T_DAY,		"day" },
119*6b5e5868SGarrett D'Amore 	{ T_ABMON,		"abmon" },
120*6b5e5868SGarrett D'Amore 	{ T_MON,		"mon" },
121*6b5e5868SGarrett D'Amore 	{ T_D_T_FMT,		"d_t_fmt" },
122*6b5e5868SGarrett D'Amore 	{ T_D_FMT,		"d_fmt" },
123*6b5e5868SGarrett D'Amore 	{ T_T_FMT,		"t_fmt" },
124*6b5e5868SGarrett D'Amore 	{ T_AM_PM,		"am_pm" },
125*6b5e5868SGarrett D'Amore 	{ T_T_FMT_AMPM,		"t_fmt_ampm" },
126*6b5e5868SGarrett D'Amore 	{ T_ERA,		"era" },
127*6b5e5868SGarrett D'Amore 	{ T_ERA_D_FMT,		"era_d_fmt" },
128*6b5e5868SGarrett D'Amore 	{ T_ERA_T_FMT,		"era_t_fmt" },
129*6b5e5868SGarrett D'Amore 	{ T_ERA_D_T_FMT,	"era_d_t_fmt" },
130*6b5e5868SGarrett D'Amore 	{ T_ALT_DIGITS,		"alt_digits" },
131*6b5e5868SGarrett D'Amore 	{ T_CTYPE,		"LC_CTYPE" },
132*6b5e5868SGarrett D'Amore 	{ T_ISUPPER,		"upper" },
133*6b5e5868SGarrett D'Amore 	{ T_ISLOWER,		"lower" },
134*6b5e5868SGarrett D'Amore 	{ T_ISALPHA,		"alpha" },
135*6b5e5868SGarrett D'Amore 	{ T_ISDIGIT,		"digit" },
136*6b5e5868SGarrett D'Amore 	{ T_ISPUNCT,		"punct" },
137*6b5e5868SGarrett D'Amore 	{ T_ISXDIGIT,		"xdigit" },
138*6b5e5868SGarrett D'Amore 	{ T_ISSPACE,		"space" },
139*6b5e5868SGarrett D'Amore 	{ T_ISPRINT,		"print" },
140*6b5e5868SGarrett D'Amore 	{ T_ISGRAPH,		"graph" },
141*6b5e5868SGarrett D'Amore 	{ T_ISBLANK,		"blank" },
142*6b5e5868SGarrett D'Amore 	{ T_ISCNTRL,		"cntrl" },
143*6b5e5868SGarrett D'Amore 	/*
144*6b5e5868SGarrett D'Amore 	 * These entries are local additions, and not specified by
145*6b5e5868SGarrett D'Amore 	 * TOG.  Note that they are not guaranteed to be accurate for
146*6b5e5868SGarrett D'Amore 	 * all locales, and so applications should not depend on them.
147*6b5e5868SGarrett D'Amore 	 */
148*6b5e5868SGarrett D'Amore 	{ T_ISSPECIAL,		"special" },
149*6b5e5868SGarrett D'Amore 	{ T_ISENGLISH,		"english" },
150*6b5e5868SGarrett D'Amore 	{ T_ISPHONOGRAM,	"phonogram" },
151*6b5e5868SGarrett D'Amore 	{ T_ISIDEOGRAM,		"ideogram" },
152*6b5e5868SGarrett D'Amore 	{ T_ISNUMBER,		"number" },
153*6b5e5868SGarrett D'Amore 	/*
154*6b5e5868SGarrett D'Amore 	 * We have to support this in the grammar, but it would be a
155*6b5e5868SGarrett D'Amore 	 * syntax error to define a character as one of these without
156*6b5e5868SGarrett D'Amore 	 * also defining it as an alpha or digit.  We ignore it in our
157*6b5e5868SGarrett D'Amore 	 * parsing.
158*6b5e5868SGarrett D'Amore 	 */
159*6b5e5868SGarrett D'Amore 	{ T_ISALNUM,		"alnum" },
160*6b5e5868SGarrett D'Amore 	{ T_TOUPPER,		"toupper" },
161*6b5e5868SGarrett D'Amore 	{ T_TOLOWER,		"tolower" },
162*6b5e5868SGarrett D'Amore 
163*6b5e5868SGarrett D'Amore 	/*
164*6b5e5868SGarrett D'Amore 	 * These are keywords used in the charmap file.  Note that
165*6b5e5868SGarrett D'Amore 	 * Solaris orginally used angle brackets to wrap some of them,
166*6b5e5868SGarrett D'Amore 	 * but we removed that to simplify our parser.  The first of these
167*6b5e5868SGarrett D'Amore 	 * items are "global items."
168*6b5e5868SGarrett D'Amore 	 */
169*6b5e5868SGarrett D'Amore 	{ T_CHARMAP,		"CHARMAP" },
170*6b5e5868SGarrett D'Amore 	{ T_WIDTH,		"WIDTH" },
171*6b5e5868SGarrett D'Amore 	{ T_WIDTH_DEFAULT,	"WIDTH_DEFAULT" },
172*6b5e5868SGarrett D'Amore 
173*6b5e5868SGarrett D'Amore 	{ -1, NULL },
174*6b5e5868SGarrett D'Amore };
175*6b5e5868SGarrett D'Amore 
176*6b5e5868SGarrett D'Amore /*
177*6b5e5868SGarrett D'Amore  * These special words are only used in a charmap file, enclosed in <>.
178*6b5e5868SGarrett D'Amore  */
179*6b5e5868SGarrett D'Amore static struct token symwords[] = {
180*6b5e5868SGarrett D'Amore 	{ T_COM_CHAR,		"comment_char" },
181*6b5e5868SGarrett D'Amore 	{ T_ESC_CHAR,		"escape_char" },
182*6b5e5868SGarrett D'Amore 	{ T_CODE_SET,		"code_set_name" },
183*6b5e5868SGarrett D'Amore 	{ T_MB_CUR_MAX,		"mb_cur_max" },
184*6b5e5868SGarrett D'Amore 	{ T_MB_CUR_MIN,		"mb_cur_min" },
185*6b5e5868SGarrett D'Amore 	{ -1, NULL },
186*6b5e5868SGarrett D'Amore };
187*6b5e5868SGarrett D'Amore 
188*6b5e5868SGarrett D'Amore static int categories[] = {
189*6b5e5868SGarrett D'Amore 	T_CHARMAP,
190*6b5e5868SGarrett D'Amore 	T_CTYPE,
191*6b5e5868SGarrett D'Amore 	T_COLLATE,
192*6b5e5868SGarrett D'Amore 	T_MESSAGES,
193*6b5e5868SGarrett D'Amore 	T_MONETARY,
194*6b5e5868SGarrett D'Amore 	T_NUMERIC,
195*6b5e5868SGarrett D'Amore 	T_TIME,
196*6b5e5868SGarrett D'Amore 	0
197*6b5e5868SGarrett D'Amore };
198*6b5e5868SGarrett D'Amore 
199*6b5e5868SGarrett D'Amore void
200*6b5e5868SGarrett D'Amore reset_scanner(const char *fname)
201*6b5e5868SGarrett D'Amore {
202*6b5e5868SGarrett D'Amore 	if (fname == NULL) {
203*6b5e5868SGarrett D'Amore 		filename = "<stdin>";
204*6b5e5868SGarrett D'Amore 		input = stdin;
205*6b5e5868SGarrett D'Amore 	} else {
206*6b5e5868SGarrett D'Amore 		if (input != stdin)
207*6b5e5868SGarrett D'Amore 			(void) fclose(input);
208*6b5e5868SGarrett D'Amore 		if ((input = fopen(fname, "r")) == NULL) {
209*6b5e5868SGarrett D'Amore 			perror("fopen");
210*6b5e5868SGarrett D'Amore 			exit(4);
211*6b5e5868SGarrett D'Amore 		}
212*6b5e5868SGarrett D'Amore 		filename = fname;
213*6b5e5868SGarrett D'Amore 	}
214*6b5e5868SGarrett D'Amore 	com_char = '#';
215*6b5e5868SGarrett D'Amore 	esc_char = '\\';
216*6b5e5868SGarrett D'Amore 	instring = 0;
217*6b5e5868SGarrett D'Amore 	escaped = 0;
218*6b5e5868SGarrett D'Amore 	lineno = 1;
219*6b5e5868SGarrett D'Amore 	nextline = 1;
220*6b5e5868SGarrett D'Amore 	tokidx = 0;
221*6b5e5868SGarrett D'Amore 	wideidx = 0;
222*6b5e5868SGarrett D'Amore }
223*6b5e5868SGarrett D'Amore 
224*6b5e5868SGarrett D'Amore #define	hex(x)	\
225*6b5e5868SGarrett D'Amore 	(isdigit(x) ? (x - '0') : ((islower(x) ? (x - 'a') : (x - 'A')) + 10))
226*6b5e5868SGarrett D'Amore #define	isodigit(x)	((x >= '0') && (x <= '7'))
227*6b5e5868SGarrett D'Amore 
228*6b5e5868SGarrett D'Amore static int
229*6b5e5868SGarrett D'Amore scanc(void)
230*6b5e5868SGarrett D'Amore {
231*6b5e5868SGarrett D'Amore 	int	c;
232*6b5e5868SGarrett D'Amore 
233*6b5e5868SGarrett D'Amore 	c = getc(input);
234*6b5e5868SGarrett D'Amore 	lineno = nextline;
235*6b5e5868SGarrett D'Amore 	if (c == '\n') {
236*6b5e5868SGarrett D'Amore 		nextline++;
237*6b5e5868SGarrett D'Amore 	}
238*6b5e5868SGarrett D'Amore 	return (c);
239*6b5e5868SGarrett D'Amore }
240*6b5e5868SGarrett D'Amore 
241*6b5e5868SGarrett D'Amore static void
242*6b5e5868SGarrett D'Amore unscanc(int c)
243*6b5e5868SGarrett D'Amore {
244*6b5e5868SGarrett D'Amore 	if (c == '\n') {
245*6b5e5868SGarrett D'Amore 		nextline--;
246*6b5e5868SGarrett D'Amore 	}
247*6b5e5868SGarrett D'Amore 	if (ungetc(c, input) < 0) {
248*6b5e5868SGarrett D'Amore 		yyerror(_("ungetc failed"));
249*6b5e5868SGarrett D'Amore 	}
250*6b5e5868SGarrett D'Amore }
251*6b5e5868SGarrett D'Amore 
252*6b5e5868SGarrett D'Amore static int
253*6b5e5868SGarrett D'Amore scan_hex_byte(void)
254*6b5e5868SGarrett D'Amore {
255*6b5e5868SGarrett D'Amore 	int	c1, c2;
256*6b5e5868SGarrett D'Amore 	int	v;
257*6b5e5868SGarrett D'Amore 
258*6b5e5868SGarrett D'Amore 	c1 = scanc();
259*6b5e5868SGarrett D'Amore 	if (!isxdigit(c1)) {
260*6b5e5868SGarrett D'Amore 		yyerror(_("malformed hex digit"));
261*6b5e5868SGarrett D'Amore 		return (0);
262*6b5e5868SGarrett D'Amore 	}
263*6b5e5868SGarrett D'Amore 	c2 = scanc();
264*6b5e5868SGarrett D'Amore 	if (!isxdigit(c2)) {
265*6b5e5868SGarrett D'Amore 		yyerror(_("malformed hex digit"));
266*6b5e5868SGarrett D'Amore 		return (0);
267*6b5e5868SGarrett D'Amore 	}
268*6b5e5868SGarrett D'Amore 	v = ((hex(c1) << 4) | hex(c2));
269*6b5e5868SGarrett D'Amore 	return (v);
270*6b5e5868SGarrett D'Amore }
271*6b5e5868SGarrett D'Amore 
272*6b5e5868SGarrett D'Amore static int
273*6b5e5868SGarrett D'Amore scan_dec_byte(void)
274*6b5e5868SGarrett D'Amore {
275*6b5e5868SGarrett D'Amore 	int	c1, c2, c3;
276*6b5e5868SGarrett D'Amore 	int	b;
277*6b5e5868SGarrett D'Amore 
278*6b5e5868SGarrett D'Amore 	c1 = scanc();
279*6b5e5868SGarrett D'Amore 	if (!isdigit(c1)) {
280*6b5e5868SGarrett D'Amore 		yyerror(_("malformed decimal digit"));
281*6b5e5868SGarrett D'Amore 		return (0);
282*6b5e5868SGarrett D'Amore 	}
283*6b5e5868SGarrett D'Amore 	b = c1 - '0';
284*6b5e5868SGarrett D'Amore 	c2 = scanc();
285*6b5e5868SGarrett D'Amore 	if (!isdigit(c2)) {
286*6b5e5868SGarrett D'Amore 		yyerror(_("malformed decimal digit"));
287*6b5e5868SGarrett D'Amore 		return (0);
288*6b5e5868SGarrett D'Amore 	}
289*6b5e5868SGarrett D'Amore 	b *= 10;
290*6b5e5868SGarrett D'Amore 	b += (c2 - '0');
291*6b5e5868SGarrett D'Amore 	c3 = scanc();
292*6b5e5868SGarrett D'Amore 	if (!isdigit(c3)) {
293*6b5e5868SGarrett D'Amore 		unscanc(c3);
294*6b5e5868SGarrett D'Amore 	} else {
295*6b5e5868SGarrett D'Amore 		b *= 10;
296*6b5e5868SGarrett D'Amore 		b += (c3 - '0');
297*6b5e5868SGarrett D'Amore 	}
298*6b5e5868SGarrett D'Amore 	return (b);
299*6b5e5868SGarrett D'Amore }
300*6b5e5868SGarrett D'Amore 
301*6b5e5868SGarrett D'Amore static int
302*6b5e5868SGarrett D'Amore scan_oct_byte(void)
303*6b5e5868SGarrett D'Amore {
304*6b5e5868SGarrett D'Amore 	int c1, c2, c3;
305*6b5e5868SGarrett D'Amore 	int	b;
306*6b5e5868SGarrett D'Amore 
307*6b5e5868SGarrett D'Amore 	b = 0;
308*6b5e5868SGarrett D'Amore 
309*6b5e5868SGarrett D'Amore 	c1 = scanc();
310*6b5e5868SGarrett D'Amore 	if (!isodigit(c1)) {
311*6b5e5868SGarrett D'Amore 		yyerror(_("malformed octal digit"));
312*6b5e5868SGarrett D'Amore 		return (0);
313*6b5e5868SGarrett D'Amore 	}
314*6b5e5868SGarrett D'Amore 	b = c1 - '0';
315*6b5e5868SGarrett D'Amore 	c2 = scanc();
316*6b5e5868SGarrett D'Amore 	if (!isodigit(c2)) {
317*6b5e5868SGarrett D'Amore 		yyerror(_("malformed octal digit"));
318*6b5e5868SGarrett D'Amore 		return (0);
319*6b5e5868SGarrett D'Amore 	}
320*6b5e5868SGarrett D'Amore 	b *= 8;
321*6b5e5868SGarrett D'Amore 	b += (c2 - '0');
322*6b5e5868SGarrett D'Amore 	c3 = scanc();
323*6b5e5868SGarrett D'Amore 	if (!isodigit(c3)) {
324*6b5e5868SGarrett D'Amore 		unscanc(c3);
325*6b5e5868SGarrett D'Amore 	} else {
326*6b5e5868SGarrett D'Amore 		b *= 8;
327*6b5e5868SGarrett D'Amore 		b += (c3 - '0');
328*6b5e5868SGarrett D'Amore 	}
329*6b5e5868SGarrett D'Amore 	return (b);
330*6b5e5868SGarrett D'Amore }
331*6b5e5868SGarrett D'Amore 
332*6b5e5868SGarrett D'Amore void
333*6b5e5868SGarrett D'Amore add_tok(int c)
334*6b5e5868SGarrett D'Amore {
335*6b5e5868SGarrett D'Amore 	if ((tokidx + 1) >= toksz) {
336*6b5e5868SGarrett D'Amore 		toksz += 64;
337*6b5e5868SGarrett D'Amore 		if ((token = realloc(token, toksz)) == NULL) {
338*6b5e5868SGarrett D'Amore 			yyerror(_("out of memory"));
339*6b5e5868SGarrett D'Amore 			tokidx = 0;
340*6b5e5868SGarrett D'Amore 			toksz = 0;
341*6b5e5868SGarrett D'Amore 			return;
342*6b5e5868SGarrett D'Amore 		}
343*6b5e5868SGarrett D'Amore 	}
344*6b5e5868SGarrett D'Amore 
345*6b5e5868SGarrett D'Amore 	token[tokidx++] = (char)c;
346*6b5e5868SGarrett D'Amore 	token[tokidx] = 0;
347*6b5e5868SGarrett D'Amore }
348*6b5e5868SGarrett D'Amore void
349*6b5e5868SGarrett D'Amore add_wcs(wchar_t c)
350*6b5e5868SGarrett D'Amore {
351*6b5e5868SGarrett D'Amore 	if ((wideidx + 1) >= widesz) {
352*6b5e5868SGarrett D'Amore 		widesz += 64;
353*6b5e5868SGarrett D'Amore 		widestr = realloc(widestr, (widesz * sizeof (wchar_t)));
354*6b5e5868SGarrett D'Amore 		if (widestr == NULL) {
355*6b5e5868SGarrett D'Amore 			yyerror(_("out of memory"));
356*6b5e5868SGarrett D'Amore 			wideidx = 0;
357*6b5e5868SGarrett D'Amore 			widesz = 0;
358*6b5e5868SGarrett D'Amore 			return;
359*6b5e5868SGarrett D'Amore 		}
360*6b5e5868SGarrett D'Amore 	}
361*6b5e5868SGarrett D'Amore 
362*6b5e5868SGarrett D'Amore 	widestr[wideidx++] = c;
363*6b5e5868SGarrett D'Amore 	widestr[wideidx] = 0;
364*6b5e5868SGarrett D'Amore }
365*6b5e5868SGarrett D'Amore 
366*6b5e5868SGarrett D'Amore wchar_t *
367*6b5e5868SGarrett D'Amore get_wcs(void)
368*6b5e5868SGarrett D'Amore {
369*6b5e5868SGarrett D'Amore 	wchar_t *ws = widestr;
370*6b5e5868SGarrett D'Amore 	wideidx = 0;
371*6b5e5868SGarrett D'Amore 	widestr = NULL;
372*6b5e5868SGarrett D'Amore 	widesz = 0;
373*6b5e5868SGarrett D'Amore 	if (ws == NULL) {
374*6b5e5868SGarrett D'Amore 		if ((ws = wsdup(L"")) == NULL) {
375*6b5e5868SGarrett D'Amore 			yyerror(_("out of memory"));
376*6b5e5868SGarrett D'Amore 		}
377*6b5e5868SGarrett D'Amore 	}
378*6b5e5868SGarrett D'Amore 	return (ws);
379*6b5e5868SGarrett D'Amore }
380*6b5e5868SGarrett D'Amore 
381*6b5e5868SGarrett D'Amore static int
382*6b5e5868SGarrett D'Amore get_byte(void)
383*6b5e5868SGarrett D'Amore {
384*6b5e5868SGarrett D'Amore 	int	c;
385*6b5e5868SGarrett D'Amore 
386*6b5e5868SGarrett D'Amore 	if ((c = scanc()) != esc_char) {
387*6b5e5868SGarrett D'Amore 		unscanc(c);
388*6b5e5868SGarrett D'Amore 		return (EOF);
389*6b5e5868SGarrett D'Amore 	}
390*6b5e5868SGarrett D'Amore 	c = scanc();
391*6b5e5868SGarrett D'Amore 
392*6b5e5868SGarrett D'Amore 	switch (c) {
393*6b5e5868SGarrett D'Amore 	case 'd':
394*6b5e5868SGarrett D'Amore 	case 'D':
395*6b5e5868SGarrett D'Amore 		return (scan_dec_byte());
396*6b5e5868SGarrett D'Amore 	case 'x':
397*6b5e5868SGarrett D'Amore 	case 'X':
398*6b5e5868SGarrett D'Amore 		return (scan_hex_byte());
399*6b5e5868SGarrett D'Amore 	case '0':
400*6b5e5868SGarrett D'Amore 	case '1':
401*6b5e5868SGarrett D'Amore 	case '2':
402*6b5e5868SGarrett D'Amore 	case '3':
403*6b5e5868SGarrett D'Amore 	case '4':
404*6b5e5868SGarrett D'Amore 	case '5':
405*6b5e5868SGarrett D'Amore 	case '6':
406*6b5e5868SGarrett D'Amore 	case '7':
407*6b5e5868SGarrett D'Amore 		/* put the character back so we can get it */
408*6b5e5868SGarrett D'Amore 		unscanc(c);
409*6b5e5868SGarrett D'Amore 		return (scan_oct_byte());
410*6b5e5868SGarrett D'Amore 	default:
411*6b5e5868SGarrett D'Amore 		unscanc(c);
412*6b5e5868SGarrett D'Amore 		unscanc(esc_char);
413*6b5e5868SGarrett D'Amore 		return (EOF);
414*6b5e5868SGarrett D'Amore 	}
415*6b5e5868SGarrett D'Amore }
416*6b5e5868SGarrett D'Amore 
417*6b5e5868SGarrett D'Amore int
418*6b5e5868SGarrett D'Amore get_escaped(int c)
419*6b5e5868SGarrett D'Amore {
420*6b5e5868SGarrett D'Amore 	switch (c) {
421*6b5e5868SGarrett D'Amore 	case 'n':
422*6b5e5868SGarrett D'Amore 		return ('\n');
423*6b5e5868SGarrett D'Amore 	case 'r':
424*6b5e5868SGarrett D'Amore 		return ('\r');
425*6b5e5868SGarrett D'Amore 	case 't':
426*6b5e5868SGarrett D'Amore 		return ('\t');
427*6b5e5868SGarrett D'Amore 	case 'f':
428*6b5e5868SGarrett D'Amore 		return ('\f');
429*6b5e5868SGarrett D'Amore 	case 'v':
430*6b5e5868SGarrett D'Amore 		return ('\v');
431*6b5e5868SGarrett D'Amore 	case 'b':
432*6b5e5868SGarrett D'Amore 		return ('\b');
433*6b5e5868SGarrett D'Amore 	case 'a':
434*6b5e5868SGarrett D'Amore 		return ('\a');
435*6b5e5868SGarrett D'Amore 	default:
436*6b5e5868SGarrett D'Amore 		return (c);
437*6b5e5868SGarrett D'Amore 	}
438*6b5e5868SGarrett D'Amore }
439*6b5e5868SGarrett D'Amore 
440*6b5e5868SGarrett D'Amore int
441*6b5e5868SGarrett D'Amore get_wide(void)
442*6b5e5868SGarrett D'Amore {
443*6b5e5868SGarrett D'Amore 	static char mbs[MB_LEN_MAX + 1] = "";
444*6b5e5868SGarrett D'Amore 	static int mbi = 0;
445*6b5e5868SGarrett D'Amore 	int c;
446*6b5e5868SGarrett D'Amore 	wchar_t	wc;
447*6b5e5868SGarrett D'Amore 
448*6b5e5868SGarrett D'Amore 	if (mb_cur_max >= sizeof (mbs)) {
449*6b5e5868SGarrett D'Amore 		yyerror(_("max multibyte character size too big"));
450*6b5e5868SGarrett D'Amore 		mbi = 0;
451*6b5e5868SGarrett D'Amore 		return (T_NULL);
452*6b5e5868SGarrett D'Amore 	}
453*6b5e5868SGarrett D'Amore 	for (;;) {
454*6b5e5868SGarrett D'Amore 		if ((mbi == mb_cur_max) || ((c = get_byte()) == EOF)) {
455*6b5e5868SGarrett D'Amore 			/*
456*6b5e5868SGarrett D'Amore 			 * end of the byte sequence reached, but no
457*6b5e5868SGarrett D'Amore 			 * valid wide decoding.  fatal error.
458*6b5e5868SGarrett D'Amore 			 */
459*6b5e5868SGarrett D'Amore 			mbi = 0;
460*6b5e5868SGarrett D'Amore 			yyerror(_("not a valid character encoding"));
461*6b5e5868SGarrett D'Amore 			return (T_NULL);
462*6b5e5868SGarrett D'Amore 		}
463*6b5e5868SGarrett D'Amore 		mbs[mbi++] = c;
464*6b5e5868SGarrett D'Amore 		mbs[mbi] = 0;
465*6b5e5868SGarrett D'Amore 
466*6b5e5868SGarrett D'Amore 		/* does it decode? */
467*6b5e5868SGarrett D'Amore 		if (to_wide(&wc, mbs) >= 0) {
468*6b5e5868SGarrett D'Amore 			break;
469*6b5e5868SGarrett D'Amore 		}
470*6b5e5868SGarrett D'Amore 	}
471*6b5e5868SGarrett D'Amore 
472*6b5e5868SGarrett D'Amore 	mbi = 0;
473*6b5e5868SGarrett D'Amore 	if (category != T_CHARMAP) {
474*6b5e5868SGarrett D'Amore 		if (check_charmap(wc) < 0) {
475*6b5e5868SGarrett D'Amore 			yyerror(_("no symbolic name for character"));
476*6b5e5868SGarrett D'Amore 			return (T_NULL);
477*6b5e5868SGarrett D'Amore 		}
478*6b5e5868SGarrett D'Amore 	}
479*6b5e5868SGarrett D'Amore 
480*6b5e5868SGarrett D'Amore 	yylval.wc = wc;
481*6b5e5868SGarrett D'Amore 	return (T_CHAR);
482*6b5e5868SGarrett D'Amore }
483*6b5e5868SGarrett D'Amore 
484*6b5e5868SGarrett D'Amore int
485*6b5e5868SGarrett D'Amore get_symbol(void)
486*6b5e5868SGarrett D'Amore {
487*6b5e5868SGarrett D'Amore 	int	c;
488*6b5e5868SGarrett D'Amore 
489*6b5e5868SGarrett D'Amore 	while ((c = scanc()) != EOF) {
490*6b5e5868SGarrett D'Amore 		if (escaped) {
491*6b5e5868SGarrett D'Amore 			escaped = 0;
492*6b5e5868SGarrett D'Amore 			if (c == '\n')
493*6b5e5868SGarrett D'Amore 				continue;
494*6b5e5868SGarrett D'Amore 			add_tok(get_escaped(c));
495*6b5e5868SGarrett D'Amore 			continue;
496*6b5e5868SGarrett D'Amore 		}
497*6b5e5868SGarrett D'Amore 		if (c == esc_char) {
498*6b5e5868SGarrett D'Amore 			escaped = 1;
499*6b5e5868SGarrett D'Amore 			continue;
500*6b5e5868SGarrett D'Amore 		}
501*6b5e5868SGarrett D'Amore 		if (c == '\n') {	/* well that's strange! */
502*6b5e5868SGarrett D'Amore 			yyerror(_("unterminated symbolic name"));
503*6b5e5868SGarrett D'Amore 			continue;
504*6b5e5868SGarrett D'Amore 		}
505*6b5e5868SGarrett D'Amore 		if (c == '>') {		/* end of symbol */
506*6b5e5868SGarrett D'Amore 
507*6b5e5868SGarrett D'Amore 			/*
508*6b5e5868SGarrett D'Amore 			 * This restarts the token from the beginning
509*6b5e5868SGarrett D'Amore 			 * the next time we scan a character.  (This
510*6b5e5868SGarrett D'Amore 			 * token is complete.)
511*6b5e5868SGarrett D'Amore 			 */
512*6b5e5868SGarrett D'Amore 
513*6b5e5868SGarrett D'Amore 			if (token == NULL) {
514*6b5e5868SGarrett D'Amore 				yyerror(_("missing symbolic name"));
515*6b5e5868SGarrett D'Amore 				return (T_NULL);
516*6b5e5868SGarrett D'Amore 			}
517*6b5e5868SGarrett D'Amore 			tokidx = 0;
518*6b5e5868SGarrett D'Amore 
519*6b5e5868SGarrett D'Amore 			/*
520*6b5e5868SGarrett D'Amore 			 * A few symbols are handled as keywords outside
521*6b5e5868SGarrett D'Amore 			 * of the normal categories.
522*6b5e5868SGarrett D'Amore 			 */
523*6b5e5868SGarrett D'Amore 			if (category == T_END) {
524*6b5e5868SGarrett D'Amore 				int i;
525*6b5e5868SGarrett D'Amore 				for (i = 0; symwords[i].name != 0; i++) {
526*6b5e5868SGarrett D'Amore 					if (strcmp(token, symwords[i].name) ==
527*6b5e5868SGarrett D'Amore 					    0) {
528*6b5e5868SGarrett D'Amore 						last_kw = symwords[i].id;
529*6b5e5868SGarrett D'Amore 						return (last_kw);
530*6b5e5868SGarrett D'Amore 					}
531*6b5e5868SGarrett D'Amore 				}
532*6b5e5868SGarrett D'Amore 			}
533*6b5e5868SGarrett D'Amore 			/*
534*6b5e5868SGarrett D'Amore 			 * Contextual rule: Only literal characters are
535*6b5e5868SGarrett D'Amore 			 * permitted in CHARMAP.  Anywhere else the symbolic
536*6b5e5868SGarrett D'Amore 			 * forms are fine.
537*6b5e5868SGarrett D'Amore 			 */
538*6b5e5868SGarrett D'Amore 			if ((category != T_CHARMAP) &&
539*6b5e5868SGarrett D'Amore 			    (lookup_charmap(token, &yylval.wc)) != -1) {
540*6b5e5868SGarrett D'Amore 				return (T_CHAR);
541*6b5e5868SGarrett D'Amore 			}
542*6b5e5868SGarrett D'Amore 			if ((yylval.collsym = lookup_collsym(token)) != NULL) {
543*6b5e5868SGarrett D'Amore 				return (T_COLLSYM);
544*6b5e5868SGarrett D'Amore 			}
545*6b5e5868SGarrett D'Amore 			if ((yylval.collelem = lookup_collelem(token)) !=
546*6b5e5868SGarrett D'Amore 			    NULL) {
547*6b5e5868SGarrett D'Amore 				return (T_COLLELEM);
548*6b5e5868SGarrett D'Amore 			}
549*6b5e5868SGarrett D'Amore 			/* its an undefined symbol */
550*6b5e5868SGarrett D'Amore 			yylval.token = strdup(token);
551*6b5e5868SGarrett D'Amore 			token = NULL;
552*6b5e5868SGarrett D'Amore 			toksz = 0;
553*6b5e5868SGarrett D'Amore 			tokidx = 0;
554*6b5e5868SGarrett D'Amore 			return (T_SYMBOL);
555*6b5e5868SGarrett D'Amore 		}
556*6b5e5868SGarrett D'Amore 		add_tok(c);
557*6b5e5868SGarrett D'Amore 	}
558*6b5e5868SGarrett D'Amore 
559*6b5e5868SGarrett D'Amore 	yyerror(_("unterminated symbolic name"));
560*6b5e5868SGarrett D'Amore 	return (EOF);
561*6b5e5868SGarrett D'Amore }
562*6b5e5868SGarrett D'Amore 
563*6b5e5868SGarrett D'Amore int
564*6b5e5868SGarrett D'Amore get_category(void)
565*6b5e5868SGarrett D'Amore {
566*6b5e5868SGarrett D'Amore 	return (category);
567*6b5e5868SGarrett D'Amore }
568*6b5e5868SGarrett D'Amore 
569*6b5e5868SGarrett D'Amore static int
570*6b5e5868SGarrett D'Amore consume_token(void)
571*6b5e5868SGarrett D'Amore {
572*6b5e5868SGarrett D'Amore 	int	len = tokidx;
573*6b5e5868SGarrett D'Amore 	int	i;
574*6b5e5868SGarrett D'Amore 
575*6b5e5868SGarrett D'Amore 	tokidx = 0;
576*6b5e5868SGarrett D'Amore 	if (token == NULL)
577*6b5e5868SGarrett D'Amore 		return (T_NULL);
578*6b5e5868SGarrett D'Amore 
579*6b5e5868SGarrett D'Amore 	/*
580*6b5e5868SGarrett D'Amore 	 * this one is special, because we don't want it to alter the
581*6b5e5868SGarrett D'Amore 	 * last_kw field.
582*6b5e5868SGarrett D'Amore 	 */
583*6b5e5868SGarrett D'Amore 	if (strcmp(token, "...") == 0) {
584*6b5e5868SGarrett D'Amore 		return (T_ELLIPSIS);
585*6b5e5868SGarrett D'Amore 	}
586*6b5e5868SGarrett D'Amore 
587*6b5e5868SGarrett D'Amore 	/* search for reserved words first */
588*6b5e5868SGarrett D'Amore 	for (i = 0; keywords[i].name; i++) {
589*6b5e5868SGarrett D'Amore 		int j;
590*6b5e5868SGarrett D'Amore 		if (strcmp(keywords[i].name, token) != 0) {
591*6b5e5868SGarrett D'Amore 			continue;
592*6b5e5868SGarrett D'Amore 		}
593*6b5e5868SGarrett D'Amore 
594*6b5e5868SGarrett D'Amore 		last_kw = keywords[i].id;
595*6b5e5868SGarrett D'Amore 
596*6b5e5868SGarrett D'Amore 		/* clear the top level category if we're done with it */
597*6b5e5868SGarrett D'Amore 		if (last_kw == T_END) {
598*6b5e5868SGarrett D'Amore 			category = T_END;
599*6b5e5868SGarrett D'Amore 		}
600*6b5e5868SGarrett D'Amore 
601*6b5e5868SGarrett D'Amore 		/* set the top level category if we're changing */
602*6b5e5868SGarrett D'Amore 		for (j = 0; categories[j]; j++) {
603*6b5e5868SGarrett D'Amore 			if (categories[j] != last_kw)
604*6b5e5868SGarrett D'Amore 				continue;
605*6b5e5868SGarrett D'Amore 			category = last_kw;
606*6b5e5868SGarrett D'Amore 		}
607*6b5e5868SGarrett D'Amore 
608*6b5e5868SGarrett D'Amore 		return (keywords[i].id);
609*6b5e5868SGarrett D'Amore 	}
610*6b5e5868SGarrett D'Amore 
611*6b5e5868SGarrett D'Amore 	/* maybe its a numeric constant? */
612*6b5e5868SGarrett D'Amore 	if (isdigit(*token) || (*token == '-' && isdigit(token[1]))) {
613*6b5e5868SGarrett D'Amore 		char *eptr;
614*6b5e5868SGarrett D'Amore 		yylval.num = strtol(token, &eptr, 10);
615*6b5e5868SGarrett D'Amore 		if (*eptr != 0)
616*6b5e5868SGarrett D'Amore 			yyerror(_("malformed number"));
617*6b5e5868SGarrett D'Amore 		return (T_NUMBER);
618*6b5e5868SGarrett D'Amore 	}
619*6b5e5868SGarrett D'Amore 
620*6b5e5868SGarrett D'Amore 	/*
621*6b5e5868SGarrett D'Amore 	 * A single lone character is treated as a character literal.
622*6b5e5868SGarrett D'Amore 	 * To avoid duplication of effort, we stick in the charmap.
623*6b5e5868SGarrett D'Amore 	 */
624*6b5e5868SGarrett D'Amore 	if (len == 1) {
625*6b5e5868SGarrett D'Amore 		yylval.wc = token[0];
626*6b5e5868SGarrett D'Amore 		return (T_CHAR);
627*6b5e5868SGarrett D'Amore 	}
628*6b5e5868SGarrett D'Amore 
629*6b5e5868SGarrett D'Amore 	/* anything else is treated as a symbolic name */
630*6b5e5868SGarrett D'Amore 	yylval.token = strdup(token);
631*6b5e5868SGarrett D'Amore 	token = NULL;
632*6b5e5868SGarrett D'Amore 	toksz = 0;
633*6b5e5868SGarrett D'Amore 	tokidx = 0;
634*6b5e5868SGarrett D'Amore 	return (T_NAME);
635*6b5e5868SGarrett D'Amore }
636*6b5e5868SGarrett D'Amore 
637*6b5e5868SGarrett D'Amore void
638*6b5e5868SGarrett D'Amore scan_to_eol(void)
639*6b5e5868SGarrett D'Amore {
640*6b5e5868SGarrett D'Amore 	int	c;
641*6b5e5868SGarrett D'Amore 	while ((c = scanc()) != '\n') {
642*6b5e5868SGarrett D'Amore 		if (c == EOF) {
643*6b5e5868SGarrett D'Amore 			/* end of file without newline! */
644*6b5e5868SGarrett D'Amore 			errf(_("missing newline"));
645*6b5e5868SGarrett D'Amore 			return;
646*6b5e5868SGarrett D'Amore 		}
647*6b5e5868SGarrett D'Amore 	}
648*6b5e5868SGarrett D'Amore 	assert(c == '\n');
649*6b5e5868SGarrett D'Amore }
650*6b5e5868SGarrett D'Amore 
651*6b5e5868SGarrett D'Amore int
652*6b5e5868SGarrett D'Amore yylex(void)
653*6b5e5868SGarrett D'Amore {
654*6b5e5868SGarrett D'Amore 	int		c;
655*6b5e5868SGarrett D'Amore 
656*6b5e5868SGarrett D'Amore 	while ((c = scanc()) != EOF) {
657*6b5e5868SGarrett D'Amore 
658*6b5e5868SGarrett D'Amore 		/* special handling for quoted string */
659*6b5e5868SGarrett D'Amore 		if (instring) {
660*6b5e5868SGarrett D'Amore 			if (escaped) {
661*6b5e5868SGarrett D'Amore 				escaped = 0;
662*6b5e5868SGarrett D'Amore 
663*6b5e5868SGarrett D'Amore 				/* if newline, just eat and forget it */
664*6b5e5868SGarrett D'Amore 				if (c == '\n')
665*6b5e5868SGarrett D'Amore 					continue;
666*6b5e5868SGarrett D'Amore 
667*6b5e5868SGarrett D'Amore 				if (strchr("xXd01234567", c)) {
668*6b5e5868SGarrett D'Amore 					unscanc(c);
669*6b5e5868SGarrett D'Amore 					unscanc(esc_char);
670*6b5e5868SGarrett D'Amore 					return (get_wide());
671*6b5e5868SGarrett D'Amore 				}
672*6b5e5868SGarrett D'Amore 				yylval.wc = get_escaped(c);
673*6b5e5868SGarrett D'Amore 				return (T_CHAR);
674*6b5e5868SGarrett D'Amore 			}
675*6b5e5868SGarrett D'Amore 			if (c == esc_char) {
676*6b5e5868SGarrett D'Amore 				escaped = 1;
677*6b5e5868SGarrett D'Amore 				continue;
678*6b5e5868SGarrett D'Amore 			}
679*6b5e5868SGarrett D'Amore 			switch (c) {
680*6b5e5868SGarrett D'Amore 			case '<':
681*6b5e5868SGarrett D'Amore 				return (get_symbol());
682*6b5e5868SGarrett D'Amore 			case '>':
683*6b5e5868SGarrett D'Amore 				/* oops! should generate syntax error  */
684*6b5e5868SGarrett D'Amore 				return (T_GT);
685*6b5e5868SGarrett D'Amore 			case '"':
686*6b5e5868SGarrett D'Amore 				instring = 0;
687*6b5e5868SGarrett D'Amore 				return (T_QUOTE);
688*6b5e5868SGarrett D'Amore 			default:
689*6b5e5868SGarrett D'Amore 				yylval.wc = c;
690*6b5e5868SGarrett D'Amore 				return (T_CHAR);
691*6b5e5868SGarrett D'Amore 			}
692*6b5e5868SGarrett D'Amore 		}
693*6b5e5868SGarrett D'Amore 
694*6b5e5868SGarrett D'Amore 		/* escaped characters first */
695*6b5e5868SGarrett D'Amore 		if (escaped) {
696*6b5e5868SGarrett D'Amore 			escaped = 0;
697*6b5e5868SGarrett D'Amore 			if (c == '\n') {
698*6b5e5868SGarrett D'Amore 				/* eat the newline */
699*6b5e5868SGarrett D'Amore 				continue;
700*6b5e5868SGarrett D'Amore 			}
701*6b5e5868SGarrett D'Amore 			hadtok = 1;
702*6b5e5868SGarrett D'Amore 			if (tokidx) {
703*6b5e5868SGarrett D'Amore 				/* an escape mid-token is nonsense */
704*6b5e5868SGarrett D'Amore 				return (T_NULL);
705*6b5e5868SGarrett D'Amore 			}
706*6b5e5868SGarrett D'Amore 
707*6b5e5868SGarrett D'Amore 			/* numeric escapes are treated as wide characters */
708*6b5e5868SGarrett D'Amore 			if (strchr("xXd01234567", c)) {
709*6b5e5868SGarrett D'Amore 				unscanc(c);
710*6b5e5868SGarrett D'Amore 				unscanc(esc_char);
711*6b5e5868SGarrett D'Amore 				return (get_wide());
712*6b5e5868SGarrett D'Amore 			}
713*6b5e5868SGarrett D'Amore 
714*6b5e5868SGarrett D'Amore 			add_tok(get_escaped(c));
715*6b5e5868SGarrett D'Amore 			continue;
716*6b5e5868SGarrett D'Amore 		}
717*6b5e5868SGarrett D'Amore 
718*6b5e5868SGarrett D'Amore 		/* if it is the escape charter itself note it */
719*6b5e5868SGarrett D'Amore 		if (c == esc_char) {
720*6b5e5868SGarrett D'Amore 			escaped = 1;
721*6b5e5868SGarrett D'Amore 			continue;
722*6b5e5868SGarrett D'Amore 		}
723*6b5e5868SGarrett D'Amore 
724*6b5e5868SGarrett D'Amore 		/* remove from the comment char to end of line */
725*6b5e5868SGarrett D'Amore 		if (c == com_char) {
726*6b5e5868SGarrett D'Amore 			while (c != '\n') {
727*6b5e5868SGarrett D'Amore 				if ((c = scanc()) == EOF) {
728*6b5e5868SGarrett D'Amore 					/* end of file without newline! */
729*6b5e5868SGarrett D'Amore 					return (EOF);
730*6b5e5868SGarrett D'Amore 				}
731*6b5e5868SGarrett D'Amore 			}
732*6b5e5868SGarrett D'Amore 			assert(c == '\n');
733*6b5e5868SGarrett D'Amore 			if (!hadtok) {
734*6b5e5868SGarrett D'Amore 				/*
735*6b5e5868SGarrett D'Amore 				 * If there were no tokens on this line,
736*6b5e5868SGarrett D'Amore 				 * then just pretend it didn't exist at all.
737*6b5e5868SGarrett D'Amore 				 */
738*6b5e5868SGarrett D'Amore 				continue;
739*6b5e5868SGarrett D'Amore 			}
740*6b5e5868SGarrett D'Amore 			hadtok = 0;
741*6b5e5868SGarrett D'Amore 			return (T_NL);
742*6b5e5868SGarrett D'Amore 		}
743*6b5e5868SGarrett D'Amore 
744*6b5e5868SGarrett D'Amore 		if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) {
745*6b5e5868SGarrett D'Amore 			/*
746*6b5e5868SGarrett D'Amore 			 * These are all token delimiters.  If there
747*6b5e5868SGarrett D'Amore 			 * is a token already in progress, we need to
748*6b5e5868SGarrett D'Amore 			 * process it.
749*6b5e5868SGarrett D'Amore 			 */
750*6b5e5868SGarrett D'Amore 			unscanc(c);
751*6b5e5868SGarrett D'Amore 			return (consume_token());
752*6b5e5868SGarrett D'Amore 		}
753*6b5e5868SGarrett D'Amore 
754*6b5e5868SGarrett D'Amore 		switch (c) {
755*6b5e5868SGarrett D'Amore 		case '\n':
756*6b5e5868SGarrett D'Amore 			if (!hadtok) {
757*6b5e5868SGarrett D'Amore 				/*
758*6b5e5868SGarrett D'Amore 				 * If the line was completely devoid of tokens,
759*6b5e5868SGarrett D'Amore 				 * then just ignore it.
760*6b5e5868SGarrett D'Amore 				 */
761*6b5e5868SGarrett D'Amore 				continue;
762*6b5e5868SGarrett D'Amore 			}
763*6b5e5868SGarrett D'Amore 			/* we're starting a new line, reset the token state */
764*6b5e5868SGarrett D'Amore 			hadtok = 0;
765*6b5e5868SGarrett D'Amore 			return (T_NL);
766*6b5e5868SGarrett D'Amore 		case ',':
767*6b5e5868SGarrett D'Amore 			hadtok = 1;
768*6b5e5868SGarrett D'Amore 			return (T_COMMA);
769*6b5e5868SGarrett D'Amore 		case ';':
770*6b5e5868SGarrett D'Amore 			hadtok = 1;
771*6b5e5868SGarrett D'Amore 			return (T_SEMI);
772*6b5e5868SGarrett D'Amore 		case '(':
773*6b5e5868SGarrett D'Amore 			hadtok = 1;
774*6b5e5868SGarrett D'Amore 			return (T_LPAREN);
775*6b5e5868SGarrett D'Amore 		case ')':
776*6b5e5868SGarrett D'Amore 			hadtok = 1;
777*6b5e5868SGarrett D'Amore 			return (T_RPAREN);
778*6b5e5868SGarrett D'Amore 		case '>':
779*6b5e5868SGarrett D'Amore 			hadtok = 1;
780*6b5e5868SGarrett D'Amore 			return (T_GT);
781*6b5e5868SGarrett D'Amore 		case '<':
782*6b5e5868SGarrett D'Amore 			/* symbol start! */
783*6b5e5868SGarrett D'Amore 			hadtok = 1;
784*6b5e5868SGarrett D'Amore 			return (get_symbol());
785*6b5e5868SGarrett D'Amore 		case ' ':
786*6b5e5868SGarrett D'Amore 		case '\t':
787*6b5e5868SGarrett D'Amore 			/* whitespace, just ignore it */
788*6b5e5868SGarrett D'Amore 			continue;
789*6b5e5868SGarrett D'Amore 		case '"':
790*6b5e5868SGarrett D'Amore 			hadtok = 1;
791*6b5e5868SGarrett D'Amore 			instring = 1;
792*6b5e5868SGarrett D'Amore 			return (T_QUOTE);
793*6b5e5868SGarrett D'Amore 		default:
794*6b5e5868SGarrett D'Amore 			hadtok = 1;
795*6b5e5868SGarrett D'Amore 			add_tok(c);
796*6b5e5868SGarrett D'Amore 			continue;
797*6b5e5868SGarrett D'Amore 		}
798*6b5e5868SGarrett D'Amore 	}
799*6b5e5868SGarrett D'Amore 	return (EOF);
800*6b5e5868SGarrett D'Amore }
801*6b5e5868SGarrett D'Amore 
802*6b5e5868SGarrett D'Amore void
803*6b5e5868SGarrett D'Amore yyerror(const char *msg)
804*6b5e5868SGarrett D'Amore {
805*6b5e5868SGarrett D'Amore 	(void) fprintf(stderr, _("%s: %d: error: %s\n"),
806*6b5e5868SGarrett D'Amore 	    filename, lineno, msg);
807*6b5e5868SGarrett D'Amore 	exit(4);
808*6b5e5868SGarrett D'Amore }
809*6b5e5868SGarrett D'Amore 
810*6b5e5868SGarrett D'Amore void
811*6b5e5868SGarrett D'Amore errf(const char *fmt, ...)
812*6b5e5868SGarrett D'Amore {
813*6b5e5868SGarrett D'Amore 	char	*msg;
814*6b5e5868SGarrett D'Amore 
815*6b5e5868SGarrett D'Amore 	va_list	va;
816*6b5e5868SGarrett D'Amore 	va_start(va, fmt);
817*6b5e5868SGarrett D'Amore 	(void) vasprintf(&msg, fmt, va);
818*6b5e5868SGarrett D'Amore 	va_end(va);
819*6b5e5868SGarrett D'Amore 
820*6b5e5868SGarrett D'Amore 	(void) fprintf(stderr, _("%s: %d: error: %s\n"),
821*6b5e5868SGarrett D'Amore 	    filename, lineno, msg);
822*6b5e5868SGarrett D'Amore 	free(msg);
823*6b5e5868SGarrett D'Amore 	exit(4);
824*6b5e5868SGarrett D'Amore }
825*6b5e5868SGarrett D'Amore 
826*6b5e5868SGarrett D'Amore void
827*6b5e5868SGarrett D'Amore warn(const char *fmt, ...)
828*6b5e5868SGarrett D'Amore {
829*6b5e5868SGarrett D'Amore 	char	*msg;
830*6b5e5868SGarrett D'Amore 
831*6b5e5868SGarrett D'Amore 	va_list	va;
832*6b5e5868SGarrett D'Amore 	va_start(va, fmt);
833*6b5e5868SGarrett D'Amore 	(void) vasprintf(&msg, fmt, va);
834*6b5e5868SGarrett D'Amore 	va_end(va);
835*6b5e5868SGarrett D'Amore 
836*6b5e5868SGarrett D'Amore 	(void) fprintf(stderr, _("%s: %d: warning: %s\n"),
837*6b5e5868SGarrett D'Amore 	    filename, lineno, msg);
838*6b5e5868SGarrett D'Amore 	free(msg);
839*6b5e5868SGarrett D'Amore 	warnings++;
840*6b5e5868SGarrett D'Amore 	if (!warnok)
841*6b5e5868SGarrett D'Amore 		exit(4);
842*6b5e5868SGarrett D'Amore }
843