/* asmmain.c -- microsoft 80x86 assembler ** ** microsoft (r) macro assembler ** copyright (c) microsoft corp 1986. all rights reserved ** ** randy nevin ** ** 10/90 - Quick conversion to 32 bit by Jeff Spencer */ #include #include #include /* BUGBUG */ #ifndef FLATMODEL #include #endif #include #include #define ASMGLOBAL #include "asm86.h" #include "asmfcn.h" #include "asmctype.h" #include #ifdef MSDOS # include # include # include # if defined CPDOS && !defined OS2_2 # include # endif #endif extern char *strrchr(); extern char *strchr(); #include "asmmsg.h" static VOID panic(); /* defined below */ long farAvail(void); #if defined MSDOS && !defined FLATMODEL UCHAR * PASCAL ctime(); #else extern long time(); /* Use C library functions */ extern UCHAR *ctime(); extern long _lseek(); #endif /* MSDOS */ #if defined M8086OPT extern char qlcname[]; /* defined in asmhelp.asm */ extern char qname[]; /* defined in asmhelp.asm */ extern char qsvlcname[]; /* defined in asmhelp.asm */ extern char qsvname[]; /* defined in asmhelp.asm */ UCHAR *naim = qname; UCHAR *svname = qsvname; #else static UCHAR qname[SYMMAX + 1]; static UCHAR qlcname[SYMMAX + 1]; static UCHAR qsvname[SYMMAX + 1]; static UCHAR qsvlcname[SYMMAX + 1]; FASTNAME naim = {qname, qlcname, 0, 0}; FASTNAME svname = {qsvname, qsvlcname, 0, 0}; #endif UCHAR X87type; char *argv0; char *atime; char *begatom; char addplusflagCur; char ampersand; char baseName[25] = "@FileName="; USHORT blocklevel; char caseflag = DEF_CASE; char checkpure; /* do checks for pure code? */ OFFSET clausesize; char condflag; USHORT condlevel; /* conditional level */ USHORT count; UCHAR cputype = DEF_CPU; SHORT wordszdefault = 2; #ifdef V386 SHORT wordsize = 2; /* preprocessor constant in other ver */ #endif OFFSET cbProcParms; OFFSET cbProcLocals; USHORT crefcount; UCHAR crefinc; UCHAR cpu; char crefopt = 0; char crefing = DEF_CREFING; char crefnum[CREFINF] = { /* CREFEND */ 4, /* End of line */ /* REF */ 1, /* Reference */ /* DEF */ 2 /* Define */ }; UCHAR creftype; struct fileptr crf; SYMBOL FARSYM *curgroup; USHORT codeview; /* codeveiw obj level = 0 => CVNONE */ PFPOSTRUCT pFpoHead = 0; PFPOSTRUCT pFpoTail = 0; unsigned long numFpoRecords = 0; #ifdef DEBUG FILE *d_df; long d_debug = 0; /* debug selection */ long d_dlevel = 0; /* debug level selection */ long d_indent = 0; /* debug output indention count */ long d_sindent = 0; /* indentation printing temporary */ #endif /* DEBUG */ /* note that TDW has to be last */ USHORT datadsize[TMACRO - TDB + 1] = { /* TDB */ 1, /* TDD */ 4, /* TDQ */ 8, /* TDT */ 10, /* TDF */ 6, /* TDW */ 2, /* TMACRO */ 0 }; char debug = DEF_DEBUG; /* true if debug set */ UCHAR delim; char displayflag; char dumpsymbols = DEF_DUMPSYM; /* symbol table display if true */ char dupflag; USHORT duplevel; /* indent for dup listing */ char elseflag; char emittext = TRUE; /* emit linker text if true */ struct dscrec emptydsc; char emulatethis; char *endatom; char endbody; char equdef; char equflag; char equsel; SHORT errorcode; USHORT errorlineno; USHORT errornum; /* error count */ char exitbody; char expandflag; USHORT externnum = 1; SYMBOL FARSYM *firstsegment; UCHAR fixvalues[] = { /* FPOINTER */ 3, /* FOFFSET */ 1, /* FBASESEG */ 2, /* FGROUPSEG */ 1, /* FCONSTANT */ 0, /* FHIGH */ 4, /* FLOW */ 0, /* FNONE */ 0, /* F32POINTER*/ 11, /* F32OFFSET */ 9, /* DIR32NB */ 14, }; char fDosSeg; char fSimpleSeg; char fCheckRes; UCHAR fCrefline; char fSecondArg; char f386already; char fArth32; char fProcArgs; struct dscrec *fltdsc; char fltemulate = DEF_FLTEMULATE; USHORT fltfixmisc[9][2] = { /* fixup characters */ 'E', 0, 'C', 0, 'S', 0, 'A', 0, 'C', 0, 'S', 0, 'A', 0, 'D', 0, 'W', 0 }; USHORT fltselect[4][2] = { /* [TDD][0] */ 5, /* Single precision non IEEE */ /* [TDD][1] */ 3, /* Single precision IEEE */ /* [TDQ][0] */ 4, /* Double precision non IEEE */ /* [TDQ][1] */ 2, /* Double precision IEEE */ /* [TDT][0] */ 1, /* No temp real - use double */ /* [TDT][1] */ 1 /* 80 bit precision IEEE */ }; char *fname; UCHAR fKillPass1; UCHAR fPutFirstOp; char fSkipList; USHORT fPass1Err; jmp_buf forceContext; char generate; USHORT groupnum = 1; char impure; USHORT iProcCur; USHORT iProc; char inclcnt = 1; char inclFirst = 1; char *inclpath[INCLUDEMAX+1]; char initflag; struct dscrec *itemptr; SHORT iRegSave; char labelflag; USHORT lastcondon; SHORT handler; char lastreader; SYMBOL FARSYM *lastsegptr; SHORT langType; char lbuf[LBUFMAX + 1]; char *lbufp; char *linebp; char linebuffer[LBUFMAX + 1]; UCHAR linelength; /* length of line */ long linessrc; long linestot; char listbuffer[LISTMAX + 10] = " "; char listconsole = DEF_LISTCON; char listed; char listflag; char listindex; char listquiet; USHORT lnameIndex = 2; char loption = 0; /* listion option from command line */ USHORT localbase; char localflag; struct fileptr lst; char lsting = DEF_LSTING; USHORT macrolevel; SYMBOL FARSYM *macroptr; SYMBOL FARSYM *macroroot; /* reg initialization data */ struct mreg makreg[] = { { "CS", SEGREG, 1 }, { "DS", SEGREG, 3 }, { "ES", SEGREG, 0 }, { "SS", SEGREG, 2 }, { "AX", WRDREG, 0 }, { "CX", WRDREG, 1 }, { "DX", WRDREG, 2 }, { "AL", BYTREG, 0 }, { "BL", BYTREG, 3 }, { "CL", BYTREG, 1 }, { "DL", BYTREG, 2 }, { "AH", BYTREG, 4 }, { "BH", BYTREG, 7 }, { "CH", BYTREG, 5 }, { "DH", BYTREG, 6 }, { "BX", INDREG, 3 }, { "BP", INDREG, 5 }, { "SI", INDREG, 6 }, { "DI", INDREG, 7 }, { "SP", WRDREG, 4 }, { "ST", STKREG, 0 }, 0 }; #ifdef V386 struct mreg mak386regs[] = { { "FS", SEGREG, 4 }, { "GS", SEGREG, 5 }, { "EAX", DWRDREG, 0 }, { "ECX", DWRDREG, 1 }, { "EDX", DWRDREG, 2 }, { "EBX", DWRDREG, 3 }, { "EBP", DWRDREG, 5 }, { "ESI", DWRDREG, 6 }, { "EDI", DWRDREG, 7 }, { "ESP", DWRDREG, 4 }, 0 }; struct mreg mak386prot[] = { { "CR0", CREG, 0 }, { "CR2", CREG, 2 }, { "CR3", CREG, 3 }, { "DR0", CREG, 010 }, { "DR1", CREG, 011 }, { "DR2", CREG, 012 }, { "DR3", CREG, 013 }, { "DR6", CREG, 016 }, { "DR7", CREG, 017 }, { "TR6", CREG, 026 }, { "TR7", CREG, 027 }, 0 }; #endif /* V386 */ UCHAR modrm; char moduleflag; long memEnd; USHORT memRequest = 0xFFFF; NAME FAR *modulename; USHORT nearMem; USHORT nestCur; USHORT nestMax; USHORT nearMem; UCHAR nilseg; char noexp; char objectascii[9]; char objing = DEF_OBJING; long oEndPass1; UCHAR opcbase; char opctype; USHORT operprec; char opertype; char opkind; char optyp; char opcref; char origcond = DEF_ORIGCON; USHORT pagelength; USHORT pageline; short pagemajor; short pageminor; USHORT pagewidth; char pass2 = FALSE; /* true if in pass 2 */ OFFSET pcmax; OFFSET pcoffset; SYMBOL FARSYM *procStack[PROCMAX]; short iProcStack = 0; SYMBOL FARSYM *pcproc; SYMBOL FARSYM *pcsegment; SYMBOL FARSYM *pProcCur; SYMBOL FARSYM *pProcFirst; SYMBOL FARSYM *pStrucCur; SYMBOL FARSYM *pStrucFirst; TEXTSTR FAR *pLib; MC *pMCur; char popcontext; char radix; /* assumed radix base */ char radixescape; SYMBOL FARSYM *recptr; SYMBOL FARSYM *regsegment[6]; /* 386 has 6 segments. -Hans */ struct dscrec *resptr; char regSave[8][SYMMAX+1]; char resvspace; char save[LBUFMAX]; char segalpha = DEF_SEGA; /* true if segment output in alpha order */ USHORT segidx = 0; USHORT segmentnum = 1; char segtyp; struct dscrec *startaddr; struct duprec FARSYM *strclastover; char strucflag; SYMBOL FARSYM *struclabel; struct duprec FARSYM *strucoveride; struct duprec FARSYM *strucprev; SYMBOL FARSYM *strucroot; char subttlbuf[TITLEWIDTH + 1]; char swaphandler; short symbolcnt; SYMBOL FARSYM *symptr; SYMBOL FARSYM *symroot[MAXCHR]; SYMBOL FARSYM *pFlatGroup = (SYMBOL FARSYM *)-1; char titlebuf[TITLEWIDTH + 1]; char titleflag; char titlefn[TITLEWIDTH + 1]; USHORT tempLabel; char terse; USHORT typeIndex = 514; /* structure/record types */ extern char version[]; char unaryset[] = { 15, OPLENGTH, OPSIZE, OPWIDTH, OPMASK, OPOFFSET, OPSEG, OPTYPE, OPSTYPE, OPTHIS, OPHIGH, OPLOW, OPNOT, OPSHORT, OPLPAR, OPLBRK }; OFFSET val; USHORT varsize; char verbose = DEF_VERBOSE; USHORT warnnum; /* warning count */ USHORT warnlevel = 1; /* warning level */ USHORT warnCode; char xcreflag; /* Array to convert symbol kind to bits in RESULT record */ USHORT xltsymtoresult[13] = { /* SEGMENT */ 1 << SEGRESULT, /* GROUP */ 1 << SEGRESULT, /* CLABEL */ 0, /* PROC */ 1 << CODE, /* REC */ 1 << RCONST, /* STRUC */ (1 << RCONST)|(1 << STRUCTEMPLATE), /* EQU */ 1 << RCONST, /* DVAR */ 1 << DATA, /* CLASS */ 0, /* RECFIELD */ 1 << RCONST, /* STRUCFIELD */ 1 << RCONST, /* MACRO */ 0, /* REGISTER */ 1 << REGRESULT }; char xoptoargs[OPCODPARSERS] = { /* PGENARG */ TWO, /* PCALL */ ONE, /* PJUMP */ ONE, /* PSTACK */ ONE, /* PRETURN */ MAYBE, /* PRELJMP */ ONE, /* PNOARGS */ NONE, /* PREPEAT */ NONE, /* PINCDEC */ ONE, /* PINOUT */ TWO, /* PARITH */ ONE, /* PESC */ TWO, /* PXCHG */ TWO, /* PLOAD */ TWO, /* PMOV */ TWO, /* PSHIFT */ TWO, /* PXLAT */ MAYBE, /* PSTR */ VARIES, /* PINT */ ONE, /* PENTER */ TWO, /* PBOUND */ TWO, /* PCLTS */ NONE, /* PDESCRTBL */ ONE, /* PDTTRSW */ ONE, /* PARSL */ TWO, /* PARPL */ TWO, /* PVER */ ONE, /* PMOVX */ TWO, /* PSETCC */ ONE, /* PBIT */ TWO, /* PBITSCAN */ TWO, }; UCHAR xoptoseg[] = { /* PGENARG */ 1 << FIRSTDS | 1 << SECONDDS, /* PCALL */ 1 << FIRSTDS, /* PJUMP */ 1 << FIRSTDS, /* PSTACK */ 1 << FIRSTDS, /* PRETURN */ 0, /* PRELJMP */ 0, /* PNOARGS */ 0, /* PREPEAT */ 0, /* PINCDEC */ 1 << FIRSTDS, /* PINOUT */ 0, /* PARITH */ 1 << FIRSTDS | 1 << SECONDDS, /* PESC */ 1 << SECONDDS, /* PXCHG */ 1 << FIRSTDS | 1 << SECONDDS, /* PLOAD */ 1 << SECONDDS, /* PMOV */ 1 << FIRSTDS | 1 << SECONDDS, /* PSHIFT */ 1 << FIRSTDS, /* PXLAT */ 1 << FIRSTDS, /* PSTR */ 1 << FIRSTDS | 1 << SECONDDS, /* PINT */ 0, /* PENTER */ 0, /* PBOUND */ 1 << SECONDDS, /* PCLTS */ 0, /* PDESCRTBL */ 1 << FIRSTDS, /* PDTTRSW */ 1 << FIRSTDS, /* PARSL */ 1 << SECONDDS, /* PARPL */ 1 << FIRSTDS, /* PVER */ 1 << FIRSTDS, /* PMOVX */ 1 << SECONDDS, /* PSETCC */ 1 << FIRSTDS, /* PBIT */ 1 << FIRSTDS, /* PBITSCAN */ 1 << SECONDDS, /* empty slots */ 0,0,0,0,0,0, /* FNOARGS */ 0, /* F2MEMSTK */ 1 << FIRSTDS, /* FSTKS */ 0, /* FMEMSTK */ 1 << FIRSTDS, /* FSTK */ 0, /* FMEM42 */ 1 << FIRSTDS, /* FMEM842 */ 1 << FIRSTDS, /* FMEM4810 */ 1 << FIRSTDS, /* FMEM2 */ 1 << FIRSTDS, /* FMEM14 */ 1 << FIRSTDS, /* FMEM94 */ 1 << FIRSTDS, /* FWAIT */ 0, /* FBCDMEM */ 1 << FIRSTDS, }; char segName[8+31] = "@CurSeg="; OFFSET CondJmpDist; /* conditional jump distance (for error) */ struct objfile obj; SHORT objerr = 0; USHORT obufsiz = DEF_OBJBUFSIZ; #ifdef BCBOPT BCB * pBCBAvail = NULL; /* List of deallocatable file buffers */ FCB * pFCBInc = NULL; /* Next include file */ UCHAR fBuffering = TRUE; /* TRUE if storing lines for pass 2 */ UCHAR fNotStored = FALSE;/* == TRUE when lbuf contains valid line to save */ #endif FCB * pFCBCur = NULL; /* Current file being read */ FCB * pFCBMain; /* main file */ char srceof; /* EOF flag for source reads */ #ifndef XENIX286 static SHORT PASCAL nulname(char *); /* defined below */ static SHORT PASCAL conname(char *); /* defined below */ extern char *file[]; #endif /* XENIX286 */ #ifdef CPDOS extern unsigned _osmode; #endif /*** main - main routine for assembler * */ VOID main (ac, av) int ac; char **av; { char *p; SHORT i; #ifdef MSDOS # ifdef FLATMODEL # pragma message("BUGBUG signals don't work") # else signal( SIGINT, panic ); # endif #else if (signal( SIGINT, SIG_IGN ) != SIG_IGN) /* don't panic() if we're in the background */ signal( SIGINT, panic ); #endif /* MSDOS */ initregs(makreg); makedefaultdsc(); argv0 = av[0]; #ifdef MSGISOL0 strcpy( titlefn, __NMSG_TEXT(ER_TIT) ); #else #ifndef RELEASE // version string nolonger has a date to trim off // version[strlen(version) - 20] = NULL; /* Trim date off */ #endif strncpy(titlefn, &version[5], TITLEWIDTH-3); i = strlen(titlefn); memset(&titlefn[i], ' ', TITLEWIDTH-2 - i); #endif #ifndef XENIX286 sprintf(&save[256], __NMSG_TEXT(ER_COP), &version[5]); UserInterface( ac, av, &save[256] ); fname = file[0]; #else ac--; av++; while (**av == '-') { ac--; nextarg( *av++ ); } if (ac-- < 1) usage( EX_NONE ); fname = *av; #endif /* XENIX286 */ initproc(); dopass(); listopen(); /* List unterminated blocks */ dumpCodeview(); /* output symbols in speical segments for codeview */ if (crefing == CREF_SINGLE) { fprintf( crf.fil, "\7%c%c", pagelength, pagewidth ); if (titleflag) fprintf( crf.fil, "\6%s", titlebuf ); fprintf( crf.fil, "\x8%s", pFCBCur->fname); } /* Output end of pass 1 linker information */ creftype = CREFEND; if (!moduleflag) dumpname(); /* Output end pass 1 symbol table to linker */ /* Assign link #s and clear bit */ scansymbols(assignlinknum); /* Output segment definitions */ while (firstsegment) { scansegment( firstsegment ); firstsegment = firstsegment->symu.segmnt.segordered; } scansymbols(scangroup); /* Emit group defs */ scansymbols(scanextern); /* Emit extern defs */ emitFpo(); scansymbols(scanglobal); /* Emit global defs */ emitEndPass1(); /* Emit end of pass1 OMF record */ /* do pass 2 */ pass2 = TRUE; pFCBCur = pFCBMain; #ifdef BCBOPT pFCBInc = pFCBMain; fNotStored = FALSE; pFCBCur->pBCBCur = pFCBCur->pBCBFirst; pFCBCur->pbufCur = pFCBCur->pBCBCur->pbuf; pFCBCur->pBCBCur->fInUse = 1; #endif pFCBCur->ptmpbuf = pFCBCur->buf; pFCBCur->line = 0; pFCBCur->ctmpbuf = 0; _lseek(pFCBCur->fh, 0L, 0); /* go back to beginning of file */ dopass(); dumpCodeview(); /* write codeview symbols */ /* List unterminated blocks */ listopen(); if (lsting && dumpsymbols) { scansymbols(sortalpha); pagemajor = 0; pageminor = 0; pageline = pagelength - 1; /* Suppress SUBTTL listing */ subttlbuf[0] = '\0'; /* List out all macro names */ listed = FALSE; scanSorted( macroroot, macrolist ); /* List out records/structures */ listed = FALSE; scanSorted( strucroot, struclist ); /* List out segments and groups */ seglist(); /* List remaining symbols out */ symbollist(); } emitFpo(); emitdone( startaddr ); /* Emit end of object file */ #if !defined(FLATMODEL) /* In flat model don't display heap space available */ # if defined(CPDOS) || defined(XENIX286) sprintf(lbuf, "\n%7u %s\n", _freect( 0 ) << 1, __NMSG_TEXT(ER_BYT)); # else if (!terse || lsting + warnnum + errornum){ nearMem = _freect(0) << 1; memEnd = farAvail(); while(memRequest > 1024) if(_fmalloc(memRequest)) memEnd += memRequest; else memRequest >>= 1; memEnd -= nearMem; if (memEnd < 0) memEnd = 0; sprintf(lbuf, "\n%7u + %ld %s\n", nearMem, memEnd, __NMSG_TEXT(ER_BYT)); } # endif #else lbuf[0] = '\0'; /* Null string for symbol space free */ #endif /* FLATMODEL */ #ifdef MSDOS _flushall(); #endif /* Put # errors in listing */ if (lsting){ #ifdef MSDOS _setmode( _fileno(lst.fil), O_TEXT ); #endif if (pagelength - pageline < 12) pageheader (); showresults( lst.fil, TRUE, lbuf ); } /* List # errors and warnings to console */ if (!listquiet) if (!terse || warnnum || errornum) showresults( stdout, verbose, lbuf ); if (crefing) /* Flag end of cref info */ fprintf( crf.fil, "\5" ); if (objing) { # if defined MSDOS && !defined FLATMODEL farwrite( obj.fh, obj.buf, obj.siz - obj.cnt ); # else if (_write( obj.fh, obj.buf, obj.siz - obj.cnt ) != obj.siz - obj.cnt) objerr = -1; # endif /* MSDOS */ if (fKillPass1){ /* extrn happened on pass 2 */ /* over write linker comment record */ i = 0xd2<<8 | 0; _lseek(obj.fh, oEndPass1, 0); #if defined MSDOS && !defined FLATMODEL farwrite( obj.fh, (UCHAR FAR *)&i, 2); #else _write( obj.fh, (UCHAR *)&i, 2); #endif } _close( obj.fh ); } if (objing && (objerr)) fprintf(ERRFILE,__NMSG_TEXT(ER_WEO) ); if (objing && (errornum || objerr)) _unlink( obj.name ); if (lsting && ferror(lst.fil)) fprintf(ERRFILE,__NMSG_TEXT(ER_WEL) ); if (crefing && ferror(crf.fil)) { fprintf(ERRFILE,__NMSG_TEXT(ER_WEC) ); _unlink( crf.name ); } if (errornum) exit( EX_ASME ); else exit( EX_NONE ); } VOID PASCAL CODESIZE getincenv () { #ifdef MSDOS char *pchT; char pathname[128]; char *getenv(); char *env = NULL; #endif if (inclcnt < INCLUDEMAX - 1) inclpath[inclcnt++] = _strdup(""); #ifdef MSDOS if (!(env = getenv("INCLUDE"))) return; while (*env==';') env++; while (*env && (inclcnt < INCLUDEMAX - 1)) { pchT = pathname; while(*env && *env!=';') { if (*env == ALTPSEP) { *pchT++ = PSEP; env++; } else *pchT++ = *env++; } if (*(pchT-1) != PSEP) *pchT++ = PSEP; *pchT = '\0'; while (*env == ';') env++; inclpath[inclcnt++] = _strdup(pathname); } #endif /* MSDOS */ } VOID PASCAL initproc () { register char *p; char c; struct mreg *index; long gmttime; long filelen; char * q; #ifdef DEBUG if (d_debug) if (!(d_df = fopen("asm.trace", "w"))) { fprintf (ERRFILE, "Unable to open trace output file\n"); d_debug = 0; } #endif if (!(pFCBCur = (FCB *) malloc(sizeof(FCB) + strlen(fname) + 1))) memerror( "main file FCB" ); pFCBMain = pFCBCur; #ifdef BCBOPT pFCBInc = pFCBMain; pFCBCur->pFCBNext = NULL; #endif pFCBCur->pFCBParent = NULL; pFCBCur->pFCBChild = NULL; strcpy(pFCBCur->fname, fname); #ifdef XENIX286 if ((pFCBCur->fh = _open(fname, TEXTREAD)) == -1) #else if ((pFCBCur->fh = _sopen(fname, O_RDONLY | O_BINARY, SH_DENYWR)) == -1) #endif TERMINATE1(ER_UOI, EX_UINP, fname); if ((filelen = _lseek(pFCBCur->fh, 0L, 2 )) == -1L) TERMINATE1(ER_ULI, EX_UINP, fname); /* go back to beginning */ _lseek(pFCBCur->fh, 0L, 0 ); pFCBCur->ctmpbuf = 0; pFCBCur->cbbuf = DEF_SRCBUFSIZ * 1024; if (filelen < DEF_SRCBUFSIZ * 1024) pFCBCur->cbbuf = filelen + 2; /* Allocate line buffer for main file */ #ifdef XENIX286 pFCBCur->ptmpbuf = pFCBCur->buf = malloc(pFCBCur->cbbuf); #else pFCBCur->ptmpbuf = pFCBCur->buf = _fmalloc(pFCBCur->cbbuf); #endif if (!pFCBCur->ptmpbuf) memerror ( "main file buf"); #ifdef BCBOPT pFCBCur->pBCBFirst = pBCBalloc(pFCBCur->cbbuf); pFCBCur->pBCBCur = pFCBCur->pBCBFirst; #endif pFCBCur->line = 0; p = fname; if (q = strrchr( p, PSEP )) p = ++q; if (q = strrchr( p, ALTPSEP )) p = ++q; if (!LEGAL1ST(*p)) baseName[10] = '_'; strcat(baseName, p); /* put ..\sourceFile at the head of the include paths */ if (fname[0] == '.' && fname[1] == '.') { *--p = NULL; inclpath[0] = (char *) _strdup(fname); *p = PSEP; inclFirst--; } if (p = strchr( baseName, '.' )) *p = '\0'; /* map legal files names into legal idents */ for (p = &baseName[11]; *p; p++) if (!TOKLEGAL(*p)) *p = '_'; getincenv(); /* get INCLUDE environment variable paths */ #ifdef XENIX286 if (lsting) { if (!lst.name) lst.name = _strdup( strcat( strcpy( save, &baseName[10] ), LST_EXT )); #else if (file[2] && !nulname( file[2] )) { lsting = TRUE; lst.name = _strdup( file[2] ); #endif /* XENIX286 */ #ifdef XENIX286 if (*(lst.name) == '-') { #else if (conname( lst.name )) { #endif lst.fil = stdout; verbose = listconsole = FALSE; listquiet = TRUE; } else if (!(lst.fil = fopen( lst.name, "w" BINSTDIO))) TERMINATE1(ER_UOL, EX_ULST, lst.name); setvbuf(lst.fil, malloc(BUFSIZ*4), _IOFBF, BUFSIZ*4); } #ifdef XENIX286 if (objing) { #else if (file[1] && !nulname( file[1] )) { #endif #ifdef XENIX286 if (!obj.name) obj.name = _strdup( strcat( strcpy( save, &baseName[10] ), OBJ_EXT )); #else obj.name = _strdup( file[1] ); #endif /* let the file be read or overwritten by anybody, like * other utilities. -Hans */ if ((obj.fh = _open( obj.name, BINOPEN, 0666)) == -1) TERMINATE1(ER_UOO, EX_UOBJ, obj.name ); obj.cnt = obj.siz = obufsiz << 10; #ifdef XENIX286 if (!(obj.pos = obj.buf = malloc( obj.cnt))) #else if (!(obj.pos = obj.buf = _fmalloc( obj.cnt))) #endif memerror( "main-obj buffer" ); } #ifndef XENIX286 else objing = FALSE; if (file[3] && !nulname( file[3] )) crefing = CREF_SINGLE; #endif if (crefing) { #ifdef XENIX286 crf.name = _strdup( strcat( strcpy( save, &baseName[10] ), ".crf" )); #else crf.name = _strdup( file[3] ); #endif if (!(crf.fil = fopen( crf.name, "w" BINSTDIO ))) TERMINATE1(ER_UOC, EX_UCRF, crf.name ); } lbufp = strcpy( lbuf, titlefn ); storetitle( titlefn ); memset(titlebuf, ' ', TITLEWIDTH); /* get date and time of assembly */ #if defined MSDOS && !defined FLATMODEL atime = ctime(); /* ctime() is defined below */ #else gmttime = time( (long *)0 ); atime = ctime( &gmttime ); #endif /* MSDOS */ definesym(baseName); /* define @FileName & @WordSize */ defwordsize(); } #ifdef V386 VOID init386( short prot ){ if (!f386already) { initregs(mak386regs); f386already = 1; } if (prot && f386already<2) { initregs(mak386prot); f386already = 2; } } #endif #ifdef XENIX286 /*** nextarg - scan next argument string and set parameters * * nextarg (p); * * Entry p = pointer to argument string * Exit parameters set * Returns none * Calls malloc */ VOID PASCAL nextarg ( register char *p ){ register char cc, *q; SHORT i; while (cc = *++p) switch (cc) { case 'a': segalpha = TRUE; break; case 'b': p++; while(isdigit(p[1])) p++; break; case 'c': crefing = CREF_SINGLE; break; case 'C': crefing = CREF_MULTI; break; case 'd': debug = TRUE; break; case 'D': p++; for (q = p; *q && !isspace( *q ); q++); cc = *q; *q = '\0'; definesym(p); if (errorcode) if (errorcode){ error_line (ERRFILE, "command line", 0); if (errornum) exit (EX_DSYM); } *q = cc; p = q - 1; break; case 'e': fltemulate = TRUE; X87type = PX287; break; case 'h': farPuts(stdout, __FMSG_TEXT(ER_HXUSE)); putchar('\n'); for (i = ER_H01; i <= ER_H18; i++){ putchar('-'); farPuts(stdout, __FMSG_TEXT(i)); putchar('\n'); } exit( 0 ); /* let him start again */ case 'I': if (!*++p || isspace( *p )) TERMINATE(ER_PAT, EX_ARGE); if (inclcnt < INCLUDEMAX - 1) inclpath[inclcnt++] = p; p += strlen( p ) - 1; break; case 'L': loption++; case 'l': lsting = TRUE; if (p[1]) { /* listing file name specified */ lst.name = _strdup( p+1 ); p += strlen( p ) - 1; } break; case 'M': switch (*++p) { case 'l': caseflag = CASEL; break; case 'u': caseflag = CASEU; break; case 'x': caseflag = CASEX; break; default: fprintf(ERRFILE,__NMSG_TEXT(ER_UNC), *p ); usage( EX_ARGE ); } break; case 'n': dumpsymbols = FALSE; break; case 'o': objing = FALSE; if (p[1]) { /* object file name specified */ objing = TRUE; obj.name = _strdup( p+1 ); p += strlen( p ) - 1; } break; case 'p': checkpure = TRUE; break; case 'r': fltemulate = FALSE; break; case 's': segalpha = FALSE; break; case 't': terse = TRUE; break; case 'v': terse = FALSE; verbose = TRUE; break; case 'w': p++; if (! isdigit(*p) || (warnlevel = atoi(p)) > 2) TERMINATE(ER_WAN, EX_ARGE ); break; case 'X': origcond = !origcond; break; case 'x': listconsole = FALSE; if (p[1] == '-') { listquiet = TRUE; /* total quiet */ p++; } break; case 'z': break; /* accept just 'Z' */ case 'Z': if (p[1] == 'd'){ codeview = CVLINE; p++; break; } else if (p[1] == 'i'){ codeview = CVSYMBOLS; p++; break; } default: fprintf(stderr, "Argument error: %s\n", p ); usage( EX_ARGE ); } } /*** usage - display usage line and exit * * usage (exitcode); * * Entry * Exit * Returns * Calls */ VOID PASCAL usage ( SHORT exitcode ){ farPuts(stderr, __FMSG_TEXT(ER_HXHELP)); putchar('\n'); exit (exitcode); } #endif /* XENIX286 */ #ifdef DEBUG /*** hatoi - convert hex ASCII string to integer * * hex = hatoi(p); * * ENTRY p = pointer to hex string in ASCII * EXIT none * RETURNS integer equivalent of hex string * CALLS none */ SHORT PASCAL hatoi ( char *p ){ SHORT i; i = 0; while (isxdigit(*p)) if (*p <= '9') i = 0x10*i + *p++ - '0'; else i = 0x10*i + (*p++ & 0xF) + 9; return i; } #endif /* DEBUG */ #ifndef XENIX286 static SHORT PASCAL nulname ( p ) char *p; { char *q; SHORT result; if ((q = strrchr( p, PSEP )) || (q = strrchr( p, ':' ))) q++; else q = p; if (p = strchr( q, '.' )) { if (!_stricmp( p + 1, "nul" )) return( 1 ); *p = '\0'; } result = _stricmp( q, "nul" ); if (p) *p = '.'; return( !result ); } static SHORT PASCAL conname ( char *p ){ char *q; SHORT result; if (q = strrchr( p, PSEP )) q++; else q = p; if (p = strchr( q, '.' )) { if (!_stricmp( p + 1, "con" )) return( 1 ); *p = '\0'; } result = _stricmp( q, "con" ); if (p) *p = '.'; return( !result ); } #endif /* XENIX286 */ static VOID panic () { # ifdef FLATMODEL # pragma message("BUGBUG signals don't work") # else signal( SIGINT, SIG_IGN ); # endif closeOpenFiles(); exit( EX_INT ); } VOID PASCAL closeOpenFiles() /* close and delete all output files on error */ { if (crf.fil) { fclose( crf.fil ); _unlink( crf.name ); } if (lst.fil) { fclose( lst.fil ); _unlink( lst.name ); } if (obj.fh) { _close( obj.fh ); _unlink( obj.name ); } } /*** terminate - exit masm with terminal message * * * ENTRY packed message number, exit code * pointers with up to 1 arguments to a printf function * EXIT exits to DOS, no return */ VOID terminate( SHORT message, char *arg1, char *arg2, char *arg3 ){ fprintf(ERRFILE,__NMSG_TEXT((USHORT)(0xfff & message)), arg1, arg2, arg3); exit(message >> 12); } # if defined MSDOS && !defined FLATMODEL /* get date in form: ** -- ::\n */ static UCHAR seetime[25]; UCHAR * PASCAL ctime () { USHORT year; UCHAR month; UCHAR day; UCHAR hour; UCHAR minute; UCHAR second; register char *p = &seetime[4]; #ifdef CPDOS { struct DateTime regs; DOSGETDATETIME( (struct DateTime far *)(®s) ); hour = regs.hour; minute = regs.minutes; second = regs.seconds; year = regs.year; month = regs.month; day = regs.day; } #else { union REGS regs; regs.h.ah = 0x2c; /* get time */ intdos( ®s, ®s ); hour = regs.h.ch; minute = regs.h.cl; second = regs.h.dh; regs.h.ah = 0x2a; /* get date */ intdos( ®s, ®s ); year = (regs.h.ch << 8) | regs.h.cl; month = regs.h.dh; day = regs.h.dl; } #endif _itoa( month, p++, 10 ); if (month >= 10) p++; *p++ = '/'; _itoa( day, p++, 10 ); if (day >= 10) p++; *p++ = '/'; _itoa( year % 100, p, 10 ); p += 2; *p++ = ' '; if (hour < 10) *p++ = '0'; _itoa( hour, p++, 10 ); if (hour >= 10) p++; *p++ = ':'; if (minute < 10) *p++ = '0'; _itoa( minute, p++, 10 ); if (minute >= 10) p++; *p++ = ':'; if (second < 10) *p++ = '0'; _itoa( second, p++, 10 ); if (second >= 10) p++; *p = '\n'; p[1] = NULL; return( seetime ); } # endif /* MSDOS && !flatmodel */ // Only needed if C library doesn't contain strchr and strrchr #ifdef PRIVATESTRCHR char * strchr ( string, ch ) register char *string; register ch; { while (*string && *string != ch) string++; if (*string == ch) return( string ); return( NULL ); } char * strrchr ( string, ch ) register char *string; register ch; { register char *start = string; while (*string++) ; while (--string != start && *string != ch) ; if (*string == ch) return( string ); return( NULL ); } #endif /* PRIVATESTRCHR */ #ifdef XENIX286 #pragma loop_opt (on) SHORT _stricmp ( first, last ) char *first; char *last; { return(memicmp(first, last, strlen(first))); } SHORT memicmp ( first, last,count) register char *first; register char *last; SHORT count; { char c1, c2; do { if ((c1 = *first++) >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; if ((c2 = *last++) >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; if (c1 != c2) return (c1 - c2); } while (--count >= 0); return(0); } farPuts(pFile, psz) /* print a far string */ FILE *pFile; char FAR *psz; { while(*psz) fputc(*psz++, pFile); } char *strstr(p1, p2) char *p1; char *p2; { SHORT cb = strlen(p2); while (*p1) { if (memcmp(p1, p2, cb) == 0) return(p1); p1++; } return (0); } #endif /* XENIX286 */