#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int fields = 0;
char ** member_types = NULL;

int read_struct_member() {
  char line[512];
  
  printf("> ");
  fgets(line, 512, stdin);
  
  if(strlen(line) > 1) {
    if(fields++)
      member_types = realloc(member_types, fields*sizeof(char *));
    else
      member_types = malloc(sizeof(char *));
    
    member_types[fields-1] = malloc(strlen(line));
    strncpy(member_types[fields-1], line, strlen(line)-1);
    member_types[fields-1][strlen(line)-1] = '\0';
    
    return 1;
  }
  return 0;
}

void print_struct_definition(FILE * dst) {
  int i;
  
  fprintf(dst, "typedef struct {\n");
  for(i = 0; i < fields; i++) {
    fprintf(dst, "   %s %c;\n", member_types[i], 'a'+i);
  }
  fprintf(dst, "} foo;\n");
}

char * sixtey_four_spaces = "                                                                ";
char * spaces_of_length(int length) {
  return sixtey_four_spaces + 64 - length;
}

int main(int argc, char ** argv) {
  int i;
  FILE * foo;
  
  printf("Enter struct types in order, newline to finish:\n");
  while(read_struct_member());
  printf("\n");
  
  printf("Struct definition:\n");
  print_struct_definition(stdout);
  printf("\n");

  printf("Outputting program \"foo.c\"...\n");
  foo = fopen("foo.c", "w");
  fprintf(foo,"%s", "\
#include <stdio.h>\n\
#include <stdlib.h>\n\
#include <stddef.h>\n\
\n");
  print_struct_definition(foo);
  fprintf(foo,"%s", "\n\
int position = 0;\n\
void print_position() {\n\
  if(!(position%4))\n\
    printf(\"%s%2x:\", position?\"\\n\":\"\", position);\n\
}\n\
\n\
void print_object(char * type_and_name, int length) {\n\
  int i;\n\
  \n\
  for(i = 0; i < length; i++, position++) {\n\
    print_position();\n\
    printf(\"%s\", type_and_name);\n\
  }\n\
}\n\
\n\
int main(void) {\n");
  
  for(i = 0; i < fields; i++) {
    fprintf(foo, "  print_object(\"[%s%s%c]\", sizeof(%s));\n",
	    member_types[i], spaces_of_length(13-strlen(member_types[i])-1), 'a'+i, member_types[i], member_types[i]);
    if(i+1 == fields)
      fprintf(foo, "  print_object(\"---------------\", sizeof(foo)      -(offsetof(foo, %c)+sizeof(%s)));\n",
	      'a'+i, member_types[i]);
    else
      fprintf(foo, "  print_object(\"---------------\", offsetof(foo, %c)-(offsetof(foo, %c)+sizeof(%s)));\n",
	      'a'+i+1, 'a'+i, member_types[i]);
  }
  
  fprintf(foo,"%s", "\
  print_position();\n\
  printf(\"\\n\");\n\
  \n\
  return 0;\n\
}");
  
  return 0;
}

/*
Enter struct types in order, newline to finish:
> int
> char
> long double
> char
> 

Struct definition:
typedef struct {
   int a;
   char b;
   long double c;
   char d;
} foo;

Outputting program...
mr-dos-computer% gcc foo.c 
mr-dos-computer% ./a.out 
 0:[int         a][int         a][int         a][int         a]
 4:[char        b]---------------------------------------------
 8:------------------------------------------------------------
 c:------------------------------------------------------------
10:[long double c][long double c][long double c][long double c]
14:[long double c][long double c][long double c][long double c]
18:[long double c][long double c][long double c][long double c]
1c:[long double c][long double c][long double c][long double c]
20:[char        d]---------------------------------------------
24:------------------------------------------------------------
28:------------------------------------------------------------
2c:------------------------------------------------------------
30:
*/

