Leaked source code of windows server 2003
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.

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