Re: copyright notices for vms.c and vmsish.h
[p5sagit/p5-mst-13.2.git] / vms / munchconfig.c
CommitLineData
97abc6ad 1/* munchconfig.c
2
3 A very, very (very!) simple program to process a config_h.sh file on
4 non-unix systems.
5
6 usage:
b8df70f4 7 munchconfig config.sh config_h.sh [-f file] [foo=bar [baz=xyzzy [...]]] >config.h
97abc6ad 8
b8df70f4 9 which is to say, it takes as its first parameter a config.sh (or
10 equivalent), as its second a config_h.sh (or equivalent), an optional file
11 containing tag=value pairs (one on each line), and an optional list of
12 tag=value pairs on the command line.
97abc6ad 13
14 It spits the processed config.h out to STDOUT.
15
16 */
17
18#include <stdio.h>
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22#include <ctype.h>
b8df70f4 23#include <unistd.h>
97abc6ad 24
25/* The failure code to exit with */
26#ifndef EXIT_FAILURE
27#ifdef VMS
28#define EXIT_FAILURE 0
29#else
30#define EXIT_FAILURE -1
31#endif
32#endif
33
34/* The biggest line we can read in from a file */
e43aec62 35#define LINEBUFFERSIZE 1024
97abc6ad 36#define NUMTILDESUBS 30
37#define NUMCONFIGSUBS 1000
38#define TOKENBUFFERSIZE 80
39
40typedef struct {
41 char Tag[TOKENBUFFERSIZE];
42 char Value[512];
43} Translate;
44
45void tilde_sub(char [], Translate [], int);
46
47int
48main(int argc, char *argv[])
49{
b8df70f4 50 int c, i;
51 char *ifile = NULL;
52 char WorkString[LINEBUFFERSIZE];
53 FILE *ConfigSH, *Config_H, *Extra_Subs;
97abc6ad 54 char LineBuffer[LINEBUFFERSIZE], *TempValue, *StartTilde, *EndTilde;
cc391245 55 char SecondaryLineBuffer[LINEBUFFERSIZE], OutBuf[LINEBUFFERSIZE];
97abc6ad 56 char TokenBuffer[TOKENBUFFERSIZE];
57 int LineBufferLength, TempLength, DummyVariable, LineBufferLoop;
cc391245 58 int TokenBufferLoop, ConfigSubLoop, GotIt, OutBufPos;
97abc6ad 59 Translate TildeSub[NUMTILDESUBS]; /* Holds the tilde (~FOO~) */
60 /* substitutions */
61 Translate ConfigSub[NUMCONFIGSUBS]; /* Holds the substitutions from */
62 /* config.sh */
63 int TildeSubCount = 0, ConfigSubCount = 0; /* # of tilde substitutions */
64 /* and config substitutions, */
65 /* respectively */
66 if (argc < 3) {
b8df70f4 67 printf("Usage: munchconfig config.sh config_h.sh [-f file] [foo=bar [baz=xyzzy [...]]]\n");
97abc6ad 68 exit(EXIT_FAILURE);
69 }
70
b8df70f4 71 optind = 3; /* skip config.sh and config_h.sh */
72 while ((c = getopt(argc, argv, "f:")) != -1) {
73 switch (c) {
74 case 'f':
75 ifile = optarg;
76 break;
77 case ':':
78 fprintf(stderr, "Option -%c requires an operand\n", optopt);
79 break;
80 case '?':
81 fprintf(stderr,"Unrecognised option: -%c\n", optopt);
82 }
83 }
84
97abc6ad 85 /* First, open the input files */
86 if (NULL == (ConfigSH = fopen(argv[1], "r"))) {
87 printf("Error %i trying to open config.sh file %s\n", errno, argv[1]);
88 exit(EXIT_FAILURE);
89 }
90
91 if (NULL == (Config_H = fopen(argv[2], "r"))) {
92 printf("Error %i trying to open config_h.sh file %s\n", errno, argv[2]);
93 exit(EXIT_FAILURE);
94 }
95
b8df70f4 96 if (ifile != NULL && NULL == (Extra_Subs = fopen(ifile, "r"))) {
97 printf("Error %i trying to open extra substitutions file %s\n", errno, ifile);
98 exit(EXIT_FAILURE);
99 }
100
97abc6ad 101 /* Any tag/value pairs on the command line? */
b8df70f4 102 if (argc > optind) {
103 for (i=optind; i < argc && argv[i]; i++) {
97abc6ad 104 /* Local copy */
105 strcpy(WorkString, argv[i]);
106 /* Stick a NULL over the = */
107 TempValue = strchr(WorkString, '=');
108 *TempValue++ = '\0';
109
110 /* Copy the tag and value into the holding array */
111 strcpy(TildeSub[TildeSubCount].Tag, WorkString);
112 strcpy(TildeSub[TildeSubCount].Value, TempValue);
113 TildeSubCount++;
114 }
115 }
116
b8df70f4 117 /* Now read in the tag/value pairs from the extra substitutions file, if any */
118 while(ifile && fgets(LineBuffer, LINEBUFFERSIZE - 1, Extra_Subs)) {
119 /* Force a trailing null, just in case */
120 LineBuffer[LINEBUFFERSIZE - 1] = '\0';
121 LineBufferLength = strlen(LineBuffer);
122
123 /* Chop trailing control characters */
124 while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
125 LineBuffer[LineBufferLength - 1] = '\0';
126 LineBufferLength--;
127 }
128
129 /* If it's empty, then try again */
130 if (!*LineBuffer)
131 continue;
132
133 /* Local copy */
134 strcpy(WorkString, LineBuffer);
135 /* Stick a NULL over the = */
136 TempValue = strchr(WorkString, '=');
137 *TempValue++ = '\0';
138
139 /* Copy the tag and value into the holding array */
140 strcpy(TildeSub[TildeSubCount].Tag, WorkString);
141 strcpy(TildeSub[TildeSubCount].Value, TempValue);
142 TildeSubCount++;
143 }
144
145
97abc6ad 146 /* Now read in the config.sh file. */
147 while(fgets(LineBuffer, LINEBUFFERSIZE - 1, ConfigSH)) {
148 /* Force a trailing null, just in case */
149 LineBuffer[LINEBUFFERSIZE - 1] = '\0';
150
151 LineBufferLength = strlen(LineBuffer);
152
153 /* Chop trailing control characters */
154 while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
155 LineBuffer[LineBufferLength - 1] = '\0';
156 LineBufferLength--;
157 }
158
159 /* If it's empty, then try again */
160 if (!*LineBuffer)
161 continue;
162
163 /* If the line begins with a '#' or ' ', skip */
164 if ((LineBuffer[0] == ' ') || (LineBuffer[0] == '#'))
165 continue;
166
167 /* We've got something. Guess we need to actually handle it */
168 /* Do the tilde substitution */
169 tilde_sub(LineBuffer, TildeSub, TildeSubCount);
170
171 /* Stick a NULL over the = */
172 TempValue = strchr(LineBuffer, '=');
173 *TempValue++ = '\0';
174 /* And another over the leading ', which better be there */
175 *TempValue++ = '\0';
176
b6e4eeb2 177 /* Check to see if there's a trailing ' or ". If not, add a newline to
178 the buffer and grab another line. */
97abc6ad 179 TempLength = strlen(TempValue);
b6e4eeb2 180 while ((TempValue[TempLength-1] != '\'') &&
181 (TempValue[TempLength-1] != '"')) {
97abc6ad 182 fgets(SecondaryLineBuffer, LINEBUFFERSIZE - 1, ConfigSH);
183 /* Force a trailing null, just in case */
184 SecondaryLineBuffer[LINEBUFFERSIZE - 1] = '\0';
185 /* Go substitute */
186 tilde_sub(SecondaryLineBuffer, TildeSub, TildeSubCount);
187 /* Tack a nweline on the end of our primary buffer */
188 strcat(TempValue, "\n");
189 /* Concat the new line we just read */
190 strcat(TempValue, SecondaryLineBuffer);
191
192 /* Refigure the length */
193 TempLength = strlen(TempValue);
194
195 /* Chop trailing control characters */
196 while((TempLength > 0) && (TempValue[TempLength-1] < ' ')) {
197 TempValue[TempLength - 1] = '\0';
198 TempLength--;
199 }
200 }
201
202 /* And finally one over the trailing ' */
203 TempValue[TempLength-1] = '\0';
204
205 /* Is there even anything left? */
206 if(*TempValue) {
207 /* Copy the tag over */
208 strcpy(ConfigSub[ConfigSubCount].Tag, LineBuffer);
209 /* Copy the value over */
210 strcpy(ConfigSub[ConfigSubCount].Value, TempValue);
211
212 /* Up the count */
213 ConfigSubCount++;
214
215 }
216 }
217
218 /* Okay, we've read in all the substititions from our config.sh */
219 /* equivalent. Read in the config_h.sh equiv and start the substitution */
220
221 /* First, eat all the lines until we get to one with !GROK!THIS! in it */
222 while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
223 "!GROK!THIS!")) {
224
225 /* Dummy statement to shut up any compiler that'll whine about an empty */
226 /* loop */
227 DummyVariable++;
228 }
229
230 /* Right, we've read all the lines through the first one with !GROK!THIS! */
231 /* in it. That gets us through the beginning stuff. Now start in earnest */
232 /* with our translations, which run until we get to another !GROK!THIS! */
233 while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
234 "!GROK!THIS!")) {
235 /* Force a trailing null, just in case */
236 LineBuffer[LINEBUFFERSIZE - 1] = '\0';
237
238 /* Tilde Substitute */
239 tilde_sub(LineBuffer, TildeSub, TildeSubCount);
240
241 LineBufferLength = strlen(LineBuffer);
242
243 /* Chop trailing control characters */
244 while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
245 LineBuffer[LineBufferLength - 1] = '\0';
246 LineBufferLength--;
247 }
248
cc391245 249 OutBufPos = 0;
97abc6ad 250 /* Right. Go looking for $s. */
251 for(LineBufferLoop = 0; LineBufferLoop < LineBufferLength;
252 LineBufferLoop++) {
253 /* Did we find one? */
254 if ('$' != LineBuffer[LineBufferLoop]) {
255 /* Nope, spit out the value */
cc391245 256 OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
97abc6ad 257 } else {
258 /* Yes, we did. Is it escaped? */
259 if ((LineBufferLoop > 0) && ('\\' == LineBuffer[LineBufferLoop -
260 1])) {
261 /* Yup. Spit it out */
cc391245 262 OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
97abc6ad 263 } else {
264 /* Nope. Go grab us a token */
265 TokenBufferLoop = 0;
266 /* Advance to the next character in the input stream */
267 LineBufferLoop++;
268 while((LineBufferLoop < LineBufferLength) &&
269 ((isalnum(LineBuffer[LineBufferLoop]) || ('_' ==
270 LineBuffer[LineBufferLoop])))) {
271 TokenBuffer[TokenBufferLoop] = LineBuffer[LineBufferLoop];
272 LineBufferLoop++;
273 TokenBufferLoop++;
274 }
275
276 /* Trailing null on the token buffer */
277 TokenBuffer[TokenBufferLoop] = '\0';
278
279 /* Back the line buffer pointer up one */
280 LineBufferLoop--;
281
282 /* Right, we're done grabbing a token. Check to make sure we got */
283 /* something */
284 if (TokenBufferLoop) {
285 /* Well, we do. Run through all the tokens we've got in the */
286 /* ConfigSub array and see if any match */
287 GotIt = 0;
288 for(ConfigSubLoop = 0; ConfigSubLoop < ConfigSubCount;
289 ConfigSubLoop++) {
290 if (!strcmp(TokenBuffer, ConfigSub[ConfigSubLoop].Tag)) {
cc391245 291 char *cp = ConfigSub[ConfigSubLoop].Value;
292 GotIt = 1;
293 while (*cp) OutBuf[OutBufPos++] = *(cp++);
97abc6ad 294 break;
295 }
296 }
297
298 /* Did we find something? If not, spit out what was in our */
299 /* buffer */
300 if (!GotIt) {
cc391245 301 char *cp = TokenBuffer;
302 OutBuf[OutBufPos++] = '$';
303 while (*cp) OutBuf[OutBufPos++] = *(cp++);
97abc6ad 304 }
305
306 } else {
307 /* Just a bare $. Spit it out */
cc391245 308 OutBuf[OutBufPos++] = '$';
97abc6ad 309 }
310 }
311 }
312 }
313
cc391245 314 /* If we've created an #undef line, make sure we don't output anthing
315 * after the "#undef FOO" besides comments. We could do this as we
316 * go by recognizing the #undef as it goes by, and thus avoid another
317 * use of a fixed-length buffer, but this is simpler.
318 */
319 if (!strncmp(OutBuf,"#undef",6)) {
320 char *cp = OutBuf;
321 int i, incomment = 0;
322 LineBufferLoop = 0;
323 OutBuf[OutBufPos] = '\0';
324 for (i = 0; i <= 1; i++) {
325 while (!isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
326 while ( isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
327 }
328 while (*cp) {
329 while (isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
330 if (!incomment && *cp == '/' && *(cp+1) == '*') incomment = 1;
331 while (*cp && !isspace(*cp)) {
332 if (incomment) LineBuffer[LineBufferLoop++] = *cp;
333 cp++;
334 }
335 if (incomment && *cp == '*' && *(cp+1) == '/') incomment = 0;
336 }
337 LineBuffer[LineBufferLoop] = '\0';
338 puts(LineBuffer);
339 }
340 else {
341 OutBuf[OutBufPos] = '\0';
342 puts(OutBuf);
343 }
97abc6ad 344 }
345
346 /* Close the files */
347 fclose(ConfigSH);
348 fclose(Config_H);
b8df70f4 349 if (ifile) fclose(Extra_Subs);
97abc6ad 350}
351
352void
353tilde_sub(char LineBuffer[], Translate TildeSub[], int TildeSubCount)
354{
355 char TempBuffer[LINEBUFFERSIZE], TempTilde[TOKENBUFFERSIZE];
356 int TildeLoop, InTilde, CopiedBufferLength, TildeBufferLength, k, GotIt;
357 int TempLength;
358 InTilde = 0;
359 CopiedBufferLength = 0;
360 TildeBufferLength = 0;
361 TempLength = strlen(LineBuffer);
362
363 /* Grovel over our input looking for ~foo~ constructs */
364 for(TildeLoop = 0; TildeLoop < TempLength; TildeLoop++) {
365 /* Are we in a tilde? */
366 if (InTilde) {
367 /* Yup. Is the current character a tilde? */
368 if (LineBuffer[TildeLoop] == '~') {
369 /* Yup. That means we're ready to do a substitution */
370 InTilde = 0;
371 GotIt = 0;
372 /* Trailing null */
373 TempTilde[TildeBufferLength] = '\0';
374 for( k=0; k < TildeSubCount; k++) {
375 if (!strcmp(TildeSub[k].Tag, TempTilde)) {
376 GotIt = 1;
377 /* Tack on the trailing null to the main buffer */
378 TempBuffer[CopiedBufferLength] = '\0';
379 /* Copy the tilde substitution over */
380 strcat(TempBuffer, TildeSub[k].Value);
381 CopiedBufferLength = strlen(TempBuffer);
382 }
383 }
384
385 /* Did we find anything? */
386 if (GotIt == 0) {
387 /* Guess not. Copy the whole thing out verbatim */
388 TempBuffer[CopiedBufferLength] = '\0';
389 TempBuffer[CopiedBufferLength++] = '~';
390 TempBuffer[CopiedBufferLength] = '\0';
391 strcat(TempBuffer, TempTilde);
392 strcat(TempBuffer, "~");
393 CopiedBufferLength = strlen(TempBuffer);
394 }
395
396 } else {
397 /* 'Kay, not a tilde. Is it a word character? */
154545c7 398 if (isalnum(LineBuffer[TildeLoop]) ||
97abc6ad 399 (LineBuffer[TildeLoop] == '-')) {
400 TempTilde[TildeBufferLength++] = LineBuffer[TildeLoop];
401 } else {
402 /* No, it's not a tilde character. For shame! We've got a */
403 /* bogus token. Copy a ~ into the output buffer, then append */
404 /* whatever we've got in our token buffer */
405 TempBuffer[CopiedBufferLength++] = '~';
406 TempBuffer[CopiedBufferLength] = '\0';
407 TempTilde[TildeBufferLength] = '\0';
408 strcat(TempBuffer, TempTilde);
409 CopiedBufferLength += TildeBufferLength;
410 InTilde = 0;
411 }
412 }
413 } else {
414 /* We're not in a tilde. Do we want to be? */
415 if (LineBuffer[TildeLoop] == '~') {
416 /* Guess so */
417 InTilde = 1;
418 TildeBufferLength = 0;
419 } else {
420 /* Nope. Copy the character to the output buffer */
421 TempBuffer[CopiedBufferLength++] = LineBuffer[TildeLoop];
422 }
423 }
424 }
425
426 /* Out of the loop. First, double-check to see if there was anything */
427 /* pending. */
428 if (InTilde) {
429 /* bogus token. Copy a ~ into the output buffer, then append */
430 /* whatever we've got in our token buffer */
431 TempBuffer[CopiedBufferLength++] = '~';
432 TempBuffer[CopiedBufferLength] = '\0';
433 TempTilde[TildeBufferLength] = '\0';
434 strcat(TempBuffer, TempTilde);
435 CopiedBufferLength += TildeBufferLength;
436 } else {
437 /* Nope, nothing pensing. Tack on a \0 */
438 TempBuffer[CopiedBufferLength] = '\0';
439 }
440
441 /* Okay, we're done. Copy the temp buffer back into the line buffer */
442 strcpy(LineBuffer, TempBuffer);
443
444}
445