From 6e37905b1898589b70d9d67428a3a5ae9c81cd0f Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 24 Mar 2002 13:26:18 +0000 Subject: [PATCH] Completed _scanf.c, added vsscanf.c, rewrote sscanf.c. 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 --- libsrc/common/.cvsignore | 1 + libsrc/common/Makefile | 1 + libsrc/common/_fdesc.s | 55 +++++++------ libsrc/common/_file.h | 3 +- libsrc/common/_file.inc | 27 ++++++ libsrc/common/_file.s | 25 +++--- libsrc/common/_scanf.c | 173 +++++++++++++++++++++++++++++++++------ libsrc/common/fclose.c | 2 +- libsrc/common/fgetc.c | 21 +++-- libsrc/common/fgets.c | 2 +- libsrc/common/fputc.c | 4 +- libsrc/common/fputs.c | 2 +- libsrc/common/gets.c | 2 +- libsrc/common/sscanf.c | 31 +------ libsrc/common/vsscanf.c | 51 ++++++++++++ 15 files changed, 298 insertions(+), 102 deletions(-) create mode 100644 libsrc/common/_file.inc create mode 100644 libsrc/common/vsscanf.c diff --git a/libsrc/common/.cvsignore b/libsrc/common/.cvsignore index 31181a27c..68876ae16 100644 --- a/libsrc/common/.cvsignore +++ b/libsrc/common/.cvsignore @@ -33,3 +33,4 @@ sscanf.s strtok.s strxfrm.s vprintf.s +vsscanf.s diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile index a54897385..d16393381 100644 --- a/libsrc/common/Makefile +++ b/libsrc/common/Makefile @@ -116,6 +116,7 @@ S_OBJS = _fdesc.o \ vcprintf.o \ vfprintf.o \ vsprintf.o \ + vsscanf.o \ zerobss.o diff --git a/libsrc/common/_fdesc.s b/libsrc/common/_fdesc.s index 2ffadd5e8..a2cf747ce 100644 --- a/libsrc/common/_fdesc.s +++ b/libsrc/common/_fdesc.s @@ -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 + diff --git a/libsrc/common/_file.h b/libsrc/common/_file.h index 8a27796c2..e8ba411a3 100644 --- a/libsrc/common/_file.h +++ b/libsrc/common/_file.h @@ -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 index 000000000..14a9412a7 --- /dev/null +++ b/libsrc/common/_file.inc @@ -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 + diff --git a/libsrc/common/_file.s b/libsrc/common/_file.s index 19e6ac202..4a4545a87 100644 --- a/libsrc/common/_file.s +++ b/libsrc/common/_file.s @@ -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) diff --git a/libsrc/common/_scanf.c b/libsrc/common/_scanf.c index e7d7389dc..8dbe2cb77 100644 --- a/libsrc/common/_scanf.c +++ b/libsrc/common/_scanf.c @@ -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 #include +#include #include #include #include @@ -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; diff --git a/libsrc/common/fclose.c b/libsrc/common/fclose.c index 0ab2d422d..8eecbc605 100644 --- a/libsrc/common/fclose.c +++ b/libsrc/common/fclose.c @@ -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 */ diff --git a/libsrc/common/fgetc.c b/libsrc/common/fgetc.c index 97e6dcb0b..e9bb7d5a7 100644 --- a/libsrc/common/fgetc.c +++ b/libsrc/common/fgetc.c @@ -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); */ @@ -13,13 +14,19 @@ +/*****************************************************************************/ +/* 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; } } diff --git a/libsrc/common/fgets.c b/libsrc/common/fgets.c index 10c32bde2..7a51e4598 100644 --- a/libsrc/common/fgets.c +++ b/libsrc/common/fgets.c @@ -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) { diff --git a/libsrc/common/fputc.c b/libsrc/common/fputc.c index 012cc052d..fdae61768 100644 --- a/libsrc/common/fputc.c +++ b/libsrc/common/fputc.c @@ -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 */ diff --git a/libsrc/common/fputs.c b/libsrc/common/fputs.c index 2fd42efae..26eeb85b3 100644 --- a/libsrc/common/fputs.c +++ b/libsrc/common/fputs.c @@ -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 */ diff --git a/libsrc/common/gets.c b/libsrc/common/gets.c index 4177522d4..b1872edc3 100644 --- a/libsrc/common/gets.c +++ b/libsrc/common/gets.c @@ -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) { diff --git a/libsrc/common/sscanf.c b/libsrc/common/sscanf.c index fdbf44058..1a7cd20fc 100644 --- a/libsrc/common/sscanf.c +++ b/libsrc/common/sscanf.c @@ -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 -#include -#include "_scanf.h" @@ -19,39 +17,18 @@ -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 index 000000000..7dc28dcbb --- /dev/null +++ b/libsrc/common/vsscanf.c @@ -0,0 +1,51 @@ +/* + * vsscanf.c + * + * (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org) + * + */ + + + +#include +#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); +} + + + -- 2.39.5