/**
 * Copyright (C) 1999, 2000, 2001  Free Software Foundation, Inc.
 *
 * This file is part of GNU gengetopt 
 *
 * GNU gengetopt is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2, or (at your option) 
 * any later version. 
 *
 * GNU gengetopt is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details. 
 *
 * You should have received a copy of the GNU General Public License along 
 * with gengetopt; see the file COPYING. If not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 */

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

extern int yyparse () ;

void gengetopt_free (void);

#include "argsdef.h"
#include "ggos.h"
#include "gm.h"

/* The following one is generated by gengetopt itself */
#include "cmdline.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gengetopt.h"

#ifndef HAVE_STRDUP
extern char *strdup (const char *s) ;
#endif

#define DEFAULT_HEADER_EXT "h"
#define DEFAULT_C_EXT "c"

struct gengetopt_option * gengetopt_options = NULL;
char * gengetopt_package = NULL;
char * gengetopt_version = NULL;
char * gengetopt_purpose = NULL;
int gengetopt_count_line = 1;

int canonize_vars (void);

extern int reportbugs_text_length;
extern char *reportbugs_text[];
extern int copyright_text_length;
extern char *copyright_text[];

static void print_copyright();
static void print_reportbugs();

int
main (int argc, char **argv)
{
  struct gengetopt_args_info args_info ;
  char *cmdline_parser_name ; /* name of the generated function */
  char *cmdline_filename ; /* name of generated file */
  char **comment ;
  int i, len ;
  FILE *input_file ;

  if (cmdline_parser (argc, argv, &args_info) != 0)
    {
      fprintf (stderr, "Run gengetopt --help to see the list of options.\n");
      exit(1) ;
    }

  if (args_info.help_given)
  {
    printf ("GNU ");
    cmdline_parser_print_help ();
    print_reportbugs ();
    exit (0);
  }

  if (args_info.version_given)
  {
    printf ("GNU ");
    cmdline_parser_print_version ();
    print_copyright ();
    exit (0);
  }

  cmdline_parser_name = args_info.func_name_arg ;
  cmdline_filename = args_info.file_name_arg ;

  switch  (gengetopt_add_option ("help", 'h', "Print help and exit", ARG_NO, 0, 0, 0))
  {
  case 1: fprintf (stderr, "gengetopt: line %d: not enough memory\n",
		   gengetopt_count_line);
	  return 1;
  case 2:
  case 3:
  case 4: fprintf (stderr, "gengetopt: bug found in %s:%d!!\n", __FILE__, __LINE__);
	  abort ();
  }
  switch  (gengetopt_add_option ("version", 'V', "Print version and exit", ARG_NO, 0, 0, 0))
  {
  case 1: fprintf (stderr, "gengetopt: line %d: not enough memory\n",
		   gengetopt_count_line);
	  return 1;
  case 2:
  case 3:
  case 4: fprintf (stderr, "gengetopt: bug found in %s:%d!!\n", __FILE__, __LINE__);
	  abort ();
  }

  if ( args_info.input_arg )
    {
      input_file = freopen (args_info.input_arg, "r", stdin) ;
      if (!input_file)
        {
          fprintf (stderr, "Error opening input file: %s\n", 
                   args_info.input_arg);
          exit (1);
        }
    } /* else standard input is used */

  if (yyparse ()) {
	gengetopt_free ();
	return 1;
  }

  if (canonize_vars ()) {
	gengetopt_free ();
	return 1;
  }

  comment = (char **)( malloc ( 3*sizeof(char *) ) ) ;
  /* one for our added line, and one for termination string */
  comment[0] = "generated with the following command:" ;
  len = 0 ;
  for ( i = 0; i < argc ; ++i )
    len += strlen (argv[i]) + 1 ; /* +1 is for added space */

  comment[1] = (char *) malloc (len * sizeof (char)) ;
  comment[1][0] = 0;

  for ( i = 0; i < argc ; ++i )
    {
      strcat (comment[1], argv[i]) ;
      strcat (comment[1], " ") ;
    }
  comment[2] = NULL ;

  if (generate_cmdline_parser (cmdline_parser_name,
                               args_info.unamed_opts_given,
                               cmdline_filename,
                               DEFAULT_HEADER_EXT,
                               DEFAULT_C_EXT,
                               args_info.long_help_given,
                               args_info.no_handle_help_given,
                               args_info.no_handle_version_given,
                               args_info.no_handle_error_given,
                               comment))
    {
	gengetopt_free ();
	return 1;
    }

  gengetopt_free ();

  return 0;
}


/* ************* */

int
gengetopt_define_package (char * s)
{
	gengetopt_package = strdup (s);
	if (gengetopt_package == NULL)
		return 1;
	return 0;
}

int
gengetopt_define_version (char * s)
{
	gengetopt_version = strdup (s);
	if (gengetopt_version == NULL)
		return 1;
	return 0;
}

int
gengetopt_define_purpose (char * s)
{
  gengetopt_purpose = strdup (s);
  if (gengetopt_purpose == NULL)
    return 1;
  return 0;
}

int
gengetopt_add_option (char * long_opt, char short_opt, char * desc,
		      int type, int flagstat, int required,
                      char * default_value)
{
	struct gengetopt_option * n;

	if (long_opt == NULL || long_opt[0] == 0 ||
	    desc == NULL)
		return 4;

	/* search for collisions */
	for (n = gengetopt_options; n != NULL; n = n->next)
	{
		if (!strcmp (n->long_opt, long_opt)) return 2;
        if (short_opt
            && n->short_opt == short_opt)
            return 3;
	}

	n = malloc (sizeof (struct gengetopt_option));
	if (n == NULL) return 1;

	n->long_opt = strdup (long_opt);
	if (n->long_opt == NULL) {
		free (n);
		return 1;
	}

	n->desc = strdup (desc);
	if (n->desc == NULL) {
		free (n->long_opt);
		free (n);
		return 1;
	}
	
	n->short_opt = ((short_opt == '-') ? 0 : short_opt);
	n->type = type;
	n->flagstat = flagstat;
        n->required = required;
        n->default_string = 0;
        n->default_given = (default_value != 0);
        if (n->default_given)
          {
            if (type == ARG_STRING)
              n->default_string = strdup (default_value);
            else
              n->default_num = atof (default_value);
          }
	n->next = NULL;
	n->var_arg = NULL;

	/* if empty stack */
	if (gengetopt_options == NULL)
		gengetopt_options = n;
	else {
		struct gengetopt_option * p = gengetopt_options;
		while (p->next != NULL) p = p->next;
		p->next = n;
	}
	return 0;
}


void
gengetopt_free (void)
{
  struct gengetopt_option *p, *pnext;

  if (gengetopt_package != NULL) free (gengetopt_package);
  for (p = gengetopt_options; p != NULL; p = pnext)
  {
	pnext = p->next;
	if (p->long_opt != NULL) free (p->long_opt);
	if (p->desc != NULL) free (p->desc);
	if (p->var_arg != NULL) free (p->var_arg);
	free (p);
  }
}


int
canonize_vars (void)
{
  struct gengetopt_option *p;
  char *pvar;

  if (gengetopt_options == NULL) {
	printf ("gengetopt: bug found in %s:%d!!\n", __FILE__, __LINE__);
	abort ();
  }

  for (p = gengetopt_options; p != NULL; p = p->next)
  {
    p->var_arg = strdup (p->long_opt);
    if (p->var_arg == NULL) {
	printf ("gengetopt: not enough memory to canonize vars\n");
	return 1;
    }

    for (pvar = p->var_arg; *pvar; pvar++)
      if (*pvar == '.' || *pvar == '-') *pvar = '_';
  }
  return 0;
}

void
print_copyright()
{
  int i;

  for (i = 1; i <= copyright_text_length; ++i)
    printf("%s\n", copyright_text[i]);
}

void
print_reportbugs()
{
  int i;

  for (i = 1; i <= reportbugs_text_length; ++i)
    printf("%s\n", reportbugs_text[i]);
}
