summaryrefslogtreecommitdiff
path: root/tools/quickbook/src/state.cpp
blob: d16200d62626f91ffcf367997dc7d3e95bed711d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*=============================================================================
    Copyright (c) 2002 2004 2006 Joel de Guzman
    Copyright (c) 2004 Eric Niebler
    Copyright (c) 2005 Thomas Guest
    http://spirit.sourceforge.net/

    Use, modification and distribution is subject to the Boost Software
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include "state.hpp"
#include "state_save.hpp"
#include "quickbook.hpp"
#include "grammar.hpp"
#include "input_path.hpp"
#include <boost/filesystem/operations.hpp>

#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
#pragma warning(disable:4355)
#endif

namespace quickbook
{
    char const* quickbook_get_date = "__quickbook_get_date__";
    char const* quickbook_get_time = "__quickbook_get_time__";

    unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version

    state::state(fs::path const& filein_, fs::path const& xinclude_base_,
            string_stream& out_, id_manager& ids)
        : grammar_()

        , xinclude_base(xinclude_base_)

        , templates()
        , error_count(0)
        , anchors()
        , warned_about_breaks(false)
        , conditional(true)
        , ids(ids)
        , callouts()
        , callout_depth(0)

        , imported(false)
        , macro()
        , source_mode("c++")
        , source_mode_next()
        , current_file(0)
        , filename_relative(filein_.filename())

        , template_depth(0)
        , min_section_level(1)

        , out(out_)
        , phrase()
        , values(&current_file)
    {
        // add the predefined macros
        macro.add
            ("__DATE__", std::string(quickbook_get_date))
            ("__TIME__", std::string(quickbook_get_time))
            ("__FILENAME__", detail::path_to_generic(filename_relative))
        ;

        boost::scoped_ptr<quickbook_grammar> g(
            new quickbook_grammar(*this));
        grammar_.swap(g);
    }

    quickbook_grammar& state::grammar() const {
        return *grammar_;
    }

    bool state::add_dependency(fs::path const& f) {
        fs::path p = fs::absolute(f);
        bool found = fs::exists(fs::status(p));

        // Pop path sections from path until we find an existing
        // path, adjusting for any dot path sections.
        fs::path extra;
        int parent_count = 0;
        while (!fs::exists(fs::status(p))) {
            fs::path name = p.filename();
            p = p.parent_path();
            if (name == "..") {
                ++parent_count;
            }
            else if (name == ".") {
            }
            else if (parent_count) {
                --parent_count;
            }
            else {
                extra = name / extra;
            }
        }

        // If there are any left over ".." sections, then add them
        // on to the end of the real path, and trust Boost.Filesystem
        // to sort them out.
        while (parent_count) {
            p = p / "..";
            --parent_count;
        }

        p = fs::canonical(p) / extra;
        dependencies[p] |= found;
        return found;
    }

    file_state::file_state(quickbook::state& state, scope_flags scope)
        : state(state)
        , scope(scope)
        , qbk_version(qbk_version_n)
        , imported(state.imported)
        , current_file(state.current_file)
        , filename_relative(state.filename_relative)
        , xinclude_base(state.xinclude_base)
        , source_mode(state.source_mode)
        , macro()
    {
        if (scope & scope_macros) macro = state.macro;
        if (scope & scope_templates) state.templates.push();
        if (scope & scope_output) {
            state.out.push();
            state.phrase.push();
        }
        state.values.builder.save();
    }

    file_state::~file_state()
    {
        state.values.builder.restore();
        boost::swap(qbk_version_n, qbk_version);
        boost::swap(state.imported, imported);
        boost::swap(state.current_file, current_file);
        boost::swap(state.filename_relative, filename_relative);
        boost::swap(state.xinclude_base, xinclude_base);
        boost::swap(state.source_mode, source_mode);
        if (scope & scope_output) {
            state.out.pop();
            state.phrase.pop();
        }
        if (scope & scope_templates) state.templates.pop();
        if (scope & scope_macros) state.macro = macro;
    }

    template_state::template_state(quickbook::state& state)
        : file_state(state, file_state::scope_all)
        , template_depth(state.template_depth)
        , min_section_level(state.min_section_level)
    {
    }

    template_state::~template_state()
    {
        boost::swap(state.template_depth, template_depth);
        boost::swap(state.min_section_level, min_section_level);
    }
}