Squashed 'third_party/ctemplate/' content from commit 6742f62

Change-Id: I828e4e4c906f13ba19944d78a8a78652b62949af
git-subtree-dir: third_party/ctemplate
git-subtree-split: 6742f6233db12f545e90baa8f34f5c29c4eb396a
diff --git a/contrib/README.contrib b/contrib/README.contrib
new file mode 100644
index 0000000..861ba7c
--- /dev/null
+++ b/contrib/README.contrib
@@ -0,0 +1,13 @@
+All files under this contrib directory are UNSUPPORTED; use at your
+own risk.  They were provided by users of ctemplate and were not
+tested by the authors of ctemplate.  These files are not owned by
+Google.  Please contact the authors of the contributions for help
+about these, not the ctemplate authors. Thanks!, and enjoy.
+
+highlighting.vim    by Patrick Lacasse <patlac@borabora.crchul.ulaval.ca>
+   How to set up syntax highlighting (colorization) for ctemplate .tpl
+   files, using vim.  A shar file; see top-of-file for how to extract.
+
+tpl-mode.el   by Tony Gentilcore
+   Elisp file for syntax highlighting (colorization) for ctemplate
+   .tpl files, using emacs.  See top-of-file for how to use.
diff --git a/contrib/convert_to_95.pl b/contrib/convert_to_95.pl
new file mode 100755
index 0000000..1b70e1c
--- /dev/null
+++ b/contrib/convert_to_95.pl
@@ -0,0 +1,117 @@
+#!/usr/bin/perl -pli.bak
+
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ---
+# Author: Craig Silverstein
+
+# This is a perl script for editing your source files that were
+# written with ctemplate <0.95, to use the new #include paths,
+# namespace names, and function locations in ctemplate 0.95.
+#
+# This script will modify your files in place.  It is safe to
+# call it multiple times.  To call it, do something like:
+#    find <root of my project tree> -print0 | xargs -0 ./convert_to_95.pl
+#
+# Issues:
+#    TemplateFromString logic is tricky.  Best to check up by hand.
+#    Can't always tell when 1st arg to TemplateFromString is empty string.
+#      If it might be for your app, change the logic to use StringToTemplate.
+#    Fails if TemplateFromString or StringToTemplate span multiple lines.
+
+# Change all the #include lines
+s@google/template.h@ctemplate/template.h@g;
+s@google/per_expand_data.h@ctemplate/per_expand_data.h@g;
+s@google/template.h@ctemplate/template.h@g;
+s@google/template_annotator.h@ctemplate/template_annotator.h@g;
+s@google/template_dictionary.h@ctemplate/template_dictionary.h@g;
+s@google/template_dictionary_interface.h@ctemplate/template_dictionary_interface.h@g;
+s@google/template_emitter.h@ctemplate/template_emitter.h@g;
+s@google/template_enums.h@ctemplate/template_enums.h@g;
+s@google/template_from_string.h@ctemplate/template_from_string.h@g;
+s@google/template_modifiers.h@ctemplate/template_modifiers.h@g;
+s@google/template_namelist.h@ctemplate/template_namelist.h@g;
+s@google/template_pathops.h@ctemplate/template_pathops.h@g;
+s@google/template_string.h@ctemplate/template_string.h@g;
+
+# Change all the namespace uses
+s@namespace\s+google@namespace ctemplate@g;   # brought into google namespace
+s@\bgoogle::@ctemplate::@g;
+s@namespace\s+template_modifiers\s*{@@ && ($in_tm = 1);
+$in_tm && s@}@@ && ($in_tm = 0);
+s@\btemplate_modifiers::@@g;
+
+# Change TemplateFromString::GetTemplate to
+#   Template::StringToTemplateCache(cache_key, template_text);
+#   return Template::GetTemplate(cache_key, strip);
+# unless cache_key is the empty string, in which case it should be
+#   return Template::StringToTemplate(template_text, strip, TC_MANUAL);
+# We have to be tricky, to do this in one command.
+# Better would be to just do Template::StringToTemplate(), but then we
+# have to free the memory when we're done, which is too hard to do here.
+s@TemplateFromString::GetTemplate\s*\(""\s*,([^,]+),([^,]+)\)@Template::StringToTemplate($1, $2, ctemplate::TC_MANUAL)@;
+s@TemplateFromString::GetTemplate\s*\(([^,]+),([^,]+),([^,]+)\)@Template::GetTemplate((ctemplate::Template::StringToTemplateCache($1, $2), $1), $3)@;
+
+if (m@TemplateFromString::GetTemplate\s*\([^)]*$@) {
+  warn("$ARGV:$.: TemplateFromString spans mutiple lines.  You will need " .
+       "to clean it up by hand.  See comments in $0.");
+}
+
+# Get rid of the 4th arg to Template::TemplateToString.  If it's
+# TC_MANUAL, that's fine.  If it's not, we need to tell the user to
+# fix this up manually by adding an {{%PRAGMA AUTOESCAPE}} to the
+# beginning of their string.
+if (s@(\bStringToTemplate\s*\([^)]*),\s*TC_([A-Z_]*)@$1@g) {
+  if ($2 ne "MANUAL") {    # TC_MANUAL is the new default
+    warn("WARNING: $ARGV:$.: You will need to manually fix up the " .
+         "StringToTemplate change to add an AUTOESCAPE {{\%pragma}} to " .
+         "the beginning of the input string, to set the context to TC_$2\n");
+  }
+}
+if (m@\bStringToTemplate\s*\([^)]*$@) {
+  warn("$ARGV:$.: StringToTemplate spans mutiple lines.  You will need " .
+       "to clean it up by hand: get rid of the TC_foo arg.  If it's not " .
+       "TC_MANUAL, you will need to add an AUTOESCAPE pragma.  " .
+       "See comments in $0.");
+}
+
+# Change all the TemplateDictionary escapes.  Now they are globals in
+# the ctemplate namespace.
+s@TemplateDictionary::html_escape@html_escape@g;
+s@TemplateDictionary::pre_escape@pre_escape@g;
+s@TemplateDictionary::xml_escape@xml_escape@g;
+s@TemplateDictionary::javascript_escape@javascript_escape@g;
+s@TemplateDictionary::url_query_escape@url_query_escape@g;
+s@TemplateDictionary::json_escape@json_escape@g;
+
+# This cleans up anything messy we left behind.
+s@\bctemplate::ctemplate::@ctemplate::@g;   # get rid of redundant specifier
+
+close ARGV if eof;        # to reset $. for each file
diff --git a/contrib/highlighting.vim b/contrib/highlighting.vim
new file mode 100644
index 0000000..67d534d
--- /dev/null
+++ b/contrib/highlighting.vim
@@ -0,0 +1,212 @@
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2.1).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 2006-08-08 13:38 PDT by <patlac@borabora.crchul.ulaval.ca>.
+# Commandline: shar -T .vim
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode       name
+# ------ ---------- ------------------------------------------
+#   1477 -rw-r--r-- .vim/syntax/tpl.vim
+#     56 -rw-r--r-- .vim/ftdetect/tpl.vim
+#
+echo >/dev/null <<_NOTES_EOF
+From: Patrick Lacasse <patlac@borabora.crchul.ulaval.ca>
+Subject: vim color for google-ctemplate howto
+To: google-ctemplate@googlegroups.com
+Date: Fri, 4 Aug 2006 11:38:39 -0400
+
+Hi group,
+
+  I'm now using google-ctemplate. My text editor is vim. Here is a little gift 
+for other people like me.
+
+Howto have google-ctemplate colored by vim :
+
+In your home directory, run 'sh $0'.
+
+Now restart vim.
+
+This will autodetects file with tpl extension and colors them. You can change 
+the color by changing the HiLink lines ( try changing String by 
+Identifier ) .
+
+I'm not sure exactly about what are the legal marker names. Feel free to 
+change the regexes.
+
+I only tryed this with vim 6.4 , I just cut and past the things about version 
+checking.
+
+For more information about syntax higlithning in vim, try 
+:help syntax
+
+Amusez-vous bien,
+
+Patrick Lacasse
+patlac@borabora.crchul.ulaval.ca
+_NOTES_EOF
+
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+     && ($dir/gettext --version >/dev/null 2>&1)
+  then
+    set `$dir/gettext --version 2>&1`
+    if test "$3" = GNU
+    then
+      gettext_dir=$dir
+    fi
+  fi
+  if test "$locale_dir" = FAILED && test -f $dir/shar \
+     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+  then
+    locale_dir=`$dir/shar --print-text-domain-dir`
+  fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+  echo=echo
+else
+  TEXTDOMAINDIR=$locale_dir
+  export TEXTDOMAINDIR
+  TEXTDOMAIN=sharutils
+  export TEXTDOMAIN
+  echo="$gettext_dir/gettext -s"
+fi
+if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
+  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
+elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
+  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
+elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
+  shar_touch='touch -am $3$4$5$6$2 "$8"'
+else
+  shar_touch=:
+  echo
+  $echo 'WARNING: not restoring timestamps.  Consider getting and'
+  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+  echo
+fi
+rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
+#
+if mkdir _sh09814; then
+  $echo 'x -' 'creating lock directory'
+else
+  $echo 'failed to create lock directory'
+  exit 1
+fi
+# ============= .vim/syntax/tpl.vim ==============
+if test ! -d '.vim'; then
+  $echo 'x -' 'creating directory' '.vim'
+  mkdir '.vim'
+fi
+if test ! -d '.vim/syntax'; then
+  $echo 'x -' 'creating directory' '.vim/syntax'
+  mkdir '.vim/syntax'
+fi
+if test -f '.vim/syntax/tpl.vim' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING '.vim/syntax/tpl.vim' '(file already exists)'
+else
+  $echo 'x -' extracting '.vim/syntax/tpl.vim' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > '.vim/syntax/tpl.vim' &&
+" Vim syntax file
+" Language:     google-ctemplate
+" Maintainer:   Patrick Lacasse <patlac@borabora.crchul.ulaval.ca>
+" Last Change:  2006 Août 03
+"
+" For information about google-ctemplate see 
+"   http://goog-ctemplate.sourceforge.net/
+"
+" This vim syntax file works on vim 5.6, 5.7, 5.8 and 6.x.
+" It implements Bram Moolenaar's April 25, 2001 recommendations to make
+" the syntax file maximally portable across different versions of vim.
+X
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+X  syntax clear
+elseif exists("b:current_syntax")
+X  finish
+endif
+X
+syntax match tplMarkerError "{{}\?\([^}]\+}\?\)*}}"
+syntax match tplSectionMarker "{{[#/][A-Za-z_]\+}}"
+syntax match tplInclude "{{>[A-Za-z_]\+}}"
+syntax match tplComment "{{![A-Za-z_]\+}}"
+syntax match tplVariableMarker "{{[_A-Za-z]\+}}"
+X
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_tpl_syn_inits")
+X  if version < 508
+X    let did_tpl_syn_inits = 1
+X    command -nargs=+ HiLink hi link <args>
+X  else
+X    command -nargs=+ HiLink hi def link <args>
+X  endif
+X
+X  HiLink tplSectionMarker   Repeat
+X  HiLink tplInclude         Include
+X  HiLink tplComment         Comment
+X  HiLink tplVariableMarker  String
+X  HiLink tplMarkerError     Error
+X
+X  delcommand HiLink
+endif
+X
+let b:current_syntax = "tpl"
+SHAR_EOF
+  (set 20 06 08 08 13 34 11 '.vim/syntax/tpl.vim'; eval "$shar_touch") &&
+  chmod 0644 '.vim/syntax/tpl.vim' ||
+  $echo 'restore of' '.vim/syntax/tpl.vim' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo '.vim/syntax/tpl.vim:' 'MD5 check failed'
+536faef79eff0597e642c5db04c1f79d  .vim/syntax/tpl.vim
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/syntax/tpl.vim'`"
+    test 1477 -eq "$shar_count" ||
+    $echo '.vim/syntax/tpl.vim:' 'original size' '1477,' 'current size' "$shar_count!"
+  fi
+fi
+# ============= .vim/ftdetect/tpl.vim ==============
+if test ! -d '.vim/ftdetect'; then
+  $echo 'x -' 'creating directory' '.vim/ftdetect'
+  mkdir '.vim/ftdetect'
+fi
+if test -f '.vim/ftdetect/tpl.vim' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING '.vim/ftdetect/tpl.vim' '(file already exists)'
+else
+  $echo 'x -' extracting '.vim/ftdetect/tpl.vim' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > '.vim/ftdetect/tpl.vim' &&
+au BufRead,BufNewFile *.tpl            set filetype=tpl
+SHAR_EOF
+  (set 20 06 08 08 13 34 20 '.vim/ftdetect/tpl.vim'; eval "$shar_touch") &&
+  chmod 0644 '.vim/ftdetect/tpl.vim' ||
+  $echo 'restore of' '.vim/ftdetect/tpl.vim' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo '.vim/ftdetect/tpl.vim:' 'MD5 check failed'
+774fd4a092b77400ef6e74a7256ff8ef  .vim/ftdetect/tpl.vim
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/ftdetect/tpl.vim'`"
+    test 56 -eq "$shar_count" ||
+    $echo '.vim/ftdetect/tpl.vim:' 'original size' '56,' 'current size' "$shar_count!"
+  fi
+fi
+rm -fr _sh09814
+exit 0
diff --git a/contrib/tpl-mode.el b/contrib/tpl-mode.el
new file mode 100644
index 0000000..ff1afd4
--- /dev/null
+++ b/contrib/tpl-mode.el
@@ -0,0 +1,262 @@
+;;; tpl-mode.el -- a major mode for editing Google CTemplate files.
+;;; By Tony Gentilcore, July 2006
+;;;
+;;; TO USE:
+;;; 1) Copy this file somewhere you in emacs load-path.  To see what
+;;;    your load-path is, run inside emacs: C-h v load-path<RET>
+;;; 2) Add the following two lines to your .emacs file:
+;;;    (setq auto-mode-alist (cons '("\\.tpl$" . tpl-mode) auto-mode-alist))
+;;;    (autoload 'tpl-mode "tpl-mode" "Major mode for editing CTemplate files." t)
+;;; 3) Optionally (but recommended), add this third line as well:
+;;;    (add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
+;;; ---
+;;;
+;;; While the CTemplate language can be used for any types of text,
+;;; this mode is intended for using CTemplate to write HTML.
+;;;
+;;; The indentation still has minor bugs due to the fact that
+;;; templates do not require valid HTML.
+;;;
+;;; It would be nice to be able to highlight attributes of HTML tags,
+;;; however this is difficult due to the presence of CTemplate symbols
+;;; embedded within attributes.
+
+(eval-when-compile
+  (require 'font-lock))
+
+(defgroup tpl-mode nil
+  "Major mode for editing CTemplate files"
+  :group 'languages)
+
+(defvar tpl-mode-version "1.0"
+  "Version of `tpl-mode.el'.")
+
+(defvar tpl-mode-abbrev-table nil
+  "Abbrev table for use in tpl-mode buffers.")
+
+(define-abbrev-table 'tpl-mode-abbrev-table ())
+
+(defcustom tpl-mode-hook nil
+  "*Hook that runs upon entering tpl-mode."
+  :type 'hook
+  )
+
+(defvar tpl-mode-map nil
+  "Keymap for tpl-mode major mode")
+
+(if tpl-mode-map
+    nil
+  (setq tpl-mode-map (make-sparse-keymap))
+  )
+
+(define-key tpl-mode-map "\t" 'tpl-indent-command)
+(define-key tpl-mode-map "\C-m" 'newline-and-indent)
+
+
+(defvar tpl-mode-syntax-table nil
+  "Syntax table in use in tpl-mode buffers.")
+
+;; Syntax table.
+(if tpl-mode-syntax-table
+    nil
+  (setq tpl-mode-syntax-table (make-syntax-table text-mode-syntax-table))
+  (modify-syntax-entry ?<  "(>  " tpl-mode-syntax-table)
+  (modify-syntax-entry ?>  ")<  " tpl-mode-syntax-table)
+  (modify-syntax-entry ?\" ".   " tpl-mode-syntax-table)
+  (modify-syntax-entry ?\\ ".   " tpl-mode-syntax-table)
+  (modify-syntax-entry ?'  "w   " tpl-mode-syntax-table)
+  )
+
+(defvar tpl-basic-offset 2
+  "The basic indentation offset.")
+
+;; Constant regular expressions to identify template elements.
+(defconst tpl-mode-tpl-token "[a-zA-Z][a-zA-Z0-9_:=\-]*?")
+(defconst tpl-mode-section (concat "\\({{[#/]"
+				   tpl-mode-tpl-token
+				   "}}\\)"))
+(defconst tpl-mode-open-section (concat "\\({{#"
+					tpl-mode-tpl-token
+					"}}\\)"))
+(defconst tpl-mode-close-section (concat "{{/\\("
+					 tpl-mode-tpl-token
+					 "\\)}}"))
+(defconst tpl-mode-comment "\\({{![^}]+?}}\\)")
+(defconst tpl-mode-include (concat "\\({{>"
+				   tpl-mode-tpl-token
+				   "}}\\)"))
+(defconst tpl-mode-variable (concat "\\({{"
+				    tpl-mode-tpl-token
+				    "}}\\)"))
+(defconst tpl-mode-builtins
+  (concat
+   "\\({{\\<"
+   (regexp-opt
+    '("BI_NEWLINE" "BI_SPACE")
+    t)
+   "\\>}}\\)"))
+(defconst tpl-mode-close-section-at-start (concat "^[ \t]*?"
+						  tpl-mode-close-section))
+
+;; Constant regular expressions to identify html tags.
+;; Taken from HTML 4.01 / XHTML 1.0 Reference found at:
+;; http://www.w3schools.com/tags/default.asp.
+(defconst tpl-mode-html-constant "\\(&#?[a-z0-9]\\{2,5\\};\\)")
+(defconst tpl-mode-pair-tag
+  (concat
+   "\\<"
+   (regexp-opt
+    '("a" "abbr" "acronym" "address" "applet" "area" "b" "bdo"
+      "big" "blockquote" "body" "button" "caption" "center" "cite"
+      "code" "col" "colgroup" "dd" "del" "dfn" "dif" "div" "dl"
+      "dt" "em" "fieldset" "font" "form" "frame" "frameset" "h1"
+      "h2" "h3" "h4" "h5" "h6" "head" "html" "i" "iframe" "ins"
+      "kbd" "label" "legend" "li" "link" "map" "menu" "noframes"
+      "noscript" "object" "ol" "optgroup" "option" "p" "pre" "q"
+      "s" "samp" "script" "select" "small" "span" "strike"
+      "strong" "style" "sub" "sup" "table" "tbody" "td" "textarea"
+      "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
+    t)
+   "\\>"))
+(defconst tpl-mode-standalone-tag
+  (concat
+   "\\<"
+   (regexp-opt
+    '("base" "br" "hr" "img" "input" "meta" "param")
+    t)
+   "\\>"))
+(defconst tpl-mode-open-tag (concat "<\\("
+				    tpl-mode-pair-tag
+				    "\\)"))
+(defconst tpl-mode-close-tag (concat "</\\("
+				     tpl-mode-pair-tag
+				     "\\)>"))
+(defconst tpl-mode-close-tag-at-start (concat "^[ \t]*?"
+					      tpl-mode-close-tag))
+
+(defconst tpl-mode-blank-line "^[ \t]*?$")
+(defconst tpl-mode-dangling-open (concat "\\("
+					 tpl-mode-open-section
+					 "\\)\\|\\("
+					 tpl-mode-open-tag
+					 "\\)[^/]*$"))
+
+(defun tpl-indent-command ()
+  "Command for indenting text. Just calls tpl-indent."
+  (interactive)
+  (tpl-indent))
+
+;; Function to control indenting.
+(defun tpl-indent ()
+  "Indent current line"
+  ;; Set the point to beginning of line.
+  (beginning-of-line)
+  ;; If we are at the beginning of the file, indent to 0.
+  (if (bobp)
+      (indent-line-to 0)
+    (let ((tag-stack 1) (close-tag "") (cur-indent 0) (old-pnt (point-marker))
+	  (close-at-start) (open-token) (dangling-open))
+      (progn
+	;; Determine if this is a template line or an html line.
+	(if (looking-at "^[ \t]*?{{")
+	    (setq close-at-start tpl-mode-close-section-at-start
+		  open-token "{{#")
+	  (setq close-at-start tpl-mode-close-tag-at-start
+		open-token "<")
+	  )
+	;; If there is a closing tag at the start of the line, search back
+	;; for its opener and indent to that level.
+	(if (looking-at close-at-start)
+	    (progn
+	      (save-excursion
+		(setq close-tag (match-string 1))
+		;; Keep searching for a match for the close tag until
+		;; the tag-stack is 0.
+		(while (and (not (bobp))
+			    (> tag-stack 0)
+			    (re-search-backward (concat open-token
+							"\\(/?\\)"
+							close-tag) nil t))
+		  (if (string-equal (match-string 1) "/")
+		      ;; We found another close tag, so increment tag-stack.
+		      (setq tag-stack (+ tag-stack 1))
+		    ;; We found an open tag, so decrement tag-stack.
+		    (setq tag-stack (- tag-stack 1))
+		    )
+		  (setq cur-indent (current-indentation))
+		  )
+		)
+	      (if (> tag-stack 0)
+		  (save-excursion
+		    (forward-line -1)
+		    (setq cur-indent (current-indentation))
+		    )
+		)
+	      )
+	  ;; This was not a closing tag, so we check if the previous line
+	  ;; was an opening tag.
+	  (save-excursion
+	    ;; Keep moving back until we find a line that is not blank
+	    (while (progn
+		     (forward-line -1)
+		     (and (not (bobp)) (looking-at tpl-mode-blank-line))
+		     )
+	      )
+	    (setq cur-indent (current-indentation))
+	    (if (re-search-forward tpl-mode-dangling-open old-pnt t)
+		(setq cur-indent (+ cur-indent tpl-basic-offset))
+	      )
+	    )
+	  )
+	;; Finally, we execute the actual indentation.
+	(if (> cur-indent 0)
+	    (indent-line-to cur-indent)
+	  (indent-line-to 0)
+	  )
+	)
+      )
+    )
+  )
+
+;; controls highlighting
+(defconst tpl-mode-font-lock-keywords
+  (list
+   (list tpl-mode-section
+         '(1 font-lock-keyword-face))
+   (list tpl-mode-comment
+         '(1 font-lock-comment-face))
+   (list tpl-mode-include
+         '(1 font-lock-builtin-face))
+   (list tpl-mode-builtins
+         '(1 font-lock-variable-name-face))
+   (list tpl-mode-variable
+         '(1 font-lock-reference-face))
+   (list (concat "</?\\(" tpl-mode-pair-tag "\\)")
+         '(1 font-lock-function-name-face))
+   (list (concat "<\\(" tpl-mode-standalone-tag "\\)")
+         '(1 font-lock-function-name-face))
+   (list tpl-mode-html-constant
+         '(1 font-lock-variable-name-face))
+   ))
+
+(put 'tpl-mode 'font-lock-defaults '(tpl-font-lock-keywords nil t))
+
+(defun tpl-mode ()
+  "Major mode for editing CTemplate file."
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map tpl-mode-map)
+  (setq major-mode 'tpl-mode)
+  (setq mode-name "tpl-mode")
+  (setq local-abbrev-table tpl-mode-abbrev-table)
+  (setq indent-tabs-mode nil)
+  (set-syntax-table tpl-mode-syntax-table)
+  ; show trailing whitespace, but only when the user can fix it
+  (setq show-trailing-whitespace (not buffer-read-only))
+  (make-local-variable 'indent-line-function)
+  (setq indent-line-function 'tpl-indent)
+  (setq font-lock-defaults '(tpl-mode-font-lock-keywords))
+  (run-hooks 'tpl-mode-hook)
+)
+
+(provide 'tpl-mode)