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