/* 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 /* Types and constants */ #include /* The same */ #include /* Types and constants */ #include /* Linker I/O definitions */ #include /* Error messages */ #include /* 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 }