/* munchconfig.c
A very, very (very!) simple program to process a config_h.sh file on
non-unix systems.
usage:
munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]] >config.h
which is to say, it takes as its firt parameter a config.sh (or
equivalent), as its second a config_h.sh (or equvalent), and a list of
optional tag=value pairs.
It spits the processed config.h out to STDOUT.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* The failure code to exit with */
#ifndef EXIT_FAILURE
#ifdef VMS
#define EXIT_FAILURE 0
#else
#define EXIT_FAILURE -1
#endif
#endif
/* The biggest line we can read in from a file */
#define LINEBUFFERSIZE 1024
#define NUMTILDESUBS 30
#define NUMCONFIGSUBS 1000
#define TOKENBUFFERSIZE 80
typedef struct {
char Tag[TOKENBUFFERSIZE];
char Value[512];
} Translate;
void tilde_sub(char [], Translate [], int);
int
main(int argc, char *argv[])
{
FILE *ConfigSH, *Config_H;
char LineBuffer[LINEBUFFERSIZE], *TempValue, *StartTilde, *EndTilde;
char SecondaryLineBuffer[LINEBUFFERSIZE], OutBuf[LINEBUFFERSIZE];
char TokenBuffer[TOKENBUFFERSIZE];
int LineBufferLength, TempLength, DummyVariable, LineBufferLoop;
int TokenBufferLoop, ConfigSubLoop, GotIt, OutBufPos;
Translate TildeSub[NUMTILDESUBS]; /* Holds the tilde (~FOO~) */
/* substitutions */
Translate ConfigSub[NUMCONFIGSUBS]; /* Holds the substitutions from */
/* config.sh */
int TildeSubCount = 0, ConfigSubCount = 0; /* # of tilde substitutions */
/* and config substitutions, */
/* respectively */
if (argc < 3) {
printf("Usage: munchconfig config.sh config_h.sh [foo=bar [baz=xyzzy [...]]]\n");
exit(EXIT_FAILURE);
}
/* First, open the input files */
if (NULL == (ConfigSH = fopen(argv[1], "r"))) {
printf("Error %i trying to open config.sh file %s\n", errno, argv[1]);
exit(EXIT_FAILURE);
}
if (NULL == (Config_H = fopen(argv[2], "r"))) {
printf("Error %i trying to open config_h.sh file %s\n", errno, argv[2]);
exit(EXIT_FAILURE);
}
/* Any tag/value pairs on the command line? */
if (argc > 3) {
int i;
char WorkString[LINEBUFFERSIZE];
for (i=3; i < argc && argv[i]; i++) {
/* Local copy */
strcpy(WorkString, argv[i]);
/* Stick a NULL over the = */
TempValue = strchr(WorkString, '=');
*TempValue++ = '\0';
/* Copy the tag and value into the holding array */
strcpy(TildeSub[TildeSubCount].Tag, WorkString);
strcpy(TildeSub[TildeSubCount].Value, TempValue);
TildeSubCount++;
}
}
/* Now read in the config.sh file. */
while(fgets(LineBuffer, LINEBUFFERSIZE - 1, ConfigSH)) {
/* Force a trailing null, just in case */
LineBuffer[LINEBUFFERSIZE - 1] = '\0';
LineBufferLength = strlen(LineBuffer);
/* Chop trailing control characters */
while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
LineBuffer[LineBufferLength - 1] = '\0';
LineBufferLength--;
}
/* If it's empty, then try again */
if (!*LineBuffer)
continue;
/* If the line begins with a '#' or ' ', skip */
if ((LineBuffer[0] == ' ') || (LineBuffer[0] == '#'))
continue;
/* We've got something. Guess we need to actually handle it */
/* Do the tilde substitution */
tilde_sub(LineBuffer, TildeSub, TildeSubCount);
/* Stick a NULL over the = */
TempValue = strchr(LineBuffer, '=');
*TempValue++ = '\0';
/* And another over the leading ', which better be there */
*TempValue++ = '\0';
/* Check to see if there's a trailing ' or ". If not, add a newline to
the buffer and grab another line. */
TempLength = strlen(TempValue);
while ((TempValue[TempLength-1] != '\'') &&
(TempValue[TempLength-1] != '"')) {
fgets(SecondaryLineBuffer, LINEBUFFERSIZE - 1, ConfigSH);
/* Force a trailing null, just in case */
SecondaryLineBuffer[LINEBUFFERSIZE - 1] = '\0';
/* Go substitute */
tilde_sub(SecondaryLineBuffer, TildeSub, TildeSubCount);
/* Tack a nweline on the end of our primary buffer */
strcat(TempValue, "\n");
/* Concat the new line we just read */
strcat(TempValue, SecondaryLineBuffer);
/* Refigure the length */
TempLength = strlen(TempValue);
/* Chop trailing control characters */
while((TempLength > 0) && (TempValue[TempLength-1] < ' ')) {
TempValue[TempLength - 1] = '\0';
TempLength--;
}
}
/* And finally one over the trailing ' */
TempValue[TempLength-1] = '\0';
/* Is there even anything left? */
if(*TempValue) {
/* Copy the tag over */
strcpy(ConfigSub[ConfigSubCount].Tag, LineBuffer);
/* Copy the value over */
strcpy(ConfigSub[ConfigSubCount].Value, TempValue);
/* Up the count */
ConfigSubCount++;
}
}
/* Okay, we've read in all the substititions from our config.sh */
/* equivalent. Read in the config_h.sh equiv and start the substitution */
/* First, eat all the lines until we get to one with !GROK!THIS! in it */
while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
"!GROK!THIS!")) {
/* Dummy statement to shut up any compiler that'll whine about an empty */
/* loop */
DummyVariable++;
}
/* Right, we've read all the lines through the first one with !GROK!THIS! */
/* in it. That gets us through the beginning stuff. Now start in earnest */
/* with our translations, which run until we get to another !GROK!THIS! */
while(!strstr(fgets(LineBuffer, LINEBUFFERSIZE, Config_H),
"!GROK!THIS!")) {
/* Force a trailing null, just in case */
LineBuffer[LINEBUFFERSIZE - 1] = '\0';
/* Tilde Substitute */
tilde_sub(LineBuffer, TildeSub, TildeSubCount);
LineBufferLength = strlen(LineBuffer);
/* Chop trailing control characters */
while((LineBufferLength > 0) && (LineBuffer[LineBufferLength-1] < ' ')) {
LineBuffer[LineBufferLength - 1] = '\0';
LineBufferLength--;
}
OutBufPos = 0;
/* Right. Go looking for $s. */
for(LineBufferLoop = 0; LineBufferLoop < LineBufferLength;
LineBufferLoop++) {
/* Did we find one? */
if ('$' != LineBuffer[LineBufferLoop]) {
/* Nope, spit out the value */
OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
} else {
/* Yes, we did. Is it escaped? */
if ((LineBufferLoop > 0) && ('\\' == LineBuffer[LineBufferLoop -
1])) {
/* Yup. Spit it out */
OutBuf[OutBufPos++] = LineBuffer[LineBufferLoop];
} else {
/* Nope. Go grab us a token */
TokenBufferLoop = 0;
/* Advance to the next character in the input stream */
LineBufferLoop++;
while((LineBufferLoop < LineBufferLength) &&
((isalnum(LineBuffer[LineBufferLoop]) || ('_' ==
LineBuffer[LineBufferLoop])))) {
TokenBuffer[TokenBufferLoop] = LineBuffer[LineBufferLoop];
LineBufferLoop++;
TokenBufferLoop++;
}
/* Trailing null on the token buffer */
TokenBuffer[TokenBufferLoop] = '\0';
/* Back the line buffer pointer up one */
LineBufferLoop--;
/* Right, we're done grabbing a token. Check to make sure we got */
/* something */
if (TokenBufferLoop) {
/* Well, we do. Run through all the tokens we've got in the */
/* ConfigSub array and see if any match */
GotIt = 0;
for(ConfigSubLoop = 0; ConfigSubLoop < ConfigSubCount;
ConfigSubLoop++) {
if (!strcmp(TokenBuffer, ConfigSub[ConfigSubLoop].Tag)) {
char *cp = ConfigSub[ConfigSubLoop].Value;
GotIt = 1;
while (*cp) OutBuf[OutBufPos++] = *(cp++);
break;
}
}
/* Did we find something? If not, spit out what was in our */
/* buffer */
if (!GotIt) {
char *cp = TokenBuffer;
OutBuf[OutBufPos++] = '$';
while (*cp) OutBuf[OutBufPos++] = *(cp++);
}
} else {
/* Just a bare $. Spit it out */
OutBuf[OutBufPos++] = '$';
}
}
}
}
/* If we've created an #undef line, make sure we don't output anthing
* after the "#undef FOO" besides comments. We could do this as we
* go by recognizing the #undef as it goes by, and thus avoid another
* use of a fixed-length buffer, but this is simpler.
*/
if (!strncmp(OutBuf,"#undef",6)) {
char *cp = OutBuf;
int i, incomment = 0;
LineBufferLoop = 0;
OutBuf[OutBufPos] = '\0';
for (i = 0; i <= 1; i++) {
while (!isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
while ( isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
}
while (*cp) {
while (isspace(*cp)) LineBuffer[LineBufferLoop++] = *(cp++);
if (!incomment && *cp == '/' && *(cp+1) == '*') incomment = 1;
while (*cp && !isspace(*cp)) {
if (incomment) LineBuffer[LineBufferLoop++] = *cp;
cp++;
}
if (incomment && *cp == '*' && *(cp+1) == '/') incomment = 0;
}
LineBuffer[LineBufferLoop] = '\0';
puts(LineBuffer);
}
else {
OutBuf[OutBufPos] = '\0';
puts(OutBuf);
}
}
/* Close the files */
fclose(ConfigSH);
fclose(Config_H);
}
void
tilde_sub(char LineBuffer[], Translate TildeSub[], int TildeSubCount)
{
char TempBuffer[LINEBUFFERSIZE], TempTilde[TOKENBUFFERSIZE];
int TildeLoop, InTilde, CopiedBufferLength, TildeBufferLength, k, GotIt;
int TempLength;
InTilde = 0;
CopiedBufferLength = 0;
TildeBufferLength = 0;
TempLength = strlen(LineBuffer);
/* Grovel over our input looking for ~foo~ constructs */
for(TildeLoop = 0; TildeLoop < TempLength; TildeLoop++) {
/* Are we in a tilde? */
if (InTilde) {
/* Yup. Is the current character a tilde? */
if (LineBuffer[TildeLoop] == '~') {
/* Yup. That means we're ready to do a substitution */
InTilde = 0;
GotIt = 0;
/* Trailing null */
TempTilde[TildeBufferLength] = '\0';
for( k=0; k < TildeSubCount; k++) {
if (!strcmp(TildeSub[k].Tag, TempTilde)) {
GotIt = 1;
/* Tack on the trailing null to the main buffer */
TempBuffer[CopiedBufferLength] = '\0';
/* Copy the tilde substitution over */
strcat(TempBuffer, TildeSub[k].Value);
CopiedBufferLength = strlen(TempBuffer);
}
}
/* Did we find anything? */
if (GotIt == 0) {
/* Guess not. Copy the whole thing out verbatim */
TempBuffer[CopiedBufferLength] = '\0';
TempBuffer[CopiedBufferLength++] = '~';
TempBuffer[CopiedBufferLength] = '\0';
strcat(TempBuffer, TempTilde);
strcat(TempBuffer, "~");
CopiedBufferLength = strlen(TempBuffer);
}
} else {
/* 'Kay, not a tilde. Is it a word character? */
if (isalnum(LineBuffer[TildeLoop]) ||
(LineBuffer[TildeLoop] == '-')) {
TempTilde[TildeBufferLength++] = LineBuffer[TildeLoop];
} else {
/* No, it's not a tilde character. For shame! We've got a */
/* bogus token. Copy a ~ into the output buffer, then append */
/* whatever we've got in our token buffer */
TempBuffer[CopiedBufferLength++] = '~';
TempBuffer[CopiedBufferLength] = '\0';
TempTilde[TildeBufferLength] = '\0';
strcat(TempBuffer, TempTilde);
CopiedBufferLength += TildeBufferLength;
InTilde = 0;
}
}
} else {
/* We're not in a tilde. Do we want to be? */
if (LineBuffer[TildeLoop] == '~') {
/* Guess so */
InTilde = 1;
TildeBufferLength = 0;
} else {
/* Nope. Copy the character to the output buffer */
TempBuffer[CopiedBufferLength++] = LineBuffer[TildeLoop];
}
}
}
/* Out of the loop. First, double-check to see if there was anything */
/* pending. */
if (InTilde) {
/* bogus token. Copy a ~ into the output buffer, then append */
/* whatever we've got in our token buffer */
TempBuffer[CopiedBufferLength++] = '~';
TempBuffer[CopiedBufferLength] = '\0';
TempTilde[TildeBufferLength] = '\0';
strcat(TempBuffer, TempTilde);
CopiedBufferLength += TildeBufferLength;
} else {
/* Nope, nothing pensing. Tack on a \0 */
TempBuffer[CopiedBufferLength] = '\0';
}
/* Okay, we're done. Copy the temp buffer back into the line buffer */
strcpy(LineBuffer, TempBuffer);
}
|