#!/bin/sh

ggo=cmdline.ggo

cat<<EOF
/* Generated by $0 on $(date) */
EOF

awk '
BEGIN { n = 0 }
/^option/ { 
  opt=$2
  split(opt, a, /\"/)
  optn=a[2]

  print "#define OPT_" optn "_type " n 
  print "static const char OPT_" optn "_name[] = \"" optn "\";"
  n = n + 1
} 
END {
  print "#define OPT_version_type " n 
  print "static const char OPT_version_name[] = \"version\";"
  n = n + 1
  print "#define OPT_help_type " n 
  print "static const char OPT_help_name[] = \"help\";"
  n = n + 1
}
' $ggo

awk '
BEGIN { n = 0 }
/^option/ { 
  opt=$2
  shrt=$3
  mult=0
  type="OPT_string"
  ext="_arg"
  def="0"
  req="0"
  inhelp=1
  help=""

  split(opt, a, /\"/)
  optn=a[2]

  for (x=4; x <= NF; x++) {
    if (inhelp == 1) {
      help=help " " $x
      if ($x ~ /\"$/) inhelp=0
    } else if ($x == "string") {
      type="OPT_string"
    } else if ($x == "int") {
      type="OPT_integer"
    } else if ($x == "long") {
      type="OPT_long"
    } else if ($x == "flag") {
      type="OPT_flag"
    } else if ($x == "off") {
      def="0"
      ext="_flag"
    } else if ($x == "on") {
      def="1"
    } else if ($x == "no") {
      req="0"
    } else if ($x == "multiple") {
      mult=1
    } else if ($x ~ "default=") {
      def=$x
      sub(/default=/,"",def)
    } else {
      print "Unhandled! " $x
    }
  }

  if (shrt == "-") shrt=0
  else {
    print "#define OPT_idx_" shrt " " n
  }

  if (type == "OPT_flag") {
    print "#define OPT_" optn "_set offsetof(struct gengetopt_args_info," optn ext "), -1, offsetof(struct gengetopt_args_info," optn "_given)"
  } else {
    print "#define OPT_" optn "_set offsetof(struct gengetopt_args_info," optn ext "), offsetof(struct gengetopt_args_info," optn "_orig), offsetof(struct gengetopt_args_info," optn "_given)"
  }
  n = n + 1
} 
END {
  print "#define OPT_version_set -1, -1, offsetof(struct gengetopt_args_info,version_given)"
  print "#define OPT_idx_V " n
  n = n + 1
  print "#define OPT_help_set -1, -1, offsetof(struct gengetopt_args_info,help_given)"
  print "#define OPT_idx_h " n
  n = n + 1
}
' $ggo

cat<<EOF
struct opt_def_t opts[] = {
EOF
awk '
BEGIN { 
  n = 0
  defs=""
}
/^option/ { 
  opt=$2
  shrt=$3
  mult=0
  type="OPT_string"
  def="0"
  req="0"
  inhelp=1
  help=""

  split(opt, a, /\"/)
  optn=a[2]

  for (x=4; x <= NF; x++) {
    if (inhelp == 1) {
      help=help " " $x
      if ($x ~ /\"$/) inhelp=0
    } else if ($x == "string") {
      type="OPT_string"
    } else if ($x == "int") {
      type="OPT_integer"
    } else if ($x == "long") {
      type="OPT_long"
    } else if ($x == "flag") {
      type="OPT_flag"
    } else if ($x == "off") {
      def="0"
    } else if ($x == "on") {
      def="1"
    } else if ($x == "no") {
      req="0"
    } else if ($x == "multiple") {
      mult=1
    } else if ($x ~ "default=") {
      def=$x
      sub(/default=/,"",def)
    } else {
      print "Unhandled! " $x
    }
  }

  if (shrt == "-") shrt=0
  else shrt="\"" shrt "\""

  if (def != "0") 
    defs=defs " OPT_generic(args_info,"n","def",0);"

  print "  { " type ", OPT_" optn "_name, " mult ", OPT_" optn "_set },"
  n = n + 1
}
END {
  print "  { OPT_flag, OPT_version_name, 0, OPT_version_set },"
  print "  { OPT_flag, OPT_help_name, 0, OPT_help_set },"
  print "};"
  print "#define getopt_DEFAULTS" defs
}
' $ggo

cat<<EOF
static struct option long_options[] = {
EOF
awk -v "q='" '
BEGIN { 
  n = 0
  options=""
  checks=""
}
/^option/ { 
  opt=$2
  shrt=$3
  args=1
  inhelp=1

  split(opt, a, /\"/)
  optn=a[2]

  for (x=4; x <= NF; x++) {
    if (inhelp == 1) {
      help=help " " $x
      if ($x ~ /\"$/) inhelp=0
    } else if ($x == "string") {
    } else if ($x == "int") {
    } else if ($x == "long") {
    } else if ($x == "flag") {
      args=0
    } else if ($x == "off") {
    } else if ($x == "on") {
    } else if ($x == "no") {
    } else if ($x == "multiple") {
    } else if ($x ~ "default=") {
    } else {
      print "Unhandled! " $x
    }
  }

  if (shrt == "-") shrt=0
  else {
    if (args == 1) {
      options=options shrt ":"
    } else {
      options=options shrt
    }
    checks=checks " case " q shrt q ": OPT_generic(args_info, OPT_idx_" shrt ", optarg, 1); break;"
    shrt=q shrt q
  }

  print "  { OPT_" optn "_name, " args ", NULL, " shrt " },"
  n = n + 1
}
END { 
  print "  { OPT_version_name, 0, NULL, " q "V" q " },"
  print "  { OPT_help_name, 0, NULL, " q "h" q " },"
  print "  { 0, 0, 0, 0 }"
  print "};"
  print "#define getopt_OPTIONS \"Vh" options "\""
  checks=checks " case " q "V" q ": OPT_generic(args_info, OPT_idx_V, optarg, 1); break;"
  checks=checks " case " q "h" q ": OPT_generic(args_info, OPT_idx_h, optarg, 1); break;"
  print "#define getopt_CHECKS" checks 
}
' $ggo
cat<<EOF
EOF

