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