home *** CD-ROM | disk | FTP | other *** search
- /* scanf.c (emx+gcc) */
-
- /* Note: This program is not portable and uses dirty tricks. */
- /* It's a test program, not a sample program. */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #define FALSE 0
- #define TRUE 1
-
- #define TYPE_STRING 0
- #define TYPE_U16 1
- #define TYPE_S16 2
- #define TYPE_U32 3
- #define TYPE_S32 4
- #define TYPE_FLOAT 5
- #define TYPE_DOUBLE 6
-
- struct data
- {
- char type;
- size_t len;
- };
-
- static struct data *data;
- static void **list;
- static int allocated, used;
-
-
- static void add (size_t n, char type)
- {
- void *tmp;
-
- tmp = malloc (n);
- if (tmp == NULL)
- {
- fputs ("Out of memory\n", stderr);
- exit (1);
- }
- if (used >= allocated)
- {
- allocated += 1;
- list = realloc (list, allocated * sizeof (list[0]));
- data = realloc (data, allocated * sizeof (data[0]));
- if (list == NULL || data == NULL)
- {
- fputs ("Out of memory\n", stderr);
- exit (1);
- }
- }
- list[used] = tmp;
- data[used].type = type;
- data[used].len = n;
- ++used;
- }
-
-
- static void parse (const char *fmt)
- {
- int assign, first;
- char size;
-
- list = NULL; data = NULL; allocated = 0; used = 0;
- while (*fmt != 0)
- {
- if (*fmt == '%')
- {
- ++fmt;
- assign = TRUE; size = 0;
- if (*fmt == '*')
- {
- assign = FALSE; ++fmt;
- }
- while (isdigit (*fmt))
- ++fmt;
- if (*fmt == 'h' || *fmt == 'l')
- size = *fmt++;
- if (*fmt == 0)
- break;
- switch (*fmt)
- {
- case '[':
- first = TRUE;
- ++fmt;
- if (*fmt == '^')
- ++fmt;
- while (*fmt != 0)
- {
- if (*fmt == ']' && !first)
- break;
- if (fmt[1] == '-' && fmt[2] != 0 &&
- (unsigned char)fmt[0] < (unsigned char)fmt[2])
- fmt += 3;
- else
- ++fmt;
- first = FALSE;
- }
- if (*fmt == 0)
- --fmt;
- if (assign)
- add (1024, TYPE_STRING);
- break;
- case 'c':
- case 's':
- if (assign)
- add (1024, TYPE_STRING);
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- if (assign)
- {
- if (size == 'l')
- add (sizeof (double), TYPE_DOUBLE);
- else
- add (sizeof (float), TYPE_FLOAT);
- }
- break;
- case 'i':
- case 'd':
- if (assign)
- {
- if (size == 'h')
- add (sizeof (short), TYPE_S16);
- else
- add (sizeof (int), TYPE_S32);
- }
- break;
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- if (assign)
- {
- if (size == 'h')
- add (sizeof (short), TYPE_U16);
- else
- add (sizeof (int), TYPE_U32);
- }
- break;
- }
- }
- ++fmt;
- }
- }
-
-
- int main (void)
- {
- int i, n;
- char fmt[128], *p;
-
- printf ("Format: "); fflush (stdout);
- if (fgets (fmt, sizeof (fmt), stdin) == NULL)
- return (0);
- p = strchr (fmt, '\n');
- if (p != NULL) *p = 0;
- parse (fmt);
- for (;;)
- {
- for (i = 0; i < used; ++i)
- memset (list[i], 0, data[i].len);
- printf ("Input: "); fflush (stdout);
- n = vscanf (fmt, list);
- printf ("n=%d", n);
- for (i = 0; i < used; ++i)
- {
- printf (" %d:", i+1);
- switch (data[i].type)
- {
- case TYPE_STRING:
- printf ("%s", (char *)list[i]);
- break;
- case TYPE_U16:
- printf ("%hu", *(unsigned short *)list[i]);
- break;
- case TYPE_S16:
- printf ("%hd", *(short *)list[i]);
- break;
- case TYPE_U32:
- printf ("%lu", *(unsigned long *)list[i]);
- break;
- case TYPE_S32:
- printf ("%ld", *(long *)list[i]);
- break;
- case TYPE_FLOAT:
- printf ("%g", *(float *)list[i]);
- break;
- case TYPE_DOUBLE:
- printf ("%g", *(double *)list[i]);
- break;
- }
- }
- putchar ('\n');
- if (feof (stdin))
- break;
- }
- return (0);
- }
-