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:
cuz
2002-03-17 17:11:54 +00:00
parent f901555264
commit d036b8946f

View File

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