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
This commit is contained in:
cuz
2002-03-24 13:26:18 +00:00
parent d4cb713197
commit 6e37905b18
15 changed files with 295 additions and 99 deletions

View File

@@ -33,3 +33,4 @@ sscanf.s
strtok.s strtok.s
strxfrm.s strxfrm.s
vprintf.s vprintf.s
vsscanf.s

View File

@@ -116,6 +116,7 @@ S_OBJS = _fdesc.o \
vcprintf.o \ vcprintf.o \
vfprintf.o \ vfprintf.o \
vsprintf.o \ vsprintf.o \
vsscanf.o \
zerobss.o zerobss.o

View File

@@ -6,34 +6,37 @@
.export __fdesc .export __fdesc
.import return0, __filetab .import return0
.importzp tmp1
.include "_file.inc"
.proc __fdesc
__fdesc:
ldy #0 ldy #0
L1: lda __filetab+1,y ; load flags lda #_FOPEN
beq L2 ; jump if empty (== CLOSED) Loop: and __filetab + _FILE_f_flags,y ; load flags
beq Found ; jump if closed
.repeat ::_FILE_size
iny iny
iny .endrepeat
cpy #16 ; Done? cpy #(FOPEN_MAX * _FILE_size) ; Done?
bne L1 bne Loop
; File table is full ; File table is full
jmp return0 jmp return0
; Free slot found ; Free slot found, get address
L2: sty tmp1 ; Offset Found: tya ; Offset
lda #<__filetab
ldx #>__filetab
clc clc
adc tmp1 adc #<__filetab
tay ldx #>__filetab ; High byte
txa bcc @L1 ; Jump if no overflow
adc #0 inx ; Bump high byte
tax @L1: rts
tya
rts .endproc

View File

@@ -1,7 +1,7 @@
/* /*
* _file.h * _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 _FOPEN 0x01
#define _FEOF 0x02 #define _FEOF 0x02
#define _FERROR 0x04 #define _FERROR 0x04
#define _FPUSHBACK 0x08

27
libsrc/common/_file.inc Normal file
View File

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

View File

@@ -6,23 +6,26 @@
.export __filetab, _stdin, _stdout, _stderr .export __filetab, _stdin, _stdout, _stderr
.include "_file.inc"
.data .data
__filetab: __filetab:
in: .byte 0, 1 ; stdin .byte 0, _FOPEN ; stdin
out: .byte 1, 1 ; stdout .byte 1, _FOPEN ; stdout
err: .byte 2, 1 ; stderr .byte 2, _FOPEN ; stderr
.byte 0, 0 ; free slot .repeat FOPEN_MAX - 3
.byte 0, 0 ; free slot .byte 0, _FCLOSED ; free slot
.byte 0, 0 ; free slot .endrepeat
.byte 0, 0 ; free slot
.byte 0, 0 ; free slot
; Standard file descriptors
_stdin: _stdin:
.word in .word __filetab + (0 * _FILE_size)
_stdout: _stdout:
.word out .word __filetab + (1 * _FILE_size)
_stderr: _stderr:
.word err .word __filetab + (2 * _FILE_size)

View File

@@ -1,15 +1,18 @@
/* /*
* _scanf.c * _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 <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <setjmp.h> #include <setjmp.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
@@ -49,6 +52,11 @@ static unsigned char Positive; /* Flag for positive value */
static unsigned char NoAssign; /* Supppress assigment */ static unsigned char NoAssign; /* Supppress assigment */
static unsigned char IsShort; /* Short type */ static unsigned char IsShort; /* Short type */
static unsigned char IsLong; /* Long 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
};
@@ -58,6 +66,45 @@ static unsigned char IsLong; /* Long type */
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 */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
@@ -126,7 +173,6 @@ static void ReadInt (unsigned char Base)
/* Read the value */ /* Read the value */
IntVal = 0; IntVal = 0;
while (isxdigit (C) && Width-- > 0) { while (isxdigit (C) && Width-- > 0) {
printf ("ReadInt: '%c'\n", C);
IntVal = IntVal * Base + HexVal (C); IntVal = IntVal * Base + HexVal (C);
ReadChar (); ReadChar ();
} }
@@ -170,6 +216,7 @@ int _scanf (struct indesc* D_, const char* format, va_list ap_)
char* S; char* S;
unsigned char Base; /* Integer base in %i */ unsigned char Base; /* Integer base in %i */
unsigned char HaveWidth; /* True if a width was given */ 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 /* 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 * 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. * is reached.
*/ */
Result = setjmp (JumpBuf); Result = setjmp (JumpBuf);
printf ("Result = %u\n", Result);
if (Result == RC_OK) { if (Result == RC_OK) {
Again: Again:
@@ -219,7 +265,6 @@ Again:
/* A mismatch. We will stop scanning the input and return /* A mismatch. We will stop scanning the input and return
* the number of conversions. * the number of conversions.
*/ */
printf ("F = '%c', C = '%c' --> mismatch\n", F, C);
return Conversions; return Conversions;
} else { } else {
@@ -265,7 +310,6 @@ Again:
FlagsDone: FlagsDone:
/* Check for the actual conversion character */ /* Check for the actual conversion character */
printf ("F = '%c'\n", F);
switch (F) { switch (F) {
case 'D': case 'D':
@@ -352,6 +396,7 @@ FlagsDone:
if (!NoAssign) { if (!NoAssign) {
*S = '\0'; *S = '\0';
} }
++Conversions;
break; break;
case 'c': case 'c':
@@ -362,28 +407,108 @@ FlagsDone:
} }
if (!NoAssign) { if (!NoAssign) {
S = va_arg (ap, char*); S = va_arg (ap, char*);
}
while (Width--) { while (Width--) {
if (!NoAssign) {
*S++ = C; *S++ = C;
}
ReadChar (); ReadChar ();
} }
} else {
/* Just skip as many chars as given */
while (Width--) {
ReadChar ();
}
}
++Conversions; ++Conversions;
break; break;
case '[': case '[':
/* String using characters from a set */ /* 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; break;
case 'p': 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; break;
case 'n': case 'n':
/* Store characters consumed so far */ /* Store characters consumed so far */
IntVal = D->ccount; IntVal = D->ccount;
IsLong = 0;
AssignInt (); AssignInt ();
break; break;

View File

@@ -15,7 +15,7 @@ int fclose (FILE* f)
if ((f->f_flags & _FOPEN) == 0) { if ((f->f_flags & _FOPEN) == 0) {
/* File is not open */ /* File is not open */
_errno = EINVAL; /* File not input */ _errno = EINVAL; /* File not input */
return -1; return EOF;
} }
/* Reset the flags and close the file */ /* Reset the flags and close the file */

View 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);
*/ */
@@ -13,13 +14,19 @@
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int fgetc (FILE* f) int fgetc (FILE* f)
{ {
char c; unsigned char c;
/* Check if the file is open or if there is an error condition */ /* 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) { if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
return -1; return EOF;
} }
/* Read the byte */ /* Read the byte */
@@ -28,16 +35,16 @@ int fgetc (FILE* f)
case -1: case -1:
/* Error */ /* Error */
f->f_flags |= _FERROR; f->f_flags |= _FERROR;
return -1; return EOF;
case 0: case 0:
/* EOF */ /* EOF */
f->f_flags |= _FEOF; f->f_flags |= _FEOF;
return -1; return EOF;
default: default:
/* Char read */ /* Char read */
return ((int) c) & 0xFF; return c;
} }
} }

View File

@@ -22,7 +22,7 @@ char* fgets (char* s, unsigned size, FILE* f)
/* Get next character */ /* Get next character */
c = fgetc (f); c = fgetc (f);
if (c == -1) { if (c == EOF) {
s [i] = 0; s [i] = 0;
/* Error or EOF */ /* Error or EOF */
if (f->f_flags & _FERROR) { if (f->f_flags & _FERROR) {

View File

@@ -16,14 +16,14 @@ int fputc (int c, FILE* f)
{ {
/* Check if the file is open or if there is an error condition */ /* 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) { if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
return -1; return EOF;
} }
/* Write the byte (knows about byte order!) */ /* Write the byte (knows about byte order!) */
if (write (f->f_fd, &c, 1) <= 0) { if (write (f->f_fd, &c, 1) <= 0) {
/* Error */ /* Error */
f->f_flags |= _FERROR; f->f_flags |= _FERROR;
return -1; return EOF;
} }
/* Return the byte written */ /* Return the byte written */

View 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 */ /* 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) { if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
return -1; return EOF;
} }
/* Write the string */ /* Write the string */

View File

@@ -20,7 +20,7 @@ char* gets (char* s)
/* Get next character */ /* Get next character */
c = fgetc (stdin); c = fgetc (stdin);
if (c == -1) { if (c == EOF) {
/* Error or EOF */ /* Error or EOF */
s [i] = 0; s [i] = 0;
if (stdin->f_flags & _FERROR) { if (stdin->f_flags & _FERROR) {

View File

@@ -1,15 +1,13 @@
/* /*
* sscanf.c * 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 <stdio.h>
#include <string.h>
#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, ...) int sscanf (const char* str, const char* format, ...)
/* Standard C function */ /* Standard C function */
{ {
struct indesc id;
va_list ap; 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 */ /* Setup for variable arguments */
va_start (ap, format); va_start (ap, format);
/* Call the internal function. Since we know that va_end won't do anything, /* Call vsscanf(). Since we know that va_end won't do anything, we will
* we will save the call and return the value directly. * save the call and return the value directly.
*/ */
return _scanf (&id, format, ap); return vsscanf (str, format, ap);
} }

51
libsrc/common/vsscanf.c Normal file
View File

@@ -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);
}