2 TITLE COMPPAR
.SAL - LOOK
AT COMMAND LINE PARMS
3 ;****************** START OF SPECIFICATIONS *****************************
4 ; MODULE NAME: COMPPAR.SAL
6 ; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters
7 ; and the interface to the DOS system PARSER.
9 ;FUNCTION: The static data areas are prescribed by the DOS system PARSER
10 ; to define the several parameters presented to COMP. These
11 ; data areas are passed to the PARSER, and its responses checked
12 ; to determine the nature of the user's specifications. Any errors
13 ; found in the user's parameters are defined in messages back
16 ; ENTRY POINT: PARSER, near
18 ; INPUT: (DOS COMMAND LINE PARAMETERS)
20 ; [d:][path] COMP [d:][path][filenam1[.ext]] [d:][path][filenam2[.ext]]
23 ; [d:][path] before COMP to specify the drive and path that
24 ; contains the COMP command file.
26 ; [d:][path][filenam1[.ext]] - to specify the FIRST (or primary)
27 ; file or group of files to be compared
29 ; [d:][path][filenam2[.ext]] - to specify the SECOND file or group
30 ; of files to be compared with the corresponding file
31 ; from the FIRST group
33 ; Global filename characters are allowed in both filenames,
34 ; and will cause all of the files matching the first filename
35 ; to be compared with the corresponding files from the second
36 ; filename. Thus, entering COMP A:*.ASM B:*.BAK will cause
37 ; each file from drive A: that has an extension of .ASM to be
38 ; compared with a file of the same name (but with an extension
39 ; of .BAK) from drive B:.
41 ; If you enter only a drive specification, COMP will assume
42 ; all files in the current directory of the specified drive.
43 ; If you enter a path without a filename, COMP assumes all
44 ; files in the specified directory. Thus, COMP A:\LEVEL1
45 ; B:\LEVEL2 will compare all files in directory A:\LEVEL1 with
46 ; the files of the same names in directory B:\LEVEL2.
48 ; If no parameters are entered with the COMP command, you will
49 ; be prompted for both. If the second parm is omitted, COMP
50 ; will prompt for it. If you simply press ENTER when prompted
51 ; for the second filename, COMP assumes *.* (all files
52 ; matching the primary filename), and will use the current
53 ; directory of the default drive.
55 ; If no file matches the primary filename, COMP will prompt
56 ; again for both parameters.
59 ; Upon entry to PARSER in this module,
60 ; "CURRENT_PARM" = offset to start of parm text in command string
61 ; "ORDINAL" = initialized to zero
62 ; PSP+81H = text of DOS command line parms string
64 ; EXIT-NORMAL: If a Code Page number was specified
65 ; BX = Offset to language table to be loaded
66 ; DX = Integer value of Code Page specified
67 ; If /STATUS (or /STA) was specified
69 ; If Question mark was specified
72 ; EXIT-ERROR: If there was any problem with the parms,
73 ; the question mark is assumed, and the appropriate
74 ; PARSE error message is displayed.
75 ; The Errorlevel code of "EXPAR" (3), meaning: "PARM ERROR",
76 ; set in "EXITFL", is requested to be returned to the user.
78 ; INTERNAL REFERENCES:
80 ; PARSE_ERROR:NEAR Display the appropriate Parse error message.
83 ; The several parameter control blocks, defined by the System
84 ; PARSER interface, defining the COMP parameters.
86 ; EXTERNAL REFERENCES:
88 ; SENDMSG:NEAR Uses Msg Descriptor to drive message handler.
89 ; SYSPARSE:NEAR System Command Line Common Parser.
92 ; EXITFL:BYTE Errorlevel return code.
93 ; MSGNUM_PARSE:WORD Message descriptor for all parse errors.
96 ; This module should be processed with the SALUT preprocessor
97 ; with the re-alignment not requested, as:
101 ; To assemble these modules, the alphabetical or sequential
102 ; ordering of segments may be used.
104 ; For LINK instructions, refer to the PROLOG of the main module,
108 ; A000 Version 4.0 : add PARSER, System Message Handler,
109 ; Add compare of extended attributes, if present.
111 ; COPYRIGHT: The following notice is found in the OBJ code generated from
112 ; the "COMPSM.SAL" module:
114 ; "The DOS COMP Utility"
115 ; "Version 4.0 (C) Copyright 1988 Microsoft"
116 ; "Licensed Material - Property of Microsoft"
118 ;PROGRAM AUTHOR: Edwin M. K.
120 ;****************** END OF SPECIFICATIONS *****************************
122 %
OUT COMPONENT
=COMP
, MODULE
=COMPPAR
.SAL... ;AN000;
124 ; = = = = = = = = = = = = ;AN000;
125 HEADER
MACRO TEXT
;;AN000;
131 ; = = = = = = = = = = = = ;AN000;
132 ; $SALUT (4,23,28,36) ;AN000;
134 INCLUDE COMPEQ
.INC ;AN000;
135 ; LOCAL EQUATES ;AN000;
136 MAX_PATH_LEN EQU
64 ;MAX CHAR IN A PATH ;AN000;
137 EXPAR EQU
1 ;RETURN TO DOS, INVALID DOS COMMAND LINE PARMS ;AN000;
138 ZERO_PARM_CT EQU
0 ;ORDINAL VALUE BEFORE FIRST PARM FOUND ;AN000;
139 FIRST_PARM_CT EQU
1 ;ORDINAL VALUE AFTER FIRST PARM FOUND ;AN000;
140 NUL EQU
0 ;ASCIIZ STRING DELIMITER ;AN000;
141 ; = = = = = = = = = = = = ;AN000;
142 ; EXIT CODES FROM SYSPARSE (WHEN CY=0) ;AN000;
144 SYSPRM_EX_OK EQU
0 ; no error ;AN000;
145 SYSPRM_EX_MANY EQU
1 ; too many operands ;AN000;
146 SYSPRM_EX_MISSING EQU
2 ; required operand missing ;AN000;
147 SYSPRM_EX_NOT_SWLIST EQU
3 ; not in switch list provided ;AN000;
148 SYSPRM_EX_NOT_KEYLIST EQU
4 ; not in keyword list provided ;AN000;
149 SYSPRM_EX_RANGE EQU
6 ; out of range specified ;AN000;
150 SYSPRM_EX_VALUE EQU
7 ; not in value list provided ;AN000;
151 SYSPRM_EX_STRING EQU
8 ; not in string list provided ;AN000;
152 SYSPRM_EX_SYNTAX EQU
9 ; syntax error ;AN000;
153 SYSPRM_EX_EOL EQU
-1 ; end of command line ;AN000;
154 ; = = = = = = = = = = = = ;AN000;
155 HEADER
<STRUC - DEFINITIONS OF EXTERNAL CONTROL BLOCKS
> ;AN000;
157 DB 80H
DUP (?
) ;SKIP OVER FIRST HALF OF PSP ;AN000;
158 PSP_PARMLEN
DB ?
;NUMBER OF BYTES IN DOS COMMAND LINE ;AN000;
159 PSP_COMMAND
DB 127 DUP(?
) ;TEXT OF DOS COMMAND LINE ;AN000;
161 ; = = = = = = = = = = = = ;AN000;
162 FILESPEC
STRUC ;AN000;
163 FS_DRIVE_ID
DB ?
;DRIVE LETTER ;AN000;
164 FS_COLON
DB ":" ;COLON SEPARATOR ;AN000;
165 FS_SLASH1
DB "\" ;LEADING BACKSLASH,START AT ROOT ;AN000;
166 FS_PATH DB MAX_PATH_LEN DUP (0) ;TEXT OF PATH ;AN000;
168 ;LOCATION OF REMAINING FIELDS DEPENDS ON LENGTH OF ACTUAL PATH ;AN000;
169 ;POSITIONS SHOWN ARE FOR MAX PATH LENGTH ONLY ;AN000;
171 FS_SLASH2 DB 0 ;TRAILING BACKSLASH ;AN000;
172 FS_FNAME DB 8 DUP (0) ;FILENAME ;AN000;
173 FS_PER DB 0 ;PERIOD END OF FILENAME ;AN000;
174 FS_EXT DB 3 DUP (0) ;FILENAME EXTENSION ;AN000;
175 FILESPEC ENDS ;AN000;
176 ; = = = = = = = = = = = = ;AN000;
177 HEADER <PARSING WORKAREAS> ;AN000;
178 ; $SALUT (4,14,19,36) ;AN000;
179 CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000;
180 ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000;
182 EXTRN SENDMSG:NEAR ;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR ;AN000;
183 EXTRN SYSPARSE:NEAR ;SYSTEM COMMAND LINE PARSER ;AN000;
185 EXTRN EXITFL:BYTE ;ERRORLEVEL RETURN CODE ;AN000;
186 EXTRN PATH1:BYTE ;FIRST POSITIONAL PARM ;AN000;
187 EXTRN PATH2:BYTE ;SECOND POSITIONAL PARM ;AN000;
188 EXTRN MSGNUM_PPARSE:WORD ;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS ;AN000;
189 EXTRN SUBLIST_24:WORD ;sublist for parse error messages ;AN000;
190 ; = = = = = = = = = = = = ;AN000;
192 CURRENT_PARM DW 81H ;POINTER INTO COMMAND OF NEXT OPERAND ;AN000;
193 PUBLIC CURRENT_PARM ;AN000;
195 ORDINAL DW 0 ;ORDINAL NUMBER OF WHICH PARM TO PARSE ;AN000;
196 PUBLIC ORDINAL ;AN000;
198 PARM_COUNT DW 00H ;CURRENT PARM COUNT (USED TO TRICK "PARSER
" ;AN000;
199 PUBLIC PARM_COUNT ;INTO PARSING FILE NAMES ENTERED FROM THE ;AN000;
200 ;KEYBOARD INSTEAD OF COMMAND LINE ;AN000;
201 ; = = = = = = = = = = = = ;AN000;
202 HEADER <DOS COMMAND LINE PARSER CONTROL BLOCKS> ;AN000;
204 ;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER ;AN000;
206 PUBLIC PARMS ;LET LINK MAKE PARMS BLOCK ADDRESSABLE ;AN000;
207 PARMS LABEL BYTE ;PARMS CONTROL BLOCK ;AN000;
208 DW PARMSX ;POINTER TO PARMS EXTENSION ;AN000;
209 DB 0 ; NUMBER OF STRINGS (0, 1, 2) ;AN000;
210 ; NEXT LIST WOULD BE EXTRA DELIM LIST ;AN000;
211 ; (,& WHITESPACE ALWAYS) ;AN000;
212 ; NEXT LIST WOULD BE EXTRA END OF LINE LIST ;AN000;
213 ; (CR,LF,0 ALWAYS) ;AN000;
215 ;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK ;AN000;
216 PARMSX LABEL BYTE ;PARMS EXTENSION CONTROL BLOCK ;AN000;
217 DB 0,2 ; MIN, MAX POSITIONAL OPERANDS ALLOWED ;AN000;
218 DW CONTROL_POS ; DESCRIPTION OF POSITIONAL 1 ;AN000;
219 DW CONTROL_POS ; DESCRIPTION OF POSITIONAL 2 ;AN000;
221 DB 0 ; MAX SWITCH OPERANDS ALLOWED ;AN000;
223 DB 0 ; MAX KEYWORD OPERANDS ALLOWED ;AN000;
224 ; THERE IS NO CONTROL BLOCK ;AN000;
225 ; DEFINING KEYWORDS ;AN000;
227 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000;
228 HEADER <POSITIONAL PARM DESCRIPTOR BLOCK> ;AN000;
229 ;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL ;AN000;
230 ;BOTH POSITIONAL PARAMETER ARE: ;AN000;
231 ; [d:][path][filename[.ext]] ;AN000;
233 PUBLIC CONTROL_POS ;LET LINK MAKE THIS ADDRESSABLE ;AN000;
234 CONTROL_POS LABEL BYTE ;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC, ;AN000;
236 DW 0201H ; CONTROLS TYPE MATCHED ;AN000;
237 ; SELECTED BITS: "FILESPEC
" AND "OPTIONAL
" ;AN000;
239 ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) ;AN000;
240 ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE ;AN000;
242 ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) ;AN000;
243 ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) ;AN000;
244 ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) ;AN000;
245 ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) ;AN000;
246 ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) ;AN000;
247 ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) ;AN000;
248 ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) ;AN000;
249 ; 0010H=IGNORE ":" AT END IN MATCH ;AN000;
250 ; 0002H=REPEATS ALLOWED ;AN000;
251 ; 0001H=OPTIONAL ;AN000;
253 DW 0001H ;FUNCTION_FLAGS ;AN000;
254 ; 0001H=CAP RESULT BY FILE TABLE ;AN000;
255 ; 0002H=CAP RESULT BY CHAR TABLE ;AN000;
256 ; 0010H=REMOVE ":" AT END ;AN000;
257 DW RESULT1 ; RESULT BUFFER ;AN000;
258 DW NOVALS ; VALUE LISTS ;AN000;
259 DB 0 ; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000;
260 ; IN FOLLOWING LIST ;AN000;
262 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000;
263 ;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER ;AN000;
264 RESULT1 LABEL BYTE ; BELOW FILLED IN FOR DEFAULTS ;AN000;
265 DB 5 ; TYPE RETURNED: 0=RESERVED, ;AN000;
266 ; 1=NUMBER, 2=LIST INDEX, ;AN000;
267 ; 3=STRING, 4=COMPLEX, ;AN000;
268 ; 5=FILESPEC, 6=DRIVE ;AN000;
269 ; 7=DATE, 8=TIME ;AN000;
270 ; 9=QUOTED STRING ;AN000;
271 RESULT_TAG DB 0FFH ; MATCHED ITEM TAG ;AN000;
272 DW 0 ;POINTER TO SYNONYM ;AN000;
274 RESULT_PTR1 DD ? ; OFFSET OF STRING VALUE ;AN000;
276 ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000;
277 ;VALUE CONTROL BLOCK ;AN000;
278 NOVALS LABEL BYTE ;AN000;
279 DB 0 ; NUMBER OF VALUE DEFINITIONS (0 - 3) ;AN000;
281 ; = = = = = = = = = = = = ;AN000;
282 HEADER <PARSER - ASK SYSPARM TO DECODE PARAMETERS> ;AN000;
283 ; $SALUT (4,4,9,36) ;AN000;
284 PARSER PROC NEAR ;AN000;
285 PUBLIC PARSER ;AN000;
287 ;INPUT: "CURRENT_PARM
" = OFFSET TO NEXT PARM IN COMMAND STRING ;AN000;
288 ; "ORDINAL
" = COUNT OF NEXT PARM TO PARSE ;AN000;
289 ; PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING ;AN000;
291 ;OUTPUT: IF SPECIFIED, FIRST PARM GOES TO "PATH1
". ;AN000;
292 ; IF SPECIFIED, SECOND PARM GOES TO "PATH2
". ;AN000;
293 ; IF EITHER PARM MISSING, THEN "PATHn
" STARTS WITH NUL CHAR. ;AN000;
294 ; CARRY SET IF ERROR. ;AN000;
295 ; = = = = = = = = = = = = ;AN000;
297 ; $SEARCH COMPLEX ;LOOP THRU COMMAND LINE ;AN000;
300 ;LOOKING AT RETURN CODE FROM SYSPARSE... ;AN000;
301 AND AX,AX ;AN008; ;WERE THERE ANY ERRORS? ;AN000;
302 ; $EXITIF NE ;HAD A PROBLEM ;AN000;
304 CALL PARSE_ERROR ;DISPLAY REASON FOR ERROR ;AN000;
305 MOV AL,01h ;AN000; ;pass back errorlevel ret code
308 ; $ORELSE ;SINCE NO PROBLEM, SO FAR ;AN000;
311 MOV ORDINAL,CX ;SAVE UPDATED COUNT ;AN000;
312 MOV CURRENT_PARM,SI ;REMEMBER HOW FAR I GOT ;AN000;
313 MOV BX,DX ;SET DATA BASE REG TO POINT TO ;AN000;
314 ;RESULT BUFFER OF THIS OPERAND ;AN000;
316 MOV SI,WORD PTR RESULT_PTR1 ;GET WHERE STRING IS PUT ;AN000;
317 ;GUESS, THIS IS THE FIRST PARM ;AN000;
318 MOV DI,OFFSET PATH1 ;GET WHERE STRING IS TO GO ;AN000;
320 ;IF PARSING FILENAME INPUTED FROM KEYBOARD ;AN000;
321 ;THEN PARM_COUNT MUST = ZERO_PARM_CT = 0 ;AN000;
322 CMP CX,PARM_COUNT ;IS THIS THE FIRST PARM OR JUST A FILENAME IN BUFFER ;AN000;
324 ; $IF NE ;NO, MUST BE THE SECOND PARM ;AN000;
326 ;MADE A BAD GUESS, FIX IT ;AN000;
327 MOV DI,OFFSET PATH2 ;CHANGE DEST TO WHERE SECOND STRING GOES ;AN000;
331 ;MOVE ASCIIZ STRING FROM DS:SI ;AN000;
332 ;WHERE COMMAND PARSE PUT IT ;AN000;
333 ;TO ES:DI WHERE COMP2 USES IT ;AN000;
335 ; $DO COMPLEX ;AN000;
338 STOSB ;PUT CHAR IN AL TO ES:DI ;AN000;
341 LODSB ;GET CHAR FROM DS:SI TO AL ;AN000;
342 CMP AL,NUL ;IS THAT THE END OF STRING? ;AN000;
343 ; $ENDDO E ;IF SO, QUIT ;AN000;
348 LEA DI,PARMS ;ES:DI = PARSE CONTROL DEFINITON ;AN000;
349 MOV SI,CURRENT_PARM ;DS:SI = COMMAND STRING, NEXT PARM ;AN000;
350 XOR DX,DX ;RESERVED, INIT TO ZERO ;AN000;
351 MOV CX,ORDINAL ;OPERAND ORDINAL, INITIALLY ZERO ;AN000;
352 CALL SYSPARSE ;LOOK AT DOS PARMS ;AN000;
353 ;AX=EXIT CODE ;AN000;
354 ;BL=TERMINATED DELIMETER CODE ;AN000;
355 ;CX=NEW OPERAND ORDINAL ;AN000;
356 ;SI=SET TO PAST SCANNED OPERAND ;AN000;
357 ;DX=SELECTED RESULT BUFFER ;AN000;
358 CMP AX,SYSPRM_EX_EOL ;IS THAT THE END OF THE PARMS? ;AN000;
359 ;IF NOT, LOOP BACK AND FIND OUT ;AN000;
360 ;WHAT THAT PARM IS ;AN000;
361 ; $ENDLOOP E ;END OF LIST ;AN000;
363 CLC ;RETURN FLAG FOR "NO ERROR
" ;AN000;
364 ; $ENDSRCH ;FINISHED WITH DOS COMMAND LINE ;AN000;
366 RET ;RETURN TO CALLER ;AN000;
368 ; = = = = = = = = = = = = ;AN000;
369 HEADER <PARSE_ERROR - DISPLAY REASON FOR PARSE ERROR> ;AN000;
370 PARSE_ERROR PROC NEAR ;AN000;
372 ;INPUT: "FIRST_TIME
" - IF NON-ZERO, FORCE ERROR CODE TO "TOO MANY PARMS
" ;AN000;
373 ; AX - ERROR NUMBER RETURNED FROM PARSE. ;AN000;
374 ;OUTPUT: APPROPRIATE ERROR MESSAGE IS DISPLAYED. ;AN000;
375 ; = = = = = = = = = = = = ;AN000;
377 MOV MSGNUM_PPARSE,AX ;PASS MESSAGE NUMBER TO DESCRIPTOR ;AN000;
378 MOV DX,OFFSET MSGNUM_PPARSE ;PASS MESSAGE DESCRIPTOR ;AN000;
379 MOV BX,CURRENT_PARM ;AN000;
381 CMP BX,SI ;are we past the point the parser stopped ? ;AN000;
382 JAE PE_BX_OK ;yes, we are done. ;AN000;
383 CMP BYTE PTR [BX],20H ;by-pass leading blanks ;AN000;
388 MOV SUBLIST_24.SUB_VALUE,BX ;AN000;
390 ;make a ASCIIZ string out of parameter
393 CMP BX,SI ;are we past the point the parser stopped ? ;AN000;
394 JAE PE_OK ;yes, we are done. ;AN000;
395 CMP BYTE PTR [BX],20H ;check for spaec or end of line ;AN000;
400 MOV byte ptr [BX],00H ;end string with zero ;AN000;
402 CALL SENDMSG ;DISPLAY ERROR MESSAGE ;AN000;
404 MOV EXITFL,EXPAR ;ERRORLEVEL CODE TO "PARM ERROR
" ;AN000;
405 RET ;RETURN TO CALLER ;AN000;
406 PARSE_ERROR ENDP ;AN000; ;AN000;
407 ; = = = = = = = = = = = = ;AN000;