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