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 38 typedef struct { 39 char Tag[TOKENBUFFERSIZE]; 40 char Value[512]; 41 } Translate; 42 43 void tilde_sub(char [], Translate [], int); 44 45 int 46 main(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 302 void 303 tilde_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]) || 349 (LineBuffer[TildeLoop] == '-')) { 350 TempTilde[TildeBufferLength++] = LineBuffer[TildeLoop]; 351 } else { 352 /* No, it's not a tilde character. For shame! We've got a */ 353 /* bogus token. Copy a ~ into the output buffer, then append */ 354 /* whatever we've got in our token buffer */ 355 TempBuffer[CopiedBufferLength++] = '~'; 356 TempBuffer[CopiedBufferLength] = '\0'; 357 TempTilde[TildeBufferLength] = '\0'; 358 strcat(TempBuffer, TempTilde); 359 CopiedBufferLength += TildeBufferLength; 360 InTilde = 0; 361 } 362 } 363 } else { 364 /* We're not in a tilde. Do we want to be? */ 365 if (LineBuffer[TildeLoop] == '~') { 366 /* Guess so */ 367 InTilde = 1; 368 TildeBufferLength = 0; 369 } else { 370 /* Nope. Copy the character to the output buffer */ 371 TempBuffer[CopiedBufferLength++] = LineBuffer[TildeLoop]; 372 } 373 } 374 } 375 376 /* Out of the loop. First, double-check to see if there was anything */ 377 /* pending. */ 378 if (InTilde) { 379 /* bogus token. Copy a ~ into the output buffer, then append */ 380 /* whatever we've got in our token buffer */ 381 TempBuffer[CopiedBufferLength++] = '~'; 382 TempBuffer[CopiedBufferLength] = '\0'; 383 TempTilde[TildeBufferLength] = '\0'; 384 strcat(TempBuffer, TempTilde); 385 CopiedBufferLength += TildeBufferLength; 386 } else { 387 /* Nope, nothing pensing. Tack on a \0 */ 388 TempBuffer[CopiedBufferLength] = '\0'; 389 } 390 391 /* Okay, we're done. Copy the temp buffer back into the line buffer */ 392 strcpy(LineBuffer, TempBuffer); 393 394 } 395 396