X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/5c2f3045ca9662b32e0369d10771eecf8dfe0231..288cbc5cbbbb68f1c95fd491c667d34e162f7863:/src/cscanner.l diff --git a/src/cscanner.l b/src/cscanner.l index eddfd1d..3e962cf 100644 --- a/src/cscanner.l +++ b/src/cscanner.l @@ -1,6 +1,6 @@ /*;-*-C-*-; ** Splint - annotation-assisted static program checker -** Copyright (C) 1994-2001 University of Virginia, +** Copyright (C) 1994-2002 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,8 +17,8 @@ ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ** MA 02111-1307, USA. ** -** For information on lclint: lclint-request@cs.virginia.edu -** To report a bug: lclint-bug@cs.virginia.edu +** For information on splint: splint@cs.virginia.edu +** To report a bug: splint-bug@cs.virginia.edu ** For more information: http://www.splint.org */ /* @@ -36,7 +36,7 @@ /* ** Modified by Mike Smith ** Corrected missing 'line' in scanf() calls in handleSpecial(). -** Without this, I get an error when LCLint hits a '#line' directive +** Without this, I get an error when Splint 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. @@ -64,14 +64,22 @@ IS (u|U|l|L)* ULSuffix ({U}{L}|{L}{U}) %{ -# include "lclintMacros.nf" +# include "splintMacros.nf" # if defined(OS2) && defined(__IBMC__) /* needed for isatty()... */ # include # else + +/* +** Win32 doesn't have unistd.h +*/ + +# ifndef WIN32 # include # endif +# endif + # include "basic.h" # include "cgrammar.h" @@ -95,7 +103,8 @@ static bool continueLine = FALSE; static int ninput (void); static char processChar (void); static double processFloat (void); -static /*@only@*/ exprNode processString (void); +static /*@only@*/ exprNode processString (void) ; +static /*@only@*/ exprNode processWideString (void) ; static long processDec (void); static long processHex (void); static long processOctal (void); @@ -272,7 +281,7 @@ static void setTokLengthT (size_t len) "static" { setTokLength (6); RETURN_TOK (QSTATIC); } \"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); } -L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); } +L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processWideString ()); } "out" { return (processSpec (QOUT)); } "in" { return (processSpec (QIN)); } "partial" { return (processSpec (QPARTIAL)); } @@ -287,6 +296,8 @@ L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); "isnull" { return (processSpec (QISNULL)); } "truenull" { return (processSpec (QTRUENULL)); } "falsenull" { return (processSpec (QFALSENULL)); } +"nullwhentrue" { return (processSpec (QTRUENULL)); } +"nullwhenfalse" { return (processSpec (QFALSENULL)); } "relnull" { return (processSpec (QRELNULL)); } "reldef" { return (processSpec (QRELDEF)); } "exposed" { return (processSpec (QEXPOSED)); } @@ -465,7 +476,7 @@ L'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext)); if (context_inMacro ()) { /* Don't use RETURN_TOK */ - yylval.tok = lltok_create (TENDMACRO, g_currentloc); + yylval.tok = lltok_create (TENDMACRO, fileloc_copy (g_currentloc)); /* !!! evans 2002-03-13 */ lastWasString = FALSE; return (TENDMACRO); } @@ -609,6 +620,7 @@ struct skeyword s_parsetable[] = { { "testinRange", QTESTINRANGE}, { "requires", QPRECLAUSE } , { "ensures", QPOSTCLAUSE } , + { "invariant", QINVARIANT} , { NULL, BADTOK } } ; @@ -631,6 +643,8 @@ struct skeyword s_keytable[] = { { "special", QSPECIAL } , { "truenull", QTRUENULL } , { "falsenull", QFALSENULL } , + { "nullwhentrue", QTRUENULL } , + { "falsewhennull", QFALSENULL } , { "keep", QKEEP } , { "kept", QKEPT } , { "notnull", QNOTNULL } , @@ -659,10 +673,15 @@ struct skeyword s_keytable[] = { { "reldef", QRELDEF } , { "observer", QOBSERVER } , { "exits", QEXITS } , + { "noreturn", QEXITS } , { "mayexit", QMAYEXIT } , + { "maynotreturn", QMAYEXIT } , { "trueexit", QTRUEEXIT } , { "falseexit", QFALSEEXIT } , + { "noreturnwhentrue", QTRUEEXIT } , + { "noreturnwhenfalse", QFALSEEXIT } , { "neverexit", QNEVEREXIT } , + { "alwaysreturns", QNEVEREXIT } , { "temp", QTEMP } , { "shared", QSHARED } , { "ref", QREF } , @@ -766,9 +785,8 @@ static int tokenMacroCode (cstring s) 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 " + ("Traditional lint comment /*FALLTHROUGH*/ used. " + "Splint interprets this in the same way as most Unix lints, but it is " "preferable to replace it with the /*@fallthrough@*/ " "semantic comment"), g_currentloc); @@ -779,9 +797,8 @@ static int tokenMacroCode (cstring s) 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 " + ("Traditional lint comment /*FALLTHRU*/ used. " + "Splint interprets this in the same way as most Unix lints, but it is " "preferable to replace it with the /*@fallthrough@*/ " "semantic comment"), g_currentloc); @@ -792,9 +809,8 @@ static int tokenMacroCode (cstring s) 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 " + ("Traditional lint comment /*NOTREACHED*/ used. " + "Splint interprets this in the same way as most Unix lints, but it is " "preferable to replace it with the /*@notreached@*/ " "semantic comment."), g_currentloc); @@ -811,9 +827,8 @@ static int tokenMacroCode (cstring s) 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 " + ("Traditional lint comment /*PRINTFLIKE*/ used. " + "Splint interprets this in the same way as most Unix lints, but it is " "preferable to replace it with either /*@printflike@*/, " "/*@scanflike@*/ or /*@messagelike@*/."), g_currentloc); @@ -836,9 +851,8 @@ static int tokenMacroCode (cstring s) 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 " + ("Traditional lint comment /*ARGSUSED*/ used. " + "Splint interprets this in the same way as most Unix lints, but it is " "preferable to use /*@unused@*/ annotations on " "the unused parameters."), g_currentloc); @@ -1699,20 +1713,23 @@ static bool handleSpecial (char *yyt) char c; char *ol; cstring olc; - - strcpy (l, yyt + 1); - /* Need to safe original l for deallocating. */ - ol = l; + int len_yyt; - l += strlen (yyt) - 1; + len_yyt = strlen (yyt +1) ; + + l = mstring_copy (yyt + 1); while ((c = char_fromInt (lminput ())) != '\n' && c != '\0') { - *l++ = c; + l = mstring_append(l, c); } - *l = '\0'; + /* Need to safe original l for deallocating. */ + ol = l; + + l += strlen (l); + olc = cstring_fromChars (ol); if (cstring_equalPrefixLit (olc, "pragma")) @@ -1978,7 +1995,7 @@ static int handleLlSpecial () (FLG_SYNTAX, message ("Likely parse error: syntactic comment token spans multiple lines: %s", cstring_fromChars (s)), - g_currentloc); + loc); } s = mstring_append (s, c); @@ -2026,8 +2043,8 @@ static int handleLlSpecial () if (!context_getFlag (FLG_NOCOMMENTS)) { cstring flagname = thisflag; - flagcode fflag = identifyFlag (flagname); - + flagcode fflag = flags_identifyFlag (flagname); + if (flagcode_isSkip (fflag)) { ; @@ -2056,7 +2073,7 @@ static int handleLlSpecial () (FLG_UNRECOGFLAGCOMMENTS, message ("Unrecognized option in semantic comment: %s", flagname), - g_currentloc); + loc); } } else if (flagcode_isGlobalFlag (fflag)) @@ -2067,11 +2084,11 @@ static int handleLlSpecial () ("Semantic comment attempts to set global flag %s. " "A global flag cannot be set locally.", flagname), - g_currentloc); + loc); } else { - context_fileSetFlag (fflag, set); + context_fileSetFlag (fflag, set, loc); if (flagcode_hasArgument (fflag)) { @@ -2083,7 +2100,7 @@ static int handleLlSpecial () ("Semantic comment attempts to restore flag %s. " "A flag for setting a value cannot be restored.", flagname), - g_currentloc); + loc); } else { /* cut-and-pastied from llmain...blecch */ @@ -2126,7 +2143,11 @@ static int handleLlSpecial () { s--; - if (flagcode_hasValue (fflag)) + if (flagcode_hasNumber (fflag)) + { + setValueFlag (fflag, extra); + } + else if (flagcode_hasChar (fflag)) { setValueFlag (fflag, extra); } @@ -2158,7 +2179,7 @@ static int handleLlSpecial () if (context_inHeader () && !isArtificial (cstring_fromChars (os))) { DPRINTF (("Here adding comment: %s", os)); - context_addComment (cstring_fromCharsNew (os)); + context_addComment (cstring_fromCharsNew (os), loc); } else { @@ -2226,8 +2247,14 @@ static int handleLlSpecial () && macrocode != SKIPTOK && !isArtificial (cstring_fromChars (os))) { - DPRINTF (("Add comment: %s", os)); - context_addComment (cstring_fromCharsNew (os)); + if (context_processingMacros ()) + { + /* evans 2002-02-24: don't add comments when procssing macros */ + } + else + { + context_addComment (cstring_fromCharsNew (os), loc); + } } else { @@ -2244,7 +2271,7 @@ static int handleLlSpecial () { if (!context_getFlag (FLG_NOCOMMENTS)) { - context_enterSuppressRegion (); + context_enterSuppressRegion (loc); } } else if ((*t == 'i' || *t == 't') @@ -2253,7 +2280,7 @@ static int handleLlSpecial () if (!context_getFlag (FLG_NOCOMMENTS) && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS))) { - context_enterSuppressLine (-1); /* infinite suppression */ + context_enterSuppressLine (-1, loc); /* infinite suppression */ } } else if (((*t == 'i') || (*t == 't')) @@ -2276,19 +2303,19 @@ static int handleLlSpecial () lc = *(++tt); } } - if (!context_getFlag (FLG_NOCOMMENTS) && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS))) { - context_enterSuppressLine (val); + DPRINTF (("Here: enter suppress: %s", fileloc_unparse (loc))); + context_enterSuppressLine (val, loc); } } else if (mstring_equal (t, "end")) { if (!context_getFlag (FLG_NOCOMMENTS)) { - context_exitSuppressRegion (); + context_exitSuppressRegion (loc); } } else if (mstring_equal (t, "notfunction")) @@ -2343,20 +2370,20 @@ static int handleLlSpecial () message ("Non-abstract type %s used in access comment", tname), - g_currentloc); + loc); } } else { if (!(context_inSuppressRegion () - || context_inSuppressZone (g_currentloc))) + || context_inSuppressZone (loc))) { voptgenerror (FLG_COMMENTERROR, message ("Unrecognized type %s used in access comment", tname), - g_currentloc); + loc); } } } @@ -2414,7 +2441,7 @@ static int handleLlSpecial () else { if (!(context_inSuppressRegion () - || context_inSuppressZone (g_currentloc))) + || context_inSuppressZone (loc))) { uentry ue = usymtab_getTypeEntry (tuid); @@ -2425,7 +2452,7 @@ static int handleLlSpecial () message ("Non-accessible abstract type %s used in noaccess comment", tname), - g_currentloc); + loc); } else { @@ -2434,7 +2461,7 @@ static int handleLlSpecial () message ("Non-abstract type %s used in noaccess comment", tname), - g_currentloc); + loc); } } } @@ -2442,14 +2469,14 @@ static int handleLlSpecial () else { if (!(context_inSuppressRegion () - || context_inSuppressZone (g_currentloc))) + || context_inSuppressZone (loc))) { voptgenerror (FLG_COMMENTERROR, message ("Unrecognized type %s used in noaccess comment", tname), - g_currentloc); + loc); } } } @@ -2469,9 +2496,10 @@ static int handleLlSpecial () { voptgenerror (FLG_UNRECOGCOMMENTS, message ("Semantic comment unrecognized: %s", - cstring_fromChars (os)), loc); + cstring_fromChars (os)), + loc); } - + sfree (t); } @@ -2636,6 +2664,14 @@ static int processIdentifier (cstring id) { tok = CALIGNOF; /* alignof is parsed like sizeof */ } + else if (cstring_equalLit (id, "__typeof__")) + { + tok = CTYPEOF; + } + else if (cstring_equalLit (id, "typeof")) + { + tok = CTYPEOF; + } else if (cstring_equalLit (id, "__FUNCTION__") || cstring_equalLit (id, "__PRETTY_FUNCTION__")) { @@ -2894,6 +2930,46 @@ static /*@only@*/ exprNode processString () return (res); } +/* +** process a wide character string L"...." +*/ + +static /*@only@*/ exprNode processWideString () +{ + exprNode res; + fileloc loc; + char *nl = strchr (yytext, '\n'); + cstring ns; + + llassert (*yytext == 'L'); + yytext++; + + 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_wideStringLiteral (ns, loc); + return (res); +} + static char processChar () {