Repository navigation
Expand file tree
/
Copy pathstring.asm
More file actions
2027 lines (1856 loc) · 51.1 KB
/
Copy pathstring.asm
File metadata and controls
2027 lines (1856 loc) · 51.1 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/string
case on
mcopy string.macros
****************************************************************
*
* String - String Processing Library
*
* This code implements the subroutines needed to support the
* standard C library STRING.
*
* December 1988
* Mike Westerfield
*
* Copyright 1988
* Byte Works, Inc.
*
****************************************************************
*
String start dummy routine
copy equates.asm
end
****************************************************************
*
* c2pCommon - common work buffer for c2pstr and p2cstr
*
****************************************************************
*
c2pCommon privdata
str1 ds 258
end
****************************************************************
*
* char *c2pstr(str)
* char *str;
*
* Inputs:
* str - pointer to the c string to convert
*
* Outputs:
* Returns a pointer to the p string.
*
* Notes:
* Any characters after the 255th are truncated without
* warning.
*
****************************************************************
*
c2pstr start
using c2pCommon
addr equ 1
csubroutine (4:str),4
phb
phk
plb
short I,M
ldy #0
lb1 lda [str],Y
sta str1+1,Y
beq lb2
iny
bne lb1
dey
lb2 sty str1
long I,M
lla addr,str1
plb
creturn 4:addr
end
****************************************************************
*
* makeset - create a set of characters
*
* This subroutine is called by strspn, strcspn, strpbrk and
* strrpbrk to create a set of characters.
*
* Inputs:
* set - pointer to the set of characters
*
* Outputs:
* strset - set of bytes; non-zero for chars in set
*
****************************************************************
*
makeset private
set equ 8 string set
lda set if the set is null then
ora set+2
beq lb3 return
lda #0 clear the string set
sta >strset
phb
move strset,strset+1,#255
plb
short I,M while there are chars in the set do
ldy #0
lb1 lda [set],Y
beq lb2
tax set the array element for this char
lda #1
sta >strset,X
iny endwhile
bne lb1
inc set+1
bne lb1
inc set+2
bra lb1
lb2 long I,M
lb3 rts
end
****************************************************************
*
* memchr - find a byte in memory
*
* Returns a pointer to the byte in memory
*
* Inputs:
* ptr - first byte to search
* val - byte to search for
* len - # bytes to search
*
* Outputs:
* A,X - pointer to the byte; NULL for no match
*
****************************************************************
*
memchr start
ptr equ 4 pointer to the first byte
val equ 8 byte to search for
len equ 10 # bytes to search
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
short M
ldy #0
ldx len+2 scan 64K blocks
beq lb1a
lb1 lda [ptr],Y
cmp val
beq lb3
iny
bne lb1
inc ptr+2
dex
bne lb1
lb1a ldx len
beq lb2a
lb2 lda [ptr],Y scan the remaining characters
cmp val
beq lb3
iny
dex
bne lb2
lb2a long M no match found -> return NULL
ldx #0
txy
bra lb4
lb3 long M compute the length
tya
clc
adc ptr
tay
ldx ptr+2
bcc lb4
inx
lb4 lda rtl+1 remove parameters from the stack
sta len+2
lda rtl
sta len+1
pld
tsc
clc
adc #10
tcs
tya return the pointer in X-A
rtl
end
****************************************************************
*
* memcmp - memory compare
*
* Compare *s1 to *s2. If *s1 < *s2 then return -1; if they are
* equal, return 0; otherwise, return 1.
*
* Inputs:
* p1 - string to concatenate to
* p2 - string to concatenate
*
* Outputs:
* A - result
*
****************************************************************
*
memcmp start
p1 equ 4 pointer to memory area 1
p2 equ 8 pointer to memory area 2
len equ 12 length to compare
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
short M
ldy #0 scan 64K chunks
ldx len+2
beq lb2
lb1 lda [p1],Y
cmp [p2],Y
bne lb4
iny
bne lb1
inc p1+2
inc p2+2
dex
bne lb1
lb2 ldx len
beq lb5
lb3 lda [p1],Y scan until the end of memory is reached
cmp [p2],Y or a difference is found
bne lb4
iny
dex
bne lb3
; ldx #0
bra lb5 memory matches
lb4 blt less memory differs - set the result
ldx #1
bra lb5
less ldx #-1
lb5 lda rtl remove the parameters from the stack
sta len+1
long M
lda rtl+1
sta len+2
pld
tsc
clc
adc #12
tcs
txa return the result
rtl
end
****************************************************************
*
* memccpy - copy up to n bytes, stopping if c is encountered
*
* Copy *s2 to *s1, stopping after (unsigned char)c is copied
* or after n bytes
*
* Inputs:
* s1 - location to copy to
* s2 - location to copy from
* c - terminator character
* n - max length to copy
*
* Outputs:
* X-A - pointer to just after the character c in s1,
* or NULL if c was not encountered
*
****************************************************************
*
memccpy start
csubroutine (4:s1,4:s2,2:c,4:n),0
ldx n copy characters until c is found
bne lb0 or we have copied n characters
lda n+2
beq lb3a
dec n+2
lb0 short M
ldy #0
lb1 lda [s2],Y
sta [s1],Y
cmp c
beq lb2
dex
bne lb1b
lb1a ldx n+2
beq lb3
dex
stx n+2
ldx #0
lb1b iny
bne lb1
inc s1+2
inc s2+2
bra lb1
lb2 long M c encountered:
sec return pointer just past c in s1
tya
adc s1
sta s1
bcc lb4
inc s1+2
bra lb4
lb3 long M c not encountered:
lb3a stz s1 return null
stz s1+2
lb4 creturn 4:s1
end
****************************************************************
*
* memcpy - memory copy
*
* Copy len bytes from p1 to p2.
*
* Inputs:
* p1 - destination pointer
* p2 - source pointer
* len - # bytes to copy
*
* Outputs:
* X-A - p1
*
* Notes: The memory areas should not overlap
*
****************************************************************
*
memcpy start
p1 equ 4 destination pointer
p2 equ 8 source pointer
len equ 12 length to compare
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
ph4 <p1 save the dest pointer
lda len if there are an odd # of bytes then
lsr A
bcc lb1
short M move 1 byte now
lda [p2]
sta [p1]
dec len
long M
inc4 p1
inc4 p2
lb1 anop endif
ldx len+2 move full banks of memory
beq lb1b
ldy #0
lb1a lda [p2],Y
sta [p1],Y
dey
dey
bne lb1a
inc p2+2
inc p1+2
dex
bne lb1a
lb1b ldy len move len bytes
beq lb4
dey
dey
beq lb3
lb2 lda [p2],Y
sta [p1],Y
dey
dey
bne lb2
lb3 lda [p2]
sta [p1]
lb4 ply get the original source pointer
plx
lda rtl remove the parameters from the stack
sta len+1
lda rtl+1
sta len+2
pld
tsc
clc
adc #12
tcs
tya return the result
rtl
end
****************************************************************
*
* memmove - memory move
*
* Move len bytes from p1 to p2.
*
* Inputs:
* p1 - destination pointer
* p2 - source pointer
* len - # bytes to copy
*
* Outputs:
* X-A - p2
*
* Notes: The memory areas may overlap; the move will still work
*
****************************************************************
*
memmove start
p1 equ 4 destination pointer
p2 equ 8 source pointer
len equ 12 length to compare
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
ph4 <p1 save the dest pointer
lda p1+2 if p1 < p2 then
cmp p2+2
bne lb1
lda p1
cmp p2
lb1 bge lb5
short M move len bytes, starting with the 1st
ldy #0
ldx len+2 move 64K chunks
beq lb3
lb2 lda [p2],Y
sta [p1],Y
iny
bne lb2
inc p2+2
inc p1+2
dex
bne lb2
lb3 ldx len skip if there are no more bytes to
beq lb11 move
lb4 lda [p2],Y move the remaining bytes
sta [p1],Y
iny
dex
bne lb4
bra lb11 else
longa on
lb5 add2 p1+2,len+2 move len bytes, starting from the end
add2 p2+2,len+2
short M
ldy len branch if there are no individual
beq lb8 bytes to move
dey move the individual bytes
beq lb7
lb6 lda [p2],Y
sta [p1],Y
dey
bne lb6
lb7 lda [p2]
sta [p1]
lb8 ldx len+2 branch if there are no 64K chunks to
beq lb11 move
lb9 dec p1+2 move the 64K chunks
dec p2+2
ldy #$FFFF
lb10 lda [p2],Y
sta [p1],Y
dey
bne lb10
lda [p2]
sta [p1]
dex
bne lb9
lb11 ply get the original source pointer
plx
lda rtl remove the parameters from the stack
sta len+1
long M
lda rtl+1
sta len+2
pld
tsc
clc
adc #12
tcs
tya return the result
rtl
end
****************************************************************
*
* memset,memset_explicit - set memory to a value
*
* Set len bytes, starting at p, to val.
*
* Inputs:
* p - destination pointer
* val - value (byte!) to set memory to
* len - # bytes to set
*
* Outputs:
* X-A - p
*
****************************************************************
*
memset start
memset_explicit entry
p equ 4 destination pointer
val equ 8 source pointer
len equ 10 length to compare
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
ph4 <p save the pointer
short I,M
ldx val form a 2 byte value
stx val+1
lda len if there are an odd # of bytes then
lsr A
bcc lb1
txa set 1 byte now
sta [p]
dec len
long I,M
inc4 p
lb1 long I,M endif
lda val set len bytes
ldx len+2 set full banks
beq lb1b
ldy #0
lb1a sta [p],Y
dey
dey
bne lb1a
inc p+2
dex
bne lb1a
lb1b ldy len set a partial bank
beq lb4
dey
dey
beq lb3
lb2 sta [p],Y
dey
dey
bne lb2
lb3 sta [p]
lb4 ply get the original source pointer
plx
lda rtl remove the parameters from the stack
sta len+1
lda rtl+1
sta len+2
pld
tsc
clc
adc #10
tcs
tya return the result
rtl
end
****************************************************************
*
* char *p2cstr(str)
* char *str;
*
* Inputs:
* str - pointer to the p string to convert
*
* Outputs:
* Returns a pointer to the c string.
*
****************************************************************
*
p2cstr start
using c2pCommon
addr equ 1
csubroutine (4:str),4
phb
phk
plb
short I,M
lda [str]
tay
lda #0
sta str1,Y
tyx
beq lb2
lb1 lda [str],Y
sta str1-1,Y
dey
bne lb1
lb2 long I,M
lla addr,str1
plb
creturn 4:addr
end
****************************************************************
*
* strcat - string concatenation
*
* Place *s2 at the end of *s1, returning a pointer to *s1. No
* checking for length is performed.
*
* Inputs:
* s1 - string to concatenate to
* s2 - string to concatenate
*
* Outputs:
* X-A - pointer to the result (s1)
*
****************************************************************
*
strcat start
s1 equ 8 pointer to string 1
s2 equ 12 pointer to string 2
rtl equ 5 return address
rval equ 1 string value to return
lda 6,S save the starting value of s1
pha
lda 6,S
pha
tsc establish DP addressing
phd
tcd
ldy #0 advance s1 to point to the terminating
short M null
lb1 lda [s1],Y
beq lb2
iny
bne lb1
inc s1+2
bra lb1
lb2 long M
tya
clc
adc s1
sta s1
bcc lb2a
inc s1+2
lb2a short M copy characters 'til the null is found
ldy #0
lb3 lda [s2],Y
sta [s1],Y
beq lb4
iny
bne lb3
inc s1+2
inc s2+2
bra lb3
lb4 lda rtl return to the caller
sta s2+1
long M
lda rtl+1
sta s2+2
ldx rval+2
ldy rval
pld
tsc
clc
adc #12
tcs
tya
rtl
end
****************************************************************
*
* strchr - find a character in a string
*
* Returns a pointer to the character in the string
*
* Inputs:
* str - string to search
* c - character to search for
*
* Outputs:
* A,X - pointer to the character; NULL for no match
*
****************************************************************
*
strchr start
str equ 4 pointer to the string
c equ 8 character
tsc establish DP addressing
phd
tcd
short M advance s1 to point to the char
ldy #0
lb1 lda [str],Y
cmp c
beq lb3
cmp #0
beq lb2
iny
bne lb1
inc str+2
bra lb1
lb2 long M no match found -> return NULL
ldy #0
tyx
bra lb4
lb3 long M compute the length
tya
clc
adc str
tay
ldx str+2
bcc lb4
inx
lb4 pld remove parameters from the stack
lda 2,S
sta 8,S
pla
sta 5,S
pla
pla
tya return the pointer in X-A
rtl
end
****************************************************************
*
* strcmp - string compare
*
* Compare *s1 to *s2. If *s1 < *s2 then return -1; if they are
* equal, return 0; otherwise, return 1.
*
* Inputs:
* s1 - first string ptr
* s2 - second string ptr
*
* Outputs:
* A - result
*
****************************************************************
*
strcmp start
s1 equ 4 pointer to string 1
s2 equ 8 pointer to string 2
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
ldy #0 scan until the end of string is reached
short M or a difference is found
lb1 lda [s1],Y
beq lb2
cmp [s2],Y
bne lb3
iny
bne lb1
inc s1+2
inc s2+2
bra lb1
lb2 ldx #0 s1 is finished. If s2 is, too, the
lda [s2],Y strings are equal.
beq lb4
less ldx #-1 It wasn't, so *s1 < *s2
bra lb4
lb3 blt less the strings differ - set the result
ldx #1
lb4 lda rtl remove the parameters from the stack
sta s2+1
long M
lda rtl+1
sta s2+2
pld
tsc
clc
adc #8
tcs
txa return the result
rtl
end
****************************************************************
*
* int strcoll(const char *s1, const char *s2);
*
* Compare *s1 to *s2 based on current locale's collation order.
* If *s1 < *s2 then return a negative number; if they are
* equal, return 0; otherwise, return a positive number.
*
* Inputs:
* s1 - first string ptr
* s2 - second string ptr
*
* Outputs:
* A - result
*
* Notes:
* The current implementation assumes all supported locales
* have the same collation order as given by strcmp.
*
****************************************************************
*
strcoll start
jml strcmp
end
****************************************************************
*
* strcpy - string copy
*
* Copy string *s2 to string *s1. Return a pointer to s1.
*
* Inputs:
* s1 - string to copy to
* s2 - string to copy
*
* Outputs:
* X-A - pointer to the result (s1)
*
****************************************************************
*
strcpy start
s1 equ 8 pointer to string 1
s2 equ 12 pointer to string 2
rtl equ 5 return address
rval equ 1 string value to return
lda 6,S save the starting value of s1
pha
lda 6,S
pha
tsc establish DP addressing
phd
tcd
short M copy characters 'til the null is found
ldy #0
lb1 lda [s2],Y
sta [s1],Y
beq lb2
iny
bne lb1
inc s1+2
inc s2+2
bra lb1
lb2 lda rtl return to the caller
sta s2+1
long M
lda rtl+1
sta s2+2
ldx rval+2
ldy rval
pld
tsc
clc
adc #12
tcs
tya
rtl
end
****************************************************************
*
* strcspn - find the first char in s in set
*
* Inputs:
* s - pointer to the string to scan
* set - set of characters to check against
*
* Outputs:
* A - disp to first char in s
*
****************************************************************
*
strcspn start
s equ 4 string to scan
set equ 8 set of characters
rtl equ 1 return address
tsc establish DP addressing
phd
tcd
jsr makeset form the set of characters
stz set set initial displacement
stz set+2
short I,M scan for a matching char
ldy #0
lb1 lda [s],Y
beq lb2
tax
lda >strset,X
bne lb2
iny
bne lb1
long M
inc s+1
inc set+1
short M
bra lb1
lb2 sty set set the disp past the current disp
long I,M
ldx set+2 get the return value
ldy set
lda rtl+1 remove the parameters
sta set+2
lda rtl
sta set+1
pld
tsc
clc
adc #8
tcs
tya return the disp
rtl
end
****************************************************************
*
* char *strdup(const char *str)
*
* Inputs:
* str - string to copy
*
* Outputs:
* Pointer to copy of str (allocated with malloc),
* or NULL on allocation failure.
*
****************************************************************
*
strdup start
csubroutine (4:str)
ph4 <str ptr = malloc(strlen(str)+1)
jsl strlen
inc a
bne lb1
inx
lb1 phx
pha
jsl malloc
tay if ptr != NULL
bne lb2
txy
beq ret
lb2 ph4 <str ptr = strcpy(ptr, str)
phx
pha