mirror of
https://github.com/cc65/cc65.git
synced 2025-02-26 23:30:03 +00:00
Removed tabs from the foreign sources
git-svn-id: svn://svn.cc65.org/cc65/trunk@3379 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
0a12a012e6
commit
de4162a63f
@ -36,42 +36,42 @@ extern void __fastcall__ _seterrno (unsigned char code);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SetJmp return codes */
|
||||
/* SetJmp return codes */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
RC_OK, /* setjmp() call */
|
||||
RC_NOCONV, /* No conversion possible */
|
||||
RC_EOF /* EOF reached */
|
||||
RC_OK, /* setjmp() call */
|
||||
RC_NOCONV, /* No conversion possible */
|
||||
RC_EOF /* EOF reached */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static const char* format; /* Copy of function argument */
|
||||
static const struct scanfdata* D_; /* Copy of function argument */
|
||||
static va_list ap; /* Copy of function argument */
|
||||
static jmp_buf JumpBuf; /* "Label" that is used for failures */
|
||||
static char F; /* Character from format string */
|
||||
static unsigned CharCount; /* Characters read so far */
|
||||
static int C; /* Character from input */
|
||||
static unsigned Width; /* Maximum field width */
|
||||
static long IntVal; /* Converted int value */
|
||||
static int Assignments; /* Number of assignments */
|
||||
static unsigned char IntBytes; /* Number of bytes-1 for int conversions */
|
||||
static const char* format; /* Copy of function argument */
|
||||
static const struct scanfdata* D_; /* Copy of function argument */
|
||||
static va_list ap; /* Copy of function argument */
|
||||
static jmp_buf JumpBuf; /* "Label" that is used for failures */
|
||||
static char F; /* Character from format string */
|
||||
static unsigned CharCount; /* Characters read so far */
|
||||
static int C; /* Character from input */
|
||||
static unsigned Width; /* Maximum field width */
|
||||
static long IntVal; /* Converted int value */
|
||||
static int Assignments; /* Number of assignments */
|
||||
static unsigned char IntBytes; /* Number of bytes-1 for int conversions */
|
||||
|
||||
/* Flags */
|
||||
static bool Converted; /* Some object was converted */
|
||||
static bool Positive; /* Flag for positive value */
|
||||
static bool NoAssign; /* Suppress assignment */
|
||||
static bool Invert; /* Do we need to invert the charset? */
|
||||
static bool Converted; /* Some object was converted */
|
||||
static bool Positive; /* Flag for positive value */
|
||||
static bool NoAssign; /* Suppress assignment */
|
||||
static bool Invert; /* Do we need to invert the charset? */
|
||||
static unsigned char CharSet[(1+UCHAR_MAX)/CHAR_BIT];
|
||||
static const unsigned char Bits[CHAR_BIT] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
|
||||
@ -89,7 +89,7 @@ static const unsigned char Bits[CHAR_BIT] = {
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Character sets */
|
||||
/* Character sets */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -107,13 +107,13 @@ static unsigned FindBit (void)
|
||||
*/
|
||||
{
|
||||
asm ("pha");
|
||||
asm ("lsr a"); /* Divide by CHAR_BIT */
|
||||
asm ("lsr a"); /* Divide by CHAR_BIT */
|
||||
asm ("lsr a");
|
||||
asm ("lsr a");
|
||||
asm ("tax"); /* Byte's offset */
|
||||
asm ("tax"); /* Byte's offset */
|
||||
asm ("pla");
|
||||
asm ("and #%b", CHAR_BIT-1);
|
||||
asm ("tay"); /* Bit's offset */
|
||||
asm ("tay"); /* Bit's offset */
|
||||
asm ("lda %v,y", Bits);
|
||||
return (unsigned) __AX__;
|
||||
}
|
||||
@ -139,7 +139,7 @@ static unsigned char IsCharInSet (void)
|
||||
/* Get the character from C. */
|
||||
asm ("lda #$00");
|
||||
asm ("ldx %v+1", C);
|
||||
asm ("bne L1"); /* EOF never is in the set */
|
||||
asm ("bne L1"); /* EOF never is in the set */
|
||||
asm ("lda %v", C);
|
||||
FindBit();
|
||||
asm ("and %v,x", CharSet);
|
||||
@ -167,7 +167,7 @@ static void InvertCharSet (void)
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -290,7 +290,7 @@ static void CheckEnd (void)
|
||||
asm ("ldx %v+1", C);
|
||||
asm ("beq %g", Done);
|
||||
|
||||
Error (RC_EOF);
|
||||
Error (RC_EOF);
|
||||
Done:
|
||||
}
|
||||
|
||||
@ -300,7 +300,7 @@ static void SkipWhite (void)
|
||||
/* Skip white space in the input and return the first non white character */
|
||||
{
|
||||
while ((bool) isspace (C)) {
|
||||
ReadChar ();
|
||||
ReadChar ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,8 +346,8 @@ static unsigned char __fastcall__ HexVal (char C)
|
||||
/* Convert a digit to a value */
|
||||
{
|
||||
return (bool) isdigit (C) ?
|
||||
C - '0' :
|
||||
(char) tolower ((int) C) - ('a' - 10);
|
||||
C - '0' :
|
||||
(char) tolower ((int) C) - ('a' - 10);
|
||||
}
|
||||
|
||||
|
||||
@ -360,15 +360,15 @@ static void __fastcall__ ReadInt (unsigned char Base)
|
||||
/* Read the integer value */
|
||||
IntVal = 0L;
|
||||
while ((bool) isxdigit (C) && ++Width != 0
|
||||
&& (Val = HexVal ((char) C)) < Base) {
|
||||
++CharCount;
|
||||
IntVal = IntVal * (long) Base + (long) Val;
|
||||
ReadChar ();
|
||||
&& (Val = HexVal ((char) C)) < Base) {
|
||||
++CharCount;
|
||||
IntVal = IntVal * (long) Base + (long) Val;
|
||||
ReadChar ();
|
||||
}
|
||||
|
||||
/* If we didn't convert anything, it's a failure. */
|
||||
if (CharCount == 0) {
|
||||
Error (RC_NOCONV);
|
||||
Error (RC_NOCONV);
|
||||
}
|
||||
|
||||
/* Another conversion */
|
||||
@ -403,10 +403,10 @@ Loop: asm ("lda %v,y", IntVal);
|
||||
asm ("dey");
|
||||
asm ("bpl %g", Loop);
|
||||
|
||||
/* Another assignment */
|
||||
asm ("inc %v", Assignments);
|
||||
asm ("bne %g", Done);
|
||||
asm ("inc %v+1", Assignments);
|
||||
/* Another assignment */
|
||||
asm ("inc %v", Assignments);
|
||||
asm ("bne %g", Done);
|
||||
asm ("inc %v+1", Assignments);
|
||||
Done:
|
||||
}
|
||||
}
|
||||
@ -432,17 +432,17 @@ static void __fastcall__ ScanInt (unsigned char Base)
|
||||
case 'x':
|
||||
case 'X':
|
||||
Base = 16;
|
||||
Converted = true;
|
||||
Converted = true;
|
||||
ReadChar ();
|
||||
break;
|
||||
default:
|
||||
Base = 8;
|
||||
|
||||
/* Restart at the beginning of the number because it might
|
||||
* be only a single zero digit (which already was read).
|
||||
*/
|
||||
PushBack ();
|
||||
C = '0';
|
||||
/* Restart at the beginning of the number because it might
|
||||
* be only a single zero digit (which already was read).
|
||||
*/
|
||||
PushBack ();
|
||||
C = '0';
|
||||
}
|
||||
} else {
|
||||
Base = 10;
|
||||
@ -480,23 +480,23 @@ static char GetFormat (void)
|
||||
|
||||
|
||||
int __fastcall__ _scanf (const struct scanfdata* D,
|
||||
const char* format_, va_list ap_)
|
||||
const char* format_, va_list ap_)
|
||||
/* This is the routine used to do the actual work. It is called from several
|
||||
* types of wrappers to implement the actual ISO xxscanf functions.
|
||||
*/
|
||||
{
|
||||
register char* S;
|
||||
bool HaveWidth; /* True if a width was given */
|
||||
bool Match; /* True if a character-set has any matches */
|
||||
bool Match; /* True if a character-set has any matches */
|
||||
char Start; /* Walks over a 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
|
||||
* do not have to be passed as parameters.
|
||||
*/
|
||||
D_ = D;
|
||||
D_ = D;
|
||||
format = format_;
|
||||
ap = ap_;
|
||||
ap = ap_;
|
||||
|
||||
/* Initialize variables */
|
||||
Converted = false;
|
||||
@ -509,81 +509,81 @@ int __fastcall__ _scanf (const struct scanfdata* D,
|
||||
if ((unsigned char) setjmp (JumpBuf) == RC_OK) {
|
||||
Again:
|
||||
|
||||
/* Get the next input character */
|
||||
ReadChar ();
|
||||
/* Get the next input character */
|
||||
ReadChar ();
|
||||
|
||||
/* Walk over the format string */
|
||||
while (GetFormat ()) {
|
||||
/* Walk over the format string */
|
||||
while (GetFormat ()) {
|
||||
|
||||
/* Check for a conversion */
|
||||
if (F != '%') {
|
||||
/* Check for a conversion */
|
||||
if (F != '%') {
|
||||
|
||||
/* Check for a match */
|
||||
if ((bool) isspace ((int) F)) {
|
||||
/* Check for a match */
|
||||
if ((bool) isspace ((int) F)) {
|
||||
|
||||
/* Special white space handling: Any whitespace in the
|
||||
/* Special white space handling: Any whitespace in the
|
||||
* format string matches any amount of whitespace including
|
||||
* none(!). So this match will never fail.
|
||||
*/
|
||||
SkipWhite ();
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
SkipWhite ();
|
||||
continue;
|
||||
}
|
||||
|
||||
Percent:
|
||||
/* ### Note: The opposite test (C == F)
|
||||
** would be optimized into buggy code!
|
||||
*/
|
||||
if (C != (int) F) {
|
||||
/* ### Note: The opposite test (C == F)
|
||||
** would be optimized into buggy code!
|
||||
*/
|
||||
if (C != (int) F) {
|
||||
|
||||
/* A mismatch -- we will stop scanning the input,
|
||||
* and return the number of assigned conversions.
|
||||
*/
|
||||
goto NoConv;
|
||||
}
|
||||
/* A mismatch -- we will stop scanning the input,
|
||||
* and return the number of assigned conversions.
|
||||
*/
|
||||
goto NoConv;
|
||||
}
|
||||
|
||||
/* A match -- get the next input character, and continue. */
|
||||
goto Again;
|
||||
/* A match -- get the next input character, and continue. */
|
||||
goto Again;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
/* A conversion. Skip the percent sign. */
|
||||
/* 0. Check for %% */
|
||||
if (GetFormat () == '%') {
|
||||
goto Percent;
|
||||
}
|
||||
/* A conversion. Skip the percent sign. */
|
||||
/* 0. Check for %% */
|
||||
if (GetFormat () == '%') {
|
||||
goto Percent;
|
||||
}
|
||||
|
||||
/* 1. Assignment suppression */
|
||||
NoAssign = (F == '*');
|
||||
if (NoAssign) {
|
||||
GetFormat ();
|
||||
/* 1. Assignment suppression */
|
||||
NoAssign = (F == '*');
|
||||
if (NoAssign) {
|
||||
GetFormat ();
|
||||
}
|
||||
|
||||
/* 2. Maximum field width */
|
||||
Width = UINT_MAX;
|
||||
HaveWidth = (bool) isdigit (F);
|
||||
if (HaveWidth) {
|
||||
Width = 0;
|
||||
Width = UINT_MAX;
|
||||
HaveWidth = (bool) isdigit (F);
|
||||
if (HaveWidth) {
|
||||
Width = 0;
|
||||
do {
|
||||
/* ### Non portable ### */
|
||||
Width = Width * 10 + (F & 0x0F);
|
||||
} while ((bool) isdigit (GetFormat ()));
|
||||
} while ((bool) isdigit (GetFormat ()));
|
||||
}
|
||||
if (Width == 0) {
|
||||
/* Invalid specification */
|
||||
/* Note: This method of leaving the function might seem
|
||||
* to be crude, but it optimizes very well because
|
||||
* the four exits can share this code.
|
||||
*/
|
||||
_seterrno (EINVAL);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
}
|
||||
/* Increment-and-test makes better code than test-and-decrement
|
||||
* does. So, change the width into a form that can be used in
|
||||
* that way.
|
||||
*/
|
||||
Width = ~Width;
|
||||
if (Width == 0) {
|
||||
/* Invalid specification */
|
||||
/* Note: This method of leaving the function might seem
|
||||
* to be crude, but it optimizes very well because
|
||||
* the four exits can share this code.
|
||||
*/
|
||||
_seterrno (EINVAL);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
}
|
||||
/* Increment-and-test makes better code than test-and-decrement
|
||||
* does. So, change the width into a form that can be used in
|
||||
* that way.
|
||||
*/
|
||||
Width = ~Width;
|
||||
|
||||
/* 3. Length modifier */
|
||||
IntBytes = sizeof(int) - 1;
|
||||
@ -593,7 +593,7 @@ Percent:
|
||||
IntBytes = sizeof(char) - 1;
|
||||
++format;
|
||||
}
|
||||
GetFormat ();
|
||||
GetFormat ();
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
@ -604,108 +604,108 @@ Percent:
|
||||
/* FALLTHROUGH */
|
||||
case 'j': /* intmax_t */
|
||||
IntBytes = sizeof(long) - 1;
|
||||
/* FALLTHROUGH */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 'z': /* size_t */
|
||||
case 't': /* ptrdiff_t */
|
||||
/* Same size as int */
|
||||
/* Same size as int */
|
||||
|
||||
case 'L': /* long double - ignore this one */
|
||||
GetFormat ();
|
||||
GetFormat ();
|
||||
}
|
||||
|
||||
/* 4. Conversion specifier */
|
||||
switch (F) {
|
||||
switch (F) {
|
||||
/* 'd' and 'u' conversions are actually the same, since the
|
||||
* standard says that even the 'u' modifier allows an
|
||||
* optionally signed integer.
|
||||
*/
|
||||
case 'd': /* Optionally signed decimal integer */
|
||||
case 'd': /* Optionally signed decimal integer */
|
||||
case 'u':
|
||||
ScanInt (10);
|
||||
break;
|
||||
ScanInt (10);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
/* Optionally signed integer with a base */
|
||||
ScanInt (0);
|
||||
break;
|
||||
case 'i':
|
||||
/* Optionally signed integer with a base */
|
||||
ScanInt (0);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
/* Optionally signed octal integer */
|
||||
ScanInt (8);
|
||||
break;
|
||||
case 'o':
|
||||
/* Optionally signed octal integer */
|
||||
ScanInt (8);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
/* Optionally signed hexadecimal integer */
|
||||
ScanInt (16);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
/* Optionally signed hexadecimal integer */
|
||||
ScanInt (16);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
/* Whitespace-terminated string */
|
||||
SkipWhite ();
|
||||
CheckEnd (); /* Is it an input failure? */
|
||||
case 's':
|
||||
/* Whitespace-terminated string */
|
||||
SkipWhite ();
|
||||
CheckEnd (); /* Is it an input failure? */
|
||||
Converted = true; /* No, conversion will succeed */
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
}
|
||||
while (C != EOF
|
||||
&& (bool) isspace (C) == false
|
||||
&& ++Width) {
|
||||
if (NoAssign == false) {
|
||||
*S++ = C;
|
||||
}
|
||||
ReadChar ();
|
||||
}
|
||||
/* Terminate the string just read */
|
||||
if (NoAssign == false) {
|
||||
*S = '\0';
|
||||
++Assignments;
|
||||
}
|
||||
break;
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
}
|
||||
while (C != EOF
|
||||
&& (bool) isspace (C) == false
|
||||
&& ++Width) {
|
||||
if (NoAssign == false) {
|
||||
*S++ = C;
|
||||
}
|
||||
ReadChar ();
|
||||
}
|
||||
/* Terminate the string just read */
|
||||
if (NoAssign == false) {
|
||||
*S = '\0';
|
||||
++Assignments;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
/* Fixed-length string, NOT zero-terminated */
|
||||
if (HaveWidth == false) {
|
||||
/* No width given, default is 1 */
|
||||
Width = ~1u;
|
||||
}
|
||||
CheckEnd (); /* Is it an input failure? */
|
||||
Converted = true; /* No, at least 1 char. available */
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
/* ## This loop is convenient for us, but it isn't
|
||||
* standard C. The standard implies that a failure
|
||||
* shouldn't put anything into the array argument.
|
||||
*/
|
||||
case 'c':
|
||||
/* Fixed-length string, NOT zero-terminated */
|
||||
if (HaveWidth == false) {
|
||||
/* No width given, default is 1 */
|
||||
Width = ~1u;
|
||||
}
|
||||
CheckEnd (); /* Is it an input failure? */
|
||||
Converted = true; /* No, at least 1 char. available */
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
/* ## This loop is convenient for us, but it isn't
|
||||
* standard C. The standard implies that a failure
|
||||
* shouldn't put anything into the array argument.
|
||||
*/
|
||||
while (++Width) {
|
||||
CheckEnd (); /* Is it a matching failure? */
|
||||
CheckEnd (); /* Is it a matching failure? */
|
||||
*S++ = C;
|
||||
ReadChar ();
|
||||
}
|
||||
++Assignments;
|
||||
} else {
|
||||
++Assignments;
|
||||
} else {
|
||||
/* Just skip as many chars as given */
|
||||
while (++Width) {
|
||||
CheckEnd (); /* Is it a matching failure? */
|
||||
CheckEnd (); /* Is it a matching failure? */
|
||||
ReadChar ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* String using characters from a set */
|
||||
case '[':
|
||||
/* String using characters from a set */
|
||||
/* Clear the set */
|
||||
memset (CharSet, 0, sizeof (CharSet));
|
||||
/* Skip the left-bracket, and test for inversion. */
|
||||
Invert = (GetFormat () == '^');
|
||||
/* Skip the left-bracket, and test for inversion. */
|
||||
Invert = (GetFormat () == '^');
|
||||
if (Invert) {
|
||||
GetFormat ();
|
||||
}
|
||||
if (F == ']') {
|
||||
/* Empty sets aren't allowed; so, a right-bracket
|
||||
* at the beginning must be a member of the set.
|
||||
*/
|
||||
/* Empty sets aren't allowed; so, a right-bracket
|
||||
* at the beginning must be a member of the set.
|
||||
*/
|
||||
AddCharToSet (F);
|
||||
GetFormat ();
|
||||
}
|
||||
@ -716,16 +716,16 @@ Percent:
|
||||
Start = F;
|
||||
++format;
|
||||
switch (GetFormat ()) {
|
||||
case '\0':
|
||||
case ']':
|
||||
case '\0':
|
||||
case ']':
|
||||
/* '-' as last char means: include '-' */
|
||||
AddCharToSet (Start);
|
||||
AddCharToSet ('-');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
/* Include all characters
|
||||
* that are in the range.
|
||||
*/
|
||||
* that are in the range.
|
||||
*/
|
||||
while (1) {
|
||||
AddCharToSet (Start);
|
||||
if (Start == F) {
|
||||
@ -743,11 +743,11 @@ Percent:
|
||||
GetFormat ();
|
||||
}
|
||||
}
|
||||
/* Don't go beyond the end of the format string. */
|
||||
/* (Maybe, this should mean an invalid specification.) */
|
||||
if (F == '\0') {
|
||||
--format;
|
||||
}
|
||||
/* Don't go beyond the end of the format string. */
|
||||
/* (Maybe, this should mean an invalid specification.) */
|
||||
if (F == '\0') {
|
||||
--format;
|
||||
}
|
||||
|
||||
/* Invert the set if requested */
|
||||
if (Invert) {
|
||||
@ -758,102 +758,102 @@ Percent:
|
||||
* store them into a string while they are part of
|
||||
* the set.
|
||||
*/
|
||||
Match = false;
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
}
|
||||
Match = false;
|
||||
if (NoAssign == false) {
|
||||
S = va_arg (ap, char*);
|
||||
}
|
||||
while (IsCharInSet () && ++Width) {
|
||||
if (NoAssign == false) {
|
||||
if (NoAssign == false) {
|
||||
*S++ = C;
|
||||
}
|
||||
Match = Converted = true;
|
||||
ReadChar ();
|
||||
}
|
||||
Match = Converted = true;
|
||||
ReadChar ();
|
||||
}
|
||||
/* At least one character must match the set. */
|
||||
if (Match == false) {
|
||||
goto NoConv;
|
||||
}
|
||||
if (NoAssign == false) {
|
||||
/* At least one character must match the set. */
|
||||
if (Match == false) {
|
||||
goto NoConv;
|
||||
}
|
||||
if (NoAssign == false) {
|
||||
*S = '\0';
|
||||
++Assignments;
|
||||
}
|
||||
break;
|
||||
++Assignments;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
/* Pointer, general format is 0xABCD.
|
||||
* %hhp --> zero-page pointer
|
||||
* %hp --> near pointer
|
||||
* %lp --> far pointer
|
||||
*/
|
||||
SkipWhite ();
|
||||
if (CHAR (C) != '0') {
|
||||
goto NoConv;
|
||||
case 'p':
|
||||
/* Pointer, general format is 0xABCD.
|
||||
* %hhp --> zero-page pointer
|
||||
* %hp --> near pointer
|
||||
* %lp --> far pointer
|
||||
*/
|
||||
SkipWhite ();
|
||||
if (CHAR (C) != '0') {
|
||||
goto NoConv;
|
||||
}
|
||||
Converted = true;
|
||||
ReadChar ();
|
||||
switch (CHAR (C)) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
break;
|
||||
default:
|
||||
goto NoConv;
|
||||
}
|
||||
Converted = true;
|
||||
ReadChar ();
|
||||
switch (CHAR (C)) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
break;
|
||||
default:
|
||||
goto NoConv;
|
||||
}
|
||||
ReadChar ();
|
||||
ReadInt (16);
|
||||
AssignInt ();
|
||||
break;
|
||||
AssignInt ();
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
/* Store the number of characters consumed so far
|
||||
* (the read-ahead character hasn't been consumed).
|
||||
*/
|
||||
IntVal = (long) (CharCount - (C == EOF ? 0u : 1u));
|
||||
AssignInt ();
|
||||
/* Don't count it. */
|
||||
if (NoAssign == false) {
|
||||
--Assignments;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
/* Store the number of characters consumed so far
|
||||
* (the read-ahead character hasn't been consumed).
|
||||
*/
|
||||
IntVal = (long) (CharCount - (C == EOF ? 0u : 1u));
|
||||
AssignInt ();
|
||||
/* Don't count it. */
|
||||
if (NoAssign == false) {
|
||||
--Assignments;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
case 'C':
|
||||
/* Wide characters */
|
||||
case 'S':
|
||||
case 'C':
|
||||
/* Wide characters */
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
/* Optionally signed float */
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
/* Optionally signed float */
|
||||
|
||||
/* Those 2 groups aren't implemented. */
|
||||
_seterrno (ENOSYS);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
/* Those 2 groups aren't implemented. */
|
||||
_seterrno (ENOSYS);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
|
||||
default:
|
||||
/* Invalid specification */
|
||||
_seterrno (EINVAL);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
/* Invalid specification */
|
||||
_seterrno (EINVAL);
|
||||
Assignments = EOF;
|
||||
PushBack ();
|
||||
return Assignments;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NoConv:
|
||||
|
||||
/* Coming here means a failure. If that happens at EOF, with no
|
||||
/* Coming here means a failure. If that happens at EOF, with no
|
||||
* conversion attempts, then it is considered an error; otherwise,
|
||||
* the number of assignments is returned (the default behaviour).
|
||||
* the number of assignments is returned (the default behaviour).
|
||||
*/
|
||||
if (C == EOF && Converted == false) {
|
||||
Assignments = EOF; /* Special case: error */
|
||||
}
|
||||
if (C == EOF && Converted == false) {
|
||||
Assignments = EOF; /* Special case: error */
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the read-ahead character back into the input stream. */
|
||||
|
@ -5,18 +5,18 @@
|
||||
; 2004-12-31, Greg King
|
||||
;
|
||||
|
||||
.export _scanf
|
||||
.export _scanf
|
||||
|
||||
.import _stdin, pushax, addysp, _vfscanf
|
||||
.import sp:zp, ptr1:zp
|
||||
.import _stdin, pushax, addysp, _vfscanf
|
||||
.import sp:zp, ptr1:zp
|
||||
|
||||
.macpack generic
|
||||
.macpack generic
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; Code
|
||||
;
|
||||
_scanf:
|
||||
sty ArgSize ; Number of argument bytes passed in .Y
|
||||
sty ArgSize ; Number of argument bytes passed in .Y
|
||||
|
||||
; We are using a (hopefully) clever trick here to reduce code size. On entry,
|
||||
; the stack pointer points to the last pushed argument of the variable
|
||||
@ -28,47 +28,47 @@ _scanf:
|
||||
; * we will have the address of the Format argument which needs to
|
||||
; be pushed next.
|
||||
|
||||
lda _stdin
|
||||
ldx _stdin+1
|
||||
jsr pushax
|
||||
lda _stdin
|
||||
ldx _stdin+1
|
||||
jsr pushax
|
||||
|
||||
; Now, calculate the va_list pointer, which does point to Format.
|
||||
|
||||
lda sp
|
||||
ldx sp+1
|
||||
add ArgSize
|
||||
bcc @L1
|
||||
inx
|
||||
@L1: sta ptr1
|
||||
stx ptr1+1
|
||||
lda sp
|
||||
ldx sp+1
|
||||
add ArgSize
|
||||
bcc @L1
|
||||
inx
|
||||
@L1: sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Push a copy of Format.
|
||||
|
||||
ldy #1
|
||||
lda (ptr1),y
|
||||
tax
|
||||
dey
|
||||
lda (ptr1),y
|
||||
jsr pushax
|
||||
ldy #1
|
||||
lda (ptr1),y
|
||||
tax
|
||||
dey
|
||||
lda (ptr1),y
|
||||
jsr pushax
|
||||
|
||||
; Load va_list [last and __fastcall__ argument to vfscanf()].
|
||||
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
|
||||
; Call vfscanf().
|
||||
|
||||
jsr _vfscanf
|
||||
jsr _vfscanf
|
||||
|
||||
; Clean up the stack. We will return what we got from vfscanf().
|
||||
|
||||
ldy ArgSize
|
||||
jmp addysp
|
||||
ldy ArgSize
|
||||
jmp addysp
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; Data
|
||||
;
|
||||
.bss
|
||||
.bss
|
||||
ArgSize:
|
||||
.res 1 ; Number of argument bytes
|
||||
.res 1 ; Number of argument bytes
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user