Dmitry V. Levin
5cb45b25a3
Avoid duplicate definitions of xlat structures in files compiled in mpers mode. Each xlat file defines the corresponding xlat struct with either global or local visibility using the following rules: - if xlat struct declaration is available in defs.h, a global definition is provided in regular mode, and nothing is provided in mpers mode; - otherwise, if xlat file is included by a mpers source file, a global definition is provided in regular mode (unless no mpers mode is supported on this architecture, in that case, a local definition is provided instead), and a declaration is provided in mpers mode; - otherwise, a local definition is provided in regular mode, and an error message is printed in mpers mode. Fallback definitions of constants provided by xlat files remain available in all modes. * bootstrap: Invoke generate_mpers_am.sh before xlat/gen.sh. * defs.h (adjtimex_modes, adjtimex_status, sigev_value): Remove. * generate_mpers_am.sh: Generate mpers_xlat.h. * Makefile.am (EXTRA_DIST): Add mpers_xlat.h. * print_sigevent.c: Include "xlat/sigev_value.h" unconditionally. * print_timex.c: Include "xlat/adjtimex_modes.h" and "xlat/adjtimex_status.h" unconditionally. * xlat/gen.sh (cond_xlat): Move printing of fallback definitions ... (cond_def): ... here. (gen_header): Check also mpers_xlat.h for global declarations of xlat structures. Process input file twice, first time print directives only, second time print everything. Wrap struct xlat into #ifdef IN_MPERS ... #else ... #endif. * xlat/getrandom_flags.in: Cleanup.
254 lines
4.3 KiB
Bash
Executable File
254 lines
4.3 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
usage()
|
|
{
|
|
cat <<EOF
|
|
Usage: $0 <input> <output>
|
|
|
|
Generate xlat header files from <input> (a file or dir of files) and write
|
|
the generated headers to <output>.
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
cond_def()
|
|
{
|
|
local line
|
|
line="$1"; shift
|
|
|
|
local val
|
|
val="$(printf %s "$line" |
|
|
sed -n 's/^\([^[:space:]]\+\).*$/\1/p')"
|
|
|
|
local def
|
|
def="$(printf %s "${line}" |
|
|
sed -n 's/^[^[:space:]]\+[[:space:]]\+\([^[:space:]].*\)$/\1/p')"
|
|
|
|
if [ -n "$def" ]; then
|
|
cat <<-EOF
|
|
#if !(defined($val) || (defined(HAVE_DECL_$val) && HAVE_DECL_$val))
|
|
# define $val $def
|
|
#endif
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
cond_xlat()
|
|
{
|
|
local line val m def xlat
|
|
line="$1"; shift
|
|
|
|
val="$(printf %s "${line}" | sed -n 's/^\([^[:space:]]\+\).*$/\1/p')"
|
|
m="${val%%|*}"
|
|
def="$(printf %s "${line}" |
|
|
sed -n 's/^[^[:space:]]\+[[:space:]]\+\([^[:space:]].*\)$/\1/p')"
|
|
|
|
if [ "${m}" = "${m#1<<}" ]; then
|
|
xlat=" XLAT(${val}),"
|
|
else
|
|
m="${m#1<<}"
|
|
xlat=" { ${val}, \"${m}\" },"
|
|
fi
|
|
|
|
if [ -z "${def}" ]; then
|
|
cat <<-EOF
|
|
#if defined(${m}) || (defined(HAVE_DECL_${m}) && HAVE_DECL_${m})
|
|
${xlat}
|
|
#endif
|
|
EOF
|
|
else
|
|
echo "$xlat"
|
|
fi
|
|
}
|
|
|
|
gen_header()
|
|
{
|
|
local input="$1" output="$2" name="$3"
|
|
echo "generating ${output}"
|
|
(
|
|
local defs="${0%/*}/../defs.h"
|
|
local mpers="${0%/*}/../mpers_xlat.h"
|
|
local decl="extern const struct xlat ${name}[];"
|
|
local in_defs= in_mpers=
|
|
|
|
if grep -F -x "$decl" "$defs" > /dev/null; then
|
|
in_defs=1
|
|
elif grep -F -x "$decl" "$mpers" > /dev/null; then
|
|
in_mpers=1
|
|
fi
|
|
|
|
echo "/* Generated by $0 from $1; do not edit. */"
|
|
|
|
local unconditional= unterminated= line
|
|
# 1st pass: output directives.
|
|
while read line; do
|
|
LC_COLLATE=C
|
|
case $line in
|
|
'#unconditional')
|
|
unconditional=1
|
|
;;
|
|
'#unterminated')
|
|
unterminated=1
|
|
;;
|
|
'#'*)
|
|
echo "${line}"
|
|
;;
|
|
[A-Z_]*)
|
|
[ -n "$unconditional" ] ||
|
|
cond_def "$line"
|
|
;;
|
|
esac
|
|
done < "$input"
|
|
|
|
echo
|
|
if [ -n "$in_defs" ]; then
|
|
cat <<-EOF
|
|
#ifndef IN_MPERS
|
|
|
|
EOF
|
|
elif [ -n "$in_mpers" ]; then
|
|
cat <<-EOF
|
|
#ifdef IN_MPERS
|
|
|
|
${decl}
|
|
|
|
#else
|
|
|
|
# if !(defined HAVE_M32_MPERS || defined HAVE_MX32_MPERS)
|
|
static
|
|
# endif
|
|
EOF
|
|
else
|
|
cat <<-EOF
|
|
#ifdef IN_MPERS
|
|
|
|
# error static const struct xlat ${name} in mpers mode
|
|
|
|
#else
|
|
|
|
static
|
|
EOF
|
|
fi
|
|
echo "const struct xlat ${name}[] = {"
|
|
|
|
unconditional=
|
|
# 2nd pass: output everything.
|
|
while read line; do
|
|
LC_COLLATE=C
|
|
case ${line} in
|
|
'#unconditional')
|
|
unconditional=1
|
|
;;
|
|
'#unterminated')
|
|
# processed during 1st pass
|
|
;;
|
|
[A-Z_]*) # symbolic constants
|
|
if [ -n "${unconditional}" ]; then
|
|
echo " XLAT(${line}),"
|
|
else
|
|
cond_xlat "${line}"
|
|
fi
|
|
;;
|
|
'1<<'[A-Z_]*) # symbolic constants with shift
|
|
if [ -n "${unconditional}" ]; then
|
|
echo " { ${line}, \"${line#1<<}\" },"
|
|
else
|
|
cond_xlat "${line}"
|
|
fi
|
|
;;
|
|
[0-9]*) # numeric constants
|
|
echo " XLAT(${line}),"
|
|
;;
|
|
*) # verbatim lines
|
|
echo "${line}"
|
|
;;
|
|
esac
|
|
done < "${input}"
|
|
if [ -n "${unterminated}" ]; then
|
|
echo " /* this array should remain not NULL-terminated */"
|
|
else
|
|
echo " XLAT_END"
|
|
fi
|
|
|
|
cat <<-EOF
|
|
};
|
|
|
|
#endif /* !IN_MPERS */
|
|
EOF
|
|
) >"${output}"
|
|
}
|
|
|
|
gen_make()
|
|
{
|
|
local output="$1"
|
|
local name
|
|
shift
|
|
echo "generating ${output}"
|
|
(
|
|
printf "XLAT_INPUT_FILES = "
|
|
printf 'xlat/%s.in ' "$@"
|
|
echo
|
|
printf "XLAT_HEADER_FILES = "
|
|
printf 'xlat/%s.h ' "$@"
|
|
echo
|
|
for name; do
|
|
printf '$(top_srcdir)/xlat/%s.h: $(top_srcdir)/xlat/%s.in $(top_srcdir)/xlat/gen.sh\n' \
|
|
"${name}" "${name}"
|
|
echo ' $(AM_V_GEN)$(top_srcdir)/xlat/gen.sh $< $@'
|
|
done
|
|
) >"${output}"
|
|
}
|
|
|
|
gen_git()
|
|
{
|
|
local output="$1"
|
|
shift
|
|
echo "generating ${output}"
|
|
(
|
|
printf '/%s\n' .gitignore Makemodule.am
|
|
printf '/%s.h\n' "$@"
|
|
) >"${output}"
|
|
}
|
|
|
|
main()
|
|
{
|
|
case $# in
|
|
0) set -- "${0%/*}" "${0%/*}" ;;
|
|
2) ;;
|
|
*) usage ;;
|
|
esac
|
|
|
|
local input="$1"
|
|
local output="$2"
|
|
local name
|
|
local jobs=0
|
|
local ncpus="$(getconf _NPROCESSORS_ONLN)"
|
|
[ "${ncpus}" -ge 1 ] ||
|
|
ncpus=1
|
|
|
|
if [ -d "${input}" ]; then
|
|
local f names=
|
|
for f in "${input}"/*.in; do
|
|
[ -f "${f}" ] || continue
|
|
name=${f##*/}
|
|
name=${name%.in}
|
|
gen_header "${f}" "${output}/${name}.h" "${name}" &
|
|
names="${names} ${name}"
|
|
: $(( jobs += 1 ))
|
|
if [ ${jobs} -ge ${ncpus} ]; then
|
|
jobs=0
|
|
wait
|
|
fi
|
|
done
|
|
gen_git "${output}/.gitignore" ${names}
|
|
gen_make "${output}/Makemodule.am" ${names}
|
|
wait
|
|
else
|
|
name=${input##*/}
|
|
name=${name%.in}
|
|
gen_header "${input}" "${output}" "${name}"
|
|
fi
|
|
}
|
|
|
|
main "$@"
|