]> andersk Git - splint.git/blob - src/cscanner.l
Fixed anytype resolution.
[splint.git] / src / cscanner.l
1 /*;-*-C-*-; 
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
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.
19 **
20 ** For information on splint: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** cscanner.l
26 **
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
30 */
31 /*
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 */
36 /*
37 ** Modified by Mike Smith 
38 ** Corrected missing 'line' in scanf() calls in handleSpecial().
39 ** Without this, I get an error when Splint hits a '#line' directive
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 */
55
56 Digit                   [0-9]
57 Letter                  [a-zA-Z_$]
58 H                       [a-fA-F0-9]
59 E                       [Ee][+-]?{Digit}+
60 U                       (u|U)
61 L                       (l|L)
62 FS                      (f|F|l|L)
63 IS                      (u|U|l|L)*
64 ULSuffix                ({U}{L}|{L}{U})
65
66 %{
67 # include "splintMacros.nf"
68 # if defined(OS2) && defined(__IBMC__)
69    /* needed for isatty()... */
70 # include <io.h>
71 # else
72
73 /*
74 ** Win32 doesn't have unistd.h
75 */
76
77 # ifndef WIN32
78 # include <unistd.h>
79 # endif
80
81 # endif
82
83 # include "basic.h"
84
85 # include "cgrammar.h"
86 # include "cgrammar_tokens.h"
87
88 # include "fileIdList.h"
89 # include "portab.h"
90
91 static bool lastWasString = FALSE;
92 static char savechar = '\0';
93
94 /*@notfunction@*/
95 # define yyinput() (incColumn (), getc (yyin))
96
97 static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
98 static int lminput (void);
99 static int tokLength = 0;
100 static bool inSpecPart = FALSE;
101 static bool continueLine = FALSE;
102
103 static int ninput (void);
104 static char processChar (void);
105 static double processFloat (void);
106 static /*@only@*/ exprNode processString (void) ;
107 static /*@only@*/ exprNode processWideString (void) ;
108 static long processDec (void);
109 static long processHex (void);
110 static long processOctal (void);
111 static int processIdentifier (/*@only@*/ cstring)
112    /*@globals undef lastidprocessed@*/ ;
113 static bool processHashIdentifier (/*@only@*/ cstring)
114    /*@globals undef lastidprocessed@*/ ;
115
116 static int processSpec (int);
117 static bool handleSpecial (char *);
118 static int handleLlSpecial (void);
119 static void handleMacro (void);
120 static bool processMacro (void);
121 static /*@only@*/ cstring makeIdentifier (char *);
122
123 /* yes, this is exported! */
124 bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */
125
126 static bool expectingMetaStateName = FALSE;
127
128 static int returnInt (ctype, long);
129 static int returnFloat (ctype, double);
130 static int returnChar (char);
131 static void setTokLength (int) /*@modifies g_currentloc@*/ ;
132 static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;
133
134 static 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
182 static void setTokLength (int len) 
183 {
184   addColumn (len);
185   tokLength = len;
186   DPRINTF (("Set tok length: %d", len));
187 }
188
189 static 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 "/*"            { llfatalerror (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 ()); }
284 L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processWideString ()); }
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)); } 
299 "nullwhentrue"          { return (processSpec (QTRUENULL)); } 
300 "nullwhenfalse"             { return (processSpec (QFALSENULL)); } 
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                             }
338 0[xX]{H}+               { setTokLengthT (mstring_length (yytext)); 
339                           RETURN_INT (ctype_int, processHex ());  /* evs 2000-05-17 was ctype_uint */
340                         }
341 0[xX]{H}+{L}            { setTokLengthT (mstring_length (yytext)); 
342                           RETURN_INT (ctype_lint, processHex ()); }
343 0[xX]{H}+{L}{L}         { setTokLengthT (mstring_length (yytext)); 
344                           RETURN_INT (ctype_llint, processHex ()); }
345 0[xX]{H}+{U}            { setTokLengthT (mstring_length (yytext)); 
346                           RETURN_INT (ctype_uint, processHex ()); }
347 0[xX]{H}+{ULSuffix}     { setTokLengthT (mstring_length (yytext)); 
348                           RETURN_INT (ctype_ulint, processHex ()); }
349 0[xX]{H}+{U}{L}{L}      { setTokLengthT (mstring_length (yytext)); 
350                           RETURN_INT (ctype_ullint, processHex ()); }
351 0[xX]{H}+{L}{L}{U}      { setTokLengthT (mstring_length (yytext)); 
352                           RETURN_INT (ctype_ullint, processHex ()); }
353 0{Digit}+               { setTokLengthT (mstring_length (yytext)); 
354                           RETURN_INT (ctype_int, processOctal ()); } 
355 0{Digit}+{U}            { setTokLengthT (mstring_length (yytext)); 
356                           RETURN_INT (ctype_uint, processOctal ()); } 
357 0{Digit}+{L}            { setTokLengthT (mstring_length (yytext)); 
358                           RETURN_INT (ctype_lint, processOctal ()); } 
359 0{Digit}+{L}{L}         { setTokLengthT (mstring_length (yytext)); 
360                           RETURN_INT (ctype_llint, processOctal ()); } 
361 0{Digit}+{ULSuffix}     { setTokLengthT (mstring_length (yytext)); 
362                           RETURN_INT (ctype_ulint, processOctal ()); } 
363 0{Digit}+{U}{L}{L}      { setTokLengthT (mstring_length (yytext)); 
364                           RETURN_INT (ctype_ullint, processOctal ()); } 
365 0{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 ()); }
383 L'(\\.|[^\\'])+'       { 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 */
479                          yylval.tok = lltok_create (TENDMACRO, fileloc_copy (g_currentloc)); /* !!! evans 2002-03-13 */
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                         {
523                           DPRINTF (("Here we are: %s", context_unparse ()));
524                           
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
592 struct 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
603 struct 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 } ,
623   { "invariant", QINVARIANT} ,
624   { NULL, BADTOK } 
625 } ;
626
627 /*
628 ** These tokens are either stand-alone tokens, or followed by 
629 ** token-specific text.
630 */
631
632 struct 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 } ,
646   { "nullwhentrue", QTRUENULL } ,
647   { "falsewhennull", QFALSENULL } ,
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 } ,
676   { "noreturn", QEXITS } ,
677   { "mayexit", QMAYEXIT } ,
678   { "maynotreturn", QMAYEXIT } ,
679   { "trueexit", QTRUEEXIT } ,
680   { "falseexit", QFALSEEXIT } ,
681   { "noreturnwhentrue", QTRUEEXIT } ,
682   { "noreturnwhenfalse", QFALSEEXIT } ,
683   { "neverexit", QNEVEREXIT } ,
684   { "alwaysreturns", QNEVEREXIT } ,
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
714 static 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
722 void 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
756 static 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
775 static 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
788                  ("Traditional lint comment /*FALLTHROUGH*/ used. "
789                   "Splint interprets this in the same way as most Unix lints, but it is "
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
800                  ("Traditional lint comment /*FALLTHRU*/ used. "
801                   "Splint interprets this in the same way as most Unix lints, but it is "
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
812                  ("Traditional lint comment /*NOTREACHED*/ used. "
813                   "Splint interprets this in the same way as most Unix lints, but it is "
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
830                  ("Traditional lint comment /*PRINTFLIKE*/ used. "
831                   "Splint interprets this in the same way as most Unix lints, but it is "
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
854                  ("Traditional lint comment /*ARGSUSED*/ used. "
855                   "Splint interprets this in the same way as most Unix lints, but it is "
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
873 static 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
888 static void lmsavechar (char c)
889 {
890   if (savechar == '\0') savechar = c;
891   else
892     {
893       llbuglit ("lmsavechar: override");
894     }
895 }
896
897 static 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
905 static 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
927 static 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
935 static 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
947 static 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
1051 static 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
1140 static char skip_whitespace ()
1141 {
1142   char c;
1143
1144   while ((c = macro_nextChar ()) == ' ' || c == '\t')
1145     {
1146       ;
1147     }
1148
1149   return c;
1150 }
1151
1152 static 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
1203 static 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
1709 static bool handleSpecial (char *yyt)
1710 {
1711   char *l = mstring_create (MAX_NAME_LENGTH);
1712   int lineno = 0;
1713   char c;
1714   char *ol;
1715   cstring olc;
1716
1717   int len_yyt;
1718
1719   len_yyt = strlen (yyt +1) ;
1720
1721   l = mstring_copy (yyt + 1);
1722   
1723   while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')
1724     {
1725       l = mstring_append(l, c);
1726     }
1727
1728     /* Need to safe original l for deallocating. */
1729   ol = l;
1730
1731   l += strlen (l);
1732
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 {
1908         voptgenerror
1909           (FLG_UNRECOGDIRECTIVE,
1910            message ("Unrecognized pre-processor directive: #%s", 
1911                     cstring_fromChars (ol)),
1912            g_currentloc);
1913       }
1914       
1915       sfree (ol);
1916       return FALSE; /* evans 2001-12-30: was: TRUE; */
1917     }
1918
1919   sfree (ol);
1920   return FALSE;
1921 }
1922   
1923 static 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)),
1998                loc);
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;
2046               flagcode fflag = flags_identifyFlag (flagname);
2047               
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),
2076                          loc);
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),
2087                      loc);
2088                 }
2089               else
2090                 {
2091                   context_fileSetFlag (fflag, set, loc);
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),
2103                              loc);
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                               
2146                               if (flagcode_hasNumber (fflag))
2147                                 {
2148                                   setValueFlag (fflag, extra);
2149                                 }
2150                               else if (flagcode_hasChar (fflag))
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));
2182           context_addComment (cstring_fromCharsNew (os), loc);
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             {
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                 }
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             {
2274               context_enterSuppressRegion (loc);
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             {
2283               context_enterSuppressLine (-1, loc); /* infinite suppression */
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             }
2306           
2307           if (!context_getFlag (FLG_NOCOMMENTS)
2308               && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
2309             {
2310               DPRINTF (("Here: enter suppress: %s", fileloc_unparse (loc)));
2311               context_enterSuppressLine (val, loc);
2312             }
2313         }
2314       else if (mstring_equal (t, "end"))
2315         {
2316           if (!context_getFlag (FLG_NOCOMMENTS))
2317             {
2318               context_exitSuppressRegion (loc);
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),
2373                              loc);
2374                         }
2375                     }
2376                   else
2377                     {
2378                       if (!(context_inSuppressRegion ()
2379                             || context_inSuppressZone (loc)))
2380                         {
2381                           voptgenerror
2382                             (FLG_COMMENTERROR,
2383                              message
2384                              ("Unrecognized type %s used in access comment",
2385                               tname),
2386                              loc);
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 () 
2444                                 || context_inSuppressZone (loc)))
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),
2455                                      loc);
2456                                 }
2457                               else
2458                                 {
2459                                   voptgenerror
2460                                     (FLG_COMMENTERROR,
2461                                      message
2462                                      ("Non-abstract type %s used in noaccess comment",
2463                                       tname),
2464                                      loc);
2465                                 }
2466                             }
2467                         }
2468                     }
2469                   else
2470                     {
2471                       if (!(context_inSuppressRegion () 
2472                             || context_inSuppressZone (loc)))
2473                         {
2474                           voptgenerror
2475                             (FLG_COMMENTERROR,
2476                              message
2477                              ("Unrecognized type %s used in noaccess comment",
2478                               tname),
2479                              loc);
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", 
2499                                  cstring_fromChars (os)),
2500                         loc);
2501         }
2502       
2503       sfree (t);
2504     }
2505   
2506   sfree (os);
2507   fileloc_free (loc);
2508   return BADTOK;
2509 }
2510
2511 static /*@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
2571 static 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         }
2667       else if (cstring_equalLit (id, "__typeof__")) 
2668         {
2669           tok = CTYPEOF;
2670         }
2671       else if (cstring_equalLit (id, "typeof")) 
2672         {
2673           tok = CTYPEOF;
2674         }
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 */
2679           /* evans 2001-12-30: changed from exprNode_stringLiteral; bug reported by Jim Zelenka. */
2680           yylval.expr = exprNode_makeConstantString (id, fileloc_copy (g_currentloc));
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
2868 static 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     {
2891       /*
2892       ** Will be handled by handleLlSpecial
2893       */
2894
2895       cstring_free (id);
2896       return FALSE;
2897     }
2898 }
2899
2900
2901 static /*@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
2933 /*
2934 ** process a wide character string L"...."
2935 */
2936
2937 static /*@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
2973 static 
2974 char 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
2996 static
2997 double processFloat ()
2998 {
2999   double ret = atof (yytext);
3000
3001     return (ret);
3002 }
3003
3004 static
3005 long 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
3056 static
3057 long 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';
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;
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
3103 static
3104 long processDec ()
3105 {
3106   return (atol (yytext));
3107 }
3108
3109 static int
3110 processSpec (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
3128 void cscanner_expectingMetaStateName ()
3129 {
3130   llassert (!expectingMetaStateName);
3131   llassert (context_inFunctionHeader ());
3132   expectingMetaStateName = TRUE;
3133 }
3134
3135 void cscanner_clearExpectingMetaStateName ()
3136 {
3137   llassert (expectingMetaStateName);
3138   expectingMetaStateName = FALSE;
3139 }
This page took 0.313692 seconds and 5 git commands to generate.