home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / EMXLIB8F.ZIP / EMX / LIB / IO / INPUT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-02  |  11.4 KB  |  399 lines

  1. /* input.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
  2.  
  3. #include <sys/emx.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdarg.h>
  7. #include <string.h>
  8. #include <limits.h>
  9. #include <ctype.h>
  10.  
  11. #define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
  12. #define BEGIN do {
  13. #define END } while (0)
  14.  
  15. #define NEXT(x) \
  16.   BEGIN \
  17.     x = getc (stream); \
  18.     if (x == EOF) \
  19.       return (count == 0 ? EOF : count); \
  20.     ++chars; \
  21.   END
  22.  
  23. #define UNGETC(x) \
  24.   BEGIN \
  25.     ungetc (x, stream); \
  26.     --chars; \
  27.   END
  28.  
  29. int _input (FILE *stream, const char *format, char *arg_ptr)
  30. {
  31.   int count, chars, c, width, radix, d, i;
  32.   int *int_ptr;
  33.   short *short_ptr;
  34.   char *char_ptr;
  35.   unsigned char f;
  36.   char neg, assign, ok, size;
  37.   unsigned long n;
  38.   char map[256], end;
  39.   double dx, dd, *dbl_ptr;
  40.   float *flt_ptr;
  41.   int exp;
  42.   char eneg;
  43.  
  44.   count = 0; chars = 0; c = 0;
  45.   while ((f = *format) != 0)
  46.     {
  47.       if (WHITE (f))
  48.         {
  49.           do
  50.             {
  51.               ++format; f = *format;
  52.             } while (WHITE (f));
  53.           do
  54.             {
  55.               c = getc (stream);
  56.               if (c == EOF)
  57.                 {
  58.                   if (f == 0 || count != 0)
  59.                     return (count);
  60.                   else
  61.                     return (EOF);
  62.                 }
  63.               else
  64.                 ++chars;
  65.             } while (WHITE (c));
  66.           UNGETC (c);
  67.         }
  68.       else if (f != '%')
  69.         {
  70.           NEXT (c);
  71.           if (c != f)
  72.             return (count);
  73.           ++format;
  74.         }
  75.       else
  76.         {
  77.           assign = TRUE; width = INT_MAX;
  78.           char_ptr = NULL;
  79.           ++format;
  80.           if (*format == '*')
  81.             {
  82.               assign = FALSE;
  83.               ++format;
  84.             }
  85.           if (isdigit (*format))
  86.             {
  87.               width = 0;
  88.               while (isdigit (*format))
  89.                 width = width * 10 + (*format++ - '0');
  90.               if (width == 0) width = INT_MAX;
  91.             }
  92.           size = 0;
  93.           if (*format == 'h' || *format == 'l')
  94.             size = *format++;
  95.           f = *format;
  96.           switch (f)
  97.             {
  98.             case 'c':
  99.               if (width == INT_MAX)
  100.                 width = 1;
  101.               if (assign)
  102.                 char_ptr = va_arg (arg_ptr, char *);
  103.               while (width > 0)
  104.                 {
  105.                   --width;
  106.                   NEXT (c);
  107.                   if (assign)
  108.                     {
  109.                       *char_ptr++ = (char)c;
  110.                       ++count;
  111.                     }
  112.                 }
  113.               break;
  114.             case '[':
  115.               memset (map, 0, 256);
  116.               end = 0;
  117.               ++format;
  118.               if (*format == '^')
  119.                 {
  120.                   ++format; end = 1;
  121.                 }
  122.               i = 0;
  123.               for (;;)
  124.                 {
  125.                   f = (unsigned char)*format;
  126.                   switch (f)
  127.                     {
  128.                     case 0:
  129.                       --format;       /* avoid skipping past 0 */
  130.                       NEXT (c);
  131.                       goto string;
  132.                     case ']':
  133.                       if (i > 0)
  134.                         {
  135.                           NEXT (c);
  136.                           goto string;
  137.                         }
  138.                       /* no break */
  139.                     default:
  140.                       if (format[1] == '-' && format[2] != 0 &&
  141.                           f < (unsigned char)format[2])
  142.                         {
  143.                           memset (map+f, 1, (unsigned char)format[2]-f);
  144.                           format += 2;
  145.                         }
  146.                       else
  147.                         map[f] = 1;
  148.                       break;
  149.                     }
  150.                   ++format; ++i;
  151.                 }
  152.             case 's':
  153.               memset (map, 0, 256);
  154.               map[' '] = 1;
  155.               map['\n'] = 1;
  156.               map['\t'] = 1;
  157.               end = 1;
  158.               do
  159.                 {
  160.                   NEXT (c);
  161.                 } while (WHITE (c));
  162. string:
  163.               if (assign)
  164.                 char_ptr = va_arg (arg_ptr, char *);
  165.               while (width > 0 && map[(unsigned char)c] != end)
  166.                 {
  167.                   --width;
  168.                   if (assign)
  169.                     *char_ptr++ = (char)c;
  170.                   c = getc (stream);
  171.                   if (c == EOF)
  172.                     break;
  173.                   else
  174.                     ++chars;
  175.                 }
  176.               if (assign)
  177.                 {
  178.                   *char_ptr = 0;
  179.                   ++count;
  180.                 }
  181.               if (c == EOF)
  182.                 return (count);
  183.               else
  184.                 UNGETC (c);
  185.               break;
  186.             case 'f':
  187.             case 'e':
  188.             case 'E':
  189.             case 'g':
  190.             case 'G':
  191.               neg = ok = FALSE; dx = 0.0;
  192.               do
  193.                 {
  194.                   NEXT (c);
  195.                 } while (WHITE (c));
  196.               if (c == '+')
  197.                 {
  198.                   NEXT (c); --width;
  199.                 }
  200.               else if (c == '-')
  201.                 {
  202.                   neg = TRUE; NEXT (c); --width;
  203.                 }
  204.               while (width > 0 && isdigit (c))
  205.                 {
  206.                   --width;
  207.                   dx = dx * 10.0 + (double)(c - '0');
  208.                   ok = TRUE;
  209.                   c = getc (stream);
  210.                   if (c == EOF)
  211.                     break;
  212.                   else
  213.                     ++chars;
  214.                 }
  215.               if (width > 0 && c == '.')
  216.                 {
  217.                   --width;
  218.                   dd = 10.0; NEXT (c);
  219.                   while (width > 0 && isdigit (c))
  220.                     {
  221.                       --width;
  222.                       dx += (double)(c - '0') / dd;
  223.                       dd *= 10.0;
  224.                       ok = TRUE;
  225.                       c = getc (stream);
  226.                       if (c == EOF)
  227.                         break;
  228.                       else
  229.                         ++chars;
  230.                     }
  231.                 }
  232.               if (!ok)
  233.                 return (count);
  234.               if (width > 0 && (c == 'e' || c == 'E'))
  235.                 {
  236.                   eneg = FALSE; exp = 0; NEXT (c); --width;
  237.                   if (width > 0 && c == '+')
  238.                     {
  239.                       NEXT (c); --width;
  240.                     }
  241.                   else if (width > 0 && c == '-')
  242.                     {
  243.                       eneg = TRUE; NEXT (c); --width;
  244.                     }
  245.                   if (!(width > 0 && isdigit (c)))
  246.                     {
  247.                       UNGETC (c);
  248.                       return (count);
  249.                     }
  250.                   while (width > 0 && isdigit (c))
  251.                     {
  252.                       --width;
  253.                       exp = exp * 10 + (c - '0');
  254.                       c = getc (stream);
  255.                       if (c == EOF)
  256.                         break;
  257.                       else
  258.                         ++chars;
  259.                     }
  260.                   if (eneg) exp = -exp;
  261.                   while (exp > 0)
  262.                     {
  263.                       dx *= 10.0;
  264.                       --exp;
  265.                     }
  266.                   while (exp < 0)
  267.                     {
  268.                       dx /= 10.0;
  269.                       ++exp;
  270.                     }
  271.                 }
  272.               if (assign)
  273.                 {
  274.                   if (neg) dx = -dx;
  275.                   if (size == 'l')
  276.                     {
  277.                       dbl_ptr = va_arg (arg_ptr, double *);
  278.                       *dbl_ptr = dx;
  279.                     }
  280.                   else
  281.                     {
  282.                       flt_ptr = va_arg (arg_ptr, float *);
  283.                       *flt_ptr = (float)dx;
  284.                     }
  285.                   ++count;
  286.                 }
  287.               if (c == EOF)
  288.                 return (count);
  289.               else
  290.                 UNGETC (c);
  291.               break;
  292.             case 'i':
  293.               neg = FALSE; radix = 10;
  294.               do
  295.                 {
  296.                   NEXT (c);
  297.                 } while (WHITE (c));
  298.               if (!(width > 0 && c == '0'))
  299.                 goto scan_complete_number;
  300.               NEXT (c); --width;
  301.               if (width > 0 && (c == 'x' || c == 'X'))
  302.                 {
  303.                   NEXT (c); radix = 16; --width;
  304.                 }
  305.               else if (width > 0 && (c >= '0' && c <= '7'))
  306.                 radix = 8;
  307.               goto scan_unsigned_number;
  308.             case 'd':
  309.             case 'u':
  310.             case 'o':
  311.             case 'x':
  312.             case 'X':
  313.               do
  314.                 {
  315.                   NEXT (c);
  316.                 } while (WHITE (c));
  317.               switch (f)
  318.                 {
  319.                 case 'o':           radix = 8; break;
  320.                 case 'x': case 'X': radix = 16; break;
  321.                 default:            radix = 10; break;
  322.                 }
  323. scan_complete_number:
  324.               neg = FALSE;
  325.               if (width > 0 && c == '+')
  326.                 {
  327.                   NEXT (c); --width;
  328.                 }
  329.               else if (width > 0 && c == '-' && radix == 10)
  330.                 {
  331.                   neg = TRUE; NEXT (c); --width;
  332.                 }
  333. scan_unsigned_number:
  334.               n = 0; ok = FALSE;
  335.               while (width > 0)
  336.                 {
  337.                   --width;
  338.                   if (isdigit (c))
  339.                     d = c - '0';
  340.                   else if (isupper (c))
  341.                     d = c - 'A' + 10;
  342.                   else if (islower (c))
  343.                     d = c - 'a' + 10;
  344.                   else
  345.                     break;
  346.                   if (d < 0 || d >= radix)
  347.                     break;
  348.                   ok = TRUE;
  349.                   n = n * radix + d;
  350.                   c = getc (stream);
  351.                   if (c == EOF)
  352.                     break;
  353.                   else
  354.                     ++chars;
  355.                 }
  356.               if (!ok)
  357.                 return (count);
  358.               if (assign)
  359.                 {
  360.                   if (neg) n = -n;
  361.                   if (size == 'h')
  362.                     {
  363.                       short_ptr = va_arg (arg_ptr, short *);
  364.                       *short_ptr = (short)n;
  365.                     }
  366.                   else
  367.                     {
  368.                       int_ptr = va_arg (arg_ptr, int *);
  369.                       *int_ptr = (int)n;
  370.                     }
  371.                   ++count;
  372.                 }
  373.               if (c == EOF)
  374.                 return (count);
  375.               else
  376.                 UNGETC (c);
  377.               break;
  378.             case 'n':
  379.               if (assign)
  380.                 {
  381.                   int_ptr = va_arg (arg_ptr, int *);
  382.                   *int_ptr = chars;
  383.                   ++count;
  384.                 }
  385.               break;
  386.             default:
  387.               if (f == 0)                 /* % at end of string */
  388.                 return (count);
  389.               NEXT (c);
  390.               if (c != f)
  391.                 return (count);
  392.               break;
  393.             }
  394.           ++format;
  395.         }
  396.     }
  397.   return (count);
  398. }
  399.