Home | History | Annotate | Download | only in xlat
      1 #!/bin/sh
      2 #
      3 # Copyright (c) 2014-2015 Mike Frysinger <vapier (at] gentoo.org>
      4 # Copyright (c) 2014-2015 Dmitry V. Levin <ldv (at] 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 
     29 usage()
     30 {
     31 	cat <<EOF
     32 Usage: $0 <input> <output>
     33 
     34 Generate xlat header files from <input> (a file or dir of files) and write
     35 the generated headers to <output>.
     36 EOF
     37 	exit 1
     38 }
     39 
     40 cond_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 
     62 cond_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 
     90 gen_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 
    207 gen_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 
    228 gen_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 
    239 main()
    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 
    279 main "$@"
    280