4 * (C) Copyright 2001 Ullrich von Bassewitz (uz@cc65.org)
6 * This is the basic layer for all scanf type functions.
21 /*****************************************************************************/
22 /* SetJmp return codes */
23 /*****************************************************************************/
27 #define RC_OK 0 /* Regular call */
28 #define RC_EOF 1 /* EOF reached */
29 #define RC_NOCONV 2 /* No conversion possible */
33 /*****************************************************************************/
35 /*****************************************************************************/
39 static struct indesc* D; /* Copy of function argument */
40 static va_list ap; /* Copy of function argument */
41 static jmp_buf JumpBuf; /* Label that is used in case of EOF */
42 static char C; /* Character from input */
43 static unsigned Width; /* Maximum field width */
44 static long IntVal; /* Converted int value */
45 static unsigned Conversions; /* Number of conversions */
48 static unsigned char Positive; /* Flag for positive value */
49 static unsigned char NoAssign; /* Supppress assigment */
50 static unsigned char IsShort; /* Short type */
51 static unsigned char IsLong; /* Long type */
55 /*****************************************************************************/
57 /*****************************************************************************/
61 /*****************************************************************************/
63 /*****************************************************************************/
67 static void ReadChar (void)
68 /* Get an input character, count characters */
76 static void SkipWhite (void)
77 /* Skip white space in the input and return the first non white character */
86 static void ReadSign (void)
87 /* Read an optional sign and skip it. Store 1 in Positive if the value is
88 * positive, store 0 otherwise.
105 static unsigned char HexVal (char C)
106 /* Convert a digit to a value */
112 return C - toupper (C) + ('A' + 10);
118 static void ReadInt (unsigned char Base)
119 /* Read an integer and store it into IntVal */
121 /* Value must start with a digit */
123 longjmp (JumpBuf, RC_NOCONV);
128 while (isxdigit (C) && Width-- > 0) {
129 printf ("ReadInt: '%c'\n", C);
130 IntVal = IntVal * Base + HexVal (C);
134 /* One more conversion */
140 static void AssignInt (void)
141 /* Assign the integer value in Val to the next argument. The function makes
142 * several non portable assumptions to reduce code size:
143 * - int and unsigned types have the same representation
144 * - short and int have the same representation.
145 * - all pointer types have the same representation.
149 /* Get the next argument pointer */
150 void* P = va_arg (ap, void*);
152 /* Assign to the converted value */
156 *(int*)P = (int) IntVal;
163 int _scanf (struct indesc* D_, const char* format, va_list ap_)
164 /* This is the routine used to do the actual work. It is called from several
165 * types of wrappers to implement the actual ISO xxscanf functions.
168 char F; /* Character from format string */
169 unsigned char Result; /* setjmp result */
171 unsigned char Base; /* Integer base in %i */
173 /* Place copies of the arguments into global variables. This is not very
174 * nice, but on a 6502 platform it gives better code, since the values
175 * do not have to be passed as parameters.
180 /* Initialize variables */
184 /* Set up the jump label. The get() routine will use this label when EOF
187 Result = setjmp (JumpBuf);
188 printf ("Result = %u\n", Result);
189 if (Result == RC_OK) {
192 /* Get the next input character */
195 /* Walk over the format string */
196 while (F = *format++) {
198 /* Check for a conversion */
199 if (F != '%' || *format == '%') {
201 /* %% or any char other than % */
206 /* Check for a match */
209 /* Special white space handling: Any whitespace matches
210 * any amount of whitespace including none(!). So this
211 * match will never fail.
218 /* A mismatch. We will stop scanning the input and return
219 * the number of conversions.
221 printf ("F = '%c', C = '%c' --> mismatch\n", F, C);
226 /* A match. Read the next input character and start over */
233 /* A conversion. Skip the percent sign. */
236 /* Initialize variables */
242 /* Check for flags. */
247 /* ### Non portable ### */
248 Width = Width * 10 + (F & 0x0F);
250 } while (isdigit (F));
253 case '*': NoAssign = 1; break;
254 case 'h': IsShort = 1; break;
256 case 'L': IsLong = 1; break;
257 default: goto FlagsDone;
264 /* Check for the actual conversion character */
265 printf ("F = '%c'\n", F);
271 /* Optionally signed decimal integer */
282 /* Optionally signed integer with a base */
307 /* Unsigned octal integer */
314 /* Unsigned decimal integer */
322 /* Unsigned hexadecimal integer */
332 /* Optionally signed float */
336 /* Whitespace terminated string */
338 S = NoAssign? 0 : va_arg (ap, char*);
339 while (C && !isspace (C) && Width--) {
348 /* Fixed length string */
352 /* String using characters from a set */
360 /* Store characters consumed so far */
367 /* Invalid conversion */
372 /* Skip the format char */
379 } else if (Result == RC_EOF) {
381 /* Jump via JumpBuf means EOF on input */
382 if (D->ccount == 0) {
383 /* Special case: error */
389 /* Return the number of conversions */