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:
parent
d4cb713197
commit
6e37905b18
@ -33,3 +33,4 @@ sscanf.s
|
||||
strtok.s
|
||||
strxfrm.s
|
||||
vprintf.s
|
||||
vsscanf.s
|
||||
|
@ -116,6 +116,7 @@ S_OBJS = _fdesc.o \
|
||||
vcprintf.o \
|
||||
vfprintf.o \
|
||||
vsprintf.o \
|
||||
vsscanf.o \
|
||||
zerobss.o
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
27
libsrc/common/_file.inc
Normal 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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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
51
libsrc/common/vsscanf.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user