]> andersk Git - splint.git/blob - src/fileTable.c
Fixed unsignedcompare test. Removed diag for unclosed files.
[splint.git] / src / fileTable.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 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
59 static bool fileTable_inRange (fileTable ft, fileId fid) /*@*/ 
60 {
61   return (fileTable_isDefined (ft) && (fid >= 0) && (fid < ft->nentries));
62 }
63
64 static fileId fileTable_internAddEntry (fileTable p_ft, /*@only@*/ ftentry p_e) 
65    /*@modifies p_ft@*/ ;
66 static /*@only@*/ cstring makeTempName (cstring p_dir, cstring p_pre, cstring p_suf);
67
68 static /*@only@*/ cstring
69 fileType_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");
77     case FILE_XH:  return cstring_makeLiteral ("xh");
78     case FILE_MACROS:  return cstring_makeLiteral ("macros");
79     case FILE_METASTATE:  return cstring_makeLiteral ("metastate");
80     }
81
82   BADEXIT;
83 }
84
85 static int
86 fileTable_getIndex (fileTable ft, cstring s)
87 {
88   if (ft == NULL) return NOT_FOUND;
89   return (cstringTable_lookup (ft->htable, s));
90 }
91
92 /*@only@*/ cstring
93 fileTable_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
124 void 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
154 static /*@notnull@*/ ftentry
155 ftentry_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
178 static void
179 ftentry_free (/*@only@*/ ftentry t)
180 {
181   cstring_free (t->fname);
182   cstring_free (t->basename);
183   sfree (t);
184 }
185
186 /*@only@*/ /*@notnull@*/ fileTable
187 fileTable_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));
194   ft->htable = cstringTable_create (FTHASHSIZE);
195
196   ft->nopen = 0;
197   ft->nopenspace = FTBASESIZE;
198   ft->openelements = (foentry *) dmalloc (FTBASESIZE * sizeof (*ft->openelements));
199   
200   return (ft);
201 }
202
203 static void
204 fileTable_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
224 static void
225 fileTable_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
245 static fileId
246 fileTable_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
255   cstringTable_insert (ft->htable, e->fname, ft->nentries);
256   ft->elements[ft->nentries] = e;
257
258   ft->nentries++;
259   return (ft->nentries - 1);
260 }
261
262 void 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
273 static fileId
274 fileTable_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
296           e->basename = fileLib_removePathFree (fileLib_removeAnyExtension (name));
297           e->fsystem = context_isSystemDir (name);
298           e->fspecial = context_isSpecialFile (name);
299
300           if (e->fspecial)
301             {
302               cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (name), 
303                                                      C_EXTENSION);
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
335 fileId
336 fileTable_addFile (fileTable ft, cstring name)
337 {
338   /* while (*name == '.' && *(name + 1) == '/') name += 2; */
339
340   return (fileTable_addFilePrim (ft, cstring_copy (name), 
341                                  FALSE, FILE_NORMAL, fileId_invalid));
342 }
343
344 fileId
345 fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name)
346 {
347   return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
348 }
349
350 fileId
351 fileTable_addHeaderFile (fileTable ft, cstring name)
352 {
353   fileId res;
354
355   res = fileTable_addFilePrim (ft, cstring_copy (name), FALSE, 
356                                FILE_HEADER, fileId_invalid);
357   return res;
358
359 }
360
361 bool
362 fileTable_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
373 bool
374 fileTable_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
385 bool
386 fileTable_isXHFile (fileTable ft, fileId fid)
387 {
388   if (fileId_isInvalid (fid))
389     {
390       return FALSE;
391     }
392
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     }
402 }
403
404 bool
405 fileTable_isSpecialFile (fileTable ft, fileId fid)
406 {
407   if (fileId_isInvalid (fid))
408     {
409       return FALSE;
410     }
411   
412   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
413   return (ft->elements[fid]->fspecial);
414 }
415
416 fileId
417 fileTable_addLibraryFile (fileTable ft, cstring name)
418 {
419   return (fileTable_addFilePrim (ft, cstring_copy (name),
420                                  FALSE, FILE_HEADER, fileId_invalid));
421 }
422
423 fileId
424 fileTable_addXHFile (fileTable ft, cstring name)
425 {
426   return (fileTable_addFilePrim (ft, cstring_copy (name),
427                                  FALSE, FILE_XH, fileId_invalid));
428 }
429
430 # ifndef NOLCL
431 fileId
432 fileTable_addImportFile (fileTable ft, cstring name)
433 {
434   return (fileTable_addFilePrim (ft, cstring_copy (name), 
435                                  FALSE, FILE_HEADER, fileId_invalid));
436 }
437
438 fileId
439 fileTable_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
447 static int tmpcounter = 0;
448 # endif
449
450 fileId
451 fileTable_addMacrosFile (fileTable ft)
452 {
453   cstring newname =
454     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("lmx"),
455                   cstring_makeLiteralTemp (".llm"));
456
457   return (fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid));
458 }
459
460 fileId
461 fileTable_addMetastateFile (fileTable ft, cstring name)
462 {
463   return (fileTable_addFilePrim (ft, cstring_copy (name), 
464                                  FALSE, FILE_METASTATE, fileId_invalid));
465 }
466
467 fileId
468 fileTable_addCTempFile (fileTable ft, fileId fid)
469 {
470   cstring newname =
471     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("cl"), 
472                   C_EXTENSION);
473
474   llassert (fileTable_isDefined (ft));
475
476   if (!fileId_isValid (ft->elements[fid]->fder))
477     {
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         }
486     }
487   else 
488     {
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         }
499     }
500 }
501
502 # ifndef NOLCL
503 fileId
504 fileTable_addltemp (fileTable ft)
505 {
506   cstring newname = makeTempName (context_tmpdir (),
507                                   cstring_makeLiteralTemp ("ls"), 
508                                   cstring_makeLiteralTemp (".lsl"));
509   fileId ret;
510   
511   if (cstring_hasNonAlphaNumBar (newname))
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",
520               newname));
521           lldiagmsg (cstring_makeLiteral 
522                      ("Try cleaning up the tmp directory.  Attempting to continue."));
523         }
524       
525       /*@access cstring@*/
526       llassert (cstring_isDefined (newname));
527       lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */
528       llassert (lastpath != NULL);
529       *lastpath = '\0';
530
531       newname = message ("%q%hlsl%d.lsl", 
532                          newname,
533                          CONNECTCHAR,
534                          tmpcounter);
535       /*@noaccess cstring@*/
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
545   ret = fileTable_addFilePrim (ft, cstring_copy (newname),
546                                TRUE, FILE_LSLTEMP, fileId_invalid);
547   cstring_free (newname);
548   return (ret);
549 }
550 # endif
551
552 bool
553 fileTable_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
563 fileId
564 fileTable_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
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
583 void
584 fileTable_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
593 fileId
594 fileTable_lookupBase (fileTable ft, cstring base)
595 {
596   int tindex = fileTable_getIndex (ft, base);
597
598   if (tindex == NOT_FOUND)
599     {
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
619 cstring
620 fileTable_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
633 cstring
634 fileTable_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
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
661 cstring
662 fileTable_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
678 bool
679 fileTable_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
718 void
719 fileTable_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             {
754               /*@i423 this should use close (fd) also... */
755               (void) osd_unlink (fe->fname);
756             }
757           else if (fe->ftype == FILE_MACROS)
758             {
759               (void) osd_unlink (fe->fname);
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
792 void
793 fileTable_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   
808   cstringTable_free (f->htable);
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
818 static 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
856 static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf)
857 {
858   static int pid = 0; 
859   static /*@owned@*/ char *msg = NULL; 
860   static /*@only@*/ cstring pidname = NULL;
861   int maxlen;
862   cstring smsg;
863
864   llassert (cstring_length (pre) <= 3);
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
885   if (cstring_isUndefined (pidname)) 
886     {
887       pidname = message ("%d", pid % 100);
888     }
889   
890   maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg) 
891             + cstring_length (pidname) + cstring_length (suf) + 2);
892
893   smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
894   nextMsg (msg);
895
896   while (osd_fileExists (smsg))
897     {
898       cstring_free (smsg);
899       smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
900       nextMsg (msg);
901     }
902   
903
904   return smsg;
905 }
906
907 static foentry
908 foentry_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
916 static void 
917 foentry_free (/*@only@*/ foentry foe)
918 {
919   cstring_free (foe->fname);
920   sfree (foe);
921 }
922
923 static void 
924 fileTable_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
938 FILE *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
950 bool 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
988 void fileTable_closeAll (fileTable ft)
989 {
990   int i = 0;
991
992   for (i = 0; i < ft->nopen; i++) 
993     {
994       /* 
995          lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname)); 
996       */
997
998       (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */
999       lldiagmsg (message ("Unclosed file at exit: %s", cstring_toCharsSafe (ft->openelements[i]->fname)));
1000       ft->openelements[i]->f = NULL;
1001       foentry_free (ft->openelements[i]);
1002       ft->openelements[i] = NULL;
1003     }
1004   
1005   ft->nopenspace += ft->nopen;
1006   ft->nopen = 0;
1007 }
1008
This page took 0.151354 seconds and 5 git commands to generate.