Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1590 lines
42 KiB

  1. /* asmmain.c -- microsoft 80x86 assembler
  2. **
  3. ** microsoft (r) macro assembler
  4. ** copyright (c) microsoft corp 1986. all rights reserved
  5. **
  6. ** randy nevin
  7. **
  8. ** 10/90 - Quick conversion to 32 bit by Jeff Spencer
  9. */
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #ifndef FLATMODEL
  15. #include <signal.h>
  16. #endif
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #define ASMGLOBAL
  20. #include "asm86.h"
  21. #include "asmfcn.h"
  22. #include "asmctype.h"
  23. #include <fcntl.h>
  24. #include <time.h>
  25. #ifdef MSDOS
  26. # include <dos.h>
  27. # include <share.h>
  28. # include <io.h>
  29. # if defined CPDOS && !defined OS2_2
  30. # include <doscalls.h>
  31. # endif
  32. #endif
  33. //extern char *strrchr();
  34. //extern char *strchr();
  35. #include "asmmsg.h"
  36. static VOID panic(); /* defined below */
  37. long farAvail(void);
  38. #if defined MSDOS && !defined FLATMODEL
  39. UCHAR * PASCAL ctime();
  40. #else
  41. // extern long time(); /* Use C library functions */
  42. // extern UCHAR *ctime();
  43. // extern long _lseek();
  44. #endif /* MSDOS */
  45. #if defined M8086OPT
  46. extern char qlcname[]; /* defined in asmhelp.asm */
  47. extern char qname[]; /* defined in asmhelp.asm */
  48. extern char qsvlcname[]; /* defined in asmhelp.asm */
  49. extern char qsvname[]; /* defined in asmhelp.asm */
  50. UCHAR *naim = qname;
  51. UCHAR *svname = qsvname;
  52. #else
  53. static UCHAR qname[SYMMAX + 1];
  54. static UCHAR qlcname[SYMMAX + 1];
  55. static UCHAR qsvname[SYMMAX + 1];
  56. static UCHAR qsvlcname[SYMMAX + 1];
  57. FASTNAME naim = {qname, qlcname, 0, 0};
  58. FASTNAME svname = {qsvname, qsvlcname, 0, 0};
  59. #endif
  60. UCHAR X87type;
  61. char *argv0;
  62. char *atime;
  63. char *begatom;
  64. char addplusflagCur;
  65. char ampersand;
  66. char baseName[25] = "@FileName=";
  67. USHORT blocklevel;
  68. char caseflag = DEF_CASE;
  69. char checkpure; /* do checks for pure code? */
  70. OFFSET clausesize;
  71. char condflag;
  72. USHORT condlevel; /* conditional level */
  73. USHORT count;
  74. UCHAR cputype = DEF_CPU;
  75. SHORT wordszdefault = 2;
  76. #ifdef V386
  77. SHORT wordsize = 2; /* preprocessor constant in other ver */
  78. #endif
  79. OFFSET cbProcParms;
  80. OFFSET cbProcLocals;
  81. USHORT crefcount;
  82. UCHAR crefinc;
  83. UCHAR cpu;
  84. char crefopt = 0;
  85. char crefing = DEF_CREFING;
  86. char crefnum[CREFINF] = {
  87. /* CREFEND */ 4, /* End of line */
  88. /* REF */ 1, /* Reference */
  89. /* DEF */ 2 /* Define */
  90. };
  91. UCHAR creftype;
  92. struct fileptr crf;
  93. SYMBOL FARSYM *curgroup;
  94. USHORT codeview; /* codeveiw obj level = 0 => CVNONE */
  95. PFPOSTRUCT pFpoHead = 0;
  96. PFPOSTRUCT pFpoTail = 0;
  97. unsigned long numFpoRecords = 0;
  98. #ifdef DEBUG
  99. FILE *d_df;
  100. long d_debug = 0; /* debug selection */
  101. long d_dlevel = 0; /* debug level selection */
  102. long d_indent = 0; /* debug output indention count */
  103. long d_sindent = 0; /* indentation printing temporary */
  104. #endif /* DEBUG */
  105. /* note that TDW has to be last */
  106. USHORT datadsize[TMACRO - TDB + 1] = {
  107. /* TDB */ 1,
  108. /* TDD */ 4,
  109. /* TDQ */ 8,
  110. /* TDT */ 10,
  111. /* TDF */ 6,
  112. /* TDW */ 2,
  113. /* TMACRO */ 0
  114. };
  115. char debug = DEF_DEBUG; /* true if debug set */
  116. UCHAR delim;
  117. char displayflag;
  118. char dumpsymbols = DEF_DUMPSYM; /* symbol table display if true */
  119. char dupflag;
  120. USHORT duplevel; /* indent for dup listing */
  121. char elseflag;
  122. char emittext = TRUE; /* emit linker text if true */
  123. struct dscrec emptydsc;
  124. char emulatethis;
  125. char *endatom;
  126. char endbody;
  127. char equdef;
  128. char equflag;
  129. char equsel;
  130. SHORT errorcode;
  131. USHORT errorlineno;
  132. USHORT errornum; /* error count */
  133. char exitbody;
  134. char expandflag;
  135. USHORT externnum = 1;
  136. SYMBOL FARSYM *firstsegment;
  137. UCHAR fixvalues[] = {
  138. /* FPOINTER */ 3,
  139. /* FOFFSET */ 1,
  140. /* FBASESEG */ 2,
  141. /* FGROUPSEG */ 1,
  142. /* FCONSTANT */ 0,
  143. /* FHIGH */ 4,
  144. /* FLOW */ 0,
  145. /* FNONE */ 0,
  146. /* F32POINTER*/ 11,
  147. /* F32OFFSET */ 9,
  148. /* DIR32NB */ 14,
  149. };
  150. char fDosSeg;
  151. char fSimpleSeg;
  152. char fCheckRes;
  153. UCHAR fCrefline;
  154. char fSecondArg;
  155. char f386already;
  156. char fArth32;
  157. char fProcArgs;
  158. struct dscrec *fltdsc;
  159. char fltemulate = DEF_FLTEMULATE;
  160. USHORT fltfixmisc[9][2] = { /* fixup characters */
  161. 'E', 0, 'C', 0, 'S', 0, 'A', 0, 'C', 0,
  162. 'S', 0, 'A', 0, 'D', 0, 'W', 0
  163. };
  164. USHORT fltselect[4][2] = {
  165. /* [TDD][0] */ 5, /* Single precision non IEEE */
  166. /* [TDD][1] */ 3, /* Single precision IEEE */
  167. /* [TDQ][0] */ 4, /* Double precision non IEEE */
  168. /* [TDQ][1] */ 2, /* Double precision IEEE */
  169. /* [TDT][0] */ 1, /* No temp real - use double */
  170. /* [TDT][1] */ 1 /* 80 bit precision IEEE */
  171. };
  172. char *fname;
  173. UCHAR fKillPass1;
  174. UCHAR fPutFirstOp;
  175. char fSkipList;
  176. USHORT fPass1Err;
  177. jmp_buf forceContext;
  178. char generate;
  179. USHORT groupnum = 1;
  180. char impure;
  181. USHORT iProcCur;
  182. USHORT iProc;
  183. char inclcnt = 1;
  184. char inclFirst = 1;
  185. char *inclpath[INCLUDEMAX+1];
  186. char initflag;
  187. struct dscrec *itemptr;
  188. SHORT iRegSave;
  189. char labelflag;
  190. USHORT lastcondon;
  191. SHORT handler;
  192. char lastreader;
  193. SYMBOL FARSYM *lastsegptr;
  194. SHORT langType;
  195. char lbuf[LBUFMAX + 1];
  196. char *lbufp;
  197. char *linebp;
  198. char linebuffer[LBUFMAX + 1];
  199. UCHAR linelength; /* length of line */
  200. long linessrc;
  201. long linestot;
  202. char listbuffer[LISTMAX + 10] = " ";
  203. char listconsole = DEF_LISTCON;
  204. char listed;
  205. char listflag;
  206. char listindex;
  207. char listquiet;
  208. USHORT lnameIndex = 2;
  209. char loption = 0; /* listion option from command line */
  210. USHORT localbase;
  211. char localflag;
  212. struct fileptr lst;
  213. char lsting = DEF_LSTING;
  214. USHORT macrolevel;
  215. SYMBOL FARSYM *macroptr;
  216. SYMBOL FARSYM *macroroot;
  217. /* reg initialization data */
  218. struct mreg makreg[] = {
  219. { "CS", SEGREG, 1 },
  220. { "DS", SEGREG, 3 },
  221. { "ES", SEGREG, 0 },
  222. { "SS", SEGREG, 2 },
  223. { "AX", WRDREG, 0 },
  224. { "CX", WRDREG, 1 },
  225. { "DX", WRDREG, 2 },
  226. { "AL", BYTREG, 0 },
  227. { "BL", BYTREG, 3 },
  228. { "CL", BYTREG, 1 },
  229. { "DL", BYTREG, 2 },
  230. { "AH", BYTREG, 4 },
  231. { "BH", BYTREG, 7 },
  232. { "CH", BYTREG, 5 },
  233. { "DH", BYTREG, 6 },
  234. { "BX", INDREG, 3 },
  235. { "BP", INDREG, 5 },
  236. { "SI", INDREG, 6 },
  237. { "DI", INDREG, 7 },
  238. { "SP", WRDREG, 4 },
  239. { "ST", STKREG, 0 },
  240. 0
  241. };
  242. #ifdef V386
  243. struct mreg mak386regs[] = {
  244. { "FS", SEGREG, 4 },
  245. { "GS", SEGREG, 5 },
  246. { "EAX", DWRDREG, 0 },
  247. { "ECX", DWRDREG, 1 },
  248. { "EDX", DWRDREG, 2 },
  249. { "EBX", DWRDREG, 3 },
  250. { "EBP", DWRDREG, 5 },
  251. { "ESI", DWRDREG, 6 },
  252. { "EDI", DWRDREG, 7 },
  253. { "ESP", DWRDREG, 4 },
  254. 0
  255. };
  256. struct mreg mak386prot[] = {
  257. { "CR0", CREG, 0 },
  258. { "CR2", CREG, 2 },
  259. { "CR3", CREG, 3 },
  260. { "DR0", CREG, 010 },
  261. { "DR1", CREG, 011 },
  262. { "DR2", CREG, 012 },
  263. { "DR3", CREG, 013 },
  264. { "DR6", CREG, 016 },
  265. { "DR7", CREG, 017 },
  266. { "TR6", CREG, 026 },
  267. { "TR7", CREG, 027 },
  268. 0
  269. };
  270. #endif /* V386 */
  271. UCHAR modrm;
  272. char moduleflag;
  273. long memEnd;
  274. USHORT memRequest = 0xFFFF;
  275. NAME FAR *modulename;
  276. USHORT nearMem;
  277. USHORT nestCur;
  278. USHORT nestMax;
  279. USHORT nearMem;
  280. UCHAR nilseg;
  281. char noexp;
  282. char objectascii[9];
  283. char objing = DEF_OBJING;
  284. long oEndPass1;
  285. UCHAR opcbase;
  286. char opctype;
  287. USHORT operprec;
  288. char opertype;
  289. char opkind;
  290. char optyp;
  291. char opcref;
  292. char origcond = DEF_ORIGCON;
  293. USHORT pagelength;
  294. USHORT pageline;
  295. short pagemajor;
  296. short pageminor;
  297. USHORT pagewidth;
  298. char pass2 = FALSE; /* true if in pass 2 */
  299. OFFSET pcmax;
  300. OFFSET pcoffset;
  301. SYMBOL FARSYM *procStack[PROCMAX];
  302. short iProcStack = 0;
  303. SYMBOL FARSYM *pcproc;
  304. SYMBOL FARSYM *pcsegment;
  305. SYMBOL FARSYM *pProcCur;
  306. SYMBOL FARSYM *pProcFirst;
  307. SYMBOL FARSYM *pStrucCur;
  308. SYMBOL FARSYM *pStrucFirst;
  309. TEXTSTR FAR *pLib;
  310. MC *pMCur;
  311. char popcontext;
  312. char radix; /* assumed radix base */
  313. char radixescape;
  314. SYMBOL FARSYM *recptr;
  315. SYMBOL FARSYM *regsegment[6]; /* 386 has 6 segments. -Hans */
  316. struct dscrec *resptr;
  317. char regSave[8][SYMMAX+1];
  318. char resvspace;
  319. char save[LBUFMAX];
  320. char segalpha = DEF_SEGA; /* true if segment output in alpha order */
  321. USHORT segidx = 0;
  322. USHORT segmentnum = 1;
  323. char segtyp;
  324. struct dscrec *startaddr;
  325. struct duprec FARSYM *strclastover;
  326. char strucflag;
  327. SYMBOL FARSYM *struclabel;
  328. struct duprec FARSYM *strucoveride;
  329. struct duprec FARSYM *strucprev;
  330. SYMBOL FARSYM *strucroot;
  331. char subttlbuf[TITLEWIDTH + 1];
  332. char swaphandler;
  333. short symbolcnt;
  334. SYMBOL FARSYM *symptr;
  335. SYMBOL FARSYM *symroot[MAXCHR];
  336. SYMBOL FARSYM *pFlatGroup = (SYMBOL FARSYM *)-1;
  337. char titlebuf[TITLEWIDTH + 1];
  338. char titleflag;
  339. char titlefn[TITLEWIDTH + 1];
  340. USHORT tempLabel;
  341. char terse;
  342. USHORT typeIndex = 514; /* structure/record types */
  343. extern char version[];
  344. char unaryset[] = { 15,
  345. OPLENGTH, OPSIZE, OPWIDTH, OPMASK,
  346. OPOFFSET, OPSEG, OPTYPE, OPSTYPE,
  347. OPTHIS, OPHIGH, OPLOW, OPNOT,
  348. OPSHORT, OPLPAR, OPLBRK
  349. };
  350. OFFSET val;
  351. USHORT varsize;
  352. char verbose = DEF_VERBOSE;
  353. USHORT warnnum; /* warning count */
  354. USHORT warnlevel = 1; /* warning level */
  355. USHORT warnCode;
  356. char xcreflag;
  357. /* Array to convert symbol kind to bits in RESULT record */
  358. USHORT xltsymtoresult[13] = {
  359. /* SEGMENT */ 1 << SEGRESULT,
  360. /* GROUP */ 1 << SEGRESULT,
  361. /* CLABEL */ 0,
  362. /* PROC */ 1 << CODE,
  363. /* REC */ 1 << RCONST,
  364. /* STRUC */ (1 << RCONST)|(1 << STRUCTEMPLATE),
  365. /* EQU */ 1 << RCONST,
  366. /* DVAR */ 1 << DATA,
  367. /* CLASS */ 0,
  368. /* RECFIELD */ 1 << RCONST,
  369. /* STRUCFIELD */ 1 << RCONST,
  370. /* MACRO */ 0,
  371. /* REGISTER */ 1 << REGRESULT
  372. };
  373. char xoptoargs[OPCODPARSERS] = {
  374. /* PGENARG */ TWO,
  375. /* PCALL */ ONE,
  376. /* PJUMP */ ONE,
  377. /* PSTACK */ ONE,
  378. /* PRETURN */ MAYBE,
  379. /* PRELJMP */ ONE,
  380. /* PNOARGS */ NONE,
  381. /* PREPEAT */ NONE,
  382. /* PINCDEC */ ONE,
  383. /* PINOUT */ TWO,
  384. /* PARITH */ ONE,
  385. /* PESC */ TWO,
  386. /* PXCHG */ TWO,
  387. /* PLOAD */ TWO,
  388. /* PMOV */ TWO,
  389. /* PSHIFT */ TWO,
  390. /* PXLAT */ MAYBE,
  391. /* PSTR */ VARIES,
  392. /* PINT */ ONE,
  393. /* PENTER */ TWO,
  394. /* PBOUND */ TWO,
  395. /* PCLTS */ NONE,
  396. /* PDESCRTBL */ ONE,
  397. /* PDTTRSW */ ONE,
  398. /* PARSL */ TWO,
  399. /* PARPL */ TWO,
  400. /* PVER */ ONE,
  401. /* PMOVX */ TWO,
  402. /* PSETCC */ ONE,
  403. /* PBIT */ TWO,
  404. /* PBITSCAN */ TWO,
  405. };
  406. UCHAR xoptoseg[] = {
  407. /* PGENARG */ 1 << FIRSTDS | 1 << SECONDDS,
  408. /* PCALL */ 1 << FIRSTDS,
  409. /* PJUMP */ 1 << FIRSTDS,
  410. /* PSTACK */ 1 << FIRSTDS,
  411. /* PRETURN */ 0,
  412. /* PRELJMP */ 0,
  413. /* PNOARGS */ 0,
  414. /* PREPEAT */ 0,
  415. /* PINCDEC */ 1 << FIRSTDS,
  416. /* PINOUT */ 0,
  417. /* PARITH */ 1 << FIRSTDS | 1 << SECONDDS,
  418. /* PESC */ 1 << SECONDDS,
  419. /* PXCHG */ 1 << FIRSTDS | 1 << SECONDDS,
  420. /* PLOAD */ 1 << SECONDDS,
  421. /* PMOV */ 1 << FIRSTDS | 1 << SECONDDS,
  422. /* PSHIFT */ 1 << FIRSTDS,
  423. /* PXLAT */ 1 << FIRSTDS,
  424. /* PSTR */ 1 << FIRSTDS | 1 << SECONDDS,
  425. /* PINT */ 0,
  426. /* PENTER */ 0,
  427. /* PBOUND */ 1 << SECONDDS,
  428. /* PCLTS */ 0,
  429. /* PDESCRTBL */ 1 << FIRSTDS,
  430. /* PDTTRSW */ 1 << FIRSTDS,
  431. /* PARSL */ 1 << SECONDDS,
  432. /* PARPL */ 1 << FIRSTDS,
  433. /* PVER */ 1 << FIRSTDS,
  434. /* PMOVX */ 1 << SECONDDS,
  435. /* PSETCC */ 1 << FIRSTDS,
  436. /* PBIT */ 1 << FIRSTDS,
  437. /* PBITSCAN */ 1 << SECONDDS,
  438. /* empty slots */ 0,0,0,0,0,0,
  439. /* FNOARGS */ 0,
  440. /* F2MEMSTK */ 1 << FIRSTDS,
  441. /* FSTKS */ 0,
  442. /* FMEMSTK */ 1 << FIRSTDS,
  443. /* FSTK */ 0,
  444. /* FMEM42 */ 1 << FIRSTDS,
  445. /* FMEM842 */ 1 << FIRSTDS,
  446. /* FMEM4810 */ 1 << FIRSTDS,
  447. /* FMEM2 */ 1 << FIRSTDS,
  448. /* FMEM14 */ 1 << FIRSTDS,
  449. /* FMEM94 */ 1 << FIRSTDS,
  450. /* FWAIT */ 0,
  451. /* FBCDMEM */ 1 << FIRSTDS,
  452. };
  453. char segName[8+31] = "@CurSeg=";
  454. OFFSET CondJmpDist; /* conditional jump distance (for error) */
  455. struct objfile obj;
  456. SHORT objerr = 0;
  457. USHORT obufsiz = DEF_OBJBUFSIZ;
  458. #ifdef BCBOPT
  459. BCB * pBCBAvail = NULL; /* List of deallocatable file buffers */
  460. FCB * pFCBInc = NULL; /* Next include file */
  461. UCHAR fBuffering = TRUE; /* TRUE if storing lines for pass 2 */
  462. UCHAR fNotStored = FALSE;/* == TRUE when lbuf contains valid line to save */
  463. #endif
  464. FCB * pFCBCur = NULL; /* Current file being read */
  465. FCB * pFCBMain; /* main file */
  466. char srceof; /* EOF flag for source reads */
  467. #ifndef XENIX286
  468. static SHORT PASCAL nulname(char *); /* defined below */
  469. static SHORT PASCAL conname(char *); /* defined below */
  470. extern char *file[];
  471. #endif /* XENIX286 */
  472. #ifdef CPDOS
  473. extern unsigned _osmode;
  474. #endif
  475. /*** main - main routine for assembler
  476. *
  477. */
  478. VOID main (ac, av)
  479. int ac;
  480. char **av;
  481. {
  482. char *p;
  483. SHORT i;
  484. #ifdef MSDOS
  485. # ifdef FLATMODEL
  486. //# pragma message("signals don't work")
  487. # else
  488. signal( SIGINT, panic );
  489. # endif
  490. #else
  491. if (signal( SIGINT, SIG_IGN ) != SIG_IGN)
  492. /* don't panic() if we're in the background */
  493. signal( SIGINT, panic );
  494. #endif /* MSDOS */
  495. initregs(makreg);
  496. makedefaultdsc();
  497. argv0 = av[0];
  498. #ifdef MSGISOL0
  499. strcpy( titlefn, __NMSG_TEXT(ER_TIT) );
  500. #else
  501. #ifndef RELEASE
  502. // version string nolonger has a date to trim off
  503. // version[strlen(version) - 20] = NULL; /* Trim date off */
  504. #endif
  505. strncpy(titlefn, &version[5], TITLEWIDTH-3);
  506. i = (SHORT) strlen(titlefn);
  507. memset(&titlefn[i], ' ', TITLEWIDTH-2 - i);
  508. #endif
  509. #ifndef XENIX286
  510. sprintf(&save[256], __NMSG_TEXT(ER_COP), &version[5]);
  511. UserInterface( ac, av, &save[256] );
  512. fname = file[0];
  513. #else
  514. ac--;
  515. av++;
  516. while (**av == '-') {
  517. ac--;
  518. nextarg( *av++ );
  519. }
  520. if (ac-- < 1)
  521. usage( EX_NONE );
  522. fname = *av;
  523. #endif /* XENIX286 */
  524. initproc();
  525. dopass();
  526. listopen(); /* List unterminated blocks */
  527. dumpCodeview(); /* output symbols in speical segments for codeview */
  528. if (crefing == CREF_SINGLE) {
  529. fprintf( crf.fil, "\7%c%c", pagelength, pagewidth );
  530. if (titleflag)
  531. fprintf( crf.fil, "\6%s", titlebuf );
  532. fprintf( crf.fil, "\x8%s", pFCBCur->fname);
  533. }
  534. /* Output end of pass 1 linker information */
  535. creftype = CREFEND;
  536. if (!moduleflag)
  537. dumpname();
  538. /* Output end pass 1 symbol table to linker */
  539. /* Assign link #s and clear bit */
  540. scansymbols(assignlinknum);
  541. /* Output segment definitions */
  542. while (firstsegment) {
  543. scansegment( firstsegment );
  544. firstsegment = firstsegment->symu.segmnt.segordered;
  545. }
  546. scansymbols(scangroup); /* Emit group defs */
  547. scansymbols(scanextern); /* Emit extern defs */
  548. emitFpo();
  549. scansymbols(scanglobal); /* Emit global defs */
  550. emitEndPass1(); /* Emit end of pass1 OMF record */
  551. /* do pass 2 */
  552. pass2 = TRUE;
  553. pFCBCur = pFCBMain;
  554. #ifdef BCBOPT
  555. pFCBInc = pFCBMain;
  556. fNotStored = FALSE;
  557. pFCBCur->pBCBCur = pFCBCur->pBCBFirst;
  558. pFCBCur->pbufCur = pFCBCur->pBCBCur->pbuf;
  559. pFCBCur->pBCBCur->fInUse = 1;
  560. #endif
  561. pFCBCur->ptmpbuf = pFCBCur->buf;
  562. pFCBCur->line = 0;
  563. pFCBCur->ctmpbuf = 0;
  564. if (_lseek(pFCBCur->fh, 0L, 0 ) == -1)
  565. TERMINATE1(ER_ULI, EX_UINP, fname);
  566. dopass();
  567. dumpCodeview(); /* write codeview symbols */
  568. /* List unterminated blocks */
  569. listopen();
  570. if (lsting && dumpsymbols) {
  571. scansymbols(sortalpha);
  572. pagemajor = 0;
  573. pageminor = 0;
  574. pageline = pagelength - 1;
  575. /* Suppress SUBTTL listing */
  576. subttlbuf[0] = '\0';
  577. /* List out all macro names */
  578. listed = FALSE;
  579. scanSorted( macroroot, macrolist );
  580. /* List out records/structures */
  581. listed = FALSE;
  582. scanSorted( strucroot, struclist );
  583. /* List out segments and groups */
  584. seglist();
  585. /* List remaining symbols out */
  586. symbollist();
  587. }
  588. emitFpo();
  589. emitdone( startaddr ); /* Emit end of object file */
  590. #if !defined(FLATMODEL) /* In flat model don't display heap space available */
  591. # if defined(CPDOS) || defined(XENIX286)
  592. sprintf(lbuf, "\n%7u %s\n", _freect( 0 ) << 1,
  593. __NMSG_TEXT(ER_BYT));
  594. # else
  595. if (!terse || lsting + warnnum + errornum){
  596. nearMem = _freect(0) << 1;
  597. memEnd = farAvail();
  598. while(memRequest > 1024)
  599. if(_fmalloc(memRequest))
  600. memEnd += memRequest;
  601. else
  602. memRequest >>= 1;
  603. memEnd -= nearMem;
  604. if (memEnd < 0)
  605. memEnd = 0;
  606. sprintf(lbuf, "\n%7u + %ld %s\n", nearMem, memEnd,
  607. __NMSG_TEXT(ER_BYT));
  608. }
  609. # endif
  610. #else
  611. lbuf[0] = '\0'; /* Null string for symbol space free */
  612. #endif /* FLATMODEL */
  613. #ifdef MSDOS
  614. _flushall();
  615. #endif
  616. /* Put # errors in listing */
  617. if (lsting){
  618. #ifdef MSDOS
  619. _setmode( _fileno(lst.fil), O_TEXT );
  620. #endif
  621. if (pagelength - pageline < 12)
  622. pageheader ();
  623. showresults( lst.fil, TRUE, lbuf );
  624. }
  625. /* List # errors and warnings to console */
  626. if (!listquiet)
  627. if (!terse || warnnum || errornum)
  628. showresults( stdout, verbose, lbuf );
  629. if (crefing)
  630. /* Flag end of cref info */
  631. fprintf( crf.fil, "\5" );
  632. if (objing) {
  633. # if defined MSDOS && !defined FLATMODEL
  634. farwrite( obj.fh, obj.buf, obj.siz - obj.cnt );
  635. # else
  636. if (_write( obj.fh, obj.buf, obj.siz - obj.cnt )
  637. != obj.siz - obj.cnt)
  638. objerr = -1;
  639. # endif /* MSDOS */
  640. if (fKillPass1){ /* extrn happened on pass 2 */
  641. /* over write linker comment record */
  642. i = (SHORT)(0xd2<<8 | 0);
  643. if (_lseek(obj.fh, oEndPass1, 0 ) == -1)
  644. TERMINATE1(ER_ULI, EX_UINP, fname);
  645. #if defined MSDOS && !defined FLATMODEL
  646. farwrite( obj.fh, (UCHAR FAR *)&i, 2);
  647. #else
  648. _write( obj.fh, (UCHAR *)&i, 2);
  649. #endif
  650. }
  651. _close( obj.fh );
  652. }
  653. if (objing && (objerr))
  654. fprintf(ERRFILE,__NMSG_TEXT(ER_WEO) );
  655. if (objing && (errornum || objerr))
  656. _unlink( obj.name );
  657. if (lsting && ferror(lst.fil))
  658. fprintf(ERRFILE,__NMSG_TEXT(ER_WEL) );
  659. if (crefing && ferror(crf.fil)) {
  660. fprintf(ERRFILE,__NMSG_TEXT(ER_WEC) );
  661. _unlink( crf.name );
  662. }
  663. if (errornum)
  664. exit( EX_ASME );
  665. else
  666. exit( EX_NONE );
  667. }
  668. VOID PASCAL CODESIZE
  669. getincenv ()
  670. {
  671. #ifdef MSDOS
  672. char *pchT;
  673. char pathname[128];
  674. char *getenv();
  675. char *env = NULL;
  676. #endif
  677. if (inclcnt < INCLUDEMAX - 1)
  678. inclpath[inclcnt++] = _strdup("");
  679. #ifdef MSDOS
  680. if (!(env = getenv("INCLUDE")))
  681. return;
  682. while (*env==';')
  683. env++;
  684. while (*env && (inclcnt < INCLUDEMAX - 1)) {
  685. pchT = pathname;
  686. while(*env && *env!=';') {
  687. if (*env == ALTPSEP) {
  688. *pchT++ = PSEP;
  689. env++;
  690. } else
  691. *pchT++ = *env++;
  692. }
  693. if (*(pchT-1) != PSEP)
  694. *pchT++ = PSEP;
  695. *pchT = '\0';
  696. while (*env == ';')
  697. env++;
  698. inclpath[inclcnt++] = _strdup(pathname);
  699. }
  700. #endif /* MSDOS */
  701. }
  702. VOID PASCAL
  703. initproc ()
  704. {
  705. register char *p;
  706. char c;
  707. struct mreg *index;
  708. time_t gmttime;
  709. long filelen;
  710. char * q;
  711. #ifdef DEBUG
  712. if (d_debug)
  713. if (!(d_df = fopen("asm.trace", "w"))) {
  714. fprintf (ERRFILE, "Unable to open trace output file\n");
  715. d_debug = 0;
  716. }
  717. #endif
  718. if (!(pFCBCur = (FCB *) malloc(sizeof(FCB) + strlen(fname) + 1)))
  719. memerror( "main file FCB" );
  720. pFCBMain = pFCBCur;
  721. #ifdef BCBOPT
  722. pFCBInc = pFCBMain;
  723. pFCBCur->pFCBNext = NULL;
  724. #endif
  725. pFCBCur->pFCBParent = NULL;
  726. pFCBCur->pFCBChild = NULL;
  727. strcpy(pFCBCur->fname, fname);
  728. #ifdef XENIX286
  729. if ((pFCBCur->fh = _open(fname, TEXTREAD)) == -1)
  730. #else
  731. if ((pFCBCur->fh = _sopen(fname, O_RDONLY | O_BINARY, SH_DENYWR)) == -1)
  732. #endif
  733. TERMINATE1(ER_UOI, EX_UINP, fname);
  734. if ((filelen = _lseek(pFCBCur->fh, 0L, 2 )) == -1L)
  735. TERMINATE1(ER_ULI, EX_UINP, fname);
  736. /* go back to beginning */
  737. if (_lseek(pFCBCur->fh, 0L, 0 ) == -1)
  738. TERMINATE1(ER_ULI, EX_UINP, fname);
  739. pFCBCur->ctmpbuf = 0;
  740. pFCBCur->cbbuf = DEF_SRCBUFSIZ * 1024;
  741. if (filelen < DEF_SRCBUFSIZ * 1024)
  742. pFCBCur->cbbuf = (USHORT)filelen + 2;
  743. /* Allocate line buffer for main file */
  744. #ifdef XENIX286
  745. pFCBCur->ptmpbuf = pFCBCur->buf = malloc(pFCBCur->cbbuf);
  746. #else
  747. pFCBCur->ptmpbuf = pFCBCur->buf = _fmalloc(pFCBCur->cbbuf);
  748. #endif
  749. if (!pFCBCur->ptmpbuf)
  750. memerror ( "main file buf");
  751. #ifdef BCBOPT
  752. pFCBCur->pBCBFirst = pBCBalloc(pFCBCur->cbbuf);
  753. pFCBCur->pBCBCur = pFCBCur->pBCBFirst;
  754. #endif
  755. pFCBCur->line = 0;
  756. p = fname;
  757. if (q = strrchr( p, PSEP ))
  758. p = ++q;
  759. if (q = strrchr( p, ALTPSEP ))
  760. p = ++q;
  761. if (!LEGAL1ST(*p))
  762. baseName[10] = '_';
  763. strcat(baseName, p);
  764. /* put ..\sourceFile at the head of the include paths */
  765. if (fname[0] == '.' && fname[1] == '.') {
  766. *--p = NULL;
  767. inclpath[0] = (char *) _strdup(fname);
  768. *p = PSEP;
  769. inclFirst--;
  770. }
  771. if (p = strchr( baseName, '.' ))
  772. *p = '\0';
  773. /* map legal files names into legal idents */
  774. for (p = &baseName[11]; *p; p++)
  775. if (!TOKLEGAL(*p))
  776. *p = '_';
  777. getincenv(); /* get INCLUDE environment variable paths */
  778. #ifdef XENIX286
  779. if (lsting) {
  780. if (!lst.name)
  781. lst.name = _strdup( strcat( strcpy( save, &baseName[10] ), LST_EXT ));
  782. if (!lst.name)
  783. memerror( "lst-name" );
  784. #else
  785. if (file[2] && !nulname( file[2] )) {
  786. lsting = TRUE;
  787. lst.name = _strdup( file[2] );
  788. if (!lst.name)
  789. memerror( "lst-name" );
  790. #endif /* XENIX286 */
  791. #ifdef XENIX286
  792. if (*(lst.name) == '-') {
  793. #else
  794. if (conname( lst.name )) {
  795. #endif
  796. lst.fil = stdout;
  797. verbose = listconsole = FALSE;
  798. listquiet = TRUE;
  799. }
  800. else if (!(lst.fil = fopen( lst.name, "w" BINSTDIO)))
  801. TERMINATE1(ER_UOL, EX_ULST, lst.name);
  802. setvbuf(lst.fil, malloc(BUFSIZ*4), _IOFBF, BUFSIZ*4);
  803. }
  804. #ifdef XENIX286
  805. if (objing) {
  806. #else
  807. if (file[1] && !nulname( file[1] )) {
  808. #endif
  809. #ifdef XENIX286
  810. if (!obj.name)
  811. obj.name = _strdup( strcat( strcpy( save, &baseName[10] ), OBJ_EXT ));
  812. if (!obj.name)
  813. memerror( "obj-name" );
  814. #else
  815. obj.name = _strdup( file[1] );
  816. if (!obj.name)
  817. memerror( "obj-name" );
  818. #endif
  819. /* let the file be read or overwritten by anybody, like
  820. * other utilities. -Hans */
  821. if ((obj.fh = _open( obj.name, BINOPEN, 0666)) == -1)
  822. TERMINATE1(ER_UOO, EX_UOBJ, obj.name );
  823. obj.cnt = obj.siz = obufsiz << 10;
  824. #ifdef XENIX286
  825. if (!(obj.pos = obj.buf = malloc( obj.cnt)))
  826. #else
  827. if (!(obj.pos = obj.buf = _fmalloc( obj.cnt)))
  828. #endif
  829. memerror( "main-obj buffer" );
  830. }
  831. #ifndef XENIX286
  832. else
  833. objing = FALSE;
  834. if (file[3] && !nulname( file[3] ))
  835. crefing = CREF_SINGLE;
  836. #endif
  837. if (crefing) {
  838. #ifdef XENIX286
  839. crf.name = _strdup( strcat( strcpy( save, &baseName[10] ), ".crf" ));
  840. #else
  841. crf.name = _strdup( file[3] );
  842. #endif
  843. if (!(crf.fil = fopen( crf.name, "w" BINSTDIO )))
  844. TERMINATE1(ER_UOC, EX_UCRF, crf.name );
  845. }
  846. lbufp = strcpy( lbuf, titlefn );
  847. storetitle( titlefn );
  848. memset(titlebuf, ' ', TITLEWIDTH);
  849. /* get date and time of assembly */
  850. #if defined MSDOS && !defined FLATMODEL
  851. atime = ctime(); /* ctime() is defined below */
  852. #else
  853. gmttime = time( NULL );
  854. atime = ctime( &gmttime );
  855. #endif /* MSDOS */
  856. definesym(baseName); /* define @FileName & @WordSize */
  857. defwordsize();
  858. }
  859. #ifdef V386
  860. VOID init386(
  861. short prot
  862. ){
  863. if (!f386already)
  864. {
  865. initregs(mak386regs);
  866. f386already = 1;
  867. }
  868. if (prot && f386already<2)
  869. {
  870. initregs(mak386prot);
  871. f386already = 2;
  872. }
  873. }
  874. #endif
  875. #ifdef XENIX286
  876. /*** nextarg - scan next argument string and set parameters
  877. *
  878. * nextarg (p);
  879. *
  880. * Entry p = pointer to argument string
  881. * Exit parameters set
  882. * Returns none
  883. * Calls malloc
  884. */
  885. VOID PASCAL
  886. nextarg (
  887. register char *p
  888. ){
  889. register char cc, *q;
  890. SHORT i;
  891. while (cc = *++p)
  892. switch (cc) {
  893. case 'a':
  894. segalpha = TRUE;
  895. break;
  896. case 'b':
  897. p++;
  898. while(isdigit(p[1])) p++;
  899. break;
  900. case 'c':
  901. crefing = CREF_SINGLE;
  902. break;
  903. case 'C':
  904. crefing = CREF_MULTI;
  905. break;
  906. case 'd':
  907. debug = TRUE;
  908. break;
  909. case 'D':
  910. p++;
  911. for (q = p; *q && !isspace( *q ); q++);
  912. cc = *q;
  913. *q = '\0';
  914. definesym(p);
  915. if (errorcode)
  916. if (errorcode){
  917. error_line (ERRFILE, "command line", 0);
  918. if (errornum)
  919. exit (EX_DSYM);
  920. }
  921. *q = cc;
  922. p = q - 1;
  923. break;
  924. case 'e':
  925. fltemulate = TRUE;
  926. X87type = PX287;
  927. break;
  928. case 'h':
  929. farPuts(stdout, __FMSG_TEXT(ER_HXUSE));
  930. putchar('\n');
  931. for (i = ER_H01; i <= ER_H18; i++){
  932. putchar('-');
  933. farPuts(stdout, __FMSG_TEXT(i));
  934. putchar('\n');
  935. }
  936. exit( 0 ); /* let him start again */
  937. case 'I':
  938. if (!*++p || isspace( *p ))
  939. TERMINATE(ER_PAT, EX_ARGE);
  940. if (inclcnt < INCLUDEMAX - 1)
  941. inclpath[inclcnt++] = p;
  942. p += strlen( p ) - 1;
  943. break;
  944. case 'L':
  945. loption++;
  946. case 'l':
  947. lsting = TRUE;
  948. if (p[1]) { /* listing file name specified */
  949. lst.name = _strdup( p+1 );
  950. p += strlen( p ) - 1;
  951. }
  952. break;
  953. case 'M':
  954. switch (*++p) {
  955. case 'l':
  956. caseflag = CASEL;
  957. break;
  958. case 'u':
  959. caseflag = CASEU;
  960. break;
  961. case 'x':
  962. caseflag = CASEX;
  963. break;
  964. default:
  965. fprintf(ERRFILE,__NMSG_TEXT(ER_UNC), *p );
  966. usage( EX_ARGE );
  967. }
  968. break;
  969. case 'n':
  970. dumpsymbols = FALSE;
  971. break;
  972. case 'o':
  973. objing = FALSE;
  974. if (p[1]) { /* object file name specified */
  975. objing = TRUE;
  976. obj.name = _strdup( p+1 );
  977. p += strlen( p ) - 1;
  978. }
  979. break;
  980. case 'p':
  981. checkpure = TRUE;
  982. break;
  983. case 'r':
  984. fltemulate = FALSE;
  985. break;
  986. case 's':
  987. segalpha = FALSE;
  988. break;
  989. case 't':
  990. terse = TRUE;
  991. break;
  992. case 'v':
  993. terse = FALSE;
  994. verbose = TRUE;
  995. break;
  996. case 'w':
  997. p++;
  998. if (! isdigit(*p) || (warnlevel = atoi(p)) > 2)
  999. TERMINATE(ER_WAN, EX_ARGE );
  1000. break;
  1001. case 'X':
  1002. origcond = !origcond;
  1003. break;
  1004. case 'x':
  1005. listconsole = FALSE;
  1006. if (p[1] == '-') {
  1007. listquiet = TRUE; /* total quiet */
  1008. p++;
  1009. }
  1010. break;
  1011. case 'z':
  1012. break; /* accept just 'Z' */
  1013. case 'Z':
  1014. if (p[1] == 'd'){
  1015. codeview = CVLINE;
  1016. p++;
  1017. break;
  1018. }
  1019. else if (p[1] == 'i'){
  1020. codeview = CVSYMBOLS;
  1021. p++;
  1022. break;
  1023. }
  1024. default:
  1025. fprintf(stderr, "Argument error: %s\n", p );
  1026. usage( EX_ARGE );
  1027. }
  1028. }
  1029. /*** usage - display usage line and exit
  1030. *
  1031. * usage (exitcode);
  1032. *
  1033. * Entry
  1034. * Exit
  1035. * Returns
  1036. * Calls
  1037. */
  1038. VOID PASCAL
  1039. usage (
  1040. SHORT exitcode
  1041. ){
  1042. farPuts(stderr, __FMSG_TEXT(ER_HXHELP));
  1043. putchar('\n');
  1044. exit (exitcode);
  1045. }
  1046. #endif /* XENIX286 */
  1047. #ifdef DEBUG
  1048. /*** hatoi - convert hex ASCII string to integer
  1049. *
  1050. * hex = hatoi(p);
  1051. *
  1052. * ENTRY p = pointer to hex string in ASCII
  1053. * EXIT none
  1054. * RETURNS integer equivalent of hex string
  1055. * CALLS none
  1056. */
  1057. SHORT PASCAL
  1058. hatoi (
  1059. char *p
  1060. ){
  1061. SHORT i;
  1062. i = 0;
  1063. while (isxdigit(*p))
  1064. if (*p <= '9')
  1065. i = 0x10*i + *p++ - '0';
  1066. else
  1067. i = 0x10*i + (*p++ & 0xF) + 9;
  1068. return i;
  1069. }
  1070. #endif /* DEBUG */
  1071. #ifndef XENIX286
  1072. static SHORT PASCAL nulname ( p )
  1073. char *p;
  1074. {
  1075. char *q;
  1076. SHORT result;
  1077. if ((q = strrchr( p, PSEP )) || (q = strrchr( p, ':' )))
  1078. q++;
  1079. else
  1080. q = p;
  1081. if (p = strchr( q, '.' )) {
  1082. if (!_stricmp( p + 1, "nul" ))
  1083. return( 1 );
  1084. *p = '\0';
  1085. }
  1086. result = (SHORT)_stricmp( q, "nul" );
  1087. if (p)
  1088. *p = '.';
  1089. return( !result );
  1090. }
  1091. static SHORT PASCAL
  1092. conname (
  1093. char *p
  1094. ){
  1095. char *q;
  1096. SHORT result;
  1097. if (q = strrchr( p, PSEP ))
  1098. q++;
  1099. else
  1100. q = p;
  1101. if (p = strchr( q, '.' )) {
  1102. if (!_stricmp( p + 1, "con" ))
  1103. return( 1 );
  1104. *p = '\0';
  1105. }
  1106. result = (SHORT)_stricmp( q, "con" );
  1107. if (p)
  1108. *p = '.';
  1109. return( !result );
  1110. }
  1111. #endif /* XENIX286 */
  1112. static VOID panic () {
  1113. # ifdef FLATMODEL
  1114. //# pragma message("signals don't work")
  1115. # else
  1116. signal( SIGINT, SIG_IGN );
  1117. # endif
  1118. closeOpenFiles();
  1119. exit( EX_INT );
  1120. }
  1121. VOID PASCAL
  1122. closeOpenFiles() /* close and delete all output files on error */
  1123. {
  1124. if (crf.fil) {
  1125. fclose( crf.fil );
  1126. _unlink( crf.name );
  1127. }
  1128. if (lst.fil) {
  1129. fclose( lst.fil );
  1130. _unlink( lst.name );
  1131. }
  1132. if (obj.fh) {
  1133. _close( obj.fh );
  1134. _unlink( obj.name );
  1135. }
  1136. }
  1137. /*** terminate - exit masm with terminal message
  1138. *
  1139. *
  1140. * ENTRY packed message number, exit code
  1141. * pointers with up to 1 arguments to a printf function
  1142. * EXIT exits to DOS, no return
  1143. */
  1144. VOID terminate(
  1145. SHORT message,
  1146. char *arg1,
  1147. char *arg2,
  1148. char *arg3
  1149. ){
  1150. fprintf(ERRFILE,__NMSG_TEXT((USHORT)(0xfff & message)), arg1, arg2, arg3);
  1151. exit(message >> 12);
  1152. }
  1153. # if defined MSDOS && !defined FLATMODEL
  1154. /* get date in form:
  1155. ** <month>-<day>-<year> <hour>:<minute>:<second>\n
  1156. */
  1157. static UCHAR seetime[25];
  1158. UCHAR * PASCAL
  1159. ctime ()
  1160. {
  1161. USHORT year;
  1162. UCHAR month;
  1163. UCHAR day;
  1164. UCHAR hour;
  1165. UCHAR minute;
  1166. UCHAR second;
  1167. register char *p = &seetime[4];
  1168. #ifdef CPDOS
  1169. {
  1170. struct DateTime regs;
  1171. DOSGETDATETIME( (struct DateTime far *)(&regs) );
  1172. hour = regs.hour;
  1173. minute = regs.minutes;
  1174. second = regs.seconds;
  1175. year = regs.year;
  1176. month = regs.month;
  1177. day = regs.day;
  1178. }
  1179. #else
  1180. {
  1181. union REGS regs;
  1182. regs.h.ah = 0x2c; /* get time */
  1183. intdos( &regs, &regs );
  1184. hour = regs.h.ch;
  1185. minute = regs.h.cl;
  1186. second = regs.h.dh;
  1187. regs.h.ah = 0x2a; /* get date */
  1188. intdos( &regs, &regs );
  1189. year = (regs.h.ch << 8) | regs.h.cl;
  1190. month = regs.h.dh;
  1191. day = regs.h.dl;
  1192. }
  1193. #endif
  1194. _itoa( month, p++, 10 );
  1195. if (month >= 10)
  1196. p++;
  1197. *p++ = '/';
  1198. _itoa( day, p++, 10 );
  1199. if (day >= 10)
  1200. p++;
  1201. *p++ = '/';
  1202. _itoa( year % 100, p, 10 );
  1203. p += 2;
  1204. *p++ = ' ';
  1205. if (hour < 10)
  1206. *p++ = '0';
  1207. _itoa( hour, p++, 10 );
  1208. if (hour >= 10)
  1209. p++;
  1210. *p++ = ':';
  1211. if (minute < 10)
  1212. *p++ = '0';
  1213. _itoa( minute, p++, 10 );
  1214. if (minute >= 10)
  1215. p++;
  1216. *p++ = ':';
  1217. if (second < 10)
  1218. *p++ = '0';
  1219. _itoa( second, p++, 10 );
  1220. if (second >= 10)
  1221. p++;
  1222. *p = '\n';
  1223. p[1] = NULL;
  1224. return( seetime );
  1225. }
  1226. # endif /* MSDOS && !flatmodel */
  1227. // Only needed if C library doesn't contain strchr and strrchr
  1228. #ifdef PRIVATESTRCHR
  1229. char * strchr ( string, ch )
  1230. register char *string;
  1231. register ch;
  1232. {
  1233. while (*string && *string != ch)
  1234. string++;
  1235. if (*string == ch)
  1236. return( string );
  1237. return( NULL );
  1238. }
  1239. char * strrchr ( string, ch )
  1240. register char *string;
  1241. register ch;
  1242. {
  1243. register char *start = string;
  1244. while (*string++)
  1245. ;
  1246. while (--string != start && *string != ch)
  1247. ;
  1248. if (*string == ch)
  1249. return( string );
  1250. return( NULL );
  1251. }
  1252. #endif /* PRIVATESTRCHR */
  1253. #ifdef XENIX286
  1254. #pragma loop_opt (on)
  1255. SHORT _stricmp ( first, last )
  1256. char *first;
  1257. char *last;
  1258. {
  1259. return(memicmp(first, last, strlen(first)));
  1260. }
  1261. SHORT memicmp ( first, last,count)
  1262. register char *first;
  1263. register char *last;
  1264. SHORT count;
  1265. {
  1266. char c1, c2;
  1267. do {
  1268. if ((c1 = *first++) >= 'A' && c1 <= 'Z')
  1269. c1 += 'a' - 'A';
  1270. if ((c2 = *last++) >= 'A' && c2 <= 'Z')
  1271. c2 += 'a' - 'A';
  1272. if (c1 != c2)
  1273. return (c1 - c2);
  1274. } while (--count >= 0);
  1275. return(0);
  1276. }
  1277. farPuts(pFile, psz) /* print a far string */
  1278. FILE *pFile;
  1279. char FAR *psz;
  1280. {
  1281. while(*psz)
  1282. fputc(*psz++, pFile);
  1283. }
  1284. char *strstr(p1, p2)
  1285. char *p1;
  1286. char *p2;
  1287. {
  1288. SHORT cb = strlen(p2);
  1289. while (*p1) {
  1290. if (memcmp(p1, p2, cb) == 0)
  1291. return(p1);
  1292. p1++;
  1293. }
  1294. return (0);
  1295. }
  1296. #endif /* XENIX286 */