3 A very, very (very!) simple program to process a config_h.sh file on
7 munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]] >config.h
9 which is to say, it takes as its firt parameter a config.sh (or
10 equivalent), as its second a config_h.sh (or equvalent), and a list of
11 optional tag=value pairs.
13 It spits the processed config.h out to STDOUT.
23 /* The failure code to exit with */
26 #define EXIT_FAILURE 0
28 #define EXIT_FAILURE -1
32 /* The biggest line we can read in from a file */
33 #define LINEBUFFERSIZE 400
34 #define NUMTILDESUBS 30
35 #define NUMCONFIGSUBS 1000
36 #define TOKENBUFFERSIZE 80
39 char Tag[TOKENBUFFERSIZE];
43 void tilde_sub(char [], Translate [], int);
46 main(int argc, char *argv[])
48 FILE *ConfigSH, *Config_H;
49 char LineBuffer[LINEBUFFERSIZE], *TempValue, *StartTilde, *EndTilde;
50 char SecondaryLineBuffer[LINEBUFFERSIZE], OutBuf[LINEBUFFERSIZE];
51 char TokenBuffer[TOKENBUFFERSIZE];
52 int LineBufferLength, TempLength, DummyVariable, LineBufferLoop;
53 int TokenBufferLoop, ConfigSubLoop, GotIt, OutBufPos;
54 Translate TildeSub[NUMTILDESUBS]; /* Holds the tilde (~FOO~) */
56 Translate ConfigSub[NUMCONFIGSUBS]; /* Holds the substitutions from */
58 int TildeSubCount = 0, ConfigSubCount = 0; /* # of tilde substitutions */
59 /* and config substitutions, */
62 printf("Usage: munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]]\n");
67 /* First, open the input files */
68 if (NULL == (ConfigSH = fopen(argv[1], "r"))) {
69 printf("Error %i trying to open config.sh file %s\n", errno, argv[1]);
73 if (NULL == (Config_H = fopen(argv[2], "r"))) {
74 printf("Error %i trying to open config_h.sh file %s\n", errno, argv[2]);
78 /* Any tag/value pairs on the command line? */
82 for (i=3; i < argc && argv[i]; i++) {
85 strcpy(WorkString, argv[i]);
86 /* Stick a NULL over the = */
87 TempValue = strchr(WorkString, '=');
90 /* Copy the tag and value into the holding array */
91 strcpy(TildeSub[TildeSubCount].Tag, WorkString);
92 strcpy(TildeSub[TildeSubCount].Value, TempValue);
97 /* Now read in the config.sh file. */
98 while(fgets(LineBuffer, LINEBUFFERSIZE - 1, ConfigSH)) {
99 /* Force a trailing null, just in case */
100 LineBuffer[LINEBUFFERSIZE - 1] = '\0';
102 LineBufferLength = strlen(LineBuffer);
104 /* Chop trailing control characters */
105 while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
106 LineBuffer[LineBufferLength - 1] = '\0';
110 /* If it's empty, then try again */
114 /* If the line begins with a '#' or ' ', skip */
115 if ((LineBuffer[0] == ' ') || (LineBuffer[0] == '#'))
118 /* We've got something. Guess we need to actually handle it */
119 /* Do the tilde substitution */
120 tilde_sub(LineBuffer, TildeSub, TildeSubCount);
122 /* Stick a NULL over the = */
123 TempValue = strchr(LineBuffer, '=');
125 /* And another over the leading ', which better be there */
128 /* Check to see if there's a trailing ' or ". If not, add a newline to
129 the buffer and grab another line. */
130 TempLength = strlen(TempValue);
131 while ((TempValue[TempLength-1] != '\'') &&
132 (TempValue[TempLength-1] != '"')) {
133 fgets(SecondaryLineBuffer, LINEBUFFERSIZE - 1, ConfigSH);
134 /* Force a trailing null, just in case */
135 SecondaryLineBuffer[LINEBUFFERSIZE - 1] = '\0';
137 tilde_sub(SecondaryLineBuffer, TildeSub, TildeSubCount);
138 /* Tack a nweline on the end of our primary buffer */
139 strcat(TempValue, "\n");
140 /* Concat the new line we just read */
141 strcat(TempValue, SecondaryLineBuffer);
143 /* Refigure the length */
144 TempLength = strlen(TempValue);
146 /* Chop trailing control characters */
147 while((TempLength > 0) && (TempValue[TempLength-1] < ' ')) {
148 TempValue[TempLength - 1] = '\0';
153 /* And finally one over the trailing ' */
154 TempValue[TempLength-1] = '\0';
156 /* Is there even anything left? */
158 /* Copy the tag over */
159 strcpy(ConfigSub[ConfigSubCount].Tag, LineBuffer);
160 /* Copy the value over */
161 strcpy(ConfigSub[ConfigSubCount].Value, TempValue);
169 /* Okay, we've read in all the substititions from our config.sh */
170 /* equivalent. Read in the config_h.sh equiv and start the substitution */
172 /* First, eat all the lines until we get to one with !GROK!THIS! in it */
173 while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
176 /* Dummy statement to shut up any compiler that'll whine about an empty */
181 /* Right, we've read all the lines through the first one with !GROK!THIS! */
182 /* in it. That gets us through the beginning stuff. Now start in earnest */
183 /* with our translations, which run until we get to another !GROK!THIS! */
184 while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
186 /* Force a trailing null, just in case */
187 LineBuffer[LINEBUFFERSIZE - 1] = '\0';
189 /* Tilde Substitute */
190 tilde_sub(LineBuffer, TildeSub, TildeSubCount);
192 LineBufferLength = strlen(LineBuffer);
194 /* Chop trailing control characters */
195 while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
196 LineBuffer[LineBufferLength - 1] = '\0';
201 /* Right. Go looking for $s. */
202 for(LineBufferLoop = 0; LineBufferLoop < LineBufferLength;
204 /* Did we find one? */
205 if ('$' != LineBuffer[LineBufferLoop]) {
206 /* Nope, spit out the value */
207 OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
209 /* Yes, we did. Is it escaped? */
210 if ((LineBufferLoop > 0) && ('\\' == LineBuffer[LineBufferLoop -
212 /* Yup. Spit it out */
213 OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
215 /* Nope. Go grab us a token */
217 /* Advance to the next character in the input stream */
219 while((LineBufferLoop < LineBufferLength) &&
220 ((isalnum(LineBuffer[LineBufferLoop]) || ('_' ==
221 LineBuffer[LineBufferLoop])))) {
222 TokenBuffer[TokenBufferLoop] = LineBuffer[LineBufferLoop];
227 /* Trailing null on the token buffer */
228 TokenBuffer[TokenBufferLoop] = '\0';
230 /* Back the line buffer pointer up one */
233 /* Right, we're done grabbing a token. Check to make sure we got */
235 if (TokenBufferLoop) {
236 /* Well, we do. Run through all the tokens we've got in the */
237 /* ConfigSub array and see if any match */
239 for(ConfigSubLoop = 0; ConfigSubLoop < ConfigSubCount;
241 if (!strcmp(TokenBuffer, ConfigSub[ConfigSubLoop].Tag)) {
242 char *cp = ConfigSub[ConfigSubLoop].Value;
244 while (*cp) OutBuf[OutBufPos++] = *(cp++);
249 /* Did we find something? If not, spit out what was in our */
252 char *cp = TokenBuffer;
253 OutBuf[OutBufPos++] = '$';
254 while (*cp) OutBuf[OutBufPos++] = *(cp++);
258 /* Just a bare $. Spit it out */
259 OutBuf[OutBufPos++] = '$';
265 /* If we've created an #undef line, make sure we don't output anthing
266 * after the "#undef FOO" besides comments. We could do this as we
267 * go by recognizing the #undef as it goes by, and thus avoid another
268 * use of a fixed-length buffer, but this is simpler.
270 if (!strncmp(OutBuf,"#undef",6)) {
272 int i, incomment = 0;
274 OutBuf[OutBufPos] = '\0';
275 for (i = 0; i <= 1; i++) {
276 while (!isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
277 while ( isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
280 while (isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
281 if (!incomment && *cp == '/' && *(cp+1) == '*') incomment = 1;
282 while (*cp && !isspace(*cp)) {
283 if (incomment) LineBuffer[LineBufferLoop++] = *cp;
286 if (incomment && *cp == '*' && *(cp+1) == '/') incomment = 0;
288 LineBuffer[LineBufferLoop] = '\0';
292 OutBuf[OutBufPos] = '\0';
297 /* Close the files */
303 tilde_sub(char LineBuffer[], Translate TildeSub[], int TildeSubCount)
305 char TempBuffer[LINEBUFFERSIZE], TempTilde[TOKENBUFFERSIZE];
306 int TildeLoop, InTilde, CopiedBufferLength, TildeBufferLength, k, GotIt;
309 CopiedBufferLength = 0;
310 TildeBufferLength = 0;
311 TempLength = strlen(LineBuffer);
313 /* Grovel over our input looking for ~foo~ constructs */
314 for(TildeLoop = 0; TildeLoop < TempLength; TildeLoop++) {
315 /* Are we in a tilde? */
317 /* Yup. Is the current character a tilde? */
318 if (LineBuffer[TildeLoop] == '~') {
319 /* Yup. That means we're ready to do a substitution */
323 TempTilde[TildeBufferLength] = '\0';
324 for( k=0; k < TildeSubCount; k++) {
325 if (!strcmp(TildeSub[k].Tag, TempTilde)) {
327 /* Tack on the trailing null to the main buffer */
328 TempBuffer[CopiedBufferLength] = '\0';
329 /* Copy the tilde substitution over */
330 strcat(TempBuffer, TildeSub[k].Value);
331 CopiedBufferLength = strlen(TempBuffer);
335 /* Did we find anything? */
337 /* Guess not. Copy the whole thing out verbatim */
338 TempBuffer[CopiedBufferLength] = '\0';
339 TempBuffer[CopiedBufferLength++] = '~';
340 TempBuffer[CopiedBufferLength] = '\0';
341 strcat(TempBuffer, TempTilde);
342 strcat(TempBuffer, "~");
343 CopiedBufferLength = strlen(TempBuffer);
347 /* 'Kay, not a tilde. Is it a word character? */
348 if (isalnum(LineBuffer[TildeLoop]) || (LineBuffer[TildeLoop] =
350 (LineBuffer[TildeLoop] == '-')) {
351 TempTilde[TildeBufferLength++] = LineBuffer[TildeLoop];
353 /* No, it's not a tilde character. For shame! We've got a */
354 /* bogus token. Copy a ~ into the output buffer, then append */
355 /* whatever we've got in our token buffer */
356 TempBuffer[CopiedBufferLength++] = '~';
357 TempBuffer[CopiedBufferLength] = '\0';
358 TempTilde[TildeBufferLength] = '\0';
359 strcat(TempBuffer, TempTilde);
360 CopiedBufferLength += TildeBufferLength;
365 /* We're not in a tilde. Do we want to be? */
366 if (LineBuffer[TildeLoop] == '~') {
369 TildeBufferLength = 0;
371 /* Nope. Copy the character to the output buffer */
372 TempBuffer[CopiedBufferLength++] = LineBuffer[TildeLoop];
377 /* Out of the loop. First, double-check to see if there was anything */
380 /* bogus token. Copy a ~ into the output buffer, then append */
381 /* whatever we've got in our token buffer */
382 TempBuffer[CopiedBufferLength++] = '~';
383 TempBuffer[CopiedBufferLength] = '\0';
384 TempTilde[TildeBufferLength] = '\0';
385 strcat(TempBuffer, TempTilde);
386 CopiedBufferLength += TildeBufferLength;
388 /* Nope, nothing pensing. Tack on a \0 */
389 TempBuffer[CopiedBufferLength] = '\0';
392 /* Okay, we're done. Copy the temp buffer back into the line buffer */
393 strcpy(LineBuffer, TempBuffer);