Home | History | Annotate | Line # | Download | only in sh
mkoptions.sh revision 1.6
      1 #! /bin/sh
      2 
      3 # $NetBSD: mkoptions.sh,v 1.6 2024/04/05 22:22:17 christos 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 E_FILE=$(${MKTEMP:-mktemp} -t MKOXXXXXXXX.E.$$)
     22 O_FILE=$(${MKTEMP:-mktemp} -t MKOXXXXXXXX.O.$$)
     23 trap 'rm -f "${E_FILE}" "${O_FILE}"' EXIT
     24 
     25 exec 5> "${E_FILE}"
     26 exec 6> "${O_FILE}"
     27 
     28 {
     29 	printf '/*\n * File automatically generated by %s.\n' "$0"
     30 	printf ' * Do not edit, do not add to cvs.\n'
     31 	printf ' */\n\n'
     32 
     33 	printf '#ifdef DEFINE_OPTIONS\n'
     34 	printf 'struct optent optlist[] = {\n'
     35 } >"${OF}"
     36 
     37 FIRST=true
     38 
     39 ${SED:-sed} <"${IF}"			\
     40 	-e '/^$/d'			\
     41 	-e '/^#/d'			\
     42 	-e '/^[ 	]*\//d'		\
     43 	-e '/^[ 	]*\*/d'		\
     44 	-e '/^[ 	]*;/d'		|
     45 sort -b -k2,2f -k2,2			|
     46 while read line
     47 do
     48 	# Look for comments in various styles, and ignore them
     49 	# (these should generally be already removed by sed above)
     50 
     51 	case "${line}" in
     52 	'')	continue;;
     53 	/*)	continue;;
     54 	\**)	continue;;
     55 	\;*)	continue;;
     56 	\#*)	continue;;
     57 	esac
     58 
     59 	case "${line}" in
     60 	*'#if'*)
     61 		COND="${line#*#}"
     62 		COND="#${COND%%#*}"
     63 		;;
     64 	*)
     65 		COND=
     66 		;;
     67 	esac
     68 	set -- ${line%%[ 	]#*}
     69 
     70 	var="$1" name="$2"
     71 
     72 	case "${var}" in
     73 	('' | [!A-Za-z_]* | *[!A-Za-z0-9_]*)
     74 		printf >&2 "Bad var name: '%s'\\n" "${var}"
     75 		# exit 1
     76 		continue	# just ignore it for now
     77 	esac
     78 
     79 	case "${name}" in
     80 	?) 	set -- ${var} '' $name $3 $4; name= ;;
     81 	esac
     82 
     83 	chr="$3" set="$4" dflt="$5"
     84 
     85 	case "${chr}" in
     86 	-)	chr= set= dflt="$4";;
     87 	''|?)	;;
     88 	*)	printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;;
     89 	esac
     90 
     91 	# options must have some kind of name, or they are useless...
     92 	test -z "${name}${chr}" && continue
     93 
     94 	case "${set}" in
     95 	-)	set= ;;
     96 	[01] | [Oo][Nn] | [Oo][Ff][Ff])	dflt="${set}"; set= ;;
     97 	''|?)	;;
     98 	*)	printf >&2 'set "%s": Not a character\n' "${set}"; continue;;
     99 	esac
    100 
    101 	case "${dflt}" in
    102 	'')		;;
    103 	[Oo][Nn])	dflt=1;;
    104 	[Oo][Ff][Ff])	dflt=0;;
    105 	[01])		;;
    106 	*)	printf >&2 'default "%s" invalid, use 0 off 1 on\n'; continue;;
    107 	esac
    108 
    109 	# validation complete, now to generate output
    110 
    111 	if [ -n "${COND}" ]
    112 	then
    113 		printf '%s\n' "${COND}" >&4
    114 		printf '%s\n' "${COND}" >&5
    115 		printf '%s\n' "${COND}" >&6
    116 	fi
    117 
    118 	printf '\t_SH_OPT_%s,\n' "${var}" >&5
    119 
    120 	if [ -n "${name}" ]
    121 	then
    122 		printf '    { "%s", ' "${name}"	>&4
    123 	else
    124 		printf '    { 0, '		>&4
    125 	fi
    126 
    127 	if [ -n "${chr}" ]
    128 	then
    129 		printf "'%s', " "${chr}"	>&4
    130 	else
    131 		chr=
    132 		printf '0, '			>&4
    133 	fi
    134 
    135 	if [ -n "${set}" ]
    136 	then
    137 		printf "'%s', 0, " "${set}"	>&4
    138 	else
    139 		printf '0, 0, '			>&4
    140 	fi
    141 
    142 	if [ -n "${dflt}" ]
    143 	then
    144 		printf '%s },\n' "${dflt}"	>&4
    145 	else
    146 		printf '0 },\n'			>&4
    147 	fi
    148 
    149 	printf '#define %s\toptlist[_SH_OPT_%s].val\n' "${var}" "${var}" >&6
    150 
    151 	if [ -n "${COND}" ]
    152 	then
    153 		printf '#endif\n' >&4
    154 		printf '#endif\n' >&5
    155 		printf '#endif\n' >&6
    156 	fi
    157 
    158 	test -z "${chr}" && continue
    159 
    160 	printf '%s _SH_OPT_%s %s\n' "${chr}" "${var}" "${COND}"
    161 
    162 done 4>>"${OF}" | sort -t' ' -k1,1f -k1,1 | while read chr index COND
    163 do
    164 	if $FIRST
    165 	then
    166 		printf '    { 0, 0, 0, 0, 0 }\n};\n'
    167 		printf '#endif\n\n'
    168 
    169 		printf 'enum shell_opt_names {\n'
    170 		cat "${E_FILE}"
    171 		printf '};\n\n'
    172 
    173 		printf '#ifdef DEFINE_OPTIONS\n'
    174 		printf 'const unsigned char optorder[] = {\n'
    175 		FIRST=false
    176 	fi
    177 	[ -n "${COND}" ] && printf '%s\n' "${COND}"
    178 	printf '\t%s,\n' "${index}"
    179 	[ -n "${COND}" ] && printf '#endif\n'
    180 
    181 done >>"${OF}"
    182 
    183 {
    184 	printf '};\n\n'
    185 	printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n'
    186 	printf 'int sizeof_optlist = sizeof optlist;\n\n'
    187 	printf	\
    188 	   'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n'
    189 	printf '\n#else\n\n'
    190 	printf 'extern struct optent optlist[];\n'
    191 	printf 'extern int sizeof_optlist;\n'
    192 	printf 'extern const unsigned char optorder[];\n'
    193 	printf 'extern const int option_flags;\n'
    194 	printf '\n#endif\n\n'
    195 
    196 	cat "${O_FILE}"
    197 } >> "${OF}"
    198 
    199 exit 0
    200