#! /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