X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/a0a162cdc5db4d998824629e9f4d370b9b68df56..35b9a1d988c06908076e3a6eeae55b1147879607:/src/fileTable.c diff --git a/src/fileTable.c b/src/fileTable.c index f66bbd3..dee235e 100644 --- a/src/fileTable.c +++ b/src/fileTable.c @@ -1,6 +1,6 @@ /* -** LCLint - annotation-assisted static program checker -** Copyright (C) 1994-2000 University of Virginia, +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2003 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,9 +17,9 @@ ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ** MA 02111-1307, USA. ** -** For information on lclint: lclint-request@cs.virginia.edu -** To report a bug: lclint-bug@cs.virginia.edu -** For more information: http://lclint.cs.virginia.edu +** For information on splint: info@splint.org +** To report a bug: splint-bug@splint.org +** For more information: http://www.splint.org */ /* ** fileTable.c @@ -44,18 +44,30 @@ * - Added conditional stuff (#define and #include) for IBM's compiler. */ -# include "lclintMacros.nf" +# include +# include +# include +# include "splintMacros.nf" # include "llbasic.h" # include "osd.h" # include "llmain.h" # include "portab.h" + # if defined(__IBMC__) && defined(OS2) # include +# include # define getpid _getpid +# define S_IRUSR S_IREAD +# define S_IWUSR S_IWRITE +# define S_IXUSR S_IEXEC # endif /*@access fileId*/ +static void +fileTable_addOpen (fileTable p_ft, /*@observer@*/ FILE *p_f, /*@only@*/ cstring p_fname) + /*@modifies p_ft@*/ ; + static bool fileTable_inRange (fileTable ft, fileId fid) /*@*/ { return (fileTable_isDefined (ft) && (fid >= 0) && (fid < ft->nentries)); @@ -63,7 +75,7 @@ static bool fileTable_inRange (fileTable ft, fileId fid) /*@*/ static fileId fileTable_internAddEntry (fileTable p_ft, /*@only@*/ ftentry p_e) /*@modifies p_ft@*/ ; -static /*@only@*/ char *makeTempName (char *p_dir, char *p_pre, char *p_suf); +static /*@only@*/ cstring makeTempName (cstring p_dir, cstring p_pre, cstring p_suf); static /*@only@*/ cstring fileType_unparse (fileType ft) @@ -74,7 +86,9 @@ fileType_unparse (fileType ft) case FILE_NODELETE: return cstring_makeLiteral ("normal"); case FILE_LSLTEMP: return cstring_makeLiteral ("ltemp"); case FILE_HEADER: return cstring_makeLiteral ("header"); + case FILE_XH: return cstring_makeLiteral ("xh"); case FILE_MACROS: return cstring_makeLiteral ("macros"); + case FILE_METASTATE: return cstring_makeLiteral ("metastate"); } BADEXIT; @@ -83,8 +97,39 @@ fileType_unparse (fileType ft) static int fileTable_getIndex (fileTable ft, cstring s) { + int res; + cstring abspath; if (ft == NULL) return NOT_FOUND; - return (hashTable_lookup (ft->htable, s)); + abspath = osd_absolutePath (cstring_undefined, s); + + if (context_getFlag (FLG_CASEINSENSITIVEFILENAMES)) + { + abspath = cstring_downcase (abspath); + } + + DPRINTF (("Absolute path: %s: %s", s, abspath)); + res = cstringTable_lookup (ft->htable, abspath); + cstring_free (abspath); + return res; +} + +static cstring ftentry_unparse (fileTable ft, ftentry fte) +{ + if (fileId_isValid (fte->fder)) + { + llassert (fileTable_isDefined (ft)); + + return message ("%s %q %d (%s)", + fte->fname, + fileType_unparse (fte->ftype), + fte->fder, + ft->elements[fte->fder]->fname); + } + else + { + return message ("%s %q", fte->fname, + fileType_unparse (fte->ftype)); + } } /*@only@*/ cstring @@ -100,21 +145,8 @@ fileTable_unparse (fileTable ft) for (i = 0; i < ft->nentries; i++) { - if (fileId_isValid (ft->elements[i]->fder)) - { - s = message ("%s\n[%d] %s %q %d (%s)", - s, i, - ft->elements[i]->fname, - fileType_unparse (ft->elements[i]->ftype), - ft->elements[i]->fder, - ft->elements[ft->elements[i]->fder]->fname); - } - else - { - s = message ("%s\n[%d] %s %q", s, i, ft->elements[i]->fname, - fileType_unparse (ft->elements[i]->ftype)); - } - } + s = message ("%s\n[%d] %q", s, i, ftentry_unparse (ft, ft->elements[i])); + } return s; } @@ -160,7 +192,6 @@ ftentry_create (/*@keep@*/ cstring tn, bool temp, fileType typ, fileId der) } t->fname = tn; - t->basename = cstring_undefined; t->ftemp = temp; t->ftype = typ; @@ -189,11 +220,16 @@ fileTable_create () ft->nentries = 0; ft->nspace = FTBASESIZE; ft->elements = (ftentry *) dmalloc (FTBASESIZE * sizeof (*ft->elements)); - ft->htable = hashTable_create (FTHASHSIZE); - + ft->htable = cstringTable_create (FTHASHSIZE); + + ft->nopen = 0; + ft->nopenspace = FTBASESIZE; + ft->openelements = (foentry *) dmalloc (FTBASESIZE * sizeof (*ft->openelements)); + return (ft); } +/*@-bounds@*/ static void fileTable_grow (fileTable ft) { @@ -214,6 +250,27 @@ fileTable_grow (fileTable ft) sfree (ft->elements); ft->elements = newent; } +/*@=bounds@*/ +static void +fileTable_growOpen (fileTable ft) +{ + int i; + foentry *newent; + + llassert (fileTable_isDefined (ft)); + + ft->nopenspace = FTBASESIZE; + + newent = (foentry *) dmalloc ((ft->nopen + ft->nopenspace) * sizeof (*newent)); + + for (i = 0; i < ft->nopen; i++) + { + newent[i] = ft->openelements[i]; + } + + sfree (ft->openelements); + ft->openelements = newent; +} static fileId fileTable_internAddEntry (fileTable ft, /*@only@*/ ftentry e) @@ -225,7 +282,23 @@ fileTable_internAddEntry (fileTable ft, /*@only@*/ ftentry e) ft->nspace--; - hashTable_insert (ft->htable, e->fname, ft->nentries); + DPRINTF (("Adding: %s", e->fname)); + + if (context_getFlag (FLG_CASEINSENSITIVEFILENAMES)) + { + cstring sd = cstring_downcase (e->fname); + cstringTable_insert (ft->htable, sd, ft->nentries); + } + else + { + cstringTable_insert (ft->htable, cstring_copy (e->fname), ft->nentries); + } + + /* evans 2002-07-12: + Before, there was no cstring_copy above, and e->fname was free'd in the if branch. + Splint should have caught this, and produced a warning for this assignment. + Why not? + */ ft->elements[ft->nentries] = e; ft->nentries++; @@ -236,47 +309,61 @@ void fileTable_noDelete (fileTable ft, cstring name) { fileId fid = fileTable_lookup (ft, name); - if (fileId_isValid (fid)) { - llassert (fileTable_isDefined (ft)); - - ft->elements[fid]->ftype = FILE_NODELETE; - } + if (fileId_isValid (fid)) + { + llassert (fileTable_isDefined (ft)); + ft->elements[fid]->ftype = FILE_NODELETE; + } + else + { + DPRINTF (("Invalid no delete: %s", name)); + } } static fileId -fileTable_addFilePrim (fileTable ft, /*@only@*/ cstring name, +fileTable_addFilePrim (fileTable ft, /*@temp@*/ cstring name, bool temp, fileType typ, fileId der) /*@modifies ft@*/ { - int tindex = fileTable_getIndex (ft, name); - + cstring absname = osd_absolutePath (NULL, name); + int tindex = fileTable_getIndex (ft, absname); + + /*@i534 fprintf (stderr, "Got abs path: %s", absname); */ llassert (ft != fileTable_undefined); if (tindex != NOT_FOUND) { - llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", name)); - + llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", absname)); return tindex; } else { - ftentry e = ftentry_create (name, temp, typ, der); + ftentry e = ftentry_create (absname, temp, typ, der); if (der == fileId_invalid) { llassert (cstring_isUndefined (e->basename)); - e->basename = cstring_fromChars - (removePathFree (removeAnyExtension - (cstring_toCharsSafe (name)))); - e->fsystem = context_isSystemDir (name); - e->fspecial = context_isSpecialFile (name); + e->basename = fileLib_removePathFree (fileLib_removeAnyExtension (absname)); + e->fsystem = context_isSystemDir (absname); + + /* + ** evans 2002-03-15: change suggested by Jim Zelenka + ** support relative paths for system directories + */ + + if (!e->fsystem) + { + e->fsystem = context_isSystemDir (name); + } + + e->fspecial = context_isSpecialFile (absname); if (e->fspecial) { - cstring srcname = cstring_concatFree (cstring_fromChars (removeAnyExtension (cstring_toCharsSafe (name))), cstring_makeLiteral (".c")); + cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (absname), + C_EXTENSION); fileId fid = fileTable_lookup (ft, srcname); - cstring_free (srcname); if (fileId_isValid (fid)) @@ -309,22 +396,30 @@ fileTable_addFilePrim (fileTable ft, /*@only@*/ cstring name, fileId fileTable_addFile (fileTable ft, cstring name) { - /* while (*name == '.' && *(name + 1) == '/') name += 2; */ - return (fileTable_addFilePrim (ft, cstring_copy (name), - FALSE, FILE_NORMAL, fileId_invalid)); + return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid)); } fileId fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name) { - return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid)); + fileId res = fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid); + cstring_free (name); + return res; } fileId fileTable_addHeaderFile (fileTable ft, cstring name) { - return (fileTable_addFilePrim (ft, cstring_copy (name), FALSE, - FILE_HEADER, fileId_invalid)); + fileId res; + res = fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid); + return res; + +} + +void +fileTable_addStreamFile (fileTable ft, FILE *fstream, cstring name) +{ + fileTable_addOpen (ft, fstream, cstring_copy (name)); } bool @@ -352,13 +447,32 @@ fileTable_isSystemFile (fileTable ft, fileId fid) } bool -fileTable_isSpecialFile (fileTable ft, fileId fid) +fileTable_isXHFile (fileTable ft, fileId fid) { if (fileId_isInvalid (fid)) { return FALSE; } + if (!(fileTable_isDefined (ft) && fileTable_inRange (ft, fid))) + { + llcontbug (message ("Bad file table or id: %s %d", bool_unparse (fileTable_isDefined (ft)), fid)); + return FALSE; + } + else + { + return (ft->elements[fid]->ftype == FILE_XH); + } +} + +bool +fileTable_isSpecialFile (fileTable ft, fileId fid) +{ + if (fileId_isInvalid (fid)) + { + return FALSE; + } + llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid)); return (ft->elements[fid]->fspecial); } @@ -366,73 +480,98 @@ fileTable_isSpecialFile (fileTable ft, fileId fid) fileId fileTable_addLibraryFile (fileTable ft, cstring name) { - return (fileTable_addFilePrim (ft, cstring_copy (name), - FALSE, FILE_HEADER, fileId_invalid)); + return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid)); +} + +fileId +fileTable_addXHFile (fileTable ft, cstring name) +{ + return (fileTable_addFilePrim (ft, name, FALSE, FILE_XH, fileId_invalid)); } -# ifndef NOLCL fileId fileTable_addImportFile (fileTable ft, cstring name) { - return (fileTable_addFilePrim (ft, cstring_copy (name), - FALSE, FILE_HEADER, fileId_invalid)); + return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid)); } fileId fileTable_addLCLFile (fileTable ft, cstring name) { - return (fileTable_addFilePrim (ft, cstring_copy (name), - FALSE, FILE_HEADER, fileId_invalid)); + return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid)); } -# endif -# ifndef NOLCL static int tmpcounter = 0; -# endif fileId fileTable_addMacrosFile (fileTable ft) { - cstring newname = cstring_fromChars - (makeTempName (cstring_toCharsSafe (context_tmpdir ()), "lmx", ".llm")); + cstring newname = + makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("lmx"), + cstring_makeLiteralTemp (".llm")); + fileId res = fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid); + cstring_free (newname); + return res; +} - return (fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid)); +fileId +fileTable_addMetastateFile (fileTable ft, cstring name) +{ + return (fileTable_addFilePrim (ft, name, FALSE, FILE_METASTATE, fileId_invalid)); } fileId fileTable_addCTempFile (fileTable ft, fileId fid) { -# if FALSE - /* Can't control output file name for cl preprocessor */ - cstring newname = cstring_concatChars (removeAnyExtension (fileName (fid)), ".i"); -# else - cstring newname = cstring_fromChars - (makeTempName (cstring_toCharsSafe (context_tmpdir ()), "cl", ".c")); -# endif + cstring newname = + makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("cl"), + C_EXTENSION); + fileId res; + + DPRINTF (("tmp dir: %s", context_tmpdir ())); + DPRINTF (("new name: %s", newname)); llassert (fileTable_isDefined (ft)); if (!fileId_isValid (ft->elements[fid]->fder)) { - return (fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid)); + if (fileTable_isXHFile (ft, fid)) + { + res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH, fid); + } + else + { + res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid); + } } else { - return (fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, - ft->elements[fid]->fder)); + if (fileTable_isXHFile (ft, fid)) + { + res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH, + ft->elements[fid]->fder); + } + else + { + res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, + ft->elements[fid]->fder); + } } + + DPRINTF (("Added file: %s", fileTable_fileName (res))); + cstring_free (newname); + return res; } -# ifndef NOLCL fileId fileTable_addltemp (fileTable ft) { - char *newname = makeTempName (cstring_toCharsSafe (context_tmpdir ()), - "ls", ".lsl"); - char *onewname; + cstring newname = makeTempName (context_tmpdir (), + cstring_makeLiteralTemp ("ls"), + cstring_makeLiteralTemp (".lsl")); fileId ret; - if (cstring_hasNonAlphaNumBar (cstring_fromChars (newname))) + if (cstring_hasNonAlphaNumBar (newname)) { char *lastpath = (char *)NULL; @@ -441,21 +580,22 @@ fileTable_addltemp (fileTable ft) lldiagmsg (message ("Operating system generates tmp filename containing invalid charater: %s", - cstring_fromChars (newname))); + newname)); lldiagmsg (cstring_makeLiteral ("Try cleaning up the tmp directory. Attempting to continue.")); } + /*@access cstring@*/ + llassert (cstring_isDefined (newname)); lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */ llassert (lastpath != NULL); *lastpath = '\0'; - onewname = newname; - newname = cstring_toCharsSafe (message ("%s%hlsl%d.lsl", - cstring_fromChars (newname), - CONNECTCHAR, - tmpcounter)); - sfree (onewname); + newname = message ("%q%hlsl%d.lsl", + newname, + CONNECTCHAR, + tmpcounter); + /*@noaccess cstring@*/ tmpcounter++; } @@ -465,12 +605,10 @@ fileTable_addltemp (fileTable ft) ** since cstring is abstract. Should make it an only? */ - ret = fileTable_addFilePrim (ft, cstring_copy (cstring_fromChars (newname)), - TRUE, FILE_LSLTEMP, fileId_invalid); - sfree (newname); + ret = fileTable_addFilePrim (ft, newname, TRUE, FILE_LSLTEMP, fileId_invalid); + cstring_free (newname); return (ret); } -# endif bool fileTable_exists (fileTable ft, cstring s) @@ -478,9 +616,14 @@ fileTable_exists (fileTable ft, cstring s) int tindex = fileTable_getIndex (ft, s); if (tindex == NOT_FOUND) - return FALSE; + { + DPRINTF (("Not found: %s", s)); + return FALSE; + } else - return TRUE; + { + return TRUE; + } } fileId @@ -498,14 +641,39 @@ fileTable_lookup (fileTable ft, cstring s) } } +/* +** This is pretty awkward --- when we find the real path of +** a .xh file, we may need to change the recorded name. [Sigh] +*/ + +void +fileTable_setFilePath (fileTable ft, fileId fid, cstring path) +{ + llassert (fileId_isValid (fid)); + llassert (fileTable_isDefined (ft)); + /* Need to put new string in hash table */ + cstringTable_insert (ft->htable, cstring_copy (path), fid); + ft->elements[fid]->fname = cstring_copy (path); +} + fileId fileTable_lookupBase (fileTable ft, cstring base) { - int tindex = fileTable_getIndex (ft, base); + int tindex; + + if (context_getFlag (FLG_CASEINSENSITIVEFILENAMES)) + { + cstring dbase = cstring_downcase (base); + tindex = fileTable_getIndex (ft, dbase); + cstring_free (dbase); + } + else + { + tindex = fileTable_getIndex (ft, base); + } if (tindex == NOT_FOUND) { - return fileId_invalid; } else @@ -638,8 +806,8 @@ fileTable_cleanup (fileTable ft) if (msg) { - (void) fflush (g_msgstream); - fprintf (stderr, "< cleaning"); + (void) fflush (g_warningstream); + displayScanOpen (cstring_makeLiteral ("cleaning")); } for (i = 0; i < ft->nentries; i++) @@ -653,6 +821,7 @@ fileTable_cleanup (fileTable ft) /* ** Make sure it is really a derived file */ + if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE) { @@ -660,11 +829,12 @@ fileTable_cleanup (fileTable ft) } else if (fileId_isValid (fe->fder)) { - (void) osd_unlink (cstring_toCharsSafe (fe->fname)); + /*@i423 this should use close (fd) also... */ + (void) osd_unlink (fe->fname); } else if (fe->ftype == FILE_MACROS) { - (void) osd_unlink (cstring_toCharsSafe (fe->fname)); + (void) osd_unlink (fe->fname); } else { @@ -679,21 +849,13 @@ fileTable_cleanup (fileTable ft) if (msg && ((i % skip) == 0)) { - (void) fflush (g_msgstream); - - if (i == 0) { - fprintf (stderr, " "); - } else { - fprintf (stderr, "."); - } - - (void) fflush (stderr); + displayScanContinue (cstring_makeLiteral (i == 0 ? " " : ".")); } } - + if (msg) { - fprintf (stderr, " >\n"); + displayScanClose (); } } @@ -713,8 +875,9 @@ fileTable_free (/*@only@*/ fileTable f) i++; } - hashTable_free (f->htable); + cstringTable_free (f->htable); sfree (f->elements); + sfree (f->openelements); /*!! why didn't splint report this? */ sfree (f); } @@ -761,15 +924,15 @@ static void nextMsg (char *msg) /*@-charint@*/ } -static /*@only@*/ char *makeTempName (char *dir, char *pre, char *suf) +static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf) { static int pid = 0; static /*@owned@*/ char *msg = NULL; - static /*@only@*/ char *pidname = NULL; + static /*@only@*/ cstring pidname = NULL; size_t maxlen; - char *buf; + cstring smsg; - llassert (strlen (pre) <= 3); + llassert (cstring_length (pre) <= 3); /* ** We limit the temp name to 8 characters: @@ -790,31 +953,237 @@ static /*@only@*/ char *makeTempName (char *dir, char *pre, char *suf) /*@=matchanyintegral@*/ } - if (pidname == NULL) - { - pidname = cstring_toCharsSafe (message ("%d", pid % 100)); - } - else + if (cstring_isUndefined (pidname)) { - pidname = mstring_createEmpty (); + pidname = message ("%d", pid % 100); } - maxlen = (strlen (dir) + strlen (pre) + strlen (msg) - + strlen (pidname) + strlen (suf) + 2); + maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg) + + cstring_length (pidname) + cstring_length (suf) + 2); - buf = mstring_create (size_toInt (maxlen)); + DPRINTF (("Dir: %s / %s / %s / %s / %s", + dir, pre, pidname, msg, suf)); - sprintf (buf, "%s%s%s%s%s", dir, pre, pidname, msg, suf); + smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf); nextMsg (msg); - while (osd_fileExists (buf)) + DPRINTF (("Trying: %s", smsg)); + + while (osd_fileExists (smsg)) { - sprintf (buf, "%s%s%s%s%s", dir, pre, pidname, msg, suf); + cstring_free (smsg); + smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf); nextMsg (msg); } - return buf; + return smsg; +} + +static foentry +foentry_create (/*@exposed@*/ FILE *f, /*@only@*/ cstring fname) +{ + foentry t = (foentry) dmalloc (sizeof (*t)); + t->f = f; + t->fname = fname; + return t; +} + +static void +foentry_free (/*@only@*/ foentry foe) +{ + cstring_free (foe->fname); + sfree (foe); +} + +static void +fileTable_addOpen (fileTable ft, /*@observer@*/ FILE *f, /*@only@*/ cstring fname) +{ + llassert (fileTable_isDefined (ft)); + + if (ft->nopenspace <= 0) + { + fileTable_growOpen (ft); + } + + ft->nopenspace--; + ft->openelements[ft->nopen] = foentry_create (f, fname); + ft->nopen++; } + +FILE *fileTable_createFile (fileTable ft, cstring fname) +{ +# ifdef WIN32 + int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); /* not supported by VS.net: , S_IRUSR | S_IWUSR); */ +# else + int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); +# endif + + if (fdesc == -1) + { + osd_setTempError (); + llfatalerror (message ("Temporary file for " + "pre-processor output already exists. Trying to " + "open: %s.", + fname)); + + /*@notreached@*/ return NULL; + } + else + { + FILE *res = fdopen (fdesc, "w"); + if (res != NULL) + { + fileTable_addOpen (ft, res, cstring_copy (fname)); + DPRINTF (("Opening file: %s / %p", fname, res)); + } + else + { + DPRINTF (("Error opening: %s", fname)); + } + return res; + } +} + +FILE *fileTable_createMacrosFile (fileTable ft, cstring fname) +{ + int fdesc = open (cstring_toCharsSafe (fname), O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); + + if (fdesc == -1) + { + osd_setTempError (); + llfatalerror (message ("Temporary file for " + "pre-processor output already exists. Trying to " + "open: %s.", + fname)); + + /*@notreached@*/ return NULL; + } + else + { + FILE *res = fdopen (fdesc, "w+"); + + if (res != NULL) + { + fileTable_addOpen (ft, res, cstring_copy (fname)); + DPRINTF (("Opening file: %s / %p", fname, res)); + } + else + { + DPRINTF (("Error opening: %s", fname)); + } + + return res; + } +} + +FILE *fileTable_openReadFile (fileTable ft, cstring fname) +{ + FILE *res = fopen (cstring_toCharsSafe (fname), "r"); + + if (res != NULL) + { + fileTable_addOpen (ft, res, cstring_copy (fname)); + DPRINTF (("Opening read file: %s / %p", fname, res)); + } + else + { + DPRINTF (("Cannot open read file: %s", fname)); + } + + return res; +} + +/* +** Allows overwriting +*/ + +FILE *fileTable_openWriteFile (fileTable ft, cstring fname) +{ + FILE *res = fopen (cstring_toCharsSafe (fname), "w"); + + if (res != NULL) { + fileTable_addOpen (ft, res, cstring_copy (fname)); + DPRINTF (("Opening file: %s / %p", fname, res)); + } + + return res; +} + +FILE *fileTable_openWriteUpdateFile (fileTable ft, cstring fname) +{ + FILE *res = fopen (cstring_toCharsSafe (fname), "w+"); + + if (res != NULL) { + fileTable_addOpen (ft, res, cstring_copy (fname)); + DPRINTF (("Opening file: %s / %p", fname, res)); + } + + return res; +} + +bool fileTable_closeFile (fileTable ft, FILE *f) +{ + bool foundit = FALSE; + int i = 0; + + llassert (fileTable_isDefined (ft)); + + DPRINTF (("Closing file: %p", f)); + + for (i = 0; i < ft->nopen; i++) + { + if (ft->openelements[i]->f == f) + { + DPRINTF (("Closing file: %p = %s", f, ft->openelements[i]->fname)); + + if (i == ft->nopen - 1) + { + foentry_free (ft->openelements[i]); + ft->openelements[i] = NULL; + } + else + { + foentry_free (ft->openelements[i]); + ft->openelements[i] = ft->openelements[ft->nopen - 1]; + ft->openelements[ft->nopen - 1] = NULL; + } + + ft->nopen--; + ft->nopenspace++; + foundit = TRUE; + break; + } + } + + llassert (foundit); + return (fclose (f) == 0); +} + +void fileTable_closeAll (fileTable ft) +{ + int i = 0; + + llassert (fileTable_isDefined (ft)); + + for (i = 0; i < ft->nopen; i++) + { + /* + lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname)); + */ + + if (ft->openelements[i]->f != NULL) + { + (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */ + } + + ft->openelements[i]->f = NULL; + foentry_free (ft->openelements[i]); + ft->openelements[i] = NULL; + } + + ft->nopenspace += ft->nopen; + ft->nopen = 0; +}