]> andersk Git - splint.git/blame - src/fileTable.c
Moved doc/lclint.1 to doc/splint.1
[splint.git] / src / fileTable.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
77d37419 3** Copyright (C) 1994-2002 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** fileTable.c
26**
27** replaces filenamemap.c
28** based (loosely) on typeTable.c
29**
30** entries in the fileTable are:
31**
32** name - name of the file
33** type - kind of file (a temp file to be deleted?)
34** link - derived from this file
35**
36*/
37/*
38 * Herbert 04/1997:
39 * - Added conditional stuff (macros OS2 and MSDOS) to make names of temporary
40 * files under Windows or OS/2 not larger than 8+3 characters to avoid
41 * trouble with FAT file systems or Novell Netware volumes.
42 * - Added include of new header file portab.h containing OS dependent stuff.
43 * - Changed occurance of '/' as path delimiter to a macro.
44 * - Added conditional stuff (#define and #include) for IBM's compiler.
45 */
46
1b8ae690 47# include "splintMacros.nf"
616915dd 48# include "llbasic.h"
49# include "osd.h"
50# include "llmain.h"
51# include "portab.h"
52# if defined(__IBMC__) && defined(OS2)
53# include <process.h>
54# define getpid _getpid
55# endif
56
57/*@access fileId*/
58
59static bool fileTable_inRange (fileTable ft, fileId fid) /*@*/
60{
61 return (fileTable_isDefined (ft) && (fid >= 0) && (fid < ft->nentries));
62}
63
64static fileId fileTable_internAddEntry (fileTable p_ft, /*@only@*/ ftentry p_e)
65 /*@modifies p_ft@*/ ;
28bf4b0b 66static /*@only@*/ cstring makeTempName (cstring p_dir, cstring p_pre, cstring p_suf);
616915dd 67
68static /*@only@*/ cstring
69fileType_unparse (fileType ft)
70{
71 switch (ft)
72 {
73 case FILE_NORMAL: return cstring_makeLiteral ("normal");
74 case FILE_NODELETE: return cstring_makeLiteral ("normal");
75 case FILE_LSLTEMP: return cstring_makeLiteral ("ltemp");
76 case FILE_HEADER: return cstring_makeLiteral ("header");
28bf4b0b 77 case FILE_XH: return cstring_makeLiteral ("xh");
616915dd 78 case FILE_MACROS: return cstring_makeLiteral ("macros");
28bf4b0b 79 case FILE_METASTATE: return cstring_makeLiteral ("metastate");
616915dd 80 }
81
82 BADEXIT;
83}
84
85static int
86fileTable_getIndex (fileTable ft, cstring s)
87{
53a89507 88 int res;
89 cstring abspath;
616915dd 90 if (ft == NULL) return NOT_FOUND;
53a89507 91 abspath = osd_absolutePath (cstring_undefined, s);
f2b6724f 92 DPRINTF (("Absolute path: %s: %s", s, abspath));
53a89507 93 res = cstringTable_lookup (ft->htable, abspath);
94 cstring_free (abspath);
95 return res;
616915dd 96}
97
4dd72714 98static cstring ftentry_unparse (fileTable ft, ftentry fte)
99{
100 if (fileId_isValid (fte->fder))
101 {
102 return message ("%s %q %d (%s)",
103 fte->fname,
104 fileType_unparse (fte->ftype),
105 fte->fder,
106 ft->elements[fte->fder]->fname);
107 }
108 else
109 {
110 return message ("%s %q", fte->fname,
111 fileType_unparse (fte->ftype));
112 }
113}
114
616915dd 115/*@only@*/ cstring
116fileTable_unparse (fileTable ft)
117{
118 cstring s = cstring_undefined;
119 int i;
120
121 if (fileTable_isUndefined (ft))
122 {
123 return (cstring_makeLiteral ("<fileTable undefined>"));
124 }
125
126 for (i = 0; i < ft->nentries; i++)
127 {
4dd72714 128 s = message ("%s\n[%d] %q", s, i, ftentry_unparse (ft, ft->elements[i]));
129 }
616915dd 130
131 return s;
132}
133
134void fileTable_printTemps (fileTable ft)
135{
136 if (fileTable_isDefined (ft))
137 {
138 int i;
139
140 for (i = 0; i < ft->nentries; i++)
141 {
142 if (ft->elements[i]->ftemp)
143 {
144 if (fileId_isValid (ft->elements[i]->fder))
145 {
146 fprintf (stderr, " %s:1\n\t%s:1\n",
147 cstring_toCharsSafe (ft->elements[ft->elements[i]->fder]->fname),
148 cstring_toCharsSafe (ft->elements[i]->fname));
149 }
150 else
151 {
152 fprintf (stderr, "[no file]\n\t%s:1\n",
153 cstring_toCharsSafe (ft->elements[i]->fname));
154 }
155 }
156 }
157 }
158}
159
160/*
161** loads in fileTable from fileTable_dump
162*/
163
164static /*@notnull@*/ ftentry
165ftentry_create (/*@keep@*/ cstring tn, bool temp, fileType typ, fileId der)
166{
167 ftentry t = (ftentry) dmalloc (sizeof (*t));
168
169 if (cstring_isUndefined (tn))
170 {
171 llbug (cstring_makeLiteral ("Undefined filename!"));
172 }
173
174 t->fname = tn;
175
176 t->basename = cstring_undefined;
177 t->ftemp = temp;
178 t->ftype = typ;
179 t->fder = der;
180
181 /* Don't set these until the basename is needed. */
182 t->fsystem = FALSE;
183 t->fspecial = FALSE;
184
185 return t;
186}
187
188static void
189ftentry_free (/*@only@*/ ftentry t)
190{
191 cstring_free (t->fname);
192 cstring_free (t->basename);
193 sfree (t);
194}
195
196/*@only@*/ /*@notnull@*/ fileTable
197fileTable_create ()
198{
199 fileTable ft = (fileTable) dmalloc (sizeof (*ft));
200
201 ft->nentries = 0;
202 ft->nspace = FTBASESIZE;
203 ft->elements = (ftentry *) dmalloc (FTBASESIZE * sizeof (*ft->elements));
28bf4b0b 204 ft->htable = cstringTable_create (FTHASHSIZE);
dfd82dce 205
206 ft->nopen = 0;
207 ft->nopenspace = FTBASESIZE;
208 ft->openelements = (foentry *) dmalloc (FTBASESIZE * sizeof (*ft->openelements));
616915dd 209
210 return (ft);
211}
212
213static void
214fileTable_grow (fileTable ft)
215{
216 int i;
217 ftentry *newent;
218
219 llassert (fileTable_isDefined (ft));
220
221 ft->nspace = FTBASESIZE;
222
223 newent = (ftentry *) dmalloc ((ft->nentries + ft->nspace) * sizeof (*newent));
224
225 for (i = 0; i < ft->nentries; i++)
226 {
227 newent[i] = ft->elements[i];
228 }
229
230 sfree (ft->elements);
231 ft->elements = newent;
232}
233
dfd82dce 234static void
235fileTable_growOpen (fileTable ft)
236{
237 int i;
238 foentry *newent;
239
240 llassert (fileTable_isDefined (ft));
241
242 ft->nopenspace = FTBASESIZE;
243
244 newent = (foentry *) dmalloc ((ft->nopen + ft->nopenspace) * sizeof (*newent));
245
246 for (i = 0; i < ft->nopen; i++)
247 {
248 newent[i] = ft->openelements[i];
249 }
250
251 sfree (ft->openelements);
252 ft->openelements = newent;
253}
254
616915dd 255static fileId
256fileTable_internAddEntry (fileTable ft, /*@only@*/ ftentry e)
257{
258 llassert (fileTable_isDefined (ft));
259
260 if (ft->nspace <= 0)
261 fileTable_grow (ft);
262
263 ft->nspace--;
264
f2b6724f 265 DPRINTF (("Adding: %s", e->fname));
28bf4b0b 266 cstringTable_insert (ft->htable, e->fname, ft->nentries);
616915dd 267 ft->elements[ft->nentries] = e;
268
269 ft->nentries++;
270 return (ft->nentries - 1);
271}
272
273void fileTable_noDelete (fileTable ft, cstring name)
274{
275 fileId fid = fileTable_lookup (ft, name);
276
4dd72714 277 if (fileId_isValid (fid))
278 {
279 llassert (fileTable_isDefined (ft));
280 ft->elements[fid]->ftype = FILE_NODELETE;
281 }
282 else
283 {
284 DPRINTF (("Invalid no delete: %s", name));
285 }
616915dd 286}
287
288static fileId
53a89507 289fileTable_addFilePrim (fileTable ft, /*@temp@*/ cstring name,
616915dd 290 bool temp, fileType typ, fileId der)
291 /*@modifies ft@*/
292{
53a89507 293 cstring absname = osd_absolutePath (NULL, name);
294 int tindex = fileTable_getIndex (ft, absname);
4dd72714 295
296 DPRINTF (("Got abs path: %s", absname));
616915dd 297 llassert (ft != fileTable_undefined);
298
299 if (tindex != NOT_FOUND)
300 {
53a89507 301 llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", absname));
616915dd 302 return tindex;
303 }
304 else
305 {
53a89507 306 ftentry e = ftentry_create (absname, temp, typ, der);
616915dd 307
308 if (der == fileId_invalid)
309 {
310 llassert (cstring_isUndefined (e->basename));
311
53a89507 312 e->basename = fileLib_removePathFree (fileLib_removeAnyExtension (absname));
313 e->fsystem = context_isSystemDir (absname);
314 e->fspecial = context_isSpecialFile (absname);
616915dd 315
316 if (e->fspecial)
317 {
53a89507 318 cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (absname),
28bf4b0b 319 C_EXTENSION);
616915dd 320 fileId fid = fileTable_lookup (ft, srcname);
616915dd 321 cstring_free (srcname);
322
323 if (fileId_isValid (fid))
324 {
325 fileId derid = ft->elements[fid]->fder;
326
327 ft->elements[fid]->fspecial = TRUE;
328
329 if (fileId_isValid (derid))
330 {
331 ft->elements[derid]->fspecial = TRUE;
332 }
333 }
334 }
335 }
336 else
337 {
338 ftentry de = ft->elements[der];
339
340 llassert (cstring_isUndefined (e->basename));
341 e->basename = cstring_copy (de->basename);
342 e->fsystem = de->fsystem;
343 e->fspecial = de->fspecial;
344 }
345
346 return (fileTable_internAddEntry (ft, e));
347 }
348}
349
350fileId
351fileTable_addFile (fileTable ft, cstring name)
352{
53a89507 353 return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
616915dd 354}
355
356fileId
357fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name)
358{
53a89507 359 fileId res = fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid);
360 cstring_free (name);
361 return res;
616915dd 362}
363
364fileId
365fileTable_addHeaderFile (fileTable ft, cstring name)
366{
28bf4b0b 367 fileId res;
53a89507 368 res = fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid);
28bf4b0b 369 return res;
370
616915dd 371}
372
373bool
374fileTable_isHeader (fileTable ft, fileId fid)
375{
376 if (fileId_isInvalid (fid))
377 {
378 return FALSE;
379 }
380
381 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
382 return (ft->elements[fid]->ftype == FILE_HEADER);
383}
384
385bool
386fileTable_isSystemFile (fileTable ft, fileId fid)
387{
388 if (fileId_isInvalid (fid))
389 {
390 return FALSE;
391 }
392
393 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
394 return (ft->elements[fid]->fsystem);
395}
396
28bf4b0b 397bool
398fileTable_isXHFile (fileTable ft, fileId fid)
399{
400 if (fileId_isInvalid (fid))
401 {
402 return FALSE;
403 }
404
ccf0a4a8 405 if (!(fileTable_isDefined (ft) && fileTable_inRange (ft, fid)))
406 {
407 llcontbug (message ("Bad file table or id: %s %d", bool_unparse (fileTable_isDefined (ft)), fid));
408 return FALSE;
409 }
410 else
411 {
412 return (ft->elements[fid]->ftype == FILE_XH);
413 }
28bf4b0b 414}
415
616915dd 416bool
417fileTable_isSpecialFile (fileTable ft, fileId fid)
418{
419 if (fileId_isInvalid (fid))
420 {
421 return FALSE;
422 }
ccf0a4a8 423
616915dd 424 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
425 return (ft->elements[fid]->fspecial);
426}
427
428fileId
429fileTable_addLibraryFile (fileTable ft, cstring name)
430{
53a89507 431 return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
616915dd 432}
433
28bf4b0b 434fileId
435fileTable_addXHFile (fileTable ft, cstring name)
436{
53a89507 437 return (fileTable_addFilePrim (ft, name, FALSE, FILE_XH, fileId_invalid));
28bf4b0b 438}
439
616915dd 440# ifndef NOLCL
441fileId
442fileTable_addImportFile (fileTable ft, cstring name)
443{
53a89507 444 return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
616915dd 445}
446
447fileId
448fileTable_addLCLFile (fileTable ft, cstring name)
449{
53a89507 450 return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
616915dd 451}
452# endif
453
454# ifndef NOLCL
455static int tmpcounter = 0;
456# endif
457
458fileId
459fileTable_addMacrosFile (fileTable ft)
460{
28bf4b0b 461 cstring newname =
462 makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("lmx"),
463 cstring_makeLiteralTemp (".llm"));
53a89507 464 fileId res = fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid);
465 cstring_free (newname);
466 return res;
616915dd 467}
468
28bf4b0b 469fileId
470fileTable_addMetastateFile (fileTable ft, cstring name)
471{
53a89507 472 return (fileTable_addFilePrim (ft, name, FALSE, FILE_METASTATE, fileId_invalid));
28bf4b0b 473}
474
616915dd 475fileId
476fileTable_addCTempFile (fileTable ft, fileId fid)
477{
28bf4b0b 478 cstring newname =
479 makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("cl"),
480 C_EXTENSION);
53a89507 481 fileId res;
616915dd 482
4dd72714 483 DPRINTF (("tmp dir: %s", context_tmpdir ()));
484 DPRINTF (("new name: %s", newname));
485
616915dd 486 llassert (fileTable_isDefined (ft));
487
488 if (!fileId_isValid (ft->elements[fid]->fder))
489 {
28bf4b0b 490 if (fileTable_isXHFile (ft, fid))
491 {
53a89507 492 res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH, fid);
28bf4b0b 493 }
494 else
495 {
53a89507 496 res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid);
28bf4b0b 497 }
616915dd 498 }
499 else
500 {
28bf4b0b 501 if (fileTable_isXHFile (ft, fid))
502 {
53a89507 503 res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH,
504 ft->elements[fid]->fder);
28bf4b0b 505 }
506 else
507 {
53a89507 508 res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL,
509 ft->elements[fid]->fder);
28bf4b0b 510 }
616915dd 511 }
53a89507 512
4dd72714 513 DPRINTF (("Added file: %s", fileTable_fileName (res)));
53a89507 514 cstring_free (newname);
515 return res;
616915dd 516}
517
518# ifndef NOLCL
519fileId
520fileTable_addltemp (fileTable ft)
521{
28bf4b0b 522 cstring newname = makeTempName (context_tmpdir (),
523 cstring_makeLiteralTemp ("ls"),
524 cstring_makeLiteralTemp (".lsl"));
616915dd 525 fileId ret;
526
28bf4b0b 527 if (cstring_hasNonAlphaNumBar (newname))
616915dd 528 {
529 char *lastpath = (char *)NULL;
530
531 if (tmpcounter == 0)
532 {
533 lldiagmsg
534 (message
535 ("Operating system generates tmp filename containing invalid charater: %s",
28bf4b0b 536 newname));
616915dd 537 lldiagmsg (cstring_makeLiteral
538 ("Try cleaning up the tmp directory. Attempting to continue."));
539 }
540
28bf4b0b 541 /*@access cstring@*/
542 llassert (cstring_isDefined (newname));
616915dd 543 lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */
544 llassert (lastpath != NULL);
545 *lastpath = '\0';
546
28bf4b0b 547 newname = message ("%q%hlsl%d.lsl",
548 newname,
549 CONNECTCHAR,
550 tmpcounter);
551 /*@noaccess cstring@*/
616915dd 552 tmpcounter++;
553 }
554
555 /*
556 ** this is kind of yucky...need to make the result of cstring_fromChars
557 ** refer to the same storage as its argument. Of course, this loses,
558 ** since cstring is abstract. Should make it an only?
559 */
560
53a89507 561 ret = fileTable_addFilePrim (ft, newname, TRUE, FILE_LSLTEMP, fileId_invalid);
28bf4b0b 562 cstring_free (newname);
616915dd 563 return (ret);
564}
565# endif
566
567bool
568fileTable_exists (fileTable ft, cstring s)
569{
570 int tindex = fileTable_getIndex (ft, s);
571
572 if (tindex == NOT_FOUND)
f2b6724f 573 {
574 DPRINTF (("Not found: %s", s));
575 return FALSE;
576 }
616915dd 577 else
f2b6724f 578 {
579 return TRUE;
580 }
616915dd 581}
582
583fileId
584fileTable_lookup (fileTable ft, cstring s)
585{
586 int tindex = fileTable_getIndex (ft, s);
587
588 if (tindex == NOT_FOUND)
589 {
590 return fileId_invalid;
591 }
592 else
593 {
594 return tindex;
595 }
596}
597
28bf4b0b 598/*
599** This is pretty awkward --- when we find the real path of
600** a .xh file, we may need to change the recorded name. [Sigh]
601*/
602
603void
604fileTable_setFilePath (fileTable ft, fileId fid, cstring path)
605{
606 llassert (fileId_isValid (fid));
607 llassert (fileTable_isDefined (ft));
608 /* Need to put new string in hash table */
609 cstringTable_insert (ft->htable, cstring_copy (path), fid);
610 ft->elements[fid]->fname = cstring_copy (path);
611}
612
616915dd 613fileId
614fileTable_lookupBase (fileTable ft, cstring base)
615{
616 int tindex = fileTable_getIndex (ft, base);
617
618 if (tindex == NOT_FOUND)
619 {
616915dd 620 return fileId_invalid;
621 }
622 else
623 {
624 fileId der;
625
626 llassert (fileTable_isDefined (ft));
627
628 der = ft->elements[tindex]->fder;
629
630 if (!fileId_isValid (der))
631 {
632 der = tindex;
633 }
634
635 return der;
636 }
637}
638
639cstring
640fileTable_getName (fileTable ft, fileId fid)
641{
642 if (!fileId_isValid (fid))
643 {
644 llcontbug
645 (message ("fileTable_getName: called with invalid type id: %d", fid));
646 return cstring_makeLiteralTemp ("<invalid>");
647 }
648
649 llassert (fileTable_isDefined (ft));
650 return (ft->elements[fid]->fname);
651}
652
653cstring
654fileTable_getRootName (fileTable ft, fileId fid)
655{
656 fileId fder;
657
658 if (!fileId_isValid (fid))
659 {
660 llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
661 return cstring_makeLiteralTemp ("<invalid>");
662 }
663
664 if (!fileTable_isDefined (ft))
665 {
666 return cstring_makeLiteralTemp ("<no file table>");
667 }
668
616915dd 669 fder = ft->elements[fid]->fder;
670
671 if (fileId_isValid (fder))
672 {
673 return (ft->elements[fder]->fname);
674 }
675 else
676 {
677 return (ft->elements[fid]->fname);
678 }
679}
680
681cstring
682fileTable_getNameBase (fileTable ft, fileId fid)
683{
684 if (!fileId_isValid (fid))
685 {
686 llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
687 return cstring_makeLiteralTemp ("<invalid>");
688 }
689
690 if (!fileTable_isDefined (ft))
691 {
692 return cstring_makeLiteralTemp ("<no file table>");
693 }
694
695 return (ft->elements[fid]->basename);
696}
697
698bool
699fileTable_sameBase (fileTable ft, fileId f1, fileId f2)
700{
701 fileId fd1, fd2;
702
703 if (!fileId_isValid (f1))
704 {
705 return FALSE;
706 }
707
708 if (!fileId_isValid (f2))
709 {
710 return FALSE;
711 }
712
713 llassert (fileTable_isDefined (ft));
714
715 if (f1 == f2)
716 {
717 return TRUE;
718 }
719
720 fd1 = ft->elements[f1]->fder;
721
722 if (!fileId_isValid (fd1))
723 {
724 fd1 = f1;
725 }
726
727 fd2 = ft->elements[f2]->fder;
728
729
730 if (!fileId_isValid (fd2))
731 {
732 fd2 = f2;
733 }
734
735 return (fd1 == fd2);
736}
737
738void
739fileTable_cleanup (fileTable ft)
740{
741 int i;
742 bool msg;
743 int skip;
744
745 llassert (fileTable_isDefined (ft));
746
747 msg = ((ft->nentries > 40) && context_getFlag (FLG_SHOWSCAN));
748 skip = ft->nentries / 10;
749
750 if (msg)
751 {
752 (void) fflush (g_msgstream);
753 fprintf (stderr, "< cleaning");
754 }
755
756 for (i = 0; i < ft->nentries; i++)
757 {
758 ftentry fe = ft->elements[i];
759
760 if (fe->ftemp)
761 {
762 /* let's be real careful now, hon! */
763
764 /*
765 ** Make sure it is really a derived file
766 */
4dd72714 767
616915dd 768
769 if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
770 {
771 ; /* already removed */
772 }
773 else if (fileId_isValid (fe->fder))
774 {
28bf4b0b 775 /*@i423 this should use close (fd) also... */
776 (void) osd_unlink (fe->fname);
616915dd 777 }
778 else if (fe->ftype == FILE_MACROS)
779 {
28bf4b0b 780 (void) osd_unlink (fe->fname);
616915dd 781 }
782 else
783 {
784 llbug (message ("Temporary file is not derivative: %s "
785 "(not deleted)", fe->fname));
786 }
787 }
788 else
789 {
790 ;
791 }
792
793 if (msg && ((i % skip) == 0))
794 {
795 (void) fflush (g_msgstream);
796
797 if (i == 0) {
798 fprintf (stderr, " ");
799 } else {
800 fprintf (stderr, ".");
801 }
802
803 (void) fflush (stderr);
804 }
805 }
806
807 if (msg)
808 {
809 fprintf (stderr, " >\n");
810 }
811}
812
813void
814fileTable_free (/*@only@*/ fileTable f)
815{
816 int i = 0;
817
818 if (f == (fileTable)NULL)
819 {
820 return;
821 }
822
823 while ( i < f->nentries )
824 {
825 ftentry_free (f->elements[i]);
826 i++;
827 }
828
28bf4b0b 829 cstringTable_free (f->htable);
616915dd 830 sfree (f->elements);
831 sfree (f);
832}
833
834/*
835** unique temp filename are constructed from <dir><pre><pid><msg>.<suf>
836** requires: <dir> must end in '/'
837*/
838
839static void nextMsg (char *msg)
840{
841 /*@+charint@*/
842 if (msg[0] < 'Z')
843 {
844 msg[0]++;
845 }
846 else
847 {
848 msg[0] = 'A';
849 if (msg[1] < 'Z')
850 {
851 msg[1]++;
852 }
853 else
854 {
855 msg[1] = 'A';
856 if (msg[2] < 'Z')
857 {
858 msg[2]++;
859 }
860 else
861 {
862 msg[2] = 'A';
863 if (msg[3] < 'Z')
864 {
865 msg[3]++;
866 }
867 else
868 {
869 llassertprint (FALSE, ("nextMsg: out of unique names!!!"));
870 }
871 }
872 }
873 }
874 /*@-charint@*/
875}
876
28bf4b0b 877static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf)
616915dd 878{
879 static int pid = 0;
880 static /*@owned@*/ char *msg = NULL;
28bf4b0b 881 static /*@only@*/ cstring pidname = NULL;
882 int maxlen;
883 cstring smsg;
616915dd 884
28bf4b0b 885 llassert (cstring_length (pre) <= 3);
616915dd 886
887 /*
888 ** We limit the temp name to 8 characters:
889 ** pre: 3 or less
890 ** msg: 3
891 ** pid: 2 (% 100)
892 */
893
894 if (msg == NULL)
895 {
896 msg = mstring_copy ("AAA"); /* there are 26^3 temp names */
897 }
898
899 if (pid == 0)
900 {
901 /*@+matchanyintegral@*/
902 pid = osd_getPid ();
903 /*@=matchanyintegral@*/
904 }
905
28bf4b0b 906 if (cstring_isUndefined (pidname))
616915dd 907 {
28bf4b0b 908 pidname = message ("%d", pid % 100);
616915dd 909 }
910
28bf4b0b 911 maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg)
912 + cstring_length (pidname) + cstring_length (suf) + 2);
616915dd 913
4dd72714 914 DPRINTF (("Dir: %s / %s / %s / %s / %s",
915 dir, pre, pidname, msg, suf));
916
28bf4b0b 917 smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
616915dd 918 nextMsg (msg);
919
4dd72714 920 DPRINTF (("Trying: %s", smsg));
921
28bf4b0b 922 while (osd_fileExists (smsg))
616915dd 923 {
28bf4b0b 924 cstring_free (smsg);
925 smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
616915dd 926 nextMsg (msg);
927 }
616915dd 928
929
28bf4b0b 930 return smsg;
931}
dfd82dce 932
933static foentry
934foentry_create (/*@exposed@*/ FILE *f, /*@only@*/ cstring fname)
935{
936 foentry t = (foentry) dmalloc (sizeof (*t));
937 t->f = f;
938 t->fname = fname;
939 return t;
940}
941
942static void
943foentry_free (/*@only@*/ foentry foe)
944{
945 cstring_free (foe->fname);
946 sfree (foe);
947}
948
949static void
950fileTable_addOpen (fileTable ft, /*@observer@*/ FILE *f, /*@only@*/ cstring fname)
951{
952 llassert (fileTable_isDefined (ft));
953
954 if (ft->nopenspace <= 0)
955 {
956 fileTable_growOpen (ft);
957 }
958
959 ft->nopenspace--;
960 ft->openelements[ft->nopen] = foentry_create (f, fname);
961 ft->nopen++;
962}
963
964FILE *fileTable_openFile (fileTable ft, cstring fname, char *mode)
965{
966 FILE *res = fopen (cstring_toCharsSafe (fname), mode);
967
968 if (res != NULL) {
969 fileTable_addOpen (ft, res, cstring_copy (fname));
970 DPRINTF (("Opening file: %s / %p", fname, res));
971 }
972
973 return res;
974}
975
976bool fileTable_closeFile (fileTable ft, FILE *f)
977{
978 bool foundit = FALSE;
979 int i = 0;
980
981 llassert (fileTable_isDefined (ft));
982
983 DPRINTF (("Closing file: %p", f));
984
985 for (i = 0; i < ft->nopen; i++)
986 {
987 if (ft->openelements[i]->f == f)
988 {
989 DPRINTF (("Closing file: %p = %s", f, ft->openelements[i]->fname));
990
991 if (i == ft->nopen - 1)
992 {
993 foentry_free (ft->openelements[i]);
994 ft->openelements[i] = NULL;
995 }
996 else
997 {
998 foentry_free (ft->openelements[i]);
999 ft->openelements[i] = ft->openelements[ft->nopen - 1];
1000 ft->openelements[ft->nopen - 1] = NULL;
1001 }
1002
1003 ft->nopen--;
1004 ft->nopenspace++;
1005 foundit = TRUE;
1006 break;
1007 }
1008 }
1009
1010 llassert (foundit);
1011 return (fclose (f) == 0);
1012}
1013
1014void fileTable_closeAll (fileTable ft)
1015{
1016 int i = 0;
1017
1018 for (i = 0; i < ft->nopen; i++)
1019 {
107b60d6 1020 /*
1021 lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname));
1022 */
1023
1024 (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */
dfd82dce 1025 ft->openelements[i]->f = NULL;
1026 foentry_free (ft->openelements[i]);
1027 ft->openelements[i] = NULL;
1028 }
1029
1030 ft->nopenspace += ft->nopen;
1031 ft->nopen = 0;
1032}
1033
This page took 0.211665 seconds and 5 git commands to generate.