]> andersk Git - splint.git/blob - src/fileTable.c
Fixed problem with loop guards in loop test effects. New test case
[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
321           /*
322           ** evans 2002-03-15: change suggested by Jim Zelenka
323           **                   support relative paths for system directories
324           */
325
326           if (!e->fsystem)
327             {
328               e->fsystem = context_isSystemDir (name);
329             }
330
331           e->fspecial = context_isSpecialFile (absname);
332
333           if (e->fspecial)
334             {
335               cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (absname), 
336                                                      C_EXTENSION);
337               fileId fid = fileTable_lookup (ft, srcname);
338               cstring_free (srcname);
339
340               if (fileId_isValid (fid))
341                 {
342                   fileId derid = ft->elements[fid]->fder;
343
344                   ft->elements[fid]->fspecial = TRUE;
345
346                   if (fileId_isValid (derid))
347                     {
348                       ft->elements[derid]->fspecial = TRUE;
349                     }
350                 }
351             }
352         }
353       else
354         {
355           ftentry de = ft->elements[der];
356
357           llassert (cstring_isUndefined (e->basename));
358           e->basename = cstring_copy (de->basename);
359           e->fsystem = de->fsystem;
360           e->fspecial = de->fspecial;
361         }
362
363       return (fileTable_internAddEntry (ft, e));
364     }
365 }
366
367 fileId
368 fileTable_addFile (fileTable ft, cstring name)
369 {
370   return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
371 }
372
373 fileId
374 fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name)
375 {
376   fileId res = fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid);
377   cstring_free (name);
378   return res;
379 }
380
381 fileId
382 fileTable_addHeaderFile (fileTable ft, cstring name)
383 {
384   fileId res;
385   res = fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid);
386   return res;
387
388 }
389
390 void
391 fileTable_addStreamFile (fileTable ft, FILE *fstream, cstring name)
392 {
393   fileTable_addOpen (ft, fstream, cstring_copy (name));
394 }
395
396 bool
397 fileTable_isHeader (fileTable ft, fileId fid)
398 {
399   if (fileId_isInvalid (fid))
400     {
401       return FALSE;
402     }
403
404   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
405   return (ft->elements[fid]->ftype == FILE_HEADER);
406 }
407
408 bool
409 fileTable_isSystemFile (fileTable ft, fileId fid)
410 {
411   if (fileId_isInvalid (fid))
412     {
413       return FALSE;
414     }
415
416   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
417   return (ft->elements[fid]->fsystem);
418 }
419
420 bool
421 fileTable_isXHFile (fileTable ft, fileId fid)
422 {
423   if (fileId_isInvalid (fid))
424     {
425       return FALSE;
426     }
427
428   if (!(fileTable_isDefined (ft) && fileTable_inRange (ft, fid)))
429     {
430       llcontbug (message ("Bad file table or id: %s %d", bool_unparse (fileTable_isDefined (ft)), fid));
431       return FALSE;
432     }
433   else
434     {
435       return (ft->elements[fid]->ftype == FILE_XH);
436     }
437 }
438
439 bool
440 fileTable_isSpecialFile (fileTable ft, fileId fid)
441 {
442   if (fileId_isInvalid (fid))
443     {
444       return FALSE;
445     }
446   
447   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
448   return (ft->elements[fid]->fspecial);
449 }
450
451 fileId
452 fileTable_addLibraryFile (fileTable ft, cstring name)
453 {
454   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
455 }
456
457 fileId
458 fileTable_addXHFile (fileTable ft, cstring name)
459 {
460   return (fileTable_addFilePrim (ft, name, FALSE, FILE_XH, fileId_invalid));
461 }
462
463 # ifndef NOLCL
464 fileId
465 fileTable_addImportFile (fileTable ft, cstring name)
466 {
467   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
468 }
469
470 fileId
471 fileTable_addLCLFile (fileTable ft, cstring name)
472 {
473   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
474 }
475 # endif
476
477 # ifndef NOLCL
478 static int tmpcounter = 0;
479 # endif
480
481 fileId
482 fileTable_addMacrosFile (fileTable ft)
483 {
484   cstring newname =
485     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("lmx"),
486                   cstring_makeLiteralTemp (".llm"));
487   fileId res = fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid);
488   cstring_free (newname);
489   return res;
490 }
491
492 fileId
493 fileTable_addMetastateFile (fileTable ft, cstring name)
494 {
495   return (fileTable_addFilePrim (ft, name, FALSE, FILE_METASTATE, fileId_invalid));
496 }
497
498 fileId
499 fileTable_addCTempFile (fileTable ft, fileId fid)
500 {
501   cstring newname =
502     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("cl"), 
503                   C_EXTENSION);
504   fileId res;
505
506   DPRINTF (("tmp dir: %s", context_tmpdir ()));
507   DPRINTF (("new name: %s", newname));
508
509   llassert (fileTable_isDefined (ft));
510
511   if (!fileId_isValid (ft->elements[fid]->fder))
512     {
513       if (fileTable_isXHFile (ft, fid))
514         {
515           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH, fid);
516         }
517       else
518         {
519           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid);
520         }
521     }
522   else 
523     {
524       if (fileTable_isXHFile (ft, fid))
525         {
526           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH,
527                                        ft->elements[fid]->fder);
528         }
529       else
530         {
531           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL,
532                                        ft->elements[fid]->fder);
533         }
534     }
535
536   DPRINTF (("Added file: %s", fileTable_fileName (res)));
537   cstring_free (newname);
538   return res;
539 }
540
541 # ifndef NOLCL
542 fileId
543 fileTable_addltemp (fileTable ft)
544 {
545   cstring newname = makeTempName (context_tmpdir (),
546                                   cstring_makeLiteralTemp ("ls"), 
547                                   cstring_makeLiteralTemp (".lsl"));
548   fileId ret;
549   
550   if (cstring_hasNonAlphaNumBar (newname))
551     {
552       char *lastpath = (char *)NULL;
553
554       if (tmpcounter == 0)
555         {
556           lldiagmsg
557             (message
558              ("Operating system generates tmp filename containing invalid charater: %s",
559               newname));
560           lldiagmsg (cstring_makeLiteral 
561                      ("Try cleaning up the tmp directory.  Attempting to continue."));
562         }
563       
564       /*@access cstring@*/
565       llassert (cstring_isDefined (newname));
566       lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */
567       llassert (lastpath != NULL);
568       *lastpath = '\0';
569
570       newname = message ("%q%hlsl%d.lsl", 
571                          newname,
572                          CONNECTCHAR,
573                          tmpcounter);
574       /*@noaccess cstring@*/
575       tmpcounter++;
576     }
577   
578   /*
579   ** this is kind of yucky...need to make the result of cstring_fromChars
580   ** refer to the same storage as its argument.  Of course, this loses,
581   ** since cstring is abstract.  Should make it an only?
582   */
583
584   ret = fileTable_addFilePrim (ft, newname, TRUE, FILE_LSLTEMP, fileId_invalid);
585   cstring_free (newname);
586   return (ret);
587 }
588 # endif
589
590 bool
591 fileTable_exists (fileTable ft, cstring s)
592 {
593   int tindex = fileTable_getIndex (ft, s);
594
595   if (tindex == NOT_FOUND)
596     {
597       DPRINTF (("Not found: %s", s));
598       return FALSE;
599     }
600   else
601     {
602       return TRUE;
603     }
604 }
605
606 fileId
607 fileTable_lookup (fileTable ft, cstring s)
608 {
609   int tindex = fileTable_getIndex (ft, s);
610
611   if (tindex == NOT_FOUND)
612     {
613       return fileId_invalid;
614     }
615   else
616     {
617       return tindex;
618     }
619 }
620
621 /*
622 ** This is pretty awkward --- when we find the real path of 
623 ** a .xh file, we may need to change the recorded name.  [Sigh]
624 */
625
626 void
627 fileTable_setFilePath (fileTable ft, fileId fid, cstring path)
628 {
629   llassert (fileId_isValid (fid));
630   llassert (fileTable_isDefined (ft));
631   /* Need to put new string in hash table */
632   cstringTable_insert (ft->htable, cstring_copy (path), fid);
633   ft->elements[fid]->fname = cstring_copy (path);
634 }
635
636 fileId
637 fileTable_lookupBase (fileTable ft, cstring base)
638 {
639   int tindex = fileTable_getIndex (ft, base);
640
641   if (tindex == NOT_FOUND)
642     {
643       return fileId_invalid;
644     }
645   else
646     {
647       fileId der;
648
649       llassert (fileTable_isDefined (ft));
650
651       der = ft->elements[tindex]->fder;
652       
653       if (!fileId_isValid (der))
654         {
655           der = tindex;
656         }
657
658       return der; 
659     }
660 }
661
662 cstring
663 fileTable_getName (fileTable ft, fileId fid)
664 {
665   if (!fileId_isValid (fid))
666     {
667       llcontbug 
668         (message ("fileTable_getName: called with invalid type id: %d", fid));
669       return cstring_makeLiteralTemp ("<invalid>");
670     }
671
672   llassert (fileTable_isDefined (ft));
673   return (ft->elements[fid]->fname);
674 }
675
676 cstring
677 fileTable_getRootName (fileTable ft, fileId fid)
678 {
679   fileId fder;
680
681   if (!fileId_isValid (fid))
682     {
683       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
684       return cstring_makeLiteralTemp ("<invalid>");
685     }
686
687   if (!fileTable_isDefined (ft))
688     {
689       return cstring_makeLiteralTemp ("<no file table>");
690     }
691
692   fder = ft->elements[fid]->fder;
693
694   if (fileId_isValid (fder))
695     {
696       return (ft->elements[fder]->fname);
697     }
698   else
699     {
700       return (ft->elements[fid]->fname);
701     }
702 }
703
704 cstring
705 fileTable_getNameBase (fileTable ft, fileId fid)
706 {
707   if (!fileId_isValid (fid))
708     {
709       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
710       return cstring_makeLiteralTemp ("<invalid>");
711     }
712   
713   if (!fileTable_isDefined (ft))
714     {
715       return cstring_makeLiteralTemp ("<no file table>");
716     }
717   
718   return (ft->elements[fid]->basename);
719 }
720
721 bool
722 fileTable_sameBase (fileTable ft, fileId f1, fileId f2)
723 {
724   fileId fd1, fd2;
725
726   if (!fileId_isValid (f1))
727     {
728       return FALSE;
729     }
730
731   if (!fileId_isValid (f2))
732     {
733       return FALSE;
734     }
735
736   llassert (fileTable_isDefined (ft));
737
738   if (f1 == f2) 
739     {
740       return TRUE;
741     }
742
743   fd1 = ft->elements[f1]->fder;
744
745   if (!fileId_isValid (fd1))
746     {
747       fd1 = f1;
748     }
749
750   fd2 = ft->elements[f2]->fder;
751
752
753   if (!fileId_isValid (fd2))
754     {
755       fd2 = f2;
756     }
757
758   return (fd1 == fd2);
759 }
760
761 void
762 fileTable_cleanup (fileTable ft)
763 {
764   int i;
765   bool msg;
766   int skip;
767   
768   llassert (fileTable_isDefined (ft));
769
770   msg = ((ft->nentries > 40) && context_getFlag (FLG_SHOWSCAN));
771   skip = ft->nentries / 10;
772
773   if (msg)
774     {
775       (void) fflush (g_warningstream);
776       fprintf (stderr, "< cleaning");
777     }
778
779   for (i = 0; i < ft->nentries; i++)
780     {
781       ftentry fe = ft->elements[i];
782
783       if (fe->ftemp)
784         {
785           /* let's be real careful now, hon! */
786           
787           /*
788           ** Make sure it is really a derived file
789           */
790
791           
792           if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
793             {
794               ; /* already removed */ 
795             }
796           else if (fileId_isValid (fe->fder)) 
797             {
798               /*@i423 this should use close (fd) also... */
799               (void) osd_unlink (fe->fname);
800             }
801           else if (fe->ftype == FILE_MACROS)
802             {
803               (void) osd_unlink (fe->fname);
804             }
805           else
806             {
807               llbug (message ("Temporary file is not derivative: %s "
808                               "(not deleted)", fe->fname));
809             }
810         }
811       else
812         {
813           ;
814         }
815
816       if (msg && ((i % skip) == 0))
817         {
818           (void) fflush (g_warningstream);
819
820           if (i == 0) {
821             fprintf (stderr, " ");
822           } else {
823             fprintf (stderr, ".");
824           }
825
826           (void) fflush (stderr);
827         }
828     }
829   
830   if (msg)
831     {
832       fprintf (stderr, " >\n");
833     }
834 }
835
836 void
837 fileTable_free (/*@only@*/ fileTable f)
838 {
839   int i = 0;
840   
841   if (f == (fileTable)NULL) 
842     {
843       return;
844     }
845
846   while ( i < f->nentries ) 
847     {
848       ftentry_free (f->elements[i]);
849       i++;
850     }
851   
852   cstringTable_free (f->htable);
853   sfree (f->elements);
854   sfree (f);
855 }
856
857 /*
858 ** unique temp filename are constructed from <dir><pre><pid><msg>.<suf>
859 ** requires: <dir> must end in '/'
860 */
861
862 static void nextMsg (char *msg)
863 {
864   /*@+charint@*/
865   if (msg[0] < 'Z') 
866     {
867       msg[0]++; 
868     }
869   else 
870     {
871       msg[0] = 'A';
872       if (msg[1] < 'Z')
873         { 
874           msg[1]++; 
875         }
876       else
877         {
878           msg[1] = 'A';
879           if (msg[2] < 'Z') 
880             {
881               msg[2]++;
882             }
883           else
884             {
885               msg[2] = 'A';
886               if (msg[3] < 'Z') 
887                 {
888                   msg[3]++; 
889                 }
890               else
891                 {
892                   llassertprint (FALSE, ("nextMsg: out of unique names!!!"));
893                 }
894             }
895         }
896     }
897   /*@-charint@*/
898 }
899
900 static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf)
901 {
902   static int pid = 0; 
903   static /*@owned@*/ char *msg = NULL; 
904   static /*@only@*/ cstring pidname = NULL;
905   int maxlen;
906   cstring smsg;
907
908   llassert (cstring_length (pre) <= 3);
909
910   /*
911   ** We limit the temp name to 8 characters:
912   **   pre: 3 or less
913   **   msg: 3
914   **   pid: 2  (% 100)
915   */
916
917   if (msg == NULL)
918     {
919       msg = mstring_copy ("AAA"); /* there are 26^3 temp names */
920     }
921
922   if (pid == 0) 
923     {
924       /*@+matchanyintegral@*/
925       pid = osd_getPid ();
926       /*@=matchanyintegral@*/
927     }
928
929   if (cstring_isUndefined (pidname)) 
930     {
931       pidname = message ("%d", pid % 100);
932     }
933   
934   maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg) 
935             + cstring_length (pidname) + cstring_length (suf) + 2);
936
937   DPRINTF (("Dir: %s / %s / %s / %s / %s",
938             dir, pre, pidname, msg, suf));
939
940   smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
941   nextMsg (msg);
942
943   DPRINTF (("Trying: %s", smsg));
944
945   while (osd_fileExists (smsg))
946     {
947       cstring_free (smsg);
948       smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
949       nextMsg (msg);
950     }
951   
952
953   return smsg;
954 }
955
956 static foentry
957 foentry_create (/*@exposed@*/ FILE *f, /*@only@*/ cstring fname)
958 {
959   foentry t = (foentry) dmalloc (sizeof (*t));
960   t->f = f;
961   t->fname = fname;
962   return t;
963 }
964
965 static void 
966 foentry_free (/*@only@*/ foentry foe)
967 {
968   cstring_free (foe->fname);
969   sfree (foe);
970 }
971
972 static void 
973 fileTable_addOpen (fileTable ft, /*@observer@*/ FILE *f, /*@only@*/ cstring fname)
974 {
975   llassert (fileTable_isDefined (ft));
976
977   if (ft->nopenspace <= 0) 
978     {
979       fileTable_growOpen (ft);
980     }
981
982   ft->nopenspace--;
983   ft->openelements[ft->nopen] = foentry_create (f, fname);
984   ft->nopen++;
985 }
986
987 FILE *fileTable_openFile (fileTable ft, cstring fname, char *mode)
988 {
989   FILE *res = fopen (cstring_toCharsSafe (fname), mode);
990
991   if (res != NULL) {
992     fileTable_addOpen (ft, res, cstring_copy (fname));
993     DPRINTF (("Opening file: %s / %p", fname, res));
994   }
995
996   return res;
997 }
998
999 bool fileTable_closeFile (fileTable ft, FILE *f)
1000 {
1001   bool foundit = FALSE;
1002   int i = 0;
1003
1004   llassert (fileTable_isDefined (ft));
1005
1006   DPRINTF (("Closing file: %p", f));
1007
1008   for (i = 0; i < ft->nopen; i++) 
1009     {
1010       if (ft->openelements[i]->f == f)
1011         {
1012           DPRINTF (("Closing file: %p = %s", f, ft->openelements[i]->fname));
1013
1014           if (i == ft->nopen - 1)
1015             {
1016               foentry_free (ft->openelements[i]);
1017               ft->openelements[i] = NULL;
1018             }
1019           else
1020             {
1021               foentry_free (ft->openelements[i]);
1022               ft->openelements[i] = ft->openelements[ft->nopen - 1];
1023               ft->openelements[ft->nopen - 1] = NULL;
1024             }
1025
1026           ft->nopen--;
1027           ft->nopenspace++;
1028           foundit = TRUE;
1029           break;
1030         }
1031     }
1032   
1033   llassert (foundit);
1034   return (fclose (f) == 0);
1035 }
1036
1037 void fileTable_closeAll (fileTable ft)
1038 {
1039   int i = 0;
1040
1041   llassert (fileTable_isDefined (ft));
1042
1043   for (i = 0; i < ft->nopen; i++) 
1044     {
1045       /* 
1046          lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname)); 
1047       */
1048       
1049       if (ft->openelements[i]->f != NULL)
1050         {
1051           (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */
1052         }
1053
1054       ft->openelements[i]->f = NULL;
1055       foentry_free (ft->openelements[i]);
1056       ft->openelements[i] = NULL;
1057     }
1058   
1059   ft->nopenspace += ft->nopen;
1060   ft->nopen = 0;
1061 }
1062
This page took 0.1129 seconds and 5 git commands to generate.