ctemplate-2.2/ 0000755 0001750 0001750 00000000000 11743633635 010347 5 0000000 0000000 ctemplate-2.2/config.sub 0000755 0001750 0001750 00000101153 11743633405 012246 0000000 0000000 #! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
timestamp='2008-01-16'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to A template system can be used to separate output formatting
specifications, which govern the appearance and location of output
text and data elements, from the executable logic which prepares the
data and makes decisions about what appears in the output. Template systems lie along a continuum of power versus separation.
"Powerful" constructs like variable assignment or conditional
statements make it easy to modify the look of an application within
the template system exclusively, without having to modify any of the
underlying "application logic". They do so, however, at the cost of
separation, turning the templates themselves into part of the
application logic. This template system leans strongly towards preserving the
separation of logic and presentation. It is intentionally constrained
in the features it supports and, as a result, applications tend to
require quite a bit of code to instantiate a template. This may not
be to everybody's tastes. However, while this design limits the power
of the template language, it does not limit the power or
flexibility of the template system. This system supports
arbitrarily complex text formatting. Many Google applications,
including the "main" Google web search, use this system
for formatting output. Finally, this system is designed with an eye towards efficiency.
Template instantiation is very quick, with an eye towards minimizing
both memory use and memory fragmentation. There are two main parts to the Ctemplate System: The templates are text files that contain the format specification
for the formatted output, i.e, the template language. The data
dictionaries contain the mappings from the template elements (markers)
embedded in the templates to the data that they will format. Here's
a simple template: Here's a dictionary that one could use to instantiate the template: If we instantiated the template with this dictionary (a process we
call "expanding"), here's the output we would get: A few points are clear even from this simple example: The template language has four major types of markers (the full
list of marker types is described in the reference guide): These marker types each have their own namespace. For readability,
however, it is best to not overuse a single name. Anything found in a template of the form A data dictionary is a map from keys to values. The keys are
always strings, each string representing either a variable, a section,
or a template-include file. (Comments are not stored in the data
dictionary!) These values correspond to the name of the associated
template marker: a section The value associated with a key differs according to key type. The
value associated with a variable is simple: it's the value for
that variable. Both keys and values can be any 8-bit
character-string, and may include internal NULs (\0). The value associated with a section is more complicated, and
somewhat recursive: it's a list of data dictionaries. Come
template-expansion time, the section is expanded once for each
dictionary in the list, so if there are two dictionaries in the list,
then the section text will occur in the output twice. The first time,
all variables/etc. in the section will be evaluated taking into
account the first dictionary. The second time, all
variables/etc. will be evaluated taking into account the second
dictionary. (See below for a definition of
"taking into account.") A template-include is a special type of section, so the
associated value is the same: a list of dictionaries.
Template-includes also have one other, mandatory associated piece of
information: the filename of the template to include. The application program is responsible for building this data
dictionary, including all nesting. It then applies this dictionary to
a single template to produce formatted output. A program using Ctemplate typically reads in templates at
load time. During the course of program execution, the program will
repeatedly perform the following two steps: first, instantiate a data
dictionary, and second, apply the dictionary to the template to
produce output. The template system applies a dictionary to a template by finding
all template markers in the template, and replacing them with the
appropriate dictionary values. It matches template markers to
dictionary keys in the obvious way. For instance, a template marker
If no dictionary key is found for a given template marker, then the
template marker is ignored: if a variable, it expands to the empty
string; if a section or include-template, the section or
include-template is expanded zero times. All names are case sensitive. Names -- that is, variable keys and,
as a result, template markers -- must be made of (7-bit ascii)
alphanumeric characters and the underscore. The comment marker,
which does not map to dictionary keys, may contain any characters
whatsoever except Outside of the template markers, templates may contain any text
whatsoever, including (single) curly braces and NUL characters. The Auto Escape mode helps protect against cross-site scripting
(XSS) attacks in web-applications by automatically escaping variables
in your template. The Guide to using Auto
Escape has an overview of Auto Escape as well as discussion of its
limitations. Auto Escape is enabled on a template-by-template basis. Simply add
the AUTOESCAPE pragma to the desired template. That template will then
be automatically escaped, independently of the templates it may
include or it may be included from. The AUTOESCAPE pragma must be
placed at the top of the template. It takes a 'context' argument
saying what context the template is used in: html, javascript, css,
xml, etc. (There's also a The table below shows four small sample templates along with their
corresponding AUTOESCAPE pragma. The two most common contexts are
How To Use the Ctemplate (formerly Google Template) System
(as of
)
Motivation
Overview
<html><head><title>{{TITLE}}</title>{{META_TAGS}}</head>
<body>{{BODY}}</body></html>
{"TITLE": "Template example",
"BODY": "This is a simple template example.\nIt's boring",
"DATE": "11/20/2005"}
<html><head><title>Template example</title></head>
<body>This is a simple template example.
It's boring</body></html>
{{TITLE}}
and {{BODY}}
are template
elements, also called markers. In the dictionary,
TITLE
, BODY
, and DATE
are
dictionary names, and the values associated with each one, such
as 11/20/2005
, are dictionary values.
DATE
, and to insert the date into the dictionary
already formatted. DATE
is entirely ignored. {{META_TAGS}}
is not found in the
dictionary. This is perfectly legal; missing dictionary names
evaluate to the empty string. Templates
{{FOO}}
{{#FOO}}...{{/FOO}}
{{>FOO}}
{{! comment lives here -- cool, no?}}
{{...}}
is
interpreted as a template marker. All other text is considered
formatting text and is output verbatim at template expansion time.
Formatting text may consist of HTML tags, XML tags, linefeeds and
other spacing characters, constant text, etc. Data Dictionaries
{{#FOO}}
in the template text
is matched to the key "FOO"
in the dictionary, if it
exists. Note the case must match as well.Expanding a Template
{{FOO}}
matches the dictionary key FOO
. The
marker {{#BAR}}
matches the dictionary key
BAR
, as does the marker {{/BAR}}
. The
marker {{>BAZ}}
matches the dictionary key
BAZ
. (And of course, the marker {{!
comment}}
doesn't match any dictionary key at all.)}
, the close-curly brace. It's a
syntax error for any template marker to violate this rule. Auto Escape Mode
state=IN_TAG
argument that is
used when the template is just a snippet of html intended for use in a
tag.) See the reference
guide for a full description of autoescape arguments.HTML
and JAVASCRIPT
. We also show a sample
template for the CSS
context as well as a sample template
for the IN_TAG
state of HTML
(although it is expected to be rarely used).
HTML
JAVASCRIPT
CSS
HTML IN_TAG (uncommon)
{{%AUTOESCAPE context="HTML"}}
<body>
<p>Hello {{USER}}</p>
<p><a href="{{URL}}">Your Account</a></p>
</body>
{{%AUTOESCAPE context="JAVASCRIPT"}}
function showMessage(user, msg) {
alert("Hello: " + user + " Message: " + msg);
}
var user = '{{USER}}';
var msg = '{{MSG}}';
showMessage(user, msg);
{{%AUTOESCAPE context="CSS"}}
P.abstract {
text-align:{{EDGE}};
font-size:{{FONT_SIZE_PC}};
}
.italic {font-style:{{ITALIC}}}
{{%AUTOESCAPE context="HTML" state="IN_TAG"}}
class="{{CLASS}}" id="{{ID}}"
Auto-escaping works by automatically applying modifiers to every variable in the template. You can manually apply modifiers as well, and even define your own. See the reference guide for a full discussion of modifiers and how to use them.
The dictionary structure is a tree: there's a 'main' dictionary, and then a list of sub-dictionaries for each section or include-template. Even with all this complexity, the lookup rules are mostly straightforward: when looking up a marker -- be it a variable, section, or include-template marker -- the system looks in the currently applicable dictionary. If it's found there, great. If not, and the parent dictionary is not an include-template, it continues the look in the parent dictionary, and possibly the grandparent, etc. That is, lookup has static scoping: you look in your dictionary and any parent dictionary that is associated with the same template-file. As soon as continuing the lookup would require you to jump to a new template-file (which is what include-template would do), we stop the lookup.
For instance, for a template that says
{{#RESULTS}}{{RESULTNUM}}. {{>ONE_RESULT}}{{/RESULTS}}
,
"ONE_RESULT"
is looked for in the "RESULTS" dictionary,
and if not found there, is looked for in the main, top-level
dictionary. Likewise, the variable "RESULTNUM"
is looked
for first in the "RESULTS" dictionary, then in the main dictionary if
necessary. However, "ONE_RESULT" will not do equivalent cascading
lookups. In fact, it will have no parent dictionaries at all, because
it's a different template file and thus in a different scope.
Because of these scoping rules, it's perfectly reasonable to set
all variables that are needed in a given template file, in the
top-level dictionary for that template. In fact, the ShowSection()
function is provided to
support just this idiom. To avoid confusion in such a usage mode,
it's strongly encouraged that you give unique names to all sections
and include-templates in a single template file. (It's no problem,
given the template scoping rules, for a single section or
include-template name to be repeated across different template
files.)
There's a single special case: the global variable dictionary. Every dictionary inherits its initial set of values from the global dictionary. Clients can set variables in the global dictionary just like they can in normal template dictionaries they create.
The system initializes the global dictionary with a few useful
values for your convenience. All system variables are prefixed with
BI
, to emphasize they are "built in" variables.
BI_SPACE
, which has the value
<space>
. It is used to force a space
at the beginning or end of a line in the template,
where it would normally be suppressed. (See below.) BI_NEWLINE
, which has the value
<newline>
It is used to force a
newline at the end of a line, where it would normally
be suppressed. (See below.) As is usual for inheritance, if a user explicitly assigns a value
to these variable-names in its own dictionary, this overrides the
inherited value. So, dict->SetValue("BI_SPACE",
" ")
causes BI_SPACE
to have the value
, rather than <space>
, when
expanding dict
.
Note that only variables can be inherited from the global dictionary, not section dictionaries or include-file dictionaries.
A couple of small implementation notes: global inheritance is "last
chance", so if a section's parent dictionary redefined
BI_SPACE
, say, the section dictionary inherits the
parent-dict value, not the global-dict value. Second, variable
inheritance happens at expand time, not at dictionary-create time. So
if you create a section dictionary, and then afterwards set a variable
in its parent dictionary (or in the global dictionary), the section
will inherit that variable value, if it doesn't define the
value itself.
Most application code concerns filling a template dictionary, but there is also code for expanding templates given a dictionary. A final category of code lets you inspect and control the template system.
The class TemplateDictionary
is used for all template
dictionary operations. new ctemplate::TemplateDictionary(name)
is
used to create a new top-level dictionary.
dict->AddSectionDictionary(name)
and
dict->AddIncludeDictionary(name)
are used to create
sub-dictionaries for sections or include-files. After
creating a dictionary, the application should call one or more
functions for each marker in the template. As an example, consider
the following template:
<html><body> {{! This page has no head section.}} {{#CHANGE_USER}} <A HREF="/login">Click here</A> if you are not {{USERNAME}}<br> {{/CHANGE_USER}} Last five searches:<ol> {{#PREV_SEARCHES} <li> {{PREV_SEARCH}} {{/PREV_SEARCHES}} </ol> {{>RESULT_TEMPLATE}} {{FOOTER}} </body></html>
To instantiate the template, the user should call a function to set
up FOOTER
, and a function to say what to do for the
sections CHANGE_USER
and PREV_SEARCHES
, and
for the include-template RESULT_TEMPLATE
. Quite likely,
the application will also want to create a sub-dictionary for
CHANGE_USER
, and in that sub-dictionary call a function
to set up USERNAME
. There will also be sub-dictionaries
for PREV_SEARCHES
, each of which will need to set
PREV_SEARCH
. Only when this is all set up will the
application be able to apply the dictionary to the template to get
output.
The appropriate function to call for a given template marker depends on its type.
For variables, the only interesting action is to set the variable's
value. For most variables, the right method to call is
dict->SetValue(name, value)
. (The name and value
can be specified as strings in a variety of ways: C++ strings, char
*'s, or char *'s plus length.)
There are two other ways to set a variable's value as well, each
with a different scoping rule. You can call
ctemplate::TemplateDictionary::SetGlobalValue(name, value)
-- no TemplateDictionary
instance needed here -- to set a
variable that can be used by all templates in an application. This
is quite rare.
You can also call dict->SetTemplateGlobalValue(name,
value)
. This sets a variable that is seen by all child
dictionaries of this dictionary: sub-sections you create via
AddSectionDictionary
, and included templates you create
via AddIncludeDictionary
(both described below). This
differs from SetValue()
, because SetValue()
values are never inherited across template-includes. Almost always,
SetValue
is what you want;
SetTemplateGlobalValue
is intended for variables that are
"global" to a particular template tree not all template trees, such as
a color scheme to use, a language code, etc.
To make it easier to use SetValue()
, there are a few
helper routines to help setting values of a few special forms.
SetIntValue(name, int)
: takes an int as the value. SetFormattedValue(name, fmt, ...)
: the
fmt
and ...
work just like in
printf
: SetFormattedValue("HOMEPAGE",
"http://%s/", hostname)
. Example:
ctemplate::TemplateDictionary* dict = new ctemplate::TemplateDictionary("var example"); dict->SetValue("FOOTER", "Aren't these great results?");
Sections are used in two ways in templates. One is to expand some
text multiple times. This is how PREV_SEARCHES
is used
in the example above. In this case we'll have one small
sub-dictionary for each of the five previous searches the user did.
To do this, call AddSectionDictionary(section_name)
to create the sub-dictionary. It returns a
TemplateDictionary*
that you can use to fill the
sub-dictionary.
The other use of sections is to conditionally show or hide a block
of text at template-expand time. This is how CHANGE_USER
is used in the example template: if the user is logged in, we show the
section with the user's username, otherwise we choose not to show the
section.
This second case is a special case of the first, and the "standard"
way to show a section is to expand it exactly one time, by calling
AddSectionDictionary()
once, and then setting
USERNAME
in the sub-dictionary.
However, the hide/show idiom is so common there are a few
convenience methods to make it simpler. The first takes advantage of
the fact sections inherit variables from their parent: you set
USERNAME
in the parent dictionary, rather than a section
sub-dictionary, and then call ShowSection()
, which adds a
single, empty dictionary for that section. This causes the section to
be shown once, and to inherit all its variable values from its
parent.
A second convenience method is written for the particular case we
have with USERNAME
: if the user's username is non-empty,
we wish to
show the section with USERNAME
set to the username,
otherwise we wish to hide the section and show neither
USERNAME
nor the text around it. The method
SetValueAndShowSection(name, value, section_name)
does
exactly that: if value is non-empty, add a single dictionary to
section_name
and call section_dict->AddValue(name,
value)
.
Example:
ctemplate::TemplateDictionary* dict = new ctemplate::TemplateDictionary("section example"); const char* username = GetUsername(); // returns "" for no user if (username[0] != '\0') { ctemplate::TemplateDictionary* sub_dict = dict->AddSectionDictionary("CHANGE_USER"); sub_dict->SetValue("USERNAME", username); } else { // don't need to do anything; we want a hidden section, which is the default } // Instead of the above 'if' statement, we could have done this: if (username[0] != '\0') { dict->ShowSection("CHANGE_USER"); // adds a single, empty dictionary dict->SetValue("USERNAME", username); // take advantage of inheritance } else { // don't need to do anything; we want a hidden section, which is the default } // Or we could have done this: dict->SetValueAndShowSection("USERNAME", username, "CHANGE_USER"); // Moving on... GetPrevSearches(prev_searches, &num_prev_searches); if (num_prev_searches > 0) { for (int i = 0; i < num_prev_searches; ++i) { TemplateDictionary* sub_dict = dict->AddSectionDictionary("PREV_SEARCHES"); sub_dict->SetValue("PREV_SEARCH", prev_searches[i]); } }
Template-include markers are much like section markers, so
AddIncludeDictionary(name)
acts, not surprisingly,
exactly like AddSectionDictionary(name)
. However, since
variable inheritance doesn't work across include boundaries, there is
no template-include equivalent to ShowSection()
or
SetValueAndShowSection()
.
One difference between template-includes and sections is that for a
sub-dictionary that you create via
AddIncludeDictionary()
, you must call
subdict->SetFilename()
to indicate the name of the
template to include. If you do not set this, the sub-dictionary will
be ignored. The filename may be absolute, or relative, in which case
it's relative to some entry in the template search path.
Example:
using ctemplate::TemplateDictionary; TemplateDictionary* dict = new TemplateDictionary("include example"); GetResults(results, &num_results); for (int i = 0; i < num_results; ++i) { TemplateDictionary* sub_dict = dict->AddIncludeDictionary("RESULT_TEMPLATE"); sub_dict->SetFilename("results.tpl"); FillResultsTemplate(sub_dict, results[i]); }
In practice, it's much more likely that
FillResultsTemplate()
will be the one to call
SetFilename()
. Note that it's not an error to call
SetFilename()
on a dictionary even if the dictionary is
not being used for a template-include; in that case, the function is a
no-op, but is perhaps still useful as self-documenting code.
Another property of template-includes is that they set the indentation level
for the included template, that is, every line in the included template is
indented by the same amount as the template-includes line itself. For
instance, if you have a template PRINT_STUFF
like this:
print "Hello!" print "You are the 10th caller!" print "Congratulations!"
and you include it in the template:
if ShouldPrintStuff(): {{>PRINT_STUFF}} else: pass
then when it is expanded, all three print lines will be indented, not just the first one:
if ShouldPrintStuff(): print "Hello!" print "You are the 10th caller!" print "Congratulations!" else: pass
Note that this behavior is immaterial when using STRIP_WHITESPACE
, since in that case
all leading whitespace is stripped.
Once you have a template dictionary, it's simplicity itself to expand the template with those dictionary values, putting the output in a string:
ctemplate::TemplateDictionary dict("debug-name"); FillDictionary(&dict, ...); string output; bool error_free = ctemplate::ExpandTemplate(<filename>, ctemplate::STRIP_WHITESPACE, &dict, &output); // output now holds the expanded template. // ExpandTemplate returns false if the system cannot load-and-parse // <filename> or any of the template files referenced by the // TemplateDictionary.
The first argument to ExpandTemplate
is the filename
holding the template to expand (though there are ways to use non-file-based templates as well). The second argument
is the "strip" mode, which specifies how to treat whitespace in the
template. It can take the following values:
ctemplate::DO_NOT_STRIP
: do nothing. This expands
the template file verbatim.
ctemplate::STRIP_BLANK_LINES
: remove all blank
lines. This ignores any blank lines found in the template file
when parsing it. When the template is html, this reduces the
size of the output text without requiring a sacrifice of
readability for the input file.
ctemplate::STRIP_WHITESPACE
: remove not only blank
lines when parsing, but also whitespace at the beginning and
end of each line. It also removes any linefeed (possibly
following whitespace) that follows a closing }}
of
any kind of template marker except a template variable.
(This means a linefeed may be removed anywhere by simply
placing a comment marker as the last element on the line.)
When the template is html, this reduces the size of the output
html without changing the way it renders (except in a few
special cases.) When using this flag, the built-in template
variables BI_NEWLINE
and BI_SPACE
can
be useful to force a space or newline in a particular
situation.
The expanded template is written to the string output
.
If output
was not empty before calling
Expand()
, the expanded template is appended to the end of
output
.
There is also a "power user" version of
ExpandTemplate()
, called ExpandWithData()
,
that allows you to pass in per-expand data. Another "power user"
version allows you to expand the template into a custom output
container, rather than a string. See the reference guide for more
information about these advanced methods.
The first argument to ExpandTemplate
is named
"filename", suggesting that the template has to be read from an
on-disk file. But in reality, the "filename" argument is just a key
into an internal cache. (By default, the template system looks on
disk to satisfy a cache miss, hence the "filename" to describe this
variable.) If you have a template specified in a string rather than a
file, you can manually insert it into the cache via
ctemplate::StringToTemplateCache()
.
StringToTemplateCache()
parses the string you pass in
as if it were a template file, and inserts it into the global cache
with the key and strip-mode that you provide. You can then use this
key and strip-mode as the first two arguments to
ExpandTemplate
. You can also use the key as the argument
to ctemplate::TemplateDictionary::SetFilename()
.
Prefer file-based to string-based templates where possible. Updating a file-based template requires merely a data push, rather than pushing the new executable, and it also makes it easier for non-programmers to modify the template. One reason to use string-based templates is if you are in an environment where having data files could be dangerous—for instance, you work on a disk that is usually full, or need the template to work even in the face of disk I/O errors.
This package comes with a script, template-converter, that
takes a template file as input and emits a C++ code snippet (an .h
file) that defines a string with those template contents. This makes
it easy to start by using a normal, file-based template, and then
switch to StringToTemplateCache()
later if you so
desire.
You can use the MakeCopy()
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
MakeCopy()
to do it:
newdict1 = dict->MakeCopy();
newdict2 = dict->MakeCopy();
When templates are loaded from disk, they are stored in an internal
template cache, which is used by ExpandTemplate()
and
(most obviously) StringToTemplateCache()
. You can define
your own template cache with the TemplateCache
class.
This is an advanced technique used when you want to support having several versions of a template file in memory at the same time (for instance, a webserver might want to keep an old version of a template file around until all old requests using that template are done being serviced). It also supports advanced operations like removing a template from the cache, and reloading templates from disk if they have changed.
See the reference manual for more details about the template cache.
All expansion functions and static TemplateDictionary
methods are threadsafe: you can safely call
ctemplate::TemplateDictionary::SetGlobalValue()
without needing to worry about locking.
Non-static TemplateDictionary
methods are not
thread-safe. It is not safe for two threads to assign values to the
same template-dictionary without doing their own locking. Note that
this is expected to be quite rare: usually only one thread will care
about a given template-dictionary.
Templates have the advantage that they separate the presentation of your data from the application logic that generates the data. Naturally, you want to do the same for testing: you would like to test the application's logic in a way that is robust to changes in the presentation.
The easiest way to test this logic is with unit tests that exercise
the functions in your code that fill template dictionaries. The class
ctemplate::TemplateDictionaryPeer
in
template_test_util.h
is designed to help you do exactly
that.
Here's a sample test using TemplateDictionaryPeer
:
void MyTestMethod() { // Create and populate the dictionary as your app normally would. // In this case, we create a dict with data like this: // { color:blue, // shape_section: [ // { size:big, num_sides:7 }, // { size:big, num_sides:7 }, // { size:big, num_sides:7 } // ] // } MyObject obj; ctemplate::TemplateDictionary dict; obj.FillDictionary(&dict); // Create a TemplateDictionaryPeer to gain access to the dict contents. ctemplate::TemplateDictionaryPeer peer(&dict); // Expect color:blue at the top level of this dictionary. EXPECT_STREQ("blue", peer.GetSectionValue("color")); // Fetch sub-dictionaries from the dict. vector<const ctemplate::TemplateDictionary*> shape_dicts; peer.GetSectionDictionaries("shape_section", &shape_dicts); EXPECT_EQ(3, shape_dicts.size()); for (int i = 0; i < 3; ++i) { // Create another peer for each sub-dict, and assert that each sub-dict // contains the expected data. ctemplate::TemplateDictionaryPeer shape_peer(dicts[i]); EXPECT_STREQ("big", shape_peer.GetSectionValue("size")); EXPECT_STREQ("7", shape_peer.GetSectionValue("num_sides")); } }
Note that by using TemplateDictionaryPeer
, you can
unit test the code for filling a TemplateDictionary
independent of the consuming Template
.
The above tests your dictionary filling functions, but doesn't touch the template expansion. Naturally, you may also want to test the template itself. In this case, you will want to avoid using your program's dictionary filling functions, and will instead provide a custom dictionary in your test. There are a variety of properties you might want to test about the template, but here are a few sample tests:
void TestTemplateHTMLEscapesColor() { // Populate a dictionary that lets us exercise the condition we're testing. // In this case, that the 'color' tag will be HTML escaped. ctemplate::TemplateDictionary dict("t1"); dict.SetValue("color", "<blue>"); // Expand the template with this dictionary. string result; ctemplate::ExpandTemplate(FLAGS_test_srcdir + "templates/my_template.html", ctemplate::STRIP_WHITESPACE, &dict, &result); // Assert that the expansion has the appropriate text in it. EXPECT_THAT(result, HasSubstr("<blue>")); } void TestColorAppearsBeforeShape() { // This time, the condition under test is that the "color" element of // the dictionary appears before the "shape" element. // Create an appropriate dictionary. ctemplate::TemplateDictionary dict("t2"); // Note: use sufficiently unique dict.SetValue("color", "white_asdf"); // strings that they won't occur dict.SetValue("shape", "square_asdf"); // "bare" in the template. string result; ctemplate::ExpandTemplate(FLAGS_test_srcdir + "templates/my_template.html", ctemplate::STRIP_WHITESPACE, &dict, &result); // Assert that color comes before shape. EXPECT_THAT(result, ContainsRegex("white_asdf.*square_asdf")); }
Like all web applications, programs that use the Ctemplate
System to create HTML documents can be vulnerable to
Cross-Site-Scripting (XSS) attacks unless data inserted into a
template is appropriately sanitized and/or escaped. Which specific
form of escaping or sanitization is required depends on the context in
which the template variable appears within a HTML document (such as,
regular "inner text", within a <script>
tag, or
within an onClick
handler).
If you are concerned with XSS, your are strongly encouraged to leverage the Auto Escape mode developed specifically to better defend your application against XSS. The Auto Escape mode follows the guidelines outlined below. Do note however that regardless of whether you use Auto Escape or not, escaping alone while generally required, is often not enough! You also may need to sanitize or validate the input, as for instance with URL attributes. For further information, refer to additional resources on Cross-Site-Scripting issues.
The remainder of this section provides a brief summary of techniques to prevent XSS vulnerabilities due to template variables in various HTML contexts.Use the auto-escape pragma to html-escape the variable.
In addition to the auto-escape pragma, ensure that the attribute is enclosed in double quotes in the template.
In addition to the auto-escape pragma, ensure that the attribute is enclosed in double quotes in the template.
style
tag or
attribute.
Certain CSS style-sheet constructs can result in the invocation of javascript. To prevent XSS, the variable must be carefully validated and sanitized.
In addition to the auto-escape pragma, ensure that the literal is enclosed in quotes in the template:
<script> var msg_text = '{{MESSAGE}}'; </script>
Literals of non-string types cannot be quoted and escaped. Instead, ensure that the variable's value is set such that it is guaranteed that the resulting string corresponds to a javascript literal of the expected type. For example, use
dict->SetValueInt("NUM_ITEMS", num_items);
to populate an integer javascript variable in the template fragment
<script> var num_items = {{NUM_ITEMS}}; </script>
onClick
.
Tag attributes whose values are evaluated as a javascript
expression (such as on{Click,Load,etc}
handlers)
generally require HTML-Escape in addition to Javascript-Escape,
since the attribute's value is HTML-unescaped by the browser
before it is passed to the javascript interpreter.
However, the javascript-escaping provided by auto-escape makes a subsequent HTML-Escape unnecessary. As such you can apply the same rules for variables within event handlers as you would for javascript variables in string literals:
<button ... onclick='GotoUrl("{{TARGET_URL}}");'>
There are a number of scenarios in which XSS can arise that are unrelated to the insertion of values into HTML templates, including,
Location
,charset
,Content-Type
,Content-Disposition: attachment
).Please consult additional documentation on Cross-Site-Scripting for more detailed discussion of such issues.
Both dictionary keys and template filenames are strings. Instead of using raw strings, we encourage you to use a bit of machinery to help protect against various types of errors.
For dictionary keys, you can use the make_tpl_varnames_h tool to create static string variables to use instead of a string constant. This will protect against typos, as the make_tpl_varnames_h documentation describes. It also yields slightly more efficient code.
For template filenames that a program uses -- including sub-templates -- we suggest the following idiom:
#include "example.tpl.varnames.h" // defines 1 string per dictionary key RegisterTemplateFilename(EXAMPLE_FN, "example.tpl"); // defines template ... include_dict->SetFilename(EXAMPLE_FN); ... ctemplate::ExpandTemplate(EXAMPLE_FN, ctemplate::DO_NOT_STRIP, ...); ...
By registering the filename, you can query the template system to detect syntax errors, reload-status, and so forth.
There are methods to change the global state of the template system, to examine templates, and to examine template dictionaries. See the reference guide for more information.
This document has split into two parts: a user's guide and a reference guide. Use the links below to see these, and other documents about the template system.
One reason this example is so simple is that it doesn't even
require a separate template file, but instead uses
StringToTemplateCache()
. It also doesn't use sections or
template-includes.
int main() { static const char template_text[] = "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n"; ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP); FILE* fp = fopen(argv[1], "r"); if (fp == NULL) { int err_no = errno; // squirrel this away ctemplate::TemplateDictionary dict("error_msg: fopen()"); dict.SetValue("FUNCTION", "fopen"); dict.SetValue("ARGS", argv[1]); dict.SetIntValue("ERROR_CODE", err_no); dict.SetValue("ERROR_MESSAGE", strerror(err_no)); string error_text; ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text); puts(error_text.c_str()); } }Note: If this template was intended to run in a web application, you can leverage the functionality provided by the auto-escape mode. Simply add the AUTOESCAPE pragma directive at the top of the template text and your variables will be automatically escaped for the context you specify. For example, if your template is returned in an HTML context, change the
template_text
declaration as follows:
static const char template_text[] = "{{%AUTOESCAPE context=\"HTML\"}}" "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
This example is only slightly more complicated: we only print the ": <error message>" part when the error message isn't the empty string.
int main() { static const char template_text[] = "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}" "{{#MSG_SECTION}}: {{ERROR_MESSAGE}}{{/MSG_SECTION}}\n"; ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP); FILE* fp = fopen(argv[1], "r"); if (fp == NULL) { int err_no = errno; // squirrel this away ctemplate::TemplateDictionary dict("file_error_message"); dict.SetValue("FUNCTION", "fopen"); dict.SetValue("ARGS", argv[1]); dict.SetIntValue("ERROR_CODE", err_no); if (err_no > 0) dict.SetValueAndShowSection("ERROR_MESSAGE", strerror(err_no), "MSG_SECTION"); string error_text; ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text); puts(error_text.c_str()); } delete tpl; }
This maybe-show-text functionality is one way the template
machinery is more powerful than just using printf
.
Another nice property of templates is you can reuse the same variable
multiple times in your template string. You can also define the
variable values in any order.
Here is an example template that could be used to format a Google search results page:
{{>HEADER}} <body bgcolor=white> {{>PAGE_HEADING}}{{!The following div must be on the same line}}<div> {{!The ONE_RESULT section displays a single search item}} {{#ONE_RESULT}} {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}} {{#SUBITEM_SECTION}}<blockquote>{{/SUBITEM_SECTION}} {{! LEAD_LINE is received HTML-escaped from the backend.}} <p><a href="{{JUMP_TO_URL:html_escape}}" target=nw>{{LEAD_LINE}}</a><font size=-1> {{! SNIPPET1, SNIPPET2 are HTML-escaped in the snippet generator.}} {{#SNIPPET1_SECTION}} <br>{{SNIPPET1}} {{/SNIPPET1_SECTION}} {{#SNIPPET2_SECTION}} <br>{{SNIPPET2}} {{/SNIPPET2_SECTION}} {{#DESCRIPTION_SECTION}} {{! DESC is received HTML-escaped from the backend.}} <br><span class=f>Description:</span> {{DESC}} {{/DESCRIPTION_SECTION}} {{#CATEGORY_SECTION}} <br><span class=f>Category:</span> <a href="{{CAT_URL:html_escape}}" class=f> {{CATEGORY:html_escape}}</a> {{/CATEGORY_SECTION}} {{#LASTLINE_SECTION}} <br><font color="{{ALT_TEXT_COLOR:h}}">{{URL:h}} {{#KS_SECTION}}} - {{KSIZE:h}}{{/KS_SECTION}}} {{#CACHE_SECTION}}} - <a href="{{CACHE_URL:h}}" class=f>Cached</A> {{/CACHE_SECTION}}} {{#SIM_SECTION}}} - <a href="{{SIM_PAGES_URL:h}}" class=f>Similar pages</A> {{/SIM_SECTION}}} {{#STOCK_SECTION}} - <a href="{{STOCK_URL:h}}" class=f>Stock quotes: {{STOCK_SYMBOL:h}}</a> {{/STOCK_SECTION}} </font> {{/LASTLINE_SECTION}} {{#MORE_SECTION}} <br>[ <a href="{{MORE_URL:h}}" class=f>More results from {{MORE_LABEL:h}}</a> ] {{/MORE_SECTION}} </font><br> {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}} {{#SUBITEM_SECTION}}</blockquote>{{/SUBITEM_SECTION}} {{/ONE_RESULT}} </div> {{! this /div closes the div at the top of this file}} {{>PAGE_FOOTING}}
Here is a sample procedure that could populate a dictionary for
expanding that template. The "one procedure" entry point is
fill_search_results_dictionary
. The
SetTemplateValues
function is a separate entry point for
initializing each top-level template with some standard values.
#include "template.h" RegisterTemplateFilename(SEARCH_RESULTS_FN, "search_results.tpl"); #include "search_results.tpl.varnames.h" // defines ksr_HEADER, etc. using ctemplate::TemplateDictionary; using ctemplate::ExpandTemplate; using ctemplate::STRIP_WHITESPACE; // IsEmpty // A simple utility function static bool IsEmpty(const string &str) { return str.empty(); } // SetTemplateValues // Use the TemplateDictionary object to set template-wide values that // may be used in the top-level template and all its sub-sections // and included templates. The template-wide values are all // colors from the Palette object void SetTemplateValues(TemplateDictionary *dictionary, const Palette* colors) { // better would be to use ksr_LINK_COLOR, etc, assuming those are // defined in search_results.tpl.varnames.h. But using literal // text, as here, is legal as well. dictionary->SetValue("LINK_COLOR", colors->link_color); dictionary->SetValue("BAR_TEXT_COLOR", colors->bar_text_color); dictionary->SetValue("TEXT_COLOR", colors->text_color); dictionary->SetValue("FAINT_COLOR", colors->faint_color); dictionary->SetValue("IMPORTANT_COLOR", colors->important_color); dictionary->SetValue("BAR_COLOR", colors->bar_color); dictionary->SetValue("ALT_TEXT_COLOR", colors->alt_text_color); dictionary->SetValue("ALINK_COLOR", colors->alink_color); dictionary->SetValue("VLINK_COLOR", colors->vlink_color); } // fill_search_results_dictionary // Iterates through all the QueryResults contained in the Query object. // For each one, it sets corresponding template dictionary values // (or hides sections containing their variables, if appropriate) in // a sub-dictionary and then adds that dictionary to the parent void fill_search_results_dictionary(TemplateDictionary *dictionary, const Query *query) { dictionary->SetFilename(SEARCH_RESULTS_FN); // These two functions are defined elsewhere fill_header_dictionary(dictionary->AddIncludeDictionary(ksr_HEADER)); fill_page_heading_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_HEADING), query); ResultsList *results = query->GetResults(); int resCount = 0; for (ResultsList::const_iterator iter = results->begin(); iter != results->end(); ++iter) { QueryResult *qr = (*iter); // Create a new sub-dictionary named "Result Dict <n>" for this entry ++resCount; TemplateDictionary *result_dictionary = dictionary->AddSectionDictionary(ksr_ONE_RESULT); result_dictionary->SetValue(ksr_JUMP_TO_URL, qr->GetUrl()); if (qr->IsSubItem()) { result_dictionary->ShowSection(ksr_SUBITEM_SECTION); } result_dictionary->SetValue(ksr_LEAD_LINE, qr->GetLeadLine()); result_dictionary->SetValueAndShowSection(ksr_SNIPPET1, qr->GetSnippet1(), ksr_SNIPPET1_SECTION); result_dictionary->SetValueAndShowSection(ksr_SNIPPET2, qr->GetSnippet2(), ksr_SNIPPET2_SECTION); result_dictionary->SetValueAndShowSection(ksr_DESC, qr->GetDescription(), ksr_DESCRIPTION_SECTION); result_dictionary->SetValueAndShowSection(ksr_CAT_URL, qr->GetCategoryUrl(), ksr_CATEGORY_SECTION); result_dictionary->SetValueAndShowSection("CATEGORY", qr->GetCategoryName(), "CATEGORY_SECTION"); if (IsEmpty(qr->GetDisplayUrl()) && IsEmpty(qr->GetPageSize()) && IsEmpty(qr->GetCachedUrl()) && IsEmpty(qr->GetSimilarPagesUrl()) && (IsEmpty(qr->GetStockUrl()) || IsEmpty(qr->GetStockSymbol())) ) { // there is nothing on the last line, so hide it altogether } else { result_dictionary->ShowSection("LASTLINE_SECTION"); result_dictionary->SetValue(ksr_URL, qr->GetDisplayUrl()); result_dictionary->SetValueAndShowSection(ksr_KSIZE, qr->GetPageSize(), ksr_KS_SECTION); result_dictionary->SetValueAndShowSection(ksr_CACHE_URL, qr->GetCachedUrl(), ksr_CACHE_SECTION); result_dictionary->SetValueAndShowSection(ksr_SIM_PAGES_URL, qr->GetSimilarPagesUrl(), ksr_SIM_SECTION); result_dictionary->SetValueAndShowSection(ksr_STOCK_URL, qr->GetStockUrl(), ksr_STOCK_SECTION); result_dictionary->SetValueAndShowSection(ksr_STOCK_SYMBOL, qr->GetStockSymbol(), ksr_STOCK_SECTION); } result_dictionary->SetValueAndShowSection(ksr_MORE_URL, qr->GetMoreUrl(), ksr_MORE_SECTION); result_dictionary->SetValueAndShowSection(ksr_MORE_LABEL, qr->GetMoreLabel(), ksr_MORE_SECTION); } fill_page_footing_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_FOOTING), query); } void output_page(const Query* query) { TemplateDictionary dict("search-results dict"); string output; fill_search_results_dictionary(&dict, query); ctemplate::ExpandTemplate(SEARCH_RESULTS_FN, STRIP_WHITESPACE, &dict, &output); // output now holds the expanded template }
tag for bits of code and for variables and objects. */
code,pre,samp,var {
color: #006000;
}
/* Use the tag for file and directory paths and names. */
file {
color: #905050;
font-family: monospace;
}
/* Use the tag for stuff the user should type. */
kbd {
color: #600000;
}
div.note p {
float: right;
width: 3in;
margin-right: 0%;
padding: 1px;
border: 2px solid #6060a0;
background-color: #fffff0;
}
UL.nobullets {
list-style-type: none;
list-style-image: none;
margin-left: -1em;
}
/* pretty printing styles. See prettify.js */
.str { color: #080; }
.kwd { color: #008; }
.com { color: #800; }
.typ { color: #606; }
.lit { color: #066; }
.pun { color: #660; }
.pln { color: #000; }
.tag { color: #008; }
.atn { color: #606; }
.atv { color: #080; }
pre.prettyprint { padding: 2px; border: 1px solid #888; }
.embsrc { background: #eee; }
@media print {
.str { color: #060; }
.kwd { color: #006; font-weight: bold; }
.com { color: #600; font-style: italic; }
.typ { color: #404; font-weight: bold; }
.lit { color: #044; }
.pun { color: #440; }
.pln { color: #000; }
.tag { color: #006; font-weight: bold; }
.atn { color: #404; }
.atv { color: #060; }
}
/* Table Column Headers */
.hdr {
color: #006;
font-weight: bold;
background-color: #dddddd; }
.hdr2 {
color: #006;
background-color: #eeeeee; } ctemplate-2.2/doc/auto_escape.html 0000644 0001750 0001750 00000037006 11743633404 014212 0000000 0000000
Guide to using Auto Escape
Guide to using Auto Escape
Introduction
Auto Escape is an optional mode of execution in the Template System
developed to provide a better defense against cross-site scripting (XSS)
in web applications. In this mode, the Template System assumes
responsibility for applying the proper escaping modifiers for each
variable in your template (and templates it may include). As such, the
template developer no longer needs to manually apply escaping modifiers
to each variable, a process which is repetitive and error-prone
particularly in larger and more complex applications.
In order for the Template System to properly determine the escaping
modifiers to apply to variables, it activates a built-in HTML-aware
parser during template initialization. The parser scans the template
to determines the context in which each variable is being emitted.
The scanning is performed at initialization-time only hence does not
contribute to processing costs at template expansion time.
Refer to Security Considerations
for additional security information on escaping directives and their
use according to the context in which content is being expanded.
Current Status
Auto Escape currently supports well HTML
and
Javascript
templates. It also provides very basic support
for CSS
, JSON
and XML
templates
where it applies the corresponding escaping modifier but without
utilizing a parser. We may in the future provide parsers specific
to these contexts and modifiers for them that are finer-grained.
Overview
This section provides more background on Auto Escape.
Refer to How to Auto Escape
for information on how to leverage this mode in your application.
Using template modifiers
In the simplest case, where you only want to use template-modifiers
to achieve html-safety (that is, you only use
html_escape
, url_query_escape
, and so
forth), you can stop specifying template-modifiers in your template at
all. The Auto Escape mode will generate the modifiers on its own and
perform the correct escaping.
If you need other types of modifiers, including your own custom
modifiers, you can still specify them in your template and they will
continue to work just the same. The Auto Escape mode will simply apply
the appropriate escaping modifiers after your own.
Other reasons for manually specifying variable modifiers include:
- To indicate a variable is safe. You may add the
:none
modifier as the last modifier for a given
variable, in which case the Auto Escape mode will leave it
untouched and not apply escaping directives to it. Use only
when you are sure the variable is trusted to be safe from XSS.
- To select a different escaping modifier from a list of
equivalent modifiers. Certain modifiers are equivalent from
an escaping point of view in that they would all ensure given
content is safe when escaped in a specific context. The
Auto Escape mode choses the most common escaping modifier for
that use but allows you to indicate a different choice as shown
below:
TemplateContext Primary Modifier
Accepted alternatives
TC_HTML
:html_escape
:pre_escape
:html_escape_with_arg=snippet
:html_escape_with_arg=attribute
:html_escape_with_arg=url
:url_query_escape
:url_escape_with_arg=html
:img_src_url_escape_with_arg=html
TC_HTML
and TC_CSS
:cleanse_css
:url_escape_with_arg=css
:img_src_url_escape_with_arg=css
TC_XML
:xml_escape
:html_escape
:html_escape_with_arg=attribute
TC_JS
:javascript_escape
:url_escape_with_arg=javascript
:img_src_url_escape_with_arg=javascript
TC_JSON
:javascript_escape
:json_escape
- To add additional escaping modifiers. The Template System will
never remove escaping directives you explicitly specify.
Escaping Contexts
The table belows indicates which modifier Auto-Escape selects to
escape a given variable, based on the context of the variable being
inserted and, possibly, on more specific information such as whether
the variable is inside quotation marks. The table only applies for
the well-supported TemplateContext values (currently
TC_HTML
and TC_JS
).
In a few cases, we do not have
a modifier that is both safe against XSS and respecting of
the semantics of the variable therefore we fail the template
initialization. An error is logged indicating the cause of
the failure.
Context HTML Quoted?
Examples Action Performed
Regular HTML Body and HTML comments Any
<p>Hello {{USER}}</p>
Escape USER
using
:html_escape
In URL attribute: Starts at pos 0 Yes
<a href="{{URL}}">;
Escape URL
using
:url_escape_with_arg=html
In URL attribute: Other Yes
<a href="/foo?q={{QUERY}}">
Escape QUERY
using
:html_escape
In URL attribute: Starting at pos 0 No
<form action={{URL}}>
Fail template initialization
In URL attribute: Other No
<a href=/foo?q={{QUERY}}>My Link</a>
Escape QUERY
using
:url_query_escape
In STYLE attribute Yes
<div style="color:{{COLOR}};">
Escape COLOR
using
:cleanse_css
In STYLE attribute No
<div style=color:{{COLOR}};>
Fail template initialization
In Javascript attribute: String literal Yes
<a href="url" onclick="doFoo('{{ARG}}');">
Escape ARG
using
:javascript_escape
In Javascript attribute: Non-string literal Yes
<a href="url" onclick="doFoo({{ARG}});">
Escape ARG
using
:javascript_escape_with_arg=number
In Javascript attribute: Any No
<a href="url" onclick=doFoo('{{ARG}}');>
Fail template initialization.
In all other attributes Yes
<b class="{{CLASS}}">
Escape CLASS
using
:html_escape
In all other attributes No
<table border={{BORDER}}>
Escape BORDER
using
:html_escape_with_arg=attribute
In Javascript code: In a string literal Any
<script>var a = '{{VALUE}}';</script>
Escape VALUE
using
:javascript_escape
In Javascript code: Non-string literal Any
<script>var a = {{VALUE}};</script>
Escape VALUE
using
:javascript_escape_with_arg=number
In a <style> tag Any
<style>font-size={{FONTSIZE}};</style>
Escape FONTSIZE
using
:cleanse_css
Comments:
- For values of URL-accepting attributes, we apply a different
modifier if the variable is at the beginning of the attribute
value or not because in the former case we consider the
variable to represent a complete URL and hence also check
that its scheme is safe (
HTTP
or
HTTPS
).
- We recommend that you enclose attribute values in quotes
in particular:
- Under some conditions outlined in the table above, when
variables are present in attribute values that are not
enclosed in quotes, we may fail template initialization
because we do not have escaping modifiers that are safe to
use.
- Also the determination of which escaping modifier
to apply for unquoted attribute values specifically
is likely to change in the future.
The Auto Escape mode is designed to be simple to use and to produce
correct correct escaping with minimal input. It does however come with
restrictions governing the use of this template system.
Limitations
-
Templates may only be included in regular HTML
text. Including a template within HTML comments or inside an
HTML tag is currently not supported. In the example below,
HEADER
and FOOTER
are properly
included but TAG
and COMMENT
are
not.
<html><head>{{>HEADER}}</head><body>
<{{>TAG}}>
<p>
<!-- {{>COMMENT}} -->
<p>{{>FOOTER}}
</body></html>
If the template system detects that you are including a
template in another HTML context, it will log a warning.
-
Included templates may not cross HTML boundaries. They
cannot start with one TemplateContext
and end in
another. For example, the template below crosses boundaries --
it starts in HTML and ends in Javascript -- and is therefore
not a valid included template for auto-escaping.
<html>
<head>
</head>
<body>
Hello USER.
<script>
var a = 'not a nice template';
To rectify this violation, continue the template by
completing the javascript code and terminating it with a
</script>
tag.
-
Error reporting. We currently report errors by logging
a warning or an error during initial template
initialization and parsing if we suspect something is
incorrect. Please check for them, as they indicate an error
that may cause auto-escaping to work improperly.
-
Beware of double escaping. When you use the Auto Escape mode,
you surrender all variable escaping to the template system.
If you also perform your own escaping in your source code, you may
face situations where content was escaped multiple times.
In particular, do not use any of the legacy methods below or
others that perform variable escaping.
-
SetEscapedValue
-
SetEscapedFormatttedValue
-
SetEscapedValueAndShowSection
-
Supported HTML contexts. HTML (TC_HTML
) and
Javascript (TC_JS
) templates are well supported.
Other template contexts have only basic support.
For these contexts, variables are escaped as follows:
TemplateContext Escaping Applied
TC_JSON
:javascript_escape
TC_XML
:xml_escape
TC_CSS
:cleanse_css
-
New restrictions on the use of BI_SPACE
and
BI_NEWLINE
. These system variables may not be
re-assigned to a semantically different value via
dict->SetValue
or related methods, and they may
not have modifiers attached to them in templates. For
instance: it's ok to redefine BI_NEWLINE
from
\n
to \r\n
, since html treats them
identically. But changing it to hello, world!
is
not allowed.
A new filename convention
The Auto Escape feature codifies simple conventions
of template filenames:
- CSS templates optionally include, in their filename, the
keywords
style
or stylesheet
or
css
.
- Javascript templates optionally include, in their filename, the
keywords
js
or javascript
.
If we find one of these keywords in the filename but
it does not match the template type given, we log a warning.
Jad Boutros
ctemplate-2.2/doc/reference.html 0000644 0001750 0001750 00000213372 11743633404 013662 0000000 0000000
Ctemplate System Reference Guide
Ctemplate System Reference Guide
(as of
)
Overview
The main class used by the template system is
TemplateDictionary
, which is used to expand a template
file. It is used by the main functions for expanding a template,
found in template.h
.
TemplateCache
is used to hold a collection of
Template
objects. TemplateNamelist
provides
various introspection routines on collections of Template
objects.
TemplateModifier
and PerExpandData
are
used to modify the values of a TemplateDictionary
at
expand time. TemplateAnnotator
does too, but is intended
for debugging purposes. TemplateDictionaryPeer
is used
for testing template code.
ExpandEmitter
provides the ability to emit an expanded
template to an arbitrary output store.
TemplateString
is a string-like class that is built to
be very efficient when used with the template system. For instance,
tools are available to hash constant TemplateString
objects at compile-time, speeding up their use at run-time.
The rest of this document describes these classes and functions in
more detail, as well as build tools and other mechanisms for handling
templates.
(Note: the code snippets below all assume the default configuration
option is set, which puts template code in namespace
ctemplate
.)
Expanding Templates
The Template Language
Templates are strings that contain special formatting code called
template markers. In the Ctemplate System, template
strings are usually read from a file.
Anything found in a template of the form {{...}} is
interpreted as a template marker. All other text is considered
formatting text and is output verbatim at template expansion time.
Outside of the template markers, templates may contain any text
whatsoever, including (single) curly braces and NUL characters.
The template language has six types of markers:
- Variable markers, which are replaced by text based on
dictionary values. Variable markers look like this:
{{FOO}}
- Start section and end section markers, which
delimit sections which may appear zero, one, or N times in
the output. Section markers look like this:
{{#FOO}}...{{/FOO}}
- Template-include markers, which designate other
templates to be expanded and inserted at the location where the
marker appears. These are treated much like sections -- one
may think of them as sections whose content is specified in a
different file instead of inline -- and just like sections, can
be expanded zero, one or N times in the output, each with a
different dictionary. Template-include markers look like this:
{{>FOO}}
- Comment markers, which may annotate the template
structure but drop completely out of the expanded
output. Comment markers look like this:
{{! comment lives here -- cool, no?}}
- Set-delimiter markers, which change the marker
delimiters from
{{
and }}
to custom
strings. (The only requirement is that these strings not
contain whitespace or the equals sign.) This is useful for
languages like TeX, where double-braces may occur in the text
and are awkward to use for markup. Set-delimiter markers look
like this: {{=< >=}} <! Now markers are
delimited by braces > <=| |=> |! And now markers are
delimited by bars! |
- Pragma markers, which invoke additional built-in template
features when processing the template. Pragma markers look like
this:
{{%PRAGMA [name="value"...]}}
. Currently,
AUTOESCAPE is the only pragma defined.
These marker types each have their own namespace. For readability,
however, it is best to not overuse a single name.
Modifiers
A variable and include-template can have one or more modifiers attached to them, like so:
{{MYVAR:mod1:mod2:mod3=value:mod4=value with spaces:mod5}}
A modifier is a filter that's
applied at template-expand time, that munges the value of the variable
before it's output. See the TemplateModifier
class for
more details.
When expanding a variable (or template-include) with a modifier,
the modifiers are applied in order, left to right. For a
template-include, first the entire sub-template is expanded, as a
single string, and then the modifiers are applied to that string.
In general, using explicit modifiers does not turn off auto-escaping on a variable. The explicit
modifier :none
does suppress auto-escaping.
Special Markers
Some marker names may have a special meaning in the template
system. Right now, there's one such name.
Separator Sections
If you have a section named FOO, you can define inside
of it a section named FOO_separator, and the template
system will automatically expand that section every time
FOO
is expanded, except for the last. Thus, the
contents of FOO_separator
can be used to separate
repeated values of a section.
Here's an example:
Here are the meeting attendees:
{{#ATTENDEES}}
{{NAME}}
{{#ATTENDEES_separator}}, {{/ATTENDEES_separator}}
{{/ATTENDEES}}
.
Here is a more convoluted example, to show the date:
{{#DATE}}{{DATE_COMPONENT}}{{#DATE_separator}}{{DATE_SEP}}{{/DATE_separator}}{{/DATE}}
You'd set up a template dictionary to repeat DATE
three times, with DATE_COMPONENT
set to the month, day,
and year (or day, month, and year, depending on your locale...), and
DATE_SEP
set to /
or -
or
whatever date-separator is called for.
SEP_separator
is always evaluated with the current
dictionary. Thus, in the date example, if you wanted a different
separator each time, you could do so by setting DATE_SEP
to a different value for each repetition of DATE
.
While SEP_separator
is automatically expanded by the
template system, it is otherwise a perfectly normal section. You can
even instantiate it yourself by calling
AddSectionDictionary("SEP_separator")
. In that case, the
section will be expanded both via the automatic expansion as a
separator, and as a normal section via the section dictionary you
added. This is more confusing than helpful, and you should probably
never do it.
There can be at most one "separator" sub-section per section. If
there are more, only the last is automatically expanded.
Specifying a template
In the template system -- in functions like
ExpandTemplate()
-- a template is specified by a pair:
filename + strip-mode. The filename specifies the name of the
template file on disk (but see below for string templates). The strip
mode specifies how this file should be parsed as it's read from disk,
in particular, how whitespace should be handled. It can take the
following values:
-
ctemplate::DO_NOT_STRIP
: do nothing. This expands
the template file verbatim.
-
ctemplate::STRIP_BLANK_LINES
: remove all blank
lines. This ignores any blank lines found in the template file
when parsing it. When the template is html, this reduces the
size of the output text without requiring a sacrifice of
readability for the input file.
-
ctemplate::STRIP_WHITESPACE
: remove not only blank
lines when parsing, but also whitespace at the beginning and
end of each line. It also removes any linefeed (possibly
following whitespace) that follows a closing }}
of
any kind of template marker except a template variable.
(This means a linefeed may be removed anywhere by simply
placing a comment marker as the last element on the line.)
When the template is html, this reduces the size of the output
html without changing the way it renders (except in a few
special cases.) When using this flag, the built-in template
variables BI_NEWLINE
and BI_SPACE
can
be useful to force a space or newline in a particular
situation.
The filename is where the template file lives on disk. It can be
either an absolute filename, or relative to a directory in the
template search path.
In addition to reading a template from disk, it is possible to read
a template from a string, using StringToTemplateCache()
.
The first argument of StringToTemplateCache()
is a "key"
to use to refer to this string-based template. This key takes the
place of the filename, for any routine that asks for a
filename + strip.
ExpandTemplate()
This is the main workhorse function of the template system. It
takes the filename of a template, a template dictionary, and a string to
emit to, and emits an "expanded" version of the template using the
given template dictionary to fill in the template markers.
If the template specified by the given filename is already found in
an internal cache, the cached version of the template is used,
otherwise the template is loaded from disk, parsed, and stored in the
cache before expansion is performed. As always, the "filename" can
also be a key to a string-based template,
inserted directly into the cache via
StringToTemplateCache()
.
There is an overloaded version of Expand()
that takes
an ExpandEmitter
rather
than a string, as the source to expand the template into.
This function returns true if the template was successfully
expanded into the output parameter. It returns false if expansion
failed or was only partially successful. It might fail because the
template file cannot be found on disk, or because the template has
syntax errors and cannot be parsed, or because the template
sub-includes another template, and that sub-template has errors. To
minimize the risk of errors at expand-time, you can call
LoadTemplate()
(below) first to load and parse the
template into the cache. This will catch all errors except for errors
involving sub-templates.
In the case of partial failures -- typically, failures resulting in
an error in a sub-inclued template -- there may be partial data
emitted to the output before the error was detected. If
ExpandTemplate()
returns false, you should be careful to
check for and remove this partial data, if desired.
ExpandWithData()
ExpandWithData()
is like
ExpandTemplate()
, with the addition that it allows you to
pass in per-expand data. It's called
like this:
ctemplate::TemplateDictionary dict(...);
ctemplate::PerExpandData per_expand_data;
string output;
ctemplate::ExpandWithData(filename, strip_mode, &output, &dict,
&per_expand_data);
Per-expand data is applied to all templates that are seen while
expanding: not only the template you called Expand()
on,
but also sub-templates that are brought in via template-includes
({{>INCLUDE}}
). See the description of the PerExpandData
class for more
details about how expansion can be modified by per-expand data.
The return value has the same meaning as for
ExpandTemplate()
In fact, if you pass in
NULL
as the per_expand_data
argument, this
function is exactly equivalent to ExpandTemplate()
.
LoadTemplate()
This function takes a filename and a strip-mode, and loads the file
into the default template cache. Future calls to
ExpandTemplate()
or ExpandWithData()
will
get the parsed template from the cache, without needing to go to
disk.
This function returns true if the template was successfully read
from disk, parsed, and inserted into the cache. It will also return
true if the template is already in the cache (even if the file has
changed on disk since the template was inserted into the cache). It
will return false if the file cannot be found on disk, or cannot be
successfully parsed. (Note that LoadTemplate()
cannot
detect errors in sub-included templates, since the identity of
sub-included templates is specified in a
TemplateDictionary
, not in the template itself.)
StringToTemplateCache()
In addition to reading a template file from disk, it is also
possible to read a template file from a string, using
StringToTemplateCache()
. It takes the content
as a string. It also takes in a key and a strip
mode. The given key and strip mode can be used as the filename/strip
pair in calls to ExpandTemplate()
and similar
functions. The key can also be used as the "filename" in calls to
ctemplate::TemplateDictionary::SetFilename()
, allowing
this template to be included inside other templates.
StringToTemplateCache()
returns true if the string is
successfully inserted into the cache. It returns false otherwise,
probably because there is already a string or filename in the cache
with the same key.
default_template_cache() and mutable_default_template_cache()
All the above routines -- ExpandTemplate()
,
LoadTemplate()
, and the like -- read and write parsed
templates to the default template cache. This is just a static
instance of the TemplateCache
class. It can
be accessed via these two functions:
default_template_cache()
and, if you need a non-const
version of the cache, mutable_default_template_cache()
.
These can be useful if you need the advanced features of template
caches, such as ReloadAllIfChanged()
or
ClearCache()
.
The TemplateDictionary
Class
The class TemplateDictionary
is used for all template
dictionary operations. In general, an application will need to call a
TemplateDictionary
method for every marker in the
associated template (the major exception: markers that evaluate to the
empty string can be ignored).
The appropriate function to call for a given template marker
depends on its type.
Data Dictionaries
A data dictionary is a map from keys to values. The keys are
always strings, corresponding to the name of the associated template
marker, so a section {{#FOO}}
in the template text is
matched to the key FOO
in the dictionary, if it exists.
Note the case must match as well.
The value associated with a key differs according to key type. The
value associated with a variable is simple: it's the value for
that variable. Both keys and values can be any 8-bit
character-string, and may include internal NULs (\0
).
The value associated with a section is a list of data
dictionaries. At template-expansion time, the section is expanded
once for each dictionary in the list. The first time, all
variables/etc. in the section will be evaluated taking into account
the first dictionary. The second time, all variables/etc. will be
evaluated taking into account the second dictionary. (See below for a definition of "taking into
account.")
The value associated with a template-include is also a list
of data dictionaries. Each data dictionary in this list must also
have one other, mandatory associated piece of associated information:
the filename of the template to include. At expand-time, that
filename is passed as-is to ctemplate::ExpandTemplate()
(or, more exactly, the equivalent of ExpandTemplate()
in
the same TemplateCache
that the parent template comes
from).
Details on Dictionary Lookup
The dictionary structure is a tree: there's a 'main' dictionary,
and then a list of sub-dictionaries for each section or
include-template. When looking up a marker -- be it a variable,
section, or include-template marker -- the system looks in the
currently applicable dictionary. If it's found there, that value is
used. If not, and the parent dictionary is not an include-template,
it continues the look in the parent dictionary, and possibly the
grandparent, etc. That is, lookup has static scoping: you look
in your dictionary and any parent dictionary that is associated with
the same template-file. As soon as continuing the lookup would
require you to jump to a new template-file (which is what
include-template would do), we stop the lookup.
If lookup fails in all dictionaries, the template system does a
final lookup in the global variable dictionary.
The system initializes the global dictionary with a few useful
values for your convenience (the user can add more). All system
variables are prefixed with BI
, to emphasize they are
"built in" variables.
-
BI_SPACE
, which has the value
<space>
. It is used to force a space
at the beginning or end of a line in the template,
where it would normally be suppressed. (See below.)
BI_NEWLINE
, which has the value
<newline>
It is used to force a
newline at the end of a line, where it would normally
be suppressed. (See below.)
Variable inheritance happens at expand time, not at
dictionary-create time. So if you create a section dictionary, and
then afterwards set a variable in its parent dictionary (or in the
global dictionary), the section will inherit that variable
value, if it doesn't define the value itself.
SetValue() and variants
SetValue() is used to set the value for a variable
marker in a dictionary. It takes a string as input -- nominally a TemplateString
, though a C++
string or C char* will be auto-converted -- for the variable name and
its value. The name is the same string as is used for the variable's
template-marker inside the template this dictionary will be expanded
with: if the template reads Hello {{NAME}}
then the
first argument to SetValue()
must be NAME
.
Case matters.
SetIntValue()
takes an integer as the value, rather
than a string. On all platforms, the integer may be up to 64
bits.
SetFormattedValue()
is a convenience routine.
SetFormattedValue(key, arg1, arg2, ...)
is logically
equivalent to
char buffer[A_BIG_ENOUGH_NUMBER];
sprintf(buffer, arg1, arg2, ...);
SetValue(key, buffer);
without having to worry about the size of buffer
, or
about stack overflow.
SetValueWithoutCopy()
is provided to give an extra bit
of efficiency when needed. SetValue()
will copy the key
and value into an internal data structure used by the
TemplateDictionary
; this avoids dangling pointers if the
arguments to SetValue()
are temporaries, or otherwise
have shorter lifetime than the TemplateDictionary
. But
if you know that both the key and value strings have lifetime longer
than the TemplateDictionary
-- perhaps because they are
global (static duration) char*
's -- you can call
SetValueWIthoutCopy()
to avoid the copy. This yields a
small time savings at the cost of significant code fragility, so
should only be used when absolutely necessary.
SetGlobalValue() and SetTemplateGlobalValue()
SetGlobalValue()
is like SetValue()
but
works on the global dictionary. Since the global dictionary is shared
across all template dictionaries, this is a static method on
TemplateDictionary
. It is thread-safe. It is also
relatively slow.
SetTemplateGlobalValue()
is like
SetValue()
, but the values are preserved across
template-includes.
This example shows all three forms:
A.tpl:
{{NAME}} has won {{>PRIZE}}. It is worth {{AMOUNT}}.
B.tpl:
{{AMOUNT}} dollars! And it's all yours, {{NAME}}
C.tpl:
To: {{NAME}}. Amount: {{AMOUNT}}.
code:
ctemplate::TemplateDictionary dict("set_value_demo");
ctemplate::TemplateDictionary* subdict = dict.AddIncludeDictionary("PRIZE");
subdict->SetFilename("B.tpl");
dict->SetValue("NAME", "Jane McJane");
dict->SetTemplateGlobalValue("AMOUNT", "One Million");
ctemplate::TemplateDictionary::SetGlobalValue("NAME", "John Doe");
ctemplate::TemplateDictionary dict_c("set_value_demo, part 2");
ctemplate::ExpandTemplate("A.tpl", ..., &dict);
ctemplate::ExpandTemplate("C.tpl", ..., &dict_c);
The first expand yields this:
Jane McJane has won One Million dollars! And it's all yours, John Doe. It is worth One Million.
The second expand yields this:
To: John Doe. Amount: .
NAME
was set via SetValue()
, so its
value was not propagated across the include-dict boundary; instead,
the subdict (B.tpl) got its value for NAME
from the
global dictionary. AMOUNT
, on the other hand, was set
via SetTemplateGlobalValue()
, so its value was propagated
across the boundary, and the subdict saw it. However, the totally
unrelated template, C.tpl, did not see either value, and only sees the
values in the global dictionary. (Of course, had we filled
dict_c
with some values, C.tpl would have had access to
those.)
AddSectionDictionary(), ShowSection(),
and SetValueAndShowSection()
AddSectionDictionary(section_name)
returns a
sub-dictionary associated with the given section_name (for instance,
dict.AddSectionDictionary("MYSECT")
for a template like
{{#MYSECT}}...{{/MYSECT}}
). If called multiple times, it
will return a new dictionary each time. During Expand()
,
the section will be expanded once for each time
AddSectionDictionary()
was called; that is, the text
inside the section delimiters will be repeated once for each
AddSectionDictionary()
call, and within a single
repetition, the dictionary returned by
AddSectionDictionary()
will be used to populate the text
inside the section delimiters. (With the current dictionary as that
dictionary's parent, for inheritance purposes.)
This suggests that if AddSectionDictionary()
is never
called on a section, the text inside the section will be omitted
entirely by Expand()
.
ShowSection()
is a convenience method used to show the
text inside the section exactly once. It is equivalent to calling
AddSectionDictionary()
once, and ignoring the returned
sub-dictionary. All variables in the section will depend on
dictionary inheritence to get their values.
SetValueAndShowSection()
is another convenience
method,, used to show a section if and only if a related variable is
set to a non-empty value. SetValueAndShowSection(name, value,
section_name)
is equivalent to this: if value is empty do
nothing, otherwise add a single dictionary to
section_name
and call section_dict->AddValue(name,
value)
.
Example:
ctemplate::TemplateDictionary* dict = new ctemplate::TemplateDictionary("section example");
const char* username = GetUsername(); // returns "" for no user
if (username[0] != '\0') {
ctemplate::TemplateDictionary* sub_dict = dict->AddSectionDictionary("CHANGE_USER");
sub_dict->SetValue("USERNAME", username);
} else {
// don't need to do anything; we want a hidden section, which is the default
}
// Instead of the above 'if' statement, we could have done this:
if (username[0] != '\0') {
dict->ShowSection("CHANGE_USER"); // adds a single, empty dictionary
dict->SetValue("USERNAME", username); // take advantage of inheritance
} else {
// don't need to do anything; we want a hidden section, which is the default
}
// Or we could have done this:
dict->SetValueAndShowSection("USERNAME", username, "CHANGE_USER");
// Moving on...
GetPrevSearches(prev_searches, &num_prev_searches);
if (num_prev_searches > 0) {
for (int i = 0; i < num_prev_searches; ++i) {
TemplateDictionary* sub_dict = dict->AddSectionDictionary("PREV_SEARCHES");
sub_dict->SetValue("PREV_SEARCH", prev_searches[i]);
}
}
AddIncludeDictionary() and SetFilename()
AddIncludeDictionary(section_name)
returns a
sub-dictionary associated with the given include_name (for instance,
dict.AddIncludeDictionary("MYTPL")
for a template like
{{>MYTPL}}
). If called multiple times, it
will return a new dictionary each time. It is the responsibility of
the caller to then call SetFilename()
on the
sub-dictionary returned.
During Expand()
,
each dictionary returned by AddIncludeDictionary
will be
examined in turn. For each dictionary for which
SetFilename()
is called, that filename will be read as a
template (via LoadTemplate()
, with the same
"strip" value as the current template), and expanded using the
dictionary. (Note that the dictionary will not inherit
SetValue()
values from the parent dictionary, though it
will inherit SetTemplateGlobalValue()
values.) This
expanded template will then be emitted to the output.
Note that if AddIncludeDictionary()
is never called,
the template-include will be a no-op during Expand()
.
Likewise, if it is called but SetFilename()
is never
called on the resulting sub-dictionary, the template-include will be a
no-op. On the other hand, if it is called multiple times, multiple
templates -- possibly all from the same file, possibly not -- will be
inserted at the point of the template-include.
If a user has called StringToTemplateCache(key, ...)
,
then the user can call SetFilename(key)
to include the
contents of the string as the sub-template.
Dump() and DumpToString()
These routines dump the contents of a dictionary and its
sub-dictionaries. Dump()
dumps to stdout,
DumpToString()
to a string. They are intended for
debugging.
The TemplateCache
Class
This class holds a collection of templates. It can be used to give
you a coherent view of the template system: you load all the templates
you are going to use into the cache, and then reload them from disk in
one atomic operation. You can have multiple
TemplateCache
objects in your executable, perhaps one for
each service you provide, or perhaps one per thread (so as to avoid
thread contention when loading templates).
One intended use of the template cache is to make it safe to reload
template files while serving user requests from a webserver. The idea
is that every user request, as it's created, is associated with the
current template cache. When you wish to reload, you
Clone()
the current cache, and then reload inside the
cloned copy. New requests will get the cloned cache, while old
requests will continue to render using the old cache.
TemplateCache
is written to make this use-case efficient:
templates are shared between caches when appropriate, with
reference-counting to keep memory management easy.
The default template cache
The template system creates a default template cache, which is
available via the functions default_template_cache()
and
mutable_default_template_cache()
.
For simple uses of the template system, using the default cache,
via ExpandTemplate()
and the like, may be perfectly
adequate. If you want more sophisticated features, such as the
ability to have different versions of the same template file active at
one time, or to change the template root-directory, you will have to
use an explicit TemplateCache
.
LoadTemplate() and StringToTemplateCache()
These two routines are how you explicitly insert data into the
cache. LoadTemplate()
reads a template from disk, while
StringToTemplateCache()
takes the data from a
user-specified string. These work exactly the same as the global LoadTemplate()
and StringToTemplateCache()
,
except they insert into the given TemplateCache
, rather
than the global cache.
LoadTemplate()
is not strictly necessary: if the cache
cannot find a template it needs at Expand*()
time, it will
automatically try to fetch it from disk. It is intended mostly for
use with Freeze()
, which disables
this auto-fetch behavior.
Both of these routines take a strip mode
specifying how the template system should treat whitespace while
parsing.
If the template-cache is frozen,
LoadTemplate()
will only return true if the template is
already stored in the cache, and will return false in every other
case. For a frozen cache, StringToTemplateCache()
will
always return false.
ExpandWithData() and ExpandFrozen()
These routines takes a string that represents either a template
filename (for disk-based templates), or a key used in
StringToTemplateCache()
(for string-based templates), a strip mode saying how to parse the template's
whitespace, and per-expand data (which
can be NULL). Overloads are provided to output the expanded template
to either a string or to an arbitrary ExpandEmitter
.
Expand uses the filename + strip pair to fetch the template from
the cache, if it's there. If not, ExpandWithData()
will
fetch the template from disk and insert it into the cache.
ExpandFrozen()
, on the other hand, will just fail to
expand, and return false. This is the only difference in behavior
between the two routines. To reinforce this behavior,
ExpandFrozen()
will return false immediately if Freeze()
has not been called on the
cache.
While expanding, the template system may come across template
sub-includes ({{>SUB_TEMPLATE}}
). It will attempt to
fetch these templates from the cache as well; failing that, it will
try to load the template from disk (for ExpandWithData()
)
or else fail the expand and return false (for
ExpandFrozen()
).
Because ExpandFrozen()
never updates the cache, it is
a const method, unlike ExpandWithData()
.
Note that TemplateCache
does not provide the
convenience ExpandTemplate()
routine, as the analogue of
the global ExpandTemplate()
. If you are
not interested in the per-expand data, just call
ExpandWithData()
with the per-expand data set to NULL.
ReloadAllIfChanged()
For every file-based template in the cache (this method ignores
string-based templates), ReloadAllIfChanged()
checks the
filesystem to see if the file has changed since it was loaded into the
cache. If so, the cache loads a new version of the file into the
cache. Note that at this point both the old and new versions of the
file exist in the cache! Only the new version is accessible via new
calls to Expand()
, but any expansions currently in flight
during the ReloadAllIfChanged()
call will continue to use
the old version.
NOTE: ReloadAllIfChanged()
never modifies existing
items in the cache in any way. It only loads new entries into the
cache.
ReloadAllIfChanged()
comes in two flavors, controlled
by the passed-in enum. In "immediate" mode, it synchronously iterates
through the cache and reloads all files that need it. In "lazy" mode,
it waits to reload a given template file until the next time it's
actually used (in a call to Expand*()
). "Immediate" mode
is safer in the case where templates depend on each other and the
files change a lot, since all files are reloaded at about the same
time. "Lazy" mode avoids the latency spike of "immediate" mode, and
is preferable in the (common) case that files on disk change only
rarely.
SetTemplateRootDirectory(),
AddAlternateTemplateRootDirectory(), and
template_root_directory()
By default, filenames passed in to Expand*()
are taken
to be relative to the current working directory. These functions
change that behavior. SetTemplateRootDirectory()
resets
the search path to be the single path passed in to this function.
Every time AddAlternateTemplateRootDirectory()
is called,
it adds another directory to the end of the search path. The template
system will follow the search path, in order, when looking for a
filename.
Note that the template search path is only meaningful when the
filename passed to Expand*()
(or specified for a
sub-include) is a relative filename. If the filename is an absolute
filename, starting with /
, the search path is
ignored.
template_root_directory()
returns the first entry in
the search path. There is currently no way to access other entries in
the search path.
FindTemplateFilename()
FindTemplateFilename()
does the work of finding a
template file in the filesystem, using the current template search
path. It takes a relative pathname as input, and returns an absolute
pathname as output, indicating where the template file lives on the
filesystem. If the template file is not found, this method returns
the empty string.
Freeze()
Freeze()
marks the template cache as immutable. After
this method is called, the cache can no longer be modified by loading
new templates or reloading existing templates. During expansion only
cached included templates will be used; they won't be loaded
on-demand.
Before calling Freeze()
, you should make sure your
cache has all the templates it might need, using
LoadTemplate()
and StringToTemplateCache()
.
Otherwise, ExpandWithData()
and
ExpandFrozen()
may fail.
Once the cache is frozen, calls to
SetTemplateRootDirectory()
,
AddAlternateTemplateRootDirectory()
,
Delete()
, and ReloadAllIfChanged()
will
fail.
After the cache is frozen, the TemplateCache
object is
effectively const.
Delete()
This method deletes an entry from the cache. If the entry is in
the cache multiple times (each with a different "strip" mode), this
method deletes all of them.
ClearCache()
This method deletes all entries from the cache. It can be called
even on a frozen cache.
Note: this method is not typically necessary unless you are testing
for memory leaks. It is intended to be called just before exiting the
program, and after all template expansions are completed. Using it in
that way may prevent unnecessary reporting by the leak checker.
Clone()
Clone()
makes a shallow copy of the given
TemplateCache
object, and returns the copy. The new copy
and the old share the same template objects; since it's a shallow
copy, they actually share pointers to the exact same object. (Since
the template cache never changes a template object once it's loaded
into the cache, sharing the pointer isn't a risk.)
The intended use of Clone()
, as described above, is to
allow fine control over "epochal" changes in templates. One
TemplateCache
can hold all versions of the template files
before the big update; after the update is done, you can clone the old
cache and then call ReloadAllIfChanged()
on the clone.
This is a low-cost operation, since the two copies share most
resources. Smart pointers take care of most memory management
issues.
The caller is responsible for calling delete
on the
returned TemplateCache
object.
The TemplateNamelist
Class
This class provides information about registered templates. Or more
precisely, all templates corresponding to registered filenames.
All methods in this class are static.
RegisterTemplate() and
RegisterTemplateFilename()
TemplateNamelist::RegisterTemplate()
takes a filename
and adds it to the static namelist used by
TemplateNamelist
. All other methods of
TemplateNamelist
work only on registered filenames.
It's fairly rare to call this method directly. Instead, the more
common use is to use the macro RegisterTemplateFilename
somewhere in the global scope, like so:
RegisterTemplateFilename(EXAMPLE_FN, "example.tpl");
The reason to prefer the macro is it defines a global variable that
you can use instead of the hard-coded template name. This helps catch
typos. The RegisterTemplateFilename()
example is
functionally equivalent to:
#define EXAMPLE_FN "example.tpl"
It can be used like this:
ctemplate::ExpandTemplate(EXAMPLE_FN, ctemplate::DO_NOT_STRIP, ...);
GetMissingList()
TemplateNamelist::GetMissingList()
returns a list of
all registered templates (or rather, all filenames) where the file
could not be found on disk.
AllDoExist()
Returns true if and only if the missing-list is empty.
GetBadSyntax()
Returns a list of all registered templates where the template
contains a syntax error, and thus cannot be used.
IsAllSyntaxOkay()
True if and only if the bad-syntax list is empty.
GetLastmodTime()
Returns the latest last-modified time for any registered
template-file.
The TemplateModifier Class
and Associated Functions
A modifier is a filter that's applied at template-expand time, that
munges the value of the variable before it's output. For instance,
<html><body>{{NAME:html_escape}}</body></html>
asks the template system to apply the built-in
html_escape
modifier when expanding
{{NAME}}
. If you set NAME
in your
dictionary to be Jim & Bob
, what will actually be
emitted in the template is Jim & Bob
.
You can chain modifiers together. This template first html-escapes
NAME
, and then javascript-escapes that result:
<html><body>{{NAME:html_escape:javascript_escape}}</body></html>
Modifiers typically have a long, descriptive name and also a
one-letter abbreviation. So this example is equivalent to the
previous one:
<html><body>{{NAME:h:j}}</body></html>
Some modifiers take an argument, specified after an equals
sign:
<html><body>{{NAME:html_escape_with_arg=pre}}</body></html>
Built-in Modifiers
Here are the modifiers that are built in to the template system.
They are all defined in template_modifiers.cc:
long name short name description
:cleanse_css
:c
Removes characters not safe for a CSS value. Safe characters
are alphanumeric, space, underscore, period, coma, exclamation
mark, pound, percent, and dash.
:html_escape
:h
html-escapes the variable before output
(eg &
-> &
)
:html_escape_with_arg
:H
special purpose html escaping. See
:H Arguments
below for details.
:img_src_url_escape_with_arg
:I
special purpose image url escaping. See
:I and :U Arguments
below for details.
:javascript_escape
:j
javascript-escapes the variable before output (eg
"
-> \x27
and
&
-> \x26
)
:javascript_escape_with_arg
:J
special purpose javascript escaping. See
:J Arguments
below for details.
:json_escape
:o
json-escapes a variable before output as a string in json;
HTML characters are escaped using Unicode escape sequences
(e.g &
-> \u0026
) to comply with
RFC 4627.
:none
leaves the variable as is (used to disable auto-escaping)
:pre_escape
:p
pre-escapes the variable before output (same as html_escape but
whitespace is preserved; useful for <pre>...</pre>)
:url_escape_with_arg
:U
special purpose url escaping. See
:I and :U Arguments
below for details.
:url_query_escape
:u
performs URL escaping on the variable before output.
space is turned into +, and everything other than [0-9a-zA-Z.,_:*/~!()-], is
transformed into %-style escapes. Use this when you are building
URLs with variables as parameters:
<a href="http://google.com/search?q={{QUERY:u}}">{{QUERY:h}}</a>
:xml_escape
xml-escapes the variable before output
(the five characters <>&"'
become
<>&"'
)
suitable for content returned in raw XML. It is not intended
for escaping content within CDATA blocks.
The *_with_arg
modifiers require an argument to
specify the type of escaping to use. The following sections list
the supported arguments for each of these modifiers.
:H Arguments
Here are the values that are supported by
the html_escape_with_arg
modifier:
value description
=snippet
like html_escape
, but allows HTML entities and
some tags to pass through unchanged. The allowed tags
are <br>
, <wbr>
, <b>
,
and </b>
.
=pre
same as pre_escape
=url
same as :U=html
below. For backwards compatibility.
=attribute
replaces characters not safe for an use in an unquoted
attribute with underscore. Safe characters are alphanumeric,
underscore, dash, period, and colon.
:I and :U Arguments
Here are the values that are supported by
the img_src_url_escape_with_arg
and
url_escape_with_arg
modifiers:
value description
=html
Ensures that a variable contains a safe URL. Safe means that
it is either a http or https URL, or else it has no protocol
specified.
- If the URL is safe, the modifier HTML-escapes the URL.
- Otherwise, the modifier replaces the unsafe URL with one of the
following values:
/images/cleardot.gif
(the :I
modifier)
#
(the :U
modifier)
Do not use :U
for image URLs. Use :I
instead. #
is not a safe replacement for an image URL.
<img src=#>
can cause each browser to request the
entire page again.
=javascript
Same as =html
, but using javascript escaping
instead of html escaping.
=css
Same as =html
but using CSS escaping instead
of html escaping so that the variable can be safely inserted
within a CSS @import
statement or a CSS property.
The characters in [\r\n()'"<>*\] are transformed
into %-style escapes.
=query
(Supported for :U
only) Same as
url_query_escape
.
:J Arguments
Here are the values that are supported by
the javascript_escape_with_arg
modifier:
value description
=number
Ensures that the variable is a valid number or boolean
javascript literal. This includes booleans
true
and false
, decimal
numbers (e.g. 4.10
or -5.01e+10
)
as well as hex numbers (e.g. 0x5FF
). This modifier
is intended to ensure the variable not enclosed in
quotes cannot contain javascript code that may execute. It does
not guarantee that the variable is syntactically well-formed.
If the variable is safe, it is returned
as-is, otherwise it is replaced with null
.
In the future we may add more logic to support objects and
arrays.
Custom Modifiers
In addition to the built-in modifiers, you can write your own
modifier. Custom modifiers must have a name starting with "x-", and
the name can contain alphanumeric characters plus dashes and
underscores. Custom modifiers can also accept values with any
character except for : and }
. For example
this template could be a valid use of a custom modifier:
{{VAR:x-my_modifier:value1,value2,value3 has spaces,etc}}
See <template_modifiers.h>
for details on how to
write a modifier and how to register it. In short, you write a
modifier by subclassing ctemplate::TemplateModifier
and
overriding the Modify
method, and you register it by
calling ctemplate::AddModifier()
Here is an example of
the code for a custom modifier:
class StarEscape : public ctemplate::TemplateModifier {
void Modify(const char* in, size_t inlen,
const ctemplate::PerExpandData* per_expand_data,
ctemplate::ExpandEmitter* outbuf, const string& arg) const {
outbuf->Emit(string("*") + string(in, inlen) + string("*"));
}
};
Subclassing TemplateModifier
The minimum work to create a custom modifier is to subclass
TemplateModifier
and override the Modify()
method. Modify()
takes as input the value of the text to
be modified, as well as the per expand
data associated with this Expand()
call. The method
may use this input, plus any other data it may have, to generate
output, which it should write into the given
ExpandEmitter
.
The subclass can also override MightModify()
. This is
useful for modifiers that are typically a no-op (in which case the
modifier is just doing busy-work, copying its input to the output
ExpandEmitter
). If MightModify()
returns
false, the template system will avoid calling Modify()
at
all on that variable, avoiding the busy-work copy.
AddModifier()
AddModifier() is used to register a custom modifier,
so the modifier can be used in templates. The name of the modifier
must start with x-
.
AddXssSafeModifier()
AddXssSafeModifier()
is used to register a custom
modifier that can work well with the auto-escape system. It is used when the
modifier produces output that is "safe" from cross-site scripting
attacks in all contexts in which it might be used. For instance, a
modifier that only emits numbers is xss-safe if it's only used in html
or javascript contexts.
Auto-escaping and Manual Escaping
If the auto-escape pragma is used
in a document, then all variables will be auto-escaped, even if
explicit modifiers are used on the variable. The rules are a little
complicated:
- If the explicit modifier is a built-in modifier, and that
modifier is "compatible" with the modifier that auto-escape
would perform ("compatible" means it safely escapes in at least
as many contexts as the auto-escape modifier), then only the
explicit modifier is applied, and no further auto-escaping is
done.
- If the explicit modifier is a custom modifier registered using
AddXssSafeModifier(), no further auto-escaping is
done.
- If the explicit modifier is the :none modifier, no
further auto-escaping is done. This is the mechanism for
manually turning off auto-escaping.
- In all other situations, auto-escaping will be performed after
the explicit modifiers have all run.
The PerExpandData
Class
ExpandWithData()
and
TemplateModifier::Modify()
both take a
PerExpandData
object. Per-expand data is applied to all
templates that are seen while expanding: not only the template you
called ExpandWithData()
on, but also sub-templates that
are brought in via template-includes ({{>INCLUDE}}
).
There are several types of per-expand data you can set, by calling
the appropriate method on a PerExpandData
object.
SetAnnotateOutput()
This is a debugging function. When expanding this template, it adds
marker-strings to the output to indicate what template-substitutions
the system made. This takes a string argument which can be used to
shorten the filenames printed in the annotations: if the filename
contains the string you give, everything before that string is elided
from the filename before printing. (It's safe to just always pass in
the empty string.)
SetAnnotator()
This overrides the default text-based annotation used by
SetAnnotateOutput()
. If this is set and
SetAnnotateOutput()
is called, the per-expand data will
use this TemplateAnnotator
instance
to do the annotation, rather than the default instance.
InsertForModifiers() and LookupForModifiers()
InsertForModifiers()
stores an arbitrary key/value
pair in the PerExpandData
structure. This is used with
template modifiers: the
PerExpandData
object passed to
ExpandWithData()
is made available to every template
modifier that is called during expand time (including any custom
modifiers). The intended use of this functionality is to allow a
modifier to work one way when expanding a template with dictionary A,
and another way when expanding a template with dictionary B. For
instance, a modifier might encrypt part of a webpage using a user's
secret-key, which is of course different for every expansion of the
webpage.
LookupForModifiers()
can be used by a
template-modifier to read the key/value pair inserted by
InsertForModifiers()
.
LookupForModifiersAsString()
is the same, but returns the
value as a char* rather than a void*, for convenience.
SetTemplateExpansionModifier()
This is an advanced feature for those who need a custom hook into
template expansion. It will not be used by most programmers. It
takes a template-modifier as its argument, but this template modifier
is treated specially: instead of applying when an appropriate magic
string appears in the text of a template, it applies every time a
template is expanded during a call to ExpandWithData()
.
Note this means that it's called not only after the top-level
template, that ExpandWithData()
is called on, is
expanded, but also on every sub-template that is expanded due to a
template-include.
This unusual functionality has a few unusual properties. Since the
template expansion modifier is not called in normal fashion, the
normal arg
argument to the template modifier does not
make sense. Instead, the arg
is set to the path of the
template which is being expanded. Also, template expansion modifiers
can be expensive, since they are applied pretty indiscriminately, so
it can be worth implementing the MightModifiy()
predicate
for the passed-in TemplateModifier
to avoid unnecessary
work.
The TemplateAnnotator
Class
The TemplateAnnotator
class is used to pass in to PerExpandData::SetAnnotator()
,
to control how expand-time annotation is done. This is meant to be
used as a debugging routine.
This class is an abstract base class; SetAnnotator()
takes a subclass that implements the various methods of the base
class. These methods control the action taken when various template
markers are seen during template expansion.
template_annotator.h
defines the abstract base class,
and also a concrete subclass that is used by default for annotation if
SetAnnotator()
is not called.
The
TemplateDictionaryPeer
Class
By design, it is not possible to view the contents of a
TemplateDictionary
; we want to make sure the interface
between the logic layer of the application and the presentation layer
of the template goes in only one direction. While generally this
keeps programs as clean as possible, it presents problems in testing
code, which may want to verify that a given
TemplateDictionary
has been filled properly. The
TemplateDictionaryPeer
addresses this need. It lives in
template_test_util.h
.
Some of the methods of TemplateDictionaryPeer
are
useful for internal tests only. Below are some of the methods that
are most useful for user-level tests.
STS_INIT_FOR_TEST
This macro allows use of STS_INIT
for testing, even
when the input pointer is not guaranteed to be allocated for the
entire length of the test (it must, of course, be allocated for the
entire lifetime of the template being tested). Since normally
STS_INIT
requires inputs to have static duration, this
allows for more flexibility in tests, at the cost of worse memory
management and decreased code safety (in that it's possible to
accidentally violate the lifetime requirements).
GetSectionValue()
This returns the value for the named variable. It uses normal
template scoping rules to resolve the name.
IsHiddenSection() and IsHiddenTemplate()
Checks if a section or sub-template is "hidden" (that is, won't be
displayed at all).
GetSectionDictionaries() and GetIncludeDictionaries()
Returns all the sub-dictionaries for a given section or
template-include, in a vector.>
Other Testing Functions
template_test_util.h has other useful routines for
testing, such as ExpandIs(), which tests whether a
template + dictionary pair expands into an expected string. See the
header file for details.
The ExpandEmitter
Class
There are two overloads of ExpandTemplate()
: the first
emits the expanded template to a C++ string, and the second emits to
an ExpandEmitter
: an abstract base class that serves as a
data source. It supports just one overloaded method,
Emit()
, that can take a char, a char*, or a C++ string as
input.
Using this class requires subclassing ExpandEmitter
and providing the various definitions for Emit()
. For
instance, a subclass might provide definitions of Emit()
that send the input bytes out to a network socket.
In addition to defining the abstract base class,
template_emitter.h
provides a sample concrete subclass
implementation, for emitting to a string.
The TemplateString
and
StaticTemplateString
Classes
TemplateString
is a string-like implementation.
Ctemplate uses TemplateString
almost exclusively,
internally. Many of the public API methods, such as
TemplateDictionary::SetValue()
, also take
TemplateString
as input. TemplateString
has implicit constructors for both C++ strings and char*'s, so every
method that takes a TemplateString
will also work if
given a C++ string or a char*. If you have a char* and know its
length, you can save a bit of work by explicitly constructing a
TemplateString
with a char* + length, for instance:
dict->SetValue(ctemplate::TemplateString("MYVAR", 5), value);
Some compile-time tools work with TemplateString
to
offload computation from runtime to compile-time. This is possible
because the Ctemplate code often stores a hash of a string
rather than a string directly. For static, immutable strings,
TemplateString
can store a pre-computed hash value. This
functionality is used by make_tpl_varnames_h
. Thus,
using this tool to create constants to use for SetValue()
keys provides not only protection against typos, but a speed
improvement as well.
For immutable strings in your code, you can create efficient
compile-time template-string objects of your own -- in this case of
type StaticTemplateString
-- by using the
STS_INIT
macro, like so:
static const StaticTemplateString kSectName =
STS_INIT(kSectName, "test_SetAddSectionDictionary");
The string variable's name, kSectName
is repeated
twice. The variable's value is specified inside the macro. Note that
this macro should be used at the top level of a file, not inside
functions (even when the variables are made static), and you should
define the StaticTemplateString
exactly as above:
static const StaticTemplateString
. Otherwise, the
undefined constructor/destructor order of C++ may result in surprising
behavior, wherein the StaticTemplateString
is not
initialized when it ought to be.
The Template
Class
In older version of ctemplate, the Template
class,
which holds parsed templates, was a major part of the template
workflow: the common template use-case would be:
Template* tpl = Template::GetTemplate(filename, strip_mode);
TemplateDictionary dict(name);
tpl->Expand(&dict, &outstring);
In current use, this model is deprecated in favor of the single
ExpandTemplate()
call; support for Template
methods may be removed entirely in future versions of ctemplate.
However, you may still find older code using this old formulation.
Auto-Escaping
The Guide to using Auto Escape has
an overview of Auto Escape as well as discussion of its limitations.
To use it, put the following text at the top of the template:
{{%AUTOESCAPE context="CONTEXT" [state="STATE"]}}
Description of the arguments:
- The context attribute is one of
HTML
,
JAVASCRIPT
, CSS
,
JSON
or XML
. It must correspond
to the context in which the browser will interpret this
template. Warning: Setting the wrong context will
result in wrong escaping applied to all variables in
the given template. In particular, if the template starts with
a <script>
tag, its context is
HTML
and not JAVASCRIPT
. Auto-Escape
will recognize the <script>
tag and hence
properly Javascript-escape the variables within it. Similarly,
if the template starts with a <style>
tag,
its context is HTML
and not CSS
.
- The state attribute is commonly omitted. It accepts the
value
IN_TAG
in the HTML
context
to indicate that the template only contains (one or more)
HTML attribute name and value pairs that are part of an
HTML tag formed in a parent template.
This will auto-escape every variable in the template. To turn off
auto-escaping for a particular variable, you can apply the
none
modifier, like so: {{MYVAR:none}}
.
Here is an example of an autoescaped document:
{{%AUTOESCAPE context="HTML"}}
<body>
<p>Hello {{USER}}</p>
<p><a href="{{URL}}">Your Account</a></p>
<p>Your identifier: {{ID:none}}{{! This is dangerous! }}</p>
</body>
Development Tools
This package includes several tools to make it easier to use write
and use templates.
make_tpl_varnames_h:
Template Syntax Checker and Header File Generator
make_tpl_varnames_h
is a "lint" style syntax checker
and header file generator. It takes the names of template files as
command line arguments and loads each file into a Template object by
retrieving the file via the Template factory method. The loading of
the file does pure syntax checking and reports such errors as
mis-matched section start/end markers, mis-matched open/close
double-curly braces, such as "{{VAR}"
, or invalid
characters in template variables/names/comments.
If the template passes the syntax check, by default the utility
then creates a header file for use in the executable code that fills
the dictionary for the template. If the developer includes this
header file, then constants in the header file may be referenced in
the dictionary building function, rather than hard-coding strings as
variable and section names. By using these constants, the compiler
can notify the developer of spelling errors and mismatched names.
Here's an example of how this is used, and how it helps prevent
errors:
const char * const kosr_RESULT_NUMBER = "RESULT_NUMBER"; // script output
dict.SetValue("RESSULT_NUMBER", "4"); // typo is silently missed
dict.SetValue(kosr_RESSULT_NUMBER, "4"); // compiler catches typo
Each constant is named as follows:
- The initial letter 'k', indicating a defined constant.
- One or more prefix letters which are derived from the
template file name. These prefix letters consist of the first
letter of the file name, followed by the first letter following
each underscore in the name, with the exception of the letter
'p' when it is followed by the letters "ost", as is a recommended convention for
template versioning. For example, the prefix letters for the
file
one_search_result_post20020815.tpl
are
osr
.
- An underscore.
- The variable or section name itself, same casing.
As an example, the section name "RESULT_NUMBER" in the file
one_search_result_post20020815.tpl would be given the constant name
kosr_RESULT_NUMBER
and would appear in the header file as
const char * const kosr_RESULT_NUMBER = "RESULT_NUMBER";
-- as in the example above. (The variable is actually a
StaticTemplateString
, not a char*, but the basic idea
holds.)
An alternate output directory may be specified by the command line
flag --header_dir
.
The name of the generated header file is the same as the name of
the template file with an extension added to the name. By default,
that extension is .varnames.h
. In the above example, the
header file containing the constant declarations would be named
one_search_result_post20020815.tpl.varnames.h
. An
alternate extension may be provided via the command line flag
--outputfile_suffix
.
Important command line flags:
-
--noheader
-- Indicates that a header file
should not be generated; only syntax checking should be done.
-
--header_dir
-- sets the directory where the header
is written. Default: "./"
-
--template_dir
-- sets the template root
directory. Default: ./
which is the correct
specification when it is run from the directory where the templates
are located. This is only used if the input template filenames
are specified as relative paths rather than absolute
paths.
-
--outputfile_suffix
-- the extension added to the
name of the template file to create the name of the generated
header file. Default: .varnames.h
.
For a full list of command line flags, run
make_tpl_varnames_h --help
.
template-converter: convert a
template to a C++ string
StringToTemplateCache()
lets you load a template
from a string instead of a file. Applications may prefer this option
to reduce the dependencies of the executable, or use it in
environments where data files are not practical. In such cases,
template-converter
can be used as a template "compiler",
letting the developer write a template file as a data file in the
normal way, and then "compiling" it to a C++ string to be included in
the executable.
Usage is template-converter <template filename>
.
C++ code is output is to stdout; it can be stored in a .h file or
included directly into a C++ file. Perl must be installed to use this
script.
Craig Silverstein
ctemplate-2.2/doc/tips.html 0000644 0001750 0001750 00000047476 11743633404 012715 0000000 0000000
Tips and Guidelines for Using the Ctemplate System
Tips and Guidelines for Using the Ctemplate System
(as of 10 March 2010)
The basic rules of the template system are
enough to use it, but over time, we at Google have developed some
tips, guidelines, and best practices that make it easier to use
templates effectively, and to avoid common template errors.
Program Design Considerations
Template naming and versioning
Early in Google's use of templates, we noticed a problem: if a
binary that uses a template and its corresponding template were both
modified, particularly if the change were such that the old binary
could not work with the new template or the new binary could not work
with the old template, then somehow they both had to be deployed at
the same instant to not present errors to our users. This was hard to
do. The solution was to adopt a template naming and versioning
convention. The procedure to use it follows:
- Each template name ends with
_postYYYYMMDD.tpl
,
where YYYMMDD is the date of this version's initial
creation.
- Before making (non-backward-compatible) modifications to a
template, copy the template to a new name, incorporating a
later date than the original one being copied.
- Edit the new file, and push it to the production server.
- Finally, update the code to refer to the new template-name
(ideally, using the
RegisterTemplateFilename
idiom), and push the new executable to the production
server.
When this convention is followed, the new template file does not
overwrite the old one when it is deployed, because it is a new file
with a new name. The old template file is still there to be used as
long as the old binary is still in production and the new template
file just sits there being ignored. Then when the new binary finally
gets deployed, it immediately starts using the new template file,
because it is coded (in RegisterTemplateFilename
) to do
so. After that, it is the old template file that continues to sit
there ignored.
The make_tpl_varnames_h
utility knows about the "_postYYYYMMDD" naming convention, so it
is important that you use that convention exactly if you use the
make_tpl_varnames_h
.
Processing Phases
Typically a program using the Ctemplate System will
perform the following phases, usually in this order:
- Retrieve and prepare the data used to fill a dictionary.
- Build the data dictionary, including all its
sub-dictionaries, that will supply the values to the
designated template object, its sections, and its
included templates.
- Retrieve the top-level template object required to
format the data. (This may or may
not involve reading and parsing a template file,
depending on whether the requested file has already
been read and parsed by the running program or
whether that file has been marked "reload if changed"
and was in fact changed.)
- Expand the template object into an output buffer
using the completed data dictionary.
- Output the buffer.
- Clean up: Destroy the top-level data dictionary
whenever it is no longer needed.
- Optionally, clear the cache at the end of program
execution.
One template / One procedure call
Most of the code of the program will be in Phases 1 and
2. Clearly, Phase 1 is outside the scope of the template system. But
in designing the code for Phase 2 (building the data dictionary), it
is wise to have the structure of the program reflect the structure of
the templates being used. Specifically, there should be a single
procedure call to build the dictionary for a single template. That
procedure call should take parameters that include all the data
required to populate the data dictionary for that template and all the
templates it includes. Following this "one template/one procedure
call" guideline further, for each included template, another procedure
should be called to populate the (or each) data dictionary for
that included template. This maintains the "one template/one procedure
call" principle in a nested fashion that reflects the nesting of the
templates.
This is not to imply that the "one procedure call" for a template
should not be modularized into sub-procedures for readability and
maintainability, or that it should not call other auxilliary
procedures for such things as formatting the data and converting it to
the appropriate strings, etc. But it does mean that there should be
one entry point for building the dictionary tree for one template and
that entry point should show the data dependencies of that template
through its parameter list. This code for populating the data
dictionary should NOT be intermingled with data gathering code
that should have been done in Phase 1.
(Inside Google, the convention has been used to name the dictionary
building procedure using the pattern fill_..._dictionary
where the dots are related to the name of the template the data is
being prepared for. For instance, the data for the template named
one_search_result.tpl might be placed in a dictionary via a function
named fill_one_search_result_dictionary
.)
Tips, Idioms, and Conventions
- Choose template names to create unique constant prefixes.
Template names should contain at least two words
to avoid constant prefix clashes (e.g. kxy_
instead of kx_
) The name of a new template
should be checked against the existing names before
proceeding. If your new template name produces a prefix that
conflicts with an already existing template, you should change
the name of your new template, even though it may be the only
perfect name you can come up with. You'll have to use a less
than perfect name in that case. (See "Template Syntax Checker
and Header File Generator" below for more explanation about
constant prefixes.)
- Use SetFormattedValue
discriminately.
This method should never be used to sneak HTML into the
executable as in
dictionary->SetFormattedValue(kxy_VAR,
"<b>%s</b>",
some_const_char_string);
In that case, the <b>
and
</b>
should be moved into the template.
- Never have a section encompass an entire template.
If the first line of a template is a start section marker
and the last line is its matching end section marker, then
those markers are unnecessary in almost all cases. They are
usually put there to allow the entire template to be hidden or
iterated, but since it encompasses the entire file, the
section may be hidden by not expanding the file (or by hiding
the template-include section that includes the file) and it
may be iterated by iterating the template-include marker of
the including template. (The only exception might be if the
entire page is to be iterated, but this seems a bit of a
stretch.)
- An included template is just a section whose contents are
located in a separate file. You may iterate over it just
like you do sections.
For example, if your template has the following
template-include marker:
{{>MY_INCLUDED_TEMPLATE}}
you may call
ctemplate::TemplateDictionary *child_dict =
dictionary->AddIncludeDictionary(kxy_MY_INCLUDED_TEMPLATE);
to iterate that section. (Note: Make sure you call
child_dict->SetFilename()
! If your included
template is not showing in the output, this is the first thing
you should check.)
- The recommended idiom to fill an include-template dictionary is
like this:
fill_include_template_dictionary(dict->AddIncludeDictionary(name), ...);
But what do you do if you decide, in
fill_include_template_dictionary
, that you don't
want to display anything for this include-template after all? It
seems like it's too late: you've already created the
sub-dictionary. The solution is simple: just be sure that
fill_include_template_dictionary()
doesn't call
SetFilename()
in that case.
- Never have a section which only contains another section.
For example, don't do this:
{{#OUTER_SECTION}}
{{#INNER_SECTION}}
section contents here
{{/INNER_SECTION}}
{{/OUTER_SECTION}}
or this equivalent template code (see the previous item):
{{#OUTER_SECTION}}
{{>INCLUDED_SECTION}}
{{/OUTER_SECTION}}
This is usually done because the developer thinks the outer
section must be used to hide the section when the inner
section, intended for iteration, has no iterations. In both
cases, you should only have one section (either
INNER_SECTION
or INCLUDED_SECTION
in
the examples) and iterate that section either 0 times or more
than 0 times. It's the wonder of the dual use of sections,
i.e. that they may be conditional or iterative or, in this case,
both.
A related suggestion: Do not have a section whose entire
contents is one variable marker with nothing else, unless you
need to iterate over that section with multiple values of that
variable. You don't need the surrounding section just to hide
the marker. A variable marker that is not set, does not
produce output. By convention, we set such variables to the
empty string. But in neither case do you need to hide it by
hiding a surrounding section that contains nothing else.
- Use this hide/show idiom for
if-else
blocks.
Since sections are hidden by default, you can use represent
if-else logic in your code via ShowSection
. For
example:
if ( my_test ) {
dict->ShowSection(kxyz_TRUE_BLOCK);
[ more code to fill the values for that section]
} else {
dict->ShowSection(kxyz_FALSE_BLOCK);
[ more code to fill the values for that section]
}
-
Write...
vs. Fill...Dictionary
methods
- Observe the proper division of labor, don't mix them.
The output (or write) function should create the top level
template dictionary, call one or more fill-dictionary routines
with it, then get the template and expand it. It should not call
dictionary modifying methods, like ShowSection
and SetValue
. By keeping these separated into
their own fill-dictionary routine, the code is more modular and
lends itself to template re-use. If you maintain the proper
division of labor, the template you are filling and outputting
may be filled and included in a larger template by someone
else.
- Use
AddSectionDictionary
only when you want to
iterate over a section or, secondarily, if you need to avoid name
conflicts.
Sometimes developers get the idea that every section requires
its own child dictionary created by an
AddSectionDictionary
call. Because of variable
inheritence, this isn't usually so. The intended purpose of
AddSectionDictionary
is to enable iteration over a
section. Secondarily, if the section contains generic names that
may conflict with the same name in other parts of the template,
it may be safer to call AddSectionDictionary
to
create a separate namespace. In any case, do not assume you must
call AddSectionDictionary
just because you are
working within a section. The main dictionary can be used for all
levels of conditional sections as long as you avoid name
conflicts by keeping the marker names unique.
- Do not place
RegisterTemplateFilename
statements in header (.h
) files.
RegisterTemplateFilename
is a macro that
instantiates a TemplateNamelist
object. If you place
it in a header file, a different object will get created each time
it is included in another .cc
file.
The RegisterTemplateFilename
statement and its
associated #include
of the varnames.h
file should occur only in the .cc
file that
implements the fill-dictionary routine for that template. You
should never have more than one
RegisterTemplateFilename
for a single template and
you should try hard not to copy the #include
file to
other files as well. The template versioning makes this more
important because a developer may not know that the template name
with included version number needs to be updated in more than one
file when versioning occurs. [Also see above for more information
about what routine uses the filename declared by the
RegisterTemplateFilename
statement.]
- Never reference more than one template in a
fill...dictionary method.
Each template should have its own fill-dictionary
routine. That routine should only reference marker names defined
in that template. If this convention is followed, then all the
prefixes in a fill-dictionary routine will be the same. [Note
that an implication of this convention is that if the template
includes another template, via a template-include marker, then
containing template's fill-dictionary routine should call the
included template's fill-dictionary routine (being careful to
observe the convention described above). But
then, this is merely a restatement of "One
template / One procedure call".]
- Have fill...dictionary call
SetFilename
even if the
dictionary is never used for a template-include.
SetFilename() is required when a dictionary is created via
AddIncludeDictionary()
. However, it's safe to set
all the time. By setting it always, you make the code work
properly if this dictionary ever changes to be template-included
after all. Even if not, by saying what template file the
dictionary is intended to go with, you are self-documenting your
code.
- Do not call
c_str()
on strings to pass them to
TemplateDictionary
methods.
Note that all the TemplateDictionary methods are defined to
take TemplateString
objects. These are created
automatically from both strings and char*'s (and can be created
manually if you have a char* and a length). So if you have a
string, it's safe and efficient to just pass it in directly; you
do not need to extract the const char * from your string object
to pass it to these methods. For some reason, this is a common
error of novice template coders.
The one exception to this rule is when using the method
SetFormattedValue
. When calling that
method, you must call c_str()
on strings that are to
be inserted
into the format string, just as you would when providing data for
any other printf format string.
- Do not use
SetGlobalValue
when you could use
SetValue
or SetTemplateGlobalValue
.
SetGlobalValue
should be used quite rarely, for
constants that really are consistent across all your templates.
It's slower to look up a value in the global dictionary than it
is in the template-specific dictionary.
- Do not use
StringToTemplateCache
unless you have
a specific need for its non-file-based attributes.
ctemplate::StringToTemplateCache
was created for
use in highly constrained cases where file I/O may be impaired or
undesirable, for instance to produce a server error message
where there may be disk problems or to produce formatted
output where there are processes that do not have a facility
for updating data files dynamically. It is not recommended for
ordinary use since it cannot be updated dynamically via a
data-push; changes always require a binary push.
- Use auto-escaping to prevent
Cross-Site-Scripting security vulnerabilities.
Use {{%AUTOESCAPE}}
consistently. Use the
:none
modifier to override autoesacping only in
those (usually rare) cases where there is a specific reason the
template variable should not be escaped, for example:
- The template variable contains HTML markup that should be
interpreted by the browser. In this case you must be very careful to
ensure that the variable can in no case contain "harmful" HTML. Also,
keep in mind the above
recommendation on the use of
SetFormattedValue
and
consider moving the HTML markup into the template.
- The variable is known to be already escaped at the point it
is inserted into the template (for example, the value might be
kept in escaped form in a storage backend). Here, escaping again
via a variable-modifier would result in "double escaping". You
must ensure that the variable comes escaped in the appropriate
context (that is, if you're inserting the variable into an html
document, it's html-escaped and not java-escaped).
- Do not leave an extra space when using
{{BI_SPACE}}
The built-in template variable BI_SPACE
is itself
replaced by a single space. It is used where you need to make
sure a space is preserved at the end of a line. It is a common
mistake to leave an extra space before this marker, which results
in not one, but two, spaces created in the document.
Incorrect:
<table border=0 {{BI_SPACE}}
align=center>
Correct:
<table border=0{{BI_SPACE}}
align=center>
Craig Silverstein
ctemplate-2.2/doc/xss_resources.html 0000644 0001750 0001750 00000004507 11743633404 014631 0000000 0000000
Cross-Site Scripting Resources
Cross-Site Scripting Resources
Status: Current
(as of 17 August 2006)
Cross-Site Scripting (commonly abbreviated as XSS) is a security
issue that arises when an attacker can cause client-side script (such as
JavaScript) of his or her choosing to execute within another user's
browser in the context of a given web-site or web-application. This may
allow the attacker to steal that user's session cookies for the
web-application in question, or otherwise manipulate that user's session
context.
XSS vulnerabilities most often arise if a web-application renders
data that originated from an untrusted source (such as a query
parameter) in a HTML document without carefully validating or escaping
that data.
The following online resources provide further information on XSS
vulnerabilities and how to avoid them:
- The Open Web Application Security Project (OWASP) has an
introductory
article on XSS.
- In addition, the OWASP's Guide to Building Secure Web
Applications and Web Services and the "Top
Ten" Vulnerabilities include sections on XSS.
- The CERT Coordination Center published Understanding
Malicious Content Mitigation for Web Developers and Advisory
CA-2000-02 Malicious HTML Tags Embedded in Client Web Requests.
ctemplate-2.2/doc/index.html 0000644 0001750 0001750 00000006415 11743633404 013031 0000000 0000000
Ctemplate (formerly Google Template) System
Ctemplate System
Status: Current
(as of 25 April 2008)
Welcome to the C++ CTemplate system! (This project was originally
called Google Templates, due to its origin as the template system used
for Google search result pages, but now has a more general name
matching its community-owned nature.)
As a quick start, here's a small but complete program that uses this
template library. For more details see, the links below.
Template file example.tpl
Hello {{NAME}},
You have just won ${{VALUE}}!
{{#IN_CA}}Well, ${{TAXED_VALUE}}, after taxes.{{/IN_CA}}
C++ program example.cc
#include <stdlib.h>
#include <string>
#include <iostream>
#include <ctemplate/template.h>
int main(int argc, char** argv) {
ctemplate::TemplateDictionary dict("example");
dict.SetValue("NAME", "John Smith");
int winnings = rand() % 100000;
dict.SetIntValue("VALUE", winnings);
dict.SetFormattedValue("TAXED_VALUE", "%.2f", winnings * 0.83);
// For now, assume everyone lives in CA.
// (Try running the program with a 0 here instead!)
if (1) {
dict.ShowSection("IN_CA");
}
std::string output;
ctemplate::ExpandTemplate("example.tpl", ctemplate::DO_NOT_STRIP, &dict, &output);
std::cout << output;
return 0;
}
Compiling and linking (using gcc)
gcc -o example example.cc -lctemplate_nothreads
I can use the "nothreads" library because example.cc
doesn't use threads. If example.cc
were threaded, I
would do something like this instead:
gcc -o example example.cc -lctemplate -pthread
See the README for more details about the two different ctemplate
libraries.
In-depth Documentation
- Howto: Introduction to the
Ctemplate system, and a tutorial for using it.
- Auto Escape: Guide to using
the optional Auto Escape mode to protect your web application
better against XSS.
- Tips: Advice, tips, and recommendations
for best practices with templates, to make them easier to write
and maintain, and to avoid common template mistakes.
- Examples: Some example templates and
application code that uses them. These are taken from actual
Google applications.
Craig Silverstein
Last modified: Mon Feb 22 10:59:03 PST 2010
ctemplate-2.2/NEWS 0000644 0001750 0001750 00000027360 11743633442 010772 0000000 0000000 == 18 April 2012 ==
Ctemplate 2.2 has been released. Several issues reported by G++ 4.7 have been fixed.
== 22 March 2012 ==
2.1 has been released. operator[] has been added to TemplateDictionary.
== 24 January 2012 ==
I've just released ctemplate 2.0. It has no functional changes from
ctemplate 1.2.
The `google-ctemplate` project has been renamed to `ctemplate`. I
(csilvers) am stepping down as maintainer, to be replaced by Olaf van
der Spek. Welcome to the team, Olaf! I've been impressed by your
contributions to the project discussions and code to date, and look
forward to having you on the team.
I bumped the major version number up to 2 to reflect the new community
ownership of the project. All the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-2.0/ChangeLog changes]
are related to the renaming.
=== 18 January 2011 ===
The `google-ctemplate` Google Code page has been renamed to
`ctemplate`, in preparation for the project being renamed to
`ctemplate`. In the coming weeks, I'll be stepping down as
maintainer for the ctemplate project, and as part of that Google is
relinquishing ownership of the project; it will now be entirely
community run. The name change reflects that shift.
=== 22 December 2011 ===
I've just released ctemplate 1.1. The only functionality change is
obscure: when a reload is done (via, say, `ReloadAllIfChanged`), and a
new file has been created since the last reload that both a) has the
same filename as a template file that had been loaded in the past, and
b) is earlier on the template search-path than the previously loaded
file, *and* c) the previously loaded file hasn't changed since the
last reload, then at reload-time we now load the new file into the
template, replacing the old file. Before we would only load the new
file if the old file had changed on disk, and would otherwise leave
the template alone. Even more minor changes are in the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-1.1/ChangeLog ChangeLog].
=== 26 August 2011 ===
I've just released ctemplate 1.0! (I've decided 4 weeks is well
within the definition of "the next week or so"...)
A bit anti-climactic: there are no changes from ctemplate 1.0rc2.
=== 29 July 2011 ===
I've just released ctemplate 1.0rc2. This fixes a serious bug where I
had added #includes in installed header files, that tried to include
non-installed header files. This means it was impossible to use
installed ctemplate; it only worked if you were using it from the
tarball directory.
I also fixed the unittest that was supposed to catch this, but didn't
(it was also building in the tarball directory).
If no further problems are found in the next week or so, I will
release ctemplate 1.0.
=== 22 July 2011 ===
I've just released ctemplate 1.0rc1. If no problems are found in the
next week or two, I will release ctemplate 1.0.
ctemplate 1.0rc1 has relatively few changes from ctemplate 0.99.
xml-escaping has been improved a bit. A couple of bugs have been
fixed, including one where we were ignoring template-global sections
(a relatively new feature) in some places. A full list of changes is
available in the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-1.0rc1/ChangeLog ChangeLog].
I've also changed the internal tools used to integrate
Google-supplied patches to ctemplate into the opensource release.
These new tools should result in more frequent updates with better
change descriptions. They will also result in future ChangeLog
entries being much more verbose (for better or for worse).
=== 24 January 2011 ===
I've just released ctemplate 0.99. I expect this to be the last
release before ctemplate 1.0. Code has settled down; the big change
here is some efficiency improvements to javascript template escaping.
There is also a bugfix for an obscure case where ReloadAllIfChanged()
is used with multiple ctemplate search paths, where files are deleted
in one part of the search path between reloads. Unless you need
either of the above, there's no particular reason to upgrade.
A full list of changes is available in the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-0.99/ChangeLog ChangeLog].
=== 23 September 2010 ===
I've just released ctemplate 0.98. The changes are settling down as
we approach ctemplate 1.0 -- a few new default modifiers, a few
performance tweaks, a few portability improvements, but nothing
disruptive.
In my testing for this release, I noticed that the template regression
test (but not other template tests) would segfault on gcc 4.1.1 when
compiled with -O2. This seems pretty clearly to be a compiler bug; if
you need to use gcc 4.1.1 to compile ctemplate, you may wish to build
via `./configure CXXFLAGS="-O1 -g"` just to be safe.
=== 20 April 2010 ===
I've just released ctemplate 0.97. This change consists primarily of
a significant change to the API: the addition of the `TemplateCache`
class, combined with deprecation of the `Template` class.
`TemplateCache` is a class that holds a collection of templates; this
concept always existed in ctemplate, but was not previously exposed.
Many static methods of the `Template` class, such as
`ReloadAllIfChanged()`, have become methods on `TemplateCache` instead
(the `Template` methods have been retained for backwards
compatibility.) Other methods, such as `Expand()`, have become free
functions. In fact, the entire `Template` class has been deprecated.
The deprecation of `Template` calls for changes in all clients of the
template code -- you can see in the example at the top of this page
how the code has changed from `Template* tpl =
ctemplate::Template::GetTemplate("example.tpl",
ctemplate::DO_NOT_STRIP); tpl->Expand(&output, &dict);` to
`ctemplate::ExpandTemplate("example.tpl", ctemplate::DO_NOT_STRIP,
&dict, &output);`. These changes will make the code simpler and more
thread-safe.
Old code should continue to work -- the `Template` class remains --
but new code should use the new API, and old code should transition as
convenient. One old API method is intrinsically thread-unsafe, and
should be prioritized to change: `tpl->ReloadIfChanged` should change
to `ctemplate::Template::ReloadAllIfChanged()`. Note this is a
semantic change: all templates are now reloaded, rather than just one.
However, since templates are reloaded lazily, and only if they've
changed on disk, I'm hopeful it will always be a reasonable change to
make.
To go along with these changes, the documentation has been almost
entirely revamped and made more accessible. Obscure ctemplate
features have been excised from the user's guide and moved into a
separate reference document. The new API is fully documented,
including new flexibility around reloading templates, made available
by the introduction of `TemplateCache`.
There are some more minor changes as well, such as the addition of
#include guards in the auto-generated .tpl.h files, to make it safe to
multiply-include them. I've also been continuing the portability
work: ctemplate should now work under Cygwin and MinGW. A full list
of changes is available in the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-0.97/ChangeLog ChangeLog].
I know I've said this before, but I don't expect major API changes
before the 1.0 release. The most significant changes I expect to see
are the potential removal of some of the 'forwarding' methods in the
(deprecated) `Template` class.
=== 12 June 2009 ===
I've just released ctemplate 0.95. This is entirely an API cleanup
release. Actually, relatively little of the API proper has changed:
`StringToTemplate` no longer takes an autoescape-context arg (instead
you specify this as part of the template-string, using the
`AUTOESCAPE` pragma). A few obsolete constructs have gone away, such
as the `TemplateFromString` class and
`TemplateDictionary::html_escape` and friends (just use the top-level
`html_escape`). See the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-0.95/ChangeLog
ChangeLog] for a full list of these changes.
The biggest change is a renaming: the default namespace is now
`ctemplate` rather than `google`, and the include directory is
`ctemplate` rather than `google`. Other namespaces, such as
`template_modifiers`, have gone away.
All these changes will require you to modify your old code to get it
working with ctemplate 0.95. I've written a
[http://google-ctemplate.googlecode.com/svn/trunk/contrib/convert_to_95.pl
script] to help you do that. Please open an
[http://code.google.com/p/google-ctemplate/issues/list issue] if you
see a problem with the script. I've tested it, but not as widely as
I'd like. Also note the script will not be perfect for more complex
constructs, which you will have to clean up by hand.
I hope (expect) the API is now stable, and we won't see any more such
changes before ctemplate 1.0. I tried to isolate them all in this
release; except for the API changes, this release should behave
identically to ctemplate 0.94.
=== 7 May 2009 ===
I've just released ctemplate 0.94. A few new features have been
added, such as the ability to expand a template into your own custom
`ExpandEmitter` instance, and the ability to hook the annotation
system (typically used for debugging). You can now remove strings
from the template cache in addition to adding them. Also, there
continues to be a trickle of new modifiers, in this case a modifier
for URL's in a CSS context.
However, the most invasive changes were made for speed reasons. The
biggest is that (almost) all `TemplateDictionary` allocations are now
done on the arena -- this includes allocations by the STL classes
inside the dictionary. This allows us to free all the memory at once,
rather than item by item, and has yielded a 3-4% speed improvement in
our tests. I've combined this with a `small_map` class that stores
items in a vector instead of a hash-map until we get to 3 or 4 items;
this gives another speed increase in the (common) case a template has
only a few sections or includes.
I also changed the hashing code to use
[http://murmurhash.googlepages.com/ MurmurHash] everywhere, rather
than the string hash function built into the STL library. This should
be faster.
All these changes should not be outwardly visible, but they do use
more advanced features of C++ than ctemplate has to date. This may
result in some problems compiling, or conceivably when running. If
you see any, please file an
[http://code.google.com/p/google-ctemplate/issues/list issue report].
You can see a full list of changes on the
[http://google-ctemplate.googlecode.com/svn/tags/ctemplate-0.94/ChangeLog
ChangeLog].
=== 20 August 2008 ===
ctemplate 0.91 introduces the beginning of some API changes, as I look
to clean up the API in preparation for ctemplate 1.0. After 1.0, the
API will remain backwards compatible, but until that time, the API may
change. Please take a look at the
[http://google-ctemplate.googlecode.com/svn/trunk/ChangeLog ChangeLog]
to see if any of these changes affect you.
One change is the introduction of a new `PerExpandData` class, which
holds some state that was formerly in the `TemplateDictionary` class.
I'm still not sure if this class is a good idea, if it should be
separate from `TemplateDictionary` or a member, or what functionality
should move there (for instance, should `SetTemplateGlobal` move
there, since template-global variables are really, in some sense,
per-expand variables?) If you have any feedback, ideally based on
your own experience using the current API, feel free to post it at
`google-ctemplate@googlegroups.com`.
ctemplate also has several new features, including the addition of
"separator" sections, and the ability to change the markup character
(from `{{`). See the
[http://google-ctemplate.googlecode.com/svn/trunk/ChangeLog ChangeLog]
for a complete list, and the
[http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html howto
documentation] for more details on these new features.
ctemplate-2.2/depcomp 0000755 0001750 0001750 00000042713 11743633405 011646 0000000 0000000 #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2007-03-29.01
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
# Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva .
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputing dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to .
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:
ctemplate-2.2/AUTHORS 0000644 0001750 0001750 00000000043 11743633405 011327 0000000 0000000 google-ctemplate@googlegroups.com
ctemplate-2.2/autogen.sh 0000755 0001750 0001750 00000001657 11743633405 012274 0000000 0000000 #!/bin/sh
# Before using, you should figure out all the .m4 macros that your
# configure.m4 script needs and make sure they exist in the m4/
# directory.
#
# These are the files that this script might edit:
# aclocal.m4 configure Makefile.in src/config.h.in \
# depcomp config.guess config.sub install-sh missing mkinstalldirs \
#
# Here's a command you can run to see what files aclocal will import:
# aclocal -I ../autoconf --output=- | sed -n 's/^m4_include..\([^]]*\).*/\1/p'
# Because libtoolize isn't in the hermetic build, autogen doesn't run it.
# However, it should be run manually periodically to update these files:
# in .: ltmain.sh
# in m4: libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4
set -ex
rm -rf autom4te.cache
aclocal --force -I m4
#grep -q LIBTOOL configure.ac && libtoolize -c -f
autoconf -f -W all,no-obsolete
autoheader -f -W all
automake -a -c -f -W all
rm -rf autom4te.cache
exit 0
ctemplate-2.2/aclocal.m4 0000644 0001750 0001750 00000111453 11743633625 012133 0000000 0000000 # generated automatically by aclocal 1.11.1 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
[m4_warning([this file was generated for autoconf 2.67.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.11.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.11.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 9
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ(2.52)dnl
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 10
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
# will think it sees a *use*, and therefore will trigger all it's
# C support machinery. Also note that it means that autoscan, seeing
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
# _AM_DEPENDENCIES(NAME)
# ----------------------
# See how the compiler implements dependency checking.
# NAME is "CC", "CXX", "GCJ", or "OBJC".
# We try a few techniques and use that to set a single cache variable.
#
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
# dependency, and given that the user is not expected to run this macro,
# just rely on AC_PROG_CC.
AC_DEFUN([_AM_DEPENDENCIES],
[AC_REQUIRE([AM_SET_DEPDIR])dnl
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
AC_REQUIRE([AM_DEP_TRACK])dnl
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
[$1], CXX, [depcc="$CXX" am_compiler_list=],
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], UPC, [depcc="$UPC" am_compiler_list=],
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
[depcc="$$1" am_compiler_list=])
AC_CACHE_CHECK([dependency style of $depcc],
[am_cv_$1_dependencies_compiler_type],
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_$1_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
fi
am__universal=false
m4_case([$1], [CC],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac],
[CXX],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac])
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
# Solaris 8's {/usr,}/bin/sh.
touch sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
am_cv_$1_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_$1_dependencies_compiler_type=none
fi
])
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
AM_CONDITIONAL([am__fastdep$1], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
])
# AM_SET_DEPDIR
# -------------
# Choose a directory name for dependency files.
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
AC_DEFUN([AM_SET_DEPDIR],
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
])
# AM_DEP_TRACK
# ------------
AC_DEFUN([AM_DEP_TRACK],
[AC_ARG_ENABLE(dependency-tracking,
[ --disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#serial 5
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[{
# Autoconf 2.62 quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
shift
for mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done
}
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
# AM_OUTPUT_DEPENDENCY_COMMANDS
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each `.P' file that we will
# need in order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 8
# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 16
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.62])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
[define([AC_PROG_CC],
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES(CXX)],
[define([AC_PROG_CXX],
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES(OBJC)],
[define([AC_PROG_OBJC],
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
])
dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST(install_sh)])
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from `make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 6
# AM_PROG_CC_C_O
# --------------
# Like AC_PROG_CC_C_O, but changed for automake.
AC_DEFUN([AM_PROG_CC_C_O],
[AC_REQUIRE([AC_PROG_CC_C_O])dnl
AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([compile])dnl
# FIXME: we rely on the cache variable name because
# there is no other way.
set dummy $CC
am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
if test "$am_t" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
dnl Make sure AC_PROG_CC is never called again, or it will override our
dnl setting of CC.
m4_define([AC_PROG_CC],
[m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 6
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
# If it does, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
AC_MSG_WARN([`missing' script is too old or missing])
fi
])
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
AC_DEFUN([AM_PROG_MKDIR_P],
[AC_PREREQ([2.60])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
dnl while keeping a definition of mkdir_p for backward compatibility.
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
dnl Makefile.ins that do not define MKDIR_P, so we do our own
dnl adjustment using top_builddir (which is defined more often than
dnl MKDIR_P).
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
case $mkdir_p in
[[\\/$]]* | ?:[[\\/]]*) ;;
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
esac
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# ------------------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ----------------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
esac
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT(yes)])
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 1
# AM_SILENT_RULES([DEFAULT])
# --------------------------
# Enable less verbose build rules; with the default set to DEFAULT
# (`yes' being less verbose, `no' or empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_ARG_ENABLE([silent-rules],
[ --enable-silent-rules less verbose build output (undo: `make V=1')
--disable-silent-rules verbose build output (undo: `make V=0')])
case $enable_silent_rules in
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility.
AM_MISSING_PROG([AMTAR], [tar])
m4_if([$1], [v7],
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar;
do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar /dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([m4/ac_have_attribute.m4])
m4_include([m4/ac_interlocked_exchange.m4])
m4_include([m4/ac_rwlock.m4])
m4_include([m4/acx_pthread.m4])
m4_include([m4/compiler_characteristics.m4])
m4_include([m4/google_namespace.m4])
m4_include([m4/libtool.m4])
m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])
m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
m4_include([m4/namespaces.m4])
m4_include([m4/stl_hash.m4])
m4_include([m4/stl_namespace.m4])
ctemplate-2.2/vsprojects/ 0000755 0001750 0001750 00000000000 11743633635 012551 5 0000000 0000000 ctemplate-2.2/vsprojects/template_dictionary_unittest/ 0000755 0001750 0001750 00000000000 11743633635 020550 5 0000000 0000000 ctemplate-2.2/vsprojects/template_dictionary_unittest/template_dictionary_unittest.vcproj 0000755 0001750 0001750 00000012716 11743633404 027720 0000000 0000000
ctemplate-2.2/vsprojects/template_test_util_test/ 0000755 0001750 0001750 00000000000 11743633635 017517 5 0000000 0000000 ctemplate-2.2/vsprojects/template_test_util_test/template_test_util_test.vcproj 0000644 0001750 0001750 00000013320 11743633404 025623 0000000 0000000
ctemplate-2.2/vsprojects/generate_fsm_c_test/ 0000755 0001750 0001750 00000000000 11743633635 016551 5 0000000 0000000 ctemplate-2.2/vsprojects/generate_fsm_c_test/generate_fsm_c_test.vcproj 0000644 0001750 0001750 00000007630 11743633404 023716 0000000 0000000
ctemplate-2.2/vsprojects/template_modifiers_unittest/ 0000755 0001750 0001750 00000000000 11743633635 020364 5 0000000 0000000 ctemplate-2.2/vsprojects/template_modifiers_unittest/template_modifiers_unittest.vcproj 0000755 0001750 0001750 00000013023 11743633404 027340 0000000 0000000
ctemplate-2.2/vsprojects/template_cache_test/ 0000755 0001750 0001750 00000000000 11743633635 016546 5 0000000 0000000 ctemplate-2.2/vsprojects/template_cache_test/template_cache_test.vcproj 0000755 0001750 0001750 00000012641 11743633404 023711 0000000 0000000
ctemplate-2.2/vsprojects/libctemplate/ 0000755 0001750 0001750 00000000000 11743633635 015216 5 0000000 0000000 ctemplate-2.2/vsprojects/libctemplate/libctemplate.vcproj 0000755 0001750 0001750 00000030036 11743633404 021027 0000000 0000000
ctemplate-2.2/vsprojects/make_tpl_varname_h/ 0000755 0001750 0001750 00000000000 11743633635 016365 5 0000000 0000000 ctemplate-2.2/vsprojects/make_tpl_varname_h/make_tpl_varname_h.vcproj 0000755 0001750 0001750 00000011374 11743633404 023351 0000000 0000000
ctemplate-2.2/vsprojects/statemachine_test/ 0000755 0001750 0001750 00000000000 11743633635 016255 5 0000000 0000000 ctemplate-2.2/vsprojects/statemachine_test/statemachine_test.vcproj 0000644 0001750 0001750 00000011515 11743633404 023123 0000000 0000000
ctemplate-2.2/vsprojects/template_setglobals_unittest/ 0000755 0001750 0001750 00000000000 11743633635 020542 5 0000000 0000000 ctemplate-2.2/vsprojects/template_setglobals_unittest/template_setglobals_unittest.vcproj 0000755 0001750 0001750 00000012645 11743633404 027705 0000000 0000000
ctemplate-2.2/vsprojects/diff_tpl_auto_escape/ 0000755 0001750 0001750 00000000000 11743633635 016710 5 0000000 0000000 ctemplate-2.2/vsprojects/diff_tpl_auto_escape/diff_tpl_auto_escape.vcproj 0000644 0001750 0001750 00000011551 11743633404 024211 0000000 0000000
ctemplate-2.2/vsprojects/template_unittest/ 0000755 0001750 0001750 00000000000 11743633635 016323 5 0000000 0000000 ctemplate-2.2/vsprojects/template_unittest/template_unittest.vcproj 0000755 0001750 0001750 00000012627 11743633404 023247 0000000 0000000
ctemplate-2.2/vsprojects/template_unittest_static/ 0000755 0001750 0001750 00000000000 11743633635 017672 5 0000000 0000000 ctemplate-2.2/vsprojects/template_unittest_static/template_unittest_static.vcproj 0000755 0001750 0001750 00000033622 11743633404 026163 0000000 0000000
ctemplate-2.2/vsprojects/compile_test/ 0000755 0001750 0001750 00000000000 11743633635 015240 5 0000000 0000000 ctemplate-2.2/vsprojects/compile_test/compile_test.vcproj 0000644 0001750 0001750 00000011512 11743633404 021066 0000000 0000000
ctemplate-2.2/vsprojects/htmlparser_test/ 0000755 0001750 0001750 00000000000 11743633635 015771 5 0000000 0000000 ctemplate-2.2/vsprojects/htmlparser_test/htmlparser_test.vcproj 0000644 0001750 0001750 00000007611 11743633404 022355 0000000 0000000
ctemplate-2.2/vsprojects/template_regtest/ 0000755 0001750 0001750 00000000000 11743633635 016121 5 0000000 0000000 ctemplate-2.2/vsprojects/template_regtest/template_regtest.vcproj 0000755 0001750 0001750 00000012622 11743633404 022636 0000000 0000000
ctemplate-2.2/contrib/ 0000755 0001750 0001750 00000000000 11743633404 012001 5 0000000 0000000 ctemplate-2.2/contrib/README.contrib 0000644 0001750 0001750 00000001300 11743633404 014232 0000000 0000000 All files under this contrib directory are UNSUPPORTED; use at your
own risk. They were provided by users of ctemplate and were not
tested by the authors of ctemplate. These files are not owned by
Google. Please contact the authors of the contributions for help
about these, not the ctemplate authors. Thanks!, and enjoy.
highlighting.vim by Patrick Lacasse
How to set up syntax highlighting (colorization) for ctemplate .tpl
files, using vim. A shar file; see top-of-file for how to extract.
tpl-mode.el by Tony Gentilcore
Elisp file for syntax highlighting (colorization) for ctemplate
.tpl files, using emacs. See top-of-file for how to use.
ctemplate-2.2/contrib/.svn/ 0000755 0001750 0001750 00000000000 11743633405 012666 5 0000000 0000000 ctemplate-2.2/contrib/.svn/entries 0000444 0001750 0001750 00000001463 11743633404 014203 0000000 0000000 10
dir
126
https://ctemplate.googlecode.com/svn/trunk/contrib
https://ctemplate.googlecode.com/svn
2012-01-25T01:28:24.102602Z
100
csilvers
cb39b542-eb2e-2a05-867b-f1791dd5f601
highlighting.vim
file
2012-04-18T21:49:56.000000Z
ee6d0e3f5a0485a9ab881804c6c5ae1a
2007-03-21T23:20:57.987219Z
15
csilvers
6981
tpl-mode.el
file
2012-04-18T21:49:56.000000Z
4ce6fd69000a3e93b7a86a243689c894
2012-01-25T01:28:24.102602Z
100
csilvers
8238
convert_to_95.pl
file
2012-04-18T21:49:56.000000Z
a2532acf199e0cc3a8bcfbdc612a266e
2009-06-13T00:30:27.370329Z
42
csilvers
has-props
5779
README.contrib
file
2012-04-18T21:49:56.000000Z
076a543356a7c43efc29c5fbd484af84
2007-03-21T23:20:57.987219Z
15
csilvers
704
ctemplate-2.2/contrib/.svn/all-wcprops 0000444 0001750 0001750 00000000737 11743633404 015000 0000000 0000000 K 25
svn:wc:ra_dav:version-url
V 31
/svn/!svn/ver/100/trunk/contrib
END
highlighting.vim
K 25
svn:wc:ra_dav:version-url
V 47
/svn/!svn/ver/15/trunk/contrib/highlighting.vim
END
tpl-mode.el
K 25
svn:wc:ra_dav:version-url
V 43
/svn/!svn/ver/100/trunk/contrib/tpl-mode.el
END
convert_to_95.pl
K 25
svn:wc:ra_dav:version-url
V 47
/svn/!svn/ver/42/trunk/contrib/convert_to_95.pl
END
README.contrib
K 25
svn:wc:ra_dav:version-url
V 45
/svn/!svn/ver/15/trunk/contrib/README.contrib
END
ctemplate-2.2/contrib/.svn/tmp/ 0000755 0001750 0001750 00000000000 11743633404 013465 5 0000000 0000000 ctemplate-2.2/contrib/.svn/tmp/prop-base/ 0000755 0001750 0001750 00000000000 11743633404 015355 5 0000000 0000000 ctemplate-2.2/contrib/.svn/tmp/text-base/ 0000755 0001750 0001750 00000000000 11743633404 015361 5 0000000 0000000 ctemplate-2.2/contrib/.svn/tmp/props/ 0000755 0001750 0001750 00000000000 11743633404 014630 5 0000000 0000000 ctemplate-2.2/contrib/.svn/prop-base/ 0000755 0001750 0001750 00000000000 11743633404 014555 5 0000000 0000000 ctemplate-2.2/contrib/.svn/prop-base/convert_to_95.pl.svn-base 0000444 0001750 0001750 00000000036 11743633404 021243 0000000 0000000 K 14
svn:executable
V 1
*
END
ctemplate-2.2/contrib/.svn/text-base/ 0000755 0001750 0001750 00000000000 11743633404 014561 5 0000000 0000000 ctemplate-2.2/contrib/.svn/text-base/highlighting.vim.svn-base 0000444 0001750 0001750 00000015505 11743633404 021404 0000000 0000000 #!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2006-08-08 13:38 PDT by .
# Commandline: shar -T .vim
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1477 -rw-r--r-- .vim/syntax/tpl.vim
# 56 -rw-r--r-- .vim/ftdetect/tpl.vim
#
echo >/dev/null <<_NOTES_EOF
From: Patrick Lacasse
Subject: vim color for google-ctemplate howto
To: google-ctemplate@googlegroups.com
Date: Fri, 4 Aug 2006 11:38:39 -0400
Hi group,
I'm now using google-ctemplate. My text editor is vim. Here is a little gift
for other people like me.
Howto have google-ctemplate colored by vim :
In your home directory, run 'sh $0'.
Now restart vim.
This will autodetects file with tpl extension and colors them. You can change
the color by changing the HiLink lines ( try changing String by
Identifier ) .
I'm not sure exactly about what are the legal marker names. Feel free to
change the regexes.
I only tryed this with vim 6.4 , I just cut and past the things about version
checking.
For more information about syntax higlithning in vim, try
:help syntax
Amusez-vous bien,
Patrick Lacasse
patlac@borabora.crchul.ulaval.ca
_NOTES_EOF
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh09814; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= .vim/syntax/tpl.vim ==============
if test ! -d '.vim'; then
$echo 'x -' 'creating directory' '.vim'
mkdir '.vim'
fi
if test ! -d '.vim/syntax'; then
$echo 'x -' 'creating directory' '.vim/syntax'
mkdir '.vim/syntax'
fi
if test -f '.vim/syntax/tpl.vim' && test "$first_param" != -c; then
$echo 'x -' SKIPPING '.vim/syntax/tpl.vim' '(file already exists)'
else
$echo 'x -' extracting '.vim/syntax/tpl.vim' '(text)'
sed 's/^X//' << 'SHAR_EOF' > '.vim/syntax/tpl.vim' &&
" Vim syntax file
" Language: google-ctemplate
" Maintainer: Patrick Lacasse
" Last Change: 2006 Août 03
"
" For information about google-ctemplate see
" http://goog-ctemplate.sourceforge.net/
"
" This vim syntax file works on vim 5.6, 5.7, 5.8 and 6.x.
" It implements Bram Moolenaar's April 25, 2001 recommendations to make
" the syntax file maximally portable across different versions of vim.
X
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
X syntax clear
elseif exists("b:current_syntax")
X finish
endif
X
syntax match tplMarkerError "{{}\?\([^}]\+}\?\)*}}"
syntax match tplSectionMarker "{{[#/][A-Za-z_]\+}}"
syntax match tplInclude "{{>[A-Za-z_]\+}}"
syntax match tplComment "{{![A-Za-z_]\+}}"
syntax match tplVariableMarker "{{[_A-Za-z]\+}}"
X
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_tpl_syn_inits")
X if version < 508
X let did_tpl_syn_inits = 1
X command -nargs=+ HiLink hi link
X else
X command -nargs=+ HiLink hi def link
X endif
X
X HiLink tplSectionMarker Repeat
X HiLink tplInclude Include
X HiLink tplComment Comment
X HiLink tplVariableMarker String
X HiLink tplMarkerError Error
X
X delcommand HiLink
endif
X
let b:current_syntax = "tpl"
SHAR_EOF
(set 20 06 08 08 13 34 11 '.vim/syntax/tpl.vim'; eval "$shar_touch") &&
chmod 0644 '.vim/syntax/tpl.vim' ||
$echo 'restore of' '.vim/syntax/tpl.vim' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo '.vim/syntax/tpl.vim:' 'MD5 check failed'
536faef79eff0597e642c5db04c1f79d .vim/syntax/tpl.vim
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/syntax/tpl.vim'`"
test 1477 -eq "$shar_count" ||
$echo '.vim/syntax/tpl.vim:' 'original size' '1477,' 'current size' "$shar_count!"
fi
fi
# ============= .vim/ftdetect/tpl.vim ==============
if test ! -d '.vim/ftdetect'; then
$echo 'x -' 'creating directory' '.vim/ftdetect'
mkdir '.vim/ftdetect'
fi
if test -f '.vim/ftdetect/tpl.vim' && test "$first_param" != -c; then
$echo 'x -' SKIPPING '.vim/ftdetect/tpl.vim' '(file already exists)'
else
$echo 'x -' extracting '.vim/ftdetect/tpl.vim' '(text)'
sed 's/^X//' << 'SHAR_EOF' > '.vim/ftdetect/tpl.vim' &&
au BufRead,BufNewFile *.tpl set filetype=tpl
SHAR_EOF
(set 20 06 08 08 13 34 20 '.vim/ftdetect/tpl.vim'; eval "$shar_touch") &&
chmod 0644 '.vim/ftdetect/tpl.vim' ||
$echo 'restore of' '.vim/ftdetect/tpl.vim' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo '.vim/ftdetect/tpl.vim:' 'MD5 check failed'
774fd4a092b77400ef6e74a7256ff8ef .vim/ftdetect/tpl.vim
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/ftdetect/tpl.vim'`"
test 56 -eq "$shar_count" ||
$echo '.vim/ftdetect/tpl.vim:' 'original size' '56,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh09814
exit 0
ctemplate-2.2/contrib/.svn/text-base/tpl-mode.el.svn-base 0000444 0001750 0001750 00000020056 11743633404 020262 0000000 0000000 ;;; tpl-mode.el -- a major mode for editing Google CTemplate files.
;;; By Tony Gentilcore, July 2006
;;;
;;; TO USE:
;;; 1) Copy this file somewhere you in emacs load-path. To see what
;;; your load-path is, run inside emacs: C-h v load-path
;;; 2) Add the following two lines to your .emacs file:
;;; (setq auto-mode-alist (cons '("\\.tpl$" . tpl-mode) auto-mode-alist))
;;; (autoload 'tpl-mode "tpl-mode" "Major mode for editing CTemplate files." t)
;;; 3) Optionally (but recommended), add this third line as well:
;;; (add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
;;; ---
;;;
;;; While the CTemplate language can be used for any types of text,
;;; this mode is intended for using CTemplate to write HTML.
;;;
;;; The indentation still has minor bugs due to the fact that
;;; templates do not require valid HTML.
;;;
;;; It would be nice to be able to highlight attributes of HTML tags,
;;; however this is difficult due to the presence of CTemplate symbols
;;; embedded within attributes.
(eval-when-compile
(require 'font-lock))
(defgroup tpl-mode nil
"Major mode for editing CTemplate files"
:group 'languages)
(defvar tpl-mode-version "1.0"
"Version of `tpl-mode.el'.")
(defvar tpl-mode-abbrev-table nil
"Abbrev table for use in tpl-mode buffers.")
(define-abbrev-table 'tpl-mode-abbrev-table ())
(defcustom tpl-mode-hook nil
"*Hook that runs upon entering tpl-mode."
:type 'hook
)
(defvar tpl-mode-map nil
"Keymap for tpl-mode major mode")
(if tpl-mode-map
nil
(setq tpl-mode-map (make-sparse-keymap))
)
(define-key tpl-mode-map "\t" 'tpl-indent-command)
(define-key tpl-mode-map "\C-m" 'newline-and-indent)
(defvar tpl-mode-syntax-table nil
"Syntax table in use in tpl-mode buffers.")
;; Syntax table.
(if tpl-mode-syntax-table
nil
(setq tpl-mode-syntax-table (make-syntax-table text-mode-syntax-table))
(modify-syntax-entry ?< "(> " tpl-mode-syntax-table)
(modify-syntax-entry ?> ")< " tpl-mode-syntax-table)
(modify-syntax-entry ?\" ". " tpl-mode-syntax-table)
(modify-syntax-entry ?\\ ". " tpl-mode-syntax-table)
(modify-syntax-entry ?' "w " tpl-mode-syntax-table)
)
(defvar tpl-basic-offset 2
"The basic indentation offset.")
;; Constant regular expressions to identify template elements.
(defconst tpl-mode-tpl-token "[a-zA-Z][a-zA-Z0-9_:=\-]*?")
(defconst tpl-mode-section (concat "\\({{[#/]"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-open-section (concat "\\({{#"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-close-section (concat "{{/\\("
tpl-mode-tpl-token
"\\)}}"))
(defconst tpl-mode-comment "\\({{![^}]+?}}\\)")
(defconst tpl-mode-include (concat "\\({{>"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-variable (concat "\\({{"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-builtins
(concat
"\\({{\\<"
(regexp-opt
'("BI_NEWLINE" "BI_SPACE")
t)
"\\>}}\\)"))
(defconst tpl-mode-close-section-at-start (concat "^[ \t]*?"
tpl-mode-close-section))
;; Constant regular expressions to identify html tags.
;; Taken from HTML 4.01 / XHTML 1.0 Reference found at:
;; http://www.w3schools.com/tags/default.asp.
(defconst tpl-mode-html-constant "\\(?[a-z0-9]\\{2,5\\};\\)")
(defconst tpl-mode-pair-tag
(concat
"\\<"
(regexp-opt
'("a" "abbr" "acronym" "address" "applet" "area" "b" "bdo"
"big" "blockquote" "body" "button" "caption" "center" "cite"
"code" "col" "colgroup" "dd" "del" "dfn" "dif" "div" "dl"
"dt" "em" "fieldset" "font" "form" "frame" "frameset" "h1"
"h2" "h3" "h4" "h5" "h6" "head" "html" "i" "iframe" "ins"
"kbd" "label" "legend" "li" "link" "map" "menu" "noframes"
"noscript" "object" "ol" "optgroup" "option" "p" "pre" "q"
"s" "samp" "script" "select" "small" "span" "strike"
"strong" "style" "sub" "sup" "table" "tbody" "td" "textarea"
"tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
t)
"\\>"))
(defconst tpl-mode-standalone-tag
(concat
"\\<"
(regexp-opt
'("base" "br" "hr" "img" "input" "meta" "param")
t)
"\\>"))
(defconst tpl-mode-open-tag (concat "<\\("
tpl-mode-pair-tag
"\\)"))
(defconst tpl-mode-close-tag (concat "\\("
tpl-mode-pair-tag
"\\)>"))
(defconst tpl-mode-close-tag-at-start (concat "^[ \t]*?"
tpl-mode-close-tag))
(defconst tpl-mode-blank-line "^[ \t]*?$")
(defconst tpl-mode-dangling-open (concat "\\("
tpl-mode-open-section
"\\)\\|\\("
tpl-mode-open-tag
"\\)[^/]*$"))
(defun tpl-indent-command ()
"Command for indenting text. Just calls tpl-indent."
(interactive)
(tpl-indent))
;; Function to control indenting.
(defun tpl-indent ()
"Indent current line"
;; Set the point to beginning of line.
(beginning-of-line)
;; If we are at the beginning of the file, indent to 0.
(if (bobp)
(indent-line-to 0)
(let ((tag-stack 1) (close-tag "") (cur-indent 0) (old-pnt (point-marker))
(close-at-start) (open-token) (dangling-open))
(progn
;; Determine if this is a template line or an html line.
(if (looking-at "^[ \t]*?{{")
(setq close-at-start tpl-mode-close-section-at-start
open-token "{{#")
(setq close-at-start tpl-mode-close-tag-at-start
open-token "<")
)
;; If there is a closing tag at the start of the line, search back
;; for its opener and indent to that level.
(if (looking-at close-at-start)
(progn
(save-excursion
(setq close-tag (match-string 1))
;; Keep searching for a match for the close tag until
;; the tag-stack is 0.
(while (and (not (bobp))
(> tag-stack 0)
(re-search-backward (concat open-token
"\\(/?\\)"
close-tag) nil t))
(if (string-equal (match-string 1) "/")
;; We found another close tag, so increment tag-stack.
(setq tag-stack (+ tag-stack 1))
;; We found an open tag, so decrement tag-stack.
(setq tag-stack (- tag-stack 1))
)
(setq cur-indent (current-indentation))
)
)
(if (> tag-stack 0)
(save-excursion
(forward-line -1)
(setq cur-indent (current-indentation))
)
)
)
;; This was not a closing tag, so we check if the previous line
;; was an opening tag.
(save-excursion
;; Keep moving back until we find a line that is not blank
(while (progn
(forward-line -1)
(and (not (bobp)) (looking-at tpl-mode-blank-line))
)
)
(setq cur-indent (current-indentation))
(if (re-search-forward tpl-mode-dangling-open old-pnt t)
(setq cur-indent (+ cur-indent tpl-basic-offset))
)
)
)
;; Finally, we execute the actual indentation.
(if (> cur-indent 0)
(indent-line-to cur-indent)
(indent-line-to 0)
)
)
)
)
)
;; controls highlighting
(defconst tpl-mode-font-lock-keywords
(list
(list tpl-mode-section
'(1 font-lock-keyword-face))
(list tpl-mode-comment
'(1 font-lock-comment-face))
(list tpl-mode-include
'(1 font-lock-builtin-face))
(list tpl-mode-builtins
'(1 font-lock-variable-name-face))
(list tpl-mode-variable
'(1 font-lock-reference-face))
(list (concat "?\\(" tpl-mode-pair-tag "\\)")
'(1 font-lock-function-name-face))
(list (concat "<\\(" tpl-mode-standalone-tag "\\)")
'(1 font-lock-function-name-face))
(list tpl-mode-html-constant
'(1 font-lock-variable-name-face))
))
(put 'tpl-mode 'font-lock-defaults '(tpl-font-lock-keywords nil t))
(defun tpl-mode ()
"Major mode for editing CTemplate file."
(interactive)
(kill-all-local-variables)
(use-local-map tpl-mode-map)
(setq major-mode 'tpl-mode)
(setq mode-name "tpl-mode")
(setq local-abbrev-table tpl-mode-abbrev-table)
(setq indent-tabs-mode nil)
(set-syntax-table tpl-mode-syntax-table)
; show trailing whitespace, but only when the user can fix it
(setq show-trailing-whitespace (not buffer-read-only))
(make-local-variable 'indent-line-function)
(setq indent-line-function 'tpl-indent)
(setq font-lock-defaults '(tpl-mode-font-lock-keywords))
(run-hooks 'tpl-mode-hook)
)
(provide 'tpl-mode)
ctemplate-2.2/contrib/.svn/text-base/convert_to_95.pl.svn-base 0000444 0001750 0001750 00000013223 11743633404 021251 0000000 0000000 #!/usr/bin/perl -pli.bak
# Copyright (c) 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ---
# Author: Craig Silverstein
# This is a perl script for editing your source files that were
# written with ctemplate <0.95, to use the new #include paths,
# namespace names, and function locations in ctemplate 0.95.
#
# This script will modify your files in place. It is safe to
# call it multiple times. To call it, do something like:
# find -print0 | xargs -0 ./convert_to_95.pl
#
# Issues:
# TemplateFromString logic is tricky. Best to check up by hand.
# Can't always tell when 1st arg to TemplateFromString is empty string.
# If it might be for your app, change the logic to use StringToTemplate.
# Fails if TemplateFromString or StringToTemplate span multiple lines.
# Change all the #include lines
s@google/template.h@ctemplate/template.h@g;
s@google/per_expand_data.h@ctemplate/per_expand_data.h@g;
s@google/template.h@ctemplate/template.h@g;
s@google/template_annotator.h@ctemplate/template_annotator.h@g;
s@google/template_dictionary.h@ctemplate/template_dictionary.h@g;
s@google/template_dictionary_interface.h@ctemplate/template_dictionary_interface.h@g;
s@google/template_emitter.h@ctemplate/template_emitter.h@g;
s@google/template_enums.h@ctemplate/template_enums.h@g;
s@google/template_from_string.h@ctemplate/template_from_string.h@g;
s@google/template_modifiers.h@ctemplate/template_modifiers.h@g;
s@google/template_namelist.h@ctemplate/template_namelist.h@g;
s@google/template_pathops.h@ctemplate/template_pathops.h@g;
s@google/template_string.h@ctemplate/template_string.h@g;
# Change all the namespace uses
s@namespace\s+google@namespace ctemplate@g; # brought into google namespace
s@\bgoogle::@ctemplate::@g;
s@namespace\s+template_modifiers\s*{@@ && ($in_tm = 1);
$in_tm && s@}@@ && ($in_tm = 0);
s@\btemplate_modifiers::@@g;
# Change TemplateFromString::GetTemplate to
# Template::StringToTemplateCache(cache_key, template_text);
# return Template::GetTemplate(cache_key, strip);
# unless cache_key is the empty string, in which case it should be
# return Template::StringToTemplate(template_text, strip, TC_MANUAL);
# We have to be tricky, to do this in one command.
# Better would be to just do Template::StringToTemplate(), but then we
# have to free the memory when we're done, which is too hard to do here.
s@TemplateFromString::GetTemplate\s*\(""\s*,([^,]+),([^,]+)\)@Template::StringToTemplate($1, $2, ctemplate::TC_MANUAL)@;
s@TemplateFromString::GetTemplate\s*\(([^,]+),([^,]+),([^,]+)\)@Template::GetTemplate((ctemplate::Template::StringToTemplateCache($1, $2), $1), $3)@;
if (m@TemplateFromString::GetTemplate\s*\([^)]*$@) {
warn("$ARGV:$.: TemplateFromString spans mutiple lines. You will need " .
"to clean it up by hand. See comments in $0.");
}
# Get rid of the 4th arg to Template::TemplateToString. If it's
# TC_MANUAL, that's fine. If it's not, we need to tell the user to
# fix this up manually by adding an {{%PRAGMA AUTOESCAPE}} to the
# beginning of their string.
if (s@(\bStringToTemplate\s*\([^)]*),\s*TC_([A-Z_]*)@$1@g) {
if ($2 ne "MANUAL") { # TC_MANUAL is the new default
warn("WARNING: $ARGV:$.: You will need to manually fix up the " .
"StringToTemplate change to add an AUTOESCAPE {{\%pragma}} to " .
"the beginning of the input string, to set the context to TC_$2\n");
}
}
if (m@\bStringToTemplate\s*\([^)]*$@) {
warn("$ARGV:$.: StringToTemplate spans mutiple lines. You will need " .
"to clean it up by hand: get rid of the TC_foo arg. If it's not " .
"TC_MANUAL, you will need to add an AUTOESCAPE pragma. " .
"See comments in $0.");
}
# Change all the TemplateDictionary escapes. Now they are globals in
# the ctemplate namespace.
s@TemplateDictionary::html_escape@html_escape@g;
s@TemplateDictionary::pre_escape@pre_escape@g;
s@TemplateDictionary::xml_escape@xml_escape@g;
s@TemplateDictionary::javascript_escape@javascript_escape@g;
s@TemplateDictionary::url_query_escape@url_query_escape@g;
s@TemplateDictionary::json_escape@json_escape@g;
# This cleans up anything messy we left behind.
s@\bctemplate::ctemplate::@ctemplate::@g; # get rid of redundant specifier
close ARGV if eof; # to reset $. for each file
ctemplate-2.2/contrib/.svn/text-base/README.contrib.svn-base 0000444 0001750 0001750 00000001300 11743633404 020525 0000000 0000000 All files under this contrib directory are UNSUPPORTED; use at your
own risk. They were provided by users of ctemplate and were not
tested by the authors of ctemplate. These files are not owned by
Google. Please contact the authors of the contributions for help
about these, not the ctemplate authors. Thanks!, and enjoy.
highlighting.vim by Patrick Lacasse
How to set up syntax highlighting (colorization) for ctemplate .tpl
files, using vim. A shar file; see top-of-file for how to extract.
tpl-mode.el by Tony Gentilcore
Elisp file for syntax highlighting (colorization) for ctemplate
.tpl files, using emacs. See top-of-file for how to use.
ctemplate-2.2/contrib/.svn/props/ 0000755 0001750 0001750 00000000000 11743633404 014030 5 0000000 0000000 ctemplate-2.2/contrib/tpl-mode.el 0000644 0001750 0001750 00000020056 11743633404 013767 0000000 0000000 ;;; tpl-mode.el -- a major mode for editing Google CTemplate files.
;;; By Tony Gentilcore, July 2006
;;;
;;; TO USE:
;;; 1) Copy this file somewhere you in emacs load-path. To see what
;;; your load-path is, run inside emacs: C-h v load-path
;;; 2) Add the following two lines to your .emacs file:
;;; (setq auto-mode-alist (cons '("\\.tpl$" . tpl-mode) auto-mode-alist))
;;; (autoload 'tpl-mode "tpl-mode" "Major mode for editing CTemplate files." t)
;;; 3) Optionally (but recommended), add this third line as well:
;;; (add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
;;; ---
;;;
;;; While the CTemplate language can be used for any types of text,
;;; this mode is intended for using CTemplate to write HTML.
;;;
;;; The indentation still has minor bugs due to the fact that
;;; templates do not require valid HTML.
;;;
;;; It would be nice to be able to highlight attributes of HTML tags,
;;; however this is difficult due to the presence of CTemplate symbols
;;; embedded within attributes.
(eval-when-compile
(require 'font-lock))
(defgroup tpl-mode nil
"Major mode for editing CTemplate files"
:group 'languages)
(defvar tpl-mode-version "1.0"
"Version of `tpl-mode.el'.")
(defvar tpl-mode-abbrev-table nil
"Abbrev table for use in tpl-mode buffers.")
(define-abbrev-table 'tpl-mode-abbrev-table ())
(defcustom tpl-mode-hook nil
"*Hook that runs upon entering tpl-mode."
:type 'hook
)
(defvar tpl-mode-map nil
"Keymap for tpl-mode major mode")
(if tpl-mode-map
nil
(setq tpl-mode-map (make-sparse-keymap))
)
(define-key tpl-mode-map "\t" 'tpl-indent-command)
(define-key tpl-mode-map "\C-m" 'newline-and-indent)
(defvar tpl-mode-syntax-table nil
"Syntax table in use in tpl-mode buffers.")
;; Syntax table.
(if tpl-mode-syntax-table
nil
(setq tpl-mode-syntax-table (make-syntax-table text-mode-syntax-table))
(modify-syntax-entry ?< "(> " tpl-mode-syntax-table)
(modify-syntax-entry ?> ")< " tpl-mode-syntax-table)
(modify-syntax-entry ?\" ". " tpl-mode-syntax-table)
(modify-syntax-entry ?\\ ". " tpl-mode-syntax-table)
(modify-syntax-entry ?' "w " tpl-mode-syntax-table)
)
(defvar tpl-basic-offset 2
"The basic indentation offset.")
;; Constant regular expressions to identify template elements.
(defconst tpl-mode-tpl-token "[a-zA-Z][a-zA-Z0-9_:=\-]*?")
(defconst tpl-mode-section (concat "\\({{[#/]"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-open-section (concat "\\({{#"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-close-section (concat "{{/\\("
tpl-mode-tpl-token
"\\)}}"))
(defconst tpl-mode-comment "\\({{![^}]+?}}\\)")
(defconst tpl-mode-include (concat "\\({{>"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-variable (concat "\\({{"
tpl-mode-tpl-token
"}}\\)"))
(defconst tpl-mode-builtins
(concat
"\\({{\\<"
(regexp-opt
'("BI_NEWLINE" "BI_SPACE")
t)
"\\>}}\\)"))
(defconst tpl-mode-close-section-at-start (concat "^[ \t]*?"
tpl-mode-close-section))
;; Constant regular expressions to identify html tags.
;; Taken from HTML 4.01 / XHTML 1.0 Reference found at:
;; http://www.w3schools.com/tags/default.asp.
(defconst tpl-mode-html-constant "\\(?[a-z0-9]\\{2,5\\};\\)")
(defconst tpl-mode-pair-tag
(concat
"\\<"
(regexp-opt
'("a" "abbr" "acronym" "address" "applet" "area" "b" "bdo"
"big" "blockquote" "body" "button" "caption" "center" "cite"
"code" "col" "colgroup" "dd" "del" "dfn" "dif" "div" "dl"
"dt" "em" "fieldset" "font" "form" "frame" "frameset" "h1"
"h2" "h3" "h4" "h5" "h6" "head" "html" "i" "iframe" "ins"
"kbd" "label" "legend" "li" "link" "map" "menu" "noframes"
"noscript" "object" "ol" "optgroup" "option" "p" "pre" "q"
"s" "samp" "script" "select" "small" "span" "strike"
"strong" "style" "sub" "sup" "table" "tbody" "td" "textarea"
"tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
t)
"\\>"))
(defconst tpl-mode-standalone-tag
(concat
"\\<"
(regexp-opt
'("base" "br" "hr" "img" "input" "meta" "param")
t)
"\\>"))
(defconst tpl-mode-open-tag (concat "<\\("
tpl-mode-pair-tag
"\\)"))
(defconst tpl-mode-close-tag (concat "\\("
tpl-mode-pair-tag
"\\)>"))
(defconst tpl-mode-close-tag-at-start (concat "^[ \t]*?"
tpl-mode-close-tag))
(defconst tpl-mode-blank-line "^[ \t]*?$")
(defconst tpl-mode-dangling-open (concat "\\("
tpl-mode-open-section
"\\)\\|\\("
tpl-mode-open-tag
"\\)[^/]*$"))
(defun tpl-indent-command ()
"Command for indenting text. Just calls tpl-indent."
(interactive)
(tpl-indent))
;; Function to control indenting.
(defun tpl-indent ()
"Indent current line"
;; Set the point to beginning of line.
(beginning-of-line)
;; If we are at the beginning of the file, indent to 0.
(if (bobp)
(indent-line-to 0)
(let ((tag-stack 1) (close-tag "") (cur-indent 0) (old-pnt (point-marker))
(close-at-start) (open-token) (dangling-open))
(progn
;; Determine if this is a template line or an html line.
(if (looking-at "^[ \t]*?{{")
(setq close-at-start tpl-mode-close-section-at-start
open-token "{{#")
(setq close-at-start tpl-mode-close-tag-at-start
open-token "<")
)
;; If there is a closing tag at the start of the line, search back
;; for its opener and indent to that level.
(if (looking-at close-at-start)
(progn
(save-excursion
(setq close-tag (match-string 1))
;; Keep searching for a match for the close tag until
;; the tag-stack is 0.
(while (and (not (bobp))
(> tag-stack 0)
(re-search-backward (concat open-token
"\\(/?\\)"
close-tag) nil t))
(if (string-equal (match-string 1) "/")
;; We found another close tag, so increment tag-stack.
(setq tag-stack (+ tag-stack 1))
;; We found an open tag, so decrement tag-stack.
(setq tag-stack (- tag-stack 1))
)
(setq cur-indent (current-indentation))
)
)
(if (> tag-stack 0)
(save-excursion
(forward-line -1)
(setq cur-indent (current-indentation))
)
)
)
;; This was not a closing tag, so we check if the previous line
;; was an opening tag.
(save-excursion
;; Keep moving back until we find a line that is not blank
(while (progn
(forward-line -1)
(and (not (bobp)) (looking-at tpl-mode-blank-line))
)
)
(setq cur-indent (current-indentation))
(if (re-search-forward tpl-mode-dangling-open old-pnt t)
(setq cur-indent (+ cur-indent tpl-basic-offset))
)
)
)
;; Finally, we execute the actual indentation.
(if (> cur-indent 0)
(indent-line-to cur-indent)
(indent-line-to 0)
)
)
)
)
)
;; controls highlighting
(defconst tpl-mode-font-lock-keywords
(list
(list tpl-mode-section
'(1 font-lock-keyword-face))
(list tpl-mode-comment
'(1 font-lock-comment-face))
(list tpl-mode-include
'(1 font-lock-builtin-face))
(list tpl-mode-builtins
'(1 font-lock-variable-name-face))
(list tpl-mode-variable
'(1 font-lock-reference-face))
(list (concat "?\\(" tpl-mode-pair-tag "\\)")
'(1 font-lock-function-name-face))
(list (concat "<\\(" tpl-mode-standalone-tag "\\)")
'(1 font-lock-function-name-face))
(list tpl-mode-html-constant
'(1 font-lock-variable-name-face))
))
(put 'tpl-mode 'font-lock-defaults '(tpl-font-lock-keywords nil t))
(defun tpl-mode ()
"Major mode for editing CTemplate file."
(interactive)
(kill-all-local-variables)
(use-local-map tpl-mode-map)
(setq major-mode 'tpl-mode)
(setq mode-name "tpl-mode")
(setq local-abbrev-table tpl-mode-abbrev-table)
(setq indent-tabs-mode nil)
(set-syntax-table tpl-mode-syntax-table)
; show trailing whitespace, but only when the user can fix it
(setq show-trailing-whitespace (not buffer-read-only))
(make-local-variable 'indent-line-function)
(setq indent-line-function 'tpl-indent)
(setq font-lock-defaults '(tpl-mode-font-lock-keywords))
(run-hooks 'tpl-mode-hook)
)
(provide 'tpl-mode)
ctemplate-2.2/contrib/convert_to_95.pl 0000755 0001750 0001750 00000013223 11743633404 014761 0000000 0000000 #!/usr/bin/perl -pli.bak
# Copyright (c) 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ---
# Author: Craig Silverstein
# This is a perl script for editing your source files that were
# written with ctemplate <0.95, to use the new #include paths,
# namespace names, and function locations in ctemplate 0.95.
#
# This script will modify your files in place. It is safe to
# call it multiple times. To call it, do something like:
# find -print0 | xargs -0 ./convert_to_95.pl
#
# Issues:
# TemplateFromString logic is tricky. Best to check up by hand.
# Can't always tell when 1st arg to TemplateFromString is empty string.
# If it might be for your app, change the logic to use StringToTemplate.
# Fails if TemplateFromString or StringToTemplate span multiple lines.
# Change all the #include lines
s@google/template.h@ctemplate/template.h@g;
s@google/per_expand_data.h@ctemplate/per_expand_data.h@g;
s@google/template.h@ctemplate/template.h@g;
s@google/template_annotator.h@ctemplate/template_annotator.h@g;
s@google/template_dictionary.h@ctemplate/template_dictionary.h@g;
s@google/template_dictionary_interface.h@ctemplate/template_dictionary_interface.h@g;
s@google/template_emitter.h@ctemplate/template_emitter.h@g;
s@google/template_enums.h@ctemplate/template_enums.h@g;
s@google/template_from_string.h@ctemplate/template_from_string.h@g;
s@google/template_modifiers.h@ctemplate/template_modifiers.h@g;
s@google/template_namelist.h@ctemplate/template_namelist.h@g;
s@google/template_pathops.h@ctemplate/template_pathops.h@g;
s@google/template_string.h@ctemplate/template_string.h@g;
# Change all the namespace uses
s@namespace\s+google@namespace ctemplate@g; # brought into google namespace
s@\bgoogle::@ctemplate::@g;
s@namespace\s+template_modifiers\s*{@@ && ($in_tm = 1);
$in_tm && s@}@@ && ($in_tm = 0);
s@\btemplate_modifiers::@@g;
# Change TemplateFromString::GetTemplate to
# Template::StringToTemplateCache(cache_key, template_text);
# return Template::GetTemplate(cache_key, strip);
# unless cache_key is the empty string, in which case it should be
# return Template::StringToTemplate(template_text, strip, TC_MANUAL);
# We have to be tricky, to do this in one command.
# Better would be to just do Template::StringToTemplate(), but then we
# have to free the memory when we're done, which is too hard to do here.
s@TemplateFromString::GetTemplate\s*\(""\s*,([^,]+),([^,]+)\)@Template::StringToTemplate($1, $2, ctemplate::TC_MANUAL)@;
s@TemplateFromString::GetTemplate\s*\(([^,]+),([^,]+),([^,]+)\)@Template::GetTemplate((ctemplate::Template::StringToTemplateCache($1, $2), $1), $3)@;
if (m@TemplateFromString::GetTemplate\s*\([^)]*$@) {
warn("$ARGV:$.: TemplateFromString spans mutiple lines. You will need " .
"to clean it up by hand. See comments in $0.");
}
# Get rid of the 4th arg to Template::TemplateToString. If it's
# TC_MANUAL, that's fine. If it's not, we need to tell the user to
# fix this up manually by adding an {{%PRAGMA AUTOESCAPE}} to the
# beginning of their string.
if (s@(\bStringToTemplate\s*\([^)]*),\s*TC_([A-Z_]*)@$1@g) {
if ($2 ne "MANUAL") { # TC_MANUAL is the new default
warn("WARNING: $ARGV:$.: You will need to manually fix up the " .
"StringToTemplate change to add an AUTOESCAPE {{\%pragma}} to " .
"the beginning of the input string, to set the context to TC_$2\n");
}
}
if (m@\bStringToTemplate\s*\([^)]*$@) {
warn("$ARGV:$.: StringToTemplate spans mutiple lines. You will need " .
"to clean it up by hand: get rid of the TC_foo arg. If it's not " .
"TC_MANUAL, you will need to add an AUTOESCAPE pragma. " .
"See comments in $0.");
}
# Change all the TemplateDictionary escapes. Now they are globals in
# the ctemplate namespace.
s@TemplateDictionary::html_escape@html_escape@g;
s@TemplateDictionary::pre_escape@pre_escape@g;
s@TemplateDictionary::xml_escape@xml_escape@g;
s@TemplateDictionary::javascript_escape@javascript_escape@g;
s@TemplateDictionary::url_query_escape@url_query_escape@g;
s@TemplateDictionary::json_escape@json_escape@g;
# This cleans up anything messy we left behind.
s@\bctemplate::ctemplate::@ctemplate::@g; # get rid of redundant specifier
close ARGV if eof; # to reset $. for each file
ctemplate-2.2/contrib/highlighting.vim 0000644 0001750 0001750 00000015505 11743633404 015111 0000000 0000000 #!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2006-08-08 13:38 PDT by .
# Commandline: shar -T .vim
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1477 -rw-r--r-- .vim/syntax/tpl.vim
# 56 -rw-r--r-- .vim/ftdetect/tpl.vim
#
echo >/dev/null <<_NOTES_EOF
From: Patrick Lacasse
Subject: vim color for google-ctemplate howto
To: google-ctemplate@googlegroups.com
Date: Fri, 4 Aug 2006 11:38:39 -0400
Hi group,
I'm now using google-ctemplate. My text editor is vim. Here is a little gift
for other people like me.
Howto have google-ctemplate colored by vim :
In your home directory, run 'sh $0'.
Now restart vim.
This will autodetects file with tpl extension and colors them. You can change
the color by changing the HiLink lines ( try changing String by
Identifier ) .
I'm not sure exactly about what are the legal marker names. Feel free to
change the regexes.
I only tryed this with vim 6.4 , I just cut and past the things about version
checking.
For more information about syntax higlithning in vim, try
:help syntax
Amusez-vous bien,
Patrick Lacasse
patlac@borabora.crchul.ulaval.ca
_NOTES_EOF
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh09814; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= .vim/syntax/tpl.vim ==============
if test ! -d '.vim'; then
$echo 'x -' 'creating directory' '.vim'
mkdir '.vim'
fi
if test ! -d '.vim/syntax'; then
$echo 'x -' 'creating directory' '.vim/syntax'
mkdir '.vim/syntax'
fi
if test -f '.vim/syntax/tpl.vim' && test "$first_param" != -c; then
$echo 'x -' SKIPPING '.vim/syntax/tpl.vim' '(file already exists)'
else
$echo 'x -' extracting '.vim/syntax/tpl.vim' '(text)'
sed 's/^X//' << 'SHAR_EOF' > '.vim/syntax/tpl.vim' &&
" Vim syntax file
" Language: google-ctemplate
" Maintainer: Patrick Lacasse
" Last Change: 2006 Août 03
"
" For information about google-ctemplate see
" http://goog-ctemplate.sourceforge.net/
"
" This vim syntax file works on vim 5.6, 5.7, 5.8 and 6.x.
" It implements Bram Moolenaar's April 25, 2001 recommendations to make
" the syntax file maximally portable across different versions of vim.
X
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
X syntax clear
elseif exists("b:current_syntax")
X finish
endif
X
syntax match tplMarkerError "{{}\?\([^}]\+}\?\)*}}"
syntax match tplSectionMarker "{{[#/][A-Za-z_]\+}}"
syntax match tplInclude "{{>[A-Za-z_]\+}}"
syntax match tplComment "{{![A-Za-z_]\+}}"
syntax match tplVariableMarker "{{[_A-Za-z]\+}}"
X
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_tpl_syn_inits")
X if version < 508
X let did_tpl_syn_inits = 1
X command -nargs=+ HiLink hi link
X else
X command -nargs=+ HiLink hi def link
X endif
X
X HiLink tplSectionMarker Repeat
X HiLink tplInclude Include
X HiLink tplComment Comment
X HiLink tplVariableMarker String
X HiLink tplMarkerError Error
X
X delcommand HiLink
endif
X
let b:current_syntax = "tpl"
SHAR_EOF
(set 20 06 08 08 13 34 11 '.vim/syntax/tpl.vim'; eval "$shar_touch") &&
chmod 0644 '.vim/syntax/tpl.vim' ||
$echo 'restore of' '.vim/syntax/tpl.vim' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo '.vim/syntax/tpl.vim:' 'MD5 check failed'
536faef79eff0597e642c5db04c1f79d .vim/syntax/tpl.vim
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/syntax/tpl.vim'`"
test 1477 -eq "$shar_count" ||
$echo '.vim/syntax/tpl.vim:' 'original size' '1477,' 'current size' "$shar_count!"
fi
fi
# ============= .vim/ftdetect/tpl.vim ==============
if test ! -d '.vim/ftdetect'; then
$echo 'x -' 'creating directory' '.vim/ftdetect'
mkdir '.vim/ftdetect'
fi
if test -f '.vim/ftdetect/tpl.vim' && test "$first_param" != -c; then
$echo 'x -' SKIPPING '.vim/ftdetect/tpl.vim' '(file already exists)'
else
$echo 'x -' extracting '.vim/ftdetect/tpl.vim' '(text)'
sed 's/^X//' << 'SHAR_EOF' > '.vim/ftdetect/tpl.vim' &&
au BufRead,BufNewFile *.tpl set filetype=tpl
SHAR_EOF
(set 20 06 08 08 13 34 20 '.vim/ftdetect/tpl.vim'; eval "$shar_touch") &&
chmod 0644 '.vim/ftdetect/tpl.vim' ||
$echo 'restore of' '.vim/ftdetect/tpl.vim' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo '.vim/ftdetect/tpl.vim:' 'MD5 check failed'
774fd4a092b77400ef6e74a7256ff8ef .vim/ftdetect/tpl.vim
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '.vim/ftdetect/tpl.vim'`"
test 56 -eq "$shar_count" ||
$echo '.vim/ftdetect/tpl.vim:' 'original size' '56,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh09814
exit 0
ctemplate-2.2/src/ 0000755 0001750 0001750 00000000000 11743633635 011136 5 0000000 0000000 ctemplate-2.2/src/template_modifiers_internal.h 0000644 0001750 0001750 00000025203 11743633404 016773 0000000 0000000 // 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: csilvers@google.com (Craig Silverstein)
//
// These are used by template.cc and when registering new modifiers.
// (Or more exactly, registering new modifier/value pairs.)
// They are not intended for any other users.
//
// If you do find yourself needing to use them directly, please email
// template-users.
//
// Known outside-template users of this class:
// template/bidi/bidi_modifiers_test.cc
//
// These routines are implemented in template_modifiers.cc.
#ifndef TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_
#define TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_
#include
#include // for size_t
#include // for strchr
#include
#include
#include // for null_modifier
// Annoying stuff for windows -- make sure clients (in this case
// unittests) can import the class definitions and variables.
#ifndef CTEMPLATE_DLL_DECL
# ifdef _MSC_VER
# define CTEMPLATE_DLL_DECL __declspec(dllimport)
# else
# define CTEMPLATE_DLL_DECL /* should be the empty string for non-windows */
# endif
#endif
using std::string;
using std::vector;
namespace HTMLPARSER_NAMESPACE {
class HtmlParser;
}
_START_GOOGLE_NAMESPACE_
class TemplateModifier;
// A Modifier belongs to an XssClass which determines whether
// it is an XSS safe addition to a modifier chain or not. This
// is used by the Auto-Escape mode when determining how to handle
// extra modifiers provided in template. For example, :j is a safe
// addition to :h because they are both in the same class (XSS_WEB_STANDARD).
//
// XssClass is not exposed in any API and cannot be set in custom
// modifiers, it is for internal use only (for Auto-Escape). We currently
// have only three classes.
//
// XSS_UNUSED: not used.
// XSS_WEB_STANDARD: All the curent built-in escaping modifiers.
// XSS_UNIQUE: Set for all custom modifiers added via AddModifier()
// and may need to be escaped.
// XSS_SAFE: Set for all custom modifiers added via AddXssSafeModifier()
// that are considered to produce safe output and hence
// do not need further escaping. Also includes the :none modifier.
enum XssClass {
XSS_UNUSED,
XSS_WEB_STANDARD,
XSS_UNIQUE,
XSS_SAFE,
};
// TODO(csilvers): collapse this into the TemplateModifier class?
struct ModifierInfo {
// longname should end in an '=' iff the modifier takes a value
// (same as in getopt(3)).
// To specialize -- add a modifier that applies only when we see the name
// with a particular value -- specify longname like so: "longname=value".
// (See example in the comment-doc below, for AddModifier.)
// sn can be '\0' if there is no associated shortname.
// m should be NULL *only if* default-registering a user-defined longname
// that the user neglected to register themselves. In this case, we
// use the null modifier as the actual modifier.
// xss_class indicates an equivalence class this modifier is
// in, such that any other modifier in the class could be applied
// after this modifier without affecting its XSS-safety. If in
// doubt, say XSS_UNIQUE, which is the most conservative choice.
ModifierInfo(string ln, char sn, XssClass xc, const TemplateModifier* m)
: long_name(ln), short_name(sn),
modval_required(strchr(ln.c_str(), '=') != NULL),
is_registered(m != NULL), xss_class(xc),
modifier(m ? m : &null_modifier) { }
string long_name;
char short_name;
bool modval_required; // true iff ln has an '=' in it
bool is_registered; // true for built-in and AddModifier mods
XssClass xss_class;
const TemplateModifier* modifier;
};
// An escaping directive is completely defined by the escaping function to use
// (ModifierInfo.modifier) as well as the optional value it may require. This
// structure is a small wrapper on ModifierInfo to convey that needed value.
// Note: The given value pointer must be valid for the life of the struct.
// Also, value is not null-terminated.
struct ModifierAndValue {
ModifierAndValue(const ModifierInfo* mod_info, const char* val,
size_t val_len)
: modifier_info(mod_info), value(val), value_len(val_len) { }
const ModifierInfo* modifier_info;
const char* value;
size_t value_len;
};
// Returns whether or not candidate can be safely (w.r.t XSS)
// used in lieu of our ModifierInfo. This is true iff:
// 1. Both have the same modifier function OR
// 2. Candidate's modifier function is in our ModifierInfo's
// list (vector) of safe alternative modifier functions.
// Note that this function is not commutative therefore
// IsSafeXSSAlternative(a, b) may not be equal to IsSafeXSSAlternative(b, a).
extern CTEMPLATE_DLL_DECL
bool IsSafeXSSAlternative(const ModifierInfo& our,
const ModifierInfo& candidate);
// modname is the name of the modifier (shortname or longname).
// value is the modifier-value (empty string if there is no modval).
// Returns a pointer into g_modifiers, or NULL if not found.
extern CTEMPLATE_DLL_DECL
const ModifierInfo* FindModifier(const char* modname, size_t modname_len,
const char* modval, size_t modval_len);
// Convenience function to dump the (zero or more) modifiers (and values)
// in the format:
// :[=][:][=]...
// If the modifier does not have a short_name, we print its long_name instead.
// The separator may be an empty string.
extern CTEMPLATE_DLL_DECL
string PrettyPrintModifiers(
const vector& modvals,
const string& separator);
extern CTEMPLATE_DLL_DECL
string PrettyPrintOneModifier(const ModifierAndValue& modval);
// Returns the appropriate escaping directives to escape content in an
// HTML or Javascript context. HTML and Javascript contexts exercise
// the same parser APIs and hence are combined here.
// If an error occurs, we return NULL and append and error to error_msg.
// The htmlparser and error_msg arguments must be non-NULL.
// Currently, on success, we always return a vector of length 1, meaning
// we never need to chain escaping directives. However, this is subject
// to change.
extern CTEMPLATE_DLL_DECL
vector GetModifierForHtmlJs(
HTMLPARSER_NAMESPACE::HtmlParser* htmlparser, string* error_msg);
// Returns the appropriate escaping directives to escape content
// in a CSS context.
// Currently always returns cleanse_css and hence does not require the
// parser nor can it fail. This will change once the parser is able to
// distinguish between different CSS contexts, in particular CSS properties
// that take URLs, which require a different escaping function (non-existent).
extern CTEMPLATE_DLL_DECL
vector GetModifierForCss(
HTMLPARSER_NAMESPACE::HtmlParser* htmlparser, string* error_msg);
// Returns the appropriate escaping directives to escape content
// in an XML context.
// Currently always returns xml_escape and hence does not require the
// parser nor can it fail. This may change once the parser can parse XML.
extern CTEMPLATE_DLL_DECL
vector GetModifierForXml(
HTMLPARSER_NAMESPACE::HtmlParser* htmlparser, string* error_msg);
// Returns the appropriate escaping directives to escape content
// in a JSON context.
// Currently always returns javascript_escape and hence does not require the
// parser nor can it fail. This may change once the parser can parse
// and distinguish different contexts within JSON.
extern CTEMPLATE_DLL_DECL
vector GetModifierForJson(
HTMLPARSER_NAMESPACE::HtmlParser* htmlparser, string* error_msg);
// Return the default escaping directives to escape content for the given
// context. These methods are useful when the caller does not have
// access to a parser or when the parsed failed to parse.
// GetDefaultModifierForHtml
// GetDefaultModifierForJs
// GetDefaultModifierForCss
// GetDefaultModifierForXxml
// GetDefaultModifierForJson
// These functions are different from the GetModifierForXXX functions
// in that they do not take a parser and cannot fail. They simply
// return the most common escaping directive for the context they refer to.
//
// Some of these contexts (currently HTML and Javascript) have more than
// one escaping directive associated with them and so we usually rely on
// the current state of the parser to determine which directive to chose.
// However, in some cases, the parser may fail to parse a given input
// and so we may want to select the most likely escaping directive that
// applies to the given context. Hence we use these functions instead of
// the corresponding GetModifierForXXX ones.
extern CTEMPLATE_DLL_DECL
std::vector GetDefaultModifierForHtml();
extern CTEMPLATE_DLL_DECL
std::vector GetDefaultModifierForJs();
extern CTEMPLATE_DLL_DECL
std::vector GetDefaultModifierForCss();
extern CTEMPLATE_DLL_DECL
std::vector GetDefaultModifierForXml();
extern CTEMPLATE_DLL_DECL
std::vector GetDefaultModifierForJson();
_END_GOOGLE_NAMESPACE_
#endif // TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_
ctemplate-2.2/src/base/ 0000755 0001750 0001750 00000000000 11743633635 012050 5 0000000 0000000 ctemplate-2.2/src/base/arena-inl.h 0000644 0001750 0001750 00000032644 11743633404 014012 0000000 0000000 // Copyright (c) 2000, 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.
// ---
//
// Reorganized by Craig Silverstein
//
// In this file we define the arena template code. This includes the
// ArenaAllocator, which is meant only to be used with STL, and also
// the Gladiator (which needs to know how to new and delete various
// types of objects).
//
// If you're only using the MALLOC-LIKE functionality of the arena,
// you don't need to include this file at all! You do need to include
// it (in your own .cc file) if you want to use the STRING, STL, or
// NEW aspects of the arena. See arena.h for details on these types.
//
// ArenaAllocator is an STL allocator, but because it relies on unequal
// instances, it may not work with all standards-conforming STL
// implementations. But it works with SGI STL so we're happy.
//
// Here's an example of how the ArenaAllocator would be used.
// Say we have a vector of ints that we want to have use the arena
// for memory allocation. Here's one way to do it:
// UnsafeArena* arena = new UnsafeArena(1000); // or SafeArena(), or 10000
// vector > v(arena);
//
// Note that every STL type always allows the allocator (in this case,
// the arena, which is automatically promoted to an allocator) as the last
// arg to the constructor. So if you would normally do
// vector<...> v(foo, bar),
// with the arena you can do
// vector<...> v(foo, bar, arena);
#ifndef BASE_ARENA_INL_H_
#define BASE_ARENA_INL_H_
#include
#include "base/arena.h"
#include
#include
#include
#include
_START_GOOGLE_NAMESPACE_
// T is the type we want to allocate, and C is the type of the arena.
// ArenaAllocator has the thread-safety characteristics of C.
template class ArenaAllocator {
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
pointer address(reference r) const { return &r; }
const_pointer address(const_reference r) const { return &r; }
size_type max_size() const { return size_t(-1) / sizeof(T); }
// DO NOT USE! The default constructor is for gcc3 compatibility only.
ArenaAllocator() : arena_(0) { }
// This is not an explicit constructor! So you can pass in an arena*
// to functions needing an ArenaAllocator (like the astring constructor)
// and everything will work ok.
ArenaAllocator(C* arena) : arena_(arena) { } // NOLINT
~ArenaAllocator() { }
pointer allocate(size_type n,
std::allocator::const_pointer /*hint*/ = 0) {
assert(arena_ && "No arena to allocate from!");
return reinterpret_cast(arena_->AllocAligned(n * sizeof(T),
kAlignment));
}
void deallocate(pointer p, size_type n) {
arena_->Free(p, n * sizeof(T));
}
void construct(pointer p, const T & val) {
new(reinterpret_cast(p)) T(val);
}
void construct(pointer p) {
new(reinterpret_cast(p)) T();
}
void destroy(pointer p) { p->~T(); }
C* arena(void) const { return arena_; }
template struct rebind {
typedef ArenaAllocator other;
};
template ArenaAllocator(const ArenaAllocator& other)
: arena_(other.arena()) { }
template bool operator==(const ArenaAllocator& other) const {
return arena_ == other.arena();
}
template bool operator!=(const ArenaAllocator& other) const {
return arena_ != other.arena();
}
protected:
static const int kAlignment;
C* arena_;
};
template const int ArenaAllocator::kAlignment =
(1 == sizeof(T) ? 1 : BaseArena::kDefaultAlignment);
// 'new' must be in the global namespace.
_END_GOOGLE_NAMESPACE_
using GOOGLE_NAMESPACE::UnsafeArena;
// Operators for allocation on the arena
// Syntax: new (AllocateInArena, arena) MyClass;
// new (AllocateInArena, arena) MyClass[num];
// Useful for classes you can't descend from Gladiator, such as POD,
// STL containers, etc.
enum AllocateInArenaType { AllocateInArena };
inline void* operator new(size_t size,
AllocateInArenaType /* unused */,
UnsafeArena *arena) {
return arena->Alloc(size);
}
inline void* operator new[](size_t size,
AllocateInArenaType /* unused */,
UnsafeArena *arena) {
return arena->Alloc(size);
}
_START_GOOGLE_NAMESPACE_
// Ordinarily in C++, one allocates all instances of a class from an
// arena. If that's what you want to do, you don't need Gladiator.
// (However you may find ArenaOnlyGladiator useful.)
//
// However, for utility classes that are used by multiple clients, the
// everything-in-one-arena model may not work. Some clients may wish
// not to use an arena at all. Or perhaps a composite structure
// (tree) will contain multiple objects (nodes) and some of those
// objects will be created by a factory, using an arena, while other
// objects will be created on-the-fly by an unsuspecting user who
// doesn't know anything about the arena.
//
// To support that, have the arena-allocated class inherit from
// Gladiator. The ordinary operator new will continue to allocate
// from the heap. To allocate from an arena, do
// Myclass * m = new (AllocateInArena, a) Myclass (args, to, constructor);
// where a is either an arena or an allocator. Now you can call
// delete on all the objects, whether they are allocated from an arena
// or on the heap. Heap memory will be released, while arena memory will
// not be.
//
// If a client knows that no objects were allocated on the heap, it
// need not delete any objects (but it may if it wishes). The only
// objects that must be deleted are those that were actually allocated
// from the heap.
//
// NOTE: an exception to the google C++ style guide rule for "No multiple
// implementation inheritance" is granted for this class: you can treat this
// class as an "Interface" class, and use it in a multiple inheritence context,
// even though it implements operator new/delete.
class Gladiator {
public:
Gladiator() { }
virtual ~Gladiator() { }
// We do not override the array allocators, so array allocation and
// deallocation will always be from the heap. Typically, arrays are
// larger, and thus the costs of arena allocation are higher and the
// benefits smaller. Since arrays are typically allocated and deallocated
// very differently from scalars, this may not interfere too much with
// the arena concept. If it does pose a problem, flesh out the
// ArrayGladiator class below.
void* operator new(const size_t size) {
void* ret = ::operator new(1 + size);
static_cast(ret)[size] = 1; // mark as heap-allocated
return ret;
}
// the ignored parameter keeps us from stepping on placement new
template void* operator new(const size_t size, const int ignored,
T* allocator) {
if (allocator) {
void* ret = allocator->AllocAligned(1 + size,
BaseArena::kDefaultAlignment);
static_cast(ret)[size] = 0; // mark as arena-allocated
return ret;
} else {
return operator new(size); // this is the function above
}
}
void operator delete(void* memory, const size_t size) {
if (static_cast(memory)[size]) {
assert (1 == static_cast(memory)[size]);
::operator delete(memory);
} else {
// We never call the allocator's Free method. If we need to do
// that someday, we can store a pointer to the arena instead of
// the Boolean marker flag.
}
}
template void operator delete(void* memory, const size_t size,
const int ign, T* allocator) {
// This "placement delete" can only be called if the constructor
// throws an exception.
if (allocator) {
allocator->Free(memory, 1 + size);
} else {
::operator delete(memory);
}
}
};
// This avoids the space overhead of Gladiator if you just want to
// override new and delete. It helps avoid some of the more common
// problems that can occur when overriding new and delete.
class ArenaOnlyGladiator {
public:
ArenaOnlyGladiator() { }
// No virtual destructor is needed because we ignore the size
// parameter in all the delete functions.
// virtual ~ArenaOnlyGladiator() { }
// can't just return NULL here -- compiler gives a warning. :-|
void* operator new(const size_t /*size*/) {
assert(0);
return reinterpret_cast(1);
}
void* operator new[](const size_t /*size*/) {
assert(0);
return reinterpret_cast(1);
}
// the ignored parameter keeps us from stepping on placement new
template void* operator new(const size_t size, const int ignored,
T* allocator) {
assert(allocator);
return allocator->AllocAligned(size, BaseArena::kDefaultAlignment);
}
template void* operator new[](const size_t size,
const int ignored, T* allocator) {
assert(allocator);
return allocator->AllocAligned (size, BaseArena::kDefaultAlignment);
}
void operator delete(void* /*memory*/, const size_t /*size*/) { }
template void operator delete(void* memory, const size_t size,
const int ign, T* allocator) { }
void operator delete [](void* /*memory*/) { }
template void operator delete(void* memory,
const int ign, T* allocator) { }
};
#if 0 // ********** for example purposes only; 100% untested.
// Note that this implementation incurs an overhead of kHeaderSize for
// every array that is allocated. *Before* the space is returned to the
// user, we store the address of the Arena that owns the space, and
// the length of th space itself.
class ArrayGladiator : public Gladiator {
public:
void * operator new[] (const size_t size) {
const int sizeplus = size + kHeaderSize;
void * const ret = ::operator new(sizeplus);
*static_cast(ret) = NULL; // mark as heap-allocated
*static_cast(ret + sizeof(Arena *)) = sizeplus;
return ret + kHeaderSize;
}
// the ignored parameter keeps us from stepping on placement new
template void * operator new[] (const size_t size,
const int ignored, T * allocator) {
if (allocator) {
const int sizeplus = size + kHeaderSize;
void * const ret =
allocator->AllocAligned(sizeplus, BaseArena::kDefaultAlignment);
*static_cast(ret) = allocator->arena();
*static_cast(ret + sizeof(Arena *)) = sizeplus;
return ret + kHeaderSize;
} else {
return operator new[](size); // this is the function above
}
}
void operator delete [] (void * memory) {
memory -= kHeaderSize;
Arena * const arena = *static_cast(memory);
const size_t sizeplus = *static_cast(memory + sizeof(arena));
if (arena) {
arena->SlowFree(memory, sizeplus);
} else {
::operator delete (memory);
}
}
template void * operator delete (void * memory,
const int ign, T * allocator) {
// This "placement delete" can only be called if the constructor
// throws an exception.
memory -= kHeaderSize;
const size_t sizeplus = *static_cast(memory + sizeof(Arena *));
if (allocator) {
allocator->Free(memory, 1 + size);
} else {
operator delete (memory);
}
}
protected:
static const int kMinSize = sizeof size_t + sizeof(Arena *);
static const int kHeaderSize = kMinSize > BaseArena::kDefaultAlignment ?
2 * BaseArena::kDefaultAlignment : BaseArena::kDefaultAlignment;
};
#endif // ********** example
_END_GOOGLE_NAMESPACE_
#endif // BASE_ARENA_INL_H_
ctemplate-2.2/src/base/fileutil.h 0000644 0001750 0001750 00000006424 11743633404 013756 0000000 0000000 // Copyright (c) 2011, 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: csilvers@google.com (Craig Silverstein)
//
// A tiny wrapper around struct stat and FILE*.
#ifndef TEMPLATE_OPENSOURCE_FILEUTIL_H_
#define TEMPLATE_OPENSOURCE_FILEUTIL_H_
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
# include
#endif
#include
_START_GOOGLE_NAMESPACE_
class FileStat {
public:
time_t mtime;
off_t length;
bool IsDirectory() { return S_ISDIR(internal_statbuf.st_mode); }
private:
friend class File;
struct stat internal_statbuf;
};
class File {
public:
static bool Stat(const std::string& filename, FileStat* statbuf) {
if (stat(filename.c_str(), &statbuf->internal_statbuf) != 0)
return false;
statbuf->mtime = statbuf->internal_statbuf.st_mtime;
statbuf->length = statbuf->internal_statbuf.st_size;
return true;
}
static bool Readable(const char* filename) {
return access(filename, R_OK) == 0;
}
static File* Open(const char* filename, const char* mode) {
char binary_mode[3];
const char* mode_to_use = mode;
if ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0') {
// We add a 'b' to make sure we do the right thing even on
// Windows. On unix, this will be a noop.
binary_mode[0] = mode[0];
binary_mode[1] = 'b';
binary_mode[2] = '\0';
mode_to_use = binary_mode;
}
FILE* fp = fopen(filename, mode_to_use);
if (!fp) return NULL;
return new File(fp);
}
size_t Read(char* buf, size_t size) {
return fread(buf, 1, size, fp_);
}
void Close() {
fclose(fp_);
delete this; // naughty naughty!
}
private:
explicit File(FILE* fp) : fp_(fp) { }
FILE* fp_;
};
_END_GOOGLE_NAMESPACE_
#endif // TEMPLATE_OPENSOURCE_FILEUTIL_H_
ctemplate-2.2/src/base/util.h 0000644 0001750 0001750 00000022266 11743633404 013120 0000000 0000000 // Copyright (c) 2011, 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.
// ---
//
// Some generically useful utility routines that in google-land would
// be their own projects. We make a shortened version here.
#ifndef TEMPLATE_UTIL_H_
#define TEMPLATE_UTIL_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// -- utility macros ---------------------------------------------------------
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE.
#if !defined(_MSC_VER) || _MSC_VER < 1400
#define ARRAYSIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast(!(sizeof(a) % sizeof(*(a)))))
#endif
template // use like this: down_cast(foo);
inline To down_cast(From* f) { // so we only accept pointers
return static_cast(f);
}
// -- CHECK macros ---------------------------------------------------------
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode. Therefore, it is safe to do things like:
// CHECK(fp->Write(x) == 4)
// We allow stream-like objects after this for debugging, but they're ignored.
#define CHECK(condition) \
if (true) { \
if (!(condition)) { \
fprintf(stderr, "Check failed: %s\n", #condition); \
exit(1); \
} \
} else std::cerr << ""
#define CHECK_OP(op, val1, val2) \
if (true) { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} else std::cerr << ""
#define CHECK_EQ(val1, val2) CHECK_OP(==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(!=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(<=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(< , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
// Synonyms for CHECK_* that are used in some unittests.
#define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2)
#define EXPECT_NE(val1, val2) CHECK_NE(val1, val2)
#define EXPECT_LE(val1, val2) CHECK_LE(val1, val2)
#define EXPECT_LT(val1, val2) CHECK_LT(val1, val2)
#define EXPECT_GE(val1, val2) CHECK_GE(val1, val2)
#define EXPECT_GT(val1, val2) CHECK_GT(val1, val2)
#define EXPECT_TRUE(cond) CHECK(cond)
#define EXPECT_FALSE(cond) CHECK(!(cond))
#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
#define ASSERT_TRUE(cond) EXPECT_TRUE(cond)
// LOG(FATAL) is an alias for CHECK(FALSE). We define FATAL, but no
// other value that is reasonable inside LOG(), so the compile will
// fail if someone tries to use LOG(DEBUG) or the like.
#define LOG(x) INTERNAL_DO_LOG_ ## x
#define INTERNAL_DO_LOG_FATAL CHECK(false)
// These are used only in debug mode.
#ifdef NDEBUG
#define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
#else
#define DCHECK(condition) if (true) {} else std::cerr << ""
#define DCHECK_EQ(val1, val2) if (true) {} else std::cerr << ""
#define DCHECK_NE(val1, val2) if (true) {} else std::cerr << ""
#define DCHECK_LE(val1, val2) if (true) {} else std::cerr << ""
#define DCHECK_LT(val1, val2) if (true) {} else std::cerr << ""
#define DCHECK_GE(val1, val2) if (true) {} else std::cerr << ""
#define DCHECK_GT(val1, val2) if (true) {} else std::cerr << ""
#endif
#define PCHECK(cond) CHECK(cond) << ": " << strerror(errno)
#define PFATAL(s) do { perror(s); exit(1); } while (0)
// -- testing-related macros --------------------------------------------------
// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
#define TEST_INIT \
static std::vector g_testlist; /* the tests to run */ \
static int RUN_ALL_TESTS() { \
std::vector::const_iterator it; \
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
(*it)(); /* The test will error-exit if there's a problem. */ \
} \
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
static_cast(g_testlist.size())); \
return 0; \
}
#define TEST(a, b) \
class Test_##a##_##b { \
public: \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::Run()
// This is a dummy class that eases the google->opensource transition.
namespace testing {
class Test {};
}
// -- template-related macros ----------------------------------------------
#ifndef DEFAULT_TEMPLATE_ROOTDIR
# define DEFAULT_TEMPLATE_ROOTDIR "."
#endif
// -- string-related functions ----------------------------------------------
inline bool safe_strto32(const std::string& s, int* i) {
char* error_pos;
if (s.empty()) return false; // no input at all
errno = 0; // just to be sure
*i = strtol(s.c_str(), &error_pos, 10);
return *error_pos == '\0' && errno == 0;
}
inline int atoi32(const char* s) {
return atoi(s);
}
inline void StripWhiteSpace(std::string* str) {
int str_length = str->length();
// Strip off leading whitespace.
int first = 0;
while (first < str_length && isspace(str->at(first))) {
++first;
}
// If entire string is white space.
if (first == str_length) {
str->clear();
return;
}
if (first > 0) {
str->erase(0, first);
str_length -= first;
}
// Strip off trailing whitespace.
int last = str_length - 1;
while (last >= 0 && isspace(str->at(last))) {
--last;
}
if (last != (str_length - 1) && last >= 0) {
str->erase(last + 1, std::string::npos);
}
}
inline void SplitStringIntoKeyValuePairs(
const std::string& s,
const char* kv_split, // For instance: "="
const char* pair_split, // For instance: ","
std::vector< std::pair > *pairs) {
std::string key, value;
std::string* add_to = &key;
for (std::string::size_type i = 0; i < s.length(); ++i) {
if (s[i] == kv_split[0]) {
add_to = &value;
} else if (s[i] == pair_split[0]) {
if (!key.empty())
pairs->push_back(std::pair(key, value));
key.clear();
value.clear();
add_to = &key;
} else {
*add_to += s[i];
}
}
if (!key.empty())
pairs->push_back(std::pair(key, value));
}
#endif // TEMPLATE_UTIL_H_
ctemplate-2.2/src/base/thread_annotations.h 0000644 0001750 0001750 00000013165 11743633404 016025 0000000 0000000 // Copyright (c) 2008, 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.
// ---
//
//
// This header file contains the macro definitions for thread safety
// annotations that allow the developers to document the locking policies
// of their multi-threaded code. The annotations can also help program
// analysis tools to identify potential thread safety issues.
//
//
// The annotations are implemented using GCC's "attributes" extension.
// Using the macros defined here instead of the raw GCC attributes allows
// for portability and future compatibility.
//
#ifndef BASE_THREAD_ANNOTATIONS_H_
#define BASE_THREAD_ANNOTATIONS_H_
#include
#if defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) && !defined(SWIG)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
// Document if a shared variable/field needs to be protected by a lock.
// GUARDED_BY allows the user to specify a particular lock that should be
// held when accessing the annotated variable, while GUARDED_VAR only
// indicates a shared variable should be guarded (by any lock). GUARDED_VAR
// is primarily used when the client cannot express the name of the lock.
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded)
// Document if the memory location pointed to by a pointer should be guarded
// by a lock when dereferencing the pointer. Similar to GUARDED_VAR,
// PT_GUARDED_VAR is primarily used when the client cannot express the name
// of the lock. Note that a pointer variable to a shared memory location
// could itself be a shared variable. For example, if a shared global pointer
// q, which is guarded by mu1, points to a shared memory location that is
// guarded by mu2, q should be annotated as follows:
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
#define PT_GUARDED_BY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x))
#define PT_GUARDED_VAR \
THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded)
// Document the acquisition order between locks that can be held
// simultaneously by a thread. For any two locks that need to be annotated
// to establish an acquisition order, only one of them needs the annotation.
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
// and ACQUIRED_BEFORE.)
#define ACQUIRED_AFTER(x) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
#define ACQUIRED_BEFORE(x) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
// The following three annotations document the lock requirements for
// functions/methods.
// Document if a function expects certain locks to be held before it is called
#define EXCLUSIVE_LOCKS_REQUIRED(x) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
#define SHARED_LOCKS_REQUIRED(x) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(x))
// Document the locks acquired in the body of the function. These locks
// non-reentrant).
#define LOCKS_EXCLUDED(x) \
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
// Document the lock the annotated function returns without acquiring it.
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
// Document if a class/type is a lockable type (such as the Mutex class).
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
// Document if a class is a scoped lockable type (such as the MutexLock class).
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
// The following annotations specify lock and unlock primitives.
#define EXCLUSIVE_LOCK_FUNCTION(x) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock(x))
#define SHARED_LOCK_FUNCTION(x) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x))
#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x))
#define SHARED_TRYLOCK_FUNCTION(x) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x))
#define UNLOCK_FUNCTION(x) \
THREAD_ANNOTATION_ATTRIBUTE__(unlock(x))
// An escape hatch for thread safety analysis to ignore the annotated function.
#define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
#endif // BASE_THREAD_ANNOTATIONS_H_
ctemplate-2.2/src/base/manual_constructor.h 0000644 0001750 0001750 00000021221 11743633404 016053 0000000 0000000 // Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Author: kenton@google.com (Kenton Varda)
//
// ManualConstructor statically-allocates space in which to store some
// object, but does not initialize it. You can then call the constructor
// and destructor for the object yourself as you see fit. This is useful
// for memory management optimizations, where you want to initialize and
// destroy an object multiple times but only allocate it once.
//
// (When I say ManualConstructor statically allocates space, I mean that
// the ManualConstructor object itself is forced to be the right size.)
//
// For example usage, check out util/gtl/small_map.h.
#ifndef UTIL_GTL_MANUAL_CONSTRUCTOR_H_
#define UTIL_GTL_MANUAL_CONSTRUCTOR_H_
#include
_START_GOOGLE_NAMESPACE_
namespace util {
namespace gtl {
namespace internal {
//
// Provides a char array with the exact same alignment as another type. The
// first parameter must be a complete type, the second parameter is how many
// of that type to provide space for.
//
// UTIL_GTL_ALIGNED_CHAR_ARRAY(struct stat, 16) storage_;
//
// Because MSVC and older GCCs require that the argument to their alignment
// construct to be a literal constant integer, we use a template instantiated
// at all the possible powers of two.
#ifndef SWIG
template struct AlignType { };
template struct AlignType<0, size> { typedef char result[size]; };
#if defined(_MSC_VER)
#define UTIL_GTL_ALIGN_ATTRIBUTE(X) __declspec(align(X))
#define UTIL_GTL_ALIGN_OF(T) __alignof(T)
#elif defined(__GNUC__) || defined(__APPLE__) || defined(__INTEL_COMPILER) \
|| defined(__nacl__)
#define UTIL_GTL_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X)))
#define UTIL_GTL_ALIGN_OF(T) __alignof__(T)
#endif
#if defined(UTIL_GTL_ALIGN_ATTRIBUTE)
#define UTIL_GTL_ALIGNTYPE_TEMPLATE(X) \
template struct AlignType { \
typedef UTIL_GTL_ALIGN_ATTRIBUTE(X) char result[size]; \
}
UTIL_GTL_ALIGNTYPE_TEMPLATE(1);
UTIL_GTL_ALIGNTYPE_TEMPLATE(2);
UTIL_GTL_ALIGNTYPE_TEMPLATE(4);
UTIL_GTL_ALIGNTYPE_TEMPLATE(8);
UTIL_GTL_ALIGNTYPE_TEMPLATE(16);
UTIL_GTL_ALIGNTYPE_TEMPLATE(32);
UTIL_GTL_ALIGNTYPE_TEMPLATE(64);
UTIL_GTL_ALIGNTYPE_TEMPLATE(128);
UTIL_GTL_ALIGNTYPE_TEMPLATE(256);
UTIL_GTL_ALIGNTYPE_TEMPLATE(512);
UTIL_GTL_ALIGNTYPE_TEMPLATE(1024);
UTIL_GTL_ALIGNTYPE_TEMPLATE(2048);
UTIL_GTL_ALIGNTYPE_TEMPLATE(4096);
UTIL_GTL_ALIGNTYPE_TEMPLATE(8192);
// Any larger and MSVC++ will complain.
#define UTIL_GTL_ALIGNED_CHAR_ARRAY(T, Size) \
typename util::gtl::internal::AlignType::result
#undef UTIL_GTL_ALIGNTYPE_TEMPLATE
#undef UTIL_GTL_ALIGN_ATTRIBUTE
#else // defined(UTIL_GTL_ALIGN_ATTRIBUTE)
#error "You must define UTIL_GTL_ALIGNED_CHAR_ARRAY for your compiler."
#endif // defined(UTIL_GTL_ALIGN_ATTRIBUTE)
#else // !SWIG
// SWIG can't represent alignment and doesn't care about alignment on data
// members (it works fine without it).
template
struct AlignType { typedef char result[Size]; };
#define UTIL_GTL_ALIGNED_CHAR_ARRAY(T, Size) \
util::gtl::internal::AlignType::result
#endif // !SWIG
} // namespace internal
} // namespace gtl
} // namespace util
template
class ManualConstructor {
public:
// No constructor or destructor because one of the most useful uses of
// this class is as part of a union, and members of a union cannot have
// constructors or destructors. And, anyway, the whole point of this
// class is to bypass these.
inline Type* get() {
return reinterpret_cast(space_);
}
inline const Type* get() const {
return reinterpret_cast(space_);
}
inline Type* operator->() { return get(); }
inline const Type* operator->() const { return get(); }
inline Type& operator*() { return *get(); }
inline const Type& operator*() const { return *get(); }
// You can pass up to four constructor arguments as arguments of Init().
inline void Init() {
new(space_) Type;
}
template
inline void Init(const T1& p1) {
new(space_) Type(p1);
}
template
inline void Init(const T1& p1, const T2& p2) {
new(space_) Type(p1, p2);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3) {
new(space_) Type(p1, p2, p3);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
new(space_) Type(p1, p2, p3, p4);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5) {
new(space_) Type(p1, p2, p3, p4, p5);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6) {
new(space_) Type(p1, p2, p3, p4, p5, p6);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
template
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10, const T11& p11) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
inline void Destroy() {
get()->~Type();
}
private:
UTIL_GTL_ALIGNED_CHAR_ARRAY(Type, 1) space_;
};
#undef UTIL_GTL_ALIGNED_CHAR_ARRAY
#undef UTIL_GTL_ALIGN_OF
_END_GOOGLE_NAMESPACE_
#endif // UTIL_GTL_MANUAL_CONSTRUCTOR_H_
ctemplate-2.2/src/base/arena.h 0000644 0001750 0001750 00000073226 11743633404 013233 0000000 0000000 // Copyright (c) 2000, 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.
// ---
//
// Reorganized by Craig Silverstein
// "Handles" by Ilan Horn
//
// Sometimes it is necessary to allocate a large number of small
// objects. Doing this the usual way (malloc, new) is slow,
// especially for multithreaded programs. A BaseArena provides a
// mark/release method of memory management: it asks for a large chunk
// from the operating system and doles it out bit by bit as required.
// Then you free all the memory at once by calling BaseArena::Reset().
//
// Use SafeArena for multi-threaded programs where multiple threads
// could access the same arena at once. Use UnsafeArena otherwise.
// Usually you'll want UnsafeArena.
//
// There are four ways to use the arena. arena.h and arena.cc are
// sufficient for the MALLOC and STRINGS uses. For NEW and STL you'll
// also need to include arena-inl.h in the appropriate .cc file.
// However, we do *declare* (but not define) the template types here.
//
// LIKE MALLOC: --Uses UnsafeArena (or SafeArena)--
// This is the simplest way. Just create an arena, and whenever you
// need a block of memory to put something in, call BaseArena::Alloc(). eg
// s = arena.Alloc(100);
// snprintf(s, 100, "%s:%d", host, port);
// arena.Shrink(strlen(s)+1); // optional; see below for use
//
// You'll probably use the convenience routines more often:
// s = arena.Strdup(host); // a copy of host lives in the arena
// s = arena.Strndup(host, 100); // we guarantee to NUL-terminate!
// s = arena.Memdup(protobuf, sizeof(protobuf);
//
// If you go the Alloc() route, you'll probably allocate too-much-space.
// You can reclaim the extra space by calling Shrink() before the next
// Alloc() (or Strdup(), or whatever), with the #bytes you actually used.
// If you use this method, memory management is easy: just call Alloc()
// and friends a lot, and call Reset() when you're done with the data.
//
// FOR STRINGS: --Uses UnsafeArena (or SafeArena)--
// This is a special case of STL (below), but is simpler. Use an
// astring, which acts like a string but allocates from the passed-in
// arena:
// astring s(arena); // or "sastring" to use a SafeArena
// s.assign(host);
// astring s2(host, hostlen, arena);
//
// WITH NEW: --Uses BaseArena, Gladiator (or ArenaOnlyGladiator)--
// Use this to allocate a C++ class object (or any other object you
// have to get via new/delete rather than malloc/free).
// There are several things you have to do in this case:
// 1) Your class (the one you new) must inherit from Gladiator.
// 2) To actually allocate this class on the arena, use
// myclass = new (AllocateInArena, arena) MyClass(constructor, args)
//
// Note that MyClass doesn't need to have the arena passed in.
// But if it, in turn, wants to call "new" on some of its member
// variables, and you want those member vars to be on the arena
// too, you better pass in an arena so it can call new(0,arena).
//
// If you can guarantee that everyone who ever calls new on
// MyClass uses the new(0,arena) form (ie nobody ever just says
// new), you can have MyClass subclass from ArenaOnlyGladiator
// rather than from Gladiator. ArenaOnlyGladiator is a bit more
// efficient (faster and smaller), but is otherwise identical.
//
// If you allocate myclass using new(0,arena), and MyClass only
// does memory management in the destructor, it's not necessary
// to even call "delete myclass;", you can just call arena.Reset();
// If the destructor does something else (closes a file, logs
// a message, whatever), you'll have to call destructor and Reset()
// both: "delete myclass; arena.Reset();"
//
// Note that you can not allocate an array of classes this way:
// noway = new (AllocateInArena, arena) MyClass[5]; // not supported!
// It's not difficult to program, we just haven't done it. Arrays
// are typically big and so there's little point to arena-izing them.
//
// WITH NEW: --Uses UnsafeArena--
// There are cases where you can't inherit the class from Gladiator,
// or inheriting would be too expensive. Examples of this include
// plain-old-data (allocated using new) and third-party classes (such
// as STL containers). arena-inl.h provides a global operator new
// that can be used as follows:
//
// #include "base/arena-inl.h"
//
// UnsafeArena arena(1000);
// Foo* foo = new (AllocateInArena, &arena) Foo;
// Foo* foo_array = new (AllocateInArena, &arena) Foo[10];
//
// IN STL: --Uses BaseArena, ArenaAllocator--
// All STL containers (vector, hash_map, etc) take an allocator.
// You can use the arena as an allocator. Then whenever the vector
// (or whatever) wants to allocate memory, it will take it from the
// arena. To use, you just indicate in the type that you want to use the
// arena, and then actually give a pointer to the arena as the last
// constructor arg:
// vector > v(&arena);
// v.push_back(3);
//
// WARNING: Careless use of STL within an arena-allocated object can
// result in memory leaks if you rely on arena.Reset() to free
// memory and do not call the object destructor. This is actually
// a subclass of a more general hazard: If an arena-allocated
// object creates (and owns) objects that are not also
// arena-allocated, then the creating object must have a
// destructor that deletes them, or they will not be deleted.
// However, since the outer object is arena allocated, it's easy to
// forget to call delete on it, and needing to do so may seem to
// negate much of the benefit of arena allocation. A specific
// example is use of vector in an arena-allocated object,
// since type string is not atomic and is always allocated by the
// default runtime allocator. The arena definition provided here
// allows for much flexibility, but you ought to carefully consider
// before defining arena-allocated objects which in turn create
// non-arena allocated objects.
//
// WITH HANDLES:
// The various arena classes can supply compact handles to data kept
// in the arena. These handles consume only 4 bytes each, and are thus
// more efficient than pointers - this may be interesting in cases
// where a very large number of references to memory in the arena need
// to be kept.
// Note that handles are limited in the amount of data that can be reference
// in the arena, typically to 4GB*the number given to set_handle_alignment()
// (which defaults to 1). The number of allocations that can have handles
// is, of course, smaller than 4G (that's what's representable by 32 bits).
// It does depend on their sizes, however. In a worst-case scenario each
// allocation consumes a page of its own, and we will run out of handles
// after approximately (4G/block_size)*handle_alignment allocations.
// When we run out of handles or allocate data over the amount of memory
// that handles can reference, an invalid handle will be returned (but
// the requested memory will still be allocated in the arena).
// Handles memory use is most efficient when the arena block size is a power
// of two. When this is not the case, we can run out of handles when at
// most half of the addressable space (as described above) is not in use.
// At worst handles can reference at least 2GB*handle_alignment.
// Example use:
// UnsafeArena arena(16384);
// arena.set_handle_alignment(4);
// // Assume you want to keep the string s in the arena.
// Handle h = arena.MemdupWithHandle(s.c_str(), s.length());
// // Later, to get the memory from the handle, use:
// void* p = arena.HandleToPointer(h);
// // Note that there's no way to retrieve the size from the handle.
// // It probably makes sense to encode the size into the buffer saved,
// // unless the size is known/fixed.
// Internal machinery of handles:
// The handle consists of the block index in the arena and the offset
// inside the block, encoded into a single unsigned uint32 value.
// Note that, the rightmost alignment bits (controlled by
// set_handle_alignment()) are shaved off the saved offset in the Handle,
// to give some extra capacity :)
// set_handle_alignment() can only be called when the arena is empty,
// as changing it invalidates any handles that are still in flight.
//
//
// PUTTING IT ALL TOGETHER
// Here's a program that uses all of the above. Note almost all the
// examples are the various ways to use "new" and STL. Using the
// malloc-like features and the string type are much easier!
//
// Class A : public Gladiator {
// public:
// int i;
// vector v1;
// vector >* v3;
// vector >* v4;
// vector* v5;
// vector vs;
// vector va;
// char *s;
// A() : v1(), v3(NULL), v4(NULL), vs(), va(), s(NULL) {
// // v1 is allocated on the arena whenever A is. Its ints never are.
// v5 = new vector;
// // v5 is not allocated on the arena, and neither are any of its ints.
// }
// ~A() {
// delete v5; // needed since v5 wasn't allocated on the arena
// printf("I'm done!\n");
// }
// };
//
// class B : public A { // we inherit from Gladiator, but indirectly
// public:
// UnsafeArena* arena_;
// vector > v2;
// vector va1;
// vector > va2;
// vector* pva;
// vector >* pva2;
// astring a;
//
// B(UnsafeArena * arena)
// : arena_(arena), v2(arena_), va1(), va2(arena_), a("initval", arena_) {
// v3 = new vector >(arena_);
// v4 = new (AllocateInArena, arena_) vector >(arena_);
// v5 = new (AllocateInArena, arena_) vector;
// // v2 is allocated on the arena whenever B is. Its ints always are.
// // v3 is not allocated on the arena, but the ints you give it are
// // v4 is allocated on the arena, and so are the ints you give it
// // v5 is allocated on the arena, but the ints you give it are not
// // va1 is allocated on the arena whenever B is. No A ever is.
// // va2 is allocated on the arena whenever B is. Its A's always are.
// pva = new (AllocateInArena, arena_) vector;
// pva2 = new (AllocateInArena, arena_) vector >(arena_);
// // pva is allocated on the arena, but its A's are not
// // pva2 is allocated on the arena, and so are its A's.
// // a's value "initval" is stored on the arena. If we reassign a,
// // the new value will be stored on the arena too.
// }
// ~B() {
// delete v3; // necessary to free v3's memory, though not its ints'
// // don't need to delete v4: arena_.Reset() will do as good
// delete v5; // necessary to free v5's ints memory, though not v5 itself
// delete pva; // necessary to make sure you reclaim space used by A's
// delete pva2; // safe to call this; needed if you want to see the printfs
// // pva2->clear() -- not necessary, arena_.Reset() will do just as good
// }
// };
//
// main() {
// UnsafeArena arena(1000);
// A a1; // a1 is not on the arena
// a1.vs.push_back(string("hello")); // hello is not copied onto the arena
// a1.va.push_back(astring("hello", &arena)); // hello is on the arena,
// // astring container isn't
// a1.s = arena.Strdup("hello"); // hello is on the arena
//
// A* a2 = new (AllocateInArena, arena) A; // a2 is on the arena
// a2.vs.push_back(string("hello")); // hello is *still* not on the arena
// a2.s = arena.Strdup("world"); // world is on the arena. a1.s is ok
//
// B b1(&arena); // B is not allocated on the arena
// b1.a.assign("hello"); // hello is on the arena
// b1.pva2.push_back(a1); // our copy of a1 will be stored on
// // the arena, though a1 itself wasn't
// arena.Reset(); // all done with our memory!
// }
#ifndef BASE_ARENA_H_
#define BASE_ARENA_H_
#include
#include "base/mutex.h" // must go first to get _XOPEN_SOURCE
#include
#include
#include
#include "base/thread_annotations.h"
#include "base/macros.h" // for uint32
#include "base/util.h" // for CHECK, etc
_START_GOOGLE_NAMESPACE_
// Annoying stuff for windows -- make sure clients (in this case
// unittests) can import the class definitions and variables.
#ifndef CTEMPLATE_DLL_DECL
# ifdef _MSC_VER
# define CTEMPLATE_DLL_DECL __declspec(dllimport)
# else
# define CTEMPLATE_DLL_DECL /* should be the empty string for non-windows */
# endif
#endif
// This class is "thread-compatible": different threads can access the
// arena at the same time without locking, as long as they use only
// const methods.
class CTEMPLATE_DLL_DECL BaseArena {
protected: // You can't make an arena directly; only a subclass of one
BaseArena(char* first_block, const size_t block_size, bool align_to_page);
public:
virtual ~BaseArena();
virtual void Reset();
// A handle to a pointer in an arena. An opaque type, with default
// copy and assignment semantics.
class Handle {
public:
static const uint32 kInvalidValue = 0xFFFFFFFF; // int32-max
Handle() : handle_(kInvalidValue) { }
// Default copy constructors are fine here.
bool operator==(const Handle& h) const { return handle_ == h.handle_; }
bool operator!=(const Handle& h) const { return handle_ != h.handle_; }
uint32 hash() const { return handle_; }
bool valid() const { return handle_ != kInvalidValue; }
private:
// Arena needs to be able to access the internal data.
friend class BaseArena;
explicit Handle(uint32 handle) : handle_(handle) { }
uint32 handle_;
};
// they're "slow" only 'cause they're virtual (subclasses define "fast" ones)
virtual char* SlowAlloc(size_t size) = 0;
virtual void SlowFree(void* memory, size_t size) = 0;
virtual char* SlowRealloc(char* memory, size_t old_size, size_t new_size) = 0;
virtual char* SlowAllocWithHandle(const size_t size, Handle* handle) = 0;
// Set the alignment to be used when Handles are requested. This can only
// be set for an arena that is empty - it cannot be changed on the fly.
// The alignment must be a power of 2 that the block size is divisable by.
// The default alignment is 1.
// Trying to set an alignment that does not meet the above constraints will
// cause a CHECK-failure.
void set_handle_alignment(int align);
// Retrieve the memory pointer that the supplied handle refers to.
// Calling this with an invalid handle will CHECK-fail.
void* HandleToPointer(const Handle& h) const;
class Status {
private:
friend class BaseArena;
size_t bytes_allocated_;
public:
Status() : bytes_allocated_(0) { }
size_t bytes_allocated() const {
return bytes_allocated_;
}
};
// Accessors and stats counters
// This accessor isn't so useful here, but is included so we can be
// type-compatible with ArenaAllocator (in arena-inl.h). That is,
// we define arena() because ArenaAllocator does, and that way you
// can template on either of these and know it's safe to call arena().
virtual BaseArena* arena() { return this; }
size_t block_size() const { return block_size_; }
int block_count() const;
bool is_empty() const {
// must check block count in case we allocated a block larger than blksize
return freestart_ == freestart_when_empty_ && 1 == block_count();
}
// This should be the worst-case alignment for any type. This is
// good for IA-32, SPARC version 7 (the last one I know), and
// supposedly Alpha. i386 would be more time-efficient with a
// default alignment of 8, but ::operator new() uses alignment of 4,
// and an assertion will fail below after the call to MakeNewBlock()
// if you try to use a larger alignment.
#ifdef __i386__
static const int kDefaultAlignment = 4;
#else
static const int kDefaultAlignment = 8;
#endif
protected:
void MakeNewBlock();
void* GetMemoryFallback(const size_t size, const int align);
void* GetMemory(const size_t size, const int align) {
assert(remaining_ <= block_size_); // an invariant
if ( size > 0 && size < remaining_ && align == 1 ) { // common case
last_alloc_ = freestart_;
freestart_ += size;
remaining_ -= size;
return reinterpret_cast(last_alloc_);
}
return GetMemoryFallback(size, align);
}
// This doesn't actually free any memory except for the last piece allocated
void ReturnMemory(void* memory, const size_t size) {
if ( memory == last_alloc_ && size == freestart_ - last_alloc_ ) {
remaining_ += size;
freestart_ = last_alloc_;
}
}
// This is used by Realloc() -- usually we Realloc just by copying to a
// bigger space, but for the last alloc we can realloc by growing the region.
bool AdjustLastAlloc(void* last_alloc, const size_t newsize);
// Since using different alignments for different handles would make
// the handles incompatible (e.g., we could end up with the same handle
// value referencing two different allocations, the alignment is not passed
// as an argument to GetMemoryWithHandle, and handle_alignment_ is used
// automatically for all GetMemoryWithHandle calls.
void* GetMemoryWithHandle(const size_t size, Handle* handle);
Status status_;
size_t remaining_;
private:
struct AllocatedBlock {
char *mem;
size_t size;
};
// The returned AllocatedBlock* is valid until the next call to AllocNewBlock
// or Reset (i.e. anything that might affect overflow_blocks_).
AllocatedBlock *AllocNewBlock(const size_t block_size);
const AllocatedBlock *IndexToBlock(int index) const;
const int first_block_we_own_; // 1 if they pass in 1st block, 0 else
const size_t block_size_;
char* freestart_; // beginning of the free space in most recent block
char* freestart_when_empty_; // beginning of the free space when we're empty
char* last_alloc_; // used to make sure ReturnBytes() is safe
// STL vector isn't as efficient as it could be, so we use an array at first
int blocks_alloced_; // how many of the first_blocks_ have been alloced
AllocatedBlock first_blocks_[16]; // the length of this array is arbitrary
// if the first_blocks_ aren't enough, expand into overflow_blocks_.
std::vector* overflow_blocks_;
const bool page_aligned_; // when true, all blocks need to be page aligned
int handle_alignment_; // Alignment to be used when Handles are requested.
int handle_alignment_bits_; // log2(handle_alignment_).
// The amount of bits required to keep block_size_ (ceil(log2(block_size_))).
size_t block_size_bits_;
void FreeBlocks(); // Frees all except first block
// This subclass needs to alter permissions for all allocated blocks.
friend class ProtectableUnsafeArena;
DISALLOW_COPY_AND_ASSIGN(BaseArena);
};
class CTEMPLATE_DLL_DECL UnsafeArena : public BaseArena {
public:
// Allocates a thread-compatible arena with the specified block size.
explicit UnsafeArena(const size_t block_size)
: BaseArena(NULL, block_size, false) { }
UnsafeArena(const size_t block_size, bool align)
: BaseArena(NULL, block_size, align) { }
// Allocates a thread-compatible arena with the specified block
// size. "first_block" must have size "block_size". Memory is
// allocated from "first_block" until it is exhausted; after that
// memory is allocated by allocating new blocks from the heap.
UnsafeArena(char* first_block, const size_t block_size)
: BaseArena(first_block, block_size, false) { }
UnsafeArena(char* first_block, const size_t block_size, bool align)
: BaseArena(first_block, block_size, align) { }
char* Alloc(const size_t size) {
return reinterpret_cast(GetMemory(size, 1));
}
void* AllocAligned(const size_t size, const int align) {
return GetMemory(size, align);
}
char* Calloc(const size_t size) {
void* return_value = Alloc(size);
memset(return_value, 0, size);
return reinterpret_cast(return_value);
}
void* CallocAligned(const size_t size, const int align) {
void* return_value = AllocAligned(size, align);
memset(return_value, 0, size);
return return_value;
}
// Free does nothing except for the last piece allocated.
void Free(void* memory, size_t size) {
ReturnMemory(memory, size);
}
typedef BaseArena::Handle Handle;
char* AllocWithHandle(const size_t size, Handle* handle) {
return reinterpret_cast(GetMemoryWithHandle(size, handle));
}
virtual char* SlowAlloc(size_t size) { // "slow" 'cause it's virtual
return Alloc(size);
}
virtual void SlowFree(void* memory, size_t size) { // "slow" 'cause it's virt
Free(memory, size);
}
virtual char* SlowRealloc(char* memory, size_t old_size, size_t new_size) {
return Realloc(memory, old_size, new_size);
}
virtual char* SlowAllocWithHandle(const size_t size, Handle* handle) {
return AllocWithHandle(size, handle);
}
char* Memdup(const char* s, size_t bytes) {
char* newstr = Alloc(bytes);
memcpy(newstr, s, bytes);
return newstr;
}
char* MemdupPlusNUL(const char* s, size_t bytes) { // like "string(s, len)"
char* newstr = Alloc(bytes+1);
memcpy(newstr, s, bytes);
newstr[bytes] = '\0';
return newstr;
}
Handle MemdupWithHandle(const char* s, size_t bytes) {
Handle handle;
char* newstr = AllocWithHandle(bytes, &handle);
memcpy(newstr, s, bytes);
return handle;
}
char* Strdup(const char* s) {
return Memdup(s, strlen(s) + 1);
}
// Unlike libc's strncpy, I always NUL-terminate. libc's semantics are dumb.
// This will allocate at most n+1 bytes (+1 is for the NULL terminator).
char* Strndup(const char* s, size_t n) {
// Use memchr so we don't walk past n.
// We can't use the one in //strings since this is the base library,
// so we have to reinterpret_cast from the libc void *.
const char* eos = reinterpret_cast(memchr(s, '\0', n));
// if no null terminator found, use full n
const size_t bytes = (eos == NULL) ? n + 1 : eos - s + 1;
char* ret = Memdup(s, bytes);
ret[bytes-1] = '\0'; // make sure the string is NUL-terminated
return ret;
}
// You can realloc a previously-allocated string either bigger or smaller.
// We can be more efficient if you realloc a string right after you allocate
// it (eg allocate way-too-much space, fill it, realloc to just-big-enough)
char* Realloc(char* s, size_t oldsize, size_t newsize);
// If you know the new size is smaller (or equal), you don't need to know
// oldsize. We don't check that newsize is smaller, so you'd better be sure!
char* Shrink(char* s, size_t newsize) {
AdjustLastAlloc(s, newsize); // reclaim space if we can
return s; // never need to move if we go smaller
}
// We make a copy so you can keep track of status at a given point in time
Status status() const { return status_; }
// Number of bytes remaining before the arena has to allocate another block.
size_t bytes_until_next_allocation() const { return remaining_; }
private:
DISALLOW_COPY_AND_ASSIGN(UnsafeArena);
};
// we inherit from BaseArena instead of UnsafeArena so that we don't need
// virtual methods for allocation/deallocation. This means, however,
// I have to copy the definitions of strdup, strndup, etc. :-(
class CTEMPLATE_DLL_DECL SafeArena : public BaseArena {
public:
// Allocates a thread-safe arena with the specified block size.
explicit SafeArena(const size_t block_size)
: BaseArena(NULL, block_size, false) { }
// Allocates a thread-safe arena with the specified block size.
// "first_block" must have size "block_size". Memory is allocated
// from "first_block" until it is exhausted; after that memory is
// allocated by allocating new blocks from the heap.
SafeArena(char* first_block, const size_t block_size)
: BaseArena(first_block, block_size, false) { }
virtual void Reset() LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_); // in case two threads Reset() at same time
BaseArena::Reset();
}
char* Alloc(const size_t size) LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return reinterpret_cast(GetMemory(size, 1));
}
void* AllocAligned(const size_t size, const int align)
LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return GetMemory(size, align);
}
char* Calloc(const size_t size) {
void* return_value = Alloc(size);
memset(return_value, 0, size);
return reinterpret_cast(return_value);
}
void* CallocAligned(const size_t size, const int align) {
void* return_value = AllocAligned(size, align);
memset(return_value, 0, size);
return return_value;
}
// Free does nothing except for the last piece allocated.
void Free(void* memory, size_t size) LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
ReturnMemory(memory, size);
}
typedef BaseArena::Handle Handle;
char* AllocWithHandle(const size_t size, Handle* handle)
LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return reinterpret_cast(GetMemoryWithHandle(size, handle));
}
virtual char* SlowAlloc(size_t size) { // "slow" 'cause it's virtual
return Alloc(size);
}
virtual void SlowFree(void* memory, size_t size) { // "slow" 'cause it's virt
Free(memory, size);
}
virtual char* SlowRealloc(char* memory, size_t old_size, size_t new_size) {
return Realloc(memory, old_size, new_size);
}
virtual char* SlowAllocWithHandle(const size_t size, Handle* handle) {
return AllocWithHandle(size, handle);
}
char* Memdup(const char* s, size_t bytes) {
char* newstr = Alloc(bytes);
memcpy(newstr, s, bytes);
return newstr;
}
char* MemdupPlusNUL(const char* s, size_t bytes) { // like "string(s, len)"
char* newstr = Alloc(bytes+1);
memcpy(newstr, s, bytes);
newstr[bytes] = '\0';
return newstr;
}
Handle MemdupWithHandle(const char* s, size_t bytes) {
Handle handle;
char* newstr = AllocWithHandle(bytes, &handle);
memcpy(newstr, s, bytes);
return handle;
}
char* Strdup(const char* s) {
return Memdup(s, strlen(s) + 1);
}
// Unlike libc's strncpy, I always NUL-terminate. libc's semantics are dumb.
// This will allocate at most n+1 bytes (+1 is for the NULL terminator).
char* Strndup(const char* s, size_t n) {
// Use memchr so we don't walk past n.
// We can't use the one in //strings since this is the base library,
// so we have to reinterpret_cast from the libc void *.
const char* eos = reinterpret_cast(memchr(s, '\0', n));
// if no null terminator found, use full n
const size_t bytes = (eos == NULL) ? n + 1 : eos - s + 1;
char* ret = Memdup(s, bytes);
ret[bytes-1] = '\0'; // make sure the string is NUL-terminated
return ret;
}
// You can realloc a previously-allocated string either bigger or smaller.
// We can be more efficient if you realloc a string right after you allocate
// it (eg allocate way-too-much space, fill it, realloc to just-big-enough)
char* Realloc(char* s, size_t oldsize, size_t newsize)
LOCKS_EXCLUDED(mutex_);
// If you know the new size is smaller (or equal), you don't need to know
// oldsize. We don't check that newsize is smaller, so you'd better be sure!
char* Shrink(char* s, size_t newsize) LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
AdjustLastAlloc(s, newsize); // reclaim space if we can
return s; // we never need to move if we go smaller
}
Status status() LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return status_;
}
// Number of bytes remaining before the arena has to allocate another block.
size_t bytes_until_next_allocation() LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return remaining_;
}
protected:
Mutex mutex_;
private:
DISALLOW_COPY_AND_ASSIGN(SafeArena);
};
_END_GOOGLE_NAMESPACE_
#endif // BASE_ARENA_H_
ctemplate-2.2/src/base/small_map.h 0000644 0001750 0001750 00000041207 11743633404 014104 0000000 0000000 // Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Author: kenton@google.com (Kenton Varda)
//
// small_map is a drop-in replacement for map or hash_map. It uses a fixed
// array to store a certain number of elements, then reverts to using a
// map or hash_map when it runs out of space. For maps that are typically
// small, this can be considerably faster than using something like hash_map
// directly, as hash_map is optimized for large data sets. Of course, in
// order for this to be a significant win, you have to have a situation where
// you are using lots and lots of these small maps. One such situation is
// MessageSet: A set of search results may contain thousands of MessageSets,
// each containing only a couple items.
//
// TODO(kenton): This is very minimal, and was originally written for a
// very specific use (MessageSet). It only implements a few core methods
// of the STL associative container interface, though you are welcome to
// extend it.
#ifndef UTIL_GTL_SMALL_MAP_H_
#define UTIL_GTL_SMALL_MAP_H_
#include
#include
#include // for make_pair()
#include "base/manual_constructor.h"
_START_GOOGLE_NAMESPACE_
template struct CompileAssert { };
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
// An STL-like associative container which starts out backed by a simple
// array but switches to some other container type if it grows beyond a
// fixed size.
//
// NormalMap: The map type to fall back to. This also defines the key
// and value types for the small_map.
// kArraySize: The size of the initial array of results. Once the map
// grows beyond this size, the map type will be used instead.
// EqualKey: A functor which tests two keys for equality. If the wrapped
// map type has a "key_equal" member (hash_map does), then that
// will be used by default. Otherwise you must specify this
// manually.
// MapInit: A functor that takes a ManualConstructor* and uses it to
// initialize the map. This functor will be called at most once per
// small_map, when the map exceeds the threshold of kArraySize and we
// are about to copy values from the array to the map. The functor
// *must* call one of the Init() methods provided by
// ManualConstructor, since after it runs we assume that the NormalMap
// has been initialized.
//
// example:
// small_map > days;
// days["sunday" ] = 0;
// days["monday" ] = 1;
// days["tuesday" ] = 2;
// days["wednesday"] = 3;
// days["thursday" ] = 4;
// days["friday" ] = 5;
// days["saturday" ] = 6;
//
// You should assume that small_map might invalidate all the iterators
// on any call to erase(), insert() and operator[].
template
class small_map_default_init {
public:
void operator ()(ManualConstructor* map) const {
map->Init();
}
};
template >
class small_map {
// We cannot rely on the compiler to reject array of size 0. In
// particular, gcc 2.95.3 does it but later versions allow 0-length
// arrays. Therefore, we explicitly reject non-positive kArraySize
// here.
COMPILE_ASSERT(kArraySize > 0, default_initial_size_should_be_positive);
public:
typedef typename NormalMap::key_type key_type;
typedef typename NormalMap::mapped_type data_type;
typedef typename NormalMap::mapped_type mapped_type;
typedef typename NormalMap::value_type value_type;
typedef EqualKey key_equal;
small_map() : size_(0), functor_(MapInit()) {}
explicit small_map(const MapInit& functor) : size_(0), functor_(functor) {}
// Allow copy-constructor and assignment, since STL allows them too.
small_map(const small_map& src) {
// size_ and functor_ are initted in InitFrom()
InitFrom(src);
}
void operator=(const small_map& src) {
if (&src == this) return;
// This is not optimal. If src and dest are both using the small
// array, we could skip the teardown and reconstruct. One problem
// to be resolved is that the value_type itself is pair, and const K is not assignable.
Destroy();
InitFrom(src);
}
~small_map() {
Destroy();
}
class const_iterator;
class iterator {
public:
typedef typename NormalMap::iterator::iterator_category iterator_category;
typedef typename NormalMap::iterator::value_type value_type;
typedef typename NormalMap::iterator::difference_type difference_type;
typedef typename NormalMap::iterator::pointer pointer;
typedef typename NormalMap::iterator::reference reference;
inline iterator(): array_iter_(NULL) {}
inline iterator& operator++() {
if (array_iter_ != NULL) {
++array_iter_;
} else {
++hash_iter_;
}
return *this;
}
inline iterator operator++(int) {
iterator result(*this);
++(*this);
return result;
}
inline iterator& operator--() {
if (array_iter_ != NULL) {
--array_iter_;
} else {
--hash_iter_;
}
return *this;
}
inline iterator operator--(int) {
iterator result(*this);
--(*this);
return result;
}
inline value_type* operator->() const {
if (array_iter_ != NULL) {
return array_iter_->get();
} else {
return hash_iter_.operator->();
}
}
inline value_type& operator*() const {
if (array_iter_ != NULL) {
return *array_iter_->get();
} else {
return *hash_iter_;
}
}
inline bool operator==(const iterator& other) const {
if (array_iter_ != NULL) {
return array_iter_ == other.array_iter_;
} else {
return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
}
}
inline bool operator!=(const iterator& other) const {
return !(*this == other);
}
bool operator==(const const_iterator& other) const;
bool operator!=(const const_iterator& other) const;
private:
friend class small_map;
friend class const_iterator;
inline explicit iterator(ManualConstructor* init)
: array_iter_(init) {}
inline explicit iterator(const typename NormalMap::iterator& init)
: array_iter_(NULL), hash_iter_(init) {}
ManualConstructor* array_iter_;
typename NormalMap::iterator hash_iter_;
};
class const_iterator {
public:
typedef typename NormalMap::const_iterator::iterator_category iterator_category;
typedef typename NormalMap::const_iterator::value_type value_type;
typedef typename NormalMap::const_iterator::difference_type difference_type;
typedef typename NormalMap::const_iterator::pointer pointer;
typedef typename NormalMap::const_iterator::reference reference;
inline const_iterator(): array_iter_(NULL) {}
inline const_iterator(const iterator& other)
: array_iter_(other.array_iter_), hash_iter_(other.hash_iter_) {}
inline const_iterator& operator++() {
if (array_iter_ != NULL) {
++array_iter_;
} else {
++hash_iter_;
}
return *this;
}
inline const_iterator operator++(int) {
const_iterator result(*this);
++(*this);
return result;
}
inline const_iterator& operator--() {
if (array_iter_ != NULL) {
--array_iter_;
} else {
--hash_iter_;
}
return *this;
}
inline const_iterator operator--(int) {
const_iterator result(*this);
--(*this);
return result;
}
inline const value_type* operator->() const {
if (array_iter_ != NULL) {
return array_iter_->get();
} else {
return hash_iter_.operator->();
}
}
inline const value_type& operator*() const {
if (array_iter_ != NULL) {
return *array_iter_->get();
} else {
return *hash_iter_;
}
}
inline bool operator==(const const_iterator& other) const {
if (array_iter_ != NULL) {
return array_iter_ == other.array_iter_;
} else {
return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
}
}
inline bool operator!=(const const_iterator& other) const {
return !(*this == other);
}
private:
friend class small_map;
inline explicit const_iterator(
const ManualConstructor* init)
: array_iter_(init) {}
inline explicit const_iterator(
const typename NormalMap::const_iterator& init)
: array_iter_(NULL), hash_iter_(init) {}
const ManualConstructor* array_iter_;
typename NormalMap::const_iterator hash_iter_;
};
iterator find(const key_type& key) {
key_equal compare;
if (size_ >= 0) {
for (int i = 0; i < size_; i++) {
if (compare(array_[i]->first, key)) {
return iterator(array_ + i);
}
}
return iterator(array_ + size_);
} else {
return iterator(map()->find(key));
}
}
const_iterator find(const key_type& key) const {
key_equal compare;
if (size_ >= 0) {
for (int i = 0; i < size_; i++) {
if (compare(array_[i]->first, key)) {
return const_iterator(array_ + i);
}
}
return const_iterator(array_ + size_);
} else {
return const_iterator(map()->find(key));
}
}
// Invalidates iterators.
data_type& operator[](const key_type& key) {
key_equal compare;
if (size_ >= 0) {
// operator[] searches backwards, favoring recently-added
// elements.
for (int i = size_-1; i >= 0; --i) {
if (compare(array_[i]->first, key)) {
return array_[i]->second;
}
}
if (size_ == kArraySize) {
ConvertToRealMap();
return (*map_)[key];
} else {
array_[size_].Init(key, data_type());
return array_[size_++]->second;
}
} else {
return (*map_)[key];
}
}
// Invalidates iterators.
std::pair insert(const value_type& x) {
key_equal compare;
if (size_ >= 0) {
for (int i = 0; i < size_; i++) {
if (compare(array_[i]->first, x.first)) {
return std::make_pair(iterator(array_ + i), false);
}
}
if (size_ == kArraySize) {
ConvertToRealMap(); // Invalidates all iterators!
std::pair ret = map_->insert(x);
return std::make_pair(iterator(ret.first), ret.second);
} else {
array_[size_].Init(x);
return std::make_pair(iterator(array_ + size_++), true);
}
} else {
std::pair ret = map_->insert(x);
return std::make_pair(iterator(ret.first), ret.second);
}
}
// Invalidates iterators.
template
void insert(InputIterator f, InputIterator l) {
while (f != l) {
insert(*f);
++f;
}
}
iterator begin() {
if (size_ >= 0) {
return iterator(array_);
} else {
return iterator(map_->begin());
}
}
const_iterator begin() const {
if (size_ >= 0) {
return const_iterator(array_);
} else {
return const_iterator(map_->begin());
}
}
iterator end() {
if (size_ >= 0) {
return iterator(array_ + size_);
} else {
return iterator(map_->end());
}
}
const_iterator end() const {
if (size_ >= 0) {
return const_iterator(array_ + size_);
} else {
return const_iterator(map_->end());
}
}
void clear() {
if (size_ >= 0) {
for (int i = 0; i < size_; i++) {
array_[i].Destroy();
}
} else {
map_.Destroy();
}
size_ = 0;
}
// Invalidates iterators.
void erase(const iterator& position) {
if (size_ >= 0) {
int i = position.array_iter_ - array_;
array_[i].Destroy();
--size_;
if (i != size_) {
array_[i].Init(*array_[size_]);
array_[size_].Destroy();
}
} else {
map_->erase(position.hash_iter_);
}
}
int erase(const key_type& key) {
iterator iter = find(key);
if (iter == end()) return 0;
erase(iter);
return 1;
}
int count(const key_type& key) const {
return (find(key) == end()) ? 0 : 1;
}
int size() const {
if (size_ >= 0) {
return size_;
} else {
return map_->size();
}
}
bool empty() const {
if (size_ >= 0) {
return (size_ == 0);
} else {
return map_->empty();
}
}
// Returns true if we have fallen back to using the underlying map
// representation.
bool using_full_map() const {
return size_ < 0;
}
inline NormalMap* map() {
assert(using_full_map());
return map_.get();
}
inline const NormalMap* map() const {
assert(using_full_map());
return map_.get();
}
private:
int size_; // negative = using hash_map
MapInit functor_;
// We want to call constructors and destructors manually, but we don't
// want to allocate and deallocate the memory used for them separately.
// So, we use this crazy ManualConstructor class.
//
// Since array_ and map_ are mutually exclusive, we'll put them in a
// union, too. We add in a dummy_ value which quiets MSVC (both
// 7.1 and 8.0) from otherwise giving an erroneous "union member has
// copy constructor" error message (C2621). This dummy member has
// to come before array_ to quiet the compiler. Shrug.
union {
ManualConstructor dummy_;
ManualConstructor array_[kArraySize];
ManualConstructor map_;
};
void ConvertToRealMap() {
// Move the current elements into a temporary array.
ManualConstructor temp_array[kArraySize];
for (int i = 0; i < kArraySize; i++) {
temp_array[i].Init(*array_[i]);
array_[i].Destroy();
}
// Initialize the map.
size_ = -1;
functor_(&map_);
// Insert elements into it.
for (int i = 0; i < kArraySize; i++) {
map_->insert(*temp_array[i]);
temp_array[i].Destroy();
}
}
// Helpers for constructors and destructors.
void InitFrom(const small_map& src) {
functor_ = src.functor_;
size_ = src.size_;
if (src.size_ >= 0) {
for (int i = 0; i < size_; i++) {
array_[i].Init(*src.array_[i]);
}
} else {
functor_(&map_);
(*map_.get()) = (*src.map_.get());
}
}
void Destroy() {
if (size_ >= 0) {
for (int i = 0; i < size_; i++) {
array_[i].Destroy();
}
} else {
map_.Destroy();
}
}
};
template
inline bool small_map::iterator::operator==(
const const_iterator& other) const {
return other == *this;
}
template
inline bool small_map::iterator::operator!=(
const const_iterator& other) const {
return other != *this;
}
_END_GOOGLE_NAMESPACE_
#endif // UTIL_GTL_SMALL_MAP_H_
ctemplate-2.2/src/base/mutex.h 0000644 0001750 0001750 00000040236 11743633404 013302 0000000 0000000 // 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.
//
// ---
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
// 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 and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
// to expose it, you'll want to move it to the Google namespace. We
// cannot put this class in global namespace because there can be some
// problems when we have multiple versions of Mutex in each shared object.
//
// NOTE: by default, we have #ifdef'ed out the TryLock() method.
// This is for two reasons:
// 1) TryLock() under Windows is a bit annoying (it requires a
// #define to be defined very early).
// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
// mode.
// If you need TryLock(), and either these two caveats are not a
// problem for you, or you're willing to work around them, then
// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
// in the code below.
//
// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
// Because of that, we might as well use windows locks for
// cygwin. They seem to be more reliable than the cygwin pthreads layer.
//
// TRICKY IMPLEMENTATION NOTE:
// This class is designed to be safe to use during
// dynamic-initialization -- that is, by global constructors that are
// run before main() starts. The issue in this case is that
// dynamic-initialization happens in an unpredictable order, and it
// could be that someone else's dynamic initializer could call a
// function that tries to acquire this mutex -- but that all happens
// before this mutex's constructor has run. (This can happen even if
// the mutex and the function that uses the mutex are in the same .cc
// file.) Basically, because Mutex does non-trivial work in its
// constructor, it's not, in the naive implementation, safe to use
// before dynamic initialization has run on it.
//
// The solution used here is to pair the actual mutex primitive with a
// bool that is set to true when the mutex is dynamically initialized.
// (Before that it's false.) Then we modify all mutex routines to
// look at the bool, and not try to lock/unlock until the bool makes
// it to true (which happens after the Mutex constructor has run.)
//
// This works because before main() starts -- particularly, during
// dynamic initialization -- there are no threads, so a) it's ok that
// the mutex operations are a no-op, since we don't need locking then
// anyway; and b) we can be quite confident our bool won't change
// state between a call to Lock() and a call to Unlock() (that would
// require a global constructor in one translation unit to call Lock()
// and another global constructor in another translation unit to call
// Unlock() later, which is pretty perverse).
//
// That said, it's tricky, and can conceivably fail; it's safest to
// avoid trying to acquire a mutex in a global constructor, if you
// can. One way it can fail is that a really smart compiler might
// initialize the bool to true at static-initialization time (too
// early) rather than at dynamic-initialization time. To discourage
// that, we set is_safe_ to true in code (not the constructor
// colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough.
//
// A related issue is code that could try to access the mutex
// after it's been destroyed in the global destructors (because
// the Mutex global destructor runs before some other global
// destructor, that tries to acquire the mutex). The way we
// deal with this is by taking a constructor arg that global
// mutexes should pass in, that causes the destructor to do no
// work. We still depend on the compiler not doing anything
// weird to a Mutex's memory after it is destroyed, but for a
// static global variable, that's pretty safe.
#ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_
#include
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifndef NOMINMAX
# define NOMINMAX // Don't want windows to override min()/max()
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something.
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
# endif
# endif
# include
typedef CRITICAL_SECTION MutexType;
#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 -- it
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
# if _XOPEN_SOURCE < 500 // including not being defined at all
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# endif
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
# include
#endif
typedef pthread_rwlock_t MutexType;
#elif defined(HAVE_PTHREAD)
#if defined(HAVE_PTHREAD) && !defined(NO_THREADS)
# include
#endif
typedef pthread_mutex_t MutexType;
#else
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif
#include
#include // for abort()
_START_GOOGLE_NAMESPACE_
namespace base {
// This is used for the single-arg constructor
enum LinkerInitialized { LINKER_INITIALIZED };
}
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.
inline Mutex();
// This constructor should be used for global, static Mutex objects.
// It inhibits work being done by the destructor, which makes it
// safer for code that tries to acqiure this mutex in their global
// destructor.
inline Mutex(base::LinkerInitialized);
// Destructor
inline ~Mutex();
inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock()
#ifdef GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false
#endif
// 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.
inline void ReaderLock(); // Block until free or shared then acquire a share
inline void ReaderUnlock(); // Release a read share of this Mutex
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
private:
MutexType mutex_;
// We want to make sure that the compiler sets is_safe_ to true only
// when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that.
volatile bool is_safe_;
// This indicates which constructor was called.
bool destroy_;
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock.
Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors
Mutex(const Mutex&);
void operator=(const Mutex&);
};
// We will also define GoogleOnceType, GOOGLE_ONCE_INIT, and
// GoogleOnceInit, which are portable versions of pthread_once_t,
// PTHREAD_ONCE_INIT, and pthread_once.
// Now the implementation of Mutex for various systems
#if defined(NO_THREADS)
// When we don't have threads, we can be either reading or writing,
// but not both. We can have lots of readers at once (in no-threads
// mode, that's most likely to happen in recursive function calls),
// but only one writer. We represent this by having mutex_ be -1 when
// writing and a number > 0 when reading (and 0 when no lock is held).
//
// In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an
// assert.
Mutex::Mutex() : mutex_(0) { }
Mutex::Mutex(base::LinkerInitialized) : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
#endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
typedef int GoogleOnceType;
const GoogleOnceType GOOGLE_ONCE_INIT = 0;
inline int GoogleOnceInit(GoogleOnceType* once_control,
void (*init_routine)(void)) {
if ((*once_control)++ == 0)
(*init_routine)();
return 0;
}
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
Mutex::Mutex() : destroy_(true) {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::Mutex(base::LinkerInitialized) : destroy_(false) {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
TryEnterCriticalSection(&mutex_) != 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); }
// We do a simple spinlock for pthread_once_t. See
// http://www.ddj.com/cpp/199203083?pgno=3
#ifdef INTERLOCKED_EXCHANGE_NONVOLATILE
typedef LONG GoogleOnceType;
#else
typedef volatile LONG GoogleOnceType;
#endif
const GoogleOnceType GOOGLE_ONCE_INIT = 0;
inline int GoogleOnceInit(GoogleOnceType* once_control,
void (*init_routine)(void)) {
while (1) {
LONG prev = InterlockedCompareExchange(once_control, 1, 0);
if (prev == 2) { // We've successfully initted in the past.
return 0;
} else if (prev == 0) { // No init yet, but we have the lock.
(*init_routine)();
InterlockedExchange(once_control, 2);
return 0;
} else { // Someone else is holding the lock, so wait.
assert(1 == prev);
Sleep(1); // sleep for 1ms
}
}
return 1; // unreachable
}
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::Mutex(base::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD
typedef pthread_once_t GoogleOnceType;
const GoogleOnceType GOOGLE_ONCE_INIT = PTHREAD_ONCE_INIT;
inline int GoogleOnceInit(GoogleOnceType* once_control,
void (*init_routine)(void)) {
return pthread_once(once_control, init_routine);
}
#elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::Mutex(base::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_mutex_trylock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); }
#undef SAFE_PTHREAD
typedef pthread_once_t GoogleOnceType;
const GoogleOnceType GOOGLE_ONCE_INIT = PTHREAD_ONCE_INIT;
inline int GoogleOnceInit(GoogleOnceType* once_control,
void (*init_routine)(void)) {
return pthread_once(once_control, init_routine);
}
#endif
// --------------------------------------------------------------------------
// Some helper classes
// 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)
_END_GOOGLE_NAMESPACE_
#endif /* #define GOOGLE_MUTEX_H__ */
ctemplate-2.2/src/base/macros.h 0000644 0001750 0001750 00000007627 11743633404 013433 0000000 0000000 // Copyright 2011 Google Inc. All Rights Reserved.
// Author: csilvers@google.com (Craig Silverstein)
//
// Provides macros and typedefs based on config.h settings.
// Provides the following macros:
// UNALIGNED_LOAD32 (may be an inline function on some architectures)
// and the following typedefs:
// uint32
// uint64
#ifndef CTEMPLATE_MACROS_H_
#define CTEMPLATE_MACROS_H_
#include
#ifdef HAVE_STDINT_H
#include // the normal place uint32_t is defined
#endif
#ifdef HAVE_SYS_TYPES_H
#include // the normal place u_int32_t is defined
#endif
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
# include
#endif // a third place for uint32_t or u_int32_t
#endif
#if defined(HAVE_U_INT32_T)
typedef u_int32_t uint32;
#elif defined(HAVE_UINT32_T)
typedef uint32_t uint32;
#elif defined(HAVE___INT32)
typedef unsigned __int32 uint32;
#endif
#if defined(HAVE_U_INT64_T)
typedef u_int64_t uint64;
#elif defined(HAVE_UINT64_T)
typedef uint64_t uint64;
#elif defined(HAVE___INT64)
typedef unsigned __int64 uint64;
#endif
// This is all to figure out endian-ness and byte-swapping on various systems
#if defined(HAVE_ENDIAN_H)
#include // for the __BYTE_ORDER use below
#elif defined(HAVE_SYS_ENDIAN_H)
#include // location on FreeBSD
#elif defined(HAVE_MACHINE_ENDIAN_H)
#include // location on OS X
#endif
#if defined(HAVE_SYS_BYTEORDER_H)
#include // BSWAP_32 on Solaris 10
#endif
#ifdef HAVE_SYS_ISA_DEFS_H
#include // _BIG_ENDIAN/_LITTLE_ENDIAN on Solaris 10
#endif
// MurmurHash does a lot of 4-byte unaligned integer access. It
// interprets these integers in little-endian order. This is perfect
// on x86, for which this is a natural memory access; for other systems
// we do what we can to make this as efficient as possible.
#if defined(HAVE_BYTESWAP_H)
# include // GNU (especially linux)
# define BSWAP32(x) bswap_32(x)
#elif defined(HAVE_LIBKERN_OSBYTEORDER_H)
# include // OS X
# define BSWAP32(x) OSSwapInt32(x)
#elif defined(bswap32) // FreeBSD
// FreeBSD defines bswap32 as a macro in sys/endian.h (already #included)
# define BSWAP32(x) bswap32(x)
#elif defined(BSWAP_32) // Solaris 10
// Solaris defines BSWSAP_32 as a macro in sys/byteorder.h (already #included)
# define BSWAP32(x) BSWAP_32(x)
#elif !defined(BSWAP32)
# define BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0xff000000) >> 24));
#else
# define CTEMPLATE_BSWAP32_ALREADY_DEFINED
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
// We know they allow unaligned memory access and are little-endian
# define UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p))
#elif defined(__ppc__) || defined(__ppc64__)
// We know they allow unaligned memory access and are big-endian
# define UNALIGNED_LOAD32(_p) BSWAP32(*reinterpret_cast(_p))
#elif (BYTE_ORDER == 1234) || (_BYTE_ORDER == 1234) || defined(_LITTLE_ENDIAN)
// Use memcpy to align the memory properly
inline uint32 UNALIGNED_LOAD32(const void *p) {
uint32 t;
memcpy(&t, p, sizeof(t));
return t;
}
#elif (BYTE_ORDER == 4321) || (_BYTE_ORDER == 4321) || defined(_BIG_ENDIAN)
inline uint32 UNALIGNED_LOAD32(const void *p) {
uint32 t;
memcpy(&t, p, sizeof(t));
return BSWAP32(t);
}
#else
// Means we can't find find endian.h on this machine:
# error Need to define UNALIGNED_LOAD32 for this architecture
#endif
#ifndef CTEMPLATE_BSWAP32_ALREADY_DEFINED
# undef BSWAP32 // don't leak outside this file
#else
# undef CTEMPLATE_BSWAP32_ALREADY_DEFINED // just cleaning up
#endif
#endif // CTEMPLATE_MACROS_H_
ctemplate-2.2/src/base/arena.cc 0000644 0001750 0001750 00000051211 11743633404 013357 0000000 0000000 // Copyright (c) 2000, 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.
// ---
//
// Reorganized by Craig Silverstein
// "Handles" by Ilan Horn
//
// This approach to arenas overcomes many of the limitations described
// in the "Specialized allocators" section of
// http://www.pdos.lcs.mit.edu/~dm/c++-new.html
//
// A somewhat similar approach to Gladiator, but for heap-detection, was
// suggested by Ron van der Wal and Scott Meyers at
// http://www.aristeia.com/BookErrata/M27Comments_frames.html
#include
#include "base/arena.h"
#include "base/arena-inl.h"
#include
#include
#ifdef HAVE_UNISTD_H
# include
#endif
#include
#include // one place uintptr_t might be
#ifdef HAVE_INTTYPES_H
# include
#endif // another place uintptr_t might be
#ifdef HAVE_UNISTD_H
# include
#endif // last place uintptr_t might be
#include "base/macros.h" // for uint64
#include "base/mutex.h"
#include "base/util.h" // for DCHECK_*
using std::min;
using std::vector;
// TODO(csilvers): add in a portable implementation of aligned_malloc
static void* aligned_malloc(size_t size, size_t alignment) {
LOG(FATAL) << "page_aligned_ not currently supported\n";
}
// The value here doesn't matter until page_aligned_ is supported.
static const int kPageSize = 8192; // should be getpagesize()
_START_GOOGLE_NAMESPACE_
// We used to only keep track of how much space has been allocated in
// debug mode. Now we track this for optimized builds, as well. If you
// want to play with the old scheme to see if this helps performance,
// change this ARENASET() macro to a NOP. However, NOTE: some
// applications of arenas depend on this space information (exported
// via bytes_allocated()).
#define ARENASET(x) (x)
// ----------------------------------------------------------------------
// BaseArena::BaseArena()
// BaseArena::~BaseArena()
// Destroying the arena automatically calls Reset()
// ----------------------------------------------------------------------
BaseArena::BaseArena(char* first, const size_t block_size, bool align_to_page)
: remaining_(0),
first_block_we_own_(first ? 1 : 0),
block_size_(block_size),
freestart_(NULL), // set for real in Reset()
last_alloc_(NULL),
blocks_alloced_(1),
overflow_blocks_(NULL),
page_aligned_(align_to_page),
handle_alignment_(1),
handle_alignment_bits_(0),
block_size_bits_(0) {
assert(block_size > kDefaultAlignment);
while ((static_cast(1) << block_size_bits_) < block_size_) {
++block_size_bits_;
}
if (page_aligned_) {
// kPageSize must be power of 2, so make sure of this.
CHECK(kPageSize > 0 && 0 == (kPageSize & (kPageSize - 1)))
<< "kPageSize[ " << kPageSize << "] is not "
<< "correctly initialized: not a power of 2.";
}
if (first) {
CHECK(!page_aligned_ ||
(reinterpret_cast(first) & (kPageSize - 1)) == 0);
first_blocks_[0].mem = first;
} else {
if (page_aligned_) {
// Make sure the blocksize is page multiple, as we need to end on a page
// boundary.
CHECK_EQ(block_size & (kPageSize - 1), 0) << "block_size is not a"
<< "multiple of kPageSize";
first_blocks_[0].mem = reinterpret_cast(aligned_malloc(block_size_,
kPageSize));
PCHECK(NULL != first_blocks_[0].mem);
} else {
first_blocks_[0].mem = reinterpret_cast(malloc(block_size_));
}
}
first_blocks_[0].size = block_size_;
Reset();
}
BaseArena::~BaseArena() {
FreeBlocks();
assert(overflow_blocks_ == NULL); // FreeBlocks() should do that
// The first X blocks stay allocated always by default. Delete them now.
for ( int i = first_block_we_own_; i < blocks_alloced_; ++i )
free(first_blocks_[i].mem);
}
// ----------------------------------------------------------------------
// BaseArena::block_count()
// Only reason this is in .cc file is because it involves STL.
// ----------------------------------------------------------------------
int BaseArena::block_count() const {
return (blocks_alloced_ +
(overflow_blocks_ ? static_cast(overflow_blocks_->size()) : 0));
}
// ----------------------------------------------------------------------
// BaseArena::Reset()
// Clears all the memory an arena is using.
// ----------------------------------------------------------------------
void BaseArena::Reset() {
FreeBlocks();
freestart_ = first_blocks_[0].mem;
remaining_ = first_blocks_[0].size;
last_alloc_ = NULL;
ARENASET(status_.bytes_allocated_ = block_size_);
// We do not know for sure whether or not the first block is aligned,
// so we fix that right now.
const int overage = reinterpret_cast(freestart_) &
(kDefaultAlignment-1);
if (overage > 0) {
const int waste = kDefaultAlignment - overage;
freestart_ += waste;
remaining_ -= waste;
}
freestart_when_empty_ = freestart_;
assert(!(reinterpret_cast(freestart_)&(kDefaultAlignment-1)));
}
// ----------------------------------------------------------------------
// BaseArena::MakeNewBlock()
// Our sbrk() equivalent. We always make blocks of the same size
// (though GetMemory() can also make a new block for really big
// data.
// ----------------------------------------------------------------------
void BaseArena::MakeNewBlock() {
AllocatedBlock *block = AllocNewBlock(block_size_);
freestart_ = block->mem;
remaining_ = block->size;
}
// -------------------------------------------------------------
// BaseArena::AllocNewBlock()
// Adds and returns an AllocatedBlock.
// The returned AllocatedBlock* is valid until the next call
// to AllocNewBlock or Reset. (i.e. anything that might
// affect overflow_blocks_).
// -------------------------------------------------------------
BaseArena::AllocatedBlock* BaseArena::AllocNewBlock(const size_t block_size) {
AllocatedBlock *block;
// Find the next block.
if ( blocks_alloced_ < ARRAYSIZE(first_blocks_) ) {
// Use one of the pre-allocated blocks
block = &first_blocks_[blocks_alloced_++];
} else { // oops, out of space, move to the vector
if (overflow_blocks_ == NULL) overflow_blocks_ = new vector;
// Adds another block to the vector.
overflow_blocks_->resize(overflow_blocks_->size()+1);
// block points to the last block of the vector.
block = &overflow_blocks_->back();
}
if (page_aligned_) {
// We need the size to be multiple of kPageSize to mprotect it later.
size_t num_pages = ((block_size - 1) / kPageSize) + 1;
size_t new_block_size = num_pages * kPageSize;
block->mem = reinterpret_cast(aligned_malloc(new_block_size,
kPageSize));
PCHECK(NULL != block->mem);
block->size = new_block_size;
} else {
block->mem = reinterpret_cast(malloc(block_size));
block->size = block_size;
}
ARENASET(status_.bytes_allocated_ += block_size);
return block;
}
// ----------------------------------------------------------------------
// BaseArena::IndexToBlock()
// Index encoding is as follows:
// For blocks in the first_blocks_ array, we use index of the block in
// the array.
// For blocks in the overflow_blocks_ vector, we use the index of the
// block in iverflow_blocks_, plus the size of the first_blocks_ array.
// ----------------------------------------------------------------------
const BaseArena::AllocatedBlock *BaseArena::IndexToBlock(int index) const {
if (index < ARRAYSIZE(first_blocks_)) {
return &first_blocks_[index];
}
CHECK(overflow_blocks_ != NULL);
int index_in_overflow_blocks = index - ARRAYSIZE(first_blocks_);
CHECK_GE(index_in_overflow_blocks, 0);
CHECK_LT(static_cast(index_in_overflow_blocks),
overflow_blocks_->size());
return &(*overflow_blocks_)[index_in_overflow_blocks];
}
// ----------------------------------------------------------------------
// BaseArena::GetMemoryFallback()
// We take memory out of our pool, aligned on the byte boundary
// requested. If we don't have space in our current pool, we
// allocate a new block (wasting the remaining space in the
// current block) and give you that. If your memory needs are
// too big for a single block, we make a special your-memory-only
// allocation -- this is equivalent to not using the arena at all.
// ----------------------------------------------------------------------
void* BaseArena::GetMemoryFallback(const size_t size, const int align_as_int) {
if (0 == size) {
return NULL; // stl/stl_alloc.h says this is okay
}
// This makes the type-checker happy.
const size_t align = static_cast(align_as_int);
assert(align_as_int > 0 && 0 == (align & (align - 1))); // must be power of 2
// If the object is more than a quarter of the block size, allocate
// it separately to avoid wasting too much space in leftover bytes
if (block_size_ == 0 || size > block_size_/4) {
// then it gets its own block in the arena
assert(align <= kDefaultAlignment); // because that's what new gives us
// This block stays separate from the rest of the world; in particular
// we don't update last_alloc_ so you can't reclaim space on this block.
return AllocNewBlock(size)->mem;
}
const size_t overage =
(reinterpret_cast(freestart_) & (align-1));
if (overage) {
const size_t waste = align - overage;
freestart_ += waste;
if (waste < remaining_) {
remaining_ -= waste;
} else {
remaining_ = 0;
}
}
if (size > remaining_) {
MakeNewBlock();
}
remaining_ -= size;
last_alloc_ = freestart_;
freestart_ += size;
assert(0 == (reinterpret_cast(last_alloc_) & (align-1)));
return reinterpret_cast(last_alloc_);
}
// ----------------------------------------------------------------------
// BaseArena::ReturnMemoryFallback()
// BaseArena::FreeBlocks()
// Unlike GetMemory(), which does actual work, ReturnMemory() is a
// no-op: we don't "free" memory until Reset() is called. We do
// update some stats, though. Note we do no checking that the
// pointer you pass in was actually allocated by us, or that it
// was allocated for the size you say, so be careful here!
// FreeBlocks() does the work for Reset(), actually freeing all
// memory allocated in one fell swoop.
// ----------------------------------------------------------------------
void BaseArena::FreeBlocks() {
for ( int i = 1; i < blocks_alloced_; ++i ) { // keep first block alloced
free(first_blocks_[i].mem);
first_blocks_[i].mem = NULL;
first_blocks_[i].size = 0;
}
blocks_alloced_ = 1;
if (overflow_blocks_ != NULL) {
vector::iterator it;
for (it = overflow_blocks_->begin(); it != overflow_blocks_->end(); ++it) {
free(it->mem);
}
delete overflow_blocks_; // These should be used very rarely
overflow_blocks_ = NULL;
}
}
// ----------------------------------------------------------------------
// BaseArena::AdjustLastAlloc()
// If you realize you didn't want your last alloc to be for
// the size you asked, after all, you can fix it by calling
// this. We'll grow or shrink the last-alloc region if we
// can (we can always shrink, but we might not be able to
// grow if you want to grow too big.
// RETURNS true if we successfully modified the last-alloc
// region, false if the pointer you passed in wasn't actually
// the last alloc or if you tried to grow bigger than we could.
// ----------------------------------------------------------------------
bool BaseArena::AdjustLastAlloc(void *last_alloc, const size_t newsize) {
// It's only legal to call this on the last thing you alloced.
if (last_alloc == NULL || last_alloc != last_alloc_) return false;
// last_alloc_ should never point into a "big" block, w/ size >= block_size_
assert(freestart_ >= last_alloc_ && freestart_ <= last_alloc_ + block_size_);
assert(remaining_ >= 0); // should be: it's a size_t!
if (newsize > (freestart_ - last_alloc_) + remaining_)
return false; // not enough room, even after we get back last_alloc_ space
const char* old_freestart = freestart_; // where last alloc used to end
freestart_ = last_alloc_ + newsize; // where last alloc ends now
remaining_ -= (freestart_ - old_freestart); // how much new space we've taken
return true;
}
// ----------------------------------------------------------------------
// BaseArena::GetMemoryWithHandle()
// First, memory is allocated using GetMemory, using handle_alignment_.
// Since using different alignments for different handles would make
// the handles incompatible (e.g., we could end up with the same handle
// value referencing two different allocations, the alignment is not passed
// as an argument to GetMemoryWithHandle, and handle_alignment_ is used
// automatically for all GetMemoryWithHandle calls.
// Then we go about building a handle to reference the allocated memory.
// The block index used for the allocation, along with the offset inside
// the block, are encoded into the handle as follows:
// (block_index*block_size)+offset
// offset is simply the difference between the pointer returned by
// GetMemory and the starting pointer of the block.
// The above value is then divided by the alignment. As we know that
// both offset and the block_size are divisable by the alignment (this is
// enforced by set_handle_alignment() for block_size, and by GetMemory()
// for the offset), this does not lose any information, but allows to cram
// more into the limited space in handle.
// If the result does not fit into an unsigned 32-bit integer, we
// have run out of space that the handle can represent, and return
// an invalid handle. Note that the returned pointer is still usable,
// but this allocation cannot be referenced by a handle.
// ----------------------------------------------------------------------
void* BaseArena::GetMemoryWithHandle(
const size_t size, BaseArena::Handle* handle) {
CHECK(handle != NULL);
// For efficiency, handles are always allocated aligned to a power of 2.
void* p = GetMemory(size, (1 << handle_alignment_bits_));
// Find the index of the block the memory was allocated from. In most
// cases, this will be the last block, so the following loop will
// iterate exactly once.
int block_index;
const AllocatedBlock* block = NULL;
for (block_index = block_count() - 1; block_index >= 0; --block_index) {
block = IndexToBlock(block_index);
if ((p >= block->mem) && (p < (block->mem + block->size))) {
break;
}
}
CHECK_GE(block_index, 0) << "Failed to find block that was allocated from";
CHECK(block != NULL) << "Failed to find block that was allocated from";
const uint64 offset = reinterpret_cast(p) - block->mem;
DCHECK_LT(offset, block_size_);
DCHECK((offset & ((1 << handle_alignment_bits_) - 1)) == 0);
DCHECK((block_size_ & ((1 << handle_alignment_bits_) - 1)) == 0);
uint64 handle_value =
((static_cast(block_index) << block_size_bits_) + offset) >>
handle_alignment_bits_;
if (handle_value >= static_cast(0xFFFFFFFF)) {
// We ran out of space to be able to return a handle, so return an invalid
// handle.
handle_value = Handle::kInvalidValue;
}
handle->handle_ = static_cast(handle_value);
return p;
}
// ----------------------------------------------------------------------
// BaseArena::set_handle_alignment()
// Set the alignment to be used when Handles are requested. This can only
// be set for an arena that is empty - it cannot be changed on the fly.
// The alignment must be a power of 2 that the block size is divisable by.
// The default alignment is 1.
// Trying to set an alignment that does not meet the above constraints will
// cause a CHECK-failure.
// ----------------------------------------------------------------------
void BaseArena::set_handle_alignment(int align) {
CHECK(align > 0 && 0 == (align & (align - 1))); // must be power of 2
CHECK(static_cast(align) < block_size_);
CHECK((block_size_ % align) == 0);
CHECK(is_empty());
handle_alignment_ = align;
handle_alignment_bits_ = 0;
while ((1 << handle_alignment_bits_) < handle_alignment_) {
++handle_alignment_bits_;
}
}
// ----------------------------------------------------------------------
// BaseArena::HandleToPointer()
// First, the handle value needs to gain back the alignment factor that
// was divided out of it by GetMemoryWithHandle. Once this is done, it
// becomes trivial to extract the block index and offset in the block out
// of it, and calculate the pointer.
// ----------------------------------------------------------------------
void* BaseArena::HandleToPointer(const Handle& h) const {
CHECK(h.valid());
uint64 handle = static_cast(h.handle_) << handle_alignment_bits_;
int block_index = static_cast(handle >> block_size_bits_);
size_t block_offset =
static_cast(handle & ((1 << block_size_bits_) - 1));
const AllocatedBlock* block = IndexToBlock(block_index);
CHECK(block != NULL);
return reinterpret_cast(block->mem + block_offset);
}
// ----------------------------------------------------------------------
// UnsafeArena::Realloc()
// SafeArena::Realloc()
// If you decide you want to grow -- or shrink -- a memory region,
// we'll do it for you here. Typically this will involve copying
// the existing memory to somewhere else on the arena that has
// more space reserved. But if you're reallocing the last-allocated
// block, we may be able to accomodate you just by updating a
// pointer. In any case, we return a pointer to the new memory
// location, which may be the same as the pointer you passed in.
// Here's an example of how you might use Realloc():
//
// compr_buf = arena->Alloc(uncompr_size); // get too-much space
// int compr_size;
// zlib.Compress(uncompr_buf, uncompr_size, compr_buf, &compr_size);
// compr_buf = arena->Realloc(compr_buf, uncompr_size, compr_size);
// ----------------------------------------------------------------------
char* UnsafeArena::Realloc(char* s, size_t oldsize, size_t newsize) {
assert(oldsize >= 0 && newsize >= 0);
if ( AdjustLastAlloc(s, newsize) ) // in case s was last alloc
return s;
if ( newsize <= oldsize ) {
return s; // no need to do anything; we're ain't reclaiming any memory!
}
char * newstr = Alloc(newsize);
memcpy(newstr, s, min(oldsize, newsize));
return newstr;
}
char* SafeArena::Realloc(char* s, size_t oldsize, size_t newsize) {
assert(oldsize >= 0 && newsize >= 0);
{ MutexLock lock(&mutex_);
if ( AdjustLastAlloc(s, newsize) ) // in case s was last alloc
return s;
}
if ( newsize <= oldsize ) {
return s; // no need to do anything; we're ain't reclaiming any memory!
}
char * newstr = Alloc(newsize);
memcpy(newstr, s, min(oldsize, newsize));
return newstr;
}
_END_GOOGLE_NAMESPACE_
ctemplate-2.2/src/per_expand_data.cc 0000644 0001750 0001750 00000005624 11743633404 014504 0000000 0000000 // Copyright (c) 2009, 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.
// ---
//
// This contains some implementation of PerExpandData that is still simple
// but is not conveniently defined in the header file, e.g., because it would
// introduce new include dependencies.
#include
#include
#include
_START_GOOGLE_NAMESPACE_
using std::string;
#ifndef _MSC_VER
bool PerExpandData::DataEq::operator()(const char* s1, const char* s2) const {
return ((s1 == 0 && s2 == 0) ||
(s1 && s2 && *s1 == *s2 && strcmp(s1, s2) == 0));
}
#endif
PerExpandData::~PerExpandData() {
delete map_;
}
TemplateAnnotator* PerExpandData::annotator() const {
if (annotator_ != NULL) {
return annotator_;
}
// TextTemplateAnnotator has no static state. So direct static definition
// should be safe.
static TextTemplateAnnotator g_default_annotator;
return &g_default_annotator;
}
void PerExpandData::InsertForModifiers(const char* key, const void* value) {
if (!map_)
map_ = new DataMap;
(*map_)[key] = value;
}
// Retrieve data specific to this Expand call. Returns NULL if key
// is not found. This should only be used by template modifiers.
const void* PerExpandData::LookupForModifiers(const char* key) const {
if (!map_)
return NULL;
const DataMap::const_iterator it = map_->find(key);
return it == map_->end() ? NULL : it->second;
}
_END_GOOGLE_NAMESPACE_
ctemplate-2.2/src/solaris/ 0000755 0001750 0001750 00000000000 11743633635 012612 5 0000000 0000000 ctemplate-2.2/src/solaris/libstdc++.la 0000644 0001750 0001750 00000002755 11743633404 014625 0000000 0000000 # libstdc++.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# ---
# NOTE: This file lives in /usr/sfw/lib on Solaris 10. Unfortunately,
# due to an apparent bug in the Solaris 10 6/06 release,
# /usr/sfw/lib/libstdc++.la is empty. Below is the correct content,
# according to
# http://forum.java.sun.com/thread.jspa?threadID=5073150
# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
# this copy of the file rather than the empty copy in /usr/sfw/lib.
#
# Also see
# http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
#
# Note: this is for 32-bit systems. If you have a 64-bit system,
# uncomment the appropriate dependency_libs line below.
# ----
# The name that we can dlopen(3).
dlname='libstdc++.so.6'
# Names of this library.
library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
# The name of the static archive.
old_library='libstdc++.a'
# Libraries that this one depends upon.
# 32-bit version:
dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
# 64-bit version:
#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
# Version information for libstdc++.
current=6
age=0
revision=3
# Is this an already installed library?
installed=yes
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/usr/sfw/lib'
ctemplate-2.2/src/template.cc 0000644 0001750 0001750 00000345061 11743633404 013203 0000000 0000000 // Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
#include
#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
#include
#include
#include
#include // for fwrite, fflush
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
# include
#endif // for stat() and open() and getcwd()
#include