home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / ansi / stdio / doscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-18  |  8.0 KB  |  390 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <ctype.h>
  6. #include <libc/file.h>
  7. #include <libc/local.h>
  8.  
  9. #define    SPC    01
  10. #define    STP    02
  11.  
  12. #define    SHORT    0
  13. #define    REGULAR    1
  14. #define    LONG    2
  15. #define LONGDOUBLE 4
  16. #define    INT    0
  17. #define    FLOAT    1
  18.  
  19. static int _innum(int **ptr, int type, int len, int size, FILE *iop, 
  20.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  21.                   int *eofptr);
  22. static int _instr(char *ptr, int type, int len, FILE *iop, 
  23.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  24.                   int *eofptr);
  25. static const char *_getccl(const unsigned char *s);
  26.  
  27. static char _sctab[256] = {
  28.     0,0,0,0,0,0,0,0,
  29.     0,SPC,SPC,SPC,SPC,SPC,0,0,
  30.     0,0,0,0,0,0,0,0,
  31.     0,0,0,0,0,0,0,0,
  32.     SPC,0,0,0,0,0,0,0,
  33.     0,0,0,0,0,0,0,0,
  34.     0,0,0,0,0,0,0,0,
  35.     0,0,0,0,0,0,0,0,
  36. };
  37.  
  38. static int nchars = 0;
  39.  
  40. int 
  41. _doscan(FILE *iop, const char *fmt, void **argp)
  42. {
  43.   return(_doscan_low(iop, fgetc, ungetc, fmt, argp));
  44. }
  45.  
  46. int
  47. _doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
  48.             const char *fmt, void **argp)
  49. {
  50.   register int ch;
  51.   int nmatch, len, ch1;
  52.   int **ptr, fileended, size;
  53.  
  54.   nchars = 0;
  55.   nmatch = 0;
  56.   fileended = 0;
  57.   for (;;) switch (ch = *fmt++) {
  58.   case '\0': 
  59.     return (nmatch);
  60.   case '%':
  61.     if ((ch = *fmt++) == '%')
  62.       goto def;
  63.     ptr = 0;
  64.     if (ch != '*')
  65.       ptr = (int **)argp++;
  66.     else
  67.       ch = *fmt++;
  68.     len = 0;
  69.     size = REGULAR;
  70.     while (isdigit(ch)) {
  71.       len = len*10 + ch - '0';
  72.       ch = *fmt++;
  73.     }
  74.     if (len == 0)
  75.       len = 30000;
  76.     
  77.     if (ch=='l') 
  78.     {
  79.       size = LONG;
  80.       ch = *fmt++;
  81.       if (ch=='l')
  82.       {
  83.         size = LONGDOUBLE; /* for long long 'll' format */
  84.         ch = *fmt++;
  85.       }
  86.     }
  87.     else if (ch=='h') {
  88.       size = SHORT;
  89.       ch = *fmt++;
  90.     } else if (ch=='L') {
  91.       size = LONGDOUBLE;
  92.       ch = *fmt++;
  93.     } else if (ch=='[')
  94.       fmt = _getccl((const unsigned char *)fmt);
  95.     if (isupper(ch)) {
  96.       /* ch = tolower(ch);
  97.      gcc gives warning: ANSI C forbids braced
  98.      groups within expressions */
  99.       ch += 'a' - 'A';
  100.       if (size==LONG)
  101.         size = LONGDOUBLE;
  102.       else
  103.         size = LONG;
  104.     }
  105.     if (ch == '\0')
  106.       return(-1);
  107.  
  108.     if (ch == 'n')
  109.     {
  110.       if (!ptr)
  111.         break;
  112.       if (size==LONG)
  113.     **(long**)ptr = nchars;
  114.       else if (size==SHORT)
  115.         **(short**)ptr = nchars;
  116.       else if (size==LONGDOUBLE)
  117.         **(long long**)ptr = nchars;
  118.       else
  119.         **(int**)ptr = nchars;
  120.       break;
  121.     }
  122.       
  123.     if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc,
  124.            &fileended))
  125.     {
  126.       if (ptr)
  127.         nmatch++;
  128.     }
  129.     else
  130.     {
  131.       if (fileended && nmatch==0)
  132.         return(-1);
  133.       return(nmatch);
  134.     }
  135.     break;
  136.   case ' ':
  137.   case '\n':
  138.   case '\t': 
  139.   case '\r':
  140.   case '\f':
  141.   case '\v':
  142.     while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC))
  143.       ;
  144.     if (ch1 != EOF)
  145.     {
  146.       scan_ungetc(ch1, iop);
  147.     }
  148.     nchars--;
  149.     break;
  150.  
  151.   default:
  152.   def:
  153.     ch1 = scan_getc(iop);
  154.     if (ch1 != EOF) nchars++;
  155.     if (ch1 != ch) {
  156.       if (ch1==EOF)
  157.     return(nmatch? nmatch: -1);
  158.       scan_ungetc(ch1, iop);
  159.       nchars--;
  160.       return(nmatch);
  161.     }
  162.   }
  163. }
  164.  
  165. static int
  166. _innum(int **ptr, int type, int len, int size, FILE *iop,
  167.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  168. {
  169.   register char *np;
  170.   char numbuf[64];
  171.   register c, base;
  172.   int expseen, scale, negflg, c1, ndigit;
  173.   long long lcval;
  174.   int cpos;
  175.  
  176.   if (type=='c' || type=='s' || type=='[')
  177.     return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len,
  178.           iop, scan_getc, scan_ungetc, eofptr));
  179.   lcval = 0;
  180.   ndigit = 0;
  181.   scale = INT;
  182.   if (type=='e'||type=='f'||type=='g')
  183.     scale = FLOAT;
  184.   base = 10;
  185.   if (type=='o')
  186.     base = 8;
  187.   else if (type=='x')
  188.     base = 16;
  189.   np = numbuf;
  190.   expseen = 0;
  191.   negflg = 0;
  192.   while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC))
  193.     ;
  194.   if (c == EOF) nchars--;
  195.   if (c=='-') {
  196.     negflg++;
  197.     *np++ = c;
  198.     c = scan_getc(iop);
  199.     nchars++;
  200.     len--;
  201.   } else if (c=='+') {
  202.     len--;
  203.     c = scan_getc(iop);
  204.     nchars++;
  205.   }
  206.   cpos = 0;
  207.   for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) {
  208.     cpos++;
  209.     if (c == '0' && cpos == 1 && type == 'i')
  210.       base = 8;
  211.     if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x')
  212.     && cpos == 2 && lcval == 0)
  213.     {
  214.       base = 16;
  215.       continue;
  216.     }
  217.     if (isdigit(c)
  218.     || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) {
  219.       ndigit++;
  220.       if (base==8)
  221.     lcval <<=3;
  222.       else if (base==10)
  223.     lcval = ((lcval<<2) + lcval)<<1;
  224.       else
  225.     lcval <<= 4;
  226.       c1 = c;
  227.       if (isdigit(c))
  228.     c -= '0';
  229.       else if ('a'<=c && c<='f')
  230.     c -= 'a'-10;
  231.       else
  232.     c -= 'A'-10;
  233.       lcval += c;
  234.       c = c1;
  235.       continue;
  236.     } else if (c=='.') {
  237.       if (base!=10 || scale==INT)
  238.     break;
  239.       ndigit++;
  240.       continue;
  241.     } else if ((c=='e'||c=='E') && expseen==0) {
  242.       if (base!=10 || scale==INT || ndigit==0)
  243.     break;
  244.       expseen++;
  245.       *np++ = c;
  246.       c = scan_getc(iop);
  247.       nchars++;
  248.       if (c!='+'&&c!='-'&&('0'>c||c>'9'))
  249.     break;
  250.     } else
  251.       break;
  252.   }
  253.   if (negflg)
  254.     lcval = -lcval;
  255.   if (c != EOF) {
  256.     scan_ungetc(c, iop);
  257.     *eofptr = 0;
  258.   } else
  259.     *eofptr = 1;
  260.   nchars--;
  261.   if (np==numbuf || (negflg && np==numbuf+1) ) /* gene dykes*/
  262.     return(0);
  263.   if (ptr==NULL)
  264.     return(1);
  265.   *np++ = 0;
  266.   switch((scale<<4) | size) {
  267.  
  268.   case (FLOAT<<4) | SHORT:
  269.   case (FLOAT<<4) | REGULAR:
  270.     **(float **)ptr = atof(numbuf);
  271.     break;
  272.  
  273.   case (FLOAT<<4) | LONG:
  274.     **(double **)ptr = atof(numbuf);
  275.     break;
  276.  
  277.   case (FLOAT<<4) | LONGDOUBLE:
  278.     **(long double **)ptr = _atold(numbuf);
  279.     break;
  280.  
  281.   case (INT<<4) | SHORT:
  282.     **(short **)ptr = (short)lcval;
  283.     break;
  284.  
  285.   case (INT<<4) | REGULAR:
  286.     **(int **)ptr = (int)lcval;
  287.     break;
  288.  
  289.   case (INT<<4) | LONG:
  290.     **(long **)ptr = lcval;
  291.     break;
  292.  
  293.   case (INT<<4) | LONGDOUBLE:
  294.     **(long long **)ptr = lcval;
  295.     break;
  296.   }
  297.   return(1);
  298. }
  299.  
  300. static int
  301. _instr(char *ptr, int type, int len, FILE *iop,
  302.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  303. {
  304.   register ch;
  305.   register char *optr;
  306.   int ignstp;
  307.  
  308.   *eofptr = 0;
  309.   optr = ptr;
  310.   if (type=='c' && len==30000)
  311.     len = 1;
  312.   ignstp = 0;
  313.   if (type=='s')
  314.     ignstp = SPC;
  315.   while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp)
  316.     ;
  317.   ignstp = SPC;
  318.   if (type=='c')
  319.     ignstp = 0;
  320.   else if (type=='[')
  321.     ignstp = STP;
  322.   while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
  323.     if (ptr)
  324.       *ptr++ = ch;
  325.     if (--len <= 0)
  326.       break;
  327.     ch = scan_getc(iop);
  328.     nchars++;
  329.   }
  330.   if (ch != EOF) {
  331.     if (len > 0)
  332.     {
  333.       scan_ungetc(ch, iop);
  334.       nchars--;
  335.     }
  336.     *eofptr = 0;
  337.   } else
  338.   {
  339.     nchars--;
  340.     *eofptr = 1;
  341.   }
  342.   if (!ptr)
  343.     return(1);
  344.   if (ptr!=optr) {
  345.     if (type!='c')
  346.       *ptr++ = '\0';
  347.     return(1);
  348.   }
  349.   return(0);
  350. }
  351.  
  352. static const char *
  353. _getccl(const unsigned char *s)
  354. {
  355.   register c, t;
  356.  
  357.   t = 0;
  358.   if (*s == '^') {
  359.     t++;
  360.     s++;
  361.   }
  362.   for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
  363.     if (t)
  364.       _sctab[c] &= ~STP;
  365.     else
  366.       _sctab[c] |= STP;
  367.   if ((c = *s) == ']' || c == '-') { /* first char is special */
  368.     if (t)
  369.       _sctab[c] |= STP;
  370.     else
  371.       _sctab[c] &= ~STP;
  372.     s++;
  373.   }
  374.   while ((c = *s++) != ']') {
  375.     if (c==0)
  376.       return((const char *)--s);
  377.     else if (c == '-' && *s != ']' && s[-2] < *s) {
  378.       for (c = s[-2] + 1; c < *s; c++)
  379.     if (t)
  380.       _sctab[c] |= STP;
  381.     else
  382.       _sctab[c] &= ~STP;
  383.     } else if (t)
  384.       _sctab[c] |= STP;
  385.     else
  386.       _sctab[c] &= ~STP;
  387.   }
  388.   return((const char *)s);
  389. }
  390.