/*
  File autogenerated by gengetopt 
  generated with the following command:
  gengetopt -g 

  The developers of gengetopt consider the fixed text that goes in all
  gengetopt output files to be in the public domain:
  we make no copyright claims on it.
*/

/* If we use autoconf.  */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

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

#include "getopt.h"

#include "cmdline.h"

const char *gengetopt_args_info_purpose = "A modular realtime audio processing system";

const char *gengetopt_args_info_usage = "Usage: ingen [OPTIONS]...";

const char *gengetopt_args_info_description = "Ingen can be run in various configurations. The engine can\nrun as a stand-alone server controlled by OSC, or internal to\nanother process (e.g. the GUI).  The GUI can communicate with the engine\nvia either method, and many GUIs (or other things) may connect to an\nengine via OSC.\n\nExamples:\n\n  ingen -e                     - Run an engine, listen for OSC           \n  ingen -g                     - Run a GUI, connect via OSC            \n  ingen -eg                    - Run an engine and a GUI in one process\n\nThe -l (load) option can be used in all cases:\n	\n  ingen -el patch.ingen.ttl    - Run an engine and load a patch\n  ingen -gl patch.ingen.ttl    - Run a GUI and load a patch\n  ingen -egl patch.ingen.ttl   - Run an engine and a GUI and load a patch\n\nOptions:\n";

const char *gengetopt_args_info_help[] = {
  "  -h, --help              Print help and exit",
  "  -V, --version           Print version and exit",
  "  -C, --client-port=INT   Client OSC port",
  "  -c, --connect=STRING    Connect to existing engine at URI  \n                            (default=`osc.udp://localhost:16180')",
  "  -e, --engine            Run (JACK) engine  (default=off)",
  "  -E, --engine-port=INT   Engine OSC port  (default=`16180')",
  "  -g, --gui               Launch the GTK graphical interface  (default=off)",
  "  -n, --jack-name=STRING  JACK client name  (default=`ingen')",
  "  -l, --load=STRING       Load patch",
  "  -p, --parallelism=INT   Number of concurrent process threads  (default=`1')",
  "  -L, --path=STRING       Target path for loaded patch",
  "  -r, --run=STRING        Run script",
    0
};

typedef enum {ARG_NO
  , ARG_FLAG
  , ARG_STRING
  , ARG_INT
} cmdline_parser_arg_type;

static
void clear_given (struct gengetopt_args_info *args_info);
static
void clear_args (struct gengetopt_args_info *args_info);

static int
cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
                        struct cmdline_parser_params *params, const char *additional_error);


static char *
gengetopt_strdup (const char *s);

static
void clear_given (struct gengetopt_args_info *args_info)
{
  args_info->help_given = 0 ;
  args_info->version_given = 0 ;
  args_info->client_port_given = 0 ;
  args_info->connect_given = 0 ;
  args_info->engine_given = 0 ;
  args_info->engine_port_given = 0 ;
  args_info->gui_given = 0 ;
  args_info->jack_name_given = 0 ;
  args_info->load_given = 0 ;
  args_info->parallelism_given = 0 ;
  args_info->path_given = 0 ;
  args_info->run_given = 0 ;
}

static
void clear_args (struct gengetopt_args_info *args_info)
{
  args_info->client_port_orig = NULL;
  args_info->connect_arg = gengetopt_strdup ("osc.udp://localhost:16180");
  args_info->connect_orig = NULL;
  args_info->engine_flag = 0;
  args_info->engine_port_arg = 16180;
  args_info->engine_port_orig = NULL;
  args_info->gui_flag = 0;
  args_info->jack_name_arg = gengetopt_strdup ("ingen");
  args_info->jack_name_orig = NULL;
  args_info->load_arg = NULL;
  args_info->load_orig = NULL;
  args_info->parallelism_arg = 1;
  args_info->parallelism_orig = NULL;
  args_info->path_arg = NULL;
  args_info->path_orig = NULL;
  args_info->run_arg = NULL;
  args_info->run_orig = NULL;
  
}

static
void init_args_info(struct gengetopt_args_info *args_info)
{


  args_info->help_help = gengetopt_args_info_help[0] ;
  args_info->version_help = gengetopt_args_info_help[1] ;
  args_info->client_port_help = gengetopt_args_info_help[2] ;
  args_info->connect_help = gengetopt_args_info_help[3] ;
  args_info->engine_help = gengetopt_args_info_help[4] ;
  args_info->engine_port_help = gengetopt_args_info_help[5] ;
  args_info->gui_help = gengetopt_args_info_help[6] ;
  args_info->jack_name_help = gengetopt_args_info_help[7] ;
  args_info->load_help = gengetopt_args_info_help[8] ;
  args_info->parallelism_help = gengetopt_args_info_help[9] ;
  args_info->path_help = gengetopt_args_info_help[10] ;
  args_info->run_help = gengetopt_args_info_help[11] ;
  
}

void
cmdline_parser_print_version (void)
{
  printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
}

static void print_help_common(void) {
  cmdline_parser_print_version ();

  if (strlen(gengetopt_args_info_purpose) > 0)
    printf("\n%s\n", gengetopt_args_info_purpose);

  if (strlen(gengetopt_args_info_usage) > 0)
    printf("\n%s\n", gengetopt_args_info_usage);

  printf("\n");

  if (strlen(gengetopt_args_info_description) > 0)
    printf("%s\n\n", gengetopt_args_info_description);
}

void
cmdline_parser_print_help (void)
{
  int i = 0;
  print_help_common();
  while (gengetopt_args_info_help[i])
    printf("%s\n", gengetopt_args_info_help[i++]);
}

void
cmdline_parser_init (struct gengetopt_args_info *args_info)
{
  clear_given (args_info);
  clear_args (args_info);
  init_args_info (args_info);
}

void
cmdline_parser_params_init(struct cmdline_parser_params *params)
{
  if (params)
    { 
      params->override = 0;
      params->initialize = 1;
      params->check_required = 1;
      params->check_ambiguity = 0;
      params->print_errors = 1;
    }
}

struct cmdline_parser_params *
cmdline_parser_params_create(void)
{
  struct cmdline_parser_params *params = 
    (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
  cmdline_parser_params_init(params);  
  return params;
}

static void
free_string_field (char **s)
{
  if (*s)
    {
      free (*s);
      *s = 0;
    }
}


static void
cmdline_parser_release (struct gengetopt_args_info *args_info)
{

  free_string_field (&(args_info->client_port_orig));
  free_string_field (&(args_info->connect_arg));
  free_string_field (&(args_info->connect_orig));
  free_string_field (&(args_info->engine_port_orig));
  free_string_field (&(args_info->jack_name_arg));
  free_string_field (&(args_info->jack_name_orig));
  free_string_field (&(args_info->load_arg));
  free_string_field (&(args_info->load_orig));
  free_string_field (&(args_info->parallelism_orig));
  free_string_field (&(args_info->path_arg));
  free_string_field (&(args_info->path_orig));
  free_string_field (&(args_info->run_arg));
  free_string_field (&(args_info->run_orig));
  
  

  clear_given (args_info);
}


static void
write_into_file(FILE *outfile, const char *opt, const char *arg, char *values[])
{
  if (arg) {
    fprintf(outfile, "%s=\"%s\"\n", opt, arg);
  } else {
    fprintf(outfile, "%s\n", opt);
  }
}


int
cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
{
  int i = 0;

  if (!outfile)
    {
      fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
      return EXIT_FAILURE;
    }

  if (args_info->help_given)
    write_into_file(outfile, "help", 0, 0 );
  if (args_info->version_given)
    write_into_file(outfile, "version", 0, 0 );
  if (args_info->client_port_given)
    write_into_file(outfile, "client-port", args_info->client_port_orig, 0);
  if (args_info->connect_given)
    write_into_file(outfile, "connect", args_info->connect_orig, 0);
  if (args_info->engine_given)
    write_into_file(outfile, "engine", 0, 0 );
  if (args_info->engine_port_given)
    write_into_file(outfile, "engine-port", args_info->engine_port_orig, 0);
  if (args_info->gui_given)
    write_into_file(outfile, "gui", 0, 0 );
  if (args_info->jack_name_given)
    write_into_file(outfile, "jack-name", args_info->jack_name_orig, 0);
  if (args_info->load_given)
    write_into_file(outfile, "load", args_info->load_orig, 0);
  if (args_info->parallelism_given)
    write_into_file(outfile, "parallelism", args_info->parallelism_orig, 0);
  if (args_info->path_given)
    write_into_file(outfile, "path", args_info->path_orig, 0);
  if (args_info->run_given)
    write_into_file(outfile, "run", args_info->run_orig, 0);
  

  i = EXIT_SUCCESS;
  return i;
}

int
cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
{
  FILE *outfile;
  int i = 0;

  outfile = fopen(filename, "w");

  if (!outfile)
    {
      fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
      return EXIT_FAILURE;
    }

  i = cmdline_parser_dump(outfile, args_info);
  fclose (outfile);

  return i;
}

void
cmdline_parser_free (struct gengetopt_args_info *args_info)
{
  cmdline_parser_release (args_info);
}

/** @brief replacement of strdup, which is not standard */
char *
gengetopt_strdup (const char *s)
{
  char *result = NULL;
  if (!s)
    return result;

  result = (char*)malloc(strlen(s) + 1);
  if (result == (char*)0)
    return (char*)0;
  strcpy(result, s);
  return result;
}

int
cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
{
  return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
}

int
cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info,
                   struct cmdline_parser_params *params)
{
  int result;
  result = cmdline_parser_internal (argc, argv, args_info, params, NULL);

  if (result == EXIT_FAILURE)
    {
      cmdline_parser_free (args_info);
      exit (EXIT_FAILURE);
    }
  
  return result;
}

int
cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
{
  int result;
  struct cmdline_parser_params params;
  
  params.override = override;
  params.initialize = initialize;
  params.check_required = check_required;
  params.check_ambiguity = 0;
  params.print_errors = 1;

  result = cmdline_parser_internal (argc, argv, args_info, &params, NULL);

  if (result == EXIT_FAILURE)
    {
      cmdline_parser_free (args_info);
      exit (EXIT_FAILURE);
    }
  
  return result;
}

int
cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
{
  return EXIT_SUCCESS;
}


static char *package_name = 0;

/**
 * @brief updates an option
 * @param field the generic pointer to the field to update
 * @param orig_field the pointer to the orig field
 * @param field_given the pointer to the number of occurrence of this option
 * @param prev_given the pointer to the number of occurrence already seen
 * @param value the argument for this option (if null no arg was specified)
 * @param possible_values the possible values for this option (if specified)
 * @param default_value the default value (in case the option only accepts fixed values)
 * @param arg_type the type of this option
 * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
 * @param override @see cmdline_parser_params.override
 * @param no_free whether to free a possible previous value
 * @param multiple_option whether this is a multiple option
 * @param long_opt the corresponding long option
 * @param short_opt the corresponding short option (or '-' if none)
 * @param additional_error possible further error specification
 */
static
int update_arg(void *field, char **orig_field,
               unsigned int *field_given, unsigned int *prev_given, 
               char *value, char *possible_values[], const char *default_value,
               cmdline_parser_arg_type arg_type,
               int check_ambiguity, int override,
               int no_free, int multiple_option,
               const char *long_opt, char short_opt,
               const char *additional_error)
{
  char *stop_char = 0;
  const char *val = value;
  int found;
  char **string_field;

  stop_char = 0;
  found = 0;

  if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
    {
      if (short_opt != '-')
        fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", 
               package_name, long_opt, short_opt,
               (additional_error ? additional_error : ""));
      else
        fprintf (stderr, "%s: `--%s' option given more than once%s\n", 
               package_name, long_opt,
               (additional_error ? additional_error : ""));
      return 1; /* failure */
    }

    
  if (field_given && *field_given && ! override)
    return 0;
  if (prev_given)
    (*prev_given)++;
  if (field_given)
    (*field_given)++;
  if (possible_values)
    val = possible_values[found];

  switch(arg_type) {
  case ARG_FLAG:
    *((int *)field) = !*((int *)field);
    break;
  case ARG_INT:
    if (val) *((int *)field) = strtol (val, &stop_char, 0);
    break;
  case ARG_STRING:
    if (val) {
      string_field = (char **)field;
      if (!no_free && *string_field)
        free (*string_field); /* free previous string */
      *string_field = gengetopt_strdup (val);
    }
    break;
  default:
    break;
  };

  /* check numeric conversion */
  switch(arg_type) {
  case ARG_INT:
    if (val && !(stop_char && *stop_char == '\0')) {
      fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
      return 1; /* failure */
    }
    break;
  default:
    ;
  };

  /* store the original value */
  switch(arg_type) {
  case ARG_NO:
  case ARG_FLAG:
    break;
  default:
    if (value && orig_field) {
      if (no_free) {
        *orig_field = value;
      } else {
        if (*orig_field)
          free (*orig_field); /* free previous string */
        *orig_field = gengetopt_strdup (value);
      }
    }
  };

  return 0; /* OK */
}


int
cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
                        struct cmdline_parser_params *params, const char *additional_error)
{
  int c;	/* Character of the parsed option.  */

  int error = 0;
  struct gengetopt_args_info local_args_info;
  
  int override;
  int initialize;
  int check_required;
  int check_ambiguity;
  
  package_name = argv[0];
  
  override = params->override;
  initialize = params->initialize;
  check_required = params->check_required;
  check_ambiguity = params->check_ambiguity;

  if (initialize)
    cmdline_parser_init (args_info);

  cmdline_parser_init (&local_args_info);

  optarg = 0;
  optind = 0;
  opterr = params->print_errors;
  optopt = '?';

  while (1)
    {
      int option_index = 0;

      static struct option long_options[] = {
        { "help",	0, NULL, 'h' },
        { "version",	0, NULL, 'V' },
        { "client-port",	1, NULL, 'C' },
        { "connect",	1, NULL, 'c' },
        { "engine",	0, NULL, 'e' },
        { "engine-port",	1, NULL, 'E' },
        { "gui",	0, NULL, 'g' },
        { "jack-name",	1, NULL, 'n' },
        { "load",	1, NULL, 'l' },
        { "parallelism",	1, NULL, 'p' },
        { "path",	1, NULL, 'L' },
        { "run",	1, NULL, 'r' },
        { NULL,	0, NULL, 0 }
      };

      c = getopt_long (argc, argv, "hVC:c:eE:gn:l:p:L:r:", long_options, &option_index);

      if (c == -1) break;	/* Exit from `while (1)' loop.  */

      switch (c)
        {
        case 'h':	/* Print help and exit.  */
          cmdline_parser_print_help ();
          cmdline_parser_free (&local_args_info);
          exit (EXIT_SUCCESS);

        case 'V':	/* Print version and exit.  */
          cmdline_parser_print_version ();
          cmdline_parser_free (&local_args_info);
          exit (EXIT_SUCCESS);

        case 'C':	/* Client OSC port.  */
        
        
          if (update_arg( (void *)&(args_info->client_port_arg), 
               &(args_info->client_port_orig), &(args_info->client_port_given),
              &(local_args_info.client_port_given), optarg, 0, 0, ARG_INT,
              check_ambiguity, override, 0, 0,
              "client-port", 'C',
              additional_error))
            goto failure;
        
          break;
        case 'c':	/* Connect to existing engine at URI.  */
        
        
          if (update_arg( (void *)&(args_info->connect_arg), 
               &(args_info->connect_orig), &(args_info->connect_given),
              &(local_args_info.connect_given), optarg, 0, "osc.udp://localhost:16180", ARG_STRING,
              check_ambiguity, override, 0, 0,
              "connect", 'c',
              additional_error))
            goto failure;
        
          break;
        case 'e':	/* Run (JACK) engine.  */
        
        
          if (update_arg((void *)&(args_info->engine_flag), 0, &(args_info->engine_given),
              &(local_args_info.engine_given), optarg, 0, 0, ARG_FLAG,
              check_ambiguity, override, 1, 0, "engine", 'e',
              additional_error))
            goto failure;
        
          break;
        case 'E':	/* Engine OSC port.  */
        
        
          if (update_arg( (void *)&(args_info->engine_port_arg), 
               &(args_info->engine_port_orig), &(args_info->engine_port_given),
              &(local_args_info.engine_port_given), optarg, 0, "16180", ARG_INT,
              check_ambiguity, override, 0, 0,
              "engine-port", 'E',
              additional_error))
            goto failure;
        
          break;
        case 'g':	/* Launch the GTK graphical interface.  */
        
        
          if (update_arg((void *)&(args_info->gui_flag), 0, &(args_info->gui_given),
              &(local_args_info.gui_given), optarg, 0, 0, ARG_FLAG,
              check_ambiguity, override, 1, 0, "gui", 'g',
              additional_error))
            goto failure;
        
          break;
        case 'n':	/* JACK client name.  */
        
        
          if (update_arg( (void *)&(args_info->jack_name_arg), 
               &(args_info->jack_name_orig), &(args_info->jack_name_given),
              &(local_args_info.jack_name_given), optarg, 0, "ingen", ARG_STRING,
              check_ambiguity, override, 0, 0,
              "jack-name", 'n',
              additional_error))
            goto failure;
        
          break;
        case 'l':	/* Load patch.  */
        
        
          if (update_arg( (void *)&(args_info->load_arg), 
               &(args_info->load_orig), &(args_info->load_given),
              &(local_args_info.load_given), optarg, 0, 0, ARG_STRING,
              check_ambiguity, override, 0, 0,
              "load", 'l',
              additional_error))
            goto failure;
        
          break;
        case 'p':	/* Number of concurrent process threads.  */
        
        
          if (update_arg( (void *)&(args_info->parallelism_arg), 
               &(args_info->parallelism_orig), &(args_info->parallelism_given),
              &(local_args_info.parallelism_given), optarg, 0, "1", ARG_INT,
              check_ambiguity, override, 0, 0,
              "parallelism", 'p',
              additional_error))
            goto failure;
        
          break;
        case 'L':	/* Target path for loaded patch.  */
        
        
          if (update_arg( (void *)&(args_info->path_arg), 
               &(args_info->path_orig), &(args_info->path_given),
              &(local_args_info.path_given), optarg, 0, 0, ARG_STRING,
              check_ambiguity, override, 0, 0,
              "path", 'L',
              additional_error))
            goto failure;
        
          break;
        case 'r':	/* Run script.  */
        
        
          if (update_arg( (void *)&(args_info->run_arg), 
               &(args_info->run_orig), &(args_info->run_given),
              &(local_args_info.run_given), optarg, 0, 0, ARG_STRING,
              check_ambiguity, override, 0, 0,
              "run", 'r',
              additional_error))
            goto failure;
        
          break;

        case 0:	/* Long option with no short option */
        case '?':	/* Invalid option.  */
          /* `getopt_long' already printed an error message.  */
          goto failure;

        default:	/* bug: option not considered.  */
          fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
          abort ();
        } /* switch */
    } /* while */




  cmdline_parser_release (&local_args_info);

  if ( error )
    return (EXIT_FAILURE);

  return 0;

failure:
  
  cmdline_parser_release (&local_args_info);
  return (EXIT_FAILURE);
}