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.

1633 lines
48 KiB

  1. /*
  2. * Copyright Microsoft Corporation, 1983-1989
  3. *
  4. * This Module contains Proprietary Information of Microsoft
  5. * Corporation and should be treated as Confidential.
  6. */
  7. /****************************************************************
  8. * *
  9. * FLAG PROCESSOR MODULE *
  10. * *
  11. ****************************************************************/
  12. #include <minlit.h> /* Types and constants */
  13. #include <bndtrn.h> /* Types and constants */
  14. #include <bndrel.h> /* Types and constants */
  15. #include <lnkio.h> /* Linker I/O definitions */
  16. #include <lnkmsg.h> /* Error messages */
  17. #if OIAPX286
  18. #include <xenfmt.h> /* x.out definitions */
  19. #endif
  20. #include <extern.h> /* External declarations */
  21. #include <newexe.h> /* DOS & 286 .EXE format structure def.s */
  22. #if EXE386
  23. #include <exe386.h> /* 386 .EXE format structure def.s */
  24. #endif
  25. #include <process.h>
  26. extern FTYPE fNoExtDic; /* Not searching extended dictionary */
  27. LOCAL BYTE *osbSwitch; /* Switch pointer */
  28. LOCAL MSGTYPE SwitchErr; /* Switch error number */
  29. /*
  30. * FUNCTION PROTOTYPES
  31. */
  32. #if TIMINGS
  33. LOCAL void NEAR SwShowTiming(void);
  34. #endif // TIMINGS
  35. #if PCODE
  36. LOCAL void NEAR SwPCode(void);
  37. #endif
  38. LOCAL void NEAR SwAlign(void);
  39. LOCAL void NEAR SwBatch(void);
  40. #if ODOS3EXE
  41. LOCAL void NEAR SwBinary(void);
  42. #endif
  43. LOCAL void NEAR SwCase(void);
  44. LOCAL void NEAR SwCParMax(void);
  45. LOCAL void NEAR SwDelexe(void);
  46. LOCAL void NEAR SwDosExtend(void);
  47. LOCAL void NEAR SwDosseg(void);
  48. LOCAL void NEAR SwDSAlloc(void);
  49. LOCAL void NEAR SwDynamic(void);
  50. LOCAL void NEAR SwIdef(void);
  51. LOCAL void NEAR SwOldOvl(void);
  52. LOCAL void NEAR SwExePack(void);
  53. LOCAL void NEAR SwFarCall(void);
  54. #if EXE386
  55. LOCAL void NEAR SwHeader(void);
  56. #endif
  57. #if NOT WIN_3
  58. LOCAL void NEAR SwHelp(void);
  59. LOCAL void NEAR SwShortHelp(void);
  60. #endif
  61. LOCAL void NEAR SwHigh(void);
  62. #if ILINK
  63. LOCAL void NEAR SwIncremental(void);
  64. #endif
  65. LOCAL void NEAR SwInfo(void);
  66. LOCAL void NEAR SwIntNo(void);
  67. #if (OSEGEXE AND defined(LEGO)) OR EXE386
  68. LOCAL void NEAR SwKeepFixups(void);
  69. #endif
  70. #if EXE386
  71. LOCAL void NEAR SwKeepVSize(void);
  72. #endif
  73. LOCAL void NEAR SwLineNos(void);
  74. LOCAL void NEAR SwMap(void);
  75. #if O68K
  76. LOCAL void NEAR SwMac(void);
  77. #endif /* O68K */
  78. #if WIN_NT
  79. LOCAL void NEAR SwMemAlign(void);
  80. #endif
  81. #if NOT EXE386
  82. LOCAL void NEAR SwNewFiles(void);
  83. #endif
  84. LOCAL void NEAR SwNoDefLib(void);
  85. LOCAL void NEAR SwNoExtDic(void);
  86. LOCAL void NEAR SwNoFarCall(void);
  87. LOCAL void NEAR SwNoGrp(void);
  88. LOCAL void NEAR SwNologo();
  89. LOCAL void NEAR SwNonulls(void);
  90. LOCAL void NEAR SwNoPack(void);
  91. LOCAL void NEAR SwNoUseReal(void);
  92. LOCAL void NEAR SwPack(void);
  93. LOCAL void NEAR SwPackData(void);
  94. LOCAL void NEAR SwPackFunctions(void);
  95. LOCAL void NEAR SwNoPackFunctions(void);
  96. LOCAL void NEAR SwPadCode(void);
  97. LOCAL void NEAR SwPadData(void);
  98. LOCAL void NEAR SwPause(void);
  99. LOCAL void NEAR SwPmType(void);
  100. LOCAL void NEAR SwQuicklib(void);
  101. LOCAL void NEAR SwSegments(void);
  102. LOCAL void NEAR SwStack(void);
  103. LOCAL void NEAR SwSymdeb(void);
  104. LOCAL void NEAR SwWarnFixup(void);
  105. #if DOSEXTENDER
  106. LOCAL void NEAR SwRunReal(void);
  107. #endif
  108. #if QCLINK
  109. LOCAL void NEAR SwZ1(void);
  110. #endif
  111. #if QCLINK OR Z2_ON
  112. LOCAL void NEAR SwZ2 (void);
  113. #endif
  114. #if QCLINK
  115. LOCAL void NEAR SwZincr(void);
  116. #endif
  117. LOCAL int NEAR ParseNo(unsigned long *pResult);
  118. LOCAL int NEAR ParseStr(char *pResult);
  119. LOCAL void NEAR BadFlag(unsigned char *psb, MSGTYPE errnum);
  120. LOCAL int NEAR FPrefix(unsigned char *psb1,unsigned char *psb2);
  121. /*
  122. * ParseNo : Parse switch number
  123. *
  124. * Return value:
  125. * 1 result stored in pointer
  126. * 0 no switch given
  127. * -1 error
  128. */
  129. LOCAL int NEAR ParseNo(pResult)
  130. unsigned long *pResult;
  131. {
  132. REGISTER char *s; /* String pointer */
  133. REGISTER WORD ch; /* A character */
  134. WORD strlen; /* String length */
  135. WORD base = 10; /* Base to read constant in */
  136. DWORD oldval;
  137. oldval = *pResult = 0L; /* Initialize */
  138. strlen = IFind(osbSwitch,':'); /* Look for a colon in the string */
  139. if(strlen != INIL && strlen < (WORD) (B2W(osbSwitch[0]) - 1))
  140. { /* If switch form valid */
  141. s = &osbSwitch[strlen + 2];
  142. /* Set pointer past colon */
  143. strlen = B2W(osbSwitch[0]) - strlen - 1;
  144. /* Get length of string left */
  145. if(*s == '0') /* If string starts with 0 */
  146. {
  147. if(strlen > 1 && ((WORD) s[1] & 0137) == 'X')
  148. { /* If string starts with "0x" */
  149. base = 16; /* Change base to hexadecimal */
  150. ++s; /* Skip over "0" */
  151. --strlen; /* Decrement length */
  152. }
  153. else base = 8; /* Else change to octal */
  154. ++s; /* Skip "0" (or "x") */
  155. --strlen; /* Decrement length */
  156. }
  157. while(strlen--) /* While not at end of string */
  158. {
  159. ch = B2W(*s++); /* Get character */
  160. if(ch >= '0' && ch <= '9') ch -= (WORD) '0';
  161. /* Remove offset */
  162. else if(ch >= 'A' && ch < 'A' + base - 10) ch -= (WORD) 'A' - 10;
  163. /* Remove offset */
  164. else if(ch >= 'a' && ch < 'a' + base - 10) ch -= (WORD) 'a' - 10;
  165. /* Remove offset */
  166. else /* Invalid character */
  167. {
  168. SwitchErr = ER_swbadnum;
  169. return(-1); /* Error */
  170. }
  171. if((*pResult *= base) < oldval)
  172. {
  173. SwitchErr = ER_swbadnum;
  174. return(-1); /* Error */
  175. }
  176. *pResult += ch;
  177. oldval = *pResult;
  178. }
  179. return(1); /* Number is present */
  180. }
  181. else return(0); /* No number present */
  182. }
  183. /*
  184. * ParseStr : Parse switch string
  185. *
  186. * Return value:
  187. * 1 result stored in string
  188. * 0 no switch string given
  189. */
  190. LOCAL int NEAR ParseStr(pResult)
  191. char *pResult; /* Length prefixed result */
  192. {
  193. REGISTER char *s; /* String pointer */
  194. WORD strlen; /* String length */
  195. *pResult = '\0'; /* Initialize */
  196. strlen = IFind(osbSwitch,':'); /* Look for a colon in the string */
  197. if(strlen != INIL && strlen < (WORD) (B2W(osbSwitch[0]) - 1))
  198. { /* If switch form valid */
  199. s = &osbSwitch[strlen + 2];
  200. /* Set pointer past colon */
  201. strlen = B2W(osbSwitch[0]) - strlen - 1;
  202. /* Get length of string left */
  203. *pResult++ = (char) strlen; /* Store length */
  204. while(strlen--) /* While not at end of string */
  205. {
  206. *pResult++ = (char) (*s++); /* Get character */
  207. }
  208. return(1); /* String is present */
  209. }
  210. else return(0); /* No stringr present */
  211. }
  212. #if PCODE
  213. LOCAL void NEAR SwPCode(void)
  214. {
  215. SBTYPE SwString;
  216. fNewExe = (FTYPE) TRUE;
  217. fMPC = (FTYPE) TRUE;
  218. if (ParseStr(SwString))
  219. {
  220. if(SwString[1] == 'n' || SwString[1] == 'N') // /PCODE:NOMPC
  221. {
  222. fIgnoreMpcRun = (FTYPE) TRUE;
  223. fMPC = (FTYPE) FALSE;
  224. }
  225. }
  226. }
  227. #endif
  228. /***************************************************************/
  229. /* Options common to all versions regardless of output format */
  230. LOCAL void NEAR SwCase()
  231. {
  232. fIgnoreCase = (FTYPE) ~IGNORECASE; /* Toggle default case sensitivity */
  233. }
  234. LOCAL void NEAR SwLineNos() /* Line numbers requested */
  235. {
  236. vfLineNos = (FTYPE) TRUE; /* Set flag */
  237. }
  238. #if LOCALSYMS
  239. LOCAL void NEAR SwLocals() /* Local symbols requested */
  240. {
  241. fLocals = (FTYPE) TRUE; /* Set flag */
  242. }
  243. #endif
  244. #pragma check_stack(on)
  245. LOCAL void NEAR SwMap() /* Link map requested */
  246. {
  247. SBTYPE SwString;
  248. int rc;
  249. vfMap = (FTYPE) TRUE; // Set flag
  250. if ((rc = ParseStr(SwString)) <= 0) // Done if no num or error
  251. return;
  252. // The optional parameter following /MAP was originally intended
  253. // to tell the linker how much to space to allocate for sorting
  254. // more public symbols than the stack-based limit. Since we now
  255. // dyamically allocate as much space as possible for sorting,
  256. // the parameter is no longer necessary and its value is ignored.
  257. // However, the side effect of suppressing the "sorted by name"
  258. // list is retained.
  259. if (SwString[1] == 'A' || SwString[1] == 'a')
  260. fListAddrOnly = (FTYPE) TRUE; // /MAP:ADDRESS
  261. else if (SwString[1] == 'F' || SwString[1] == 'f')
  262. fFullMap = (FTYPE) TRUE; // /MAP:FULL or /MAP:full
  263. }
  264. LOCAL void NEAR SwNoDefLib() /* Do not search default library */
  265. {
  266. SBTYPE SwString;
  267. SBTYPE LibName;
  268. if (ParseStr(SwString))
  269. {
  270. vfNoDefaultLibrarySearch = FALSE;
  271. /* Clear flag - selective library search */
  272. strcpy(LibName, sbDotLib);
  273. UpdateFileParts(LibName, SwString);
  274. EnterName(LibName,ATTRSKIPLIB,TRUE);
  275. }
  276. else vfNoDefaultLibrarySearch = (FTYPE) TRUE;
  277. /* Set flag */
  278. }
  279. #pragma check_stack(off)
  280. LOCAL void NEAR SwNologo()
  281. {
  282. // if fNoprompt is already set then either
  283. // a) /BATCH was specified, in which case /NOLOGO is redundant
  284. // b) BATCH was in _MSC_IDE_FLAGS in which case fNoEchoLrf has not been
  285. // set, and we want to suppress echoing of the response file
  286. // (see CAVIAR 2378 [rm])
  287. if (fNoprompt)
  288. fNoEchoLrf = TRUE; /* Do not echo response file */
  289. fNoBanner = TRUE; /* Do not display banner */
  290. }
  291. LOCAL void NEAR SwBatch() /* Do not prompt for files */
  292. {
  293. fNoEchoLrf = (FTYPE) TRUE; /* Do not echo response file */
  294. fNoprompt = (FTYPE) TRUE; /* Do not prompt */
  295. fPauseRun = FALSE; /* Disable /PAUSE */
  296. fNoBanner = (FTYPE) TRUE; /* Do not display banner */
  297. }
  298. #if ODOS3EXE
  299. LOCAL void NEAR SwBinary() /* Produce .COM file */
  300. {
  301. fBinary = (FTYPE) TRUE;
  302. SwNonulls(); /* No nulls */
  303. fFarCallTrans = (FTYPE) TRUE; /* Far call translation */
  304. packLim = LXIVK - 36; /* Default limit is 64K - 36 */
  305. fPackSet = (FTYPE) TRUE; /* Remember packLim was set */
  306. }
  307. #endif
  308. #if SYMDEB
  309. LOCAL void NEAR SwSymdeb() /* Symbolic debugging */
  310. {
  311. SBTYPE SwString;
  312. fSymdeb = (FTYPE) TRUE;
  313. if (ParseStr(SwString))
  314. {
  315. fCVpack = (FTYPE) (SwString[1] == 'c' || SwString[1] == 'C');
  316. }
  317. }
  318. #endif
  319. #if PERFORMANCE
  320. LOCAL void NEAR SwVMPerf() /* Report on VM performance */
  321. {
  322. fPerformance = (FTYPE) TRUE; /* Set flag */
  323. }
  324. #endif
  325. #if OSMSDOS
  326. LOCAL void NEAR SwPause() /* Pause before writing executable */
  327. {
  328. fPauseRun = (FTYPE) TRUE; /* Set flag */
  329. fNoprompt = FALSE; /* Disable /NOPROMPT */
  330. }
  331. #endif
  332. LOCAL void NEAR SwStack() /* Set stack segment size */
  333. {
  334. unsigned long num;
  335. int rc;
  336. if((rc = ParseNo(&num)) < 0) /* Quit if error */
  337. return;
  338. #if EXE386
  339. if(!rc || num > CBMAXSEG32 - 4L)
  340. #else
  341. if(!rc || num > LXIVK - 2L)
  342. #endif
  343. SwitchErr = ER_swstack;
  344. else
  345. #if EXE386
  346. cbStack = num;
  347. #else
  348. cbStack = (WORD) num;
  349. #endif
  350. }
  351. LOCAL void NEAR SwSegments() /* Set maximum number of segments */
  352. {
  353. unsigned long nsegs; /* Number of segments */
  354. int rc;
  355. if((rc = ParseNo(&nsegs)) <= 0) /* Quit if error or no argument */
  356. return;
  357. if(nsegs > (long) GSNMAX)
  358. SwitchErr = ER_swseglim;
  359. else
  360. {
  361. if ((nsegs + 3L) > GSNMAX)
  362. gsnMax = GSNMAX;
  363. else
  364. gsnMax = (SNTYPE) nsegs; /* Else set limit */
  365. }
  366. }
  367. #if EXE386
  368. LOCAL void NEAR SwMemAlign(void)/* Set memory object alignment factor */
  369. {
  370. long align; /* Alignment size in bytes */
  371. int rc;
  372. if ((rc = ParseNo(&align)) < 0) /* Quit if error */
  373. return;
  374. if (rc && align >= 1)
  375. { /* If value in legal range */
  376. for (objAlign = 32; objAlign != 0; --objAlign)
  377. { /* Loop to find log of align */
  378. if ((1L << objAlign) & align)
  379. break; /* Break when high bit found */
  380. }
  381. if ((1L << objAlign) == align)
  382. return; /* Align must be power of two */
  383. }
  384. OutWarn(ER_alnbad); /* Output warning message */
  385. objAlign = DFOBJALIGN; /* Use default value */
  386. }
  387. #endif
  388. #if NOT EXE386
  389. LOCAL void NEAR SwNewFiles(void)
  390. {
  391. vFlagsOthers |= NENEWFILES; /* Set flag */
  392. }
  393. #endif
  394. #if FDEBUG
  395. LOCAL void NEAR SwInfo() /* Turn on runtime debugging */
  396. {
  397. fDebug = (FTYPE) TRUE; /* Set flag */
  398. }
  399. #endif
  400. #if LIBMSDOS
  401. LOCAL void NEAR SwNoExtDic() /* Don't search extended dictionary */
  402. {
  403. fNoExtDic = (FTYPE) TRUE;
  404. }
  405. #endif
  406. /***************************************************************/
  407. /* Options for segmented executable format. */
  408. #if OSEGEXE
  409. LOCAL void NEAR SwAlign() /* Set segment alignment factor */
  410. {
  411. long align; /* Alignment size in byutes */
  412. int rc;
  413. if((rc = ParseNo(&align)) < 0) /* Quit if error */
  414. return;
  415. if(rc && align >= 1 && align <= 32768L)
  416. { /* If value in legal range */
  417. for(fileAlign = 16; fileAlign != 0; --fileAlign)
  418. { /* Loop to find log of align */
  419. if((1L << fileAlign) & align) break;
  420. /* Break when high bit found */
  421. }
  422. if((1L << fileAlign) == align) return;
  423. /* Align must be power of two */
  424. }
  425. OutWarn(ER_alnbad); /* Output warning message */
  426. fileAlign = DFSAALIGN; /* Use default value */
  427. }
  428. #pragma check_stack(on)
  429. #if OUT_EXP
  430. LOCAL void NEAR SwIdef(void) /* Dump exports to a text file */
  431. {
  432. SBTYPE SwString;
  433. int rc;
  434. if ((rc = ParseStr(SwString)) <= 0) // Done if no string or error
  435. {
  436. bufExportsFileName[0] = '.'; // Use the default file name
  437. return;
  438. }
  439. strcpy(bufExportsFileName, SwString);
  440. }
  441. #endif
  442. #if NOT EXE386
  443. LOCAL void NEAR SwPmType() /* /PMTYPE:<type> */
  444. {
  445. SBTYPE SwString;
  446. if (ParseStr(SwString))
  447. {
  448. if (FPrefix("\002PM", SwString))
  449. vFlags |= NEWINAPI;
  450. else if (FPrefix("\003VIO", SwString))
  451. vFlags |= NEWINCOMPAT;
  452. else if (FPrefix("\005NOVIO", SwString))
  453. vFlags |= NENOTWINCOMPAT;
  454. else
  455. OutWarn(ER_badpmtype, &osbSwitch[1]);
  456. }
  457. else
  458. OutWarn(ER_badpmtype, &osbSwitch[1]);
  459. }
  460. #endif
  461. #pragma check_stack(off)
  462. LOCAL void NEAR SwWarnFixup()
  463. {
  464. fWarnFixup = (FTYPE) TRUE;
  465. }
  466. #if O68K
  467. LOCAL void NEAR SwMac() /* Target is a Macintosh */
  468. {
  469. SBTYPE SwString;
  470. f68k = fTBigEndian = fNewExe = (FTYPE) TRUE;
  471. iMacType = (BYTE) (ParseStr(SwString) && FPrefix("\011SWAPPABLE", SwString)
  472. ? MAC_SWAP : MAC_NOSWAP);
  473. /* If we are packing code to the default value, change the default. */
  474. if (fPackSet && packLim == LXIVK - 36)
  475. packLim = LXIVK / 2;
  476. }
  477. #endif /* O68K */
  478. #endif /* OSEGEXE */
  479. /***************************************************************/
  480. /* Options shared by DOS3 and segmented exe formats. */
  481. #if OEXE
  482. /*
  483. * HACK ALERT !!!!!!!!!!!!!!!
  484. * Function SetDosseg is used to hide local call to SwDosseg().
  485. * This function is called from ComRc1 (in NEWTP1.C).
  486. *
  487. */
  488. void SetDosseg(void)
  489. {
  490. SwDosseg();
  491. }
  492. LOCAL void NEAR SwDosseg() /* DOS Segment ordering switch given */
  493. {
  494. static FTYPE FirstTimeCalled = (FTYPE) TRUE; /* If true create symbols _edata */
  495. /* and _end */
  496. fSegOrder = (FTYPE) TRUE; /* Set switch */
  497. if (FirstTimeCalled && vfPass1)
  498. {
  499. MkPubSym((BYTE *) "\006_edata",0,0,(RATYPE)0);
  500. MkPubSym((BYTE *) "\007__edata",0,0,(RATYPE)0);
  501. MkPubSym((BYTE *) "\004_end",0,0,(RATYPE)0);
  502. MkPubSym((BYTE *) "\005__end",0,0,(RATYPE)0);
  503. FirstTimeCalled = FALSE;
  504. #if ODOS3EXE
  505. if (cparMaxAlloc == 0)
  506. cparMaxAlloc = 0xFFFF; /* Turn off /HIGH */
  507. vfDSAlloc = FALSE; /* Turn off DS Allocation */
  508. #endif
  509. }
  510. }
  511. #if ODOS3EXE
  512. LOCAL void NEAR SwDosExtend(void)
  513. {
  514. long mode; // Extender mode
  515. int rc;
  516. if ((rc = ParseNo(&mode)) < 0) // Quit if error
  517. return;
  518. if (rc)
  519. dosExtMode = (WORD) mode;
  520. fDOSExtended = (FTYPE) TRUE;
  521. }
  522. #endif
  523. #if TIMINGS
  524. LOCAL void NEAR SwShowTiming(void)
  525. {
  526. extern int fShowTiming;
  527. fShowTiming = TRUE;
  528. }
  529. #endif // TIMINGS
  530. #if USE_REAL
  531. LOCAL void NEAR SwNoUseReal(void)
  532. {
  533. fSwNoUseReal = TRUE;
  534. }
  535. #endif
  536. #if FEXEPACK
  537. LOCAL void NEAR SwExePack() /* Set exepack switch */
  538. {
  539. #if QBLIB
  540. /* If /QUICKLIB given, issue fatal error. */
  541. if(fQlib)
  542. Fatal(ER_swqe);
  543. #endif
  544. #if ODOS3EXE
  545. if (cparMaxAlloc == 0)
  546. OutWarn(ER_loadhi);
  547. else
  548. #endif
  549. fExePack = (FTYPE) TRUE;
  550. }
  551. #endif
  552. LOCAL void NEAR SwNonulls ()
  553. {
  554. extern FTYPE fNoNulls;
  555. /*
  556. * /NONULLSDOSSEG: just like /DOSSEG except do not insert
  557. * 16 null bytes in _TEXT.
  558. */
  559. SwDosseg();
  560. fNoNulls = (FTYPE) TRUE;
  561. }
  562. LOCAL void NEAR SwNoFarCall() /* Disable far call optimization */
  563. {
  564. fFarCallTrans = FALSE;
  565. }
  566. void NEAR SwNoPack() /* Disable code packing */
  567. {
  568. fPackSet = (FTYPE) TRUE; /* Remember packLim was set */
  569. packLim = 0L;
  570. }
  571. LOCAL void NEAR SwPack() /* Pack code segments */
  572. {
  573. int rc;
  574. fPackSet = (FTYPE) TRUE; /* Remember packLim was set */
  575. if((rc = ParseNo(&packLim)) < 0) /* Quit if error */
  576. return;
  577. if(!rc)
  578. #if EXE386
  579. packLim = CBMAXSEG32; /* Default limit is 4Gb */
  580. #else
  581. #if O68K
  582. packLim = iMacType != MAC_NONE ? LXIVK / 2 : LXIVK - 36;
  583. /* Default limit is 32K or 64K - 36 */
  584. #else
  585. packLim = LXIVK - 36; /* Default limit is 64K - 36 */
  586. #endif
  587. else if(packLim > LXIVK) /* If limit set too high */
  588. SwitchErr = ER_swpack;
  589. else if(packLim > LXIVK - 36)
  590. OutWarn(ER_pckval);
  591. #endif
  592. }
  593. LOCAL void NEAR SwPackData() /* Pack data segments */
  594. {
  595. int rc;
  596. fPackData = (FTYPE) TRUE;
  597. if((rc = ParseNo(&DataPackLim)) < 0)/* Quit if error */
  598. return;
  599. if(!rc)
  600. #if EXE386
  601. DataPackLim = CBMAXSEG32; /* Default limit is 4Gb */
  602. #else
  603. DataPackLim = LXIVK; /* Default limit is 64K */
  604. else if(DataPackLim > LXIVK) /* If limit set too high */
  605. SwitchErr = ER_swpack;
  606. #endif
  607. }
  608. LOCAL void NEAR SwNoPackFunctions()// DO NOT eliminate uncalled COMDATs
  609. {
  610. fPackFunctions = (FTYPE) FALSE;
  611. }
  612. LOCAL void NEAR SwPackFunctions()// DO eliminate uncalled COMDATs
  613. {
  614. #if TCE
  615. SBTYPE SwString;
  616. int rc;
  617. #endif
  618. fPackFunctions = (FTYPE) TRUE;
  619. #if TCE
  620. if ((rc = ParseStr(SwString)) <= 0) // Done if no num or error
  621. return;
  622. if (SwString[1] == 'M' || SwString[1] == 'm')
  623. {
  624. fTCE = (FTYPE) TRUE; // /PACKF:MAX = perform TCE
  625. fprintf(stdout, "\r\nTCE is active. ");
  626. }
  627. #endif
  628. }
  629. LOCAL void NEAR SwFarCall() /* Enable far call optimization */
  630. {
  631. fFarCallTrans = (FTYPE) TRUE;
  632. }
  633. #endif /* OEXE */
  634. #if DOSEXTENDER
  635. LOCAL void NEAR SwRunReal(void)
  636. {
  637. OutWarn(ER_rnotfirst);
  638. }
  639. #endif
  640. /***************************************************************/
  641. /* Options for DOS3 exe format. */
  642. #if ODOS3EXE
  643. LOCAL void NEAR SwDSAlloc() /* DS allocation requested */
  644. {
  645. if(!fSegOrder) vfDSAlloc = (FTYPE) TRUE; /* Set flag if not overridden */
  646. }
  647. #if OVERLAYS
  648. LOCAL void NEAR SwDynamic(void)
  649. {
  650. unsigned long cThunks;
  651. int rc;
  652. if ((rc = ParseNo(&cThunks)) < 0)
  653. return; /* Bad argument */
  654. fDynamic = (FTYPE) TRUE;
  655. fFarCallTrans = (FTYPE) TRUE;
  656. fPackSet = (FTYPE) TRUE;
  657. packLim = LXIVK - 36; /* Default limit is 64K - 36 */
  658. if (!rc)
  659. cThunks = 256;
  660. else if (cThunks > LXIVK / OVLTHUNKSIZE)
  661. {
  662. char buf[17];
  663. cThunks = LXIVK / OVLTHUNKSIZE;
  664. OutWarn(ER_arginvalid, "DYNAMIC", _itoa((WORD)cThunks, buf, 10));
  665. }
  666. ovlThunkMax = (WORD) cThunks;
  667. }
  668. LOCAL void NEAR SwOldOvl(void)
  669. {
  670. fOldOverlay = (FTYPE) TRUE;
  671. fDynamic = (FTYPE) FALSE;
  672. }
  673. #endif
  674. LOCAL void NEAR SwHigh() /* Load high */
  675. {
  676. if(!fSegOrder)
  677. {
  678. #if FEXEPACK
  679. if (fExePack == (FTYPE) TRUE)
  680. {
  681. OutWarn(ER_loadhi);
  682. fExePack = FALSE;
  683. }
  684. #endif
  685. cparMaxAlloc = 0; /* Dirty trick! */
  686. }
  687. }
  688. #if OVERLAYS
  689. LOCAL void NEAR SwIntNo()
  690. {
  691. unsigned long intno;
  692. int rc;
  693. if((rc = ParseNo(&intno)) < 0) /* Quit if error */
  694. return;
  695. if(rc == 0 || intno > 255) /* If no number or num exceeds 255 */
  696. SwitchErr = ER_swovl;
  697. else vintno = (BYTE) intno; /* Else store interrupt number */
  698. }
  699. #endif
  700. LOCAL void NEAR SwCParMax()
  701. {
  702. unsigned long cparmax;
  703. int rc;
  704. if((rc = ParseNo(&cparmax)) < 0) /* Quit if error */
  705. return;
  706. if(rc == 0 || cparmax > 0xffffL) /* If no number or num exceeds ffff */
  707. SwitchErr = ER_swcpar;
  708. else cparMaxAlloc = (WORD) cparmax; /* Else store cparMaxAlloc */
  709. }
  710. LOCAL void NEAR SwNoGrp()
  711. {
  712. fNoGrpAssoc = (FTYPE) TRUE; /* Don't associate publics w/ groups */
  713. }
  714. #endif /* ODOS3EXE */
  715. /***************************************************************/
  716. /* Options for ILINK-version */
  717. #if ILINK
  718. LOCAL void NEAR SwIncremental() /* Incremental linking support */
  719. {
  720. //fIncremental = (FTYPE) !fZincr;
  721. fIncremental = (FTYPE) FALSE; //INCR support dropped in 5.30.30
  722. }
  723. #endif
  724. LOCAL void NEAR SwPadCode() /* Code padding */
  725. {
  726. long num;
  727. int rc;
  728. if((rc = ParseNo(&num)) < 0)
  729. return;
  730. /* PADCODE:xxx option specifies code padding size */
  731. if(rc)
  732. {
  733. if(num < 0 || num > 0x8000)
  734. SwitchErr = ER_swbadnum;
  735. else cbPadCode = (WORD) num;
  736. }
  737. }
  738. LOCAL void NEAR SwPadData() /* Data padding */
  739. {
  740. long num;
  741. int rc;
  742. if((rc = ParseNo(&num)) < 0)
  743. return;
  744. /* PADDATA:xxx option specifies data padding size */
  745. if(rc)
  746. {
  747. if(num < 0 || num > 0x8000)
  748. SwitchErr = ER_swbadnum;
  749. else cbPadData = (WORD) num;
  750. }
  751. }
  752. /***************************************************************/
  753. /* Switches for segmented x.out format */
  754. #if OIAPX286
  755. LOCAL void NEAR SwAbsolute ()
  756. {
  757. if(!cbStack)
  758. ParseNo(&absAddr);
  759. }
  760. LOCAL void NEAR SwNoPack() /* Disable code packing */
  761. {
  762. fPack = FALSE;
  763. }
  764. LOCAL void NEAR SwTextbias ()
  765. {
  766. long num;
  767. if(ParseNo(&num) > 0)
  768. stBias = num;
  769. }
  770. LOCAL void NEAR SwDatabias ()
  771. {
  772. long num;
  773. if(ParseNo(&num) > 0)
  774. stDataBias = num;
  775. }
  776. LOCAL void NEAR SwPagesize ()
  777. {
  778. long num;
  779. if(ParseNo(&num) > 0)
  780. cblkPage = num >> 9;
  781. }
  782. LOCAL void NEAR SwTextrbase ()
  783. {
  784. long num;
  785. if(ParseNo(&num) > 0)
  786. rbaseText = num;
  787. }
  788. LOCAL void NEAR SwDatarbase ()
  789. {
  790. long num;
  791. if(ParseNo(&num) > 0)
  792. rbaseData = num;
  793. }
  794. LOCAL void NEAR SwVmod ()
  795. {
  796. long num;
  797. if(ParseNo(&num) <= 0)
  798. return;
  799. switch(num)
  800. {
  801. case 0:
  802. xevmod = XE_VMOD;
  803. break;
  804. case 1:
  805. xevmod = XE_EXEC | XE_VMOD;
  806. break;
  807. default:
  808. SwitchErr = ER_swbadnum;
  809. }
  810. }
  811. #endif /* OIAPX286 */
  812. #if OXOUT OR OIAPX286
  813. LOCAL void NEAR SwNosymbols ()
  814. {
  815. fSymbol = FALSE;
  816. }
  817. LOCAL void NEAR SwMixed ()
  818. {
  819. fMixed = (FTYPE) TRUE;
  820. }
  821. LOCAL void NEAR SwLarge ()
  822. {
  823. fLarge = (FTYPE) TRUE;
  824. SwMedium();
  825. }
  826. LOCAL void NEAR SwMedium()
  827. {
  828. fMedium = (FTYPE) TRUE; /* Medium model */
  829. fIandD = (FTYPE) TRUE; /* Separate code and data */
  830. }
  831. LOCAL void NEAR SwPure()
  832. {
  833. fIandD = (FTYPE) TRUE; /* Separate code and data */
  834. }
  835. #endif /* OXOUT OR OIAPX286 */
  836. /* Options for linker profiling */
  837. #if LNKPROF
  838. char fP1stop = FALSE; /* Stop after pass 1 */
  839. LOCAL void NEAR SwPass1()
  840. {
  841. fP1stop = (FTYPE) TRUE;
  842. }
  843. #endif /* LNKPROF */
  844. /* Special options */
  845. #if QBLIB
  846. LOCAL void NEAR SwQuicklib() /* Create a QB userlibrary */
  847. {
  848. #if FEXEPACK
  849. /* If /EXEPACK given, issue fatal error. */
  850. if(fExePack)
  851. Fatal(ER_swqe);
  852. #endif
  853. fQlib = (FTYPE) TRUE;
  854. SwDosseg(); /* /QUICKLIB forces /DOSSEG */
  855. fNoExtDic = (FTYPE) TRUE; /* /QUICKLIB forces /NOEXTDICTIONARY */
  856. }
  857. #endif
  858. #if (QCLINK) AND NOT EXE386
  859. typedef int (cdecl far * FARFPTYPE)(int, ...);/* Far function pointer type */
  860. extern FARFPTYPE far *pfQTab; /* Table of addresses */
  861. #pragma check_stack(on)
  862. /*
  863. * PromptQC : output a prompt to the QC prompt routine
  864. *
  865. * Call pfQTab[1] with parameters described below.
  866. * Returns:
  867. * always TRUE
  868. *
  869. * QCPrompt : display a message with a prompt
  870. *
  871. * void far QCPrompt (type, msg1, msg2, msg3, pResponse)
  872. * short type; /* type of message, as follows:
  873. * 0 = undefined
  874. * 1 = edit field required (e.g. file name)
  875. * 2 = wait for some action
  876. * all other values undefined
  877. * Any of the following fields may be NULL:
  878. * char far *msg1; /* 1st message (error)
  879. * char far *msg2; /* 2nd message (file name)
  880. * char far *msg3; /* 3rd message (prompt text)
  881. * char far *pResponse; /* Pointer to buffer in which to
  882. * * store response.
  883. */
  884. int cdecl PromptQC (sbNew,msg,msgparm,pmt,pmtparm)
  885. BYTE *sbNew; /* Buffer for response */
  886. MSGTYPE msg; /* Error message */
  887. int msgparm; /* Message parameter */
  888. MSGTYPE pmt; /* Prompt */
  889. int pmtparm; /* Prompt parameter */
  890. {
  891. int type;
  892. SBTYPE message;
  893. SBTYPE prompt;
  894. if(sbNew != NULL)
  895. type = 1;
  896. else
  897. type = 2;
  898. sprintf(message,GetMsg(msg),msgparm);
  899. sprintf(prompt,GetMsg(pmt),pmtparm);
  900. /* Return value of 1 means interrupt. */
  901. if((*pfQTab[1])(type,(char far *) message,0L,(char far *)prompt,
  902. (char far *) sbNew) == 1)
  903. UserKill();
  904. return(TRUE);
  905. }
  906. #pragma check_stack(off)
  907. /*
  908. * CputcQC : console character output routine for QC
  909. */
  910. void CputcQC (ch)
  911. int ch;
  912. {
  913. }
  914. /*
  915. * CputsQC : console string output routine for QC
  916. */
  917. void CputsQC (str)
  918. char *str;
  919. {
  920. }
  921. /*
  922. * SwZ1 : process /Z1:address
  923. *
  924. * /Z1 is a special undocumented switch for QC. It contains
  925. * the address of a table of routines to use for console I/O.
  926. */
  927. LOCAL void NEAR SwZ1 (void) /* Get address for message I/O */
  928. {
  929. long num;
  930. extern FARFPTYPE far
  931. *pfQTab; /* Table of addresses */
  932. if(ParseNo(&num) <= 0)
  933. return;
  934. pfQTab = (FARFPTYPE far *) num;
  935. pfPrompt = PromptQC;
  936. fNoprompt = FALSE; /* Disable /NOPROMPT */
  937. fNoBanner = (FTYPE) TRUE;
  938. pfCputc = CputcQC;
  939. pfCputs = CputsQC;
  940. fZ1 = (FTYPE) TRUE;
  941. }
  942. /*
  943. * /Zincr is a special undocumented switch for QC. It is required
  944. * for "ILINK-breaking" errors. If ILINK encounters one of these errors,
  945. * it ivokes the linker w /ZINCR which override /INCR.
  946. */
  947. LOCAL void NEAR SwZincr(void)
  948. {
  949. fZincr = (FTYPE) TRUE;
  950. }
  951. #endif
  952. #if Z2_ON OR (QCLINK AND NOT EXE386)
  953. /*
  954. * SwZ2 : process /Z2
  955. *
  956. * /Z2 is another special undocumented switch for QC.
  957. * It causes deletion of responce file passed to the linker.
  958. */
  959. LOCAL void NEAR SwZ2 (void)
  960. {
  961. fZ2 = (FTYPE) TRUE;
  962. }
  963. #endif
  964. /* Structure for table of linker options */
  965. struct option
  966. {
  967. char *sbSwitch; /* length-prefixed switch string */
  968. #ifdef M68000
  969. int (*proc)(); /* pointer to switch function */
  970. #else
  971. void (NEAR *proc)(); /* pointer to switch function */
  972. #endif
  973. };
  974. /* Table of linker options */
  975. LOCAL struct option switchTab[] =
  976. {
  977. #if NOT WIN_3
  978. { "\01?", SwShortHelp },
  979. #endif
  980. #if OIAPX286
  981. { "\017ABSOLUTEADDRESS", SwAbsolute },
  982. #endif
  983. #if OSEGEXE AND NOT QCLINK
  984. { "\011ALIGNMENT", SwAlign },
  985. #endif
  986. { "\005BATCH", SwBatch },
  987. #if LNKPROF
  988. { "\007BUFSIZE", SwBufsize },
  989. #endif
  990. #if SYMDEB
  991. { "\010CODEVIEW", SwSymdeb },
  992. #endif
  993. #if ODOS3EXE
  994. { "\014CPARMAXALLOC", SwCParMax },
  995. #endif
  996. #if OIAPX286
  997. { "\010DATABIAS", SwDatabias },
  998. { "\011DATARBASE", SwDatarbase },
  999. #endif
  1000. #if ODOS3EXE
  1001. { "\013DOSEXTENDER", SwDosExtend },
  1002. #endif
  1003. #if OEXE
  1004. { "\006DOSSEG", SwDosseg },
  1005. #endif
  1006. #if ODOS3EXE
  1007. { "\012DSALLOCATE", SwDSAlloc },
  1008. #if OVERLAYS
  1009. { "\007DYNAMIC", SwDynamic },
  1010. #endif
  1011. #endif
  1012. #if FEXEPACK
  1013. { "\007EXEPACK", SwExePack },
  1014. #endif
  1015. #if OEXE
  1016. { "\022FARCALLTRANSLATION", SwFarCall },
  1017. #endif
  1018. #if EXE386
  1019. { "\006HEADER", SwHeader },
  1020. #endif
  1021. #if NOT WIN_3
  1022. { "\004HELP",
  1023. #if C8_IDE
  1024. SwShortHelp },
  1025. #else
  1026. SwHelp },
  1027. #endif
  1028. #endif
  1029. #if ODOS3EXE
  1030. { "\004HIGH", SwHigh },
  1031. #endif
  1032. #if NOT IGNORECASE
  1033. { "\012IGNORECASE", SwCase },
  1034. #endif
  1035. #if EXE386
  1036. { "\016IMAGEALIGNMENT", SwMemAlign },
  1037. #endif
  1038. #if ILINK AND NOT IBM_LINK
  1039. { "\013INCREMENTAL", SwIncremental },
  1040. #endif
  1041. #if FDEBUG
  1042. { "\013INFORMATION", SwInfo },
  1043. #endif
  1044. #if OSEGEXE AND OUT_EXP
  1045. { "\004IDEF", SwIdef },
  1046. #endif
  1047. #if (OSEGEXE AND defined(LEGO)) OR EXE386
  1048. { "\012KEEPFIXUPS", SwKeepFixups },
  1049. #endif
  1050. #if EXE386
  1051. { "\012KEEPVSIZE", SwKeepVSize },
  1052. #endif
  1053. #if OIAPX286
  1054. { "\005LARGE", SwLarge },
  1055. #endif
  1056. { "\013LINENUMBERS", SwLineNos },
  1057. #if LOCALSYMS
  1058. { "\014LOCALSYMBOLS", SwLocals },
  1059. #endif
  1060. #if O68K
  1061. { "\011MACINTOSH", SwMac },
  1062. #endif /* O68K */
  1063. { "\003MAP", SwMap },
  1064. #if OXOUT OR OIAPX286
  1065. { "\006MEDIUM", SwMedium },
  1066. { "\005MIXED", SwMixed },
  1067. #endif
  1068. #if NOT EXE386
  1069. { "\010KNOWEAS", SwNewFiles },
  1070. #endif
  1071. { "\026NODEFAULTLIBRARYSEARCH",
  1072. SwNoDefLib },
  1073. #if LIBMSDOS
  1074. { "\017NOEXTDICTIONARY", SwNoExtDic },
  1075. #endif
  1076. #if OEXE
  1077. { "\024NOFARCALLTRANSLATION",
  1078. SwNoFarCall },
  1079. #endif
  1080. #if ODOS3EXE
  1081. { "\022NOGROUPASSOCIATION", SwNoGrp },
  1082. #endif
  1083. #if IGNORECASE
  1084. { "\014NOIGNORECASE", SwCase },
  1085. #endif
  1086. #if TIMINGS
  1087. { "\002BT", SwShowTiming },
  1088. #endif // TIMINGS
  1089. { "\006NOLOGO", SwNologo },
  1090. { "\015NONULLSDOSSEG", SwNonulls },
  1091. { "\012NOPACKCODE", SwNoPack },
  1092. { "\017NOPACKFUNCTIONS", SwNoPackFunctions },
  1093. #if OXOUT OR OIAPX286
  1094. { "\011NOSYMBOLS", SwNosymbols },
  1095. #endif
  1096. #if USE_REAL
  1097. { "\011NOFREEMEM", SwNoUseReal },
  1098. #endif
  1099. #if OVERLAYS
  1100. { "\012OLDOVERLAY", SwOldOvl },
  1101. #endif
  1102. { "\007ONERROR", SwDelexe },
  1103. #if OVERLAYS
  1104. { "\020OVERLAYINTERRUPT", SwIntNo },
  1105. #endif
  1106. { "\010PACKCODE", SwPack },
  1107. { "\010PACKDATA", SwPackData },
  1108. { "\015PACKFUNCTIONS", SwPackFunctions },
  1109. #if ILINK AND NOT IBM_LINK
  1110. { "\007PADCODE", SwPadCode },
  1111. { "\007PADDATA", SwPadData },
  1112. #endif
  1113. #if OIAPX286
  1114. { "\010PAGESIZE", SwPagesize },
  1115. #endif
  1116. #if OSMSDOS
  1117. { "\005PAUSE", SwPause },
  1118. #endif
  1119. #if LNKPROF
  1120. { "\005PASS1", SwPass1 },
  1121. #endif
  1122. #if PCODE
  1123. { "\005PCODE", SwPCode },
  1124. #endif
  1125. #if OSEGEXE AND NOT (QCLINK OR EXE386)
  1126. { "\006PMTYPE", SwPmType },
  1127. #endif
  1128. #if OXOUT OR OIAPX286
  1129. { "\004PURE", SwPure },
  1130. #endif
  1131. #if QBLIB
  1132. { "\014QUICKLIBRARY", SwQuicklib },
  1133. #endif
  1134. #if DOSEXTENDER AND NOT WIN_NT
  1135. { "\001r", SwRunReal },
  1136. #endif
  1137. { "\010SEGMENTS", SwSegments },
  1138. { "\005STACK", SwStack },
  1139. #if OIAPX286
  1140. { "010TEXTBIAS", SwTextbias },
  1141. { "\011TEXTRBASE", SwTextrbase },
  1142. #endif
  1143. #if ODOS3EXE
  1144. { "\004TINY", SwBinary },
  1145. #endif
  1146. #if PERFORMANCE
  1147. { "\030VIRTUALMEMORYPERFORMANCE",
  1148. SwVMPerf },
  1149. #endif
  1150. #if OIAPX286
  1151. { "\004VMOD", SwVmod },
  1152. #endif
  1153. #if OSEGEXE AND NOT QCLINK
  1154. { "\011WARNFIXUP", SwWarnFixup },
  1155. #endif
  1156. #if OSEGEXE AND NOT EXE386 AND QCLINK
  1157. { "\002Z1", SwZ1 },
  1158. #endif
  1159. #if Z2_ON OR QCLINK
  1160. { "\002Z2", SwZ2 },
  1161. #endif
  1162. #if QCLINK
  1163. { "\005ZINCR", SwZincr },
  1164. #endif
  1165. { NULL, 0}
  1166. };
  1167. #if QCLINK
  1168. #define SWSTOP &switchTab[(sizeof(switchTab)/sizeof(struct option)) - 5]
  1169. #else
  1170. #if EXE386
  1171. #define SWSTOP &switchTab[(sizeof(switchTab)/sizeof(struct option)) - 2]
  1172. #else
  1173. #define SWSTOP &switchTab[(sizeof(switchTab)/sizeof(struct option)) - 2]
  1174. #endif
  1175. #endif
  1176. #define FIELDLENGTH 28
  1177. #if NOT WIN_3
  1178. LOCAL void NEAR SwShortHelp() /* Print valid switches */
  1179. {
  1180. struct option *pTab; /* Option table pointer */
  1181. int toggle = 1;
  1182. int n;
  1183. #if CMDMSDOS
  1184. /* Maybe display banner here, in case /NOLOGO seen first. */
  1185. DisplayBanner();
  1186. #endif
  1187. fputs(GetMsg(P_usage1),stdout);
  1188. fputs(GetMsg(P_usage2),stdout);
  1189. fputs(GetMsg(P_usage3),stdout);
  1190. fputs(GetMsg(P_switches),stdout);
  1191. NEWLINE(stdout);
  1192. for(pTab = switchTab; pTab < SWSTOP; ++pTab)
  1193. {
  1194. // Don't display undocumented swiches
  1195. if (pTab->proc == &SwNewFiles)
  1196. {
  1197. continue;
  1198. }
  1199. if (pTab->proc == &SwDosExtend)
  1200. {
  1201. continue;
  1202. }
  1203. #ifdef LEGO
  1204. #if OSEGEXE
  1205. if (pTab->proc == &SwKeepFixups)
  1206. continue;
  1207. #endif
  1208. #endif /* LEGO */
  1209. fputs(" /",stdout);
  1210. fwrite(&pTab->sbSwitch[1],1,B2W(pTab->sbSwitch[0]),stdout);
  1211. /* Output switches in two columns */
  1212. if(toggle ^= 1)
  1213. NEWLINE(stdout);
  1214. else for(n = FIELDLENGTH - B2W(pTab->sbSwitch[0]); n > 0; --n)
  1215. fputc(' ',stdout);
  1216. }
  1217. NEWLINE(stdout);
  1218. fflush(stdout);
  1219. #if USE_REAL
  1220. RealMemExit();
  1221. #endif
  1222. exit(0);
  1223. }
  1224. #endif
  1225. LOCAL void NEAR SwDelexe() // Supress .EXE generation if errors occur
  1226. {
  1227. SBTYPE SwString;
  1228. int rc;
  1229. vfMap = (FTYPE) TRUE; // Set flag
  1230. if ((rc = ParseStr(SwString)) == 0) // NOEXE not present
  1231. {
  1232. OutWarn(ER_opnoarg, "ONERROR");
  1233. return;
  1234. }
  1235. if (SwString[1] == 'N' || SwString[1] == 'n')
  1236. {
  1237. fDelexe = TRUE; // ONERROR:NOEXE
  1238. }
  1239. else
  1240. { // ONERROR:????
  1241. OutWarn(ER_opnoarg, "ONERROR");
  1242. return;
  1243. }
  1244. }
  1245. #if (OSEGEXE AND defined(LEGO)) OR EXE386
  1246. LOCAL void NEAR SwKeepFixups(void)
  1247. {
  1248. fKeepFixups = (FTYPE) TRUE;
  1249. }
  1250. #endif
  1251. #if EXE386
  1252. LOCAL void NEAR SwHeader() // Set executable header size
  1253. {
  1254. int rc;
  1255. DWORD newSize;
  1256. if ((rc = ParseNo(&newSize)) < 0) // Quit if error
  1257. return;
  1258. if (rc)
  1259. hdrSize = ((newSize << 10) + 0xffffL) & ~0xffffL;
  1260. }
  1261. LOCAL void NEAR SwKeepVSize(void)
  1262. {
  1263. fKeepVSize = (FTYPE) TRUE;
  1264. }
  1265. #endif
  1266. #if NOT WIN_3
  1267. LOCAL void NEAR SwHelp() /* Print valid switches */
  1268. {
  1269. intptr_t exitCode;
  1270. char *pszPath;
  1271. char *pszQH;
  1272. char *pszHELPFILES;
  1273. char FAR *lpch;
  1274. char *pch;
  1275. int len;
  1276. // Try to use QuickHelp - this is tricky; We have stubbed the
  1277. // C run-time environment setup, so spawnlp has no way of
  1278. // searching the path. Here we first add the path to C run-time
  1279. // environemt table and then invoke spawnlp.
  1280. if (lpszPath)
  1281. {
  1282. // Recreate C run-time PATH variable
  1283. len = FSTRLEN(lpszPath);
  1284. if ((pszPath = calloc(len + 6, sizeof(char))) != NULL)
  1285. {
  1286. strcpy(pszPath, "PATH=");
  1287. for (lpch = lpszPath, pch = pszPath + 5; len > 0; len--)
  1288. *pch++ = *lpch++;
  1289. _putenv(pszPath);
  1290. }
  1291. }
  1292. if (lpszQH)
  1293. {
  1294. // Recreate C run-time QH variable
  1295. len = FSTRLEN(lpszQH);
  1296. if ((pszQH = calloc(len + 4, sizeof(char))) != NULL)
  1297. {
  1298. strcpy(pszQH, "QH=");
  1299. for (lpch = lpszQH, pch = pszQH + 3; len > 0; len--)
  1300. *pch++ = *lpch++;
  1301. _putenv(pszQH);
  1302. }
  1303. }
  1304. if (lpszHELPFILES)
  1305. {
  1306. // Recreate C run-time HELPFILES variable
  1307. len = FSTRLEN(lpszHELPFILES);
  1308. if ((pszHELPFILES = calloc(len + 12, sizeof(char))) != NULL)
  1309. {
  1310. strcpy(pszHELPFILES, "HELPFILES=");
  1311. for (lpch = lpszHELPFILES, pch = pszHELPFILES + 10; len > 0; len--)
  1312. *pch++ = *lpch++;
  1313. _putenv(pszHELPFILES);
  1314. }
  1315. }
  1316. #if USE_REAL
  1317. RealMemExit();
  1318. #endif
  1319. exitCode = _spawnlp(P_WAIT, "QH.EXE", "qh", "/u link.exe", NULL);
  1320. if (exitCode < 0 || exitCode == 3)
  1321. SwShortHelp();
  1322. exit(0);
  1323. }
  1324. #endif
  1325. /****************************************************************
  1326. * *
  1327. * BadFlag: *
  1328. * *
  1329. * This function takes as its argument a pointer to a length- *
  1330. * prefixed string containing an invalid switch. It goes *
  1331. * through the customary contortions of dying with grace. *
  1332. * *
  1333. ****************************************************************/
  1334. LOCAL void NEAR BadFlag(psb,errnum)
  1335. BYTE *psb; /* Pointer to the bad switch */
  1336. MSGTYPE errnum; /* Error number */
  1337. {
  1338. psb[B2W(psb[0]) + 1] = '\0'; /* Null-terminate it */
  1339. Fatal(errnum,psb + 1);
  1340. }
  1341. /****************************************************************
  1342. * *
  1343. * FPrefix: *
  1344. * *
  1345. * This function takes as its arguments two pointers to *
  1346. * length-prefixed strings. It returns true if the second is *
  1347. * a prefix of the first. *
  1348. * *
  1349. ****************************************************************/
  1350. LOCAL int NEAR FPrefix(psb1,psb2)
  1351. BYTE *psb1; /* Pointer to first string */
  1352. BYTE *psb2; /* Pointer to second string */
  1353. {
  1354. REGISTER WORD len; /* Length of string 2 */
  1355. if((len = B2W(psb2[0])) > B2W(psb1[0])) return(FALSE);
  1356. /* String 2 cannot be longer */
  1357. while(len) /* Compare the strings */
  1358. {
  1359. if(UPPER(psb2[len]) != UPPER(psb1[len])) return(FALSE);
  1360. /* Check for mismatch */
  1361. --len; /* Decrement index */
  1362. }
  1363. return(TRUE); /* 2 is a prefix of 1 */
  1364. }
  1365. /****************************************************************
  1366. * *
  1367. * ProcFlag: *
  1368. * *
  1369. * This function takes as its argument a length-prefixed *
  1370. * string containing a single '/-type' flag. It processes it, *
  1371. * but does not return a meaningful value. *
  1372. * *
  1373. ****************************************************************/
  1374. void ProcFlag(psb) /* Process a flag */
  1375. BYTE *psb; /* Pointer to flag string */
  1376. {
  1377. struct option *pTab; /* Pointer to option table */
  1378. struct option *pTabMatch; /* Pointer to matching entry */
  1379. WORD ich3; /* Index */
  1380. WORD ich4; /* Index */
  1381. pTabMatch = NULL; /* Not found */
  1382. if((ich3 = IFind(psb,':')) == INIL)
  1383. ich3 = B2W(psb[0]); /* Get index to colon */
  1384. ich4 = B2W(psb[0]); /* Save the original length */
  1385. psb[0] = (BYTE) ich3; /* Set new length */
  1386. for(pTab = switchTab; pTab->sbSwitch; pTab++)
  1387. { /* Loop thru switch table */
  1388. if(FPrefix(pTab->sbSwitch,psb))
  1389. { /* If we've identified the switch */
  1390. if(pTabMatch) /* If there was a previous match */
  1391. BadFlag(psb,ER_swambig);/* Ambiguous switch */
  1392. pTabMatch = pTab; /* Save the match */
  1393. }
  1394. }
  1395. if(!pTabMatch) /* If no match found */
  1396. {
  1397. psb[psb[0]+1] = '\0';
  1398. OutWarn(ER_swunrecw,&psb[1]); /* Unrecognized switch */
  1399. return;
  1400. }
  1401. psb[0] = (BYTE) ich4; /* Restore original length */
  1402. osbSwitch = psb; /* Pass the switch implicitly */
  1403. SwitchErr = 0; /* Assume no error */
  1404. (*pTabMatch->proc)(); /* Invoke the processing procedure */
  1405. if(SwitchErr) BadFlag(psb,SwitchErr); /* Check for errors */
  1406. }
  1407. #pragma check_stack(on)
  1408. /****************************************************************
  1409. * *
  1410. * PeelFlags: *
  1411. * *
  1412. * This function takes as its argument a pointer to a length- *
  1413. * prefixed string of bytes. It "peels/processes all '/-type' *
  1414. * switches." It does not return a meaningful value. *
  1415. * *
  1416. ****************************************************************/
  1417. void PeelFlags(psb) /* Peel/process flags */
  1418. BYTE *psb; /* Pointer to a byte string */
  1419. {
  1420. REGISTER WORD ich; /* Index */
  1421. SBTYPE sbFlags; /* The flags */
  1422. if((ich = IFind(psb,CHSWITCH)) != INIL)
  1423. { /* If a switch found */
  1424. memcpy(&sbFlags[1],&psb[ich + 2],B2W(psb[0]) - ich - 1);
  1425. /* Move flags to flag buffer */
  1426. sbFlags[0] = (BYTE) ((psb[0]) - ich - 1);
  1427. /* Set the length of flags */
  1428. while(psb[ich] == ' ' && ich) --ich;
  1429. /* Delete trailing spaces */
  1430. psb[0] = (BYTE) ich; /* Reset length of input line */
  1431. ich = sbFlags[0];
  1432. while((sbFlags[ich] == ' ' ||
  1433. sbFlags[ich] == ';' ||
  1434. sbFlags[ich] == ',' ) && ich) --ich;
  1435. /* Delete unwanted characters */
  1436. sbFlags[0] = (BYTE) ich;
  1437. BreakLine(sbFlags,ProcFlag,CHSWITCH);
  1438. /* Process the switch */
  1439. }
  1440. }
  1441. #pragma check_stack(off)