]> andersk Git - splint.git/blob - src/lcllib.c
300ab7aa69d9e8044fa0c7c9e981b34392ff0bdd
[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 "basic.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       for (i = 0; i < NUMLIBS; i++)
173         {
174           if (mstring_equal (libname, stdlibs[i]))
175             {
176               sfree (xname);
177               return TRUE;
178             }
179         }
180     }
181
182   for (i = 0; i < NUMPOSIXLIBS; i++)
183     {
184       if (strchr (posixlibs[i], CONNECTCHAR) != NULL
185 # if defined (OS2)
186           || strchr (posixlibs[i], ALTCONNECTCHAR) != NULL
187 # endif
188           )
189         {
190           char *ptr;
191           
192           DPRINTF (("xname: %s, posix: %s", xname, posixlibs[i]));
193           if ((ptr = strstr (xname, posixlibs[i])) != NULL) 
194             {
195               if (ptr[strlen (posixlibs[i])] == '\0')
196                 {
197                   posixlib = TRUE;
198                   matchname = ptr;
199                   break;
200                 }
201               else
202                 {
203                   ; /* no match */
204                 }
205             }
206         }
207       else
208         {
209           if (mstring_equal (libname, posixlibs[i]))
210             {
211               posixlib = TRUE;
212               matchname = libname;
213               break;
214             }
215           /*@-branchstate@*/ 
216         }
217     } /*@=branchstate@*/
218   
219   if (posixlib)
220     {
221       if (context_usingPosixLibrary ())
222         {
223           if (context_getFlag (FLG_SKIPPOSIXHEADERS))
224             {
225               cstring_free (xname);
226               /*@-nullstate@*/ 
227               return TRUE; 
228               /*@=nullstate@*/
229
230               /* evans 2002-03-02: 
231                    the returned reference is possibly null,
232                    but this should not change the null state of the parameter
233               */
234             }
235         }
236       else
237         {       
238           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
239           
240           voptgenerror 
241             (FLG_WARNPOSIX,
242              message ("Include file <%s.h> matches the name of a "
243                       "POSIX library, but the POSIX library is "
244                       "not being used.  Consider using +posixlib "
245                       "or +posixstrictlib to select the POSIX "
246                       "library, or -warnposix "
247                       "to suppress this message.",
248                       cstring_fromChars (matchname)),
249              tmp);
250           
251           fileloc_free (tmp);
252         }
253     }
254
255   cstring_free (xname);
256   /*@noaccess cstring@*/
257   /*@-nullstate@*/ /* same problem as above */
258   return FALSE;
259   /*@=nullstate@*/
260 }
261
262 static void printDot (void)
263 {
264   displayScanContinue (cstring_makeLiteralTemp ("."));
265 }
266
267 void
268 dumpState (cstring cfname)
269 {
270   FILE *f;
271   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
272   
273   f = fileTable_openWriteFile (context_fileTable (), fname);
274
275   displayScanOpen (message ("Dumping to %s ", fname)); 
276   
277   if (f == NULL)
278     {
279       lldiagmsg (message ("Cannot open dump file for writing: %s", fname));
280     }
281   else
282     {
283       /*
284       ** sequence is convulted --- must call usymtab_prepareDump before
285       **    dumping ctype table to convert type uid's
286       */
287
288       printDot ();
289
290       /*
291       DPRINTF (("Before prepare dump:"));
292       ctype_printTable ();
293       DPRINTF (("Preparing dump..."));
294       */
295
296       usymtab_prepareDump ();
297
298       /*
299       ** Be careful, these lines must match loadLCDFile checking.
300       */
301
302       fprintf (f, "%s %s\n", LIBRARY_MARKER, cstring_toCharsSafe (fname));
303       fprintf (f, ";;Splint %f\n", SPLINT_LIBVERSION);
304       fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
305       fprintf (f, ";;ctTable\n");
306       
307       DPRINTF (("Dumping types..."));
308       printDot ();
309       ctype_dumpTable (f);
310       printDot ();
311       
312       DPRINTF (("Dumping type sets..."));
313       fprintf (f, ";;tistable\n");
314       typeIdSet_dumpTable (f);
315       printDot ();
316       
317       DPRINTF (("Dumping usymtab..."));
318       fprintf (f, ";;symTable\n");
319       usymtab_dump (f);
320       printDot ();
321
322       DPRINTF (("Dumping modules..."));
323       fprintf (f, ";; Modules access\n");
324       context_dumpModuleAccess (f);
325       fprintf (f, ";;End\n");
326       check (fileTable_closeFile (context_fileTable (), f));
327     }
328
329   displayScanClose ();
330   cstring_free (fname);
331 }
332
333 bool
334 loadStandardState ()
335 {
336   cstring fpath;
337   FILE *stdlib;
338   bool result;
339   cstring libname = fileLib_addExtension (context_selectedLibrary (), 
340                                           cstring_makeLiteralTemp (DUMP_SUFFIX));
341   
342   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
343     {
344       lldiagmsg (message ("Cannot find %sstandard library: %s", 
345                           cstring_makeLiteralTemp 
346                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
347                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
348                           libname));
349       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
350       result = FALSE;
351     }
352   else
353     {
354       stdlib = fileTable_openReadFile (context_fileTable (), fpath);
355
356       if (stdlib == NULL)
357         {
358           lldiagmsg (message ("Cannot read standard library: %s",
359                               fpath));
360           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
361
362           result = FALSE;
363         }
364       else
365         {
366           if (context_getFlag (FLG_WHICHLIB))
367             {
368               char *t = mstring_create (MAX_NAME_LENGTH);
369               char *ot = t;
370
371               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
372                 {
373                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
374                 }
375
376               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
377                 {
378                   if (*t == ';' && *(t + 1) == ';') 
379                     {
380                       t += 2;
381                     }
382                 }
383
384               if (t == NULL)
385                 {
386                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
387                                       fpath));
388                 }
389               else
390                 {
391                   char *tt;
392
393                   tt = strrchr (t, '\n');
394                   if (tt != NULL)
395                     *tt = '\0';
396
397                   lldiagmsg (message ("Standard library: %s", fpath));
398                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
399                 }
400
401               sfree (ot);
402               
403               check (fileTable_closeFile (context_fileTable (), stdlib));
404               stdlib = fileTable_openReadFile (context_fileTable (), fpath);
405             }
406
407           llassert (stdlib != NULL);
408
409           fileloc_reallyFree (g_currentloc);
410           g_currentloc = fileloc_createLib (libname);
411
412           DPRINTF (("Loading: %s", fpath));
413
414           displayScanOpen (message ("loading standard library %s ", fpath));
415           result = loadLCDFile (stdlib, fpath);
416           displayScanClose ();
417
418           check (fileTable_closeFile (context_fileTable (), stdlib));
419         }
420     }
421
422   cstring_free (libname);
423   return result;
424 }
425
426 /*@constant int BUFLEN;@*/
427 # define BUFLEN 128
428
429 static bool
430 loadLCDFile (FILE *f, cstring name)
431 {
432   char buf[BUFLEN];
433   
434   /*
435   ** Check version.  Should be >= SPLINT_LIBVERSION
436   */
437
438   if (reader_readLine (f, buf, BUFLEN) == NULL
439       || !mstring_equalPrefix (buf, LIBRARY_MARKER))
440     {
441       loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
442                           "to continue without library.", name));
443       return FALSE;
444     }
445   
446   if (reader_readLine (f, buf, BUFLEN) != NULL)
447     {
448       if (!mstring_equalPrefix (buf, ";;"))
449         {
450           loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
451                               "to continue without library.", name));
452           return FALSE;
453         }
454       else if (mstring_equalPrefix (buf, ";;ctTable"))
455         {
456           loadllmsg (message ("Load library %s is in obsolete Splint library format.  Attempting "
457                               "to continue anyway, but results may be incorrect.  Rebuild "
458                               "the library with this version of splint.", 
459                               name));
460         }
461       else 
462         {
463           float version = 0.0;
464
465           if (sscanf (buf, ";;Splint %f", &version) != 1
466               && (sscanf (buf, ";;LCLint %f", &version) != 1))
467             {
468               loadllmsg (message ("Load library %s is not in Splint library format (missing version "
469                                   "number).  Attempting "
470                                   "to continue without library.", name));
471               return FALSE;
472             }
473           else
474             {
475               if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
476                 {
477                   cstring vname;
478                   char *nl = strchr (buf, '\n');
479
480                   *nl = '\0';
481
482                   vname = cstring_fromChars (buf + 9);
483
484                   loadllmsg (message ("Load library %s is in obsolete Splint library "
485                                       "format (version %f (%s), expecting version %f).  Attempting "
486                                       "to continue anyway, but results may be incorrect.  Rebuild "
487                                       "the library with this version of splint.", 
488                                       name, 
489                                       version,
490                                       vname, 
491                                       SPLINT_LIBVERSION));
492                 }
493               else
494                 {
495                   if (reader_readLine (f, buf, BUFLEN) == NULL)
496                     {
497                       loadllmsg (message ("Load library %s is not in Splint library "
498                                           "format (missing library code). Attempting "
499                                           "to continue without library.", name));
500                       return FALSE;
501                     }
502                   else 
503                     {
504                       int lib;
505                       
506                       if (sscanf (buf, ";;lib:%d", &lib) != 1)
507                         {
508                           loadllmsg (message ("Load library %s is not in Splint library "
509                                               "format (missing library code). Attempting "
510                                               "to continue without library.", name));
511                           return FALSE;
512                         }
513                       else
514                         {
515                           flagcode code = (flagcode) lib;
516
517                           if (flagcode_isLibraryFlag (code))
518                             {
519                               if (context_doMerge ()) 
520                                 {
521                                   context_setLibrary (code);
522                                 }
523                             }
524                           else
525                             {
526                               loadllmsg (message ("Load library %s has invalid library code (%s).  "
527                                                   "Attempting to continue without library.",
528                                                   name,
529                                                   flagcode_unparse (code)));
530                               
531                               return FALSE;
532                             }
533                         }
534                     }
535                 }
536             }
537         }
538     }
539   else
540     {
541       loadllmsg (message ("Load library %s is not in Splint library format (missing lines).  "
542                           "Attempting to continue without library.", name));
543       return FALSE;
544     }
545   
546   ctype_loadTable (f);
547   printDot ();
548   
549   typeIdSet_loadTable (f);
550   printDot ();
551   
552   usymtab_load (f);
553   printDot ();
554   
555   context_loadModuleAccess (f);
556   printDot ();
557   
558   return TRUE;
559 }
560
561 /*
562 ** load state from file created by dumpState
563 */
564
565 void
566 loadState (cstring cfname)
567 {
568   FILE *f;
569   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
570
571   f = fileTable_openReadFile (context_fileTable (), fname);
572
573   if (f == NULL)
574     {
575       displayScanClose ();
576       llfatalerror (message ("Cannot open dump file for loading: %s", 
577                              fname));
578     }
579   else
580     {
581       fileloc_reallyFree (g_currentloc);
582       g_currentloc = fileloc_createLib (cfname);
583
584       if (!loadLCDFile (f, cfname)) 
585         {
586           if (!loadStandardState ()) 
587             {
588               ctype_initTable ();
589             }
590         }
591       
592       check (fileTable_closeFile (context_fileTable (), f));
593     }
594
595   /* usymtab_printAll (); */
596   cstring_free (fname);
597 }
598
This page took 0.086637 seconds and 3 git commands to generate.