MZ is back!

This commit is contained in:
Mark Zbikowski
2024-04-25 21:24:10 +01:00
parent 8ee9712c74
commit 656c98b804
1259 changed files with 519749 additions and 4 deletions

View File

@@ -0,0 +1,241 @@
; SCCSID = @(#)comequ.asm 1.1 85/05/14
; SCCSID = @(#)comequ.asm 1.1 85/05/14
;*************************************
; COMMAND EQUs which are not switch dependant
EMGDEBUG = FALSE
SYM EQU ">"
LINESPERPAGE EQU 25 ;AC000; default lines per page
NORMPERLIN EQU 1
WIDEPERLIN EQU 5
COMBUFLEN EQU 128 ; Length of commmand buffer
BatLen EQU 32 ; buffer for batch files
YES_ECHO EQU 1 ; echo line
NO_ECHO EQU 0 ; don't echo line
No_Echo_Char EQU "@" ; don't echo line if this is first char
call_in_progress EQU 1 ; indicate we're in the CALL command
length_call EQU 4 ; length of CALL
max_nest EQU 10 ; max # levels of batch nesting allowed
fail_allowed EQU 00001000b ; critical error
retry_allowed EQU 00010000b ; critical error
Ignore_allowed EQU 00100000b ; critical error
nullcommand EQU 1 ; no command on command line
end_of_line EQU -1 ;AN000; end of line return from parser
end_of_line_out EQU 0 ;AN000; end of line for output
end_of_line_in EQU 0dh ;AN000; end of line for input
result_number EQU 1 ;AN000; number returned from parser
result_string EQU 3 ;AN000; string returned from parser
result_filespec EQU 5 ;AN000; filespec returned from parser
result_drive EQU 6 ;AN000; drive returned from parser
result_date EQU 7 ;AN000; date returned from parser
result_time EQU 8 ;AN000; time returned from parser
result_no_error EQU 0 ;AN000; no error returned from parser
no_cont_flag EQU 0 ;AN000; no control flags for message
util_msg_class EQU -1 ;AN000; message class for utility
ext_msg_class EQU 1 ;AN000; message class for extended error
parse_msg_class EQU 2 ;AN000; message class for parse error
crit_msg_class EQU 3 ;AN000; message class for critical error
ext_crlf_class EQU 081h ;AN054; message class for extended error with no CRLF
colon_char EQU ":" ;AN000; colon character
crt_ioctl_ln EQU 14 ;AN000; default length of data for display ioctl
text_mode EQU 1 ;AN000; text mode return from ioctl
get_generic EQU 07Fh ;AN000; generic ioctl - get device info
set_crit_dev EQU 0100H ;AN000; device attribute for critical error on I/0
mult_ansi EQU 01Ah ;AC064; multiplex for ansi.sys
mult_shell_get EQU 01902h ;AC065; multiplex for Shell - get next command
mult_shell_brk EQU 01903h ;AN000; multiplex for Shell - ^C batch check
shell_action equ 0ffh ;AN000; SHELL - return for taking SHELL specific action
bat_not_open EQU -1 ;AN000; batch handle will be set to this if not open
bat_open_handle EQU 19 ;AN000; handle will be in this position in JFN table
Ptr_seg_pos equ 7 ;AN000; Offset from start of message block for subst segment
Ptr_off_pos equ 5 ;AN000; Offset from start of message block for subst offset
Parm_off_pos equ word ptr 2 ;AN000; Offset from start of subst list for subst offset
parm_block_size equ 11 ;AN000; size of message subst block
blank equ " " ;AN000; blank character
no_subst equ 0 ;AN000; no substitutions for messages
one_subst equ 1 ;AN000; one substitution for messages
no_handle_out equ -1 ;AN000; use function 1 thru 12 for message retriever
res_subst equ 2 ;AN000; offset from start of message definition to number of subst
read_open_mode equ 0000000000000000b ;AN024; extended open mode for read
read_open_flag equ 0000000100000001b ;AN000; extended open flags for read
write_open_mode equ 0000000000000001b ;AN024; extended open mode for read
write_open_flag equ 0000000100000001b ;AN000; extended open flags for read
creat_open_flag equ 0000000100010010b ;AN000; extended open flags for read
get_CPSW equ 3 ;AN000; minor function for get CPSW status
CPSW_off equ 0 ;AN000; CPSW return from function - OFF
Get_XA equ 2 ;AN030; minor function for get extended attributes
Set_XA equ 4 ;AN000; minor function for set extended attributes
file_no_cpage equ 0 ;AN000; file has no code page tag
file_inv_cpage equ -1 ;AN000; file has invalid code page tag
do_xa equ -1 ;AN000; flag to get extended attributes
inv_cp_tag equ 0 ;AC039; tag for invalid code page
no_xa_seg equ -1 ;AN000; no segment for extended attributes - COPY
capital_A equ 'A' ;AC000;
vbar equ '|' ;AC000;
labracket equ '<' ;AC000;
rabracket equ '>' ;AC000;
dollar equ '$' ;AC000;
lparen equ '(' ;AC000;
rparen equ ')' ;AC000;
nullrparen equ 29h ;AC000;
in_word equ 4e49h ;AC000; 'NI' ('IN' backwards)
do_word equ 4f44h ;AC000; 'OD' ('DO' backwards)
star equ '*' ;AC000;
plus_chr equ '+' ;AC000;
small_a equ 'a' ;AC000;
small_z equ 'z' ;AC000;
dot_chr equ '.' ;AC000;
tab_chr equ 9 ;AN032;
equal_chr equ '=' ;AN032;
semicolon equ ';' ;AN049;
dot_qmark equ 2e3fh ;AC000; '.?'
dot_colon equ 2e3ah ;AC000; '.:'
capital_n equ 0 ;AC000; result from Y/N call if N entered
capital_y equ 1 ;AC000; result from Y/N call if Y entered
AppendInstall equ 0B700H ;AN020; append install check
AppendDOS equ 0B702H ;AN020; append DOS version check
AppendGetState equ 0B706H ;AN020; append get current state
AppendSetState equ 0B707H ;AN020; append set current state
AppendTruename equ 0B711H ;AN042; Get file's real location for Batch
search_attr equ attr_read_only+attr_hidden+attr_directory ;AC042;
;*************************************
;* PARSE ERROR MESSAGES
;*************************************
MoreArgs_Ptr equ 1 ;AN000;"Too many parameters" message number
LessArgs_Ptr equ 2 ;AN000;"Required parameter missing" message number
BadSwt_Ptr equ 3 ;AN000;"Invalid switch" message number
BadParm_Ptr equ 10 ;AN000;"Invalid parameter" message number
;*************************************
;* EQUATES FOR MESSAGE RETRIEVER
;*************************************
GET_EXTENDED_MSG EQU 0 ;AN000; get extended message address
SET_EXTENDED_MSG EQU 1 ;AN000; set extended message address
GET_PARSE_MSG EQU 2 ;AN000; get parse message address
SET_PARSE_MSG EQU 3 ;AN000; set parse message address
GET_CRITICAL_MSG EQU 4 ;AN000; get critical message address
SET_CRITICAL_MSG EQU 5 ;AN000; set critical message address
MESSAGE_2F EQU 46 ;AN000; minor code for message retriever
;*********************************
;* EQUATES FOR INT 10H
;*********************************
VIDEO_IO_INT EQU 10H ;AN000; equate for int 10h
SET_VIDEO_MODE EQU 0 ;AN000; set video mode
SET_CURSOR_POSITION EQU 2 ;AN000; set new cursor position
SCROLL_VIDEO_PAGE EQU 6 ;AN000; scroll active page up
VIDEO_ATTRIBUTE EQU 7 ;AN000; attribute to be used on blank line
SET_COLOR_PALETTE EQU 11 ;AN000; set color for video
GET_VIDEO_STATE EQU 15 ;AN000; get current video state
VIDEO_ALPHA EQU 3 ;AN000; alpha video is 3 or below
VIDEO_BW EQU 7 ;AN000; mode for 80X25 black & white
AltPipeChr equ "|" ; alternate pipe character
FCB EQU 5CH
VARSTRUC STRUC
ISDIR DB ?
SIZ DB ?
TTAIL DW ?
INFO DB ?
BUF DB DIRSTRLEN + 20 DUP (?)
VARSTRUC ENDS
fCheckDrive equ 00000001b
fSwitchAllowed equ 00000010b
;
; Test switches
;
fParse EQU 0001h ; display results of parseline
;
; Batch segment structure
;
; BYTE type of segment
; BYTE echo state of parent on entry to batch file
; WORD segment of last batch file
; WORD segment for FOR command
; BYTE FOR flag state on entry to batch file
; DWORD offset for next line
; 10 WORD pointers to parameters. -1 is empty parameter
; ASCIZ file name (with . and ..)
; BYTES CR-terminated parameters
; BYTE 0 flag to indicate end of parameters
;
BatchType equ 0
BatchSegment struc
BatType DB BatchType ; signature
Batechoflag DB 0 ; G state of echo
Batlast DW 0 ; G segment of last batch file
Batforptr DW 0 ; G segment for FOR command
Batforflag DB 0 ; G state of FOR
BatSeek DD ? ; lseek position of next char
BatParm DW 10 dup (?) ; pointers to parameters
BatFile DB ? ; beginning of batch file name
BatchSegment ends
ANULL equ 0 ; terminates an argv string
ARGMAX equ 64 ; max args on a command line
ARGBLEN equ 2*128 ; 1char each plus term NUL
tplen equ 64 ; max size of one argument
arg_cnt_error equ 1 ; number of args > MAXARG
arg_buf_ovflow equ 2 ; overflowed argbuffer
argv_ele STRUC ; elements in the argv array
argpointer DW (?) ; pointer to the argstring
argflags DB (?) ; cparse flags for this argstring
argstartel DW (?) ; the result of cparse's [STARTEL]
arglen DW (?) ; cparse's char count + one (for null)
argsw_word DW (?) ; any switches after this? what kinds?
arg_ocomptr DW (?) ; pointer into original command string
argv_ele ENDS
arg_unit STRUC
argv DB (ARGMAX * SIZE argv_ele) DUP (?)
argvcnt DW (?) ; number of arguments
argswinfo DW (?) ; Switch information for entire line
argbuf DW ARGBLEN DUP (?) ; storage for argv strings
argforcombuf db COMBUFLEN DUP (?) ; Original for loop command string
arg_unit ENDS
parseflags RECORD special_delim:1, unused:4, path_sep:1, wildcard:1, sw_flag:1
SwitchV EQU 10h
SwitchB EQU 08h
SwitchA EQU 04h
SwitchP EQU 02h
SwitchW EQU 01h
fSwitch EQU 8000h
fBadSwitch EQU 4000h
SwitchDir EQU SwitchP + SwitchW + fSwitch
SwitchCopy EQU SwitchV + SwitchA + SwitchB + fSwitch
break <Trap: Get the attention of MSDOS>
; TRAP snares the operating system for a service call
; AX, as well as any other registers MS-DOS takes a fancy to, will be crunched.
trap MACRO dos_function,dos_info
ifnb <dos_info>
mov AX, (dos_function SHL 8) + dos_info
else
mov AX, (dos_function SHL 8)
endif
int int_command
ENDM
;
; Equates for initialization
;
initInit equ 01h ; initialization in progress
initSpecial equ 02h ; in initialization time/date routine
initCtrlC equ 04h ; already in ^C handler

View File

@@ -0,0 +1,6 @@
/map COMMAND1.OBJ COMMAND2.OBJ RUCODE.OBJ RDATA.OBJ INIT.OBJ IPARSE.OBJ +
UINIT.OBJ TCODE.OBJ TBATCH.OBJ TBATCH2.OBJ TFOR.OBJ TCMD1A.OBJ TCMD1B.OBJ +
TCMD2A.OBJ TCMD2B.OBJ TENV.OBJ TENV2.OBJ TMISC1.OBJ TMISC2.OBJ TPIPE.OBJ +
PARSE2.OBJ PATH1.OBJ PATH2.OBJ TUCODE.OBJ COPY.OBJ COPYPR1.OBJ COPYPR2.OBJ +
CPARSE.OBJ TPARSE.OBJ TPRINTF.OBJ TDATA.OBJ TSPC.OBJ,COMMAND.EXE,,;


View File

@@ -0,0 +1,213 @@
;*************************
;* MESSAGE SKELETON FILE *
;*************************
:util COMMAND ;AC000;
:class 1 ;AC000; Transient extended errors
:use EXTEND2 ;AC000; "File not found"
:use EXTEND3 ;AC000; "Path not found"
:use EXTEND8 ;AC000; "Insufficient memory"
:class 2 ;AC000; Transient parse errors
:class 3 ;AC000; Resident extended errors
:use -1 EXTEND999 ;AN000; "Extended error #"
:class 4 ;AC000; Resident parse errors
:use -1 PARSE999 ;AN000; "Parse error #"
:class A ;AC000; resident messages
:use 220 COMMON17 ;AC000; "File allocation table bad, drive %1"
:use 223 COMMON28 ;AC000; "Press any key to continue"
:def 201 "A" ;AC000;
:def 202 "R" ;AC000;
:def 203 "I" ;AC000;
:def 204 "F" ;AC000;
:def 205 "Y" ;AC000;
:def 206 "N" ;AC000;
:def 210 "Abort" ;AC000;
:def 211 ", Retry" ;AC000;
:def 212 ", Ignore" ;AC000;
:def 213 ", Fail" ;AC000;
:def 214 "?" ;AC000;
:def 215 "reading",0 ;AC000;
:def 216 "writing",0 ;AC000;
:def 217 " %1 drive %2",CR,LF ;AC000;
:def 218 " %1 device %2",CR,LF ;AC000;
:def 219 "Please insert volume %1 serial %2-%3",CR,LF ;AC009;
:def 221 "Invalid COMMAND.COM",CR,LF ;AC000;
:def 222 "Insert disk with %1 in drive %2",CR,LF ;AC000;
:def 224 CR,LF,"Terminate batch job (Y/N)?" ;AC000;
:def 225 "Cannot execute %1",CR,LF ;AC000;
:def 226 "Error in EXE file",CR,LF ;AC000;
:def 227 "Program too big to fit in memory",CR,LF ;AC000;
:def 228 CR,LF,"No free file handles" ;AC000;
:def 229 "Bad Command or file name",CR,LF ;AC000;
:use 230 EXTEND5 ;AC000;
:def 231 CR,LF,"Memory allocation error" ;AC000;
:def 232 CR,LF,"Cannot load COMMAND, system halted",CR,LF;AC000;
:def 233 CR,LF,"Cannot start COMMAND, exiting",CR,LF ;AC000;
:def 234 CR,LF,"Top level process aborted, cannot continue",CR,LF;AC000;
:def 235 CR,LF ;AC000;
:class B ;AC000; Initialization messages
:use 461 COMMON1 ;AC000; "Incorrect DOS version"
:def 463 "Out of environment space",CR,LF ;AC000;
:def 464 CR,LF,CR,LF,"MS DOS ",CR,LF
"Version 4.00 (C)Copyright International Business Machines Corp 1981,1988",CR,LF
" (C)Copyright Microsoft Corp 1981, 1988",CR,LF ;AC000;
:def 465 "Specified COMMAND search directory bad",CR,LF ;AC025;
:def 466 "Specified COMMAND search directory bad access denied",CR,LF ;AC025;
:class C ;AC000; Parse messages
:use PARSE1 ;AC000; "Too many parameters"
:use PARSE2 ;AC000; "Required parameter missing"
:use PARSE3 ;AC000; "Invalid switch"
:use PARSE4 ;AC000; "Invalid keyword"
:use PARSE6 ;AC000; "Parameter value not in allowed range"
:use PARSE7 ;AC000; "Parameter value not allowed"
:use PARSE8 ;AC000; "Parameter value not allowed"
:use PARSE9 ;AC000; "Parameter format not correct"
:use PARSE10 ;AC000; "Invalid parameter"
:use PARSE11 ;AC000; "Invalid parameter combination"
:class D ;AC000; Extended errors - critical
:use EXTEND19 ;AC000; "Write protect"
:use EXTEND20 ;AC000; "Invalid unit"
:use EXTEND21 ;AC000; "Drive not ready"
:use EXTEND22 ;AC000; "Invalid device request"
:use EXTEND23 ;AC000; "Data error"
:use EXTEND24 ;AC000; "Invalid device request parameters"
:use EXTEND25 ;AC000; "Seek error"
:use EXTEND26 ;AC000; "Invalid media type"
:use EXTEND27 ;AC000; "Sector not found"
:use EXTEND28 ;AC000; "Printer out of paper"
:use EXTEND29 ;AC000; "Write fault error"
:use EXTEND30 ;AC000; "Read fault error"
:use EXTEND31 ;AC000; "General Failure"
:use EXTEND32 ;AC000; "Sharing Violation"
:use EXTEND33 ;AC000; "Lock Violation"
:use EXTEND34 ;AC000; "Invalid Disk Change"
:use EXTEND35 ;AC000; "FCB unavailable"
:use EXTEND36 ;AC000; "System resource exhausted"
:use EXTEND37 ;AC000; "Code page mismatch"
:use EXTEND38 ;AC026; "Out of input"
:use EXTEND39 ;AC026; "Insufficient disk space"
:class E ;AC000; extended errors
:use EXTEND1 ;AC000; "Invalid Function"
:use EXTEND2 ;AC000; "File not found"
:use EXTEND3 ;AC000; "Path not found"
:use EXTEND4 ;AC000; "Too many open files"
:use EXTEND5 ;AC000; "Access denied"
:use EXTEND6 ;AC000; "Invalid handle"
:use EXTEND7 ;AC000; "Memory control blocks destroyed"
:use EXTEND8 ;AC000; "Insufficient memory"
:use EXTEND9 ;AC000; "Invalid memory block address"
:use EXTEND10 ;AC000; "Invalid Environment"
:use EXTEND11 ;AC000; "Invalid format"
:use EXTEND12 ;AC000; "Invalid function parameter"
:use EXTEND13 ;AC000; "Invalid data"
:use EXTEND15 ;AC000; "Invalid drive specification"
:use EXTEND16 ;AC000; "Attempt to remove current directory"
:use EXTEND17 ;AC000; "Not same device"
:use EXTEND18 ;AC000; "No more files"
:use EXTEND80 ;AC000; "File already exists"
:use EXTEND82 ;AC000; "Can not make directory entry"
:use EXTEND83 ;AC000; "Fail requested to Critical Error"
:use EXTEND84 ;AC000; "Too many attaches"
:use EXTEND85 ;AC000; "Device or file already attached"
:use EXTEND86 ;AC000; "Invalid password"
:use EXTEND87 ;AC000; "Invalid parameter"
:use EXTEND88 ;AC000; "File system data fault"
:use EXTEND89 ;AC000; "Function not supported by file system"
:use EXTEND90 ;AC000;
:class F ;AC000; Transient messages
:use 1020 COMMON4 ;AC000; "%1 bytes free",CR,LF
:use 1015 COMMON18 ;AC000; "File cannot be copied onto itself",CR,LF
:use 1004 COMMON20 ;AC000; "Insufficient disk space",CR,LF
:use 1026 COMMON22 ;AC000; "Invalid code page",CR,LF
:use 1031 COMMON23 ;AC000; "Invalid date"
:use 1035 COMMON24 ;AC000; "Invalid time"
:use 1062 COMMON25 ;AC000; "Invalid path"
:use 1028 COMMON28 ;AC000; "Press any key to continue"
:use 1045 COMMON32 ;AC000; "Unable to create directory",CR,LF
:use 1041 COMMON33 ;AC000; "Volume in drive %1 has no label"
:use 1042 COMMON34 ;AC000; "Volume in drive %1 is %2"
:use 1043 COMMON36 ;AC000; "Volume Serial Number is %1"
:def 1002 "Duplicate file name or file not found",CR,LF ;AC000;
:def 1003 "Invalid path or file name",CR,LF ;AC000;
:def 1007 "Out of environment space",CR,LF ;AC000;
:def 1008 "File creation error",CR,LF ;AC000;
:def 1009 "Batch file missing",CR,LF ;AC000;
:def 1010 CR,LF,"Insert disk with batch file",CR,LF ;AC000;
:def 1011 "Bad command or file name",CR,LF ;AC000;
:use 1014 EXTEND5 ;AC000;
:def 1016 "Content of destination lost before copy",CR,LF ;AC000;
:def 1017 "Invalid filename or file not found",CR,LF ;AC000;
:def 1018 "%1 File(s) copied",CR,LF ;AC000;
:def 1019 "%1 File(s) " ;AC000;
:use 1021 EXTEND15 ;AC000;
:def 1022 "Code page %1 not prepared for system",CR,LF ;AC000;
:def 1023 "Code page %1 not prepared for all devices",CR,LF ;AC000;
:def 1024 "Active code page: %1",CR,LF ;AC000;
:def 1025 "NLSFUNC not installed",CR,LF ;AC000;
:def 1027 "Current drive is no longer valid" ;AC000;
:def 1029 "Label not found",CR,LF ;AC000;
:def 1030 "Syntax error",CR,LF ;AC000;
:def 1032 "Current date is %1 %2",CR,LF ;AC000;
:def 1033 "SunMonTueWedThuFriSat" ;AC000;
:def 1034 "Enter new date (%1): " ;AC031;
:def 1036 "Current time is %1",CR,LF ;AC000;
:def 1037 "Enter new time: " ;AC031;
:def 1038 ", Delete (Y/N)?" ;AC000;
:def 1039 "All files in directory will be deleted!",CR,LF
"Are you sure (Y/N)?" ;AC000;
:def 1040 "Microsoft DOS Version %1.%2",CR,LF ;AC000;
:def 1044 "Invalid directory",CR,LF ;AC000;
:def 1046 "Invalid path, not directory,",CR,LF,"or directory not empty",CR,LF ;AC000;
:def 1047 "Must specify ON or OFF",CR,LF ;AC000;
:def 1048 "Directory of %1",CR,LF ;AC000;
:def 1049 "No Path",CR,LF ;AC000;
:def 1050 "Invalid drive in search path",CR,LF ;AC000;
:def 1051 "Invalid device",CR,LF ;AC000;
:def 1052 "FOR cannot be nested",CR,LF ;AC000;
:def 1053 "Intermediate file error during pipe",CR,LF ;AC000;
:def 1054 "Cannot do binary reads from a device",CR,LF ;AC000;
:def 1055 "BREAK is %1",CR,LF ;AC000;
:def 1056 "VERIFY is %1",CR,LF ;AC000;
:def 1057 "ECHO is %1",CR,LF ;AC000;
:def 1059 "off",0 ;AC000;
:def 1060 "on",0 ;AC000;
:def 1061 "Error writing to device",CR,LF ;AC000;
:def 1063 "%1" ;AC000;
:def 1064 "%1" ;AC000;
:def 1065 "%1" ;AC000;
:def 1066 "%1" ;AC000;
:def 1067 9 ;AC000;
:def 1068 " <DIR> " ;AC000;
:def 1069 8," ",8 ;AC000;
:def 1070 CR,LF ;AC000;
:def 1071 "%1" ;AC000;
:def 1072 "mm-dd-yy" ;AC000;
:def 1073 "dd-mm-yy" ;AC000;
:def 1074 "yy-mm-dd" ;AC000;
:def 1075 "%1 %2" ;AC000;
:def 1076 "%1" ;AC000;
:def 1077 " %1 %2" ;AC053;
:def 1078 "Directory already exists",CR,LF ;AC000;
:end ;AC000;

View File

@@ -0,0 +1,638 @@
page 80,132
; SCCSID = @(#)command1.asm 1.1 85/05/14
; SCCSID = @(#)command1.asm 1.1 85/05/14
TITLE COMMAND - resident code for COMMAND.COM
NAME COMMAND
;*****************************************************************************
;
; MODULE: COMMAND.COM
;
; DESCRIPTIVE NAME: Default DOS command interpreter
;
; FUNCTION: This version of COMMAND is divided into three distinct
; parts. First is the resident portion, which includes
; handlers for interrupts 23H (Cntrl-C), 24H (fatal
; error), and 2EH (command line execute); it also has
; code to test and, if necessary, reload the transient
; portion. Following the resident is the init code, which
; is overwritten after use. Then comes the transient
; portion, which includes all command processing (whether
; internal or external). The transient portion loads at
; the end of physical memory, and it may be overlayed by
; programs that need as much memory as possible. When the
; resident portion of command regains control from a user
; program, a check sum is performed on the transient
; portion to see if it must be reloaded. Thus programs
; which do not need maximum memory will save the time
; required to reload COMMAND when they terminate.
;
; ENTRY POINT: PROGSTART
;
; INPUT: command line at offset 81H
;
; EXIT_NORMAL: No exit from root level command processor. Can exit
; from a secondary command processor via the EXIT
; internal command.
;
; EXIT_ERROR: Exit to prior command processor if possible, otherwise
; hang the system.
;
; INTERNAL REFERENCES:
;
; ROUTINES: See the COMMAND Subroutine Description Document
; (COMMAND.DOC)
;
; DATA AREAS: See the COMMAND Subroutine Description Document
; (COMMAND.DOC)
;
; EXTERNAL REFERENCES:
;
; ROUTINES: none
;
; DATA AREAS: none
;
;*****************************************************************************
;
; REVISION HISTORY
; ----------------
;
; DOS 1.00 to DOS 3.30
; --------------------------
; SEE REVISION LOG IN COPY.ASM ALSO
;
; REV 1.17
; 05/19/82 Fixed bug in BADEXE error (relocation error must return to
; resident since the EXELOAD may have overwritten the transient.
;
; REV 1.18
; 05/21/82 IBM version always looks on drive A
; MSVER always looks on default drive
;
; REV 1.19
; 06/03/82 Drive spec now entered in command line
; 06/07/82 Added VER command (print DOS version number) and VOL command
; (print volume label)
;
; REV 1.20
; 06/09/82 Prints "directory" after directories
; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added
;
; REV 1.50
; Some code for new 2.0 DOS, sort of HACKey. Not enough time to
; do it right.
;
; REV 1.70
; EXEC used to fork off new processes
;
; REV 1.80
; C switch for single command execution
;
; REV 1.90
; Batch uses XENIX
;
; Rev 2.00
; Lots of neato stuff
; IBM 2.00 level
;
; Rev 2.01
; 'D' switch for date time suppression
;
; Rev 2.02
; Default userpath is NUL rather than BIN
; same as IBM
; COMMAND split into pieces
;
; Rev 2.10
; INTERNATIONAL SUPPORT
;
; Rev 2.50
; all the 2.x new stuff -MU
;
; Rev 3.30 (Ellen G)
; CALL internal command (TBATCH2.ASM)
; CHCP internal command (TCMD2B.ASM)
; INT 24H support of abort, retry, ignore, and fail prompt
; @ sign suppression of batch file line
; Replaceable environment value support in batch files
; INT 2FH calls for APPEND
; Lots of PTR fixes!
;
; Beyond 3.30 to forever (Ellen G)
; ----------------------
;
; A000 DOS 4.00 - Use SYSPARSE for internal commands
; Use Message Retriever services
; /MSG switch for resident extended error msg
; Convert to new capitalization support
; Better error recovery on CHCP command
; Code page file tag support
; TRUENAME internal command
; Extended screen line support
; /P switch on DEL/ERASE command
; Improved file redirection error recovery
; (removed) Improved batch file performance
; Unconditional DBCS support
; Volume serial number support
; (removed) COMMENT=?? support
;
; A001 PTM P20 Move system_cpage from TDATA to TSPC
;
; A002 PTM P74 Fix PRESCAN so that redirection symbols do not
; require delimiters.
;
; A003 PTM P5,P9,P111 Included in A000 development
;
; A004 PTM P86 Fix IF command to turn off piping before
; executing
;
; A005 DCR D17 If user specifies an extension on the command
; line search for that extension only.
;
; A006 DCR D15 New message for MkDir - "Directory already
; exists"
;
; A007 DCR D2 Change CTTY so that a write is done before XDUP
;
; A008 PTM P182 Change COPY to set default if invalid function
; returned from code page call.
;
; A009 PTM P179 Add CRLF to invalid disk change message
;
; A010 DCR D43 Allow APPEND to do a far call to SYSPARSE in
; transient COMMAND.
;
; A011 DCR D130 Change redirection to overwrite an EOF mark
; before appending to a file.
;
; A012 PTM P189 Fix redirection error recovery.
;
; A013 PTM P330 Change date format
;
; A014 PTM P455 Fix echo parsing
;
; A015 PTM P517 Fix DIR problem with * vs *.
;
; A016 PTM P354 Fix extended error message addressing
;
; A017 PTM P448 Fix appending to 0 length files
;
; A018 PTM P566,P3903 Fix parse error messages to print out parameter
; the parser fails on. Fail on duplicate switches.
;
; A019 PTM P542 Fix device name to be printed correctly during
; critical error
;
; A020 DCR D43 Set append state off while in DIR
;
; A021 PTM P709 Fix CTTY printing ascii characters.
;
; A022 DCR D209 Enhanced error recovery
;
; A023 PTM P911 Fix ANSI.SYS IOCTL structure.
;
; A024 PTM P899 Fix EXTOPEN open modes.
;
; A025 PTM P922 Fix messages and optimize PARSE switches
;
; A026 DCR D191 Change redirection error recovery support.
;
; A027 PTM P991 Fix so that KAUTOBAT & AUTOEXEC are terminated
; with a carriage return.
;
; A028 PTM P1076 Print a blank line before printing invalid
; date and invalid time messages.
;
; A029 PTM P1084 Eliminate calls to parse_check_eol in DATE
; and TIME.
;
; A030 DCR D201 New extended attribute format.
;
; A031 PTM P1149 Fix DATE/TIME add blank before prompt.
;
; A032 PTM P931 Fix =ON, =OFF for BREAK, VERIFY, ECHO
;
; A033 PTM P1298 Fix problem with system crashes on ECHO >""
;
; A034 PTM P1387 Fix COPY D:fname+,, to work
;
; A035 PTM P1407 Fix so that >> (appending) to a device does
; do a read to determine eof.
;
; A036 PTM P1406 Use 69h instead of 44h to get volume serial
; so that ASSIGN works correctly.
;
; A037 PTM P1335 Fix COMMAND /C with FOR
;
; A038 PTM P1635 Fix COPY so that it doesn't accept /V /V
;
; A039 DCR D284 Change invalid code page tag from -1 to 0.
;
; A040 PTM P1787 Fix redirection to cause error when no file is
; specified.
;
; A041 PTM P1705 Close redirected files after internal APPEND
; executes.
;
; A042 PTM P1276 Fix problem of APPEND paths changes in batch
; files causing loss of batch file.
;
; A043 PTM P2208 Make sure redirection is not set up twice for
; CALL'ed batch files.
;
; A044 PTM P2315 Set switch on PARSE so that 0ah is not used
; as an end of line character
;
; A045 PTM P2560 Make sure we don't lose parse, critical error,
; and extended message pointers when we EXIT if
; COMMAND /P is the top level process.
;
; A046 PTM P2690 Change COPY message "fn File not found" to
; "File not found - fn"
;
; A047 PTM P2819 Fix transient reload prompt message
;
; A048 PTM P2824 Fix COPY path to be upper cased. This was broken
; when DBCS code was added.
;
; A049 PTM P2891 Fix PATH so that it doesn't accept extra characters
; on line.
;
; A050 PTM P3030 Fix TYPE to work properly on files > 64K
;
; A051 PTM P3011 Fix DIR header to be compatible with prior releases.
;
; A052 PTM P3063,P3228 Fix COPY message for invalid filename on target.
;
; A053 PTM P2865 Fix DIR to work in 40 column mode.
;
; A054 PTM P3407 Code reduction and critical error on single line
; PTM P3672 (Change to single parser exported under P3407)
;
; A055 PTM P3282 Reset message service variables in INT 23h to fix
; problems with breaking out of INT 24h
;
; A056 PTM P3389 Fix problem of environment overlaying transient.
;
; A057 PTM P3384 Fix COMMAND /C so that it works if there is no space
; before the "string". EX: COMMAND /CDIR
;
; A058 PTM P3493 Fix DBCS so that CPARSE eats second character of
; DBCS switch.
;
; A059 PTM P3394 Change the TIME command to right align the display of
; the time.
;
; A060 PTM P3672 Code reduction - change PARSE and EXTENDED ERROR
; messages to be disk based. Only keep them if /MSG
; is used.
;
; A061 PTM P3928 Fix so that transient doesn't reload when breaking
; out of internal commands, due to substitution blocks
; not being reset.
;
; A062 PTM P4079 Fix segment override for fetching address of environment
; of parent copy of COMMAND when no COMSPEC exists in
; secondary copy of environment. Change default slash in
; default comspec string to backslash.
; A063 PTM P4140 REDIRECTOR and IFSFUNC changed interface for getting
; text for critical error messages.
; A064 PTM P4934 Multiplex number for ANSI.SYS changed due to conflict
; 5/20/88 with Microsoft product already shipped.
; A065 PTM P4935 Multiplex number for SHELL changed due to conflict with
; 5/20/88 with Microsoft product already shipped.
; A066 PTM P4961 DIR /W /P scrolled first line off the screen in some
; 5/24/88 cases; where the listing would barely fit without the
; header and space remaining.
; A067 PTM P5011 For /E: values of 993 to 1024 the COMSPEC was getting
; 6/6/88 trashed. Turns out that the SETBLOCK for the new
; environment was putting a "Z block" marker in the old
; environment. The fix is to move to the old environment
; to the new environment before doing the SETBLOCK.
;***********************************************************************************
.XCREF
.XLIST
INCLUDE DOSSYM.INC
INCLUDE comsw.asm
INCLUDE comequ.asm
INCLUDE resmsg.equ ;AN000;
.LIST
.CREF
CODERES SEGMENT PUBLIC BYTE ;AC000;
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE
EXTRN BATCH:WORD
EXTRN ECHOFLAG:BYTE
EXTRN disp_class:byte ;AN055;
EXTRN execemes_block:byte ;AC000;
EXTRN execemes_off:word ;AC000;
EXTRN execemes_subst:byte ;AC000;
EXTRN execemes_seg:word ;AC000;
EXTRN EXTCOM:BYTE
EXTRN FORFLAG:BYTE
EXTRN IFFlag:BYTE
EXTRN InitFlag:BYTE
EXTRN NEST:WORD
EXTRN number_subst:byte ;AC000;
EXTRN PIPEFLAG:BYTE
EXTRN RETCODE:WORD
EXTRN SINGLECOM:WORD
DATARES ENDS
BATARENA SEGMENT PUBLIC PARA ;AC000;
BATARENA ENDS
BATSEG SEGMENT PUBLIC PARA ;AC000;
BATSEG ENDS
ENVARENA SEGMENT PUBLIC PARA ;AC000;
ENVARENA ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC PARA
EXTRN CONPROC:NEAR
EXTRN init_contc_specialcase:near
INIT ENDS
TAIL SEGMENT PUBLIC PARA
TAIL ENDS
TRANCODE SEGMENT PUBLIC PARA
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC PARA
TRANTAIL ENDS
RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
INCLUDE envdata.asm
; START OF RESIDENT PORTION
CODERES SEGMENT PUBLIC BYTE ;AC000;
PUBLIC EXT_EXEC
PUBLIC CONTC
PUBLIC Exec_Wait
ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN lodcom:near
EXTRN LODCOM1:near
ORG 0
ZERO = $
ORG 80h-1
PUBLIC RESCOM
RESCOM LABEL BYTE
ORG 100H
PROGSTART:
JMP RESGROUP:CONPROC
;
; COMMAND has issued an EXEC system call and it has returned an error. We
; examine the error code and select an appropriate message.
;
EXEC_ERR:
push ds ;AC000; get transient segment
pop es ;AC000; into ES
push cs ;AC000; get resident segment
pop ds ;AC000; into DS
ASSUME DS:RESGROUP ;AN000;
MOV BX,RBADNAM ;AC000; Get message number for Bad command
CMP AX,error_file_not_found
JZ GOTEXECEMES
MOV BX,TOOBIG ;AC000; Get message number for file not found
CMP AX,error_not_enough_memory
JZ GOTEXECEMES
MOV BX,EXEBAD ;AC000; Get message number for bad exe file
CMP AX,error_bad_format
JZ GOTEXECEMES
MOV BX,AccDen ;AC000; Get message number for access denied
CMP AX,error_access_denied
JZ GOTEXECEMES ;AC000; go print message
DEFAULT_MESSAGE:
MOV BX,EXECEMES ;AC000; Get message number for default message
MOV EXECEMES_OFF,DX ;AN000; put offset of EXEC string in subst block
MOV EXECEMES_SEG,ES ;AN000; put segment of EXEC string in subst block
MOV AL,EXECEMES_SUBST ;AN000; get number of substitutions
MOV NUMBER_SUBST,AL ;AN000;
MOV SI,OFFSET RESGROUP:EXECEMES_BLOCK ;AN000; get address of subst block
GOTEXECEMES:
PUSH CS
POP ES ;AC000; get resident segment into ES
ASSUME ES:RESGROUP ;AN000;
MOV DX,BX ;AN000; get message number in DX
INVOKE RPRINT
JMP SHORT NOEXEC
;
; The transient has set up everything for an EXEC system call. For
; cleanliness, we issue the EXEC here in the resident so that we may be able
; to recover cleanly upon success.
;
EXT_EXEC:
push dx ;AN000; save the command name offset
INT int_command ; Do the EXEC
pop dx ;AN000; restore the command name offset
JC EXEC_ERR ; EXEC failed
;
; The exec has completed. Retrieve the exit code.
;
EXEC_WAIT:
push cs ;AC000; get resident segment
pop ds ;AC000; into DS
MOV AH,WAITPROCESS ;AC000; Get errorlevel
INT int_command ; Get the return code
MOV [RETCODE],AX
;
; We need to test to see if we can reload the transient. THe external command
; may have overwritten part of the transient.
;
NOEXEC:
JMP LODCOM
;
; This is the default system INT 23 handler. All processes (including
; COMMAND) get it by default. There are some games that are played: We
; ignore ^C during most of the INIT code. This is because we may perform an
; ALLOC and diddle the header! Also, if we are prompting for date/time in the
; init code, we are to treat ^C as empty responses.
;
CONTC PROC FAR
ASSUME CS:ResGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
test InitFlag,initINIT ; in initialization?
jz NotAtInit ; no
test InitFlag,initSpecial ; doing special stuff?
jz CmdIRet ; no, ignore ^C
jmp resgroup:init_contc_specialcase ; Yes, go handle it
CmdIret:
iret ; yes, ignore the ^C
NotAtInit:
test InitFlag,initCtrlC ; are we already in a ^C?
jz NotInit ; nope too.
;
; We are interrupting ourselves in this ^C handler. We need to set carry
; and return to the user sans flags only if the system call was a 1-12 one.
; Otherwise, we ignore the ^C.
;
cmp ah,1
jb CmdIRet
cmp ah,12
ja CmdIRet
add sp,6 ; remove int frame
stc
ret 2 ; remove those flags...
;
; We have now received a ^C for some process (maybe ourselves but not at INIT).
;
; Note that we are running on the user's stack!!! Bad news if any of the
; system calls below go and issue another INT 24... Massive stack overflow!
; Another bad point is that SavHand will save an already saved handle, thus
; losing a possible redirection...
;
; All we need to do is set the flag to indicate nested ^C. The above code
; will correctly flag the ^C diring the message output and prompting while
; ignoring the ^C the rest of the time.
;
; Clean up: flush disk. If we are in the middle of a batch file, we ask if
; he wants to terminate it. If he does, then we turn off all internal flags
; and let the DOS abort.
;
NotInit:
or InitFlag,initCtrlC ; nested ^c is on
STI
PUSH CS ; El Yucko! Change the user's DS!!
POP DS
ASSUME DS:RESGROUP
MOV DISP_CLASS,UTIL_MSG_CLASS ;AN055; reset display class
MOV NUMBER_SUBST,NO_SUBST ;AN055; reset number of substitutions
MOV AX,SingleCom
OR AX,AX
JNZ NoReset
PUSH AX
MOV AH,DISK_RESET
INT int_command ; Reset disks in case files were open
POP AX
NoReset:
;
; In the generalized version of FOR, PIPE and BATCH, we would walk the entire
; active list and free each segment. Here, we just free the single batch
; segment.
;
TEST Batch,-1
JZ CONTCTERM
OR AX,AX
JNZ Contcterm
invoke SavHand
invoke ASKEND ; See if user wants to terminate batch
;
; If the carry flag is clear, we do NOT free up the batch file
;
JNC ContBatch
mov cl,echoflag ;AN000; get current echo flag
PUSH BX ;G
ClearBatch:
MOV ES,[BATCH] ; get batch segment
mov di,batfile ;AN000; get offset of batch file name
mov ax,mult_shell_brk ;AN000; does the SHELL want this terminated?
int 2fh ;AN000; call the SHELL
cmp al,shell_action ;AN000; does shell want this batch?
jz shell_bat_cont ;AN000; yes - keep it
MOV BX,ES:[BATFORPTR] ;G get old FOR segment
cmp bx,0 ;G is a FOR in progress
jz no_bat_for ;G no - don't deallocate
push es ;G
mov es,bx ;G yes - free it up...
MOV AH,DEALLOC ;G
INT 21H ;G
pop es ;G restore to batch segment
no_bat_for:
mov cl,ES:[batechoflag] ;G get old echo flag
MOV BX,ES:[BATLAST] ;G get old batch segment
MOV AH,DEALLOC ; free it up...
INT 21H
MOV [BATCH],BX ;G get ready to deallocate next batch
DEC NEST ;G Is there another batch file?
JNZ CLEARBATCH ;G Keep going until no batch file
;
; We are terminating a batch file; restore the echo status
;
shell_bat_cont: ;AN000; continue batch for SHELL
POP BX ;G
MOV ECHOFLAG,CL ;G reset echo status
MOV PIPEFLAG,0 ;G turn off pipeflag
ContBatch:
invoke CRLF ;G print out crlf before returning
invoke RestHand
;
; Yes, we are terminating. Turn off flags and allow the DOS to abort.
;
CONTCTERM:
XOR AX,AX ; Indicate no read
MOV BP,AX
;
; The following resetting of the state flags is good for the generalized batch
; processing.
;
MOV IfFlag,AL ; turn off iffing
MOV [FORFLAG],AL ; Turn off for processing
call ResPipeOff
CMP [SINGLECOM],AX ; See if we need to set SINGLECOM
JZ NOSETSING
MOV [SINGLECOM],-1 ; Cause termination on pipe, batch, for
NOSETSING:
;
; If we are doing an internal command, go through the reload process. If we
; are doing an external, let DOS abort the process. In both cases, we are
; now done with the ^C processing.
;
AND InitFlag,NOT initCtrlC
CMP [EXTCOM],AL
JNZ DODAB ; Internal ^C
JMP LODCOM1
DODAB:
STC ; Tell DOS to abort
RET ; Leave flags on stack
ContC ENDP
public ResPipeOff
assume ds:nothing,es:nothing
ResPipeOff:
SaveReg <AX>
xor ax,ax
xchg PipeFlag,al
or al,al
jz NoPipePop
shr EchoFlag,1
NoPipePop:
RestoreReg <AX>
return
CODERES ENDS
END PROGSTART

View File

@@ -0,0 +1,619 @@
page 80,132
; SCCSID = @(#)command2.asm 4.3 85/10/16
; SCCSID = @(#)command2.asm 4.3 85/10/16
TITLE COMMAND2 - resident code for COMMAND.COM part II
NAME COMMAND2
.XCREF
.XLIST
INCLUDE DOSSYM.INC
INCLUDE comsw.asm
INCLUDE comequ.asm
INCLUDE resmsg.equ ;AN000;
.LIST
.CREF
tokenized = FALSE
CODERES SEGMENT PUBLIC BYTE ;AC000;
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE
EXTRN append_state:word ;AN020;
EXTRN append_flag:byte ;AN020;
EXTRN COMDRV:BYTE
EXTRN comprmt1_block:byte ;AN000;
EXTRN comprmt1_subst:byte ;AN000;
EXTRN COMSPEC:BYTE
EXTRN cpdrv:byte
EXTRN envirseg:word
EXTRN EXTCOM:BYTE
EXTRN HANDLE01:WORD
EXTRN InitFlag:BYTE
EXTRN INT_2E_RET:DWORD ;AC000;
EXTRN IO_SAVE:WORD
EXTRN LOADING:BYTE
EXTRN LTPA:WORD
EXTRN MEMSIZ:WORD
EXTRN number_subst:byte ;AN000;
EXTRN OldTerm:DWORD ;AC000;
EXTRN PARENT:WORD ;AC000;
EXTRN PERMCOM:BYTE
EXTRN RDIRCHAR:BYTE
EXTRN RES_TPA:WORD
EXTRN RETCODE:WORD
EXTRN rsrc_xa_seg:word ;AN030;
EXTRN RSWITCHAR:BYTE
EXTRN SAVE_PDB:WORD
EXTRN SINGLECOM:WORD
EXTRN SUM:WORD
EXTRN TRANS:WORD
EXTRN TranVarEnd:BYTE
EXTRN TRANVARS:BYTE
EXTRN TRNSEG:WORD
EXTRN VERVAL:WORD
DATARES ENDS
BATARENA SEGMENT PUBLIC PARA ;AC000;
BATARENA ENDS
BATSEG SEGMENT PUBLIC PARA ;AC000;
BATSEG ENDS
ENVARENA SEGMENT PUBLIC PARA ;AC000;
ENVARENA ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC PARA
EXTRN envsiz:word
EXTRN oldenv:word
EXTRN resetenv:byte
EXTRN usedenv:word
INIT ENDS
TAIL SEGMENT PUBLIC PARA
TAIL ENDS
TRANCODE SEGMENT PUBLIC PARA
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC BYTE
EXTRN TRANDATAEND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE
EXTRN TRANSPACEEND:BYTE
EXTRN HEADCALL:DWORD
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC PARA
TRANTAIL ENDS
RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
; START OF RESIDENT PORTION
CODERES SEGMENT PUBLIC BYTE ;AC000;
PUBLIC CHKSUM
PUBLIC endinit
PUBLIC GETCOMDSK2
PUBLIC INT_2E
PUBLIC LOADCOM
PUBLIC LODCOM
PUBLIC LODCOM1
PUBLIC RESTHAND
PUBLIC SAVHAND
PUBLIC SETVECT
PUBLIC THEADFIX
PUBLIC TREMCHECK
PUBLIC tjmp
ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN contc:near
EXTRN DSKERR:NEAR
EXTRN rstack:word
;
; If we cannot allocate enough memory for the transient or there was some
; other allocation error, we display a message and then die.
;
BADMEMERR: ; Allocation error loading transient
MOV DX,BMEMMES ;AC000; get message number
FATALC:
PUSH CS
POP DS
ASSUME DS:ResGroup
invoke RPRINT
;
; If this is NOT a permanent (top-level) COMMAND, then we exit; we can't do
; anything else!
;
CMP PERMCOM,0
JZ FATALRET
;
; We are a permanent command. If we are in the process of the magic interrupt
; (Singlecom) then exit too.
;
CMP SINGLECOM,0 ; If PERMCOM and SINGLECOM
JNZ FATALRET ; Must take INT_2E exit
;
; Permanent command. We can't do ANYthing except halt.
;
MOV DX,HALTMES ;AC000; get message number
invoke RPRINT
STI
STALL:
JMP STALL ; Crash the system nicely
FATALRET:
MOV DX,FRETMES ;AC000; get message number
invoke RPRINT
FATALRET2:
CMP [PERMCOM],0 ; If we get here and PERMCOM,
JNZ RET_2E ; must be INT_2E
invoke reset_msg_pointers ;AN000; reset critical & parse error messages
MOV AX,[PARENT]
MOV WORD PTR CS:[PDB_Parent_PID],AX
MOV AX,WORD PTR OldTerm
MOV WORD PTR CS:[PDB_Exit],AX
MOV AX,WORD PTR OldTerm+2
MOV WORD PTR CS:[PDB_Exit+2],AX
MOV AX,(EXIT SHL 8) ; Return to lower level
INT int_command
RET_2E:
PUSH CS
POP DS
ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING
MOV [SINGLECOM],0 ; Turn off singlecom
MOV ES,[RES_TPA]
MOV AH,DEALLOC
INT int_command ; Free up space used by transient
MOV BX,[SAVE_PDB]
MOV AH,SET_CURRENT_PDB
INT int_command ; Current process is user
MOV AX,[RETCODE]
CMP [EXTCOM],0
JNZ GOTECODE
XOR AX,AX ; Internals always return 0
GOTECODE:
MOV [EXTCOM],1 ; Force external
JMP [INT_2E_RET] ;"IRET"
INT_2E: ; Magic command executer
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
POP WORD PTR [INT_2E_RET]
POP WORD PTR [INT_2E_RET+2] ;Get return address
POP AX ;Chuck flags
PUSH CS
POP ES
MOV DI,80H
MOV CX,64
REP MOVSW
MOV AH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOV [SAVE_PDB],BX
MOV AH,SET_CURRENT_PDB
MOV BX,CS
INT int_command ; Current process is me
MOV [SINGLECOM],81H
MOV [EXTCOM],1 ; Make sure this case forced
LODCOM: ; Termination handler
CMP [EXTCOM],0
jz lodcom1 ; if internal, memory already allocated
mov bx,0ffffh
MOV AH,ALLOC
INT int_command
CALL SetSize
ADD AX,20H
CMP BX,AX ; Is less than 512 byte buffer worth it?
JNC MEMOK
BADMEMERRJ:
JMP BADMEMERR ; Not enough memory
; SetSize - get transient size in paragraphs
Procedure SetSize,NEAR
MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15
MOV CL,4
SHR AX,CL
return
EndProc SetSize
MEMOK:
MOV AH,ALLOC
INT int_command
JC BADMEMERRJ ; Memory arenas probably trashed
MOV [EXTCOM],0 ; Flag not to ALLOC again
MOV [RES_TPA], AX ; Save current TPA segment
AND AX, 0F000H
ADD AX, 01000H ; Round up to next 64K boundary
JC BAD_TPA ; Memory wrap if carry set
; Make sure that new boundary is within allocated range
MOV DX, [RES_TPA]
ADD DX, BX ; Compute maximum address
CMP DX, AX ; Is 64K address out of range?
JBE BAD_TPA
; Must have 64K of usable space.
SUB DX, AX ; Compute the usable space
CMP DX, 01000H ; Is space >= 64K ?
JAE LTPASET
BAD_TPA:
MOV AX, [RES_TPA]
LTPASET:
MOV [LTPA],AX ; Usable TPA is 64k buffer aligned
MOV AX, [RES_TPA] ; Actual TPA is buffer allocated
ADD BX,AX
MOV [MEMSIZ],BX
CALL SetSize
SUB BX,AX
MOV [TRNSEG],BX ; Transient starts here
LODCOM1:
MOV AX,CS
MOV SS,AX
ASSUME SS:RESGROUP
MOV SP,OFFSET RESGROUP:RSTACK
MOV DS,AX
ASSUME DS:RESGROUP
CALL HEADFIX ; Make sure files closed stdin and stdout restored
XOR BP,BP ; Flag command ok
MOV AX,-1
XCHG AX,[VERVAL]
CMP AX,-1
JZ NOSETVER
MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
INT int_command
NOSETVER:
CMP [SINGLECOM],-1
JNZ NOSNG
JMP FATALRET2 ; We have finished the single command
NOSNG:
CALL CHKSUM ; Check the transient
CMP DX,[SUM]
JZ HAVCOM ; Transient OK
BOGUS_COM:
MOV [LOADING],1 ; Flag DSKERR routine
CALL LOADCOM
CHKSAME:
CALL CHKSUM
CMP DX,[SUM]
JZ HAVCOM ; Same COMMAND
ALSO_BOGUS:
CALL WRONGCOM
JMP SHORT CHKSAME
HAVCOM:
MOV AX,CHAR_OPER SHL 8
INT int_command
MOV [RSWITCHAR],DL
CMP DL,'/'
JNZ USESLASH
mov cl,'\'
MOV [RDIRCHAR],cl ; Select alt path separator
USESLASH:
MOV [LOADING],0 ; Flag to DSKERR
MOV SI,OFFSET RESGROUP:TRANVARS
MOV DI,OFFSET TRANGROUP:HEADCALL
MOV ES,[TRNSEG]
CLD
MOV CX,OFFSET ResGroup:TranVarEnd
SUB CX,SI
REP MOVSB ; Transfer INFO to transient
MOV AX,[MEMSIZ]
MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
; Just a public label so this spot can be found easily.
tjmp:
JMP DWORD PTR [TRANS]
; Far call to REMCHECK for TRANSIENT
TREMCHECK PROC FAR
CALL REMCHECK
RET
TREMCHECK ENDP
REMCHECK:
;All registers preserved. Returns ZF set if media removable, NZ if fixed
; AL is drive (0=DEF, 1=A,...).
SaveReg <AX,BX>
MOV BX,AX
MOV AX,(IOCTL SHL 8) + 8
INT 21h
jnc RCcont ; If an error occurred, assume the media
or ax,ax ; is NON-removable.
; AX contains the non-zero error code
; from the INT 21, so the OR AX,AX sets
; Non-zero. This behavior makes Network
; drives appear to be non-removable.
jmp SHORT ResRegs
RCcont:
AND AX,1
NOT AX
ResRegs:
RestoreReg <BX,AX>
return
; Far call to HEADFIX for TRANSIENT
THEADFIX PROC FAR
CALL HEADFIX
RET
THEADFIX ENDP
HEADFIX:
CALL SETVECT
XOR BX,BX ; Clean up header
MOV CX,[IO_SAVE]
MOV DX,WORD PTR DS:[PDB_JFN_Table]
CMP CL,DL
JZ CHK1 ; Stdin matches
MOV AH,CLOSE
INT int_command
MOV DS:[PDB_JFN_Table],CL ; Restore stdin
CHK1:
INC BX
CMP CH,DH ; Stdout matches
JZ CHKOTHERHAND
MOV AH,CLOSE
INT int_command
MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout
CHKOTHERHAND:
ADD BX,4 ; Skip 2,3,4
MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4
CLOSELOOP:
MOV AH,CLOSE
INT int_command
INC BX
LOOP CLOSELOOP
push ds ;AN020; save data segment
push cs ;AN020; Get local segment into DS
pop ds ;AN020;
cmp append_flag,-1 ;AN020; Do we need to reset APPEND?
jnz append_fix_end ;AN030; no - just exit
mov ax,AppendSetState ;AN020; Set the state of Append
mov bx,Append_state ;AN020; back to the original state
int 2fh ;AN020;
mov append_flag,0 ;AN020; Set append flag to invalid
append_fix_end: ;AN030;
cmp [rsrc_xa_seg],no_xa_seg ;AN030; Is there any active XA segment?
jz xa_fix_end ;AN030; no - exit
push es ;AN030; Yes - deallocate it
mov es,rsrc_xa_seg ;AN030;
mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call
int int_command ;AN030;
pop es ;AN030;
mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment
xa_fix_end:
pop ds ;AN020; get data segment back
return
SAVHAND:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH DS
PUSH BX ; Set stdin to sterr, stdout to stderr
PUSH AX
MOV AH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOV DS,BX
LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table...
MOV AX,WORD PTR DS:[BX]
MOV [HANDLE01],AX ; Save user's stdin, stdout
MOV AL,CS:[PDB_JFN_Table+2] ; get COMMAND stderr
MOV AH,AL
MOV WORD PTR DS:[BX],AX ; Dup stderr
POP AX
POP BX
POP DS
return
ASSUME DS:RESGROUP
GETCOMDSK2:
CALL GETCOMDSK
JMP LODCOM1 ; Memory already allocated
RESTHAND:
PUSH DS
PUSH BX ; Restore stdin, stdout to user
PUSH AX
MOV AH,GET_CURRENT_PDB
INT int_command ; Point to user's header
MOV AX,[HANDLE01]
MOV DS,BX
ASSUME DS:NOTHING
LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table...
MOV WORD PTR DS:[BX],AX ; Stuff his old 0 and 1
POP AX
POP BX
POP DS
return
ASSUME DS:RESGROUP,SS:RESGROUP
HOPELESS:
MOV DX,COMBAD ;AC000;
JMP FATALC
GETCOMDSK:
mov al,[comdrv]
CALL REMCHECK
jNZ HOPELESS ;Non-removable media
getcomdsk3:
cmp dx,combad ;AC000;
jnz getcomdsk4
mov dx,combad ;AN000; get message number
invoke RPRINT ; Say command is invalid
getcomdsk4:
cmp [cpdrv],0 ;g is there a drive in the comspec?
jnz users_drive ;g yes - use it
mov ah,Get_default_drive ;g use default drive
int 21h ;g
add al,"A" ;g convert to ascii
mov [cpdrv],al ;g put in message to print out
users_drive: ;g
mov dx,comprmt1 ;AC000; Prompt for diskette containing command
IF tokenized
or byte ptr [si],80h
endif
MOV AL,COMPRMT1_SUBST ;AN000; get number of substitutions
MOV SI,OFFSET RESGROUP:COMPRMT1_BLOCK ;AN000; get address of subst block
MOV NUMBER_SUBST,AL ;AN000;
invoke rprint
if tokenized
and byte ptr [si],NOT 80h
endif
mov dx,prompt ;AN047; Tell the user to strike a key
invoke rprint ;AN047;
CALL GetRawFlushedByte
return
; flush world and get raw input
GetRawFlushedByte:
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT
INT int_command ; Get char without testing or echo
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0
INT int_command
return
LOADCOM: ; Load in transient
INC BP ; Flag command read
MOV DX,OFFSET RESGROUP:COMSPEC
MOV AX,OPEN SHL 8
INT int_command ; Open COMMAND.COM
JNC READCOM
CMP AX,error_too_many_open_files
JNZ TRYDOOPEN
MOV DX,NOHANDMES ;AC000;
JMP FATALC ; Fatal, will never find a handle
TRYDOOPEN:
CALL GETCOMDSK
JMP LOADCOM
READCOM:
MOV BX,AX ; Handle
MOV DX,OFFSET RESGROUP:TRANSTART
XOR CX,CX ; Seek loc
MOV AX,LSEEK SHL 8
INT int_command
JC WRONGCOM1
MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H
PUSH DS
MOV DS,[TRNSEG]
ASSUME DS:NOTHING
MOV DX,100H
MOV AH,READ
INT int_command
POP DS
ASSUME DS:RESGROUP
WRONGCOM1:
PUSHF
PUSH AX
MOV AH,CLOSE
INT int_command ; Close COMMAND.COM
POP AX
POPF
JC WRONGCOM ; If error on READ
CMP AX,CX
retz ; Size matched
WRONGCOM:
MOV DX,COMBAD ;AC000;
CALL GETCOMDSK
JMP LOADCOM ; Try again
CHKSUM: ; Compute transient checksum
PUSH DS
MOV DS,[TRNSEG]
MOV SI,100H
MOV CX,OFFSET TRANGROUP:TranDataEnd - 100H
CHECK_SUM:
CLD
SHR CX,1
XOR DX,DX
CHK:
LODSW
ADD DX,AX
ADC DX,0
LOOP CHK
POP DS
return
SETVECT: ; Set useful vectors
MOV DX,OFFSET RESGROUP:LODCOM
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H
MOV WORD PTR DS:[PDB_EXIT],DX
MOV WORD PTR DS:[PDB_EXIT+2],DS
INT int_command
MOV DX,OFFSET RESGROUP:CONTC
INC AL
INT int_command
MOV DX,OFFSET RESGROUP:DSKERR
INC AL
INT int_command
return
;
; This routine moves the environment to a newly allocated segment
; at the end of initialization
;
ENDINIT:
push ds ;g save segments
push es ;g
push cs ;g get resident segment to DS
pop ds ;g
ASSUME DS:RESGROUP
mov cx,usedenv ;g get number of bytes to move
mov es,envirseg ;g get target environment segment
ASSUME ES:NOTHING
mov DS:[PDB_environ],es ;g put new environment in my header ;AM067;
mov ds,oldenv ;g source environment segment ;AM067;
ASSUME DS:NOTHING ;AM067;
xor si,si ;g set up offsets to start of segments ;AM067;
xor di,di ;g ;AM067;
cld ;g make sure we move the right way! ;AM067;
rep movsb ;g move it ;AM067;
xor ax,ax ;g ;AM067;
stosb ;g make sure there are double 0 at end ;AM067;
cmp resetenv,1 ;eg Do we need to setblock to env end?
jnz noreset ;eg no - we already did it
mov bx,envsiz ;eg get size of environment in paragraphs
push es ;eg save environment - just to make sure
mov ah,SETBLOCK ;eg
int int_command ;eg
pop es ;eg
noreset:
mov InitFlag,FALSE ;AC042; Turn off init flag
pop es ;g
pop ds ;g
jmp lodcom ;g allocate transient
CODERES ENDS
; This TAIL segment is used to produce a PARA aligned label in the resident
; group which is the location where the transient segments will be loaded
; initial.
TAIL SEGMENT PUBLIC PARA
ORG 0
PUBLIC TranStart
TRANSTART LABEL WORD
TAIL ENDS
; This TAIL segment is used to produce a PARA aligned label in the transient
; group which is the location where the exec segments will be loaded
; initial.
TRANTAIL SEGMENT PUBLIC PARA
ORG 0
EXECSTART LABEL WORD
TRANTAIL ENDS
END

View File

@@ -0,0 +1,43 @@
; SCCSID = @(#)comseg.asm 1.1 85/05/14
; SCCSID = @(#)comseg.asm 1.1 85/05/14
; The following are all of the segments used in the load order
CODERES SEGMENT PUBLIC BYTE ;AC000; resident code
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000; resident data
DATARES ENDS
BATARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header
BATARENA ENDS
BATSEG SEGMENT PUBLIC PARA ;AC000; AUTOEXEC batch segment
BATSEG ENDS
ENVARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header
ENVARENA ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ;AC000; Default COMMAND environment
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC PARA ;AC000; Initialization code
INIT ENDS
TAIL SEGMENT PUBLIC PARA ;AC000; End of Init - start of Transient
TAIL ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000; Transient code
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000; Transient data area
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000; Transient modifiable data area
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC PARA ;AC000; End of Transient
TRANTAIL ENDS
RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL


View File

@@ -0,0 +1,6 @@
; SCCSID = @(#)comsw.asm 1.1 85/05/14
; SCCSID = @(#)comsw.asm 1.1 85/05/14
include version.inc


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
page 80,132
; SCCSID = @(#)copypr1.asm 1.1 85/05/14
; SCCSID = @(#)copypr1.asm 1.1 85/05/14
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
; INCLUDE DEVSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN DEVWMES_ptr:word
EXTRN ext_open_parms:byte ;AN000;
EXTRN ext_open_seg:word ;AN000;
EXTRN ext_open_off:word ;AN000;
EXTRN Extend_buf_sub:byte ;AN000;
EXTRN LOSTERR_ptr:word
EXTRN NOSPACE_ptr:word
EXTRN OVERWR_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN ASCII:BYTE
EXTRN BINARY:BYTE
EXTRN CFLAG:BYTE
EXTRN CONCAT:BYTE
EXTRN concat_xa:byte ;AC000;
EXTRN DESTBUF:BYTE
EXTRN DESTCLOSED:BYTE
EXTRN DESTHAND:WORD
EXTRN DESTISDEV:BYTE
EXTRN DESTSWITCH:WORD
EXTRN INEXACT:BYTE
EXTRN NOWRITE:BYTE
EXTRN NXTADD:WORD
EXTRN plus_comma:byte ;AN000;
EXTRN RDEOF:BYTE
EXTRN src_xa_seg:word ;AN000;
EXTRN SRCISDEV:BYTE
EXTRN string_ptr_2:word ;AN000;
EXTRN TERMREAD:BYTE
EXTRN TPA:WORD
EXTRN WRITTEN:WORD
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
EXTRN ENDCOPY:NEAR
PUBLIC FLSHFIL
PUBLIC TRYFLUSH
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
TRYFLUSH:
mov al,[CONCAT]
push ax
call FLSHFIL
pop ax
cmp al,[CONCAT]
return
FLSHFIL:
;
; Write out any data remaining in memory.
; Inputs:
; [NXTADD] = No. of bytes to write
; [CFLAG] <> 0 if file has been created
; Outputs:
; [NXTADD] = 0
;
MOV [TERMREAD],0
cmp [CFLAG],0
JZ NOTEXISTS
JMP EXISTS
NOTEXISTS:
invoke BUILDDEST ; Find out all about the destination
invoke COMPNAME ; Source and dest. the same?
JNZ PROCDEST ; If not, go ahead
CMP [SRCISDEV],0
JNZ PROCDEST ; Same name on device OK
CMP [CONCAT],0 ; Concatenation?
MOV DX,OFFSET TRANGROUP:OVERWR_ptr
JNZ NO_CONCAT_ERR ;AC000; If not, overwrite error
JMP COPERR ;AC000;
NO_CONCAT_ERR: ;AC000;
MOV [NOWRITE],1 ; Flag not writting (just seeking)
PROCDEST:
MOV AX,EXTOPEN SHL 8 ;AC000; open the file
mov si,offset trangroup:destbuf ;AN030; get file name
mov di,-1 ;AN030; indicate no parameters
cmp src_xa_seg,no_xa_seg ;AN030; is there an XA segment?
jz cont_no_xa ;AN030; no - no parameters
mov di,offset trangroup:Ext_open_parms ;AN030; get parameters
mov bx,src_xa_seg ;AN030; get extended attribute segment
mov ext_open_seg,bx ;AN030; put it in parameter list
mov ext_open_off,0 ;AN030; offset is 0
cont_no_xa: ;AN030;
mov bx,write_open_mode ;AN000; get open mode for COPY
xor cx,cx ;AN000; no special files
mov dx,write_open_flag ;AN000; set up open flags
CMP [NOWRITE],0
JNZ DODESTOPEN ; Don't actually create if NOWRITE set
mov dx,creat_open_flag ;AC000; set up create flags
DODESTOPEN:
INT int_command
;
; We assume that the error is normal. TriageError will correct the DX value
; appropriately.
;
JNC dest_open_okay ;AC030;
xa_set_error: ;AN030; error occurred on XA
invoke set_ext_error_msg ;AN030; get extended error
ext_err_set: ;AN030;
mov string_ptr_2,offset trangroup:destbuf ;AN000; get address of failed string
mov Extend_buf_sub,one_subst ;AN030; put number of subst in control block
COPERRJ2: ;AN030;
jmp COPERR ;AN030; go issue message
dest_open_okay: ;AC030
mov [DESTHAND],ax ; Save handle
mov [CFLAG],1 ; Destination now exists
mov bx,ax
mov cx,bx ;AN030; get handle into CX
invoke set_file_code_page ;AN030; set the code page for the target
jc ext_err_set ;AN030; if no error, continue
mov [concat_xa],0 ;AN000; set first file flag off
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
mov [DESTISDEV],dl ; Set dest info
test dl,devid_ISDEV
jz exists ;AC030; Dest a device
mov al,BYTE PTR [DESTSWITCH]
AND AL,SwitchA+SwitchB
JNZ TESTBOTH
MOV AL,[ASCII] ; Neither set, use current setting
OR AL,[BINARY]
JZ EXSETA ; Neither set, default to ASCII
TESTBOTH:
JPE EXISTS ; Both are set, ignore
test AL,SwitchB
jz EXISTS ; Leave in cooked mode
mov ax,(IOCTL SHL 8) OR 1
xor dh,dh
or dl,devid_RAW
mov [DESTISDEV],dl ; New value
INT int_command ; Set device to RAW mode
jmp short EXISTS
COPERRJ:
jmp SHORT COPERR
EXSETA:
;
; What we read in may have been in binary mode, flag zapped write OK
;
mov [ASCII],SwitchA ; Set ASCII mode
or [INEXACT],SwitchA ; ASCII -> INEXACT
EXISTS:
cmp [NOWRITE],0
jnz NOCHECKING ; If nowrite don't bother with name check
cmp plus_comma,1 ;g don't check if just doing +,,
jz NOCHECKING ;g
invoke COMPNAME ; Source and dest. the same?
JNZ NOCHECKING ; If not, go ahead
CMP [SRCISDEV],0
JNZ NOCHECKING ; Same name on device OK
;
; At this point we know in append (would have gotten overwrite error on first
; destination create otherwise), and user trying to specify destination which
; has been scribbled already (if dest had been named first, NOWRITE would
; be set).
;
MOV DX,OFFSET TRANGROUP:LOSTERR_ptr ; Tell him he's not going to get it
invoke std_Eprintf ;AC022;
MOV [NXTADD],0 ; Set return
INC [TERMREAD] ; Tell Read to give up
RET60:
return
NOCHECKING:
mov bx,[DESTHAND] ; Get handle
XOR CX,CX
XCHG CX,[NXTADD]
JCXZ RET60 ; If Nothing to write, forget it
INC [WRITTEN] ; Flag that we wrote something
CMP [NOWRITE],0 ; If NOWRITE set, just seek CX bytes
JNZ SEEKEND
XOR DX,DX
PUSH DS
MOV DS,[TPA]
ASSUME DS:NOTHING
MOV AH,WRITE
INT int_command
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE_ptr
JC xa_set_error_Jmp ;AC022; Failure
sub cx,ax
retz ; Wrote all supposed to
test [DESTISDEV],devid_ISDEV
jz COPERR ; Is a file, error
test [DESTISDEV],devid_RAW
jnz DEVWRTERR ; Is a raw device, error
cmp [INEXACT],0
retnz ; INEXACT so OK
dec cx
retz ; Wrote one byte less (the ^Z)
DEVWRTERR:
MOV DX,OFFSET TRANGROUP:DEVWMES_ptr
PUBLIC COPERR
COPERR:
INVOKE std_Eprintf ;AC022;
COPERRP:
inc [DESTCLOSED]
cmp [CFLAG],0
jz ENDCOPYJ ; Never actually got it open
MOV bx,[DESTHAND]
CMP BX,0
JLE NoClose
MOV AH,CLOSE ; Close the file
INT int_command
NoClose:
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [CFLAG],0
ENDCOPYJ:
JMP ENDCOPY
XA_SET_ERROR_JMP: ;AN022; Go set up error message
jmp xa_set_error ;AN022;
SEEKEND:
xor dx,dx ; Zero high half of offset
xchg dx,cx ; cx:dx is seek location
mov ax,(LSEEK SHL 8) OR 1
INT int_command ; Seek ahead in the file
cmp [RDEOF],0
retz
;
; If a ^Z has been read we must set the file size to the current
; file pointer location
;
MOV AH,WRITE
INT int_command ; CX is zero, truncates file
jc xa_set_error_Jmp ;AC022; Failure
return
TRANCODE ENDS
END


View File

@@ -0,0 +1,450 @@
page 80,132
; SCCSID = @(#)copypr2.asm 1.1 85/05/14
; SCCSID = @(#)copypr2.asm 1.1 85/05/14
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN FulDir_ptr:word ;AN052;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN ASCII:BYTE
EXTRN BINARY:BYTE
EXTRN CONCAT:BYTE
EXTRN DESTBUF:BYTE
EXTRN DESTFCB:BYTE
EXTRN DESTINFO:BYTE
EXTRN DESTISDIR:BYTE
EXTRN DESTTAIL:WORD
EXTRN DESTVARS:BYTE
EXTRN DIRBUF:BYTE
EXTRN DIRCHAR:BYTE
EXTRN FIRSTDEST:BYTE
EXTRN INEXACT:BYTE
EXTRN MELCOPY:BYTE
EXTRN NXTADD:WORD
EXTRN PLUS:BYTE
EXTRN SDIRBUF:BYTE
EXTRN SRCINFO:BYTE
EXTRN srcxname:byte
EXTRN TPA:WORD
EXTRN trgxname:byte
EXTRN USERDIR1:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
EXTRN BADPATH_ERR:NEAR ;AN022;
EXTRN COPERR:NEAR ;AN052;
EXTRN EXTEND_SETUP:NEAR ;AN022;
PUBLIC BUILDPATH
PUBLIC SETSTARS
PUBLIC SETASC
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SETASC:
;
; Given switch vector in AX,
; Set ASCII switch if A is set
; Clear ASCII switch if B is set
; BINARY set if B specified
; Leave ASCII unchanged if neither or both are set
; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
;
AND AL,SwitchA+SwitchB
JPE LOADSW ; PE means both or neither are set
PUSH AX
AND AL,SwitchB
MOV [BINARY],AL
POP AX
AND AL,SwitchA
MOV [ASCII],AL
OR [INEXACT],AL
LOADSW:
MOV AL,[ASCII]
OR AL,AL
return
public builddest
BUILDDEST:
cmp [DESTISDIR],-1
jnz KNOWABOUTDEST ; Already done the figuring
MOV DI,OFFSET TRANGROUP:USERDIR1
mov bp,offset trangroup:DESTVARS
call BUILDPATH
invoke RESTUDIR1
; Now know all about the destination
KNOWABOUTDEST:
xor al,al
xchg al,[FIRSTDEST]
or al,al
jnz FIRSTDST
jmp NOTFIRSTDEST
FIRSTDST:
mov si,[DESTTAIL] ; Create an FCB of the original DEST
mov di,offset trangroup:DESTFCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
CMP BYTE PTR [SI],0
JZ GoodParse
;AD052; MOV BYTE PTR [DI+1],"|" ; must be illegal file name character
mov dx,offset trangroup:fuldir_ptr ;AN052; Issue "File creation error"
jmp coperr ;AN052;
GoodParse:
mov ax,word ptr [DESTBUF] ; Get drive
cmp ah,':'
jz DRVSPEC4
mov al,'@'
DRVSPEC4:
MOV CL,[ASCII] ; Save current ASCII setting
or al,20h
sub al,60h
mov [DESTFCB],al
mov al,[DESTINFO]
mov ah,[SRCINFO]
and ax,0202H
or al,al
jz NOTMELCOPY
cmp al,ah
jnz NOTMELCOPY
cmp [PLUS],0
jz NOTMELCOPY
inc [MELCOPY] ; ambig source, ambig dest, and pluses
xor al,al
jmp short SETCONC
NOTMELCOPY:
xor al,2 ; al=2 if unambig dest, =0 if ambig dest
and al,ah
shr al,1 ; al=1 if unambig dest AND ambig sorce
; Implies concatenation
SETCONC:
or al,[PLUS] ; al=1 if concat
mov [CONCAT],al
shl al,1
shl al,1
mov [INEXACT],al ; Concat -> inexact copy
cmp [BINARY],0
jnz NOTFIRSTDEST ; Binary explicitly given, all OK
mov [ASCII],al ; Concat -> ASCII
or cl,cl
jnz NOTFIRSTDEST ; ASCII flag set before, DATA read correctly
or al,al
JZ NOTFIRSTDEST ; ASCII flag did not change states
;
; At this point there may already be binary read data in the read buffer.
; We need to find the first ^Z (if there is one) and trim the amount
; of data in the buffer correctly.
;
MOV CX,[NXTADD]
JCXZ NOTFIRSTDEST ; No data, everything OK
MOV AL,1AH
PUSH ES
XOR DI,DI
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ NOTFIRSTDEST ; No ^Z in buffer, everything OK
DEC DI ; Point at ^Z
MOV [NXTADD],DI ; New buffer
NOTFIRSTDEST:
mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars
cmp [CONCAT],0
jz GOTCHRSRC ; Not a concat
mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars
GOTCHRSRC:
mov si,offset trangroup:DESTFCB+1 ; Original dest name
mov di,[DESTTAIL] ; Where to put result
public buildname
BUILDNAME:
mov cx,8
BUILDMAIN:
lodsb
cmp al,'?'
jnz NOTAMBIG
mov al,byte ptr [BX]
NOTAMBIG:
cmp al,' '
jz NOSTORE
stosb
NOSTORE:
inc bx
loop BUILDMAIN
mov cl,3
mov al,' '
cmp byte ptr [SI],al
jz ENDDEST ; No extension
mov al,dot_chr
stosb
BUILDEXT:
lodsb
cmp al,'?'
jnz NOTAMBIGE
mov al,byte ptr [BX]
NOTAMBIGE:
cmp al,' '
jz NOSTOREE
stosb
NOSTOREE:
inc bx
loop BUILDEXT
ENDDEST:
xor al,al
stosb ; NUL terminate
return
BUILDPATH:
test [BP.INFO],2
jnz NOTPFILE ; If ambig don't bother with open
mov dx,bp
add dx,BUF ; Set DX to spec
push di ;AN000;
MOV AX,EXTOPEN SHL 8 ;AC000; open the file
mov bx,read_open_mode ;AN000; get open mode for COPY
xor cx,cx ;AN000; no special files
mov si,dx ;AN030; get file name offset
mov di,-1 ;AN030; no parm list
mov dx,read_open_flag ;AN000; set up open flags
INT int_command
pop di ;AN000;
jnc pure_file ;AN022; is pure file
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_file_not_found ;AN022; if file not found - okay
jz notpfile ;AN022;
cmp ax,error_path_not_found ;AN022; if path not found - okay
jz notpfile ;AN022;
cmp ax,error_access_denied ;AN022; if access denied - okay
jz notpfile ;AN022;
jmp extend_setup ;AN022; exit with error
pure_file:
mov bx,ax ; Is pure file
mov ax,IOCTL SHL 8
INT int_command
mov ah,CLOSE
INT int_command
test dl,devid_ISDEV
jnz ISADEV ; If device, done
test [BP.INFO],4
jz ISSIMPFILE ; If no path seps, done
NOTPFILE:
mov dx,word ptr [BP.BUF]
cmp dl,0 ;AN034; If no drive specified, get
jz set_drive_spec ;AN034; default drive dir
cmp dh,':'
jz DRVSPEC5
set_drive_spec: ;AN034;
mov dl,'@'
DRVSPEC5:
or dl,20h
sub dl,60h ; A = 1
invoke SAVUDIR1
jnc curdir_ok ;AN022; if error - exit
invoke get_ext_error_number ;AN022; get the extended error
jmp extend_setup ;AN022; exit with error
curdir_ok: ;AN022;
mov dx,bp
add dx,BUF ; Set DX for upcomming CHDIRs
mov bh,[BP.INFO]
and bh,6
cmp bh,6 ; Ambig and path ?
jnz CHECKAMB ; jmp if no
mov si,[BP.TTAIL]
mov bl,':'
cmp byte ptr [si-2],bl
jnz KNOWNOTSPEC
mov [BP.ISDIR],2 ; Know is d:/file
jmp short DOPCDJ
KNOWNOTSPEC:
mov [BP.ISDIR],1 ; Know is path/file
dec si ; Point to the /
DOPCDJ:
jmp DOPCD ;AC022; need long jump
CHECKAMB:
cmp bh,2
jnz CHECKCD
ISSIMPFILE:
ISADEV:
mov [BP.ISDIR],0 ; Know is file since ambig but no path
return
CHECKCD:
invoke SETREST1
mov ah,CHDIR
INT int_command
jc NOTPDIR
mov di,dx
xor ax,ax
mov cx,ax
dec cx
Kloop: ;AN000; 3/3/KK
MOV AL,ES:[DI] ;AN000; 3/3/KK
INC DI ;AN000; 3/3/KK
OR AL,AL ;AN000; 3/3/KK
JZ Done ;AN000; 3/3/KK
xor ah,ah ;AN000; 3/3/KK
invoke Testkanj ;AN000; 3/3/KK
JZ Kloop ;AN000; 3/3/KK
INC DI ;AN000; 3/3/KK
INC AH ;AN000; 3/3/KK
jmp Kloop ;AN000; 3/3/KK
Done: ;AN000; 3/3/KK
dec di
mov al,[DIRCHAR]
mov [bp.ISDIR],2 ; assume d:/file
OR AH, AH ;AN000; 3/3/KK
JNZ Store_pchar ;AN000; 3/3/KK this is the trailing byte of ECS code
cmp al,[di-1]
jz GOTSRCSLSH
Store_pchar: ;AN000; 3/3/KK
stosb
mov [bp.ISDIR],1 ; know path/file
GOTSRCSLSH:
or [bp.INFO],6
call SETSTARS
return
NOTPDIR:
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_path_not_found ;AN022; if path not found - okay
jz notpdir_try ;AN022;
cmp ax,error_access_denied ;AN022; if access denied - okay
jnz extend_setupj ;AN022; otherwise - exit error
notpdir_try: ;AN022;
mov [bp.ISDIR],0 ; assume pure file
mov bh,[bp.INFO]
test bh,4
retz ; Know pure file, no path seps
mov [bp.ISDIR],2 ; assume d:/file
mov si,[bp.TTAIL]
cmp byte ptr [si],0
jz BADCDERRJ2 ; Trailing '/'
mov bl,dot_chr
cmp byte ptr [si],bl
jz BADCDERRJ2 ; If . or .. pure cd should have worked
mov bl,':'
cmp byte ptr [si-2],bl
jz DOPCD ; Know d:/file
mov [bp.ISDIR],1 ; Know path/file
dec si ; Point at last '/'
DOPCD:
xor bl,bl
xchg bl,[SI] ; Stick in a NUL
invoke SETREST1
CMP DX,SI ;AN000; 3/3/KK
JAE LookBack ;AN000; 3/3/KK
PUSH SI ;AN000; 3/3/KK
PUSH CX ;AN000; 3/3/KK
MOV CX,SI ;AN000; 3/3/KK
MOV SI,DX ;AN000; 3/3/KK
Kloop2: ;AN000; 3/3/KK
LODSB ;AN000; 3/3/KK
invoke TestKanj ;AN000; 3/3/KK
jz NotKanj4 ;AN000; 3/3/KK
LODSB ;AN000; 3/3/KK
CMP SI,CX ;AN000; 3/3/KK
JB Kloop2 ;AN000; 3/3/KK
POP CX ;AN000; 3/3/KK
POP SI ;AN000; 3/3/KK
JMP SHORT DoCdr ;AN000; 3/3/KK Last char is ECS code, don't check for
; trailing path sep
NotKanj4: ;AN000; 3/3/KK
CMP SI,CX ;AN000; 3/3/KK
JB Kloop2 ;AN000; 3/3/KK
POP CX ;AN000; 3/3/KK
POP SI ;AN000; 3/3/KK
LookBack: ;AN000; 3/3/KK
CMP BL,[SI-1] ; if double slash, then complain.
JZ BadCDErrJ2
DoCdr: ;AN000; 3/3/KK
mov ah,CHDIR
INT int_command
xchg bl,[SI]
retnc
invoke get_ext_error_number ;AN022; get the extended error
EXTEND_SETUPJ: ;AN022;
JMP EXTEND_SETUP ;AN022; go issue the error message
BADCDERRJ2:
jmp badpath_err ;AC022; go issue path not found message
SETSTARS:
mov [bp.TTAIL],DI
add [bp.SIZ],12
mov ax,dot_qmark
mov cx,8
rep stosb
xchg al,ah
stosb
xchg al,ah
mov cl,3
rep stosb
xor al,al
stosb
return
PUBLIC CompName
COMPNAME:
mov si,offset trangroup:DESTBUF ;g do name translate of target
mov di,offset trangroup:TRGXNAME ;g save for name comparison
mov ah,xnametrans ;g
int int_command ;g
MOV si,offset trangroup:SRCXNAME ;g get name translate of source
MOV di,offset trangroup:TRGXNAME ;g get name translate of target
invoke STRCOMP
return
TRANCODE ENDS
END


View File

@@ -0,0 +1,417 @@
page 80,132
; SCCSID = @(#)cparse.asm 1.1 85/05/14
; SCCSID = @(#)cparse.asm 1.1 85/05/14
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADCD_PTR:WORD ;AC022;
EXTRN BADCPMES_ptr:word ;AC000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN comma:byte
EXTRN cpyflag:byte
EXTRN CURDRV:BYTE
EXTRN ELCNT:BYTE
EXTRN ELPOS:BYTE
EXTRN EXPAND_STAR:BYTE
EXTRN SKPDEL:BYTE
EXTRN STARTEL:WORD
EXTRN SWITCHAR:BYTE
EXTRN switch_list:byte
EXTRN TPA:WORD
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
EXTRN CERROR:NEAR
PUBLIC BADCDERR ;AC022;
PUBLIC CPARSE
SWCOUNT EQU 5 ; Must agree with length of switch_list
;-----------------------------------------------------------------------;
; ENTRY: ;
; DS:SI Points input buffer ;
; ES:DI Points to the token buffer ;
; BL Special delimiter for this call ;
; Always checked last ;
; set it to space if there is no special delimiter ;
; EXIT: ;
; DS:SI Points to next char in the input buffer ;
; ES:DI Points to the token buffer ;
; [STARTEL] Points to start of last element of path in token ;
; points to a NUL for no element strings 'd:' 'd:/' ;
; CX Character count ;
; BH Condition Code ;
; Bit 1H of BH set if switch character ;
; Token buffer contains char after ;
; switch character ;
; BP has switch bits set (ORing only) ;
; Bit 2H of BH set if ? or * in token ;
; if * found element ? filled ;
; Bit 4H of BH set if path sep in token ;
; Bit 80H of BH set if the special delimiter ;
; was skipped at the start of this token ;
; Token buffer always starts d: for non switch tokens ;
; CARRY SET ;
; if CR on input ;
; token buffer not altered ;
; ;
; DOES NOT RETURN ON BAD PATH, OR TRAILING SWITCH CHAR ERROR ;
; MODIFIES: ;
; CX, SI, AX, BH, DX and the Carry Flag ; ;
; ;
; -----------------------------------------------------------------------;
;---------------
; Modifications to cparse: recognition of right and left parentheses
; as integral tokens, and removal of automatic upper-case conversion code.
;
; Both modifications were installed in the course of adding a coherent
; command-line parser to COMMAND.COM which builds a UNIX-style argv[]/argc
; structure for command-line arguments. This parser relies on cparse to
; recognize individual tokens.
;
; To process for-loops correctly, parentheses must therefore be
; recognized as tokens. The upper-case conversion code was removed so
; that commands (such as for and echo) would be able to use the "original"
; text of the command line.
;
; Note also the modification to prevent the automatic conversion of colons
; into spaces WITHIN THE SOURCE TEXT!
;
; Also note that BP is also clobbered if cparse recognizes any switches
; on the command line.
;
; Alan L, OS/MSDOS 14 August 1983
;---------------
CPARSE:
ASSUME DS:TRANGROUP,ES:TRANGROUP
xor ax,ax
mov [STARTEL],DI ; No path element (Is DI correct?)
mov [ELPOS],al ; Start in 8 char prefix
mov [SKPDEL],al ; No skip delimiter yet
mov bh,al ; Init nothing
pushf ; save flags
push di ; save the token buffer addrss
xor cx,cx ; no chars in token buffer
mov comma,cl ;g reset comma flag
moredelim:
LODSB
INVOKE DELIM
JNZ SCANCDONE
CMP AL,' '
JZ moredelim
CMP AL,9
JZ moredelim
xchg al,[SKPDEL]
or al,al
jz moredelim ; One non space/tab delimiter allowed
test bh,080h ;g has a special char been found?
jz no_comma ;g no - just exit
mov comma,1 ;g set comma flag
no_comma:
JMP x_done ; Nul argument
SCANCDONE:
;;;; IF NOT KANJI 3/3/KK
;---------------
; Mod to avoid upper-case conversion.
; cmp cpyflag,1 3/3/KK
; jnz cpcont1 3/3/KK
; invoke UPCONV 3/3/KK
cpcont1:
;---------------
;;;; ENDIF 3/3/KK
cmp al,bl ; Special delimiter?
jnz nospec
or bh,80H
jmp short moredelim
nospec:
cmp al,0DH ; a CR?
jne ncperror
jmp cperror
ncperror:
cmp al,[SWITCHAR] ; is the char the switch char?
jne na_switch ; yes, process...
jmp a_switch
na_switch:
mov dl,':'
cmp byte ptr [si],dl
jne anum_chard ; Drive not specified
;;;; IF KANJI 3/3/KK
;---------------
; Mod to avoid upper-case conversion.
cmp cpyflag,1
jnz cpcont2
invoke UPCONV
cpcont2:
;---------------
;;;; ENDIF 3/3/KK
call move_char
lodsb ; Get the ':'
call move_char
mov [STARTEL],di
mov [ELCNT],0
jmp anum_test
anum_chard:
mov [STARTEL],di
mov [ELCNT],0 ; Store of this char sets it to one
cmp cpyflag,1 ; Was CPARSE called from COPY?
jnz anum_char ; No, don't add drive spec.
invoke PATHCHRCMP ; Starts with a pathchar?
jnz anum_char ; no
push ax
mov al,[CURDRV] ; Insert drive spec
add al,capital_A
call move_char
mov al,':'
call move_char
pop ax
mov [STARTEL],di
mov [ELCNT],0
anum_char:
;;;; IF KANJI 3/3/KK
invoke TESTKANJ
jz NOTKANJ ;AC048;
call move_char
lodsb
jmp short notspecial
NOTKANJ: ;AN048; If not kanji
cmp cpyflag,1 ;AN048; and if we're in COPY
jnz testdot ;AN048;
invoke upconv ;AN048; upper case the char
TESTDOT:
;;;; ENDIF 3/3/KK
cmp al,dot_chr
jnz testquest
inc [ELPOS] ; flag in extension
mov [ELCNT],0FFH ; Store of the '.' resets it to 0
testquest:
cmp al,'?'
jnz testsplat
or bh,2
testsplat:
cmp al,star
jnz testpath
or bh,2
cmp byte ptr [expand_star],0
jnz expand_filename
jmp SHORT testpath
badperr2j:
jmp badperr2
expand_filename:
mov ah,7
cmp [ELPOS],0
jz gotelcnt
mov ah,2
gotelcnt:
mov al,'?'
sub ah,[ELCNT]
jc badperr2j
xchg ah,cl
jcxz testpathx
qmove:
xchg ah,cl
call move_char
xchg ah,cl
loop qmove
testpathx:
xchg ah,cl
testpath:
invoke PATHCHRCMP
jnz notspecial
or bh,4
cmp byte ptr [expand_star],0
jz no_err_check
test bh,2 ; If just hit a '/', cannot have ? or * yet
jnz badperr
no_err_check:
mov [STARTEL],di ; New element
INC [STARTEL] ; Point to char after /
mov [ELCNT],0FFH ; Store of '/' sets it to 0
mov [ELPOS],0
notspecial:
call move_char ; just an alphanum string
anum_test:
lodsb
;;;; IF NOT KANJI 3/3/KK
;---------------
; Mod to avoid upper-case conversion.
; cmp cpyflag,1 3/3/KK
; jnz cpcont3 3/3/KK
; invoke UPCONV 3/3/KK
cpcont3:
;---------------
;;;; ENDIF 3/3/KK
INVOKE DELIM
je x_done
cmp al,0DH
je x_done
cmp al,[SWITCHAR]
je x_done
cmp al,bl
je x_done
cmp al,':' ; ':' allowed as trailer because
; of devices
;;;; IF KANJI 3/3/KK
je FOO15
jmp anum_char
FOO15:
;;; ELSE 3/3/KK
;;; jne anum_charj 3/3/KK
;;; ENDIF 3/3/KK
;---------------
; Modification made for parseline.
; Why would it be necessary to change colons to spaces? In this
; case, EVERY colon is changed to a space; e.g., 'f:' yields 'f ',
; but so does 'echo foo:bar' yield 'echo foo bar'.
;---------------
cmp cpyflag,2 ; Is CPARSE parsing the 1st token from
; from PARSELINE?
jnz cpcont4 ; No, continue
call move_char ; Yes, save the ':' and go get another
jmp anum_test ; character.
cpcont4:
inc si ;Skip the ':'
jmp short x_done
anum_charj:
jmp anum_char
badperr2:
mov dx,offset trangroup:BADCPMES_ptr
jmp CERROR
badperr:
BADCDERR: ;AC022; Issue "Invalid Directory"
MOV DX,OFFSET TRANGROUP:BADCD_ptr ;AC022; message
JMP CERROR ;AC022;
cperror:
dec si ; adjust the pointer
pop di ; retrive token buffer address
popf ; restore flags
stc ; set the carry bit
return
x_done:
dec si ; adjust for next round
;---------------
; Mod to recognize right and left parens as integral tokens.
x_done2:
;---------------
jmp short out_token
a_switch:
OR BH,1 ; Indicate switch
OR BP,fSwitch
INVOKE SCANOFF
INC SI
invoke testkanj ;AN057; See if DBCS lead byte
jz a_switch_notkanj ;AN057; no - continue processing
call move_char ;AN057; DBCS - store first byte
lodsb ;AN057; get second byte
call move_char ;AN057; store second byte
or bp,fBadSwitch ;AN057; DBCS switch is invalid
jmp short out_token ;AN057; don't bother checking switch
a_switch_notkanj: ;AN057;
cmp al,0DH
jne Store_swt
mov al,0
stosb ; null at the end
OR BP,fBadSwitch
jmp cperror ; Trailing switch character error
; BP = fSwitch but no switch
; bit is set (unknown switch)
Store_swt:
call move_char ; store the character
;
;---------------
; This upconv call must stay. It is used to identify copy-switches
; on the command line, and won't store anything into the output buffer.
invoke UPCONV
;---------------
;
PUSH ES
PUSH DI
PUSH CX
PUSH CS
POP ES
ASSUME ES:TRANGROUP
MOV DI,OFFSET TRANGROUP:switch_list
MOV CX,SWCOUNT
OR BP,fBadSwitch
REPNE SCASB
JNZ out_tokenp
AND BP,NOT fBadSwitch
MOV AX,1
SHL AX,CL
OR BP,AX
out_tokenp:
POP CX
POP DI
POP ES
ASSUME ES:NOTHING
out_token:
mov al,0
stosb ; null at the end
pop di ; restore token buffer pointer
popf
clc ; clear carry flag
return
move_char:
stosb ; store char in token buffer
inc cx ; increment char count
inc [ELCNT] ; increment element count for * substi
return
TRANCODE ENDS
END

View File

@@ -0,0 +1,28 @@
; SCCSID = @(#)envdata.asm 1.1 85/05/14
; SCCSID = @(#)envdata.asm 1.1 85/05/14
; This file is included by command.asm and is used as the default command
; environment.
ENVARENA SEGMENT PUBLIC PARA
ORG 0
DB 10h DUP (?) ;Pad for memory allocation addr mark
ENVARENA ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
PUBLIC ECOMSPEC,ENVIREND,PATHSTRING
ORG 0
PATHSTRING DB "PATH="
USERPATH LABEL BYTE
DB 0 ; Null path
DB "COMSPEC="
ECOMSPEC DB "\COMMAND.COM" ;AC062
DB 134 DUP (0)
ENVIREND LABEL BYTE
ENVIRONSIZ EQU $-PATHSTRING
ENVIRONSIZ2 EQU $-ECOMSPEC
ENVIRONMENT ENDS

View File

@@ -0,0 +1,19 @@
; SCCSID = @(#)fordata.asm 1.1 85/05/14
; SCCSID = @(#)fordata.asm 1.1 85/05/14
; Data structure definitions included by tfor.asm
for_info STRUC
for_args DB (SIZE arg_unit) DUP (?) ; argv[] structure
FOR_COM_START DB (?) ; beginning of <command>
FOR_EXPAND DW (?) ; * or ? item in <list>?
FOR_MINARG DW (?) ; beginning of <list>
FOR_MAXARG DW (?) ; end of <list>
forbuf DW 64 DUP (?) ; temporary buffer
fordma DW 64 DUP (?) ; FindFirst/Next buffer
FOR_VAR DB (?) ; loop control variable
for_info ENDS
; empty segment done for bogus addressing
for_segment segment
f LABEL BYTE
for_segment ends

View File

@@ -0,0 +1,18 @@
; SCCSID = @(#)ifequ.asm 1.1 85/05/14
; SCCSID = @(#)ifequ.asm 1.1 85/05/14
;*************************************
; COMMAND EQUs which are switch dependant
IF1
IF IBM
%OUT DBCS Enabled IBM version
ELSE
%OUT Normal version
ENDIF
;; IF KANJI 3/3/KK
;; %OUT Kanji version 3/3/KK
;; ENDIF 3/3/KK
ENDIF


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
page 80,132
; SCCSID = @(#)iparse.asm 4.1 87/04/28
; SCCSID = @(#)iparse.asm 4.1 87/04/28
TITLE COMMAND interface to SYSPARSE
.xlist
.xcref
INCLUDE comseg.asm ;AN000;
.list
.cref
INIT SEGMENT PUBLIC PARA ;AN000;
ASSUME CS:RESGROUP,DS:RESGROUP,ES:NOTHING,SS:NOTHING ;AN000;
;AD054; public SYSPARSE ;AN000;
DateSW equ 0 ;AN000; do not Check date format
TimeSW equ 0 ;AN000; do not Check time format
CmpxSW equ 0 ;AN000; do not check complex list
KeySW equ 0 ;AN025; do not support keywords
Val2SW equ 0 ;AN025; do not Support value definition 2
Val3SW equ 0 ;AN000; do not Support value definition 3
QusSW equ 0 ;AN025; do not include quoted string
DrvSW equ 0 ;AN025; do not include drive only
.xlist
.xcref
;AD054; INCLUDE parse.asm ;AN000;
.list
.cref
INIT ends ;AN000;
end ;AN000;


View File

@@ -0,0 +1,134 @@
#************************** makefile for cmd\append ***************************
msg =..\..\messages
dos =..\..\dos
inc =..\..\inc
hinc =..\..\h
#
####################### dependencies begin here. #########################
#
all: command.com
$(inc)\dossym.inc: $(inc)\dosmac.inc $(inc)\bpb.inc \
$(inc)\buffer.inc $(inc)\sysvar.inc $(inc)\vector.inc \
$(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \
$(inc)\cpmfcb.inc $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \
$(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc $(inc)\mi.inc \
$(inc)\filemode.inc $(inc)\error.inc $(inc)\syscall.inc
echo "touch $(inc)\dossym.inc"
command.ctl: command.skl $(msg)\$(COUNTRY).msg makefile
command1.obj: command1.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \
envdata.asm
command2.obj: command2.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \
envdata.asm
copy.obj: copy.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm
copypr1.obj: copypr1.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm
copypr2.obj: copypr2.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm
cparse.obj: cparse.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm
init.obj: init.asm $(inc)\dossym.inc $(inc)\devsym.inc \
comsw.asm comseg.asm comequ.asm resmsg.equ $(inc)\sysmsg.inc \
$(inc)\msgserv.asm command.ctl
iparse.obj: iparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc
parse2.obj: parse2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \
comseg.asm comequ.asm
path1.obj: path1.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \
comseg.asm comequ.asm
path2.obj: path2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \
comseg.asm comequ.asm
rdata.obj: rdata.asm comsw.asm comseg.asm $(inc)\sysmsg.inc \
$(inc)\msgserv.asm command.cla command.cl3 command.cl4 \
command.cld command.clc command.cle command.ctl
rucode.obj: rucode.asm $(inc)\dossym.inc $(inc)\devsym.inc \
$(inc)\doscntry.inc resmsg.equ $(inc)\sysmsg.inc \
$(inc)\msgserv.asm comsw.asm comseg.asm comequ.asm command.ctl
tbatch.obj: tbatch.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tbatch2.obj: tbatch2.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tcmd1a.obj: tcmd1a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tcmd1b.obj: tcmd1b.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm $(inc)\ea.inc
tcmd2a.obj: tcmd2a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tcmd2b.obj: tcmd2b.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tcode.obj: tcode.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm \
$(inc)\mshalo.asm
tdata.obj: tdata.asm comsw.asm comseg.asm $(inc)\curdir.inc \
$(inc)\error.inc ifequ.asm comequ.asm $(inc)\sysmsg.inc \
$(inc)\msgserv.asm tranmsg.asm command.clf command.cl1 command.cl2 \
command.ctl $(inc)\ea.inc
tenv.obj: tenv.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \
comseg.asm comequ.asm ifequ.asm $(inc)\doscntry.inc
tenv2.obj: tenv2.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \
comseg.asm comequ.asm ifequ.asm
tfor.obj: tfor.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \
comseg.asm comequ.asm ifequ.asm fordata.asm
tmisc1.obj: tmisc1.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tmisc2.obj: tmisc2.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tparse.obj: tparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc
tpipe.obj: tpipe.asm comsw.asm $(inc)\dossym.inc \
$(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm
tprintf.obj: tprintf.asm comsw.asm $(inc)\dosmac.inc \
comseg.asm comequ.asm $(inc)\sysmsg.inc $(inc)\msgserv.asm \
command.ctl
tspc.obj: tspc.asm comsw.asm $(inc)\dossym.inc comequ.asm \
ifequ.asm comseg.asm $(inc)\ea.inc
tucode.obj: tucode.asm $(inc)\dosmac.inc $(inc)\dossym.inc \
comsw.asm comseg.asm comequ.asm ifequ.asm
uinit.obj: uinit.asm comsw.asm comseg.asm ifequ.asm command.clb \
$(inc)\sysmsg.inc $(inc)\msgserv.asm command.ctl
command.com: command1.obj command2.obj rucode.obj rdata.obj init.obj iparse.obj \
uinit.obj tcode.obj tbatch.obj tbatch2.obj tfor.obj tcmd1a.obj tcmd1b.obj \
tcmd2a.obj tcmd2b.obj tenv.obj tenv2.obj tmisc1.obj tmisc2.obj tpipe.obj \
parse2.obj path1.obj path2.obj tucode.obj copy.obj copypr1.obj copypr2.obj \
cparse.obj tparse.obj tprintf.obj tdata.obj tspc.obj
link @command.lnk
exe2bin command.exe command.com
del command.exe

View File

@@ -0,0 +1,422 @@
page 80,132
; SCCSID = @(#)parse.asm 1.1 85/05/14
; SCCSID = @(#)parse.asm 1.1 85/05/14
.sall
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
include comsw.asm
include comseg.asm
include comequ.asm
.list
.cref
break <Parse.Asm>
;----------------------------------------------------------------------------
; PARSE.ASM contains the routines to perform command line parsing.
; Parse and Path share a buffer and argv[] definitions.
; Invoking <Parseline> maps the unparsed command line in COMBUF into an
; array of pointers to the parsed tokens. The resulting array, argv[],
; also contains extra information provided by cparse about each token
; <Parseline> should be executed prior to <Path_Search>
;
; Alan L, OS/MSDOS August 15, 1983
;
;
; ENTRY:
; <Parseline>: command line in COMTAB.
; EXIT:
; <Parseline>: success flag, argcnt (number of args), argv[].
; NOTE(S):
; * <Argv_calc> handily turns an array index into an absolute pointer.
; The computation depends on the size of an argv[] element (arg_ele).
; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
; does not function as specified; see <Parseline> for more details.
; * <Parseline> now knows about the flags the internals of COMMAND.COM
; need to know about. This extra information is stored in a switch_flag
; word with each command-line argument; the switches themselves will not
; appear in the resulting arg structure.
; * With the exception of CARRY, flags are generally preserved across calls.
;---------------
; CONSTANTS:
;---------------
DEBUGx equ FALSE ; prints out debug info
;---------------
; DATA:
;---------------
DATARES SEGMENT PUBLIC BYTE
EXTRN FORFLAG:BYTE
DATARES ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN combuf:byte
EXTRN cpyflag:byte
EXTRN expand_star:byte
EXTRN RESSEG:word
EXTRN STARTEL:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
PUBLIC argv_calc ; convert array index into address
PUBLIC parseline
assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
break <Parseline: Munch on the command line>
;----------------------------------------------------------------------------
; PARSELINE takes an MSDOS command line and maps it into a UNIX-style
; argv[argvcnt] array. The most important difference between this array and
; the tradition UNIX format is the extra cparse information included with
; each argument element.
;---------------
; ENTRY:
; (BL special delimiter for cparse -- not implemented)
;---------------
; EXIT:
; CF set if error
; AL error code (carry set). Note AH clobbered in any event.
; argv[] array of cparse flags and pointers to arguments
; argvcnt argument count
;---------------
; NOTE(S):
; * BL (special delimiter) is ignored, for now (set to space).
; * Parseflags record contains cparse flags, as follows:
; sw_flag -- was this arg a switch?
; wildcard -- whether or not it contained a * or ?
; path_sep -- maybe it was a pathname
; unused -- for future expansion
; special_delim -- was there an initial special delimiter?
; * argv[] and argvcnt are undefined if CF/AL indicates an error.
; * Relationship between input, cparse output, and comtail can be
; found in the following chart. Despite the claim of the cparse
; documentation that, "Token buffer always starts d: for non switch
; tokens", such is not the case (see column two, row two).
; Similarly, [STARTEL] is not null when the command line is one of
; the forms, "d:", "d:\", or "d:/". In fact, *STARTEL (i.e., what
; STARTEL addresses) will be null. This is clearly just a
; documentation error.
; * cparse also returns a switch code in BP for each switch it
; recognizes on the command line.
; * arglen for each token does NOT include the terminating null.
; * Finally, note that interesting constructions like 'foodir/*.exe'
; parse as three separate tokens, and the asterisk is NOT a wildcard.
; For example, 'for %i in (foodir/*.exe) do echo %i' will first
; echo 'foodir', then '*', then '.exe'. Using cparse for command-
; line parsing may result in slightly different behavior than
; previously observed with the old COMMAND.COM command-line parser.
;
; Input Cparse Command Line (80H)
; \alan\foo.bat c:\alan\foo.bat \alan\foo.bat
; alan\foo.bat alan\foo.bat alan\foo.bat
; foo.bat foo.bat foo.bat
; c:\alan\foo.bat c:\alan\foo.bat c:\alan\foo.bat
; c:alan\foo.bat c:alan\foo.bat c:alan\foo.bat
; c:foo.bat c:foo.bat c:foo.bat
;---------------
; CONSTANTS:
;---------------
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte
EXTRN argbufptr:word
EXTRN comptr:word
EXTRN last_arg:word
EXTRN tpbuf:byte
TRANSPACE ENDS
;---------------
parseline:
;---------------
push AX ; most of these are clobbered
push BX ; by cparse...
push CX
push DX
push DI
push SI
pushf
mov cpyflag,0 ; Turn "CPARSE called from COPY flag" off
mov [LAST_ARG], -1 ; last argument at which to accumulate
xor ax,ax
mov cx,SIZE arg_unit
mov di,offset trangroup:arg
rep stosb
mov argbufptr,offset trangroup:arg.argbuf
mov arg.argswinfo, 0 ; switch information, and info to date
mov arg.argvcnt, 0 ; initialize argvcnt/argv[]
mov SI, OFFSET TRANGROUP:combuf+2 ; prescan leaves cooked input in combuf
; This next section of code (up to pcont:) makes sure that si is set up for
; parsing. It should point at COMBUF if FORFLAG is set and arg.argforcombuf
; otherwise. This is done so that commands can get arg pointers into their
; original command line (or an exact copy of it) in arg_ocomptr.
; Arg.argforcombuf is used so that the for loop processor will always be able
; to get a hold of its original command line; even after COMBUF is blasted by
; the command to be repeated or the transient part of command has been
; reloaded.
push ds
mov ds,[RESSEG]
assume ds:resgroup
cmp FORFLAG,0
pop ds
assume ds:trangroup
jnz pcont
mov di,OFFSET TRANGROUP:arg.argforcombuf
xor ch,ch
mov cl,[COMBUF+1]
inc cl
rep movsb
mov si,OFFSET TRANGROUP:arg.argforcombuf
pcont:
mov DI, OFFSET TRANGROUP:tpbuf ; destination is temporary token buffer
mov BL, ' ' ; no special delimiter, for now
parseloop:
mov comptr,si ; save ptr into original command buffer
xor BP, BP ; switch information put here by cparse
mov byte ptr [expand_star],0 ; don't expand *'s to ?'s
invoke scanoff ; skip leading blanks...
invoke cparse ; byte off a token (args in SI, DI, BL)
jnc More_prse
or BP,BP ; Check for trailing switch character
jz parsedone
call newarg ; We hit CR but BP is non-zero. The
; typical cause of this is that a
; switch char IMMEDIATELY preceeds
; the CR. We have an argument, but it
; is sort of an error.
jmp short parsedone ; We're done (found the CR).
More_prse:
mov cpyflag,2 ; tell CPARSE that 1st token is done
call newarg ; add to argv array (CX has char count)
jnc parseloop ; was everything OK?
jmp short parse_error ; NO, it wasn't -- bug out (CF set)
parsedone: ; successful completion of parseline
popf
clc
jmp short parse_exit
parse_error: ; error entry (er, exit) point
popf
stc
parse_exit: ; depend on not changing CF
pop SI
pop DI
pop DX
pop CX
pop BX
pop AX
ret
;---------------
; parseline ends
;----------------------------------------------------------------------------
break <NewArg>
;----------------------------------------------------------------------------
; NEWARG adds the supplied argstring and cparse data to arg.argv[].
; ENTRY:
; BH argflags
; CX character count in argstring
; DI pointer to argstring
; comptr ptr to starting loc of current token in original command
; [STARTEL] cparse's answer to where the last element starts
; EXIT:
; argbufptr points to next free section of argbuffer
; arg.argbuf contains null-terminated argument strings
; arg.argvcnt argument count
; arg.argv[] array of flags and pointers
; arg.arg_ocomptr ptr to starting loc of current token in original command
; CF set if error
; AL carry set: error code; otherwise, zero
;---------------
newarg:
;---------------
push BX
push CX
push DX ; one never knows, do one?
push DI
push SI
pushf
call arg_switch ; if it's a switch, record switch info
; LEAVE SWITCH ON COMMAND LINE!!
;;; jc newarg_done ; previous arg's switches -- and leave
cmp arg.argvcnt, ARGMAX ; check to ensure we've not
jge too_many_args ; exceeded array limits
mov DH, BH ; save argflags
mov BX, arg.argvcnt ; argv[argvcnt++] = arg data
inc arg.argvcnt
mov AX, OFFSET TRANGROUP:arg.argv
call argv_calc ; convert offset to pointer
mov [BX].argsw_word, 0 ; no switch information, yet...
mov [BX].arglen, CX ; argv[argvcnt].arglen = arg length
mov [BX].argflags, DH ; argv[argvcnt].argflags = cparse flags
mov SI, argbufptr
mov [BX].argpointer, SI ; argv[argvcnt].argpointer = [argbufptr]
add SI, [STARTEL] ; save startel from new location
sub SI, DI ; form pointer into argbuf
mov [BX].argstartel, SI ; argv[argvcnt].argstartel = new [STARTEL]
mov si,[comptr]
mov [BX].arg_ocomptr,si ; arg_ocomptr=ptr into original com line
mov SI, DI ; now save argstring in argbuffer
mov DI, argbufptr ; load the argbuf pointer and make
add DI, CX ; sure we're not about to run off
cmp DI, OFFSET TRANGROUP:arg.argbuf+ARGBLEN-1
jge buf_ovflow ; the end of the buffer (plus null byte)
sub DI, CX ; adjust the pointer
cld
rep movsb ; and save the string in argbuffer
mov AL, ANULL ; tack a null byte on the end
stosb
mov argbufptr, DI ; update argbufptr after copy
newarg_done:
popf
clc
jmp short newarg_exit
too_many_args:
mov AX, arg_cnt_error
jmp short newarg_error
buf_ovflow:
mov AX, arg_buf_ovflow
newarg_error:
popf
stc
newarg_exit:
pop SI
pop DI
pop DX
pop CX
pop BX
ret
;---------------
; NewArg ends
;----------------------------------------------------------------------------
break <Arg_Switch>
;----------------------------------------------------------------------------
; ARG_SWITCH decides if an argument might really be a switch. In the
; event that it is, and we can recognize
; ENTRY:
; As in <newarg>.
; EXIT:
; CF -- clear (wasn't a switch); set (was a switch)
; NOTE(S):
; * The mechanism mapping a switch into a bit-value depends entirely
; on the order of definition in the <switch_list> variable and the
; values chosen to define the bits in CMDT:COMEQU.ASM. Change either
; <switch_list> or the definitions in CMDT:COMEQU.ASM -- and rewrite
; this mechanism. This code taken from CMDT:TCODE.ASM.
; * The <switch_list> declared below is redundant to one declared in
; TDATA.ASM, and used in TCODE.ASM.
; * An ugly routine.
;---------------
; CONSTANTS:
;---------------
; Constants come from the definitions in CMDT:COMEQU.ASM.
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
extrn switch_list:byte
switch_count EQU $-switch_list
transpace ends
;---------------
Arg_Switch:
;---------------
push AX
push BX
push CX
push DI
pushf
test BH, MASK sw_flag ; is it a switch? (preserve flag word)
jz arg_no_switch0
cmp [LAST_ARG], -1 ; have we encountered any REAL args yet?
je arg_no_switch1 ; no, so leading switches don't matter
mov BX, [LAST_ARG] ; yes, add switch info to last REAL arg
mov AX, OFFSET TRANGROUP:arg.argv
call argv_calc
or [BX].argsw_word, BP
or arg.argswinfo, BP
arg_yes_switch: ; ah, sweet success...
popf
stc
jmp short arg_switch_exit
arg_no_switch0:
mov AX, arg.argvcnt ; future switches should then affect
mov [LAST_ARG], AX ; this argument
arg_no_switch1: ; wasn't a switch, or we're pretending
popf
clc
arg_switch_exit:
pop DI
pop CX
pop BX
pop AX
ret
;---------------
; Arg_Switch ends
;----------------------------------------------------------------------------
break <Argv_calc>
;----------------------------------------------------------------------------
; ARGV_CALC maps an array index into a byte-offset from the base of
; the supplied array. Method used for computing the address is:
; Array Index * Array Elt Size + Base Addr = Elt Addr
; ENTRY:
; AX -- base of array
; BX -- array index
; EXIT:
; BX -- byte offset
;---------------
argv_calc:
push ax ; Save base
mov al,bl ; al = array index
mov bl,SIZE argv_ele ; bl = size of an argv element
mul bl ; ax = base offset
pop bx ; Get base
add ax,bx ; Add in base offset
xchg ax,bx ; Restore ax and put byte offset in bx
ret
;---------------
; argv_calc ends
;----------------------------------------------------------------------------
trancode ends
end

View File

@@ -0,0 +1,507 @@
page 80,132
; SCCSID = @(#)path1.asm 1.1 85/05/14
; SCCSID = @(#)path1.asm 1.1 85/05/14
.sall
.xlist
.xcref
INCLUDE DOSSYM.INC
include comsw.asm
include comseg.asm
include comequ.asm
.list
.cref
break <Path.Asm>
;----------------------------------------------------------------------------
; PATH.ASM contains the routines to perform pathname incovation. Path and
; Parse share a temporary buffer and argv[] definitions. <Path_Search>,
; given a pathname, attempts to find a corresponding executable or batch
; file on disk. Directories specified in the user's search path will be
; searched for a matching file, if a match is not found in the current
; directory and if the pathname is actually only an MSDOS filename.
; <Path_Search> assumes that the parsed command name can be found in
; argv[0] -- in other words, <Parseline> should be executed prior to
; <Path_Search>. Alternatively, the command name and appropriate
; information could be placed in argv[0], or <Path_Search> could be
; (easily) modified to make no assumptions about where its input is found.
; Please find enclosed yet another important routine, <Save_Args>, which
; places the entire arg/argv[]/argbuf structure on a piece of newly
; allocated memory. This is handy for for-loop processing, and anything
; else that wants to save the whole shebang and then process other command
; lines.
;
; Alan L, OS/MSDOS August 15, 1983
;
; ENTRY:
; <Path_Search>: argv[0].
; <Save_Args>: bytes to allocate in addition to arg structure
; EXIT:
; <Path_Search>: success flag, best pathname match in EXECPATH.
; <Save_Args>: success flag, segment address of new memory
; NOTE(S):
; * <Argv_calc> handily turns an array index into an absolute pointer.
; The computation depends on the size of an argv[] element (arg_ele).
; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
; does not function as specified; see <Parseline> for more details.
; * <Parseline> now knows about the flags the internals of COMMAND.COM
; need to know about. This extra information is stored in a switch_flag
; word with each command-line argument; the switches themselves will not
; appear in the resulting arg structure.
; * With the exception of CARRY, flags are generally preserved across calls.
;---------------
; CONSTANTS:
;---------------
DEBUGx equ FALSE ; prints out debug info
;---------------
; DATA:
;---------------
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN baddrv_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte
EXTRN BADPMES_ptr:word
EXTRN curdrv:byte
EXTRN EXECPATH:byte
EXTRN search_best_buf:byte
EXTRN search_error:word
EXTRN string_ptr_2:word
EXTRN tpbuf:byte
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
break <Path_Search>
;------------------------------------------------------------------------------
; PATH_SEARCH tries to find the file it's given, somewhere. An initial value
; of *argv[0].argstartel == 0 implies that there is no command (empty line
; or 'd:' or 'd:/'). This check is done in strip; otherwise, strip formats
; the filename/pathname into tpbuf. Search(tpbuf) is executed to see if we
; have a match, either in the current working directory if we were handed
; a filename, or in the specified directory, given a pathname. If this call
; fails, and we were given a pathname, then Path_Search fails. Otherwise,
; Path_Crunch is repeatedly invoked on tpbuf[STARTEL] (if there's a drive
; prefix, we want to skip it) for each pathstring in userpath. Success on
; either the first invocation of search or on one of the succeeding calls
; sets up the appropriate information for copying the successful pathname
; prefix (if any) into the result buffer, followed by the successful filename
; match (from [search_best_buf]). The result is returned in in EXECPATH.
; ENTRY:
; argv[0] -- command name and associated information
; EXIT:
; AX -- non-zero indicates type of file found
; EXECPATH -- successful pathname (AX non-zero)
; NOTE(S):
; 1) Uses the temporary buffer, tpbuf, from the parse routines.
; 2) Some files are more equal than others. See search: for rankings.
; 3) Path_Search terminates as soon as a call to search succeeds, even
; if search returns an .exe or .bat.
; 5) Clobbers dma address.
pbuflen equ 128 ; length of EXECPATH
path_sep_char equ ';'
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN fbuf:byte
EXTRN pathinfo:word
EXTRN psep_char:byte
TRANSPACE ENDS
Procedure Path_Search,NEAR
push BX
push CX
push DX ; could use a "stack 'em" instruction
push SI
push DI
push BP
pushf
test DS:arg.argv[0].argflags, (MASK wildcard) + (MASK sw_flag)
jz path_search_ok
path_failure_jmp:
jmp path_failure ; ambiguous commands not allowed
path_search_ok:
call store_pchar ; figure out the pathname separator
mov DX, OFFSET TRANGROUP:fbuf ; clobber old dma value with
trap set_dma ; a pointer to our dma buffer
push ES
invoke find_path ; get a handle (ES:DI) on user path
mov DS:pathinfo[0], ES ; and squirrel it away
mov DS:pathinfo[2], DI ; "old" pathstring pointer
mov DS:pathinfo[4], DI ; "new" pathstring pointer
pop ES
mov BX, pbuflen ; copy/format argv[0] into temp buffer
mov SI, OFFSET TRANGROUP:EXECPATH
invoke strip
jc path_failure_jmp ; if possible, of course
mov DX, SI ; search(EXECPATH, error_message)
mov [search_error], OFFSET TRANGROUP:BADDRV_ptr
invoke search ; must do at least one search
or AX, AX ; find anything?
jz path_noinit ; failure ... search farther
mov BP, AX ; success... save filetype code
mov DI, OFFSET TRANGROUP:EXECPATH
mov SI, DS:arg.argv[0].argpointer
mov CX, DS:arg.argv[0].argstartel
sub CX, SI ; compute prefix bytes to copy
;
; We have the number of bytes in the prefix (up to the final component).
; We need to form the complete pathname including leading drive and current
; directory.
;
; Is there a drive letter present?
;
mov ah,':'
cmp cx,2 ; room for drive letter?
jb AddDrive ; no, stick it in
cmp [si+1],ah ; colon present?
jz MoveDrive ; yes, just move it
AddDrive:
mov al,curdrv ; get current drive
add al,"A" ; convert to uppercase letter
stosw ; store d:
jmp short CheckPath
MoveDrive:
lodsw ; move d:
stosw
sub cx,2 ; 2 bytes less to move
CheckPath:
or al,20h
mov dl,al
sub dl,"a"-1 ; convert to 1-based for current dir
;
; Stick in beginning path char
;
mov al,psep_char
stosb
;
; Is there a leading /? If so, then no current dir copy is necessary.
; Otherwise, get current dir for DL.
;
cmp cx,1 ; is there room for path char?
jb AddPath ; no, go add path
lodsb
dec cx
cmp al,psep_char ; is there a path separator?
jz MovePath ; yes, go move remainder of path
inc cx
dec si ; undo the lodsb
AddPath:
SaveReg <SI>
mov si,di ; remainder of buffer
trap Current_dir
;
; The previous current dir will succeed a previous find_first already worked.
;
; Find end of string.
;
mov di,si
RestoreReg <SI>
mov al,psep_char
cmp byte ptr [di],0 ; root (empty dir string)?
jz MovePath ; yes, no need for path char
ScanEnd:
cmp byte ptr [dI],0 ; end of string?
jz FoundEnd
inc di
jmp ScanEnd
;
; Stick in a trailing path char
;
FoundEnd:
stosb
;
; Move remaining part of path. Skip leading path char if present.
;
MovePath:
cmp [si],al ; first char a path char?
jnz CopyPath
inc si ; move past leading char
dec cx ; drop from count
CopyPath:
jcxz CopyDone ; no chars to move!
rep movsb
CopyDone:
jmp path_success ; run off and form complete pathname
path_noinit:
test DS:arg.argv[0].argflags, MASK path_sep
jnz path_failure ; complete pathname specified ==> fail
mov BH, path_sep_char ; semicolon terminates pathstring
mov DX, DS:arg.argv[0].argstartel ; this is where the last element starts
sub DX, DS:arg.argv[0].argpointer ; form pointer into EXECPATH,
add DX, OFFSET TRANGROUP:EXECPATH ; skipping over drive spec, if any
path_loop:
call path_crunch ; pcrunch(EXECPATH, pathinfo)
mov BP, AX ; save filetype code
lahf ; save flags, just in case
or BP, BP ; did path_crunch find anything?
jne path_found
sahf ; see? needed those flags, after all!
jnc path_loop ; is there anything left to the path?
path_failure:
xor AX, AX
;; jmp short path_exit ; 3/3/KK
jmp path_exit ;AC000; 3/3/KK
path_found: ; pathinfo[] points to winner
mov DI, OFFSET TRANGROUP:EXECPATH
mov CX, pathinfo[4] ; "new" pointer -- end of string
mov SI, pathinfo[2] ; "old" pointer -- beginning of string
;
; BAS Nov 20/84
; Look at the pathname and expand . and .. if they are the first element
; in the pathname (after the drive letter)
;
push ES
push pathinfo[0]
pop ES
cmp Byte Ptr ES:[SI+2],'.' ; Look for Current dir at start of path
jnz path_cpy
push CX ; Save pointer to end of string
mov AL, ES:[SI]
mov [DI],AL ; Copy drive letter, :, and root char
mov AL, ES:[SI+1] ; to EXECPATH
mov [DI+1],AL
mov AL,psep_char
mov [DI+2],AL
push SI ; Save pointer to begining of string
mov DL,ES:[SI] ; Convert device letter for cur dir
or DL,20h
sub DL,"a"-1
mov SI,DI ; pointer to EXECPATH
add SI, 3 ; Don't wipe out drive and root info
trap Current_dir
invoke DStrlen ; Determine length of present info
add SI,CX ; Don't copy over drive and root info
dec SI
mov DI,SI ; Point to end of target string
pop SI ; Restore pointer to begining of string
add SI, 3 ; Point past drive letter, :, .
pop CX ; Restore pointer to end of string
path_cpy:
pop ES
sub CX, SI ; yields character count
push DS ; time to switch segments
push pathinfo[0] ; string lives in this segment
pop DS
cld
;; rep movsb 3/3/KK ; copy the prefix path into EXECPATH
Kloop: ;AN000; 3/3/KK
lodsb ;AN000; 3/3/KK
stosb ;AN000; 3/3/KK
invoke testkanj ;AN000; 3/3/KK
jz NotKanj1 ;AN000; 3/3/KK
dec cx ;AN000; 3/3/KK
JCXZ PopDone ;AN000; Ignore boundary error 3/3/KK
movsb ;AN000; 3/3/KK
dec cx ;AN000; 3/3/KK
cmp cx,1 ;AN000; One char (the terminator) left ? 3/3/KK
ja Kloop ;AN000; no. 3/3/KK
PopDone: ;AN000; 3/3/KK
POP DS ;AN000; Yes ES:DI->terminator, last char is 3/3/KK
mov AL, psep_char ;AN000; KANJI 3/3/KK
jmp Short path_store ;AN000; 3/3/KK
NotKanj1:
loop Kloop
pop DS ; return to our segment
dec DI ; overwrite terminator
mov AL, psep_char ; with a pathname separator
cmp al,byte ptr [di-1]
jz path_success
path_store: ;AN000; 3/3/KK
stosb
path_success:
mov SI, OFFSET TRANGROUP:search_best_buf
xor CX, CX
path_succ_loop:
lodsb ; append winning filename to path
stosb ; (including terminating null)
or al,al
jnz path_succ_loop
mov AX, BP ; retrieve filetype code
path_exit:
popf
pop BP
pop DI
pop SI ; chill out...
pop DX
pop CX
pop BX
ret
EndProc Path_Search
break <Store_Pchar>
;----------------------------------------------------------------------------
; STORE_PCHAR determines the pathname-element separator and squirrels
; it away. In other words, must we say '/bin/ls' or '\bin\ls'?
; ENTRY:
; EXIT:
; NOTE(S):
; * Uses <psep_char>, defined in <path_search>.
;---------------
;---------------
Procedure Store_PChar,NEAR
;---------------
push AX
mov AL, '/' ; is the pathname-element separator
invoke pathchrcmp ; a regular slash?
jz store_slash ; if yes, remember slash
mov al,'\'
mov [psep_char], al ; otherwise, remember back-slash
pop ax
ret
store_slash:
mov [psep_char], al
pop ax
return
;---------------
EndProc Store_Pchar
;----------------------------------------------------------------------------
break <Path_Crunch>
;----------------------------------------------------------------------------
; PATH_CRUNCH takes a prefix from a prefix string, and a suffix from
; EXECPATH, and smooshes them into tpbuf. The caller may supply an
; additional separator to use for breaking up the path-string. Null is the
; default. Once the user-string has been formed, search is invoked to see
; what's out there.
; ENTRY:
; BH -- additional terminator character
; SI -- pointer into pathstring to be dissected
; DX -- pointer to stripped filename
; EXIT:
; AX -- non-zero (file type), zero (nothing found)
; SI -- moves along pathstring from call to call
; [search_best_buf] -- name of best file (AX non-zero)
; [tpbuf] -- clobbered
; NOTE(S):
; * Implicit in this code is the ability to specify when to search
; the current directory (if at all) through the PATH defined by
; the user, a la UNIX (e.g., PATH=;c:\bin;c:\etc searches the
; current directory before the bin and etc directories of drive c).
;---------------
Procedure Path_Crunch,NEAR
;---------------
push BX
push CX
push DX
push DI
push SI
pushf
call store_pchar ; figure out pathname separator
mov DI, OFFSET TRANGROUP:tpbuf ; destination of concatenated string
mov SI, pathinfo[4] ; "new" pointer to start with
mov pathinfo[2], SI ; becomes "old" pointer
push DS ; save old segment pointer
push pathinfo[0] ; replace with pointer to userpath's
pop DS ; segment
xor cl,cl ;AN000; clear flag for later use 3/3/KK
path_cr_copy:
lodsb ; get a pathname byte
or al,al ; check for terminator(s)
jz path_seg ; null terminates segment & pathstring
cmp AL, BH
jz path_seg ; BH terminates a pathstring segment
invoke testkanj ;AN000; 3/3/KK
jz NotKanj2 ;AN000; 3/3/KK
stosb ;AN000; 3/3/KK
movsb ;AN000; 3/3/KK
MOV CL,1 ;AN000; CL=1 means latest stored char is DBCS 3/3/KK
jmp path_cr_copy ;AN000; 3/3/KK
NotKanj2: ;AN000; 3/3/KK
xor cl,cl ;AN000; CL=0 means latest stored char is SBCS 3/3/KK
stosb ; save byte in concat buffer
jmp path_cr_copy ; loop until we see a terminator
path_seg:
pop DS ; restore old data segment
mov pathinfo[4], SI ; save "new" pointer for next time
mov BL, AL ; remember if we saw null or not...
;;; REMOVE NEXT 3 LINES FOR CURDIR SPEC
xor AX, AX ; in case nothing in pathstr...
cmp DI, OFFSET TRANGROUP:tpbuf ; was there really anything in pathstr?
je path_cr_leave ; if nothing was copied, pathstr empty
path_cr_look: ; form complete pathname
mov al, psep_char ; add pathname separator for suffix
or cl,cl ;AN000; 3/3/KK
jnz path_cr_store ;AN000; this is a trailing byte of ECS code 3/3/KK
cmp al,byte ptr [di-1]
jz path_cr_l1
path_cr_store: ;AN000; 3/3/KK
stosb
path_cr_l1:
mov SI, DX
path_cr_l2:
lodsb ; tack the stripped filename onto
stosb ; the end of the path, up to and
or AL, AL ; including the terminating null
jnz path_cr_l2
mov DX, OFFSET TRANGROUP:tpbuf ; and look for an appropriate file...
mov [search_error], OFFSET TRANGROUP:BADPMES_ptr
invoke search ; results are in AX & search_best_buf
path_cr_leave:
or BL, BL ; did we finish off the pathstring?
jz path_cr_empty ; null in BL means all gone...
popf ; otherwise, plenty left
clc
jmp short path_cr_exit
path_cr_empty:
popf
stc
path_cr_exit:
pop SI
pop DI
pop DX
pop CX
pop BX
ret
;---------------
EndProc Path_Crunch
;----------------------------------------------------------------------------
trancode ends
END

View File

@@ -0,0 +1,458 @@
page 80,132
; SCCSID = @(#)path2.asm 1.1 85/05/14
; SCCSID = @(#)path2.asm 1.1 85/05/14
.sall
.xlist
.xcref
INCLUDE DOSSYM.INC
include comsw.asm
include comseg.asm
include comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE
EXTRN FORFLAG:BYTE
DATARES ENDS
break <Path.Asm>
;----------------------------------------------------------------------------
; PATH.ASM contains the routines to perform pathname incovation. Path and
; Parse share a temporary buffer and argv[] definitions. <Path_Search>,
; given a pathname, attempts to find a corresponding executable or batch
; file on disk. Directories specified in the user's search path will be
; searched for a matching file, if a match is not found in the current
; directory and if the pathname is actually only an MSDOS filename.
; <Path_Search> assumes that the parsed command name can be found in
; argv[0] -- in other words, <Parseline> should be executed prior to
; <Path_Search>. Alternatively, the command name and appropriate
; information could be placed in argv[0], or <Path_Search> could be
; (easily) modified to make no assumptions about where its input is found.
; Please find enclosed yet another important routine, <Save_Args>, which
; places the entire arg/argv[]/argbuf structure on a piece of newly
; allocated memory. This is handy for for-loop processing, and anything
; else that wants to save the whole shebang and then process other command
; lines.
;
; Alan L, OS/MSDOS August 15, 1983
;
; ENTRY:
; <Path_Search>: argv[0].
; <Save_Args>: bytes to allocate in addition to arg structure
; EXIT:
; <Path_Search>: success flag, best pathname match in EXECPATH.
; <Save_Args>: success flag, segment address of new memory
; NOTE(S):
; * <Argv_calc> handily turns an array index into an absolute pointer.
; The computation depends on the size of an argv[] element (arg_ele).
; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
; does not function as specified; see <Parseline> for more details.
; * <Parseline> now knows about the flags the internals of COMMAND.COM
; need to know about. This extra information is stored in a switch_flag
; word with each command-line argument; the switches themselves will not
; appear in the resulting arg structure.
; * With the exception of CARRY, flags are generally preserved across calls.
;---------------
; CONSTANTS:
;---------------
DEBUGx equ FALSE ; prints out debug info
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte
EXTRN BADPMES_ptr:word
EXTRN curdrv:byte
EXTRN EXECPATH:byte
EXTRN ext_entered:byte ;AN005;
EXTRN fbuf:byte
EXTRN pathinfo:word
EXTRN psep_char:byte
EXTRN string_ptr_2:word
EXTRN tpbuf:byte
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
break <Search>
;----------------------------------------------------------------------------
; SEARCH, when given a pathname, attempts to find a file with
; one of the following extensions: .com, .exe, .bat (highest to
; lowest priority). Where conflicts arise, the extension with
; the highest priority is favored.
; ENTRY:
; DX -- pointer to null-terminated pathname
; fbuf -- dma buffer for findfirst/next
; EXIT:
; AX -- 8) file found with .com extension
; 4) file found with .exe extension
; 2) file found with .bat extension
; 0) no such file to be found
; (if AX is non-zero:)
; [search_best] identical to AX
; [search_best_buf] null-terminated filename
; NOTES:
; 1) Requires caller to have allocated a dma buffer and executed a setdma.
;---------------
; CONSTANTS:
;---------------
search_file_not_found equ 0
search_com equ 8
search_exe equ 4
search_bat equ 2
fname_len equ 8
fname_max_len equ 13
dot equ '.'
wildchar equ '?'
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN search_best:byte
EXTRN search_best_buf:byte
EXTRN search_curdir_buf:byte
EXTRN search_error:word
TRANSPACE ENDS
;---------------
Procedure Search,NEAR
;---------------
push CX
push DX
push DI
push SI
pushf
push DX ; check drivespec (save pname ptr)
mov DI, DX ; working copy of pathname
mov SI, OFFSET TRANGROUP:search_curdir_buf
xor DX, DX ; zero means current drive
cmp BYTE PTR [DI+1],':' ; is there a drive spec?
jne search_dir_check
mov DL, [DI] ; get the drive byte
and DL, NOT 20H ; uppercase the sucker
sub DL, '@' ; and convert to drive number
search_dir_check:
trap Current_Dir ; can we get the drive's current
pop DX ; directory? If we can't we'll
jc search_invalid_drive ; assume it's a bad drive...
mov CX, search_attr ; filetypes to search for
trap Find_First ; request first match, if any
jc search_no_file
mov search_best, search_file_not_found
mov [search_best_buf], ANULL ; nothing's been found, yet
search_loop:
call search_ftype ; determine if .com, &c...
cmp AL, search_best ; better than what we've found so far?
jle search_next ; no, look for another
mov search_best, AL ; found something... save its code
mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname
mov DI, OFFSET TRANGROUP:search_best_buf
mov CX, fname_max_len
cld
rep movsb ; save complete pathname representation
cmp AL, search_com ; have we found the best of all?
je search_done
search_next: ; keep on looking
mov CX, search_attr
trap Find_Next ; next match
jnc search_loop
search_done: ; it's all over with...
mov AL, search_best ; pick best to return with
cmp ext_entered,1 ;AN005; Did user request a specific ext?
jz search_exit ;AN005; no - exit
mov al,ext_entered ;AN005; yes - get the real file type back
mov search_best,al ;AN005; save the real file type
jmp short search_exit
search_invalid_drive: ; Tell the user path/drive
mov DX, [search_error] ; appropriate error message
invoke std_printf ; and pretend no file found
search_no_file: ; couldn't find a match
mov AX, search_file_not_found
search_exit:
popf
pop SI
pop DI
pop DX
pop CX
ret
;---------------
EndProc Search
;----------------------------------------------------------------------------
break <Search_Ftype>
;----------------------------------------------------------------------------
; SEARCH_FTYPE determines the type of a file by examining its extension.
; ENTRY:
; fbuf -- dma buffer containing filename
; EXIT:
; AX -- file code, as given in search header
; NOTE(S):
; * Implicit assumption that NULL == search_file_not_found
;---------------
; DATA:
;---------------
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
extrn comext:byte,exeext:byte,batext:byte
trandata ends
;---------------
Procedure Search_Ftype,NEAR
;---------------
push DI
push si
mov AX, ANULL ; find the end of the filename
mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname
mov CX, fname_max_len
cld
repnz scasb ; search for the terminating null
jnz ftype_exit ; weird... no null byte at end
sub di,5 ; . + E + X + T + NULL
;
; Compare .COM
;
mov si,offset trangroup:comext
mov ax,di
cmpsw
jnz ftype_exe
cmpsw
jnz ftype_exe
mov AX, search_com ; success!
jmp short ftype_exit
;
; Compare .EXE
;
ftype_exe: ; still looking... now for '.exe'
mov di,ax
mov si,offset trangroup:exeext
cmpsw
jnz ftype_bat
cmpsw
jnz ftype_bat
mov AX, search_exe ; success!
jmp short ftype_exit
;
; Compare .BAT
;
ftype_bat: ; still looking... now for '.bat'
mov di,ax
mov si,offset trangroup:batext
cmpsw
jnz ftype_fail
cmpsw
jnz ftype_fail
mov AX, search_bat ; success!
jmp short ftype_exit
ftype_fail: ; file doesn't match what we need
mov ax,ANULL
ftype_exit:
cmp ext_entered,1 ;AN005; was an extension entered?
jz ftype_done ;AN005; no - exit
cmp ax,ANULL ;AN005; was any match found
jz ftype_done ;AN005; no - exit
mov ext_entered,al ;AN005; save the match type found
mov AX, search_com ;AN005; send back best was found to stop search
ftype_done: ;AN005;
pop SI
pop DI
ret
;---------------
EndProc Search_Ftype
;----------------------------------------------------------------------------
break <Strip>
;----------------------------------------------------------------------------
; STRIP copies the source string (argv[0]) into the destination buffer,
; replacing any extension with wildcards.
; ENTRY:
; BX -- maximum length of destination buffer
; DS:SI -- address of destination buffer
; argv[0] -- command name to be stripped
; EXIT:
; CF -- set if failure, clear if successful
; NOTE(S):
;---------------
Procedure Strip,NEAR
;---------------
push AX
push BX
push CX
push DX
push DI
push SI
pushf
mov ext_entered,1 ;AN005; assume no extension on file name
mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring
mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element
cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command
jz strip_error
mov CX, DX ; compute where end of argstring lies
add CX, DS:arg.argv[0].arglen
sub CX, DI ; and then find length of last element
inc CX ; include null as well
mov AL, dot ; let's find the filetype extension
cld
repnz scasb ; wind up pointing to either null or dot
jcxz process_ext ;AN005; if no extension found, just continue
mov ext_entered,0 ;AN005; we found an extension
mov al,ANULL ;AN005; continue scanning until the
repnz scasb ;AN005; end of line is reached.
process_ext: ;AN005;
mov CX, DI ; pointer to end of argstring yields
sub CX, DX ; number of bytes to be copied
sub BX, 4 ; can argstring fit into dest. buffer?
cmp CX, BX
jg strip_error ; if not, we must have a bad pathname
mov DI, SI ; destination buffer
mov SI, DX ; source is beginning of pathname
cld
rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg
cmp ext_entered,1 ;AN005; if an extension was entered
jnz skip_wilds ;AN005; don't set up wildcard ext.
dec DI ; overwrite null or dot
stosb ; with a dot
mov AL, wildchar ; now add wildcards
stosb
stosb
stosb
mov AL, ANULL ; and a terminating null
stosb
skip_wilds: ;AN005;
popf
clc ; chill out...
jmp short strip_exit
strip_error:
popf
stc
strip_exit:
pop SI
pop DI
pop DX
pop CX
pop BX
pop AX
ret
;---------------
EndProc Strip
;----------------------------------------------------------------------------
break <Save_Args>
;----------------------------------------------------------------------------
; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer
; structure in newly allocated memory. The argv[] structure is found at the
; beginning of this area. The caller indicates how much extra space is
; needed in the resulting structure; Save_Args returns a segment number and
; an offset into that area, indicating where the caller may preserve its own
; data. Note that <argvcnt> can be found at <offset-2>.
; ENTRY:
; BX -- size (in bytes) of extra area to allocate
; EXIT:
; AX -- segment of new area.
; CF -- set if unable to save a copy.
; NOTE(S):
; 1) The allocated area will be AT LEAST the size requested -- since
; the underlying MSDOS call, <alloc> returns an integral number of
; paragraphs.
; 2) It is an error if MSDOS can't allocate AT LEAST as much memory
; as the caller of Save_Args requests.
; 3) AX is undefined if CF indicates an error.
;---------------
Procedure Save_Args,NEAR
;---------------
push BX
push CX
push DX
push DI
push SI
push BP
pushf
add BX, SIZE arg_unit + 0FH ; space for arg structure, round up
mov CL, 4 ; to paragraph size and convert
shr BX, CL ; size in bytes to size in paragraphs
trap Alloc
jc save_error
mov BP, AX ; save segment id
push ES ; save TRANGROUP address
mov ES, AX ; switch to new memory segment
assume ES:nothing
mov CX, SIZE arg_unit ; get back structure size
xor DI, DI ; destination is new memory area
mov SI, OFFSET TRANGROUP:arg ; source is arg structure
rep movsb ; move that sucker!
mov CX, arg.argvcnt ; adjust argv pointers
xor AX, AX ; base address for argv_calc
mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf
save_ptr_loop:
dec CX ; exhausted all args?
jl save_done
mov BX, CX ; get arg index and
invoke argv_calc ; convert to a pointer
mov DX, DS:arg.argv[BX].argpointer
sub DX, SI ; adjust argpointer
mov ES:argv[BX].argpointer, DX
mov DX, DS:arg.argv[BX].argstartel
sub DX, SI ; and adjust argstartel
mov ES:argv[BX].argstartel, DX
mov DX, DS:arg.argv[BX].arg_ocomptr
sub DX, SI ; and adjust arg_ocomptr
mov ES:argv[BX].arg_ocomptr, DX
jmp save_ptr_loop
save_done:
pop ES ; back we go to TRANGROUP
assume ES:trangroup
mov AX, BP ; restore segment id
jmp short save_ok
save_error:
popf
stc
jmp short save_exit
save_ok:
popf
clc
save_exit:
pop BP
pop SI
pop DI
pop DX
pop CX
pop BX
ret
;---------------
EndProc Save_Args
;----------------------------------------------------------------------------
trancode ends
END

View File

@@ -0,0 +1,611 @@
page 80,132
; SCCSID = @(#)rdata.asm 4.2 85/09/22
; SCCSID = @(#)rdata.asm 4.2 85/09/22
TITLE COMMAND Resident DATA
include comsw.asm
.xlist
.xcref
include comseg.asm
.list
.cref
;
; Equates for initialization (from COMEQU)
;
initInit equ 01h ; initialization in progress
initSpecial equ 02h ; in initialization time/date routine
initCtrlC equ 04h ; already in ^C handler
Tokenized = FALSE
CODERES SEGMENT PUBLIC BYTE ;AC000;
PUBLIC RSTACK
EXTRN EXT_EXEC:NEAR
EXTRN THEADFIX:NEAR
EXTRN TREMCHECK:NEAR
DB (80H - 3) DUP (?)
RSTACK LABEL WORD
CODERES ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
EXTRN COMMAND:NEAR
TRANCODE ENDS
; Data for resident portion
DATARES SEGMENT PUBLIC BYTE
IF Tokenized
PUBLIC IOTYP
PUBLIC MESADD
ENDIF
PUBLIC abort_char
PUBLIC append_flag ;AN020;
PUBLIC append_state ;AN020;
PUBLIC BADFAT_BLOCK ;AC000;
PUBLIC BADFAT_OP_SEG ;AC000;
PUBLIC BADFAT_SUBST ;AC000;
PUBLIC BATCH
PUBLIC Batch_Abort
PUBLIC call_batch_flag
PUBLIC call_flag
PUBLIC CDEVAT ;AC000;
PUBLIC COM_FCB1
PUBLIC COM_FCB2
PUBLIC COM_PTR
PUBLIC COM_XLAT_ADDR
PUBLIC COMDRV
PUBLIC COMPRMT1_BLOCK ;AC000;
PUBLIC COMPRMT1_SEG ;AC000;
PUBLIC COMPRMT1_SEG2 ;AC000;
PUBLIC COMPRMT1_SUBST ;AC000;
PUBLIC COMSPEC
PUBLIC crit_msg_off ;AC000;
PUBLIC crit_msg_seg ;AC000;
PUBLIC critical_msg_start ;AC000;
PUBLIC comspec_print
PUBLIC comspec_end
PUBLIC cpdrv
PUBLIC crit_err_INFO
PUBLIC DATARESEND
PUBLIC dbcs_vector_addr ;AN000;
PUBLIC DEVE_OP_OFF ;AC000;
PUBLIC DEVE_OP_SEG ;AC000;
PUBLIC DEVE_OP_SEG2 ;AC000;
PUBLIC DEVEMES_BLOCK ;AC000;
PUBLIC DEVEMES_SUBST ;AC000;
PUBLIC DEVENAM ;AC000;
PUBLIC DISP_CLASS ;AN000;
PUBLIC DRVLET
PUBLIC DRVNUM_BLOCK ;AC000;
PUBLIC DRVNUM_OP_OFF ;AC000;
PUBLIC DRVNUM_OP_SEG ;AC000;
PUBLIC DRVNUM_OP_SEG2 ;AC000;
PUBLIC DRVNUM_SUBST ;AC000;
PUBLIC ECHOFLAG
PUBLIC ENVIRSEG
PUBLIC ERR15_OP_SEG ;AC000;
PUBLIC ERR15_OP_SEG2 ;AC000;
PUBLIC ERR15_OP_SEG3 ;AC000;
PUBLIC ERR15MES_BLOCK ;AC000;
PUBLIC ERR15MES_SUBST ;AC000;
PUBLIC ERRCD_24
PUBLIC ErrType
PUBLIC EXEC_BLOCK
PUBLIC EXECEMES_BLOCK ;AC000;
PUBLIC EXECEMES_SUBST ;AC000;
PUBLIC EXECEMES_OFF ;AC000;
PUBLIC EXECEMES_SEG ;AC000;
PUBLIC EXTCOM
PUBLIC extended_msg_start ;AN000;
PUBLIC extmsgend ;AN000;
PUBLIC fail_char ;AC000;
PUBLIC fFail
PUBLIC FORFLAG
PUBLIC forptr
PUBLIC fucase_addr ;AN000;
PUBLIC HANDLE01
PUBLIC IFFlag
PUBLIC ignore_char
PUBLIC In_Batch
PUBLIC InitFlag
PUBLIC INPIPEPTR
PUBLIC INT_2E_RET
PUBLIC IO_SAVE
PUBLIC LOADING
PUBLIC LTPA
PUBLIC MEMSIZ
;AD054; PUBLIC MESBAS ;AC000;
PUBLIC MYSEG
PUBLIC MYSEG1
PUBLIC MYSEG2
PUBLIC nest
PUBLIC next_batch
PUBLIC no_char
PUBLIC NULLFLAG
PUBLIC NUMBER_SUBST ;AN000;
PUBLIC olderrno
PUBLIC OldTerm
PUBLIC OUTPIPEPTR
PUBLIC PARENT
;AD060; PUBLIC pars_msg_off ;AN000;
;AD060; PUBLIC pars_msg_seg ;AN000;
PUBLIC parse_msg_start ;AN000;
PUBLIC PERMCOM
PUBLIC PIPE1
PUBLIC pipe1t
PUBLIC PIPE2
PUBLIC pipe2t
PUBLIC PIPEFILES
PUBLIC PIPEFLAG
PUBLIC PIPEPTR
PUBLIC PIPESTR
PUBLIC RDIRCHAR
PUBLIC RE_OUT_APP
PUBLIC RE_OUTSTR
PUBLIC RemMsg
PUBLIC resmsgend ;AN000;
PUBLIC RES_TPA
PUBLIC RESTDIR
PUBLIC ResTest
PUBLIC RETCODE
PUBLIC retry_char
PUBLIC rsrc_xa_seg ;AN030;
PUBLIC RSWITCHAR
PUBLIC SAVE_PDB
PUBLIC SINGLECOM
PUBLIC SUM
PUBLIC SUPPRESS
PUBLIC TRANS
PUBLIC TranVarEnd
PUBLIC TRANVARS
PUBLIC TRNSEG
PUBLIC TrnMvFlg
PUBLIC VERVAL
PUBLIC VolName
PUBLIC VOLSER ;AN000;
PUBLIC yes_char
;AD054;MESBAS DW 19 ;AC000; error_write_protect
;AD054; DW 20 ;AC000; error_bad_unit
;AD054; DW 21 ;AC000; error_not_ready
;AD054; DW 22 ;AC000; error_bad_command
;AD054; DW 23 ;AC000; error_CRC
;AD054; DW 24 ;AC000; error_bad_length
;AD054; DW 25 ;AC000; error_Seek
;AD054; DW 26 ;AC000; error_not_DOS_disk
;AD054; DW 27 ;AC000; error_sector_not_found
;AD054; DW 28 ;AC000; error_out_of_paper
;AD054; DW 29 ;AC000; error_write_fault
;AD054; DW 30 ;AC000; error_read_fault
;AD054; DW 31 ;AC000; error_gen_failure
;AD054; DW 32 ;AC000; error_sharing_violation
;AD054; DW 33 ;AC000; error_lock_violation
;AD054; DW 34 ;AC000; error_wrong_disk
;AD054; DW 35 ;AC000; error_FCB_unavailable
;AD054; DW 36 ;AC000; error_sharing_buffer_exceeded
;AD054; DW 37 ;AC000; error_code_page_mismatch
;AD054; DW 38 ;AC026; error_out_of_input
;AD054; DW 39 ;AN026; error_insufficient_disk_space
IF Tokenized
MESADD LABEL WORD
DW OFFSET ResGroup:NEWLIN ;"0"
DW OFFSET ResGroup:COM$1 ;"1"
DW OFFSET ResGroup:ERR3 ;"2"
DW OFFSET ResGroup:ALLOC$3 ;"3"
DW OFFSET ResGroup:FILE$4 ;"4"
DW OFFSET ResGroup:RROR$5 ;"5"
DW OFFSET ResGroup:CAN$6 ;"6"
DW OFFSET ResGroup:EMORY$7 ;"7"
DW OFFSET ResGroup:BAT$8 ;"8"
DW OFFSET ResGroup:INS$9 ;"9"
ERR0 DB "Write protec","t"+80h
ERR1 DB "Bad uni","t"+80h
ERR2 DB "Not read","y"+80h
ERR3 DB "Bad command"," "+80h
ERR4 DB "Dat","a"+80h
ERR5 DB "Bad call forma","t"+80h
ERR6 DB "See","k"+80h
ERR7 DB "Non-DOS dis","k"+80h
ERR8 DB "Sector not foun","d"+80h
ERR9 DB "No pape","r"+80h
ERR10 DB "Write faul","t"+80h
ERR11 DB "Read faul","t"+80h
ERR12 DB "General Failur","e"+80h
ERR13 DB "Sharing Violatio","n"+80h
ERR14 DB "Lock Violatio","n"+80h
ERR15 DB "Invalid Disk Chang","e"+80h
ERR16 DB "FCB unavailabl","e"+80h
ERR17 DB "Sharing buffer exceede","d"+80h
;--- Extra message for error 15
Err15Mes db "Please Insert disk "
VolName db 11 dup(?)
db 13,10,"$"
MREAD DB "read"
MWRITE DB "writ"
ERRMES DB " e5"
IOTYP DB "writin","g"+80h
DRVNUM DB " drive "
DRVLET DB "A"
NEWLIN DB 13,10+80h
DEVEMES DB " device "
DEVENAM DB 8 DUP (?)
DB 13,10,"$" ;Must be $ terminated
COM$1 DB " COMMAN","D"+80h
ALLOC$3 DB " allocation"," "+80h
FILE$4 DB " file"," "+80h
RROR$5 DB "rror"," "+80h
CAN$6 DB "Cannot"," "+80h
EMORY$7 DB "emor","y"+80h
BAT$8 DB " batc","h"+80h
INS$9 DB "Inser","t"+80h
CDEVAT DB ?
BADFAT DB "0File 3table bad",","+80h
COMBAD DB "0Invalid1.COM","0"+80h
comprmt1 DB "9 disk with"," "+80h
comprmt2 DB " in drive "
cpdrv DB " "
PROMPT DB "0and strike any key when ready","0"+80h
ENDBATMES DB "0Terminate8 job (Y/N)?"," "+80h
EXECEMES DB "EXEC failure","0"+80h
EXEBAD DB "E5in EXE4","0"+80h
TOOBIG DB "Program too big to fit in m7","0"+80h
NOHANDMES DB "0No free4handle","s"+80h
BMEMMES DB "0M73e","5"+80h
HALTMES DB "06load1, system halte","d"+80h
FRETMES DB "06start1, exiting","0"+80h
RBADNAM DB "2or4name","0"+80h
AccDen DB "Access Denied","0"+80h
Patricide DB 13,10,"Top level process aborted, cannot continue."," "+80h
COMSPEC_PRINT DW ?
ELSE
parm_block_size EQU 11 ;AN000; size of message subst block
blank EQU " " ;AN000; blank character
DISP_CLASS DB -1 ;AN000; utility message class
NUMBER_SUBST DB 0 ;AN000; number of message substitutions - def 0
DRVNUM_SUBST db 2 ;AN000; number of subst
DRVNUM_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
DRVNUM_OP_OFF dw 0 ;AN000;offset of arg
DRVNUM_OP_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg
DRVNUM_OP_SEG2 dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Char_field_Char ;AN000;one character
db 1 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
DRVLET DB "A"
DEVEMES_SUBST db 2 ;AN000; number of subst
DEVEMES_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
DEVE_OP_OFF dw 0 ;AN000;offset of arg
DEVE_OP_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:DEVENAM ;AN000;offset of arg
DEVE_OP_SEG2 dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Char_field_ASCIIZ ;AN000;character string
db 8 ;AN019;maximum width
db 8 ;AN019;minimum width
db blank ;AN000;pad character
DEVENAM DB 8 DUP (?)
;--- Extra message for error 15
ERR15MES_SUBST db 3 ;AN000; number of subst
ERR15MES_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:VOLNAME ;AN000;offset of arg
ERR15_OP_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 12 ;AN000;maximum width
db 12 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:VOLSER+2;AN000;offset of arg
ERR15_OP_SEG2 dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db right_align+Bin_Hex_Word ;AN000;long binary to decimal
db 4 ;AN000;maximum width
db 4 ;AN000;minimum width
db "0" ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:VOLSER ;AN000;offset of arg
ERR15_OP_SEG3 dw 0 ;AN000;segment of arg
db 3 ;AN000;third subst
db right_align+Bin_Hex_Word ;AN000;long binary to decimal
db 4 ;AN000;maximum width
db 4 ;AN000;minimum width
db "0" ;AN000;pad character
;************************************
;* DO NOT SEPARATE VOLNAME & VOLSER *
;************************************
;*
VolName DB 11 dup(?) ;*
DB 0 ;*
VolSer DD 0 ;*
;*
;************************************
CDEVAT DB ?
BADFAT_SUBST db 1 ;AN000; number of subst
BADFAT_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg
BADFAT_OP_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_Char ;AN000;one character
db 1 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
COMPRMT1_SUBST db 2 ;AN000; number of subst
COMPRMT1_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
COMSPEC_PRINT dw ? ;AN000;offset of arg
COMPRMT1_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 64 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET RESGROUP:CPDRV ;AN000;offset of arg
COMPRMT1_SEG2 dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Char_field_Char ;AN000;one character
db 1 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
cpdrv DB " "
;
; Exec error messages
;
EXECEMES_SUBST db 1 ;AN000; number of subst
EXECEMES_BLOCK db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
EXECEMES_OFF dw 0 ;AN000;offset of arg
EXECEMES_SEG dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 64 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
;
; These characters MUST remain in order
;
abort_char db "A"
retry_char db "R"
ignore_char db "I"
fail_char db "F"
yes_char db "Y"
no_char db "N"
;
; End of characters that MUST remain in order
;
ENDIF
RemMsg DD ? ;Pointer to message in error 15
ErrType DB ? ; Error message style, 0=old, 1=new
INT_2E_RET DD ? ; Magic command executer return address
SAVE_PDB DW ?
PARENT DW ?
OldTerm DD ?
ERRCD_24 DW ?
HANDLE01 DW ?
LOADING DB 0
BATCH DW 0 ; Assume no batch mode initially
COMSPEC DB 64 DUP(0)
comspec_end dw ?
TRANS DW OFFSET TRANGROUP:COMMAND
TRNSEG DW ?
; BAS DEBUG
TrnMvFlg DB 0 ; Indicate if transient portion has been moved
In_Batch DB 0 ; Indicate if we are in Batch processing mode.
Batch_Abort DB 0 ; Indicate if user wants to abort from batch mode.
COMDRV DB ? ; DRIVE SPEC TO LOAD AUTOEXEC AND COMMAND
MEMSIZ DW ?
SUM DW ?
EXTCOM DB 1 ; For init, pretend just did an external
RETCODE DW ?
CRIT_ERR_INFO DB ? ;G hold critical error flags for R,I,F
rsrc_xa_seg DW -1 ;AN030; holds segment of xa copy buffer
;
; The echo flag needs to be pushed and popped around pipes and batch files.
; We implement this as a bit queue that is shr/shl for push and pop.
;
ECHOFLAG DB 00000001B ; low bit TRUE => echo commands
SUPPRESS DB 1 ; used for echo, 1=echo line
IO_SAVE DW ?
RESTDIR DB 0
PERMCOM DB 0 ; TRUE => permanent command
SINGLECOM DW 0 ; TRUE => single command version
VERVAL DW -1
fFail DB 0 ; TRUE => FAIL all INT 24s
IFFLAG DB 0 ; TRUE => If statement in progress
FORFLAG DB 0 ; TRUE => FOR statement in progress
FORPTR DW 0
NEST DW 0 ; NESTED BATCH FILE COUNTER
CALL_FLAG DB 0 ; NO CALL (BATCH COMMAND) IN PROGRESS
CALL_BATCH_FLAG DB 0
NEXT_BATCH DW 0 ; ADDRESS OF NEXT BATCH SEGMENT
NULLFLAG DB 0 ; FLAG IF NO COMMAND ON COMMAND LINE
COM_XLAT_ADDR DB 5 DUP (0) ;G BUFFER FOR TRANSLATE TABLE ADDRESS
FUCASE_ADDR DB 5 DUP (0) ;AN000; BUFFER FOR FILE UCASE ADDRESS
CRIT_MSG_OFF DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE OFFSET
CRIT_MSG_SEG DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE SEGMENT
;AD060; PARS_MSG_OFF DW 0 ;AN000; SAVED PARSE ERROR MESSAGE OFFSET
;AD060; PARS_MSG_SEG DW 0 ;AN000; SAVED PARSE ERROR MESSAGE SEGMENT
Dbcs_vector_addr DW 0 ;AN000; DBCS vector offset
DW 0 ;AN000; DBCS vector segment
APPEND_STATE DW 0 ;AN020; current state of append (if flag = -1)
APPEND_FLAG DB 0 ;AN020; set if APPEND state valid
RE_OUT_APP DB 0
RE_OUTSTR DB 64+3+13 DUP (?)
;
; We flag the state of COMMAND in order to correctly handle the ^Cs at
; various times. Here is the breakdown:
;
; initINIT We are in the init code.
; initSpecial We are in the date/time prompt
; initCtrlC We are handling a ^C already.
;
; If we get a ^C in the initialization but not in the date/time prompt, we
; ignore the ^C. This is so the system calls work on nested commands.
;
; If we are in the date/time prompt at initialization, we stuff the user's
; input buffer with a CR to pretend an empty response.
;
; If we are already handling a ^C, we set the carry bit and return to the user
; (ourselves). We can then detect the carry set and properly retry the
; operation.
;
InitFlag DB initINIT
;These two bytes refed as a word
PIPEFLAG DB 0
PIPEFILES DB 0
;--- 2.x data for piping
;
; All the "_" are substituted later, the one before the : is substituted
; by the current drive, and the others by the CreateTemp call with the
; unique file name. Note that the first 0 is the first char of the pipe
; name. -MU
;
;--- Order dependant, do not change
Pipe1 db "_:/"
Pipe1T db 0
db "_______.___",0
Pipe2 db "_:/"
Pipe2T db 0
db "_______.___",0
PIPEPTR DW ?
PIPESTR DB 129 DUP(?)
INPIPEPTR DW OFFSET ResGroup:PIPE1
OUTPIPEPTR DW OFFSET ResGroup:PIPE2
EXEC_BLOCK LABEL BYTE ; The data block for EXEC calls
ENVIRSEG DW ?
COM_PTR LABEL DWORD
DW 80H ; Point at unformatted parameters
DW ?
COM_FCB1 LABEL DWORD
DW 5CH
DW ?
COM_FCB2 LABEL DWORD
DW 6CH
DW ?
TRANVARS LABEL BYTE ; Variables passed to transient
DW OFFSET ResGroup:THEADFIX
MYSEG DW 0 ; Put our own segment here
LTPA DW 0 ; WILL STORE TPA SEGMENT HERE
RSWITCHAR DB "-"
RDIRCHAR DB "/"
DW OFFSET ResGroup:EXT_EXEC
MYSEG1 DW ?
DW OFFSET ResGroup:TREMCHECK
MYSEG2 DW 0
ResTest DW 0
RES_TPA DW 0 ; Original TPA (not rounded to 64K)
TranVarEnd LABEL BYTE
olderrno dw ?
RESMSGEND DW 0 ;AN000;; holds offset of msg end (end of resident)
.xlist
.xcref
INCLUDE SYSMSG.INC ;AN000; include message services
.list
.cref
ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP
MSG_UTILNAME <COMMAND> ;AN000; define utility name
;AD054; MSG_SERVICES <COMR,MSGDATA,COMMAND.CLA,COMMAND.CL3,COMMAND.CL4> ;AN000; get message services data and resident messages
MSG_SERVICES <COMR,MSGDATA,COMMAND.CLA> ;AN054; get message services data and resident messages
CRITICAL_MSG_START LABEL BYTE ;AN000; start of critical error messages
MSG_SERVICES <COMR,COMMAND.CLD> ;AN000; get critical error messages
DATARESEND LABEL BYTE ;AC060; end of resident portion if /msg not used
PARSE_MSG_START LABEL BYTE ;AN000; start of parse error messages
MSG_SERVICES <COMR,COMMAND.CLC> ;AN000; get parse error messages
;AD060; DATARESEND LABEL BYTE ; end of resident portion if /msg not used
EXTENDED_MSG_START LABEL BYTE ;AN000; start of extended error messages
MSG_SERVICES <COMR,COMMAND.CLE> ;AN000; get extended error messages
EXTMSGEND LABEL BYTE ;AN000; end of extended error messages
include msgdcl.inc
DATARES ENDS
END

View File

@@ -0,0 +1,43 @@
; SCCSID = @(#)resmsg.equ 4.1 85/09/10
; SCCSID = @(#)resmsg.equ 4.1 85/09/10
;****************************
;* RESIDENT MESSAGE EQUATES *
;****************************
REQ_ABORT EQU 210 ;AC000; "Abort"
REQ_RETRY EQU 211 ;AC000; ", Retry"
REQ_IGNORE EQU 212 ;AC000; ", Ignore"
REQ_FAIL EQU 213 ;AC000; ", Fail"
REQ_END EQU 214 ;AC000; "? "
MREAD EQU 215 ;AC000; "reading"
MWRITE EQU 216 ;AC000; "writing"
DRVNUM EQU 217 ;AC000; "%1 drive %2"
DEVEMES EQU 218 ;AC000; "%1 device %2"
Err15Mes EQU 219 ;AC000; "Please insert volume %1 serial %2"
BADFAT EQU 220 ;AC000; "File allocation table bad, drive %1"
COMBAD EQU 221 ;AC000; 13,10,"Invalid COMMAND.COM",13,10"
comprmt1 EQU 222 ;AC000; "Insert disk with %1 in drive %1"
PROMPT EQU 223 ;AC000; "Press any key to continue"
ENDBATMES EQU 224 ;AC000; 13,10,"Terminate batch job (Y/N)? "
EXECEMES EQU 225 ;AC000; "Cannot execute %1",13,10
EXEBAD EQU 226 ;AC000; "Error in EXE file",13,10
TOOBIG EQU 227 ;AC000; "Program too big to fit in memory",13,10
NOHANDMES EQU 228 ;AC000; 13,10,"No free file handles"
RBADNAM EQU 229 ;AC000; "Bad Command or file name",13,10
AccDen EQU 230 ;AC000; Extended error - "Access denied",13,10
BMEMMES EQU 231 ;AC000; 13,10,"Memory allocation error "
HALTMES EQU 232 ;AC000; 13,10,"Cannot load COMMAND, system halted"
FRETMES EQU 233 ;AC000; 13,10,"Cannot start COMMAND, exiting",13,10
Patricide EQU 234 ;AC000; 13,10,"Top level process aborted, cannot continue."
NEWLIN EQU 235 ;AC000; 13,10
;************************
;* INIT MESSAGE EQUATES *
;************************
BADVER EQU 461 ;AC000; "Incorrect DOS version",13,10,"$"
OUTENVERR_PTR EQU 463 ;AC000; "Out of environment space",13,10,0
HEADER_PTR EQU 464 ;AC000; Long Copyright Notice
BADCOMLKMES_PTR EQU 465 ;AC000;"Specified COMMAND search directory bad",13,10,0
BADCOMACCMES_PTR EQU 466 ;AC000; "Specified COMMAND search directory bad access denied",13,10,0

View File

@@ -0,0 +1,739 @@
page 80,132
; SCCSID = @(#)rucode.asm 4.5 85/07/22
; SCCSID = @(#)rucode.asm 4.5 85/07/22
TITLE COMMAND Language modifiable Code Resident
.xlist
.xcref
INCLUDE DOSSYM.INC ;AC000;
include doscntry.inc ;AC000;
DEBUG = 0 ; NEED TO SET IT TO WHAT IT IS IN DOSSYM.INC
INCLUDE DEVSYM.INC
INCLUDE comsw.asm
INCLUDE comseg.asm
INCLUDE comequ.asm
include resmsg.equ ;AN000;
.list
.cref
Tokenized = FALSE
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN abort_char:byte
EXTRN badfat_block:byte ;AC000;
EXTRN badfat_subst:byte ;AC000;
EXTRN Batch_Abort:byte
EXTRN CDEVAT:BYTE
EXTRN COMSPEC:BYTE ;AN060;
EXTRN com_xlat_addr:word
EXTRN crit_err_info:byte
EXTRN crit_msg_off:word ;AC000;
EXTRN crit_msg_seg:word ;AC000;
EXTRN dbcs_vector_addr:dword ;AN000;
EXTRN devemes_block:byte ;AC000;
EXTRN devemes_subst:byte ;AC000;
EXTRN DEVENAM:BYTE
EXTRN deve_op_off:word ;AC000;
EXTRN disp_class:byte ;AC000;
EXTRN DRVLET:BYTE
EXTRN drvnum_block:byte ;AC000;
EXTRN drvnum_op_off:word ;AC000;
EXTRN drvnum_subst:byte ;AC000;
EXTRN err15mes_block:byte ;AC000;
EXTRN err15mes_subst:byte ;AC000;
EXTRN ERRCD_24:WORD
EXTRN ErrType:BYTE
EXTRN fail_char:byte
EXTRN fFail:BYTE
EXTRN FORFLAG:BYTE
EXTRN ignore_char:byte
EXTRN InitFlag:BYTE
EXTRN In_Batch:byte
EXTRN LOADING:BYTE
;AD054; EXTRN MESBAS:BYTE
EXTRN no_char:byte
EXTRN number_subst:byte ;AC000;
EXTRN olderrno:word
EXTRN PARENT:WORD
;AD060; EXTRN pars_msg_off:word ;AC000;
;AD060; EXTRN pars_msg_seg:word ;AC000;
EXTRN PERMCOM:BYTE
EXTRN RemMsg:DWORD
EXTRN retry_char:byte
EXTRN PIPEFLAG:BYTE
EXTRN SINGLECOM:WORD
EXTRN VolName:BYTE
EXTRN yes_char:byte
IF Tokenized
EXTRN IOTYP:BYTE
EXTRN MESADD:BYTE
ENDIF
DATARES ENDS
CODERES SEGMENT PUBLIC BYTE
EXTRN GETCOMDSK2:NEAR
PUBLIC ASKEND
PUBLIC CRLF
PUBLIC DSKERR
PUBLIC ITESTKANJ ;AN000;
PUBLIC RESET_MSG_POINTERS ;AC000;
PUBLIC RPRINT
ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;
; AskEnd - prompt the user to see if he should terminate the batch file. If
; any system call returns with carry set or if RPRINT returns with carry set,
; we jump to the top and start over.
;
; Returns: carry set if response indicates that the batch file should
; be terminated.
; carry clear otherwise.
;
ASSUME DS:RESGROUP
ASKEND:
MOV DX,ENDBATMES ;AC000; get batch terminate question
CALL RPRINT
MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT
INT 21H
call in_char_xlat ;g change to upper case
CMP AL,no_char
retz ; carry is clear => no free
CMP AL,yes_char
JNZ ASKEND
stc ; carry set => free batch
return
DSKERR:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
; ******************************************************
; THIS IS THE DEFAULT DISK ERROR HANDLING CODE
; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO
; INTERCEPT INTERRUPT 24H.
; ******************************************************
STI
PUSH DS
PUSH ES
PUSH SI ;AN000; save si
PUSH CX
PUSH DI
PUSH CX
PUSH AX
MOV DS,BP
MOV AX,[SI.SDEVATT]
MOV [CDEVAT],AH
PUSH CS
POP ES
MOV DI,OFFSET RESGROUP:DEVENAM
MOV CX,8
ADD SI,SDEVNAME ; Suck up device name (even on Block)
REP MOVSB
POP AX
POP CX
POP DI ; Stack just contains DS and ES
; at this point
INVOKE SAVHAND
PUSH CS
POP DS ; Set up local data segment
ASSUME DS:RESGROUP
PUSH DX
CALL CRLF
POP DX
MOV CRIT_ERR_INFO,AH ;G save so we know if R,I,F are valid
ADD AL,'A' ; Compute drive letter (even on character)
MOV [DRVLET],AL
TEST AH,80H ; Check if hard disk error
JZ NOHARDE
TEST [CDEVAT],DEVTYP SHR 8
JNZ NOHARDE
JMP FATERR
NOHARDE:
MOV SI,MREAD ;AC000;
TEST AH,1
JZ SAVMES
MOV SI,MWRITE ;AC000;
SAVMES:
IF Tokenized
LODSW
MOV WORD PTR [IOTYP],AX
LODSW
MOV WORD PTR [IOTYP+2],AX
ENDIF
mov olderrno,di ; keep code in a safe place
PUSH ES ;AN000;
PUSH DS ; GetExtendedError likes to STOMP
PUSH BP
PUSH SI
PUSH DX
PUSH CX
PUSH BX
mov ah,GetExtendedError ; get extended error code
INT 21H
POP BX
POP CX
POP DX
POP SI
POP BP
POP DS
mov word ptr cs:[RemMsg],di ;AC000; save pointer to remote message
mov word ptr cs:[RemMsg+2],es ;AC000; (only used on code 15)
pop ES ;AN000;
XOR AH,AH
mov di,ax ; REAL error code to DI
;
; DI is now the correct error code. Classify things to see what we are
; allowed to report. We convert DI into a 0-based index into a message table.
; This presumes that the int 24 errors (oldstyle) and new errors (sharing and
; the like) are contiguous.
;
SUB DI,error_write_protect
JAE HavCod
MOV DI,error_Gen_failure-error_write_protect
;
; DI now has the mapped error code. Old style errors are:
; FOOBAR <read|writ>ing drive ZZ.
; New style errors are:
; FOOBAR
; We need to figure out which the particular error belongs to.
;
HAVCOD:
mov ErrType,0 ; assume Old style
cmp di,error_FCB_Unavailable-error_write_protect
jz SetStyle
cmp di,error_sharing_buffer_exceeded-error_write_protect
jnz GotStyle
SetStyle:
mov ErrType,1 ; must be new type
GotStyle:
MOV [ERRCD_24],DI
cmp di,error_handle_disk_full-error_write_protect ;AC026;
; If the error message is unknown
jbe NormalError ; redirector, continue. Otherwise,
;
; We do not know how to handle this error. Ask IFSFUNC if she knows
; how to handle things
;
;input to IFSFUNC: AL=1
; BX=extended error number
;output from IFSFUNC: AL=error type (0 or 1)
; 0=<message> error (read/writ)ing (drive/device) xxx
; Abort, Retry, Ignore
; 1=<message>
; Abort, Retry, Ignore
; ES:DI=pointer to message text
; carry set=>no message
MOV DI,AX ; retrieve correct extended error...
mov ax,0500h ; Is the redir there?
int 2fh
cmp al,0ffh
jnz NoHandler ; No, go to NoHandler
push bx ;AN063;
mov bx,di ; Get ErrType and ptr to error msg ;AC063;
mov ax,0501h ;AC063;
int 2fh
pop bx ;AC063;
jc NoHandler
mov ErrType,al
push ds
push es
pop ds
mov dx,di
mov cx,-1 ; Find the end of the error msg and turn
xor al,al ; the high byte on for rprint
repnz scasb
IF Tokenized
or byte ptr [di-2],80h
call rprint ; Print the message
and byte ptr [di-2], NOT 80h ; Restore msg to original condition
ELSE
mov byte ptr [di-1],'$'
MOV AH,Std_con_string_output ;AC000; Print the message
INT 21h ;AN000;
mov byte ptr [di-1],0 ; Restore msg to original condition
ENDIF
pop ds ; Clean up and continue processing
jmp short CheckErrType
NoHandler: ; Redir isn't available or doesn't
mov ErrType,0 ; recognize the error. Reset vars and
mov di,olderrno ; regs to unextended err and continue
mov ERRCD_24,di ; normally.
NormalError:
;AD054; SHL DI,1
;AD054; MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message
add DI,error_write_protect ;AN054;
XCHG DI,DX ; May need DX later
MOV DISP_CLASS,EXT_CRLF_CLASS ;AN054; printing extended error class
CALL RPRINT ; Print error type
CheckErrType:
cmp ErrType,0 ; Check error style...
je ContOld
call CRLF ; if new style then done printing
jmp short ASK
ContOld:
IF NOT Tokenized
MOV AX,SI ;AN000; get reading/writing for message
MOV DH,UTIL_MSG_CLASS ;AN000; this is a utility message
CALL SYSGETMSG ;AN000; get the message
ENDIF
TEST [CDEVAT],DEVTYP SHR 8
JZ BLKERR
MOV DX,DEVEMES ;AC000; get message number for device message
MOV DEVE_OP_OFF,SI ;AN000; put address of read/write in subst block
MOV AL,DEVEMES_SUBST ;AN000; get number of substitutions
MOV NUMBER_SUBST,AL ;AN000;
MOV SI,OFFSET RESGROUP:DEVEMES_BLOCK;AN000; get address of subst block
CALL RPRINT ;AC000; print the message
JMP SHORT ASK ; Don't ralph on COMMAND
BLKERR:
MOV DX,DRVNUM ;AN000; get drive message number
MOV DRVNUM_OP_OFF,SI ;AN000; put address of read/write in subst block
MOV AL,DRVNUM_SUBST ;AN000; get number of substitutions
MOV NUMBER_SUBST,AL ;AN000;
MOV SI,OFFSET RESGROUP:DRVNUM_BLOCK ;AN000; get address of subst block
CALL RPRINT
CMP [LOADING],0
JZ ASK
INVOKE RESTHAND
JMP GETCOMDSK2 ; If error loading COMMAND, re-prompt
ASK:
cmp [ERRCD_24],15 ; Wait! Error 15 has an extra message
jne Not15
PUSH CX
push ds
pop es
lds si,[RemMsg]
assume ds:nothing
push di
mov di,offset resgroup:VolName
mov cx,16 ;AC000; extra message volume name & serial number
cld ; just in case!
rep movsb
pop di
push es
pop ds
POP CX
assume ds:resgroup
mov dx,Err15Mes ;AC000; get message number
MOV AL,ERR15MES_SUBST ;AN000; get number of substitutions
MOV NUMBER_SUBST,AL ;AN000;
MOV SI,OFFSET RESGROUP:ERR15MES_BLOCK ;AN000; get address of subst block
CALL RPRINT
; PRINT OUT ABORT, RETRY, IGNORE, FAIL MESSAGE. ONLY PRINT OUT OPTIONS
; THAT ARE VALID
Not15:
MOV DX,REQ_ABORT ;AC000;G print out abort message
CALL RPRINT ;G
TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is retry allowed?
JZ TRY_IGNORE ;G
MOV DX,REQ_RETRY ;AC000;G yes,print out retry message
CALL RPRINT ;G
try_ignore:
TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is ignore allowed?
JZ TRY_FAIL ;G
MOV DX,REQ_IGNORE ;AC000;G yes,print out ignore message
CALL RPRINT ;G
try_fail:
TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed?
JZ TERM_QUESTION ;G
MOV DX,REQ_FAIL ;AC000;G yes,print out FAIL message
CALL RPRINT ;G
Term_Question:
MOV DX,REQ_END ;AC000;G terminate the string
CALL RPRINT ;G
;
; If the /f switch was given, we fail all requests...
;
TEST fFail,-1
JZ DoPrompt
MOV AH,3 ; signal fail
JMP EExit
DoPrompt:
MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT
INT 21H ; Get response
invoke TestKanjR ;AN000; 3/3/KK
jz notkanj ;AN000; 3/3/KK
MOV AX,(STD_CON_INPUT SHL 8) ;AN000; eat the 2nd byte of ECS code 3/3/KK
INT 21H ;AN000; 3/3/KK
CALL CRLF ;AN000; 3/3/KK
JMP ASK ;AN000; 3/3/KK
notkanj: ;AN000; 3/3/KK
CALL CRLF
CALL IN_CHAR_XLAT ;G Convert to upper case
MOV AH,0 ; Return code for ignore
TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is IGNORE allowed?
JZ USER_RETRY ;G
CMP AL,ignore_char ; Ignore?
JZ EEXITJ
USER_RETRY:
INC AH ; return code for retry
TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is RETRY allowed?
JZ USER_ABORT ;G
CMP AL,retry_char ; Retry?
JZ EEXITJ
USER_ABORT:
INC AH ; return code for abort - always allowed
CMP AL,abort_char ; Abort?
JZ abort_process ;G exit user program
INC AH ;G return code for fail
TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed?
JZ ASKJ ;G
CMP AL,fail_char ;G fail?
JZ EEXITJ ;G
ASKJ:
JMP ASK ;G
EEXITJ:
JMP SHORT EEXIT ;G
abort_process:
test InitFlag,initINIT ; Was command initialization interrupted
jz AbortCont ; No, handle it normally
cmp PERMCOM,0 ; Is this the top level process?
jz JustExit ; Yes, just exit
mov dx,Patricide ;AC000; No, load ptr to error msg
call RPRINT ; Print it
DeadInTheWater:
jmp DeadInTheWater ; Loop until the user reboots
JustExit:
ASSUME DS:RESGROUP
call reset_msg_pointers ;AN000; reset critical & parse message addresses
mov ax,[PARENT] ; Load real parent PID
mov word ptr ds:[PDB_Parent_PID],ax ; Put it back where it belongs
mov ax,(Exit SHL 8) OR 255
int 21H
AbortCont:
test byte ptr [In_Batch],-1 ; Are we accessing a batch file?
jz Not_Batch_Abort
mov byte ptr [Batch_Abort],1 ; set flag for abort
Not_Batch_Abort:
mov dl,PipeFlag
invoke ResPipeOff
OR DL,DL
JZ CHECKFORA
CMP [SINGLECOM],0
JZ CHECKFORA
MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits
CHECKFORA:
CMP [ERRCD_24],0 ; Write protect
JZ ABORTFOR
CMP [ERRCD_24],2 ; Drive not ready
JNZ EEXIT ; Don't abort the FOR
ABORTFOR:
MOV [FORFLAG],0 ; Abort a FOR in progress
CMP [SINGLECOM],0
JZ EEXIT
MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits
EEXIT:
MOV AL,AH
MOV DX,DI
RESTHD:
INVOKE RESTHAND
POP CX
POP SI ;AN000; restore registers
POP ES
POP DS
IRET
FATERR:
MOV DX,BADFAT ;AC000;
MOV AL,BADFAT_SUBST ;AN000; get number of substitutions
MOV NUMBER_SUBST,AL ;AN000;
MOV SI,OFFSET RESGROUP:BADFAT_BLOCK ;AN000; get address of subst block
CALL RPRINT
IF Tokenized
MOV DX,OFFSET RESGROUP:ERRMES
CALL RPRINT
ENDIF
MOV AL,2 ; Abort
JMP RESTHD
;*********************************************
; Print routines for Tokenized resident messages
ASSUME DS:RESGROUP,SS:RESGROUP
CRLF:
MOV DX,NEWLIN ;AC000;
;
; RPRINT prints out a message on the user's console. We clear carry before
; each system call. We do this so that the ^C checker may change things so
; that carry is set. If we detect a system call that returns with carry set,
; we merely return.
;
; Inputs: DX has the message number as an offset from DS.
; Outputs: Carry clear: no carries detected in the system calls
; Carry set: at least one system call returned with carry set
; Registers modified: none
;
RPRINT:
;
; If we are not tokenized, the message consists of a $-terminated string.
; Use CPM io to output it.
;
if NOT tokenized
PUSH AX
PUSH BX ;AC000; save BX register
PUSH CX ;AC000; save CX register
PUSH DX ;AC000; save DX register
MOV AX,DX ;AC000; get message number
MOV DH,DISP_CLASS ;AC000; get display class
MOV DL,NO_CONT_FLAG ;AN000; set control flags off
MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12
XOR CH,CH ;AC000; clear upper part of cx
MOV CL,NUMBER_SUBST ;AC000; set number of substitutions
CALL SYSDISPMSG ;AC000; display the message
MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class
MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions
POP DX ;AC000; restore registers
POP CX ;AC000;
POP BX ;AC000;
POP AX
return
endif
;
; If we are tokenized, output character-by-character. If there is a digit in
; the output, look up that substring in the tokenization table. Use the high
; bit to determine the end-of-string.
;
If Tokenized
SaveReg <AX,DX,SI>
MOV SI,DX
RPRINT1:
LODSB
PUSH AX ; save for EOS testing
AND AL,7FH
CMP AL,'0'
JB RPRINT2
CMP AL,'9'
JA RPRINT2
SUB AL,'0'
CBW ; DS must be RESGROUP if we get here
SHL AX,1 ; clear carry
XCHG SI,AX
MOV DX,[SI + OFFSET RESGroup:MesADD]
CALL RPrint
XCHG SI,AX
JMP SHORT RPRINT3
RPRINT2:
MOV DL,AL
MOV AH,STD_CON_OUTPUT
clc ; set ok flag
INT 21H
RPRINT3:
POP AX
JC RPrint5 ; Abnormal termination?
TEST AL,80h ; High bit set indicates end (carry clear)
JZ RPRINT1
RPRINT5:
RestoreReg <SI,DX,AX>
RET
endif
;g
;g This routine returns the upper case of the character in AL
;g from the upper case table in DOS if character if above
;g ascii 128, else subtract 20H if between "a" and "z"
;g
assume ds:resgroup
in_char_xlat proc near
cmp al,80h ;g see if char is above ascii 128
jb other_xlat ;g no - upper case math
sub al,80h ;g only upper 128 characters in table
push ds
push bx
lds bx,dword ptr com_xlat_addr+1 ;g get table address
add bx,2 ;g skip over first word, of table
xlat ds:byte ptr [bx] ;g convert to upper case
pop bx
pop ds
jmp short in_char_xlat_end ;g we finished - exit
other_xlat:
cmp al,'a' ;g if between "a" and "z", subtract
jb in_char_xlat_end ;g 20h to get upper case
cmp al,'z' ;g equivalent.
ja in_char_xlat_end ;g
sub al,20h ;g Lower-case changed to upper-case
in_char_xlat_end:
ret
in_char_xlat endp
;---------------------- DBCS lead byte check. this is resident code ; 3/3/KK
ITESTKANJ: ;AN000;
TestKanjR: ;AN000; 3/3/KK
push ds ;AN000; 3/3/KK
push si ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
lds si,dbcs_vector_addr ;AN000; GET DBCS VECTOR
ktlop: ;AN000; 3/3/KK
cmp word ptr ds:[si],0 ;AN000; 3/3/KK end of Lead Byte Table
je notlead ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jb notlead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jbe islead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
jmp short ktlop ;AN000; 3/3/KK try another range
Notlead: ;AN000; 3/3/KK
xor ax,ax ;AN000; 3/3/KK set zero
jmp short ktret ;AN000; 3/3/KK
Islead: ;AN000; 3/3/KK
xor ax,ax ;AN000; 3/3/KK reset zero
inc ax ;AN000; 3/3/KK
ktret: ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
pop si ;AN000; 3/3/KK
pop ds ;AN000; 3/3/KK
return ;AN000; 3/3/KK
; ****************************************************************
; *
; * ROUTINE: RESET_MSG_POINTERS
; *
; * FUNCTION: Resets addresses for parse and critical error
; * messages in DOS via INT 2fh. This routine
; * is invoked before command exits.
; *
; * INPUT: none
; *
; * OUTPUT: none
; *
; ****************************************************************
reset_msg_pointers proc near
assume ds:resgroup, es:nothing
push es ;AN000; save used registers
push ax ;AN000;
push dx ;AN000;
push di ;AN000;
;AD060; mov ah,multdos ;AN000; reset parse message pointers
;AD060; mov al,message_2f ;AN000; call for message retriever
;AD060; mov dl,set_parse_msg ;AN000; set up parse message address
;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages
;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages
;AD060; int 2fh ;AN000; go set it
;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
;AD060; mov al,message_2f ;AN000; call for message retriever
mov ax,(multdos shl 8 or message_2f);AN060; reset critical message pointers
mov dl,set_critical_msg ;AN000; set up critical error message address
mov di,crit_msg_off ;AN000; old offset of critical messages
mov es,crit_msg_seg ;AN000; old segment of critical messages
int 2fh ;AN000; go set it
pop di ;AN000; restore used registers
pop dx ;AN000;
pop ax ;AN000;
pop es ;AN000;
ret
reset_msg_pointers endp
PUBLIC MSG_SERV_ST ;AN000;
MSG_SERV_ST LABEL BYTE ;AN000;
PUBLIC SYSGETMSG,SYSDISPMSG
ASSUME DS:RESGROUP, ES:RESGROUP
.xlist
.xcref
INCLUDE SYSMSG.INC ;AN000; include message services
.list
.cref
MSG_UTILNAME <COMMAND> ;AN000; define utility name
MSG_SERVICES <COMR,NEARmsg,DISK_PROC,GETmsg,DISPLAYmsg,CHARmsg,NUMmsg> ;AC060; include message services macro
PUBLIC RES_CODE_END ;AN000;
RES_CODE_END LABEL BYTE ;AN000;
include msgdcl.inc
CODERES ENDS
END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,753 @@
page 80,132
; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
TITLE Batch processing routines part II
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN BATCH:WORD
EXTRN Batch_Abort:byte
EXTRN call_batch_flag:byte
EXTRN call_flag:byte
EXTRN IFFlag:BYTE
EXTRN In_Batch:byte
EXTRN Nest:word
EXTRN PIPEFILES:BYTE
EXTRN RETCODE:WORD
EXTRN SINGLECOM:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADLAB_PTR:WORD
EXTRN BatBufLen:WORD
EXTRN IFTAB:BYTE
EXTRN SYNTMES_PTR:WORD
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
EXTRN BatBuf:BYTE
EXTRN BatBufEnd:WORD
EXTRN BatBufPos:WORD
EXTRN BATHAND:WORD
EXTRN COMBUF:BYTE
EXTRN DIRBUF:BYTE
EXTRN GOTOLEN:WORD
EXTRN if_not_count:word
EXTRN IFNOTFLAG:BYTE
EXTRN RESSEG:WORD
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
EXTRN docom1:near
EXTRN tcommand:near
public $if,iferlev,goto,shift,ifexists,ifnot,forerror,$call
Break <GetBatByt - retrieve a byte from the batch file>
; Get one byte from the batch file and return it in AL. End-of-file returns
; <CR> and ends batch mode. DS must be set to resident segment.
; AH, DX destroyed.
Procedure GETBATBYT,NEAR
ASSUME DS:RESGROUP
SaveReg <BX,CX,DS>
test byte ptr [Batch_Abort],-1
jnz BatEOF
TEST Batch,-1
JZ BatEOF
PUSH ES
MOV ES,Batch
ASSUME ES:NOTHING
ADD WORD PTR ES:[BatSeek],1
ADC WORD PTR ES:[BatSeek+2],0
POP ES
;
; See if we have bytes buffered...
;
MOV AX,CS
MOV DS,AX
ASSUME DS:TranGroup
MOV BX,BatBufPos
CMP BX,-1
JNZ UnBuf
;
; There are no bytes in the buffer. Let's try to fill it up.
;
MOV DX,OFFSET TranGROUP:BatBuf
MOV CX,BatBufLen ; max to read.
MOV BX,BatHand
MOV AH,READ
INT int_command ; Get one more byte from batch file
jnc bat_read_ok ;AN022; if no error - continue
invoke get_ext_error_number ;AN022; get the error
push ds ;AN022; save local segment
mov ds,[resseg] ;AN022; get resident segment
assume ds:resgroup ;AN022;
mov dx,ax ;AN022; put error in DX
invoke output_batch_name ;AN022; set up to print the error
pop ds ;AN022;
assume ds:trangroup ;AN022;
invoke std_eprintf ;AN022; print out the error
mov byte ptr combuf+2,end_of_line_in;AN022; terminate the batch line for parsing
mov byte ptr combuf+3,end_of_line_out ;AN022; terminate the batch line for output
jmp bateof ;AN022; terminate the batch file
bat_read_ok: ;AN022;
MOV CX,AX
JCXZ BATEOFDS
MOV BatBufEnd,CX
XOR BX,BX
MOV BatBufPos,BX
;
; Buffered bytes!
;
UnBuf:
MOV AL,BatBuf[BX] ; get next byte
INC BX
CMP BX,BatBufEnd ; beyond end of buffer?
JB SetBufPos
MOV BX,-1
SetBufPos:
MOV BatBufPos,BX
CMP AL,1AH ; ^Z for termination?
jnz GetByteDone
BatEOFDS:
ASSUME DS:TranGroup
MOV DS,ResSeg
ASSUME DS:ResGroup
BATEOF:
invoke BatchOff
CALL BATCLOSE
MOV AL,0DH ; If end-of-file, then end of line
test byte ptr [Batch_Abort],-1
mov byte ptr [Batch_Abort],0
jz Cont_Get_Byt
mov di,offset TRANGROUP:COMBUF+2 ; reset pointer to beginning of buffer
xor cx,cx ; zero line length
jmp short GetByteDone
Cont_Get_Byt:
CMP [SINGLECOM],0FFF0H ; See if we need to set SINGLECOM
JNZ GetByteDone
CMP NEST,0 ;G See if we have nested batch files
JNZ GETBYTEDONE ;G Yes - don't exit just yet
MOV [SINGLECOM],-1 ; Cause termination
GetByteDone:
RestoreReg <DS,CX,BX>
return
EndProc GetBatByt
break <$If - conditional execution>
assume ds:trangroup,es:trangroup
IFERRORP:
POP AX
IFERROR:
FORERROR:
MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
JMP CERROR
$IF:
;
; Turn off any pipes in progress.
;
push ds ;AN004; save local DS
mov ds,[resseg] ;AN004; get resident segment
assume ds:resgroup ;AN004;
cmp [PIPEFILES],0 ;AN004; Only turn off if present.
jz IFNoPipe ;AN004; no pipe - continue
invoke PipeDel ;AN004; turn off piping
IFNoPipe: ;AN004;
pop ds ;AN004; get local DS back
assume ds:trangroup ;AN004;
MOV [IFNOTFLAG],0
mov [if_not_count], 0
MOV SI,81H
IFREENT:
invoke SCANOFF
CMP AL,0DH
JZ IFERROR
MOV BP,SI
MOV DI,OFFSET TRANGROUP:IFTAB ; Prepare to search if table
MOV CH,0
IFINDCOM:
MOV SI,BP
MOV CL,[DI]
INC DI
JCXZ IFSTRING
JMP SHORT FIRSTCOMP
IFCOMP:
JNZ IF_DIF ;AC000;
FIRSTCOMP:
LODSB
MOV AH,ES:[DI]
INC DI
CMP AL,AH
JZ IFLP
OR AH,20H ; Try lower case
CMP AL,AH
IFLP:
LOOP IFCOMP
IF_DIF: ;AC000;
LAHF
ADD DI,CX ; Bump to next position without affecting flags
MOV BX,[DI] ; Get handler address
INC DI
INC DI
SAHF
JNZ IFINDCOM
LODSB
CMP AL,0DH
IFERRORJ:
JZ IFERROR
invoke DELIM
JNZ IFINDCOM
invoke SCANOFF
JMP BX
IFNOT:
NOT [IFNOTFLAG]
inc [if_not_count]
JMP IFREENT
;
; We are comparing two strings for equality. First, find the end of the
; first string.
;
IFSTRING:
PUSH SI ; save away pointer for later compare
XOR CX,CX ; count of chars in first string
FIRST_STRING:
LODSB ; get character
CMP AL,0DH ; end of line?
JZ IFERRORP ; yes => error
invoke DELIM ; is it a delimiter?
JZ EQUAL_CHECK ; yes, go find equal sign
INC CX ; remember 1 byte for the length
JMP FIRST_STRING ; go back for more
;
; We have found the end of the first string. Unfortunately, we CANNOT use
; scanoff to find the next token; = is a valid separator and will be skipped
; over.
;
EQUAL_CHECK:
CMP AL,'=' ; is char we have an = sign?
JZ EQUAL_CHECK2 ; yes, go find second one.
CMP AL,0DH ; end of line?
JZ IFERRORPj ;AC004; yes, syntax error
LODSB ; get next char
JMP EQUAL_CHECK
;
; The first = has been found. The next char had better be an = too.
;
EQUAL_CHECK2:
LODSB ; get potential = char
CMP AL,'=' ; is it good?
jnz iferrorpj ; no, error
;
; Find beginning of second string.
;
invoke SCANOFF
CMP AL,0DH
jz iferrorpj
POP DI
;
; DS:SI points to second string
; CX has number of chars in first string
; ES:DI points to first string
;
; Perform compare to elicit match
;
REPE CMPSB
JZ MATCH ; match found!
;
; No match. Let's find out what was wrong. The character that did not match
; has been advanced over. Let's back up to it.
;
DEC SI
;
; If it is EOL, then syntax error
;
CMP BYTE PTR [SI],0DH
JZ IFERRORJ
;
; Advance pointer over remainder of unmatched text to next delimiter
;
SKIPSTRINGEND:
LODSB
NOTMATCH:
CMP AL,0DH
IFERRORJ2:
JZ IFERRORJ
invoke DELIM
JNZ SKIPSTRINGEND
;
; Signal that we did NOT have a match
;
MOV AL,-1
JMP SHORT IFRET
iferrorpj:
jmp iferrorp
;
; The compare succeeded. Was the second string longer than the first? We
; do this by seeing if the next char is a delimiter.
;
MATCH:
LODSB
invoke DELIM
JNZ NOTMATCH ; not same.
XOR AL,AL
JMP SHORT IFRET
IFEXISTS:
ifexist_attr EQU attr_hidden+attr_system
moredelim:
lodsb ; move command line pointer over
invoke delim ; pathname -- have to do it ourselves
jnz moredelim ; 'cause parse_file_descriptor is dumb
mov DX, OFFSET TRANGROUP:dirbuf
trap set_dma
mov BX, 2 ; if(0) [|not](|1) exist[1|2] file(2|3)
add BX, [if_not_count]
mov AX, OFFSET TRANGROUP:arg.argv
invoke argv_calc ; convert arg index to pointer
mov DX, [BX].argpointer ; get pointer to supposed filename
mov CX, ifexist_attr ; filetypes to search for
trap Find_First ; request first match, if any
jc if_ex_c ; carry is how to determine error
xor AL, AL
jmp ifret
if_ex_c:
mov AL, -1 ; false 'n' fall through...
IFRET:
TEST [IFNOTFLAG],-1
JZ REALTEST
NOT AL
REALTEST:
OR AL,AL
JZ IFTRUE
JMP TCOMMAND
IFTRUE:
invoke SCANOFF
MOV CX,SI
SUB CX,81H
SUB DS:[80H],CL
MOV CL,DS:[80H]
MOV [COMBUF+1],CL
MOV DI,OFFSET TRANGROUP:COMBUF+2
CLD
REP MOVSB
MOV AL,0DH
STOSB
;
; Signal that an IF was done. This prevents the redirections from getting
; lost.
;
PUSH DS
MOV DS,ResSeg
ASSUME DS:RESGROUP
MOV IFFlag,-1
POP DS
ASSUME DS:TRANGROUP
;
; Go do the command
;
JMP DOCOM1
iferrorj3:
jmp iferrorj2
IFERLEV:
MOV BH,10
XOR BL,BL
GETNUMLP:
LODSB
CMP AL,0DH
jz iferrorj3
invoke DELIM
JZ GOTNUM
SUB AL,'0'
XCHG AL,BL
MUL BH
ADD AL,BL
XCHG AL,BL
JMP SHORT GETNUMLP
GOTNUM:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AH,BYTE PTR [RETCODE]
POP DS
ASSUME DS:TRANGROUP
XOR AL,AL
CMP AH,BL
JAE IFRET
DEC AL
JMP SHORT IFRET
break <Shift - advance arguments>
assume ds:trangroup,es:trangroup
;
; Shift the parameters in the batch structure by 1 and set up the new argument.
; This is a NOP if no batch in progress.
;
Procedure Shift,NEAR
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AX,[BATCH] ; get batch pointer
OR AX,AX ; in batch mode?
retz ; no, done.
MOV ES,AX ; operate in batch segment
MOV DS,AX
ASSUME DS:NOTHING,ES:NOTHING
;
; Now move the batch args down by 1 word
;
MOV DI,BatParm ; point to parm table
LEA SI,[DI+2] ; make source = dest + 2
MOV CX,9 ; move 9 parameters
REP MOVSW ; SHIFT down
;
; If the last parameter (the one not moved) is empty (= -1) then we are done.
; We have copied it into the previous position
;
CMP WORD PTR [DI],-1 ; if last one was not in use then
retz ; No new parm
;
; This last pointer is NOT nul. Get it and scan to find the next argument.
; Assume, first, that there is no next argument
;
MOV SI,[DI]
MOV WORD PTR [DI],-1 ; Assume no parm
;
; The parameters are CR separated. Scan for end of this parm
;
SKIPCRLP:
LODSB
CMP AL,0DH
JNZ SKIPCRLP
;
; We are now pointing at next arg. If it is 0 (end of original line) then we
; are finished. There ARE no more parms and the pointer has been previously
; initialized to indicate it.
;
CMP BYTE PTR [SI],0
retz ; End of parms
MOV [DI],SI ; Pointer to next parm as %9
return
EndProc Shift
;
; Skip delim reads bytes from the batch file until a non-delimiter is seen.
; returns char in AL, carry set -> eof
;
Procedure SkipDelim,NEAR
ASSUME DS:ResGroup,ES:NOTHING
TEST Batch,-1
JZ SkipErr ; batch file empty. OOPS!
CALL GetBatByt ; get a char
invoke Delim ; check for ignoreable chars
JZ SkipDelim ; ignore this char.
clc
return
SkipErr:
stc
return
EndProc SkipDelim
break $Call
; CALL is an internal command that transfers control to a .bat, .exe, or
; .com file. This routine strips the CALL off the command line, sets
; the CALL_FLAG to indicate a call in progress, and returns control to
; DOCOM1 in TCODE to reprocess the command line and execute the file
; being CALLed.
$CALL:
; strip off CALL from command line
ASSUME DS:trangroup,ES:trangroup
push si
push di
push ax
push cx
mov si,offset trangroup:combuf+2
invoke scanoff ;get to first non-delimeter
add si,length_call ;point to char past CALL
mov di,offset trangroup:combuf+2
mov cx,combuflen-length_call ;get length of buffer
rep movsb ;move it
pop cx
pop ax
pop di
pop si
; set call flag to indicate call in progress
push ds
mov ds,[resseg]
ASSUME DS:resgroup,ES:resgroup
mov call_flag, call_in_progress
mov call_batch_flag, call_in_progress
;
; Turn off any pipes in progress.
;
cmp [PIPEFILES],0 ; Only turn off if present.
jz NoPipe
invoke PipeDel
NoPipe:
pop ds
ret
break Goto
GOTO:
assume ds:trangroup,es:trangroup
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
TEST [BATCH],-1
retz ; If not in batch mode, a nop
XOR DX,DX
PUSH DS
MOV DS,Batch
MOV WORD PTR DS:[BatSeek],DX ; Back to start
MOV WORD PTR DS:[BatSeek+2],DX ; Back to start
POP DS
GotoOpen:
invoke promptBat
MOV DI,FCB+1 ; Get the label
MOV CX,11
MOV AL,' '
REPNE SCASB
JNZ NOINC
INC CX
NOINC:
SUB CX,11
NEG CX
MOV [GOTOLEN],CX
;
; At beginning of file. Skip to first non-delimiter char
;
CALL SkipDelim
JC BadGoto
CMP AL,':'
JZ CHKLABEL
LABLKLP: ; Look for the label
CALL GETBATBYT
CMP AL,0AH
JNZ LABLKTST
;
; At beginning of line. Skip to first non-delimiter char
;
CALL SkipDelim
JC BadGoto
CMP AL,':'
JZ CHKLABEL
LABLKTST:
TEST [BATCH],-1
JNZ LABLKLP
BadGoto:
CALL BATCLOSE
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADLAB_ptr
JMP CERROR
;
; Found the :. Skip to first non-delimiter char
;
CHKLABEL:
CALL SkipDelim
JC BadGoto
MOV DI,FCB+1
MOV CX,[GOTOLEN]
JMP SHORT GotByte
NEXTCHRLP:
PUSH CX
CALL GETBATBYT
POP CX
GotByte:
INVOKE TESTKANJ ;AN000; 3/3/KK
JZ NOTKANJ1 ;AN000; 3/3/KK
CMP AL, ES:[DI] ;AN000; 3/3/KK
JNZ LABLKTST ;AN000; 3/3/KK
INC DI ;AN000; 3/3/KK
DEC CX ;AN000; 3/3/KK
JCXZ LABLKTST ;AN000; 3/3/KK
PUSH CX ;AN000; 3/3/KK
CALL GETBATBYT ;AN000; 3/3/KK
POP CX ;AN000; 3/3/KK
CMP AL, ES:[DI] ;AN000; 3/3/KK
JMP SHORT KNEXTLABCHR ;AN000; 3/3/KK
NOTKANJ1: ;AN000; 3/3/KK
OR AL,20H
CMP AL,ES:[DI]
JNZ TRYUPPER
JMP SHORT NEXTLABCHR
TRYUPPER:
SUB AL,20H
CMP AL,ES:[DI]
KNEXTLABCHR: ;AN000; 3/3/KK
JNZ LABLKTST
NEXTLABCHR:
INC DI
LOOP NEXTCHRLP
CALL GETBATBYT
cmp [GOTOLEN],8 ; Is the label atleast 8 chars long?
jge gotocont ; Yes, then the next char doesn't matter
CMP AL,' '
JA LABLKTST
gotocont:
CMP AL,0DH
JZ SKIPLFEED
TONEXTBATLIN:
CALL GETBATBYT
CMP AL,0DH
JNZ TONEXTBATLIN
SKIPLFEED:
CALL GETBATBYT
CALL BatClose
return
Procedure BatClose,NEAR
MOV BX,CS:[BATHAND]
CMP BX,5
JB CloseReturn
MOV AH,CLOSE
INT int_command
CloseReturn:
mov byte ptr [In_Batch],0 ; reset flag
return
EndProc BatClose
;
; Open the BATCH file, If open fails, AL is drive of batch file (A=1)
; Also, fills internal batch buffer. If access denied, then AX = -1
;
Procedure BatOpen,NEAR
ASSUME DS:RESGROUP,ES:TRANGROUP
PUSH DS
MOV DS,[BATCH]
ASSUME DS:NOTHING
MOV DX,BatFile
MOV AX,OPEN SHL 8
INT int_command ; Open the batch file
JC SETERRDL
MOV DX,WORD PTR DS:[BatSeek]
MOV CX,WORD PTR DS:[BatSeek+2]
POP DS
ASSUME DS:RESGROUP
MOV [BATHAND],AX
MOV BX,AX
MOV AX,LSEEK SHL 8 ; Go to the right spot
INT int_command
MOV BatBufPos,-1 ; nuke batch buffer position
return
SETERRDL:
MOV BX,DX
invoke get_ext_error_number ;AN022; get the extended error
mov dx,ax ;AN022; save extended error in DX
MOV AL,[BX] ; Get drive spec
SUB AL,'@' ; A = 1
POP DS
STC ; SUB mucked over carry
return
EndProc BatOpen
TRANCODE ENDS
END


View File

@@ -0,0 +1,598 @@
page 80,132
; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14
TITLE PART4 COMMAND Transient routines.
; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm ;AC000;
include ioctl.inc ;AN000;
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AN020;
EXTRN append_flag:byte ;AN020;
EXTRN append_state:word ;AN020;
DATARES ENDS ;AN020;
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BadCD_ptr:word
EXTRN bits:word
EXTRN Bytmes_ptr:word
EXTRN comsw:word
EXTRN dir_w_syn:word ;AC000;
EXTRN dirdat_mo_day:word ;AC000;
EXTRN dirdat_yr:word ;AC000;
EXTRN dirdattim_ptr:word
EXTRN dirhead_ptr:word
EXTRN dirtim_hr_min:word ;AC000;
EXTRN Dirmes_ptr:word
EXTRN disp_file_size_ptr:word
EXTRN Dmes_ptr:word
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN msg_disp_class:byte ;AN000;
EXTRN parse_dir:byte ;AC000;
EXTRN slash_p_syn:word ;AC000;
EXTRN string_buf_ptr:word
EXTRN tab_ptr:word ;AC000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN bytes_free:word
EXTRN charbuf:byte
EXTRN COM:byte
EXTRN Destisdir:byte
EXTRN Desttail:word
EXTRN dir_num:word
EXTRN Dirbuf:byte
EXTRN dirflag:byte ;AN015;
EXTRN display_ioctl:word ;AC000;
EXTRN display_mode:byte ;AC000;
EXTRN filecnt:word
EXTRN file_size_high:word
EXTRN file_size_low:word
EXTRN fullscr:word
EXTRN ID:byte
EXTRN lincnt:byte ;AC000;
EXTRN linlen:byte
EXTRN linperpag:word ;AC000;
EXTRN msg_numb:word ;AN022;
EXTRN parse1_addr:dword ;AC000;
EXTRN parse1_syn:word ;AC000;
EXTRN parse1_type:byte ;AC000;
EXTRN pathcnt:word ;AN000;
EXTRN pathpos:word ;AN000;
EXTRN resseg:word ;AN020;
EXTRN srcbuf:byte ;AC000;
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
TRANSPACE ENDS
;---------------
EXTRN cerror:near
EXTRN std_printf:near
PUBLIC catalog
break Catalog - Directory command
assume ds:trangroup,es:trangroup
;
; The DIR command displays the contents of a directory.
;
; ****************************************************************
; *
; * ROUTINE: CATALOG - display file(s) in directory
; *
; * FUNCTION: PARSE command line for drive, file, or path name.
; * DIR allows two switches, /P (pause) and /W (wide).
; * If an error occurs issue and error message and
; * transfer control to CERROR.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
CATALOG:
;
; Set up DTA for dir search firsts
;
mov dx,offset trangroup:Dirbuf ;AC000; Set Disk transfer address
mov ah,Set_DMA ;AC000;
int int_command ;AC000;
;
; Set up defaults for switches and parse the command line.
;
mov msg_numb,0 ;AN022; initialize message flag
mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf
mov [pathpos],di ;AN000; this is start of path
mov [pathcnt],1 ;AN000; initialize length to 1 char
mov al,star ;AN000; initialize srcbuf to *,0d
stosb ;AN000;
mov al,end_of_line_in ;AN000;
stosb ;AN000;
mov si,81H ;AN000; Get command line
mov di,offset trangroup:parse_dir ;AN000; Get adderss of PARSE_DIR
xor cx,cx ;AC000; clear counter for positionals
mov ComSw,cx ;AC000; initialize flags
mov bits,cx ;AC000; initialize switches
mov linperpag,linesperpage ;AC000; Set default for lines per page
mov linlen,normperlin ;AC000; Set number of entries per line
mov lincnt,normperlin ;AC000;
dirscan:
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jne dirscan_cont ;AN000; No - continue parsing
jmp scandone ;AN000; yes - go process
dirscan_cont:
cmp ax,result_no_error ;AN000; did we have an error?
jz dirscan_cont2 ;AN000; No - continue parsing
jmp badparm ;AN000; yes - exit
dirscan_cont2:
cmp parse1_syn,offset trangroup:dir_w_syn ;AN000; was /W entered?
je set_dir_width ;AN000; yes - go set wide lines
cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered?
je set_dir_pause ;AN000; yes - go set pause at end of screen
;
; Must be filespec since no other matches occurred. move filename to srcbuf
;
push si ;AC000; save position in line
lds si,parse1_addr ;AC000; get address of filespec
push si ;AN000; save address
invoke move_to_srcbuf ;AC000; move to srcbuf
pop dx ;AC000; get address in DX
;
; The user may have specified a device. Search for the path and see if the
; attributes indicate a device.
;
mov ah,Find_First ;AC000; find the file
int int_command ;AC000;
jnc Dir_check_device ;AN022; if no error - check device
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_no_more_files ;AN022; was error no file found
jz Dir_fspec_end ;AC022; yes -> obviously not a device
cmp ax,error_path_not_found ;AN022; was error no file found
jz Dir_fspec_end ;AC022; yes -> obviously not a device
jmp dir_err_setup ;AN022; otherwise - go issue error message
dir_check_device: ;AN022;
test byte ptr (DirBuf+find_buf_attr),attr_device ;AC000;
jz Dir_fspec_end ;AC000; no, go do normal operation
mov ComSw,-2 ;AC000; signal device
dir_fspec_end:
pop si ;AC000; restore position in line
jmp short dirscan ;AC000; keep parsing
set_dir_width:
test byte ptr[bits],SwitchW ;AN018; /W already set?
jz ok_set_width ;AN018; no - okay to set width
mov ax,moreargs_ptr ;AN018; set up too many arguments
invoke setup_parse_error_msg ;AN018; set up an error message
jmp badparm ;AN018; exit
ok_set_width:
or bits,switchw ;AC000; indicate /w was selected
mov linlen,wideperlin ;AC000; Set number of entries per line
mov lincnt,wideperlin ;AC000;
jmp short dirscan ;AC000; keep parsing
set_dir_pause:
test byte ptr[bits],SwitchP ;AN018; /p already set?
jz ok_set_pause ;AN018; no - okay to set width
mov ax,moreargs_ptr ;AN018; set up too many arguments
invoke setup_parse_error_msg ;AN018; set up an error message
jmp badparm ;AN018; exit
ok_set_pause:
or bits,switchp ;AC000; indicate /p was selected
push cx ;AN000; save necessary registers
push si ;AN000;
mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display
mov bx,stdout ;AN000; lines for stdout
mov ch,ioc_sc ;AN000; type is display
mov cl,get_generic ;AN000; get information
mov dx,offset trangroup:display_ioctl ;AN000;
int int_command ;AN000;
lines_set:
dec linperpag ;AN000; lines per actual page should
dec linperpag ;AN000; two less than the max
mov ax,linperpag ;AN000; get number of lines into
mov [fullscr],ax ;AC000; screen line counter
pop si ;AN000; restore registers
pop cx ;AN000;
jmp dirscan ;AC000; keep parsing
;
; The syntax is incorrect. Report only message we can.
;
BadParm:
jmp cerror ;AC000; invalid switches get displayed
ScanDone:
;
; Find and display the volume ID on the drive.
;
invoke okvolarg ;AC000;
mov [filecnt],0 ;AC000; Keep track of how many files found
cmp comsw,0 ;AC000; did an error occur?
jnz doheader ;AC000; yes - don't bother to fix path
mov dirflag,-1 ;AN015; set pathcrunch called from DIR
invoke pathcrunch ;AC000; set up FCB for dir
mov dirflag,0 ;AN015; reset dirflag
jc DirCheckPath ;AC015; no CHDIRs worked.
jz doheader ;AC015; chdirs worked - path\*.*
mov si,[desttail] ;AN015; get filename back
jmp short DoRealParse ;AN015; go parse it
DirCheckPath:
mov ax,[msg_numb] ;AN022; get message number
cmp ax,0 ;AN022; Is there a message?
jnz dir_err_setup ;AN022; yes - there's an error
cmp [destisdir],0 ;AC000; Were pathchars found?
jz doparse ;AC000; no - no problem
inc comsw ;AC000; indicate error
jmp short doheader ;AC000; go print header
DirNF:
mov ax,error_file_not_found ;AN022; get message number in control block
dir_err_setup:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov extend_buf_ptr,ax ;AN022;
DirError:
jmp Cerror
;
; We have changed to something. We also have a file. Parse it into a
; reasonable form, leaving drive alone, leaving extention alone and leaving
; filename alone. We need to special case ... If we are at the root, the
; parse will fail and it will give us a file not found instead of file not
; found.
;
DoParse:
mov si,offset trangroup:srcbuf ;AN000; Get address of source
cmp byte ptr [si+1],colon_char ;AN000; Is there a drive?
jnz dir_no_drive ;AN000; no - keep going
lodsw ;AN000; bypass drive
dir_no_drive:
cmp [si],".."
jnz DoRealParse
cmp byte ptr [si+2],0
jnz DoRealParse
inc ComSw
jmp short DoHeader
DoRealParse:
mov di,FCB ; where to put the file name
mov ax,(Parse_File_Descriptor SHL 8) OR 0EH
int int_command
;
; Check to see if APPEND installed. If it is installed, set all flags
; off. This will be reset in the HEADFIX routine
;
DoHeader:
mov ax,AppendInstall ;AN020; see if append installed
int 2fh ;AN020;
cmp al,0 ;AN020; append installed?
je DoHeaderCont ;AN020; no - continue
mov ax,AppendDOS ;AN020; see if append DOS version right
int 2fh ;AN020;
cmp ax,-1 ;AN020; append version correct?
jne DoHeaderCont ;AN020; no - continue
mov ax,AppendGetState ;AN020; Get the state of Append
int 2fh ;AN020;
push ds ;AN020; save current data segment
mov ds,[resseg] ;AN020; get resident segment
assume ds:resgroup ;AN020;
mov append_state,bx ;AN020; save append state
mov append_flag,-1 ;AN020; set append flag
xor bx,bx ;AN020; clear out state
mov ax,AppendSetState ;AN020; Set the state of Append
int 2fh ;AN020; set everything off
pop ds ;AN020; save current data segment
assume ds:trangroup ;AN020;
;
; Display the header
;
DoHeaderCont:
mov al,blank ;AN051; Print out a blank
invoke print_char ;AN051; before DIR header
invoke build_dir_string ; get current dir string
mov dx,offset trangroup:Dirhead_ptr
invoke printf_crlf ; bang!
;
; If there were chars left after parse or device, then invalid file name
;
cmp ComSw,0
jz DoSearch ; nothing left; good parse
jl DirNFFix ; not .. => error file not found
invoke RestUDir
mov dx,offset TranGroup:BadCD_ptr
jmp Cerror ; was .. => error directory not found
DirNFFix:
invoke RestUDir
jmp DirNF
;
; We are assured that everything is correct. Let's go and search. Use
; attributes that will include finding directories. perform the first search
; and reset our directory afterward.
;
DoSearch:
mov byte ptr DS:[FCB-7],0FFH
mov byte ptr DS:[FCB-1],010H
;
; Caution! Since we are using an extended FCB, we will *also* be returning
; the directory information as an extended FCB. We must bias all fetches into
; DIRBUF by 8 (Extended FCB part + drive)
;
mov ah,Dir_Search_First
mov dx,FCB-7
int int_command
push ax ;AN022; save return state
inc al ;AN022; did an error occur?
pop ax ;AN022; get return state back
jnz found_first_file ;AN022; no error - start dir
invoke set_ext_error_msg ;AN022; yes - set up error message
push dx ;AN022; save message
invoke restudir ;AN022; restore user's dir
pop dx ;AN022; restore message
cmp word ptr Extend_Buf_Ptr,Error_No_More_Files ;AN022; convert no more files to
jnz DirCerrorJ ;AN022; file not found
mov Extend_Buf_Ptr,Error_File_Not_Found ;AN022;
DirCerrorJ: ;AN022;
jmp Cerror ;AN022; exit
;
; Restore the user's directory. We preserve, though, the return from the
; previous system call for later checking.
;
found_first_file:
push ax
invoke restudir
pop ax
;
; Main scanning loop. Entry has AL = Search first/next error code. Test for
; no more.
;
DIRSTART:
inc al ; FF = file not found
jnz Display
jmp DirDone ; Either an error or we are finished
;
; Note that we've seen a file and display the found file.
;
Display:
inc [filecnt] ; Keep track of how many we find
mov si,offset trangroup:dirbuf+8 ; SI -> information returned by sys call
call shoname
;
; If we are displaying in wide mode, do not output the file info
;
test byte ptr[bits],SwitchW ; W switch set?
jz DirTest
jmp nexent ; If so, no size, date, or time
;
; Test for directory.
;
DirTest:
test [dirbuf+8].dir_attr,attr_directory
jz fileent
;
; We have a directory. Display the <DIR> field in place of the file size
;
mov dx,offset trangroup:Dmes_ptr
call std_printf
jmp short nofsiz
;
; We have a file. Display the file size
;
fileent:
mov dx,[DirBuf+8].dir_size_l
mov file_size_low,dx
mov dx,[DirBuf+8].dir_size_h
mov file_size_high,dx
mov dx,offset trangroup:disp_file_size_ptr
call std_printf
;
; Display time and date of last modification
;
nofsiz:
mov ax,[DirBuf+8].dir_date ; Get date
;
; If the date is 0, then we have found a 1.x level diskette. We skip the
; date/time fields as 1.x did not have them.
;
or ax,ax
jz nexent ; Skip if no date
mov bx,ax
and ax,1FH ; get day
mov dl,al
mov ax,bx
mov cl,5
shr ax,cl ; Align month
and al,0FH ; Get month
mov dh,al
mov cl,bh
shr cl,1 ; Align year
xor ch,ch
add cx,80 ; Relative 1980
cmp cl,100
jb millenium
sub cl,100
millenium:
xchg dh,dl ;AN000; switch month & day
mov DirDat_yr,cx ;AC000; put year into message control block
mov DirDat_mo_day,dx ;AC000; put month and day into message control block
mov cx,[DirBuf+8].dir_time ; Get time
jcxz prbuf ; Time field present?
shr cx,1
shr cx,1
shr cx,1
shr cl,1
shr cl,1 ; Hours in CH, minutes in CL
xchg ch,cl ;AN000; switch hours & minutes
mov DirTim_hr_min,cx ;AC000; put hours and minutes into message subst block
prbuf:
mov dx,offset trangroup:DirDatTim_ptr
call std_printf
invoke crlf2 ;AC066;end the line
dec byte ptr [fullscr] ;AC066;count the line
jnz endif04 ;AN066;IF the last on the screen THEN
call check_for_P ;AN066; pause if /P requested
endif04: ;AN066;
jmp scroll ; If not, just continue
;AD061; mov DirDat_yr,0 ;AC000; reset year, month and day
;AD061; mov DirDat_mo_day,0 ;AC000; in control block
;AD061; mov DirTim_hr_min,0 ;AC000; reset hour & minute in control block
;
; We are done displaying an entry. The code between "noexent:" and "scroll:"
; is only for /W case.
;
nexent:
mov bl,[lincnt] ;AN066;save for check for first entry on line
dec [lincnt] ;count this entry on the line
jnz else01 ;AX066;IF last entry on line THEN
mov al,[linlen]
mov [lincnt],al
invoke crlf2
cmp [fullscr],0 ;AC066;IF have filled the screen THEN
jnz endif02 ;AN066;
call check_for_P ;AN066; reinitialize fullscr,
endif02: ;AN066; IF P requested THEN pause
jmp short endif01 ;AN066;
else01: ;AN066;ELSE since screen not full
cmp bl,[linlen] ;AN066; IF starting new line THEN
jne endif03 ; count the line
dec byte ptr [fullscr] ;AN066; ENDIF
endif03: ;AC066;We are outputting on the same line, between fields, we tab.
mov dx,offset trangroup:tab_ptr ;Output a tab
call std_printf
endif01: ;AX066;
;
; All we need to do now is to get the next directory entry.
;
scroll:
mov ah,Dir_Search_Next
mov dx,FCB-7 ; DX -> Unopened FCB
int int_command ; Search for a file to match FCB
jmp DirStart
;
; If no files have been found, display a not-found message
;
DirDone:
invoke get_ext_error_number ;AN022; get the extended error number
cmp ax,error_no_more_files ;AN022; was error file not found?
jnz dir_err_setup_jmp ;AN022; no - setup error message
test [filecnt],-1
jnz Trailer
mov ax,error_file_not_found ;AN022;
dir_err_setup_jmp: ;AN022;
jmp dir_err_setup ;AN022; go setup error msg & print it
;
; If we have printed the maximum number of files per line, terminate it with
; CRLF.
;
Trailer:
mov al,[linlen]
cmp al,[lincnt] ; Will be equal if just had CR/LF
jz mmessage
invoke crlf2
cmp [fullscr],0 ;AN066;IF on last line of screen THEN
jnz endif06 ;AN066; pause before going on
call check_for_P ;AN066; to number and freespace
endif06: ;AN066; displays
mmessage:
mov dx,offset trangroup:Dirmes_ptr
mov si,[filecnt]
mov dir_num,si
call std_printf
mov ah,Get_Drive_Freespace
mov dl,byte ptr DS:[FCB]
int int_command
cmp ax,-1
retz
mul cx ; AX is bytes per cluster
mul bx
mov bytes_free,ax ;AC000;
mov bytes_free+2,dx ;AC000;
MOV DX,OFFSET TRANGROUP:BYTMES_ptr
jmp std_printf
shoname:
mov di,offset trangroup:charbuf
mov cx,8
rep movsb
mov al,' '
stosb
mov cx,3
rep movsb
xor ax,ax
stosb
push dx
mov dx,offset trangroup:charbuf
mov string_ptr_2,dx
mov dx,offset trangroup:string_buf_ptr
call std_printf
pop DX
return
check_for_P PROC NEAR ;AN066;
test byte ptr[bits],SwitchP ;P switch present?
jz endif05 ;AN066;
mov ax,linperpag ;AN000; transfer lines per page
mov [fullscr],ax ;AC000; to fullscr
invoke Pause
endif05:
ret ;AN066;
check_for_P ENDP ;AN066;
trancode ends
end

View File

@@ -0,0 +1,730 @@
page 80,132
; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14
; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14
TITLE PART4 COMMAND Transient routines.
; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comsw.asm ;AC000;
INCLUDE comequ.asm
INCLUDE ioctl.inc ;AN000;
INCLUDE ea.inc ;AN030;
.list
.cref
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN badcpmes_ptr:word ;AC022;
EXTRN Extend_buf_ptr:word ;AC000;
EXTRN Extend_buf_sub:byte ;AN000;
EXTRN inornot_ptr:word
EXTRN msg_disp_class:byte ;AC000;
EXTRN parse_erase:byte ;AC000;
EXTRN parse_mrdir:byte ;AC000;
EXTRN parse_rename:byte ;AC000;
EXTRN parse_vol:byte ;AC000;
EXTRN PauseMes_ptr:word
EXTRN renerr_ptr:word
EXTRN slash_p_syn:word ;AC000;
EXTRN volmes_ptr:word ;AC000;
EXTRN volmes_ptr_2:word ;AC000;
EXTRN volsermes_ptr:word ;AC000;
EXTRN xa_cp:byte ;AN030;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN bytcnt:word
EXTRN charbuf:byte
EXTRN comsw:word
EXTRN cpyflag:byte ;AC000;
EXTRN curdrv:byte
EXTRN destinfo:byte
EXTRN destisdir:byte
EXTRN dirbuf:byte
EXTRN msg_numb:word ;AN022;
EXTRN one_char_val:byte
EXTRN parse1_addr:dword ;AN000;
EXTRN parse1_syn:word ;AN000;
EXTRN srcbuf:byte ;AN000;
EXTRN string_ptr_2:word ;AN000;
EXTRN TPA:word
EXTRN vol_drv:byte
EXTRN vol_ioctl_buf:byte ;AC000;
EXTRN vol_label:byte ;AC000;
EXTRN vol_serial:dword ;AC000;
EXTRN xa_cp_out:byte ;AN030;
EXTRN xa_cp_length:word ;AN030;
EXTRN xa_list_attr:word ;AC030;
EXTRN zflag:byte
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
transpace ends
;---------------
EXTRN cerror:near
EXTRN error_output:near
EXTRN notest2:near
EXTRN slashp_erase:near ;AN000;
EXTRN std_printf:near
EXTRN tcommand:near
PUBLIC badpath_err ;AN022;
PUBLIC crename
PUBLIC erase
PUBLIC extend_setup ;AN022;
PUBLIC Get_ext_error_number ;AN022;
PUBLIC Get_file_code_page_tag ;AN000;
PUBLIC pause
PUBLIC Set_ext_error_msg ;AN000;
PUBLIC set_file_code_page ;AN000;
PUBLIC typefil
PUBLIC volume
assume ds:trangroup,es:trangroup
break Pause
assume ds:trangroup,es:trangroup
PAUSE:
mov dx,offset trangroup:pausemes_ptr
call std_printf
invoke GetKeystroke
invoke crlf2
return
break Erase
;****************************************************************
;*
;* ROUTINE: DEL/ERASE - erase file(s)
;*
;* FUNCTION: PARSE command line for file or path name and /P
;* and invoke PATHCRUNCH. If an error occurs, set
;* up an error message and transfer control to CERROR.
;* Otherwise, transfer control to NOTEST2 if /P not
;* entered or SLASHP_ERASE if /P entered.
;*
;* INPUT: command line at offset 81H
;*
;* OUTPUT: if no error:
;* FCB at 5ch set up with filename(s) entered
;* Current directory set to entered directory
;*
;****************************************************************
assume ds:trangroup,es:trangroup
ERASE:
mov si,81H ;AC000; get command line
mov comsw,0 ;AN000; clear switch indicator
mov di,offset trangroup:parse_erase ;AN000; Get adderss of PARSE_erase
xor cx,cx ;AN000; clear cx,dx
erase_scan:
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jz good_line ;AN000; yes - done parsing
cmp ax,result_no_error ;AC000; did we have an error?
jnz errj2 ;AC000; yes exit
cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered?
je set_erase_prompt ;AN000; yes - go set prompt
;
; Must be filespec since no other matches occurred. move filename to srcbuf
;
push si ;AC000; save position in line
lds si,parse1_addr ;AC000; get address of filespec
cmp byte ptr[si+1],colon_char ;AC000; drive specified?
jnz Erase_drive_ok ;AC000; no - continue
cmp byte ptr[si+2],end_of_line_out ;AC000; was only drive entered?
jnz erase_drive_ok ;AC000; no - continue
mov ax,error_file_not_found ;AN022; get message number in control block
jmp short extend_setup ;AC000; exit
erase_drive_ok:
invoke move_to_srcbuf ;AC000; move to srcbuf
pop si ;AC000; get position back
jmp short erase_scan ;AN000; continue parsing
set_erase_prompt:
cmp comsw,0 ;AN018; was /P already entered?
jz ok_to_set_erase_prompt ;AN018; no go set switch
mov ax,moreargs_ptr ;AN018; set up too many arguments
invoke setup_parse_error_msg ;AN018; set up an error message
jmp short errj2 ;AN018; exit
ok_to_set_erase_prompt: ;AN018;
inc comsw ;AN000; indicate /p specified
jmp short erase_scan ;AN000; continue parsing
good_line: ;G We know line is good
invoke pathcrunch
jnc checkdr
mov ax,[msg_numb] ;AN022; get message number
cmp ax,0 ;AN022; was message flag set?
jnz extend_setup ;AN022; yes - print out message
cmp [destisdir],0 ; No CHDIRs worked
jnz badpath_err ;AC022; see if they should have
checkdr:
cmp comsw,0 ;AN000; was /p specified
jz notest2j ;AN000; no - go to notest2
jmp slashp_erase ;AN000; yes - go to slashp_erase
notest2j:
jmp notest2
badpath_err: ;AN022; "Path not found" message
mov ax,error_path_not_found ;AN022; set up error number
extend_setup: ;AN022;
mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC022; get extended message pointer
mov Extend_Buf_ptr,ax ;AN022; get message number in control block
errj2: ;AC022; exit jump
jmp Cerror ;AN022;
break Rename
; ****************************************************************
; *
; * ROUTINE: CRENAME - rename file(s)
; *
; * FUNCTION: PARSE command line for one full filespec and one
; * filename. Invoke PATHCRUNCH on the full filespec.
; * Make sure the second filespec only contains a
; * filename. If both openands are valid, attempt
; * to rename the file.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
CRENAME:
mov si,81H ;AC000; Point to command line
mov di,offset trangroup:parse_rename;AN000; Get adderss of PARSE_RENAME
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,result_no_error ;AC000; did we have an error?
jz crename_no_parse_error ;AC000; no - continue
JMP crename_parse_error ;AC000; Yes, fail. (need long jump)
;
; Get first file name returned from parse into our buffer
;
crename_no_parse_error:
push si ;AN000; save position in line
lds si,parse1_addr ;AN000; get address of filespec
invoke move_to_srcbuf ;AN000; move to srcbuf
pop si ;AN000; restore position in line
xor dx,dx ;AN000; clear dx
invoke parse_with_msg ;AC018; call parser
cmp ax,result_no_error ;AN000; did we have an error?
JNZ crename_parse_error ;AN000; Yes, fail.
;
; Check the second file name for drive letter colon
;
push si ;AN000; save position in line
lds si,parse1_addr ;AC000; get address of path
mov al,':' ;AC000;
cmp [si+1],al ;AC000; Does the 2nd parm have a drive spec?
jnz ren_no_drive ;AN000; Yes, error
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,BadParm_ptr ;AN000; get "Invalid parameter" message number
pop si ;AN000;
crename_parse_error: ;AC022;
jmp short errj ;AC000;
;
; Get second file name returned from parse into the fCB. Save
; character after file name so we can later check to make sure it
; isn't a path character.
;
ren_no_drive:
mov di,FCB+10H ;AC000; set up to parse second file name
mov ax,(Parse_File_Descriptor SHL 8) OR 01H ;AC000;
int int_command ;AC000; do the function
lodsb ;AC000; Load char after filename
mov one_char_val,al ;AN000; save char after filename
pop si ;AN000; get line position back
;
; We have source and target. See if any args beyond.
;
mov di,offset trangroup:parse_rename;AC000; get address of parse_rename
invoke parse_check_eol ;AC000; are we at end of line?
jnz crename_parse_error ;AN000; no, fail.
invoke pathcrunch
mov dx,offset trangroup:badcpmes_ptr
jz errj2 ; If 1st parm a dir, print error msg
jnc notest3
mov ax,[msg_numb] ;AN022; get message number
cmp ax,0 ;AN022; was message flag set?
jnz extend_setup ;AN022; yes - print out message
cmp [destisdir],0 ; No CHDIRs worked
jz notest3 ; see if they should have
Jmp badpath_err ;AC022; set up error
notest3:
mov al,one_char_val ;AN000; move char into AX
mov dx,offset trangroup:inornot_ptr ; Load invalid fname error ptr
invoke pathchrcmp ; Is the char in al a path sep?
jz errj ; Yes, error - 2nd arg must be
; filename only.
mov ah,FCB_Rename
mov dx,FCB
int int_command
cmp al, 0FFH ; Did an error occur??
jnz renameok
invoke get_ext_error_number ;AN022; get extended error
SaveReg <AX> ;AC022; Save results
mov al, 0FFH ; Restore original error state
renameok:
push ax
invoke restudir
pop ax
inc al
retnz
RestoreReg <AX> ;AC022; get the error number back
cmp ax,error_file_not_found ;AN022; error file not found?
jz use_renerr ;AN022; yes - use generic error message
cmp ax,error_access_denied ;AN022; error file not found?
jz use_renerr ;AN022; yes - use generic error message
jmp extend_setup ;AN022; need long jump - use extended error
use_renerr:
mov dx,offset trangroup:RenErr_ptr ;AC022;
ERRJ:
jmp Cerror
ret56: ret
break Type
;****************************************************************
;*
;* ROUTINE: TYPEFIL - Display the contents of a file to the
;* standard output device
;*
;* SYNTAX: TYPE filespec
;*
;* FUNCTION: If a valid filespec is found, read the file until
;* 1Ah and display the contents to STDOUT.
;*
;* INPUT: command line at offset 81H
;*
;* OUTPUT: none
;*
;****************************************************************
assume ds:trangroup,es:trangroup
TYPEFIL:
mov si,81H
mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,result_no_error ;AC000; did we have an error?
jnz typefil_parse_error ;AN000; yes - issue error message
push si ;AC000; save position in line
lds si,parse1_addr ;AC000; get address of filespec
invoke move_to_srcbuf ;AC000; move to srcbuf
pop si ;AC000; get position back
mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir
invoke parse_check_eol ;AC000; are we at end of line?
jz gottarg ;AC000; yes - continue
typefil_parse_error: ;AN000; no - set up error message and exit
jmp Cerror
gottarg:
invoke setpath
test [destinfo],00000010b ; Does the filespec contain wildcards
jz nowilds ; No, continue processing
mov dx,offset trangroup:inornot_ptr ; Yes, report error
jmp Cerror
nowilds:
mov ax,ExtOpen SHL 8 ;AC000; open the file
mov bx,read_open_mode ;AN000; get open mode for TYPE
xor cx,cx ;AN000; no special files
mov dx,read_open_flag ;AN000; set up open flags
mov di,-1 ;AN030; no parm list
mov si,offset trangroup:srcbuf ;AN030; get file name
int int_command
jnc typecont ; If open worked, continue. Otherwise load
Typerr: ;AN022;
push cs ;AN022; make sure we have local segment
pop ds ;AN022;
invoke set_ext_error_msg ;AN022;
Typerr2: ;AN022;
mov string_ptr_2,offset trangroup:srcbuf ;AC022; get address of failed string
mov Extend_buf_sub,one_subst ;AC022; put number of subst in control block
jmp cerror ;AC022; exit
typecont:
mov bx,ax ;AC000; get Handle
mov cx,stdout ;AN000; set output to STDOUT
call set_file_code_page ;AN000; Set code page on output device
jc typerr2 ;AN022; exit if error
mov zflag,0 ; Reset ^Z flag
mov ds,[TPA]
xor dx,dx
ASSUME DS:NOTHING
typelp:
cmp cs:[zflag],0 ;AC050; Is the ^Z flag set?
retnz ; Yes, return
mov cx,cs:[bytcnt] ;AC056; No, continue
mov ah,read
int int_command
jc typerr ;AN022; Exit if error
mov cx,ax
jcxz typelp_ret ;AC000; exit if nothing read
push ds
pop es ; Check to see if a ^Z was read.
assume es:nothing
xor di,di
push ax
mov al,1ah
repnz scasb
pop ax
xchg ax,cx
cmp ax,0
jnz foundz ; Yes, handle it
cmp byte ptr [di-1],1ah ; No, double check
jnz typecont2 ; No ^Z, continue
foundz:
sub cx,ax ; Otherwise change cx so that only those
dec cx ; bytes up to but NOT including the ^Z
push cs ; will be typed.
pop es
assume es:trangroup
not zflag ; Turn on ^Z flag so that the routine
typecont2: ; will quit after this write.
push bx
mov bx,1
mov ah,write
int int_command
pop bx
jc Error_outputj
cmp ax,cx
jz typelp
dec cx
cmp ax,cx
retz ; One less byte OK (^Z)
Error_outputj:
mov bx,1
mov ax,IOCTL SHL 8
int int_command
test dl,devid_ISDEV
retnz ; If device, no error message
jmp error_output
typelp_ret:
ret
break Volume
assume ds:trangroup,es:trangroup
;
; VOLUME command displays the volume ID on the specified drive
;
VOLUME:
mov si,81H
mov di,offset trangroup:parse_vol ;AN000; Get adderss of PARSE_VOL
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
jz OkVolArg ;AC000; Yes, display default volume ID
cmp ax,result_no_error ;AC000; did we have an error?
jnz BadVolArg ;AC000; Yes, fail.
;
; We have parsed off the drive. See if there are any more chars left
;
mov di,offset trangroup:parse_vol ;AC000; get address of parse_vol
xor dx,dx ;AC000;
invoke parse_check_eol ;AC000; call parser
jz OkVolArg ;AC000; yes, end of road
;
; The line was not interpretable. Report an error.
;
badvolarg:
jmp Cerror
;
; Find the Volume ID on the disk.
;
PUBLIC OkVolArg
OKVOLARG:
invoke crlf2
mov al,blank ;AN051; Print out a blank
invoke print_char ;AN051; before volume message
push ds
pop es
;
; Volume IDs are only findable via extended FCBs or find_first with attributes
; of volume_id ONLY.
;
mov di,FCB-7 ; Point to extended FCB beginning
mov al,-1 ; Tag to indicate Extention
stosb
xor ax,ax ; Zero padding to volume label
stosw
stosw
stosb
mov al,attr_volume_ID ; Look for volume label
stosb
inc di ; Skip drive byte; it is already set
mov cx,11 ; fill in remainder of file
mov al,'?'
rep stosb
;
; Set up transfer address (destination of search first information)
;
mov dx,offset trangroup:dirbuf
mov ah,set_DMA
int int_command
;
; Do the search
;
mov dx,FCB-7
mov ah,Dir_Search_First
int int_command
;********************************
; Print volume ID info
push ax ;AC000; AX return from SEARCH_FIRST for VOL ID
mov al,DS:[FCB] ;AC000; get drive letter
add al,'@'
cmp al,'@'
jnz drvok
mov al,[curdrv]
add al,capital_A
drvok:
mov vol_drv,al ;AC000; get drive letter into argument
pop ax ;AC000; get return code back
or al,al ;AC000; volume label found?
jz Get_vol_name ;AC000; volume label exists - go get it
mov dx,offset trangroup:VolMes_ptr_2 ;AC000; set up no volume message
jmp short print_serial ;AC000; go print it
Get_vol_name:
mov di,offset trangroup:charbuf
mov dx,di
mov si,offset trangroup:dirbuf + 8 ;AN000; 3/3/KK
mov cx,11 ;AN000; 3/3/KK
rep movsb ;AN000; 3/3/KK
xor al,al ;AC000; store a zero to terminate the string
stosb
mov dx,offset trangroup:VolMes_ptr ;AC000; set up message
PRINT_SERIAL:
;
; Attempt to get the volume serial number from the disk. If an error
; occurs, do not print volume serial number.
;
push dx ;AN000; save message offset
mov ax,(GetSetMediaID SHL 8) ;AC036; Get the volume serial info
mov bl,DS:[FCB] ;AN000; get drive number from FCB
mov dx,offset trangroup:vol_ioctl_buf ;AN000;target buffer
int int_command ;AN000; do the call
pop dx ;AN000; get message offset back
jc printvol_end ;AN000; if error, just go print label
call std_printf ;AC000; go print volume message
mov al,blank ;AN051; Print out a blank
invoke print_char ;AN051; before volume message
mov dx,offset trangroup:VolSerMes_ptr ;AN000; get serial number message
printvol_end:
jmp std_printf ;AC000; go print and exit
;****************************************************************
;*
;* ROUTINE: Set file Code page
;*
;* FUNCTION: Check CPSW status, if CPSW is on, get the file's
;* code page and attempt to invoke it on the
;* output device.
;*
;* INPUT: file handle in BX - unless copyflg is set
;* handle of output device in CX
;*
;* OUTPUT: if carry set (code page invoke failed)
;* ax = extended error
;* otherwise
;* ax modified
;*
;*
;****************************************************************
Set_file_code_page proc near ;AN000;
push bx ;AN000; save registers
push di ;AN000;
push dx ;AN000;
cmp cpyflag,1 ;AN000; were we called from COPY?
jz Already_have_cp ;AN000; yes - already have code page
call get_file_code_page_tag ;AN000; get the file's code page
jc cp_set_error ;AN000; if error - just continue
already_have_cp: ;AN000; See what was returned.
mov ax,(file_times SHL 8)+set_XA ;AC030; set code page
mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list
mov bx,cx ;AN000; get handle of output device
int int_command ;AN000;
jnc set_file_cp_end ;AN000; all okay - return
cp_set_error:
pop dx ;AC030; we don't restore DX for error -
call Set_Ext_Error_msg ;AN000; we return error message
jmp short set_file_cp_exit ;AC030; exit
set_file_cp_end: ;AN000; finished
pop dx ;AN000; restore registers
set_file_cp_exit:
pop di ;AN000;
pop bx ;AN000;
ret ;AN000; return
Set_file_code_page endp ;AN000;
;****************************************************************
;*
;* ROUTINE: Get file Code page tag
;*
;* FUNCTION: Get code page file attribute.
;*
;* INPUT: file handle in BX
;*
;* OUTPUT: if error - carry set
;* otherwise - xa_list_attr set to file's code page
;*
;* AX and DI modified
;*
;****************************************************************
Get_file_code_page_tag proc near ;AN000;
push cx ;AN030;
push si ;AN030;
push di ;AN030;
mov xa_list_attr,0 ;AN030; initialize code page
mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attributes
mov si,offset trangroup:xa_cp ;AN030; get xa request buffer
mov di,offset trangroup:xa_cp_out ;AC030; get xa output buffer
mov cx,xa_cp_length ;AN030; length of buffer
int int_command ;AN000;
pop di ;AN030;
pop si ;AN030;
pop cx ;AN030;
ret ;AN000; return
Get_file_code_page_tag endp ;AN000;
;****************************************************************
;*
;* ROUTINE: Set_ext_error_msg
;*
;* FUNCTION: Sets up extended error message for printing
;*
;* INPUT: return from INT 21
;*
;* OUTPUT: extended error message set up in extended error
;* buffer.
;*
;****************************************************************
Set_ext_error_msg proc near ;AN000;
call get_ext_error_number ;AC022; get the extended error
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,ax ;AN000; get message number in control block
stc ;AN000; make sure carry is set
ret ;AN000; return
Set_ext_error_msg endp ;AN000;
;****************************************************************
;*
;* ROUTINE: Get_ext_error_number
;*
;* FUNCTION: Does get extended error function call
;*
;* INPUT: return from INT 21
;*
;* OUTPUT: AX - extended error number
;*
;****************************************************************
Get_ext_error_number proc near ;AN022;
SaveReg <BX,CX,DX,SI,DI,BP,ES,DS> ;AN022; save registers
mov ah,GetExtendedError ;AN022; get extended error
xor bx,bx ;AN022; clear BX
int int_command ;AN022;
RestoreReg <DS,ES,BP,DI,SI,DX,CX,BX> ;AN022; restore registers
ret ;AN022; return
Get_ext_error_number endp ;AN022;
trancode ends
end


View File

@@ -0,0 +1,552 @@
page 80,132
; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25
; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25
TITLE PART5 COMMAND Transient routines.
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comequ.asm
INCLUDE comseg.asm
include ioctl.inc
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf_ptr:word
EXTRN BadCurDrv:byte ;AC000;
EXTRN clsstring:byte
EXTRN dback_ptr:word
EXTRN display_ioctl:word ;AN000;
EXTRN display_width:word ;AN000;
EXTRN Extend_buf_ptr:word ;AN049;
EXTRN linperpag:word ;AN000;
EXTRN msg_disp_class:byte ;AN049;
EXTRN nulpath_ptr:word
EXTRN prompt_table:word
EXTRN string_buf_ptr:word ;AC000;
EXTRN vermes_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN Arg_Buf:byte
EXTRN bwdbuf:byte
EXTRN curdrv:byte
EXTRN dirchar:byte
EXTRN major_ver_num:word
EXTRN minor_ver_num:word
EXTRN srcxname:byte ;AN049;
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
transpace ends
;---------------
EXTRN cerror:near ;AN049;
EXTRN crlf2:near
EXTRN drvbad:near
EXTRN std_printf:near
PUBLIC build_dir_for_chdir
PUBLIC build_dir_for_prompt
PUBLIC build_dir_string
PUBLIC cls
PUBLIC path
PUBLIC print_char
PUBLIC print_drive
PUBLIC print_version
PUBLIC print_b
PUBLIC print_back
PUBLIC print_eq
PUBLIC print_esc
PUBLIC print_g
PUBLIC print_l
PUBLIC print_prompt
PUBLIC version
break Version
assume ds:trangroup,es:trangroup
VERSION:
call crlf2
call print_version
jmp crlf2
print_version:
mov ah,Get_version
int int_command
push ax
xor ah,ah
mov major_ver_num,ax
pop ax
xchg ah,al
xor ah,ah
mov minor_ver_num,ax
mov dx,offset trangroup:vermes_ptr
jmp std_printf
print_prompt:
push ds
push cs
pop ds ; MAKE SURE DS IS IN TRANGROUP
push es
invoke find_prompt ; LOOK FOR PROMPT STRING
jc PP0 ; CAN'T FIND ONE
cmp byte ptr es:[di],0
jnz PP1
PP0:
call print_drive ; USE DEFAULT PROMPT
mov al,sym
call print_char
jmp short PP5
PP1:
mov al,es:[di] ; GET A CHAR
inc di
or al,al
jz PP5 ; NUL TERMINATED
cmp al,dollar ; META CHARACTER?
jz PP2 ; NOPE
PPP1:
call print_char
jmp PP1
PP2:
mov al,es:[di]
inc di
mov bx,offset trangroup:prompt_table-3
or al,al
jz PP5
PP3:
add bx,3
invoke upconv
cmp al,[bx]
jz PP4
cmp byte ptr [bx],0
jnz PP3
jmp PP1
PP4:
push es
push di
push cs
pop es
call [bx+1]
pop di
pop es
jmp PP1
PP5:
pop es ; RESTORE SEGMENTS
pop ds
return
print_back:
mov dx,offset trangroup:dback_ptr
jmp std_printf
print_EQ:
mov al,'='
jmp short print_char
print_esc:
mov al,1BH
jmp short print_char
print_G:
mov al,rabracket
jmp short print_char
print_L:
mov al,labracket
jmp short print_char
print_B:
mov al,vbar
print_char:
push es
push ds
pop es
push di
push dx
mov dl,al ;AC000; Get char into al
mov ah,Std_CON_output ;AC000; print the char to stdout
int int_command ;AC000;
pop dx
pop di
pop es
ret
print_drive:
mov ah,Get_Default_drive
int int_command
add al,capital_A
call print_char
ret
ASSUME DS:TRANGROUP,ES:TRANGROUP
build_dir_for_prompt:
xor dl,dl
mov si,offset trangroup:bwdbuf
mov di,SI
mov al,CurDrv
add al,'A'
mov ah,':'
stosw
mov al,[dirchar]
stosb
xchg si,di
mov string_ptr_2,di
mov ah,Current_dir
int int_command
mov dx,offset trangroup:string_buf_ptr
jnc DoPrint
mov dx,offset trangroup:BadCurDrv
DoPrint:
call std_printf
ret
build_dir_for_chdir:
call build_dir_string
mov dx,offset trangroup:bwdbuf
mov string_ptr_2,dx
mov dx,offset trangroup:string_buf_ptr
call std_printf
ret
build_dir_string:
mov dl,ds:[FCB]
mov al,DL
add al,'@'
cmp al,'@'
jnz gotdrive
add al,[CURDRV]
inc al
gotdrive:
push ax
mov si,offset trangroup:bwdbuf+3
mov ah,Current_dir
int int_command
jnc dpbisok
push cs
pop ds
jmp drvbad
dpbisok:
mov di,offset trangroup:bwdbuf
mov dx,di
pop ax
mov ah,':'
stosw
mov al,[dirchar]
stosb
ret
break Path
assume ds:trangroup,es:trangroup
PATH:
xor al,al ;AN049; Set up holding buffer
mov di,offset Trangroup:srcxname ;AN049; for PATH while parsing
stosb ;AN049; Initialize PATH to null
dec di ;AN049; point to the start of buffer
invoke PGetarg ; Pre scan for arguments
jz disppath ; Print the current path
cmp al,semicolon ;AC049; NUL path argument?
jnz pathslp ;AC049;
inc si ;AN049; point past semicolon
jmp short scan_white ;AC049; Yes - make sure nothing else on line
pathslp: ; Get the user specified path
lodsb ; Get a character
cmp al,end_of_line_in ;AC049; Is it end of line?
jz path_eol ;AC049; yes - end of command
invoke testkanj ;See if DBCS
jz notkanj2 ;No - continue
stosb ;AC049; Yes - store the first byte
lodsb ;skip second byte of DBCS
path_hold: ;AN049;
stosb ;AC049; Store a byte in the PATH buffer
jmp short pathslp ;continue parsing
notkanj2:
invoke upconv ;upper case the character
cmp al,semicolon ;AC049; ';' not a delimiter on PATH
jz path_hold ;AC049; go store it
invoke delim ;delimiter?
jnz path_hold ;AC049; no - go store character
scan_white: ;AN049; make sure were at EOL
lodsb ;AN049; get a character
cmp al,end_of_line_in ;AN049; end of line?
jz path_eol ;AN049; yes - go set path
cmp al,blank ;AN049; whitespace?
jz scan_white ;AN049; yes - continue scanning
cmp al,tab_chr ;AN049; whitespace?
jz scan_white ;AN049; yes - continue scanning
mov dx,offset TranGroup:Extend_Buf_ptr ;AN049; no - set up error message
mov Extend_Buf_ptr,MoreArgs_ptr ;AN049; get "Too many parameters" message number
mov msg_disp_class,parse_msg_class ;AN049; set up parse error msg class
jmp cerror ;AN049;
path_eol: ;AN049; Parsing was clean
xor al,al ;AN049; null terminate the PATH
stosb ;AN049; buffer
invoke find_path ;AN049; Find PATH in environment
invoke delete_path ;AC049; Delete any offending name
invoke scan_double_null ;AC049; Scan to end of environment
invoke move_name ;AC049; move in PATH=
mov si,offset Trangroup:srcxname ;AN049; Set up source as PATH buffer
store_path: ;AN049; Store the PATH in the environment
lodsb ;AN049; Get a character
cmp al,end_of_line_out ;AN049; null character?
jz got_paths ;AN049; yes - exit
invoke store_char ;AN049; no - store character
jmp short store_path ;AN049; continue
got_paths: ;AN049; we're finished
xor ax,ax ;null terminate the PATH in
stosw ; the environment
return
disppath:
invoke find_path ;AN049;
call print_path
call crlf2
return
print_path:
cmp byte ptr es:[di],0
jnz path1
path0:
mov dx,offset trangroup:nulpath_ptr
push cs
pop es
push cs
pop ds
jmp std_printf
path1:
push es
pop ds
sub di,5
mov si,di
ASSUME DS:RESGROUP
invoke scasb2 ; LOOK FOR NUL
cmp cx,0FFH
jz path0
push cs
pop es
mov di,offset trangroup:arg_buf
mov dx,100h
sub dx,cx
xchg dx,cx
rep movsb
mov dx,offset trangroup:arg_buf_ptr
push cs
pop ds
jmp std_printf
ASSUME DS:TRANGROUP
break Cls
; ****************************************************************
; *
; * ROUTINE: CLS
; *
; * FUNCTION: Clear the screen using INT 10h. If ANSI.SYS is
; * installed, send a control string to clear the
; * screen.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
ANSI_installed equ 0ffh
CLS:
mov ah,Mult_ANSI ;AN000; see if ANSI.SYS installed
mov al,0 ;AN000;
int 2fh ;AN000;
cmp al,ANSI_installed ;AN000;
jz ansicls ;AN000; installed - go do ANSI CLS
check_lines:
mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display
mov bx,stdout ;AN000; lines for stdout
mov ch,ioc_sc ;AN000; type is display
mov cl,get_generic ;AN000; get information
mov dx,offset trangroup:display_ioctl ;AN000;
int int_command ;AN000;
jc no_variable ;AN000; function had error, use default
mov ax,linperpag ;AN000; get number of rows returned
mov dh,al ;AN000; set number of rows
mov ax,display_width ;AN000; get number of columns returned
mov dl,al ;AN000; set number of columns
jmp short regcls ;AN000; go do cls
no_variable:
mov bx,stdout ;AC000; set handle as stdout
mov ax,IOCTL SHL 8 ;AC000; do ioctl - get device
int int_command ;AC000; info
test dl,devid_ISDEV ;AC000; is handle a device
jz ANSICLS ;AC000; If a file put out ANSI
test dl,devid_SPECIAL ;AC000;
jnz cls_normal ;AC000; If not special CON, do ANSI
ansicls:
call ansi_cls ;AN000; clear the screen
jmp short cls_ret ;AN000; exit
;
; Get video mode
;
cls_normal: ;AC000;
mov ah,get_video_state ;AC000; set up to get video state
int video_io_int ;AC000; do int 10h - BIOS video IO
cmp al,video_alpha ;AC000; see if in text mode
jbe DoAlpha
cmp al,video_bw ;AC000; see if black & white card
jz DoAlpha
;
; We are in graphics mode. Bogus IBM ROM does not scroll correctly. We will
; be just as bogus and set the mode that we just got. This will blank the
; screen too.
;
mov ah,set_video_mode ;AC000; set video mode call
int video_io_int ;AC000; do int 10h - BIOS video IO
jmp short cls_ret ;AC000; exit
DoAlpha:
;
; Get video mode and number of columns to scroll
;
mov ah,get_video_state ;AC000; set up to get current video state
int video_io_int ;AC000; do int 10h - BIOS video IO
mov dl,ah
mov dh,linesperpage ;AC000; have 25 rows on the screen
regcls:
call reg_cls ;AC000; go clear the screen
cls_ret:
ret ;AC000; exit
; ****************************************************************
; *
; * ROUTINE: REG_CLS
; *
; * FUNCTION: Clear the screen using INT 10H.
; *
; * INPUT: DL = NUMBER OF COLUMNS
; * DH = NUMBER OF ROWS
; *
; * OUTPUT: none
; *
; ****************************************************************
reg_cls proc near ;AC000;
;
; Set overscan to black.
;
dec dh ;AC000; decrement rows and columns
dec dl ;AC000; to zero base
push dx ;AN000; save rows,columns
mov ah,set_color_palette ;AC000; set up to set the color to blank
xor bx,bx
int video_io_int ;AC000; do int 10h - BIOS video IO
pop dx ;AN000; retore rows,colums
xor ax,ax ;AC000; zero out ax
mov CX,ax ;AC000; an cx
;
; Scroll active page
;
mov ah,scroll_video_page ;AC000; set up to scroll page up
mov bh,video_attribute ;AC000; attribute for blank line
xor bl,bl ;AC000; set BL to 0
int video_io_int ;AC000; do int 10h - BIOS video IO
;
; Seek to cursor to 0,0
;
mov ah,set_cursor_position ;AC000; set up to set cursor position
xor dx,dx ;AC000; row and column 0
mov bh,0 ;AC000;
int video_io_int ;AC000; do into 10h - BIOS video IO
ret ;AC000;
reg_cls endp ;AC000;
; ****************************************************************
; *
; * ROUTINE: ANSI_CLS
; *
; * FUNCTION: Clear the screen using by writing a control code
; * to STDOUT.
; *
; * INPUT: none
; *
; * OUTPUT: none
; *
; ****************************************************************
ansi_cls proc near ;AC000;
mov si,offset trangroup:clsstring
lodsb
mov cl,al
xor ch,ch
mov ah,Raw_CON_IO
clrloop:
lodsb
mov DL,al
int int_command
loop clrloop
return
ansi_cls endp ;AC000;
trancode ends
end


View File

@@ -0,0 +1,597 @@
page 80,132
; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22
; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22
TITLE PART5 COMMAND Transient routines.
.xlist
.xcref
INCLUDE comsw.asm
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
EXTRN LODCOM1:NEAR
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN crit_msg_off:word ;AC000;
EXTRN crit_msg_seg:word ;AC000;
EXTRN IO_SAVE:WORD
EXTRN OldTerm:DWORD
EXTRN PARENT:WORD
;AD060; EXTRN pars_msg_off:word ;AC000;
;AD060; EXTRN pars_msg_seg:word ;AC000;
EXTRN PERMCOM:BYTE ;AN045;
EXTRN RetCode:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN ACRLF_PTR:WORD ;AN007;
EXTRN baddev_ptr:word
EXTRN CP_active_Ptr:word
EXTRN CP_not_all_Ptr:word
EXTRN CP_not_set_Ptr:word
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN Extend_buf_sub:byte ;AN000;
EXTRN inv_code_page:word ;AC000;
EXTRN msg_disp_class:byte ;AN000;
EXTRN NLSFUNC_Ptr:word ;AC000;
EXTRN parse_chcp:byte ;AC000;
EXTRN parse_chdir:byte ;AC000;
EXTRN parse_ctty:byte ;AC000;
EXTRN string_buf_ptr:word ;AC000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN COMBUF:BYTE
EXTRN parse_last:word ;AN018;
EXTRN parse1_addr:dword ;AC000;
EXTRN parse1_type:byte ;AC000;
EXTRN RESSEG:WORD
EXTRN srcbuf:byte
EXTRN srcxname:byte ;AC000;
EXTRN string_ptr_2:word
EXTRN system_cpage:word
EXTRN TRAN_TPA:WORD
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
TRANSPACE ENDS
;---------------
EXTRN cerror:near
PUBLIC $exit
PUBLIC chcp
PUBLIC ctty
PUBLIC parse_check_eol ;AN000;
PUBLIC parse_with_msg ;AN018;
PUBLIC setup_parse_error_msg ;AN018;
PUBLIC truename ;AN000;
break Ctty
assume ds:trangroup,es:trangroup
; ****************************************************************
; *
; * ROUTINE: CTTY - Change console
; *
; * SYNTAX: CTTY device
; *
; * FUNCTION: If a valid console device is specified, CTTY will
; * duplicate the device handle to STDIN, STDOUT and
; * STDERR. This routine returns to LODCOM1.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
CTTY:
push ds ;AN000; Get local ES
pop es ;AN000;
mov si,81H ;AC000; Get command argument for CTTY
mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY
xor cx,cx ;AC000; clear cx,dx
xor dx,dx ;AC000;
invoke cmd_parse ;AC000; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jz ctty_error ;AN000; yes - error
cmp ax,result_no_error ;AN000; did an error occur
jnz ctty_error ;AN000; YES -ERROR
push si ;AN000; save position in line
lds si,parse1_addr ;AN000; get address of filespec
mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf
ctty_move_filename: ;AN000; put filespec in srcbuf
lodsb ;AN000; get a char from buffer
stosb ;AN000; store in srcbuf
cmp al,end_of_line_out ;AN000; it char a terminator?
jnz ctty_move_filename ;AN000; no - keep moving
pop si ;AN000; get line position back
mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY
call parse_check_eol ;AN000; are we at end of line?
jz nocolon ;AN000; yes - continue
ctty_error:
jmp isbaddev ;AC000; yes - exit
nocolon:
mov dx,offset trangroup:srcbuf ;AN000; get address of srcbuf
MOV AX,(OPEN SHL 8) OR 2 ; Read and write
INT int_command ; Open new device
JC ISBADDEV
MOV BX,AX
MOV AX,IOCTL SHL 8
INT int_command
TEST DL,80H
JNZ DEVISOK
CLOSEDEV: ;AN007;
MOV AH,CLOSE ; Close initial handle
INT int_command
ISBADDEV:
MOV DX,OFFSET TRANGROUP:BADDEV_ptr
invoke std_printf
JMP RESRET
DEVISOK:
push dx ;AN007; save device info
mov ax,acrlf_ptr ;AN021; get message number for 0d, 0a
mov dh,util_msg_class ;AN021; this is a utility message
push bx ;AN021; save handle
invoke Tsysgetmsg ;AN021; get the address of the message
mov dx,si ;AN021; get address into dx
mov ax,(write shl 8) ;AN007; write to device
mov cx,2 ;AN007; write two bytes
int int_command ;AN007;
pop bx ;AN021; get back handle
pop dx ;AN007; get back device info
jc closedev ;AN007; if error, quit
XOR DH,DH
OR DL,3 ; Make sure has CON attributes
MOV AX,(IOCTL SHL 8) OR 1
INT int_command
PUSH BX ; Save handle
MOV CX,3
XOR BX,BX
ICLLOOP: ; Close basic handles
MOV AH,CLOSE
INT int_command
INC BX
LOOP ICLLOOP
POP BX ; Get handle
MOV AH,XDUP
INT int_command ; Dup it to 0
MOV AH,XDUP
INT int_command ; Dup to 1
MOV AH,XDUP
INT int_command ; Dup to 2
MOV AH,CLOSE ; Close initial handle
INT int_command
RESRET:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
PUSH DS
MOV AX,WORD PTR DS:[PDB_JFN_Table] ; Get new 0 and 1
MOV [IO_SAVE],AX
MOV AX,OFFSET RESGROUP:LODCOM1
PUSH AX
ZMMMM PROC FAR
RET ; Force header to be checked
ZMMMM ENDP
break Chcp
;****************************************************************
;*
;* ROUTINE: CHCP - Change code page internal command
;* (added DOS 3.30 07/21/86)
;*
;* SYNTAX: CHCP [xxx]
;* where xxx is a valid code page
;*
;* FUNCTION: If xxx is specified, CHCP will use INT 21H function
;* 6402H to set the code page to xxxx. If no parameters
;* are specified, CHCP will use INT 21H function 6401H
;* to get global code page and display it to the user.
;*
;* INPUT: command line at offset 81H
;*
;* OUTPUT: none
;*
;****************************************************************
NLSFUNC_installed equ 0ffh
set_global_cp equ 2
get_global_cp equ 1
assume ds:trangroup,es:trangroup
CHCP:
push ds ;AN000; Get local ES
pop es ;AN000;
mov si,81H ;AC000; Get command argument for CHCP
mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP
xor cx,cx ;AC000; clear cx,dx
xor dx,dx ;AC000;
call parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jnz setcp ;AC000; no go get number & set code page
jmp getcp ;AC000; yes - no parm - get code page
setcp:
cmp ax,result_no_error ;AN000; did we have an error?
jne cp_error ;AC018; yes - go issue message
push cx ;AN000; save positional count
mov bx,offset trangroup:parse1_addr ;AN000; get number returned
mov cx,word ptr [bx] ;AN000; into cx
mov system_cpage,cx ;AN000; save user input number
pop cx ;AC000; restore positional count
mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP
call parse_check_eol ;AN000; are we at end of line?
jnz cp_error ;AC000; no - exit
okset:
mov ah,NLSFUNC ;AN000; see if NLSFUNC installed
mov al,0 ;AN000;
int 2fh ;AN000;
cmp al,NLSFUNC_installed ;AN000;
jz got_NLS ;AN000; Yes - continue
mov dx,offset trangroup:NLSFUNC_ptr ;AN000; no - set up error message
jmp short cp_error ;AN000; error exit
got_NLS:
mov bx,system_cpage ;AN000; get user input code page
mov ah,getsetcdpg ;get/set global code page function
mov al,set_global_cp ;minor - set
int int_command
jnc chcp_return ;no error - exit
;
;added for p716
;
cmp ax,error_file_not_found ;p716 was the error file not found?
jnz chcp_other_error ;no - country.sys was found
mov ah,GetExtendedError ;p850 see if error is invalid data
xor bx,bx ; which is file was found but CP
int int_command ; information was not found.
cmp ax,error_invalid_data ;AC000; invalid code page
jnz no_countrysys ;no - use file not found
mov dx,offset trangroup:inv_code_page ;AN000; get message
jmp short cp_error ;AC000; error exit
no_countrysys:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block
jmp short cp_error ;AC000; error exit
chcp_other_error:
;
; end of p716
;
mov ah,GetExtendedError ;error - see what it is
xor bx,bx
int int_command
cmp ax,65 ;was it access denied?
jnz none_set ;no - assume all failed
mov dx,offset trangroup:cp_not_all_ptr ;set up message
jmp short cp_error ;AC000; error exit
none_set:
mov dx,offset trangroup:cp_not_set_ptr ;set up message
cp_error: ;AN000;
jmp cerror ;exit
getcp:
mov ah,getsetcdpg ;get/set global code page function
mov al,get_global_cp ;minor - get
int int_command
mov system_cpage,bx ;get active cp for output
mov dx,offset trangroup:cp_active_ptr
invoke std_printf ;print it out
chcp_return:
RET
break TRUENAME ;AN000;
; ****************************************************************
; *
; * ROUTINE: TRUENAME
; *
; * FUNCTION: Entry point for the internal TRUENAME command.
; * Parses the command line. If a path is found, set
; * SRCXNAME to path. If only a drive letter is
; * found, set SRCXNAME to the drive letter. If
; * no path is found, set the path of SRCXNAME to
; * dot (.) for current directory. Use the NAME
; * TRANSLATE system call to get the real name and
; * then display the real name. If an error occurs
; * issue an error message and transfer control to
; * CERROR.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup ;AN000;
TRUENAME: ;AN000; TRUENAME entry point
push ds ;AN000; Get local ES
pop es ;AN000;
mov si,81H ;AN000; Get command line
mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
call parse_with_msg ;AC018; call parser
mov di,offset trangroup:srcxname ;AN000; get address of srcxname
cmp ax,end_of_line ;AN000; are we at end of line?
je tn_eol ;AN000; yes - go process
cmp ax,result_no_error ;AN000; did we have an error?
jne tn_parse_error ;AN000; yes - go issue message
cmp parse1_type,result_drive ;AN000; was a drive entered?
je tn_drive ;AN000; yes - go process
jmp short tn_filespec ;AN000; nothing else - must be filespec
tn_eol: ;AN000; no parameters on line
mov ah,end_of_line_out ;AN000; set buffer to .
mov al,dot_chr ;AN000; for current dir
stosw ;AN000; store in srcxname
jmp short tn_doit ;AN000; go do command
tn_drive: ;AN000; a drive was entered
push si ;AN000; save position in line
mov si,offset trangroup:parse1_addr ;AN000; get address of drive
lodsb ;AN000; get the drive number
add al,"A"-1 ;AN000; convert it to char
stosb ;AN000; store it in srcxname
mov ax,dot_colon ;AN000; get colon and . and
stosw ;AN000; store in srcxname
mov al,end_of_line_out ;AN000; put a terminator char
stosb ;AN000;
pop si ;AN000; get line position back
jmp short tn_check_eol ;AN000; check to make sure eol
tn_filespec: ;AN000; a filespec was entered
push si ;AN000; save position in line
lds si,parse1_addr ;AN000; get address of filespec
tn_move_filename: ;AN000; put filespec in srcxname
lodsb ;AN000; get a char from buffer
stosb ;AN000; store in srcxname
cmp al,end_of_line_out ;AN000; it char a terminator?
jnz tn_move_filename ;AN000; no - keep moving
pop si ;AN000; get line position back
tn_check_eol: ;AN000; make sure no extra parms
mov di,offset trangroup:parse_chdir ;AN000; get address of parse_chdir
call parse_check_eol ;AN000; are we at end of line?
je tn_doit ;AN000; Yes - do the command
tn_parse_error: ;AN000; A parse error occurred
jmp cerror ;AN000; Go to error routine
tn_doit: ;AN000;
mov si,offset trangroup:srcxname ;AN000; set up srcxname as source
mov di,offset trangroup:combuf ;AN000; set up combuf as target (need big target)
mov ah,xnametrans ;AN000; do name translate call
int int_command ;AN000;
jnc tn_print_xname ;AN000; If no error - print result
invoke Set_ext_error_msg ;AN000; get extended message
mov string_ptr_2,offset trangroup:srcxname ;AN000; get address of failed string
mov Extend_buf_sub,one_subst ;AN000; put number of subst in control block
jmp cerror ;AN000; Go to error routine
tn_print_xname: ;AN000;
mov string_ptr_2,offset Trangroup:combuf ;AN000; Set up address of combuf
mov dx,offset trangroup:string_buf_ptr ;AN000; Set up address of print control block
invoke crlf2 ;AN000; print a crlf
invoke printf_crlf ;AN000; print it out
ret ;AN000;
break $Exit
assume ds:trangroup,es:trangroup
$EXIT:
push ds ;AN000; save data segment
mov ds,[resseg] ;AN000; get resident data segment
assume ds:resgroup ;AN000;
cmp [permcom],0 ;AN045; is this a permanent COMMAND?
jnz no_reset ;AN045; Yes - don't do anything
;AD060; mov ah,multdos ;AN000; reset parse message pointers
;AD060; mov al,message_2f ;AN000; call for message retriever
;AD060; mov dl,set_parse_msg ;AN000; set up parse message address
;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages
;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages
;AD060; int 2fh ;AN000; go set it
;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh
;AD060; mov al,message_2f ;AN000; call for message retriever
mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers
mov dl,set_critical_msg ;AN000; set up critical error message address
mov di,crit_msg_off ;AN000; old offset of critical messages
mov es,crit_msg_seg ;AN000; old segment of critical messages
int 2fh ;AN000; go set it
no_reset: ;AN045;
pop ds ;AN000; restore local data segment
assume ds:trangroup ;AN000;
MOV ES,[RESSEG]
assume es:resgroup
MOV AX,[PARENT]
MOV WORD PTR ES:[PDB_Parent_PID],AX
MOV AX,WORD PTR OldTerm
MOV WORD PTR ES:[PDB_Exit],AX
MOV AX,WORD PTR OldTerm+2
MOV WORD PTR ES:[PDB_Exit+2],AX
PUSH ES
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT int_command ; Now running in "free" space
POP ES
MOV AH,Exit
MOV AL,BYTE PTR RetCode
INT int_command
; ****************************************************************
; *
; * ROUTINE: PARSE_CHECK_EOL
; *
; * FUNCTION: Calls parser to see if end of line occurred.
; * If not end of line, set up to print parse
; * error message. ASSUMES NO MORE PARAMETERS ARE
; * EXPECTED!
; *
; * INPUT: DS:SI last output from parser
; * ES:DI points to parse block
; * CX last output from parser
; *
; * OUTPUT: AX parser return code
; *
; * if end of line found
; * zero flag set
; * else
; * MSG_DISPLAY_CLASS set to parse error
; *
; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN000;
parse_check_eol Proc near ;AN000;
xor dx,dx ;AN000;
mov [parse_last],si ;AN018; save start of parameter
invoke cmd_parse ;AN000; call parser
cmp al,end_of_line ;AN000; Are we at end of line?
jz parse_good_eol ;AN000; yes - no problem
cmp ax,result_no_error ;AN018; was any error found?
jnz ok_to_setup_pmsg ;AN018; yes - continue
inc ax ;AN018; set AX to 1 and turn off zero flag
ok_to_setup_pmsg:
call setup_parse_error_msg ;AN018; go set up error message
parse_good_eol:
ret ;AN000;
parse_check_eol endp ;AN000;
; ****************************************************************
; *
; * ROUTINE: PARSE_WITH_MSG
; *
; * FUNCTION: Calls parser. If an error occurred, the error
; * message is set up.
; *
; * INPUT: DS:SI last output from parser
; * ES:DI points to parse block
; * CX last output from parser
; *
; * OUTPUT: AX parser return code
; *
; * if no error
; * outputs from parser
; * else
; * MSG_DISPLAY_CLASS set to parse error
; * error message set up for STD_PRINTF
; *
; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018;
parse_with_msg Proc near ;AN018;
mov [parse_last],si ;AN018; save start of parameter
invoke cmd_parse ;AN018; call parser
cmp al,end_of_line ;AN018; Are we at end of line?
jz parse_msg_good ;AN018; yes - no problem
cmp ax,result_no_error ;AN018; did an error occur
jz parse_msg_good ;AN018; yes - no problem
call setup_parse_error_msg ;AN018; go set up error message
parse_msg_good:
ret ;AN018;
parse_with_msg endp ;AN018;
; ****************************************************************
; *
; * ROUTINE: SETUP_PARSE_ERROR_MSG
; *
; * FUNCTION: Calls parser. If an error occurred, the error
; * message is set up.
; *
; * INPUT: AX Parse error number
; * SI Set to past last parameter
; * Parse_last Set to start of last parameter
; *
; * OUTPUT: MSG_DISPLAY_CLASS set to parse error
; * error message set up for STD_PRINTF
; *
; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018;
SETUP_PARSE_ERROR_MSG Proc near ;AN018;
mov msg_disp_class,parse_msg_class ;AC018; Set up parse message class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC018; get extended message pointer
mov byte ptr [si],end_of_line_out ;AC018; terminate the parameter string
mov Extend_Buf_ptr,ax ;AC018; get message number in control block
cmp ax,lessargs_ptr ;AC018; if required parameter missing
jz Setup_parse_msg_ret ;AN018; no subst
mov si,[parse_last] ;AC018; get start of parameter
mov string_ptr_2,si ;AC018; get address of failed string
mov Extend_buf_sub,one_subst ;AC018; put number of subst in control block
setup_parse_msg_ret:
inc si ;AN018; make sure zero flag not set
ret ;AC018;
SETUP_PARSE_ERROR_MSG Endp ;AN018;
trancode ends
end

View File

@@ -0,0 +1,540 @@
page 80,132
; SCCSID = @(#)tcode.asm 1.1 85/05/14
; SCCSID = @(#)tcode.asm 1.1 85/05/14
TITLE Part1 COMMAND Transient Routines
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
EXTRN EXEC_WAIT:NEAR
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN BATCH:WORD
EXTRN CALL_BATCH_FLAG:byte
EXTRN CALL_FLAG:BYTE
EXTRN ECHOFLAG:BYTE
EXTRN envirseg:word
EXTRN EXTCOM:BYTE
EXTRN FORFLAG:BYTE
EXTRN IFFLAG:BYTE
EXTRN next_batch:word
EXTRN nullflag:byte
EXTRN PIPEFILES:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE
EXTRN RESTDIR:BYTE
EXTRN SINGLECOM:WORD
EXTRN VERVAL:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BadNam_Ptr:word ;AC000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN APPEND_EXEC:BYTE ;AN041;
EXTRN ARG1S:WORD
EXTRN ARG2S:WORD
EXTRN ARGTS:WORD
EXTRN BYTCNT:WORD
EXTRN COMBUF:BYTE
EXTRN COMSW:WORD
EXTRN CURDRV:BYTE
EXTRN HEADCALL:DWORD
EXTRN IDLEN:BYTE
EXTRN INTERNATVARS:BYTE
EXTRN PARM1:BYTE
EXTRN PARM2:BYTE
EXTRN RE_INSTR:BYTE
EXTRN RESSEG:WORD
EXTRN SPECDRV:BYTE
EXTRN STACK:WORD
EXTRN SWITCHAR:BYTE
EXTRN TPA:WORD
EXTRN UCOMBUF:BYTE
EXTRN USERDIR1:BYTE
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
TRANSPACE ENDS
; ********************************************************************
; START OF TRANSIENT PORTION
; This code is loaded at the end of memory and may be overwritten by
; memory-intensive user programs.
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN $EXIT:NEAR
EXTRN DRVBAD:NEAR
EXTRN EXTERNAL:NEAR
EXTRN FNDCOM:NEAR
EXTRN FORPROC:NEAR
EXTRN PIPEPROC:NEAR
EXTRN PIPEPROCSTRT:NEAR
PUBLIC COMMAND
PUBLIC DOCOM
PUBLIC DOCOM1
PUBLIC NOPIPEPROC
PUBLIC TCOMMAND
IF IBM
PUBLIC ROM_EXEC
PUBLIC ROM_SCAN
ENDIF
ORG 0
ZERO = $
ORG 100H ; Allow for 100H parameter area
SETDRV:
MOV AH,SET_DEFAULT_DRIVE
INT int_command
;
; TCOMMAND is the recycle point in COMMAND. Nothing is known here.
; No registers (CS:IP) no flags, nothing.
;
TCOMMAND:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AX,-1
XCHG AX,[VERVAL]
CMP AX,-1
JZ NOSETVER2
MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
INT int_command
NOSETVER2:
CALL [HEADCALL] ; Make sure header fixed
XOR BP,BP ; Flag transient not read
CMP [SINGLECOM],-1
JNZ COMMAND
$EXITPREP:
PUSH CS
POP DS
JMP $EXIT ; Have finished the single command
ASSUME DS:NOTHING
;
; Main entry point from resident portion.
;
; If BP <> 0, then we have just loaded transient portion otherwise we are
; just beginning the processing of another command.
;
COMMAND:
;
; We are not always sure of the state of the world at this time. We presume
; worst case and initialize the relevant registers: segments and stack.
;
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
CLD
MOV AX,CS
CLI
MOV SS,AX
ASSUME SS:TRANGROUP
MOV SP,OFFSET TRANGROUP:STACK
STI
MOV ES,AX
MOV DS,AX ;AN000; set DS to transient
ASSUME ES:TRANGROUP,DS:TRANGROUP ;AC000;
invoke TSYSLOADMSG ;AN000; preload messages
invoke SETSTDINOFF ;AN026; turn off critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
mov append_exec,0 ;AN041; set internal append state off
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF
MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE)
;
; If we have just loaded the transient, then we do NOT need to initialize the
; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I
; guess not: the only circumstances in which we reload the command processor
; is after a transient program execution. In this case, we let the current
; directory lie where it may.
;
OR BP,BP ; See if just read
JZ TESTRDIR ; Not read, check user directory
MOV WORD PTR [UCOMBUF+1],0D01H ; Reset buffer
JMP SHORT NOSETBUF
TESTRDIR:
CMP [RESTDIR],0
JZ NOSETBUF ; User directory OK
PUSH DS
;
; We have an unusual situation to handle. The user *may* have changed his
; directory as a result of an internal command that got aborted. Restoring it
; twice may not help us: the problem may never go away. We just attempt it
; once and give up.
;
MOV [RESTDIR],0 ; Flag users dirs OK
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:USERDIR1
MOV AH,CHDIR
INT int_command ; Restore users directory
POP DS
ASSUME DS:RESGROUP
NOSETBUF:
CMP [PIPEFILES],0
JZ NOPCLOSE ; Don't bother if they don't exist
CMP [PIPEFLAG],0
JNZ NOPCLOSE ; Don't del if still piping
INVOKE PIPEDEL
NOPCLOSE:
MOV [EXTCOM],0 ; Flag internal command
MOV AX,CS ; Get segment we're in
MOV DS,AX
ASSUME DS:TRANGROUP
PUSH AX
MOV DX,OFFSET TRANGROUP:INTERNATVARS
MOV AX,INTERNATIONAL SHL 8
INT 21H
POP AX
SUB AX,[TPA] ; AX=size of TPA in paragraphs
PUSH BX
MOV BX,16
MUL BX ; DX:AX=size of TPA in bytes
POP BX
OR DX,DX ; See if over 64K
JZ SAVSIZ ; OK if not
MOV AX,-1 ; If so, limit to 65535 bytes
SAVSIZ:
;
; AX is the number of bytes free in the buffer between the resident and the
; transient with a maximum of 64K-1. We round this down to a multiple of 512.
;
CMP AX,512
JBE GotSize
AND AX,0FE00h ; NOT 511 = NOT 1FF
GotSize:
MOV [BYTCNT],AX ; Max no. of bytes that can be buffered
MOV DS,[RESSEG] ; All batch work must use resident seg.
ASSUME DS:RESGROUP
TEST [ECHOFLAG],1
JZ GETCOM ; Don't do the CRLF
INVOKE SINGLETEST
JB GETCOM
TEST [PIPEFLAG],-1
JNZ GETCOM
TEST [FORFLAG],-1 ; G Don't print prompt in FOR
JNZ GETCOM ; G
TEST [BATCH], -1 ; G Don't print prompt if in batch
JNZ GETCOM ; G
INVOKE CRLF2
GETCOM:
MOV CALL_FLAG,0 ; G Reset call flags
MOV CALL_BATCH_FLAG,0 ; G
MOV AH,GET_DEFAULT_DRIVE
INT int_command
MOV [CURDRV],AL
TEST [PIPEFLAG],-1 ; Pipe has highest presedence
JZ NOPIPE
JMP PIPEPROC ; Continue the pipeline
NOPIPE:
TEST [ECHOFLAG],1
JZ NOPDRV ; No prompt if echo off
INVOKE SINGLETEST
JB NOPDRV
TEST [FORFLAG],-1 ; G Don't print prompt in FOR
JNZ NOPDRV ; G
TEST [BATCH], -1 ; G Don't print prompt if in batch
JNZ TESTFORBAT ; G
INVOKE PRINT_PROMPT ; Prompt the user
NOPDRV:
TEST [FORFLAG],-1 ; FOR has next highest precedence
JZ TESTFORbat
JMP FORPROC ; Continue the FOR
TESTFORBAT:
MOV [RE_INSTR],0 ; Turn redirection back off
MOV [RE_OUTSTR],0
MOV [RE_OUT_APP],0
MOV IFFlag,0 ; no more ifs...
TEST [BATCH],-1 ; Batch has lowest precedence
JZ ISNOBAT
push es ;AN000; save ES
push ds ;AN000; save DS
mov ax,mult_shell_get ;AN000; check to see if SHELL has command
mov es,[batch] ;AN000; get batch segment
mov di,batfile ;AN000; get batch file name
push cs ;AN000; get local segment to DS
pop ds ;AN000;
mov dx,offset trangroup:combuf ;AN000; pass communications buffer
int 2fh ;AN000; call the shell
cmp al,shell_action ;AN000; does shell have a commmand?
pop ds ;AN000; restore DS
pop es ;AN000; restore ES
jz jdocom1 ;AN000; yes - go process command
PUSH DS ;G
INVOKE READBAT ; Continue BATCH
POP DS ;G
mov nullflag,0 ;G reset no command flag
TEST [BATCH],-1 ;G
JNZ JDOCOM1 ;G if batch still in progress continue
MOV BX,NEXT_BATCH ;G
CMP BX,0 ;G see if there is a new batch file
JZ JDOCOM1 ;G no - go do command
MOV BATCH,BX ;G get segment of next batch file
MOV NEXT_BATCH,0 ;G reset next batch
JDOCOM1:
PUSH CS ;G
POP DS ;G
JMP SHORT DoCom1 ; echoing already done
ISNOBAT:
CMP [SINGLECOM],0
JZ REGCOM
MOV SI,-1
XCHG SI,[SINGLECOM]
MOV DI,OFFSET TRANGROUP:COMBUF + 2
XOR CX,CX
SINGLELOOP:
LODSB
STOSB
INC CX
CMP AL,0DH
JNZ SINGLELOOP
DEC CX
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV [COMBUF + 1],CL
;
; do NOT issue a trailing CRLF...
;
JMP DOCOM1
;
; We have a normal command.
; Printers are a bizarre quantity. Sometimes they are a stream and
; sometimes they aren't. At this point, we automatically close all spool
; files and turn on truncation mode.
;
REGCOM:
MOV AX,(ServerCall SHL 8) + 9
INT 21h
MOV AX,(ServerCall SHL 8) + 8
MOV DL,1
INT 21h
PUSH CS
POP DS ; Need local segment to point to buffer
MOV DX,OFFSET TRANGROUP:UCOMBUF
MOV AH,STD_CON_STRING_INPUT
INT int_command ; Get a command
MOV CL,[UCOMBUF]
XOR CH,CH
ADD CX,3
MOV SI,OFFSET TRANGROUP:UCOMBUF
MOV DI,OFFSET TRANGROUP:COMBUF
REP MOVSB ; Transfer it to the cooked buffer
;---------------
transpace segment
extrn arg:byte ; the arg structure!
transpace ends
;---------------
DOCOM:
INVOKE CRLF2
DOCOM1:
INVOKE PRESCAN ; Cook the input buffer
JZ NOPIPEPROC
JMP PIPEPROCSTRT ; Fire up the pipe
nullcomj:
jmp nullcom
NOPIPEPROC:
invoke parseline
jnc OkParse ; user error? or maybe we goofed?
BadParse:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
INVOKE std_eprintf
JMP TCOMMAND
OkParse:
test arg.argv[0].argflags, MASK wildcard
jnz BadParse ; ambiguous commands not allowed
cmp arg.argvcnt, 0 ; there WAS a command, wasn't there?
jz nullcomj
cmp arg.argv[0].arglen, 0 ; probably an unnecessary check...
jz nullcomj ; guarantees argv[0] at least x<NULL>
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,OFFSET TRANGROUP:IDLEN
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H ; Make FCB with blank scan-off
INT int_command
mov BX, arg.argv[0].argpointer
cmp BYTE PTR [BX+1],':' ; was a drive specified?
jne short drvgd ; no, use default of zero...
mov DL, BYTE PTR [BX] ; pick-up drive letter
and DL, NOT 20H ; uppercase the sucker
sub DL, capital_A ; convert it to a drive number, A=0
CMP AL,-1 ; See what PARSE said about our drive letter.
JZ drvbadj2 ; It was invalid.
mov DI, arg.argv[0].argstartel
cmp BYTE PTR [DI], 0 ; is there actually a command there?
jnz drvgd ; if not, we have: "d:", "d:\", "d:/"
jmp setdrv ; and set drive to new drive spec
drvbadj2:
jmp drvbad
DRVGD:
MOV AL,[DI]
MOV [SPECDRV],AL
MOV AL,' '
MOV CX,9
INC DI
REPNE SCASB ; Count no. of letters in command name
MOV AL,8
SUB AL,CL
MOV [IDLEN],AL ; IDLEN is truly the length
MOV DI,81H
PUSH SI
mov si, OFFSET TRANGROUP:COMBUF+2 ; Skip over all leading delims
invoke scanoff
do_skipcom:
lodsb ; move command line pointer over
invoke delim ; pathname -- have to do it ourselves
jz do_skipped ; 'cause parse_file_descriptor is dumb
cmp AL, 0DH ; can't always depend on argv[0].arglen
jz do_skipped ; to be the same length as the user-
cmp AL, [SWITCHAR] ; specified command string
jnz do_skipcom
do_skipped:
dec SI
XOR CX,CX
COMTAIL:
LODSB
STOSB ; Move command tail to 80H
CMP AL,13
LOOPNZ COMTAIL
DEC DI
MOV BP,DI
NOT CL
MOV BYTE PTR DS:[80H],CL
POP SI
;-----
; Some of these comments are sadly at odds with this brave new code.
;-----
; If the command has 0 parameters must check here for
; any switches that might be present.
; SI -> first character after the command.
mov DI, arg.argv[0].argsw_word
mov [COMSW], DI ; ah yes, the old addressing mode problem...
mov SI, arg.argv[1 * SIZE argv_ele].argpointer ; s = argv[1];
OR SI,SI ; if (s == NULL)
JNZ DoParse
MOV SI,BP ; s = bp; (buffer end)
DoParse:
MOV DI,FCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT int_command
MOV [PARM1],AL ; Save result of parse
mov DI, arg.argv[1*SIZE argv_ele].argsw_word
mov [ARG1S], DI
mov SI, arg.argv[2*SIZE argv_ele].argpointer ; s = argv[2];
OR SI,SI ; if (s == NULL)
JNZ DoParse2
MOV SI,BP ; s = bp; (bufend)1
DoParse2:
MOV DI,FCB+10H
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT int_command ; Parse file name
MOV [PARM2],AL ; Save result
mov DI, arg.argv[2*SIZE argv_ele].argsw_word
mov [ARG2S], DI
mov DI, arg.argv[0].argsw_word
not DI ; ARGTS doesn't include the flags
and DI, arg.argswinfo ; from COMSW...
mov [ARGTS], DI
MOV AL,[IDLEN]
MOV DL,[SPECDRV]
or DL, DL ; if a drive was specified...
jnz externalj1 ; it MUST be external, by this time
dec al ; (I don't know why -- old code did it)
jmp fndcom ; otherwise, check internal com table
externalj1:
jmp external
nullcom:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
TEST [BATCH], -1 ;G Are we in a batch file?
JZ nosetflag ;G only set flag if in batch
mov nullflag,nullcommand ;G set flag to indicate no command
nosetflag:
CMP [SINGLECOM],-1
JZ EXITJ
JMP GETCOM
EXITJ:
JMP $EXITPREP
IF IBM
include mshalo.asm
ENDIF
TRANCODE ENDS
END

View File

@@ -0,0 +1,777 @@
page 80,132
; SCCSID = @(#)tdata.asm 4.3 85/05/17
; SCCSID = @(#)tdata.asm 4.3 85/05/17
TITLE COMMAND Transient Initialized DATA
; MODIFICATION HISTORY
;
; EE 10-20-83 Changed the drive check indicator bytes (DCIB's) in
; COMTAB to be a flag byte in which bit 0 is now the
; DCIB(bit) and bit 1 is on if the command can take
; switches.
fmt macro name,string,args
local a
a db string
PUBLIC name
name dw offset trangroup:a
irp val,<args>
dw offset trangroup:val
endm
endm
btab macro b,sym
db b
dw offset trangroup:sym
endm
.xlist
.xcref
INCLUDE comsw.asm ;AC000;
INCLUDE comseg.asm
INCLUDE EA.inc ;AN030;
INCLUDE dirent.inc ;AN042;
.list
.cref
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
;
; WARNING: DO NOT INCLUDE DOSSYM.INC BECAUSE IT DESTROYS THE MACRO 'FMT' THAT
; has been defined above - RS.
;
INCLUDE CURDIR.INC
INCLUDE ERROR.INC
INCLUDE ifequ.asm
INCLUDE comequ.asm
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf:BYTE
EXTRN bwdbuf:byte
EXTRN bytes_free:WORD
EXTRN charbuf:byte
EXTRN copy_Num:WORD
EXTRN cpyflag:BYTE
EXTRN DATE_OUTPUT:BYTE ;AC000;
EXTRN Dir_Num:WORD
EXTRN DRIVE_OUTPUT:BYTE ;AC000;
EXTRN file_size_high:WORD
EXTRN file_size_low:WORD
EXTRN major_ver_num:WORD
EXTRN minor_ver_num:WORD
EXTRN one_char_val:BYTE
EXTRN PARSE1_OUTPUT:BYTE ;AC000;
EXTRN srcbuf:byte
EXTRN string_ptr_2:WORD
EXTRN system_cpage:word
EXTRN TIME_OUTPUT:BYTE ;AC000;
EXTRN vol_drv:BYTE
EXTRN vol_serial:dword ;AN000;
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
EXTRN $CALL:NEAR
EXTRN $CHDIR:NEAR
EXTRN $EXIT:NEAR
EXTRN $FOR:NEAR
EXTRN $IF:NEAR
EXTRN $MKDIR:NEAR
EXTRN $RMDIR:NEAR
EXTRN ADD_NAME_TO_ENVIRONMENT:NEAR
EXTRN ADD_PROMPT:NEAR
EXTRN build_dir_for_prompt:near
EXTRN CATALOG:NEAR
EXTRN CHCP:NEAR
EXTRN CLS:NEAR
EXTRN CNTRLC:NEAR
EXTRN COPY:NEAR
EXTRN CRENAME:NEAR
EXTRN CRLF2:NEAR
EXTRN CTIME:NEAR
EXTRN CTTY:NEAR
EXTRN DATE:NEAR
EXTRN ECHO:NEAR
EXTRN ERASE:NEAR
EXTRN GOTO:NEAR
EXTRN IFERLEV:NEAR
EXTRN IFEXISTS:NEAR
EXTRN IFNOT:NEAR
EXTRN PATH:NEAR
EXTRN PAUSE:NEAR
EXTRN PRINT_B:NEAR
EXTRN PRINT_BACK:NEAR
EXTRN PRINT_DATE:NEAR
EXTRN PRINT_CHAR:NEAR
EXTRN PRINT_DRIVE:NEAR
EXTRN PRINT_EQ:NEAR
EXTRN PRINT_ESC:NEAR
EXTRN PRINT_G:NEAR
EXTRN PRINT_L:NEAR
EXTRN PRINT_TIME:NEAR
EXTRN PRINT_VERSION:NEAR
EXTRN SHIFT:NEAR
EXTRN TCOMMAND:NEAR
EXTRN TRUENAME:NEAR ;AN000;
EXTRN TYPEFIL:NEAR
EXTRN VERSION:NEAR
EXTRN VOLUME:NEAR
EXTRN VERIFY:NEAR
;
; WARNING!!! No code may appear after this label!!!!
;
PUBLIC TranCodeLast
TranCodeLast LABEL BYTE
TRANCODE ENDS
; Data for transient portion
TRANDATA SEGMENT PUBLIC BYTE
PUBLIC accden_ptr ;AN000;
PUBLIC acrlf_ptr ;AN000;
PUBLIC arg_buf_ptr ;AN000;
PUBLIC badbat_ptr ;AN000;
PUBLIC badcd_ptr ;AN000;
PUBLIC badCPmes_ptr ;AN000;
PUBLIC badcurdrv ;AN000;
PUBLIC baddat_ptr ;AN000;
PUBLIC baddev_ptr ;AN000;
PUBLIC baddrv_ptr ;AN000;
PUBLIC badlab_ptr ;AN000;
PUBLIC badmkd_ptr ;AN000;
PUBLIC badnam_ptr ;AN000;
PUBLIC bad_on_off_ptr ;AN000;
PUBLIC badPmes_ptr ;AN000;
PUBLIC badrmd_ptr ;AN000;
PUBLIC badtim_ptr ;AN000;
PUBLIC batext
PUBLIC bytmes_ptr ;AN000;
PUBLIC CLSSTRING
PUBLIC comext
PUBLIC COMSPECSTR
PUBLIC COMTAB
PUBLIC copied_ptr ;AN000;
PUBLIC cp_active_ptr ;AN000;
PUBLIC cp_not_all_ptr ;AN000;
PUBLIC cp_not_set_ptr ;AN000;
PUBLIC ctrlcmes_ptr ;AN000;
PUBLIC curdat_mo_day ;AN000;
PUBLIC curdat_ptr ;AN000;
PUBLIC curdat_yr ;AN000;
PUBLIC curtim_hr_min ;AN000;
PUBLIC curtim_ptr ;AN000;
PUBLIC curtim_sec_hn ;AN000;
PUBLIC dback_ptr ;AN000;
PUBLIC del_Y_N_ptr ;AN000;
PUBLIC devwmes_ptr ;AN000;
PUBLIC dirdattim_ptr ;AN000;
PUBLIC dirdat_mo_day ;AN000;
PUBLIC dirdat_yr ;AN000;
PUBLIC dirhead_ptr ;AN000;
PUBLIC dirmes_ptr ;AN000;
PUBLIC dirtim_hr_min ;AN000;
PUBLIC dirtim_sec_hn ;AN000;
PUBLIC DIR_W_SYN ;AN000;
PUBLIC disp_file_size_ptr ;AN000;
PUBLIC dmes_ptr ;AN000;
PUBLIC echomes_ptr ;AN000;
PUBLIC enverr_ptr ;AN000;
PUBLIC eurdat_ptr ;AN000;
PUBLIC exeext
PUBLIC extend_buf_off ;AN000;
PUBLIC extend_buf_ptr ;AN000;
PUBLIC extend_buf_seg ;AN000;
PUBLIC extend_buf_sub ;AN000;
PUBLIC file_name_ptr ;AN000;
PUBLIC fornestmes_ptr ;AN000;
PUBLIC fuldir_ptr ;AN000;
PUBLIC IFTAB
PUBLIC inBdev_ptr ;AN000;
PUBLIC inornot_ptr ;AN000;
PUBLIC Inv_code_page ;AN000;
PUBLIC inval_path_ptr ;AN000;
PUBLIC japdat_ptr ;AN000;
PUBLIC Losterr_ptr ;AN000;
PUBLIC md_exists_ptr ;AN006;
PUBLIC msg_cont_flag ;AN000;
PUBLIC msg_disp_class ;AN000;
PUBLIC needbat_ptr ;AN000;
PUBLIC newdat_format ;AN000;
PUBLIC newdat_ptr ;AN000;
PUBLIC newtim_ptr ;AN000;
PUBLIC NLSFUNC_ptr ;AN000;
PUBLIC nospace_ptr ;AN000;
PUBLIC no_values ;AN000;
PUBLIC nulpath_ptr ;AN000;
PUBLIC offmes_ptr ;AN000;
PUBLIC onmes_ptr ;AN000;
PUBLIC overwr_ptr ;AN000;
PUBLIC PARSE_BREAK ;AN000;
PUBLIC PARSE_CHCP ;AN000;
PUBLIC PARSE_CHDIR ;AN000;
PUBLIC PARSE_CTTY ;AN000;
PUBLIC PARSE_DATE ;AN000;
PUBLIC PARSE_DIR ;AN000;
PUBLIC PARSE_ERASE ;AN000;
PUBLIC PARSE_MRDIR ;AN000;
PUBLIC PARSE_RENAME ;AN000;
PUBLIC PARSE_TIME ;AN000;
PUBLIC PARSE_VOL ;AN000;
PUBLIC PATH_TEXT
PUBLIC pausemes_ptr ;AN000;
PUBLIC pipeEmes_ptr ;AN000;
PUBLIC promptdat_moday ;AN000;
PUBLIC promptdat_ptr ;AN000;
PUBLIC promptdat_yr ;AN000;
PUBLIC PROMPT_TABLE
PUBLIC PROMPT_TEXT
PUBLIC promtim_hr_min ;AN000;
PUBLIC promtim_ptr ;AN000;
PUBLIC promtim_sec_hn ;AN000;
PUBLIC renerr_ptr ;AN000;
PUBLIC SLASH_P_SYN ;AN000;
PUBLIC string_buf_ptr ;AN000;
PUBLIC suremes_ptr ;AN000;
PUBLIC switch_list
PUBLIC syntmes_ptr ;AN000;
PUBLIC tab_ptr ;AN000;
PUBLIC TRANDATAEND
PUBLIC usadat_ptr ;AN000;
PUBLIC verimes_ptr ;AN000;
PUBLIC vermes_ptr ;AN000;
PUBLIC volmes_ptr ;AN000;
PUBLIC volmes_ptr_2 ;AN000;
PUBLIC volsermes_ptr ;AN000;
PUBLIC WEEKTAB
PUBLIC xa_cp ;AN030;
INCLUDE tranmsg.asm
CLSSTRING DB 4,01BH,"[2J" ; ANSI Clear screen
PROMPT_TABLE LABEL BYTE
btab "B",Print_B
btab "D",PRINT_DATE
btab "E",PRINT_ESC
btab "G",PRINT_G
btab "H",PRINT_BACK
btab "L",PRINT_L
btab "N",PRINT_DRIVE
btab "P",build_dir_for_prompt
btab "Q",PRINT_EQ
btab "T",PRINT_TIME
btab "V",PRINT_VERSION
btab "_",CRLF2
btab "$",PRINT_CHAR
DB 0 ; NUL TERMINATED
IFTAB LABEL BYTE ; Table of IF conditionals
DB 3,"NOT" ; First byte is count
DW OFFSET TRANGROUP:IFNOT
DB 10,"ERRORLEVEL"
DW OFFSET TRANGROUP:IFERLEV
DB 5,"EXIST"
DW OFFSET TRANGROUP:IFEXISTS
DB 0
; Table for internal command names
COMTAB DB 3,"DIR",fSwitchAllowed+fCheckDrive
DW OFFSET TRANGROUP:CATALOG ; In TCMD1.ASM
DB 4,"CALL",fSwitchAllowed
DW OFFSET TRANGROUP:$CALL ; In TBATCH2.ASM
DB 4,"CHCP",fSwitchAllowed
DW OFFSET TRANGROUP:CHCP ; In TCMD2B.ASM
DB 6,"RENAME",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM
DB 3,"REN",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM
DB 5,"ERASE",fSwitchAllowed+fCheckDrive
DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM
DB 3,"DEL",fSwitchAllowed+fCheckDrive
DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM
DB 4,"TYPE",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:TYPEFIL ; In TCMD1.ASM
DB 3,"REM",fSwitchAllowed
DW OFFSET TRANGROUP:TCOMMAND ; In TCODE.ASM
DB 4,"COPY",fSwitchAllowed+fCheckDrive
DW OFFSET TRANGROUP:COPY ; In COPY.ASM
DB 5,"PAUSE",fSwitchAllowed
DW OFFSET TRANGROUP:PAUSE ; In TCMD1.ASM
DB 4,"DATE",fSwitchAllowed
DW OFFSET TRANGROUP:DATE ; In TPIPE.ASM
DB 4,"TIME",fSwitchAllowed ;AC018; P3903
DW OFFSET TRANGROUP:CTIME ; In TPIPE.ASM
DB 3,"VER",0
DW OFFSET TRANGROUP:VERSION ; In TCMD2.ASM
DB 3,"VOL",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:VOLUME ; In TCMD1.ASM
DB 2,"CD",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM
DB 5,"CHDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM
DB 2,"MD",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM
DB 5,"MKDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM
DB 2,"RD",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM
DB 5,"RMDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903
DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM
DB 5,"BREAK",fSwitchAllowed ;AC018; P3903
DW OFFSET TRANGROUP:CNTRLC ; In TUCODE.ASM
DB 6,"VERIFY",fSwitchAllowed ;AC018; P3903
DW OFFSET TRANGROUP:VERIFY ; In TUCODE.ASM
DB 3,"SET",fSwitchAllowed
DW OFFSET TRANGROUP:ADD_NAME_TO_ENVIRONMENT; In TENV.ASM
DB 6,"PROMPT",fSwitchAllowed
DW OFFSET TRANGROUP:ADD_PROMPT ; In TENV.ASM
DB 4,"PATH",fSwitchAllowed
DW OFFSET TRANGROUP:PATH ; In TCMD2.ASM
DB 4,"EXIT",0
DW OFFSET TRANGROUP:$EXIT ; In TCMD2.ASM
DB 4,"CTTY",fCheckDrive+fSwitchAllowed
DW OFFSET TRANGROUP:CTTY ; In TCMD2.ASM
DB 4,"ECHO",fSwitchAllowed
DW OFFSET TRANGROUP:ECHO ; In TUCODE.ASM
DB 4,"GOTO",fSwitchAllowed
DW OFFSET TRANGROUP:GOTO ; In TBATCH.ASM
DB 5,"SHIFT",fSwitchAllowed
DW OFFSET TRANGROUP:SHIFT ; In TBATCH.ASM
DB 2,"IF",fSwitchAllowed
DW OFFSET TRANGROUP:$IF ; In TBATCH.ASM
DB 3,"FOR",fSwitchAllowed
DW OFFSET TRANGROUP:$FOR ; In TBATCH.ASM
DB 3,"CLS",0
DW OFFSET TRANGROUP:CLS ; In TCMD2.ASM
DB 8,"TRUENAME",fSwitchAllowed+fCheckDrive ;AN000; P3903 changed
DW OFFSET TRANGROUP:TRUENAME ;AN000;
DB 0 ; Terminate command table
comext dB ".COM"
exeext dB ".EXE"
batext dB ".BAT"
switch_list DB "VBAPW" ; flags we can recognize
XA_cp Label byte ;AN030; list for one extended attribute
DW 1 ;AN030;
DB EAISBINARY ;AN030; type
DW EASYSTEM ;AN030; flags
DB 2 ;AN030; name length
DB "CP" ;AN030; name
PUBLIC BatBufLen
BatBufLen DW BatLen
; *****************************************************
; EMG 4.00
; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00
; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE
; *****************************************************
;
; COMMON PARSE BLOCKS
;
;
; Indicates no value list for PARSE.
;
NO_VALUES DW 0 ;AN000; no values
;
; PARSE control block for a required file specification (upper cased)
;
FILE_REQUIRED LABEL BYTE ;AN000;
DW 0200H ;AN000; filespec - required
DW 1 ;AN000; capitalize - file table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE control block for an optional file specification (upper cased)
; or drive number
;
FILE_OPTIONAL LABEL BYTE ;AN000;
DW 0301H ;AN000; filespec or drive number
; optional
DW 1 ;AN000; capitalize - file table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE control block for an optional file specification (upper cased)
;
FILE_OPTIONAL2 LABEL BYTE ;AN000;
DW 0201H ;AN000; filespec or drive number
; optional
DW 1 ;AN000; capitalize - file table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE control block for an optional /P switch
;
SLASH_P_SWITCH LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize - char table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 1 ;AN000; 1 keyword
SLASH_P_SYN DB "/P",0 ;AN000; /P switch
; PARSE BLOCK FOR BREAK, VERIFY, ECHO
;
; The following parse control block can be used for any command which
; needs only the optional "ON" and "OFF" keywords as operands. Allows
; the equal sign as an additional delimiter. Returns verified result
; in PARSE1_OUTPUT. Currently used for the BREAK, VERIFY, and ECHO
; internal commands.
;
PARSE_BREAK LABEL BYTE ;AN000;
DW TRANGROUP:BREAK_PARMS ;AN000;
DB 0 ;AN032; no extra delimiter
BREAK_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:BREAK_CONTROL1;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
BREAK_CONTROL1 LABEL BYTE ;AN000;
DW 2001H ;AN000; string value - optional
DW 2 ;AN000; capitalize - char table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:BREAK_VALUES ;AN000;
DB 0 ;AN000; no keywords
BREAK_VALUES LABEL BYTE ;AN000;
DB 3 ;AN000;
DB 0 ;AN000; no ranges
DB 0 ;AN000; no numeric values
DB 2 ;AN000; 2 string values
DB 0 ;AN000; returned if ON
DW TRANGROUP:BREAK_ON ;AN000; point to ON string
DB 'f' ;AN000; returned if OFF
DW TRANGROUP:BREAK_OFF ;AN000; point to OFF string
BREAK_ON DB "ON",0 ;AN000;
BREAK_OFF DB "OFF",0 ;AN000;
;
; PARSE BLOCK FOR CHCP
;
;
; The following parse control block can be used for any command which
; needs only one optional three digit decimal parameter for operands.
; Returns verified result in PARSE1_OUTPUT. Currently used for the
; CHCP internal command.
;
CHCP_MINVAL EQU 100 ;AN000;
CHCP_MAXVAL EQU 999 ;AN000;
PARSE_CHCP LABEL BYTE ;AN000;
DW TRANGROUP:CHCP_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
CHCP_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:CHCP_CONTROL1 ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
CHCP_CONTROL1 LABEL BYTE ;AN000;
DW 8001H ;AN000; numeric value - optional
DW 0 ;AN000; no function flags
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:CHCP_VALUES ;AN000;
DB 0 ;AN000; no keywords
CHCP_VALUES LABEL BYTE ;AN000;
DB 1 ;AN000;
DB 1 ;AN000; 1 range
DB 1 ;AN000; returned if result
DD CHCP_MINVAL,CHCP_MAXVAL ;AN000; minimum & maximum value
DB 0 ;AN000; no numeric values
DB 0 ;AN000; no string values
;
; PARSE BLOCK FOR DATE
;
;
; The following parse control block can be used for any command which
; needs only an optional date string as an operand. Returns unverified
; result in DATE_OUTPUT. Currently used for the DATE internal command.
;
PARSE_DATE LABEL BYTE ;AN000;
DW TRANGROUP:DATE_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
DATE_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:DATE_CONTROL1 ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
DATE_CONTROL1 LABEL BYTE ;AN000;
DW 1001H ;AN000; date - optional
DW 0 ;AN000; no function flags
DW TRANGROUP:DATE_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR TIME
;
;
; The following parse control block can be used for any command which
; needs only an optional time string as an operand. Returns unverified
; result in TIME_OUTPUT. Currently used for the TIME internal command.
;
PARSE_TIME LABEL BYTE ;AN000;
DW TRANGROUP:TIME_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
TIME_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:TIME_CONTROL1 ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
TIME_CONTROL1 LABEL BYTE ;AN000;
DW 0801H ;AN000; TIME - optional
DW 0 ;AN000; no function flags
DW TRANGROUP:TIME_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR VOL
;
;
; The following parse control block can be used for any command which
; needs only an optional drive letter as an operand. Returns unverified
; drive number (one based) in DRIVE_OUTPUT. Currently used for the VOL
; internal command.
;
PARSE_VOL LABEL BYTE ;AN000;
DW TRANGROUP:VOL_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
VOL_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:DRIVE_CONTROL1;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
DRIVE_CONTROL1 LABEL BYTE ;AN000;
DW 0101H ;AN000; DRIVE - optional
DW 1 ;AN000; capitalize - file table
DW TRANGROUP:DRIVE_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR MKDIR, RMDIR, TYPE
;
;
; The following parse control block can be used for any command which
; needs only one required file specification as an operand. Returns a
; pointer to the unverified string in PARSE1_OUTPUT. Currently used
; for the MKDIR, RMDIR, and TYPE internal commands.
;
PARSE_MRDIR LABEL BYTE ;AN000;
DW TRANGROUP:MRDIR_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
MRDIR_PARMS LABEL BYTE ;AN000;
DB 1,1 ;AN000; 1 positional parm
DW TRANGROUP:FILE_REQUIRED ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR CHDIR, TRUENAME
;
;
; The following parse control block can be used for any command which
; needs only one optional file specification an operand. Returns a
; pointer to the unverified string in PARSE1_OUTPUT. Currently used
; for the CHDIR and TRUENAME internal commands.
;
PARSE_CHDIR LABEL BYTE ;AN000;
DW TRANGROUP:CHDIR_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
CHDIR_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:FILE_OPTIONAL ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR ERASE
;
;
; The following parse control block is used for the DEL/ERASE internal
; commands. This command has one required file specification and an
; optional switch (/p) as operands. The verified switch or unverified
; file specification is returned in PARSE1_OUTPUT.
;
PARSE_ERASE LABEL BYTE ;AN000;
DW TRANGROUP:ERASE_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
ERASE_PARMS LABEL BYTE ;AN000;
DB 1,1 ;AN000; 1 positional parm
DW TRANGROUP:FILE_REQUIRED ;AN000;
DB 1 ;AN000; 1 switch
DW TRANGROUP:SLASH_P_SWITCH;AN000;
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR DIR
;
;
; The following parse control block is used for the DIR internal command.
; This command has one optional file specification and two optional
; switches (/p and /w) as operands. The verified switch or unverified
; file specification is returned in PARSE1_OUTPUT.
;
PARSE_DIR LABEL BYTE ;AN000;
DW TRANGROUP:DIR_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
DIR_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW TRANGROUP:FILE_OPTIONAL2;AN000;
DB 2 ;AN000; 2 switches
DW TRANGROUP:SLASH_P_SWITCH;AN000;
DW TRANGROUP:DIR_SWITCH1 ;AN000;
DB 0 ;AN000; no keywords
DIR_SWITCH1 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 1 ;AN000; 1 keyword
DIR_W_SYN DB "/W",0 ;AN000; /W switch
;
; PARSE BLOCK FOR RENAME
;
;
; The following parse control block can be used for any command which
; needs only two required file specifications as operands. Returns
; pointers to the unverified string in PARSE1_OUTPUT.
; Currently used for the RENAME internal command.
;
PARSE_RENAME LABEL BYTE ;AN000;
DW TRANGROUP:RENAME_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
RENAME_PARMS LABEL BYTE ;AN000;
DB 2,2 ;AN000; 2 positional parms
DW TRANGROUP:FILE_REQUIRED ;AN000;
DW TRANGROUP:FILE_REQUIRED ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
;
; PARSE BLOCK FOR CTTY
;
;
; The following parse control block can be used for any command which
; needs one required device name as an operand. Returns a pointer to
; unverified string in PARSE1_OUTPUT. Currently used for the CTTY
; internal command.
;
PARSE_CTTY LABEL BYTE ;AN000;
DW TRANGROUP:CTTY_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
CTTY_PARMS LABEL BYTE ;AN000;
DB 1,1 ;AN000; 1 positional parm
DW TRANGROUP:CTTY_CONTROL1 ;AN000;
DB 0 ;AN000; no switches
DB 0 ;AN000; no keywords
CTTY_CONTROL1 LABEL BYTE ;AN000;
DW 2000H ;AN000; string value - required
DW 11H ;AN000; capitalize - file table
;AN000; remove colon at end
DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer
DW TRANGROUP:NO_VALUES ;AN000;
DB 0 ;AN000; no keywords
TRANDATA ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AN000;
.xlist
.xcref
INCLUDE SYSMSG.INC ;AN000;
.list
.cref
ASSUME DS:TRANGROUP,ES:TRANGROUP,CS:TRANGROUP
MSG_UTILNAME <COMMAND> ;AN000; define utility name
MSG_SERVICES <COMT,COMMAND.CLF,COMMAND.CL1,COMMAND.CL2> ;AN000; The transient messages
include msgdcl.inc
TRANCODE ENDS ;AN000;
TRANDATA SEGMENT PUBLIC BYTE
TRANDATAEND LABEL BYTE
TRANDATA ENDS ;AN000;
END

View File

@@ -0,0 +1,633 @@
page 80,132
; SCCSID = @(#)tenv.asm 4.2 85/08/16
; SCCSID = @(#)tenv.asm 4.2 85/08/16
TITLE Part6 COMMAND Transient routines.
; Environment utilities and misc. routines
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
INCLUDE DOSCNTRY.INC ;AN000;
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN comdrv:byte
EXTRN comspec_end:word
EXTRN comspec_print:word
EXTRN cpdrv:byte
EXTRN dbcs_vector_addr:dword ;AN000;
EXTRN ENVIRSEG:WORD
EXTRN fucase_addr:word ;AC000;
EXTRN RESTDIR:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf_ptr:word
EXTRN comspec:byte
EXTRN comspec_flag:byte
EXTRN comspecstr:byte
EXTRN ENVERR_PTR:WORD
EXTRN PATH_TEXT:byte
EXTRN PROMPT_TEXT:byte
EXTRN SYNTMES_PTR:WORD
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN Arg_Buf:BYTE
EXTRN RESSEG:WORD
EXTRN USERDIR1:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
PUBLIC add_name_to_environment
PUBLIC add_prompt
PUBLIC delete_path
PUBLIC find_name_in_environment
PUBLIC find_path
PUBLIC find_prompt
PUBLIC move_name
PUBLIC restudir
PUBLIC restudir1
PUBLIC scan_double_null
PUBLIC scasb2
PUBLIC store_char
PUBLIC Testkanj ;AN000; 3/3/KK
PUBLIC upconv
BREAK <Environment utilities>
ASSUME DS:TRANGROUP
break Prompt command
assume ds:trangroup,es:trangroup
ADD_PROMPT:
CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT
CALL SCAN_DOUBLE_NULL
ADD_PROMPT2:
PUSH SI
CALL GETARG
POP SI
retz ; PRE SCAN FOR ARGUMENTS
CALL MOVE_NAME ; MOVE IN NAME
CALL GETARG
PUSH SI
JMP SHORT ADD_NAME
break The SET command
assume ds:trangroup,es:trangroup
;
; Input: DS:SI points to a CR terminated string
; Output: carry flag is set if no room
; otherwise name is added to environment
;
DISP_ENVj:
jmp DISP_ENV
ADD_NAME_TO_ENVIRONMENT:
CALL GETARG
JZ DISP_ENVj
;
; check if line contains exactly one equals sign
;
XOR BX,BX ;= COUNT IS 0
PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
EQLP:
LODSB ;GET A CHAR
CMP AL,13 ;IF CR WE'RE ALL DONE
JZ QUEQ
CMP AL,'=' ;LOOK FOR = SIGN
JNZ EQLP ;NOT THERE, GET NEXT CHAR
INC BL ;OTHERWISE INCREMENT EQ COUNT
CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN
JNZ EQLP
INC BH ;SET BH=1 MEANS NO PARAMETERS
JMP EQLP ;AND LOOK FOR MORE
QUEQ:
POP SI ;RESTORE BEGINNING OF LINE
DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
JZ ONEQ ;GOOD LINE
MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
JMP CERROR
ONEQ:
PUSH BX
CALL DELETE_NAME_IN_ENVIRONMENT
POP BX
DEC BH
retz
CALL SCAN_DOUBLE_NULL
mov bx,di ; Save ptr to beginning of env var name
CALL MOVE_NAME
push si
xchg bx,di ; Switch ptrs to beginning and end of
; env var name
;
; We want to special-case COMSPEC. This is to reduce the amount of code
; necessary in the resident for re-reading the transient. Let's look for
; COMSPEC=
;
mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC"
mov cx,4 ; If the new env var is comspec, set
repz cmpsw ; the comspec_flag
;
; Zero set => exact match
;
jnz not_comspec
mov comspec_flag,1
not_comspec:
mov di,bx ; Load ptr to end of env var name
ADD_NAME: ; Add the value of the new env var
pop si ; to the environment.
push si
add_name1:
LODSB
CMP AL,13
jz add_name_ret
CALL STORE_CHAR
JMP ADD_NAME1
add_name_ret:
pop si
cmp comspec_flag,0 ; If the new env var is comspec,
retz ; copy the value into the
;
; We have changed the COMSPEC variable. We need to update the resident
; pieces necessary to reread in the info. First, skip all delimiters
;
invoke ScanOff
mov es,[resseg] ; comspec var in the resident
assume es:resgroup
;
; Make sure that the printer knows where the beginning of the string is
;
mov di,offset resgroup:comspec
mov bx,di
;
; Generate drive letter for display
;
xor ax,ax ;g assume no drive first
mov comdrv,al ;g
push ax ;AN000; 3/3/KK
mov al,[si] ;AN000; 3/3/KK
call testkanj ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
jnz GotDrive
cmp byte ptr [si+1],':' ; drive specified?
jnz GotDrive
mov al,[si] ; get his specified drive
call UpConv ; convert to uppercase
sub al,'A' ; convert to 0-based
add di,2
inc al ; convert to 1-based number
mov comdrv,al
;
; Stick the drive letter in the prompt message. Nothing special needs to be
; done here..
;
add al,'A'-1
GotDrive: ;g
mov comspec_print,di ;g point to beginning of name after drive
mov es:cpdrv,al
;
; Copy chars until delim
;
mov di,bx
copy_comspec:
lodsb
invoke Delim
jz CopyDone
cmp al,13
jz CopyDone
stosb
jmp short copy_comspec
CopyDone:
xor al,al ; Null terminate the string and quit
stosb
mov comspec_flag,0
dec di
mov comspec_end,di
ret
DISP_ENV:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV DS,[ENVIRSEG]
ASSUME DS:NOTHING
XOR SI,SI
PENVLP:
CMP BYTE PTR [SI],0
retz
mov di,offset trangroup:arg_buf
PENVLP2:
LODSB
stosb
OR AL,AL
JNZ PENVLP2
mov dx,offset trangroup:arg_buf_ptr
push ds
push es
pop ds
invoke printf_crlf
pop ds
JMP PENVLP
ASSUME DS:TRANGROUP
DELETE_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT DELETE_NAME_IN_environment
DELETE_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
DELETE_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: carry flag is set if name not found
; otherwise name is deleted
;
PUSH SI
PUSH DS
CALL FIND ; ES:DI POINTS TO NAME
JC DEL1
MOV SI,DI ; SAVE IT
CALL SCASB2 ; SCAN FOR THE NUL
XCHG SI,DI
CALL GETENVSIZ
SUB CX,SI
PUSH ES
POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
REP MOVSB ; DELETE THE NAME
DEL1:
POP DS
POP SI
return
FIND_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT FIND_NAME_IN_environment
FIND_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
FIND_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: ES:DI points to the arguments in the environment
; zero is set if name not found
; carry flag is set if name not valid format
;
CALL FIND ; FIND THE NAME
retc ; CARRY MEANS NOT FOUND
JMP SCASB1 ; SCAN FOR = SIGN
;
; On return of FIND1, ES:DI points to beginning of name
;
FIND:
CLD
CALL COUNT0 ; CX = LENGTH OF NAME
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
FIND1:
PUSH CX
PUSH SI
PUSH DI
FIND11:
LODSB
CALL TESTKANJ
JZ NOTKANJ3
DEC SI
LODSW
INC DI
INC DI
CMP AX,ES:[DI-2]
JNZ FIND12
DEC CX
LOOP FIND11
JMP SHORT FIND12
NOTKANJ3:
CALL UPCONV
INC DI
CMP AL,ES:[DI-1]
JNZ FIND12
LOOP FIND11
FIND12:
POP DI
POP SI
POP CX
retz
PUSH CX
CALL SCASB2 ; SCAN FOR A NUL
POP CX
CMP BYTE PTR ES:[DI],0
JNZ FIND1
STC ; INDICATE NOT FOUND
return
COUNT0:
PUSH DS
POP ES
MOV DI,SI
COUNT1:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
CALL SCASB1
JMP SHORT COUNTX
COUNT2:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
CALL SCASB2
COUNTX:
POP CX
SUB DI,CX
XCHG DI,CX
return
MOVE_NAME:
CMP BYTE PTR DS:[SI],13
retz
LODSB
;;;; IF KANJI 3/3/KK
CALL TESTKANJ
JZ NOTKANJ1
CALL STORE_CHAR
LODSB
CALL STORE_CHAR
JMP SHORT MOVE_NAME
NOTKANJ1:
;;;; ENDIF 3/3/KK
CALL UPCONV
CALL STORE_CHAR
CMP AL,'='
JNZ MOVE_NAME
return
GETARG:
MOV SI,80H
LODSB
OR AL,AL
retz
invoke SCANOFF
CMP AL,13
return
;
; Point ES:DI to the final NULL string. Note that in an empty environment,
; there is NO double NULL, merely a string that is empty.
;
SCAN_DOUBLE_NULL:
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
;
; Top cycle-point. If the string here is empty, then we are done
;
SDN1:
cmp byte ptr es:[di],0 ; nul string?
retz ; yep, all done
CALL SCASB2
JMP SDN1
SCASB1:
MOV AL,'=' ; SCAN FOR AN =
JMP SHORT SCASBX
SCASB2:
XOR AL,AL ; SCAN FOR A NUL
SCASBX:
MOV CX,100H
REPNZ SCASB
return
TESTKANJ:
push ds ;AN000; 3/3/KK
push si ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
mov ds,cs:[resseg] ;AN000; Get resident segment
assume ds:resgroup ;AN000;
lds si,dbcs_vector_addr ;AN000; get DBCS vector
ktlop: ;AN000; 3/3/KK
cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK
je notlead ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jb notlead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jbe islead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
jmp short ktlop ;AN000; try another range ; 3/3/KK
Notlead: ;AN000; 3/3/KK
xor ax,ax ;AN000; set zero 3/3/KK
jmp short ktret ;AN000; 3/3/KK
Islead: ;AN000; 3/3/KK
xor ax,ax ;AN000; reset zero 3/3/KK
inc ax ;AN000; 3/3/KK
ktret: ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
pop si ;AN000; 3/3/KK
pop ds ;AN000; 3/3/KK
return ;AN000; 3/3/KK
;------------------------------------- ;3/3/KK
; ****************************************************************
; *
; * ROUTINE: UPCONV (ADDED BY EMG 4.00)
; *
; * FUNCTION: This routine returns the upper case equivalent of
; * the character in AL from the file upper case table
; * in DOS if character if above ascii 128, else
; * subtracts 20H if between "a" and "z".
; *
; * INPUT: AL char to be upper cased
; * FUCASE_ADDR set to the file upper case table
; *
; * OUTPUT: AL upper cased character
; *
; ****************************************************************
assume ds:trangroup ;AN000;
upconv proc near ;AN000;
cmp al,80h ;AN000; see if char is > ascii 128
jb oth_fucase ;AN000; no - upper case math
sub al,80h ;AN000; only upper 128 chars in table
push ds ;AN000;
push bx ;AN000;
mov ds,[resseg] ;AN000; get resident data segment
assume ds:resgroup ;AN000;
lds bx,dword ptr fucase_addr+1 ;AN000; get table address
add bx,2 ;AN000; skip over first word
xlat ds:byte ptr [bx] ;AN000; convert to upper case
pop bx ;AN000;
pop ds ;AN000;
assume ds:trangroup ;AN000;
jmp short upconv_end ;AN000; we finished - exit
oth_fucase: ;AN000;
cmp al,small_a ;AC000; if between "a" and "z",
jb upconv_end ;AC000; subtract 20h to get
cmp al,small_z ;AC000; upper case equivalent.
ja upconv_end ;AC000;
sub al,20h ;AC000; Change lower-case to upper
upconv_end: ;AN000;
ret
upconv endp ;AN000;
;
; STORE A CHAR IN environment, GROWING IT IF NECESSARY
;
STORE_CHAR:
PUSH CX
PUSH BX
PUSH ES ;AN056;
PUSH DS ;AN056; Save local DS
MOV DS,[RESSEG] ;AN056; Get resident segment
ASSUME DS:RESGROUP ;AN056;
MOV ES,[ENVIRSEG] ;AN056; Get environment segment
ASSUME ES:NOTHING ;AN056;
POP DS ;AN056; Get local segment back
ASSUME DS:TRANGROUP ;AN056;
CALL GETENVSIZ
MOV BX,CX
SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
CMP DI,BX
JB STORE1
PUSH AX
PUSH CX
PUSH BX ; Save Size of environment
invoke FREE_TPA
POP BX
ADD BX,2 ; Recover true environment size
CMP BX, 8000H ; Don't let environment grow > 32K
JB ENVSIZ_OK
BAD_ENV_SIZE: ;AN056;
STC
JMP ENVNOSET
ENVSIZ_OK:
MOV CL,4
SHR BX,CL ; Convert back to paragraphs
INC BX ; Try to grow environment by one para
MOV CX,ES ;AN056; Get environment segment
ADD CX,BX ;AN056; Add in size of environment
ADD CX,020H ;AN056; Add in some TPA
MOV AX,CS ;AN056; Get the transient segment
CMP CX,AX ;AN056; Are we hitting the transient?
JNB BAD_ENV_SIZE ;AN056; Yes - don't do it!!!
MOV AH,SETBLOCK
INT int_command
ENVNOSET:
PUSHF
PUSH ES
MOV ES,[RESSEG]
invoke ALLOC_TPA
POP ES
POPF
POP CX
POP AX
JNC STORE1
POP ES ;AN056;
MOV DX,OFFSET TRANGROUP:ENVERR_ptr
JMP CERROR
STORE1:
STOSB
MOV WORD PTR ES:[DI],0 ; NULL IS AT END
POP ES ;AN056;
POP BX
POP CX
return
GETENVSIZ:
;Get size of environment in bytes, rounded up to paragraph boundry
;ES has environment segment
;Size returned in CX, all other registers preserved
PUSH ES
PUSH AX
MOV AX,ES
DEC AX ;Point at arena
MOV ES,AX
MOV AX,ES:[arena_size]
MOV CL,4
SHL AX,CL ;Convert to bytes
MOV CX,AX
POP AX
POP ES
return
ASSUME DS:TRANGROUP
RESTUDIR1:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
CMP [RESTDIR],0
POP DS
ASSUME DS:TRANGROUP
retz
RESTUDIR:
MOV DX,OFFSET TRANGROUP:USERDIR1
MOV AH,CHDIR
INT int_command ; Restore users DIR
XOR AL,AL
invoke SETREST
RET56:
return
trancode ends
end

View File

@@ -0,0 +1,663 @@
page 80,132
; SCCSID = @(#)tenv2.asm 1.1 85/05/14
; SCCSID = @(#)tenv2.asm 1.1 85/05/14
TITLE Part6 COMMAND Transient routines.
; Environment utilities and misc. routines
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN pipeflag:byte
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN ACRLF_PTR:WORD
EXTRN BadCD_Ptr:WORD
EXTRN Badmkd_ptr:word
EXTRN BADRMD_PTR:WORD
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN Extend_buf_sub:byte ;AN022;
EXTRN MD_exists_ptr:word ;AN006;
EXTRN msg_disp_class:byte ;AC000;
EXTRN NOSPACE_PTR:WORD
EXTRN parse_chdir:byte ;AC000;
EXTRN parse_mrdir:byte ;AC000;
EXTRN PIPEEMES_PTR:WORD
EXTRN string_buf_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN CURDRV:BYTE
EXTRN DESTINFO:BYTE
EXTRN DESTTAIL:WORD
EXTRN DIRCHAR:BYTE
EXTRN dirflag:byte ;AN015;
EXTRN KPARSE:BYTE ;AC000; 3/3/KK
EXTRN msg_numb:word ;AN022;
EXTRN parse1_addr:dword ;AC000;
EXTRN parse1_type:byte ;AC000;
EXTRN PATHPOS:WORD
EXTRN RESSEG:WORD
EXTRN srcxname:byte ;AC000;
EXTRN string_ptr_2:word
EXTRN SWITCHAR:BYTE
EXTRN USERDIR1:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
PUBLIC $chdir
PUBLIC $mkdir
PUBLIC $rmdir
PUBLIC crlf2
PUBLIC crprint
PUBLIC delim
PUBLIC error_output
PUBLIC fcb_to_ascz
PUBLIC pathchrcmp
PUBLIC pathcrunch
PUBLIC savudir
PUBLIC savudir1
PUBLIC scanoff
PUBLIC strcomp
break $Chdir
; ****************************************************************
; *
; * ROUTINE: $CHDIR
; *
; * FUNCTION: Entry point for CHDIR command. Parse the command
; * line. If path is found, CHDIR to path. If a drive
; * letter is found, get and display the current dir
; * of the specified drive. If nothing is found, get
; * and display the current dir of the default drive.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
$CHDIR:
mov si,81H
mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke parse_with_msg ;AC018; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
jz bwdJ ; No args
cmp ax,result_no_error ;AC000; did we have an error?
jnz ChDirErr ;AC018; yes - exit
cmp parse1_type,result_drive ;AC000; was a drive entered?
jnz REALCD ; no
;
; D: was found. See if there is anything more.
;
mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir
xor dx,dx ;AC000;
invoke parse_check_eol ;AC000; call parser
jnz ChDirErr ;AC000;
bwdJ:
invoke build_dir_for_chdir ; Drive only specified
call crlf2
return
REALCD:
push si ;AN000; save position in line
lds si,parse1_addr ;AN000; get address of filespec
invoke move_to_srcbuf ;AN000; move to srcbuf
pop si ;AN000; restore position in line
mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir
xor dx,dx ;AC000;
invoke parse_check_eol ;AC000; call parser
jnz ChDirErr ;AC000;
invoke SETPATH
TEST [DESTINFO],2
JNZ BadChdir
MOV AH,CHDIR
INT int_command
retnc
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_path_not_found ;AN022; see if path not found
jz BadChDir ;AN022; yes - issue old message
call Set_Ext_Error_Subst ;AN022;
jmp short chdirerr ;AN022;
BadChDir:
MOV DX,OFFSET TRANGROUP:BADCD_ptr
ChDirErr:
invoke Std_Eprintf
return
break $Mkdir
assume ds:trangroup,es:trangroup
$MKDIR:
CALL SETRMMK
JC MkDirErr
MOV AH,MKDIR
INT int_command
retnc
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_path_not_found ;AN022; see if path not found
jz MD_other_err ;AN022; yes - issue old message
cmp ax,error_access_denied ;AN022; access denied?
jz badmderr ;AN022; yes - see if file exists
call Set_Ext_Error_Subst ;AN022;
jmp short MkDirerr ;AC022; yes - go print it
BADMDERR:
mov dx,offset trangroup:srcxname ;AN006; Set Disk transfer address
mov ah,Set_DMA ;AN006;
int int_command ;AN006;
MOV AH,Find_First ;AN006; see if file/dir exists
mov cx,attr_directory ;AN006; search for directory
INT int_command ;AN006;
jc MD_other_err ;AN006; doesn't exist - must be something else
mov dl,srcxname.find_buf_attr ;AN006; we found a file/dir
test dl,attr_directory ;AN006; was it a directory?
jz MD_other_err ;AN006; no - must have been a file
mov dx,offset trangroup:MD_exists_ptr ;AN006; set up already exists error
jmp short MkDirErr ;AN006; make sure we didn't have network error
MD_other_err: ;AN006;
MOV DX,OFFSET TRANGROUP:BADMKD_ptr
MkDirErr:
invoke Std_Eprintf
return
Break <Common MkDir/RmDir set up code>
;****************************************************************
;*
;* ROUTINE: SETRMMK
;*
;* FUNCTION: Parse routine for the internal MKDIR and RMDIR
;* commands. Parses the command line for a required
;* filespec.
;*
;* INPUT: command line at offset 81H
;*
;* OUTPUT: carry clear
;* DS:DX points to ASCIIZ argument
;* carry set
;* DS:DX has error message pointer
;*
;****************************************************************
SETRMMK:
mov si,81H
mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke parse_with_msg ;AC000; call parser
cmp ax,result_no_error ;AC000; did we have an error?
jnz NOARGERR ;AC000; yes - exit
mov di,offset trangroup:srcxname ;AN000; get address of srcxname
push di ;AN000; save address
push si ;AN000; save position in line
lds si,parse1_addr ;AN000; get address of path
mrdir_move_filename: ;AN000; put filespec in srcxname
lodsb ;get a char from buffer
stosb ;AN000; store in srcxname
cmp al,end_of_line_out ;AC000; it char a terminator?
jnz mrdir_move_filename ;AC000; no - keep moving
pop si ;AN000; get line position back
;
; we have scanned an argument. See if any args beyond.
;
mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir
invoke parse_check_eol ;AC000; are we at end of line?
pop dx ;AC000; get address of SRCXNAME
retz ;yes - return no error
NOARGERR:
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
XOR AX,AX
STC
return
break $Rmdir
assume ds:trangroup,es:trangroup
$RMDIR:
CALL SETRMMK
JC RmDirErr
JNZ BADRDERR
MOV AH,RMDIR
INT int_command
retnc
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_path_not_found ;AN022; see if path not found
jz badrderr ;AN022; yes - issue old message
cmp ax,error_access_denied ;AN022; access denied?
jz badrderr ;AN022; yes - issue old message
call Set_Ext_Error_Subst ;AN022;
jmp short RmDirerr ;AC022; yes - go print it
BADRDERR:
MOV DX,OFFSET TRANGROUP:BADRMD_ptr
RmDirErr:
invoke STD_Eprintf
return
;****************************************************************
;*
;* ROUTINE: Set_ext_error_subst
;*
;* FUNCTION: Sets up substitution for extended error
;*
;* INPUT: AX - extended error number
;* DX - offset of string
;*
;* OUTPUT: Extend_Buf_Ptr set up for STD_EPRINTF
;*
;****************************************************************
Set_ext_error_subst proc near ;AN022;
mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class
mov string_ptr_2,dx ;AN022; get address of failed string
mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block
mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer
mov Extend_Buf_ptr,ax ;AN022; get message number in control block
ret ;AN022; return
Set_ext_error_subst endp ;AN022;
Break <SavUDir - preserve the users current directory on a particular drive>
;
; SavUDir - move the user's current directory on a drive into UserDir1
; SavUDir1 - move the user's current directory on a drive into a specified
; buffer
;
; Inputs: DL has 1-based drive number
; ES:DI has destination buffer (SavUDir1 only)
; Outputs: Carry Clear
; DS = TranGroup
; Carry Set
; AX has error code
; Registers Modified: AX, SI
;
SAVUDIR:
MOV DI,OFFSET TRANGROUP:USERDIR1
SAVUDIR1:
MOV AL,DL
ADD AL,'@'
CMP AL,'@'
JNZ GOTUDRV
ADD AL,[CURDRV]
INC AL ; A = 1
GOTUDRV:
STOSB
MOV AH,[DIRCHAR]
MOV AL,':'
STOSW
PUSH ES
POP DS
ASSUME DS:NOTHING
MOV SI,DI
MOV AH,CURRENT_DIR ; Get the Directory Text
INT int_command
retc
PUSH CS
POP DS
ASSUME DS:TRANGROUP
return
CRLF2:
PUSH DX
MOV DX,OFFSET TRANGROUP:ACRLF_ptr
PR:
PUSH DS
PUSH CS
POP DS
invoke std_printf
POP DS
POP DX
return
;
; These routines (SCANOFF, DELIM) are called in batch processing when DS
; may NOT be TRANGROUP
;
ASSUME DS:NOTHING,ES:NOTHING
SCANOFF:
LODSB
CALL DELIM
JZ SCANOFF
DEC SI ; Point to first non-delimiter
return
;
; Input: AL is character to classify
; Output: Z set if delimiter
; NZ set otherwise
; Registers modified: none
;
DELIM:
CMP AL,' '
retz
CMP AL,'='
retz
CMP AL,','
retz
CMP AL,';'
retz
CMP AL,9 ; Check for TAB character
retz
CMP AL,0ah ; Check for line feed character - BAS
return
ASSUME DS:TRANGROUP,ES:TRANGROUP
FCB_TO_ASCZ: ; Convert DS:SI to ASCIZ ES:DI
MOV CX,8
MAINNAME:
LODSB
CMP AL,' '
JZ SKIPSPC
STOSB
SKIPSPC:
LOOP MAINNAME
LODSB
CMP AL,' '
JZ GOTNAME
MOV AH,AL
MOV AL,dot_chr
STOSB
XCHG AL,AH
STOSB
MOV CL,2
EXTNAME:
LODSB
CMP AL,' '
JZ GOTNAME
STOSB
LOOP EXTNAME
GOTNAME:
XOR AL,AL
STOSB
return
STRCOMP:
;
; Compare ASCIZ DS:SI with ES:DI.
; SI,DI destroyed.
;
CMPSB
retnz ; Strings not equal
cmp byte ptr [SI-1],0 ; Hit NUL terminator?
retz ; Yes, strings equal
jmp short STRCOMP ; Equal so far, keep going
CRPRINT:
PUSH AX
MOV AL,13
PUSH CX
PUSH DI
MOV DI,DX
MOV CX,-1
PUSH ES
PUSH DS
POP ES
REPNZ SCASB ; LOOK FOR TERMINATOR
mov byte ptr [di-1],0 ; nul terminate the string
POP ES
mov string_ptr_2,dx
mov dx,offset trangroup:string_buf_ptr
invoke std_printf
mov ds:byte ptr [di-1],13 ; now put the CR back
JC ERROR_OUTPUT
POP DI
POP CX
POP AX
return
ERROR_OUTPUT:
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE_ptr
CMP [PIPEFLAG],0
JZ GO_TO_ERROR
invoke PipeOff
MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr
GO_TO_ERROR:
JMP CERROR
ASSUME DS:TRANGROUP,ES:TRANGROUP
PATHCHRCMP:
;---- Mod for path invocation ----
PUBLIC pathchrcmp
;----
push ax
mov ah,'/'
CMP [SWITCHAR],ah
JZ NOSLASHT
CMP AL,'/'
jz pccont
NOSLASHT:
CMP AL,'\'
pccont:
pop ax
return
; Drive taken from FCB
; User dir saved in userdir1
;
; Zero set if path dir, CHDIR to this dir, FCB filled with ?
; NZ set if path/file, CHDIR to file, FCB has file (parsed fill ' ')
; [DESTTAIL] points to parse point
; Carry set if no CHDIRs worked, FCB not altered.
; DESTISDIR set non zero if PATHCHRs in path (via SETPATH)
;
PATHCRUNCH:
mov [msg_numb],0 ;AN022; Set up message flag
MOV DL,DS:[FCB]
CALL SAVUDIR
jc pcrunch_cderrJ ;AN022; if error on current dir - report
invoke SETPATH
TEST [DESTINFO],2
JNZ TRYPEEL ; If ? or * cannot be pure dir
MOV AH,CHDIR
INT int_command
jnc chdir_worked ;AN022; no error - continue
invoke get_ext_error_number ;AN022; get the extended error
cmp ax,error_path_not_found ;AN022; if path not found
jz trypeel ;AC022; keep trying
cmp ax,error_access_denied ;AN022; if access denied
jz trypeel ;AC022; keep trying
mov [msg_numb],ax ;AN022; set up message flag
jmp peelfail ;AN022; exit with other error
chdir_worked:
invoke SETREST1
MOV AL,'?' ; *.* is default file spec if pure dir
MOV DI,5DH
MOV CX,11
REP STOSB
XOR AL,AL ; Set zero
return
pcrunch_cderrj: ;AN022; need this for long jmp
jmp pcrunch_cderr ;AN022;
TRYPEEL:
MOV SI,[PATHPOS]
DEC SI ; Point at NUL
MOV AL,[SI-1]
CMP [KPARSE],0
JNZ DELSTRT ; Last char is second KANJI byte, might be '\'
CALL PATHCHRCMP
JZ PEELFAIL ; Trailing '/'
DELSTRT:
MOV CX,SI
MOV SI,DX
PUSH DX
DELLOOP:
CMP SI,CX
JZ GOTDELE
LODSB
invoke TESTKANJ
JZ NOTKANJ8
INC SI
JMP DELLOOP
NOTKANJ8:
CALL PATHCHRCMP
JNZ DELLOOP
MOV DX,SI
DEC DX
JMP DELLOOP
GOTDELE:
MOV SI,DX
POP DX
CMP SI,DX
JZ BADRET
MOV CX,SI
MOV SI,DX
DELLOOP2: ; Set value of KPARSE
CMP SI,CX
JZ TRYCD
MOV [KPARSE],0
LODSB
INVOKE TESTKANJ
JZ DELLOOP2
INC SI
INC [KPARSE]
JMP DELLOOP2
TRYCD:
push ax
mov al,dot_chr
CMP BYTE PTR [SI+1],al
pop ax
JZ PEELFAIL ; If . or .., pure cd should have worked
mov al,[si-1]
CMP al,':' ; Special case d:\file
JZ BADRET
CMP [KPARSE],0
JNZ NOTDOUBLESL ; Last char is second KANJI byte, might be '\'
CALL PATHCHRCMP
JNZ NOTDOUBLESL
PEELFAIL:
STC ; //
return
NOTDOUBLESL:
MOV BYTE PTR [SI],0
MOV AH,CHDIR
INT int_command
JNC CDSUCC
pcrunch_cderr:
invoke get_ext_error_number ;AN022; get the extended error
mov [msg_numb],ax ;AN022; set up message flag
or si,si ;AN022; set up zero flag to not zero
stc ;AN022; set up carry flag
return
BADRET:
MOV AL,[SI]
CALL PATHCHRCMP ; Special case 'DIRCHAR'file
STC
retnz
XOR BL,BL
XCHG BL,[SI+1]
MOV AH,CHDIR
INT int_command
jc pcrunch_cderr ;AN022; go to error exit
MOV [SI+1],BL
CDSUCC:
invoke SETREST1
INC SI ; Reset zero
MOV [DESTTAIL],SI
pushf ;AN015; save flags
cmp dirflag,-1 ;AN015; don't do parse if in DIR
jz pcrunch_end ;AN015;
MOV DI,FCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H ; Parse with default drive
INT int_command
pcrunch_end:
popf ;AN015; get flags back
return
trancode ends
end


View File

@@ -0,0 +1,551 @@
page 80,132
; SCCSID = @(#)tfor.asm 4.1 85/09/17
; SCCSID = @(#)tfor.asm 4.1 85/09/17
TITLE Part3 COMMAND Transient Routines
; For loop processing routines
.xlist
.xcref
include comsw.asm
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
include comseg.asm
include comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN BATCH:WORD
EXTRN ECHOFLAG:BYTE
EXTRN FORFLAG:BYTE
EXTRN FORPTR:WORD
EXTRN NEST:WORD
EXTRN NULLFLAG:BYTE
EXTRN PIPEFILES:BYTE
EXTRN SINGLECOM:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN Extend_buf_ptr:word ;AN000;
extrn fornestmes_ptr:word
EXTRN msg_disp_class:byte ;AN000;
extrn string_buf_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
extrn arg:byte ; the arg structure!
EXTRN COMBUF:BYTE
EXTRN RESSEG:WORD
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
EXTRN docom:near
EXTRN docom1:near
EXTRN forerror:near
EXTRN tcommand:near
PUBLIC $for
PUBLIC forproc
; All batch proccessing has DS set to segment of resident portion
ASSUME DS:RESGROUP,ES:TRANGROUP
FORTERM:
push cs ;AN037; Get local segment into
pop ds ;AN037; DS, ES
push cs ;AN037;
pop es ;AN037;
call ForOff
mov ds,ResSeg
ASSUME DS:RESGROUP
CMP [SINGLECOM],0FF00H
JNZ BATCRLF
CMP NEST,0 ;G See if we have nested batch files
JNZ BATCRLF ;G Yes - don't exit just yet
MOV [SINGLECOM],-1 ; Cause a terminate
JMP SHORT NOFORP2
BATCRLF:
test [ECHOFLAG],1 ;G Is echo on?
JZ NOFORP2 ;G no - exit
TEST [BATCH], -1 ;G print CRLF if in batch
JZ NOFORP2 ;G
invoke CRLF2
NOFORP2:
JMP TCOMMAND
;------
; For-loop processing. For loops are of the form:
; for %<loop-variable> in (<list>) do <command>
; where <command> may contain references of the form %<variable>, which are
; later substituted with the items in <list>. The for-loop structure is
; set-up by the procedure '$for'; successive calls to 'forproc' execute
; <command> once for each item in <list>. All of the information needed for
; loop processing is stored on a piece of memory gotten from 'alloc'. This
; structure is actually fairly large, on the order of 700 bytes, and includes
; a complete copy of the original command-line structure as parsed by
; 'parseline', loop control variables, and a dma buffer for the
; 'FindFirst/FindNext' expansion of wildcard filenames in <list>. When loop
; processing has completed, this chunk of memory is returned to the system.
;
; All of the previously defined variables, in 'datares', used for loop
; processing may be erased. Only one, (DW) ForPtr, need be allocated.
;
; The error message, 'for_alloc_mes', should be moved into the file
; containing all of the other error messages.
;
; Referencing the allocated for-loop structure is a little tricky.
; At the moment, a byte is defined as part of a new segment, 'for_segment'.
; When 'forproc' actually runs, ES and DS are set to point to the base of the
; new chunk of memory. References to this byte, 'f', thus assemble correctly
; as offsets of ES or DS. 'f' would not be necessary, except that the
; assembler translates an instruction such as 'mov AX, [for_minarg]' as an
; immediate move of the offset of 'for_minarg' into AX. In other words, in
; terms of PDP-11 mnemonics, the assembler ACTUALLY assembles
; mov AX, #for_minarg ; AX := 02CA (for example)
; instead of
; mov AX, for_minarg ; AX := [02CA] (contents of 02CA)
; By using 'f', we pretend that we are actually referencing an allocated
; structure, and the assembler coughs up the code we want. Notice that it
; doesn't matter whether we put brackets around the location or not -- the
; assembler is "smart" enough to know that we want an address instead of the
; contents of that location.
;
; Finally, there now exists the potential to easily implement nested loops.
; One method would be to have a link field in each for-structure pointing to
; its parent. Variable references that couldn't be resolved in the local
; frame would cause a search of prior frames. For-structures would still be
; allocated and released in exactly the same fashion. The only limit on the
; number of nested loops would be memory size (although at 700 bytes a pop,
; memory wouldn't last THAT long). Alternately, a small structure could be
; maintained in the resident data area. This structure would be an array of
; control-variable names and pointers to for-structure blocks. This would
; greatly speed up the resolution of non-local variable references. However,
; since space in the resident is precious, we would have to compromise on a
; "reasonable" level of nesting -- 10, 16, 32 levels, whatever. For-structure
; allocation and de-allocation would have to be modified slightly to take this
; new structure into account.
;
; Oops, just one more thing. Forbuf need not be a part of the for-structure.
; It could just as well be one structure allocated in 'transpace'. Actually,
; it may be easier to allocate it as part of 'for_segment'.
;------
include fordata.asm
$for_exit:
jmp forterm ; exceeding maxarg means all done
forproc:
assume DS:resgroup
mov AX, [ForPtr]
mov DS, AX
mov ES, AX ; operate in for-info area
assume DS:for_segment, ES:for_segment
mov DX, OFFSET fordma
trap Set_Dma
for_begin:
cmp f.for_expand, 0 ; non-zero for_expand equals FALSE
je for_begin1
inc f.for_minarg
for_begin1:
mov BX, f.for_minarg ; current item in <list> to examine
cmp BX, f.for_maxarg
jg $for_exit ; exceeding maxarg means all done
mov AX, OFFSET for_args.argv
invoke argv_calc ; compute argv[x] address
mov CX, [BX].argstartel
mov DX, [BX].argpointer
test [bx].argflags,00000100b ; Is there a path separator in this arg?
jnz forsub ; Yes, argstartel should be correct
mov si, [BX].argpointer
mov al,lparen
cmp byte ptr [si-1],al ; If the current token is the first
jnz forsub ; one in the list and originally had
inc cx ; the opening paren as its first char,
; the argstartel ptr needs to be
; advanced passed it before the prefix
; length is computed.
mov al,':'
cmp byte ptr [si+1],al ; If the token begins with "(d:",
jnz forsub ; argstartel has to be moved over the
add cx,2 ; rest of the prefix as well.
forsub:
sub CX, DX ; compute length of pathname prefix
cmp f.for_expand, 0 ; are we still expanding a name?
je for_find_next ; if so, get next matching filename
test [BX].argflags, MASK wildcard
jnz for_find_first ; should we expand THIS (new) arg?
mov CX, [BX].arglen ; else, just copy all of it directly
jmp for_smoosh
for_find_first:
PUSH CX
XOR CX,CX
trap Find_First ; and search for first filename match
POP CX
jmp for_result
for_find_next:
trap Find_Next ; search for next filename match
for_result:
mov AX, -1 ; assume worst case
jc forCheck
mov ax,0
forCheck: ; Find* returns 0 for SUCCESS
mov f.FOR_EXPAND, AX ; record success of findfirst/next
or AX, AX ; anything out there?
jnz for_begin ; if not, try next arg
for_smoosh:
mov SI, [BX].argpointer ; copy argv[arg][0,CX] into destbuf
mov DI, OFFSET forbuf ; some days this will be the entire
rep movsb ; arg, some days just the path prefix
cmp f.FOR_EXPAND, 0 ; if we're not expanding, we can
jnz for_make_com ; skip the following
mov SI, OFFSET fordma.find_buf_pname
for_more: ; tack on matching filename
cmp BYTE PTR [SI], 0
je for_make_com
movsb
jnz for_more
for_make_com:
xor AL, AL ; tack a null byte onto the end
stosb ; of the substitute string
xor CX, CX ; character count for command line
not CX ; negate it -- take advantage of loopnz
xor BX, BX ; argpointer
mov DI, OFFSET TRANGROUP:COMBUF+2
mov bl, f.FOR_COM_START ; argindex
mov DH, f.FOR_VAR ; %<for-var> is replaced by [forbuf]
; time to form the <command> string
push CS
pop ES
assume ES:trangroup
mov AX, OFFSET for_args ; translate offset to pointer
invoke argv_calc
mov si,[bx].arg_ocomptr
inc si ; mov ptr passed beginning space
for_make_loop:
mov al,[si] ; the <command> arg, byte by byte
inc si
cmp AL,'%' ; looking for %<control-variable>
jne for_stosb ; no % ... add byte to string
cmp BYTE PTR [SI], DH ; got the right <variable>?
jne for_stosb ; got a %, but wrong <variable>
inc SI ; skip over <for-variable>
push SI
mov SI, OFFSET forbuf ; substitute the <item> for <variable>
; to make a final <command> to execute
sloop:
lodsb ; grab all those <item> bytes, and
stosb ; add 'em to the <command> string,
or AL, AL ; until we run into a null
loopnz sloop
dec DI ; adjust length and <command> pointer
inc CX ; so we can overwrite the null
pop SI
jmp for_make_loop ; got back for more <command> bytes
for_stosb:
stosb ; take a byte from the <command> arg
dec CX ; and put it into the <command> to be
; executed (and note length, too)
cmp al,0dh ; If not done, loop.
jne for_make_loop
for_made_com: ; finished all the <command> args
not CL ; compute and record command length
mov [COMBUF+1], CL
mov DS, [RESSEG]
assume DS:resgroup
test [ECHOFLAG],1 ; shall we echo this <command>, dearie?
jz noecho3
cmp nullflag,nullcommand ;G was there a command last time?
jz No_crlf_pr ;G no - don't print crlf
invoke CRLF2 ;G Print out prompt
no_crlf_pr:
mov nullflag,0 ;G reset no command flag
push CS
pop DS
assume DS:trangroup
push di
invoke PRINT_PROMPT ;G Prompt the user
pop di
mov BYTE PTR ES:[DI-1],0 ; yeah, PRINT it out...
mov string_ptr_2,OFFSET TRANGROUP:COMBUF+2
mov dx,offset trangroup:string_buf_ptr
invoke std_printf
mov BYTE PTR ES:[DI-1], 0DH
jmp DoCom
noecho3: ; run silent, run deep...
assume DS:resgroup
mov nullflag,0 ;G reset no command flag
push CS
pop DS
assume DS:trangroup
jmp docom1
fornesterrj: ; no multi-loop processing... yet!
assume ES:resgroup
call ForOff
jmp fornesterr
forerrorj:
jmp forerror
break $For
assume ds:trangroup,es:trangroup
$for:
mov ES, [RESSEG]
assume ES:resgroup
cmp ForFlag,0 ; is another one already running?
jnz fornesterrj ; if flag is set.... boom!
;
; Turn off any pipes in progress.
;
cmp [PIPEFILES],0 ; Only turn off if present.
jz NoPipe
invoke PipeDel
NoPipe:
xor DX, DX ; counter (0 <= DX < argvcnt)
call nextarg ; move to next argv[n]
jc forerrorj ; no more args -- bad forloop
cmp AL,'%' ; next arg MUST start with '%'...
jne forerrorj
mov BP, AX ; save forloop variable
lodsb
or AL, AL ; and MUST end immediately...
jne forerrorj
call nextarg ; let's make sure the next arg is 'in'
jc forerrorj
and AX, NOT 2020H ; uppercase the letters
cmp AX, in_word
jne forerrorj
lodsb
or AL, AL ; it, too, must end right away
je CheckLParen
;
; Not null. Perhaps there are no spaces between this and the (:
; FOR %i in(foo bar...
; Check for the Lparen here
;
CMP AL,lparen
JNZ forerrorj
;
; The token was in(... We strip off the "in" part to simulate a separator
; being there in the first place.
;
ADD [BX].argpointer,2 ; advance source pointer
ADD [BX].arg_ocomptr,2 ; advance original string
SUB [BX].arglen,2 ; decrement the appropriate length
;
; SI now points past the in(. Simulate a nextarg call that results in the
; current value.
;
MOV ax,[si-1] ; get lparen and next char
jmp short lpcheck
CheckLParen:
call nextarg ; lparen delimits beginning of <list>
jc forerrorj
lpcheck:
cmp al, lparen
jne forerrorj
cmp ah,0
je for_paren_token
cmp ah, rparen ; special case: null list
jne for_list_not_empty
jmp forterm
for_list_not_empty:
inc [bx].argpointer ; Advance ptr past "("
; Adjust the rest of this argv entry
dec [bx].arglen ; to agree.
inc si ; Inc si so check for ")" works
jmp for_list
for_paren_token:
call nextarg ; what have we in our <list>?
jc forerrorj
cmp ax, nullrparen ; special case: null list
jne for_list
jmp forterm
forerrorjj:
jmp forerror
for_list: ; skip over rest of <list>
mov CX, DX ; first arg of <list>
skip_list:
add si,[bx].arglen
sub si,3 ; si = ptr to last char of token
mov al,rparen
cmp byte ptr [si],al ; Is this the last element in <list>
je for_end_list ; Yes, exit loop.
call nextarg ; No, get next arg <list>
jc forerrorjj ; If no more and no rparen, error.
jmp skip_list
for_end_list:
mov DI, DX ; record position of last arg in <list>
mov byte ptr [si],0 ; Zap the rparen
cmp ax,nullrparen ; Was this token only a rparen
jz for_do ; Yes, continue
inc di ; No, inc position of last arg
for_do:
call nextarg ; now we had BETTER find a 'do'...
jc forerrorjj
and AX, NOT 2020H ; uppercase the letters
cmp AX, do_word
jne forerrorjj
lodsb
or AL, AL ; and it had BETTER be ONLY a 'do'...
jne forerrorjj
call nextarg ; on to the beginning of <command>
jc forerrorjj ; null <command> not legal
push AX
push BX
push CX
push DX ; preserve registers against disaster
push DI
push SI
push BP
invoke FREE_TPA ; need to make free memory, first
ASSUME ES:RESGROUP
call ForOff
mov BX, SIZE for_info - SIZE arg_unit
invoke Save_Args ; extra bytes needed for for-info
pushf
mov [ForPtr], AX
invoke ALLOC_TPA ; ALLOC_TPA clobbers registers...
popf
pop BP
pop SI
pop DI
pop DX
pop CX
pop BX
pop AX
jc for_alloc_err
push ES ; save resgroup seg...
push [ForPtr]
pop ES
assume ES:for_segment ; make references to for-info segment
dec CX ; forproc wants min pointing before
dec DI ; first arg, max right at last one
mov f.for_minarg, CX
mov f.for_maxarg, DI
mov f.for_com_start, DL
mov f.for_expand, -1 ; non-zero means FALSE
mov AX, BP
mov f.for_var, AH
pop ES
assume ES:resgroup
inc [FORFLAG]
cmp [SINGLECOM], -1
jnz for_ret
mov [SINGLECOM], 0FF00H
for_ret:
ret
for_alloc_err:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block
jmp cerror
nextarg:
inc DX ; next argv[n]
cmp DX, arg.argvcnt ; make sure we don't run off end
jge nextarg_err ; of argv[]...
mov BX, DX
mov AX, OFFSET TRANGROUP:arg.argv
invoke argv_calc ; convert array index to pointer
mov SI, [BX].argpointer ; load pointer to argstring
lodsw ; and load first two chars
clc
ret
nextarg_err:
stc
ret
ASSUME DS:TRANGROUP,ES:TRANGROUP
FORNESTERR:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV DX,OFFSET TRANGROUP:FORNESTMES_ptr
CMP [SINGLECOM],0FF00H
JNZ NOFORP3
MOV [SINGLECOM],-1 ; Cause termination
NOFORP3:
POP DS
ASSUME DS:TRANGROUP
JMP CERROR
;
; General routine called to free the for segment. We also clear the forflag
; too. Change no registers.
;
PUBLIC ForOff
ForOff:
assume DS:NOTHING,ES:NOTHING
SaveReg <AX,ES>
mov es,ResSeg
assume es:ResGroup
mov AX,ForPtr
or ax,ax
jz FreeDone
push es
mov es,ax
mov ah,dealloc
int 21h
pop es
FreeDone:
mov ForPtr,0
mov ForFlag,0
RestoreReg <ES,AX>
return
trancode ends
end


View File

@@ -0,0 +1,655 @@
page 80,132
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
TITLE Part7 COMMAND Transient Routines
; More misc routines
.xlist
.xcref
INCLUDE comsw.asm
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
EXTRN RSTACK:BYTE
CodeRes ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN CALL_FLAG:BYTE
EXTRN EchoFlag:BYTE
EXTRN EXEC_BLOCK:BYTE
EXTRN EXTCOM:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN PIPEPTR:WORD
EXTRN PIPESTR:BYTE
EXTRN RESTDIR:BYTE
EXTRN RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADDRV_PTR:WORD
EXTRN BADNAM_PTR:WORD
EXTRN COMTAB:BYTE ;AC000;
EXTRN extend_buf_ptr:word ;AN000;
EXTRN msg_disp_class:byte ;AN000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
EXTRN APPEND_EXEC:BYTE ;AN041;
EXTRN CHKDRV:BYTE
EXTRN COMBUF:BYTE
EXTRN EXECPATH:BYTE
EXTRN EXEC_ADDR:DWORD
EXTRN FILTYP:BYTE
EXTRN IDLEN:BYTE
EXTRN KPARSE:BYTE ;AC000;
EXTRN PARM1:BYTE
EXTRN PARM2:BYTE
EXTRN PathPos:word
EXTRN RESSEG:WORD
EXTRN RE_INSTR:BYTE
EXTRN SPECDRV:BYTE
EXTRN SWITCHAR:BYTE
EXTRN switch_list:byte
EXTRN TRAN_TPA:WORD
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN APPEND_PARSE:NEAR ;AN010;
EXTRN BATCOM:NEAR
EXTRN DOCOM1:NEAR
EXTRN PIPEERRSYN:NEAR
EXTRN TCOMMAND:NEAR
IF IBM
EXTRN ROM_EXEC:NEAR
EXTRN ROM_SCAN:NEAR
ENDIF
PUBLIC CERROR
PUBLIC DRVBAD
PUBLIC EXTERNAL
PUBLIC FNDCOM
PUBLIC PRESCAN
PUBLIC SWITCH
ASSUME DS:TRANGROUP
;---------------------------
; We can get rid of this switch processing code if we can take
; care of the remaining two calls to switch, later in the file.
; However, I have not checked whether or not any other files use
; switch -- after all, it IS public!
;---------------------------
RETSW:
XCHG AX,BX ; Put switches in AX
return
SWITCH:
XOR BX,BX ; Initialize - no switches set
SWLOOP:
INVOKE SCANOFF ; Skip any delimiters
CMP AL,[SWITCHAR] ; Is it a switch specifier?
JNZ RETSW ; No -- we're finished
OR BX,fSwitch ; Indicate there is a switch specified
INC SI ; Skip over the switch character
INVOKE SCANOFF
CMP AL,0DH
JZ RETSW ; Oops
INC SI
; Convert lower case input to upper case
INVOKE UPCONV
MOV DI,OFFSET TRANGROUP:switch_list
MOV CX,SWCOUNT
REPNE SCASB ; Look for matching switch
JNZ BADSW
MOV AX,1
SHL AX,CL ; Set a bit for the switch
OR BX,AX
JMP SHORT SWLOOP
BADSW:
JMP SHORT SWLOOP
SWCOUNT EQU 5 ; Length of switch_list
DRVBAD:
MOV DX,OFFSET TRANGROUP:BADDRV_ptr
JMP CERROR
externalj:
jmp EXTERNAL
fndcom: ; search the internal command table
OR AL,AL ; Get real length of first arg
jz externalj ; If 0, it must begin with "\" so has
; to be external.
; barryf code starts here
IF IBM
call test_append ; see if APPEND installed
je contcom ; not loaded
append_internal:
mov cl,TRANGROUP:IDLEN
mov ch,0
mov pathpos,cx
inc append_exec ;AN041; set APPEND to ON
invoke ioset ; re-direct the o'l io
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set invoke function
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
mov AX,0AE01H
int 2FH ; execute command
cmp TRANGROUP:IDLEN,0 ; execute requested
jne contcom
jmp Cmd_done
contcom: ; continue with internal scan
ENDIF
; barryf code ends here
mov DI, OFFSET TRANGROUP:COMTAB
XOR CX,CX
findcom:
mov SI, offset TRANGROUP:IDLEN+1 ; pointer to command argument
mov CL, [DI] ; load length of internal command
inc di ; advance past length
jcxz externalj ; if it's zero, we're out of internals
cmp CL, IDLEN ; that of the command argument
jnz abcd ; lengths not equal ==> strings not eq
MOV PathPos,CX ; store length of command
repz cmpsb
abcd:
lahf ; save the good ol' flags
add DI, CX ; skip over remaining internal, if any
mov AL, BYTE PTR [DI] ; load drive-check indicator byte (DCIB)
mov [CHKDRV], AL ; save command flag byte in chkdrv
inc DI ; increment DI (OK, OK, I'll stop)
mov BX, WORD PTR [DI] ; load internal command address
inc DI ; skip over the puppy
inc DI
sahf ; remember those flags?
jnz findcom ; well, if all the cmps worked...
;
; All messages get redirected.
;
cmp append_exec,0 ;AN041; APPEND just executed?
jnz dont_set_io ;AN041; Yes - this junk is already set
invoke ioset ; re-direct the ol' i/o
dont_set_io: ;AN041;
invoke SETSTDINON ;AN026; turn on critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
test [CHKDRV], fCheckDrive ; did we wanna check those drives?
jz nocheck
mov AL, [PARM1] ; parse_file_descriptor results tell
or AL, [PARM2] ; us whether those drives were OK
cmp AL, -1
jnz nocheck
jmp drvbad
;
; The user may have omitted the space between the command and its arguments.
; We need to copy the remainder of the user's command line into the buffer.
; Note that thisdoes not screw up the arg structure; it points into COMBUF not
; into the command line at 80.
;
nocheck:
call cmd_copy
switcheck:
test [CHKDRV], fSwitchAllowed ; Does the command take switches
jnz realwork ; Yes, process the command
call noswit ; No, check to see if any switches
jnz realwork ; None, process the command
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
jmp CERROR ; Print error and chill out...
realwork:
call BX ; do some real work, at last
; See if we're in a batch CALL command. If we are, reprocess the command line,
; otherwise, go get another command.
Cmd_done:
push cs ; g restore data segment
pop ds ; g
push ds ; g save data segment
mov ds,[resseg] ; g get segment containing call flag
ASSUME ds:resgroup
cmp call_flag, call_in_progress ; G Is a call in progress?
mov call_flag, 0 ; G Either way, reset flag
pop ds ; g get data segment back
jz incall ; G
jmp tcommand ; chill out...
incall:
JMP DOCOM1
noswit:
push di ; Save di
mov di,81h ; di = ptr to command args
mov si,80h ; Get address of length of command args
lodsb ; Load length
mov cl,al ; Move length to cl
xor ch,ch ; Zero ch
mov al,[SWITCHAR] ; al = switch character
cmp al,0 ; Turn off ZF
repnz scasb ; Scan for a switch character and return
pop di ; with ZF set if one was found
ret
EXTERNAL:
IF IBM
call test_append ; check to see if append installed
je not_barryf ; no - truly external command
jmp append_internal ; yes - go to Barryf code
not_barryf:
ENDIF
MOV [FILTYP],0
MOV DL,[SPECDRV]
MOV [IDLEN],DL
IF IBM
MOV [ROM_CALL],0
PUSH DX
MOV DX,OFFSET TRANGROUP:IDLEN
CALL ROM_SCAN
POP DX
JNC DO_SCAN
INC [ROM_CALL]
JMP PostSave
DO_SCAN:
ENDIF
IF IBM
PostSave:
ENDIF
MOV DI,OFFSET TRANGROUP:EXECPATH
MOV BYTE PTR [DI],0 ; Initialize to current directory
IF IBM
CMP [ROM_CALL],0
JZ Research
JMP NeoExecute
ENDIF
RESEARCH:
invoke path_search ; find the mother (result in execpath)
or AX, AX ; did we find anything?
je badcomj45 ; null means no (sob)
cmp AX, 04H ; 04H and 08H are .exe and .com
jl rsrch_br1 ; fuckin' sixteen-bit machine ought
jmp execute ; to be able to handle a SIXTEEN-BIT
rsrch_br1: ; DISPLACEMENT!!
jmp batcom ; 02H is .bat
BADCOMJ45:
JMP BADCOM
ASSUME DS:TRANGROUP,ES:TRANGROUP
EXECUTE:
NeoExecute:
invoke IOSET
invoke SETSTDINOFF ;AN026; turn off critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT int_command ; Now running in "free" space
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
INC [EXTCOM] ; Indicate external command
MOV [RESTDIR],0 ; Since USERDIR1 is in transient, insure
; this flag value for re-entry to COMMAND
MOV DI,FCB
MOV SI,DI
MOV CX,052H ; moving (100h-5Ch)/2 = 80h-2Eh
REP MOVSW ; Transfer parameters to resident header
MOV DX,OFFSET TRANGROUP:EXECPATH
MOV BX,OFFSET RESGROUP:EXEC_BLOCK
MOV AX,EXEC SHL 8
IF IBM
TEST [ROM_CALL],-1
JZ OK_EXEC
JMP ROM_EXEC
OK_EXEC:
ENDIF
;
; we are now running in free space. anything we do from here on may get
; trashed. Move the stack (also in free space) to allocated space because
; since EXEC restores the stack, somebody may trash what is on the stack.
;
MOV CX,ES
MOV SS,CX
MOV SP,OFFSET RESGROUP:RSTACK
JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident
BADCOM:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
CERROR:
INVOKE std_eprintf
JMP TCOMMAND
;
; Prescan converts the input buffer into a canonicalized form. All
; redirections and pipes are removed.
;
PRESCAN: ; Cook the input buffer
ASSUME DS:TRANGROUP,ES:TRANGROUP
XOR CX,CX
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,SI
CountQuotes:
LODSB ; get a byte
CMP AL,22h ; is it a quote?
JNZ CountEnd ; no, try for end of road
INC CH ; bump count
JMP CountQuotes ; go get next char
CountEnd:
CMP AL,13 ; end of road?
JNZ CountQuotes ; no, go back for next char
;;;; IF KANJI 3/3/KK
PUSH CX ; save count
MOV SI,DI ; get back beginning of buffer
KanjiScan:
LODSB ; get a byte
INVOKE TestKanj ; is it a leadin byte
JZ KanjiQuote ; no, check for quotes
MOV AH,AL ; save leadin
LODSB ; get trailing byte
CMP AX,8140h ; is it Kanji space
JNZ KanjiScan ; no, go get next
MOV [SI-2],2020h ; replace with spaces
JMP KanjiScan ; go get next char
KanjiQuote:
CMP AL,22h ; beginning of quoted string
JNZ KanjiEnd ; no, check for end
DEC CH ; drop count
JZ KanjiScan ; if count is zero, no quoting
KanjiQuoteLoop:
LODSB ; get next byte
CMP AL,22h ; is it another quote
JNZ KanjiQuoteLoop ; no, get another
DEC CH ; yes, drop count
JMP KanjiScan ; go get next char
KanjiEnd:
CMP AL,13 ; end of line character?
JNZ KanjiScan ; go back to beginning
POP CX ; get back original count
;;;; ENDIF 3/3/KK
MOV SI,DI ; restore pointer to begining
PRESCANLP:
LODSB
;;;; IF KANJI 3/3/KK
INVOKE TESTKANJ
JZ NOTKANJ6
MOV [DI],AL
INC DI ; fake STOSB into DS
LODSB ; grab second byte
MOV [DI],AL ; fake stosb into DS
INC DI
INC CL
INC CL
JMP PRESCANLP
NOTKANJ6:
;;;; ENDIF 3/3/KK
CMP AL,'"' ; " character
JNZ TRYGREATER
DEC CH
JZ TRYGREATER
QLOOP:
MOV [DI],AL
INC DI
INC CL
LODSB
CMP AL,'"' ; " character
JNZ QLOOP
DEC CH
TRYGREATER:
CMP AL,rabracket
JNZ NOOUT
;
; We have found a ">" char. We need to see if there is another ">"
; following it.
;
CMP BYTE PTR [SI],al
JNZ NOAPPND
LODSB
INC [RE_OUT_APP] ; Flag >>
NOAPPND:
;
; Now we attempt to find the file name. First, scan off all whitespace
;
INVOKE SCANOFF
CMP AL,labracket ;AN040; was there no filename?
JZ REOUT_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREOFIL
;
; There was no file present. Set us up at end-of-line.
;
REOUT_ERRSET: ;AN040; set up for an error
mov byte ptr [di], 0dh ; Clobber first ">"
MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later
JMP PRESCANEND
GOTREOFIL:
PUSH DI
MOV DI,OFFSET RESGROUP:RE_OUTSTR
MOV BX,DI
PUSH ES
SETREOUTSTR: ; Get the output redirection name
LODSB
CMP AL,0DH
JZ GOTRESTR
INVOKE DELIM
JZ GOTRESTR
CMP AL,[SWITCHAR]
JZ GOTRESTR
CMP AL,'"' ;AN033; Is the character a quote?
JZ PIPEERRSYNJ5 ;AN033; Yes - get out quick - or system crashes
CMP AL,labracket ;AN002; Is char for input redirection
JZ ABRACKET_TERM ;AN002; yes - end of string
CMP AL,rabracket ;AN002; Is char for output redirection
JNZ NO_ABRACKET ;AN002; no - not end of string
abracket_term: ;AN002; have end of string by < or >
DEC SI ;AN002; back up over symbol
MOV AL,BLANK ;AN002; show delimiter as char
JMP SHORT GOTRESTR ;AN002; go process it
no_abracket: ;AN002; not at end of string
STOSB ; store it into resgroup
JMP SHORT SETREOUTSTR
NOOUT:
CMP AL,labracket
JNZ CHKPIPE
mov bx,si ; Save loc of "<"
INVOKE SCANOFF
CMP AL,rabracket ;AN040; was there no filename?
JZ REIN_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREIFIL
REIN_ERRSET: ;AN040; set up for error
mov byte ptr [di],0dh ; Clobber "<"
MOV WORD PTR [RE_INSTR],09H ; Cause an error later
JMP SHORT PRESCANEND
GOTREIFIL:
PUSH DI
MOV DI,OFFSET TranGROUP:RE_INSTR
MOV BX,DI
PUSH ES
PUSH CS
POP ES ; store in TRANGROUP
JMP SHORT SETREOUTSTR ; Get the input redirection name
CHKPIPE:
MOV AH,AL
CMP AH,AltPipeChr
JZ IsPipe3
CMP AH,vbar
JNZ CONTPRESCAN
IsPipe3:
;
; Only push the echo flag if we are entering the pipe for the first time.
;
CMP PipeFlag,0
JNZ NoEchoPush
SHL EchoFlag,1 ; push echo state and turn it off
NoEchoPush:
INC [PIPEFLAG]
INVOKE SCANOFF
CMP AL,0DH
JZ PIPEERRSYNJ5
CMP AL,AltPipeChr
JZ PIPEERRSYNJ5
CMP AL,vbar ; Double '|'?
JNZ CONTPRESCAN
PIPEERRSYNJ5:
PUSH ES
POP DS ; DS->RESGROUP
JMP PIPEERRSYN
;
; Trailing :s are allowed on devices. Check to be sure that there is more
; than just a : in the redir string.
;
GOTRESTR:
XCHG AH,AL
mov al,':'
SUB BX,DI ; compute negatinve of number of chars
CMP BX,-1 ; is there just a :?
JZ NotTrailCol ; yep, don't change
CMP BYTE PTR ES:[DI-1],al ; Trailing ':' OK on devices
JNZ NOTTRAILCOL
DEC DI ; Back up over trailing ':'
NOTTRAILCOL:
XOR AL,AL
STOSB ; NUL terminate the string
POP ES
POP DI ; Remember the start
CONTPRESCAN:
MOV [DI],AH ; "delete" the redirection string
INC DI
CMP AH,0DH
JZ PRESCANEND
INC CL
JMP PRESCANLP
PRESCANEND:
CMP [PIPEFLAG],0
JZ ISNOPIPE
MOV DI,OFFSET RESGROUP:PIPESTR
MOV [PIPEPTR],DI
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE SCANOFF
PIPESETLP: ; Transfer the pipe into the resident
LODSB ; pipe buffer
STOSB
CMP AL,0DH
JNZ PIPESETLP
ISNOPIPE:
MOV [COMBUF+1],CL
CMP [PIPEFLAG],0
PUSH CS
POP ES
return
cmd_copy proc near
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE Scanoff ; advance past separators...
add si,PathPos
mov di,81h
xor cx,cx
CmdCopy:
lodsb
stosb
cmp al,0dh
jz CopyDone
inc cx
jmp CmdCopy
CopyDone:
mov byte ptr ds:[80h],cl ; Store count
ret
cmd_copy endp
test_append proc near
mov BX,offset TRANGROUP:COMBUF ; barry can address
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set install check function
mov AX,0AE00H
int 2FH ; see if loaded
cmp AL,00H
ret
test_append endp
TRANCODE ENDS
END


View File

@@ -0,0 +1,487 @@
page 80,132
; SCCSID = @(#)tmisc2.asm 4.3 85/06/25
; SCCSID = @(#)tmisc2.asm 4.3 85/06/25
TITLE Part7 COMMAND Transient Routines
; More misc routines
.xlist
.xcref
INCLUDE comsw.asm
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
INCLUDE ioctl.inc
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
CodeRes ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN IFFlag:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN RE_OUTSTR:BYTE
EXTRN RE_OUT_APP:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN AccDen_PTR:WORD
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN FULDIR_PTR:WORD
EXTRN msg_disp_class:byte ;AN000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN DESTINFO:BYTE
EXTRN DESTISDIR:BYTE
EXTRN KPARSE:BYTE ;AC000;
EXTRN ONE_CHAR_VAL:BYTE ;AN011;
EXTRN PATHCNT:WORD
EXTRN PATHPOS:WORD
EXTRN PATHSW:WORD
EXTRN RE_INSTR:BYTE
EXTRN RESSEG:WORD
EXTRN SRCBUF:BYTE
EXTRN SWITCHAR:BYTE
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN CERROR:NEAR
IF IBM
EXTRN ROM_EXEC:NEAR
EXTRN ROM_SCAN:NEAR
ENDIF
PUBLIC IOSET
PUBLIC MOVE_TO_SRCBUF ;AN000;
PUBLIC PGETARG
PUBLIC SETPATH
PUBLIC TESTDOREIN
PUBLIC TESTDOREOUT
ASSUME DS:TRANGROUP
SETPATH:
;
; Get an ASCIZ argument from the unformatted parms
; DESTISDIR set if pathchars in string
; DESTINFO set if ? or * in string
;
MOV AX,[PATHCNT] ;AC000; get length of string
MOV SI,[PATHPOS] ;AC000; get start of source buffer
GETPATH:
MOV [DESTINFO],0
MOV [DESTISDIR],0
MOV SI,[PATHPOS]
MOV CX,[PATHCNT]
MOV DX,SI
JCXZ PATHDONE
PUSH CX
PUSH SI
INVOKE SWITCH
MOV [PATHSW],AX
POP BX
SUB BX,SI
POP CX
ADD CX,BX
MOV DX,SI
SKIPPATH:
;;;; IF KANJI 3/3/KK
MOV [KPARSE],0
SKIPPATH2:
;;;; ENDIF 3/3/KK
JCXZ PATHDONE
DEC CX
LODSB
;;;; IF KANJI 3/3/KK
INVOKE TESTKANJ
JZ TESTPPSEP
DEC CX
INC SI
INC [KPARSE]
JMP SKIPPATH2
TESTPPSEP:
;;;; ENDIF 3/3/KK
INVOKE PATHCHRCMP
JNZ TESTPMETA
INC [DESTISDIR]
TESTPMETA:
CMP AL,'?'
JNZ TESTPSTAR
OR [DESTINFO],2
TESTPSTAR:
CMP AL,star
JNZ TESTPDELIM
OR [DESTINFO],2
TESTPDELIM:
INVOKE DELIM
JZ PATHDONEDEC
CMP AL,[SWITCHAR]
JNZ SKIPPATH
PATHDONEDEC:
DEC SI
PATHDONE:
XOR AL,AL
XCHG AL,[SI]
INC SI
CMP AL,0DH
JNZ NOPSTORE
MOV [SI],AL ;Don't loose the CR
NOPSTORE:
MOV [PATHPOS],SI
MOV [PATHCNT],CX
return
PGETARG:
MOV SI,80H
LODSB
OR AL,AL
retz
CALL PSCANOFF
CMP AL,13
return
PSCANOFF:
LODSB
INVOKE DELIM
JNZ PSCANOFFD
CMP AL,';'
JNZ PSCANOFF ; ';' is not a delimiter
PSCANOFFD:
DEC SI ; Point to first non-delimiter
return
IOSET:
;
; ALL REGISTERS PRESERVED
;
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH DS
PUSH DX
PUSH AX
PUSH BX
PUSH CX
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
CMP [PIPEFLAG],0
JNZ NOREDIR ; Don't muck up the pipe
TEST IFFlag,-1
JNZ NoRedir
CALL TESTDOREIN
CALL TESTDOREOUT
NOREDIR:
POP CX
POP BX
POP AX
POP DX
POP DS
ASSUME DS:NOTHING
return
TESTDOREIN:
ASSUME DS:RESGROUP
CMP [RE_INSTR],0
retz
PUSH DS
PUSH CS
POP DS
MOV DX,OFFSET tranGROUP:RE_INSTR
MOV AX,(OPEN SHL 8)
MOV BX,AX
INT int_command
POP DS
JC REDIRERR
MOV BX,AX
MOV AL,0FFH
;
; Mega sleaze!! We move the SFN from the new handle spot into the old stdin
; spot. We invalidate the new JFN we got.
;
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table],AL
return
;
; We had some kind of error on the redirection. Figure out what the
; appropriate message should be; BX has the system call that failed
;
REDIRERR:
PUSH CS
POP DS
Call TriageError
;
; At this point, we have recognized the network-generated access denied error.
; The correct message is in DX
;
CMP AX,65
JZ CERRORJ ;AC000; just issue message returned
CMP BH,OPEN
JZ OpenError
;
; The error was for a create operation. Report the error as a creation error.
;
MOV DX,OFFSET TranGroup:FULDIR_PTR
CERRORJ:
JMP CERROR
;
; The system call was an OPEN. Report either file not found or path not found.
;
OpenError:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,ax ;AN000; get message number in control block
JMP CERROR
TESTDOREOUT:
ASSUME DS:RESGROUP
CMP [RE_OUTSTR],0
JNZ REOUTEXISTS ;AN017; need long jump
JMP NOREOUT ;AN017;
REOUTEXISTS:
CMP [RE_OUT_APP],0
JZ REOUTCRT
;
; The output redirection was for append. We open for write and seek to the
; end.
;
MOV DX,OFFSET RESGROUP:RE_OUTSTR
MOV AX,(OPEN SHL 8) OR 2 ;AC011; Open for read/write
PUSH AX
INT int_command
POP BX
JC OpenWriteError
MOV BX,AX
MOV AX,IOCTL SHL 8 ;AN035; Get attributes of handle
INT int_command ;AN035;
TEST DL,devid_ISDEV ;AN035; Is it a device?
JNZ SET_REOUT ;AN035; Yes, don't read from it
MOV AX,(LSEEK SHL 8) OR 2
MOV CX,-1 ;AC011; MOVE TO EOF -1
MOV DX,CX ;AC011;
INT int_command
PUSH CS ;AN011; Get transient seg to DS
POP DS ;AN011;
assume DS:Trangroup ;AN011;
MOV AX,(READ SHL 8) ;AN011; Read one byte from the
MOV CX,1 ;AN011; file into one_char_val
MOV DX,OFFSET Trangroup:ONE_CHAR_VAL;AN011;
INT int_command ;AN011;
JC OpenWriteError ;AN011; If error, exit
cmp ax,cx ;AN017; Did we read 1 byte?
jnz reout_0_length ;AN017; No - file must be 0 length
cmp one_char_val,01ah ;AN011; Was char an eof mark?
mov DS,[resseg] ;AN011; Get resident segment back
assume DS:Resgroup ;AN011;
JNZ SET_REOUT ;AN011; No, just continue
MOV AX,(LSEEK SHL 8) OR 1 ;AN011; EOF mark found
MOV CX,-1 ;AN011; LSEEK back one byte
MOV DX,CX ;AN011;
INT int_command ;AN011;
JMP SHORT SET_REOUT
reout_0_length: ;AN017; We have a 0 length file
mov DS,[resseg] ;AN017; Get resident segment back
assume DS:Resgroup ;AN017;
MOV AX,(LSEEK SHL 8) ;AN017; Move to beginning of file
XOR CX,CX ;AN017; Offset is 0
MOV DX,CX ;AN017;
INT int_command ;AN017;
JMP SHORT SET_REOUT ;AN017; now finish setting up redirection
OpenWriteError:
CMP AX,error_access_denied
STC ; preserve error
JNZ REOUTCRT ;AN017; need long jump
JMP REDIRERR ;AN017;
REOUTCRT:
MOV DX,OFFSET RESGROUP:RE_OUTSTR
XOR CX,CX
MOV AH,CREAT
PUSH AX
INT int_command
POP BX
JNC NOREDIRERR ;AC011;
JMP REDIRERR ;AC011;
NOREDIRERR: ;AN011;
MOV BX,AX
SET_REOUT:
;
; Mega sleaze!! We move the SFN from the new handle spot into the old stdout
; spot. We invalidate the new JFN we got.
;
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table+1],AL
NOREOUT:
return
;
; Compute length of string (including NUL) in DS:SI into CX. Change no other
; registers
;
Procedure DSTRLEN,NEAR
SaveReg <AX>
XOR CX,CX
CLD
DLoop: LODSB
INC CX
OR AL,AL
JNZ DLoop
SUB SI,CX
RestoreReg <AX>
return
EndProc DSTRLEN
Break <Extended error support>
;
; TriageError will examine the return from a carry-set system call and
; return the correct error if applicable.
;
; Inputs: outputs from a carry-settable system call
; No system calls may be done in the interrim
; Outputs: If carry was set on input
; carry set on output
; DX contains trangroup offset to printf message
; else
; No registers changed
;
Procedure TriageError,NEAR
retnc ; no carry => do nothing...
PUSHF
SaveReg <BX,CX,SI,DI,BP,ES,DS,AX,DX>
MOV AH,GetExtendedError
INT 21h
RestoreReg <CX,BX> ; restore original AX
MOV DX,OFFSET TranGroup:AccDen_PTR
CMP AX,65 ; network access denied?
JZ NoMove ; Yes, return it.
MOV AX,BX
MOV DX,CX
NoMove:
RestoreReg <DS,ES,BP,DI,SI,CX,BX>
popf
return
EndProc TriageError
PUBLIC Triage_Init
Triage_Init proc FAR
call TriageError
ret
Triage_Init endp
; ****************************************************************
; *
; * ROUTINE: MOVE_TO_SRCBUF
; *
; * FUNCTION: Move ASCIIZ string from DS:SI to SRCBUF. Change
; * terminating 0 to 0dH. Set PATHCNT to length of
; * string. Set PATHPOS to start of SRCBUF.
; *
; * INPUT: DS:SI points to ASCIIZ string
; * ES points to TRANGROUP
; *
; * OUTPUT: SRCBUF filled in with string terminated by 0dH
; * PATHCNT set to length of string
; * PATHPOS set to start of SRCBUF
; * CX,AX changed
; *
; ****************************************************************
assume es:trangroup,ds:nothing ;AN000;
MOVE_TO_SRCBUF PROC NEAR ;AN000;
push si ;AN000; save si,di
push di ;AN000;
push cx ;AN000;
mov di,offset TRANGROUP:srcbuf ;AN000; set ES:DI to srcbuf
xor cx,cx ;AN000; clear cx for counint
mov ax,cx ;AN000; clear ax
push di ;AN000; save start of srcbuf
lodsb ;AN000; get a character from DS:SI
mts_get_chars: ;AN000;
cmp al,0 ;AN000; was it a null char?
jz mts_end_string ;AN000; yes - exit
stosb ;AN000; no - store it in srcbuf
inc cx ;AN000; increment length count
lodsb ;AN000; get a character from DS:SI
jmp short mts_get_chars ;AN000; go check it
mts_end_string: ;AN000; we've reached the end of line
mov al,end_of_line_in ;AN000; store 0dH in srcbuf
stosb ;AN000;
pop di ;AN000; restore start of srcbuf
push cs ;AN000; set DS to local segment
pop ds ;AN000;
assume ds:trangroup ;AN000;
mov [pathcnt],cx ;AN000; set patchcnt to length count
mov [pathpos],di ;AN000; set pathpos to start of srcbuf
pop cx ;AN000; restore cx,di,si
pop di ;AN000;
pop si ;AN000;
RET ;AN000; exit
MOVE_TO_SRCBUF ENDP ;AN000;
TRANCODE ENDS
END


View File

@@ -0,0 +1,76 @@
page 80,132
; SCCSID = @(#)tparse.asm 4.1 87/04/28
; SCCSID = @(#)tparse.asm 4.1 87/04/28
TITLE COMMAND interface to SYSPARSE
.xlist
.xcref
INCLUDE comseg.asm ;AN000;
.list
.cref
TRANSPACE SEGMENT PUBLIC BYTE ;AN000;
CmpxSW equ 0 ;AN000; do not check complex list
KeySW equ 0 ;AN000; do not support keywords
Val2SW equ 0 ;AN000; do not Support value definition 2
IncSW equ 0 ;AN000; do not include psdata.inc
QusSW equ 0 ;AN025; do not include quoted string
LFEOLSW equ 0 ;AN044; do not use 0ah as line terminator
.xlist
.xcref
include psdata.inc ;AN000;
.list
.cref
TRANSPACE ENDS ;AN000;
TRANCODE SEGMENT PUBLIC BYTE ;AN000;
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN054;
; ****************************************************************
; *
; * ROUTINE: CMD_PARSE
; *
; * FUNCTION: Interface for transient COMMAND to invoke
; * SYSPARSE.
; *
; * INPUT: inputs to SYSPARSE
; *
; * OUTPUT: outputs from SYSPARSE
; *
; ****************************************************************
public Cmd_parse ;AN000;
.xlist
.xcref
INCLUDE parse.asm ;AN000;
.list
.cref
Cmd_parse Proc near ;AN000;
call sysparse ;AN000;
ret ;AN000;
Cmd_parse endp ;AN000;
public Append_parse ;AN010;
Append_parse Proc Far ;AN010;
call sysparse ;AN010;
ret ;AN010;
Append_parse endp ;AN010;
trancode ends ;AN000;
end ;AN000;


View File

@@ -0,0 +1,660 @@
page 80,132
; SCCSID = @(#)tpipe.asm 1.1 85/05/14
; SCCSID = @(#)tpipe.asm 1.1 85/05/14
TITLE PART8 COMMAND Transient routines.
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN ECHOFLAG:BYTE
EXTRN InitFlag:byte
EXTRN INPIPEPTR:WORD
EXTRN OUTPIPEPTR:WORD
EXTRN PIPE1:BYTE
EXTRN PIPE1T:BYTE
EXTRN PIPE2:BYTE
EXTRN PIPE2T:BYTE
EXTRN PIPEFILES:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN PIPEPTR:WORD
EXTRN RESTDIR:BYTE
EXTRN SINGLECOM:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADDAT_PTR:WORD
EXTRN BADTIM_PTR:WORD
EXTRN curdat_mo_day:word ;AN000;
EXTRN CURDAT_PTR:WORD
EXTRN curdat_yr:word ;AN000;
EXTRN curtim_hr_min:word ;AN000;
EXTRN CURTIM_PTR:WORD
EXTRN curtim_sec_hn:word ;AN000;
EXTRN eurdat_ptr:word
EXTRN japdat_ptr:word
EXTRN newdat_format:word ;AN000;
EXTRN NEWDAT_PTR:WORD
EXTRN NEWTIM_PTR:WORD
EXTRN parse_date:byte ;AN000;
EXTRN parse_time:byte ;AN000;
EXTRN PIPEEMES_PTR:WORD
EXTRN promtim_hr_min:word ;AN000;
EXTRN promtim_ptr:word ;AN000;
EXTRN promtim_sec_hn:word ;AN000;
EXTRN STRING_BUF_PTR:WORD ;AC000;
EXTRN SYNTMES_PTR:WORD
EXTRN usadat_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN COMBUF:BYTE
EXTRN date_day:byte ;AN000;
EXTRN date_month:byte ;AN000;
EXTRN date_year:word ;AN000;
EXTRN INTERNATVARS:BYTE
EXTRN RESSEG:WORD
EXTRN time_fraction:byte ;AN000;
EXTRN time_hour:byte ;AN000;
EXTRN time_minutes:byte ;AN000;
EXTRN time_seconds:byte ;AN000;
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN CERROR:NEAR
EXTRN NOPIPEPROC:NEAR
EXTRN STD_PRINTF:NEAR
EXTRN TCOMMAND:NEAR
EXTRN TESTDOREIN:NEAR
EXTRN TESTDOREOUT:NEAR
EXTRN TESTKANJ:NEAR ;AN000;3/3/KK
EXTRN TSYSGETMSG:NEAR ;AN000;
PUBLIC CTIME
PUBLIC DATE
PUBLIC DATINIT
PUBLIC PIPEDEL
PUBLIC PIPEERRSYN
PUBLIC PIPEPROC
PUBLIC PIPEPROCSTRT
PUBLIC PRINT_TIME
PUBLIC SETREST
PUBLIC SETREST1
PUBLIC SINGLETEST
SINGLETEST:
ASSUME DS:NOTHING
push ds
MOV DS,ResSeg
ASSUME DS:ResGroup
CMP [SINGLECOM],0
JZ TestDone
CMP [SINGLECOM],0EFFFH
TestDone:
pop ds
return
ASSUME DS:TRANGROUP
SETREST1:
MOV AL,1
SETREST:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV [RESTDIR],AL
POP DS
ASSUME DS:TRANGROUP
return
ASSUME DS:RESGROUP
;
; Note that we need to handle the same thing that RestDir handles: the
; requirement that we try only once to restore the user's environment after
; and INT 24 or the like. If the condition that causes the INT 24 does not
; disappear, we just give up.
;
PIPEDEL:
assume ds:nothing
push ds
PUSH DX
mov ds,ResSeg
assume ds:ResGroup
mov DX,OFFSET RESGROUP:PIPE1 ; Clean up in case ^C
MOV AH,UNLINK
INT int_command
MOV DX,OFFSET RESGROUP:PIPE2
MOV AH,UNLINK
INT int_command
POP DX
call PipeOff
mov PipeFiles,0
pop ds
return
PIPEERRSYN:
MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
CALL PIPEDEL
PUSH CS
POP DS
JMP CERROR
PIPEERR:
pushf
invoke triageError
SaveReg <AX,DX> ; Save results from TriageError
MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr
CALL PIPEDEL
PUSH CS
POP DS
invoke std_eprintf
RestoreReg <DX,AX> ; Restore results from TriageError
popf
cmp ax, 65
jnz tcommandj
JMP CERROR
tcommandj:
jmp tcommand
PIPEPROCSTRT:
ASSUME DS:TRANGROUP,ES:TRANGROUP
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
INC [PIPEFILES] ; Flag that the pipe files exist
MOV AH,Get_Default_Drive ; Get current drive
INT int_command
ADD AL,capital_A
MOV [PIPE2],AL ; Make pipe files in root of def drv
MOV BX,OFFSET RESGROUP:PIPE1
MOV [BX],AL
xor ah,ah ; nul terminate path names
mov [Pipe1T],ah
mov [Pipe2T],ah
MOV DX,BX
XOR CX,CX
mov ah,CreateTempFile ; the CreateTemp call
INT int_command
JC PIPEERR ; Couldn't create
MOV BX,AX
MOV AH,CLOSE ; Don't proliferate handles
INT int_command
MOV DX,OFFSET RESGROUP:PIPE2
mov ah,createTempFile ; the CreateTemp call
INT int_command
JC PIPEERR
MOV BX,AX
MOV AH,CLOSE
INT int_command
CALL TESTDOREIN ; Set up a redirection if specified
MOV SI,[PIPEPTR]
CMP [SINGLECOM],-1
JNZ NOSINGP
MOV [SINGLECOM],0F000H ; Flag single command pipe
NOSINGP:
JMP SHORT FIRSTPIPE
PIPEPROC:
ASSUME DS:RESGROUP
AND [ECHOFLAG],0FEh ; force current echo to be off
MOV SI,[PIPEPTR]
LODSB
CMP AL,AltPipeChr ; Alternate pipe char?
JZ IsPipe1 ; Yes
CMP AL,vbar
jz IsPipe1
jmp PIPEEND ; Pipe done
IsPipe1:
MOV DX,[INPIPEPTR] ; Get the input file name
MOV AX,(OPEN SHL 8)
INT int_command
PIPEERRJ:
jnc no_pipeerr
JMP PIPEERR ; Lost the pipe file
no_pipeerr:
MOV BX,AX
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table],AL ; Redirect
FIRSTPIPE:
MOV DI,OFFSET TRANGROUP:COMBUF + 2
XOR CX,CX
CMP BYTE PTR [SI],0DH ; '|<CR>'
JNZ PIPEOK1
PIPEERRSYNJ:
JMP PIPEERRSYN
PIPEOK1:
mov al,vbar
CMP BYTE PTR [SI],al ; '||'
JZ PIPEERRSYNJ
CMP BYTE PTR [SI],AltPipeChr ; '##' or '|#'?
JZ PipeErrSynJ ; Yes, Error
PIPECOMLP:
LODSB
STOSB
;;;; IF KANJI 3/3/KK
CALL TESTKANJ
JZ NOTKANJ5
MOVSB
;
; Added following 2 commands to the fix pipe bug.
;
inc cx ;AN000; 3/3/KK
inc cx ;AN000; 3/3/KK
;
JMP PIPECOMLP
NOTKANJ5:
;;;; ENDIF ; 3/3/KK
CMP AL,0DH
JZ LASTPIPE
INC CX
CMP AL,AltPipeChr
JZ IsPipe2
CMP AL,vbar
JNZ PIPECOMLP
IsPipe2:
MOV BYTE PTR ES:[DI-1],0DH
DEC CX
MOV [COMBUF+1],CL
DEC SI
MOV [PIPEPTR],SI ; On to next pipe element
MOV DX,[OUTPIPEPTR]
PUSH CX
XOR CX,CX
MOV AX,(CREAT SHL 8)
INT int_command
POP CX
JC PIPEERRJ ; Lost the file
MOV BX,AX
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table+1],AL
XCHG DX,[INPIPEPTR] ; Swap for next element of pipe
MOV [OUTPIPEPTR],DX
JMP SHORT PIPECOM
LASTPIPE:
MOV [COMBUF+1],CL
DEC SI
MOV [PIPEPTR],SI ; Point at the CR (anything not '|' will do)
CALL TESTDOREOUT ; Set up the redirection if specified
PIPECOM:
PUSH CS
POP DS
JMP NOPIPEPROC ; Process the pipe element
PIPEEND:
CALL PIPEDEL
CMP [SINGLECOM],0F000H
JNZ NOSINGP2
MOV [SINGLECOM],-1 ; Make it return
NOSINGP2:
JMP TCOMMAND
ASSUME DS:TRANGROUP,ES:TRANGROUP
; Date and time are set during initialization and use
; this routines since they need to do a long return
DATINIT PROC FAR
mov cs:[resseg],ds ; SetInitFlag needs resseg initialized
PUSH ES
PUSH DS ; Going to use the previous stack
MOV AX,CS ; Set up the appropriate segment registers
MOV ES,AX
MOV DS,AX
invoke TSYSLOADMSG ;AN000; preload messages
invoke SETSTDINON ;AN026; turn on critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
MOV DX,OFFSET TRANGROUP:INTERNATVARS;Set up internat vars
MOV AX,INTERNATIONAL SHL 8
INT 21H
MOV WORD PTR DS:[81H],13 ; Want to prompt for date during initialization
MOV [COMBUF],COMBUFLEN ; Init COMBUF
MOV WORD PTR [COMBUF+1],0D01H
CALL DATE
CALL CTIME
POP DS
POP ES
RET
DATINIT ENDP
; DATE - Gets and sets the time
break Date
; ****************************************************************
; *
; * ROUTINE: DATE - Set system date
; *
; * FUNCTION: If a date is specified, set the system date,
; * otherwise display the current system date and
; * prompt the user for a new date. If an invalid
; * date is specified, issue an error message and
; * prompt for a new date. If the user enters
; * nothing when prompted for a date, terminate.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
DATE:
MOV SI,81H ; Accepting argument for date inline
mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE
xor cx,cx ;AN000; clear counter for positionals
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
JZ PRMTDAT ;AC000; yes - go ask for date
cmp ax,result_no_error ;AN000; did we have an error?
jne daterr ;AN000; yes - go issue message
JMP COMDAT ;AC000; we have a date
PRMTDAT:
; Print "Current date is
invoke GetDate ;AN000; get date for output
xchg dh,dl ;AN000; switch month & day
mov CurDat_yr,cx ;AC000; put year into message control block
mov CurDat_mo_day,dx ;AC000; put month and day into message control block
mov dx,offset trangroup:CurDat_ptr ;AC000; set up message for output
invoke std_printf
;AD061; mov CurDat_yr,0 ;AC000; reset year, month and day
;AD061; mov CurDat_mo_day,0 ;AC000; pointers in control block
GET_NEW_DATE: ;AN000;
call getdat ;AC000; prompt user for date
cmp ax,end_of_line ;AC000; are we at end of line?
jz date_end ;AC000; yes - exit
cmp ax,result_no_error ;AN000; did we have an error?
jne daterr ;AN000; yes - go issue message
COMDAT:
mov cx,date_year ;AC000; get parts of date in
mov dh,date_month ;AC000; cx and dx for set
mov dl,date_day ;AC000; date function call.
push cx ;AC000; save date
push dx ;AC000;
mov cx,1 ;AC000; set 1 positional entered
xor dx,dx ;AN029;
invoke cmd_parse ;AN029; call parser
cmp al,end_of_line ;AN029; Are we at end of line?
pop dx ;AC000; retrieve date
pop cx ;AC000;
jnz daterr ;AC000; extra stuff on line - try again
MOV AH,SET_DATE ;yes - set date
INT int_command
OR AL,AL
JNZ DATERR
date_end:
ret
DATERR:
invoke crlf2 ;AN028; print out a blank line
MOV DX,OFFSET TRANGROUP:BADDAT_ptr
invoke std_printf
JMP GET_NEW_DATE ;AC000; get date again
; TIME gets and sets the time
break Time
; ****************************************************************
; *
; * ROUTINE: TIME - Set system time
; *
; * FUNCTION: If a time is specified, set the system time,
; * otherwise display the current system time and
; * prompt the user for a new time. If an invalid
; * time is specified, issue an error message and
; * prompt for a new time. If the user enters
; * nothing when prompted for a time, terminate.
; *
; * INPUT: command line at offset 81H
; *
; * OUTPUT: none
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
CTIME:
MOV SI,81H ; Accepting argument for time inline
mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_time
xor cx,cx ;AN000; clear counter for positionals
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
JZ PRMTTIM ;AC000; yes - prompt for time
cmp ax,result_no_error ;AN000; did we have an error?
jne timerr ;AN000; yes - go issue message
JMP COMTIM ;AC000; we have a time
PRMTTIM:
;Printf "Current time is ... "
MOV AH,GET_TIME ;AC000; get the current time
INT int_command ;AC000; Get time in CX:DX
xchg ch,cl ;AN000; switch hours & minutes
xchg dh,dl ;AN000; switch seconds & hundredths
mov CurTim_hr_min,cx ;AC000; put hours and minutes into message subst block
mov CurTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block
mov dx,offset trangroup:CurTim_ptr ;AC000; set up message for output
invoke std_printf
;AD061; mov CurTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths
;AD061; mov CurTim_sec_hn,0 ;AC000; pointers in control block
GET_NEW_TIME:
call gettim ;AC000;
cmp ax,end_of_line ;AC000; are we at end of line?
jz time_end ;AC000;
cmp ax,result_no_error ;AN000; did we have an error?
jne timerr ;AN000; yes - go issue message
COMTIM:
mov ch,time_hour ;AC000; get parts of time in
mov cl,time_minutes ;AC000; cx and dx for set
mov dh,time_seconds ;AC000; time function call
mov dl,time_fraction ;AC000;
push cx ;AC000; save time
push dx ;AC000;
mov cx,1 ;AC000; set 1 positional parm entered
xor dx,dx ;AN029;
invoke cmd_parse ;AN029; call parser
cmp al,end_of_line ;AN029; Are we at end of line?
pop dx ;AC000; retieve time
pop cx ;AC000;
jnz timerr ;AC000; extra stuff on line - try again
SAVTIM:
MOV AH,SET_TIME
INT int_command
OR AL,AL
JNZ TIMERR ;AC000; if an error occured, try again
TIME_END:
ret
TIMERR:
invoke crlf2 ;AN028; print out a blank line
MOV DX,OFFSET TRANGROUP:BADTIM_ptr
invoke std_printf ; Print error message
JMP GET_NEW_TIME ;AC000; Try again
;
; Set the special flag in the INIT flag to the value in CX.
;
SetInitFlag:
mov ds,[RESSEG]
assume ds:resgroup
and InitFlag,NOT initSpecial
or InitFlag,cL
push cs
pop ds
return
Public PipeOff
PipeOff:
ASSUME DS:NOTHING,ES:NOTHING
SaveReg <DS,AX>
MOV DS,ResSeg
ASSUME DS:RESGroup
XOR AL,AL
XCHG PipeFlag,AL
OR AL,AL
JZ PipeOffDone
SHR EchoFlag,1
PipeOffDone:
RestoreReg <AX,DS>
return
PRINT_TIME:
MOV AH,GET_TIME
INT int_command ; Get time in CX:DX
PUSH ES
PUSH CS
POP ES
xchg ch,cl ;AN000; switch hours & minutes
xchg dh,dl ;AN000; switch seconds & hundredths
mov promTim_hr_min,cx ;AC000; put hours and minutes into message subst block
mov promTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block
mov dx,offset trangroup:promTim_ptr ;AC000; set up message for output
invoke std_printf
;AD061; mov promTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths
;AD061; mov promTim_sec_hn,0 ;AC000; pointers in control block
POP ES
return
; ****************************************************************
; *
; * ROUTINE: GETDAT - Prompt user for date
; *
; * FUNCTION: Gets the date format from the COUNTRY DEPENDENT
; * INFORMATION and issues the "Enter new date"
; * message with the proper date format. COMBUF
; * is reset to get a date from the command line.
; * The PARSE_DATE blocks are then reset and the
; * PARSE function call is issued.
; *
; * INPUT: NONE
; *
; * OUTPUT: COMBUF
; * PARSER RETURN CODES
; *
; ****************************************************************
GETDAT proc near ;AC000;
mov ax,(International SHL 8) ; Determine what format the date
mov dx,5ch ; should be entered in and
int int_command ; print a message describing it
mov si,dx
lodsw
mov dx,usadat_ptr ;AC000; get mm-dd-yy
dec ax
js printformat
mov dx,eurdat_ptr ;AC000; get dd-mm-yy
jz printformat
mov dx,japdat_ptr ;AC000; get yy-mm-dd
printformat:
mov ax,dx ;AN000; get message number of format
mov dh,util_msg_class ;AN000; this is a utility message
call Tsysgetmsg ;AN000; get the address of the message
mov newdat_format,si ;AN000; put the address in subst block
MOV DX,OFFSET TRANGROUP:NEWDAT_ptr ;AC000; get address of message to print
invoke std_printf
mov newdat_format,no_subst ;AN000; reset subst block
MOV AH,STD_CON_STRING_INPUT
MOV DX,OFFSET TRANGROUP:COMBUF
mov cx,initSpecial ; Set bit in InitFlag that indicates
call SetInitFlag ; prompting for date.
INT int_command ; Get input line
xor cx,cx ; Reset bit in InitFlag that indicates
call SetInitFlag ; prompting for date.
invoke CRLF2
MOV SI,OFFSET TRANGROUP:COMBUF+2
mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE
xor cx,cx ;AN000; clear counter for positionals
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
ret
GETDAT endp ;AC000;
; ****************************************************************
; *
; * ROUTINE: GETTIME - Prompt user for time
; *
; * FUNCTION: Gets the time format from the COUNTRY DEPENDENT
; * INFORMATION and issues the "Enter new time"
; * message. COMBUF is reset to get a time from the
; * command line. The PARSE_TIME blocks are then
; * reset and the PARSE function call is issued.
; *
; * INPUT: NONE
; *
; * OUTPUT: COMBUF
; * PARSER RETURN CODES
; *
; ****************************************************************
GETTIM proc near ;AC000;
XOR CX,CX ; Initialize hours and minutes to zero
MOV DX,OFFSET TRANGROUP:NEWTIM_ptr
invoke std_printf
MOV AH,STD_CON_STRING_INPUT
MOV DX,OFFSET TRANGROUP:COMBUF
mov cx,initSpecial ; Set bit in InitFlag that indicates
call SetInitFlag ; prompting for time.
INT int_command ; Get input line
xor cx,cx ; Reset bit in InitFlag that indicates
call SetInitFlag ; prompting for time.
invoke CRLF2
MOV SI,OFFSET TRANGROUP:COMBUF+2
mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_TIME
xor cx,cx ;AN000; clear counter for positionals
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
ret
GETTIM endp ;AC000;
TRANCODE ENDS
END

View File

@@ -0,0 +1,365 @@
page 80,132
; SCCSID = @(#)tprintf.asm 4.3 85/07/02
; SCCSID = @(#)tprintf.asm 4.3 85/07/02
TITLE COMMAND Transient Printf routine
;****************************************************************
;*
;* ROUTINE: STD_PRINTF/STD_EPRINTF
;*
;* FUNCTION: Set up to print out a message using SYSDISPMSG.
;* Set up substitutions if utility message. Make
;* sure any changes to message variables in TDATA
;* are reset to avoid reloading the transient.
;*
;* INPUT: Msg_Disp_Class - set to message class
;* Msg_Cont_Flag - set to control flags
;* DS points to transient segment
;*
;* if utility message:
;* DX points to a block with message number
;* (word), number of substitutions (byte),
;* followed by substitution list if there
;* are substitutions. If substitutions
;* are not in transient segment they must
;* be set.
;* else
;* AX set to message number
;*
;* OUTPUT: none
;*
;****************************************************************
.xlist
.xcref
INCLUDE comsw.asm ;AC000;
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm ;AN000;
INCLUDE SYSMSG.INC ;AN000;
.list
.cref
datares segment public
extrn pipeflag:byte
datares ends
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN extend_buf_off:word ;AN000;
EXTRN Extend_Buf_ptr:word ;AN000;
EXTRN Extend_Buf_seg:word ;AN000;
EXTRN Msg_Cont_Flag:byte ;AN000;
EXTRN Msg_disp_Class:byte ;AN000;
EXTRN pipeemes_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN msg_flag:byte ;AN022;
EXTRN print_err_flag:word ;AN000;
EXTRN RESSEG:WORD
EXTRN String_ptr_2:word ;AC000;
EXTRN Subst_buffer:byte ;AN061;
;AD061; EXTRN String_ptr_2_sb:word ;AN000;
; include data area for message services
MSG_UTILNAME <COMMAND> ;AN000; define utility name
MSG_SERVICES <MSGDATA> ;AN000;
PRINTF_HANDLE DW ? ;AC000;
TRANSPACE ENDS ;AC000;
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
EXTRN cerror:near
EXTRN crlf2:near
EXTRN tcommand:near ;AN026;
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING,SS:NOTHING ;AC000;
PUBLIC SETSTDINOFF ;AN026;
PUBLIC SETSTDINON ;AN026;
PUBLIC SETSTDOUTOFF ;AN026;
PUBLIC SETSTDOUTON ;AN026;
PUBLIC TSYSGETMSG ;AN000;
PUBLIC TSYSLOADMSG ;AN000;
PUBLIC Printf_Init
printf_init proc far
call std_printf
ret
printf_init endp
Public Printf_Crlf
PRINTF_CRLF:
CALL STD_PRINTF
CALL CRLF2
RET
PUBLIC Std_EPrintf
STD_EPRINTF:
mov Printf_Handle,2 ;AC000;Print to STDERR
jmp short NEW_PRINTF ;AC000;
PUBLIC Std_Printf
STD_PRINTF:
mov Printf_Handle,1 ;AC000;Print to STDOUT
NEW_PRINTF:
push ax ;AN000;save registers
push bx ;AN000;
push cx ;AN000;
push es ;AN000;get local ES
push ds ;AN000;
pop es ;AN000;
push di ;AN000;
push si ;AN000;
push dx ;AN000;
assume es:trangroup ;AN000;
;AD061; mov string_ptr_2_sb,0 ;AN000;initialize
mov print_err_flag,0 ;AN000;
UTILITY_SETUP:
mov si,dx ;AN000;Get offset of message number
lodsw ;AN000;load message number
push ax ;AN000;save it
lodsb ;AN000;get number of substitutions
mov cl,al ;AN000;set up CX as # of subst
xor ch,ch ;AN000; SI now points to subst list
pop ax ;AN000;get message number back
cmp cx,0 ;AN000;Any substitutions?
jz READY_TO_PRINT ;AN000;No - continue
;AD061; add dx,Ptr_Seg_Pos ;AN000;Point to position of first segment
;AD061; push cx ;AN000;save substitution count
;AD061;SET_SUBST:
;AD061; mov bx,dx ;AN000;get dx into base register
;AD061; cmp word ptr [bx],0 ;AN000;has segment been set?
;AD061; jnz SUBST_SEG_SET ;AN000;if not 0, don't replace it
;AD061; test word ptr [bx+3],date_type ;AN000;if date or time - don't set segment
;AD061; jnz subst_seg_set ;AN000;yes - skip it
;AD061; mov word ptr [bx],cs ;AN000;put segment of subst parm in list
;AD061;SUBST_SEG_SET:
;AD061; add dx,Parm_Block_Size ;AN000;point to position of next segment
;AD061; loop SET_SUBST ;AN000;keep replacing until complete
;AD061; pop cx ;AN000;
;AD061;NO_REPLACEMENT:
;AD061; mov bx,parm_off_pos [si] ;AN000;get subst offset
;AD061; cmp bx,offset trangroup:string_ptr_2 ;AN000;this is used for double indirection
;AD061; jnz ready_to_print ;AN000;we already have address
;AD061; mov dx,string_ptr_2 ;AN000;get address in string_ptr_2
;AD061; mov parm_off_pos [si],dx ;AN000;put proper address in table
;AD061; mov string_ptr_2_sb,si ;AN000;save block changed
mov di,offset trangroup:subst_buffer;AN061; Get address of message subst buffer
push di ;AN061; save it
push cx ;AN061; save number of subst
MOVE_SUBST:
push cx ;AN061;save number of subst
mov bx,si ;AN061;save start of sublist
mov cx,parm_block_size ;AN061;get size of sublist
rep movsb ;AN061;move sublist
test byte ptr [bx.$M_S_FLAG],date_type ;AN061;are we doing date/time?
jz move_subst_cont ;AN061;no - no need to reset
mov word ptr [bx.$M_S_VALUE],0 ;AN061;reset original date or time to 0
mov word ptr [bx.$M_S_VALUE+2],0 ;AN061;
MOVE_SUBST_CONT: ;AN061;
pop cx ;AN061;get number of subst back
loop move_subst ;AN061;move cx sublists
pop cx ;AN061;get number of subst
push ax ;AN061;save message number
cmp Msg_Disp_Class,Util_Msg_Class ;AN061;Is this a utility message
jz CHECK_FIX ;AN061;YES - go see if substitutions
mov msg_flag,ext_msg_class ;AN061;set message flag
mov di,offset trangroup:extend_buf_ptr ;AN061; Get address of extended message block
xor ax,ax ;AN061;clear ax register
stosw ;AN061;clear out message number
stosb ;AN061;clear out subst count
CHECK_FIX: ;AN061;
pop ax ;AN061;get message number back
pop di ;AN061;get start of sublists
mov si,di ;AN061;get into SI for msgserv
mov bx,si ;AN061;get into BX for addressing
push cx ;AN061;save number of subst
SET_SUBST: ;AN061;store the segment of the subst
cmp word ptr [bx.$M_S_VALUE+2],0 ;AN061;was it set already?
jnz subst_seg_set ;AN061;if not 0, don't replace it
test byte ptr [bx.$M_S_FLAG],date_type ;AN061;don't replace if date or time
jnz subst_seg_set ;AN061;yes - skip it
mov word ptr [bx.$M_S_VALUE+2],cs ;AN061;set segment value
SUBST_SEG_SET: ;AN061;
add bx,parm_block_size ;AN061;go to next sublist
loop set_subst ;AN061;loop CX times
pop cx ;AN061;get number of subst back
mov bx,si ;AN061;get start of sublist to BX
cmp word ptr [bx.$M_S_VALUE],offset trangroup:string_ptr_2 ;AN061;are we using double indirection?
jnz ready_to_print ;AN061;no - we already have address
mov dx,string_ptr_2 ;AN061;get address in string_ptr_2
mov word ptr [bx.$M_S_VALUE],dx ;AN061;put it into the subst block
READY_TO_PRINT:
mov bx,Printf_Handle ;AN000;get print handle
mov dl,Msg_Cont_Flag ;AN000;set up control flag
mov dh,Msg_Disp_Class ;AN000;set up display class
mov Msg_Cont_Flag,No_Cont_Flag ;AN061;reset flags to avoid
mov Msg_Disp_Class,Util_Msg_Class ;AN061; transient reload
;AD061; push bx ;AN026; save registers
;AD061; push cx ;AN026;
;AD061; push dx ;AN026;
;AD061; push si ;AN026;
;AD061; push di ;AN026;
push ds ;AN026;
push es ;AN026;
call SYSDISPMSG ;AN000;call Rod
pop es ;AN026; restore registers
pop ds ;AN026;
;AD061; pop di ;AN026;
;AD061; pop si ;AN026;
;AD061; pop dx ;AN026;
;AD061; pop cx ;AN026;
;AD061; pop bx ;AN026;
jnc Print_success ;AN000; everything went okay
mov print_err_flag,ax ;AN000;
print_success:
;AD061; cmp Msg_Disp_Class,Util_Msg_Class ;AN000;Is this a utility message
;AD061; jz CHECK_FIX ;AN000;YES - go see if substitutions
;AD061; mov msg_flag,ext_msg_class ;AN022;set message flag
;AD061; mov di,offset trangroup:extend_buf_ptr ;AN000; Get address of extended message block
;AD061; xor ax,ax ;AN000;clear ax register
;AD061; stosw ;AN000;clear out message number
;AD061; stosb ;AN000;clear out subst count
;AD061; CHECK_FIX:
;AD061; pop dx ;AN000;restore dx
;AD061; cmp cx,0 ;AN000;Any substitutions?
;AD061; jz NO_FIXUP ;AN000;No - leave
;AD061; mov si,dx ;AN000;Reset changes so transient won't reload
;AD061; add si,Ptr_Seg_Pos ;AN000;Point to position of first segment
;AD061;FIX_SUBST:
;AD061; mov word ptr [si],0 ;AN000;reset segment to 0
;AD061; add si,Parm_Block_Size ;AN000;point to position of next segment
;AD061; loop FIX_SUBST ;AN000;keep replacing until complete
;AD061; cmp string_ptr_2_sb,no_subst ;AN000;was double indirection used?
;AD061; jz no_fixup ;AN000;no - we're finished
;AD061; mov si,string_ptr_2_sb ;AN000;get offset changed
;AD061; mov parm_off_pos [si],offset trangroup:string_ptr_2 ;AN000; set address back to string_ptr_2
;AD061;NO_FIXUP:
;AD061; mov Msg_Cont_Flag,No_Cont_Flag ;AN000;reset flags to avoid
;AD061; mov Msg_Disp_Class,Util_Msg_Class ;AN000; transient reload
pop dx ;AN061;restore dx
pop si ;AN000;restore registers
pop di ;AN000;
pop es ;AN000;restore registers
pop cx ;AN000;
pop bx ;AN000;
pop ax ;AN000;
cmp print_err_flag,0 ;AN000; if an error occurred - handle it
jnz print_err ;AN000;
ret ;AC000;
print_err:
push cs
pop es
cmp Printf_Handle,2 ;AN026;Print to STDERR?
jnz not_stderr ;AN026;no - continue
jmp tcommand ;AN026;Yes - hopless - just exit
not_stderr:
mov ax,print_err_flag ;AN026;get extended error number back
mov es,[resseg] ; No, set up for error, load the
assume es:resgroup ; right error msg, and jmp to cerror.
test PipeFlag,-1
jz go_to_error
invoke PipeOff
mov dx,offset trangroup:pipeemes_ptr
jmp print_err_exit ;AC000;
go_to_error:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,ax ;AN000; get message number in control block
PRINT_ERR_EXIT: ;AC000;
push cs
pop es
JMP CERROR
;****************************************************************
;*
;* ROUTINE: TSYSLOADMSG
;*
;* FUNCTION: Interface to call SYSLOADMSG to avoid duplicate
;* names since these routines are also used in the
;* resident.
;*
;* INPUT: Inputs to SYSLOADMSG
;*
;* OUTPUT: Outputs from SYSLOADMSG
;*
;****************************************************************
TSYSLOADMSG PROC NEAR ;AN000;
push bx ;AN000;
call sysloadmsg ;AN000; call routine
pop bx ;AN000;
ret ;AN000; exit
TSYSLOADMSG ENDP ;AN000;
;****************************************************************
;*
;* ROUTINE: TSYSGETMSG
;*
;* FUNCTION: Interface to call SYSGETMSG to avoid duplicate
;* names since these routines are also used in the
;* resident.
;*
;* INPUT: Inputs to SYSGETMSG
;*
;* OUTPUT: Outputs from SYSGETMSG
;*
;****************************************************************
TSYSGETMSG PROC NEAR ;AN000;
push cx ;AN000;
call sysgetmsg ;AN000; call routine
pop cx ;AN000;
ret ;AN000; exit
TSYSGETMSG ENDP ;AN000;
MSG_SERVICES <COMT,NOVERCHECKmsg,NEARmsg,LOADmsg,NOCHECKSTDIN,NOCHECKSTDOUT,GETmsg> ;AC026; The message services
MSG_SERVICES <COMT,NEARmsg,SETSTDIO,DISPLAYmsg,CHARmsg,NUMmsg,TIMEmsg,DATEmsg> ;AC026; The message services
PRINTF_LAST LABEL WORD
include msgdcl.inc
TRANCODE ENDS
END

View File

@@ -0,0 +1,671 @@
;****************************************************
;* TRANSIENT MESSAGE POINTERS & SUBSTITUTION BLOCKS *
;****************************************************
msg_disp_class db Util_msg_class
msg_cont_flag db No_cont_flag
; extended error string output
;
Extend_Buf_ptr dw 0 ;AN000;set to no message
Extend_Buf_sub db 0 ;AN000;set to no substitutions
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
Extend_Buf_off dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg
Extend_Buf_seg dw 0 ;AN000;segment of arg
db 0 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
; "Duplicate file name or file not found"
;
Renerr_Ptr dw 1002 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid path or file name"
;
BadCPMes_Ptr dw 1003 ;AN000;message number
db no_subst ;AN000;number of subst
; "Insufficient disk space"
;
NoSpace_Ptr dw 1004 ;AN000;message number
db no_subst ;AN000;number of subst
; "Out of environment space"
;
EnvErr_Ptr dw 1007 ;AN000;message number
db no_subst ;AN000;number of subst
; "File creation error"
;
FulDir_Ptr dw 1008 ;AN000;message number
db no_subst ;AN000;number of subst
; "Batch file missing",13,10
;
BadBat_Ptr dw 1009 ;AN000;message number
db no_subst ;AN000;number of subst
; "Insert disk with batch file",13,10
;
NeedBat_Ptr dw 1010 ;AN000;message number
db no_subst ;AN000;number of subst
; "Bad command or file name",13,10
;
BadNam_Ptr dw 1011 ;AN000;message number
db no_subst ;AN000;number of subst
; "Access denied",13,10
;
AccDen_Ptr dw 1014 ;AN000;message number
db no_subst ;AN000;number of subst
; "File cannot be copied onto itself",13,10
;
OverWr_Ptr dw 1015 ;AN000;message number
db no_subst ;AN000;number of subst
; "Content of destination lost before copy",13,10
;
LostErr_Ptr dw 1016 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid filename or file not found",13,10
;
InOrNot_Ptr dw 1017 ;AN000;message number
db no_subst ;AN000;number of subst
; "%1 File(s) copied",13,10
;
Copied_Ptr dw 1018 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Copy_num ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 9 ;AN000;maximum width
db 9 ;AN000;minimum width
db blank ;AN000;pad character
; "%1 File(s) "
;
DirMes_Ptr dw 1019 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Dir_num ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 9 ;AN000;maximum width
db 9 ;AN000;minimum width
db blank ;AN000;pad character
; "%1 bytes free",13,10
;
BytMes_Ptr dw 1020 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Bytes_Free ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal
db 10 ;AN000;maximum width
db 10 ;AN000;minimum width
db blank ;AN000;pad character
; "Invalid drive specification",13,10
;
BadDrv_Ptr dw 1021 ;AN000;message number
db no_subst ;AN000;number of subst
; "Code page %1 not prepared for system",13,10
;
CP_not_set_Ptr dw 1022 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:System_cpage ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 5 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "Code page %1 not prepared for all devices",13,10
;
CP_not_all_Ptr dw 1023 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:System_cpage ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 5 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "Active code page: %1",13,10
;
CP_active_Ptr dw 1024 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:System_cpage ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 5 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "NLSFUNC not installed",13,10
;
NLSFUNC_Ptr dw 1025 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid code page",13,10
;
Inv_Code_Page dw 1026 ;AN000;message number
db no_subst ;AN000;number of subst
; "Current drive is no longer valid"
;
BadCurDrv dw 1027 ;AN000;message number
db no_subst ;AN000;number of subst
; "Press any key to continue"
;
PauseMes_Ptr dw 1028 ;AN000;message number
db no_subst ;AN000;number of subst
; "Label not found",13,10
;
BadLab_Ptr dw 1029 ;AN000;message number
db no_subst ;AN000;number of subst
; "Syntax error",13,10
;
SyntMes_Ptr dw 1030 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid date",13,10
;
BadDat_Ptr dw 1031 ;AN000;message number
db no_subst ;AN000;number of subst
; "Current date is %1 %2",13,10
;
CurDat_Ptr dw 1032 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 3 ;AN000;maximum width
db 3 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
CurDat_yr dw 0 ;AN000;year
CurDat_mo_day dw 0 ;AN000;month,day
db 2 ;AN000;second subst
db DATE_MDY_4 ;AN000;date
db 10 ;AN000;maximum width
db 10 ;AN000;minimum width
db blank ;AN000;pad character
; "SunMonTueWedThuFriSat"
;
WeekTab dw 1033 ;AN000;message number
db no_subst ;AN000;number of subst
; "Enter new date (%1):"
;
NewDat_Ptr dw 1034 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
NewDat_Format dw 0 ;AN000;offset of replacement
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 8 ;AN000;maximum width
db 8 ;AN000;minimum width
db blank ;AN000;pad character
; "Invalid time",13,10
;
BadTim_Ptr dw 1035 ;AN000;message number
db no_subst ;AN000;number of subst
; "Current time is %1",13,10
;
CurTim_Ptr dw 1036 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
CurTim_hr_min dw 0 ;AN000;hours,minutes
CurTim_Sec_hn dw 0 ;AN000;seconds,hundredths
db 1 ;AN000;first subst
db Right_Align+TIME_HHMMSSHH_Cty ;AC059;time
db 12 ;AC059;maximum width
db 12 ;AC059;minimum width
db blank ;AN000;pad character
; "Enter new time:"
;
NewTim_Ptr dw 1037 ;AN000;message number
db no_subst ;AN000;number of subst
; ", Delete (Y/N)?",13,10
;
Del_Y_N_Ptr dw 1038 ;AN000;message number
db no_subst ;AN000;number of subst
; "All files in directory will be deleted!",13,10
; "Are you sure (Y/N)?",13,10
;
SureMes_Ptr dw 1039 ;AN000;message number
db no_subst ;AN000;number of subst
; "Microsoft DOS Version %1.%2",13,10
;
VerMes_Ptr dw 1040 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Major_Ver_Num ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal
db 1 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Minor_Ver_Num ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Unsgn_Bin_Word ;AN000;binary to decimal
db 2 ;AN000;maximum width
db 2 ;AN000;minimum width
db "0" ;AN000;pad character
; "Volume in drive %1 has no label",13,10
;
VolMes_Ptr_2 dw 1041 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:vol_drv ;AN000;offset of drive
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_Char ;AN000;character
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "Volume in drive %1 is %2",13,10
;
VolMes_Ptr dw 1042 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:vol_drv ;AN000;offset of drive
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db 00000000b ;AN000;character
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:CHARBUF ;AN000;offset of string
dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "Volume Serial Number is %1-%2",13,10
;
VolSerMes_Ptr dw 1043 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:vol_serial+2 ;AN000;offset of serial
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Bin_Hex_Word ;AN000;binary to hex
db 4 ;AN000;maximum width
db 4 ;AN000;minimum width
db "0" ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:vol_serial ;AN000;offset of serial
dw 0 ;AN000;segment of arg
db 2 ;AN000;second subst
db Right_Align+Bin_Hex_Word ;AN000;binary to hex
db 4 ;AN000;maximum width
db 4 ;AN000;minimum width
db "0" ;AN000;pad character
; "Invalid directory",13,10
;
BadCD_Ptr dw 1044 ;AN000;message number
db no_subst ;AN000;number of subst
; "Unable to create directory",13,10
;
BadMkD_Ptr dw 1045 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid path, not directory,",13,10
; "or directory not empty",13,10
;
BadRmD_Ptr dw 1046 ;AN000;message number
db no_subst ;AN000;number of subst
; "Must specify ON or OFF",13,10
;
Bad_ON_OFF_Ptr dw 1047 ;AN000;message number
db no_subst ;AN000;number of subst
; "Directory of %1",13,10
;
DirHead_Ptr dw 1048 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:BWDBUF ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
; "No Path",13,10
;
NulPath_Ptr dw 1049 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid drive in search path",13,10
;
BadPMes_Ptr dw 1050 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid device",13,10
;
BadDev_Ptr dw 1051 ;AN000;message number
db no_subst ;AN000;number of subst
; "FOR cannot be nested",13,10
;
ForNestMes_Ptr dw 1052 ;AN000;message number
db no_subst ;AN000;number of subst
; "Intermediate file error during pipe",13,10
;
PipeEMes_Ptr dw 1053 ;AN000;message number
db no_subst ;AN000;number of subst
; "Cannot do binary reads from a device",13,10
;
InBDev_Ptr dw 1054 ;AN000;message number
db no_subst ;AN000;number of subst
; "BREAK is %1",13,10
;
CtrlcMes_Ptr dw 1055 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw 0 ;AN000;offset of on/off (new)
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "VERIFY is %1",13,10
;
VeriMes_Ptr dw 1056 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw 0 ;AN000;offset of on/off (new)
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "ECHO is %1",13,10
;
EchoMes_Ptr dw 1057 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw 0 ;AN000;offset of on/off (new)
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 1 ;AN000;minimum width
db blank ;AN000;pad character
; "off"
;
OffMes_Ptr dw 1059 ;AN000;message number
db no_subst ;AN000;number of subst
; "on"
;
OnMes_Ptr dw 1060 ;AN000;message number
db no_subst ;AN000;number of subst
; "Error writing to device",13,10
;
DevWMes_Ptr dw 1061 ;AN000;message number
db no_subst ;AN000;number of subst
; "Invalid path",13,10
;
Inval_Path_Ptr dw 1062 ;AN000;message number
db no_subst ;AN000;number of subst
; unformatted string output
;
arg_Buf_Ptr dw 1063 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
; file name output
;
File_Name_Ptr dw 1064 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:SRCBUF ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
; file size output for dir
;
Disp_File_Size_Ptr dw 1065 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:File_size_low ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal
db 10 ;AN000;maximum width
db 10 ;AN000;minimum width
db blank ;AN000;pad character
; unformatted string output
; %s
String_Buf_Ptr dw 1066 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 128 ;AN000;maximum width
db 0 ;AN000;minimum width
db blank ;AN000;pad character
db 0 ;AN000;
; tab character
;
Tab_ptr dw 1067 ;AN000;message number
db no_subst ;AN000;number of subst
; " <DIR> "
;
DMes_Ptr dw 1068 ;AN000;message number
db no_subst ;AN000;number of subst
; destructive back space
;
Dback_Ptr dw 1069 ;AN000;message number
db no_subst ;AN000;number of subst
; carriage return / line feed
;
ACRLF_Ptr dw 1070 ;AN000;message number
db no_subst ;AN000;number of subst
; output a single character
;
;One_Char_Buf_Ptr dw 1071 ;AN000;message number
; db 1 ;AN000;number of subst
; db parm_block_size ;AN000;size of sublist
; db 0 ;AN000;reserved
; dw OFFSET TranGroup:One_Char_Val ;AN000;offset of charcacter
; dw 0 ;AN000;segment of arg
; db 1 ;AN000;first subst
; db Char_field_Char ;AN000;character
; db 1 ;AN000;maximum width
; db 1 ;AN000;minimum width
; db blank ;AN000;pad character
; "mm-dd-yy"
;
USADat_Ptr dw 1072 ;AN000;message number
db no_subst ;AN000;number of subst
; "dd-mm-yy"
;
EurDat_Ptr dw 1073 ;AN000;message number
db no_subst ;AN000;number of subst
; "yy-mm-dd"
;
JapDat_Ptr dw 1074 ;AN000;message number
db no_subst ;AN000;number of subst
; date string for prompt
;
promptDat_Ptr dw 1075 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg
dw 0 ;AN000;segment of arg
db 1 ;AN000;first subst
db Char_field_ASCIIZ ;AN000;character string
db 3 ;AN000;maximum width
db 3 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
promptDat_yr dw 0 ;AN000;year
promptDat_moday dw 0 ;AN000;month,day
db 2 ;AN000;second subst
db DATE_MDY_4 ;AN000;date
db 10 ;AN000;maximum width
db 8 ;AN000;minimum width
db blank ;AN000;pad character
; Time for prompt
;
promTim_Ptr dw 1076 ;AN000;message number
db 1 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
PromTim_hr_min dw 0 ;AN000;hours,minutes
PromTim_Sec_hn dw 0 ;AN000;seconds,hundredths
db 1 ;AN000;first subst
db Right_Align+TIME_HHMMSSHH_24 ;AC013;time
db 11 ;AN000;maximum width
db 11 ;AC013;minimum width
db blank ;AN000;pad character
; Date and time for DIR
;
DirDatTim_Ptr dw 1077 ;AN000;message number
db 2 ;AN000;number of subst
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
DirDat_yr dw 0 ;AN000;year
DirDat_mo_day dw 0 ;AN000;month,day
db 1 ;AN000;first subst
db Right_Align+DATE_MDY_2 ;AN000;date
db 10 ;AN000;maximum width
db 8 ;AN000;minimum width
db blank ;AN000;pad character
db parm_block_size ;AN000;size of sublist
db 0 ;AN000;reserved
DirTim_hr_min dw 0 ;AN000;hours,minutes
DirTim_Sec_hn dw 0 ;AN000;seconds,hundredths
db 2 ;AN000;second subst
db Right_align+TIME_HHMM_Cty ;AN000;time
db 6 ;AN000;maximum width
db 6 ;AN000;minimum width
db blank ;AN000;pad character
; "Directory already exists"
;
MD_exists_ptr dw 1078 ;AN000;message number
db no_subst ;AN000;number of subst
PATH_TEXT DB "PATH="
PROMPT_TEXT DB "PROMPT="
comspecstr db "COMSPEC="

View File

@@ -0,0 +1,488 @@
page 80,132
; SCCSID = @(#)tspc.asm 4.1 85/09/22
; SCCSID = @(#)tspc.asm 4.1 85/09/22
TITLE COMMAND Transient Uninitialized DATA
INCLUDE comsw.asm
.xlist
.xcref
INCLUDE DOSSYM.INC
INCLUDE comequ.asm
INCLUDE comseg.asm
INCLUDE EA.inc ;AN030;
.list
.cref
; Uninitialized transient data
TRANSPACE SEGMENT PUBLIC BYTE
PUBLIC ALLSWITCH
PUBLIC append_exec ;AN041;
PUBLIC arg
PUBLIC argbufptr
PUBLIC ARGC
PUBLIC ARG1S
PUBLIC ARG2S
PUBLIC ARGTS
PUBLIC arg_buf
PUBLIC ASCII
PUBLIC BatBuf
PUBLIC BatBufEnd
PUBLIC BatBufPos
PUBLIC BATHAND
PUBLIC BINARY
PUBLIC BITS
PUBLIC BWDBUF
PUBLIC BYTCNT
PUBLIC bytes_free
PUBLIC CFLAG
PUBLIC CHARBUF
PUBLIC CHKDRV
PUBLIC COM
PUBLIC COMBUF
PUBLIC comma
PUBLIC comptr
PUBLIC comspec_flag
PUBLIC COMSW
PUBLIC CONCAT
PUBLIC concat_xa ;AN000;
PUBLIC copy_Num
PUBLIC CPDATE
PUBLIC CPTIME
PUBLIC cpyflag
PUBLIC CURDRV
PUBLIC DATE_DAY ;AN000;
PUBLIC DATE_MONTH ;AN000;
PUBLIC DATE_OUTPUT ;AN000;
PUBLIC DATE_TYPE ;AN000;
PUBLIC DATE_YEAR ;AN000;
PUBLIC DEST
PUBLIC DESTBUF
PUBLIC DestClosed
PUBLIC DESTDIR
PUBLIC DESTFCB
PUBLIC DESTFCB2
PUBLIC DESTHAND
PUBLIC DESTINFO
PUBLIC DESTISDEV
PUBLIC DESTISDIR
PUBLIC DESTNAME
PUBLIC DESTSIZ
PUBLIC DESTSWITCH
PUBLIC DESTTAIL
PUBLIC DESTVARS
PUBLIC DIRBUF
PUBLIC DIRCHAR
PUBLIC dirflag ;AN015;
PUBLIC Dir_Num
PUBLIC display_ioctl ;AN000;
PUBLIC display_mode ;AN000;
PUBLIC display_width ;AN000;
PUBLIC DRIVE_NUMBER ;AN000;
PUBLIC DRIVE_OUTPUT ;AN000;
PUBLIC DRIVE_TYPE ;AN000;
PUBLIC DRIVE_VALUE ;AN000;
PUBLIC ELCNT
PUBLIC ELPOS
PUBLIC EXECPATH
PUBLIC EXEC_ADDR
PUBLIC EXEFCB
PUBLIC expand_star
PUBLIC ext_entered ;AN005;
PUBLIC ext_open_off ;AN000;
PUBLIC ext_open_parms ;AN000;
PUBLIC ext_open_seg ;AN000;
PUBLIC FBUF
PUBLIC FILECNT
PUBLIC file_size_high
PUBLIC file_size_low
PUBLIC FILTYP
PUBLIC FIRSTDEST
PUBLIC FRSTSRCH
PUBLIC FULLSCR
PUBLIC GOTOLEN
PUBLIC HEADCALL
PUBLIC ID
PUBLIC IDLEN
PUBLIC IFNOTFLAG
PUBLIC if_not_count
PUBLIC INEXACT
PUBLIC INTERNATVARS
PUBLIC KPARSE
PUBLIC last_arg
PUBLIC LINCNT
PUBLIC LINLEN
PUBLIC linperpag ;AN000;
PUBLIC major_ver_num
PUBLIC MELCOPY
PUBLIC MELSTART
PUBLIC minor_ver_num
PUBLIC msg_flag ;AN022;
PUBLIC msg_numb ;AN022;
PUBLIC NOWRITE
PUBLIC NXTADD
PUBLIC objcnt
PUBLIC one_char_val
PUBLIC PARM1
PUBLIC PARM2
PUBLIC parse_last ;AN018;
PUBLIC PARSE1_ADDR ;AN000;
PUBLIC PARSE1_CODE ;AN000;
PUBLIC PARSE1_OUTPUT ;AN000;
PUBLIC PARSE1_SYN ;AN000;
PUBLIC PARSE1_TYPE ;AN000;
PUBLIC PATHCNT
PUBLIC pathinfo
PUBLIC PATHPOS
PUBLIC PATHSW
PUBLIC PLUS
PUBLIC plus_comma
PUBLIC print_err_flag ;AN000;
PUBLIC psep_char
PUBLIC RCH_ADDR
PUBLIC RDEOF
PUBLIC RE_INSTR
PUBLIC RESSEG
PUBLIC SCANBUF
PUBLIC SDIRBUF
PUBLIC search_best
PUBLIC search_best_buf
PUBLIC search_curdir_buf
PUBLIC search_error
PUBLIC SKPDEL
PUBLIC SOURCE
PUBLIC SPECDRV
PUBLIC SRCBUF
PUBLIC SRCHAND
PUBLIC SRCINFO
PUBLIC SRCISDEV
PUBLIC SRCISDIR
PUBLIC SRCPT
PUBLIC SRCSIZ
PUBLIC SRCTAIL
PUBLIC SRCVARS
PUBLIC srcxname
PUBLIC src_xa_seg ;AN000;
PUBLIC src_xa_size ;AN000;
PUBLIC STACK
PUBLIC STARTEL
PUBLIC string_ptr_2
;AD061; PUBLIC string_ptr_2_sb ;AN000;
PUBLIC subst_buffer ;AN061;
PUBLIC SWITCHAR
PUBLIC system_cpage
PUBLIC TERMREAD
PUBLIC TIME_FRACTION ;AN000;
PUBLIC TIME_HOUR ;AN000;
PUBLIC TIME_MINUTES ;AN000;
PUBLIC TIME_OUTPUT ;AN000;
PUBLIC TIME_SECONDS ;AN000;
PUBLIC TIME_TYPE ;AN000;
PUBLIC TPA
PUBLIC tpbuf
PUBLIC TRANSPACEEND
PUBLIC TRAN_TPA
PUBLIC trgxname
PUBLIC UCOMBUF
PUBLIC USERDIR1
PUBLIC vol_drv
PUBLIC vol_ioctl_buf ;AC030;
PUBLIC vol_serial ;AC030;
PUBLIC vol_label ;AC030;
PUBLIC WRITTEN
PUBLIC xa_cp_length ;AN030;
PUBLIC xa_cp_out ;AN030;
PUBLIC xa_list_attr ;AN030;
PUBLIC zflag
IF IBM
PUBLIC ROM_CALL
PUBLIC ROM_CS
PUBLIC ROM_IP
ENDIF
ORG 0
ZERO = $
SRCXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate
TRGXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate
UCOMBUF DB COMBUFLEN+3 DUP(?) ; Raw console buffer
COMBUF DB COMBUFLEN+3 DUP(?) ; Cooked console buffer
USERDIR1 DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory
EXECPATH DB COMBUFLEN+3 DUP(?) ; Path for external command
RE_INSTR DB DIRSTRLEN+3+13 DUP (?) ; path for input to redirection
; Variables passed up from resident
HEADCALL LABEL DWORD
DW ?
RESSEG DW ?
TPA DW ?
SWITCHAR DB ?
DIRCHAR DB ?
EXEC_ADDR DD ?
RCH_ADDR DD ?
fTest DW ?
TRAN_TPA DW ?
CHKDRV DB ?
RDEOF LABEL BYTE ; Misc flags
IFNOTFLAG LABEL BYTE
FILTYP DB ?
CURDRV DB ?
concat_xa db 0 ;AN000; flag for XA on file concatenations
CONCAT LABEL BYTE
PARM1 DB ?
ARGC LABEL BYTE
PARM2 DB ?
COMSW DW ? ; Switches between command and 1st arg
ARG1S DW ? ; Switches between 1st and 2nd arg
DESTSWITCH LABEL WORD
ARG2S DW ? ; Switches after 2nd arg
ALLSWITCH LABEL WORD
ARGTS DW ? ; ALL switches except for COMSW
CFLAG DB ?
DESTCLOSED LABEL BYTE
SPECDRV DB ?
BYTCNT DW ? ; Size of buffer between RES and TRANS
NXTADD DW ?
FRSTSRCH DB ?
LINCNT DB ?
LINLEN DB ?
FILECNT DW ?
CHARBUF DB 80 DUP (?) ;line byte character buffer for xenix write
DESTFCB2 LABEL BYTE
IDLEN DB ?
ID DB 8 DUP(?)
COM DB 3 DUP(?)
DEST DB 37 DUP(?)
DESTNAME DB 11 DUP(?)
DESTFCB LABEL BYTE
DESTDIR DB DIRSTRLEN DUP(?) ; Directory for PATH searches
GOTOLEN LABEL WORD
BWDBUF LABEL BYTE
EXEFCB LABEL WORD
DIRBUF DB DIRSTRLEN+3 DUP(?)
SDIRBUF DB 12 DUP(?)
BITS DW ?
PATHCNT DW ?
PATHPOS DW ?
PATHSW DW ?
FULLSCR DW ?
comma db 0 ;g flag set if +,, occurs
plus_comma db 0 ;g flag set if +,, occurs
dirflag db 0 ;AN015; set when pathcrunch called from DIR
parse_last dw 0 ;AN018; used to hold parsing position
system_cpage DW 0 ;AC001; used for CHCP variable
src_XA_size DW 0 ;AN000; size of extended attributes
src_XA_seg DW 0 ;AN000; segment of extended attributes
ext_open_parms label byte ;AN000; extended open parameter list
;emg340 ext_open_off dw offset trangroup:srcbuf ;AN000; offset of file name
ext_open_off dw ? ;AN030; offset of extended attributes
ext_open_seg dw ? ;AN000; segment of extended attributes
dw 0 ;AN000; no additional parameters
XA_cp_out label byte ;AN030; list for one extended attribute
DW 1 ;AN030; count of entries
DB EAISBINARY ;AN030; ea_type
DW EASYSTEM ;AN030; ea_flags
DB ? ;AN030; ea_rc
DB 2 ;AN030; ea_namelen
DW 2 ;AN030; ea_valuelen
DB "CP" ;AN030; ea_name
xa_list_attr DW 0 ;AC030; code page
xa_cp_length DW $-XA_cp_out ;AN030; length of buffer
arg_buf db 128 dup (?)
file_size_low dw ? ;AC000;
file_size_high dw ? ;AC000;
string_ptr_2 dw ?
;AD061;string_ptr_2_sb dw ?
copy_Num dw ?
cpyflag db ?
Dir_Num DW ?
bytes_free dw ?
dw ?
major_ver_num dw ?
minor_ver_num dw ?
one_char_val db ?,0
vol_drv db ?
IF IBM
ROM_CALL DB ? ; flag for rom function
ROM_IP DW ?
ROM_CS DW ?
ENDIF
DESTVARS LABEL BYTE
DESTISDIR DB ?
DESTSIZ DB ?
DESTTAIL DW ?
DESTINFO DB ?
DESTBUF DB DIRSTRLEN + 20 DUP (?)
DESTHAND DW ?
DESTISDEV DB ?
FIRSTDEST DB ?
MELCOPY DB ?
MELSTART DW ?
SRCVARS LABEL BYTE
SRCISDIR DB ?
SRCSIZ DB ?
SRCTAIL DW ?
SRCINFO DB ?
SRCBUF DB DIRSTRLEN + 20 DUP (?)
SRCHAND DW ?
SRCISDEV DB ?
SCANBUF DB DIRSTRLEN + 20 DUP (?)
SRCPT DW ?
INEXACT DB ?
NOWRITE DB ?
BINARY DB ?
WRITTEN DW ?
TERMREAD DB ?
ASCII DB ?
PLUS DB ?
objcnt db ? ; Used in copy
CPDATE DW ?
CPTIME DW ?
BATHAND DW ? ; Batch handle
STARTEL DW ?
ELCNT DB ?
ELPOS DB ?
SKPDEL DB ?
SOURCE DB 11 DUP(?)
ext_entered db 0 ;AN005;
display_ioctl db 0 ;AN000; info level
db 0 ;AN000; reserved
dw crt_ioctl_ln ;AN000; length of data
dw ? ;AN000; control flags
display_mode db ? ;AN000; display mode, colors
db 0 ;AN000; reserved
dw ? ;AN023; colors
dw ? ;AN000; display width (PELS)
dw ? ;AN000; display length (PELS)
display_width dw ? ;AN000; display width
linperpag dw linesperpage ;AN000; display length (default to linesperpage)
vol_ioctl_buf label byte ;AN000; buffer for ioctl volume label/serial call
dw 0 ;AN000; info level
vol_serial dd 0 ;AN000; volume serial number
vol_label db 11 dup (" ") ;AN000; volume label - init to blanks
db 8 dup (" ") ;AN000; file system type
expand_star db ?
comspec_flag db ?
msg_flag db ? ;AN022; flag set if non-utility message issued
msg_numb dw 0 ;AN022; set with extended error message issued
append_exec db 0 ;AN041; set if internal append executed
print_err_flag dw 0 ;AN000; flag set if error during sysdispmsg
subst_buffer db parm_block_size*2 dup (0);AN061;
;;;; IF KANJI 3/3/KK
KPARSE DB ?
;;;; ENDIF 3/3/KK
; Data declarations taken out of parse.asm
arg arg_unit <> ; pointers, arg count, string buffer
argbufptr DW ? ; index for argv[].argpointer
tpbuf DB 128 DUP (?) ; temporary buffer
LAST_ARG DW ? ; point at which to accumulate switch info
comptr dw ? ; ptr into combuf
; Data declarations taken out of path.asm
fbuf find_buf <> ; dma buffer for findfirst/findnext
pathinfo DW 3 DUP (?) ; ES, SI(old), and SI(new) of user path
psep_char DB ? ; '/' or '\'
search_best DB (?) ; best code, best filename so far
fname_max_len equ 13
search_best_buf DB fname_max_len DUP (?)
search_curdir_buf DB 64 DUP (?) ; a place for CurDir info, if successful
search_error DW (?) ; address of error message to be printed
; Data declarations taken out of tbatch.asm
if_not_count DW ?
zflag db ? ; Used by typefil to indicate ^Z's
DW 80H DUP(0) ; Init to 0 to make sure the linker is not fooled
STACK LABEL WORD
INTERNATVARS internat_block <>
DB (internat_block_max - ($ - INTERNATVARS)) DUP (?)
BatBufPos DW ? ; integer position in buffer of next byte
BatBuf DB BatLen DUP (?)
BatBufEnd DW ?
; *****************************************************
; EMG 4.00
; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00
; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE
; *****************************************************
;
; COMMON PARSE OUTPUT BLOCKS
;
;
; Common output blocks for PARSE number, complex, or string values.
;
PARSE1_OUTPUT LABEL BYTE ;AN000;
PARSE1_TYPE DB 0 ;AN000; type
PARSE1_CODE DB 0 ;AN000; return value
PARSE1_SYN DW 0 ;AN000; es offset of synonym
PARSE1_ADDR DD 0 ;AN000; numeric value / address
; of string value
;
; Common output block for PARSE date strings.
;
DATE_OUTPUT LABEL BYTE ;AN000;
DATE_TYPE DB 0 ;AN000; type
DB 0 ;AN000; return value
DW 0 ;AN000; es offset of synonym
DATE_YEAR DW 0 ;AN000; year
DATE_MONTH DB 0 ;AN000; month
DATE_DAY DB 0 ;AN000; day
;
; Common output block for PARSE time strings.
;
TIME_OUTPUT LABEL BYTE ;AN000;
TIME_TYPE DB 0 ;AN000; type
DB 0 ;AN000; return value
DW 0 ;AN000; es offset of synonym
TIME_HOUR DB 0 ;AN000; hour
TIME_MINUTES DB 0 ;AN000; minutes
TIME_SECONDS DB 0 ;AN000; seconds
TIME_FRACTION DB 0 ;AN000; hundredths
;
; Common output block for PARSE drive specifier (one based drive number).
;
DRIVE_OUTPUT LABEL BYTE ;AN000;
DRIVE_TYPE DB 0 ;AN000; type
DRIVE_VALUE DB 0 ;AN000; return value
DW 0 ;AN000; es offset of synonym
DRIVE_NUMBER DB 0 ;AN000; drive number
DB 0,0,0 ;AN000; reserved
TRANSPACEEND LABEL BYTE
TRANSPACE ENDS
END

View File

@@ -0,0 +1,520 @@
page 80,132
; SCCSID = @(#)tucode.asm 4.2 85/05/31
; SCCSID = @(#)tucode.asm 4.2 85/05/31
Title COMMAND Language midifiable Code Transient
.xlist
.xcref
INCLUDE dossym.inc
INCLUDE comsw.asm
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN ECHOFLAG:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BAD_ON_OFF_ptr:word
EXTRN ctrlcmes_ptr:word
EXTRN DEL_Y_N_PTR:WORD
EXTRN ECHOMES_ptr:word
EXTRN extend_buf_ptr:word ;AC000;
EXTRN offmes_ptr:word
EXTRN onmes_ptr:word
EXTRN PARSE_BREAK:BYTE ;AN000;
EXTRN promptdat_moday:word ;AC000;
EXTRN promptdat_ptr:word ;AC000;
EXTRN promptdat_yr:word ;AC000;
EXTRN string_buf_ptr:word
EXTRN SUREMES_ptr:word
EXTRN VERIMES_ptr:BYTE
EXTRN WeekTab:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf:byte
EXTRN BWDBUF:BYTE
EXTRN DEST:BYTE
EXTRN destdir:byte
EXTRN dirchar:byte
EXTRN PARSE1_CODE:BYTE ;AN000;
EXTRN RESSEG:WORD
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
EXTRN CERROR:NEAR
EXTRN CRLF2:NEAR
EXTRN extend_setup:near ;AN022;
PUBLIC CNTRLC
PUBLIC ECHO
PUBLIC GetDate
PUBLIC NOTEST2
PUBLIC PRINT_DATE
PUBLIC SLASHP_ERASE ;AN000;
PUBLIC VERIFY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
; ****************************************************************
; *
; * ROUTINE: NOTEST2 - execution of DEL/ERASE command
; *
; * FUNCTION: Delete files based on user parsed input. Prompt
; * user for Y/N if necessary. If an error occurs,
; * set up an error message and go to CERROR.
; *
; * INPUT: FCB at 5ch set up with filename(s) entered
; * Current directory set to entered directory
; *
; * OUTPUT: none
; *
; ****************************************************************
;
; ARE YOU SURE prompt when deleting *.*
NOTEST2:
MOV CX,11
MOV SI,FCB+1
AMBSPEC:
LODSB
CMP AL,'?'
JNZ ALLFIL
LOOP AMBSPEC
ALLFIL:
CMP CX,0
JNZ NOPRMPT
ASKAGN:
MOV DX,OFFSET TRANGROUP:SUREMES_ptr ; "Are you sure (Y/N)?"
invoke std_printf
MOV SI,80H
MOV DX,SI
MOV WORD PTR [SI],120 ; zero length
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_STRING_INPUT
INT 21H
LODSW
OR AH,AH
JZ ASKAGN
INVOKE SCANOFF
call char_in_xlat ;G Convert to upper case
retc ;AN000; return if function not supported
CMP AL,CAPITAL_N ;G
retz
CMP AL,CAPITAL_Y ;G
PUSHF
CALL CRLF2
POPF
JNZ ASKAGN
NOPRMPT:
MOV AH,FCB_DELETE
MOV DX,FCB
INT 21H
INC AL
jz eraerr
invoke RESTUDIR
ret ; If no error, return
eraerr:
invoke set_ext_error_msg ;AN022; set up the extended error
push dx ;AN022; save message
invoke RESTUDIR
pop dx ;AN022; restore message
cmp word ptr extend_buf_ptr,error_no_more_files ;AN022; convert no more files to
jnz cerrorj2 ;AN022; file not found
mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block
cerrorj2:
jmp cerror
; ****************************************************************
; *
; * ROUTINE: SLASHP_ERASE - execution of DEL/ERASE /P
; *
; * FUNCTION: Delete files based on user parsed input. Prompt
; * user for Y/N where necessary. If an error occurs
; * set up and error message and transfer control
; * to CERROR.
; *
; * INPUT: FCB at 5ch set up with filename(s) entered
; * Current directory set to entered directory
; *
; * OUTPUT: none
; *
; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SLASHP_ERASE: ;AN000; entry point
invoke build_dir_string ;AN000; set up current directory string for output
mov ah,Set_DMA ;AN000; issue set dta int 21h
mov dx,offset trangroup:destdir ;AN000; use Destdir for target
int 21H ;AN000;
mov ah,Dir_Search_First ;AN000; do dir search first int 21h
mov dx,FCB ;AN000; use FCB at 5Ch for target
int 21H ;AN000;
inc al ;AN000; did an error occur
jz eraerr ;AN022; go to error exit
delete_prompt_loop: ;AN000;
mov si,offset trangroup:destdir+1 ;AN000; set up FCB as source
mov di,offset trangroup:dest ;AN000; set up dest as target
mov al,dirchar ;AN000; store a "\" in the first char
stosb ;AN000; of DEST
invoke fcb_to_ascz ;AN000; convert filename from FCB to ASCIIZ string
slashp_askagn: ;AN000;
call crlf2 ;AN000; print out carriage return, line feed
mov dx,offset trangroup:bwdbuf ;AN000; print out current directory string
mov bx,dx ;AN000; get string pointer in bx
cmp byte ptr [bx+3],end_of_line_out ;AN000; see if only D:\,0
jnz not_del_root ;AN000; no continue
mov byte ptr [bx+2],end_of_line_out ;AN000; yes, get rid of \
Not_del_root: ;AN000;
mov string_ptr_2,dx ;AN000;
mov dx,offset trangroup:string_buf_ptr ;AN000;
invoke std_printf ;AN000;
mov dx,offset trangroup:dest ;AN000; print out file name string
mov string_ptr_2,dx ;AN000;
mov dx,offset trangroup:string_buf_ptr ;AN000;
invoke std_printf ;AN000;
mov dx,offset trangroup:Del_Y_N_Ptr ;AN000; issue ", Delete (Y/N)?" message
invoke std_printf ;AN000;
mov si,80H ;AN000; set up buffer for input
mov dx,si ;AN000;
mov word ptr [si],combuflen ;AN000;
mov ax,(std_con_input_flush shl 8) or std_con_string_input ;AN000;
int int_command ;AN000; get input from the user
lodsw ;AN000;
or ah,ah ;AN000; was a character entered?
jz slashp_askagn ;AN000; no - ask again
invoke scanoff ;AN000; scan off leading delimiters
call char_in_xlat ;AN000; yes - upper case it
retc ;AN000; return if function not supported
cmp al,capital_n ;AN000; was it no?
jz next_del_file ;AN000; yes - don't delete file
cmp al,capital_y ;AN000; was it yes?
jz delete_this_file ;AN000; yes - delete the file
jmp short slashp_askagn ;AN000; it was neither - ask again
delete_this_file: ;AN000;
mov ah,fcb_delete ;AN000; delete the file
mov dx,offset trangroup:destdir ;AN000; use Destdir for target
int int_command ;AN000;
inc al ;AN000; did an error occur?
jnz next_del_file ;AN000; no - get next file
jmp eraerr ;AN022; go to error exit - need long jmp
next_del_file: ;AN000;
mov ah,dir_search_next ;AN000; search for another file
mov dx,FCB ;AN000;
int int_command ;AN000;
inc al ;AN000; was a file found?
jz slash_p_exit ;AN000; no - exit
jmp delete_prompt_loop ;AN000; yes - continue (need long jump)
slash_p_exit:
invoke get_ext_error_number ;AN022; get the extended error number
cmp ax,error_no_more_files ;AN022; was error file not found?
jz good_erase_exit ;AN022; yes - clean exit
jmp extend_setup ;AN022; go issue error message
good_erase_exit:
invoke restudir ;AN000; we're finished - restore user's dir
call crlf2 ;AN000; print out carriage return, line feed
ret ;AN000; exit
;************************************************
; ECHO, BREAK, and VERIFY commands. Check for "ON" and "OFF"
break Echo
assume ds:trangroup,es:trangroup
ECHO:
CALL ON_OFF
JC DOEMES
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
JNZ ECH_OFF
OR [ECHOFLAG],1
RET
ECH_OFF:
AND [ECHOFLAG],NOT 1
RET
CERRORJ:
JMP CERROR
;
; There was no discrenable ON or OFF after the ECHO. If there is nothing but
; delimiters on the command line, we issue the ECHO is ON/OFF message.
;
ASSUME DS:TRANGROUP
DOEMES:
cmp cl,0 ;AC000; was anything on the line?
jz PEcho ; just display current state.
MOV DX,82H ; Skip one char after "ECHO"
invoke CRPRINT
JMP CRLF2
PECHO:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV BL,[ECHOFLAG]
PUSH CS
POP DS
ASSUME DS:TRANGROUP
AND BL,1
MOV DX,OFFSET TRANGROUP:ECHOMES_ptr
JMP SHORT PYN
break Break
assume ds:trangroup,es:trangroup
CNTRLC:
CALL ON_OFF
MOV AX,(SET_CTRL_C_TRAPPING SHL 8) OR 1
JC PCNTRLC
JNZ CNTRLC_OFF
MOV DL,1
INT 21H ; Set ^C
RET
CNTRLC_OFF:
XOR DL,DL
INT 21H ; Turn off ^C check
RET
PCNTRLC:
CMP CL,0 ;AC000; rest of line blank?
JNZ CERRORJ ; no, oops!
pccont:
XOR AL,AL
INT 21H
MOV BL,DL
MOV DX,OFFSET TRANGROUP:CTRLCMES_ptr
PYN:
mov si,offset trangroup:onmes_ptr ;AC000; get ON pointer
OR BL,BL
JNZ PRINTVAL
mov si,offset trangroup:offmes_ptr ;AC000; get OFF pointer
PRINTVAL:
push dx ;AN000; save offset of message block
mov bx,dx ;AN000; save offset value
lodsw ;AN000; get message number of on or off
mov dh,util_msg_class ;AN000; this is a utility message
invoke Tsysgetmsg ;AN000; get the address of the message
add bx,ptr_off_pos ;AN000; point to offset of ON/OFF
mov word ptr [bx],si ;AN000; put the offset in the message block
pop dx ;AN000; get message back
invoke std_printf ;AC000; go print message
mov word ptr [bx],0 ;AN000; zero out message pointer
ret ;AN000; exit
break Verify
assume ds:trangroup,es:trangroup
VERIFY:
CALL ON_OFF
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1
JC PVERIFY
JNZ VER_OFF
INT 21H ; Set verify
RET
VER_OFF:
DEC AL
INT 21H ; Turn off verify after write
RET
PVERIFY:
CMP CL,0 ;AC000; is rest of line blank?
JNZ CERRORJ ; nope...
MOV AH,GET_VERIFY_ON_WRITE
INT 21H
MOV BL,AL
MOV DX,OFFSET TRANGROUP:VERIMES_ptr
JMP PYN
; ****************************************************************
; *
; * ROUTINE: ON_OFF
; *
; * FUNCTION: Parse the command line for an optional ON or
; * OFF string for the BREAK, VERIFY, and ECHO
; * routines.
; *
; * INPUT: command line at offset 81H
; * PARSE_BREAK control block
; *
; * OUTPUT: If carry is clear
; * If ON is found
; * Zero flag set
; * If OFF is found
; * Zero flag clear
; * If carry set
; * If nothing on command line
; * CL set to zero
; * If error
; * CL contains error value from parse
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
ON_OFF:
MOV SI,81h
scan_on_off: ;AN032; scan off leading blanks & equal
lodsb ;AN032; get a char
cmp al,blank ;AN032; if whitespace
jz scan_on_off ;AN032; keep scanning
cmp al,tab_chr ;AN032; if tab
jz scan_on_off ;AN032; keep scanning
cmp al,equal_chr ;AN032; if equal char
jz parse_on_off ;AN032; start parsing
dec si ;AN032; if none of above - back up
parse_on_off: ;AN032; and start parsing
mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
jz BADONF ;AC000; yes, return error
cmp ax,result_no_error ;AN000; did an error occur
jz on_off_there ;AN000; no - continue
mov cx,ax ;AN000; yes - set cl to error code
jmp short BADONF ;AN000; return error
on_off_there:
cmp parse1_code,-1 ;AN014; was a valid positional present?
jnz good_on_off ;AN014; yes - continue
mov cx,badparm_ptr ;AN014; something other than ON/OFF
jmp short BADONF ;AN014; return error
good_on_off: ;AN014;
xor ax,ax ;AC000; set up return code for
or al,parse1_code ;AC000; ON or OFF in AX
pushf ;AN000; save flags
mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK
xor dx,dx ;AN000;
invoke cmd_parse ;AN000; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jnz BADONF_flags ;AN000; NO, return error
popf ;AN000; restore flags
clc ;AC000; no error
jmp short on_off_end ;AN000; return to caller
BADONF_flags:
mov cx,ax
popf
;
; No discernable ON or OFF has been found. Put an error message pointer in DX
; and return the error
;
BADONF:
MOV DX,OFFSET TRANGROUP:BAD_ON_OFF_ptr
STC
ON_OFF_END:
RET
;*************************************************************************
; print date
PRINT_DATE:
PUSH ES
PUSH DI
PUSH CS
POP ES
CALL GetDate ; get date
xchg dh,dl ;AN000; switch month & day
mov promptDat_yr,cx ;AC000; put year into message control block
mov promptDat_moday,dx ;AC000; put month and day into message control block
mov dx,offset trangroup:promptDat_ptr ;AC000; set up message for output
invoke std_printf
;AD061; mov promptDat_yr,0 ;AC000; reset year, month and day
;AD061; mov promptDat_moday,0 ;AC000; pointers in control block
POP DI ;AC000; restore di,es
POP ES ;AC000;
return
;
; Do GET DATE system call and set up 3 character day of week in ARG_BUF
; for output. Date will be returned in CX,DX.
;
GetDate:
mov di,offset trangroup:arg_buf ;AC000; target for day of week
MOV AH,GET_DATE ;AC000; get current date
INT int_command ;AC000; Get date in CX:DX
CBW ;AC000;
push cx ;AN000; save date returned in
push dx ;AN000; CX:DX
MOV SI,AX
SHL SI,1
ADD SI,AX ; SI=AX*3
mov cx,si ;AN000; save si
mov ax,weektab ;AN000; get message number of weektab
mov dh,util_msg_class ;AN000; this is a utility message
push di ;AN000; save argument buffer
invoke Tsysgetmsg ;AN000; get the address of the message
pop di ;AN000; retrieve argument buffer
add si,cx ;AC000; get day of week
MOV CX,3
REP MOVSB
mov al,end_of_line_out ;AC000; terminate the string
stosb
pop dx ;AN000; get back date
pop cx ;AN000;
return
;g
;g This routine determines whether the character in AL is a
;g Yes or No character. On return, if AL=0, the character is
;g No, if AL=1, the character is Yes.
;g
assume ds:trangroup
char_in_xlat proc near
mov dl,al ;AC000; get character into DX
xor dh,dh ;AC000;
mov ax,(getextcntry SHL 8) + 35 ;AC000; Yes/No char call
int int_command ;AC000;
ret
char_in_xlat endp
TRANCODE ENDS
END

View File

@@ -0,0 +1,270 @@
page 80,132
; SCCSID = @(#)uinit.asm 4.5 85/12/04
; SCCSID = @(#)uinit.asm 4.5 85/12/04
TITLE COMMAND Initialization messages
.XCREF
.XLIST
include comsw.asm
include comseg.asm
include ifequ.asm
.LIST
.CREF
addr macro sym,name
public name
ifidn <name>,<>
dw offset resgroup:sym
else
name dw offset resgroup:sym
endif
endm
ENVIRONMENT SEGMENT PUBLIC PARA ;AC000;
EXTRN ECOMSPEC:BYTE
ENVIRONMENT ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
extrn Printf_init:FAR
extrn Triage_Init:FAR
extrn append_parse:FAR ;AN054;
TranCode ENDS
INIT SEGMENT PUBLIC PARA ;AC000;
public icondev
public BADCSPFL
public COMSPECT
public AUTOBAT
public fslash
public bslash
public space
public PRDATTM
public INITADD
public print_add
public CHUCKENV
public scswitch
public ucasea
public ECOMLOC
public equalsign
public lcasea
public lcasez
public comspstring
public EnvSiz
public EnvMax
public initend
public trnsize
public resetenv ;AC000;
public ext_msg ;AC000;
public num_positionals
public internat_info
public parsemes_ptr
PUBLIC triage_add
PUBLIC oldenv
PUBLIC usedenv
PUBLIC KAUTOBAT ;AN000; 3/3/KK
public eswitch ;AN018;
public dswitch ;AN018;
public init_parse ;AN054;
public old_parse_ptr ;AN057;
PUBLIC pars_msg_off ;AN060;
PUBLIC pars_msg_seg ;AN060;
include resmsg.equ ;AC000;
ICONDEV LABEL BYTE
DB "/DEV/"
DB "CON",0,0,0,0,0,0 ; Room for 8 char device
BADCSPFL DB 0
COMSPECT DB "/COMMAND.COM",0,0
AUTOBAT DB 0,":\AUTOEXEC.BAT",0,0DH ;AC027;
KAUTOBAT DB 0,":\KAUTOEXE.BAT",0,0DH ;AC027; 3/3/KK
PRDATTM DB -1 ;Init not to prompt for date time
INITADD DD ?
print_add LABEL DWORD
DW OFFSET TranGroup:Printf_INIT
DW 0
triage_add LABEL DWORD
DW OFFSET TranGroup:Triage_Init
DW 0
CHUCKENV DB 0
;eg ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC-10H
ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC ;eg
COMSPSTRING DB "COMSPEC="
equalsign db "="
lcasea db "a"
lcasez db "z"
fslash db "/"
bslash db "\"
space db " "
scswitch db "C" ; Single command
ucasea db "A"
EnvSiz DW 0 ; size user wants to allocate
EnvMax DW 0 ; maximum size allowed.
oldenv DW 0 ; envirseg at initialization
usedenv DW 0 ; amount of envirseg used
PARS_MSG_OFF DW 0 ;AN060; SAVED PARSE ERROR MESSAGE OFFSET
PARS_MSG_SEG DW 0 ;AN060; SAVED PARSE ERROR MESSAGE SEGMENT
;Do not separate the following two words. Used to call transient PARSE routine
init_parse label dword ;AN054;
init_p DW TRANGROUP:APPEND_PARSE ;AN054;
initend DW 0 ;eg segment address of end of init
;End of data that shouldn't be separated.
trnsize DW 0 ;eg size of transient in paragraphs
resetenv DB 0 ;eg set if we need to setblck env at endinit
ext_msg DB 0 ;AN000; set if /MSG switch entered
eswitch db 0 ;AN018; set if /e was entered
dswitch db 0 ;AN018; set if /d was entered
parsemes_ptr dw 0 ;AN000; word to store parse error number
;
; PARSE BLOCK FOR COMMAND
;
PUBLIC PARSE_COMMAND ;AN000;
PUBLIC COMND1_OUTPUT ;AN000;
PUBLIC COMND1_TYPE ;AN000;
PUBLIC COMND1_CODE ;AN000;
PUBLIC COMND1_SYN ;AN000;
PUBLIC COMND1_ADDR ;AN000;
PUBLIC COMMAND_F_SYN ;AN000;
PUBLIC COMMAND_P_SYN ;AN000;
PUBLIC COMMAND_C_SYN ;AN000;
PUBLIC COMMAND_D_SYN ;AN000;
PUBLIC COMMAND_E_SYN ;AN000;
PUBLIC COMMAND_M_SYN ;AN000;
;
; The following parse control block is used for COMMAND. This block is
; used for parsing during initialization. The sytax for COMMAND is:
; COMMAND [d:][path][/P][/F][/D][/E:xxxxx][/MSG][/C executable]
; Anything on the command line after the /C switch will be passed to the
; executable command, so if /C is used, it must be specified last. The
; /MSG switch can only be specified if the /P switch is specified.
;
ENVBIG EQU 32768 ;AN000; maximum environment size
ENVSML EQU 160 ;AN000; minimum environment size
INTERNAT_INFO LABEL BYTE ;AN000; used for country info after parsing is completed
PARSE_COMMAND LABEL BYTE ;AN000;
DW RESGROUP:COMMAND_PARMS ;AN000;
DB 0 ;AN000; no extra delimiter
COMMAND_PARMS LABEL BYTE ;AN000;
DB 0,1 ;AN000; 1 positional parm
DW RESGROUP:COMMAND_FILE ;AN000;
DB 6 ;AN000; 6 switches
DW RESGROUP:COMMAND_SWITCH1 ;AN000;
DW RESGROUP:COMMAND_SWITCH2 ;AN000;
DW RESGROUP:COMMAND_SWITCH3 ;AN000;
DW RESGROUP:COMMAND_SWITCH4 ;AN000;
DW RESGROUP:COMMAND_SWITCH5 ;AN000;
DW RESGROUP:COMMAND_SWITCH6 ;AN000;
DB 0 ;AN000; no keywords
COMMAND_FILE LABEL BYTE ;AN000;
DW 0201H ;AN000; filespec - optional
DW 1 ;AN000; capitalize - file table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 0 ;AN000; no keywords
COMMAND_SWITCH1 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 1 ;AN000; 1 keyword
COMMAND_P_SYN DB "/P",0 ;AN000; /P switch
COMMAND_SWITCH2 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 1 ;AN000; 1 keyword
COMMAND_F_SYN DB "/F",0 ;AN000; /F switch
COMMAND_SWITCH3 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 1 ;AN000; 1 keyword
COMMAND_D_SYN DB "/D",0 ;AN000; /D switch
COMMAND_SWITCH4 LABEL BYTE ;AN000;
DW 8000H ;AN000; numeric value - required
DW 0 ;AN000; no function flags
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:COMMAND_E_VAL ;AN000; pointer to value list
DB 1 ;AN000; 1 keyword
COMMAND_E_SYN DB "/E",0 ;AN000; /E switch
COMMAND_E_VAL LABEL BYTE ;AN000;
DB 1 ;AN000;
DB 1 ;AN000; 1 range
DB 1 ;AN000; returned if result
DD ENVSML,ENVBIG ;AN000; minimum & maximum value
DB 0 ;AN000; no numeric values
DB 0 ;AN000; no string values
COMMAND_SWITCH5 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 1 ;AN000; 1 keyword
COMMAND_C_SYN DB "/C",0 ;AN000; /C switch
COMMAND_SWITCH6 LABEL BYTE ;AN000;
DW 0 ;AN000; no match flags
DW 2 ;AN000; capitalize by char table
DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer
DW RESGROUP:NO_VAL ;AN000;
DB 1 ;AN000; 1 keyword
COMMAND_M_SYN DB "/MSG",0 ;AN000; /MSG switch
COMND1_OUTPUT LABEL BYTE ;AN000;
COMND1_TYPE DB 0 ;AN000; type
COMND1_CODE DB 0 ;AN000; return value
COMND1_SYN DW 0 ;AN000; synonym pointer
COMND1_ADDR DD 0 ;AN000; numeric value / address
; of string value
NO_VAL DB 0 ;AN000; no values
num_positionals DW 0 ;AN000; counter for positionals
old_parse_ptr DW 0 ;AN057; SI position before calling parser
.xlist
.xcref
INCLUDE SYSMSG.INC ;AN000; get message services routine
.list
.cref
ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP
MSG_UTILNAME <COMMAND> ;AN000; define utility name
MSG_SERVICES <COMR,COMMAND.CLB> ;AN000; include initialization messages
include msgdcl.inc
INIT ENDS
END