mirror of
https://github.com/OlafvdSpek/ctemplate.git
synced 2025-09-28 19:05:49 +08:00
Thu Jun 21 14:02:32 2007 Google Inc. <opensource@google.com>
* ctemplate: version 0.6.1 release * Bugfix: data corruption bug with >2 template modifiers (jmacgill) * Bugfix: syntax error in template-namelist: configure-bug (csilvers) * Bugfix: improve lock hygenie to avoid potential deadlock (csilvers)
This commit is contained in:
parent
f0a3fceb99
commit
cf4599bd94
|
@ -51,3 +51,10 @@ Sat Jun 9 22:34:52 2007 Google Inc. <opensource@google.com>
|
|||
* New modifiers for url-escaping, attribute-cleansing, etc (ribrdb)
|
||||
* Annotations now include modifier information (csilvers)
|
||||
* Support embedded NULs in template names and values (csilvers)
|
||||
|
||||
Thu Jun 21 14:02:32 2007 Google Inc. <opensource@google.com>
|
||||
|
||||
* ctemplate: version 0.6.1 release
|
||||
* Bugfix: data corruption bug with >2 template modifiers (jmacgill)
|
||||
* Bugfix: syntax error in template-namelist: configure-bug (csilvers)
|
||||
* Bugfix: improve lock hygenie to avoid potential deadlock (csilvers)
|
||||
|
|
70
INSTALL
70
INSTALL
|
@ -1,16 +1,14 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
|
@ -70,9 +68,9 @@ The simplest way to compile this package is:
|
|||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
|
@ -85,7 +83,7 @@ is an example:
|
|||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
|
@ -102,19 +100,19 @@ for another architecture.
|
|||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
|
@ -125,7 +123,7 @@ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
|
@ -140,11 +138,11 @@ you can use the `configure' options `--x-includes=DIR' and
|
|||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
|
@ -159,7 +157,7 @@ where SYSTEM can have one of these forms:
|
|||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
|
@ -170,9 +168,9 @@ eventually be run) with `--host=TYPE'.
|
|||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
|
@ -181,7 +179,7 @@ A warning: not all `configure' scripts look for a site script.
|
|||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
|
@ -189,18 +187,14 @@ them in the `configure' command line, using `VAR=value'. For example:
|
|||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script). Here is a another example:
|
||||
|
||||
/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
|
||||
configuration-related scripts to be executed by `/bin/bash'.
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
|
|
|
@ -64,7 +64,7 @@ CTEMPLATE_SYMBOLS = '[^A-Za-z](Template|TemplateDictionary|TemplateNamelist|Temp
|
|||
|
||||
lib_LTLIBRARIES += libctemplate.la
|
||||
libctemplate_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
|
||||
src/base/arena.h src/base/arena.cc src/base/mutex.h src/base/mutex.cc \
|
||||
src/base/arena.h src/base/arena.cc src/base/mutex.h \
|
||||
src/template.cc src/template_dictionary.cc src/template_modifiers.cc \
|
||||
src/template_namelist.cc src/template_from_string.cc
|
||||
libctemplate_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
|
||||
|
|
22
Makefile.in
22
Makefile.in
|
@ -90,7 +90,7 @@ am__DEPENDENCIES_1 =
|
|||
libctemplate_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
am__objects_1 =
|
||||
am_libctemplate_la_OBJECTS = $(am__objects_1) libctemplate_la-arena.lo \
|
||||
libctemplate_la-mutex.lo libctemplate_la-template.lo \
|
||||
libctemplate_la-template.lo \
|
||||
libctemplate_la-template_dictionary.lo \
|
||||
libctemplate_la-template_modifiers.lo \
|
||||
libctemplate_la-template_namelist.lo \
|
||||
|
@ -98,7 +98,6 @@ am_libctemplate_la_OBJECTS = $(am__objects_1) libctemplate_la-arena.lo \
|
|||
libctemplate_la_OBJECTS = $(am_libctemplate_la_OBJECTS)
|
||||
libctemplate_nothreads_la_LIBADD =
|
||||
am__objects_2 = $(am__objects_1) libctemplate_nothreads_la-arena.lo \
|
||||
libctemplate_nothreads_la-mutex.lo \
|
||||
libctemplate_nothreads_la-template.lo \
|
||||
libctemplate_nothreads_la-template_dictionary.lo \
|
||||
libctemplate_nothreads_la-template_modifiers.lo \
|
||||
|
@ -326,6 +325,7 @@ ac_ct_RANLIB = @ac_ct_RANLIB@
|
|||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
ac_cv_cxx_hash_map = @ac_cv_cxx_hash_map@
|
||||
ac_cv_cxx_hash_namespace = @ac_cv_cxx_hash_namespace@
|
||||
ac_cv_cxx_hash_set = @ac_cv_cxx_hash_set@
|
||||
ac_google_attribute = @ac_google_attribute@
|
||||
ac_google_end_namespace = @ac_google_end_namespace@
|
||||
ac_google_namespace = @ac_google_namespace@
|
||||
|
@ -435,7 +435,7 @@ noinst_SCRIPTS = src/tests/make_tpl_varnames_h_unittest.sh
|
|||
# These are the symbols (classes, mostly) we want to export from our library
|
||||
CTEMPLATE_SYMBOLS = '[^A-Za-z](Template|TemplateDictionary|TemplateNamelist|TemplateFromString|TemplateString|TemplateState|Strip)[^A-Za-z]'
|
||||
libctemplate_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
|
||||
src/base/arena.h src/base/arena.cc src/base/mutex.h src/base/mutex.cc \
|
||||
src/base/arena.h src/base/arena.cc src/base/mutex.h \
|
||||
src/template.cc src/template_dictionary.cc src/template_modifiers.cc \
|
||||
src/template_namelist.cc src/template_from_string.cc
|
||||
|
||||
|
@ -723,14 +723,12 @@ distclean-compile:
|
|||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-arena.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-mutex.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-template.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-template_dictionary.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-template_from_string.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-template_modifiers.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_la-template_namelist.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_nothreads_la-arena.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_nothreads_la-mutex.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_nothreads_la-template.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_nothreads_la-template_dictionary.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctemplate_nothreads_la-template_from_string.Plo@am__quote@
|
||||
|
@ -779,13 +777,6 @@ libctemplate_la-arena.lo: src/base/arena.cc
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_la_CXXFLAGS) $(CXXFLAGS) -c -o libctemplate_la-arena.lo `test -f 'src/base/arena.cc' || echo '$(srcdir)/'`src/base/arena.cc
|
||||
|
||||
libctemplate_la-mutex.lo: src/base/mutex.cc
|
||||
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_la_CXXFLAGS) $(CXXFLAGS) -MT libctemplate_la-mutex.lo -MD -MP -MF "$(DEPDIR)/libctemplate_la-mutex.Tpo" -c -o libctemplate_la-mutex.lo `test -f 'src/base/mutex.cc' || echo '$(srcdir)/'`src/base/mutex.cc; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libctemplate_la-mutex.Tpo" "$(DEPDIR)/libctemplate_la-mutex.Plo"; else rm -f "$(DEPDIR)/libctemplate_la-mutex.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/mutex.cc' object='libctemplate_la-mutex.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_la_CXXFLAGS) $(CXXFLAGS) -c -o libctemplate_la-mutex.lo `test -f 'src/base/mutex.cc' || echo '$(srcdir)/'`src/base/mutex.cc
|
||||
|
||||
libctemplate_la-template.lo: src/template.cc
|
||||
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_la_CXXFLAGS) $(CXXFLAGS) -MT libctemplate_la-template.lo -MD -MP -MF "$(DEPDIR)/libctemplate_la-template.Tpo" -c -o libctemplate_la-template.lo `test -f 'src/template.cc' || echo '$(srcdir)/'`src/template.cc; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libctemplate_la-template.Tpo" "$(DEPDIR)/libctemplate_la-template.Plo"; else rm -f "$(DEPDIR)/libctemplate_la-template.Tpo"; exit 1; fi
|
||||
|
@ -828,13 +819,6 @@ libctemplate_nothreads_la-arena.lo: src/base/arena.cc
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_nothreads_la_CXXFLAGS) $(CXXFLAGS) -c -o libctemplate_nothreads_la-arena.lo `test -f 'src/base/arena.cc' || echo '$(srcdir)/'`src/base/arena.cc
|
||||
|
||||
libctemplate_nothreads_la-mutex.lo: src/base/mutex.cc
|
||||
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_nothreads_la_CXXFLAGS) $(CXXFLAGS) -MT libctemplate_nothreads_la-mutex.lo -MD -MP -MF "$(DEPDIR)/libctemplate_nothreads_la-mutex.Tpo" -c -o libctemplate_nothreads_la-mutex.lo `test -f 'src/base/mutex.cc' || echo '$(srcdir)/'`src/base/mutex.cc; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libctemplate_nothreads_la-mutex.Tpo" "$(DEPDIR)/libctemplate_nothreads_la-mutex.Plo"; else rm -f "$(DEPDIR)/libctemplate_nothreads_la-mutex.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/mutex.cc' object='libctemplate_nothreads_la-mutex.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_nothreads_la_CXXFLAGS) $(CXXFLAGS) -c -o libctemplate_nothreads_la-mutex.lo `test -f 'src/base/mutex.cc' || echo '$(srcdir)/'`src/base/mutex.cc
|
||||
|
||||
libctemplate_nothreads_la-template.lo: src/template.cc
|
||||
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libctemplate_nothreads_la_CXXFLAGS) $(CXXFLAGS) -MT libctemplate_nothreads_la-template.lo -MD -MP -MF "$(DEPDIR)/libctemplate_nothreads_la-template.Tpo" -c -o libctemplate_nothreads_la-template.lo `test -f 'src/template.cc' || echo '$(srcdir)/'`src/template.cc; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libctemplate_nothreads_la-template.Tpo" "$(DEPDIR)/libctemplate_nothreads_la-template.Plo"; else rm -f "$(DEPDIR)/libctemplate_nothreads_la-template.Tpo"; exit 1; fi
|
||||
|
|
24
configure
vendored
24
configure
vendored
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.59 for ctemplate 0.6.
|
||||
# Generated by GNU Autoconf 2.59 for ctemplate 0.6.1.
|
||||
#
|
||||
# Report bugs to <opensource@google.com>.
|
||||
#
|
||||
|
@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='ctemplate'
|
||||
PACKAGE_TARNAME='ctemplate'
|
||||
PACKAGE_VERSION='0.6'
|
||||
PACKAGE_STRING='ctemplate 0.6'
|
||||
PACKAGE_VERSION='0.6.1'
|
||||
PACKAGE_STRING='ctemplate 0.6.1'
|
||||
PACKAGE_BUGREPORT='opensource@google.com'
|
||||
|
||||
ac_unique_file="README"
|
||||
|
@ -465,7 +465,7 @@ ac_includes_default="\
|
|||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS ac_google_namespace ac_google_start_namespace ac_google_end_namespace ac_cv_cxx_hash_namespace ac_cv_cxx_hash_map ac_google_attribute LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS ac_google_namespace ac_google_start_namespace ac_google_end_namespace ac_cv_cxx_hash_namespace ac_cv_cxx_hash_map ac_cv_cxx_hash_set ac_google_attribute LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures ctemplate 0.6 to adapt to many kinds of systems.
|
||||
\`configure' configures ctemplate 0.6.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of ctemplate 0.6:";;
|
||||
short | recursive ) echo "Configuration of ctemplate 0.6.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1163,7 +1163,7 @@ fi
|
|||
test -n "$ac_init_help" && exit 0
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
ctemplate configure 0.6
|
||||
ctemplate configure 0.6.1
|
||||
generated by GNU Autoconf 2.59
|
||||
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
@ -1177,7 +1177,7 @@ cat >&5 <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by ctemplate $as_me 0.6, which was
|
||||
It was created by ctemplate $as_me 0.6.1, which was
|
||||
generated by GNU Autoconf 2.59. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -1823,7 +1823,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='ctemplate'
|
||||
VERSION='0.6'
|
||||
VERSION='0.6.1'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -20613,6 +20613,7 @@ echo "$as_me: WARNING: could not find an STL hash_map" >&2;}
|
|||
|
||||
|
||||
|
||||
|
||||
if test "$ac_cv___attribute__" == "yes"; then
|
||||
ac_google_attribute=1
|
||||
|
||||
|
@ -21007,7 +21008,7 @@ _ASBOX
|
|||
} >&5
|
||||
cat >&5 <<_CSEOF
|
||||
|
||||
This file was extended by ctemplate $as_me 0.6, which was
|
||||
This file was extended by ctemplate $as_me 0.6.1, which was
|
||||
generated by GNU Autoconf 2.59. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -21070,7 +21071,7 @@ _ACEOF
|
|||
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
ctemplate config.status 0.6
|
||||
ctemplate config.status 0.6.1
|
||||
configured by $0, generated by GNU Autoconf 2.59,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -21351,6 +21352,7 @@ s,@ac_google_start_namespace@,$ac_google_start_namespace,;t t
|
|||
s,@ac_google_end_namespace@,$ac_google_end_namespace,;t t
|
||||
s,@ac_cv_cxx_hash_namespace@,$ac_cv_cxx_hash_namespace,;t t
|
||||
s,@ac_cv_cxx_hash_map@,$ac_cv_cxx_hash_map,;t t
|
||||
s,@ac_cv_cxx_hash_set@,$ac_cv_cxx_hash_set,;t t
|
||||
s,@ac_google_attribute@,$ac_google_attribute,;t t
|
||||
s,@LIBOBJS@,$LIBOBJS,;t t
|
||||
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# make sure we're interpreted by some minimal autoconf
|
||||
AC_PREREQ(2.57)
|
||||
|
||||
AC_INIT(ctemplate, 0.6, opensource@google.com)
|
||||
AC_INIT(ctemplate, 0.6.1, opensource@google.com)
|
||||
# The argument here is just something that should be in the current directory
|
||||
# (for sanity checking)
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
|
@ -58,6 +58,7 @@ AC_SUBST(ac_google_start_namespace)
|
|||
AC_SUBST(ac_google_end_namespace)
|
||||
AC_SUBST(ac_cv_cxx_hash_namespace)
|
||||
AC_SUBST(ac_cv_cxx_hash_map)
|
||||
AC_SUBST(ac_cv_cxx_hash_set)
|
||||
if test "$ac_cv___attribute__" == "yes"; then
|
||||
AC_SUBST(ac_google_attribute, 1)
|
||||
else
|
||||
|
|
|
@ -32,6 +32,75 @@
|
|||
<br>
|
||||
|
||||
|
||||
<h2> Simple Example </h2>
|
||||
|
||||
<p>One reason this example is so simple is that it doesn't even
|
||||
require a separate template file, but instead uses
|
||||
<code>TemplateFromString</code>. It also doesn't use sections or
|
||||
template-includes.</p>
|
||||
|
||||
<pre class=example>
|
||||
|
||||
int main() {
|
||||
static const char template_text[] =
|
||||
"ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
|
||||
Template* tpl = TemplateFromString::GetTemplate("error_msg_tpl", template_text,
|
||||
DO_NOT_STRIP);
|
||||
FILE* fp = fopen(argv[1], "r");
|
||||
if (fp == NULL) {
|
||||
int err_no = errno; // squirrel this away
|
||||
TemplateDictionary dict("error_msg: fopen()");
|
||||
dict.SetValue("FUNCTION", "fopen");
|
||||
dict.SetValue("ARGS", argv[1]);
|
||||
dict.SetIntValue("ERROR_CODE", err_no);
|
||||
dict.SetValue("ERROR_MESSAGE", strerror(err_no));
|
||||
|
||||
string error_text;
|
||||
tpl->Expand(&error_text, &dict);
|
||||
puts(error_text.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
|
||||
<p>This example is only slightly more complicated: we only print the
|
||||
": <error message>" part when the error message isn't the empty
|
||||
string.</p>
|
||||
|
||||
<pre class=example>
|
||||
|
||||
int main() {
|
||||
static const char template_text[] =
|
||||
"ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}"
|
||||
"{{#MSG_SECTION}}: {{ERROR_MESSAGE}}{{/MSG_SECTION}}\n";
|
||||
Template* tpl = TemplateFromString::GetTemplate("error_msg", template_text,
|
||||
DO_NOT_STRIP);
|
||||
FILE* fp = fopen(argv[1], "r");
|
||||
if (fp == NULL) {
|
||||
int err_no = errno; // squirrel this away
|
||||
TemplateDictionary dict("file_error_message");
|
||||
dict.SetValue("FUNCTION", "fopen");
|
||||
dict.SetValue("ARGS", argv[1]);
|
||||
dict.SetIntValue("ERROR_CODE", err_no);
|
||||
if (err_no > 0)
|
||||
dict.SetValueAndShowSection("ERROR_MESSAGE", strerror(err_no),
|
||||
"MSG_SECTION");
|
||||
|
||||
string error_text;
|
||||
tpl->Expand(&error_text, &dict);
|
||||
puts(error_text.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
|
||||
<p>This maybe-show-text functionality is one way the template
|
||||
machinery is more powerful than just using <code>printf</code>.
|
||||
Another nice property of templates is you can reuse the same variable
|
||||
multiple times in your template string. You can also define the
|
||||
variable values in any order.</p>
|
||||
|
||||
|
||||
<h2> Search Results Page </h2>
|
||||
|
||||
<p>Here is an example template that could be used to format a Google
|
||||
|
|
65
ltmain.sh
65
ltmain.sh
|
@ -1,3 +1,8 @@
|
|||
# NOTE(csilvers): This file (ltmain.sh) is taken from
|
||||
# http://ftp.gnu.org/gnu/libtool/libtool-1.5.22.tar.gz
|
||||
# with the following patch applied:
|
||||
# http://www.marcuscom.com/downloads/patch-ltmain.sh
|
||||
|
||||
# ltmain.sh - Provide generalized library-building support services.
|
||||
# NOTE: Changing this file will not affect anything until you rerun configure.
|
||||
#
|
||||
|
@ -43,7 +48,7 @@ EXIT_FAILURE=1
|
|||
|
||||
PROGRAM=ltmain.sh
|
||||
PACKAGE=libtool
|
||||
VERSION="1.5.22 Debian 1.5.22-2"
|
||||
VERSION=1.5.22
|
||||
TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
|
||||
|
||||
# See if we are running on zsh, and set the options which allow our
|
||||
|
@ -1604,11 +1609,18 @@ EOF
|
|||
compiler_flags="$compiler_flags $arg"
|
||||
compile_command="$compile_command $arg"
|
||||
finalize_command="$finalize_command $arg"
|
||||
deplibs="$deplibs $arg"
|
||||
continue
|
||||
;;
|
||||
|
||||
-module)
|
||||
module=yes
|
||||
case $host in
|
||||
*-*-freebsd*)
|
||||
# Do not build the useless static library
|
||||
build_old_libs=no
|
||||
;;
|
||||
esac
|
||||
continue
|
||||
;;
|
||||
|
||||
|
@ -2082,10 +2094,7 @@ EOF
|
|||
case $pass in
|
||||
dlopen) libs="$dlfiles" ;;
|
||||
dlpreopen) libs="$dlprefiles" ;;
|
||||
link)
|
||||
libs="$deplibs %DEPLIBS%"
|
||||
test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
|
||||
;;
|
||||
link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
|
||||
esac
|
||||
fi
|
||||
if test "$pass" = dlopen; then
|
||||
|
@ -2104,6 +2113,29 @@ EOF
|
|||
else
|
||||
compiler_flags="$compiler_flags $deplib"
|
||||
fi
|
||||
|
||||
case $linkmode in
|
||||
lib)
|
||||
deplibs="$deplib $deplibs"
|
||||
test "$pass" = conv && continue
|
||||
newdependency_libs="$deplib $newdependency_libs"
|
||||
;;
|
||||
prog)
|
||||
if test "$pass" = conv; then
|
||||
deplibs="$deplib $deplibs"
|
||||
continue
|
||||
fi
|
||||
if test "$pass" = scan; then
|
||||
deplibs="$deplib $deplibs"
|
||||
else
|
||||
compile_deplibs="$deplib $compile_deplibs"
|
||||
finalize_deplibs="$deplib $finalize_deplibs"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac # linkmode
|
||||
|
||||
continue
|
||||
;;
|
||||
-l*)
|
||||
|
@ -3204,11 +3236,6 @@ EOF
|
|||
age="$number_minor"
|
||||
revision="$number_minor"
|
||||
;;
|
||||
*)
|
||||
$echo "$modename: unknown library version type \`$version_type'" 1>&2
|
||||
$echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
|
||||
exit $EXIT_FAILURE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
no)
|
||||
|
@ -4713,6 +4740,9 @@ static const void *lt_preloaded_setup() {
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
# FreeBSD doesn't need this...
|
||||
;;
|
||||
*)
|
||||
$echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
|
||||
exit $EXIT_FAILURE
|
||||
|
@ -6003,10 +6033,17 @@ relink_command=\"$relink_command\""
|
|||
fi
|
||||
|
||||
# Install the pseudo-library for information purposes.
|
||||
name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
|
||||
instname="$dir/$name"i
|
||||
$show "$install_prog $instname $destdir/$name"
|
||||
$run eval "$install_prog $instname $destdir/$name" || exit $?
|
||||
case $host in
|
||||
*-*-freebsd*)
|
||||
# Do not install the useless pseudo-library
|
||||
;;
|
||||
*)
|
||||
name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
|
||||
instname="$dir/$name"i
|
||||
$show "$install_prog $instname $destdir/$name"
|
||||
$run eval "$install_prog $instname $destdir/$name" || exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Maybe install the static library, too.
|
||||
test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
ctemplate (0.6.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Google Inc. <opensource@google.com> Thu, 21 Jun 2007 14:02:32 -0700
|
||||
|
||||
ctemplate (0.6-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
/* Copyright (c) 2007, 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
|
||||
*
|
||||
* A simple mutex wrapper. Right now, it's implemented in terms of
|
||||
* pthreads, but is meant to be easy to extend to other threads impls.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#if defined(NO_THREADS)
|
||||
|
||||
Mutex::Mutex() {}
|
||||
Mutex::~Mutex() {}
|
||||
void Mutex::Lock() {}
|
||||
void Mutex::Unlock() {}
|
||||
void Mutex::ReaderLock() {}
|
||||
void Mutex::ReaderUnlock() {}
|
||||
|
||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
||||
|
||||
#include <stdlib.h> // for abort()
|
||||
#include <pthread.h>
|
||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
||||
|
||||
Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
|
||||
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
|
||||
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
|
||||
#include <stdlib.h> // for abort()
|
||||
#include <pthread.h>
|
||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
||||
|
||||
Mutex::Mutex() { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); }
|
||||
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy(&mutex_)); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock(&mutex_)); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&mutex_)); }
|
||||
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
|
||||
void Mutex::ReaderUnlock() { Unlock(); }
|
||||
|
||||
#else
|
||||
|
||||
#error Need to implement mutex.h/cc for your architecture, or #define NO_THREADS
|
||||
|
||||
#endif
|
|
@ -45,21 +45,25 @@
|
|||
#ifndef GOOGLE_MUTEX_H__
|
||||
#define GOOGLE_MUTEX_H__
|
||||
|
||||
#include "config.h" // to figure out pthreads support
|
||||
#include "config.h" // to figure out pthreads support
|
||||
|
||||
#if defined(NO_THREADS)
|
||||
typedef int MutexType; // some dummy type; it won't be used
|
||||
typedef int MutexType; // some dummy type; it won't be used
|
||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
||||
// Needed for pthread_rwlock_*. If it causes problems, you could take
|
||||
// it out, but then you'd have to unset HAVE_RWLOCK (at least on linux).
|
||||
# define _XOPEN_SOURCE 500 // needed to get the rwlock calls
|
||||
# define _XOPEN_SOURCE 500 // needed to get the rwlock calls
|
||||
# include <pthread.h>
|
||||
typedef pthread_rwlock_t MutexType;
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
# include <pthread.h>
|
||||
typedef pthread_mutex_t MutexType;
|
||||
#elif defined(WIN32)
|
||||
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
|
||||
# include <windows.h>
|
||||
typedef CRITICAL_SECTION MutexType;
|
||||
#else
|
||||
# error Need to implement mutex.h/cc for your architecture, or #define NO_THREADS
|
||||
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
|
||||
#endif
|
||||
|
||||
class Mutex {
|
||||
|
@ -68,22 +72,22 @@ class Mutex {
|
|||
// typically used for Mutexes allocated on the heap or the stack.
|
||||
// See below for a recommendation for constructing global Mutex
|
||||
// objects.
|
||||
Mutex();
|
||||
inline Mutex();
|
||||
|
||||
// Destructor
|
||||
~Mutex();
|
||||
inline ~Mutex();
|
||||
|
||||
void Lock(); // Block if necessary until free, then acquire exclusively
|
||||
void Unlock(); // Release. Caller must hold it exclusively (via Lock())
|
||||
inline void Lock(); // Block if needed until free then acquire exclusively
|
||||
inline void Unlock(); // Release a lock acquired via Lock()
|
||||
|
||||
// Note that on systems that don't support read-write locks, these may
|
||||
// be implemented as synonyms to Lock() and Unlock(). So you can use
|
||||
// these for efficiency, but don't use them anyplace where being able
|
||||
// to do shared reads is necessary to avoid deadlock.
|
||||
void ReaderLock(); // Block until free or shared, then acquire a share
|
||||
void ReaderUnlock(); // Release a read share of this Mutex
|
||||
void WriterLock() { Lock(); } // Block until free, then acquire exclusively
|
||||
void WriterUnlock() { Unlock(); } // Release the exclusive lock of this Mutex
|
||||
inline void ReaderLock(); // Block until free or shared then acquire a share
|
||||
inline void ReaderUnlock(); // Release a read share of this Mutex
|
||||
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
|
||||
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
|
||||
|
||||
private:
|
||||
MutexType mutex_;
|
||||
|
@ -95,6 +99,56 @@ class Mutex {
|
|||
void operator=(const Mutex&);
|
||||
};
|
||||
|
||||
// Now the implementation of Mutex for various systems
|
||||
#if defined(NO_THREADS)
|
||||
|
||||
Mutex::Mutex() {}
|
||||
Mutex::~Mutex() {}
|
||||
void Mutex::Lock() {}
|
||||
void Mutex::Unlock() {}
|
||||
void Mutex::ReaderLock() {}
|
||||
void Mutex::ReaderUnlock() {}
|
||||
|
||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
||||
|
||||
#include <stdlib.h> // for abort()
|
||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
||||
|
||||
Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
|
||||
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
|
||||
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
|
||||
#undef SAFE_PTHREAD
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
|
||||
#include <stdlib.h> // for abort()
|
||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
||||
|
||||
Mutex::Mutex() { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); }
|
||||
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy(&mutex_)); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock(&mutex_)); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&mutex_)); }
|
||||
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
|
||||
void Mutex::ReaderUnlock() { Unlock(); }
|
||||
#undef SAFE_PTHREAD
|
||||
|
||||
#elif defined(WIN32)
|
||||
|
||||
Mutex::Mutex() { InitializeCriticalSection(&mutex_); }
|
||||
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
|
||||
void Mutex::Lock() { EnterCriticalSection(&mutex_); }
|
||||
void Mutex::Unlock() { LeaveCriticalSection(&mutex_); }
|
||||
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
|
||||
void Mutex::ReaderUnlock() { Unlock(); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Some helper classes
|
||||
|
||||
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
||||
class MutexLock {
|
||||
|
|
|
@ -201,6 +201,10 @@ class Template {
|
|||
const TemplateDictionary *dictionary,
|
||||
const TemplateDictionary *force_annotate_dict) const;
|
||||
|
||||
// Internal version of ReloadIfChanged, used when the function already
|
||||
// has a write-lock on mutex_.
|
||||
bool ReloadIfChangedLocked();
|
||||
|
||||
// set_state
|
||||
// Sets the state of the template. Used during BuildTree().
|
||||
void set_state(TemplateState new_state);
|
||||
|
|
|
@ -67,28 +67,32 @@ class TemplateFromString : public Template {
|
|||
/* GetTemplate
|
||||
Parameters:
|
||||
(NOTE: The parameter list is not the same as Template::GetTemplate.)
|
||||
template_name - a logical name for the template text
|
||||
cache_key - the cache string used for the template text.
|
||||
template_text - the text of the template containing the template
|
||||
code with markers, the very same language that
|
||||
would be stored in a file for the parent class
|
||||
strip - same as the parent class
|
||||
Description:
|
||||
Attempts to find an instance of the class with the given template_name
|
||||
Attempts to find an instance of the class with the given cache_key
|
||||
stored in the cache. If it finds one, it returns it, ignoring the
|
||||
template_text passed to the method.
|
||||
If it does not find one, it creates a new instance of the class,
|
||||
stores it in the cache under the template_name, and returns it.
|
||||
Note: since cache lookup is by name, you can't have two instances
|
||||
with the same name but different text, and expect it to work.
|
||||
Note: since cache lookup is by key, you can't have two instances
|
||||
with the same key but different text, and expect it to work.
|
||||
However, if cache_key is the empty string, we ignore the cache,
|
||||
and always create a new instance of the class (without storing it
|
||||
in the cache). In this case *only*, you're responsible for
|
||||
deleting the returned TemplateFromString object when done with it.
|
||||
*/
|
||||
static TemplateFromString *GetTemplate(const std::string& template_name,
|
||||
static TemplateFromString *GetTemplate(const std::string& cache_key,
|
||||
const std::string& template_text,
|
||||
Strip strip);
|
||||
|
||||
private:
|
||||
/* This templates constuctor is private just like the parent's is.
|
||||
New ones are acquired through TemplateFromString::GetTemplate */
|
||||
TemplateFromString(const std::string& template_name,
|
||||
TemplateFromString(const std::string& cache_key,
|
||||
const std::string& template_text,
|
||||
Strip strip);
|
||||
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
|
165
src/template.cc
165
src/template.cc
|
@ -40,7 +40,9 @@
|
|||
#include <time.h>
|
||||
#include <ctype.h> // for isspace()
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> // for stat() and open() and getcwd()
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <iostream> // for logging
|
||||
#include <iomanip> // for indenting in Dump()
|
||||
|
@ -78,6 +80,9 @@ namespace {
|
|||
// Mutexes protecting the globals below. First protects g_use_current_dict
|
||||
// and template_root_directory_, second protects g_template_cache.
|
||||
// Third protects vars_seen in WriteOneHeaderEntry, below.
|
||||
// Lock priority invariant: you should never acquire a Template::mutex_
|
||||
// while holding one of these mutexes.
|
||||
// TODO(csilvers): assert this in the codebase.
|
||||
static Mutex g_static_mutex;
|
||||
static Mutex g_cache_mutex;
|
||||
static Mutex g_header_mutex;
|
||||
|
@ -267,24 +272,28 @@ struct TemplateToken {
|
|||
static void EmitModifiedString(const ModifierAndNonces& modifiers,
|
||||
const char* in, int inlen,
|
||||
ExpandEmitter* outbuf) {
|
||||
// If there's more than one modifiers, we need to store the
|
||||
// intermediate results in a temp-buffer. We use a string.
|
||||
string scratch;
|
||||
string result;
|
||||
if (modifiers.size() > 1) {
|
||||
// We'll assume that each modifier adds about 12% to the input size. We
|
||||
// should exponentiate by |modifiers| but we just multiply, to save time.
|
||||
scratch.reserve((inlen + inlen/8) * (modifiers.size()-1) + 16);
|
||||
StringEmitter scratchbuf(&scratch);
|
||||
// Each time through, we append the latest version of the string to
|
||||
// scratch, and keep a pointer pointing to the most recent version.
|
||||
// Except for (rare!) vars with 3+ modifiers, this loop at most once.
|
||||
for (ModifierAndNonces::const_iterator it = modifiers.begin();
|
||||
// If there's more than one modifiers, we need to store the
|
||||
// intermediate results in a temp-buffer. We use a string.
|
||||
// We'll assume that each modifier adds about 12% to the input
|
||||
// size.
|
||||
result.reserve((inlen + inlen/8) + 16);
|
||||
StringEmitter scratchbuf(&result);
|
||||
modifiers.front().first->Modify(in, inlen, &scratchbuf,
|
||||
modifiers.front().second);
|
||||
// Only used when modifiers.size() > 2
|
||||
for (ModifierAndNonces::const_iterator it = modifiers.begin()+1;
|
||||
it != modifiers.end()-1; ++it) {
|
||||
const int startpos = scratch.size(); // where we start appendend
|
||||
it->first->Modify(in, inlen, &scratchbuf, it->second);
|
||||
in = scratch.data() + startpos; // point to the new "in"
|
||||
inlen = scratch.size() - startpos;
|
||||
string output_of_this_modifier;
|
||||
output_of_this_modifier.reserve(result.size() + result.size()/8 + 16);
|
||||
StringEmitter scratchbuf2(&output_of_this_modifier);
|
||||
it->first->Modify(result.c_str(), result.size(),
|
||||
&scratchbuf2, it->second);
|
||||
result.swap(output_of_this_modifier);
|
||||
}
|
||||
in = result.data();
|
||||
inlen = result.size();
|
||||
}
|
||||
// For the last modifier, we can write directly into outbuf
|
||||
assert(!modifiers.empty());
|
||||
|
@ -626,6 +635,8 @@ class SectionTemplateNode : public TemplateNode {
|
|||
// section, or template to the list of nodes contained in this
|
||||
// section. Returns true iff we really added a node and didn't just
|
||||
// end a section or hit a syntax error in the template file.
|
||||
// You should hold a write-lock on my_template->mutex_ when calling this.
|
||||
// (unless you're calling it from a constructor).
|
||||
bool AddSubnode(Template *my_template);
|
||||
|
||||
// Expands a section node as follows:
|
||||
|
@ -932,6 +943,8 @@ string *Template::template_root_directory_ = NULL;
|
|||
// inappropriate characters in a name, not finding the closing curly
|
||||
// braces, etc.) an error message is logged, the error state of the
|
||||
// template is set, and a NULL token is returned. Updates parse_state_.
|
||||
// You should hold a write-lock on my_template->mutex_ when calling this
|
||||
// (unless you're calling it from a constructor).
|
||||
TemplateToken SectionTemplateNode::GetNextToken(Template *my_template) {
|
||||
Template::ParseState* ps = &my_template->parse_state_; // short abbrev.
|
||||
const char* token_start = ps->bufstart;
|
||||
|
@ -1120,9 +1133,11 @@ TemplateToken SectionTemplateNode::GetNextToken(Template *my_template) {
|
|||
// Template::~Template()
|
||||
// Template::AssureGlobalsInitialized()
|
||||
// Template::GetTemplate()
|
||||
// Calls ReloadIfChanged to load the template the first time.
|
||||
// The constructor is private; GetTemplate() is the factory
|
||||
// method used to actually construct a new template if needed.
|
||||
// Calls ReloadIfChanged to load the template the first time. The
|
||||
// constructor is private; GetTemplate() is the factory method
|
||||
// used to actually construct a new template if needed -- it's the
|
||||
// only thing that calls the template constructor -- and where we
|
||||
// actually call ReloadIfChanged() (based on state_ == TS_EMPTY).
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Template::Template(const string& filename, Strip strip)
|
||||
|
@ -1134,10 +1149,7 @@ Template::Template(const string& filename, Strip strip)
|
|||
// of calling Expand() or other Template classes that access globals.
|
||||
AssureGlobalsInitialized();
|
||||
|
||||
// phase_ indicates what type of thing we expect next during tokenization.
|
||||
// We start off expecting text, hence the initial value is GETTING_TEXT
|
||||
|
||||
VLOG(2) << endl << "Constructing Template for " << template_file() << endl;
|
||||
VLOG(2) << "Constructing Template for " << template_file();
|
||||
|
||||
// Preserve whitespace in Javascript files because carriage returns
|
||||
// can convey meaning for comment termination and closures
|
||||
|
@ -1145,8 +1157,6 @@ Template::Template(const string& filename, Strip strip)
|
|||
!strcmp(filename.c_str() + filename.length() - 3, ".js") ) {
|
||||
strip = STRIP_BLANK_LINES;
|
||||
}
|
||||
|
||||
ReloadIfChanged();
|
||||
}
|
||||
|
||||
Template::~Template() {
|
||||
|
@ -1173,26 +1183,33 @@ Template *Template::GetTemplate(const string& filename, Strip strip) {
|
|||
// No need to have the cache-mutex acquired for this step
|
||||
string abspath(PathJoin(template_root_directory(), filename));
|
||||
|
||||
MutexLock ml(&g_cache_mutex);
|
||||
if (g_template_cache == NULL)
|
||||
g_template_cache = new TemplateCache;
|
||||
Template* tpl = NULL;
|
||||
{
|
||||
MutexLock ml(&g_cache_mutex);
|
||||
if (g_template_cache == NULL)
|
||||
g_template_cache = new TemplateCache;
|
||||
|
||||
Template *tpl = (*g_template_cache)[pair<string, Strip>(abspath, strip)];
|
||||
if (tpl) {
|
||||
// Note: if the status is TS_ERROR here, we don't attempt
|
||||
// to reload the template file, but we don't return
|
||||
// the template object either
|
||||
if (tpl->state() == TS_RELOAD) {
|
||||
tpl->ReloadIfChanged();
|
||||
tpl = (*g_template_cache)[pair<string, Strip>(abspath, strip)];
|
||||
if (!tpl) {
|
||||
tpl = new Template(abspath, strip);
|
||||
(*g_template_cache)[pair<string, Strip>(abspath, strip)] = tpl;
|
||||
}
|
||||
} else {
|
||||
tpl = new Template(abspath, strip);
|
||||
(*g_template_cache)[pair<string, Strip>(abspath, strip)] = tpl;
|
||||
}
|
||||
|
||||
// if the statis is not TS_READY, then it is TS_ERROR at this
|
||||
// point. If it is TS_ERROR, we leave the state as is, but return
|
||||
// NULL. We won't try to load the template file again until the
|
||||
// Even though we only read state() here, not write it, we acquire
|
||||
// the lock in write-mode in case we have to call ReloadIfChanged.
|
||||
WriterMutexLock ml(tpl->mutex_);
|
||||
|
||||
// Note: if the status is TS_ERROR here, we don't attempt to reload
|
||||
// the template file, but we don't return the template object
|
||||
// either. If the state is TS_EMPTY, it means tpl was just constructed
|
||||
// and doesn't have *any* content yet, so we should certainly reload.
|
||||
if (tpl->state() == TS_RELOAD || tpl->state() == TS_EMPTY) {
|
||||
tpl->ReloadIfChangedLocked();
|
||||
}
|
||||
|
||||
// If the state is TS_ERROR, we leave the state as is, but return
|
||||
// NULL. We won't try to load the template file again until the
|
||||
// state gets changed to TS_RELOAD by another call to
|
||||
// ReloadAllIfChanged.
|
||||
if (tpl->state() != TS_READY) {
|
||||
|
@ -1214,6 +1231,8 @@ Template *Template::GetTemplate(const string& filename, Strip strip) {
|
|||
|
||||
// NOTE: BuildTree takes over ownership of input_buffer, and will delete it.
|
||||
// It should have been created via new[].
|
||||
// You should hold a write-lock on mutex_ before calling this
|
||||
// (unless you're calling it from a constructor).
|
||||
bool Template::BuildTree(const char* input_buffer,
|
||||
const char* input_buffer_end) {
|
||||
// Assign an arbitrary name to the top-level node
|
||||
|
@ -1331,6 +1350,7 @@ const char *Template::template_file() const {
|
|||
|
||||
// ----------------------------------------------------------------------
|
||||
// Template::ReloadIfChanged()
|
||||
// Template::ReloadIfChangedLocked()
|
||||
// Template::ReloadAllIfChanged()
|
||||
// If one template, try immediately to reload it from disk. If
|
||||
// all templates, just set all their statuses to TS_RELOAD, so
|
||||
|
@ -1341,15 +1361,9 @@ const char *Template::template_file() const {
|
|||
// and parsed it. It never returns true if filename_ is "".
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Template::ReloadIfChanged() {
|
||||
bool Template::ReloadIfChangedLocked() {
|
||||
if (filename_.empty()) return false;
|
||||
|
||||
// This entire routine is protected by mutex_ so when it's called
|
||||
// from different threads, they don't stomp on tree_ and state_.
|
||||
// This is still not perfect, since set_filename() could stomp
|
||||
// on filename_ while we're reading it, but it's good enough.
|
||||
WriterMutexLock ml(mutex_);
|
||||
|
||||
struct stat statbuf;
|
||||
if (stat(filename_.c_str(), &statbuf) != 0) {
|
||||
LOG(WARNING) << "Unable to stat file " << filename_ << endl;
|
||||
|
@ -1403,35 +1417,62 @@ bool Template::ReloadIfChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Template::ReloadIfChanged() {
|
||||
// ReloadIfChanged() is protected by mutex_ so when it's called from
|
||||
// different threads, they don't stomp on tree_ and state_.
|
||||
WriterMutexLock ml(mutex_);
|
||||
return ReloadIfChangedLocked();
|
||||
}
|
||||
|
||||
void Template::ReloadAllIfChanged() {
|
||||
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||
if (g_template_cache == NULL) {
|
||||
return;
|
||||
// This is slightly annoying: we copy all the template-pointers to
|
||||
// a vector, so we don't have to hold g_cache_mutex while messing
|
||||
// with the templates (which would violate our lock invariant).
|
||||
vector<Template*> templates_in_cache;
|
||||
{
|
||||
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||
if (g_template_cache == NULL) {
|
||||
return;
|
||||
}
|
||||
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
||||
iter != g_template_cache->end();
|
||||
++iter) {
|
||||
templates_in_cache.push_back(iter->second);
|
||||
}
|
||||
}
|
||||
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
||||
iter != g_template_cache->end();
|
||||
for (vector<Template*>::iterator iter = templates_in_cache.begin();
|
||||
iter != templates_in_cache.end();
|
||||
++iter) {
|
||||
(*iter).second->set_state(TS_RELOAD);
|
||||
WriterMutexLock ml((*iter)->mutex_);
|
||||
(*iter)->set_state(TS_RELOAD);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Template::ClearCache()
|
||||
// Deletes all the objects in the template cache
|
||||
// Deletes all the objects in the template cache. Note: it's
|
||||
// dangerous to clear the cache if other threads are still
|
||||
// referencing the templates that are stored in it!
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Template::ClearCache() {
|
||||
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||
if (g_template_cache == NULL) {
|
||||
return;
|
||||
// We clear the cache by swapping it with an empty cache. This lets
|
||||
// us delete the items in the cache at our leisure without needing
|
||||
// to hold g_cache_mutex.
|
||||
TemplateCache tmp_cache;
|
||||
{
|
||||
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||
if (g_template_cache == NULL) {
|
||||
return;
|
||||
}
|
||||
g_template_cache->swap(tmp_cache); // now g_template_cache is empty
|
||||
}
|
||||
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
||||
iter != g_template_cache->end();
|
||||
// Now delete everything we've removed from the cache.
|
||||
for (TemplateCache::const_iterator iter = tmp_cache.begin();
|
||||
iter != tmp_cache.end();
|
||||
++iter) {
|
||||
delete (*iter).second;
|
||||
delete iter->second;
|
||||
}
|
||||
delete g_template_cache;
|
||||
g_template_cache = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
|
||||
_START_GOOGLE_NAMESPACE_
|
||||
|
||||
// Lock priority invariant: you should never acquire a
|
||||
// TemplateFromString::mutex_ while holding this mutex.
|
||||
// TODO(csilvers): assert this in the codebase.
|
||||
static Mutex g_cache_mutex;
|
||||
|
||||
using std::string;
|
||||
|
@ -53,11 +56,11 @@ using HASH_NAMESPACE::hash_map;
|
|||
// the template text is taken from the second parameter. After that, the
|
||||
// object is identical to a Template object, except that it cannot be
|
||||
// "reloaded."
|
||||
TemplateFromString::TemplateFromString(const string& template_name,
|
||||
TemplateFromString::TemplateFromString(const string& cache_key,
|
||||
const string& template_text,
|
||||
Strip strip)
|
||||
: Template("", strip) {
|
||||
filename_ = template_name; // for cache and reporting purposes only
|
||||
filename_ = cache_key; // for cache and reporting purposes only
|
||||
|
||||
// We know that InsertFile never writes more output than it gets input.
|
||||
// While we allocate buffer here, BuildTree takes ownership and deletes it.
|
||||
|
@ -94,27 +97,30 @@ static TemplateFromStringCache *g_template_from_string_cache = NULL;
|
|||
|
||||
// TemplateFromString::GetTemplate
|
||||
// Makes sure the template cache has been created and then tries to
|
||||
// retrieve a TemplateFromString object from it via the template_name.
|
||||
TemplateFromString *TemplateFromString::GetTemplate(const string& template_name,
|
||||
// retrieve a TemplateFromString object from it via the cache_key.
|
||||
TemplateFromString *TemplateFromString::GetTemplate(const string& cache_key,
|
||||
const string& template_text,
|
||||
Strip strip) {
|
||||
// Only perform this method when you have the lock so multiple threads
|
||||
// don't conflict over inserting and retrieving into the cache
|
||||
MutexLock ml(&g_cache_mutex);
|
||||
if (g_template_from_string_cache == NULL) {
|
||||
g_template_from_string_cache = new TemplateFromStringCache;
|
||||
TemplateFromString *tpl = NULL;
|
||||
if (cache_key.empty()) { // user doesn't want to use the cache
|
||||
tpl = new TemplateFromString(cache_key, template_text, strip);
|
||||
} else {
|
||||
MutexLock ml(&g_cache_mutex);
|
||||
if (g_template_from_string_cache == NULL) {
|
||||
g_template_from_string_cache = new TemplateFromStringCache;
|
||||
}
|
||||
// If the object isn't really a TemplateFromString this will be a cache miss
|
||||
tpl = (*g_template_from_string_cache)[pair<string,Strip>(cache_key, strip)];
|
||||
|
||||
// If we didn't find one, then create one and store it in the cache
|
||||
if (!tpl) {
|
||||
tpl = new TemplateFromString(cache_key, template_text, strip);
|
||||
(*g_template_from_string_cache)[pair<string, Strip>(cache_key, strip)] =
|
||||
tpl;
|
||||
}
|
||||
}
|
||||
|
||||
// If the object isn't really a TemplateFromString, this will be a cache miss
|
||||
TemplateFromString *tpl =
|
||||
(*g_template_from_string_cache)[pair<string, Strip>(template_name, strip)];
|
||||
|
||||
// If we didn't find one, then create one and store it in the cache
|
||||
if (!tpl) {
|
||||
tpl = new TemplateFromString(template_name, template_text, strip);
|
||||
(*g_template_from_string_cache)[pair<string, Strip>(template_name, strip)] =
|
||||
tpl;
|
||||
}
|
||||
WriterMutexLock ml(tpl->mutex_); // to access state()
|
||||
|
||||
// state_ can be TS_RELOAD if ReloadAllIfChanged() touched this file.
|
||||
// That's fine; we'll just ignore the reload directive for this guy.
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> // for access()
|
||||
#endif
|
||||
#include <time.h> // for time_t
|
||||
#include <sys/stat.h> // for stat()
|
||||
#include <string>
|
||||
|
|
|
@ -39,13 +39,17 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm> // for sort
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h> // for readdir
|
||||
#endif
|
||||
#include <google/template_from_string.h>
|
||||
#include <google/template_dictionary.h>
|
||||
|
||||
|
@ -133,6 +137,8 @@ class TemplateFromStringUnittest {
|
|||
}
|
||||
|
||||
static void TestGetTemplate() {
|
||||
TemplateDictionary dict("dict");
|
||||
|
||||
// Tests the cache
|
||||
const char* const tpltext = "{This is perfectly valid} yay!";
|
||||
const char* const tpltext2 = "This will be ignored";
|
||||
|
@ -148,6 +154,22 @@ class TemplateFromStringUnittest {
|
|||
ASSERT(tpl1 == tpl2);
|
||||
ASSERT(tpl3 == tpl4);
|
||||
ASSERT(tpl1 != tpl3);
|
||||
AssertExpandIs(tpl1, &dict, tpltext);
|
||||
AssertExpandIs(tpl2, &dict, tpltext);
|
||||
AssertExpandIs(tpl3, &dict, tpltext);
|
||||
AssertExpandIs(tpl4, &dict, tpltext);
|
||||
|
||||
// Tests our mechanism for ignoring the cache (first arg is empty-string)
|
||||
Template* tpl1b = TemplateFromString::GetTemplate(
|
||||
"", tpltext, DO_NOT_STRIP);
|
||||
Template* tpl2b = TemplateFromString::GetTemplate(
|
||||
"", tpltext2, DO_NOT_STRIP);
|
||||
ASSERT(tpl1b != tpl2b);
|
||||
AssertExpandIs(tpl1b, &dict, tpltext);
|
||||
AssertExpandIs(tpl2b, &dict, tpltext2);
|
||||
// When you don't cache the template, you have to delete it!
|
||||
delete tpl1b;
|
||||
delete tpl2b;
|
||||
|
||||
// Tests that syntax errors cause us to return NULL
|
||||
Template* tpl5 = StringToTemplate("{{This has spaces in it}}", DO_NOT_STRIP);
|
||||
|
|
|
@ -289,6 +289,24 @@ class TemplateUnittest {
|
|||
// Check we don't allow modifiers on sections
|
||||
tpl = StringToTemplate("hi {{#VAR:h}} lo {{/VAR}}", STRIP_WHITESPACE);
|
||||
ASSERT(tpl == NULL);
|
||||
|
||||
// Test when expanded grows by more than 12% per modifier.
|
||||
dict.SetValue("VAR", "http://a.com?b=c&d=e&f=g&q=a>b");
|
||||
tpl = StringToTemplate("{{VAR:u:j:h}}",
|
||||
STRIP_WHITESPACE);
|
||||
AssertExpandIs(tpl, &dict,
|
||||
"http%3A//a.com%3Fb%3Dc%26d%3De%26f%3Dg%26q%3Da%3Eb",
|
||||
true);
|
||||
|
||||
// As above with 4 modifiers.
|
||||
dict.SetValue("VAR", "http://a.com?b=c&d=e&f=g&q=a>b");
|
||||
tpl = StringToTemplate("{{VAR:u:j:h:h}}",
|
||||
STRIP_WHITESPACE);
|
||||
AssertExpandIs(tpl, &dict,
|
||||
"http%3A//a.com%3Fb%3Dc%26d%3De%26f%3Dg%26q%3Da%3Eb",
|
||||
true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void TestSection() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user