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