trans-coord-devel
[Top][All Lists]
Advanced

[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(/&/, "\\&amp;", str); gsub(/"/, "\\&quot;", str)
+  gsub(/</, "\\&lt;", str);  gsub(/>/, "\\&gt;", 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
+    }
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]