]> andersk Git - splint.git/blob - src/lcllib.c
Making fixes for Microsoft Visual C++ compiler.
[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                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
398                 }
399
400               sfree (ot);
401               
402               check (fileTable_closeFile (context_fileTable (), stdlib));
403               stdlib = fileTable_openReadFile (context_fileTable (), fpath);
404             }
405
406           llassert (stdlib != NULL);
407
408           fileloc_reallyFree (g_currentloc);
409           g_currentloc = fileloc_createLib (libname);
410
411           DPRINTF (("Loading: %s", fpath));
412
413           displayScanOpen (message ("loading standard library %s ", fpath));
414           result = loadLCDFile (stdlib, fpath);
415           displayScanClose ();
416
417           check (fileTable_closeFile (context_fileTable (), stdlib));
418         }
419     }
420
421   cstring_free (libname);
422   return result;
423 }
424
425 /*@constant int BUFLEN;@*/
426 # define BUFLEN 128
427
428 static bool
429 loadLCDFile (FILE *f, cstring name)
430 {
431   char buf[BUFLEN];
432   
433   /*
434   ** Check version.  Should be >= SPLINT_LIBVERSION
435   */
436
437   if (reader_readLine (f, buf, BUFLEN) == NULL
438       || !mstring_equalPrefix (buf, LIBRARY_MARKER))
439     {
440       loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
441                           "to continue without library.", name));
442       return FALSE;
443     }
444   
445   if (reader_readLine (f, buf, BUFLEN) != NULL)
446     {
447       if (!mstring_equalPrefix (buf, ";;"))
448         {
449           loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
450                               "to continue without library.", name));
451           return FALSE;
452         }
453       else if (mstring_equalPrefix (buf, ";;ctTable"))
454         {
455           loadllmsg (message ("Load library %s is in obsolete Splint library format.  Attempting "
456                               "to continue anyway, but results may be incorrect.  Rebuild "
457                               "the library with this version of splint.", 
458                               name));
459         }
460       else 
461         {
462           float version = 0.0;
463
464           if (sscanf (buf, ";;Splint %f", &version) != 1
465               && (sscanf (buf, ";;LCLint %f", &version) != 1))
466             {
467               loadllmsg (message ("Load library %s is not in Splint library format (missing version "
468                                   "number).  Attempting "
469                                   "to continue without library.", name));
470               return FALSE;
471             }
472           else
473             {
474               if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
475                 {
476                   cstring vname;
477                   char *nl = strchr (buf, '\n');
478
479                   *nl = '\0';
480
481                   vname = cstring_fromChars (buf + 9);
482
483                   loadllmsg (message ("Load library %s is in obsolete Splint library "
484                                       "format (version %f (%s), expecting version %f).  Attempting "
485                                       "to continue anyway, but results may be incorrect.  Rebuild "
486                                       "the library with this version of splint.", 
487                                       name, 
488                                       version,
489                                       vname, 
490                                       SPLINT_LIBVERSION));
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.09007 seconds and 5 git commands to generate.