]> andersk Git - splint.git/blame - src/cscanner.l
*** empty log message ***
[splint.git] / src / cscanner.l
CommitLineData
885824d3 1/*;-*-C-*-;
2** Copyright (c) Massachusetts Institute of Technology 1994-1998.
3** All Rights Reserved.
4** Unpublished rights reserved under the copyright laws of
5** the United States.
6**
7** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9**
10** This code is distributed freely and may be used freely under the
11** following conditions:
12**
13** 1. This notice may not be removed or altered.
14**
15** 2. Works derived from this code are not distributed for
16** commercial gain without explicit permission from MIT
17** (for permission contact lclint-request@sds.lcs.mit.edu).
18*/
19/*
20 * Modified by Herbert 08/19/97:
21 * - added #include for IBM's OS/2 compiler.
22 * - fixed weird bug with lookup of tmp files (OS/2 and MSDOS only).
23 */
24
25/*
26 * Modified by Mike Smith
27 * Corrected missing 'line' in scanf() calls in handleSpecial().
28 * Without this, I get an error when LCLint hits a '#line' directive
29 * in the pre-pre-processed source files. For safety, I have made these
30 * conditional on OS2 and MSDOS because I don't understand why noone else
31 * has seen this problem.
32 *
33 * Modified by Mike Smith, 4th June 1997
34 * Finally resolved the #line problem. The scanf() calls have been fixed to
35 * allow the following #line forms:-
36 *
37 * #line 123 "filename"
38 * #line 123
39 * # 123 "filename"
40 * # 123
41 *
42 * The last two are generated by the GNU pre-processor, apparently
43 */
44
45Digit [0-9]
46Letter [a-zA-Z_$]
47H [a-fA-F0-9]
48E [Ee][+-]?{Digit}+
49U (u|U)
50L (l|L)
51FS (f|F|l|L)
52IS (u|U|l|L)*
53ULSuffix ({U}{L}|{L}{U})
54
55%{
56/*
57** based on original C lexer by Nate Osgood
58** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993
59**
60*/
61
62# include "lclintMacros.nf"
63# include "basic.h"
64
885824d3 65# include "cgrammar.h"
66# include "cgrammar_tokens.h"
885824d3 67
68# include "fileIdList.h"
69# include "portab.h"
70
71# if defined(OS2) && defined(__IBMC__)
72 /* needed for isatty()... */
73# include <io.h>
74# endif
75
76static bool lastWasString = FALSE;
77static char savechar = '\0';
78
79/*@notfunction@*/
80# define yyinput() (incColumn (), getc (yyin))
81
82/*@-noparams@*/
83/*@-incondefs@*/
84extern /*@external@*/ int read ();
85/*@=incondefs@*/
86/*@=noparams@*/
87
88static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
89
90static int lminput (void);
91static int tokLength = 0;
92static bool inSpecPart = FALSE;
93static bool continueLine = FALSE;
94
95static int ninput (void);
96static char processChar (void);
97static double processFloat (void);
98static /*@only@*/ exprNode processString (void);
99static long processDec (void);
100static long processHex (void);
101static long processOctal (void);
102static int processIdentifier (/*@only@*/ cstring)
103 /*@globals undef lastidprocessed@*/ ;
104static bool processHashIdentifier (/*@only@*/ cstring)
105 /*@globals undef lastidprocessed@*/ ;
106
107static int processSpec (int);
108static bool handleSpecial (char *);
109static int handleLlSpecial (void);
110static void handleMacro (void);
111static bool processMacro (void);
112static /*@only@*/ cstring makeIdentifier (char *);
113
114/* yes, this is exported! */
115bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */
116
08eb3d0e 117static bool expectingMetaStateName = FALSE;
118
885824d3 119static int returnInt (ctype, long);
120static int returnFloat (ctype, double);
121static int returnChar (char);
122static void setTokLength (int) /*@modifies g_currentloc@*/ ;
123static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;
124
125static void advanceLine (void)
126{
127 tokLength = 0;
128 beginLine ();
129}
130
131/*@-allmacros@*/
132# define RETURN_INT(c,i) \
133 do { lastWasString = FALSE; \
134 return (returnInt (c, i)); } while (FALSE)
135
136# define RETURN_FLOAT(c,f) \
137 do { lastWasString = FALSE; \
138 return (returnFloat (c, f)); \
139 } while (FALSE)
140
141# define RETURN_CHAR(c) \
142 do { lastWasString = FALSE; \
143 return (returnChar (c)); \
144 } while (FALSE)
145
146# define RETURN_TOK(t) \
147 do { yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, tokLength)); \
148 tokLength = 0; \
149 lastWasString = FALSE; \
150 return (t); } while (FALSE)
151
152# define RETURN_TYPE(t, ct) \
153 do { yylval.ctyp = ct; tokLength = 0; return (t); } while (FALSE)
154
155/* don't fileloc_decColumn (g_currentloc, tokLength));
156 the string could have \n's in it!
157*/
158
159# define RETURN_STRING(c) \
160 do { yylval.expr = exprNode_stringLiteral (c, fileloc_decColumn (g_currentloc, tokLength)); \
161 tokLength = 0; \
162 lastWasString = TRUE; \
163 return (CCONSTANT); } while (FALSE)
164
165# define RETURN_EXPR(e) \
166 do { yylval.expr = e; \
167 tokLength = 0; \
168 lastWasString = TRUE; \
169 return (CCONSTANT); } while (FALSE)
170
171/*@=allmacros@*/
172
173static void setTokLength (int len)
174{
175 addColumn (len);
176 tokLength = len;
177}
178
179static void setTokLengthT (size_t len)
180{
181 setTokLength (size_toInt (len));
182}
183
184# include "flex.head"
28bf4b0b 185
186/*@-unrecog@*/ /*@i5343@*/
187
885824d3 188%}
189
190%%
191
192"/*" { llfatalbug (cstring_makeLiteral ("Comment in pre-processor output")); }
193
194"#"{Letter}({Letter}|{Digit})* {
195 context_saveLocation ();
196 setTokLength (longUnsigned_toInt (mstring_length (yytext)));
197
198 if (processHashIdentifier (makeIdentifier (yytext + 1)))
199 {
200 if (lastWasString)
201 {
28bf4b0b 202 /* was nothing! */ /*@i32@*/
203 RETURN_STRING (cstring_makeLiteral ("\"\""));
885824d3 204 }
205 else
206 {
207 RETURN_STRING (cstring_makeLiteral ("\"\""));
208 }
209 }
210 else
211 {
212 if (handleSpecial (yytext))
213 {
214 setTokLength (1);
215 RETURN_TOK (0);
216 }
217 }
218 }
219"#" { if (handleSpecial (yytext))
220 {
221 setTokLength (1); RETURN_TOK (0);
222 }
223 }
224"..." { setTokLength (3); RETURN_TOK (CTOK_ELIPSIS); }
225"break" { setTokLength (5); RETURN_TOK (BREAK); }
226"case" { setTokLength (4); RETURN_TOK (CASE); }
227"continue" { setTokLength (8); RETURN_TOK (CONTINUE); }
228"default" { setTokLength (7); RETURN_TOK (DEFAULT); }
229"do" { setTokLength (2); RETURN_TOK (DO); }
230"else" { setTokLength (4); RETURN_TOK (CELSE); }
231"for" { setTokLength (3); RETURN_TOK (CFOR); }
232"goto" { setTokLength (4); RETURN_TOK (GOTO); }
233"if" { setTokLength (2); RETURN_TOK (CIF); }
234"return" { setTokLength (6); RETURN_TOK (RETURN); }
235"sizeof" { setTokLength (6); RETURN_TOK (CSIZEOF); }
236"offsetof" { setTokLength (8); RETURN_TOK (COFFSETOF); }
237"switch" { setTokLength (6); RETURN_TOK (SWITCH); }
238"while" { setTokLength (5); RETURN_TOK (WHILE); }
239"va_arg" { setTokLength (6); RETURN_TOK (VA_ARG); }
240"va_dcl" { setTokLength (6); RETURN_TOK (VA_DCL); }
241"inline" {
242 /* gcc extension...this might not be appropriate */
243 setTokLength (6); RETURN_TOK (QINLINE); }
244
245"struct" { setTokLength (6); RETURN_TOK (CSTRUCT); }
246"typedef" { setTokLength (7); RETURN_TOK (CTYPEDEF); }
247
248"union" { setTokLength (5); RETURN_TOK (CUNION); }
249"enum" { setTokLength (4); RETURN_TOK (CENUM); }
250
251"void" { setTokLength (4); RETURN_TYPE (CVOID, ctype_void); }
252"int" { setTokLength (3); RETURN_TYPE (CINT, ctype_int); }
253"double" { setTokLength (6); RETURN_TYPE (CDOUBLE, ctype_double); }
254"char" { setTokLength (4); RETURN_TYPE (CGCHAR, ctype_char); }
255"float" { setTokLength (5); RETURN_TYPE (CGFLOAT, ctype_float); }
256
257"long" { setTokLength (4); RETURN_TOK (QLONG); }
258"short" { setTokLength (5); RETURN_TOK (QSHORT); }
259"unsigned" { setTokLength (8); RETURN_TOK (QUNSIGNED); }
260"signed" { setTokLength (6); RETURN_TOK (QSIGNED); }
261
262"volatile" { setTokLength (8); RETURN_TOK (QVOLATILE); }
263"const" { setTokLength (5); RETURN_TOK (QCONST); }
264
265 /* some systems expect this! [gack!] */
266"__const" { setTokLength (7); RETURN_TOK (QCONST); }
267
268"extern" { setTokLength (6); RETURN_TOK (QEXTERN); }
269"auto" { setTokLength (4); RETURN_TOK (QAUTO); }
270"register" { setTokLength (8); RETURN_TOK (QREGISTER); }
271"static" { setTokLength (6); RETURN_TOK (QSTATIC); }
272
273\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
7b1629ab 274L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
885824d3 275"out" { return (processSpec (QOUT)); }
276"in" { return (processSpec (QIN)); }
277"partial" { return (processSpec (QPARTIAL)); }
278"special" { return (processSpec (QSPECIAL)); }
279"anytype" { return (processSpec (QANYTYPE)); }
280"integraltype" { return (processSpec (QINTEGRALTYPE)); }
281"unsignedintegraltype" { return (processSpec (QUNSIGNEDINTEGRALTYPE)); }
282"signedintegraltype" { return (processSpec (QSIGNEDINTEGRALTYPE)); }
283"keep" { return (processSpec (QKEEP)); }
284"null" { return (processSpec (QNULL)); }
285"notnull" { return (processSpec (QNOTNULL)); }
286"isnull" { return (processSpec (QISNULL)); }
287"truenull" { return (processSpec (QTRUENULL)); }
288"falsenull" { return (processSpec (QFALSENULL)); }
289"relnull" { return (processSpec (QRELNULL)); }
290"reldef" { return (processSpec (QRELDEF)); }
291"exposed" { return (processSpec (QEXPOSED)); }
292"newref" { return (processSpec (QNEWREF)); }
293"tempref" { return (processSpec (QTEMPREF)); }
294"killref" { return (processSpec (QKILLREF)); }
295"refcounted" { return (processSpec (QREFCOUNTED)); }
296"checked" { return (processSpec (QCHECKED)); }
297"checkmod" { return (processSpec (QCHECKMOD)); }
298"checkedstrict" { return (processSpec (QCHECKEDSTRICT)); }
299"unchecked" { return (processSpec (QUNCHECKED)); }
300"only" { return (processSpec (QONLY)); }
301"owned" { return (processSpec (QOWNED)); }
302"observer" { return (processSpec (QOBSERVER)); }
303"dependent" { return (processSpec (QDEPENDENT)); }
304"unused" { return (processSpec (QUNUSED)); }
305"external" { return (processSpec (QEXTERNAL)); }
306"sef" { return (processSpec (QSEF)); }
307"shared" { return (processSpec (QSHARED)); }
308"yield" { return (processSpec (QYIELD)); }
309"undef" { return (processSpec (QUNDEF)); }
310"killed" { return (processSpec (QKILLED)); }
1ac6313d 311"nullterminated" { return (processSpec (QNULLTERMINATED));}
93307a76 312"MaxSet" { return (processSpec (QMAXSET));}
7272a1c1 313"MaxRead" { return (processSpec (QMAXREAD));}
314"maxSet" { return (processSpec (QMAXSET));}
315"maxRead" { return (processSpec (QMAXREAD));}
11ed4f45 316
885824d3 317{Letter}({Letter}|{Digit})* { int tok;
318 context_saveLocation ();
319 setTokLength (longUnsigned_toInt (mstring_length (yytext)));
320 tok = processIdentifier (makeIdentifier (yytext));
321 if (tok != BADTOK)
322 {
323 return (tok);
324 }
325 }
3260[xX]{H}+ { setTokLengthT (mstring_length (yytext));
327 RETURN_INT (ctype_int, processHex ()); /* evs 2000-05-17 was ctype_uint */
328 }
3290[xX]{H}+{L} { setTokLengthT (mstring_length (yytext));
330 RETURN_INT (ctype_lint, processHex ()); }
3310[xX]{H}+{L}{L} { setTokLengthT (mstring_length (yytext));
332 RETURN_INT (ctype_llint, processHex ()); }
3330[xX]{H}+{U} { setTokLengthT (mstring_length (yytext));
334 RETURN_INT (ctype_uint, processHex ()); }
3350[xX]{H}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
336 RETURN_INT (ctype_ulint, processHex ()); }
3370[xX]{H}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
338 RETURN_INT (ctype_ullint, processHex ()); }
3390[xX]{H}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
340 RETURN_INT (ctype_ullint, processHex ()); }
3410{Digit}+ { setTokLengthT (mstring_length (yytext));
342 RETURN_INT (ctype_int, processOctal ()); }
3430{Digit}+{U} { setTokLengthT (mstring_length (yytext));
344 RETURN_INT (ctype_uint, processOctal ()); }
3450{Digit}+{L} { setTokLengthT (mstring_length (yytext));
346 RETURN_INT (ctype_lint, processOctal ()); }
3470{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
348 RETURN_INT (ctype_llint, processOctal ()); }
3490{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
350 RETURN_INT (ctype_ulint, processOctal ()); }
3510{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
352 RETURN_INT (ctype_ullint, processOctal ()); }
3530{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
354 RETURN_INT (ctype_ullint, processOctal ()); }
355{Digit}+ { setTokLengthT (mstring_length (yytext));
356 RETURN_INT (ctype_int, processDec ()); }
357{Digit}+{U} { setTokLengthT (mstring_length (yytext));
358 RETURN_INT (ctype_uint, processDec ()); }
359{Digit}+{L} { setTokLengthT (mstring_length (yytext));
360 RETURN_INT (ctype_lint, processDec ()); }
361{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
362 RETURN_INT (ctype_llint, processDec ()); }
363{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
364 RETURN_INT (ctype_ulint, processDec ()); }
365{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
366 RETURN_INT (ctype_ullint, processDec ()); }
367{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
368 RETURN_INT (ctype_ullint, processDec ()); }
369'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext));
370 RETURN_CHAR (processChar ()); }
371{Digit}+{E}[fF] { setTokLengthT (mstring_length (yytext));
372 RETURN_FLOAT (ctype_float, processFloat ()); }
373{Digit}+{E}[lL] { setTokLengthT (mstring_length (yytext));
374 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
375{Digit}+{E} { setTokLengthT (mstring_length (yytext));
376 RETURN_FLOAT (ctype_double, processFloat ()); }
377
378{Digit}*"."{Digit}+({E})?[fF] { setTokLengthT (mstring_length (yytext));
379 RETURN_FLOAT (ctype_float, processFloat ()); }
380{Digit}*"."{Digit}+({E})?[lL] { setTokLengthT (mstring_length (yytext));
381 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
382{Digit}*"."{Digit}+({E})? { setTokLengthT (mstring_length (yytext));
383 RETURN_FLOAT (ctype_double, processFloat ()); }
384
385{Digit}+"."{Digit}*({E})?[fF] { setTokLengthT (mstring_length (yytext));
386 RETURN_FLOAT (ctype_float, processFloat ()); }
387{Digit}+"."{Digit}*({E})?[lL] { setTokLengthT (mstring_length (yytext));
388 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
389{Digit}+"."{Digit}*({E})? { setTokLengthT (mstring_length (yytext));
390 RETURN_FLOAT (ctype_double, processFloat ()); }
391
392">>=" { setTokLength (3); RETURN_TOK (RIGHT_ASSIGN); }
393"<<=" { setTokLength (3); RETURN_TOK (LEFT_ASSIGN); }
394"+=" { setTokLength (2); RETURN_TOK (ADD_ASSIGN); }
395"-=" { setTokLength (2); RETURN_TOK (SUB_ASSIGN); }
396"*=" { setTokLength (2); RETURN_TOK (MUL_ASSIGN); }
397"/=" { setTokLength (2); RETURN_TOK (DIV_ASSIGN); }
398"%=" { setTokLength (2); RETURN_TOK (MOD_ASSIGN); }
399"&=" { setTokLength (2); RETURN_TOK (AND_ASSIGN); }
400"^=" { setTokLength (2); RETURN_TOK (XOR_ASSIGN); }
401"|=" { setTokLength (2); RETURN_TOK (OR_ASSIGN); }
402">>" { setTokLength (2); RETURN_TOK (RIGHT_OP); }
403"<<" { setTokLength (2); RETURN_TOK (LEFT_OP); }
404"++" { setTokLength (2); RETURN_TOK (INC_OP); }
405"--" { setTokLength (2); RETURN_TOK (DEC_OP); }
406"->" { setTokLength (2); RETURN_TOK (ARROW_OP); }
407"&&" { setTokLength (2); RETURN_TOK (AND_OP); }
408"||" { setTokLength (2); RETURN_TOK (OR_OP); }
409"<=" { setTokLength (2); RETURN_TOK (LE_OP); }
410">=" { setTokLength (2); RETURN_TOK (GE_OP); }
411"==" { setTokLength (2); RETURN_TOK (EQ_OP); }
412"!=" { setTokLength (2); RETURN_TOK (NE_OP); }
413";" { setTokLength (1); RETURN_TOK (TSEMI); }
414"{" { setTokLength (1); RETURN_TOK (TLBRACE); }
415"}" { setTokLength (1); RETURN_TOK (TRBRACE); }
416"," { setTokLength (1); RETURN_TOK (TCOMMA); }
417":" { setTokLength (1); RETURN_TOK (TCOLON); }
418"=" { setTokLength (1); RETURN_TOK (TASSIGN); }
419"(" { setTokLength (1); RETURN_TOK (TLPAREN); }
420")" { setTokLength (1); RETURN_TOK (TRPAREN); }
421"[" { setTokLength (1); RETURN_TOK (TLSQBR); }
422"]" { setTokLength (1); RETURN_TOK (TRSQBR); }
423"." { setTokLength (1); RETURN_TOK (TDOT); }
424"&" { setTokLength (1); RETURN_TOK (TAMPERSAND); }
425"!" { setTokLength (1); RETURN_TOK (TEXCL); }
426
427
428"~" { setTokLength (1); RETURN_TOK (TTILDE); }
429"-" { setTokLength (1); RETURN_TOK (TMINUS); }
430"+" { setTokLength (1); RETURN_TOK (TPLUS); }
431"*" { setTokLength (1); RETURN_TOK (TMULT); }
432"/" { setTokLength (1); RETURN_TOK (TDIV); }
433"%" { setTokLength (1); RETURN_TOK (TPERCENT); }
434"<" { setTokLength (1); RETURN_TOK (TLT); }
435">" { setTokLength (1); RETURN_TOK (TGT); }
436"^" { setTokLength (1); RETURN_TOK (TCIRC); }
437"|" { setTokLength (1); RETURN_TOK (TBAR); }
438"?" { setTokLength (1); RETURN_TOK (TQUEST); }
439
dcaf75ea 440
441"/\\" { setTokLength (1); RETURN_TOK (TCAND); }
442
443
885824d3 444[ \t\v\f] { incColumn (); }
445\n { context_incLineno ();
446 if (continueLine)
447 {
448 continueLine = FALSE;
449 }
450 else
451 {
452 if (context_inMacro ())
453 {
454 /* Don't use RETURN_TOK */
455 yylval.tok = lltok_create (TENDMACRO, g_currentloc);
456 lastWasString = FALSE;
457 return (TENDMACRO);
458 }
459 }
460 }
461"@@MR@@" { setTokLength (6);
462
463 if (processMacro ()) {
464 if (context_inIterDef ())
465 {
466 RETURN_TOK (LLMACROITER);
467 }
468 if (context_inIterEnd ())
469 {
470 RETURN_TOK (LLMACROEND);
471 }
472 if (context_inMacro ())
473 {
474 RETURN_TOK (LLMACRO);
475 }
476 }
477 }
478"@QLMR" { if (context_inHeader () || context_inFunction ())
479 {
480 handleMacro ();
481 }
482 else
483 {
484 int nspchar = ninput ();
485 int nspaces;
486
487 /*
488 ** This is a hack to get the column number correct.
489 */
490
491 llassert (nspchar >= '0' && nspchar <= '9');
492
493 nspaces = nspchar - '0';
494
495 setTokLength (5 + nspaces);
496
497 if (processMacro ())
498 {
499 if (context_inIterDef ())
500 {
501 RETURN_TOK (LLMACROITER);
502 }
503 if (context_inIterEnd ())
504 {
505 RETURN_TOK (LLMACROEND);
506 }
507 if (context_inMacro ())
508 {
509 RETURN_TOK (LLMACRO);
510 }
511 }
512 }
513 }
514"@.CT" { setTokLength (4); lldiagmsg (ctype_unparseTable ()); }
28bf4b0b 515"@.FA" { setTokLength (4); lldiagmsg (message ("Access types: %q", typeIdSet_unparse (context_fileAccessTypes ()))); }
885824d3 516"@.F" { setTokLength (3);
517 lldiagmsg (message ("%q: *** marker ***", fileloc_unparse (g_currentloc)));
518 }
519"@.L" { setTokLength (3); usymtab_printLocal (); }
520"@.A" { setTokLength (3); lldiagmsg (usymtab_unparseAliases ()); }
521"@.C" { setTokLength (3); lldiagmsg (context_unparse ()); }
522"@.W" { setTokLength (3); lldiagmsg (context_unparseClauses ()); }
523"@.G" { setTokLength (3); usymtab_printGuards (); }
524"@.S" { setTokLength (3); usymtab_printOut (); }
525"@.X" { setTokLength (3); usymtab_printAll (); }
526"@.Z" { setTokLength (3); usymtab_printComplete (); }
527"@.T" { setTokLength (3); usymtab_printTypes (); }
528"@.K" { setTokLength (3); lldiagmsg (usymtab_unparseStack ()); }
529"@.M" { setTokLength (3);
530 lldiagmsg (message ("Can modify: %q",
531 sRefSet_unparse (context_modList ())));
532 }
533"%{" { /* BEFORE_COMMENT_MARKER */
534 int tok;
535 incColumn (); incColumn ();
536 tok = handleLlSpecial ();
28bf4b0b 537
885824d3 538 if (tok != BADTOK)
539 {
28bf4b0b 540 if (tok == CANNOTATION) {
541 return (tok);
542 } else {
543 /* Beware - this bashes yylval! */
544 RETURN_TOK (tok);
545 }
885824d3 546 }
547 }
548"%}" { /* AFTER_COMMENT_MARKER */
549 setTokLength (2);
550 inSpecPart = FALSE;
551 RETURN_TOK (QENDMACRO); }
552"\\" { incColumn (); continueLine = TRUE; }
553. { incColumn ();
28bf4b0b 554 if ((int) *yytext == 13 ) {
555 ;
556 } else {
557 voptgenerror
558 (FLG_SYNTAX,
559 message ("Invalid character (ascii: %d), skipping character",
560 (int)(*yytext)),
561 g_currentloc);
562 }
885824d3 563 }
564%%
565
566struct skeyword
567{
568 /*@null@*/ /*@observer@*/ char *name;
569 int token;
570} ;
571
572/*
573** These tokens are followed by syntax that is parsed by the
574** grammar proper.
575*/
576
577struct skeyword s_parsetable[] = {
578 { "modifies", QMODIFIES } ,
579 { "globals", QGLOBALS } ,
580 { "alt", QALT } ,
28bf4b0b 581 { "warn", QWARN } ,
885824d3 582 { "constant", QCONSTANT } ,
583 { "function", QFUNCTION } ,
584 { "iter", QITER } ,
585 { "defines", QDEFINES } ,
586 { "uses", QUSES } ,
587 { "allocates", QALLOCATES } ,
588 { "sets", QSETS } ,
589 { "releases", QRELEASES } ,
590 { "pre", QPRECLAUSE } ,
591 { "post", QPOSTCLAUSE } ,
60eced23 592 { "setBufferSize", QSETBUFFERSIZE},
60eced23 593 { "setStringLength", QSETSTRINGLENGTH},
594 { "testinRange", QTESTINRANGE},
28bf4b0b 595 { "requires", QPRECLAUSE } ,
596 { "ensures", QPOSTCLAUSE } ,
597 { NULL, BADTOK }
885824d3 598} ;
599
600/*
601** These tokens are either stand-alone tokens, or followed by
602** token-specific text.
603*/
604
605struct skeyword s_keytable[] = {
606 { "anytype", QANYTYPE } ,
607 { "integraltype", QINTEGRALTYPE } ,
608 { "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,
609 { "signedintegraltype", QSIGNEDINTEGRALTYPE } ,
610 { "out", QOUT } ,
611 { "in", QIN } ,
612 { "only", QONLY } ,
613 { "owned", QOWNED } ,
614 { "dependent", QDEPENDENT } ,
615 { "partial", QPARTIAL } ,
616 { "special", QSPECIAL } ,
617 { "truenull", QTRUENULL } ,
618 { "falsenull", QFALSENULL } ,
619 { "keep", QKEEP } ,
620 { "kept", QKEPT } ,
621 { "notnull", QNOTNULL } ,
622 { "abstract", QABSTRACT } ,
623 { "concrete", QCONCRETE } ,
624 { "mutable", QMUTABLE } ,
625 { "immutable", QIMMUTABLE } ,
626 { "unused", QUNUSED } ,
627 { "external", QEXTERNAL } ,
628 { "sef", QSEF } ,
629 { "unique", QUNIQUE } ,
630 { "returned", QRETURNED } ,
631 { "exposed", QEXPOSED } ,
632 { "refcounted", QREFCOUNTED } ,
633 { "refs", QREFS } ,
634 { "newref", QNEWREF } ,
635 { "tempref", QTEMPREF } ,
636 { "killref", QKILLREF } ,
637 { "null", QNULL } ,
638 { "relnull", QRELNULL } ,
1ac6313d 639 { "nullterminated", QNULLTERMINATED },
11ed4f45 640 { "setBufferSize", QSETBUFFERSIZE },
a0a162cd 641 { "testInRange", QTESTINRANGE},
93307a76 642 { "MaxSet", QMAXSET},
643 { "MaxRead", QMAXREAD},
885824d3 644 { "reldef", QRELDEF } ,
645 { "observer", QOBSERVER } ,
646 { "exits", QEXITS } ,
647 { "mayexit", QMAYEXIT } ,
648 { "trueexit", QTRUEEXIT } ,
649 { "falseexit", QFALSEEXIT } ,
650 { "neverexit", QNEVEREXIT } ,
651 { "temp", QTEMP } ,
652 { "shared", QSHARED } ,
653 { "ref", QREF } ,
654 { "unchecked", QUNCHECKED } ,
655 { "checked", QCHECKED } ,
656 { "checkmod", QCHECKMOD } ,
657 { "checkedstrict", QCHECKEDSTRICT } ,
658 { "innercontinue", QINNERCONTINUE } ,
659 { "innerbreak", QINNERBREAK } ,
660 { "loopbreak", QLOOPBREAK } ,
661 { "switchbreak", QSWITCHBREAK } ,
662 { "safebreak", QSAFEBREAK } ,
663 { "fallthrough", QFALLTHROUGH } ,
664 { "l_fallthrou", QLINTFALLTHROUGH } ,
665 { "l_fallth", QLINTFALLTHRU } ,
666 { "notreached", QNOTREACHED } ,
667 { "l_notreach", QLINTNOTREACHED } ,
668 { "printflike", QPRINTFLIKE } ,
669 { "l_printfli", QLINTPRINTFLIKE } ,
670 { "scanflike", QSCANFLIKE } ,
671 { "messagelike", QMESSAGELIKE } ,
672 { "l_argsus", QARGSUSED } ,
673 { NULL, BADTOK }
674} ;
675
676/*
677** would be better if these weren't hard coded...
678*/
679
680static bool isArtificial (cstring s)
681{
682 return (cstring_equalLit (s, "modifies")
683 || cstring_equalLit (s, "globals")
28bf4b0b 684 || cstring_equalLit (s, "warn")
885824d3 685 || cstring_equalLit (s, "alt"));
686}
687
688void swallowMacro (void)
689{
690 int i;
691 bool skipnext = FALSE;
692
693 while ((i = lminput ()) != EOF)
694 {
695 char c = (char) i;
696
697
698 if (c == '\\')
699 {
700 skipnext = TRUE;
701 }
702 else if (c == '\n')
703 {
704 if (skipnext)
705 {
706 skipnext = FALSE;
707 }
708 else
709 {
28bf4b0b 710 reader_checkUngetc (i, yyin);
885824d3 711 return;
712 }
713 }
714 }
715
716 if (i != EOF)
717 {
28bf4b0b 718 reader_checkUngetc (i, yyin);
885824d3 719 }
720}
721
722static int commentMarkerToken (cstring s)
723{
724 int i = 0;
725
726 while (s_parsetable[i].name != NULL)
727 {
28bf4b0b 728 DPRINTF (("Try :%s:%s:", s, s_parsetable[i].name));
729
885824d3 730 if (cstring_equalLit (s, s_parsetable[i].name))
731 {
732 return s_parsetable[i].token;
733 }
734
735 i++;
736 }
737
738 return BADTOK;
739}
740
741static int tokenMacroCode (cstring s)
742{
743 int i = 0;
744
745 while (s_keytable[i].name != NULL)
746 {
747 if (cstring_equalLit (s, s_keytable[i].name))
748 {
749 if (s_keytable[i].token == QLINTFALLTHROUGH)
750 {
751 voptgenerror
752 (FLG_WARNLINTCOMMENTS,
753 cstring_makeLiteral
754 ("Traditional lint comment /*FALLTHROUGH*/ used. "
755 "This is interpreted by "
756 "LCLint in the same way as most Unix lints, but it is "
757 "preferable to replace it with the /*@fallthrough@*/ "
28bf4b0b 758 "semantic comment"),
885824d3 759 g_currentloc);
760 return QFALLTHROUGH;
761 }
762 else if (s_keytable[i].token == QLINTFALLTHRU)
763 {
764 voptgenerror
765 (FLG_WARNLINTCOMMENTS,
766 cstring_makeLiteral
767 ("Traditional lint comment /*FALLTHRU*/ used. "
768 "This is interpreted by "
769 "LCLint in the same way as most Unix lints, but it is "
770 "preferable to replace it with the /*@fallthrough@*/ "
28bf4b0b 771 "semantic comment"),
885824d3 772 g_currentloc);
773 return QFALLTHROUGH;
774 }
775 else if (s_keytable[i].token == QLINTNOTREACHED)
776 {
777 voptgenerror
778 (FLG_WARNLINTCOMMENTS,
779 cstring_makeLiteral
780 ("Traditional lint comment /*NOTREACHED*/ used. "
781 "This is interpreted by "
782 "LCLint in the same way as most Unix lints, but it is "
783 "preferable to replace it with the /*@notreached@*/ "
28bf4b0b 784 "semantic comment."),
885824d3 785 g_currentloc);
786
787 return QNOTREACHED;
788 }
789 else if (s_keytable[i].token == QPRINTFLIKE)
790 {
28bf4b0b 791 setSpecialFunction (qual_createPrintfLike ());
885824d3 792 return SKIPTOK;
793 }
794 else if (s_keytable[i].token == QLINTPRINTFLIKE)
795 {
796 voptgenerror
797 (FLG_WARNLINTCOMMENTS,
798 cstring_makeLiteral
799 ("Traditional lint comment /*PRINTFLIKE*/ used. "
800 "This is interpreted by "
801 "LCLint in the same way as most Unix lints, but it is "
802 "preferable to replace it with either /*@printflike@*/, "
803 "/*@scanflike@*/ or /*@messagelike@*/."),
804 g_currentloc);
805
28bf4b0b 806 setSpecialFunction (qual_createPrintfLike ());
885824d3 807 return SKIPTOK;
808 }
809 else if (s_keytable[i].token == QSCANFLIKE)
810 {
28bf4b0b 811 setSpecialFunction (qual_createScanfLike ());
885824d3 812 return SKIPTOK;
813 }
814 else if (s_keytable[i].token == QMESSAGELIKE)
815 {
28bf4b0b 816 setSpecialFunction (qual_createMessageLike ());
885824d3 817 return SKIPTOK;
818 }
819 else if (s_keytable[i].token == QARGSUSED)
820 {
821 voptgenerror
822 (FLG_WARNLINTCOMMENTS,
823 cstring_makeLiteral
824 ("Traditional lint comment /*ARGSUSED*/ used. "
825 "This is interpreted by "
826 "LCLint in the same way as most Unix lints, but it is "
827 "preferable to use /*@unused@*/ annotations on "
828 "the unused parameters."),
829 g_currentloc);
830
831 setArgsUsed ();
832 return SKIPTOK;
833 }
834
835 return s_keytable[i].token;
836 }
837
838 i++;
839 }
840
841 return BADTOK;
842}
843
844static int lminput ()
845{
846 if (savechar == '\0')
847 {
848 incColumn ();
849 return (input ());
850 }
851 else
852 {
853 int save = (int) savechar;
854 savechar = '\0';
855 return save;
856 }
857}
858
859static void lmsavechar (char c)
860{
861 if (savechar == '\0') savechar = c;
862 else
863 {
864 llbuglit ("lmsavechar: override");
865 }
866}
867
868static int returnFloat (ctype ct, double f)
869{
870 yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext),
871 fileloc_decColumn (g_currentloc, tokLength));
872 tokLength = 0;
873 return (CCONSTANT);
874}
875
876static int returnInt (ctype ct, long i)
877{
878 ctype c = ct;
879
880 if (ctype_equal (ct, ctype_int))
881 {
882 if (i == 0)
883 {
884 c = context_typeofZero ();
885 }
886 else if (i == 1)
887 {
888 c = context_typeofOne ();
889 }
890 }
891
892 yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
893 fileloc_decColumn (g_currentloc, tokLength), i);
894 tokLength = 0;
895 return (CCONSTANT);
896}
897
898static int returnChar (char c)
899{
900 yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext),
901 fileloc_decColumn (g_currentloc, tokLength));
902 tokLength = 0;
903 return (CCONSTANT);
904}
905
906static int ninput ()
907{
908 int c = lminput ();
909
910 if (c != EOF && ((char)c == '\n'))
911 {
912 context_incLineno ();
913 }
914
915 return c;
916}
917
918static char macro_nextChar ()
919{
920 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
921 int ic;
922 char c;
923
924 ic = lminput ();
925 c = char_fromInt (ic);
926
927 if (!in_quote && !in_char && (c == '\\' || c == BEFORE_COMMENT_MARKER[0]))
928 {
929 if (c == '\\')
930 {
931 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
932 {
933 ; /* skip to newline */
934 }
935
936 context_incLineno ();
937
938 if (c != '\0')
939 {
940 return macro_nextChar ();
941 }
942 else
943 {
944 return c;
945 }
946 }
947 else /* if (c == '@') */
948 {
28bf4b0b 949 llassert (FALSE); /*@i23@*/
885824d3 950 if (handleLlSpecial () != BADTOK)
951 {
952 llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax");
953 }
954
955 return macro_nextChar ();
956 }
957 }
958 else if (!in_escape && c == '\"')
959 {
960 in_quote = !in_quote;
961 }
962 else if (!in_escape && c == '\'')
963 {
964 in_char = !in_char;
965 }
966 else if ((in_quote || in_char) && c == '\\')
967 {
968 in_escape = !in_escape;
969 }
970 else if ((in_quote || in_char) && in_escape)
971 {
972 in_escape = FALSE;
973 }
974 else if (!in_quote && c == '/')
975 {
976 char c2;
977
978 if ((c2 = char_fromInt (lminput ())) == '*')
979 {
980 while (c2 != '\0')
981 {
982 while ((c2 = char_fromInt (lminput ())) != '\0'
983 && c2 != '\n' && c2 != '*')
984 {
985 ;
986 }
987
988 if (c2 == '*')
989 {
990 while ((c2 = char_fromInt (lminput ())) != '\0'
991 && c2 == '*')
992 {
993 ;
994 }
995
996 if (c2 == '/')
997 {
998 goto outofcomment;
999 }
1000 }
1001 else
1002 {
1003 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
1004 }
1005 }
1006 outofcomment:
1007 return macro_nextChar ();
1008 }
1009 else
1010 {
1011 /*** putchar does not work! why? puts to stdio...??! ***/
1012 lmsavechar (c2);
1013 }
1014 }
1015 return c;
1016}
1017
1018/*
28bf4b0b 1019** keeps semantic comments
885824d3 1020*/
1021
1022static char macro_nextCharC ()
1023{
1024 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
1025 char c;
1026
1027 c = char_fromInt (lminput ());
1028
1029 if (!in_quote && !in_char && c == '\\')
1030 {
1031 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
1032 {
1033 ; /* skip to newline */
1034 }
1035
1036 context_incLineno ();
1037
1038 if (c != '\0')
1039 {
1040 return macro_nextCharC ();
1041 }
1042 else
1043 {
1044 return c;
1045 }
1046 }
1047 else if (!in_escape && c == '\"')
1048 {
1049 in_quote = !in_quote;
1050 }
1051 else if (!in_escape && c == '\'')
1052 {
1053 in_char = !in_char;
1054 }
1055 else if ((in_quote || in_char) && c == '\\')
1056 {
1057 in_escape = !in_escape;
1058 }
1059 else if ((in_quote || in_char) && in_escape)
1060 {
1061 in_escape = FALSE;
1062 }
1063 else if (!in_quote && c == '/')
1064 {
1065 char c2;
1066
1067 if ((c2 = char_fromInt (lminput ())) == '*')
1068 {
1069 while (c2 != '\0')
1070 {
1071 while ((c2 = char_fromInt (lminput ())) != '\0'
1072 && c2 != '\n' && c2 != '*')
1073 {
1074 ;
1075 }
1076
1077 if (c2 == '*')
1078 {
1079 while ((c2 = char_fromInt (lminput ())) != '\0'
1080 && c2 == '*')
1081 {
1082 ;
1083 }
1084
1085 if (c2 == '/')
1086 {
1087 goto outofcomment;
1088 }
1089 }
1090 else
1091 {
1092 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
1093 }
1094 }
1095 outofcomment:
1096 return macro_nextCharC ();
1097 }
1098 else
1099 {
1100 lmsavechar (c2);
1101 }
1102 }
1103 return c;
1104}
1105
1106/*
1107** skips whitespace (handles line continuations)
1108** returns first non-whitespace character
1109*/
1110
1111static char skip_whitespace ()
1112{
1113 char c;
1114
1115 while ((c = macro_nextChar ()) == ' ' || c == '\t')
1116 {
1117 ;
1118 }
1119
1120 return c;
1121}
1122
1123static void handleMacro ()
1124{
1125 cstring mac = cstring_undefined;
1126 int macrocode;
1127 char c;
1128
1129 while (currentColumn () > 2)
1130 {
1131 mac = cstring_appendChar (mac, ' ');
1132 setTokLength (-1);
1133 }
1134
1135 c = macro_nextCharC ();
1136
1137 if (c >= '0' && c <= '9')
1138 {
1139 int i;
1140
1141 for (i = 0; i < ((c - '0') + 1); i++)
1142 {
1143 mac = cstring_appendChar (mac, ' ');
1144 }
1145 }
1146 else
1147 {
1148 BADBRANCH;
1149 }
1150
1151 while (((c = macro_nextCharC ()) != '\0') && (c != '\n'))
1152 {
1153 mac = cstring_appendChar (mac, c);
1154 }
1155
1156
1157 macrocode = tokenMacroCode (mac);
1158
1159 if (macrocode == BADTOK && !isArtificial (mac))
1160 {
885824d3 1161 context_addMacroCache (mac);
1162 }
1163 else
1164 {
1165 cstring_free (mac);
1166 }
1167
1168 if (c == '\n')
1169 {
1170 context_incLineno ();
1171 }
1172}
1173
1174static bool processMacro (void)
1175{
1176 uentry e2;
1177 ctype ct;
1178 int noparams = 0;
1179 cstring fname = cstring_undefined;
1180 bool res = TRUE;
1181 bool isspecfcn = FALSE;
1182 bool isiter = FALSE;
1183 bool skipparam = FALSE;
1184 bool isenditer = FALSE;
1185 bool unknownm = FALSE;
1186 bool hasParams = FALSE;
1187 bool emptyMacro = FALSE;
1188 char c = skip_whitespace ();
1189 fileloc loc = fileloc_noColumn (g_currentloc);
1190
1191 /* are both of these necessary? what do they mean? */
1192 uentryList specparams = uentryList_undefined;
1193 uentryList pn = uentryList_undefined;
1194
1195 context_resetMacroMissingParams ();
1196
1197 if (c == '\0' || c == '\n')
1198 {
1199 llcontbug (cstring_makeLiteral ("Bad macro"));
1200 fileloc_free (loc);
1201 return FALSE;
1202 }
1203
1204 fname = cstring_appendChar (fname, c);
1205
1206 while ((c = macro_nextChar ()) != '(' && c != '\0'
1207 && c != ' ' && c != '\t' && c != '\n')
1208 {
1209 fname = cstring_appendChar (fname, c);
1210 }
1211
1212 if (c == ' ' || c == '\t' || c == '\n')
1213 {
1214 char oldc = c;
1215
1216 if (c != '\n')
1217 {
1218 while (c == ' ' || c == '\t')
1219 {
1220 c = macro_nextChar ();
1221 }
1222 unput (c);
1223 }
1224
1225 if (c == '\n')
1226 {
1227 emptyMacro = TRUE;
1228 unput (c);
1229 }
1230
1231 c = oldc;
1232 }
1233
1234 hasParams = (c == '(');
1235
1236
1237 if (usymtab_exists (fname))
1238 {
1239 e2 = usymtab_lookupExpose (fname);
1240 ct = uentry_getType (e2);
1241
1242
1243 if (uentry_isCodeDefined (e2)
1244 && fileloc_isUser (uentry_whereDefined (e2)))
1245 {
1246 if (optgenerror
1247 (FLG_MACROREDEF,
1248 message ("Macro %s already defined", fname),
1249 loc))
1250 {
1251 uentry_showWhereDefined (e2);
1252 uentry_clearDefined (e2);
1253 }
1254
1255 if (uentry_isFunction (e2))
1256 {
1257 uentry_setType (e2, ctype_unknown);
1258 ct = ctype_unknown;
1259 unknownm = TRUE;
1260 context_enterUnknownMacro (e2);
1261 }
1262 else
1263 {
1264 context_enterConstantMacro (e2);
1265 }
1266 }
1267 else
1268 {
1269 if (uentry_isForward (e2) && uentry_isFunction (e2))
1270 {
1271 unknownm = TRUE;
1272
1273 voptgenerror
1274 (FLG_MACROFCNDECL,
1275 message
1276 ("Parameterized macro has no prototype or specification: %s ",
1277 fname),
1278 loc);
1279
1280 ct = ctype_unknown;
1281 uentry_setType (e2, ctype_unknown);
1282 uentry_setFunctionDefined (e2, loc);
1283 uentry_setUsed (e2, fileloc_undefined);
1284 context_enterUnknownMacro (e2);
1285 }
1286 else
1287 {
1288 if (uentry_isIter (e2))
1289 {
1290 isiter = TRUE;
1291 specparams = uentry_getParams (e2);
1292 noparams = uentryList_size (specparams);
1293 uentry_setDefined (e2, loc);
1294 context_enterIterDef (e2);
1295 }
1296 else if (uentry_isEndIter (e2))
1297 {
1298 isenditer = TRUE;
1299 uentry_setDefined (e2, loc);
1300 context_enterIterEnd (e2); /* don't care about it now */
1301 /* but should parse like an iter! */
1302 }
1303 else if (uentry_isConstant (e2))
1304 {
1305 if (hasParams)
1306 {
1307 voptgenerror
1308 (FLG_INCONDEFS,
1309 message ("Constant %s implemented as parameterized macro",
1310 fname),
1311 g_currentloc);
1312
1313 uentry_showWhereSpecified (e2);
1314 uentry_setType (e2, ctype_unknown);
1315 uentry_makeVarFunction (e2);
1316 uentry_setDefined (e2, g_currentloc);
1317 uentry_setFunctionDefined (e2, g_currentloc);
1318 context_enterUnknownMacro (e2);
1319 }
1320 else
1321 {
1322 if (!uentry_isSpecified (e2))
1323 {
1324 fileloc oloc = uentry_whereDeclared (e2);
1325
1326 if (fileloc_isLib (oloc))
1327 {
1328 ;
1329 }
1330 else if (fileloc_isUndefined (oloc)
1331 || fileloc_isPreproc (oloc))
1332 {
1333 if (!emptyMacro)
1334 {
1335 voptgenerror
1336 (FLG_MACROCONSTDECL,
1337 message
1338 ("Macro constant %q not declared",
1339 uentry_getName (e2)),
1340 loc);
1341 }
1342 }
1343 else if (!fileloc_withinLines (oloc, loc, 2))
1344 { /* bogus! will give errors if there is too much whitespace */
1345 voptgenerror
1346 (FLG_SYNTAX,
1347 message
1348 ("Macro constant name %s does not match name in "
1349 "previous constant declaration. This constant "
1350 "is declared at %q", fname,
1351 fileloc_unparse (oloc)),
1352 loc);
1353 }
1354 }
1355
1356 context_enterConstantMacro (e2);
1357 cstring_free (fname);
1358 fileloc_free (loc);
1359 return res;
1360 }
1361
1362 }
1363 else if (ctype_isFunction (ct))
1364 {
1365 isspecfcn = TRUE;
1366 specparams = ctype_argsFunction (ct);
1367 noparams = uentryList_size (specparams);
1368
1369 uentry_setFunctionDefined (e2, loc);
1370 context_enterMacro (e2);
1371 }
1372 else if (uentry_isVar (e2))
1373 {
1374 if (hasParams)
1375 {
1376 voptgenerror
1377 (FLG_INCONDEFS,
1378 message ("Variable %s implemented as parameterized macro",
1379 fname),
1380 loc);
1381
1382 uentry_showWhereSpecified (e2);
1383 uentry_setType (e2, ctype_unknown);
1384 uentry_makeVarFunction (e2);
1385 uentry_setDefined (e2, g_currentloc);
1386 uentry_setFunctionDefined (e2, g_currentloc);
1387 context_enterUnknownMacro (e2);
1388 }
1389 else
1390 {
1391 uentry ucons = uentry_makeConstant (fname,
1392 ctype_unknown,
1393 loc);
1394 if (uentry_isExpandedMacro (e2))
1395 {
1396 ; /* okay */
1397 }
1398 else
1399 {
1400 if (optgenerror
1401 (FLG_INCONDEFS,
1402 message ("Variable %s implemented by a macro",
1403 fname),
1404 loc))
1405 {
1406 uentry_showWhereSpecified (e2);
1407 }
1408 }
1409
1410 uentry_setDefined (e2, loc);
1411 uentry_setUsed (ucons, loc);
1412
1413 context_enterConstantMacro (ucons);
1414 uentry_markOwned (ucons);
1415 cstring_free (fname);
1416 return res;
1417 }
1418 }
1419 else
1420 {
1421 if (uentry_isDatatype (e2))
1422 {
1423 vgenhinterror
1424 (FLG_SYNTAX,
1425 message ("Type implemented as macro: %x",
1426 uentry_getName (e2)),
1427 message ("A type is implemented using a macro definition. A "
1428 "typedef should be used instead."),
1429 g_currentloc);
1430
1431 swallowMacro ();
1432 /* Must exit scope (not sure why a new scope was entered?) */
1433 usymtab_quietExitScope (g_currentloc);
1434 uentry_setDefined (e2, g_currentloc);
1435 res = FALSE;
1436 }
1437 else
1438 {
1439 llcontbug
1440 (message ("Unexpanded macro not function or constant: %q",
1441 uentry_unparse (e2)));
1442 uentry_setType (e2, ctype_unknown);
1443
1444 if (hasParams)
1445 {
1446 uentry_makeVarFunction (e2);
1447 uentry_setDefined (e2, g_currentloc);
1448 uentry_setFunctionDefined (e2, g_currentloc);
1449 context_enterUnknownMacro (e2);
1450 }
1451 }
1452 }
1453 }
1454 }
1455 }
1456 else
1457 {
1458 uentry ce;
1459
1460 voptgenerror
1461 (FLG_MACROMATCHNAME,
1462 message ("Unexpanded macro %s does not match name of a constant "
1463 "or iter declaration. The name used in the control "
1464 "comment on the previous line should match. "
1465 "(Assuming macro defines a constant.)",
1466 fname),
1467 loc);
1468
1469
1470 ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined);
1471 uentry_setUsed (ce, loc); /* perhaps bogus? */
1472 e2 = usymtab_supEntryReturn (ce);
1473
1474 context_enterConstantMacro (e2);
1475 cstring_free (fname);
1476 fileloc_free (loc);
1477 return res;
1478 }
1479
1480 /* in macros, ( must follow immediatetly after name */
1481
1482 if (hasParams)
1483 {
1484 int paramno = 0;
1485
1486 c = skip_whitespace ();
1487
1488 while (c != ')' && c != '\0')
1489 {
1490 uentry param;
1491 bool suppress = context_inSuppressRegion ();
1492 cstring paramname = cstring_undefined;
1493
1494 /*
1495 ** save the parameter location
1496 */
1497
1498 decColumn ();
1499 context_saveLocation ();
1500 incColumn ();
1501
1502 while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')
1503 {
1504 paramname = cstring_appendChar (paramname, c);
1505 c = macro_nextChar ();
1506 }
1507
1508 if (c == ' ' || c == '\t') c = skip_whitespace ();
1509
1510 if (c == ',')
1511 {
1512 c = macro_nextChar ();
1513 if (c == ' ' || c == '\t') c = skip_whitespace ();
1514 }
1515
1516 if (c == '\0')
1517 {
1518 llfatalerror (cstring_makeLiteral
1519 ("Bad macro syntax: uentryList"));
1520 }
1521
1522 if ((isspecfcn || isiter) && (paramno < noparams)
1523 && !uentry_isElipsisMarker (uentryList_getN
1524 (specparams, paramno)))
1525 {
1526 uentry decl = uentryList_getN (specparams, paramno);
1527 sRef sr;
1528
1529 param = uentry_nameCopy (paramname, decl);
1530
1531
1532 uentry_setParam (param);
1533 sr = sRef_makeParam (paramno, uentry_getType (param));
1534
1535 if (sRef_getNullState (sr) == NS_ABSNULL)
1536 {
1537 ctype pt = ctype_realType (uentry_getType (param));
1538
1539 if (ctype_isUser (pt))
1540 {
1541 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));
1542
1543 if (uentry_isValid (te))
1544 {
1545 sRef_setStateFromUentry (sr, te);
1546 }
1547 }
1548 else
1549 {
1550 sRef_setNullState (sr, NS_UNKNOWN, g_currentloc);
1551 }
1552 }
1553
1554 uentry_setSref (param, sr);
1555 uentry_setDeclaredForceOnly (param, context_getSaveLocation ());
1556
1557 skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));
1558 }
1559 else
1560 {
1561 fileloc sloc = context_getSaveLocation ();
1562
1563 param = uentry_makeVariableSrefParam
1564 (paramname, ctype_unknown, sRef_makeParam (paramno, ctype_unknown));
1565 cstring_free (paramname);
1566
1567 sRef_setPosNull (uentry_getSref (param), sloc);
1568
1569 uentry_setDeclaredForce (param, sloc);
1570
1571 skipparam = FALSE;
1572 fileloc_free (sloc);
1573 }
1574
1575 if (!skipparam)
1576 {
1577 llassert (!uentry_isElipsisMarker (param));
1578
1579 if (!suppress)
1580 {
1581 sRef_makeUnsafe (uentry_getSref (param));
1582 }
1583
1584 pn = uentryList_add (pn, uentry_copy (param));
1585 usymtab_supEntry (param);
1586 }
1587 else
1588 {
1589 /* don't add param */
1590 uentry_free (param);
1591 }
1592
1593 if (c == ',')
1594 {
1595 (void) macro_nextChar ();
1596 c = skip_whitespace ();
1597 }
1598
1599 paramno++;
1600 }
1601
1602 if (c == ')')
1603 {
1604 if (isspecfcn || isiter)
1605 {
1606 if (paramno != noparams && noparams >= 0)
1607 {
1608 advanceLine ();
1609
1610 voptgenerror
1611 (FLG_INCONDEFS,
1612 message ("Macro %s specified with %d args, defined with %d",
1613 fname, noparams, paramno),
1614 g_currentloc);
1615
1616 uentry_showWhereSpecified (e2);
1617 uentry_resetParams (e2, pn);
1618 }
1619 }
1620 else
1621 {
1622 uentry_resetParams (e2, pn);
1623 }
1624 }
1625 }
1626 else
1627 {
1628 /*
1629 ** the form should be:
1630 **
1631 ** # define newname oldname
1632 ** where oldname refers to a function matching the specification
1633 ** of newname.
1634 */
1635
1636 if (unknownm)
1637 {
1638 sRef_setGlobalScope ();
1639 usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));
1640 sRef_clearGlobalScope ();
1641 }
1642 else
1643 {
1644 context_setMacroMissingParams ();
1645 }
1646 }
1647
1648
1649 /* context_setuentryList (pn); */
1650 usymtab_enterScope ();
1651
1652 fileloc_free (loc);
1653 cstring_free (fname);
1654
1655 return res;
1656}
1657
1658static bool handleSpecial (char *yyt)
1659{
1660 char *l = mstring_create (MAX_NAME_LENGTH);
1661 static bool reportcpp = FALSE;
1662 int lineno = 0;
1663 char c;
1664 char *ol;
1665 cstring olc;
1666
1667 strcpy (l, yyt + 1);
1668
1669 /* Need to safe original l for deallocating. */
1670 ol = l;
1671
1672 l += strlen (yyt) - 1;
1673
1674 while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')
1675 {
1676 *l++ = c;
1677 }
1678
1679 *l = '\0';
1680 olc = cstring_fromChars (ol);
1681
1682 if (cstring_equalPrefix (olc, "pragma"))
1683 {
1684 char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN));
1685 char *opname = pname;
1686 char *ptr = ol + 6; /* pragma is six characters, plus space */
1687 int len = 0;
1688
1689
1690 /* skip whitespace */
1691 while (((c = *ptr) != '\0') && isspace (c))
1692 {
1693 ptr++;
1694 }
1695
1696
1697 while (((c = *ptr) != '\0') && !isspace (c))
1698 {
1699 len++;
1700
1701 if (len > MAX_PRAGMA_LEN)
1702 {
1703 break;
1704 }
1705
1706 ptr++;
1707 *pname++ = c;
1708 }
1709
1710 *pname = '\0';
1711
1712 if (len == PRAGMA_LEN_EXPAND
1713 && mstring_equal (opname, PRAGMA_EXPAND))
1714 {
1715 cstring exname = cstring_undefined;
1716 uentry ue;
1717
1718 ptr++;
1719 while (((c = *ptr) != '\0') && !isspace (c))
1720 {
1721 exname = cstring_appendChar (exname, c);
1722 ptr++;
1723 }
1724
1725
1726 ue = usymtab_lookupExposeGlob (exname);
1727
1728 if (uentry_isExpandedMacro (ue))
1729 {
1730 if (fileloc_isPreproc (uentry_whereDefined (ue)))
1731 {
1732 fileloc_setColumn (g_currentloc, 1);
1733 uentry_setDefined (ue, g_currentloc);
1734 }
1735 }
1736
1737 cstring_free (exname);
1738 }
1739 }
1740 else if (cstring_equalPrefix (olc, "ident"))
1741 {
1742 /* Some pre-processors will leave these in the code. Ignore rest of line */
1743 }
1744 /*
1745 ** Yuk...Win32 filenames can have spaces in them...we need to read
1746 ** to the matching end quote.
1747 */
1748 else if ((sscanf (ol, "line %d \"", &lineno) == 1)
1749 || (sscanf (ol, " %d \"", &lineno) == 1))
1750 {
1751 char *tmp = ol;
28bf4b0b 1752 cstring fname;
885824d3 1753 fileId fid;
1754
28bf4b0b 1755 /*@access cstring@*/
885824d3 1756 while (*tmp != '\"' && *tmp != '\0')
1757 {
1758 tmp++;
1759 }
1760
1761 llassert (*tmp == '\"');
1762
1763 tmp++;
28bf4b0b 1764
885824d3 1765 fname = tmp;
1766
1767 while (*tmp != '\"' && *tmp != '\0')
1768 {
1769 tmp++;
1770 }
1771
1772 llassert (*tmp == '\"');
1773
1774 *tmp = '\0';
1775
885824d3 1776# if defined(OS2) || defined(MSDOS) || defined(WIN32)
1777
1778 /*
1779 ** DOS-like path delimiters get delivered in pairs, something like
1780 ** \"..\\\\file.h\", so we have to make it normal again. We do NOT
1781 ** remove the pre dirs yet as we usually specify tmp paths relative
1782 ** to the current directory, so tmp files would not get found in
1783 ** the hash table. If this method fails we try it again later.
1784 */
1785
1786 {
1787 char *stmp = fname;
1788
1789 /*
1790 ** Skip past the drive marker.
1791 */
1792
885824d3 1793 if (strchr (stmp, ':') != NULL)
1794 {
1795 stmp = strchr (stmp, ':') + 1;
1796 }
1797
885824d3 1798 while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )
1799 {
1800 if (*(stmp+1) == CONNECTCHAR)
1801 {
1802 memmove (stmp, stmp+1, strlen (stmp));
1803 }
1804
1805 stmp++;
885824d3 1806 }
1807
28bf4b0b 1808 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1809 if (!(fileId_isValid (fid)))
1810 {
1811 fname = removePreDirs (fname);
28bf4b0b 1812 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1813 }
1814 }
1815# else /* !defined(OS2) && !defined(MSDOS) */
1816 fname = removePreDirs (fname);
28bf4b0b 1817 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1818# endif /* !defined(OS2) && !defined(MSDOS) */
1819
1820 if (!(fileId_isValid (fid)))
1821 {
28bf4b0b 1822 if (isHeaderFile (fname))
885824d3 1823 {
28bf4b0b 1824 fid = fileTable_addHeaderFile (context_fileTable (), fname);
885824d3 1825 }
1826 else
1827 {
28bf4b0b 1828 fid = fileTable_addFile (context_fileTable (), fname);
885824d3 1829 }
1830 }
1831
1832 setFileLine (fid, lineno);
28bf4b0b 1833 /*@noaccess cstring@*/
885824d3 1834 }
1835 else if ((sscanf (ol, "line %d", &lineno) == 1)
1836 || (sscanf (ol, " %d", &lineno) == 1))
1837 {
1838 setLine (lineno); /* next line is <cr> */
1839 }
1840 else
1841 {
1842 if (mstring_equal (ol, "")) {
1843 DPRINTF (("Empty pp command!"));
1844 /*
1845 ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.
1846 ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.
1847 */
1848 mstring_free (ol);
1849 return FALSE;
1850 } else {
1851 if (!reportcpp)
1852 {
1853
1854 } else {
1855 llbug (message ("File contains preprocessor command: #%s",
1856 cstring_fromChars (ol)));
1857 reportcpp = TRUE;
1858 }
1859 }
1860
1861 sfree (ol);
1862 return TRUE;
1863 }
1864
1865 sfree (ol);
1866 return FALSE;
1867}
1868
1869static int handleLlSpecial ()
1870{
1871 int ic;
1872 char c;
1873 char *s = mstring_createEmpty ();
1874 char *os;
1875 int tok;
1876 int charsread = 0;
28bf4b0b 1877 fileloc loc;
1878
1879 loc = fileloc_copy (g_currentloc);
1880 DPRINTF (("Handle special: %s", fileloc_unparse (loc)));
885824d3 1881
1882 while (((ic = ninput ()) != 0) && isalpha (ic))
1883 {
1884 c = (char) ic;
1885 s = mstring_append (s, c);
1886 charsread++;
1887 }
1888
28bf4b0b 1889 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
885824d3 1890 os = s;
1891
1892 if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])
1893 {
1894 ic = ninput ();
1895
1896 llassert (ic == AFTER_COMMENT_MARKER[1]);
885824d3 1897
28bf4b0b 1898 if (*s == '\0')
885824d3 1899 {
1900 sfree (os);
28bf4b0b 1901 fileloc_free (loc);
885824d3 1902 return QNOMODS; /* special token no modifications token */
1903 }
885824d3 1904 }
1905
28bf4b0b 1906 DPRINTF (("Coment marker: %s", os));
885824d3 1907 tok = commentMarkerToken (cstring_fromChars (os));
1908
1909 if (tok != BADTOK)
1910 {
1911 tokLength = charsread;
1912 sfree (os);
1913 inSpecPart = TRUE;
28bf4b0b 1914 fileloc_free (loc);
885824d3 1915 return tok;
1916 }
28bf4b0b 1917
1918 DPRINTF (("Not a comment marker..."));
885824d3 1919 /* Add rest of the comment */
1920
1921 if (ic != 0 && ic != EOF)
1922 {
1923 c = (char) ic;
885824d3 1924
1925 s = mstring_append (s, c);
1926 charsread++;
1927
1928 while (((ic = ninput ()) != 0) && (ic != EOF)
1929 && (ic != AFTER_COMMENT_MARKER[0]))
1930 {
1931 c = (char) ic;
1932 s = mstring_append (s, c);
1933 charsread++;
1934 }
1935 }
1936
28bf4b0b 1937 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
1938
885824d3 1939 if (ic == AFTER_COMMENT_MARKER[0])
1940 {
1941 int nc = ninput ();
1942 llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
1943 charsread++;
1944 }
1945
885824d3 1946 os = s;
1947
1948 while (*s == ' ' || *s == '\t' || *s == '\n')
1949 {
1950 s++;
1951 }
1952
1953 if (*s == '-' || *s == '+' || *s == '=') /* setting flags */
1954 {
1955 c = *s;
1956
1957 while (c == '-' || c == '+' || c == '=')
1958 {
1959 ynm set = ynm_fromCodeChar (c);
1960 cstring thisflag;
1961
1962 s++;
1963
1964 thisflag = cstring_fromChars (s);
1965
1966 while ((c = *s) != '\0' && (c != '-') && (c != '=')
1967 && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))
1968 {
1969 s++;
1970 }
1971
1972 *s = '\0';
1973
1974 if (!context_getFlag (FLG_NOCOMMENTS))
1975 {
1976 cstring flagname = thisflag;
1977 flagcode fflag = identifyFlag (flagname);
a0a162cd 1978
885824d3 1979 if (flagcode_isSkip (fflag))
1980 {
1981 ;
1982 }
1983 else if (flagcode_isInvalid (fflag))
1984 {
1985 if (isMode (flagname))
1986 {
1987 if (ynm_isMaybe (set))
1988 {
1989 llerror
1990 (FLG_BADFLAG,
1991 message
28bf4b0b 1992 ("Semantic comment attempts to restore flag %s. "
885824d3 1993 "A mode flag cannot be restored.",
1994 flagname));
1995 }
1996 else
1997 {
1998 context_setMode (flagname);
1999 }
2000 }
2001 else
2002 {
990ec868 2003 voptgenerror
2004 (FLG_UNRECOGFLAGCOMMENTS,
28bf4b0b 2005 message ("Unrecognized option in semantic comment: %s",
990ec868 2006 flagname),
2007 g_currentloc);
885824d3 2008 }
2009 }
2010 else if (flagcode_isGlobalFlag (fflag))
2011 {
990ec868 2012 voptgenerror
885824d3 2013 (FLG_BADFLAG,
2014 message
28bf4b0b 2015 ("Semantic comment attempts to set global flag %s. "
885824d3 2016 "A global flag cannot be set locally.",
990ec868 2017 flagname),
2018 g_currentloc);
885824d3 2019 }
2020 else
2021 {
2022 context_fileSetFlag (fflag, set);
a0a162cd 2023
885824d3 2024 if (flagcode_hasArgument (fflag))
2025 {
2026 if (ynm_isMaybe (set))
2027 {
990ec868 2028 voptgenerror
885824d3 2029 (FLG_BADFLAG,
2030 message
28bf4b0b 2031 ("Semantic comment attempts to restore flag %s. "
885824d3 2032 "A flag for setting a value cannot be restored.",
990ec868 2033 flagname),
2034 g_currentloc);
885824d3 2035 }
2036 else
2037 { /* cut-and-pastied from llmain...blecch */
2038 cstring extra = cstring_undefined;
2039 char *rest;
2040 char *orest;
2041 char rchar;
2042
2043 *s = c;
2044 rest = mstring_copy (s);
2045 orest = rest;
2046 *s = '\0';
2047
2048 while ((rchar = *rest) != '\0'
2049 && (isspace (rchar)))
2050 {
2051 rest++;
2052 s++;
2053 }
2054
2055 while ((rchar = *rest) != '\0'
2056 && !isspace (rchar))
2057 {
2058 extra = cstring_appendChar (extra, rchar);
2059 rest++;
2060 s++;
2061 }
2062
2063 sfree (orest);
a0a162cd 2064
885824d3 2065 if (cstring_isUndefined (extra))
2066 {
2067 llerror
2068 (FLG_BADFLAG,
2069 message
28bf4b0b 2070 ("Flag %s (in semantic comment) must be followed by an argument",
885824d3 2071 flagcode_unparse (fflag)));
2072 }
2073 else
2074 {
2075 s--;
2076
2077 if (flagcode_hasValue (fflag))
2078 {
2079 setValueFlag (fflag, extra);
2080 }
2081 else if (flagcode_hasString (fflag))
2082 {
2083 setStringFlag (fflag, extra);
2084 }
2085 else
2086 {
2087 BADEXIT;
2088 }
2089 }
2090 }
2091 }
2092 }
2093 }
2094 else
2095 {
a0a162cd 2096 ;
2097 }
885824d3 2098
2099 *s = c;
2100 while ((c == ' ') || (c == '\t') || (c == '\n'))
2101 {
2102 c = *(++s);
2103 }
2104 }
2105
2106 if (context_inHeader () && !isArtificial (cstring_fromChars (os)))
2107 {
28bf4b0b 2108 DPRINTF (("Here adding comment: %s", os));
2109 context_addComment (cstring_fromCharsNew (os));
885824d3 2110 }
2111 else
2112 {
2113 ;
2114 }
2115 }
2116 else
2117 {
2118 char *t = s;
2119 int macrocode;
2120 char tchar = '\0';
28bf4b0b 2121 annotationInfo ainfo;
885824d3 2122
2123 while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n')
2124 {
2125 s++;
2126 }
2127
2128 if (*s != '\0')
2129 {
2130 tchar = *s;
2131 *s = '\0';
2132 s++;
2133 }
2134
2135 t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));
2136 macrocode = tokenMacroCode (cstring_fromChars (t));
2137
2138 if (macrocode != BADTOK)
2139 {
2140 tokLength = mstring_length (t);
885824d3 2141
2142 sfree (t);
2143 sfree (os);
28bf4b0b 2144 fileloc_free (loc);
885824d3 2145
2146 if (macrocode == SKIPTOK)
2147 {
2148 return BADTOK;
2149 }
2150
2151 return macrocode;
2152 }
2153
28bf4b0b 2154 ainfo = context_lookupAnnotation (cstring_fromChars (os));
2155
2156 if (annotationInfo_isDefined (ainfo)) {
2157 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
2158 /*@i324@*/ yylval.annotation = ainfo;
2159 tokLength = 0;
2160 sfree (os);
2161 sfree (t);
2162 fileloc_free (loc);
2163 return CANNOTATION;
2164 }
2165
885824d3 2166 if (context_inHeader ())
2167 {
2168 if (tchar != '\0')
2169 {
2170 *(s-1) = tchar;
2171 }
2172
2173 if ((context_inMacro () || context_inGlobalContext ())
2174 && macrocode != SKIPTOK
2175 && !isArtificial (cstring_fromChars (os)))
2176 {
28bf4b0b 2177 DPRINTF (("Add comment: %s", os));
885824d3 2178 context_addComment (cstring_fromCharsNew (os));
2179 }
2180 else
2181 {
2182 ;
2183 }
2184
2185 if (tchar != '\0')
2186 {
2187 *(s-1) = '\0';
2188 }
2189 }
2190
2191 if (mstring_equal (t, "ignore"))
2192 {
2193 if (!context_getFlag (FLG_NOCOMMENTS))
2194 {
2195 context_enterSuppressRegion ();
2196 }
2197 }
2198 else if ((*t == 'i' || *t == 't')
2199 && (*(t + 1) == '\0'))
2200 {
2201 if (!context_getFlag (FLG_NOCOMMENTS)
2202 && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))
2203 {
2204 context_enterSuppressLine (-1); /* infinite suppression */
2205 }
2206 }
2207 else if (((*t == 'i') || (*t == 't'))
2208 && ((*(t + 1) >= '0' && *(t + 1) <= '9')))
2209 {
2210 bool tmpcomment = (*t == 't');
2211 int val = -1;
2212 char *tt = t; /* don't mangle t, since it is free'd */
2213 char lc = *(++tt);
2214
2215 if (lc >= '0' && lc <= '9')
2216 {
2217 val = (int)(lc - '0');
2218
2219 lc = *(++tt);
2220 while (lc >= '0' && lc <= '9')
2221 {
2222 val *= 10;
2223 val += lc - '0';
2224 lc = *(++tt);
2225 }
2226 }
2227
2228
2229 if (!context_getFlag (FLG_NOCOMMENTS)
2230 && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
2231 {
2232 context_enterSuppressLine (val);
2233 }
2234 }
2235 else if (mstring_equal (t, "end"))
2236 {
2237 if (!context_getFlag (FLG_NOCOMMENTS))
2238 {
2239 context_exitSuppressRegion ();
2240 }
2241 }
2242 else if (mstring_equal (t, "notfunction"))
2243 {
2244 ; /* handled by pcpp */
2245 }
2246 else if (mstring_equal (t, "access"))
2247 {
2248 cstring tname;
2249
2250 while (TRUE)
2251 {
2252 while ((c = *s) && (c == ' ' || c == '\t' || c == '\n'))
2253 {
2254 s++;
2255 }
2256
2257 if (c == '\0')
2258 {
2259 break;
2260 }
2261
2262 tname = cstring_fromChars (s);
2263
2264 while ((c = *s) != '\0' && c != ' '
2265 && c != '\t' && c != '\n' && c != ',')
2266 {
2267 s++;
2268 }
2269
2270 *s = '\0';
2271
28bf4b0b 2272 DPRINTF (("Access %s", tname));
2273
885824d3 2274 if (!context_getFlag (FLG_NOCOMMENTS)
2275 && !context_getFlag (FLG_NOACCESS))
2276 {
2277 if (usymtab_existsType (tname))
2278 {
28bf4b0b 2279 typeId uid = usymtab_getTypeId (tname);
2280 uentry ue = usymtab_getTypeEntry (uid);
2281
2282 if (uentry_isAbstractDatatype (ue))
2283 {
2284 context_addFileAccessType (uid);
2285 DPRINTF (("Adding access to: %s / %d", tname, uid));
2286 }
2287 else
2288 {
2289 voptgenerror
2290 (FLG_COMMENTERROR,
2291 message
2292 ("Non-abstract type %s used in access comment",
2293 tname),
2294 g_currentloc);
2295 }
885824d3 2296 }
2297 else
2298 {
2299 if (!(context_inSuppressRegion ()
2300 || context_inSuppressZone (g_currentloc)))
2301 {
28bf4b0b 2302 voptgenerror
2303 (FLG_COMMENTERROR,
2304 message
2305 ("Unrecognized type %s used in access comment",
2306 tname),
2307 g_currentloc);
885824d3 2308 }
2309 }
2310 }
2311
2312 if (c != '\0')
2313 {
2314 s++;
2315 }
2316
2317 if (c != ',' && c != ' ')
2318 {
2319 break;
2320 }
2321 }
2322 }
2323 else if (mstring_equal (t, "noaccess"))
2324 {
2325 cstring tname;
2326 char lc;
2327
2328 while (TRUE)
2329 {
2330 while ((lc = *s) && (lc == ' ' || lc == '\t' || lc == '\n'))
2331 {
2332 s++;
2333 }
2334
2335 if (lc == '\0')
2336 {
2337 break;
2338 }
2339
2340 tname = cstring_fromChars (s);
2341
2342 while ((lc = *s) != '\0' && lc != ' ' && lc != '\t'
2343 && lc != '\n' && lc != ',')
2344 {
2345 s++;
2346 }
2347
2348 *s = '\0';
2349
2350 if (!context_getFlag (FLG_NOCOMMENTS)
2351 && !context_getFlag (FLG_NOACCESS))
2352 {
2353 if (usymtab_existsType (tname))
2354 {
2355 typeId tuid = usymtab_getTypeId (tname);
2356
2357 if (context_couldHaveAccess (tuid))
2358 {
28bf4b0b 2359 DPRINTF (("Removing access: %s", tname));
885824d3 2360 context_removeFileAccessType (tuid);
2361 }
2362 else
2363 {
2364 if (!(context_inSuppressRegion ()
2365 || context_inSuppressZone (g_currentloc)))
2366 {
2367 uentry ue = usymtab_getTypeEntry (tuid);
2368
2369 if (uentry_isAbstractDatatype (ue))
2370 {
28bf4b0b 2371 voptgenerror
2372 (FLG_COMMENTERROR,
2373 message
2374 ("Non-accessible abstract type %s used in noaccess comment",
2375 tname),
2376 g_currentloc);
885824d3 2377 }
2378 else
2379 {
28bf4b0b 2380 voptgenerror
2381 (FLG_COMMENTERROR,
2382 message
2383 ("Non-abstract type %s used in noaccess comment",
2384 tname),
2385 g_currentloc);
885824d3 2386 }
2387 }
2388 }
2389 }
2390 else
2391 {
2392 if (!(context_inSuppressRegion ()
2393 || context_inSuppressZone (g_currentloc)))
2394 {
28bf4b0b 2395 voptgenerror
2396 (FLG_COMMENTERROR,
2397 message
2398 ("Unrecognized type %s used in noaccess comment",
2399 tname),
2400 g_currentloc);
885824d3 2401 }
2402 }
2403 }
2404
2405 if (lc != '\0')
2406 {
2407 s++;
2408 }
2409
2410 if (lc != ',' && lc != ' ')
2411 {
2412 break;
2413 }
2414 }
2415 }
2416 else
2417 {
885824d3 2418 voptgenerror (FLG_UNRECOGCOMMENTS,
28bf4b0b 2419 message ("Semantic comment unrecognized: %s",
2420 cstring_fromChars (os)), loc);
885824d3 2421 }
2422
2423 sfree (t);
2424 }
2425
28bf4b0b 2426 sfree (os);
2427 fileloc_free (loc);
885824d3 2428 return BADTOK;
2429}
2430
2431static /*@only@*/ cstring makeIdentifier (char *s)
2432{
2433 char *c = mstring_create (size_toInt (strlen (s)) + 1);
2434 cstring id = cstring_fromChars (c);
2435
2436 while (isalnum (*s) || (*s == '_') || (*s == '$'))
2437 {
2438 *c++ = *s++;
2439 }
2440
2441 *c = '\0';
2442 return (id);
2443}
2444
2445/*@observer@*/ /*@dependent@*/ uentry coerceId (cstring cn)
2446{
2447 if (!(usymtab_exists (cn)))
2448 {
2449 fileloc loc = fileloc_createExternal ();
2450
2451 /*
2452 ** We need to put this in a global scope, otherwise the sRef will be deallocated.
2453 */
2454
2455 uentry ce = uentry_makeUnrecognized (cn, loc);
2456
2457 if (!context_inIterEnd ())
2458 {
2459 voptgenerror
2460 (FLG_SYSTEMUNRECOG,
2461 message ("Unrecognized (possibly system) identifier: %q",
2462 uentry_getName (ce)),
2463 g_currentloc);
2464 }
2465
2466 return ce;
2467 }
2468
2469 return (usymtab_lookup (cn));
2470}
2471
2472/*
2473** like, coerceId, but doesn't supercede for iters
2474*/
2475
2476/*@observer@*/ uentry coerceIterId (cstring cn)
2477{
2478 if (!(usymtab_exists (cn)))
2479 {
2480 return uentry_undefined;
2481 }
2482
2483 return (usymtab_lookup (cn));
2484}
2485
2486/*@observer@*/ cstring LastIdentifier ()
2487{
2488 return (lastidprocessed);
2489}
2490
2491static int processIdentifier (cstring id)
2492{
2493 uentry le;
2494
28bf4b0b 2495 DPRINTF (("Process identifier: %s / %s / %s", id, fileloc_unparse (g_currentloc),
2496 bool_unparse (context_inFunctionHeader ())));
885824d3 2497
2498 context_clearJustPopped ();
2499 lastidprocessed = id;
2500
28bf4b0b 2501 if (context_inFunctionHeader ())
885824d3 2502 {
2503 int tok = commentMarkerToken (id);
28bf4b0b 2504 DPRINTF (("in function decl..."));
885824d3 2505
2506 if (tok != BADTOK)
2507 {
2508 return tok;
2509 }
2510 else
2511 {
2512 tok = tokenMacroCode (id);
2513
2514 if (tok != BADTOK)
2515 {
2516 return tok;
2517 }
28bf4b0b 2518 else
2519 {
08eb3d0e 2520 annotationInfo ainfo;
2521
2522 if (expectingMetaStateName)
2523 {
2524 metaStateInfo msinfo = context_lookupMetaStateInfo (id);
2525
2526 if (metaStateInfo_isDefined (msinfo))
2527 {
2528 yylval.msinfo = msinfo;
2529 return METASTATE_NAME;
2530 }
2531 else
2532 {
ba45e1e4 2533 DPRINTF (("Not meta state name: %s", cstring_toCharsSafe (id)));
08eb3d0e 2534 }
2535 }
2536
2537 ainfo = context_lookupAnnotation (id);
28bf4b0b 2538
2539 if (annotationInfo_isDefined (ainfo))
2540 {
2541 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
2542 /*@i324@*/ yylval.annotation = ainfo;
2543 return CANNOTATION;
2544 }
2545 else
2546 {
2547 DPRINTF (("Not annotation: %s", id));
2548 }
2549 }
885824d3 2550 }
2551 }
2552
2553 /* Consider handling: Defined by C99 as static const char __func__[] */
2554
2555 if (context_getFlag (FLG_GNUEXTENSIONS))
2556 {
2557 int tok = BADTOK;
2558
2559 if (cstring_equalLit (id, "__stdcall")
2560 || cstring_equalLit (id, "__cdecl")
2561 || cstring_equalLit (id, "__extension__"))
2562 {
2563 return BADTOK;
2564 }
2565 else if (cstring_equalLit (id, "__volatile__"))
2566 {
2567 tok = QVOLATILE;
2568 }
2569 else if (cstring_equalLit (id, "__signed"))
2570 {
2571 tok = QSIGNED;
2572 }
2573 else if (cstring_equalLit (id, "__unsigned"))
2574 {
2575 tok = QUNSIGNED;
2576 }
2577 else if (cstring_equalLit (id, "__const__"))
2578 {
2579 tok = QCONST;
2580 }
2581 else if (cstring_equalLit (id, "__alignof__"))
2582 {
2583 tok = CALIGNOF; /* alignof is parsed like sizeof */
2584 }
2585 else if (cstring_equalLit (id, "__FUNCTION__")
2586 || cstring_equalLit (id, "__PRETTY_FUNCTION__"))
2587 {
2588 /* These tokens hold the name of the current function as strings */
2589 yylval.expr = exprNode_stringLiteral (id, fileloc_copy (g_currentloc));
2590 tokLength = 0;
2591 lastWasString = TRUE;
2592 tok = CCONSTANT;
2593 return tok;
2594 }
2595 else if (cstring_equalLit (id, "__attribute__")
2596 || cstring_equalLit (id, "__asm__")
2597 || cstring_equalLit (id, "_asm")
2598 || cstring_equalLit (id, "__asm")
2599 || cstring_equalLit (id, "__declspec"))
2600 {
2601 int depth = 0;
2602 bool useparens = FALSE;
2603 bool usebraces = FALSE;
2604 bool inquote = FALSE;
2605 bool inescape = FALSE;
2606 int ic;
2607
2608 while ((ic = input ()) != EOF)
2609 {
2610
2611 if (inescape)
2612 {
2613 inescape = FALSE;
2614 }
2615 else if (ic == '\\')
2616 {
2617 inescape = TRUE;
2618 }
2619 else if (ic == '\"')
2620 {
2621 inquote = !inquote;
2622 }
2623 else if (!inquote)
2624 {
2625 if (ic == '(')
2626 {
2627 if (!useparens)
2628 {
2629 if (!usebraces)
2630 {
2631 useparens = TRUE;
2632 }
2633 }
2634
2635 if (useparens)
2636 {
2637 depth++;
2638 }
2639 }
2640 else if (ic == '{')
2641 {
2642 if (!usebraces)
2643 {
2644 if (!useparens)
2645 {
2646 usebraces = TRUE;
2647 }
2648 }
2649
2650 if (usebraces)
2651 {
2652 depth++;
2653 }
2654 }
2655 else if (ic == ')' && useparens)
2656 {
2657 depth--;
2658 if (depth == 0) break;
2659 }
2660 else if (ic == '}' && usebraces)
2661 {
2662 depth--;
2663 if (depth == 0) break;
2664 }
2665 else if (ic == '}'
2666 && !usebraces && !useparens
2667 && cstring_equalLit (id, "__asm"))
2668 {
2669 /*
2670 ** We need this because some MS VC++ include files
2671 ** have __asm mov ... }
2672 ** Its a kludge, but otherwise would need to parse
2673 ** the asm code!
2674 */
2675 return TRBRACE;
2676 }
2677 }
2678
2679 if (ic == '\n')
2680 {
2681 context_incLineno ();
2682
2683 if (cstring_equalLit (id, "__asm")
2684 && !useparens && !usebraces)
2685 {
2686 break;
2687 }
2688 }
2689 }
2690
2691 llassert ((useparens && ic == ')')
2692 || (usebraces && ic == '}')
2693 || (!useparens && !usebraces));
2694
2695 return BADTOK;
2696 }
2697 else if (cstring_equalLit (id, "inline")
2698 || cstring_equalLit (id, "__inline")
2699 || cstring_equalLit (id, "_inline")
2700 || cstring_equalLit (id, "__inline__"))
2701 {
2702 tok = QINLINE;
2703 }
2704
2705 if (tok != BADTOK)
2706 {
2707 RETURN_TOK (tok);
2708 }
2709 }
2710
2711 le = usymtab_lookupSafe (id);
2712
2713 /*@-dependenttrans@*/
2714
2715 if (uentry_isIter (le))
2716 {
28bf4b0b 2717 /*@i32@*/ yylval.entry = le;
885824d3 2718 return (ITER_NAME);
2719 }
2720 else if (uentry_isEndIter (le))
2721 {
28bf4b0b 2722 /*@i32@*/ yylval.entry = le;
885824d3 2723 return (ITER_ENDNAME);
2724 }
2725 else if (uentry_isUndefined (le))
2726 {
2727 yylval.cname = id;
2728
2729 /* avoid parse errors for certain system built ins */
2730
2731 if (g_expectingTypeName && (cstring_firstChar (id) == '_')
2732 && (cstring_secondChar (id) == '_'))
2733 {
2734 return (TYPE_NAME_OR_ID);
2735 }
2736
2737 return (NEW_IDENTIFIER);
2738 }
2739 else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))
2740 {
2741 if (uentry_isDatatype (le))
2742 {
2743 yylval.cname = id;
2744 return (NEW_IDENTIFIER);
2745 }
2746 else
2747 {
28bf4b0b 2748 /*@i32@*/ yylval.entry = le;
885824d3 2749 return (IDENTIFIER);
2750 }
2751 }
2752 else if (uentry_isDatatype (le))
2753 {
2754 if (!g_expectingTypeName)
2755 {
2756 yylval.cname = id;
2757
2758 return (NEW_IDENTIFIER);
2759 }
2760 else
2761 {
2762 yylval.ctyp = uentry_getAbstractType (le);
2763
2764 uentry_setUsed (le, g_currentloc);
2765 return (TYPE_NAME);
2766 }
2767 }
2768 else
2769 {
28bf4b0b 2770 /*@i32@*/ yylval.entry = le;
885824d3 2771 return (IDENTIFIER);
2772 }
2773
2774 /*@=dependenttrans@*/
2775}
2776
2777static bool processHashIdentifier (/*@only@*/ cstring id)
2778{
2779 if (context_inMacro () || context_inIterDef () ||
2780 context_inIterEnd ())
2781 {
2782 uentry le;
2783
2784 context_clearJustPopped ();
2785
2786 lastidprocessed = id;
2787 le = usymtab_lookupSafe (id);
2788
2789 if (uentry_isParam (le) || uentry_isRefParam (le))
2790 {
2791 return TRUE;
2792 }
2793 else
2794 {
2795 return FALSE;
2796 }
2797 }
2798 else
2799 {
2800 cstring_free (id);
2801 return FALSE;
2802 }
2803}
2804
2805
2806static /*@only@*/ exprNode processString ()
2807{
2808 exprNode res;
2809 fileloc loc;
2810 char *nl = strchr (yytext, '\n');
2811 cstring ns = cstring_fromCharsNew (yytext);
2812
2813 if (nl == NULL)
2814 {
2815 loc = fileloc_copy (g_currentloc);
2816 addColumn (cstring_length (ns));
2817 }
2818 else
2819 {
2820 char *lastnl = nl;
2821
2822 loc = fileloc_copy (g_currentloc);
2823
2824 context_incLineno ();
2825
2826 while ((nl = strchr ((nl + 1), '\n')) != NULL)
2827 {
2828 context_incLineno ();
2829 lastnl = nl;
2830 }
2831 }
2832
2833
2834 res = exprNode_stringLiteral (ns, loc);
2835 return (res);
2836}
2837
2838static
2839char processChar ()
2840{
2841 char fchar;
2842 char next;
2843
2844 llassert (*yytext != '\0');
2845 fchar = *(yytext + 1);
2846 if (fchar != '\\') return fchar;
2847
2848 next = *(yytext + 2);
2849
2850 switch (next)
2851 {
2852 case 'n': return '\n';
2853 case 't': return '\t';
2854 case '\"': return '\"';
2855 case '\'': return '\'';
2856 case '\\': return '\\';
2857 default: return '\0';
2858 }
2859}
2860
2861static
2862double processFloat ()
2863{
2864 double ret = atof (yytext);
2865
2866 return (ret);
2867}
2868
2869static
2870long processHex ()
2871{
2872 int index = 2;
2873 long val = 0;
2874
2875 llassert (yytext[0] == '0'
2876 && (yytext[1] == 'X' || yytext[1] == 'x'));
2877
2878 while (yytext[index] != '\0') {
2879 int tval;
2880 char c = yytext[index];
2881
2882 if (c >= '0' && c <= '9') {
2883 tval = (int) c - (int) '0';
2884 } else if (c >= 'A' && c <= 'F') {
2885 tval = (int) c - (int) 'A' + 10;
2886 } else if (c >= 'a' && c <= 'f') {
2887 tval = (int) c - (int) 'a' + 10;
a0a162cd 2888 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2889 index++;
2890 while (yytext[index] != '\0') {
2891 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2892 ;
2893 } else {
2894 voptgenerror
2895 (FLG_SYNTAX,
2896 message ("Invalid character (%c) following specifier in hex constant: %s",
2897 c, cstring_fromChars (yytext)),
2898 g_currentloc);
2899 }
2900 index++;
2901 }
2902
2903 break;
885824d3 2904 } else {
2905 voptgenerror
2906 (FLG_SYNTAX,
2907 message ("Invalid character (%c) in hex constant: %s",
2908 c, cstring_fromChars (yytext)),
2909 g_currentloc);
2910 break;
2911 }
2912
2913 val = (val * 16) + tval;
2914 index++;
2915 }
2916
2917 DPRINTF (("Hex constant: %s = %ld", yytext, val));
2918 return val;
2919}
2920
2921static
2922long processOctal ()
2923{
2924 int index = 1;
2925 long val = 0;
2926
2927 llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');
2928
2929 while (yytext[index] != '\0') {
2930 int tval;
2931 char c = yytext[index];
2932
2933 if (c >= '0' && c <= '7') {
2934 tval = (int) c - (int) '0';
2935 } else {
2936 voptgenerror
2937 (FLG_SYNTAX,
2938 message ("Invalid character (%c) in octal constant: %s",
2939 c, cstring_fromChars (yytext)),
2940 g_currentloc);
2941 break;
2942 }
2943
2944 val = (val * 8) + tval;
2945 index++;
2946 }
2947
2948 DPRINTF (("Octal constant: %s = %ld", yytext, val));
2949 return val;
2950}
2951
2952static
2953long processDec ()
2954{
2955 return (atol (yytext));
2956}
2957
2958static int
2959processSpec (int tok)
2960{
2961 size_t length = strlen (yytext);
2962
2963
2964 if (inSpecPart)
2965 {
2966 setTokLengthT (length);
2967 RETURN_TOK (tok);
2968 }
2969 else
2970 {
2971
2972 context_saveLocation ();
2973 setTokLengthT (length);
2974 return (processIdentifier (makeIdentifier (yytext)));
2975 }
2976}
08eb3d0e 2977
2978void cscanner_expectingMetaStateName ()
2979{
2980 llassert (!expectingMetaStateName);
2981 llassert (context_inFunctionHeader ());
2982 expectingMetaStateName = TRUE;
2983}
2984
2985void cscanner_clearExpectingMetaStateName ()
2986{
2987 llassert (expectingMetaStateName);
2988 expectingMetaStateName = FALSE;
2989}
This page took 0.453651 seconds and 5 git commands to generate.