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
43 KiB
1590 lines
43 KiB
/* 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))
|
|
fputs(__NMSG_TEXT(ER_WEO),ERRFILE );
|
|
|
|
if (objing && (errornum || objerr))
|
|
_unlink( obj.name );
|
|
|
|
if (lsting && ferror(lst.fil))
|
|
fputs(__NMSG_TEXT(ER_WEL),ERRFILE );
|
|
|
|
if (crefing && ferror(crf.fil)) {
|
|
fputs(__NMSG_TEXT(ER_WEC),ERRFILE );
|
|
_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 */
|