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