/*
 NAME 
	poptitem-test.m - test program for PoptItem class
 VERSION
	$Id$
 CHANGELOG
	$Log$
 NOTE
	This test program is copied from `test1.c' distributed with
	popt 1.6.2 package.
 */

#include <coconut/coptparser.h>
#include <stdlib.h>

static void option_callback(poptContext con, int reason, struct poptOption *opt,
  char *arg, void *data) ;

static const char s_thisfile[] = "optparser.h" ;

static const int CB_ID		= (int) 'c' ;
static const int CB2_ID		= (int) 'c' ;
static const int LONG_ID	= (int) 'l' ;

static int	arg1 = 0 ;
static char *	arg2 = "(none)" ;
static int 	arg3 = 0 ;
static int 	inc = 0 ;
static int 	shortopt = 0 ;
static float	afloat = 0.0 ;
static double	adouble = 0.0 ;
static char *	ostr = (char *) -1 ;
static int 	singledash = 0 ;

static int pass2 = 0 ;

static void reset_vars(void) ;

static void reset_vars(void)
{
	arg1 = 0 ;
	arg2 = "(none)" ;
	arg3 = 0 ;
	inc  = 0 ;
	shortopt = 0 ;
	afloat = 0.0 ;
	adouble = 0.0 ;
	singledash = 0 ;
	pass2 = 0 ;
}

int main(int argc, const char **argv)
{
	id 		callbackargs, morecallbackargs, moreargs, options ;
	id <PError>	err ;
	int 		rc ;
	int 		ec = 0 ;
	const char ** 	rest ;
	int 		help = 0 ;
	int 		usage = 0 ;
	char 		errmsg[256] ;

	fprintf(stderr, "*** test program for COptParser class\n") ;
	options = [[COptParser alloc] init] ;
	morecallbackargs = [[COptParser alloc] init] ;
	callbackargs = [[COptParser alloc] init] ;
	moreargs = [[COptParser alloc] init] ;

	// make morecallbackargs
	[morecallbackargs setCallbackFunc: &option_callback param: NULL] ;
	[morecallbackargs defineOption: string_arg code: CB2_ID
 	  long_name: "cb2" short_name: 'c' result: NULL
	  desc: "Test argument callbacks" arg_desc: NULL] ;
	[morecallbackargs finishOption] ;

	// make callbackargs
	[callbackargs setCallbackFunc: &option_callback param: "sampledata"] ;
	[callbackargs defineOption: string_arg code: CB_ID 
 	  long_name: "cb" short_name: 'c' result: NULL 
	  desc: "Test argument callbacks" arg_desc:NULL] ;
	[callbackargs defineOption: none_arg code: LONG_ID 
	  long_name: "long" short_name:'\0' result:NULL 
	  desc: "Unused option for help testing" arg_desc: NULL] ;
	[callbackargs finishOption] ;

	// make moreargs
	[moreargs defineOption: none_arg code: 0 
	  long_name: "inc" 
	  short_name: 'i'
	  result: &inc 
	  desc: "An included argument" 
	  arg_desc: NULL] ;
	[moreargs finishOption] ;

	// make options
	[options includeOptions: morecallbackargs desc: "arg for cb2"] ;
	[options defineOption: none_arg code: 0 
  	  long_name: "arg1" short_name: '\0' result: &arg1 
	  desc:"First argument with a really long"
	  " description. After all, we have to test argument help"
	  " wrapping somehow, right?"
	  arg_desc: NULL] ;
	[options defineOption: string_arg code:0 
	  long_name: "arg2" short_name: '2' result: &arg2 
	  desc: "Another argument" arg_desc: NULL ] ;
	[options defineOption: int_arg code: 0 
	  long_name: "arg3" short_name: '3' result: &arg3 
	  desc: "A third argument" arg_desc:NULL ] ;
	[options defineOption: none_arg code:0 
	  long_name: "shortoption" short_name: '\0' result: &shortopt 
	  desc: "Needs a single -" arg_desc: NULL] ;
	[options setOnedashProperty] ;
	[options defineOption: string_arg code: 0 
	  long_name: "hidden" short_name: '\0' result: NULL 
	  desc: "This shouldn't show up" arg_desc: NULL] ;
	[options setDocHiddenProperty] ;
	[options defineOption: string_arg code:0 
	  long_name: "unused" short_name: '\0' result: NULL 
	  desc: "Unused option for help testing" arg_desc: "UNUSED" ];
	[options defineOption: float_arg code:0 
	  long_name: "float" short_name: 'f' result: &afloat 
	  desc: "A float argument" arg_desc: "FLOAT" ];
	[options defineOption: double_arg code:0 
	  long_name: "double" short_name: 'd' result: &adouble 
	  desc: "A double argument" arg_desc: "DOUBLE"] ;
	[options defineOption: string_arg code:0 
	  long_name: "ostr" 
	  short_name: '\0'
	  result: &ostr 
	  desc: "An optional str" 
	  arg_desc: "ARG"] ;
	[options setOptionalProperty] ;
	[options defineOption: none_arg code:0 
	  long_name: NULL 
	  short_name: '-'
	  result: &singledash 
	  desc: NULL
	  arg_desc: NULL] ;
	[options setDocHiddenProperty] ;
	[options includeOptions: moreargs desc: NULL] ;
	[options includeOptions: callbackargs 
	  desc: "Callback arguments" ] ;

	// setup analyzer
	reset_vars() ;
	[options startAnalysis: "optparser-test.out" argc:argc argv:argv] ;
	err = [options load: "./coptparser-test.rc"] ;
	if(err != nil){
		printf("ERROR: can not read config file\n"); 
	}

/*
	fprintf(stderr, "finished setup. item num: %d\n", [options elm_num]) ;
	[options print] ;
 */

#if 1
	while((rc = [options nextOpt]) < -1)
		;
	[options resetAnalysis] ;
	reset_vars() ;
#endif

/*
	fprintf(stderr, "moving into pass2 (help %d, usage %d)\n",help,usage) ;
 */
	pass2 = 1 ;
	if((rc = [options nextOpt]) < -1){
		[options getErrorMessage: errmsg size:256 code:rc] ;
		fprintf(stderr, "optparser-test.out: bad argument %s\n",
		  errmsg) ;
		ec = 2 ;
		goto exit ;
	}

	if(help){
		[options printHelp] ;
		goto exit ;
	}

	if(usage){
		[options printUsage] ;
		goto exit ;
	}

	fprintf(stdout, "arg1: %d arg2: %s", arg1, arg2) ;

	if(arg3) fprintf(stdout, " arg3: %d", arg3);
	if(inc)  fprintf(stdout, " inc: %d", inc);
	if(shortopt) fprintf(stdout, " short: %d", shortopt);
	if(afloat != 0.0) fprintf(stdout, " aFloat: %g", afloat);
	if(adouble != 0.0) fprintf(stdout, " aDouble: %g", adouble);
	if(ostr != (char *) -1) 
		fprintf(stdout, " oStr: %s", (ostr ? ostr : "(none)"));
	if(singledash)
		fprintf(stdout, " -");

	rest = [options allArgs] ;
	if(rest){
		fprintf(stdout, " rest:");
		while (*rest) {
			fprintf(stdout, " %s", *rest);
			rest++;
		}
	}

exit:
	[options free] ;

	fprintf(stderr, "\nbye\n") ;
	exit(ec) ;
}

static void option_callback(poptContext con, int reason, struct poptOption *opt,
  char *arg, void *data){
        if(pass2){
		printf("callback: %c %s %s ", opt->val, (char *) data, arg) ;
	}
}

