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