• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# Copyright (c) 2014-2015 Mike Frysinger <vapier@gentoo.org>
4# Copyright (c) 2014-2015 Dmitry V. Levin <ldv@altlinux.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. The name of the author may not be used to endorse or promote products
16#    derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29usage()
30{
31	cat <<EOF
32Usage: $0 <input> <output>
33
34Generate xlat header files from <input> (a file or dir of files) and write
35the generated headers to <output>.
36EOF
37	exit 1
38}
39
40cond_def()
41{
42	local line
43	line="$1"; shift
44
45	local val
46	val="$(printf %s "$line" |
47		sed -n 's/^\([^[:space:]]\+\).*$/\1/p')"
48
49	local def
50	def="$(printf %s "${line}" |
51		sed -n 's/^[^[:space:]]\+[[:space:]]\+\([^[:space:]].*\)$/\1/p')"
52
53	if [ -n "$def" ]; then
54		cat <<-EOF
55		#if !(defined($val) || (defined(HAVE_DECL_$val) && HAVE_DECL_$val))
56		# define $val $def
57		#endif
58		EOF
59	fi
60}
61
62cond_xlat()
63{
64	local line val m def xlat
65	line="$1"; shift
66
67	val="$(printf %s "${line}" | sed -n 's/^\([^[:space:]]\+\).*$/\1/p')"
68	m="${val%%|*}"
69	def="$(printf %s "${line}" |
70	       sed -n 's/^[^[:space:]]\+[[:space:]]\+\([^[:space:]].*\)$/\1/p')"
71
72	if [ "${m}" = "${m#1<<}" ]; then
73		xlat=" XLAT(${val}),"
74	else
75		m="${m#1<<}"
76		xlat=" { ${val}, \"${m}\" },"
77	fi
78
79	if [ -z "${def}" ]; then
80		cat <<-EOF
81		#if defined(${m}) || (defined(HAVE_DECL_${m}) && HAVE_DECL_${m})
82		 ${xlat}
83		#endif
84		EOF
85	else
86		echo "$xlat"
87	fi
88}
89
90gen_header()
91{
92	local input="$1" output="$2" name="$3"
93	echo "generating ${output}"
94	(
95	local defs="${0%/*}/../defs.h"
96	local mpers="${0%/*}/../mpers_xlat.h"
97	local decl="extern const struct xlat ${name}[];"
98	local in_defs= in_mpers=
99
100	if grep -F -x "$decl" "$defs" > /dev/null; then
101		in_defs=1
102	elif grep -F -x "$decl" "$mpers" > /dev/null; then
103		in_mpers=1
104	fi
105
106	echo "/* Generated by $0 from $1; do not edit. */"
107
108	local unconditional= unterminated= line
109	# 1st pass: output directives.
110	while read line; do
111		LC_COLLATE=C
112		case $line in
113		'#unconditional')
114			unconditional=1
115			;;
116		'#unterminated')
117			unterminated=1
118			;;
119		'#'*)
120			echo "${line}"
121			;;
122		[A-Z_]*)
123			[ -n "$unconditional" ] ||
124				cond_def "$line"
125			;;
126		esac
127	done < "$input"
128
129	echo
130	if [ -n "$in_defs" ]; then
131		cat <<-EOF
132			#ifndef IN_MPERS
133
134		EOF
135	elif [ -n "$in_mpers" ]; then
136		cat <<-EOF
137			#ifdef IN_MPERS
138
139			${decl}
140
141			#else
142
143			# if !(defined HAVE_M32_MPERS || defined HAVE_MX32_MPERS)
144			static
145			# endif
146		EOF
147	else
148		cat <<-EOF
149			#ifdef IN_MPERS
150
151			# error static const struct xlat ${name} in mpers mode
152
153			#else
154
155			static
156		EOF
157	fi
158	echo "const struct xlat ${name}[] = {"
159
160	unconditional=
161	# 2nd pass: output everything.
162	while read line; do
163		LC_COLLATE=C
164		case ${line} in
165		'#unconditional')
166			unconditional=1
167			;;
168		'#unterminated')
169			# processed during 1st pass
170			;;
171		[A-Z_]*)	# symbolic constants
172			if [ -n "${unconditional}" ]; then
173				echo " XLAT(${line}),"
174			else
175				cond_xlat "${line}"
176			fi
177			;;
178		'1<<'[A-Z_]*)	# symbolic constants with shift
179			if [ -n "${unconditional}" ]; then
180				echo " { ${line}, \"${line#1<<}\" },"
181			else
182				cond_xlat "${line}"
183			fi
184			;;
185		[0-9]*)	# numeric constants
186			echo " XLAT(${line}),"
187			;;
188		*)	# verbatim lines
189			echo "${line}"
190			;;
191		esac
192	done < "${input}"
193	if [ -n "${unterminated}" ]; then
194		echo " /* this array should remain not NULL-terminated */"
195	else
196		echo " XLAT_END"
197	fi
198
199	cat <<-EOF
200		};
201
202		#endif /* !IN_MPERS */
203	EOF
204	) >"${output}"
205}
206
207gen_make()
208{
209	local output="$1"
210	local name
211	shift
212	echo "generating ${output}"
213	(
214		printf "XLAT_INPUT_FILES = "
215		printf 'xlat/%s.in ' "$@"
216		echo
217		printf "XLAT_HEADER_FILES = "
218		printf 'xlat/%s.h ' "$@"
219		echo
220		for name; do
221			printf '$(top_srcdir)/xlat/%s.h: $(top_srcdir)/xlat/%s.in $(top_srcdir)/xlat/gen.sh\n' \
222				"${name}" "${name}"
223			echo '	$(AM_V_GEN)$(top_srcdir)/xlat/gen.sh $< $@'
224		done
225	) >"${output}"
226}
227
228gen_git()
229{
230	local output="$1"
231	shift
232	echo "generating ${output}"
233	(
234		printf '/%s\n' .gitignore Makemodule.am
235		printf '/%s.h\n' "$@"
236	) >"${output}"
237}
238
239main()
240{
241	case $# in
242	0) set -- "${0%/*}" "${0%/*}" ;;
243	2) ;;
244	*) usage ;;
245	esac
246
247	local input="$1"
248	local output="$2"
249	local name
250	local jobs=0
251	local ncpus="$(getconf _NPROCESSORS_ONLN)"
252	[ "${ncpus}" -ge 1 ] ||
253		ncpus=1
254
255	if [ -d "${input}" ]; then
256		local f names=
257		for f in "${input}"/*.in; do
258			[ -f "${f}" ] || continue
259			name=${f##*/}
260			name=${name%.in}
261			gen_header "${f}" "${output}/${name}.h" "${name}" &
262			names="${names} ${name}"
263			: $(( jobs += 1 ))
264			if [ ${jobs} -ge ${ncpus} ]; then
265				jobs=0
266				wait
267			fi
268		done
269		gen_git "${output}/.gitignore" ${names}
270		gen_make "${output}/Makemodule.am" ${names}
271		wait
272	else
273		name=${input##*/}
274		name=${name%.in}
275		gen_header "${input}" "${output}" "${name}"
276	fi
277}
278
279main "$@"
280