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