#include <errmsg: see ... '~$ sh aaa.sh.c -h'   (other opt:no/-m/-w/)>	/*
C='^[/][/*]SH_';O=${0##*[/]};R=`dirname $0`;R=${R%/}/;R0=$R$O;Rb=$R${O%%.*};O="
";R=${0##*.};Rs=$Rb.$R;Rm=$Rb.tmp.$R;Rh=$Rb.h;R=$Rs$Rh$Rm;Rp='printf %s\n ';Rc=:
[ "${R##*$0*}" = '' ]&&$Rp"$0:NG suffix"&&exit 1;R='sed -ne ';Cm=$R'"/[E]ND/!d
:l;n;p;bl"<$R0>$Rm;$Rp"$Rm"';RB=$($R"s/${C}OP//p"<$R0|(F=mw;while read -r a b;do
B=${a%:};F=`$Rp"$F"|$R"s#$B:*##1;p"`${a%_};$Rp"C$B=\$(cat<<'E'$O$b${O}E$O)";done
$Rp"R1=$F"));Rw=$R'"/$C$R/!d;:l;n;/${C}ED/q;p;bl"<$R0';Cw="(R=LS;$Rw;$Rw>&3;R=HD
$Rw;R=SC;$Rw>&3)"'>$Rh 3>$Rs;$Rp"$Rh $Rs"';Re=eval\ ;$Re"$RB";while getopts $R1\
 R;do case $R in \?)exit 1;;*)$Re"O$R=\$OPTARG";Rc=$Rc$O`$Re'$Rp"$C'$R\"`;;esac
done;[ "$Rc" = : ]&&Rc=$Cm;shift $((OPTIND-1));$Re"$C_$O$Rc";exit   #END	*/

/*SH_LS*/
/* Copyright (C) 2020 Momi-g

 This program 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 3 of the License, or
 (at your option) any later version.

 This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*-*
@_name	OPTBOX_SET, OPTBOX_BASENAME, optbox
@auther momi-g
@brief	cmdline option parse func/macros consisting only of header file
@_synopsys
	#include "optbox.hpp"
	
	OPTBOX_SET(
	 ( clm1, clm2, clm3, clm4, clm5)
	 , ( clm1, clm2, clm3, clm4)
	 , ...
	);	//macro. clm cnt is 1-4 or 1-5.
	
	static optbox_t optbox_obj		//static val for optdata buffer
	static int optbox_err
	static optbox_t* optbox(char* mode, int *argc_p, char** *argv_p)
	
	//-- global func, getter/setter
	int optbox_geti(const char*)
	double optbox_getd(const char*)
	const char* optbox_gets(const char*)
	
	void* optbox_getptr(const char*)
	int optbox_geterr(const char*)
	
	int optbox_seti(const char*, int)
	int optbox_setd(const char*, double)
	int optbox_sets(const char*, const char*)
@_eg
	#include <stdio.h>
	#include "optbox.hpp"
	
	OPTBOX_SET(
	   ( help,  "-h", "0"     ,bool )
	 , ( count, "-n", "1"     ,int	,return (0<=i && i<=3) )
	 , ( file,  "-f", "a.ini" ,str	,if(strlen(s)>10){return 0;} )
	 , ( wait,  "-d", "0.3"   ,dbl	,if(0<d)	\
	 	{ return 1;}; return 0; )
	)
	int main(int argc, char** argv){
	 optbox_t* obj=optbox("", &argc, &argv);		// ""...parse mode setting

	 printf("%d\n", obj->help);		// 0 or 1. bool is treated as int.
	 printf("%d\n", obj->count);	// 0<=num<=3 
	 puts(obj->file);		// "a.ini" "cmdin.string"	etc
	 puts(argv[1]);	// ~$ a.out -h abc xyz >> ac==3, av[1]=="abc" ..shift args
	 return 0;
	}	// ~$ cc src.c && ./a.out -hd0.01 ag2 ag3 	>> header file only

@param clm1	option name used for access the parse result. no quotes.  
@param clm2	cmdline short option char. needs prefix hyphen '-'. needs quotes.
@param clm3	dfl val. needs quotes.
@param clm4	data type. select 'bool(on/off)/int/dbl/str'. no quotes.
@param clm5	optional. raw code you want to test. no quotes. expands as below.
 static int func_[clm1](const char* s){
	int i=atoi(s);double d=atof(s);
	--- expand [clm5] --- 
	;return 1;}		// ~$ a.out -n 32  >>  s == "32" 
	
 ..s is cmdin optarg. if rtn 0, raise err and exit. dfl setdata skips this test.

@param mode	flgchars for parse mode. dfl is "". allows "xq" chars.
 x: expantion. dfl mode works under the posix Utility Syntax Guidelines.
    'x' allows symbol charopt. '-@' '-_' '-+' '-=' etc. '--' works as optend.
    'x' parses until detect '--' or args end.	eg) a.out abc -h >> hit -h
 
 q: quiet. dfl mode outputs emsg to stderr and exit(1) if err. 'q' mode set
    err charcode to static var 'optbox_err' and stops emsg/exit. 
    eg) optbox("q", &ac,&av);if(optbox_err){printf("bad: -%c\n", optbox_err);}
  
@param argc_p/argv_p	parse target. optbox eats opt and shift rest args.
 eg) ./a.out -h -v ag_a ag_b	>> before/after: argv[1]=="-h" / "ag_a"

@return	ptr to static var, 'optbox_obj'. optbox() saves optdata to it.
 struct 'optbox_t' depends on OPTBOX_SET() setting.
 eg)
	OPTBOX_SET(
	 ( aaa, "-a", "0",     int, return (i !=5 ) ),
	 ( xyz, "-z", "alice", str)
	);		>>> (expands macro)
	
	typedef struct optbox_tag{
	 int aaa;		// type is set as 'int' by OPTBOX_SET macro
	 const char* aaa_dfl;	// lit "0", "0x123" etc
	 const char* aaa_cmdin;		//dfl:NULL. if cmdin '-a 3' exists, set to "3"
	  
	 const char* xyz;	//xyz: str
	 const char* xyz_dfl;
	 const char* xyz_cmdin;
	} optbox_t;
	static optbox_t optbox_obj={0};
 
 each opt has 3 data.
  optbox_obj.?	:int(bool)/double/const char*. dfl/cmdin parsed main value.
  optbox_obj.?_dfl	:const char*. dfl optarg str.
  optbox_obj.?_cmdin	:const char*. NULL(dfl) or cmdin optarg str.

@details
 - OPTBOX_SET() includes static func/value/type impl start with 'optbox', 
   optbox_t, optbox_err, optbox_test_func_XXX, etc.
   you can change name by redefine it before call OPTBOX_SET().
   	#undef OPTBOX_BASENAME
   	#define OPTBOX_BASENAME	obox123	//change to obox123_t, obox123_obj etc
   	OPTBOX_SET( ..
 - optbox() doesnt use getopt()/optarg/optind/opterr/optopt/malloc()
 - if you want to access optbox data from other srcfile, use getter/setter.
   optbox_geterr(void) rtns 1 if getter/setter failed. (same as sh-script $?)
   optbox_getptr() rtns static var ptr address, &(optbox_obj.help) etc.
 eg)
 --- aa.c (main)
 	#include "optbox.hpp"
 	#undef OPTBOX_BASENAME
 	#define OPTBOX_BASENAME	myopt
 	OPTBOX_SET(
 		(help, "-h", "0", bool),
 		(name, "-@", "alice", str, return(0<strlen(s)) )
	)
  	int main(int argc, char** argv){
 		myopt("x", &argc, &argv);	//parse
 		puts(myopt_obj.name);	//alice
 		myopt_obj.name = "bob";
 		myf();	//other src, bb.c
 		puts(myopt_obj.name);	//chris
 		return 0;
	}
 --- bb.c
	//	#include <stdio.h>	//uncmt if you want to stop compile warning
	//	const char* myopt_gets(const char*);
	//	int myopt_sets(const char*, const char*);
	//	int myopt_geterr(void);
	int myf(void){
		const char* s = myopt_gets("name");
		if(myopt_geterr() ){return 1;}	// set 1 if fail myopt_getX()
		puts(s);	//bob
		int rc = myopt_sets("name", "chris");	//setter rtns 0(suc)/1(fail)
		if(rc){return 1;}
		return 0;
	}
	//-- ~$cc a.c b.c && ./a.out
	
@_note
 - optbox is created with the following concept
 	- easy to set standard items such as '-h' and '-n 10'
	- support simple test such as int/str and range check
	- easy to access parse result
	- collect the setting information to reduce screen scroll
	- avoid forcing the complex apis and macro names

@conforming POSIX.1-2001+
@version 1.0.0, 2020-10-23
-*/
/*SH_ED*/

/*SH_HD*/
#ifndef a18d0ac31a24b
#define a18d0ac31a24b

#include <features.h>
#if ( _POSIX_C_SOURCE +0 < 200112L )
	#error	"needs compiler posix-2001 or upper"
	#include "//dmy inc, preprocess stopper"
#endif

#include <errno.h>
#define OPTBOX_ERR(xpr, msg, act)	do{if(xpr){ fprintf(stderr, \
	"ERR: %s %d: %s():%s msg:%s sys:%s\n",__FILE__,__LINE__, __func__,\
	"hit(" #xpr ")", msg, strerror(errno) );act ;} }while(0)

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

typedef int (*optboxtest_ft)(const char*);
typedef struct optboxifmt_tag {
	const char* name;
	const char* optstr;
	const char* dflstr;
	const char* tp;
	optboxtest_ft func;
	void*	p;	//& static XXobj.?	...obj.help, myopt.count etc
	const char*	*cmdin;	//& obj.?_cmdin	strnew
	const char* *dfl;	//& obj.?_dfl	strold
}optboxifmt_t;
// ini reqdata and raw address of target static obj member 

#ifndef OPTBOX_BASENAME
	#define OPTBOX_BASENAME optbox		//avoid static val collision 
#endif

#define OPTBOX_BN	OPTBOX_BASENAME

#define OPTBOX_UNAME(a,b,c)		OPTBOX_UNAMEsub(a,b,c)
#define OPTBOX_UNAMEsub(a,b,c)	a ## b ## c

#define OPTBOX_SET(...)	OPTBOX_UNIQUE(__VA_ARGS__) OPTBOX_TESTF(__VA_ARGS__) \
	OPTBOX_INIARR(__VA_ARGS__)  OPTBOX_APIF(__VA_ARGS__) OPTBOX_PARSEF(__VA_ARGS__)

#define OPTBOX_UNIQUE(...)	typedef struct OPTBOX_UNAME(OPTBOX_BN,_tag,){ \
	OPTBOX_ARGCNT(__VA_ARGS__)(T, __VA_ARGS__) } OPTBOX_UNAME(OPTBOX_BN,_t,); \
	static OPTBOX_UNAME(OPTBOX_BN,_t,) OPTBOX_UNAME(OPTBOX_BN,_obj,)={0}; \
	static int OPTBOX_UNAME(OPTBOX_BN,_err,)=0;
#define	TOPTBOX_INI(a,b,c,d,...)	OPTBOX_##d a;const char* a##_cmdin;const char* a##_dfl;
#define OPTBOX_int	int
#define OPTBOX_dbl	double
#define OPTBOX_str	const char*
#define OPTBOX_bool	int

//tpの後じゃないとstatic ?optbox_t ?optbox={};が見えない
#define OPTBOX_INIARR(...)	static optboxifmt_t OPTBOX_UNAME(OPTBOX_BN,_iniarr,)[] = \
	{ OPTBOX_ARGCNT(__VA_ARGS__)(N, __VA_ARGS__) {0} }; 
#define	NOPTBOX_INI(a,b,c,d,...) {#a, b, c, #d, OPTBOX_UNAME(OPTBOX_BN,_test_,a) \
	,&(OPTBOX_UNAME(OPTBOX_BN,_obj.a,) ),&(OPTBOX_UNAME(OPTBOX_BN,_obj.a,_cmdin) ) \
	,&(OPTBOX_UNAME(OPTBOX_BN,_obj.a,_dfl) ) },
// { "help", "-h", "0", "bool", OPTBOXtest_name, &(OPTBOX_obj.name), &,&}, ...

#define OPTBOX_TESTF(...)	OPTBOX_ARGCNT(__VA_ARGS__)(F, __VA_ARGS__)
#define	FOPTBOX_INI(aa,bb,cc,dd,...) static int OPTBOX_UNAME(OPTBOX_BN,_test_,aa)(const char* s){ \
	int i=atoi(s);double d=atof(s);__VA_ARGS__ ;i=i;d=d;return 1;} // i=i..stop no use warning

//getter,setter
#define OPTBOX_APIF(...) \
	int OPTBOX_UNAME(OPTBOX_BN,_geti,)(const char* s){ \
		return optbox_getisub(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,), s);} \
	double OPTBOX_UNAME(OPTBOX_BN,_getd,)(const char* s){ \
		return optbox_getdsub(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,), s);} \
	const char* OPTBOX_UNAME(OPTBOX_BN,_gets,)(const char* s){ \
		return optbox_getssub(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,), s);} \
	void* OPTBOX_UNAME(OPTBOX_BN,_getptr,)(const char* s){ \
		return optbox_getptrsub(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,), s);} \
	int OPTBOX_UNAME(OPTBOX_BN,_geterr,)(void){ \
		return OPTBOX_UNAME(OPTBOX_BN,_err,);} \
\
	int OPTBOX_UNAME(OPTBOX_BN,_seti,)(const char* s, int i){ \
		return optbox_setcmn(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,),s,'i',i,0,0);} \
	int OPTBOX_UNAME(OPTBOX_BN,_setd,)(const char* s, double d){ \
		return optbox_setcmn(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,),s,'d',0,d,0);} \
	int OPTBOX_UNAME(OPTBOX_BN,_sets,)(const char* s, const char* ss){ \
		return optbox_setcmn(OPTBOX_UNAME(OPTBOX_BN,_iniarr,), &OPTBOX_UNAME(OPTBOX_BN,_err,),s,'s',0,0,ss);}

static int optbox_getisub(optboxifmt_t* arr, int* eflg, const char* s){
	*eflg=0;
	for(int i=0;;i++){
		if(arr[i].name==NULL){ *eflg=1;return 0;}
		if(strcmp(arr[i].name, s) ){continue;}
		if(! (arr[i].tp[0]=='i'||arr[i].tp[0]=='b') ){
			fprintf(stderr, ": %s %s\n",s, arr[i].tp);
			OPTBOX_ERR(1, "fatal err. optname(not int) detect.", exit(1) );
		}
		int buf;
		memcpy(&buf, arr[i].p, sizeof(int) );
		return buf;
	}
}
static double optbox_getdsub(optboxifmt_t* arr, int* eflg, const char* s){
	*eflg=0;
	for(int i=0;;i++){
		if(arr[i].name==NULL){ *eflg=1;return 0;}
		if(strcmp(arr[i].name, s) ){continue;}
		if(arr[i].tp[0]!='d'){
			fprintf(stderr, ": %s %s\n",s, arr[i].tp);
			OPTBOX_ERR(1, "fatal err. optname(not dbl) detect.", exit(1) );
		}
		double buf;
		memcpy(&buf, arr[i].p, sizeof(double) );
		return buf;
	}
}
static const char* optbox_getssub(optboxifmt_t* arr, int* eflg, const char* s){
	*eflg=0;
	for(int i=0;;i++){
		if(arr[i].name==NULL){ *eflg=1;return 0;}
		if(strcmp(arr[i].name, s) ){continue;}
		if(arr[i].tp[0]!='s'){
			fprintf(stderr, ": %s %s\n",s, arr[i].tp);
			OPTBOX_ERR(1, "fatal err. optname(not str) detect.", exit(1) );
		}
		const char* *buf =  (const char**)(arr[i].p);
		return *buf;
	}
}
static void* optbox_getptrsub(optboxifmt_t* arr, int* eflg, const char* s){
	*eflg=0;
	for(int i=0;;i++){
		if(arr[i].name==NULL){ *eflg=1;return 0;}
//		if(arr[i].tp[0]!='s'){OPTBOX_ERR(1, "fatal err. optname(not str) detect.", exit(1) ); }
		if(strcmp(arr[i].name, s) ){continue;}
		return arr[i].p;
	}
}
static int optbox_setcmn(optboxifmt_t* arr, int* eflg,const char* nm, int tpreq, int i, double d, const char* s){
	for(int ii=0;;ii++){
		int tp = arr[ii].tp[0]; if(tp=='b'){tp='i';}
		if(arr[ii].name==NULL){ *eflg=1;return 1;}
		if( tpreq != tp ){ continue;}
		if(strcmp(arr[ii].name, nm) ){continue;}

		if(tp=='i'){memcpy( arr[ii].p, &i, sizeof(int) );}
		if(tp=='d'){memcpy( arr[ii].p, &d, sizeof(double) );}
		if(tp=='s'){memcpy( arr[ii].p, &s, sizeof(char*) );}
		*eflg=0;
		return 0;
	}
	OPTBOX_ERR(1, "fatal err. unreachable code.", exit(1) );
}

//cmdline parser. subは使用時にばらされるので定義が本体より前にある
#define OPTBOX_PARSEF(...)	OPTBOX_UNAME(OPTBOX_BN,_t*,) \
	OPTBOX_UNAME(OPTBOX_BN,,)(char* mode, int *ac, char** *av){ \
	OPTBOX_UNAME(OPTBOX_BN,_err,)=0; \
	int rc=optbox_sub(OPTBOX_UNAME(OPTBOX_BN,_iniarr,),&OPTBOX_UNAME(OPTBOX_BN,_err,),mode,ac,av); \
	if(rc!=0){return NULL;}	return &OPTBOX_UNAME(OPTBOX_BN,_obj,); }

static int optbox_sub(optboxifmt_t* iniarr, int* eptr, char* mode, int *argc, char** *argv){
	int ac= *argc;
	char** av= *argv;
	char* emsg=NULL;
	int apos[130];	/*95:sym33 aZ52 num10, (sp)32- 09/48-57 Az65-90/97-122 -(~)126 */
	for(int i=0;i<130;i++){apos[i]= -1;}
	/*init*/
	for(int i=0;;i++) {
//dbg(i, iniarr[i].optstr, iniarr[i].dflstr);	
		if(iniarr[i].optstr==NULL){break;}
		OPTBOX_ERR(iniarr[i].optstr[1]=='-',
			"err, char '-' cant set as optchar",exit(1) );
		OPTBOX_ERR(strstr("bool/int/dbl/str", iniarr[i].tp)==NULL
			,"err, opttype allows only bool/int/dbl/str: "
			, fprintf(stderr, "%s\n",iniarr[i].tp);exit(1) );
		if(strpbrk(mode, "x")==NULL){
			char c = iniarr[i].optstr[1];
			int rc = ( (48<=c&&c<=57) || (65<=c&&c<=90) || (97<=c&&c<=122) );
			OPTBOX_ERR(rc==0, "err, out of posix optchar[0-9a-zA-Z] is set:"
				, fprintf(stderr,"%c\n", c);exit(1) );
		}
		*(iniarr[i].dfl) = iniarr[i].dflstr;
		if(iniarr[i].tp[0]=='i'||iniarr[i].tp[0]=='b'){
			char* p;
			int v = (int)strtol(iniarr[i].dflstr, &p, 0);
			OPTBOX_ERR(*p!='\0', "err, bad intchar exist in dfl lit:"
				, fprintf(stderr,"%s\n", iniarr[i].dflstr);exit(1) );
			memcpy(iniarr[i].p, &v, sizeof(int) );
			/*可変型なのでtype警告が邪魔。memで踏み潰す*/
		}
		if(iniarr[i].tp[0]=='d'){
			char* p;
			double v = strtod(iniarr[i].dflstr, &p);
			OPTBOX_ERR(*p!='\0', "err, bad dblchar exist in dfl lit:"
				, fprintf(stderr,"%s\n", iniarr[i].dflstr);exit(1) );
			memcpy(iniarr[i].p, &v, sizeof(double) );
		}
		if(iniarr[i].tp[0]=='s'){ memcpy(iniarr[i].p, &(iniarr[i].dflstr), sizeof(char*) ); }
		apos[(int)iniarr[i].optstr[1]]=i;
	}
	/* parse cmd */
	int argind=1;	/*argv[0]: filename */
	int charpos=1;	 /*  -h .. skip '-' */
//dbg(argind, charpos, ac);
	while(argind<ac){
		if(av[argind][0]!='-'&&strpbrk(mode, "x")==NULL )	{break;}
		if(av[argind][0]!='-'||av[argind][1]==0)	{argind++;charpos=1;continue;}
		if(av[argind][charpos]==0)	{av[argind]=NULL;argind++;charpos=1;continue;}
		if(strcmp(av[argind],"--")==0)	{av[argind]=NULL;break;}

		/*optparse ... -h123 はh/1/2/3の順番でoptか後ろにsubを持たないとダメ*/
		int optchar=(int)av[argind][charpos];
		if(apos[optchar]<0)	{emsg="no such opt";goto lbl_OPTERR;}
		optboxifmt_t ini = iniarr[apos[optchar]];

		/*tpck ... bool*/
		if(ini.tp[0]=='b'){
			int v=1;
			memcpy(ini.p, &v, sizeof(int) );
			*(ini.cmdin)="";
			charpos++;
			goto lbl_TESTFUNC;
		}
		/* i,d,s has optarg */
		if(av[argind][charpos+1]==0){
			av[argind]=NULL;
			argind++;charpos=0;
			if(ac-1<argind){emsg="optarg not found";goto lbl_OPTERR;}
		}
		if(ini.tp[0]=='i'){
			char* p;
			int v = (int)strtol(charpos+av[argind], &p, 0);
			if(*p!='\0'){emsg="detect invalid intchar";goto lbl_OPTERR;}
			memcpy(ini.p, &v, sizeof(int) );
			*(ini.cmdin) = charpos+av[argind];
			av[argind]=NULL;argind++;
			charpos=1;
			goto lbl_TESTFUNC;
		}
		if(ini.tp[0]=='d'){
			char* p;
			double v = strtod(charpos+av[argind], &p);
			if(*p!='\0'){emsg="detect invalid numchar";goto lbl_OPTERR;}  \
			memcpy(ini.p, &v, sizeof(double) );
			*(ini.cmdin) = charpos+av[argind];
			av[argind]=NULL;argind++;
			charpos=1;
			goto lbl_TESTFUNC;
		}
		if(ini.tp[0]=='s'){
			char* p = charpos+av[argind];
			memcpy(ini.p, &p, sizeof(char*) );
			*(ini.cmdin) = charpos+av[argind];
			av[argind]=NULL;argind++;
			charpos=1;
			goto lbl_TESTFUNC;
		}
		OPTBOX_ERR(1,"fatal err. unreachable code, optbox() bug", exit(1) );
lbl_TESTFUNC:;
		int rc = ini.func(*ini.cmdin);
		if(rc==0){fprintf(stderr,"value test failed: -%c\n", optchar); exit(1);}
		continue;
lbl_OPTERR:;
		*eptr=optchar;
		if(strpbrk(mode, "q")){return 1;}
		fprintf(stderr,"%s: -%c\n", emsg, optchar);
		exit(1);
	}
	/* shift args  */
	int agpos=1;
	for(int i=1; i<ac;i++){
		if(av[i]==NULL){continue;}
		av[agpos] =av[i];
		agpos++;
	}
	av[agpos]=NULL;
	*argc=agpos;
	return 0;
}

//95:sym33 aZ52 num10, (sp)32- 09/48-57 Az65-90/97-122 -(~)126
#define OPTBOX_ARGCNT(...)	OPTBOX_ARGCNT2(__VA_ARGS__,99,98,97,96,95,94,93,92,\
	91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,\
	66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,\
	41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,\
	16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 )
#define OPTBOX_ARGCNT2(a99,a98,a97,a96,a95,a94,a93,a92,a91,a90,a89,a88,a87,a86,\
	a85,a84,a83,a82,a81,a80,a79,a78,a77,a76,a75,a74,a73,a72,a71,a70,a69,a68,a67,\
	a66,a65,a64,a63,a62,a61,a60,a59,a58,a57,a56,a55,a54,a53,a52,a51,a50,a49,a48,\
	a47,a46,a45,a44,a43,a42,a41,a40,a39,a38,a37,a36,a35,a34,a33,a32,a31,a30,a29,\
	a28,a27,a26,a25,a24,a23,a22,a21,a20,a19,a18,a17,a16,a15,a14,a13,a12,a11,a10,\
	a9,a8,a7,a6,a5,a4,a3,a2,a1,a0,a,...)	OPTBOX_ITER_ ## a

// ITER(MCR, (fname...), (help...),..)	>> MCR(fname..) ITER(MCR, (help,..) )
#define OPTBOX_ITER_0(a,b) a ## OPTBOX_INI b
#define OPTBOX_ITER_1(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_0(a,__VA_ARGS__)
#define OPTBOX_ITER_2(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_1(a,__VA_ARGS__)
#define OPTBOX_ITER_3(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_2(a,__VA_ARGS__)
#define OPTBOX_ITER_4(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_3(a,__VA_ARGS__)
#define OPTBOX_ITER_5(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_4(a,__VA_ARGS__)
#define OPTBOX_ITER_6(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_5(a,__VA_ARGS__)
#define OPTBOX_ITER_7(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_6(a,__VA_ARGS__)
#define OPTBOX_ITER_8(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_7(a,__VA_ARGS__)
#define OPTBOX_ITER_9(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_8(a,__VA_ARGS__)
#define OPTBOX_ITER_10(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_9(a,__VA_ARGS__)
#define OPTBOX_ITER_11(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_10(a,__VA_ARGS__)
#define OPTBOX_ITER_12(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_11(a,__VA_ARGS__)
#define OPTBOX_ITER_13(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_12(a,__VA_ARGS__)
#define OPTBOX_ITER_14(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_13(a,__VA_ARGS__)
#define OPTBOX_ITER_15(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_14(a,__VA_ARGS__)
#define OPTBOX_ITER_16(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_15(a,__VA_ARGS__)
#define OPTBOX_ITER_17(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_16(a,__VA_ARGS__)
#define OPTBOX_ITER_18(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_17(a,__VA_ARGS__)
#define OPTBOX_ITER_19(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_18(a,__VA_ARGS__)
#define OPTBOX_ITER_20(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_19(a,__VA_ARGS__)
#define OPTBOX_ITER_21(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_20(a,__VA_ARGS__)
#define OPTBOX_ITER_22(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_21(a,__VA_ARGS__)
#define OPTBOX_ITER_23(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_22(a,__VA_ARGS__)
#define OPTBOX_ITER_24(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_23(a,__VA_ARGS__)
#define OPTBOX_ITER_25(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_24(a,__VA_ARGS__)
#define OPTBOX_ITER_26(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_25(a,__VA_ARGS__)
#define OPTBOX_ITER_27(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_26(a,__VA_ARGS__)
#define OPTBOX_ITER_28(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_27(a,__VA_ARGS__)
#define OPTBOX_ITER_29(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_28(a,__VA_ARGS__)
#define OPTBOX_ITER_30(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_29(a,__VA_ARGS__)
#define OPTBOX_ITER_31(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_30(a,__VA_ARGS__)
#define OPTBOX_ITER_32(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_31(a,__VA_ARGS__)
#define OPTBOX_ITER_33(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_32(a,__VA_ARGS__)
#define OPTBOX_ITER_34(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_33(a,__VA_ARGS__)
#define OPTBOX_ITER_35(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_34(a,__VA_ARGS__)
#define OPTBOX_ITER_36(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_35(a,__VA_ARGS__)
#define OPTBOX_ITER_37(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_36(a,__VA_ARGS__)
#define OPTBOX_ITER_38(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_37(a,__VA_ARGS__)
#define OPTBOX_ITER_39(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_38(a,__VA_ARGS__)
#define OPTBOX_ITER_40(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_39(a,__VA_ARGS__)
#define OPTBOX_ITER_41(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_40(a,__VA_ARGS__)
#define OPTBOX_ITER_42(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_41(a,__VA_ARGS__)
#define OPTBOX_ITER_43(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_42(a,__VA_ARGS__)
#define OPTBOX_ITER_44(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_43(a,__VA_ARGS__)
#define OPTBOX_ITER_45(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_44(a,__VA_ARGS__)
#define OPTBOX_ITER_46(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_45(a,__VA_ARGS__)
#define OPTBOX_ITER_47(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_46(a,__VA_ARGS__)
#define OPTBOX_ITER_48(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_47(a,__VA_ARGS__)
#define OPTBOX_ITER_49(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_48(a,__VA_ARGS__)
#define OPTBOX_ITER_50(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_49(a,__VA_ARGS__)
#define OPTBOX_ITER_51(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_50(a,__VA_ARGS__)
#define OPTBOX_ITER_52(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_51(a,__VA_ARGS__)
#define OPTBOX_ITER_53(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_52(a,__VA_ARGS__)
#define OPTBOX_ITER_54(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_53(a,__VA_ARGS__)
#define OPTBOX_ITER_55(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_54(a,__VA_ARGS__)
#define OPTBOX_ITER_56(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_55(a,__VA_ARGS__)
#define OPTBOX_ITER_57(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_56(a,__VA_ARGS__)
#define OPTBOX_ITER_58(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_57(a,__VA_ARGS__)
#define OPTBOX_ITER_59(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_58(a,__VA_ARGS__)
#define OPTBOX_ITER_60(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_59(a,__VA_ARGS__)
#define OPTBOX_ITER_61(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_60(a,__VA_ARGS__)
#define OPTBOX_ITER_62(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_61(a,__VA_ARGS__)
#define OPTBOX_ITER_63(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_62(a,__VA_ARGS__)
#define OPTBOX_ITER_64(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_63(a,__VA_ARGS__)
#define OPTBOX_ITER_65(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_64(a,__VA_ARGS__)
#define OPTBOX_ITER_66(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_65(a,__VA_ARGS__)
#define OPTBOX_ITER_67(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_66(a,__VA_ARGS__)
#define OPTBOX_ITER_68(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_67(a,__VA_ARGS__)
#define OPTBOX_ITER_69(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_68(a,__VA_ARGS__)
#define OPTBOX_ITER_70(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_69(a,__VA_ARGS__)
#define OPTBOX_ITER_71(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_70(a,__VA_ARGS__)
#define OPTBOX_ITER_72(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_71(a,__VA_ARGS__)
#define OPTBOX_ITER_73(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_72(a,__VA_ARGS__)
#define OPTBOX_ITER_74(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_73(a,__VA_ARGS__)
#define OPTBOX_ITER_75(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_74(a,__VA_ARGS__)
#define OPTBOX_ITER_76(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_75(a,__VA_ARGS__)
#define OPTBOX_ITER_77(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_76(a,__VA_ARGS__)
#define OPTBOX_ITER_78(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_77(a,__VA_ARGS__)
#define OPTBOX_ITER_79(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_78(a,__VA_ARGS__)
#define OPTBOX_ITER_80(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_79(a,__VA_ARGS__)
#define OPTBOX_ITER_81(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_80(a,__VA_ARGS__)
#define OPTBOX_ITER_82(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_81(a,__VA_ARGS__)
#define OPTBOX_ITER_83(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_82(a,__VA_ARGS__)
#define OPTBOX_ITER_84(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_83(a,__VA_ARGS__)
#define OPTBOX_ITER_85(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_84(a,__VA_ARGS__)
#define OPTBOX_ITER_86(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_85(a,__VA_ARGS__)
#define OPTBOX_ITER_87(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_86(a,__VA_ARGS__)
#define OPTBOX_ITER_88(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_87(a,__VA_ARGS__)
#define OPTBOX_ITER_89(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_88(a,__VA_ARGS__)
#define OPTBOX_ITER_90(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_89(a,__VA_ARGS__)
#define OPTBOX_ITER_91(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_90(a,__VA_ARGS__)
#define OPTBOX_ITER_92(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_91(a,__VA_ARGS__)
#define OPTBOX_ITER_93(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_92(a,__VA_ARGS__)
#define OPTBOX_ITER_94(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_93(a,__VA_ARGS__)
#define OPTBOX_ITER_95(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_94(a,__VA_ARGS__)
#define OPTBOX_ITER_96(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_95(a,__VA_ARGS__)
#define OPTBOX_ITER_97(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_96(a,__VA_ARGS__)
#define OPTBOX_ITER_98(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_97(a,__VA_ARGS__)
#define OPTBOX_ITER_99(a,b, ...) a##OPTBOX_INI b OPTBOX_ITER_98(a,__VA_ARGS__)

#endif //a18d0ac31a24b
/*SH_ED*/

/*SH_SC*/

//no code, header only

/*SH_SMP
#include "*SH_bn*.hpp"
OPTBOX_SET(
 ( help,  "-h", "0"     ,bool )
 ,( count, "-n", "1"     ,int	,return (0<=i && i<=3) )
 ,( file,  "-f", "a.ini" ,str	,if(strlen(s)>10){return 0;} )
 ,( wait,  "-d", "0.3"   ,dbl	,if(0<d){return 1;}; return 0; )
)
int main(int ac, char** av) {
	optbox_t* obj = optbox("q", &ac, &av);
	
	printf("%f\n", obj->wait);
	puts(obj->file);
}
/*SH_SMPE	sampleend*/

#ifdef TEST
#include "hcut.cc"
#include "msgp.h"
#include "*SH_bn*.hpp"

#undef OPTBOX_BASENAME
#define OPTBOX_BASENAME optboxabc
OPTBOX_SET(
 ( help,  "-h", "0"     ,bool )
 ,( count, "-n", "1"     ,int	,return (0<=i && i<=3) )
 ,( file,  "-f", "a.ini" ,str	,if(strlen(s)>10){return 0;} )
 ,( wait,  "-d", "0.3"   ,dbl	,if(0<d){return 1;}; return 0; )
)

HCUT_ADD(t_test) {
	int i,rc;
	double d; const char* s;
	
	optboxabc_t* obj = optboxabc("x", &argc, &argv);		//"" ...parse mode setting(dfl)
	printf("ac: %d %s\n", argc, argv[0] );

	eq_s("a.ini", obj->file_dfl);
	eq_i(obj->help, 0);
	eq_i(obj->count, 1);
	eq_s(obj->file, "a.ini");
	eq_d(obj->wait, 0.3);
	
	eq_i(optboxabc_geti("help"), 0);
	eq_d(optboxabc_getd("wait"), 0.3);
	eq_s(optboxabc_gets("file"), "a.ini");
	eq_p(optboxabc_getptr("file"), &obj->file );
	
	optboxabc_seti("help", 10);
	eq_i(optboxabc_geti("help"),10);
	optboxabc_setd("wait", 0.01);
	eq_d(optboxabc_getd("wait"), 0.01);
	optboxabc_sets("file", "hw");
	eq_s(optboxabc_gets("file"), "hw");
	rc=optboxabc_geterr();
	eq_i(rc, 0);
	
	optboxabc_seti("help", 4.1);
	eq_i(optboxabc_geti("help"), 4);
	rc=optboxabc_geterr();
	eq_i(rc, 0);
}
#endif

#ifdef TEST
HCUT_RUN("stderr", 1,	/* keep newline. use for SH sed edit, -t test.*/
t_test);
#endif

/*
 change log
 --
2020-10-25  Momi-g	<dmy@dmy.dmy>

	* *SH_bn*.c (all): add getter/setter for access optdata from outer srcfile

2020-10-23  Momi-g	<dmy@dmy.dmy>

	* *SH_bn*.c (all): v1.0.0 release

*/
/*SH_ED*/

/*SH_OP _ a=`sed -ne "/${C}DF/!d;:l;n;/${C}DE/q;p;bl"<$R0`;eval "$a"	#*/
/*SH_OP g $e"$CW">/dev/null;fg "$Rh" "$Rs" #*/

/*SH_OP	h $p"-t/s/b:test/smpl/bld /T:t+mem /f:functop"	 #*/
/*SH_OP	f (sed -ne 's@^HCUT_ADD(\([^)]*\).*@\1,@p'<$R0;sed -e '/^[a-z].*)/!d;/;/d'<$R0)|$cn #*/

/*SH_OP t $e"$CW";[ "$1" != "" ]&&$i4;cat $Rs $tf>$Rm;$p'cc -g $Rm `fA $Rm`'|fv #*/
/*SH_OP T $e"$Ct";$p"valgrind --leak-check=full ./a.out 2>&1|sed -e '/SUMMA/!d;n;n;n;n'"|fv #*/
/*SH_OP M $e"$Ct";$p"$i5"|fv	 #*/
/*SH_OP s $e"$CB";(f0 "${C}SMP" "${C}SMPE"<$Rs;$p"//`fg $Rh $Rs`")>eg.c;$p'cc eg.c $Rs `fA $Rs $Rh`'|fv #*/

/*SH_OP b $e"$CW";$p'cc -c $Rs -O2 -Wall'|fv;$p"$bn.o"		#*/
/*SH_OP B $e"$Cb";$p"ar r lib$bn.a `fo $Rh $Rs` $bn.o"|fv;$p"lib$bn.a"	#*/
/*SH_OP S $e"$CW";$p'cc $Rs `fA $Rs $Rh` -O2 -Wall -shared -fPIC -o lib'$bn'.so'|fv;$p"lib$bn.so" #*/
/*SH_OP W $e"$Cw";$i0;$i1;($cn<$Rh;$p"//`fg $Rh $Rs`")>$Rm;mv $Rm $Rh;$p"$Rs $tf"	#*/

/*SH_DF

#--name
bn=`basename ${Rs%.*}`
tf=${bn}_ts.${Rs##*.}
Rh="$bn.hpp"

#--cmd
e="eval "
p="$Rp"
cn=$e'sed -e "s@\*${C##*]}bn\*@$bn@g"'
n=$e"tr ' \t' '\n'|grep -v ^$"
N=$e'(tr "\n" " ";$p)'
u=$e'$n|sort -u|$N'

f0()(sed -ne "/$1/!d;:l;n;/$2/d;p;bl"|$cn)
f1()(sed -e "/$1/!d;:l;/$2/{p;d};n;bl"|$cn)

fo()(a=$#;set `cat $@|(sed -ne 's/^#in.*"\(.*\.h\)".*$/\1/p';$p"$@")|$u`
if [ $a = $# ];then $p"$@"|$n|sed -ne 's/\.h$/.o/p'|grep -vF "$bn.o";else fo "$@";fi)
fg()(sed -ne 's/.*\*SH_co\*\([^*]*\).*$/\1/p' "$@"|$u)

fd()(find `dirname $0` -type d|sed -e 's/\(.*\)/ -I\1 -L\1 /g'|$N)
fA()( (fo "$@";fg "$@";fd "$@")|$N)

fv()(while read -r a;do $e"cat<<E$O# $a${O}E">/dev/stderr;$e"$a";done)

i0=$e'f0 "^#ifdef TEST" "^#endif"<$Rs>$tf'
i1=$e'sed -ne "/^#ifdef TEST/bl;p;d;:l;n;/^#endif/d;bl"<$Rs|$cn>$Rm;mv $Rm $Rs'
i4=$e'sed -ne "p;/_RUN/bl;d;:l;/);/{c\\$O $1);$O p;d};n;bl"<$tf>$Rm;mv $Rm $tf'
i5="valgrind -q --tool=massif --massif-out-file=./vmem.buf \
--stacks=yes --trace-children=yes ./a.out "$@" >/dev/null
ms_print ./vmem.buf|sed -ne '/[KMG]B/bl;d;:l;/snap/q;p;n;bl';rm ./vmem.buf"
/*SH_DE*/
