X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/11ed4f45e321c24d9340dc277c54e1d2c9cd0046..b072092f32623dab70e6ffe1613740542ea66748:/src/cscanner.l diff --git a/src/cscanner.l b/src/cscanner.l index 1a7a509..66405db 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)); } @@ -307,6 +309,10 @@ static void setTokLengthT (size_t len) "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 (); @@ -431,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) @@ -502,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))); } @@ -523,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 */ @@ -534,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); + } } %% @@ -557,6 +578,7 @@ struct skeyword s_parsetable[] = { { "modifies", QMODIFIES } , { "globals", QGLOBALS } , { "alt", QALT } , + { "warn", QWARN } , { "constant", QCONSTANT } , { "function", QFUNCTION } , { "iter", QITER } , @@ -567,9 +589,12 @@ struct skeyword s_parsetable[] = { { "releases", QRELEASES } , { "pre", QPRECLAUSE } , { "post", QPOSTCLAUSE } , - {"setBufferSize", QSETBUFFERSIZE}, - {"setStringLength", QSETSTRINGLENGTH}, - { NULL, BADTOK } + { "setBufferSize", QSETBUFFERSIZE}, + { "setStringLength", QSETSTRINGLENGTH}, + { "testinRange", QTESTINRANGE}, + { "requires", QPRECLAUSE } , + { "ensures", QPOSTCLAUSE } , + { NULL, BADTOK } } ; /* @@ -613,6 +638,9 @@ struct skeyword s_keytable[] = { { "relnull", QRELNULL } , { "nullterminated", QNULLTERMINATED }, { "setBufferSize", QSETBUFFERSIZE }, + { "testInRange", QTESTINRANGE}, + { "MaxSet", QMAXSET}, + { "MaxRead", QMAXREAD}, { "reldef", QRELDEF } , { "observer", QOBSERVER } , { "exits", QEXITS } , @@ -653,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")); } @@ -678,7 +707,7 @@ void swallowMacro (void) } else { - checkUngetc (i, yyin); + reader_checkUngetc (i, yyin); return; } } @@ -686,7 +715,7 @@ void swallowMacro (void) if (i != EOF) { - checkUngetc (i, yyin); + reader_checkUngetc (i, yyin); } } @@ -696,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; @@ -724,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; } @@ -737,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; } @@ -750,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) @@ -772,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) @@ -915,6 +946,7 @@ static char macro_nextChar () } else /* if (c == '@') */ { + llassert (FALSE); /*@i23@*/ if (handleLlSpecial () != BADTOK) { llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax"); @@ -984,7 +1016,7 @@ static char macro_nextChar () } /* -** keeps stylized comments +** keeps semantic comments */ static char macro_nextCharC () @@ -1126,7 +1158,6 @@ static void handleMacro () if (macrocode == BADTOK && !isArtificial (mac)) { - DPRINTF (("Add macro: %s", mac)); context_addMacroCache (mac); } else @@ -1281,7 +1312,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); @@ -1718,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++; @@ -1729,6 +1761,7 @@ static bool handleSpecial (char *yyt) llassert (*tmp == '\"'); tmp++; + fname = tmp; while (*tmp != '\"' && *tmp != '\0') @@ -1740,8 +1773,6 @@ static bool handleSpecial (char *yyt) *tmp = '\0'; - DPRINTF (("fname: %s", fname)); - # if defined(OS2) || defined(MSDOS) || defined(WIN32) /* @@ -1759,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) @@ -1776,41 +1803,34 @@ 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 (isHeaderFile (fname)) { - fid = fileTable_addHeaderFile (context_fileTable (), - cstring_fromChars (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)) @@ -1854,6 +1874,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)) { @@ -1862,6 +1886,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]) @@ -1869,19 +1894,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) @@ -1889,15 +1911,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++; @@ -1911,6 +1934,8 @@ static int handleLlSpecial () } } + DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc))); + if (ic == AFTER_COMMENT_MARKER[0]) { int nc = ninput (); @@ -1918,7 +1943,6 @@ static int handleLlSpecial () charsread++; } - os = s; while (*s == ' ' || *s == '\t' || *s == '\n') @@ -1951,7 +1975,7 @@ static int handleLlSpecial () { cstring flagname = thisflag; flagcode fflag = identifyFlag (flagname); - + if (flagcode_isSkip (fflag)) { ; @@ -1965,7 +1989,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)); } @@ -1976,35 +2000,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 */ @@ -2034,13 +2061,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 @@ -2066,7 +2093,8 @@ static int handleLlSpecial () } else { - } + ; + } *s = c; while ((c == ' ') || (c == '\t') || (c == '\n')) @@ -2077,7 +2105,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 { @@ -2089,6 +2118,7 @@ static int handleLlSpecial () char *t = s; int macrocode; char tchar = '\0'; + annotationInfo ainfo; while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n') { @@ -2108,10 +2138,10 @@ static int handleLlSpecial () if (macrocode != BADTOK) { tokLength = mstring_length (t); - sfree (t); sfree (os); + fileloc_free (loc); if (macrocode == SKIPTOK) { @@ -2121,6 +2151,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') @@ -2132,6 +2174,7 @@ static int handleLlSpecial () && macrocode != SKIPTOK && !isArtificial (cstring_fromChars (os))) { + DPRINTF (("Add comment: %s", os)); context_addComment (cstring_fromCharsNew (os)); } else @@ -2226,25 +2269,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); } } } @@ -2296,6 +2356,7 @@ static int handleLlSpecial () if (context_couldHaveAccess (tuid)) { + DPRINTF (("Removing access: %s", tname)); context_removeFileAccessType (tuid); } else @@ -2307,17 +2368,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); } } } @@ -2327,10 +2392,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); } } } @@ -2348,18 +2415,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; } @@ -2427,14 +2492,16 @@ static int processIdentifier (cstring id) { uentry le; - DPRINTF (("Process identifier: %s", id)); + DPRINTF (("Process identifier: %s / %s / %s", id, fileloc_unparse (g_currentloc), + bool_unparse (context_inFunctionHeader ()))); context_clearJustPopped (); lastidprocessed = id; - if (context_inFunctionDecl ()) + if (context_inFunctionHeader ()) { int tok = commentMarkerToken (id); + DPRINTF (("in function decl...")); if (tok != BADTOK) { @@ -2448,6 +2515,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)); + } + } } } @@ -2615,12 +2714,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)) @@ -2646,7 +2745,7 @@ static int processIdentifier (cstring id) } else { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (IDENTIFIER); } } @@ -2668,7 +2767,7 @@ static int processIdentifier (cstring id) } else { - yylval.entry = le; + /*@i32@*/ yylval.entry = le; return (IDENTIFIER); } @@ -2786,6 +2885,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, @@ -2859,3 +2974,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; +}