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

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