Various minor fixes for compiler/linter (other then splint itself) warnings.
[splint-patched.git] / src / imports.c
blob936cddab33ffe4db169d10bf43059d40d4f84bc6
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** imports.c
27 ** module for importing LCL specs.
29 ** AUTHOR:
30 ** Yang Meng Tan,
31 ** Massachusetts Institute of Technology
34 # include "splintMacros.nf"
35 # include "basic.h"
36 # include "osd.h"
37 # include "imports.h"
38 # include "lslparse.h"
39 # include "llmain.h"
41 void
42 outputLCSFile (char *path, char *msg, char *specname)
44 static bool haserror = FALSE;
45 char *sfile = mstring_concat (specname, ".lcs");
46 char *outfile = mstring_concat (path, sfile);
47 char *s;
48 FILE *outfptr = fileTable_openWriteFile (context_fileTable (), cstring_fromChars (outfile));
49 sfree (sfile);
51 DPRINTF (("Output lcl file: %s / %s / %s", path, specname, outfile));
53 /* check write permission */
55 if (outfptr == NULL) /* Cannot open file */
57 if (!haserror)
59 lclplainerror (message ("Cannot write to output file: %s",
60 cstring_fromChars (outfile)));
61 haserror = TRUE;
63 sfree (outfile);
64 return;
67 fprintf (outfptr, "%s", msg);
68 fprintf (outfptr, "%s\n", LCL_PARSE_VERSION);
70 /* output line %LCLimports foo bar ... */
71 fprintf (outfptr, "%%LCLimports ");
73 lsymbolSet_elements (g_currentImports, sym)
75 s = lsymbol_toChars (sym);
77 if (s != NULL && !mstring_equal (s, specname))
79 fprintf (outfptr, "%s ", s);
81 } end_lsymbolSet_elements;
83 fprintf (outfptr, "\n");
85 sort_dump (outfptr, TRUE);
86 symtable_dump (g_symtab, outfptr, TRUE);
88 check (fileTable_closeFile (context_fileTable (), outfptr));
89 sfree (outfile);
92 void
93 importCTrait (void)
95 cstring infile = cstring_undefined;
96 filestatus status = osd_getPath (context_getLarchPath (),
97 cstring_makeLiteralTemp (CTRAITSYMSNAME),
98 &infile);
100 switch (status)
102 case OSD_FILEFOUND:
104 ** This line was missing before version 2.3f. Bug fix by Mike Smith.
105 ** This looks like a bug - infile is already fully qualified path
106 ** parseSignatures() adds another path to the front and fails to
107 ** open the file.
110 (void) parseSignatures (cstring_fromCharsNew (CTRAITSYMSNAME));
111 (void) parseSignatures (infile);
112 break;
113 case OSD_FILENOTFOUND:
114 /* try spec name */
115 status = osd_getPath (context_getLarchPath (),
116 cstring_makeLiteralTemp (CTRAITSPECNAME),
117 &infile);
119 if (status == OSD_FILEFOUND)
121 callLSL (cstring_makeLiteralTemp (CTRAITSPECNAME),
122 message ("includes %s (%s for String)",
123 cstring_fromChars (CTRAITFILENAMEN),
124 cstring_fromChars (sort_getName (g_sortCstring))));
125 cstring_free (infile);
126 break;
128 else
130 lldiagmsg
131 (message ("Unable to find %s or %s. Check LARCH_PATH environment variable.",
132 cstring_fromChars (CTRAITSYMSNAME),
133 cstring_fromChars (CTRAITSPECNAME)));
134 cstring_free (infile);
135 llexit (LLFAILURE);
137 case OSD_PATHTOOLONG:
138 lclbug (message ("importCTrait: the concatenated directory and file "
139 "name are too long: %s: "
140 "continuing without it",
141 cstring_fromChars (CTRAITSPECNAME)));
142 cstring_free (infile);
143 break;
148 ** processImport --- load imports from file
150 ** impkind: IMPPLAIN file on SPEC_PATH
151 ** # include "./file.h" if it exists,
152 ** # include "<directory where spec was found>/file.h" if not.
153 ** (warn if neither exists)
154 ** IMPBRACKET file in default LCL imports directory
155 ** # include <file.h>
156 ** IMPQUOTE file directly
157 ** # include "file.h"
160 void
161 processImport (lsymbol importSymbol, ltoken tok, impkind kind)
163 bool readableP, oldexporting;
164 bool compressedFormat = FALSE;
165 inputStream imported, imported2;
166 char *bufptr;
167 char *cptr;
168 cstring name;
169 lsymbol sym;
170 char importName[MAX_NAME_LENGTH + 1];
171 cstring importFileName;
172 cstring path = cstring_undefined;
173 cstring fpath, fpath2;
174 mapping map;
175 filestatus ret;
177 importFileName = lsymbol_toString (importSymbol);
178 name = cstring_concat (importFileName, cstring_makeLiteralTemp (IO_SUFFIX));
181 ** find .lcs file
184 switch (kind)
186 case IMPPLAIN:
187 path = osd_pathListConcat (g_localSpecPath,
188 cstring_toCharsSafe (context_getLarchPath ()));
190 break;
191 case IMPBRACKET:
192 path = cstring_copy (context_getLCLImportDir ());
193 break;
194 case IMPQUOTE:
195 path = cstring_fromCharsNew (g_localSpecPath);
196 break;
197 default:
198 llbuglit ("bad imports case\n");
201 if ((ret = osd_getPath (path, name, &fpath)) != OSD_FILEFOUND)
203 cstring fname2;
205 if (ret == OSD_PATHTOOLONG)
207 llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
210 imported2 = inputStream_create (cstring_copy (importFileName),
211 LCL_EXTENSION, FALSE);
212 fname2 = inputStream_fileName (imported2);
214 if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
216 llfatalerrorLoc
217 (message ("Specs must be processed before it can be imported: %s",
218 fpath2));
220 else
222 if (kind == IMPPLAIN || kind == IMPQUOTE)
224 llfatalerrorLoc (message ("Cannot find file to import: %s", name));
226 else
228 llfatalerrorLoc (message ("Cannot find standard import file: %s", name));
234 imported = inputStream_create (fpath, cstring_makeLiteralTemp (IO_SUFFIX), FALSE);
236 readableP = inputStream_open (imported);
238 if (!readableP)
239 { /* can't read ? */
240 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
241 inputStream_fileName (imported)));
244 bufptr = inputStream_nextLine (imported);
246 if (bufptr == 0)
248 llerror (FLG_SYNTAX, message ("Import file is empty: %s",
249 inputStream_fileName (imported)));
250 cstring_free (name);
251 (void) inputStream_close (imported);
252 inputStream_free (imported);
254 cstring_free (path);
255 return;
258 /* was it processed successfully ? */
259 if (firstWord (bufptr, "%FAILED"))
261 llfatalerrorLoc
262 (message ("Imported file was not checked successfully: %s.", name));
266 ** Is it generated by the right version of the checker?
268 ** Uncompressed .lcs files start with %PASSED
269 ** Compressed files start with %LCS
272 if (firstWord (bufptr, "%PASSED"))
274 /* %PASSED Output from LCP Version 2.* and 3.* */
275 /* 1234567890123*/
276 /* +*/
278 cptr = strstr (bufptr, "LCP Version");
280 if (cptr != NULL)
283 ** Only really old files start this way!
286 cptr += 12;
287 if (*cptr != '2' && *cptr != '3')
289 llfatalerrorLoc (message ("Imported file %s is obsolete: %s.",
290 inputStream_fileName (imported),
291 cstring_fromChars (bufptr)));
295 compressedFormat = FALSE;
297 else
299 if (!firstWord (bufptr, "%LCS"))
301 llfatalerrorLoc (message ("Imported file %s is not in correct format: %s",
302 inputStream_fileName (imported),
303 cstring_fromChars (bufptr)));
306 compressedFormat = TRUE;
309 /* push the imported LCL spec onto g_currentImports */
311 context_enterImport ();
313 bufptr = inputStream_nextLine (imported);
314 llassert (bufptr != NULL);
316 /* expect %LCLimports foo bar ... */
317 if (firstWord (bufptr, "%LCLimports "))
319 bufptr = bufptr + strlen ("%LCLimports ");
320 while (sscanf (bufptr, "%s", importName) == 1)
322 bufptr = bufptr + strlen (importName) + 1; /* 1 for space */
323 sym = lsymbol_fromChars (importName);
324 if (sym == importSymbol ||
325 lsymbolSet_member (g_currentImports, sym))
327 /* ensure that the import list does not contain itself: an
328 invariant useful for checking imports cycles. */
329 lclfatalerror (tok,
330 message ("Imports cycle: %s%s imports %s",
331 importFileName,
332 LCL_EXTENSION,
333 cstring_fromChars (importName)));
335 /* push them onto g_currentImports */
336 /* evs - 94 Apr 3: I don't think it should do this! */
337 /* (void) lsymbolSet_insert (g_currentImports, sym); */
340 else
342 lclfatalerror (tok, message ("Unexpected line in imported file %s: %s",
343 name,
344 cstring_fromChars (bufptr)));
347 /* read in the imported info */
348 oldexporting = sort_setExporting (TRUE);
350 map = mapping_create ();
352 /* tok for error line numbering */
354 if (!compressedFormat)
356 sort_import (imported, tok, map);
359 (void) sort_setExporting (oldexporting);
361 /* sort_import updates a mapping of old anonymous sorts to new
362 anonymous sort that is needed in symtable_import */
363 /* mapping_print (map); */
365 if (!compressedFormat)
367 symtable_import (imported, tok, map);
369 else
371 /* symtable_loadImport (imported, tok, map); */
374 check (inputStream_close (imported));
375 inputStream_free (imported);
377 mapping_free (map);
378 cstring_free (name);
379 cstring_free (path);
381 context_leaveImport ();