Moved OS dependent constants from constants.h to osd.h
[splint-patched.git] / src / lcllib.c
blob5e151252dcd4e23c89c1f2f36065a57b78725154
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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.
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
25 ** lcllib.c
27 ** routines for loading and creating library files
29 ** this is a brute-force implementation, a more efficient
30 ** representation should be designed.
35 * Herbert 02/17/2002:
36 * - fixed the recognition of Posix headers for OS/2
39 # include "splintMacros.nf"
40 # include "basic.h"
41 # include "osd.h"
42 # include "version.h"
44 # include "lclscan.h"
46 # include "lcllib.h"
47 # include "llmain.h"
49 /*@constant int NUMLIBS; @*/
50 # define NUMLIBS 25
52 /*@constant int NUMPOSIXLIBS; @*/
53 # define NUMPOSIXLIBS 18
55 static ob_mstring posixlibs[NUMPOSIXLIBS] =
57 "dirent",
58 "fcntl",
59 "grp",
60 "pwd",
61 "regex",
62 "sys/stat",
63 "sys/times",
64 "sys/types",
65 "netdb", /* unix */
66 "netinet/in", /* unix */
67 "sys/resource", /* unix */
68 "sys/socket", /* not posix */
69 "sys/syslog", /* not posix */
70 "sys/utsname",
71 "sys/wait",
72 "termios",
73 "unistd",
74 "utime"
75 } ;
77 static ob_mstring stdlibs[NUMLIBS] =
79 "assert",
80 "complex"
81 "ctype",
82 "errno",
83 "fenv",
84 "float",
85 "inttypes",
86 "iso646",
87 "limits",
88 "locale",
89 "math",
90 "setjmp",
91 "signal",
92 "stdarg",
93 "stdbool",
94 "stddef",
95 "stdint",
96 "stdio",
97 "stdlib",
98 "string",
99 "strings", /* some systems use this...they shouldn't */
100 "tgmath",
101 "time",
102 "wchar",
103 "wctype"
106 static bool loadLCDFile (FILE * p_f, cstring p_name);
108 bool
109 lcllib_isSkipHeader (cstring sname)
111 int i;
112 bool posixlib = FALSE;
113 char *libname;
114 char *matchname;
115 cstring xname;
117 llassert (cstring_isDefined (sname));
118 xname = fileLib_withoutExtension (sname, cstring_makeLiteralTemp (".h"));
120 DPRINTF (("Include? %s", sname));
122 /*@access cstring@*/
123 llassert (cstring_isDefined (xname));
124 # if defined (OS2)
126 /* Posixlibs use forward slashes, so we use them here, too */
127 cstring_replaceAll (xname, '\\', '/');
128 libname = strrchr (xname, '/');
129 DPRINTF (("libname: %s", libname));
131 # else
132 libname = strrchr (xname, CONNECTCHAR);
133 # endif
134 matchname = libname;
136 if (libname == NULL)
138 libname = xname;
140 else
142 libname++;
143 /*@-branchstate@*/
145 /*@=branchstate@*/
147 if (mstring_equal (libname, "varargs"))
149 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
151 voptgenerror
152 (FLG_USEVARARGS,
153 message ("Include file <%s.h> is inconsistent with "
154 "ANSI library (should use <stdarg.h>)",
155 cstring_fromChars (libname)),
156 tmp);
158 fileloc_free (tmp);
159 cstring_free (xname);
160 return TRUE;
163 if (context_getFlag (FLG_SKIPISOHEADERS)
164 && context_usingAnsiLibrary ())
166 for (i = 0; i < NUMLIBS; i++)
168 if (mstring_equal (libname, stdlibs[i]))
170 sfree (xname);
171 return TRUE;
176 for (i = 0; i < NUMPOSIXLIBS; i++)
178 if (strchr (posixlibs[i], CONNECTCHAR) != NULL
179 # if defined (OS2)
180 || strchr (posixlibs[i], ALTCONNECTCHAR) != NULL
181 # endif
184 char *ptr;
186 DPRINTF (("xname: %s, posix: %s", xname, posixlibs[i]));
187 if ((ptr = strstr (xname, posixlibs[i])) != NULL)
189 if (ptr[strlen (posixlibs[i])] == '\0')
191 posixlib = TRUE;
192 matchname = ptr;
193 break;
195 else
197 ; /* no match */
201 else
203 if (mstring_equal (libname, posixlibs[i]))
205 posixlib = TRUE;
206 matchname = libname;
207 break;
209 /*@-branchstate@*/
211 } /*@=branchstate@*/
213 if (posixlib)
215 if (context_usingPosixLibrary ())
217 if (context_getFlag (FLG_SKIPPOSIXHEADERS))
219 cstring_free (xname);
220 /*@-nullstate@*/
221 return TRUE;
222 /*@=nullstate@*/
224 /* evans 2002-03-02:
225 the returned reference is possibly null,
226 but this should not change the null state of the parameter
230 else
232 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
234 voptgenerror
235 (FLG_WARNPOSIX,
236 message ("Include file <%s.h> matches the name of a "
237 "POSIX library, but the POSIX library is "
238 "not being used. Consider using +posixlib "
239 "or +posixstrictlib to select the POSIX "
240 "library, or -warnposix "
241 "to suppress this message.",
242 cstring_fromChars (matchname)),
243 tmp);
245 fileloc_free (tmp);
249 cstring_free (xname);
250 /*@noaccess cstring@*/
251 /*@-nullstate@*/ /* same problem as above */
252 return FALSE;
253 /*@=nullstate@*/
256 static void printDot (void)
258 displayScanContinue (cstring_makeLiteralTemp ("."));
261 void
262 dumpState (cstring cfname)
264 FILE *f;
265 cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
267 f = fileTable_openWriteFile (context_fileTable (), fname);
269 displayScanOpen (message ("Dumping to %s ", fname));
271 if (f == NULL)
273 lldiagmsg (message ("Cannot open dump file for writing: %s", fname));
275 else
278 ** sequence is convulted --- must call usymtab_prepareDump before
279 ** dumping ctype table to convert type uid's
282 printDot ();
285 DPRINTF (("Before prepare dump:"));
286 ctype_printTable ();
287 DPRINTF (("Preparing dump..."));
290 usymtab_prepareDump ();
293 ** Be careful, these lines must match loadLCDFile checking.
296 fprintf (f, "%s %s\n", LIBRARY_MARKER, cstring_toCharsSafe (fname));
297 fprintf (f, ";;Splint %f\n", SPLINT_LIBVERSION);
298 fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
299 fprintf (f, ";;ctTable\n");
301 DPRINTF (("Dumping types..."));
302 printDot ();
303 ctype_dumpTable (f);
304 printDot ();
306 DPRINTF (("Dumping type sets..."));
307 fprintf (f, ";;tistable\n");
308 typeIdSet_dumpTable (f);
309 printDot ();
311 DPRINTF (("Dumping usymtab..."));
312 fprintf (f, ";;symTable\n");
313 usymtab_dump (f);
314 printDot ();
316 DPRINTF (("Dumping modules..."));
317 fprintf (f, ";; Modules access\n");
318 context_dumpModuleAccess (f);
319 fprintf (f, ";;End\n");
320 check (fileTable_closeFile (context_fileTable (), f));
323 displayScanClose ();
324 cstring_free (fname);
327 bool
328 loadStandardState ()
330 cstring fpath;
331 FILE *stdlib;
332 bool result;
333 cstring libname = fileLib_addExtension (context_selectedLibrary (),
334 cstring_makeLiteralTemp (DUMP_SUFFIX));
336 if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
338 lldiagmsg (message ("Cannot find %sstandard library: %s",
339 cstring_makeLiteralTemp
340 (context_getFlag (FLG_STRICTLIB) ? "strict "
341 : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
342 libname));
343 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
344 result = FALSE;
346 else
348 stdlib = fileTable_openReadFile (context_fileTable (), fpath);
350 if (stdlib == NULL)
352 lldiagmsg (message ("Cannot read standard library: %s",
353 fpath));
354 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
356 result = FALSE;
358 else
360 if (context_getFlag (FLG_WHICHLIB))
362 char *t = mstring_create (MAX_NAME_LENGTH);
363 char *ot = t;
365 if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL)
367 llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
370 if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL)
372 if (*t == ';' && *(t + 1) == ';')
374 t += 2;
378 if (t == NULL)
380 lldiagmsg (message ("Standard library: %s <cannot read creation information>",
381 fpath));
383 else
385 char *tt;
387 tt = strrchr (t, '\n');
388 if (tt != NULL)
389 *tt = '\0';
391 lldiagmsg (message ("Standard library: %s", fpath));
392 /* evans 2004-01-13: removed this (it is the libversion which is confusing) */
393 /* lldiagmsg (message (" (created using %s)", cstring_fromChars (t))); */
396 sfree (ot);
398 check (fileTable_closeFile (context_fileTable (), stdlib));
399 stdlib = fileTable_openReadFile (context_fileTable (), fpath);
402 llassert (stdlib != NULL);
404 fileloc_reallyFree (g_currentloc);
405 g_currentloc = fileloc_createLib (libname);
407 DPRINTF (("Loading: %s", fpath));
409 displayScanOpen (message ("loading standard library %s ", fpath));
410 result = loadLCDFile (stdlib, fpath);
411 displayScanClose ();
413 check (fileTable_closeFile (context_fileTable (), stdlib));
417 cstring_free (libname);
418 return result;
421 /*@constant int BUFLEN;@*/
422 # define BUFLEN 128
424 static bool
425 loadLCDFile (FILE *f, cstring name)
427 char buf[BUFLEN];
430 ** Check version. Should be >= SPLINT_LIBVERSION
433 if (reader_readLine (f, buf, BUFLEN) == NULL
434 || !mstring_equalPrefix (buf, LIBRARY_MARKER))
436 loadllmsg (message ("Load library %s is not in Splint library format. Attempting "
437 "to continue without library.", name));
438 return FALSE;
441 if (reader_readLine (f, buf, BUFLEN) != NULL)
443 if (!mstring_equalPrefix (buf, ";;"))
445 loadllmsg (message ("Load library %s is not in Splint library format. Attempting "
446 "to continue without library.", name));
447 return FALSE;
449 else if (mstring_equalPrefix (buf, ";;ctTable"))
451 loadllmsg (message ("Load library %s is in obsolete Splint library format. Attempting "
452 "to continue anyway, but results may be incorrect. Rebuild "
453 "the library with this version of splint.",
454 name));
456 else
458 float version = 0.0;
460 if (sscanf (buf, ";;Splint %f", &version) != 1
461 && (sscanf (buf, ";;LCLint %f", &version) != 1))
463 loadllmsg (message ("Load library %s is not in Splint library format (missing version "
464 "number). Attempting "
465 "to continue without library.", name));
466 return FALSE;
468 else
470 if ((SPLINT_LIBVERSION - version) >= FLT_EPSILON)
472 cstring vname;
473 char *nl = strchr (buf, '\n');
475 *nl = '\0';
477 vname = cstring_fromChars (buf + 9);
479 loadllmsg (message ("Load library %s is in obsolete Splint library "
480 "format (version %f (%s), expecting version %f). Attempting "
481 "to continue anyway, but results may be incorrect. Rebuild "
482 "the library with this version of splint.",
483 name,
484 version,
485 vname,
486 SPLINT_LIBVERSION));
488 else
490 if (reader_readLine (f, buf, BUFLEN) == NULL)
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;
497 else
499 int lib;
501 if (sscanf (buf, ";;lib:%d", &lib) != 1)
503 loadllmsg (message ("Load library %s is not in Splint library "
504 "format (missing library code). Attempting "
505 "to continue without library.", name));
506 return FALSE;
508 else
510 flagcode code = (flagcode) lib;
512 if (flagcode_isLibraryFlag (code))
514 if (context_doMerge ())
516 context_setLibrary (code);
519 else
521 loadllmsg (message ("Load library %s has invalid library code (%s). "
522 "Attempting to continue without library.",
523 name,
524 flagcode_unparse (code)));
526 return FALSE;
534 else
536 loadllmsg (message ("Load library %s is not in Splint library format (missing lines). "
537 "Attempting to continue without library.", name));
538 return FALSE;
541 ctype_loadTable (f);
542 printDot ();
544 typeIdSet_loadTable (f);
545 printDot ();
547 usymtab_load (f);
548 printDot ();
550 context_loadModuleAccess (f);
551 printDot ();
553 return TRUE;
557 ** load state from file created by dumpState
560 void
561 loadState (cstring cfname)
563 FILE *f;
564 cstring fname = fileLib_addExtension (cfname, cstring_makeLiteralTemp (DUMP_SUFFIX));
566 f = fileTable_openReadFile (context_fileTable (), fname);
568 if (f == NULL)
570 displayScanClose ();
571 llfatalerror (message ("Cannot open dump file for loading: %s",
572 fname));
574 else
576 fileloc_reallyFree (g_currentloc);
577 g_currentloc = fileloc_createLib (cfname);
579 if (!loadLCDFile (f, cfname))
581 if (!loadStandardState ())
583 ctype_initTable ();
587 check (fileTable_closeFile (context_fileTable (), f));
590 /* usymtab_printAll (); */
591 cstring_free (fname);