]> andersk Git - splint.git/blame_incremental - src/imports.c
changed PLUS to BINARYOP_PLUS
[splint.git] / src / imports.c
... / ...
CommitLineData
1/*
2** LCLint - annotation-assisted static program checker
3** Copyright (C) 1994-2001 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.
19**
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
23*/
24/*
25** imports.c
26**
27** module for importing LCL specs.
28**
29** AUTHOR:
30** Yang Meng Tan,
31** Massachusetts Institute of Technology
32*/
33
34# include "lclintMacros.nf"
35# include "llbasic.h"
36# include "osd.h"
37# include "llgrammar.h" /* need simpleOp, MULOP and logicalOp in makeInfixTermNode */
38# include "lclscan.h"
39# include "checking.h"
40# include "imports.h"
41# include "lslparse.h"
42# include "lh.h"
43# include "llmain.h"
44# include "portab.h"
45# include "herald.h"
46
47void
48outputLCSFile (char *path, char *msg, char *specname)
49{
50 static bool haserror = FALSE;
51 char *sfile = mstring_concat (specname, ".lcs");
52 char *outfile = mstring_concat (path, sfile);
53 char *s;
54 FILE *outfptr = fopen (outfile, "w");
55 sfree (sfile);
56
57 DPRINTF (("Output lcl file: %s / %s / %s", path, specname, outfile));
58
59 /* check write permission */
60
61 if (outfptr == 0)
62 { /* fopen fails */
63 if (!haserror)
64 {
65 lclplainerror (message ("Cannot write to output file: %s",
66 cstring_fromChars (outfile)));
67 haserror = TRUE;
68 }
69 sfree (outfile);
70 return;
71 }
72
73 fprintf (outfptr, "%s", msg);
74 fprintf (outfptr, "%s\n", LCL_PARSE_VERSION);
75
76 /* output line %LCLimports foo bar ... */
77 fprintf (outfptr, "%%LCLimports ");
78
79 lsymbolSet_elements (g_currentImports, sym)
80 {
81 s = lsymbol_toChars (sym);
82
83 if (s != NULL && !mstring_equal (s, specname))
84 {
85 fprintf (outfptr, "%s ", s);
86 }
87 } end_lsymbolSet_elements;
88
89 fprintf (outfptr, "\n");
90
91 sort_dump (outfptr, TRUE);
92 symtable_dump (g_symtab, outfptr, TRUE);
93
94 check (fclose (outfptr) == 0);
95 sfree (outfile);
96}
97
98void
99importCTrait (void)
100{
101 cstring infile = cstring_undefined;
102 filestatus status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSYMSNAME),
103 &infile);
104
105 switch (status)
106 {
107 case OSD_FILEFOUND:
108 /*
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
112 ** open the file.
113 */
114
115 (void) parseSignatures (cstring_fromCharsNew (CTRAITSYMSNAME));
116 (void) parseSignatures (infile);
117 break;
118 case OSD_FILENOTFOUND:
119 /* try spec name */
120 status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSPECNAME),
121 &infile);
122
123 if (status == OSD_FILEFOUND)
124 {
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);
130 break;
131 }
132 else
133 {
134 lldiagmsg
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);
139 llexit (LLFAILURE);
140 }
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);
147 break;
148 }
149}
150
151/*
152** processImport --- load imports from file
153**
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"
162*/
163
164void
165processImport (lsymbol importSymbol, ltoken tok, impkind kind)
166{
167 bool readableP, oldexporting;
168 bool compressedFormat = FALSE;
169 inputStream imported, imported2, lclsource;
170 char *bufptr;
171 char *tmpbufptr;
172 char *cptr;
173 cstring name;
174 lsymbol sym;
175 char importName[MAX_NAME_LENGTH + 1];
176 cstring importFileName;
177 cstring path = cstring_undefined;
178 cstring fpath, fpath2;
179 mapping map;
180 filestatus ret;
181
182 importFileName = lsymbol_toString (importSymbol);
183 name = cstring_concat (importFileName, cstring_makeLiteralTemp (IO_SUFFIX));
184
185 /*
186 ** find .lcs file
187 */
188
189 switch (kind)
190 {
191 case IMPPLAIN:
192 path = message ("%s%c%s", cstring_fromChars (g_localSpecPath), PATH_SEPARATOR,
193 context_getLarchPath ());
194
195 break;
196 case IMPBRACKET:
197 path = cstring_copy (context_getLCLImportDir ());
198 break;
199 case IMPQUOTE:
200 path = cstring_fromCharsNew (g_localSpecPath);
201 break;
202 default:
203 llbuglit ("bad imports case\n");
204 }
205
206 if ((ret = osd_getPath (path, name, &fpath)) != OSD_FILEFOUND)
207 {
208 cstring fname2;
209
210 if (ret == OSD_PATHTOOLONG)
211 {
212 llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
213 }
214
215 imported2 = inputStream_create (cstring_copy (importFileName),
216 LCL_EXTENSION, FALSE);
217 fname2 = inputStream_fileName (imported2);
218
219 if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
220 {
221 llfatalerrorLoc
222 (message ("Specs must be processed before it can be imported: %s",
223 fpath2));
224 }
225 else
226 {
227 if (kind == IMPPLAIN || kind == IMPQUOTE)
228 {
229 llfatalerrorLoc (message ("Cannot find file to import: %s", name));
230 }
231 else
232 {
233 llfatalerrorLoc (message ("Cannot find standard import file: %s", name));
234 }
235 }
236 }
237
238
239 imported = inputStream_create (fpath, cstring_makeLiteralTemp (IO_SUFFIX), FALSE);
240
241 readableP = inputStream_open (imported);
242
243 if (!readableP)
244 { /* can't read ? */
245 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
246 inputStream_fileName (imported)));
247 }
248
249 bufptr = inputStream_nextLine (imported);
250
251 if (bufptr == 0)
252 {
253 llerror (FLG_SYNTAX, message ("Import file is empty: %s",
254 inputStream_fileName (imported)));
255 cstring_free (name);
256 (void) inputStream_close (imported);
257 inputStream_free (imported);
258
259 cstring_free (path);
260 return;
261 }
262
263 /* was it processed successfully ? */
264 if (firstWord (bufptr, "%FAILED"))
265 {
266 llfatalerrorLoc
267 (message ("Imported file was not checked successfully: %s.", name));
268 }
269
270 /*
271 ** Is it generated by the right version of the checker?
272 **
273 ** Uncompressed .lcs files start with %PASSED
274 ** Compressed files start with %LCS
275 */
276
277 if (firstWord (bufptr, "%PASSED"))
278 {
279 /* %PASSED Output from LCP Version 2.* and 3.* */
280 /* 1234567890123*/
281 /* +*/
282
283 cptr = strstr (bufptr, "LCP Version");
284
285 if (cptr != NULL)
286 {
287 /*
288 ** Only really old files start this way!
289 */
290
291 cptr += 12;
292 if (*cptr != '2' && *cptr != '3')
293 {
294 llfatalerrorLoc (message ("Imported file %s is obsolete: %s.",
295 inputStream_fileName (imported),
296 cstring_fromChars (bufptr)));
297 }
298 }
299
300 compressedFormat = FALSE;
301 }
302 else
303 {
304 if (!firstWord (bufptr, "%LCS"))
305 {
306 llfatalerrorLoc (message ("Imported file %s is not in correct format: %s",
307 inputStream_fileName (imported),
308 cstring_fromChars (bufptr)));
309 }
310
311 compressedFormat = TRUE;
312 }
313
314 /* push the imported LCL spec onto g_currentImports */
315
316 context_enterImport ();
317
318 bufptr = inputStream_nextLine (imported);
319 llassert (bufptr != NULL);
320
321 tmpbufptr = bufptr;
322
323 /* expect %LCLimports foo bar ... */
324 if (firstWord (bufptr, "%LCLimports "))
325 {
326 bufptr = bufptr + strlen ("%LCLimports ");
327 while (sscanf (bufptr, "%s", importName) == 1)
328 {
329 bufptr = bufptr + strlen (importName) + 1; /* 1 for space */
330 sym = lsymbol_fromChars (importName);
331 if (sym == importSymbol ||
332 lsymbolSet_member (g_currentImports, sym))
333 {
334 /* ensure that the import list does not contain itself: an
335 invariant useful for checking imports cycles. */
336 lclsource = LCLScanSource ();
337 lclfatalerror (tok,
338 message ("Imports cycle: %s%s imports %s",
339 importFileName,
340 LCL_EXTENSION,
341 cstring_fromChars (importName)));
342 }
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); */
346 }
347 }
348 else
349 {
350 lclsource = LCLScanSource ();
351 lclfatalerror (tok, message ("Unexpected line in imported file %s: %s",
352 name,
353 cstring_fromChars (bufptr)));
354 }
355
356 /* read in the imported info */
357 oldexporting = sort_setExporting (TRUE);
358
359 map = mapping_create ();
360
361 /* tok for error line numbering */
362
363 if (!compressedFormat)
364 {
365 sort_import (imported, tok, map);
366 }
367
368 (void) sort_setExporting (oldexporting);
369
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); */
373
374 if (!compressedFormat)
375 {
376 symtable_import (imported, tok, map);
377 }
378 else
379 {
380 /* symtable_loadImport (imported, tok, map); */
381 }
382
383 check (inputStream_close (imported));
384 inputStream_free (imported);
385
386 mapping_free (map);
387 cstring_free (name);
388 cstring_free (path);
389
390 context_leaveImport ();
391}
392
393
394
This page took 0.03517 seconds and 5 git commands to generate.