Home | History | Annotate | Line # | Download | only in sh
      1 #! /bin/sh
      2 
      3 # $NetBSD: mkoptions.sh,v 1.9 2024/10/11 08:53:09 kre Exp $
      4 
      5 #
      6 # It would be more sensible to generate 2 .h files, one which
      7 # is for everyone to use, defines the "variables" and (perhaps) generates
      8 # the externs (though they could just be explicit in options.h)
      9 # and one just for options.c which generates the initialisation.
     10 #
     11 # But then I'd have to deal with making the Makefile handle that properly...
     12 # (this is simpler there, and it just means a bit more sh compile time.)
     13 
     14 set -f
     15 IFS=' 	'	# blank, tab (no newline)
     16 export LC_ALL=C	# for sort consistency
     17 
     18 IF="$1"
     19 OF="${3+$3/}$2"
     20 
     21 case $- in
     22 *x*)
     23 	E_FILE=$(${MKTEMP:-mktemp} "${TMPDIR:-/tmp}/MKO.E.$$.XXXXXX") || exit 1
     24 	O_FILE=$(${MKTEMP:-mktemp} "${TMPDIR:-/tmp}/MKO.O.$$.XXXXXX") || {
     25 		rm -f "${E_FILE}"
     26 		exit 1
     27 	}
     28 	;;
     29 *)
     30 	E_FILE=$(${MKTEMP:-mktemp}) || exit 1
     31 	O_FILE=$(${MKTEMP:-mktemp}) || { rm -f "${E_FILE}"; exit 1; }
     32 	trap 'rm -f "${E_FILE}" "${O_FILE}"' EXIT
     33 	;;
     34 esac
     35 
     36 exec 5> "${E_FILE}"
     37 exec 6> "${O_FILE}"
     38 
     39 {
     40 	printf '/*\n * File automatically generated by %s.\n' "$0"
     41 	printf ' * Do not edit, do not add to cvs.\n'
     42 	printf ' */\n\n'
     43 
     44 	printf '#ifdef DEFINE_OPTIONS\n'
     45 	printf 'struct optent optlist[] = {\n'
     46 } >"${OF}"
     47 
     48 FIRST=true
     49 
     50 ${SED:-sed} <"${IF}"			\
     51 	-e '/^$/d'			\
     52 	-e '/^#/d'			\
     53 	-e '/^[ 	]*\//d'		\
     54 	-e '/^[ 	]*\*/d'		\
     55 	-e '/^[ 	]*;/d'		|
     56 sort -k2b,2f -k2b,2			|
     57 while read line
     58 do
     59 	# Look for comments in various styles, and ignore them
     60 	# (these should generally be already removed by sed above)
     61 
     62 	case "${line}" in
     63 	'')	continue;;
     64 	/*)	continue;;
     65 	\**)	continue;;
     66 	\;*)	continue;;
     67 	\#*)	continue;;
     68 	esac
     69 
     70 	case "${line}" in
     71 	*'#if'*)
     72 		COND="${line#*#}"
     73 		COND="#${COND%%#*}"
     74 		;;
     75 	*)
     76 		COND=
     77 		;;
     78 	esac
     79 	set -- ${line%%[ 	]#*}
     80 
     81 	var="$1" name="$2"
     82 
     83 	case "${var}" in
     84 	('' | [!A-Za-z_]* | *[!A-Za-z0-9_]*)
     85 		printf >&2 "Bad var name: '%s'\\n" "${var}"
     86 		# exit 1
     87 		continue	# just ignore it for now
     88 	esac
     89 
     90 	case "${name}" in
     91 	?) 	set -- ${var} '' $name $3 $4; name= ;;
     92 	esac
     93 
     94 	chr="$3" set="$4" dflt="$5"
     95 
     96 	case "${chr}" in
     97 	-)	chr= set= dflt="$4";;
     98 	+)	chr= ;;
     99 	''|?)	;;
    100 	*)	printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;;
    101 	esac
    102 
    103 	# options must have some kind of name, or they are useless...
    104 	test -z "${name}${chr}" && continue
    105 
    106 	case "${set}" in
    107 	-)	set= ;;
    108 	[01] | [Oo][Nn] | [Oo][Ff][Ff])	dflt="${set}"; set= ;;
    109 	''|?)	;;
    110 	*)	printf >&2 'set "%s": Not a character\n' "${set}"; continue;;
    111 	esac
    112 
    113 	case "${dflt}" in
    114 	'')		;;
    115 	[Oo][Nn])	dflt=1;;
    116 	[Oo][Ff][Ff])	dflt=0;;
    117 	[01])		;;
    118 	*)	printf >&2 'default "%s" invalid, use 0 off 1 on\n'; continue;;
    119 	esac
    120 
    121 	# validation complete, now to generate output
    122 
    123 	if [ -n "${COND}" ]
    124 	then
    125 		printf '%s\n' "${COND}" >&4
    126 		printf '%s\n' "${COND}" >&5
    127 		printf '%s\n' "${COND}" >&6
    128 	fi
    129 
    130 	printf '\t_SH_OPT_%s,\n' "${var}" >&5
    131 
    132 	if [ -n "${name}" ]
    133 	then
    134 		printf '    { "%s", ' "${name}"	>&4
    135 	else
    136 		printf '    { 0, '		>&4
    137 	fi
    138 
    139 	if [ -n "${chr}" ]
    140 	then
    141 		printf "'%s', " "${chr}"	>&4
    142 	else
    143 		chr=
    144 		printf '0, '			>&4
    145 	fi
    146 
    147 	if [ -n "${set}" ]
    148 	then
    149 		printf "'%s', 0, " "${set}"	>&4
    150 	else
    151 		printf '0, 0, '			>&4
    152 	fi
    153 
    154 	if [ -n "${dflt}" ]
    155 	then
    156 		printf '%s },\n' "${dflt}"	>&4
    157 	else
    158 		printf '0 },\n'			>&4
    159 	fi
    160 
    161 	printf '#define %s\toptlist[_SH_OPT_%s].val\n' "${var}" "${var}" >&6
    162 
    163 	if [ -n "${COND}" ]
    164 	then
    165 		printf '#endif\n' >&4
    166 		printf '#endif\n' >&5
    167 		printf '#endif\n' >&6
    168 	fi
    169 
    170 	test -z "${chr}" && continue
    171 
    172 	printf '%s _SH_OPT_%s %s\n' "${chr}" "${var}" "${COND}"
    173 
    174 done 4>>"${OF}" | sort -t' ' -k1,1f -k1,1 | while read chr index COND
    175 do
    176 	if $FIRST
    177 	then
    178 		printf '    { 0, 0, 0, 0, 0 }\n};\n'
    179 		printf '#endif\n\n'
    180 
    181 		printf 'enum shell_opt_names {\n'
    182 		cat "${E_FILE}"
    183 		printf '};\n\n'
    184 
    185 		printf '#ifdef DEFINE_OPTIONS\n'
    186 		printf 'const unsigned char optorder[] = {\n'
    187 		FIRST=false
    188 	fi
    189 	[ -n "${COND}" ] && printf '%s\n' "${COND}"
    190 	printf '\t%s,\n' "${index}"
    191 	[ -n "${COND}" ] && printf '#endif\n'
    192 
    193 done >>"${OF}"
    194 
    195 {
    196 	printf '};\n\n'
    197 	printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n'
    198 	printf 'int sizeof_optlist = sizeof optlist;\n\n'
    199 	printf	\
    200 	   'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n'
    201 	printf '\n#else\n\n'
    202 	printf 'extern struct optent optlist[];\n'
    203 	printf 'extern int sizeof_optlist;\n'
    204 	printf 'extern const unsigned char optorder[];\n'
    205 	printf 'extern const int option_flags;\n'
    206 	printf '\n#endif\n\n'
    207 
    208 	cat "${O_FILE}"
    209 } >> "${OF}"
    210 
    211 exit 0
    212