;
; Ullrich von Bassewitz, 31.05.1998
+; Christian Krueger: 2013-Jul-24, minor optimization
;
; char* strcat (char* dest, const char* src);
;
sta ptr1 ; Save src
stx ptr1+1
jsr popax ; Get dest
- sta ptr2
- stx ptr2+1
sta tmp3 ; Remember for function return
- ldy #0
-
-; find end of dest
+ tay
+ lda #0
+ sta ptr2 ; access from page start, y contains low byte
+ stx ptr2+1
-sc1: lda (ptr2),y
- beq sc2
+findEndOfDest:
+ lda (ptr2),y
+ beq endOfDestFound
iny
- bne sc1
- inc ptr2+1
- bne sc1
-
-; end found, get offset in y into pointer
-
-sc2: tya
- clc
- adc ptr2
- sta ptr2
- bcc sc3
+ bne findEndOfDest
inc ptr2+1
+ bne findEndOfDest
-; copy src
+endOfDestFound:
+ sty ptr2 ; advance pointer to last y position
+ ldy #0 ; reset new y-offset
-sc3: ldy #0
-sc4: lda (ptr1),y
+copyByte:
+ lda (ptr1),y
sta (ptr2),y
- beq sc5
+ beq done
iny
- bne sc4
+ bne copyByte
inc ptr1+1
inc ptr2+1
- bne sc4
+ bne copyByte ; like bra here
-; done, return pointer to dest
-
-sc5: lda tmp3 ; X does still contain high byte
+; return pointer to dest
+done: lda tmp3 ; X does still contain high byte
rts
-
;
; Ullrich von Bassewitz, 31.05.1998
+; Christian Krueger, 2013-Aug-04, minor optimization
;
; const char* strchr (const char* s, int c);
;
.importzp ptr1, tmp1
_strchr:
- sta tmp1 ; Save c
- jsr popax ; get s
- sta ptr1
- stx ptr1+1
- ldy #0
-
-Loop: lda (ptr1),y ; Get next char
- beq EOS ; Jump on end of string
- cmp tmp1 ; Found?
- beq Found ; Jump if yes
+ sta tmp1 ; Save c
+ jsr popax ; get s
+ tay ; low byte of pointer to y
+ stx ptr1+1
+ lda #0
+ sta ptr1 ; ptr access page wise
+
+Loop: lda (ptr1),y ; Get next char
+ beq EOS ; Jump on end of string
+ cmp tmp1 ; Found?
+ beq Found ; Jump if yes
iny
- bne Loop
- inc ptr1+1
- bne Loop ; Branch always
+ bne Loop
+ inc ptr1+1
+ bne Loop ; Branch always
; End of string. Check if we're searching for the terminating zero
-EOS: lda tmp1 ; Get the char we're searching for
- bne NotFound ; Jump if not searching for terminator
+EOS:
+ lda tmp1 ; Get the char we're searching for
+ bne NotFound ; Jump if not searching for terminator
-; Found. Calculate pointer to c.
+; Found. Set pointer to c.
-Found: ldx ptr1+1 ; Load high byte of pointer
- tya ; Low byte offset
- clc
- adc ptr1
- bcc Found1
- inx
-Found1: rts
+Found:
+ ldx ptr1+1 ; Load high byte of pointer
+ tya ; low byte is in y
+ rts
; Not found, return NULL
NotFound:
- lda #0
+ lda #0
tax
rts
-
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SourceStringSize 257 // test correct page passing (>256)
+
+static char SourceString[SourceStringSize+1]; // +1 room for terminating null
+static char DestinationString[2*SourceStringSize+1]; // will contain two times the source buffer
+
+
+int main (void)
+{
+ unsigned i,j;
+ char* p;
+
+ /* Print a header */
+ printf ("strcat(): ");
+
+ for (i=0; i < SourceStringSize; ++i)
+ SourceString[i] = (i%128)+1;
+
+ SourceString[i] = 0;
+
+ if (strlen(SourceString) != SourceStringSize)
+ {
+ printf ("Fail: Source string initialization or 'strlen()' problem!\n");
+ printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(SourceString));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Ensure empty destination string */
+ DestinationString[0] = 0;
+
+ if (strlen(DestinationString) != 0)
+ {
+ printf ("Fail: Destination string initialization or 'strlen()' problem!\n");
+ printf ("Expected length: %u but is %u!\n", 0, strlen(DestinationString));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Test concatenation to empty buffer */
+
+ p = strcat(DestinationString, SourceString);
+
+ if (strlen(DestinationString) != SourceStringSize)
+ {
+ printf ("Fail: String concatenation to empty buffer!\n");
+ printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(DestinationString));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Test concatenation to non empty buffer */
+
+ p = strcat(DestinationString, SourceString);
+
+ if (strlen(DestinationString) != 2*SourceStringSize)
+ {
+ printf ("Fail: String concatenation to non-empty buffer!\n");
+ printf ("Expected length: %u but is %u!\n", 2*SourceStringSize, strlen(DestinationString));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Test return value */
+
+ if (p != DestinationString)
+ {
+ printf ("Invalid return value!\n");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Test contents */
+
+ for(j=0; j <2; ++j)
+ for(i=0; i < SourceStringSize; ++i)
+ {
+ unsigned position = j*SourceStringSize+i;
+ unsigned current = DestinationString[position];
+ unsigned expected = (i%128)+1;
+ if (current != expected)
+ {
+ printf ("Fail: Unexpected destination buffer contents at position %u!\n", position);
+ printf ("Expected %u, but is %u!\n", expected, current);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ /* Test passed */
+ printf ("Passed\n");
+ return EXIT_SUCCESS;
+}
+
+
+