NetBSD/bin/sh/mkoptions.sh

199 lines
4.0 KiB
Bash

#! /bin/sh
# $NetBSD: mkoptions.sh,v 1.5 2017/11/15 09:21:19 kre Exp $
#
# It would be more sensible to generate 2 .h files, one which
# is for everyone to use, defines the "variables" and (perhaps) generates
# the externs (though they could just be explicit in options.h)
# and one just for options.c which generates the initialisation.
#
# But then I'd have to deal with making the Makefile handle that properly...
# (this is simpler there, and it just means a bit more sh compile time.)
set -f
IFS=' ' # blank, tab (no newline)
IF="$1"
OF="${3+$3/}$2"
E_FILE=$(${MKTEMP:-mktemp} -t MKO.E.$$)
O_FILE=$(${MKTEMP:-mktemp} -t MKO.O.$$)
trap 'rm -f "${E_FILE}" "${O_FILE}"' EXIT
exec 5> "${E_FILE}"
exec 6> "${O_FILE}"
{
printf '/*\n * File automatically generated by %s.\n' "$0"
printf ' * Do not edit, do not add to cvs.\n'
printf ' */\n\n'
printf '#ifdef DEFINE_OPTIONS\n'
printf 'struct optent optlist[] = {\n'
} >"${OF}"
FIRST=true
${SED:-sed} <"${IF}" \
-e '/^$/d' \
-e '/^#/d' \
-e '/^[ ]*\//d' \
-e '/^[ ]*\*/d' \
-e '/^[ ]*;/d' |
sort -b -k2,2f -k2,2 < "${IF}" |
while read line
do
# Look for comments in various styles, and ignore them
# (these should generally be already removed by sed above)
case "${line}" in
'') continue;;
/*) continue;;
\**) continue;;
\;*) continue;;
\#*) continue;;
esac
case "${line}" in
*'#if'*)
COND="${line#*#}"
COND="#${COND%%#*}"
;;
*)
COND=
;;
esac
set -- ${line%%[ ]#*}
var="$1" name="$2"
case "${var}" in
('' | [!A-Za-z_]* | *[!A-Za-z0-9_]*)
printf >&2 "Bad var name: '%s'\\n" "${var}"
# exit 1
continue # just ignore it for now
esac
case "${name}" in
?) set -- ${var} '' $name $3 $4; name= ;;
esac
chr="$3" set="$4" dflt="$5"
case "${chr}" in
-) chr= set= dflt="$4";;
''|?) ;;
*) printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;;
esac
# options must have some kind of name, or they are useless...
test -z "${name}${chr}" && continue
case "${set}" in
-) set= ;;
[01] | [Oo][Nn] | [Oo][Ff][Ff]) dflt="${set}"; set= ;;
''|?) ;;
*) printf >&2 'set "%s": Not a character\n' "${set}"; continue;;
esac
case "${dflt}" in
'') ;;
[Oo][Nn]) dflt=1;;
[Oo][Ff][Ff]) dflt=0;;
[01]) ;;
*) printf >&2 'default "%s" invalid, use 0 off 1 on\n'; continue;;
esac
# validation complete, now to generate output
if [ -n "${COND}" ]
then
printf '%s\n' "${COND}" >&4
printf '%s\n' "${COND}" >&5
printf '%s\n' "${COND}" >&6
fi
printf '\t_SH_OPT_%s,\n' "${var}" >&5
if [ -n "${name}" ]
then
printf ' { "%s", ' "${name}" >&4
else
printf ' { 0, ' >&4
fi
if [ -n "${chr}" ]
then
printf "'%s', " "${chr}" >&4
else
chr=
printf '0, ' >&4
fi
if [ -n "${set}" ]
then
printf "'%s', 0, " "${set}" >&4
else
printf '0, 0, ' >&4
fi
if [ -n "${dflt}" ]
then
printf '%s },\n' "${dflt}" >&4
else
printf '0 },\n' >&4
fi
printf '#define %s\toptlist[_SH_OPT_%s].val\n' "${var}" "${var}" >&6
if [ -n "${COND}" ]
then
printf '#endif\n' >&4
printf '#endif\n' >&5
printf '#endif\n' >&6
fi
test -z "${chr}" && continue
printf '%s _SH_OPT_%s %s\n' "${chr}" "${var}" "${COND}"
done 4>>"${OF}" | sort -t' ' -k1,1f -k1,1 | while read chr index COND
do
if $FIRST
then
printf ' { 0, 0, 0, 0, 0 }\n};\n'
printf '#endif\n\n'
printf 'enum shell_opt_names {\n'
cat "${E_FILE}"
printf '};\n\n'
printf '#ifdef DEFINE_OPTIONS\n'
printf 'const unsigned char optorder[] = {\n'
FIRST=false
fi
[ -n "${COND}" ] && printf '%s\n' "${COND}"
printf '\t%s,\n' "${index}"
[ -n "${COND}" ] && printf '#endif\n'
done >>"${OF}"
{
printf '};\n\n'
printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n'
printf 'int sizeof_optlist = sizeof optlist;\n\n'
printf \
'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n'
printf '\n#else\n\n'
printf 'extern struct optent optlist[];\n'
printf 'extern int sizeof_optlist;\n'
printf 'extern const unsigned char optorder[];\n'
printf 'extern const int option_flags;\n'
printf '\n#endif\n\n'
cat "${O_FILE}"
} >> "${OF}"
exit 0