2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** module for importing LCL specs.
31 ** Massachusetts Institute of Technology
34 # include "splintMacros.nf"
38 # include "lslparse.h"
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
);
48 FILE *outfptr
= fileTable_openWriteFile (context_fileTable (), cstring_fromChars (outfile
));
51 DPRINTF (("Output lcl file: %s / %s / %s", path
, specname
, outfile
));
53 /* check write permission */
55 if (outfptr
== NULL
) /* Cannot open file */
59 lclplainerror (message ("Cannot write to output file: %s",
60 cstring_fromChars (outfile
)));
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
));
95 cstring infile
= cstring_undefined
;
96 filestatus status
= osd_getPath (context_getLarchPath (),
97 cstring_makeLiteralTemp (CTRAITSYMSNAME
),
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
110 (void) parseSignatures (cstring_fromCharsNew (CTRAITSYMSNAME
));
111 (void) parseSignatures (infile
);
113 case OSD_FILENOTFOUND
:
115 status
= osd_getPath (context_getLarchPath (),
116 cstring_makeLiteralTemp (CTRAITSPECNAME
),
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
);
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
);
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
);
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"
161 processImport (lsymbol importSymbol
, ltoken tok
, impkind kind
)
163 bool readableP
, oldexporting
;
164 bool compressedFormat
= FALSE
;
165 inputStream imported
, imported2
;
170 char importName
[MAX_NAME_LENGTH
+ 1];
171 cstring importFileName
;
172 cstring path
= cstring_undefined
;
173 cstring fpath
, fpath2
;
177 importFileName
= lsymbol_toString (importSymbol
);
178 name
= cstring_concat (importFileName
, cstring_makeLiteralTemp (IO_SUFFIX
));
187 path
= osd_pathListConcat (g_localSpecPath
,
188 cstring_toCharsSafe (context_getLarchPath ()));
192 path
= cstring_copy (context_getLCLImportDir ());
195 path
= cstring_fromCharsNew (g_localSpecPath
);
198 llbuglit ("bad imports case\n");
201 if ((ret
= osd_getPath (path
, name
, &fpath
)) != OSD_FILEFOUND
)
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
)
217 (message ("Specs must be processed before it can be imported: %s",
222 if (kind
== IMPPLAIN
|| kind
== IMPQUOTE
)
224 llfatalerrorLoc (message ("Cannot find file to import: %s", name
));
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
);
240 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
241 inputStream_fileName (imported
)));
244 bufptr
= inputStream_nextLine (imported
);
248 llerror (FLG_SYNTAX
, message ("Import file is empty: %s",
249 inputStream_fileName (imported
)));
251 (void) inputStream_close (imported
);
252 inputStream_free (imported
);
258 /* was it processed successfully ? */
259 if (firstWord (bufptr
, "%FAILED"))
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.* */
278 cptr
= strstr (bufptr
, "LCP Version");
283 ** Only really old files start this way!
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
;
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. */
330 message ("Imports cycle: %s%s imports %s",
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); */
342 lclfatalerror (tok
, message ("Unexpected line in imported file %s: %s",
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
);
371 /* symtable_loadImport (imported, tok, map); */
374 check (inputStream_close (imported
));
375 inputStream_free (imported
);
381 context_leaveImport ();