Repository navigation
Expand file tree
/
Copy pathcall.asm
More file actions
5274 lines (4994 loc) · 97.7 KB
/
Copy pathcall.asm
File metadata and controls
5274 lines (4994 loc) · 97.7 KB
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
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
keep obj/call
mcopy call.macros
copy sh.dp
****************************************************************
*
* ShellCall - Shell Command Dispatcher
*
* Inputs:
* TOS - command code
* TOS-2 - address of DCB
*
****************************************************************
*
ShellCall start
debug ShellCall
using Common
num_calls equ $1F number of calls
;
; See if the call belongs to us - if so, high byte is $01.
;
phb save user's data bank
php
sta >la save user's A (for QUIT call only)
long I use long regs
short M make sure data bank matches program bank
lda 5,s
pha
plb
long M
phy save his Y
ldy #1 get the call number
lda (5,S),Y
cmp #$0029 branch if QUIT call
jeq Quit
cmp #$2029 branch if QUIT call
jeq OSQuit
cmp #$2027 branch if OSGetName call
jeq OSGetName
;
; Any calls that can change a file must be intercepted and checked against
; the files in the FastFile system. If any match, the file is removed from
; the FastFile system.
;
and #$DFFF if the call is DESTROY, CHANGE_PATH,
cmp #$0002 SET_FILE_INF0, or OPEN, wipe out any
beq dp1 files in FASTFILES list
cmp #$0004
beq dp1
cmp #$0005
beq dp1
cmp #$0010
jne dp3
lda #2
bra dp2
dp1 lda #0
dp2 phx see if this is a class 1 call
pha
ldy #1
lda (9,S),Y
and #$2000
sta >isClass1
pla
clc get addr of the call
ldy #3
adc (7,S),Y
tax
ldy #5
lda (7,S),Y
adc #0
tay
lda >isClass1 if this is a class 1 call, add 2 bytes
beq pc2 to account for the pCount field
inx
bne pc1
iny
pc1 inx
bne pc2
iny
pc2 phd set up our DP
phb set up local addressing
phk
plb
lda sh_my_dp
tcd
ph4 r8 get some work space
ph4 r4
ph4 r0
sty r6 save the addr of the file name ptr
stx r4
lda filelist skip if nothing in file list
ora filelist+2
jeq ff5
ldy #2 get the file name ptr
lda [r4]
sta r0
lda [r4],Y
sta r2
stz tp1 tp1 = nil
stz tp1+2
lda isClass1 if this is a class 0 call then
bne pc3
ph4 r0 convert the name to an OS string
jsl PtoOSString
sta tp1
sta r0
stx tp1+2
stx r2
ora r2
jeq ff5
pc3 move4 r0,epIn expand the path name
ph4 #epRec
jsr ExpandPath
free tp1 if we allocated a buffer, trash it
add4 epPathname,#2,r0 get a file pointer
move4 filelist,r4 get initial fastfile pointer
ff1 lda r4 while there are files to check do
ora r6
beq ff5
ldy #18 get the address of the path name
lda [r4],Y
pha
ldy #16
lda [r4],Y
pha
ph4 r0 if the file names match then
jsl CompareOSStrings
tay
bne ff3
ldy #10 if the file may be purged then
lda [r4],Y
and #$4000
beq ff5
ldy #14 dispose of the handle
lda [r4],Y
pha
lda #0
sta [r4],Y
ldy #12
lda [r4],Y
pha
lda #0
sta [r4],Y
_DisposeHandle
bra ff5 exit while loop
ff3 long M
ff4 ldy #2 next file...
lda [r4]
tax
lda [r4],Y
sta r6
stx r4
bra ff1
ff5 pl4 r0 restore regs, DP
pl4 r4
pl4 r8
free epPathname
plb
pld
plx
lda #0 make sure we make the call
;
; Handle a call to us
;
dp3 ply
and #$FF00 branch if is a call to ORCA/HOST
cmp #$0100
jeq oh1
plp patch things up
plb
ProDOS entry pass the call to ProDOS
ds 4 (JML to ProDOS placed here by TrapProDOS)
;
; Handle a ProDOS QUIT call
;
OSQuit sta >quitNum
lda #$FFFF
sta >quitAnd
sec
bra os1
Quit sta >quitNum
lda #$00FF
sta >quitAnd
clc
os1 ldy #5 get the dcb address
lda (5,S),Y
tax
dey
dey
lda (5,S),Y
phx
pha
phd set up DP addressing to it
tsc
tcd
bcc os2 if this is an OSQuit then
lda [3] if there are no parms then
beq qt1 quit now
inc 3 skip the pCount field
inc 3
os2 ldy #2 if there is a file name, quit to it
lda [3]
ora [3],Y
beq qt1
lda [3],Y
tax
lda [3]
tay
sta 3
stx 5
lda [3]
and >quitAnd
beq qt1
phk set up our data bank, DP
plb
lda sh_my_dp
tcd
sty r0 save addr of file name
stx r2
lda quitNum if this is a class 1 quit then
cmp #$2029
bne qq2
ldy #254 save the GS/OS path name
qq1 lda [r0],Y
sta buff1,Y
dey
dey
bpl qq1
bra qq4 else
qq2 ldy #64 move the ProDOS path name
qq3 lda [r0],Y
sta buff1+1,Y
dey
dey
bpl qq3
lda buff1+1 convert to a class 1 name
and #$00FF
sta buff1
qq4 anop endif
jsl ShutDownApp shut down the active application
lda user_call_stack restore our stack
tcs
lda #buff1 quit to the file
ldx #^buff1
jmp sys16_2
qt1 pld
pla
pla
lda >user_call_stack
tcs
lda >la
rtl
;
; Handle a ProDOS OSGetName call
;
OSGetName anop
ldy #5 get the dcb address
lda (5,S),Y
tax
dey
dey
lda (5,S),Y
phx
pha
phd set up DP addressing to it
tsc
tcd
phk use local addressing
plb
lda [3] check the pCount field
dec A
bne ge1
ldy #4 get the pathname address
lda [3],Y
tax
dey
dey
lda [3],Y
sta 3
stx 5
ora 3
beq ge2
clc check the output buffer size
lda appName
adc #3
cmp [3]
bge ge3
ldy appName move the name to the output buffer
iny
tyx
iny
iny
short M
gn1 lda appName,X
sta [3],Y
dey
dex
bpl gn1
long M
stz err no error
gn2 add4 11,#6 return to caller
pld
pla
pla
ply
plp
plb
clc
lda >err
beq gn3
sec
gn3 rtl
ge1 lda #4 parameter count out of range
bne ge4
ge2 lda #$53 invalid parameter
bne ge4
ge3 lda #$4F buffer too small
ge4 sta err
bra gn2
err ds 2 error code
;
; Call the ORCA/HOST handler.
;
oh1 phx save the caller's registers
phy (B has already been pushed)
phd
phk set data bank to our program bank
plb
lda sh_my_dp switch to our direct page
tcd
cld enforce sanity
move4 r0,lr0 save r0
clc get & update return addr
lda 9,s
sta r0
adc #6
sta 9,s
lda 11,s
sta r2
adc #0
sta 11,s
ldy #1 get call number
lda [r0],Y
sta sh_fnum
iny get addr of dcb
iny
lda [r0],Y
sta sh_dadr
iny
lda [r0],Y
sta sh_dadr+1
lda lr0 restore r0
sta r0
lda lr2
sta r2
ldy #max_dcb-2 copy over DCB to local area
oh2 lda [sh_dadr],Y
tyx
sta sh_dcb,X
dey
dbpl Y,oh2
lda sh_fnum get address of command handler
and #$003F
cmp #num_calls
bgt bad
asl A
tax
jmp (shellcom-2,X) handle the command
;
; Return with bad command number error
;
bad return #1 ProDOS Invalid call number
;
; Local data
;
ch ds 2 uppercase character buffer
isClass1 ds 2 is this a class 1 call?
quitAnd ds 2 Quit call AND mask
quitNum ds 2 Quit call number
shellcom anop
dc a'GetLInfo' get linfo
dc a'SetLInfo' set linfo
dc a'GetLanguage' get language
dc a'SetLanguage' set language
dc a'Error' error handler
dc a'SetVariable' set a variable
dc a'Version' version number
dc a'ReadIndexed' indexed read of a variable
dc a'InitWildcard' initialize wildcard
dc a'NextWildcard' next wildcard
dc a'ReadVariable' read a variable
dc a'ChangeVector' change a vector
dc a'Execute' execute
dc a'FastFile' fast file handler
dc a'Direction' direction of I/O
dc a'Redirect' redirect I/O
dc a'BAD'
dc a'BAD'
dc a'Stop' stop
dc a'ExpDevice' expand devices
dc a'Unset' unset a variable
dc a'Export' export a variable
dc a'PopVariables' pop a variable table
dc a'PushVariables' push a variable table
dc a'SetStop' set the stop flag
dc a'CharOut' pascal console output
dc a'SetDevices' set console devices
dc a'GetDevices' get console devices
dc a'GetCommand' get a command table entry
dc a'KeyPress' see if a keypress is available
dc a'ReadKey' read the next available key
la ds 2 A reg
lr0 ds 2 local copies of r0, r2
lr2 ds 2
tp1 ds 4 temp pointer
epRec dc i'3' expand path record
epIn ds 4
epPathname ds 4
dc i'0'
end
****************************************************************
*
* StackShellCall - Stack Based Shell Command Dispatcher
*
****************************************************************
*
StackShellCall start
debug StackShellCall
using Common
php save the reg sizes
long I,M use long registers
lda 5,S
and #$FF00 if this call should be intercepted then
cmp #$0100
beq lb3
cmp #$2000
bne lb1
lda 5,S
and #$00FF
bra lb2
lb1 lda 5,S
lb2 cmp #$0029
beq lb3
cmp #$0002
beq lb3
cmp #$0004
beq lb3
cmp #$0005
beq lb3
cmp #$0027
beq lb3
cmp #$0010
bne lb4
lb3 plx pull P & the return addr from the stack
ply
pla set up an in-line call
sta >callNum
pla
sta >rec
pla
sta >rec+2
phy restore P & the address
phx
plp switch back to the caller's size
jsl ShellCall go handle the intercepted call
callNum ds 2 (call number)
rec ds 4 (ptr to call record)
rtl return to the caller
lb4 plp let GS/OS do it
StackProDOS entry ProDOS stack entry point
ds 4 (JML to ProDOS placed here by TramProDOS)
end
****************************************************************
*
* ChangeVector - Change one of the user modifiable vectors
*
* Inputs:
* SH_DADR - address of original DCB
* SH_DCB - copy of call DCB
*
* DCB:
* Disp Length Name Use
* ==== ====== ==== ===
* 0 2 RESERVED for future expansion of vector types
* 2 2 VECTOR number of the vector to change
* 4 4 PROCPTR pointer to the new location
* 8 4 OLDPROCPTR old value, so user can change back
*
****************************************************************
*
ChangeVector private
using Common
using reccom
d_reserved equ 0 disp to reserved field
d_vector equ 2 disp to vector number
d_procptr equ 4 disp to proc ptr
d_oldprocptr equ 8 disp to old proc ptr field
lda sh_fnum if this is a class 1 call then
and #$40
beq lb3
lda sh_dcb if pCount <> 4 then
cmp #4
beq lb1
return #4 return invalid pCount error
lb1 ldx #0 change the call to a class 0 call
ldy #6
lb2 lda sh_dcb+2,X
sta sh_dcb,X
inx
inx
dey
bne lb2
add4 sh_dadr,#2
lb3 lda sh_dcb+d_vector compute a disp into the vector table
asl a
asl a
tax
lda edit_vector+3,X save the old vector
and #$00FF
ldy #d_oldprocptr+2
sta [sh_dadr],Y
dey
dey
lda edit_vector+1,X
sta [sh_dadr],Y
lda sh_dcb+d_procptr set the new vector
sta edit_vector+1,X
lda sh_dcb+d_procptr+1
sta edit_vector+2,X
return #0
end
****************************************************************
*
* CharOut - Console Output Routine
*
* Inputs:
* SH_DADR - address of original DCB
* SH_DCB - copy of call DCB
*
****************************************************************
*
CharOut start
using Common
using IOCom
d_char equ 0 disp to character
lda sh_fnum if this is a class 1 call then
and #$40
beq lb2
lda sh_dcb if pCount <> 1 then
cmp #1
beq lb1
return #4 return invalid pCount error
lb1 lda sh_dcb+2 change the call to a class 0 call
sta sh_dcb
lb2 lda sh_dcb+d_char skip cursor on/off
and #$00FF
cmp #5
beq no2
cmp #6
beq no2
cmp #10 skip a line feed
beq no2
pha
jsl COut_Vector
no2 return #0
;
; ChOut - actual output routine
;
ChOut entry
php
long I,M
plx
ply
pla
phy
phx
sta ch save the character
lda consoleRefnum write the character
sta wrRefnum
~OSWrite wrRec
plp
rtl
wrRec dc i'4' write DCB
wrRefnum ds 2
dc a4'ch'
dc i4'1'
ds 4
ch ds 2
end
****************************************************************
*
* Direction - Detect direction
*
* Inputs:
* SH_DADR - address of original DCB
* SH_DCB - copy of call DCB
*
****************************************************************
*
Direction private
using Common
using IOCom
d_devc equ 0 disp to device number
d_dir equ 2 disp to direction
lda sh_fnum if this is a class 1 call then
and #$40
beq cl2
lda sh_dcb if pCount <> 2 then
cmp #2
beq cl1
return #4 return invalid pCount error
cl1 lda sh_dcb+2 change the call to a class 0 call
sta sh_dcb
lda sh_dcb+4
sta sh_dcb+2
add4 sh_dadr,#2
cl2 lda sh_dcb+d_devc load A with proper direction based
cmp #3 in the device
bge err
cmp #1
bge lb1
lda stin_direction
bra lb3
lb1 bne lb2
lda stout_direction
bra lb3
lb2 lda errout_direction
lb3 ldy #2 set direction
sta [sh_dadr],y
return #0
err return #$53 parameter out of range
end
****************************************************************
*
* Error - Error Handler
*
* Inputs:
* SH_DADR - address of original DCB
* SH_DCB - copy of call DCB
*
****************************************************************
*
Error private
using Common
d_err equ 0 disp to error number
lda sh_fnum if this is a class 1 call then
and #$40
beq lb2
lda sh_dcb if pCount <> 1 then
cmp #1
beq lb1
return #4 return invalid pCount error
lb1 lda sh_dcb+d_err+2
bra lb3
lb2 lda sh_dcb+d_err
lb3 jsl SysError
return #0
end
****************************************************************
*
* Execute - Execute a command processor file
*
* DCB:
* Disp Length Name Use
* ==== ====== ==== ===
* 0 2 FLAG flags (MSB == EXECUTE flag)
* 2 4 ADDR address of the commands string
*
* Notes:
* The commands string is a one word length followed by
* an ASCII command file.
*
****************************************************************
*
Execute private
using Common
using RecCom
d_flag equ 0 disp to flags
d_addr equ 2 disp to pointer to EXEC file
;
; Create the new EXEC record
;
jsr ClearLine clear any old stuff in the line
lda sh_fnum if this is a class 1 call then
and #$40
beq ex1
lda sh_dcb if pCount <> 2 then
cmp #2
beq lb1
return #4 return invalid pCount error
lb1 lda sh_dcb+2 change the call to a class 0 call
sta sh_dcb
lda sh_dcb+4
sta sh_dcb+2
lda sh_dcb+6
sta sh_dcb+4
ex1 tsx make sure there is enough stack space
cpx sh_my_stack
bgt ex1a
cpx sh_low_stack
blt ex1a
cpx sh_min_stack
bge ex1a
return #outofmem memory full error
ex1a jsr PushExec push the current exec file entry
bcs ex2
jsr PushInstruction push the current instruction stack
bcs ex2
move4 sh_dcb+d_addr,exec_ptr set the new exec file pointer
stz exec_disp set disp to begining
stz exec_exit initialize variables
stz exec_return
lda sh_dcb+d_flag
asl A
lda #0
rol A
sta executeCmd
malloc #ins_stack_size get an instruction buffer
sta ins_ptr
stx ins_ptr+2
ora ins_ptr+2
bne ex3
ex2 return #$FFFF probably no memory for exec node
ex3 stz ins_disp set initial displacement
la ins_size,ins_stack_size set initial size
;
; Process a line
;
pl1 stz rcode no error so far
jsr Spin spin the spinner
jsr NextCLine get the next line
bcs dn1
jsr ShellCommand process the line
cmp #0 quit if monitor reports an error
beq pl1a
sta rcode
lla r12,exitStr and EXIT is non-null
jsr FindVariable
lda r0
ora r2
bne dn1
pl1a lda stop_flag if stopflag is set then
beq pl2
lda sh_my_stack restore stack pointer
tcs
lda sh_my_dp restore direct page
tcd
stz stop_flag reset the stop flag
jsr CleanUp clean up any memory buffers
jsl mntr_vector goto command level
pl2 ldx exec_exit quit if exit requested
beq pl1
;
; Done: get rid of EXEC entry
;
dn1 stz exec_exit clear early return values
stz exec_return
stz exec_level
jsr ClearLine clear any old stuff in the line
jsr PopExec pop the exec file entry
jsr PopInstruction pop the instruction stack
return rcode
rcode ds 2 return code
end
****************************************************************
*
* ExpDevice - Expand devices
*
* Inputs: (level $00)
* sh_dadr - address of original DCB
* sh_dcb - copy of call DCB
* sh_dcb+d_name - address of the name buffer
*
* Inputs: (level $40)
* sh_dadr - address of original DCB
* sh_dcb - copy of call DCB
* sh_dcb+e_parms - number of parameters
* sh_dcb+e_inName - address of the input name buffer
* sh_dcb+e_outName - address of the output name buffer
*
****************************************************************
*
ExpDevice private
using Common
d_name equ 0 disp to name pointer
e_parms equ 0 disp to parameters
e_name equ 2 disp to input name pointer
e_out equ 6 disp to output buffer (level $40 only)
maxDP equ 20 # bytes of general purpose DP used
;
; Form a local, GS/OS style copy of the input name
;
ldx #maxDP-2 save DP work space
sp1 lda r0,X
sta regs,X
dex
dex
bpl sp1
stz err no error, yet
stz pr_name no pr_name buffer allocated, yet
stz pr_name+2
stz outBuff no ouput buffer allocated, yet
stz outBuff+2
lda sh_fnum get the length & start addr of the string
and #$0040
bne lc1
add4 sh_dcb+d_name,#1,r0
lda [sh_dcb+d_name]
and #$00FF
bra lc2
lc1 lda sh_dcb+e_parms
cmp #2
beq lc1a
return #4
lc1a add4 sh_dcb+e_name,#2,r0
lda [sh_dcb+e_name]
lc2 sta r4 save the length
inc A get memory for the local copy
inc A
jsl Malloc
sta inBuff
sta r8
stx inBuff+2
stx r10
ora r10 done if out of memory
jeq oom
add4 r8,#2,r12 form the character destination address
lda r4 set the length of the buffer
sta [r8]
tay move the characters
beq dw1
dey
short M
lc3 lda [r0],Y
sta [r12],Y
dey
bpl lc3
long M
;
; If the name starts with .. followed by a delimiter then form full path
;
dw1 move4 inBuff,r0 skip if the prefix does not start with
lda [r0] ..
cmp #2
jlt ep1
ldy #2
lda [r0],Y
cmp #'..'
jne ep1
stz pr_num read prefix 0
ph4 #pr_dcb
jsr GetPrefix
sta err
jcs db1
move4 pr_name,r0 if the prefix is null then
ldy #2
lda [r0],Y
bne dw2
free pr_name dispose of the prefix 0 buffer
lda #8 read prefix 8
sta pr_num
ph4 #pr_dcb
jsr GetPrefix
sta err
jcs db1
dw2 move4 inBuff,r0 determine what the delimiter is
lda [r0]
beq dw5
tax
short M
ldy #2
dw3 lda [r0],Y
beq dw4
cmp #'/'
beq dw4
cmp #':'
beq dw5
iny
dex
bne dw3
bra dw5
dw4 sta r4 save the delimiter
cd1 lda #':' change the delimiters to ':'
sta [r0],Y
lda r4
cd2 iny
dex
beq dw5
cmp [r0],Y
beq cd1
bra cd2
dw5 long M
move4 inBuff,r0 r0 == ptr to 1st char in path
lda [r0] r4 == length of path
sta r4
add4 r0,#2
move4 pr_name,r8 r8 == ptr to 1st char in prefix -1
ldy #2 r6 == length of prefix
lda [r8],Y
sta r6
add4 r8,#3
dw6 lda r4 while path starts with .. do begin
cmp #2
blt dw8
lda [r0]
cmp #'..'
bne dw8
ldy r6 erase the last directory in the
short M prefix
lda #':'
dw7 dey
bpl dw7a
lda #$40 (invalid pathname syntax)
sta err
brl db1
dw7a cmp [r8],Y
bne dw7
long M
tya
sta r6
add4 r0,#2 skip the ..
dec r4
dec r4
beq dw6
lda [r0] if the next char is a delimiter then
and #$00FF
cmp #':'
bne dw6
inc4 r0 skip the delimiter
dec r4
bra dw6 end
dw8 clc find the length of the prefix + path
lda r4
adc r6
sta r16
inc A reserve memory for the combined name
inc A
jsl Malloc
sta r12
stx r14
ora r14
bne dw9
oom lda #outOfMem
sta err
brl db1
dw9 lda r16 set the length of the combined name
sta [r12]
add4 r12,#1,r16 move in the prefix
ldy r6
beq dw10a
short M
dw10 lda [r8],Y
sta [r16],Y
dey
bne dw10
long M
dw10a sec move in the path
lda r6