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