X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/7272a1c162ecf75235b8a4c44c9b86d023e7ef16..4c9767b33603c69226bbb51e618873fe972dd7ac:/src/cscanner.l diff --git a/src/cscanner.l b/src/cscanner.l index 66701f5..7b0f8de 100644 --- a/src/cscanner.l +++ b/src/cscanner.l @@ -1,46 +1,57 @@ /*;-*-C-*-; -** Copyright (c) Massachusetts Institute of Technology 1994-1998. -** All Rights Reserved. -** Unpublished rights reserved under the copyright laws of -** the United States. +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2001 University of Virginia, +** Massachusetts Institute of Technology ** -** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED -** OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 2 of the License, or (at your +** option) any later version. +** +** This program is distributed in the hope that it will be useful, but +** WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** The GNU General Public License is available from http://www.gnu.org/ or +** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +** MA 02111-1307, USA. ** -** This code is distributed freely and may be used freely under the -** following conditions: -** -** 1. This notice may not be removed or altered. +** For information on lclint: lclint-request@cs.virginia.edu +** To report a bug: lclint-bug@cs.virginia.edu +** For more information: http://www.splint.org +*/ +/* +** cscanner.l ** -** 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). +** Flex lexer for C. +** Based on a C lexer by Nate Osgood +** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993 */ /* - * 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 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 - */ +** 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_$] @@ -53,13 +64,14 @@ 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" +# if defined(OS2) && defined(__IBMC__) + /* needed for isatty()... */ +# include +# else +# include +# endif + # include "basic.h" # include "cgrammar.h" @@ -68,25 +80,13 @@ ULSuffix ({U}{L}|{L}{U}) # include "fileIdList.h" # include "portab.h" -# if defined(OS2) && defined(__IBMC__) - /* needed for isatty()... */ -# include -# endif - static bool lastWasString = FALSE; static char savechar = '\0'; /*@notfunction@*/ # define yyinput() (incColumn (), getc (yyin)) -/*@-noparams@*/ -/*@-incondefs@*/ -extern /*@external@*/ int read (); -/*@=incondefs@*/ -/*@=noparams@*/ - static /*@owned@*/ cstring lastidprocessed = cstring_undefined; - static int lminput (void); static int tokLength = 0; static bool inSpecPart = FALSE; @@ -174,6 +174,7 @@ static void setTokLength (int len) { addColumn (len); tokLength = len; + DPRINTF (("Set tok length: %d", len)); } static void setTokLengthT (size_t len) @@ -368,6 +369,8 @@ L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); 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)); @@ -443,6 +446,16 @@ L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); [ \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; @@ -496,6 +509,8 @@ L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); if (processMacro ()) { + DPRINTF (("Here we are: %s", context_unparse ())); + if (context_inIterDef ()) { RETURN_TOK (LLMACROITER); @@ -1232,14 +1247,12 @@ static bool processMacro (void) } hasParams = (c == '('); - if (usymtab_exists (fname)) { e2 = usymtab_lookupExpose (fname); ct = uentry_getType (e2); - if (uentry_isCodeDefined (e2) && fileloc_isUser (uentry_whereDefined (e2))) { @@ -1312,7 +1325,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); @@ -1457,24 +1470,47 @@ static bool processMacro (void) { uentry ce; - 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; + /* 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 */ @@ -1523,14 +1559,14 @@ static bool processMacro (void) && !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)); + sr = sRef_makeParam (paramno, uentry_getType (param), stateInfo_makeLoc (sloc)); if (sRef_getNullState (sr) == NS_ABSNULL) { @@ -1547,12 +1583,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)); } @@ -1561,11 +1597,12 @@ 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))); + DPRINTF (("Unknown param: %s", uentry_unparseFull (param))); cstring_free (paramname); sRef_setPosNull (uentry_getSref (param), sloc); - uentry_setDeclaredForce (param, sloc); skipparam = FALSE; @@ -1658,7 +1695,6 @@ static bool processMacro (void) static bool handleSpecial (char *yyt) { char *l = mstring_create (MAX_NAME_LENGTH); - static bool reportcpp = FALSE; int lineno = 0; char c; char *ol; @@ -1679,7 +1715,7 @@ static bool handleSpecial (char *yyt) *l = '\0'; olc = cstring_fromChars (ol); - if (cstring_equalPrefix (olc, "pragma")) + if (cstring_equalPrefixLit (olc, "pragma")) { char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN)); char *opname = pname; @@ -1737,7 +1773,7 @@ static bool handleSpecial (char *yyt) cstring_free (exname); } } - else if (cstring_equalPrefix (olc, "ident")) + else if (cstring_equalPrefixLit (olc, "ident")) { /* Some pre-processors will leave these in the code. Ignore rest of line */ } @@ -1819,7 +1855,11 @@ static bool handleSpecial (char *yyt) if (!(fileId_isValid (fid))) { - if (isHeaderFile (fname)) + if (context_inXHFile ()) + { + fid = fileTable_addXHFile (context_fileTable (), fname); + } + else if (isHeaderFile (fname)) { fid = fileTable_addHeaderFile (context_fileTable (), fname); } @@ -1848,18 +1888,15 @@ static bool handleSpecial (char *yyt) mstring_free (ol); return FALSE; } else { - if (!reportcpp) - { - - } else { - llbug (message ("File contains preprocessor command: #%s", - cstring_fromChars (ol))); - reportcpp = TRUE; - } + voptgenerror + (FLG_UNRECOGDIRECTIVE, + message ("Unrecognized pre-processor directive: #%s", + cstring_fromChars (ol)), + g_currentloc); } sfree (ol); - return TRUE; + return FALSE; /* evans 2001-12-30: was: TRUE; */ } sfree (ol); @@ -1868,6 +1905,7 @@ static bool handleSpecial (char *yyt) static int handleLlSpecial () { + bool hasnl = FALSE; int ic; char c; char *s = mstring_createEmpty (); @@ -1929,6 +1967,20 @@ static int handleLlSpecial () && (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++; } @@ -2137,7 +2189,7 @@ static int handleLlSpecial () if (macrocode != BADTOK) { - tokLength = mstring_length (t); + tokLength = hasnl ? 0 : mstring_length (t); sfree (t); sfree (os); @@ -2492,8 +2544,10 @@ static int processIdentifier (cstring id) { uentry le; - DPRINTF (("Process identifier: %s / %s / %s", id, fileloc_unparse (g_currentloc), - bool_unparse (context_inFunctionHeader ()))); + if (context_getFlag (FLG_GRAMMAR)) + { + lldiagmsg (message ("Process identifier: %s", id)); + } context_clearJustPopped (); lastidprocessed = id; @@ -2797,6 +2851,10 @@ static bool processHashIdentifier (/*@only@*/ cstring id) } else { + /* + ** Will be handled by handleLlSpecial + */ + cstring_free (id); return FALSE; } @@ -2932,6 +2990,22 @@ long processOctal () if (c >= '0' && c <= '7') { tval = (int) c - (int) '0'; + } 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 octal constant: %s", + c, cstring_fromChars (yytext)), + g_currentloc); + } + index++; + } + + break; } else { voptgenerror (FLG_SYNTAX, @@ -2959,7 +3033,6 @@ static int processSpec (int tok) { size_t length = strlen (yytext); - if (inSpecPart) {