Working on the _scanf implementation
git-svn-id: svn://svn.cc65.org/cc65/trunk@1199 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -168,7 +168,8 @@ int _scanf (struct indesc* D_, const char* format, va_list ap_)
|
|||||||
char F; /* Character from format string */
|
char F; /* Character from format string */
|
||||||
unsigned char Result; /* setjmp result */
|
unsigned char Result; /* setjmp result */
|
||||||
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 */
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -198,67 +199,69 @@ Again:
|
|||||||
/* Check for a conversion */
|
/* Check for a conversion */
|
||||||
if (F != '%' || *format == '%') {
|
if (F != '%' || *format == '%') {
|
||||||
|
|
||||||
/* %% or any char other than % */
|
/* %% or any char other than % */
|
||||||
if (F == '%') {
|
if (F == '%') {
|
||||||
++format;
|
++format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for a match */
|
/* Check for a match */
|
||||||
if (isspace (F)) {
|
if (isspace (F)) {
|
||||||
|
|
||||||
/* Special white space handling: Any whitespace matches
|
/* Special white space handling: Any whitespace matches
|
||||||
* any amount of whitespace including none(!). So this
|
* any amount of whitespace including none(!). So this
|
||||||
* match will never fail.
|
* match will never fail.
|
||||||
*/
|
*/
|
||||||
SkipWhite ();
|
SkipWhite ();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (F != C) {
|
} else if (F != C) {
|
||||||
|
|
||||||
/* 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);
|
printf ("F = '%c', C = '%c' --> mismatch\n", F, C);
|
||||||
return Conversions;
|
return Conversions;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* A match. Read the next input character and start over */
|
/* A match. Read the next input character and start over */
|
||||||
goto Again;
|
goto Again;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* A conversion. Skip the percent sign. */
|
/* A conversion. Skip the percent sign. */
|
||||||
F = *format++;
|
F = *format++;
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
NoAssign = 0;
|
NoAssign = 0;
|
||||||
IsShort = 0;
|
IsShort = 0;
|
||||||
IsLong = 0;
|
IsLong = 0;
|
||||||
Width = UINT_MAX;
|
Width = UINT_MAX;
|
||||||
|
HaveWidth = 0;
|
||||||
|
|
||||||
/* Check for flags. */
|
/* Check for flags. */
|
||||||
while (1) {
|
while (1) {
|
||||||
if (isdigit (F)) {
|
if (isdigit (F)) {
|
||||||
Width = 0;
|
HaveWidth = 1;
|
||||||
do {
|
Width = 0;
|
||||||
/* ### Non portable ### */
|
do {
|
||||||
Width = Width * 10 + (F & 0x0F);
|
/* ### Non portable ### */
|
||||||
F = *format++;
|
Width = Width * 10 + (F & 0x0F);
|
||||||
} while (isdigit (F));
|
F = *format++;
|
||||||
} else {
|
} while (isdigit (F));
|
||||||
switch (F) {
|
} else {
|
||||||
case '*': NoAssign = 1; break;
|
switch (F) {
|
||||||
case 'h': IsShort = 1; break;
|
case '*': NoAssign = 1; break;
|
||||||
case 'l':
|
case 'h': IsShort = 1; break;
|
||||||
case 'L': IsLong = 1; break;
|
case 'l':
|
||||||
default: goto FlagsDone;
|
case 'L': IsLong = 1; break;
|
||||||
}
|
default: goto FlagsDone;
|
||||||
F = *format++;
|
}
|
||||||
}
|
F = *format++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
FlagsDone:
|
FlagsDone:
|
||||||
|
|
||||||
/* Check for the actual conversion character */
|
/* Check for the actual conversion character */
|
||||||
@@ -330,22 +333,43 @@ FlagsDone:
|
|||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
case 'g':
|
||||||
/* Optionally signed float */
|
/* Optionally signed float */
|
||||||
|
longjmp (JumpBuf, RC_NOCONV);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
/* Whitespace terminated string */
|
/* Whitespace terminated string */
|
||||||
SkipWhite ();
|
SkipWhite ();
|
||||||
S = NoAssign? 0 : va_arg (ap, char*);
|
if (!NoAssign) {
|
||||||
while (C && !isspace (C) && Width--) {
|
S = va_arg (ap, char*);
|
||||||
if (S) {
|
}
|
||||||
*S++ = C;
|
while (!isspace (C) && Width--) {
|
||||||
|
if (!NoAssign) {
|
||||||
|
*S++ = C;
|
||||||
}
|
}
|
||||||
ReadChar ();
|
ReadChar ();
|
||||||
}
|
}
|
||||||
|
/* Terminate the string just read */
|
||||||
|
if (!NoAssign) {
|
||||||
|
*S = '\0';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Fixed length string */
|
/* Fixed length string, NOT zero terminated */
|
||||||
|
if (!HaveWidth) {
|
||||||
|
/* No width given, default is 1 */
|
||||||
|
Width = 1;
|
||||||
|
}
|
||||||
|
if (!NoAssign) {
|
||||||
|
S = va_arg (ap, char*);
|
||||||
|
}
|
||||||
|
while (Width--) {
|
||||||
|
if (!NoAssign) {
|
||||||
|
*S++ = C;
|
||||||
|
}
|
||||||
|
ReadChar ();
|
||||||
|
}
|
||||||
|
++Conversions;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
@@ -365,6 +389,7 @@ FlagsDone:
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* Invalid conversion */
|
/* Invalid conversion */
|
||||||
|
longjmp (JumpBuf, RC_NOCONV);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user