1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
|
TITLE COPYRPOC ;Procedures called by COPY
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN DEVWMES:BYTE,INBDEV:BYTE,NOSPACE:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN CFLAG:BYTE,NXTADD:WORD,DESTCLOSED:BYTE
EXTRN PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
EXTRN WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
EXTRN SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,MELCOPY:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD
EXTRN DESTTAIL:WORD,DESTINFO:BYTE,INEXACT:BYTE
EXTRN DESTVARS:BYTE,SRCINFO:BYTE,RDEOF:BYTE
EXTRN USERDIR1:BYTE,NOWRITE:BYTE
EXTRN SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
PUBLIC SEARCH,SEARCHNEXT,DOCOPY,CLOSEDEST,FLSHFIL,SETASC
PUBLIC BUILDNAME,COPERR
EXTRN PRINT:NEAR,BUILDPATH:NEAR,RESTUDIR1:NEAR
EXTRN COMPNAME:NEAR,ENDCOPY:NEAR
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SEARCHNEXT:
MOV AH,DIR_SEARCH_NEXT
TEST [SRCINFO],2
JNZ SEARCH ; Do serach-next if ambig
OR AH,AH ; Reset zero flag
return
SEARCH:
PUSH AX
MOV AH,SET_DMA
MOV DX,OFFSET TRANGROUP:DIRBUF
INT int_command ; Put result of search in DIRBUF
POP AX ; Restore search first/next command
MOV DX,FCB
INT int_command ; Do the search
OR AL,AL
return
DOCOPY:
mov [RDEOF],0 ; No EOF yet
mov dx,offset trangroup:SRCBUF
mov ax,OPEN SHL 8
INT int_command
retc ; If open fails, ignore
mov bx,ax ; Save handle
mov [SRCHAND],bx ; Save handle
mov ax,(FILE_TIMES SHL 8)
INT int_command
mov [CPDATE],dx ; Save DATE
mov [CPTIME],cx ; Save TIME
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
and dl,devid_ISDEV
mov [SRCISDEV],dl ; Set source info
jz COPYLP ; Source not a device
cmp [BINARY],0
jz COPYLP ; ASCII device OK
mov dx,offset trangroup:INBDEV ; Cannot do binary input
jmp COPERR
COPYLP:
mov bx,[SRCHAND]
mov cx,[BYTCNT]
mov dx,[NXTADD]
sub cx,dx ; Compute available space
jnz GOTROOM
call FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
mov cx,[BYTCNT]
GOTROOM:
push ds
mov ds,[TPA]
ASSUME DS:NOTHING
mov ah,READ
INT int_command
pop ds
ASSUME DS:TRANGROUP
jc CLOSESRC ; Give up if error
mov cx,ax ; Get count
jcxz CLOSESRC ; No more to read
cmp [SRCISDEV],0
jnz NOTESTA ; Is a device, ASCII mode
cmp [ASCII],0
jz BINREAD
NOTESTA:
MOV DX,CX
MOV DI,[NXTADD]
MOV AL,1AH
PUSH ES
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ USEALL
INC [RDEOF]
INC CX
USEALL:
SUB DX,CX
MOV CX,DX
BINREAD:
ADD CX,[NXTADD]
MOV [NXTADD],CX
CMP CX,[BYTCNT] ; Is buffer full?
JB TESTDEV ; If not, we may have found EOF
CALL FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
JMP SHORT COPYLP
TESTDEV:
cmp [SRCISDEV],0
JZ CLOSESRC ; If file then EOF
CMP [RDEOF],0
JZ COPYLP ; On device, go till ^Z
CLOSESRC:
mov bx,[SRCHAND]
mov ah,CLOSE
INT int_command
return
CLOSEDEST:
cmp [DESTCLOSED],0
retnz ; Don't double close
MOV AL,BYTE PTR [DESTSWITCH]
CALL SETASC ; Check for B or A switch on destination
JZ BINCLOS
MOV BX,[NXTADD]
CMP BX,[BYTCNT] ; Is memory full?
JNZ PUTZ
call TRYFLUSH ; Make room for one lousy byte
jz NOCONC
CONCHNG: ; Concat flag changed on us
stc
return
NOCONC:
XOR BX,BX
PUTZ:
PUSH DS
MOV DS,[TPA]
MOV WORD PTR [BX],1AH ; Add End-of-file mark (Ctrl-Z)
POP DS
INC [NXTADD]
MOV [NOWRITE],0 ; Make sure our ^Z gets written
MOV AL,[WRITTEN]
XOR AH,AH
ADD AX,[NXTADD]
JC BINCLOS ; > 1
CMP AX,1
JZ FORGETIT ; WRITTEN = 0 NXTADD = 1 (the ^Z)
BINCLOS:
call TRYFLUSH
jnz CONCHNG
cmp [WRITTEN],0
jz FORGETIT ; Never wrote nothin
MOV BX,[DESTHAND]
MOV CX,[CPTIME]
MOV DX,[CPDATE]
CMP [INEXACT],0 ; Copy not exact?
JZ DODCLOSE ; If no, copy date & time
MOV AH,GET_TIME
INT int_command
SHL CL,1
SHL CL,1 ; Left justify min in CL
SHL CX,1
SHL CX,1
SHL CX,1 ; hours to high 5 bits, min to 5-10
SHR DH,1 ; Divide seconds by 2 (now 5 bits)
OR CL,DH ; And stick into low 5 bits of CX
PUSH CX ; Save packed time
MOV AH,GET_DATE
INT int_command
SUB CX,1980
XCHG CH,CL
SHL CX,1 ; Year to high 7 bits
SHL DH,1 ; Month to high 3 bits
SHL DH,1
SHL DH,1
SHL DH,1
SHL DH,1 ; Most sig bit of month in carry
ADC CH,0 ; Put that bit next to year
OR DL,DH ; Or low three of month into day
MOV DH,CH ; Get year and high bit of month
POP CX ; Get time back
DODCLOSE:
MOV AX,(FILE_TIMES SHL 8) OR 1
INT int_command ; Set date and time
MOV AH,CLOSE
INT int_command
INC [FILECNT]
INC [DESTCLOSED]
RET50:
CLC
return
FORGETIT:
MOV BX,[DESTHAND]
CALL DODCLOSE ; Close the dest
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [FILECNT],0 ; No files transferred
JMP RET50
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:
call BUILDDEST ; Find out all about the destination
CALL 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
JZ COPERRJ ; If not, overwrite error
MOV [NOWRITE],1 ; Flag not writting (just seeking)
PROCDEST:
mov ax,(OPEN SHL 8) OR 1
CMP [NOWRITE],0
JNZ DODESTOPEN ; Don't actually create if NOWRITE set
mov ah,CREAT
xor cx,cx
DODESTOPEN:
mov dx,offset trangroup:DESTBUF
INT int_command
MOV DX,OFFSET TRANGROUP:FULDIR
JC COPERRJ
mov [DESTHAND],ax ; Save handle
mov [CFLAG],1 ; Destination now exists
mov bx,ax
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
mov [DESTISDEV],dl ; Set dest info
test dl,devid_ISDEV
jz EXISTS ; Dest not a device
mov al,BYTE PTR [DESTSWITCH]
AND AL,ASWITCH+BSWITCH
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,BSWITCH
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],ASWITCH ; Set ASCII mode
or [INEXACT],ASWITCH ; ASCII -> INEXACT
EXISTS:
cmp [NOWRITE],0
jnz NOCHECKING ; If nowrite don't bother with name check
CALL 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 ; Tell him he's not going to get it
CALL PRINT
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
JC COPERR ; 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
COPERR:
CALL PRINT
inc [DESTCLOSED]
cmp [CFLAG],0
jz ENDCOPYJ ; Never actually got it open
MOV bx,[DESTHAND]
MOV AH,CLOSE ; Close the file
INT int_command
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [CFLAG],0
ENDCOPYJ:
JMP ENDCOPY
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
return
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,ASWITCH+BSWITCH
JPE LOADSW ; PE means both or neither are set
PUSH AX
AND AL,BSWITCH
MOV [BINARY],AL
POP AX
AND AL,ASWITCH
MOV [ASCII],AL
OR [INEXACT],AL
LOADSW:
MOV AL,[ASCII]
OR AL,AL
return
BUILDDEST:
cmp [DESTISDIR],-1
jnz KNOWABOUTDEST ; Already done the figuring
MOV DI,OFFSET TRANGROUP:USERDIR1
mov bp,offset trangroup:DESTVARS
call BUILDPATH
call 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
mov ax,word ptr [DESTBUF] ; Get drive
cmp ah,':'
jz DRVSPEC4
mov al,'@'
DRVSPEC4:
MOV CL,[ASCII] ; Save current ASCII setting
sub al,'@'
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 concatination
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
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
cmp byte ptr [SI],' '
jz ENDDEST ; No extension
mov al,'.'
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
TRANCODE ENDS
END
|