1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-24 11:31:31 +00:00

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
strxfrm.s
vprintf.s
vsscanf.s

View File

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

View File

@ -6,34 +6,37 @@
.export __fdesc
.import return0, __filetab
.importzp tmp1
.import return0
__fdesc:
ldy #0
L1: lda __filetab+1,y ; load flags
beq L2 ; jump if empty (== CLOSED)
iny
iny
cpy #16 ; Done?
bne L1
.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
jmp return0
; Free slot found
; 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
L2: sty tmp1 ; Offset
lda #<__filetab
ldx #>__filetab
clc
adc tmp1
tay
txa
adc #0
tax
tya
rts

View 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

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
.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)

View 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;

View 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 */

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

View 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) {

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 */
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 */

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

View 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) {

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

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