2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
27 ** module for importing LCL specs.
31 ** Massachusetts Institute of Technology
34 # include "lclintMacros.nf"
37 # include "llgrammar.h" /* need simpleOp, MULOP and logicalOp in makeInfixTermNode */
39 # include "checking.h"
41 # include "lslparse.h"
48 outputLCSFile (char *path, char *msg, char *specname)
50 static bool haserror = FALSE;
51 char *sfile = mstring_concat (specname, ".lcs");
52 char *outfile = mstring_concat (path, sfile);
54 FILE *outfptr = fopen (outfile, "w");
57 DPRINTF (("Output lcl file: %s / %s / %s", path, specname, outfile));
59 /* check write permission */
65 lclplainerror (message ("Cannot write to output file: %s",
66 cstring_fromChars (outfile)));
73 fprintf (outfptr, msg);
74 fprintf (outfptr, "%s\n", LCL_PARSE_VERSION);
76 /* output line %LCLimports foo bar ... */
77 fprintf (outfptr, "%%LCLimports ");
79 lsymbolSet_elements (g_currentImports, sym)
81 s = lsymbol_toChars (sym);
83 if (s != NULL && !mstring_equal (s, specname))
85 fprintf (outfptr, "%s ", s);
87 } end_lsymbolSet_elements;
89 fprintf (outfptr, "\n");
91 sort_dump (outfptr, TRUE);
92 symtable_dump (g_symtab, outfptr, TRUE);
94 check (fclose (outfptr) == 0);
101 char **infile = (char **) dmalloc (sizeof (*infile));
102 filestatus status = osd_findOnLarchPath (CTRAITSYMSNAME, infile);
109 ** This line was missing before version 2.3f. Bug fix by Mike Smith.
110 ** This looks like a bug - infile is already fully qualified path
111 ** parseSignatures() adds another path to the front and fails to
115 (void) parseSignatures (cstring_fromChars (CTRAITSYMSNAME));
116 (void) parseSignatures (cstring_fromChars (*infile));
118 case OSD_FILENOTFOUND:
120 status = osd_findOnLarchPath (CTRAITSPECNAME, infile);
122 if (status == OSD_FILEFOUND)
124 callLSL (CTRAITSPECNAME,
126 (message ("includes %s (%s for String)",
127 cstring_fromChars (CTRAITFILENAMEN),
128 cstring_fromChars (sort_getName (sort_cstring)))));
134 (message ("Unable to find %s or %s. Check LARCH_PATH environment variable.",
135 cstring_fromChars (CTRAITSYMSNAME),
136 cstring_fromChars (CTRAITSPECNAME)));
139 case OSD_PATHTOOLONG:
140 lclbug (message ("importCTrait: the concatenated directory and file "
141 "name are too long: %s: "
142 "continuing without it",
143 cstring_fromChars (CTRAITSPECNAME)));
152 ** processImport --- load imports from file
154 ** impkind: IMPPLAIN file on SPEC_PATH
155 ** # include "./file.h" if it exists,
156 ** # include "<directory where spec was found>/file.h" if not.
157 ** (warn if neither exists)
158 ** IMPBRACKET file in default LCL imports directory
159 ** # include <file.h>
160 ** IMPQUOTE file directly
161 ** # include "file.h"
165 processImport (lsymbol importSymbol, ltoken tok, impkind kind)
167 bool readableP, oldexporting;
168 bool oldFormat = FALSE;
169 tsource *imported, *imported2, *lclsource;
170 char *bufptr, *tmpbufptr, *cptr;
173 char importName[MAX_NAME_LENGTH + 1], *importFileName, *realfname;
175 char *fpath, *fpath2;
179 importFileName = lsymbol_toCharsSafe (importSymbol);
180 name = mstring_concat (importFileName, IO_SUFFIX);
190 path = cstring_toCharsSafe
191 (message ("%s%c%s", cstring_fromChars (g_localSpecPath), SEPCHAR, context_getLarchPath ()));
195 path = mstring_copy (cstring_toCharsSafe (context_getLCLImportDir ()));
198 path = mstring_copy (g_localSpecPath);
201 path = mstring_createEmpty (); /* suppress gcc error message */
202 llbuglit ("bad imports case\n");
205 if ((ret = osd_getPath (path, realfname, &fpath)) != OSD_FILEFOUND)
209 if (ret == OSD_PATHTOOLONG)
211 llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
214 imported2 = tsource_create (importFileName, LCL_SUFFIX, FALSE);
215 fname2 = tsource_fileName (imported2);
219 if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
222 (message ("Specs must be processed before it can be imported: %s",
223 cstring_fromChars (fpath2)));
227 if (kind == IMPPLAIN || kind == IMPQUOTE)
228 llfatalerrorLoc (message ("Cannot find file to import: %s",
229 cstring_fromChars (realfname)));
231 llfatalerrorLoc (message ("Cannot find standard import file: %s",
232 cstring_fromChars (realfname)));
237 imported = tsource_create (fpath, IO_SUFFIX, FALSE);
240 readableP = tsource_open (imported);
244 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
245 cstring_fromChars (tsource_fileName (imported))));
248 bufptr = tsource_nextLine (imported);
252 llerror (FLG_SYNTAX, message ("Import file is empty: %s",
253 cstring_fromChars (tsource_fileName (imported))));
255 (void) tsource_close (imported);
256 tsource_free (imported);
262 /* was it processed successfully ? */
263 if (firstWord (bufptr, "%FAILED"))
266 (message ("Imported file was not checked successfully: %s.",
267 cstring_fromChars (name)));
270 /** is it generated by the right version of the checker?
272 ** old .lcs files start with %PASSED
273 ** new (compressed) files start with %LCS
276 if (firstWord (bufptr, "%PASSED"))
278 /* %PASSED Output from LCP Version 2.* and 3.* */
282 cptr = strstr (bufptr, "LCP Version");
287 if (*cptr != '2' && *cptr != '3')
289 llfatalerrorLoc (message ("Imported file is obsolete: %s.",
290 cstring_fromChars (bufptr)));
297 if (!firstWord (bufptr, "%LCS"))
299 llfatalerrorLoc (message ("Imported file is not in correct format: %s.",
300 cstring_fromChars (bufptr)));
304 /* push the imported LCL spec onto g_currentImports */
306 context_enterImport ();
308 bufptr = tsource_nextLine (imported);
309 llassert (bufptr != NULL);
313 /* expect %LCLimports foo bar ... */
314 if (firstWord (bufptr, "%LCLimports "))
316 bufptr = bufptr + strlen ("%LCLimports ");
317 while (sscanf (bufptr, "%s", importName) == 1)
319 bufptr = bufptr + strlen (importName) + 1; /* 1 for space */
320 sym = lsymbol_fromChars (importName);
321 if (sym == importSymbol ||
322 lsymbolSet_member (g_currentImports, sym))
324 /* ensure that the import list does not contain itself: an
325 invariant useful for checking imports cycles. */
326 lclsource = LCLScanSource ();
328 message ("Imports cycle: %s.lcl imports %s",
329 cstring_fromChars (importFileName),
330 cstring_fromChars (importName)));
332 /* push them onto g_currentImports */
333 /* evs - 94 Apr 3: I don't think it should do this! */
334 /* (void) lsymbolSet_insert (g_currentImports, sym); */
339 lclsource = LCLScanSource ();
340 lclfatalerror (tok, message ("Unexpected line in imported file %s: %s",
341 cstring_fromChars (name),
342 cstring_fromChars (bufptr)));
345 /* read in the imported info */
346 oldexporting = sort_setExporting (TRUE);
348 map = mapping_create ();
350 /* tok for error line numbering */
354 sort_import (imported, tok, map);
357 (void) sort_setExporting (oldexporting);
359 /* sort_import updates a mapping of old anonymous sorts to new
360 anonymous sort that is needed in symtable_import */
361 /* mapping_print (map); */
365 symtable_import (imported, tok, map);
369 /* symtable_loadImport (imported, tok, map); */
372 check (tsource_close (imported));
373 tsource_free (imported);
379 context_leaveImport ();