Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/quickbook/detail/actions.hpp @ 12

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

added boost

  • Property svn:executable set to *
File size: 31.5 KB
RevLine 
[12]1/*=============================================================================
2    Copyright (c) 2002 2004 Joel de Guzman
3    Copyright (c) 2004 Eric Niebler
4    http://spirit.sourceforge.net/
5
6    Use, modification and distribution is subject to the Boost Software
7    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8    http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10#if !defined(BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP)
11#define BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP
12
13#include <time.h>
14#include <string>
15#include <vector>
16#include <stack>
17#include <algorithm>
18#include <sstream>
19#include <boost/spirit/iterator/position_iterator.hpp>
20#include "../syntax_highlight.hpp"
21#include "utils.hpp"
22
23namespace quickbook
24{
25    struct error_action
26    {
27        // Prints an error message to std::cerr
28
29        template <typename Iterator>
30        void operator()(Iterator const& first, Iterator const& /*last*/) const
31        {
32            boost::spirit::file_position const pos = first.get_position();
33            std::cerr
34                << "Syntax Error at \"" << pos.file
35                << "\" line " << pos.line
36                << ", column " << pos.column << ".\n";
37        }
38    };
39
40    struct phrase_action
41    {
42        //  Handles paragraph, h1, h2, h3, h4, h5, h6,
43        //  blurb, blockquote, preformatted, list_item,
44        //  unordered_list, ordered_list
45
46        phrase_action(
47            std::ostream&       out,
48            std::stringstream&  phrase,
49            std::string&        section_id,
50            std::string const&  pre,
51            std::string const&  post,
52            bool                anchor = false)
53        : out(out)
54        , phrase(phrase)
55        , section_id(section_id)
56        , pre(pre)
57        , post(post)
58        , anchor(anchor) {}
59
60        template <typename Iterator>
61        void operator()(Iterator const& first, Iterator const& last) const
62        {
63            if (out)
64            {
65                std::string  str = phrase.str();
66                if (anchor)
67                    out << "<anchor id=\""
68                        << section_id << '.'
69                        << detail::make_identifier(str.begin(), str.end())
70                        << "\" />";
71                phrase.str(std::string());
72                out << pre << str << post;
73            }
74        }
75
76        std::ostream&       out;
77        std::stringstream&  phrase;
78        std::string&        section_id;
79        std::string         pre;
80        std::string         post;
81        bool                anchor;
82    };
83
84    struct simple_phrase_action
85    {
86        //  Handles simple text formats
87
88        simple_phrase_action(
89            std::ostream&       out,
90            std::string const&  pre,
91            std::string const&  post)
92        : out(out)
93        , pre(pre)
94        , post(post) {}
95
96        template <typename Iterator>
97        void operator()(Iterator first, Iterator const& last) const
98        {
99            if (out)
100            {
101                out << pre;
102                while (first != last)
103                    detail::print_char(*first++, out);
104                out << post;
105            }
106        }
107
108        std::ostream&   out;
109        std::string     pre;
110        std::string     post;
111    };
112
113    struct list_action
114    {
115        //  Handles lists
116
117        typedef std::pair<char, int> mark_type;
118        list_action(
119            std::ostream& out
120          , std::stringstream& list_buffer
121          , int& indent
122          , std::stack<mark_type>& list_marks)
123        : out(out)
124        , list_buffer(list_buffer)
125        , indent(indent)
126        , list_marks(list_marks) {}
127
128        template <typename Iterator>
129        void operator()(Iterator const& first, Iterator const& last) const
130        {
131            assert(!list_marks.empty()); // there must be at least one item in the stack
132            std::string  str = list_buffer.str();
133            list_buffer.str(std::string());
134            out << str;
135
136            while (!list_marks.empty())
137            {
138                char mark = list_marks.top().first;
139                list_marks.pop();
140                out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
141                if (list_marks.size() >= 1)
142                    out << std::string("\n</listitem>");
143            }
144
145            indent = -1; // reset
146        }
147
148        std::ostream& out;
149        std::stringstream& list_buffer;
150        int& indent;
151        std::stack<mark_type>& list_marks;
152    };
153
154    struct list_format_action
155    {
156        //  Handles list formatting and hierarchy
157
158        typedef std::pair<char, int> mark_type;
159        list_format_action(
160            std::stringstream& out
161          , int& indent
162          , std::stack<mark_type>& list_marks)
163        : out(out)
164        , indent(indent)
165        , list_marks(list_marks) {}
166
167        template <typename Iterator>
168        void operator()(Iterator first, Iterator const& last) const
169        {
170            int new_indent = 0;
171            while (first != last && (*first == ' ' || *first == '\t'))
172            {
173                char mark = *first++;
174                if (mark == ' ')
175                {
176                    ++new_indent;
177                }
178                else // must be a tab
179                {
180                    assert(mark == '\t');
181                    // hardcoded tab to 4 for now
182                    new_indent = ((new_indent + 4) / 4) * 4;
183                }
184            }
185
186            char mark = *first;
187            assert(mark == '#' || mark == '*'); // expecting a mark
188
189            if (indent == -1) // the very start
190            {
191                assert(new_indent == 0);
192            }
193
194            if (new_indent > indent)
195            {
196                //~ char parent_mark = 0;
197                //~ if (list_marks.size() >= 1)
198                    //~ parent_mark = list_marks.top().first;
199                indent = new_indent;
200                list_marks.push(mark_type(mark, indent));
201                if (list_marks.size() > 1)
202                {
203                    // Make this new list a child of the previous list.
204                    // The previous listelem has already ended so we erase
205                    // </listitem> to accomodate this sub-list. We'll close
206                    // the listelem later.
207
208                    std::string str = out.str();
209                    std::string::size_type pos = str.rfind("\n</listitem>");
210                    assert(pos <= str.size());
211                    str.erase(str.begin()+pos, str.end());
212                    out.str(std::string());
213                    out << str;
214                    //~ out << std::string((parent_mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
215                }
216                //~ else
217                //~ {
218                    out << std::string((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
219                //~ }
220            }
221
222            else if (new_indent < indent)
223            {
224                assert(!list_marks.empty());
225                indent = new_indent;
226                //~ list_marks.pop();
227                //~ out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
228                //~ if (list_marks.size() >= 1)
229                    //~ out << std::string("\n</listitem>");
230
231                while (!list_marks.empty() && (indent < list_marks.top().second))
232                {
233                    char mark = list_marks.top().first;
234                    list_marks.pop();
235                    out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
236                    if (list_marks.size() >= 1)
237                        out << std::string("\n</listitem>");
238                }
239            }
240
241            if (mark != list_marks.top().first) // new_indent == indent
242            {
243                boost::spirit::file_position const pos = first.get_position();
244                std::cerr
245                    << "Illegal change of list style at \"" << pos.file
246                    << "\" line " << pos.line
247                    << ", column " << pos.column << ".\n";
248                std::cerr << "Ignoring change of list style" << std::endl;
249            }
250        }
251
252        std::stringstream& out;
253        int& indent;
254        std::stack<mark_type>& list_marks;
255    };
256
257    struct span
258    {
259        // Decorates c++ code fragments
260
261        span(char const* name, std::ostream& out)
262        : name(name), out(out) {}
263
264        template <typename Iterator>
265        void operator()(Iterator first, Iterator last) const
266        {
267            if (out)
268            {
269                out << "<phrase role=\"" << name << "\">";
270                while (first != last)
271                    detail::print_char(*first++, out);
272                out << "</phrase>";
273            }
274        }
275
276        char const* name;
277        std::ostream& out;
278    };
279
280    struct unexpected_char
281    {
282        // Handles unexpected chars in c++ syntax
283
284        unexpected_char(std::ostream& out)
285        : out(out) {}
286
287        template <typename Char>
288        void operator()(Char) const
289        {
290            if (out)
291                out << '#'; // print out an unexpected character
292        }
293
294        std::ostream& out;
295    };
296
297    struct anchor_action
298    {
299        // Handles anchors
300
301        anchor_action(std::ostream& out)
302            : out(out) {}
303
304        template <typename Iterator>
305        void operator()(Iterator first, Iterator last) const
306        {
307            if (out)
308            {
309                out << "<anchor id=\"";
310                while (first != last)
311                    detail::print_char(*first++, out);
312                out << "\" />\n";
313            }
314        }
315
316        std::ostream& out;
317    };
318
319    char const* quickbook_get_date = "__quickbook_get_date__";
320    char const* quickbook_get_time = "__quickbook_get_time__";
321
322    struct do_macro_action
323    {
324        // Handles macro substitutions
325
326        do_macro_action(std::ostream& phrase)
327        : phrase(phrase) {}
328
329        void operator()(std::string const& str) const
330        {
331            if (str == quickbook_get_date)
332            {
333                char strdate[ 64 ];
334                time_t t = time(0);
335                strftime( strdate, sizeof(strdate), "%Y-%b-%d", localtime(&t) );
336                phrase << strdate;
337            }
338            else if (str == quickbook_get_time)
339            {
340                char strdate[ 64 ];
341                time_t t = time(0);
342                strftime( strdate, sizeof(strdate), "%I:%M:%S %p", localtime(&t) );
343                phrase << strdate;
344            }
345            else
346            {
347                phrase << str;
348            }
349        }
350
351        std::ostream& phrase;
352    };
353
354    struct space
355    {
356        // Prints a space
357
358        space(std::ostream& out)
359        : out(out) {}
360
361        template <typename Iterator>
362        void operator()(Iterator first, Iterator last) const
363        {
364            if (out)
365            {
366                while (first != last)
367                    detail::print_space(*first++, out);
368            }
369        }
370
371        template <typename Char>
372        void operator()(Char ch) const
373        {
374            if (out)
375            {
376                detail::print_space(ch, out);
377            }
378        }
379
380        std::ostream& out;
381    };
382
383    struct code_action
384    {
385        // Does the actual syntax highlighing of code
386
387        code_action(std::ostream& out,
388                    std::string const & source_mode,
389                    symbols<std::string> const& macro)
390        : out(out)
391        , source_mode(source_mode)
392        , cpp_p(out, macro, do_macro_action(out))
393        , python_p(out, macro, do_macro_action(out))
394        {
395        }
396
397        template <typename Iterator>
398        void operator()(Iterator first, Iterator last) const
399        {
400            if (out)
401            {
402                // preprocess the code section to remove the initial indentation
403                std::string program(first, last);
404                detail::unindent(program);
405               
406                out << "<programlisting>\n"
407                    << "<literal>\n";
408
409                // print the code with syntax coloring
410                if (source_mode == "c++")
411                {
412                    parse(program.begin(), program.end(), cpp_p);
413                }
414                else if (source_mode == "python")
415                {
416                    parse(program.begin(), program.end(), python_p);
417                }
418               
419                out << "</literal>\n"
420                    << "</programlisting>\n";
421            }
422        }
423
424        std::ostream& out;
425        std::string const& source_mode;
426       
427        cpp_highlight<
428            span
429          , space
430          , symbols<std::string>
431          , do_macro_action
432          , unexpected_char
433          , std::ostream>
434        cpp_p;
435       
436        python_highlight<
437            span
438          , space
439          , symbols<std::string>
440          , do_macro_action
441          , unexpected_char
442          , std::ostream>
443        python_p;
444    };
445
446    struct inline_code_action
447    {
448        // Does the actual syntax highlighing of code inlined in text
449
450        inline_code_action(std::ostream& out,
451                           std::string const& source_mode,
452                           symbols<std::string> const& macro)
453        : out(out)
454        , source_mode(source_mode)
455        , cpp_p(out, macro, do_macro_action(out))
456        , python_p(out, macro, do_macro_action(out))
457        {}
458
459        template <typename Iterator>
460        void operator()(Iterator first, Iterator last) const
461        {
462            if (out)
463            {
464                out << "<code>";
465
466                // print the code with syntax coloring
467                if (source_mode == "c++")
468                {
469                    parse(first, last, cpp_p);
470                }
471                else if (source_mode == "python")
472                {
473                    parse(first, last, python_p);
474                }
475               
476                out << "</code>";
477            }
478        }
479
480        std::ostream& out;
481        std::string const& source_mode;
482       
483        cpp_highlight<
484            span
485          , space
486          , symbols<std::string>
487          , do_macro_action
488          , unexpected_char
489          , std::ostream>
490        cpp_p;
491       
492        python_highlight<
493            span
494          , space
495          , symbols<std::string>
496          , do_macro_action
497          , unexpected_char
498          , std::ostream>
499        python_p;
500    };
501
502    namespace
503    {
504        // Some markups
505
506        const char* paragraph_pre   = "<para>\n";
507        const char* paragraph_post  = "</para>\n";
508        const char* h1_pre          = "<bridgehead renderas=\"sect1\">";
509        const char* h1_post         = "</bridgehead>";
510        const char* h2_pre          = "<bridgehead renderas=\"sect2\">";
511        const char* h2_post         = "</bridgehead>";
512        const char* h3_pre          = "<bridgehead renderas=\"sect3\">";
513        const char* h3_post         = "</bridgehead>";
514        const char* h4_pre          = "<bridgehead renderas=\"sect4\">";
515        const char* h4_post         = "</bridgehead>";
516        const char* h5_pre          = "<bridgehead renderas=\"sect5\">";
517        const char* h5_post         = "</bridgehead>";
518        const char* h6_pre          = "<bridgehead renderas=\"sect6\">";
519        const char* h6_post         = "</bridgehead>";
520        const char* hr_             = "<para/>";
521
522        const char* blurb_pre =
523            "<informaltable frame=\"all\">\n"
524            "<?dbhtml table-width=\"74%\" ?>\n"
525            "<tgroup cols=\"1\">\n"
526            "<tbody>\n"
527            "<row>\n"
528            "<entry role=\"blurb\">\n"
529            ;
530
531        const char* blurb_post =
532            "</entry>\n"
533            "</row>\n"
534            "</tbody>\n"
535            "</tgroup>\n"
536            "</informaltable>\n"
537            ;
538
539        const char* blockquote_pre      = "<blockquote><para>";
540        const char* blockquote_post     = "</para></blockquote>";
541        const char* preformatted_pre    = "<programlisting><literal>";
542        const char* preformatted_post   = "</literal></programlisting>";
543        const char* list_item_pre       = "<listitem>\n";
544        const char* list_item_post      = "\n</listitem>";
545        const char* bold_pre_           = "<emphasis role=\"bold\">";
546        const char* bold_post_          = "</emphasis>";
547        const char* italic_pre_         = "<emphasis>";
548        const char* italic_post_        = "</emphasis>";
549        const char* underline_pre_      = "<emphasis role=\"underline\">";
550        const char* underline_post_     = "</emphasis>";
551        const char* teletype_pre_       = "<literal>";
552        const char* teletype_post_      = "</literal>";
553        const char* break_mark          = "<sbr/>\n";
554        const char* url_pre_            = "<ulink url=\"";
555        const char* url_post_           = "</ulink>";
556        const char* link_pre_           = "<link linkend=\"";
557        const char* link_post_          = "</link>";
558        const char* start_varlistentry_ = "<varlistentry>";
559        const char* end_varlistentry_   = "</varlistentry>\n";
560        const char* start_varlistterm_  = "<term>";
561        const char* end_varlistterm_    = "</term>";
562        const char* start_varlistitem_  = "<listitem>";
563        const char* end_varlistitem_    = "</listitem>";
564        const char* start_header_       = "<thead>";
565        const char* end_header_         = "</thead>\n";
566        const char* start_row_          = "<row>";
567        const char* end_row_            = "</row>\n";
568        const char* start_cell_         = "<entry>";
569        const char* end_cell_           = "</entry>";
570        const char* funcref_pre_        = "<functionname alt=\"";
571        const char* funcref_post_       = "</functionname>";
572        const char* classref_pre_       = "<classname alt=\"";
573        const char* classref_post_      = "</classname>";
574        const char* memberref_pre_      = "<methodname alt=\"";
575        const char* memberref_post_     = "</methodname>";
576        const char* enumref_pre_        = "<enumname alt=\"";
577        const char* enumref_post_       = "</enumname>";
578        const char* headerref_pre_      = "<headername alt=\"";
579        const char* headerref_post_     = "</headername>";
580    }
581
582    struct raw_char_action
583    {
584        // Prints a single raw (unprocessed) char.
585        // Allows '<', '>'... etc.
586
587        raw_char_action(std::ostream& phrase)
588        : phrase(phrase) {}
589
590        template <typename Char>
591        void operator()(Char const& ch) const
592        {
593            phrase << ch;
594        }
595
596        template <typename Iterator>
597        void operator()(Iterator const& first, Iterator const& /*last*/) const
598        {
599            phrase << *first;
600        }
601
602        std::ostream& phrase;
603    };
604
605    struct plain_char_action
606    {
607        // Prints a single plain char.
608        // Converts '<' to "&lt;"... etc See utils.hpp
609
610        plain_char_action(std::ostream& phrase)
611        : phrase(phrase) {}
612
613        template <typename Char>
614        void operator()(Char const& ch) const
615        {
616            detail::print_char(ch, phrase);
617        }
618
619        template <typename Iterator>
620        void operator()(Iterator const& first, Iterator const& /*last*/) const
621        {
622            detail::print_char(*first, phrase);
623        }
624
625        std::ostream& phrase;
626    };
627
628    struct image_action
629    {
630        // Handles inline images
631
632        image_action(std::ostream& phrase)
633        : phrase(phrase) {}
634
635        template <typename Iterator>
636        void operator()(Iterator first, Iterator last) const
637        {
638            phrase << "<inlinemediaobject><imageobject><imagedata fileref=\"";
639            while (first != last)
640                detail::print_char(*first++, phrase);
641            phrase << "\"></imagedata></imageobject></inlinemediaobject>";
642        }
643
644        std::ostream& phrase;
645    };
646
647    struct markup_action
648    {
649        // A generic markup action
650
651        markup_action(std::ostream& phrase, std::string const& str)
652        : phrase(phrase), str(str) {}
653
654        template <typename T>
655        void operator()(T const&) const
656        {
657            phrase << str;
658        }
659
660        template <typename T>
661        void operator()(T const&, T const&) const
662        {
663            phrase << str;
664        }
665
666        std::ostream& phrase;
667        std::string str;
668    };
669
670    template <typename Actions>
671    struct indentifier_action
672    {
673        // Handles macro identifiers
674
675        indentifier_action(Actions& actions)
676        : actions(actions) {}
677
678        template <typename Iterator>
679        void operator()(Iterator const& first, Iterator const& last) const
680        {
681            actions.macro_id.assign(first, last);
682            actions.phrase_save = actions.phrase.str();
683            actions.phrase.str(std::string());
684        }
685
686        Actions& actions;
687    };
688
689    template <typename Actions>
690    struct macro_def_action
691    {
692        // Handles macro definitions
693
694        macro_def_action(Actions& actions)
695        : actions(actions) {}
696
697        template <typename Iterator>
698        void operator()(Iterator const& first, Iterator const& last) const
699        {
700            actions.macro.add(
701                actions.macro_id.begin()
702              , actions.macro_id.end()
703              , actions.phrase.str());
704            actions.phrase.str(actions.phrase_save);
705        }
706
707        Actions& actions;
708    };
709
710    struct link_action
711    {
712        // Handles links (URL, XML refentry, function, class, member)
713
714        link_action(std::ostream& phrase, char const* tag)
715        : phrase(phrase), tag(tag) {}
716
717        template <typename Iterator>
718        void operator()(Iterator first, Iterator last) const
719        {
720            Iterator save = first;
721            phrase << tag;
722            while (first != last)
723                detail::print_char(*first++, phrase);
724            phrase << "\">";
725
726            // Yes, it is safe to dereference last here. When we
727            // reach here, *last is certainly valid. We test if
728            // *last == ']'. In which case, the url is the text.
729            // Example: [@http://spirit.sourceforge.net/]
730
731            if (*last == ']')
732            {
733                first = save;
734                while (first != last)
735                    detail::print_char(*first++, phrase);
736            }
737        }
738
739        std::ostream& phrase;
740        char const* tag;
741    };
742
743    template <typename Actions>
744    struct variablelist_action
745    {
746        // Handles variable lists
747
748        variablelist_action(Actions& actions)
749        : actions(actions) {}
750
751        template <typename Iterator>
752        void operator()(Iterator, Iterator) const
753        {
754            if (!!actions.out)
755            {
756                actions.out << "<variablelist>\n";
757
758                actions.out << "<title>";
759                std::string::iterator first = actions.table_title.begin();
760                std::string::iterator last = actions.table_title.end();
761                while (first != last)
762                    detail::print_char(*first++, actions.out);
763                actions.out << "</title>\n";
764
765                std::string str = actions.phrase.str();
766                actions.phrase.str(std::string());
767                actions.out << str;
768
769                actions.out << "</variablelist>\n";
770                actions.table_span = 0;
771                actions.table_header.clear();
772                actions.table_title.clear();
773            }
774        }
775
776        Actions& actions;
777    };
778
779    template <typename Actions>
780    struct table_action
781    {
782        // Handles tables
783
784        table_action(Actions& actions)
785        : actions(actions) {}
786
787        template <typename Iterator>
788        void operator()(Iterator, Iterator) const
789        {
790            if (!!actions.out)
791            {
792                actions.out << "<informaltable frame=\"all\">\n"
793                             << "<bridgehead renderas=\"sect4\">";
794
795                actions.out << "<phrase role=\"table-title\">";
796                std::string::iterator first = actions.table_title.begin();
797                std::string::iterator last = actions.table_title.end();
798                while (first != last)
799                    detail::print_char(*first++, actions.out);
800                actions.out << "</phrase>";
801
802                actions.out << "</bridgehead>\n"
803                             << "<tgroup cols=\"" << actions.table_span << "\">\n";
804
805                if(!actions.table_header.empty())
806                {
807                    actions.out << "<thead>" << actions.table_header << "</thead>\n";
808                }
809
810                actions.out << "<tbody>\n";
811
812                std::string str = actions.phrase.str();
813                actions.phrase.str(std::string());
814                actions.out << str;
815
816                actions.out << "</tbody>\n"
817                             << "</tgroup>\n"
818                             << "</informaltable>\n";
819                actions.table_span = 0;
820                actions.table_header.clear();
821                actions.table_title.clear();
822            }
823        }
824
825        Actions& actions;
826    };
827
828    struct start_row_action
829    {
830        // Handles table rows
831
832        start_row_action(std::stringstream& phrase, unsigned& span, std::string& header)
833            : phrase(phrase), span(span), header(header) {}
834
835        template <typename T>
836        void operator()(T const&) const
837        {
838            // the first row is the header
839            if(header.empty() && !phrase.str().empty())
840            {
841                header = phrase.str();
842                phrase.str(std::string());
843            }
844
845            phrase << start_row_;
846            span = 0;
847        }
848
849        template <typename T>
850        void operator()(T const& t,T const&) const
851        {
852            (*this)(t);
853        }
854
855        std::stringstream& phrase;
856        unsigned& span;
857        std::string& header;
858    };
859
860    struct start_col_action
861    {
862        // Handles table columns
863
864        start_col_action(std::ostream& phrase, unsigned& span)
865        : phrase(phrase), span(span) {}
866
867        template <typename T>
868        void operator()(T const&) const
869        {
870            phrase << start_cell_; ++span;
871        }
872
873        std::ostream& phrase;
874        unsigned& span;
875    };
876
877    struct begin_section_action
878    {
879        // Handles begin page
880
881        begin_section_action(
882            std::ostream& phrase
883          , std::string& library_id
884          , std::string& section_id)
885        : phrase(phrase)
886        , library_id(library_id)
887        , section_id(section_id) {}
888
889        template <typename Iterator>
890        void operator()(Iterator first, Iterator last) const
891        {
892            if (section_id.empty())
893                section_id = detail::make_identifier(first, last);
894            phrase << "\n<section id=\"" << library_id << "." << section_id << "\">\n";
895            phrase << "<title>";
896            while (first != last)
897                detail::print_char(*first++, phrase);
898            phrase << "</title>\n";
899        }
900
901        std::ostream& phrase;
902        std::string& library_id;
903        std::string& section_id;
904    };
905
906    struct xinclude_action
907    {
908        // Handles XML includes
909
910        xinclude_action(std::ostream& out_)
911            : out(out_) {}
912
913        template <typename Iterator>
914        void operator()(Iterator first, Iterator last) const
915        {
916            out << "\n<xi:include href=\"";
917            while (first != last)
918                detail::print_char(*first++, out);
919            out << "\" />\n";
920        }
921
922        std::ostream& out;
923    };
924
925    struct xml_author
926    {
927        // Handles xml author
928
929        xml_author(std::ostream& out)
930        : out(out) {}
931
932        void operator()(std::pair<std::string, std::string> const& author) const
933        {
934            out << "    <author>\n"
935                << "      <firstname>" << author.first << "</firstname>\n"
936                << "      <surname>" << author.second << "</surname>\n"
937                << "    </author>\n";
938        }
939
940        std::ostream& out;
941    };
942
943    struct xml_year
944    {
945        // Handles xml year
946
947        xml_year(std::ostream& out)
948            : out(out) {}
949
950        void operator()(std::string const &year) const
951        {
952            out << "      <year>" << year << "</year>\n";
953        }
954
955        std::ostream& out;
956    };
957
958    template <typename Actions>
959    void pre(std::ostream& out, Actions& actions)
960    {
961        // The quickbook file has been parsed. Now, it's time to
962        // generate the output. Here's what we'll do *before* anything else.
963
964        if (actions.doc_id.empty())
965            actions.doc_id = detail::make_identifier(
966                actions.doc_title.begin(),actions.doc_title.end());
967
968        if (actions.doc_dirname.empty())
969            actions.doc_dirname = actions.doc_id;
970
971        if (actions.doc_last_revision.empty())
972        {
973            // default value for last-revision is now
974
975            char strdate[ 30 ];
976            time_t t = time(0);
977            strftime(
978                strdate, sizeof(strdate),
979                "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $",
980                gmtime(&t)
981            );
982
983            actions.doc_last_revision = strdate;
984        }
985
986        out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
987            << "<!DOCTYPE library PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n"
988            << "     \"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd\">\n"
989            << '<' << actions.doc_type << "\n"
990            << "    id=\"" << actions.doc_id << "\"\n"
991            << "    name=\"" << actions.doc_title << "\"\n"
992            << "    dirname=\"" << actions.doc_dirname << "\"\n"
993            << "    last-revision=\"" << actions.doc_last_revision << "\" \n"
994            << "    xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n"
995            << "  <" << actions.doc_type << "info>\n";
996
997        for_each(
998            actions.doc_authors.begin()
999          , actions.doc_authors.end()
1000          , xml_author(out));
1001
1002        if (!actions.doc_copyright_holder.empty())
1003        {
1004            out << "\n" << "    <copyright>\n";
1005
1006            for_each(
1007                actions.doc_copyright_years.begin()
1008              , actions.doc_copyright_years.end()
1009              , xml_year(out));
1010
1011            out << "      <holder>" << actions.doc_copyright_holder << "</holder>\n"
1012                << "    </copyright>\n"
1013                << "\n"
1014            ;
1015        }
1016
1017        if (!actions.doc_license.empty())
1018        {
1019            out << "    <legalnotice>\n"
1020                << "      <para>\n"
1021                << "        " << actions.doc_license << "\n"
1022                << "      </para>\n"
1023                << "    </legalnotice>\n"
1024                << "\n"
1025            ;
1026        }
1027
1028        if (!actions.doc_purpose.empty())
1029        {
1030            out << "    <" << actions.doc_type << "purpose>\n"
1031                << "      " << actions.doc_purpose
1032                << "    </" << actions.doc_type << "purpose>\n"
1033                << "\n"
1034            ;
1035        }
1036
1037        if (!actions.doc_purpose.empty())
1038        {
1039            out << "    <" << actions.doc_type << "category name=\"category:"
1040                << actions.doc_category
1041                << "\"></" << actions.doc_type << "category>\n"
1042                << "\n"
1043            ;
1044        }
1045
1046        out << "  </" << actions.doc_type << "info>\n"
1047            << "\n"
1048        ;
1049
1050        if (!actions.doc_title.empty())
1051        {
1052            out << "  <title>" << actions.doc_title;
1053            if (!actions.doc_version.empty())
1054                out << ' ' << actions.doc_version;
1055            out << "</title>\n\n\n";
1056        }
1057    }
1058
1059    template <typename Actions>
1060    void post(std::ostream& out, Actions& actions)
1061    {
1062        // We've finished generating our output. Here's what we'll do
1063        // *after* everything else.
1064        out << "\n</" << actions.doc_type << ">\n\n";
1065    }
1066}
1067
1068#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
1069
Note: See TracBrowser for help on using the repository browser.