]> andersk Git - splint.git/blob - src/imports.c
Making fixes for Microsoft Visual C++ compiler.
[splint.git] / src / imports.c
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.
19 **
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
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 "splintMacros.nf"
35 # include "basic.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
45 void
46 outputLCSFile (char *path, char *msg, char *specname)
47 {
48   static bool haserror = FALSE;
49   char *sfile = mstring_concat (specname, ".lcs");
50   char *outfile = mstring_concat (path, sfile);
51   char *s;
52   FILE *outfptr = fileTable_openWriteFile (context_fileTable (), cstring_fromChars (outfile));
53   sfree (sfile);
54
55   DPRINTF (("Output lcl file: %s / %s / %s", path, specname, outfile));
56   
57   /* check write permission */
58   
59   if (outfptr == NULL)  /* Cannot open file */
60     {                   
61       if (!haserror)
62         {
63           lclplainerror (message ("Cannot write to output file: %s", 
64                                   cstring_fromChars (outfile)));
65           haserror = TRUE;
66         }
67       sfree (outfile);
68       return;
69     }
70
71   fprintf (outfptr, "%s", msg);
72   fprintf (outfptr, "%s\n", LCL_PARSE_VERSION);
73   
74   /* output line %LCLimports foo bar ... */
75   fprintf (outfptr, "%%LCLimports ");
76
77   lsymbolSet_elements (g_currentImports, sym)
78     {
79       s = lsymbol_toChars (sym);
80
81       if (s != NULL && !mstring_equal (s, specname))
82         {
83           fprintf (outfptr, "%s ", s);
84         }
85     } end_lsymbolSet_elements;
86   
87   fprintf (outfptr, "\n");
88   
89   sort_dump (outfptr, TRUE);
90   symtable_dump (g_symtab, outfptr, TRUE);
91
92   check (fileTable_closeFile (context_fileTable (), outfptr));  
93   sfree (outfile);  
94 }
95
96 void
97 importCTrait (void)
98 {
99   cstring infile = cstring_undefined;
100   filestatus status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSYMSNAME), 
101                                            &infile);
102
103   switch (status)
104     {
105     case OSD_FILEFOUND:
106       /*
107       ** This line was missing before version 2.3f.  Bug fix by Mike Smith.
108       **    This looks like a bug - infile is already fully qualified path  
109       **    parseSignatures() adds another path to the front and fails to   
110       **    open the file.                                                  
111       */
112            
113       (void) parseSignatures (cstring_fromCharsNew (CTRAITSYMSNAME));
114       (void) parseSignatures (infile);
115       break;
116     case OSD_FILENOTFOUND:
117       /* try spec name */
118       status = osd_findOnLarchPath (cstring_makeLiteralTemp (CTRAITSPECNAME),
119                                     &infile);
120
121       if (status == OSD_FILEFOUND)
122         {
123           callLSL (cstring_makeLiteralTemp (CTRAITSPECNAME),
124                    message ("includes %s (%s for String)",
125                             cstring_fromChars (CTRAITFILENAMEN), 
126                             cstring_fromChars (sort_getName (g_sortCstring))));
127           cstring_free (infile);
128           break;
129         }
130       else
131         {
132           lldiagmsg 
133             (message ("Unable to find %s or %s.  Check LARCH_PATH environment variable.",
134                       cstring_fromChars (CTRAITSYMSNAME), 
135                       cstring_fromChars (CTRAITSPECNAME)));
136           cstring_free (infile);
137           llexit (LLFAILURE);
138         }
139     case OSD_PATHTOOLONG:
140       lclbug (message ("importCTrait: the concatenated directory and file "
141                        "name are too long: %s: "
142                        "continuing without it", 
143                        cstring_fromChars (CTRAITSPECNAME)));
144       cstring_free (infile);
145       break;
146     }
147 }
148
149 /*
150 ** processImport --- load imports from file
151 **
152 **    impkind: IMPPLAIN  file on SPEC_PATH
153 **                       # include "./file.h" if it exists,
154 **                       # include "<directory where spec was found>/file.h" if not.
155 **                         (warn if neither exists)
156 **            IMPBRACKET file in default LCL imports directory
157 **                       # include <file.h>
158 **            IMPQUOTE   file directly
159 **                       # include "file.h"
160 */
161
162 void
163 processImport (lsymbol importSymbol, ltoken tok, impkind kind)
164 {
165   bool readableP, oldexporting;
166   bool compressedFormat = FALSE;
167   inputStream imported, imported2, lclsource;
168   char *bufptr;
169   char *tmpbufptr;
170   char *cptr;
171   cstring name;
172   lsymbol sym;
173   char importName[MAX_NAME_LENGTH + 1];
174   cstring importFileName;
175   cstring path = cstring_undefined;
176   cstring fpath, fpath2;
177   mapping map;
178   filestatus ret;
179
180   importFileName = lsymbol_toString (importSymbol);
181   name = cstring_concat (importFileName, cstring_makeLiteralTemp (IO_SUFFIX));
182
183   /*
184   ** find .lcs file
185   */
186   
187   switch (kind)
188     {
189     case IMPPLAIN:
190       path = message ("%s%c%s", cstring_fromChars (g_localSpecPath), PATH_SEPARATOR, 
191                       context_getLarchPath ());
192
193       break;
194     case IMPBRACKET:
195       path = cstring_copy (context_getLCLImportDir ());
196       break;
197     case IMPQUOTE:
198       path = cstring_fromCharsNew (g_localSpecPath);
199       break;
200     default:
201       llbuglit ("bad imports case\n");
202     }
203
204   if ((ret = osd_getPath (path, name, &fpath)) != OSD_FILEFOUND)
205     {
206       cstring fname2;
207       
208       if (ret == OSD_PATHTOOLONG)
209         {
210           llfatalerrorLoc (cstring_makeLiteral ("Path too long"));
211         }
212       
213       imported2 = inputStream_create (cstring_copy (importFileName),
214                                       LCL_EXTENSION, FALSE);
215       fname2 = inputStream_fileName (imported2);
216
217       if (osd_getPath (path, fname2, &fpath2) == OSD_FILEFOUND)
218         {
219           llfatalerrorLoc
220             (message ("Specs must be processed before it can be imported: %s", 
221                       fpath2));
222         }
223       else
224         {
225           if (kind == IMPPLAIN || kind == IMPQUOTE)
226             {
227               llfatalerrorLoc (message ("Cannot find file to import: %s", name));
228             }
229           else
230             {
231               llfatalerrorLoc (message ("Cannot find standard import file: %s", name));
232             }
233         }
234     }
235
236   
237   imported = inputStream_create (fpath, cstring_makeLiteralTemp (IO_SUFFIX), FALSE);
238     
239   readableP = inputStream_open (imported);
240     
241   if (!readableP)
242     {                   /* can't read ? */
243       llfatalerrorLoc (message ("Cannot open import file for reading: %s",
244                                 inputStream_fileName (imported)));
245     }
246
247   bufptr = inputStream_nextLine (imported);
248
249   if (bufptr == 0)
250     {
251       llerror (FLG_SYNTAX, message ("Import file is empty: %s", 
252                                     inputStream_fileName (imported)));
253       cstring_free (name);
254       (void) inputStream_close (imported);
255       inputStream_free (imported);
256
257       cstring_free (path);
258       return;
259     }
260
261   /* was it processed successfully ? */
262   if (firstWord (bufptr, "%FAILED"))
263     {
264       llfatalerrorLoc
265         (message ("Imported file was not checked successfully: %s.", name));
266     }
267   
268   /*
269   ** Is it generated by the right version of the checker? 
270   **
271   ** Uncompressed  .lcs files start with %PASSED
272   ** Compressed files start with %LCS 
273   */
274   
275   if (firstWord (bufptr, "%PASSED"))
276     {
277       /* %PASSED Output from LCP Version 2.* and 3.* */
278       /*                     1234567890123*/
279       /*                                 +*/
280
281       cptr = strstr (bufptr, "LCP Version");
282       
283       if (cptr != NULL)
284         {
285           /* 
286           ** Only really old files start this way!
287           */
288
289           cptr += 12;
290           if (*cptr != '2' && *cptr != '3')
291             {
292               llfatalerrorLoc (message ("Imported file %s is obsolete: %s.",
293                                         inputStream_fileName (imported),
294                                         cstring_fromChars (bufptr)));
295             }
296         }
297
298       compressedFormat = FALSE;
299     }
300   else 
301     {
302       if (!firstWord (bufptr, "%LCS"))
303         {
304           llfatalerrorLoc (message ("Imported file %s is not in correct format: %s",
305                                     inputStream_fileName (imported),
306                                     cstring_fromChars (bufptr)));
307         }
308       
309       compressedFormat = TRUE;
310     }
311   
312   /* push the imported LCL spec onto g_currentImports */
313
314   context_enterImport ();
315   
316   bufptr = inputStream_nextLine (imported);
317   llassert (bufptr != NULL);
318
319   tmpbufptr = bufptr;
320
321     /* expect %LCLimports foo bar ... */
322   if (firstWord (bufptr, "%LCLimports "))
323     {
324       bufptr = bufptr + strlen ("%LCLimports ");
325       while (sscanf (bufptr, "%s", importName) == 1)
326         {
327           bufptr = bufptr + strlen (importName) + 1;    /* 1 for space */
328           sym = lsymbol_fromChars (importName);
329           if (sym == importSymbol || 
330               lsymbolSet_member (g_currentImports, sym))
331             {
332               /* ensure that the import list does not contain itself: an
333                  invariant useful for checking imports cycles. */
334               lclsource = LCLScanSource ();
335               lclfatalerror (tok, 
336                              message ("Imports cycle: %s%s imports %s",
337                                       importFileName,
338                                       LCL_EXTENSION,
339                                       cstring_fromChars (importName)));
340             }     
341           /* push them onto g_currentImports */
342           /* evs - 94 Apr 3:  I don't think it should do this! */
343           /* (void) lsymbolSet_insert (g_currentImports, sym); */
344         }
345     }
346   else
347     {
348       lclsource = LCLScanSource ();
349       lclfatalerror (tok, message ("Unexpected line in imported file %s: %s", 
350                                    name, 
351                                    cstring_fromChars (bufptr)));
352     }
353           
354   /* read in the imported info */
355   oldexporting = sort_setExporting (TRUE);
356
357   map = mapping_create ();
358
359   /* tok for error line numbering */
360
361   if (!compressedFormat)
362     {
363       sort_import (imported, tok, map); 
364     }
365   
366   (void) sort_setExporting (oldexporting);
367   
368   /* sort_import updates a mapping of old anonymous sorts to new
369      anonymous sort that is needed in symtable_import */
370   /* mapping_print (map); */
371   
372   if (!compressedFormat)
373     {
374       symtable_import (imported, tok, map);
375     }
376   else
377     {
378       /* symtable_loadImport (imported, tok, map); */
379     }
380   
381   check (inputStream_close (imported));
382   inputStream_free (imported);
383   
384   mapping_free (map);
385   cstring_free (name);
386   cstring_free (path);
387
388   context_leaveImport ();  
389 }
390
391
392
This page took 0.066672 seconds and 5 git commands to generate.