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