home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / lang / lsc30p4u.sit / scanf2.c < prev    next >
Text File  |  1988-08-02  |  13KB  |  619 lines

  1. /*
  2.     scanf routines for LightspeedC
  3.  
  4.     (C) Copyright 1986. THINK Technologies, Inc.  All rights reserved.
  5. */
  6.  
  7. #include "config.h"
  8.  
  9. #ifndef _stdioh_
  10. #include "stdio.h"
  11. #endif
  12.  
  13. #ifndef    _MacTypes_
  14. #include "MacTypes.h"
  15. #endif
  16.  
  17. #ifndef _ctypeh_
  18. #include "ctype.h"
  19. #endif
  20.  
  21. #ifndef _saneh_
  22. #include "sane.h"
  23. #endif
  24.  
  25. #ifndef _setjmph_
  26. #include "setjmp.h"
  27. #endif
  28.  
  29. #ifndef _math_
  30. #include "Math.h"
  31. #endif
  32.  
  33. #include "pascal.h"
  34.  
  35. #ifdef _MC68881_
  36.  
  37. /* conversion from 68881 to SANE extended type */
  38. static void x96tox80(x96, x80)
  39. register Extended96 *x96;
  40. register Extended80 *x80;
  41.  
  42. {
  43.     (*x80).exponent = (*x96).exponent;
  44.     (*x80).mantissa = (*x96).mantissa;
  45. }
  46.  
  47. static void x80tox96(x80, x96)
  48. register Extended80 *x80;
  49. register Extended96 *x96;
  50. {
  51.     (*x96).exponent = (*x80).exponent;
  52.     (*x96).reserved = 0;
  53.     (*x96).mantissa = (*x80).mantissa;
  54. }
  55.  
  56. #define _fromDecimal() fp68k(&_decimal_,&x80,FFEXT|FOD2B)
  57. #define _tox96() x80tox96(&x80, *(double**)argument)
  58. #else
  59.  
  60. #define _fromDecimal() fp68k(&_decimal_,*(double**)argument,FFEXT|FOD2B)
  61. #define _tox96()
  62. #endif
  63.  
  64. /*----------------------------------------------------------------------------
  65.   some global storage to prevent excessive parameter transfer
  66. ----------------------------------------------------------------------------*/
  67.  
  68. int (*_scanf_input)();        /* global pointer to function for input */
  69. int (*_scanf_putback)();    /* global pointer to function for putback */
  70. _scanf_scan();                /* function to handle formatting */
  71. jmp_buf _scanf_env;            /* for error exit context switch */
  72.  
  73. static unsigned char *destination;    /* pointer to indicate stream for output */
  74. static char scratch[256];    /* used for [ command for byte validation */
  75.  
  76. static
  77. int from_memory()
  78. {
  79.     register unsigned char c;
  80.     c = *destination;
  81.     if (c) {
  82.         destination++;
  83.         return(c);
  84.     } else return(EOF);
  85. }
  86.  
  87. static
  88. put_back_into_memory(x)
  89. char x;
  90. {
  91.     destination--;
  92. }
  93.  
  94. #line 0 sscanf
  95. int sscanf(dest, fmt)
  96. unsigned char *dest;        /* pointer to buffer space */
  97. char *fmt;                    /* pointer to format string */
  98. {
  99.     _scanf_input = from_memory;
  100.     _scanf_putback = put_back_into_memory;
  101.  
  102.     destination = dest;
  103.     return(_scanf_scan(&fmt));
  104. }
  105.  
  106. static
  107. Boolean okdigit(c, base, value_in_base_ptr)
  108. register char c;
  109. register int base;
  110. register int *value_in_base_ptr;
  111. {
  112.     /* only works for bases 2 through 10 (inclusive) and 16! */
  113.     
  114.     *value_in_base_ptr = 0;
  115.     
  116.     if (c >= '0')
  117.     {
  118.         if (c <= (((base<=10)?base:10)+'0'-1))
  119.         {
  120.             *value_in_base_ptr = c-'0';
  121.             return (true);
  122.         }
  123.         
  124.         if (base == 16)
  125.         {
  126.             /* if character is lower case, convert to upper case */
  127.             
  128.             if ((c >= 'a') && (c <= 'f')) c -= 'a'-'A';
  129.             
  130.             if ((c >= 'A') && (c <= 'F'))
  131.             {
  132.                 *value_in_base_ptr = c - 'A' + 10;
  133.                 return (true);
  134.             }
  135.         }
  136.     }
  137.     
  138.     return (false);
  139. }
  140.  
  141.  
  142. static
  143. long read_num(num,err,at_least_one, base)
  144. register unsigned num;
  145. register Boolean *err;
  146. register Boolean *at_least_one;
  147. register int base;
  148. {
  149. register long number = 0;
  150. register int c;
  151. register Boolean oneX=false;
  152. int value_in_base;
  153.  
  154.     *at_least_one = false;
  155.     *err = false;
  156.     if (num == 0) num--;
  157.     
  158.     /* if first char is EOF, then it's not a number */
  159.     
  160.     if ((c = (*_scanf_input)()) == EOF)
  161.     {
  162.         *err = true;
  163.         return(EOF);
  164.     }
  165.  
  166.     /* loop collecting digits while num is not zero */
  167.  
  168.     while (okdigit(c, base, &value_in_base) && num--)
  169.     {
  170.         number = number * base + value_in_base;
  171.         *at_least_one = true;
  172.  
  173.         /* no need to put back EOF if we hit it */
  174.         
  175.         if ((c = (*_scanf_input)()) == EOF) return (number);
  176.  
  177.         /* the form 0xNNNN is allowed for hex numbers, just swallow the
  178.             X and continue from there, but only do it once! */
  179.             
  180.         if ((base == 16) && ((c == 'x') || (c == 'X')))
  181.         {
  182.             if ((number > 0) || oneX) break;
  183.             
  184.             /* pick up next digit -- error if nothing follows X */
  185.             
  186.             if ((c = (*_scanf_input)()) == EOF) return (EOF);
  187.         }
  188.         
  189.         /* only allow hex form after first zero, otherwise it is an error */
  190.         
  191.         oneX = true;
  192.     }
  193.  
  194.     (*_scanf_putback)(c);
  195.  
  196.     return(number);
  197. }
  198.  
  199. static
  200. int skip_white()
  201. {
  202. register int c;
  203.  
  204.     do
  205.     {
  206.         if ((c = (*_scanf_input)()) == EOF) longjmp(_scanf_env, EOF);
  207.     }
  208.     while (c && isspace(c));
  209.  
  210.     return(c);    /* returns character after white space */
  211. }
  212. int _scanf_scan(fmt)
  213. char    **fmt;                  /* pointer to pointer to format string */
  214. {
  215. char    c;                    /* current character under inspection */
  216. char    *format;            /* pointer to format string */
  217. Boolean its_a_long;            /* flag to indicate long integer */
  218. Boolean its_a_short;        /* flag to indicate short integer */
  219. Boolean neg;                /* flag for negative # */
  220. register Boolean assign;    /* flag for suppression flag */
  221. Boolean    read_err;            /* Used as error flag for read_ routines */
  222. Boolean valid;                /* valid digit? */
  223. register long    value;        /* for conversion of numerics */
  224. register char    *argument;    /* pointer to arguments for fmt string */
  225. register unsigned width;    /* field width as specified by format */
  226. register int    curr_char;    /* last character read */
  227. register char    **loc;        /* used to run thru argument */
  228. int i;                        /* counter */
  229. register count;                /* counter */
  230. register int (*_scanf_putbackx)() = _scanf_putback;
  231.  
  232. #ifdef _MC68881_
  233. Extended80 x80;
  234. #endif
  235.  
  236.     if (count=setjmp(_scanf_env)) return (count); /* set up error handler */
  237.     
  238.     format = *fmt++;            /* set "format" to the format string */
  239.                                 /* "fmt" is left pointing to first argument */
  240.     argument = (char *) fmt;    /* set "argument" to point to first argument */
  241.     count = 0;                    /* set count to zero */
  242.     
  243.     while (c = *format++)        /* scan format string until NULL */
  244.     {
  245.         if (c == '%')
  246.         {
  247.             neg = false;
  248.             assign = true;
  249.  
  250.             if ((c = *format) == '*')    /* suppress mode? */
  251.             {
  252.                 assign = false;            /* set flag if so */
  253.                 format++;                /* point to next char */
  254.             }
  255.  
  256.             /* compute total field width, zero allows arbitrary width */
  257.             
  258.             width = (isdigit(*format)) ? _std_decode(&format) : 0;
  259.  
  260.             /* check if long integer is required */
  261.             
  262.             if (its_a_long = ((*format) == 'l')) format++;
  263.  
  264.             /* check if short integer is required */
  265.             
  266.             if (its_a_short = ((*format) == 'h')) format++;
  267.  
  268.             c = *format++;
  269.  
  270.             /* note that "format" is left ready for the next pass */
  271.             
  272.             switch (c)
  273.             {
  274.                  case 'd':    switch (curr_char = skip_white())
  275.                              {
  276.                                  case '+':    /* swallow a + */
  277.                                              break;
  278.                                              
  279.                                  case '-':    /* remember a -, swallow char */
  280.                                              neg = true;
  281.                                              break;
  282.                                  
  283.                                  default:    /* oops, put it back! */
  284.                                              (*_scanf_putbackx)(curr_char);
  285.                                              break;
  286.                              }
  287.  
  288.                             value = read_num(width,&read_err,&valid, 10);
  289.                             
  290.                             if (read_err) return(EOF);
  291.                                 
  292.                             if (valid == false) return(count);
  293.  
  294.                             if (neg) value = -value;
  295.                                 
  296.                             if (assign)
  297.                             {
  298.                                 if(its_a_long)
  299.                                     **(long **)argument = value;
  300.                                 else
  301.                                     **(int **)argument = value;
  302.  
  303.                                 argument += sizeof(long);
  304.                                 count++;
  305.                             }
  306.                             break;
  307.  
  308.                  case 'u':    
  309.                             (*_scanf_putbackx)(skip_white());
  310.  
  311.                             value = read_num(width,&read_err,&valid, 10);
  312.                             
  313.                             if (read_err) return(EOF);
  314.                                 
  315.                             if (valid == false) return(count);
  316.                                 
  317.                             if (assign)
  318.                             {
  319.                                 if(its_a_long)
  320.                                     **(unsigned long **)argument = value;
  321.                                 else
  322.                                     **(unsigned int **)argument = value;
  323.  
  324.                                 argument += sizeof(long);
  325.                                 count++;
  326.                             }
  327.                             break;
  328.  
  329.                  case 'x':
  330.                 case 'X':    
  331.                             (*_scanf_putbackx)(skip_white());
  332.                                 
  333.                             value = read_num(width,&read_err,&valid, 16);
  334.                             
  335.                             if (read_err) return(EOF);
  336.  
  337.                             if (valid == false) return(count);
  338.                                 
  339.                             if (assign)
  340.                             {
  341.                                 if(its_a_long)
  342.                                     **(unsigned long **)argument = value;
  343.                                 else
  344.                                     **(unsigned int **)argument = value;
  345.  
  346.                                 argument += sizeof(long);
  347.                                 count++;
  348.                             }
  349.                             break;
  350.                  case 'o':
  351.                 case 'O':    
  352.                             (*_scanf_putbackx)(skip_white());
  353.  
  354.                             value = read_num(width,&read_err,&valid, 8);
  355.                             
  356.                             if (read_err) return(EOF);
  357.  
  358.                             if (valid == false) return(count);
  359.                                 
  360.                             if (assign)
  361.                             {
  362.                                 if(its_a_long)
  363.                                     **(unsigned long **)argument = value;
  364.                                 else
  365.                                     **(unsigned int **)argument = value;
  366.  
  367.                                 argument += sizeof(long);
  368.                                 count++;
  369.                             }
  370.                             break;
  371.  
  372.                 case 'c':    if (width<=0) width = 1;
  373.                 
  374.                             loc = (char **)argument;
  375.                             
  376.                             do
  377.                             {
  378.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  379.                                     return(EOF);
  380.                                     
  381.                                 if (assign)
  382.                                 {
  383.                                     **(char **)loc = curr_char;
  384.                                     (*loc)++;
  385.                                 }
  386.                                 width--;
  387.                             }
  388.                             while (width);
  389.                             
  390.                             if (assign)
  391.                             {
  392.                                 argument += sizeof(long);
  393.                                 count++;
  394.                             }
  395.  
  396.                             break;
  397.                 
  398.                 case 'p':
  399.                 case 's':    
  400.                         {    char *strStart;
  401.                             /* first char cannot be EOF after skip_white */    
  402.                             
  403.                             (*_scanf_putbackx)(skip_white());
  404.  
  405.                             loc = (char **)argument;
  406.                             strStart = *loc;
  407.  
  408.                             do
  409.                             {
  410.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  411.                                 {
  412.                                     if (assign) {
  413.                                         **(char**) loc = '\0';
  414.                                         if (c == 'p') CtoPstr(strStart);
  415.                                     }
  416.                                     return (count);
  417.                                 }
  418.  
  419.                                 if (assign)
  420.                                 {
  421.                                     if (!isspace(curr_char))
  422.                                         **(char **)loc = curr_char;
  423.                                     else
  424.                                         **(char **)loc = '\0';
  425.                                     (*loc)++;
  426.                                 }
  427.                                 width--;
  428.                             }
  429.                             while ((curr_char)&&(width)&&(!isspace(curr_char)));
  430.                             if (!curr_char || isspace(curr_char))
  431.                                 (*_scanf_putbackx)(curr_char);
  432.                             else
  433.                                 if (assign)
  434.                                     **(char **)loc = '\0';
  435.  
  436.                             
  437.                             if (assign)
  438.                             {
  439.                                 argument += sizeof(long);
  440.                                 if (c == 'p') CtoPstr(strStart);
  441.                                 count++;
  442.                             }
  443.                             break;
  444.                         }
  445.  
  446.                 case '[':    neg = false;
  447.  
  448.                             if (*format == '^')        /* check for negate */
  449.                             {
  450.                                 neg = true;            /* set if necessary */
  451.                                 format++;
  452.                             }
  453.  
  454.                             loc = (char **)argument; /* point to destination */
  455.  
  456.                             /* initialize lookup table */
  457.  
  458.                             for (i=255; i>=0; i--)
  459.                                 scratch[i] = neg;    
  460.  
  461.                             /* pointing after [ or ^ */
  462.  
  463.                             while ((curr_char = *format++) != ']')
  464.                                 scratch[curr_char] = (!neg);
  465.  
  466.                             do
  467.                             {
  468.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  469.                                     return(EOF);
  470.  
  471.                                 if (assign)
  472.                                 {
  473.                                     if (scratch[curr_char])
  474.                                         **(char **)loc = curr_char;
  475.                                     else
  476.                                         **(char **)loc = '\0';
  477.                                     (*loc)++;
  478.                                 }
  479.                                 width--;
  480.                             }
  481.                             while ((width) && (scratch[curr_char]));
  482.  
  483.                             if (!scratch[curr_char])
  484.                                 (*_scanf_putbackx)(curr_char);
  485.                             else
  486.                                 if (assign)
  487.                                     **(char **)loc = '\0';
  488.  
  489.                             if (assign)
  490.                             {
  491.                                 argument += sizeof(long);
  492.                                 count++;
  493.                             }
  494.                             break;
  495.  
  496.  
  497.  
  498.                 case '%':    if ((curr_char = (*_scanf_input)()) == EOF)
  499.                                 return(EOF);
  500.                             if (curr_char != '%')
  501.                                 return (count);
  502.                             break;
  503.  
  504.                 case 'f':
  505.                 case 'e':
  506.                 case 'E':
  507.                 case 'g':
  508.                 case 'G':
  509.  
  510.                         {Decimal _decimal_;
  511.                          int fblen = 0;
  512.                          
  513.                             scratch[0] = '\0';
  514.                             curr_char = skip_white();
  515.  
  516.                             valid = false;
  517.                             do
  518.                             {int index = 0;
  519.                             
  520.                                 scratch[fblen++] = curr_char;
  521.                                 scratch[fblen] = '\0';
  522.                                 read_err = false;
  523.                                 
  524.                                 if (scratch[fblen-1])
  525.                                 {
  526.                                     CStr2Dec(&scratch,&index,&_decimal_,&read_err);
  527.                                     
  528.                                     /* read_err is true if NO READ ERROR! */
  529.                                     
  530.                                     if (read_err)
  531.                                     {
  532.                                         valid = true;
  533.                                         
  534.                                         /* read next character */
  535.                                         
  536.                                         if ((curr_char = (*_scanf_input)()) == EOF) 
  537.                                             read_err = false;
  538.                                             
  539.                                         if (isspace(curr_char))
  540.                                         {
  541.                                             read_err = false;
  542.                                             (*_scanf_putbackx)(curr_char);
  543.                                         }
  544.                                     }
  545.                                     else
  546.                                         (*_scanf_putbackx)(scratch[fblen-1]);
  547.                                 }
  548.  
  549.                             } while ((read_err)&&(--width));
  550.     
  551.                             if (!valid) return(count);
  552.  
  553.                             if (assign)
  554.                             {
  555.                                 if (its_a_long) {
  556.                                     _fromDecimal();
  557.                                     _tox96();
  558.                                 }
  559.                                 else
  560.                                     if (its_a_short)
  561.                                         fp68k(&_decimal_,*(short double**)argument,FFDBL|FOD2B);
  562.                                     else
  563.                                         fp68k(&_decimal_,*(float**)argument,FFSGL|FOD2B);
  564.                                         
  565.                                 count++;
  566.                             }
  567.                             
  568.                             argument += sizeof(long);
  569.                             break;
  570.                         }
  571.             } /* end switch */
  572.         } /* end '%' */
  573.         else
  574.         {
  575.             if (!c || isspace(c))
  576.             {
  577.                 /* expecting zero or more spaces
  578.                     pdg - 6/20/86 - used to require at least 1 space! */
  579.                 
  580.                 while (isspace(curr_char = (*_scanf_input)()))
  581.                     ;
  582.                 
  583.                 /* prevent trailing white space from incurring EOF exit */
  584.                 
  585.                 if (curr_char == EOF)
  586.                 {
  587.                     if (count > 0) return (count);
  588.                     return (EOF);
  589.                 }
  590.                 
  591.                 (*_scanf_putbackx)(curr_char);
  592.  
  593.                 /* skip all contiguous spaces in format string */
  594.                 
  595.                 while (isspace(*format)) format++;
  596.             }
  597.             else
  598.             {
  599.                 if ((curr_char = (*_scanf_input)()) == EOF) return(EOF);
  600.                 
  601.                 /* character must match exactly! */
  602.                 
  603.                 if (curr_char != c)
  604.                 {
  605.                     (*_scanf_putbackx)(curr_char);
  606.                     return(count);
  607.                 }
  608.             }
  609.         } /* else % */
  610.  
  611.     } /* end while (*format) */
  612.  
  613.     /* return number of successful assignments */
  614.     
  615.     return(count);        
  616.  
  617. }
  618.  
  619.