1591 lines
42 KiB
C
1591 lines
42 KiB
C
/* 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 <stdio.h>
|
||
#include <ctype.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
|
||
#ifndef FLATMODEL
|
||
#include <signal.h>
|
||
#endif
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
|
||
#define ASMGLOBAL
|
||
#include "asm86.h"
|
||
#include "asmfcn.h"
|
||
#include "asmctype.h"
|
||
#include <fcntl.h>
|
||
#include <time.h>
|
||
|
||
#ifdef MSDOS
|
||
# include <dos.h>
|
||
# include <share.h>
|
||
# include <io.h>
|
||
# if defined CPDOS && !defined OS2_2
|
||
# include <doscalls.h>
|
||
# 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("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 = (SHORT) 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;
|
||
if (_lseek(pFCBCur->fh, 0L, 0 ) == -1)
|
||
TERMINATE1(ER_ULI, EX_UINP, fname);
|
||
|
||
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 = (SHORT)(0xd2<<8 | 0);
|
||
if (_lseek(obj.fh, oEndPass1, 0 ) == -1)
|
||
TERMINATE1(ER_ULI, EX_UINP, fname);
|
||
#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;
|
||
time_t 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 */
|
||
if (_lseek(pFCBCur->fh, 0L, 0 ) == -1)
|
||
TERMINATE1(ER_ULI, EX_UINP, fname);
|
||
|
||
pFCBCur->ctmpbuf = 0;
|
||
pFCBCur->cbbuf = DEF_SRCBUFSIZ * 1024;
|
||
|
||
if (filelen < DEF_SRCBUFSIZ * 1024)
|
||
pFCBCur->cbbuf = (USHORT)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 ));
|
||
if (!lst.name)
|
||
memerror( "lst-name" );
|
||
#else
|
||
if (file[2] && !nulname( file[2] )) {
|
||
lsting = TRUE;
|
||
|
||
lst.name = _strdup( file[2] );
|
||
if (!lst.name)
|
||
memerror( "lst-name" );
|
||
|
||
#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 ));
|
||
if (!obj.name)
|
||
memerror( "obj-name" );
|
||
#else
|
||
obj.name = _strdup( file[1] );
|
||
if (!obj.name)
|
||
memerror( "obj-name" );
|
||
#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( NULL );
|
||
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 = (SHORT)_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 = (SHORT)_stricmp( q, "con" );
|
||
|
||
if (p)
|
||
*p = '.';
|
||
|
||
return( !result );
|
||
}
|
||
|
||
#endif /* XENIX286 */
|
||
|
||
|
||
static VOID panic () {
|
||
|
||
# ifdef FLATMODEL
|
||
//# pragma message("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:
|
||
** <month>-<day>-<year> <hour>:<minute>:<second>\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 */
|