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