/*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2000 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2002 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** 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
* - Added conditional stuff (#define and #include) for IBM's compiler.
*/
-# include "lclintMacros.nf"
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include "splintMacros.nf"
# include "llbasic.h"
# include "osd.h"
# include "llmain.h"
# include "portab.h"
+
# if defined(__IBMC__) && defined(OS2)
# include <process.h>
+# include <io.h>
# 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));
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)
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;
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);
+ 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
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;
}
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);
}
ft->elements = newent;
}
+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)
{
ft->nspace--;
- hashTable_insert (ft->htable, e->fname, ft->nentries);
+ DPRINTF (("Adding: %s", e->fname));
+ cstringTable_insert (ft->htable, e->fname, ft->nentries);
ft->elements[ft->nentries] = e;
ft->nentries++;
{
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);
+
+ DPRINTF (("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))
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
}
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);
}
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
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;
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++;
}
** 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
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
}
}
+/*
+** 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)
{
if (tindex == NOT_FOUND)
{
-
return fileId_invalid;
}
else
return cstring_makeLiteralTemp ("<no file table>");
}
- if (fid >= ft->nentries)
- {
- llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
- // fprintf(stderr, "\nbad\n");
- return cstring_makeLiteralTemp ("<invalid>");
- }
-
fder = ft->elements[fid]->fder;
if (fileId_isValid (fder))
if (msg)
{
- (void) fflush (g_msgstream);
+ (void) fflush (g_warningstream);
fprintf (stderr, "< cleaning");
}
/*
** Make sure it is really a derived file
*/
+
if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
{
}
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
{
if (msg && ((i % skip) == 0))
{
- (void) fflush (g_msgstream);
+ (void) fflush (g_warningstream);
if (i == 0) {
fprintf (stderr, " ");
i++;
}
- hashTable_free (f->htable);
+ cstringTable_free (f->htable);
sfree (f->elements);
sfree (f);
}
/*@-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;
- size_t maxlen;
- char *buf;
+ static /*@only@*/ cstring pidname = NULL;
+ int maxlen;
+ cstring smsg;
- llassert (strlen (pre) <= 3);
+ llassert (cstring_length (pre) <= 3);
/*
** We limit the temp name to 8 characters:
/*@=matchanyintegral@*/
}
- if (pidname == NULL)
+ if (cstring_isUndefined (pidname))
{
- pidname = cstring_toCharsSafe (message ("%d", pid % 100));
- }
- else
- {
- 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)
+{
+ int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | 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_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;
+}