1: 2# NAME: 3# setopts.sh - set opt_* for shell scripts 4# 5# SYNOPSIS: 6# opt_str=s:a.b^cl,z= 7# opt_a=default 8# 9# . setopts.sh 10# 11# DESCRIPTION: 12# This module sets shell variables for each option specified in 13# "opt_str". 14# 15# If the option is followed by a ``:'' it requires an argument. 16# It defaults to an empty string and specifying that option on 17# the command line overrides the current value. 18# 19# If the option is followed by a ``.'' then it is treated as for 20# ``:'' except that any argument provided on the command line is 21# appended to the current value using the value of "opt_dot" as 22# separator (default is a space). 23# 24# If the option is followed by a ``,'' then it is treated as for 25# a ``.'' except that the separator is "opt_comma" (default ,). 26# 27# If the option is followed by ``='' it requires an argument 28# of the form "var=val" which will be evaluated. 29# 30# If the option is followed by a ``^'' then it is treated as a 31# boolean and defaults to 0. 32# 33# Options that have no qualifier are set to the flag if present 34# otherwise they are unset. That is if '-c' is given then 35# "opt_c" will be set to '-c'. 36# 37# If "opt_assign_eval" is set (and to something other than 38# 'no'), args of the form "var=val" will be evaluated. 39# 40# NOTES: 41# The implementation uses the getopts builtin if available. 42# 43# Also it does not work when loaded via a function call as "$@" 44# will be the args to that function. In such cases set 45# _SETOPTS_DELAY and call 'setopts "$@"; shift $__shift' 46# afterwards. 47# 48# AUTHOR: 49# Simon J. Gerraty <sjg@crufty.net> 50# 51 52# RCSid: 53# $Id: setopts.sh,v 1.13 2023/02/20 19:30:06 sjg Exp $ 54# 55# @(#) Copyright (c) 1995-2023 Simon J. Gerraty 56# 57# This file is provided in the hope that it will 58# be of use. There is absolutely NO WARRANTY. 59# Permission to copy, redistribute or otherwise 60# use this file is hereby granted provided that 61# the above copyright notice and this notice are 62# left intact. 63# 64# Please send copies of changes and bug-fixes to: 65# sjg@crufty.net 66# 67 68# the case checks just skip the sed(1) commands unless needed 69case "$opt_str" in 70*\^*) # the only ones we need to set are the booleans x, 71 eval `echo $opt_str | sed -e 's/[^^]*$//' -e 's/[^^]*\([^^]^\)/\1/g' -e 's/\(.\)^/opt_\1=${opt_\1-0}; /g'` 72 ;; 73esac 74case "$opt_str" in 75*[=,.\^]*) 76 _opt_str=`echo $opt_str | sed -e 's/[=,.]/:/g' -e 's/\^//g'`;; 77*) _opt_str=$opt_str;; 78esac 79 80opt_append=${opt_append:-" "} 81opt_dot=${opt_dot:-$opt_append} 82opt_comma=${opt_comma:-,} 83 84set1opt() { 85 o=$1 86 a="$2" 87 88 case "$opt_str" in 89 *${o}:*) eval "opt_$o=\"$a\"";; 90 *${o}.*) eval "opt_$o=\"\${opt_$o}\${opt_$o:+$opt_dot}$a\"";; 91 *${o},*) eval "opt_$o=\"\${opt_$o}\${opt_$o:+$opt_comma}$a\"";; 92 *${o}=*) 93 case "$a" in 94 *=*) eval "$a";; 95 *) Myname=${Myname:-`basename $0 .sh`} 96 echo "$Myname: -$o requires argument of form var=val" >&2 97 exit 1 98 ;; 99 esac 100 ;; 101 *${o}\^*) eval opt_$o=1;; 102 *) eval opt_$o=-$o;; 103 esac 104} 105 106setopts() { 107 __shift=$# 108 # use getopts builtin if we can 109 case `type getopts 2>&1` in 110 *builtin*) 111 : OPTIND=$OPTIND @="$@" 112 while getopts $_opt_str o 113 do 114 case "$o" in 115 \?) exit 1;; 116 esac 117 set1opt $o "$OPTARG" 118 done 119 shift $(($OPTIND - 1)) 120 while : 121 do 122 case "$1" in 123 *=*) 124 case "$opt_assign_eval" in 125 ""|no) break;; 126 *) eval "$1"; shift;; 127 esac 128 ;; 129 *) break;; 130 esac 131 done 132 ;; 133 *) # likely not a POSIX shell either 134 # getopt(1) isn't as good 135 set -- `getopt $_opt_str "$@" 2>&1` 136 case "$1" in 137 getopt:) 138 Myname=${Myname:-`basename $0 .sh`} 139 echo "$*" | tr ':' '\012' | sed -e '/^getopt/d' -e 's/ getopt$//' -e "s/^/$Myname:/" -e 's/ --/:/' -e 's/-.*//' 2>&2 140 exit 1 141 ;; 142 esac 143 144 while : 145 do 146 : 1="$1" 147 case "$1" in 148 --) shift; break;; 149 -*) 150 # Most shells give you ' ' in IFS whether you 151 # want it or not, but at least one, doesn't. 152 # So the following gives us consistency. 153 o=`IFS=" -"; set -- $1; echo $*` # lose the '-' 154 set1opt $o "$2" 155 case "$_opt_str" in 156 *${o}:*) shift;; 157 esac 158 ;; 159 *=*) case "$opt_assign_eval" in 160 ""|no) break;; 161 *) eval "$1";; 162 esac 163 ;; 164 *) break;; 165 esac 166 shift 167 done 168 ;; 169 esac 170 # let caller know how many args we consumed 171 __shift=`expr $__shift - $#` 172} 173 174${_SETOPTS_DELAY:+:} setopts "$@" 175${_SETOPTS_DELAY:+:} shift $__shift 176