]> andersk Git - splint.git/blame - src/lcllib.c
Updating to use the LEnsures and LRequires instead of the ensures requires so
[splint.git] / src / lcllib.c
CommitLineData
616915dd 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@*/
52extern /*@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
61static 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
77static 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
98static bool loadStateFile (FILE * p_f, cstring p_name);
99
100bool
101lcllib_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
221static 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
231void
232dumpState (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
296bool
297loadStandardState ()
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
397static bool
398loadStateFile (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
c3e695ff 447 /*drl7x this is evans is code I think
448 I'll need is find out if code is safe or if I
449 broke it somehow... */
450 /*@i223*/ *nl = '\0';
616915dd 451
452 vname = cstring_fromChars (buf + 9);
453
454 loadllmsg (message ("Load library %s is in obsolete LCLint library "
455 "format (version %s). Attempting "
456 "to continue anyway, but results may be incorrect. Rebuild "
457 "the library with this version of lclint.",
458 name, vname));
459 }
460 else
461 {
462 if ((fgets (buf, BUFLEN, f) == NULL))
463 {
464 loadllmsg (message ("Load library %s is not in LCLint library "
465 "format (missing library code). Attempting "
466 "to continue without library.", name));
467 return FALSE;
468 }
469 else
470 {
471 int lib;
472
473 if (sscanf (buf, ";;lib:%d", &lib) != 1)
474 {
475 loadllmsg (message ("Load library %s is not in LCLint library "
476 "format (missing library code). Attempting "
477 "to continue without library.", name));
478 return FALSE;
479 }
480 else
481 {
482 flagcode code = (flagcode) lib;
483
484 if (flagcode_isLibraryFlag (code))
485 {
486 if (context_doMerge ())
487 {
488 context_setLibrary (code);
489 }
490 }
491 else
492 {
493 loadllmsg (message ("Load library %s has invalid library code. "
494 "Attempting to continue without library.",
495 name));
496
497 return FALSE;
498 }
499 }
500 }
501 }
502 }
503 }
504 }
505 else
506 {
507 loadllmsg (message ("Load library %s is not in LCLint library format (missing lines). "
508 "Attempting to continue without library.", name));
509 return FALSE;
510 }
511
512 ctype_loadTable (f);
513 printDot ();
514
515 typeIdSet_loadTable (f);
516 printDot ();
517
518 usymtab_load (f);
519 printDot ();
520
521 context_loadModuleAccess (f);
522 printDot ();
523
524 return TRUE;
525}
526
527/*
528** load state from file created by dumpState
529*/
530
531void
532loadState (cstring cfname)
533{
534 FILE *f;
535 char *fname = cstring_toCharsSafe (cfname);
536 cstring ofname = cstring_copy (cfname);
537
538 fname = addExtension (fname, DUMP_SUFFIX);
539
540 f = fopen (fname, "r");
541
542 if (f == NULL)
543 {
544 if (context_getDebug (FLG_SHOWSCAN))
545 fprintf (g_msgstream, " >\n");
546
547 llfatalerror (message ("Cannot open dump file for loading: %s", cfname));
548 }
549 else
550 {
551 fileloc_reallyFree (g_currentloc);
552 g_currentloc = fileloc_createLib (ofname);
553
554 if (!loadStateFile (f, ofname))
555 {
556 if (!loadStandardState ())
557 {
558 ctype_initTable ();
559 }
560 }
561
562 check (fclose (f) == 0);
563 }
564
565 cstring_free (ofname);
566 sfree (fname);
567}
568
This page took 0.11632 seconds and 5 git commands to generate.