summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/XCOPY/XCPYINIT.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/XCOPY/XCPYINIT.ASM')
-rw-r--r--v4.0/src/CMD/XCOPY/XCPYINIT.ASM1890
1 files changed, 1890 insertions, 0 deletions
diff --git a/v4.0/src/CMD/XCOPY/XCPYINIT.ASM b/v4.0/src/CMD/XCOPY/XCPYINIT.ASM
new file mode 100644
index 0000000..33559ef
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCPYINIT.ASM
@@ -0,0 +1,1890 @@
1 PAGE ,132 ;
2TITLE XCPYINIT - XCOPY INITIALIZATION PROGRAM - Ver. 4.00
3
4;****************** START OF SPECIFICATIONS *****************************
5; MODULE NAME: XCPYINIT
6;
7; DESCRIPTIVE NAME: Called by XCOPY(MAIN) to perform initialization
8; functions.
9;
10; FUNCTION: Performs Parsing, Resource validation and Tagging, Error
11; hooking and then returns to XCOPY(MAIN). This code will
12; then be overwritten, providing additional memory for the
13; copy process.
14;
15; ENTRY POINT: INIT
16;
17; INPUT: (DOS COMMAND LINE PARAMETERS)
18;
19; SOURCE OPERAND: TARGET OPERAND:
20;
21; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
22; or
23; [d:] path [filename[.ext]]
24; or
25; d: [path] [filename[.ext]]
26;
27; SWITCHES:
28;
29; /A /D /E /M /P /S /V /W
30;
31; EXIT-NORMAL: ERRORLEVEL_0 - This is the normal completion code.
32; ERRORLEVEL_2 - This is due to termination via Control-Break.
33; ERRORLEVEL_4 - This is used to indicate an error condition.
34;
35; INTERNAL REFERENCES:
36;
37; ROUTINES:
38;
39; DATA AREAS:
40;
41;
42; EXTERNAL REFERENCES:
43;
44; ROUTINES:
45;
46; DATA AREAS:
47;
48;
49; NOTES: This module should be processed with the SALUT pre-processor
50; with the re-alignment not requested, as:
51;
52; SALUT XCOPY,NUL,;
53;
54; To assemble these modules, the sequential
55; ordering of segments may be used.
56;
57; For LINK instructions:
58; link profile ..\lib
59;
60; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
61; Remove the BELL char.,turn off APPEND during TREE
62; search,Extended Attribute processing, Uppercasing
63; and "Out Of Space" during write to standard out.
64; NOTE: SEE XCOPY.SAL FOR TOTAL HISTORY.
65;
66; Label: "The DOS XCOPY Utility"
67; "Version 4.00 (C) Copyright 1988 Microsoft"
68; "Licensed Material - Program Property of Microsoft"
69;
70;****************** END OF SPECIFICATIONS *****************************
71;EQUATES
72INCLUDE XCOPY.EQU
73INCLUDE DOS.EQU
74include versiona.inc
75
76;
77CSEG SEGMENT PUBLIC ;PLACE HOLDER FOR INIT CODE
78CSEG ENDS
79
80;******************************************************************************
81
82DGROUP GROUP DSEG, DSEG_INIT
83DSEG SEGMENT PARA PUBLIC
84;--- EXTERNAL VARIABLES ---
85EXTRN ERRORLEVEL:BYTE
86EXTRN PSP_SEG:WORD ;PSP segment ** USE OF ES SHOULD BE EXAMINED FURTHER
87EXTRN SAV_DEFAULT_DRV:BYTE ;1 = A, 2 = B ...
88EXTRN SAV_DEFAULT_DIR:BYTE
89EXTRN SAV_S_DRV:BYTE
90EXTRN SAV_S_CURDIR:BYTE
91EXTRN SAV_T_DRV:BYTE
92EXTRN SAV_T_CURDIR:BYTE
93EXTRN TOP_OF_MEMORY:WORD
94EXTRN S_DRV_NUMBER:BYTE ;source drive number, 1 = A, 2 = B ...
95EXTRN T_DRV_NUMBER:BYTE ;target drive number
96EXTRN SO_DRIVE:BYTE ;AN000;S DRIVE LETTER SPECIFIED IN PARSE
97EXTRN S_DRV:BYTE
98EXTRN S_DRV_1:BYTE
99EXTRN S_DRV_PATH:BYTE ;formal source drv, path
100EXTRN S_PATH:BYTE
101EXTRN T_DRV_PATH:BYTE ;formal target drv, path
102EXTRN T_PATH:BYTE
103EXTRN TAR_DRIVE:BYTE ;AN000;T DRIVE LETTER SPECIFIED IN PARSE
104EXTRN PARMS:DWORD ;AN000;PARSER PARAMETER CONTROL BLOCK
105EXTRN CURRENT_PARM:WORD ;AN004;POINTER TO NEXT CMD LINE OPERAND
106EXTRN T_DRV:BYTE ;target drv letter
107EXTRN T_DRV_1:BYTE ;target drv letter
108EXTRN T_DRV_2:BYTE
109EXTRN S_FILE:BYTE ;source filename
110EXTRN T_FILENAME:BYTE
111EXTRN T_TEMPLATE:BYTE
112EXTRN DISP_S_PATH:BYTE ;input mirror image source path
113EXTRN DISP_T_PATH:BYTE ;input mirror image target path
114EXTRN BUFFER_PTR:WORD
115EXTRN BUFFER_BASE:WORD
116EXTRN BUFFER_LEFT:WORD
117EXTRN MAX_BUFFER_SIZE:WORD
118EXTRN MAX_CX:WORD
119EXTRN S_ARC_DRV:BYTE ;source drv, path for archieve bit handling
120EXTRN S_ARC_PATH:BYTE
121EXTRN T_MKDIR_LVL:BYTE ;# of target starting directories created.
122EXTRN MSG_NUM:WORD ;AN000;MESSAGE NUMBER
123EXTRN MSG_CLASS:BYTE ;AN000;MESSAGE CLASS
124EXTRN INPUT_FLAG:BYTE ;AN000;TYPE INT21 USED FOR KBD INPUT
125EXTRN SUBST_COUNT:WORD ;AN000;MESSAGE SUBSTITUTION COUNT
126EXTRN SUBLIST1:DWORD ;AN000;MSG SUBLIST USED BY INIT & MAIN
127;
128EXTRN MY_FLAG:BYTE
129EXTRN SYS_FLAG:BYTE
130EXTRN COPY_STATUS:BYTE
131EXTRN OPTION_FLAG:BYTE
132;
133EXTRN INPUT_DATE:WORD
134EXTRN INPUT_TIME:WORD
135;
136;
137DSEG ENDS
138;
139DSEG_INIT SEGMENT PARA PUBLIC ;AN000;
140;--- Local variables for INIT which will be free into memory after init.
141;----include file(s)------
142INCLUDE XINITMSG.EQU ;AN000;xcopy initialization, prompt msg
143;----variables------------
144S_INPUT_PARM DB 80 DUP (0) ;source image of input parm
145T_INPUT_PARM DB 80 DUP (0) ;target image of input parm
146T_TRANS_PATH DB 128 DUP (0) ;AN016;TARGET BUFFER FOR NAME TRANSLATE
147S_TRANS_PATH DB 128 DUP (0) ;AN016;SOURCE BUFFER FOR NAME TRANSLATE
148
149PUBLIC PARM_FLAG
150PARM_FLAG DB 0
151; first_parm_flag equ 01h ;first parm entered in input parm
152; second_parm_flag equ 02h ;second parm entered.
153; end_of_parm_flag equ 04h ;end of parm reached
154; copy_onto_itself_flag equ 08h ;copy onto itself flag
155; cyclic_flag equ 10h ;cyclic copy flag
156; inv_time_flag equ 20h ;invalid time
157; inv_date_flag equ 40h ;invalid date
158; init_error_flag equ 80h ;critical initialization error. Should abort.
159
160PARM1_FLAG DB 0
161; inv_s_path_flag equ 01h ;invalid source path (path not found)
162; inv_t_path_flag equ 02h ;invalid target path
163; s_file_flag equ 04h ;source filename entered
164; t_file_flag equ 08h ;target filename entered
165; INV_SW_flag equ 10h ;AN004;DUPLICATE OR INVALID SW ENTERED
166;
167TEMP_T_FILENAME DB 15 DUP (0) ;temporary target filename holder
168FILENAME_FOR_PROMPT DB 15 DUP (0) ;upper case lettered TEMP_T_FILENAME for prompts
169;** The following definitions are used for "Does ... specify a file name
170;** or directory name (F:file, D:directory)?.
171ALPHA_FILE DW ? ;AN000;THIS IS THE TRANSLATION OF 'F'
172ALPHA_DIR DW ? ;AN000;THIS IS THE TRANSLATION OF 'D'
173USER_INPUT DW ? ;AC000;KEYBOARD SAVE - MAY BE DBCS -
174
175Maxdays db 31,28,31,30,31,30,31,31,30,31,30,31 ;Max days per month
176Day db ? ;
177Month db ? ;
178Year dw ? ;
179Parmdate dw ? ;date parameter used in file date
180;
181COUNTRY_INFO DB 34 DUP (0)
182;-------------------------------
183; Structures
184;-------------------------------
185
186SUB_LIST STRUC ;AN000;MSG RETRIEVER SUBSTITUTION LST
187 DB 11 ;AN000;
188 DB 0 ;AN000;
189DATA_OFF DW 0 ;AN000; offset of data to be inserted
190DATA_SEG DW 0 ;AN000; offset of data to be inserted
191MSG_ID DB 0 ;AN000; n of %n
192FLAGS DB 0 ;AN000; Flags
193MAX_WIDTH DB 0 ;AN000; Maximum field width
194MIN_WIDTH DB 0 ;AN000; Minimum field width
195PAD_CHAR DB 0 ;AN000; character for pad field
196
197SUB_LIST ENDS ;AN000;
198
199DSEG_INIT ENDS
200;*******************************************************************************
201
202CSEG SEGMENT PUBLIC ;ATTACHED TO MAIN PROGRAM
203 ASSUME CS:CSEG, DS:DGROUP, ES:DGROUP
204;
205;--- PUBLIC PROCEDURES --- ;USED BY PARSER
206PUBLIC GET_PARMS ;AN000;
207;---------------------------
208
209;--- EXTERNAL PROCEDURES ---
210EXTRN SET_BUFFER_PTR:NEAR
211EXTRN STRING_LENGTH:NEAR
212EXTRN CONCAT_ASCIIZ:NEAR
213EXTRN LAST_DIR_OUT:NEAR
214EXTRN CHK_DBCS:NEAR ;AN010;NEEDED TO PARSE THE PATH STRING
215EXTRN COMPRESS_FILENAME:NEAR
216EXTRN CHK_DRV_LETTER:NEAR
217EXTRN SET_DEFAULT_DRV:NEAR
218EXTRN PRINT_STDOUT:NEAR
219EXTRN PRINT_STDERR:NEAR
220EXTRN MAIN_EXIT:NEAR
221EXTRN MAIN_EXIT_A:NEAR
222EXTRN CTRL_BREAK_EXIT:NEAR
223EXTRN PARSER:NEAR ;AN000;PROCESS THE KBD INPUT STRING
224EXTRN SYSGETMSG:NEAR ;AN000;TO GET THE 'F'ILE or 'D'IRECTORY
225EXTRN MY_INT24:WORD
226;---
227EXTRN SAV_INT24_OFF:WORD ;int 24, critical error handler addr.
228EXTRN SAV_INT24_SEG:WORD
229;
230;--- PARSER REFERENCES ---
231;
232EXTRN RESULT1:BYTE ;AN000;
233EXTRN RESULT_PTR1:DWORD ;AN000;
234EXTRN TYPE1:BYTE ;AN000;
235EXTRN RESULT2:BYTE ;AN000;
236EXTRN RESULT_PTR2:DWORD ;AN000;
237EXTRN TYPE2:BYTE ;AN000;
238EXTRN RESULTSW1:BYTE ;AN000;
239EXTRN RESULTSWSYN:WORD ;AN000;
240EXTRN SW_A:BYTE ;AN000;
241EXTRN SW_E:BYTE ;AN000;
242EXTRN SW_M:BYTE ;AN000;
243EXTRN SW_P:BYTE ;AN000;
244EXTRN SW_S:BYTE ;AN000;
245EXTRN SW_V:BYTE ;AN000;
246EXTRN SW_W:BYTE ;AN000;
247EXTRN SW_D:BYTE ;AN000;
248EXTRN DATE_YEAR:WORD ;AN000;
249EXTRN DATE_MONTH:BYTE ;AN000;
250EXTRN DATE_DAY:BYTE ;AN000;
251;---
252
253PUBLIC INIT
254INIT PROC NEAR
255 CMP AX, 0 ;check drv validity
256; $IF NE
257 JE $$IF1
258 MOV DX, MSG_INVALID_DRV ;AC000;GET THE MESSAGE ID
259 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error. Abort
260; $ELSE
261 JMP SHORT $$EN1
262$$IF1:
263 CALL HOOK_CTRL_BREAK ;hooks control break
264 CALL SAV_HOOK_INT24 ;hooks critical err handler
265 CALL GET_CUR_DRV ;save current default drv
266 MOV DL, SAV_DEFAULT_DRV
267 LEA SI, SAV_DEFAULT_DIR
268 CALL GET_CUR_DIR ;save current default dir
269 CALL PARSE_INPUT_PARM
270 TEST PARM_FLAG, INIT_ERROR_FLAG
271; $IF Z ;no error
272 JNZ $$IF3
273 CALL TOP_OF_MEM ;set top_of_memory
274 CALL INIT_BUFFER ;init buffer information
275
276 MOV DL, S_DRV_NUMBER
277 DEC DL
278 CALL SET_DEFAULT_DRV ;set source as a default drv
279; $ENDIF
280$$IF3:
281; $ENDIF
282$$EN1:
283 TEST PARM_FLAG, INIT_ERROR_FLAG ;any error?
284; $IF NZ ;yes. critical error
285 JZ $$IF6
286 CMP DX,MSG_INV_SW ;AN004;MSG REQUIRES SUB LIST
287; $IF NE,AND ;AC023;NO SUBLIST REQUIRED
288 JE $$IF7
289 CMP DX,MSG_INVALID_PARM ;AN004;MSG REQUIRES SUB LIST
290; $IF NE,AND ;AC023;NO SUBLIST REQUIRED
291 JE $$IF7
292 CMP DX,MSG_INV_NUM_PARM ;AN004;MSG REQUIRES SUB LIST
293; $IF NE ;AC023;NO SUBLIST REQUIRED
294 JE $$IF7
295 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
296 CMP DX,SYSPRM_MISSING_OP ;AN024;OPERANDS MISSING(2) ERR?
297; $IF E ;AN024;
298 JNE $$IF8
299 MOV DX,MSG_INV_NUM_PARM ;AN024;NO SUBLIST REQUIRED
300; $ENDIF ;AN024;
301$$IF8:
302 MOV MSG_NUM,DX ;AN000;NEED MESSAGE ID FOR PRINT
303; $ELSE ;AN004;SUBST LIST REQUIRED
304 JMP SHORT $$EN7
305$$IF7:
306 MOV MSG_NUM,DX ;AN004;NEED MESSAGE ID FOR PRINT
307 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN004;PARM SUBST COUNT=1
308;
309 MOV DX,CURRENT_PARM ;AN004;OFFSET TO BAD SWITCH
310 LEA SI,SUBLIST1 ;AN004; address to sublist
311 MOV [SI].DATA_OFF,DX ;AN004; save data offset
312 MOV [SI].DATA_SEG,DS ;AN004; save data segment
313 MOV [SI].MSG_ID,0 ;AN023; message ID
314 MOV [SI].FLAGS,010H ;AN004; ASCIIZ str,l align
315 MOV [SI].MAX_WIDTH,0 ;AN004; MAXIMUM FIELD WITH
316 MOV [SI].MIN_WIDTH,0 ;AN004; MINIMUM FIELD WITH
317; $ENDIF ;AN004;
318$$EN7:
319 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
320 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
321 CALL PRINT_STDERR ;AN000;print error. AX point to msg ID
322 MOV ERRORLEVEL, 4 ;error ending
323 STC ;set carry and exit to the main_exit
324; $ELSE
325 JMP SHORT $$EN6
326$$IF6:
327 CLC
328; $ENDIF
329$$EN6:
330 RET
331INIT ENDP
332
333;
334PARSE_INPUT_PARM PROC NEAR
335;
336 CALL PARSER ;AN000;the PARSER interface routine
337; $IF C ;AC000;if no non_delimiter chr?
338 JNC $$IF14
339 TEST PARM_FLAG,INIT_ERROR_FLAG ;AN000;PARM ERR HAS OCCURRED
340; $IF Z ;AN000;NO, MUST BE PARSER ERROR
341 JNZ $$IF15
342 OR PARM_FLAG,INIT_ERROR_FLAG ;AN000;SET THE FLAG
343 CMP AX,SYSPRM_EX_MANY ;AN000;TOO MANY OPERANDS (1) ERR?
344; $IF E ;AN000;
345 JNE $$IF16
346 MOV BYTE PTR [SI],NUL ;AN024;DELIMIT BAD PARM
347 MOV DX,MSG_INV_NUM_PARM ;AN000;MSG NUM = 21
348; $ELSE ;AN000;
349 JMP SHORT $$EN16
350$$IF16:
351 CMP AX,SYSPRM_DUP_SW ;AN004;DUPLICATE SW REQUESTED
352; $IF E ;AN004;
353 JNE $$IF18
354 MOV BYTE PTR [SI],NUL ;AN004;DELIMIT BAD PARM
355 MOV DX,MSG_INV_SW ;AN004;MSG NUM = 35
356; $ELSE ;AN004;
357 JMP SHORT $$EN18
358$$IF18:
359 CMP AX,SYSPRM_MISSING_OP ;AN006;MISSING PARM=2
360; $IF E ;AN006;
361 JNE $$IF20
362 MOV DX,AX ;AN024 ;MSG NUM=21-NO SUBLIST
363; $ELSE ;AN006;
364 JMP SHORT $$EN20
365$$IF20:
366 MOV BYTE PTR [SI],NUL ;AN024;DELIMIT BAD PARM
367 MOV DX,MSG_INVALID_PARM ;AN000;MSG NUM = 3
368; $ENDIF ;AN006;
369$$EN20:
370; $ENDIF ;AN004;
371$$EN18:
372; $ENDIF ;AN000;
373$$EN16:
374; $ELSE ;AN006;INIT_ERROR_FLAG ALSO SET
375 JMP SHORT $$EN15
376$$IF15:
377 TEST PARM_FLAG,INV_DATE_FLAG ;AN006;WAS DATE INVALID?
378; $IF NZ ;AN006;THE DATE IS INVALID
379 JZ $$IF26
380 MOV DX,MSG_INVALID_DATE ;AN006;MSG NUM = 9
381; $ENDIF ;AN006;
382$$IF26:
383; $ENDIF ;AN000;
384$$EN15:
385; $ELSE ;AN000;
386 JMP SHORT $$EN14
387$$IF14:
388 CALL GET_DRIVES ;get source, target drive
389 TEST PARM_FLAG, INIT_ERROR_FLAG ;critical syntax error?
390; $IF Z ;if not,
391 JNZ $$IF30
392 CALL CHK_SLASH_W ;with /w, show "Press any key to begin ... " msg.
393 call save_for_display ;save source, target parm for display purposes
394 CALL CHK_SET_PARMS ;check and set each parms.
395 TEST PARM_FLAG, INIT_ERROR_FLAG ;critical syntax error?
396; $IF Z ;no
397 JNZ $$IF31
398 call modify_for_display ;set the source, target parm for display
399; $ENDIF
400$$IF31:
401; $ENDIF
402$$IF30:
403; $ENDIF
404$$EN14:
405 MOV AL, 0
406 LEA DI, S_PATH
407 CALL STRING_LENGTH ;cx - # of chr
408 LEA SI, S_PATH
409 LEA DI, S_ARC_PATH
410 REP MOVSB ;s_path => s_arc_path
411 RET
412PARSE_INPUT_PARM ENDP
413;
414
415CHK_SLASH_W PROC NEAR
416;if /W option is specified, then
417;show "Press any key to begin copying file(z)" message and wait for a key stroke.
418
419
420 TEST OPTION_FLAG, SLASH_W ;/W option taken?
421; $IF NZ ;yes.
422 JZ $$IF35
423 PUSH AX ;AN000;
424 MOV AX, MSG_TO_BEGIN ;AC000;GET THE MESSAGE ID
425 MOV MSG_NUM,AX ;AN000;SET THE MESSAGE NUMBER
426 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
427 MOV INPUT_FLAG,DOS_KEYB_INP ;AN000;RESPONSE EXPECTED = 1
428 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
429 CALL PRINT_STDOUT ;AN000;MSG AX points to message ID
430
431 MOV AX,MSG_CR_LF_STR ;AN000; JUST CR,LF
432 MOV MSG_NUM,AX ;AN000; set message number
433 MOV INPUT_FLAG,NO_INPUT ;AN000; NO INPUT
434 CALL PRINT_STDOUT ;AN000; Display message
435
436 POP AX ;AN000;
437; $ENDIF
438$$IF35:
439 RET
440
441CHK_SLASH_W ENDP
442;
443PROMPT_TO_USER PROC NEAR
444;guide the user to enter the input parameters
445;get user input to S_INPUT_PARM, T_INPUT_PARM for source, target parms.
446;INPUT: ES - PSP seg
447; DS - data seg
448; SAV_DEFAULT_DRV
449;
450 MOV dx, msg_inv_num_parm ;AC000;GET THE MESSAGE ID
451 or parm_flag, init_error_flag
452 RET
453PROMPT_TO_USER ENDP
454;
455GET_PARMS PROC NEAR
456;Get the first parameter(s), second parameter(s) and option(s).
457;Not checking correct character entered.
458;The logic is:
459;1). Find the first non_delim from the Parser control block. This is the
460; start of the first parm. Validate the length and put into S_INPUT_PARM.
461; Note that this routine currently does not check the S_INPUT_PARM to see
462; if it is valid or not.
463;2). Find the next non_delim from the Parser control block. This is the
464; start of the second parm. Validate the length and put into T_INPUT_PARM.
465; Note that this routine currently does not check the T_INPUT_PARM to see
466; if it is valid or not.
467;3). Find the switch(es) from the parser control block and set the
468; corresponding bit in the option flag word(OPTION_FLAG) by calling
469; GET_OPTIONS.
470;
471;INPUT:
472; BX - PARSER OPERAND POINTER
473
474 PUSH DS ;AN000;
475 CMP BX,OFFSET DGROUP:RESULT1 ;AN000;WAS FIRST FILESPEC SPECIFIED?
476; $IF E ;AN000;IF FIRST FILESPEC SPECIFIED,
477 JNE $$IF37
478 LDS SI,RESULT_PTR1 ;AN000;GET WHERE THE STRING IS
479 ASSUME DS:NOTHING ;AN000;
480 CMP DS:BYTE PTR [SI]+BYTE,COLON ;AN000;DOES FILESPEC START WITH
481 ;DRIVE?
482; $IF E ;AN000;STARTS WITH DRIVE
483 JNE $$IF38
484 LODSW ;AN000;GET JUST THE DRIVE LETTER AND
485 MOV ES:SO_DRIVE,AL ;AN000;ALSO ADJUSTS WHERE THE STRING IS
486 LEA DI,ES:S_INPUT_PARM ;AN000;MOVE PARM TO SOURCE FILESPEC
487 STOSW ;AN000;MOVE DRIVE TO FILESPEC
488; $ELSE ;AN000;DOES NOT START WITH DRIVE
489 JMP SHORT $$EN38
490$$IF38:
491 LEA DI,ES:S_INPUT_PARM ;AN000;MOVE PARM TO SOURCE FILESPEC
492; $ENDIF ;AN000;FILESPEC HAVE DRIVE?
493$$EN38:
494 CMP DGROUP:TYPE1,5 ;AN000;FILESPEC ?
495; $IF E ;AN000;MORE THAN JUST DRIVE
496 JNE $$IF41
497 ;MOVE PARM TO WHERE FIND FIRST/NEXT
498 ; WILL KNOW WHERE TO START
499 PUSH BX ;AN000;SAVE THE DATABASE POINTER
500 XOR BX,BX ;AN000;ZERO FOR THE PARAMETER LENGTH
501; $DO COMPLEX ;AN000;
502 JMP SHORT $$SD42
503$$DO42:
504 INC BX ;AN000;CALCULATE LENGTH
505 STOSB ;AN000;MOVE CHAR TO FILESPEC
506; $STRTDO ;AN000;
507$$SD42:
508 LODSB ;AN000;GET NEXT CHAR FROM COMMAND LINE
509 CMP AL,NUL ;AN000;IS THAT THE END OF THE STRING
510; $ENDDO E ;AN000;GOT IT ALL, QUIT
511 JNE $$DO42
512 CALL CHK_MAX_LENGTH ;AN000;LENGTH OF STRING <=64
513 POP BX ;AN000;RESTORE THE DATA BASE POINTER
514; $IF NC ;no, less than or equal
515 JC $$IF45
516 OR PARM_FLAG, FIRST_PARM_FLAG
517; $ELSE ;AN000;
518 JMP SHORT $$EN45
519$$IF45:
520 MOV DX, MSG_LONG_PATH ;AN000;ADDRESS OF MESSAGE TXT
521 OR PARM_FLAG, INIT_ERROR_FLAG ;AN000;
522; $ENDIF ;AN000;CRITICAL ERROR INDICATED
523$$EN45:
524; $ENDIF ;AN000;MOVE ALL DONE
525$$IF41:
526; $ELSE ;AN000;IF SECOND FILESPEC SPECIFIED,
527 JMP SHORT $$EN37
528$$IF37:
529 CMP BX,OFFSET DGROUP:RESULT2 ;AN000;WAS 2nd FILESPEC SPECIFIED?
530; $IF E ;AN000;IF SECOND FILESPEC SPECIFIED
531 JNE $$IF50
532 LDS SI,RESULT_PTR2 ;AN000;GET WHERE THE STRING IS
533 ASSUME DS:NOTHING ;AN000;
534 CMP DS:BYTE PTR [SI]+BYTE,COLON ;AN000;DOES FILESPEC START
535 ;WITH DRIVE?
536; $IF E ;AN000;STARTS WITH DRIVE
537 JNE $$IF51
538 LODSW ;AN000;GET JUST THE DRIVE LETTER AND
539 MOV ES:TAR_DRIVE,AL ;AN000;ALSO ADJUSTS WHERE THE STRING IS
540 LEA DI,ES:T_INPUT_PARM ;AN000;MOVE PARM TO TARGET FILESPEC
541 STOSW ;AN000;MOVE DRIVE TO FILESPEC
542; $ELSE ;AN000;DOES NOT START WITH DRIVE
543 JMP SHORT $$EN51
544$$IF51:
545 LEA DI,ES:T_INPUT_PARM ;AN000;MOVE PARM TO TARGET FILESPEC
546; $ENDIF ;AN000;FILESPEC HAVE DRIVE?
547$$EN51:
548 CMP DGROUP:TYPE2,5 ;AN000;FILESPEC ?
549; $IF E ;AN000;MORE THAN JUST DRIVE
550 JNE $$IF54
551 ;AN000;MOVE PARM TO WHERE FIND FIRST/NEXT
552 ;AN000; WILL KNOW WHERE TO START
553 PUSH BX ;AN000;SAVE THE DATABASE POINTER
554 XOR BX,BX ;AN000;ZERO FOR THE PARAMETER LENGTH
555; $DO COMPLEX ;AN000;
556 JMP SHORT $$SD55
557$$DO55:
558 INC BX ;AN000;CALCULATE LENGTH
559 STOSB ;AN000;MOVE CHAR TO FILESPEC
560; $STRTDO ;AN000;
561$$SD55:
562 LODSB ;AN000;GET NEXT CHAR FROM COMMAND LINE
563 CMP AL,NUL ;AN000;IS THAT THE END OF THE STRING
564; $ENDDO E ;AN000;GOT IT ALL, QUIT
565 JNE $$DO55
566 CALL CHK_MAX_LENGTH ;AN000;LENGTH OF STRING <=64
567 POP BX ;AN000;RESTORE THE DATA BASE POINTER
568; $IF NC
569 JC $$IF58
570 OR PARM_FLAG, SECOND_PARM_FLAG
571; $ELSE
572 JMP SHORT $$EN58
573$$IF58:
574 MOV DX, MSG_LONG_PATH ;AN000;ADDRESS OF MESSAGE TXT
575 OR PARM_FLAG, INIT_ERROR_FLAG ;AN000;
576; $ENDIF ;AN000;CRITICAL ERROR INDICATED
577$$EN58:
578; $ENDIF ;AN000;SECOND FILESPEC
579$$IF54:
580; $ELSE ;AN000;FILESPEC NOT SPECIFIED
581 JMP SHORT $$EN50
582$$IF50:
583 CALL GET_OPTIONS ;AN000;PROCESS THE SWITCHES
584; $ENDIF ;AN000;MOVE ALL DONE
585$$EN50:
586; $ENDIF ;AN000;FILESPEC?
587$$EN37:
588 POP DS ;AN000;
589 ASSUME DS:DGROUP ;AN000;
590 RET
591GET_PARMS ENDP
592;
593SAVE_FOR_DISPLAY PROC NEAR
594;save first parm, second parm into DISP_S_PATH, DISP_T_PATH.
595;at this time, this is not gauranteed to be a path. They may
596;contains filename in it.
597;input: S_INPUT_PARM, T_INPUT_PARM, PARM_FLAG
598; DS: data seg
599; ES: psp
600
601 PUSH ES ;save ES
602 PUSH DS
603 POP ES ;ES = DS
604 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm entered?
605; $IF NZ ;yes
606 JZ $$IF65
607 MOV AL, 0 ;asciiz
608 LEA DI, S_INPUT_PARM
609 CALL STRING_LENGTH ;now CX has length
610 LEA SI, S_INPUT_PARM
611 LEA DI, DISP_S_PATH ;source path for display
612 CALL MOV_STRING ;AC000;s_input_parm => disp_s_path
613
614; $ENDIF
615$$IF65:
616 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm entered?
617; $IF NZ
618 JZ $$IF67
619 MOV AL, 0
620 LEA DI, T_INPUT_PARM
621 CALL STRING_LENGTH
622 LEA SI, T_INPUT_PARM
623 LEA DI, DISP_T_PATH
624 CALL MOV_STRING ;AC000;s_input_parm => disp_s_path
625; $ENDIF
626$$IF67:
627 POP ES
628 RET
629SAVE_FOR_DISPLAY ENDP
630;
631MOV_STRING PROC NEAR ;AN000;
632; move string from DS:SI to ES:DI
633; CX should indicate string length
634 cld
635; $DO
636$$DO69:
637 CMP CX, 0
638; $LEAVE Z
639 JZ $$EN69
640 LODSB ;[si] => AL
641 STOSB ;AL => [di]
642 DEC CX
643; $ENDDO
644 JMP SHORT $$DO69
645$$EN69:
646 RET
647MOV_STRING ENDP ;AN000;
648;
649MODIFY_FOR_DISPLAY PROC NEAR
650;finally trims DISP_S_PATH, DISP_T_PATH into good shape.
651;input: DS, ES = data seg. S_FILE_FLAG, T_FILE_FLAG
652
653 LEA DI, DISP_S_PATH
654 LEA SI, DISP_S_PATH
655 TEST PARM1_FLAG, S_FILE_FLAG ;source filename entered?
656 JZ MFD_NO_FILE1 ;no
657 CALL MASSAGE_DISP_PATH ;yes, entered.
658 JMP SHORT MFD_TARGET
659MFD_NO_FILE1: ;no source filename
660 CALL CHK_DRV_LETTER ;using [si]
661 JC MFD_CHK_TAIL1
662 CMP BYTE PTR [SI], 0 ;D:,0 case
663 JE MFD_TARGET ;OK
664 CMP BYTE PTR [SI], '\'
665 JNE MFD_CHK_TAIL1 ;D:dir... case
666 CMP BYTE PTR [SI+1], 0 ;D:\,0 case
667 JE MFD_TARGET ;OK
668MFD_CHK_TAIL1: ;else check tail
669 CALL CHK_TAIL_CHR ;chk tail and put \ at the end. using di
670MFD_TARGET:
671 LEA DI, DISP_T_PATH
672 LEA SI, DISP_T_PATH
673 TEST PARM1_FLAG, T_FILE_FLAG
674 JZ MFD_NO_FILE2
675 CALL MASSAGE_DISP_PATH
676 JMP SHORT MFD_EXIT
677MFD_NO_FILE2:
678 CALL CHK_DRV_LETTER
679 JC MFD_CHK_TAIL2
680 CMP BYTE PTR [SI], 0
681 JE MFD_EXIT
682 CMP BYTE PTR [SI], '\'
683 JNE MFD_CHK_TAIL2
684 CMP BYTE PTR [SI+1], 0
685 JE MFD_EXIT
686MFD_CHK_TAIL2:
687 CALL CHK_TAIL_CHR
688MFD_EXIT:
689 RET
690MODIFY_FOR_DISPLAY ENDP
691;
692CHK_TAIL_CHR PROC NEAR
693;check the last chr of ASCIIZ string pointed by DI.
694;if it is \,0 then OK, else put \ there.
695;DS, ES = data seg
696;DI points to string.
697;OUTPUT: Revised string.
698;AX, BX, CX - destroyed
699 MOV AL, 0 ;asciiz
700 PUSH DI ;save di
701 CALL STRING_LENGTH ;now cx got the length including 0
702 POP DI ;restore di
703 DEC CX
704 DEC CX
705 MOV BX, CX
706 CMP BYTE PTR [DI][BX], '\' ;last chr before 0
707 JE CTC_EXIT ;\,0 case
708 MOV BYTE PTR [DI][BX+1], '\' ;change 0 to '\'
709 MOV BYTE PTR [DI][BX+2], 0 ;make it asciiz again.
710CTC_EXIT:
711 RET
712CHK_TAIL_CHR ENDP
713;
714MASSAGE_DISP_PATH PROC NEAR
715;INPUT: DS, ES = data seg
716; DI = points to source. Used for LAST_DIR_OUT
717; SI = points to source. Used for CHK_DRV_LETTER routine
718;OUTPUT: Revised source string
719
720 CALL LAST_DIR_OUT
721; $IF C ;failure? no '\' found
722 JNC $$IF72
723 CALL CHK_DRV_LETTER ;drive letter?
724; $IF NC ;yes. "D:filename",0 case
725 JC $$IF73
726 MOV BYTE PTR DS:[SI], 0 ;make it "D:",0 since SI now points to the next chr
727; $ELSE ;no. "filename",0 case
728 JMP SHORT $$EN73
729$$IF73:
730 MOV BYTE PTR [DI], 0 ;set DISP_S_PATH to 0
731; $ENDIF
732$$EN73:
733; $ELSE ;found '\' and last '\' became 0
734 JMP SHORT $$EN72
735$$IF72:
736 MOV DI, AX ;we want to restore '\' and put 0 just after that.
737 DEC DI ;for ex, "D:\filename"=>"D:"=>"D:\"
738 MOV BYTE PTR [DI], '\' ; "D:dir1\dir2"=>"D:dir1"=>"D:dir1\"
739 MOV BYTE PTR [DI+1], 0
740; $ENDIF
741$$EN72:
742 RET
743MASSAGE_DISP_PATH ENDP
744;
745CHK_MAX_LENGTH PROC NEAR
746;Check the length of the source or target input string although this does not
747;gaurantee the validity of the length of path. This will just check/reduce
748;the possibilities of long path.
749;If the path string is longer than 64 (this includes 0 at the end of the string)
750;then, carry will be set.
751;INPUT: ds - data seg
752; es - psp seg
753; SI - points to the starting chr of the string.
754; BX - length of the string
755;OUTPUT:
756; carry will set if the length if longer than we expected.
757
758 PUSH BX ;AN000;
759 PUSH DI
760 PUSH SI
761 ;AC001;DELETED CODE FOR PTM0011
762 CMP BYTE PTR [SI], '\' ;SI points to '\'?
763 JNE CML_LENGTH ;no, now compare the length
764 DEC BX ;AC000;decrease length by 1 for '\'
765CML_LENGTH:
766 CMP BX, 63 ;AC000;length of string > 63?
767 JG CML_CARRY ;AC027;WORK WITH ONLY + CMP RESULT
768 CLC ;NO. OK.
769 JMP CML_EXIT
770CML_CARRY:
771 STC ;not OK
772CML_EXIT:
773 POP SI
774 POP DI
775 POP BX ;AN000;
776 RET
777
778CHK_MAX_LENGTH ENDP
779;
780;
781GET_OPTIONS PROC NEAR
782;get options from the PARSER and
783;set OPTION_FLAG.
784;INPUT:
785; BX - PARSER OPERAND POINTER
786;
787 CMP BX,OFFSET DGROUP:RESULTSW1 ;AN000;WAS SW 1 THROUGH 7 SPECIFIED?
788 MOV DI,RESULTSWSYN ;AN000;GET THE SYNONYM POINTER [ES]
789
790; $IF E,LONG ;AN000;IF SWITCH SPECIFIED
791 JE $$XL1
792 JMP $$IF78
793$$XL1:
794 CMP BYTE PTR ES:[DI+BYTE],ALPHA_S ;AC000;"S"
795 JNE GO_A
796 OR OPTION_FLAG, SLASH_S ;set the walk the tree bit on.
797 MOV SW_S,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
798 JMP GO_EXIT ;AC000;
799GO_A:
800 CMP BYTE PTR ES:[DI+BYTE],ALPHA_A ;AN000;"A"
801 JNE GO_M
802 MOV SW_A,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
803 TEST OPTION_FLAG, SLASH_M ;hard archieve already on?
804 JZ GO_A1 ;if not, continue
805 AND OPTION_FLAG, RESET_SLASH_M ;else turn it off
806GO_A1:
807 OR OPTION_FLAG, SLASH_A ;set soft archieve
808 JMP GO_EXIT ;AC000;
809GO_M:
810 CMP BYTE PTR ES:[DI+BYTE],ALPHA_M ;AN000;"M"
811 JNE GO_P
812 MOV SW_M,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
813 TEST OPTION_FLAG, SLASH_A ;soft archieve already on?
814 JZ GO_M1 ;if not, skip this part
815 AND OPTION_FLAG, RESET_SLASH_A ;else turn off the soft archieve bit
816GO_M1:
817 OR OPTION_FLAG, SLASH_M ;turn on the hard archieve bit.
818 JMP GO_EXIT ;AC000;
819GO_P:
820 CMP BYTE PTR ES:[DI+BYTE],ALPHA_P ;AN000;"P"
821 JNE GO_E
822 MOV SW_P,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
823 OR OPTION_FLAG, SLASH_P
824 OR MY_FLAG, SINGLE_COPY_FLAG ;if user want prompt, then should be single copy (not a multi copy).
825 JMP SHORT GO_EXIT ;AC000;
826GO_E:
827 CMP BYTE PTR ES:[DI+BYTE],ALPHA_E ;AN000;"E"
828 JNE GO_V
829 MOV SW_E,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
830 OR OPTION_FLAG, SLASH_E ;turn on "creating empty dir" bit.
831 JMP SHORT GO_EXIT ;AC000;
832GO_V:
833 CMP BYTE PTR ES:[DI+BYTE],ALPHA_V ;AN000;"V"
834 JNE GO_W
835 MOV SW_V,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
836 MOV AH, 54h ;get verify setting
837 INT 21H
838 CMP AL, 0
839 JNE GO_EXIT ;AC000;if not 0, then already on.
840 MOV AX, 2E01h ;else set it on
841 INT 21h
842 OR SYS_FLAG, TURN_VERIFY_OFF_FLAG ;don't forget it off when exit to dos.
843 JMP SHORT GO_EXIT ;AC000;
844GO_W:
845 OR OPTION_FLAG, SLASH_W
846 MOV SW_W,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
847 JMP SHORT GO_EXIT ;AC000;
848; $ELSE ;AN000;SINCE SWITCH 1 - 7 NOT SPECIFIED
849 JMP SHORT $$EN78
850$$IF78:
851 ; IT MUST BE THE DATE SWITCH
852 CALL GET_INPUT_DATE ;AN000;get date from parser control block
853 OR OPTION_FLAG, SLASH_D
854 MOV SW_D,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
855; $ENDIF ;AN000;
856$$EN78:
857GO_EXIT:
858 RET
859GET_OPTIONS ENDP
860
861GET_INPUT_DATE PROC NEAR
862;get the input date from the parser and save it to INPUT_DATE form which
863;it can be used for comparison with FILE_DATE_DTA.
864;INPUT:
865;
866;
867;OUTPUT:
868;
869;
870;
871
872 CALL VALIDATE_INPUT_DATE ;AN006;GO CHECK THE DATE
873; $IF C ;AN006;SET IF THE DATE WAS INVALID
874 JNC $$IF81
875 OR PARM_FLAG,INV_DATE_FLAG ;AN006;SET THE FLAG FOR DATE ERROR
876 OR PARM_FLAG,INIT_ERROR_FLAG ;AN006;SET THE FLAG FOR ERROR
877; $ELSE ;AN006;DATE WAS OK
878 JMP SHORT $$EN81
879$$IF81:
880 MOV AX,DATE_YEAR ;AN000;GET YEAR FROM PARSER CTRL BLOCK
881 SUB AX,1980 ;AN000;SUBTRACT THE BASE YEAR
882 mov cl,4 ;AN000;SHIFT REG COUNT = 4
883 shl ax,cl ;AN000;Shift it over 4
884 xor dh,dh ;AN000;CLEAR THE AREA
885 mov dl,DATE_MONTH ;AN000;GET MONTH FROM PARSER CTRL BLOCK
886 add ax,dx ;AN000;Add in the Month
887 inc cl ;AN000;BUMP SHIFT COUNT
888 shl ax,cl ;AN000;Shift it over 5
889 xor dh,dh ;AN000;CLEAR THE AREA
890 mov dl,DATE_DAY ;AN000;GET DAY FROM PARSER CTRL BLOCK
891 add ax,dx ;AN000;Add in the Day
892 mov INPUT_DATE,ax ;AN000;Store the date in DOS FCB format
893 CLC ;AN000;CLEAR THE CARRY
894; $ENDIF ;AN006;
895$$EN81:
896 RET
897GET_INPUT_DATE ENDP
898;
899VALIDATE_INPUT_DATE PROC NEAR
900;CHECK FOR VALID DATE.
901;
902;OUTPUT: INVALID DATE = CARRY SET
903;
904;
905;
906;
907 MOV AH,GET_DATE ;AN006;DOS INT 2AH
908 INT 21H ;AN006;MAKE THE CALL
909 PUSH CX ;AN006;YEAR
910 PUSH DX ;AN006;MONTH,DAY
911 MOV AH,SET_DATE ;AN006;DOS INT 2BH
912 MOV CX,DATE_YEAR ;AN006;GET YEAR FROM PARSER CTL BLOCK
913 MOV DH,DATE_MONTH ;AN006;GET MONTH FROM PARSER CTL BLOCK
914 MOV DL,DATE_DAY ;AN006;GET DAY FROM PARSER CTL BLOCK
915 INT 21H ;AN006;MAKE THE CALL
916 POP DX ;AN006;GET THE SYSTEM MONTH,DAY
917 POP CX ;AN006;GET THE SYSTEM YEAR
918 OR AL,AL ;AN006;WAS MY INPUT DATE VALID?
919 STC ;AN006;SET THE CARRY
920 JNZ ERR_DATE ;AN006;GET OUT WITH C SET
921 CLC ;AN006;CLEAR THE CARRY, NO ERROR
922 MOV AH,SET_DATE ;AN006;RESTORE THE SYSTEM DATE
923 INT 21H ;AN006;MAKE THE CALL
924ERR_DATE: ;AN006;
925 RET ;AN006;
926;
927VALIDATE_INPUT_DATE ENDP
928;
929CHK_SET_PARMS PROC NEAR
930;This does a semantic checking on the given S_INPUT_PARM, T_INPUT_PARM and
931;sets each of the starting drv path into S_PATH, T_PATH.
932;The basic logic is:
933;1). Try to change dir to a given S_INPUT_PARM.
934; if a success, then it must be the path. Chdir to it and get current
935; source directory using S_DRV_NUMBER by issuing GET_Current_directory call,
936; which starts from the root of the source drive. In this way, you don't
937; have to worry about what type of path for the source has been entered.
938; You just try to chdir according to S_INPUT_PARM and
939; then call get_cur_dir to get the S_PATH which will always start
940; from the root of the source drive.
941; if not, then there must be the filename at the end, or there might be
942; garbage in the path. So, take the last path name (which is, hopely,
943; a filename) and try chdir again. If a success, then current source dir
944; is determined. Otherwise, error. Issue "Invalid direcory name". If a
945; success, then check the saved filename to make sure that there are no
946; invalid chr's in it. (When you try to take the last_dir_out, and
947; it has failed (carry set), then it was a filename candidate itself
948; (sometimes together with an drive id d:). In this case, you have to
949; check the filename candidate if it has a drive id in front of it.
950; if it is, then take the drive id d: off from it and reshape the
951; filename candidate. And check the invalid characters if any. Of cause
952; in this case, current direcory of source drv becomes S_PATH.
953;2). Try to change dir to a given T_INPUT_PARM, if any. (If no T_INPUT_PARM
954; entered, then set current directory to the starting path of target using
955; T_DRV_NUMBER.)
956; If a success, then no problem. It is a strating target path.
957; If not, then take the last dir out and try again. If a failure, then
958; error "Invalid directory".
959; If a success, then check the saved filename to see if any illigal
960; characters in it. If they are, then error. Else issue fun.29h
961; to see if there are any global characters in it. If there
962; are, then assume a filename. If there are not, then ask user
963; "Is XXXXX a filename in the target? (n)" If no, then it is a
964; subdirectory name. Make a new subdirectory in the target and
965; concatenate a new directory name to the T_INPUT_PARM and chdir to
966; the new path (, which is the original path in fact) again.
967;INPUT:
968; ES - PSP seg ; this will be changed to DS within this routine
969; DS - data seg
970
971 PUSH DS
972 POP ES ;set ES to DS
973 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm entered?
974; $IF Z,AND ;NO
975 JNZ $$IF84
976 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm entered?
977; $IF Z ;NO
978 JNZ $$IF84
979 MOV DX, MSG_INV_NUM_PARM ;AC000;GET THE MESSAGE ID
980 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error. exit program
981; $ELSE
982 JMP SHORT $$EN84
983$$IF84:
984
985 MOV DL, S_DRV_NUMBER
986 LEA SI, SAV_S_CURDIR
987 CALL GET_CUR_DIR ;get and save current source directory
988 OR SYS_FLAG, DEFAULT_S_DIR_FLAG ;indicates source dir saved
989 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm only entered?
990; $IF Z ;no first parm
991 JNZ $$IF86
992 LEA SI, S_PATH ;then make current source dir as S_PATH
993 CALL GET_CUR_DIR
994; $ELSE ;else first parm entered. check it
995 JMP SHORT $$EN86
996$$IF86:
997 LEA DX, S_INPUT_PARM ;try to chdir to S_INPUT_PARM
998 MOV AH, Chdir ;= 3Bh
999 INT 21h
1000; $IF NC ;success?
1001 JC $$IF88
1002 MOV DL, S_DRV_NUMBER
1003 LEA SI, S_PATH ;get current dir and save it
1004 CALL GET_CUR_DIR ;as a starting dir to S_PATH
1005; $ELSE
1006 JMP SHORT $$EN88
1007$$IF88:
1008 LEA BX, S_INPUT_PARM
1009 LEA DX, S_FILE ;source filename
1010 CALL TAKE_PATH_TAIL ;take out the tail part of S_INPUT_PARM
1011 LEA DX, S_INPUT_PARM
1012 MOV AH, Chdir ;= 3Bh
1013 INT 21h ;try chdir again
1014; $IF NC,AND ;success?
1015 JC $$IF90
1016 CMP S_FILE, 0 ;check s_file if something is there
1017; $IF NE ;yes, filename entered.
1018 JE $$IF90
1019 MOV DL, S_DRV_NUMBER
1020 LEA SI, S_PATH
1021 CALL GET_CUR_DIR ;save current dir
1022 OR PARM1_FLAG, S_FILE_FLAG ;source filename entered
1023 call chk_s_reserved_name ;is it a reserved name?
1024; $ELSE
1025 JMP SHORT $$EN90
1026$$IF90:
1027 MOV DX, MSG_INVALID_PATH ;AC000;GET THE MESSAGE ID
1028 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1029; $ENDIF
1030$$EN90:
1031; $ENDIF
1032$$EN88:
1033; $ENDIF
1034$$EN86:
1035; $ENDIF
1036$$EN84:
1037 TEST PARM_FLAG, INIT_ERROR_FLAG
1038; $IF Z,LONG ;no error so far,
1039 JZ $$XL2
1040 JMP $$IF96
1041$$XL2:
1042 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;if one disk copy
1043; $IF NZ ;then saved source default directory
1044 JZ $$IF97
1045 LEA DX, SAV_S_DRV ;is the same as target current dir
1046 MOV AH, Chdir ;=3Bh
1047 INT 21h ;so restore target default dir.
1048; $ENDIF
1049$$IF97:
1050 MOV DL, T_DRV_NUMBER
1051 LEA SI, SAV_T_CURDIR
1052 CALL GET_CUR_DIR ;save current target directory
1053 OR SYS_FLAG, DEFAULT_T_DIR_FLAG ;indicates target dir saved
1054 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm has been entered?
1055; $IF Z ;second parm not entered
1056 JNZ $$IF99
1057 LEA SI, T_PATH
1058 CALL GET_CUR_DIR ;make the current target dir as T_PATH
1059; $ELSE ;then deals with the second parm
1060 JMP SHORT $$EN99
1061$$IF99:
1062
1063 LEA DX, T_INPUT_PARM ;try to chdir according to T_INPUT
1064 MOV AH, Chdir
1065 INT 21h ;= 3Bh
1066; $IF C ;FAILURE?
1067 JNC $$IF101
1068 CALL PARSE_SECOND_PARM
1069; $ENDIF
1070$$IF101:
1071
1072 TEST PARM_FLAG, INIT_ERROR_FLAG ;no error so far?
1073; $IF Z ;no error
1074 JNZ $$IF103
1075 MOV DL, T_DRV_NUMBER
1076 LEA SI, T_PATH
1077 CALL GET_CUR_DIR ;save target starting dir
1078 CMP TEMP_T_FILENAME, 0 ;any non_global target file name entered?
1079; $IF NE ;yes
1080 JE $$IF104
1081 MOV CX, 13 ;maximum 13 char.
1082 LEA SI, TEMP_T_FILENAME
1083 LEA DI, T_FILENAME ;then move it to T_FILENAME while convert it to capital letter.
1084 CALL MOV_STRING ;AC000; SI => DI
1085; $ENDIF
1086$$IF104:
1087; $ENDIF ;end - no error so far
1088$$IF103:
1089; $ENDIF ;end - second parm not entered
1090$$EN99:
1091; $ENDIF
1092$$IF96:
1093
1094 TEST PARM_FLAG, INIT_ERROR_FLAG
1095; $IF Z ;no error
1096 JNZ $$IF109
1097 CALL CHK_CYCLIC_COPY ;check source, target parms
1098 TEST PARM_FLAG, INIT_ERROR_FLAG ;cyclic copy?
1099; $IF Z,AND ;no
1100 JNZ $$IF110
1101 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;if one disk drv letter copy
1102; $IF NZ ;then set the starting dir
1103 JZ $$IF110
1104 LEA DX, S_DRV_PATH ;to that of source.
1105 MOV AH, Chdir ; = 3Bh
1106 INT 21H ;should succeed since alreay tested.
1107; $ENDIF
1108$$IF110:
1109; $ENDIF
1110$$IF109:
1111
1112 RET
1113CHK_SET_PARMS ENDP
1114;
1115PARSE_SECOND_PARM PROC NEAR
1116;called after the initial chdir to T_INPUT_PARM failed. Remember the second parm should
1117;exist when you call this routine.
1118;INPUT: DS, ES - data seg
1119;OUTPUT:if error, init_error_flag will be set.
1120;
1121 LEA SI, T_INPUT_PARM
1122 CALL CHK_HEAD_PARM ;check the head part of parm. SI will points
1123 ;to the next chr after the header.
1124 TEST PARM_FLAG, INIT_ERROR_FLAG
1125 JNZ PSP_EXIT ;YES, ERROR.
1126 CALL NEXT_PATH_DELIM ;Let SI points to the next path delim "\" or 0
1127 LEA DX, T_INPUT_PARM
1128 CALL PARSING_T_PATH ;chdir for every directory starting from the
1129 ;first. If it fails, then create a directory
1130 ;and chdir to it.
1131PSP_EXIT:
1132 RET
1133PARSE_SECOND_PARM ENDP
1134;
1135NEXT_PATH_DELIM PROC NEAR
1136;starting from SI, check every chr until it is '\' or 0 or ':'.
1137;if the starting chr is '\' or 0 or ':', then SI won't change.
1138;the caller should be sure that it is an ASCIIZ string.
1139;INPUT: DS, ES - data seg
1140; SI - starting point
1141;OUTPUT:
1142; SI - next path delimeter
1143
1144 CLD
1145 PUSH DI
1146 PUSH SI
1147 POP DI ;NOW DI POINTS TO THE STARTING CHR
1148NPD_LOOP:
1149; $DO ;AN010;
1150$$DO113:
1151 CLC ;AN010;INITIALIZE TO NOT DBCS
1152 MOV AL,BYTE PTR [DI] ;AN010;GET THE 1st CHAR TO TEST
1153 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
1154; $LEAVE NC ;AN010;THIS IS NOT DBCS
1155 JNC $$EN113
1156 INC DI ;AN010;GO TO THE NEXT CHAR TO CHECK
1157 INC DI ;AN010;DITO
1158; $ENDDO ;AN010;
1159 JMP SHORT $$DO113
1160$$EN113:
1161 MOV AL, 0
1162 SCASB ;0 - ES:[DI], DI=DI+1
1163 JZ NPD_FOUND
1164 DEC DI ;check it again if it is '\'
1165 MOV AL, '\'
1166 SCASB
1167 JZ NPD_FOUND
1168 DEC DI
1169 MOV AL, ':' ;is it a filename terminator not filter before?
1170 SCASB
1171 JZ NPD_FOUND
1172 JMP SHORT NPD_LOOP
1173NPD_FOUND:
1174 DEC DI ;adjust DI to the chr found
1175 PUSH DI
1176 POP SI ;now SI points to the chr
1177 POP DI ;restore DI
1178 RET
1179NEXT_PATH_DELIM ENDP
1180;
1181
1182CHK_HEAD_PARM PROC NEAR
1183;check the starting header part of parameter pointed by SI to eliminate
1184;error such as A:\\..., A:\.., \\, \.. etc.
1185;This routine will change the current target directory to the root
1186;when "d:\" or "\" has been found.
1187;The parameter string should be ASCIIZ and should exist.
1188;INPUT: DS, ES - DATA SEG
1189; SI - POINTS TO THE PARAMETER
1190;OUTPUT:SI POINTS TO THE NEXT VALID PATH
1191; DX WILL POINTS TO THE ERROR MESSAGE
1192
1193 CALL CHK_DRV_LETTER ;si points to the next chr after drv letter, if found.
1194 CMP BYTE PTR [SI], 0 ;"A:0" case
1195; $IF E
1196 JNE $$IF116
1197 MOV BYTE PTR [SI], '.'
1198 INC SI
1199 MOV BYTE PTR [SI], 0 ;make it "A:.0"
1200; $ELSE
1201 JMP SHORT $$EN116
1202$$IF116:
1203 CMP BYTE PTR [SI], '\'
1204; $IF E ;A:\--- or \--- cases
1205 JNE $$IF118
1206 INC SI
1207 CLC ;AN010;INITIALIZE TO NOT DBCS
1208 MOV AL,DS:BYTE PTR [SI] ;AN010;GET THE 1st CHAR TO TEST
1209 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
1210; $IF NC ;AN010;THIS IS NOT DBCS
1211 JC $$IF119
1212 CMP BYTE PTR [SI], '\'
1213; $IF E ;A:\\--- or \\--- cases ; ERROR
1214 JNE $$IF120
1215 MOV DX, MSG_INVALID_PATH ;AC000;GET THE MESSAGE ID
1216 OR PARM_FLAG, INIT_ERROR_FLAG
1217; $ELSE
1218 JMP SHORT $$EN120
1219$$IF120:
1220 CMP BYTE PTR [SI], '.'
1221; $IF E ;A:\.--- or \.--- cases
1222 JNE $$IF122
1223 INC SI
1224 MOV AL,DS:BYTE PTR [SI] ;AN010;GET 1st CHAR
1225 ; TO TEST
1226 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN
1227 ; DBCS
1228; $IF NC ;AN010;THIS IS NOT DBCS
1229 JC $$IF123
1230 CMP BYTE PTR [SI], '.'
1231; $IF E,OR
1232 JE $$LL124
1233 CMP BYTE PTR [SI], '\'
1234; $IF NE ;if not A:\.\--- or \.\--- cases
1235 JE $$IF124
1236$$LL124:
1237 MOV DX, MSG_INVALID_PATH ;AC000;MSG ID
1238 OR PARM_FLAG, INIT_ERROR_FLAG
1239; $ENDIF
1240$$IF124:
1241; $ENDIF ;AN010;END OF DBCS TEST
1242$$IF123:
1243 CLC ;AN010;
1244; $ENDIF
1245$$IF122:
1246; $ENDIF
1247$$EN120:
1248 LEA DX, T_DRV
1249 MOV AH, Chdir
1250 INT 21h ;"Chdir to root" is no problem.
1251; $ENDIF ;AN010;DBCS TEST END
1252$$IF119:
1253 CLC ;AN010;
1254; $ENDIF
1255$$IF118:
1256; $ENDIF
1257$$EN116:
1258 RET
1259CHK_HEAD_PARM ENDP
1260;
1261PARSING_T_PATH PROC NEAR
1262;chdir to every path element from the first. If fails, create the directory and
1263;try to chdir again. T_MKDIR_LVL will increase when new starting directory is created
1264;INPUT: DX - OFFSET OF T_INPUT_PARM
1265; SI - points to '\' or 0, or ':'
1266;OUTPUT: directories are created if necessary.
1267; DX points to the last path entry
1268; if fails to create a directory, then INIT_ERROR_FLAG set and
1269; DX points to MSG_NOT_CREATE_DIR msg.
1270
1271 PUSH DX ;save DX
1272 MOV DL, T_DRV_NUMBER
1273 DEC DL
1274 CALL SET_DEFAULT_DRV ;set target drive as a default
1275 POP DX ;restore DX
1276PTP_NEXT:
1277 CMP BYTE PTR [SI], 0 ;end of string? the last path element?
1278 JE PTP_LAST
1279 CMP BYTE PTR [SI], ':' ;filename terminator not checked before?
1280 JNE PTP_CHDIR ;else it is '\'.
1281 MOV BYTE PTR [SI], 0 ;change ':' to 0 for termination.
1282PTP_LAST:
1283 CALL LAST_T_PATH
1284 JMP PTP_EXIT
1285PTP_CHDIR:
1286 MOV BYTE PTR [SI], 0 ;replace '\' with 0
1287 MOV AH, Chdir ;=38h
1288 INT 21h
1289 JC PTP_MKDIR
1290 MOV BYTE PTR [SI], '\' ;restore '\'
1291 INC SI ;SI points to next to old '\'
1292 MOV DX, SI ;DX points to next path entry
1293 CALL NEXT_PATH_DELIM
1294 JMP PTP_NEXT ;handles next path element
1295PTP_MKDIR:
1296 MOV AH, Mkdir ;=39h
1297 INT 21h
1298 JC PTP_ERROR ;cannot make directory
1299 INC T_MKDIR_LVL ;# of MKDIR for the starting directory.
1300 JMP PTP_CHDIR ;try again to chdir
1301PTP_ERROR:
1302 MOV DX, MSG_NOT_CREATE_DIR ;AC000;GET THE MESSAGE ID
1303 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1304PTP_EXIT:
1305 RET
1306
1307PARSING_T_PATH ENDP
1308;
1309LAST_T_PATH PROC NEAR
1310;called when the second parm reached last. *** this routine is the same as the old routine ***
1311;and the initial try to chdir to the given T_INPUT_PARM has been failed.
1312;INPUT: ES, DS - data seg
1313; DX - points to the last path entry
1314;OUTPUT:target starting directory.
1315
1316 MOV AH, Chdir ;try to chdir to the last path entry
1317 INT 21h
1318; $IF C,LONG ;if fail.
1319 JC $$XL3
1320 JMP $$IF132
1321$$XL3:
1322
1323 LEA BX, T_INPUT_PARM
1324 LEA DX, TEMP_T_FILENAME ;take the last path element into TEMP_T_FILENAME
1325 CALL TAKE_PATH_TAIL
1326 CMP TEMP_T_FILENAME, 0 ;any filename candidate entered?
1327; $IF NE,LONG ;yes. let's check it has any global chr.
1328 JNE $$XL4
1329 JMP $$IF133
1330$$XL4:
1331 PUSH ES
1332 MOV AH, 29h
1333 LEA SI, TEMP_T_FILENAME
1334 MOV ES, PSP_SEG ;ES - psp seg
1335 MOV DI, PSPFCB2_DRV ;use this area for this test purposes
1336 MOV AL, 0 ;control bit
1337 INT 21h
1338 POP ES
1339 CMP AL, 0 ;no global filename entered?
1340; $IF E ;yes, no globals
1341 JNE $$IF134
1342 CALL PROMPT_CREATE_DIR ;then ask the user, it is a filename or subdir name?
1343 MOV DX,USER_INPUT ;AN000;SET UP FOR COMPAIR
1344 CMP DX, alpha_dir ;directory?
1345; $IF E ;yes, a subdir name.
1346 JNE $$IF135
1347 LEA DX, TEMP_T_FILENAME
1348 MOV AH, Mkdir ;=39h
1349 INT 21h ;create a new subdir
1350; $IF NC
1351 JC $$IF136
1352 INC T_MKDIR_LVL ;one more directory has been made.
1353 MOV AH, Chdir
1354 INT 21h ;Chdir to a new dir. This time it should be a success.
1355 MOV TEMP_T_FILENAME, 0 ;mark temp_t_filename that it is empty
1356; $ELSE ;ERROR IN CREATING DIRECTORY
1357 JMP SHORT $$EN136
1358$$IF136:
1359 MOV DX, MSG_NOT_CREATE_DIR ;AC000;GET THE MESSAGE ID
1360 OR PARM_FLAG, INIT_ERROR_FLAG
1361; $ENDIF
1362$$EN136:
1363; $ELSE ;USER ANSWERED IT A FILENAME
1364 JMP SHORT $$EN135
1365$$IF135:
1366 OR PARM1_FLAG, T_FILE_FLAG ;set target file entered.
1367; $ENDIF ;use TEMP_T_FILENAME as a filename
1368$$EN135:
1369; $ELSE ;GLOBALS IN THE FILENAME
1370 JMP SHORT $$EN134
1371$$IF134:
1372 MOV TEMP_T_FILENAME, 0 ;mark it to 0 since we don;t need this.
1373 CALL MAKE_TEMPLATE ;make a template of the target filename
1374 OR PARM1_FLAG, T_FILE_FLAG ;set target file entered flag
1375; $ENDIF ;GLOBAL TEST
1376$$EN134:
1377; $ENDIF ;NO, FILENAME NOT ENTERED. TEMP_T_FILENAME = 0
1378$$IF133:
1379; $ENDIF ;CHDIR FAIL
1380$$IF132:
1381 RET
1382LAST_T_PATH ENDP
1383;
1384;
1385CHK_S_RESERVED_NAME PROC NEAR
1386;check the source filename entered, and if it does not have any global chr,
1387;then check it whether it is reserved filename or not.
1388;input: es,ds - data seg
1389
1390 mov ax, 3d00h ;let's try to open it
1391 lea dx, s_drv_1 ;'A:S_FILE'
1392 int 21h
1393 jc csrn_exit ;open failure? jmp to exit
1394 mov bx, ax ;else ax has file handle
1395 mov ax, 4400h ;get device info.
1396 int 21h ;ioctl fun call
1397 test dx, 80h ;ISDEV ?
1398 jz csrn_close ;no, block device. close handle and exit
1399 PUSH AX ;AN000;
1400 MOV AX, msg_res_s_name ;AC000;reserved file name as a source"
1401 MOV MSG_NUM,AX ;AN000;NEED MESSAGE ID FOR PRINT
1402 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
1403 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
1404 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1405 CALL PRINT_STDERR ;AN000;print error. AX points to msg ID
1406 POP AX ;AN000;
1407 mov errorlevel, 4 ;abnormal termination
1408 or parm_flag, init_error_flag ;set init_error_flag
1409 jmp main_exit
1410csrn_close:
1411 mov ah, 3eh ;close filehandle in bx
1412 int 21h
1413csrn_exit:
1414 ret
1415CHK_S_RESERVED_NAME ENDP
1416;
1417PROMPT_CREATE_DIR PROC NEAR
1418;DS, ES - data seg
1419 PUSH AX ;AN000;
1420 mov cx, 13
1421 lea si, temp_t_filename
1422 lea di, filename_for_prompt
1423 call mov_STRING ;AC000;
1424
1425;CALL GET MESSAGE TO DETERMINE WHAT THIS COUNTRY INPUT FOR 'F' OR 'D' IS.
1426
1427 PUSH DS ;AN000;
1428 ASSUME DS:NOTHING ;AN000;TELL THE ASSEMBLER
1429 MOV AX,MSG_F_D ;AN000;MESSAGE NUMBER = 29 = 'F D '
1430 MOV DH,UTILITY_MSG_CLASS ;AN000;MESSAGE DEFINED FOR XCPYINIT
1431 CALL SYSGETMSG ;AN000;GET THE MESSAGE
1432 LODSW ;AN000;'F'PART OF MSG (DS:SI => AX)
1433 CMP AH,SPACE ;AN000;NOT 'SPACE' THEN IT IS DBCS !
1434; $IF E ;AN000;IGNORE THE NEXT WORD
1435 JNE $$IF145
1436 MOV AH,NUL ;AN000;THE END OF THE STRING
1437; $ENDIF ;AN000;NOW GET TRANSLATION OF 'D'
1438$$IF145:
1439 MOV ES:ALPHA_FILE,AX ;AN000;TRANSLATED CHAR FOR 'F' TO BUFF
1440 LODSW ;AN000;'D'PART OF MSG (DS:SI => AX)
1441 CMP AH,SPACE ;AN000;NOT 'SPACE' THEN IT IS DBCS !
1442; $IF E ;AN000;IGNORE THE NEXT WORD
1443 JNE $$IF147
1444 MOV AH,NUL ;AN000;REMOVE SPACE CHARACTER
1445; $ENDIF ;AN000;NOW GET TRANSLATION OF 'D'
1446$$IF147:
1447 MOV ES:ALPHA_DIR,AX ;AN000;TRANSLATED CHAR FOR 'D' TO BUFF
1448 POP DS ;AN000;RESTORE AFTER CALL TO MSG HANDLR
1449 ASSUME DS:DGROUP ;AN000;TELL THE ASSEMBLER
1450 ;remember this may be DBCS
1451PCD_AGAIN:
1452; Set message substitution list
1453 LEA SI,SUBLIST1 ;AN000; get addressability to sublist
1454 LEA DX,FILENAME_FOR_PROMPT ;AN000; offset to file name
1455 MOV [SI].DATA_OFF,DX ;AN000; save data offset
1456 MOV [SI].DATA_SEG,DS ;AN000; save data segment
1457 MOV [SI].MSG_ID,1 ;AN000; message ID
1458 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
1459 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
1460 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
1461
1462 MOV AX,MSG_CREATE_DIR ;AN000;ID OF MESSAGE TO BE DISPLAYED
1463 MOV MSG_NUM,AX ;AN000;SET THE MESSAGE NUMBER
1464 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN000;PARM SUBSTITUTION COUNT=1
1465 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1466 MOV INPUT_FLAG,KEYBOARD_INPUT ;AN000;KEYBOARD INPUT EXPECTED FUNCTION
1467 CALL PRINT_STDOUT ;show prompt and get user input
1468
1469 MOV USER_INPUT,AX ;AN000;RESPONSE BUFF FOR CAPITALIZATION
1470
1471 MOV AX,MSG_CR_LF_STR ;AN000; JUST CR,LF
1472 MOV MSG_NUM,AX ;AN000; set message number
1473 MOV SUBST_COUNT,NO_SUBST ;AN000;NO PARAMETER SUBSTITUTION
1474 MOV INPUT_FLAG,NO_INPUT ;AN000; NO INPUT
1475 CALL PRINT_STDOUT ;AN000; Display message
1476
1477 MOV AX,UPPER_CASE_STRING ;AN000;AX = 6521H GET EXT CTRY INFO
1478 LEA DX,USER_INPUT ;AN000;RESPONSE BUFF FOR CAPITALIZATION
1479 MOV CX,2 ;AN000;TWO CHARACTERS, ONE WORD
1480 INT 21H ;AN000;ISSUE INT TO CAP STRING (DBCS?)
1481 MOV AX,USER_INPUT ;AN000;SO I CAN DO THE COMPARE
1482 CMP AX,ALPHA_FILE ;AN000;KEYBOARD INPUT AX = 'F' ?
1483 JE PCD_EXIT
1484 CMP AX,ALPHA_DIR ;AN000;KEYBOARD INPUT AX = 'D' ?
1485 JE PCD_EXIT
1486 JMP SHORT PCD_AGAIN
1487PCD_EXIT:
1488
1489 POP AX ;AN000;
1490 RET
1491PROMPT_CREATE_DIR ENDP
1492;
1493TAKE_PATH_TAIL PROC NEAR
1494;check the tail of the source input parm.
1495;Call LAST_DIR_OUT
1496;If carry set
1497; then check the drive letter
1498; if entered, then save the rest of the string after drv: into
1499; a tempory filename holder, and put "." after the drive letter
1500; (For ex, if the input had been 'A:name1',0 then no change after
1501; LAST_DIR_OUT. This has to be changed to 'A:.',0 and name1.)
1502; else save the last dir into a filename, and
1503; check the result path
1504; if it is a drive only, then put "\" ( For ex, if the input
1505; had been 'A:\name1',0 then after LAST_DIR_OUT, it will be changed
1506; to 'A:',0 and 'name1',0. In this case, we have to change the
1507; path to A:\)
1508; else OK.
1509;INPUT: DS - data seg
1510; ES - data seg
1511; BX - offset value of S_INPUT_PARM or T_INPUT_PARM
1512; DX - offset value of TEMP_S_FILENAME or TEMP_T_FILENAME
1513
1514
1515 MOV DI, BX ;offset of S(T)_INPUT_PARM
1516 CALL LAST_DIR_OUT
1517; $IF C ;Not found a "\"
1518 JNC $$IF149
1519 MOV SI, DI ;set si = di
1520 CALL CHK_DRV_LETTER ;if drv letter:, then SI will
1521 ;point to next chr. Otherwise no change
1522 cmp byte ptr [si], 0 ;only drv letter has entered. No filename
1523; $IF NE ;filename entered
1524 JE $$IF150
1525 push si ;save si
1526 MOV CX, 13 ;max # of filename in ASCIIZ
1527 MOV DI, DX
1528 REP MOVSB ;save it to temporay name holder
1529 pop si ;restore si
1530; $ENDIF
1531$$IF150:
1532 mov byte ptr [si], A_dot ;to be used for Chdir fun call
1533 mov byte ptr [si+1], 0 ;make it ASCIIZ
1534; $ELSE ;at least found a "\"
1535 JMP SHORT $$EN149
1536$$IF149:
1537 mov cx, 13 ;let's save tail into filename holder first
1538 mov si, ax ;AX is an offset value of the tail
1539 mov di, DX ;TEMP_FILENAME
1540 rep movsb
1541 mov si, BX ;return to the Revised input
1542 CALL CHK_DRV_LETTER ;it starts with drv letter?
1543 cmp byte ptr [si], 0 ;si points to the end of string?
1544; $IF E
1545 JNE $$IF153
1546 MOV byte ptr [SI], '\' ;then add '\' in the Revised S_INPUT_PARM
1547 MOV byte ptr [SI+1], 0
1548; $ENDIF
1549$$IF153:
1550; $ENDIF
1551$$EN149:
1552 RET
1553
1554TAKE_PATH_TAIL ENDP
1555;
1556CHK_CYCLIC_COPY PROC NEAR
1557;With the one_disk_copy case, if the starting source path is a member of
1558;parent directory of the startind target path, then infinite copy cycle
1559;can occur. This routine prevents that situation.
1560;ES: data seg
1561;DS: data seg
1562
1563 PUSH DS
1564 POP ES ;set ES to DS (ES = DS)
1565 CALL TRANS_NAMES ;AN016;CHK ASSIGN, JOIN & SUBST CONDITN
1566 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;source, target drv let same
1567; $IF NZ ;if they are, then check below facts
1568 JZ $$IF156
1569 MOV DI, OFFSET DGROUP:T_TRANS_PATH ;AC025;
1570 MOV AL, 0
1571 CALL STRING_LENGTH
1572 MOV DX, CX ;save the length of S_PATH
1573 MOV DI, OFFSET DGROUP:S_TRANS_PATH ;AC025;
1574 CALL STRING_LENGTH
1575 CMP DX,CX ;compare the length
1576; $IF AE ;if target length >= source length
1577 JNAE $$IF157
1578 MOV SI, OFFSET DGROUP:S_TRANS_PATH ;AC025;
1579 MOV DI, OFFSET DGROUP:T_TRANS_PATH ;AC025;
1580 DEC CX ;get the actual length of chr's
1581 DEC DX
1582 CLD
1583; $SEARCH ;current CX = source length
1584$$DO158:
1585 CMP CX, 0
1586; $EXITIF E ;exit if cx = 0
1587 JNE $$IF158
1588 CMP DX, 0 ;target length = 0 too?
1589; $IF E ;yes, source = target
1590 JNE $$IF160
1591 TEST OPTION_FLAG, SLASH_S ; tree copy?
1592; $IF NZ,OR ;yes
1593 JNZ $$LL161
1594 TEST OPTION_FLAG, SLASH_E
1595; $IF NZ
1596 JZ $$IF161
1597$$LL161:
1598 MOV DX, MSG_CYCLIC_COPY ;AC000;GET THE MESSAGE ID
1599 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1600; $ELSE ;same length, but not a tree copy.
1601 JMP SHORT $$EN161
1602$$IF161:
1603 OR COPY_STATUS, MAYBE_ITSELF_FLAG ;possibly, copy onto itself.
1604; $ENDIF ;cannot fully determine this time until file creation time
1605$$EN161:
1606; $ELSE ;target > source
1607 JMP SHORT $$EN160
1608$$IF160:
1609 TEST OPTION_FLAG, SLASH_S ;tree copy?
1610; $IF NZ,OR
1611 JNZ $$LL165
1612 TEST OPTION_FLAG, SLASH_E
1613; $IF NZ
1614 JZ $$IF165
1615$$LL165:
1616 CMP BYTE PTR [DI], '\' ;source = d:\abc, target = d:\abc\def case
1617; $IF E,OR
1618 JE $$LL166
1619 CMP BYTE PTR [DI-1], '\' ;source = d:\, target=d:\abc case
1620; $IF E
1621 JNE $$IF166
1622$$LL166:
1623 MOV DX, MSG_CYCLIC_COPY ;AC000;GET THE MESSAGE ID
1624 OR PARM_FLAG, INIT_ERROR_FLAG ; critical error
1625; $ENDIF
1626$$IF166:
1627; $ENDIF
1628$$IF165:
1629; $ENDIF
1630$$EN160:
1631; $ORELSE
1632 JMP SHORT $$SR158
1633$$IF158:
1634 LODSB ;[SI] => AL, SI = SI + 1
1635 SCASB ;AL vs. [DI], DI = DI + 1
1636; $LEAVE NE ;leave if not same
1637 JNE $$EN158
1638 DEC CX
1639 DEC DX ;decrease target length, too
1640; $ENDLOOP
1641 JMP SHORT $$DO158
1642$$EN158:
1643; $ENDSRCH
1644$$SR158:
1645; $ENDIF
1646$$IF157:
1647; $ENDIF
1648$$IF156:
1649 RET
1650
1651CHK_CYCLIC_COPY ENDP
1652;
1653TRANS_NAMES PROC NEAR
1654;TRANSLATE THE INPUT TARGET AND SOURCE PATH TO DETERMINE
1655;IF ASSIGN, JOIN OR SUBSD WAS USET TO MODIFY HIDE THE TRUE
1656;PATH. THIS INFO. WILL BE USED TO DETERMINE CYCLIC COPY.
1657;INPUT: T_DRV_PATH, S_DRV_PATH
1658
1659 PUSH SI ;AN016;SI WILL BE DESTROYED
1660 PUSH DI ;AN016;DI WILL BE DESTROYED
1661
1662 MOV SI,OFFSET DGROUP:T_DRV_PATH ;AN016;DO NAME TRANSLATE OF TAR
1663 MOV DI,OFFSET DGROUP:T_TRANS_PATH ;AN025;SAVE FOR COMPARE
1664 MOV AH,60h ;AN016;NAMETRANSLATE
1665 INT 21h ;AN016;EXECUTE
1666
1667 MOV SI,OFFSET DGROUP:S_DRV_PATH ;AN016;DO NAME TRANSLATE OF SRC
1668 MOV DI,OFFSET DGROUP:S_TRANS_PATH ;AN025;SAVE FOR COMPARE
1669 MOV AH,60h ;AN016;NAMETRANSLATE
1670 INT 21h ;AN016;EXECUTE
1671
1672;NOW COMPARE THE TRANSLATED NAMES
1673
1674 MOV SI,OFFSET DGROUP:T_TRANS_PATH ;AN025;GET THE TAR FOR COMPARE
1675 MOV DI,OFFSET DGROUP:S_TRANS_PATH ;AN025;GET THE SRC FOR COMPARE
1676 CALL STR_COMP ;AN016;DO THE COMPARE
1677; $IF Z ;AN016;STRING DID COMPARE
1678 JNZ $$IF176
1679 OR SYS_FLAG, ONE_DISK_COPY_FLAG ;AN016;source, target drv let same
1680; $ENDIF ;AN016;
1681$$IF176:
1682
1683 POP DI ;AN016;restore DI
1684 POP SI ;AN016;restore SI
1685 RET
1686TRANS_NAMES ENDP
1687;
1688STR_COMP PROC NEAR
1689;COMPARE ASCIIZ DS:SI WITH ES:DI
1690;DI,SI ARE DESTROYED
1691
1692STRCOMP:
1693 CMPSB ;AN016;ONE BYTE AT A TIME
1694; $IF NZ ;AN016;DID NOT COMPARE
1695 JZ $$IF178
1696 RET ;AN016;NZ = DIFFERENCE
1697; $ENDIF ;AN016;
1698$$IF178:
1699 CMP BYTE PTR [SI-1],NUL ;AN016;CHK FOR END OF THE STRING
1700; $IF Z ;ANO16;IT IS E O S
1701 JNZ $$IF180
1702 RET ;AN016;IT COMPARED
1703; $ENDIF ;AN016;
1704$$IF180:
1705 JMP SHORT STRCOMP ;AN016;GO AGAIN
1706STR_COMP ENDP
1707
1708MAKE_TEMPLATE PROC NEAR
1709;copy the formatted filename into the T_TEMPLATE which will be
1710;used to name a new filename.
1711;INPUT: PSP FCB 6ch for filename which have global chr.
1712;
1713 PUSH DS ;ES = DS = DATA SEG
1714
1715 MOV DS, PSP_SEG ;DS = PSP_SEG
1716
1717 MOV SI, PSPFCB2_DRV
1718 INC SI
1719 LEA DI, T_TEMPLATE
1720 MOV CX, 11
1721 REP MOVSB ;filename => t_template
1722
1723 POP DS ;restore DS
1724 RET
1725MAKE_TEMPLATE ENDP
1726
1727GET_DRIVES PROC NEAR
1728;get source and target phisical drive letter from parser area.
1729;set ONE_DISK_COPY_FLAG, if the user XCOPY using the same drive letter.
1730
1731 MOV AL, SO_DRIVE ;AN000;source drive letter
1732 CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
1733; $IF E ;AN000;YES, GET THE DEFAULT
1734 JNE $$IF182
1735 MOV AL, SAV_DEFAULT_DRV ;(1=A, 2=B,...)
1736; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
1737 JMP SHORT $$EN182
1738$$IF182:
1739 SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
1740; $ENDIF
1741$$EN182:
1742 MOV S_DRV_NUMBER, AL ;SAVE DRV #
1743 ADD AL, BASE_OF_ALPHA_DRV
1744 MOV S_DRV, AL ;save source drive letter
1745 MOV S_DRV_1, AL
1746 MOV S_ARC_DRV, AL
1747 MOV SAV_S_DRV, AL
1748
1749 MOV AL, TAR_DRIVE ;AN000;target drive letter
1750 CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
1751; $IF E ;AN000;YES, GET THE DEFAULT
1752 JNE $$IF185
1753 MOV AL, SAV_DEFAULT_DRV ;AN000;(1=A, 2=B,...)
1754; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
1755 JMP SHORT $$EN185
1756$$IF185:
1757 SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
1758; $ENDIF
1759$$EN185:
1760 MOV T_DRV_NUMBER, AL ;save target drv #
1761
1762 CMP S_DRV_NUMBER, AL ;s_drv_number = t_drv_number?
1763; $IF E
1764 JNE $$IF188
1765 OR SYS_FLAG, ONE_DISK_COPY_FLAG ;same logical drv copy
1766; $ENDIF
1767$$IF188:
1768
1769 ADD AL, BASE_OF_ALPHA_DRV ;make target drv # to drive letter
1770 MOV T_DRV, AL ;target drive letter
1771 MOV T_DRV_1, AL
1772 MOV T_DRV_2, AL
1773 MOV SAV_T_DRV, AL
1774 RET
1775GET_DRIVES ENDP
1776;
1777;
1778GET_CUR_DRV PROC NEAR
1779;get the current default drive number (0 = A, 1 = B ..),
1780;change it to BIOS drive number and save it.
1781 MOV AH, Current_Disk ; = 19h
1782 INT 21h
1783 INC AL ;(1 = A, 2 = B ..)
1784 MOV SAV_DEFAULT_DRV, AL ;save it
1785 RET
1786GET_CUR_DRV ENDP
1787;
1788GET_CUR_DIR PROC NEAR
1789;get current directory and save it
1790;input: DL - drive # (0 = default, 1 = A etc)
1791; DS:SI - pointer to 64 byte user memory
1792
1793 MOV AH, Get_Current_Directory
1794 INT 21H
1795 RET
1796GET_CUR_DIR ENDP
1797;
1798TOP_OF_MEM PROC NEAR
1799;set Top_of_memory
1800
1801 PUSH ES
1802 MOV BX, PSP_SEG
1803 MOV ES, BX
1804 MOV AX, ES:2 ;PSP top of memory location
1805 SUB AX, 140H ;subtract dos transient area (5k)
1806 MOV TOP_OF_MEMORY, AX ;save it for buffer top
1807 POP ES
1808 RET
1809TOP_OF_MEM ENDP
1810
1811INIT_BUFFER PROC NEAR
1812;initialize buffer information
1813;set buffer_base, max_buffer_size
1814; call set_block ;SET BLOCK FOR BUFFR (for new 3.2 linker)
1815 MOV AX, OFFSET INIT
1816 PUSH CS ;cs segment is the highest segment in this program
1817 POP DX
1818 MOV BUFFER_PTR, DX
1819 CALL SET_BUFFER_PTR
1820 MOV AX, BUFFER_PTR
1821 MOV BUFFER_BASE, AX ;set buffer_base
1822 MOV AX, BUFFER_LEFT
1823 CMP AX, 140h ;BUFFER_LEFT < 5K which is the minimum size this program supports?
1824 JAE IB_CONT
1825 PUSH AX ;AN000;
1826 MOV AX, MSG_INSUF_MEMORY ;AC000;GET THE MESSAGE ID
1827 MOV MSG_NUM,AX ;AN000;NEED MESSAGE ID FOR PRINT
1828 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
1829 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
1830 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1831 CALL PRINT_STDERR ;AN000;print error. AX points to msg ID
1832 POP AX ;AN000;
1833 MOV ERRORLEVEL, 4 ;abnormal termination
1834 JMP MAIN_EXIT_A ;terminate this program
1835IB_CONT:
1836 MOV MAX_BUFFER_SIZE, AX ;set max buffer size in para
1837 CMP AX, 0FFFh ;max_buffer_size > 64 K in para ?
1838; $IF B
1839 JNB $$IF190
1840 MOV CX, 16
1841 MUL CX ;AX = AX * 16 (DX part will be 0)
1842 SUB AX, 544 ;AN000;subtract header size
1843 MOV MAX_CX, AX ;this will be max_cx
1844; $ELSE
1845 JMP SHORT $$EN190
1846$$IF190:
1847 MOV MAX_CX, 0FFD0h ;else max_cx = fff0 - 32 bytes
1848 ;which is the max # this program can support.
1849; $ENDIF ;(min # this program support for buffer is 5 k
1850$$EN190:
1851 ; which has been decided by BIG_FILE )
1852 RET
1853INIT_BUFFER ENDP
1854;
1855HOOK_CTRL_BREAK PROC NEAR
1856;
1857 PUSH DS ;save DS
1858 PUSH CS
1859 POP DS ;ds = cs
1860 MOV AX, 2523h
1861 MOV DX, OFFSET CTRL_BREAK_EXIT
1862 INT 21H
1863 POP DS ;restore ds
1864 RET
1865HOOK_CTRL_BREAK ENDP
1866;
1867SAV_HOOK_INT24 PROC NEAR
1868;sav the int_24 addr, and hooks it to my_int24
1869 PUSH ES
1870 MOV AH, 35h
1871 MOV AL, 24h ;get critical error handler addr
1872 INT 21h
1873 MOV SAV_INT24_OFF, BX ;offset ip
1874 MOV SAV_INT24_SEG, ES ;seg cs
1875 POP ES
1876 PUSH DS ;save DS
1877 PUSH CS
1878 POP DS ;ds = cs
1879 MOV AH, 25h
1880 MOV AL, 24h
1881 MOV DX, OFFSET MY_INT24 ;now DS:DX contains the addr.
1882 INT 21h ;hook it to my_int24 routine
1883 POP DS ;restore ds
1884 RET
1885SAV_HOOK_INT24 ENDP
1886;
1887CSEG ENDS
1888 END
1889
1890 \ No newline at end of file