491aa223b1b252b0ec634a30f2d1447295b72530
[robodoc.git] / Source / generator.c
1 // vi: spell ff=unix
2 /*
3 Copyright (C) 1994-2007  Frans Slothouber, Jacco van Weert, Petteri Kettunen,
4 Bernd Koesling, Thomas Aglassinger, Anthon Pang, Stefan Kost, David Druffner,
5 Sasha Vasko, Kai Hofmann, Thierry Pierron, Friedrich Haase, and Gergely Budai.
6
7 This file is part of ROBODoc
8
9 ROBODoc is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 */
23
24
25
26 /****h* ROBODoc/Generator
27  * FUNCTION
28  *   This contains routines to generate the documentation from the
29  *   headers collected from the source code.   It contains
30  *   functionality common for all document types (HTML, RTF etc).
31  *   The specifics are handled in the modules for each of the several
32  *   document types.
33  *
34  *   The behaviour of many of the functions in this module are
35  *   modified by the global output_mode.
36  *
37  *   The general call sequence is as follows:
38  *     RB_Generate_Documentation
39  *     +> RB_Generate_SingleDoc
40  *        +> RB_Generate_Part
41  *           +> Generate_Header
42  *                 +> Generate_Item_Line
43  *                    +> Generate_Char
44  * BUGS
45  *   o Confusing use of doctype and output mode.
46  * NOTES
47  *   Might be a good idea to replace all the switch statements with
48  *   function pointers.
49  *   So instead of:
50  *     switch (output_mode)
51  *     {
52  *         case HTML:
53  *             RB_HTML_Generate_Doc_Start(dest_doc, src_name, name, toc);
54  *             break;
55  *         case LATEX:
56  *             RB_LaTeX_Generate_Doc_Start(dest_doc, src_name, name, toc);
57  *             break;
58  *         case RTF:
59  *             RB_RTF_Generate_Doc_Start(dest_doc, src_name, name, toc);
60  *             break;
61  *         case ASCII:
62  *             RB_ASCII_Generate_Doc_Start(dest_doc, src_name, name, toc);
63  *             break;
64  *         case TROFF:
65  *             RB_TROFF_Generate_Doc_Start(dest_doc, src_name, name, toc);
66  *             break;
67  *         default:
68  *             break;
69  *     }
70  *   we will have
71  *     (*rb_generate_doc_start)(dest_doc, src_name, name, toc);
72  *
73  *   were the function pointers are initialized at program start based
74  *   on the output mode.
75  *******
76  * $Id: generator.c,v 1.106 2007/07/10 19:13:51 gumpu Exp $
77  */
78
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <ctype.h>
83 #include <assert.h>
84
85 #include "globals.h"
86 #include "robodoc.h"
87 #include "headers.h"
88 #include "items.h"
89 #include "util.h"
90 #include "links.h"
91 #include "generator.h"
92 #include "document.h"
93 #include "part.h"
94 #include "file.h"
95 #include "roboconfig.h"
96
97 /* Generators */
98 #include "html_generator.h"
99 #include "latex_generator.h"
100 #include "xmldocbook_generator.h"
101 #include "rtf_generator.h"
102 #include "troff_generator.h"
103 #include "ascii_generator.h"
104 #include "test_generator.h"
105
106 /* TODO This should not be here.... */
107 #include "analyser.h"
108
109 #ifdef DMALLOC
110 #include <dmalloc.h>
111 #endif
112
113
114 /* Module functions */
115 // static void         RB_Generate_Empty_Item( FILE * dest_doc );
116
117 static void         Generate_Item_Line(
118     FILE *dest_doc,
119     char *line,
120     int item_type,
121     char *docname,
122     struct RB_header *fnames );
123 void                Generate_Char(
124     FILE *dest_doc,
125     int cur_char );
126 static void         Generate_Index(
127     struct RB_Document *document );
128
129 static void         Generate_Header(
130     FILE *f,
131     struct RB_Document *document,
132     struct RB_header *header,
133     char *docname );
134
135 static void         Generate_Begin_Paragraph(
136     FILE *dest_doc );
137 static void         Generate_End_Paragraph(
138     FILE *dest_doc );
139 static void         Format_Line(
140     FILE *dest_doc,
141     long format );
142 static void         Generate_Begin_Preformatted(
143     FILE *dest_doc,
144     int source );
145 static void         Generate_End_Preformatted(
146     FILE *dest_doc );
147 static void         Generate_Begin_List_Item(
148     FILE *dest_doc );
149 static void         Generate_End_List_Item(
150     FILE *dest_doc );
151 static void         Generate_Begin_List(
152     FILE *dest_doc );
153 static void         Generate_End_List(
154     FILE *dest_doc );
155 static void         Pipe_Line(
156     FILE *dest_doc,
157     char *arg_line );
158
159 static char         piping = FALSE;
160
161
162 /* TODO Documentation */
163 void RB_Generate_False_Link(
164     FILE *dest_doc,
165     char *name )
166 {
167     switch ( output_mode )
168     {
169     case TEST:
170         RB_TEST_Generate_False_Link( dest_doc, name );
171         break;
172     case XMLDOCBOOK:
173         RB_XMLDB_Generate_False_Link( dest_doc, name );
174         break;
175     case HTML:
176         RB_HTML_Generate_False_Link( dest_doc, name );
177         break;
178     case LATEX:
179         RB_LaTeX_Generate_False_Link( dest_doc, name );
180         break;
181     case RTF:
182         RB_RTF_Generate_False_Link( dest_doc, name );
183         break;
184     case ASCII:
185         RB_ASCII_Generate_False_Link( dest_doc, name );
186         break;
187     case TROFF:
188         RB_TROFF_Generate_False_Link( dest_doc, name );
189         break;
190     case UNKNOWN:
191     default:
192         assert( 0 );
193     }
194 }
195
196 /****f* Generator/RB_Generate_Item_Begin
197  * FUNCTION
198  *   Generate the begin of an item.  This should switch to some
199  *   preformatted output mode, similar to HTML's <PRE>.
200  * SYNOPSIS
201  */
202 void RB_Generate_Item_Begin(
203     FILE *dest_doc,
204     char *name )
205 /*
206  * INPUTS
207  *   dest_doc -- file to be written to
208  *   output_mode -- global with the current output mode
209  * SOURCE
210  */
211 {
212     switch ( output_mode )
213     {
214     case TEST:
215         RB_TEST_Generate_Item_Begin( dest_doc );
216         break;
217     case XMLDOCBOOK:
218         RB_XMLDB_Generate_Item_Begin( dest_doc );
219         break;
220     case HTML:
221         RB_HTML_Generate_Item_Begin( dest_doc, name );
222         break;
223     case LATEX:
224         RB_LaTeX_Generate_Item_Begin( dest_doc );
225         break;
226     case RTF:
227         RB_RTF_Generate_Item_Begin( dest_doc );
228         break;
229     case ASCII:
230         RB_ASCII_Generate_Item_Begin( dest_doc );
231         break;
232     case TROFF:
233         /* nothing */
234         break;
235     case UNKNOWN:
236     default:
237         assert( 0 );
238     }
239 }
240
241 /******/
242
243
244 /****f* Generator/Generate_Label
245  * FUNCTION
246  *   Generate a label that can be used for a link.
247  *   For instance in HTML this is <a name="label">
248  * SYNOPSIS
249  */
250 void Generate_Label(
251     FILE *dest_doc,
252     char *name )
253 /*
254  * INPUTS
255  *   * dest_doc -- file to be written to
256  *   * name -- the label's name.
257  *   * output_mode -- global with the current output mode
258  * SOURCE
259  */
260 {
261     switch ( output_mode )
262     {
263     case TEST:
264         RB_TEST_Generate_Label( dest_doc, name );
265         break;
266     case XMLDOCBOOK:
267         RB_XMLDB_Generate_Label( dest_doc, name );
268         break;
269     case HTML:
270         RB_HTML_Generate_Label( dest_doc, name );
271         break;
272     case LATEX:
273         /* lowtexx 21.09.2005 11:33 */
274         RB_LaTeX_Generate_Label( dest_doc, name );
275         break;
276     case RTF:
277         RB_RTF_Generate_Label( dest_doc, name );
278         break;
279     case ASCII:
280         /* Doesn't apply */
281         break;
282     case TROFF:
283         /* Doesn't apply */
284         break;
285     case UNKNOWN:
286     default:
287         assert( 0 );
288     }
289 }
290
291 /******/
292
293
294 /****f* Generator/RB_Generate_Item_End
295  * FUNCTION
296  *   Generate the end of an item.  This should switch back from the
297  *   preformatted mode.  So in HTML it generates the </PRE> of a <PRE>
298  *   </PRE> pair.
299  * INPUTS
300  *   * dest_doc -- file to be written to
301  *   * output_mode -- global with the current output mode
302  * SOURCE
303  */
304
305 void RB_Generate_Item_End(
306     FILE *dest_doc,
307     char *name )
308 {
309     switch ( output_mode )
310     {
311     case TEST:
312         RB_TEST_Generate_Item_End( dest_doc );
313         break;
314     case XMLDOCBOOK:
315         RB_XMLDB_Generate_Item_End( dest_doc );
316         break;
317     case HTML:
318         RB_HTML_Generate_Item_End( dest_doc, name );
319         break;
320     case LATEX:
321         if ( piping == TRUE )
322         {
323             fprintf( dest_doc, "\\begin{verbatim}\n" );
324             piping = FALSE;
325         }
326         RB_LaTeX_Generate_Item_End( dest_doc );
327         break;
328     case RTF:
329         RB_RTF_Generate_Item_End( dest_doc );
330         break;
331     case ASCII:
332         RB_ASCII_Generate_Item_End( dest_doc );
333         break;
334     case TROFF:
335         /* Doesn't apply */ break;
336     case UNKNOWN:
337
338     default:
339         assert( 0 );
340     }
341 }
342
343 /****/
344
345
346
347 /****f Generator/RB_Get_Len_Extension
348  * FUNCTION
349  *   Compute the length of the filename extension for
350  *   the current document type.
351  *****
352  */
353
354 size_t RB_Get_Len_Extension(
355     char *extension )
356 {
357     size_t              size = 0;
358
359     size = strlen( extension );
360     if ( *extension != '.' )
361         size++;
362     return size;
363 }
364
365 /****f* Generator/RB_Add_Extension
366  * FUNCTION
367  *   Add an extension to the filename base based on on the current
368  *   output mode.
369  * INPUTS
370  *   * doctype -- output mode
371  *   * name    -- the name of the file without extension and with
372  *              enough room left to add the extension.
373  * OUTPUT
374  *   name    -- the name of the file including the extension.
375  * SOURCE
376  */
377
378 void RB_Add_Extension(
379     char *extension,
380     char *name )
381 {
382     if ( *extension != '.' )
383         strcat( name, "." );
384     strcat( name, extension );
385 }
386
387 /******/
388
389 /*x**f Generator/RB_Default_Len_Extension
390  * FUNCTION
391  *   Returns default extension for
392  *   the current document type.
393  *****
394  */
395
396 char               *RB_Get_Default_Extension(
397     T_RB_DocType doctype )
398 {
399     char               *extension = NULL;
400
401     switch ( doctype )
402     {
403     case TEST:
404         extension = RB_TEST_Get_Default_Extension(  );
405         break;
406     case XMLDOCBOOK:
407         extension = RB_XMLDB_Get_Default_Extension(  );
408         break;
409     case HTML:
410         extension = RB_HTML_Get_Default_Extension(  );
411         break;
412     case LATEX:
413         extension = RB_LaTeX_Get_Default_Extension(  );
414         break;
415     case RTF:
416         extension = RB_RTF_Get_Default_Extension(  );
417         break;
418     case ASCII:
419         extension = RB_ASCII_Get_Default_Extension(  );
420         break;
421     case TROFF:
422         extension = RB_TROFF_Get_Default_Extension(  );
423         break;
424     case UNKNOWN:
425     default:
426         assert( 0 );
427     }
428     return extension;
429 }
430
431
432 /****f* Generator/RB_Generate_BeginSection
433  * FUNCTION
434  *   Generate a section of level depth in the current output mode.
435  *   This is used for the --sections option.  Where each header is
436  *   placed in a section based on the header hierarchy.
437  * INPUTS
438  *   * dest_doc    -- the destination file.
439  *   * doctype     -- document type
440  *   * depth       -- the level of the section
441  *   * name        -- the name of the section
442  *   * header      -- pointer to the header structure
443  *   * output_mode -- global with the current output mode.
444  * SOURCE
445  */
446
447 void RB_Generate_BeginSection(
448     FILE *dest_doc,
449     int depth,
450     char *name,
451     struct RB_header *header )
452 {
453     switch ( output_mode )
454     {
455     case TEST:
456         RB_TEST_Generate_BeginSection( dest_doc, depth, name );
457         break;
458     case XMLDOCBOOK:
459         RB_XMLDB_Generate_BeginSection( dest_doc, depth, name );
460         break;
461     case HTML:
462         RB_HTML_Generate_BeginSection( dest_doc, depth, name, header );
463         break;
464     case LATEX:
465         RB_LaTeX_Generate_BeginSection( dest_doc, depth, name, header );
466         break;
467     case RTF:
468         RB_RTF_Generate_BeginSection( dest_doc, depth, name );
469         break;
470     case TROFF:
471 /* RB_TROFF_Generate_BeginSection( dest_doc, depth, name ); */
472         break;
473     case ASCII:
474         RB_ASCII_Generate_BeginSection( dest_doc, depth, name, header );
475         break;
476     case UNKNOWN:
477     default:
478         assert( 0 );
479     }
480 }
481
482 /*******/
483
484
485 /****f* Generator/RB_Generate_EndSection
486  * FUNCTION
487  *   Generate the end of a section base on the current output mode.
488  *   The functions is used for the --section option.
489  *   It closes a section in the current output mode.
490  * INPUTS
491  *   * dest_doc -- the destination file.
492  *   * doctype  --
493  *   * depth    -- the level of the section
494  *   * name     -- the name of the section
495  *   * output_mode -- global with the current output mode.
496  * SOURCE
497  */
498
499 void RB_Generate_EndSection(
500     FILE *dest_doc,
501     int depth,
502     char *name )
503 {
504     switch ( output_mode )
505     {
506     case TEST:
507         RB_TEST_Generate_EndSection( dest_doc, depth, name );
508         break;
509     case XMLDOCBOOK:
510         RB_XMLDB_Generate_EndSection( dest_doc, depth, name );
511         break;
512     case HTML:
513         RB_HTML_Generate_EndSection( dest_doc, depth, name );
514         break;
515     case LATEX:
516         RB_LaTeX_Generate_EndSection( dest_doc, depth, name );
517         break;
518     case RTF:
519         RB_RTF_Generate_EndSection( dest_doc, depth, name );
520         break;
521     case TROFF:
522         /* doesn't apply */
523         break;
524     case ASCII:
525         RB_HTML_Generate_EndSection( dest_doc, depth, name );
526         break;
527     case UNKNOWN:
528
529     default:
530         assert( 0 );
531     }
532 }
533
534 /******/
535
536
537 /****f* Generator/RB_Generate_Index_Entry
538  * FUNCTION
539  *   Generate an entry for an auto generated index.  This works only
540  *   for output modes that support this, LaTeX for instance.   This
541  *   has nothting to do with the master index.
542  * SYNOPSIS
543  */
544 void RB_Generate_Index_Entry(
545     FILE *dest_doc,
546     T_RB_DocType doctype,
547     struct RB_header *header )
548 /*
549  * INPUTS
550  *   * dest_doc -- the destination file.
551  *   * header   -- pointer to the header the index entry is for.
552  *   * output_mode -- global with the current output mode.
553  * SOURCE
554  */
555 {
556     switch ( doctype )
557     {
558     case TEST:
559         /* TODO */
560         break;
561     case XMLDOCBOOK:
562         /* TODO */
563         break;
564     case HTML:
565         /* TODO */
566         break;
567     case LATEX:
568         RB_LaTeX_Generate_Index_Entry( dest_doc, header );
569         break;
570     case RTF:
571         /* TODO */
572         break;
573     case ASCII:
574         /* No index available */
575         break;
576     case TROFF:
577         /* No index available */
578         break;
579     case UNKNOWN:
580     default:
581         assert( 0 );
582     }
583 }
584
585 /*******/
586
587
588 /****f* Generator/RB_Generate_TOC_2
589  * FUNCTION
590  *   Create a Table of Contents based on the headers found in
591  *   _all_ source files.   There is also a function to create
592  *   a table of contents based on the headers found in a single
593  *   source file RB_Generate_TOC_1
594  * SYNOPSIS
595  */
596 void RB_Generate_TOC_2(
597     FILE *dest_doc,
598     struct RB_header **headers,
599     int count,
600     struct RB_Part *owner,
601     char *dest_name )
602 /*
603  * INPUTS
604  *   * dest_doc -- the destination file.
605  *   * headers  -- an array of pointers to all the headers.
606  *   * count    -- the number of pointers in the array.
607  *   * output_mode -- global with the current output mode.
608  *   * owner    -- The owner of the TOC. Only the headers that are owned
609  *               by this owner are included in the TOC.  Can be NULL,
610  *               in which case all headers are included.
611  * SOURCE
612  */
613 {
614     switch ( output_mode )
615     {
616     case TEST:
617         break;
618     case TROFF:
619         break;
620     case XMLDOCBOOK:
621         break;
622     case HTML:
623         RB_HTML_Generate_TOC_2( dest_doc, headers, count, owner, dest_name );
624         break;
625     case LATEX:
626         /* LaTeX has it's own mechanism for creating
627          * a table of content */
628         break;
629     case RTF:
630         RB_RTF_Generate_TOC_2( dest_doc, headers, count );
631         break;
632     case ASCII:
633         /* TODO: No TOC in ASCII mode */
634         break;
635     case UNKNOWN:
636
637     default:
638         assert( 0 );
639     }
640 }
641
642 /******/
643
644
645 /****f* Generator/RB_Generate_Doc_Start
646  * NAME
647  *   RB_Generate_Doc_Start -- Generate document header.
648  * SYNOPSIS
649  */
650 void RB_Generate_Doc_Start(
651     struct RB_Document *document,
652     FILE *dest_doc,
653     char *src_name,
654     char *title,
655     char toc,
656     char *dest_name,
657     char *charset )
658 /*
659  * FUNCTION
660  *   Generates for depending on the output_mode the text that
661  *   will be at the start of a document.
662  *   Including the table of contents.
663  * INPUTS
664  *   o dest_doc - pointer to the file to which the output will
665  *                be written.
666  *   o src_name - the name of the source file or directory.
667  *   o name     - the name of this file.
668  *   o output_mode - global variable that indicates the output
669  *                   mode.
670  *   o toc      - generate table of contens
671  * SEE ALSO
672  *   RB_Generate_Doc_End
673  * SOURCE
674  */
675 {
676     switch ( output_mode )
677     {
678     case TEST:
679         RB_TEST_Generate_Doc_Start( dest_doc, src_name, title, toc );
680         break;
681     case XMLDOCBOOK:
682         RB_XMLDB_Generate_Doc_Start( document, dest_doc, charset );
683         break;
684     case HTML:
685         RB_HTML_Generate_Doc_Start( dest_doc, src_name, title, dest_name,
686                                     charset );
687         break;
688     case LATEX:
689         RB_LaTeX_Generate_Doc_Start( dest_doc, src_name, title, charset );
690         break;
691     case RTF:
692         RB_RTF_Generate_Doc_Start( dest_doc, src_name, title, toc );
693         break;
694     case ASCII:
695         RB_ASCII_Generate_Doc_Start( dest_doc, src_name, title, toc );
696         break;
697     case TROFF:
698         /* */ ;
699         break;
700     case UNKNOWN:
701     default:
702         ;
703     }
704 }
705
706 /***************/
707
708
709 /****f* Generator/RB_Generate_Doc_End
710  * NAME
711  *   RB_Generate_Doc_End -- generate document trailer.
712  * SYNOPSIS
713  */
714 void RB_Generate_Doc_End(
715     FILE *dest_doc,
716     char *name,
717     char *src_name )
718 /*
719  * FUNCTION
720  *   Generates for depending on the output_mode the text that
721  *   will be at the end of a document.
722  * INPUTS
723  *   o dest_doc - pointer to the file to which the output will
724  *                be written.
725  *   o name     - the name of this file.
726  *   o output_mode - global variable that indicates the output
727  *                   mode.
728  * NOTES
729  *   Doesn't do anything with its arguments, but that might
730  *   change in the future.
731  * BUGS
732  * SOURCE
733  */
734 {
735     switch ( output_mode )
736     {
737     case TEST:
738         RB_TEST_Generate_Doc_End( dest_doc, name );
739         break;
740     case XMLDOCBOOK:
741         RB_XMLDB_Generate_Doc_End( dest_doc, name );
742         break;
743     case HTML:
744         RB_HTML_Generate_Doc_End( dest_doc, name, src_name );
745         break;
746     case LATEX:
747         RB_LaTeX_Generate_Doc_End( dest_doc, name );
748         break;
749     case RTF:
750         RB_RTF_Generate_Doc_End( dest_doc, name );
751         break;
752     case TROFF:
753         break;
754     case ASCII:
755         break;
756     case UNKNOWN:
757
758     default:
759         assert( 0 );
760     }
761 }
762
763 /************/
764
765
766 /****f* Generator/RB_Generate_Header_Start [3.0h]
767  * NAME
768  *   RB_Generate_Header_Start -- generate header start text.
769  * SYNOPSIS
770  */
771 FILE               *RB_Generate_Header_Start(
772     FILE *dest_doc,
773     struct RB_header *cur_header )
774 /*
775  * FUNCTION
776  *   Generates depending on the output_mode the text that
777  *   will be at the end of each header.
778  * INPUTS
779  *   o dest_doc - pointer to the file to which the output will
780  *                be written.
781  *   o cur_header - pointer to a RB_header structure.
782  * SEE ALSO
783  *   RB_Generate_Header_End
784  * SOURCE
785  */
786 {
787     switch ( output_mode )
788     {
789     case TEST:
790         RB_TEST_Generate_Header_Start( dest_doc, cur_header );
791         break;
792     case XMLDOCBOOK:
793         RB_XMLDB_Generate_Header_Start( dest_doc, cur_header );
794         break;
795     case HTML:
796         RB_HTML_Generate_Header_Start( dest_doc, cur_header );
797         break;
798     case LATEX:
799         RB_LaTeX_Generate_Header_Start( dest_doc, cur_header );
800         break;
801     case RTF:
802         RB_RTF_Generate_Header_Start( dest_doc, cur_header );
803         break;
804     case ASCII:
805         RB_ASCII_Generate_Header_Start( dest_doc, cur_header );
806         break;
807     case TROFF:
808         dest_doc = RB_TROFF_Generate_Header_Start( dest_doc, cur_header );
809         break;
810     case UNKNOWN:
811     default:
812         assert( 0 );
813     }
814     return dest_doc;
815 }
816
817 /******/
818
819
820 /****f* Generator/RB_Generate_Header_End [3.0h]
821  * NAME
822  *   RB_Generate_Header_End
823  * SYNOPSIS
824  */
825 void RB_Generate_Header_End(
826     FILE *dest_doc,
827     struct RB_header *cur_header )
828 /*
829  * FUNCTION
830  *   Generates for depending on the output_mode the text that
831  *   will be at the end of a header.
832  *   This function is used if the option --section is _not_
833  *   used.
834  * INPUTS
835  *   o dest_doc - pointer to the file to which the output will
836  *              be written.
837  *   o cur_header - pointer to a RB_header structure.
838  * SEE ALSO
839  *   RB_Generate_Header_Start, RB_Generate_EndSection,
840  *   RB_Generate_BeginSection
841  * SOURCE
842  */
843 {
844     switch ( output_mode )
845     {                           /* switch by *koessi */
846     case TEST:
847         RB_TEST_Generate_Header_End( dest_doc, cur_header );
848         break;
849     case XMLDOCBOOK:
850         RB_XMLDB_Generate_Header_End( dest_doc, cur_header );
851         break;
852     case HTML:
853         RB_HTML_Generate_Header_End( dest_doc, cur_header );
854         break;
855     case LATEX:
856         RB_LaTeX_Generate_Header_End( dest_doc, cur_header );
857         break;
858     case RTF:
859         RB_RTF_Generate_Header_End( dest_doc, cur_header );
860         break;
861     case ASCII:
862         RB_ASCII_Generate_Header_End( dest_doc, cur_header );
863         break;
864     case TROFF:
865         RB_TROFF_Generate_Header_End( dest_doc, cur_header );
866         break;
867     case UNKNOWN:
868     default:
869         break;
870     }
871 }
872
873 /*****/
874
875
876 /****f* Generator/Generate_Item_Name [2.01]
877  * NAME
878  *   Generate_Item_Name -- fast&easy
879  * SYNOPSIS
880  */
881 void Generate_Item_Name(
882     FILE *dest_doc,
883     int item_type )
884 /*
885  * FUNCTION
886  *   write the item's name to the doc
887  * INPUTS
888  *   o FILE* dest_doc      -- destination file
889  *   o int item_type       -- the type of item
890  * AUTHOR
891  *   Koessi
892  * NOTES
893  *   uses globals: output_mode
894  * SOURCE
895  */
896 {
897     char               *name = configuration.items.names[item_type];
898
899     switch ( output_mode )
900     {
901     case TEST:
902         RB_TEST_Generate_Item_Name( dest_doc, name );
903         break;
904     case XMLDOCBOOK:
905         RB_XMLDB_Generate_Item_Name( dest_doc, name );
906         break;
907     case HTML:
908         RB_HTML_Generate_Item_Name( dest_doc, name );
909         break;
910     case LATEX:
911         RB_LaTeX_Generate_Item_Name( dest_doc, name );
912         break;
913     case RTF:
914         RB_RTF_Generate_Item_Name( dest_doc, name );
915         break;
916     case ASCII:
917         RB_ASCII_Generate_Item_Name( dest_doc, name );
918         break;
919     case TROFF:
920         RB_TROFF_Generate_Item_Name( dest_doc, name, item_type );
921         break;
922         break;
923     case UNKNOWN:
924     default:
925         assert( 0 );
926     }
927 }
928
929 /*********/
930
931
932 void Generate_Begin_Content(
933     FILE *dest_doc )
934 {
935     switch ( output_mode )
936     {
937     case HTML:
938         HTML_Generate_Begin_Content( dest_doc );
939         break;
940     default:
941         break;
942     }
943 }
944
945 void Generate_End_Content(
946     FILE *dest_doc )
947 {
948     switch ( output_mode )
949     {
950     case HTML:
951         HTML_Generate_End_Content( dest_doc );
952         break;
953     default:
954         break;
955     }
956 }
957
958 void Generate_Begin_Navigation(
959     FILE *dest_doc )
960 {
961     switch ( output_mode )
962     {
963     case HTML:
964         HTML_Generate_Begin_Navigation( dest_doc );
965         break;
966     default:
967         break;
968     }
969
970 }
971
972 void Generate_End_Navigation(
973     FILE *dest_doc )
974 {
975     switch ( output_mode )
976     {
977     case HTML:
978         HTML_Generate_End_Navigation( dest_doc );
979         break;
980     default:
981         break;
982     }
983
984 }
985
986 void Generate_IndexMenu(
987     FILE *dest_doc,
988     char *filename,
989     struct RB_Document *document )
990 {
991     switch ( output_mode )
992     {
993     case HTML:
994         RB_HTML_Generate_IndexMenu( dest_doc, filename, document, NULL );
995         break;
996     default:
997         break;
998     }
999
1000 }
1001
1002 void Generate_Begin_Extra(
1003     FILE *dest_doc )
1004 {
1005     switch ( output_mode )
1006     {
1007     case HTML:
1008         HTML_Generate_Begin_Extra( dest_doc );
1009         break;
1010     default:
1011         break;
1012     }
1013 }
1014
1015 void Generate_End_Extra(
1016     FILE *dest_doc )
1017 {
1018     switch ( output_mode )
1019     {
1020     case HTML:
1021         HTML_Generate_End_Extra( dest_doc );
1022         break;
1023     default:
1024         break;
1025     }
1026 }
1027
1028
1029
1030
1031
1032
1033 /* TODO Documentation */
1034 void RB_Generate_Nav_Bar(
1035     struct RB_Document *document,
1036     FILE *current_doc,
1037     struct RB_header *current_header )
1038 {
1039     switch ( output_mode )
1040     {
1041     case TEST:
1042         break;
1043     case XMLDOCBOOK:
1044         break;
1045     case HTML:
1046         if ( course_of_action.do_one_file_per_header )
1047         {
1048             /* Nothing */
1049         }
1050         else
1051         {
1052             RB_HTML_Generate_Nav_Bar( document, current_doc, current_header );
1053         }
1054         break;
1055     case LATEX:
1056         break;
1057     case RTF:
1058         break;
1059     case ASCII:
1060         break;
1061     case TROFF:
1062         break;
1063     case UNKNOWN:
1064     default:
1065         /* Bug */
1066         assert( 0 );
1067     }
1068 }
1069
1070
1071
1072 /* TODO Documentation */
1073 int RB_HTML_Extra(
1074     FILE *dest_doc,
1075     int item_type,
1076     char *cur_char,
1077     char prev_char )
1078 {
1079     int                 res = -1;
1080
1081     switch ( output_mode )
1082     {
1083     case TEST:
1084         break;
1085     case XMLDOCBOOK:
1086         break;
1087     case HTML:
1088         res =
1089             RB_HTML_Generate_Extra( dest_doc, item_type, cur_char,
1090                                     prev_char );
1091         break;
1092     case LATEX:
1093         /* TODO */
1094         break;
1095     case RTF:
1096         /* TODO */
1097         break;
1098     case ASCII:
1099         /* TODO */
1100         break;
1101     case TROFF:
1102         res = RB_TROFF_Generate_Extra( dest_doc, item_type, cur_char );
1103         break;
1104         break;
1105     case UNKNOWN:
1106     default:
1107         /* Bug */
1108         assert( 0 );
1109     }
1110     return res;
1111 }
1112
1113
1114 /****f* Generator/RB_Name_Headers
1115  * FUNCTION
1116  *   Give all headers a unique name. This makes sure that if
1117  *   two headers have the same name linking to one of the headers
1118  *   still works.
1119  * SYNOPSIS
1120  */
1121 void RB_Name_Headers(
1122     struct RB_header **headers,
1123     long count )
1124 /*
1125  * SOURCE
1126  */
1127 #define MAX_UNIQUE_ID_LENGTH 80
1128 {
1129     int                 i;
1130     char                id[MAX_UNIQUE_ID_LENGTH + 1];
1131
1132     RB_Say( "Assigning headers a unique name.\n", SAY_DEBUG );
1133     for ( i = 0; i < count; ++i )
1134     {
1135         struct RB_header   *header;
1136
1137         header = headers[i];
1138         sprintf( id, "robo%d", i );
1139         header->unique_name = RB_StrDup( id );
1140     }
1141 }
1142
1143 /******/
1144
1145 /****f* Generator/RB_Sort_Items
1146  * FUNCTION
1147  *   Sort the items in all the headers according to the order
1148  *   specified in the 'item order' block in the robodoc.rc 
1149  *   file.
1150  * SYNOPSIS
1151  */
1152 static void RB_Sort_Items(
1153     struct RB_header **headers,
1154     long header_count )
1155 /*
1156  * SOURCE
1157  */
1158 {
1159     int                 n_order = configuration.item_order.number;
1160
1161     if ( n_order )
1162     {
1163         int                 i = 0;
1164         int                 j = 0;
1165         int                 max_number_of_items = 0;
1166         struct RB_Item    **items = NULL;
1167         struct RB_Item    **items_sorted = NULL;
1168
1169         RB_Say( "Sorting items in %d headers.\n", SAY_DEBUG, header_count );
1170
1171         /* Compute the maximum number of items in any given header */
1172         for ( j = 0; j < header_count; ++j )
1173         {
1174             struct RB_header   *header;
1175             struct RB_Item     *item;
1176             int                 item_count = 0;
1177
1178             header = headers[j];
1179             for ( item = header->items; item; item = item->next )
1180             {
1181                 ++item_count;
1182             }
1183
1184             if ( item_count > max_number_of_items )
1185             {
1186                 max_number_of_items = item_count;
1187             }
1188         }
1189         /* Allocate an array for the items, this makes it easier to
1190          * sort. */
1191
1192         RB_Say( "Largest header has %d items.\n", SAY_DEBUG,
1193                 max_number_of_items );
1194
1195         if ( max_number_of_items == 0 )
1196         {
1197             /* No items in any of the headers, do nothing */
1198         }
1199         else
1200         {
1201             items = calloc( max_number_of_items, sizeof( struct RB_Item * ) );
1202             items_sorted =
1203                 calloc( max_number_of_items, sizeof( struct RB_Item * ) );
1204
1205             /* Sort items */
1206             for ( j = 0; j < header_count; ++j )
1207             {
1208                 struct RB_header   *header = NULL;
1209                 struct RB_Item     *item = NULL;
1210                 int                 item_index = 0;
1211                 int                 sorted_item_index = 0;
1212                 int                 item_count = 0;
1213
1214                 header = headers[j];
1215
1216                 /* Copy item pointers to array */
1217                 for ( item = header->items; item;
1218                       item = item->next, ++item_index )
1219                 {
1220                     items[item_index] = item;
1221                     items_sorted[item_index] = item;
1222                 };
1223                 item_count = item_index;
1224
1225                 if ( item_count == 0 )
1226                 {
1227                     /* No items in this header, do nothing. */
1228                 }
1229                 else
1230                 {
1231                     assert( item_count <= max_number_of_items );
1232
1233                     /* First copy the items in the order that is defined in
1234                      * item_order[] to sorted_items[] */
1235                     sorted_item_index = 0;
1236                     for ( i = 0; i < n_order; ++i )
1237                     {
1238                         for ( item_index = 0; item_index < item_count;
1239                               ++item_index )
1240                         {
1241                             if ( items[item_index] )
1242                             {
1243                                 if ( strcmp
1244                                      ( configuration.items.
1245                                        names[items[item_index]->type],
1246                                        configuration.item_order.names[i] ) ==
1247                                      0 )
1248                                 {
1249                                     /* copy to items_sorted */
1250                                     items_sorted[sorted_item_index] =
1251                                         items[item_index];
1252                                     ++sorted_item_index;
1253                                     items[item_index] = NULL;
1254                                 }
1255                             }
1256                         }
1257                     }
1258                     /* Then copy the remaining items to items_sorted[] */
1259                     for ( item_index = 0; item_index < item_count;
1260                           ++item_index )
1261                     {
1262                         if ( items[item_index] )
1263                         {
1264                             /* copy to items_sorted */
1265                             items_sorted[sorted_item_index] =
1266                                 items[item_index];
1267                             ++sorted_item_index;
1268                             items[item_index] = NULL;
1269                         }
1270                     }
1271
1272                     assert( sorted_item_index == item_count );
1273
1274                     /* Now copy the items in items_sorted[] back into the linked list in
1275                      * the header */
1276                     if ( item_count > 1 )
1277                     {
1278                         /* Chain all the items */
1279                         for ( item_index = 0; item_index < item_count - 1;
1280                               ++item_index )
1281                         {
1282                             items_sorted[item_index]->next =
1283                                 items_sorted[item_index + 1];
1284                         }
1285                     }
1286
1287                     assert( item_count > 0 );
1288                     items_sorted[item_count - 1]->next = NULL;
1289                     /* now link the first item to the header. */
1290                     header->items = items_sorted[0];
1291                 }
1292             }
1293
1294             free( items_sorted );
1295             free( items );
1296         }
1297     }
1298
1299     RB_Say( "Done sorting items in %d headers.\n", SAY_DEBUG, header_count );
1300 }
1301
1302 /*******/
1303
1304
1305 /****f* Generator/RB_Generate_Documentation
1306  * FUNCTION
1307  *   Generate the documentation for all the information contained in a
1308  *   RB_Document structure.
1309  * SYNOPSIS
1310  */
1311 void RB_Generate_Documentation(
1312     struct RB_Document *document )
1313 /*
1314  * INPUTS
1315  *   document -- pointer to the RB_Document structure.
1316  * SOURCE
1317  */
1318 {
1319     RB_SetCurrentFile( NULL );
1320
1321
1322
1323     if ( document->actions.do_singledoc )
1324     {
1325         RB_Generate_SingleDoc( document );
1326     }
1327     else if ( document->actions.do_multidoc )
1328     {
1329         RB_Generate_MultiDoc( document );
1330     }
1331     else if ( document->actions.do_singlefile )
1332     {
1333         RB_Generate_SingleDoc( document );
1334     }
1335 }
1336
1337 /*****/
1338
1339 /****f* Generator/RB_Generate_MultiDoc
1340  * FUNCTION
1341  *   Create documentation by creating a file for each
1342  *   individual source file that was scanned.
1343  * SYNOPSIS
1344  */
1345 void RB_Generate_MultiDoc(
1346     struct RB_Document *document )
1347 /*
1348  * INPUTS
1349  *   document -- pointer to the RB_Document structure.
1350  * SOURCE
1351  */
1352 {
1353     struct RB_Part     *i_part;
1354     FILE               *document_file = NULL;
1355
1356     RB_Document_Determine_DocFilePaths( document );
1357     RB_Document_Create_DocFilePaths( document );
1358     if ( document->actions.do_one_file_per_header )
1359     {
1360         RB_Document_Split_Parts( document );
1361     }
1362     RB_Document_Determine_DocFileNames( document );
1363     RB_Document_Collect_Headers( document );
1364     if ( document->actions.do_nosort )
1365     {
1366         /* Nothing */
1367     }
1368     else
1369     {
1370         RB_Document_Sort_Headers( document );
1371     }
1372     RB_Document_Link_Headers( document );
1373     RB_Fill_Header_Filename( document );
1374     RB_Name_Headers( document->headers, document->no_headers );
1375     RB_Sort_Items( document->headers, document->no_headers );
1376     RB_CollectLinks( document, document->headers, document->no_headers );
1377     if ( output_mode == HTML )
1378     {
1379         RB_Create_CSS( document );
1380     }
1381
1382
1383     for ( i_part = document->parts; i_part != NULL; i_part = i_part->next )
1384     {
1385
1386         char               *srcname = Get_Fullname( i_part->filename );
1387         char               *docname = RB_Get_FullDocname( i_part->filename );
1388
1389         /* Nothing found in this part, do not generate it */
1390         if ( i_part->headers == 0 )
1391             continue;
1392
1393
1394         if ( output_mode != TROFF )
1395         {
1396             document_file = RB_Open_Documentation( i_part );
1397             RB_Generate_Doc_Start( document,
1398                                    document_file, srcname, srcname, 1,
1399                                    docname, document->charset );
1400
1401             Generate_Begin_Navigation( document_file );
1402             if ( document->actions.do_one_file_per_header )
1403             {
1404                 RB_HTML_Generate_Nav_Bar_One_File_Per_Header( document,
1405                                                               document_file,
1406                                                               i_part->
1407                                                               headers );
1408             }
1409             else
1410             {
1411                 Generate_IndexMenu( document_file, docname, document );
1412             }
1413             Generate_End_Navigation( document_file );
1414
1415             Generate_Begin_Content( document_file );
1416
1417             if ( ( document->actions.do_toc ) && document->no_headers )
1418             {
1419                 RB_Generate_TOC_2( document_file,
1420                                    document->headers, document->no_headers,
1421                                    i_part, docname );
1422             }
1423             RB_Generate_Part( document_file, document, i_part );
1424             Generate_End_Content( document_file );
1425
1426             RB_Generate_Doc_End( document_file, docname, srcname );
1427             fclose( document_file );
1428         }
1429         else
1430         {
1431             RB_Generate_Part( document_file, document, i_part );
1432         }
1433     }
1434
1435     if ( document->actions.do_index )
1436     {
1437         Generate_Index( document );
1438     }
1439
1440     RB_Free_Links(  );
1441 }
1442
1443 /*****/
1444
1445
1446 /****f* Generator/RB_Generate_SingleDoc
1447  * FUNCTION
1448  *   Create documentation by creating a single file for all individual
1449  *   source file that were scanned.
1450  *
1451  *   This function is called when the option --singledoc is used.
1452  *   Based on whether the option --sections is used this function then
1453  *   calls RB_Generate_Sections or RB_Generate_Part
1454  * SYNOPSIS
1455  */
1456 void RB_Generate_SingleDoc(
1457     struct RB_Document *document )
1458 /*
1459  * INPUTS
1460  *   document -- pointer to the RB_Document structure.
1461  * SOURCE
1462  */
1463 {
1464     FILE               *document_file;
1465     struct RB_Part     *i_part;
1466
1467     RB_Document_Collect_Headers( document );
1468     if ( document->actions.do_nosort )
1469     {
1470         /* Nothing */
1471     }
1472     else
1473     {
1474         RB_Document_Sort_Headers( document );
1475     }
1476     RB_Document_Link_Headers( document );
1477     RB_Fill_Header_Filename( document );
1478     RB_Name_Headers( document->headers, document->no_headers );
1479     RB_Sort_Items( document->headers, document->no_headers );
1480     RB_CollectLinks( document, document->headers, document->no_headers );
1481
1482     for ( i_part = document->parts; i_part != NULL; i_part = i_part->next )
1483     {
1484         RB_Set_FullDocname( i_part->filename, document->singledoc_name );
1485     }
1486
1487     if ( output_mode == HTML )
1488     {
1489         RB_Create_CSS( document );
1490     }
1491
1492     document_file = RB_Open_SingleDocumentation( document );
1493     assert( document->parts->filename->name );
1494
1495
1496     RB_Generate_Doc_Start( document,
1497                            document_file,
1498                            document->srcroot->name,
1499                            document->singledoc_name, 1,
1500                            document->singledoc_name, document->charset );
1501
1502     if ( ( document->actions.do_toc ) && document->no_headers )
1503     {
1504         RB_Generate_TOC_2( document_file,
1505                            document->headers, document->no_headers, NULL,
1506                            document->parts->filename->name );
1507     }
1508     if ( document->actions.do_sections )
1509     {
1510         RB_Generate_Sections( document_file, document );
1511     }
1512     else
1513     {
1514         for ( i_part = document->parts;
1515               i_part != NULL; i_part = i_part->next )
1516         {
1517             RB_Generate_Part( document_file, document, i_part );
1518         }
1519     }
1520
1521     RB_Generate_Doc_End( document_file, "singledoc",
1522                          document->srcroot->name );
1523     fclose( document_file );
1524
1525     RB_Free_Links(  );
1526 }
1527
1528 /******/
1529
1530
1531 /****f* Generator/RB_Generate_Sections
1532  * FUNCTION
1533  *   Creates the documentation for all headers found in all source
1534  *   files.  The order in which they are generated depends on the
1535  *   header hierarchy.  First the top level header's documentation
1536  *   is generated then, the documentation for all it's childern, then
1537  *   the next top level header's documentation is generated.
1538  *   This is a recursive proces.
1539  *   The idea is to create something like:
1540  *     1. Parentheader1
1541  *     1.1 Child1
1542  *     1.2 Child2
1543  *     1.2.1 Child's child1
1544  *     2. Parentheader2
1545  *   etc
1546  * SYNOPSIS
1547  */
1548 void RB_Generate_Sections(
1549     FILE *document_file,
1550     struct RB_Document *document )
1551 /*
1552  * INPUTS
1553  *   o document_file -- destination file.
1554  *   o document -- pointer to the RB_Document structure.
1555  * SOURCE
1556  */
1557 {
1558     unsigned long       i;
1559     int                 depth = 1;
1560     struct RB_header   *header;
1561
1562     depth = document->first_section_level;
1563
1564     RB_Say( "Generating Sections\n", SAY_INFO );
1565     for ( i = 0; i < document->no_headers; ++i )
1566     {
1567         header = ( document->headers )[i];
1568         if ( header->parent )
1569         {
1570             /* This will be in one of the subsections */
1571         }
1572         else
1573         {
1574             RB_Generate_Section( document_file, header, document, depth );
1575         }
1576     }
1577 }
1578
1579 /******/
1580
1581
1582
1583 /****f* Generator/RB_Generate_Section
1584  * FUNCTION
1585  *   Generate the documentation for a header and all
1586  *   its childern.
1587  * INPUTS
1588  *   o document_file -- destination file
1589  *   o parent -- the parent of the header for which the documentation
1590  *               is to be generated.
1591  *   o document -- pointer to the RB_Document structure.
1592  *   o depth -- level of sectioning ( 1  1.1  1.1.1  etc)
1593  * SYNOPSIS
1594  */
1595 void RB_Generate_Section(
1596     FILE *document_file,
1597     struct RB_header *parent,
1598     struct RB_Document *document,
1599     int depth )
1600 /*
1601  * NOTE
1602  *   This is a recursive function.
1603  * SEE ALSO
1604  *    RB_Generate_Sections
1605  * SOURCE
1606  */
1607 {
1608     unsigned long       i;
1609     struct RB_header   *header;
1610     char               *headername;
1611
1612     // We pass either modulename/name or just the name
1613     if ( course_of_action.do_sectionnameonly )
1614     {
1615         headername = parent->function_name;
1616     }
1617     else
1618     {
1619         headername = parent->name;
1620     }
1621
1622     switch ( output_mode )
1623     {
1624     case XMLDOCBOOK:
1625         {
1626             RB_Generate_BeginSection( document_file, depth, headername,
1627                                       parent );
1628             /* Docbook output does not like the labels to be
1629              * generated before the <section> part
1630              */
1631             Generate_Label( document_file, parent->unique_name );
1632             Generate_Label( document_file, parent->name );
1633         }
1634         break;
1635         /* lowtexx 21.09.2005 11:37 */
1636     case LATEX:
1637         {
1638             RB_Generate_BeginSection( document_file, depth, headername,
1639                                       parent );
1640             /* We have to start section before labeling in latex */
1641             Generate_Label( document_file, parent->unique_name );
1642             Generate_Label( document_file, parent->name );
1643         }
1644         break;
1645         /* --- */
1646     default:
1647         {
1648             Generate_Label( document_file, parent->unique_name );
1649             Generate_Label( document_file, parent->name );
1650             RB_Generate_BeginSection( document_file, depth, headername,
1651                                       parent );
1652         }
1653         break;
1654     }
1655
1656     RB_Generate_Nav_Bar( document, document_file, parent );
1657     RB_Generate_Index_Entry( document_file, document->doctype, parent );
1658     Generate_Header( document_file, document, parent, "dummy" );
1659     for ( i = 0; i < document->no_headers; ++i )
1660     {
1661         header = ( document->headers )[i];
1662         if ( header->parent == parent )
1663         {
1664             RB_Generate_Section( document_file, header, document, depth + 1 );
1665         }
1666         else
1667         {
1668             /* Leeg */
1669         }
1670     }
1671     RB_Generate_EndSection( document_file, depth, parent->name );
1672 }
1673
1674 /******/
1675
1676
1677
1678 /****f* Generator/RB_Generate_Part
1679  * FUNCTION
1680  *   Generate the documention for all the headers found in a single
1681  *   source file.
1682  * SYNOPSIS
1683  */
1684 void RB_Generate_Part(
1685     FILE *document_file,
1686     struct RB_Document *document,
1687     struct RB_Part *part )
1688 /*
1689  * INPUTS
1690  *   * document_file -- The file were it stored.
1691  *   * document      -- All the documentation.
1692  *   * part          -- pointer to a RB_Part that contains all the headers found
1693  *                    in a single source file.
1694  * SOURCE
1695  */
1696 {
1697     struct RB_header   *i_header;
1698     char               *docname = NULL;
1699     char               *srcname = Get_Fullname( part->filename );
1700
1701     RB_Say( "generating documentation for file \"%s\"\n", SAY_INFO, srcname );
1702     if ( document->actions.do_singledoc )
1703     {
1704         docname = document->singledoc_name;
1705     }
1706     else if ( document->actions.do_multidoc )
1707     {
1708         docname = RB_Get_FullDocname( part->filename );
1709     }
1710     else if ( document->actions.do_singlefile )
1711     {
1712         docname = document->singledoc_name;
1713     }
1714     else
1715     {
1716         assert( 0 );
1717     }
1718
1719     if ( output_mode == TROFF )
1720     {
1721         RB_TROFF_Set_Param( document->compress, document->section );
1722     }
1723
1724
1725     for ( i_header = part->headers; i_header; i_header = i_header->next )
1726     {
1727         RB_Say( "generating documentation for header \"%s\"\n", SAY_INFO,
1728                 i_header->name );
1729         document_file = RB_Generate_Header_Start( document_file, i_header );
1730         RB_Generate_Nav_Bar( document, document_file, i_header );
1731         RB_Generate_Index_Entry( document_file, document->doctype, i_header );
1732         Generate_Header( document_file, document, i_header, docname );
1733         RB_Generate_Header_End( document_file, i_header );
1734     }
1735 }
1736
1737 /******/
1738
1739
1740 /****f* Generator/RB_Get_DOT_Type
1741  * FUNCTION
1742  *   Returns the type of the DOT file for the given output mode
1743  * SOURCE
1744  */
1745 char               *RB_Get_DOT_Type(
1746     void )
1747 {
1748     switch ( output_mode )
1749     {
1750     case HTML:
1751         return DOT_HTML_TYPE;
1752         break;
1753
1754     case LATEX:
1755         return DOT_LATEX_TYPE;
1756         break;
1757
1758     default:
1759         break;
1760     }
1761
1762     return NULL;
1763 }
1764
1765 /******/
1766
1767
1768 /****f* Generator/RB_Generate_DOT_Image_Link
1769  * FUNCTION
1770  *   Generates the image link for the created dot graphics
1771  * SOURCE
1772  */
1773 void RB_Generate_DOT_Image_Link(
1774     FILE *f,
1775     int dot_nr,
1776     char *dot_type )
1777 {
1778     switch ( output_mode )
1779     {
1780     case HTML:
1781         fprintf( f, "<img src=\"%s%d.%s\">\n", DOT_GRAPH_NAME, dot_nr,
1782                  dot_type );
1783         break;
1784
1785     case LATEX:
1786         {
1787             char                str[TEMP_BUF_SIZE];
1788
1789             // First we need to convert graph to PDF
1790             // (maybe the user is using pdflatex)
1791 #if defined(RB_MSVC)
1792             sprintf( str, "%s %s%d.%s", EPSTOPDF_NAME,
1793                      DOT_GRAPH_NAME, dot_nr, dot_type );
1794 #else
1795             snprintf( str, sizeof( str ), "%s %s%d.%s", EPSTOPDF_NAME,
1796                       DOT_GRAPH_NAME, dot_nr, dot_type );
1797 #endif
1798             system( str );
1799
1800             fprintf( f, "\\includegraphics{%s%d}\n", DOT_GRAPH_NAME, dot_nr );
1801         }
1802         break;
1803
1804     default:
1805         break;
1806     }
1807 }
1808
1809 /******/
1810
1811 /****f* Generator/Generate_Item
1812  * SYNOPSIS
1813  */
1814 static void Generate_Item(
1815     FILE *f,
1816     struct RB_Document *document,
1817     struct RB_header *header,
1818     struct RB_Item *cur_item,
1819     char *docname )
1820  /*
1821   * FUNCTION
1822   *   Generate the documentation for a single item.
1823   * SOURCE
1824   */
1825 {
1826     static int          dot_nr = 1;
1827     int                 line_nr;
1828     char               *dot_type = NULL;
1829     FILE               *tool = NULL;    // Pipe handler to the tool we use
1830     enum ItemType       item_type = cur_item->type;
1831     char               *name = configuration.items.names[item_type];
1832
1833
1834     Generate_Item_Name( f, item_type );
1835     RB_Generate_Item_Begin( f, name );
1836     for ( line_nr = 0; line_nr < cur_item->no_lines; ++line_nr )
1837     {
1838         struct RB_Item_Line *item_line = cur_item->lines[line_nr];
1839         char               *line = item_line->line;
1840
1841         // Plain item lines
1842         if ( !Works_Like_SourceItem( item_type ) &&
1843              ( item_line->kind == ITEM_LINE_PLAIN ) )
1844         {
1845             Format_Line( f, item_line->format );
1846             Generate_Item_Line( f, line, item_type, docname, header );
1847         }
1848         // Last line
1849         else if ( item_line->kind == ITEM_LINE_END )
1850         {
1851             Format_Line( f, item_line->format );
1852         }
1853         // Normal Pipes
1854         else if ( !Works_Like_SourceItem( item_type ) &&
1855                   ( item_line->kind == ITEM_LINE_PIPE ) )
1856         {
1857             Format_Line( f, item_line->format );
1858             if ( item_line->pipe_mode == output_mode )
1859             {
1860                 Pipe_Line( f, line );
1861             }
1862         }
1863         // Tool start
1864         else if ( !Works_Like_SourceItem( item_type ) &&
1865                   ( item_line->kind == ITEM_LINE_TOOL_START ) )
1866         {
1867             Format_Line( f, item_line->format );
1868
1869             // Change to docdir
1870             RB_Change_To_Docdir( document );
1871
1872             // Open pipe to tool
1873             tool = Open_Pipe( line );
1874
1875             // Get back to working dir
1876             RB_Change_Back_To_CWD(  );
1877         }
1878         // Tool (or DOT) body
1879         else if ( !Works_Like_SourceItem( item_type ) &&
1880                   ( item_line->kind == ITEM_LINE_TOOL_BODY ) )
1881         {
1882             if ( tool != NULL )
1883             {
1884                 fprintf( tool, "%s\n", line );
1885             }
1886         }
1887         // Tool end
1888         else if ( !Works_Like_SourceItem( item_type ) &&
1889                   ( item_line->kind == ITEM_LINE_TOOL_END ) )
1890         {
1891             // Close pipe
1892             Close_Pipe( tool );
1893             tool = NULL;
1894         }
1895         // DOT start
1896         else if ( !Works_Like_SourceItem( item_type ) &&
1897                   ( item_line->kind == ITEM_LINE_DOT_START ) )
1898         {
1899             Format_Line( f, item_line->format );
1900
1901             // Get DOT file type
1902             dot_type = RB_Get_DOT_Type(  );
1903
1904             if ( dot_type )
1905             {
1906                 char                pipe_str[TEMP_BUF_SIZE];
1907
1908                 // Change to docdir
1909                 RB_Change_To_Docdir( document );
1910 #if defined(RB_MSVC)
1911                 sprintf( pipe_str,
1912                          "%s -T%s -o%s%d.%s", dot_name,
1913                          dot_type, DOT_GRAPH_NAME, dot_nr, dot_type );
1914 #else
1915                 snprintf( pipe_str, sizeof( pipe_str ),
1916                           "%s -T%s -o%s%d.%s", dot_name,
1917                           dot_type, DOT_GRAPH_NAME, dot_nr, dot_type );
1918 #endif
1919                 tool = Open_Pipe( pipe_str );
1920             }
1921         }
1922         // DOT end
1923         else if ( !Works_Like_SourceItem( item_type ) &&
1924                   ( item_line->kind == ITEM_LINE_DOT_END ) )
1925         {
1926             if ( tool )
1927             {
1928                 // Close pipe
1929                 Close_Pipe( tool );
1930                 tool = NULL;
1931
1932                 // Generate link to image
1933                 RB_Generate_DOT_Image_Link( f, dot_nr, dot_type );
1934
1935                 // Get back to working dir
1936                 RB_Change_Back_To_CWD(  );
1937
1938                 // Increment dot file number
1939                 dot_nr++;
1940             }
1941         }
1942         // DOT file include
1943         else if ( !Works_Like_SourceItem( item_type ) &&
1944                   ( item_line->kind == ITEM_LINE_DOT_FILE ) )
1945         {
1946             Format_Line( f, item_line->format );
1947
1948             // Get DOT file type
1949             dot_type = RB_Get_DOT_Type(  );
1950
1951             if ( dot_type )
1952             {
1953                 char                str[TEMP_BUF_SIZE];
1954
1955                 // Change to docdir
1956                 RB_Change_To_Docdir( document );
1957
1958 #if defined(RB_MSVC)
1959                 sprintf( str,
1960                          "%s -T%s \"%s/%s\" -o%s%d.%s", dot_name,
1961                          dot_type, RB_Get_Saved_CWD(  ), line,
1962                          DOT_GRAPH_NAME, dot_nr, dot_type );
1963 #else
1964                 snprintf( str, sizeof( str ),
1965                           "%s -T%s \"%s/%s\" -o%s%d.%s", dot_name,
1966                           dot_type, RB_Get_Saved_CWD(  ), line,
1967                           DOT_GRAPH_NAME, dot_nr, dot_type );
1968 #endif
1969                 system( str );
1970
1971                 // Generate link to image
1972                 RB_Generate_DOT_Image_Link( f, dot_nr, dot_type );
1973
1974                 // Get back to working dir
1975                 RB_Change_Back_To_CWD(  );
1976
1977                 // Increment dot file number
1978                 dot_nr++;
1979             }
1980         }
1981         // Exec item
1982         else if ( !Works_Like_SourceItem( item_type ) &&
1983                   ( item_line->kind == ITEM_LINE_EXEC ) )
1984         {
1985             Format_Line( f, item_line->format );
1986
1987             // Change to docdir
1988             RB_Change_To_Docdir( document );
1989
1990             // Execute line
1991             system( line );
1992
1993             // Get back to working dir
1994             RB_Change_Back_To_CWD(  );
1995         }
1996         // Source lines
1997         else if ( Works_Like_SourceItem( item_type ) )
1998         {
1999             Format_Line( f, item_line->format );
2000             Generate_Item_Line( f, line, item_type, docname, header );
2001         }
2002         else
2003         {
2004             /* This item line is ignored */
2005         }
2006     }
2007     RB_Generate_Item_End( f, name );
2008 }
2009
2010 /******/
2011
2012
2013 /****f* Generator/Generate_Header
2014  * FUNCTION
2015  *   Generate the documentation for all the items found in
2016  *   a header except for any items specified in
2017  *   configuration.ignore_items.
2018  * SYNOPSIS
2019  */
2020 static void Generate_Header(
2021     FILE *f,
2022     struct RB_Document *document,
2023     struct RB_header *header,
2024     char *docname )
2025 /*
2026  * INPUTS
2027  *   * f -- destination file
2028  *   * header -- header to be searched.
2029  *   * srcname -- name of the source file the header was found in.
2030  *   * document -- name of the documentation file.
2031  * BUGS
2032  *   This skips the first item body if the first item name was
2033  *   not correctly spelled.
2034  * SOURCE
2035  */
2036 {
2037     struct RB_Item     *cur_item;
2038
2039     for ( cur_item = header->items; cur_item; cur_item = cur_item->next )
2040     {
2041         enum ItemType       item_type = cur_item->type;
2042         char               *name = configuration.items.names[item_type];
2043
2044         if ( Is_Ignore_Item( name ) )
2045         {
2046             /* User does not want this item */
2047         }
2048         else if ( Works_Like_SourceItem( item_type )
2049                   && ( course_of_action.do_nosource ) )
2050         {
2051             /* User does not want source items */
2052         }
2053         else
2054         {
2055             Generate_Item( f, document, header, cur_item, docname );
2056         }
2057     }
2058 }
2059
2060 /******/
2061
2062
2063 static void Pipe_Line(
2064     FILE *dest_doc,
2065     char *arg_line )
2066 {
2067     char               *cur_char = arg_line;
2068
2069     for ( ; *cur_char && ( *cur_char == ' ' || *cur_char == '\t' );
2070           cur_char++ )
2071     {
2072         fputc( *cur_char, dest_doc );
2073     }
2074     fprintf( dest_doc, "%s%s", cur_char,
2075              ( output_mode == RTF ? "\\line" : "\n" ) );
2076 }
2077
2078
2079 static void Format_Line(
2080     FILE *dest_doc,
2081     long format )
2082 {
2083     if ( format & RBILA_END_LIST_ITEM )
2084     {
2085         Generate_End_List_Item( dest_doc );
2086     }
2087     if ( format & RBILA_END_LIST )
2088     {
2089         Generate_End_List( dest_doc );
2090     }
2091     if ( format & RBILA_END_PRE )
2092     {
2093         Generate_End_Preformatted( dest_doc );
2094     }
2095     if ( format & RBILA_BEGIN_PARAGRAPH )
2096     {
2097         Generate_Begin_Paragraph( dest_doc );
2098     }
2099     if ( format & RBILA_END_PARAGRAPH )
2100     {
2101         Generate_End_Paragraph( dest_doc );
2102     }
2103     if ( format & RBILA_BEGIN_PRE )
2104     {
2105         Generate_Begin_Preformatted( dest_doc,
2106                                      ( format & RBILA_BEGIN_SOURCE ) );
2107     }
2108     if ( format & RBILA_BEGIN_LIST )
2109     {
2110         Generate_Begin_List( dest_doc );
2111     }
2112     if ( format & RBILA_BEGIN_LIST_ITEM )
2113     {
2114         Generate_Begin_List_Item( dest_doc );
2115     }
2116 }
2117
2118
2119
2120 static void Generate_Begin_List_Item(
2121     FILE *dest_doc )
2122 {
2123     switch ( output_mode )
2124     {
2125     case TEST:
2126         TEST_Generate_Begin_List_Item( dest_doc );
2127         break;
2128     case XMLDOCBOOK:
2129         XMLDB_Generate_Begin_List_Item( dest_doc );
2130         break;
2131     case HTML:
2132         HTML_Generate_Begin_List_Item( dest_doc );
2133         break;
2134     case LATEX:
2135         LaTeX_Generate_Begin_List_Item( dest_doc );
2136         break;
2137     case RTF:
2138         break;
2139     case TROFF:
2140         TROFF_Generate_Begin_List_Item( dest_doc );
2141         break;
2142         break;
2143     case ASCII:
2144         break;
2145     case UNKNOWN:
2146     default:
2147         assert( 0 );
2148     }
2149 }
2150
2151
2152 static void Generate_End_List_Item(
2153     FILE *dest_doc )
2154 {
2155     switch ( output_mode )
2156     {
2157     case TEST:
2158         TEST_Generate_End_List_Item( dest_doc );
2159         break;
2160     case XMLDOCBOOK:
2161         XMLDB_Generate_End_List_Item( dest_doc );
2162         break;
2163     case HTML:
2164         HTML_Generate_End_List_Item( dest_doc );
2165         break;
2166     case LATEX:
2167         LaTeX_Generate_End_List_Item( dest_doc );
2168         break;
2169     case RTF:
2170         break;
2171     case TROFF:
2172         TROFF_Generate_End_List_Item( dest_doc );
2173         break;
2174         break;
2175     case ASCII:
2176         break;
2177     case UNKNOWN:
2178     default:
2179         assert( 0 );
2180     }
2181 }
2182
2183
2184 static void Generate_Begin_List(
2185     FILE *dest_doc )
2186 {
2187     switch ( output_mode )
2188     {
2189     case TEST:
2190         TEST_Generate_Begin_List( dest_doc );
2191         break;
2192     case XMLDOCBOOK:
2193         XMLDB_Generate_Begin_List( dest_doc );
2194         break;
2195     case HTML:
2196         HTML_Generate_Begin_List( dest_doc );
2197         break;
2198     case LATEX:
2199         LaTeX_Generate_Begin_List( dest_doc );
2200         break;
2201
2202     case RTF:
2203     case TROFF:
2204     case ASCII:
2205         break;
2206
2207     case UNKNOWN:
2208     default:
2209         assert( 0 );
2210     }
2211 }
2212
2213 /* TODO FS Document */
2214
2215 static void Generate_End_List(
2216     FILE *dest_doc )
2217 {
2218     switch ( output_mode )
2219     {
2220     case TEST:
2221         TEST_Generate_End_List( dest_doc );
2222         break;
2223     case XMLDOCBOOK:
2224         XMLDB_Generate_End_List( dest_doc );
2225         break;
2226     case HTML:
2227         HTML_Generate_End_List( dest_doc );
2228         break;
2229     case LATEX:
2230         LaTeX_Generate_End_List( dest_doc );
2231         break;
2232
2233     case RTF:
2234     case TROFF:
2235     case ASCII:
2236         break;
2237
2238     case UNKNOWN:
2239     default:
2240         assert( 0 );
2241     }
2242 }
2243
2244
2245 /* TODO FS Document */
2246
2247 static void Generate_Begin_Preformatted(
2248     FILE *dest_doc,
2249     int source )
2250 {
2251     switch ( output_mode )
2252     {
2253     case TEST:
2254         TEST_Generate_Begin_Preformatted( dest_doc );
2255         break;
2256     case XMLDOCBOOK:
2257         XMLDB_Generate_Begin_Preformatted( dest_doc );
2258         break;
2259     case HTML:
2260         HTML_Generate_Begin_Preformatted( dest_doc, source );
2261         break;
2262     case LATEX:
2263         LaTeX_Generate_Begin_Preformatted( dest_doc );
2264         break;
2265     case RTF:
2266         break;
2267     case TROFF:
2268         TROFF_Generate_Begin_Preformatted( dest_doc );
2269         break;
2270     case ASCII:
2271         break;
2272     case UNKNOWN:
2273     default:
2274         assert( 0 );
2275     }
2276 }
2277
2278
2279 /* TODO FS Document */
2280 static void Generate_End_Preformatted(
2281     FILE *dest_doc )
2282 {
2283     switch ( output_mode )
2284     {
2285     case TEST:
2286         TEST_Generate_End_Preformatted( dest_doc );
2287         break;
2288     case XMLDOCBOOK:
2289         XMLDB_Generate_End_Preformatted( dest_doc );
2290         break;
2291     case HTML:
2292         HTML_Generate_End_Preformatted( dest_doc );
2293         break;
2294     case LATEX:
2295         LaTeX_Generate_End_Preformatted( dest_doc );
2296         break;
2297     case RTF:
2298         break;
2299     case TROFF:
2300         TROFF_Generate_End_Preformatted( dest_doc );
2301         break;
2302     case ASCII:
2303         break;
2304     case UNKNOWN:
2305     default:
2306         assert( 0 );
2307     }
2308 }
2309
2310
2311 /* TODO FS Document */
2312 static void Generate_End_Paragraph(
2313     FILE *dest_doc )
2314 {
2315     switch ( output_mode )
2316     {
2317     case TEST:
2318         TEST_Generate_End_Paragraph( dest_doc );
2319         break;
2320     case XMLDOCBOOK:
2321         XMLDB_Generate_End_Paragraph( dest_doc );
2322         break;
2323     case HTML:
2324         HTML_Generate_End_Paragraph( dest_doc );
2325         break;
2326     case LATEX:
2327         LaTeX_Generate_End_Paragraph( dest_doc );
2328         break;
2329     case RTF:
2330         break;
2331     case TROFF:
2332         TROFF_Generate_End_Paragraph( dest_doc );
2333         break;
2334     case ASCII:
2335         break;
2336     case UNKNOWN:
2337     default:
2338         assert( 0 );
2339     }
2340 }
2341
2342
2343 /* TODO FS Document */
2344 static void Generate_Begin_Paragraph(
2345     FILE *dest_doc )
2346 {
2347     switch ( output_mode )
2348     {
2349     case TEST:
2350         TEST_Generate_Begin_Paragraph( dest_doc );
2351         break;
2352     case XMLDOCBOOK:
2353         XMLDB_Generate_Begin_Paragraph( dest_doc );
2354         break;
2355     case HTML:
2356         HTML_Generate_Begin_Paragraph( dest_doc );
2357         break;
2358     case LATEX:
2359         LaTeX_Generate_Begin_Paragraph( dest_doc );
2360         break;
2361     case RTF:
2362         break;
2363     case TROFF:
2364         TROFF_Generate_Begin_Paragraph( dest_doc );
2365         break;
2366     case ASCII:
2367         break;
2368     case UNKNOWN:
2369     default:
2370         assert( 0 );
2371     }
2372 }
2373
2374
2375 #if 0
2376 /*x**f* Generator/RB_Generate_Empty_Item
2377  * FUNCTION
2378  *   Generate documentation for an item with an empty body.
2379  * INPUTS
2380  *   dest_doc -- destination file.
2381  ****
2382  * TODO Documentation
2383  */
2384
2385 static void RB_Generate_Empty_Item(
2386     FILE *dest_doc )
2387 {
2388     switch ( output_mode )
2389     {
2390     case TEST:
2391         break;
2392     case XMLDOCBOOK:
2393         break;
2394     case HTML:
2395         RB_HTML_Generate_Empty_Item( dest_doc );
2396         break;
2397     case LATEX:
2398         RB_LaTeX_Generate_Empty_Item( dest_doc );
2399         break;
2400     case RTF:
2401         RB_RTF_Generate_Empty_Item( dest_doc );
2402         break;
2403     case TROFF:
2404         break;
2405     case ASCII:
2406         RB_ASCII_Generate_Empty_Item( dest_doc );
2407         break;
2408     case UNKNOWN:
2409     default:
2410         assert( 0 );
2411     }
2412 }
2413 #endif
2414
2415
2416
2417 static void Generate_Item_Line(
2418     FILE *dest_doc,
2419     char *line,
2420     int item_type,
2421     char *docname,
2422     struct RB_header *fnames )
2423 {
2424     char               *cur_char = line;
2425     char               *object_name = NULL;
2426     char               *label_name = NULL;
2427     char               *file_name = NULL;
2428
2429     enum EIL_State
2430     { SKIP_ALPHANUM, SKIP_SPACE, SEARCH_LINK_START_WORD, SEARCH_LINK }
2431     state = SKIP_SPACE;
2432
2433     for ( ; *cur_char; cur_char++ )
2434     {
2435         char                c = *cur_char;
2436
2437         /* This is a little statemachine to switch searching for
2438          * links on and off.  A link can be found for a word
2439          * or for a word combined with some punctuation
2440          * characters.  A word is a string of alpha numeric
2441          * characters (including a '_'),  say FunctionAA_10_B
2442          * All other characters are punctuation characters.
2443          * We do not want links to start in the middle of a word,
2444          * but they can start after or on a punctuation character.
2445          * So for a link can start at
2446          *     Foo_bar::SnaFu
2447          *     ^      ^^^
2448          *     |      |||
2449          *
2450          */
2451
2452         /* Move to the next state based on current character.  */
2453         switch ( state )
2454         {
2455         case SKIP_SPACE:
2456             /* In this state we try to skip of a string of space
2457              * characters until we find something else.
2458              */
2459             {
2460                 if ( utf8_ispunct( c ) )
2461                 {
2462                     /* we were in the process of skipping spaces,
2463                      * but now we found a non-space character.
2464                      * This might be the begin of a link, so
2465                      * switch to the search link state.
2466                      */
2467                     state = SEARCH_LINK;
2468                 }
2469                 else if ( utf8_isalnum( c ) || ( c == '_' ) )
2470                 {
2471                     state = SEARCH_LINK_START_WORD;
2472                 }
2473                 else
2474                 {
2475                     /* Links can only start with a none space character,
2476                      * so if the current charater is a space, we skip it.
2477                      */
2478                 }
2479                 break;
2480             }
2481         case SKIP_ALPHANUM:
2482             /* In this state we skipping a string of alpha
2483              * numeric charaters after that the first
2484              * character in this string did not result in a
2485              * link.
2486              */
2487             {
2488                 if ( utf8_isspace( c ) )
2489                 {
2490                     /* We found the end of the string, so we go 
2491                      * back to the space skipping state
2492                      */
2493                     state = SKIP_SPACE;
2494                 }
2495                 else if ( utf8_ispunct( c ) && ( c != '_' ) )
2496                 {
2497                     /* We found a puntuation character, this end
2498                      * the string of alpha numeric character, but
2499                      * can be the begin of a new link, so we
2500                      * switch to the seach link state.
2501                      */
2502                     state = SEARCH_LINK;
2503                 }
2504                 else
2505                 {
2506                     /* We stay in this state */
2507                 }
2508             }
2509             break;
2510         case SEARCH_LINK_START_WORD:
2511             /* In this state we are at the start of a string
2512              * of alpha numeric characters.
2513              */
2514             {
2515                 if ( utf8_isalnum( c ) || ( c == '_' ) )
2516                 {
2517                     /* We are not at the second character of
2518                      * a string of alpha numeric characters,
2519                      * we can stop searching for links, as a
2520                      * link can only start at the begin of
2521                      * such a string.
2522                      */
2523                     state = SKIP_ALPHANUM;
2524                 }
2525                 else if ( utf8_ispunct( c ) && ( c != '_' ) )
2526                 {
2527                     state = SEARCH_LINK;
2528                 }
2529                 else if ( utf8_isspace( c ) )
2530                 {
2531                     state = SKIP_SPACE;
2532                 }
2533                 else
2534                 {
2535                     state = SKIP_SPACE;
2536                 }
2537             }
2538             break;
2539         case SEARCH_LINK:
2540             {
2541                 /* In this state we search for links. We stop
2542                  * searching if we encounter a space because this
2543                  * marks end of the word,
2544                  */
2545                 if ( utf8_isalnum( c ) || ( c == '_' ) )
2546                 {
2547                     /* We are at the start of a word.
2548                      */
2549                     state = SEARCH_LINK_START_WORD;
2550                 }
2551                 else if ( utf8_isspace( c ) )
2552                 {
2553                     state = SKIP_SPACE;
2554                 }
2555                 else
2556                 {
2557                     /* We stay in this state */
2558                 }
2559             }
2560             break;
2561         default:
2562             assert( 0 );
2563             break;
2564         }
2565
2566         if ( ( ( state == SEARCH_LINK ) ||
2567                ( state == SEARCH_LINK_START_WORD ) ) &&
2568              Find_Link( cur_char, &object_name, &label_name, &file_name ) )
2569         {
2570             /* We found a link, so we can stop searching for one
2571              * for now.
2572              */
2573             state = SKIP_SPACE;
2574
2575             if ( object_name && fnames->no_names > 0 )
2576             {
2577                 extern char        *function_name(
2578     char * );
2579                 int                 i;
2580
2581                 for ( i = 0; i < fnames->no_names; i++ )
2582                     if ( strcmp
2583                          ( object_name,
2584                            function_name( fnames->names[i] ) ) == 0 )
2585                         break;
2586                 if ( i < fnames->no_names )
2587                 {
2588                     RB_Generate_False_Link( dest_doc, object_name );
2589                     cur_char += strlen( object_name ) - 1;
2590                 }
2591                 else
2592                 {
2593                     Generate_Link( dest_doc, docname,
2594                                    file_name, label_name, object_name );
2595                     cur_char += strlen( object_name ) - 1;
2596                 }
2597             }
2598             else
2599             {
2600                 assert( 0 );
2601             }
2602         }
2603         else
2604         {
2605             int                 res =
2606                 RB_HTML_Extra( dest_doc, item_type, cur_char,
2607                                ( cur_char == line ) ? 0 : *( cur_char - 1 ) );
2608
2609             if ( res >= 0 )
2610             {
2611                 cur_char += res;
2612             }
2613             else
2614             {
2615                 /* convert from signed to unsigned */
2616                 unsigned char       c2 = *cur_char;
2617
2618                 Generate_Char( dest_doc, c2 );
2619             }
2620         }
2621     }
2622
2623     /* TODO Move to the RTF_Generator */
2624     switch ( output_mode )
2625     {
2626     case RTF:
2627         fprintf( dest_doc, "\\line" );
2628         break;
2629
2630     case TROFF:
2631         RB_TROFF_Start_New_Line( dest_doc );
2632         break;
2633
2634     case HTML:
2635         // Check for source line comment endings
2636         RB_HTML_Generate_Line_Comment_End( dest_doc );
2637         break;
2638
2639     case TEST:
2640     case ASCII:
2641     case LATEX:
2642     case XMLDOCBOOK:
2643     case UNKNOWN:
2644         break;
2645     default:
2646         break;
2647     }
2648
2649     /* For all modes we add a newline. */
2650     fputc( '\n', dest_doc );
2651 }
2652
2653
2654
2655 /****f* Generator/Generate_Link
2656  * FUNCTION
2657  *   Generate a link to another headers documentation.
2658  * SYNOPSIS
2659  */
2660 void Generate_Link(
2661     FILE *dest_doc,
2662     char *docname,
2663     char *file_name,
2664     char *label_name,
2665     char *function_name )
2666 /*
2667  * INPUTS
2668  *   * dest_doc      -- the output file
2669  *   * docname       -- the name of the output file
2670  *   * file_name     -- the name of the file that contains the link's body
2671  *   * label_name    -- the label for the link
2672  *   * function_name -- the name that is shown for the link in the
2673  *                      documentation
2674  * SOURCE
2675  */
2676 {
2677
2678     switch ( output_mode )
2679     {
2680     case TEST:
2681         RB_TEST_Generate_Link( dest_doc, docname, file_name, label_name,
2682                                function_name );
2683         break;
2684     case XMLDOCBOOK:
2685         RB_XMLDB_Generate_Link( dest_doc, docname, file_name, label_name,
2686                                 function_name );
2687         break;
2688     case HTML:
2689         RB_HTML_Generate_Link( dest_doc, docname, file_name, label_name,
2690                                function_name, NULL );
2691         break;
2692     case RTF:
2693         RB_RTF_Generate_Link( dest_doc, docname, file_name, label_name,
2694                               function_name );
2695         break;
2696     case LATEX:
2697         RB_LaTeX_Generate_String( dest_doc, function_name );
2698         /* lowtexx 21.09.2005 11:43 */
2699         /* generate a simple link here */
2700         RB_LaTeX_Generate_Link( dest_doc, docname, file_name, label_name,
2701                                 function_name );
2702         break;
2703     case UNKNOWN:
2704     case ASCII:
2705     case TROFF:
2706     default:
2707         fprintf( dest_doc, "%s", function_name );
2708     }
2709 }
2710
2711 /******/
2712
2713
2714 /****f* Generator/Generate_Char
2715  * FUNCTION
2716  *   Generate a single character in the current output mode.
2717  *   The individual generators will make sure that special
2718  *   characters are escaped.
2719  * SYNOPSIS
2720  */
2721 void Generate_Char(
2722     FILE *dest_doc,
2723     int cur_char )
2724 /*
2725  * INPUTS
2726  *   * dest_doc -- destination file.
2727  *   * cur_char -- character to be generated.
2728  *******
2729  */
2730 {
2731     switch ( output_mode )
2732     {
2733     case TEST:
2734         RB_TEST_Generate_Char( dest_doc, cur_char );
2735         break;
2736     case XMLDOCBOOK:
2737         RB_XMLDB_Generate_Char( dest_doc, cur_char );
2738         break;
2739     case HTML:
2740         RB_HTML_Generate_Char( dest_doc, cur_char );
2741         break;
2742     case LATEX:
2743         RB_LaTeX_Generate_Char( dest_doc, cur_char );
2744         break;
2745     case RTF:
2746         RB_RTF_Generate_Char( dest_doc, cur_char );
2747         break;
2748     case TROFF:
2749         RB_TROFF_Generate_Char( dest_doc, cur_char );
2750         break;
2751     case ASCII:
2752         RB_ASCII_Generate_Char( dest_doc, cur_char );
2753         break;
2754     case UNKNOWN:
2755     default:
2756         assert( 0 );
2757     }
2758 }
2759
2760
2761 /****f* Generator/RB_Get_SubIndex_FileName
2762  * FUNCTION
2763  *   Get the name of the master index file for a specific
2764  *   header_type.
2765  * SYNOPSIS
2766  */
2767 char               *RB_Get_SubIndex_FileName(
2768     char *docroot,
2769     char *extension,
2770     struct RB_HeaderType *header_type )
2771 /*
2772  * INPUTS
2773  *   * docroot      -- the path to the documentation directory.
2774  *   * extension    -- the extension for the file
2775  *   * header_type  -- the header type
2776  * RESULT
2777  *   a pointer to a freshly allocated string.
2778  * NOTES
2779  *   Has too many parameters.
2780  * SOURCE
2781  */
2782 {
2783     size_t              l;
2784     char               *filename;
2785
2786     assert( docroot );
2787
2788     l = strlen( docroot );
2789
2790     l += RB_Get_Len_Extension( extension );
2791     l += strlen( docroot );
2792     l += strlen( header_type->fileName );
2793
2794     filename = ( char * ) malloc( l + 2 );
2795     assert( filename );
2796     filename[0] = '\0';
2797
2798     strcat( filename, docroot );
2799     strcat( filename, header_type->fileName );
2800     RB_Add_Extension( extension, filename );
2801
2802     return filename;
2803 }
2804
2805 /*****/
2806
2807
2808 /****f* Generator/Generate_Index
2809  * NAME
2810  *   Generate_Index -- generate index file based on xref files.
2811  * SYNOPSIS
2812  */
2813 static void Generate_Index(
2814     struct RB_Document *document )
2815 /*
2816  * FUNCTION
2817  *   Create a master index file. It contains pointers to the
2818  *   documentation generated for each source file, as well as all
2819  *   "objects" found in the source files.
2820  * SOURCE
2821  */
2822 {
2823     switch ( output_mode )
2824     {
2825     case TEST:
2826         break;
2827     case XMLDOCBOOK:
2828         break;
2829     case HTML:
2830         RB_HTML_Generate_Index( document );
2831         break;
2832     case LATEX:
2833         /* RB_LaTeX_Generate_Index(dest, source); */
2834         /* Latex has a index by default */
2835         break;
2836     case UNKNOWN:
2837     case ASCII:
2838     case TROFF:
2839     case RTF:
2840     default:
2841         break;
2842     }
2843 }
2844
2845 /*****/