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.

2520 lines
72 KiB

  1. /* SCCSID = @(#)newtrn.c 4.10 86/10/08 */
  2. /*
  3. * Copyright Microsoft Corporation, 1983-1987
  4. *
  5. * This Module contains Proprietary Information of Microsoft
  6. * Corporation and should be treated as Confidential.
  7. */
  8. /****************************************************************
  9. * *
  10. * NEWTRN.C *
  11. * *
  12. * Main function of the linker. *
  13. * *
  14. ****************************************************************/
  15. #include <minlit.h> /* Types, constants, macros */
  16. #if USE_REAL AND (NOT defined( _WIN32 ))
  17. #define i386
  18. #endif
  19. #include <bndtrn.h> /* Types and constants */
  20. #include <bndrel.h> /* More types and constants */
  21. #include <lnkio.h> /* Linker I/O definitions */
  22. #include <lnkmsg.h> /* Error messages */
  23. #include <extern.h> /* External declarations */
  24. #include <nmsg.h> /* Near message strings */
  25. #include <newexe.h>
  26. #include <sys\types.h>
  27. #if NOT CLIBSTD
  28. #include <fcntl.h>
  29. #endif
  30. #include <direct.h>
  31. #if EXE386
  32. #include <exe386.h>
  33. #endif
  34. #if OSEGEXE AND CPU286
  35. #define INCL_DOSSESMGR
  36. #define INCL_DOSERRORS
  37. #include <os2.h>
  38. #if defined(M_I86LM)
  39. #undef NEAR
  40. #define NEAR
  41. #endif
  42. #endif
  43. #include <process.h>
  44. #include <malloc.h>
  45. #include <undname.h>
  46. #if WIN_NT
  47. #include <except.h>
  48. #endif
  49. #if (WIN_3 OR USE_REAL)
  50. #if defined( _WIN32 )
  51. #undef NEAR
  52. #undef FAR
  53. #undef PASCAL
  54. #endif
  55. #include <windows.h>
  56. #endif
  57. #define _32k 0x8000
  58. LOCAL FTYPE RunFileOpen; /* Executable-file-open flag */
  59. LOCAL int ifhLast; /* Last input file */
  60. #if LNKPROF
  61. extern FTYPE fP1stop; /* Stop after Pass 1 */
  62. #endif
  63. #if NEWIO
  64. #include <errno.h> /* System level error codes */
  65. #endif
  66. /*
  67. * LOCAL FUNCTION PROTOTYPES
  68. */
  69. LOCAL void NEAR PrintStats(void);
  70. LOCAL void PrintAnUndef(APROPNAMEPTR prop,
  71. RBTYPE rhte,
  72. RBTYPE rprop,
  73. WORD fNewHte);
  74. LOCAL void NEAR InitFP(void);
  75. LOCAL void NEAR InitFpSym(BYTE *sb, BYTE flags);
  76. LOCAL void NEAR InterPass(void);
  77. LOCAL void NEAR InitAfterCmd(void);
  78. #if EXE386
  79. LOCAL void NEAR ChkSize386(void);
  80. #endif
  81. LOCAL void NEAR CleanUp(void);
  82. LOCAL void NEAR OutRunFile(BYTE *sbRun);
  83. LOCAL void NEAR SpawnOther(BYTE *sbRun, BYTE *szMyself);
  84. #if CVPACK_MONDO
  85. extern int cvpack_main(int, char **);
  86. #endif // CVPACK_MONDO
  87. #ifdef PENTER_PROFILE
  88. void saveEntries();
  89. #endif
  90. #if TIMINGS
  91. #include <sys\types.h>
  92. #include <sys\timeb.h>
  93. struct _timeb time_start;
  94. struct _timeb time_end;
  95. int fShowTiming;
  96. #endif // TIMINGS
  97. #if DEBUG_HEAP_ALLOCS
  98. #define D_SIZE 5 // Number of test bytes on each side of the allocated buffer
  99. #define FILL_CHAR 1 // Character to fill the test areas
  100. #define P_SIZE 5000 // Size of an array of 'malloc'ated pointers
  101. struct Entry {
  102. BYTE FAR * ptr;
  103. int size;
  104. };
  105. struct Entry Pointers[P_SIZE];
  106. int indexMac = 0;
  107. // Check a block from the Pointers table
  108. int Ckb ( int index )
  109. {
  110. BYTE * pBuf;
  111. int size,i;
  112. int ret = 1;
  113. if(index > P_SIZE)
  114. {
  115. fprintf(stdout, "INDEX TOO LARGE %d ", index);
  116. return 0;
  117. }
  118. if(!Pointers[index].ptr) // a freed entry
  119. return 1;
  120. pBuf = Pointers[index].ptr-D_SIZE;
  121. size = Pointers[index].size;
  122. for( i=0; i<D_SIZE; i++ )
  123. {
  124. if(pBuf[i] != FILL_CHAR)
  125. {
  126. fprintf(stdout, "\r\nFront block memory error; idx %d at %d, %x != %x ",
  127. index, i, pBuf[i], FILL_CHAR);
  128. ret = 0;
  129. }
  130. }
  131. pBuf += D_SIZE + size;
  132. for( i=0; i<D_SIZE; i++ )
  133. {
  134. if(pBuf[i] != FILL_CHAR)
  135. {
  136. fprintf(stdout, "\r\nMemory tail error; idx %d at %d, %x != %x",
  137. index, i, pBuf[i], FILL_CHAR);
  138. ret = 0;
  139. }
  140. }
  141. fflush(stdout);
  142. return ret;
  143. }
  144. // Ckeck all the memory blocks allocated so far
  145. int CheckAll(void)
  146. {
  147. int i;
  148. for(i=0; i<indexMac; i++)
  149. {
  150. if(!Ckb(i))
  151. return 0;
  152. }
  153. return 1;
  154. }
  155. #pragma intrinsic(memset)
  156. BYTE FAR *GETMEM(unsigned size, BYTE* pFile, int Line)
  157. {
  158. BYTE FAR *p;
  159. BYTE FAR *pBuf;
  160. fprintf(stdout,"\r\nGETMEM : size %d bytes, idx %d, file %s, line %d ",
  161. size, indexMac, pFile, Line);
  162. if(!CheckAll()) // check all so far allocated blocks first
  163. exit(2);
  164. pBuf = (BYTE FAR *) malloc(size + 2*D_SIZE);
  165. if(pBuf)
  166. {
  167. p = pBuf + D_SIZE;
  168. memset(pBuf, FILL_CHAR, size + 2*D_SIZE);
  169. }
  170. else
  171. Fatal(ER_memovf);
  172. memset(p, 0, size);
  173. Pointers[indexMac].ptr = p;
  174. Pointers[indexMac++].size = size;
  175. fprintf(stdout, " returns %x ", p);
  176. fflush(stdout);
  177. return(p);
  178. }
  179. #pragma function(memset)
  180. void FreeMem( void * p )
  181. {
  182. int i;
  183. unsigned size;
  184. BYTE FAR * pBuf = (BYTE*)p-D_SIZE;
  185. fprintf(stdout, "\r\nFreeMem : %x ", p);
  186. for( i=0; i<= indexMac; i++)
  187. {
  188. if(Pointers[i].ptr == p)
  189. {
  190. size = Pointers[i].size;
  191. fprintf(stdout, "size %d, idx %d ", size, i);
  192. break;
  193. }
  194. }
  195. if (i> indexMac)
  196. {
  197. fprintf(stdout, "Pointer UNKNOWN ");
  198. return;
  199. }
  200. if (!Ckb(i))
  201. exit(1);
  202. fprintf(stdout, " freeing %x ", (BYTE*)p-D_SIZE);
  203. fflush(stdout);
  204. free((BYTE*)p-D_SIZE);
  205. fprintf(stdout, ". ");
  206. fflush(stdout);
  207. Pointers[i].ptr = NULL;
  208. }
  209. void *REALLOC_ (void * memblock, size_t nsize, char* pFile, int Line)
  210. {
  211. int i;
  212. unsigned size;
  213. BYTE * ret;
  214. BYTE FAR * pBuf = (BYTE FAR* )memblock-D_SIZE;
  215. fprintf(stdout, "\r\nREALLOC %x, new size %d, file %s, line %d ",
  216. memblock, nsize, pFile, Line);
  217. if(!CheckAll())
  218. exit(2);
  219. if(!memblock)
  220. exit(2);
  221. for( i=0; i<= indexMac; i++)
  222. {
  223. if(Pointers[i].ptr == memblock)
  224. {
  225. size = Pointers[i].size;
  226. fprintf(stdout, "old size %d, idx %d ", size, i);
  227. if(Ckb(i))
  228. fprintf(stdout, " Chk OK ");
  229. break;
  230. }
  231. }
  232. if (i> indexMac)
  233. {
  234. fprintf(stdout, "Pointer UNKNOWN ");
  235. memblock = realloc( memblock, nsize );
  236. if (!memblock)
  237. Fatal(ER_memovf);
  238. return (void*)memblock;
  239. }
  240. else
  241. {
  242. fflush(stdout);
  243. fprintf(stdout, "\r\nreallocing %x ", pBuf);
  244. fflush(stdout);
  245. pBuf = malloc(nsize + 2*D_SIZE);
  246. if (!pBuf) Fatal(ER_memovf);
  247. memset(pBuf, FILL_CHAR, nsize+2*D_SIZE);
  248. memcpy(pBuf+D_SIZE, memblock, size);
  249. free((BYTE*)memblock-D_SIZE);
  250. fprintf(stdout, " new addr %x ", pBuf);
  251. fflush(stdout);
  252. Pointers[i].size = nsize;
  253. Pointers[i].ptr = pBuf+D_SIZE;
  254. if(Ckb(i))
  255. fprintf(stdout, " Chk2 OK ");
  256. else
  257. exit(2);
  258. return pBuf+D_SIZE;
  259. }
  260. }
  261. #else // IF !DEBUG_HEAP_ALLOCS
  262. /*** GetMem - memory allocator
  263. *
  264. * Purpose:
  265. * Allocate memory block and zero-out it. Report problems.
  266. *
  267. * Input:
  268. * - size - memory block size in bytes.
  269. *
  270. * Output:
  271. * If sucessfull function returns pointer to the allocated memory,
  272. * otherwise function doesnt return.
  273. *
  274. * Exceptions:
  275. * No more memory - fatal error - abort
  276. *
  277. * Notes:
  278. * None.
  279. *
  280. *************************************************************************/
  281. #pragma intrinsic(memset)
  282. BYTE FAR *GetMem(unsigned size)
  283. {
  284. BYTE FAR *p;
  285. p = (BYTE FAR *) FMALLOC(size);
  286. if (p == NULL)
  287. Fatal(ER_memovf);
  288. FMEMSET(p, 0, size);
  289. return(p);
  290. }
  291. #pragma function(memset)
  292. #endif // !DEBUG_HEAP_ALLOCS
  293. /*** DeclareStdIds - declare standard identifiers
  294. *
  295. * Purpose:
  296. * Introduce to linker's symbol table standard identifiers
  297. *
  298. * Input:
  299. * None.
  300. *
  301. * Output:
  302. * No explicit value is returned. Symbol table is initialized.
  303. *
  304. * Exceptions:
  305. * None.
  306. *
  307. * Notes:
  308. * None.
  309. *
  310. *************************************************************************/
  311. void DeclareStdIds(void)
  312. {
  313. APROPGROUPPTR papropGroup;
  314. // Definition of DGROUP
  315. papropGroup = (APROPGROUPPTR ) PropSymLookup((BYTE *) "\006DGROUP", ATTRGRP, TRUE);
  316. papropGroup->ag_ggr = ggrMac;
  317. // In case we won't see a DGROUP definition
  318. mpggrrhte[ggrMac] = vrhte;
  319. ggrDGroup = ggrMac++;
  320. // Definition of class "CODE"
  321. PropSymLookup((BYTE *) "\004CODE", ATTRNIL, TRUE);
  322. /* Create hash table entry */
  323. vrhteCODEClass = vrhte; /* Save virtual hash table address */
  324. // Definition of special classes
  325. PropSymLookup((BYTE *) "\007BEGDATA", ATTRNIL, TRUE);
  326. rhteBegdata = vrhte;
  327. PropSymLookup((BYTE *) "\003BSS", ATTRNIL, TRUE);
  328. rhteBss = vrhte;
  329. PropSymLookup((BYTE *) "\005STACK", ATTRNIL, TRUE);
  330. rhteStack = vrhte;
  331. }
  332. #if FDEBUG
  333. /*
  334. * Print statistics to list file or console.
  335. */
  336. LOCAL void NEAR PrintStats()
  337. {
  338. if (fLstFileOpen) /* Send to list file if any */
  339. bsErr = bsLst;
  340. // Print statistics
  341. FmtPrint(GetMsg(STAT_segs), gsnMac - 1);
  342. FmtPrint(GetMsg(STAT_groups), ggrMac - 1);
  343. FmtPrint(GetMsg(STAT_bytes),
  344. #if NEWSYM
  345. (long) cbSymtab);
  346. #else
  347. (long) rbMacSyms << SYMSCALE);
  348. #endif
  349. #if OVERLAYS
  350. if (fOverlays)
  351. FmtPrint(GetMsg(STAT_ovls), iovMac);
  352. #endif
  353. bsErr = stderr; /* Reset */
  354. }
  355. #endif /* FDEBUG */
  356. /****************************************************************
  357. * *
  358. * CleanUp: *
  359. * *
  360. * This function cleans up after the rest of the linker. *
  361. * *
  362. ****************************************************************/
  363. LOCAL void NEAR CleanUp(void)
  364. {
  365. SBTYPE buf;
  366. if (bsRunfile != NULL) /* If run file open, close it */
  367. CloseFile (bsRunfile);
  368. if(vgsnLineNosPrev && fLstFileOpen) NEWLINE(bsLst); /* Write newline */
  369. #if CMDMSDOS AND NOT WIN_3
  370. if (
  371. #if QCLINK
  372. !fZ1 &&
  373. #endif
  374. cErrors) /* If there were non-fatal errors */
  375. FmtPrint(strcpy(buf, GetMsg((MSGTYPE)(cErrors > 1 ? P_errors : P_1error))),
  376. cErrors);
  377. #endif
  378. }
  379. #if NEWIO
  380. /* #pragma loop_opt(on) */
  381. /*
  382. * FreeHandle : Free a file handle by closing an open file
  383. *
  384. * In pass 1, close the currently open file. In pass 2, close
  385. * an open library handle.
  386. * Mark the appropriate record fields 0 to indicate unopened.
  387. */
  388. void FreeHandle ()
  389. {
  390. APROPFILEPTR apropFile; /* Pointer to file */
  391. RBTYPE vindx; /* Virtual temp. pointer */
  392. int FileHandle;
  393. int CurrentFileHandle;
  394. FTYPE fLibFile;
  395. int count;
  396. CurrentFileHandle = fileno(bsInput);
  397. /* Loop throught all open files and close one, that is different from */
  398. /* currently open file */
  399. vindx = rprop1stOpenFile;
  400. count = 0;
  401. do
  402. {
  403. apropFile = (APROPFILEPTR) FetchSym(vindx,TRUE);
  404. /* Fetch file property cell from VM */
  405. fLibFile = (FTYPE) (apropFile->af_ifh != FHNIL);
  406. /* Check if this is library file */
  407. if (fLibFile) /* Get file handle */
  408. FileHandle = mpifhfh[apropFile->af_ifh];
  409. else
  410. FileHandle = apropFile->af_fh;
  411. if (FileHandle &&
  412. FileHandle != CurrentFileHandle &&
  413. FileHandle != vmfd)
  414. { /* File can be closed */
  415. _close(FileHandle);
  416. count++;
  417. if (fLibFile) /* Mark data structures */
  418. mpifhfh[apropFile->af_ifh] = 0;
  419. else
  420. apropFile->af_fh = 0;
  421. if (count == 2)
  422. {
  423. rprop1stOpenFile = (apropFile->af_FNxt == RHTENIL) ?
  424. r1stFile : apropFile->af_FNxt;
  425. /* Set new first open file pointer */
  426. /* If end of file list goto list begin */
  427. /* Becouse of bug in bind API emulation */
  428. /* we have to free to handles at any time */
  429. break; /* Job done */
  430. }
  431. }
  432. vindx = (apropFile->af_FNxt == RHTENIL) ? r1stFile : apropFile->af_FNxt;
  433. } while (vindx != rprop1stOpenFile);
  434. }
  435. /* #pragma loop_opt(off) */
  436. /*
  437. * SmartOpen : open a file, closing another file if necessary
  438. *
  439. * Open the given file for binary reading, plus sharing mode
  440. * "deny write" if library file. If no more handles, free a
  441. * handle and try again. Update mpifhfh[].
  442. *
  443. * PARAMETERS:
  444. * sbInput Null-terminated string, name of file
  445. * ifh File index (FHNIL if not a library)
  446. *
  447. * RETURNS
  448. * File handle of opened file or -1.
  449. *
  450. * SIDE EFFECTS
  451. * Sets mpifhfh[ifh] to file handle if successful.
  452. */
  453. int NEAR SmartOpen (char *sbInput, int ifh)
  454. {
  455. int fh; /* File handle */
  456. FTYPE fLib; /* True if library */
  457. int secondtry = 0; /* True if on second try */
  458. // Determine whether library file or not.
  459. fLib = (FTYPE) (ifh != FHNIL);
  460. secondtry = 0;
  461. // Do at most twice
  462. for(;;)
  463. {
  464. if (fLib)
  465. fh = _sopen(sbInput, O_BINARY|O_RDONLY, SH_DENYWR);
  466. else
  467. fh = _open(sbInput, O_BINARY|O_RDONLY);
  468. // If open succeeds or we've tried twice exit the loop.
  469. if (fh != -1 || secondtry)
  470. break;
  471. // Prepare for second try: free a file handle
  472. FreeHandle();
  473. secondtry = 1;
  474. }
  475. // If library file and open succeeded, update mpifhfh[].
  476. if (fLib && fh != -1)
  477. mpifhfh[ifh] = (char) fh;
  478. return(fh);
  479. }
  480. #endif /* NEWIO */
  481. /*** SearchPathLink - self-expalnatory
  482. *
  483. * Purpose:
  484. * Search given path for given file and open file if found.
  485. *
  486. * Input:
  487. * lpszPath - path to search
  488. * pszFile - file to search for
  489. * ifh - file handle index for libraries
  490. * fStripPath - TRUE if original path specification
  491. * can be ignored
  492. *
  493. * Output:
  494. * Returns file handle if file was found.
  495. *
  496. * Exceptions:
  497. * None.
  498. *
  499. * Notes:
  500. * None.
  501. *
  502. *************************************************************************/
  503. #pragma check_stack(on)
  504. int NEAR SearchPathLink(char FAR *lpszPath, char *pszFile,
  505. int ifh, WORD fStripPath)
  506. {
  507. char oldDrive[_MAX_DRIVE];
  508. char oldDir[_MAX_DIR];
  509. char oldName[_MAX_FNAME];
  510. char oldExt[_MAX_EXT];
  511. char newDir[_MAX_DIR];
  512. char fullPath[_MAX_PATH];
  513. int fh;
  514. char FAR *lpch;
  515. char *pch;
  516. /* Decompose pszFile into four components */
  517. _splitpath(pszFile, oldDrive, oldDir, oldName, oldExt);
  518. // Don't search path if the input file has absolute or
  519. // relative path and you are not allowed to ignore it
  520. if (!fStripPath && (oldDrive[0] != '\0' || oldDir[0] != '\0'))
  521. return(-1);
  522. /* Loop through environment value */
  523. lpch = lpszPath;
  524. pch = newDir;
  525. do
  526. {
  527. if (*lpch == ';' || *lpch == '\0')
  528. { /* If end of path specification */
  529. if (pch > newDir)
  530. { /* If specification not empty */
  531. if (!fPathChr(pch[-1]) && pch[-1] != ':')
  532. *pch++ = CHPATH; /* Add path char if none */
  533. *pch = '\0';
  534. _makepath(fullPath, NULL, newDir, oldName, oldExt);
  535. fh = SmartOpen(fullPath, ifh);
  536. if (fh > 0)
  537. return(fh); /* File found - return file handle */
  538. pch = newDir; /* Reset pointer */
  539. }
  540. }
  541. else
  542. *pch++ = *lpch; /* Else copy character to path */
  543. }
  544. while(*lpch++ != '\0' && pch < &newDir[_MAX_DIR - 1]);
  545. /* Loop until end of string */
  546. return(-1);
  547. }
  548. #pragma check_stack(off)
  549. /****************************************************************
  550. * *
  551. * DrivePass: *
  552. * *
  553. * This function applies either the pass 1 or the pass 2 *
  554. * object module processor to all the objects being linked *
  555. * together. *
  556. * *
  557. ****************************************************************/
  558. void NEAR DrivePass(void (NEAR *pProcessPass)(void))
  559. {
  560. GRTYPE grggr[GRMAX]; /* f(local grpnum) = global grpnum */
  561. SNTYPE sngsn[SNMAX]; /* f(local segnum) = global segnum */
  562. AHTEPTR ahte; /* Pointer to hash table entry */
  563. APROPFILEPTR apropFile; /* Pointer to file entry */
  564. int ifh; /* File handle index */
  565. RBTYPE rbFileNext; /* Ptr to prop list of next file */
  566. long lfa; /* File offset */
  567. WORD i;
  568. BYTE *psbName;
  569. #if NEWSYM
  570. BYTE *sbInput;
  571. #else
  572. SBTYPE sbInput; /* Input file name */
  573. #endif
  574. #if OSMSDOS
  575. BYTE b; /* A byte */
  576. #endif
  577. #if NEWIO
  578. int fh; /* File handle */
  579. #endif
  580. fDrivePass = (FTYPE) TRUE; /* Executing DrivePass */
  581. mpgrggr = grggr; /* Initialize pointer */
  582. mpsngsn = sngsn; /* Initialize pointer */
  583. rbFileNext = rprop1stFile; /* Next file to look at is first */
  584. while(rbFileNext) /* Loop to process objects */
  585. {
  586. vrpropFile = rbFileNext; /* Make next file the current file */
  587. apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,FALSE);
  588. /* Fetch table entry from VM */
  589. #if ILINK
  590. if (fIncremental)
  591. imodFile = apropFile->af_imod;
  592. #endif
  593. rbFileNext = apropFile->af_FNxt;/* Get pointer to next file */
  594. ifh = apropFile->af_ifh; /* Get the file handle index */
  595. fLibraryFile = (FTYPE) (ifh != FHNIL);
  596. /* Set library flag */
  597. #if NEWIO
  598. if(fLibraryFile)
  599. fh = mpifhfh[ifh];
  600. else
  601. fh = (int) apropFile->af_fh;
  602. #endif
  603. if(!vfPass1)
  604. vfNewOMF = (FTYPE) ((apropFile->af_flags & FNEWOMF) != 0);
  605. lfa = apropFile->af_lfa; /* Get file offset */
  606. /* "Get hte (name) of file" */
  607. while(apropFile->af_attr != ATTRNIL)
  608. { /* While haven't found nil attr */
  609. vrhteFile = apropFile->af_next;
  610. /* Try next entry in list */
  611. apropFile = (APROPFILEPTR ) FetchSym(vrhteFile,FALSE);
  612. /* Fetch it from VM */
  613. }
  614. DEBUGVALUE(vrhteFile); /* Debug info */
  615. ahte = (AHTEPTR ) apropFile; /* Save pointer to hash tab entry */
  616. #if CMDMSDOS
  617. /* Library file with offset 0 means process all the modules
  618. * the library. This is done on pass 1; in pass 2 they are
  619. * inserted into the file list.
  620. */
  621. if(fLibraryFile && lfa == 0 && vfPass1)
  622. {
  623. psbName = GetFarSb(ahte->cch);
  624. #if WIN_3
  625. StatMsgWin("%s\r\n", psbName+1);
  626. #endif
  627. #if C8_IDE
  628. if(fC8IDE)
  629. {
  630. sprintf(msgBuf, "@I4%s\r\n", psbName+1);
  631. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  632. }
  633. #endif
  634. GetLibAll(psbName);
  635. continue;
  636. }
  637. #endif
  638. /* If new object file, or pass2 and new library, there's a
  639. * new file to open.
  640. */
  641. if(!fLibraryFile || (!fLibPass && ifhLast != ifh))
  642. {
  643. #if NOT NEWIO
  644. if(!fLibPass && ifhLast != FHNIL) fclose(bsInput);
  645. /* Close previous lib. on pass two */
  646. #endif
  647. for(;;) /* Loop to get input file and */
  648. { /* allow user to change diskette */
  649. #if NEWSYM
  650. sbInput = GetFarSb(ahte->cch);
  651. #else
  652. memcpy(sbInput,1 + GetFarSb(ahte->cch),B2W(ahte->cch[0]));
  653. /* Copy name to buffer */
  654. sbInput[B2W(ahte->cch[0])] = '\0';
  655. /* Null-terminate file name */
  656. #endif
  657. #if WIN_3
  658. StatMsgWin("%s\r\n", sbInput+1);
  659. #endif
  660. #if C8_IDE
  661. if(fC8IDE)
  662. {
  663. sprintf(msgBuf, "@I4%s\r\n", sbInput+1);
  664. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  665. }
  666. #endif
  667. #if NEWIO
  668. if(!fh)
  669. fh = SmartOpen(&sbInput[1],ifh);
  670. if(fh > 0)
  671. break;
  672. #if OSMSDOS
  673. else if (lpszLIB != NULL)
  674. { /* If variable set */
  675. fh = SearchPathLink(lpszLIB, &sbInput[1], ifh, FALSE);
  676. if(fh > 0)
  677. break; /* File found, breake WHILE loop */
  678. }
  679. #endif
  680. #else
  681. if((bsInput = fopen(sbInput,RDBIN)) != NULL)
  682. /* If no error opening input file */
  683. break; /* Exit loop */
  684. #endif /* NEWIO */
  685. #if OSMSDOS
  686. if (ahte->cch[2] == ':') b = (char) (ahte->cch[1] - 'A');
  687. /* If disk specified, grab it */
  688. else b = DskCur; /* Else use current drive */
  689. #endif
  690. fDrivePass = FALSE;
  691. #if OSMSDOS
  692. /* "If we are changing the listfile device or
  693. * the VM.TMP device or if the device is not
  694. * changeable, then exit."
  695. */
  696. if((fLstFileOpen && b == chListFile) ||
  697. (!fScrClosed && b == DskCur) || !FCHGDSK(b) ||
  698. fNoprompt)
  699. #endif
  700. Fatal(ER_opnobj,&sbInput[1]);
  701. #if OSMSDOS
  702. if(!(*pfPrompt)(NULL,ER_fileopn,(int) (INT_PTR)(sbInput+1),P_ChangeDiskette,
  703. b + 'A'))
  704. Fatal(0);
  705. #endif
  706. #if NEWIO
  707. fh = 0;
  708. #endif
  709. fDrivePass = (FTYPE) TRUE;
  710. #if OSXENIX
  711. break; /* Make sure we exit the loop */
  712. #endif
  713. }
  714. if(fh > 0)
  715. {
  716. fflush(bsInput);
  717. bsInput->_file = (char) fh;
  718. bsInput->_flag &= ~_IOEOF;
  719. }
  720. }
  721. /* If previous module was in same library, do relative seek
  722. * else do absolute seek.
  723. * Can't do it with Xenix libraries unless __.SYMDEF is loaded
  724. * in memory.
  725. */
  726. #if LIBMSDOS
  727. if(fLibraryFile && ifh == ifhLast)
  728. {
  729. if (lfa-lfaLast > 0)
  730. fseek(bsInput,lfa - lfaLast,1);
  731. else
  732. fseek(bsInput,lfa,0);
  733. }
  734. else
  735. #endif
  736. if(fLibraryFile || !vfPass1)
  737. fseek(bsInput,lfa,0); /* Seek to desired offset */
  738. lfaLast = lfa; /* Update current file position */
  739. (*pProcessPass)(); /* Call ProcP1 or ProcP2 */
  740. ifhLast = ifh; /* Save this file handle */
  741. if(!fLibraryFile) /* If not a library */
  742. {
  743. #if NEWIO
  744. apropFile = (APROPFILEPTR) FetchSym(vrpropFile,TRUE);
  745. if(vfPass1)
  746. apropFile->af_fh = fileno(bsInput);
  747. else
  748. {
  749. _close(fileno(bsInput));
  750. apropFile->af_fh = 0;
  751. }
  752. #else
  753. fclose(bsInput); /* Close input file */
  754. #endif
  755. }
  756. #if NEWIO
  757. rbFilePrev = vrpropFile;
  758. #endif
  759. }
  760. #if NEWIO
  761. if(!vfPass1) /* Free up file stream on pass two */
  762. #else
  763. if(ifh != FHNIL && !vfPass1) // Close libraries on pass two
  764. #endif
  765. {
  766. for (i = 0; i < ifhLibMac; i++)
  767. {
  768. if (mpifhfh[i])
  769. {
  770. _close(mpifhfh[i]);
  771. mpifhfh[i] = 0;
  772. }
  773. }
  774. }
  775. fDrivePass = FALSE; /* No longer executing DrivePass */
  776. }
  777. /****************************************************************
  778. * *
  779. * PrintAnUndef: *
  780. * *
  781. * This function will print the name of an undefined symbol *
  782. * and the name(s) of the module(s) in which it is referenced. *
  783. * This routine is passed as an argument to EnSyms(). *
  784. * *
  785. ****************************************************************/
  786. LOCAL void PrintAnUndef(prop,rhte,rprop,fNewHte)
  787. APROPNAMEPTR prop; /* Pointer to undef prop cell */
  788. RBTYPE rprop; /* Virt addr of prop cell */
  789. RBTYPE rhte; /* Virt addr of hash tab ent */
  790. WORD fNewHte; /* True if name has been written */
  791. {
  792. APROPUNDEFPTR propUndef;
  793. AHTEPTR hte; /* Pointer to hash table entry */
  794. WORD x;
  795. MSGTYPE errKind;
  796. PLTYPE FAR * entry;
  797. char *puname;
  798. char *substitute;
  799. SBTYPE testName;
  800. SBTYPE undecorUndef;
  801. SBTYPE undecorSubst;
  802. propUndef = (APROPUNDEFPTR) prop;
  803. if (((propUndef->au_flags & WEAKEXT) && !(propUndef->au_flags & UNDECIDED)) ||
  804. !propUndef->u.au_rFil)
  805. return; // Don't print "weak" externs or
  806. // undefined exports
  807. hte = (AHTEPTR ) FetchSym(rhte,FALSE);
  808. /* Fetch symbol from hash table */
  809. puname = GetFarSb(hte->cch);
  810. substitute = NULL;
  811. if (propUndef->au_flags & SUBSTITUTE)
  812. {
  813. substitute = puname;
  814. puname = GetPropName(FetchSym(propUndef->au_Default, FALSE));
  815. }
  816. ++cErrors; /* Increment error count */
  817. hte = (AHTEPTR ) FetchSym(rhte,FALSE);
  818. /* Fetch symbol from hash table */
  819. errKind = ER_UnresExtern;
  820. #if WIN_3
  821. fSeverity = SEV_ERROR;
  822. #endif
  823. // Check here for calling convention mismatch
  824. if (puname[1] == '@' || puname[1] == '_')
  825. {
  826. strcpy(testName, puname);
  827. if (testName[1] == '@')
  828. testName[1] = '_';
  829. else
  830. testName[1] = '@';
  831. // Check for fast-call/C-call mismatch
  832. if (PropSymLookup(testName, ATTRPNM, FALSE) != PROPNIL)
  833. errKind = ER_callmis;
  834. else
  835. {
  836. // Check for Pascal/fast-call or C-call mismatch
  837. for (x = 1; x < testName[0]; x++)
  838. testName[x] = (BYTE) toupper(testName[x + 1]);
  839. testName[0]--;
  840. if (PropSymLookup(testName, ATTRPNM, FALSE) != PROPNIL)
  841. errKind = ER_callmis;
  842. }
  843. }
  844. // Undecorate names if necessary
  845. if (puname[1] == '?')
  846. {
  847. UndecorateSb(puname, undecorUndef, sizeof(undecorUndef));
  848. puname = undecorUndef;
  849. }
  850. if (substitute && substitute[1] == '?')
  851. {
  852. UndecorateSb(substitute, undecorSubst, sizeof(undecorSubst));
  853. substitute = undecorSubst;
  854. }
  855. // Walk the list of file references to this symbol
  856. entry = propUndef->u.au_rFil;
  857. vrpropFile = 0;
  858. do
  859. {
  860. if (vrpropFile != entry->pl_rprop)
  861. vrpropFile = entry->pl_rprop;/* Set the file pointer */
  862. else
  863. {
  864. entry = entry->pl_next; /* Advance the list pointer */
  865. continue;
  866. }
  867. if(fLstFileOpen && bsLst != stdout)
  868. { /* If listing but not to console */
  869. #if QCLINK
  870. if (fZ1)
  871. {
  872. fZ1 = FALSE; // Restore normal linker print function
  873. OutFileCur(bsLst); // Output file name
  874. fZ1 = (FTYPE) TRUE; // Restore QC call-back
  875. }
  876. else
  877. #endif
  878. {
  879. #if WIN_3
  880. APROPFILEPTR apropFile; /* Pointer to file property cell */
  881. AHTEPTR ahte; /* Pointer symbol name */
  882. SBTYPE sb; /* String buffer */
  883. int n; /* String length counter */
  884. apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,FALSE);
  885. ahte = GetHte(vrpropFile);
  886. for(n = B2W(ahte->cch[0]), sb[n+1] = 0; n >= 0; sb[n] = ahte->cch[n], --n);
  887. fprintf(bsLst, sb+1);
  888. #else
  889. OutFileCur(bsLst); /* Output file name */
  890. #endif
  891. }
  892. }
  893. OutFileCur(stderr); /* Output file name */
  894. if(fLstFileOpen && bsLst != stdout)
  895. { /* If listing but not to console */
  896. #if MSGMOD
  897. fprintf(bsLst, " : %s %c%04d: ",
  898. __NMSG_TEXT(N_error), 'L', ER_UnresExtern);
  899. fprintf(bsLst, GetMsg(errKind), &puname[1]);
  900. if (substitute)
  901. fprintf(bsLst, GetMsg(ER_UnresExtra), &substitute[1]);
  902. #else
  903. fprintf(bsLst, " : error: ");
  904. fprintf(bsLst, GetMsg(errKind), &puname[1]);
  905. #endif
  906. }
  907. #if MSGMOD
  908. FmtPrint(" : %s %c%04d: ", __NMSG_TEXT(N_error), 'L', errKind);
  909. FmtPrint(GetMsg(errKind), &puname[1]);
  910. if (substitute)
  911. FmtPrint(GetMsg(ER_UnresExtra), &substitute[1]);
  912. #else
  913. FmtPrint(" : error: ");
  914. FmtPrint(GetMsg(errKind), &puname[1]);
  915. #endif
  916. entry = entry->pl_next; /* Advance the list pointer */
  917. } while(entry != NULL);
  918. }
  919. #if OSEGEXE AND NOT QCLINK
  920. LOCAL void NEAR InitFpSym(sb, flags)
  921. BYTE * sb;
  922. BYTE flags;
  923. {
  924. APROPNAMEPTR aprop;
  925. /* If symbol exists as EXTDEF, convert to PUBDEF */
  926. aprop = (APROPNAMEPTR ) PropSymLookup(sb,ATTRUND,FALSE);
  927. if(aprop != PROPNIL)
  928. {
  929. aprop->an_attr = ATTRPNM;
  930. aprop->an_gsn = 0;
  931. aprop->an_ra = 0;
  932. aprop->an_ggr = 0;
  933. aprop->an_flags = 0;
  934. }
  935. /* Otherwise, if it exists as a PUBDEF, get it else quit */
  936. else
  937. {
  938. aprop = (APROPNAMEPTR) PropSymLookup(sb,ATTRPNM,FALSE);
  939. if(aprop == PROPNIL)
  940. return;
  941. }
  942. aprop->an_flags |= flags;
  943. MARKVP();
  944. }
  945. /*
  946. * InitFP
  947. *
  948. * Initialize table for processing floating-point fixups for new-format
  949. * executables.
  950. */
  951. LOCAL void NEAR InitFP ()
  952. {
  953. InitFpSym((BYTE *) "\006FIARQQ", 1 << FFPSHIFT);
  954. InitFpSym((BYTE *) "\006FISRQQ", 2 << FFPSHIFT);
  955. InitFpSym((BYTE *) "\006FICRQQ", 3 << FFPSHIFT);
  956. InitFpSym((BYTE *) "\006FIERQQ", 4 << FFPSHIFT);
  957. InitFpSym((BYTE *) "\006FIDRQQ", 5 << FFPSHIFT);
  958. InitFpSym((BYTE *) "\006FIWRQQ", 6 << FFPSHIFT);
  959. InitFpSym((BYTE *) "\006FJARQQ", FFP2ND);
  960. InitFpSym((BYTE *) "\006FJSRQQ", FFP2ND);
  961. InitFpSym((BYTE *) "\006FJCRQQ", FFP2ND);
  962. }
  963. #endif /* OSEGEXE AND NOT QCLINK */
  964. #if (OSEGEXE AND CPU286)
  965. /* until the 16 bit bsedos.h supports these definitions: */
  966. #define FAPPTYP_NOTSPEC 0x0000
  967. #define FAPPTYP_NOTWINDOWCOMPAT 0x0001
  968. #define FAPPTYP_WINDOWCOMPAT 0x0002
  969. #define FAPPTYP_WINDOWAPI 0x0003
  970. #define FAPPTYP_BOUND 0x0008
  971. #define FAPPTYP_DLL 0x0010
  972. #define FAPPTYP_DOS 0x0020
  973. #define FAPPTYP_PHYSDRV 0x0040 /* physical device driver */
  974. #define FAPPTYP_VIRTDRV 0x0080 /* virtual device driver */
  975. #define FAPPTYP_PROTDLL 0x0100 /* 'protected memory' dll */
  976. /* I added these definitions: */
  977. #define _FAPPTYP_32BIT 0x4000
  978. #define _FAPPTYP_EXETYPE FAPPTYP_WINDOWAPI
  979. /*-----------------------------------------------------------*/
  980. /* from cruiser DCR 1117: */
  981. /*
  982. * PM Program PM (0x0)
  983. * DOS DOSFS (0x1)
  984. * OS/2 or FAPI Window Compatible OS2W (0x2)
  985. * OS/2 or FAPI Non-Window Compatible OS2FS (0x3)
  986. */
  987. #define _AT_PMAPI 0x00 /* Uses PM API */
  988. #define _AT_DOS 0x01 /* DOS APP */
  989. #define _AT_PMW 0x02 /* Window compatible */
  990. #define _AT_NOPMW 0x03 /* Not Window compatible */
  991. #define _AT_EXETYPE 0x03 /* EXE type mask */
  992. /*** InitEA - initialize buffer describing extended attribute
  993. *
  994. * Purpose:
  995. * Initialize EA buffer by coping its name and setting up the FEALIST.
  996. *
  997. * Input:
  998. * pEABuf - pointer to EA buffer
  999. * cbBuf - size of EA buffer
  1000. * pszEAName - extended attribute name
  1001. * peaop - pointer to EA operand
  1002. * cbEAVal - size of extended attribute value
  1003. * bEAFlags - extended attribute flags
  1004. *
  1005. * Output:
  1006. * Pointer to the place where the EA value should be copied into EA buffer
  1007. *
  1008. * Exceptions:
  1009. * None.
  1010. *
  1011. * Notes:
  1012. * None.
  1013. *
  1014. *************************************************************************/
  1015. LOCAL BYTE * NEAR InitEA(BYTE *pEABuf, WORD cbBuf, char *pszEAName,
  1016. EAOP *peaop, WORD cbEAVal, WORD bEAFlags)
  1017. {
  1018. WORD cbFEAList;
  1019. FEALIST *pfeaList;
  1020. WORD cbEAName;
  1021. BYTE *pszT;
  1022. cbEAName = strlen(pszEAName);
  1023. cbFEAList = sizeof(FEALIST) + 1 + cbEAName + cbEAVal + 2*sizeof(USHORT);
  1024. if (cbFEAList > cbBuf)
  1025. return(NULL);
  1026. pfeaList = (FEALIST *) pEABuf;
  1027. /* First initialize the EAOP structure */
  1028. peaop->fpGEAList = NULL; /* Not used for sets */
  1029. peaop->fpFEAList = (PFEALIST)pfeaList;
  1030. /* Now initialize the FEAList */
  1031. pfeaList->cbList = cbFEAList;
  1032. pfeaList->list[0].fEA = (BYTE) bEAFlags;
  1033. pfeaList->list[0].cbName = (unsigned char) cbEAName;
  1034. pfeaList->list[0].cbValue = cbEAVal + 2*sizeof(USHORT);
  1035. pszT = (char *) pfeaList + sizeof(FEALIST);
  1036. strcpy(pszT, pszEAName);
  1037. pszT += cbEAName + 1;
  1038. return(pszT);
  1039. }
  1040. #pragma check_stack(on)
  1041. /*** SetFileEABinary - set file extended attribute binary value
  1042. *
  1043. * Purpose:
  1044. * Set file extended attributes for OS/2 1.2 and higher.
  1045. *
  1046. * Input:
  1047. * fh - file handle
  1048. * pszEAName - extended attribute name
  1049. * EAVal - extended attribute value
  1050. * bEAFlags - extended attribute flags
  1051. *
  1052. * Output:
  1053. * No explicit value is returned. If succesfull file extended attributes
  1054. * are set, otherwise not.
  1055. *
  1056. * Exceptions:
  1057. * None.
  1058. *
  1059. * Notes:
  1060. * This function allocates quite a bit on stack, so don't remove
  1061. * stack checking pragma.
  1062. *
  1063. *************************************************************************/
  1064. LOCAL void NEAR SetFileEABinary(int fh, char *pszEAName,
  1065. BYTE *pEAVal, USHORT cbEAVal,
  1066. WORD bEAFlags)
  1067. {
  1068. BYTE bEABuf[512]; /* Should be enought for linker purposes */
  1069. EAOP eaop;
  1070. BYTE *pszT;
  1071. WORD retCode;
  1072. if (pszEAName == NULL || cbEAVal > sizeof(bEABuf))
  1073. return;
  1074. pszT = InitEA(bEABuf, sizeof(bEABuf), pszEAName, &eaop, cbEAVal, bEAFlags);
  1075. if (pszT == NULL)
  1076. return;
  1077. *((USHORT *)pszT) = EAT_BINARY;
  1078. pszT += sizeof(USHORT);
  1079. *((USHORT *)pszT) = cbEAVal;
  1080. pszT += sizeof(USHORT);
  1081. memmove(pszT, pEAVal, cbEAVal);
  1082. /* Now call the set file info to set the EA */
  1083. retCode = DosSetFileInfo(fh, 0x2, (void FAR *)&eaop, sizeof(EAOP));
  1084. #if FALSE
  1085. switch (retCode)
  1086. {
  1087. case 0:
  1088. fprintf(stdout, "EA -> Binary set - %s; %d bytes\r\n", pszEAName, cbEAVal);
  1089. break;
  1090. case ERROR_BUFFER_OVERFLOW:
  1091. fprintf(stdout, "Buffer overflow\r\n");
  1092. break;
  1093. case ERROR_DIRECT_ACCESS_HANDLE:
  1094. fprintf(stdout, "Direct access handle\r\n");
  1095. break;
  1096. case ERROR_EA_LIST_INCONSISTENT:
  1097. fprintf(stdout, "EA list inconsistent\r\n");
  1098. break;
  1099. case ERROR_INVALID_EA_NAME:
  1100. fprintf(stdout, "Invalid EA name\r\n");
  1101. break;
  1102. case ERROR_INVALID_HANDLE:
  1103. fprintf(stdout, "Invalid handle\r\n");
  1104. break;
  1105. case ERROR_INVALID_LEVEL:
  1106. fprintf(stdout, "Invalid level\r\n");
  1107. break;
  1108. default:
  1109. fprintf(stdout, "Unknow %d\r\n", retCode);
  1110. break;
  1111. }
  1112. #endif
  1113. return;
  1114. }
  1115. /*** SetFileEAString - set file extended attribute string
  1116. *
  1117. * Purpose:
  1118. * Set file extended attributes for OS/2 1.2 and higher.
  1119. *
  1120. * Input:
  1121. * fh - file handle
  1122. * pszEAName - extended attribute name
  1123. * pszEAVal - extended attribute string
  1124. * bEAFlags - extended attribute flags
  1125. *
  1126. * Output:
  1127. * No explicit value is returned. If succesfull file extended attributes
  1128. * are set, otherwise not.
  1129. *
  1130. * Exceptions:
  1131. * None.
  1132. *
  1133. * Notes:
  1134. * This function allocates quite a bit on stack, so don't remove
  1135. * stack checking pragma.
  1136. *
  1137. *************************************************************************/
  1138. LOCAL void NEAR SetFileEAString(int fh, char *pszEAName,
  1139. char *pszEAVal, WORD bEAFlags)
  1140. {
  1141. BYTE bEABuf[512]; /* Should be enought for linker purposes */
  1142. EAOP eaop;
  1143. WORD cbEAVal;
  1144. char *pszT;
  1145. WORD retCode;
  1146. if (pszEAName == NULL)
  1147. return;
  1148. if (pszEAVal != NULL)
  1149. cbEAVal = strlen(pszEAVal);
  1150. else
  1151. cbEAVal = 0;
  1152. pszT = InitEA(bEABuf, sizeof(bEABuf), pszEAName, &eaop, cbEAVal, bEAFlags);
  1153. if (pszT == NULL)
  1154. return;
  1155. if (pszEAVal != NULL)
  1156. {
  1157. *((USHORT *)pszT) = EAT_ASCII;
  1158. pszT += sizeof(USHORT);
  1159. *((USHORT *)pszT) = cbEAVal;
  1160. pszT += sizeof(USHORT);
  1161. memmove(pszT ,pszEAVal , cbEAVal);
  1162. }
  1163. /* Now call the set path call to set the EA */
  1164. retCode = DosSetFileInfo(fh, 0x2, (void FAR *)&eaop, sizeof(EAOP));
  1165. #if FALSE
  1166. switch (retCode)
  1167. {
  1168. case 0:
  1169. fprintf(stdout, "EA -> String set - %s = '%s'\r\n", pszEAName, pszEAVal);
  1170. break;
  1171. case ERROR_BUFFER_OVERFLOW:
  1172. fprintf(stdout, "Buffer overflow\r\n");
  1173. break;
  1174. case ERROR_DIRECT_ACCESS_HANDLE:
  1175. fprintf(stdout, "Direct access handle\r\n");
  1176. break;
  1177. case ERROR_EA_LIST_INCONSISTENT:
  1178. fprintf(stdout, "EA list inconsistent\r\n");
  1179. break;
  1180. case ERROR_INVALID_EA_NAME:
  1181. fprintf(stdout, "Invalid EA name\r\n");
  1182. break;
  1183. case ERROR_INVALID_HANDLE:
  1184. fprintf(stdout, "Invalid handle\r\n");
  1185. break;
  1186. case ERROR_INVALID_LEVEL:
  1187. fprintf(stdout, "Invalid level\r\n");
  1188. break;
  1189. default:
  1190. fprintf(stdout, "Unknow %d\r\n", retCode);
  1191. break;
  1192. }
  1193. #endif
  1194. return;
  1195. }
  1196. #pragma check_stack(off)
  1197. #endif
  1198. #pragma check_stack(on)
  1199. /*
  1200. * OutRunFile:
  1201. *
  1202. * Top-level routine to outputting executable file. Prepares some,
  1203. * then calls routine to do the work according exe format.
  1204. */
  1205. LOCAL void NEAR OutRunFile(sbRun)
  1206. BYTE *sbRun; /* Executable file name */
  1207. {
  1208. AHTEPTR hte; /* Hash table entry address */
  1209. #if (OSEGEXE AND CPU286) OR EXE386
  1210. #pragma pack(1)
  1211. struct {
  1212. WORD ibm; /* IBM part */
  1213. WORD ms; /* Microsoft part */
  1214. } EAAppType; /* Happy EA's !?! */
  1215. #pragma pack()
  1216. #endif
  1217. #if defined(M_I386) || defined( _WIN32 )
  1218. BYTE *pIOBuf;
  1219. #endif
  1220. CheckSegmentsMemory();
  1221. #if CMDMSDOS
  1222. #if ODOS3EXE
  1223. if(fQlib)
  1224. ValidateRunFileName(sbDotQlb, TRUE, TRUE);
  1225. /* Force extension to .QLB */
  1226. else if (fBinary)
  1227. ValidateRunFileName(sbDotCom, TRUE, TRUE);
  1228. /* Force extension to .COM */
  1229. else
  1230. #endif
  1231. #if OSMSDOS
  1232. /* If runfile is a dynlink library and no runfile extension
  1233. * has been given, force the extension to ".DLL". Issue a
  1234. * warning that the name is being changed.
  1235. */
  1236. if ((vFlags & NENOTP) && (TargetOs == NE_OS2))
  1237. ValidateRunFileName(sbDotDll, TRUE, TRUE);
  1238. else
  1239. #endif /* OSMSDOS */
  1240. ValidateRunFileName(sbDotExe, TRUE, TRUE);
  1241. /* If extension missing add .EXE */
  1242. #endif
  1243. hte = (AHTEPTR ) FetchSym(rhteRunfile,FALSE);
  1244. /* Get run file name */
  1245. #if OSMSDOS
  1246. #if NOT WIN_NT
  1247. if(hte->cch[2] != ':') /* If no drive spec */
  1248. {
  1249. sbRun[1] = chRunFile; /* Use saved drive letter */
  1250. sbRun[2] = ':'; /* Put in colon */
  1251. sbRun[0] = '\002'; /* Set length */
  1252. }
  1253. else
  1254. #endif
  1255. sbRun[0] = '\0'; /* Length is zero */
  1256. memcpy(&sbRun[B2W(sbRun[0]) + 1],&GetFarSb(hte->cch)[1],B2W(hte->cch[0]));
  1257. /* Get name from hash table */
  1258. sbRun[0] += hte->cch[0]; /* Fix length */
  1259. #else
  1260. memcpy(sbRun,GetFarSb(hte->cch),B2W(hte->cch[0]) + 1);
  1261. /* Get name from hash table */
  1262. #endif
  1263. sbRun[B2W(sbRun[0]) + 1] = '\0';
  1264. #if C8_IDE
  1265. if(fC8IDE)
  1266. {
  1267. sprintf(msgBuf, "@I4%s\r\n", sbRun+1);
  1268. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1269. }
  1270. #endif
  1271. if ((bsRunfile = fopen(&sbRun[1],WRBIN)) == NULL)
  1272. Fatal(ER_runopn, &sbRun[1], strerror(errno));
  1273. #if CPU286 AND OSMSDOS
  1274. /* Relative seeking to character devices is prohibited in
  1275. * protect mode (and under API emulation). Since we call fseek
  1276. * later on, if the output file is a character device then just
  1277. * skip the output stage.
  1278. */
  1279. if(isatty(fileno(bsRunfile)))
  1280. return;
  1281. #endif
  1282. #if OSMSDOS
  1283. #if defined(M_I386) || defined( _WIN32 )
  1284. pIOBuf = GetMem(_32k); // Allocate 32k I/O buffer
  1285. setvbuf(bsRunfile,pIOBuf,_IOFBF,_32k);
  1286. #else
  1287. setvbuf(bsRunfile,bigbuf,_IOFBF,sizeof(bigbuf));
  1288. #endif
  1289. #endif
  1290. psbRun = sbRun; /* Set global pointer */
  1291. #if OIAPX286
  1292. OutXenExe();
  1293. #endif
  1294. #if OSEGEXE
  1295. #if EXE386
  1296. OutExe386();
  1297. #else
  1298. if(fNewExe)
  1299. OutSegExe();
  1300. #if ODOS3EXE
  1301. else
  1302. #endif
  1303. #endif
  1304. #endif
  1305. #if ODOS3EXE
  1306. OutDos3Exe();
  1307. #endif
  1308. #if (OSEGEXE AND CPU286)
  1309. if ((_osmode == OS2_MODE && (_osmajor == 1 && _osminor >= 20 || _osmajor >= 2)) ||
  1310. (_osmode == DOS_MODE && _osmajor >= 10))
  1311. {
  1312. /* Set Extended Attributes for .EXE file */
  1313. SetFileEAString(fileno(bsRunfile), ".TYPE", "Executable", 0);
  1314. EAAppType.ibm = 0;
  1315. EAAppType.ms = FAPPTYP_NOTSPEC;
  1316. if (fNewExe)
  1317. {
  1318. #if NOT EXE386
  1319. if (vFlags & NENOTP)
  1320. EAAppType.ms = FAPPTYP_DLL;
  1321. if ((vFlags & NEWINAPI) == NEWINAPI)
  1322. {
  1323. EAAppType.ibm = _AT_PMAPI;
  1324. EAAppType.ms |= FAPPTYP_WINDOWAPI;
  1325. }
  1326. else if (vFlags & NEWINCOMPAT)
  1327. {
  1328. EAAppType.ibm = _AT_PMW;
  1329. EAAppType.ms |= FAPPTYP_WINDOWCOMPAT;
  1330. }
  1331. else if (vFlags & NENOTWINCOMPAT)
  1332. {
  1333. EAAppType.ibm = _AT_NOPMW;
  1334. EAAppType.ms |= FAPPTYP_NOTWINDOWCOMPAT;
  1335. }
  1336. #endif
  1337. }
  1338. else
  1339. {
  1340. EAAppType.ibm = _AT_DOS;
  1341. EAAppType.ms = FAPPTYP_DOS;
  1342. }
  1343. SetFileEABinary(fileno(bsRunfile), ".APPTYPE",
  1344. (BYTE *) &EAAppType, sizeof(EAAppType), 0);
  1345. }
  1346. #endif
  1347. CloseFile(bsRunfile); /* Close run file */
  1348. #if defined(M_I386) || defined( _WIN32 )
  1349. FreeMem(pIOBuf);
  1350. #endif
  1351. #if OSXENIX
  1352. if(!fUndefinedExterns) chmod(&sbRun[1],0775 & ~umask(077));
  1353. /* Set protection executable */
  1354. #endif
  1355. }
  1356. #pragma check_stack(off)
  1357. #if NOT WIN_3
  1358. /*** SpawnOther - spawn any other processes
  1359. *
  1360. * Purpose:
  1361. * Spawn the other processes (i.e. cvpack) necessary to complete the
  1362. * construction of the executible.
  1363. *
  1364. * Input:
  1365. * sbRun - pointer to the name of the executible
  1366. *
  1367. * Output:
  1368. * None.
  1369. *
  1370. * Exceptions:
  1371. * None.
  1372. *
  1373. * Notes:
  1374. * None.
  1375. *
  1376. *************************************************************************/
  1377. LOCAL void NEAR SpawnOther(sbRun, szMyself)
  1378. BYTE *sbRun; /* Executable file name */
  1379. BYTE *szMyself; /* A full LINK path */
  1380. {
  1381. char FAR *env[2]; /* Enviroment for MPC */
  1382. SBTYPE progName; /* Program to invoke after linker */
  1383. SBTYPE progOptions; /* Program options */
  1384. char path_buffer[_MAX_PATH]; /* Stuff for splitpath() */
  1385. char drive[_MAX_DRIVE];
  1386. char dir[_MAX_DIR];
  1387. char fname[_MAX_FNAME];
  1388. char ext[_MAX_EXT];
  1389. intptr_t status;
  1390. if ((
  1391. #if PCODE
  1392. fMPC ||
  1393. #endif
  1394. (fSymdeb && fCVpack)
  1395. #if O68K
  1396. || iMacType != MAC_NONE
  1397. #endif
  1398. ) && !cErrors && !fUndefinedExterns)
  1399. {
  1400. #if FAR_SEG_TABLES
  1401. FreeSymTab();
  1402. #if NOT WIN_NT AND NOT DOSX32
  1403. _fheapmin();
  1404. #endif
  1405. #endif
  1406. #if NOT WIN_NT
  1407. if(lpszPath != NULL)
  1408. {
  1409. FSTRCPY((char FAR *) bufg, lpszPath - 5);
  1410. env[0] = (char FAR *) bufg;
  1411. env[1] = NULL;
  1412. _putenv((char FAR *) bufg);
  1413. }
  1414. #endif
  1415. #if O68K
  1416. if (fMPC || (fSymdeb && fCVpack)) {
  1417. #endif /* O68K */
  1418. progOptions[0] = '\0';
  1419. #if PCODE
  1420. if (fSymdeb && fCVpack && fMPC)
  1421. {
  1422. strcpy(progName, "cvpack");
  1423. strcpy(progOptions, "/pcode");
  1424. }
  1425. else
  1426. strcpy(progName, fMPC ? "mpc" : "cvpack16");
  1427. #else
  1428. strcpy(progName, "cvpack");
  1429. #endif
  1430. #ifndef C8_IDE
  1431. if (fNoBanner)
  1432. #endif
  1433. strcat(progOptions, "/nologo");
  1434. // Now determine which instance of child is to be loaded
  1435. // First - check the LINK directory
  1436. _splitpath(szMyself, drive, dir, fname, ext);
  1437. strcpy(fname, progName);
  1438. _makepath(path_buffer, drive, dir, fname, ext);
  1439. if (_access(path_buffer, 0) != 0) // file not in the LINK dir
  1440. {
  1441. // Second - check the current dir
  1442. drive[0] = '\0';
  1443. _getcwd(dir, _MAX_DIR);
  1444. _makepath(path_buffer, drive, dir, fname, ext);
  1445. if (_access(path_buffer, 0) != 0) // file not in the current dir
  1446. {
  1447. strcpy(path_buffer, progName);// spawn on the PATH
  1448. }
  1449. }
  1450. #if NOT (WIN_NT OR EXE386)
  1451. // If /TINY is active, we are building a .COM file,
  1452. // and the cv info is in a .DBG file
  1453. if (fBinary)
  1454. {
  1455. _splitpath(sbRun+1, drive, dir, fname, ext);
  1456. strcpy(ext, ".DBG");
  1457. _makepath(sbRun+1, drive, dir, fname, ext);
  1458. }
  1459. #endif
  1460. #if WIN_NT OR DOSX32
  1461. if ((status = _spawnlp(P_WAIT, path_buffer, path_buffer, progOptions, &sbRun[1], NULL)) == -1)
  1462. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1463. else if (status != 0)
  1464. cErrors++;
  1465. #else
  1466. if (spawnlpe(
  1467. #if DOSEXTENDER
  1468. (!_fDosExt) ?
  1469. #else
  1470. (_osmode == DOS_MODE && _osmajor < 10) ?
  1471. #endif
  1472. P_OVERLAY : P_WAIT, path_buffer, path_buffer, progOptions, &sbRun[1], NULL, env) == -1)
  1473. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1474. #endif
  1475. #if O68K
  1476. }
  1477. if (iMacType != MAC_NONE) {
  1478. progOptions[0] = '\0';
  1479. strcpy(progName, "link_68k");
  1480. /* Now determine which instance of child is to be loaded */
  1481. /* First - check the LINK directory */
  1482. _splitpath (szMyself, drive, dir, fname, ext);
  1483. strcpy (fname, progName);
  1484. _makepath (path_buffer, drive, dir, fname, ext);
  1485. if (_access (path_buffer, 0) != 0) // file not in the LINK dir
  1486. {
  1487. // Second - check the current dir
  1488. drive[0] = '\0';
  1489. #if (_MSC_VER >= 700)
  1490. _getcwd (0, dir, _MAX_DIR);
  1491. #else
  1492. _getcwd (dir, _MAX_DIR);
  1493. #endif
  1494. _makepath (path_buffer, drive, dir, fname, ext);
  1495. if (_access (path_buffer, 0) != 0) // file not in the current dir
  1496. {
  1497. strcpy (path_buffer, progName); // spawn on the PATH
  1498. }
  1499. }
  1500. if (iMacType == MAC_SWAP)
  1501. strcat(progOptions, "/s ");
  1502. if (fSymdeb)
  1503. strcat(progOptions, "/c ");
  1504. if ((status = spawnlp(P_WAIT, path_buffer, path_buffer,
  1505. progOptions, &sbRun[1], NULL)) == -1)
  1506. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1507. else if (status != 0)
  1508. cErrors++;
  1509. }
  1510. #endif /* O68K */
  1511. }
  1512. }
  1513. #endif
  1514. /****************************************************************
  1515. * *
  1516. * InterPass: *
  1517. * *
  1518. * Take care of miscellaneous items which must be done between *
  1519. * pass 1 and 2. *
  1520. * *
  1521. ****************************************************************/
  1522. LOCAL void NEAR InterPass (void)
  1523. {
  1524. #if OEXE
  1525. if(!fPackSet) packLim = fNewExe ?
  1526. #if EXE386
  1527. CBMAXSEG32 :
  1528. #elif O68K
  1529. (iMacType != MAC_NONE ? LXIVK / 2 :
  1530. LXIVK - 36) :
  1531. #else
  1532. LXIVK - 36 :
  1533. #endif
  1534. 0L;
  1535. #endif
  1536. #if NOT EXE386
  1537. // Set TargetOS - see LINK540 bug #11 for description
  1538. if (fNewExe && TargetOs != NE_OS2)
  1539. {
  1540. // Import/export seen in the OBJ files or .DEF file specified
  1541. #if CPU286
  1542. if(rhteDeffile == RHTENIL) // OS2 host and no .def file - OS2 target
  1543. TargetOs = NE_OS2;
  1544. else
  1545. TargetOs = NE_WINDOWS;
  1546. #else
  1547. TargetOs = NE_WINDOWS;
  1548. #endif
  1549. }
  1550. #endif
  1551. #if ODOS3EXE
  1552. // /DOSSEG (from switch or comment rec) forces off /DS, /NOG
  1553. if (fSegOrder)
  1554. vfDSAlloc = fNoGrpAssoc = FALSE;
  1555. #endif
  1556. #if ILINK
  1557. fQCIncremental = (FTYPE) (!fNewExe && fIncremental);
  1558. /* QC incremental link */
  1559. if (fQCIncremental)
  1560. {
  1561. TargetOs = 0xff; /* Mark .EXE as not compatibile with OS/2 .EXE */
  1562. fNewExe = (FTYPE) TRUE; /* Force to build segemented-executable */
  1563. }
  1564. #endif
  1565. #if ODOS3EXE AND OSEGEXE AND NOT EXE386
  1566. if (fNewExe)
  1567. {
  1568. // Check for invalid options for segmented-executable and ignore them
  1569. if ((vFlags & NENOTP) && cbStack)
  1570. {
  1571. cbStack = 0; // For DLLs ignore STACKSIZE
  1572. OutWarn(ER_ignostksize);
  1573. }
  1574. if (
  1575. #if ILINK
  1576. !fQCIncremental &&
  1577. #endif
  1578. cparMaxAlloc != 0xffff)
  1579. {
  1580. OutWarn(ER_swbadnew, "/HIGH or /CPARMAXALLOC");
  1581. cparMaxAlloc = 0xffff;
  1582. }
  1583. if (vfDSAlloc)
  1584. {
  1585. OutWarn(ER_swbadnew, "/DSALLOCATE");
  1586. vfDSAlloc = FALSE;
  1587. }
  1588. if (fNoGrpAssoc)
  1589. {
  1590. OutWarn(ER_swbadnew, "/NOGROUPASSOCIATION");
  1591. fNoGrpAssoc = FALSE;
  1592. }
  1593. if (fBinary)
  1594. {
  1595. OutWarn(ER_swbadnew, "/TINY");
  1596. fBinary = FALSE;
  1597. }
  1598. #if OVERLAYS
  1599. if (fOverlays)
  1600. {
  1601. OutWarn(ER_swbadnew, "Overlays");
  1602. fOverlays = FALSE;
  1603. }
  1604. #endif
  1605. }
  1606. else
  1607. {
  1608. if(fileAlign != DFSAALIGN)
  1609. OutWarn(ER_swbadold,"/ALIGNMENT");
  1610. #ifdef LEGO
  1611. if (fKeepFixups)
  1612. OutWarn(ER_swbadold, "/KEEPFIXUPS");
  1613. #endif /* LEGO */
  1614. if(fPackData)
  1615. OutWarn(ER_swbadold,"/PACKDATA");
  1616. #if OVERLAYS
  1617. if(fOldOverlay)
  1618. fDynamic= (FTYPE) FALSE;
  1619. else
  1620. fDynamic = fOverlays;
  1621. #endif
  1622. }
  1623. #if NOT QCLINK
  1624. // Check if fixup optimizations are possible
  1625. fOptimizeFixups = (FTYPE) ((TargetOs == NE_OS2 || TargetOs == NE_WINDOWS)
  1626. #if ILINK
  1627. && !fIncremental
  1628. #endif
  1629. #if O68K
  1630. && iMacType == MAC_NONE
  1631. #endif
  1632. );
  1633. #endif
  1634. pfProcFixup = fNewExe ? FixNew : FixOld;
  1635. #ifdef LEGO
  1636. if (fKeepFixups && fNewExe && (vFlags & NEPROT)
  1637. #if ILINK
  1638. && !fIncremental
  1639. #endif
  1640. #if O68K
  1641. && (iMacType == MAC_NONE)
  1642. #endif
  1643. )
  1644. pfProcFixup = FixNewKeep;
  1645. #endif /* LEGO */
  1646. #endif
  1647. /* Since mpsegraFirst was used for something else, clear it. */
  1648. FMEMSET(mpsegraFirst,0, gsnMax * sizeof(RATYPE));
  1649. }
  1650. #if EXE386
  1651. /*
  1652. * ChkSize386 : check 386 program size
  1653. *
  1654. * Made necessary by the way segment mapping is done to VM. See
  1655. * msa386().
  1656. */
  1657. LOCAL void NEAR ChkSize386(void)
  1658. {
  1659. register long *p; /* Pointer to mpsegcb */
  1660. register long *pEnd; /* Pointer to end of mpsegcb */
  1661. register unsigned long cb; /* Byte count */
  1662. /*
  1663. * Check that total size of segments fits within virtual memory
  1664. * area alloted for segments. Note that we DO NOT CHECK FOR
  1665. * ARITHMETIC OVERFLOW. To be strictly correct we should but
  1666. * it will be very rare and the error should be evident elsewhere.
  1667. */
  1668. if (fNewExe)
  1669. {
  1670. p = &mpsacb[1];
  1671. pEnd = &mpsacb[segLast];
  1672. }
  1673. #if ODOS3EXE
  1674. else
  1675. {
  1676. p = &mpsegcb[1];
  1677. pEnd = &mpsegcb[segLast];
  1678. }
  1679. #endif
  1680. for(cb = 0; p <= pEnd; ++p)
  1681. cb += (*p + (PAGLEN - 1)) & ~(PAGLEN - 1);
  1682. /* If size exceeds VM limit, quit with a fatal error. */
  1683. if(cb > (((unsigned long)VPLIB1ST<<LG2PAG)-AREAFSG))
  1684. Fatal(ER_pgmtoobig,(((unsigned long)VPLIB1ST<<LG2PAG)-AREAFSG));
  1685. }
  1686. #endif
  1687. LOCAL void NEAR InitAfterCmd (void)
  1688. {
  1689. #if ILINK
  1690. if (fIncremental && fBinary)
  1691. {
  1692. fIncremental = FALSE;
  1693. OutWarn(ER_tinyincr);
  1694. }
  1695. if (fIncremental && !fPackSet)
  1696. {
  1697. packLim = 0;
  1698. fPackSet = (FTYPE) TRUE;
  1699. }
  1700. #endif
  1701. fFarCallTransSave = fFarCallTrans;
  1702. InitTabs(); /* Initialize dynamic tables */
  1703. #if QBLIB
  1704. if(fQlib) InitQbLib(); /* Initialize QB-Library items */
  1705. #endif
  1706. #if CMDMSDOS
  1707. LibEnv(); /* Process LIB= environment variable */
  1708. #endif
  1709. if(fLstFileOpen && cbStack)
  1710. fprintf(bsLst,"Stack Allocation = %u bytes\r\n",
  1711. (cbStack + 1) & ~1); /* Print stack size */
  1712. }
  1713. /****************************************************************
  1714. * *
  1715. * main: *
  1716. * *
  1717. * The main function. *
  1718. * *
  1719. ****************************************************************/
  1720. #if NOT WIN_3
  1721. void __cdecl main (argc,argv)
  1722. int argc; /* Argument count */
  1723. char **argv; /* Argument list */
  1724. #else
  1725. int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
  1726. #endif
  1727. {
  1728. #if OVERLAYS OR ODOS3EXE
  1729. APROPNAMEPTR apropName; /* Public symbol pointer */
  1730. #endif
  1731. SBTYPE sbRun; /* Executable file name */
  1732. #if NOT WIN_3
  1733. #if !defined( _WIN32 ) AND ( WIN_NT AND !defined(DOSX32) OR USE_REAL )
  1734. int exceptCode;
  1735. _try
  1736. {
  1737. #endif
  1738. /* DLH bsErr can't be statically initialized with the CRT in a DLL */
  1739. bsErr = stderr;
  1740. #if CVPACK_MONDO
  1741. /* check for special cvpack only invocation */
  1742. if (argc > 1 && strcmp(argv[1], "/CvpackOnly") == 0)
  1743. {
  1744. /* we're not linking at all -- just invoke the built in cvpack */
  1745. argv[1] = "cvpack";
  1746. argv++;
  1747. argc--;
  1748. exit(cvpack_main(argc, argv));
  1749. }
  1750. #endif // CVPACK_MONDO
  1751. #if TIMINGS
  1752. ftime(&time_start);
  1753. #endif // TIMINGS
  1754. #if OSEGEXE
  1755. /* HACK ALERT !!! - special check for undocumented /Z1 option */
  1756. if (argc > 1)
  1757. {
  1758. if ((argv[1][0] == CHSWITCH) &&
  1759. ((argv[1][1] == 'Z') || (argv[1][1] == 'z')))
  1760. {
  1761. BYTE option[30];
  1762. option[0] = (BYTE) strlen(argv[1]);
  1763. strcpy(&option[1], argv[1]);
  1764. PeelFlags(option); /* Process /Z1 */
  1765. }
  1766. }
  1767. #endif
  1768. #else // WIN_3 TRUE
  1769. ProcessWinArgs( lpCmdLine );
  1770. #endif // WIN_3
  1771. InitializeWorld(); /* Initialize the linker */
  1772. #if NOT WIN_3
  1773. #if CMDMSDOS
  1774. if (argc <= 1 && !fNoBanner)
  1775. #endif
  1776. DisplayBanner(); /* Display signon banner */
  1777. ParseCmdLine(argc,argv); /* Parse the command line */
  1778. InitAfterCmd(); /* Initialize post-cmd stuff */
  1779. #else // WIN_3 is TRUE
  1780. ParseLinkCmdStr();
  1781. InitAfterCmd(); /* Initialize post-cmd stuff */
  1782. #endif // WIN_3
  1783. #if USE_REAL
  1784. if(IsDosxnt() && IsWin31() && !fSwNoUseReal)
  1785. fUseReal = (FTYPE)MakeConvMemPageable();
  1786. if(fUseReal)
  1787. _onexit( (_onexit_t) RealMemExit );
  1788. #endif
  1789. #if OSEGEXE
  1790. #if FDEBUG AND NOT QCLINK AND NOT WIN_3
  1791. if(fDebug) FmtPrint(GetMsg(P_parsedeffile)); // **** PARSE DEFINITIONS FILE ****\r\n
  1792. #endif
  1793. #if WIN_3
  1794. StatHdrWin(GetMsg(P_lwParseDef));
  1795. #endif
  1796. #if C8_IDE
  1797. if(fC8IDE)
  1798. {
  1799. sprintf(msgBuf, "@I0\r\n");
  1800. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1801. sprintf(msgBuf, "@I1Microsoft (R) Linker Version 5.40\r\n");
  1802. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1803. sprintf(msgBuf, "@I2Copyright (C) Microsoft Corp 1992\r\n");
  1804. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1805. sprintf(msgBuf, "@I3%s\r\n", GetMsg(P_lwParseDef));
  1806. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1807. }
  1808. #endif
  1809. #if NOT QCLINK
  1810. #if NOT EXE386
  1811. if (!fBinary)
  1812. #endif
  1813. ParseDeffile(); /* Parse the definitions file */
  1814. #endif
  1815. #endif
  1816. #if ODOS3EXE
  1817. // If overlays have been specified, but switches /OLDOV /DYN were
  1818. // not present on the command line, set /DYN to ON
  1819. // (dynamic overlays are the default)
  1820. if(fOverlays && !fOldOverlay && !fDynamic)
  1821. {
  1822. fDynamic = TRUE;
  1823. fFarCallTrans = (FTYPE) TRUE;
  1824. fPackSet = (FTYPE) TRUE;
  1825. packLim = LXIVK - 36; /* Default limit is 64K - 36 */
  1826. ovlThunkMax = 256;
  1827. }
  1828. #endif
  1829. fFarCallTransSave = fFarCallTrans;
  1830. if(fDynamic && fExePack)
  1831. {
  1832. fExePack = FALSE;
  1833. OutWarn(ER_dynexep);
  1834. }
  1835. #if WIN_3
  1836. StatHdrWin(GetMsg(P_lwPassOne));
  1837. #endif
  1838. #if C8_IDE
  1839. if(fC8IDE)
  1840. {
  1841. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwPassOne));
  1842. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1843. }
  1844. #endif
  1845. #if FDEBUG
  1846. if(fDebug) FmtPrint(GetMsg(P_passone)); // **** PASS ONE ****\r\n
  1847. #endif
  1848. #if OSMSDOS AND AUTOVM
  1849. CleanupNearHeap();
  1850. #endif
  1851. snkey = 0; /* Initialize for pass 1 */
  1852. modkey = 0; /* Initialize for pass 1 */
  1853. ObjDebTotal = 1;
  1854. ifhLast = FHNIL; /* No files looked at yet */
  1855. #if NEWIO
  1856. /* Allocate a file stream for bsInput with a dummy file handle */
  1857. bsInput = fdopen(0,RDBIN);
  1858. #endif /*NEWIO*/
  1859. #if OSMSDOS
  1860. setvbuf(bsInput,bigbuf,_IOFBF,sizeof(bigbuf));
  1861. #endif
  1862. rprop1stOpenFile = rprop1stFile; /* Remember first open file */
  1863. r1stFile = rprop1stFile; /* which is also first input file */
  1864. vfPass1 = (FTYPE) TRUE; /* Now pass 1 */
  1865. DrivePass(ProcP1); /* Make pass 1 */
  1866. #if OVERLAYS
  1867. // If overlays, make $$OVLINIT or $$MOVEINIT an undefined symbol
  1868. if (fOverlays)
  1869. {
  1870. if (!fOldOverlay)
  1871. {
  1872. if (PropSymLookup("\012$$MOVEINIT",ATTRPNM,FALSE) == PROPNIL)
  1873. PropSymLookup("\012$$MOVEINIT", ATTRUND, TRUE);
  1874. }
  1875. else
  1876. {
  1877. if (PropSymLookup("\011$$OVLINIT",ATTRPNM,FALSE) == PROPNIL)
  1878. PropSymLookup("\011$$OVLINIT", ATTRUND, TRUE);
  1879. }
  1880. }
  1881. #endif
  1882. #if WIN_3
  1883. StatHdrWin(GetMsg(P_lwLibraryS));
  1884. #endif
  1885. #if C8_IDE
  1886. if(fC8IDE)
  1887. {
  1888. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwLibraryS));
  1889. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1890. }
  1891. #endif
  1892. #if FDEBUG
  1893. if(fDebug) FmtPrint(GetMsg(P_libsearch));
  1894. #endif
  1895. #if OSMSDOS AND AUTOVM
  1896. CleanupNearHeap();
  1897. #endif
  1898. #if OEXE
  1899. if (fSegOrder)
  1900. SetDosseg();
  1901. #endif
  1902. LibrarySearch(); /* Search libraries */
  1903. vfPass1 = FALSE; /* No longer pass 1 */
  1904. #if LNKPROF
  1905. if(fP1stop) { FlsStdio(); exit(0); }
  1906. #endif
  1907. InterPass(); /* Do various between-pass tasks */
  1908. #if OSMSDOS AND AUTOVM
  1909. CleanupNearHeap();
  1910. #endif
  1911. #if WIN_3
  1912. StatHdrWin(GetMsg(P_lwAssign));
  1913. #endif
  1914. #if C8_IDE
  1915. if(fC8IDE)
  1916. {
  1917. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwAssign));
  1918. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1919. }
  1920. #endif
  1921. #if FDEBUG
  1922. if(fDebug) FmtPrint(GetMsg(P_assignadd)); /* **** ASSIGN ADDRESSES ****\r\n*/
  1923. #endif
  1924. AllocComDat();
  1925. AssignAddresses(); /* Assign addresses to segments */
  1926. #if SYMDEB
  1927. if (fSymdeb)
  1928. DoComdatDebugging();
  1929. #endif
  1930. if (fFullMap)
  1931. UpdateComdatContrib(
  1932. #if ILINK
  1933. FALSE,
  1934. #endif
  1935. TRUE);
  1936. #if EXE386
  1937. InitVmBase(); /* Set VM object areas base addresses */
  1938. FillInImportTable();
  1939. #endif
  1940. if(fLstFileOpen) /* If list file open */
  1941. {
  1942. #if WIN_3
  1943. StatHdrWin(GetMsg(P_lwMapfile));
  1944. #endif
  1945. #if C8_IDE
  1946. if(fC8IDE)
  1947. {
  1948. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwMapfile));
  1949. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1950. }
  1951. #endif
  1952. #if FDEBUG
  1953. if(fDebug) FmtPrint(GetMsg(P_printmap));/* **** PRINT MAP ****\r\n */
  1954. #endif
  1955. PrintMap(); /* Print load map */
  1956. #if QBLIB
  1957. if(fQlib) PrintQbStart();
  1958. #endif
  1959. }
  1960. #if OSEGEXE AND NOT QCLINK
  1961. if (fNewExe
  1962. #if NOT EXE386 AND ILINK
  1963. && !fQCIncremental
  1964. #endif
  1965. )
  1966. InitEntTab(); /* Initialize the Entry Table */
  1967. #endif
  1968. #if EXE386
  1969. if(f386) ChkSize386(); /* Check program size for 386 */
  1970. #endif
  1971. #if OSEGEXE AND NOT QCLINK
  1972. if (fNewExe
  1973. #if NOT EXE386 AND ILINK
  1974. && !fQCIncremental
  1975. #endif
  1976. )
  1977. InitFP(); /* Initialize floating-point items */
  1978. #endif
  1979. #if OSMSDOS AND AUTOVM
  1980. CleanupNearHeap();
  1981. #endif
  1982. snkey = 0; /* Initialize for pass 2 */
  1983. modkey = 0; /* Initialize for pass 2 */
  1984. ifhLast = FHNIL; /* No files examined on pass 2 yet */
  1985. #if WIN_3
  1986. StatHdrWin(GetMsg(P_lwPassTwo));
  1987. #endif
  1988. #if C8_IDE
  1989. if(fC8IDE)
  1990. {
  1991. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwPassTwo));
  1992. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1993. }
  1994. #endif
  1995. #if FDEBUG
  1996. if(fDebug) FmtPrint(GetMsg(P_passtwo)); /* **** PASS TWO ****\r\n*/
  1997. #endif
  1998. DrivePass(ProcP2); /* Make pass 2 */
  1999. #if OSEGEXE
  2000. if (vpropAppLoader != PROPNIL)
  2001. {
  2002. APROPUNDEFPTR apropUndef;
  2003. apropUndef = (APROPUNDEFPTR) FetchSym(vpropAppLoader, TRUE);
  2004. fUndefinedExterns = fUndefinedExterns || (FTYPE) (apropUndef->au_attr == ATTRUND);
  2005. apropUndef->u.au_rFil = AddVmProp(apropUndef->u.au_rFil, rprop1stFile);
  2006. }
  2007. #endif
  2008. #if ODOS3EXE
  2009. if (fDOSExtended)
  2010. {
  2011. apropName = (APROPNAMEPTR ) PropSymLookup("\017__DOSEXT16_MODE", ATTRPNM, FALSE);
  2012. // Look up public symbol
  2013. if (apropName != PROPNIL)
  2014. {
  2015. if (dosExtMode != 0)
  2016. MoveToVm(sizeof(WORD), (BYTE *) &dosExtMode, mpgsnseg[apropName->an_gsn], apropName->an_ra);
  2017. // Store value
  2018. }
  2019. }
  2020. #endif
  2021. #if OVERLAYS
  2022. if (fOverlays)
  2023. {
  2024. // If there are overlays check if we have an overlay manager
  2025. apropName = (APROPNAMEPTR ) PropSymLookup(fDynamic ? "\012$$MOVEINIT" :
  2026. "\011$$OVLINIT",
  2027. ATTRPNM, FALSE);
  2028. if (apropName != PROPNIL)
  2029. { // If starting point defined
  2030. raStart = apropName->an_ra;// Get offset of entry point
  2031. segStart = mpgsnseg[apropName->an_gsn];
  2032. // Get base number of entry point
  2033. }
  2034. else
  2035. OutError(ER_ovlmnger);
  2036. }
  2037. #endif
  2038. if(fUndefinedExterns) /* If we have unresolved references */
  2039. {
  2040. if(fLstFileOpen && bsLst != stdout)
  2041. { /* If we have a list file */
  2042. NEWLINE(bsLst);
  2043. #if CMDXENIX
  2044. fprintf(bsLst,"%s: ",lnknam);
  2045. /* Linker name */
  2046. #endif
  2047. }
  2048. #if QCLINK
  2049. if (!fZ1)
  2050. #endif
  2051. NEWLINE(stderr);
  2052. EnSyms(PrintAnUndef,ATTRUND); /* Print undefined symbols */
  2053. if(fLstFileOpen && bsLst != stdout)
  2054. NEWLINE(bsLst);
  2055. #if QCLINK
  2056. if (!fZ1)
  2057. #endif
  2058. NEWLINE(stderr);
  2059. }
  2060. #if ILINK
  2061. if (fIncremental)
  2062. {
  2063. OutputIlk(); /* Output .ilk / .sym files */
  2064. }
  2065. #endif /*ILINK*/
  2066. #if FDEBUG
  2067. if(fDebug)
  2068. {
  2069. if( !fDelexe || fDelexe && cErrors==0 )
  2070. {
  2071. FmtPrint(GetMsg(P_writing1)); /* **** WRITING */
  2072. if (fNewExe)
  2073. {
  2074. if (TargetOs == NE_OS2)
  2075. FmtPrint("OS/2");
  2076. else if (TargetOs == NE_WINDOWS)
  2077. FmtPrint("WINDOWS");
  2078. }
  2079. else
  2080. {
  2081. FmtPrint("DOS");
  2082. #if OVERLAYS
  2083. if (fOverlays)
  2084. FmtPrint(GetMsg(P_writing2)); /* - overlaid*/
  2085. #endif
  2086. }
  2087. FmtPrint(GetMsg(P_writing3)); /* EXECUTABLE ****\r\n*/
  2088. #if OVERLAYS
  2089. if (fOverlays && fDynamic)
  2090. FmtPrint(GetMsg(P_overlaycalls), ovlThunkMax, ovlThunkMac);/***** NUMBER OF INTEROVERLAY CALLS: requested %d; generated %d ****\r\n*/
  2091. #endif
  2092. PrintStats();
  2093. #if PROFSYM
  2094. ProfSym(); /* Profile symbol table */
  2095. #endif
  2096. }
  2097. else // some errors occured
  2098. {
  2099. FmtPrint(GetMsg(P_noexe));
  2100. }
  2101. }
  2102. #endif /* FDEBUG */
  2103. if( !fDelexe || fDelexe && cErrors==0 )
  2104. {
  2105. #if WIN_3
  2106. StatHdrWin(GetMsg(P_lwExecutable));
  2107. #endif
  2108. #if C8_IDE
  2109. if(fC8IDE)
  2110. {
  2111. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwExecutable));
  2112. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  2113. }
  2114. #endif
  2115. #if OSMSDOS
  2116. if (chRunFile >= 'a' && chRunFile <= 'z')
  2117. chRunFile += (BYTE) ('A' - 'a');
  2118. /* Make drive letter upper case */
  2119. if(fPauseRun && FCHGDSK(chRunFile - 'A'))
  2120. {
  2121. if(fLstFileOpen && chListFile == (BYTE) (chRunFile - 'A'))
  2122. { /* If map on EXE drive */
  2123. fclose(bsLst); /* Close the list file */
  2124. fLstFileOpen = FALSE; /* Set flag accordingly */
  2125. }
  2126. (*pfPrompt)(NULL,P_genexe,(int) NULL,P_ChangeDiskette,chRunFile);
  2127. }
  2128. else
  2129. fPauseRun = FALSE;
  2130. #endif
  2131. if(fLstFileOpen && bsLst != stdout)
  2132. {
  2133. fclose(bsLst);
  2134. fLstFileOpen = FALSE;
  2135. }
  2136. fclose(bsInput); /* Close input file */
  2137. #if NOT EXE386
  2138. if (fExePack && fNewExe && (TargetOs == NE_WINDOWS))
  2139. {
  2140. OutWarn(ER_exepack);
  2141. fExePack = FALSE;
  2142. }
  2143. #endif
  2144. OutRunFile(sbRun); /* Output executable file */
  2145. CleanUp(); /* Mop up after itself */
  2146. #ifdef PENTER_PROFILE
  2147. saveEntries();
  2148. #endif
  2149. #if OWNSTDIO
  2150. FlsStdio();
  2151. #endif
  2152. #if TIMINGS
  2153. if (fShowTiming) // check if we started the timer...
  2154. {
  2155. char buf[80];
  2156. int hundr;
  2157. time_t td;
  2158. ftime(&time_end);
  2159. td = time_end.time - time_start.time;
  2160. hundr = (time_end.millitm - time_start.millitm)/10;
  2161. td = td*100 + hundr;
  2162. sprintf(buf, "Linker phase: %d.%02ds\r\n", td/100, td%100);
  2163. _write(fileno(stdout), buf, strlen(buf));
  2164. time_start = time_end;
  2165. }
  2166. #endif // TIMINGS
  2167. #if NOT WIN_3
  2168. #ifndef CVPACK_MONDO
  2169. SpawnOther(sbRun, argv[0]);
  2170. #else
  2171. if (fSymdeb && fCVpack && !cErrors && !fUndefinedExterns)
  2172. {
  2173. char drive[_MAX_DRIVE];
  2174. char dir[_MAX_DIR];
  2175. char fname[_MAX_FNAME];
  2176. int argcT = 0;
  2177. char *argvT[5];
  2178. argvT[argcT++] = "cvpack";
  2179. argvT[argcT++] = "/nologo";
  2180. if (fMPC)
  2181. argvT[argcT++] = "/pcode";
  2182. sbRun[sbRun[0]+1] = '\0'; // NUL terminate
  2183. // If /TINY is active, we are building a .COM file,
  2184. // and the cv info is in a .DBG file
  2185. if (fBinary)
  2186. {
  2187. _splitpath(sbRun+1, drive, dir, fname, NULL);
  2188. _makepath(sbRun+1, drive, dir, fname, ".DBG");
  2189. }
  2190. argvT[argcT++] = sbRun+1;
  2191. argvT[argcT] = NULL;
  2192. fflush(stderr);
  2193. fflush(stdout);
  2194. _setmode(1,_O_TEXT);
  2195. _setmode(2,_O_TEXT);
  2196. #if FAR_SEG_TABLES
  2197. FreeSymTab();
  2198. #if NOT WIN_NT AND NOT DOSX32
  2199. _fheapmin();
  2200. #endif
  2201. #endif
  2202. cvpack_main(argcT, argvT);
  2203. }
  2204. else if (fMPC)
  2205. SpawnOther(sbRun, argv[0]); // we'll be running MPC
  2206. #endif
  2207. #if TIMINGS
  2208. if (fShowTiming) // check if we started the timer...
  2209. {
  2210. char buf[80];
  2211. int hundr;
  2212. time_t td;
  2213. ftime(&time_end);
  2214. td = time_end.time - time_start.time;
  2215. hundr = (time_end.millitm - time_start.millitm)/10;
  2216. td = td*100 + hundr;
  2217. sprintf(buf, "Cvpack phase: %d.%02ds\r\n", td/100, td%100);
  2218. _write(fileno(stdout), buf, strlen(buf));
  2219. time_start = time_end;
  2220. }
  2221. #endif // TIMINGS
  2222. #endif
  2223. }
  2224. fflush(stdout);
  2225. fflush(stderr);
  2226. #if USE_REAL
  2227. RealMemExit();
  2228. #endif
  2229. EXIT((cErrors || fUndefinedExterns)? 2: 0);
  2230. #if !defined( _WIN32 ) AND ( WIN_NT AND !defined(DOSX32) OR USE_REAL )
  2231. }
  2232. _except (1)
  2233. {
  2234. #if USE_REAL
  2235. RealMemExit();
  2236. #endif
  2237. exceptCode = _exception_code();
  2238. if (exceptCode == EXCEPTION_ACCESS_VIOLATION)
  2239. {
  2240. fprintf(stdout, "\r\nLINK : fatal error L5000 : internal failure - access violation ");
  2241. fflush(stdout);
  2242. }
  2243. else if (exceptCode == EXCEPTION_DATATYPE_MISALIGNMENT)
  2244. {
  2245. fprintf(stdout, "\r\nLINK : fatal error L5001 : internal failure - datatype misalignment ");
  2246. fflush(stdout);
  2247. }
  2248. else
  2249. CtrlC();
  2250. }
  2251. #endif
  2252. }