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