1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-22 17:29:34 +00:00

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:
cuz 2005-02-14 09:19:59 +00:00
parent a4f6f14a6b
commit d406a9f677
8 changed files with 615 additions and 358 deletions

View File

@ -29,7 +29,6 @@ puts.s
qsort.s
realloc.s
rewind.s
scanf.s
sleep.s
strftime.s
strtok.s

View File

@ -1,5 +1,6 @@
# -*- makefile -*-
#
# makefile for CC65 runtime library
# makefile for CC65's common library
#
.SUFFIXES: .o .s .c
@ -26,9 +27,19 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
%.o: %.s
@$(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
# From C source-files
C_OBJS = _afailed.o \
_aligned_malloc.o \
_hextab.o \
@ -59,7 +70,6 @@ C_OBJS = _afailed.o \
qsort.o \
realloc.o \
rewind.o \
scanf.o \
sleep.o \
strftime.o \
strxfrm.o \
@ -67,7 +77,7 @@ C_OBJS = _afailed.o \
system.o \
timezone.o
# From assembly source-files
S_OBJS = _cwd.o \
_fdesc.o \
_file.o \
@ -134,6 +144,7 @@ S_OBJS = _cwd.o \
raise.o \
remove.o \
rename.o \
scanf.o \
setjmp.o \
signal.o \
sigtable.o \
@ -183,10 +194,10 @@ S_OBJS = _cwd.o \
all: $(C_OBJS) $(S_OBJS)
clean:
@rm -f *~
@rm -f $(C_OBJS:.o=.s)
@rm -f $(C_OBJS)
@rm -f $(S_OBJS)
@$(RM) *~ *.lst
@$(RM) $(C_OBJS:.o=.s)
@$(RM) $(C_OBJS)
@$(RM) $(S_OBJS)
zap: clean

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* _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.
*/
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);
/* Control structure passed to the low level worker function.
* 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 {
getfunc get; /* Pointer to input routine */
ungetfunc unget; /* Pointer to pushback routine */
/* Fields used outside of _scanf */
void* data; /* Caller data */
getfunc get; /* Pointer to input routine */
ungetfunc unget; /* Pointer to pushback routine */
void* data; /* Pointer to struct. used outside of _scanf() */
};
/* 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);

View File

@ -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
View 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

View File

@ -1,14 +1,19 @@
;
; 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
.import _fgetc, _ungetc
.import _fgetc, _ungetc, _ferror
.include "zeropage.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)
; /* Standard C function */
; {
; struct scanfdata d;
;
; /* 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
; * and ungetc functions.
; * because the (getfunc) and (ungetfunc) functions are crafted so that they
; * match the standard-I/O fgetc() and ungetc().
; */
; d.get = (getfunc) fgetc,
; d.unget = (ungetfunc) ungetc,
; d.data = f;
; static struct scanfdata d = {
; ( getfunc) fgetc,
; (ungetfunc) ungetc
; };
; static int count;
;
; /* Call the internal function and return the result */
; return _scanf (&d, format, ap);
; d.data = (void*) f;
;
; /* 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,
; we will do exactly that. _scanf will then clean up the stack, so we can jump
; directly there, no need to return.
; Because _scanf() has the same parameter stack as vfscanf(), with f replaced
; by &d, we will do exactly that. _scanf() then will clean up the stack.
; Beware: Since ap is a fastcall parameter, we must not destroy a/x.
;
@ -63,8 +72,27 @@ _vfscanf:
lda #>d
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
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

View File

@ -2,10 +2,12 @@
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap);
; /* Standard C function */
;
; Ullrich von Bassewitz, 2004-11-28
; 2004-11-28, Ullrich von Bassewitz
; 2004-12-21, Greg King
;
.export _vsscanf
.import popax, __scanf
.importzp sp, ptr1, ptr2
@ -25,14 +27,13 @@
; static int __fastcall__ get (struct sscanfdata* d)
; /* Read a character from the input string and return it */
; {
; char C;
; if (C = d->str[d->index]) {
; /* Increment index only if end not reached */
; ++d->index;
; return C;
; } else {
; char C = d->str[d->index];
; if (C == '\0') {
; return EOF;
; }
; /* Increment index only if end not reached */
; ++d->index;
; return C;
; }
;
@ -73,17 +74,17 @@
L1: tax ; Save return value
tya ; Low byte of index
ldy #SSCANFDATA::INDEX
add #1
add #<1
sta (ptr1),y
iny
lda (ptr1),y
adc #$00
adc #>1
sta (ptr1),y
; Return the char just read
txa
ldx #$00
ldx #>0
rts
.endproc
@ -110,11 +111,11 @@ L1: tax ; Save return value
ldy #SSCANFDATA::INDEX
lda (ptr1),y
sub #1
sub #<1
sta (ptr1),y
iny
lda (ptr1),y
sbc #0
sbc #>1
sta (ptr1),y
; Return c
@ -127,15 +128,16 @@ L1: tax ; Save return value
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap)
; /* Standard C function */
; {
; struct sscanfdata sd;
; struct scanfdata d;
;
; /* 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;
; d.unget = (ungetfunc) unget,
; d.data = &sd;
; static struct sscanfdata sd;
; static const struct scanfdata d = {
; ( getfunc) get,
; (ungetfunc) unget,
; (void*) &sd
; };
;
; sd.str = str;
; sd.index = 0;
;
@ -144,10 +146,10 @@ L1: tax ; Save return value
; }
;
.data
.bss
sd: .tag SSCANFDATA
.rodata
d: .addr get
.addr unget
.addr sd
@ -177,11 +179,10 @@ d: .addr get
sta sd + SSCANFDATA::INDEX
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
jmp __scanf
.endproc