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 */
172 unsigned char HaveWidth; /* True if a width was given */
174 /* Place copies of the arguments into global variables. This is not very
175 * nice, but on a 6502 platform it gives better code, since the values
176 * do not have to be passed as parameters.
181 /* Initialize variables */
185 /* Set up the jump label. The get() routine will use this label when EOF
188 Result = setjmp (JumpBuf);
189 printf ("Result = %u\n", Result);
190 if (Result == RC_OK) {
193 /* Get the next input character */
196 /* Walk over the format string */
197 while (F = *format++) {
199 /* Check for a conversion */
200 if (F != '%' || *format == '%') {
202 /* %% or any char other than % */
207 /* Check for a match */
210 /* Special white space handling: Any whitespace matches
211 * any amount of whitespace including none(!). So this
212 * match will never fail.
219 /* A mismatch. We will stop scanning the input and return
220 * the number of conversions.
222 printf ("F = '%c', C = '%c' --> mismatch\n", F, C);
227 /* A match. Read the next input character and start over */
234 /* A conversion. Skip the percent sign. */
237 /* Initialize variables */
244 /* Check for flags. */
250 /* ### Non portable ### */
251 Width = Width * 10 + (F & 0x0F);
253 } while (isdigit (F));
256 case '*': NoAssign = 1; break;
257 case 'h': IsShort = 1; break;
259 case 'L': IsLong = 1; break;
260 default: goto FlagsDone;
267 /* Check for the actual conversion character */
268 printf ("F = '%c'\n", F);
274 /* Optionally signed decimal integer */
285 /* Optionally signed integer with a base */
310 /* Unsigned octal integer */
317 /* Unsigned decimal integer */
325 /* Unsigned hexadecimal integer */
335 /* Optionally signed float */
336 longjmp (JumpBuf, RC_NOCONV);
340 /* Whitespace terminated string */
343 S = va_arg (ap, char*);
345 while (!isspace (C) && Width--) {
351 /* Terminate the string just read */
358 /* Fixed length string, NOT zero terminated */
360 /* No width given, default is 1 */
364 S = va_arg (ap, char*);
376 /* String using characters from a set */
384 /* Store characters consumed so far */
391 /* Invalid conversion */
392 longjmp (JumpBuf, RC_NOCONV);
397 /* Skip the format char */
404 } else if (Result == RC_EOF) {
406 /* Jump via JumpBuf means EOF on input */
407 if (D->ccount == 0) {
408 /* Special case: error */
414 /* Return the number of conversions */