home *** CD-ROM | disk | FTP | other *** search
- /*
- scanf routines for LightspeedC
-
- (C) Copyright 1986. THINK Technologies, Inc. All rights reserved.
- */
-
- #include "config.h"
-
- #ifndef _stdioh_
- #include "stdio.h"
- #endif
-
- #ifndef _MacTypes_
- #include "MacTypes.h"
- #endif
-
- #ifndef _ctypeh_
- #include "ctype.h"
- #endif
-
- #ifndef _saneh_
- #include "sane.h"
- #endif
-
- #ifndef _setjmph_
- #include "setjmp.h"
- #endif
-
- #ifndef _math_
- #include "Math.h"
- #endif
-
- #include "pascal.h"
-
- #ifdef _MC68881_
-
- /* conversion from 68881 to SANE extended type */
- static void x96tox80(x96, x80)
- register Extended96 *x96;
- register Extended80 *x80;
-
- {
- (*x80).exponent = (*x96).exponent;
- (*x80).mantissa = (*x96).mantissa;
- }
-
- static void x80tox96(x80, x96)
- register Extended80 *x80;
- register Extended96 *x96;
- {
- (*x96).exponent = (*x80).exponent;
- (*x96).reserved = 0;
- (*x96).mantissa = (*x80).mantissa;
- }
-
- #define _fromDecimal() fp68k(&_decimal_,&x80,FFEXT|FOD2B)
- #define _tox96() x80tox96(&x80, *(double**)argument)
- #else
-
- #define _fromDecimal() fp68k(&_decimal_,*(double**)argument,FFEXT|FOD2B)
- #define _tox96()
- #endif
-
- /*----------------------------------------------------------------------------
- some global storage to prevent excessive parameter transfer
- ----------------------------------------------------------------------------*/
-
- int (*_scanf_input)(); /* global pointer to function for input */
- int (*_scanf_putback)(); /* global pointer to function for putback */
- _scanf_scan(); /* function to handle formatting */
- jmp_buf _scanf_env; /* for error exit context switch */
-
- static unsigned char *destination; /* pointer to indicate stream for output */
- static char scratch[256]; /* used for [ command for byte validation */
-
- static
- int from_memory()
- {
- register unsigned char c;
- c = *destination;
- if (c) {
- destination++;
- return(c);
- } else return(EOF);
- }
-
- static
- put_back_into_memory(x)
- char x;
- {
- destination--;
- }
-
- #line 0 sscanf
- int sscanf(dest, fmt)
- unsigned char *dest; /* pointer to buffer space */
- char *fmt; /* pointer to format string */
- {
- _scanf_input = from_memory;
- _scanf_putback = put_back_into_memory;
-
- destination = dest;
- return(_scanf_scan(&fmt));
- }
-
- static
- Boolean okdigit(c, base, value_in_base_ptr)
- register char c;
- register int base;
- register int *value_in_base_ptr;
- {
- /* only works for bases 2 through 10 (inclusive) and 16! */
-
- *value_in_base_ptr = 0;
-
- if (c >= '0')
- {
- if (c <= (((base<=10)?base:10)+'0'-1))
- {
- *value_in_base_ptr = c-'0';
- return (true);
- }
-
- if (base == 16)
- {
- /* if character is lower case, convert to upper case */
-
- if ((c >= 'a') && (c <= 'f')) c -= 'a'-'A';
-
- if ((c >= 'A') && (c <= 'F'))
- {
- *value_in_base_ptr = c - 'A' + 10;
- return (true);
- }
- }
- }
-
- return (false);
- }
-
-
- static
- long read_num(num,err,at_least_one, base)
- register unsigned num;
- register Boolean *err;
- register Boolean *at_least_one;
- register int base;
- {
- register long number = 0;
- register int c;
- register Boolean oneX=false;
- int value_in_base;
-
- *at_least_one = false;
- *err = false;
- if (num == 0) num--;
-
- /* if first char is EOF, then it's not a number */
-
- if ((c = (*_scanf_input)()) == EOF)
- {
- *err = true;
- return(EOF);
- }
-
- /* loop collecting digits while num is not zero */
-
- while (okdigit(c, base, &value_in_base) && num--)
- {
- number = number * base + value_in_base;
- *at_least_one = true;
-
- /* no need to put back EOF if we hit it */
-
- if ((c = (*_scanf_input)()) == EOF) return (number);
-
- /* the form 0xNNNN is allowed for hex numbers, just swallow the
- X and continue from there, but only do it once! */
-
- if ((base == 16) && ((c == 'x') || (c == 'X')))
- {
- if ((number > 0) || oneX) break;
-
- /* pick up next digit -- error if nothing follows X */
-
- if ((c = (*_scanf_input)()) == EOF) return (EOF);
- }
-
- /* only allow hex form after first zero, otherwise it is an error */
-
- oneX = true;
- }
-
- (*_scanf_putback)(c);
-
- return(number);
- }
-
- static
- int skip_white()
- {
- register int c;
-
- do
- {
- if ((c = (*_scanf_input)()) == EOF) longjmp(_scanf_env, EOF);
- }
- while (c && isspace(c));
-
- return(c); /* returns character after white space */
- }
- int _scanf_scan(fmt)
- char **fmt; /* pointer to pointer to format string */
- {
- char c; /* current character under inspection */
- char *format; /* pointer to format string */
- Boolean its_a_long; /* flag to indicate long integer */
- Boolean its_a_short; /* flag to indicate short integer */
- Boolean neg; /* flag for negative # */
- register Boolean assign; /* flag for suppression flag */
- Boolean read_err; /* Used as error flag for read_ routines */
- Boolean valid; /* valid digit? */
- register long value; /* for conversion of numerics */
- register char *argument; /* pointer to arguments for fmt string */
- register unsigned width; /* field width as specified by format */
- register int curr_char; /* last character read */
- register char **loc; /* used to run thru argument */
- int i; /* counter */
- register count; /* counter */
- register int (*_scanf_putbackx)() = _scanf_putback;
-
- #ifdef _MC68881_
- Extended80 x80;
- #endif
-
- if (count=setjmp(_scanf_env)) return (count); /* set up error handler */
-
- format = *fmt++; /* set "format" to the format string */
- /* "fmt" is left pointing to first argument */
- argument = (char *) fmt; /* set "argument" to point to first argument */
- count = 0; /* set count to zero */
-
- while (c = *format++) /* scan format string until NULL */
- {
- if (c == '%')
- {
- neg = false;
- assign = true;
-
- if ((c = *format) == '*') /* suppress mode? */
- {
- assign = false; /* set flag if so */
- format++; /* point to next char */
- }
-
- /* compute total field width, zero allows arbitrary width */
-
- width = (isdigit(*format)) ? _std_decode(&format) : 0;
-
- /* check if long integer is required */
-
- if (its_a_long = ((*format) == 'l')) format++;
-
- /* check if short integer is required */
-
- if (its_a_short = ((*format) == 'h')) format++;
-
- c = *format++;
-
- /* note that "format" is left ready for the next pass */
-
- switch (c)
- {
- case 'd': switch (curr_char = skip_white())
- {
- case '+': /* swallow a + */
- break;
-
- case '-': /* remember a -, swallow char */
- neg = true;
- break;
-
- default: /* oops, put it back! */
- (*_scanf_putbackx)(curr_char);
- break;
- }
-
- value = read_num(width,&read_err,&valid, 10);
-
- if (read_err) return(EOF);
-
- if (valid == false) return(count);
-
- if (neg) value = -value;
-
- if (assign)
- {
- if(its_a_long)
- **(long **)argument = value;
- else
- **(int **)argument = value;
-
- argument += sizeof(long);
- count++;
- }
- break;
-
- case 'u':
- (*_scanf_putbackx)(skip_white());
-
- value = read_num(width,&read_err,&valid, 10);
-
- if (read_err) return(EOF);
-
- if (valid == false) return(count);
-
- if (assign)
- {
- if(its_a_long)
- **(unsigned long **)argument = value;
- else
- **(unsigned int **)argument = value;
-
- argument += sizeof(long);
- count++;
- }
- break;
-
- case 'x':
- case 'X':
- (*_scanf_putbackx)(skip_white());
-
- value = read_num(width,&read_err,&valid, 16);
-
- if (read_err) return(EOF);
-
- if (valid == false) return(count);
-
- if (assign)
- {
- if(its_a_long)
- **(unsigned long **)argument = value;
- else
- **(unsigned int **)argument = value;
-
- argument += sizeof(long);
- count++;
- }
- break;
- case 'o':
- case 'O':
- (*_scanf_putbackx)(skip_white());
-
- value = read_num(width,&read_err,&valid, 8);
-
- if (read_err) return(EOF);
-
- if (valid == false) return(count);
-
- if (assign)
- {
- if(its_a_long)
- **(unsigned long **)argument = value;
- else
- **(unsigned int **)argument = value;
-
- argument += sizeof(long);
- count++;
- }
- break;
-
- case 'c': if (width<=0) width = 1;
-
- loc = (char **)argument;
-
- do
- {
- if ((curr_char = (*_scanf_input)()) == EOF)
- return(EOF);
-
- if (assign)
- {
- **(char **)loc = curr_char;
- (*loc)++;
- }
- width--;
- }
- while (width);
-
- if (assign)
- {
- argument += sizeof(long);
- count++;
- }
-
- break;
-
- case 'p':
- case 's':
- { char *strStart;
- /* first char cannot be EOF after skip_white */
-
- (*_scanf_putbackx)(skip_white());
-
- loc = (char **)argument;
- strStart = *loc;
-
- do
- {
- if ((curr_char = (*_scanf_input)()) == EOF)
- {
- if (assign) {
- **(char**) loc = '\0';
- if (c == 'p') CtoPstr(strStart);
- }
- return (count);
- }
-
- if (assign)
- {
- if (!isspace(curr_char))
- **(char **)loc = curr_char;
- else
- **(char **)loc = '\0';
- (*loc)++;
- }
- width--;
- }
- while ((curr_char)&&(width)&&(!isspace(curr_char)));
- if (!curr_char || isspace(curr_char))
- (*_scanf_putbackx)(curr_char);
- else
- if (assign)
- **(char **)loc = '\0';
-
-
- if (assign)
- {
- argument += sizeof(long);
- if (c == 'p') CtoPstr(strStart);
- count++;
- }
- break;
- }
-
- case '[': neg = false;
-
- if (*format == '^') /* check for negate */
- {
- neg = true; /* set if necessary */
- format++;
- }
-
- loc = (char **)argument; /* point to destination */
-
- /* initialize lookup table */
-
- for (i=255; i>=0; i--)
- scratch[i] = neg;
-
- /* pointing after [ or ^ */
-
- while ((curr_char = *format++) != ']')
- scratch[curr_char] = (!neg);
-
- do
- {
- if ((curr_char = (*_scanf_input)()) == EOF)
- return(EOF);
-
- if (assign)
- {
- if (scratch[curr_char])
- **(char **)loc = curr_char;
- else
- **(char **)loc = '\0';
- (*loc)++;
- }
- width--;
- }
- while ((width) && (scratch[curr_char]));
-
- if (!scratch[curr_char])
- (*_scanf_putbackx)(curr_char);
- else
- if (assign)
- **(char **)loc = '\0';
-
- if (assign)
- {
- argument += sizeof(long);
- count++;
- }
- break;
-
-
-
- case '%': if ((curr_char = (*_scanf_input)()) == EOF)
- return(EOF);
- if (curr_char != '%')
- return (count);
- break;
-
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
-
- {Decimal _decimal_;
- int fblen = 0;
-
- scratch[0] = '\0';
- curr_char = skip_white();
-
- valid = false;
- do
- {int index = 0;
-
- scratch[fblen++] = curr_char;
- scratch[fblen] = '\0';
- read_err = false;
-
- if (scratch[fblen-1])
- {
- CStr2Dec(&scratch,&index,&_decimal_,&read_err);
-
- /* read_err is true if NO READ ERROR! */
-
- if (read_err)
- {
- valid = true;
-
- /* read next character */
-
- if ((curr_char = (*_scanf_input)()) == EOF)
- read_err = false;
-
- if (isspace(curr_char))
- {
- read_err = false;
- (*_scanf_putbackx)(curr_char);
- }
- }
- else
- (*_scanf_putbackx)(scratch[fblen-1]);
- }
-
- } while ((read_err)&&(--width));
-
- if (!valid) return(count);
-
- if (assign)
- {
- if (its_a_long) {
- _fromDecimal();
- _tox96();
- }
- else
- if (its_a_short)
- fp68k(&_decimal_,*(short double**)argument,FFDBL|FOD2B);
- else
- fp68k(&_decimal_,*(float**)argument,FFSGL|FOD2B);
-
- count++;
- }
-
- argument += sizeof(long);
- break;
- }
- } /* end switch */
- } /* end '%' */
- else
- {
- if (!c || isspace(c))
- {
- /* expecting zero or more spaces
- pdg - 6/20/86 - used to require at least 1 space! */
-
- while (isspace(curr_char = (*_scanf_input)()))
- ;
-
- /* prevent trailing white space from incurring EOF exit */
-
- if (curr_char == EOF)
- {
- if (count > 0) return (count);
- return (EOF);
- }
-
- (*_scanf_putbackx)(curr_char);
-
- /* skip all contiguous spaces in format string */
-
- while (isspace(*format)) format++;
- }
- else
- {
- if ((curr_char = (*_scanf_input)()) == EOF) return(EOF);
-
- /* character must match exactly! */
-
- if (curr_char != c)
- {
- (*_scanf_putbackx)(curr_char);
- return(count);
- }
- }
- } /* else % */
-
- } /* end while (*format) */
-
- /* return number of successful assignments */
-
- return(count);
-
- }
-
-