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