Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

lcllib.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** lcllib.c
00026 **
00027 ** routines for loading and creating library files
00028 **
00029 ** this is a brute-force implementation, a more efficient
00030 ** representation should be designed.
00031 **
00032 */
00033 
00034 # include "lclintMacros.nf"
00035 # include "llbasic.h"
00036 
00037 # include "osd.h"
00038 
00039 # ifndef NOLCL
00040 # include "gram.h"
00041 
00042 # include "lclscan.h"
00043 # endif
00044 
00045 
00046 # include "herald.h"
00047 # include "lcllib.h"
00048 # include "llmain.h"
00049 # include "portab.h"
00050 
00051 /*@-incondefs@*/ /*@-redecl@*/
00052 extern /*@dependent@*/ FILE *yyin;
00053 /*@=incondefs@*/ /*@=redecl@*/
00054 
00055 /*@constant int NUMLIBS; @*/
00056 # define NUMLIBS 17
00057 
00058 /*@constant int NUMPOSIXLIBS; @*/
00059 # define NUMPOSIXLIBS 12
00060 
00061 static ob_mstring posixlibs[NUMPOSIXLIBS] = 
00062 {
00063   "sys/stat",
00064   "sys/types",
00065   "dirent",
00066   "fcntl",
00067   "grp",
00068   "pwd",
00069   "sys/times",
00070   "sys/utsname",
00071   "sys/wait",
00072   "termios",
00073   "unistd",
00074   "utime"
00075 } ;
00076 
00077 static ob_mstring stdlibs[NUMLIBS] =
00078 {
00079   "assert", 
00080   "ctype",
00081   "errno",
00082   "float", 
00083   "limits",
00084   "locale",
00085   "math", 
00086   "setjmp",
00087   "signal",
00088   "stdarg",
00089   "stddef",
00090   "stdio",
00091   "stdlib",
00092   "strings", 
00093   "string",
00094   "time",
00095   "wchar"
00096 } ;
00097 
00098 static bool loadStateFile (FILE * p_f, cstring p_name);
00099 
00100 bool
00101 lcllib_isSkipHeader (cstring sname)
00102 {
00103   int i;
00104   bool posixlib = FALSE;
00105   char *libname;
00106   char *name = cstring_toCharsSafe (sname);
00107   char *matchname;
00108 
00109   llassert (cstring_isDefined (sname));
00110   name = removeExtension (name, ".h");
00111 
00112   libname = strrchr (name, CONNECTCHAR);
00113   matchname = libname;
00114 
00115   if (libname == NULL) 
00116     {
00117       libname = name;
00118     }
00119   else
00120     {
00121       libname++;
00122       /*@-branchstate@*/
00123     }
00124   /*@=branchstate@*/
00125 
00126   if (mstring_equal (libname, "varargs"))
00127     {
00128       fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
00129       
00130       voptgenerror 
00131         (FLG_USEVARARGS,
00132          message ("Include file <%s> is inconsistent with "
00133                   "ANSI library (should use <stdarg.h>)",
00134                   cstring_fromChars (libname)),
00135          tmp);
00136       
00137       fileloc_free (tmp);
00138       sfree (name);
00139       return TRUE;
00140     }
00141 
00142   if (context_getFlag (FLG_SKIPANSIHEADERS)
00143       && context_usingAnsiLibrary ())
00144     {
00145       
00146       for (i = 0; i < NUMLIBS; i++)
00147         {
00148           if (mstring_equal (libname, stdlibs[i]))
00149             {
00150               sfree (name);
00151               return TRUE;
00152             }
00153         }
00154     }
00155 
00156   for (i = 0; i < NUMPOSIXLIBS; i++)
00157     {
00158       if (strchr (posixlibs[i], CONNECTCHAR) != NULL)
00159         {
00160           char *ptr;
00161           
00162           if ((ptr = strstr (name, posixlibs[i])) != NULL) 
00163             {
00164               if (ptr[strlen (posixlibs[i])] == '\0')
00165                 {
00166                   posixlib = TRUE;
00167                   matchname = ptr;
00168                   break;
00169                 }
00170               else
00171                 {
00172                   ; /* no match */
00173                 }
00174             }
00175         }
00176       else
00177         {
00178           if (mstring_equal (libname, posixlibs[i]))
00179             {
00180               posixlib = TRUE;
00181               matchname = libname;
00182               break;
00183             }
00184           /*@-branchstate@*/ 
00185         }
00186     } /*@=branchstate@*/
00187   
00188   if (posixlib)
00189     {
00190       if (context_usingPosixLibrary ())
00191         {
00192           if (context_getFlag (FLG_SKIPPOSIXHEADERS))
00193             {
00194               sfree (name);
00195               return TRUE;
00196             }
00197         }
00198       else
00199         {       
00200           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
00201           
00202           voptgenerror 
00203             (FLG_WARNPOSIX,
00204              message ("Include file <%s> matches the name of a "
00205                       "POSIX library, but the POSIX library is "
00206                       "not being used.  Consider using +posixlib "
00207                       "or +posixstrictlib to select the POSIX "
00208                       "library, or -warnposix "
00209                       "to suppress this message.",
00210                       cstring_fromChars (matchname)),
00211              tmp);
00212           
00213           fileloc_free (tmp);
00214         }
00215     }
00216 
00217   sfree (name);
00218   return FALSE;
00219 }
00220 
00221 static void printDot (void)
00222 {
00223   if (context_getFlag (FLG_SHOWSCAN)) 
00224     {
00225       (void) fflush (g_msgstream);
00226       fprintf (stderr, "."); 
00227       (void) fflush (stderr);
00228     }
00229 }
00230 
00231 void
00232 dumpState (cstring cfname)
00233 {
00234   FILE *f;
00235   char *fname = cstring_toCharsSafe (cfname);
00236   
00237   fname = addExtension (fname, DUMP_SUFFIX);
00238   
00239   f = fopen (fname, "w");
00240 
00241   if (context_getFlag (FLG_SHOWSCAN))
00242     {
00243       fprintf (stderr, "< Dumping to %s ", fname); 
00244     }
00245   
00246   if (f == NULL)
00247     {
00248       llgloberror (message ("Cannot open dump file for writing: %s", cfname));
00249     }
00250   else
00251     {
00252       /*
00253       ** sequence is convulted --- must call usymtab_prepareDump before
00254       **    dumping ctype table to convert type uid's
00255       */
00256 
00257       printDot ();
00258 
00259       usymtab_prepareDump ();
00260 
00261       /*
00262       ** Be careful, these lines must match loadStateFile checking.
00263       */
00264 
00265       fprintf (f, ";;LCLint Dump: %s\n", fname);
00266       fprintf (f, ";;%s\n", LCL_VERSION);
00267       fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
00268       fprintf (f, ";;ctTable\n");
00269 
00270       printDot ();
00271             ctype_dumpTable (f);
00272       printDot ();
00273 
00274       fprintf (f, ";;tistable\n");
00275       typeIdSet_dumpTable (f);
00276       printDot ();
00277 
00278             fprintf (f, ";;symTable\n");
00279       usymtab_dump (f);
00280       printDot ();
00281 
00282       fprintf (f, ";; Modules access\n");
00283       context_dumpModuleAccess (f);
00284       fprintf (f, ";;End\n");
00285       check (fclose (f) == 0);
00286     }
00287 
00288   if (context_getFlag (FLG_SHOWSCAN))
00289     {
00290       fprintf (g_msgstream, " >\n");
00291     }
00292 
00293   sfree (fname);
00294 }
00295 
00296 bool
00297 loadStandardState ()
00298 {
00299   char *fpath;
00300   FILE *stdlib;
00301   bool result;
00302   char *libname = addExtension (context_selectedLibrary (), DUMP_SUFFIX);
00303   
00304   
00305   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
00306     {
00307       lldiagmsg (message ("Cannot find %sstandard library: %s", 
00308                           cstring_makeLiteralTemp 
00309                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
00310                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
00311                           cstring_makeLiteralTemp (libname)));
00312       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
00313       result = FALSE;
00314     }
00315   else
00316     {
00317       stdlib = fopen (fpath, "r");
00318 
00319       if (stdlib == NULL)
00320         {
00321           lldiagmsg (message ("Cannot read standard library: %s",
00322                           cstring_fromChars (fpath)));
00323           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
00324 
00325           result = FALSE;
00326         }
00327       else
00328         {
00329           if (context_getFlag (FLG_WHICHLIB))
00330             {
00331               char *t = mstring_create (MAX_NAME_LENGTH);
00332               char *ot = t;
00333 
00334               if (fgets (t, MAX_NAME_LENGTH, stdlib) == NULL)
00335                 {
00336                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
00337                 }
00338 
00339               if (fgets (t, MAX_NAME_LENGTH, stdlib) != NULL)
00340                 {
00341                   if (*t == ';' && *(t + 1) == ';') 
00342                     {
00343                       t += 2;
00344                     }
00345                 }
00346 
00347               if (t == NULL)
00348                 {
00349                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
00350                                   cstring_fromChars (fpath)));
00351                 }
00352               else
00353                 {
00354                   char *tt;
00355 
00356                   tt = strrchr (t, '\n');
00357                   if (tt != NULL)
00358                     *tt = '\0';
00359 
00360                   lldiagmsg (message ("Standard library: %s", cstring_fromChars (fpath)));
00361                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
00362                 }
00363 
00364               sfree (ot);
00365               
00366               check (fclose (stdlib) == 0);
00367               stdlib = fopen (fpath, "r");
00368             }
00369 
00370           llassert (stdlib != NULL);
00371 
00372           fileloc_reallyFree (g_currentloc);
00373           g_currentloc = fileloc_createLib (cstring_makeLiteralTemp (libname));
00374 
00375           if (context_getDebug (FLG_SHOWSCAN))
00376             {
00377               context_hideShowscan ();
00378               result = loadStateFile (stdlib, cstring_fromChars (fpath));
00379               context_unhideShowscan ();
00380             }
00381           else
00382             {
00383               result = loadStateFile (stdlib, cstring_fromChars (fpath));
00384             }
00385 
00386           check (fclose (stdlib) == 0);
00387         }
00388     }
00389 
00390   sfree (libname);
00391   return result;
00392 }
00393 
00394 /*@constant int BUFLEN;@*/
00395 # define BUFLEN 128
00396 
00397 static bool
00398 loadStateFile (FILE *f, cstring name)
00399 {
00400   char buf[BUFLEN];
00401   
00402   /*
00403   ** Check version.  Should be >= LCL_MIN_VERSION
00404   */
00405 
00406   if ((fgets (buf, BUFLEN, f) == NULL)
00407       || !mstring_equalPrefix (buf, ";;LCLint Dump:"))
00408     {
00409       loadllmsg (message ("Load library %s is not in LCLint library format.  Attempting "
00410                       "to continue without library.", name));
00411       return FALSE;
00412     }
00413   
00414   if (fgets (buf, BUFLEN, f) != NULL)
00415     {
00416       if (!mstring_equalPrefix (buf, ";;"))
00417         {
00418           loadllmsg (message ("Load library %s is not in LCLint library format.  Attempting "
00419                           "to continue without library.", name));
00420           return FALSE;
00421         }
00422       else if (mstring_equalPrefix (buf, ";;ctTable"))
00423         {
00424           loadllmsg (message ("Load library %s is in obsolete LCLint library format.  Attempting "
00425                           "to continue anyway, but results may be incorrect.  Rebuild "
00426                           "the library with this version of lclint.", 
00427                           name));
00428         }
00429       else 
00430         {
00431           float version = 0.0;
00432 
00433           if (sscanf (buf, ";;LCLint %f", &version) != 1)
00434             {
00435               loadllmsg (message ("Load library %s is not in LCLint library format (missing version "
00436                               "number).  Attempting "
00437                               "to continue without library.", name));
00438               return FALSE;
00439             }
00440           else
00441             {
00442               if ((LCL_MIN_VERSION - version) >= FLT_EPSILON)
00443                 {
00444                   cstring vname;
00445                   char *nl = strchr (buf, '\n');
00446 
00447                   *nl = '\0';
00448 
00449                   vname = cstring_fromChars (buf + 9);
00450 
00451                   loadllmsg (message ("Load library %s is in obsolete LCLint library "
00452                                       "format (version %s).  Attempting "
00453                                       "to continue anyway, but results may be incorrect.  Rebuild "
00454                                       "the library with this version of lclint.", 
00455                                       name, vname));
00456                 }
00457               else
00458                 {
00459                   if ((fgets (buf, BUFLEN, f) == NULL))
00460                     {
00461                       loadllmsg (message ("Load library %s is not in LCLint library "
00462                                           "format (missing library code). Attempting "
00463                                           "to continue without library.", name));
00464                       return FALSE;
00465                     }
00466                   else 
00467                     {
00468                       int lib;
00469                       
00470                       if (sscanf (buf, ";;lib:%d", &lib) != 1)
00471                         {
00472                           loadllmsg (message ("Load library %s is not in LCLint library "
00473                                               "format (missing library code). Attempting "
00474                                               "to continue without library.", name));
00475                           return FALSE;
00476                         }
00477                       else
00478                         {
00479                           flagcode code = (flagcode) lib;
00480 
00481                           if (flagcode_isLibraryFlag (code))
00482                             {
00483                               if (context_doMerge ()) 
00484                                 {
00485                                   context_setLibrary (code);
00486                                 }
00487                             }
00488                           else
00489                             {
00490                               loadllmsg (message ("Load library %s has invalid library code.  "
00491                                                   "Attempting to continue without library.",
00492                                                   name));
00493                               
00494                               return FALSE;
00495                             }
00496                         }
00497                     }
00498                 }
00499             }
00500         }
00501     }
00502   else
00503     {
00504       loadllmsg (message ("Load library %s is not in LCLint library format (missing lines).  "
00505                           "Attempting to continue without library.", name));
00506       return FALSE;
00507     }
00508   
00509   ctype_loadTable (f);
00510   printDot ();
00511   
00512   typeIdSet_loadTable (f);
00513   printDot ();
00514   
00515   usymtab_load (f);
00516   printDot ();
00517   
00518   context_loadModuleAccess (f);
00519   printDot ();
00520   
00521   return TRUE;
00522 }
00523 
00524 /*
00525 ** load state from file created by dumpState
00526 */
00527 
00528 void
00529 loadState (cstring cfname)
00530 {
00531   FILE *f;
00532   char *fname = cstring_toCharsSafe (cfname);
00533   cstring ofname = cstring_copy (cfname);
00534 
00535   fname = addExtension (fname, DUMP_SUFFIX);
00536 
00537   f = fopen (fname, "r");
00538 
00539   if (f == NULL)
00540     {
00541       if (context_getDebug (FLG_SHOWSCAN))
00542         fprintf (g_msgstream, " >\n");
00543 
00544       llfatalerror (message ("Cannot open dump file for loading: %s", cfname));
00545     }
00546   else
00547     {
00548       fileloc_reallyFree (g_currentloc);
00549       g_currentloc = fileloc_createLib (ofname);
00550 
00551       if (!loadStateFile (f, ofname)) 
00552         {
00553           if (!loadStandardState ()) 
00554             {
00555               ctype_initTable ();
00556             }
00557         }
00558       
00559       check (fclose (f) == 0);
00560     }
00561 
00562   cstring_free (ofname);
00563   sfree (fname);
00564 }
00565 

Generated at Fri Nov 3 18:57:42 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000