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