home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl560.zip / vms / munchconfig.c < prev    next >
C/C++ Source or Header  |  1999-07-20  |  13KB  |  397 lines

  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]) || (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.  
  397.