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.

2497 lines
93 KiB

  1. /*
  2. * Copyright Microsoft Corporation, 1983-1989
  3. *
  4. * This Module contains Proprietary Information of Microsoft
  5. * Corporation and should be treated as Confidential.
  6. */
  7. /****************************************************************
  8. * *
  9. * NEWTP1.C *
  10. * *
  11. * Pass 1 object module processing routines. *
  12. * *
  13. ****************************************************************/
  14. #include <minlit.h> /* Basic types and constants */
  15. #include <bndtrn.h> /* More types and constants */
  16. #include <bndrel.h> /* Relocation record definitions */
  17. #include <lnkio.h> /* Linker I/O definitions */
  18. #include <newexe.h> /* DOS & 286 .EXE data structures */
  19. #if EXE386
  20. #include <exe386.h> /* 386 .EXE data structures */
  21. #endif
  22. #include <lnkmsg.h> /* Error messages */
  23. #if OXOUT OR OIAPX286
  24. #include <xenfmt.h> /* Xenix format definitions */
  25. #endif
  26. #include <extern.h> /* External declarations */
  27. #include <undname.h>
  28. #if OVERLAYS
  29. WORD iovFile; /* Overlay number of input file */
  30. #endif
  31. LOCAL FTYPE fP2Start; /* Start of Pass 2 records */
  32. LOCAL FTYPE fModEnd; /* MODEND seen */
  33. LOCAL WORD cSegCode; /* Number of code seg's in module */
  34. #if O68K
  35. #define F68KCODE(ch) ((ch) >= 'A' && (ch) <= 'E')
  36. #endif /* O68K */
  37. /*
  38. * LOCAL FUNCTION PROTOTYPES
  39. */
  40. LOCAL void NEAR TypErr(MSGTYPE msg,unsigned char *sb);
  41. LOCAL void NEAR DoCommon(APROPUNDEFPTR apropUndef,
  42. long length,
  43. unsigned short cbEl,
  44. unsigned char *sb);
  45. LOCAL void NEAR SegUnreliable(APROPSNPTR apropSn);
  46. LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes);
  47. LOCAL void NEAR SegRc1(void);
  48. LOCAL void NEAR TypRc1(void);
  49. LOCAL void NEAR ComDf1(void);
  50. LOCAL void NEAR GrpRc1(void);
  51. LOCAL void NEAR PubRc1(void);
  52. LOCAL void NEAR ExtRc1(void);
  53. LOCAL void NEAR imprc1(void);
  54. LOCAL void NEAR exprc1(void);
  55. LOCAL void NEAR ComRc1(void);
  56. LOCAL void NEAR EndRc1(void);
  57. extern void NEAR FixRc1(void);
  58. LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes)
  59. {
  60. // Redefinition of default resolution.
  61. // Warn the user.
  62. SBTYPE oldDefault;
  63. SBTYPE newDefault;
  64. APROPUNDEFPTR undef;
  65. AHTEPTR rhte;
  66. undef = (APROPUNDEFPTR ) FetchSym(oldDefRes, FALSE);
  67. while (undef->au_attr != ATTRNIL)
  68. {
  69. rhte = (AHTEPTR) undef->au_next;
  70. /* Try next entry in list */
  71. undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
  72. /* Fetch it from VM */
  73. }
  74. strcpy(oldDefault, GetFarSb(rhte->cch));
  75. undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextDefRes], FALSE);
  76. while (undef->au_attr != ATTRNIL)
  77. {
  78. rhte = (AHTEPTR) undef->au_next;
  79. /* Try next entry in list */
  80. undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
  81. /* Fetch it from VM */
  82. }
  83. strcpy(newDefault, GetFarSb(rhte->cch));
  84. undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], FALSE);
  85. while (undef->au_attr != ATTRNIL)
  86. {
  87. rhte = (AHTEPTR) undef->au_next;
  88. /* Try next entry in list */
  89. undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
  90. /* Fetch it from VM */
  91. }
  92. OutWarn(ER_weakredef, 1 + GetFarSb(rhte->cch), &oldDefault[1], &newDefault[1]);
  93. }
  94. /*** IsDebSeg - check is segment is one of the special debug segments
  95. *
  96. * Purpose:
  97. * Check if segment name and class name match reserved debugger
  98. * segment names.
  99. *
  100. * Input:
  101. * - rhteClass - pointer to class name
  102. * - rhteSeg - pointer to segment name
  103. *
  104. * Output:
  105. * If this is a debug segment function returns 1 for $$TYPES, and 2
  106. * for $$SYMBOLS. For non-debug segments it returns FALSE.
  107. *
  108. * Exceptions:
  109. * None.
  110. *
  111. * Notes:
  112. * None.
  113. *
  114. *************************************************************************/
  115. WORD NEAR IsDebSeg(RBTYPE rhteClass, RBTYPE rhteSeg)
  116. {
  117. if (rhteClass == rhteDebTyp)
  118. return ((rhteSeg == rhteTypes || rhteSeg == rhte0Types) ? 1 : FALSE);
  119. else if (rhteClass == rhteDebSym)
  120. return ((rhteSeg == rhteSymbols || rhteSeg == rhte0Symbols) ? 2 : FALSE);
  121. else
  122. return(FALSE);
  123. }
  124. /****************************************************************
  125. * *
  126. * ModRc1: *
  127. * *
  128. * This function reads the name from a THEADR record and makes *
  129. * an entry containing the name in the hash table. *
  130. * See p. 26 in "8086 Object Module Formats EPS." *
  131. * *
  132. ****************************************************************/
  133. void NEAR ModRc1(void)
  134. {
  135. APROPFILEPTR apropFile;
  136. sbModule[0] = (BYTE) Gets(); /* Read in the length byte */
  137. GetBytes(&sbModule[1],B2W(sbModule[0]));
  138. /* Read in the name */
  139. PropSymLookup(sbModule, ATTRNIL, TRUE);
  140. /* Make entry in hash table */
  141. apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,TRUE);
  142. /* Allocate space in virt mem */
  143. // The name of a module is given by the very first THEADR record
  144. if(apropFile->af_rMod == 0)
  145. apropFile->af_rMod = vrhte; /* Load pointer into hash table */
  146. #if FDEBUG
  147. if(fDebug) /* If runtime debugging on */
  148. {
  149. OutFileCur(stderr); /* Write current file and module */
  150. NEWLINE(stderr);
  151. }
  152. #endif
  153. }
  154. long NEAR TypLen() /* Get type length */
  155. {
  156. WORD b; /* Byte value */
  157. long l; /* Size */
  158. if(cbRec < 2) InvalidObject(); /* Make sure record long enough */
  159. b = Gets(); /* Get length byte */
  160. if(b < 128) return(B2L(b)); /* One byte length field */
  161. if(b == 129) /* If two byte length */
  162. {
  163. if(cbRec < 3) InvalidObject(); /* Make sure record long enough */
  164. return((long) WGets()); /* Return the length */
  165. }
  166. if(b == 132) /* If three byte length */
  167. {
  168. if(cbRec < 4) InvalidObject(); /* Make sure record long enough */
  169. l = (long) WGets(); /* Get the low word */
  170. return(l + ((long) Gets() << WORDLN));
  171. /* Return the length */
  172. }
  173. if(b == 136) /* If four byte length */
  174. {
  175. if(cbRec < 5) InvalidObject(); /* Make sure record long enough */
  176. l = (long) WGets(); /* Get the low word */
  177. return(l + ((long) WGets() << WORDLN));
  178. /* Return the length */
  179. }
  180. InvalidObject(); /* Bad length specification */
  181. }
  182. /****************************************************************
  183. * *
  184. * TypRc1: *
  185. * *
  186. * This function processes TYPDEF records. These records are *
  187. * difficult to understand. They are (poorly) described on *
  188. * pp. 40-43 of "8086 Object Module Formats EPS," with some *
  189. * additional information on pp. 89-90. *
  190. * Microsoft used to used them for communal variables but they *
  191. * have been superseded by COMDEF records. *
  192. * *
  193. ****************************************************************/
  194. LOCAL void NEAR TypRc1(void)
  195. {
  196. long l;
  197. WORD b;
  198. WORD typ; /* Near or FAR */
  199. WORD ityp; /* Type index */
  200. if(typMac >= TYPMAX)
  201. Fatal(ER_typdef);
  202. SkipBytes(Gets()); /* Skip the name field */
  203. Gets(); /* Skip the EN byte */
  204. l = -1L; /* Initialize */
  205. mpityptyp[typMac] = 0; /* Assume no element type */
  206. if(cbRec > 3) /* If at least four bytes left */
  207. {
  208. typ = Gets(); /* Get type leaf */
  209. b = Gets(); /* Get next leaf */
  210. if(typ == TYPENEAR) /* If near variable */
  211. {
  212. if(b != 0x7B && b != 0x79 && b != 0x77) InvalidObject();
  213. /* Scalar, structure, or array */
  214. fCommon = (FTYPE) TRUE; /* We have communal variables */
  215. l = (TypLen() + 7) >> 3; /* Round length to nearest byte */
  216. }
  217. else if(typ == TYPEFAR) /* Else if FAR variable */
  218. {
  219. if(b != 0x77) InvalidObject();
  220. /* Must have an array */
  221. fCommon = (FTYPE) TRUE; /* We have communal variables */
  222. l = TypLen(); /* Get number of elements */
  223. ityp = GetIndex(1, (WORD) (typMac - 1));
  224. /* Get type index */
  225. if(mpityptyp[ityp] || mpitypelen[ityp] == -1L) InvalidObject();
  226. /* Must index valid TYPDEF */
  227. mpityptyp[typMac] = ityp; /* Save type index */
  228. /* If element length too big, treat as TYPENEAR */
  229. if(mpitypelen[ityp] > CBELMAX)
  230. {
  231. l *= mpitypelen[ityp];
  232. mpitypelen[ityp] = 0;
  233. }
  234. }
  235. }
  236. mpitypelen[typMac++] = l; /* Store length */
  237. SkipBytes((WORD) (cbRec - 1)); /* Skip all but the checksum */
  238. }
  239. LOCAL void NEAR TypErr(msg,sb) /* Type error message routine */
  240. MSGTYPE msg; /* Message */
  241. BYTE *sb; /* Symbol to which error refers */
  242. {
  243. sb[B2W(sb[0]) + 1] = '\0'; /* Null-terminate */
  244. OutError(msg,1 + sb);
  245. }
  246. /*
  247. * DoCommon
  248. *
  249. * Resolves old and new communal definitions of the same symbol.
  250. * Does work for both ComDf1() and ExtRc1().
  251. */
  252. LOCAL void NEAR DoCommon (apropUndef, length, cbEl, sb)
  253. APROPUNDEFPTR apropUndef; /* Ptr to property cell */
  254. long length; /* Length or number of elements */
  255. WORD cbEl; /* # bytes per array element */
  256. BYTE *sb; /* Name of symbol */
  257. {
  258. if(apropUndef->au_len == -1L) /* If not previously a communal */
  259. {
  260. apropUndef->au_cbEl = cbEl; /* Set the element size */
  261. MARKVP(); /* Page has changed */
  262. }
  263. else if (cbEl == 0 && apropUndef->au_cbEl != 0)
  264. { /* Else if near reference to FAR */
  265. apropUndef->au_len *= apropUndef->au_cbEl;
  266. /* Calculate FAR variable length */
  267. apropUndef->au_cbEl = 0; /* Force DS-type to near */
  268. MARKVP(); /* Page has changed */
  269. if (apropUndef->au_len > LXIVK) /* If huge variable */
  270. {
  271. TypErr(ER_nearhuge,sb); /* Issue error message */
  272. return; /* Skip this symbol */
  273. }
  274. }
  275. else if (cbEl != 0 && apropUndef->au_cbEl == 0)
  276. { /* Else if FAR reference to near */
  277. length *= cbEl; /* Calculate FAR variable length */
  278. cbEl = 0; /* Force DS-type to near */
  279. if (length > LXIVK) /* If huge variable */
  280. {
  281. TypErr(ER_nearhuge,sb); /* Issue error message */
  282. return; /* Skip this symbol */
  283. }
  284. }
  285. else if (cbEl != apropUndef->au_cbEl)
  286. { /* If array element sizes don't match */
  287. TypErr(ER_arrmis,sb);
  288. return; /* Skip this symbol */
  289. }
  290. if (apropUndef->au_len < length)
  291. { /* If new length is larger */
  292. apropUndef->au_len = length; /* Save it */
  293. MARKVP();
  294. }
  295. }
  296. /*
  297. * ComDf1
  298. *
  299. * This function processes COMDEF records on pass 1.
  300. */
  301. LOCAL void NEAR ComDf1 (void)
  302. {
  303. int tmp; /* workaround a cl bug */
  304. SBTYPE sb; /* COMDEF symbol */
  305. REGISTER APROPUNDEFPTR
  306. apropUndef; /* Pointer to symbol entry */
  307. long length; /* Communal variable length */
  308. long cbEl; /* Size of array element */
  309. WORD itype; /* Type index */
  310. while(cbRec > 1) /* While there are symbols left */
  311. {
  312. if(extMac >= EXTMAX - 1) /* Check for table overflow */
  313. Fatal(ER_extdef);
  314. sb[0] = (BYTE) Gets(); /* Get symbol length */
  315. if(rect == COMDEF)
  316. GetBytes(&sb[1],B2W(sb[0]));/* Read in text of symbol */
  317. else
  318. GetLocName(sb); /* Transform local name */
  319. #if CMDXENIX
  320. if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen;
  321. /* Truncate if necessary */
  322. #endif
  323. itype = GetIndex(0,0x7FFF); /* Get type index */
  324. tmp = Gets();
  325. switch(tmp) /* Get data seg type */
  326. {
  327. case TYPENEAR:
  328. length = TypLen(); /* Get length */
  329. cbEl = 0;
  330. break;
  331. case TYPEFAR:
  332. length = TypLen(); /* Get number of elements */
  333. /* Get element length. If too big, treat as near. Cmerge
  334. * will never generate cbEl > 64K so this is not a problem.
  335. */
  336. if((cbEl = TypLen()) > CBELMAX)
  337. {
  338. length *= cbEl;
  339. cbEl = 0;
  340. }
  341. break;
  342. default:
  343. InvalidObject(); /* Unrecognized DS type */
  344. }
  345. #if FALSE
  346. if(fDebug)
  347. {
  348. sb[sb[0]+1] = '\0';
  349. fprintf(stdout, "%s has index = %u\r\n", sb+1, extMac);
  350. }
  351. #endif
  352. apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE);
  353. /* Look for a matching PUBDEF */
  354. if(apropUndef == PROPNIL) /* If there isn't one */
  355. {
  356. /* Insert as undefined symbol */
  357. if (vrhte == RHTENIL)
  358. apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE);
  359. else
  360. apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
  361. mpextprop[extMac++] = vrprop;
  362. fCommon = (FTYPE) TRUE; /* There are communals */
  363. if (vfCreated)
  364. apropUndef->au_flags |= UNDECIDED;
  365. else if (apropUndef->au_flags & UNDECIDED)
  366. {
  367. apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE);
  368. apropUndef->au_flags |= STRONGEXT;
  369. }
  370. else if (apropUndef->au_flags & WEAKEXT)
  371. apropUndef->au_flags |= UNDECIDED;
  372. if (vfCreated || !(apropUndef->au_flags & COMMUNAL))
  373. { /* If not previously defined */
  374. apropUndef->au_flags |= COMMUNAL;
  375. /* Mark as communal */
  376. apropUndef->au_len = -1L;
  377. #if ILINK
  378. apropUndef->u.au_module = imodFile;
  379. /* Save module index. */
  380. #endif
  381. DoCommon(apropUndef, length, (WORD) cbEl, sb);
  382. #if SYMDEB
  383. if (fSymdeb && (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~'))
  384. {
  385. #if O68K
  386. /* REVIEW: This should not be under the O68K flag. */
  387. apropUndef->au_CVtype = itype;
  388. #endif /* O68K */
  389. DebPublic(mpextprop[extMac-1], rect);
  390. }
  391. #endif
  392. }
  393. else
  394. DoCommon(apropUndef, length, (WORD) cbEl, sb);
  395. }
  396. else
  397. {
  398. mpextprop[extMac++] = vrprop;
  399. if (mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn])
  400. /* Communal matches code PUBDEF */
  401. DupErr(sb); /* Duplicate definition */
  402. }
  403. }
  404. }
  405. /****************************************************************
  406. * *
  407. * LNmRc1: *
  408. * *
  409. * This function reads LNAME records and stores the names in *
  410. * the hash table. The function does not return a meaningful *
  411. * value. *
  412. * See p. 31 in "8086 Object Module Formats EPS." *
  413. * *
  414. ****************************************************************/
  415. void NEAR LNmRc1(WORD fLocal)
  416. {
  417. SBTYPE lname; /* Buffer for lnames */
  418. RBTYPE FAR *lnameTab;
  419. #if NOT ALIGN_REC
  420. FILE *f;
  421. #endif
  422. WORD cb;
  423. while(cbRec > 1) /* While not at end of record */
  424. {
  425. if (lnameMac >= lnameMax)
  426. {
  427. if (lnameMax >= (LXIVK >> 2))
  428. Fatal(ER_nammax);
  429. lnameTab = (RBTYPE FAR *) FREALLOC(mplnamerhte, 2*lnameMax*sizeof(RBTYPE));
  430. if (lnameTab == NULL)
  431. Fatal(ER_nammax);
  432. mplnamerhte = lnameTab;
  433. lnameMax <<= 1;
  434. }
  435. #if ALIGN_REC
  436. if (!fLocal)
  437. {
  438. cb = 1 + *pbRec;
  439. PropSymLookup(pbRec, ATTRNIL, TRUE);
  440. cbRec -= cb;
  441. pbRec += cb;
  442. }
  443. else
  444. {
  445. lname[0] = (BYTE)Gets(); /* Get name length */
  446. GetLocName(lname); /* Read in text of name */
  447. PropSymLookup(lname, ATTRNIL, TRUE);
  448. }
  449. #else
  450. f = bsInput;
  451. if (!fLocal && f->_cnt && (WORD)f->_cnt > (cb = 1 + *(BYTE *)f->_ptr))
  452. {
  453. PropSymLookup((BYTE *)f->_ptr, ATTRNIL, TRUE);
  454. f->_cnt -= cb;
  455. f->_ptr += cb;
  456. cbRec -= cb;
  457. }
  458. else
  459. {
  460. lname[0] = (BYTE) Gets(); /* Get name length */
  461. DEBUGVALUE(B2W(lname[0])); /* Length of name */
  462. if (lname[0] > SBLEN - 1)
  463. Fatal(ER_badobj);
  464. if (fLocal)
  465. GetLocName(lname);
  466. else
  467. GetBytes(&lname[1],B2W(lname[0]));
  468. /* Read in text of name */
  469. DEBUGSB(lname); /* The name itself */
  470. PropSymLookup(lname, ATTRNIL, TRUE);
  471. }
  472. #endif
  473. /* Insert symbol in hash table */
  474. mplnamerhte[lnameMac++] = vrhte;/* Save address of hash table entry */
  475. }
  476. }
  477. /*
  478. * GetPropName - get the name of a property cell.
  479. *
  480. * Return pointer to the result, stored in a static buffer.
  481. * Alternate between two buffers so we can be used in multi-part
  482. * messages.
  483. * Terminate result with null byte.
  484. */
  485. typedef BYTE SBTYPE1[SBLEN+1];/* 1 extra for null byte */
  486. BYTE * NEAR GetPropName(ahte)
  487. AHTEPTR ahte;
  488. {
  489. static SBTYPE1 msgbuf[2];
  490. static int toggle = 0;
  491. char *p;
  492. while(ahte->attr != ATTRNIL)
  493. ahte = (AHTEPTR ) FetchSym(ahte->rhteNext,FALSE);
  494. p = msgbuf[toggle ^= 1];
  495. /* Copy string to buffer */
  496. FMEMCPY((char FAR *) p, ahte->cch, B2W(ahte->cch[0]) + 1);
  497. p[1 + B2W(p[0])] = '\0'; /* Null-terminate */
  498. return(p);
  499. }
  500. /*
  501. * SegUnreliable - warning message for 286 bug
  502. */
  503. LOCAL void NEAR SegUnreliable (apropSn)
  504. APROPSNPTR apropSn;
  505. {
  506. static FTYPE fReported = FALSE;
  507. MARKVP(); /* Take care of current vp */
  508. if (!fReported)
  509. {
  510. OutWarn(ER_segunsf,1 + GetPropName(apropSn));
  511. fReported = (FTYPE) TRUE;
  512. }
  513. }
  514. /*** CheckClass - check segment's class name
  515. *
  516. * Purpose:
  517. * Check if we have the segment with the same name but with different
  518. * class name.
  519. *
  520. * Input:
  521. * apropSn - real pointer to segment symbol table descriptor
  522. * rhteClass - hash vector entry for class name
  523. *
  524. * Output:
  525. * Returns real pointer to segment symbol table descriptor.
  526. *
  527. * Exceptions:
  528. * Found same segment with different class name - display error.
  529. *
  530. * Notes:
  531. * None.
  532. *
  533. *************************************************************************/
  534. APROPSNPTR CheckClass(APROPSNPTR apropSn, RBTYPE rhteClass)
  535. {
  536. #if ILINK
  537. FTYPE fDifClass = FALSE;
  538. #endif
  539. while(apropSn->as_attr != ATTRNIL)
  540. { /* Look for class match or list end */
  541. if(apropSn->as_attr == ATTRPSN &&
  542. apropSn->as_rCla == rhteClass) break;
  543. /* Break if pub. with matching class */
  544. apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE);
  545. /* Advance down the list */
  546. #if ILINK
  547. fDifClass = (FTYPE) TRUE; /* Same seg exists with dif. class */
  548. #endif
  549. }
  550. #if ILINK
  551. if(fIncremental && fDifClass)
  552. OutError(ER_difcls, 1 + GetPropName(apropSn));
  553. #endif
  554. if(apropSn->as_attr == ATTRNIL)
  555. { /* If attribute not public */
  556. vfCreated = (FTYPE) TRUE; /* New cell */
  557. apropSn = (APROPSNPTR ) PropAdd(vrhte, ATTRPSN);
  558. /* Segment is public */
  559. }
  560. return(apropSn);
  561. }
  562. #if OVERLAYS
  563. void CheckOvl(APROPSNPTR apropSn, WORD iovFile)
  564. {
  565. SNTYPE gsn;
  566. WORD fCanOverlayData;
  567. WORD fOverlaySegment;
  568. if (fOverlays)
  569. {
  570. // First check if mapping tables are allocated.
  571. //
  572. // SNTYPE mposngsn[OSNMAX];
  573. // SNTYPE htgsnosn[OSNMAX];
  574. if (mposngsn == NULL && htgsnosn == NULL)
  575. {
  576. mposngsn = (SNTYPE FAR *) GetMem(2*OSNMAX*sizeof(SNTYPE));
  577. htgsnosn = (SNTYPE FAR *) &mposngsn[OSNMAX];
  578. }
  579. fCanOverlayData = IsDataFlg(apropSn->as_flags) &&
  580. apropSn->as_ggr != ggrDGroup &&
  581. apropSn->as_fExtra & FROM_DEF_FILE &&
  582. apropSn->as_iov != (IOVTYPE) NOTIOVL;
  583. fOverlaySegment = IsCodeFlg(apropSn->as_flags) || fCanOverlayData;
  584. if (fOverlaySegment)
  585. {
  586. // We allow DATA segment overlaying ONLY if they ar NOT a members
  587. // of DGROUP and HAVE preassigned overlay number form .DEF file.
  588. // If segment is to be overlaid - check overlay number assigments
  589. if ((apropSn->as_iov != (IOVTYPE) NOTIOVL) && (iovFile != apropSn->as_iov))
  590. {
  591. if (apropSn->as_fExtra & FROM_DEF_FILE)
  592. {
  593. // Use .DEF file overlay assigment
  594. iovFile = apropSn->as_iov;
  595. }
  596. else
  597. {
  598. // Use current .OBJ file overlay assigment
  599. OutWarn(ER_badsegovl, 1 + GetPropName(apropSn), apropSn->as_iov, iovFile);
  600. }
  601. }
  602. }
  603. if (iovFile != IOVROOT && fOverlaySegment)
  604. {
  605. if (osnMac < OSNMAX)
  606. {
  607. gsn = (SNTYPE)(apropSn->as_gsn & ((LG2OSN << 1) - 1));
  608. // Get initial hash index
  609. while (htgsnosn[gsn] != SNNIL)
  610. { // While buckets are full
  611. if ((gsn += HTDELTA) >= OSNMAX)
  612. gsn -= OSNMAX; // Calculate next hash index
  613. }
  614. htgsnosn[gsn] = osnMac; // Save overlay segment number
  615. mposngsn[osnMac++] = apropSn->as_gsn;
  616. // Map osn to gsn
  617. apropSn->as_iov = iovFile; // Save overlay number
  618. }
  619. else
  620. {
  621. if (osnMac++ == OSNMAX)
  622. OutWarn(ER_osnmax, OSNMAX);
  623. apropSn->as_iov = IOVROOT;
  624. }
  625. }
  626. else
  627. apropSn->as_iov = IOVROOT; // Not an overlay
  628. }
  629. else
  630. apropSn->as_iov = IOVROOT;
  631. }
  632. #endif
  633. /****************************************************************
  634. * *
  635. * SegRc1: *
  636. * *
  637. * This function processes SEGDEF records. *
  638. * See pp. 32-35 in "8086 Object Module Formats EPS." *
  639. * *
  640. ****************************************************************/
  641. LOCAL void NEAR SegRc1(void)
  642. {
  643. WORD tysn; /* ACBP byte */
  644. LNAMETYPE lname; /* Index into mplnamerhte */
  645. APROPSNPTR apropSn; /* Pointer to seg. record */
  646. SNTYPE gsn; /* Global SEGDEF number */
  647. WORD align; /* This contributuion alignment */
  648. WORD prevAlign; /* Logical segment aligment so FAR */
  649. WORD comb; /* Segment combine-type */
  650. DWORD seglen; /* Segment length */
  651. DWORD contriblen; /* Contribution length */
  652. DWORD cbMaxPrev; /* Segment length previously */
  653. AHTEPTR ahte; /* Pointer to hash table entry */
  654. SATYPE saAbs; /* Address for absolute seg */
  655. BYTE flags; /* Segment attribute flags */
  656. RBTYPE rhteClass; /* Class hash table address */
  657. #if SYMDEB
  658. APROPFILEPTR apropFile;
  659. CVINFO FAR *pCvInfo; // Pointer to CodeView information
  660. #endif
  661. if(snMac >= SNMAX)
  662. Fatal(ER_segdef);
  663. tysn = Gets(); /* Read in the ACBP byte */
  664. align = (WORD) ((tysn >> 5) & 7); /* Get the alignment field */
  665. ASSERT(align != 6); /* Not supported by this linker */
  666. if(align == ALGNABS) /* If absolute LSEG */
  667. {
  668. saAbs = (SATYPE) WGets(); /* Get the frame number */
  669. Gets(); /* Punt the frame offset */
  670. }
  671. #if OMF386
  672. if(rect & 1) /* If 386 extension */
  673. seglen = LGets();
  674. else
  675. #endif
  676. seglen = (DWORD) WGets(); /* Get segment length */
  677. if(tysn & BIGBIT)
  678. {
  679. #if OMF386
  680. if(rect & 1)
  681. seglen = CBMAXSEG32 + 1; /* Force fatal error below */
  682. else
  683. #endif
  684. seglen = LXIVK; /* Sixty-four K */
  685. }
  686. contriblen = seglen;
  687. lname = (LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1));
  688. /* Get segment name index */
  689. ahte = (AHTEPTR ) FetchSym(mplnamerhte[lname],FALSE);
  690. rhteClass = mplnamerhte[(LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1))];
  691. /* Get class name rhte */
  692. #if SYMDEB
  693. if (IsDebSeg(rhteClass, mplnamerhte[lname]))
  694. { /* If MS debug segment */
  695. mpsngsn[snMac++] = 0;
  696. if (fSymdeb) /* If debugger support on */
  697. {
  698. apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE);
  699. if (apropFile->af_cvInfo == NULL)
  700. apropFile->af_cvInfo = (CVINFO FAR *) GetMem(sizeof(CVINFO));
  701. pCvInfo = apropFile->af_cvInfo;
  702. if (rhteClass == rhteDebTyp)
  703. {
  704. // "DEBTYP"
  705. pCvInfo->cv_cbTyp = (DWORD) seglen;
  706. #ifdef RGMI_IN_PLACE
  707. pCvInfo->cv_typ = NULL; // defer allocation until pass 2 (!)
  708. #else
  709. pCvInfo->cv_typ = GetMem(seglen);
  710. #endif
  711. }
  712. else if (rhteClass == rhteDebSym)
  713. {
  714. // "DEBSYM"
  715. pCvInfo->cv_cbSym = (DWORD) seglen;
  716. #ifdef RGMI_IN_PLACE
  717. pCvInfo->cv_sym = NULL; // defer allocation until pass 2 (!)
  718. #else
  719. pCvInfo->cv_sym = GetMem(seglen);
  720. #endif
  721. }
  722. }
  723. SkipBytes((WORD) (cbRec - 1));
  724. return;
  725. }
  726. #endif
  727. GetIndex(0, (WORD) (lnameMac - 1)); /* Eat overlay name index */
  728. DEBUGVALUE(seglen); /* Debug info */
  729. DEBUGVALUE(lname); /* Debug info */
  730. ahte = (AHTEPTR ) FetchSym(rhteClass,FALSE);
  731. /* Fetch hash table entry from VM */
  732. if(SbSuffix(GetFarSb(ahte->cch),"\004CODE",TRUE))
  733. flags = FCODE;
  734. else
  735. flags = 0;
  736. #if OMF386
  737. /* Remember if 32-bit segment */
  738. if(tysn & CODE386BIT)
  739. {
  740. flags |= FCODE386;
  741. #if EXE386
  742. /* Must set f386 here because newdeb needs to know in pass 1 */
  743. f386 = (FTYPE) TRUE;
  744. #endif
  745. }
  746. #endif
  747. #if ILINK
  748. else
  749. if (fIncremental && !fLibraryFile && seglen && seglen != LXIVK)
  750. {
  751. /* Add padding to non-zero-length, non-library, non-64K segment
  752. * contributions. (64K from huge model)
  753. * UNDONE: More general overflow check, accounting for previous
  754. * UNDONE: contributions.
  755. */
  756. seglen += (flags & FCODE) ? cbPadCode : cbPadData;
  757. }
  758. #endif
  759. switch(align) /* Switch on alignment type */
  760. {
  761. case ALGNABS: /* Absolute LSEG */
  762. case ALGNBYT: /* Relocatable byte-aligned LSEG */
  763. case ALGNWRD: /* Relocatable word-aligned LSEG */
  764. case ALGNPAR: /* Relocatable para-aligned LSEG */
  765. case ALGNPAG: /* Relocatable page-aligned LSEG */
  766. #if OMF386
  767. case ALGNDBL: /* double-word-aligned */
  768. #endif
  769. break;
  770. default: /* ABSMAS, LTL LSEG, or error */
  771. mpsngsn[snMac++] = 0;
  772. return;
  773. }
  774. ++snkey; /* Increment segment i.d. key */
  775. if(comb = (WORD) ((tysn >> 2) & 7)) /* If "public" segment */
  776. {
  777. apropSn = (APROPSNPTR )
  778. PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) TRUE);
  779. /* Look up symbol table entry */
  780. if(!vfCreated) /* If it was already there */
  781. {
  782. apropSn = CheckClass(apropSn, rhteClass);
  783. #if OSEGEXE
  784. if (apropSn->as_fExtra & FROM_DEF_FILE)
  785. { /* Override .DEF file segment attributes */
  786. mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE);
  787. apropSn->as_tysn = (TYSNTYPE) tysn;
  788. /* Save ACBP field */
  789. #if NOT EXE386
  790. if (flags & FCODE386 || seglen > LXIVK)
  791. apropSn->as_flags |= NS32BIT;
  792. /* Set Big/Default bit */
  793. #endif
  794. apropSn->as_key = snkey;/* Save the key value */
  795. }
  796. #endif
  797. }
  798. }
  799. else /* Else if private segment */
  800. {
  801. apropSn = (APROPSNPTR )
  802. PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) FALSE);
  803. /* Check if defined in .def file - caviar:4767 */
  804. if(apropSn && apropSn->as_fExtra & FROM_DEF_FILE)
  805. {
  806. OutWarn(ER_farovl, GetPropName(apropSn)+1, "root");
  807. }
  808. vfCreated = (FTYPE) TRUE; /* This is a new segment */
  809. apropSn = (APROPSNPTR ) PropAdd(mplnamerhte[lname],ATTRLSN);
  810. }
  811. if(vfCreated) /* If a new cell was created */
  812. {
  813. if(gsnMac >= gsnMax)
  814. Fatal(ER_segmax);
  815. /* Check for table overflow */
  816. apropSn->as_gsn = gsnMac; /* Assign new global SEGDEF number */
  817. mpgsnrprop[gsnMac++] = vrprop; /* Save address of property list */
  818. apropSn->as_rCla = rhteClass; /* Save ptr to class hash tab ent */
  819. /* Superclass hash table entry */
  820. DEBUGVALUE(apropSn); /* Debug info */
  821. DEBUGVALUE(apropSn->as_rCla); /* Debug info */
  822. apropSn->as_tysn = (TYSNTYPE) tysn;
  823. /* Save ACBP field */
  824. mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE);
  825. #if OSEGEXE
  826. #if EXE386
  827. apropSn->as_flags = flags & FCODE ? dfCode : dfData;
  828. /* Assume default flags */
  829. #else
  830. apropSn->as_flags = (WORD) (flags & FCODE ? dfCode : dfData);
  831. /* Assume default flags */
  832. if (flags & FCODE386 || seglen > LXIVK)
  833. apropSn->as_flags |= NS32BIT;
  834. /* Set Big/Default bit */
  835. #endif
  836. #else
  837. apropSn->as_flags = flags;
  838. #endif
  839. apropSn->as_key = snkey; /* Save the key value */
  840. apropSn->as_ComDat = NULL; /* No COMDATs yet */
  841. #if OVERLAYS
  842. apropSn->as_iov = (IOVTYPE) NOTIOVL;
  843. // No overlay assigment yet
  844. #endif
  845. }
  846. #if OMF386 AND NOT EXE386
  847. else
  848. {
  849. /* If segment defined as both 16- and 32-bit, fatal error */
  850. WORD fNew, fOld;
  851. fNew = (WORD) ((flags & FCODE386) ? 1 : 0);
  852. fOld = (WORD) (
  853. #if OSEGEXE
  854. (apropSn->as_flags & NS32BIT) ?
  855. #else
  856. (apropSn->as_flags & FCODE386) ?
  857. #endif
  858. 1 : 0);
  859. if (fNew != fOld)
  860. Fatal(ER_16seg32,1 + GetPropName(apropSn));
  861. }
  862. #endif
  863. #if OVERLAYS
  864. CheckOvl(apropSn, iovFile);
  865. #endif
  866. #if SYMDEB
  867. if (seglen && (flags & FCODE))
  868. cSegCode++; /* Count code seg's, so CV gets proper */
  869. /* number of sstModule subsections */
  870. #endif
  871. gsn = apropSn->as_gsn; /* Save global SEGDEF no. */
  872. if(comb == COMBSTK) /* If segment combines like stack */
  873. {
  874. gsnStack = gsn; /* Set stack global SEGDEF number */
  875. align = ALGNBYT; /* Force to byte alignment */
  876. if (cbStack)
  877. seglen = 0L; /* Ignore stack segment size if /STACK given */
  878. }
  879. else if(comb == COMBCOM) /* If segment combines like common */
  880. {
  881. cbMaxPrev = apropSn->as_cbMx; /* Get previous segment size */
  882. apropSn->as_cbMx = 0L; /* Set size to zero */
  883. if(seglen < cbMaxPrev) seglen = cbMaxPrev;
  884. /* Take the larger of the two sizes */
  885. }
  886. cbMaxPrev = apropSn->as_cbMx; /* Get previous size */
  887. if(align == ALGNWRD) cbMaxPrev = (~0L<<1) & (cbMaxPrev + (1<<1) - 1);
  888. /* Round size up to word boundary */
  889. #if OMF386
  890. else if(align == ALGNDBL) cbMaxPrev = (~0L<<2) & (cbMaxPrev + (1<<2) - 1);
  891. #endif /* Round size up to double boundary */
  892. else if(align == ALGNPAR) cbMaxPrev = (~0L<<4) & (cbMaxPrev + (1<<4) - 1);
  893. /* Round size up to para. boundary */
  894. else if(align == ALGNPAG) cbMaxPrev = (~0L<<8) & (cbMaxPrev + (1<<8) - 1);
  895. /* Round size up to word boundary */
  896. prevAlign = (WORD) ((apropSn->as_tysn >> 5) & 7);
  897. // In Assign Addresses pass the aligment of the whole logical
  898. // segment has to be equal to the biggest aligment of all
  899. // contributions for given logical segment. Here we are checking
  900. // if current contribution has bigger aligment then the
  901. // contributions seen so FAR. The bigger aligment criteria is a
  902. // bit tricky - the aligment constants are defined as follows:
  903. //
  904. // 1 - byte aligment
  905. // 2 - word aligment
  906. // 3 - paragraph aligment
  907. // 4 - page aligment
  908. // 5 - double word aligment
  909. //
  910. // The aligment ordering is as follows:
  911. //
  912. // byte < word < dword < para < page
  913. // 1 2 5 3 4
  914. //
  915. // If align greater than prev. val.
  916. if (prevAlign == ALGNDBL || align == ALGNDBL)
  917. {
  918. if (prevAlign == ALGNDBL && align >= ALGNPAR)
  919. apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
  920. /* Use new value */
  921. else if (align == ALGNDBL && prevAlign <= ALGNWRD)
  922. apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
  923. /* Use new value */
  924. }
  925. else if (align > prevAlign)
  926. apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
  927. /* Use new value */
  928. if (align != ALGNABS) /* If not an absolute LSEG */
  929. {
  930. seglen += cbMaxPrev;
  931. #if EXE386 OR OMF386
  932. if ((flags & FCODE386) != 0
  933. #if O68K
  934. && iMacType == MAC_NONE
  935. #endif
  936. )
  937. {
  938. #if EXE386
  939. if (seglen < cbMaxPrev) /* errmsg takes # megabytes */
  940. Fatal(ER_seg386, 1 + GetPropName(apropSn), 1 << (LG2SEG32 - 20));
  941. #else
  942. if (seglen > CBMAXSEG32) /* errmsg takes # megabytes */
  943. Fatal(ER_seg386,1 + GetPropName(apropSn),1 << (LG2SEG32 - 20));
  944. #endif
  945. }
  946. else
  947. #endif
  948. if (seglen > LXIVK)
  949. {
  950. if (comb != COMBSTK)
  951. OutError(ER_segsize,1 + GetPropName(apropSn));
  952. /* Check for segment overflow */
  953. else
  954. {
  955. if (!cbStack)
  956. OutWarn(ER_stack64);
  957. cbStack = LXIVK - 2;/* Assume 64k stack segment */
  958. }
  959. }
  960. apropSn->as_cbMx = seglen; /* Save new segment size */
  961. /*
  962. * If this is a 16-bit code segment, check for unreliable
  963. * lengths due to the 286 bug. For DOS exes, assume worst
  964. * case, i.e. real mode limit.
  965. */
  966. if((flags & FCODE) && !(EXE386 && (flags & FCODE386)))
  967. #if OIAPX286
  968. if(seglen == LXIVK)
  969. #else
  970. if(seglen > LXIVK - 36)
  971. #endif
  972. SegUnreliable(apropSn);
  973. }
  974. else apropSn->as_cbMx = (long) saAbs;
  975. /* "Hack to save origin of abs seg" */
  976. mpgsndra[gsn] = cbMaxPrev; /* Save previous size */
  977. mpsngsn[snMac++] = gsn; /* Map SEGDEF no to global SEGDEF no */
  978. MARKVP(); /* Virtual page has changed */
  979. if (fFullMap && contriblen)
  980. AddContributor(gsn, (unsigned long) -1L, contriblen);
  981. }
  982. /****************************************************************
  983. * *
  984. * GrpRc1: *
  985. * *
  986. * This function processes GRPDEF records on pass 1. *
  987. * See pp. 36-39 in "8086 Object Module Formats EPS." *
  988. * *
  989. ****************************************************************/
  990. LOCAL void NEAR GrpRc1(void)
  991. {
  992. LNAMETYPE lnameGroup; /* Group LNAME number */
  993. SNTYPE sn; /* Group (local) segment number */
  994. APROPSNPTR apropSn;
  995. APROPGROUPPTR apropGroup;
  996. GRTYPE ggr; /* Global GRPDEF number */
  997. WORD gcdesc; /* GRPDEF component descriptor */
  998. #if EXE386
  999. BYTE *pGrName; /* Group name */
  1000. #endif
  1001. if(grMac >= GRMAX) Fatal(ER_grpdef);
  1002. lnameGroup = GetIndex(1, (WORD) (lnameMac - 1));
  1003. /* Read in group name index */
  1004. apropGroup = (APROPGROUPPTR )
  1005. PropRhteLookup(mplnamerhte[lnameGroup], ATTRGRP, (FTYPE) TRUE);
  1006. /* Look up cell in hash table */
  1007. if(vfCreated) /* If entry did not exist before */
  1008. {
  1009. if(ggrMac >= GGRMAX) Fatal(ER_grpmax);
  1010. apropGroup->ag_ggr = ggrMac++; /* Save global GRPDEF no. */
  1011. }
  1012. ggr = apropGroup->ag_ggr; /* Get global GRPDEF no. */
  1013. mpggrrhte[ggr] = mplnamerhte[lnameGroup];
  1014. /* Save pointer to name */
  1015. mpgrggr[grMac++] = ggr; /* Map local to global */
  1016. #if EXE386
  1017. /* Check for pseudo-group FLAT here */
  1018. pGrName = GetFarSb(((AHTEPTR)(FetchSym(mpggrrhte[ggr], FALSE)))->cch);
  1019. if (SbCompare(pGrName, sbFlat, TRUE))
  1020. ggrFlat = ggr;
  1021. #endif
  1022. while(cbRec > 1) /* While not at end of record */
  1023. {
  1024. gcdesc = Gets(); /* Read in the descriptor */
  1025. ASSERT(gcdesc == 0xFF); /* Linker doesn't handle others */
  1026. sn = GetIndex(1,snMac); /* Get local SEGDEF index */
  1027. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
  1028. /* Fetch from virt mem */
  1029. if(apropSn->as_ggr == GRNIL)
  1030. { /* Store global GRPDEF no. if none */
  1031. apropSn->as_ggr = ggr;
  1032. #if OSEGEXE
  1033. /*
  1034. * Check if a segment which is part of DGROUP was defined
  1035. * as class "CODE", also if it was given a sharing attribute
  1036. * that conflicts with the autodata type.
  1037. * Could only happen if seg defined in a def-file. Must be
  1038. * done here because only now do we know that it's in DGROUP.
  1039. */
  1040. if(ggr == ggrDGroup && (apropSn->as_fExtra & FROM_DEF_FILE))
  1041. {
  1042. #if EXE386
  1043. if (IsEXECUTABLE(apropSn->as_flags))
  1044. {
  1045. SetREADABLE(apropSn->as_flags);
  1046. SetWRITABLE(apropSn->as_flags);
  1047. apropSn->as_rCla = rhteBegdata;
  1048. mpgsnfCod[apropSn->as_gsn] = FALSE;
  1049. OutWarn(ER_cod2dat,1 + GetPropName(apropSn));
  1050. apropSn = (APROPSNPTR )
  1051. FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
  1052. }
  1053. if (((vFlags & NESOLO) && !IsSHARED(apropSn->as_flags)) ||
  1054. ((vFlags & NEINST) && IsSHARED(apropSn->as_flags)))
  1055. {
  1056. if (vFlags & NESOLO)
  1057. SetSHARED(apropSn->as_flags);
  1058. else
  1059. apropSn->as_flags &= ~OBJ_SHARED;
  1060. OutWarn(ER_adcvt,1 + GetPropName(apropSn));
  1061. }
  1062. #else
  1063. if((apropSn->as_flags & NSTYPE) != NSDATA)
  1064. {
  1065. apropSn->as_flags &= ~NSTYPE;
  1066. apropSn->as_flags |= NSDATA;
  1067. apropSn->as_rCla = rhteBegdata;
  1068. mpgsnfCod[apropSn->as_gsn] = FALSE;
  1069. OutWarn(ER_cod2dat,1 + GetPropName(apropSn));
  1070. apropSn = (APROPSNPTR )
  1071. FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
  1072. }
  1073. if(((vFlags & NESOLO) && !(apropSn->as_flags & NSSHARED)) ||
  1074. ((vFlags & NEINST) && (apropSn->as_flags & NSSHARED)))
  1075. {
  1076. if(vFlags & NESOLO) apropSn->as_flags |= NSSHARED;
  1077. else apropSn->as_flags &= ~NSSHARED;
  1078. OutWarn(ER_adcvt,1 + GetPropName(apropSn));
  1079. }
  1080. #endif /* EXE386 */
  1081. }
  1082. #endif /* OSEGEXE */
  1083. }
  1084. else if (apropSn->as_ggr != ggr)/* If segment belongs to other group */
  1085. {
  1086. if(fLstFileOpen) fflush(bsLst);
  1087. /* Flush list file, if any */
  1088. OutWarn(ER_grpmul,1 + GetPropName(apropSn));
  1089. }
  1090. }
  1091. }
  1092. void NEAR DupErr(BYTE *sb)/* Duplicate definition error */
  1093. /* Symbol to which error refers */
  1094. {
  1095. BSTYPE bsTmp; /* Temporary file pointer */
  1096. MSGTYPE msg; /* Message to use */
  1097. #if OSMSDOS
  1098. extern char *pExtDic; /* Pointer to extended dictionary */
  1099. #endif
  1100. SBTYPE sbUndecor; /* a buffer for undecorated name */
  1101. /* If this module is in an extended dictionary, suggest /NOEXT in error
  1102. * message.
  1103. */
  1104. msg = (MSGTYPE) (
  1105. #if OSMSDOS
  1106. pExtDic ? ER_symdup1 :
  1107. #endif
  1108. ER_symdup);
  1109. UndecorateSb((char FAR*) sb, (char FAR*) sbUndecor, sizeof(sbUndecor) );
  1110. OutError(msg,1 + sbUndecor);
  1111. if(fLstFileOpen && bsErr != bsLst)
  1112. {
  1113. bsTmp = bsErr;
  1114. bsErr = bsLst;
  1115. OutError(msg,1 + sbUndecor);
  1116. bsErr = bsTmp;
  1117. }
  1118. }
  1119. /****************************************************************
  1120. * *
  1121. * PubRc1: *
  1122. * *
  1123. * This function processes PUBDEF records on pass 1. *
  1124. * See pp. 44-46 in "8086 Object Module Formats EPS." *
  1125. * *
  1126. ****************************************************************/
  1127. LOCAL void NEAR PubRc1(void)
  1128. {
  1129. GRTYPE ggr; /* Group definition number */
  1130. SNTYPE sn; /* Local SEGDEF no. */
  1131. SNTYPE gsn; /* Global SEGDEF no. */
  1132. RATYPE dra;
  1133. SBTYPE sb; /* Public symbol */
  1134. RATYPE ra; /* Public symbol offset */
  1135. APROPNAMEPTR apropName; /* Table entry for symbol name */
  1136. WORD type; /* Local type no. */
  1137. int fSkipCv = FALSE;/* Don't register DATA PUBDEF if a COMDEF
  1138. for that symbol has already been seen */
  1139. DEBUGVALUE(grMac - 1); /* Debug info */
  1140. ggr = (GRTYPE) GetIndex(0, (WORD) (grMac - 1));/* Get group index */
  1141. DEBUGVALUE(ggr); /* Debug info */
  1142. if (!(sn = GetIndex(0, (WORD) (snMac - 1))))/* If frame number present */
  1143. {
  1144. gsn = 0; /* No global SEGDEF no. */
  1145. dra = 0;
  1146. SkipBytes(2); /* Skip the frame number */
  1147. }
  1148. else /* Else if local SEGDEF no. given */
  1149. {
  1150. if (ggr != GRNIL)
  1151. ggr = mpgrggr[ggr]; /* If group specified, get global no */
  1152. gsn = mpsngsn[sn]; /* Get global SEGDEF no. */
  1153. dra = mpgsndra[gsn];
  1154. }
  1155. DEBUGVALUE(cbRec); /* Debug info */
  1156. while (cbRec > 1) /* While there are symbols left */
  1157. {
  1158. sb[0] = (BYTE) Gets(); /* Get symbol length */
  1159. if (TYPEOF(rect) == PUBDEF)
  1160. GetBytes(&sb[1],B2W(sb[0]));/* Read in symbol text */
  1161. else
  1162. GetLocName(sb); /* Transform local name */
  1163. #if CMDXENIX
  1164. if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen;
  1165. /* Truncate if necessary */
  1166. #endif
  1167. #if OMF386
  1168. if (rect & 1)
  1169. ra = LGets();
  1170. else
  1171. #endif
  1172. ra = WGets(); /* Get symbol segment offset */
  1173. type = GetIndex(0,0x7FFF); /* Get type index */
  1174. if (!vfNewOMF)
  1175. type = 0;
  1176. /* Look for symbol among undefined */
  1177. apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRUND, FALSE);
  1178. if (apropName != PROPNIL) /* Symbol known to be undefined */
  1179. {
  1180. if (((APROPUNDEFPTR )apropName)->au_flags & COMMUNAL)
  1181. {
  1182. if (mpgsnfCod[gsn])
  1183. DupErr(sb); /* Communal matches code PUBDEF */
  1184. fSkipCv = TRUE;
  1185. }
  1186. vfCreated = (FTYPE) TRUE;
  1187. }
  1188. else
  1189. {
  1190. /* Look for symbol among ALIASes */
  1191. if (vrhte == RHTENIL)
  1192. apropName = PROPNIL;
  1193. else
  1194. apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
  1195. if (apropName != PROPNIL)
  1196. {
  1197. #if FDEBUG
  1198. if (fDebug)
  1199. {
  1200. sb[sb[0] + 1] = '\0';
  1201. OutWarn(ER_ignoalias, &sb[1]);
  1202. }
  1203. #endif
  1204. continue;
  1205. }
  1206. else if (vrhte == RHTENIL)
  1207. {
  1208. apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRPNM, TRUE);
  1209. }
  1210. else
  1211. {
  1212. apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRPNM, TRUE);
  1213. }
  1214. }
  1215. if (vfCreated) /* If new PUBNAM entry created or */
  1216. { /* old UNDEF entry to modify */
  1217. // If printable symbol, increment counter and set flags
  1218. if (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~')
  1219. {
  1220. ++pubMac;
  1221. apropName->an_flags = FPRINT;
  1222. }
  1223. else
  1224. {
  1225. #if ILINK
  1226. ++locMac; /* Included in .SYM file */
  1227. #endif
  1228. }
  1229. apropName->an_attr = ATTRPNM;
  1230. /* Symbol is a public name */
  1231. apropName->an_ra = ra + dra;/* Give symbol its adjusted offset */
  1232. apropName->an_gsn = gsn; /* Save its global SEGDEF no. */
  1233. apropName->an_ggr = ggr; /* Save its global SEGDEF no. */
  1234. #if OVERLAYS
  1235. apropName->an_thunk = THUNKNIL;
  1236. #endif
  1237. #if ILINK
  1238. apropName->an_module = imodFile;
  1239. #endif
  1240. MARKVP(); /* Mark virtual page as changed */
  1241. #if SYMDEB
  1242. if (fSymdeb && (apropName->an_flags & FPRINT) && !fSkipPublics && !fSkipCv)
  1243. {
  1244. // Remember CV type index
  1245. apropName->an_CVtype = type;
  1246. DebPublic(vrprop, rect);
  1247. }
  1248. #endif
  1249. }
  1250. else if(apropName->an_gsn != gsn || apropName->an_ra != ra + dra)
  1251. {
  1252. DupErr(sb); /* Definitions do not match */
  1253. }
  1254. }
  1255. }
  1256. /****************************************************************
  1257. * *
  1258. * ExtRc1: *
  1259. * *
  1260. * This function processes EXTDEF records on pass 1. *
  1261. * See pp. 47-48 in "8086 Object Module Formats EPS." *
  1262. * *
  1263. ****************************************************************/
  1264. LOCAL void NEAR ExtRc1(void)
  1265. {
  1266. SBTYPE sb; /* EXTDEF symbol */
  1267. APROPUNDEFPTR apropUndef; /* Pointer to symbol entry */
  1268. APROPALIASPTR apropAlias; /* Pointer to symbol entry */
  1269. APROPNAMEPTR apropName; /* Pointer to symbol entry */
  1270. APROPCOMDATPTR apropComdat; /* pointer to symbol entry */
  1271. WORD itype; /* Type index */
  1272. RBTYPE rhte; /* Virt. addr. of hash table entry */
  1273. AHTEPTR ahte; // Symbol table hash entry
  1274. while (cbRec > 1) /* While there are symbols left */
  1275. {
  1276. if (extMac >= EXTMAX - 1) /* Check for table overflow */
  1277. Fatal(ER_extdef);
  1278. if (TYPEOF(rect) == CEXTDEF)
  1279. {
  1280. itype = GetIndex(0, (WORD) (lnameMac - 1));
  1281. rhte = mplnamerhte[itype];
  1282. ahte = (AHTEPTR) FetchSym(rhte, FALSE);
  1283. FMEMCPY((char FAR *) sb, ahte->cch, ahte->cch[0] + 1);
  1284. /* Look for a matching PUBDEF */
  1285. apropUndef = (APROPUNDEFPTR) PropRhteLookup(rhte, ATTRPNM, FALSE);
  1286. }
  1287. else
  1288. {
  1289. rhte = RHTENIL;
  1290. sb[0] = (BYTE) Gets(); /* Get symbol length */
  1291. if (TYPEOF(rect) == EXTDEF)
  1292. GetBytes(&sb[1], B2W(sb[0]));
  1293. /* Read in text of symbol */
  1294. else
  1295. GetLocName(sb); /* Get local name */
  1296. #if CMDXENIX
  1297. if (symlen && B2W(sb[0]) > symlen)
  1298. sb[0] = symlen; /* Truncate if necessary */
  1299. #endif
  1300. /* Look for a matching PUBDEF */
  1301. apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE);
  1302. }
  1303. DEBUGSB(sb); /* Print symbol */
  1304. if (!vfNewOMF) /* If old-style OMF */
  1305. itype = GetIndex(0, (WORD) (typMac - 1));/* Get type index */
  1306. else
  1307. itype = GetIndex(0, 0x7FFF); /* Get type index (any value OK) */
  1308. #if FALSE
  1309. if (fDebug)
  1310. {
  1311. sb[sb[0]+1] = '\0';
  1312. fprintf(stdout, "\r\n%s has index = %u", sb+1, extMac);
  1313. }
  1314. #endif
  1315. apropName = PROPNIL;
  1316. if (apropUndef == PROPNIL) /* If there isn't one */
  1317. {
  1318. /* Look for a matching ALIAS */
  1319. if (vrhte == RHTENIL)
  1320. apropAlias = PROPNIL;
  1321. else
  1322. apropAlias = (APROPALIASPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
  1323. if (apropAlias != PROPNIL)
  1324. {
  1325. /* ALIAS matches this EXTDEF */
  1326. mpextprop[extMac++] = apropAlias->al_sym;
  1327. apropName = (APROPNAMEPTR) FetchSym(apropAlias->al_sym, TRUE);
  1328. if (apropName->an_attr == ATTRPNM)
  1329. {
  1330. // If substitute name is a PUBDEF then use it
  1331. if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) &&
  1332. mpgsnfCod[apropName->an_gsn])
  1333. /* Communal matches code PUBDEF */
  1334. DupErr(sb); /* Duplicate definition */
  1335. }
  1336. else
  1337. {
  1338. // The substitute name is an EXTDEF
  1339. // Mark substitute name so it causes the library search, because
  1340. // we don't know neither the alias nor the substitute
  1341. apropUndef = (APROPUNDEFPTR) apropName;
  1342. apropUndef->au_flags |= SEARCH_LIB;
  1343. apropName = PROPNIL;
  1344. #if NEW_LIB_SEARCH
  1345. if (fStoreUndefsInLookaside)
  1346. StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0);
  1347. #endif
  1348. #ifdef DEBUG_SHOWALIAS
  1349. sb[sb[0]+1] = '\0';
  1350. fprintf(stderr, "extdef alias: %s\r\n", sb+1);
  1351. fflush(stderr);
  1352. #endif
  1353. }
  1354. }
  1355. else
  1356. {
  1357. /* Insert as undefined symbol */
  1358. if (vrhte == RHTENIL)
  1359. apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE);
  1360. else
  1361. apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
  1362. mpextprop[extMac++] = vrprop;
  1363. if(vfCreated)
  1364. {
  1365. apropUndef->au_flags |= UNDECIDED;
  1366. apropUndef->au_len = -1L;
  1367. #if NEWLIST
  1368. apropUndef->u.au_rbNxt = rbLstUndef;
  1369. rbLstUndef = vrprop;
  1370. #endif
  1371. }
  1372. else if (apropUndef->au_flags & UNDECIDED)
  1373. {
  1374. apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE);
  1375. apropUndef->au_flags |= STRONGEXT;
  1376. #if NEW_LIB_SEARCH
  1377. if (fStoreUndefsInLookaside)
  1378. StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0);
  1379. #endif
  1380. }
  1381. else if (apropUndef->au_flags & WEAKEXT)
  1382. apropUndef->au_flags |= UNDECIDED;
  1383. if (vfNewOMF) continue; /* Skip if module uses COMDEFs */
  1384. if(itype) /* If there is reference to TYPDEF */
  1385. DoCommon(apropUndef, mpitypelen[itype],
  1386. (WORD) (mpityptyp[itype] ? mpitypelen[mpityptyp[itype]] : 0),
  1387. sb);
  1388. if (apropUndef->au_len > 0L)
  1389. apropUndef->au_flags |= COMMUNAL;
  1390. /* Mark as true communal or not */
  1391. MARKVP(); /* Mark virt page as changed */
  1392. }
  1393. }
  1394. else
  1395. {
  1396. apropName = (APROPNAMEPTR ) apropUndef;
  1397. mpextprop[extMac++] = vrprop;
  1398. if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) &&
  1399. mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn])
  1400. /* Communal matches code PUBDEF */
  1401. DupErr(sb); /* Duplicate definition */
  1402. }
  1403. // If we are processing CEXTDEF/EXTDEF and there is public symbol
  1404. // matching the CEXTDEF/EXTDEF symbol, then mark COMDAT descriptor
  1405. // as referenced
  1406. if (apropName != PROPNIL)
  1407. {
  1408. apropComdat = (APROPCOMDATPTR) PropRhteLookup(vrhte, ATTRCOMDAT,
  1409. #if TCE
  1410. FALSE
  1411. #else
  1412. TRUE
  1413. #endif
  1414. );
  1415. if (apropComdat != PROPNIL)
  1416. {
  1417. apropComdat->ac_flags |= REFERENCED_BIT;
  1418. #if TCE_DEBUG
  1419. fprintf(stdout, "\r\nEXTDEF1 referencing '%s' ", 1+GetPropName(apropComdat));
  1420. #endif
  1421. }
  1422. }
  1423. }
  1424. }
  1425. #if OSEGEXE AND NOT QCLINK
  1426. /****************************************************************
  1427. * *
  1428. * imprc1: *
  1429. * *
  1430. * This function processes Microsoft OMF extension records of *
  1431. * type IMPDEF (i.e. IMPort DEFinition records). *
  1432. * *
  1433. ****************************************************************/
  1434. LOCAL void NEAR imprc1(void)
  1435. {
  1436. SBTYPE sbInt; /* Internal name */
  1437. SBTYPE sbMod; /* Module name */
  1438. SBTYPE sbImp; /* Imported name */
  1439. FTYPE fOrd; /* Import-by-ordinal flag */
  1440. #if ODOS3EXE
  1441. fNewExe = (FTYPE) TRUE; /* Import forces new-format exe */
  1442. #endif
  1443. fOrd = (FTYPE) Gets(); /* Get ordinal flag */
  1444. sbInt[0] = (BYTE) Gets(); /* Get length of internal name */
  1445. GetBytes(&sbInt[1],B2W(sbInt[0])); /* Get the internal name */
  1446. sbMod[0] = (BYTE) Gets(); /* Get length of module name */
  1447. GetBytes(&sbMod[1],B2W(sbMod[0])); /* Get the module name */
  1448. if(!(fOrd & 0x1)) /* If import by name */
  1449. {
  1450. sbImp[0] = (BYTE) Gets(); /* Get length of imported name */
  1451. if(sbImp[0] != '\0') /* If names differ */
  1452. {
  1453. GetBytes(&sbImp[1],B2W(sbImp[0]));
  1454. /* Get the imported name */
  1455. #if EXE386
  1456. NewImport(sbImp,0,sbMod,sbInt, (fOrd & 0x2));
  1457. #else
  1458. NewImport(sbImp,0,sbMod,sbInt);
  1459. #endif
  1460. /* Enter new import */
  1461. }
  1462. else
  1463. #if EXE386
  1464. NewImport(sbInt,0,sbMod,sbInt, (fOrd & 0x2));
  1465. #else
  1466. NewImport(sbInt,0,sbMod,sbInt);
  1467. #endif
  1468. /* Enter new import */
  1469. }
  1470. else
  1471. #if EXE386
  1472. NewImport(NULL,WGets(),sbMod,sbInt, (fOrd & 0x2));
  1473. #else
  1474. NewImport(NULL,WGets(),sbMod,sbInt);
  1475. #endif
  1476. /* Else import by ordinal */
  1477. }
  1478. /****************************************************************
  1479. * *
  1480. * exprc1: *
  1481. * *
  1482. * This function processes Microsoft OMF extension records of *
  1483. * type EXPDEF (i.e. EXPort DEFinition records). *
  1484. * *
  1485. ****************************************************************/
  1486. LOCAL void NEAR exprc1(void)
  1487. {
  1488. SBTYPE sbInt; /* Internal name */
  1489. SBTYPE sbExp; /* Exported name */
  1490. WORD OrdNum; /* Ordinal number */
  1491. WORD fRec; /* Record flags */
  1492. #if ODOS3EXE
  1493. fNewExe = (FTYPE) TRUE; /* Export forces new-format exe */
  1494. #endif
  1495. fRec = (BYTE) Gets(); /* Get record flags */
  1496. sbExp[0] = (BYTE) Gets(); /* Get length of exported name */
  1497. GetBytes(&sbExp[1],B2W(sbExp[0])); /* Get the exported name */
  1498. sbInt[0] = (BYTE) Gets(); /* Get length of internal name */
  1499. if (sbInt[0])
  1500. GetBytes(&sbInt[1],B2W(sbInt[0]));
  1501. /* Get the internal name */
  1502. if (fRec & 0x80)
  1503. { /* If ordinal number specified */
  1504. OrdNum = WGets(); /* Read it and set highest bit */
  1505. OrdNum |= ((fRec & 0x40) << 1); /* if resident name */
  1506. }
  1507. else
  1508. OrdNum = 0; /* No ordinal number specified */
  1509. // Convert flags:
  1510. // OMF flags:
  1511. // 80h = set if ordinal number specified
  1512. // 40h = set if RESIDENTNAME
  1513. // 20h = set if NODATA
  1514. // 1Fh = # of parameter words
  1515. // EXE flags:
  1516. // 01h = set if entry is exported
  1517. // 02h = set if entry uses global (shared) data segment (!NODATA)
  1518. // F8h = # of parameter words
  1519. //
  1520. // Since the logic is reversed for the NODATA flag, we toggle bit 0x20
  1521. // in the OMF flags via the expression ((fRec & 0x20) ^ 0x20).
  1522. fRec = (BYTE) (((fRec & 0x1f) << 3) | (((fRec & 0x20) ^ 0x20) >> 4) | 1);
  1523. // Mark fRec, so NewExport doesn't try to free name buffers
  1524. fRec |= 0x8000;
  1525. if (sbInt[0])
  1526. NewExport(sbExp, sbInt, OrdNum, fRec);
  1527. else
  1528. NewExport(sbExp, NULL, OrdNum, fRec);
  1529. }
  1530. #endif /* OSEGEXE */
  1531. /****************************************************************
  1532. * *
  1533. * ComRc1: *
  1534. * *
  1535. * This function processes COMENT records on pass 1. *
  1536. * See pp. 86-87 in "8086 Object Module Formats EPS." *
  1537. * *
  1538. ****************************************************************/
  1539. #pragma check_stack(on)
  1540. LOCAL void NEAR ComRc1(void)
  1541. {
  1542. #if OXOUT OR OIAPX286
  1543. WORD mismatch; /* Model mismatch flag */
  1544. #endif
  1545. #if FALSE
  1546. static BYTE modtype = 0; /* Initial model type */
  1547. BYTE curmodtype; /* Current model type */
  1548. #endif
  1549. SBTYPE text; /* Comment text */
  1550. SBTYPE LibName;
  1551. APROPFILEPTR aprop;
  1552. WORD iextWeak;
  1553. WORD iextDefRes;
  1554. APROPUNDEFPTR undefName;
  1555. FTYPE fIgnoreCaseSave;
  1556. BYTE flags;
  1557. void FAR *pTmp;
  1558. #if ILINK
  1559. SNTYPE noPadSn;
  1560. APROPSNPTR apropSn; /* Pointer to seg. record */
  1561. #endif
  1562. #if O68K
  1563. BYTE chModel;
  1564. #endif /* O68K */
  1565. Gets(); /* Skip byte 1 of comment type field */
  1566. switch(Gets()) /* Switch on comment class */
  1567. {
  1568. #if OEXE
  1569. case 0: /* Translator record */
  1570. if(fNewExe)
  1571. break;
  1572. #if ODOS3EXE
  1573. text[0] = (BYTE) (cbRec - 1);/* Get length of comment */
  1574. GetBytes(&text[1],(WORD)(cbRec - 1));/* Read in text of comment */
  1575. /*
  1576. * If translator is pre-3.30 MS/IBM PASCAL or FORTRAN,
  1577. * force on /DS and /NOG.
  1578. */
  1579. if(SbCompare(text,"\011MS PASCAL", TRUE) ||
  1580. SbCompare(text,"\012FORTRAN 77", TRUE))
  1581. vfDSAlloc = fNoGrpAssoc = (FTYPE) TRUE;
  1582. #endif
  1583. break;
  1584. #endif
  1585. case 0x81: /* Library specifier */
  1586. #if OSMSDOS OR OSPCDOS
  1587. case 0x9F: /* Library specifier (alt.) */
  1588. #endif
  1589. text[0] = (BYTE) (cbRec - 1);/* Get length of comment */
  1590. if (text[0] == 0)
  1591. break; /* Skip empty spec */
  1592. GetBytes(&text[1], (WORD) (cbRec - 1));/* Read in text of comment */
  1593. /* Add name to search list */
  1594. #if CMDMSDOS
  1595. strcpy(LibName, sbDotLib);
  1596. UpdateFileParts(LibName, text);
  1597. #endif
  1598. #if CMDXENIX
  1599. memcpy(LibName, text, B2W(text[0]) + 1);
  1600. /* Leave name unchanged */
  1601. #endif
  1602. if(!vfNoDefaultLibrarySearch)
  1603. {
  1604. #if OSMSDOS
  1605. fIgnoreCaseSave = fIgnoreCase;
  1606. fIgnoreCase = (FTYPE) TRUE;
  1607. /* If the name begins with a drive letter, skip it. This
  1608. * is to allow compatibility with old compilers which
  1609. * generated comments of the form "A:FOO.LIB".
  1610. */
  1611. if(LibName[2] == ':' && B2W(LibName[0]) > 1)
  1612. {
  1613. LibName[2] = (BYTE) (LibName[0] - 2);
  1614. if (PropSymLookup(LibName+2,ATTRSKIPLIB,FALSE) == PROPNIL)
  1615. AddLibrary(LibName+2);
  1616. }
  1617. else
  1618. #endif
  1619. if (PropSymLookup(LibName,ATTRSKIPLIB,FALSE) == PROPNIL)
  1620. AddLibrary(LibName);
  1621. fIgnoreCase = fIgnoreCaseSave;
  1622. }
  1623. break;
  1624. #if OEXE
  1625. case 0x9E: /* Force segment order directive */
  1626. SetDosseg(); /* Set switch */
  1627. break;
  1628. #endif /* OEXE */
  1629. case 0x9D: /* Model specifier */
  1630. #if FALSE
  1631. /* Removed */
  1632. mismatch = 0; /* Assume all is well */
  1633. while(cbRec > 1) /* While bytes remain */
  1634. {
  1635. curmodtype = Gets(); /* Get byte value */
  1636. switch(curmodtype)
  1637. {
  1638. case 'c': /* Compact model */
  1639. case 's': /* Small model */
  1640. case 'm': /* Medium model */
  1641. case 'l': /* Large model */
  1642. case 'h': /* Huge model */
  1643. if (modtype)
  1644. mismatch = curmodtype != modtype;
  1645. else
  1646. modtype = curmodtype;
  1647. break;
  1648. }
  1649. }
  1650. if(mismatch) OutWarn(ER_memmodel);
  1651. /* Warn if mismatch found */
  1652. #endif
  1653. #if OXOUT OR OIAPX286
  1654. mismatch = 0; /* Assume all is well */
  1655. while(cbRec > 1) /* While bytes remain */
  1656. {
  1657. modtype = Gets(); /* Get byte value */
  1658. if (fMixed) continue; /* Mixed model means we don't care */
  1659. switch(modtype)
  1660. {
  1661. case 'c': /* Compact model */
  1662. if(!fLarge || fMedium) mismatch = 1;
  1663. break; /* Warn if near data or FAR code */
  1664. case 's': /* Small model */
  1665. if(fLarge || fMedium) mismatch = 1;
  1666. /* Warn if FAR data or FAR code */
  1667. break;
  1668. case 'm': /* Medium model */
  1669. if(fLarge || !fMedium) mismatch = 1;
  1670. /* Warn if FAR data or near code */
  1671. break;
  1672. case 'l': /* Large model */
  1673. case 'h': /* Huge model */
  1674. if(!fLarge || !fMedium) mismatch = 1;
  1675. /* Warn if near data or near code */
  1676. break;
  1677. }
  1678. }
  1679. if(mismatch) OutError(ER_modelmis);
  1680. /* Warn if mismatch found */
  1681. #endif /* OXOUT OR OIAPX286 */
  1682. #if O68K
  1683. while (!f68k && cbRec > 1) /* While bytes remain */
  1684. {
  1685. chModel = (BYTE) Gets();/* Get byte value */
  1686. f68k = (FTYPE) F68KCODE(chModel);
  1687. }
  1688. #endif /* O68K */
  1689. break;
  1690. #if OSEGEXE AND NOT QCLINK
  1691. case 0xA0: /* Microsoft OMF extension */
  1692. switch(Gets()) /* Switch on extension record type */
  1693. {
  1694. case 0x01: /* IMPort DEFinition */
  1695. imprc1(); /* Call the processing routine */
  1696. break;
  1697. case 0x02: /* EXPort DEFinition */
  1698. exprc1(); /* Call the processing routine */
  1699. break;
  1700. case 0x03:
  1701. break; /* In pass-1 skip INCDEF's for QC */
  1702. #if EXE386
  1703. case 0x04: // OMF extension - link386
  1704. // if (IsDLL(vFlags))
  1705. // vFlags |= E32PROTDLL;
  1706. // Protected memory library module
  1707. break;
  1708. #endif
  1709. case 0x05: // C++ directives
  1710. flags = (BYTE) Gets();// Get flags field
  1711. #if NOT EXE386
  1712. if (flags & 0x01)
  1713. fNewExe = (FTYPE) TRUE; // PCODE forces segmented exe format
  1714. #endif
  1715. #if SYMDEB
  1716. if (flags & 0x02)
  1717. fSkipPublics = (FTYPE) TRUE;
  1718. // In C++ they don't want PUBLIC subsection in CV info
  1719. #endif
  1720. if ((flags & 0x04) && !fIgnoreMpcRun) // ignore if /PCODE:NOMPC
  1721. fMPC = (FTYPE) TRUE; // PCODE app - spawn MPC
  1722. break;
  1723. case 0x06: // target is a big-endian machine
  1724. #if O68K
  1725. fTBigEndian = (FTYPE) TRUE;
  1726. #endif /* O68K */
  1727. break;
  1728. case 0x07: // Use SSTPRETYPES instead of SSTTYPES4 in OutSSt
  1729. aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE);
  1730. aprop->af_flags |= FPRETYPES;
  1731. break;
  1732. default: /* Unknown */
  1733. InvalidObject(); /* Invalid object module */
  1734. }
  1735. break;
  1736. #endif
  1737. case 0xA1: /* 1st OMF extension: COMDEFs */
  1738. vfNewOMF = (FTYPE) TRUE;
  1739. aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE);
  1740. aprop->af_flags |= FNEWOMF;
  1741. break;
  1742. case 0xA2: /* 2nd OMF extension */
  1743. switch(Gets())
  1744. {
  1745. case 0x01: /* Start linkpass2 records */
  1746. /*
  1747. * WARNING: It is assumed this comment will NOT be in a
  1748. * module whose MODEND record contains a program starting
  1749. * address. If there are overlays, we need to see the
  1750. * starting address on pass 1 to define the symbol $$MAIN.
  1751. */
  1752. fP2Start = fModEnd = (FTYPE) TRUE;
  1753. break;
  1754. default:
  1755. break;
  1756. }
  1757. break;
  1758. #if FALSE
  1759. case 0xA3: // DON'T use - already used by LIB
  1760. break;
  1761. #endif
  1762. case 0xA4: /* OMF extension - EXESTR */
  1763. fExeStrSeen = (FTYPE) TRUE;
  1764. // WARNING: The code in this loop assumes:
  1765. //
  1766. // ExeStrLen, cBrec and ExeStrMax are 16-bit unsigned WORDS
  1767. // An int is 32-bits
  1768. // All arithmetic and comparisons are 32-bit
  1769. //
  1770. while (cbRec > 1)
  1771. {
  1772. // Limit total EXESTR to 64K - 2 bytes. We lose 1 because 0 means 0,
  1773. // and we lose another because the buffer extension loop tops out at
  1774. // 0xFFFE bytes.
  1775. if (ExeStrLen + cbRec - 1 > 0xFFFEu)
  1776. {
  1777. SkipBytes ( (WORD) (cbRec - 1) );
  1778. }
  1779. else
  1780. if (ExeStrLen + cbRec - 1 > ExeStrMax)
  1781. {
  1782. if (ExeStrBuf == NULL)
  1783. {
  1784. ExeStrBuf = GetMem(cbRec - 1);
  1785. ExeStrMax = cbRec - 1;
  1786. }
  1787. else
  1788. {
  1789. // This loop doubles the buffer size until it overflows 16 bits. After this,
  1790. // it adds one half of the difference between the current value and 0xFFFF
  1791. //
  1792. while (ExeStrMax < ExeStrLen + cbRec - 1) {
  1793. ASSERT (ExeStrMax != 0);
  1794. if ((ExeStrMax << 1) >= 0x10000)
  1795. ExeStrMax += (~ExeStrMax & 0xFFFF) >> 1;
  1796. else
  1797. ExeStrMax <<= 1;
  1798. }
  1799. pTmp = GetMem(ExeStrMax);
  1800. FMEMCPY(pTmp, ExeStrBuf, ExeStrLen);
  1801. FFREE(ExeStrBuf);
  1802. ExeStrBuf = pTmp;
  1803. }
  1804. }
  1805. // This must be done first because GetBytes() decrements
  1806. // cbRec as a side effect.
  1807. ExeStrLen += cbRec - 1;
  1808. GetBytes(&ExeStrBuf[ExeStrLen-cbRec+1], (WORD) (cbRec - 1));
  1809. }
  1810. break;
  1811. case 0xA6: /* OMF extension - INCERR */
  1812. Fatal(ER_incerr); /* Invalid object due to aborted incremental compile */
  1813. break;
  1814. #if ILINK
  1815. case 0xA7: /* OMF extension - NOPAD */
  1816. if (fIncremental && !fLibraryFile)
  1817. {
  1818. /* Remove padding from non-zero-length, non-library,
  1819. * non-64K segment contributions. (64K from huge model)
  1820. */
  1821. while (cbRec > 1)
  1822. {
  1823. noPadSn = GetIndex(1, snMac - 1);
  1824. apropSn = (APROPSNPTR) FetchSym(mpgsnrprop[mpsngsn[noPadSn]], TRUE);
  1825. if (apropSn->as_cbMx > 0L && apropSn->as_cbMx != LXIVK)
  1826. {
  1827. apropSn->as_cbMx -= mpgsnfCod[mpsngsn[noPadSn]] ? cbPadCode : cbPadData;
  1828. apropSn->as_fExtra |= NOPAD;
  1829. }
  1830. }
  1831. }
  1832. break;
  1833. #endif
  1834. case 0xA8: /* OMF extension - WeaK EXTern */
  1835. while (cbRec > 1)
  1836. {
  1837. iextWeak = GetIndex(1, (WORD) (extMac - 1));
  1838. /* Get weak extern index */
  1839. iextDefRes = GetIndex(1, (WORD) (extMac - 1));
  1840. /* Get default extern index */
  1841. #if FALSE
  1842. DumpWeakExtern(mpextprop, iextWeak, iextDefRes);
  1843. #endif
  1844. if (mpextprop[iextWeak] != PROPNIL && iextWeak < extMac)
  1845. {
  1846. undefName = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], TRUE);
  1847. if (undefName->au_attr == ATTRUND)
  1848. {
  1849. // If this is EXTDEF
  1850. if (undefName->au_flags & UNDECIDED)
  1851. {
  1852. // This can be one of the following:
  1853. // - weakness specified for the first time
  1854. // if WEAKEXT is not set
  1855. // - redefinition of weakness if the WEAKEXT
  1856. // is set.
  1857. // In case of weakness redefinition check if
  1858. // it specified the same default resolution as
  1859. // the first one. Issue warning if different
  1860. // default resolutions and override old one
  1861. // with new. In both cases reset UNDECIDED bit.
  1862. undefName->au_flags &= ~UNDECIDED;
  1863. if (undefName->au_flags & WEAKEXT)
  1864. {
  1865. if (undefName->au_Default != mpextprop[iextDefRes])
  1866. redefinition(iextWeak, iextDefRes, undefName->au_Default);
  1867. undefName->au_Default = mpextprop[iextDefRes];
  1868. }
  1869. else
  1870. {
  1871. undefName->au_Default = mpextprop[iextDefRes];
  1872. undefName->au_flags |= WEAKEXT;
  1873. }
  1874. }
  1875. // Ignore weakness - must be strong extern form
  1876. // some other .OBJ
  1877. }
  1878. }
  1879. else
  1880. InvalidObject();
  1881. }
  1882. break;
  1883. default: /* Unrecognized */
  1884. break;
  1885. }
  1886. if (cbRec > 1)
  1887. SkipBytes((WORD) (cbRec - 1)); /* Punt rest of text */
  1888. }
  1889. /*** AliasRc1 - pass 1 ALIAS record processing
  1890. *
  1891. * Purpose:
  1892. * Read and decode ALIAS OMF record (Microsoft OMF extension).
  1893. * ALIAS record introduces pair of names - alias name and substitute
  1894. * name. Enter both names into linker symbol table.
  1895. *
  1896. * Input:
  1897. * No explicit value is passed. When this function is called the record
  1898. * type and lenght are already read, so we can start reading name pairs.
  1899. *
  1900. * Output:
  1901. * No explicit value is returned. Names are entered into symbol table.
  1902. *
  1903. * Exceptions:
  1904. * Warning - redefinition of ALIAS <name>; substitute name changed
  1905. * from <name1> to <name2>.
  1906. *
  1907. * Notes:
  1908. * None.
  1909. *
  1910. *************************************************************************/
  1911. LOCAL void NEAR AliasRc1(void)
  1912. {
  1913. SBTYPE alias;
  1914. SBTYPE substitute;
  1915. APROPALIASPTR aliasDsc;
  1916. RBTYPE vAliasDsc;
  1917. APROPNAMEPTR pubName;
  1918. APROPUNDEFPTR undefName;
  1919. RBTYPE vPtr;
  1920. WORD fReferenced;
  1921. while (cbRec > 1) /* While there are symbols left */
  1922. {
  1923. /* Read alias and its substitute */
  1924. alias[0] = (BYTE) Gets();
  1925. GetBytes(&alias[1], B2W(alias[0]));
  1926. substitute[0] = (BYTE) Gets();
  1927. GetBytes(&substitute[1], B2W(substitute[0]));
  1928. aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, FALSE);
  1929. vAliasDsc = vrprop;
  1930. if (aliasDsc == PROPNIL)
  1931. {
  1932. /* New ALIAS - check if we have PUBDEF for the alias name */
  1933. pubName = (APROPNAMEPTR ) PropSymLookup(alias, ATTRPNM, FALSE);
  1934. if (pubName == PROPNIL)
  1935. {
  1936. /* Enter ALIAS name in to symbol table */
  1937. aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, TRUE);
  1938. vAliasDsc = vrprop;
  1939. #if SYMDEB
  1940. if (fSymdeb)
  1941. DebPublic(vrprop, ALIAS);
  1942. #endif
  1943. // Check if we have an EXTDEF for alias name. If we have
  1944. // this means, that substitute name has to be used in
  1945. // the library search.
  1946. undefName = (APROPUNDEFPTR ) PropSymLookup(alias, ATTRUND, FALSE);
  1947. fReferenced = (WORD) (undefName != PROPNIL);
  1948. // Check if we know the substitute name as PUBDEF or EXTDEF
  1949. pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE);
  1950. if (pubName != PROPNIL)
  1951. vPtr = vrprop;
  1952. else
  1953. {
  1954. undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE);
  1955. if (undefName != NULL)
  1956. {
  1957. vPtr = vrprop;
  1958. undefName->au_flags |= (SUBSTITUTE | SEARCH_LIB);
  1959. undefName->au_Default = vAliasDsc;
  1960. #if NEW_LIB_SEARCH
  1961. if (fStoreUndefsInLookaside)
  1962. StoreUndef((APROPNAMEPTR)undefName, RhteFromProp((APROPPTR)undefName),0,0);
  1963. #endif
  1964. }
  1965. else
  1966. {
  1967. /* Enter substitute name into symbol table */
  1968. /* as undefined symbol */
  1969. if (extMac >= EXTMAX - 1)
  1970. Fatal(ER_extdef);
  1971. undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, TRUE);
  1972. vPtr = vrprop;
  1973. mpextprop[extMac++] = vrprop;
  1974. if (fReferenced)
  1975. undefName->au_flags |= (STRONGEXT | SUBSTITUTE | SEARCH_LIB);
  1976. else
  1977. undefName->au_flags |= (UNDECIDED | SUBSTITUTE);
  1978. undefName->au_len = -1L;
  1979. undefName->au_Default = vAliasDsc;
  1980. #if NEWLIST
  1981. undefName->u.au_rbNxt = rbLstUndef;
  1982. rbLstUndef = vrprop;
  1983. #endif
  1984. }
  1985. }
  1986. /* Attach substitute symbol to the ALIAS */
  1987. aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
  1988. aliasDsc->al_sym = vPtr;
  1989. }
  1990. else
  1991. {
  1992. #if FDEBUG
  1993. if (fDebug)
  1994. {
  1995. alias[alias[0] + 1] = '\0';
  1996. OutWarn(ER_ignoalias, &alias[1]);
  1997. }
  1998. #endif
  1999. }
  2000. }
  2001. else
  2002. {
  2003. /* Check if we have redefinition */
  2004. vPtr = aliasDsc->al_sym;
  2005. pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE);
  2006. if (pubName != PROPNIL)
  2007. {
  2008. if (vPtr != vrprop)
  2009. {
  2010. aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
  2011. aliasDsc->al_sym = vrprop;
  2012. OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(pubName), &substitute[1]);
  2013. }
  2014. }
  2015. else
  2016. {
  2017. undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE);
  2018. if (undefName != PROPNIL)
  2019. {
  2020. if (vPtr != vrprop)
  2021. {
  2022. aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
  2023. aliasDsc->al_sym = vrprop;
  2024. OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(undefName), &substitute[1]);
  2025. }
  2026. }
  2027. }
  2028. }
  2029. }
  2030. }
  2031. #pragma check_stack(off)
  2032. #if OVERLAYS
  2033. /****************************************************************
  2034. * *
  2035. * EndRc1: *
  2036. * *
  2037. * This function is called to process the information *
  2038. * contained in a MODEND (type 8AH) record concerning the *
  2039. * program starting address. The function does not return a *
  2040. * meaningful value. *
  2041. * See pp. 80-81 in "8086 Object Module Formats EPS." *
  2042. * *
  2043. ****************************************************************/
  2044. LOCAL void NEAR EndRc1(void)
  2045. {
  2046. WORD modtyp; /* MODEND record modtyp byte */
  2047. WORD fixdat; /* Fixdat byte */
  2048. SNTYPE gsn; /* Global SEGDEF number */
  2049. RATYPE ra; /* Symbol offset */
  2050. APROPSNPTR apropSn; /* Pointer to segment info */
  2051. WORD frameMethod;
  2052. if ((modtyp = Gets()) & FSTARTADDRESS)
  2053. { /* If execution start address given */
  2054. ASSERT(modtyp & 1); /* Must be logical start address */
  2055. fixdat = Gets(); /* Get fixdat byte */
  2056. ASSERT(!(fixdat & 0x8F)); /* Frame, target must be explicit,
  2057. * target must be given by seg index
  2058. */
  2059. frameMethod = (fixdat & 0x70) >> 4;
  2060. if (frameMethod != F4 && frameMethod != F5)
  2061. GetIndex(0,IMAX - 1); /* Punt frame index */
  2062. gsn = mpsngsn[GetIndex((WORD)1,(WORD)(snMac - 1))];
  2063. /* Get gsn from target segment index */
  2064. #if OMF386
  2065. if(rect & 1) ra = LGets() + mpgsndra[gsn];
  2066. else
  2067. #endif
  2068. ra = WGets() + mpgsndra[gsn]; /* Get offset */
  2069. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE);
  2070. /* Get segment information */
  2071. MkPubSym("\006$$MAIN",apropSn->as_ggr,gsn,ra);
  2072. /* Make public symbol */
  2073. }
  2074. }
  2075. #endif /* OVERLAYS */
  2076. /****************************************************************
  2077. * *
  2078. * ProcP1: *
  2079. * *
  2080. * This function controls the processing of an object module *
  2081. * on pass 1. *
  2082. * *
  2083. ****************************************************************/
  2084. #pragma check_stack(on)
  2085. void NEAR ProcP1(void)
  2086. {
  2087. long typlen[TYPMAX];
  2088. WORD typtyp[TYPMAX];
  2089. RBTYPE extprop[EXTMAX];
  2090. FTYPE fFirstRec; /* First record flag */
  2091. FTYPE fFirstMod; /* First module flag */
  2092. APROPFILEPTR apropFile; /* File name entry */
  2093. #if OXOUT OR OIAPX286
  2094. RUNTYPE xhdr;
  2095. LFATYPE lfa;
  2096. #endif
  2097. mpitypelen = typlen; /* Initialize pointer */
  2098. mpityptyp = typtyp; /* Initialize pointer */
  2099. mpextprop = (RBTYPE FAR *) extprop; /* Initialize pointer */
  2100. FMEMSET(mpextprop, 0, sizeof(extprop));
  2101. fFirstMod = (FTYPE) TRUE; /* First module */
  2102. for(;;) /* Loop to process file */
  2103. {
  2104. snMac = 1; /* Initialize counter */
  2105. grMac = 1; /* Initialize */
  2106. extMac = 1; /* Initialize counter */
  2107. lnameMac = 1; /* Initialize counter */
  2108. typMac = 1; /* Initialize counter */
  2109. vfNewOMF = FALSE; /* Assume old OMF */
  2110. DEBUGVALUE(gsnMac); /* Debug info */
  2111. DEBUGVALUE(ggrMac); /* Debug info */
  2112. #if OXOUT OR OIAPX286
  2113. lfa = ftell(bsInput); /* Save initial file position */
  2114. fread(&xhdr,1,CBRUN,bsInput); /* Read x.out header */
  2115. if(xhdr.x_magic == X_MAGIC) /* If magic number found */
  2116. {
  2117. #if OXOUT
  2118. if((xhdr.x_cpu & XC_CPU) != XC_8086) InvalidObject();
  2119. /* Bad if not 8086 */
  2120. #else
  2121. xhdr.x_cpu &= XC_CPU; /* Get CPU specification */
  2122. if(xhdr.x_cpu != XC_286 && xhdr.x_cpu != XC_8086) InvalidObject();
  2123. /* Bad if not 286 or 8086 */
  2124. #endif
  2125. if(xhdr.x_relsym != (XR_R86REL | XR_S86REL)) InvalidObject();
  2126. /* Check symbol table type */
  2127. if((xhdr.x_renv & XE_VERS) != xever) InvalidObject();
  2128. /* Check Xenix version */
  2129. }
  2130. else
  2131. fseek(bsInput,lfa,0); /* Else return to start */
  2132. #endif /* OXOUT OR OIAPX286 */
  2133. #if OVERLAYS
  2134. if(fOverlays) /* If there are overlays */
  2135. iovFile = ((APROPFILEPTR) vrpropFile)->af_iov;
  2136. /* Save overlay number for file */
  2137. else
  2138. iovFile = 0; /* File contains part of root */
  2139. #endif
  2140. fFirstRec = (FTYPE) TRUE; /* Looking at first record */
  2141. fModEnd = FALSE; /* Not at module's end */
  2142. fP2Start = FALSE; /* No p2start record yet */
  2143. #if SYMDEB
  2144. cSegCode = 0; /* No code segments yet */
  2145. #endif
  2146. while(!fModEnd) /* Loop to process object module */
  2147. {
  2148. rect = (WORD) getc(bsInput);/* Read record type */
  2149. if(fFirstRec) /* If first record */
  2150. {
  2151. if(rect != THEADR && rect != LHEADR)
  2152. { /* If not header */
  2153. if(fFirstMod) break;/* Error if first module */
  2154. return; /* Else return */
  2155. }
  2156. fFirstRec = FALSE; /* Not first record any more */
  2157. }
  2158. else if (IsBadRec(rect)) break;
  2159. /* Break if invalid object */
  2160. cbRec = WSGets(); /* Read record length */
  2161. lfaLast += cbRec + 3; /* Update current file pos. */
  2162. #if ALIGN_REC
  2163. if (bsInput->_cnt >= cbRec)
  2164. {
  2165. pbRec = bsInput->_ptr;
  2166. bsInput->_ptr += cbRec;
  2167. bsInput->_cnt -= cbRec;
  2168. }
  2169. else
  2170. {
  2171. if (cbRec > sizeof(recbuf))
  2172. {
  2173. // error -- record too large [rm]
  2174. InvalidObject();
  2175. }
  2176. // read record into contiguous buffer
  2177. fread(recbuf,1,cbRec,bsInput);
  2178. pbRec = recbuf;
  2179. }
  2180. #endif
  2181. DEBUGVALUE(rect); /* Debug info */
  2182. DEBUGVALUE(cbRec); /* Debug info */
  2183. switch(TYPEOF(rect)) /* Switch on record type */
  2184. {
  2185. #if TCE
  2186. case FIXUPP:
  2187. if(fTCE)
  2188. FixRc1();
  2189. else
  2190. SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
  2191. break;
  2192. #endif
  2193. case TYPDEF:
  2194. TypRc1();
  2195. break;
  2196. case COMDEF:
  2197. case LCOMDEF:
  2198. ComDf1();
  2199. break;
  2200. case SEGDEF:
  2201. SegRc1();
  2202. break;
  2203. case THEADR:
  2204. ModRc1();
  2205. break;
  2206. case COMENT:
  2207. ComRc1();
  2208. break;
  2209. case LHEADR:
  2210. ModRc1();
  2211. break;
  2212. case GRPDEF:
  2213. GrpRc1();
  2214. break;
  2215. case EXTDEF:
  2216. case LEXTDEF:
  2217. case CEXTDEF:
  2218. ExtRc1();
  2219. break;
  2220. case LNAMES:
  2221. case LLNAMES:
  2222. LNmRc1((WORD) (TYPEOF(rect) == LLNAMES));
  2223. break;
  2224. case PUBDEF:
  2225. case LPUBDEF:
  2226. PubRc1();
  2227. break;
  2228. case MODEND:
  2229. #if OVERLAYS
  2230. if(fOverlays) EndRc1();
  2231. else
  2232. #endif
  2233. SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
  2234. fModEnd = (FTYPE) TRUE; /* Stop processing module */
  2235. break;
  2236. case COMDAT:
  2237. ComDatRc1();
  2238. break;
  2239. case ALIAS:
  2240. AliasRc1();
  2241. break;
  2242. default:
  2243. if (rect == EOF)
  2244. InvalidObject();
  2245. SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
  2246. break;
  2247. }
  2248. if(cbRec != 1) break; /* If record length bad */
  2249. Gets(); /* Eat the checksum byte */
  2250. }
  2251. if(!fModEnd)
  2252. {
  2253. ChkInput(); /* First check for I/O problems */
  2254. InvalidObject(); /* Invalid module */
  2255. }
  2256. ++modkey; /* For local symbols */
  2257. #if SYMDEB
  2258. if (fSymdeb)
  2259. {
  2260. apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE);
  2261. if (apropFile->af_cvInfo || apropFile->af_Src)
  2262. ++ObjDebTotal; /* Count the .OBJ with CV info */
  2263. }
  2264. #endif
  2265. if(extMac > extMax) /* Possibly set new extMax */
  2266. extMax = extMac;
  2267. if(fLibraryFile || fP2Start) return;
  2268. fFirstMod = FALSE; /* Not first module */
  2269. }
  2270. }
  2271. #pragma check_stack(off)