Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1004 lines
20 KiB

  1. //
  2. // ADDTOLST.C - Add each record from the .SBR file to the approprate list.
  3. //
  4. #define LINT_ARGS
  5. #include "sbrfdef.h"
  6. #include "mbrmake.h"
  7. #include <ctype.h>
  8. // local types
  9. typedef struct _mstk {
  10. struct _mstk FAR *pmstkPrev; // next module stack entry
  11. VA vaCurMod; // saved current module
  12. BOOL fDupMod; // saved dup module flag
  13. BOOL fExclMod; // saved exclude module flag
  14. } MSTK, FAR * PMSTK;
  15. typedef struct _bstk {
  16. struct _bstk FAR *pbstkPrev; // next block stack entry
  17. VA vaOwnerProp; // saved current owner
  18. } BSTK, FAR * PBSTK;
  19. // static variables
  20. BOOL near fDupSym = FALSE; // TRUE if adding duplicate atom
  21. BOOL near cMacroDepth = 0; // depth of MACROBEG records
  22. WORD near ModCnt; // count of modules
  23. WORD near isbrCur; // current SBR file index
  24. VA near vaUnknownSym = vaNil; // Unknown symbol
  25. VA near vaUnknownMod = vaNil; // Unknown module
  26. static VA near vaOwnerProp = vaNil; // ptr to current procedure
  27. static BOOL near fDupMod = FALSE; // duplicate module
  28. static BOOL near fExclMod = FALSE; // exclude this module
  29. static BOOL near fFirstMod = TRUE; // this is 1st module of file
  30. static PMSTK pmstkRoot; // root of module stack
  31. static PBSTK pbstkRoot; // root of block stack
  32. // forward references
  33. static BOOL FSkipMacro(void);
  34. static VOID PushMstk(VOID);
  35. static VOID PushBstk(VOID);
  36. static VOID PopMstk(VOID);
  37. static VOID PopBstk(VOID);
  38. static VOID CheckStacksEmpty(VOID);
  39. VOID
  40. SBRCorrupt (char *psz)
  41. // sbr file corrupt -- print message
  42. //
  43. {
  44. #ifdef DEBUG
  45. printf("Info = %s\n", psz);
  46. #else
  47. // to make /W3 happy
  48. psz;
  49. #endif
  50. Error(ERR_SBR_CORRUPT, lszFName);
  51. }
  52. static VOID
  53. PushMstk (VOID)
  54. // stack the current module context -- occurs before SBR_REC_MODULE
  55. //
  56. {
  57. PMSTK pmstk;
  58. pmstk = LpvAllocCb(sizeof(*pmstk));
  59. pmstk->vaCurMod = vaCurMod; // current module
  60. pmstk->fDupMod = fDupMod; // dup module
  61. pmstk->fExclMod = fExclMod; // exclude module
  62. pmstk->pmstkPrev = pmstkRoot; // make stack links
  63. pmstkRoot = pmstk; // root <- new
  64. }
  65. static VOID
  66. PushBstk (VOID)
  67. // stack the current block context -- occurs before SBR_REC_BLKBEG
  68. //
  69. {
  70. PBSTK pbstk;
  71. pbstk = LpvAllocCb(sizeof(*pbstk));
  72. pbstk->vaOwnerProp = vaOwnerProp; // current owner
  73. pbstk->pbstkPrev = pbstkRoot; // make stack links
  74. pbstkRoot = pbstk; // root <- new
  75. }
  76. static VOID
  77. PopMstk (VOID)
  78. // restore previous module context -- occurs on SBR_REC_MODEND
  79. //
  80. {
  81. PMSTK pmstk;
  82. if (pmstkRoot == NULL) {
  83. #ifdef DEBUG
  84. SBRCorrupt("Module stack empty but MODEND was found");
  85. #else
  86. SBRCorrupt("");
  87. #endif
  88. }
  89. vaCurMod = pmstkRoot->vaCurMod; // get previous current module
  90. fDupMod = pmstkRoot->fDupMod; // get previous dup mod flag
  91. fExclMod = pmstkRoot->fExclMod; // get previous excl mod flag
  92. pmstk = pmstkRoot;
  93. pmstkRoot = pmstkRoot->pmstkPrev;
  94. FreeLpv(pmstk);
  95. }
  96. static VOID
  97. PopBstk (VOID)
  98. // restore previous block context -- occurs on SBR_REC_BLKEND
  99. //
  100. {
  101. PBSTK pbstk;
  102. if (pbstkRoot == NULL) {
  103. #ifdef DEBUG
  104. SBRCorrupt("Block stack empty but BLKEND was found");
  105. #else
  106. SBRCorrupt("");
  107. #endif
  108. }
  109. vaOwnerProp = pbstkRoot->vaOwnerProp; // get previous current proc
  110. pbstk = pbstkRoot;
  111. pbstkRoot = pbstkRoot->pbstkPrev;
  112. FreeLpv(pbstk);
  113. }
  114. static VOID
  115. CheckStacksEmpty(VOID)
  116. // check to make sure that both stacks are empty at the .sbr file EOF
  117. //
  118. {
  119. if (pmstkRoot != NULL) {
  120. #ifdef DEBUG
  121. SBRCorrupt("Module stack not empty at EOF");
  122. #else
  123. SBRCorrupt("");
  124. #endif
  125. }
  126. if (pbstkRoot != NULL) {
  127. #ifdef DEBUG
  128. SBRCorrupt("Block stack not empty at EOF");
  129. #else
  130. SBRCorrupt("");
  131. #endif
  132. }
  133. }
  134. BOOL
  135. FInExcList (LSZ lszName)
  136. // Is the module name in the exclude file list?
  137. //
  138. {
  139. EXCLINK FAR * px;
  140. LSZ lszAbs;
  141. if (OptEs && !fFirstMod) {
  142. if (lszName[0] == '\0') return FALSE;
  143. if (lszName[0] == '/' || lszName[0] == '\\') return TRUE;
  144. if (lszName[1] == ':' && lszName[2] == '/') return TRUE;
  145. if (lszName[1] == ':' && lszName[2] == '\\') return TRUE;
  146. }
  147. px = pExcludeFileList;
  148. // this name is relative to the path given in the header file
  149. lszAbs = ToAbsPath(lszName, r_cwd);
  150. while (px) {
  151. if ((FWildMatch (px->pxfname, lszAbs)))
  152. return TRUE;
  153. px = px->xnext;
  154. }
  155. return FALSE;
  156. }
  157. static BOOL
  158. FSkipMacro()
  159. // return TRUE if this record should be skipped given that we are inside
  160. // of a macro definition (i.e cMacroDepth is known to be non-zero)
  161. //
  162. {
  163. if (!OptEm)
  164. return FALSE;
  165. if ((r_rectyp == SBR_REC_BLKBEG) ||
  166. (r_rectyp == SBR_REC_BLKEND) ||
  167. (r_rectyp == SBR_REC_MACROEND))
  168. return FALSE;
  169. return TRUE;
  170. }
  171. VOID
  172. InstallSBR()
  173. // Read the next .sbr file and add all the defs/refs/cals/cbys etc to
  174. // the various lists
  175. //
  176. {
  177. WORD nlen;
  178. VA vaCurSym; // current symbol
  179. VA vaProp; // current property
  180. VA vaOrd; // current property temp
  181. BOOL fSymSet = FALSE; // TRUE if symbol set reference
  182. r_lineno = 0;
  183. fExclMod = FALSE;
  184. fFirstMod = TRUE; // we haven't seen the first MODULE record yet
  185. vaUnknownSym = MbrAddAtom ("<Unknown>", TRUE); // unknown module name
  186. if (vaUnknownMod == vaNil) {
  187. vaUnknownMod = VaAllocGrpCb(grpMod, sizeof(MOD));
  188. vaCurMod = vaUnknownMod;
  189. gMOD(vaCurMod).csyms = 0;
  190. cMOD.vaNameSym = vaUnknownSym;
  191. pMOD(vaCurMod);
  192. gSYM(vaUnknownSym).vaFirstProp = vaCurMod; // store pointer back to MOD
  193. pSYM(vaUnknownSym);
  194. ModCnt++;
  195. }
  196. else
  197. fDupMod = (vaUnknownMod != 0);
  198. vaCurMod = vaUnknownMod;
  199. if (vaRootMod == vaNil)
  200. vaRootMod = vaCurMod;
  201. while (GetSBRRec() != S_EOF) {
  202. #ifdef DEBUG
  203. if (OptD & 1) DecodeSBR ();
  204. #endif
  205. if (cMacroDepth != 0) // skip SYMBOLS in macros if true
  206. if (FSkipMacro ())
  207. continue;
  208. if (fExclMod) {
  209. if ((r_rectyp == SBR_REC_MODULE) ||
  210. (r_rectyp == SBR_REC_SYMDEF) ||
  211. (r_rectyp == SBR_REC_MODEND)) {
  212. ;
  213. }
  214. else
  215. continue;
  216. }
  217. switch(r_rectyp) {
  218. case SBR_REC_MODULE:
  219. PushMstk (); // save state
  220. r_lineno = 0; // reset line no.
  221. fDupMod = FALSE; // go to a known state
  222. fExclMod = FALSE;
  223. if (fExclMod = FInExcList (r_bname)) {
  224. #ifdef DEBUG
  225. if (OptD & 256)
  226. printf (" module excluded = %s\n", r_bname);
  227. #endif
  228. vaCurMod = vaUnknownMod;
  229. }
  230. else if ((vaCurMod = VaSearchModule (r_bname)) != vaNil) {
  231. if (gMOD(vaCurMod).csyms == 0) {
  232. fDupMod = TRUE;
  233. #ifdef DEBUG
  234. if (OptD & 256)
  235. printf (" module redef = %s\n", r_bname);
  236. #endif
  237. }
  238. else {
  239. cMOD.csyms = 0;
  240. pMOD(vaCurMod);
  241. #ifdef DEBUG
  242. if (OptD & 256)
  243. printf (" module subst = %s\n", r_bname);
  244. #endif
  245. }
  246. }
  247. else {
  248. SetVMClient(VM_ADD_MOD);
  249. ModCnt++;
  250. vaCurMod = VaAllocGrpCb(grpMod, sizeof(MOD));
  251. gMOD(vaCurMod);
  252. cMOD.vaFirstModSym = vaNil;
  253. cMOD.csyms = 0;
  254. cMOD.vaNameSym =
  255. MbrAddAtom (ToCanonPath(r_bname, r_cwd, c_cwd), TRUE);
  256. cMOD.vaNextMod = vaRootMod;
  257. pMOD(vaCurMod);
  258. vaRootMod = vaCurMod;
  259. gSYM(cMOD.vaNameSym).vaFirstProp = vaCurMod; // ptr to MOD
  260. pSYM(cMOD.vaNameSym);
  261. SetVMClient(VM_MISC);
  262. }
  263. fFirstMod = FALSE;
  264. break;
  265. case SBR_REC_LINDEF:
  266. break;
  267. case SBR_REC_SYMDEF:
  268. // if module is being excluded then just make the ord and prop entry
  269. // in case it is referred to later.
  270. // REVIEW For FORTRAN if ordinal is already defined
  271. // REVIEW then this is a refined definition -- we
  272. // REVIEW override the old definition with the new
  273. // REVIEW one at this time -Rico
  274. nlen = strlen (r_bname);
  275. if (nlen > MaxSymLen) MaxSymLen = (BYTE)nlen;
  276. vaCurSym = MbrAddAtom (r_bname, FALSE);
  277. vaOrd = VaOrdAdd (); // add sym ord to ord list
  278. gORD(vaOrd).vaOrdProp = VaPropAddToSym(vaCurSym);
  279. pORD(vaOrd);
  280. break;
  281. case SBR_REC_OWNER:
  282. if (!(vaProp = VaOrdFind(r_ordinal))) {
  283. // emit error message in case of forward reference
  284. // try to continue
  285. //
  286. #ifdef DEBUG
  287. if (OptD & 4)
  288. printf ("mbrmake: Owner Forward Reference(%d)\n",
  289. r_ordinal);
  290. #endif
  291. break;
  292. }
  293. vaOwnerProp = vaProp;
  294. break;
  295. case SBR_REC_SYMREFSET:
  296. fSymSet = TRUE;
  297. // fall through
  298. case SBR_REC_SYMREFUSE:
  299. if (!(vaProp = VaOrdFind(r_ordinal))) {
  300. // emit error message in case of forward reference
  301. // try to continue
  302. //
  303. #ifdef DEBUG
  304. if (OptD & 4)
  305. printf ("mbrmake: Forward Reference(%d)\n", r_ordinal);
  306. #endif
  307. break;
  308. }
  309. AddRefProp (vaProp);
  310. break;
  311. case SBR_REC_BLKBEG:
  312. PushBstk(); // save state
  313. break;
  314. case SBR_REC_MACROBEG:
  315. cMacroDepth++;
  316. break;
  317. case SBR_REC_MACROEND:
  318. cMacroDepth--;
  319. break;
  320. case SBR_REC_BLKEND:
  321. PopBstk();
  322. break;
  323. case SBR_REC_MODEND:
  324. PopMstk();
  325. break;
  326. default:
  327. SBRCorrupt ("unknown rec type");
  328. Fatal ();
  329. break;
  330. }
  331. }
  332. CheckStacksEmpty();
  333. }
  334. VOID
  335. AddCalProp(VA vaCurProp)
  336. // Add a symbol reference to the calling procedure's Calls/Uses list.
  337. //
  338. {
  339. CAL cal;
  340. SetVMClient(VM_SEARCH_CAL);
  341. ENM_LIST (gPROP(vaOwnerProp).vaCalList, CAL) // proc call list
  342. if (cCAL.vaCalProp == vaCurProp) {
  343. cCAL.isbr = isbrCur;
  344. cCAL.calcnt++; // multiple calls
  345. ENM_PUT(CAL);
  346. return;
  347. }
  348. ENM_END
  349. cal.isbr = isbrCur;
  350. cal.vaCalProp = vaCurProp; // symbol called or used
  351. cal.calcnt = 1;
  352. SetVMClient(VM_ADD_CAL);
  353. VaAddList(&cPROP.vaCalList, &cal, sizeof(cal), grpCal);
  354. pPROP(vaOwnerProp);
  355. SetVMClient(VM_MISC);
  356. #ifdef DEBUG
  357. if (OptD & 8) {
  358. printf("New CAL for: ");
  359. DebugDumpProp(vaOwnerProp);
  360. }
  361. #endif
  362. }
  363. VOID
  364. AddCbyProp(VA vaCurProp)
  365. // Add a symbol reference to it's property Called/Used by list.
  366. //
  367. {
  368. CBY cby;
  369. SetVMClient(VM_SEARCH_CBY);
  370. ENM_LIST (gPROP(vaCurProp).vaCbyList, CBY) // prop called/used by list
  371. if (cCBY.vaCbyProp == vaOwnerProp) {
  372. cCBY.isbr = isbrCur;
  373. cCBY.cbycnt++;
  374. ENM_PUT(CBY);
  375. return;
  376. }
  377. ENM_END
  378. cby.isbr = isbrCur;
  379. cby.vaCbyProp = vaOwnerProp; // symbol we are called or used by
  380. cby.cbycnt = 1;
  381. SetVMClient(VM_ADD_CBY);
  382. VaAddList(&cPROP.vaCbyList, &cby, sizeof(cby), grpCby);
  383. pPROP(vaCurProp);
  384. SetVMClient(VM_MISC);
  385. #ifdef DEBUG
  386. if (OptD & 8) {
  387. printf("New CBY for: ");
  388. DebugDumpProp(vaCurProp);
  389. }
  390. #endif
  391. }
  392. VOID
  393. AddRefProp(VA vaCurProp)
  394. // Add a symbol reference to it's property reference list.
  395. //
  396. {
  397. VA vaRef, vaFileSym;
  398. SetVMClient(VM_SEARCH_REF);
  399. vaFileSym = gMOD(vaCurMod).vaNameSym;
  400. gPROP(vaCurProp);
  401. if (fDupMod) {
  402. // try looking at the hint for this PROP if there is one, if there
  403. // isn't then we're stuck -- we must search the whole REF list
  404. //
  405. if (vaRef = cPROP.vaHintRef) {
  406. gREF(vaRef);
  407. if (cREF.reflin == r_lineno) {
  408. cREF.isbr = isbrCur;
  409. pREF(vaRef);
  410. SetVMClient(VM_MISC);
  411. return;
  412. }
  413. vaRef = VaFrVp(cREF.vpNextRef);
  414. if (vaRef) {
  415. gREF(vaRef);
  416. if (cREF.reflin == r_lineno) {
  417. cREF.isbr = isbrCur;
  418. pREF(vaRef);
  419. cPROP.vaHintRef = vaRef;
  420. pPROP(vaCurProp);
  421. SetVMClient(VM_MISC);
  422. return;
  423. }
  424. }
  425. }
  426. vaRef = VaFrVp(cPROP.vpFirstRef);
  427. while (vaRef) {
  428. gREF(vaRef);
  429. if ((VaFrVp(cREF.vpFileSym) == vaFileSym) && // ignore multiple
  430. (cREF.reflin == r_lineno)) { // references to same file & line
  431. cREF.isbr = isbrCur;
  432. pREF(vaRef);
  433. cPROP.vaHintRef = vaRef;
  434. pPROP(vaCurProp);
  435. SetVMClient(VM_MISC);
  436. return;
  437. }
  438. vaRef = VaFrVp(cREF.vpNextRef);
  439. }
  440. }
  441. else {
  442. if (vaRef = VaFrVp(cPROP.vpLastRef)) {
  443. gREF(vaRef);
  444. if (cREF.reflin == r_lineno &&
  445. vaFileSym == VaFrVp(cREF.vpFileSym)) {
  446. SetVMClient(VM_MISC);
  447. return;
  448. }
  449. }
  450. }
  451. SetVMClient(VM_ADD_REF);
  452. vaRef = VaAllocGrpCb(grpRef, sizeof(REF));
  453. gREF(vaRef);
  454. cREF.isbr = isbrCur;
  455. cREF.reflin = r_lineno;
  456. MkVpVa(cREF.vpFileSym, vaFileSym);
  457. pREF(vaRef);
  458. gPROP(vaCurProp);
  459. AddTail (Ref, REF);
  460. cPROP.cref++; // count references
  461. cPROP.vaHintRef = vaRef;
  462. pPROP(vaCurProp);
  463. #ifdef DEBUG
  464. if (OptD & 8) {
  465. printf("New REF for: ");
  466. DebugDumpProp(vaCurProp);
  467. }
  468. #endif
  469. SetVMClient(VM_MISC);
  470. if (vaOwnerProp) {
  471. AddCbyProp (vaCurProp); // add to called/used by
  472. AddCalProp (vaCurProp); // add to call/uses
  473. }
  474. }
  475. VOID
  476. AddDefProp(VA vaCurProp)
  477. // Add a symbol definition to it's property definition list.
  478. // -Set vaOwnerProp if symbol is an internal function.
  479. {
  480. DEF def;
  481. VA vaFileSym;
  482. #if 0
  483. // if current symbol is FUNCTION and formally declared
  484. // (block stack not empty), then remember it.
  485. // Subsequent symbols are called by or used by this function.
  486. //
  487. // this is going away when all compilers support SBR_REC_OWNER
  488. if ((r_attrib & SBR_TYPMASK) == SBR_TYP_FUNCTION)
  489. if (pfblkstack != NULL && !(r_attrib & SBR_ATR_DECL_ONLY))
  490. vaOwnerProp = vaCurProp;
  491. #endif
  492. vaFileSym = gMOD(vaCurMod).vaNameSym;
  493. ENM_LIST (gPROP(vaCurProp).vaDefList, DEF) // proc def list
  494. if ((cDEF.vaFileSym == vaFileSym) && // ignore multiple
  495. (cDEF.deflin == r_lineno)) { // references to same file & line
  496. cDEF.isbr = isbrCur;
  497. ENM_PUT(DEF);
  498. SetVMClient(VM_MISC);
  499. return;
  500. }
  501. ENM_END
  502. def.isbr = isbrCur;
  503. def.deflin = r_lineno;
  504. def.vaFileSym = vaFileSym;
  505. SetVMClient(VM_ADD_DEF);
  506. gPROP(vaCurProp);
  507. VaAddList(&cPROP.vaDefList, &def, sizeof(def), grpDef);
  508. pPROP(vaCurProp);
  509. SetVMClient(VM_MISC);
  510. #ifdef DEBUG
  511. if (OptD & 8) {
  512. printf("New DEF for: ");
  513. DebugDumpProp(vaCurProp);
  514. }
  515. #endif
  516. // don't count the definitions of the current proc as uses
  517. if (vaOwnerProp && vaCurProp != vaOwnerProp) {
  518. AddCbyProp (vaCurProp); // add to called/used by
  519. AddCalProp (vaCurProp); // add to call/uses
  520. }
  521. }
  522. VA
  523. VaPropBestOfSym(VA vaSym)
  524. //
  525. // Returns property pointer if:
  526. // 1). symbol is already defined,
  527. // 2). attributes match (except for possibly ATR_DECL_ONLY)
  528. //
  529. // Idea is to recognize the definition of an external.
  530. //
  531. {
  532. VA vaProp;
  533. WORD sattr;
  534. SetVMClient(VM_SEARCH_PROP);
  535. vaProp = gSYM(vaSym).vaFirstProp;
  536. while (vaProp) {
  537. sattr = gPROP(vaProp).sattr;
  538. if ((r_attrib & (~SBR_ATR_DECL_ONLY))
  539. == (sattr & (~SBR_ATR_DECL_ONLY))) {
  540. SetVMClient(VM_MISC);
  541. return (vaProp);
  542. }
  543. vaProp = cPROP.vaNextProp;
  544. }
  545. SetVMClient(VM_MISC);
  546. return vaNil;
  547. }
  548. VA
  549. VaPropAddToSym(VA vaCurSym)
  550. // Add a property node for the given symbol.
  551. //
  552. {
  553. char fDupProp = FALSE;
  554. VA vaCurProp;
  555. if (vaCurProp = VaPropBestOfSym (vaCurSym)) {
  556. if ( (cPROP.sattr & SBR_ATR_DECL_ONLY) &&
  557. !(r_attrib & SBR_ATR_DECL_ONLY)) {
  558. cPROP.sattr = r_attrib;
  559. pPROP(vaCurProp);
  560. }
  561. fDupProp = TRUE;
  562. }
  563. else {
  564. SetVMClient(VM_ADD_PROP);
  565. vaCurProp = VaAllocGrpCb(grpProp, sizeof(PROP));
  566. gPROP(vaCurProp);
  567. cPROP.vaNameSym = vaCurSym;
  568. cPROP.sattr = r_attrib;
  569. if (gSYM(vaCurSym).vaFirstProp)
  570. cPROP.vaNextProp = cSYM.vaFirstProp;
  571. pPROP(vaCurProp);
  572. cSYM.vaFirstProp = vaCurProp;
  573. cSYM.cprop++;
  574. pSYM(vaCurSym);
  575. SetVMClient(VM_MISC);
  576. }
  577. if (!fExclMod) {
  578. if (r_attrib & SBR_ATR_DECL_ONLY)
  579. AddRefProp (vaCurProp); // treat extern as ref
  580. else
  581. AddDefProp (vaCurProp); // define others
  582. }
  583. return (vaCurProp);
  584. }
  585. VOID
  586. BldModSymList ()
  587. // Build each module's symbol list
  588. //
  589. {
  590. WORD i;
  591. VA vaMod, vaModSym, vaSym, vaProp;
  592. SetVMClient(VM_BUILD_MODSYM);
  593. // zero out module symbol counts
  594. vaMod = vaRootMod;
  595. while (vaMod) {
  596. gMOD(vaMod);
  597. cMOD.csyms = 0;
  598. pMOD(vaMod);
  599. vaMod = cMOD.vaNextMod;
  600. }
  601. for (i=0; i < cSymbolsMac; i++) {
  602. vaSym = rgvaSymSorted[i];
  603. if (!vaSym) continue;
  604. vaProp = gSYM(vaSym).vaFirstProp;
  605. while (vaProp) {
  606. ENM_LIST(gPROP(vaProp).vaDefList, DEF)
  607. vaMod = vaRootMod; // look at defs for each mod */
  608. while (vaMod) {
  609. if (cDEF.vaFileSym == gMOD(vaMod).vaNameSym) {
  610. if (cMOD.vaLastModSym &&
  611. gMODSYM(cMOD.vaLastModSym).vaFirstProp == vaProp)
  612. goto break2; // duplicate
  613. // belongs to this mod
  614. cMOD.csyms++;
  615. vaModSym = VaAllocGrpCb(grpModSym, sizeof(MODSYM));
  616. gMODSYM(vaModSym);
  617. cMODSYM.vaFirstProp = vaProp;
  618. cMODSYM.vaNextModSym = 0;
  619. pMODSYM(vaModSym);
  620. if (!cMOD.vaFirstModSym)
  621. cMOD.vaFirstModSym = cMOD.vaLastModSym = vaModSym;
  622. else {
  623. gMODSYM(cMOD.vaLastModSym).vaNextModSym = vaModSym;
  624. pMODSYM(cMOD.vaLastModSym);
  625. cMOD.vaLastModSym = vaModSym;
  626. }
  627. pMOD(vaMod);
  628. break;
  629. }
  630. vaMod = cMOD.vaNextMod;
  631. }
  632. break2: ; // duplicate Modsyms will cause goto here
  633. ENM_END
  634. vaProp = cPROP.vaNextProp;
  635. }
  636. }
  637. SetVMClient(VM_MISC);
  638. }
  639. VOID
  640. CleanUp()
  641. // 1. Remove symbols that have no references.
  642. // 2. Remove symbols that have only references
  643. // 3. Connect used symbols with no definition to <Unknown>
  644. //
  645. {
  646. WORD i;
  647. VA vaSym, vaProp, vaPropNext, vaPropPrev = vaNil;
  648. DEF def;
  649. BOOL fDelete;
  650. #define FExternAttr(attr) (!!(attr & SBR_ATR_DECL_ONLY))
  651. #define FFunctionAttr(attr) ((attr & SBR_TYPMASK) == SBR_TYP_FUNCTION)
  652. def.vaFileSym = vaUnknownSym;
  653. def.deflin = 0;
  654. def.isbr = 0xffff;
  655. SetVMClient(VM_CLEAN_REFS);
  656. for (i=0; i < cSymbolsMac; i++) {
  657. vaSym = rgvaSymSorted[i];
  658. vaPropPrev = vaNil;
  659. vaProp = gSYM(vaSym).vaFirstProp;
  660. while (vaProp) {
  661. vaPropNext = gPROP(vaProp).vaNextProp;
  662. fDelete = FALSE;
  663. // figure out what to delete here
  664. // if the symbol is used by anyone or uses anyone we must keep it
  665. // regardless of all other considerations
  666. //
  667. if (((!cPROP.vaCalList) && (!cPROP.vaCbyList)) && (
  668. // at this point we know there are only refs & defs
  669. // if it is totally unreferenced & undefined it can go
  670. (cPROP.cref == 0 && (!cPROP.vaDefList))
  671. ||
  672. // if we're allowed to remove "useless" symbols then we try
  673. ((!OptIu) &&
  674. // if there are only prototypes we can delete it
  675. (((!cPROP.vaDefList) && FExternAttr(cPROP.sattr))
  676. ||
  677. // or if it is unreferenced and is not a function
  678. (cPROP.cref == 0 && (!FFunctionAttr(cPROP.sattr))))))) {
  679. fDelete = TRUE; // nuke it
  680. }
  681. else if (!cPROP.vaDefList) {
  682. // if we couldn't get rid of the thing, and there are no
  683. // definitions for it then we must make a fake definition
  684. // in the <Unknown> file. This will happen (in particular)
  685. // for library functions that are called by someone
  686. //
  687. // library functions that are not called would fall under
  688. // the case of a symbol with only prototypes above
  689. VaAddList(&cPROP.vaDefList, &def, sizeof(def), grpDef);
  690. pPROP(vaProp);
  691. #ifdef DEBUG
  692. if (OptD & 32)
  693. printf ("PROP unknown: %s\n", GetAtomStr (vaSym));
  694. #endif
  695. }
  696. if (fDelete) {
  697. #ifdef DEBUG
  698. if (OptD & 32)
  699. printf ("PROP deleted: %s\n", GetAtomStr (vaSym));
  700. #endif
  701. cSYM.cprop--;
  702. if (vaPropPrev == vaNil) {
  703. cSYM.vaFirstProp = vaPropNext;
  704. }
  705. else {
  706. gPROP(vaPropPrev);
  707. cPROP.vaNextProp = vaPropNext;
  708. pPROP(vaPropPrev);
  709. }
  710. pSYM(vaSym);
  711. }
  712. else
  713. vaPropPrev = vaProp; // prev = current
  714. vaProp = vaPropNext;
  715. }
  716. if (!cSYM.cprop) {
  717. #ifdef DEBUG
  718. if (OptD & 32)
  719. printf ("SYM deleted: %s\n", GetAtomStr (vaSym));
  720. #endif
  721. rgvaSymSorted[i] = vaNil;
  722. }
  723. }
  724. SetVMClient(VM_MISC);
  725. }
  726. BOOL
  727. FWildMatch(char *pchPat, char *pchText)
  728. // return TRUE if pchText matchs pchPat in the dos wildcard sense
  729. //
  730. // REVIEW FWildMatch for 1.2 file name support
  731. //
  732. {
  733. char chText, chPat;
  734. for (;;) {
  735. switch (*pchPat) {
  736. case '\0':
  737. return *pchText == '\0';
  738. case '/':
  739. case '\\':
  740. if (*pchText != '/' && *pchText != '\\')
  741. return FALSE;
  742. pchText++;
  743. pchPat++;
  744. break;
  745. case '.':
  746. pchPat++;
  747. switch (*pchText) {
  748. case '.':
  749. pchText++;
  750. break;
  751. case '\0': case '/': case '\\':
  752. break;
  753. default:
  754. return FALSE;
  755. }
  756. break;
  757. case '*':
  758. pchText += strcspn(pchText, ":./\\");
  759. pchPat += strcspn(pchPat, ":./\\");
  760. break;
  761. case '?':
  762. pchPat++;
  763. switch (*pchText) {
  764. case '\0': case '.': case '/': case '\\':
  765. break;
  766. default:
  767. pchText++;
  768. break;
  769. }
  770. break;
  771. default:
  772. chText = *pchText;
  773. chPat = *pchPat;
  774. if (islower(chText)) chText = (char)toupper(chText);
  775. if (islower(chPat)) chPat = (char)toupper(chPat);
  776. if (chText != chPat)
  777. return FALSE;
  778. pchPat++;
  779. pchText++;
  780. break;
  781. }
  782. }
  783. }