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