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 -r -n 's/^([^[:space:]]+).*$/\1/p')" 48 49 local def 50 def="$(printf %s "${line}" | 51 sed -r -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 62print_xlat() 63{ 64 local val 65 val="$1"; shift 66 67 if [ -z "${val_type-}" ]; then 68 echo " XLAT(${val})," 69 else 70 echo " XLAT_TYPE(${val_type}, ${val})," 71 fi 72} 73 74print_xlat_pair() 75{ 76 local val str 77 val="$1"; shift 78 str="$1"; shift 79 80 if [ -z "${val_type-}" ]; then 81 echo " XLAT_PAIR(${val}, \"${str}\")," 82 else 83 echo " XLAT_TYPE_PAIR(${val_type}, ${val}, \"${str}\")," 84 fi 85} 86 87cond_xlat() 88{ 89 local line val m def xlat 90 line="$1"; shift 91 92 val="$(printf %s "${line}" | sed -r -n 's/^([^[:space:]]+).*$/\1/p')" 93 m="${val%%|*}" 94 def="$(printf %s "${line}" | 95 sed -r -n 's/^[^[:space:]]+[[:space:]]+([^[:space:]].*)$/\1/p')" 96 97 if [ "${m}" = "${m#1<<}" ]; then 98 xlat="$(print_xlat "${val}")" 99 else 100 xlat="$(print_xlat_pair "1ULL<<${val#1<<}" "${val}")" 101 m="${m#1<<}" 102 fi 103 104 if [ -z "${def}" ]; then 105 cat <<-EOF 106 #if defined(${m}) || (defined(HAVE_DECL_${m}) && HAVE_DECL_${m}) 107 ${xlat} 108 #endif 109 EOF 110 else 111 echo "$xlat" 112 fi 113} 114 115gen_header() 116{ 117 local input="$1" output="$2" name="$3" 118 echo "generating ${output}" 119 ( 120 local defs="${0%/*}/../defs.h" 121 local mpers="${0%/*}/../mpers_xlat.h" 122 local decl="extern const struct xlat ${name}[];" 123 local in_defs= in_mpers= 124 125 if grep -F -x "$decl" "$defs" > /dev/null; then 126 in_defs=1 127 elif grep -F -x "$decl" "$mpers" > /dev/null; then 128 in_mpers=1 129 fi 130 131 echo "/* Generated by $0 from $1; do not edit. */" 132 133 local unconditional= unterminated= line 134 # 1st pass: output directives. 135 while read line; do 136 LC_COLLATE=C 137 case $line in 138 '#stop') 139 exit 0 140 ;; 141 '#conditional') 142 unconditional= 143 ;; 144 '#unconditional') 145 unconditional=1 146 ;; 147 '#unterminated') 148 unterminated=1 149 ;; 150 '#val_type '*) 151 # to be processed during 2nd pass 152 ;; 153 '#'*) 154 echo "${line}" 155 ;; 156 [A-Z_]*) 157 [ -n "$unconditional" ] || 158 cond_def "$line" 159 ;; 160 esac 161 done < "$input" 162 163 echo 164 if [ -n "$in_defs" ]; then 165 cat <<-EOF 166 #ifndef IN_MPERS 167 168 EOF 169 elif [ -n "$in_mpers" ]; then 170 cat <<-EOF 171 #ifdef IN_MPERS 172 173 ${decl} 174 175 #else 176 177 # if !(defined HAVE_M32_MPERS || defined HAVE_MX32_MPERS) 178 static 179 # endif 180 EOF 181 else 182 cat <<-EOF 183 #ifdef IN_MPERS 184 185 # error static const struct xlat ${name} in mpers mode 186 187 #else 188 189 static 190 EOF 191 fi 192 echo "const struct xlat ${name}[] = {" 193 194 unconditional= val_type= 195 # 2nd pass: output everything. 196 while read line; do 197 LC_COLLATE=C 198 case ${line} in 199 '#conditional') 200 unconditional= 201 ;; 202 '#unconditional') 203 unconditional=1 204 ;; 205 '#unterminated') 206 # processed during 1st pass 207 ;; 208 '#val_type '*) 209 val_type="${line#\#val_type }" 210 ;; 211 [A-Z_]*) # symbolic constants 212 if [ -n "${unconditional}" ]; then 213 print_xlat "${line}" 214 else 215 cond_xlat "${line}" 216 fi 217 ;; 218 '1<<'[A-Z_]*) # symbolic constants with shift 219 if [ -n "${unconditional}" ]; then 220 print_xlat_pair "1ULL<<${line#1<<}" "${line}" 221 else 222 cond_xlat "${line}" 223 fi 224 ;; 225 [0-9]*) # numeric constants 226 print_xlat "${line}" 227 ;; 228 *) # verbatim lines 229 echo "${line}" 230 ;; 231 esac 232 done < "${input}" 233 if [ -n "${unterminated}" ]; then 234 echo " /* this array should remain not NULL-terminated */" 235 else 236 echo " XLAT_END" 237 fi 238 239 cat <<-EOF 240 }; 241 242 #endif /* !IN_MPERS */ 243 EOF 244 ) >"${output}" 245} 246 247gen_make() 248{ 249 local output="$1" 250 local name 251 shift 252 echo "generating ${output}" 253 ( 254 printf "XLAT_INPUT_FILES = " 255 printf 'xlat/%s.in ' "$@" 256 echo 257 printf "XLAT_HEADER_FILES = " 258 printf 'xlat/%s.h ' "$@" 259 echo 260 for name; do 261 printf '$(top_srcdir)/xlat/%s.h: $(top_srcdir)/xlat/%s.in $(top_srcdir)/xlat/gen.sh\n' \ 262 "${name}" "${name}" 263 echo ' $(AM_V_GEN)$(top_srcdir)/xlat/gen.sh $< $@' 264 done 265 ) >"${output}" 266} 267 268gen_git() 269{ 270 local output="$1" 271 shift 272 echo "generating ${output}" 273 ( 274 printf '/%s\n' .gitignore Makemodule.am 275 printf '/%s.h\n' "$@" 276 ) >"${output}" 277} 278 279main() 280{ 281 case $# in 282 0) set -- "${0%/*}" "${0%/*}" ;; 283 2) ;; 284 *) usage ;; 285 esac 286 287 local input="$1" 288 local output="$2" 289 local name 290 local jobs=0 291 local ncpus="$(getconf _NPROCESSORS_ONLN)" 292 [ "${ncpus}" -ge 1 ] || 293 ncpus=1 294 295 if [ -d "${input}" ]; then 296 local f names= 297 for f in "${input}"/*.in; do 298 [ -f "${f}" ] || continue 299 name=${f##*/} 300 name=${name%.in} 301 gen_header "${f}" "${output}/${name}.h" "${name}" & 302 names="${names} ${name}" 303 : $(( jobs += 1 )) 304 if [ ${jobs} -ge ${ncpus} ]; then 305 jobs=0 306 wait 307 fi 308 done 309 gen_git "${output}/.gitignore" ${names} 310 gen_make "${output}/Makemodule.am" ${names} 311 wait 312 else 313 name=${input##*/} 314 name=${name%.in} 315 gen_header "${input}" "${output}" "${name}" 316 fi 317} 318 319main "$@" 320