]> andersk Git - splint.git/blob - src/lcllib.c
Fixed creation of temp files.
[splint.git] / src / lcllib.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 ** lcllib.c
26 **
27 ** routines for loading and creating library files
28 **
29 ** this is a brute-force implementation, a more efficient
30 ** representation should be designed.
31 **
32 */
33
34 /*
35  * Herbert 02/17/2002:
36  * - fixed the recognition of Posix headers for OS/2
37  */
38
39 # include "splintMacros.nf"
40 # include "llbasic.h"
41 # include "osd.h"
42
43 # ifndef NOLCL
44 # include "gram.h"
45
46 # include "lclscan.h"
47 # endif
48
49 # include "lcllib.h"
50 # include "llmain.h"
51 # include "portab.h"
52
53 /*@-incondefs@*/ /*@-redecl@*/
54 extern /*:open:*/ /*@dependent@*/ FILE *yyin;
55 /*@=incondefs@*/ /*@=redecl@*/
56
57 /*@constant int NUMLIBS; @*/
58 # define NUMLIBS 25
59
60 /*@constant int NUMPOSIXLIBS; @*/
61 # define NUMPOSIXLIBS 18
62
63 static ob_mstring posixlibs[NUMPOSIXLIBS] = 
64 {
65   "dirent",
66   "fcntl",
67   "grp",
68   "pwd",
69   "regex",
70   "sys/stat",
71   "sys/times",
72   "sys/types", 
73   "netdb", /* unix */
74   "netinet/in", /* unix */
75   "sys/resource", /* unix */
76   "sys/socket", /* not posix */
77   "sys/syslog", /* not posix */
78   "sys/utsname",
79   "sys/wait",
80   "termios",
81   "unistd",
82   "utime"
83 } ;
84
85 static ob_mstring stdlibs[NUMLIBS] =
86 {
87   "assert", 
88   "complex"
89   "ctype",
90   "errno",
91   "fenv",
92   "float",
93   "inttypes",
94   "iso646",
95   "limits",
96   "locale",
97   "math", 
98   "setjmp",
99   "signal",
100   "stdarg",
101   "stdbool",
102   "stddef",
103   "stdint",
104   "stdio",
105   "stdlib",
106   "string",
107   "strings", /* some systems use this...they shouldn't */
108   "tgmath",
109   "time",
110   "wchar",
111   "wctype"
112 } ;
113
114 static bool loadLCDFile (FILE * p_f, cstring p_name);
115
116 bool
117 lcllib_isSkipHeader (cstring sname)
118 {
119   int i;
120   bool posixlib = FALSE;
121   char *libname;
122   char *matchname;
123   cstring xname;
124
125   llassert (cstring_isDefined (sname));
126   xname = fileLib_withoutExtension (sname, cstring_makeLiteralTemp (".h"));
127
128   DPRINTF (("Include? %s", sname));
129
130   /*@access cstring@*/
131   llassert (cstring_isDefined (xname));
132 # if defined (OS2)
133   {
134     /* Posixlibs use forward slashes, so we use them here, too */
135     cstring_replaceAll (xname, '\\', '/');
136     libname = strrchr (xname, '/');
137     DPRINTF (("libname: %s", libname));
138   }
139 # else
140   libname = strrchr (xname, CONNECTCHAR);
141 # endif
142   matchname = libname;
143
144   if (libname == NULL) 
145     {
146       libname = xname;
147     }
148   else
149     {
150       libname++;
151       /*@-branchstate@*/
152     }
153   /*@=branchstate@*/
154
155   if (mstring_equal (libname, "varargs"))
156     {
157       fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
158       
159       voptgenerror 
160         (FLG_USEVARARGS,
161          message ("Include file <%s.h> is inconsistent with "
162                   "ANSI library (should use <stdarg.h>)",
163                   cstring_fromChars (libname)),
164          tmp);
165       
166       fileloc_free (tmp);
167       cstring_free (xname);
168       return TRUE;
169     }
170
171   if (context_getFlag (FLG_SKIPISOHEADERS)
172       && context_usingAnsiLibrary ())
173     {
174       
175       for (i = 0; i < NUMLIBS; i++)
176         {
177           if (mstring_equal (libname, stdlibs[i]))
178             {
179               sfree (xname);
180               return TRUE;
181             }
182         }
183     }
184
185   for (i = 0; i < NUMPOSIXLIBS; i++)
186     {
187       if (strchr (posixlibs[i], CONNECTCHAR) != NULL
188 # if defined (OS2)
189           || strchr (posixlibs[i], ALTCONNECTCHAR) != NULL
190 # endif
191           )
192         {
193           char *ptr;
194           
195           DPRINTF (("xname: %s, posix: %s", xname, posixlibs[i]));
196           if ((ptr = strstr (xname, posixlibs[i])) != NULL) 
197             {
198               if (ptr[strlen (posixlibs[i])] == '\0')
199                 {
200                   posixlib = TRUE;
201                   matchname = ptr;
202                   break;
203                 }
204               else
205                 {
206                   ; /* no match */
207                 }
208             }
209         }
210       else
211         {
212           if (mstring_equal (libname, posixlibs[i]))
213             {
214               posixlib = TRUE;
215               matchname = libname;
216               break;
217             }
218           /*@-branchstate@*/ 
219         }
220     } /*@=branchstate@*/
221   
222   if (posixlib)
223     {
224       if (context_usingPosixLibrary ())
225         {
226           if (context_getFlag (FLG_SKIPPOSIXHEADERS))
227             {
228               cstring_free (xname);
229               /*@-nullstate@*/ 
230               return TRUE; 
231               /*@=nullstate@*/
232               /*@i233@*/
233               /* evans 2002-03-02: 
234                  the returned reference is possibly null,
235                  but this should not change the null state of the parameter
236                  investigate this warning 
237               */
238             }
239         }
240       else
241         {       
242           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
243           
244           voptgenerror 
245             (FLG_WARNPOSIX,
246              message ("Include file <%s.h> matches the name of a "
247                       "POSIX library, but the POSIX library is "
248                       "not being used.  Consider using +posixlib "
249                       "or +posixstrictlib to select the POSIX "
250                       "library, or -warnposix "
251                       "to suppress this message.",
252                       cstring_fromChars (matchname)),
253              tmp);
254           
255           fileloc_free (tmp);
256         }
257     }
258
259   cstring_free (xname);
260   /*@noaccess cstring@*/
261   /*@-nullstate@*/ /*@i233@*/ /* same problem as above */
262   return FALSE;
263   /*@=nullstate@*/
264 }
265
266 static void printDot (void)
267 {
268   displayScanContinue (cstring_makeLiteralTemp ("."));
269 }
270
271 void
272 dumpState (cstring cfname)
273 {
274   FILE *f;
275   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
276   
277   f = fileTable_openWriteFile (context_fileTable (), fname);
278
279   displayScanOpen (message ("Dumping to %s ", fname)); 
280   
281   if (f == NULL)
282     {
283       lldiagmsg (message ("Cannot open dump file for writing: %s", fname));
284     }
285   else
286     {
287       /*
288       ** sequence is convulted --- must call usymtab_prepareDump before
289       **    dumping ctype table to convert type uid's
290       */
291
292       printDot ();
293
294       /*
295       DPRINTF (("Before prepare dump:"));
296       ctype_printTable ();
297       DPRINTF (("Preparing dump..."));
298       */
299
300       usymtab_prepareDump ();
301
302       /*
303       ** Be careful, these lines must match loadLCDFile checking.
304       */
305
306       fprintf (f, "%s %s\n", LIBRARY_MARKER, cstring_toCharsSafe (fname));
307       fprintf (f, ";;%s\n", SPLINT_VERSION);
308       fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
309       fprintf (f, ";;ctTable\n");
310       
311       DPRINTF (("Dumping types..."));
312       printDot ();
313       ctype_dumpTable (f);
314       printDot ();
315       
316       DPRINTF (("Dumping type sets..."));
317       fprintf (f, ";;tistable\n");
318       typeIdSet_dumpTable (f);
319       printDot ();
320       
321       DPRINTF (("Dumping usymtab..."));
322       fprintf (f, ";;symTable\n");
323       usymtab_dump (f);
324       printDot ();
325
326       DPRINTF (("Dumping modules..."));
327       fprintf (f, ";; Modules access\n");
328       context_dumpModuleAccess (f);
329       fprintf (f, ";;End\n");
330       check (fileTable_closeFile (context_fileTable (), f));
331     }
332
333   displayScanClose ();
334   cstring_free (fname);
335 }
336
337 bool
338 loadStandardState ()
339 {
340   cstring fpath;
341   FILE *stdlib;
342   bool result;
343   cstring libname = fileLib_addExtension (context_selectedLibrary (), 
344                                           cstring_makeLiteralTemp (DUMP_SUFFIX));
345   
346   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
347     {
348       lldiagmsg (message ("Cannot find %sstandard library: %s", 
349                           cstring_makeLiteralTemp 
350                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
351                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
352                           libname));
353       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
354       result = FALSE;
355     }
356   else
357     {
358       stdlib = fileTable_openReadFile (context_fileTable (), fpath);
359
360       if (stdlib == NULL)
361         {
362           lldiagmsg (message ("Cannot read standard library: %s",
363                               fpath));
364           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
365
366           result = FALSE;
367         }
368       else
369         {
370           if (context_getFlag (FLG_WHICHLIB))
371             {
372               char *t = mstring_create (MAX_NAME_LENGTH);
373               char *ot = t;
374
375               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
376                 {
377                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
378                 }
379
380               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
381                 {
382                   if (*t == ';' && *(t + 1) == ';') 
383                     {
384                       t += 2;
385                     }
386                 }
387
388               if (t == NULL)
389                 {
390                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
391                                       fpath));
392                 }
393               else
394                 {
395                   char *tt;
396
397                   tt = strrchr (t, '\n');
398                   if (tt != NULL)
399                     *tt = '\0';
400
401                   lldiagmsg (message ("Standard library: %s", fpath));
402                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
403                 }
404
405               sfree (ot);
406               
407               check (fileTable_closeFile (context_fileTable (), stdlib));
408               stdlib = fileTable_openReadFile (context_fileTable (), fpath);
409             }
410
411           llassert (stdlib != NULL);
412
413           fileloc_reallyFree (g_currentloc);
414           g_currentloc = fileloc_createLib (libname);
415
416           DPRINTF (("Loading: %s", fpath));
417
418           displayScanOpen (message ("loading standard library %s ", fpath));
419           result = loadLCDFile (stdlib, fpath);
420           displayScanClose ();
421
422           check (fileTable_closeFile (context_fileTable (), stdlib));
423         }
424     }
425
426   cstring_free (libname);
427   return result;
428 }
429
430 /*@constant int BUFLEN;@*/
431 # define BUFLEN 128
432
433 static bool
434 loadLCDFile (FILE *f, cstring name)
435 {
436   char buf[BUFLEN];
437   
438   /*
439   ** Check version.  Should be >= SPLINT_LIBVERSION
440   */
441
442   if (reader_readLine (f, buf, BUFLEN) == NULL
443       || !mstring_equalPrefix (buf, LIBRARY_MARKER))
444     {
445       loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
446                           "to continue without library.", name));
447       return FALSE;
448     }
449   
450   if (reader_readLine (f, buf, BUFLEN) != NULL)
451     {
452       if (!mstring_equalPrefix (buf, ";;"))
453         {
454           loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
455                               "to continue without library.", name));
456           return FALSE;
457         }
458       else if (mstring_equalPrefix (buf, ";;ctTable"))
459         {
460           loadllmsg (message ("Load library %s is in obsolete Splint library format.  Attempting "
461                               "to continue anyway, but results may be incorrect.  Rebuild "
462                               "the library with this version of splint.", 
463                               name));
464         }
465       else 
466         {
467           float version = 0.0;
468
469           if (sscanf (buf, ";;Splint %f", &version) != 1
470               && (sscanf (buf, ";;LCLint %f", &version) != 1))
471             {
472               loadllmsg (message ("Load library %s is not in Splint library format (missing version "
473                                   "number).  Attempting "
474                                   "to continue without library.", name));
475               return FALSE;
476             }
477           else
478             {
479               if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
480                 {
481                   cstring vname;
482                   char *nl = strchr (buf, '\n');
483
484                   *nl = '\0';
485
486                   vname = cstring_fromChars (buf + 9);
487
488                   loadllmsg (message ("Load library %s is in obsolete Splint library "
489                                       "format (version %s).  Attempting "
490                                       "to continue anyway, but results may be incorrect.  Rebuild "
491                                       "the library with this version of splint.", 
492                                       name, vname));
493                 }
494               else
495                 {
496                   if (reader_readLine (f, buf, BUFLEN) == NULL)
497                     {
498                       loadllmsg (message ("Load library %s is not in Splint library "
499                                           "format (missing library code). Attempting "
500                                           "to continue without library.", name));
501                       return FALSE;
502                     }
503                   else 
504                     {
505                       int lib;
506                       
507                       if (sscanf (buf, ";;lib:%d", &lib) != 1)
508                         {
509                           loadllmsg (message ("Load library %s is not in Splint library "
510                                               "format (missing library code). Attempting "
511                                               "to continue without library.", name));
512                           return FALSE;
513                         }
514                       else
515                         {
516                           flagcode code = (flagcode) lib;
517
518                           if (flagcode_isLibraryFlag (code))
519                             {
520                               if (context_doMerge ()) 
521                                 {
522                                   context_setLibrary (code);
523                                 }
524                             }
525                           else
526                             {
527                               loadllmsg (message ("Load library %s has invalid library code (%s).  "
528                                                   "Attempting to continue without library.",
529                                                   name,
530                                                   flagcode_unparse (code)));
531                               
532                               return FALSE;
533                             }
534                         }
535                     }
536                 }
537             }
538         }
539     }
540   else
541     {
542       loadllmsg (message ("Load library %s is not in Splint library format (missing lines).  "
543                           "Attempting to continue without library.", name));
544       return FALSE;
545     }
546   
547   ctype_loadTable (f);
548   printDot ();
549   
550   typeIdSet_loadTable (f);
551   printDot ();
552   
553   usymtab_load (f);
554   printDot ();
555   
556   context_loadModuleAccess (f);
557   printDot ();
558   
559   return TRUE;
560 }
561
562 /*
563 ** load state from file created by dumpState
564 */
565
566 void
567 loadState (cstring cfname)
568 {
569   FILE *f;
570   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
571
572   f = fileTable_openReadFile (context_fileTable (), fname);
573
574   if (f == NULL)
575     {
576       displayScanClose ();
577       llfatalerror (message ("Cannot open dump file for loading: %s", 
578                              fname));
579     }
580   else
581     {
582       fileloc_reallyFree (g_currentloc);
583       g_currentloc = fileloc_createLib (cfname);
584
585       if (!loadLCDFile (f, cfname)) 
586         {
587           if (!loadStandardState ()) 
588             {
589               ctype_initTable ();
590             }
591         }
592       
593       check (fileTable_closeFile (context_fileTable (), f));
594     }
595
596   /* usymtab_printAll (); */
597   cstring_free (fname);
598 }
599
This page took 0.469442 seconds and 5 git commands to generate.