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