From 0a12a012e62fe0dbdfd785eeb11daf60abc4eae9 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 14 Feb 2005 09:21:54 +0000 Subject: [PATCH] New cscanf routines by Greg King git-svn-id: svn://svn.cc65.org/cc65/trunk@3378 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/conio/Makefile | 18 +++++- libsrc/conio/cscanf.s | 62 ++++++++++++++++++++ libsrc/conio/vcscanf.s | 130 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 libsrc/conio/cscanf.s create mode 100644 libsrc/conio/vcscanf.s diff --git a/libsrc/conio/Makefile b/libsrc/conio/Makefile index b19abe9cb..9fb54428b 100644 --- a/libsrc/conio/Makefile +++ b/libsrc/conio/Makefile @@ -1,5 +1,6 @@ +# -*- makefile -*- # -# makefile for CC65 runtime library +# makefile for CC65's console library # .SUFFIXES: .o .s .c @@ -26,6 +27,15 @@ 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 @@ -33,9 +43,11 @@ OBJS = _cursor.o \ cprintf.o \ cputhex.o \ cputs.o \ + cscanf.o \ cursor.o \ scrsize.o \ - vcprintf.o + vcprintf.o \ + vcscanf.o #-------------------------------------------------------------------------- # Targets @@ -45,7 +57,7 @@ OBJS = _cursor.o \ all: $(OBJS) clean: - @$(RM) *~ $(OBJS) + @$(RM) *~ *.lst $(OBJS) zap: clean diff --git a/libsrc/conio/cscanf.s b/libsrc/conio/cscanf.s new file mode 100644 index 000000000..3725f96fa --- /dev/null +++ b/libsrc/conio/cscanf.s @@ -0,0 +1,62 @@ +; +; int cscanf(const char* format, ...); +; +; 2000-12-01, Ullrich von Bassewitz +; 2005-01-01, Greg King +; + + .export _cscanf + + .import pushax, addysp, _vcscanf + + .macpack generic + .include "zeropage.inc" + +; ---------------------------------------------------------------------------- +; Code +; +_cscanf: + sty ArgSize ; Number of argument bytes passed in .Y + dey ; subtract size of format pointer + dey + tya + +; Now, calculate the va_list pointer -- which points to format. + + ldx sp+1 + add sp + bcc @L1 + inx +@L1: sta ptr1 + stx ptr1+1 + +; Push a copy of the format pointer onto the stack. + + ldy #1 + lda (ptr1),y + tax + dey + lda (ptr1),y + jsr pushax + +; Load va_list [last and __fastcall__ argument for vcscanf()]. + + lda ptr1 + ldx ptr1+1 + +; Call vcscanf(). + + jsr _vcscanf + +; Clean up the stack. We will return what we got from vcscanf(). + + ldy ArgSize + jmp addysp + +; ---------------------------------------------------------------------------- +; Data +; + .bss +ArgSize: + .res 1 ; Number of argument bytes + diff --git a/libsrc/conio/vcscanf.s b/libsrc/conio/vcscanf.s new file mode 100644 index 000000000..a55704dfd --- /dev/null +++ b/libsrc/conio/vcscanf.s @@ -0,0 +1,130 @@ +; +; int fastcall vcscanf(const char* format, va_list ap); +; +; 2005-01-02, Greg King +; + + .export _vcscanf + + .import _cgetc, _cputc + .import popax, pushax, swapstk + + .include "../common/_scanf.inc" + + +; static bool pushed; +; static char back; +; + .bss +pushed: .res 1 +back: .res 1 + + .code +; /* Call-back functions: +; ** (Note: These prototypes must NOT be declared with fastcall! They don't +; ** use (getfunc)'s and (ungetfunc)'s last parameter. Leaving it out of these +; ** prototypes makes more efficient code.) +; */ + +; ---------------------------------------------------------------------------- +; /* Read a character from the console, and return it to an internal function */ +; static int get(void) { +; static char C; +; +; if (pushed) { +; pushed = false; +; return (int)back; +; } +; cputc(C = cgetc()); /* echo a typed character */ +; return (int)C; +; } +; +get: ldx pushed + beq L1 + +; Return the old, pushed-back character (instead of getting a new one). +; + dex ; ldx #>0 + stx pushed + lda back + rts + +; Directly read the keyboard. +; +L1: jsr _cgetc + +; Echo the character to the screen. +; + pha + jsr _cputc + pla + ldx #>0 + rts + + +; ---------------------------------------------------------------------------- +; static int unget(int c) { +; pushed = true; +; return back = c; +; } +; +unget: ldx #1 + stx pushed + jsr popax ; get the first argument + sta back + rts + + +; ---------------------------------------------------------------------------- +; int fastcall vcscanf(const char* format, va_list ap) { +; /* Initiate the data structure. +; ** Don't initiate the member that these conio functions don't use. +; */ +; static const struct scanfdata d = { +; ( getfunc) get, +; (ungetfunc)unget +; }; +; +; /* conio is very interactive. So, don't use any pushed-back character. +; ** Start fresh, each time that this function is called. +; */ +; pushed = false; +; +; /* Call the internal function, and return the result. */ +; return _scanf(&d, format, ap); +; } +; +; Beware: Because ap is a fastcall parameter, we must not destroy .XA. +; + .proc _vcscanf + +; ---------------------------------------------------------------------------- +; Static, constant scanfdata structure for the _vcscanf routine. +; + .rodata +d: .addr get ; SCANFDATA::GET + .addr unget ; SCANFDATA::UNGET +; .addr 0 ; SCANFDATA::DATA (not used) + + .code + pha ; Save low byte of ap + txa + pha ; Save high byte of ap + ldx #0 + stx pushed + +; Put &d on the stack in front of the format pointer. + + lda #d + jsr swapstk ; Swap .XA with top-of-stack + jsr pushax ; Put format pointer back on stack + +; Restore ap, and jump to _scanf which will clean up the stack. + + pla + tax + pla + jmp __scanf + .endproc + -- 2.39.5