summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/initvars.c
blob: 1fb2a6d541a96b729130a8d55f1f9534f34bcc2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

/**** init_globals(fp, names, types, ...)
**
** public domain by Raymond Gardner     Sept. 1991
**
** fp is a FILE * to the (already fopen'ed) file containing
**      initialization data
**  names is a space-separated list of names of globals (as they
**      are to appear in the data file)
**  types is a list of datatype characters, corresponding to names
**      i  for a pointer to integer
**      s  for a pointer to string (already allocated char array)
**      p  for a pointer to pointer to char (space will be malloc'd)
**    (NOTE: no whitespace allowed in types !!)
**  followed by var arg list of pointers to variables to init
*/

#define LNSZ 256

int init_globals(FILE *fp, char *names, char *types, ...)
{
    char ln[LNSZ];
    char *p;
    va_list arglist;
    char *namep, *typep, name[40], *e;
    void *argp;
    int k;

    while ( fgets(ln, LNSZ, fp) ) {             /* read init file */
        while ( isspace(ln[0]) )            /* drop leading whitespace */
            memmove(ln, ln+1, strlen(ln));
        if ( ln[0] == 0 )                       /* skip if blank line */
            continue;
        p = strchr(ln, '=');                    /* find equal sign */
        if ( p == NULL )                        /* error if none */
            return -1;  /* or continue; */
        while ( p > ln && isspace(p[-1]) ) {    /* remove whitespace */
            memmove(p-1, p, strlen(p-1));       /*   before = sign */
            --p;
        }
        *p++ = 0;                               /* plug EOS over = sign */
        while ( isspace(p[0]) )             /* remove leading space on */
            memmove(p, p+1, strlen(p));         /*    init string */
        k = strlen(p) - 1;                      /* init string length */
        if ( k < 1 )
            return -1;

        if ( p[k] != '\n' )             /* if '\n' is missing, input */
            return -1;                  /*   exceeded buffer; error return */
        p[k] = 0;                       /* plug EOS over newline */

        va_start(arglist, types);       /* setup for arglist search */

        namep = names;                  /* init ptr to var names */
        typep = types;                  /* init ptr to var types */
        while ( *namep == ' ' )         /* skip blanks before namelist */
            ++namep;
        while ( *typep ) {          /* while any typelist items left...*/

            argp = (void *)va_arg(arglist, void *); /* get var arg */

            k = strcspn(namep, " ");        /* length of namelist entry */
            memmove(name, namep, k);        /* put into name hold area */
            name[k] = 0;                    /* terminate it */
            if ( strcmp(name, ln) != 0 ) { /* if it doesn't match... */
                namep += k;                 /* get next name */
                while ( *namep == ' ' )
                    ++namep;
                ++typep;                    /* get next type */
            } else {                        /* else name is found... */
                if ( *typep == 'i' ) {      /* if it's an int, init it */
                    *(int *)argp = atoi(p);
                } else if ( *typep == 's' || *typep == 'p' ) {
                    if ( *p == '"' ) {      /* is string in quotes? */
                        ++p;                /* skip leading quote, and */
                        e = strchr(p, '"'); /* look for trailing quote */
                        if ( e )            /* terminate string if found */
                            *e = 0;
                    }
                    if ( *typep == 'p' ) {      /* if it's a char *ptr */
                        e = malloc(strlen(p) + 1); /* get space */
                        if ( e == 0 ) {         /* error if no space */
                            return -1; /* call va_end(arglist); first? */
                        }
                        *(char **)argp = e;
                        strcpy(*(char **)argp, p);  /* copy in string */
                    } else                          /* must be char array */
                        strcpy(argp, p);            /* copy in string */
                } else {
                    return -1;                      /* bad type */
                }
                break;              /* break search; get next line */
            }
        }
        va_end(arglist);
    }
    return 0;
}
#ifdef TEST

int foo;
char bar[80];
int baz;
char *quux;

int main(int argc, char **argv)
{
    FILE *fp;
    int k;

    if ( argc < 2 ) {
        fprintf(stderr, "missing arg\n");
        exit(1);
    }

    fp = fopen(argv[1], "r");
    assert(fp);
    k = init_globals(fp, "foo bar baz quux", "isip",
        &foo, bar, &baz, &quux);
    printf("k: %d\n", k);
    printf("foo: %d\nbar: <%s>\nbaz: %d\nquux: <%s>\n",
        foo, bar, baz, quux);
    fclose(fp);

    return 0;
}
#endif
/* test data file:
foo=123
bar = "a test"
   baz     =  456
quux=    what is this
*/