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