diff --git a/src/actions.cpp b/src/actions.cpp index fd8d78b..2b7e6b9 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -677,10 +677,10 @@ namespace quickbook if (program.size() == 0) return; // Nothing left to do here. The program is empty. - file fake_file; - - fake_file.path = actions.current_file->path; - fake_file.source = program; + file fake_file( + actions.current_file->path, + program, + qbk_version_n); parse_iterator first_(fake_file.source.begin()); parse_iterator last_(fake_file.source.end()); @@ -852,7 +852,8 @@ namespace quickbook // fit in a tiny box (IE7). // - attributes.insert(attribute_map::value_type("format", qbk_value("SVG"))); + attributes.insert(attribute_map::value_type("format", + qbk_value("SVG", qbk_version_n))); // // Image paths are relative to the html subdirectory: @@ -890,7 +891,8 @@ namespace quickbook { attributes.insert(std::make_pair( "contentwidth", qbk_value(std::string( - svg_text.begin() + a + 1, svg_text.begin() + b)) + svg_text.begin() + a + 1, svg_text.begin() + b), + qbk_version_n) )); } a = svg_text.find("height"); @@ -901,7 +903,8 @@ namespace quickbook { attributes.insert(std::make_pair( "contentdepth", qbk_value(std::string( - svg_text.begin() + a + 1, svg_text.begin() + b)) + svg_text.begin() + a + 1, svg_text.begin() + b), + qbk_version_n) )); } } @@ -1135,47 +1138,32 @@ namespace quickbook bool parse_template( template_body const& body - , bool escape , quickbook::actions& actions ) { - if (escape) - { - // TODO: Should this be surrounded in escape comments? - // escape the body of the template - // we just copy out the literal body - (body.is_block() ? actions.out : actions.phrase) << body.content.get_quickbook(); - return true; - } - else if (body.type == template_body::raw_output) - { - (body.is_block() ? actions.out : actions.phrase) << body.content.get_boostbook(); - return true; - } - else - { - file const* saved_current_file = actions.current_file; + assert(body.type != template_body::raw_output); - actions.current_file = body.content.get_file(); - string_ref source = body.content.get_quickbook(); + file const* saved_current_file = actions.current_file; - parse_iterator first(source.begin()); - parse_iterator last(source.end()); + actions.current_file = body.content.get_file(); + string_ref source = body.content.get_quickbook(); - bool r = cl::parse(first, last, - body.is_block() ? - actions.grammar().block : - actions.grammar().simple_phrase - ).full; + parse_iterator first(source.begin()); + parse_iterator last(source.end()); - boost::swap(actions.current_file, saved_current_file); + bool r = cl::parse(first, last, + body.is_block() ? + actions.grammar().block : + actions.grammar().simple_phrase + ).full; - return r; - } + boost::swap(actions.current_file, saved_current_file); + + return r; } } - void call_template(quickbook::actions& actions, bool template_escape, + void call_template(quickbook::actions& actions, template_symbol const* symbol, std::vector const& args, string_iterator first) @@ -1193,6 +1181,8 @@ namespace quickbook { template_state state(actions); + qbk_version_n = symbol->body.content.get_file()->version(); + ++actions.template_depth; if (actions.template_depth > actions.max_template_depth) { @@ -1206,7 +1196,7 @@ namespace quickbook // [section] and [endsect] tags in the template are balanced. actions.min_section_level = actions.ids.section_level(); - // Quickbook 1.4-: When expanding the tempalte continue to use the + // Quickbook 1.4-: When expanding the template continue to use the // current scope (the dynamic scope). // Quickbook 1.5+: Use the scope the template was defined in // (the static scope). @@ -1228,7 +1218,7 @@ namespace quickbook /////////////////////////////////// // parse the template body: - if (!parse_template(symbol->body, template_escape, actions)) + if (!parse_template(symbol->body, actions)) { detail::outerr(actions.current_file, first) << "Expanding " @@ -1269,7 +1259,6 @@ namespace quickbook } void call_code_snippet(quickbook::actions& actions, - bool template_escape, template_symbol const* symbol, string_iterator first) { @@ -1296,7 +1285,7 @@ namespace quickbook callout_ids.push_back(callout_id2); } - call_template(actions, template_escape, symbol, args, first); + call_template(actions, symbol, args, first); std::string block; @@ -1314,8 +1303,7 @@ namespace quickbook template_state state(actions); ++actions.template_depth; - bool r = parse_template( - template_body(c), false, actions); + bool r = parse_template(template_body(c), actions); if(!r) { @@ -1368,6 +1356,30 @@ namespace quickbook template_symbol const* symbol = actions.templates.find(identifier); BOOST_ASSERT(symbol); + // Deal with raw templates and escaped templates. + + if (symbol->body.type == template_body::raw_output) + { + // Note: 'raw_output' is currently only used for callouts in code_snippets. + (symbol->body.is_block() ? actions.out : actions.phrase) + << symbol->body.content.get_boostbook(); + return; + } + else if (template_escape) + { + if (!args.empty()) + { + detail::outerr(actions.current_file, first) + << "Arguments for escaped template." + <body.is_block() ? actions.out : actions.phrase) + << symbol->body.content.get_quickbook(); + return; + } + /////////////////////////////////// // Initialise the arguments @@ -1391,7 +1403,7 @@ namespace quickbook return; } - call_template(actions, template_escape, symbol, args, first); + call_template(actions, symbol, args, first); } else { @@ -1405,7 +1417,7 @@ namespace quickbook args.clear(); } - call_code_snippet(actions, template_escape, symbol, first); + call_code_snippet(actions, symbol, first); } } @@ -1807,7 +1819,8 @@ namespace quickbook qbk_version_n >= 106u ? file_state::scope_callables : file_state::scope_macros); - actions.current_file = load(paths.filename); // Throws load_error + actions.current_file_tmp = load(paths.filename); // Throws load_error + actions.current_file = actions.current_file_tmp; actions.filename_relative = paths.filename_relative; actions.imported = (load_type == block_tags::import); @@ -1871,7 +1884,7 @@ namespace quickbook if (tname == "!") { ts.parent = &actions.templates.top_scope(); - call_code_snippet(actions, false, &ts, first); + call_code_snippet(actions, &ts, first); } } diff --git a/src/actions_class.hpp b/src/actions_class.hpp index f654dc0..eecf335 100644 --- a/src/actions_class.hpp +++ b/src/actions_class.hpp @@ -49,6 +49,9 @@ namespace quickbook int context; bool conditional; id_manager& ids; + file* current_file_tmp; // Temporary non-const pointer to new + // current_file so that the + // version can be written to. // state saved for files and templates. bool imported; diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp index 50dd406..d19e034 100644 --- a/src/code_snippet.cpp +++ b/src/code_snippet.cpp @@ -26,7 +26,7 @@ namespace quickbook struct code_snippet_actions { code_snippet_actions(std::vector& storage, - file const* source_file, + file* source_file, char const* source_type) : callout_id(0) , storage(storage) @@ -84,7 +84,7 @@ namespace quickbook std::string code; std::string id; std::vector& storage; - file const* source_file; + file* source_file; char const* const source_type; }; @@ -321,7 +321,7 @@ namespace quickbook load_type == block_tags::import); bool is_python = extension == ".py"; - code_snippet_actions a(storage, load(filename), is_python ? "[python]" : "[c++]"); + code_snippet_actions a(storage, load(filename, qbk_version_n), is_python ? "[python]" : "[c++]"); // TODO: Should I check that parse succeeded? @@ -461,7 +461,7 @@ namespace quickbook } // TODO: Save position in start_snippet - template_symbol symbol(snippet->id, params, qbk_value(body, template_tags::block)); + template_symbol symbol(snippet->id, params, qbk_value(body, qbk_version_n, template_tags::block)); symbol.callouts = callouts; storage.push_back(symbol); diff --git a/src/doc_info_actions.cpp b/src/doc_info_actions.cpp index 40cb678..d4a22e0 100644 --- a/src/doc_info_actions.cpp +++ b/src/doc_info_actions.cpp @@ -146,6 +146,7 @@ namespace quickbook if (!docinfo_type) { + actions.current_file_tmp->version(qbk_version_n); actions.ids.start_file(include_doc_id_, id_, actions.doc_title_qbk); return; @@ -193,6 +194,8 @@ namespace quickbook ++actions.error_count; } + actions.current_file_tmp->version(qbk_version_n); + id_manager::start_file_info start_file_info = actions.ids.start_file_with_docinfo( qbk_version_n, include_doc_id_, id_, diff --git a/src/files.cpp b/src/files.cpp index ac313f7..2103ef3 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -96,17 +96,13 @@ namespace quickbook boost::unordered_map files; } - file const* load(fs::path const& filename) + file* load(fs::path const& filename, unsigned qbk_version) { - boost::unordered_map::iterator pos; - bool inserted; + boost::unordered_map::iterator pos + = files.find(filename); - boost::tie(pos, inserted) = files.emplace(filename, file()); - - if (inserted) + if (pos == files.end()) { - pos->second.path = filename; - fs::ifstream in(filename, std::ios_base::in); if (!in) @@ -115,10 +111,21 @@ namespace quickbook // Turn off white space skipping on the stream in.unsetf(std::ios::skipws); + std::string source; normalize( std::istream_iterator(in), std::istream_iterator(), - std::back_inserter(pos->second.source)); + std::back_inserter(source)); + + bool inserted; + + boost::tie(pos, inserted) = files.emplace( + boost::unordered::piecewise_construct, + boost::make_tuple(filename), + boost::make_tuple(filename, source, qbk_version) + ); + + assert(inserted); } return &pos->second; diff --git a/src/files.hpp b/src/files.hpp index c5b5ca7..d23f65c 100644 --- a/src/files.hpp +++ b/src/files.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace quickbook { @@ -27,11 +28,34 @@ namespace quickbook { struct file { - fs::path path; - std::string source; + fs::path const path; + std::string const source; + private: + unsigned qbk_version; + public: + + file(fs::path const& path, std::string const& source, + unsigned qbk_version) : + path(path), source(source), qbk_version(qbk_version) + {} + + unsigned version() const { + assert(qbk_version); + return qbk_version; + } + + void version(unsigned v) { + // Check that either version hasn't been set, or it was + // previously set to the same version (because the same + // file has been loaded twice). + assert(!qbk_version || qbk_version == v); + qbk_version = v; + } }; - file const* load(fs::path const& filename); + // If version isn't supplied then it must be set later. + file* load(fs::path const& filename, + unsigned qbk_version = 0); } #endif // BOOST_QUICKBOOK_FILES_HPP diff --git a/src/quickbook.cpp b/src/quickbook.cpp index 2af0647..1cfba23 100644 --- a/src/quickbook.cpp +++ b/src/quickbook.cpp @@ -130,7 +130,8 @@ namespace quickbook actions actor(filein_, xinclude_base_, buffer, ids); set_macros(actor); - actor.current_file = load(filein_); // Throws load_error + actor.current_file_tmp = load(filein_); // Throws load_error + actor.current_file = actor.current_file_tmp; parse_file(actor); diff --git a/src/values.cpp b/src/values.cpp index 7d32cc1..fd82241 100644 --- a/src/values.cpp +++ b/src/values.cpp @@ -315,7 +315,7 @@ namespace quickbook struct value_qbk_string_impl : public value_node { public: - explicit value_qbk_string_impl(std::string const&, value::tag_type); + explicit value_qbk_string_impl(std::string const&, unsigned qbk_version, value::tag_type); explicit value_qbk_string_impl(file const&, value::tag_type); private: char const* type_name() const { return "quickbook"; } @@ -427,12 +427,11 @@ namespace quickbook value_qbk_string_impl::value_qbk_string_impl( std::string const& v, + unsigned qbk_version, value::tag_type tag) : value_node(tag) - , fake_file_() + , fake_file_("(generated code)", v, qbk_version) { - fake_file_.source = v; - fake_file_.path = "(generated code)"; } value_qbk_string_impl::value_qbk_string_impl( @@ -584,9 +583,9 @@ namespace quickbook return value(new detail::value_qbk_ref_impl(f, x, y, t)); } - value qbk_value(std::string const& x, value::tag_type t) + value qbk_value(std::string const& x, unsigned qbk_version, value::tag_type t) { - return value(new detail::value_qbk_string_impl(x, t)); + return value(new detail::value_qbk_string_impl(x, qbk_version, t)); } value bbk_value(std::string const& x, value::tag_type t) diff --git a/src/values.hpp b/src/values.hpp index 8111a6e..d0a564f 100644 --- a/src/values.hpp +++ b/src/values.hpp @@ -240,7 +240,7 @@ namespace quickbook // Boostbook and quickbook strings value qbk_value_ref(file const*, string_iterator, string_iterator, value::tag_type = value::default_tag); - value qbk_value(std::string const&, value::tag_type = value::default_tag); + value qbk_value(std::string const&, unsigned qbk_version, value::tag_type = value::default_tag); value bbk_value(std::string const&, value::tag_type = value::default_tag); value qbk_bbk_value(file const*, string_iterator, string_iterator, std::string const&, value::tag_type = value::default_tag); diff --git a/src/values_parse.hpp b/src/values_parse.hpp index 7ae3196..dc3d65b 100644 --- a/src/values_parse.hpp +++ b/src/values_parse.hpp @@ -66,13 +66,6 @@ namespace quickbook { b.insert(qbk_value_ref(*current_file, begin.base(), end.base(), tag)); } - void operator()(parse_iterator begin, parse_iterator, - std::string const& v, - value::tag_type tag = value::default_tag) const - { - b.insert(qbk_value(v, tag)); - } - void operator()(int v, value::tag_type tag = value::default_tag) const { diff --git a/test/unit/values_test.cpp b/test/unit/values_test.cpp index 8747f40..e8085d0 100644 --- a/test/unit/values_test.cpp +++ b/test/unit/values_test.cpp @@ -25,8 +25,8 @@ void empty_tests() void qbk_tests() { - quickbook::file fake_file; - fake_file.source = "Source"; + quickbook::file fake_file( + "(fake file)", "Source", 105u); quickbook::value q = quickbook::qbk_value_ref( &fake_file, fake_file.source.begin(),