]> andersk Git - splint.git/blob - src/lcllib.c
Cahnged default LCLIMPORTDIR
[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 # include "lcllib.h"
46 # include "llmain.h"
47 # include "portab.h"
48
49 /*@-incondefs@*/ /*@-redecl@*/
50 extern /*:open:*/ /*@dependent@*/ FILE *yyin;
51 /*@=incondefs@*/ /*@=redecl@*/
52
53 /*@constant int NUMLIBS; @*/
54 # define NUMLIBS 17
55
56 /*@constant int NUMPOSIXLIBS; @*/
57 # define NUMPOSIXLIBS 18
58
59 static ob_mstring posixlibs[NUMPOSIXLIBS] = 
60 {
61   "dirent",
62   "fcntl",
63   "grp",
64   "pwd",
65   "regex",
66   "sys/stat",
67   "sys/times",
68   "sys/types", 
69   "netdb", /* unix */
70   "netinet/in", /* unix */
71   "sys/resource", /* unix */
72   "sys/socket", /* not posix */
73   "sys/syslog", /* not posix */
74   "sys/utsname",
75   "sys/wait",
76   "termios",
77   "unistd",
78   "utime"
79 } ;
80
81 static ob_mstring stdlibs[NUMLIBS] =
82 {
83   "assert", 
84   "ctype",
85   "errno",
86   "float", 
87   "limits",
88   "locale",
89   "math", 
90   "setjmp",
91   "signal",
92   "stdarg",
93   "stddef",
94   "stdio",
95   "stdlib",
96   "strings", 
97   "string",
98   "time",
99   "wchar"
100 } ;
101
102 static bool loadLCDFile (FILE * p_f, cstring p_name);
103
104 bool
105 lcllib_isSkipHeader (cstring sname)
106 {
107   int i;
108   bool posixlib = FALSE;
109   char *libname;
110   char *matchname;
111   cstring xname;
112
113   llassert (cstring_isDefined (sname));
114   xname = fileLib_withoutExtension (sname, cstring_makeLiteralTemp (".h"));
115
116   DPRINTF (("Include? %s", sname));
117
118   /*@access cstring@*/
119   llassert (cstring_isDefined (xname));
120   libname = strrchr (xname, CONNECTCHAR);
121   matchname = libname;
122
123   if (libname == NULL) 
124     {
125       libname = xname;
126     }
127   else
128     {
129       libname++;
130       /*@-branchstate@*/
131     }
132   /*@=branchstate@*/
133
134   if (mstring_equal (libname, "varargs"))
135     {
136       fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
137       
138       voptgenerror 
139         (FLG_USEVARARGS,
140          message ("Include file <%s.h> is inconsistent with "
141                   "ANSI library (should use <stdarg.h>)",
142                   cstring_fromChars (libname)),
143          tmp);
144       
145       fileloc_free (tmp);
146       cstring_free (xname);
147       return TRUE;
148     }
149
150   if (context_getFlag (FLG_SKIPANSIHEADERS)
151       && context_usingAnsiLibrary ())
152     {
153       
154       for (i = 0; i < NUMLIBS; i++)
155         {
156           if (mstring_equal (libname, stdlibs[i]))
157             {
158               sfree (xname);
159               return TRUE;
160             }
161         }
162     }
163
164   for (i = 0; i < NUMPOSIXLIBS; i++)
165     {
166       if (strchr (posixlibs[i], CONNECTCHAR) != NULL)
167         {
168           char *ptr;
169           
170           if ((ptr = strstr (xname, posixlibs[i])) != NULL) 
171             {
172               if (ptr[strlen (posixlibs[i])] == '\0')
173                 {
174                   posixlib = TRUE;
175                   matchname = ptr;
176                   break;
177                 }
178               else
179                 {
180                   ; /* no match */
181                 }
182             }
183         }
184       else
185         {
186           if (mstring_equal (libname, posixlibs[i]))
187             {
188               posixlib = TRUE;
189               matchname = libname;
190               break;
191             }
192           /*@-branchstate@*/ 
193         }
194     } /*@=branchstate@*/
195   
196   if (posixlib)
197     {
198       if (context_usingPosixLibrary ())
199         {
200           if (context_getFlag (FLG_SKIPPOSIXHEADERS))
201             {
202               cstring_free (xname);
203               return TRUE;
204             }
205         }
206       else
207         {       
208           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
209           
210           voptgenerror 
211             (FLG_WARNPOSIX,
212              message ("Include file <%s.h> matches the name of a "
213                       "POSIX library, but the POSIX library is "
214                       "not being used.  Consider using +posixlib "
215                       "or +posixstrictlib to select the POSIX "
216                       "library, or -warnposix "
217                       "to suppress this message.",
218                       cstring_fromChars (matchname)),
219              tmp);
220           
221           fileloc_free (tmp);
222         }
223     }
224
225   cstring_free (xname);
226   /*@noaccess cstring@*/
227   return FALSE;
228 }
229
230 static void printDot (void)
231 {
232   if (context_getFlag (FLG_SHOWSCAN)) 
233     {
234       (void) fflush (g_msgstream);
235       fprintf (stderr, "."); 
236       (void) fflush (stderr);
237     }
238 }
239
240 void
241 dumpState (cstring cfname)
242 {
243   FILE *f;
244   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
245   
246   f = fileTable_openFile (context_fileTable (), fname, "w");
247
248   if (context_getFlag (FLG_SHOWSCAN))
249     {
250       fprintf (stderr, "< Dumping to %s ", cstring_toCharsSafe (fname)); 
251     }
252   
253   if (f == NULL)
254     {
255       lldiagmsg (message ("Cannot open dump file for writing: %s", fname));
256     }
257   else
258     {
259       /*
260       ** sequence is convulted --- must call usymtab_prepareDump before
261       **    dumping ctype table to convert type uid's
262       */
263
264       printDot ();
265
266       /*
267       DPRINTF (("Before prepare dump:"));
268       ctype_printTable ();
269       DPRINTF (("Preparing dump..."));
270       */
271
272       usymtab_prepareDump ();
273
274       /*
275       ** Be careful, these lines must match loadLCDFile checking.
276       */
277
278       fprintf (f, ";;LCLint Dump: %s\n", cstring_toCharsSafe (fname));
279       fprintf (f, ";;%s\n", LCL_VERSION);
280       fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
281       fprintf (f, ";;ctTable\n");
282       
283       DPRINTF (("Dumping types..."));
284       printDot ();
285       ctype_dumpTable (f);
286       printDot ();
287       
288       DPRINTF (("Dumping type sets..."));
289       fprintf (f, ";;tistable\n");
290       typeIdSet_dumpTable (f);
291       printDot ();
292       
293       DPRINTF (("Dumping usymtab..."));
294       fprintf (f, ";;symTable\n");
295       usymtab_dump (f);
296       printDot ();
297
298       DPRINTF (("Dumping modules..."));
299       fprintf (f, ";; Modules access\n");
300       context_dumpModuleAccess (f);
301       fprintf (f, ";;End\n");
302       check (fileTable_closeFile (context_fileTable (), f));
303     }
304
305   if (context_getFlag (FLG_SHOWSCAN))
306     {
307       fprintf (g_msgstream, " >\n");
308     }
309
310   cstring_free (fname);
311 }
312
313 bool
314 loadStandardState ()
315 {
316   cstring fpath;
317   FILE *stdlib;
318   bool result;
319   cstring libname = fileLib_addExtension (context_selectedLibrary (), 
320                                           cstring_makeLiteralTemp (DUMP_SUFFIX));
321   
322   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
323     {
324       lldiagmsg (message ("Cannot find %sstandard library: %s", 
325                           cstring_makeLiteralTemp 
326                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
327                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
328                           libname));
329       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
330       result = FALSE;
331     }
332   else
333     {
334       stdlib = fileTable_openFile (context_fileTable (), fpath, "r");
335
336       if (stdlib == NULL)
337         {
338           lldiagmsg (message ("Cannot read standard library: %s",
339                               fpath));
340           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
341
342           result = FALSE;
343         }
344       else
345         {
346           if (context_getFlag (FLG_WHICHLIB))
347             {
348               char *t = mstring_create (MAX_NAME_LENGTH);
349               char *ot = t;
350
351               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
352                 {
353                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
354                 }
355
356               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
357                 {
358                   if (*t == ';' && *(t + 1) == ';') 
359                     {
360                       t += 2;
361                     }
362                 }
363
364               if (t == NULL)
365                 {
366                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
367                                       fpath));
368                 }
369               else
370                 {
371                   char *tt;
372
373                   tt = strrchr (t, '\n');
374                   if (tt != NULL)
375                     *tt = '\0';
376
377                   lldiagmsg (message ("Standard library: %s", fpath));
378                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
379                 }
380
381               sfree (ot);
382               
383               check (fileTable_closeFile (context_fileTable (), stdlib));
384               stdlib = fileTable_openFile (context_fileTable (), fpath, "r");
385             }
386
387           llassert (stdlib != NULL);
388
389           fileloc_reallyFree (g_currentloc);
390           g_currentloc = fileloc_createLib (libname);
391
392           DPRINTF (("Loading: %s", fpath));
393
394           if (context_getDebug (FLG_SHOWSCAN))
395             {
396               fprintf (g_msgstream, "< loading standard library %s ", 
397                        cstring_toCharsSafe (fpath));
398               result = loadLCDFile (stdlib, fpath);
399               fprintf (g_msgstream, " >\n");
400             }
401           else
402             {
403               result = loadLCDFile (stdlib, fpath);
404             }
405
406           check (fileTable_closeFile (context_fileTable (), stdlib));
407         }
408     }
409
410   cstring_free (libname);
411   return result;
412 }
413
414 /*@constant int BUFLEN;@*/
415 # define BUFLEN 128
416
417 static bool
418 loadLCDFile (FILE *f, cstring name)
419 {
420   char buf[BUFLEN];
421   
422   /*
423   ** Check version.  Should be >= LCLINT_LIBVERSION
424   */
425
426   if (reader_readLine (f, buf, BUFLEN) == NULL
427       || !mstring_equalPrefix (buf, ";;LCLint Dump:"))
428     {
429       loadllmsg (message ("Load library %s is not in LCLint library format.  Attempting "
430                           "to continue without library.", name));
431       return FALSE;
432     }
433   
434   if (reader_readLine (f, buf, BUFLEN) != NULL)
435     {
436       if (!mstring_equalPrefix (buf, ";;"))
437         {
438           loadllmsg (message ("Load library %s is not in LCLint library format.  Attempting "
439                               "to continue without library.", name));
440           return FALSE;
441         }
442       else if (mstring_equalPrefix (buf, ";;ctTable"))
443         {
444           loadllmsg (message ("Load library %s is in obsolete LCLint library format.  Attempting "
445                               "to continue anyway, but results may be incorrect.  Rebuild "
446                               "the library with this version of lclint.", 
447                               name));
448         }
449       else 
450         {
451           float version = 0.0;
452
453           if (sscanf (buf, ";;LCLint %f", &version) != 1)
454             {
455               loadllmsg (message ("Load library %s is not in LCLint 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 LCLint 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 LCLint 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 LCLint 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.081172 seconds and 5 git commands to generate.