#!/bin/sh
# platform ... debian dash 
cat << 'EEE' > /dev/null
/* rdopt ....read option, simple option parse helper. bourne-shell script.
 * Copyright (C) 2017-2019 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/>.
 */
EEE

# usage--------
if [ "$#" -eq 0 ] || [ "$1" = '-h' ] ; then
cat << 'EEE'
HowTo (readOpt, option parse helper. bourne-shell script.)
option: -h (this)
------
ex.) ~$ rdopt ":ab:c" zzz -b vvv "y' y" -a    # format first ':' is quiet err.
>>>	opt_a='1'
	opt_b='vvv'	
	opt_c=''
	set -- 'zzz' 'y'"'"' yy'	(literal safe)
ex.)
 #!/bin/sh			# yoursh.sh zzz -b vvv -c yyy
 buf=`rdopt ":ab:c" "$@"` 		#use "$@" or $@, not work at $*
 eval "$buf"
 if [ $? -ne 0 ] ; then echo "optErr. $OPTARG" >/dev/stderr ; exit 1; fi
 echo "$opt_b"  	# >>> vvv
 echo "$@ $#"		# >>> zzz yyy,  2	...opts removed

- check all args or until detect '--'.
	yoursh.sh -c zzz -5+4	>> NG. -5 is treated as option. rtns err.
	yoursh.sh -c zzz -- -5+4	>> OK. -5+4 parsed as args '$1'
- if failed to parse option, ' eval "$buf" ' returns $?=1
  wrong optchar is set to OPTARG (OPTARG='z' etc)
- if not quiet mode (:a:bc -> a:bc etc), disp errmsg & loop sleep.
- you can use parse function directly (copy & paste). see source.
EEE
exit 0
fi


# purse func. 
# inner vars uses prefix 'rdopt_*' and clean at function end.
# OPTIND is reset to '1' at the end.
# maybe you can copy & paste to your script directly.
# time
# normal use: 10-20 ms
# copy&paste: 5-10 ms

########## copy start ###########
func_rdopt() {
rdopt_fmt="$1"	#	":ab:c"	etc. format.
shift

#ck quiet mode
rdopt_quiet=1
rdopt_buf=${rdopt_fmt%%[!:]*}
if [ "$rdopt_buf" != ':' ] ; then
	rdopt_quiet=0
	rdopt_fmt=':'"$rdopt_fmt"
fi

#--inicialize	make list opt_a='', ...

#ab:c -> 'a' \n 'b' \n 'c' \n
rdopt_buf='s/://g
s/./&\
/g'
rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e "
/^$/d
s/^/opt_/g
s/$/=''/g
" `

#--- local vars
# rdopt_fmt="$1"	#	":ab:c"		opt format
# rdopt_quiet=1
# rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e "
# rdopt_buf='s/://g

rdopt_out=""
rdopt_opt=""
rdopt_skip=""
rdopt_err=""

rdopt_safe="
s#'#'\"'\"'#g
1 s/^/'/g
$ s/$/'/g"

#---getopts loop. break if all args read or detect '--'
while :
do
if [ 0 -eq "$#" ] || [ "$rdopt_err" = "1" ] ; then
	break
fi
if [ "$1" = "--" ] ; then
	shift ; break
fi

getopts "$rdopt_fmt" rdopt_opt "$@"	# ":a:bc:f:" etc...
# err detect@silent mode
# $?=1 ... detect optend or '--'. '--' is removed at previous line.
# ':' ... detect option, but dont have subargs (OPTARG="factor").
# '?' ... detect unsupported option char (OPTARG="factor") or args end (OPTARG="blank").
# OPTARG ... "" is optend. "a/b/c..." is invalid option 
# OPTIND ... if err, OPTIND indicates next (new) arg pos. 

if [ "$?" = "1" ] ; then 		# normal end (detect normal args). save general args.
	shift $((OPTIND - 1))
	if [ "$#" -eq "0" ] ; then
		break
	fi
	# new set make
	rdopt_buf=`printf '%s' "$1" | sed -e "$rdopt_safe"`
	rdopt_skip="$rdopt_skip $rdopt_buf"
	shift
	OPTIND=1
	continue
fi

if [ "$rdopt_opt" = "?" ] || [ "$rdopt_opt" = ":" ] ; then 	# detect invalid opt
	rdopt_err=1		#OPTARG has err option char.
	continue
fi

# normal. detect option.
if [ "$OPTARG" = "" ] ; then	# no subargs 
	rdopt_out="$rdopt_out
opt_$rdopt_opt"'=1'
else	# exist subargs 
rdopt_buf=`printf "%s\n" "$OPTARG" | sed -e "$rdopt_safe" `
	rdopt_out="$rdopt_out
opt_$rdopt_opt"'='"$rdopt_buf"
fi
done
# exit parse

if [ "$rdopt_err" = "1" ] ; then
	if [ "$rdopt_quiet" = "0" ] ; then
		rdopt_buf=${0##*/}
		echo "$rdopt_buf: invalid option. sleep. ( $OPTARG )" >/dev/stderr
		while :
		do
			sleep 1000
		done
	else
		rdopt_out="OPTARG=$OPTARG
OPTIND=1
test 1 = 0"
	fi
else

#	'--' end
	if [ "$#" != "0" ] ; then
	rdopt_buf=`cat << 'EEE'
for ii
do
	printf '%s' "$ii" | sed -e "
s#'#'\"'\"'#g
1 s/^/'/g
$ s/$/' /g"
done 
EEE
`
	rdopt_buf=`eval "$rdopt_buf"`
	rdopt_skip="$rdopt_skip $rdopt_buf"
	fi

	rdopt_out="OPTIND=1

$rdopt_zerolist
$rdopt_out
set -- $rdopt_skip
"
fi



printf '%s\n' "$rdopt_out"

# clean
OPTIND=1
rdopt_fmt=""
rdopt_quiet=""
rdopt_zerolist=""
rdopt_buf=""

rdopt_out=""
rdopt_opt=""
rdopt_skip=""
rdopt_err=""
rdopt_safe=""
}
########## copy end ###########

# direct use sample
# buf=`func_rdopt ':ab:c:d' "$@" `
# eval "$buf"
# if [ $? != 0 ] ; then echo "err. $OPTARG" >/dev/stderr ; exit 1; fi
# ... or ...
# buf=`func_rdopt 'ab:c:d' "$@" `		# stop mode.	

# ---main
func_rdopt "$@"
