Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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