]> andersk Git - splint.git/blob - src/fileTable.c
03a6be1e7a96d842bb8fe0bcb6c606be6af836df
[splint.git] / src / fileTable.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** fileTable.c
26 **
27 ** replaces filenamemap.c
28 ** based (loosely) on typeTable.c
29 **
30 ** entries in the fileTable are:
31 **
32 **        name - name of the file
33 **        type - kind of file (a temp file to be deleted?)
34 **        link - derived from this file
35 **
36 */
37 /*
38  * Herbert 04/1997:
39  * - Added conditional stuff (macros OS2 and MSDOS) to make names of temporary 
40  *   files under Windows or OS/2 not larger than 8+3 characters to avoid 
41  *   trouble with FAT file systems or Novell Netware volumes.
42  * - Added include of new header file portab.h containing OS dependent stuff.
43  * - Changed occurance of '/' as path delimiter to a macro.
44  * - Added conditional stuff (#define and #include) for IBM's compiler.
45  */
46
47 # include <sys/types.h>
48 # include <sys/stat.h>
49 # include <fcntl.h>
50 # include "splintMacros.nf"
51 # include "llbasic.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   
196   t->basename = cstring_undefined;
197   t->ftemp = temp;
198   t->ftype = typ;
199   t->fder  = der;
200
201   /* Don't set these until the basename is needed. */
202   t->fsystem = FALSE;
203   t->fspecial = FALSE;
204
205   return t;
206 }
207
208 static void
209 ftentry_free (/*@only@*/ ftentry t)
210 {
211   cstring_free (t->fname);
212   cstring_free (t->basename);
213   sfree (t);
214 }
215
216 /*@only@*/ /*@notnull@*/ fileTable
217 fileTable_create ()
218 {
219   fileTable ft = (fileTable) dmalloc (sizeof (*ft));
220   
221   ft->nentries = 0;
222   ft->nspace = FTBASESIZE;
223   ft->elements = (ftentry *) dmalloc (FTBASESIZE * sizeof (*ft->elements));
224   ft->htable = cstringTable_create (FTHASHSIZE);
225
226   ft->nopen = 0;
227   ft->nopenspace = FTBASESIZE;
228   ft->openelements = (foentry *) dmalloc (FTBASESIZE * sizeof (*ft->openelements));
229   
230   return (ft);
231 }
232
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
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       cstring_free (e->fname);
292     }
293   else
294     {
295       cstringTable_insert (ft->htable, e->fname, ft->nentries); 
296     }
297
298   ft->elements[ft->nentries] = e;
299
300   ft->nentries++;
301   return (ft->nentries - 1);
302 }
303
304 void fileTable_noDelete (fileTable ft, cstring name)
305 {
306   fileId fid = fileTable_lookup (ft, name);
307
308   if (fileId_isValid (fid)) 
309     {
310       llassert (fileTable_isDefined (ft));
311       ft->elements[fid]->ftype = FILE_NODELETE;
312     }
313   else
314     {
315       DPRINTF (("Invalid no delete: %s", name));
316     }
317 }
318
319 static fileId
320 fileTable_addFilePrim (fileTable ft, /*@temp@*/ cstring name, 
321                        bool temp, fileType typ, fileId der)
322    /*@modifies ft@*/
323 {
324   cstring absname = osd_absolutePath (NULL, name);
325   int tindex = fileTable_getIndex (ft, absname);
326   
327   /*@i534 fprintf (stderr, "Got abs path: %s", absname); */
328   llassert (ft != fileTable_undefined);
329
330   if (tindex != NOT_FOUND)
331     {
332       llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", absname));
333       return tindex;
334     }
335   else
336     {
337       ftentry e = ftentry_create (absname, temp, typ, der);
338
339       if (der == fileId_invalid)
340         {
341           llassert (cstring_isUndefined (e->basename));
342
343           e->basename = fileLib_removePathFree (fileLib_removeAnyExtension (absname));
344           e->fsystem = context_isSystemDir (absname);
345
346           /*
347           ** evans 2002-03-15: change suggested by Jim Zelenka
348           **                   support relative paths for system directories
349           */
350
351           if (!e->fsystem)
352             {
353               e->fsystem = context_isSystemDir (name);
354             }
355
356           e->fspecial = context_isSpecialFile (absname);
357
358           if (e->fspecial)
359             {
360               cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (absname), 
361                                                      C_EXTENSION);
362               fileId fid = fileTable_lookup (ft, srcname);
363               cstring_free (srcname);
364
365               if (fileId_isValid (fid))
366                 {
367                   fileId derid = ft->elements[fid]->fder;
368
369                   ft->elements[fid]->fspecial = TRUE;
370
371                   if (fileId_isValid (derid))
372                     {
373                       ft->elements[derid]->fspecial = TRUE;
374                     }
375                 }
376             }
377         }
378       else
379         {
380           ftentry de = ft->elements[der];
381
382           llassert (cstring_isUndefined (e->basename));
383           e->basename = cstring_copy (de->basename);
384           e->fsystem = de->fsystem;
385           e->fspecial = de->fspecial;
386         }
387
388       return (fileTable_internAddEntry (ft, e));
389     }
390 }
391
392 fileId
393 fileTable_addFile (fileTable ft, cstring name)
394 {
395   return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
396 }
397
398 fileId
399 fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name)
400 {
401   fileId res = fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid);
402   cstring_free (name);
403   return res;
404 }
405
406 fileId
407 fileTable_addHeaderFile (fileTable ft, cstring name)
408 {
409   fileId res;
410   res = fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid);
411   return res;
412
413 }
414
415 void
416 fileTable_addStreamFile (fileTable ft, FILE *fstream, cstring name)
417 {
418   fileTable_addOpen (ft, fstream, cstring_copy (name));
419 }
420
421 bool
422 fileTable_isHeader (fileTable ft, fileId fid)
423 {
424   if (fileId_isInvalid (fid))
425     {
426       return FALSE;
427     }
428
429   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
430   return (ft->elements[fid]->ftype == FILE_HEADER);
431 }
432
433 bool
434 fileTable_isSystemFile (fileTable ft, fileId fid)
435 {
436   if (fileId_isInvalid (fid))
437     {
438       return FALSE;
439     }
440
441   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
442   return (ft->elements[fid]->fsystem);
443 }
444
445 bool
446 fileTable_isXHFile (fileTable ft, fileId fid)
447 {
448   if (fileId_isInvalid (fid))
449     {
450       return FALSE;
451     }
452
453   if (!(fileTable_isDefined (ft) && fileTable_inRange (ft, fid)))
454     {
455       llcontbug (message ("Bad file table or id: %s %d", bool_unparse (fileTable_isDefined (ft)), fid));
456       return FALSE;
457     }
458   else
459     {
460       return (ft->elements[fid]->ftype == FILE_XH);
461     }
462 }
463
464 bool
465 fileTable_isSpecialFile (fileTable ft, fileId fid)
466 {
467   if (fileId_isInvalid (fid))
468     {
469       return FALSE;
470     }
471   
472   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
473   return (ft->elements[fid]->fspecial);
474 }
475
476 fileId
477 fileTable_addLibraryFile (fileTable ft, cstring name)
478 {
479   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
480 }
481
482 fileId
483 fileTable_addXHFile (fileTable ft, cstring name)
484 {
485   return (fileTable_addFilePrim (ft, name, FALSE, FILE_XH, fileId_invalid));
486 }
487
488 # ifndef NOLCL
489 fileId
490 fileTable_addImportFile (fileTable ft, cstring name)
491 {
492   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
493 }
494
495 fileId
496 fileTable_addLCLFile (fileTable ft, cstring name)
497 {
498   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
499 }
500 # endif
501
502 # ifndef NOLCL
503 static int tmpcounter = 0;
504 # endif
505
506 fileId
507 fileTable_addMacrosFile (fileTable ft)
508 {
509   cstring newname =
510     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("lmx"),
511                   cstring_makeLiteralTemp (".llm"));
512   fileId res = fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid);
513   cstring_free (newname);
514   return res;
515 }
516
517 fileId
518 fileTable_addMetastateFile (fileTable ft, cstring name)
519 {
520   return (fileTable_addFilePrim (ft, name, FALSE, FILE_METASTATE, fileId_invalid));
521 }
522
523 fileId
524 fileTable_addCTempFile (fileTable ft, fileId fid)
525 {
526   cstring newname =
527     makeTempName (context_tmpdir (), cstring_makeLiteralTemp ("cl"), 
528                   C_EXTENSION);
529   fileId res;
530
531   DPRINTF (("tmp dir: %s", context_tmpdir ()));
532   DPRINTF (("new name: %s", newname));
533
534   llassert (fileTable_isDefined (ft));
535
536   if (!fileId_isValid (ft->elements[fid]->fder))
537     {
538       if (fileTable_isXHFile (ft, fid))
539         {
540           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH, fid);
541         }
542       else
543         {
544           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid);
545         }
546     }
547   else 
548     {
549       if (fileTable_isXHFile (ft, fid))
550         {
551           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_XH,
552                                        ft->elements[fid]->fder);
553         }
554       else
555         {
556           res = fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL,
557                                        ft->elements[fid]->fder);
558         }
559     }
560
561   DPRINTF (("Added file: %s", fileTable_fileName (res)));
562   cstring_free (newname);
563   return res;
564 }
565
566 # ifndef NOLCL
567 fileId
568 fileTable_addltemp (fileTable ft)
569 {
570   cstring newname = makeTempName (context_tmpdir (),
571                                   cstring_makeLiteralTemp ("ls"), 
572                                   cstring_makeLiteralTemp (".lsl"));
573   fileId ret;
574   
575   if (cstring_hasNonAlphaNumBar (newname))
576     {
577       char *lastpath = (char *)NULL;
578
579       if (tmpcounter == 0)
580         {
581           lldiagmsg
582             (message
583              ("Operating system generates tmp filename containing invalid charater: %s",
584               newname));
585           lldiagmsg (cstring_makeLiteral 
586                      ("Try cleaning up the tmp directory.  Attempting to continue."));
587         }
588       
589       /*@access cstring@*/
590       llassert (cstring_isDefined (newname));
591       lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */
592       llassert (lastpath != NULL);
593       *lastpath = '\0';
594
595       newname = message ("%q%hlsl%d.lsl", 
596                          newname,
597                          CONNECTCHAR,
598                          tmpcounter);
599       /*@noaccess cstring@*/
600       tmpcounter++;
601     }
602   
603   /*
604   ** this is kind of yucky...need to make the result of cstring_fromChars
605   ** refer to the same storage as its argument.  Of course, this loses,
606   ** since cstring is abstract.  Should make it an only?
607   */
608
609   ret = fileTable_addFilePrim (ft, newname, TRUE, FILE_LSLTEMP, fileId_invalid);
610   cstring_free (newname);
611   return (ret);
612 }
613 # endif
614
615 bool
616 fileTable_exists (fileTable ft, cstring s)
617 {
618   int tindex = fileTable_getIndex (ft, s);
619
620   if (tindex == NOT_FOUND)
621     {
622       DPRINTF (("Not found: %s", s));
623       return FALSE;
624     }
625   else
626     {
627       return TRUE;
628     }
629 }
630
631 fileId
632 fileTable_lookup (fileTable ft, cstring s)
633 {
634   int tindex = fileTable_getIndex (ft, s);
635
636   if (tindex == NOT_FOUND)
637     {
638       return fileId_invalid;
639     }
640   else
641     {
642       return tindex;
643     }
644 }
645
646 /*
647 ** This is pretty awkward --- when we find the real path of 
648 ** a .xh file, we may need to change the recorded name.  [Sigh]
649 */
650
651 void
652 fileTable_setFilePath (fileTable ft, fileId fid, cstring path)
653 {
654   llassert (fileId_isValid (fid));
655   llassert (fileTable_isDefined (ft));
656   /* Need to put new string in hash table */
657   cstringTable_insert (ft->htable, cstring_copy (path), fid);
658   ft->elements[fid]->fname = cstring_copy (path);
659 }
660
661 fileId
662 fileTable_lookupBase (fileTable ft, cstring base)
663 {
664   int tindex;
665
666   if (context_getFlag (FLG_CASEINSENSITIVEFILENAMES))
667     {
668       cstring dbase = cstring_downcase (base);
669       tindex = fileTable_getIndex (ft, dbase);
670       cstring_free (dbase);
671     }
672   else
673     {
674       tindex = fileTable_getIndex (ft, base);
675     }
676
677   if (tindex == NOT_FOUND)
678     {
679       return fileId_invalid;
680     }
681   else
682     {
683       fileId der;
684
685       llassert (fileTable_isDefined (ft));
686
687       der = ft->elements[tindex]->fder;
688       
689       if (!fileId_isValid (der))
690         {
691           der = tindex;
692         }
693
694       return der; 
695     }
696 }
697
698 cstring
699 fileTable_getName (fileTable ft, fileId fid)
700 {
701   if (!fileId_isValid (fid))
702     {
703       llcontbug 
704         (message ("fileTable_getName: called with invalid type id: %d", fid));
705       return cstring_makeLiteralTemp ("<invalid>");
706     }
707
708   llassert (fileTable_isDefined (ft));
709   return (ft->elements[fid]->fname);
710 }
711
712 cstring
713 fileTable_getRootName (fileTable ft, fileId fid)
714 {
715   fileId fder;
716
717   if (!fileId_isValid (fid))
718     {
719       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
720       return cstring_makeLiteralTemp ("<invalid>");
721     }
722
723   if (!fileTable_isDefined (ft))
724     {
725       return cstring_makeLiteralTemp ("<no file table>");
726     }
727
728   fder = ft->elements[fid]->fder;
729
730   if (fileId_isValid (fder))
731     {
732       return (ft->elements[fder]->fname);
733     }
734   else
735     {
736       return (ft->elements[fid]->fname);
737     }
738 }
739
740 cstring
741 fileTable_getNameBase (fileTable ft, fileId fid)
742 {
743   if (!fileId_isValid (fid))
744     {
745       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
746       return cstring_makeLiteralTemp ("<invalid>");
747     }
748   
749   if (!fileTable_isDefined (ft))
750     {
751       return cstring_makeLiteralTemp ("<no file table>");
752     }
753   
754   return (ft->elements[fid]->basename);
755 }
756
757 bool
758 fileTable_sameBase (fileTable ft, fileId f1, fileId f2)
759 {
760   fileId fd1, fd2;
761
762   if (!fileId_isValid (f1))
763     {
764       return FALSE;
765     }
766
767   if (!fileId_isValid (f2))
768     {
769       return FALSE;
770     }
771
772   llassert (fileTable_isDefined (ft));
773
774   if (f1 == f2) 
775     {
776       return TRUE;
777     }
778
779   fd1 = ft->elements[f1]->fder;
780
781   if (!fileId_isValid (fd1))
782     {
783       fd1 = f1;
784     }
785
786   fd2 = ft->elements[f2]->fder;
787
788
789   if (!fileId_isValid (fd2))
790     {
791       fd2 = f2;
792     }
793
794   return (fd1 == fd2);
795 }
796
797 void
798 fileTable_cleanup (fileTable ft)
799 {
800   int i;
801   bool msg;
802   int skip;
803   
804   llassert (fileTable_isDefined (ft));
805
806   msg = ((ft->nentries > 40) && context_getFlag (FLG_SHOWSCAN));
807   skip = ft->nentries / 10;
808
809   if (msg)
810     {
811       (void) fflush (g_warningstream);
812       displayScanOpen (cstring_makeLiteral ("< cleaning"));
813     }
814
815   for (i = 0; i < ft->nentries; i++)
816     {
817       ftentry fe = ft->elements[i];
818
819       if (fe->ftemp)
820         {
821           /* let's be real careful now, hon! */
822           
823           /*
824           ** Make sure it is really a derived file
825           */
826
827           
828           if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
829             {
830               ; /* already removed */ 
831             }
832           else if (fileId_isValid (fe->fder)) 
833             {
834               /*@i423 this should use close (fd) also... */
835               (void) osd_unlink (fe->fname);
836             }
837           else if (fe->ftype == FILE_MACROS)
838             {
839               (void) osd_unlink (fe->fname);
840             }
841           else
842             {
843               llbug (message ("Temporary file is not derivative: %s "
844                               "(not deleted)", fe->fname));
845             }
846         }
847       else
848         {
849           ;
850         }
851
852       if (msg && ((i % skip) == 0))
853         {
854           displayScan (cstring_makeLiteral (i == 0 ? " " : "."));
855         }
856     }
857
858   if (msg)
859     {
860       displayScanClose ();
861     }
862 }
863
864 void
865 fileTable_free (/*@only@*/ fileTable f)
866 {
867   int i = 0;
868   
869   if (f == (fileTable)NULL) 
870     {
871       return;
872     }
873
874   while ( i < f->nentries ) 
875     {
876       ftentry_free (f->elements[i]);
877       i++;
878     }
879   
880   cstringTable_free (f->htable);
881   sfree (f->elements);
882   sfree (f);
883 }
884
885 /*
886 ** unique temp filename are constructed from <dir><pre><pid><msg>.<suf>
887 ** requires: <dir> must end in '/'
888 */
889
890 static void nextMsg (char *msg)
891 {
892   /*@+charint@*/
893   if (msg[0] < 'Z') 
894     {
895       msg[0]++; 
896     }
897   else 
898     {
899       msg[0] = 'A';
900       if (msg[1] < 'Z')
901         { 
902           msg[1]++; 
903         }
904       else
905         {
906           msg[1] = 'A';
907           if (msg[2] < 'Z') 
908             {
909               msg[2]++;
910             }
911           else
912             {
913               msg[2] = 'A';
914               if (msg[3] < 'Z') 
915                 {
916                   msg[3]++; 
917                 }
918               else
919                 {
920                   llassertprint (FALSE, ("nextMsg: out of unique names!!!"));
921                 }
922             }
923         }
924     }
925   /*@-charint@*/
926 }
927
928 static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf)
929 {
930   static int pid = 0; 
931   static /*@owned@*/ char *msg = NULL; 
932   static /*@only@*/ cstring pidname = NULL;
933   int maxlen;
934   cstring smsg;
935
936   llassert (cstring_length (pre) <= 3);
937
938   /*
939   ** We limit the temp name to 8 characters:
940   **   pre: 3 or less
941   **   msg: 3
942   **   pid: 2  (% 100)
943   */
944
945   if (msg == NULL)
946     {
947       msg = mstring_copy ("AAA"); /* there are 26^3 temp names */
948     }
949
950   if (pid == 0) 
951     {
952       /*@+matchanyintegral@*/
953       pid = osd_getPid ();
954       /*@=matchanyintegral@*/
955     }
956
957   if (cstring_isUndefined (pidname)) 
958     {
959       pidname = message ("%d", pid % 100);
960     }
961   
962   maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg) 
963             + cstring_length (pidname) + cstring_length (suf) + 2);
964
965   DPRINTF (("Dir: %s / %s / %s / %s / %s",
966             dir, pre, pidname, msg, suf));
967
968   smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
969   nextMsg (msg);
970
971   DPRINTF (("Trying: %s", smsg));
972
973   while (osd_fileExists (smsg))
974     {
975       cstring_free (smsg);
976       smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
977       nextMsg (msg);
978     }
979
980   return smsg;
981 }
982
983 static foentry
984 foentry_create (/*@exposed@*/ FILE *f, /*@only@*/ cstring fname)
985 {
986   foentry t = (foentry) dmalloc (sizeof (*t));
987   t->f = f;
988   t->fname = fname;
989   return t;
990 }
991
992 static void 
993 foentry_free (/*@only@*/ foentry foe)
994 {
995   cstring_free (foe->fname);
996   sfree (foe);
997 }
998
999 static void 
1000 fileTable_addOpen (fileTable ft, /*@observer@*/ FILE *f, /*@only@*/ cstring fname)
1001 {
1002   llassert (fileTable_isDefined (ft));
1003
1004   if (ft->nopenspace <= 0) 
1005     {
1006       fileTable_growOpen (ft);
1007     }
1008
1009   ft->nopenspace--;
1010   ft->openelements[ft->nopen] = foentry_create (f, fname);
1011   ft->nopen++;
1012 }
1013
1014 FILE *fileTable_createFile (fileTable ft, cstring fname)
1015 {
1016   int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
1017
1018   if (fdesc == -1)
1019     {
1020       osd_setTempError ();
1021       llfatalerror (message ("Temporary file for "
1022                              "pre-processor output already exists.  Trying to "
1023                              "open: %s.",
1024                              fname));
1025
1026       /*@notreached@*/ return NULL;
1027     }
1028   else
1029     {
1030       FILE *res = fdopen (fdesc, "w");
1031   
1032       if (res != NULL) 
1033         {
1034           fileTable_addOpen (ft, res, cstring_copy (fname));
1035           DPRINTF (("Opening file: %s / %p", fname, res));
1036         }
1037       else
1038         {
1039           DPRINTF (("Error opening: %s", fname));
1040         }
1041
1042       return res;
1043     }
1044 }
1045
1046 FILE *fileTable_createMacrosFile (fileTable ft, cstring fname)
1047 {
1048   int fdesc = open (cstring_toCharsSafe (fname), O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
1049
1050   if (fdesc == -1)
1051     {
1052       osd_setTempError ();
1053       llfatalerror (message ("Temporary file for "
1054                              "pre-processor output already exists.  Trying to "
1055                              "open: %s.",
1056                              fname));
1057
1058       /*@notreached@*/ return NULL;
1059     }
1060   else
1061     {
1062       FILE *res = fdopen (fdesc, "w+");
1063   
1064       if (res != NULL) 
1065         {
1066           fileTable_addOpen (ft, res, cstring_copy (fname));
1067           DPRINTF (("Opening file: %s / %p", fname, res));
1068         }
1069       else
1070         {
1071           DPRINTF (("Error opening: %s", fname));
1072         }
1073
1074       return res;
1075     }
1076 }
1077
1078 FILE *fileTable_openReadFile (fileTable ft, cstring fname)
1079 {
1080   FILE *res = fopen (cstring_toCharsSafe (fname), "r");
1081
1082   if (res != NULL) 
1083     {
1084       fileTable_addOpen (ft, res, cstring_copy (fname));
1085       DPRINTF (("Opening read file: %s / %p", fname, res));
1086     }
1087   else
1088     {
1089       DPRINTF (("Cannot open read file: %s", fname));
1090     }
1091
1092   return res;
1093 }
1094
1095 /*
1096 ** Allows overwriting
1097 */
1098
1099 FILE *fileTable_openWriteFile (fileTable ft, cstring fname)
1100 {
1101   FILE *res = fopen (cstring_toCharsSafe (fname), "w");
1102
1103   if (res != NULL) {
1104     fileTable_addOpen (ft, res, cstring_copy (fname));
1105     DPRINTF (("Opening file: %s / %p", fname, res));
1106   }
1107
1108   return res;
1109 }
1110
1111 FILE *fileTable_openWriteUpdateFile (fileTable ft, cstring fname)
1112 {
1113   FILE *res = fopen (cstring_toCharsSafe (fname), "w+");
1114
1115   if (res != NULL) {
1116     fileTable_addOpen (ft, res, cstring_copy (fname));
1117     DPRINTF (("Opening file: %s / %p", fname, res));
1118   }
1119
1120   return res;
1121 }
1122
1123 bool fileTable_closeFile (fileTable ft, FILE *f)
1124 {
1125   bool foundit = FALSE;
1126   int i = 0;
1127
1128   llassert (fileTable_isDefined (ft));
1129
1130   DPRINTF (("Closing file: %p", f));
1131
1132   for (i = 0; i < ft->nopen; i++) 
1133     {
1134       if (ft->openelements[i]->f == f)
1135         {
1136           DPRINTF (("Closing file: %p = %s", f, ft->openelements[i]->fname));
1137           
1138           if (i == ft->nopen - 1)
1139             {
1140               foentry_free (ft->openelements[i]);
1141               ft->openelements[i] = NULL;
1142             }
1143           else
1144             {
1145               foentry_free (ft->openelements[i]);
1146               ft->openelements[i] = ft->openelements[ft->nopen - 1];
1147               ft->openelements[ft->nopen - 1] = NULL;
1148             }
1149
1150           ft->nopen--;
1151           ft->nopenspace++;
1152           foundit = TRUE;
1153           break;
1154         }
1155     }
1156   
1157   llassert (foundit);
1158   return (fclose (f) == 0);
1159 }
1160
1161 void fileTable_closeAll (fileTable ft)
1162 {
1163   int i = 0;
1164
1165   llassert (fileTable_isDefined (ft));
1166
1167   for (i = 0; i < ft->nopen; i++) 
1168     {
1169       /* 
1170          lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname)); 
1171       */
1172       
1173       if (ft->openelements[i]->f != NULL)
1174         {
1175           (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */
1176         }
1177
1178       ft->openelements[i]->f = NULL;
1179       foentry_free (ft->openelements[i]);
1180       ft->openelements[i] = NULL;
1181     }
1182   
1183   ft->nopenspace += ft->nopen;
1184   ft->nopen = 0;
1185 }
1186
This page took 0.116844 seconds and 3 git commands to generate.