xref: /netbsd-src/external/bsd/pcc/dist/pcc/cc/cxxcom/scan.l (revision 479d8f7d843cc1b22d497efdf1f27a50ee8418d4)
1 %{
2 /*	Id: scan.l,v 1.6 2015/11/13 11:33:14 ragge Exp 	*/
3 /*	$NetBSD: scan.l,v 1.1.1.3 2016/02/09 20:29:02 plunky Exp $	*/
4 
5 /*
6  * Copyright (c) 2002 Anders Magnusson. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 %}
31 
32 
33 D			[0-9]
34 L			[a-zA-Z_]
35 H			[a-fA-F0-9]
36 E			[Ee][+-]?{D}+
37 P			[Pp][+-]?{D}+
38 FS			(f|F|l|L)?i?
39 IS			(u|U|l|L)*
40 UL			({L}|\\u{H}{H}{H}{H}|\\U{H}{H}{H}{H}{H}{H}{H}{H})
41 
42 %{
43 #include <stdlib.h>
44 #include <errno.h>
45 #include <string.h>
46 #include <stdarg.h>
47 #include <ctype.h>
48 
49 #include "pass1.h"
50 #include "cgram.h"
51 
52 static NODE *cvtdig(int radix);
53 static NODE *charcon(void);
54 static NODE *wcharcon(void);
55 static void control(int);
56 static void pragma(void);
57 int notype, parbal, inattr, parlvl, nodinit, inoso;
58 static int resw(TWORD, int);
59 static int namechk(void);
60 
61 #define	CPP_IDENT 	2
62 #define	CPP_LINE 	3
63 #define	CPP_HASH	4
64 
65 #ifdef STABS
66 #define	STABS_LINE(x) if (gflag && cftnsp) stabs_line(x)
67 #else
68 #define STABS_LINE(x)
69 #endif
70 #if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION == 31
71 /* Hack to avoid unnecessary warnings */
72 FILE *yyget_in  (void);
73 FILE *yyget_out  (void);
74 int yyget_leng  (void);
75 char *yyget_text  (void);
76 void yyset_in (FILE *);
77 void yyset_out (FILE *);
78 int yyget_debug  (void);
79 void yyset_debug (int);
80 int yylex_destroy  (void);
81 extern int yyget_lineno (void);
82 extern void yyset_lineno (int);
83 #endif
84 
85 %}
86 
87 %%
88 
89 "__func__"		{
90 				if (cftnsp == NULL)
91 					uerror("__func__ outside function");
92 				yylval.strp = cftnsp->sname; /* XXX - not C99 */
93 				return(C_STRING);
94 			}
95 "asm"			{ return(C_ASM); }
96 "auto"			{ 	return resw(AUTO, C_CLASS); }
97 "_Bool"			{ 	return resw(BOOL, C_TYPE); }
98 "break"			{ return(C_BREAK); }
99 "case"			{ return(C_CASE); }
100 "char"			{ 	return resw(CHAR, C_TYPE); }
101 "class"			{ yylval.intval = CLNAME; notype=1; return(C_STRUCT); }
102 "_Complex"		{ 	return resw(COMPLEX, C_TYPE); }
103 "const"			{ 	return resw(CON, C_QUALIFIER); }
104 "const_cast"		{ yylval.intval = CONST_CAST; return(CXX_CASTS); }
105 "continue"		{ return(C_CONTINUE); }
106 "default"		{ return(C_DEFAULT); }
107 "delete"		{ return(CXX_DELETE); }
108 "do"			{ return(C_DO); }
109 "double"		{ 	return resw(DOUBLE, C_TYPE); }
110 "dynamic_cast"		{ yylval.intval = DYN_CAST; return(CXX_CASTS); }
111 "else"			{ return(C_ELSE); }
112 "enum"			{ notype=1; return(C_ENUM); }
113 "extern"		{ 	return resw(EXTERN, C_CLASS); }
114 "float"			{ 	return resw(FLOAT, C_TYPE); }
115 "for"			{ return(C_FOR); }
116 "goto"			{ notype=1; return(C_GOTO); }
117 "if"			{ return(C_IF); }
118 "_Imaginary"		{ 	return resw(IMAG, C_TYPE); }
119 "inline"		{ return(C_FUNSPEC); }
120 "int"			{ 	return resw(INT, C_TYPE); }
121 "long"			{ 	return resw(LONG, C_TYPE); }
122 "namespace"		{ 	return(CXX_NAMESPACE); }
123 "new"			{ 	notype = 0; return(CXX_NEW); }
124 "register"		{ 	return resw(REGISTER, C_CLASS); }
125 "reinterpret_cast"	{ yylval.intval = REINT_CAST; return(CXX_CASTS); }
126 "restrict"		{ ; /* just ignore */ }
127 "return"		{ return(C_RETURN); }
128 "short"			{ 	return resw(SHORT, C_TYPE); }
129 "signed"		{ 	return resw(SIGNED, C_TYPE); }
130 "sizeof"		{ return(C_SIZEOF); }
131 "static"		{ 	return resw(STATIC, C_CLASS); }
132 "static_cast"		{ yylval.intval = STATIC_CAST; return(CXX_CASTS); }
133 "struct"		{ yylval.intval = STNAME; notype=1; return(C_STRUCT); }
134 "switch"		{ return(C_SWITCH); }
135 "template"		{ return(CXX_TEMPLATE); }
136 "typedef"		{ 	return resw(TYPEDEF, C_CLASS); }
137 "typename"		{ return(CXX_TYPENAME); }
138 "union"			{ yylval.intval = UNAME; notype=1; return(C_STRUCT); }
139 "unsigned"		{ 	return resw(UNSIGNED, C_TYPE); }
140 "using"			{ return(CXX_USING); }
141 "void"			{ 	return resw(VOID, C_TYPE); }
142 "volatile"		{	return resw(VOL, C_QUALIFIER); }
143 "while"			{ return(C_WHILE); }
144 
145 {UL}({UL}|{D})*		{ return namechk(); }
146 0[xX]{H}+{IS}?		{ yylval.nodep = cvtdig(16); return(C_ICON); }
147 0{D}+{IS}?		{ yylval.nodep = cvtdig(8); return(C_ICON); }
148 {D}+{IS}?		{ yylval.nodep = cvtdig(10); return(C_ICON); }
149 L'(\\.|[^\\'])*'	{ yylval.nodep = wcharcon(); return(C_ICON); }
150 '(\\.|[^\\'])*'		{ yylval.nodep = charcon(); return(C_ICON); }
151 
152 {D}+{E}{FS}?		{ yylval.nodep = floatcon(yytext); return(C_FCON); }
153 {D}*"."{D}+({E})?{FS}?	{ yylval.nodep = floatcon(yytext); return(C_FCON); }
154 {D}+"."{D}*({E})?{FS}?	{ yylval.nodep = floatcon(yytext); return(C_FCON); }
155 0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
156 0[xX]{H}+"."{P}{FS}?	{ yylval.nodep = fhexcon(yytext); return(C_FCON); }
157 0[xX]{H}+{P}{FS}?	{ yylval.nodep = fhexcon(yytext); return(C_FCON); }
158 
159 L?\"(\\.|[^\\"])*\"	{ yylval.strp = yytext; return C_STRING; }
160 
161 "..."			{ return(C_ELLIPSIS); }
162 ">>="			{ yylval.intval = RSEQ; return(C_ASOP); }
163 "<<="			{ yylval.intval = LSEQ; return(C_ASOP); }
164 "+="			{ yylval.intval = PLUSEQ; return(C_ASOP); }
165 "-="			{ yylval.intval = MINUSEQ; return(C_ASOP); }
166 "*="			{ yylval.intval = MULEQ; return(C_ASOP); }
167 "/="			{ yylval.intval = DIVEQ; return(C_ASOP); }
168 "%="			{ yylval.intval = MODEQ; return(C_ASOP); }
169 "&="			{ yylval.intval = ANDEQ; return(C_ASOP); }
170 "^="			{ yylval.intval = EREQ; return(C_ASOP); }
171 "|="			{ yylval.intval = OREQ; return(C_ASOP); }
172 ">>"			{ yylval.intval = RS; return(C_SHIFTOP); }
173 "<<"			{ yylval.intval = LS; return(C_SHIFTOP); }
174 "++"			{ yylval.intval = INCR; return(C_INCOP); }
175 "--"			{ yylval.intval = DECR; return(C_INCOP); }
176 "->"			{ yylval.intval = STREF; return(C_STROP); }
177 "&&"			{ yylval.intval = ANDAND; return(C_ANDAND); }
178 "||"			{ yylval.intval = OROR; return(C_OROR); }
179 "<="			{ yylval.intval = LE; return(C_RELOP); }
180 ">="			{ yylval.intval = GE; return(C_RELOP); }
181 "=="			{ yylval.intval = EQ; return(C_EQUOP); }
182 "!="			{ yylval.intval = NE; return(C_EQUOP); }
183 "::"			{ return(CXX_DUALCC); }
184 ";"			{ notype = 0; return(';'); }
185 ("{"|"<%")		{ notype = 0; return('{'); }
186 ("}"|"%>")		{ if (rpole) notype = 1; return('}'); }
187 ","			{ if (parbal && !inoso) notype = 0; return(','); }
188 ":"			{ if (doing_init) nodinit--; return(':'); }
189 "="			{ return('='); }
190 "("			{ parbal++; notype = 0; return('('); }
191 ")"			{	parbal--;
192 				inoso = 0;
193 				if (parbal==0) { notype = 0; }
194 				if (inattr && parlvl == parbal)
195 					inattr = 0;
196 				return(')'); }
197 ("["|"<:")		{ return('['); }
198 ("]"|":>")		{ return(']'); }
199 "."			{ yylval.intval = DOT; return(C_STROP); }
200 "&"			{ return('&'); }
201 "!"			{ yylval.intval = NOT; return(C_UNOP); }
202 "~"			{ yylval.intval = COMPL; return(C_UNOP); }
203 "-"			{ return('-'); }
204 "+"			{ return('+'); }
205 "*"			{ if (parbal && notype == 0) notype = 1; return('*'); }
206 "/"			{ yylval.intval = DIV; return(C_DIVOP); }
207 "%"			{ yylval.intval = MOD; return(C_DIVOP); }
208 "<"			{ yylval.intval = LT; return(C_RELOP); }
209 ">"			{ yylval.intval = GT; return(C_RELOP); }
210 "^"			{ return('^'); }
211 "|"			{ return('|'); }
212 "?"			{ if (doing_init) nodinit++; return('?'); }
213 ^#pragma[ \t].*		{ pragma(); }
214 ^#ident[ \t].*		{ control(CPP_IDENT); }
215 ^#line[ \t].*		{ control(CPP_LINE); }
216 ^#.*			{ control(CPP_HASH); }
217 
218 [ \t\v\f]		{ }
219 "\n"			{ ++lineno; STABS_LINE(lineno); }
220 .			{ /* ignore bad characters */ }
221 
222 %%
223 
224 int lineno, issyshdr;
225 char *ftitle = "<stdin>";
226 
227 static int
228 namechk(void)
229 {
230 	struct symtab *s;
231 	int i;
232 
233 	yylval.strp = addname(yytext);
234 
235 	while ((i = input()) == ' ' || i == '\t')
236 		;
237 	if (i == ':') {
238 		if ((i = input()) == ':')
239 			return CXX_MORENM;
240 		unput(i);
241 		if (doing_init && nodinit == 0)
242 			return(GCC_DESIG);
243 		i = ':';
244 	}
245 	unput(i);
246 
247 #ifdef GCC_COMPAT
248 	if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0)
249 		return i;
250 #endif
251 
252 	if (notype)
253 		return(C_NAME);
254 	s = lookup(yylval.strp, SNOCREAT);
255 	return s && s->sclass == TYPEDEF ?  notype=1, C_TYPENAME : C_NAME;
256 }
257 
258 int
259 yywrap(void)
260 {
261 	if (0) unput(0); /* quiet gcc */
262 	return(1);
263 }
264 
265 int
266 resw(TWORD t, int rv)
267 {
268 	if (inattr) {
269 		yylval.strp = addname(yytext);
270 		return C_NAME;
271 	}
272 
273 	switch (rv) {
274 	case C_CLASS:
275 		yylval.nodep = block(CLASS, NIL, NIL, t, 0, 0);
276 		return rv;
277 
278 	case C_QUALIFIER:
279 		yylval.nodep = block(QUALIFIER, NIL, NIL, 0, 0, 0);
280 		yylval.nodep->n_qual = t;
281 		return rv;
282 
283 	case C_TYPE:
284 		yylval.nodep = mkty(t, 0, 0);
285 		notype=1;
286 		return(rv);
287 
288 	default:
289 		cerror("resw");
290 	}
291 	return 0;
292 }
293 
294 #ifndef SOFTFLOAT
295 
296 static long double
297 typround(long double dc, char *e, TWORD *tw)
298 {
299 	int im = 0;
300 
301 	*tw = DOUBLE;
302 	for (; *e; e++) {
303 		switch (*e) {
304 		case 'f':
305 		case 'F':
306 			*tw = FLOAT;
307 			dc = (float)dc;
308 			break;
309 		case 'l':
310 		case 'L':
311 			*tw = LDOUBLE;
312 			break;
313 		case 'i':
314 		case 'I':
315 			im = 1;
316 			break;
317 		}
318 	}
319 	if (*tw == DOUBLE)
320 		dc = (double)dc;
321 #ifndef NO_COMPLEX
322 	if (im)
323 		*tw += (FIMAG-FLOAT);
324 #endif
325 	return dc;
326 }
327 
328 /*
329  * XXX floatcon() and fhexcon() should be in support libraries for
330  * the target floating point.
331  */
332 static NODE *
333 f2(char *str)
334 {
335 	TWORD tw;
336 	NODE *p;
337 	long double dc;
338 	char *eptr;
339 
340 #ifdef HAVE_STRTOLD
341 	dc = strtold(str, &eptr); /* XXX - avoid strtod() */
342 #else
343 	dc = strtod(str, &eptr); /* XXX - avoid strtod() */
344 #endif
345 	dc = typround(dc, eptr, &tw);
346 	p = block(FCON, NIL, NIL, tw, 0, 0);
347 	p->n_dcon = tmpalloc(sizeof(union flt));;
348 	((union flt *)p->n_dcon)->fp = dc;
349 	return p;
350 }
351 
352 NODE *
353 floatcon(char *s)
354 {
355 	return f2(s);
356 }
357 
358 static int
359 h2n(int ch)
360 {
361 	if (ch >= '0' && ch <= '9')
362 		return ch - '0';
363 	if (ch >= 'a' && ch <= 'f')
364 		return ch - 'a' + 10;
365 	return ch - 'A' + 10;
366 
367 }
368 
369 NODE *
370 fhexcon(char *c)
371 {
372 	TWORD tw;
373 	char *ep;
374 	long double d;
375 	int i, ed;
376 	NODE *p;
377 
378 	d = 0.0;
379 	ed = 0;
380 	c+= 2; /* skip 0x */
381 #define FSET(n) { d *= 2; if (i & n) d += 1.0; }
382 	for (; *c != '.' && *c != 'p' && *c != 'P'; c++) {
383 		i = h2n(*c);
384 		FSET(8); FSET(4); FSET(2); FSET(1);
385 	}
386 	if (*c != '.' && *c != 'p' && *c != 'P')
387 		cerror("fhexcon");
388 	if (*c == '.') {
389 		c++;
390 		for (; *c != 'p' && *c != 'P'; c++) {
391 			i = h2n(*c);
392 			FSET(8); FSET(4); FSET(2); FSET(1);
393 			ed -= 4;
394 		}
395 	}
396 	if (*c != 'P' && *c != 'p')
397 		cerror("fhexcon2");
398 	c++;
399 	ed += strtol(c, &ep, 10);
400 
401 	/* avoid looping in vain. Idea from Fred J. Tydeman */
402 	if (ed > 32769) ed = 32769;
403 	if (ed < -32769) ed = -32769;
404 
405 	while (ed > 0)
406 		d *= 2, ed--;
407 	while (ed < 0)
408 		d /= 2, ed++;
409 	d = typround(d, ep, &tw);
410 	p = block(FCON, NIL, NIL, tw, 0, 0);
411 	p->n_dcon = tmpalloc(sizeof(union flt));;
412 	((union flt *)p->n_dcon)->fp = d;
413 	return p;
414 }
415 #endif
416 
417 unsigned int
418 esccon(char **sptr)
419 {
420 	char *wr = *sptr;
421 	char *owr;
422 	char c;
423 	unsigned int val;
424 	int wsz = 4, esccon_warn = 1;
425 
426 	switch (*wr++) {
427 	case 'a': val = '\a'; break;
428 	case 'b': val = '\b'; break;
429 	case 'f': val = '\f'; break;
430 	case 'n': val = '\n'; break;
431 	case 'r': val = '\r'; break;
432 	case 't': val = '\t'; break;
433 	case 'v': val = '\v'; break;
434 	case '\"': val = '\"'; break;
435 	case 'x': val = strtoul(wr, &wr, 16); break;
436 	/* ISO/IEC 9099:1999 (E) 6.4.3 */
437 	case 'U'|(char)0x80:
438 		esccon_warn = 0;
439 		/* FALLTHROUGH */
440 	case 'U':
441 		wsz = 8;
442 		/* FALLTHROUGH */
443 	case 'u':
444 		owr = wr;
445 		while (wr < (owr + wsz))
446 			if (*wr == '\0')
447 				break;
448 			else
449 				++wr;
450 		if (wr != (owr + wsz)) {
451 			/* incomplete */
452 			val = strtoul(owr, &wr, 16);
453 		} else {
454 			c = owr[wsz];
455 			owr[wsz] = '\0'; /* prevent it from reading too much */
456 			val = strtoul(owr, &wr, 16);
457 			owr[wsz] = c;
458 		}
459 		if (wr != (owr + wsz))
460 			werror("incomplete universal character name");
461 		if (wsz == 4)
462 			val &= 0xFFFF;
463 		if (esccon_warn && ((val >= 0xD800 && val <= 0xDFFF) ||
464 		    (val < 0xA0 && val != 0x24 && val != 0x40 && val != 0x60)))
465 			werror("invalid universal character name %04X", val);
466 		break;
467 	case '0': case '1': case '2': case '3': case '4':
468 	case '5': case '6': case '7':
469 		val = wr[-1] - '0';
470 		if (*wr >= '0' && *wr <= '7') {
471 			val = (val << 3) + (*wr++ - '0');
472 			if (*wr >= '0' && *wr <= '7')
473 				val = (val << 3) + (*wr++ - '0');
474 		}
475 		break;
476 	default: val = wr[-1];
477 	}
478 	*sptr = wr;
479 	return val;
480 }
481 
482 NODE *
483 cvtdig(int radix)
484 {
485 	NODE *p;
486 	TWORD otype, ntype;
487 	unsigned long long v;
488 	char *ch = yytext;
489 	int n, numl, numu;
490 
491 	if (radix == 16)
492 		ch += 2; /* Skip 0x */
493 
494 	v = 0;
495 	while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') ||
496 	    (*ch >= 'A' && *ch <= 'F')) {
497 		v *= radix;
498 		n = *ch;
499 		n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10);
500 		ch++;
501 		v += n;
502 	}
503 	/* Parse trailing chars */
504 	ntype = INT;
505 	numl = numu = 0;
506 	for (n = 0; n < 3; n++) {
507 		if (*ch == 0)
508 			break;
509 		if ((*ch == 'l' || *ch == 'L') && numl < 2)
510 			ntype+=2, numl++;
511 		else if ((*ch == 'u' || *ch == 'U') && numu < 1)
512 			ntype = ENUNSIGN(ntype), numu++;
513 		else
514 			break;
515 		ch++;
516 	}
517 	if (*ch)
518 		uerror("constant has too many '%c'", *ch);
519 
520 	otype = ntype;
521 	switch (ntype) {
522 	case INT:
523 	case LONG:
524 	case LONGLONG:
525 		if (radix == 10) {
526 			if (otype == LONGLONG)
527 				break;
528 			if (v > MAX_LONG) {
529 				ntype = LONGLONG;
530 				if (otype == LONG)
531 					break;
532 			} else if (v > MAX_INT)
533 				ntype = LONG;
534 		} else {
535 			if (v > MAX_LONGLONG) {
536 				ntype = ULONGLONG;
537 				if (otype == LONGLONG)
538 					break;
539 			} else if (v > MAX_ULONG) {
540 				ntype = LONGLONG;
541 			} else if (v > MAX_LONG) {
542 				ntype = ULONG;
543 				if (otype == LONG)
544 					break;
545 			} else if (v > MAX_UNSIGNED) {
546 				ntype = LONG;
547 			} else if (v > MAX_INT)
548 				ntype = UNSIGNED;
549 		}
550 		break;
551 	case UNSIGNED:
552 	case ULONG:
553 		if (v > MAX_ULONG) {
554 			ntype = ULONGLONG;
555 			if (otype == ULONG)
556 				break;
557 		} else if (v > MAX_UNSIGNED)
558 			ntype = ULONG;
559 		break;
560 	}
561 
562 	ntype = ctype(ntype);
563 	p = xbcon(v, NULL, ntype);
564 	ASGLVAL(p->n_slval, v);
565 
566 	return p;
567 }
568 
569 /*
570  * Convert a character constant to an integer.
571  */
572 NODE *
573 charcon(void)
574 {
575 	int lastcon = 0;
576 	int val, i = 0;
577 	char *pp = yytext;
578 
579 	pp++;	/* skip ' */
580 	while (*pp != '\'') {
581 		if (*pp++ == '\\') {
582 			val = esccon(&pp);
583 		} else
584 			val = pp[-1];
585 		makecc(val, i);
586 		i++;
587 	}
588 
589 	if (i == 0)
590 		uerror("empty character constant");
591 	else if (i > (SZINT/SZCHAR) || (i>1))
592 		werror("too many characters in character constant");
593 	return bcon(lastcon);
594 }
595 
596 NODE *
597 wcharcon(void)
598 {
599 	unsigned int lastcon = 0;
600 	unsigned int val, i = 0;
601 	char *pp = yytext;
602 
603 	pp++;	/* skip L */
604 	pp++;	/* skip ' */
605 	while (*pp != '\'') {
606 		if (*pp++ == '\\') {
607 			val = esccon(&pp);
608 		} else
609 			val = pp[-1];
610 #if WCHAR_SIZE == 2
611 		lastcon = (lastcon << 16) | (val & 0xFFFF);
612 #else
613 		lastcon = val;
614 #endif
615 		i++;
616 	}
617 
618 	if (i == 0)
619 		uerror("empty wide-character constant");
620 	else if (i > 1)
621 		werror("too many characters in wide-character constant");
622 	return xbcon(lastcon, NULL, ctype(UNSIGNED));
623 }
624 
625 void
626 control(int t)
627 {
628 	char *wr = yytext;
629 	char *eptr;
630 	int val;
631 
632 	wr++;	/* Skip initial '#' */
633 	switch (t) {
634 	case CPP_IDENT:
635 		return;	/* Just skip these for now. */
636 
637 	case CPP_LINE:
638 		wr += 4;
639 		/* FALLTHROUGH */
640 	case CPP_HASH:
641 		val = strtol(wr, &eptr, 10);
642 		if (wr == eptr)	/* Illegal string */
643 			goto bad;
644 		wr = eptr;
645 		lineno = val - 1;
646 		while (*wr && *wr != '\"')
647 			wr++;
648 		if (*wr == 0)
649 			return;
650 		if (*wr++ != '\"')
651 			goto bad;
652 		eptr = wr;
653 		while (*wr && *wr != '\"')
654 			wr++;
655 		if (*wr != '\"')
656 			goto bad;
657 		*wr = 0;
658 		ftitle = addstring(eptr);
659 #ifdef STABS
660 		if (gflag)
661 			stabs_file(ftitle);
662 #endif
663 	}
664 	return;
665 bad:
666 	werror("%s: illegal control", yytext);
667 }
668 
669 int pragma_allpacked;
670 int pragma_packed, pragma_aligned;
671 char *pragma_renamed;
672 
673 static int
674 pragmas_weak(char *str)
675 {
676 	struct symtab *sp;
677 	char *s1, *s2;
678 
679 	if ((s1 = pragtok(NULL)) == NULL)
680 		return 1;
681 	if ((s2 = pragtok(NULL)) == NULL) {
682 		sp = lookup(addname(s1), SNORMAL);
683 #ifdef GCC_COMPAT
684 		sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(NAME, "weak")));
685 #else
686 		sp->sap = 0;
687 #endif
688 	} else if (*s2 == '=') {
689 		if ((s2 = pragtok(NULL)) == NULL)
690 			return 1;
691 		sp = lookup(addname(s2), SNORMAL);
692 #ifdef GCC_COMPAT
693 		sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(CALL,
694 		    bdty(NAME, "aliasweak"), bdty(STRING, s1, 0))));
695 #else
696 		sp->sap = NULL;
697 #endif
698 	} else
699 		return 1;
700 	return 0;
701 }
702 
703 char *pragstore;
704 
705 /* trivial tokenizer for pragmas */
706 #define ps pragstore
707 char *
708 pragtok(char *sin)
709 {
710 	static char ss[2];
711 	char *rv;
712 
713 	if (sin)
714 		ps = sin;
715 
716 	for (; isspace((int)*ps); ps++)
717 		;
718 	if (*ps == 0)
719 		return NULL;
720 	for (rv = ps; isalpha((int)*ps) || isdigit((int)*ps) || *ps == '_'; ps++)
721 		;
722 	ss[0] = *ps;
723 	if (rv == ps) {
724 		rv = ss, ps++;
725 	} else {
726 		*ps = 0;
727 		rv = tmpstrdup(rv);
728 		*ps = ss[0];
729 	}
730 	return rv;
731 }
732 
733 /* return 1 on error */
734 int
735 eat(int ch)
736 {
737 	char *s = pragtok(0);
738 	return (s == 0 || *s != ch);
739 }
740 
741 static int
742 pragmas_alpack(char *t)
743 {
744 	char *s;
745 	int ap;
746 
747 	ap = (s = pragtok(0)) ? atoi(s) : 1;
748 	if (strcmp(t, "packed") == 0)
749 		pragma_packed = ap;
750 	else
751 		pragma_aligned = ap;
752 	return 0;
753 }
754 
755 
756 /*
757  * Packing control.
758  * still missing push/pop.
759  */
760 static int
761 pragmas_pack(char *t)
762 {
763 	char *s;
764 
765 	if (eat('('))
766 		return 1;
767 	s = pragtok(0);
768 	if (*s == ')')
769 		return pragma_allpacked = 0;
770 
771 	if (*s < '0' || *s > '9') /* no number */
772 		return 1;
773 	pragma_allpacked = atoi(s);
774 	return eat(')');
775 }
776 
777 static int
778 pragmas_renamed(char *t)
779 {
780 	char *f = pragtok(0);
781 
782 	if (f == 0)
783 		return 1;
784 	pragma_renamed = newstring(f, strlen(f));
785 	return 0;
786 }
787 
788 static int
789 pragmas_stdc(char *t)
790 {
791 	return 0; /* Just ignore */
792 }
793 
794 struct pragmas {
795 	char *name;
796 	int (*fun)(char *);
797 } pragmas[] = {
798 	{ "pack", pragmas_pack },
799 	{ "packed", pragmas_alpack },
800 	{ "aligned", pragmas_alpack },
801 	{ "rename", pragmas_renamed },
802 #ifdef GCC_COMPAT
803 	{ "GCC", pragmas_gcc },
804 #endif
805 	{ "STDC", pragmas_stdc },
806 	{ "weak", pragmas_weak },
807 	{ "ident", NULL },
808 	{ 0 },
809 };
810 
811 /*
812  * got a full pragma line.  Split it up here.
813  */
814 static void
815 pragma(void)
816 {
817 	struct pragmas *p;
818 	char *t, *pt;
819 
820 	if ((t = pragtok(&yytext[7])) != NULL) {
821 		pt = ps;
822 		for (p = pragmas; p->name; p++) {
823 			if (strcmp(t, p->name) == 0) {
824 				if (p->fun && (*p->fun)(t))
825 					uerror("bad argument to #pragma");
826 				return;
827 			}
828 		}
829 		ps = pt;
830 		if (mypragma(t))
831 			return;
832 	}
833 	warner(Wunknown_pragmas, t, ps);
834 }
835 
836 void
837 cunput(char c)
838 {
839 	unput(c);
840 }
841