-/*;-*-C-*-;
-** Copyright (c) Massachusetts Institute of Technology 1994-1998.
-** All Rights Reserved.
-** Unpublished rights reserved under the copyright laws of
-** the United States.
-**
-** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
-** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
-**
-** This code is distributed freely and may be used freely under the
-** following conditions:
-**
-** 1. This notice may not be removed or altered.
-**
-** 2. Works derived from this code are not distributed for
-** commercial gain without explicit permission from MIT
-** (for permission contact lclint-request@sds.lcs.mit.edu).
-*/
-/*
- * Modified by Herbert 08/19/97:
- * - added #include for IBM's OS/2 compiler.
- * - fixed weird bug with lookup of tmp files (OS/2 and MSDOS only).
- */
-
-/*
- * Modified by Mike Smith
- * Corrected missing 'line' in scanf() calls in handleSpecial().
- * Without this, I get an error when LCLint hits a '#line' directive
- * in the pre-pre-processed source files. For safety, I have made these
- * conditional on OS2 and MSDOS because I don't understand why noone else
- * has seen this problem.
- *
- * Modified by Mike Smith, 4th June 1997
- * Finally resolved the #line problem. The scanf() calls have been fixed to
- * allow the following #line forms:-
- *
- * #line 123 "filename"
- * #line 123
- * # 123 "filename"
- * # 123
- *
- * The last two are generated by the GNU pre-processor, apparently
- */
-
-Digit [0-9]
-Letter [a-zA-Z_$]
-H [a-fA-F0-9]
-E [Ee][+-]?{Digit}+
-U (u|U)
-L (l|L)
-FS (f|F|l|L)
-IS (u|U|l|L)*
-ULSuffix ({U}{L}|{L}{U})
-
-%{
-/*
-** based on original C lexer by Nate Osgood
-** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993
-**
-*/
-
-# include "lclintMacros.nf"
-# include <unistd.h>
-# include "basic.h"
-
-# include "cgrammar.h"
-# include "cgrammar_tokens.h"
-
-# include "fileIdList.h"
-# include "portab.h"
-
-# if defined(OS2) && defined(__IBMC__)
- /* needed for isatty()... */
-# include <io.h>
-# endif
-
-static bool lastWasString = FALSE;
-static char savechar = '\0';
-
-/*@notfunction@*/
-# define yyinput() (incColumn (), getc (yyin))
-
-static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
-static int lminput (void);
-static int tokLength = 0;
-static bool inSpecPart = FALSE;
-static bool continueLine = FALSE;
-
-static int ninput (void);
-static char processChar (void);
-static double processFloat (void);
-static /*@only@*/ exprNode processString (void);
-static long processDec (void);
-static long processHex (void);
-static long processOctal (void);
-static int processIdentifier (/*@only@*/ cstring)
- /*@globals undef lastidprocessed@*/ ;
-static bool processHashIdentifier (/*@only@*/ cstring)
- /*@globals undef lastidprocessed@*/ ;
-
-static int processSpec (int);
-static bool handleSpecial (char *);
-static int handleLlSpecial (void);
-static void handleMacro (void);
-static bool processMacro (void);
-static /*@only@*/ cstring makeIdentifier (char *);
-
-/* yes, this is exported! */
-bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */
-
-static bool expectingMetaStateName = FALSE;
-
-static int returnInt (ctype, long);
-static int returnFloat (ctype, double);
-static int returnChar (char);
-static void setTokLength (int) /*@modifies g_currentloc@*/ ;
-static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;
-
-static void advanceLine (void)
-{
- tokLength = 0;
- beginLine ();
-}
-
-/*@-allmacros@*/
-# define RETURN_INT(c,i) \
- do { lastWasString = FALSE; \
- return (returnInt (c, i)); } while (FALSE)
-
-# define RETURN_FLOAT(c,f) \
- do { lastWasString = FALSE; \
- return (returnFloat (c, f)); \
- } while (FALSE)
-
-# define RETURN_CHAR(c) \
- do { lastWasString = FALSE; \
- return (returnChar (c)); \
- } while (FALSE)
-
-# define RETURN_TOK(t) \
- do { yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, tokLength)); \
- tokLength = 0; \
- lastWasString = FALSE; \
- return (t); } while (FALSE)
-
-# define RETURN_TYPE(t, ct) \
- do { yylval.ctyp = ct; tokLength = 0; return (t); } while (FALSE)
-
-/* don't fileloc_decColumn (g_currentloc, tokLength));
- the string could have \n's in it!
-*/
-
-# define RETURN_STRING(c) \
- do { yylval.expr = exprNode_stringLiteral (c, fileloc_decColumn (g_currentloc, tokLength)); \
- tokLength = 0; \
- lastWasString = TRUE; \
- return (CCONSTANT); } while (FALSE)
-
-# define RETURN_EXPR(e) \
- do { yylval.expr = e; \
- tokLength = 0; \
- lastWasString = TRUE; \
- return (CCONSTANT); } while (FALSE)
-
-/*@=allmacros@*/
-
-static void setTokLength (int len)
-{
- addColumn (len);
- tokLength = len;
- DPRINTF (("Set tok length: %d", len));
-}
-
-static void setTokLengthT (size_t len)
-{
- setTokLength (size_toInt (len));
-}
-
-# include "flex.head"
-
-/*@-unrecog@*/ /*@i5343@*/
-
-%}
-
-%%
-
-"/*" { llfatalbug (cstring_makeLiteral ("Comment in pre-processor output")); }
-
-"#"{Letter}({Letter}|{Digit})* {
- context_saveLocation ();
- setTokLength (longUnsigned_toInt (mstring_length (yytext)));
-
- if (processHashIdentifier (makeIdentifier (yytext + 1)))
- {
- if (lastWasString)
- {
- /* was nothing! */ /*@i32@*/
- RETURN_STRING (cstring_makeLiteral ("\"\""));
- }
- else
- {
- RETURN_STRING (cstring_makeLiteral ("\"\""));
- }
- }
- else
- {
- if (handleSpecial (yytext))
- {
- setTokLength (1);
- RETURN_TOK (0);
- }
- }
- }
-"#" { if (handleSpecial (yytext))
- {
- setTokLength (1); RETURN_TOK (0);
- }
- }
-"..." { setTokLength (3); RETURN_TOK (CTOK_ELIPSIS); }
-"break" { setTokLength (5); RETURN_TOK (BREAK); }
-"case" { setTokLength (4); RETURN_TOK (CASE); }
-"continue" { setTokLength (8); RETURN_TOK (CONTINUE); }
-"default" { setTokLength (7); RETURN_TOK (DEFAULT); }
-"do" { setTokLength (2); RETURN_TOK (DO); }
-"else" { setTokLength (4); RETURN_TOK (CELSE); }
-"for" { setTokLength (3); RETURN_TOK (CFOR); }
-"goto" { setTokLength (4); RETURN_TOK (GOTO); }
-"if" { setTokLength (2); RETURN_TOK (CIF); }
-"return" { setTokLength (6); RETURN_TOK (RETURN); }
-"sizeof" { setTokLength (6); RETURN_TOK (CSIZEOF); }
-"offsetof" { setTokLength (8); RETURN_TOK (COFFSETOF); }
-"switch" { setTokLength (6); RETURN_TOK (SWITCH); }
-"while" { setTokLength (5); RETURN_TOK (WHILE); }
-"va_arg" { setTokLength (6); RETURN_TOK (VA_ARG); }
-"va_dcl" { setTokLength (6); RETURN_TOK (VA_DCL); }
-"inline" {
- /* gcc extension...this might not be appropriate */
- setTokLength (6); RETURN_TOK (QINLINE); }
-
-"struct" { setTokLength (6); RETURN_TOK (CSTRUCT); }
-"typedef" { setTokLength (7); RETURN_TOK (CTYPEDEF); }
-
-"union" { setTokLength (5); RETURN_TOK (CUNION); }
-"enum" { setTokLength (4); RETURN_TOK (CENUM); }
-
-"void" { setTokLength (4); RETURN_TYPE (CVOID, ctype_void); }
-"int" { setTokLength (3); RETURN_TYPE (CINT, ctype_int); }
-"double" { setTokLength (6); RETURN_TYPE (CDOUBLE, ctype_double); }
-"char" { setTokLength (4); RETURN_TYPE (CGCHAR, ctype_char); }
-"float" { setTokLength (5); RETURN_TYPE (CGFLOAT, ctype_float); }
-
-"long" { setTokLength (4); RETURN_TOK (QLONG); }
-"short" { setTokLength (5); RETURN_TOK (QSHORT); }
-"unsigned" { setTokLength (8); RETURN_TOK (QUNSIGNED); }
-"signed" { setTokLength (6); RETURN_TOK (QSIGNED); }
-
-"volatile" { setTokLength (8); RETURN_TOK (QVOLATILE); }
-"const" { setTokLength (5); RETURN_TOK (QCONST); }
-
- /* some systems expect this! [gack!] */
-"__const" { setTokLength (7); RETURN_TOK (QCONST); }
-
-"extern" { setTokLength (6); RETURN_TOK (QEXTERN); }
-"auto" { setTokLength (4); RETURN_TOK (QAUTO); }
-"register" { setTokLength (8); RETURN_TOK (QREGISTER); }
-"static" { setTokLength (6); RETURN_TOK (QSTATIC); }
-
-\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
-L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
-"out" { return (processSpec (QOUT)); }
-"in" { return (processSpec (QIN)); }
-"partial" { return (processSpec (QPARTIAL)); }
-"special" { return (processSpec (QSPECIAL)); }
-"anytype" { return (processSpec (QANYTYPE)); }
-"integraltype" { return (processSpec (QINTEGRALTYPE)); }
-"unsignedintegraltype" { return (processSpec (QUNSIGNEDINTEGRALTYPE)); }
-"signedintegraltype" { return (processSpec (QSIGNEDINTEGRALTYPE)); }
-"keep" { return (processSpec (QKEEP)); }
-"null" { return (processSpec (QNULL)); }
-"notnull" { return (processSpec (QNOTNULL)); }
-"isnull" { return (processSpec (QISNULL)); }
-"truenull" { return (processSpec (QTRUENULL)); }
-"falsenull" { return (processSpec (QFALSENULL)); }
-"relnull" { return (processSpec (QRELNULL)); }
-"reldef" { return (processSpec (QRELDEF)); }
-"exposed" { return (processSpec (QEXPOSED)); }
-"newref" { return (processSpec (QNEWREF)); }
-"tempref" { return (processSpec (QTEMPREF)); }
-"killref" { return (processSpec (QKILLREF)); }
-"refcounted" { return (processSpec (QREFCOUNTED)); }
-"checked" { return (processSpec (QCHECKED)); }
-"checkmod" { return (processSpec (QCHECKMOD)); }
-"checkedstrict" { return (processSpec (QCHECKEDSTRICT)); }
-"unchecked" { return (processSpec (QUNCHECKED)); }
-"only" { return (processSpec (QONLY)); }
-"owned" { return (processSpec (QOWNED)); }
-"observer" { return (processSpec (QOBSERVER)); }
-"dependent" { return (processSpec (QDEPENDENT)); }
-"unused" { return (processSpec (QUNUSED)); }
-"external" { return (processSpec (QEXTERNAL)); }
-"sef" { return (processSpec (QSEF)); }
-"shared" { return (processSpec (QSHARED)); }
-"yield" { return (processSpec (QYIELD)); }
-"undef" { return (processSpec (QUNDEF)); }
-"killed" { return (processSpec (QKILLED)); }
-"nullterminated" { return (processSpec (QNULLTERMINATED));}
-"MaxSet" { return (processSpec (QMAXSET));}
-"MaxRead" { return (processSpec (QMAXREAD));}
-"maxSet" { return (processSpec (QMAXSET));}
-"maxRead" { return (processSpec (QMAXREAD));}
-
-{Letter}({Letter}|{Digit})* { int tok;
- context_saveLocation ();
- setTokLength (longUnsigned_toInt (mstring_length (yytext)));
- tok = processIdentifier (makeIdentifier (yytext));
- if (tok != BADTOK)
- {
- return (tok);
- }
- }
-0[xX]{H}+ { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_int, processHex ()); /* evs 2000-05-17 was ctype_uint */
- }
-0[xX]{H}+{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_lint, processHex ()); }
-0[xX]{H}+{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_llint, processHex ()); }
-0[xX]{H}+{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_uint, processHex ()); }
-0[xX]{H}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ulint, processHex ()); }
-0[xX]{H}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processHex ()); }
-0[xX]{H}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processHex ()); }
-0{Digit}+ { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_int, processOctal ()); }
-0{Digit}+{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_uint, processOctal ()); }
-0{Digit}+{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_lint, processOctal ()); }
-0{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_llint, processOctal ()); }
-0{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ulint, processOctal ()); }
-0{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processOctal ()); }
-0{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processOctal ()); }
-{Digit}+ { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_int, processDec ()); }
-{Digit}+{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_uint, processDec ()); }
-{Digit}+{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_lint, processDec ()); }
-{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_llint, processDec ()); }
-{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ulint, processDec ()); }
-{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processDec ()); }
-{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
- RETURN_INT (ctype_ullint, processDec ()); }
-'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext));
- RETURN_CHAR (processChar ()); }
-L'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext));
- RETURN_CHAR (processChar ()); }
-{Digit}+{E}[fF] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_float, processFloat ()); }
-{Digit}+{E}[lL] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_ldouble, processFloat ()); }
-{Digit}+{E} { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_double, processFloat ()); }
-
-{Digit}*"."{Digit}+({E})?[fF] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_float, processFloat ()); }
-{Digit}*"."{Digit}+({E})?[lL] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_ldouble, processFloat ()); }
-{Digit}*"."{Digit}+({E})? { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_double, processFloat ()); }
-
-{Digit}+"."{Digit}*({E})?[fF] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_float, processFloat ()); }
-{Digit}+"."{Digit}*({E})?[lL] { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_ldouble, processFloat ()); }
-{Digit}+"."{Digit}*({E})? { setTokLengthT (mstring_length (yytext));
- RETURN_FLOAT (ctype_double, processFloat ()); }
-
-">>=" { setTokLength (3); RETURN_TOK (RIGHT_ASSIGN); }
-"<<=" { setTokLength (3); RETURN_TOK (LEFT_ASSIGN); }
-"+=" { setTokLength (2); RETURN_TOK (ADD_ASSIGN); }
-"-=" { setTokLength (2); RETURN_TOK (SUB_ASSIGN); }
-"*=" { setTokLength (2); RETURN_TOK (MUL_ASSIGN); }
-"/=" { setTokLength (2); RETURN_TOK (DIV_ASSIGN); }
-"%=" { setTokLength (2); RETURN_TOK (MOD_ASSIGN); }
-"&=" { setTokLength (2); RETURN_TOK (AND_ASSIGN); }
-"^=" { setTokLength (2); RETURN_TOK (XOR_ASSIGN); }
-"|=" { setTokLength (2); RETURN_TOK (OR_ASSIGN); }
-">>" { setTokLength (2); RETURN_TOK (RIGHT_OP); }
-"<<" { setTokLength (2); RETURN_TOK (LEFT_OP); }
-"++" { setTokLength (2); RETURN_TOK (INC_OP); }
-"--" { setTokLength (2); RETURN_TOK (DEC_OP); }
-"->" { setTokLength (2); RETURN_TOK (ARROW_OP); }
-"&&" { setTokLength (2); RETURN_TOK (AND_OP); }
-"||" { setTokLength (2); RETURN_TOK (OR_OP); }
-"<=" { setTokLength (2); RETURN_TOK (LE_OP); }
-">=" { setTokLength (2); RETURN_TOK (GE_OP); }
-"==" { setTokLength (2); RETURN_TOK (EQ_OP); }
-"!=" { setTokLength (2); RETURN_TOK (NE_OP); }
-";" { setTokLength (1); RETURN_TOK (TSEMI); }
-"{" { setTokLength (1); RETURN_TOK (TLBRACE); }
-"}" { setTokLength (1); RETURN_TOK (TRBRACE); }
-"," { setTokLength (1); RETURN_TOK (TCOMMA); }
-":" { setTokLength (1); RETURN_TOK (TCOLON); }
-"=" { setTokLength (1); RETURN_TOK (TASSIGN); }
-"(" { setTokLength (1); RETURN_TOK (TLPAREN); }
-")" { setTokLength (1); RETURN_TOK (TRPAREN); }
-"[" { setTokLength (1); RETURN_TOK (TLSQBR); }
-"]" { setTokLength (1); RETURN_TOK (TRSQBR); }
-"." { setTokLength (1); RETURN_TOK (TDOT); }
-"&" { setTokLength (1); RETURN_TOK (TAMPERSAND); }
-"!" { setTokLength (1); RETURN_TOK (TEXCL); }
-
-
-"~" { setTokLength (1); RETURN_TOK (TTILDE); }
-"-" { setTokLength (1); RETURN_TOK (TMINUS); }
-"+" { setTokLength (1); RETURN_TOK (TPLUS); }
-"*" { setTokLength (1); RETURN_TOK (TMULT); }
-"/" { setTokLength (1); RETURN_TOK (TDIV); }
-"%" { setTokLength (1); RETURN_TOK (TPERCENT); }
-"<" { setTokLength (1); RETURN_TOK (TLT); }
-">" { setTokLength (1); RETURN_TOK (TGT); }
-"^" { setTokLength (1); RETURN_TOK (TCIRC); }
-"|" { setTokLength (1); RETURN_TOK (TBAR); }
-"?" { setTokLength (1); RETURN_TOK (TQUEST); }
-
-
-"/\\" { setTokLength (1); RETURN_TOK (TCAND); }
-
-
-[ \t\v\f] { incColumn (); }
-\n { context_incLineno ();
- if (tokLength != 0) {
- tokLength = 0;
- /* No error to report
- voptgenerror
- (FLG_SYNTAX,
- message ("Likely parse error: token spans multiple lines."),
- g_currentloc);
- */
- }
-
- if (continueLine)
- {
- continueLine = FALSE;
- }
- else
- {
- if (context_inMacro ())
- {
- /* Don't use RETURN_TOK */
- yylval.tok = lltok_create (TENDMACRO, g_currentloc);
- lastWasString = FALSE;
- return (TENDMACRO);
- }
- }
- }
-"@@MR@@" { setTokLength (6);
-
- if (processMacro ()) {
- if (context_inIterDef ())
- {
- RETURN_TOK (LLMACROITER);
- }
- if (context_inIterEnd ())
- {
- RETURN_TOK (LLMACROEND);
- }
- if (context_inMacro ())
- {
- RETURN_TOK (LLMACRO);
- }
- }
- }
-"@QLMR" { if (context_inHeader () || context_inFunction ())
- {
- handleMacro ();
- }
- else
- {
- int nspchar = ninput ();
- int nspaces;
-
- /*
- ** This is a hack to get the column number correct.
- */
-
- llassert (nspchar >= '0' && nspchar <= '9');
-
- nspaces = nspchar - '0';
-
- setTokLength (5 + nspaces);
-
- if (processMacro ())
- {
- if (context_inIterDef ())
- {
- RETURN_TOK (LLMACROITER);
- }
- if (context_inIterEnd ())
- {
- RETURN_TOK (LLMACROEND);
- }
- if (context_inMacro ())
- {
- RETURN_TOK (LLMACRO);
- }
- }
- }
- }
-"@.CT" { setTokLength (4); lldiagmsg (ctype_unparseTable ()); }
-"@.FA" { setTokLength (4); lldiagmsg (message ("Access types: %q", typeIdSet_unparse (context_fileAccessTypes ()))); }
-"@.F" { setTokLength (3);
- lldiagmsg (message ("%q: *** marker ***", fileloc_unparse (g_currentloc)));
- }
-"@.L" { setTokLength (3); usymtab_printLocal (); }
-"@.A" { setTokLength (3); lldiagmsg (usymtab_unparseAliases ()); }
-"@.C" { setTokLength (3); lldiagmsg (context_unparse ()); }
-"@.W" { setTokLength (3); lldiagmsg (context_unparseClauses ()); }
-"@.G" { setTokLength (3); usymtab_printGuards (); }
-"@.S" { setTokLength (3); usymtab_printOut (); }
-"@.X" { setTokLength (3); usymtab_printAll (); }
-"@.Z" { setTokLength (3); usymtab_printComplete (); }
-"@.T" { setTokLength (3); usymtab_printTypes (); }
-"@.K" { setTokLength (3); lldiagmsg (usymtab_unparseStack ()); }
-"@.M" { setTokLength (3);
- lldiagmsg (message ("Can modify: %q",
- sRefSet_unparse (context_modList ())));
- }
-"%{" { /* BEFORE_COMMENT_MARKER */
- int tok;
- incColumn (); incColumn ();
- tok = handleLlSpecial ();
-
- if (tok != BADTOK)
- {
- if (tok == CANNOTATION) {
- return (tok);
- } else {
- /* Beware - this bashes yylval! */
- RETURN_TOK (tok);
- }
- }
- }
-"%}" { /* AFTER_COMMENT_MARKER */
- setTokLength (2);
- inSpecPart = FALSE;
- RETURN_TOK (QENDMACRO); }
-"\\" { incColumn (); continueLine = TRUE; }
-. { incColumn ();
- if ((int) *yytext == 13 ) {
- ;
- } else {
- voptgenerror
- (FLG_SYNTAX,
- message ("Invalid character (ascii: %d), skipping character",
- (int)(*yytext)),
- g_currentloc);
- }
- }
-%%
-
-struct skeyword
-{
- /*@null@*/ /*@observer@*/ char *name;
- int token;
-} ;
-
-/*
-** These tokens are followed by syntax that is parsed by the
-** grammar proper.
-*/
-
-struct skeyword s_parsetable[] = {
- { "modifies", QMODIFIES } ,
- { "globals", QGLOBALS } ,
- { "alt", QALT } ,
- { "warn", QWARN } ,
- { "constant", QCONSTANT } ,
- { "function", QFUNCTION } ,
- { "iter", QITER } ,
- { "defines", QDEFINES } ,
- { "uses", QUSES } ,
- { "allocates", QALLOCATES } ,
- { "sets", QSETS } ,
- { "releases", QRELEASES } ,
- { "pre", QPRECLAUSE } ,
- { "post", QPOSTCLAUSE } ,
- { "setBufferSize", QSETBUFFERSIZE},
- { "setStringLength", QSETSTRINGLENGTH},
- { "testinRange", QTESTINRANGE},
- { "requires", QPRECLAUSE } ,
- { "ensures", QPOSTCLAUSE } ,
- { NULL, BADTOK }
-} ;
-
-/*
-** These tokens are either stand-alone tokens, or followed by
-** token-specific text.
-*/
-
-struct skeyword s_keytable[] = {
- { "anytype", QANYTYPE } ,
- { "integraltype", QINTEGRALTYPE } ,
- { "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,
- { "signedintegraltype", QSIGNEDINTEGRALTYPE } ,
- { "out", QOUT } ,
- { "in", QIN } ,
- { "only", QONLY } ,
- { "owned", QOWNED } ,
- { "dependent", QDEPENDENT } ,
- { "partial", QPARTIAL } ,
- { "special", QSPECIAL } ,
- { "truenull", QTRUENULL } ,
- { "falsenull", QFALSENULL } ,
- { "keep", QKEEP } ,
- { "kept", QKEPT } ,
- { "notnull", QNOTNULL } ,
- { "abstract", QABSTRACT } ,
- { "concrete", QCONCRETE } ,
- { "mutable", QMUTABLE } ,
- { "immutable", QIMMUTABLE } ,
- { "unused", QUNUSED } ,
- { "external", QEXTERNAL } ,
- { "sef", QSEF } ,
- { "unique", QUNIQUE } ,
- { "returned", QRETURNED } ,
- { "exposed", QEXPOSED } ,
- { "refcounted", QREFCOUNTED } ,
- { "refs", QREFS } ,
- { "newref", QNEWREF } ,
- { "tempref", QTEMPREF } ,
- { "killref", QKILLREF } ,
- { "null", QNULL } ,
- { "relnull", QRELNULL } ,
- { "nullterminated", QNULLTERMINATED },
- { "setBufferSize", QSETBUFFERSIZE },
- { "testInRange", QTESTINRANGE},
- { "MaxSet", QMAXSET},
- { "MaxRead", QMAXREAD},
- { "reldef", QRELDEF } ,
- { "observer", QOBSERVER } ,
- { "exits", QEXITS } ,
- { "mayexit", QMAYEXIT } ,
- { "trueexit", QTRUEEXIT } ,
- { "falseexit", QFALSEEXIT } ,
- { "neverexit", QNEVEREXIT } ,
- { "temp", QTEMP } ,
- { "shared", QSHARED } ,
- { "ref", QREF } ,
- { "unchecked", QUNCHECKED } ,
- { "checked", QCHECKED } ,
- { "checkmod", QCHECKMOD } ,
- { "checkedstrict", QCHECKEDSTRICT } ,
- { "innercontinue", QINNERCONTINUE } ,
- { "innerbreak", QINNERBREAK } ,
- { "loopbreak", QLOOPBREAK } ,
- { "switchbreak", QSWITCHBREAK } ,
- { "safebreak", QSAFEBREAK } ,
- { "fallthrough", QFALLTHROUGH } ,
- { "l_fallthrou", QLINTFALLTHROUGH } ,
- { "l_fallth", QLINTFALLTHRU } ,
- { "notreached", QNOTREACHED } ,
- { "l_notreach", QLINTNOTREACHED } ,
- { "printflike", QPRINTFLIKE } ,
- { "l_printfli", QLINTPRINTFLIKE } ,
- { "scanflike", QSCANFLIKE } ,
- { "messagelike", QMESSAGELIKE } ,
- { "l_argsus", QARGSUSED } ,
- { NULL, BADTOK }
-} ;
-
-/*
-** would be better if these weren't hard coded...
-*/
-
-static bool isArtificial (cstring s)
-{
- return (cstring_equalLit (s, "modifies")
- || cstring_equalLit (s, "globals")
- || cstring_equalLit (s, "warn")
- || cstring_equalLit (s, "alt"));
-}
-
-void swallowMacro (void)
-{
- int i;
- bool skipnext = FALSE;
-
- while ((i = lminput ()) != EOF)
- {
- char c = (char) i;
-
-
- if (c == '\\')
- {
- skipnext = TRUE;
- }
- else if (c == '\n')
- {
- if (skipnext)
- {
- skipnext = FALSE;
- }
- else
- {
- reader_checkUngetc (i, yyin);
- return;
- }
- }
- }
-
- if (i != EOF)
- {
- reader_checkUngetc (i, yyin);
- }
-}
-
-static int commentMarkerToken (cstring s)
-{
- int i = 0;
-
- while (s_parsetable[i].name != NULL)
- {
- DPRINTF (("Try :%s:%s:", s, s_parsetable[i].name));
-
- if (cstring_equalLit (s, s_parsetable[i].name))
- {
- return s_parsetable[i].token;
- }
-
- i++;
- }
-
- return BADTOK;
-}
-
-static int tokenMacroCode (cstring s)
-{
- int i = 0;
-
- while (s_keytable[i].name != NULL)
- {
- if (cstring_equalLit (s, s_keytable[i].name))
- {
- if (s_keytable[i].token == QLINTFALLTHROUGH)
- {
- voptgenerror
- (FLG_WARNLINTCOMMENTS,
- cstring_makeLiteral
- ("Traditional lint comment /*FALLTHROUGH*/ used. "
- "This is interpreted by "
- "LCLint in the same way as most Unix lints, but it is "
- "preferable to replace it with the /*@fallthrough@*/ "
- "semantic comment"),
- g_currentloc);
- return QFALLTHROUGH;
- }
- else if (s_keytable[i].token == QLINTFALLTHRU)
- {
- voptgenerror
- (FLG_WARNLINTCOMMENTS,
- cstring_makeLiteral
- ("Traditional lint comment /*FALLTHRU*/ used. "
- "This is interpreted by "
- "LCLint in the same way as most Unix lints, but it is "
- "preferable to replace it with the /*@fallthrough@*/ "
- "semantic comment"),
- g_currentloc);
- return QFALLTHROUGH;
- }
- else if (s_keytable[i].token == QLINTNOTREACHED)
- {
- voptgenerror
- (FLG_WARNLINTCOMMENTS,
- cstring_makeLiteral
- ("Traditional lint comment /*NOTREACHED*/ used. "
- "This is interpreted by "
- "LCLint in the same way as most Unix lints, but it is "
- "preferable to replace it with the /*@notreached@*/ "
- "semantic comment."),
- g_currentloc);
-
- return QNOTREACHED;
- }
- else if (s_keytable[i].token == QPRINTFLIKE)
- {
- setSpecialFunction (qual_createPrintfLike ());
- return SKIPTOK;
- }
- else if (s_keytable[i].token == QLINTPRINTFLIKE)
- {
- voptgenerror
- (FLG_WARNLINTCOMMENTS,
- cstring_makeLiteral
- ("Traditional lint comment /*PRINTFLIKE*/ used. "
- "This is interpreted by "
- "LCLint in the same way as most Unix lints, but it is "
- "preferable to replace it with either /*@printflike@*/, "
- "/*@scanflike@*/ or /*@messagelike@*/."),
- g_currentloc);
-
- setSpecialFunction (qual_createPrintfLike ());
- return SKIPTOK;
- }
- else if (s_keytable[i].token == QSCANFLIKE)
- {
- setSpecialFunction (qual_createScanfLike ());
- return SKIPTOK;
- }
- else if (s_keytable[i].token == QMESSAGELIKE)
- {
- setSpecialFunction (qual_createMessageLike ());
- return SKIPTOK;
- }
- else if (s_keytable[i].token == QARGSUSED)
- {
- voptgenerror
- (FLG_WARNLINTCOMMENTS,
- cstring_makeLiteral
- ("Traditional lint comment /*ARGSUSED*/ used. "
- "This is interpreted by "
- "LCLint in the same way as most Unix lints, but it is "
- "preferable to use /*@unused@*/ annotations on "
- "the unused parameters."),
- g_currentloc);
-
- setArgsUsed ();
- return SKIPTOK;
- }
-
- return s_keytable[i].token;
- }
-
- i++;
- }
-
- return BADTOK;
-}
-
-static int lminput ()
-{
- if (savechar == '\0')
- {
- incColumn ();
- return (input ());
- }
- else
- {
- int save = (int) savechar;
- savechar = '\0';
- return save;
- }
-}
-
-static void lmsavechar (char c)
-{
- if (savechar == '\0') savechar = c;
- else
- {
- llbuglit ("lmsavechar: override");
- }
-}
-
-static int returnFloat (ctype ct, double f)
-{
- yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext),
- fileloc_decColumn (g_currentloc, tokLength));
- tokLength = 0;
- return (CCONSTANT);
-}
-
-static int returnInt (ctype ct, long i)
-{
- ctype c = ct;
-
- if (ctype_equal (ct, ctype_int))
- {
- if (i == 0)
- {
- c = context_typeofZero ();
- }
- else if (i == 1)
- {
- c = context_typeofOne ();
- }
- }
-
- yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
- fileloc_decColumn (g_currentloc, tokLength), i);
- tokLength = 0;
- return (CCONSTANT);
-}
-
-static int returnChar (char c)
-{
- yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext),
- fileloc_decColumn (g_currentloc, tokLength));
- tokLength = 0;
- return (CCONSTANT);
-}
-
-static int ninput ()
-{
- int c = lminput ();
-
- if (c != EOF && ((char)c == '\n'))
- {
- context_incLineno ();
- }
-
- return c;
-}
-
-static char macro_nextChar ()
-{
- static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
- int ic;
- char c;
-
- ic = lminput ();
- c = char_fromInt (ic);
-
- if (!in_quote && !in_char && (c == '\\' || c == BEFORE_COMMENT_MARKER[0]))
- {
- if (c == '\\')
- {
- while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
- {
- ; /* skip to newline */
- }
-
- context_incLineno ();
-
- if (c != '\0')
- {
- return macro_nextChar ();
- }
- else
- {
- return c;
- }
- }
- else /* if (c == '@') */
- {
- llassert (FALSE); /*@i23@*/
- if (handleLlSpecial () != BADTOK)
- {
- llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax");
- }
-
- return macro_nextChar ();
- }
- }
- else if (!in_escape && c == '\"')
- {
- in_quote = !in_quote;
- }
- else if (!in_escape && c == '\'')
- {
- in_char = !in_char;
- }
- else if ((in_quote || in_char) && c == '\\')
- {
- in_escape = !in_escape;
- }
- else if ((in_quote || in_char) && in_escape)
- {
- in_escape = FALSE;
- }
- else if (!in_quote && c == '/')
- {
- char c2;
-
- if ((c2 = char_fromInt (lminput ())) == '*')
- {
- while (c2 != '\0')
- {
- while ((c2 = char_fromInt (lminput ())) != '\0'
- && c2 != '\n' && c2 != '*')
- {
- ;
- }
-
- if (c2 == '*')
- {
- while ((c2 = char_fromInt (lminput ())) != '\0'
- && c2 == '*')
- {
- ;
- }
-
- if (c2 == '/')
- {
- goto outofcomment;
- }
- }
- else
- {
- llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
- }
- }
- outofcomment:
- return macro_nextChar ();
- }
- else
- {
- /*** putchar does not work! why? puts to stdio...??! ***/
- lmsavechar (c2);
- }
- }
- return c;
-}
-
-/*
-** keeps semantic comments
-*/
-
-static char macro_nextCharC ()
-{
- static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
- char c;
-
- c = char_fromInt (lminput ());
-
- if (!in_quote && !in_char && c == '\\')
- {
- while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
- {
- ; /* skip to newline */
- }
-
- context_incLineno ();
-
- if (c != '\0')
- {
- return macro_nextCharC ();
- }
- else
- {
- return c;
- }
- }
- else if (!in_escape && c == '\"')
- {
- in_quote = !in_quote;
- }
- else if (!in_escape && c == '\'')
- {
- in_char = !in_char;
- }
- else if ((in_quote || in_char) && c == '\\')
- {
- in_escape = !in_escape;
- }
- else if ((in_quote || in_char) && in_escape)
- {
- in_escape = FALSE;
- }
- else if (!in_quote && c == '/')
- {
- char c2;
-
- if ((c2 = char_fromInt (lminput ())) == '*')
- {
- while (c2 != '\0')
- {
- while ((c2 = char_fromInt (lminput ())) != '\0'
- && c2 != '\n' && c2 != '*')
- {
- ;
- }
-
- if (c2 == '*')
- {
- while ((c2 = char_fromInt (lminput ())) != '\0'
- && c2 == '*')
- {
- ;
- }
-
- if (c2 == '/')
- {
- goto outofcomment;
- }
- }
- else
- {
- llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
- }
- }
- outofcomment:
- return macro_nextCharC ();
- }
- else
- {
- lmsavechar (c2);
- }
- }
- return c;
-}
-
-/*
-** skips whitespace (handles line continuations)
-** returns first non-whitespace character
-*/
-
-static char skip_whitespace ()
-{
- char c;
-
- while ((c = macro_nextChar ()) == ' ' || c == '\t')
- {
- ;
- }
-
- return c;
-}
-
-static void handleMacro ()
-{
- cstring mac = cstring_undefined;
- int macrocode;
- char c;
-
- while (currentColumn () > 2)
- {
- mac = cstring_appendChar (mac, ' ');
- setTokLength (-1);
- }
-
- c = macro_nextCharC ();
-
- if (c >= '0' && c <= '9')
- {
- int i;
-
- for (i = 0; i < ((c - '0') + 1); i++)
- {
- mac = cstring_appendChar (mac, ' ');
- }
- }
- else
- {
- BADBRANCH;
- }
-
- while (((c = macro_nextCharC ()) != '\0') && (c != '\n'))
- {
- mac = cstring_appendChar (mac, c);
- }
-
-
- macrocode = tokenMacroCode (mac);
-
- if (macrocode == BADTOK && !isArtificial (mac))
- {
- context_addMacroCache (mac);
- }
- else
- {
- cstring_free (mac);
- }
-
- if (c == '\n')
- {
- context_incLineno ();
- }
-}
-
-static bool processMacro (void)
-{
- uentry e2;
- ctype ct;
- int noparams = 0;
- cstring fname = cstring_undefined;
- bool res = TRUE;
- bool isspecfcn = FALSE;
- bool isiter = FALSE;
- bool skipparam = FALSE;
- bool isenditer = FALSE;
- bool unknownm = FALSE;
- bool hasParams = FALSE;
- bool emptyMacro = FALSE;
- char c = skip_whitespace ();
- fileloc loc = fileloc_noColumn (g_currentloc);
-
- /* are both of these necessary? what do they mean? */
- uentryList specparams = uentryList_undefined;
- uentryList pn = uentryList_undefined;
-
- context_resetMacroMissingParams ();
-
- if (c == '\0' || c == '\n')
- {
- llcontbug (cstring_makeLiteral ("Bad macro"));
- fileloc_free (loc);
- return FALSE;
- }
-
- fname = cstring_appendChar (fname, c);
-
- while ((c = macro_nextChar ()) != '(' && c != '\0'
- && c != ' ' && c != '\t' && c != '\n')
- {
- fname = cstring_appendChar (fname, c);
- }
-
- if (c == ' ' || c == '\t' || c == '\n')
- {
- char oldc = c;
-
- if (c != '\n')
- {
- while (c == ' ' || c == '\t')
- {
- c = macro_nextChar ();
- }
- unput (c);
- }
-
- if (c == '\n')
- {
- emptyMacro = TRUE;
- unput (c);
- }
-
- c = oldc;
- }
-
- hasParams = (c == '(');
-
- if (usymtab_exists (fname))
- {
- e2 = usymtab_lookupExpose (fname);
- ct = uentry_getType (e2);
-
- if (uentry_isCodeDefined (e2)
- && fileloc_isUser (uentry_whereDefined (e2)))
- {
- if (optgenerror
- (FLG_MACROREDEF,
- message ("Macro %s already defined", fname),
- loc))
- {
- uentry_showWhereDefined (e2);
- uentry_clearDefined (e2);
- }
-
- if (uentry_isFunction (e2))
- {
- uentry_setType (e2, ctype_unknown);
- ct = ctype_unknown;
- unknownm = TRUE;
- context_enterUnknownMacro (e2);
- }
- else
- {
- context_enterConstantMacro (e2);
- }
- }
- else
- {
- if (uentry_isForward (e2) && uentry_isFunction (e2))
- {
- unknownm = TRUE;
-
- voptgenerror
- (FLG_MACROFCNDECL,
- message
- ("Parameterized macro has no prototype or specification: %s ",
- fname),
- loc);
-
- ct = ctype_unknown;
- uentry_setType (e2, ctype_unknown);
- uentry_setFunctionDefined (e2, loc);
- uentry_setUsed (e2, fileloc_undefined);
- context_enterUnknownMacro (e2);
- }
- else
- {
- if (uentry_isIter (e2))
- {
- isiter = TRUE;
- specparams = uentry_getParams (e2);
- noparams = uentryList_size (specparams);
- uentry_setDefined (e2, loc);
- context_enterIterDef (e2);
- }
- else if (uentry_isEndIter (e2))
- {
- isenditer = TRUE;
- uentry_setDefined (e2, loc);
- context_enterIterEnd (e2); /* don't care about it now */
- /* but should parse like an iter! */
- }
- else if (uentry_isConstant (e2))
- {
- if (hasParams)
- {
- voptgenerror
- (FLG_INCONDEFS,
- message ("Constant %s implemented as parameterized macro",
- fname),
- g_currentloc);
-
- uentry_showWhereSpecified (e2);
- uentry_setType (e2, ctype_unknown);
- uentry_makeConstantFunction (e2);
- uentry_setDefined (e2, g_currentloc);
- uentry_setFunctionDefined (e2, g_currentloc);
- context_enterUnknownMacro (e2);
- }
- else
- {
- if (!uentry_isSpecified (e2))
- {
- fileloc oloc = uentry_whereDeclared (e2);
-
- if (fileloc_isLib (oloc))
- {
- ;
- }
- else if (fileloc_isUndefined (oloc)
- || fileloc_isPreproc (oloc))
- {
- if (!emptyMacro)
- {
- voptgenerror
- (FLG_MACROCONSTDECL,
- message
- ("Macro constant %q not declared",
- uentry_getName (e2)),
- loc);
- }
- }
- else if (!fileloc_withinLines (oloc, loc, 2))
- { /* bogus! will give errors if there is too much whitespace */
- voptgenerror
- (FLG_SYNTAX,
- message
- ("Macro constant name %s does not match name in "
- "previous constant declaration. This constant "
- "is declared at %q", fname,
- fileloc_unparse (oloc)),
- loc);
- }
- }
-
- context_enterConstantMacro (e2);
- cstring_free (fname);
- fileloc_free (loc);
- return res;
- }
-
- }
- else if (ctype_isFunction (ct))
- {
- isspecfcn = TRUE;
- specparams = ctype_argsFunction (ct);
- noparams = uentryList_size (specparams);
-
- uentry_setFunctionDefined (e2, loc);
- context_enterMacro (e2);
- }
- else if (uentry_isVar (e2))
- {
- if (hasParams)
- {
- voptgenerror
- (FLG_INCONDEFS,
- message ("Variable %s implemented as parameterized macro",
- fname),
- loc);
-
- uentry_showWhereSpecified (e2);
- uentry_setType (e2, ctype_unknown);
- uentry_makeVarFunction (e2);
- uentry_setDefined (e2, g_currentloc);
- uentry_setFunctionDefined (e2, g_currentloc);
- context_enterUnknownMacro (e2);
- }
- else
- {
- uentry ucons = uentry_makeConstant (fname,
- ctype_unknown,
- loc);
- if (uentry_isExpandedMacro (e2))
- {
- ; /* okay */
- }
- else
- {
- if (optgenerror
- (FLG_INCONDEFS,
- message ("Variable %s implemented by a macro",
- fname),
- loc))
- {
- uentry_showWhereSpecified (e2);
- }
- }
-
- uentry_setDefined (e2, loc);
- uentry_setUsed (ucons, loc);
-
- context_enterConstantMacro (ucons);
- uentry_markOwned (ucons);
- cstring_free (fname);
- return res;
- }
- }
- else
- {
- if (uentry_isDatatype (e2))
- {
- vgenhinterror
- (FLG_SYNTAX,
- message ("Type implemented as macro: %x",
- uentry_getName (e2)),
- message ("A type is implemented using a macro definition. A "
- "typedef should be used instead."),
- g_currentloc);
-
- swallowMacro ();
- /* Must exit scope (not sure why a new scope was entered?) */
- usymtab_quietExitScope (g_currentloc);
- uentry_setDefined (e2, g_currentloc);
- res = FALSE;
- }
- else
- {
- llcontbug
- (message ("Unexpanded macro not function or constant: %q",
- uentry_unparse (e2)));
- uentry_setType (e2, ctype_unknown);
-
- if (hasParams)
- {
- uentry_makeVarFunction (e2);
- uentry_setDefined (e2, g_currentloc);
- uentry_setFunctionDefined (e2, g_currentloc);
- context_enterUnknownMacro (e2);
- }
- }
- }
- }
- }
- }
- else
- {
- uentry ce;
-
- /* evans 2001-09-09 - if it has params, assume a function */
- if (hasParams)
- {
- voptgenerror
- (FLG_MACROMATCHNAME,
- message ("Unexpanded macro %s does not match name of a declared "
- "function. The name used in the control "
- "comment on the previous line should match.",
- fname),
- loc);
-
- ce = uentry_makeFunction (fname, ctype_unknown,
- typeId_invalid,
- globSet_undefined,
- sRefSet_undefined,
- warnClause_undefined,
- fileloc_undefined);
- uentry_setUsed (ce, loc); /* perhaps bogus? */
- e2 = usymtab_supEntryReturn (ce);
- context_enterUnknownMacro (e2);
- }
- else
- {
- voptgenerror
- (FLG_MACROMATCHNAME,
- message ("Unexpanded macro %s does not match name of a constant "
- "or iter declaration. The name used in the control "
- "comment on the previous line should match. "
- "(Assuming macro defines a constant.)",
- fname),
- loc);
-
- ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined);
- uentry_setUsed (ce, loc); /* perhaps bogus? */
- e2 = usymtab_supEntryReturn (ce);
-
- context_enterConstantMacro (e2);
- cstring_free (fname);
- fileloc_free (loc);
- return res;
- }
- }
-
- /* in macros, ( must follow immediatetly after name */
-
- if (hasParams)
- {
- int paramno = 0;
-
- c = skip_whitespace ();
-
- while (c != ')' && c != '\0')
- {
- uentry param;
- bool suppress = context_inSuppressRegion ();
- cstring paramname = cstring_undefined;
-
- /*
- ** save the parameter location
- */
-
- decColumn ();
- context_saveLocation ();
- incColumn ();
-
- while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')
- {
- paramname = cstring_appendChar (paramname, c);
- c = macro_nextChar ();
- }
-
- if (c == ' ' || c == '\t') c = skip_whitespace ();
-
- if (c == ',')
- {
- c = macro_nextChar ();
- if (c == ' ' || c == '\t') c = skip_whitespace ();
- }
-
- if (c == '\0')
- {
- llfatalerror (cstring_makeLiteral
- ("Bad macro syntax: uentryList"));
- }
-
- if ((isspecfcn || isiter) && (paramno < noparams)
- && !uentry_isElipsisMarker (uentryList_getN
- (specparams, paramno)))
- {
- fileloc sloc = context_getSaveLocation ();
- uentry decl = uentryList_getN (specparams, paramno);
- sRef sr;
-
- param = uentry_nameCopy (paramname, decl);
-
- uentry_setParam (param);
- sr = sRef_makeParam (paramno, uentry_getType (param), stateInfo_makeLoc (sloc));
-
- if (sRef_getNullState (sr) == NS_ABSNULL)
- {
- ctype pt = ctype_realType (uentry_getType (param));
-
- if (ctype_isUser (pt))
- {
- uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));
-
- if (uentry_isValid (te))
- {
- sRef_setStateFromUentry (sr, te);
- }
- }
- else
- {
- sRef_setNullState (sr, NS_UNKNOWN, sloc);
- }
- }
-
- uentry_setSref (param, sr);
- uentry_setDeclaredForceOnly (param, sloc);
-
- skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));
- }
- else
- {
- fileloc sloc = context_getSaveLocation ();
-
- param = uentry_makeVariableSrefParam
- (paramname, ctype_unknown, fileloc_copy (sloc),
- sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (sloc)));
- DPRINTF (("Unknown param: %s", uentry_unparseFull (param)));
- cstring_free (paramname);
-
- sRef_setPosNull (uentry_getSref (param), sloc);
- uentry_setDeclaredForce (param, sloc);
-
- skipparam = FALSE;
- fileloc_free (sloc);
- }
-
- if (!skipparam)
- {
- llassert (!uentry_isElipsisMarker (param));
-
- if (!suppress)
- {
- sRef_makeUnsafe (uentry_getSref (param));
- }
-
- pn = uentryList_add (pn, uentry_copy (param));
- usymtab_supEntry (param);
- }
- else
- {
- /* don't add param */
- uentry_free (param);
- }
-
- if (c == ',')
- {
- (void) macro_nextChar ();
- c = skip_whitespace ();
- }
-
- paramno++;
- }
-
- if (c == ')')
- {
- if (isspecfcn || isiter)
- {
- if (paramno != noparams && noparams >= 0)
- {
- advanceLine ();
-
- voptgenerror
- (FLG_INCONDEFS,
- message ("Macro %s specified with %d args, defined with %d",
- fname, noparams, paramno),
- g_currentloc);
-
- uentry_showWhereSpecified (e2);
- uentry_resetParams (e2, pn);
- }
- }
- else
- {
- uentry_resetParams (e2, pn);
- }
- }
- }
- else
- {
- /*
- ** the form should be:
- **
- ** # define newname oldname
- ** where oldname refers to a function matching the specification
- ** of newname.
- */
-
- if (unknownm)
- {
- sRef_setGlobalScope ();
- usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));
- sRef_clearGlobalScope ();
- }
- else
- {
- context_setMacroMissingParams ();
- }
- }
-
-
- /* context_setuentryList (pn); */
- usymtab_enterScope ();
-
- fileloc_free (loc);
- cstring_free (fname);
-
- return res;
-}
-
-static bool handleSpecial (char *yyt)
-{
- char *l = mstring_create (MAX_NAME_LENGTH);
- static bool reportcpp = FALSE;
- int lineno = 0;
- char c;
- char *ol;
- cstring olc;
-
- strcpy (l, yyt + 1);
-
- /* Need to safe original l for deallocating. */
- ol = l;
-
- l += strlen (yyt) - 1;
-
- while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')
- {
- *l++ = c;
- }
-
- *l = '\0';
- olc = cstring_fromChars (ol);
-
- if (cstring_equalPrefixLit (olc, "pragma"))
- {
- char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN));
- char *opname = pname;
- char *ptr = ol + 6; /* pragma is six characters, plus space */
- int len = 0;
-
-
- /* skip whitespace */
- while (((c = *ptr) != '\0') && isspace (c))
- {
- ptr++;
- }
-
-
- while (((c = *ptr) != '\0') && !isspace (c))
- {
- len++;
-
- if (len > MAX_PRAGMA_LEN)
- {
- break;
- }
-
- ptr++;
- *pname++ = c;
- }
-
- *pname = '\0';
-
- if (len == PRAGMA_LEN_EXPAND
- && mstring_equal (opname, PRAGMA_EXPAND))
- {
- cstring exname = cstring_undefined;
- uentry ue;
-
- ptr++;
- while (((c = *ptr) != '\0') && !isspace (c))
- {
- exname = cstring_appendChar (exname, c);
- ptr++;
- }
-
-
- ue = usymtab_lookupExposeGlob (exname);
-
- if (uentry_isExpandedMacro (ue))
- {
- if (fileloc_isPreproc (uentry_whereDefined (ue)))
- {
- fileloc_setColumn (g_currentloc, 1);
- uentry_setDefined (ue, g_currentloc);
- }
- }
-
- cstring_free (exname);
- }
- }
- else if (cstring_equalPrefixLit (olc, "ident"))
- {
- /* Some pre-processors will leave these in the code. Ignore rest of line */
- }
- /*
- ** Yuk...Win32 filenames can have spaces in them...we need to read
- ** to the matching end quote.
- */
- else if ((sscanf (ol, "line %d \"", &lineno) == 1)
- || (sscanf (ol, " %d \"", &lineno) == 1))
- {
- char *tmp = ol;
- cstring fname;
- fileId fid;
-
- /*@access cstring@*/
- while (*tmp != '\"' && *tmp != '\0')
- {
- tmp++;
- }
-
- llassert (*tmp == '\"');
-
- tmp++;
-
- fname = tmp;
-
- while (*tmp != '\"' && *tmp != '\0')
- {
- tmp++;
- }
-
- llassert (*tmp == '\"');
-
- *tmp = '\0';
-
-# if defined(OS2) || defined(MSDOS) || defined(WIN32)
-
- /*
- ** DOS-like path delimiters get delivered in pairs, something like
- ** \"..\\\\file.h\", so we have to make it normal again. We do NOT
- ** remove the pre dirs yet as we usually specify tmp paths relative
- ** to the current directory, so tmp files would not get found in
- ** the hash table. If this method fails we try it again later.
- */
-
- {
- char *stmp = fname;
-
- /*
- ** Skip past the drive marker.
- */
-
- if (strchr (stmp, ':') != NULL)
- {
- stmp = strchr (stmp, ':') + 1;
- }
-
- while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )
- {
- if (*(stmp+1) == CONNECTCHAR)
- {
- memmove (stmp, stmp+1, strlen (stmp));
- }
-
- stmp++;
- }
-
- fid = fileTable_lookupBase (context_fileTable (), fname);
- if (!(fileId_isValid (fid)))
- {
- fname = removePreDirs (fname);
- fid = fileTable_lookupBase (context_fileTable (), fname);
- }
- }
-# else /* !defined(OS2) && !defined(MSDOS) */
- fname = removePreDirs (fname);
- fid = fileTable_lookupBase (context_fileTable (), fname);
-# endif /* !defined(OS2) && !defined(MSDOS) */
-
- if (!(fileId_isValid (fid)))
- {
- if (context_inXHFile ())
- {
- fid = fileTable_addXHFile (context_fileTable (), fname);
- }
- else if (isHeaderFile (fname))
- {
- fid = fileTable_addHeaderFile (context_fileTable (), fname);
- }
- else
- {
- fid = fileTable_addFile (context_fileTable (), fname);
- }
- }
-
- setFileLine (fid, lineno);
- /*@noaccess cstring@*/
- }
- else if ((sscanf (ol, "line %d", &lineno) == 1)
- || (sscanf (ol, " %d", &lineno) == 1))
- {
- setLine (lineno); /* next line is <cr> */
- }
- else
- {
- if (mstring_equal (ol, "")) {
- DPRINTF (("Empty pp command!"));
- /*
- ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.
- ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.
- */
- mstring_free (ol);
- return FALSE;
- } else {
- if (!reportcpp)
- {
-
- } else {
- llbug (message ("File contains preprocessor command: #%s",
- cstring_fromChars (ol)));
- reportcpp = TRUE;
- }
- }
-
- sfree (ol);
- return TRUE;
- }
-
- sfree (ol);
- return FALSE;
-}
-
-static int handleLlSpecial ()
-{
- bool hasnl = FALSE;
- int ic;
- char c;
- char *s = mstring_createEmpty ();
- char *os;
- int tok;
- int charsread = 0;
- fileloc loc;
-
- loc = fileloc_copy (g_currentloc);
- DPRINTF (("Handle special: %s", fileloc_unparse (loc)));
-
- while (((ic = ninput ()) != 0) && isalpha (ic))
- {
- c = (char) ic;
- s = mstring_append (s, c);
- charsread++;
- }
-
- DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
- os = s;
-
- if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])
- {
- ic = ninput ();
-
- llassert (ic == AFTER_COMMENT_MARKER[1]);
-
- if (*s == '\0')
- {
- sfree (os);
- fileloc_free (loc);
- return QNOMODS; /* special token no modifications token */
- }
- }
-
- DPRINTF (("Coment marker: %s", os));
- tok = commentMarkerToken (cstring_fromChars (os));
-
- if (tok != BADTOK)
- {
- tokLength = charsread;
- sfree (os);
- inSpecPart = TRUE;
- fileloc_free (loc);
- return tok;
- }
-
- DPRINTF (("Not a comment marker..."));
- /* Add rest of the comment */
-
- if (ic != 0 && ic != EOF)
- {
- c = (char) ic;
-
- s = mstring_append (s, c);
- charsread++;
-
- while (((ic = ninput ()) != 0) && (ic != EOF)
- && (ic != AFTER_COMMENT_MARKER[0]))
- {
- c = (char) ic;
-
- /* evans 2001-09-01 added to prevent assertion failures for uncloses syntactic comments */
-
- if (c == '\n') {
- hasnl = TRUE; /* This prevents tokLength from being set later. */
- tokLength = 0;
-
- voptgenerror
- (FLG_SYNTAX,
- message ("Likely parse error: syntactic comment token spans multiple lines: %s",
- cstring_fromChars (s)),
- g_currentloc);
- }
-
- s = mstring_append (s, c);
- charsread++;
- }
- }
-
- DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
-
- if (ic == AFTER_COMMENT_MARKER[0])
- {
- int nc = ninput ();
- llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
- charsread++;
- }
-
- os = s;
-
- while (*s == ' ' || *s == '\t' || *s == '\n')
- {
- s++;
- }
-
- if (*s == '-' || *s == '+' || *s == '=') /* setting flags */
- {
- c = *s;
-
- while (c == '-' || c == '+' || c == '=')
- {
- ynm set = ynm_fromCodeChar (c);
- cstring thisflag;
-
- s++;
-
- thisflag = cstring_fromChars (s);
-
- while ((c = *s) != '\0' && (c != '-') && (c != '=')
- && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))
- {
- s++;
- }
-
- *s = '\0';
-
- if (!context_getFlag (FLG_NOCOMMENTS))
- {
- cstring flagname = thisflag;
- flagcode fflag = identifyFlag (flagname);
-
- if (flagcode_isSkip (fflag))
- {
- ;
- }
- else if (flagcode_isInvalid (fflag))
- {
- if (isMode (flagname))
- {
- if (ynm_isMaybe (set))
- {
- llerror
- (FLG_BADFLAG,
- message
- ("Semantic comment attempts to restore flag %s. "
- "A mode flag cannot be restored.",
- flagname));
- }
- else
- {
- context_setMode (flagname);
- }
- }
- else
- {
- voptgenerror
- (FLG_UNRECOGFLAGCOMMENTS,
- message ("Unrecognized option in semantic comment: %s",
- flagname),
- g_currentloc);
- }
- }
- else if (flagcode_isGlobalFlag (fflag))
- {
- voptgenerror
- (FLG_BADFLAG,
- message
- ("Semantic comment attempts to set global flag %s. "
- "A global flag cannot be set locally.",
- flagname),
- g_currentloc);
- }
- else
- {
- context_fileSetFlag (fflag, set);
-
- if (flagcode_hasArgument (fflag))
- {
- if (ynm_isMaybe (set))
- {
- voptgenerror
- (FLG_BADFLAG,
- message
- ("Semantic comment attempts to restore flag %s. "
- "A flag for setting a value cannot be restored.",
- flagname),
- g_currentloc);
- }
- else
- { /* cut-and-pastied from llmain...blecch */
- cstring extra = cstring_undefined;
- char *rest;
- char *orest;
- char rchar;
-
- *s = c;
- rest = mstring_copy (s);
- orest = rest;
- *s = '\0';
-
- while ((rchar = *rest) != '\0'
- && (isspace (rchar)))
- {
- rest++;
- s++;
- }
-
- while ((rchar = *rest) != '\0'
- && !isspace (rchar))
- {
- extra = cstring_appendChar (extra, rchar);
- rest++;
- s++;
- }
-
- sfree (orest);
-
- if (cstring_isUndefined (extra))
- {
- llerror
- (FLG_BADFLAG,
- message
- ("Flag %s (in semantic comment) must be followed by an argument",
- flagcode_unparse (fflag)));
- }
- else
- {
- s--;
-
- if (flagcode_hasValue (fflag))
- {
- setValueFlag (fflag, extra);
- }
- else if (flagcode_hasString (fflag))
- {
- setStringFlag (fflag, extra);
- }
- else
- {
- BADEXIT;
- }
- }
- }
- }
- }
- }
- else
- {
- ;
- }
-
- *s = c;
- while ((c == ' ') || (c == '\t') || (c == '\n'))
- {
- c = *(++s);
- }
- }
-
- if (context_inHeader () && !isArtificial (cstring_fromChars (os)))
- {
- DPRINTF (("Here adding comment: %s", os));
- context_addComment (cstring_fromCharsNew (os));
- }
- else
- {
- ;
- }
- }
- else
- {
- char *t = s;
- int macrocode;
- char tchar = '\0';
- annotationInfo ainfo;
-
- while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n')
- {
- s++;
- }
-
- if (*s != '\0')
- {
- tchar = *s;
- *s = '\0';
- s++;
- }
-
- t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));
- macrocode = tokenMacroCode (cstring_fromChars (t));
-
- if (macrocode != BADTOK)
- {
- tokLength = hasnl ? 0 : mstring_length (t);
-
- sfree (t);
- sfree (os);
- fileloc_free (loc);
-
- if (macrocode == SKIPTOK)
- {
- return BADTOK;
- }
-
- return macrocode;
- }
-
- ainfo = context_lookupAnnotation (cstring_fromChars (os));
-
- if (annotationInfo_isDefined (ainfo)) {
- DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
- /*@i324@*/ yylval.annotation = ainfo;
- tokLength = 0;
- sfree (os);
- sfree (t);
- fileloc_free (loc);
- return CANNOTATION;
- }
-
- if (context_inHeader ())
- {
- if (tchar != '\0')
- {
- *(s-1) = tchar;
- }
-
- if ((context_inMacro () || context_inGlobalContext ())
- && macrocode != SKIPTOK
- && !isArtificial (cstring_fromChars (os)))
- {
- DPRINTF (("Add comment: %s", os));
- context_addComment (cstring_fromCharsNew (os));
- }
- else
- {
- ;
- }
-
- if (tchar != '\0')
- {
- *(s-1) = '\0';
- }
- }
-
- if (mstring_equal (t, "ignore"))
- {
- if (!context_getFlag (FLG_NOCOMMENTS))
- {
- context_enterSuppressRegion ();
- }
- }
- else if ((*t == 'i' || *t == 't')
- && (*(t + 1) == '\0'))
- {
- if (!context_getFlag (FLG_NOCOMMENTS)
- && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))
- {
- context_enterSuppressLine (-1); /* infinite suppression */
- }
- }
- else if (((*t == 'i') || (*t == 't'))
- && ((*(t + 1) >= '0' && *(t + 1) <= '9')))
- {
- bool tmpcomment = (*t == 't');
- int val = -1;
- char *tt = t; /* don't mangle t, since it is free'd */
- char lc = *(++tt);
-
- if (lc >= '0' && lc <= '9')
- {
- val = (int)(lc - '0');
-
- lc = *(++tt);
- while (lc >= '0' && lc <= '9')
- {
- val *= 10;
- val += lc - '0';
- lc = *(++tt);
- }
- }
-
-
- if (!context_getFlag (FLG_NOCOMMENTS)
- && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
- {
- context_enterSuppressLine (val);
- }
- }
- else if (mstring_equal (t, "end"))
- {
- if (!context_getFlag (FLG_NOCOMMENTS))
- {
- context_exitSuppressRegion ();
- }
- }
- else if (mstring_equal (t, "notfunction"))
- {
- ; /* handled by pcpp */
- }
- else if (mstring_equal (t, "access"))
- {
- cstring tname;
-
- while (TRUE)
- {
- while ((c = *s) && (c == ' ' || c == '\t' || c == '\n'))
- {
- s++;
- }
-
- if (c == '\0')
- {
- break;
- }
-
- tname = cstring_fromChars (s);
-
- while ((c = *s) != '\0' && c != ' '
- && c != '\t' && c != '\n' && c != ',')
- {
- s++;
- }
-
- *s = '\0';
-
- DPRINTF (("Access %s", tname));
-
- if (!context_getFlag (FLG_NOCOMMENTS)
- && !context_getFlag (FLG_NOACCESS))
- {
- if (usymtab_existsType (tname))
- {
- typeId uid = usymtab_getTypeId (tname);
- uentry ue = usymtab_getTypeEntry (uid);
-
- if (uentry_isAbstractDatatype (ue))
- {
- context_addFileAccessType (uid);
- DPRINTF (("Adding access to: %s / %d", tname, uid));
- }
- else
- {
- voptgenerror
- (FLG_COMMENTERROR,
- message
- ("Non-abstract type %s used in access comment",
- tname),
- g_currentloc);
- }
- }
- else
- {
- if (!(context_inSuppressRegion ()
- || context_inSuppressZone (g_currentloc)))
- {
- voptgenerror
- (FLG_COMMENTERROR,
- message
- ("Unrecognized type %s used in access comment",
- tname),
- g_currentloc);
- }
- }
- }
-
- if (c != '\0')
- {
- s++;
- }
-
- if (c != ',' && c != ' ')
- {
- break;
- }
- }
- }
- else if (mstring_equal (t, "noaccess"))
- {
- cstring tname;
- char lc;
-
- while (TRUE)
- {
- while ((lc = *s) && (lc == ' ' || lc == '\t' || lc == '\n'))
- {
- s++;
- }
-
- if (lc == '\0')
- {
- break;
- }
-
- tname = cstring_fromChars (s);
-
- while ((lc = *s) != '\0' && lc != ' ' && lc != '\t'
- && lc != '\n' && lc != ',')
- {
- s++;
- }
-
- *s = '\0';
-
- if (!context_getFlag (FLG_NOCOMMENTS)
- && !context_getFlag (FLG_NOACCESS))
- {
- if (usymtab_existsType (tname))
- {
- typeId tuid = usymtab_getTypeId (tname);
-
- if (context_couldHaveAccess (tuid))
- {
- DPRINTF (("Removing access: %s", tname));
- context_removeFileAccessType (tuid);
- }
- else
- {
- if (!(context_inSuppressRegion ()
- || context_inSuppressZone (g_currentloc)))
- {
- uentry ue = usymtab_getTypeEntry (tuid);
-
- if (uentry_isAbstractDatatype (ue))
- {
- voptgenerror
- (FLG_COMMENTERROR,
- message
- ("Non-accessible abstract type %s used in noaccess comment",
- tname),
- g_currentloc);
- }
- else
- {
- voptgenerror
- (FLG_COMMENTERROR,
- message
- ("Non-abstract type %s used in noaccess comment",
- tname),
- g_currentloc);
- }
- }
- }
- }
- else
- {
- if (!(context_inSuppressRegion ()
- || context_inSuppressZone (g_currentloc)))
- {
- voptgenerror
- (FLG_COMMENTERROR,
- message
- ("Unrecognized type %s used in noaccess comment",
- tname),
- g_currentloc);
- }
- }
- }
-
- if (lc != '\0')
- {
- s++;
- }
-
- if (lc != ',' && lc != ' ')
- {
- break;
- }
- }
- }
- else
- {
- voptgenerror (FLG_UNRECOGCOMMENTS,
- message ("Semantic comment unrecognized: %s",
- cstring_fromChars (os)), loc);
- }
-
- sfree (t);
- }
-
- sfree (os);
- fileloc_free (loc);
- return BADTOK;
-}
-
-static /*@only@*/ cstring makeIdentifier (char *s)
-{
- char *c = mstring_create (size_toInt (strlen (s)) + 1);
- cstring id = cstring_fromChars (c);
-
- while (isalnum (*s) || (*s == '_') || (*s == '$'))
- {
- *c++ = *s++;
- }
-
- *c = '\0';
- return (id);
-}
-
-/*@observer@*/ /*@dependent@*/ uentry coerceId (cstring cn)
-{
- if (!(usymtab_exists (cn)))
- {
- fileloc loc = fileloc_createExternal ();
-
- /*
- ** We need to put this in a global scope, otherwise the sRef will be deallocated.
- */
-
- uentry ce = uentry_makeUnrecognized (cn, loc);
-
- if (!context_inIterEnd ())
- {
- voptgenerror
- (FLG_SYSTEMUNRECOG,
- message ("Unrecognized (possibly system) identifier: %q",
- uentry_getName (ce)),
- g_currentloc);
- }
-
- return ce;
- }
-
- return (usymtab_lookup (cn));
-}
-
-/*
-** like, coerceId, but doesn't supercede for iters
-*/
-
-/*@observer@*/ uentry coerceIterId (cstring cn)
-{
- if (!(usymtab_exists (cn)))
- {
- return uentry_undefined;
- }
-
- return (usymtab_lookup (cn));
-}
-
-/*@observer@*/ cstring LastIdentifier ()
-{
- return (lastidprocessed);
-}
-
-static int processIdentifier (cstring id)
-{
- uentry le;
-
- if (context_getFlag (FLG_GRAMMAR))
- {
- lldiagmsg (message ("Process identifier: %s", id));
- }
-
- context_clearJustPopped ();
- lastidprocessed = id;
-
- if (context_inFunctionHeader ())
- {
- int tok = commentMarkerToken (id);
- DPRINTF (("in function decl..."));
-
- if (tok != BADTOK)
- {
- return tok;
- }
- else
- {
- tok = tokenMacroCode (id);
-
- if (tok != BADTOK)
- {
- return tok;
- }
- else
- {
- annotationInfo ainfo;
-
- if (expectingMetaStateName)
- {
- metaStateInfo msinfo = context_lookupMetaStateInfo (id);
-
- if (metaStateInfo_isDefined (msinfo))
- {
- yylval.msinfo = msinfo;
- return METASTATE_NAME;
- }
- else
- {
- DPRINTF (("Not meta state name: %s", cstring_toCharsSafe (id)));
- }
- }
-
- ainfo = context_lookupAnnotation (id);
-
- if (annotationInfo_isDefined (ainfo))
- {
- DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
- /*@i324@*/ yylval.annotation = ainfo;
- return CANNOTATION;
- }
- else
- {
- DPRINTF (("Not annotation: %s", id));
- }
- }
- }
- }
-
- /* Consider handling: Defined by C99 as static const char __func__[] */
-
- if (context_getFlag (FLG_GNUEXTENSIONS))
- {
- int tok = BADTOK;
-
- if (cstring_equalLit (id, "__stdcall")
- || cstring_equalLit (id, "__cdecl")
- || cstring_equalLit (id, "__extension__"))
- {
- return BADTOK;
- }
- else if (cstring_equalLit (id, "__volatile__"))
- {
- tok = QVOLATILE;
- }
- else if (cstring_equalLit (id, "__signed"))
- {
- tok = QSIGNED;
- }
- else if (cstring_equalLit (id, "__unsigned"))
- {
- tok = QUNSIGNED;
- }
- else if (cstring_equalLit (id, "__const__"))
- {
- tok = QCONST;
- }
- else if (cstring_equalLit (id, "__alignof__"))
- {
- tok = CALIGNOF; /* alignof is parsed like sizeof */
- }
- else if (cstring_equalLit (id, "__FUNCTION__")
- || cstring_equalLit (id, "__PRETTY_FUNCTION__"))
- {
- /* These tokens hold the name of the current function as strings */
- yylval.expr = exprNode_stringLiteral (id, fileloc_copy (g_currentloc));
- tokLength = 0;
- lastWasString = TRUE;
- tok = CCONSTANT;
- return tok;
- }
- else if (cstring_equalLit (id, "__attribute__")
- || cstring_equalLit (id, "__asm__")
- || cstring_equalLit (id, "_asm")
- || cstring_equalLit (id, "__asm")
- || cstring_equalLit (id, "__declspec"))
- {
- int depth = 0;
- bool useparens = FALSE;
- bool usebraces = FALSE;
- bool inquote = FALSE;
- bool inescape = FALSE;
- int ic;
-
- while ((ic = input ()) != EOF)
- {
-
- if (inescape)
- {
- inescape = FALSE;
- }
- else if (ic == '\\')
- {
- inescape = TRUE;
- }
- else if (ic == '\"')
- {
- inquote = !inquote;
- }
- else if (!inquote)
- {
- if (ic == '(')
- {
- if (!useparens)
- {
- if (!usebraces)
- {
- useparens = TRUE;
- }
- }
-
- if (useparens)
- {
- depth++;
- }
- }
- else if (ic == '{')
- {
- if (!usebraces)
- {
- if (!useparens)
- {
- usebraces = TRUE;
- }
- }
-
- if (usebraces)
- {
- depth++;
- }
- }
- else if (ic == ')' && useparens)
- {
- depth--;
- if (depth == 0) break;
- }
- else if (ic == '}' && usebraces)
- {
- depth--;
- if (depth == 0) break;
- }
- else if (ic == '}'
- && !usebraces && !useparens
- && cstring_equalLit (id, "__asm"))
- {
- /*
- ** We need this because some MS VC++ include files
- ** have __asm mov ... }
- ** Its a kludge, but otherwise would need to parse
- ** the asm code!
- */
- return TRBRACE;
- }
- }
-
- if (ic == '\n')
- {
- context_incLineno ();
-
- if (cstring_equalLit (id, "__asm")
- && !useparens && !usebraces)
- {
- break;
- }
- }
- }
-
- llassert ((useparens && ic == ')')
- || (usebraces && ic == '}')
- || (!useparens && !usebraces));
-
- return BADTOK;
- }
- else if (cstring_equalLit (id, "inline")
- || cstring_equalLit (id, "__inline")
- || cstring_equalLit (id, "_inline")
- || cstring_equalLit (id, "__inline__"))
- {
- tok = QINLINE;
- }
-
- if (tok != BADTOK)
- {
- RETURN_TOK (tok);
- }
- }
-
- le = usymtab_lookupSafe (id);
-
- /*@-dependenttrans@*/
-
- if (uentry_isIter (le))
- {
- /*@i32@*/ yylval.entry = le;
- return (ITER_NAME);
- }
- else if (uentry_isEndIter (le))
- {
- /*@i32@*/ yylval.entry = le;
- return (ITER_ENDNAME);
- }
- else if (uentry_isUndefined (le))
- {
- yylval.cname = id;
-
- /* avoid parse errors for certain system built ins */
-
- if (g_expectingTypeName && (cstring_firstChar (id) == '_')
- && (cstring_secondChar (id) == '_'))
- {
- return (TYPE_NAME_OR_ID);
- }
-
- return (NEW_IDENTIFIER);
- }
- else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))
- {
- if (uentry_isDatatype (le))
- {
- yylval.cname = id;
- return (NEW_IDENTIFIER);
- }
- else
- {
- /*@i32@*/ yylval.entry = le;
- return (IDENTIFIER);
- }
- }
- else if (uentry_isDatatype (le))
- {
- if (!g_expectingTypeName)
- {
- yylval.cname = id;
-
- return (NEW_IDENTIFIER);
- }
- else
- {
- yylval.ctyp = uentry_getAbstractType (le);
-
- uentry_setUsed (le, g_currentloc);
- return (TYPE_NAME);
- }
- }
- else
- {
- /*@i32@*/ yylval.entry = le;
- return (IDENTIFIER);
- }
-
- /*@=dependenttrans@*/
-}
-
-static bool processHashIdentifier (/*@only@*/ cstring id)
-{
- if (context_inMacro () || context_inIterDef () ||
- context_inIterEnd ())
- {
- uentry le;
-
- context_clearJustPopped ();
-
- lastidprocessed = id;
- le = usymtab_lookupSafe (id);
-
- if (uentry_isParam (le) || uentry_isRefParam (le))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- else
- {
- cstring_free (id);
- return FALSE;
- }
-}
-
-
-static /*@only@*/ exprNode processString ()
-{
- exprNode res;
- fileloc loc;
- char *nl = strchr (yytext, '\n');
- cstring ns = cstring_fromCharsNew (yytext);
-
- if (nl == NULL)
- {
- loc = fileloc_copy (g_currentloc);
- addColumn (cstring_length (ns));
- }
- else
- {
- char *lastnl = nl;
-
- loc = fileloc_copy (g_currentloc);
-
- context_incLineno ();
-
- while ((nl = strchr ((nl + 1), '\n')) != NULL)
- {
- context_incLineno ();
- lastnl = nl;
- }
- }
-
-
- res = exprNode_stringLiteral (ns, loc);
- return (res);
-}
-
-static
-char processChar ()
-{
- char fchar;
- char next;
-
- llassert (*yytext != '\0');
- fchar = *(yytext + 1);
- if (fchar != '\\') return fchar;
-
- next = *(yytext + 2);
-
- switch (next)
- {
- case 'n': return '\n';
- case 't': return '\t';
- case '\"': return '\"';
- case '\'': return '\'';
- case '\\': return '\\';
- default: return '\0';
- }
-}
-
-static
-double processFloat ()
-{
- double ret = atof (yytext);
-
- return (ret);
-}
-
-static
-long processHex ()
-{
- int index = 2;
- long val = 0;
-
- llassert (yytext[0] == '0'
- && (yytext[1] == 'X' || yytext[1] == 'x'));
-
- while (yytext[index] != '\0') {
- int tval;
- char c = yytext[index];
-
- if (c >= '0' && c <= '9') {
- tval = (int) c - (int) '0';
- } else if (c >= 'A' && c <= 'F') {
- tval = (int) c - (int) 'A' + 10;
- } else if (c >= 'a' && c <= 'f') {
- tval = (int) c - (int) 'a' + 10;
- } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
- index++;
- while (yytext[index] != '\0') {
- if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
- ;
- } else {
- voptgenerror
- (FLG_SYNTAX,
- message ("Invalid character (%c) following specifier in hex constant: %s",
- c, cstring_fromChars (yytext)),
- g_currentloc);
- }
- index++;
- }
-
- break;
- } else {
- voptgenerror
- (FLG_SYNTAX,
- message ("Invalid character (%c) in hex constant: %s",
- c, cstring_fromChars (yytext)),
- g_currentloc);
- break;
- }
-
- val = (val * 16) + tval;
- index++;
- }
-
- DPRINTF (("Hex constant: %s = %ld", yytext, val));
- return val;
-}
-
-static
-long processOctal ()
-{
- int index = 1;
- long val = 0;
-
- llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');
-
- while (yytext[index] != '\0') {
- int tval;
- char c = yytext[index];
-
- if (c >= '0' && c <= '7') {
- tval = (int) c - (int) '0';
- } else {
- voptgenerror
- (FLG_SYNTAX,
- message ("Invalid character (%c) in octal constant: %s",
- c, cstring_fromChars (yytext)),
- g_currentloc);
- break;
- }
-
- val = (val * 8) + tval;
- index++;
- }
-
- DPRINTF (("Octal constant: %s = %ld", yytext, val));
- return val;
-}
-
-static
-long processDec ()
-{
- return (atol (yytext));
-}
-
-static int
-processSpec (int tok)
-{
- size_t length = strlen (yytext);
-
- if (inSpecPart)
- {
- setTokLengthT (length);
- RETURN_TOK (tok);
- }
- else
- {
-
- context_saveLocation ();
- setTokLengthT (length);
- return (processIdentifier (makeIdentifier (yytext)));
- }
-}
-
-void cscanner_expectingMetaStateName ()
-{
- llassert (!expectingMetaStateName);
- llassert (context_inFunctionHeader ());
- expectingMetaStateName = TRUE;
-}
-
-void cscanner_clearExpectingMetaStateName ()
-{
- llassert (expectingMetaStateName);
- expectingMetaStateName = FALSE;
-}
+/*;-*-C-*-; \r
+** Copyright (c) Massachusetts Institute of Technology 1994-1998.\r
+** All Rights Reserved.\r
+** Unpublished rights reserved under the copyright laws of\r
+** the United States.\r
+**\r
+** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\r
+** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.\r
+**\r
+** This code is distributed freely and may be used freely under the \r
+** following conditions:\r
+**\r
+** 1. This notice may not be removed or altered.\r
+**\r
+** 2. Works derived from this code are not distributed for\r
+** commercial gain without explicit permission from MIT \r
+** (for permission contact lclint-request@sds.lcs.mit.edu).\r
+*/\r
+/*\r
+ * Modified by Herbert 08/19/97:\r
+ * - added #include for IBM's OS/2 compiler.\r
+ * - fixed weird bug with lookup of tmp files (OS/2 and MSDOS only).\r
+ */\r
+\r
+/*\r
+ * Modified by Mike Smith \r
+ * Corrected missing 'line' in scanf() calls in handleSpecial().\r
+ * Without this, I get an error when LCLint hits a '#line' directive\r
+ * in the pre-pre-processed source files. For safety, I have made these\r
+ * conditional on OS2 and MSDOS because I don't understand why noone else\r
+ * has seen this problem.\r
+ *\r
+ * Modified by Mike Smith, 4th June 1997\r
+ * Finally resolved the #line problem. The scanf() calls have been fixed to\r
+ * allow the following #line forms:-\r
+ *\r
+ * #line 123 "filename"\r
+ * #line 123\r
+ * # 123 "filename"\r
+ * # 123\r
+ *\r
+ * The last two are generated by the GNU pre-processor, apparently\r
+ */\r
+\r
+Digit [0-9]\r
+Letter [a-zA-Z_$]\r
+H [a-fA-F0-9]\r
+E [Ee][+-]?{Digit}+\r
+U (u|U)\r
+L (l|L)\r
+FS (f|F|l|L)\r
+IS (u|U|l|L)*\r
+ULSuffix ({U}{L}|{L}{U})\r
+\r
+%{\r
+/*\r
+** based on original C lexer by Nate Osgood\r
+** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993\r
+**\r
+*/\r
+\r
+# include "lclintMacros.nf"\r
+# if defined(OS2) && defined(__IBMC__)\r
+ /* needed for isatty()... */\r
+# include <io.h>\r
+# else\r
+# include <unistd.h>\r
+# endif\r
+\r
+# include "basic.h"\r
+\r
+# include "cgrammar.h"\r
+# include "cgrammar_tokens.h"\r
+\r
+# include "fileIdList.h"\r
+# include "portab.h"\r
+\r
+static bool lastWasString = FALSE;\r
+static char savechar = '\0';\r
+\r
+/*@notfunction@*/\r
+# define yyinput() (incColumn (), getc (yyin))\r
+\r
+static /*@owned@*/ cstring lastidprocessed = cstring_undefined;\r
+static int lminput (void);\r
+static int tokLength = 0;\r
+static bool inSpecPart = FALSE;\r
+static bool continueLine = FALSE;\r
+\r
+static int ninput (void);\r
+static char processChar (void);\r
+static double processFloat (void);\r
+static /*@only@*/ exprNode processString (void);\r
+static long processDec (void);\r
+static long processHex (void);\r
+static long processOctal (void);\r
+static int processIdentifier (/*@only@*/ cstring)\r
+ /*@globals undef lastidprocessed@*/ ;\r
+static bool processHashIdentifier (/*@only@*/ cstring)\r
+ /*@globals undef lastidprocessed@*/ ;\r
+\r
+static int processSpec (int);\r
+static bool handleSpecial (char *);\r
+static int handleLlSpecial (void);\r
+static void handleMacro (void);\r
+static bool processMacro (void);\r
+static /*@only@*/ cstring makeIdentifier (char *);\r
+\r
+/* yes, this is exported! */\r
+bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */\r
+\r
+static bool expectingMetaStateName = FALSE;\r
+\r
+static int returnInt (ctype, long);\r
+static int returnFloat (ctype, double);\r
+static int returnChar (char);\r
+static void setTokLength (int) /*@modifies g_currentloc@*/ ;\r
+static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;\r
+\r
+static void advanceLine (void)\r
+{\r
+ tokLength = 0;\r
+ beginLine ();\r
+}\r
+ \r
+/*@-allmacros@*/\r
+# define RETURN_INT(c,i) \\r
+ do { lastWasString = FALSE; \\r
+ return (returnInt (c, i)); } while (FALSE)\r
+\r
+# define RETURN_FLOAT(c,f) \\r
+ do { lastWasString = FALSE; \\r
+ return (returnFloat (c, f)); \\r
+ } while (FALSE)\r
+\r
+# define RETURN_CHAR(c) \\r
+ do { lastWasString = FALSE; \\r
+ return (returnChar (c)); \\r
+ } while (FALSE)\r
+\r
+# define RETURN_TOK(t) \\r
+ do { yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, tokLength)); \\r
+ tokLength = 0; \\r
+ lastWasString = FALSE; \\r
+ return (t); } while (FALSE)\r
+\r
+# define RETURN_TYPE(t, ct) \\r
+ do { yylval.ctyp = ct; tokLength = 0; return (t); } while (FALSE)\r
+\r
+/* don't fileloc_decColumn (g_currentloc, tokLength)); \r
+ the string could have \n's in it!\r
+*/\r
+\r
+# define RETURN_STRING(c) \\r
+ do { yylval.expr = exprNode_stringLiteral (c, fileloc_decColumn (g_currentloc, tokLength)); \\r
+ tokLength = 0; \\r
+ lastWasString = TRUE; \\r
+ return (CCONSTANT); } while (FALSE)\r
+\r
+# define RETURN_EXPR(e) \\r
+ do { yylval.expr = e; \\r
+ tokLength = 0; \\r
+ lastWasString = TRUE; \\r
+ return (CCONSTANT); } while (FALSE)\r
+\r
+/*@=allmacros@*/\r
+\r
+static void setTokLength (int len) \r
+{\r
+ addColumn (len);\r
+ tokLength = len;\r
+ DPRINTF (("Set tok length: %d", len));\r
+}\r
+\r
+static void setTokLengthT (size_t len)\r
+{\r
+ setTokLength (size_toInt (len));\r
+}\r
+\r
+# include "flex.head"\r
+\r
+/*@-unrecog@*/ /*@i5343@*/\r
+\r
+%}\r
+\r
+%%\r
+\r
+"/*" { llfatalbug (cstring_makeLiteral ("Comment in pre-processor output")); }\r
+\r
+"#"{Letter}({Letter}|{Digit})* { \r
+ context_saveLocation (); \r
+ setTokLength (longUnsigned_toInt (mstring_length (yytext))); \r
+\r
+ if (processHashIdentifier (makeIdentifier (yytext + 1)))\r
+ {\r
+ if (lastWasString)\r
+ {\r
+ /* was nothing! */ /*@i32@*/\r
+ RETURN_STRING (cstring_makeLiteral ("\"\""));\r
+ }\r
+ else\r
+ {\r
+ RETURN_STRING (cstring_makeLiteral ("\"\""));\r
+ }\r
+ }\r
+ else\r
+ { \r
+ if (handleSpecial (yytext)) \r
+ { \r
+ setTokLength (1); \r
+ RETURN_TOK (0); \r
+ }\r
+ }\r
+ } \r
+"#" { if (handleSpecial (yytext)) \r
+ { \r
+ setTokLength (1); RETURN_TOK (0); \r
+ }\r
+ }\r
+"..." { setTokLength (3); RETURN_TOK (CTOK_ELIPSIS); }\r
+"break" { setTokLength (5); RETURN_TOK (BREAK); }\r
+"case" { setTokLength (4); RETURN_TOK (CASE); }\r
+"continue" { setTokLength (8); RETURN_TOK (CONTINUE); }\r
+"default" { setTokLength (7); RETURN_TOK (DEFAULT); }\r
+"do" { setTokLength (2); RETURN_TOK (DO); }\r
+"else" { setTokLength (4); RETURN_TOK (CELSE); }\r
+"for" { setTokLength (3); RETURN_TOK (CFOR); }\r
+"goto" { setTokLength (4); RETURN_TOK (GOTO); }\r
+"if" { setTokLength (2); RETURN_TOK (CIF); }\r
+"return" { setTokLength (6); RETURN_TOK (RETURN); }\r
+"sizeof" { setTokLength (6); RETURN_TOK (CSIZEOF); }\r
+"offsetof" { setTokLength (8); RETURN_TOK (COFFSETOF); }\r
+"switch" { setTokLength (6); RETURN_TOK (SWITCH); }\r
+"while" { setTokLength (5); RETURN_TOK (WHILE); }\r
+"va_arg" { setTokLength (6); RETURN_TOK (VA_ARG); } \r
+"va_dcl" { setTokLength (6); RETURN_TOK (VA_DCL); } \r
+"inline" { \r
+ /* gcc extension...this might not be appropriate */\r
+ setTokLength (6); RETURN_TOK (QINLINE); }\r
+\r
+"struct" { setTokLength (6); RETURN_TOK (CSTRUCT); } \r
+"typedef" { setTokLength (7); RETURN_TOK (CTYPEDEF); }\r
+\r
+"union" { setTokLength (5); RETURN_TOK (CUNION); }\r
+"enum" { setTokLength (4); RETURN_TOK (CENUM); }\r
+\r
+"void" { setTokLength (4); RETURN_TYPE (CVOID, ctype_void); }\r
+"int" { setTokLength (3); RETURN_TYPE (CINT, ctype_int); }\r
+"double" { setTokLength (6); RETURN_TYPE (CDOUBLE, ctype_double); }\r
+"char" { setTokLength (4); RETURN_TYPE (CGCHAR, ctype_char); }\r
+"float" { setTokLength (5); RETURN_TYPE (CGFLOAT, ctype_float); }\r
+\r
+"long" { setTokLength (4); RETURN_TOK (QLONG); }\r
+"short" { setTokLength (5); RETURN_TOK (QSHORT); }\r
+"unsigned" { setTokLength (8); RETURN_TOK (QUNSIGNED); }\r
+"signed" { setTokLength (6); RETURN_TOK (QSIGNED); }\r
+\r
+"volatile" { setTokLength (8); RETURN_TOK (QVOLATILE); }\r
+"const" { setTokLength (5); RETURN_TOK (QCONST); }\r
+\r
+ /* some systems expect this! [gack!] */ \r
+"__const" { setTokLength (7); RETURN_TOK (QCONST); }\r
+\r
+"extern" { setTokLength (6); RETURN_TOK (QEXTERN); }\r
+"auto" { setTokLength (4); RETURN_TOK (QAUTO); }\r
+"register" { setTokLength (8); RETURN_TOK (QREGISTER); }\r
+"static" { setTokLength (6); RETURN_TOK (QSTATIC); }\r
+\r
+\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }\r
+L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }\r
+"out" { return (processSpec (QOUT)); }\r
+"in" { return (processSpec (QIN)); }\r
+"partial" { return (processSpec (QPARTIAL)); }\r
+"special" { return (processSpec (QSPECIAL)); }\r
+"anytype" { return (processSpec (QANYTYPE)); }\r
+"integraltype" { return (processSpec (QINTEGRALTYPE)); }\r
+"unsignedintegraltype" { return (processSpec (QUNSIGNEDINTEGRALTYPE)); }\r
+"signedintegraltype" { return (processSpec (QSIGNEDINTEGRALTYPE)); }\r
+"keep" { return (processSpec (QKEEP)); }\r
+"null" { return (processSpec (QNULL)); } \r
+"notnull" { return (processSpec (QNOTNULL)); } \r
+"isnull" { return (processSpec (QISNULL)); } \r
+"truenull" { return (processSpec (QTRUENULL)); } \r
+"falsenull" { return (processSpec (QFALSENULL)); } \r
+"relnull" { return (processSpec (QRELNULL)); }\r
+"reldef" { return (processSpec (QRELDEF)); }\r
+"exposed" { return (processSpec (QEXPOSED)); }\r
+"newref" { return (processSpec (QNEWREF)); }\r
+"tempref" { return (processSpec (QTEMPREF)); }\r
+"killref" { return (processSpec (QKILLREF)); }\r
+"refcounted" { return (processSpec (QREFCOUNTED)); }\r
+"checked" { return (processSpec (QCHECKED)); }\r
+"checkmod" { return (processSpec (QCHECKMOD)); }\r
+"checkedstrict" { return (processSpec (QCHECKEDSTRICT)); }\r
+"unchecked" { return (processSpec (QUNCHECKED)); }\r
+"only" { return (processSpec (QONLY)); }\r
+"owned" { return (processSpec (QOWNED)); }\r
+"observer" { return (processSpec (QOBSERVER)); }\r
+"dependent" { return (processSpec (QDEPENDENT)); }\r
+"unused" { return (processSpec (QUNUSED)); }\r
+"external" { return (processSpec (QEXTERNAL)); }\r
+"sef" { return (processSpec (QSEF)); }\r
+"shared" { return (processSpec (QSHARED)); }\r
+"yield" { return (processSpec (QYIELD)); }\r
+"undef" { return (processSpec (QUNDEF)); }\r
+"killed" { return (processSpec (QKILLED)); }\r
+"nullterminated" { return (processSpec (QNULLTERMINATED));}\r
+"MaxSet" { return (processSpec (QMAXSET));}\r
+"MaxRead" { return (processSpec (QMAXREAD));}\r
+"maxSet" { return (processSpec (QMAXSET));}\r
+"maxRead" { return (processSpec (QMAXREAD));}\r
+\r
+{Letter}({Letter}|{Digit})* { int tok; \r
+ context_saveLocation (); \r
+ setTokLength (longUnsigned_toInt (mstring_length (yytext))); \r
+ tok = processIdentifier (makeIdentifier (yytext)); \r
+ if (tok != BADTOK)\r
+ {\r
+ return (tok);\r
+ }\r
+ }\r
+0[xX]{H}+ { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_int, processHex ()); /* evs 2000-05-17 was ctype_uint */\r
+ }\r
+0[xX]{H}+{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_lint, processHex ()); }\r
+0[xX]{H}+{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_llint, processHex ()); }\r
+0[xX]{H}+{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_uint, processHex ()); }\r
+0[xX]{H}+{ULSuffix} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ulint, processHex ()); }\r
+0[xX]{H}+{U}{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processHex ()); }\r
+0[xX]{H}+{L}{L}{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processHex ()); }\r
+0{Digit}+ { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_int, processOctal ()); } \r
+0{Digit}+{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_uint, processOctal ()); } \r
+0{Digit}+{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_lint, processOctal ()); } \r
+0{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_llint, processOctal ()); } \r
+0{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ulint, processOctal ()); } \r
+0{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processOctal ()); } \r
+0{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processOctal ()); } \r
+{Digit}+ { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_int, processDec ()); } \r
+{Digit}+{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_uint, processDec ()); } \r
+{Digit}+{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_lint, processDec ()); } \r
+{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_llint, processDec ()); } \r
+{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ulint, processDec ()); } \r
+{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processDec ()); } \r
+{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_INT (ctype_ullint, processDec ()); } \r
+'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_CHAR (processChar ()); }\r
+L'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_CHAR (processChar ()); }\r
+{Digit}+{E}[fF] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_float, processFloat ()); }\r
+{Digit}+{E}[lL] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_ldouble, processFloat ()); }\r
+{Digit}+{E} { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_double, processFloat ()); }\r
+\r
+{Digit}*"."{Digit}+({E})?[fF] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_float, processFloat ()); }\r
+{Digit}*"."{Digit}+({E})?[lL] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_ldouble, processFloat ()); }\r
+{Digit}*"."{Digit}+({E})? { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_double, processFloat ()); }\r
+\r
+{Digit}+"."{Digit}*({E})?[fF] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_float, processFloat ()); }\r
+{Digit}+"."{Digit}*({E})?[lL] { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_ldouble, processFloat ()); }\r
+{Digit}+"."{Digit}*({E})? { setTokLengthT (mstring_length (yytext)); \r
+ RETURN_FLOAT (ctype_double, processFloat ()); }\r
+\r
+">>=" { setTokLength (3); RETURN_TOK (RIGHT_ASSIGN); }\r
+"<<=" { setTokLength (3); RETURN_TOK (LEFT_ASSIGN); }\r
+"+=" { setTokLength (2); RETURN_TOK (ADD_ASSIGN); }\r
+"-=" { setTokLength (2); RETURN_TOK (SUB_ASSIGN); }\r
+"*=" { setTokLength (2); RETURN_TOK (MUL_ASSIGN); }\r
+"/=" { setTokLength (2); RETURN_TOK (DIV_ASSIGN); }\r
+"%=" { setTokLength (2); RETURN_TOK (MOD_ASSIGN); }\r
+"&=" { setTokLength (2); RETURN_TOK (AND_ASSIGN); }\r
+"^=" { setTokLength (2); RETURN_TOK (XOR_ASSIGN); }\r
+"|=" { setTokLength (2); RETURN_TOK (OR_ASSIGN); }\r
+">>" { setTokLength (2); RETURN_TOK (RIGHT_OP); }\r
+"<<" { setTokLength (2); RETURN_TOK (LEFT_OP); }\r
+"++" { setTokLength (2); RETURN_TOK (INC_OP); }\r
+"--" { setTokLength (2); RETURN_TOK (DEC_OP); }\r
+"->" { setTokLength (2); RETURN_TOK (ARROW_OP); }\r
+"&&" { setTokLength (2); RETURN_TOK (AND_OP); }\r
+"||" { setTokLength (2); RETURN_TOK (OR_OP); }\r
+"<=" { setTokLength (2); RETURN_TOK (LE_OP); }\r
+">=" { setTokLength (2); RETURN_TOK (GE_OP); }\r
+"==" { setTokLength (2); RETURN_TOK (EQ_OP); }\r
+"!=" { setTokLength (2); RETURN_TOK (NE_OP); }\r
+";" { setTokLength (1); RETURN_TOK (TSEMI); }\r
+"{" { setTokLength (1); RETURN_TOK (TLBRACE); }\r
+"}" { setTokLength (1); RETURN_TOK (TRBRACE); }\r
+"," { setTokLength (1); RETURN_TOK (TCOMMA); }\r
+":" { setTokLength (1); RETURN_TOK (TCOLON); }\r
+"=" { setTokLength (1); RETURN_TOK (TASSIGN); }\r
+"(" { setTokLength (1); RETURN_TOK (TLPAREN); }\r
+")" { setTokLength (1); RETURN_TOK (TRPAREN); }\r
+"[" { setTokLength (1); RETURN_TOK (TLSQBR); }\r
+"]" { setTokLength (1); RETURN_TOK (TRSQBR); }\r
+"." { setTokLength (1); RETURN_TOK (TDOT); }\r
+"&" { setTokLength (1); RETURN_TOK (TAMPERSAND); }\r
+"!" { setTokLength (1); RETURN_TOK (TEXCL); }\r
+\r
+\r
+"~" { setTokLength (1); RETURN_TOK (TTILDE); }\r
+"-" { setTokLength (1); RETURN_TOK (TMINUS); }\r
+"+" { setTokLength (1); RETURN_TOK (TPLUS); }\r
+"*" { setTokLength (1); RETURN_TOK (TMULT); }\r
+"/" { setTokLength (1); RETURN_TOK (TDIV); }\r
+"%" { setTokLength (1); RETURN_TOK (TPERCENT); }\r
+"<" { setTokLength (1); RETURN_TOK (TLT); }\r
+">" { setTokLength (1); RETURN_TOK (TGT); }\r
+"^" { setTokLength (1); RETURN_TOK (TCIRC); }\r
+"|" { setTokLength (1); RETURN_TOK (TBAR); }\r
+"?" { setTokLength (1); RETURN_TOK (TQUEST); }\r
+\r
+\r
+"/\\" { setTokLength (1); RETURN_TOK (TCAND); }\r
+\r
+\r
+[ \t\v\f] { incColumn (); }\r
+\n { context_incLineno ();\r
+ if (tokLength != 0) { \r
+ tokLength = 0; \r
+ /* No error to report \r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Likely parse error: token spans multiple lines."),\r
+ g_currentloc);\r
+ */\r
+ }\r
+ \r
+ if (continueLine)\r
+ {\r
+ continueLine = FALSE;\r
+ }\r
+ else \r
+ {\r
+ if (context_inMacro ())\r
+ {\r
+ /* Don't use RETURN_TOK */\r
+ yylval.tok = lltok_create (TENDMACRO, g_currentloc);\r
+ lastWasString = FALSE;\r
+ return (TENDMACRO);\r
+ } \r
+ }\r
+ }\r
+"@@MR@@" { setTokLength (6); \r
+ \r
+ if (processMacro ()) {\r
+ if (context_inIterDef ()) \r
+ { \r
+ RETURN_TOK (LLMACROITER); \r
+ }\r
+ if (context_inIterEnd ())\r
+ {\r
+ RETURN_TOK (LLMACROEND); \r
+ }\r
+ if (context_inMacro ())\r
+ {\r
+ RETURN_TOK (LLMACRO); \r
+ }\r
+ }\r
+ }\r
+"@QLMR" { if (context_inHeader () || context_inFunction ())\r
+ { \r
+ handleMacro ();\r
+ }\r
+ else\r
+ {\r
+ int nspchar = ninput ();\r
+ int nspaces;\r
+\r
+ /* \r
+ ** This is a hack to get the column number correct.\r
+ */\r
+\r
+ llassert (nspchar >= '0' && nspchar <= '9');\r
+ \r
+ nspaces = nspchar - '0';\r
+\r
+ setTokLength (5 + nspaces); \r
+ \r
+ if (processMacro ()) \r
+ {\r
+ if (context_inIterDef ()) \r
+ {\r
+ RETURN_TOK (LLMACROITER); \r
+ }\r
+ if (context_inIterEnd ())\r
+ {\r
+ RETURN_TOK (LLMACROEND); \r
+ }\r
+ if (context_inMacro ())\r
+ { \r
+ RETURN_TOK (LLMACRO); \r
+ }\r
+ }\r
+ }\r
+ }\r
+"@.CT" { setTokLength (4); lldiagmsg (ctype_unparseTable ()); }\r
+"@.FA" { setTokLength (4); lldiagmsg (message ("Access types: %q", typeIdSet_unparse (context_fileAccessTypes ()))); }\r
+"@.F" { setTokLength (3); \r
+ lldiagmsg (message ("%q: *** marker ***", fileloc_unparse (g_currentloc)));\r
+ }\r
+"@.L" { setTokLength (3); usymtab_printLocal (); }\r
+"@.A" { setTokLength (3); lldiagmsg (usymtab_unparseAliases ()); }\r
+"@.C" { setTokLength (3); lldiagmsg (context_unparse ()); }\r
+"@.W" { setTokLength (3); lldiagmsg (context_unparseClauses ()); }\r
+"@.G" { setTokLength (3); usymtab_printGuards (); }\r
+"@.S" { setTokLength (3); usymtab_printOut (); }\r
+"@.X" { setTokLength (3); usymtab_printAll (); }\r
+"@.Z" { setTokLength (3); usymtab_printComplete (); }\r
+"@.T" { setTokLength (3); usymtab_printTypes (); }\r
+"@.K" { setTokLength (3); lldiagmsg (usymtab_unparseStack ()); }\r
+"@.M" { setTokLength (3); \r
+ lldiagmsg (message ("Can modify: %q", \r
+ sRefSet_unparse (context_modList ()))); \r
+ }\r
+"%{" { /* BEFORE_COMMENT_MARKER */\r
+ int tok; \r
+ incColumn (); incColumn ();\r
+ tok = handleLlSpecial (); \r
+\r
+ if (tok != BADTOK)\r
+ {\r
+ if (tok == CANNOTATION) {\r
+ return (tok);\r
+ } else {\r
+ /* Beware - this bashes yylval! */\r
+ RETURN_TOK (tok); \r
+ }\r
+ }\r
+ }\r
+"%}" { /* AFTER_COMMENT_MARKER */ \r
+ setTokLength (2);\r
+ inSpecPart = FALSE;\r
+ RETURN_TOK (QENDMACRO); }\r
+"\\" { incColumn (); continueLine = TRUE; }\r
+. { incColumn (); \r
+ if ((int) *yytext == 13 ) {\r
+ ;\r
+ } else {\r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Invalid character (ascii: %d), skipping character",\r
+ (int)(*yytext)),\r
+ g_currentloc);\r
+ }\r
+ }\r
+%%\r
+\r
+struct skeyword\r
+{\r
+ /*@null@*/ /*@observer@*/ char *name;\r
+ int token;\r
+} ;\r
+\r
+/*\r
+** These tokens are followed by syntax that is parsed by the \r
+** grammar proper.\r
+*/\r
+\r
+struct skeyword s_parsetable[] = {\r
+ { "modifies", QMODIFIES } ,\r
+ { "globals", QGLOBALS } ,\r
+ { "alt", QALT } ,\r
+ { "warn", QWARN } ,\r
+ { "constant", QCONSTANT } ,\r
+ { "function", QFUNCTION } ,\r
+ { "iter", QITER } ,\r
+ { "defines", QDEFINES } ,\r
+ { "uses", QUSES } ,\r
+ { "allocates", QALLOCATES } ,\r
+ { "sets", QSETS } ,\r
+ { "releases", QRELEASES } ,\r
+ { "pre", QPRECLAUSE } ,\r
+ { "post", QPOSTCLAUSE } ,\r
+ { "setBufferSize", QSETBUFFERSIZE},\r
+ { "setStringLength", QSETSTRINGLENGTH},\r
+ { "testinRange", QTESTINRANGE},\r
+ { "requires", QPRECLAUSE } ,\r
+ { "ensures", QPOSTCLAUSE } ,\r
+ { NULL, BADTOK } \r
+} ;\r
+\r
+/*\r
+** These tokens are either stand-alone tokens, or followed by \r
+** token-specific text.\r
+*/\r
+\r
+struct skeyword s_keytable[] = {\r
+ { "anytype", QANYTYPE } ,\r
+ { "integraltype", QINTEGRALTYPE } ,\r
+ { "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,\r
+ { "signedintegraltype", QSIGNEDINTEGRALTYPE } ,\r
+ { "out", QOUT } ,\r
+ { "in", QIN } ,\r
+ { "only", QONLY } , \r
+ { "owned", QOWNED } ,\r
+ { "dependent", QDEPENDENT } ,\r
+ { "partial", QPARTIAL } ,\r
+ { "special", QSPECIAL } ,\r
+ { "truenull", QTRUENULL } ,\r
+ { "falsenull", QFALSENULL } ,\r
+ { "keep", QKEEP } ,\r
+ { "kept", QKEPT } ,\r
+ { "notnull", QNOTNULL } ,\r
+ { "abstract", QABSTRACT } ,\r
+ { "concrete", QCONCRETE } ,\r
+ { "mutable", QMUTABLE } ,\r
+ { "immutable", QIMMUTABLE } ,\r
+ { "unused", QUNUSED } ,\r
+ { "external", QEXTERNAL } ,\r
+ { "sef", QSEF } ,\r
+ { "unique", QUNIQUE } ,\r
+ { "returned", QRETURNED } ,\r
+ { "exposed", QEXPOSED } ,\r
+ { "refcounted", QREFCOUNTED } ,\r
+ { "refs", QREFS } ,\r
+ { "newref", QNEWREF } ,\r
+ { "tempref", QTEMPREF } ,\r
+ { "killref", QKILLREF } ,\r
+ { "null", QNULL } ,\r
+ { "relnull", QRELNULL } ,\r
+ { "nullterminated", QNULLTERMINATED }, \r
+ { "setBufferSize", QSETBUFFERSIZE },\r
+ { "testInRange", QTESTINRANGE},\r
+ { "MaxSet", QMAXSET},\r
+ { "MaxRead", QMAXREAD},\r
+ { "reldef", QRELDEF } ,\r
+ { "observer", QOBSERVER } ,\r
+ { "exits", QEXITS } ,\r
+ { "mayexit", QMAYEXIT } ,\r
+ { "trueexit", QTRUEEXIT } ,\r
+ { "falseexit", QFALSEEXIT } ,\r
+ { "neverexit", QNEVEREXIT } ,\r
+ { "temp", QTEMP } ,\r
+ { "shared", QSHARED } ,\r
+ { "ref", QREF } ,\r
+ { "unchecked", QUNCHECKED } ,\r
+ { "checked", QCHECKED } ,\r
+ { "checkmod", QCHECKMOD } ,\r
+ { "checkedstrict", QCHECKEDSTRICT } ,\r
+ { "innercontinue", QINNERCONTINUE } ,\r
+ { "innerbreak", QINNERBREAK } ,\r
+ { "loopbreak", QLOOPBREAK } ,\r
+ { "switchbreak", QSWITCHBREAK } ,\r
+ { "safebreak", QSAFEBREAK } , \r
+ { "fallthrough", QFALLTHROUGH } ,\r
+ { "l_fallthrou", QLINTFALLTHROUGH } , \r
+ { "l_fallth", QLINTFALLTHRU } ,\r
+ { "notreached", QNOTREACHED } ,\r
+ { "l_notreach", QLINTNOTREACHED } ,\r
+ { "printflike", QPRINTFLIKE } ,\r
+ { "l_printfli", QLINTPRINTFLIKE } ,\r
+ { "scanflike", QSCANFLIKE } ,\r
+ { "messagelike", QMESSAGELIKE } ,\r
+ { "l_argsus", QARGSUSED } ,\r
+ { NULL, BADTOK } \r
+} ;\r
+\r
+/*\r
+** would be better if these weren't hard coded...\r
+*/\r
+\r
+static bool isArtificial (cstring s)\r
+{\r
+ return (cstring_equalLit (s, "modifies") \r
+ || cstring_equalLit (s, "globals") \r
+ || cstring_equalLit (s, "warn")\r
+ || cstring_equalLit (s, "alt"));\r
+}\r
+\r
+void swallowMacro (void)\r
+{\r
+ int i;\r
+ bool skipnext = FALSE;\r
+\r
+ while ((i = lminput ()) != EOF)\r
+ {\r
+ char c = (char) i;\r
+ \r
+ \r
+ if (c == '\\')\r
+ {\r
+ skipnext = TRUE;\r
+ }\r
+ else if (c == '\n')\r
+ {\r
+ if (skipnext)\r
+ {\r
+ skipnext = FALSE;\r
+ }\r
+ else\r
+ {\r
+ reader_checkUngetc (i, yyin);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (i != EOF)\r
+ {\r
+ reader_checkUngetc (i, yyin);\r
+ }\r
+}\r
+\r
+static int commentMarkerToken (cstring s)\r
+{\r
+ int i = 0;\r
+ \r
+ while (s_parsetable[i].name != NULL) \r
+ {\r
+ DPRINTF (("Try :%s:%s:", s, s_parsetable[i].name));\r
+\r
+ if (cstring_equalLit (s, s_parsetable[i].name))\r
+ {\r
+ return s_parsetable[i].token;\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ return BADTOK;\r
+}\r
+\r
+static int tokenMacroCode (cstring s)\r
+{\r
+ int i = 0;\r
+ \r
+ while (s_keytable[i].name != NULL) \r
+ {\r
+ if (cstring_equalLit (s, s_keytable[i].name)) \r
+ {\r
+ if (s_keytable[i].token == QLINTFALLTHROUGH) \r
+ {\r
+ voptgenerror\r
+ (FLG_WARNLINTCOMMENTS,\r
+ cstring_makeLiteral\r
+ ("Traditional lint comment /*FALLTHROUGH*/ used. "\r
+ "This is interpreted by "\r
+ "LCLint in the same way as most Unix lints, but it is "\r
+ "preferable to replace it with the /*@fallthrough@*/ "\r
+ "semantic comment"),\r
+ g_currentloc);\r
+ return QFALLTHROUGH; \r
+ }\r
+ else if (s_keytable[i].token == QLINTFALLTHRU)\r
+ {\r
+ voptgenerror \r
+ (FLG_WARNLINTCOMMENTS,\r
+ cstring_makeLiteral\r
+ ("Traditional lint comment /*FALLTHRU*/ used. "\r
+ "This is interpreted by "\r
+ "LCLint in the same way as most Unix lints, but it is "\r
+ "preferable to replace it with the /*@fallthrough@*/ "\r
+ "semantic comment"),\r
+ g_currentloc);\r
+ return QFALLTHROUGH;\r
+ }\r
+ else if (s_keytable[i].token == QLINTNOTREACHED)\r
+ {\r
+ voptgenerror \r
+ (FLG_WARNLINTCOMMENTS,\r
+ cstring_makeLiteral\r
+ ("Traditional lint comment /*NOTREACHED*/ used. "\r
+ "This is interpreted by "\r
+ "LCLint in the same way as most Unix lints, but it is "\r
+ "preferable to replace it with the /*@notreached@*/ "\r
+ "semantic comment."),\r
+ g_currentloc);\r
+ \r
+ return QNOTREACHED;\r
+ }\r
+ else if (s_keytable[i].token == QPRINTFLIKE)\r
+ {\r
+ setSpecialFunction (qual_createPrintfLike ());\r
+ return SKIPTOK;\r
+ }\r
+ else if (s_keytable[i].token == QLINTPRINTFLIKE)\r
+ { \r
+ voptgenerror \r
+ (FLG_WARNLINTCOMMENTS,\r
+ cstring_makeLiteral\r
+ ("Traditional lint comment /*PRINTFLIKE*/ used. "\r
+ "This is interpreted by "\r
+ "LCLint in the same way as most Unix lints, but it is "\r
+ "preferable to replace it with either /*@printflike@*/, "\r
+ "/*@scanflike@*/ or /*@messagelike@*/."),\r
+ g_currentloc);\r
+ \r
+ setSpecialFunction (qual_createPrintfLike ());\r
+ return SKIPTOK;\r
+ }\r
+ else if (s_keytable[i].token == QSCANFLIKE)\r
+ {\r
+ setSpecialFunction (qual_createScanfLike ());\r
+ return SKIPTOK;\r
+ }\r
+ else if (s_keytable[i].token == QMESSAGELIKE)\r
+ {\r
+ setSpecialFunction (qual_createMessageLike ());\r
+ return SKIPTOK;\r
+ }\r
+ else if (s_keytable[i].token == QARGSUSED)\r
+ {\r
+ voptgenerror\r
+ (FLG_WARNLINTCOMMENTS,\r
+ cstring_makeLiteral\r
+ ("Traditional lint comment /*ARGSUSED*/ used. "\r
+ "This is interpreted by "\r
+ "LCLint in the same way as most Unix lints, but it is "\r
+ "preferable to use /*@unused@*/ annotations on "\r
+ "the unused parameters."),\r
+ g_currentloc);\r
+ \r
+ setArgsUsed ();\r
+ return SKIPTOK;\r
+ }\r
+ \r
+ return s_keytable[i].token;\r
+ }\r
+ \r
+ i++;\r
+ }\r
+ \r
+ return BADTOK;\r
+}\r
+\r
+static int lminput ()\r
+{\r
+ if (savechar == '\0')\r
+ {\r
+ incColumn ();\r
+ return (input ());\r
+ }\r
+ else\r
+ {\r
+ int save = (int) savechar;\r
+ savechar = '\0';\r
+ return save;\r
+ }\r
+}\r
+\r
+static void lmsavechar (char c)\r
+{\r
+ if (savechar == '\0') savechar = c;\r
+ else\r
+ {\r
+ llbuglit ("lmsavechar: override");\r
+ }\r
+}\r
+\r
+static int returnFloat (ctype ct, double f)\r
+{\r
+ yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext), \r
+ fileloc_decColumn (g_currentloc, tokLength));\r
+ tokLength = 0; \r
+ return (CCONSTANT);\r
+}\r
+\r
+static int returnInt (ctype ct, long i)\r
+{\r
+ ctype c = ct;\r
+\r
+ if (ctype_equal (ct, ctype_int))\r
+ {\r
+ if (i == 0)\r
+ {\r
+ c = context_typeofZero ();\r
+ }\r
+ else if (i == 1)\r
+ {\r
+ c = context_typeofOne ();\r
+ }\r
+ }\r
+ \r
+ yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext), \r
+ fileloc_decColumn (g_currentloc, tokLength), i); \r
+ tokLength = 0; \r
+ return (CCONSTANT);\r
+}\r
+\r
+static int returnChar (char c)\r
+{\r
+ yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext), \r
+ fileloc_decColumn (g_currentloc, tokLength));\r
+ tokLength = 0; \r
+ return (CCONSTANT);\r
+}\r
+\r
+static int ninput () \r
+{\r
+ int c = lminput ();\r
+\r
+ if (c != EOF && ((char)c == '\n'))\r
+ {\r
+ context_incLineno ();\r
+ }\r
+\r
+ return c;\r
+}\r
+\r
+static char macro_nextChar ()\r
+{\r
+ static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;\r
+ int ic;\r
+ char c;\r
+\r
+ ic = lminput ();\r
+ c = char_fromInt (ic);\r
+ \r
+ if (!in_quote && !in_char && (c == '\\' || c == BEFORE_COMMENT_MARKER[0]))\r
+ {\r
+ if (c == '\\')\r
+ {\r
+ while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')\r
+ {\r
+ ; /* skip to newline */\r
+ }\r
+ \r
+ context_incLineno ();\r
+ \r
+ if (c != '\0')\r
+ {\r
+ return macro_nextChar ();\r
+ }\r
+ else \r
+ {\r
+ return c;\r
+ }\r
+ }\r
+ else /* if (c == '@') */\r
+ {\r
+ llassert (FALSE); /*@i23@*/\r
+ if (handleLlSpecial () != BADTOK)\r
+ {\r
+ llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax");\r
+ }\r
+\r
+ return macro_nextChar ();\r
+ }\r
+ }\r
+ else if (!in_escape && c == '\"')\r
+ {\r
+ in_quote = !in_quote;\r
+ }\r
+ else if (!in_escape && c == '\'')\r
+ {\r
+ in_char = !in_char;\r
+ }\r
+ else if ((in_quote || in_char) && c == '\\')\r
+ {\r
+ in_escape = !in_escape;\r
+ }\r
+ else if ((in_quote || in_char) && in_escape)\r
+ {\r
+ in_escape = FALSE;\r
+ }\r
+ else if (!in_quote && c == '/')\r
+ {\r
+ char c2;\r
+ \r
+ if ((c2 = char_fromInt (lminput ())) == '*')\r
+ {\r
+ while (c2 != '\0')\r
+ {\r
+ while ((c2 = char_fromInt (lminput ())) != '\0'\r
+ && c2 != '\n' && c2 != '*')\r
+ {\r
+ ;\r
+ }\r
+ \r
+ if (c2 == '*')\r
+ {\r
+ while ((c2 = char_fromInt (lminput ())) != '\0' \r
+ && c2 == '*')\r
+ {\r
+ ;\r
+ }\r
+\r
+ if (c2 == '/')\r
+ {\r
+ goto outofcomment;\r
+ }\r
+ }\r
+ else \r
+ {\r
+ llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));\r
+ }\r
+ }\r
+ outofcomment:\r
+ return macro_nextChar ();\r
+ }\r
+ else\r
+ {\r
+ /*** putchar does not work! why? puts to stdio...??! ***/\r
+ lmsavechar (c2);\r
+ }\r
+ }\r
+ return c;\r
+}\r
+\r
+/*\r
+** keeps semantic comments\r
+*/\r
+\r
+static char macro_nextCharC ()\r
+{\r
+ static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;\r
+ char c;\r
+\r
+ c = char_fromInt (lminput ());\r
+\r
+ if (!in_quote && !in_char && c == '\\')\r
+ {\r
+ while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')\r
+ {\r
+ ; /* skip to newline */\r
+ }\r
+ \r
+ context_incLineno ();\r
+ \r
+ if (c != '\0')\r
+ {\r
+ return macro_nextCharC ();\r
+ }\r
+ else\r
+ {\r
+ return c;\r
+ }\r
+ }\r
+ else if (!in_escape && c == '\"')\r
+ {\r
+ in_quote = !in_quote;\r
+ }\r
+ else if (!in_escape && c == '\'')\r
+ {\r
+ in_char = !in_char;\r
+ }\r
+ else if ((in_quote || in_char) && c == '\\')\r
+ {\r
+ in_escape = !in_escape;\r
+ }\r
+ else if ((in_quote || in_char) && in_escape)\r
+ {\r
+ in_escape = FALSE;\r
+ }\r
+ else if (!in_quote && c == '/')\r
+ {\r
+ char c2;\r
+ \r
+ if ((c2 = char_fromInt (lminput ())) == '*')\r
+ {\r
+ while (c2 != '\0')\r
+ {\r
+ while ((c2 = char_fromInt (lminput ())) != '\0' \r
+ && c2 != '\n' && c2 != '*')\r
+ {\r
+ ;\r
+ }\r
+ \r
+ if (c2 == '*')\r
+ {\r
+ while ((c2 = char_fromInt (lminput ())) != '\0'\r
+ && c2 == '*')\r
+ {\r
+ ;\r
+ }\r
+\r
+ if (c2 == '/') \r
+ {\r
+ goto outofcomment;\r
+ }\r
+ }\r
+ else \r
+ {\r
+ llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));\r
+ }\r
+ }\r
+ outofcomment:\r
+ return macro_nextCharC ();\r
+ }\r
+ else\r
+ {\r
+ lmsavechar (c2);\r
+ }\r
+ }\r
+ return c;\r
+}\r
+\r
+/*\r
+** skips whitespace (handles line continuations)\r
+** returns first non-whitespace character\r
+*/\r
+\r
+static char skip_whitespace ()\r
+{\r
+ char c;\r
+\r
+ while ((c = macro_nextChar ()) == ' ' || c == '\t')\r
+ {\r
+ ;\r
+ }\r
+\r
+ return c;\r
+}\r
+\r
+static void handleMacro ()\r
+{\r
+ cstring mac = cstring_undefined;\r
+ int macrocode;\r
+ char c;\r
+\r
+ while (currentColumn () > 2)\r
+ {\r
+ mac = cstring_appendChar (mac, ' ');\r
+ setTokLength (-1);\r
+ }\r
+\r
+ c = macro_nextCharC ();\r
+\r
+ if (c >= '0' && c <= '9')\r
+ {\r
+ int i;\r
+\r
+ for (i = 0; i < ((c - '0') + 1); i++)\r
+ {\r
+ mac = cstring_appendChar (mac, ' ');\r
+ }\r
+ }\r
+ else\r
+ {\r
+ BADBRANCH;\r
+ }\r
+\r
+ while (((c = macro_nextCharC ()) != '\0') && (c != '\n'))\r
+ {\r
+ mac = cstring_appendChar (mac, c);\r
+ }\r
+\r
+ \r
+ macrocode = tokenMacroCode (mac);\r
+\r
+ if (macrocode == BADTOK && !isArtificial (mac))\r
+ {\r
+ context_addMacroCache (mac);\r
+ }\r
+ else\r
+ {\r
+ cstring_free (mac);\r
+ }\r
+\r
+ if (c == '\n')\r
+ {\r
+ context_incLineno ();\r
+ }\r
+}\r
+\r
+static bool processMacro (void)\r
+{\r
+ uentry e2;\r
+ ctype ct;\r
+ int noparams = 0;\r
+ cstring fname = cstring_undefined;\r
+ bool res = TRUE;\r
+ bool isspecfcn = FALSE;\r
+ bool isiter = FALSE;\r
+ bool skipparam = FALSE;\r
+ bool isenditer = FALSE;\r
+ bool unknownm = FALSE;\r
+ bool hasParams = FALSE;\r
+ bool emptyMacro = FALSE;\r
+ char c = skip_whitespace ();\r
+ fileloc loc = fileloc_noColumn (g_currentloc);\r
+\r
+ /* are both of these necessary? what do they mean? */\r
+ uentryList specparams = uentryList_undefined;\r
+ uentryList pn = uentryList_undefined;\r
+\r
+ context_resetMacroMissingParams ();\r
+\r
+ if (c == '\0' || c == '\n')\r
+ {\r
+ llcontbug (cstring_makeLiteral ("Bad macro"));\r
+ fileloc_free (loc);\r
+ return FALSE;\r
+ }\r
+ \r
+ fname = cstring_appendChar (fname, c); \r
+\r
+ while ((c = macro_nextChar ()) != '(' && c != '\0'\r
+ && c != ' ' && c != '\t' && c != '\n')\r
+ {\r
+ fname = cstring_appendChar (fname, c);\r
+ }\r
+\r
+ if (c == ' ' || c == '\t' || c == '\n')\r
+ {\r
+ char oldc = c;\r
+\r
+ if (c != '\n')\r
+ {\r
+ while (c == ' ' || c == '\t')\r
+ {\r
+ c = macro_nextChar ();\r
+ }\r
+ unput (c);\r
+ }\r
+\r
+ if (c == '\n')\r
+ {\r
+ emptyMacro = TRUE;\r
+ unput (c);\r
+ }\r
+\r
+ c = oldc;\r
+ }\r
+\r
+ hasParams = (c == '(');\r
+ \r
+ if (usymtab_exists (fname))\r
+ {\r
+ e2 = usymtab_lookupExpose (fname);\r
+ ct = uentry_getType (e2);\r
+\r
+ if (uentry_isCodeDefined (e2) \r
+ && fileloc_isUser (uentry_whereDefined (e2)))\r
+ {\r
+ if (optgenerror \r
+ (FLG_MACROREDEF,\r
+ message ("Macro %s already defined", fname),\r
+ loc))\r
+ {\r
+ uentry_showWhereDefined (e2);\r
+ uentry_clearDefined (e2);\r
+ }\r
+\r
+ if (uentry_isFunction (e2))\r
+ {\r
+ uentry_setType (e2, ctype_unknown);\r
+ ct = ctype_unknown;\r
+ unknownm = TRUE;\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ else\r
+ {\r
+ context_enterConstantMacro (e2);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (uentry_isForward (e2) && uentry_isFunction (e2))\r
+ {\r
+ unknownm = TRUE;\r
+\r
+ voptgenerror \r
+ (FLG_MACROFCNDECL,\r
+ message\r
+ ("Parameterized macro has no prototype or specification: %s ", \r
+ fname),\r
+ loc);\r
+ \r
+ ct = ctype_unknown;\r
+ uentry_setType (e2, ctype_unknown);\r
+ uentry_setFunctionDefined (e2, loc); \r
+ uentry_setUsed (e2, fileloc_undefined);\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ else\r
+ {\r
+ if (uentry_isIter (e2))\r
+ {\r
+ isiter = TRUE;\r
+ specparams = uentry_getParams (e2);\r
+ noparams = uentryList_size (specparams);\r
+ uentry_setDefined (e2, loc);\r
+ context_enterIterDef (e2); \r
+ }\r
+ else if (uentry_isEndIter (e2))\r
+ {\r
+ isenditer = TRUE;\r
+ uentry_setDefined (e2, loc);\r
+ context_enterIterEnd (e2); /* don't care about it now */\r
+ /* but should parse like an iter! */\r
+ }\r
+ else if (uentry_isConstant (e2))\r
+ {\r
+ if (hasParams)\r
+ {\r
+ voptgenerror \r
+ (FLG_INCONDEFS, \r
+ message ("Constant %s implemented as parameterized macro",\r
+ fname),\r
+ g_currentloc);\r
+ \r
+ uentry_showWhereSpecified (e2);\r
+ uentry_setType (e2, ctype_unknown);\r
+ uentry_makeConstantFunction (e2);\r
+ uentry_setDefined (e2, g_currentloc);\r
+ uentry_setFunctionDefined (e2, g_currentloc);\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ else\r
+ {\r
+ if (!uentry_isSpecified (e2))\r
+ {\r
+ fileloc oloc = uentry_whereDeclared (e2);\r
+\r
+ if (fileloc_isLib (oloc))\r
+ {\r
+ ;\r
+ }\r
+ else if (fileloc_isUndefined (oloc)\r
+ || fileloc_isPreproc (oloc))\r
+ {\r
+ if (!emptyMacro)\r
+ {\r
+ voptgenerror\r
+ (FLG_MACROCONSTDECL,\r
+ message \r
+ ("Macro constant %q not declared",\r
+ uentry_getName (e2)),\r
+ loc); \r
+ }\r
+ }\r
+ else if (!fileloc_withinLines (oloc, loc, 2))\r
+ { /* bogus! will give errors if there is too much whitespace */\r
+ voptgenerror\r
+ (FLG_SYNTAX,\r
+ message \r
+ ("Macro constant name %s does not match name in "\r
+ "previous constant declaration. This constant "\r
+ "is declared at %q", fname, \r
+ fileloc_unparse (oloc)),\r
+ loc);\r
+ }\r
+ }\r
+\r
+ context_enterConstantMacro (e2); \r
+ cstring_free (fname);\r
+ fileloc_free (loc);\r
+ return res;\r
+ }\r
+\r
+ }\r
+ else if (ctype_isFunction (ct))\r
+ {\r
+ isspecfcn = TRUE;\r
+ specparams = ctype_argsFunction (ct);\r
+ noparams = uentryList_size (specparams);\r
+ \r
+ uentry_setFunctionDefined (e2, loc); \r
+ context_enterMacro (e2);\r
+ }\r
+ else if (uentry_isVar (e2))\r
+ {\r
+ if (hasParams)\r
+ {\r
+ voptgenerror\r
+ (FLG_INCONDEFS,\r
+ message ("Variable %s implemented as parameterized macro", \r
+ fname),\r
+ loc);\r
+\r
+ uentry_showWhereSpecified (e2);\r
+ uentry_setType (e2, ctype_unknown);\r
+ uentry_makeVarFunction (e2);\r
+ uentry_setDefined (e2, g_currentloc);\r
+ uentry_setFunctionDefined (e2, g_currentloc);\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ else\r
+ {\r
+ uentry ucons = uentry_makeConstant (fname,\r
+ ctype_unknown,\r
+ loc);\r
+ if (uentry_isExpandedMacro (e2))\r
+ {\r
+ ; /* okay */\r
+ }\r
+ else\r
+ {\r
+ if (optgenerror \r
+ (FLG_INCONDEFS,\r
+ message ("Variable %s implemented by a macro",\r
+ fname),\r
+ loc))\r
+ {\r
+ uentry_showWhereSpecified (e2);\r
+ }\r
+ }\r
+\r
+ uentry_setDefined (e2, loc);\r
+ uentry_setUsed (ucons, loc);\r
+\r
+ context_enterConstantMacro (ucons);\r
+ uentry_markOwned (ucons);\r
+ cstring_free (fname);\r
+ return res;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (uentry_isDatatype (e2))\r
+ {\r
+ vgenhinterror \r
+ (FLG_SYNTAX,\r
+ message ("Type implemented as macro: %x", \r
+ uentry_getName (e2)),\r
+ message ("A type is implemented using a macro definition. A "\r
+ "typedef should be used instead."),\r
+ g_currentloc);\r
+\r
+ swallowMacro ();\r
+ /* Must exit scope (not sure why a new scope was entered?) */\r
+ usymtab_quietExitScope (g_currentloc);\r
+ uentry_setDefined (e2, g_currentloc);\r
+ res = FALSE;\r
+ }\r
+ else\r
+ {\r
+ llcontbug \r
+ (message ("Unexpanded macro not function or constant: %q", \r
+ uentry_unparse (e2)));\r
+ uentry_setType (e2, ctype_unknown);\r
+ \r
+ if (hasParams)\r
+ {\r
+ uentry_makeVarFunction (e2);\r
+ uentry_setDefined (e2, g_currentloc);\r
+ uentry_setFunctionDefined (e2, g_currentloc);\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ uentry ce;\r
+\r
+ /* evans 2001-09-09 - if it has params, assume a function */\r
+ if (hasParams)\r
+ {\r
+ voptgenerror \r
+ (FLG_MACROMATCHNAME,\r
+ message ("Unexpanded macro %s does not match name of a declared "\r
+ "function. The name used in the control "\r
+ "comment on the previous line should match.",\r
+ fname),\r
+ loc);\r
+ \r
+ ce = uentry_makeFunction (fname, ctype_unknown, \r
+ typeId_invalid,\r
+ globSet_undefined,\r
+ sRefSet_undefined,\r
+ warnClause_undefined,\r
+ fileloc_undefined); \r
+ uentry_setUsed (ce, loc); /* perhaps bogus? */\r
+ e2 = usymtab_supEntryReturn (ce);\r
+ context_enterUnknownMacro (e2); \r
+ }\r
+ else\r
+ {\r
+ voptgenerror \r
+ (FLG_MACROMATCHNAME,\r
+ message ("Unexpanded macro %s does not match name of a constant "\r
+ "or iter declaration. The name used in the control "\r
+ "comment on the previous line should match. "\r
+ "(Assuming macro defines a constant.)", \r
+ fname),\r
+ loc);\r
+ \r
+ ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined); \r
+ uentry_setUsed (ce, loc); /* perhaps bogus? */\r
+ e2 = usymtab_supEntryReturn (ce);\r
+ \r
+ context_enterConstantMacro (e2); \r
+ cstring_free (fname);\r
+ fileloc_free (loc);\r
+ return res;\r
+ }\r
+ }\r
+ \r
+ /* in macros, ( must follow immediatetly after name */\r
+ \r
+ if (hasParams)\r
+ {\r
+ int paramno = 0;\r
+ \r
+ c = skip_whitespace ();\r
+\r
+ while (c != ')' && c != '\0')\r
+ {\r
+ uentry param;\r
+ bool suppress = context_inSuppressRegion ();\r
+ cstring paramname = cstring_undefined;\r
+\r
+ /*\r
+ ** save the parameter location\r
+ */\r
+\r
+ decColumn ();\r
+ context_saveLocation ();\r
+ incColumn ();\r
+\r
+ while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')\r
+ {\r
+ paramname = cstring_appendChar (paramname, c);\r
+ c = macro_nextChar ();\r
+ }\r
+ \r
+ if (c == ' ' || c == '\t') c = skip_whitespace ();\r
+\r
+ if (c == ',')\r
+ {\r
+ c = macro_nextChar ();\r
+ if (c == ' ' || c == '\t') c = skip_whitespace ();\r
+ }\r
+ \r
+ if (c == '\0')\r
+ {\r
+ llfatalerror (cstring_makeLiteral\r
+ ("Bad macro syntax: uentryList"));\r
+ }\r
+ \r
+ if ((isspecfcn || isiter) && (paramno < noparams)\r
+ && !uentry_isElipsisMarker (uentryList_getN \r
+ (specparams, paramno)))\r
+ {\r
+ fileloc sloc = context_getSaveLocation ();\r
+ uentry decl = uentryList_getN (specparams, paramno);\r
+ sRef sr;\r
+ \r
+ param = uentry_nameCopy (paramname, decl);\r
+ \r
+ uentry_setParam (param);\r
+ sr = sRef_makeParam (paramno, uentry_getType (param), stateInfo_makeLoc (sloc));\r
+\r
+ if (sRef_getNullState (sr) == NS_ABSNULL)\r
+ {\r
+ ctype pt = ctype_realType (uentry_getType (param));\r
+\r
+ if (ctype_isUser (pt))\r
+ {\r
+ uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));\r
+ \r
+ if (uentry_isValid (te))\r
+ {\r
+ sRef_setStateFromUentry (sr, te);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ sRef_setNullState (sr, NS_UNKNOWN, sloc);\r
+ }\r
+ }\r
+\r
+ uentry_setSref (param, sr);\r
+ uentry_setDeclaredForceOnly (param, sloc);\r
+\r
+ skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));\r
+ }\r
+ else\r
+ {\r
+ fileloc sloc = context_getSaveLocation ();\r
+\r
+ param = uentry_makeVariableSrefParam \r
+ (paramname, ctype_unknown, fileloc_copy (sloc), \r
+ sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (sloc)));\r
+ DPRINTF (("Unknown param: %s", uentry_unparseFull (param)));\r
+ cstring_free (paramname);\r
+\r
+ sRef_setPosNull (uentry_getSref (param), sloc);\r
+ uentry_setDeclaredForce (param, sloc);\r
+\r
+ skipparam = FALSE;\r
+ fileloc_free (sloc);\r
+ }\r
+\r
+ if (!skipparam)\r
+ {\r
+ llassert (!uentry_isElipsisMarker (param));\r
+\r
+ if (!suppress)\r
+ {\r
+ sRef_makeUnsafe (uentry_getSref (param));\r
+ }\r
+ \r
+ pn = uentryList_add (pn, uentry_copy (param));\r
+ usymtab_supEntry (param);\r
+ }\r
+ else\r
+ {\r
+ /* don't add param */\r
+ uentry_free (param);\r
+ }\r
+\r
+ if (c == ',') \r
+ {\r
+ (void) macro_nextChar ();\r
+ c = skip_whitespace ();\r
+ }\r
+\r
+ paramno++;\r
+ }\r
+ \r
+ if (c == ')')\r
+ {\r
+ if (isspecfcn || isiter)\r
+ {\r
+ if (paramno != noparams && noparams >= 0)\r
+ {\r
+ advanceLine ();\r
+\r
+ voptgenerror \r
+ (FLG_INCONDEFS,\r
+ message ("Macro %s specified with %d args, defined with %d", \r
+ fname, noparams, paramno),\r
+ g_currentloc);\r
+\r
+ uentry_showWhereSpecified (e2);\r
+ uentry_resetParams (e2, pn);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ uentry_resetParams (e2, pn);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ ** the form should be:\r
+ **\r
+ ** # define newname oldname\r
+ ** where oldname refers to a function matching the specification\r
+ ** of newname.\r
+ */\r
+\r
+ if (unknownm)\r
+ {\r
+ sRef_setGlobalScope ();\r
+ usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));\r
+ sRef_clearGlobalScope ();\r
+ }\r
+ else\r
+ {\r
+ context_setMacroMissingParams ();\r
+ }\r
+ }\r
+ \r
+ \r
+ /* context_setuentryList (pn); */\r
+ usymtab_enterScope ();\r
+\r
+ fileloc_free (loc);\r
+ cstring_free (fname);\r
+\r
+ return res;\r
+}\r
+\r
+static bool handleSpecial (char *yyt)\r
+{\r
+ char *l = mstring_create (MAX_NAME_LENGTH);\r
+ static bool reportcpp = FALSE;\r
+ int lineno = 0;\r
+ char c;\r
+ char *ol;\r
+ cstring olc;\r
+ \r
+ strcpy (l, yyt + 1);\r
+\r
+ /* Need to safe original l for deallocating. */\r
+ ol = l;\r
+\r
+ l += strlen (yyt) - 1;\r
+ \r
+ while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')\r
+ {\r
+ *l++ = c;\r
+ }\r
+\r
+ *l = '\0';\r
+ olc = cstring_fromChars (ol);\r
+ \r
+ if (cstring_equalPrefixLit (olc, "pragma"))\r
+ {\r
+ char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN));\r
+ char *opname = pname;\r
+ char *ptr = ol + 6; /* pragma is six characters, plus space */\r
+ int len = 0;\r
+ \r
+ \r
+ /* skip whitespace */\r
+ while (((c = *ptr) != '\0') && isspace (c))\r
+ {\r
+ ptr++;\r
+ }\r
+\r
+ \r
+ while (((c = *ptr) != '\0') && !isspace (c))\r
+ {\r
+ len++;\r
+\r
+ if (len > MAX_PRAGMA_LEN)\r
+ {\r
+ break;\r
+ }\r
+\r
+ ptr++;\r
+ *pname++ = c;\r
+ }\r
+\r
+ *pname = '\0';\r
+ \r
+ if (len == PRAGMA_LEN_EXPAND \r
+ && mstring_equal (opname, PRAGMA_EXPAND))\r
+ {\r
+ cstring exname = cstring_undefined;\r
+ uentry ue;\r
+ \r
+ ptr++; \r
+ while (((c = *ptr) != '\0') && !isspace (c))\r
+ {\r
+ exname = cstring_appendChar (exname, c);\r
+ ptr++;\r
+ }\r
+ \r
+ \r
+ ue = usymtab_lookupExposeGlob (exname);\r
+ \r
+ if (uentry_isExpandedMacro (ue))\r
+ {\r
+ if (fileloc_isPreproc (uentry_whereDefined (ue)))\r
+ {\r
+ fileloc_setColumn (g_currentloc, 1);\r
+ uentry_setDefined (ue, g_currentloc);\r
+ }\r
+ }\r
+\r
+ cstring_free (exname);\r
+ }\r
+ }\r
+ else if (cstring_equalPrefixLit (olc, "ident"))\r
+ {\r
+ /* Some pre-processors will leave these in the code. Ignore rest of line */\r
+ }\r
+ /*\r
+ ** Yuk...Win32 filenames can have spaces in them...we need to read\r
+ ** to the matching end quote.\r
+ */\r
+ else if ((sscanf (ol, "line %d \"", &lineno) == 1)\r
+ || (sscanf (ol, " %d \"", &lineno) == 1))\r
+ {\r
+ char *tmp = ol;\r
+ cstring fname;\r
+ fileId fid;\r
+\r
+ /*@access cstring@*/\r
+ while (*tmp != '\"' && *tmp != '\0')\r
+ {\r
+ tmp++;\r
+ }\r
+\r
+ llassert (*tmp == '\"');\r
+\r
+ tmp++;\r
+\r
+ fname = tmp;\r
+ \r
+ while (*tmp != '\"' && *tmp != '\0')\r
+ {\r
+ tmp++;\r
+ }\r
+\r
+ llassert (*tmp == '\"');\r
+\r
+ *tmp = '\0';\r
+\r
+# if defined(OS2) || defined(MSDOS) || defined(WIN32)\r
+\r
+ /*\r
+ ** DOS-like path delimiters get delivered in pairs, something like \r
+ ** \"..\\\\file.h\", so we have to make it normal again. We do NOT\r
+ ** remove the pre dirs yet as we usually specify tmp paths relative\r
+ ** to the current directory, so tmp files would not get found in\r
+ ** the hash table. If this method fails we try it again later. \r
+ */\r
+\r
+ {\r
+ char *stmp = fname;\r
+ \r
+ /*\r
+ ** Skip past the drive marker.\r
+ */\r
+ \r
+ if (strchr (stmp, ':') != NULL)\r
+ {\r
+ stmp = strchr (stmp, ':') + 1;\r
+ }\r
+ \r
+ while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )\r
+ {\r
+ if (*(stmp+1) == CONNECTCHAR)\r
+ {\r
+ memmove (stmp, stmp+1, strlen (stmp));\r
+ }\r
+ \r
+ stmp++;\r
+ }\r
+ \r
+ fid = fileTable_lookupBase (context_fileTable (), fname);\r
+ if (!(fileId_isValid (fid)))\r
+ {\r
+ fname = removePreDirs (fname);\r
+ fid = fileTable_lookupBase (context_fileTable (), fname);\r
+ }\r
+ }\r
+# else /* !defined(OS2) && !defined(MSDOS) */\r
+ fname = removePreDirs (fname);\r
+ fid = fileTable_lookupBase (context_fileTable (), fname); \r
+# endif /* !defined(OS2) && !defined(MSDOS) */\r
+ \r
+ if (!(fileId_isValid (fid)))\r
+ {\r
+ if (context_inXHFile ())\r
+ {\r
+ fid = fileTable_addXHFile (context_fileTable (), fname);\r
+ }\r
+ else if (isHeaderFile (fname))\r
+ {\r
+ fid = fileTable_addHeaderFile (context_fileTable (), fname);\r
+ }\r
+ else\r
+ {\r
+ fid = fileTable_addFile (context_fileTable (), fname);\r
+ }\r
+ }\r
+ \r
+ setFileLine (fid, lineno);\r
+ /*@noaccess cstring@*/\r
+ }\r
+ else if ((sscanf (ol, "line %d", &lineno) == 1) \r
+ || (sscanf (ol, " %d", &lineno) == 1))\r
+ {\r
+ setLine (lineno); /* next line is <cr> */\r
+ }\r
+ else\r
+ {\r
+ if (mstring_equal (ol, "")) {\r
+ DPRINTF (("Empty pp command!"));\r
+ /*\r
+ ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.\r
+ ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.\r
+ */\r
+ mstring_free (ol);\r
+ return FALSE;\r
+ } else {\r
+ if (!reportcpp)\r
+ {\r
+ \r
+ } else {\r
+ llbug (message ("File contains preprocessor command: #%s", \r
+ cstring_fromChars (ol)));\r
+ reportcpp = TRUE;\r
+ }\r
+ }\r
+ \r
+ sfree (ol);\r
+ return TRUE;\r
+ }\r
+\r
+ sfree (ol);\r
+ return FALSE;\r
+}\r
+ \r
+static int handleLlSpecial ()\r
+{ \r
+ bool hasnl = FALSE;\r
+ int ic; \r
+ char c;\r
+ char *s = mstring_createEmpty ();\r
+ char *os; \r
+ int tok;\r
+ int charsread = 0;\r
+ fileloc loc;\r
+\r
+ loc = fileloc_copy (g_currentloc);\r
+ DPRINTF (("Handle special: %s", fileloc_unparse (loc)));\r
+\r
+ while (((ic = ninput ()) != 0) && isalpha (ic))\r
+ {\r
+ c = (char) ic;\r
+ s = mstring_append (s, c);\r
+ charsread++;\r
+ }\r
+\r
+ DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));\r
+ os = s;\r
+\r
+ if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])\r
+ {\r
+ ic = ninput ();\r
+\r
+ llassert (ic == AFTER_COMMENT_MARKER[1]);\r
+ \r
+ if (*s == '\0')\r
+ {\r
+ sfree (os);\r
+ fileloc_free (loc);\r
+ return QNOMODS; /* special token no modifications token */\r
+ }\r
+ }\r
+ \r
+ DPRINTF (("Coment marker: %s", os));\r
+ tok = commentMarkerToken (cstring_fromChars (os));\r
+\r
+ if (tok != BADTOK)\r
+ {\r
+ tokLength = charsread;\r
+ sfree (os);\r
+ inSpecPart = TRUE;\r
+ fileloc_free (loc);\r
+ return tok;\r
+ }\r
+\r
+ DPRINTF (("Not a comment marker..."));\r
+ /* Add rest of the comment */\r
+ \r
+ if (ic != 0 && ic != EOF)\r
+ {\r
+ c = (char) ic;\r
+ \r
+ s = mstring_append (s, c);\r
+ charsread++;\r
+\r
+ while (((ic = ninput ()) != 0) && (ic != EOF)\r
+ && (ic != AFTER_COMMENT_MARKER[0]))\r
+ {\r
+ c = (char) ic;\r
+\r
+ /* evans 2001-09-01 added to prevent assertion failures for uncloses syntactic comments */\r
+\r
+ if (c == '\n') {\r
+ hasnl = TRUE; /* This prevents tokLength from being set later. */\r
+ tokLength = 0; \r
+\r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Likely parse error: syntactic comment token spans multiple lines: %s",\r
+ cstring_fromChars (s)),\r
+ g_currentloc);\r
+ }\r
+\r
+ s = mstring_append (s, c);\r
+ charsread++;\r
+ }\r
+ }\r
+\r
+ DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));\r
+\r
+ if (ic == AFTER_COMMENT_MARKER[0]) \r
+ {\r
+ int nc = ninput ();\r
+ llassert ((char) nc == AFTER_COMMENT_MARKER[1]);\r
+ charsread++;\r
+ }\r
+\r
+ os = s;\r
+\r
+ while (*s == ' ' || *s == '\t' || *s == '\n') \r
+ {\r
+ s++;\r
+ }\r
+\r
+ if (*s == '-' || *s == '+' || *s == '=') /* setting flags */\r
+ {\r
+ c = *s;\r
+\r
+ while (c == '-' || c == '+' || c == '=')\r
+ {\r
+ ynm set = ynm_fromCodeChar (c);\r
+ cstring thisflag;\r
+\r
+ s++;\r
+ \r
+ thisflag = cstring_fromChars (s);\r
+ \r
+ while ((c = *s) != '\0' && (c != '-') && (c != '=')\r
+ && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))\r
+ {\r
+ s++;\r
+ }\r
+\r
+ *s = '\0';\r
+\r
+ if (!context_getFlag (FLG_NOCOMMENTS))\r
+ {\r
+ cstring flagname = thisflag;\r
+ flagcode fflag = identifyFlag (flagname);\r
+ \r
+ if (flagcode_isSkip (fflag))\r
+ {\r
+ ;\r
+ }\r
+ else if (flagcode_isInvalid (fflag))\r
+ {\r
+ if (isMode (flagname))\r
+ {\r
+ if (ynm_isMaybe (set))\r
+ {\r
+ llerror\r
+ (FLG_BADFLAG, \r
+ message \r
+ ("Semantic comment attempts to restore flag %s. "\r
+ "A mode flag cannot be restored.",\r
+ flagname));\r
+ }\r
+ else\r
+ {\r
+ context_setMode (flagname);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ voptgenerror\r
+ (FLG_UNRECOGFLAGCOMMENTS,\r
+ message ("Unrecognized option in semantic comment: %s", \r
+ flagname),\r
+ g_currentloc);\r
+ }\r
+ }\r
+ else if (flagcode_isGlobalFlag (fflag))\r
+ {\r
+ voptgenerror\r
+ (FLG_BADFLAG, \r
+ message \r
+ ("Semantic comment attempts to set global flag %s. "\r
+ "A global flag cannot be set locally.",\r
+ flagname),\r
+ g_currentloc);\r
+ }\r
+ else\r
+ {\r
+ context_fileSetFlag (fflag, set);\r
+ \r
+ if (flagcode_hasArgument (fflag))\r
+ {\r
+ if (ynm_isMaybe (set))\r
+ {\r
+ voptgenerror\r
+ (FLG_BADFLAG, \r
+ message \r
+ ("Semantic comment attempts to restore flag %s. "\r
+ "A flag for setting a value cannot be restored.",\r
+ flagname),\r
+ g_currentloc);\r
+ }\r
+ else\r
+ { /* cut-and-pastied from llmain...blecch */\r
+ cstring extra = cstring_undefined;\r
+ char *rest;\r
+ char *orest;\r
+ char rchar;\r
+ \r
+ *s = c;\r
+ rest = mstring_copy (s);\r
+ orest = rest;\r
+ *s = '\0';\r
+ \r
+ while ((rchar = *rest) != '\0'\r
+ && (isspace (rchar)))\r
+ {\r
+ rest++;\r
+ s++;\r
+ }\r
+ \r
+ while ((rchar = *rest) != '\0'\r
+ && !isspace (rchar))\r
+ {\r
+ extra = cstring_appendChar (extra, rchar);\r
+ rest++; \r
+ s++;\r
+ }\r
+ \r
+ sfree (orest);\r
+ \r
+ if (cstring_isUndefined (extra))\r
+ {\r
+ llerror \r
+ (FLG_BADFLAG,\r
+ message\r
+ ("Flag %s (in semantic comment) must be followed by an argument",\r
+ flagcode_unparse (fflag)));\r
+ }\r
+ else\r
+ {\r
+ s--;\r
+ \r
+ if (flagcode_hasValue (fflag))\r
+ {\r
+ setValueFlag (fflag, extra);\r
+ }\r
+ else if (flagcode_hasString (fflag))\r
+ {\r
+ setStringFlag (fflag, extra);\r
+ }\r
+ else\r
+ {\r
+ BADEXIT;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ;\r
+ }\r
+\r
+ *s = c;\r
+ while ((c == ' ') || (c == '\t') || (c == '\n'))\r
+ {\r
+ c = *(++s);\r
+ }\r
+ } \r
+\r
+ if (context_inHeader () && !isArtificial (cstring_fromChars (os)))\r
+ {\r
+ DPRINTF (("Here adding comment: %s", os));\r
+ context_addComment (cstring_fromCharsNew (os));\r
+ }\r
+ else\r
+ {\r
+ ;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ char *t = s;\r
+ int macrocode;\r
+ char tchar = '\0';\r
+ annotationInfo ainfo;\r
+\r
+ while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n') \r
+ {\r
+ s++;\r
+ }\r
+\r
+ if (*s != '\0') \r
+ {\r
+ tchar = *s;\r
+ *s = '\0';\r
+ s++;\r
+ }\r
+ \r
+ t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));\r
+ macrocode = tokenMacroCode (cstring_fromChars (t));\r
+\r
+ if (macrocode != BADTOK)\r
+ {\r
+ tokLength = hasnl ? 0 : mstring_length (t);\r
+ \r
+ sfree (t);\r
+ sfree (os);\r
+ fileloc_free (loc);\r
+\r
+ if (macrocode == SKIPTOK)\r
+ {\r
+ return BADTOK;\r
+ }\r
+\r
+ return macrocode;\r
+ }\r
+ \r
+ ainfo = context_lookupAnnotation (cstring_fromChars (os));\r
+ \r
+ if (annotationInfo_isDefined (ainfo)) {\r
+ DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));\r
+ /*@i324@*/ yylval.annotation = ainfo;\r
+ tokLength = 0;\r
+ sfree (os);\r
+ sfree (t);\r
+ fileloc_free (loc);\r
+ return CANNOTATION;\r
+ } \r
+\r
+ if (context_inHeader ())\r
+ {\r
+ if (tchar != '\0')\r
+ {\r
+ *(s-1) = tchar;\r
+ }\r
+ \r
+ if ((context_inMacro () || context_inGlobalContext ())\r
+ && macrocode != SKIPTOK\r
+ && !isArtificial (cstring_fromChars (os))) \r
+ {\r
+ DPRINTF (("Add comment: %s", os));\r
+ context_addComment (cstring_fromCharsNew (os));\r
+ }\r
+ else\r
+ {\r
+ ; \r
+ }\r
+ \r
+ if (tchar != '\0')\r
+ {\r
+ *(s-1) = '\0';\r
+ }\r
+ }\r
+\r
+ if (mstring_equal (t, "ignore"))\r
+ {\r
+ if (!context_getFlag (FLG_NOCOMMENTS))\r
+ {\r
+ context_enterSuppressRegion ();\r
+ }\r
+ }\r
+ else if ((*t == 'i' || *t == 't')\r
+ && (*(t + 1) == '\0'))\r
+ {\r
+ if (!context_getFlag (FLG_NOCOMMENTS)\r
+ && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))\r
+ {\r
+ context_enterSuppressLine (-1); /* infinite suppression */\r
+ }\r
+ }\r
+ else if (((*t == 'i') || (*t == 't'))\r
+ && ((*(t + 1) >= '0' && *(t + 1) <= '9')))\r
+ {\r
+ bool tmpcomment = (*t == 't');\r
+ int val = -1; \r
+ char *tt = t; /* don't mangle t, since it is free'd */\r
+ char lc = *(++tt);\r
+\r
+ if (lc >= '0' && lc <= '9')\r
+ {\r
+ val = (int)(lc - '0');\r
+ \r
+ lc = *(++tt); \r
+ while (lc >= '0' && lc <= '9')\r
+ {\r
+ val *= 10;\r
+ val += lc - '0';\r
+ lc = *(++tt);\r
+ }\r
+ }\r
+\r
+ \r
+ if (!context_getFlag (FLG_NOCOMMENTS)\r
+ && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))\r
+ {\r
+ context_enterSuppressLine (val);\r
+ }\r
+ }\r
+ else if (mstring_equal (t, "end"))\r
+ {\r
+ if (!context_getFlag (FLG_NOCOMMENTS))\r
+ {\r
+ context_exitSuppressRegion ();\r
+ }\r
+ }\r
+ else if (mstring_equal (t, "notfunction"))\r
+ {\r
+ ; /* handled by pcpp */\r
+ }\r
+ else if (mstring_equal (t, "access"))\r
+ {\r
+ cstring tname;\r
+ \r
+ while (TRUE)\r
+ {\r
+ while ((c = *s) && (c == ' ' || c == '\t' || c == '\n'))\r
+ {\r
+ s++;\r
+ }\r
+ \r
+ if (c == '\0')\r
+ {\r
+ break;\r
+ }\r
+\r
+ tname = cstring_fromChars (s);\r
+ \r
+ while ((c = *s) != '\0' && c != ' ' \r
+ && c != '\t' && c != '\n' && c != ',') \r
+ {\r
+ s++;\r
+ }\r
+\r
+ *s = '\0';\r
+\r
+ DPRINTF (("Access %s", tname));\r
+\r
+ if (!context_getFlag (FLG_NOCOMMENTS) \r
+ && !context_getFlag (FLG_NOACCESS))\r
+ {\r
+ if (usymtab_existsType (tname))\r
+ {\r
+ typeId uid = usymtab_getTypeId (tname);\r
+ uentry ue = usymtab_getTypeEntry (uid);\r
+\r
+ if (uentry_isAbstractDatatype (ue))\r
+ {\r
+ context_addFileAccessType (uid);\r
+ DPRINTF (("Adding access to: %s / %d", tname, uid));\r
+ }\r
+ else\r
+ {\r
+ voptgenerror\r
+ (FLG_COMMENTERROR,\r
+ message\r
+ ("Non-abstract type %s used in access comment",\r
+ tname),\r
+ g_currentloc);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (!(context_inSuppressRegion ()\r
+ || context_inSuppressZone (g_currentloc)))\r
+ {\r
+ voptgenerror\r
+ (FLG_COMMENTERROR,\r
+ message\r
+ ("Unrecognized type %s used in access comment",\r
+ tname),\r
+ g_currentloc);\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (c != '\0') \r
+ {\r
+ s++;\r
+ }\r
+ \r
+ if (c != ',' && c != ' ')\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else if (mstring_equal (t, "noaccess"))\r
+ {\r
+ cstring tname;\r
+ char lc;\r
+ \r
+ while (TRUE)\r
+ {\r
+ while ((lc = *s) && (lc == ' ' || lc == '\t' || lc == '\n')) \r
+ {\r
+ s++;\r
+ }\r
+ \r
+ if (lc == '\0')\r
+ {\r
+ break;\r
+ }\r
+\r
+ tname = cstring_fromChars (s);\r
+ \r
+ while ((lc = *s) != '\0' && lc != ' ' && lc != '\t' \r
+ && lc != '\n' && lc != ',') \r
+ {\r
+ s++;\r
+ }\r
+\r
+ *s = '\0';\r
+\r
+ if (!context_getFlag (FLG_NOCOMMENTS) \r
+ && !context_getFlag (FLG_NOACCESS))\r
+ {\r
+ if (usymtab_existsType (tname))\r
+ {\r
+ typeId tuid = usymtab_getTypeId (tname);\r
+ \r
+ if (context_couldHaveAccess (tuid))\r
+ {\r
+ DPRINTF (("Removing access: %s", tname));\r
+ context_removeFileAccessType (tuid);\r
+ }\r
+ else\r
+ {\r
+ if (!(context_inSuppressRegion () \r
+ || context_inSuppressZone (g_currentloc)))\r
+ {\r
+ uentry ue = usymtab_getTypeEntry (tuid);\r
+ \r
+ if (uentry_isAbstractDatatype (ue))\r
+ {\r
+ voptgenerror\r
+ (FLG_COMMENTERROR,\r
+ message\r
+ ("Non-accessible abstract type %s used in noaccess comment",\r
+ tname),\r
+ g_currentloc);\r
+ }\r
+ else\r
+ {\r
+ voptgenerror\r
+ (FLG_COMMENTERROR,\r
+ message\r
+ ("Non-abstract type %s used in noaccess comment",\r
+ tname),\r
+ g_currentloc);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (!(context_inSuppressRegion () \r
+ || context_inSuppressZone (g_currentloc)))\r
+ {\r
+ voptgenerror\r
+ (FLG_COMMENTERROR,\r
+ message\r
+ ("Unrecognized type %s used in noaccess comment",\r
+ tname),\r
+ g_currentloc);\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (lc != '\0') \r
+ {\r
+ s++;\r
+ }\r
+ \r
+ if (lc != ',' && lc != ' ')\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ voptgenerror (FLG_UNRECOGCOMMENTS, \r
+ message ("Semantic comment unrecognized: %s", \r
+ cstring_fromChars (os)), loc);\r
+ }\r
+\r
+ sfree (t);\r
+ }\r
+ \r
+ sfree (os);\r
+ fileloc_free (loc);\r
+ return BADTOK;\r
+}\r
+\r
+static /*@only@*/ cstring makeIdentifier (char *s)\r
+{\r
+ char *c = mstring_create (size_toInt (strlen (s)) + 1);\r
+ cstring id = cstring_fromChars (c);\r
+\r
+ while (isalnum (*s) || (*s == '_') || (*s == '$')) \r
+ {\r
+ *c++ = *s++;\r
+ }\r
+\r
+ *c = '\0';\r
+ return (id);\r
+}\r
+\r
+/*@observer@*/ /*@dependent@*/ uentry coerceId (cstring cn)\r
+{\r
+ if (!(usymtab_exists (cn)))\r
+ {\r
+ fileloc loc = fileloc_createExternal ();\r
+ \r
+ /*\r
+ ** We need to put this in a global scope, otherwise the sRef will be deallocated.\r
+ */\r
+ \r
+ uentry ce = uentry_makeUnrecognized (cn, loc);\r
+ \r
+ if (!context_inIterEnd ())\r
+ {\r
+ voptgenerror \r
+ (FLG_SYSTEMUNRECOG, \r
+ message ("Unrecognized (possibly system) identifier: %q", \r
+ uentry_getName (ce)), \r
+ g_currentloc);\r
+ }\r
+ \r
+ return ce;\r
+ }\r
+ \r
+ return (usymtab_lookup (cn));\r
+}\r
+\r
+/*\r
+** like, coerceId, but doesn't supercede for iters\r
+*/\r
+\r
+/*@observer@*/ uentry coerceIterId (cstring cn)\r
+{\r
+ if (!(usymtab_exists (cn)))\r
+ {\r
+ return uentry_undefined;\r
+ }\r
+ \r
+ return (usymtab_lookup (cn));\r
+}\r
+\r
+/*@observer@*/ cstring LastIdentifier ()\r
+{\r
+ return (lastidprocessed);\r
+}\r
+\r
+static int processIdentifier (cstring id)\r
+{\r
+ uentry le;\r
+\r
+ if (context_getFlag (FLG_GRAMMAR))\r
+ {\r
+ lldiagmsg (message ("Process identifier: %s", id));\r
+ }\r
+\r
+ context_clearJustPopped ();\r
+ lastidprocessed = id; \r
+\r
+ if (context_inFunctionHeader ())\r
+ {\r
+ int tok = commentMarkerToken (id);\r
+ DPRINTF (("in function decl..."));\r
+\r
+ if (tok != BADTOK)\r
+ {\r
+ return tok;\r
+ }\r
+ else \r
+ {\r
+ tok = tokenMacroCode (id);\r
+\r
+ if (tok != BADTOK)\r
+ {\r
+ return tok;\r
+ }\r
+ else \r
+ {\r
+ annotationInfo ainfo;\r
+\r
+ if (expectingMetaStateName) \r
+ {\r
+ metaStateInfo msinfo = context_lookupMetaStateInfo (id);\r
+\r
+ if (metaStateInfo_isDefined (msinfo))\r
+ {\r
+ yylval.msinfo = msinfo;\r
+ return METASTATE_NAME;\r
+ }\r
+ else\r
+ {\r
+ DPRINTF (("Not meta state name: %s", cstring_toCharsSafe (id)));\r
+ }\r
+ }\r
+ \r
+ ainfo = context_lookupAnnotation (id);\r
+ \r
+ if (annotationInfo_isDefined (ainfo)) \r
+ {\r
+ DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));\r
+ /*@i324@*/ yylval.annotation = ainfo;\r
+ return CANNOTATION;\r
+ }\r
+ else\r
+ {\r
+ DPRINTF (("Not annotation: %s", id));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Consider handling: Defined by C99 as static const char __func__[] */\r
+\r
+ if (context_getFlag (FLG_GNUEXTENSIONS))\r
+ {\r
+ int tok = BADTOK;\r
+ \r
+ if (cstring_equalLit (id, "__stdcall")\r
+ || cstring_equalLit (id, "__cdecl")\r
+ || cstring_equalLit (id, "__extension__"))\r
+ {\r
+ return BADTOK;\r
+ }\r
+ else if (cstring_equalLit (id, "__volatile__"))\r
+ {\r
+ tok = QVOLATILE;\r
+ }\r
+ else if (cstring_equalLit (id, "__signed"))\r
+ {\r
+ tok = QSIGNED;\r
+ }\r
+ else if (cstring_equalLit (id, "__unsigned"))\r
+ {\r
+ tok = QUNSIGNED;\r
+ }\r
+ else if (cstring_equalLit (id, "__const__"))\r
+ {\r
+ tok = QCONST;\r
+ }\r
+ else if (cstring_equalLit (id, "__alignof__")) \r
+ {\r
+ tok = CALIGNOF; /* alignof is parsed like sizeof */\r
+ }\r
+ else if (cstring_equalLit (id, "__FUNCTION__")\r
+ || cstring_equalLit (id, "__PRETTY_FUNCTION__")) \r
+ {\r
+ /* These tokens hold the name of the current function as strings */\r
+ yylval.expr = exprNode_stringLiteral (id, fileloc_copy (g_currentloc));\r
+ tokLength = 0;\r
+ lastWasString = TRUE;\r
+ tok = CCONSTANT;\r
+ return tok;\r
+ }\r
+ else if (cstring_equalLit (id, "__attribute__")\r
+ || cstring_equalLit (id, "__asm__")\r
+ || cstring_equalLit (id, "_asm")\r
+ || cstring_equalLit (id, "__asm")\r
+ || cstring_equalLit (id, "__declspec"))\r
+ {\r
+ int depth = 0;\r
+ bool useparens = FALSE;\r
+ bool usebraces = FALSE;\r
+ bool inquote = FALSE;\r
+ bool inescape = FALSE;\r
+ int ic;\r
+\r
+ while ((ic = input ()) != EOF)\r
+ {\r
+ \r
+ if (inescape)\r
+ {\r
+ inescape = FALSE;\r
+ }\r
+ else if (ic == '\\')\r
+ {\r
+ inescape = TRUE;\r
+ }\r
+ else if (ic == '\"')\r
+ {\r
+ inquote = !inquote;\r
+ }\r
+ else if (!inquote)\r
+ {\r
+ if (ic == '(')\r
+ {\r
+ if (!useparens)\r
+ {\r
+ if (!usebraces)\r
+ {\r
+ useparens = TRUE;\r
+ }\r
+ }\r
+\r
+ if (useparens)\r
+ {\r
+ depth++;\r
+ }\r
+ }\r
+ else if (ic == '{')\r
+ {\r
+ if (!usebraces)\r
+ {\r
+ if (!useparens)\r
+ {\r
+ usebraces = TRUE;\r
+ }\r
+ }\r
+\r
+ if (usebraces)\r
+ {\r
+ depth++;\r
+ }\r
+ }\r
+ else if (ic == ')' && useparens)\r
+ {\r
+ depth--;\r
+ if (depth == 0) break;\r
+ }\r
+ else if (ic == '}' && usebraces)\r
+ {\r
+ depth--;\r
+ if (depth == 0) break;\r
+ }\r
+ else if (ic == '}' \r
+ && !usebraces && !useparens\r
+ && cstring_equalLit (id, "__asm"))\r
+ {\r
+ /*\r
+ ** We need this because some MS VC++ include files\r
+ ** have __asm mov ... }\r
+ ** Its a kludge, but otherwise would need to parse\r
+ ** the asm code!\r
+ */ \r
+ return TRBRACE;\r
+ }\r
+ }\r
+\r
+ if (ic == '\n')\r
+ {\r
+ context_incLineno ();\r
+\r
+ if (cstring_equalLit (id, "__asm")\r
+ && !useparens && !usebraces)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ llassert ((useparens && ic == ')')\r
+ || (usebraces && ic == '}')\r
+ || (!useparens && !usebraces));\r
+\r
+ return BADTOK;\r
+ }\r
+ else if (cstring_equalLit (id, "inline")\r
+ || cstring_equalLit (id, "__inline")\r
+ || cstring_equalLit (id, "_inline")\r
+ || cstring_equalLit (id, "__inline__"))\r
+ {\r
+ tok = QINLINE;\r
+ }\r
+ \r
+ if (tok != BADTOK)\r
+ {\r
+ RETURN_TOK (tok);\r
+ }\r
+ }\r
+\r
+ le = usymtab_lookupSafe (id);\r
+\r
+ /*@-dependenttrans@*/\r
+ \r
+ if (uentry_isIter (le))\r
+ {\r
+ /*@i32@*/ yylval.entry = le;\r
+ return (ITER_NAME);\r
+ }\r
+ else if (uentry_isEndIter (le))\r
+ {\r
+ /*@i32@*/ yylval.entry = le;\r
+ return (ITER_ENDNAME);\r
+ }\r
+ else if (uentry_isUndefined (le))\r
+ {\r
+ yylval.cname = id;\r
+\r
+ /* avoid parse errors for certain system built ins */\r
+\r
+ if (g_expectingTypeName && (cstring_firstChar (id) == '_')\r
+ && (cstring_secondChar (id) == '_'))\r
+ {\r
+ return (TYPE_NAME_OR_ID);\r
+ }\r
+\r
+ return (NEW_IDENTIFIER);\r
+ }\r
+ else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))\r
+ {\r
+ if (uentry_isDatatype (le))\r
+ {\r
+ yylval.cname = id;\r
+ return (NEW_IDENTIFIER);\r
+ }\r
+ else\r
+ {\r
+ /*@i32@*/ yylval.entry = le; \r
+ return (IDENTIFIER); \r
+ }\r
+ }\r
+ else if (uentry_isDatatype (le))\r
+ {\r
+ if (!g_expectingTypeName)\r
+ {\r
+ yylval.cname = id;\r
+\r
+ return (NEW_IDENTIFIER);\r
+ }\r
+ else\r
+ {\r
+ yylval.ctyp = uentry_getAbstractType (le);\r
+ \r
+ uentry_setUsed (le, g_currentloc);\r
+ return (TYPE_NAME);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*@i32@*/ yylval.entry = le; \r
+ return (IDENTIFIER); \r
+ }\r
+\r
+ /*@=dependenttrans@*/\r
+}\r
+\r
+static bool processHashIdentifier (/*@only@*/ cstring id)\r
+{\r
+ if (context_inMacro () || context_inIterDef () ||\r
+ context_inIterEnd ())\r
+ {\r
+ uentry le;\r
+ \r
+ context_clearJustPopped ();\r
+\r
+ lastidprocessed = id; \r
+ le = usymtab_lookupSafe (id);\r
+\r
+ if (uentry_isParam (le) || uentry_isRefParam (le))\r
+ {\r
+ return TRUE;\r
+ }\r
+ else\r
+ {\r
+ return FALSE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ cstring_free (id);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+\r
+static /*@only@*/ exprNode processString ()\r
+{\r
+ exprNode res;\r
+ fileloc loc;\r
+ char *nl = strchr (yytext, '\n');\r
+ cstring ns = cstring_fromCharsNew (yytext);\r
+\r
+ if (nl == NULL)\r
+ {\r
+ loc = fileloc_copy (g_currentloc);\r
+ addColumn (cstring_length (ns));\r
+ }\r
+ else\r
+ {\r
+ char *lastnl = nl;\r
+\r
+ loc = fileloc_copy (g_currentloc);\r
+\r
+ context_incLineno ();\r
+ \r
+ while ((nl = strchr ((nl + 1), '\n')) != NULL)\r
+ {\r
+ context_incLineno ();\r
+ lastnl = nl;\r
+ }\r
+ }\r
+\r
+ \r
+ res = exprNode_stringLiteral (ns, loc);\r
+ return (res);\r
+}\r
+\r
+static \r
+char processChar ()\r
+{\r
+ char fchar;\r
+ char next;\r
+\r
+ llassert (*yytext != '\0');\r
+ fchar = *(yytext + 1);\r
+ if (fchar != '\\') return fchar;\r
+ \r
+ next = *(yytext + 2);\r
+ \r
+ switch (next)\r
+ {\r
+ case 'n': return '\n';\r
+ case 't': return '\t';\r
+ case '\"': return '\"';\r
+ case '\'': return '\'';\r
+ case '\\': return '\\';\r
+ default: return '\0';\r
+ }\r
+}\r
+\r
+static\r
+double processFloat ()\r
+{\r
+ double ret = atof (yytext);\r
+\r
+ return (ret);\r
+}\r
+\r
+static\r
+long processHex ()\r
+{\r
+ int index = 2;\r
+ long val = 0;\r
+\r
+ llassert (yytext[0] == '0'\r
+ && (yytext[1] == 'X' || yytext[1] == 'x'));\r
+\r
+ while (yytext[index] != '\0') {\r
+ int tval;\r
+ char c = yytext[index];\r
+\r
+ if (c >= '0' && c <= '9') {\r
+ tval = (int) c - (int) '0';\r
+ } else if (c >= 'A' && c <= 'F') {\r
+ tval = (int) c - (int) 'A' + 10;\r
+ } else if (c >= 'a' && c <= 'f') {\r
+ tval = (int) c - (int) 'a' + 10;\r
+ } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {\r
+ index++;\r
+ while (yytext[index] != '\0') {\r
+ if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {\r
+ ;\r
+ } else {\r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Invalid character (%c) following specifier in hex constant: %s",\r
+ c, cstring_fromChars (yytext)),\r
+ g_currentloc);\r
+ }\r
+ index++;\r
+ }\r
+\r
+ break;\r
+ } else {\r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Invalid character (%c) in hex constant: %s",\r
+ c, cstring_fromChars (yytext)),\r
+ g_currentloc);\r
+ break;\r
+ }\r
+\r
+ val = (val * 16) + tval;\r
+ index++;\r
+ }\r
+\r
+ DPRINTF (("Hex constant: %s = %ld", yytext, val));\r
+ return val;\r
+}\r
+\r
+static\r
+long processOctal ()\r
+{\r
+ int index = 1;\r
+ long val = 0;\r
+\r
+ llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');\r
+ \r
+ while (yytext[index] != '\0') {\r
+ int tval;\r
+ char c = yytext[index];\r
+ \r
+ if (c >= '0' && c <= '7') {\r
+ tval = (int) c - (int) '0';\r
+ } else {\r
+ voptgenerror\r
+ (FLG_SYNTAX, \r
+ message ("Invalid character (%c) in octal constant: %s",\r
+ c, cstring_fromChars (yytext)),\r
+ g_currentloc);\r
+ break;\r
+ }\r
+\r
+ val = (val * 8) + tval;\r
+ index++;\r
+ }\r
+\r
+ DPRINTF (("Octal constant: %s = %ld", yytext, val));\r
+ return val;\r
+}\r
+\r
+static\r
+long processDec ()\r
+{\r
+ return (atol (yytext));\r
+}\r
+\r
+static int\r
+processSpec (int tok)\r
+{\r
+ size_t length = strlen (yytext);\r
+ \r
+ if (inSpecPart)\r
+ {\r
+ setTokLengthT (length);\r
+ RETURN_TOK (tok);\r
+ }\r
+ else\r
+ {\r
+ \r
+ context_saveLocation ();\r
+ setTokLengthT (length);\r
+ return (processIdentifier (makeIdentifier (yytext)));\r
+ }\r
+}\r
+\r
+void cscanner_expectingMetaStateName ()\r
+{\r
+ llassert (!expectingMetaStateName);\r
+ llassert (context_inFunctionHeader ());\r
+ expectingMetaStateName = TRUE;\r
+}\r
+\r
+void cscanner_clearExpectingMetaStateName ()\r
+{\r
+ llassert (expectingMetaStateName);\r
+ expectingMetaStateName = FALSE;\r
+}\r