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