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