00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 # include "lclintMacros.nf"
00048 # include "llbasic.h"
00049 # include "osd.h"
00050 # include "llmain.h"
00051 # include "portab.h"
00052 # if defined(__IBMC__) && defined(OS2)
00053 # include <process.h>
00054 # define getpid _getpid
00055 # endif
00056
00057
00058
00059 static bool fileTable_inRange (fileTable ft, fileId fid)
00060 {
00061 return (fileTable_isDefined (ft) && (fid >= 0) && (fid < ft->nentries));
00062 }
00063
00064 static fileId fileTable_internAddEntry (fileTable p_ft, ftentry p_e)
00065 ;
00066 static char *makeTempName (char *p_dir, char *p_pre, char *p_suf);
00067
00068 static cstring
00069 fileType_unparse (fileType ft)
00070 {
00071 switch (ft)
00072 {
00073 case FILE_NORMAL: return cstring_makeLiteral ("normal");
00074 case FILE_NODELETE: return cstring_makeLiteral ("normal");
00075 case FILE_LSLTEMP: return cstring_makeLiteral ("ltemp");
00076 case FILE_HEADER: return cstring_makeLiteral ("header");
00077 case FILE_MACROS: return cstring_makeLiteral ("macros");
00078 }
00079
00080 BADEXIT;
00081 }
00082
00083 static int
00084 fileTable_getIndex (fileTable ft, cstring s)
00085 {
00086 if (ft == NULL) return NOT_FOUND;
00087 return (hashTable_lookup (ft->htable, s));
00088 }
00089
00090 cstring
00091 fileTable_unparse (fileTable ft)
00092 {
00093 cstring s = cstring_undefined;
00094 int i;
00095
00096 if (fileTable_isUndefined (ft))
00097 {
00098 return (cstring_makeLiteral ("<fileTable undefined>"));
00099 }
00100
00101 for (i = 0; i < ft->nentries; i++)
00102 {
00103 if (fileId_isValid (ft->elements[i]->fder))
00104 {
00105 s = message ("%s\n[%d] %s %q %d (%s)",
00106 s, i,
00107 ft->elements[i]->fname,
00108 fileType_unparse (ft->elements[i]->ftype),
00109 ft->elements[i]->fder,
00110 ft->elements[ft->elements[i]->fder]->fname);
00111 }
00112 else
00113 {
00114 s = message ("%s\n[%d] %s %q", s, i, ft->elements[i]->fname,
00115 fileType_unparse (ft->elements[i]->ftype));
00116 }
00117 }
00118
00119 return s;
00120 }
00121
00122 void fileTable_printTemps (fileTable ft)
00123 {
00124 if (fileTable_isDefined (ft))
00125 {
00126 int i;
00127
00128 for (i = 0; i < ft->nentries; i++)
00129 {
00130 if (ft->elements[i]->ftemp)
00131 {
00132 if (fileId_isValid (ft->elements[i]->fder))
00133 {
00134 fprintf (stderr, " %s:1\n\t%s:1\n",
00135 cstring_toCharsSafe (ft->elements[ft->elements[i]->fder]->fname),
00136 cstring_toCharsSafe (ft->elements[i]->fname));
00137 }
00138 else
00139 {
00140 fprintf (stderr, "[no file]\n\t%s:1\n",
00141 cstring_toCharsSafe (ft->elements[i]->fname));
00142 }
00143 }
00144 }
00145 }
00146 }
00147
00148
00149
00150
00151
00152 static ftentry
00153 ftentry_create ( cstring tn, bool temp, fileType typ, fileId der)
00154 {
00155 ftentry t = (ftentry) dmalloc (sizeof (*t));
00156
00157 if (cstring_isUndefined (tn))
00158 {
00159 llbug (cstring_makeLiteral ("Undefined filename!"));
00160 }
00161
00162 t->fname = tn;
00163
00164 t->basename = cstring_undefined;
00165 t->ftemp = temp;
00166 t->ftype = typ;
00167 t->fder = der;
00168
00169
00170 t->fsystem = FALSE;
00171 t->fspecial = FALSE;
00172
00173 return t;
00174 }
00175
00176 static void
00177 ftentry_free ( ftentry t)
00178 {
00179 cstring_free (t->fname);
00180 cstring_free (t->basename);
00181 sfree (t);
00182 }
00183
00184 fileTable
00185 fileTable_create ()
00186 {
00187 fileTable ft = (fileTable) dmalloc (sizeof (*ft));
00188
00189 ft->nentries = 0;
00190 ft->nspace = FTBASESIZE;
00191 ft->elements = (ftentry *) dmalloc (FTBASESIZE * sizeof (*ft->elements));
00192 ft->htable = hashTable_create (FTHASHSIZE);
00193
00194 return (ft);
00195 }
00196
00197 static void
00198 fileTable_grow (fileTable ft)
00199 {
00200 int i;
00201 ftentry *newent;
00202
00203 llassert (fileTable_isDefined (ft));
00204
00205 ft->nspace = FTBASESIZE;
00206
00207 newent = (ftentry *) dmalloc ((ft->nentries + ft->nspace) * sizeof (*newent));
00208
00209 for (i = 0; i < ft->nentries; i++)
00210 {
00211 newent[i] = ft->elements[i];
00212 }
00213
00214 sfree (ft->elements);
00215 ft->elements = newent;
00216 }
00217
00218 static fileId
00219 fileTable_internAddEntry (fileTable ft, ftentry e)
00220 {
00221 llassert (fileTable_isDefined (ft));
00222
00223 if (ft->nspace <= 0)
00224 fileTable_grow (ft);
00225
00226 ft->nspace--;
00227
00228 hashTable_insert (ft->htable, e->fname, ft->nentries);
00229 ft->elements[ft->nentries] = e;
00230
00231 ft->nentries++;
00232
00233 return (ft->nentries - 1);
00234 }
00235
00236 void fileTable_noDelete (fileTable ft, cstring name)
00237 {
00238 fileId fid = fileTable_lookup (ft, name);
00239
00240 if (fileId_isValid (fid)) {
00241 llassert (fileTable_isDefined (ft));
00242
00243 ft->elements[fid]->ftype = FILE_NODELETE;
00244 }
00245 }
00246
00247 static fileId
00248 fileTable_addFilePrim (fileTable ft, cstring name,
00249 bool temp, fileType typ, fileId der)
00250
00251 {
00252 int tindex = fileTable_getIndex (ft, name);
00253
00254 llassert (ft != fileTable_undefined);
00255
00256 if (tindex != NOT_FOUND)
00257 {
00258 llcontbug (message ("fileTable_addFilePrim: duplicate entry: %q", name));
00259
00260 return tindex;
00261 }
00262 else
00263 {
00264 ftentry e = ftentry_create (name, temp, typ, der);
00265
00266 if (der == fileId_invalid)
00267 {
00268 llassert (cstring_isUndefined (e->basename));
00269
00270 e->basename = cstring_fromChars
00271 (removePathFree (removeAnyExtension
00272 (cstring_toCharsSafe (name))));
00273 e->fsystem = context_isSystemDir (name);
00274 e->fspecial = context_isSpecialFile (name);
00275
00276 if (e->fspecial)
00277 {
00278 cstring srcname = cstring_concatFree (cstring_fromChars (removeAnyExtension (cstring_toCharsSafe (name))), cstring_makeLiteral (".c"));
00279 fileId fid = fileTable_lookup (ft, srcname);
00280
00281 cstring_free (srcname);
00282
00283 if (fileId_isValid (fid))
00284 {
00285 fileId derid = ft->elements[fid]->fder;
00286
00287 ft->elements[fid]->fspecial = TRUE;
00288
00289 if (fileId_isValid (derid))
00290 {
00291 ft->elements[derid]->fspecial = TRUE;
00292 }
00293 }
00294 }
00295 }
00296 else
00297 {
00298 ftentry de = ft->elements[der];
00299
00300 llassert (cstring_isUndefined (e->basename));
00301 e->basename = cstring_copy (de->basename);
00302 e->fsystem = de->fsystem;
00303 e->fspecial = de->fspecial;
00304 }
00305
00306 return (fileTable_internAddEntry (ft, e));
00307 }
00308 }
00309
00310 fileId
00311 fileTable_addFile (fileTable ft, cstring name)
00312 {
00313
00314 return (fileTable_addFilePrim (ft, cstring_copy (name),
00315 FALSE, FILE_NORMAL, fileId_invalid));
00316 }
00317
00318 fileId
00319 fileTable_addFileOnly (fileTable ft, cstring name)
00320 {
00321 return (fileTable_addFilePrim (ft, name, FALSE, FILE_NORMAL, fileId_invalid));
00322 }
00323
00324 fileId
00325 fileTable_addHeaderFile (fileTable ft, cstring name)
00326 {
00327 DPRINTF (("Add header: %s", name));
00328 return (fileTable_addFilePrim (ft, cstring_copy (name), FALSE,
00329 FILE_HEADER, fileId_invalid));
00330 }
00331
00332 bool
00333 fileTable_isHeader (fileTable ft, fileId fid)
00334 {
00335 if (fileId_isInvalid (fid))
00336 {
00337 return FALSE;
00338 }
00339
00340 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
00341 return (ft->elements[fid]->ftype == FILE_HEADER);
00342 }
00343
00344 bool
00345 fileTable_isSystemFile (fileTable ft, fileId fid)
00346 {
00347 if (fileId_isInvalid (fid))
00348 {
00349 return FALSE;
00350 }
00351
00352 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
00353 return (ft->elements[fid]->fsystem);
00354 }
00355
00356 bool
00357 fileTable_isSpecialFile (fileTable ft, fileId fid)
00358 {
00359 if (fileId_isInvalid (fid))
00360 {
00361 return FALSE;
00362 }
00363
00364 llassert (fileTable_isDefined (ft) && fileTable_inRange (ft, fid));
00365 return (ft->elements[fid]->fspecial);
00366 }
00367
00368 fileId
00369 fileTable_addLibraryFile (fileTable ft, cstring name)
00370 {
00371 return (fileTable_addFilePrim (ft, cstring_copy (name),
00372 FALSE, FILE_HEADER, fileId_invalid));
00373 }
00374
00375 # ifndef NOLCL
00376 fileId
00377 fileTable_addImportFile (fileTable ft, cstring name)
00378 {
00379 return (fileTable_addFilePrim (ft, cstring_copy (name),
00380 FALSE, FILE_HEADER, fileId_invalid));
00381 }
00382
00383 fileId
00384 fileTable_addLCLFile (fileTable ft, cstring name)
00385 {
00386 return (fileTable_addFilePrim (ft, cstring_copy (name),
00387 FALSE, FILE_HEADER, fileId_invalid));
00388 }
00389 # endif
00390
00391 # ifndef NOLCL
00392 static int tmpcounter = 0;
00393 # endif
00394
00395 fileId
00396 fileTable_addMacrosFile (fileTable ft)
00397 {
00398 cstring newname = cstring_fromChars
00399 (makeTempName (cstring_toCharsSafe (context_tmpdir ()), "lmx", ".llm"));
00400
00401 return (fileTable_addFilePrim (ft, newname, TRUE, FILE_MACROS, fileId_invalid));
00402 }
00403
00404 fileId
00405 fileTable_addCTempFile (fileTable ft, fileId fid)
00406 {
00407 # if FALSE
00408
00409 cstring newname = cstring_concatChars (removeAnyExtension (fileName (fid)), ".i");
00410 # else
00411 cstring newname = cstring_fromChars
00412 (makeTempName (cstring_toCharsSafe (context_tmpdir ()), "cl", ".c"));
00413 # endif
00414
00415 llassert (fileTable_isDefined (ft));
00416
00417 if (!fileId_isValid (ft->elements[fid]->fder))
00418 {
00419 return (fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL, fid));
00420 }
00421 else
00422 {
00423 return (fileTable_addFilePrim (ft, newname, TRUE, FILE_NORMAL,
00424 ft->elements[fid]->fder));
00425 }
00426 }
00427
00428 # ifndef NOLCL
00429 fileId
00430 fileTable_addltemp (fileTable ft)
00431 {
00432 char *newname = makeTempName (cstring_toCharsSafe (context_tmpdir ()),
00433 "ls", ".lsl");
00434 char *onewname;
00435 fileId ret;
00436
00437 if (cstring_hasNonAlphaNumBar (cstring_fromChars (newname)))
00438 {
00439 char *lastpath = (char *)NULL;
00440
00441 if (tmpcounter == 0)
00442 {
00443 lldiagmsg
00444 (message
00445 ("Operating system generates tmp filename containing invalid charater: %s",
00446 cstring_fromChars (newname)));
00447 lldiagmsg (cstring_makeLiteral
00448 ("Try cleaning up the tmp directory. Attempting to continue."));
00449 }
00450
00451 lastpath = strrchr (newname, CONNECTCHAR);
00452 llassert (lastpath != NULL);
00453 *lastpath = '\0';
00454
00455 onewname = newname;
00456 newname = cstring_toCharsSafe (message ("%s%hlsl%d.lsl",
00457 cstring_fromChars (newname),
00458 CONNECTCHAR,
00459 tmpcounter));
00460 sfree (onewname);
00461 tmpcounter++;
00462 }
00463
00464
00465
00466
00467
00468
00469
00470 ret = fileTable_addFilePrim (ft, cstring_copy (cstring_fromChars (newname)),
00471 TRUE, FILE_LSLTEMP, fileId_invalid);
00472 sfree (newname);
00473 return (ret);
00474 }
00475 # endif
00476
00477 bool
00478 fileTable_exists (fileTable ft, cstring s)
00479 {
00480 int tindex = fileTable_getIndex (ft, s);
00481
00482 if (tindex == NOT_FOUND)
00483 return FALSE;
00484 else
00485 return TRUE;
00486 }
00487
00488 fileId
00489 fileTable_lookup (fileTable ft, cstring s)
00490 {
00491 int tindex = fileTable_getIndex (ft, s);
00492
00493 if (tindex == NOT_FOUND)
00494 {
00495 return fileId_invalid;
00496 }
00497 else
00498 {
00499 return tindex;
00500 }
00501 }
00502
00503 fileId
00504 fileTable_lookupBase (fileTable ft, cstring base)
00505 {
00506 int tindex = fileTable_getIndex (ft, base);
00507
00508 if (tindex == NOT_FOUND)
00509 {
00510
00511 return fileId_invalid;
00512 }
00513 else
00514 {
00515 fileId der;
00516
00517 llassert (fileTable_isDefined (ft));
00518
00519 der = ft->elements[tindex]->fder;
00520
00521 if (!fileId_isValid (der))
00522 {
00523 der = tindex;
00524 }
00525
00526 return der;
00527 }
00528 }
00529
00530 cstring
00531 fileTable_getName (fileTable ft, fileId fid)
00532 {
00533 if (!fileId_isValid (fid))
00534 {
00535 llcontbug
00536 (message ("fileTable_getName: called with invalid type id: %d", fid));
00537 return cstring_makeLiteralTemp ("<invalid>");
00538 }
00539
00540 llassert (fileTable_isDefined (ft));
00541 return (ft->elements[fid]->fname);
00542 }
00543
00544 cstring
00545 fileTable_getRootName (fileTable ft, fileId fid)
00546 {
00547 fileId fder;
00548
00549 if (!fileId_isValid (fid))
00550 {
00551 llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
00552 return cstring_makeLiteralTemp ("<invalid>");
00553 }
00554
00555 if (!fileTable_isDefined (ft))
00556 {
00557 return cstring_makeLiteralTemp ("<no file table>");
00558 }
00559
00560 fder = ft->elements[fid]->fder;
00561
00562 if (fileId_isValid (fder))
00563 {
00564 return (ft->elements[fder]->fname);
00565 }
00566 else
00567 {
00568 return (ft->elements[fid]->fname);
00569 }
00570 }
00571
00572 cstring
00573 fileTable_getNameBase (fileTable ft, fileId fid)
00574 {
00575 if (!fileId_isValid (fid))
00576 {
00577 llcontbug (message ("fileTable_getName: called with invalid id: %d", fid));
00578 return cstring_makeLiteralTemp ("<invalid>");
00579 }
00580
00581 if (!fileTable_isDefined (ft))
00582 {
00583 return cstring_makeLiteralTemp ("<no file table>");
00584 }
00585
00586 return (ft->elements[fid]->basename);
00587 }
00588
00589 bool
00590 fileTable_sameBase (fileTable ft, fileId f1, fileId f2)
00591 {
00592 fileId fd1, fd2;
00593
00594 if (!fileId_isValid (f1))
00595 {
00596 return FALSE;
00597 }
00598
00599 if (!fileId_isValid (f2))
00600 {
00601 return FALSE;
00602 }
00603
00604 llassert (fileTable_isDefined (ft));
00605
00606 if (f1 == f2)
00607 {
00608 return TRUE;
00609 }
00610
00611 fd1 = ft->elements[f1]->fder;
00612
00613 if (!fileId_isValid (fd1))
00614 {
00615 fd1 = f1;
00616 }
00617
00618 fd2 = ft->elements[f2]->fder;
00619
00620
00621 if (!fileId_isValid (fd2))
00622 {
00623 fd2 = f2;
00624 }
00625
00626 return (fd1 == fd2);
00627 }
00628
00629 void
00630 fileTable_cleanup (fileTable ft)
00631 {
00632 int i;
00633 bool msg;
00634 int skip;
00635
00636 llassert (fileTable_isDefined (ft));
00637
00638 msg = ((ft->nentries > 40) && context_getFlag (FLG_SHOWSCAN));
00639 skip = ft->nentries / 10;
00640
00641 if (msg)
00642 {
00643 (void) fflush (g_msgstream);
00644 fprintf (stderr, "< cleaning");
00645 }
00646
00647 for (i = 0; i < ft->nentries; i++)
00648 {
00649 ftentry fe = ft->elements[i];
00650
00651 if (fe->ftemp)
00652 {
00653
00654
00655
00656
00657
00658
00659 if (fe->ftype == FILE_LSLTEMP || fe->ftype == FILE_NODELETE)
00660 {
00661 ;
00662 }
00663 else if (fileId_isValid (fe->fder))
00664 {
00665 (void) osd_unlink (cstring_toCharsSafe (fe->fname));
00666 }
00667 else if (fe->ftype == FILE_MACROS)
00668 {
00669 (void) osd_unlink (cstring_toCharsSafe (fe->fname));
00670 }
00671 else
00672 {
00673 llbug (message ("Temporary file is not derivative: %s "
00674 "(not deleted)", fe->fname));
00675 }
00676 }
00677 else
00678 {
00679 ;
00680 }
00681
00682 if (msg && ((i % skip) == 0))
00683 {
00684 (void) fflush (g_msgstream);
00685
00686 if (i == 0) {
00687 fprintf (stderr, " ");
00688 } else {
00689 fprintf (stderr, ".");
00690 }
00691
00692 (void) fflush (stderr);
00693 }
00694 }
00695
00696 if (msg)
00697 {
00698 fprintf (stderr, " >\n");
00699 }
00700 }
00701
00702 void
00703 fileTable_free ( fileTable f)
00704 {
00705 int i = 0;
00706
00707 if (f == (fileTable)NULL)
00708 {
00709 return;
00710 }
00711
00712 while ( i < f->nentries )
00713 {
00714 ftentry_free (f->elements[i]);
00715 i++;
00716 }
00717
00718 hashTable_free (f->htable);
00719 sfree (f->elements);
00720 sfree (f);
00721 }
00722
00723
00724
00725
00726
00727
00728 static void nextMsg (char *msg)
00729 {
00730
00731 if (msg[0] < 'Z')
00732 {
00733 msg[0]++;
00734 }
00735 else
00736 {
00737 msg[0] = 'A';
00738 if (msg[1] < 'Z')
00739 {
00740 msg[1]++;
00741 }
00742 else
00743 {
00744 msg[1] = 'A';
00745 if (msg[2] < 'Z')
00746 {
00747 msg[2]++;
00748 }
00749 else
00750 {
00751 msg[2] = 'A';
00752 if (msg[3] < 'Z')
00753 {
00754 msg[3]++;
00755 }
00756 else
00757 {
00758 llassertprint (FALSE, ("nextMsg: out of unique names!!!"));
00759 }
00760 }
00761 }
00762 }
00763
00764 }
00765
00766 static char *makeTempName (char *dir, char *pre, char *suf)
00767 {
00768 static int pid = 0;
00769 static char *msg = NULL;
00770 static char *pidname = NULL;
00771 size_t maxlen;
00772 char *buf;
00773
00774 llassert (strlen (pre) <= 3);
00775
00776
00777
00778
00779
00780
00781
00782
00783 if (msg == NULL)
00784 {
00785 msg = mstring_copy ("AAA");
00786 }
00787
00788 if (pid == 0)
00789 {
00790
00791 pid = osd_getPid ();
00792
00793 }
00794
00795 if (pidname == NULL)
00796 {
00797 pidname = cstring_toCharsSafe (message ("%d", pid % 100));
00798 }
00799 else
00800 {
00801 pidname = mstring_createEmpty ();
00802 }
00803
00804 maxlen = (strlen (dir) + strlen (pre) + strlen (msg)
00805 + strlen (pidname) + strlen (suf) + 2);
00806
00807 buf = mstring_create (size_toInt (maxlen));
00808
00809 sprintf (buf, "%s%s%s%s%s", dir, pre, pidname, msg, suf);
00810 nextMsg (msg);
00811
00812 while (osd_fileExists (buf))
00813 {
00814 sprintf (buf, "%s%s%s%s%s", dir, pre, pidname, msg, suf);
00815 nextMsg (msg);
00816 }
00817
00818 return buf;
00819 }
00820
00821
00822