mirror of
https://github.com/OlafvdSpek/ctemplate.git
synced 2025-10-12 20:19:04 +08:00
Mon May 14 17:27:10 2007 Google Inc. <opensource@google.com>
* ctemplate: version 0.5 release * Add new MakeCopy() method to copy template dictionaries (csilvers) * Add JSON-escaping (mikepurvis) * Internal change that should ease thread-handling a bit (csilvers) * Fix url_query_escape to avoid stack overflow (csilvers)
This commit is contained in:
parent
73dd30e487
commit
422d6f7443
|
@ -33,3 +33,11 @@ Mon Jan 15 14:10:42 2007 Google Inc. <opensource@google.com>
|
||||||
* Add support for "pre" escaping, which preserves whitespace (dboswell)
|
* Add support for "pre" escaping, which preserves whitespace (dboswell)
|
||||||
* Typo fixes in documentation (csilvers)
|
* Typo fixes in documentation (csilvers)
|
||||||
* Expand() returns false if a template file failed to load (jmittleman)
|
* Expand() returns false if a template file failed to load (jmittleman)
|
||||||
|
|
||||||
|
Mon May 14 17:27:10 2007 Google Inc. <opensource@google.com>
|
||||||
|
|
||||||
|
* ctemplate: version 0.5 release
|
||||||
|
* Add new MakeCopy() method to copy template dictionaries (csilvers)
|
||||||
|
* Add JSON-escaping (mikepurvis)
|
||||||
|
* Internal change that should ease thread-handling a bit (csilvers)
|
||||||
|
* Fix url_query_escape to avoid stack overflow (csilvers)
|
||||||
|
|
|
@ -62,13 +62,16 @@ noinst_SCRIPTS = src/tests/make_tpl_varnames_h_unittest.sh
|
||||||
|
|
||||||
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
|
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
|
||||||
|
|
||||||
|
# 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]'
|
||||||
|
|
||||||
lib_LTLIBRARIES += libctemplate.la
|
lib_LTLIBRARIES += libctemplate.la
|
||||||
libctemplate_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
|
libctemplate_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
|
||||||
src/base/arena.h src/base/arena.cc \
|
src/base/arena.h src/base/arena.cc src/base/mutex.h src/base/mutex.cc \
|
||||||
src/template.cc src/template_dictionary.cc src/template_namelist.cc \
|
src/template.cc src/template_dictionary.cc src/template_namelist.cc \
|
||||||
src/template_from_string.cc
|
src/template_from_string.cc
|
||||||
libctemplate_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
|
libctemplate_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
|
||||||
libctemplate_la_LDFLAGS = $(PTHREAD_CFLAGS)
|
libctemplate_la_LDFLAGS = $(PTHREAD_CFLAGS) -export-symbols-regex $(CTEMPLATE_SYMBOLS)
|
||||||
libctemplate_la_LIBADD = $(PTHREAD_LIBS)
|
libctemplate_la_LIBADD = $(PTHREAD_LIBS)
|
||||||
|
|
||||||
# automake will make different .o files for this library, which is good,
|
# automake will make different .o files for this library, which is good,
|
||||||
|
@ -76,6 +79,7 @@ libctemplate_la_LIBADD = $(PTHREAD_LIBS)
|
||||||
lib_LTLIBRARIES += libctemplate_nothreads.la
|
lib_LTLIBRARIES += libctemplate_nothreads.la
|
||||||
libctemplate_nothreads_la_SOURCES = $(libctemplate_la_SOURCES)
|
libctemplate_nothreads_la_SOURCES = $(libctemplate_la_SOURCES)
|
||||||
libctemplate_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS
|
libctemplate_nothreads_la_CXXFLAGS = -DNDEBUG -DNO_THREADS
|
||||||
|
libctemplate_nothreads_la_LDFLAGS = -export-symbols-regex $(CTEMPLATE_SYMBOLS)
|
||||||
|
|
||||||
# Helper apps
|
# Helper apps
|
||||||
bin_PROGRAMS += make_tpl_varnames_h
|
bin_PROGRAMS += make_tpl_varnames_h
|
||||||
|
|
1431
trunk/Makefile.in
1431
trunk/Makefile.in
File diff suppressed because it is too large
Load Diff
8000
trunk/aclocal.m4
vendored
8000
trunk/aclocal.m4
vendored
File diff suppressed because it is too large
Load Diff
947
trunk/config.guess
vendored
947
trunk/config.guess
vendored
File diff suppressed because it is too large
Load Diff
189
trunk/config.sub
vendored
189
trunk/config.sub
vendored
|
@ -1,9 +1,9 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2003-06-18'
|
timestamp='2005-07-08'
|
||||||
|
|
||||||
# This file is (in principle) common to ALL GNU software.
|
# This file is (in principle) common to ALL GNU software.
|
||||||
# The presence of a machine in this file suggests that SOME GNU software
|
# The presence of a machine in this file suggests that SOME GNU software
|
||||||
|
@ -21,14 +21,15 @@ timestamp='2003-06-18'
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
# Boston, MA 02111-1307, USA.
|
# 02110-1301, USA.
|
||||||
|
#
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
# configuration script generated by Autoconf, you may include it under
|
# configuration script generated by Autoconf, you may include it under
|
||||||
# the same distribution terms that you use for the rest of that program.
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
|
||||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||||
# diff and a properly formatted ChangeLog entry.
|
# diff and a properly formatted ChangeLog entry.
|
||||||
#
|
#
|
||||||
|
@ -70,7 +71,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||||
version="\
|
version="\
|
||||||
GNU config.sub ($timestamp)
|
GNU config.sub ($timestamp)
|
||||||
|
|
||||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
|
@ -83,11 +84,11 @@ Try \`$me --help' for more information."
|
||||||
while test $# -gt 0 ; do
|
while test $# -gt 0 ; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--time-stamp | --time* | -t )
|
--time-stamp | --time* | -t )
|
||||||
echo "$timestamp" ; exit 0 ;;
|
echo "$timestamp" ; exit ;;
|
||||||
--version | -v )
|
--version | -v )
|
||||||
echo "$version" ; exit 0 ;;
|
echo "$version" ; exit ;;
|
||||||
--help | --h* | -h )
|
--help | --h* | -h )
|
||||||
echo "$usage"; exit 0 ;;
|
echo "$usage"; exit ;;
|
||||||
-- ) # Stop option processing
|
-- ) # Stop option processing
|
||||||
shift; break ;;
|
shift; break ;;
|
||||||
- ) # Use stdin as input.
|
- ) # Use stdin as input.
|
||||||
|
@ -99,7 +100,7 @@ while test $# -gt 0 ; do
|
||||||
*local*)
|
*local*)
|
||||||
# First pass through any local machine types.
|
# First pass through any local machine types.
|
||||||
echo $1
|
echo $1
|
||||||
exit 0;;
|
exit ;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
break ;;
|
break ;;
|
||||||
|
@ -118,7 +119,8 @@ esac
|
||||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||||
case $maybe_os in
|
case $maybe_os in
|
||||||
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
|
||||||
|
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||||
os=-$maybe_os
|
os=-$maybe_os
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||||
;;
|
;;
|
||||||
|
@ -144,7 +146,7 @@ case $os in
|
||||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||||
-apple | -axis)
|
-apple | -axis | -knuth | -cray)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
|
@ -228,14 +230,16 @@ case $basic_machine in
|
||||||
| a29k \
|
| a29k \
|
||||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||||
|
| am33_2.0 \
|
||||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||||
|
| bfin \
|
||||||
| c4x | clipper \
|
| c4x | clipper \
|
||||||
| d10v | d30v | dlx | dsp16xx \
|
| d10v | d30v | dlx | dsp16xx \
|
||||||
| fr30 | frv \
|
| fr30 | frv \
|
||||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||||
| i370 | i860 | i960 | ia64 \
|
| i370 | i860 | i960 | ia64 \
|
||||||
| ip2k \
|
| ip2k | iq2000 \
|
||||||
| m32r | m68000 | m68k | m88k | mcore \
|
| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
|
||||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||||
| mips16 \
|
| mips16 \
|
||||||
| mips64 | mips64el \
|
| mips64 | mips64el \
|
||||||
|
@ -244,31 +248,37 @@ case $basic_machine in
|
||||||
| mips64vr4100 | mips64vr4100el \
|
| mips64vr4100 | mips64vr4100el \
|
||||||
| mips64vr4300 | mips64vr4300el \
|
| mips64vr4300 | mips64vr4300el \
|
||||||
| mips64vr5000 | mips64vr5000el \
|
| mips64vr5000 | mips64vr5000el \
|
||||||
|
| mips64vr5900 | mips64vr5900el \
|
||||||
| mipsisa32 | mipsisa32el \
|
| mipsisa32 | mipsisa32el \
|
||||||
| mipsisa32r2 | mipsisa32r2el \
|
| mipsisa32r2 | mipsisa32r2el \
|
||||||
| mipsisa64 | mipsisa64el \
|
| mipsisa64 | mipsisa64el \
|
||||||
|
| mipsisa64r2 | mipsisa64r2el \
|
||||||
| mipsisa64sb1 | mipsisa64sb1el \
|
| mipsisa64sb1 | mipsisa64sb1el \
|
||||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||||
| mipstx39 | mipstx39el \
|
| mipstx39 | mipstx39el \
|
||||||
| mn10200 | mn10300 \
|
| mn10200 | mn10300 \
|
||||||
|
| ms1 \
|
||||||
| msp430 \
|
| msp430 \
|
||||||
| ns16k | ns32k \
|
| ns16k | ns32k \
|
||||||
| openrisc | or32 \
|
| or32 \
|
||||||
| pdp10 | pdp11 | pj | pjl \
|
| pdp10 | pdp11 | pj | pjl \
|
||||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||||
| pyramid \
|
| pyramid \
|
||||||
| s390 | s390x \
|
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
|
||||||
| sh64 | sh64le \
|
| sh64 | sh64le \
|
||||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
|
||||||
|
| sparcv8 | sparcv9 | sparcv9b \
|
||||||
| strongarm \
|
| strongarm \
|
||||||
| tahoe | thumb | tic4x | tic80 | tron \
|
| tahoe | thumb | tic4x | tic80 | tron \
|
||||||
| v850 | v850e \
|
| v850 | v850e \
|
||||||
| we32k \
|
| we32k \
|
||||||
| x86 | xscale | xstormy16 | xtensa \
|
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||||
| z8k)
|
| z8k)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
;;
|
;;
|
||||||
|
m32c)
|
||||||
|
basic_machine=$basic_machine-unknown
|
||||||
|
;;
|
||||||
m6811 | m68hc11 | m6812 | m68hc12)
|
m6811 | m68hc11 | m6812 | m68hc12)
|
||||||
# Motorola 68HC11/12.
|
# Motorola 68HC11/12.
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
|
@ -296,19 +306,19 @@ case $basic_machine in
|
||||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| avr-* \
|
| avr-* \
|
||||||
| bs2000-* \
|
| bfin-* | bs2000-* \
|
||||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||||
| clipper-* | cydra-* \
|
| clipper-* | craynv-* | cydra-* \
|
||||||
| d10v-* | d30v-* | dlx-* \
|
| d10v-* | d30v-* | dlx-* \
|
||||||
| elxsi-* \
|
| elxsi-* \
|
||||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||||
| h8300-* | h8500-* \
|
| h8300-* | h8500-* \
|
||||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||||
| i*86-* | i860-* | i960-* | ia64-* \
|
| i*86-* | i860-* | i960-* | ia64-* \
|
||||||
| ip2k-* \
|
| ip2k-* | iq2000-* \
|
||||||
| m32r-* \
|
| m32r-* | m32rle-* \
|
||||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||||
| m88110-* | m88k-* | mcore-* \
|
| m88110-* | m88k-* | maxq-* | mcore-* \
|
||||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||||
| mips16-* \
|
| mips16-* \
|
||||||
| mips64-* | mips64el-* \
|
| mips64-* | mips64el-* \
|
||||||
|
@ -317,34 +327,40 @@ case $basic_machine in
|
||||||
| mips64vr4100-* | mips64vr4100el-* \
|
| mips64vr4100-* | mips64vr4100el-* \
|
||||||
| mips64vr4300-* | mips64vr4300el-* \
|
| mips64vr4300-* | mips64vr4300el-* \
|
||||||
| mips64vr5000-* | mips64vr5000el-* \
|
| mips64vr5000-* | mips64vr5000el-* \
|
||||||
|
| mips64vr5900-* | mips64vr5900el-* \
|
||||||
| mipsisa32-* | mipsisa32el-* \
|
| mipsisa32-* | mipsisa32el-* \
|
||||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||||
| mipsisa64-* | mipsisa64el-* \
|
| mipsisa64-* | mipsisa64el-* \
|
||||||
|
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||||
| mipstx39-* | mipstx39el-* \
|
| mipstx39-* | mipstx39el-* \
|
||||||
|
| mmix-* \
|
||||||
|
| ms1-* \
|
||||||
| msp430-* \
|
| msp430-* \
|
||||||
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||||
| orion-* \
|
| orion-* \
|
||||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||||
| pyramid-* \
|
| pyramid-* \
|
||||||
| romp-* | rs6000-* \
|
| romp-* | rs6000-* \
|
||||||
| s390-* | s390x-* \
|
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
|
||||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
|
||||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
| sparclite-* \
|
||||||
|
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||||
| tahoe-* | thumb-* \
|
| tahoe-* | thumb-* \
|
||||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||||
| tron-* \
|
| tron-* \
|
||||||
| v850-* | v850e-* | vax-* \
|
| v850-* | v850e-* | vax-* \
|
||||||
| we32k-* \
|
| we32k-* \
|
||||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||||
| xtensa-* \
|
| xstormy16-* | xtensa-* \
|
||||||
| ymp-* \
|
| ymp-* \
|
||||||
| z8k-*)
|
| z8k-*)
|
||||||
;;
|
;;
|
||||||
|
m32c-*)
|
||||||
|
;;
|
||||||
# Recognize the various machine names and aliases which stand
|
# Recognize the various machine names and aliases which stand
|
||||||
# for a CPU type and a company and sometimes even an OS.
|
# for a CPU type and a company and sometimes even an OS.
|
||||||
386bsd)
|
386bsd)
|
||||||
|
@ -361,6 +377,9 @@ case $basic_machine in
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
;;
|
;;
|
||||||
|
abacus)
|
||||||
|
basic_machine=abacus-unknown
|
||||||
|
;;
|
||||||
adobe68k)
|
adobe68k)
|
||||||
basic_machine=m68010-adobe
|
basic_machine=m68010-adobe
|
||||||
os=-scout
|
os=-scout
|
||||||
|
@ -378,6 +397,9 @@ case $basic_machine in
|
||||||
amd64)
|
amd64)
|
||||||
basic_machine=x86_64-pc
|
basic_machine=x86_64-pc
|
||||||
;;
|
;;
|
||||||
|
amd64-*)
|
||||||
|
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
amdahl)
|
amdahl)
|
||||||
basic_machine=580-amdahl
|
basic_machine=580-amdahl
|
||||||
os=-sysv
|
os=-sysv
|
||||||
|
@ -437,12 +459,27 @@ case $basic_machine in
|
||||||
basic_machine=j90-cray
|
basic_machine=j90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
craynv)
|
||||||
|
basic_machine=craynv-cray
|
||||||
|
os=-unicosmp
|
||||||
|
;;
|
||||||
|
cr16c)
|
||||||
|
basic_machine=cr16c-unknown
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
crds | unos)
|
crds | unos)
|
||||||
basic_machine=m68k-crds
|
basic_machine=m68k-crds
|
||||||
;;
|
;;
|
||||||
|
crisv32 | crisv32-* | etraxfs*)
|
||||||
|
basic_machine=crisv32-axis
|
||||||
|
;;
|
||||||
cris | cris-* | etrax*)
|
cris | cris-* | etrax*)
|
||||||
basic_machine=cris-axis
|
basic_machine=cris-axis
|
||||||
;;
|
;;
|
||||||
|
crx)
|
||||||
|
basic_machine=crx-unknown
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
da30 | da30-*)
|
da30 | da30-*)
|
||||||
basic_machine=m68k-da30
|
basic_machine=m68k-da30
|
||||||
;;
|
;;
|
||||||
|
@ -465,6 +502,10 @@ case $basic_machine in
|
||||||
basic_machine=m88k-motorola
|
basic_machine=m88k-motorola
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
|
djgpp)
|
||||||
|
basic_machine=i586-pc
|
||||||
|
os=-msdosdjgpp
|
||||||
|
;;
|
||||||
dpx20 | dpx20-*)
|
dpx20 | dpx20-*)
|
||||||
basic_machine=rs6000-bull
|
basic_machine=rs6000-bull
|
||||||
os=-bosx
|
os=-bosx
|
||||||
|
@ -643,10 +684,6 @@ case $basic_machine in
|
||||||
mips3*)
|
mips3*)
|
||||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||||
;;
|
;;
|
||||||
mmix*)
|
|
||||||
basic_machine=mmix-knuth
|
|
||||||
os=-mmixware
|
|
||||||
;;
|
|
||||||
monitor)
|
monitor)
|
||||||
basic_machine=m68k-rom68k
|
basic_machine=m68k-rom68k
|
||||||
os=-coff
|
os=-coff
|
||||||
|
@ -727,10 +764,6 @@ case $basic_machine in
|
||||||
np1)
|
np1)
|
||||||
basic_machine=np1-gould
|
basic_machine=np1-gould
|
||||||
;;
|
;;
|
||||||
nv1)
|
|
||||||
basic_machine=nv1-cray
|
|
||||||
os=-unicosmp
|
|
||||||
;;
|
|
||||||
nsr-tandem)
|
nsr-tandem)
|
||||||
basic_machine=nsr-tandem
|
basic_machine=nsr-tandem
|
||||||
;;
|
;;
|
||||||
|
@ -738,9 +771,12 @@ case $basic_machine in
|
||||||
basic_machine=hppa1.1-oki
|
basic_machine=hppa1.1-oki
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
or32 | or32-*)
|
openrisc | openrisc-*)
|
||||||
basic_machine=or32-unknown
|
basic_machine=or32-unknown
|
||||||
os=-coff
|
;;
|
||||||
|
os400)
|
||||||
|
basic_machine=powerpc-ibm
|
||||||
|
os=-os400
|
||||||
;;
|
;;
|
||||||
OSE68000 | ose68000)
|
OSE68000 | ose68000)
|
||||||
basic_machine=m68000-ericsson
|
basic_machine=m68000-ericsson
|
||||||
|
@ -833,6 +869,12 @@ case $basic_machine in
|
||||||
rtpc | rtpc-*)
|
rtpc | rtpc-*)
|
||||||
basic_machine=romp-ibm
|
basic_machine=romp-ibm
|
||||||
;;
|
;;
|
||||||
|
s390 | s390-*)
|
||||||
|
basic_machine=s390-ibm
|
||||||
|
;;
|
||||||
|
s390x | s390x-*)
|
||||||
|
basic_machine=s390x-ibm
|
||||||
|
;;
|
||||||
sa29200)
|
sa29200)
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
|
@ -956,6 +998,10 @@ case $basic_machine in
|
||||||
tower | tower-32)
|
tower | tower-32)
|
||||||
basic_machine=m68k-ncr
|
basic_machine=m68k-ncr
|
||||||
;;
|
;;
|
||||||
|
tpf)
|
||||||
|
basic_machine=s390x-ibm
|
||||||
|
os=-tpf
|
||||||
|
;;
|
||||||
udi29k)
|
udi29k)
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
|
@ -999,6 +1045,10 @@ case $basic_machine in
|
||||||
basic_machine=hppa1.1-winbond
|
basic_machine=hppa1.1-winbond
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
|
xbox)
|
||||||
|
basic_machine=i686-pc
|
||||||
|
os=-mingw32
|
||||||
|
;;
|
||||||
xps | xps100)
|
xps | xps100)
|
||||||
basic_machine=xps100-honeywell
|
basic_machine=xps100-honeywell
|
||||||
;;
|
;;
|
||||||
|
@ -1029,6 +1079,9 @@ case $basic_machine in
|
||||||
romp)
|
romp)
|
||||||
basic_machine=romp-ibm
|
basic_machine=romp-ibm
|
||||||
;;
|
;;
|
||||||
|
mmix)
|
||||||
|
basic_machine=mmix-knuth
|
||||||
|
;;
|
||||||
rs6000)
|
rs6000)
|
||||||
basic_machine=rs6000-ibm
|
basic_machine=rs6000-ibm
|
||||||
;;
|
;;
|
||||||
|
@ -1045,13 +1098,10 @@ case $basic_machine in
|
||||||
we32k)
|
we32k)
|
||||||
basic_machine=we32k-att
|
basic_machine=we32k-att
|
||||||
;;
|
;;
|
||||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||||
basic_machine=sh-unknown
|
basic_machine=sh-unknown
|
||||||
;;
|
;;
|
||||||
sh64)
|
sparc | sparcv8 | sparcv9 | sparcv9b)
|
||||||
basic_machine=sh64-unknown
|
|
||||||
;;
|
|
||||||
sparc | sparcv9 | sparcv9b)
|
|
||||||
basic_machine=sparc-sun
|
basic_machine=sparc-sun
|
||||||
;;
|
;;
|
||||||
cydra)
|
cydra)
|
||||||
|
@ -1124,19 +1174,21 @@ case $os in
|
||||||
| -aos* \
|
| -aos* \
|
||||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
|
||||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||||
|
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||||
| -chorusos* | -chorusrdb* \
|
| -chorusos* | -chorusrdb* \
|
||||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
|
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||||
|
| -skyos* | -haiku*)
|
||||||
# Remember, each alternative MUST END IN *, to match a version number.
|
# Remember, each alternative MUST END IN *, to match a version number.
|
||||||
;;
|
;;
|
||||||
-qnx*)
|
-qnx*)
|
||||||
|
@ -1154,12 +1206,15 @@ case $os in
|
||||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||||
;;
|
;;
|
||||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||||
;;
|
;;
|
||||||
-mac*)
|
-mac*)
|
||||||
os=`echo $os | sed -e 's|mac|macos|'`
|
os=`echo $os | sed -e 's|mac|macos|'`
|
||||||
;;
|
;;
|
||||||
|
-linux-dietlibc)
|
||||||
|
os=-linux-dietlibc
|
||||||
|
;;
|
||||||
-linux*)
|
-linux*)
|
||||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||||
;;
|
;;
|
||||||
|
@ -1172,6 +1227,9 @@ case $os in
|
||||||
-opened*)
|
-opened*)
|
||||||
os=-openedition
|
os=-openedition
|
||||||
;;
|
;;
|
||||||
|
-os400*)
|
||||||
|
os=-os400
|
||||||
|
;;
|
||||||
-wince*)
|
-wince*)
|
||||||
os=-wince
|
os=-wince
|
||||||
;;
|
;;
|
||||||
|
@ -1193,6 +1251,9 @@ case $os in
|
||||||
-atheos*)
|
-atheos*)
|
||||||
os=-atheos
|
os=-atheos
|
||||||
;;
|
;;
|
||||||
|
-syllable*)
|
||||||
|
os=-syllable
|
||||||
|
;;
|
||||||
-386bsd)
|
-386bsd)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
|
@ -1215,6 +1276,9 @@ case $os in
|
||||||
-sinix*)
|
-sinix*)
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
|
-tpf*)
|
||||||
|
os=-tpf
|
||||||
|
;;
|
||||||
-triton*)
|
-triton*)
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
|
@ -1251,6 +1315,9 @@ case $os in
|
||||||
-kaos*)
|
-kaos*)
|
||||||
os=-kaos
|
os=-kaos
|
||||||
;;
|
;;
|
||||||
|
-zvmoe)
|
||||||
|
os=-zvmoe
|
||||||
|
;;
|
||||||
-none)
|
-none)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
@ -1282,9 +1349,9 @@ case $basic_machine in
|
||||||
arm*-semi)
|
arm*-semi)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
c4x-* | tic4x-*)
|
c4x-* | tic4x-*)
|
||||||
os=-coff
|
os=-coff
|
||||||
;;
|
;;
|
||||||
# This must come before the *-dec entry.
|
# This must come before the *-dec entry.
|
||||||
pdp10-*)
|
pdp10-*)
|
||||||
os=-tops20
|
os=-tops20
|
||||||
|
@ -1328,9 +1395,15 @@ case $basic_machine in
|
||||||
*-be)
|
*-be)
|
||||||
os=-beos
|
os=-beos
|
||||||
;;
|
;;
|
||||||
|
*-haiku)
|
||||||
|
os=-haiku
|
||||||
|
;;
|
||||||
*-ibm)
|
*-ibm)
|
||||||
os=-aix
|
os=-aix
|
||||||
;;
|
;;
|
||||||
|
*-knuth)
|
||||||
|
os=-mmixware
|
||||||
|
;;
|
||||||
*-wec)
|
*-wec)
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
|
@ -1463,9 +1536,15 @@ case $basic_machine in
|
||||||
-mvs* | -opened*)
|
-mvs* | -opened*)
|
||||||
vendor=ibm
|
vendor=ibm
|
||||||
;;
|
;;
|
||||||
|
-os400*)
|
||||||
|
vendor=ibm
|
||||||
|
;;
|
||||||
-ptx*)
|
-ptx*)
|
||||||
vendor=sequent
|
vendor=sequent
|
||||||
;;
|
;;
|
||||||
|
-tpf*)
|
||||||
|
vendor=ibm
|
||||||
|
;;
|
||||||
-vxsim* | -vxworks* | -windiss*)
|
-vxsim* | -vxworks* | -windiss*)
|
||||||
vendor=wrs
|
vendor=wrs
|
||||||
;;
|
;;
|
||||||
|
@ -1490,7 +1569,7 @@ case $basic_machine in
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo $basic_machine$os
|
echo $basic_machine$os
|
||||||
exit 0
|
exit
|
||||||
|
|
||||||
# Local variables:
|
# Local variables:
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
|
2284
trunk/configure
vendored
2284
trunk/configure
vendored
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,7 @@
|
||||||
# make sure we're interpreted by some minimal autoconf
|
# make sure we're interpreted by some minimal autoconf
|
||||||
AC_PREREQ(2.57)
|
AC_PREREQ(2.57)
|
||||||
|
|
||||||
AC_INIT(ctemplate, 0.4, opensource@google.com)
|
AC_INIT(ctemplate, 0.5, opensource@google.com)
|
||||||
# The argument here is just something that should be in the current directory
|
# The argument here is just something that should be in the current directory
|
||||||
# (for sanity checking)
|
# (for sanity checking)
|
||||||
AC_CONFIG_SRCDIR(README)
|
AC_CONFIG_SRCDIR(README)
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
/* This file is duplicated at http://www.corp.google.com/css/designstyle.css
|
|
||||||
* If you change this file, copy it to ~web/html/css/designstyle.css
|
|
||||||
*/
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
color: black;
|
color: black;
|
||||||
|
|
|
@ -319,8 +319,19 @@ are the modifiers that are supported:</p>
|
||||||
<td>javascript-escapes the variable before output
|
<td>javascript-escapes the variable before output
|
||||||
(eg <code>"</code> -> <code>\"</code>)</td>
|
(eg <code>"</code> -> <code>\"</code>)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr><td><code>:json_escape</code></td><td><code>:o</code></td>
|
||||||
|
<td>json-escapes a variable before output as a string in json;
|
||||||
|
similar to javascript escaping, but ignores characters such
|
||||||
|
as <code>=</code> and <code>&</code>.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<p><strong>NOTE:</strong> At the moment, there are no filters for handling XML
|
||||||
|
attributes and text nodes. For HTML snippets, use the html filter; in other
|
||||||
|
situations, it may be appropriate to use CDATA blocks.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3> <A NAME="inheritence">Details on Dictionary Lookup</A> </h3>
|
<h3> <A NAME="inheritence">Details on Dictionary Lookup</A> </h3>
|
||||||
|
|
||||||
|
@ -742,6 +753,24 @@ using a normal, file-based template, and then switch to
|
||||||
template-from-string later if you so desire.</p>
|
template-from-string later if you so desire.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3> Copying a Template Dictionary </h3>
|
||||||
|
|
||||||
|
<p>You can use the <code>MakeCopy()</code> method on a template
|
||||||
|
dictionary to make a "deep" copy of the template. This can be useful
|
||||||
|
for situations like the following: you want to fill a template several
|
||||||
|
times, each time with 90% of the values the same, but the last 10%
|
||||||
|
different. Computing the values is slow. Here's how you can use
|
||||||
|
<code>MakeCopy()</code> to do it:</p>
|
||||||
|
<ol>
|
||||||
|
<li> fill dict with 90%
|
||||||
|
<li> <code>newdict1 = dict->MakeCopy();</code>
|
||||||
|
<li> fill newdict1 with last 10%
|
||||||
|
<li> <code>newdict2 = dict->MakeCopy();</code>
|
||||||
|
<li> fill newdict2 with last 10%
|
||||||
|
<li> etc.
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
<h2>Security Considerations</h2>
|
<h2>Security Considerations</h2>
|
||||||
|
|
||||||
<p>Like all web applications, programs that use the Google Template System
|
<p>Like all web applications, programs that use the Google Template System
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
ctemplate (0.5) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Google Inc. <opensource@google.com> Mon, 14 May 2007 17:27:10 -0700
|
||||||
|
|
||||||
|
ctemplate (0.4) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Google Inc. <opensource@google.com> Mon, 15 Jan 2007 14:10:42 -0800
|
||||||
|
|
||||||
|
ctemplate (0.3) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Google Inc. <opensource@google.com> Mon, 21 Aug 2006 17:44:32 -0700
|
||||||
|
|
||||||
|
ctemplate (0.2) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Google Inc. <opensource@google.com> Wed, 14 Jun 2006 14:56:04 -0700
|
||||||
|
|
||||||
ctemplate (0.1-1) unstable; urgency=low
|
ctemplate (0.1-1) unstable; urgency=low
|
||||||
|
|
||||||
* Initial release.
|
* Initial release.
|
||||||
|
|
|
@ -10,18 +10,18 @@ Section: libdevel
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: libctemplate0 (= ${Source-Version})
|
Depends: libctemplate0 (= ${Source-Version})
|
||||||
Description: This package contains a library implementing a simple but
|
Description: This package contains a library implementing a simple but
|
||||||
powerful template language for C++. It emphasizes separating logic
|
powerful template language for C++. It emphasizes separating logic
|
||||||
from presentation: it is impossible to embed application logic in this
|
from presentation: it is impossible to embed application logic in this
|
||||||
template language. The devel package contains static and debug
|
template language. The devel package contains static and debug
|
||||||
libraries and header files for developing applications that use the
|
libraries and header files for developing applications that use the
|
||||||
ctemplate package.
|
ctemplate package.
|
||||||
|
|
||||||
Package: libctemplate0
|
Package: libctemplate0
|
||||||
Section: libs
|
Section: libs
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Description: This package contains a library implementing a simple but
|
Description: This package contains a library implementing a simple but
|
||||||
powerful template language for C++. It emphasizes separating logic
|
powerful template language for C++. It emphasizes separating logic
|
||||||
from presentation: it is impossible to embed application logic in this
|
from presentation: it is impossible to embed application logic in this
|
||||||
template language. This limits the power of the template language
|
template language. This limits the power of the template language
|
||||||
without limiting the power of the template *system*. Indeed, Google's
|
without limiting the power of the template *system*. Indeed, Google's
|
||||||
"main" web search uses this system exclusively for formatting output.
|
"main" web search uses this system exclusively for formatting output.
|
||||||
|
|
|
@ -9,3 +9,7 @@ doc/index.html
|
||||||
doc/howto.html
|
doc/howto.html
|
||||||
doc/tips.html
|
doc/tips.html
|
||||||
doc/example.html
|
doc/example.html
|
||||||
|
doc/xss_resources.html
|
||||||
|
contrib/README.contrib
|
||||||
|
contrib/highlighting.vim
|
||||||
|
contrib/tpl-mode.el
|
||||||
|
|
|
@ -65,7 +65,6 @@ rm -rf $RPM_BUILD_ROOT
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
|
|
||||||
%{prefix}/include/google
|
%{prefix}/include/google
|
||||||
%{prefix}/lib/debug
|
|
||||||
%{prefix}/lib/libctemplate.a
|
%{prefix}/lib/libctemplate.a
|
||||||
%{prefix}/lib/libctemplate.la
|
%{prefix}/lib/libctemplate.la
|
||||||
%{prefix}/lib/libctemplate.so
|
%{prefix}/lib/libctemplate.so
|
||||||
|
|
79
trunk/src/base/mutex.cc
Normal file
79
trunk/src/base/mutex.cc
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* 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
|
134
trunk/src/base/mutex.h
Normal file
134
trunk/src/base/mutex.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/* 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, supporting locks and read-write locks.
|
||||||
|
*
|
||||||
|
* To use: you should define the following macros in your configure.ac:
|
||||||
|
* ACX_PTHREAD
|
||||||
|
* AC_RWLOCK
|
||||||
|
* The latter is defined in ../autoconf.
|
||||||
|
*
|
||||||
|
* This class is meant to be internal-only, so it's defined in the
|
||||||
|
* global namespace. If you want to expose it, you'll want to move
|
||||||
|
* it to the Google namespace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h" // to figure out pthreads support
|
||||||
|
|
||||||
|
#if defined(NO_THREADS)
|
||||||
|
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
|
||||||
|
# include <pthread.h>
|
||||||
|
typedef pthread_rwlock_t MutexType;
|
||||||
|
#elif defined(HAVE_PTHREAD)
|
||||||
|
# include <pthread.h>
|
||||||
|
typedef pthread_mutex_t MutexType;
|
||||||
|
#else
|
||||||
|
# error Need to implement mutex.h/cc for your architecture, or #define NO_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Mutex {
|
||||||
|
public:
|
||||||
|
// Create a Mutex that is not held by anybody. This constructor is
|
||||||
|
// typically used for Mutexes allocated on the heap or the stack.
|
||||||
|
// See below for a recommendation for constructing global Mutex
|
||||||
|
// objects.
|
||||||
|
Mutex();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~Mutex();
|
||||||
|
|
||||||
|
void Lock(); // Block if necessary until free, then acquire exclusively
|
||||||
|
void Unlock(); // Release. Caller must hold it exclusively (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
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutexType mutex_;
|
||||||
|
|
||||||
|
// Catch the error of writing Mutex when intending MutexLock.
|
||||||
|
Mutex(Mutex *ignored) {}
|
||||||
|
// Disallow "evil" constructors
|
||||||
|
Mutex(const Mutex&);
|
||||||
|
void operator=(const Mutex&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
|
||||||
|
class MutexLock {
|
||||||
|
public:
|
||||||
|
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
|
||||||
|
~MutexLock() { mu_->Unlock(); }
|
||||||
|
private:
|
||||||
|
Mutex * const mu_;
|
||||||
|
// Disallow "evil" constructors
|
||||||
|
MutexLock(const MutexLock&);
|
||||||
|
void operator=(const MutexLock&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
|
||||||
|
class ReaderMutexLock {
|
||||||
|
public:
|
||||||
|
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
|
||||||
|
~ReaderMutexLock() { mu_->ReaderUnlock(); }
|
||||||
|
private:
|
||||||
|
Mutex * const mu_;
|
||||||
|
// Disallow "evil" constructors
|
||||||
|
ReaderMutexLock(const ReaderMutexLock&);
|
||||||
|
void operator=(const ReaderMutexLock&);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WriterMutexLock {
|
||||||
|
public:
|
||||||
|
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
|
||||||
|
~WriterMutexLock() { mu_->WriterUnlock(); }
|
||||||
|
private:
|
||||||
|
Mutex * const mu_;
|
||||||
|
// Disallow "evil" constructors
|
||||||
|
WriterMutexLock(const WriterMutexLock&);
|
||||||
|
void operator=(const WriterMutexLock&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
|
||||||
|
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
|
||||||
|
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
|
||||||
|
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
|
|
@ -13,12 +13,6 @@
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
#undef HAVE_DLFCN_H
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
/* define if the compiler has hash_map */
|
|
||||||
#undef HAVE_EXT_HASH_MAP
|
|
||||||
|
|
||||||
/* define if the compiler has hash_set */
|
|
||||||
#undef HAVE_EXT_HASH_SET
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `getopt_long' function. */
|
/* Define to 1 if you have the `getopt_long' function. */
|
||||||
#undef HAVE_GETOPT_LONG
|
#undef HAVE_GETOPT_LONG
|
||||||
|
|
||||||
|
@ -102,9 +96,15 @@
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#undef PACKAGE_VERSION
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
/* printf format code for printing a size_t */
|
/* printf format code for printing a size_t and ssize_t */
|
||||||
|
#undef PRIdS
|
||||||
|
|
||||||
|
/* printf format code for printing a size_t and ssize_t */
|
||||||
#undef PRIuS
|
#undef PRIuS
|
||||||
|
|
||||||
|
/* printf format code for printing a size_t and ssize_t */
|
||||||
|
#undef PRIxS
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||||
your system. */
|
your system. */
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
#undef PTHREAD_CREATE_JOINABLE
|
||||||
|
|
|
@ -245,7 +245,7 @@ class Template {
|
||||||
// The mutex object used during ReloadIfChanged to prevent the same
|
// The mutex object used during ReloadIfChanged to prevent the same
|
||||||
// object from reloading the template file in parallel by different
|
// object from reloading the template file in parallel by different
|
||||||
// threads.
|
// threads.
|
||||||
mutable class RWLock* mutex_; // RWLock defined in template.cc
|
mutable class Mutex* mutex_;
|
||||||
|
|
||||||
// The root directory for all templates. Defaults to "./" until
|
// The root directory for all templates. Defaults to "./" until
|
||||||
// SetTemplateRootDirectory changes it
|
// SetTemplateRootDirectory changes it
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
|
|
||||||
@ac_google_start_namespace@
|
@ac_google_start_namespace@
|
||||||
|
|
||||||
|
class UnsafeArena;
|
||||||
|
|
||||||
// Most methods below take a TemplateString rather than a C++ string.
|
// Most methods below take a TemplateString rather than a C++ string.
|
||||||
// This is for efficiency: it can avoid extra string copies.
|
// This is for efficiency: it can avoid extra string copies.
|
||||||
// For any argument that takes a TemplateString, you can pass in any of:
|
// For any argument that takes a TemplateString, you can pass in any of:
|
||||||
|
@ -88,10 +90,18 @@ class TemplateDictionary {
|
||||||
// arena is used to store all names and values. It can be NULL (the
|
// arena is used to store all names and values. It can be NULL (the
|
||||||
// default), in which case we create own own arena.
|
// default), in which case we create own own arena.
|
||||||
explicit TemplateDictionary(const std::string& name,
|
explicit TemplateDictionary(const std::string& name,
|
||||||
class UnsafeArena* arena=NULL);
|
UnsafeArena* arena=NULL);
|
||||||
~TemplateDictionary();
|
~TemplateDictionary();
|
||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
|
|
||||||
|
// Returns a recursive copy of this dictionary. This dictionary
|
||||||
|
// *must* be a "top-level" dictionary (that is, not created via
|
||||||
|
// AddSectionDictionary() or AddIncludeDictionary()). Caller owns
|
||||||
|
// the resulting dict, and must delete it. If arena is NULL, we
|
||||||
|
// create our own. Returns NULL if the copy fails (probably because
|
||||||
|
// the "top-level" rule was violated).
|
||||||
|
TemplateDictionary* MakeCopy(const std::string& name_of_copy,
|
||||||
|
UnsafeArena* arena=NULL);
|
||||||
|
|
||||||
// --- Routines for VARIABLES
|
// --- Routines for VARIABLES
|
||||||
// These are the five main routines used to set the value of a variable.
|
// These are the five main routines used to set the value of a variable.
|
||||||
|
@ -285,10 +295,18 @@ class TemplateDictionary {
|
||||||
// Helps set up the static stuff
|
// Helps set up the static stuff
|
||||||
static GlobalDict* SetupGlobalDictUnlocked();
|
static GlobalDict* SetupGlobalDictUnlocked();
|
||||||
|
|
||||||
|
// This is true iff this template was created via the public constructor,
|
||||||
|
// and not the private one used for subsidiary dicts (section/include)
|
||||||
|
bool is_rootlevel_template() const { return template_global_dict_owner_; }
|
||||||
|
|
||||||
// Utility functions for copying a string into the arena.
|
// Utility functions for copying a string into the arena.
|
||||||
const char *Memdup(const char* s, int slen);
|
const char *Memdup(const char* s, int slen);
|
||||||
const char *Memdup(const TemplateString& s) {return Memdup(s.ptr_, s.length_);}
|
const char *Memdup(const TemplateString& s) {return Memdup(s.ptr_, s.length_);}
|
||||||
|
|
||||||
|
// Used for recursive MakeCopy calls.
|
||||||
|
TemplateDictionary* InternalMakeCopy(const std::string& name_of_copy,
|
||||||
|
UnsafeArena* arena);
|
||||||
|
|
||||||
// Used to do the formatting for the SetFormatted*() functions
|
// Used to do the formatting for the SetFormatted*() functions
|
||||||
static int StringAppendV(char* space, char** out,
|
static int StringAppendV(char* space, char** out,
|
||||||
const char* format, va_list ap);
|
const char* format, va_list ap);
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#ifndef TEMPLATE_FROM_STRING_H
|
#ifndef TEMPLATE_FROM_STRING_H
|
||||||
#define TEMPLATE_FROM_STRING_H
|
#define TEMPLATE_FROM_STRING_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <google/template.h>
|
#include <google/template.h>
|
||||||
|
|
||||||
@ac_google_start_namespace@
|
@ac_google_start_namespace@
|
||||||
|
|
|
@ -33,10 +33,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
// Needed for pthread_rwlock_*. If it causes problems, you could take
|
#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
|
||||||
// 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
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -45,9 +42,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h> // for stat() and open()
|
#include <unistd.h> // for stat() and open()
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
|
||||||
# include <pthread.h>
|
|
||||||
#endif
|
|
||||||
#include <iostream> // for logging
|
#include <iostream> // for logging
|
||||||
#include <iomanip> // for indenting in Dump()
|
#include <iomanip> // for indenting in Dump()
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -70,58 +64,14 @@ using HASH_NAMESPACE::hash;
|
||||||
|
|
||||||
const int kIndent = 2; // num spaces to indent each level
|
const int kIndent = 2; // num spaces to indent each level
|
||||||
|
|
||||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
|
||||||
|
|
||||||
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
|
||||||
# ifdef HAVE_RWLOCK
|
|
||||||
// Easiest to use a wrapper class for the read-write mutex
|
|
||||||
class RWLock {
|
|
||||||
public:
|
|
||||||
RWLock() { SAFE_PTHREAD(pthread_rwlock_init(&lock_, NULL)); }
|
|
||||||
~RWLock() { SAFE_PTHREAD(pthread_rwlock_destroy(&lock_)); }
|
|
||||||
void LockRO() { SAFE_PTHREAD(pthread_rwlock_rdlock(&lock_)); }
|
|
||||||
void LockRW() { SAFE_PTHREAD(pthread_rwlock_wrlock(&lock_)); }
|
|
||||||
void Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&lock_)); }
|
|
||||||
private:
|
|
||||||
pthread_rwlock_t lock_;
|
|
||||||
};
|
|
||||||
# else
|
|
||||||
// Not as efficient, but the best we can do if !HAVE_RWLOCK
|
|
||||||
class RWLock {
|
|
||||||
public:
|
|
||||||
RWLock() { SAFE_PTHREAD(pthread_mutex_init(&lock_, NULL)); }
|
|
||||||
~RWLock() { SAFE_PTHREAD(pthread_mutex_destroy(&lock_)); }
|
|
||||||
void LockRO() { SAFE_PTHREAD(pthread_mutex_lock(&lock_)); }
|
|
||||||
void LockRW() { SAFE_PTHREAD(pthread_mutex_lock(&lock_)); }
|
|
||||||
void Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&lock_)); }
|
|
||||||
private:
|
|
||||||
pthread_mutex_t lock_;
|
|
||||||
};
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// Mutexes protecting the globals below. First protects g_use_current_dict
|
|
||||||
// and template_root_directory_, second protects g_template_cache.
|
|
||||||
static pthread_mutex_t g_static_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static pthread_mutex_t g_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
// This protects vars_seen in WriteOneHeaderEntry, below.
|
|
||||||
static pthread_mutex_t g_header_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
# define LOCK(m) SAFE_PTHREAD(pthread_mutex_lock(m))
|
|
||||||
# define UNLOCK(m) SAFE_PTHREAD(pthread_mutex_unlock(m))
|
|
||||||
#else
|
|
||||||
class RWLock { // since mutex_ has this type
|
|
||||||
public:
|
|
||||||
RWLock() {}
|
|
||||||
void LockRO() {}
|
|
||||||
void LockRW() {}
|
|
||||||
void Unlock() {}
|
|
||||||
};
|
|
||||||
# define LOCK(m)
|
|
||||||
# define UNLOCK(m)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
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.
|
||||||
|
static Mutex g_static_mutex;
|
||||||
|
static Mutex g_cache_mutex;
|
||||||
|
static Mutex g_header_mutex;
|
||||||
const char * const kDefaultTemplateDirectory = "./";
|
const char * const kDefaultTemplateDirectory = "./";
|
||||||
const char * const kMainSectionName = "__MAIN__";
|
const char * const kMainSectionName = "__MAIN__";
|
||||||
static vector<TemplateDictionary*>* g_use_current_dict; // vector == {NULL}
|
static vector<TemplateDictionary*>* g_use_current_dict; // vector == {NULL}
|
||||||
|
@ -187,23 +137,31 @@ static string HtmlModifier(const string& input, const string&) {
|
||||||
return TemplateDictionary::html_escape(input);
|
return TemplateDictionary::html_escape(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string PreModifier(const string& input, const string&) {
|
|
||||||
return TemplateDictionary::pre_escape(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
static string JavascriptModifier(const string& input, const string&) {
|
static string JavascriptModifier(const string& input, const string&) {
|
||||||
return TemplateDictionary::javascript_escape(input);
|
return TemplateDictionary::javascript_escape(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string JsonModifier(const string& input, const string&) {
|
||||||
|
return TemplateDictionary::json_escape(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
static string PreModifier(const string& input, const string&) {
|
||||||
|
return TemplateDictionary::pre_escape(input);
|
||||||
|
}
|
||||||
|
|
||||||
static string UrlQueryEscapeModifier(const string& input, const string&) {
|
static string UrlQueryEscapeModifier(const string& input, const string&) {
|
||||||
return TemplateDictionary::url_query_escape(input);
|
return TemplateDictionary::url_query_escape(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using "o" for JSON is not really very intuitive; template authors should
|
||||||
|
// either use json_escape in full, or provide a comment explaining the
|
||||||
|
// non-intuitive shortening.
|
||||||
static const Modifier g_modifiers[] = {
|
static const Modifier g_modifiers[] = {
|
||||||
{ "html_escape", 'h', MODVAL_FORBIDDEN, &HtmlModifier },
|
{ "html_escape", 'h', MODVAL_FORBIDDEN, &HtmlModifier },
|
||||||
{ "pre_escape", 'p', MODVAL_FORBIDDEN, &PreModifier },
|
|
||||||
{ "javascript_escape", 'j', MODVAL_FORBIDDEN, &JavascriptModifier },
|
{ "javascript_escape", 'j', MODVAL_FORBIDDEN, &JavascriptModifier },
|
||||||
{ "url_query_escape", 'u', MODVAL_FORBIDDEN, &UrlQueryEscapeModifier },
|
{ "json_escape", 'o', MODVAL_FORBIDDEN, &JsonModifier },
|
||||||
|
{ "pre_escape", 'p', MODVAL_FORBIDDEN, &PreModifier },
|
||||||
|
{ "url_query_escape", 'u', MODVAL_FORBIDDEN, &UrlQueryEscapeModifier }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,7 +203,7 @@ class HeaderEntryStringHash { // not all STL implementations define this...
|
||||||
static void WriteOneHeaderEntry(string *outstring,
|
static void WriteOneHeaderEntry(string *outstring,
|
||||||
const string& variable,
|
const string& variable,
|
||||||
const string& full_pathname) {
|
const string& full_pathname) {
|
||||||
LOCK(&g_header_mutex);
|
MutexLock ml(&g_header_mutex);
|
||||||
|
|
||||||
// we use hash_map instead of hash_set just to keep the stl size down
|
// we use hash_map instead of hash_set just to keep the stl size down
|
||||||
static hash_map<string, bool, HeaderEntryStringHash> vars_seen;
|
static hash_map<string, bool, HeaderEntryStringHash> vars_seen;
|
||||||
|
@ -303,7 +261,6 @@ static void WriteOneHeaderEntry(string *outstring,
|
||||||
}
|
}
|
||||||
vars_seen[variable] = true;
|
vars_seen[variable] = true;
|
||||||
}
|
}
|
||||||
UNLOCK(&g_header_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -869,7 +826,7 @@ void SectionTemplateNode::Dump(int level) const {
|
||||||
// --- AddSubnode and its sub-routines
|
// --- AddSubnode and its sub-routines
|
||||||
|
|
||||||
void SectionTemplateNode::AddTextNode(const char* text, int textlen) {
|
void SectionTemplateNode::AddTextNode(const char* text, int textlen) {
|
||||||
if (text != "") { // ignore null text sections
|
if (textlen > 0) { // ignore null text sections
|
||||||
node_list_.push_back(new TextTemplateNode(text, textlen));
|
node_list_.push_back(new TextTemplateNode(text, textlen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1173,7 @@ Template::Template(const string& filename, Strip strip)
|
||||||
: filename_(filename), filename_mtime_(0), strip_(strip),
|
: filename_(filename), filename_mtime_(0), strip_(strip),
|
||||||
state_(TS_EMPTY),
|
state_(TS_EMPTY),
|
||||||
template_text_(NULL), template_text_len_(0), tree_(NULL),
|
template_text_(NULL), template_text_len_(0), tree_(NULL),
|
||||||
parse_state_(), mutex_(new RWLock) {
|
parse_state_(), mutex_(new Mutex) {
|
||||||
// Make sure g_use_current_dict, etc. are initted before any possbility
|
// Make sure g_use_current_dict, etc. are initted before any possbility
|
||||||
// of calling Expand() or other Template classes that access globals.
|
// of calling Expand() or other Template classes that access globals.
|
||||||
AssureGlobalsInitialized();
|
AssureGlobalsInitialized();
|
||||||
|
@ -1247,21 +1204,20 @@ Template::~Template() {
|
||||||
// NOTE: This function must be called by any static function that
|
// NOTE: This function must be called by any static function that
|
||||||
// accesses any of the variables set here.
|
// accesses any of the variables set here.
|
||||||
void Template::AssureGlobalsInitialized() {
|
void Template::AssureGlobalsInitialized() {
|
||||||
LOCK(&g_static_mutex); // protects all the vars defined here
|
MutexLock ml(&g_static_mutex); // protects all the vars defined here
|
||||||
if (template_root_directory_ == NULL) { // only need to run this once!
|
if (template_root_directory_ == NULL) { // only need to run this once!
|
||||||
template_root_directory_ = new string(kDefaultTemplateDirectory);
|
template_root_directory_ = new string(kDefaultTemplateDirectory);
|
||||||
// this_dict is a dictionary with a single NULL entry in it
|
// this_dict is a dictionary with a single NULL entry in it
|
||||||
g_use_current_dict = new vector<TemplateDictionary*>;
|
g_use_current_dict = new vector<TemplateDictionary*>;
|
||||||
g_use_current_dict->push_back(NULL);
|
g_use_current_dict->push_back(NULL);
|
||||||
}
|
}
|
||||||
UNLOCK(&g_static_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Template *Template::GetTemplate(const string& filename, Strip strip) {
|
Template *Template::GetTemplate(const string& filename, Strip strip) {
|
||||||
// No need to have the cache-mutex acquired for this step
|
// No need to have the cache-mutex acquired for this step
|
||||||
string abspath(PathJoin(template_root_directory(), filename));
|
string abspath(PathJoin(template_root_directory(), filename));
|
||||||
|
|
||||||
LOCK(&g_cache_mutex);
|
MutexLock ml(&g_cache_mutex);
|
||||||
if (g_template_cache == NULL)
|
if (g_template_cache == NULL)
|
||||||
g_template_cache = new TemplateCache;
|
g_template_cache = new TemplateCache;
|
||||||
|
|
||||||
|
@ -1277,7 +1233,6 @@ Template *Template::GetTemplate(const string& filename, Strip strip) {
|
||||||
tpl = new Template(abspath, strip);
|
tpl = new Template(abspath, strip);
|
||||||
(*g_template_cache)[pair<string, Strip>(abspath, strip)] = tpl;
|
(*g_template_cache)[pair<string, Strip>(abspath, strip)] = tpl;
|
||||||
}
|
}
|
||||||
UNLOCK(&g_cache_mutex); // we're done messing with g_template_cache
|
|
||||||
|
|
||||||
// if the statis is not TS_READY, then it is TS_ERROR at this
|
// 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
|
// point. If it is TS_ERROR, we leave the state as is, but return
|
||||||
|
@ -1374,7 +1329,7 @@ bool Template::SetTemplateRootDirectory(const string& directory) {
|
||||||
AssureGlobalsInitialized();
|
AssureGlobalsInitialized();
|
||||||
|
|
||||||
// This is needed since we access/modify template_root_directory_
|
// This is needed since we access/modify template_root_directory_
|
||||||
LOCK(&g_static_mutex);
|
MutexLock ml(&g_static_mutex);
|
||||||
// make sure it ends with '/'
|
// make sure it ends with '/'
|
||||||
if (directory.length() == 0 || directory[directory.length()-1] != '/') {
|
if (directory.length() == 0 || directory[directory.length()-1] != '/') {
|
||||||
*template_root_directory_ = directory + '/';
|
*template_root_directory_ = directory + '/';
|
||||||
|
@ -1383,7 +1338,6 @@ bool Template::SetTemplateRootDirectory(const string& directory) {
|
||||||
}
|
}
|
||||||
VLOG(2) << "Setting Template directory to " << *template_root_directory_
|
VLOG(2) << "Setting Template directory to " << *template_root_directory_
|
||||||
<< endl;
|
<< endl;
|
||||||
UNLOCK(&g_static_mutex);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,10 +1345,8 @@ bool Template::SetTemplateRootDirectory(const string& directory) {
|
||||||
string Template::template_root_directory() {
|
string Template::template_root_directory() {
|
||||||
// Make sure template_root_directory_ has been initialized
|
// Make sure template_root_directory_ has been initialized
|
||||||
AssureGlobalsInitialized();
|
AssureGlobalsInitialized();
|
||||||
LOCK(&g_static_mutex); // protects the static var template_root_directory_
|
MutexLock ml(&g_static_mutex); // protects the static var t_r_d_
|
||||||
string retval = *template_root_directory_;
|
return *template_root_directory_;
|
||||||
UNLOCK(&g_static_mutex);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Template::set_state(TemplateState new_state) {
|
void Template::set_state(TemplateState new_state) {
|
||||||
|
@ -1428,21 +1380,19 @@ bool Template::ReloadIfChanged() {
|
||||||
// from different threads, they don't stomp on tree_ and state_.
|
// from different threads, they don't stomp on tree_ and state_.
|
||||||
// This is still not perfect, since set_filename() could stomp
|
// This is still not perfect, since set_filename() could stomp
|
||||||
// on filename_ while we're reading it, but it's good enough.
|
// on filename_ while we're reading it, but it's good enough.
|
||||||
mutex_->LockRW();
|
WriterMutexLock ml(mutex_);
|
||||||
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if (stat(filename_.c_str(), &statbuf) != 0) {
|
if (stat(filename_.c_str(), &statbuf) != 0) {
|
||||||
LOG(WARNING) << "Unable to stat file " << filename_ << endl;
|
LOG(WARNING) << "Unable to stat file " << filename_ << endl;
|
||||||
// We keep the old tree if there is one, otherwise we're in error
|
// We keep the old tree if there is one, otherwise we're in error
|
||||||
set_state(tree_ ? TS_READY : TS_ERROR);
|
set_state(tree_ ? TS_READY : TS_ERROR);
|
||||||
mutex_->Unlock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (statbuf.st_mtime == filename_mtime_ && filename_mtime_ > 0
|
if (statbuf.st_mtime == filename_mtime_ && filename_mtime_ > 0
|
||||||
&& tree_) { // force a reload if we don't already have a tree_
|
&& tree_) { // force a reload if we don't already have a tree_
|
||||||
VLOG(1) << "Not reloading file " << filename_ << ": no new mod-time" << endl;
|
VLOG(1) << "Not reloading file " << filename_ << ": no new mod-time" << endl;
|
||||||
set_state(TS_READY);
|
set_state(TS_READY);
|
||||||
mutex_->Unlock();
|
|
||||||
return false; // file's timestamp hasn't changed, so no need to reload
|
return false; // file's timestamp hasn't changed, so no need to reload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,7 +1401,6 @@ bool Template::ReloadIfChanged() {
|
||||||
LOG(ERROR) << "Can't find file " << filename_ << "; skipping" << endl;
|
LOG(ERROR) << "Can't find file " << filename_ << "; skipping" << endl;
|
||||||
// We keep the old tree if there is one, otherwise we're in error
|
// We keep the old tree if there is one, otherwise we're in error
|
||||||
set_state(tree_ ? TS_READY : TS_ERROR);
|
set_state(tree_ ? TS_READY : TS_ERROR);
|
||||||
mutex_->Unlock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char* file_buffer = new char[statbuf.st_size];
|
char* file_buffer = new char[statbuf.st_size];
|
||||||
|
@ -1462,7 +1411,6 @@ bool Template::ReloadIfChanged() {
|
||||||
delete[] file_buffer;
|
delete[] file_buffer;
|
||||||
// We could just keep the old tree, but probably safer to say 'error'
|
// We could just keep the old tree, but probably safer to say 'error'
|
||||||
set_state(TS_ERROR);
|
set_state(TS_ERROR);
|
||||||
mutex_->Unlock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -1480,19 +1428,16 @@ bool Template::ReloadIfChanged() {
|
||||||
// of input_buffer in every case, and will eventually delete it.
|
// of input_buffer in every case, and will eventually delete it.
|
||||||
if ( BuildTree(input_buffer, input_buffer + buflen) ) {
|
if ( BuildTree(input_buffer, input_buffer + buflen) ) {
|
||||||
assert(state() == TS_READY);
|
assert(state() == TS_READY);
|
||||||
mutex_->Unlock();
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
assert(state() != TS_READY);
|
assert(state() != TS_READY);
|
||||||
mutex_->Unlock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Template::ReloadAllIfChanged() {
|
void Template::ReloadAllIfChanged() {
|
||||||
LOCK(&g_cache_mutex); // this protects the static g_template_cache
|
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||||
if (g_template_cache == NULL) {
|
if (g_template_cache == NULL) {
|
||||||
UNLOCK(&g_cache_mutex);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
||||||
|
@ -1500,7 +1445,6 @@ void Template::ReloadAllIfChanged() {
|
||||||
++iter) {
|
++iter) {
|
||||||
(*iter).second->set_state(TS_RELOAD);
|
(*iter).second->set_state(TS_RELOAD);
|
||||||
}
|
}
|
||||||
UNLOCK(&g_cache_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -1509,9 +1453,8 @@ void Template::ReloadAllIfChanged() {
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
void Template::ClearCache() {
|
void Template::ClearCache() {
|
||||||
LOCK(&g_cache_mutex); // this protects the static g_template_cache
|
MutexLock ml(&g_cache_mutex); // this protects the static g_template_cache
|
||||||
if (g_template_cache == NULL) {
|
if (g_template_cache == NULL) {
|
||||||
UNLOCK(&g_cache_mutex);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
for (TemplateCache::const_iterator iter = g_template_cache->begin();
|
||||||
|
@ -1521,7 +1464,6 @@ void Template::ClearCache() {
|
||||||
}
|
}
|
||||||
delete g_template_cache;
|
delete g_template_cache;
|
||||||
g_template_cache = NULL;
|
g_template_cache = NULL;
|
||||||
UNLOCK(&g_cache_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -1668,11 +1610,10 @@ bool Template::Expand(ExpandEmitter *expand_emitter,
|
||||||
// tree_, and we want to make sure it doesn't do that (in another
|
// tree_, and we want to make sure it doesn't do that (in another
|
||||||
// thread) while we're expanding. We also protect state_, etc.
|
// thread) while we're expanding. We also protect state_, etc.
|
||||||
// Note we only need a read-lock here, so many expands can go on at once.
|
// Note we only need a read-lock here, so many expands can go on at once.
|
||||||
mutex_->LockRO();
|
ReaderMutexLock ml(mutex_);
|
||||||
|
|
||||||
if (state() != TS_READY) {
|
if (state() != TS_READY) {
|
||||||
// We'd like to reload if state_ == TS_RELOAD, but we're a const method
|
// We'd like to reload if state_ == TS_RELOAD, but we're a const method
|
||||||
mutex_->Unlock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,8 +1642,6 @@ bool Template::Expand(ExpandEmitter *expand_emitter,
|
||||||
expand_emitter->Emit(TemplateNode::CloseAnnotation("FILE"));
|
expand_emitter->Emit(TemplateNode::CloseAnnotation("FILE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_->Unlock();
|
|
||||||
|
|
||||||
return error_free;
|
return error_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,18 +33,11 @@
|
||||||
// Based on the 'old' TemplateDictionary by Frank Jernigan.
|
// Based on the 'old' TemplateDictionary by Frank Jernigan.
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
|
||||||
// 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
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h> // for varargs with StringAppendV
|
#include <stdarg.h> // for varargs with StringAppendV
|
||||||
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
|
||||||
# include <pthread.h>
|
|
||||||
#endif
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm> // for sort
|
#include <algorithm> // for sort
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -59,31 +52,7 @@ using std::string;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using HASH_NAMESPACE::hash_map;
|
using HASH_NAMESPACE::hash_map;
|
||||||
|
|
||||||
#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0)
|
static Mutex g_static_mutex;
|
||||||
|
|
||||||
#if defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) && !defined(NO_THREADS)
|
|
||||||
# define STATIC_ROLOCK SAFE_PTHREAD(pthread_rwlock_rdlock(&g_static_mutex))
|
|
||||||
# define STATIC_RWLOCK SAFE_PTHREAD(pthread_rwlock_wrlock(&g_static_mutex))
|
|
||||||
# define STATIC_UNLOCK SAFE_PTHREAD(pthread_rwlock_unlock(&g_static_mutex))
|
|
||||||
// PTHREAD_RWLOCK_INITIALIZER isn't defined on OS X, at least as of 6/1/06.
|
|
||||||
// We use a static class instance to force initialization at program-start time.
|
|
||||||
static pthread_rwlock_t g_static_mutex;
|
|
||||||
namespace { // keep this class name from polluting the global namespace
|
|
||||||
struct StaticMutexInit {
|
|
||||||
StaticMutexInit() { SAFE_PTHREAD(pthread_rwlock_init(&g_static_mutex, NULL)); }
|
|
||||||
};
|
|
||||||
static StaticMutexInit g_static_mutex_initializer; // constructs early
|
|
||||||
}
|
|
||||||
#elif defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
|
||||||
# define STATIC_ROLOCK SAFE_PTHREAD(pthread_mutex_lock(&g_static_mutex))
|
|
||||||
# define STATIC_RWLOCK SAFE_PTHREAD(pthread_mutex_lock(&g_static_mutex))
|
|
||||||
# define STATIC_UNLOCK SAFE_PTHREAD(pthread_mutex_unlock(&g_static_mutex))
|
|
||||||
static pthread_mutex_t g_static_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
#else
|
|
||||||
# define STATIC_ROLOCK
|
|
||||||
# define STATIC_RWLOCK
|
|
||||||
# define STATIC_UNLOCK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*static*/ TemplateDictionary::GlobalDict* TemplateDictionary::global_dict_
|
/*static*/ TemplateDictionary::GlobalDict* TemplateDictionary::global_dict_
|
||||||
= NULL;
|
= NULL;
|
||||||
|
@ -133,10 +102,9 @@ TemplateDictionary::TemplateDictionary(const string& name, UnsafeArena* arena)
|
||||||
parent_dict_(NULL),
|
parent_dict_(NULL),
|
||||||
filename_(NULL),
|
filename_(NULL),
|
||||||
template_path_start_for_annotations_(NULL) {
|
template_path_start_for_annotations_(NULL) {
|
||||||
STATIC_RWLOCK;
|
MutexLock ml(&g_static_mutex);
|
||||||
if (global_dict_ == NULL)
|
if (global_dict_ == NULL)
|
||||||
global_dict_ = SetupGlobalDictUnlocked();
|
global_dict_ = SetupGlobalDictUnlocked();
|
||||||
STATIC_UNLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateDictionary::TemplateDictionary(const string& name, UnsafeArena* arena,
|
TemplateDictionary::TemplateDictionary(const string& name, UnsafeArena* arena,
|
||||||
|
@ -154,10 +122,9 @@ TemplateDictionary::TemplateDictionary(const string& name, UnsafeArena* arena,
|
||||||
parent_dict_(parent_dict),
|
parent_dict_(parent_dict),
|
||||||
filename_(NULL),
|
filename_(NULL),
|
||||||
template_path_start_for_annotations_(NULL) {
|
template_path_start_for_annotations_(NULL) {
|
||||||
STATIC_RWLOCK;
|
MutexLock ml(&g_static_mutex);
|
||||||
if (global_dict_ == NULL)
|
if (global_dict_ == NULL)
|
||||||
global_dict_ = SetupGlobalDictUnlocked();
|
global_dict_ = SetupGlobalDictUnlocked();
|
||||||
STATIC_UNLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateDictionary::~TemplateDictionary() {
|
TemplateDictionary::~TemplateDictionary() {
|
||||||
|
@ -190,10 +157,84 @@ TemplateDictionary::~TemplateDictionary() {
|
||||||
if (template_global_dict_owner_) {
|
if (template_global_dict_owner_) {
|
||||||
delete template_global_dict_;
|
delete template_global_dict_;
|
||||||
}
|
}
|
||||||
if (should_delete_arena_)
|
if (should_delete_arena_) {
|
||||||
delete arena_;
|
delete arena_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// TemplateDictionary::MakeCopy()
|
||||||
|
// Makes a recursive copy: so we copy any include dictionaries and
|
||||||
|
// section dictionaries we see as well. InternalMakeCopy() is
|
||||||
|
// needed just so we can ensure that if we're doing a copy of a
|
||||||
|
// subtree, it's due to a recursive call.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
TemplateDictionary* TemplateDictionary::InternalMakeCopy(
|
||||||
|
const string& name_of_copy, UnsafeArena* arena) {
|
||||||
|
TemplateDictionary* newdict;
|
||||||
|
if (is_rootlevel_template()) { // rootlevel uses public constructor
|
||||||
|
newdict = new TemplateDictionary(name_of_copy, arena);
|
||||||
|
} else { // recursve calls use private contructor
|
||||||
|
// Note: we always use our own arena, even when we have a parent
|
||||||
|
newdict = new TemplateDictionary(name_of_copy, arena,
|
||||||
|
parent_dict_, template_global_dict_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the variable dictionary
|
||||||
|
for (VariableDict::const_iterator it = variable_dict_->begin();
|
||||||
|
it != variable_dict_->end(); ++it) {
|
||||||
|
newdict->SetValue(it->first, it->second);
|
||||||
|
}
|
||||||
|
// ...and the template-global-dict, if we're the owner of it
|
||||||
|
if (template_global_dict_owner_) {
|
||||||
|
for (VariableDict::const_iterator it = template_global_dict_->begin();
|
||||||
|
it != template_global_dict_->end(); ++it) {
|
||||||
|
newdict->SetTemplateGlobalValue(it->first, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy the section dictionary
|
||||||
|
for (SectionDict::iterator it = section_dict_->begin();
|
||||||
|
it != section_dict_->end(); ++it) {
|
||||||
|
DictVector* dicts = new DictVector;
|
||||||
|
(*newdict->section_dict_)[newdict->Memdup(it->first)] = dicts;
|
||||||
|
for (DictVector::iterator it2 = it->second->begin();
|
||||||
|
it2 != it->second->end(); ++it2) {
|
||||||
|
TemplateDictionary* subdict = *it2;
|
||||||
|
dicts->push_back(subdict->InternalMakeCopy(subdict->name(),
|
||||||
|
newdict->arena_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy the includes-dictionary
|
||||||
|
for (IncludeDict::iterator it = include_dict_->begin();
|
||||||
|
it != include_dict_->end(); ++it) {
|
||||||
|
DictVector* dicts = new DictVector;
|
||||||
|
(*newdict->include_dict_)[newdict->Memdup(it->first)] = dicts;
|
||||||
|
for (DictVector::iterator it2 = it->second->begin();
|
||||||
|
it2 != it->second->end(); ++it2) {
|
||||||
|
TemplateDictionary* subdict = *it2;
|
||||||
|
dicts->push_back(subdict->InternalMakeCopy(subdict->name(),
|
||||||
|
newdict->arena_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, copy everything else not set properly by the constructor
|
||||||
|
newdict->filename_ = newdict->Memdup(filename_);
|
||||||
|
newdict->template_path_start_for_annotations_ =
|
||||||
|
newdict->Memdup(template_path_start_for_annotations_);
|
||||||
|
|
||||||
|
return newdict;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateDictionary* TemplateDictionary::MakeCopy(const string& name_of_copy,
|
||||||
|
UnsafeArena* arena) {
|
||||||
|
if (!is_rootlevel_template()) { // we're not at the root, which is illegal
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return InternalMakeCopy(name_of_copy, arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// TemplateDictionary::StringAppendV()
|
// TemplateDictionary::StringAppendV()
|
||||||
// Does an snprintf to a string. Idea is to grow string as needed.
|
// Does an snprintf to a string. Idea is to grow string as needed.
|
||||||
|
@ -325,11 +366,10 @@ void TemplateDictionary::SetTemplateGlobalValue(const TemplateString variable,
|
||||||
memcpy(value_copy, value.ptr_, value.length_);
|
memcpy(value_copy, value.ptr_, value.length_);
|
||||||
value_copy[value.length_] = '\0';
|
value_copy[value.length_] = '\0';
|
||||||
|
|
||||||
STATIC_RWLOCK;
|
MutexLock ml(&g_static_mutex);
|
||||||
if (global_dict_ == NULL)
|
if (global_dict_ == NULL)
|
||||||
global_dict_ = SetupGlobalDictUnlocked();
|
global_dict_ = SetupGlobalDictUnlocked();
|
||||||
(*global_dict_)[variable_copy] = value_copy;
|
(*global_dict_)[variable_copy] = value_copy;
|
||||||
STATIC_UNLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -485,9 +525,8 @@ void TemplateDictionary::DumpToString(string* out, int indent) const {
|
||||||
|
|
||||||
vector<pair<const char*, const char*> > sorted_global_dict;
|
vector<pair<const char*, const char*> > sorted_global_dict;
|
||||||
{
|
{
|
||||||
STATIC_ROLOCK;
|
ReaderMutexLock ml(&g_static_mutex);
|
||||||
SortByStringKeyInto(*global_dict_, &sorted_global_dict);
|
SortByStringKeyInto(*global_dict_, &sorted_global_dict);
|
||||||
STATIC_UNLOCK;
|
|
||||||
}
|
}
|
||||||
for (vector<pair<const char*, const char*> >::const_iterator it
|
for (vector<pair<const char*, const char*> >::const_iterator it
|
||||||
= sorted_global_dict.begin();
|
= sorted_global_dict.begin();
|
||||||
|
@ -682,12 +721,11 @@ const char *TemplateDictionary::GetSectionValue(const string& variable) const {
|
||||||
|
|
||||||
// No match in dict tree or template-global dict. Last chance: global dict.
|
// No match in dict tree or template-global dict. Last chance: global dict.
|
||||||
{
|
{
|
||||||
STATIC_ROLOCK;
|
ReaderMutexLock ml(&g_static_mutex);
|
||||||
GlobalDict::const_iterator it = global_dict_->find(variable.c_str());
|
GlobalDict::const_iterator it = global_dict_->find(variable.c_str());
|
||||||
const char* retval = ""; // what we'll return if global lookup fails
|
const char* retval = ""; // what we'll return if global lookup fails
|
||||||
if (it != global_dict_->end())
|
if (it != global_dict_->end())
|
||||||
retval = it->second;
|
retval = it->second;
|
||||||
STATIC_UNLOCK;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,26 +880,22 @@ string TemplateDictionary::UrlQueryEscape::operator()(const string& in) const {
|
||||||
0x00000000L, 0x00000000L, 0x00000000L, 0x00000000L
|
0x00000000L, 0x00000000L, 0x00000000L, 0x00000000L
|
||||||
};
|
};
|
||||||
|
|
||||||
int max_string_length = in.size() * 3 + 1;
|
string out;
|
||||||
char out[max_string_length];
|
out.reserve(in.size() * 3 + 1);
|
||||||
|
|
||||||
int i;
|
for (int i = 0; i < in.size(); i++) {
|
||||||
int j;
|
|
||||||
|
|
||||||
for (i = 0, j = 0; i < in.size(); i++) {
|
|
||||||
unsigned char c = in[i];
|
unsigned char c = in[i];
|
||||||
if (c == ' ') {
|
if (c == ' ') {
|
||||||
out[j++] = '+';
|
out += '+';
|
||||||
} else if ((_safe_characters[(c)>>5] & (1 << ((c) & 31)))) {
|
} else if ((_safe_characters[(c)>>5] & (1 << ((c) & 31)))) {
|
||||||
out[j++] = c;
|
out += c;
|
||||||
} else {
|
} else {
|
||||||
out[j++] = '%';
|
out += '%';
|
||||||
out[j++] = ((c>>4) < 10 ? ((c>>4) + '0') : (((c>>4) - 10) + 'A'));
|
out += ((c>>4) < 10 ? ((c>>4) + '0') : (((c>>4) - 10) + 'A'));
|
||||||
out[j++] = ((c&0xf) < 10 ? ((c&0xf) + '0') : (((c&0xf) - 10) + 'A'));
|
out += ((c&0xf) < 10 ? ((c&0xf) + '0') : (((c&0xf) - 10) + 'A'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out[j++] = '\0';
|
return out;
|
||||||
return string(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escapes " / \ <BS> <FF> <CR> <LF> <TAB> to \" \/ \\ \b \f \r \n \t
|
// Escapes " / \ <BS> <FF> <CR> <LF> <TAB> to \" \/ \\ \b \f \r \n \t
|
||||||
|
|
|
@ -32,10 +32,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/ctemplate/hash_map.h>
|
#include <google/ctemplate/hash_map.h>
|
||||||
#include <google/template_from_string.h>
|
#include <google/template_from_string.h>
|
||||||
|
@ -43,21 +41,12 @@
|
||||||
|
|
||||||
_START_GOOGLE_NAMESPACE_
|
_START_GOOGLE_NAMESPACE_
|
||||||
|
|
||||||
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
|
static Mutex g_cache_mutex;
|
||||||
# define LOCK(m) pthread_mutex_lock(m)
|
|
||||||
# define UNLOCK(m) pthread_mutex_unlock(m)
|
|
||||||
// This is used to protect g_template_from_string_cache, below
|
|
||||||
static pthread_mutex_t g_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
#else
|
|
||||||
# define LOCK(m)
|
|
||||||
# define UNLOCK(m)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using HASH_NAMESPACE::hash_map;
|
using HASH_NAMESPACE::hash_map;
|
||||||
|
|
||||||
|
|
||||||
// TemplateFromString Constructor
|
// TemplateFromString Constructor
|
||||||
// Calls its parent with an empty string for filename so the parent's
|
// Calls its parent with an empty string for filename so the parent's
|
||||||
// constructor will not try to "load" the template from a file. Instead,
|
// constructor will not try to "load" the template from a file. Instead,
|
||||||
|
@ -111,7 +100,7 @@ TemplateFromString *TemplateFromString::GetTemplate(const string& template_name,
|
||||||
Strip strip) {
|
Strip strip) {
|
||||||
// Only perform this method when you have the lock so multiple threads
|
// Only perform this method when you have the lock so multiple threads
|
||||||
// don't conflict over inserting and retrieving into the cache
|
// don't conflict over inserting and retrieving into the cache
|
||||||
LOCK(&g_cache_mutex);
|
MutexLock ml(&g_cache_mutex);
|
||||||
if (g_template_from_string_cache == NULL) {
|
if (g_template_from_string_cache == NULL) {
|
||||||
g_template_from_string_cache = new TemplateFromStringCache;
|
g_template_from_string_cache = new TemplateFromStringCache;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +115,6 @@ TemplateFromString *TemplateFromString::GetTemplate(const string& template_name,
|
||||||
(*g_template_from_string_cache)[pair<string, Strip>(template_name, strip)] =
|
(*g_template_from_string_cache)[pair<string, Strip>(template_name, strip)] =
|
||||||
tpl;
|
tpl;
|
||||||
}
|
}
|
||||||
UNLOCK(&g_cache_mutex); // done messing with the cache
|
|
||||||
|
|
||||||
// state_ can be TS_RELOAD if ReloadAllIfChanged() touched this file.
|
// state_ can be TS_RELOAD if ReloadAllIfChanged() touched this file.
|
||||||
// That's fine; we'll just ignore the reload directive for this guy.
|
// That's fine; we'll just ignore the reload directive for this guy.
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector> // that's MissingListType, SyntaxListType
|
#include <vector> // that's MissingListType, SyntaxListType
|
||||||
#include <iostream> // for cerr
|
#include <iostream> // for cerr
|
||||||
#include <algorithm> // for find()
|
#include <algorithm> // for binary_search
|
||||||
#include <google/ctemplate/hash_set.h> // that's NameListType
|
#include <google/ctemplate/hash_set.h> // that's NameListType
|
||||||
#include <google/template_namelist.h>
|
#include <google/template_namelist.h>
|
||||||
#include <google/template.h> // for Strip, GetTemplate(), etc.
|
#include <google/template.h> // for Strip, GetTemplate(), etc.
|
||||||
|
@ -96,6 +96,7 @@ const TemplateNamelist::NameListType& TemplateNamelist::GetList() {
|
||||||
// and adds to the list any that are missing
|
// and adds to the list any that are missing
|
||||||
// On subsequent calls, if refresh is false it merely returns the
|
// On subsequent calls, if refresh is false it merely returns the
|
||||||
// list created in the prior call that refreshed the list.
|
// list created in the prior call that refreshed the list.
|
||||||
|
// Returns a sorted list of missing templates.
|
||||||
const TemplateNamelist::MissingListType& TemplateNamelist::GetMissingList(
|
const TemplateNamelist::MissingListType& TemplateNamelist::GetMissingList(
|
||||||
bool refresh) {
|
bool refresh) {
|
||||||
if (!missing_list_) {
|
if (!missing_list_) {
|
||||||
|
@ -158,11 +159,9 @@ const TemplateNamelist::SyntaxListType& TemplateNamelist::GetBadSyntaxList(
|
||||||
++iter) {
|
++iter) {
|
||||||
Template *tpl = Template::GetTemplate((*iter), strip);
|
Template *tpl = Template::GetTemplate((*iter), strip);
|
||||||
if (!tpl) {
|
if (!tpl) {
|
||||||
MissingListType::const_iterator pos =
|
if (!binary_search(missing_list.begin(), missing_list.end(), *iter)) {
|
||||||
find(missing_list.begin(), missing_list.end(), (*iter));
|
// If it's not in the missing list, then we're here because
|
||||||
// If it's not in the missing list, then we're here because it caused
|
// it caused an error during parsing
|
||||||
// an error during parsing
|
|
||||||
if (pos == missing_list.end()) {
|
|
||||||
bad_syntax_list_->push_back(*iter);
|
bad_syntax_list_->push_back(*iter);
|
||||||
std::cerr << "ERROR loading template: " << (*iter) << std::endl;
|
std::cerr << "ERROR loading template: " << (*iter) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,6 +771,57 @@ class TemplateDictionaryUnittest {
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_STREQ(dump.c_str(), expected);
|
ASSERT_STREQ(dump.c_str(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestMakeCopy(bool use_local_arena) {
|
||||||
|
UnsafeArena local_arena(1024);
|
||||||
|
UnsafeArena* arena = NULL;
|
||||||
|
if (use_local_arena)
|
||||||
|
arena = &local_arena;
|
||||||
|
|
||||||
|
// First, let's make a non-trivial template dictionary (We use
|
||||||
|
// 'new' because later we'll test deleting this dict but keeping
|
||||||
|
// around the copy.)
|
||||||
|
TemplateDictionary* dict = new TemplateDictionary("testdict", arena);
|
||||||
|
|
||||||
|
dict->SetValue("TOPLEVEL", "foo");
|
||||||
|
|
||||||
|
dict->SetTemplateGlobalValue("TEMPLATELEVEL", "foo3");
|
||||||
|
|
||||||
|
TemplateDictionary* subdict_1a = dict->AddIncludeDictionary("include1");
|
||||||
|
subdict_1a->SetFilename("incfile1a");
|
||||||
|
subdict_1a->SetValue("SUBLEVEL", "subfoo");
|
||||||
|
TemplateDictionary* subdict_1b = dict->AddIncludeDictionary("include1");
|
||||||
|
// Let's try not calling SetFilename on this one.
|
||||||
|
subdict_1b->SetValue("SUBLEVEL", "subbar");
|
||||||
|
|
||||||
|
TemplateDictionary* subdict_2a = dict->AddSectionDictionary("section1");
|
||||||
|
TemplateDictionary* subdict_2b = dict->AddSectionDictionary("section1");
|
||||||
|
subdict_2a->SetValue("SUBLEVEL", "subfoo");
|
||||||
|
subdict_2b->SetValue("SUBLEVEL", "subbar");
|
||||||
|
TemplateDictionary* subdict_3 = dict->AddSectionDictionary("section2");
|
||||||
|
subdict_3->SetValue("TOPLEVEL", "bar"); // overriding top dict
|
||||||
|
TemplateDictionary* subdict_3_1 = subdict_3->AddSectionDictionary("sub");
|
||||||
|
subdict_3_1->SetIntValue("GLOBAL", 21); // overrides value in setUp()
|
||||||
|
|
||||||
|
string orig;
|
||||||
|
dict->DumpToString(&orig);
|
||||||
|
|
||||||
|
// Make a copy
|
||||||
|
TemplateDictionary* dict_copy = dict->MakeCopy("testdict", NULL);
|
||||||
|
// Make sure it doesn't work to copy a sub-dictionary
|
||||||
|
ASSERT(subdict_1a->MakeCopy("copy of subdict") == NULL);
|
||||||
|
ASSERT(subdict_2a->MakeCopy("copy of subdict") == NULL);
|
||||||
|
|
||||||
|
// Delete the original dict, to make sure the copy really is independent
|
||||||
|
delete dict;
|
||||||
|
dict = NULL;
|
||||||
|
string copy;
|
||||||
|
dict_copy->DumpToString(©);
|
||||||
|
delete dict_copy;
|
||||||
|
|
||||||
|
ASSERT_STREQ(orig.c_str(), copy.c_str());
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_END_GOOGLE_NAMESPACE_
|
_END_GOOGLE_NAMESPACE_
|
||||||
|
@ -792,6 +843,9 @@ int main(int argc, char** argv) {
|
||||||
TemplateDictionaryUnittest::TestSetTemplateGlobalValue();
|
TemplateDictionaryUnittest::TestSetTemplateGlobalValue();
|
||||||
TemplateDictionaryUnittest::TestAddIncludeDictionary();
|
TemplateDictionaryUnittest::TestAddIncludeDictionary();
|
||||||
|
|
||||||
|
TemplateDictionaryUnittest::TestMakeCopy(true); // use our own arena
|
||||||
|
TemplateDictionaryUnittest::TestMakeCopy(false); // use fake arena
|
||||||
|
|
||||||
printf("DONE.\n");
|
printf("DONE.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,17 +47,17 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#if HAVE_DIRENT_H
|
#ifdef HAVE_DIRENT_H
|
||||||
#include <dirent.h> // for opendir() etc
|
# include <dirent.h> // for opendir() etc
|
||||||
#else
|
#else
|
||||||
# define dirent direct
|
# define dirent direct
|
||||||
# if HAVE_SYS_NDIR_H
|
# ifdef HAVE_SYS_NDIR_H
|
||||||
# include <sys/ndir.h>
|
# include <sys/ndir.h>
|
||||||
# endif
|
# endif
|
||||||
# if HAVE_SYS_DIR_H
|
# ifdef HAVE_SYS_DIR_H
|
||||||
# include <sys/dir.h>
|
# include <sys/dir.h>
|
||||||
# endif
|
# endif
|
||||||
# if HAVE_NDIR_H
|
# ifdef HAVE_NDIR_H
|
||||||
# include <ndir.h>
|
# include <ndir.h>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,17 +40,17 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h> // for mkdir
|
#include <sys/stat.h> // for mkdir
|
||||||
#if HAVE_DIRENT_H
|
#ifdef HAVE_DIRENT_H
|
||||||
# include <dirent.h> // for readdir
|
# include <dirent.h> // for readdir
|
||||||
#else
|
#else
|
||||||
# define dirent direct
|
# define dirent direct
|
||||||
# if HAVE_SYS_NDIR_H
|
# ifdef HAVE_SYS_NDIR_H
|
||||||
# include <sys/ndir.h>
|
# include <sys/ndir.h>
|
||||||
# endif
|
# endif
|
||||||
# if HAVE_SYS_DIR_H
|
# ifdef HAVE_SYS_DIR_H
|
||||||
# include <sys/dir.h>
|
# include <sys/dir.h>
|
||||||
# endif
|
# endif
|
||||||
# if HAVE_NDIR_H
|
# ifdef HAVE_NDIR_H
|
||||||
# include <ndir.h>
|
# include <ndir.h>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user