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