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