[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
trans-coord/gnun/server/gnun AUTHORS ChangeLog ...
From: |
Pavel Kharitonov |
Subject: |
trans-coord/gnun/server/gnun AUTHORS ChangeLog ... |
Date: |
Thu, 31 May 2012 04:44:43 +0000 |
CVSROOT: /sources/trans-coord
Module name: trans-coord
Changes by: Pavel Kharitonov <ineiev> 12/05/31 04:44:42
Modified files:
gnun/server/gnun: AUTHORS ChangeLog Makefile.am NEWS
gnun-validate-html gnun-validate-html.in
Added files:
gnun/server/gnun: expand-ssi.awk
Log message:
Interpret SSI directives more realistically when validating pages.
* expand-ssi.awk: New script.
* Makefile.am (dist_pkglibexec_SCRIPTS): Add `expand-ssi.awk'.
* gnun-validate-html.in: Use expand-ssi.awk when validating pages.
(TMP3): Remove variable.
* AUTHORS:
* NEWS: Update.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/AUTHORS?cvsroot=trans-coord&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/ChangeLog?cvsroot=trans-coord&r1=1.269&r2=1.270
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/Makefile.am?cvsroot=trans-coord&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/NEWS?cvsroot=trans-coord&r1=1.53&r2=1.54
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/gnun-validate-html?cvsroot=trans-coord&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/gnun-validate-html.in?cvsroot=trans-coord&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/trans-coord/gnun/server/gnun/expand-ssi.awk?cvsroot=trans-coord&rev=1.1
Patches:
Index: AUTHORS
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/AUTHORS,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- AUTHORS 24 Apr 2012 06:01:42 -0000 1.9
+++ AUTHORS 31 May 2012 04:44:42 -0000 1.10
@@ -7,7 +7,7 @@
Add add-fuzzy-diff.in, copy-msgid.in, diff-page-head.html,
diff-page-tail.html, dtd/html5.dtd (based on W3C DTD),
- expand-m4-includes.in,
+ expand-m4-includes.in, expand-ssi.awk,
languages.txt (compiled from www.gnu.org pages),
gnun-add-fuzzy-diff, priorities.mk,
translinks-head.html, translinks-tail.html,
Index: ChangeLog
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/ChangeLog,v
retrieving revision 1.269
retrieving revision 1.270
diff -u -b -r1.269 -r1.270
--- ChangeLog 29 May 2012 10:11:46 -0000 1.269
+++ ChangeLog 31 May 2012 04:44:42 -0000 1.270
@@ -1,3 +1,14 @@
+2012-05-31 Pavel Kharitonov <address@hidden>
+
+ Interpret SSI directives more realistically when validating pages.
+
+ * expand-ssi.awk: New script.
+ * Makefile.am (dist_pkglibexec_SCRIPTS): Add `expand-ssi.awk'.
+ * gnun-validate-html.in: Use expand-ssi.awk when validating pages.
+ (TMP3): Remove variable.
+ * AUTHORS:
+ * NEWS: Update.
+
2012-05-29 Pavel Kharitonov <address@hidden>
* GNUmakefile (update-po): Substitute default values in a more
Index: Makefile.am
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/Makefile.am,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- Makefile.am 24 Apr 2012 06:01:38 -0000 1.28
+++ Makefile.am 31 May 2012 04:44:42 -0000 1.29
@@ -42,7 +42,7 @@
pkglibexec_SCRIPTS += make-prototype
endif
-dist_pkglibexec_SCRIPTS = mailfail
+dist_pkglibexec_SCRIPTS = expand-ssi.awk mailfail
edit = $(SED) \
-e 's|@address@hidden|$(PACKAGE)|g' \
Index: NEWS
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/NEWS,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -b -r1.53 -r1.54
--- NEWS 27 Apr 2012 05:16:22 -0000 1.53
+++ NEWS 31 May 2012 04:44:42 -0000 1.54
@@ -2,6 +2,8 @@
* Changes in GNUnited Nations 0.6 (????-??-??)
+** SSI directives are interpreted more realistically when validating pages.
+
** Variables defined in `priorities.mk' are used to sort the reported
translations by priority.
Index: gnun-validate-html
===================================================================
RCS file: /sources/trans-coord/trans-coord/gnun/server/gnun/gnun-validate-html,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- gnun-validate-html 26 Apr 2012 08:51:04 -0000 1.14
+++ gnun-validate-html 31 May 2012 04:44:42 -0000 1.15
@@ -99,76 +99,26 @@
# Create two tempfiles and mark them for deletion on exit.
TMP1=`mktemp -t gnun.1.XXXXXX`
TMP2=`mktemp -t gnun.2.XXXXXX`
-TMP3=`mktemp -t gnun.3.XXXXXX`
-trap "rm -f $TMP1 $TMP2 $TMP3" EXIT
+trap "rm -f $TMP1 $TMP2" EXIT
# Use $TMP1 if no $OUTPUT is specified.
OUTPUT="${OUTPUT:-${TMP1}}"
-# Expand input file's #include directives and save the result in
-# $TMP1.
-cat > $TMP2 <<"EOF"
-# Limitations: CGI includes would be expanded in a wrong way
-BEGIN {
- exit_val = 0
- relative_dir_name = ARGV[1];
- if (relative_dir_name ~ /\//)
- sub (/[^\/]*$/, "", relative_dir_name);
- else
- relative_dir_name="./"
- sub (/\/*$/, "/", relative_dir_name);
-}
-
-/<!--#include +(virtual)|(file)=["`']/ {
- n = split ($0, names, "<!--#include ");
- printf ("%s", names[1]);
- for (i = 2; i <= n; i++)
- {
- # Extract the next included file name
- if (names[i] !~ /^ *(virtual)|(file)=["'`]/)
- {
- # Pass it unchanged: this is not an Apache include directive
- printf ("<!--#include %s", names[i]);
- continue;
- }
- m = index (names[i], "-->");
- if (m == 0) # This shouldn't happen: the "-->" must be on the same line
- m = length (names[i]) + 1;
- name = substr (names[i], 1, m-1);
- # Absolute paths are not allowed with "file=" type of includes,
- # but we process them in the same way for simplicity
- sub (/^ *((virtual)|(file))=/, "", name);
- quote_symbol = substr (name, 1, 1);
- name = substr (name, 2);
- sub (quote_symbol "[^" quote_symbol "]*$", "", name);
-
- # Construct the real path to the file
- if (name ~ /^\//)
- name = root name;
- else
- name = relative_dir_name name;
-
- # Invoke the script recursively
- val = system ("gawk -v script_name='" script_name "' -v root='" \
- root "' -f '" script_name "' " name)
- if (!exit_val)
- exit_val = val
-
- # Output the part remaining after the include directive
- print (substr (names[i], m + 3));
- }
- next;
-}
-
-{ print; }
-
-END { exit exit_val }
-EOF
-
-if ! gawk -v script_name=$TMP2 -v root="${ROOT}" -f $TMP2 $1 > "${OUTPUT}" \
- 2> $TMP3; then
+root_dir=`cd ${ROOT}; pwd`
+document_name=${1##*/}
+case $1 in
+ */* ) document_dir=`cd ${1%/*}; pwd` ;;
+ * ) document_dir=`pwd` ;;
+esac
+dir_from_root=${document_dir#${root_dir}}
+
+if ! LANG=C gawk -f ./expand-ssi.awk -v root="${ROOT}" \
+ -v passed_vars="DOCUMENT_NAME=${document_name};\
+DOCUMENT_URI=${dir_from_root}/${document_name};\
+REQUEST_URI=${dir_from_root}/${document_name}" $1 \
+ > "${OUTPUT}" 2> $TMP2; then
echo Failed to expand SSIs:
- cat $TMP3
+ cat $TMP2
exit 1
fi
Index: gnun-validate-html.in
===================================================================
RCS file:
/sources/trans-coord/trans-coord/gnun/server/gnun/gnun-validate-html.in,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- gnun-validate-html.in 26 Apr 2012 08:50:39 -0000 1.15
+++ gnun-validate-html.in 31 May 2012 04:44:42 -0000 1.16
@@ -99,77 +99,26 @@
# Create two tempfiles and mark them for deletion on exit.
TMP1=`mktemp -t gnun.1.XXXXXX`
TMP2=`mktemp -t gnun.2.XXXXXX`
-TMP3=`mktemp -t gnun.3.XXXXXX`
-trap "rm -f $TMP1 $TMP2 $TMP3" EXIT
+trap "rm -f $TMP1 $TMP2" EXIT
# Use $TMP1 if no $OUTPUT is specified.
OUTPUT="${OUTPUT:-${TMP1}}"
-# Expand input file's #include directives and save the result in
-# $TMP1.
-cat > $TMP2 <<"EOF"
-# Limitations: CGI includes would be expanded in a wrong way
-BEGIN {
- exit_val = 0
- relative_dir_name = ARGV[1];
- if (relative_dir_name ~ /\//)
- sub (/[^\/]*$/, "", relative_dir_name);
- else
- relative_dir_name="./"
- sub (/\/*$/, "/", relative_dir_name);
-}
-
-/<!--#include +(virtual)|(file)=["`']/ {
- n = split ($0, names, "<!--#include ");
- printf ("%s", names[1]);
- for (i = 2; i <= n; i++)
- {
- # Extract the next included file name
- if (names[i] !~ /^ *(virtual)|(file)=["'`]/)
- {
- # Pass it unchanged: this is not an Apache include directive
- printf ("<!--#include %s", names[i]);
- continue;
- }
- m = index (names[i], "-->");
- if (m == 0) # This shouldn't happen: the "-->" must be on the same line
- m = length (names[i]) + 1;
- name = substr (names[i], 1, m-1);
- # Absolute paths are not allowed with "file=" type of includes,
- # but we process them in the same way for simplicity
- sub (/^ *((virtual)|(file))=/, "", name);
- quote_symbol = substr (name, 1, 1);
- name = substr (name, 2);
- sub (quote_symbol "[^" quote_symbol "]*$", "", name);
-
- # Construct the real path to the file
- if (name ~ /^\//)
- name = root name;
- else
- name = relative_dir_name name;
-
- # Invoke the script recursively
- val = system ("@AWK@ -v script_name='" script_name "' -v root='" \
- root "' -f '" script_name "' " name);
-
- if (!exit_val)
- exit_val = val
-
- # Output the part remaining after the include directive
- print (substr (names[i], m + 3));
- }
- next;
-}
-
-{ print; }
-
-END { exit exit_val }
-EOF
-
-if ! @AWK@ -v script_name=$TMP2 -v root="${ROOT}" -f $TMP2 $1 > "${OUTPUT}" \
- 2> $TMP3; then
+root_dir=`cd ${ROOT}; pwd`
+document_name=${1##*/}
+case $1 in
+ */* ) document_dir=`cd ${1%/*}; pwd` ;;
+ * ) document_dir=`pwd` ;;
+esac
+dir_from_root=${document_dir#${root_dir}}
+
+if ! LANG=C @AWK@ -f @pkglibexecdir@/expand-ssi.awk -v root="${ROOT}" \
+ -v passed_vars="DOCUMENT_NAME=${document_name};\
+DOCUMENT_URI=${dir_from_root}/${document_name};\
+REQUEST_URI=${dir_from_root}/${document_name}" $1 \
+ > "${OUTPUT}" 2> $TMP2; then
echo Failed to expand SSIs:
- cat $TMP3
+ cat $TMP2
exit 1
fi
Index: expand-ssi.awk
===================================================================
RCS file: expand-ssi.awk
diff -N expand-ssi.awk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ expand-ssi.awk 31 May 2012 04:44:42 -0000 1.1
@@ -0,0 +1,484 @@
+# expand-ssi.awk: process Apache SSI directives.
+
+# Copyright (C) 2012 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.
+
+# 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(vars[i] ~ /^{/)
+ {
+ begin = 2; end = index(vars[i], "}"); rest = end + 1
+ }
+ else
+ {
+ begin = 1; end = match(vars[i], /\>/); 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)
+ {
+ sub(/[[:blank:]\r\n]*$/, "", arr[1])
+ enc = substr(arr[1], length("encoding='") + 1,
+ length(arr[1]) - length("encoding=''"));
+ 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, /[[:blank:]\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(/^[[:blank:]]*/, "", val)
+ sub(/[[:blank:]]*$/, "", 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)
+{
+ # Escaped `$'s are treated the same way as unescaped in `if' expressions.
+ gsub(/\\\$/, "$", str)
+ if(!match(str, /^([^=]*)=(.*)/, arr))
+ {
+ # No `=': we've got either "!string" or "string" kind of expression.
+ if(str ~ /^[[:blank:]]*!/)
+ return !length(unquoted_var(substr(str, index(str, "!") + 1)))
+ return length(unquoted_var(str))
+ }
+ 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(/^[[:blank:]]*/, "", arr[2])
+ sub(/[[:blank:]]*$/, "", 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, /[[:blank:]\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(match(directive, /^set[[:blank:]\r\n]+var=('.+'|".+")\
+[[:blank:]\r\n]+value=('.*'|".*")[[:blank:]\r\n]+-->/, pattern))
+ {
+ 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(match(directive, /^set[[:blank:]\r\n]+value=('.*'|".*")\
+[[:blank:]\r\n]+var=('.+'|".+")[[:blank:]\r\n]+-->/, pattern))
+ {
+ 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(match(chunks[ch_i], /^echo[[:blank:]\r\n]+\
+(encoding="[^\"]*"[[:blank:]\r\n]+|encoding='[^']*'\
+[[:blank:]\r\n]+)?var=('[^']+'|"[^\"]+")[[:blank:]\r\n]+-->/, pattern))
+ {
+ 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(match(chunks[ch_i], \
+/^include[[:blank:]\r\n]+(file|virtual)=("[^"]*"|'[^']*')[[:blank:]\r\n]+-->/,
\
+ pattern))
+ {
+ name = unquote(pattern[2])
+ # 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))
+ 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[[:blank:]\r\n]+\
+expr=('.*'|".*")[[:blank:]\r\n]+-->/)
+ {
+ depth++
+ finish = 0
+ while(ch_i <= ch_n && !finish)
+ {
+ exp_val = 1
+ # `Else' branches are output unconditionally.
+ if(chunks[ch_i] !~ /^else[[:blank:]\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[[:blank:]\r\n]+expr=('.*'|".*")[[:blank:]\r\n]+-->/)
+ {
+ d++; continue
+ }
+ # `Endif': break if we are at the initial depth.
+ if(chunks[ch_i] ~ /^endif[[:blank:]\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[[:blank:]\r\n]+-->/ \
+ || chunks[ch_i] ~ /^elif[[:blank:]\r\n]+\
+expr=('.*'|".*")[[:blank:]\r\n]+-->/)
+ break
+ } # while (++ch_i <= ch_n)
+ } # while(ch_i <= ch_n && !finish)
+ continue
+ } # if(chunks[ch_i] ~ /^if[[:blank:]\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[[:blank:]\r\n]+-->/) \
+ || (chunks[ch_i] ~ /^elif[[:blank:]\r\n]+\
+expr=('.*'|".*")[[:blank:]\r\n]+-->/))
+ {
+ d = 0; chunk_i = ch_i
+ while (++ch_i <= ch_n)
+ {
+ idx = directive_idx(chunks[ch_i])
+ if(chunks[ch_i] ~ /^if[[:blank:]\r\n]+\
+expr=('.*'|".*")[[:blank:]\r\n]+-->/)
+ d++
+ if(chunks[ch_i] ~ /^endif[[:blank:]\r\n]+-->/)
+ if(d-- == 0)
+ {
+ process_endif(); break
+ }
+ }
+ if(chunks[ch_i] !~ /^endif[[:blank:]\r\n]+-->/)
+ {
+ print my_name "couldn't find matching endif for `<!--#" \
+ chunks[chunk_i] "'" > "/dev/stderr"
+ exit 1
+ }
+ continue
+ } # if((chunks[ch_i] ~ /^else[[:blank:]\r\n]+-->/...
+# `Endif' directive: decrease depth and output the rest of the chunk.
+ if(chunks[ch_i] ~ /^endif[[:blank:]\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 `<!--#" \
+ chunks[chunk_i] "'" > "/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 AUTHORS ChangeLog ...,
Pavel Kharitonov <=