aboutsummaryrefslogtreecommitdiff
path: root/tcwg/cpp-script.sh
blob: fdc8cf065294791298537ae452501e5a3de62ae9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/bin/bash

# Clean: shellcheck -e 2001 ./cpp-script.sh

# NOTE: THIS SCRIPT HAS COPIES IN THE FOLLOWING REPOS:
# - CI/DOCKERFILES.GIT AND
# - CI/JOB/CONFIGS.GIT
# REMEMBER TO SYNCHRONIZE ALL COPIES ON CHANGES.

set -eu -o pipefail

input=""
vars=()

while [ $# -gt 0 ]; do
    case $1 in
	--input|-i) input="$2"; shift ;;
	--var|-v) vars+=("$2"); shift ;;
	*) echo "ERROR: Wrong option: $1"; usage ;;
    esac
    shift
done

if [ x"$input" = x"" ]; then
    echo "ERROR: No --input parameter"
    exit 1
fi

tmp_in=$(mktemp)
tmp_out=$(mktemp)
cp "$input" "$tmp_in"

# Iteratively include files until there are no more #include directives.
while grep -q "^#include .*\$" "$tmp_in"; do
    include=$(grep "^#include .*\$" "$tmp_in" | head -n1)
    inc_file=$(echo "$include" | sed -e "s/^#include \+//")
    if [ ! -f "$inc_file" ]; then
	echo "ERROR: #include file $inc_file does not exist" >&2
	exit 1
    fi
    # Escape '/' in the path name
    include=$(echo "$include" | sed -e "s#/#\\\\/#g")
    # Instruct sed to read in the include and add extra '#' to #include line.
    cat "$tmp_in" | sed -e "/^$include\$/ {
i #BEGIN: $inc_file
r $inc_file
a #END:   $inc_file
d
}" > "$tmp_out"
    cp "$tmp_out" "$tmp_in"
done

cpp_opts=()
# Undef all macros.  Next loop will define the appropriate ones to "1".
for macro in $(unifdef -s -k -t "$tmp_in"); do
    cpp_opts+=("-U${macro}")
done

declare -Ag vars_values
for var in "${vars[@]}"; do
    name=$(echo "$var" | cut -d= -f 1)
    value=$(echo "$var" | cut -s -d= -f 2)

    # Define requested macros to "1".
    cpp_opts+=("-D${name}_${value}=1")

    # Gather all values for $name in $vars_values[$name]
    if [ x"${vars_values[$name]+set}" = x"set" ]; then
        vars_values[$name]="${vars_values[$name]} $value"
    else
        vars_values[$name]="$value"
    fi
done

sed_opts=()
for name in "${!vars_values[@]}"; do
    # Substitute #{NAME} with VALUE.
    sed_opts+=("-e" "s/#{${name}}/${vars_values[$name]}/g")
done

unifdef -k -t -x2 "${cpp_opts[@]}" "$tmp_in" \
    | sed -e "s/^//" "${sed_opts[@]+"${sed_opts[@]}"}"