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