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