Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/tools/quickbook/detail/actions.cpp @ 50

Last change on this file since 50 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 29.1 KB
Line 
1/*=============================================================================
2    Copyright (c) 2002 2004 Joel de Guzman
3    Copyright (c) 2004 Eric Niebler
4    Copyright (c) 2005 Thomas Guest
5    http://spirit.sourceforge.net/
6
7    Use, modification and distribution is subject to the Boost Software
8    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9    http://www.boost.org/LICENSE_1_0.txt)
10=============================================================================*/
11#include <numeric>
12#include <functional>
13#include <boost/bind.hpp>
14#include <boost/filesystem/convenience.hpp>
15#include "./actions.hpp"
16#include "./utils.hpp"
17
18#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
19#pragma warning(disable:4355)
20#endif
21
22namespace quickbook
23{
24    void error_action::operator()(iterator const& first, iterator const& /*last*/) const
25    {
26        boost::spirit::file_position const pos = first.get_position();
27        detail::outerr(pos.file,pos.line)
28            << "Syntax Error near column " << pos.column << ".\n";
29    }
30
31    void phrase_action::operator()(iterator const& first, iterator const& last) const
32    {
33        if (out)
34        {
35            std::string str = phrase.str();
36            detail::convert_nbsp(str);
37            phrase.str(std::string());
38            out << pre << str << post;
39        }
40    }
41
42    void anchored_phrase_action::operator()(iterator const& first, iterator const& last) const
43    {
44        if (out)
45        {
46            std::string str = phrase.str();
47            detail::convert_nbsp(str);
48            if (qbk_version_n < 103) // version 1.2 and below
49            {
50                out << "<anchor id=\""
51                    << section_id << '.'
52                    << detail::make_identifier(str.begin(), str.end())
53                    << "\" />";
54            }
55            else // version 1.3 and above
56            {
57                out << "<anchor id=\""
58                    << library_id << '.' << qualified_section_id << '.'
59                    << detail::make_identifier(str.begin(), str.end())
60                    << "\" />";
61            }
62            phrase.str(std::string());
63            out << pre << str << post;
64        }
65    }
66
67    void simple_phrase_action::operator()(iterator first, iterator const& last) const
68    {
69        if (out)
70        {
71            out << pre;
72            while (first != last)
73                detail::print_char(*first++, out);
74            out << post;
75        }
76    }
77
78    void list_action::operator()(iterator const& first, iterator const& last) const
79    {
80        BOOST_ASSERT(!list_marks.empty()); // there must be at least one item in the stack
81        std::string  str = list_buffer.str();
82        list_buffer.str(std::string());
83        out << str;
84
85        while (!list_marks.empty())
86        {
87            char mark = list_marks.top().first;
88            list_marks.pop();
89            out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
90            if (list_marks.size() >= 1)
91                out << std::string("\n</listitem>");
92        }
93
94        indent = -1; // reset
95    }
96
97    void list_format_action::operator()(iterator first, iterator const& last) const
98    {
99        int new_indent = 0;
100        while (first != last && (*first == ' ' || *first == '\t'))
101        {
102            char mark = *first++;
103            if (mark == ' ')
104            {
105                ++new_indent;
106            }
107            else // must be a tab
108            {
109                BOOST_ASSERT(mark == '\t');
110                // hardcoded tab to 4 for now
111                new_indent = ((new_indent + 4) / 4) * 4;
112            }
113        }
114
115        char mark = *first;
116        BOOST_ASSERT(mark == '#' || mark == '*'); // expecting a mark
117
118        if (indent == -1) // the very start
119        {
120            BOOST_ASSERT(new_indent == 0);
121        }
122
123        if (new_indent > indent)
124        {
125            indent = new_indent;
126            list_marks.push(mark_type(mark, indent));
127            if (list_marks.size() > 1)
128            {
129                // Make this new list a child of the previous list.
130                // The previous listelem has already ended so we erase
131                // </listitem> to accomodate this sub-list. We'll close
132                // the listelem later.
133
134                std::string str = out.str();
135                std::string::size_type pos = str.rfind("\n</listitem>");
136                BOOST_ASSERT(pos <= str.size());
137                str.erase(str.begin()+pos, str.end());
138                out.str(std::string());
139                out << str;
140            }
141            out << std::string((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
142        }
143
144        else if (new_indent < indent)
145        {
146            BOOST_ASSERT(!list_marks.empty());
147            indent = new_indent;
148
149            while (!list_marks.empty() && (indent < list_marks.top().second))
150            {
151                char mark = list_marks.top().first;
152                list_marks.pop();
153                out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
154                if (list_marks.size() >= 1)
155                    out << std::string("\n</listitem>");
156            }
157        }
158
159        if (mark != list_marks.top().first) // new_indent == indent
160        {
161            boost::spirit::file_position const pos = first.get_position();
162            detail::outerr(pos.file,pos.line)
163                << "Illegal change of list style near column " << pos.column << ".\n";
164            detail::outwarn(pos.file,pos.line)
165                << "Ignoring change of list style" << std::endl;
166        }
167    }
168
169    void span::operator()(iterator first, iterator const& last) const
170    {
171        if (out)
172        {
173            out << "<phrase role=\"" << name << "\">";
174            while (first != last)
175                detail::print_char(*first++, out);
176            out << "</phrase>";
177        }
178    }
179
180    void unexpected_char::operator()(char) const
181    {
182        if (out)
183            out << '#'; // print out an unexpected character
184    }
185
186    void anchor_action::operator()(iterator first, iterator const& last) const
187    {
188        if (out)
189        {
190            out << "<anchor id=\"";
191            while (first != last)
192                detail::print_char(*first++, out);
193            out << "\" />\n";
194        }
195    }
196
197    void do_macro_action::operator()(std::string const& str) const
198    {
199        if (str == quickbook_get_date)
200        {
201            char strdate[64];
202            strftime(strdate, sizeof(strdate), "%Y-%b-%d", current_time);
203            phrase << strdate;
204        }
205        else if (str == quickbook_get_time)
206        {
207            char strdate[64];
208            strftime(strdate, sizeof(strdate), "%I:%M:%S %p", current_time);
209            phrase << strdate;
210        }
211        else
212        {
213            phrase << str;
214        }
215    }
216
217    void space::operator()(char ch) const
218    {
219        if (out)
220        {
221            detail::print_space(ch, out);
222        }
223    }
224
225    void space::operator()(iterator first, iterator const& last) const
226    {
227        if (out)
228        {
229            while (first != last)
230                detail::print_space(*first++, out);
231        }
232    }
233
234    void pre_escape_back::operator()(iterator const& first, iterator const& last) const
235    {
236        save = escape_actions.phrase.str(); // save the stream
237    }
238
239    void post_escape_back::operator()(iterator const& first, iterator const& last) const
240    {
241        std::string str = escape_actions.phrase.str();
242        escape_actions.phrase.str(save); // restore the stream
243        out << str;
244    }
245
246    void code_action::operator()(iterator const& first, iterator const& last) const
247    {
248        if (out)
249        {
250            std::string save = phrase.str();
251            phrase.str(std::string());
252
253            // preprocess the code section to remove the initial indentation
254            std::string program_(first, last);
255            detail::unindent(program_);
256
257            // $$$ fix me $$$ this is wasteful. we have to convert
258            // back to a vector<char> so we can use the same iterator type
259            // used by the rest of the system, otherwise, it is wasteful
260            // of function template instantiations
261
262            std::vector<char> program(program_.begin(), program_.end());
263            iterator first_(program.begin(), program.end());
264            iterator last_(program.end(), program.end());
265            first_.set_position(first.get_position());
266
267            // print the code with syntax coloring
268            if (source_mode == "c++")
269            {
270                parse(first_, last_, cpp_p);
271            }
272            else if (source_mode == "python")
273            {
274                parse(first_, last_, python_p);
275            }
276           
277            std::string str = temp.str();
278            temp.str(std::string());
279            phrase.str(std::string());
280            phrase << save;
281
282            out << "<programlisting>\n";
283            out << str;
284            out << "</programlisting>\n";
285        }
286    }
287
288    void inline_code_action::operator()(iterator const& first, iterator const& last) const
289    {
290        std::string save = out.str();
291        out.str(std::string());
292 
293        // print the code with syntax coloring
294        if (source_mode == "c++")
295        {
296            parse(first, last, cpp_p);
297        }
298        else if (source_mode == "python")
299        {
300            parse(first, last, python_p);
301        }
302        std::string str = temp.str();
303        temp.str(std::string());
304        out.str(std::string());
305
306        out << save;
307        out << "<code>";
308        out << str;
309        out << "</code>";
310    }
311
312    void raw_char_action::operator()(char ch) const
313    {
314        phrase << ch;
315    }
316
317    void raw_char_action::operator()(iterator const& first, iterator const& /*last*/) const
318    {
319        phrase << *first;
320    }
321
322    void plain_char_action::operator()(char ch) const
323    {
324        detail::print_char(ch, phrase);
325    }
326
327    void plain_char_action::operator()(iterator const& first, iterator const& /*last*/) const
328    {
329        detail::print_char(*first, phrase);
330    }
331
332    void image_action::operator()(iterator first, iterator const& last) const
333    {
334        fs::path const img_path(std::string(first, last));
335
336        phrase << "<inlinemediaobject>";
337
338        phrase << "<imageobject><imagedata fileref=\"";
339        while (first != last)
340            detail::print_char(*first++, phrase);
341        phrase << "\"></imagedata></imageobject>";
342
343        // Also add a textobject -- use the basename of the image file.
344        // This will mean we get "alt" attributes of the HTML img.
345        phrase << "<textobject><phrase>";
346        detail::print_string(fs::basename(img_path), phrase);
347        phrase << "</phrase></textobject>";
348
349        phrase << "</inlinemediaobject>";
350    }
351
352    void indentifier_action::operator()(iterator const& first, iterator const& last) const
353    {
354        actions.macro_id.assign(first, last);
355        actions.phrase_save = actions.phrase.str();
356        actions.phrase.str(std::string());
357    }
358
359    void macro_def_action::operator()(iterator const& first, iterator const& last) const
360    {
361        actions.macro.add(
362            actions.macro_id.begin()
363          , actions.macro_id.end()
364          , actions.phrase.str());
365        actions.phrase.str(actions.phrase_save);
366    }
367
368    void link_action::operator()(iterator first, iterator const& last) const
369    {
370        iterator save = first;
371        phrase << tag;
372        while (first != last)
373            detail::print_char(*first++, phrase);
374        phrase << "\">";
375
376        // Yes, it is safe to dereference last here. When we
377        // reach here, *last is certainly valid. We test if
378        // *last == ']'. In which case, the url is the text.
379        // Example: [@http://spirit.sourceforge.net/]
380
381        if (*last == ']')
382        {
383            first = save;
384            while (first != last)
385                detail::print_char(*first++, phrase);
386        }
387    }
388
389    void variablelist_action::operator()(iterator, iterator) const
390    {
391        if (!!actions.out)
392        {
393            actions.out << "<variablelist>\n";
394
395            actions.out << "<title>";
396            std::string::iterator first = actions.table_title.begin();
397            std::string::iterator last = actions.table_title.end();
398            while (first != last)
399                detail::print_char(*first++, actions.out);
400            actions.out << "</title>\n";
401
402            std::string str = actions.phrase.str();
403            actions.phrase.str(std::string());
404            actions.out << str;
405
406            actions.out << "</variablelist>\n";
407            actions.table_span = 0;
408            actions.table_header.clear();
409            actions.table_title.clear();
410        }
411    }
412
413    void table_action::operator()(iterator, iterator) const
414    {
415        if (!!actions.out)
416        {
417            actions.out << "<informaltable frame=\"all\">\n"
418                         << "<bridgehead renderas=\"sect4\">";
419
420            std::string::iterator first = actions.table_title.begin();
421            std::string::iterator last = actions.table_title.end();
422            if (first != last) // allow no title
423            {
424                actions.out << "<phrase role=\"table-title\">";
425                while (first != last)
426                    detail::print_char(*first++, actions.out);
427                actions.out << "</phrase>";
428            }
429            actions.out << "</bridgehead>\n"
430                         << "<tgroup cols=\"" << actions.table_span << "\">\n";
431
432            if (!actions.table_header.empty())
433            {
434                actions.out << "<thead>" << actions.table_header << "</thead>\n";
435            }
436
437            actions.out << "<tbody>\n";
438
439            std::string str = actions.phrase.str();
440            detail::convert_nbsp(str);
441            actions.phrase.str(std::string());
442            actions.out << str;
443
444            actions.out << "</tbody>\n"
445                         << "</tgroup>\n"
446                         << "</informaltable>\n";
447            actions.table_span = 0;
448            actions.table_header.clear();
449            actions.table_title.clear();
450        }
451    }
452
453    void start_row_action::operator()(char) const
454    {
455        // the first row is the header
456        if (header.empty() && !phrase.str().empty())
457        {
458            header = phrase.str();
459            phrase.str(std::string());
460        }
461
462        phrase << start_row_;
463        span = 0;
464    }
465
466    void start_row_action::operator()(iterator f, iterator) const
467    {
468        (*this)(*f);
469    }
470
471    void start_col_action::operator()(char) const
472    {
473        phrase << start_cell_; 
474        ++span;
475    }
476
477    void begin_section_action::operator()(iterator first, iterator const& last) const
478    {
479        if (section_id.empty())
480            section_id = detail::make_identifier(first, last);
481
482        if (level != 0)
483            qualified_section_id += '.';
484        else
485            BOOST_ASSERT(qualified_section_id.empty());
486        qualified_section_id += section_id;
487        ++level;
488
489        if (qbk_version_n < 103) // version 1.2 and below
490        {
491            out << "\n<section id=\"" 
492                << library_id << "." << section_id << "\">\n";
493        }
494        else // version 1.3 and above
495        {
496            out << "\n<section id=\"" << library_id
497                << "." << qualified_section_id << "\">\n";
498        }
499        std::string str;
500        str = phrase.str();
501        phrase.str(std::string());
502        out << "<title>" << str << "</title>\n";
503    }
504
505    void end_section_action::operator()(iterator const& first, iterator const& last) const
506    {
507        out << "</section>";
508
509        --level;
510        if (level < 0)
511        {
512            boost::spirit::file_position const pos = first.get_position();
513            detail::outerr(pos.file,pos.line)
514                << "Mismatched [endsect] near column " << pos.column << ".\n";
515        }
516        if (level == 0)
517        {
518            qualified_section_id.clear();
519        }
520        else
521        {
522            std::string::size_type const n = 
523                qualified_section_id.find_last_of('.');
524            BOOST_ASSERT(std::string::npos != n);
525            qualified_section_id.erase(n, std::string::npos);
526        }
527    }
528
529    fs::path path_difference(fs::path const& outdir, fs::path const& xmlfile)
530    {
531        fs::path outtmp, xmltmp;
532        fs::path::iterator out = outdir.begin(), xml = xmlfile.begin();
533        for(; out != outdir.end() && xml != xmlfile.end(); ++out, ++xml)
534        {
535            if(!fs::equivalent(outtmp /= *out, xmltmp /= *xml))
536                break;
537        }
538        std::divides<fs::path> concat;
539        out = (out == outdir.begin()) ? outdir.end() : out;
540        xmltmp = std::accumulate(out, outdir.end(), fs::path(), boost::bind(concat, _1, ".."));
541        return std::accumulate(xml, xmlfile.end(), xmltmp, concat);
542    }
543
544    void xinclude_action::operator()(iterator const& first, iterator const& last) const
545    {
546        // Given an xml file to include and the current filename, calculate the
547        // path to the XML file relative to the output directory.
548        fs::path xmlfile(std::string(first, last));
549        if (!xmlfile.is_complete())
550        {
551            fs::path infile = fs::complete(actions.filename).normalize();
552            xmlfile = (infile.branch_path() / xmlfile).normalize();
553            fs::path outdir = fs::complete(actions.outdir).normalize();
554            xmlfile = path_difference(outdir, xmlfile);
555        }
556        out << "\n<xi:include href=\"";
557        detail::print_string(detail::escape_uri(xmlfile.string()), out);
558        out << "\" />\n";
559    }
560
561    void include_action::operator()(iterator const& first, iterator const& last) const
562    {
563        fs::path filein(std::string(first, last), fs::native);
564        std::string doc_type, doc_id, doc_dirname, doc_last_revision;
565
566        // check to see if the path is complete and if not, make it relative to the current path
567        if (!filein.is_complete())
568        {
569            filein = actions.filename.branch_path() / filein;
570            filein.normalize();
571        }
572
573        // swap the filenames
574        std::swap(actions.filename, filein);
575
576        // save the doc info strings
577        actions.doc_type.swap(doc_type);
578        actions.doc_id.swap(doc_id);
579        actions.doc_dirname.swap(doc_dirname);
580        actions.doc_last_revision.swap(doc_last_revision);
581
582        // scope the macros
583        macros_type macro = actions.macro;
584
585        // if an id is specified in this include (in in [include:id foo.qbk]
586        // then use it as the doc_id.
587        if (!actions.include_doc_id.empty())
588        {
589            actions.doc_id = actions.include_doc_id;
590            actions.include_doc_id.clear();
591        }
592
593        // update the __FILENAME__ macro
594        *boost::spirit::find(actions.macro, "__FILENAME__") = actions.filename.native_file_string();
595
596        // parse the file
597        quickbook::parse(actions.filename.native_file_string().c_str(), actions, true);
598
599        // restore the values
600        std::swap(actions.filename, filein);
601
602        actions.doc_type.swap(doc_type);
603        actions.doc_id.swap(doc_id);
604        actions.doc_dirname.swap(doc_dirname);
605        actions.doc_last_revision.swap(doc_last_revision);
606
607        actions.macro = macro;
608    }
609
610    void xml_author::operator()(std::pair<std::string, std::string> const& author) const
611    {
612        out << "    <author>\n"
613            << "      <firstname>" << author.first << "</firstname>\n"
614            << "      <surname>" << author.second << "</surname>\n"
615            << "    </author>\n";
616    }
617
618    void xml_year::operator()(std::string const &year) const
619    {
620        out << "      <year>" << year << "</year>\n";
621    }
622
623    void pre(std::ostream& out, quickbook::actions& actions, bool ignore_docinfo)
624    {
625        // The doc_info in the file has been parsed. Here's what we'll do
626        // *before* anything else.
627
628        if (actions.doc_id.empty())
629            actions.doc_id = detail::make_identifier(
630                actions.doc_title.begin(),actions.doc_title.end());
631
632        if (actions.doc_dirname.empty())
633            actions.doc_dirname = actions.doc_id;
634
635        if (actions.doc_last_revision.empty())
636        {
637            // default value for last-revision is now
638
639            char strdate[64];
640            strftime(
641                strdate, sizeof(strdate),
642                (debug_mode ? 
643                    "DEBUG MODE Date: %Y/%m/%d %H:%M:%S $" :
644                    "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"),
645                current_gm_time
646            );
647            actions.doc_last_revision = strdate;
648        }
649
650        // if we're ignoring the document info, we're done.
651        if (ignore_docinfo)
652        {
653            return;
654        }
655
656        if (qbk_major_version == 0)
657        {
658            // hard code quickbook version to v1.1
659            qbk_major_version = 1;
660            qbk_minor_version = 1;
661            qbk_version_n = 101;
662            detail::outwarn(actions.filename.native_file_string(),1)
663                << "Warning: Quickbook version undefined. "
664                "Version 1.1 is assumed" << std::endl;
665        }
666        else
667        {
668            qbk_version_n = (qbk_major_version * 100) + qbk_minor_version; 
669        }
670
671        out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
672            << "<!DOCTYPE library PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n"
673            << "     \"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd\">\n"
674            << '<' << actions.doc_type << "\n"
675            << "    id=\"" << actions.doc_id << "\"\n"
676            << "    name=\"" << actions.doc_title << "\"\n"
677            << "    dirname=\"" << actions.doc_dirname << "\"\n"
678            << "    last-revision=\"" << actions.doc_last_revision << "\" \n"
679            << "    xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n"
680            << "  <" << actions.doc_type << "info>\n";
681
682        for_each(
683            actions.doc_authors.begin()
684          , actions.doc_authors.end()
685          , xml_author(out));
686
687        if (!actions.doc_copyright_holder.empty())
688        {
689            out << "\n" << "    <copyright>\n";
690
691            for_each(
692                actions.doc_copyright_years.begin()
693              , actions.doc_copyright_years.end()
694              , xml_year(out));
695
696            out << "      <holder>" << actions.doc_copyright_holder << "</holder>\n"
697                << "    </copyright>\n"
698                << "\n"
699            ;
700        }
701
702        if (qbk_version_n < 103)
703        {
704            // version < 1.3 compatibility
705            actions.doc_license = actions.doc_license_1_1;
706            actions.doc_purpose = actions.doc_purpose_1_1;
707        }
708
709        if (!actions.doc_license.empty())
710        {
711            out << "    <legalnotice>\n"
712                << "      <para>\n"
713                << "        " << actions.doc_license << "\n"
714                << "      </para>\n"
715                << "    </legalnotice>\n"
716                << "\n"
717            ;
718        }
719
720        if (!actions.doc_purpose.empty())
721        {
722            out << "    <" << actions.doc_type << "purpose>\n"
723                << "      " << actions.doc_purpose
724                << "    </" << actions.doc_type << "purpose>\n"
725                << "\n"
726            ;
727        }
728
729        if (!actions.doc_category.empty())
730        {
731            out << "    <" << actions.doc_type << "category name=\"category:"
732                << actions.doc_category
733                << "\"></" << actions.doc_type << "category>\n"
734                << "\n"
735            ;
736        }
737
738        out << "  </" << actions.doc_type << "info>\n"
739            << "\n"
740        ;
741
742        if (!actions.doc_title.empty())
743        {
744            out << "  <title>" << actions.doc_title;
745            if (!actions.doc_version.empty())
746                out << ' ' << actions.doc_version;
747            out << "</title>\n\n\n";
748        }
749    }
750
751    void post(std::ostream& out, quickbook::actions& actions, bool ignore_docinfo)
752    {
753        // if we're ignoring the document info, do nothing.
754        if (ignore_docinfo)
755        {
756            return;
757        }
758
759        // We've finished generating our output. Here's what we'll do
760        // *after* everything else.
761        out << "\n</" << actions.doc_type << ">\n\n";
762    }
763
764    void phrase_to_string_action::operator()(iterator const& first, iterator const& last) const
765    {
766        out = phrase.str();
767        phrase.str(std::string());
768    }
769
770    actions::actions(char const* filein_, fs::path const& outdir_, std::ostream &out_)
771        : filename(fs::complete(fs::path(filein_, fs::native)))
772        , outdir(outdir_)
773        , out(out_)
774        , extract_doc_license(doc_license, phrase)
775        , extract_doc_purpose(doc_purpose, phrase)
776        , table_span(0)
777        , table_header()
778        , source_mode("c++")
779        , code(out, phrase, temp, source_mode, macro, *this)
780        , code_block(phrase, phrase, temp, source_mode, macro, *this)
781        , inline_code(phrase, temp, source_mode, macro, *this)
782        , paragraph(out, phrase, paragraph_pre, paragraph_post)
783        , h1(out, phrase, doc_id, section_id, qualified_section_id, h1_pre, h1_post)
784        , h2(out, phrase, doc_id, section_id, qualified_section_id, h2_pre, h2_post)
785        , h3(out, phrase, doc_id, section_id, qualified_section_id, h3_pre, h3_post)
786        , h4(out, phrase, doc_id, section_id, qualified_section_id, h4_pre, h4_post)
787        , h5(out, phrase, doc_id, section_id, qualified_section_id, h5_pre, h5_post)
788        , h6(out, phrase, doc_id, section_id, qualified_section_id, h6_pre, h6_post)
789        , hr(out, hr_)
790        , blurb(out, phrase, blurb_pre, blurb_post)
791        , blockquote(out, phrase, blockquote_pre, blockquote_post)
792        , preformatted(out, phrase, preformatted_pre, preformatted_post)
793        , warning(out, phrase, warning_pre, warning_post)
794        , caution(out, phrase, caution_pre, caution_post)
795        , important(out, phrase, important_pre, important_post)
796        , note(out, phrase, note_pre, note_post)
797        , tip(out, phrase, tip_pre, tip_post)
798        , plain_char(phrase)
799        , raw_char(phrase)
800        , image(phrase)
801        , list_buffer()
802        , list_marks()
803        , indent(-1)
804        , list(out, list_buffer, indent, list_marks)
805        , list_format(list_buffer, indent, list_marks)
806        , list_item(list_buffer, phrase, list_item_pre, list_item_post)
807        , funcref_pre(phrase, funcref_pre_)
808        , funcref_post(phrase, funcref_post_)
809        , classref_pre(phrase, classref_pre_)
810        , classref_post(phrase, classref_post_)
811        , memberref_pre(phrase, memberref_pre_)
812        , memberref_post(phrase, memberref_post_)
813        , enumref_pre(phrase, enumref_pre_)
814        , enumref_post(phrase, enumref_post_)
815        , headerref_pre(phrase, headerref_pre_)
816        , headerref_post(phrase, headerref_post_)
817        , bold_pre(phrase, bold_pre_)
818        , bold_post(phrase, bold_post_)
819        , italic_pre(phrase, italic_pre_)
820        , italic_post(phrase, italic_post_)
821        , underline_pre(phrase, underline_pre_)
822        , underline_post(phrase, underline_post_)
823        , teletype_pre(phrase, teletype_pre_)
824        , teletype_post(phrase, teletype_post_)
825        , strikethrough_pre(phrase, strikethrough_pre_)
826        , strikethrough_post(phrase, strikethrough_post_)
827        , quote_pre(phrase, quote_pre_)
828        , quote_post(phrase, quote_post_)
829        , replaceable_pre(phrase, replaceable_pre_)
830        , replaceable_post(phrase, replaceable_post_)
831        , footnote_pre(phrase, footnote_pre_)
832        , footnote_post(phrase, footnote_post_)
833        , simple_bold(phrase, bold_pre_, bold_post_)
834        , simple_italic(phrase, italic_pre_, italic_post_)
835        , simple_underline(phrase, underline_pre_, underline_post_)
836        , simple_teletype(phrase, teletype_pre_, teletype_post_)
837        , simple_strikethrough(phrase, strikethrough_pre_, strikethrough_post_)
838        , variablelist(*this)
839        , start_varlistentry(phrase, start_varlistentry_)
840        , end_varlistentry(phrase, end_varlistentry_)
841        , start_varlistterm(phrase, start_varlistterm_)
842        , end_varlistterm(phrase, end_varlistterm_)
843        , start_varlistitem(phrase, start_varlistitem_)
844        , end_varlistitem(phrase, end_varlistitem_)
845        , break_(phrase, break_mark)
846        , identifier(*this)
847        , macro_def(*this)
848        , do_macro(phrase)
849        , url_pre(phrase, url_pre_)
850        , url_post(phrase, url_post_)
851        , link_pre(phrase, link_pre_)
852        , link_post(phrase, link_post_)
853        , table(*this)
854        , start_row(phrase, table_span, table_header)
855        , end_row(phrase, end_row_)
856        , start_cell(phrase, table_span)
857        , end_cell(phrase, end_cell_)
858        , anchor(out)
859        , begin_section(out, phrase, doc_id, section_id, level, qualified_section_id)
860        , end_section(out, level, qualified_section_id)
861        , xinclude(out, *this)
862        , include(*this)
863        , level(0)
864        , escape_pre(phrase, escape_pre_)
865        , escape_post(phrase, escape_post_)
866    {
867        // turn off __FILENAME__ macro on debug mode = true
868        std::string filename_str = debug_mode ? 
869            std::string("NO_FILENAME_MACRO_GENERATED_IN_DEBUG_MODE") : 
870            filename.native_file_string();
871
872        // add the predefined macros
873        macro.add
874            ("__DATE__", std::string(quickbook_get_date))
875            ("__TIME__", std::string(quickbook_get_time))
876            ("__FILENAME__", filename_str)
877        ;
878    }
879}
Note: See TracBrowser for help on using the repository browser.