1#!/bin/sh
2###########################################################################
3#
4#  Window Maker window manager
5#
6#  Copyright (c) 2015 Christophe CURIS
7#  Copyright (c) 2015 Window Maker Team
8#
9#  This program is free software; you can redistribute it and/or modify
10#  it under the terms of the GNU General Public License as published by
11#  the Free Software Foundation; either version 2 of the License, or
12#  (at your option) any later version.
13#
14#  This program is distributed in the hope that it will be useful,
15#  but WITHOUT ANY WARRANTY; without even the implied warranty of
16#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17#  GNU General Public License for more details.
18#
19#  You should have received a copy of the GNU General Public License along
20#  with this program; if not, write to the Free Software Foundation, Inc.,
21#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22#
23###########################################################################
24#
25# replace-ac-keywords.sh:
26#   generate text file from a template text file, processing @keywords@
27# from configure's detected stuff
28#
29# This follows the principle similar to what Autoconf does for the files
30# defined in AC_CONFIG_FILES; the reasons for this script are:
31#
32#  - Autoconf recommends to only defined Makefiles in that macro and to
33# process the rest (if possible) through a Make rule;
34#
35#  - we also take the opportunity to get access to the AC_DEFINE stuff
36# without needing to AC_SUBST them, which would grow unnecessarily the
37# makefile;
38#
39#  - contrary to Autoconf, we also give the possibility to completely
40# remove lines from the template, where Autoconf only comments them (when
41# using AM_CONDITIONAL for example)
42#
43###########################################################################
44#
45# Please note that this script is writen in sh+sed on purpose: this script
46# is gonna be run on the machine of the person who is trying to compile
47# WindowMaker, and as such we cannot be sure to find any scripting language
48# in a known version and that works (python/ruby/tcl/perl/php/you-name-it).
49#
50# So for portability, we stick to the same sh+awk constraint as Autotools
51# to limit the problem, see for example:
52#   http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Portable-Shell.html
53#
54###########################################################################
55
56# Report an error on stderr and exit with status 2 to tell make that we could
57# not do what we were asked
58arg_error() {
59    echo "$0: $@" >&2
60    exit 2
61}
62
63# print help and exit with success status
64print_help() {
65    echo "$0: convert a Texinfo file into a plain text file"
66    echo "Usage: $0 [options...] <template-file>"
67    echo "valid options are:"
68    echo "  -Dkey=value   : define 'key' to the value 'value'"
69    echo "  --filter key  : remove lines containing @key@ if it is undefined"
70    echo "  --header file : C header file to parse for #define"
71    echo "  -o file       : name for the output file"
72    echo "  --replace key : replace @key@ with its value"
73    exit 0
74}
75
76# Parse a C header file and add the defined lines to the list of known keys+values
77# We explicitely excludes macros defined on multiple lines and macros with arguments
78# Skip value defined to '0' to consider them as undefine
79extract_vars_from_c_header ()
80{
81  sed -n '/^#[ \t]*define[ \t][ \t]*[A-Za-z][A-Za-z_0-9]*[ \t].*[^\\]$/ {
82            s/^#[ \t]*define[ \t]*//
83            s/[ \t][ \t]*/=/
84            /=0$/d
85            p
86          }' "$1"
87}
88
89# Extract command line arguments
90while [ $# -gt 0 ]; do
91    case $1 in
92
93        -D*)
94            echo "$1" | grep '^-D[a-zA-Z][a-z_A-Z0-9]*=' > /dev/null || arg_error "syntax error for '$1', expected -Dname=value"
95            var_defs="$var_defs
96`echo "$1" | sed -e 's/^-D//' `"
97          ;;
98
99        --filter)
100            shift
101            list_filters="$list_filters $1"
102          ;;
103
104        --header)
105            shift
106            [ -r "$1" ] || arg_error "header file \"$1\" is not readable"
107            var_defs="$var_defs
108`extract_vars_from_c_header "$1" `"
109          ;;
110
111        -h|-help|--help) print_help ;;
112
113        -o)
114            shift
115            output_file="$1"
116          ;;
117
118        --replace)
119            shift
120            list_replaces="$list_replaces $1"
121          ;;
122
123        -*) arg_error "unknow option '$1'" ;;
124
125        *)
126            [ "x$input_file" = "x" ] || arg_error "only 1 input file can be specified, not \"$input_file\" and \"$1\""
127            input_file="$1"
128          ;;
129    esac
130    shift
131done
132
133# Check consistency of command-line
134[ "x$input_file" != "x" ] || arg_error "no input template file given"
135[ "x$output_file" != "x" ] || arg_error "no output file given"
136
137[ "x$list_replaces$list_filters" != "x" ] || arg_error "no key to process from template"
138
139###########################################################################
140
141# Generate the SED commands to replace the requested keys
142for key in $list_replaces
143do
144  # if there are multiple possible values, keep the last
145  value=`echo "$var_defs" | grep "^$key=" | tail -1 `
146  [ "x$value" != "x" ] || arg_error "key \"$key\" does not have a value"
147  sed_cmd="$sed_cmd
148    s#@$key@#`echo "$value" | sed -e 's/^[^=]*=//' `#"
149done
150
151# Generate the SED commands to filter lines with the specified keys
152for key in $list_filters
153do
154  if echo "$var_defs" | grep "^$key=" > /dev/null ; then
155    sed_cmd="$sed_cmd
156      s#@$key@##
157      /@!$key@/d"
158  else
159    sed_cmd="$sed_cmd
160      s#@!$key@##
161      /@$key@/d"
162  fi
163done
164
165###########################################################################
166
167sed -e "$sed_cmd" < "$input_file" > "$output_file"
168