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