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