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