summaryrefslogtreecommitdiff
path: root/v2.0/source/TCODE5.ASM
blob: 63fb3cfda31fc9cc88803743d63834b32d035c1e (plain) (blame)
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
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
TITLE   PART5 - COMMAND Transient routines.

        INCLUDE COMSW.ASM

.xlist
.xcref
        INCLUDE DOSSYM.ASM
        INCLUDE DEVSYM.ASM
        INCLUDE COMSEG.ASM
.list
.cref

        INCLUDE COMEQU.ASM

CODERES SEGMENT PUBLIC

        IF      IBMVER
        EXTRN   EXEC_WAIT:NEAR
        ENDIF

CODERES ENDS


DATARES SEGMENT PUBLIC
        EXTRN   BATCH:WORD,BATLOC:DWORD,BATBYT:BYTE,ECHOFLAG:BYTE
        EXTRN   SINGLECOM:WORD,RE_OUTSTR:BYTE,PIPEFLAG:BYTE,PIPEPTR:WORD
        EXTRN   RE_INSTR:BYTE,RE_OUT_APP:BYTE,PARMBUF:BYTE,PIPESTR:BYTE
        EXTRN   LTPA:WORD,ENVIRSEG:WORD
DATARES ENDS

TRANDATA        SEGMENT PUBLIC
        EXTRN   PIPEEMES:BYTE,NULPATH:BYTE,NOSPACE:BYTE
        EXTRN   DBACK:BYTE,PROMPT_TABLE:BYTE
TRANDATA        ENDS

TRANSPACE       SEGMENT PUBLIC
        EXTRN   PATHCNT:WORD,PATHPOS:WORD,PATHSW:WORD
        EXTRN   DESTISDIR:BYTE,DESTTAIL:WORD,DESTINFO:BYTE
        EXTRN   BATHAND:WORD,RESSEG:WORD,TPA:WORD,SWITCHAR:BYTE
        EXTRN   BYTCNT:WORD,COMBUF:BYTE,DIRBUF:BYTE,CHARBUF:BYTE


        IF      KANJI
        EXTRN   KPARSE:BYTE
        ENDIF

TRANSPACE       ENDS


TRANCODE        SEGMENT PUBLIC BYTE
ASSUME  CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

        IF      KANJI
        EXTRN   TESTKANJ:NEAR
        ENDIF

        EXTRN   CERROR:NEAR,UPCONV:NEAR,PIPEERRSYN:NEAR,SETREST1:NEAR
        EXTRN   SWITCH:NEAR,SETREST1:NEAR,BATCLOSE:NEAR,MOVE_NAME:NEAR
        EXTRN   FIND_PROMPT:NEAR,FIND_PATH:NEAR,DELETE_PATH:NEAR
        EXTRN   STORE_CHAR:NEAR,SCAN_DOUBLE_NULL:NEAR,SCASB2:NEAR
        EXTRN   PRINT_DRIVE:NEAR,SAVUDIR:NEAR,CRLF2:NEAR,PAUSE:NEAR
 
        PUBLIC  PRINT_B,PRINT_G,DISPSIZE,GETNUM,OUTBYTE
        PUBLIC  DELIM,OUT,OUT2,SETPATH,PATHCRUNCH
        PUBLIC  CRPRINT,SCANOFF,FCB_TO_ASCZ
        PUBLIC  PRINT_L,PATH,PATHCHRCMP,PRINT_ESC,PRINT_BACK
        PUBLIC  PRINT_EQ,PRINT,ZPRINT,PRINT_PROMPT
        PUBLIC  DISP32BITS,ERROR_PRINT,ERROR_OUTPUT
        PUBLIC  FREE_TPA,ALLOC_TPA,PRESCAN,GETBATBYT


FREE_TPA:
ASSUME  DS:TRANGROUP,ES:NOTHING
        PUSH    ES
        MOV     ES,[TPA]
        MOV     AH,DEALLOC
        INT     int_command             ; Make lots of free memory
        POP     ES
        return

ALLOC_TPA:
ASSUME DS:TRANGROUP,ES:RESGROUP
        MOV     BX,0FFFFH       ; Re-allocate the transient
        MOV     AH,ALLOC
        INT     int_command
        MOV     AH,ALLOC
        INT     int_command
        MOV     [LTPA],AX       ; Re-compute evrything
        MOV     [TPA],AX
        MOV     BX,AX
        MOV     AX,CS
        SUB     AX,BX
        MOV     DX,16
        MUL     DX
        OR      DX,DX
        JZ      SAVSIZ2
        MOV     AX,-1
SAVSIZ2:
        MOV     [BYTCNT],AX
        return


PRESCAN:                        ; Cook the input buffer
ASSUME  DS:TRANGROUP,ES:TRANGROUP
        XOR     CX,CX
        MOV     ES,[RESSEG]
ASSUME  ES:RESGROUP
        MOV     SI,OFFSET TRANGROUP:COMBUF+2
        MOV     DI,SI

CountQuotes:
        LODSB                           ; get a byte
        CMP     AL,22h                  ; is it a quote?
        JNZ     CountEnd                ; no, try for end of road
        INC     CH                      ; bump count
        JMP     CountQuotes             ; go get next char
CountEnd:
        CMP     AL,13                   ; end of road?
        JNZ     CountQuotes             ; no, go back for next char

        IF      KANJI
        PUSH    CX                      ; save count
        MOV     SI,DI                   ; get back beginning of buffer
KanjiScan:
        LODSB                           ; get a byte
        CALL    TestKanj                ; is it a leadin byte
        JZ      KanjiQuote              ; no, check for quotes
        MOV     AH,AL                   ; save leadin
        LODSB                           ; get trailing byte
        CMP     AX,8140h                ; is it Kanji space
        JNZ     KanjiScan               ; no, go get next
        MOV     [SI-2],2020h            ; replace with spaces
        JMP     KanjiScan               ; go get next char
KanjiQuote:
        CMP     AL,22h                  ; beginning of quoted string
        JNZ     KanjiEnd                ; no, check for end
        DEC     CH                      ; drop count
        JZ      KanjiScan               ; if count is zero, no quoting
KanjiQuoteLoop:
        LODSB                           ; get next byte
        CMP     AL,22h                  ; is it another quote
        JNZ     KanjiQuoteLoop          ; no, get another
        DEC     CH                      ; yes, drop count
        JMP     KanjiScan               ; go get next char
KanjiEnd:
        CMP     AL,13                   ; end of line character?
        JNZ     KanjiScan               ; go back to beginning
        POP     CX                      ; get back original count
        ENDIF

        MOV     SI,DI                   ; restore pointer to begining
PRESCANLP:
        LODSB

        IF      KANJI
        CALL    TESTKANJ
        JZ      NOTKANJ6
        MOV     [DI],AL
        INC     DI                      ; fake STOSB into DS
        LODSB                           ; grab second byte
        MOV     [DI],AL                 ; fake stosb into DS
        INC     DI
        INC     CL
        INC     CL
        JMP     PRESCANLP
NOTKANJ6:
        ENDIF

        CMP     AL,22H          ; " character
        JNZ     TRYGREATER
        DEC     CH
        JZ      TRYGREATER
QLOOP:
        MOV     [DI],AL
        INC     DI
        INC     CL
        LODSB
        CMP     AL,22H          ; " character
        JNZ     QLOOP
        DEC     CH

TRYGREATER:
        CMP     AL,'>'
        JNZ     NOOUT
        CMP     BYTE PTR [SI],'>'
        JNZ     NOAPPND
        LODSB
        INC     [RE_OUT_APP]            ; Flag >>
NOAPPND:
        CALL    SCANOFF
        CMP     AL,0DH
        JNZ     GOTREOFIL
        MOV     WORD PTR [RE_OUTSTR],09H     ; Cause an error later
        JMP     SHORT PRESCANEND
GOTREOFIL:
        PUSH    DI
        MOV     DI,OFFSET RESGROUP:RE_OUTSTR
SETREOUTSTR:                            ; Get the output redirection name
        LODSB
        CMP     AL,0DH
        JZ      GOTRESTR
        CALL    DELIM
        JZ      GOTRESTR
        CMP     AL,[SWITCHAR]
        JZ      GOTRESTR
        STOSB                           ; store it into resgroup
        JMP     SHORT SETREOUTSTR

NOOUT:
        CMP     AL,'<'
        JNZ     CHKPIPE
        CALL    SCANOFF
        CMP     AL,0DH
        JNZ     GOTREIFIL
        MOV     WORD PTR [RE_INSTR],09H ; Cause an error later
        JMP     SHORT PRESCANEND
GOTREIFIL:
        PUSH    DI
        MOV     DI,OFFSET RESGROUP:RE_INSTR
        JMP     SHORT SETREOUTSTR       ; Get the input redirection name

CHKPIPE:
        MOV     AH,AL
        CMP     AH,'|'
        JNZ     CONTPRESCAN
        INC     [PIPEFLAG]
        CALL    SCANOFF
        CMP     AL,0DH
        JZ      PIPEERRSYNJ5
        CMP     AL,'|'          ; Double '|'?
        JNZ     CONTPRESCAN
PIPEERRSYNJ5:
        PUSH    ES
        POP     DS              ; DS->RESGROUP
        JMP     PIPEERRSYN

GOTRESTR:
        XCHG    AH,AL
        CMP     BYTE PTR ES:[DI-1],':'  ; Trailing ':' OK on devices
        JNZ     NOTTRAILCOL
        DEC     DI              ; Back up over trailing ':'
NOTTRAILCOL:
        XOR     AL,AL
        STOSB                   ; NUL terminate the string
        POP     DI              ; Remember the start
CONTPRESCAN:
        MOV     [DI],AH         ; "delete" the redirection string
        INC     DI
        CMP     AH,0DH
        JZ      PRESCANEND
        INC     CL
        JMP     PRESCANLP
PRESCANEND:
        CMP     [PIPEFLAG],0
        JZ      ISNOPIPE
        MOV     DI,OFFSET RESGROUP:PIPESTR
        MOV     [PIPEPTR],DI
        MOV     SI,OFFSET TRANGROUP:COMBUF+2
        CALL    SCANOFF
PIPESETLP:                      ; Transfer the pipe into the resident pipe buffer
        LODSB
        STOSB
        CMP     AL,0DH
        JNZ     PIPESETLP
ISNOPIPE:
        MOV     [COMBUF+1],CL
        CMP     [PIPEFLAG],0
        PUSH    CS
        POP     ES
        return

ASSUME  DS:TRANGROUP,ES:TRANGROUP

PATHCHRCMP:
        CMP     [SWITCHAR],'/'
        JZ      NOSLASHT
        CMP     AL,'/'
        retz
NOSLASHT:
        CMP     AL,'\'
        return

PATHCRUNCH:
; Drive taken from FCB
; DI = Dirsave pointer
;
; Zero set if path dir, CHDIR to this dir, FCB filled with ?
; NZ set if path/file, CHDIR to file, FCB has file (parsed fill ' ')
;       [DESTTAIL] points to parse point
; Carry set if no CHDIRs worked, FCB not altered.
; DESTISDIR set non zero if PATHCHRs in path (via SETPATH)

        MOV     DL,DS:[FCB]
        CALL    SAVUDIR
        CALL    SETPATH
        TEST    [DESTINFO],2
        JNZ     TRYPEEL         ; If ? or * cannot be pure dir
        MOV     AH,CHDIR
        INT     int_command
        JC      TRYPEEL
        CALL    SETREST1
        MOV     AL,"?"          ; *.* is default file spec if pure dir
        MOV     DI,5DH
        MOV     CX,11
        REP     STOSB
        XOR     AL,AL           ; Set zero
        return

TRYPEEL:
        MOV     SI,[PATHPOS]
        DEC     SI              ; Point at NUL
        MOV     AL,[SI-1]

        IF      KANJI
        CMP     [KPARSE],0
        JNZ     DELSTRT         ; Last char is second KANJI byte, might be '\'
        ENDIF

        CALL    PATHCHRCMP
        JZ      PEELFAIL                ; Trailing '/'

        IF      KANJI
DELSTRT:
        MOV     CX,SI
        MOV     SI,DX
        PUSH    DX
DELLOOP:
        CMP     SI,CX
        JZ      GOTDELE
        LODSB
        CALL    TESTKANJ
        JZ      NOTKANJ8
        INC     SI
        JMP     DELLOOP

NOTKANJ8:
        CALL    PATHCHRCMP
        JNZ     DELLOOP
        MOV     DX,SI
        DEC     DX
        JMP     DELLOOP

GOTDELE:
        MOV     SI,DX
        POP     DX
        CMP     SI,DX
        JZ      BADRET
        MOV     CX,SI
        MOV     SI,DX
DELLOOP2:                       ; Set value of KPARSE
        CMP     SI,CX
        JZ      KSET
        MOV     [KPARSE],0
        LODSB
        CALL    TESTKANJ
        JZ      DELLOOP2
        INC     SI
        INC     [KPARSE]
        JMP     DELLOOP2

KSET:
        ELSE
DELLOOP:
        CMP     SI,DX
        JZ      BADRET
        MOV     AL,[SI]
        CALL    PATHCHRCMP
        JZ      TRYCD
        DEC     SI
        JMP     SHORT DELLOOP
        ENDIF

TRYCD:
        CMP     BYTE PTR [SI+1],'.'
        JZ      PEELFAIL                ; If . or .., pure cd should have worked
        mov     al,[si-1]
        CMP     al,DRVCHAR                  ; Special case dDRVCHAR,DIRCHARfile
        JZ      BADRET

        IF      KANJI
        CMP     [KPARSE],0
        JNZ     NOTDOUBLESL     ; Last char is second KANJI byte, might be '\'
        ENDIF

        CALL    PATHCHRCMP
        JNZ     NOTDOUBLESL
PEELFAIL:
        STC                                 ; //
        return
NOTDOUBLESL:
        MOV     BYTE PTR [SI],0
        MOV     AH,CHDIR
        INT     int_command
        JNC     CDSUCC
        return

BADRET:
        MOV     AL,[SI]
        CALL    PATHCHRCMP              ; Special case 'DIRCHAR'file
        STC
        retnz
        XOR     BL,BL
        XCHG    BL,[SI+1]
        MOV     AH,CHDIR
        INT     int_command
        retc
        MOV     [SI+1],BL
CDSUCC:
        CALL    SETREST1
        INC     SI                      ; Reset zero
        MOV     [DESTTAIL],SI
        MOV     DI,FCB
        MOV     AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H   ; Parse with default drive
        INT     int_command
        return


DISPSIZE:
        MOV     SI,WORD PTR[DIRBUF+29+7]
        MOV     DI,WORD PTR[DIRBUF+31+7]

DISP32BITS:
; Prints the 32-bit number DI:SI on the console in decimal. Uses a total
; of 9 digit positions with leading blanks.
        XOR     AX,AX
        MOV     BX,AX
        MOV     BP,AX
        MOV     CX,32
CONVLP:
        SHL     SI,1
        RCL     DI,1
        XCHG    AX,BP
        CALL    CONVWRD
        XCHG    AX,BP
        XCHG    AX,BX
        CALL    CONVWRD
        XCHG    AX,BX
        ADC     AL,0
        LOOP    CONVLP

; Conversion complete. Print 9-digit number.

        MOV     DI,OFFSET TRANGROUP:CHARBUF
        MOV     CX,1810H        ; Allow leading zero blanking for 8 digits
        XCHG    DX,AX
        CALL    DIGIT
        XCHG    AX,BX
        CALL    OUTWORD
        XCHG    AX,BP
        CALL    OUTWORD
        XOR     AX,AX
        STOSB
        MOV     DX,OFFSET TRANGROUP:CHARBUF
        JMP     ZPRINT

OUTWORD:
        PUSH    AX
        MOV     DL,AH
        CALL    OUTBYTE
        POP     DX
OUTBYTE:
        MOV     DH,DL
        SHR     DL,1
        SHR     DL,1
        SHR     DL,1
        SHR     DL,1
        CALL    DIGIT
        MOV     DL,DH
DIGIT:
        AND     DL,0FH
        JZ      BLANKZER
        MOV     CL,0
BLANKZER:
        DEC     CH
        AND     CL,CH
        OR      DL,30H
        SUB     DL,CL
        MOV     AL,DL
        STOSB
        return

CONVWRD:
        ADC     AL,AL
        DAA
        XCHG    AL,AH
        ADC     AL,AL
        DAA
        XCHG    AL,AH
        return


GETBATBYT:
; Get one byte from the batch file and return it in AL. End-of-file
; returns <CR> and ends batch mode. DS must be set to resident segment.
; AH, CX, DX destroyed.
ASSUME  DS:RESGROUP
        ADD     WORD PTR [BATLOC],1     ; Add one to file location
        ADC     WORD PTR [BATLOC+2],0
        PUSH    BX
        MOV     DX,OFFSET RESGROUP:BATBYT
        MOV     BX,[BATHAND]
        MOV     AH,READ
        MOV     CX,1
        INT     int_command              ; Get one more byte from batch file
        POP     BX
        MOV     CX,AX
        JC      BATEOF
        JCXZ    BATEOF
        MOV     AL,[BATBYT]
        CMP     AL,1AH
        retnz
BATEOF:
        PUSH    ES
        MOV     ES,[BATCH]      ; Turn off batch
        MOV     AH,DEALLOC
        INT     int_command             ; free up the batch piece
        POP     ES
        MOV     [BATCH],0       ; AFTER DEALLOC in case of ^C
        CALL    BATCLOSE
        MOV     AL,0DH          ; If end-of-file, then end of line
        CMP     [SINGLECOM],0FFF0H      ; See if we need to set SINGLECOM
        JNZ     NOSETSING2
        MOV     [SINGLECOM],-1  ; Cause termination
NOSETSING2:
        MOV     [ECHOFLAG],1
        return
ASSUME  DS:TRANGROUP

SCANOFF:
        LODSB
        CALL    DELIM
        JZ      SCANOFF
        DEC     SI              ; Point to first non-delimiter
        return

DELIM:
        CMP     AL," "
        retz
        CMP     AL,"="
        retz
        CMP     AL,","
        retz
        CMP     AL,";"
        retz
        CMP     AL,9            ; Check for TAB character
        return


PRINT_PROMPT:
        PUSH    DS
        PUSH    CS
        POP     DS              ; MAKE SURE DS IS IN TRANGROUP

        PUSH    ES
        CALL    FIND_PROMPT     ; LOOK FOR PROMPT STRING
        JC      PP0             ; CAN'T FIND ONE
        CMP     BYTE PTR ES:[DI],0
        JNZ     PP1
PP0:
        CALL    PRINT_DRIVE     ; USE DEFAULT PROMPT
        MOV     AL,SYM
        CALL    OUT
        JMP     SHORT PP5

PP1:
        MOV     AL,ES:[DI]      ; GET A CHAR
        INC     DI
        OR      AL,AL
        JZ      PP5             ; NUL TERMINATED
        CMP     AL,"$"          ; META CHARACTER?
        JZ      PP2             ; NOPE
PPP1:
        CALL    OUT
        JMP     PP1

PP2:
        MOV     AL,ES:[DI]
        INC     DI
        MOV     BX,OFFSET TRANGROUP:PROMPT_TABLE-3
        OR      AL,AL
        JZ      PP5

PP3:
        ADD     BX,3
        CALL    UPCONV
        CMP     AL,[BX]
        JZ      PP4
        CMP     BYTE PTR [BX],0
        JNZ     PP3
        JMP     PP1

PP4:
        PUSH    ES
        PUSH    DI
        PUSH    CS
        POP     ES
        CALL    [BX+1]
        POP     DI
        POP     ES
        JMP     PP1

PP5:
        POP     ES              ; RESTORE SEGMENTS
        POP     DS
        return

PRINT_BACK:
        MOV     DX,OFFSET TRANGROUP:DBACK
        JMP     ZPRINT

PRINT_EQ:
        MOV     AL,"="
        JMP     SHORT OUTV
PRINT_ESC:
        MOV     AL,1BH
        JMP     SHORT OUTV
PRINT_G:
        MOV     AL,">"
        JMP     SHORT OUTV
PRINT_L:
        MOV     AL,"<"
        JMP     SHORT OUTV
PRINT_B:
        MOV     AL,"|"
OUTV:
        JMP     OUT

SETPATH:
; Get an ASCIZ argument from the unformatted parms
; DESTISDIR set if pathchars in string
; DESTINFO  set if ? or * in string
        MOV     SI,80H
        LODSB
        XOR     AH,AH
        MOV     [PATHCNT],AX
        MOV     [PATHPOS],SI
GETPATH:
        MOV     [DESTINFO],0
        MOV     [DESTISDIR],0
        MOV     SI,[PATHPOS]
        MOV     CX,[PATHCNT]
        MOV     DX,SI
        JCXZ    PATHDONE
        PUSH    CX
        PUSH    SI
        CALL    SWITCH
        MOV     [PATHSW],AX
        POP     BX
        SUB     BX,SI
        POP     CX
        ADD     CX,BX
        MOV     DX,SI
SKIPPATH:

        IF      KANJI
        MOV     [KPARSE],0
SKIPPATH2:
        ENDIF

        JCXZ    PATHDONE
        DEC     CX
        LODSB

        IF      KANJI
        CALL    TESTKANJ
        JZ      TESTPPSEP
        DEC     CX
        INC     SI
        INC     [KPARSE]
        JMP     SKIPPATH2

TESTPPSEP:
        ENDIF

        CALL    PATHCHRCMP
        JNZ     TESTPMETA
        INC     [DESTISDIR]
TESTPMETA:
        CMP     AL,'?'
        JNZ     TESTPSTAR
        OR      [DESTINFO],2
TESTPSTAR:
        CMP     AL,'*'
        JNZ     TESTPDELIM
        OR      [DESTINFO],2
TESTPDELIM:
        CALL    DELIM
        JZ      PATHDONEDEC
        CMP     AL,[SWITCHAR]
        JNZ     SKIPPATH
PATHDONEDEC:
        DEC     SI
PATHDONE:
        XOR     AL,AL
        XCHG    AL,[SI]
        INC     SI
        CMP     AL,0DH
        JNZ     NOPSTORE
        MOV     [SI],AL       ;Don't loose the CR
NOPSTORE:
        MOV     [PATHPOS],SI
        MOV     [PATHCNT],CX
        return

PGETARG:
        MOV     SI,80H
        LODSB
        OR      AL,AL
        retz
        CALL    PSCANOFF
        CMP     AL,13
        return

PSCANOFF:
        LODSB
        CALL    DELIM
        JNZ     PSCANOFFD
        CMP     AL,';'
        JNZ     PSCANOFF        ; ';' is not a delimiter
PSCANOFFD:
        DEC     SI              ; Point to first non-delimiter
        return

PATH:
        CALL    FIND_PATH
        CALL    PGETARG         ; Pre scan for arguments
        JZ      DISPPATH        ; Print the current path
        CALL    DELETE_PATH     ; DELETE ANY OFFENDING NAME
        CALL    SCAN_DOUBLE_NULL
        CALL    MOVE_NAME       ; MOVE IN PATH=
        CALL    PGETARG
        CMP     AL,';'          ; NUL path argument?
        JZ      GOTPATHS
PATHSLP:                        ; Get the user specified path
        LODSB
        CMP     AL,0DH
        JZ      GOTPATHS

        IF      KANJI
        CALL    TESTKANJ
        JZ      NOTKANJ2
        CALL    STORE_CHAR
        LODSB
        CALL    STORE_CHAR
        JMP     SHORT PATHSLP

NOTKANJ2:
        ENDIF

        CALL    UPCONV
        CMP     AL,';'          ; ';' not a delimiter on PATH
        JZ      NOTDELIM
        CALL    DELIM
        JZ      GOTPATHS
NOTDELIM:
        CALL    STORE_CHAR
        JMP     SHORT PATHSLP

GOTPATHS:
        XOR     AX,AX
        STOSW
        return

DISPPATH:
        CALL    PRINT_PATH
        CALL    CRLF2
        return

PRINT_PATH:
        CMP     BYTE PTR ES:[DI],0
        JNZ     PATH1
PATH0:
        MOV     DX,OFFSET TRANGROUP:NULPATH
        PUSH    CS
        POP     DS
        JMP     PRINT
PATH1:
        PUSH    ES
        POP     DS
        SUB     DI,5
        MOV     DX,DI
ASSUME  DS:RESGROUP
        CALL    SCASB2                  ; LOOK FOR NUL
        CMP     CX,0FFH
        JZ      PATH0
        JMP     ZPRINT

FCB_TO_ASCZ:                            ; Convert DS:SI to ASCIZ ES:DI
        MOV     CX,8
MAINNAME:
        LODSB
        CMP     AL,' '
        JZ      SKIPSPC
        STOSB
SKIPSPC:
        LOOP    MAINNAME
        LODSB
        CMP     AL,' '
        JZ      GOTNAME
        MOV     AH,AL
        MOV     AL,'.'
        STOSB
        XCHG    AL,AH
        STOSB
        MOV     CL,2
EXTNAME:
        LODSB
        CMP     AL,' '
        JZ      GOTNAME
        STOSB
        LOOP    EXTNAME

GOTNAME:
        XOR     AL,AL
        STOSB
        return

GETNUM:
        CALL    INDIG
        retc
        MOV     AH,AL           ; Save first digit
        CALL    INDIG           ; Another digit?
        JC      OKRET
        AAD                     ; Convert unpacked BCD to decimal
        MOV     AH,AL
OKRET:
        OR      AL,1
        return

INDIG:
        MOV     AL,BYTE PTR[SI]
        SUB     AL,"0"
        retc
        CMP     AL,10
        CMC
        retc
        INC     SI
        return


OUT2:   ; Output binary number as two ASCII digits
        AAM                     ; Convert binary to unpacked BCD
        XCHG    AL,AH
        OR      AX,3030H        ; Add "0" bias to both digits
        CMP     AL,"0"          ; Is MSD zero?
        JNZ     NOSUP
        SUB     AL,BH           ; Suppress leading zero if enabled
NOSUP:
        MOV     BH,0            ; Disable zero suppression
        STOSW
        return

OUT:
; Print char in AL without affecting registers
        XCHG    AX,DX
        PUSH    AX
        CALL    OUT_CHAR
        POP     AX
        XCHG    AX,DX
        return

OUT_CHAR:
        PUSH    DS
        PUSH    DX
        PUSH    CX
        PUSH    BX
        PUSH    AX
        PUSH    CS
        POP     DS
        MOV     BX,OFFSET TRANGROUP:CHARBUF
        MOV     [BX],DL
        MOV     DX,BX
        MOV     BX,1
        MOV     CX,BX
        MOV     AH,WRITE
        INT     int_command
        POP     AX
        POP     BX
        POP     CX
        POP     DX
        POP     DS
        return


ERROR_PRINT:
        PUSH    AX
        PUSH    BX
        MOV     AL,"$"
        MOV     BX,2            ;STD ERROR
        JMP     SHORT STRING_OUT

CRPRINT:
        PUSH    AX
        MOV     AL,13
        JMP     SHORT Z$PRINT
PRINT:                          ;$ TERMINATED STRING
        PUSH    AX
        MOV     AL,"$"
        JMP     SHORT Z$PRINT
ZPRINT:
        PUSH    AX
        XOR     AX,AX           ;NUL TERMINATED STRING
Z$PRINT:
        PUSH    BX
        MOV     BX,1            ;STD CON OUT
;
; output string terminated by AL to handle BX, DS:DX points to string
;
STRING_OUT:
        PUSH    CX
        PUSH    DI
        MOV     DI,DX
        MOV     CX,-1
        PUSH    ES
        PUSH    DS
        POP     ES
        REPNZ   SCASB           ; LOOK FOR TERMINATOR
        POP     ES
        NEG     CX
        DEC     CX
        DEC     CX
;
; WRITE CHARS AT DS:DX TO HANDLE IN BX, COUNT IN CX
;
        MOV     AH,WRITE
        INT     int_command
        JC      ERROR_OUTPUT
        CMP     AX,CX
        JNZ     ERROR_OUTPUT
        POP     DI
        POP     CX
        POP     BX
        POP     AX
        return

ERROR_OUTPUT:
        PUSH    CS
        POP     DS
ASSUME  DS:TRANGROUP
        MOV     ES,[RESSEG]
ASSUME  ES:RESGROUP
        MOV     DX,OFFSET TRANGROUP:NOSPACE
        CMP     [PIPEFLAG],0
        JZ      GO_TO_ERROR
        MOV     [PIPEFLAG],0
        MOV     DX,OFFSET TRANGROUP:PIPEEMES
GO_TO_ERROR:
        JMP     CERROR


TRANCODE    ENDS
            END