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