Fixed tab removal which somehow went wrong
git-svn-id: svn://svn.cc65.org/cc65/trunk@3382 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
bb66b590a9
commit
bc5d046503
5 changed files with 381 additions and 381 deletions
|
@ -36,42 +36,42 @@ extern void __fastcall__ _seterrno (unsigned char code);
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* SetJmp return codes */
|
/* SetJmp return codes */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RC_OK, /* setjmp() call */
|
RC_OK, /* setjmp() call */
|
||||||
RC_NOCONV, /* No conversion possible */
|
RC_NOCONV, /* No conversion possible */
|
||||||
RC_EOF /* EOF reached */
|
RC_EOF /* EOF reached */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char* format; /* Copy of function argument */
|
static const char* format; /* Copy of function argument */
|
||||||
static const struct scanfdata* D_; /* Copy of function argument */
|
static const struct scanfdata* D_; /* Copy of function argument */
|
||||||
static va_list ap; /* Copy of function argument */
|
static va_list ap; /* Copy of function argument */
|
||||||
static jmp_buf JumpBuf; /* "Label" that is used for failures */
|
static jmp_buf JumpBuf; /* "Label" that is used for failures */
|
||||||
static char F; /* Character from format string */
|
static char F; /* Character from format string */
|
||||||
static unsigned CharCount; /* Characters read so far */
|
static unsigned CharCount; /* Characters read so far */
|
||||||
static int C; /* Character from input */
|
static int C; /* Character from input */
|
||||||
static unsigned Width; /* Maximum field width */
|
static unsigned Width; /* Maximum field width */
|
||||||
static long IntVal; /* Converted int value */
|
static long IntVal; /* Converted int value */
|
||||||
static int Assignments; /* Number of assignments */
|
static int Assignments; /* Number of assignments */
|
||||||
static unsigned char IntBytes; /* Number of bytes-1 for int conversions */
|
static unsigned char IntBytes; /* Number of bytes-1 for int conversions */
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
static bool Converted; /* Some object was converted */
|
static bool Converted; /* Some object was converted */
|
||||||
static bool Positive; /* Flag for positive value */
|
static bool Positive; /* Flag for positive value */
|
||||||
static bool NoAssign; /* Suppress assignment */
|
static bool NoAssign; /* Suppress assignment */
|
||||||
static bool Invert; /* Do we need to invert the charset? */
|
static bool Invert; /* Do we need to invert the charset? */
|
||||||
static unsigned char CharSet[(1+UCHAR_MAX)/CHAR_BIT];
|
static unsigned char CharSet[(1+UCHAR_MAX)/CHAR_BIT];
|
||||||
static const unsigned char Bits[CHAR_BIT] = {
|
static const unsigned char Bits[CHAR_BIT] = {
|
||||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
|
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 ("pha");
|
||||||
asm ("lsr a"); /* Divide by CHAR_BIT */
|
asm ("lsr a"); /* Divide by CHAR_BIT */
|
||||||
asm ("lsr a");
|
asm ("lsr a");
|
||||||
asm ("lsr a");
|
asm ("lsr a");
|
||||||
asm ("tax"); /* Byte's offset */
|
asm ("tax"); /* Byte's offset */
|
||||||
asm ("pla");
|
asm ("pla");
|
||||||
asm ("and #%b", CHAR_BIT-1);
|
asm ("and #%b", CHAR_BIT-1);
|
||||||
asm ("tay"); /* Bit's offset */
|
asm ("tay"); /* Bit's offset */
|
||||||
asm ("lda %v,y", Bits);
|
asm ("lda %v,y", Bits);
|
||||||
return (unsigned) __AX__;
|
return (unsigned) __AX__;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ static unsigned char IsCharInSet (void)
|
||||||
/* Get the character from C. */
|
/* Get the character from C. */
|
||||||
asm ("lda #$00");
|
asm ("lda #$00");
|
||||||
asm ("ldx %v+1", C);
|
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);
|
asm ("lda %v", C);
|
||||||
FindBit();
|
FindBit();
|
||||||
asm ("and %v,x", CharSet);
|
asm ("and %v,x", CharSet);
|
||||||
|
@ -167,7 +167,7 @@ static void InvertCharSet (void)
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@ -432,17 +432,17 @@ static void __fastcall__ ScanInt (unsigned char Base)
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
Base = 16;
|
Base = 16;
|
||||||
Converted = true;
|
Converted = true;
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Base = 8;
|
Base = 8;
|
||||||
|
|
||||||
/* Restart at the beginning of the number because it might
|
/* Restart at the beginning of the number because it might
|
||||||
* be only a single zero digit (which already was read).
|
* be only a single zero digit (which already was read).
|
||||||
*/
|
*/
|
||||||
PushBack ();
|
PushBack ();
|
||||||
C = '0';
|
C = '0';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Base = 10;
|
Base = 10;
|
||||||
|
@ -480,7 +480,7 @@ static char GetFormat (void)
|
||||||
|
|
||||||
|
|
||||||
int __fastcall__ _scanf (const struct scanfdata* D,
|
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
|
/* 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.
|
* types of wrappers to implement the actual ISO xxscanf functions.
|
||||||
*/
|
*/
|
||||||
|
@ -518,72 +518,72 @@ Again:
|
||||||
/* Check for a conversion */
|
/* Check for a conversion */
|
||||||
if (F != '%') {
|
if (F != '%') {
|
||||||
|
|
||||||
/* Check for a match */
|
/* Check for a match */
|
||||||
if ((bool) isspace ((int) F)) {
|
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
|
* format string matches any amount of whitespace including
|
||||||
* none(!). So this match will never fail.
|
* none(!). So this match will never fail.
|
||||||
*/
|
*/
|
||||||
SkipWhite ();
|
SkipWhite ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Percent:
|
Percent:
|
||||||
/* ### Note: The opposite test (C == F)
|
/* ### Note: The opposite test (C == F)
|
||||||
** would be optimized into buggy code!
|
** would be optimized into buggy code!
|
||||||
*/
|
*/
|
||||||
if (C != (int) F) {
|
if (C != (int) F) {
|
||||||
|
|
||||||
/* A mismatch -- we will stop scanning the input,
|
/* A mismatch -- we will stop scanning the input,
|
||||||
* and return the number of assigned conversions.
|
* and return the number of assigned conversions.
|
||||||
*/
|
*/
|
||||||
goto NoConv;
|
goto NoConv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A match -- get the next input character, and continue. */
|
/* A match -- get the next input character, and continue. */
|
||||||
goto Again;
|
goto Again;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* A conversion. Skip the percent sign. */
|
/* A conversion. Skip the percent sign. */
|
||||||
/* 0. Check for %% */
|
/* 0. Check for %% */
|
||||||
if (GetFormat () == '%') {
|
if (GetFormat () == '%') {
|
||||||
goto Percent;
|
goto Percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1. Assignment suppression */
|
/* 1. Assignment suppression */
|
||||||
NoAssign = (F == '*');
|
NoAssign = (F == '*');
|
||||||
if (NoAssign) {
|
if (NoAssign) {
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. Maximum field width */
|
/* 2. Maximum field width */
|
||||||
Width = UINT_MAX;
|
Width = UINT_MAX;
|
||||||
HaveWidth = (bool) isdigit (F);
|
HaveWidth = (bool) isdigit (F);
|
||||||
if (HaveWidth) {
|
if (HaveWidth) {
|
||||||
Width = 0;
|
Width = 0;
|
||||||
do {
|
do {
|
||||||
/* ### Non portable ### */
|
/* ### Non portable ### */
|
||||||
Width = Width * 10 + (F & 0x0F);
|
Width = Width * 10 + (F & 0x0F);
|
||||||
} while ((bool) isdigit (GetFormat ()));
|
} while ((bool) isdigit (GetFormat ()));
|
||||||
}
|
}
|
||||||
if (Width == 0) {
|
if (Width == 0) {
|
||||||
/* Invalid specification */
|
/* Invalid specification */
|
||||||
/* Note: This method of leaving the function might seem
|
/* Note: This method of leaving the function might seem
|
||||||
* to be crude, but it optimizes very well because
|
* to be crude, but it optimizes very well because
|
||||||
* the four exits can share this code.
|
* the four exits can share this code.
|
||||||
*/
|
*/
|
||||||
_seterrno (EINVAL);
|
_seterrno (EINVAL);
|
||||||
Assignments = EOF;
|
Assignments = EOF;
|
||||||
PushBack ();
|
PushBack ();
|
||||||
return Assignments;
|
return Assignments;
|
||||||
}
|
}
|
||||||
/* Increment-and-test makes better code than test-and-decrement
|
/* Increment-and-test makes better code than test-and-decrement
|
||||||
* does. So, change the width into a form that can be used in
|
* does. So, change the width into a form that can be used in
|
||||||
* that way.
|
* that way.
|
||||||
*/
|
*/
|
||||||
Width = ~Width;
|
Width = ~Width;
|
||||||
|
|
||||||
/* 3. Length modifier */
|
/* 3. Length modifier */
|
||||||
IntBytes = sizeof(int) - 1;
|
IntBytes = sizeof(int) - 1;
|
||||||
|
@ -593,7 +593,7 @@ Percent:
|
||||||
IntBytes = sizeof(char) - 1;
|
IntBytes = sizeof(char) - 1;
|
||||||
++format;
|
++format;
|
||||||
}
|
}
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
@ -604,108 +604,108 @@ Percent:
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 'j': /* intmax_t */
|
case 'j': /* intmax_t */
|
||||||
IntBytes = sizeof(long) - 1;
|
IntBytes = sizeof(long) - 1;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case 'z': /* size_t */
|
case 'z': /* size_t */
|
||||||
case 't': /* ptrdiff_t */
|
case 't': /* ptrdiff_t */
|
||||||
/* Same size as int */
|
/* Same size as int */
|
||||||
|
|
||||||
case 'L': /* long double - ignore this one */
|
case 'L': /* long double - ignore this one */
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. Conversion specifier */
|
/* 4. Conversion specifier */
|
||||||
switch (F) {
|
switch (F) {
|
||||||
/* 'd' and 'u' conversions are actually the same, since the
|
/* 'd' and 'u' conversions are actually the same, since the
|
||||||
* standard says that even the 'u' modifier allows an
|
* standard says that even the 'u' modifier allows an
|
||||||
* optionally signed integer.
|
* optionally signed integer.
|
||||||
*/
|
*/
|
||||||
case 'd': /* Optionally signed decimal integer */
|
case 'd': /* Optionally signed decimal integer */
|
||||||
case 'u':
|
case 'u':
|
||||||
ScanInt (10);
|
ScanInt (10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
/* Optionally signed integer with a base */
|
/* Optionally signed integer with a base */
|
||||||
ScanInt (0);
|
ScanInt (0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
/* Optionally signed octal integer */
|
/* Optionally signed octal integer */
|
||||||
ScanInt (8);
|
ScanInt (8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
/* Optionally signed hexadecimal integer */
|
/* Optionally signed hexadecimal integer */
|
||||||
ScanInt (16);
|
ScanInt (16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
/* Whitespace-terminated string */
|
/* Whitespace-terminated string */
|
||||||
SkipWhite ();
|
SkipWhite ();
|
||||||
CheckEnd (); /* Is it an input failure? */
|
CheckEnd (); /* Is it an input failure? */
|
||||||
Converted = true; /* No, conversion will succeed */
|
Converted = true; /* No, conversion will succeed */
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
S = va_arg (ap, char*);
|
S = va_arg (ap, char*);
|
||||||
}
|
}
|
||||||
while (C != EOF
|
while (C != EOF
|
||||||
&& (bool) isspace (C) == false
|
&& (bool) isspace (C) == false
|
||||||
&& ++Width) {
|
&& ++Width) {
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
*S++ = C;
|
*S++ = C;
|
||||||
}
|
}
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
}
|
}
|
||||||
/* Terminate the string just read */
|
/* Terminate the string just read */
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
*S = '\0';
|
*S = '\0';
|
||||||
++Assignments;
|
++Assignments;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Fixed-length string, NOT zero-terminated */
|
/* Fixed-length string, NOT zero-terminated */
|
||||||
if (HaveWidth == false) {
|
if (HaveWidth == false) {
|
||||||
/* No width given, default is 1 */
|
/* No width given, default is 1 */
|
||||||
Width = ~1u;
|
Width = ~1u;
|
||||||
}
|
}
|
||||||
CheckEnd (); /* Is it an input failure? */
|
CheckEnd (); /* Is it an input failure? */
|
||||||
Converted = true; /* No, at least 1 char. available */
|
Converted = true; /* No, at least 1 char. available */
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
S = va_arg (ap, char*);
|
S = va_arg (ap, char*);
|
||||||
/* ## This loop is convenient for us, but it isn't
|
/* ## This loop is convenient for us, but it isn't
|
||||||
* standard C. The standard implies that a failure
|
* standard C. The standard implies that a failure
|
||||||
* shouldn't put anything into the array argument.
|
* shouldn't put anything into the array argument.
|
||||||
*/
|
*/
|
||||||
while (++Width) {
|
while (++Width) {
|
||||||
CheckEnd (); /* Is it a matching failure? */
|
CheckEnd (); /* Is it a matching failure? */
|
||||||
*S++ = C;
|
*S++ = C;
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
}
|
}
|
||||||
++Assignments;
|
++Assignments;
|
||||||
} else {
|
} else {
|
||||||
/* Just skip as many chars as given */
|
/* Just skip as many chars as given */
|
||||||
while (++Width) {
|
while (++Width) {
|
||||||
CheckEnd (); /* Is it a matching failure? */
|
CheckEnd (); /* Is it a matching failure? */
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
/* String using characters from a set */
|
/* String using characters from a set */
|
||||||
/* Clear the set */
|
/* Clear the set */
|
||||||
memset (CharSet, 0, sizeof (CharSet));
|
memset (CharSet, 0, sizeof (CharSet));
|
||||||
/* Skip the left-bracket, and test for inversion. */
|
/* Skip the left-bracket, and test for inversion. */
|
||||||
Invert = (GetFormat () == '^');
|
Invert = (GetFormat () == '^');
|
||||||
if (Invert) {
|
if (Invert) {
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
}
|
}
|
||||||
if (F == ']') {
|
if (F == ']') {
|
||||||
/* Empty sets aren't allowed; so, a right-bracket
|
/* Empty sets aren't allowed; so, a right-bracket
|
||||||
* at the beginning must be a member of the set.
|
* at the beginning must be a member of the set.
|
||||||
*/
|
*/
|
||||||
AddCharToSet (F);
|
AddCharToSet (F);
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
}
|
}
|
||||||
|
@ -716,16 +716,16 @@ Percent:
|
||||||
Start = F;
|
Start = F;
|
||||||
++format;
|
++format;
|
||||||
switch (GetFormat ()) {
|
switch (GetFormat ()) {
|
||||||
case '\0':
|
case '\0':
|
||||||
case ']':
|
case ']':
|
||||||
/* '-' as last char means: include '-' */
|
/* '-' as last char means: include '-' */
|
||||||
AddCharToSet (Start);
|
AddCharToSet (Start);
|
||||||
AddCharToSet ('-');
|
AddCharToSet ('-');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Include all characters
|
/* Include all characters
|
||||||
* that are in the range.
|
* that are in the range.
|
||||||
*/
|
*/
|
||||||
while (1) {
|
while (1) {
|
||||||
AddCharToSet (Start);
|
AddCharToSet (Start);
|
||||||
if (Start == F) {
|
if (Start == F) {
|
||||||
|
@ -743,11 +743,11 @@ Percent:
|
||||||
GetFormat ();
|
GetFormat ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Don't go beyond the end of the format string. */
|
/* Don't go beyond the end of the format string. */
|
||||||
/* (Maybe, this should mean an invalid specification.) */
|
/* (Maybe, this should mean an invalid specification.) */
|
||||||
if (F == '\0') {
|
if (F == '\0') {
|
||||||
--format;
|
--format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invert the set if requested */
|
/* Invert the set if requested */
|
||||||
if (Invert) {
|
if (Invert) {
|
||||||
|
@ -758,90 +758,90 @@ Percent:
|
||||||
* store them into a string while they are part of
|
* store them into a string while they are part of
|
||||||
* the set.
|
* the set.
|
||||||
*/
|
*/
|
||||||
Match = false;
|
Match = false;
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
S = va_arg (ap, char*);
|
S = va_arg (ap, char*);
|
||||||
}
|
}
|
||||||
while (IsCharInSet () && ++Width) {
|
while (IsCharInSet () && ++Width) {
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
*S++ = C;
|
*S++ = C;
|
||||||
}
|
}
|
||||||
Match = Converted = true;
|
Match = Converted = true;
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
}
|
}
|
||||||
/* At least one character must match the set. */
|
/* At least one character must match the set. */
|
||||||
if (Match == false) {
|
if (Match == false) {
|
||||||
goto NoConv;
|
goto NoConv;
|
||||||
}
|
}
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
*S = '\0';
|
*S = '\0';
|
||||||
++Assignments;
|
++Assignments;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
/* Pointer, general format is 0xABCD.
|
/* Pointer, general format is 0xABCD.
|
||||||
* %hhp --> zero-page pointer
|
* %hhp --> zero-page pointer
|
||||||
* %hp --> near pointer
|
* %hp --> near pointer
|
||||||
* %lp --> far pointer
|
* %lp --> far pointer
|
||||||
*/
|
*/
|
||||||
SkipWhite ();
|
SkipWhite ();
|
||||||
if (CHAR (C) != '0') {
|
if (CHAR (C) != '0') {
|
||||||
goto NoConv;
|
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 ();
|
ReadChar ();
|
||||||
ReadInt (16);
|
ReadInt (16);
|
||||||
AssignInt ();
|
AssignInt ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
/* Store the number of characters consumed so far
|
/* Store the number of characters consumed so far
|
||||||
* (the read-ahead character hasn't been consumed).
|
* (the read-ahead character hasn't been consumed).
|
||||||
*/
|
*/
|
||||||
IntVal = (long) (CharCount - (C == EOF ? 0u : 1u));
|
IntVal = (long) (CharCount - (C == EOF ? 0u : 1u));
|
||||||
AssignInt ();
|
AssignInt ();
|
||||||
/* Don't count it. */
|
/* Don't count it. */
|
||||||
if (NoAssign == false) {
|
if (NoAssign == false) {
|
||||||
--Assignments;
|
--Assignments;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'C':
|
case 'C':
|
||||||
/* Wide characters */
|
/* Wide characters */
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
/* Optionally signed float */
|
/* Optionally signed float */
|
||||||
|
|
||||||
/* Those 2 groups aren't implemented. */
|
/* Those 2 groups aren't implemented. */
|
||||||
_seterrno (ENOSYS);
|
_seterrno (ENOSYS);
|
||||||
Assignments = EOF;
|
Assignments = EOF;
|
||||||
PushBack ();
|
PushBack ();
|
||||||
return Assignments;
|
return Assignments;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Invalid specification */
|
/* Invalid specification */
|
||||||
_seterrno (EINVAL);
|
_seterrno (EINVAL);
|
||||||
Assignments = EOF;
|
Assignments = EOF;
|
||||||
PushBack ();
|
PushBack ();
|
||||||
return Assignments;
|
return Assignments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -852,7 +852,7 @@ NoConv:
|
||||||
* the number of assignments is returned (the default behaviour).
|
* the number of assignments is returned (the default behaviour).
|
||||||
*/
|
*/
|
||||||
if (C == EOF && Converted == false) {
|
if (C == EOF && Converted == false) {
|
||||||
Assignments = EOF; /* Special case: error */
|
Assignments = EOF; /* Special case: error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,18 @@
|
||||||
; 2004-12-31, Greg King
|
; 2004-12-31, Greg King
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _scanf
|
.export _scanf
|
||||||
|
|
||||||
.import _stdin, pushax, addysp, _vfscanf
|
.import _stdin, pushax, addysp, _vfscanf
|
||||||
.import sp:zp, ptr1:zp
|
.import sp:zp, ptr1:zp
|
||||||
|
|
||||||
.macpack generic
|
.macpack generic
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; Code
|
; Code
|
||||||
;
|
;
|
||||||
_scanf:
|
_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,
|
; 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
|
; 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
|
; * we will have the address of the Format argument which needs to
|
||||||
; be pushed next.
|
; be pushed next.
|
||||||
|
|
||||||
lda _stdin
|
lda _stdin
|
||||||
ldx _stdin+1
|
ldx _stdin+1
|
||||||
jsr pushax
|
jsr pushax
|
||||||
|
|
||||||
; Now, calculate the va_list pointer, which does point to Format.
|
; Now, calculate the va_list pointer, which does point to Format.
|
||||||
|
|
||||||
lda sp
|
lda sp
|
||||||
ldx sp+1
|
ldx sp+1
|
||||||
add ArgSize
|
add ArgSize
|
||||||
bcc @L1
|
bcc @L1
|
||||||
inx
|
inx
|
||||||
@L1: sta ptr1
|
@L1: sta ptr1
|
||||||
stx ptr1+1
|
stx ptr1+1
|
||||||
|
|
||||||
; Push a copy of Format.
|
; Push a copy of Format.
|
||||||
|
|
||||||
ldy #1
|
ldy #1
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
tax
|
tax
|
||||||
dey
|
dey
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
jsr pushax
|
jsr pushax
|
||||||
|
|
||||||
; Load va_list [last and __fastcall__ argument to vfscanf()].
|
; Load va_list [last and __fastcall__ argument to vfscanf()].
|
||||||
|
|
||||||
lda ptr1
|
lda ptr1
|
||||||
ldx ptr1+1
|
ldx ptr1+1
|
||||||
|
|
||||||
; Call vfscanf().
|
; Call vfscanf().
|
||||||
|
|
||||||
jsr _vfscanf
|
jsr _vfscanf
|
||||||
|
|
||||||
; Clean up the stack. We will return what we got from vfscanf().
|
; Clean up the stack. We will return what we got from vfscanf().
|
||||||
|
|
||||||
ldy ArgSize
|
ldy ArgSize
|
||||||
jmp addysp
|
jmp addysp
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; Data
|
; Data
|
||||||
;
|
;
|
||||||
.bss
|
.bss
|
||||||
ArgSize:
|
ArgSize:
|
||||||
.res 1 ; Number of argument bytes
|
.res 1 ; Number of argument bytes
|
||||||
|
|
||||||
|
|
|
@ -5,58 +5,58 @@
|
||||||
; 2005-01-01, Greg King
|
; 2005-01-01, Greg King
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _cscanf
|
.export _cscanf
|
||||||
|
|
||||||
.import pushax, addysp, _vcscanf
|
.import pushax, addysp, _vcscanf
|
||||||
|
|
||||||
.macpack generic
|
.macpack generic
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; Code
|
; Code
|
||||||
;
|
;
|
||||||
_cscanf:
|
_cscanf:
|
||||||
sty ArgSize ; Number of argument bytes passed in .Y
|
sty ArgSize ; Number of argument bytes passed in .Y
|
||||||
dey ; subtract size of format pointer
|
dey ; subtract size of format pointer
|
||||||
dey
|
dey
|
||||||
tya
|
tya
|
||||||
|
|
||||||
; Now, calculate the va_list pointer -- which points to format.
|
; Now, calculate the va_list pointer -- which points to format.
|
||||||
|
|
||||||
ldx sp+1
|
ldx sp+1
|
||||||
add sp
|
add sp
|
||||||
bcc @L1
|
bcc @L1
|
||||||
inx
|
inx
|
||||||
@L1: sta ptr1
|
@L1: sta ptr1
|
||||||
stx ptr1+1
|
stx ptr1+1
|
||||||
|
|
||||||
; Push a copy of the format pointer onto the stack.
|
; Push a copy of the format pointer onto the stack.
|
||||||
|
|
||||||
ldy #1
|
ldy #1
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
tax
|
tax
|
||||||
dey
|
dey
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
jsr pushax
|
jsr pushax
|
||||||
|
|
||||||
; Load va_list [last and __fastcall__ argument for vcscanf()].
|
; Load va_list [last and __fastcall__ argument for vcscanf()].
|
||||||
|
|
||||||
lda ptr1
|
lda ptr1
|
||||||
ldx ptr1+1
|
ldx ptr1+1
|
||||||
|
|
||||||
; Call vcscanf().
|
; Call vcscanf().
|
||||||
|
|
||||||
jsr _vcscanf
|
jsr _vcscanf
|
||||||
|
|
||||||
; Clean up the stack. We will return what we got from vcscanf().
|
; Clean up the stack. We will return what we got from vcscanf().
|
||||||
|
|
||||||
ldy ArgSize
|
ldy ArgSize
|
||||||
jmp addysp
|
jmp addysp
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; Data
|
; Data
|
||||||
;
|
;
|
||||||
.bss
|
.bss
|
||||||
ArgSize:
|
ArgSize:
|
||||||
.res 1 ; Number of argument bytes
|
.res 1 ; Number of argument bytes
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
; 2005-01-02, Greg King
|
; 2005-01-02, Greg King
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _vcscanf
|
.export _vcscanf
|
||||||
|
|
||||||
.import _cgetc, _cputc
|
.import _cgetc, _cputc
|
||||||
.import popax, pushax, swapstk
|
.import popax, pushax, swapstk
|
||||||
|
|
||||||
.include "../common/_scanf.inc"
|
.include "../common/_scanf.inc"
|
||||||
|
|
||||||
|
|
||||||
; static bool pushed;
|
; static bool pushed;
|
||||||
; static char back;
|
; static char back;
|
||||||
;
|
;
|
||||||
.bss
|
.bss
|
||||||
pushed: .res 1
|
pushed: .res 1
|
||||||
back: .res 1
|
back: .res 1
|
||||||
|
|
||||||
.code
|
.code
|
||||||
; /* Call-back functions:
|
; /* Call-back functions:
|
||||||
|
@ -39,26 +39,26 @@ back: .res 1
|
||||||
; return (int)C;
|
; return (int)C;
|
||||||
; }
|
; }
|
||||||
;
|
;
|
||||||
get: ldx pushed
|
get: ldx pushed
|
||||||
beq L1
|
beq L1
|
||||||
|
|
||||||
; Return the old, pushed-back character (instead of getting a new one).
|
; Return the old, pushed-back character (instead of getting a new one).
|
||||||
;
|
;
|
||||||
dex ; ldx #>0
|
dex ; ldx #>0
|
||||||
stx pushed
|
stx pushed
|
||||||
lda back
|
lda back
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; Directly read the keyboard.
|
; Directly read the keyboard.
|
||||||
;
|
;
|
||||||
L1: jsr _cgetc
|
L1: jsr _cgetc
|
||||||
|
|
||||||
; Echo the character to the screen.
|
; Echo the character to the screen.
|
||||||
;
|
;
|
||||||
pha
|
pha
|
||||||
jsr _cputc
|
jsr _cputc
|
||||||
pla
|
pla
|
||||||
ldx #>0
|
ldx #>0
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ L1: jsr _cgetc
|
||||||
; return back = c;
|
; return back = c;
|
||||||
; }
|
; }
|
||||||
;
|
;
|
||||||
unget: ldx #1
|
unget: ldx #1
|
||||||
stx pushed
|
stx pushed
|
||||||
jsr popax ; get the first argument
|
jsr popax ; get the first argument
|
||||||
sta back
|
sta back
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,35 +96,35 @@ unget: ldx #1
|
||||||
;
|
;
|
||||||
; Beware: Because ap is a fastcall parameter, we must not destroy .XA.
|
; Beware: Because ap is a fastcall parameter, we must not destroy .XA.
|
||||||
;
|
;
|
||||||
.proc _vcscanf
|
.proc _vcscanf
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; Static, constant scanfdata structure for the _vcscanf routine.
|
; Static, constant scanfdata structure for the _vcscanf routine.
|
||||||
;
|
;
|
||||||
.rodata
|
.rodata
|
||||||
d: .addr get ; SCANFDATA::GET
|
d: .addr get ; SCANFDATA::GET
|
||||||
.addr unget ; SCANFDATA::UNGET
|
.addr unget ; SCANFDATA::UNGET
|
||||||
; .addr 0 ; SCANFDATA::DATA (not used)
|
; .addr 0 ; SCANFDATA::DATA (not used)
|
||||||
|
|
||||||
.code
|
.code
|
||||||
pha ; Save low byte of ap
|
pha ; Save low byte of ap
|
||||||
txa
|
txa
|
||||||
pha ; Save high byte of ap
|
pha ; Save high byte of ap
|
||||||
ldx #0
|
ldx #0
|
||||||
stx pushed
|
stx pushed
|
||||||
|
|
||||||
; Put &d on the stack in front of the format pointer.
|
; Put &d on the stack in front of the format pointer.
|
||||||
|
|
||||||
lda #<d
|
lda #<d
|
||||||
ldx #>d
|
ldx #>d
|
||||||
jsr swapstk ; Swap .XA with top-of-stack
|
jsr swapstk ; Swap .XA with top-of-stack
|
||||||
jsr pushax ; Put format pointer back on stack
|
jsr pushax ; Put format pointer back on stack
|
||||||
|
|
||||||
; Restore ap, and jump to _scanf which will clean up the stack.
|
; Restore ap, and jump to _scanf which will clean up the stack.
|
||||||
|
|
||||||
pla
|
pla
|
||||||
tax
|
tax
|
||||||
pla
|
pla
|
||||||
jmp __scanf
|
jmp __scanf
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
|
@ -39,18 +39,18 @@ static const struct {
|
||||||
const char *input, *format;
|
const char *input, *format;
|
||||||
int rvalue;
|
int rvalue;
|
||||||
enum TYPE {
|
enum TYPE {
|
||||||
INT,
|
INT,
|
||||||
CHAR
|
CHAR
|
||||||
} type1;
|
} type1;
|
||||||
union {
|
union {
|
||||||
int nvalue;
|
int nvalue;
|
||||||
const char *svalue;
|
const char *svalue;
|
||||||
} v1;
|
} v1;
|
||||||
enum TYPE type2;
|
enum TYPE type2;
|
||||||
union {
|
union {
|
||||||
int nvalue;
|
int nvalue;
|
||||||
const char *svalue;
|
const char *svalue;
|
||||||
} v2;
|
} v2;
|
||||||
} test_data[] = {
|
} test_data[] = {
|
||||||
/* Input sequences for character specifiers must be less than 80 characters
|
/* Input sequences for character specifiers must be less than 80 characters
|
||||||
** long. These format strings are allowwed a maximum of two assignment
|
** long. These format strings are allowwed a maximum of two assignment
|
||||||
|
@ -177,8 +177,8 @@ int main(void) {
|
||||||
*/
|
*/
|
||||||
sscanf("% \r\n\f\v\t 0", "%%%i", &n1);
|
sscanf("% \r\n\f\v\t 0", "%%%i", &n1);
|
||||||
if (n1 != 0)
|
if (n1 != 0)
|
||||||
PRINTF("sscanf()'s \"%%%%%%i\" couldn't scan either a \"%%\" "
|
PRINTF("sscanf()'s \"%%%%%%i\" couldn't scan either a \"%%\" "
|
||||||
"or a single zero digit.\r\n\n");
|
"or a single zero digit.\r\n\n");
|
||||||
|
|
||||||
/* Test scanf()'s return-value: EOF if input ends before the first
|
/* Test scanf()'s return-value: EOF if input ends before the first
|
||||||
** conversion-attempt begins; an assignment-count, otherwise.
|
** conversion-attempt begins; an assignment-count, otherwise.
|
||||||
|
@ -188,60 +188,60 @@ int main(void) {
|
||||||
PRINTF("Testing scanf()'s return-value,\r\nconversions, and assignments...\r\n");
|
PRINTF("Testing scanf()'s return-value,\r\nconversions, and assignments...\r\n");
|
||||||
for (t = 0; t < ARRAYSIZE(test_data); ++t) {
|
for (t = 0; t < ARRAYSIZE(test_data); ++t) {
|
||||||
|
|
||||||
/* Prefill the arguments with zeroes. */
|
/* Prefill the arguments with zeroes. */
|
||||||
n1 = n2 = 0;
|
n1 = n2 = 0;
|
||||||
memset(s1, '\0', sizeof s1);
|
memset(s1, '\0', sizeof s1);
|
||||||
memset(s2, '\0', sizeof s2);
|
memset(s2, '\0', sizeof s2);
|
||||||
|
|
||||||
c=sscanf(test_data[t].input, test_data[t].format,
|
c=sscanf(test_data[t].input, test_data[t].format,
|
||||||
/* Avoid warning messages about different
|
/* Avoid warning messages about different
|
||||||
** pointer-types, by casting them to void-pointers.
|
** pointer-types, by casting them to void-pointers.
|
||||||
*/
|
*/
|
||||||
test_data[t].type1 == INT ? (void *)&n1 : (void *)s1,
|
test_data[t].type1 == INT ? (void *)&n1 : (void *)s1,
|
||||||
test_data[t].type2 == INT ? (void *)&n2 : (void *)s2);
|
test_data[t].type2 == INT ? (void *)&n2 : (void *)s2);
|
||||||
if (c != test_data[t].rvalue)
|
if (c != test_data[t].rvalue)
|
||||||
PRINTF("Test #%u returned %d instead of %d.\r\n",
|
PRINTF("Test #%u returned %d instead of %d.\r\n",
|
||||||
t + 1, c, test_data[t].rvalue);
|
t + 1, c, test_data[t].rvalue);
|
||||||
|
|
||||||
if (test_data[t].type1 == INT) {
|
if (test_data[t].type1 == INT) {
|
||||||
if (test_data[t].v1.nvalue != n1)
|
if (test_data[t].v1.nvalue != n1)
|
||||||
PRINTF("Test #%u assigned %i, instead of %i,\r\n"
|
PRINTF("Test #%u assigned %i, instead of %i,\r\n"
|
||||||
"\tto the first argument.\r\n\n",
|
"\tto the first argument.\r\n\n",
|
||||||
t + 1, n1, test_data[t].v1.nvalue);
|
t + 1, n1, test_data[t].v1.nvalue);
|
||||||
}
|
}
|
||||||
else { /* test_data[t].type1 == CHAR */
|
else { /* test_data[t].type1 == CHAR */
|
||||||
if (strcmp(test_data[t].v1.svalue, s1))
|
if (strcmp(test_data[t].v1.svalue, s1))
|
||||||
PRINTF("Test #%u assigned\r\n\"%s\",\r\n"
|
PRINTF("Test #%u assigned\r\n\"%s\",\r\n"
|
||||||
"\tinstead of\r\n\"%s\",\r\n"
|
"\tinstead of\r\n\"%s\",\r\n"
|
||||||
"\tto the first argument.\r\n\n",
|
"\tto the first argument.\r\n\n",
|
||||||
t + 1, s1, test_data[t].v1.svalue);
|
t + 1, s1, test_data[t].v1.svalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_data[t].type2 == INT) {
|
if (test_data[t].type2 == INT) {
|
||||||
if (test_data[t].v2.nvalue != n2)
|
if (test_data[t].v2.nvalue != n2)
|
||||||
PRINTF("Test #%u assigned %i, instead of %i,\r\n"
|
PRINTF("Test #%u assigned %i, instead of %i,\r\n"
|
||||||
"\tto the second argument.\r\n\n",
|
"\tto the second argument.\r\n\n",
|
||||||
t + 1, n2, test_data[t].v2.nvalue);
|
t + 1, n2, test_data[t].v2.nvalue);
|
||||||
}
|
}
|
||||||
else { /* test_data[t].type2 == CHAR */
|
else { /* test_data[t].type2 == CHAR */
|
||||||
if (strcmp(test_data[t].v2.svalue, s2))
|
if (strcmp(test_data[t].v2.svalue, s2))
|
||||||
PRINTF("Test #%u assigned\r\n\"%s\",\r\n"
|
PRINTF("Test #%u assigned\r\n\"%s\",\r\n"
|
||||||
"\tinstead of\r\n\"%s\",\r\n"
|
"\tinstead of\r\n\"%s\",\r\n"
|
||||||
"\tto the second argument.\r\n\n",
|
"\tto the second argument.\r\n\n",
|
||||||
t + 1, s2, test_data[t].v2.svalue);
|
t + 1, s2, test_data[t].v2.svalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pause();
|
Pause();
|
||||||
|
|
||||||
/* Test the char, short, and long specification-modifiers. */
|
/* Test the char, short, and long specification-modifiers. */
|
||||||
PRINTF("Testing scanf()'s type-modifiers...\r\n");
|
PRINTF("Testing scanf()'s type-modifiers...\r\n");
|
||||||
for (t = 0; t < ARRAYSIZE(type_data); ++t) {
|
for (t = 0; t < ARRAYSIZE(type_data); ++t) {
|
||||||
n0 = 0L;
|
n0 = 0L;
|
||||||
sscanf(type_data[t].input, type_data[t].format, &n0);
|
sscanf(type_data[t].input, type_data[t].format, &n0);
|
||||||
if (type_data[t].value != n0)
|
if (type_data[t].value != n0)
|
||||||
PRINTF("Test #%u assigned %li instead of %li.\r\n",
|
PRINTF("Test #%u assigned %li instead of %li.\r\n",
|
||||||
t + 1, n0, type_data[t].value);
|
t + 1, n0, type_data[t].value);
|
||||||
}
|
}
|
||||||
Pause();
|
Pause();
|
||||||
|
|
||||||
/* Test that the pointer specification
|
/* Test that the pointer specification
|
||||||
|
@ -249,34 +249,34 @@ int main(void) {
|
||||||
*/
|
*/
|
||||||
PRINTF("Testing \"%%p\"...\r\n");
|
PRINTF("Testing \"%%p\"...\r\n");
|
||||||
sprintf(s1, "%p %p %p %p", NULL, NULL,
|
sprintf(s1, "%p %p %p %p", NULL, NULL,
|
||||||
Pause, /* static (program) storage */
|
Pause, /* static (program) storage */
|
||||||
&c); /* automatic (stack) storage */
|
&c); /* automatic (stack) storage */
|
||||||
sscanf(s1, "%p%p%p %p", &p1, &p2, &p3, &p4);
|
sscanf(s1, "%p%p%p %p", &p1, &p2, &p3, &p4);
|
||||||
if (p1 != NULL || p2 != NULL ||
|
if (p1 != NULL || p2 != NULL ||
|
||||||
p3 != (void *)Pause || p4 != (void *)&c)
|
p3 != (void *)Pause || p4 != (void *)&c)
|
||||||
PRINTF("p1 is %p, p2 is %p; they should be %p.\r\n"
|
PRINTF("p1 is %p, p2 is %p; they should be %p.\r\n"
|
||||||
"scanf() assigned %p to p3, instead of %p.\r\n"
|
"scanf() assigned %p to p3, instead of %p.\r\n"
|
||||||
"scanf() assigned %p to p4, instead of %p.\r\n",
|
"scanf() assigned %p to p4, instead of %p.\r\n",
|
||||||
p1, p2, NULL,
|
p1, p2, NULL,
|
||||||
p3, Pause,
|
p3, Pause,
|
||||||
p4, &c);
|
p4, &c);
|
||||||
|
|
||||||
/* Test that scanf() can scan typed input.
|
/* Test that scanf() can scan typed input.
|
||||||
** Retest that "%i" can decode radix prefixxes.
|
** Retest that "%i" can decode radix prefixxes.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
Pause();
|
Pause();
|
||||||
PRINTF("Type 3 signed numbers,\r\n"
|
PRINTF("Type 3 signed numbers,\r\n"
|
||||||
"separated by white-space:\r\n"
|
"separated by white-space:\r\n"
|
||||||
"octal decimal hexadecimal\r\n"
|
"octal decimal hexadecimal\r\n"
|
||||||
"? ");
|
"? ");
|
||||||
c = SCANF("%i %i %i", &n1, &n2, &n3);
|
c = SCANF("%i %i %i", &n1, &n2, &n3);
|
||||||
PRINTF("\r\n\nscanf() returned %i.\r\n"
|
PRINTF("\r\n\nscanf() returned %i.\r\n"
|
||||||
"The numbers are:\r\n"
|
"The numbers are:\r\n"
|
||||||
" %+o octal,\r\n"
|
" %+o octal,\r\n"
|
||||||
" %+d decimal,\r\n"
|
" %+d decimal,\r\n"
|
||||||
" %+#X hexadecimal.\r\n",
|
" %+#X hexadecimal.\r\n",
|
||||||
c, n1, n2, n3);
|
c, n1, n2, n3);
|
||||||
} while (c > 0);
|
} while (c > 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue