@echo $<
@$(AS) -g -o $@ $(AFLAGS) $<
-C_OBJS = fclose.o fgets.o fprintf.o strdup.o calloc.o _fopen.o\
+C_OBJS = fclose.o fgets.o fprintf.o calloc.o _fopen.o\
fputs.o fread.o fwrite.o gets.o realloc.o bsearch.o strxfrm.o\
printf.o _hextab.o vfprintf.o fdopen.o strtok.o\
_afailed.o fopen.o fgetc.o fputc.o puts.o gets.o perror.o getchar.o\
strcoll.o \
strcpy.o \
strcspn.o \
+ strdup.o \
strerror.o \
stricmp.o \
strlen.o \
--- /dev/null
+;
+; Ullrich von Bassewitz, 18.07.2000
+;
+; char* __fastcall__ strdup (const char* S);
+;
+; Note: The code knowns which zero page locations are used by malloc.
+;
+
+ .importzp sp, tmp1, ptr4
+ .import pushax, decsp4, incsp4
+ .import _strlen, _malloc, _memcpy
+ .export _strdup
+
+ .macpack generic
+
+_strdup:
+
+; Since we need some place to store the intermediate results, allocate a
+; stack frame. To make this somewhat more efficient, create the stackframe
+; as needed for the final call to the memcpy function.
+
+ jsr decsp4 ; Target/source
+
+; Store the pointer into the source slot
+
+ ldy #0
+ sta (sp),y
+ iny
+ pha
+ txa
+ sta (sp),y
+ pla
+
+; Get length of S (which is still in a/x)
+
+ jsr _strlen
+
+; Calculate strlen(S)+1 (the space needed)
+
+ add #1
+ bcc @L1
+ inx
+
+; Save the space we're about to allocate in ptr4
+
+@L1: sta ptr4
+ stx ptr4+1
+
+; Allocate memory. _malloc will not use ptr4
+
+ jsr _malloc
+
+; Store the result into the target stack slot
+
+ ldy #2
+ sta (sp),y ; Store low byte
+ sta tmp1
+ txa ; Get high byte
+ iny
+ sta (sp),y ; Store high byte
+
+; Check for a NULL pointer
+
+ ora tmp1
+ beq OutOfMemory
+
+; Copy the string. memcpy will return the target string which is exactly
+; what we need here. It will also drop the allocated stack frame.
+
+ lda ptr4
+ ldx ptr4+1 ; Load size
+ jmp _memcpy ; Copy string, drop stackframe
+
+; Out of memory, return NULL (A = 0)
+
+OutOfMemory:
+ tax
+ jmp incsp4 ; Drop stack frame
+
+