]> git.sur5r.net Git - cc65/commitdiff
Completed _scanf.c, added vsscanf.c, rewrote sscanf.c.
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Mar 2002 13:26:18 +0000 (13:26 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Mar 2002 13:26:18 +0000 (13:26 +0000)
Added an assembler include _file.inc and changed asm code that uses struct
FILE to be independent of its size.
Fixed return codes in several files to use EOF instead of -1.

git-svn-id: svn://svn.cc65.org/cc65/trunk@1205 b7a2c559-68d2-44c3-8de9-860c34a00d81

15 files changed:
libsrc/common/.cvsignore
libsrc/common/Makefile
libsrc/common/_fdesc.s
libsrc/common/_file.h
libsrc/common/_file.inc [new file with mode: 0644]
libsrc/common/_file.s
libsrc/common/_scanf.c
libsrc/common/fclose.c
libsrc/common/fgetc.c
libsrc/common/fgets.c
libsrc/common/fputc.c
libsrc/common/fputs.c
libsrc/common/gets.c
libsrc/common/sscanf.c
libsrc/common/vsscanf.c [new file with mode: 0644]

index 31181a27c0fba2453aaedbee8b1eee10373a1888..68876ae1620d1f88acedc461703ead0de6170047 100644 (file)
@@ -33,3 +33,4 @@ sscanf.s
 strtok.s
 strxfrm.s
 vprintf.s
+vsscanf.s
index a548973854af6cbe1a931c088db5849173e15867..d16393381d5b621cdead7649b10de33802d3912b 100644 (file)
@@ -116,6 +116,7 @@ S_OBJS =    _fdesc.o        \
                vcprintf.o      \
                vfprintf.o      \
                vsprintf.o      \
+                vsscanf.o       \
                zerobss.o
 
 
index 2ffadd5e8cc535d4485b26601fbb96e203100c65..a2cf747ce6520ec87864b6ef3ced50401d1df99a 100644 (file)
@@ -6,34 +6,37 @@
 
 
                .export         __fdesc
-       .import         return0, __filetab
-       .importzp       tmp1
-
-__fdesc:
-       ldy     #0
-L1:    lda     __filetab+1,y   ; load flags
-       beq     L2              ; jump if empty (== CLOSED)
-       iny
-       iny
-       cpy     #16             ; Done?
-       bne     L1
+       .import         return0
+
+        .include        "_file.inc"
+
+.proc   __fdesc
+
+               ldy     #0
+        lda     #_FOPEN
+Loop:          and     __filetab + _FILE_f_flags,y     ; load flags
+               beq     Found                           ; jump if closed
+.repeat ::_FILE_size
+       iny
+.endrepeat
+               cpy     #(FOPEN_MAX * _FILE_size)       ; Done?
+       bne     Loop
 
 ; File table is full
 
-       jmp     return0
-
-; Free slot found
-
-L2:            sty     tmp1            ; Offset
-       lda     #<__filetab
-       ldx     #>__filetab
-       clc
-       adc     tmp1
-       tay
-       txa
-       adc     #0
-       tax
-       tya
-       rts
+       jmp     return0
+
+; Free slot found, get address
+
+Found:  tya                     ; Offset
+        clc
+        adc     #<__filetab
+        ldx     #>__filetab     ; High byte
+        bcc     @L1             ; Jump if no overflow
+        inx                     ; Bump high byte
+@L1:    rts
+
+.endproc
+
 
 
index 8a27796c2512ad44ae6002834592da83f98a746d..e8ba411a31f07af210da9221cadb50da0f882173 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * _file.h
  *
- * Ullrich von Bassewitz, 02.06.1998
+ * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
  *
  */
 
@@ -30,6 +30,7 @@ extern FILE _filetab [FOPEN_MAX];
 #define        _FOPEN          0x01
 #define _FEOF          0x02
 #define _FERROR                0x04
+#define _FPUSHBACK      0x08
 
 
 
diff --git a/libsrc/common/_file.inc b/libsrc/common/_file.inc
new file mode 100644 (file)
index 0000000..14a9412
--- /dev/null
@@ -0,0 +1,27 @@
+;
+; _file.inc
+;
+; (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org)
+;
+
+; Assembler include file that makes the constants and structures in _file.h
+; available for asm code.
+
+; Struct _FILE offsets and size
+_FILE_f_fd      = $00
+_FILE_f_flags   = $01
+_FILE_size      = $02
+
+; Flags field 
+_FCLOSED        = $00
+_FOPEN          = $01
+_FEOF           = $02
+_FERROR         = $04
+_FPUSHBACK      = $08
+                     
+; Maximum number of open files (size of table)
+FOPEN_MAX       = 8
+
+; File table
+.global         __filetab
+
index 19e6ac20257f0c99bc248c9ec5e21eac4025960a..4a4545a873f013bfe259fdcc5d2b85c1b7d025b3 100644 (file)
@@ -6,23 +6,26 @@
 
        .export         __filetab, _stdin, _stdout, _stderr
 
+        .include        "_file.inc"
+
 .data
 
 __filetab:
-in:    .byte   0, 1            ; stdin
-out:   .byte   1, 1            ; stdout
-err:   .byte   2, 1            ; stderr
-       .byte   0, 0            ; free slot
-       .byte   0, 0            ; free slot
-       .byte   0, 0            ; free slot
-       .byte   0, 0            ; free slot
-       .byte   0, 0            ; free slot
+        .byte   0, _FOPEN       ; stdin
+        .byte   1, _FOPEN       ; stdout
+        .byte   2, _FOPEN       ; stderr
+.repeat FOPEN_MAX - 3
+        .byte   0, _FCLOSED     ; free slot
+.endrepeat
+
+
+; Standard file descriptors
 
 _stdin:
-       .word   in
+       .word   __filetab + (0 * _FILE_size)
 
 _stdout:
-       .word   out
+       .word   __filetab + (1 * _FILE_size)
 
 _stderr:
-       .word   err
+       .word   __filetab + (2 * _FILE_size)
index e7d7389dc0e7bc9a23d144d6946ab1a079459869..8dbe2cb77ee8ab733d41cf2e5b172472176c7fbe 100644 (file)
@@ -1,15 +1,18 @@
 /*
  * _scanf.c
  *
- * (C) Copyright 2001 Ullrich von Bassewitz (uz@cc65.org)
+ * (C) Copyright 2001-2002 Ullrich von Bassewitz (uz@cc65.org)
  *
- * This is the basic layer for all scanf type functions.
+ * This is the basic layer for all scanf type functions. It should get
+ * rewritten in assembler at some time in the future, so most of the code
+ * is not as elegant as it could be.
  */
 
 
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 #include <setjmp.h>
 #include <ctype.h>
 #include <limits.h>
@@ -49,15 +52,59 @@ static unsigned char        Positive;       /* Flag for positive value */
 static unsigned char   NoAssign;       /* Supppress assigment */
 static unsigned char   IsShort;        /* Short type */
 static unsigned char   IsLong;         /* Long type */
+static unsigned char    Invert;         /* Do we need to invert the charset? */
+static unsigned char    CharSet[32];    /* 32 * 8 bits = 256 bits */
+static const unsigned char Bits[8] = {
+    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
 
 
 
 /*****************************************************************************/
-/*                             Character sets                               */
+/*                             Character sets                               */
 /*****************************************************************************/
 
 
 
+static void AddCharToSet (unsigned char C)
+/* Set the given bit in the character set */
+{
+    asm ("ldy #%o", C);
+    asm ("lda (sp),y");
+    asm ("lsr a");
+    asm ("lsr a");
+    asm ("lsr a");
+    asm ("tax");
+    asm ("lda (sp),y");
+    asm ("and #$07");
+    asm ("tay");
+    asm ("lda %v,y", Bits);
+    asm ("ora %v,x", CharSet);
+    asm ("sta %v,x", CharSet);
+}
+
+
+
+static unsigned char IsCharInSet (unsigned char C)
+/* Check if the given char is part of the character set */
+{
+    asm ("ldy #%o", C);
+    asm ("lda (sp),y");
+    asm ("lsr a");
+    asm ("lsr a");
+    asm ("lsr a");
+    asm ("tax");
+    asm ("lda (sp),y");
+    asm ("and #$07");
+    asm ("tay");
+    asm ("lda %v,y", Bits);
+    asm ("and %v,x", CharSet);
+    asm ("ldx #$00");
+    return __AX__;
+}
+
+
+
 /*****************************************************************************/
 /*                                  Code                                    */
 /*****************************************************************************/
@@ -126,7 +173,6 @@ static void ReadInt (unsigned char Base)
     /* Read the value */
     IntVal = 0;
     while (isxdigit (C) && Width-- > 0) {
-       printf ("ReadInt: '%c'\n", C);
                IntVal = IntVal * Base + HexVal (C);
        ReadChar ();
     }
@@ -170,6 +216,7 @@ int _scanf (struct indesc* D_, const char* format, va_list ap_)
     char*        S;
     unsigned char Base;                /* Integer base in %i */
     unsigned char HaveWidth;   /* True if a width was given */
+    char          Start;        /* Start of range */
 
     /* Place copies of the arguments into global variables. This is not very
      * nice, but on a 6502 platform it gives better code, since the values
@@ -186,7 +233,6 @@ int _scanf (struct indesc* D_, const char* format, va_list ap_)
      * is reached.
      */
     Result = setjmp (JumpBuf);
-    printf ("Result = %u\n", Result);
     if (Result == RC_OK) {
 
 Again:
@@ -219,10 +265,9 @@ Again:
                    /* A mismatch. We will stop scanning the input and return
                     * the number of conversions.
                     */
-                   printf ("F = '%c', C = '%c' --> mismatch\n", F, C);
                    return Conversions;
 
-               } else {
+               } else {
 
                    /* A match. Read the next input character and start over */
                    goto Again;
@@ -253,11 +298,11 @@ Again:
                        } while (isdigit (F));
                    } else {
                        switch (F) {
-                           case '*':   NoAssign = 1;   break;
+                           case '*':   NoAssign = 1;   break;
                            case 'h':   IsShort = 1;    break;
                            case 'l':
                            case 'L':   IsLong = 1;     break;
-                           default:    goto FlagsDone;
+                           default:    goto FlagsDone;
                        }
                        F = *format++;
                    }
@@ -265,7 +310,6 @@ Again:
 FlagsDone:
 
                /* Check for the actual conversion character */
-               printf ("F = '%c'\n", F);
                switch (F) {
 
                    case 'D':
@@ -291,8 +335,8 @@ FlagsDone:
                                case 'x':
                                case 'X':
                                    Base = 16;
-                                   ReadChar();
-                                   break;
+                                   ReadChar();
+                                   break;
                                default:
                                    Base = 8;
                            }
@@ -308,7 +352,7 @@ FlagsDone:
 
                    case 'o':
                        /* Unsigned octal integer */
-                       SkipWhite ();
+                       SkipWhite ();
                        ReadInt (8);
                        AssignInt ();
                        break;
@@ -351,8 +395,9 @@ FlagsDone:
                        /* Terminate the string just read */
                        if (!NoAssign) {
                            *S = '\0';
-                       }
-                       break;
+                       }
+                        ++Conversions;
+                       break;
 
                    case 'c':
                        /* Fixed length string, NOT zero terminated */
@@ -362,28 +407,108 @@ FlagsDone:
                        }
                        if (!NoAssign) {
                            S = va_arg (ap, char*);
-                       }
-                       while (Width--) {
-                           if (!NoAssign) {
-                               *S++ = C;
-                           }
-                           ReadChar ();
-                       }
+                            while (Width--) {
+                                *S++ = C;
+                                ReadChar ();
+                            }
+                       } else {
+                            /* Just skip as many chars as given */
+                            while (Width--) {
+                                ReadChar ();
+                            }
+                        }
                        ++Conversions;
                        break;
 
                    case '[':
                        /* String using characters from a set */
+                        Invert = 0;
+                        /* Clear the set */
+                        memset (CharSet, 0, sizeof (CharSet));
+                        F = *format++;
+                        if (F == '^') {
+                            Invert = 1;
+                            F = *format++;
+                        }
+                        if (F == ']') {
+                            AddCharToSet (']');
+                            F = *format++;
+                        }
+                        /* Read the characters that are part of the set */
+                        while (F != ']' && F != '\0') {
+                            if (*format == '-') {
+                                /* A range. Get start and end, skip the '-' */
+                                Start = F;
+                                F = *++format;
+                                ++format;
+                                if (F == ']') {
+                                    /* '-' as last char means: include '-' */
+                                    AddCharToSet (Start);
+                                    AddCharToSet ('-');
+                                } else if (F != '\0') {
+                                    /* Include all chars in the range */
+                                    while (1) {
+                                        AddCharToSet (Start);
+                                        if (Start == F) {
+                                            break;
+                                        }
+                                        ++Start;
+                                    }
+                                    /* Get next char after range */
+                                    F = *format++;
+                                }
+                            } else {
+                                /* Just a character */
+                                AddCharToSet (F);
+                                /* Get next char */
+                                F = *format++;
+                            }
+                        }
+
+                        /* Invert the set if requested */
+                        if (Invert) {
+                            for (Start = 0; Start < sizeof (CharSet); ++Start) {
+                                CharSet[Start] ^= 0xFF;
+                            }
+                        }
+
+                        /* We have the set in CharSet. Read characters and
+                         * store them into a string while they are part of
+                         * the set.
+                         */
+                       if (!NoAssign) {
+                           S = va_arg (ap, char*);
+                            while (IsCharInSet (C) && Width--) {
+                                *S++ = C;
+                                ReadChar ();
+                            }
+                            *S = '\0';
+                        } else {
+                            while (IsCharInSet (C) && Width--) {
+                                ReadChar ();
+                            }
+                        }
+                        ++Conversions;
                        break;
 
                    case 'p':
-                       /* Pointer */
+                       /* Pointer, format is 0xABCD */
+                       SkipWhite ();
+                       if (C != '0') {
+                            longjmp (JumpBuf, RC_NOCONV);
+                        }
+                       ReadChar ();
+                        if (C != 'x' && C != 'X') {
+                            longjmp (JumpBuf, RC_NOCONV);
+                        }
+                        ReadChar ();
+                        ReadInt (16);
+                       AssignInt ();
                        break;
 
                    case 'n':
                        /* Store characters consumed so far */
                        IntVal = D->ccount;
-                       IsLong = 0;
                        AssignInt ();
                        break;
 
index 0ab2d422de43fa11578ac7b65672acecb77114a5..8eecbc6053b045aefd434f783fa9fcf7f09d078a 100644 (file)
@@ -15,7 +15,7 @@ int fclose (FILE* f)
     if ((f->f_flags & _FOPEN) == 0) {
        /* File is not open */
                _errno = EINVAL;                /* File not input */
-       return -1;
+       return EOF;
     }
 
     /* Reset the flags and close the file */
index 97e6dcb0bd772e83ba7d662214da30e4f10a48ca..e9bb7d5a7f625f79a88997b57fdbf280f6f9d8a8 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Ullrich von Bassewitz, 11.08.1998
+ * fgetc.c
+ *
+ * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
  *
- * int fgetc (FILE* f);
  */
 
 
 
 
 
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
 int fgetc (FILE* f)
 {
-    char c;
+    unsigned char c;
 
     /* Check if the file is open or if there is an error condition */
     if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
-       return -1;
+       return EOF;
     }
 
     /* Read the byte */
@@ -28,16 +35,16 @@ int fgetc (FILE* f)
         case -1:
            /* Error */
            f->f_flags |= _FERROR;
-           return -1;
+           return EOF;
 
         case 0:
            /* EOF */
            f->f_flags |= _FEOF;
-           return -1;
+           return EOF;
 
         default:
            /* Char read */
-           return ((int) c) & 0xFF;
+           return c;
 
     }
 }
index 10c32bde2635b104ba94197b4e07407960c4009e..7a51e459806dabf60c4a91d947282b76516d3029 100644 (file)
@@ -22,7 +22,7 @@ char* fgets (char* s, unsigned size, FILE* f)
 
                /* Get next character */
                c = fgetc (f);
-               if (c == -1) {
+               if (c == EOF) {
                    s [i] = 0;
                    /* Error or EOF */
                    if (f->f_flags & _FERROR) {
index 012cc052d3f1946561dd7de531ca94c5f46784ca..fdae61768d78b01167d386c46e89a5a6b5de8cb7 100644 (file)
@@ -16,14 +16,14 @@ int fputc (int c, FILE* f)
 {
     /* Check if the file is open or if there is an error condition */
     if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
-       return -1;
+       return EOF;
     }
 
     /* Write the byte (knows about byte order!) */
     if (write (f->f_fd, &c, 1) <= 0) {
        /* Error */
        f->f_flags |= _FERROR;
-       return -1;
+       return EOF;
     }
 
     /* Return the byte written */
index 2fd42efae54a4cff5a203a0279e2f8737fbb7094..26eeb85b32612dab9dbae9cd14fdc64e5b453920 100644 (file)
@@ -17,7 +17,7 @@ int fputs (const char* s, FILE* f)
 {
     /* Check if the file is open or if there is an error condition */
     if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
-       return -1;
+       return EOF;
     }
 
     /* Write the string */
index 4177522d42fa7fe65b864fb0c9143e429d3bd0c5..b1872edc3aae8f97ebb143875669be343436b1e6 100644 (file)
@@ -20,7 +20,7 @@ char* gets (char* s)
 
                /* Get next character */
                c = fgetc (stdin);
-               if (c == -1) {
+               if (c == EOF) {
                    /* Error or EOF */
                    s [i] = 0;
                    if (stdin->f_flags & _FERROR) {
index fdbf440584e116341830b3dc117e60755fa075f3..1a7cd20fc393485ed7dce22bb74ad4ae9138d6cb 100644 (file)
@@ -1,15 +1,13 @@
 /*
  * sscanf.c
  *
- * (C) Copyright 2001 Ullrich von Bassewitz (uz@cc65.org)
+ * (C) Copyright 2001-2002 Ullrich von Bassewitz (uz@cc65.org)
  *
  */
 
 
 
 #include <stdio.h>
-#include <string.h>
-#include "_scanf.h"
 
 
 
 
 
 
-static char get (struct indesc* d)
-/* Read a character from the input string and return it */
-{
-    char C;
-    if (C = d->buf[d->ridx]) {
-       /* Increment index only if end not reached */
-       ++d->ridx;
-    }
-    return C;
-}
-
-
-
 int sscanf (const char* str, const char* format, ...)
 /* Standard C function */
 {
-    struct indesc id;
     va_list ap;
 
-    /* Initialize the indesc struct. We leave all fields uninitialized that we
-     * don't need
-     */
-    id.fin  = (infunc) get;
-    id.buf  = (char*) str;
-    id.ridx = 0;
-
     /* Setup for variable arguments */
     va_start (ap, format);
 
-    /* Call the internal function. Since we know that va_end won't do anything,
-     * we will save the call and return the value directly.
+    /* Call vsscanf(). Since we know that va_end won't do anything, we will
+     * save the call and return the value directly.
      */
-    return _scanf (&id, format, ap);
+    return vsscanf (str, format, ap);
 }
 
 
diff --git a/libsrc/common/vsscanf.c b/libsrc/common/vsscanf.c
new file mode 100644 (file)
index 0000000..7dc28dc
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * vsscanf.c
+ *
+ * (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org)
+ *
+ */
+
+
+
+#include <stdio.h>
+#include "_scanf.h"
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static char get (struct indesc* d)
+/* Read a character from the input string and return it */
+{
+    char C;
+    if (C = d->buf[d->ridx]) {
+       /* Increment index only if end not reached */
+       ++d->ridx;
+    }
+    return C;
+}
+
+
+
+int vsscanf (const char* str, const char* format, va_list ap)
+/* Standard C function */
+{
+    struct indesc id;
+
+    /* Initialize the indesc struct. We leave all fields uninitialized that we
+     * don't need
+     */
+    id.fin  = (infunc) get;
+    id.buf  = (char*) str;
+    id.ridx = 0;
+
+    /* Call the internal function and return the result */
+    return _scanf (&id, format, ap);
+}
+
+
+