PAGE ,132 ; TITLE XCOPYPAR.SAL - LOOK AT COMMAND LINE PARMS ;****************** START OF SPECIFICATIONS ***************************** ; MODULE NAME: XCOPYPAR.SAL ; ; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters ; and the interface to the DOS system PARSER. ; ;FUNCTION: The static data areas are prescribed by the DOS system PARSER ; to define the several parameters presented to XCOPY. These ; data areas are passed to the PARSER, and its responses checked ; to determine the nature of the user's specifications. Any errors ; found in the user's parameters are defined in messages back ; to the user. ; ; ENTRY POINT: PARSER, near ; ; INPUT: (DOS COMMAND LINE PARAMETERS) ; ; SOURCE OPERAND: TARGET OPERAND: ; ; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]] ; or ; [d:] path [filename[.ext]] ; or ; d: [path] [filename[.ext]] ; ; WHERE ; ; [d:] - To specify the Source drive ; ; [d:] - To specify the Destination drive ; ; ; SWITCHES: ; ; /A /D /E /M /P /S /V /W ; ; ; Upon entry to PARSER in this module, ; "CURRENT_PARM" = offset to start of parm text in command string ; "ORDINAL" = initialized to zero ; PSP+81H = text of DOS command line parms string ; EXIT-NORMAL: ; EXIT-ERROR: ; INTERNAL REFERENCES: ; ROUTINES: ; PARSE_ERROR:NEAR Display the appropriate Parse error message. ; DATA AREAS: ; The several parameter control blocks, defined by the System ; PARSER interface, defining the XCOPY parameters. ; EXTERNAL REFERENCES: ; ROUTINES: ; SYSPARSE:NEAR System Command Line Common Parser. ; ; DATA AREAS: ; EXITFL:BYTE Errorlevel return code. ; MSGNUM_PARSE:WORD Message descriptor for all parse errors. ; ; NOTES: ; This module should be processed with the SALUT preprocessor ; with the re-alignment not requested, as: ; ; SALUT XCOPYPAR,NUL ; ; To assemble these modules, the alphabetical or sequential ; ordering of segments may be used. ; ; For LINK instructions, refer to the PROLOG of the main module, ; XCOPY.SAL. ; ; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, ; Ignore unique volume serial number differences ; A004 PTM0700 9/02/87 Avoid duplicate switches and ; display parm in error. ; ; Label: "The DOS XCOPY Utility" ; "Version 4.00 (C)Copyright 1988 Microsoft" ; "Licensed Material - Program Property of Microsoft " ; ;****************** END OF SPECIFICATIONS ***************************** IF1 %OUT COMPONENT=XCOPY, MODULE=XCOPYPAR.SAL... ENDIF ; = = = = = = = = = = = = HEADER MACRO TEXT .XLIST SUBTTL TEXT .LIST PAGE ENDM ; = = = = = = = = = = = = ; $SALUT (4,23,28,36) ; LOCAL EQUATES INIT_ERROR_FLAG EQU 80H ;AN000;critical initialization error. Should abort CMD_BUF_SIZE EQU 127 ;AN000;NUMBER BYTES IN DOS COMMAND LINE BUFFER ZERO EQU 0 ;AN000;COMPARAND FOR CLEARED REG NUL EQU 0 ;AN000;DELIMITER FOR ASCIIZ STRINGS ; = = = = = = = = = = = = ; PARSER ASSEMBLE SWITCHES FarSW EQU 0 ;AN000;CALL THE PARSER BY FAR CALL DateSW EQU 1 ;AN000;DATE FORMAT TimeSW EQU 1 ;AN000;TIME FORMAT FileSW EQU 1 ;AN000;FILE SPECIFICATION CAPSW EQU 1 ;AN000;USE FILE TABLE CAPS CmpxSW EQU 0 ;AN000;COMPLEX LIST DrvSW EQU 1 ;AN000;DRIVE ONLY FORMAT QusSW EQU 0 ;AN000;QUOTED STRING NumSW EQU 1 ;AN000;NUMERIC VALUE KeySW EQU 0 ;AN000;KEYWORDS SwSW EQU 1 ;AN000;SWITCHES Val1SW EQU 0 ;AN000;VALUE DEFINITION #1 Val2SW EQU 0 ;AN000;VALUE DEFINITION #2 Val3SW EQU 0 ;AN000;VALUE DEFINITION #3 ; = = = = = = = = = = = = ; EXIT CODES FROM SYSPARSE (WHEN CY=0) SYSPRM_EX_OK EQU 0 ;AN000; no error SYSPRM_EX_MANY EQU 1 ;AN000; too many operands SYSPRM_EX_MISSING EQU 2 ;AN000; required operand missing SYSPRM_EX_NOT_SWLIST EQU 3 ;AN000; not in switch list provided SYSPRM_EX_NOT_KEYLIST EQU 4 ;AN000; not in keyword list provided SYSPRM_EX_RANGE EQU 6 ;AN000; out of range specified SYSPRM_EX_VALUE EQU 7 ;AN000; not in value list provided SYSPRM_EX_STRING EQU 8 ;AN000; not in string list provided SYSPRM_EX_SYNTAX EQU 9 ;AN000; syntax error SYSPRM_EX_EOL EQU -1 ;AN000; end of command line ; = = = = = = = = = = = = HEADER ; $SALUT (4,17,22,36) PSP STRUC DB 80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP PSP_PARMLEN DB ? ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE PSP_COMMAND DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE PSP ENDS ; = = = = = = = = = = = = CSEG SEGMENT PUBLIC ;AN000;PLACE HOLDER FOR PARSE CODE CSEG ENDS DGROUP GROUP DSEG, DSEG_INIT DSEG SEGMENT PARA PUBLIC DSEG ENDS ; DSEG_INIT SEGMENT PARA PUBLIC ; INCLUDE PSDATA.INC ;AN018;WORK AREA USED BY PARSE.ASM ; ;--- EXTERNAL VARIABLES --- EXTRN PARM_FLAG: BYTE ;AN000; IF1 %OUT COMPONENT=XCOPY, SUBCOMPONENT=PARSE ENDIF ;--- COMMAND_LINE DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE (INTERNAL USE) PUBLIC COMMAND_LINE CURRENT_PARM DW DGROUP:COMMAND_LINE ;AN000;POINTER INTO COMMAND OF NEXT ;OPERAND PUBLIC CURRENT_PARM ORDINAL DW 0 ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE PUBLIC ORDINAL TAR_DRIVE DB " " ;AN000;TARGET DRIVE LETTER SPECIFIED IN PARMS SO_DRIVE DB " " ;AN000;SOURCE DRIVE LETTER SPECIFIED PUBLIC TAR_DRIVE,SO_DRIVE ;AN000;PASS RESULTS TO INIT ROUTINE ; = = = = = = = = = = = = HEADER ;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER PUBLIC PARMS ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE PARMS LABEL BYTE ;AN000;PARMS CONTROL BLOCK DW DGROUP:PARMSX ;AN000;POINTER TO PARMS EXTENSION DB 0 ;AN000; NUMBER OF STRINGS (0, 1, 2) DB 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS DB ";" ;AN000; ADDITIONAL DELIMITER ;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK PARMSX LABEL BYTE ;AN000; PARMS EXTENSION CONTROL BLOCK DB 1,2 ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED DW DGROUP:CONTROL_POS1 ;AN000; DESCRIPTION OF POSITIONAL 1 DW DGROUP:CONTROL_POS2 ;AN000; DESCRIPTION OF POSITIONAL 2 DB 2 ;AN000; THERE ARE 8 SWITCHES IN 2 GROUPS ;AN000; (/A, /E, /M, /P, /S, /V, /W, /D) DW DGROUP:SW1_7 ;AN000; POINTER TO THE SWITCH DEFINITION AREA DW DGROUP:SW8 ;AN000; POINTER TO EIGHTH SWITCH DEFINITION AREA DB 0 ;AN000; MAX KEYWORD OPERANDS ALLOWED ;AN000; THERE IS NO CONTROL BLOCK ;AN000; DEFINING KEYWORDS ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER ;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL ;FIRST POSITIONAL PARAMETER IS: ; ; [d:] [path] filename[.ext] ; or ; [d:] path [filename[.ext]] ; or ; d: [path] [filename[.ext]] ; PUBLIC CONTROL_POS1 ;AN000; LET LINK MAKE THIS ADDRESSABLE CONTROL_POS1 LABEL BYTE ;AN000; FIRST POSITIONAL DESCRIPTOR FOR FILESPEC ;AN000; DW 0200H ;AN000; CONTROLS TYPE MATCHED ; SELECTED BITS: "FILE SPEC" ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE ; CHECKED) ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) ; 0010H=IGNORE ":" AT END IN MATCH ; 0002H=REPEATS ALLOWED ; 0001H=OPTIONAL DW 0002H ;AN000; FUNCTION_FLAGS ; 0001H=CAP RESULT BY FILE TABLE ; 0002H=CAP RESULT BY CHAR TABLE ; 0010H=REMOVE ":" AT END DW DGROUP:RESULT1 ;AN000; RESULT BUFFER (FIRST) PUBLIC RESULT1 DW DGROUP:NOVALS ;AN000; NO VALUE LISTS DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000; IN FOLLOWING LIST ;SECOND POSITIONAL PARAMETER IS: ; ; [d:] [path] [filename[.ext]] ; PUBLIC CONTROL_POS2 ;AN000; LET LINK MAKE THIS ADDRESSABLE CONTROL_POS2 LABEL BYTE ;AN000; SECOND POSITIONAL DESCRIPTOR FOR FILESPEC, ;AN000; OPTIONAL DW 0201H ;AN000; CONTROLS TYPE MATCHED ;AN000; SELECTED BITS: "FILE SPEC" DW 0002H ;AN000; FUNCTION_FLAGS DW DGROUP:RESULT2 ;AN000; RESULT BUFFER (SECOND) DW DGROUP:NOVALS ;AN000; NO VALUE LISTS DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000; IN FOLLOWING LIST ;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS NOVALS DB 0 ;AN000;NO VALUE DEFINITIONS ;RESULTS CONTROL BLOCK FOR THE FIRST POSITIONAL PARAMETER RESULT1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS TYPE1 DB 0 ;AN000; TYPE RETURNED: 0=RESERVED, PUBLIC TYPE1 ;AN000; 1=NUMBER, 2=LIST INDEX, ;AN000; 3=STRING, 4=COMPLEX, ;AN000; 5=FILESPEC, 6=DRIVE ;AN000; 7=DATE, 8=TIME ;AN000; 9=QUOTED STRING RESULT_TAG1 DB 0FFH ;AN000; MATCHED ITEM TAG DW 0 ;AN000; POINTER TO SYNONYM RESULT_PTR1 DD 0 ;AN000; FILESPEC OFFSET PUBLIC RESULT_PTR1 ;RESULTS CONTROL BLOCK FOR THE SECOND POSITIONAL PARAMETER RESULT2 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS PUBLIC RESULT2 TYPE2 DB 0 ;AN000; TYPE RETURNED: 0=RESERVED, PUBLIC TYPE2 ;AN000; 1=NUMBER, 2=LIST INDEX, ;AN000; 3=STRING, 4=COMPLEX, ;AN000; 5=FILESPEC, 6=DRIVE ;AN000; 7=DATE, 8=TIME ;AN000; 9=QUOTED STRING RESULT_TAG2 DB 0FFH ;AN000; MATCHED ITEM TAG DW 0 ;AN000; POINTER TO SYNONYM RESULT_PTR2 DD 0 ;AN000; FILESPEC OFFSET PUBLIC RESULT_PTR2 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER ;PARSER CONTROL BLOCK DEFINING THE SWITCHES, OPTIONAL PUBLIC SW1_7 ;AN000;LET LINK MAKE THIS ADDRESSABLE SW1_7 LABEL BYTE ;AN000;SWITCH DESCRIPTOR FOR THE FIRST SEVEN SW DW 0001H ;AN000; CONTROLS TYPE MATCHED ;SELECTED BITS: "OPTIONAL" ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE ; CHECKED) ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) ; 0010H=IGNORE ":" AT END IN MATCH ; 0002H=REPEATS ALLOWED ; 0001H=OPTIONAL DW 0002H ;AN000; FUNCTION_FLAGS ; 0001H=CAP RESULT BY FILE TABLE ; 0002H=CAP RESULT BY CHAR TABLE ; 0010H=REMOVE ":" AT END DW DGROUP:RESULTSW1 ;AN000; RESULT BUFFER PUBLIC RESULTSW1 ;AN000;LET LINK MAKE THIS ADDRESSABLE DW DGROUP:NOVALS ;AN000; VALUE LISTS DB 7 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000; IN FOLLOWING LIST SW_A DB "/A",0 PUBLIC SW_A SW_E DB "/E",0 PUBLIC SW_E SW_M DB "/M",0 PUBLIC SW_M SW_P DB "/P",0 PUBLIC SW_P SW_S DB "/S",0 PUBLIC SW_S SW_V DB "/V",0 PUBLIC SW_V SW_W DB "/W",0 PUBLIC SW_W ;PARSER CONTROL BLOCK DEFINING THE DATE SWITCH, OPTIONAL PUBLIC SW8 ;AN000; LET LINK MAKE THIS ADDRESSABLE SW8 LABEL BYTE ;AN000; SWITCH DESCRIPTOR FOR THE DATE SW DW 1000H ;AN000; CONTROLS TYPE MATCHED DW 0000H ;AN000; FUNCTION_FLAGS DW DGROUP:DATE_BUFF ;AN000; RESULT BUFFER DW DGROUP:NOVALS ;AN000; VALUE LISTS DB 1 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000; IN FOLLOWING LIST SW_D DB "/D",0 PUBLIC SW_D ;RESULTS CONTROL BLOCK FOR THE /A,/E,/M,/P,/S,/V,/W SWITCHES RESULTSW1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS DB 3 ;AN000; TYPE RETURNED: 0=RESERVED, ; 1=NUMBER, 2=LIST INDEX, ; 3=STRING, 4=COMPLEX, ; 5=FILESPEC, 6=DRIVE ; 7=DATE, 8=TIME ; 9=QUOTED STRING DB 0FFh ;AN000; MATCHED ITEM TAG RESULTSWSYN DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:) PUBLIC RESULTSWSYN RESULTSWVAL DD 0 ;AN000; OFFSET OF STRING VALUE PUBLIC RESULTSWVAL ;RESULT CONTROL BLOCK FOR THE /D SWITCH DATE_BUFF LABEL BYTE DB 7 ;AN000; TYPE RETURNED (DATE) DB 0FFh ;AN000; MATCHED ITEM TAG DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:) DATE_YEAR DW 0 ;AN000; YEAR PUBLIC DATE_YEAR DATE_MONTH DB 0 ;AN000; MONTH PUBLIC DATE_MONTH DATE_DAY DB 0 ;AN000; DAY PUBLIC DATE_DAY ; = = = = = = = = = = = = DSEG_INIT ENDS HEADER ; $SALUT (4,14,19,36) CSEG SEGMENT PUBLIC ASSUME CS:CSEG, DS:DGROUP, ES:DGROUP PUBLIC SYSPARSE ;AN000;SUBROUTINE ENTRY POINT ;AN000; IF1 %OUT COMPONENT=XCOPY, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM... ENDIF INCSW EQU 0 ;AN018;TELL PARSE.ASM PSDATA.INC IS INCLUDED BASESW EQU 1 ;AN018;PSDATA.INC IS ADDRESSABLE WITH DS ; INCLUDE PARSE.ASM ;AN000;GENERATED CODE SUPPRESSED FROM LISTING .XLIST .XCREF INCLUDE PARSE.ASM .LIST .CREF EXTRN GET_PARMS:NEAR ;AN000;COMMAND LINE PARMS AND OPTIONS PROCESSING HEADER ; $SALUT (4,4,9,36) PARSER PROC NEAR PUBLIC PARSER ;INPUT: CURRENT_PARM = OFFSET TO NEXT PARM IN COMMAND STRING ; COMMAND_LINE = COPY OF DOS COMMAND LINE PARAMETERS ; "ORDINAL" = COUNT OF NEXT PARM TO PARSE ;OUTPUT: CARRY IS SET IF THERE WAS A PROBLEM, AX HAS PARSE RET CODE. ; CARRY IS CLEAR IF ALL OK WITH THE PARMS ;THE PSP IS NOT REFERENCED, SINCE THE PARMS HAVE BEEN MOVED OUT OF THERE. MOV ORDINAL,ZERO ;AN000;OPERAND ORDINAL, INITALLY ZERO ; $SEARCH COMPLEX ;AN000;LOOP THRU COMMAND LINE JMP SHORT $$SS1 $$DO1: ;AN000;LOOKING AT RETURN CODE IN AX, ;AN000; JUST PRODUCED BY SYSPARSE... CMP AX,ZERO ;AN000;WERE THERE ANY ERRORS? ; $EXITIF NE,OR ;AN000;HAD A PROBLEM JNE $$LL2 MOV ORDINAL,CX ;AN000;SAVE UPDATED COUNT MOV CURRENT_PARM,SI ;AN000;REMEMBER HOW FAR I GOT MOV BX,DX ;AN000;SET DATA BASE REG TO POINT TO THIS OPERAND CALL GET_PARMS ;AN000;GET 1ST AND 2ND PARAMETERS TEST PARM_FLAG,INIT_ERROR_FLAG ;AN000;CRITICAL PARAMETER ERROR HAS OCCURRED ; $EXITIF NZ ;AN000;HAD A PROBLEM JZ $$IF1 $$LL2: STC ;AN000;SET CARRY TO INDICATE ERROR CALL PARM_ERROR ;AN000;GET OUT WITH ERROR INFORMATION ;AN000;EITHER PARAMETER OR PARSER ERROR PROCESSED ; $ORELSE ;AN000;SINCE NO PROBLEM, SO FAR JMP SHORT $$SR1 $$IF1: ; $STRTSRCH $$SS1: LEA DI,PARMS ;AN000; ES:DI = PARSE CONTROL DEFINITON MOV SI,CURRENT_PARM ;AN000; DS:SI = COMMAND STRING, NEXT PARM XOR DX,DX ;AN000; RESERVED, INIT TO ZERO MOV CX,ORDINAL ;AN000; OPERAND ORDINAL, INITIALLY ZERO CALL SYSPARSE ;AN000; AX=EXIT CODE ;AN000; BL=TERMINATED DELIMITER CODE ;AN000; CX=NEW OPERAND ORDINAL ;AN000; SI=SET TO PAST SCANNED OPERAND ;AN000; DX=SELECTED RESULT BUFFER CMP AX,SYSPRM_EX_EOL ;AN000; IS THAT THE END OF THE PARMS? ;AN000;IF NOT, LOOP BACK AND FIND OUT ;AN000; WHAT THAT PARM IS ; $ENDLOOP E ;AN000;END OF LIST JNE $$DO1 CLC ;AN000;CLEAR CARRY, END OF LIST OK ; $ENDSRCH $$SR1: RET ;AN000;RETURN TO CALLER PARSER ENDP ; = = = = = = = = = = = = HEADER PARM_ERROR PROC NEAR ;INPUT: DX - ADDRESS OF MESSAGE TEXT ; PARM_FLAG set to INIT_ERROR_FLAG (critical error) ; OR THERE WAS A PARSER ERROR RET ;AN000;RETURN TO CALLER WITH C SET PARM_ERROR ENDP ; = = = = = = = = = = = = CSEG ENDS END