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