X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/885824d34f6f6626fde2fb041801408cbaf1f6f1..7bf960677344d11a101697c76672a0be4b3759f2:/src/cscanner.l diff --git a/src/cscanner.l b/src/cscanner.l index 0eb50f2..0038eaa 100644 --- a/src/cscanner.l +++ b/src/cscanner.l @@ -62,13 +62,8 @@ ULSuffix ({U}{L}|{L}{U}) # include "lclintMacros.nf" # include "basic.h" -# ifdef SANITIZER -# include "sgrammar.h" -# include "sgrammar_tokens.h" -# else # include "cgrammar.h" # include "cgrammar_tokens.h" -# endif # include "fileIdList.h" # include "portab.h" @@ -119,6 +114,8 @@ 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); @@ -185,6 +182,9 @@ static void setTokLengthT (size_t len) } # include "flex.head" + +/*@-unrecog@*/ /*@i5343@*/ + %} %% @@ -199,7 +199,8 @@ static void setTokLengthT (size_t len) { if (lastWasString) { - ; + /* was nothing! */ /*@i32@*/ + RETURN_STRING (cstring_makeLiteral ("\"\"")); } else { @@ -270,6 +271,7 @@ static void setTokLengthT (size_t len) "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)); } @@ -306,6 +308,12 @@ static void setTokLengthT (size_t len) "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))); @@ -429,6 +437,10 @@ static void setTokLengthT (size_t len) "|" { setTokLength (1); RETURN_TOK (TBAR); } "?" { setTokLength (1); RETURN_TOK (TQUEST); } + +"/\\" { setTokLength (1); RETURN_TOK (TCAND); } + + [ \t\v\f] { incColumn (); } \n { context_incLineno (); if (continueLine) @@ -500,6 +512,7 @@ static void setTokLengthT (size_t len) } } "@.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))); } @@ -521,9 +534,15 @@ static void setTokLengthT (size_t len) int tok; incColumn (); incColumn (); tok = handleLlSpecial (); + if (tok != BADTOK) { - RETURN_TOK (tok); + if (tok == CANNOTATION) { + return (tok); + } else { + /* Beware - this bashes yylval! */ + RETURN_TOK (tok); + } } } "%}" { /* AFTER_COMMENT_MARKER */ @@ -532,11 +551,15 @@ static void setTokLengthT (size_t len) RETURN_TOK (QENDMACRO); } "\\" { incColumn (); continueLine = TRUE; } . { incColumn (); - voptgenerror - (FLG_SYNTAX, - message ("Invalid character (ascii: %d), skipping character", - (int)(*yytext)), - g_currentloc); + if ((int) *yytext == 13 ) { + ; + } else { + voptgenerror + (FLG_SYNTAX, + message ("Invalid character (ascii: %d), skipping character", + (int)(*yytext)), + g_currentloc); + } } %% @@ -555,6 +578,7 @@ struct skeyword s_parsetable[] = { { "modifies", QMODIFIES } , { "globals", QGLOBALS } , { "alt", QALT } , + { "warn", QWARN } , { "constant", QCONSTANT } , { "function", QFUNCTION } , { "iter", QITER } , @@ -565,6 +589,11 @@ struct skeyword s_parsetable[] = { { "releases", QRELEASES } , { "pre", QPRECLAUSE } , { "post", QPOSTCLAUSE } , + { "setBufferSize", QSETBUFFERSIZE}, + { "setStringLength", QSETSTRINGLENGTH}, + { "testinRange", QTESTINRANGE}, + { "requires", QPRECLAUSE } , + { "ensures", QPOSTCLAUSE } , { NULL, BADTOK } } ; @@ -607,6 +636,11 @@ struct skeyword s_keytable[] = { { "killref", QKILLREF } , { "null", QNULL } , { "relnull", QRELNULL } , + { "nullterminated", QNULLTERMINATED }, + { "setBufferSize", QSETBUFFERSIZE }, + { "testInRange", QTESTINRANGE}, + { "MaxSet", QMAXSET}, + { "MaxRead", QMAXREAD}, { "reldef", QRELDEF } , { "observer", QOBSERVER } , { "exits", QEXITS } , @@ -647,6 +681,7 @@ static bool isArtificial (cstring s) { return (cstring_equalLit (s, "modifies") || cstring_equalLit (s, "globals") + || cstring_equalLit (s, "warn") || cstring_equalLit (s, "alt")); } @@ -672,7 +707,7 @@ void swallowMacro (void) } else { - checkUngetc (i, yyin); + reader_checkUngetc (i, yyin); return; } } @@ -680,7 +715,7 @@ void swallowMacro (void) if (i != EOF) { - checkUngetc (i, yyin); + reader_checkUngetc (i, yyin); } } @@ -690,6 +725,8 @@ static int commentMarkerToken (cstring s) 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; @@ -718,7 +755,7 @@ static int tokenMacroCode (cstring s) "This is interpreted by " "LCLint in the same way as most Unix lints, but it is " "preferable to replace it with the /*@fallthrough@*/ " - "stylized comment"), + "semantic comment"), g_currentloc); return QFALLTHROUGH; } @@ -731,7 +768,7 @@ static int tokenMacroCode (cstring s) "This is interpreted by " "LCLint in the same way as most Unix lints, but it is " "preferable to replace it with the /*@fallthrough@*/ " - "stylized comment"), + "semantic comment"), g_currentloc); return QFALLTHROUGH; } @@ -744,14 +781,14 @@ static int tokenMacroCode (cstring s) "This is interpreted by " "LCLint in the same way as most Unix lints, but it is " "preferable to replace it with the /*@notreached@*/ " - "stylized comment."), + "semantic comment."), g_currentloc); return QNOTREACHED; } else if (s_keytable[i].token == QPRINTFLIKE) { - setSpecialFunction (QU_PRINTFLIKE); + setSpecialFunction (qual_createPrintfLike ()); return SKIPTOK; } else if (s_keytable[i].token == QLINTPRINTFLIKE) @@ -766,17 +803,17 @@ static int tokenMacroCode (cstring s) "/*@scanflike@*/ or /*@messagelike@*/."), g_currentloc); - setSpecialFunction (QU_PRINTFLIKE); + setSpecialFunction (qual_createPrintfLike ()); return SKIPTOK; } else if (s_keytable[i].token == QSCANFLIKE) { - setSpecialFunction (QU_SCANFLIKE); + setSpecialFunction (qual_createScanfLike ()); return SKIPTOK; } else if (s_keytable[i].token == QMESSAGELIKE) { - setSpecialFunction (QU_MESSAGELIKE); + setSpecialFunction (qual_createMessageLike ()); return SKIPTOK; } else if (s_keytable[i].token == QARGSUSED) @@ -909,6 +946,7 @@ static char macro_nextChar () } else /* if (c == '@') */ { + llassert (FALSE); /*@i23@*/ if (handleLlSpecial () != BADTOK) { llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax"); @@ -978,7 +1016,7 @@ static char macro_nextChar () } /* -** keeps stylized comments +** keeps semantic comments */ static char macro_nextCharC () @@ -1120,7 +1158,6 @@ static void handleMacro () if (macrocode == BADTOK && !isArtificial (mac)) { - DPRINTF (("Add macro: %s", mac)); context_addMacroCache (mac); } else @@ -1202,7 +1239,6 @@ static bool processMacro (void) e2 = usymtab_lookupExpose (fname); ct = uentry_getType (e2); - if (uentry_isCodeDefined (e2) && fileloc_isUser (uentry_whereDefined (e2))) { @@ -1275,7 +1311,7 @@ static bool processMacro (void) uentry_showWhereSpecified (e2); uentry_setType (e2, ctype_unknown); - uentry_makeVarFunction (e2); + uentry_makeConstantFunction (e2); uentry_setDefined (e2, g_currentloc); uentry_setFunctionDefined (e2, g_currentloc); context_enterUnknownMacro (e2); @@ -1486,6 +1522,7 @@ static bool processMacro (void) && !uentry_isElipsisMarker (uentryList_getN (specparams, paramno))) { + fileloc sloc = context_getSaveLocation (); uentry decl = uentryList_getN (specparams, paramno); sRef sr; @@ -1493,7 +1530,7 @@ static bool processMacro (void) uentry_setParam (param); - sr = sRef_makeParam (paramno, uentry_getType (param)); + sr = sRef_makeParam (paramno, uentry_getType (param), stateInfo_makeLoc (sloc)); if (sRef_getNullState (sr) == NS_ABSNULL) { @@ -1510,12 +1547,12 @@ static bool processMacro (void) } else { - sRef_setNullState (sr, NS_UNKNOWN, g_currentloc); + sRef_setNullState (sr, NS_UNKNOWN, sloc); } } uentry_setSref (param, sr); - uentry_setDeclaredForceOnly (param, context_getSaveLocation ()); + uentry_setDeclaredForceOnly (param, sloc); skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno)); } @@ -1524,11 +1561,11 @@ static bool processMacro (void) fileloc sloc = context_getSaveLocation (); param = uentry_makeVariableSrefParam - (paramname, ctype_unknown, sRef_makeParam (paramno, ctype_unknown)); + (paramname, ctype_unknown, fileloc_copy (sloc), + sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (sloc))); cstring_free (paramname); sRef_setPosNull (uentry_getSref (param), sloc); - uentry_setDeclaredForce (param, sloc); skipparam = FALSE; @@ -1712,9 +1749,10 @@ static bool handleSpecial (char *yyt) || (sscanf (ol, " %d \"", &lineno) == 1)) { char *tmp = ol; - char *fname; + cstring fname; fileId fid; + /*@access cstring@*/ while (*tmp != '\"' && *tmp != '\0') { tmp++; @@ -1723,6 +1761,7 @@ static bool handleSpecial (char *yyt) llassert (*tmp == '\"'); tmp++; + fname = tmp; while (*tmp != '\"' && *tmp != '\0') @@ -1734,8 +1773,6 @@ static bool handleSpecial (char *yyt) *tmp = '\0'; - DPRINTF (("fname: %s", fname)); - # if defined(OS2) || defined(MSDOS) || defined(WIN32) /* @@ -1753,15 +1790,11 @@ static bool handleSpecial (char *yyt) ** Skip past the drive marker. */ - DPRINTF (("stmp: %s / %s", stmp, fname)); - if (strchr (stmp, ':') != NULL) { stmp = strchr (stmp, ':') + 1; } - DPRINTF (("stmp: %s / %s", stmp, fname)); - while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL ) { if (*(stmp+1) == CONNECTCHAR) @@ -1770,41 +1803,38 @@ static bool handleSpecial (char *yyt) } stmp++; - DPRINTF (("stmp: %s / %s", stmp, fname)); } - DPRINTF (("Now: base = %s", fname)); - - fid = fileTable_lookupBase (context_fileTable (), - cstring_fromChars (fname)); + fid = fileTable_lookupBase (context_fileTable (), fname); if (!(fileId_isValid (fid))) { fname = removePreDirs (fname); - fid = fileTable_lookupBase (context_fileTable (), - cstring_fromChars (fname)); + fid = fileTable_lookupBase (context_fileTable (), fname); } } # else /* !defined(OS2) && !defined(MSDOS) */ fname = removePreDirs (fname); - fid = fileTable_lookupBase (context_fileTable (), - cstring_fromChars (fname)); + fid = fileTable_lookupBase (context_fileTable (), fname); # endif /* !defined(OS2) && !defined(MSDOS) */ if (!(fileId_isValid (fid))) { - if (isHeaderFile (cstring_fromChars (fname))) + if (context_inXHFile ()) { - fid = fileTable_addHeaderFile (context_fileTable (), - cstring_fromChars (fname)); + fid = fileTable_addXHFile (context_fileTable (), fname); + } + else if (isHeaderFile (fname)) + { + fid = fileTable_addHeaderFile (context_fileTable (), fname); } else { - fid = fileTable_addFile (context_fileTable (), - cstring_fromChars (fname)); + fid = fileTable_addFile (context_fileTable (), fname); } } setFileLine (fid, lineno); + /*@noaccess cstring@*/ } else if ((sscanf (ol, "line %d", &lineno) == 1) || (sscanf (ol, " %d", &lineno) == 1)) @@ -1848,6 +1878,10 @@ static int handleLlSpecial () 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)) { @@ -1856,6 +1890,7 @@ static int handleLlSpecial () charsread++; } + DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc))); os = s; if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0]) @@ -1863,19 +1898,16 @@ static int handleLlSpecial () ic = ninput (); llassert (ic == AFTER_COMMENT_MARKER[1]); - - if (isProcessingGlobMods () && (*s == '\0')) + if (*s == '\0') { sfree (os); + fileloc_free (loc); return QNOMODS; /* special token no modifications token */ } - else - { - ; - } } + DPRINTF (("Coment marker: %s", os)); tok = commentMarkerToken (cstring_fromChars (os)); if (tok != BADTOK) @@ -1883,15 +1915,16 @@ static int handleLlSpecial () 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++; @@ -1905,6 +1938,8 @@ static int handleLlSpecial () } } + DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc))); + if (ic == AFTER_COMMENT_MARKER[0]) { int nc = ninput (); @@ -1912,7 +1947,6 @@ static int handleLlSpecial () charsread++; } - os = s; while (*s == ' ' || *s == '\t' || *s == '\n') @@ -1945,7 +1979,7 @@ static int handleLlSpecial () { cstring flagname = thisflag; flagcode fflag = identifyFlag (flagname); - + if (flagcode_isSkip (fflag)) { ; @@ -1959,7 +1993,7 @@ static int handleLlSpecial () llerror (FLG_BADFLAG, message - ("Stylized comment attempts to restore flag %s. " + ("Semantic comment attempts to restore flag %s. " "A mode flag cannot be restored.", flagname)); } @@ -1970,35 +2004,38 @@ static int handleLlSpecial () } else { - llerror - (FLG_BADFLAG, - message ("Unrecognized option in stylized comment: %s", - flagname)); + voptgenerror + (FLG_UNRECOGFLAGCOMMENTS, + message ("Unrecognized option in semantic comment: %s", + flagname), + g_currentloc); } } else if (flagcode_isGlobalFlag (fflag)) { - llerror + voptgenerror (FLG_BADFLAG, message - ("Stylized comment attempts to set global flag %s. " + ("Semantic comment attempts to set global flag %s. " "A global flag cannot be set locally.", - flagname)); + flagname), + g_currentloc); } else { context_fileSetFlag (fflag, set); - + if (flagcode_hasArgument (fflag)) { if (ynm_isMaybe (set)) { - llerror + voptgenerror (FLG_BADFLAG, message - ("Stylized comment attempts to restore flag %s. " + ("Semantic comment attempts to restore flag %s. " "A flag for setting a value cannot be restored.", - flagname)); + flagname), + g_currentloc); } else { /* cut-and-pastied from llmain...blecch */ @@ -2028,13 +2065,13 @@ static int handleLlSpecial () } sfree (orest); - + if (cstring_isUndefined (extra)) { llerror (FLG_BADFLAG, message - ("Flag %s (in stylized comment) must be followed by an argument", + ("Flag %s (in semantic comment) must be followed by an argument", flagcode_unparse (fflag))); } else @@ -2060,7 +2097,8 @@ static int handleLlSpecial () } else { - } + ; + } *s = c; while ((c == ' ') || (c == '\t') || (c == '\n')) @@ -2071,7 +2109,8 @@ static int handleLlSpecial () if (context_inHeader () && !isArtificial (cstring_fromChars (os))) { - context_addComment (cstring_fromCharsNew (os)); + DPRINTF (("Here adding comment: %s", os)); + context_addComment (cstring_fromCharsNew (os)); } else { @@ -2083,6 +2122,7 @@ static int handleLlSpecial () char *t = s; int macrocode; char tchar = '\0'; + annotationInfo ainfo; while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n') { @@ -2102,10 +2142,10 @@ static int handleLlSpecial () if (macrocode != BADTOK) { tokLength = mstring_length (t); - sfree (t); sfree (os); + fileloc_free (loc); if (macrocode == SKIPTOK) { @@ -2115,6 +2155,18 @@ static int handleLlSpecial () 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') @@ -2126,6 +2178,7 @@ static int handleLlSpecial () && macrocode != SKIPTOK && !isArtificial (cstring_fromChars (os))) { + DPRINTF (("Add comment: %s", os)); context_addComment (cstring_fromCharsNew (os)); } else @@ -2220,25 +2273,42 @@ static int handleLlSpecial () *s = '\0'; - + DPRINTF (("Access %s", tname)); + if (!context_getFlag (FLG_NOCOMMENTS) && !context_getFlag (FLG_NOACCESS)) { if (usymtab_existsType (tname)) { - usymId uid = usymtab_getTypeId (tname); + typeId uid = usymtab_getTypeId (tname); + uentry ue = usymtab_getTypeEntry (uid); - context_addFileAccessType (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))) { - llmsg - (message - ("%q: Unrecognized type %s used in access comment", - fileloc_unparse (g_currentloc), tname)); + voptgenerror + (FLG_COMMENTERROR, + message + ("Unrecognized type %s used in access comment", + tname), + g_currentloc); } } } @@ -2290,6 +2360,7 @@ static int handleLlSpecial () if (context_couldHaveAccess (tuid)) { + DPRINTF (("Removing access: %s", tname)); context_removeFileAccessType (tuid); } else @@ -2301,17 +2372,21 @@ static int handleLlSpecial () if (uentry_isAbstractDatatype (ue)) { - llmsg - (message - ("%q: Non-accessible abstract type %s used in noaccess comment", - fileloc_unparse (g_currentloc), tname)); + voptgenerror + (FLG_COMMENTERROR, + message + ("Non-accessible abstract type %s used in noaccess comment", + tname), + g_currentloc); } else { - llmsg - (message - ("%q: Non-abstract type %s used in noaccess comment", - fileloc_unparse (g_currentloc), tname)); + voptgenerror + (FLG_COMMENTERROR, + message + ("Non-abstract type %s used in noaccess comment", + tname), + g_currentloc); } } } @@ -2321,10 +2396,12 @@ static int handleLlSpecial () if (!(context_inSuppressRegion () || context_inSuppressZone (g_currentloc))) { - llmsg - (message - ("%q: Unrecognized type %s used in noaccess comment", - fileloc_unparse (g_currentloc), tname)); + voptgenerror + (FLG_COMMENTERROR, + message + ("Unrecognized type %s used in noaccess comment", + tname), + g_currentloc); } } } @@ -2342,18 +2419,16 @@ static int handleLlSpecial () } else { - setTokLength (- (2 + charsread)); - voptgenerror (FLG_UNRECOGCOMMENTS, - message ("Stylized comment unrecognized: %s", - cstring_fromChars (os)), - g_currentloc); + message ("Semantic comment unrecognized: %s", + cstring_fromChars (os)), loc); } sfree (t); } - sfree (os); + sfree (os); + fileloc_free (loc); return BADTOK; } @@ -2421,14 +2496,18 @@ static int processIdentifier (cstring id) { uentry le; - DPRINTF (("Process identifier: %s", id)); + if (context_getFlag (FLG_GRAMMAR)) + { + lldiagmsg (message ("Process identifier: %s", id)); + } context_clearJustPopped (); lastidprocessed = id; - if (context_inFunctionDecl ()) + if (context_inFunctionHeader ()) { int tok = commentMarkerToken (id); + DPRINTF (("in function decl...")); if (tok != BADTOK) { @@ -2442,6 +2521,38 @@ static int processIdentifier (cstring id) { 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)); + } + } } } @@ -2609,12 +2720,12 @@ static int processIdentifier (cstring id) if (uentry_isIter (le)) { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (ITER_NAME); } else if (uentry_isEndIter (le)) { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (ITER_ENDNAME); } else if (uentry_isUndefined (le)) @@ -2640,7 +2751,7 @@ static int processIdentifier (cstring id) } else { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (IDENTIFIER); } } @@ -2662,7 +2773,7 @@ static int processIdentifier (cstring id) } else { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (IDENTIFIER); } @@ -2780,6 +2891,22 @@ long processHex () 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, @@ -2853,3 +2980,16 @@ processSpec (int tok) return (processIdentifier (makeIdentifier (yytext))); } } + +void cscanner_expectingMetaStateName () +{ + llassert (!expectingMetaStateName); + llassert (context_inFunctionHeader ()); + expectingMetaStateName = TRUE; +} + +void cscanner_clearExpectingMetaStateName () +{ + llassert (expectingMetaStateName); + expectingMetaStateName = FALSE; +}