home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 2 / DATAFILE_PDCD2.iso / utilities2 / unixlib36d / UnixLib36d / src / stdio / c / scan < prev    next >
Encoding:
Text File  |  1994-03-08  |  13.2 KB  |  837 lines

  1. static char sccs_id[] = "@(#) scan.c 3.0 " __DATE__ " HJR";
  2.  
  3. /* scan.c (c) Copyright 1990 H.Rogers */
  4.  
  5. /* Implements __scanf(fp,format,argp,cnt) which is called by all
  6.  * scanf() functions to perform formatted input. __scanf() returns a count
  7.  * of the number of characters read. *cnt is assigned to an item count. */
  8.  
  9. /* A conversion is of the form "%[*][width][size]function".
  10.  * For full details RTFM for scanf(3). */
  11.  
  12. #include <stddef.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18.  
  19. __STDIOLIB__
  20.  
  21. #define ungetc(c,f) \
  22.     (((f)->i_ptr > (f)->i_base) ? ((f)->i_cnt++,*--(f)->i_ptr = (c)) : -1)
  23.  
  24. /* To avoid truncation SCBUFSIZ should be 256+.
  25.  * This library will *not* buffer overflow unless SCBUFSIZ < 4. */
  26.  
  27. #define SCBUFSIZ    256    /* size of buffer for %feEgG & %[ */
  28.  
  29.  
  30. /* the prototypes for the input functions */
  31.  
  32. static int __s_nin (FILE *, va_list *, const char **);
  33.  
  34. static int __s_char (FILE *, va_list *, const char **);
  35. static int __s_str (FILE *, va_list *, const char **);
  36. static int __s_sdec (FILE *, va_list *, const char **);
  37. static int __s_sint (FILE *, va_list *, const char **);
  38. static int __s_uoct (FILE *, va_list *, const char **);
  39. static int __s_udec (FILE *, va_list *, const char **);
  40. static int __s_uhex (FILE *, va_list *, const char **);
  41. static int __s_fdbl (FILE *, va_list *, const char **);
  42. static int __s_ptr (FILE *, va_list *, const char **);
  43. static int __s_sdel (FILE *, va_list *, const char **);
  44.  
  45.  
  46. /* __scnt is set to the number of characters read by __scanf() and
  47.  * is used by __s_nin() to output the number of characters read. */
  48.  
  49. static size_t __scnt;
  50.  
  51. static int __scflag;        /* assignment suppression flag */
  52. static int __scsize;        /* -1 = unspecified */
  53. static unsigned int __scwidth;    /* width */
  54.  
  55. static signed char __scfnc[32] =    /* conversions */
  56. {
  57.   -1, -1,
  58.   1,                /* %c */
  59.   3,                /* %d */
  60.   8,                /* %eE */
  61.   8,                /* %f */
  62.   8,                /* %gG */
  63.   -1,
  64.   4,                /* %i */
  65.   -1, -1, -1, -1,
  66.   0,                /* %n */
  67.   5,                /* %o */
  68.   9,                /* %p */
  69.   -1, -1,
  70.   2,                /* %s */
  71.   -1,
  72.   6,                /* %u */
  73.   -1, -1,
  74.   7,                /* %xX */
  75.   -1, -1, -1, -1, -1, -1, -1, -1
  76. };
  77.  
  78. /* __scfn[] is the array of input functions called by __scanf() -
  79.  * They return a value indicating whether they successfully interpreted
  80.  * the input or not. 0 indicates failure; a +ve value is a count
  81.  * of the number of characters read. */
  82.  
  83. static int (*__scfn[]) (FILE *, va_list *, const char **) =
  84. {
  85.   __s_nin,            /* %n no. of characters read so far */
  86.     __s_char,            /* %c character */
  87.     __s_str,            /* %s string */
  88.     __s_sdec,            /* %d signed decimal */
  89.     __s_sint,            /* %i signed integer */
  90.     __s_uoct,            /* %o unsigned octal */
  91.     __s_udec,            /* %u unsigned decimal */
  92.     __s_uhex,            /* %xX unsigned hex */
  93.     __s_fdbl,            /* %feEgG float (double) */
  94.     __s_ptr,            /* %p unsigned hex value of pointer */
  95.     __s_sdel            /* %[ delimited string */
  96. };
  97.  
  98.  
  99. /* __scanf() */
  100.  
  101. int
  102. __scanf (register FILE * f, const char *format, va_list ap, int *cnt)
  103. {
  104.   register const char *s1 = format;
  105.   register int n = 0;
  106.   register int c;
  107.  
  108.   for (;;)
  109.     {
  110.       if (!(c = *s1++))
  111.     goto ret;
  112.  
  113.       if (isspace (c))
  114.     continue;        /* white space in formatting string is ignored */
  115.  
  116.       if (c != '%')
  117.     {
  118.       register int m, l = 0;
  119.  
  120.     match:
  121.       do
  122.         {
  123.           if ((l++, m = getc (f)) < 0)
  124.         {
  125.           if (!n)
  126.             goto eof;
  127.           goto ret;
  128.         }
  129.         }
  130.       while (isspace (m));
  131.       __scnt += l;
  132.       if (m == c)
  133.         continue;
  134.       (void) ungetc (m, f);
  135.       goto ret;
  136.     }
  137.       else
  138.     {
  139.       if (!(c = *s1++))
  140.         goto ret;
  141.       if (c == '%')
  142.         goto match;
  143.     }
  144.  
  145.       {                /* we now have a % conversion */
  146.     register int i, j;
  147.     const char *s;
  148.  
  149. /* looking for "%[*][width][size]function" */
  150.  
  151. /* set __scflag */
  152.  
  153.     __scflag = 0;
  154.     if (c == '*')
  155.       {
  156.         if (!(c = *s1++))
  157.           goto ret;
  158.         __scflag = 1;
  159.       }
  160.  
  161. /* set __scwidth */
  162.  
  163.     __scwidth = 0;
  164.     if (isdigit (c))
  165.       {
  166.         __scwidth = (unsigned int) strtoul (s1 - 1, (char **) &s, 0);
  167.         s1 = s;
  168.         if (!(c = *s1++))
  169.           goto ret;
  170.         if (__scwidth > SCBUFSIZ)
  171.           __scwidth = SCBUFSIZ;
  172.       }
  173.  
  174. /* set __scsize */
  175.  
  176.     switch (c)
  177.       {
  178.       case 'h':
  179.         __scsize = 0;
  180.         if (!(c = *s1++))
  181.           goto ret;
  182.         break;
  183.       case 'l':
  184.         __scsize = 1;
  185.         if (!(c = *s1++))
  186.           goto ret;
  187.         break;
  188.       case 'L':
  189.         __scsize = 2;
  190.         if (!(c = *s1++))
  191.           goto ret;
  192.         break;
  193.       default:
  194.         __scsize = -1;
  195.         break;
  196.       }
  197.  
  198. /* call appropriate input function */
  199.  
  200.     i = (c == '[') ? 10 : __scfnc[(_tolower (c) - 'a') & 31];
  201.  
  202.     if (i >= 0)
  203.       {
  204.         s = s1;
  205.         j = (*__scfn[i]) (f, (va_list *) (&ap), &s);
  206.         s1 = s;
  207.  
  208.         if (j < 0 && !n)
  209.           goto eof;
  210.         else if (j <= 0)
  211.           goto ret;
  212.         else
  213.           {
  214.         __scnt += j;
  215.         if (!__scflag)
  216.           n++;
  217.           }
  218.       }
  219.     else
  220.       {
  221.         if (!n)
  222.           goto eof;
  223.         goto ret;
  224.       }
  225.       }
  226.     }
  227.  
  228. ret:*cnt = n;
  229.   return (__scnt);
  230.  
  231. eof:*cnt = 0;
  232.   return (-1);
  233. }
  234.  
  235.  
  236. /* __s_nin() */
  237.  
  238. static int
  239. __s_nin (register FILE * f, va_list * ap, const char **e)
  240. {
  241.   if (!__scflag)
  242.     {
  243.       switch (__scsize)
  244.     {
  245.     case 0:
  246.       *va_arg (*ap, short *) = (short) __scnt;
  247.       break;
  248.     case 1:
  249.       *va_arg (*ap, long *) = (long) __scnt;
  250.       break;
  251.     default:
  252.       *va_arg (*ap, int *) = (int) __scnt;
  253.       break;
  254.     }
  255.     }
  256.  
  257.   return (0);
  258. }
  259.  
  260. /* __s_char() */
  261.  
  262. static int
  263. __s_char (register FILE * f, va_list * ap, const char **e)
  264. {
  265.   register unsigned int w;
  266.   register int n = 0;
  267.   register char *s;
  268.   register int c;
  269.  
  270.   w = __scwidth;
  271.   if (!w)
  272.     w = 1;            /* default - 1 char */
  273.  
  274.   s = __scflag ? 0 : va_arg (*ap, char *);
  275.  
  276.   while (w)
  277.     {
  278.       if ((c = getc (f)) < 0)
  279.     return (n ? n : -1);
  280.       if (s)
  281.     *s++ = c;
  282.       n++, w--;
  283.     }
  284.  
  285.   return (n);
  286. }
  287.  
  288. /* __s_str() */
  289.  
  290. static int
  291. __s_str (register FILE * f, va_list * ap, const char **e)
  292. {
  293.   register unsigned int w;
  294.   register int n = 0;
  295.   register char *s;
  296.   register int c;
  297.  
  298.   w = __scwidth;
  299.   if (!w)
  300.     w = SCBUFSIZ;
  301.  
  302.   s = __scflag ? 0 : va_arg (*ap, char *);
  303.  
  304.   do
  305.     {
  306.       if ((c = getc (f)) < 0)
  307.     {
  308.       if (s)
  309.         *s = 0;
  310.       return (-1);
  311.     }
  312.     }
  313.   while (isspace (c));
  314.  
  315.   while (!isspace (c) && w)
  316.     {
  317.       if (s)
  318.     *s++ = c;
  319.       n++, w--;
  320.       if ((c = getc (f)) < 0)
  321.     {
  322.       if (s)
  323.         *s = 0;
  324.       return (n);
  325.     }
  326.     }
  327.  
  328.   if (s)
  329.     *s = 0;
  330.   (void) ungetc (c, f);
  331.  
  332.   return (n);
  333. }
  334.  
  335. /* __s_sdec() */
  336.  
  337. static int
  338. __s_sdec (register FILE * f, va_list * ap, const char **e)
  339. {
  340.   register unsigned int w;
  341.   register int n = 0;
  342.   register int c;
  343.   register int i = 0, i_ = 0;
  344.  
  345.   w = __scwidth;
  346.   if (!w)
  347.     w = SCBUFSIZ;
  348.  
  349.   do
  350.     {
  351.       if ((c = getc (f)) < 0)
  352.     return (-1);
  353.     }
  354.   while (isspace (c));
  355.  
  356.   if (c == '+' || c == '-')
  357.     {
  358.       if (c == '-')
  359.     i_ = 1;
  360.       n++, w--;
  361.       if ((c = getc (f)) < 0)
  362.     goto ret;
  363.     }
  364.  
  365.   while (isdigit (c) && w)
  366.     {
  367.       i = i * 10 + (c - '0');
  368.       n++, w--;
  369.       if ((c = getc (f)) < 0)
  370.     goto ret;
  371.     }
  372.  
  373.   (void) ungetc (c, f);
  374.  
  375. ret:if (!__scflag && n)
  376.     {
  377.       if (i_)
  378.     i = -i;
  379.       switch (__scsize)
  380.     {
  381.     case 0:
  382.       *va_arg (*ap, short *) = (short) i;
  383.       break;
  384.     case 1:
  385.       *va_arg (*ap, long *) = (long) i;
  386.       break;
  387.     default:
  388.       *va_arg (*ap, int *) = i;
  389.       break;
  390.     }
  391.     }
  392.  
  393.   return (n);
  394. }
  395.  
  396. /* __s_sint() */
  397.  
  398. static int
  399. __s_sint (register FILE * f, va_list * ap, const char **e)
  400. {
  401.   register unsigned int w;
  402.   register int n = 0;
  403.   register int c;
  404.   register int i = 0, i_ = 0;
  405.   register int b = 10;
  406.  
  407.   w = __scwidth;
  408.   if (!w)
  409.     w = SCBUFSIZ;
  410.  
  411.   do
  412.     {
  413.       if ((c = getc (f)) < 0)
  414.     return (-1);
  415.     }
  416.   while (isspace (c));
  417.  
  418.   if (c == '+' || c == '-')
  419.     {
  420.       if (c == '-')
  421.     i_ = 1;
  422.       n++, w--;
  423.       if ((c = getc (f)) < 0)
  424.     goto ret;
  425.     }
  426.  
  427.   if (c == '0' && w)
  428.     {
  429.       b = 010;
  430.       n++, w--;
  431.       if ((c = getc (f)) < 0)
  432.     goto ret;
  433.       if ((c == 'x' || c == 'X') && w)
  434.     {
  435.       b = 0x10;
  436.       n++, w--;
  437.       if ((c = getc (f)) < 0)
  438.         goto ret;
  439.     }
  440.     }
  441.  
  442.   switch (b)
  443.     {
  444.     case 010:
  445.       while (c >= '0' && c < '8' && w)
  446.     {
  447.       i = i * b + (c - '0');
  448.       n++, w--;
  449.       if ((c = getc (f)) < 0)
  450.         goto ret;
  451.     }
  452.       break;
  453.     case 10:
  454.       while (isdigit (c) && w)
  455.     {
  456.       i = i * b + (c - '0');
  457.       n++, w--;
  458.       if ((c = getc (f)) < 0)
  459.         goto ret;
  460.     }
  461.       break;
  462.     case 0x10:
  463.       while (isxdigit (c) && w)
  464.     {
  465.       i = i * b + ((c > '9') ? ((c & 31) + 9) : (c - '0'));
  466.       n++, w--;
  467.       if ((c = getc (f)) < 0)
  468.         goto ret;
  469.     }
  470.       break;
  471.     }
  472.  
  473.   (void) ungetc (c, f);
  474.  
  475. ret:if (!__scflag && n)
  476.     {
  477.       if (i_)
  478.     i = -i;
  479.       switch (__scsize)
  480.     {
  481.     case 0:
  482.       *va_arg (*ap, short *) = (short) i;
  483.       break;
  484.     case 1:
  485.       *va_arg (*ap, long *) = (long) i;
  486.       break;
  487.     default:
  488.       *va_arg (*ap, int *) = i;
  489.       break;
  490.     }
  491.     }
  492.  
  493.   return (n);
  494. }
  495.  
  496. /* __s_uoct() */
  497.  
  498. static int
  499. __s_uoct (register FILE * f, va_list * ap, const char **e)
  500. {
  501.   register unsigned int w;
  502.   register int n = 0;
  503.   register int c;
  504.   register unsigned int i = 0;
  505.  
  506.   w = __scwidth;
  507.   if (!w)
  508.     w = SCBUFSIZ;
  509.  
  510.   do
  511.     {
  512.       if ((c = getc (f)) < 0)
  513.     return (-1);
  514.     }
  515.   while (isspace (c));
  516.  
  517.   while (c >= '0' && c <= '7' && w)
  518.     {
  519.       i = i * 010 + (c - '0');
  520.       n++, w--;
  521.       if ((c = getc (f)) < 0)
  522.     goto ret;
  523.     }
  524.  
  525.   (void) ungetc (c, f);
  526.  
  527. ret:if (!__scflag && n)
  528.     {
  529.       switch (__scsize)
  530.     {
  531.     case 0:
  532.       *va_arg (*ap, short *) = (short) i;
  533.       break;
  534.     case 1:
  535.       *va_arg (*ap, long *) = (long) i;
  536.       break;
  537.     default:
  538.       *va_arg (*ap, int *) = i;
  539.       break;
  540.     }
  541.     }
  542.  
  543.   return (n);
  544. }
  545.  
  546. /* __s_udec() */
  547.  
  548. static int
  549. __s_udec (register FILE * f, va_list * ap, const char **e)
  550. {
  551.   register unsigned int w;
  552.   register int n = 0;
  553.   register int c;
  554.   register unsigned int i = 0;
  555.  
  556.   w = __scwidth;
  557.   if (!w)
  558.     w = SCBUFSIZ;
  559.  
  560.   do
  561.     {
  562.       if ((c = getc (f)) < 0)
  563.     return (-1);
  564.     }
  565.   while (isspace (c));
  566.  
  567.   while (isdigit (c) && w)
  568.     {
  569.       i = i * 10 + (c - '0');
  570.       n++, w--;
  571.       if ((c = getc (f)) < 0)
  572.     goto ret;
  573.     }
  574.  
  575.   (void) ungetc (c, f);
  576.  
  577. ret:if (!__scflag && n)
  578.     {
  579.       switch (__scsize)
  580.     {
  581.     case 0:
  582.       *va_arg (*ap, short *) = (short) i;
  583.       break;
  584.     case 1:
  585.       *va_arg (*ap, long *) = (long) i;
  586.       break;
  587.     default:
  588.       *va_arg (*ap, int *) = i;
  589.       break;
  590.     }
  591.     }
  592.  
  593.   return (n);
  594. }
  595.  
  596. /* __s_uhex() */
  597.  
  598. static int
  599. __s_uhex (register FILE * f, va_list * ap, const char **e)
  600. {
  601.   register unsigned int w;
  602.   register int n = 0;
  603.   register int c;
  604.   register unsigned int i = 0;
  605.  
  606.   w = __scwidth;
  607.   if (!w)
  608.     w = SCBUFSIZ;
  609.  
  610.   do
  611.     {
  612.       if ((c = getc (f)) < 0)
  613.     return (-1);
  614.     }
  615.   while (isspace (c));
  616.  
  617.   if (c == '0' && w)
  618.     {
  619.       n++, w--;
  620.       if ((c = getc (f)) < 0)
  621.     goto ret;
  622.       if ((c == 'x' || c == 'X') && w)
  623.     {
  624.       n++, w--;
  625.       if ((c = getc (f)) < 0)
  626.         goto ret;
  627.     }
  628.     }
  629.  
  630.   while (isxdigit (c) && w)
  631.     {
  632.       i = i * 0x10 + (isdigit (c) ? (c - '0') : ((c & 7) + 9));
  633.       n++, w--;
  634.       if ((c = getc (f)) < 0)
  635.     goto ret;
  636.     }
  637.  
  638.   (void) ungetc (c, f);
  639.  
  640. ret:if (!__scflag && n)
  641.     {
  642.       switch (__scsize)
  643.     {
  644.     case 0:
  645.       *va_arg (*ap, short *) = (short) i;
  646.       break;
  647.     case 1:
  648.       *va_arg (*ap, long *) = (long) i;
  649.       break;
  650.     default:
  651.       *va_arg (*ap, int *) = i;
  652.       break;
  653.     }
  654.     }
  655.  
  656.   return (n);
  657. }
  658.  
  659. /* __s_fdbl() */
  660.  
  661. static int
  662. __s_fdbl (register FILE * f, va_list * ap, const char **e)
  663. {
  664.   register unsigned int w;
  665.   register int n = 0;
  666.   register int c;
  667.   register double i;
  668.   register char *s;
  669.   register int l = 0;
  670.  
  671. #define F_SIGN    0001
  672. #define F_DP    0002
  673. #define F_XP    0004
  674. #define F_XSIGN 0010
  675.  
  676.   if (!__scflag)
  677.     {
  678.       if (!(s = __sbuf))
  679.     if (!(s = __sbuf = malloc (SCBUFSIZ)))
  680.       return (0);
  681.     }
  682.   else
  683.     s = 0;
  684.  
  685.   w = __scwidth;
  686.   if (!w)
  687.     w = SCBUFSIZ;
  688.  
  689.   do
  690.     {
  691.       if ((c = getc (f)) < 0)
  692.     return (-1);
  693.     }
  694.   while (isspace (c));
  695.  
  696.   if ((c == '-' || c == '+') && !(l & F_SIGN))
  697.     {
  698.       l |= F_SIGN;
  699.       goto l1;
  700.     }
  701.  
  702.   if (!isdigit (c))
  703.     goto l2;
  704.  
  705. l1:
  706.  
  707.   if (!w)
  708.     goto ret;
  709.  
  710.   if (s)
  711.     *s++ = c;
  712.   n++, w--;
  713.   if ((c = getc (f)) < 0)
  714.     goto ret;
  715.  
  716.   if (isdigit (c))
  717.     goto l1;
  718.  
  719. l2:
  720.  
  721.   if ((c == '-' || c == '+') && (l & F_XP) && !(l & F_XSIGN))
  722.     {
  723.       l |= F_XSIGN;
  724.       goto l1;
  725.     }
  726.   if (c == '.' && !(l & F_DP))
  727.     {
  728.       l |= F_DP;
  729.       goto l1;
  730.     }
  731.   if ((c == 'e' || c == 'E') && !(l & F_XP))
  732.     {
  733.       l |= F_XP;
  734.       goto l1;
  735.     }
  736.  
  737. ret:if (c >= 0)
  738.     (void) ungetc (c, f);
  739.  
  740.   if (!__scflag && n)
  741.     {
  742.       *s = 0;
  743.       i = strtod (__sbuf, 0);
  744.       switch (__scsize)
  745.     {
  746.     case 2:
  747.       *va_arg (*ap, long double *) = (long double) i;
  748.       break;
  749.     case 1:
  750.       *va_arg (*ap, double *) = i;
  751.       break;
  752.     default:
  753.       *va_arg (*ap, float *) = (float) i;
  754.       break;
  755.     }
  756.     }
  757.  
  758.   return (n);
  759.  
  760. #undef F_SIGN
  761. #undef F_DP
  762. #undef F_XP
  763. #undef F_XSIGN
  764. }
  765.  
  766. /* __s_ptr() */
  767.  
  768. static int
  769. __s_ptr (register FILE * f, va_list * ap, const char **e)
  770. {
  771.   return (__s_uhex (f, ap, e));
  772. }
  773.  
  774. /* __s_sdel() */
  775.  
  776. static int
  777. __s_sdel (register FILE * f, va_list * ap, const char **e)
  778. {
  779.   register const char *o;
  780.   register char *s, *d;
  781.   register int w, n = 0, m = 0, c;
  782.  
  783.   if (!(d = __sbuf))
  784.     if (!(d = __sbuf = malloc (SCBUFSIZ)))
  785.       return (0);
  786.  
  787.   o = (*e);
  788.   if (*o == '^')
  789.     o++, m++;
  790.  
  791.   w = SCBUFSIZ;
  792.   if (*o == ']')
  793.     *d++ = *o++, w--;
  794.  
  795.   while (w--)
  796.     {
  797.       if (!(c = *o++) || c == ']')
  798.     break;
  799.       *d++ = c;
  800.     }
  801.  
  802.   (*e) = o;
  803.   *d = 0;
  804.   d = __sbuf;
  805.  
  806.   w = __scwidth;
  807.   if (!w)
  808.     w = SCBUFSIZ;
  809.  
  810.   s = __scflag ? 0 : va_arg (*ap, char *);
  811.  
  812.   if ((c = getc (f)) < 0)
  813.     {
  814.       if (s)
  815.     *s = 0;
  816.       return (-1);
  817.     }
  818.  
  819.   while (w--)
  820.     {
  821.       if (!strchr (d, c) ^ m)
  822.     break;
  823.       if (s)
  824.     *s++ = c;
  825.       n++;
  826.       if ((c = getc (f)) < 0)
  827.     goto ret;
  828.     }
  829.  
  830.   (void) ungetc (c, f);
  831.  
  832. ret:if (s)
  833.     *s = 0;
  834.  
  835.   return (n);
  836. }
  837.