source: trunk/third/perl/vms/munchconfig.c @ 14545

Revision 14545, 12.9 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14544, which included commits to RCS files with non-trunk default branches.
Line 
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:
7   munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]] >config.h
8
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.
12
13   It spits the processed config.h out to STDOUT.
14
15   */
16
17#include <stdio.h>
18#include <errno.h>
19#include <stdlib.h>
20#include <string.h>
21#include <ctype.h>
22
23/* The failure code to exit with */
24#ifndef EXIT_FAILURE
25#ifdef VMS
26#define EXIT_FAILURE 0
27#else
28#define EXIT_FAILURE -1
29#endif
30#endif
31
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
37
38typedef struct {
39  char Tag[TOKENBUFFERSIZE];
40  char Value[512];
41} Translate;
42
43void tilde_sub(char [], Translate [], int);
44
45int
46main(int argc, char *argv[])
47{
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~) */
55                                       /* substitutions */
56  Translate ConfigSub[NUMCONFIGSUBS];  /* Holds the substitutions from */
57                                       /* config.sh */
58  int TildeSubCount = 0, ConfigSubCount = 0; /* # of tilde substitutions */
59                                             /* and config substitutions, */
60                                             /* respectively */
61  if (argc < 3) {
62    printf("Usage: munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]]\n");
63    exit(EXIT_FAILURE);
64  }
65
66 
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]);
70    exit(EXIT_FAILURE);
71  }
72 
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]);
75    exit(EXIT_FAILURE);
76  }
77
78  /* Any tag/value pairs on the command line? */
79  if (argc > 3) {
80    int i;
81    char WorkString[80];
82    for (i=3; i < argc && argv[i]; i++) {
83     
84      /* Local copy */
85      strcpy(WorkString, argv[i]);
86      /* Stick a NULL over the = */
87      TempValue = strchr(WorkString, '=');
88      *TempValue++ = '\0';
89
90      /* Copy the tag and value into the holding array */
91      strcpy(TildeSub[TildeSubCount].Tag, WorkString);
92      strcpy(TildeSub[TildeSubCount].Value, TempValue);
93      TildeSubCount++;
94    }
95  }
96
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';
101
102    LineBufferLength = strlen(LineBuffer);
103
104    /* Chop trailing control characters */
105    while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
106      LineBuffer[LineBufferLength - 1] = '\0';
107      LineBufferLength--;
108    }
109
110    /* If it's empty, then try again */
111    if (!*LineBuffer)
112      continue;
113
114    /* If the line begins with a '#' or ' ', skip */
115    if ((LineBuffer[0] == ' ') || (LineBuffer[0] == '#'))
116      continue;
117
118    /* We've got something. Guess we need to actually handle it */
119    /* Do the tilde substitution */
120    tilde_sub(LineBuffer, TildeSub, TildeSubCount);
121
122    /* Stick a NULL over the = */
123    TempValue = strchr(LineBuffer, '=');
124    *TempValue++ = '\0';
125    /* And another over the leading ', which better be there */
126    *TempValue++ = '\0';
127   
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';
136      /* Go substitute */
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);
142
143      /* Refigure the length */
144      TempLength = strlen(TempValue);
145     
146      /* Chop trailing control characters */
147      while((TempLength > 0) && (TempValue[TempLength-1] < ' ')) {
148        TempValue[TempLength - 1] = '\0';
149        TempLength--;
150      }
151    }
152   
153    /* And finally one over the trailing ' */
154    TempValue[TempLength-1] = '\0';
155
156    /* Is there even anything left? */
157    if(*TempValue) {
158      /* Copy the tag over */
159      strcpy(ConfigSub[ConfigSubCount].Tag, LineBuffer);
160      /* Copy the value over */
161      strcpy(ConfigSub[ConfigSubCount].Value, TempValue);
162
163      /* Up the count */
164      ConfigSubCount++;
165
166    }
167  }
168
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 */
171 
172  /* First, eat all the lines until we get to one with !GROK!THIS! in it */
173  while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
174                "!GROK!THIS!")) {
175
176    /* Dummy statement to shut up any compiler that'll whine about an empty */
177    /* loop */
178    DummyVariable++;
179  }
180
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),
185                "!GROK!THIS!")) {
186    /* Force a trailing null, just in case */
187    LineBuffer[LINEBUFFERSIZE - 1] = '\0';
188   
189    /* Tilde Substitute */
190    tilde_sub(LineBuffer, TildeSub, TildeSubCount);
191
192    LineBufferLength = strlen(LineBuffer);
193   
194    /* Chop trailing control characters */
195    while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
196      LineBuffer[LineBufferLength - 1] = '\0';
197      LineBufferLength--;
198    }
199
200    OutBufPos = 0;
201    /* Right. Go looking for $s. */
202    for(LineBufferLoop = 0; LineBufferLoop < LineBufferLength;
203        LineBufferLoop++) {
204      /* Did we find one? */
205      if ('$' != LineBuffer[LineBufferLoop]) {
206        /* Nope, spit out the value */
207        OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
208      } else {
209        /* Yes, we did. Is it escaped? */
210        if ((LineBufferLoop > 0) && ('\\' == LineBuffer[LineBufferLoop -
211                                                       1])) {
212          /* Yup. Spit it out */
213          OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
214        } else {
215         /* Nope. Go grab us a token */
216          TokenBufferLoop = 0;
217          /* Advance to the next character in the input stream */
218          LineBufferLoop++;
219          while((LineBufferLoop < LineBufferLength) &&
220                ((isalnum(LineBuffer[LineBufferLoop]) || ('_' ==
221                                                          LineBuffer[LineBufferLoop])))) {
222            TokenBuffer[TokenBufferLoop] = LineBuffer[LineBufferLoop];
223            LineBufferLoop++;
224            TokenBufferLoop++;
225          }
226
227          /* Trailing null on the token buffer */
228          TokenBuffer[TokenBufferLoop] = '\0';
229
230          /* Back the line buffer pointer up one */
231          LineBufferLoop--;
232         
233          /* Right, we're done grabbing a token. Check to make sure we got */
234          /* something */
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 */
238            GotIt = 0;
239            for(ConfigSubLoop = 0; ConfigSubLoop < ConfigSubCount;
240                ConfigSubLoop++) {
241              if (!strcmp(TokenBuffer, ConfigSub[ConfigSubLoop].Tag)) {
242                char *cp = ConfigSub[ConfigSubLoop].Value;
243                GotIt = 1;
244                while (*cp) OutBuf[OutBufPos++] = *(cp++);
245                break;
246              }
247            }
248
249            /* Did we find something? If not, spit out what was in our */
250            /* buffer */
251            if (!GotIt) {
252              char *cp = TokenBuffer;
253              OutBuf[OutBufPos++] = '$';
254              while (*cp) OutBuf[OutBufPos++] = *(cp++);
255            }
256           
257          } else {
258            /* Just a bare $. Spit it out */
259            OutBuf[OutBufPos++] = '$';
260          }       
261        }
262      }
263    }
264   
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.
269     */
270    if (!strncmp(OutBuf,"#undef",6)) {
271      char *cp = OutBuf;
272      int i, incomment = 0;
273      LineBufferLoop = 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++);
278      }
279      while (*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;
284          cp++;
285        }
286        if (incomment && *cp == '*' && *(cp+1) == '/') incomment = 0;
287      }
288      LineBuffer[LineBufferLoop] = '\0';
289      puts(LineBuffer);
290    }   
291    else {
292      OutBuf[OutBufPos] = '\0';
293      puts(OutBuf);
294    }
295  }
296 
297  /* Close the files */
298  fclose(ConfigSH);
299  fclose(Config_H);
300}
301
302void
303tilde_sub(char LineBuffer[], Translate TildeSub[], int TildeSubCount)
304{
305  char TempBuffer[LINEBUFFERSIZE], TempTilde[TOKENBUFFERSIZE];
306  int TildeLoop, InTilde, CopiedBufferLength, TildeBufferLength, k, GotIt;
307  int TempLength;
308  InTilde = 0;
309  CopiedBufferLength = 0;
310  TildeBufferLength = 0;
311  TempLength = strlen(LineBuffer);
312
313  /* Grovel over our input looking for ~foo~ constructs */
314  for(TildeLoop = 0; TildeLoop < TempLength; TildeLoop++) {
315    /* Are we in a tilde? */
316    if (InTilde) {
317      /* Yup. Is the current character a tilde? */
318      if (LineBuffer[TildeLoop] == '~') {
319        /* Yup. That means we're ready to do a substitution */
320        InTilde = 0;
321        GotIt = 0;
322        /* Trailing null */
323        TempTilde[TildeBufferLength] = '\0';
324        for( k=0; k < TildeSubCount; k++) {
325          if (!strcmp(TildeSub[k].Tag, TempTilde)) {
326            GotIt = 1;
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);
332          }
333        }
334       
335        /* Did we find anything? */
336        if (GotIt == 0) {
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);
344        }
345       
346      } else {
347        /* 'Kay, not a tilde. Is it a word character? */
348        if (isalnum(LineBuffer[TildeLoop]) || (LineBuffer[TildeLoop] =
349                                              '-') ||
350            (LineBuffer[TildeLoop] == '-')) {
351          TempTilde[TildeBufferLength++] = LineBuffer[TildeLoop];
352        } else {
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;
361          InTilde = 0;
362        }
363      }
364    } else {
365      /* We're not in a tilde. Do we want to be? */
366      if (LineBuffer[TildeLoop] == '~') {
367        /* Guess so */
368        InTilde = 1;
369        TildeBufferLength = 0;
370      } else {
371        /* Nope. Copy the character to the output buffer */
372        TempBuffer[CopiedBufferLength++] = LineBuffer[TildeLoop];
373      }
374    }
375  }
376 
377  /* Out of the loop. First, double-check to see if there was anything */
378  /* pending. */
379  if (InTilde) {
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;
387  } else {
388    /* Nope, nothing pensing. Tack on a \0 */
389    TempBuffer[CopiedBufferLength] = '\0';
390  }
391
392  /* Okay, we're done. Copy the temp buffer back into the line buffer */
393  strcpy(LineBuffer, TempBuffer);
394
395}
396
Note: See TracBrowser for help on using the repository browser.