Scanf improvements by Greg King
git-svn-id: svn://svn.cc65.org/cc65/trunk@3377 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
a4f6f14a6b
commit
d406a9f677
8 changed files with 615 additions and 358 deletions
|
@ -29,7 +29,6 @@ puts.s
|
||||||
qsort.s
|
qsort.s
|
||||||
realloc.s
|
realloc.s
|
||||||
rewind.s
|
rewind.s
|
||||||
scanf.s
|
|
||||||
sleep.s
|
sleep.s
|
||||||
strftime.s
|
strftime.s
|
||||||
strtok.s
|
strtok.s
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
# -*- makefile -*-
|
||||||
#
|
#
|
||||||
# makefile for CC65 runtime library
|
# makefile for CC65's common library
|
||||||
#
|
#
|
||||||
|
|
||||||
.SUFFIXES: .o .s .c
|
.SUFFIXES: .o .s .c
|
||||||
|
@ -26,9 +27,19 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
|
||||||
%.o: %.s
|
%.o: %.s
|
||||||
@$(AS) -g -o $@ $(AFLAGS) $<
|
@$(AS) -g -o $@ $(AFLAGS) $<
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
# Rules to help us see what code the compiler and assembler make.
|
||||||
|
|
||||||
|
%.s : %.c
|
||||||
|
@$(CC) $(CFLAGS) -S $<
|
||||||
|
|
||||||
|
%.lst : %.s
|
||||||
|
@$(AS) $(AFLAGS) -l -o /dev/null $<
|
||||||
|
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
# Object files
|
# Object files
|
||||||
|
|
||||||
|
# From C source-files
|
||||||
C_OBJS = _afailed.o \
|
C_OBJS = _afailed.o \
|
||||||
_aligned_malloc.o \
|
_aligned_malloc.o \
|
||||||
_hextab.o \
|
_hextab.o \
|
||||||
|
@ -59,7 +70,6 @@ C_OBJS = _afailed.o \
|
||||||
qsort.o \
|
qsort.o \
|
||||||
realloc.o \
|
realloc.o \
|
||||||
rewind.o \
|
rewind.o \
|
||||||
scanf.o \
|
|
||||||
sleep.o \
|
sleep.o \
|
||||||
strftime.o \
|
strftime.o \
|
||||||
strxfrm.o \
|
strxfrm.o \
|
||||||
|
@ -67,7 +77,7 @@ C_OBJS = _afailed.o \
|
||||||
system.o \
|
system.o \
|
||||||
timezone.o
|
timezone.o
|
||||||
|
|
||||||
|
# From assembly source-files
|
||||||
S_OBJS = _cwd.o \
|
S_OBJS = _cwd.o \
|
||||||
_fdesc.o \
|
_fdesc.o \
|
||||||
_file.o \
|
_file.o \
|
||||||
|
@ -134,6 +144,7 @@ S_OBJS = _cwd.o \
|
||||||
raise.o \
|
raise.o \
|
||||||
remove.o \
|
remove.o \
|
||||||
rename.o \
|
rename.o \
|
||||||
|
scanf.o \
|
||||||
setjmp.o \
|
setjmp.o \
|
||||||
signal.o \
|
signal.o \
|
||||||
sigtable.o \
|
sigtable.o \
|
||||||
|
@ -183,10 +194,10 @@ S_OBJS = _cwd.o \
|
||||||
all: $(C_OBJS) $(S_OBJS)
|
all: $(C_OBJS) $(S_OBJS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f *~
|
@$(RM) *~ *.lst
|
||||||
@rm -f $(C_OBJS:.o=.s)
|
@$(RM) $(C_OBJS:.o=.s)
|
||||||
@rm -f $(C_OBJS)
|
@$(RM) $(C_OBJS)
|
||||||
@rm -f $(S_OBJS)
|
@$(RM) $(S_OBJS)
|
||||||
|
|
||||||
zap: clean
|
zap: clean
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* _scanf.h
|
* _scanf.h
|
||||||
*
|
*
|
||||||
* (C) Copyright 2001 Ullrich von Bassewitz (uz@cc65.org)
|
* (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -16,26 +16,26 @@
|
||||||
* return EOF if no more data is available.
|
* return EOF if no more data is available.
|
||||||
*/
|
*/
|
||||||
typedef int __fastcall__ (*getfunc) (void* data);
|
typedef int __fastcall__ (*getfunc) (void* data);
|
||||||
|
|
||||||
|
/* Type of the function that is called to put back unused data */
|
||||||
typedef int __fastcall__ (*ungetfunc) (int c, void* data);
|
typedef int __fastcall__ (*ungetfunc) (int c, void* data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Control structure passed to the low level worker function.
|
/* Control structure passed to the low level worker function.
|
||||||
* Beware: This structure is mirrored in the _scanf.inc assembler include
|
* Beware: This structure is mirrored in the _scanf.inc assembler include
|
||||||
* file, so check this when altering the structure.
|
* file, so check this when altering the structure.
|
||||||
*/
|
*/
|
||||||
struct scanfdata {
|
struct scanfdata {
|
||||||
getfunc get; /* Pointer to input routine */
|
getfunc get; /* Pointer to input routine */
|
||||||
ungetfunc unget; /* Pointer to pushback routine */
|
ungetfunc unget; /* Pointer to pushback routine */
|
||||||
|
void* data; /* Pointer to struct. used outside of _scanf() */
|
||||||
/* Fields used outside of _scanf */
|
|
||||||
void* data; /* Caller data */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal scanning routine */
|
/* Internal scanning routine */
|
||||||
int __fastcall__ _scanf (struct scanfdata* d, const char* format, va_list ap);
|
int __fastcall__ _scanf (const struct scanfdata* d, const char* format, va_list ap);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,4 +44,3 @@ int __fastcall__ _scanf (struct scanfdata* d, const char* format, va_list ap);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* scanf.c
|
|
||||||
*
|
|
||||||
* Ullrich von Bassewitz (uz@cc65.org), 2004-11-26
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int scanf (const char* format, ...)
|
|
||||||
/* Standard C function */
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
/* Setup for variable arguments */
|
|
||||||
va_start (ap, format);
|
|
||||||
|
|
||||||
/* Call vfscanf(). Since we know that va_end won't do anything, we will
|
|
||||||
* save the call and return the value directly.
|
|
||||||
*/
|
|
||||||
return vfscanf (stdin, format, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
74
libsrc/common/scanf.s
Normal file
74
libsrc/common/scanf.s
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
;
|
||||||
|
; int scanf(const char* Format, ...);
|
||||||
|
;
|
||||||
|
; 2000-12-01, Ullrich von Bassewitz
|
||||||
|
; 2004-12-31, Greg King
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _scanf
|
||||||
|
|
||||||
|
.import _stdin, pushax, addysp, _vfscanf
|
||||||
|
.import sp:zp, ptr1:zp
|
||||||
|
|
||||||
|
.macpack generic
|
||||||
|
|
||||||
|
; ----------------------------------------------------------------------------
|
||||||
|
; Code
|
||||||
|
;
|
||||||
|
_scanf:
|
||||||
|
sty ArgSize ; Number of argument bytes passed in .Y
|
||||||
|
|
||||||
|
; We are using a (hopefully) clever trick here to reduce code size. On entry,
|
||||||
|
; the stack pointer points to the last pushed argument of the variable
|
||||||
|
; argument list. Adding the number of argument bytes, would result in a
|
||||||
|
; pointer that points _above_ the Format argument.
|
||||||
|
; Because we have to push stdin anyway, we will do that here, so:
|
||||||
|
;
|
||||||
|
; * we will save the subtraction of 2 (__fixargs__) later;
|
||||||
|
; * we will have the address of the Format argument which needs to
|
||||||
|
; be pushed next.
|
||||||
|
|
||||||
|
lda _stdin
|
||||||
|
ldx _stdin+1
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Now, calculate the va_list pointer, which does point to Format.
|
||||||
|
|
||||||
|
lda sp
|
||||||
|
ldx sp+1
|
||||||
|
add ArgSize
|
||||||
|
bcc @L1
|
||||||
|
inx
|
||||||
|
@L1: sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
|
||||||
|
; Push a copy of Format.
|
||||||
|
|
||||||
|
ldy #1
|
||||||
|
lda (ptr1),y
|
||||||
|
tax
|
||||||
|
dey
|
||||||
|
lda (ptr1),y
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Load va_list [last and __fastcall__ argument to vfscanf()].
|
||||||
|
|
||||||
|
lda ptr1
|
||||||
|
ldx ptr1+1
|
||||||
|
|
||||||
|
; Call vfscanf().
|
||||||
|
|
||||||
|
jsr _vfscanf
|
||||||
|
|
||||||
|
; Clean up the stack. We will return what we got from vfscanf().
|
||||||
|
|
||||||
|
ldy ArgSize
|
||||||
|
jmp addysp
|
||||||
|
|
||||||
|
; ----------------------------------------------------------------------------
|
||||||
|
; Data
|
||||||
|
;
|
||||||
|
.bss
|
||||||
|
ArgSize:
|
||||||
|
.res 1 ; Number of argument bytes
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
;
|
;
|
||||||
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap);
|
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap);
|
||||||
;
|
;
|
||||||
; Ullrich von Bassewitz, 2004-11-27
|
; 2004-11-27, Ullrich von Bassewitz
|
||||||
|
; 2004-12-21, Greg King
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _vfscanf
|
.export _vfscanf
|
||||||
.import _fgetc, _ungetc
|
.import _fgetc, _ungetc, _ferror
|
||||||
|
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
.include "_scanf.inc"
|
.include "_scanf.inc"
|
||||||
|
.include "stdio.inc"
|
||||||
|
|
||||||
|
|
||||||
|
count := ptr3 ; Result of scan
|
||||||
|
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
|
@ -25,23 +30,27 @@ d: .addr _fgetc ; GET
|
||||||
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap)
|
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap)
|
||||||
; /* Standard C function */
|
; /* Standard C function */
|
||||||
; {
|
; {
|
||||||
; struct scanfdata d;
|
|
||||||
;
|
|
||||||
; /* Initialize the data struct. We do only need the given file as user data,
|
; /* Initialize the data struct. We do only need the given file as user data,
|
||||||
; * since the get and ungetc are crafted so they match the standard fgetc
|
; * because the (getfunc) and (ungetfunc) functions are crafted so that they
|
||||||
; * and ungetc functions.
|
; * match the standard-I/O fgetc() and ungetc().
|
||||||
; */
|
; */
|
||||||
; d.get = (getfunc) fgetc,
|
; static struct scanfdata d = {
|
||||||
; d.unget = (ungetfunc) ungetc,
|
; ( getfunc) fgetc,
|
||||||
; d.data = f;
|
; (ungetfunc) ungetc
|
||||||
|
; };
|
||||||
|
; static int count;
|
||||||
;
|
;
|
||||||
; /* Call the internal function and return the result */
|
; d.data = (void*) f;
|
||||||
; return _scanf (&d, format, ap);
|
;
|
||||||
|
; /* Call the internal function */
|
||||||
|
; count = _scanf (&d, format, ap);
|
||||||
|
;
|
||||||
|
; /* And, return the result */
|
||||||
|
; return ferror (f) ? EOF : count;
|
||||||
; }
|
; }
|
||||||
;
|
;
|
||||||
; Since _scanf has the same parameter stack as vfscanf, with f replaced by &d,
|
; Because _scanf() has the same parameter stack as vfscanf(), with f replaced
|
||||||
; we will do exactly that. _scanf will then clean up the stack, so we can jump
|
; by &d, we will do exactly that. _scanf() then will clean up the stack.
|
||||||
; directly there, no need to return.
|
|
||||||
; Beware: Since ap is a fastcall parameter, we must not destroy a/x.
|
; Beware: Since ap is a fastcall parameter, we must not destroy a/x.
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -63,8 +72,27 @@ _vfscanf:
|
||||||
lda #>d
|
lda #>d
|
||||||
sta (sp),y
|
sta (sp),y
|
||||||
|
|
||||||
; Restore the low byte of ap and jump to the _scanf function
|
; Restore the low byte of ap, and call the _scanf function
|
||||||
|
|
||||||
pla
|
pla
|
||||||
jmp __scanf
|
jsr __scanf
|
||||||
|
sta count
|
||||||
|
stx count+1
|
||||||
|
|
||||||
|
; Return -1 if there was a read error during the scan
|
||||||
|
|
||||||
|
lda d + SCANFDATA::DATA ; Get f
|
||||||
|
ldx d + SCANFDATA::DATA+1
|
||||||
|
jsr _ferror
|
||||||
|
tay
|
||||||
|
beq L1
|
||||||
|
lda #<EOF
|
||||||
|
tax
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Or, return the result of the scan
|
||||||
|
|
||||||
|
L1: lda count
|
||||||
|
ldx count+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap);
|
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap);
|
||||||
; /* Standard C function */
|
; /* Standard C function */
|
||||||
;
|
;
|
||||||
; Ullrich von Bassewitz, 2004-11-28
|
; 2004-11-28, Ullrich von Bassewitz
|
||||||
|
; 2004-12-21, Greg King
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _vsscanf
|
.export _vsscanf
|
||||||
|
|
||||||
.import popax, __scanf
|
.import popax, __scanf
|
||||||
.importzp sp, ptr1, ptr2
|
.importzp sp, ptr1, ptr2
|
||||||
|
|
||||||
|
@ -25,14 +27,13 @@
|
||||||
; static int __fastcall__ get (struct sscanfdata* d)
|
; static int __fastcall__ get (struct sscanfdata* d)
|
||||||
; /* Read a character from the input string and return it */
|
; /* Read a character from the input string and return it */
|
||||||
; {
|
; {
|
||||||
; char C;
|
; char C = d->str[d->index];
|
||||||
; if (C = d->str[d->index]) {
|
; if (C == '\0') {
|
||||||
; /* Increment index only if end not reached */
|
|
||||||
; ++d->index;
|
|
||||||
; return C;
|
|
||||||
; } else {
|
|
||||||
; return EOF;
|
; return EOF;
|
||||||
; }
|
; }
|
||||||
|
; /* Increment index only if end not reached */
|
||||||
|
; ++d->index;
|
||||||
|
; return C;
|
||||||
; }
|
; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -73,17 +74,17 @@
|
||||||
L1: tax ; Save return value
|
L1: tax ; Save return value
|
||||||
tya ; Low byte of index
|
tya ; Low byte of index
|
||||||
ldy #SSCANFDATA::INDEX
|
ldy #SSCANFDATA::INDEX
|
||||||
add #1
|
add #<1
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
iny
|
iny
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
adc #$00
|
adc #>1
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
|
|
||||||
; Return the char just read
|
; Return the char just read
|
||||||
|
|
||||||
txa
|
txa
|
||||||
ldx #$00
|
ldx #>0
|
||||||
rts
|
rts
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
@ -110,11 +111,11 @@ L1: tax ; Save return value
|
||||||
|
|
||||||
ldy #SSCANFDATA::INDEX
|
ldy #SSCANFDATA::INDEX
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
sub #1
|
sub #<1
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
iny
|
iny
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
sbc #0
|
sbc #>1
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
|
|
||||||
; Return c
|
; Return c
|
||||||
|
@ -127,15 +128,16 @@ L1: tax ; Save return value
|
||||||
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap)
|
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap)
|
||||||
; /* Standard C function */
|
; /* Standard C function */
|
||||||
; {
|
; {
|
||||||
; struct sscanfdata sd;
|
|
||||||
; struct scanfdata d;
|
|
||||||
;
|
|
||||||
; /* Initialize the data structs. The sscanfdata struct will be passed back
|
; /* Initialize the data structs. The sscanfdata struct will be passed back
|
||||||
; * to the get and unget functions by _scanf.
|
; * to the get and unget functions by _scanf().
|
||||||
; */
|
; */
|
||||||
; d.get = (getfunc) get;
|
; static struct sscanfdata sd;
|
||||||
; d.unget = (ungetfunc) unget,
|
; static const struct scanfdata d = {
|
||||||
; d.data = &sd;
|
; ( getfunc) get,
|
||||||
|
; (ungetfunc) unget,
|
||||||
|
; (void*) &sd
|
||||||
|
; };
|
||||||
|
;
|
||||||
; sd.str = str;
|
; sd.str = str;
|
||||||
; sd.index = 0;
|
; sd.index = 0;
|
||||||
;
|
;
|
||||||
|
@ -144,10 +146,10 @@ L1: tax ; Save return value
|
||||||
; }
|
; }
|
||||||
;
|
;
|
||||||
|
|
||||||
.data
|
.bss
|
||||||
|
|
||||||
sd: .tag SSCANFDATA
|
sd: .tag SSCANFDATA
|
||||||
|
|
||||||
|
.rodata
|
||||||
d: .addr get
|
d: .addr get
|
||||||
.addr unget
|
.addr unget
|
||||||
.addr sd
|
.addr sd
|
||||||
|
@ -177,11 +179,10 @@ d: .addr get
|
||||||
sta sd + SSCANFDATA::INDEX
|
sta sd + SSCANFDATA::INDEX
|
||||||
sta sd + SSCANFDATA::INDEX+1
|
sta sd + SSCANFDATA::INDEX+1
|
||||||
|
|
||||||
; Restore the low byte of ap and jump to _scanf which will cleanup the stacl
|
; Restore the low byte of ap, and jump to _scanf() which will clean up the stack
|
||||||
|
|
||||||
pla
|
pla
|
||||||
jmp __scanf
|
jmp __scanf
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue