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.

2523 lines
74 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. if (fseek(bsInput,lfa - lfaLast,1))
  731. Fatal(ER_opnobj,&sbInput[1]);
  732. else
  733. if (fseek(bsInput,lfa,0))
  734. Fatal(ER_opnobj,&sbInput[1]);
  735. }
  736. else
  737. #endif
  738. if(fLibraryFile || !vfPass1)
  739. if (fseek(bsInput,lfa,0)) /* Seek to desired offset */
  740. Fatal(ER_opnobj,&sbInput[1]);
  741. lfaLast = lfa; /* Update current file position */
  742. (*pProcessPass)(); /* Call ProcP1 or ProcP2 */
  743. ifhLast = ifh; /* Save this file handle */
  744. if(!fLibraryFile) /* If not a library */
  745. {
  746. #if NEWIO
  747. apropFile = (APROPFILEPTR) FetchSym(vrpropFile,TRUE);
  748. if(vfPass1)
  749. apropFile->af_fh = fileno(bsInput);
  750. else
  751. {
  752. _close(fileno(bsInput));
  753. apropFile->af_fh = 0;
  754. }
  755. #else
  756. fclose(bsInput); /* Close input file */
  757. #endif
  758. }
  759. #if NEWIO
  760. rbFilePrev = vrpropFile;
  761. #endif
  762. }
  763. #if NEWIO
  764. if(!vfPass1) /* Free up file stream on pass two */
  765. #else
  766. if(ifh != FHNIL && !vfPass1) // Close libraries on pass two
  767. #endif
  768. {
  769. for (i = 0; i < ifhLibMac; i++)
  770. {
  771. if (mpifhfh[i])
  772. {
  773. _close(mpifhfh[i]);
  774. mpifhfh[i] = 0;
  775. }
  776. }
  777. }
  778. fDrivePass = FALSE; /* No longer executing DrivePass */
  779. }
  780. /****************************************************************
  781. * *
  782. * PrintAnUndef: *
  783. * *
  784. * This function will print the name of an undefined symbol *
  785. * and the name(s) of the module(s) in which it is referenced. *
  786. * This routine is passed as an argument to EnSyms(). *
  787. * *
  788. ****************************************************************/
  789. LOCAL void PrintAnUndef(prop,rhte,rprop,fNewHte)
  790. APROPNAMEPTR prop; /* Pointer to undef prop cell */
  791. RBTYPE rprop; /* Virt addr of prop cell */
  792. RBTYPE rhte; /* Virt addr of hash tab ent */
  793. WORD fNewHte; /* True if name has been written */
  794. {
  795. APROPUNDEFPTR propUndef;
  796. AHTEPTR hte; /* Pointer to hash table entry */
  797. WORD x;
  798. MSGTYPE errKind;
  799. PLTYPE FAR * entry;
  800. char *puname;
  801. char *substitute;
  802. SBTYPE testName;
  803. SBTYPE undecorUndef;
  804. SBTYPE undecorSubst;
  805. propUndef = (APROPUNDEFPTR) prop;
  806. if (((propUndef->au_flags & WEAKEXT) && !(propUndef->au_flags & UNDECIDED)) ||
  807. !propUndef->u.au_rFil)
  808. return; // Don't print "weak" externs or
  809. // undefined exports
  810. hte = (AHTEPTR ) FetchSym(rhte,FALSE);
  811. /* Fetch symbol from hash table */
  812. puname = GetFarSb(hte->cch);
  813. substitute = NULL;
  814. if (propUndef->au_flags & SUBSTITUTE)
  815. {
  816. substitute = puname;
  817. puname = GetPropName(FetchSym(propUndef->au_Default, FALSE));
  818. }
  819. ++cErrors; /* Increment error count */
  820. hte = (AHTEPTR ) FetchSym(rhte,FALSE);
  821. /* Fetch symbol from hash table */
  822. errKind = ER_UnresExtern;
  823. #if WIN_3
  824. fSeverity = SEV_ERROR;
  825. #endif
  826. // Check here for calling convention mismatch
  827. if (puname[1] == '@' || puname[1] == '_')
  828. {
  829. strcpy(testName, puname);
  830. if (testName[1] == '@')
  831. testName[1] = '_';
  832. else
  833. testName[1] = '@';
  834. // Check for fast-call/C-call mismatch
  835. if (PropSymLookup(testName, ATTRPNM, FALSE) != PROPNIL)
  836. errKind = ER_callmis;
  837. else
  838. {
  839. // Check for Pascal/fast-call or C-call mismatch
  840. for (x = 1; x < testName[0]; x++)
  841. testName[x] = (BYTE) toupper(testName[x + 1]);
  842. testName[0]--;
  843. if (PropSymLookup(testName, ATTRPNM, FALSE) != PROPNIL)
  844. errKind = ER_callmis;
  845. }
  846. }
  847. // Undecorate names if necessary
  848. if (puname[1] == '?')
  849. {
  850. UndecorateSb(puname, undecorUndef, sizeof(undecorUndef));
  851. puname = undecorUndef;
  852. }
  853. if (substitute && substitute[1] == '?')
  854. {
  855. UndecorateSb(substitute, undecorSubst, sizeof(undecorSubst));
  856. substitute = undecorSubst;
  857. }
  858. // Walk the list of file references to this symbol
  859. entry = propUndef->u.au_rFil;
  860. vrpropFile = 0;
  861. do
  862. {
  863. if (vrpropFile != entry->pl_rprop)
  864. vrpropFile = entry->pl_rprop;/* Set the file pointer */
  865. else
  866. {
  867. entry = entry->pl_next; /* Advance the list pointer */
  868. continue;
  869. }
  870. if(fLstFileOpen && bsLst != stdout)
  871. { /* If listing but not to console */
  872. #if QCLINK
  873. if (fZ1)
  874. {
  875. fZ1 = FALSE; // Restore normal linker print function
  876. OutFileCur(bsLst); // Output file name
  877. fZ1 = (FTYPE) TRUE; // Restore QC call-back
  878. }
  879. else
  880. #endif
  881. {
  882. #if WIN_3
  883. APROPFILEPTR apropFile; /* Pointer to file property cell */
  884. AHTEPTR ahte; /* Pointer symbol name */
  885. SBTYPE sb; /* String buffer */
  886. int n; /* String length counter */
  887. apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,FALSE);
  888. ahte = GetHte(vrpropFile);
  889. for(n = B2W(ahte->cch[0]), sb[n+1] = 0; n >= 0; sb[n] = ahte->cch[n], --n);
  890. fprintf(bsLst, sb+1);
  891. #else
  892. OutFileCur(bsLst); /* Output file name */
  893. #endif
  894. }
  895. }
  896. OutFileCur(stderr); /* Output file name */
  897. if(fLstFileOpen && bsLst != stdout)
  898. { /* If listing but not to console */
  899. #if MSGMOD
  900. fprintf(bsLst, " : %s %c%04d: ",
  901. __NMSG_TEXT(N_error), 'L', ER_UnresExtern);
  902. fprintf(bsLst, GetMsg(errKind), &puname[1]);
  903. if (substitute)
  904. fprintf(bsLst, GetMsg(ER_UnresExtra), &substitute[1]);
  905. #else
  906. fprintf(bsLst, " : error: ");
  907. fprintf(bsLst, GetMsg(errKind), &puname[1]);
  908. #endif
  909. }
  910. #if MSGMOD
  911. FmtPrint(" : %s %c%04d: ", __NMSG_TEXT(N_error), 'L', errKind);
  912. FmtPrint(GetMsg(errKind), &puname[1]);
  913. if (substitute)
  914. FmtPrint(GetMsg(ER_UnresExtra), &substitute[1]);
  915. #else
  916. FmtPrint(" : error: ");
  917. FmtPrint(GetMsg(errKind), &puname[1]);
  918. #endif
  919. entry = entry->pl_next; /* Advance the list pointer */
  920. } while(entry != NULL);
  921. }
  922. #if OSEGEXE AND NOT QCLINK
  923. LOCAL void NEAR InitFpSym(sb, flags)
  924. BYTE * sb;
  925. BYTE flags;
  926. {
  927. APROPNAMEPTR aprop;
  928. /* If symbol exists as EXTDEF, convert to PUBDEF */
  929. aprop = (APROPNAMEPTR ) PropSymLookup(sb,ATTRUND,FALSE);
  930. if(aprop != PROPNIL)
  931. {
  932. aprop->an_attr = ATTRPNM;
  933. aprop->an_gsn = 0;
  934. aprop->an_ra = 0;
  935. aprop->an_ggr = 0;
  936. aprop->an_flags = 0;
  937. }
  938. /* Otherwise, if it exists as a PUBDEF, get it else quit */
  939. else
  940. {
  941. aprop = (APROPNAMEPTR) PropSymLookup(sb,ATTRPNM,FALSE);
  942. if(aprop == PROPNIL)
  943. return;
  944. }
  945. aprop->an_flags |= flags;
  946. MARKVP();
  947. }
  948. /*
  949. * InitFP
  950. *
  951. * Initialize table for processing floating-point fixups for new-format
  952. * executables.
  953. */
  954. LOCAL void NEAR InitFP ()
  955. {
  956. InitFpSym((BYTE *) "\006FIARQQ", 1 << FFPSHIFT);
  957. InitFpSym((BYTE *) "\006FISRQQ", 2 << FFPSHIFT);
  958. InitFpSym((BYTE *) "\006FICRQQ", 3 << FFPSHIFT);
  959. InitFpSym((BYTE *) "\006FIERQQ", 4 << FFPSHIFT);
  960. InitFpSym((BYTE *) "\006FIDRQQ", 5 << FFPSHIFT);
  961. InitFpSym((BYTE *) "\006FIWRQQ", 6 << FFPSHIFT);
  962. InitFpSym((BYTE *) "\006FJARQQ", FFP2ND);
  963. InitFpSym((BYTE *) "\006FJSRQQ", FFP2ND);
  964. InitFpSym((BYTE *) "\006FJCRQQ", FFP2ND);
  965. }
  966. #endif /* OSEGEXE AND NOT QCLINK */
  967. #if (OSEGEXE AND CPU286)
  968. /* until the 16 bit bsedos.h supports these definitions: */
  969. #define FAPPTYP_NOTSPEC 0x0000
  970. #define FAPPTYP_NOTWINDOWCOMPAT 0x0001
  971. #define FAPPTYP_WINDOWCOMPAT 0x0002
  972. #define FAPPTYP_WINDOWAPI 0x0003
  973. #define FAPPTYP_BOUND 0x0008
  974. #define FAPPTYP_DLL 0x0010
  975. #define FAPPTYP_DOS 0x0020
  976. #define FAPPTYP_PHYSDRV 0x0040 /* physical device driver */
  977. #define FAPPTYP_VIRTDRV 0x0080 /* virtual device driver */
  978. #define FAPPTYP_PROTDLL 0x0100 /* 'protected memory' dll */
  979. /* I added these definitions: */
  980. #define _FAPPTYP_32BIT 0x4000
  981. #define _FAPPTYP_EXETYPE FAPPTYP_WINDOWAPI
  982. /*-----------------------------------------------------------*/
  983. /* from cruiser DCR 1117: */
  984. /*
  985. * PM Program PM (0x0)
  986. * DOS DOSFS (0x1)
  987. * OS/2 or FAPI Window Compatible OS2W (0x2)
  988. * OS/2 or FAPI Non-Window Compatible OS2FS (0x3)
  989. */
  990. #define _AT_PMAPI 0x00 /* Uses PM API */
  991. #define _AT_DOS 0x01 /* DOS APP */
  992. #define _AT_PMW 0x02 /* Window compatible */
  993. #define _AT_NOPMW 0x03 /* Not Window compatible */
  994. #define _AT_EXETYPE 0x03 /* EXE type mask */
  995. /*** InitEA - initialize buffer describing extended attribute
  996. *
  997. * Purpose:
  998. * Initialize EA buffer by coping its name and setting up the FEALIST.
  999. *
  1000. * Input:
  1001. * pEABuf - pointer to EA buffer
  1002. * cbBuf - size of EA buffer
  1003. * pszEAName - extended attribute name
  1004. * peaop - pointer to EA operand
  1005. * cbEAVal - size of extended attribute value
  1006. * bEAFlags - extended attribute flags
  1007. *
  1008. * Output:
  1009. * Pointer to the place where the EA value should be copied into EA buffer
  1010. *
  1011. * Exceptions:
  1012. * None.
  1013. *
  1014. * Notes:
  1015. * None.
  1016. *
  1017. *************************************************************************/
  1018. LOCAL BYTE * NEAR InitEA(BYTE *pEABuf, WORD cbBuf, char *pszEAName,
  1019. EAOP *peaop, WORD cbEAVal, WORD bEAFlags)
  1020. {
  1021. WORD cbFEAList;
  1022. FEALIST *pfeaList;
  1023. WORD cbEAName;
  1024. BYTE *pszT;
  1025. cbEAName = strlen(pszEAName);
  1026. cbFEAList = sizeof(FEALIST) + 1 + cbEAName + cbEAVal + 2*sizeof(USHORT);
  1027. if (cbFEAList > cbBuf)
  1028. return(NULL);
  1029. pfeaList = (FEALIST *) pEABuf;
  1030. /* First initialize the EAOP structure */
  1031. peaop->fpGEAList = NULL; /* Not used for sets */
  1032. peaop->fpFEAList = (PFEALIST)pfeaList;
  1033. /* Now initialize the FEAList */
  1034. pfeaList->cbList = cbFEAList;
  1035. pfeaList->list[0].fEA = (BYTE) bEAFlags;
  1036. pfeaList->list[0].cbName = (unsigned char) cbEAName;
  1037. pfeaList->list[0].cbValue = cbEAVal + 2*sizeof(USHORT);
  1038. pszT = (char *) pfeaList + sizeof(FEALIST);
  1039. strcpy(pszT, pszEAName);
  1040. pszT += cbEAName + 1;
  1041. return(pszT);
  1042. }
  1043. #pragma check_stack(on)
  1044. /*** SetFileEABinary - set file extended attribute binary value
  1045. *
  1046. * Purpose:
  1047. * Set file extended attributes for OS/2 1.2 and higher.
  1048. *
  1049. * Input:
  1050. * fh - file handle
  1051. * pszEAName - extended attribute name
  1052. * EAVal - extended attribute value
  1053. * bEAFlags - extended attribute flags
  1054. *
  1055. * Output:
  1056. * No explicit value is returned. If succesfull file extended attributes
  1057. * are set, otherwise not.
  1058. *
  1059. * Exceptions:
  1060. * None.
  1061. *
  1062. * Notes:
  1063. * This function allocates quite a bit on stack, so don't remove
  1064. * stack checking pragma.
  1065. *
  1066. *************************************************************************/
  1067. LOCAL void NEAR SetFileEABinary(int fh, char *pszEAName,
  1068. BYTE *pEAVal, USHORT cbEAVal,
  1069. WORD bEAFlags)
  1070. {
  1071. BYTE bEABuf[512]; /* Should be enought for linker purposes */
  1072. EAOP eaop;
  1073. BYTE *pszT;
  1074. WORD retCode;
  1075. if (pszEAName == NULL || cbEAVal > sizeof(bEABuf))
  1076. return;
  1077. pszT = InitEA(bEABuf, sizeof(bEABuf), pszEAName, &eaop, cbEAVal, bEAFlags);
  1078. if (pszT == NULL)
  1079. return;
  1080. *((USHORT *)pszT) = EAT_BINARY;
  1081. pszT += sizeof(USHORT);
  1082. *((USHORT *)pszT) = cbEAVal;
  1083. pszT += sizeof(USHORT);
  1084. memmove(pszT, pEAVal, cbEAVal);
  1085. /* Now call the set file info to set the EA */
  1086. retCode = DosSetFileInfo(fh, 0x2, (void FAR *)&eaop, sizeof(EAOP));
  1087. #if FALSE
  1088. switch (retCode)
  1089. {
  1090. case 0:
  1091. fprintf(stdout, "EA -> Binary set - %s; %d bytes\r\n", pszEAName, cbEAVal);
  1092. break;
  1093. case ERROR_BUFFER_OVERFLOW:
  1094. fprintf(stdout, "Buffer overflow\r\n");
  1095. break;
  1096. case ERROR_DIRECT_ACCESS_HANDLE:
  1097. fprintf(stdout, "Direct access handle\r\n");
  1098. break;
  1099. case ERROR_EA_LIST_INCONSISTENT:
  1100. fprintf(stdout, "EA list inconsistent\r\n");
  1101. break;
  1102. case ERROR_INVALID_EA_NAME:
  1103. fprintf(stdout, "Invalid EA name\r\n");
  1104. break;
  1105. case ERROR_INVALID_HANDLE:
  1106. fprintf(stdout, "Invalid handle\r\n");
  1107. break;
  1108. case ERROR_INVALID_LEVEL:
  1109. fprintf(stdout, "Invalid level\r\n");
  1110. break;
  1111. default:
  1112. fprintf(stdout, "Unknow %d\r\n", retCode);
  1113. break;
  1114. }
  1115. #endif
  1116. return;
  1117. }
  1118. /*** SetFileEAString - set file extended attribute string
  1119. *
  1120. * Purpose:
  1121. * Set file extended attributes for OS/2 1.2 and higher.
  1122. *
  1123. * Input:
  1124. * fh - file handle
  1125. * pszEAName - extended attribute name
  1126. * pszEAVal - extended attribute string
  1127. * bEAFlags - extended attribute flags
  1128. *
  1129. * Output:
  1130. * No explicit value is returned. If succesfull file extended attributes
  1131. * are set, otherwise not.
  1132. *
  1133. * Exceptions:
  1134. * None.
  1135. *
  1136. * Notes:
  1137. * This function allocates quite a bit on stack, so don't remove
  1138. * stack checking pragma.
  1139. *
  1140. *************************************************************************/
  1141. LOCAL void NEAR SetFileEAString(int fh, char *pszEAName,
  1142. char *pszEAVal, WORD bEAFlags)
  1143. {
  1144. BYTE bEABuf[512]; /* Should be enought for linker purposes */
  1145. EAOP eaop;
  1146. WORD cbEAVal;
  1147. char *pszT;
  1148. WORD retCode;
  1149. if (pszEAName == NULL)
  1150. return;
  1151. if (pszEAVal != NULL)
  1152. cbEAVal = strlen(pszEAVal);
  1153. else
  1154. cbEAVal = 0;
  1155. pszT = InitEA(bEABuf, sizeof(bEABuf), pszEAName, &eaop, cbEAVal, bEAFlags);
  1156. if (pszT == NULL)
  1157. return;
  1158. if (pszEAVal != NULL)
  1159. {
  1160. *((USHORT *)pszT) = EAT_ASCII;
  1161. pszT += sizeof(USHORT);
  1162. *((USHORT *)pszT) = cbEAVal;
  1163. pszT += sizeof(USHORT);
  1164. memmove(pszT ,pszEAVal , cbEAVal);
  1165. }
  1166. /* Now call the set path call to set the EA */
  1167. retCode = DosSetFileInfo(fh, 0x2, (void FAR *)&eaop, sizeof(EAOP));
  1168. #if FALSE
  1169. switch (retCode)
  1170. {
  1171. case 0:
  1172. fprintf(stdout, "EA -> String set - %s = '%s'\r\n", pszEAName, pszEAVal);
  1173. break;
  1174. case ERROR_BUFFER_OVERFLOW:
  1175. fprintf(stdout, "Buffer overflow\r\n");
  1176. break;
  1177. case ERROR_DIRECT_ACCESS_HANDLE:
  1178. fprintf(stdout, "Direct access handle\r\n");
  1179. break;
  1180. case ERROR_EA_LIST_INCONSISTENT:
  1181. fprintf(stdout, "EA list inconsistent\r\n");
  1182. break;
  1183. case ERROR_INVALID_EA_NAME:
  1184. fprintf(stdout, "Invalid EA name\r\n");
  1185. break;
  1186. case ERROR_INVALID_HANDLE:
  1187. fprintf(stdout, "Invalid handle\r\n");
  1188. break;
  1189. case ERROR_INVALID_LEVEL:
  1190. fprintf(stdout, "Invalid level\r\n");
  1191. break;
  1192. default:
  1193. fprintf(stdout, "Unknow %d\r\n", retCode);
  1194. break;
  1195. }
  1196. #endif
  1197. return;
  1198. }
  1199. #pragma check_stack(off)
  1200. #endif
  1201. #pragma check_stack(on)
  1202. /*
  1203. * OutRunFile:
  1204. *
  1205. * Top-level routine to outputting executable file. Prepares some,
  1206. * then calls routine to do the work according exe format.
  1207. */
  1208. LOCAL void NEAR OutRunFile(sbRun)
  1209. BYTE *sbRun; /* Executable file name */
  1210. {
  1211. AHTEPTR hte; /* Hash table entry address */
  1212. #if (OSEGEXE AND CPU286) OR EXE386
  1213. #pragma pack(1)
  1214. struct {
  1215. WORD ibm; /* IBM part */
  1216. WORD ms; /* Microsoft part */
  1217. } EAAppType; /* Happy EA's !?! */
  1218. #pragma pack()
  1219. #endif
  1220. #if defined(M_I386) || defined( _WIN32 )
  1221. BYTE *pIOBuf;
  1222. #endif
  1223. CheckSegmentsMemory();
  1224. #if CMDMSDOS
  1225. #if ODOS3EXE
  1226. if(fQlib)
  1227. ValidateRunFileName(sbDotQlb, TRUE, TRUE);
  1228. /* Force extension to .QLB */
  1229. else if (fBinary)
  1230. ValidateRunFileName(sbDotCom, TRUE, TRUE);
  1231. /* Force extension to .COM */
  1232. else
  1233. #endif
  1234. #if OSMSDOS
  1235. /* If runfile is a dynlink library and no runfile extension
  1236. * has been given, force the extension to ".DLL". Issue a
  1237. * warning that the name is being changed.
  1238. */
  1239. if ((vFlags & NENOTP) && (TargetOs == NE_OS2))
  1240. ValidateRunFileName(sbDotDll, TRUE, TRUE);
  1241. else
  1242. #endif /* OSMSDOS */
  1243. ValidateRunFileName(sbDotExe, TRUE, TRUE);
  1244. /* If extension missing add .EXE */
  1245. #endif
  1246. hte = (AHTEPTR ) FetchSym(rhteRunfile,FALSE);
  1247. /* Get run file name */
  1248. #if OSMSDOS
  1249. #if NOT WIN_NT
  1250. if(hte->cch[2] != ':') /* If no drive spec */
  1251. {
  1252. sbRun[1] = chRunFile; /* Use saved drive letter */
  1253. sbRun[2] = ':'; /* Put in colon */
  1254. sbRun[0] = '\002'; /* Set length */
  1255. }
  1256. else
  1257. #endif
  1258. sbRun[0] = '\0'; /* Length is zero */
  1259. memcpy(&sbRun[B2W(sbRun[0]) + 1],&GetFarSb(hte->cch)[1],B2W(hte->cch[0]));
  1260. /* Get name from hash table */
  1261. sbRun[0] += hte->cch[0]; /* Fix length */
  1262. #else
  1263. memcpy(sbRun,GetFarSb(hte->cch),B2W(hte->cch[0]) + 1);
  1264. /* Get name from hash table */
  1265. #endif
  1266. sbRun[B2W(sbRun[0]) + 1] = '\0';
  1267. #if C8_IDE
  1268. if(fC8IDE)
  1269. {
  1270. sprintf(msgBuf, "@I4%s\r\n", sbRun+1);
  1271. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1272. }
  1273. #endif
  1274. if ((bsRunfile = fopen(&sbRun[1],WRBIN)) == NULL)
  1275. Fatal(ER_runopn, &sbRun[1], strerror(errno));
  1276. #if CPU286 AND OSMSDOS
  1277. /* Relative seeking to character devices is prohibited in
  1278. * protect mode (and under API emulation). Since we call fseek
  1279. * later on, if the output file is a character device then just
  1280. * skip the output stage.
  1281. */
  1282. if(isatty(fileno(bsRunfile)))
  1283. return;
  1284. #endif
  1285. #if OSMSDOS
  1286. #if defined(M_I386) || defined( _WIN32 )
  1287. pIOBuf = GetMem(_32k); // Allocate 32k I/O buffer
  1288. setvbuf(bsRunfile,pIOBuf,_IOFBF,_32k);
  1289. #else
  1290. setvbuf(bsRunfile,bigbuf,_IOFBF,sizeof(bigbuf));
  1291. #endif
  1292. #endif
  1293. psbRun = sbRun; /* Set global pointer */
  1294. #if OIAPX286
  1295. OutXenExe();
  1296. #endif
  1297. #if OSEGEXE
  1298. #if EXE386
  1299. OutExe386();
  1300. #else
  1301. if(fNewExe)
  1302. OutSegExe();
  1303. #if ODOS3EXE
  1304. else
  1305. #endif
  1306. #endif
  1307. #endif
  1308. #if ODOS3EXE
  1309. OutDos3Exe();
  1310. #endif
  1311. #if (OSEGEXE AND CPU286)
  1312. if ((_osmode == OS2_MODE && (_osmajor == 1 && _osminor >= 20 || _osmajor >= 2)) ||
  1313. (_osmode == DOS_MODE && _osmajor >= 10))
  1314. {
  1315. /* Set Extended Attributes for .EXE file */
  1316. SetFileEAString(fileno(bsRunfile), ".TYPE", "Executable", 0);
  1317. EAAppType.ibm = 0;
  1318. EAAppType.ms = FAPPTYP_NOTSPEC;
  1319. if (fNewExe)
  1320. {
  1321. #if NOT EXE386
  1322. if (vFlags & NENOTP)
  1323. EAAppType.ms = FAPPTYP_DLL;
  1324. if ((vFlags & NEWINAPI) == NEWINAPI)
  1325. {
  1326. EAAppType.ibm = _AT_PMAPI;
  1327. EAAppType.ms |= FAPPTYP_WINDOWAPI;
  1328. }
  1329. else if (vFlags & NEWINCOMPAT)
  1330. {
  1331. EAAppType.ibm = _AT_PMW;
  1332. EAAppType.ms |= FAPPTYP_WINDOWCOMPAT;
  1333. }
  1334. else if (vFlags & NENOTWINCOMPAT)
  1335. {
  1336. EAAppType.ibm = _AT_NOPMW;
  1337. EAAppType.ms |= FAPPTYP_NOTWINDOWCOMPAT;
  1338. }
  1339. #endif
  1340. }
  1341. else
  1342. {
  1343. EAAppType.ibm = _AT_DOS;
  1344. EAAppType.ms = FAPPTYP_DOS;
  1345. }
  1346. SetFileEABinary(fileno(bsRunfile), ".APPTYPE",
  1347. (BYTE *) &EAAppType, sizeof(EAAppType), 0);
  1348. }
  1349. #endif
  1350. CloseFile(bsRunfile); /* Close run file */
  1351. #if defined(M_I386) || defined( _WIN32 )
  1352. FreeMem(pIOBuf);
  1353. #endif
  1354. #if OSXENIX
  1355. if(!fUndefinedExterns) chmod(&sbRun[1],0775 & ~umask(077));
  1356. /* Set protection executable */
  1357. #endif
  1358. }
  1359. #pragma check_stack(off)
  1360. #if NOT WIN_3
  1361. /*** SpawnOther - spawn any other processes
  1362. *
  1363. * Purpose:
  1364. * Spawn the other processes (i.e. cvpack) necessary to complete the
  1365. * construction of the executible.
  1366. *
  1367. * Input:
  1368. * sbRun - pointer to the name of the executible
  1369. *
  1370. * Output:
  1371. * None.
  1372. *
  1373. * Exceptions:
  1374. * None.
  1375. *
  1376. * Notes:
  1377. * None.
  1378. *
  1379. *************************************************************************/
  1380. LOCAL void NEAR SpawnOther(sbRun, szMyself)
  1381. BYTE *sbRun; /* Executable file name */
  1382. BYTE *szMyself; /* A full LINK path */
  1383. {
  1384. char FAR *env[2]; /* Enviroment for MPC */
  1385. SBTYPE progName; /* Program to invoke after linker */
  1386. SBTYPE progOptions; /* Program options */
  1387. char path_buffer[_MAX_PATH]; /* Stuff for splitpath() */
  1388. char drive[_MAX_DRIVE];
  1389. char dir[_MAX_DIR];
  1390. char fname[_MAX_FNAME];
  1391. char ext[_MAX_EXT];
  1392. intptr_t status;
  1393. if ((
  1394. #if PCODE
  1395. fMPC ||
  1396. #endif
  1397. (fSymdeb && fCVpack)
  1398. #if O68K
  1399. || iMacType != MAC_NONE
  1400. #endif
  1401. ) && !cErrors && !fUndefinedExterns)
  1402. {
  1403. #if FAR_SEG_TABLES
  1404. FreeSymTab();
  1405. #if NOT WIN_NT AND NOT DOSX32
  1406. _fheapmin();
  1407. #endif
  1408. #endif
  1409. #if NOT WIN_NT
  1410. if(lpszPath != NULL)
  1411. {
  1412. FSTRCPY((char FAR *) bufg, lpszPath - 5);
  1413. env[0] = (char FAR *) bufg;
  1414. env[1] = NULL;
  1415. _putenv((char FAR *) bufg);
  1416. }
  1417. #endif
  1418. #if O68K
  1419. if (fMPC || (fSymdeb && fCVpack)) {
  1420. #endif /* O68K */
  1421. progOptions[0] = '\0';
  1422. #if PCODE
  1423. if (fSymdeb && fCVpack && fMPC)
  1424. {
  1425. strcpy(progName, "cvpack");
  1426. strcpy(progOptions, "/pcode");
  1427. }
  1428. else
  1429. strcpy(progName, fMPC ? "mpc" : "cvpack16");
  1430. #else
  1431. strcpy(progName, "cvpack");
  1432. #endif
  1433. #ifndef C8_IDE
  1434. if (fNoBanner)
  1435. #endif
  1436. strcat(progOptions, "/nologo");
  1437. // Now determine which instance of child is to be loaded
  1438. // First - check the LINK directory
  1439. _splitpath(szMyself, drive, dir, fname, ext);
  1440. strcpy(fname, progName);
  1441. _makepath(path_buffer, drive, dir, fname, ext);
  1442. if (_access(path_buffer, 0) != 0) // file not in the LINK dir
  1443. {
  1444. // Second - check the current dir
  1445. drive[0] = '\0';
  1446. _getcwd(dir, _MAX_DIR);
  1447. _makepath(path_buffer, drive, dir, fname, ext);
  1448. if (_access(path_buffer, 0) != 0) // file not in the current dir
  1449. {
  1450. strcpy(path_buffer, progName);// spawn on the PATH
  1451. }
  1452. }
  1453. #if NOT (WIN_NT OR EXE386)
  1454. // If /TINY is active, we are building a .COM file,
  1455. // and the cv info is in a .DBG file
  1456. if (fBinary)
  1457. {
  1458. _splitpath(sbRun+1, drive, dir, fname, ext);
  1459. strcpy(ext, ".DBG");
  1460. _makepath(sbRun+1, drive, dir, fname, ext);
  1461. }
  1462. #endif
  1463. #if WIN_NT OR DOSX32
  1464. if ((status = _spawnlp(P_WAIT, path_buffer, path_buffer, progOptions, &sbRun[1], NULL)) == -1)
  1465. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1466. else if (status != 0)
  1467. cErrors++;
  1468. #else
  1469. if (spawnlpe(
  1470. #if DOSEXTENDER
  1471. (!_fDosExt) ?
  1472. #else
  1473. (_osmode == DOS_MODE && _osmajor < 10) ?
  1474. #endif
  1475. P_OVERLAY : P_WAIT, path_buffer, path_buffer, progOptions, &sbRun[1], NULL, env) == -1)
  1476. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1477. #endif
  1478. #if O68K
  1479. }
  1480. if (iMacType != MAC_NONE) {
  1481. progOptions[0] = '\0';
  1482. strcpy(progName, "link_68k");
  1483. /* Now determine which instance of child is to be loaded */
  1484. /* First - check the LINK directory */
  1485. _splitpath (szMyself, drive, dir, fname, ext);
  1486. strcpy (fname, progName);
  1487. _makepath (path_buffer, drive, dir, fname, ext);
  1488. if (_access (path_buffer, 0) != 0) // file not in the LINK dir
  1489. {
  1490. // Second - check the current dir
  1491. drive[0] = '\0';
  1492. #if (_MSC_VER >= 700)
  1493. _getcwd (0, dir, _MAX_DIR);
  1494. #else
  1495. _getcwd (dir, _MAX_DIR);
  1496. #endif
  1497. _makepath (path_buffer, drive, dir, fname, ext);
  1498. if (_access (path_buffer, 0) != 0) // file not in the current dir
  1499. {
  1500. strcpy (path_buffer, progName); // spawn on the PATH
  1501. }
  1502. }
  1503. if (iMacType == MAC_SWAP)
  1504. strcat(progOptions, "/s ");
  1505. if (fSymdeb)
  1506. strcat(progOptions, "/c ");
  1507. if ((status = spawnlp(P_WAIT, path_buffer, path_buffer,
  1508. progOptions, &sbRun[1], NULL)) == -1)
  1509. OutWarn(ER_badspawn, path_buffer, &sbRun[1], strerror(errno));
  1510. else if (status != 0)
  1511. cErrors++;
  1512. }
  1513. #endif /* O68K */
  1514. }
  1515. }
  1516. #endif
  1517. /****************************************************************
  1518. * *
  1519. * InterPass: *
  1520. * *
  1521. * Take care of miscellaneous items which must be done between *
  1522. * pass 1 and 2. *
  1523. * *
  1524. ****************************************************************/
  1525. LOCAL void NEAR InterPass (void)
  1526. {
  1527. #if OEXE
  1528. if(!fPackSet) packLim = fNewExe ?
  1529. #if EXE386
  1530. CBMAXSEG32 :
  1531. #elif O68K
  1532. (iMacType != MAC_NONE ? LXIVK / 2 :
  1533. LXIVK - 36) :
  1534. #else
  1535. LXIVK - 36 :
  1536. #endif
  1537. 0L;
  1538. #endif
  1539. #if NOT EXE386
  1540. // Set TargetOS - see LINK540 bug #11 for description
  1541. if (fNewExe && TargetOs != NE_OS2)
  1542. {
  1543. // Import/export seen in the OBJ files or .DEF file specified
  1544. #if CPU286
  1545. if(rhteDeffile == RHTENIL) // OS2 host and no .def file - OS2 target
  1546. TargetOs = NE_OS2;
  1547. else
  1548. TargetOs = NE_WINDOWS;
  1549. #else
  1550. TargetOs = NE_WINDOWS;
  1551. #endif
  1552. }
  1553. #endif
  1554. #if ODOS3EXE
  1555. // /DOSSEG (from switch or comment rec) forces off /DS, /NOG
  1556. if (fSegOrder)
  1557. vfDSAlloc = fNoGrpAssoc = FALSE;
  1558. #endif
  1559. #if ILINK
  1560. fQCIncremental = (FTYPE) (!fNewExe && fIncremental);
  1561. /* QC incremental link */
  1562. if (fQCIncremental)
  1563. {
  1564. TargetOs = 0xff; /* Mark .EXE as not compatibile with OS/2 .EXE */
  1565. fNewExe = (FTYPE) TRUE; /* Force to build segemented-executable */
  1566. }
  1567. #endif
  1568. #if ODOS3EXE AND OSEGEXE AND NOT EXE386
  1569. if (fNewExe)
  1570. {
  1571. // Check for invalid options for segmented-executable and ignore them
  1572. if ((vFlags & NENOTP) && cbStack)
  1573. {
  1574. cbStack = 0; // For DLLs ignore STACKSIZE
  1575. OutWarn(ER_ignostksize);
  1576. }
  1577. if (
  1578. #if ILINK
  1579. !fQCIncremental &&
  1580. #endif
  1581. cparMaxAlloc != 0xffff)
  1582. {
  1583. OutWarn(ER_swbadnew, "/HIGH or /CPARMAXALLOC");
  1584. cparMaxAlloc = 0xffff;
  1585. }
  1586. if (vfDSAlloc)
  1587. {
  1588. OutWarn(ER_swbadnew, "/DSALLOCATE");
  1589. vfDSAlloc = FALSE;
  1590. }
  1591. if (fNoGrpAssoc)
  1592. {
  1593. OutWarn(ER_swbadnew, "/NOGROUPASSOCIATION");
  1594. fNoGrpAssoc = FALSE;
  1595. }
  1596. if (fBinary)
  1597. {
  1598. OutWarn(ER_swbadnew, "/TINY");
  1599. fBinary = FALSE;
  1600. }
  1601. #if OVERLAYS
  1602. if (fOverlays)
  1603. {
  1604. OutWarn(ER_swbadnew, "Overlays");
  1605. fOverlays = FALSE;
  1606. }
  1607. #endif
  1608. }
  1609. else
  1610. {
  1611. if(fileAlign != DFSAALIGN)
  1612. OutWarn(ER_swbadold,"/ALIGNMENT");
  1613. #ifdef LEGO
  1614. if (fKeepFixups)
  1615. OutWarn(ER_swbadold, "/KEEPFIXUPS");
  1616. #endif /* LEGO */
  1617. if(fPackData)
  1618. OutWarn(ER_swbadold,"/PACKDATA");
  1619. #if OVERLAYS
  1620. if(fOldOverlay)
  1621. fDynamic= (FTYPE) FALSE;
  1622. else
  1623. fDynamic = fOverlays;
  1624. #endif
  1625. }
  1626. #if NOT QCLINK
  1627. // Check if fixup optimizations are possible
  1628. fOptimizeFixups = (FTYPE) ((TargetOs == NE_OS2 || TargetOs == NE_WINDOWS)
  1629. #if ILINK
  1630. && !fIncremental
  1631. #endif
  1632. #if O68K
  1633. && iMacType == MAC_NONE
  1634. #endif
  1635. );
  1636. #endif
  1637. pfProcFixup = fNewExe ? FixNew : FixOld;
  1638. #ifdef LEGO
  1639. if (fKeepFixups && fNewExe && (vFlags & NEPROT)
  1640. #if ILINK
  1641. && !fIncremental
  1642. #endif
  1643. #if O68K
  1644. && (iMacType == MAC_NONE)
  1645. #endif
  1646. )
  1647. pfProcFixup = FixNewKeep;
  1648. #endif /* LEGO */
  1649. #endif
  1650. /* Since mpsegraFirst was used for something else, clear it. */
  1651. FMEMSET(mpsegraFirst,0, gsnMax * sizeof(RATYPE));
  1652. }
  1653. #if EXE386
  1654. /*
  1655. * ChkSize386 : check 386 program size
  1656. *
  1657. * Made necessary by the way segment mapping is done to VM. See
  1658. * msa386().
  1659. */
  1660. LOCAL void NEAR ChkSize386(void)
  1661. {
  1662. register long *p; /* Pointer to mpsegcb */
  1663. register long *pEnd; /* Pointer to end of mpsegcb */
  1664. register unsigned long cb; /* Byte count */
  1665. /*
  1666. * Check that total size of segments fits within virtual memory
  1667. * area alloted for segments. Note that we DO NOT CHECK FOR
  1668. * ARITHMETIC OVERFLOW. To be strictly correct we should but
  1669. * it will be very rare and the error should be evident elsewhere.
  1670. */
  1671. if (fNewExe)
  1672. {
  1673. p = &mpsacb[1];
  1674. pEnd = &mpsacb[segLast];
  1675. }
  1676. #if ODOS3EXE
  1677. else
  1678. {
  1679. p = &mpsegcb[1];
  1680. pEnd = &mpsegcb[segLast];
  1681. }
  1682. #endif
  1683. for(cb = 0; p <= pEnd; ++p)
  1684. cb += (*p + (PAGLEN - 1)) & ~(PAGLEN - 1);
  1685. /* If size exceeds VM limit, quit with a fatal error. */
  1686. if(cb > (((unsigned long)VPLIB1ST<<LG2PAG)-AREAFSG))
  1687. Fatal(ER_pgmtoobig,(((unsigned long)VPLIB1ST<<LG2PAG)-AREAFSG));
  1688. }
  1689. #endif
  1690. LOCAL void NEAR InitAfterCmd (void)
  1691. {
  1692. #if ILINK
  1693. if (fIncremental && fBinary)
  1694. {
  1695. fIncremental = FALSE;
  1696. OutWarn(ER_tinyincr);
  1697. }
  1698. if (fIncremental && !fPackSet)
  1699. {
  1700. packLim = 0;
  1701. fPackSet = (FTYPE) TRUE;
  1702. }
  1703. #endif
  1704. fFarCallTransSave = fFarCallTrans;
  1705. InitTabs(); /* Initialize dynamic tables */
  1706. #if QBLIB
  1707. if(fQlib) InitQbLib(); /* Initialize QB-Library items */
  1708. #endif
  1709. #if CMDMSDOS
  1710. LibEnv(); /* Process LIB= environment variable */
  1711. #endif
  1712. if(fLstFileOpen && cbStack)
  1713. fprintf(bsLst,"Stack Allocation = %u bytes\r\n",
  1714. (cbStack + 1) & ~1); /* Print stack size */
  1715. }
  1716. /****************************************************************
  1717. * *
  1718. * main: *
  1719. * *
  1720. * The main function. *
  1721. * *
  1722. ****************************************************************/
  1723. #if NOT WIN_3
  1724. void __cdecl main (argc,argv)
  1725. int argc; /* Argument count */
  1726. char **argv; /* Argument list */
  1727. #else
  1728. int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
  1729. #endif
  1730. {
  1731. #if OVERLAYS OR ODOS3EXE
  1732. APROPNAMEPTR apropName; /* Public symbol pointer */
  1733. #endif
  1734. SBTYPE sbRun; /* Executable file name */
  1735. #if NOT WIN_3
  1736. #if !defined( _WIN32 ) AND ( WIN_NT AND !defined(DOSX32) OR USE_REAL )
  1737. int exceptCode;
  1738. _try
  1739. {
  1740. #endif
  1741. /* DLH bsErr can't be statically initialized with the CRT in a DLL */
  1742. bsErr = stderr;
  1743. #if CVPACK_MONDO
  1744. /* check for special cvpack only invocation */
  1745. if (argc > 1 && strcmp(argv[1], "/CvpackOnly") == 0)
  1746. {
  1747. /* we're not linking at all -- just invoke the built in cvpack */
  1748. argv[1] = "cvpack";
  1749. argv++;
  1750. argc--;
  1751. exit(cvpack_main(argc, argv));
  1752. }
  1753. #endif // CVPACK_MONDO
  1754. #if TIMINGS
  1755. ftime(&time_start);
  1756. #endif // TIMINGS
  1757. #if OSEGEXE
  1758. /* HACK ALERT !!! - special check for undocumented /Z1 option */
  1759. if (argc > 1)
  1760. {
  1761. if ((argv[1][0] == CHSWITCH) &&
  1762. ((argv[1][1] == 'Z') || (argv[1][1] == 'z')))
  1763. {
  1764. BYTE option[30];
  1765. option[0] = (BYTE) strlen(argv[1]);
  1766. strcpy(&option[1], argv[1]);
  1767. PeelFlags(option); /* Process /Z1 */
  1768. }
  1769. }
  1770. #endif
  1771. #else // WIN_3 TRUE
  1772. ProcessWinArgs( lpCmdLine );
  1773. #endif // WIN_3
  1774. InitializeWorld(); /* Initialize the linker */
  1775. #if NOT WIN_3
  1776. #if CMDMSDOS
  1777. if (argc <= 1 && !fNoBanner)
  1778. #endif
  1779. DisplayBanner(); /* Display signon banner */
  1780. ParseCmdLine(argc,argv); /* Parse the command line */
  1781. InitAfterCmd(); /* Initialize post-cmd stuff */
  1782. #else // WIN_3 is TRUE
  1783. ParseLinkCmdStr();
  1784. InitAfterCmd(); /* Initialize post-cmd stuff */
  1785. #endif // WIN_3
  1786. #if USE_REAL
  1787. if(IsDosxnt() && IsWin31() && !fSwNoUseReal)
  1788. fUseReal = (FTYPE)MakeConvMemPageable();
  1789. if(fUseReal)
  1790. _onexit( (_onexit_t) RealMemExit );
  1791. #endif
  1792. #if OSEGEXE
  1793. #if FDEBUG AND NOT QCLINK AND NOT WIN_3
  1794. if(fDebug) FmtPrint(GetMsg(P_parsedeffile)); // **** PARSE DEFINITIONS FILE ****\r\n
  1795. #endif
  1796. #if WIN_3
  1797. StatHdrWin(GetMsg(P_lwParseDef));
  1798. #endif
  1799. #if C8_IDE
  1800. if(fC8IDE)
  1801. {
  1802. sprintf(msgBuf, "@I0\r\n");
  1803. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1804. sprintf(msgBuf, "@I1Microsoft (R) Linker Version 5.40\r\n");
  1805. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1806. sprintf(msgBuf, "@I2Copyright (C) Microsoft Corp 1992\r\n");
  1807. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1808. sprintf(msgBuf, "@I3%s\r\n", GetMsg(P_lwParseDef));
  1809. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1810. }
  1811. #endif
  1812. #if NOT QCLINK
  1813. #if NOT EXE386
  1814. if (!fBinary)
  1815. #endif
  1816. ParseDeffile(); /* Parse the definitions file */
  1817. #endif
  1818. #endif
  1819. #if ODOS3EXE
  1820. // If overlays have been specified, but switches /OLDOV /DYN were
  1821. // not present on the command line, set /DYN to ON
  1822. // (dynamic overlays are the default)
  1823. if(fOverlays && !fOldOverlay && !fDynamic)
  1824. {
  1825. fDynamic = TRUE;
  1826. fFarCallTrans = (FTYPE) TRUE;
  1827. fPackSet = (FTYPE) TRUE;
  1828. packLim = LXIVK - 36; /* Default limit is 64K - 36 */
  1829. ovlThunkMax = 256;
  1830. }
  1831. #endif
  1832. fFarCallTransSave = fFarCallTrans;
  1833. if(fDynamic && fExePack)
  1834. {
  1835. fExePack = FALSE;
  1836. OutWarn(ER_dynexep);
  1837. }
  1838. #if WIN_3
  1839. StatHdrWin(GetMsg(P_lwPassOne));
  1840. #endif
  1841. #if C8_IDE
  1842. if(fC8IDE)
  1843. {
  1844. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwPassOne));
  1845. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1846. }
  1847. #endif
  1848. #if FDEBUG
  1849. if(fDebug) FmtPrint(GetMsg(P_passone)); // **** PASS ONE ****\r\n
  1850. #endif
  1851. #if OSMSDOS AND AUTOVM
  1852. CleanupNearHeap();
  1853. #endif
  1854. snkey = 0; /* Initialize for pass 1 */
  1855. modkey = 0; /* Initialize for pass 1 */
  1856. ObjDebTotal = 1;
  1857. ifhLast = FHNIL; /* No files looked at yet */
  1858. #if NEWIO
  1859. /* Allocate a file stream for bsInput with a dummy file handle */
  1860. bsInput = fdopen(0,RDBIN);
  1861. #endif /*NEWIO*/
  1862. #if OSMSDOS
  1863. setvbuf(bsInput,bigbuf,_IOFBF,sizeof(bigbuf));
  1864. #endif
  1865. rprop1stOpenFile = rprop1stFile; /* Remember first open file */
  1866. r1stFile = rprop1stFile; /* which is also first input file */
  1867. vfPass1 = (FTYPE) TRUE; /* Now pass 1 */
  1868. DrivePass(ProcP1); /* Make pass 1 */
  1869. #if OVERLAYS
  1870. // If overlays, make $$OVLINIT or $$MOVEINIT an undefined symbol
  1871. if (fOverlays)
  1872. {
  1873. if (!fOldOverlay)
  1874. {
  1875. if (PropSymLookup("\012$$MOVEINIT",ATTRPNM,FALSE) == PROPNIL)
  1876. PropSymLookup("\012$$MOVEINIT", ATTRUND, TRUE);
  1877. }
  1878. else
  1879. {
  1880. if (PropSymLookup("\011$$OVLINIT",ATTRPNM,FALSE) == PROPNIL)
  1881. PropSymLookup("\011$$OVLINIT", ATTRUND, TRUE);
  1882. }
  1883. }
  1884. #endif
  1885. #if WIN_3
  1886. StatHdrWin(GetMsg(P_lwLibraryS));
  1887. #endif
  1888. #if C8_IDE
  1889. if(fC8IDE)
  1890. {
  1891. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwLibraryS));
  1892. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1893. }
  1894. #endif
  1895. #if FDEBUG
  1896. if(fDebug) FmtPrint(GetMsg(P_libsearch));
  1897. #endif
  1898. #if OSMSDOS AND AUTOVM
  1899. CleanupNearHeap();
  1900. #endif
  1901. #if OEXE
  1902. if (fSegOrder)
  1903. SetDosseg();
  1904. #endif
  1905. LibrarySearch(); /* Search libraries */
  1906. vfPass1 = FALSE; /* No longer pass 1 */
  1907. #if LNKPROF
  1908. if(fP1stop) { FlsStdio(); exit(0); }
  1909. #endif
  1910. InterPass(); /* Do various between-pass tasks */
  1911. #if OSMSDOS AND AUTOVM
  1912. CleanupNearHeap();
  1913. #endif
  1914. #if WIN_3
  1915. StatHdrWin(GetMsg(P_lwAssign));
  1916. #endif
  1917. #if C8_IDE
  1918. if(fC8IDE)
  1919. {
  1920. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwAssign));
  1921. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1922. }
  1923. #endif
  1924. #if FDEBUG
  1925. if(fDebug) FmtPrint(GetMsg(P_assignadd)); /* **** ASSIGN ADDRESSES ****\r\n*/
  1926. #endif
  1927. AllocComDat();
  1928. AssignAddresses(); /* Assign addresses to segments */
  1929. #if SYMDEB
  1930. if (fSymdeb)
  1931. DoComdatDebugging();
  1932. #endif
  1933. if (fFullMap)
  1934. UpdateComdatContrib(
  1935. #if ILINK
  1936. FALSE,
  1937. #endif
  1938. TRUE);
  1939. #if EXE386
  1940. InitVmBase(); /* Set VM object areas base addresses */
  1941. FillInImportTable();
  1942. #endif
  1943. if(fLstFileOpen) /* If list file open */
  1944. {
  1945. #if WIN_3
  1946. StatHdrWin(GetMsg(P_lwMapfile));
  1947. #endif
  1948. #if C8_IDE
  1949. if(fC8IDE)
  1950. {
  1951. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwMapfile));
  1952. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1953. }
  1954. #endif
  1955. #if FDEBUG
  1956. if(fDebug) FmtPrint(GetMsg(P_printmap));/* **** PRINT MAP ****\r\n */
  1957. #endif
  1958. PrintMap(); /* Print load map */
  1959. #if QBLIB
  1960. if(fQlib) PrintQbStart();
  1961. #endif
  1962. }
  1963. #if OSEGEXE AND NOT QCLINK
  1964. if (fNewExe
  1965. #if NOT EXE386 AND ILINK
  1966. && !fQCIncremental
  1967. #endif
  1968. )
  1969. InitEntTab(); /* Initialize the Entry Table */
  1970. #endif
  1971. #if EXE386
  1972. if(f386) ChkSize386(); /* Check program size for 386 */
  1973. #endif
  1974. #if OSEGEXE AND NOT QCLINK
  1975. if (fNewExe
  1976. #if NOT EXE386 AND ILINK
  1977. && !fQCIncremental
  1978. #endif
  1979. )
  1980. InitFP(); /* Initialize floating-point items */
  1981. #endif
  1982. #if OSMSDOS AND AUTOVM
  1983. CleanupNearHeap();
  1984. #endif
  1985. snkey = 0; /* Initialize for pass 2 */
  1986. modkey = 0; /* Initialize for pass 2 */
  1987. ifhLast = FHNIL; /* No files examined on pass 2 yet */
  1988. #if WIN_3
  1989. StatHdrWin(GetMsg(P_lwPassTwo));
  1990. #endif
  1991. #if C8_IDE
  1992. if(fC8IDE)
  1993. {
  1994. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwPassTwo));
  1995. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  1996. }
  1997. #endif
  1998. #if FDEBUG
  1999. if(fDebug) FmtPrint(GetMsg(P_passtwo)); /* **** PASS TWO ****\r\n*/
  2000. #endif
  2001. DrivePass(ProcP2); /* Make pass 2 */
  2002. #if OSEGEXE
  2003. if (vpropAppLoader != PROPNIL)
  2004. {
  2005. APROPUNDEFPTR apropUndef;
  2006. apropUndef = (APROPUNDEFPTR) FetchSym(vpropAppLoader, TRUE);
  2007. fUndefinedExterns = fUndefinedExterns || (FTYPE) (apropUndef->au_attr == ATTRUND);
  2008. apropUndef->u.au_rFil = AddVmProp(apropUndef->u.au_rFil, rprop1stFile);
  2009. }
  2010. #endif
  2011. #if ODOS3EXE
  2012. if (fDOSExtended)
  2013. {
  2014. apropName = (APROPNAMEPTR ) PropSymLookup("\017__DOSEXT16_MODE", ATTRPNM, FALSE);
  2015. // Look up public symbol
  2016. if (apropName != PROPNIL)
  2017. {
  2018. if (dosExtMode != 0)
  2019. MoveToVm(sizeof(WORD), (BYTE *) &dosExtMode, mpgsnseg[apropName->an_gsn], apropName->an_ra);
  2020. // Store value
  2021. }
  2022. }
  2023. #endif
  2024. #if OVERLAYS
  2025. if (fOverlays)
  2026. {
  2027. // If there are overlays check if we have an overlay manager
  2028. apropName = (APROPNAMEPTR ) PropSymLookup(fDynamic ? "\012$$MOVEINIT" :
  2029. "\011$$OVLINIT",
  2030. ATTRPNM, FALSE);
  2031. if (apropName != PROPNIL)
  2032. { // If starting point defined
  2033. raStart = apropName->an_ra;// Get offset of entry point
  2034. segStart = mpgsnseg[apropName->an_gsn];
  2035. // Get base number of entry point
  2036. }
  2037. else
  2038. OutError(ER_ovlmnger);
  2039. }
  2040. #endif
  2041. if(fUndefinedExterns) /* If we have unresolved references */
  2042. {
  2043. if(fLstFileOpen && bsLst != stdout)
  2044. { /* If we have a list file */
  2045. NEWLINE(bsLst);
  2046. #if CMDXENIX
  2047. fprintf(bsLst,"%s: ",lnknam);
  2048. /* Linker name */
  2049. #endif
  2050. }
  2051. #if QCLINK
  2052. if (!fZ1)
  2053. #endif
  2054. NEWLINE(stderr);
  2055. EnSyms(PrintAnUndef,ATTRUND); /* Print undefined symbols */
  2056. if(fLstFileOpen && bsLst != stdout)
  2057. NEWLINE(bsLst);
  2058. #if QCLINK
  2059. if (!fZ1)
  2060. #endif
  2061. NEWLINE(stderr);
  2062. }
  2063. #if ILINK
  2064. if (fIncremental)
  2065. {
  2066. OutputIlk(); /* Output .ilk / .sym files */
  2067. }
  2068. #endif /*ILINK*/
  2069. #if FDEBUG
  2070. if(fDebug)
  2071. {
  2072. if( !fDelexe || fDelexe && cErrors==0 )
  2073. {
  2074. FmtPrint(GetMsg(P_writing1)); /* **** WRITING */
  2075. if (fNewExe)
  2076. {
  2077. if (TargetOs == NE_OS2)
  2078. FmtPrint("OS/2");
  2079. else if (TargetOs == NE_WINDOWS)
  2080. FmtPrint("WINDOWS");
  2081. }
  2082. else
  2083. {
  2084. FmtPrint("DOS");
  2085. #if OVERLAYS
  2086. if (fOverlays)
  2087. FmtPrint(GetMsg(P_writing2)); /* - overlaid*/
  2088. #endif
  2089. }
  2090. FmtPrint(GetMsg(P_writing3)); /* EXECUTABLE ****\r\n*/
  2091. #if OVERLAYS
  2092. if (fOverlays && fDynamic)
  2093. FmtPrint(GetMsg(P_overlaycalls), ovlThunkMax, ovlThunkMac);/***** NUMBER OF INTEROVERLAY CALLS: requested %d; generated %d ****\r\n*/
  2094. #endif
  2095. PrintStats();
  2096. #if PROFSYM
  2097. ProfSym(); /* Profile symbol table */
  2098. #endif
  2099. }
  2100. else // some errors occured
  2101. {
  2102. FmtPrint(GetMsg(P_noexe));
  2103. }
  2104. }
  2105. #endif /* FDEBUG */
  2106. if( !fDelexe || fDelexe && cErrors==0 )
  2107. {
  2108. #if WIN_3
  2109. StatHdrWin(GetMsg(P_lwExecutable));
  2110. #endif
  2111. #if C8_IDE
  2112. if(fC8IDE)
  2113. {
  2114. sprintf(msgBuf,"@I3%s\r\n", GetMsg(P_lwExecutable));
  2115. _write(fileno(stderr), msgBuf, strlen(msgBuf));
  2116. }
  2117. #endif
  2118. #if OSMSDOS
  2119. if (chRunFile >= 'a' && chRunFile <= 'z')
  2120. chRunFile += (BYTE) ('A' - 'a');
  2121. /* Make drive letter upper case */
  2122. if(fPauseRun && FCHGDSK(chRunFile - 'A'))
  2123. {
  2124. if(fLstFileOpen && chListFile == (BYTE) (chRunFile - 'A'))
  2125. { /* If map on EXE drive */
  2126. fclose(bsLst); /* Close the list file */
  2127. fLstFileOpen = FALSE; /* Set flag accordingly */
  2128. }
  2129. (*pfPrompt)(NULL,P_genexe,(int) NULL,P_ChangeDiskette,chRunFile);
  2130. }
  2131. else
  2132. fPauseRun = FALSE;
  2133. #endif
  2134. if(fLstFileOpen && bsLst != stdout)
  2135. {
  2136. fclose(bsLst);
  2137. fLstFileOpen = FALSE;
  2138. }
  2139. fclose(bsInput); /* Close input file */
  2140. #if NOT EXE386
  2141. if (fExePack && fNewExe && (TargetOs == NE_WINDOWS))
  2142. {
  2143. OutWarn(ER_exepack);
  2144. fExePack = FALSE;
  2145. }
  2146. #endif
  2147. OutRunFile(sbRun); /* Output executable file */
  2148. CleanUp(); /* Mop up after itself */
  2149. #ifdef PENTER_PROFILE
  2150. saveEntries();
  2151. #endif
  2152. #if OWNSTDIO
  2153. FlsStdio();
  2154. #endif
  2155. #if TIMINGS
  2156. if (fShowTiming) // check if we started the timer...
  2157. {
  2158. char buf[80];
  2159. int hundr;
  2160. time_t td;
  2161. ftime(&time_end);
  2162. td = time_end.time - time_start.time;
  2163. hundr = (time_end.millitm - time_start.millitm)/10;
  2164. td = td*100 + hundr;
  2165. sprintf(buf, "Linker phase: %d.%02ds\r\n", td/100, td%100);
  2166. _write(fileno(stdout), buf, strlen(buf));
  2167. time_start = time_end;
  2168. }
  2169. #endif // TIMINGS
  2170. #if NOT WIN_3
  2171. #ifndef CVPACK_MONDO
  2172. SpawnOther(sbRun, argv[0]);
  2173. #else
  2174. if (fSymdeb && fCVpack && !cErrors && !fUndefinedExterns)
  2175. {
  2176. char drive[_MAX_DRIVE];
  2177. char dir[_MAX_DIR];
  2178. char fname[_MAX_FNAME];
  2179. int argcT = 0;
  2180. char *argvT[5];
  2181. argvT[argcT++] = "cvpack";
  2182. argvT[argcT++] = "/nologo";
  2183. if (fMPC)
  2184. argvT[argcT++] = "/pcode";
  2185. sbRun[sbRun[0]+1] = '\0'; // NUL terminate
  2186. // If /TINY is active, we are building a .COM file,
  2187. // and the cv info is in a .DBG file
  2188. if (fBinary)
  2189. {
  2190. _splitpath(sbRun+1, drive, dir, fname, NULL);
  2191. _makepath(sbRun+1, drive, dir, fname, ".DBG");
  2192. }
  2193. argvT[argcT++] = sbRun+1;
  2194. argvT[argcT] = NULL;
  2195. fflush(stderr);
  2196. fflush(stdout);
  2197. _setmode(1,_O_TEXT);
  2198. _setmode(2,_O_TEXT);
  2199. #if FAR_SEG_TABLES
  2200. FreeSymTab();
  2201. #if NOT WIN_NT AND NOT DOSX32
  2202. _fheapmin();
  2203. #endif
  2204. #endif
  2205. cvpack_main(argcT, argvT);
  2206. }
  2207. else if (fMPC)
  2208. SpawnOther(sbRun, argv[0]); // we'll be running MPC
  2209. #endif
  2210. #if TIMINGS
  2211. if (fShowTiming) // check if we started the timer...
  2212. {
  2213. char buf[80];
  2214. int hundr;
  2215. time_t td;
  2216. ftime(&time_end);
  2217. td = time_end.time - time_start.time;
  2218. hundr = (time_end.millitm - time_start.millitm)/10;
  2219. td = td*100 + hundr;
  2220. sprintf(buf, "Cvpack phase: %d.%02ds\r\n", td/100, td%100);
  2221. _write(fileno(stdout), buf, strlen(buf));
  2222. time_start = time_end;
  2223. }
  2224. #endif // TIMINGS
  2225. #endif
  2226. }
  2227. fflush(stdout);
  2228. fflush(stderr);
  2229. #if USE_REAL
  2230. RealMemExit();
  2231. #endif
  2232. EXIT((cErrors || fUndefinedExterns)? 2: 0);
  2233. #if !defined( _WIN32 ) AND ( WIN_NT AND !defined(DOSX32) OR USE_REAL )
  2234. }
  2235. _except (1)
  2236. {
  2237. #if USE_REAL
  2238. RealMemExit();
  2239. #endif
  2240. exceptCode = _exception_code();
  2241. if (exceptCode == EXCEPTION_ACCESS_VIOLATION)
  2242. {
  2243. fprintf(stdout, "\r\nLINK : fatal error L5000 : internal failure - access violation ");
  2244. fflush(stdout);
  2245. }
  2246. else if (exceptCode == EXCEPTION_DATATYPE_MISALIGNMENT)
  2247. {
  2248. fprintf(stdout, "\r\nLINK : fatal error L5001 : internal failure - datatype misalignment ");
  2249. fflush(stdout);
  2250. }
  2251. else
  2252. CtrlC();
  2253. }
  2254. #endif
  2255. }