home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / hce.lha / HCE / LibSource / clib / Math / src / _scanf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  8.5 KB  |  477 lines

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