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