/*;-*-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-2002 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 splint: splint@cs.virginia.edu
+** To report a bug: splint-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 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.
+**
+** 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_$]
ULSuffix ({U}{L}|{L}{U})
%{
+# include "splintMacros.nf"
+# if defined(OS2) && defined(__IBMC__)
+ /* needed for isatty()... */
+# include <io.h>
+# else
+
/*
-** based on original C lexer by Nate Osgood
-** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993
-**
+** Win32 doesn't have unistd.h
*/
-# include "lclintMacros.nf"
+# ifndef WIN32
+# include <unistd.h>
+# endif
+
+# endif
+
# 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))
-/*@-noparams@*/
-/*@-incondefs@*/
-extern /*@external@*/ int read ();
-/*@=incondefs@*/
-/*@=noparams@*/
-
-static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
-
+static /*@owned@*/ cstring s_lastidprocessed = cstring_undefined;
static int lminput (void);
static int tokLength = 0;
-static bool inSpecPart = FALSE;
+static bool s_inSpecPart = FALSE;
+static int s_whichSpecPart;
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);
static int processIdentifier (/*@only@*/ cstring)
- /*@globals undef lastidprocessed@*/ ;
+ /*@globals s_lastidprocessed@*/ ;
static bool processHashIdentifier (/*@only@*/ cstring)
- /*@globals undef lastidprocessed@*/ ;
+ /*@globals s_lastidprocessed@*/ ;
static int processSpec (int);
static bool handleSpecial (char *);
{
addColumn (len);
tokLength = len;
+ DPRINTF (("Set tok length: %d", len));
}
static void setTokLengthT (size_t len)
%%
-"/*" { llfatalbug (cstring_makeLiteral ("Comment in pre-processor output")); }
+"/*" { llfatalerror (cstring_makeLiteral ("Comment in pre-processor output")); }
"#"{Letter}({Letter}|{Digit})* {
context_saveLocation ();
"volatile" { setTokLength (8); RETURN_TOK (QVOLATILE); }
"const" { setTokLength (5); RETURN_TOK (QCONST); }
+"restrict" { setTokLength (8); RETURN_TOK (QRESTRICT); }
/* some systems expect this! [gack!] */
"__const" { setTokLength (7); RETURN_TOK (QCONST); }
"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)); }
"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)); }
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));
[ \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;
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);
}
if (processMacro ())
{
+ DPRINTF (("Here we are: %s", context_unparse ()));
+
if (context_inIterDef ())
{
RETURN_TOK (LLMACROITER);
}
"%}" { /* AFTER_COMMENT_MARKER */
setTokLength (2);
- inSpecPart = FALSE;
+ s_inSpecPart = FALSE;
+ s_whichSpecPart = BADTOK;
RETURN_TOK (QENDMACRO); }
"\\" { incColumn (); continueLine = TRUE; }
. { incColumn ();
}
%%
+/*
+** Resets flags set by flex.head.
+*/
+
+/*@=allmacros@*/
+/*@=pred@*/
+/*@=globstate@*/
+/*@=null@*/
+/*@=boolint@*/
+/*@=charint@*/
+/*@=macrospec@*/
+/*@=macroredef@*/
+/*@=exitarg@*/
+/*@=compdef@*/
+/*@=uniondef@*/
+/*@=ignorequals@*/
+/*@=noreturn@*/
+/*@=mustfree@*/
+/*@=compdestroy@*/
+/*@=branchstate@*/
+/*@=unreachable@*/
+/*@=varuse@*/
+/*@=fcnuse@*/
+/*@=exportlocal@*/
+/*@=evalorderuncon@*/
+/*@=exportheader@*/
+/*@=redecl@*/
+/*@=loopswitchbreak@*/
+/*@=switchswitchbreak@*/
+/*@=sizeoftype@*/
+/*@=czechfcns@*/
+/*@=noparams@*/
+/*@=ansireserved@*/
+/*@=ifblock@*/
+/*@=whileblock@*/
+/*@=forblock@*/
+/*@=elseifcomplete@*/
+/*@=ptrnegate@*/
+/*@=onlytrans@*/
+/*@=temptrans@*/
+/*@=immediatetrans@*/
+/*@=namechecks@*/
+/*@=matchanyintegral@*/
+/*@=statictrans@*/
+/*@=compmempass@*/
+/*@=forempty@*/
+/*@=evalorder@*/
+/*@=retalias@*/
+/*@=redecl@*/
+/*@=retvalother@*/
+/*@=exportheader@*/
+
struct skeyword
{
/*@null@*/ /*@observer@*/ char *name;
** grammar proper.
*/
-struct skeyword s_parsetable[] = {
+static struct skeyword s_parsetable[] = {
{ "modifies", QMODIFIES } ,
{ "globals", QGLOBALS } ,
{ "alt", QALT } ,
{ "testinRange", QTESTINRANGE},
{ "requires", QPRECLAUSE } ,
{ "ensures", QPOSTCLAUSE } ,
+ { "invariant", QINVARIANT} ,
{ NULL, BADTOK }
} ;
** token-specific text.
*/
-struct skeyword s_keytable[] = {
+static struct skeyword s_keytable[] = {
{ "anytype", QANYTYPE } ,
{ "integraltype", QINTEGRALTYPE } ,
{ "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,
{ "special", QSPECIAL } ,
{ "truenull", QTRUENULL } ,
{ "falsenull", QFALSENULL } ,
+ { "nullwhentrue", QTRUENULL } ,
+ { "falsewhennull", QFALSENULL } ,
{ "keep", QKEEP } ,
{ "kept", QKEPT } ,
{ "notnull", QNOTNULL } ,
{ "nullterminated", QNULLTERMINATED },
{ "setBufferSize", QSETBUFFERSIZE },
{ "testInRange", QTESTINRANGE},
+ { "isnull", QISNULL },
{ "MaxSet", QMAXSET},
{ "MaxRead", QMAXREAD},
+ { "maxSet", QMAXSET},
+ { "maxRead", QMAXREAD},
{ "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 } ,
|| cstring_equalLit (s, "alt"));
}
-void swallowMacro (void)
+void cscanner_swallowMacro (void)
{
int i;
bool skipnext = FALSE;
{
char c = (char) i;
-
if (c == '\\')
{
skipnext = TRUE;
return;
}
}
+ else
+ {
+ ;
+ }
}
if (i != EOF)
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);
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);
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);
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);
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);
setArgsUsed ();
return SKIPTOK;
}
-
- return s_keytable[i].token;
+ else
+ {
+ return s_keytable[i].token;
+ }
}
-
+
i++;
}
{
c = context_typeofOne ();
}
+ else
+ {
+ ;
+ }
}
yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
return c;
}
-static char macro_nextChar ()
+static char macro_nextChar (void)
{
static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
int ic;
lmsavechar (c2);
}
}
+ else
+ {
+ ;
+ }
+
return c;
}
** keeps semantic comments
*/
-static char macro_nextCharC ()
+static char macro_nextCharC (void)
{
static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
char c;
lmsavechar (c2);
}
}
+ else /* normal character */
+ {
+ ;
+ }
+
return c;
}
** returns first non-whitespace character
*/
-static char skip_whitespace ()
+static char skip_whitespace (void)
{
char c;
{
int i;
- for (i = 0; i < ((c - '0') + 1); i++)
+ for (i = 0; i < (((int) (c - '0')) + 1); i++)
{
mac = cstring_appendChar (mac, ' ');
}
{
c = macro_nextChar ();
}
- unput (c);
+ unput ((int) c);
}
if (c == '\n')
{
emptyMacro = TRUE;
- unput (c);
+ unput ((int) 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)))
{
fileloc_unparse (oloc)),
loc);
}
+ else
+ {
+ /* No warning */
+ }
}
context_enterConstantMacro (e2);
"typedef should be used instead."),
g_currentloc);
- swallowMacro ();
+ cscanner_swallowMacro ();
/* Must exit scope (not sure why a new scope was entered?) */
usymtab_quietExitScope (g_currentloc);
uentry_setDefined (e2, g_currentloc);
{
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 */
&& !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)
{
}
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));
}
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;
static bool handleSpecial (char *yyt)
{
- char *l = mstring_create (MAX_NAME_LENGTH);
- static bool reportcpp = FALSE;
+ char *l; /* !! = mstring_create (MAX_NAME_LENGTH); */
int lineno = 0;
char c;
char *ol;
cstring olc;
-
- strcpy (l, yyt + 1);
+ size_t len_yyt;
- /* Need to safe original l for deallocating. */
- ol = l;
+ len_yyt = strlen (yyt +1) ;
- l += 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_equalPrefix (olc, "pragma"))
+ if (cstring_equalPrefixLit (olc, "pragma"))
{
- char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN));
+ char *pname = mstring_create (size_fromInt (MAX_PRAGMA_LEN));
char *opname = pname;
char *ptr = ol + 6; /* pragma is six characters, plus space */
int len = 0;
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 */
}
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);
return FALSE;
}
-static int handleLlSpecial ()
+static int handleLlSpecial (void)
{
+ bool hasnl = FALSE;
int ic;
char c;
char *s = mstring_createEmpty ();
{
ic = ninput ();
- llassert (ic == AFTER_COMMENT_MARKER[1]);
+ llassert (ic == (int) AFTER_COMMENT_MARKER[1]);
if (*s == '\0')
{
{
tokLength = charsread;
sfree (os);
- inSpecPart = TRUE;
+ s_inSpecPart = TRUE;
+ s_whichSpecPart = tok;
fileloc_free (loc);
return tok;
}
charsread++;
while (((ic = ninput ()) != 0) && (ic != EOF)
- && (ic != AFTER_COMMENT_MARKER[0]))
+ && (ic != (int) 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)),
+ loc);
+ }
+
s = mstring_append (s, c);
charsread++;
}
DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
- if (ic == AFTER_COMMENT_MARKER[0])
+ if (ic == (int) AFTER_COMMENT_MARKER[0])
{
int nc = ninput ();
llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
if (!context_getFlag (FLG_NOCOMMENTS))
{
cstring flagname = thisflag;
- flagcode fflag = identifyFlag (flagname);
-
+ flagcode fflag = flags_identifyFlag (flagname);
+
if (flagcode_isSkip (fflag))
{
;
}
- else if (flagcode_isInvalid (fflag))
+ else if (flagcode_isModeName (fflag))
{
- if (isMode (flagname))
+ if (ynm_isMaybe (set))
{
- 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);
- }
+ llerror
+ (FLG_BADFLAG,
+ message
+ ("Semantic comment attempts to restore flag %s. "
+ "A mode flag cannot be restored.",
+ flagname));
}
else
{
- voptgenerror
- (FLG_UNRECOGFLAGCOMMENTS,
- message ("Unrecognized option in semantic comment: %s",
- flagname),
- g_currentloc);
+ context_setMode (flagname);
}
}
+ else if (flagcode_isInvalid (fflag))
+ {
+ voptgenerror
+ (FLG_UNRECOGFLAGCOMMENTS,
+ message ("Unrecognized option in semantic comment: %s",
+ flagname),
+ loc);
+ }
else if (flagcode_isGlobalFlag (fflag))
{
voptgenerror
("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))
{
("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 */
rest++;
s++;
}
-
+ s--; /* evans 2002-07-12: this was previously only in the else branch.
+ Leads to an invalid read on the true branch.
+ */
+
sfree (orest);
if (cstring_isUndefined (extra))
message
("Flag %s (in semantic comment) must be followed by an argument",
flagcode_unparse (fflag)));
+
}
else
{
- s--;
-
- if (flagcode_hasValue (fflag))
+ if (flagcode_hasNumber (fflag))
+ {
+ setValueFlag (fflag, extra);
+ }
+ else if (flagcode_hasChar (fflag))
{
setValueFlag (fflag, extra);
}
}
else
{
+ cstring_free (extra);
BADEXIT;
}
}
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
{
if (macrocode != BADTOK)
{
- tokLength = mstring_length (t);
+ tokLength = hasnl ? 0 : size_toInt (mstring_length (t));
sfree (t);
sfree (os);
&& 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
{
{
if (!context_getFlag (FLG_NOCOMMENTS))
{
- context_enterSuppressRegion ();
+ context_enterSuppressRegion (loc);
}
}
else if ((*t == 'i' || *t == 't')
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'))
while (lc >= '0' && lc <= '9')
{
val *= 10;
- val += lc - '0';
+ val += (int) (lc - '0');
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"))
while (TRUE)
{
- while ((c = *s) && (c == ' ' || c == '\t' || c == '\n'))
+ while (((c = *s) != '\0') && (c == ' ' || c == '\t' || c == '\n'))
{
s++;
}
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);
}
}
}
while (TRUE)
{
- while ((lc = *s) && (lc == ' ' || lc == '\t' || lc == '\n'))
+ while (((lc = *s) != '\0') && (lc == ' ' || lc == '\t' || lc == '\n'))
{
s++;
}
else
{
if (!(context_inSuppressRegion ()
- || context_inSuppressZone (g_currentloc)))
+ || context_inSuppressZone (loc)))
{
uentry ue = usymtab_getTypeEntry (tuid);
message
("Non-accessible abstract type %s used in noaccess comment",
tname),
- g_currentloc);
+ loc);
}
else
{
message
("Non-abstract type %s used in noaccess 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 noaccess comment",
tname),
- g_currentloc);
+ loc);
}
}
}
{
voptgenerror (FLG_UNRECOGCOMMENTS,
message ("Semantic comment unrecognized: %s",
- cstring_fromChars (os)), loc);
+ cstring_fromChars (os)),
+ loc);
}
-
+
sfree (t);
}
static /*@only@*/ cstring makeIdentifier (char *s)
{
- char *c = mstring_create (size_toInt (strlen (s)) + 1);
+ char *c = mstring_create (strlen (s) + 1);
cstring id = cstring_fromChars (c);
while (isalnum (*s) || (*s == '_') || (*s == '$'))
return (usymtab_lookup (cn));
}
-/*@observer@*/ cstring LastIdentifier ()
+/*
+** Need to keep this in case there is a declaration that isn't processed until
+** the scope exits. Would be good to rearrange the symbol table so this doesn't
+** happen, and save all the cstring copying.
+*/
+
+/*@observer@*/ cstring cscanner_observeLastIdentifier ()
{
- return (lastidprocessed);
+ cstring res = s_lastidprocessed;
+ return res;
+}
+
+static void cscanner_setLastIdentifier (/*@keep@*/ cstring id) /*@modifies s_lastidprocessed@*/
+{
+ if (cstring_isDefined (s_lastidprocessed))
+ {
+ cstring_free (s_lastidprocessed);
+ }
+
+ s_lastidprocessed = id;
}
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;
+ cscanner_setLastIdentifier (id);
+
+ DPRINTF (("Context: %s", context_unparse ()));
if (context_inFunctionHeader ())
{
int tok = commentMarkerToken (id);
- DPRINTF (("in function decl..."));
+ DPRINTF (("in function decl: %s", id));
if (tok != BADTOK)
{
else
{
tok = tokenMacroCode (id);
-
+
if (tok != BADTOK)
{
return tok;
}
}
+ DPRINTF (("Here!"));
+
/* Consider handling: Defined by C99 as static const char __func__[] */
if (context_getFlag (FLG_GNUEXTENSIONS))
{
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__"))
{
/* These tokens hold the name of the current function as strings */
- yylval.expr = exprNode_stringLiteral (id, fileloc_copy (g_currentloc));
+ /* evans 2001-12-30: changed from exprNode_stringLiteral; bug reported by Jim Zelenka. */
+ yylval.expr = exprNode_makeConstantString (id, fileloc_copy (g_currentloc));
tokLength = 0;
lastWasString = TRUE;
tok = CCONSTANT;
while ((ic = input ()) != EOF)
{
-
+ char cc = (char) ic;
+
if (inescape)
{
inescape = FALSE;
}
- else if (ic == '\\')
+ else if (cc == '\\')
{
inescape = TRUE;
}
- else if (ic == '\"')
+ else if (cc == '\"')
{
inquote = !inquote;
}
else if (!inquote)
{
- if (ic == '(')
+ if (cc == '(')
{
if (!useparens)
{
depth++;
}
}
- else if (ic == '{')
+ else if (cc == '{')
{
if (!usebraces)
{
depth++;
}
}
- else if (ic == ')' && useparens)
+ else if (cc == ')' && useparens)
{
depth--;
if (depth == 0) break;
}
- else if (ic == '}' && usebraces)
+ else if (cc == '}' && usebraces)
{
depth--;
if (depth == 0) break;
}
- else if (ic == '}'
+ else if (cc == '}'
&& !usebraces && !useparens
&& cstring_equalLit (id, "__asm"))
{
*/
return TRBRACE;
}
+ else
+ {
+ ;
+ }
+ }
+ else
+ {
+ ;
}
- if (ic == '\n')
+ if (cc == '\n')
{
context_incLineno ();
}
}
- llassert ((useparens && ic == ')')
- || (usebraces && ic == '}')
+ llassert ((useparens && ic == (int) ')')
+ || (usebraces && ic == (int) '}')
|| (!useparens && !usebraces));
return BADTOK;
{
tok = QINLINE;
}
+ else
+ {
+ ;
+ }
if (tok != BADTOK)
{
}
else if (uentry_isUndefined (le))
{
- yylval.cname = id;
+ yylval.cname = cstring_copy (id);
/* avoid parse errors for certain system built ins */
{
if (uentry_isDatatype (le))
{
- yylval.cname = id;
+ yylval.cname = cstring_copy (id);
return (NEW_IDENTIFIER);
}
else
{
if (!g_expectingTypeName)
{
- yylval.cname = id;
+ yylval.cname = cstring_copy (id);
return (NEW_IDENTIFIER);
}
context_clearJustPopped ();
- lastidprocessed = id;
le = usymtab_lookupSafe (id);
+ cscanner_setLastIdentifier (id);
if (uentry_isParam (le) || uentry_isRefParam (le))
{
}
else
{
+ /*
+ ** Will be handled by handleLlSpecial
+ */
+
cstring_free (id);
return FALSE;
}
}
-static /*@only@*/ exprNode processString ()
+static /*@only@*/ exprNode processString (void)
{
exprNode res;
fileloc loc;
if (nl == NULL)
{
loc = fileloc_copy (g_currentloc);
- addColumn (cstring_length (ns));
+ addColumn (size_toInt (cstring_length (ns)));
}
else
{
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 (size_toInt (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 ()
{
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,
processSpec (int tok)
{
size_t length = strlen (yytext);
-
- if (inSpecPart)
- {
- setTokLengthT (length);
- RETURN_TOK (tok);
- }
- else
+ if (s_inSpecPart)
{
- context_saveLocation ();
- setTokLengthT (length);
- return (processIdentifier (makeIdentifier (yytext)));
+#if 0
+
+ if (s_whichSpecPart == QMODIFIES
+ || s_whichSpecPart == QDEFINES
+ || s_whichSpecPart == QUSES
+ || s_whichSpecPart == QALLOCATES
+ || s_whichSpecPart == QSETS
+ || s_whichSpecPart == QRELEASES
+ || s_whichSpecPart == QPRECLAUSE
+ || s_whichSpecPart == QPOSTCLAUSE
+ || s_whichSpecPart == QINVARIANT)
+ {
+ ; /* Allow specificiation keywords to be used as identifiers in these contexts. */
+ }
+ else
+
+#endif
+
+ {
+ setTokLengthT (length);
+ RETURN_TOK (tok);
+ }
}
+
+ context_saveLocation ();
+ setTokLengthT (length);
+ return (processIdentifier (makeIdentifier (yytext)));
}
void cscanner_expectingMetaStateName ()