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 case $line in 139 '#stop') 140 exit 0 141 ;; 142 '#conditional') 143 unconditional= 144 ;; 145 '#unconditional') 146 unconditional=1 147 ;; 148 '#unterminated') 149 unterminated=1 150 ;; 151 '#val_type '*) 152 # to be processed during 2nd pass 153 ;; 154 '#'*) 155 echo "${line}" 156 ;; 157 [A-Z_]*) 158 [ -n "$unconditional" ] || 159 cond_def "$line" 160 ;; 161 esac 162 done < "$input" 163 164 echo 165 if [ -n "$in_defs" ]; then 166 cat <<-EOF 167 #ifndef IN_MPERS 168 169 EOF 170 elif [ -n "$in_mpers" ]; then 171 cat <<-EOF 172 #ifdef IN_MPERS 173 174 ${decl} 175 176 #else 177 178 # if !(defined HAVE_M32_MPERS || defined HAVE_MX32_MPERS) 179 static 180 # endif 181 EOF 182 else 183 cat <<-EOF 184 #ifdef IN_MPERS 185 186 # error static const struct xlat ${name} in mpers mode 187 188 #else 189 190 static 191 EOF 192 fi 193 echo "const struct xlat ${name}[] = {" 194 195 unconditional= val_type= 196 # 2nd pass: output everything. 197 while read line; do 198 LC_COLLATE=C 199 case ${line} in 200 '#conditional') 201 unconditional= 202 ;; 203 '#unconditional') 204 unconditional=1 205 ;; 206 '#unterminated') 207 # processed during 1st pass 208 ;; 209 '#val_type '*) 210 val_type="${line#\#val_type }" 211 ;; 212 [A-Z_]*) # symbolic constants 213 if [ -n "${unconditional}" ]; then 214 print_xlat "${line}" 215 else 216 cond_xlat "${line}" 217 fi 218 ;; 219 '1<<'[A-Z_]*) # symbolic constants with shift 220 if [ -n "${unconditional}" ]; then 221 print_xlat_pair "1ULL<<${line#1<<}" "${line}" 222 else 223 cond_xlat "${line}" 224 fi 225 ;; 226 [0-9]*) # numeric constants 227 print_xlat "${line}" 228 ;; 229 *) # verbatim lines 230 echo "${line}" 231 ;; 232 esac 233 done < "${input}" 234 if [ -n "${unterminated}" ]; then 235 echo " /* this array should remain not NULL-terminated */" 236 else 237 echo " XLAT_END" 238 fi 239 240 cat <<-EOF 241 }; 242 243 #endif /* !IN_MPERS */ 244 EOF 245 ) >"${output}" 246} 247 248gen_make() 249{ 250 local output="$1" 251 local name 252 shift 253 echo "generating ${output}" 254 ( 255 printf "XLAT_INPUT_FILES = " 256 printf 'xlat/%s.in ' "$@" 257 echo 258 printf "XLAT_HEADER_FILES = " 259 printf 'xlat/%s.h ' "$@" 260 echo 261 for name; do 262 printf '$(top_srcdir)/xlat/%s.h: $(top_srcdir)/xlat/%s.in $(top_srcdir)/xlat/gen.sh\n' \ 263 "${name}" "${name}" 264 echo ' $(AM_V_GEN)$(top_srcdir)/xlat/gen.sh $< $@' 265 done 266 ) >"${output}" 267} 268 269gen_git() 270{ 271 local output="$1" 272 shift 273 echo "generating ${output}" 274 ( 275 printf '/%s\n' .gitignore Makemodule.am 276 printf '/%s.h\n' "$@" 277 ) >"${output}" 278} 279 280main() 281{ 282 case $# in 283 0) set -- "${0%/*}" "${0%/*}" ;; 284 2) ;; 285 *) usage ;; 286 esac 287 288 local input="$1" 289 local output="$2" 290 local name 291 local jobs=0 292 local ncpus="$(getconf _NPROCESSORS_ONLN)" 293 [ "${ncpus}" -ge 1 ] || 294 ncpus=1 295 296 if [ -d "${input}" ]; then 297 local f names= 298 for f in "${input}"/*.in; do 299 [ -f "${f}" ] || continue 300 name=${f##*/} 301 name=${name%.in} 302 gen_header "${f}" "${output}/${name}.h" "${name}" & 303 names="${names} ${name}" 304 : $(( jobs += 1 )) 305 if [ ${jobs} -ge ${ncpus} ]; then 306 jobs=0 307 wait 308 fi 309 done 310 gen_git "${output}/.gitignore" ${names} 311 gen_make "${output}/Makemodule.am" ${names} 312 wait 313 else 314 name=${input##*/} 315 name=${name%.in} 316 gen_header "${input}" "${output}" "${name}" 317 fi 318} 319 320main "$@" 321