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

imports.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 ** imports.c
00026 **
00027 ** module for importing LCL specs.
00028 **
00029 **  AUTHOR:
00030 **      Yang Meng Tan,
00031 **         Massachusetts Institute of Technology
00032 */
00033 
00034 # include "lclintMacros.nf"
00035 # include "llbasic.h" 
00036 # include "osd.h"
00037 # include "llgrammar.h" /* need simpleOp, MULOP and logicalOp in makeInfixTermNode */
00038 # include "lclscan.h"
00039 # include "checking.h"
00040 # include "imports.h"
00041 # include "lslparse.h"
00042 # include "lh.h"
00043 # include "llmain.h"
00044 # include "portab.h"
00045 # include "herald.h"
00046 
00047 void
00048 outputLCSFile (char *path, char *msg, char *specname)
00049 {
00050   static bool haserror = FALSE;
00051   char *sfile = mstring_concat (specname, ".lcs");
00052   char *outfile = mstring_concat (path, sfile);
00053   char *s;
00054   FILE *outfptr = fopen (outfile, "w");
00055   sfree (sfile);
00056 
00057   DPRINTF (("Output lcl file: %s / %s / %s", path, specname, outfile));
00058   
00059   /* check write permission */
00060   
00061   if (outfptr == 0)
00062     {                           /* fopen fails */
00063       if (!haserror)
00064         {
00065           lclplainerror (message ("Cannot write to output file: %s", 
00066                                   cstring_fromChars (outfile)));
00067           haserror = TRUE;
00068         }
00069       sfree (outfile);
00070       return;
00071     }
00072 
00073   fprintf (outfptr, msg);
00074   fprintf (outfptr, "%s\n", LCL_PARSE_VERSION);
00075   
00076   /* output line %LCLimports foo bar ... */
00077   fprintf (outfptr, "%%LCLimports ");
00078 
00079   lsymbolSet_elements (g_currentImports, sym)
00080     {
00081       s = lsymbol_toChars (sym);
00082 
00083       if (s != NULL && !mstring_equal (s, specname))
00084         {
00085           fprintf (outfptr, "%s ", s);
00086         }
00087     } end_lsymbolSet_elements;
00088   
00089   fprintf (outfptr, "\n");
00090   
00091   sort_dump (outfptr, TRUE);
00092   symtable_dump (g_symtab, outfptr, TRUE);
00093 
00094   check (fclose (outfptr) == 0);  
00095   sfree (outfile);  
00096 }
00097 
00098 void
00099 importCTrait (void)
00100 {
00101   char **infile = (char **) dmalloc (sizeof (*infile));
00102   filestatus status = osd_findOnLarchPath (CTRAITSYMSNAME, infile);
00103 
00104   
00105   switch (status)
00106     {
00107     case OSD_FILEFOUND:
00108       /*
00109       ** This line was missing before version 2.3f.  Bug fix by Mike Smith.
00110       **    This looks like a bug - infile is already fully qualified path  
00111       **    parseSignatures() adds another path to the front and fails to   
00112       **    open the file.                                                  
00113       */
00114            
00115       (void) parseSignatures (cstring_fromChars (CTRAITSYMSNAME));
00116       (void) parseSignatures (cstring_fromChars (*infile));
00117       break;
00118     case OSD_FILENOTFOUND:
00119       /* try spec name */
00120       status = osd_findOnLarchPath (CTRAITSPECNAME, infile);
00121 
00122       if (status == OSD_FILEFOUND)
00123         {
00124           callLSL (CTRAITSPECNAME,
00125                    cstring_toCharsSafe
00126                    (message ("includes %s (%s for String)",
00127                              cstring_fromChars (CTRAITFILENAMEN), 
00128                              cstring_fromChars (sort_getName (sort_cstring)))));
00129           break;
00130         }
00131       else
00132         {
00133           lldiagmsg 
00134             (message ("Unable to find %s or %s.  Check LARCH_PATH environment variable.",
00135                       cstring_fromChars (CTRAITSYMSNAME), 
00136                       cstring_fromChars (CTRAITSPECNAME)));
00137           llexit (LLFAILURE);
00138         }
00139     case OSD_PATHTOOLONG:
00140       lclbug (message ("importCTrait: the concatenated directory and file "
00141                        "name are too long: %s: "
00142                        "continuing without it", 
00143                        cstring_fromChars (CTRAITSPECNAME)));
00144       break;
00145     }
00146 
00147   sfree (*infile);
00148   sfree (infile);
00149 }
00150 
00151 /*
00152 ** processImport --- load imports from file
00153 **
00154 **    impkind: IMPPLAIN  file on SPEC_PATH
00155 **                       # include "./file.h" if it exists,
00156 **                       # include "<directory where spec was found>/file.h" if not.
00157 **                         (warn if neither exists)
00158 **            IMPBRACKET file in default LCL imports directory
00159 **                       # include <file.h>
00160 **            IMPQUOTE   file directly
00161 **                       # include "file.h"
00162 */
00163 
00164 void
00165 processImport (lsymbol importSymbol, ltoken tok, impkind kind)
00166 {
00167   bool readableP, oldexporting;
00168   bool oldFormat = FALSE;
00169   tsource *imported, *imported2, *lclsource;
00170   char *bufptr, *tmpbufptr, *cptr;
00171   char *name;
00172   lsymbol sym;
00173   char importName[MAX_NAME_LENGTH + 1], *importFileName, *realfname;
00174   char *path;
00175   char *fpath, *fpath2;
00176   mapping *map;
00177   filestatus ret;
00178 
00179   importFileName = lsymbol_toCharsSafe (importSymbol);
00180   name = mstring_concat (importFileName, IO_SUFFIX);
00181   realfname = name;
00182 
00183   /*
00184   ** find .lcs file
00185   */
00186   
00187   switch (kind)
00188     {
00189     case IMPPLAIN:
00190       path = cstring_toCharsSafe 
00191         (message ("%s%c%s", cstring_fromChars (g_localSpecPath), SEPCHAR, context_getLarchPath ()));
00192       
00193       break;
00194     case IMPBRACKET:
00195       path = mstring_copy (cstring_toCharsSafe (context_getLCLImportDir ()));
00196       break;
00197     case IMPQUOTE:
00198       path = mstring_copy (g_localSpecPath);
00199       break;
00200     default:
00201       path = mstring_createEmpty (); /* suppress gcc error message */
00202       llbuglit ("bad imports case\n");
00203     }
00204 
00205   if ((ret = osd_getPath (path, realfname, &fpath)) != OSD_FILEFOUND)
00206     {
00207       char *fname2;
00208       
00209       if (ret == OSD_PATHTOOLONG)
00210         {
00211           llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
00212         }
00213       
00214       imported2 = tsource_create (importFileName, LCL_SUFFIX, FALSE);
00215       fname2 = tsource_fileName (imported2);
00216       
00217       
00218 
00219       if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
00220         {
00221           llfatalerrorLoc
00222             (message ("Specs must be processed before it can be imported: %s", 
00223                       cstring_fromChars (fpath2)));
00224         }
00225       else
00226         {
00227           if (kind == IMPPLAIN || kind == IMPQUOTE)
00228             llfatalerrorLoc (message ("Cannot find file to import: %s", 
00229                                        cstring_fromChars (realfname)));
00230           else
00231             llfatalerrorLoc (message ("Cannot find standard import file: %s",
00232                                        cstring_fromChars (realfname)));
00233         }
00234     }
00235 
00236   
00237   imported = tsource_create (fpath, IO_SUFFIX, FALSE);
00238   
00239   
00240   readableP = tsource_open (imported);
00241     
00242   if (!readableP)
00243     {                   /* can't read ? */
00244       llfatalerrorLoc (message ("Cannot open import file for reading: %s",
00245                                  cstring_fromChars (tsource_fileName (imported))));
00246     }
00247 
00248   bufptr = tsource_nextLine (imported);
00249 
00250   if (bufptr == 0)
00251     {
00252       llerror (FLG_SYNTAX, message ("Import file is empty: %s", 
00253                                     cstring_fromChars (tsource_fileName (imported))));
00254       sfree (name);
00255       (void) tsource_close (imported);
00256       tsource_free (imported);
00257 
00258       sfree (path);
00259       return;
00260     }
00261 
00262   /* was it processed successfully ? */
00263   if (firstWord (bufptr, "%FAILED"))
00264     {
00265       llfatalerrorLoc
00266         (message ("Imported file was not checked successfully: %s.", 
00267                   cstring_fromChars (name)));
00268     }
00269   
00276   if (firstWord (bufptr, "%PASSED"))
00277     {
00278       /* %PASSED Output from LCP Version 2.* and 3.* */
00279       /*                     1234567890123*/
00280       /*                                 +*/
00281 
00282       cptr = strstr (bufptr, "LCP Version");
00283       
00284       if (cptr != NULL)
00285         {
00286           cptr += 12;
00287           if (*cptr != '2' && *cptr != '3')
00288             {
00289               llfatalerrorLoc (message ("Imported file is obsolete: %s.",
00290                                          cstring_fromChars (bufptr)));
00291             }
00292         }
00293       oldFormat = TRUE;
00294     }
00295   else 
00296     {
00297       if (!firstWord (bufptr, "%LCS"))
00298         {
00299           llfatalerrorLoc (message ("Imported file is not in correct format: %s.",
00300                                     cstring_fromChars (bufptr)));
00301         }
00302     }
00303   
00304   /* push the imported LCL spec onto g_currentImports */
00305 
00306   context_enterImport ();
00307   
00308   bufptr = tsource_nextLine (imported);
00309   llassert (bufptr != NULL);
00310 
00311   tmpbufptr = bufptr;
00312 
00313     /* expect %LCLimports foo bar ... */
00314   if (firstWord (bufptr, "%LCLimports "))
00315     {
00316       bufptr = bufptr + strlen ("%LCLimports ");
00317       while (sscanf (bufptr, "%s", importName) == 1)
00318         {
00319           bufptr = bufptr + strlen (importName) + 1;    /* 1 for space */
00320           sym = lsymbol_fromChars (importName);
00321           if (sym == importSymbol || 
00322               lsymbolSet_member (g_currentImports, sym))
00323             {
00324               /* ensure that the import list does not contain itself: an
00325                  invariant useful for checking imports cycles. */
00326               lclsource = LCLScanSource ();
00327               lclfatalerror (tok, 
00328                              message ("Imports cycle: %s.lcl imports %s",
00329                                       cstring_fromChars (importFileName),
00330                                       cstring_fromChars (importName)));
00331             }     
00332           /* push them onto g_currentImports */
00333           /* evs - 94 Apr 3:  I don't think it should do this! */
00334           /* (void) lsymbolSet_insert (g_currentImports, sym); */
00335         }
00336     }
00337   else
00338     {
00339       lclsource = LCLScanSource ();
00340       lclfatalerror (tok, message ("Unexpected line in imported file %s: %s", 
00341                                    cstring_fromChars (name), 
00342                                    cstring_fromChars (bufptr)));
00343     }
00344           
00345   /* read in the imported info */
00346   oldexporting = sort_setExporting (TRUE);
00347 
00348   map = mapping_create ();
00349 
00350   /* tok for error line numbering */
00351 
00352   if (oldFormat)
00353     {
00354             sort_import (imported, tok, map);   
00355     }
00356 
00357   (void) sort_setExporting (oldexporting);
00358 
00359   /* sort_import updates a mapping of old anonymous sorts to new
00360      anonymous sort that is needed in symtable_import */
00361   /* mapping_print (map); */
00362   
00363   if (oldFormat)
00364     {
00365       symtable_import (imported, tok, map);
00366     }
00367   else
00368     {
00369       /* symtable_loadImport (imported, tok, map); */
00370     }
00371   
00372   check (tsource_close (imported));
00373   tsource_free (imported);
00374 
00375   sfree (map);
00376   sfree (name);
00377   sfree (path);
00378 
00379   context_leaveImport ();  
00380 }
00381 
00382 
00383 

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