]> andersk Git - splint.git/blame_incremental - src/lcllib.c
Fixed bug in makefile causing unnecessary remaking of cgrammar.c.
[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 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# include "version.h"
43
44# include "gram.h"
45# include "lclscan.h"
46
47# include "lcllib.h"
48# include "llmain.h"
49# include "portab.h"
50
51/*@-incondefs@*/ /*@-redecl@*/
52extern /*:open:*/ /*@dependent@*/ FILE *yyin;
53/*@=incondefs@*/ /*@=redecl@*/
54
55/*@constant int NUMLIBS; @*/
56# define NUMLIBS 25
57
58/*@constant int NUMPOSIXLIBS; @*/
59# define NUMPOSIXLIBS 18
60
61static ob_mstring posixlibs[NUMPOSIXLIBS] =
62{
63 "dirent",
64 "fcntl",
65 "grp",
66 "pwd",
67 "regex",
68 "sys/stat",
69 "sys/times",
70 "sys/types",
71 "netdb", /* unix */
72 "netinet/in", /* unix */
73 "sys/resource", /* unix */
74 "sys/socket", /* not posix */
75 "sys/syslog", /* not posix */
76 "sys/utsname",
77 "sys/wait",
78 "termios",
79 "unistd",
80 "utime"
81} ;
82
83static ob_mstring stdlibs[NUMLIBS] =
84{
85 "assert",
86 "complex"
87 "ctype",
88 "errno",
89 "fenv",
90 "float",
91 "inttypes",
92 "iso646",
93 "limits",
94 "locale",
95 "math",
96 "setjmp",
97 "signal",
98 "stdarg",
99 "stdbool",
100 "stddef",
101 "stdint",
102 "stdio",
103 "stdlib",
104 "string",
105 "strings", /* some systems use this...they shouldn't */
106 "tgmath",
107 "time",
108 "wchar",
109 "wctype"
110} ;
111
112static bool loadLCDFile (FILE * p_f, cstring p_name);
113
114bool
115lcllib_isSkipHeader (cstring sname)
116{
117 int i;
118 bool posixlib = FALSE;
119 char *libname;
120 char *matchname;
121 cstring xname;
122
123 llassert (cstring_isDefined (sname));
124 xname = fileLib_withoutExtension (sname, cstring_makeLiteralTemp (".h"));
125
126 DPRINTF (("Include? %s", sname));
127
128 /*@access cstring@*/
129 llassert (cstring_isDefined (xname));
130# if defined (OS2)
131 {
132 /* Posixlibs use forward slashes, so we use them here, too */
133 cstring_replaceAll (xname, '\\', '/');
134 libname = strrchr (xname, '/');
135 DPRINTF (("libname: %s", libname));
136 }
137# else
138 libname = strrchr (xname, CONNECTCHAR);
139# endif
140 matchname = libname;
141
142 if (libname == NULL)
143 {
144 libname = xname;
145 }
146 else
147 {
148 libname++;
149 /*@-branchstate@*/
150 }
151 /*@=branchstate@*/
152
153 if (mstring_equal (libname, "varargs"))
154 {
155 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
156
157 voptgenerror
158 (FLG_USEVARARGS,
159 message ("Include file <%s.h> is inconsistent with "
160 "ANSI library (should use <stdarg.h>)",
161 cstring_fromChars (libname)),
162 tmp);
163
164 fileloc_free (tmp);
165 cstring_free (xname);
166 return TRUE;
167 }
168
169 if (context_getFlag (FLG_SKIPISOHEADERS)
170 && context_usingAnsiLibrary ())
171 {
172
173 for (i = 0; i < NUMLIBS; i++)
174 {
175 if (mstring_equal (libname, stdlibs[i]))
176 {
177 sfree (xname);
178 return TRUE;
179 }
180 }
181 }
182
183 for (i = 0; i < NUMPOSIXLIBS; i++)
184 {
185 if (strchr (posixlibs[i], CONNECTCHAR) != NULL
186# if defined (OS2)
187 || strchr (posixlibs[i], ALTCONNECTCHAR) != NULL
188# endif
189 )
190 {
191 char *ptr;
192
193 DPRINTF (("xname: %s, posix: %s", xname, posixlibs[i]));
194 if ((ptr = strstr (xname, posixlibs[i])) != NULL)
195 {
196 if (ptr[strlen (posixlibs[i])] == '\0')
197 {
198 posixlib = TRUE;
199 matchname = ptr;
200 break;
201 }
202 else
203 {
204 ; /* no match */
205 }
206 }
207 }
208 else
209 {
210 if (mstring_equal (libname, posixlibs[i]))
211 {
212 posixlib = TRUE;
213 matchname = libname;
214 break;
215 }
216 /*@-branchstate@*/
217 }
218 } /*@=branchstate@*/
219
220 if (posixlib)
221 {
222 if (context_usingPosixLibrary ())
223 {
224 if (context_getFlag (FLG_SKIPPOSIXHEADERS))
225 {
226 cstring_free (xname);
227 /*@-nullstate@*/
228 return TRUE;
229 /*@=nullstate@*/
230 /*@i233@*/
231 /* evans 2002-03-02:
232 the returned reference is possibly null,
233 but this should not change the null state of the parameter
234 investigate this warning
235 */
236 }
237 }
238 else
239 {
240 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
241
242 voptgenerror
243 (FLG_WARNPOSIX,
244 message ("Include file <%s.h> matches the name of a "
245 "POSIX library, but the POSIX library is "
246 "not being used. Consider using +posixlib "
247 "or +posixstrictlib to select the POSIX "
248 "library, or -warnposix "
249 "to suppress this message.",
250 cstring_fromChars (matchname)),
251 tmp);
252
253 fileloc_free (tmp);
254 }
255 }
256
257 cstring_free (xname);
258 /*@noaccess cstring@*/
259 /*@-nullstate@*/ /*@i233@*/ /* same problem as above */
260 return FALSE;
261 /*@=nullstate@*/
262}
263
264static void printDot (void)
265{
266 displayScanContinue (cstring_makeLiteralTemp ("."));
267}
268
269void
270dumpState (cstring cfname)
271{
272 FILE *f;
273 cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
274
275 f = fileTable_openWriteFile (context_fileTable (), fname);
276
277 displayScanOpen (message ("Dumping to %s ", fname));
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 displayScanClose ();
332 cstring_free (fname);
333}
334
335bool
336loadStandardState ()
337{
338 cstring fpath;
339 FILE *stdlib;
340 bool result;
341 cstring libname = fileLib_addExtension (context_selectedLibrary (),
342 cstring_makeLiteralTemp (DUMP_SUFFIX));
343
344 if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
345 {
346 lldiagmsg (message ("Cannot find %sstandard library: %s",
347 cstring_makeLiteralTemp
348 (context_getFlag (FLG_STRICTLIB) ? "strict "
349 : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
350 libname));
351 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
352 result = FALSE;
353 }
354 else
355 {
356 stdlib = fileTable_openReadFile (context_fileTable (), fpath);
357
358 if (stdlib == NULL)
359 {
360 lldiagmsg (message ("Cannot read standard library: %s",
361 fpath));
362 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
363
364 result = FALSE;
365 }
366 else
367 {
368 if (context_getFlag (FLG_WHICHLIB))
369 {
370 char *t = mstring_create (MAX_NAME_LENGTH);
371 char *ot = t;
372
373 if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
374 {
375 llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
376 }
377
378 if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
379 {
380 if (*t == ';' && *(t + 1) == ';')
381 {
382 t += 2;
383 }
384 }
385
386 if (t == NULL)
387 {
388 lldiagmsg (message ("Standard library: %s <cannot read creation information>",
389 fpath));
390 }
391 else
392 {
393 char *tt;
394
395 tt = strrchr (t, '\n');
396 if (tt != NULL)
397 *tt = '\0';
398
399 lldiagmsg (message ("Standard library: %s", fpath));
400 lldiagmsg (message (" (created using %s)", cstring_fromChars (t)));
401 }
402
403 sfree (ot);
404
405 check (fileTable_closeFile (context_fileTable (), stdlib));
406 stdlib = fileTable_openReadFile (context_fileTable (), fpath);
407 }
408
409 llassert (stdlib != NULL);
410
411 fileloc_reallyFree (g_currentloc);
412 g_currentloc = fileloc_createLib (libname);
413
414 DPRINTF (("Loading: %s", fpath));
415
416 displayScanOpen (message ("loading standard library %s ", fpath));
417 result = loadLCDFile (stdlib, fpath);
418 displayScanClose ();
419
420 check (fileTable_closeFile (context_fileTable (), stdlib));
421 }
422 }
423
424 cstring_free (libname);
425 return result;
426}
427
428/*@constant int BUFLEN;@*/
429# define BUFLEN 128
430
431static bool
432loadLCDFile (FILE *f, cstring name)
433{
434 char buf[BUFLEN];
435
436 /*
437 ** Check version. Should be >= SPLINT_LIBVERSION
438 */
439
440 if (reader_readLine (f, buf, BUFLEN) == NULL
441 || !mstring_equalPrefix (buf, LIBRARY_MARKER))
442 {
443 loadllmsg (message ("Load library %s is not in Splint library format. Attempting "
444 "to continue without library.", name));
445 return FALSE;
446 }
447
448 if (reader_readLine (f, buf, BUFLEN) != NULL)
449 {
450 if (!mstring_equalPrefix (buf, ";;"))
451 {
452 loadllmsg (message ("Load library %s is not in Splint library format. Attempting "
453 "to continue without library.", name));
454 return FALSE;
455 }
456 else if (mstring_equalPrefix (buf, ";;ctTable"))
457 {
458 loadllmsg (message ("Load library %s is in obsolete Splint library format. Attempting "
459 "to continue anyway, but results may be incorrect. Rebuild "
460 "the library with this version of splint.",
461 name));
462 }
463 else
464 {
465 float version = 0.0;
466
467 if (sscanf (buf, ";;Splint %f", &version) != 1
468 && (sscanf (buf, ";;LCLint %f", &version) != 1))
469 {
470 loadllmsg (message ("Load library %s is not in Splint library format (missing version "
471 "number). Attempting "
472 "to continue without library.", name));
473 return FALSE;
474 }
475 else
476 {
477 if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
478 {
479 cstring vname;
480 char *nl = strchr (buf, '\n');
481
482 *nl = '\0';
483
484 vname = cstring_fromChars (buf + 9);
485
486 loadllmsg (message ("Load library %s is in obsolete Splint library "
487 "format (version %s). Attempting "
488 "to continue anyway, but results may be incorrect. Rebuild "
489 "the library with this version of splint.",
490 name, vname));
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
564void
565loadState (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.049605 seconds and 5 git commands to generate.