Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / config / mc.c
1 /*
2  * (C) COPYRIGHT IBM CORPORATION 1987, 1988
3  * LICENSED MATERIALS - PROPERTY OF IBM
4  */
5
6 #define MAXLINELEN      1024
7 #define MAXTOKLEN       100
8 #include <sys/param.h>
9 #include <sys/types.h>
10 #include <sys/file.h>
11 #include <stdio.h>
12
13 #if  defined(__alpha)
14 extern void *malloc(int size);
15 #endif
16
17 #define TOK_DONTUSE 1 /* Don't copy if match and this flag is set. */
18 struct token {
19     struct token *next;
20     char *key;
21     int flags;
22 };
23
24 /* free token list returned by parseLine */
25 static FreeTokens(alist)
26     register struct token *alist; {
27     register struct token *nlist;
28     for(; alist; alist = nlist) {
29         nlist = alist->next;
30         free(alist->key);
31         free(alist);
32     }
33     return 0;
34 }
35
36 #define space(x)    ((x) == ' ' || (x) == '\t' || (x) == '<' || (x) == '>')
37 static ParseLine(aline, alist)
38     char *aline;
39     struct token **alist; {
40     char tbuffer[MAXTOKLEN+1];
41     register char *tptr;
42     int inToken;
43     struct token *first, *last;
44     register struct token *ttok;
45     register int tc;
46     int dontUse = 0;
47     
48     inToken = 0;        /* not copying token chars at start */
49     first = (struct token *) 0;
50     last = (struct token *) 0;
51     while (1) {
52         tc = *aline++;
53         if (tc == 0 || space(tc)) {    /* terminating null gets us in here, too */
54             if (inToken) {
55                 inToken = 0;    /* end of this token */
56                 *tptr++ = 0;
57                 ttok = (struct token *) malloc(sizeof(struct token));
58                 ttok->next = (struct token *) 0;
59                 if (dontUse) {
60                     ttok->key = (char *) malloc(strlen(tbuffer));
61                     strcpy(ttok->key, tbuffer+1);
62                     ttok->flags = TOK_DONTUSE;
63                     dontUse = 0;
64                 }
65                 else {
66                     ttok->key = (char *) malloc(strlen(tbuffer)+1);
67                     strcpy(ttok->key, tbuffer);
68                     ttok->flags = 0;
69                 }
70                 if (last) {
71                     last->next = ttok;
72                     last = ttok;
73                 }
74                 else last = ttok;
75                 if (!first) first = ttok;
76             }
77         }
78         else {
79             /* an alpha character */
80             if (!inToken) {
81                 if (tc == '-') {
82                     dontUse = 1;
83                 }
84                 tptr = tbuffer;
85                 inToken = 1;
86             }
87             if (tptr - tbuffer >= MAXTOKLEN) return -1;   /* token too long */
88             *tptr++ = tc;
89         }
90         if (tc == 0) {
91             /* last token flushed 'cause space(0) --> true */
92             if (last) last->next = (struct token *) 0;
93             *alist = first;
94             return 0;
95         }
96     }
97 }
98 /* read a line into a buffer, putting in null termination and stopping on appropriate
99     end of line char.  Returns 0 at eof, > 0 at normal line end, and < 0 on error */
100 static GetLine(afile, abuffer, amax)
101     FILE *afile;
102     int amax;
103     register char *abuffer; {
104     register int tc;
105     int first;
106
107     first = 1;
108     while (1) {
109         tc = getc(afile);
110         if (first && tc < 0) return 0;
111         first = 0;
112         if (tc <= 0 || tc == '\012') {
113             if (amax > 0) *abuffer++ = 0;
114             return (amax > 0? 1 : -1);
115         }
116         if (amax > 0) {
117             /* keep reading to end of line so next one isn't bogus */
118             *abuffer++ = tc;
119             amax--;
120         }
121     }
122 }
123 mc_copy(ain, aout, alist)
124     register FILE *ain;
125     register FILE *aout;
126     char *alist[]; {
127     char tbuffer[MAXLINELEN];
128     struct token *tokens;
129     register char **tp;
130     register struct token *tt;
131     register int code;
132     int copying;
133     int done;
134
135     copying = 1;        /* start off copying data */
136     while (1) {
137         /* copy lines, handling modes appropriately */
138         code = GetLine(ain, tbuffer, MAXLINELEN);
139         if (code <= 0) break;
140         /* otherwise process the line */
141         if (tbuffer[0] == '<') {
142             /* interpret the line as a set of options, any one of which will cause us
143                 to start copying the data again. */
144             code = ParseLine(tbuffer, &tokens);
145             if (code != 0) return -1;
146             copying = 0;
147             done = 0;
148             for(tp = alist; (!done) && (*tp != (char *)0) ; tp++) {
149                 for(tt = tokens; tt; tt=tt->next) {
150                     if (!strcmp(*tp, tt->key)) {
151                         /* Need to search all tokens in case a dont use
152                          * flag is set. But we can stop on the first
153                          * don't use.
154                          */
155                         if (tt->flags & TOK_DONTUSE) {
156                             copying = 0;
157                             done = 1;
158                             break;
159                         }
160                         else {
161                             copying = 1;
162                         }
163                     }
164                 }
165             }
166             FreeTokens(tokens);
167         }
168         else {
169             /* just copy the line */
170             if (copying) {
171                 fwrite(tbuffer, 1, strlen(tbuffer), aout);
172                 putc('\n', aout);
173             }
174         }
175     }
176     return 0;
177 }