]> andersk Git - splint.git/blob - src/fileTable.c
dee235ea4077aaa709e5732549c6dec6492a3554
[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 "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   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   /*@i534 fprintf (stderr, "Got abs path: %s", absname); */
332   llassert (ft != fileTable_undefined);
333
334   if (tindex != NOT_FOUND)
335     {
336       llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", absname));
337       return tindex;
338     }
339   else
340     {
341       ftentry e = ftentry_create (absname, temp, typ, der);
342
343       if (der == fileId_invalid)
344         {
345           llassert (cstring_isUndefined (e->basename));
346
347           e->basename = fileLib_removePathFree (fileLib_removeAnyExtension (absname));
348           e->fsystem = context_isSystemDir (absname);
349
350           /*
351           ** evans 2002-03-15: change suggested by Jim Zelenka
352           **                   support relative paths for system directories
353           */
354
355           if (!e->fsystem)
356             {
357               e->fsystem = context_isSystemDir (name);
358             }
359
360           e->fspecial = context_isSpecialFile (absname);
361
362           if (e->fspecial)
363             {
364               cstring srcname = cstring_concatFree1 (fileLib_removeAnyExtension (absname), 
365                                                      C_EXTENSION);
366               fileId fid = fileTable_lookup (ft, srcname);
367               cstring_free (srcname);
368
369               if (fileId_isValid (fid))
370                 {
371                   fileId derid = ft->elements[fid]->fder;
372
373                   ft->elements[fid]->fspecial = TRUE;
374
375                   if (fileId_isValid (derid))
376                     {
377                       ft->elements[derid]->fspecial = TRUE;
378                     }
379                 }
380             }
381         }
382       else
383         {
384           ftentry de = ft->elements[der];
385
386           llassert (cstring_isUndefined (e->basename));
387           e->basename = cstring_copy (de->basename);
388           e->fsystem = de->fsystem;
389           e->fspecial = de->fspecial;
390         }
391
392       return (fileTable_internAddEntry (ft, e));
393     }
394 }
395
396 fileId
397 fileTable_addFile (fileTable ft, cstring name)
398 {
399   return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
400 }
401
402 fileId
403 fileTable_addFileOnly (fileTable ft, /*@only@*/ cstring name)
404 {
405   fileId res = fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid);
406   cstring_free (name);
407   return res;
408 }
409
410 fileId
411 fileTable_addHeaderFile (fileTable ft, cstring name)
412 {
413   fileId res;
414   res = fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid);
415   return res;
416
417 }
418
419 void
420 fileTable_addStreamFile (fileTable ft, FILE *fstream, cstring name)
421 {
422   fileTable_addOpen (ft, fstream, cstring_copy (name));
423 }
424
425 bool
426 fileTable_isHeader (fileTable ft, fileId fid)
427 {
428   if (fileId_isInvalid (fid))
429     {
430       return FALSE;
431     }
432
433   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
434   return (ft->elements[fid]->ftype == FILE_HEADER);
435 }
436
437 bool
438 fileTable_isSystemFile (fileTable ft, fileId fid)
439 {
440   if (fileId_isInvalid (fid))
441     {
442       return FALSE;
443     }
444
445   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
446   return (ft->elements[fid]->fsystem);
447 }
448
449 bool
450 fileTable_isXHFile (fileTable ft, fileId fid)
451 {
452   if (fileId_isInvalid (fid))
453     {
454       return FALSE;
455     }
456
457   if (!(fileTable_isDefined (ft) && fileTable_inRange (ft, fid)))
458     {
459       llcontbug (message ("Bad file table or id: %s %d", bool_unparse (fileTable_isDefined (ft)), fid));
460       return FALSE;
461     }
462   else
463     {
464       return (ft->elements[fid]->ftype == FILE_XH);
465     }
466 }
467
468 bool
469 fileTable_isSpecialFile (fileTable ft, fileId fid)
470 {
471   if (fileId_isInvalid (fid))
472     {
473       return FALSE;
474     }
475   
476   llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
477   return (ft->elements[fid]->fspecial);
478 }
479
480 fileId
481 fileTable_addLibraryFile (fileTable ft, cstring name)
482 {
483   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
484 }
485
486 fileId
487 fileTable_addXHFile (fileTable ft, cstring name)
488 {
489   return (fileTable_addFilePrim (ft, name, FALSE, FILE_XH, fileId_invalid));
490 }
491
492 fileId
493 fileTable_addImportFile (fileTable ft, cstring name)
494 {
495   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
496 }
497
498 fileId
499 fileTable_addLCLFile (fileTable ft, cstring name)
500 {
501   return (fileTable_addFilePrim (ft, name, FALSE, FILE_HEADER, fileId_invalid));
502 }
503
504 static int tmpcounter = 0;
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 fileId
567 fileTable_addltemp (fileTable ft)
568 {
569   cstring newname = makeTempName (context_tmpdir (),
570                                   cstring_makeLiteralTemp ("ls"), 
571                                   cstring_makeLiteralTemp (".lsl"));
572   fileId ret;
573   
574   if (cstring_hasNonAlphaNumBar (newname))
575     {
576       char *lastpath = (char *)NULL;
577
578       if (tmpcounter == 0)
579         {
580           lldiagmsg
581             (message
582              ("Operating system generates tmp filename containing invalid charater: %s",
583               newname));
584           lldiagmsg (cstring_makeLiteral 
585                      ("Try cleaning up the tmp directory.  Attempting to continue."));
586         }
587       
588       /*@access cstring@*/
589       llassert (cstring_isDefined (newname));
590       lastpath = strrchr (newname, CONNECTCHAR); /* get the directory */
591       llassert (lastpath != NULL);
592       *lastpath = '\0';
593
594       newname = message ("%q%hlsl%d.lsl", 
595                          newname,
596                          CONNECTCHAR,
597                          tmpcounter);
598       /*@noaccess cstring@*/
599       tmpcounter++;
600     }
601   
602   /*
603   ** this is kind of yucky...need to make the result of cstring_fromChars
604   ** refer to the same storage as its argument.  Of course, this loses,
605   ** since cstring is abstract.  Should make it an only?
606   */
607
608   ret = fileTable_addFilePrim (ft, newname, TRUE, FILE_LSLTEMP, fileId_invalid);
609   cstring_free (newname);
610   return (ret);
611 }
612
613 bool
614 fileTable_exists (fileTable ft, cstring s)
615 {
616   int tindex = fileTable_getIndex (ft, s);
617
618   if (tindex == NOT_FOUND)
619     {
620       DPRINTF (("Not found: %s", s));
621       return FALSE;
622     }
623   else
624     {
625       return TRUE;
626     }
627 }
628
629 fileId
630 fileTable_lookup (fileTable ft, cstring s)
631 {
632   int tindex = fileTable_getIndex (ft, s);
633
634   if (tindex == NOT_FOUND)
635     {
636       return fileId_invalid;
637     }
638   else
639     {
640       return tindex;
641     }
642 }
643
644 /*
645 ** This is pretty awkward --- when we find the real path of 
646 ** a .xh file, we may need to change the recorded name.  [Sigh]
647 */
648
649 void
650 fileTable_setFilePath (fileTable ft, fileId fid, cstring path)
651 {
652   llassert (fileId_isValid (fid));
653   llassert (fileTable_isDefined (ft));
654   /* Need to put new string in hash table */
655   cstringTable_insert (ft->htable, cstring_copy (path), fid);
656   ft->elements[fid]->fname = cstring_copy (path);
657 }
658
659 fileId
660 fileTable_lookupBase (fileTable ft, cstring base)
661 {
662   int tindex;
663
664   if (context_getFlag (FLG_CASEINSENSITIVEFILENAMES))
665     {
666       cstring dbase = cstring_downcase (base);
667       tindex = fileTable_getIndex (ft, dbase);
668       cstring_free (dbase);
669     }
670   else
671     {
672       tindex = fileTable_getIndex (ft, base);
673     }
674
675   if (tindex == NOT_FOUND)
676     {
677       return fileId_invalid;
678     }
679   else
680     {
681       fileId der;
682
683       llassert (fileTable_isDefined (ft));
684
685       der = ft->elements[tindex]->fder;
686       
687       if (!fileId_isValid (der))
688         {
689           der = tindex;
690         }
691
692       return der; 
693     }
694 }
695
696 cstring
697 fileTable_getName (fileTable ft, fileId fid)
698 {
699   if (!fileId_isValid (fid))
700     {
701       llcontbug 
702         (message ("fileTable_getName: called with invalid type id: %d", fid));
703       return cstring_makeLiteralTemp ("<invalid>");
704     }
705
706   llassert (fileTable_isDefined (ft));
707   return (ft->elements[fid]->fname);
708 }
709
710 cstring
711 fileTable_getRootName (fileTable ft, fileId fid)
712 {
713   fileId fder;
714
715   if (!fileId_isValid (fid))
716     {
717       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
718       return cstring_makeLiteralTemp ("<invalid>");
719     }
720
721   if (!fileTable_isDefined (ft))
722     {
723       return cstring_makeLiteralTemp ("<no file table>");
724     }
725
726   fder = ft->elements[fid]->fder;
727
728   if (fileId_isValid (fder))
729     {
730       return (ft->elements[fder]->fname);
731     }
732   else
733     {
734       return (ft->elements[fid]->fname);
735     }
736 }
737
738 cstring
739 fileTable_getNameBase (fileTable ft, fileId fid)
740 {
741   if (!fileId_isValid (fid))
742     {
743       llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
744       return cstring_makeLiteralTemp ("<invalid>");
745     }
746   
747   if (!fileTable_isDefined (ft))
748     {
749       return cstring_makeLiteralTemp ("<no file table>");
750     }
751   
752   return (ft->elements[fid]->basename);
753 }
754
755 bool
756 fileTable_sameBase (fileTable ft, fileId f1, fileId f2)
757 {
758   fileId fd1, fd2;
759
760   if (!fileId_isValid (f1))
761     {
762       return FALSE;
763     }
764
765   if (!fileId_isValid (f2))
766     {
767       return FALSE;
768     }
769
770   llassert (fileTable_isDefined (ft));
771
772   if (f1 == f2) 
773     {
774       return TRUE;
775     }
776
777   fd1 = ft->elements[f1]->fder;
778
779   if (!fileId_isValid (fd1))
780     {
781       fd1 = f1;
782     }
783
784   fd2 = ft->elements[f2]->fder;
785
786
787   if (!fileId_isValid (fd2))
788     {
789       fd2 = f2;
790     }
791
792   return (fd1 == fd2);
793 }
794
795 void
796 fileTable_cleanup (fileTable ft)
797 {
798   int i;
799   bool msg;
800   int skip;
801   
802   llassert (fileTable_isDefined (ft));
803
804   msg = ((ft->nentries > 40) && context_getFlag (FLG_SHOWSCAN));
805   skip = ft->nentries / 10;
806
807   if (msg)
808     {
809       (void) fflush (g_warningstream);
810       displayScanOpen (cstring_makeLiteral ("cleaning"));
811     }
812
813   for (i = 0; i < ft->nentries; i++)
814     {
815       ftentry fe = ft->elements[i];
816
817       if (fe->ftemp)
818         {
819           /* let's be real careful now, hon! */
820           
821           /*
822           ** Make sure it is really a derived file
823           */
824
825           
826           if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
827             {
828               ; /* already removed */ 
829             }
830           else if (fileId_isValid (fe->fder)) 
831             {
832               /*@i423 this should use close (fd) also... */
833               (void) osd_unlink (fe->fname);
834             }
835           else if (fe->ftype == FILE_MACROS)
836             {
837               (void) osd_unlink (fe->fname);
838             }
839           else
840             {
841               llbug (message ("Temporary file is not derivative: %s "
842                               "(not deleted)", fe->fname));
843             }
844         }
845       else
846         {
847           ;
848         }
849
850       if (msg && ((i % skip) == 0))
851         {
852           displayScanContinue (cstring_makeLiteral (i == 0 ? " " : "."));
853         }
854     }
855
856   if (msg)
857     {
858       displayScanClose ();
859     }
860 }
861
862 void
863 fileTable_free (/*@only@*/ fileTable f)
864 {
865   int i = 0;
866   
867   if (f == (fileTable)NULL) 
868     {
869       return;
870     }
871
872   while ( i < f->nentries ) 
873     {
874       ftentry_free (f->elements[i]);
875       i++;
876     }
877   
878   cstringTable_free (f->htable);
879   sfree (f->elements);
880   sfree (f->openelements); /*!! why didn't splint report this? */
881   sfree (f);
882 }
883
884 /*
885 ** unique temp filename are constructed from <dir><pre><pid><msg>.<suf>
886 ** requires: <dir> must end in '/'
887 */
888
889 static void nextMsg (char *msg)
890 {
891   /*@+charint@*/
892   if (msg[0] < 'Z') 
893     {
894       msg[0]++; 
895     }
896   else 
897     {
898       msg[0] = 'A';
899       if (msg[1] < 'Z')
900         { 
901           msg[1]++; 
902         }
903       else
904         {
905           msg[1] = 'A';
906           if (msg[2] < 'Z') 
907             {
908               msg[2]++;
909             }
910           else
911             {
912               msg[2] = 'A';
913               if (msg[3] < 'Z') 
914                 {
915                   msg[3]++; 
916                 }
917               else
918                 {
919                   llassertprint (FALSE, ("nextMsg: out of unique names!!!"));
920                 }
921             }
922         }
923     }
924   /*@-charint@*/
925 }
926
927 static /*@only@*/ cstring makeTempName (cstring dir, cstring pre, cstring suf)
928 {
929   static int pid = 0; 
930   static /*@owned@*/ char *msg = NULL; 
931   static /*@only@*/ cstring pidname = NULL;
932   size_t maxlen;
933   cstring smsg;
934
935   llassert (cstring_length (pre) <= 3);
936
937   /*
938   ** We limit the temp name to 8 characters:
939   **   pre: 3 or less
940   **   msg: 3
941   **   pid: 2  (% 100)
942   */
943
944   if (msg == NULL)
945     {
946       msg = mstring_copy ("AAA"); /* there are 26^3 temp names */
947     }
948
949   if (pid == 0) 
950     {
951       /*@+matchanyintegral@*/
952       pid = osd_getPid ();
953       /*@=matchanyintegral@*/
954     }
955
956   if (cstring_isUndefined (pidname)) 
957     {
958       pidname = message ("%d", pid % 100);
959     }
960   
961   maxlen = (cstring_length (dir) + cstring_length (pre) + mstring_length (msg) 
962             + cstring_length (pidname) + cstring_length (suf) + 2);
963
964   DPRINTF (("Dir: %s / %s / %s / %s / %s",
965             dir, pre, pidname, msg, suf));
966
967   smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
968   nextMsg (msg);
969
970   DPRINTF (("Trying: %s", smsg));
971
972   while (osd_fileExists (smsg))
973     {
974       cstring_free (smsg);
975       smsg = message ("%s%s%s%s%s", dir, pre, pidname, cstring_fromChars (msg), suf);
976       nextMsg (msg);
977     }
978
979   return smsg;
980 }
981
982 static foentry
983 foentry_create (/*@exposed@*/ FILE *f, /*@only@*/ cstring fname)
984 {
985   foentry t = (foentry) dmalloc (sizeof (*t));
986   t->f = f;
987   t->fname = fname;
988   return t;
989 }
990
991 static void 
992 foentry_free (/*@only@*/ foentry foe)
993 {
994   cstring_free (foe->fname);
995   sfree (foe);
996 }
997
998 static void 
999 fileTable_addOpen (fileTable ft, /*@observer@*/ FILE *f, /*@only@*/ cstring fname)
1000 {
1001   llassert (fileTable_isDefined (ft));
1002
1003   if (ft->nopenspace <= 0) 
1004     {
1005       fileTable_growOpen (ft);
1006     }
1007
1008   ft->nopenspace--;
1009   ft->openelements[ft->nopen] = foentry_create (f, fname);
1010   ft->nopen++;
1011 }
1012
1013 FILE *fileTable_createFile (fileTable ft, cstring fname)
1014 {
1015 # ifdef WIN32
1016    int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); /* not supported by VS.net: , S_IRUSR | S_IWUSR); */
1017 # else
1018    int fdesc = open (cstring_toCharsSafe (fname), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
1019 # endif
1020
1021   if (fdesc == -1)
1022     {
1023       osd_setTempError ();
1024       llfatalerror (message ("Temporary file for "
1025                              "pre-processor output already exists.  Trying to "
1026                              "open: %s.",
1027                              fname));
1028
1029       /*@notreached@*/ return NULL;
1030     }
1031   else
1032     {
1033       FILE *res = fdopen (fdesc, "w");
1034   
1035       if (res != NULL) 
1036         {
1037           fileTable_addOpen (ft, res, cstring_copy (fname));
1038           DPRINTF (("Opening file: %s / %p", fname, res));
1039         }
1040       else
1041         {
1042           DPRINTF (("Error opening: %s", fname));
1043         }
1044
1045       return res;
1046     }
1047 }
1048
1049 FILE *fileTable_createMacrosFile (fileTable ft, cstring fname)
1050 {
1051   int fdesc = open (cstring_toCharsSafe (fname), O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
1052
1053   if (fdesc == -1)
1054     {
1055       osd_setTempError ();
1056       llfatalerror (message ("Temporary file for "
1057                              "pre-processor output already exists.  Trying to "
1058                              "open: %s.",
1059                              fname));
1060
1061       /*@notreached@*/ return NULL;
1062     }
1063   else
1064     {
1065       FILE *res = fdopen (fdesc, "w+");
1066   
1067       if (res != NULL) 
1068         {
1069           fileTable_addOpen (ft, res, cstring_copy (fname));
1070           DPRINTF (("Opening file: %s / %p", fname, res));
1071         }
1072       else
1073         {
1074           DPRINTF (("Error opening: %s", fname));
1075         }
1076
1077       return res;
1078     }
1079 }
1080
1081 FILE *fileTable_openReadFile (fileTable ft, cstring fname)
1082 {
1083   FILE *res = fopen (cstring_toCharsSafe (fname), "r");
1084
1085   if (res != NULL) 
1086     {
1087       fileTable_addOpen (ft, res, cstring_copy (fname));
1088       DPRINTF (("Opening read file: %s / %p", fname, res));
1089     }
1090   else
1091     {
1092       DPRINTF (("Cannot open read file: %s", fname));
1093     }
1094
1095   return res;
1096 }
1097
1098 /*
1099 ** Allows overwriting
1100 */
1101
1102 FILE *fileTable_openWriteFile (fileTable ft, cstring fname)
1103 {
1104   FILE *res = fopen (cstring_toCharsSafe (fname), "w");
1105
1106   if (res != NULL) {
1107     fileTable_addOpen (ft, res, cstring_copy (fname));
1108     DPRINTF (("Opening file: %s / %p", fname, res));
1109   }
1110
1111   return res;
1112 }
1113
1114 FILE *fileTable_openWriteUpdateFile (fileTable ft, cstring fname)
1115 {
1116   FILE *res = fopen (cstring_toCharsSafe (fname), "w+");
1117
1118   if (res != NULL) {
1119     fileTable_addOpen (ft, res, cstring_copy (fname));
1120     DPRINTF (("Opening file: %s / %p", fname, res));
1121   }
1122
1123   return res;
1124 }
1125
1126 bool fileTable_closeFile (fileTable ft, FILE *f)
1127 {
1128   bool foundit = FALSE;
1129   int i = 0;
1130
1131   llassert (fileTable_isDefined (ft));
1132
1133   DPRINTF (("Closing file: %p", f));
1134
1135   for (i = 0; i < ft->nopen; i++) 
1136     {
1137       if (ft->openelements[i]->f == f)
1138         {
1139           DPRINTF (("Closing file: %p = %s", f, ft->openelements[i]->fname));
1140           
1141           if (i == ft->nopen - 1)
1142             {
1143               foentry_free (ft->openelements[i]);
1144               ft->openelements[i] = NULL;
1145             }
1146           else
1147             {
1148               foentry_free (ft->openelements[i]);
1149               ft->openelements[i] = ft->openelements[ft->nopen - 1];
1150               ft->openelements[ft->nopen - 1] = NULL;
1151             }
1152
1153           ft->nopen--;
1154           ft->nopenspace++;
1155           foundit = TRUE;
1156           break;
1157         }
1158     }
1159   
1160   llassert (foundit);
1161   return (fclose (f) == 0);
1162 }
1163
1164 void fileTable_closeAll (fileTable ft)
1165 {
1166   int i = 0;
1167
1168   llassert (fileTable_isDefined (ft));
1169
1170   for (i = 0; i < ft->nopen; i++) 
1171     {
1172       /* 
1173          lldiagmsg (message ("Unclosed file at exit: %s", ft->openelements[i]->fname)); 
1174       */
1175       
1176       if (ft->openelements[i]->f != NULL)
1177         {
1178           (void) fclose (ft->openelements[i]->f); /* No check - cleaning up after errors */
1179         }
1180
1181       ft->openelements[i]->f = NULL;
1182       foentry_free (ft->openelements[i]);
1183       ft->openelements[i] = NULL;
1184     }
1185   
1186   ft->nopenspace += ft->nopen;
1187   ft->nopen = 0;
1188 }
1189
This page took 0.388472 seconds and 3 git commands to generate.