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