#!/bin/sh self=$0 usage() { cat <&2 Usage: $self [options] FILE Reads the Run Time CPU Detections definitions from FILE and generates a C header file on stdout. Options: --arch=ARCH Architecture to generate defs for (required) --disable-EXT Disable support for EXT extensions --require-EXT Require support for EXT extensions --sym=SYMBOL Unique symbol to use for RTCD initialization function --config=FILE File with CONFIG_FOO=yes lines to parse EOF exit 1 } die() { echo "$@" >&2 exit 1 } die_argument_required() { die "Option $opt requires argument" } for opt; do optval="${opt#*=}" case "$opt" in --arch) die_argument_required;; --arch=*) arch=${optval};; --disable-*) eval "disable_${opt#--disable-}=true";; --require-*) REQUIRES="${REQUIRES}${opt#--require-} ";; --sym) die_argument_required;; --sym=*) symbol=${optval};; --config=*) config_file=${optval};; -h|--help) usage ;; -*) die "Unrecognized option: ${opt%%=*}" ;; *) defs_file="$defs_file $opt" ;; esac shift done for f in $defs_file; do [ -f "$f" ] || usage; done [ -n "$arch" ] || usage # Import the configuration [ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file") # # Routines for the RTCD DSL to call # prototype() { rtyp="" case "$1" in unsigned) rtyp="$1 "; shift;; esac rtyp="${rtyp}$1" fn="$2" args="$3" eval "${2}_rtyp='$rtyp'" eval "${2}_args='$3'" ALL_FUNCS="$ALL_FUNCS $fn" specialize $fn c } specialize() { fn="$1" shift for opt in "$@"; do eval "${fn}_${opt}=${fn}_${opt}" done } require() { for fn in $ALL_FUNCS; do for opt in "$@"; do ofn=$(eval "echo \$${fn}_${opt}") [ -z "$ofn" ] && continue # if we already have a default, then we can disable it, as we know # we can do better. best=$(eval "echo \$${fn}_default") best_ofn=$(eval "echo \$${best}") [ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false" eval "${fn}_default=${fn}_${opt}" eval "${fn}_${opt}_link=true" done done } forward_decls() { ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1" } # # Include the user's directives # for f in $defs_file; do . $f done # # Process the directives according to the command line # process_forward_decls() { for fn in $ALL_FORWARD_DECLS; do eval $fn done } determine_indirection() { [ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS for fn in $ALL_FUNCS; do n="" rtyp="$(eval "echo \$${fn}_rtyp")" args="$(eval "echo \"\$${fn}_args\"")" dfn="$(eval "echo \$${fn}_default")" dfn=$(eval "echo \$${dfn}") for opt in "$@"; do ofn=$(eval "echo \$${fn}_${opt}") [ -z "$ofn" ] && continue link=$(eval "echo \$${fn}_${opt}_link") [ "$link" = "false" ] && continue n="${n}x" done if [ "$n" = "x" ]; then eval "${fn}_indirect=false" else eval "${fn}_indirect=true" fi done } declare_function_pointers() { for fn in $ALL_FUNCS; do rtyp="$(eval "echo \$${fn}_rtyp")" args="$(eval "echo \"\$${fn}_args\"")" dfn="$(eval "echo \$${fn}_default")" dfn=$(eval "echo \$${dfn}") for opt in "$@"; do ofn=$(eval "echo \$${fn}_${opt}") [ -z "$ofn" ] && continue echo "$rtyp ${ofn}($args);" done if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then echo "#define ${fn} ${dfn}" else echo "RTCD_EXTERN $rtyp (*${fn})($args);" fi echo done } set_function_pointers() { for fn in $ALL_FUNCS; do n="" rtyp="$(eval "echo \$${fn}_rtyp")" args="$(eval "echo \"\$${fn}_args\"")" dfn="$(eval "echo \$${fn}_default")" dfn=$(eval "echo \$${dfn}") if $(eval "echo \$${fn}_indirect"); then echo " $fn = $dfn;" for opt in "$@"; do ofn=$(eval "echo \$${fn}_${opt}") [ -z "$ofn" ] && continue [ "$ofn" = "$dfn" ] && continue; link=$(eval "echo \$${fn}_${opt}_link") [ "$link" = "false" ] && continue cond="$(eval "echo \$have_${opt}")" echo " if (${cond}) $fn = $ofn;" done fi echo done } filter() { filtered="" for opt in "$@"; do [ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt" done echo $filtered } # # Helper functions for generating the arch specific RTCD files # common_top() { outfile_basename=$(basename ${symbol:-rtcd}) include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | \ tr -c '[A-Z0-9]' _)H_ cat <