windows-nt/Source/XPSP1/NT/sdktools/link16/newcmd.c
2020-09-26 16:20:57 +08:00

850 lines
35 KiB
C

/* SCCSID = %W% %E% */
/*
* Copyright Microsoft Corporation, 1983-1987
*
* This Module contains Proprietary Information of Microsoft
* Corporation and should be treated as Confidential.
*/
/****************************************************************
* *
* NEWCMD.C *
* *
* Support routines for command prompter. *
* *
****************************************************************/
#include <minlit.h> /* Types and constants */
#include <bndtrn.h> /* The same */
#include <bndrel.h> /* Types and constants */
#include <lnkio.h> /* Linker I/O definitions */
#include <lnkmsg.h> /* Error messages */
#include <extern.h> /* External function declarations */
/*
* FUNCTION PROTOTYPES
*/
LOCAL int NEAR GetInputByte(char *prompt);
LOCAL BYTE NEAR GetStreamByte(char *prompt);
LOCAL void NEAR SetUpCommandLine(int argc, char **argv);
LOCAL void NEAR FinishCommandLine(void);
#if AUTOVM
BYTE FAR * NEAR FetchSym1(RBTYPE rb, WORD Dirty);
#define FETCHSYM FetchSym1
#else
#define FETCHSYM FetchSym
#endif
#if OSMSDOS
char *stackbuf;
#endif
LOCAL FTYPE fMoreCommandLine;
/* More command line flag */
LOCAL FTYPE fMoreIndirectFile;
/* More-input-from-file flag */
LOCAL BSTYPE bsIndir; /* File handle for indirect file */
LOCAL FTYPE fEscNext;
LOCAL FTYPE fNewLine = (FTYPE) TRUE;/* New command line */
LOCAL FTYPE fStuffed; /* Put-back-character flag */
LOCAL BYTE bStuffed; /* The character put back */
LOCAL BYTE bSepLast; /* Last separator character */
/* Char to replace spaces with */
LOCAL FTYPE fRedirect; /* True iff stdin not a device */
LOCAL WORD fQuotted; /* TRUE if inside " ... " */
LOCAL char *pszRespFile; /* Pointer to responce file name */
LOCAL char MaskedChar;
#if TRUE
#define SETCASE(c) (c) /* Leave as is */
#else
#define SETCASE(c) UPPER(c) /* Force to upper case */
#endif
#if WIN_3
extern char far *fpszLinkCmdLine;
#endif
#if AUTOVM
/*
* HACK ALERT !!!!!!!!!!!!
*
* This function is repeated here becouse of mixed medium model.
* This the same code as in NEWSYM.c but maked here LOCAL. This
* allows near calls to this function in all segments, otherwise
* function must be called as far.
*/
extern short picur;
/****************************************************************
* *
* FetchSym: *
* *
* This function fetches a symbol from the symbol table given *
* its virtual address. The symbol may either be resident or *
* in virtual memory. *
* *
****************************************************************/
BYTE FAR * NEAR FetchSym1(rb,fDirty)
RBTYPE rb; /* Virtual address */
WORD fDirty; /* Dirty page flag */
{
union {
long vptr; /* Virtual pointer */
BYTE FAR *fptr; /* Far pointer */
struct {
unsigned short offset;
/* Offset value */
unsigned short seg;
} /* Segmnet value */
ptr;
}
pointer; /* Different ways to describe pointer */
pointer.fptr = rb;
if(pointer.ptr.seg) /* If resident - segment value != 0 */
{
picur = 0; /* Picur not valid */
return(pointer.fptr); /* Return pointer */
}
pointer.fptr = (BYTE FAR *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),fDirty);
/* Fetch from virtual memory */
return(pointer.fptr);
}
#endif
// Strip path from file spec - leave drive letter and filename
void StripPath(BYTE *sb)
{
char Drive[_MAX_DRIVE];
char Dir[_MAX_DIR];
char Name[_MAX_FNAME];
char Ext[_MAX_EXT];
/* Decompose filename into four components */
sb[sb[0]+1] = '\0';
_splitpath(sb+1, Drive, Dir, Name, Ext);
/* Create modified path name */
_makepath(sb+1, Drive, NULL, Name, Ext);
sb[0] = (BYTE) strlen(sb+1);
}
/****************************************************************
* *
* SetUpCommandLine: *
* *
* This function initializes the command line parser. *
* *
****************************************************************/
LOCAL void NEAR SetUpCommandLine(int argc,char **argv)
{
fMoreCommandLine = (FTYPE) ((argc - 1) != 0 ? TRUE : FALSE);
/* If command line not empty */
if (!_isatty(fileno(stdin))) /* Determine if stdin is a device */
fRedirect = (FTYPE) TRUE;
}
/****************************************************************
* *
* FinishCommandLine: *
* *
* This function takes no arguments. If command input has *
* been coming from a file, then this function closes that *
* file; otherwise, it has no effect. It does not return a *
* meaningful value. *
* *
****************************************************************/
LOCAL void NEAR FinishCommandLine(void) /* Close indirect file */
{
fflush(stdout); /* Force to screen */
if(fMoreIndirectFile) /* If command input from file */
{
fMoreIndirectFile = FALSE; /* No more indirect file */
fclose(bsIndir); /* Close indirect file */
}
}
#if ECS
/*
* GetTxtChr : get the next character from a text file stream
*
* This routine handles mixed DBCS and ASCII characters as
* follows:
*
* 1. The second byte of a DBCS character is returned in a
* word with the high byte set to the lead byte of the character.
* Thus the return value can be used in comparisions with
* ASCII constants without being mistakenly matched.
*
* 2. A DBCS space character (0x8140) is returned as two
* ASCII spaces (0x20). I.e. return a space the 1st and 2nd
* times we're called.
*
* 3. ASCII characters and lead bytes of DBCS characters
* are returned in the low byte of a word with the high byte
* set to 0.
*/
int GetTxtChr (bs)
BSTYPE bs;
{
static int chBuf = -1; /* Character buffer */
int next; /* The next byte */
int next2; /* The one after that */
/* -1 in chBuf means it doesn't contain a valid character */
/* If we're not in the middle of a double-byte character,
* get the next byte and process it.
*/
if(chBuf == -1)
{
next = getc(bs);
/* If this byte is a lead byte, get the following byte
* and store both as a word in chBuf.
*/
if(IsLeadByte(next))
{
next2 = getc(bs);
chBuf = (next << 8) | next2;
/* If the pair matches a DBCS space, set the return value
* to ASCII space.
*/
if(chBuf == 0x8140)
next = 0x20;
}
}
/* Else we're in the middle of a double-byte character. */
else
{
/* If this is the 2nd byte of a DBCS space, set the return
* value to ASCII space.
*/
if(chBuf == 0x8140)
next = 0x20;
/* Else set the return value to the whole DBCS character */
else
next = chBuf;
/* Reset the character buffer */
chBuf = -1;
}
/* Return the next character */
return(next);
}
#endif
/****************************************************************
* *
* GetInputByte: *
* *
* This function takes as its input a pointer to an asciz *
* string with which to prompt the user when more input is *
* necessary. The function returns a byte of input. It *
* checks to make sure the byte is a printable ascii character *
* or a carriage return (^M). *
* *
****************************************************************/
LOCAL int NEAR GetInputByte(prompt)
char *prompt; /* Pointer to prompt text */
{
REGISTER unsigned b; /* Input byte */
#if ECS || defined(_MBCS)
static FTYPE fInDBC; /* True iff in double-byte char */
#endif
if(fMoreIndirectFile) /* If input from file */
{
for(;;) /* Forever */
{
b = GetTxtChr(bsIndir); /* Read a byte */
if(b == EOF || b == 032) break;
/* Break on end of file */
if(fNewLine) /* If at start of line */
{
if (prompt && !fNoEchoLrf)
(*pfCputs)(prompt); /* Prompt the user */
fNewLine = FALSE; /* Not at beginning anymore */
}
if (prompt && !fNoEchoLrf)
{
#if CRLF
/* Allow both ^J and ^M^J to terminate input lines. */
if(b == '\r') continue;
if(b == '\n') (*pfCputc)('\r');
#endif
(*pfCputc)(SETCASE(b)); /* Output byte */
}
if(b == ';' && !fNoEchoLrf) NEWLINE(stdout);
/* Follow escape by newline */
else if(b == '\n') fNewLine = (FTYPE) TRUE;
/* Look for new line */
else if (b == '\t') b = ' ';
/* Translate tabs to spaces */
if(b == '\n' || b >= ' ') return(SETCASE(b));
/* Return if valid char. */
}
FinishCommandLine(); /* Close indirect file */
}
if(fStuffed) /* If a byte saved */
{
fStuffed = FALSE; /* Now we're unstuffed */
return(bStuffed); /* Return the stuffed byte */
}
if(fMoreCommandLine) /* If more command line */
{
for(;;) /* Forever */
{
if (*lpszCmdLine == '\0') /* If at end of command line */
{
fMoreCommandLine = FALSE;
/* No more command line */
fNewLine = (FTYPE) TRUE;/* New command line */
return('\n'); /* Return '\n' */
}
b = (WORD) (*lpszCmdLine++);/* Get next character */
if (b == '\\' && *lpszCmdLine == '"')
{ /* Skip escaped double quotes */
lpszCmdLine++;
if (*lpszCmdLine == '\0')
{
fMoreCommandLine = FALSE;
/* No more command line */
fNewLine = (FTYPE) TRUE;
/* New command line */
fQuotted = FALSE;
return('\n'); /* Return '\n' */
}
else
b = (WORD) (*lpszCmdLine++);
}
#if ECS || defined(_MBCS)
/* If this is a trailing byte of a DBCS char, set the high
* byte of b to nonzero, so b won't be confused with an ASCII
* constant.
*/
if (fInDBC)
{
b |= 0x100;
fInDBC = FALSE;
}
else
fInDBC = (FTYPE) IsLeadByte(b);
#endif
if (b >= ' ') return(SETCASE(b));
/* Return if valid char. */
}
}
for(;;) /* Forever */
{
if(fNewLine) /* If at start of line */
{
if(prompt && ((!fRedirect && !fNoprompt) || (!fEsc && fNoprompt)))
/* If prompt and input from CON */
(*pfCputs)(prompt); /* Prompt the user */
fNewLine = FALSE; /* Not at beginning anymore */
}
b = GetTxtChr(stdin); /* Read a byte from terminal */
if(b == EOF) b = ';'; /* Treat EOF like escape */
else if (b == '\t') b = ' '; /* Treat tab like space */
if(b == '\n') fNewLine = (FTYPE) TRUE; /* New line */
if(b == '\n' || b >= ' ') return(SETCASE(b));
/* Return if character is valid */
}
}
/****************************************************************
* *
* GetStreamByte: *
* *
* This function takes as its input a pointer to a string of *
* text with which to prompt the user, if necessary. It *
* returns a byte of command input, and opens an indirect file *
* to do so if necessary. *
* *
****************************************************************/
LOCAL BYTE NEAR GetStreamByte(prompt)
char *prompt; /* Pointer to text of prompt */
{
REGISTER WORD ich; /* Index variable */
SBTYPE filnam; /* File name buffer */
WORD b; /* A byte */
#if OSMSDOS
extern char *stackbuf;
#endif
if (((b = (WORD)GetInputByte(prompt)) == INDIR) && !fQuotted)
{ /* If user specifies indirect file */
if (fMoreIndirectFile) Fatal(ER_nestrf);
/* Check for nesting */
DEBUGMSG("Getting response file name");
/* Debug message */
ich = 0; /* Initialize index */
while(ich < SBLEN - 1) /* Loop to get file name */
{
b = (WORD)GetInputByte((char *) 0);
/* Read in a byte */
fQuotted = fQuotted ? b != '"' : b == '"';
if ((!fQuotted && (b == ',' || b == '+' || b == ';' || b == ' ')) ||
b == CHSWITCH || b < ' ') break;
/* Exit loop on non-name char. */
if (b != '"')
filnam[ich++] = (char) b;
/* Store in file name */
}
if(b > ' ') /* If legal input character */
{
fStuffed = (FTYPE) TRUE; /* Set flag */
bStuffed = (BYTE) b; /* Save character */
}
filnam[ich] = '\0'; /* Null-terminate file name */
pszRespFile = _strdup(filnam); /* Duplicate file name */
DEBUGMSG(filnam); /* Debug message */
if((bsIndir = fopen(filnam,RDTXT)) == NULL)
Fatal(ER_opnrf,filnam);
#if OSMSDOS
setvbuf(bsIndir,stackbuf,_IOFBF,512);
#endif
fMoreIndirectFile = (FTYPE) TRUE;/* Take input from file now */
b = (WORD)GetInputByte(prompt); /* Read a byte */
DEBUGVALUE(b); /* Debug info */
}
return((BYTE) b); /* Return a byte */
}
/****************************************************************
* *
* GetLine: *
* *
* This function takes as its arguments the address of a *
* buffer in which to return a line of command text and a *
* pointer to a string with which to prompt the user, if *
* necessary. In addition to reading a line, this function *
* will set the global flag fEsc to true if the next *
* character to be read is a semicolon. The function does not *
* return a meaningful value. *
* *
****************************************************************/
void NEAR GetLine(pcmdlin,prompt) /* Get a command line */
BYTE *pcmdlin; /* Pointer to destination string */
char *prompt; /* Pointer to text of prompt string */
{
REGISTER WORD ich; /* Index */
WORD ich1; /* Index */
WORD ich2; /* Index */
BYTE b; /* A byte of input */
WORD fFirstTime; /* Boolean */
fFirstTime = (FTYPE) TRUE; /* Assume it is our first time */
bSepLast = bSep; /* Save last separator */
if(fEscNext) /* If escape character next */
{
pcmdlin[0] = '\0'; /* No command line */
fEsc = (FTYPE) TRUE; /* Set global flag */
return; /* That's all for now */
}
for(;;) /* Forever */
{
fQuotted = FALSE;
ich = 0; /* Initialize index */
while(ich < SBLEN - 1) /* While room in buffer */
{
b = GetStreamByte(prompt); /* Get a byte */
fQuotted = fQuotted ? b != '"' : b == '"';
if (b == '\n' || (!fQuotted && (b == ',' || b == ';')))
{
if (b == ';')
fMoreCommandLine = FALSE;
break; /* Leave loop on end of line */
}
if (!(b == ' ' && ich == 0))/* Store if not a leading space */
{
if (!fQuotted)
{
if (b == '+')
{
if (!MaskedChar)
MaskedChar = b;
b = chMaskSpace;
}
if (b == ' ' && !MaskedChar)
MaskedChar = b;
}
pcmdlin[++ich] = b;
}
}
/*
* If ich==SBLEN-1, last char cannot have been a line terminator
* and buffer is full. If next input char is a line terminator,
* OK, else error.
*/
if(ich == SBLEN - 1 && (b = GetStreamByte(prompt)) != '\n' &&
b != ',' && b != ';')
{
fflush(stdout);
Fatal(ER_linmax);
}
while(ich) /* Loop to trim trailing spaces */
{
if(pcmdlin[ich] != ' ') break;
/* Break on non-space */
--ich; /* Decrement count */
}
ich1 = 0; /* Initialize */
ich2 = 0; /* Initialize */
while(ich2 < ich) /* Loop to remove or replace spaces */
{
++ich2;
if (pcmdlin[ich2] == '"')
{
// Start of quotted file name
while (ich2 < ich && pcmdlin[++ich2] != '"')
pcmdlin[++ich1] = pcmdlin[ich2];
}
else if (pcmdlin[ich2] != ' ' || chMaskSpace != 0 || fQuotted)
{ /* If not space or replacing spaces */
++ich1;
if(!fQuotted && pcmdlin[ich2] == ' ') pcmdlin[ich1] = chMaskSpace;
/* Replace space if replacing */
else pcmdlin[ich1] = pcmdlin[ich2];
/* Else copy the non-space */
}
}
pcmdlin[0] = (BYTE) ich1; /* Set the length */
bSep = b; /* Save the separator */
if (ich ||
!fFirstTime ||
!((bSepLast == ',' && bSep == '\n') ||
(bSepLast == '\n' && bSep == ',')))
break; /* Exit the loop */
fFirstTime = FALSE; /* No the first time */
bSepLast = ','; /* Comma is the field separator */
}
fEscNext = (FTYPE) (b == ';'); /* Set flag */
fEsc = (FTYPE) (!ich && fEscNext); /* Set flag */
}
/****************************************************************
* *
* ParseCmdLine: *
* *
* This function takes no arguments and returns no meaningful *
* value. It parses the command line. *
* *
****************************************************************/
void ParseCmdLine(argc,argv)
/* Parse the command line */
int argc; /* Count of arguments */
char **argv; /* Argument vector */
{
SBTYPE sbFile; /* File name */
SBTYPE sbPrompt; /* Prompt text */
SBTYPE rgb; /* Command line buffer */
FTYPE fMoreInput; /* More input flag */
FTYPE fFirstTime;
AHTEPTR pahte; /* Pointer to hash table entry */
FTYPE fNoList; /* True if no list file */
BYTE *p;
WORD i;
#if OSMSDOS
char buf[512]; /* File buffer */
extern char *stackbuf;
stackbuf = buf;
#endif
#if WIN_3
lpszCmdLine = fpszLinkCmdLine;
#endif
SetUpCommandLine(argc,argv); /* Initialize command line */
chMaskSpace = 0x1f;
bsLst = stdout; /* Assume listing to console */
fLstFileOpen = (FTYPE) TRUE; /* So Fatal will flush it */
fFirstTime = fMoreCommandLine;
do /* Do while more input */
{
fMoreInput = FALSE; /* Assume no more input */
if (fFirstTime)
GetLine(rgb, NULL);
else
GetLine(rgb, strcat(strcpy(sbPrompt,GetMsg(P_objprompt)), " [.obj]: "));
/* Get a line of command text */
if(!rgb[0]) break; /* Break if length 0 */
if(rgb[B2W(rgb[0])] == chMaskSpace) /* If last char is chMaskSpace */
{
fMoreInput = (FTYPE) TRUE; /* More to come */
--rgb[0]; /* Decrement the length */
}
BreakLine(rgb,ProcObject,chMaskSpace); /* Apply ProcObject() to line */
#if CMDMSDOS
if (fFirstTime && !fNoBanner)
DisplayBanner(); /* Display signon banner */
#endif
if (fFirstTime && !fNoEchoLrf)
{
if (fMoreInput || (fMoreIndirectFile && fFirstTime))
{
(*pfCputs)(strcat(strcpy(sbPrompt,GetMsg(P_objprompt)), " [.obj]: "));
/* Prompt the user */
rgb[B2W(rgb[0]) + 2] = '\0';
if (fMoreIndirectFile)
{
if (!fMoreInput && !fNewLine && !fEscNext)
rgb[B2W(rgb[0]) + 1] = ',';
else if (!fMoreInput && fNewLine)
rgb[B2W(rgb[0]) + 1] = ' ';
else if (rgb[B2W(rgb[0]) + 1] == chMaskSpace)
rgb[B2W(rgb[0]) + 1] = '+';
}
else if (rgb[B2W(rgb[0]) + 1] == chMaskSpace)
rgb[B2W(rgb[0]) + 1] = '+';
for (i = 1; i <= rgb[0]; i++)
if (rgb[i] == chMaskSpace)
rgb[i] = MaskedChar;
(*pfCputs)(&rgb[1]); /* And display his response */
if (fMoreInput || fNewLine || fEscNext)
if (!fNoEchoLrf)
NEWLINE(stdout);
}
}
fFirstTime = FALSE;
}
while(fMoreInput); /* End of loop */
#if OVERLAYS
if(fInOverlay) Fatal(ER_unmlpar);
/* Check for parenthesis error
* See ProcObject() to find out
* what is going on here.
*/
#endif
chMaskSpace = 0; /* Remove spaces */
if(rhteFirstObject == RHTENIL) Fatal(ER_noobj);
/* There must be some objects */
#if OEXE
pahte = (AHTEPTR ) FETCHSYM(rhteFirstObject,FALSE);
/* Fetch name of first object */
memcpy(sbFile,GetFarSb(pahte->cch),B2W(pahte->cch[0]) + 1);
/* Copy name of first object */
#if ODOS3EXE
if(fQlib)
UpdateFileParts(sbFile,sbDotQlb);
else if (fBinary)
UpdateFileParts(sbFile,sbDotCom);/* Force extension to .COM */
else
#endif
UpdateFileParts(sbFile,sbDotExe);/* Force extension to .EXE */
#endif
#if OIAPX286
memcpy(sbFile,"\005a.out",6); /* a.out is default for Xenix */
#endif
#if OSMSDOS
if(sbFile[2] == ':') sbFile[1] = (BYTE) (DskCur + 'a');
/* Get drive letter of default drive */
StripPath(sbFile); /* Strip off path specification */
#endif
bufg[0] = 0;
if(!fEsc) /* If command not escaped */
{
strcat(strcpy(sbPrompt, GetMsg(P_runfile)), " [");
sbFile[1 + sbFile[0]] = '\0';
/* Build run file prompt */
/* Prompt for run file */
GetLine(bufg, strcat(strcat(sbPrompt, &sbFile[1]), "]: "));
PeelFlags(bufg); /* Peel flags */
if (B2W(bufg[0]))
memcpy(sbFile,bufg,B2W(bufg[0]) + 1);
/* Store user responce */
else
{
// Store only base name without extension
sbFile[0] -= 4;
}
}
EnterName(sbFile,ATTRNIL,TRUE); /* Create hash tab entry for name */
rhteRunfile = vrhte; /* Save hash table address */
#if OSMSDOS
if (sbFile[0] >= 2 && sbFile[2] == ':')
chRunFile = sbFile[1]; /* If disk specified, use it */
else
chRunFile = (BYTE) (DskCur + 'a');/* Else use current disk */
#endif
fNoList = (FTYPE) (!vfMap && !vfLineNos); /* Set default flag value */
#if OSMSDOS
memcpy(sbFile,"\002a:",3); /* Start with a drive spec */
#else
sbFile[0] = '\0'; /* Null name */
#endif
pahte = (AHTEPTR ) FETCHSYM(vrhte,FALSE);
/* Fetch run file name */
UpdateFileParts(sbFile,GetFarSb(pahte->cch)); /* Use .EXE file name... */
UpdateFileParts(sbFile,sbDotMap); /* ...with .MAP extension */
#if OSMSDOS
sbFile[1] = (BYTE) (DskCur + 'a'); /* Default to default drive */
StripPath(sbFile); /* Strip off path specification */
#endif
fNoList = (FTYPE) (!vfMap && !vfLineNos); /* No list if not /M and not /LI */
if(!fEsc) /* If argument not defaulted */
{
if(bSep == ',') fNoList = FALSE;/* There will be a list file */
if(fNoList) /* If no list file yet */
{
#if OSMSDOS
memcpy(sbFile,"\007nul.map",8);
/* Default null list name */
#endif
#if OSXENIX
memcpy(sbFile,"\007nul.map",8);
/* Default null list name */
#endif
}
strcat(strcpy(sbPrompt, GetMsg(P_listfile)), " [");
sbFile[1 + sbFile[0]] = '\0';
GetLine(rgb, strcat(strcat(sbPrompt, &sbFile[1]), "]: "));
/* Get map file name */
PeelFlags(rgb); /* Process any flags */
if(rgb[0]) /* If name given */
{
fNoList = FALSE; /* There will (maybe) be a list file */
UpdateFileParts(sbFile,rgb);
}
}
chMaskSpace = 0x1f; /* Change spaces to chMaskSpaces */
if(!fEsc) /* If argument not defaulted */
{
strcat(strcpy(sbPrompt,GetMsg(P_libprompt)), " [.lib]: ");
do /* Loop to get library names */
{
fMoreInput = FALSE; /* Assume no more input */
GetLine(rgb, sbPrompt);
if(fEsc || !rgb[0]) break; /* Exit loop if no more input */
if(rgb[B2W(rgb[0])] == chMaskSpace) /* If more to come */
{
fMoreInput = (FTYPE) TRUE; /* Set flag to true */
--rgb[0]; /* Decrement length */
}
BreakLine(rgb,AddLibrary,chMaskSpace);
/* Apply AddLibrary() to lib name(s) */
}
while(fMoreInput); /* End of loop */
}
#if OSEGEXE AND NOT QCLINK
chMaskSpace = 0; /* Remove spaces */
rhteDeffile = RHTENIL; /* Assume no definitions file */
if(!fEsc) /* If argument not defaulted */
{
#if OSMSDOS
GetLine(rgb, strcat(strcpy(sbPrompt,GetMsg(P_defprompt)), " [nul.def]: "));
/* Get def file name */
memcpy(sbPrompt,"\007nul.def",8); /* Default null definition file name */
#endif
#if OSXENIX
GetLine(rgb, strcat(strcpy(sbPrompt,GetMsg(P_defprompt)), " [nul.def]: "));
/* Get def file name */
memcpy(sbPrompt,"\007nul.def",8); /* Default null definition file name */
#endif
PeelFlags(rgb); /* Process any flags */
if(rgb[0]) /* If a name was given */
{
UpdateFileParts(sbPrompt,rgb);
/* Get file name */
memcpy(rgb,sbPrompt,B2W(sbPrompt[0]) + 1);
/* Copy name */
UpdateFileParts(rgb,"\003NUL");
/* Replace name with null name */
if(!SbCompare(sbPrompt,rgb,TRUE))
{ /* If name not null */
EnterName(sbPrompt,ATTRNIL,TRUE);
/* Create hash tab entry for name */
rhteDeffile = vrhte; /* Save hash table address */
}
}
}
#endif /* OSEGEXE */
FinishCommandLine(); /* Close indirect file (if any) */
fLstFileOpen = FALSE;
#if OSMSDOS
rhteLstfile = RHTENIL; /* Assume no list file */
#endif
if(!fNoList) /* If a listing wanted */
{
memcpy(sbPrompt,sbFile,B2W(sbFile[0]) + 1);
/* Copy full file name */
UpdateFileParts(sbPrompt,"\003NUL");
/* Change name only */
if(!SbCompare(sbFile,sbPrompt,TRUE))
{ /* If name given not null device */
UpdateFileParts(sbPrompt,"\003CON");
/* Change name only */
if(!SbCompare(sbFile,sbPrompt,TRUE))
{ /* If list file not console */
sbFile[B2W(++sbFile[0])] = '\0';
/* Null-terminate name */
if((bsLst = fopen(&sbFile[1],WRBIN)) == NULL)
Fatal(ER_lstopn); /* Open listing file */
#if OSMSDOS
#ifdef M_I386
if((p = GetMem(512)) != NULL)
#else
if((p = malloc(512)) != NULL)
#endif
setvbuf(bsLst,p,_IOFBF,512);
EnterName(sbFile,ATTRNIL,TRUE);
/* Create hash tab entry for name */
rhteLstfile = vrhte; /* Save hash table address */
#endif
}
else bsLst = stdout; /* Else list to console */
#if OSMSDOS
if(bsLst == stdout) chListFile = (unsigned char) '\377';
/* List file is console */
else if(_isatty(fileno(bsLst))) chListFile = (unsigned char) '\377';
/* List file is some device */
else if(sbFile[2] == ':') /* Else if drive spec given */
chListFile = (BYTE) (sbFile[1] - 'a');
/* Save floppy drive number */
else chListFile = DskCur; /* Else list file on current floppy */
#endif
fLstFileOpen = (FTYPE) TRUE;/* We have a list file */
}
}
#if FALSE AND OSMSDOS AND OWNSTDIO
/* If wer're using our own stdio, set stdout to unbuffered if it
* goes to console.
* CAN'T do this because we now use standard fprintf. Only
* stdio is custom made.
*/
if(_isatty(fileno(stdout)))
{
fflush(stdout);
stdout->_flag |= _IONBF;
}
#endif
#if QCLINK OR Z2_ON
if (fZ2 && pszRespFile != NULL)
_unlink(pszRespFile);
if (pszRespFile != NULL)
FFREE(pszRespFile);
#endif
}