]> andersk Git - splint.git/blobdiff - src/cscanner.l
Fixed handling of __FUNCTION__
[splint.git] / src / cscanner.l
index 6eeba4b382a4e8b387c5a82d25ef2ebaab6e8bf5..eddfd1d88c91147a453a369bf848e03faa483545 100644 (file)
@@ -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 <io.h>
+# else
+# include <unistd.h>
+# 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 <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 int lminput (void);
 static int tokLength = 0;
 static bool inSpecPart = FALSE;
@@ -114,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);
@@ -172,6 +174,7 @@ static void setTokLength (int len)
 {
   addColumn (len);
   tokLength = len;
+  DPRINTF (("Set tok length: %d", len));
 }
 
 static void setTokLengthT (size_t len)
@@ -269,6 +272,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,7 +311,9 @@ static void setTokLengthT (size_t len)
 "killed"                { return (processSpec (QKILLED)); }
 "nullterminated"        { return (processSpec (QNULLTERMINATED));}
 "MaxSet"                { return (processSpec (QMAXSET));}
-"MaxRead"                { return (processSpec (QMAXREAD));}
+"MaxRead"               { return (processSpec (QMAXREAD));}
+"maxSet"                { return (processSpec (QMAXSET));}
+"maxRead"               { return (processSpec (QMAXREAD));}
 
 {Letter}({Letter}|{Digit})* { int tok; 
                              context_saveLocation (); 
@@ -363,6 +369,8 @@ static void setTokLengthT (size_t len)
                         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)); 
@@ -438,6 +446,16 @@ static void setTokLengthT (size_t len)
 
 [ \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;
@@ -491,6 +509,8 @@ static void setTokLengthT (size_t len)
                      
                      if (processMacro ()) 
                        {
+                         DPRINTF (("Here we are: %s", context_unparse ()));
+                         
                          if (context_inIterDef ()) 
                            {
                              RETURN_TOK (LLMACROITER); 
@@ -584,11 +604,9 @@ struct skeyword s_parsetable[] = {
   { "releases", QRELEASES } ,
   { "pre", QPRECLAUSE } ,
   { "post", QPOSTCLAUSE } ,
-  {"setBufferSize", QSETBUFFERSIZE},
-  {"LRequires", QBUFFERCONSTRAINT},
-  {"LEnsures", QENSURESCONSTRAINT},
-  {"setStringLength", QSETSTRINGLENGTH},
-  {"testinRange", QTESTINRANGE},
+  { "setBufferSize", QSETBUFFERSIZE},
+  { "setStringLength", QSETSTRINGLENGTH},
+  { "testinRange", QTESTINRANGE},
   { "requires", QPRECLAUSE } ,
   { "ensures", QPOSTCLAUSE } ,
   { NULL, BADTOK } 
@@ -635,8 +653,6 @@ struct skeyword s_keytable[] = {
   { "relnull", QRELNULL } ,
   { "nullterminated", QNULLTERMINATED }, 
   { "setBufferSize", QSETBUFFERSIZE },
-  { "LRequires", QBUFFERCONSTRAINT },
-  { "LEnsures", QENSURESCONSTRAINT },
   { "testInRange", QTESTINRANGE},
   { "MaxSet", QMAXSET},
   { "MaxRead", QMAXREAD},
@@ -1231,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)))
        {
@@ -1311,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); 
@@ -1456,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 */
@@ -1522,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)
                {
@@ -1546,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));
            }
@@ -1560,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;
@@ -1657,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;
@@ -1678,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;
@@ -1736,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 */
     }
@@ -1818,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);
            }
@@ -1847,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);
@@ -1867,6 +1905,7 @@ static bool handleSpecial (char *yyt)
   
 static int handleLlSpecial ()
 { 
+  bool hasnl = FALSE;
   int ic; 
   char c;
   char *s = mstring_createEmpty ();
@@ -1928,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++;
        }
@@ -1999,20 +2052,22 @@ static int handleLlSpecial ()
                    }
                  else
                    {
-                     llerror
-                       (FLG_BADFLAG, 
+                     voptgenerror
+                       (FLG_UNRECOGFLAGCOMMENTS,
                         message ("Unrecognized option in semantic comment: %s", 
-                                 flagname));
+                                 flagname),
+                        g_currentloc);
                    }
                }
              else if (flagcode_isGlobalFlag (fflag))
                {
-                 llerror
+                 voptgenerror
                    (FLG_BADFLAG, 
                     message 
                     ("Semantic comment attempts to set global flag %s.  "
                      "A global flag cannot be set locally.",
-                     flagname));
+                     flagname),
+                    g_currentloc);
                }
              else
                {
@@ -2022,12 +2077,13 @@ static int handleLlSpecial ()
                    {
                      if (ynm_isMaybe (set))
                        {
-                         llerror
+                         voptgenerror
                            (FLG_BADFLAG, 
                             message 
                             ("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 */
@@ -2133,7 +2189,7 @@ static int handleLlSpecial ()
 
       if (macrocode != BADTOK)
        {
-         tokLength = mstring_length (t);
+         tokLength = hasnl ? 0 : mstring_length (t);
          
          sfree (t);
          sfree (os);
@@ -2488,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; 
@@ -2513,7 +2571,24 @@ static int processIdentifier (cstring id)
            }
          else 
            {
-             annotationInfo ainfo = context_lookupAnnotation (id);
+             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)) 
                {
@@ -2565,7 +2640,8 @@ static int processIdentifier (cstring id)
               || 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;
@@ -2776,6 +2852,10 @@ static bool processHashIdentifier (/*@only@*/ cstring id)
     }
   else
     {
+      /*
+      ** Will be handled by handleLlSpecial
+      */
+
       cstring_free (id);
       return FALSE;
     }
@@ -2911,6 +2991,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, 
@@ -2938,7 +3034,6 @@ static int
 processSpec (int tok)
 {
   size_t length = strlen (yytext);
-
   
   if (inSpecPart)
     {
@@ -2953,3 +3048,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;
+}
This page took 0.061434 seconds and 4 git commands to generate.