aab27c2ddba912b1fb17c1d7d15a03f1e67625d2
[openafs.git] / src / mpp / mpp.c
1 /*
2  *      (C) Copyright 10/17/86 by Carnegie Mellon University
3  */
4 #include <stdio.h>
5 #include <unistd.h>
6
7 extern char *malloc();
8
9 #define maxinputdepth   16
10 #define maxlinesize     1024
11 #define macrohashsize   1023
12 #define macronamesize   32
13 #define maxnestdepth    128
14
15 #define inline  xxinline
16
17 struct nest {
18     int status;
19 };
20
21 struct file {
22     char *name;
23     FILE *stream;
24     int lineno;
25 };
26
27 struct macro {
28     struct macro *next;
29     enum macromode { rdwr, rdonly } mode;
30     char *name;
31     char *value;
32 };
33
34 static stripcomments = 0;
35 static specialchar = '%';
36 static struct nest nests[maxnestdepth];
37 static struct nest *nestp = &nests[0];
38 static struct nest *lastnestp = &nests[maxnestdepth - 1];
39
40 static struct file files[maxinputdepth];
41 static struct file *lastfilep = &files[maxinputdepth - 1];
42 static struct file *filep = &files[0];
43
44 static char inline[maxlinesize];
45 static char outline[maxlinesize];
46 static struct macro *macrohashtable[macrohashsize];
47
48 static int
49 error(char *a0, char *a1)
50 {
51     fprintf(stderr, a0, a1);
52     putc('\n', stderr);
53     exit(1);
54 }
55
56 static int
57 fileerror(char *a0, char *a1);
58 {
59     fprintf(stderr, "%s; line %d: ", filep->name, filep->lineno);
60     error(a0, a1);
61 }
62
63 static struct macro **
64 macrolookup(char *name)
65 {
66     register struct macro **mpp, *mp;
67     register char *cp;
68     register unsigned hv;
69
70     for (cp = name, hv = 0; *cp; hv += *cp++);
71     mpp = &macrohashtable[hv % macrohashsize];
72     while ((mp = *mpp) && strcmp(mp->name, name))
73         mpp = &mp->next;
74     return mpp;
75 }
76
77 static void
78 macroundefine(char *name)
79 {
80     register struct macro **mpp, *mp;
81
82     mpp = macrolookup(name);
83     if (mp = *mpp) {
84         *mpp = mp->next;
85         free(mp->value);
86         free(mp->name);
87         free(mp);
88     }
89 }
90
91 static void
92 macrodefine(char *name, char *value, enum macromode mode)
93 {
94     register struct macro **mpp, *mp;
95
96     mpp = macrolookup(name);
97     if (mp = *mpp) {
98         if (mp->mode == rdonly)
99             return;
100         free(mp->value);
101     } else {
102         if ((mp = (struct macro *)malloc(sizeof(struct macro))) == 0)
103             error("Out of memory");
104         mp->name = strdup(name);
105         mp->next = 0;
106         *mpp = mp;
107     }
108     mp->mode = mode;
109     mp->value = strdup(value);
110 }
111
112
113 static char *
114 macroexpand(register char *dst, register char *src)
115 {
116     char name[macronamesize];
117     register char *np;
118     register struct macro *mp;
119
120     while (*src) {
121         if (*src != '$') {
122             *dst++ = *src++;
123             continue;
124         }
125         src++;
126         if (*src == '$') {
127             *dst++ = '$';
128             src++;
129             continue;
130         }
131         np = name;
132         if (*src == '{' || *src == '(') {
133             src++;
134             while (*src) {
135                 if (*src == '}' || *src == ')') {
136                     src++;
137                     break;
138                 }
139                 if (np >= &name[macronamesize])
140                     src++;
141                 else
142                     *np++ = *src++;
143             }
144         } else {
145             *np++ = *src++;
146         }
147         *np = 0;
148         if (mp = *macrolookup(name))
149             dst = macroexpand(dst, mp->value);
150     }
151     *dst = 0;
152     return dst;
153 }
154
155
156
157 static int
158 readline(char *line)
159 {
160     while (filep >= &files[0]) {
161         filep->lineno++;
162         if (fgets(line, maxlinesize, filep->stream) != NULL)
163             return -1;
164         if (fclose(filep->stream) == EOF)
165             error("Error closing %s", filep->name);
166         free(filep->name);
167         if (filep == &files[0])
168             return 0;
169         filep--;
170     }
171     return 0;
172 }
173
174 static void
175 writeline(char *line)
176 {
177     fputs(line, stdout);
178 }
179
180
181 static int
182 directive(char *what)
183 {
184     char *arg[3], *cp;
185     int n;
186
187     if (*what++ != specialchar)
188         return nestp->status;
189     if (cp = strrchr(what, '\n'))
190         *cp = 0;
191     for (n = 0; n < 2; n++) {
192         while (*what == ' ' || *what == '\t')
193             what++;
194         arg[n] = what;
195         while (*what != ' ' && *what != '\t' && *what != 0)
196             what++;
197         if (*what)
198             *what++ = 0;
199     }
200     while (*what == ' ' || *what == '\t')
201         what++;
202     arg[2] = what;
203     if (strcmp(arg[0], "ifdef") == 0) {
204         if (nestp == lastnestp)
205             fileerror("If Depth overflow");
206         if (nestp->status == 2 || nestp->status == 1) {
207             nestp++;
208             nestp->status = 2;
209             return 1;
210         }
211         nestp++;
212         nestp->status = (*macrolookup(arg[1])) ? 0 : 1;
213         return 1;
214     }
215     if (strcmp(arg[0], "ifndef") == 0) {
216         if (nestp == lastnestp)
217             fileerror("If Depth overflow");
218         if (nestp->status == 2 || nestp->status == 1) {
219             nestp++;
220             nestp->status = 2;
221             return 1;
222         }
223         nestp++;
224         nestp->status = (*macrolookup(arg[1])) ? 1 : 0;
225         return 1;
226     }
227     if (strcmp(arg[0], "else") == 0) {
228         if (nestp->status == 2)
229             return 1;
230         if (nestp == &nests[0])
231             fileerror("If less else");
232         nestp->status = nestp->status ? 0 : 1;
233         return 1;
234     }
235     if (strcmp(arg[0], "endif") == 0) {
236         if (nestp == &nests[0])
237             fileerror("If less endif");
238         nestp--;
239         return 1;
240     }
241     if (nestp->status)
242         return 1;
243     if (strcmp(arg[0], "include") == 0) {
244         if (filep == lastfilep)
245             fileerror("Include file overflow");
246         filep++;
247         if ((filep->stream = fopen(arg[1], "r")) == NULL) {
248             filep--;
249             fileerror("Can't open %s", arg[1]);
250         }
251         filep->name = strdup(arg[1]);
252         filep->lineno = 0;
253         return 1;
254     }
255     if (strcmp(arg[0], "define") == 0) {
256         macrodefine(arg[1], arg[2], rdwr);
257         return 1;
258     }
259     if (strcmp(arg[0], "undef") == 0) {
260         macroundefine(arg[1]);
261         return 1;
262     }
263     fileerror("Unknown directive %s", arg[0]);
264 }
265
266 void 
267 expandfile(char *name)
268 {
269     if (strcmp(name, "-") == 0) {
270         filep->stream = stdin;
271         filep->name = strdup("(stdin)");
272     } else {
273         if ((filep->stream = fopen(name, "r")) == NULL) {
274             fileerror("Can't open %s", name);
275             exit(1);
276         }
277         filep->name = strdup(name);
278     }
279     filep->lineno = 0;
280     while (readline(inline)) {
281         if (stripcomments) {
282             char *cp;
283             for (cp = inline; *cp != 0 && *cp != '#'; cp++)
284                 continue;
285             *cp = 0;
286             if (cp == inline)
287                 continue;
288         }
289         (void)macroexpand(outline, inline);
290         if (directive(outline))
291             continue;
292         writeline(outline);
293     }
294 }
295
296 static int
297 usage()
298 {
299     fprintf(stderr, "Usage: mpp [-cC][-s][-Dname=value][-Uname][-][files]\n");
300     exit(1);
301 }
302
303 #include "AFS_component_version_number.c"
304
305 int
306 main(int argc, char **argv)
307 {
308     argv++, argc--;
309     if (argc == 0)
310         usage();
311     while (argc > 0) {
312         if (**argv == '-') {
313             if (strcmp(*argv, "-s") == 0) {
314                 stripcomments++;
315                 argv++, argc--;
316                 continue;
317             }
318             if (strncmp(*argv, "-c", sizeof("-c") - 1) == 0) {
319                 specialchar = argv[0][sizeof("-c")];
320                 argv++, argc--;
321                 continue;
322             }
323             if (strncmp(*argv, "-U", sizeof("-U") - 1) == 0) {
324                 macroundefine(&argv[0][sizeof("-U")]);
325                 argv++, argc--;
326                 continue;
327             }
328             if (strncmp(*argv, "-D", sizeof("-D") - 1) == 0) {
329                 char *cp, *cp2;
330
331                 cp = &argv[0][sizeof("-D") - 1];
332                 if (cp2 = strrchr(cp, '='))
333                     *cp2++ = 0;
334                 if (cp2 == 0)
335                     cp2 = "";
336                 macrodefine(cp, cp2, rdonly);
337                 argv++, argc--;
338                 continue;
339             }
340             if (strcmp(*argv, "-"))
341                 usage();
342         }
343         expandfile(*argv);
344         argv++, argc--;
345     }
346     exit(0);
347 }