home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / prog_c / zc.lzh / ZC / ZCSRC.LZH / IOLib / Math / scanf.c < prev   
Encoding:
C/C++ Source or Header  |  1989-06-06  |  7.8 KB  |  423 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #define    FALSE    (0)
  4. #define TRUE    (!FALSE)
  5.  
  6. extern    char    _numstr[];
  7.  
  8. /* #define    skip()    do{c=(*get)(ip); if (c<1) goto done;}while(isspace(c))*/
  9.  
  10. #define    skip()    while(isspace(c)) { if ((c=(*get)(ip))<1) goto done; }
  11.  
  12. #if FLOATS
  13. /* fp scan actions */
  14. #define F_NADA    0    /* just change state */
  15. #define F_SIGN    1    /* set sign */
  16. #define F_ESIGN    2    /* set exponent's sign */
  17. #define F_INT    3    /* adjust integer part */
  18. #define F_FRAC    4    /* adjust fraction part */
  19. #define F_EXP    5    /* adjust exponent part */
  20. #define F_QUIT    6
  21.  
  22. #define NSTATE    8
  23. #define FS_INIT        0    /* initial state */
  24. #define FS_SIGNED    1    /* saw sign */
  25. #define FS_DIGS        2    /* saw digits, no . */
  26. #define FS_DOT        3    /* saw ., no digits */
  27. #define FS_DD        4    /* saw digits and . */
  28. #define FS_E        5    /* saw 'e' */
  29. #define FS_ESIGN    6    /* saw exp's sign */
  30. #define FS_EDIGS    7    /* saw exp's digits */
  31.  
  32. #define FC_DIG        0
  33. #define FC_DOT        1
  34. #define FC_E        2
  35. #define FC_SIGN        3
  36.  
  37. /* given transition,state do what action? */
  38. int fp_do[][NSTATE] = {
  39.     {F_INT,F_INT,F_INT,
  40.      F_FRAC,F_FRAC,
  41.      F_EXP,F_EXP,F_EXP},    /* see digit */
  42.     {F_NADA,F_NADA,F_NADA,
  43.      F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT},    /* see '.' */
  44.     {F_QUIT,F_QUIT,
  45.      F_NADA,F_QUIT,F_NADA,
  46.      F_QUIT,F_QUIT,F_QUIT},    /* see e/E */
  47.     {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT,
  48.      F_ESIGN,F_QUIT,F_QUIT},    /* see sign */
  49. };
  50. /* given transition,state what is new state? */
  51. int fp_ns[][NSTATE] = {
  52.     {FS_DIGS,FS_DIGS,FS_DIGS,
  53.      FS_DD,FS_DD,
  54.      FS_EDIGS,FS_EDIGS,FS_EDIGS},    /* see digit */
  55.     {FS_DOT,FS_DOT,FS_DD,
  56.      },    /* see '.' */
  57.     {0,0,
  58.      FS_E,0,FS_E,
  59.     },    /* see e/E */
  60.     {FS_SIGNED,0,0,0,0,
  61.      FS_ESIGN,0,0},    /* see sign */
  62. };
  63. /* which states are valid terminators? */
  64. int fp_sval[NSTATE] = {
  65.     0,0,1,0,1,0,0,1
  66. };
  67. #endif
  68.  
  69. _scanf(ip, get, unget, fmt, args)
  70.     register unsigned char *ip;
  71.     int (*get)();
  72.     int (*unget)();
  73.     register unsigned char *fmt;
  74.     char **args;
  75.  
  76.     {
  77.     register long n;
  78.     register int c, width, lval, cnt = 0;
  79.     int store, neg, base, wide1, endnull, rngflag, c2;
  80.     register unsigned char *p;
  81.     unsigned char delim[128], digits[17], *q;
  82.     char *strchr(), *strcpy();
  83. #if FLOATS
  84.     long frac, expo;
  85.     int eneg, fraclen, fstate, trans;
  86.     double fx, fp_scan();
  87. #endif
  88.  
  89.     if (!*fmt)
  90.         return(0);
  91.  
  92.     c = (*get)(ip);
  93.     while(c > 0)
  94.         {
  95.         store = FALSE;
  96.         if (*fmt == '%')
  97.             {
  98.             n    = 0;
  99.             width    = -1;
  100.             wide1    = 1;
  101.             base    = 10;
  102.             lval    = FALSE;
  103.             store    = TRUE;
  104.             endnull    = TRUE;
  105.             neg    = -1;
  106.  
  107.             strcpy(delim,  "\011\012\013\014\015 ");
  108.             strcpy(digits, _numstr); /* "01234567890ABCDEF" */
  109.  
  110.             if (fmt[1] == '*')
  111.                 {
  112.                 endnull = store = FALSE;
  113.                 ++fmt;
  114.                 }
  115.  
  116.             while (isdigit(*++fmt))        /* width digit(s) */
  117.                 {
  118.                 if (width == -1)
  119.                     width = 0;
  120.                 wide1 = width = (width * 10) + (*fmt - '0');
  121.                 }
  122.             --fmt;
  123. fmtnxt:
  124.             ++fmt;
  125.             switch(tolower(*fmt))    /* tolower() is a MACRO! */
  126.                 {
  127.                 case '*':
  128.                     endnull = store = FALSE;
  129.                     goto fmtnxt;
  130.  
  131.                 case 'l':    /* long data */
  132.                     lval = TRUE;
  133. /* for compatability --> */    case 'h':    /* short data */
  134.                     goto fmtnxt;
  135.  
  136.                 case 'i':    /* any-base numeric */
  137.                     base = 0;
  138.                     goto numfmt;
  139.  
  140.                 case 'b':    /* unsigned binary */
  141.                     base = 2;
  142.                     goto numfmt;
  143.  
  144.                 case 'o':    /* unsigned octal */
  145.                     base = 8;
  146.                     goto numfmt;
  147.  
  148.                 case 'x':    /* unsigned hexadecimal */
  149.                     base = 16;
  150.                     goto numfmt;
  151.  
  152.                 case 'd':    /* SIGNED decimal */
  153.                     neg = FALSE;
  154.                     /* FALL-THRU */
  155.  
  156.                 case 'u':    /* unsigned decimal */
  157. numfmt:                    skip();
  158.  
  159.                     if (isupper(*fmt))
  160.                         lval = TRUE;
  161.  
  162.                     if (!base)
  163.                         {
  164.                         base = 10;
  165.                         neg = FALSE;
  166.                         if (c == '%')
  167.                             {
  168.                             base = 2;
  169.                             goto skip1;
  170.                             }
  171.                         else if (c == '0')
  172.                             {
  173.                             c = (*get)(ip);
  174.                             if (c < 1)
  175.                                 goto savnum;
  176.                             if ((c != 'x')
  177.                              && (c != 'X'))
  178.                                 {
  179.                                 base = 8;
  180.                                 digits[8]= '\0';
  181.                                 goto zeroin;
  182.                                 }
  183.                             base = 16;
  184.                             goto skip1;
  185.                             }
  186.                         }
  187.  
  188.                     if ((neg == FALSE) && (base == 10)
  189.                      && ((neg = (c == '-')) || (c == '+')))
  190.                         {
  191. skip1:
  192.                         c = (*get)(ip);
  193.                         if (c < 1)
  194.                             goto done;
  195.                         }
  196.  
  197.                     digits[base] = '\0';
  198.                     p = ((unsigned char *)
  199.                         strchr(digits,toupper(c)));
  200.  
  201.                     if ((!c || !p) && width)
  202.                         goto done;
  203.  
  204.                     while (p && width-- && c)
  205.                         {
  206.                         n = (n * base) + (p - digits);
  207.                         c = (*get)(ip);
  208. zeroin:
  209.                         p = ((unsigned char *)
  210.                         strchr(digits,toupper(c)));
  211.                         }
  212. savnum:
  213.                     if (store)
  214.                         {
  215.                         p = ((unsigned char *) *args);
  216.                         if (neg == TRUE)
  217.                             n = -n;
  218.                         if (lval)
  219.                             *((long*) p) = n;
  220.                         else
  221.                             *((int *) p) = n;
  222.                         ++cnt;
  223.                         }
  224.                     break;
  225.  
  226. #if FLOATS
  227.                 case 'e':    /* float */
  228.                 case 'f':
  229.                 case 'g':
  230.                     skip();
  231.  
  232.                     if (isupper(*fmt))
  233.                         lval = TRUE;
  234.  
  235.                     fstate = FS_INIT;
  236.                     neg = FALSE;  eneg = FALSE;
  237.                     n = 0;  frac = 0;  expo = 0;
  238.                     fraclen = 0;
  239.  
  240.                     while (c && width--) {
  241.                         if (c >= '0' && c <= '9')
  242.                             trans = FC_DIG;
  243.                         else if (c == '.')
  244.                             trans = FC_DOT;
  245.                         else if (c == '+' || c == '-')
  246.                             trans = FC_SIGN;
  247.                         else if (tolower(c) == 'e')
  248.                             trans = FC_E;
  249.                         else
  250.                             goto fdone;
  251.  
  252.                         switch (fp_do[trans][fstate]) {
  253.                         case F_SIGN:
  254.                             neg = (c == '-');
  255.                             break;
  256.                         case F_ESIGN:
  257.                             eneg = (c == '-');
  258.                             break;
  259.                         case F_INT:
  260.                             n = 10*n + (c - '0');
  261.                             break;
  262.                         case F_FRAC:
  263.                            frac = 10*frac + (c - '0');
  264.                             fraclen++;
  265.                             break;
  266.                         case F_EXP:
  267.                            expo = 10*expo + (c - '0');
  268.                             break;
  269.                         case F_QUIT:
  270.                             goto fdone;
  271.                         }
  272.                         fstate = fp_ns[trans][fstate];
  273.                         c = (*get)(ip);
  274.                     }
  275.  
  276. fdone:
  277.                     if (!fp_sval[fstate])
  278.                         goto done;
  279.                     if (store) {
  280.                         fx = fp_scan(neg, eneg,
  281.                             n, frac, expo, fraclen);
  282.                         p = (unsigned char *) *args;
  283.                         if (lval)
  284.                             *((double *) p) = fx;
  285.                         else
  286.                             *((float *) p) = fx;
  287.                         ++cnt;
  288.                     }
  289.                     break;
  290. #endif
  291.  
  292.                 case 'c':    /* character data */
  293.                     width = wide1;
  294.                     endnull    = FALSE;
  295.                     delim[0] = '\0';
  296.                     goto strproc;
  297.  
  298.                 case '[':    /* string w/ delimiter set */
  299.  
  300.                     /* get delimiters */
  301.                     p = delim;
  302.  
  303.                     if (*++fmt == '^')
  304.                         fmt++;
  305.                     else
  306.                         lval = TRUE;
  307.  
  308.                     rngflag = 2;
  309.                     if ((*fmt == ']') || (*fmt == '-'))
  310.                         {
  311.                         *p++ = *fmt++;
  312.                         rngflag = FALSE;
  313.                         }
  314.  
  315.                     while (*fmt != ']')
  316.                         {
  317.                         if (*fmt == '\0')
  318.                             goto done;
  319.                         switch (rngflag)
  320.                             {
  321.                             case TRUE:
  322.                             c2 = *(p-2);
  323.                             if (c2 <= *fmt)
  324.                                 {
  325.                                 p -= 2;
  326.                                 while (c2 < *fmt)
  327.                                     *p++ = c2++;
  328.                                 rngflag = 2;
  329.                                 break;
  330.                                 }
  331.                             /* fall thru intentional */
  332.  
  333.                             case FALSE:
  334.                             rngflag = (*fmt == '-');
  335.                             break;
  336.  
  337.                             case 2:
  338.                             rngflag = FALSE;
  339.                             }
  340.  
  341.                         *p++ = *fmt++;
  342.                         }
  343.  
  344.                     *p = '\0';
  345.                     goto strproc;
  346.  
  347.                 case 's':    /* string data */
  348.                     skip();
  349. strproc:
  350.                     /* process string */
  351.                     p = ((unsigned char *) *args);
  352.  
  353.                     /* if the 1st char fails, match fails */
  354.                     if (width)
  355.                         {
  356.                         q = ((unsigned char *)
  357.                             strchr(delim, c));
  358.                         if((c < 1)
  359.                         || (lval ? !q : (int) q))
  360.                             {
  361.                             if (endnull)
  362.                                 *p = '\0';
  363.                             goto done;
  364.                             }
  365.                         }
  366.  
  367.                     for (;;) /* FOREVER */
  368.                         {
  369.                         if (store)
  370.                             *p++ = c;
  371.                         if (((c = (*get)(ip)) < 1) ||
  372.                             (--width == 0))
  373.                             break;
  374.  
  375.                         q = ((unsigned char *)
  376.                             strchr(delim, c));
  377.                         if (lval ? !q : (int) q)
  378.                             break;
  379.                         }
  380.  
  381.                     if (store)
  382.                         {
  383.                         if (endnull)
  384.                             *p = '\0';
  385.                         ++cnt;
  386.                         }
  387.                     break;
  388.  
  389.                 case '\0':    /* early EOS */
  390.                     --fmt;
  391.                     /* FALL THRU */
  392.  
  393.                 default:
  394.                     goto cmatch;
  395.                 }
  396.             }
  397.         else if (isspace(*fmt))        /* skip whitespace */
  398.             {
  399.             skip();
  400.             }
  401.         else 
  402.             {            /* normal match char */
  403. cmatch:
  404.             if (c != *fmt) 
  405.                 break;
  406.             c = (*get)(ip);
  407.             }
  408.  
  409.         if (store)
  410.             args++;
  411.  
  412.         if (!*++fmt)
  413.             break;
  414.         }
  415.  
  416. done:                        /* end of scan */
  417.     if ((c < 0) && (cnt == 0))
  418.         return(EOF);
  419.  
  420.     (*unget)(c, ip);
  421.     return(cnt);
  422.     }
  423.