home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / ansi / stdio / doscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-24  |  7.5 KB  |  358 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.     if (ch == 'n')
  64.     {
  65.       **(int **)argp++ = nchars;
  66.       break;
  67.     }
  68.     if (fileended)
  69.       return(nmatch? nmatch: -1);
  70.     ptr = 0;
  71.     if (ch != '*')
  72.       ptr = (int **)argp++;
  73.     else
  74.       ch = *fmt++;
  75.     len = 0;
  76.     size = REGULAR;
  77.     while (isdigit(ch)) {
  78.       len = len*10 + ch - '0';
  79.       ch = *fmt++;
  80.     }
  81.     if (len == 0)
  82.       len = 30000;
  83.     if (ch=='l') {
  84.       size = LONG;
  85.       ch = *fmt++;
  86.     } else if (ch=='h') {
  87.       size = SHORT;
  88.       ch = *fmt++;
  89.     } else if (ch=='L') {
  90.       size = LONGDOUBLE;
  91.       ch = *fmt++;
  92.     } else if (ch=='[')
  93.       fmt = _getccl((const unsigned char *)fmt);
  94.     if (isupper(ch)) {
  95.       /* ch = tolower(ch);
  96.      gcc gives warning: ANSI C forbids braced
  97.      groups within expressions */
  98.       ch += 'a' - 'A';
  99.       size = LONG;
  100.     }
  101.     if (ch == '\0')
  102.       return(-1);
  103.     if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc,
  104.            &fileended) && ptr)
  105.       nmatch++;
  106. /* breaks %n */
  107. /*    if (fileended) {
  108.       return(nmatch? nmatch: -1);
  109.     } */
  110.     break;
  111.   case ' ':
  112.   case '\n':
  113.   case '\t': 
  114.   case '\r':
  115.   case '\f':
  116.   case '\v':
  117.     while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC))
  118.       ;
  119.     if (ch1 != EOF)
  120.     {
  121.       scan_ungetc(ch1, iop);
  122.     }
  123.     nchars--;
  124.     break;
  125.  
  126.   default:
  127.   def:
  128.     ch1 = scan_getc(iop);
  129.     if (ch1 != EOF) nchars++;
  130.     if (ch1 != ch) {
  131.       if (ch1==EOF)
  132.     return(-1);
  133.       scan_ungetc(ch1, iop);
  134.       nchars--;
  135.       return(nmatch);
  136.     }
  137.   }
  138. }
  139.  
  140. static int
  141. _innum(int **ptr, int type, int len, int size, FILE *iop,
  142.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  143. {
  144.   register char *np;
  145.   char numbuf[64];
  146.   register c, base;
  147.   int expseen, scale, negflg, c1, ndigit;
  148.   long lcval;
  149.   int cpos;
  150.  
  151.   if (type=='c' || type=='s' || type=='[')
  152.     return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len,
  153.           iop, scan_getc, scan_ungetc, eofptr));
  154.   lcval = 0;
  155.   ndigit = 0;
  156.   scale = INT;
  157.   if (type=='e'||type=='f'||type=='g')
  158.     scale = FLOAT;
  159.   base = 10;
  160.   if (type=='o')
  161.     base = 8;
  162.   else if (type=='x')
  163.     base = 16;
  164.   np = numbuf;
  165.   expseen = 0;
  166.   negflg = 0;
  167.   while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC))
  168.     ;
  169.   if (c == EOF) nchars--;
  170.   if (c=='-') {
  171.     negflg++;
  172.     *np++ = c;
  173.     c = scan_getc(iop);
  174.     nchars++;
  175.     len--;
  176.   } else if (c=='+') {
  177.     len--;
  178.     c = scan_getc(iop);
  179.     nchars++;
  180.   }
  181.   cpos = 0;
  182.   for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) {
  183.     cpos++;
  184.     if (c == '0' && cpos == 1 && type == 'i')
  185.       base = 8;
  186.     if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x')
  187.     && cpos == 2 && lcval == 0)
  188.     {
  189.       base = 16;
  190.       continue;
  191.     }
  192.     if (isdigit(c)
  193.     || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) {
  194.       ndigit++;
  195.       if (base==8)
  196.     lcval <<=3;
  197.       else if (base==10)
  198.     lcval = ((lcval<<2) + lcval)<<1;
  199.       else
  200.     lcval <<= 4;
  201.       c1 = c;
  202.       if (isdigit(c))
  203.     c -= '0';
  204.       else if ('a'<=c && c<='f')
  205.     c -= 'a'-10;
  206.       else
  207.     c -= 'A'-10;
  208.       lcval += c;
  209.       c = c1;
  210.       continue;
  211.     } else if (c=='.') {
  212.       if (base!=10 || scale==INT)
  213.     break;
  214.       ndigit++;
  215.       continue;
  216.     } else if ((c=='e'||c=='E') && expseen==0) {
  217.       if (base!=10 || scale==INT || ndigit==0)
  218.     break;
  219.       expseen++;
  220.       *np++ = c;
  221.       c = scan_getc(iop);
  222.       nchars++;
  223.       if (c!='+'&&c!='-'&&('0'>c||c>'9'))
  224.     break;
  225.     } else
  226.       break;
  227.   }
  228.   if (negflg)
  229.     lcval = -lcval;
  230.   if (c != EOF) {
  231.     scan_ungetc(c, iop);
  232.     *eofptr = 0;
  233.   } else
  234.     *eofptr = 1;
  235.   nchars--;
  236.   if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) ) /* gene dykes*/
  237.     return(0);
  238.   *np++ = 0;
  239.   switch((scale<<4) | size) {
  240.  
  241.   case (FLOAT<<4) | SHORT:
  242.   case (FLOAT<<4) | REGULAR:
  243.     **(float **)ptr = atof(numbuf);
  244.     break;
  245.  
  246.   case (FLOAT<<4) | LONG:
  247.     **(double **)ptr = atof(numbuf);
  248.     break;
  249.  
  250.   case (FLOAT<<4) | LONGDOUBLE:
  251.     **(long double **)ptr = _atold(numbuf);
  252.     break;
  253.  
  254.   case (INT<<4) | SHORT:
  255.     **(short **)ptr = (short)lcval;
  256.     break;
  257.  
  258.   case (INT<<4) | REGULAR:
  259.     **(int **)ptr = (int)lcval;
  260.     break;
  261.  
  262.   case (INT<<4) | LONG:
  263.   case (INT<<4) | LONGDOUBLE:
  264.     **(long **)ptr = lcval;
  265.     break;
  266.   }
  267.   return(1);
  268. }
  269.  
  270. static int
  271. _instr(char *ptr, int type, int len, FILE *iop,
  272.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  273. {
  274.   register ch;
  275.   register char *optr;
  276.   int ignstp;
  277.  
  278.   *eofptr = 0;
  279.   optr = ptr;
  280.   if (type=='c' && len==30000)
  281.     len = 1;
  282.   ignstp = 0;
  283.   if (type=='s')
  284.     ignstp = SPC;
  285.   while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp)
  286.     ;
  287.   ignstp = SPC;
  288.   if (type=='c')
  289.     ignstp = 0;
  290.   else if (type=='[')
  291.     ignstp = STP;
  292.   while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
  293.     if (ptr)
  294.       *ptr++ = ch;
  295.     if (--len <= 0)
  296.       break;
  297.     ch = scan_getc(iop);
  298.     nchars++;
  299.   }
  300.   if (ch != EOF) {
  301.     if (len > 0)
  302.     {
  303.       scan_ungetc(ch, iop);
  304.       nchars--;
  305.     }
  306.     *eofptr = 0;
  307.   } else
  308.   {
  309.     nchars--;
  310.     *eofptr = 1;
  311.   }
  312.   if (ptr && ptr!=optr) {
  313.     if (type!='c')
  314.       *ptr++ = '\0';
  315.     return(1);
  316.   }
  317.   return(0);
  318. }
  319.  
  320. static const char *
  321. _getccl(const unsigned char *s)
  322. {
  323.   register c, t;
  324.  
  325.   t = 0;
  326.   if (*s == '^') {
  327.     t++;
  328.     s++;
  329.   }
  330.   for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
  331.     if (t)
  332.       _sctab[c] &= ~STP;
  333.     else
  334.       _sctab[c] |= STP;
  335.   if ((c = *s) == ']' || c == '-') { /* first char is special */
  336.     if (t)
  337.       _sctab[c] |= STP;
  338.     else
  339.       _sctab[c] &= ~STP;
  340.     s++;
  341.   }
  342.   while ((c = *s++) != ']') {
  343.     if (c==0)
  344.       return((const char *)--s);
  345.     else if (c == '-' && *s != ']' && s[-2] < *s) {
  346.       for (c = s[-2] + 1; c < *s; c++)
  347.     if (t)
  348.       _sctab[c] |= STP;
  349.     else
  350.       _sctab[c] &= ~STP;
  351.     } else if (t)
  352.       _sctab[c] |= STP;
  353.     else
  354.       _sctab[c] &= ~STP;
  355.   }
  356.   return((const char *)s);
  357. }
  358.