text: /* Copyrigt (C) 2002 Rene Rivera.
  ** Permission to copy, use, modify, sell and distribute this software
  ** is granted provided this copyright notice appears in all copies.
  ** This software is provided "as is" without express or implied
  ** warranty, and with no claim as to its suitability for any purpose.
  */
  #include <stdio.h>
  #include <string.h>
  #include <ctype.h>
  #include <stdlib.h>
  
  /*
  # yyacc - yacc wrapper
  #
  # Allows tokens to be written as `literal` and then automatically 
  # substituted with #defined tokens.
  #
  # Usage:
  #    yyacc file.y filetab.h file.yy 
  #
  # inputs:
  #    file.yy        yacc grammar with ` literals
  #
  # outputs:
  #    file.y        yacc grammar
  #    filetab.h    array of string <-> token mappings
  #
  # 3-13-93
  #    Documented and p moved in sed command (for some reason,
  #    s/x/y/p doesn't work).
  # 10-12-93
  #    Take basename as second argument.
  # 12-31-96
  #    reversed order of args to be compatible with GenFile rule
  # 11-20-2002
  #    Reimplemented as a C program for portability. (Rene Rivera)
  */
  
  void print_usage();
  char * copy_string(char * s, int l);
  char * tokenize_string(char * s);
  int cmp_literal(const void * a, const void * b);
  
  typedef struct
  {
      char * string;
      char * token;
  } literal;
  
  int main(int argc, char ** argv)
  {
      int result = 0;
      if (argc != 4)
      {
          print_usage();
          result = 1;
      }
      else
      {
          FILE * token_output_f = 0;
          FILE * grammar_output_f = 0;
          FILE * grammar_source_f = 0;
          
          grammar_source_f = fopen(argv[3],"r");
          if (grammar_source_f == 0) { result = 1; }
          if (result == 0)
          {
              literal literals[1024];
              int t = 0;
              char l[2048];
              while (1)
              {
                  if (fgets(l,2048,grammar_source_f) != 0)
                  {
                      char * c = l;
                      while (1)
                      {
                          char * c1 = strchr(c,'`');
                          if (c1 != 0)
                          {
                              char * c2 = strchr(c1+1,'`');
                              if (c2 != 0)
                              {
                                  literals[t].string = copy_string(c1+1,c2-c1-1);
                                  literals[t].token = tokenize_string(literals[t].string);
                                  t += 1;
                                  c = c2+1;
                              }
                              else
                                  break;
                          }
                          else
                              break;
                      }
                  }
                  else
                  {
                      break;
                  }
              }
              literals[t].string = 0;
              literals[t].token = 0;
              qsort(literals,t,sizeof(literal),cmp_literal);
              {
                  int p = 1;
                  int i = 1;
                  while (literals[i].string != 0)
                  {
                      if (strcmp(literals[p-1].string,literals[i].string) != 0)
                      {
                          literals[p] = literals[i];
                          p += 1;
                      }
                      i += 1;
                  }
                  literals[p].string = 0;
                  literals[p].token = 0;
                  t = p;
              }
              token_output_f = fopen(argv[2],"w");
              if (token_output_f != 0)
              {
                  int i = 0;
                  while (literals[i].string != 0)
                  {
                      fprintf(token_output_f,"    { \"%s\", %s },\n",literals[i].string,literals[i].token);
                      i += 1;
                  }
                  fclose(token_output_f);
              }
              else
                  result = 1;
              if (result == 0)
              {
                  grammar_output_f = fopen(argv[1],"w");
                  if (grammar_output_f != 0)
                  {
                      int i = 0;
                      while (literals[i].string != 0)
                      {
                          fprintf(grammar_output_f,"%%token %s\n",literals[i].token);
                          i += 1;
                      }
                      rewind(grammar_source_f);
                      while (1)
                      {
                          if (fgets(l,2048,grammar_source_f) != 0)
                          {
                              char * c = l;
                              while (1)
                              {
                                  char * c1 = strchr(c,'`');
                                  if (c1 != 0)
                                  {
                                      char * c2 = strchr(c1+1,'`');
                                      if (c2 != 0)
                                      {
                                          literal key;
                                          literal * replacement = 0;
                                          key.string = copy_string(c1+1,c2-c1-1);
                                          key.token = 0;
                                          replacement = (literal*)bsearch(
                                              &key,literals,t,sizeof(literal),cmp_literal);
                                          *c1 = 0;
                                          fprintf(grammar_output_f,"%s%s",c,replacement->token);
                                          c = c2+1;
                                      }
                                      else
                                      {
                                          fprintf(grammar_output_f,"%s",c);
                                          break;
                                      }
                                  }
                                  else
                                  {
                                      fprintf(grammar_output_f,"%s",c);
                                      break;
                                  }
                              }
                          }
                          else
                          {
                              break;
                          }
                      }
                      fclose(grammar_output_f);
                  }
                  else
                      result = 1;
              }
          }
          if (result != 0)
          {
              perror("yyacc");
          }
      }
      return result;
  }
  
  static char * usage[] = {
      "yyacc <grammar output.y> <token table output.h> <grammar source.yy>",
      0 };
  
  void print_usage()
  {
      char ** u;
      for (u = usage; *u != 0; ++u)
      {
          fputs(*u,stderr); putc('\n',stderr);
      }
  }
  
  char * copy_string(char * s, int l)
  {
      char * result = (char*)malloc(l+1);
      strncpy(result,s,l);
      result[l] = 0;
      return result;
  }
  
  char * tokenize_string(char * s)
  {
      char * result;
      char * literal = s;
      int l;
      int c;
      
      if (strcmp(s,":") == 0) literal = "_colon";
      else if (strcmp(s,"!") == 0) literal = "_bang";
      else if (strcmp(s,"!=") == 0) literal = "_bang_equals";
      else if (strcmp(s,"&&") == 0) literal = "_amperamper";
      else if (strcmp(s,"&") == 0) literal = "_amper";
      else if (strcmp(s,"+") == 0) literal = "_plus";
      else if (strcmp(s,"+=") == 0) literal = "_plus_equals";
      else if (strcmp(s,"||") == 0) literal = "_barbar";
      else if (strcmp(s,"|") == 0) literal = "_bar";
      else if (strcmp(s,";") == 0) literal = "_semic";
      else if (strcmp(s,"-") == 0) literal = "_minus";
      else if (strcmp(s,"<") == 0) literal = "_langle";
      else if (strcmp(s,"<=") == 0) literal = "_langle_equals";
      else if (strcmp(s,">") == 0) literal = "_rangle";
      else if (strcmp(s,">=") == 0) literal = "_rangle_equals";
      else if (strcmp(s,".") == 0) literal = "_period";
      else if (strcmp(s,"?") == 0) literal = "_question";
      else if (strcmp(s,"?=") == 0) literal = "_question_equals";
      else if (strcmp(s,"=") == 0) literal = "_equals";
      else if (strcmp(s,",") == 0) literal = "_comma";
      else if (strcmp(s,"[") == 0) literal = "_lbracket";
      else if (strcmp(s,"]") == 0) literal = "_rbracket";
      else if (strcmp(s,"{") == 0) literal = "_lbrace";
      else if (strcmp(s,"}") == 0) literal = "_rbrace";
      else if (strcmp(s,"(") == 0) literal = "_lparen";
      else if (strcmp(s,")") == 0) literal = "_rparen";
      l = strlen(literal)+2;
      result = (char*)malloc(l+1);
      for (c = 0; literal[c] != 0; ++c)
      {
          result[c] = toupper(literal[c]);
      }
      result[l-2] = '_';
      result[l-1] = 't';
      result[l] = 0;
      return result;
  }
  
  int cmp_literal(const void * a, const void * b)
  {
      return strcmp(((const literal *)a)->string,((const literal *)b)->string);
  }
  