2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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, "%s", 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 cstring infile = cstring_undefined;
102 filestatus status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSYMSNAME),
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_fromCharsNew (CTRAITSYMSNAME));
116 (void) parseSignatures (infile);
118 case OSD_FILENOTFOUND:
120 status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSPECNAME),
123 if (status == OSD_FILEFOUND)
125 callLSL (cstring_makeLiteralTemp (CTRAITSPECNAME),
126 message ("includes %s (%s for String)",
127 cstring_fromChars (CTRAITFILENAMEN),
128 cstring_fromChars (sort_getName (sort_cstring))));
129 cstring_free (infile);
135 (message ("Unable to find %s or %s. Check LARCH_PATH environment variable.",
136 cstring_fromChars (CTRAITSYMSNAME),
137 cstring_fromChars (CTRAITSPECNAME)));
138 cstring_free (infile);
141 case OSD_PATHTOOLONG:
142 lclbug (message ("importCTrait: the concatenated directory and file "
143 "name are too long: %s: "
144 "continuing without it",
145 cstring_fromChars (CTRAITSPECNAME)));
146 cstring_free (infile);
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 compressedFormat = FALSE;
169 inputStream imported, imported2, lclsource;
175 char importName[MAX_NAME_LENGTH + 1];
176 cstring importFileName;
177 cstring path = cstring_undefined;
178 cstring fpath, fpath2;
182 importFileName = lsymbol_toString (importSymbol);
183 name = cstring_concat (importFileName, cstring_makeLiteralTemp (IO_SUFFIX));
192 path = message ("%s%c%s", cstring_fromChars (g_localSpecPath), SEPCHAR,
193 context_getLarchPath ());
197 path = cstring_copy (context_getLCLImportDir ());
200 path = cstring_fromCharsNew (g_localSpecPath);
203 llbuglit ("bad imports case\n");
206 if ((ret = osd_getPath (path, name, &fpath)) != OSD_FILEFOUND)
210 if (ret == OSD_PATHTOOLONG)
212 llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
215 imported2 = inputStream_create (cstring_copy (importFileName),
216 LCL_EXTENSION, FALSE);
217 fname2 = inputStream_fileName (imported2);
219 if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
222 (message ("Specs must be processed before it can be imported: %s",
227 if (kind == IMPPLAIN || kind == IMPQUOTE)
229 llfatalerrorLoc (message ("Cannot find file to import: %s", name));
233 llfatalerrorLoc (message ("Cannot find standard import file: %s", name));
239 imported = inputStream_create (fpath, cstring_makeLiteralTemp (IO_SUFFIX), FALSE);
241 readableP = inputStream_open (imported);
245 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
246 inputStream_fileName (imported)));
249 bufptr = inputStream_nextLine (imported);
253 llerror (FLG_SYNTAX, message ("Import file is empty: %s",
254 inputStream_fileName (imported)));
256 (void) inputStream_close (imported);
257 inputStream_free (imported);
263 /* was it processed successfully ? */
264 if (firstWord (bufptr, "%FAILED"))
267 (message ("Imported file was not checked successfully: %s.", name));
271 ** Is it generated by the right version of the checker?
273 ** Uncompressed .lcs files start with %PASSED
274 ** Compressed files start with %LCS
277 if (firstWord (bufptr, "%PASSED"))
279 /* %PASSED Output from LCP Version 2.* and 3.* */
283 cptr = strstr (bufptr, "LCP Version");
288 ** Only really old files start this way!
292 if (*cptr != '2' && *cptr != '3')
294 llfatalerrorLoc (message ("Imported file %s is obsolete: %s.",
295 inputStream_fileName (imported),
296 cstring_fromChars (bufptr)));
300 compressedFormat = FALSE;
304 if (!firstWord (bufptr, "%LCS"))
306 llfatalerrorLoc (message ("Imported file %s is not in correct format: %s",
307 inputStream_fileName (imported),
308 cstring_fromChars (bufptr)));
311 compressedFormat = TRUE;
314 /* push the imported LCL spec onto g_currentImports */
316 context_enterImport ();
318 bufptr = inputStream_nextLine (imported);
319 llassert (bufptr != NULL);
323 /* expect %LCLimports foo bar ... */
324 if (firstWord (bufptr, "%LCLimports "))
326 bufptr = bufptr + strlen ("%LCLimports ");
327 while (sscanf (bufptr, "%s", importName) == 1)
329 bufptr = bufptr + strlen (importName) + 1; /* 1 for space */
330 sym = lsymbol_fromChars (importName);
331 if (sym == importSymbol ||
332 lsymbolSet_member (g_currentImports, sym))
334 /* ensure that the import list does not contain itself: an
335 invariant useful for checking imports cycles. */
336 lclsource = LCLScanSource ();
338 message ("Imports cycle: %s%s imports %s",
341 cstring_fromChars (importName)));
343 /* push them onto g_currentImports */
344 /* evs - 94 Apr 3: I don't think it should do this! */
345 /* (void) lsymbolSet_insert (g_currentImports, sym); */
350 lclsource = LCLScanSource ();
351 lclfatalerror (tok, message ("Unexpected line in imported file %s: %s",
353 cstring_fromChars (bufptr)));
356 /* read in the imported info */
357 oldexporting = sort_setExporting (TRUE);
359 map = mapping_create ();
361 /* tok for error line numbering */
363 if (!compressedFormat)
365 sort_import (imported, tok, map);
368 (void) sort_setExporting (oldexporting);
370 /* sort_import updates a mapping of old anonymous sorts to new
371 anonymous sort that is needed in symtable_import */
372 /* mapping_print (map); */
374 if (!compressedFormat)
376 symtable_import (imported, tok, map);
380 /* symtable_loadImport (imported, tok, map); */
383 check (inputStream_close (imported));
384 inputStream_free (imported);
390 context_leaveImport ();