]> andersk Git - splint.git/blob - src/lcllib.c
Fixed problem with assertion checking for negative shifts in
[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
50 /*@-incondefs@*/ /*@-redecl@*/
51 extern /*:open:*/ /*@dependent@*/ FILE *yyin;
52 /*@=incondefs@*/ /*@=redecl@*/
53
54 /*@constant int NUMLIBS; @*/
55 # define NUMLIBS 25
56
57 /*@constant int NUMPOSIXLIBS; @*/
58 # define NUMPOSIXLIBS 18
59
60 static ob_mstring posixlibs[NUMPOSIXLIBS] = 
61 {
62   "dirent",
63   "fcntl",
64   "grp",
65   "pwd",
66   "regex",
67   "sys/stat",
68   "sys/times",
69   "sys/types", 
70   "netdb", /* unix */
71   "netinet/in", /* unix */
72   "sys/resource", /* unix */
73   "sys/socket", /* not posix */
74   "sys/syslog", /* not posix */
75   "sys/utsname",
76   "sys/wait",
77   "termios",
78   "unistd",
79   "utime"
80 } ;
81
82 static ob_mstring stdlibs[NUMLIBS] =
83 {
84   "assert", 
85   "complex"
86   "ctype",
87   "errno",
88   "fenv",
89   "float",
90   "inttypes",
91   "iso646",
92   "limits",
93   "locale",
94   "math", 
95   "setjmp",
96   "signal",
97   "stdarg",
98   "stdbool",
99   "stddef",
100   "stdint",
101   "stdio",
102   "stdlib",
103   "string",
104   "strings", /* some systems use this...they shouldn't */
105   "tgmath",
106   "time",
107   "wchar",
108   "wctype"
109 } ;
110
111 static bool loadLCDFile (FILE * p_f, cstring p_name);
112
113 bool
114 lcllib_isSkipHeader (cstring sname)
115 {
116   int i;
117   bool posixlib = FALSE;
118   char *libname;
119   char *matchname;
120   cstring xname;
121
122   llassert (cstring_isDefined (sname));
123   xname = fileLib_withoutExtension (sname, cstring_makeLiteralTemp (".h"));
124
125   DPRINTF (("Include? %s", sname));
126
127   /*@access cstring@*/
128   llassert (cstring_isDefined (xname));
129 # if defined (OS2)
130   {
131     /* Posixlibs use forward slashes, so we use them here, too */
132     cstring_replaceAll (xname, '\\', '/');
133     libname = strrchr (xname, '/');
134     DPRINTF (("libname: %s", libname));
135   }
136 # else
137   libname = strrchr (xname, CONNECTCHAR);
138 # endif
139   matchname = libname;
140
141   if (libname == NULL) 
142     {
143       libname = xname;
144     }
145   else
146     {
147       libname++;
148       /*@-branchstate@*/
149     }
150   /*@=branchstate@*/
151
152   if (mstring_equal (libname, "varargs"))
153     {
154       fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
155       
156       voptgenerror 
157         (FLG_USEVARARGS,
158          message ("Include file <%s.h> is inconsistent with "
159                   "ANSI library (should use <stdarg.h>)",
160                   cstring_fromChars (libname)),
161          tmp);
162       
163       fileloc_free (tmp);
164       cstring_free (xname);
165       return TRUE;
166     }
167
168   if (context_getFlag (FLG_SKIPISOHEADERS)
169       && context_usingAnsiLibrary ())
170     {
171       for (i = 0; i < NUMLIBS; i++)
172         {
173           if (mstring_equal (libname, stdlibs[i]))
174             {
175               sfree (xname);
176               return TRUE;
177             }
178         }
179     }
180
181   for (i = 0; i < NUMPOSIXLIBS; i++)
182     {
183       if (strchr (posixlibs[i], CONNECTCHAR) != NULL
184 # if defined (OS2)
185           || strchr (posixlibs[i], ALTCONNECTCHAR) != NULL
186 # endif
187           )
188         {
189           char *ptr;
190           
191           DPRINTF (("xname: %s, posix: %s", xname, posixlibs[i]));
192           if ((ptr = strstr (xname, posixlibs[i])) != NULL) 
193             {
194               if (ptr[strlen (posixlibs[i])] == '\0')
195                 {
196                   posixlib = TRUE;
197                   matchname = ptr;
198                   break;
199                 }
200               else
201                 {
202                   ; /* no match */
203                 }
204             }
205         }
206       else
207         {
208           if (mstring_equal (libname, posixlibs[i]))
209             {
210               posixlib = TRUE;
211               matchname = libname;
212               break;
213             }
214           /*@-branchstate@*/ 
215         }
216     } /*@=branchstate@*/
217   
218   if (posixlib)
219     {
220       if (context_usingPosixLibrary ())
221         {
222           if (context_getFlag (FLG_SKIPPOSIXHEADERS))
223             {
224               cstring_free (xname);
225               /*@-nullstate@*/ 
226               return TRUE; 
227               /*@=nullstate@*/
228
229               /* evans 2002-03-02: 
230                    the returned reference is possibly null,
231                    but this should not change the null state of the parameter
232               */
233             }
234         }
235       else
236         {       
237           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
238           
239           voptgenerror 
240             (FLG_WARNPOSIX,
241              message ("Include file <%s.h> matches the name of a "
242                       "POSIX library, but the POSIX library is "
243                       "not being used.  Consider using +posixlib "
244                       "or +posixstrictlib to select the POSIX "
245                       "library, or -warnposix "
246                       "to suppress this message.",
247                       cstring_fromChars (matchname)),
248              tmp);
249           
250           fileloc_free (tmp);
251         }
252     }
253
254   cstring_free (xname);
255   /*@noaccess cstring@*/
256   /*@-nullstate@*/ /* same problem as above */
257   return FALSE;
258   /*@=nullstate@*/
259 }
260
261 static void printDot (void)
262 {
263   displayScanContinue (cstring_makeLiteralTemp ("."));
264 }
265
266 void
267 dumpState (cstring cfname)
268 {
269   FILE *f;
270   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
271   
272   f = fileTable_openWriteFile (context_fileTable (), fname);
273
274   displayScanOpen (message ("Dumping to %s ", fname)); 
275   
276   if (f == NULL)
277     {
278       lldiagmsg (message ("Cannot open dump file for writing: %s", fname));
279     }
280   else
281     {
282       /*
283       ** sequence is convulted --- must call usymtab_prepareDump before
284       **    dumping ctype table to convert type uid's
285       */
286
287       printDot ();
288
289       /*
290       DPRINTF (("Before prepare dump:"));
291       ctype_printTable ();
292       DPRINTF (("Preparing dump..."));
293       */
294
295       usymtab_prepareDump ();
296
297       /*
298       ** Be careful, these lines must match loadLCDFile checking.
299       */
300
301       fprintf (f, "%s %s\n", LIBRARY_MARKER, cstring_toCharsSafe (fname));
302       fprintf (f, ";;Splint %f\n", SPLINT_LIBVERSION);
303       fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
304       fprintf (f, ";;ctTable\n");
305       
306       DPRINTF (("Dumping types..."));
307       printDot ();
308       ctype_dumpTable (f);
309       printDot ();
310       
311       DPRINTF (("Dumping type sets..."));
312       fprintf (f, ";;tistable\n");
313       typeIdSet_dumpTable (f);
314       printDot ();
315       
316       DPRINTF (("Dumping usymtab..."));
317       fprintf (f, ";;symTable\n");
318       usymtab_dump (f);
319       printDot ();
320
321       DPRINTF (("Dumping modules..."));
322       fprintf (f, ";; Modules access\n");
323       context_dumpModuleAccess (f);
324       fprintf (f, ";;End\n");
325       check (fileTable_closeFile (context_fileTable (), f));
326     }
327
328   displayScanClose ();
329   cstring_free (fname);
330 }
331
332 bool
333 loadStandardState ()
334 {
335   cstring fpath;
336   FILE *stdlib;
337   bool result;
338   cstring libname = fileLib_addExtension (context_selectedLibrary (), 
339                                           cstring_makeLiteralTemp (DUMP_SUFFIX));
340   
341   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
342     {
343       lldiagmsg (message ("Cannot find %sstandard library: %s", 
344                           cstring_makeLiteralTemp 
345                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
346                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
347                           libname));
348       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
349       result = FALSE;
350     }
351   else
352     {
353       stdlib = fileTable_openReadFile (context_fileTable (), fpath);
354
355       if (stdlib == NULL)
356         {
357           lldiagmsg (message ("Cannot read standard library: %s",
358                               fpath));
359           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
360
361           result = FALSE;
362         }
363       else
364         {
365           if (context_getFlag (FLG_WHICHLIB))
366             {
367               char *t = mstring_create (MAX_NAME_LENGTH);
368               char *ot = t;
369
370               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
371                 {
372                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
373                 }
374
375               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
376                 {
377                   if (*t == ';' && *(t + 1) == ';') 
378                     {
379                       t += 2;
380                     }
381                 }
382
383               if (t == NULL)
384                 {
385                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
386                                       fpath));
387                 }
388               else
389                 {
390                   char *tt;
391
392                   tt = strrchr (t, '\n');
393                   if (tt != NULL)
394                     *tt = '\0';
395
396                   lldiagmsg (message ("Standard library: %s", fpath));
397                   /* evans 2004-01-13: removed this (it is the libversion which is confusing) */
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.092991 seconds and 5 git commands to generate.