-- | Generate an option parser as a function of the given name, that
-- accepts the given command line options.  The result is a function
-- that should be called with @argc@ and @argv@.  The function returns
-- the number of @argv@ elements that have been processed.
--
-- If option parsing fails for any reason, the entire process will
-- terminate with error code 1.
generateOptionParser :: String -> [Option] -> C.Func
generateOptionParser fname options =
  [C.cfun|int $id:fname(int argc, char* const argv[]) {
       int $id:chosen_option;

       static struct option long_options[] = { $inits:option_fields, {0, 0, 0, 0} };

       while (($id:chosen_option =
                 getopt_long(argc, argv, $string:option_string, long_options, NULL)) != -1) {
         $stms:option_applications
         if ($id:chosen_option == ':') {
           errx(-1, "Missing argument for option %s", argv[optind-1]);
         }
         if ($id:chosen_option == '?') {
           errx(-1, "Unknown option %s", argv[optind-1]);
         }
       }
       return optind;
     }
         |]
  where chosen_option = "ch"
        option_string = ':' : optionString options
        option_applications = optionApplications chosen_option options
        option_fields = optionFields options
generateOptionParser :: String -> [Option] -> C.Func
generateOptionParser fname options =
  [C.cfun|int $id:fname(int argc, char* const argv[]) {
       int $id:chosen_option;

       static struct option long_options[] = { $inits:option_fields, {0, 0, 0, 0} };

       while (($id:chosen_option =
                 getopt_long(argc, argv, $string:option_string, long_options, NULL)) != -1) {
         $stms:option_applications
         if ($id:chosen_option == ':') {
           errx(-1, "Missing argument for option %s", argv[optind-1]);
         }
         if ($id:chosen_option == '?') {
           errx(-1, "Unknown option %s", argv[optind-1]);
         }
       }
       return optind;
     }
         |]
  where chosen_option = "ch"
        option_string = ':' : optionString options
        option_applications = optionApplications chosen_option options
        option_fields = optionFields options
generateOptionParser fname options =
  [C.cfun|int $id:fname(int argc, char* const argv[]) {
       int $id:chosen_option;

       static struct option long_options[] = { $inits:option_fields, {0, 0, 0, 0} };

       while (($id:chosen_option =
                 getopt_long(argc, argv, $string:option_string, long_options, NULL)) != -1) {
         $stms:option_applications
         if ($id:chosen_option == ':') {
           errx(-1, "Missing argument for option %s", argv[optind-1]);
         }
         if ($id:chosen_option == '?') {
           errx(-1, "Unknown option %s", argv[optind-1]);
         }
       }
       return optind;
     }
         |]
  where chosen_option = "ch"
        option_string = ':' : optionString options
        option_applications = optionApplications chosen_option options
        option_fields = optionFields options