Home | History | Annotate | Line # | Download | only in sh
mkoptions.sh revision 1.7
      1 #! /bin/sh
      2 
      3 # $NetBSD: mkoptions.sh,v 1.7 2024/04/06 14:20:27 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 -b -k2,2f -k2,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 	''|?)	;;
     99 	*)	printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;;
    100 	esac
    101 
    102 	# options must have some kind of name, or they are useless...
    103 	test -z "${name}${chr}" && continue
    104 
    105 	case "${set}" in
    106 	-)	set= ;;
    107 	[01] | [Oo][Nn] | [Oo][Ff][Ff])	dflt="${set}"; set= ;;
    108 	''|?)	;;
    109 	*)	printf >&2 'set "%s": Not a character\n' "${set}"; continue;;
    110 	esac
    111 
    112 	case "${dflt}" in
    113 	'')		;;
    114 	[Oo][Nn])	dflt=1;;
    115 	[Oo][Ff][Ff])	dflt=0;;
    116 	[01])		;;
    117 	*)	printf >&2 'default "%s" invalid, use 0 off 1 on\n'; continue;;
    118 	esac
    119 
    120 	# validation complete, now to generate output
    121 
    122 	if [ -n "${COND}" ]
    123 	then
    124 		printf '%s\n' "${COND}" >&4
    125 		printf '%s\n' "${COND}" >&5
    126 		printf '%s\n' "${COND}" >&6
    127 	fi
    128 
    129 	printf '\t_SH_OPT_%s,\n' "${var}" >&5
    130 
    131 	if [ -n "${name}" ]
    132 	then
    133 		printf '    { "%s", ' "${name}"	>&4
    134 	else
    135 		printf '    { 0, '		>&4
    136 	fi
    137 
    138 	if [ -n "${chr}" ]
    139 	then
    140 		printf "'%s', " "${chr}"	>&4
    141 	else
    142 		chr=
    143 		printf '0, '			>&4
    144 	fi
    145 
    146 	if [ -n "${set}" ]
    147 	then
    148 		printf "'%s', 0, " "${set}"	>&4
    149 	else
    150 		printf '0, 0, '			>&4
    151 	fi
    152 
    153 	if [ -n "${dflt}" ]
    154 	then
    155 		printf '%s },\n' "${dflt}"	>&4
    156 	else
    157 		printf '0 },\n'			>&4
    158 	fi
    159 
    160 	printf '#define %s\toptlist[_SH_OPT_%s].val\n' "${var}" "${var}" >&6
    161 
    162 	if [ -n "${COND}" ]
    163 	then
    164 		printf '#endif\n' >&4
    165 		printf '#endif\n' >&5
    166 		printf '#endif\n' >&6
    167 	fi
    168 
    169 	test -z "${chr}" && continue
    170 
    171 	printf '%s _SH_OPT_%s %s\n' "${chr}" "${var}" "${COND}"
    172 
    173 done 4>>"${OF}" | sort -t' ' -k1,1f -k1,1 | while read chr index COND
    174 do
    175 	if $FIRST
    176 	then
    177 		printf '    { 0, 0, 0, 0, 0 }\n};\n'
    178 		printf '#endif\n\n'
    179 
    180 		printf 'enum shell_opt_names {\n'
    181 		cat "${E_FILE}"
    182 		printf '};\n\n'
    183 
    184 		printf '#ifdef DEFINE_OPTIONS\n'
    185 		printf 'const unsigned char optorder[] = {\n'
    186 		FIRST=false
    187 	fi
    188 	[ -n "${COND}" ] && printf '%s\n' "${COND}"
    189 	printf '\t%s,\n' "${index}"
    190 	[ -n "${COND}" ] && printf '#endif\n'
    191 
    192 done >>"${OF}"
    193 
    194 {
    195 	printf '};\n\n'
    196 	printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n'
    197 	printf 'int sizeof_optlist = sizeof optlist;\n\n'
    198 	printf	\
    199 	   'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n'
    200 	printf '\n#else\n\n'
    201 	printf 'extern struct optent optlist[];\n'
    202 	printf 'extern int sizeof_optlist;\n'
    203 	printf 'extern const unsigned char optorder[];\n'
    204 	printf 'extern const int option_flags;\n'
    205 	printf '\n#endif\n\n'
    206 
    207 	cat "${O_FILE}"
    208 } >> "${OF}"
    209 
    210 exit 0
    211