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