]> git.sur5r.net Git - cc65/commitdiff
New cscanf routines by Greg King
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 14 Feb 2005 09:21:54 +0000 (09:21 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 14 Feb 2005 09:21:54 +0000 (09:21 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3378 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/conio/Makefile
libsrc/conio/cscanf.s [new file with mode: 0644]
libsrc/conio/vcscanf.s [new file with mode: 0644]

index b19abe9cbb362d6cc7dea30cfbacda5da33f6fe8..9fb54428ba081a98ea1d6f7b51224923ee0173ff 100644 (file)
@@ -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 (file)
index 0000000..3725f96
--- /dev/null
@@ -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 (file)
index 0000000..a55704d
--- /dev/null
@@ -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
+        ldx     #>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
+