]> andersk Git - splint.git/blob - src/lcllib.c
Fixed line numbering when multi-line macro parameters are used.
[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               return TRUE; /* evans 2002-03-02: investigate this warning */
230             }
231         }
232       else
233         {       
234           fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);           
235           
236           voptgenerror 
237             (FLG_WARNPOSIX,
238              message ("Include file <%s.h> matches the name of a "
239                       "POSIX library, but the POSIX library is "
240                       "not being used.  Consider using +posixlib "
241                       "or +posixstrictlib to select the POSIX "
242                       "library, or -warnposix "
243                       "to suppress this message.",
244                       cstring_fromChars (matchname)),
245              tmp);
246           
247           fileloc_free (tmp);
248         }
249     }
250
251   cstring_free (xname);
252   /*@noaccess cstring@*/
253   return FALSE;
254 }
255
256 static void printDot (void)
257 {
258   if (context_getFlag (FLG_SHOWSCAN)) 
259     {
260       (void) fflush (g_msgstream);
261       fprintf (stderr, "."); 
262       (void) fflush (stderr);
263     }
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_openFile (context_fileTable (), fname, "w");
273
274   if (context_getFlag (FLG_SHOWSCAN))
275     {
276       fprintf (stderr, "< Dumping to %s ", cstring_toCharsSafe (fname)); 
277     }
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   if (context_getFlag (FLG_SHOWSCAN))
332     {
333       fprintf (g_msgstream, " >\n");
334     }
335
336   cstring_free (fname);
337 }
338
339 bool
340 loadStandardState ()
341 {
342   cstring fpath;
343   FILE *stdlib;
344   bool result;
345   cstring libname = fileLib_addExtension (context_selectedLibrary (), 
346                                           cstring_makeLiteralTemp (DUMP_SUFFIX));
347   
348   if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
349     {
350       lldiagmsg (message ("Cannot find %sstandard library: %s", 
351                           cstring_makeLiteralTemp 
352                           (context_getFlag (FLG_STRICTLIB) ? "strict " 
353                            : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
354                           libname));
355       lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
356       result = FALSE;
357     }
358   else
359     {
360       stdlib = fileTable_openFile (context_fileTable (), fpath, "r");
361
362       if (stdlib == NULL)
363         {
364           lldiagmsg (message ("Cannot read standard library: %s",
365                               fpath));
366           lldiagmsg (cstring_makeLiteral ("     Check LARCH_PATH environment variable."));
367
368           result = FALSE;
369         }
370       else
371         {
372           if (context_getFlag (FLG_WHICHLIB))
373             {
374               char *t = mstring_create (MAX_NAME_LENGTH);
375               char *ot = t;
376
377               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
378                 {
379                   llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
380                 }
381
382               if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
383                 {
384                   if (*t == ';' && *(t + 1) == ';') 
385                     {
386                       t += 2;
387                     }
388                 }
389
390               if (t == NULL)
391                 {
392                   lldiagmsg (message ("Standard library: %s <cannot read creation information>", 
393                                       fpath));
394                 }
395               else
396                 {
397                   char *tt;
398
399                   tt = strrchr (t, '\n');
400                   if (tt != NULL)
401                     *tt = '\0';
402
403                   lldiagmsg (message ("Standard library: %s", fpath));
404                   lldiagmsg (message ("   (created using %s)", cstring_fromChars (t)));
405                 }
406
407               sfree (ot);
408               
409               check (fileTable_closeFile (context_fileTable (), stdlib));
410               stdlib = fileTable_openFile (context_fileTable (), fpath, "r");
411             }
412
413           llassert (stdlib != NULL);
414
415           fileloc_reallyFree (g_currentloc);
416           g_currentloc = fileloc_createLib (libname);
417
418           DPRINTF (("Loading: %s", fpath));
419
420           if (context_getDebug (FLG_SHOWSCAN))
421             {
422               fprintf (g_msgstream, "< loading standard library %s ", 
423                        cstring_toCharsSafe (fpath));
424               result = loadLCDFile (stdlib, fpath);
425               fprintf (g_msgstream, " >\n");
426             }
427           else
428             {
429               result = loadLCDFile (stdlib, fpath);
430             }
431
432           check (fileTable_closeFile (context_fileTable (), stdlib));
433         }
434     }
435
436   cstring_free (libname);
437   return result;
438 }
439
440 /*@constant int BUFLEN;@*/
441 # define BUFLEN 128
442
443 static bool
444 loadLCDFile (FILE *f, cstring name)
445 {
446   char buf[BUFLEN];
447   
448   /*
449   ** Check version.  Should be >= SPLINT_LIBVERSION
450   */
451
452   if (reader_readLine (f, buf, BUFLEN) == NULL
453       || !mstring_equalPrefix (buf, LIBRARY_MARKER))
454     {
455       loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
456                           "to continue without library.", name));
457       return FALSE;
458     }
459   
460   if (reader_readLine (f, buf, BUFLEN) != NULL)
461     {
462       if (!mstring_equalPrefix (buf, ";;"))
463         {
464           loadllmsg (message ("Load library %s is not in Splint library format.  Attempting "
465                               "to continue without library.", name));
466           return FALSE;
467         }
468       else if (mstring_equalPrefix (buf, ";;ctTable"))
469         {
470           loadllmsg (message ("Load library %s is in obsolete Splint library format.  Attempting "
471                               "to continue anyway, but results may be incorrect.  Rebuild "
472                               "the library with this version of splint.", 
473                               name));
474         }
475       else 
476         {
477           float version = 0.0;
478
479           if (sscanf (buf, ";;Splint %f", &version) != 1
480               && (sscanf (buf, ";;LCLint %f", &version) != 1))
481             {
482               loadllmsg (message ("Load library %s is not in Splint library format (missing version "
483                                   "number).  Attempting "
484                                   "to continue without library.", name));
485               return FALSE;
486             }
487           else
488             {
489               if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
490                 {
491                   cstring vname;
492                   char *nl = strchr (buf, '\n');
493
494                   *nl = '\0';
495
496                   vname = cstring_fromChars (buf + 9);
497
498                   loadllmsg (message ("Load library %s is in obsolete Splint library "
499                                       "format (version %s).  Attempting "
500                                       "to continue anyway, but results may be incorrect.  Rebuild "
501                                       "the library with this version of splint.", 
502                                       name, vname));
503                 }
504               else
505                 {
506                   if (reader_readLine (f, buf, BUFLEN) == NULL)
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                       int lib;
516                       
517                       if (sscanf (buf, ";;lib:%d", &lib) != 1)
518                         {
519                           loadllmsg (message ("Load library %s is not in Splint library "
520                                               "format (missing library code). Attempting "
521                                               "to continue without library.", name));
522                           return FALSE;
523                         }
524                       else
525                         {
526                           flagcode code = (flagcode) lib;
527
528                           if (flagcode_isLibraryFlag (code))
529                             {
530                               if (context_doMerge ()) 
531                                 {
532                                   context_setLibrary (code);
533                                 }
534                             }
535                           else
536                             {
537                               loadllmsg (message ("Load library %s has invalid library code (%s).  "
538                                                   "Attempting to continue without library.",
539                                                   name,
540                                                   flagcode_unparse (code)));
541                               
542                               return FALSE;
543                             }
544                         }
545                     }
546                 }
547             }
548         }
549     }
550   else
551     {
552       loadllmsg (message ("Load library %s is not in Splint library format (missing lines).  "
553                           "Attempting to continue without library.", name));
554       return FALSE;
555     }
556   
557   ctype_loadTable (f);
558   printDot ();
559   
560   typeIdSet_loadTable (f);
561   printDot ();
562   
563   usymtab_load (f);
564   printDot ();
565   
566   context_loadModuleAccess (f);
567   printDot ();
568   
569   return TRUE;
570 }
571
572 /*
573 ** load state from file created by dumpState
574 */
575
576 void
577 loadState (cstring cfname)
578 {
579   FILE *f;
580   cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
581
582   f = fileTable_openFile (context_fileTable (), fname, "r");
583
584   if (f == NULL)
585     {
586       if (context_getDebug (FLG_SHOWSCAN))
587         fprintf (g_msgstream, " >\n");
588
589       llfatalerror (message ("Cannot open dump file for loading: %s", 
590                              fname));
591     }
592   else
593     {
594       fileloc_reallyFree (g_currentloc);
595       g_currentloc = fileloc_createLib (cfname);
596
597       if (!loadLCDFile (f, cfname)) 
598         {
599           if (!loadStandardState ()) 
600             {
601               ctype_initTable ();
602             }
603         }
604       
605       check (fileTable_closeFile (context_fileTable (), f));
606     }
607
608   /* usymtab_printAll (); */
609   cstring_free (fname);
610 }
611
This page took 0.213243 seconds and 5 git commands to generate.