%{
#include <stdio.h>
#include <string.h>
#define YYDEBUG 1
#define YYERROR_VERBOSE

char struct_name[255];

void yyerror(char *s){
   printf("ERROR: yyerror: %s\n",s);
}

void header(FILE *fp){
      fprintf(fp,"/* AUTOGENERATED write structure routine */\n");
      fprintf(fp,"#include <stdio.h>\n");
      fprintf(fp,"#include <stdlib.h>\n");
      fprintf(fp,"#include <time.h>\n");
      fprintf(fp,"#include <string.h>\n");
      fprintf(fp,"#include \"machine.h\"\n");
      fprintf(fp,"/*TO DO: MANUALLY ADD the header for the structure */\n");
      fprintf(fp,"/*TO DO: MANUALLY ADD strings or other structures not implemented */\n");
      fprintf(fp,"/*TO DO: MANUALLY REMOVE purely internal variables and flags (not to be read in) */\n");
}
void h_header(FILE *fp){
      fprintf(fp,"/* AUTOGENERATED header file for write structure routines */\n");
}

void prog(char * s,const char * strname){
      sprintf(s,"void write_%s_values(FILE * fp,struct %s *Struct_Ptr){\n",strname,strname);
      sprintf(struct_name,strname);
}

FILE * fp,*hfp;
char * string_val;
char * line;
char  outstring[1000];
int cmtflag = 0;
int newflag = 0;
int nflag = 0;
int endflag = 0;
%}
%union{
int index;
double val;
char * name;
}
%token <val> NUMBER
%token <name> NAME POINTER KEY STRNAME OTHER STRSTART
%token <index> INDEX
%type <name> Name Key Pointer
%type <index> index Index
%%
input:  | input line ;

member: Key Name Other {fprintf(stderr,"/* %s Member name: %s */\n",$1,$2);
                  if (strcasecmp ($1,"int") == 0){
                     fprintf(fp,"   fprintf(fp,\"%s %%i \\n\",Struct_Ptr->%s);\n",$2,$2);
                  }else if (strcasecmp ($1,"float") == 0 || strcasecmp($1,"ca_float") ==0){
                     fprintf(fp,"   fprintf(fp,\"%s %%g \\n\",Struct_Ptr->%s);\n",$2,$2);
                  }

                 }
;

pmember: Key Pointer Other {
                             fprintf(stderr,"/* %s Pointer member name: %s */\n",$1,$2);
                             fprintf(fp,"/* Output section for %s pointer memeber %s */ \n",$1,$2);
                             if(strcasecmp($1,"char") ==0 ){
                                fprintf(stderr,"/* Write a string from the pointer */\n");
                                string_val=(strdup($2+1+strspn(($2+1)," ")));
                                fprintf(fp,"    fprintf(fp,\"%s %%s \\n\",Struct_Ptr->%s);\n",(string_val),(string_val));
                             }else{
                                fprintf(fp,"/* cannot output %s pointer %s */\n",$1,$2);
                             }
                           }

array: Key Name Index Other { if ($3 == 0){
                                fprintf(stderr,"/*cannot do multi arrays yet */\n");
                              }else{
                                if (strcasecmp ($1,"char") ==0 ){
                                   fprintf(fp,"      fprintf(fp,\"%s %%s \\n\",Struct_Ptr->%s);\n",$2,$2);
                                }else{

                                   fprintf(stderr,"/* Member %s array %s index %i*/\n",$1,$2,$3);
                                   fprintf(fp,"     fprintf(fp,\"%s \");\n",$2);
                                   fprintf(fp,"   for(i=0;i<%i;i++){\n",$3);

                                   if (strcasecmp ($1,"int") == 0)
                                      fprintf(fp,"     fprintf(fp,\" %%i \",Struct_Ptr->%s[i]);\n",$2);
                                   else if (strcasecmp ($1,"float") == 0 || strcasecmp($1,"ca_float") == 0)
                                      fprintf(fp,"     fprintf(fp,\" %%g \",Struct_Ptr->%s[i]);\n",$2);

                                   fprintf(fp,"   }\n");
                                   fprintf(fp,"     fprintf(fp,\" \\n\");\n",$2);
                                }
                              }
                            }
;
Index: index {$$ = $1;}
       | Index index {$$=0;}
;

index: INDEX {printf("Parser: index %i\n",$1);}
;

endstr: STRNAME {fprintf(fp,"}\n/* End of structure %s */\n",$1);}
;
strstart: STRSTART STRNAME {printf("Parser: strname %s\n",$2);
                            fprintf(fp,"/* start of structure %s */\n",$2);
                            prog(outstring,$2);
                            fprintf(fp,"%s",outstring);
                            fprintf(fp,"   int i;\n\n");
                            fprintf(fp,"   fprintf(fp,\"\\n# %s STRUCTURE VALUES *****\\n\");\n" ,$2);
                            outstring[strlen(outstring)-2] = ';';
                            fprintf(hfp,"#ifndef %s_writer_h\n",$2);
                            fprintf(hfp,"#define %s_writer_h\n",$2);
                            fprintf(hfp,"extern %s",outstring);
                           }
;
info:  Name {;} | Pointer {;} | Key {;} | Other {;} | Number {;} ;
line: array | strstart | endstr | member | pmember | info | info line;

Name: NAME {printf("parser: Name: %s\n",$1)}
;

Pointer: POINTER {printf("parser: Pointer: %s\n",$1)}
;

Number: NUMBER {printf("parser: Number %f\n",$1)}
;

Key: KEY {printf("parser: Key: %s\n",$1)}
;

Other: OTHER {printf("parser: Other: %s\n",$1)}
;

%%


/*
int yylex(void){
   char * token;
   int return_val;

   if (newflag == 0){
      newflag = 1;
      token = strtok(line," ,\t");
   }else{
      token = strtok(NULL," ,\t");
   }

   if (token == NULL){
      return 0;
   }


   if ( token[0] == '/' || token[0] == '#' || token[0] == '%'){
       return_val = CMT;
       yylval.name = strdup(token);
   }else if(isalpha(token[0])){
      yylval.name = strdup(token);
      return_val = NAME;
   }else{
      yylval.val = atof(token);
      return_val= NUMBER;
   }
   return (return_val);
}
*/

int main(int argc, char * argv[]){
    char command[1000];
    fp = fopen("W_out.c","w");
    hfp = fopen("W_out.h","w");
    fprintf(fp,"/*$Id: make_structure_output.y 895 2006-03-10 16:12:45Z rcatwood $*/\n");
    fprintf(hfp,"/*$Id: make_structure_output.y 895 2006-03-10 16:12:45Z rcatwood $*/\n");
    header (fp);
    h_header(hfp);
    /*print a usage message */
    printf("%s: Input a c structure definition from standard input, and\n",argv[0]);
    printf("    output a c program to write the structure to a file\n");
    printf("    Some manual fine tuning of the results\n");
    printf("    will be necessary.\n\n");
    printf("    Files: W_out.c -- structure writing routine\n");
    printf("           W_out.h -- Prototype header for the routine\n");
    printf("    Example usage: %s < control.h > messages.txt\n\n");
    /*                    */
    while (endflag == 0){
       printf("Parsing a line (control-d to finish) ...  \n");
       yyparse();
       printf("End flag %i\n",endflag);
    }
    fclose (fp);
    fprintf(hfp,"#endif /* %s_h /*",struct_name);
    fclose (hfp);
    sprintf(command,"cp W_out.c %s_writer.c \n",struct_name);
    system(command);
    sprintf(command,"cp W_out.h %s_writer.h \n",struct_name);
    system(command);
    printf("Finished making %s_reader files (.c and .h)\nNow edit the files before using them.\n",struct_name);
    printf("%s_writer.c\n",struct_name);
    return(0);
}


