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