]> andersk Git - splint.git/blob - src/lcllib.c
15a08c5893a4b970d051a4c79994825b46e042da
[splint.git] / src / lcllib.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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, ";;%s\n", SPLINT_VERSION);
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 %s).  Attempting "
488                                       "to continue anyway, but results may be incorrect.  Rebuild "
489                                       "the library with this version of splint.", 
490                                       name, vname));
491                 }
492               else
493                 {
494                   if (reader_readLine (f, buf, BUFLEN) == NULL)
495                     {
496                       loadllmsg (message ("Load library %s is not in Splint library "
497                                           "format (missing library code). Attempting "
498                                           "to continue without library.", name));
499                       return FALSE;
500                     }
501                   else 
502                     {
503                       int lib;
504                       
505                       if (sscanf (buf, ";;lib:%d", &lib) != 1)
506                         {
507                           loadllmsg (message ("Load library %s is not in Splint library "
508                                               "format (missing library code). Attempting "
509                                               "to continue without library.", name));
510                           return FALSE;
511                         }
512                       else
513                         {
514                           flagcode code = (flagcode) lib;
515
516                           if (flagcode_isLibraryFlag (code))
517                             {
518                               if (context_doMerge ()) 
519                                 {
520                                   context_setLibrary (code);
521                                 }
522                             }
523                           else
524                             {
525                               loadllmsg (message ("Load library %s has invalid library code (%s).  "
526                                                   "Attempting to continue without library.",
527                                                   name,
528                                                   flagcode_unparse (code)));
529                               
530                               return FALSE;
531                             }
532                         }
533                     }
534                 }
535             }
536         }
537     }
538   else
539     {
540       loadllmsg (message ("Load library %s is not in Splint library format (missing lines).  "
541                           "Attempting to continue without library.", name));
542       return FALSE;
543     }
544   
545   ctype_loadTable (f);
546   printDot ();
547   
548   typeIdSet_loadTable (f);
549   printDot ();
550   
551   usymtab_load (f);
552   printDot ();
553   
554   context_loadModuleAccess (f);
555   printDot ();
556   
557   return TRUE;
558 }
559
560 /*
561 ** load state from file created by dumpState
562 */
563
564 void
565 loadState (cstring cfname)
566 {
567   FILE *f;
568   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
569
570   f = fileTable_openReadFile (context_fileTable (), fname);
571
572   if (f == NULL)
573     {
574       displayScanClose ();
575       llfatalerror (message ("Cannot open dump file for loading: %s", 
576                              fname));
577     }
578   else
579     {
580       fileloc_reallyFree (g_currentloc);
581       g_currentloc = fileloc_createLib (cfname);
582
583       if (!loadLCDFile (f, cfname)) 
584         {
585           if (!loadStandardState ()) 
586             {
587               ctype_initTable ();
588             }
589         }
590       
591       check (fileTable_closeFile (context_fileTable (), f));
592     }
593
594   /* usymtab_printAll (); */
595   cstring_free (fname);
596 }
597
This page took 0.069937 seconds and 3 git commands to generate.