[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
trans-coord/gnun/server/gnun configure.ac Makef...
From: |
Pavel Kharitonov |
Subject: |
trans-coord/gnun/server/gnun configure.ac Makef... |
Date: |
Fri, 13 Mar 2015 18:02:49 +0000 |
CVSROOT: /sources/trans-coord
Module name: trans-coord
Changes by: Pavel Kharitonov <ineiev> 15/03/13 18:02:49
Modified files:
gnun/server/gnun: configure.ac Makefile.am NEWS
Added files:
gnun/server/gnun: expand-ssi.awk.in
gnun/server/gnun/tests/validate: 5 5.0.html 5.1.html match3
match3.1.html match3.0.html
Removed files:
gnun/server/gnun: expand-ssi.awk
Log message:
Fix some SSI expansion bugs; support regexp groups
as Apache variables.
* expand-ssi.awk: Replace with `expand-ssi.awk.in'.
* expand-ssi.awk.in:
* tests/validate/5:
* tests/validate/5.0.html:
* tests/validate/5.1.html:
* tests/validate/match3:
* tests/validate/match3.0.html:
* tests/validate/match3.1.html: New files.
* configure.ac: Check if awk supports third argument
in match(); make `expand-ssi.awk' of `expand-ssi.awk.in'.
Remove conftest files. Mention installcheck in the final
message.
* expand-ssi.awk.in: Support regexp groups as Apache
variables (when awk is gawk); don't unquote double
quotes in #if directives; don't unquote regular expressions
in directives like <!--#if expr="a = /'a'/" -->.
* Makefile.am: Add new tests; replace `expand-ssi.awk'
with `expand-ssi.awk.in' and its derivation.
* NEWS: Update.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/configure.ac?cvsroot=trans-coord&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/Makefile.am?cvsroot=trans-coord&r1=1.40&r2=1.41
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/NEWS?cvsroot=trans-coord&r1=1.112&r2=1.113
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/expand-ssi.awk.in?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/expand-ssi.awk?cvsroot=trans-coord&r1=1.6&r2=0
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/5?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/5.0.html?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/5.1.html?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/match3?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/match3.1.html?cvsroot=trans-coord&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/tests/validate/match3.0.html?cvsroot=trans-coord&rev=1.1
Patches:
Index: configure.ac
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/configure.ac,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- configure.ac 22 May 2014 11:17:06 -0000 1.44
+++ configure.ac 13 Mar 2015 18:02:47 -0000 1.45
@@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script.
# Copyright (C) 2008, 2009, 2010, 2011, 2012,
-# 2013, 2014 Free Software Foundation, Inc.
+# 2013, 2014, 2015 Free Software Foundation, Inc.
# This file is part of GNUnited Nations.
@@ -69,6 +69,17 @@
AC_ARG_VAR([AWK], [the `awk' program])
AX_CHECK_AWK_GSUB([decent_awk=yes], [decent_awk=no])
+AX_TRY_AWK_EXPOUT([match(a,b,c)],[],
+[
+ if(!match("abcdefg", /b((c)d)e(f)/, arr))
+ print "no match"
+ if (arr[1] != "cd" || arr[2] != "c" || arr[3] != "f"\
+ || arr[0] != "bcdef" || 4 in arr)
+ print "wrong grouping"
+ print "OK"
+], [OK], [match3=match], [match3=match_fallback])
+AC_SUBST([MATCH3], [$match3])
+AM_CONDITIONAL([HAVE_MATCH3], [test $match3 = match])
AC_ARG_VAR([SED], [the `sed' program])
AC_PROG_SED
@@ -89,6 +100,7 @@
Unlike GNU sed, the `sed' program doesn't support --in-place option.
])
])
+rm -f conftest0.sed confest.sed
AC_MSG_CHECKING([whether sed supports the `e' option of the `s' command])
test="$(echo false | ${SED} 's/.*/true/e')"
@@ -262,7 +274,7 @@
[have_xmllint=yes
AC_MSG_CHECKING([if XHTML DTDs are installed])
have_dtds=no
-cat > conftest.dtd <<'EOF'
+cat > conftest.html <<'EOF'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
@@ -274,14 +286,15 @@
</body>
</html>
EOF
-if $XMLLINT --valid --nonet --noout conftest.dtd 2> /dev/null ; then
+if $XMLLINT --valid --nonet --noout conftest.html 2> /dev/null ; then
have_dtds=yes;
fi
- if test "$have_dtds" = no; then
+rm -f conftest.html
+if test "$have_dtds" = no; then
AC_MSG_RESULT([$have_dtds (will use our copy)])
- else
+else
AC_MSG_RESULT([$have_dtds])
- fi
+fi
])
# Our validation scripts depend on awk and xmllint.
@@ -298,6 +311,8 @@
])
AS_CASE(["$decent_gettext-$gnun_cv_recent_po4a"], [yes-yes],
[AC_CONFIG_FILES([gnun-preconvert])])
+AS_CASE([$have_validation], [yes],
+ [AC_CONFIG_FILES([expand-ssi.awk])])
AC_OUTPUT
@@ -314,5 +329,6 @@
echo "VCS support... $have_vcs $cvs $svn $bzr"
echo "Use Multiviews naming conventions... $enable_multiviews"
echo
-echo "Type \"make\" to build the scripts and \"make install\" to install
-them along with the manuals."
+echo \
+"Type \"make\" to build the scripts, \"make install\" to install them
+along with the manuals, and \"make installcheck\" to run tests."
Index: Makefile.am
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/Makefile.am,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -b -r1.40 -r1.41
--- Makefile.am 28 Jun 2014 05:57:15 -0000 1.40
+++ Makefile.am 13 Mar 2015 18:02:47 -0000 1.41
@@ -41,12 +41,23 @@
endif
endif
-validation_tests = validate/1 validate/2 validate/3 validate/4
+validation_tests = validate/1 validate/2 validate/3 validate/4 validate/5
tests_available += $(validation_tests)
+if HAVE_MATCH3
+validation_tests += validate/match3
+else
+tests_available += validate/match3
+endif
+
+noinst_SCRIPTS = stamp-config.mk
+pkglibexec_SCRIPTS = copy-msgid mailfail update-localized-urls \
+ validate-html-notify
+
if HAVE_VALIDATION
bin_SCRIPTS += gnun-validate-html
tests_enabled += $(validation_tests)
+pkglibexec_SCRIPTS += expand-ssi.awk
endif
tests_available += clear-previous
@@ -60,10 +71,6 @@
tests_enabled += copy-msgid
endif
-noinst_SCRIPTS = stamp-config.mk
-pkglibexec_SCRIPTS = copy-msgid mailfail update-localized-urls \
- validate-html-notify
-
tests_available += diff-po add-fuzzy-diff
if HAVE_WDIFF
@@ -79,7 +86,7 @@
tests_available += make-prototype
tests_enabled += make-prototype
-dist_pkglibexec_SCRIPTS = expand-ssi.awk make-prototype.awk
+dist_pkglibexec_SCRIPTS = make-prototype.awk
installcheck-local:
@failed=0; pass=0; skip=0; \
@@ -169,7 +176,7 @@
dist_pkgdata_DATA = GNUmakefile
EXTRA_DIST = add-fuzzy-diff.in copy-msgid.in diff-po.awk.in \
- gnun-add-fuzzy-diff.in gnun-diff-po.in \
+ expand-ssi.awk.in gnun-add-fuzzy-diff.in gnun-diff-po.in \
gnun-init-po.in gnun-merge-preconverted.in \
gnun-report.in gnun-validate-html.in \
mailfail.in update-localized-urls.in \
@@ -188,7 +195,10 @@
tests/validate/1 tests/validate/1.html \
tests/validate/2 tests/validate/html5.html \
tests/validate/3 tests/validate/3.0.html tests/validate/3.1.html \
- tests/validate/4 tests/validate/4.0.html tests/validate/4.1.html
+ tests/validate/4 tests/validate/4.0.html tests/validate/4.1.html \
+ tests/validate/5 tests/validate/5.0.html tests/validate/5.1.html \
+ tests/validate/match3 tests/validate/match3.0.html \
+ tests/validate/match3.1.html
CLEANFILES = add-fuzzy-diff copy-msgid diff-po.awk gnun-add-fuzzy-diff \
gnun-diff-po gnun-init-po gnun-merge-preconverted gnun-report \
Index: NEWS
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/NEWS,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -b -r1.112 -r1.113
--- NEWS 5 Nov 2014 14:52:22 -0000 1.112
+++ NEWS 13 Mar 2015 18:02:47 -0000 1.113
@@ -2,12 +2,23 @@
* Changes in GNUnited Nations 0.10 (????-??-??)
+** `gnun-validate-html' supports groups of regular expressions
+ as Apache variables when expanding SSI (when gawk is used).
+
+** GNUmakefile.team is made more suitable for parallel builds;
+
** In GNUmakefile.team, the `update' was split into
`update-www' and `update-team'; the repositories are updated
unconditionally (previously, they were only updated when VCS=yes).
** Bugs fixed in 0.10.
+*** In SSI expansion, `gnun-validate-html' wrongly assumed that double
+ quotes were removed when evaluating #if directives.
+
+*** In SSI expansion, `gnun-validate-html' wrongly unquoted regular
+ expressions in directives like <!--#if expr="a = /'a'/" -->
+
*** `gnun-add-fuzzy-diff' didn't work correctly when no input file
was given.
Index: expand-ssi.awk.in
===================================================================
RCS file: expand-ssi.awk.in
diff -N expand-ssi.awk.in
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ expand-ssi.awk.in 13 Mar 2015 18:02:46 -0000 1.1
@@ -0,0 +1,547 @@
+# expand-ssi.awk: process Apache SSI directives.
+
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This file is part of GNUnited Nations.
+
+# GNUnited Nations is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# GNUnited Nations is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>.
+
+# The implementation is very limited,
+# e.g. `&&' and `||' in `if' expressions are not supported, as well as
+# many cases of quoting; CGI includes would be expanded in a wrong way.
+
+# Fallback for awks who don't support RT.
+BEGIN { RT = "\n" }
+
+# Read whole file to `text'.
+{ text = text $0 RT }
+
+# Look for the variable first in the list of the named ones,
+# then in the numbered parts of the latest regex.
+function get_apache_var(var)
+{
+ if(var in apache_variables)
+ return apache_variables[var]
+ if(var in matched_array && var ~ /^[0-9]$/)
+ return matched_array[var]
+ return val = ""
+}
+
+# Substitute the variables in `str' with their values;
+# return the result.
+function expand_var_value(str,
+ vars, n, i, begin, end, rest, var, val)
+{
+ n = split(str, vars, /\$/)
+ if(!n)
+ return ""
+ str = vars[1];
+ for(i = 2; i <= n; i++)
+ {
+ if(substr(vars[i], 1, 1) == "{")
+ {
+ begin = 2; end = index(vars[i], "}"); rest = end + 1
+ }
+ else
+ {
+ begin = 1; end = match(vars[i] " ", /[^0-9a-zA-Z_]/); rest = end
+ }
+ if(end <= begin)
+ {
+ str = str "$" vars[i]; continue
+ }
+ var = substr(vars[i],begin,end - begin)
+ val = get_apache_var(var)
+ str = str val (rest <= length(vars[i])? substr(vars[i], rest): "")
+ }
+ return str
+}
+
+# Remove the first and the last character.
+function unquote(str)
+{
+ return substr(str, 2, length(str) - 2)
+}
+
+# Process `<!--#set ... -->' directive.
+function assign_var(var, val,
+ i, q, n, expanded_val)
+{
+ # Extract variable name and value.
+ var = unquote(var)
+ q = substr(val, 1, 1)
+ val = unquote(val)
+ if(q == "\"")
+ gsub(/\\"/, q, val)
+ if(q == "'")
+ gsub(/\\'/, q, val)
+ # Handle escaped `$'s when expanding val.
+ # Note: the unescaping is done in a different way when
+ # expanding `if' expressions in eval_expression().
+ n = split(val, arr, /\\\$/)
+ if(!n)
+ expanded_val = ""
+ else
+ {
+ expanded_val = expand_var_value(arr[1])
+ for(i = 2; i <= n; i++)
+ expanded_val = expanded_val "$" expand_var_value(arr[i])
+ }
+ apache_variables[var] = expanded_val
+}
+
+# URL encoding.
+function encode_url(str)
+{
+ gsub(/%/, "%25", str); # This substitution must be applied first.
+ gsub(/\t/, "%09", str); gsub(/\n/, "%0a", str); gsub(/\r/, "%0d", str)
+ gsub(/ /, "%20", str); gsub(/"/, "%22", str); gsub(/#/, "%23", str)
+ gsub(/;/, "%3b", str); gsub(/</, "%3c", str); gsub(/>/, "%3e", str)
+ gsub(/\?/, "%3f", str); gsub(/\[/, "%5b", str); gsub(/\]/, "%5d", str)
+ gsub(/\^/, "%5e", str); gsub(/`/, "%60", str);
+ gsub(/\{/, "%7b", str); gsub(/[|]/, "%7c", str); gsub(/}/, "%7d", str)
+ return str
+}
+
+# Entity encoding.
+function encode_entity(str)
+{
+ gsub(/&/, "\\&", str); gsub(/"/, "\\"", str)
+ gsub(/</, "\\<", str); gsub(/>/, "\\>", str)
+ return str;
+}
+
+# Process `<!--#echo ... -->' directive.
+function echo_var(str, arr,
+ var, val, enc)
+{
+ if(length(arr[2]) > 2)
+ {
+ var = unquote(arr[2])
+ val = get_apache_var(var)
+ if(1 in arr)
+ {
+ enc = arr[1]
+ if(enc == "entity")
+ val = encode_entity(val)
+ else if(enc == "url")
+ val = encode_url(val)
+ else if(enc != "none")
+ {
+ print my_name "unknown encoding `" enc \
+ "' in echo directive" > "/dev/stderr"
+ exit 1
+ }
+ }
+ else
+ val = encode_entity(val)
+ printf("%s", val)
+ }
+ else
+ {
+ val = substr(str, 1, match(str, /[ \t\r\n]-->/))
+ print my_name "couldn't process echo directive `" val "'" > "/dev/stderr"
+ exit 1
+ }
+}
+
+# Remove leading and trailing spaces, unquote, expand variables.
+function unquoted_var(str,
+ val)
+{
+ val = str
+ sub(/^[ \t]*/, "", val)
+ sub(/[ \t]*$/, "", val)
+ if(val ~ /^'.*'$/)
+ val = unquote(val)
+ return expand_var_value(val)
+}
+
+# Substituted in MATCH3 when match doesn't support third argument.
+function match_fallback(arg1, arg2, arg3)
+{
+ return match(arg1, arg2)
+}
+
+# Evaluate condition from `<!--#if ... -->' directive.
+# Supported forms are "string", "!string", "string1 = string2",
+# "string1 == string2", "string1 != string2".
+# Other forms ("-A string", "string1 > string2", "expr1 && expr2" etc.)
+# are not supported.
+# Advanced quoting patterns like "' '${test}' ' = ' '"
+# are also not supported (use "' ${test} ' = ' '").
+function eval_expression(str,
+ arr, lval, rval, negate, pattern_match, res, idx)
+{
+ # Escaped `$'s are treated the same way as unescaped in `if' expressions.
+ gsub(/\\\$/, "$", str)
+ idx = index(str, "=")
+ if(!idx)
+ {
+ # No `=': we've got either "!string" or "string" kind of expression.
+ if(str ~ /^[ \t]*!/)
+ return !length(unquoted_var(substr(str, index(str, "!") + 1)))
+ return length(unquoted_var(str))
+ }
+ if(idx > 1)
+ arr[1] = substr(str, 1, idx - 1)
+ else
+ arr[1] = ""
+ arr[2] = substr(str, idx + 1)
+ if(str ~ /!==/)
+ {
+ print my_name "bad expression `" str "'" > "/dev/stderr"
+ exit 1
+ }
+ # "string1 == string2" or "string1 != string2" or "string1 = string2" case.
+ pattern_match = 0
+ negate = 0
+ if(arr[2] ~ /^=/)
+ {
+ arr[2] = substr(arr[2], 2)
+ negate = -1
+ }
+ sub(/^[ \t]*/, "", arr[2])
+ sub(/[ \t]*$/, "", arr[2])
+ if(arr[2] ~ /^\/.*\/$/)
+ {
+ pattern_match = 1
+ arr[2] = unquote(arr[2])
+ }
+ if(!negate && (arr[1] ~ /!$/))
+ {
+ negate = 1
+ sub(/.$/, "", arr[1])
+ }
+ lval = unquoted_var(arr[1])
+ rval = arr[2]
+ if(rval ~ /^'.*'$/ && !pattern_match)
+ rval = unquote(rval)
+ rval = expand_var_value(rval)
+ if(pattern_match)
+ {
+ # Note: Apache manual says you can only capture parts of regexp
+ # with positive matching, but in fact the same is true for negative one.
+ res = @MATCH3@(lval, rval, matched_array)
+ }
+ else
+ res = (lval == rval)
+ if(negate > 0)
+ return !res
+ return res
+}
+
+# Find the end of the directive and check that
+# no comment begins before the directive ends.
+function directive_idx(str,
+ i, idx1)
+{
+ i = match(str, /[ \t\r\n]-->/)
+ if(i == 0)
+ {
+ print my_name "broken chunk `<!--#" str "': directive has no end" \
+ > "/dev/stderr"
+ exit 1
+ }
+ idx1 = index(str, "<!--")
+ if(idx1 && i >= idx1)
+ {
+ print my_name "broken chunk `<!--#" str "' (first ` -->' at " i \
+ " comes after next `<!--' at " idx1 ")" > "/dev/stderr"
+ exit 1
+ }
+ return i + 4
+}
+
+function process_endif()
+{
+ if(--depth < 0)
+ {
+ print my_name "unexpected endif directive in `" \
+ chunks[ch_i] "'" > "/dev/stderr"
+ exit 1
+ }
+ printf("%s", substr(chunks[ch_i], idx) "")
+}
+
+# Main program.
+END {
+ # Don't bother about empty files.
+ if(!length(text))
+ exit 0
+# Assign initial values.
+ # Assign prefix for error messages.
+ my_name = "expand-ssi.awk: "
+ # Default root directory is "../.."
+ if(root == "")
+ root = "../.."
+
+ # The passed_vars variable are expected to come from the command line.
+ ch_n = split(passed_vars, split_vars, /;/)
+ for(ch_i = 1; ch_i <= ch_n; ch_i++)
+ {
+ m = index(split_vars[ch_i], "=")
+ value = ""
+ if(m)
+ {
+ var_name = substr(split_vars[ch_i], 1, m - 1)
+ if(m + 1 <= length(split_vars[ch_i]))
+ value = substr(split_vars[ch_i], m + 1)
+ }
+ else
+ var_name = split_vars[ch_i]
+ if(length(var_name))
+ apache_variables[var_name] = value
+ }
+
+ # Relative directory name for the processed file
+ # (FILENAME must be relative).
+ relative_dir_name = FILENAME
+ # Assume that stdin comes from the current directory,
+ # although it is not very probable.
+ if (relative_dir_name == "-")
+ relative_dir_name = "./foo.html"
+ if (relative_dir_name ~ /\//)
+ sub (/[^\/]*$/, "", relative_dir_name)
+ else
+ relative_dir_name = root
+ sub (/\/*$/, "/", relative_dir_name)
+
+# Split the text by Apache directives.
+ ch_n = split(text, chunks, "<!--#");
+ depth = 0 # The current depth of `if' nesting.
+# Process directives.
+ if(ch_n > 0)
+ printf("%s", chunks[1])
+ for(ch_i = 2; ch_i <= ch_n; ch_i++)
+ {
+ idx = directive_idx(chunks[ch_i])
+# `Set' directive: assign a variable.
+ directive = substr(chunks[ch_i], 1, idx - 1)
+ if(directive \
+~ /^set[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+-->/)
+ {
+ pattern[1] = directive
+ sub(/^set[ \t\r\n]+var=/, "", pattern[1])
+ sub(/[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+-->.*/,
+ "", pattern[1])
+ pattern[2] = directive
+ sub(/^set[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+value=/, \
+ "", pattern[2])
+ sub(/[ \t\r\n]+-->.*/, "", pattern[2])
+ assign_var(pattern[1], pattern[2])
+ if(idx <= length(chunks[ch_i]))
+ printf("%s", substr(chunks[ch_i], idx) "")
+ continue
+ }
+# `Set' directive (different order of attributes).
+ if(directive \
+~ /^set[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+-->/)
+ {
+ pattern[1] = directive
+ sub(/^set[ \t\r\n]+value=/, "", pattern[1])
+ sub(/[ \t\r\n]+var=('.*'|".*")[ \t\r\n]+-->.*/,
+ "", pattern[1])
+ pattern[2] = directive
+ sub(/^set[ \t\r\n]+value=('.+'|".+")[ \t\r\n]+var=/, \
+ "", pattern[2])
+ sub(/[ \t\r\n]+-->.*/, "", pattern[2])
+ assign_var(pattern[2], pattern[1])
+ if(idx <= length(chunks[ch_i]))
+ printf("%s", substr(chunks[ch_i], idx) "")
+ continue
+ }
+# `Echo' directive: output a variable.
+ if(chunks[ch_i] \
+~ /^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[
\t\r\n]+)?var=('[^']+'|"[^\"]+")[ \t\r\n]+-->/)
+ {
+ if(chunks[ch_i] \
+~ /^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[ \t\r\n]+)/)
+ {
+ pattern[1] = chunks[ch_i]
+ sub(/^echo[ \t\r\n]+encoding=/, "", pattern[1])
+ idx1 = index(substr(pattern[1], 2), substr(pattern[1], 1, 1))
+ pattern[1] = substr(pattern[1], 2, idx1 - 1)
+ }
+ else
+ delete pattern[1]
+ pattern[2] = chunks[ch_i]
+ sub(\
+/^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[ \t\r\n]+)?var=/, \
+"", pattern[2])
+ idx1 = index(substr(pattern[2], 2), substr(pattern[2], 1, 1))
+ pattern[2] = substr(pattern[2], 1, idx1 + 1)
+ echo_var(chunks[ch_i], pattern)
+ if(idx <= length(chunks[ch_i]))
+ printf("%s", substr(chunks[ch_i], idx) "")
+ continue
+ }
+# `Include' directive: expand the file and rearrange chunks.
+ if(chunks[ch_i] ~ \
+/^include[ \t\r\n]+(file|virtual)=("[^"]*"|'[^']*')[ \t\r\n]+-->/)
+ {
+ pattern[2] = chunks[ch_i]
+ sub(/^include[ \t\r\n]+(file|virtual)=/, "", pattern[2])
+ pattern[1] = substr(pattern[2], 1, 1)
+ idx1 = index(substr(pattern[2], 2), pattern[1])
+ if(idx1 > 1)
+ name = substr(pattern[2], 2, idx1 - 1)
+ else
+ name = ""
+ # Construct the real path to the file.
+ # Note: relative paths actually won't work in nested includes;
+ # we could track the changes of the path through assigning a path
+ # to every chunk, but it doesn't seem to have much sense, since
+ # it is documented that we should only use absolute paths.
+ if(name ~ /^\//)
+ name = root name
+ else
+ name = relative_dir_name name
+ # Load the file.
+ text = ""
+ while(1)
+ {
+ m = getline < name
+ if(m < 0)
+ {
+ print my_name "can't read file `" name "': " ERRNO \
+ > "/dev/stderr"
+ exit 1
+ }
+ if(!m)
+ break
+ text = text $0 RT
+ }
+ close(name)
+ if(!length(text))
+ {
+ printf("%s", substr(chunks[ch_i], idx) "")
+ continue
+ }
+ m = split(text, next_chunks, "<!--#")
+ # Append the tail of current chunk to the last chunk
+ # of the included file.
+ next_chunks[m] = next_chunks[m] substr(chunks[ch_i], idx)
+ # Move the remaining chunks and put the included file
+ # in freed space.
+ if(m > 1)
+ {
+ for(j = ch_n; j > ch_i; j--)
+ chunks[j + m - 1] = chunks[j]
+ for(j = 2; j <= m ; j++)
+ chunks[j + ch_i - 1] = next_chunks[j]
+ ch_n += m - 1
+ }
+ printf("%s", next_chunks[1] "")
+ continue
+ } # if(match(chunks[ch_i], ...
+# `If' directive: skip all branches with false conditions;
+# output the branch with true condition.
+ if(chunks[ch_i] ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
+ {
+ depth++
+ finish = 0
+ while(ch_i <= ch_n && !finish)
+ {
+ exp_val = 1
+ # `Else' branches are output unconditionally
+ # (no matching `if'/`elif' found).
+ if(chunks[ch_i] !~ /^else[ \t\r\n]+-->/)
+ {
+ exp_l = index(chunks[ch_i], "expr=") + length("expr=")
+ qu = substr(chunks[ch_i], exp_l, 1)
+ expr = substr(chunks[ch_i], exp_l + 1)
+ expression = substr(expr, 1, match(expr, "[^\\\\]" qu))
+ exp_val = eval_expression(expression)
+ }
+ if(exp_val)
+ {
+ if(idx <= length(chunks[ch_i]))
+ printf("%s", substr(chunks[ch_i], idx) "")
+ break
+ }
+ # Skip to next `elif', `else' or `endif'
+ d = 0;
+ while (++ch_i <= ch_n)
+ {
+ idx = directive_idx(chunks[ch_i])
+ # Next if: increase depth.
+ if(chunks[ch_i] \
+ ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
+ {
+ d++; continue
+ }
+ # `Endif': break if we are at the initial depth.
+ if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
+ {
+ if(d-- > 0)
+ continue
+ finish = !0; process_endif(); break
+ }
+ # `Else' or `elif': break if we are at the initial depth.
+ if(d == 0 && (chunks[ch_i] ~ /^else[ \t\r\n]+-->/ \
+ || chunks[ch_i] \
+ ~ /^elif[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/))
+ break
+ } # while (++ch_i <= ch_n)
+ } # while(ch_i <= ch_n && !finish)
+ continue
+ } # if(chunks[ch_i] ~ /^if[ \t\r\n]+ ...
+# `Elif' or `else' directive: skip up to endif (since the branch with
+# matching expression was output when processing the `if' directive).
+ if((chunks[ch_i] ~ /^else[ \t\r\n]+-->/) \
+ || (chunks[ch_i] ~ /^elif[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/))
+ {
+ d = 0; chunk_i = ch_i
+ while (++ch_i <= ch_n)
+ {
+ idx = directive_idx(chunks[ch_i])
+ if(chunks[ch_i] ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
+ d++
+ if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
+ if(d-- == 0)
+ {
+ process_endif(); break
+ }
+ }
+ if(chunks[ch_i] !~ /^endif[ \t\r\n]+-->/)
+ {
+ print my_name "couldn't find matching endif for `<!--#" \
+ chunks[chunk_i] "'" > "/dev/stderr"
+ exit 1
+ }
+ continue
+ } # if((chunks[ch_i] ~ /^else[ \t\r\n]+-->/...
+# `Endif' directive: decrease depth and output the rest of the chunk.
+ if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
+ {
+ process_endif(); continue
+ }
+# A directive that must be parsed, but didn't match against its pattern.
+ if(chunks[ch_i] ~ /^(if|elif|else|endif|include|set|echo)\>/)
+ {
+ print my_name "couldn't parse directive `<!--#" \
+ substr(chunks[ch_i], 1, idx - 1) "'" > "/dev/stderr"
+ exit 1
+ }
+ # Unknown directive: hopefully it won't influence the validity.
+ printf("<!--#%s", chunks[ch_i] "")
+ } # for(ch_i = 2; ch_i <= ch_n; ch_i++)
+ if(depth > 0)
+ {
+ print my_name "some if directives are matched with no endif." \
+ > "/dev/stderr"
+ exit 1
+ }
+}
Index: tests/validate/5
===================================================================
RCS file: tests/validate/5
diff -N tests/validate/5
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/5 13 Mar 2015 18:02:48 -0000 1.1
@@ -0,0 +1,24 @@
+#! /bin/sh
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This file is part of GNUnited Nations.
+
+# GNUnited Nations is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# GNUnited Nations is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>.
+
+# Test unquoting in expressions.
+
+"${bindir}/gnun-validate-html" --expand-to=5.1.html \
+ "${srcdir}/validate/5.0.html" || exit 1
+diff "${srcdir}/validate/5.1.html" 5.1.html || exit 1
+rm 5.1.html
Index: tests/validate/5.0.html
===================================================================
RCS file: tests/validate/5.0.html
diff -N tests/validate/5.0.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/5.0.html 13 Mar 2015 18:02:48 -0000 1.1
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<!-- Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is a part of GNUN testsuite.
+
+GNUnited Nations is free software: you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+GNUnited Nations is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>. -->
+<title>title</title>
+</head>
+<body>
+<h2>Title</h2><!--#if expr="a = /'a'/" -->
+wrong "a = /'a'/" expression evaluation</p><!--#endif
+ --><!--#if expr="'a' != /^a$/" -->
+wrong "a = /'a'/" expression evaluation</p><!--#endif
+ --><!--#if expr="a != 'a'" -->
+wrong "a != 'a'" expression evaluation</p><!--#endif
+ --><!--#if expr="'a' != a" -->
+wrong "'a' != a" expression evaluation</p><!--#endif
+ --><!--#if expr='a == "a"' -->
+wrong 'a == "a"' expression evaluation</p><!--#endif
+ --><!--#if expr='"a" == a' -->
+wrong '"a" == a' expression evaluation</p><!--#endif
+ --></body>
+</html>
Index: tests/validate/5.1.html
===================================================================
RCS file: tests/validate/5.1.html
diff -N tests/validate/5.1.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/5.1.html 13 Mar 2015 18:02:48 -0000 1.1
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<!-- Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is a part of GNUN testsuite.
+
+GNUnited Nations is free software: you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+GNUnited Nations is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>. -->
+<title>title</title>
+</head>
+<body>
+<h2>Title</h2></body>
+</html>
Index: tests/validate/match3
===================================================================
RCS file: tests/validate/match3
diff -N tests/validate/match3
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/match3 13 Mar 2015 18:02:48 -0000 1.1
@@ -0,0 +1,24 @@
+#! /bin/sh
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This file is part of GNUnited Nations.
+
+# GNUnited Nations is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# GNUnited Nations is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>.
+
+# Test groups in regexes (only works with gawk).
+
+"${bindir}/gnun-validate-html" --expand-to=match3.1.html \
+ "${srcdir}/validate/match3.0.html" || exit 1
+diff "${srcdir}/validate/match3.1.html" match3.1.html || exit 1
+rm match3.1.html
Index: tests/validate/match3.1.html
===================================================================
RCS file: tests/validate/match3.1.html
diff -N tests/validate/match3.1.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/match3.1.html 13 Mar 2015 18:02:49 -0000 1.1
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<!-- Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is a part of GNUN testsuite.
+
+GNUnited Nations is free software: you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+GNUnited Nations is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>. -->
+<title>title</title>
+</head>
+<body>
+<h2>Title</h2></body>
+</html>
Index: tests/validate/match3.0.html
===================================================================
RCS file: tests/validate/match3.0.html
diff -N tests/validate/match3.0.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/validate/match3.0.html 13 Mar 2015 18:02:49 -0000 1.1
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<!-- Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is a part of GNUN testsuite.
+
+GNUnited Nations is free software: you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+GNUnited Nations is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>. -->
+<title>title</title>
+</head>
+<body>
+<h2>Title</h2><!--#if expr="ab != /(a(b))/" -->
+wrong 'ab != /(a(b))/' expression evaluation</p>
+<!--#else
+ --><!--#if expr="$1 != ab" -->
+'ab != /(a(b))/'; $1 expression evaluation:
+$1='<!--#echo encoding="none" var="1" -->'
+</p><!--#endif
+ --><!--#if expr="$2 != b" -->
+'ab != /(a(b))/'; $2 expression evaluation:
+$2='<!--#echo encoding="none" var="2" -->'
+</p><!--#endif
+ --><!--#endif
+ --><!--#if expr="c1234567890ab = /(1)(2)(3)(4)(5)(6)(7)(8)((9)(0))/"
+ --><!--#if expr="$10" -->
+wrong evaluation of "c1234567890ab = /(1)(2)(3)(4)(5)(6)(7)(8)((9)(0))/";
+$10=<!--#echo encoding="none" var="10" -->
+is assigned, unlike in Apache</p><!--#endif
+ --><!--#if expr="$0 != 1234567890" -->
+wrong evaluation of "c1234567890ab = /(1)(2)(3)(4)(5)(6)(7)(8)((9)(0))/";
+$0=<!--#echo encoding="none" var="0" --></p>
+<!--#endif
+ --><!--#else -->
+wrong $1234567890 = /(1)(2)(3)(4)(5)(6)(7)(8)((9)(0))/ evaluation</p>
+<!--#endif
+ --><!--#if expr="abd != /(a(b))c/"
+ --><!--#if expr="$1" -->
+wrong evaluation of abd != /(a(b))c/: $1=<!--#echo encoding="none" var="1"
+ --></p><!--#endif
+ --><!--#if expr="$2" -->
+wrong evaluation of abd != /(a(b))c/: $2=<!--#echo encoding="none" var="2"
+ --></p><!--#endif --><!--#endif --></body>
+</html>
Index: expand-ssi.awk
===================================================================
RCS file: expand-ssi.awk
diff -N expand-ssi.awk
--- expand-ssi.awk 15 Mar 2014 07:58:23 -0000 1.6
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,529 +0,0 @@
-# expand-ssi.awk: process Apache SSI directives.
-
-# Copyright (C) 2014 Free Software Foundation, Inc.
-
-# This file is part of GNUnited Nations.
-
-# GNUnited Nations is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-
-# GNUnited Nations is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with GNUnited Nations. If not, see <http://www.gnu.org/licenses/>.
-
-# The implementation is very limited,
-# e.g. `&&' and `||' in `if' expressions are not supported, as well as
-# many cases of quoting; CGI includes would be expanded in a wrong way.
-
-# Fallback for awks who don't support RT.
-BEGIN { RT = "\n" }
-
-# Read whole file to `text'.
-{ text = text $0 RT }
-
-# Substitute the variables in `str' with their values;
-# return the result.
-function expand_var_value(str,
- vars, n, i, begin, end, rest, var, val)
-{
- n = split(str, vars, /\$/)
- if(!n)
- return ""
- str = vars[1];
- for(i = 2; i <= n; i++)
- {
- if(substr(vars[i], 1, 1) == "{")
- {
- begin = 2; end = index(vars[i], "}"); rest = end + 1
- }
- else
- {
- begin = 1; end = match(vars[i] " ", /[^0-9a-zA-Z_]/); rest = end
- }
- if(end <= begin)
- {
- str = str "$" vars[i]; continue
- }
- var = substr(vars[i],begin,end - begin)
- if(var in apache_variables)
- val = apache_variables[var]
- else
- val = ""
- str = str val (rest <= length(vars[i])? substr(vars[i], rest): "")
- }
- return str
-}
-
-# Remove the first and the last character.
-function unquote(str)
-{
- return substr(str, 2, length(str) - 2)
-}
-
-# Process `<!--#set ... -->' directive.
-function assign_var(var, val,
- i, q, n, expanded_val)
-{
- # Extract variable name and value.
- var = unquote(var)
- q = substr(val, 1, 1)
- val = unquote(val)
- if(q == "\"")
- gsub(/\\"/, q, val)
- if(q == "'")
- gsub(/\\'/, q, val)
- # Handle escaped `$'s when expanding val.
- # Note: the unescaping is done in a different way when
- # expanding `if' expressions in eval_expression().
- n = split(val, arr, /\\\$/)
- if(!n)
- expanded_val = ""
- else
- {
- expanded_val = expand_var_value(arr[1])
- for(i = 2; i <= n; i++)
- expanded_val = expanded_val "$" expand_var_value(arr[i])
- }
- apache_variables[var] = expanded_val
-}
-
-# URL encoding.
-function encode_url(str)
-{
- gsub(/%/, "%25", str); # This substitution must be applied first.
- gsub(/\t/, "%09", str); gsub(/\n/, "%0a", str); gsub(/\r/, "%0d", str)
- gsub(/ /, "%20", str); gsub(/"/, "%22", str); gsub(/#/, "%23", str)
- gsub(/;/, "%3b", str); gsub(/</, "%3c", str); gsub(/>/, "%3e", str)
- gsub(/\?/, "%3f", str); gsub(/\[/, "%5b", str); gsub(/\]/, "%5d", str)
- gsub(/\^/, "%5e", str); gsub(/`/, "%60", str);
- gsub(/\{/, "%7b", str); gsub(/[|]/, "%7c", str); gsub(/}/, "%7d", str)
- return str
-}
-
-# Entity encoding.
-function encode_entity(str)
-{
- gsub(/&/, "\\&", str); gsub(/"/, "\\"", str)
- gsub(/</, "\\<", str); gsub(/>/, "\\>", str)
- return str;
-}
-
-# Process `<!--#echo ... -->' directive.
-function echo_var(str, arr,
- var, val, enc)
-{
- if(length(arr[2]) > 2)
- {
- var = unquote(arr[2])
- if(var in apache_variables)
- val = apache_variables[var]
- else
- val = ""
- if(1 in arr)
- {
- enc = arr[1]
- if(enc == "entity")
- val = encode_entity(val)
- else if(enc == "url")
- val = encode_url(val)
- else if(enc != "none")
- {
- print my_name "unknown encoding `" enc \
- "' in echo directive" > "/dev/stderr"
- exit 1
- }
- }
- else
- val = encode_entity(val)
- printf("%s", val)
- }
- else
- {
- val = substr(str, 1, match(str, /[ \t\r\n]-->/))
- print my_name "couldn't process echo directive `" val "'" > "/dev/stderr"
- exit 1
- }
-}
-
-# Remove leading and trailing spaces, unquote, expand variables.
-function unquoted_var(str,
- val)
-{
- val = str
- sub(/^[ \t]*/, "", val)
- sub(/[ \t]*$/, "", val)
- if(val ~ /^'.*'$/ || val ~ /^".*"$/)
- val = unquote(val)
- return expand_var_value(val)
-}
-
-# Evaluate condition from `<!--#if ... -->' directive
-# Supported forms are "string", "!string", "string1 = string2",
-# "string1 == string2", "string1 != string2".
-# Other forms ("-A string", "string1 > string2", "expr1 && expr2" etc.)
-# are not supported.
-# Advanced quoting patterns like "' '${test}' ' = ' '"
-# are also not supported (use "' ${test} ' = ' '").
-function eval_expression(str,
- arr, lval, rval, negate, pattern_match, res, idx)
-{
- # Escaped `$'s are treated the same way as unescaped in `if' expressions.
- gsub(/\\\$/, "$", str)
- idx = index(str, "=")
- if(!idx)
- {
- # No `=': we've got either "!string" or "string" kind of expression.
- if(str ~ /^[ \t]*!/)
- return !length(unquoted_var(substr(str, index(str, "!") + 1)))
- return length(unquoted_var(str))
- }
- if(idx > 1)
- arr[1] = substr(str, 1, idx - 1)
- else
- arr[1] = ""
- arr[2] = substr(str, idx + 1)
- if(str ~ /!==/)
- {
- print my_name "bad expression `" str "'" > "/dev/stderr"
- exit 1
- }
- # "string1 == string2" or "string1 != string2" or "string1 = string2" case.
- pattern_match = 0
- negate = 0
- if(arr[2] ~ /^=/)
- {
- arr[2] = substr(arr[2], 2)
- negate = -1
- }
- sub(/^[ \t]*/, "", arr[2])
- sub(/[ \t]*$/, "", arr[2])
- if(arr[2] ~ /^\/.*\/$/)
- {
- pattern_match = 1
- arr[2] = unquote(arr[2])
- }
- if(!negate && (arr[1] ~ /!$/))
- {
- negate = 1
- sub(/.$/, "", arr[1])
- }
- lval = unquoted_var(arr[1])
- rval = arr[2]
- if(rval ~ /^'.*'$/ || rval ~ /^".*"$/ && !pattern_match)
- rval = unquote(rval)
- rval = expand_var_value(rval)
- res = pattern_match? (lval ~ rval): (lval == rval)
- if(negate > 0)
- return !res
- return res
-}
-
-# Find the end of the directive and check that
-# no comment begins before the directive ends.
-function directive_idx(str,
- i, idx1)
-{
- i = match(str, /[ \t\r\n]-->/)
- if(i == 0)
- {
- print my_name "broken chunk `<!--#" str "': directive has no end" \
- > "/dev/stderr"
- exit 1
- }
- idx1 = index(str, "<!--")
- if(idx1 && i >= idx1)
- {
- print my_name "broken chunk `<!--#" str "' (first ` -->' at " i \
- " comes after next `<!--' at " idx1 ")" > "/dev/stderr"
- exit 1
- }
- return i + 4
-}
-
-function process_endif()
-{
- if(--depth < 0)
- {
- print my_name "unexpected endif directive in `" \
- chunks[ch_i] "'" > "/dev/stderr"
- exit 1
- }
- printf("%s", substr(chunks[ch_i], idx) "")
-}
-
-# Main program.
-END {
- # Don't bother about empty files.
- if(!length(text))
- exit 0
-# Assign initial values.
- # Assign prefix for error messages.
- my_name = "expand-ssi.awk: "
- # Default root directory is "../.."
- if(root == "")
- root = "../.."
-
- # The passed_vars variable are expected to come from the command line.
- ch_n = split(passed_vars, split_vars, /;/)
- for(ch_i = 1; ch_i <= ch_n; ch_i++)
- {
- m = index(split_vars[ch_i], "=")
- value = ""
- if(m)
- {
- var_name = substr(split_vars[ch_i], 1, m - 1)
- if(m + 1 <= length(split_vars[ch_i]))
- value = substr(split_vars[ch_i], m + 1)
- }
- else
- var_name = split_vars[ch_i]
- if(length(var_name))
- apache_variables[var_name] = value
- }
-
- # Relative directory name for the processed file
- # (FILENAME must be relative).
- relative_dir_name = FILENAME
- # Assume that stdin comes from the current directory,
- # although it is not very probable.
- if (relative_dir_name == "-")
- relative_dir_name = "./foo.html"
- if (relative_dir_name ~ /\//)
- sub (/[^\/]*$/, "", relative_dir_name)
- else
- relative_dir_name = root
- sub (/\/*$/, "/", relative_dir_name)
-
-# Split the text by Apache directives.
- ch_n = split(text, chunks, "<!--#");
- depth = 0 # The current depth of `if' nesting.
-# Process directives.
- if(ch_n > 0)
- printf("%s", chunks[1])
- for(ch_i = 2; ch_i <= ch_n; ch_i++)
- {
- idx = directive_idx(chunks[ch_i])
-# `Set' directive: assign a variable.
- directive = substr(chunks[ch_i], 1, idx - 1)
- if(directive \
-~ /^set[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+-->/)
- {
- pattern[1] = directive
- sub(/^set[ \t\r\n]+var=/, "", pattern[1])
- sub(/[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+-->.*/,
- "", pattern[1])
- pattern[2] = directive
- sub(/^set[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+value=/, \
- "", pattern[2])
- sub(/[ \t\r\n]+-->.*/, "", pattern[2])
- assign_var(pattern[1], pattern[2])
- if(idx <= length(chunks[ch_i]))
- printf("%s", substr(chunks[ch_i], idx) "")
- continue
- }
-# `Set' directive (different order of attributes).
- if(directive \
-~ /^set[ \t\r\n]+value=('.*'|".*")[ \t\r\n]+var=('.+'|".+")[ \t\r\n]+-->/)
- {
- pattern[1] = directive
- sub(/^set[ \t\r\n]+value=/, "", pattern[1])
- sub(/[ \t\r\n]+var=('.*'|".*")[ \t\r\n]+-->.*/,
- "", pattern[1])
- pattern[2] = directive
- sub(/^set[ \t\r\n]+value=('.+'|".+")[ \t\r\n]+var=/, \
- "", pattern[2])
- sub(/[ \t\r\n]+-->.*/, "", pattern[2])
- assign_var(pattern[2], pattern[1])
- if(idx <= length(chunks[ch_i]))
- printf("%s", substr(chunks[ch_i], idx) "")
- continue
- }
-# `Echo' directive: output a variable.
- if(chunks[ch_i] \
-~ /^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[
\t\r\n]+)?var=('[^']+'|"[^\"]+")[ \t\r\n]+-->/)
- {
- if(chunks[ch_i] \
-~ /^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[ \t\r\n]+)/)
- {
- pattern[1] = chunks[ch_i]
- sub(/^echo[ \t\r\n]+encoding=/, "", pattern[1])
- idx1 = index(substr(pattern[1], 2), substr(pattern[1], 1, 1))
- pattern[1] = substr(pattern[1], 2, idx1 - 1)
- }
- else
- delete pattern[1]
- pattern[2] = chunks[ch_i]
- sub(\
-/^echo[ \t\r\n]+(encoding=("[^\"]*"|'[^']*')[ \t\r\n]+)?var=/, \
-"", pattern[2])
- idx1 = index(substr(pattern[2], 2), substr(pattern[2], 1, 1))
- pattern[2] = substr(pattern[2], 1, idx1 + 1)
- echo_var(chunks[ch_i], pattern)
- if(idx <= length(chunks[ch_i]))
- printf("%s", substr(chunks[ch_i], idx) "")
- continue
- }
-# `Include' directive: expand the file and rearrange chunks.
- if(chunks[ch_i] ~ \
-/^include[ \t\r\n]+(file|virtual)=("[^"]*"|'[^']*')[ \t\r\n]+-->/)
- {
- pattern[2] = chunks[ch_i]
- sub(/^include[ \t\r\n]+(file|virtual)=/, "", pattern[2])
- pattern[1] = substr(pattern[2], 1, 1)
- idx1 = index(substr(pattern[2], 2), pattern[1])
- if(idx1 > 1)
- name = substr(pattern[2], 2, idx1 - 1)
- else
- name = ""
- # Construct the real path to the file.
- # Note: relative paths actually won't work in nested includes;
- # we could track the changes of the path through assigning a path
- # to every chunk, but it doesn't seem to have much sense, since
- # it is documented that we should only use absolute paths.
- if(name ~ /^\//)
- name = root name
- else
- name = relative_dir_name name
- # Load the file.
- text = ""
- while(1)
- {
- m = getline < name
- if(m < 0)
- {
- print my_name "can't read file `" name "': " ERRNO \
- > "/dev/stderr"
- exit 1
- }
- if(!m)
- break
- text = text $0 RT
- }
- close(name)
- if(!length(text))
- {
- printf("%s", substr(chunks[ch_i], idx) "")
- continue
- }
- m = split(text, next_chunks, "<!--#")
- # Append the tail of current chunk to the last chunk
- # of the included file.
- next_chunks[m] = next_chunks[m] substr(chunks[ch_i], idx)
- # Move the remaining chunks and put the included file
- # in freed space.
- if(m > 1)
- {
- for(j = ch_n; j > ch_i; j--)
- chunks[j + m - 1] = chunks[j]
- for(j = 2; j <= m ; j++)
- chunks[j + ch_i - 1] = next_chunks[j]
- ch_n += m - 1
- }
- printf("%s", next_chunks[1] "")
- continue
- } # if(match(chunks[ch_i], ...
-# `If' directive: skip all branches with false conditions;
-# output the branch with true condition.
- if(chunks[ch_i] ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
- {
- depth++
- finish = 0
- while(ch_i <= ch_n && !finish)
- {
- exp_val = 1
- # `Else' branches are output unconditionally
- # (no matching `if'/`elif' found).
- if(chunks[ch_i] !~ /^else[ \t\r\n]+-->/)
- {
- exp_l = index(chunks[ch_i], "expr=") + length("expr=")
- qu = substr(chunks[ch_i], exp_l, 1)
- expr = substr(chunks[ch_i], exp_l + 1)
- expression = substr(expr, 1, match(expr, "[^\\\\]" qu))
- exp_val = eval_expression(expression)
- }
- if(exp_val)
- {
- if(idx <= length(chunks[ch_i]))
- printf("%s", substr(chunks[ch_i], idx) "")
- break
- }
- # Skip to next `elif', `else' or `endif'
- d = 0;
- while (++ch_i <= ch_n)
- {
- idx = directive_idx(chunks[ch_i])
- # Next if: increase depth.
- if(chunks[ch_i] \
- ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
- {
- d++; continue
- }
- # `Endif': break if we are at the initial depth.
- if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
- {
- if(d-- > 0)
- continue
- finish = !0; process_endif(); break
- }
- # `Else' or `elif': break if we are at the initial depth.
- if(d == 0 && (chunks[ch_i] ~ /^else[ \t\r\n]+-->/ \
- || chunks[ch_i] \
- ~ /^elif[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/))
- break
- } # while (++ch_i <= ch_n)
- } # while(ch_i <= ch_n && !finish)
- continue
- } # if(chunks[ch_i] ~ /^if[ \t\r\n]+ ...
-# `Elif' or `else' directive: skip up to endif (since the branch with
-# matching expression was output when processing the `if' directive).
- if((chunks[ch_i] ~ /^else[ \t\r\n]+-->/) \
- || (chunks[ch_i] ~ /^elif[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/))
- {
- d = 0; chunk_i = ch_i
- while (++ch_i <= ch_n)
- {
- idx = directive_idx(chunks[ch_i])
- if(chunks[ch_i] ~ /^if[ \t\r\n]+expr=('.*'|".*")[ \t\r\n]+-->/)
- d++
- if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
- if(d-- == 0)
- {
- process_endif(); break
- }
- }
- if(chunks[ch_i] !~ /^endif[ \t\r\n]+-->/)
- {
- print my_name "couldn't find matching endif for `<!--#" \
- chunks[chunk_i] "'" > "/dev/stderr"
- exit 1
- }
- continue
- } # if((chunks[ch_i] ~ /^else[ \t\r\n]+-->/...
-# `Endif' directive: decrease depth and output the rest of the chunk.
- if(chunks[ch_i] ~ /^endif[ \t\r\n]+-->/)
- {
- process_endif(); continue
- }
-# A directive that must be parsed, but didn't match against its pattern.
- if(chunks[ch_i] ~ /^(if|elif|else|endif|include|set|echo)\>/)
- {
- print my_name "couldn't parse directive `<!--#" \
- substr(chunks[ch_i], 1, idx - 1) "'" > "/dev/stderr"
- exit 1
- }
- # Unknown directive: hopefully it won't influence the validity.
- printf("<!--#%s", chunks[ch_i] "")
- } # for(ch_i = 2; ch_i <= ch_n; ch_i++)
- if(depth > 0)
- {
- print my_name "some if directives are matched with no endif." \
- > "/dev/stderr"
- exit 1
- }
-}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- trans-coord/gnun/server/gnun configure.ac Makef...,
Pavel Kharitonov <=