Added options to make Robodoc more customizable.
[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_Header_IndexMenu(
1003     FILE *dest_doc,
1004     char *filename,
1005     struct RB_Part *owner,
1006     struct RB_Document *document )
1007 {
1008     switch ( output_mode )
1009     {
1010     case HTML:
1011         RB_HTML_Generate_Header_IndexMenu( dest_doc, filename,
1012                                            document, owner, NULL );
1013         break;
1014     default:
1015         break;
1016     }
1017
1018 }
1019
1020 void Generate_Module_IndexMenu(
1021     FILE *dest_doc,
1022     char *filename,
1023     struct RB_Document *document )
1024 {
1025     switch ( output_mode )
1026     {
1027     case HTML:
1028         RB_HTML_Generate_Module_IndexMenu( dest_doc, filename,
1029                                            document, NULL );
1030         break;
1031     default:
1032         break;
1033     }
1034
1035 }
1036
1037 void Generate_Begin_Extra(
1038     FILE *dest_doc )
1039 {
1040     switch ( output_mode )
1041     {
1042     case HTML:
1043         HTML_Generate_Begin_Extra( dest_doc );
1044         break;
1045     default:
1046         break;
1047     }
1048 }
1049
1050 void Generate_End_Extra(
1051     FILE *dest_doc )
1052 {
1053     switch ( output_mode )
1054     {
1055     case HTML:
1056         HTML_Generate_End_Extra( dest_doc );
1057         break;
1058     default:
1059         break;
1060     }
1061 }
1062
1063
1064
1065
1066
1067
1068 /* TODO Documentation */
1069 void RB_Generate_Nav_Bar(
1070     struct RB_Document *document,
1071     FILE *current_doc,
1072     struct RB_header *current_header )
1073 {
1074     switch ( output_mode )
1075     {
1076     case TEST:
1077         break;
1078     case XMLDOCBOOK:
1079         break;
1080     case HTML:
1081       if ( course_of_action.do_one_file_per_header )
1082         {
1083             /* Nothing */
1084         }
1085         else
1086         {
1087             RB_HTML_Generate_Nav_Bar( document, current_doc, current_header );
1088         }
1089         break;
1090     case LATEX:
1091         break;
1092     case RTF:
1093         break;
1094     case ASCII:
1095         break;
1096     case TROFF:
1097         break;
1098     case UNKNOWN:
1099     default:
1100         /* Bug */
1101         assert( 0 );
1102     }
1103 }
1104
1105
1106
1107 /* TODO Documentation */
1108 int RB_HTML_Extra(
1109     FILE *dest_doc,
1110     int item_type,
1111     char *cur_char,
1112     char prev_char )
1113 {
1114     int                 res = -1;
1115
1116     switch ( output_mode )
1117     {
1118     case TEST:
1119         break;
1120     case XMLDOCBOOK:
1121         break;
1122     case HTML:
1123         res =
1124             RB_HTML_Generate_Extra( dest_doc, item_type, cur_char,
1125                                     prev_char );
1126         break;
1127     case LATEX:
1128         /* TODO */
1129         break;
1130     case RTF:
1131         /* TODO */
1132         break;
1133     case ASCII:
1134         /* TODO */
1135         break;
1136     case TROFF:
1137         res = RB_TROFF_Generate_Extra( dest_doc, item_type, cur_char );
1138         break;
1139         break;
1140     case UNKNOWN:
1141     default:
1142         /* Bug */
1143         assert( 0 );
1144     }
1145     return res;
1146 }
1147
1148
1149 /****f* Generator/RB_Name_Headers
1150  * FUNCTION
1151  *   Give all headers a unique name. This makes sure that if
1152  *   two headers have the same name linking to one of the headers
1153  *   still works.
1154  * SYNOPSIS
1155  */
1156 void RB_Name_Headers(
1157     struct RB_header **headers,
1158     long count )
1159 /*
1160  * SOURCE
1161  */
1162 #define MAX_UNIQUE_ID_LENGTH 80
1163 {
1164     int                 i;
1165     char                id[MAX_UNIQUE_ID_LENGTH + 1];
1166
1167     RB_Say( "Assigning headers a unique name.\n", SAY_DEBUG );
1168     for ( i = 0; i < count; ++i )
1169     {
1170         struct RB_header   *header;
1171
1172         header = headers[i];
1173         sprintf( id, "robo%d", i );
1174         header->unique_name = RB_StrDup( id );
1175     }
1176 }
1177
1178 /******/
1179
1180 /****f* Generator/RB_Sort_Items
1181  * FUNCTION
1182  *   Sort the items in all the headers according to the order
1183  *   specified in the 'item order' block in the robodoc.rc
1184  *   file.
1185  * SYNOPSIS
1186  */
1187 static void RB_Sort_Items(
1188     struct RB_header **headers,
1189     long header_count )
1190 /*
1191  * SOURCE
1192  */
1193 {
1194     int                 n_order = configuration.item_order.number;
1195
1196     if ( n_order )
1197     {
1198         int                 i = 0;
1199         int                 j = 0;
1200         int                 max_number_of_items = 0;
1201         struct RB_Item    **items = NULL;
1202         struct RB_Item    **items_sorted = NULL;
1203
1204         RB_Say( "Sorting items in %d headers.\n", SAY_DEBUG, header_count );
1205
1206         /* Compute the maximum number of items in any given header */
1207         for ( j = 0; j < header_count; ++j )
1208         {
1209             struct RB_header   *header;
1210             struct RB_Item     *item;
1211             int                 item_count = 0;
1212
1213             header = headers[j];
1214             for ( item = header->items; item; item = item->next )
1215             {
1216                 ++item_count;
1217             }
1218
1219             if ( item_count > max_number_of_items )
1220             {
1221                 max_number_of_items = item_count;
1222             }
1223         }
1224         /* Allocate an array for the items, this makes it easier to
1225          * sort. */
1226
1227         RB_Say( "Largest header has %d items.\n", SAY_DEBUG,
1228                 max_number_of_items );
1229
1230         if ( max_number_of_items == 0 )
1231         {
1232             /* No items in any of the headers, do nothing */
1233         }
1234         else
1235         {
1236             items = calloc( max_number_of_items, sizeof( struct RB_Item * ) );
1237             items_sorted =
1238                 calloc( max_number_of_items, sizeof( struct RB_Item * ) );
1239
1240             /* Sort items */
1241             for ( j = 0; j < header_count; ++j )
1242             {
1243                 struct RB_header   *header = NULL;
1244                 struct RB_Item     *item = NULL;
1245                 int                 item_index = 0;
1246                 int                 sorted_item_index = 0;
1247                 int                 item_count = 0;
1248
1249                 header = headers[j];
1250
1251                 /* Copy item pointers to array */
1252                 for ( item = header->items; item;
1253                       item = item->next, ++item_index )
1254                 {
1255                     items[item_index] = item;
1256                     items_sorted[item_index] = item;
1257                 };
1258                 item_count = item_index;
1259
1260                 if ( item_count == 0 )
1261                 {
1262                     /* No items in this header, do nothing. */
1263                 }
1264                 else
1265                 {
1266                     assert( item_count <= max_number_of_items );
1267
1268                     /* First copy the items in the order that is defined in
1269                      * item_order[] to sorted_items[] */
1270                     sorted_item_index = 0;
1271                     for ( i = 0; i < n_order; ++i )
1272                     {
1273                         for ( item_index = 0; item_index < item_count;
1274                               ++item_index )
1275                         {
1276                             if ( items[item_index] )
1277                             {
1278                                 if ( strcmp
1279                                      ( configuration.items.
1280                                        names[items[item_index]->type],
1281                                        configuration.item_order.names[i] ) ==
1282                                      0 )
1283                                 {
1284                                     /* copy to items_sorted */
1285                                     items_sorted[sorted_item_index] =
1286                                         items[item_index];
1287                                     ++sorted_item_index;
1288                                     items[item_index] = NULL;
1289                                 }
1290                             }
1291                         }
1292                     }
1293                     /* Then copy the remaining items to items_sorted[] */
1294                     for ( item_index = 0; item_index < item_count;
1295                           ++item_index )
1296                     {
1297                         if ( items[item_index] )
1298                         {
1299                             /* copy to items_sorted */
1300                             items_sorted[sorted_item_index] =
1301                                 items[item_index];
1302                             ++sorted_item_index;
1303                             items[item_index] = NULL;
1304                         }
1305                     }
1306
1307                     assert( sorted_item_index == item_count );
1308
1309                     /* Now copy the items in items_sorted[] back into the linked list in
1310                      * the header */
1311                     if ( item_count > 1 )
1312                     {
1313                         /* Chain all the items */
1314                         for ( item_index = 0; item_index < item_count - 1;
1315                               ++item_index )
1316                         {
1317                             items_sorted[item_index]->next =
1318                                 items_sorted[item_index + 1];
1319                         }
1320                     }
1321
1322                     assert( item_count > 0 );
1323                     items_sorted[item_count - 1]->next = NULL;
1324                     /* now link the first item to the header. */
1325                     header->items = items_sorted[0];
1326                 }
1327             }
1328
1329             free( items_sorted );
1330             free( items );
1331         }
1332     }
1333
1334     RB_Say( "Done sorting items in %d headers.\n", SAY_DEBUG, header_count );
1335 }
1336
1337 /*******/
1338
1339
1340 /****f* Generator/RB_Generate_Documentation
1341  * FUNCTION
1342  *   Generate the documentation for all the information contained in a
1343  *   RB_Document structure.
1344  * SYNOPSIS
1345  */
1346 void RB_Generate_Documentation(
1347     struct RB_Document *document )
1348 /*
1349  * INPUTS
1350  *   document -- pointer to the RB_Document structure.
1351  * SOURCE
1352  */
1353 {
1354     RB_SetCurrentFile( NULL );
1355
1356
1357
1358     if ( document->actions.do_singledoc )
1359     {
1360         RB_Generate_SingleDoc( document );
1361     }
1362     else if ( document->actions.do_multidoc )
1363     {
1364         RB_Generate_MultiDoc( document );
1365     }
1366     else if ( document->actions.do_singlefile )
1367     {
1368         RB_Generate_SingleDoc( document );
1369     }
1370 }
1371
1372 /*****/
1373
1374 /****f* Generator/RB_Generate_MultiDoc
1375  * FUNCTION
1376  *   Create documentation by creating a file for each
1377  *   individual source file that was scanned.
1378  * SYNOPSIS
1379  */
1380 void RB_Generate_MultiDoc(
1381     struct RB_Document *document )
1382 /*
1383  * INPUTS
1384  *   document -- pointer to the RB_Document structure.
1385  * SOURCE
1386  */
1387 {
1388     struct RB_Part     *i_part;
1389     FILE               *document_file = NULL;
1390
1391     RB_Document_Determine_DocFilePaths( document );
1392     RB_Document_Create_DocFilePaths( document );
1393     if ( document->actions.do_one_file_per_header )
1394     {
1395         RB_Document_Split_Parts( document );
1396     }
1397     RB_Document_Determine_DocFileNames( document );
1398     RB_Document_Collect_Headers( document );
1399     if ( document->actions.do_nosort )
1400     {
1401         /* Nothing */
1402     }
1403     else
1404     {
1405         RB_Document_Sort_Headers( document );
1406     }
1407     RB_Document_Link_Headers( document );
1408     RB_Fill_Header_Filename( document );
1409     RB_Name_Headers( document->headers, document->no_headers );
1410     RB_Sort_Items( document->headers, document->no_headers );
1411     RB_CollectLinks( document, document->headers, document->no_headers );
1412     if ( output_mode == HTML )
1413     {
1414         RB_Create_CSS( document );
1415     }
1416
1417
1418     for ( i_part = document->parts; i_part != NULL; i_part = i_part->next )
1419     {
1420
1421         char               *srcname = Get_Fullname( i_part->filename );
1422         char               *docname = RB_Get_FullDocname( i_part->filename );
1423
1424         /* Nothing found in this part, do not generate it */
1425         if ( i_part->headers == 0 )
1426             continue;
1427
1428         if ( output_mode != TROFF )
1429         {
1430             document_file = RB_Open_Documentation( i_part );
1431             RB_Generate_Doc_Start( document,
1432                                    document_file, srcname,
1433                                    i_part->filename->name, 1,
1434                                    docname, document->charset );
1435
1436             Generate_Begin_Navigation( document_file );
1437             if ( document->actions.do_one_file_per_header )
1438             {
1439                 if ( document->actions.do_module_index_menu )
1440                 {
1441                     if ( i_part->headers[0].htype->typeCharacter == 'h' )
1442                         Generate_Module_IndexMenu( document_file, docname,
1443                                                    document );
1444                     else
1445                         Generate_Header_IndexMenu( document_file, docname,
1446                                                    i_part, document );
1447                 }
1448                 else
1449                 {
1450                     RB_HTML_Generate_Nav_Bar_One_File_Per_Header( document,
1451                                                                   document_file,
1452                                                                   i_part->
1453                                                                   headers );
1454                 }
1455             }
1456             else
1457             {
1458                 Generate_IndexMenu( document_file, docname, document );
1459             }
1460             Generate_End_Navigation( document_file );
1461
1462             Generate_Begin_Content( document_file );
1463
1464             if ( ( document->actions.do_toc ) && document->no_headers )
1465             {
1466                 RB_Generate_TOC_2( document_file,
1467                                    document->headers, document->no_headers,
1468                                    i_part, docname );
1469             }
1470             RB_Generate_Part( document_file, document, i_part );
1471
1472             if ( document->actions.do_header_toc && output_mode == HTML )
1473               {
1474                 if ( document->actions.do_one_file_per_header &&
1475                      i_part->headers[0].htype->typeCharacter == 'h' )
1476                     RB_HTML_Generate_TOC_Entries( document_file,
1477                                                   document->headers,
1478                                                   document->no_headers,
1479                                                   i_part, docname );
1480               }
1481
1482             Generate_End_Content( document_file );
1483
1484             RB_Generate_Doc_End( document_file, docname, srcname );
1485             fclose( document_file );
1486         }
1487         else
1488         {
1489             RB_Generate_Part( document_file, document, i_part );
1490         }
1491     }
1492
1493     if ( document->actions.do_index )
1494     {
1495         Generate_Index( document );
1496     }
1497
1498     RB_Free_Links(  );
1499 }
1500
1501 /*****/
1502
1503
1504 /****f* Generator/RB_Generate_SingleDoc
1505  * FUNCTION
1506  *   Create documentation by creating a single file for all individual
1507  *   source file that were scanned.
1508  *
1509  *   This function is called when the option --singledoc is used.
1510  *   Based on whether the option --sections is used this function then
1511  *   calls RB_Generate_Sections or RB_Generate_Part
1512  * SYNOPSIS
1513  */
1514 void RB_Generate_SingleDoc(
1515     struct RB_Document *document )
1516 /*
1517  * INPUTS
1518  *   document -- pointer to the RB_Document structure.
1519  * SOURCE
1520  */
1521 {
1522     FILE               *document_file;
1523     struct RB_Part     *i_part;
1524
1525     RB_Document_Collect_Headers( document );
1526     if ( document->actions.do_nosort )
1527     {
1528         /* Nothing */
1529     }
1530     else
1531     {
1532         RB_Document_Sort_Headers( document );
1533     }
1534     RB_Document_Link_Headers( document );
1535     RB_Fill_Header_Filename( document );
1536     RB_Name_Headers( document->headers, document->no_headers );
1537     RB_Sort_Items( document->headers, document->no_headers );
1538     RB_CollectLinks( document, document->headers, document->no_headers );
1539
1540     for ( i_part = document->parts; i_part != NULL; i_part = i_part->next )
1541     {
1542         RB_Set_FullDocname( i_part->filename, document->singledoc_name );
1543     }
1544
1545     if ( output_mode == HTML )
1546     {
1547         RB_Create_CSS( document );
1548     }
1549
1550     document_file = RB_Open_SingleDocumentation( document );
1551     assert( document->parts->filename->name );
1552
1553
1554     RB_Generate_Doc_Start( document,
1555                            document_file,
1556                            document->srcroot->name,
1557                            document->singledoc_name, 1,
1558                            document->singledoc_name, document->charset );
1559
1560     if ( ( document->actions.do_toc ) && document->no_headers )
1561     {
1562         RB_Generate_TOC_2( document_file,
1563                            document->headers, document->no_headers, NULL,
1564                            document->parts->filename->name );
1565     }
1566     if ( document->actions.do_sections )
1567     {
1568         RB_Generate_Sections( document_file, document );
1569     }
1570     else
1571     {
1572         for ( i_part = document->parts;
1573               i_part != NULL; i_part = i_part->next )
1574         {
1575             RB_Generate_Part( document_file, document, i_part );
1576         }
1577     }
1578
1579     if ( document->actions.do_header_toc && output_mode == HTML )
1580     {
1581         if ( i_part->headers[0].htype->typeCharacter == 'h' )
1582             RB_HTML_Generate_TOC_Entries( document_file,
1583                                           document->headers,
1584                                           document->no_headers,
1585                                           i_part,
1586                                           document->parts->filename->name );
1587     }
1588
1589     RB_Generate_Doc_End( document_file, "singledoc",
1590                          document->srcroot->name );
1591     fclose( document_file );
1592
1593     RB_Free_Links(  );
1594 }
1595
1596 /******/
1597
1598
1599 /****f* Generator/RB_Generate_Sections
1600  * FUNCTION
1601  *   Creates the documentation for all headers found in all source
1602  *   files.  The order in which they are generated depends on the
1603  *   header hierarchy.  First the top level header's documentation
1604  *   is generated then, the documentation for all it's childern, then
1605  *   the next top level header's documentation is generated.
1606  *   This is a recursive proces.
1607  *   The idea is to create something like:
1608  *     1. Parentheader1
1609  *     1.1 Child1
1610  *     1.2 Child2
1611  *     1.2.1 Child's child1
1612  *     2. Parentheader2
1613  *   etc
1614  * SYNOPSIS
1615  */
1616 void RB_Generate_Sections(
1617     FILE *document_file,
1618     struct RB_Document *document )
1619 /*
1620  * INPUTS
1621  *   o document_file -- destination file.
1622  *   o document -- pointer to the RB_Document structure.
1623  * SOURCE
1624  */
1625 {
1626     unsigned long       i;
1627     int                 depth = 1;
1628     struct RB_header   *header;
1629
1630     depth = document->first_section_level;
1631
1632     RB_Say( "Generating Sections\n", SAY_INFO );
1633     for ( i = 0; i < document->no_headers; ++i )
1634     {
1635         header = ( document->headers )[i];
1636         if ( header->parent )
1637         {
1638             /* This will be in one of the subsections */
1639         }
1640         else
1641         {
1642             RB_Generate_Section( document_file, header, document, depth );
1643         }
1644     }
1645 }
1646
1647 /******/
1648
1649
1650
1651 /****f* Generator/RB_Generate_Section
1652  * FUNCTION
1653  *   Generate the documentation for a header and all
1654  *   its childern.
1655  * INPUTS
1656  *   o document_file -- destination file
1657  *   o parent -- the parent of the header for which the documentation
1658  *               is to be generated.
1659  *   o document -- pointer to the RB_Document structure.
1660  *   o depth -- level of sectioning ( 1  1.1  1.1.1  etc)
1661  * SYNOPSIS
1662  */
1663 void RB_Generate_Section(
1664     FILE *document_file,
1665     struct RB_header *parent,
1666     struct RB_Document *document,
1667     int depth )
1668 /*
1669  * NOTE
1670  *   This is a recursive function.
1671  * SEE ALSO
1672  *    RB_Generate_Sections
1673  * SOURCE
1674  */
1675 {
1676     unsigned long       i;
1677     struct RB_header   *header;
1678     char               *headername;
1679
1680     // We pass either modulename/name or just the name
1681     if ( course_of_action.do_sectionnameonly )
1682     {
1683         headername = parent->function_name;
1684     }
1685     else
1686     {
1687         headername = parent->name;
1688     }
1689
1690     switch ( output_mode )
1691     {
1692     case XMLDOCBOOK:
1693         {
1694             RB_Generate_BeginSection( document_file, depth, headername,
1695                                       parent );
1696             /* Docbook output does not like the labels to be
1697              * generated before the <section> part
1698              */
1699             Generate_Label( document_file, parent->unique_name );
1700             Generate_Label( document_file, parent->name );
1701         }
1702         break;
1703         /* lowtexx 21.09.2005 11:37 */
1704     case LATEX:
1705         {
1706             RB_Generate_BeginSection( document_file, depth, headername,
1707                                       parent );
1708             /* We have to start section before labeling in latex */
1709             Generate_Label( document_file, parent->unique_name );
1710             Generate_Label( document_file, parent->name );
1711         }
1712         break;
1713         /* --- */
1714     default:
1715         {
1716             Generate_Label( document_file, parent->unique_name );
1717             Generate_Label( document_file, parent->name );
1718             RB_Generate_BeginSection( document_file, depth, headername,
1719                                       parent );
1720         }
1721         break;
1722     }
1723
1724     RB_Generate_Nav_Bar( document, document_file, parent );
1725     RB_Generate_Index_Entry( document_file, document->doctype, parent );
1726     Generate_Header( document_file, document, parent, "dummy" );
1727     for ( i = 0; i < document->no_headers; ++i )
1728     {
1729         header = ( document->headers )[i];
1730         if ( header->parent == parent )
1731         {
1732             RB_Generate_Section( document_file, header, document, depth + 1 );
1733         }
1734         else
1735         {
1736             /* Leeg */
1737         }
1738     }
1739     RB_Generate_EndSection( document_file, depth, parent->name );
1740 }
1741
1742 /******/
1743
1744
1745
1746 /****f* Generator/RB_Generate_Part
1747  * FUNCTION
1748  *   Generate the documention for all the headers found in a single
1749  *   source file.
1750  * SYNOPSIS
1751  */
1752 void RB_Generate_Part(
1753     FILE *document_file,
1754     struct RB_Document *document,
1755     struct RB_Part *part )
1756 /*
1757  * INPUTS
1758  *   * document_file -- The file were it stored.
1759  *   * document      -- All the documentation.
1760  *   * part          -- pointer to a RB_Part that contains all the headers found
1761  *                    in a single source file.
1762  * SOURCE
1763  */
1764 {
1765     struct RB_header   *i_header;
1766     char               *docname = NULL;
1767     char               *srcname = Get_Fullname( part->filename );
1768
1769     RB_Say( "generating documentation for file \"%s\"\n", SAY_INFO, srcname );
1770     if ( document->actions.do_singledoc )
1771     {
1772         docname = document->singledoc_name;
1773     }
1774     else if ( document->actions.do_multidoc )
1775     {
1776         docname = RB_Get_FullDocname( part->filename );
1777     }
1778     else if ( document->actions.do_singlefile )
1779     {
1780         docname = document->singledoc_name;
1781     }
1782     else
1783     {
1784         assert( 0 );
1785     }
1786
1787     if ( output_mode == TROFF )
1788     {
1789         RB_TROFF_Set_Param( document->compress, document->section );
1790     }
1791
1792     for ( i_header = part->headers; i_header; i_header = i_header->next )
1793     {
1794         RB_Say( "generating documentation for header \"%s\"\n", SAY_INFO,
1795                 i_header->name );
1796         document_file = RB_Generate_Header_Start( document_file, i_header );
1797         RB_Generate_Nav_Bar( document, document_file, i_header );
1798         RB_Generate_Index_Entry( document_file, document->doctype, i_header );
1799         Generate_Header( document_file, document, i_header, docname );
1800         RB_Generate_Header_End( document_file, i_header );
1801     }
1802 }
1803
1804 /******/
1805
1806
1807 /****f* Generator/RB_Get_DOT_Type
1808  * FUNCTION
1809  *   Returns the type of the DOT file for the given output mode
1810  * SOURCE
1811  */
1812 char               *RB_Get_DOT_Type(
1813     void )
1814 {
1815     switch ( output_mode )
1816     {
1817     case HTML:
1818         return DOT_HTML_TYPE;
1819         break;
1820
1821     case LATEX:
1822         return DOT_LATEX_TYPE;
1823         break;
1824
1825     default:
1826         break;
1827     }
1828
1829     return NULL;
1830 }
1831
1832 /******/
1833
1834
1835 /****f* Generator/RB_Generate_DOT_Image_Link
1836  * FUNCTION
1837  *   Generates the image link for the created dot graphics
1838  * SOURCE
1839  */
1840 void RB_Generate_DOT_Image_Link(
1841     FILE *f,
1842     int dot_nr,
1843     char *dot_type )
1844 {
1845     switch ( output_mode )
1846     {
1847     case HTML:
1848         fprintf( f, "<img src=\"%s%d.%s\">\n", DOT_GRAPH_NAME, dot_nr,
1849                  dot_type );
1850         break;
1851
1852     case LATEX:
1853         {
1854             char                str[TEMP_BUF_SIZE];
1855
1856             // First we need to convert graph to PDF
1857             // (maybe the user is using pdflatex)
1858 #if defined(RB_MSVC)
1859             sprintf( str, "%s %s%d.%s", EPSTOPDF_NAME,
1860                      DOT_GRAPH_NAME, dot_nr, dot_type );
1861 #else
1862             snprintf( str, sizeof( str ), "%s %s%d.%s", EPSTOPDF_NAME,
1863                       DOT_GRAPH_NAME, dot_nr, dot_type );
1864 #endif
1865             system( str );
1866
1867             fprintf( f, "\\includegraphics{%s%d}\n", DOT_GRAPH_NAME, dot_nr );
1868         }
1869         break;
1870
1871     default:
1872         break;
1873     }
1874 }
1875
1876 /******/
1877
1878 /****f* Generator/Generate_Item
1879  * SYNOPSIS
1880  */
1881 static void Generate_Item(
1882     FILE *f,
1883     struct RB_Document *document,
1884     struct RB_header *header,
1885     struct RB_Item *cur_item,
1886     char *docname )
1887  /*
1888   * FUNCTION
1889   *   Generate the documentation for a single item.
1890   * SOURCE
1891   */
1892 {
1893     static int          dot_nr = 1;
1894     int                 line_nr;
1895     char               *dot_type = NULL;
1896     FILE               *tool = NULL;    // Pipe handler to the tool we use
1897     enum ItemType       item_type = cur_item->type;
1898     char               *name = configuration.items.names[item_type];
1899
1900
1901     Generate_Item_Name( f, item_type );
1902     RB_Generate_Item_Begin( f, name );
1903     for ( line_nr = 0; line_nr < cur_item->no_lines; ++line_nr )
1904     {
1905         struct RB_Item_Line *item_line = cur_item->lines[line_nr];
1906         char               *line = item_line->line;
1907
1908         // Plain item lines
1909         if ( !Works_Like_SourceItem( item_type ) &&
1910              ( item_line->kind == ITEM_LINE_PLAIN ) )
1911         {
1912             Format_Line( f, item_line->format );
1913             Generate_Item_Line( f, line, item_type, docname, header );
1914         }
1915         // Last line
1916         else if ( item_line->kind == ITEM_LINE_END )
1917         {
1918             Format_Line( f, item_line->format );
1919         }
1920         // Normal Pipes
1921         else if ( !Works_Like_SourceItem( item_type ) &&
1922                   ( item_line->kind == ITEM_LINE_PIPE ) )
1923         {
1924             Format_Line( f, item_line->format );
1925             if ( item_line->pipe_mode == output_mode )
1926             {
1927                 Pipe_Line( f, line );
1928             }
1929         }
1930         // Tool start
1931         else if ( !Works_Like_SourceItem( item_type ) &&
1932                   ( item_line->kind == ITEM_LINE_TOOL_START ) )
1933         {
1934             Format_Line( f, item_line->format );
1935
1936             // Change to docdir
1937             RB_Change_To_Docdir( document );
1938
1939             // Open pipe to tool
1940             tool = Open_Pipe( line );
1941
1942             // Get back to working dir
1943             RB_Change_Back_To_CWD(  );
1944         }
1945         // Tool (or DOT) body
1946         else if ( !Works_Like_SourceItem( item_type ) &&
1947                   ( item_line->kind == ITEM_LINE_TOOL_BODY ) )
1948         {
1949             if ( tool != NULL )
1950             {
1951                 fprintf( tool, "%s\n", line );
1952             }
1953         }
1954         // Tool end
1955         else if ( !Works_Like_SourceItem( item_type ) &&
1956                   ( item_line->kind == ITEM_LINE_TOOL_END ) )
1957         {
1958             // Close pipe
1959             Close_Pipe( tool );
1960             tool = NULL;
1961         }
1962         // DOT start
1963         else if ( !Works_Like_SourceItem( item_type ) &&
1964                   ( item_line->kind == ITEM_LINE_DOT_START ) )
1965         {
1966             Format_Line( f, item_line->format );
1967
1968             // Get DOT file type
1969             dot_type = RB_Get_DOT_Type(  );
1970
1971             if ( dot_type )
1972             {
1973                 char                pipe_str[TEMP_BUF_SIZE];
1974
1975                 // Change to docdir
1976                 RB_Change_To_Docdir( document );
1977 #if defined(RB_MSVC)
1978                 sprintf( pipe_str,
1979                          "%s -T%s -o%s%d.%s", dot_name,
1980                          dot_type, DOT_GRAPH_NAME, dot_nr, dot_type );
1981 #else
1982                 snprintf( pipe_str, sizeof( pipe_str ),
1983                           "%s -T%s -o%s%d.%s", dot_name,
1984                           dot_type, DOT_GRAPH_NAME, dot_nr, dot_type );
1985 #endif
1986                 tool = Open_Pipe( pipe_str );
1987             }
1988         }
1989         // DOT end
1990         else if ( !Works_Like_SourceItem( item_type ) &&
1991                   ( item_line->kind == ITEM_LINE_DOT_END ) )
1992         {
1993             if ( tool )
1994             {
1995                 // Close pipe
1996                 Close_Pipe( tool );
1997                 tool = NULL;
1998
1999                 // Generate link to image
2000                 RB_Generate_DOT_Image_Link( f, dot_nr, dot_type );
2001
2002                 // Get back to working dir
2003                 RB_Change_Back_To_CWD(  );
2004
2005                 // Increment dot file number
2006                 dot_nr++;
2007             }
2008         }
2009         // DOT file include
2010         else if ( !Works_Like_SourceItem( item_type ) &&
2011                   ( item_line->kind == ITEM_LINE_DOT_FILE ) )
2012         {
2013             Format_Line( f, item_line->format );
2014
2015             // Get DOT file type
2016             dot_type = RB_Get_DOT_Type(  );
2017
2018             if ( dot_type )
2019             {
2020                 char                str[TEMP_BUF_SIZE];
2021
2022                 // Change to docdir
2023                 RB_Change_To_Docdir( document );
2024
2025 #if defined(RB_MSVC)
2026                 sprintf( str,
2027                          "%s -T%s \"%s/%s\" -o%s%d.%s", dot_name,
2028                          dot_type, RB_Get_Saved_CWD(  ), line,
2029                          DOT_GRAPH_NAME, dot_nr, dot_type );
2030 #else
2031                 snprintf( str, sizeof( str ),
2032                           "%s -T%s \"%s/%s\" -o%s%d.%s", dot_name,
2033                           dot_type, RB_Get_Saved_CWD(  ), line,
2034                           DOT_GRAPH_NAME, dot_nr, dot_type );
2035 #endif
2036                 system( str );
2037
2038                 // Generate link to image
2039                 RB_Generate_DOT_Image_Link( f, dot_nr, dot_type );
2040
2041                 // Get back to working dir
2042                 RB_Change_Back_To_CWD(  );
2043
2044                 // Increment dot file number
2045                 dot_nr++;
2046             }
2047         }
2048         // Exec item
2049         else if ( !Works_Like_SourceItem( item_type ) &&
2050                   ( item_line->kind == ITEM_LINE_EXEC ) )
2051         {
2052             Format_Line( f, item_line->format );
2053
2054             // Change to docdir
2055             RB_Change_To_Docdir( document );
2056
2057             // Execute line
2058             system( line );
2059
2060             // Get back to working dir
2061             RB_Change_Back_To_CWD(  );
2062         }
2063         // Source lines
2064         else if ( Works_Like_SourceItem( item_type ) )
2065         {
2066             Format_Line( f, item_line->format );
2067             Generate_Item_Line( f, line, item_type, docname, header );
2068         }
2069         else
2070         {
2071             /* This item line is ignored */
2072         }
2073     }
2074     RB_Generate_Item_End( f, name );
2075 }
2076
2077 /******/
2078
2079
2080 /****f* Generator/Generate_Header
2081  * FUNCTION
2082  *   Generate the documentation for all the items found in
2083  *   a header except for any items specified in
2084  *   configuration.ignore_items.
2085  * SYNOPSIS
2086  */
2087 static void Generate_Header(
2088     FILE *f,
2089     struct RB_Document *document,
2090     struct RB_header *header,
2091     char *docname )
2092 /*
2093  * INPUTS
2094  *   * f -- destination file
2095  *   * header -- header to be searched.
2096  *   * srcname -- name of the source file the header was found in.
2097  *   * document -- name of the documentation file.
2098  * BUGS
2099  *   This skips the first item body if the first item name was
2100  *   not correctly spelled.
2101  * SOURCE
2102  */
2103 {
2104     struct RB_Item     *cur_item;
2105
2106     for ( cur_item = header->items; cur_item; cur_item = cur_item->next )
2107     {
2108         enum ItemType       item_type = cur_item->type;
2109         char               *name = configuration.items.names[item_type];
2110
2111         if ( Is_Ignore_Item( name ) )
2112         {
2113             /* User does not want this item */
2114         }
2115         else if ( Works_Like_SourceItem( item_type )
2116                   && ( course_of_action.do_nosource ) )
2117         {
2118             /* User does not want source items */
2119         }
2120         else
2121         {
2122             Generate_Item( f, document, header, cur_item, docname );
2123         }
2124     }
2125 }
2126
2127 /******/
2128
2129
2130 static void Pipe_Line(
2131     FILE *dest_doc,
2132     char *arg_line )
2133 {
2134     char               *cur_char = arg_line;
2135
2136     for ( ; *cur_char && ( *cur_char == ' ' || *cur_char == '\t' );
2137           cur_char++ )
2138     {
2139         fputc( *cur_char, dest_doc );
2140     }
2141     fprintf( dest_doc, "%s%s", cur_char,
2142              ( output_mode == RTF ? "\\line" : "\n" ) );
2143 }
2144
2145
2146 static void Format_Line(
2147     FILE *dest_doc,
2148     long format )
2149 {
2150     if ( format & RBILA_END_LIST_ITEM )
2151     {
2152         Generate_End_List_Item( dest_doc );
2153     }
2154     if ( format & RBILA_END_LIST )
2155     {
2156         Generate_End_List( dest_doc );
2157     }
2158     if ( format & RBILA_END_PRE )
2159     {
2160         Generate_End_Preformatted( dest_doc );
2161     }
2162     if ( format & RBILA_BEGIN_PARAGRAPH )
2163     {
2164         Generate_Begin_Paragraph( dest_doc );
2165     }
2166     if ( format & RBILA_END_PARAGRAPH )
2167     {
2168         Generate_End_Paragraph( dest_doc );
2169     }
2170     if ( format & RBILA_BEGIN_PRE )
2171     {
2172         Generate_Begin_Preformatted( dest_doc,
2173                                      ( format & RBILA_BEGIN_SOURCE ) );
2174     }
2175     if ( format & RBILA_BEGIN_LIST )
2176     {
2177         Generate_Begin_List( dest_doc );
2178     }
2179     if ( format & RBILA_BEGIN_LIST_ITEM )
2180     {
2181         Generate_Begin_List_Item( dest_doc );
2182     }
2183 }
2184
2185
2186
2187 static void Generate_Begin_List_Item(
2188     FILE *dest_doc )
2189 {
2190     switch ( output_mode )
2191     {
2192     case TEST:
2193         TEST_Generate_Begin_List_Item( dest_doc );
2194         break;
2195     case XMLDOCBOOK:
2196         XMLDB_Generate_Begin_List_Item( dest_doc );
2197         break;
2198     case HTML:
2199         HTML_Generate_Begin_List_Item( dest_doc );
2200         break;
2201     case LATEX:
2202         LaTeX_Generate_Begin_List_Item( dest_doc );
2203         break;
2204     case RTF:
2205         break;
2206     case TROFF:
2207         TROFF_Generate_Begin_List_Item( dest_doc );
2208         break;
2209         break;
2210     case ASCII:
2211         break;
2212     case UNKNOWN:
2213     default:
2214         assert( 0 );
2215     }
2216 }
2217
2218
2219 static void Generate_End_List_Item(
2220     FILE *dest_doc )
2221 {
2222     switch ( output_mode )
2223     {
2224     case TEST:
2225         TEST_Generate_End_List_Item( dest_doc );
2226         break;
2227     case XMLDOCBOOK:
2228         XMLDB_Generate_End_List_Item( dest_doc );
2229         break;
2230     case HTML:
2231         HTML_Generate_End_List_Item( dest_doc );
2232         break;
2233     case LATEX:
2234         LaTeX_Generate_End_List_Item( dest_doc );
2235         break;
2236     case RTF:
2237         break;
2238     case TROFF:
2239         TROFF_Generate_End_List_Item( dest_doc );
2240         break;
2241         break;
2242     case ASCII:
2243         break;
2244     case UNKNOWN:
2245     default:
2246         assert( 0 );
2247     }
2248 }
2249
2250
2251 static void Generate_Begin_List(
2252     FILE *dest_doc )
2253 {
2254     switch ( output_mode )
2255     {
2256     case TEST:
2257         TEST_Generate_Begin_List( dest_doc );
2258         break;
2259     case XMLDOCBOOK:
2260         XMLDB_Generate_Begin_List( dest_doc );
2261         break;
2262     case HTML:
2263         HTML_Generate_Begin_List( dest_doc );
2264         break;
2265     case LATEX:
2266         LaTeX_Generate_Begin_List( dest_doc );
2267         break;
2268
2269     case RTF:
2270     case TROFF:
2271     case ASCII:
2272         break;
2273
2274     case UNKNOWN:
2275     default:
2276         assert( 0 );
2277     }
2278 }
2279
2280 /* TODO FS Document */
2281
2282 static void Generate_End_List(
2283     FILE *dest_doc )
2284 {
2285     switch ( output_mode )
2286     {
2287     case TEST:
2288         TEST_Generate_End_List( dest_doc );
2289         break;
2290     case XMLDOCBOOK:
2291         XMLDB_Generate_End_List( dest_doc );
2292         break;
2293     case HTML:
2294         HTML_Generate_End_List( dest_doc );
2295         break;
2296     case LATEX:
2297         LaTeX_Generate_End_List( dest_doc );
2298         break;
2299
2300     case RTF:
2301     case TROFF:
2302     case ASCII:
2303         break;
2304
2305     case UNKNOWN:
2306     default:
2307         assert( 0 );
2308     }
2309 }
2310
2311
2312 /* TODO FS Document */
2313
2314 static void Generate_Begin_Preformatted(
2315     FILE *dest_doc,
2316     int source )
2317 {
2318     switch ( output_mode )
2319     {
2320     case TEST:
2321         TEST_Generate_Begin_Preformatted( dest_doc );
2322         break;
2323     case XMLDOCBOOK:
2324         XMLDB_Generate_Begin_Preformatted( dest_doc );
2325         break;
2326     case HTML:
2327         HTML_Generate_Begin_Preformatted( dest_doc, source );
2328         break;
2329     case LATEX:
2330         LaTeX_Generate_Begin_Preformatted( dest_doc );
2331         break;
2332     case RTF:
2333         break;
2334     case TROFF:
2335         TROFF_Generate_Begin_Preformatted( dest_doc );
2336         break;
2337     case ASCII:
2338         break;
2339     case UNKNOWN:
2340     default:
2341         assert( 0 );
2342     }
2343 }
2344
2345
2346 /* TODO FS Document */
2347 static void Generate_End_Preformatted(
2348     FILE *dest_doc )
2349 {
2350     switch ( output_mode )
2351     {
2352     case TEST:
2353         TEST_Generate_End_Preformatted( dest_doc );
2354         break;
2355     case XMLDOCBOOK:
2356         XMLDB_Generate_End_Preformatted( dest_doc );
2357         break;
2358     case HTML:
2359         HTML_Generate_End_Preformatted( dest_doc );
2360         break;
2361     case LATEX:
2362         LaTeX_Generate_End_Preformatted( dest_doc );
2363         break;
2364     case RTF:
2365         break;
2366     case TROFF:
2367         TROFF_Generate_End_Preformatted( dest_doc );
2368         break;
2369     case ASCII:
2370         break;
2371     case UNKNOWN:
2372     default:
2373         assert( 0 );
2374     }
2375 }
2376
2377
2378 /* TODO FS Document */
2379 static void Generate_End_Paragraph(
2380     FILE *dest_doc )
2381 {
2382     switch ( output_mode )
2383     {
2384     case TEST:
2385         TEST_Generate_End_Paragraph( dest_doc );
2386         break;
2387     case XMLDOCBOOK:
2388         XMLDB_Generate_End_Paragraph( dest_doc );
2389         break;
2390     case HTML:
2391         HTML_Generate_End_Paragraph( dest_doc );
2392         break;
2393     case LATEX:
2394         LaTeX_Generate_End_Paragraph( dest_doc );
2395         break;
2396     case RTF:
2397         break;
2398     case TROFF:
2399         TROFF_Generate_End_Paragraph( dest_doc );
2400         break;
2401     case ASCII:
2402         break;
2403     case UNKNOWN:
2404     default:
2405         assert( 0 );
2406     }
2407 }
2408
2409
2410 /* TODO FS Document */
2411 static void Generate_Begin_Paragraph(
2412     FILE *dest_doc )
2413 {
2414     switch ( output_mode )
2415     {
2416     case TEST:
2417         TEST_Generate_Begin_Paragraph( dest_doc );
2418         break;
2419     case XMLDOCBOOK:
2420         XMLDB_Generate_Begin_Paragraph( dest_doc );
2421         break;
2422     case HTML:
2423         HTML_Generate_Begin_Paragraph( dest_doc );
2424         break;
2425     case LATEX:
2426         LaTeX_Generate_Begin_Paragraph( dest_doc );
2427         break;
2428     case RTF:
2429         break;
2430     case TROFF:
2431         TROFF_Generate_Begin_Paragraph( dest_doc );
2432         break;
2433     case ASCII:
2434         break;
2435     case UNKNOWN:
2436     default:
2437         assert( 0 );
2438     }
2439 }
2440
2441
2442 #if 0
2443 /*x**f* Generator/RB_Generate_Empty_Item
2444  * FUNCTION
2445  *   Generate documentation for an item with an empty body.
2446  * INPUTS
2447  *   dest_doc -- destination file.
2448  ****
2449  * TODO Documentation
2450  */
2451
2452 static void RB_Generate_Empty_Item(
2453     FILE *dest_doc )
2454 {
2455     switch ( output_mode )
2456     {
2457     case TEST:
2458         break;
2459     case XMLDOCBOOK:
2460         break;
2461     case HTML:
2462         RB_HTML_Generate_Empty_Item( dest_doc );
2463         break;
2464     case LATEX:
2465         RB_LaTeX_Generate_Empty_Item( dest_doc );
2466         break;
2467     case RTF:
2468         RB_RTF_Generate_Empty_Item( dest_doc );
2469         break;
2470     case TROFF:
2471         break;
2472     case ASCII:
2473         RB_ASCII_Generate_Empty_Item( dest_doc );
2474         break;
2475     case UNKNOWN:
2476     default:
2477         assert( 0 );
2478     }
2479 }
2480 #endif
2481
2482
2483
2484 static void Generate_Item_Line(
2485     FILE *dest_doc,
2486     char *line,
2487     int item_type,
2488     char *docname,
2489     struct RB_header *fnames )
2490 {
2491     char               *cur_char = line;
2492     char               *object_name = NULL;
2493     char               *label_name = NULL;
2494     char               *file_name = NULL;
2495
2496     enum EIL_State
2497     { SKIP_ALPHANUM, SKIP_SPACE, SEARCH_LINK_START_WORD, SEARCH_LINK }
2498     state = SKIP_SPACE;
2499
2500     for ( ; *cur_char; cur_char++ )
2501     {
2502         char                c = *cur_char;
2503
2504         /* This is a little statemachine to switch searching for
2505          * links on and off.  A link can be found for a word
2506          * or for a word combined with some punctuation
2507          * characters.  A word is a string of alpha numeric
2508          * characters (including a '_'),  say FunctionAA_10_B
2509          * All other characters are punctuation characters.
2510          * We do not want links to start in the middle of a word,
2511          * but they can start after or on a punctuation character.
2512          * So for a link can start at
2513          *     Foo_bar::SnaFu
2514          *     ^      ^^^
2515          *     |      |||
2516          *
2517          */
2518
2519         /* Move to the next state based on current character.  */
2520         switch ( state )
2521         {
2522         case SKIP_SPACE:
2523             /* In this state we try to skip of a string of space
2524              * characters until we find something else.
2525              */
2526             {
2527                 if ( utf8_ispunct( c ) )
2528                 {
2529                     /* we were in the process of skipping spaces,
2530                      * but now we found a non-space character.
2531                      * This might be the begin of a link, so
2532                      * switch to the search link state.
2533                      */
2534                     state = SEARCH_LINK;
2535                 }
2536                 else if ( utf8_isalnum( c ) || ( c == '_' ) )
2537                 {
2538                     state = SEARCH_LINK_START_WORD;
2539                 }
2540                 else
2541                 {
2542                     /* Links can only start with a none space character,
2543                      * so if the current charater is a space, we skip it.
2544                      */
2545                 }
2546                 break;
2547             }
2548         case SKIP_ALPHANUM:
2549             /* In this state we skipping a string of alpha
2550              * numeric charaters after that the first
2551              * character in this string did not result in a
2552              * link.
2553              */
2554             {
2555                 if ( utf8_isspace( c ) )
2556                 {
2557                     /* We found the end of the string, so we go
2558                      * back to the space skipping state
2559                      */
2560                     state = SKIP_SPACE;
2561                 }
2562                 else if ( utf8_ispunct( c ) && ( c != '_' ) )
2563                 {
2564                     /* We found a puntuation character, this end
2565                      * the string of alpha numeric character, but
2566                      * can be the begin of a new link, so we
2567                      * switch to the seach link state.
2568                      */
2569                     state = SEARCH_LINK;
2570                 }
2571                 else
2572                 {
2573                     /* We stay in this state */
2574                 }
2575             }
2576             break;
2577         case SEARCH_LINK_START_WORD:
2578             /* In this state we are at the start of a string
2579              * of alpha numeric characters.
2580              */
2581             {
2582                 if ( utf8_isalnum( c ) || ( c == '_' ) )
2583                 {
2584                     /* We are not at the second character of
2585                      * a string of alpha numeric characters,
2586                      * we can stop searching for links, as a
2587                      * link can only start at the begin of
2588                      * such a string.
2589                      */
2590                     state = SKIP_ALPHANUM;
2591                 }
2592                 else if ( utf8_ispunct( c ) && ( c != '_' ) )
2593                 {
2594                     state = SEARCH_LINK;
2595                 }
2596                 else if ( utf8_isspace( c ) )
2597                 {
2598                     state = SKIP_SPACE;
2599                 }
2600                 else
2601                 {
2602                     state = SKIP_SPACE;
2603                 }
2604             }
2605             break;
2606         case SEARCH_LINK:
2607             {
2608                 /* In this state we search for links. We stop
2609                  * searching if we encounter a space because this
2610                  * marks end of the word,
2611                  */
2612                 if ( utf8_isalnum( c ) || ( c == '_' ) )
2613                 {
2614                     /* We are at the start of a word.
2615                      */
2616                     state = SEARCH_LINK_START_WORD;
2617                 }
2618                 else if ( utf8_isspace( c ) )
2619                 {
2620                     state = SKIP_SPACE;
2621                 }
2622                 else
2623                 {
2624                     /* We stay in this state */
2625                 }
2626             }
2627             break;
2628         default:
2629             assert( 0 );
2630             break;
2631         }
2632
2633         if ( ( ( state == SEARCH_LINK ) ||
2634                ( state == SEARCH_LINK_START_WORD ) ) &&
2635              Find_Link( cur_char, &object_name, &label_name, &file_name ) )
2636         {
2637             /* We found a link, so we can stop searching for one
2638              * for now.
2639              */
2640             state = SKIP_SPACE;
2641
2642             if ( object_name && fnames->no_names > 0 )
2643             {
2644                 extern char        *function_name(
2645     char * );
2646                 int                 i;
2647
2648                 for ( i = 0; i < fnames->no_names; i++ )
2649                     if ( strcmp
2650                          ( object_name,
2651                            function_name( fnames->names[i] ) ) == 0 )
2652                         break;
2653                 if ( i < fnames->no_names )
2654                 {
2655                     RB_Generate_False_Link( dest_doc, object_name );
2656                     cur_char += strlen( object_name ) - 1;
2657                 }
2658                 else
2659                 {
2660                     Generate_Link( dest_doc, docname,
2661                                    file_name, label_name, object_name );
2662                     cur_char += strlen( object_name ) - 1;
2663                 }
2664             }
2665             else
2666             {
2667                 assert( 0 );
2668             }
2669         }
2670         else
2671         {
2672             int                 res =
2673                 RB_HTML_Extra( dest_doc, item_type, cur_char,
2674                                ( cur_char == line ) ? 0 : *( cur_char - 1 ) );
2675
2676             if ( res >= 0 )
2677             {
2678                 cur_char += res;
2679             }
2680             else
2681             {
2682                 /* convert from signed to unsigned */
2683                 unsigned char       c2 = *cur_char;
2684
2685                 Generate_Char( dest_doc, c2 );
2686             }
2687         }
2688     }
2689
2690     /* TODO Move to the RTF_Generator */
2691     switch ( output_mode )
2692     {
2693     case RTF:
2694         fprintf( dest_doc, "\\line" );
2695         break;
2696
2697     case TROFF:
2698         RB_TROFF_Start_New_Line( dest_doc );
2699         break;
2700
2701     case HTML:
2702         // Check for source line comment endings
2703         RB_HTML_Generate_Line_Comment_End( dest_doc );
2704         break;
2705
2706     case TEST:
2707     case ASCII:
2708     case LATEX:
2709     case XMLDOCBOOK:
2710     case UNKNOWN:
2711         break;
2712     default:
2713         break;
2714     }
2715
2716     /* For all modes we add a newline. */
2717     fputc( '\n', dest_doc );
2718 }
2719
2720
2721
2722 /****f* Generator/Generate_Link
2723  * FUNCTION
2724  *   Generate a link to another headers documentation.
2725  * SYNOPSIS
2726  */
2727 void Generate_Link(
2728     FILE *dest_doc,
2729     char *docname,
2730     char *file_name,
2731     char *label_name,
2732     char *function_name )
2733 /*
2734  * INPUTS
2735  *   * dest_doc      -- the output file
2736  *   * docname       -- the name of the output file
2737  *   * file_name     -- the name of the file that contains the link's body
2738  *   * label_name    -- the label for the link
2739  *   * function_name -- the name that is shown for the link in the
2740  *                      documentation
2741  * SOURCE
2742  */
2743 {
2744
2745     switch ( output_mode )
2746     {
2747     case TEST:
2748         RB_TEST_Generate_Link( dest_doc, docname, file_name, label_name,
2749                                function_name );
2750         break;
2751     case XMLDOCBOOK:
2752         RB_XMLDB_Generate_Link( dest_doc, docname, file_name, label_name,
2753                                 function_name );
2754         break;
2755     case HTML:
2756         RB_HTML_Generate_Link( dest_doc, docname, file_name, label_name,
2757                                function_name, NULL );
2758         break;
2759     case RTF:
2760         RB_RTF_Generate_Link( dest_doc, docname, file_name, label_name,
2761                               function_name );
2762         break;
2763     case LATEX:
2764         RB_LaTeX_Generate_String( dest_doc, function_name );
2765         /* lowtexx 21.09.2005 11:43 */
2766         /* generate a simple link here */
2767         RB_LaTeX_Generate_Link( dest_doc, docname, file_name, label_name,
2768                                 function_name );
2769         break;
2770     case UNKNOWN:
2771     case ASCII:
2772     case TROFF:
2773     default:
2774         fprintf( dest_doc, "%s", function_name );
2775     }
2776 }
2777
2778 /******/
2779
2780
2781 /****f* Generator/Generate_Char
2782  * FUNCTION
2783  *   Generate a single character in the current output mode.
2784  *   The individual generators will make sure that special
2785  *   characters are escaped.
2786  * SYNOPSIS
2787  */
2788 void Generate_Char(
2789     FILE *dest_doc,
2790     int cur_char )
2791 /*
2792  * INPUTS
2793  *   * dest_doc -- destination file.
2794  *   * cur_char -- character to be generated.
2795  *******
2796  */
2797 {
2798     switch ( output_mode )
2799     {
2800     case TEST:
2801         RB_TEST_Generate_Char( dest_doc, cur_char );
2802         break;
2803     case XMLDOCBOOK:
2804         RB_XMLDB_Generate_Char( dest_doc, cur_char );
2805         break;
2806     case HTML:
2807         RB_HTML_Generate_Char( dest_doc, cur_char );
2808         break;
2809     case LATEX:
2810         RB_LaTeX_Generate_Char( dest_doc, cur_char );
2811         break;
2812     case RTF:
2813         RB_RTF_Generate_Char( dest_doc, cur_char );
2814         break;
2815     case TROFF:
2816         RB_TROFF_Generate_Char( dest_doc, cur_char );
2817         break;
2818     case ASCII:
2819         RB_ASCII_Generate_Char( dest_doc, cur_char );
2820         break;
2821     case UNKNOWN:
2822     default:
2823         assert( 0 );
2824     }
2825 }
2826
2827
2828 /****f* Generator/RB_Get_SubIndex_FileName
2829  * FUNCTION
2830  *   Get the name of the master index file for a specific
2831  *   header_type.
2832  * SYNOPSIS
2833  */
2834 char               *RB_Get_SubIndex_FileName(
2835     char *docroot,
2836     char *extension,
2837     struct RB_HeaderType *header_type )
2838 /*
2839  * INPUTS
2840  *   * docroot      -- the path to the documentation directory.
2841  *   * extension    -- the extension for the file
2842  *   * header_type  -- the header type
2843  * RESULT
2844  *   a pointer to a freshly allocated string.
2845  * NOTES
2846  *   Has too many parameters.
2847  * SOURCE
2848  */
2849 {
2850     size_t              l;
2851     char               *filename;
2852
2853     assert( docroot );
2854
2855     l = strlen( docroot );
2856
2857     l += RB_Get_Len_Extension( extension );
2858     l += strlen( docroot );
2859     l += strlen( header_type->fileName );
2860
2861     filename = ( char * ) malloc( l + 2 );
2862     assert( filename );
2863     filename[0] = '\0';
2864
2865     strcat( filename, docroot );
2866     strcat( filename, header_type->fileName );
2867     RB_Add_Extension( extension, filename );
2868
2869     return filename;
2870 }
2871
2872 /*****/
2873
2874
2875 /****f* Generator/Generate_Index
2876  * NAME
2877  *   Generate_Index -- generate index file based on xref files.
2878  * SYNOPSIS
2879  */
2880 static void Generate_Index(
2881     struct RB_Document *document )
2882 /*
2883  * FUNCTION
2884  *   Create a master index file. It contains pointers to the
2885  *   documentation generated for each source file, as well as all
2886  *   "objects" found in the source files.
2887  * SOURCE
2888  */
2889 {
2890     switch ( output_mode )
2891     {
2892     case TEST:
2893         break;
2894     case XMLDOCBOOK:
2895         break;
2896     case HTML:
2897         RB_HTML_Generate_Index( document );
2898         break;
2899     case LATEX:
2900         /* RB_LaTeX_Generate_Index(dest, source); */
2901         /* Latex has a index by default */
2902         break;
2903     case UNKNOWN:
2904     case ASCII:
2905     case TROFF:
2906     case RTF:
2907     default:
2908         break;
2909     }
2910 }
2911
2912 /*****/