]> andersk Git - splint.git/blame - src/imports.c
OS/2 command line args fix provided by Herbert Martin Dietze.
[splint.git] / src / imports.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 University of Virginia,
616915dd 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
28bf4b0b 73 fprintf (outfptr, "%s", msg);
616915dd 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{
28bf4b0b 101 cstring infile = cstring_undefined;
102 filestatus status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSYMSNAME),
103 &infile);
616915dd 104
616915dd 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
28bf4b0b 115 (void) parseSignatures (cstring_fromCharsNew (CTRAITSYMSNAME));
116 (void) parseSignatures (infile);
616915dd 117 break;
118 case OSD_FILENOTFOUND:
119 /* try spec name */
28bf4b0b 120 status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSPECNAME),
121 &infile);
616915dd 122
123 if (status == OSD_FILEFOUND)
124 {
28bf4b0b 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);
616915dd 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)));
28bf4b0b 138 cstring_free (infile);
139 llexit (LLFAILURE);
616915dd 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)));
28bf4b0b 146 cstring_free (infile);
616915dd 147 break;
148 }
616915dd 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;
28bf4b0b 168 bool compressedFormat = FALSE;
169 inputStream imported, imported2, lclsource;
170 char *bufptr;
171 char *tmpbufptr;
172 char *cptr;
173 cstring name;
616915dd 174 lsymbol sym;
28bf4b0b 175 char importName[MAX_NAME_LENGTH + 1];
176 cstring importFileName;
177 cstring path = cstring_undefined;
178 cstring fpath, fpath2;
179 mapping map;
616915dd 180 filestatus ret;
181
28bf4b0b 182 importFileName = lsymbol_toString (importSymbol);
183 name = cstring_concat (importFileName, cstring_makeLiteralTemp (IO_SUFFIX));
616915dd 184
185 /*
186 ** find .lcs file
187 */
188
189 switch (kind)
190 {
191 case IMPPLAIN:
7272a1c1 192 path = message ("%s%c%s", cstring_fromChars (g_localSpecPath), PATH_SEPARATOR,
28bf4b0b 193 context_getLarchPath ());
194
616915dd 195 break;
196 case IMPBRACKET:
28bf4b0b 197 path = cstring_copy (context_getLCLImportDir ());
616915dd 198 break;
199 case IMPQUOTE:
28bf4b0b 200 path = cstring_fromCharsNew (g_localSpecPath);
616915dd 201 break;
202 default:
616915dd 203 llbuglit ("bad imports case\n");
204 }
205
28bf4b0b 206 if ((ret = osd_getPath (path, name, &fpath)) != OSD_FILEFOUND)
616915dd 207 {
28bf4b0b 208 cstring fname2;
616915dd 209
210 if (ret == OSD_PATHTOOLONG)
211 {
212 llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
213 }
214
28bf4b0b 215 imported2 = inputStream_create (cstring_copy (importFileName),
216 LCL_EXTENSION, FALSE);
217 fname2 = inputStream_fileName (imported2);
616915dd 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",
28bf4b0b 223 fpath2));
616915dd 224 }
225 else
226 {
227 if (kind == IMPPLAIN || kind == IMPQUOTE)
28bf4b0b 228 {
229 llfatalerrorLoc (message ("Cannot find file to import: %s", name));
230 }
616915dd 231 else
28bf4b0b 232 {
233 llfatalerrorLoc (message ("Cannot find standard import file: %s", name));
234 }
616915dd 235 }
236 }
237
238
28bf4b0b 239 imported = inputStream_create (fpath, cstring_makeLiteralTemp (IO_SUFFIX), FALSE);
240
241 readableP = inputStream_open (imported);
616915dd 242
243 if (!readableP)
244 { /* can't read ? */
245 llfatalerrorLoc (message ("Cannot open import file for reading: %s",
28bf4b0b 246 inputStream_fileName (imported)));
616915dd 247 }
248
28bf4b0b 249 bufptr = inputStream_nextLine (imported);
616915dd 250
251 if (bufptr == 0)
252 {
253 llerror (FLG_SYNTAX, message ("Import file is empty: %s",
28bf4b0b 254 inputStream_fileName (imported)));
255 cstring_free (name);
256 (void) inputStream_close (imported);
257 inputStream_free (imported);
616915dd 258
28bf4b0b 259 cstring_free (path);
616915dd 260 return;
261 }
262
263 /* was it processed successfully ? */
264 if (firstWord (bufptr, "%FAILED"))
265 {
266 llfatalerrorLoc
28bf4b0b 267 (message ("Imported file was not checked successfully: %s.", name));
616915dd 268 }
269
28bf4b0b 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 */
616915dd 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 {
28bf4b0b 287 /*
288 ** Only really old files start this way!
289 */
290
616915dd 291 cptr += 12;
292 if (*cptr != '2' && *cptr != '3')
293 {
28bf4b0b 294 llfatalerrorLoc (message ("Imported file %s is obsolete: %s.",
295 inputStream_fileName (imported),
296 cstring_fromChars (bufptr)));
616915dd 297 }
298 }
28bf4b0b 299
300 compressedFormat = FALSE;
616915dd 301 }
302 else
303 {
304 if (!firstWord (bufptr, "%LCS"))
305 {
28bf4b0b 306 llfatalerrorLoc (message ("Imported file %s is not in correct format: %s",
307 inputStream_fileName (imported),
616915dd 308 cstring_fromChars (bufptr)));
309 }
28bf4b0b 310
311 compressedFormat = TRUE;
616915dd 312 }
313
314 /* push the imported LCL spec onto g_currentImports */
315
316 context_enterImport ();
317
28bf4b0b 318 bufptr = inputStream_nextLine (imported);
616915dd 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,
28bf4b0b 338 message ("Imports cycle: %s%s imports %s",
339 importFileName,
340 LCL_EXTENSION,
616915dd 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",
28bf4b0b 352 name,
616915dd 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
28bf4b0b 363 if (!compressedFormat)
616915dd 364 {
28bf4b0b 365 sort_import (imported, tok, map);
616915dd 366 }
28bf4b0b 367
616915dd 368 (void) sort_setExporting (oldexporting);
28bf4b0b 369
616915dd 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
28bf4b0b 374 if (!compressedFormat)
616915dd 375 {
376 symtable_import (imported, tok, map);
377 }
378 else
379 {
380 /* symtable_loadImport (imported, tok, map); */
381 }
382
28bf4b0b 383 check (inputStream_close (imported));
384 inputStream_free (imported);
385
386 mapping_free (map);
387 cstring_free (name);
388 cstring_free (path);
616915dd 389
390 context_leaveImport ();
391}
392
393
394
This page took 0.106463 seconds and 5 git commands to generate.