BEGIN {
  type_name = "";	# GtkEnumType
  type_macro = "";	# GTK_TYPE_ENUM_TYPE
  type_ident = "";	# _gtk_enum_type
  type_counter = 0;
  gen_macros = 0;
  gen_entries = 0;
  gen_vars = 0;
  boxed_copy = "";
  boxed_free = "";
  
  for (i = 2; i < ARGC; i++)
    {
      if (ARGV[i] == "macros")
	gen_macros = 1;
      else if (ARGV[i] == "entries")
	gen_entries = 1;
      else if (ARGV[i] == "variables")
	gen_vars = 1;
      ARGV[i] = "";
    }
  
  if (gen_macros)
    {
      printf ("/* type macros, generated by maketypes.awk */\n");
      printf ("\n");
      printf ("#ifdef G_OS_WIN32\n");
      printf ("#  ifdef EEL_COMPILATION\n");
      printf ("#    define EELTYPEBUILTINS_VAR __declspec(dllexport)\n");
      printf ("#  else\n");
      printf ("#    define EELTYPEBUILTINS_VAR extern __declspec(dllimport)\n");
      printf ("#  endif\n");
      printf ("#else\n");
      printf ("#  ifdef EEL_COMPILATION\n");
      printf ("#    define EELTYPEBUILTINS_VAR\n");
      printf ("#  else\n");
      printf ("#    define EELTYPEBUILTINS_VAR extern\n");
      printf ("#  endif\n");
      printf ("#endif\n");
      printf ("\n");
    }
  else if (gen_entries)
    printf ("/* type entries, generated by maketypes.awk */\n\n");
  else if (gen_vars)
    printf ("/* type variables, generated by maketypes.awk */\n\n");
  else
    {
      printf ("hm? what do you want me to do?\n") > "/dev/stderr";
      exit 1;
    }
}

function set_type (set_type_1)
{
  type_counter += 1;
  type_name = set_type_1;
  type_macro = "EEL_TYPE_";
  
  tmp = type_name;
# OK, the following is ridiculous, and sed s///g would be far easier
  gsub ("[A-Z]", "@&", tmp);
  gsub ("[^A-Z]@", "&_", tmp);
  gsub ("@", "", tmp);
  gsub ("[A-Z][A-Z][A-Z][0-9a-z]", "@&", tmp);
  gsub ("@..", "&_", tmp);
  gsub ("@", "", tmp);
  type_macro = type_macro toupper (tmp);
  type_ident = "_" tolower (tmp);

  sub ("^EEL_TYPE_EEL_", "EEL_TYPE_", type_macro);
}

function generate (generate_what)
{
  if (gen_macros)
    {
      printf ("EELTYPEBUILTINS_VAR GType %s;\n", type_macro);
    }
  if (gen_entries)
    {
      printf ("  { \"%s\", &%s,\n", type_name, type_macro);
      if (generate_what == "BOXED")
	printf ("    G_TYPE_%s, %s, %s, },\n", generate_what, boxed_copy, boxed_free);
      else
	printf ("    G_TYPE_%s, %s_values },\n", generate_what, type_ident);
    }
  if (gen_vars)
    {
      printf ("EELTYPEBUILTINS_VAR GType %s = 0;\n", type_macro);
    }
}

# skip scheme comments
";" {
  sub (";.*", "");
}

# parse keywords

/\(define-enum/ {
  if ($2 == "")
    printf ("huh? define-enum keyword without arg?\n") > "/dev/stderr";
  else
    {
      set_type($2);
      generate("ENUM");
    }
}

/\(define-flags/ {
  if ($2 == "")
    printf ("huh? define-flags keyword without arg?\n") > "/dev/stderr";
  else
    {
      set_type($2);
      generate("FLAGS");
    }
}

/\(define-boxed/ {
  if ($2 == "")
    printf ("huh? define-boxed keyword without arg?\n") > "/dev/stderr";
  else
      {
	  boxed_copy = "NULL";
	  boxed_free = "NULL";
	  set_type($2);
	  do {
	      getline;
	      sub (";.*", "", $0);
	  } while ($0 ~ /^[ \t]*$/);
	  tmp_var1 = $1;
	  if ($0 ~ /\)/) { generate("BOXED"); next; }
	  do {
	      getline;
	      sub (";.*", "", $0);
	  } while ($0 ~ /^[ \t]*$/);
	  tmp_var2 = $1;
	  sub (/\).*/, "", tmp_var2);
	  if (tmp_var1 ~ /^[_A-Za-z][_A-Za-z0-9]*$/ &&
	      tmp_var2 ~ /^[_A-Za-z][_A-Za-z0-9]*$/)
	      {
		  boxed_copy = tmp_var1;
		  boxed_free = tmp_var2;
		  # printf ("read boxed funcs: %s %s\n", boxed_copy, boxed_free) > "/dev/stderr";
	      }
	  generate("BOXED");
      }
}

END {
  if (gen_macros)
    printf("\n#define\tEEL_TYPE_N_BUILTINS\t(%u)\n", type_counter);
}