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:
@@ -33,3 +33,4 @@ sscanf.s
|
|||||||
strtok.s
|
strtok.s
|
||||||
strxfrm.s
|
strxfrm.s
|
||||||
vprintf.s
|
vprintf.s
|
||||||
|
vsscanf.s
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
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
|
.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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user