--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "robodoc.h"
+#include "headers.h"
+#include "items.h"
+#include "folds.h"
+#include "util.h"
+#include "links.h"
+#include "generator.h"
+#include "analyser.h"
+
+
+/****f* ROBODoc/RB_Generate_Documentation [3.0h]
+ * NAME
+ * RB_Generate_Documentation
+ * SYNOPSIS
+ * RB_Generate_Documentation (dest_doc, name, name)
+ *
+ * RB_Generate_Documentation (FILE *, char *, char *)
+ * FUNCTION
+ * Generates the autodoc documentation from the list of
+ * function headers that has been created by
+ * RB_Analyse_Document.
+ * INPUTS
+ * dest_doc - Pointer to the file to which the output will be written.
+ * src_name - The name of the source file.
+ * dest_name - The name of this file.
+ * BUGS
+ * There might be plenty.
+ * SEE ALSO
+ * RB_Generate_Doc_Start,
+ * RB_Generate_Doc_End,
+ * RB_Generate_Header_Start,
+ * RB_Generate_Header_End,
+ * RB_Generate_Header_Name,
+ * RB_Generate_Item_Name,
+ * RB_Generate_Item_Doc,
+ * RB_Generate_Item_Body .
+ * SOURCE
+ */
+
+void
+RB_Generate_Documentation (
+ FILE * dest_doc, char *src_name, char *dest_name)
+{
+ struct RB_header *cur_header;
+ int expc = 0;
+ char fname[256];
+ FILE *orig_doc = dest_doc;
+
+ RB_Make_Index_Tables ();
+
+ RB_Generate_Doc_Start (dest_doc, src_name, dest_name, 1);
+
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header)
+ {
+ int item_type;
+ char *next_line, *item_line = NULL;
+
+ RB_Say ("generating documentation for \"%s\"\n", cur_header->name);
+
+ if (output_mode == HTML)
+ {
+ sprintf(fname, "%s_exp_%d.html", doc_base, expc++);
+ dest_doc = fopen(fname, "w");
+ }
+
+ RB_Generate_Header_Start (dest_doc, cur_header);
+
+ next_line = cur_header->contents;
+ item_type = RB_Find_Item (&next_line, &item_line);
+
+ if (item_type != NO_ITEM)
+ {
+ int old_item_type;
+ char *old_next_line;
+
+ do
+ {
+ if (course_of_action & DO_TELL)
+ printf ("[%s] ", item_names[item_type]);
+
+ if (!((item_type == SOURCE_ITEM) &&
+ (course_of_action & DO_NOSOURCE)))
+ RB_Generate_Item_Name (dest_doc, item_type);
+
+ old_next_line = next_line;
+ old_item_type = item_type;
+
+ item_type = RB_Find_Item (&next_line, &item_line);
+
+ if (!((old_item_type == SOURCE_ITEM) &&
+ (course_of_action & DO_NOSOURCE)))
+ RB_Generate_Item_Doc (dest_doc, dest_name,
+ old_next_line, item_line,
+ cur_header->function_name,
+ old_item_type);
+ }
+ while (item_type != NO_ITEM);
+ if (course_of_action & DO_TELL)
+ putchar ('\n');
+ }
+ else
+ printf ("%s: WARNING, header \"%s\" has no items\n",
+ whoami, cur_header->name);
+
+ RB_Generate_Header_End (dest_doc, cur_header);
+ }
+
+ dest_doc = orig_doc;
+ RB_Generate_Doc_End (dest_doc, dest_name);
+}
+
+/***** RB_Generate_Documentation ***/
+
+
+
+
+
+/****f* ROBODoc/RB_Generate_Doc_Start [3.0j]
+ * NAME
+ * RB_Generate_Doc_Start -- Generate document header.
+ * SYNOPSIS
+ * RB_Generate_Doc_Start (dest_doc, src_name, name, toc)
+ *
+ * RB_Generate_Doc_Start (FILE *, char *, char *, char)
+ * FUNCTION
+ * Generates for depending on the output_mode the text that
+ * will be at the start of a document.
+ * Including the table of contents.
+ * INPUTS
+ * dest_doc - pointer to the file to which the output will
+ * be written.
+ * src_name - the name of the source file.
+ * name - the name of this file.
+ * output_mode - global variable that indicates the output
+ * mode.
+ * toc - generate table of contens
+ * SEE ALSO
+ * RB_Generate_Doc_End
+ * SOURCE
+ */
+
+void
+RB_Generate_Doc_Start (
+ FILE * dest_doc, char *src_name, char *name, char toc)
+{
+ struct RB_header *cur_header;
+ int cur_len, max_len, header_nr;
+
+ switch (output_mode)
+ {
+ case AMIGAGUIDE:
+ if (strstr (name + 1, ".guide") == NULL)
+ fprintf (dest_doc, "@database %s.guide\n", name);
+ else
+ fprintf (dest_doc, "@database %s\n", name);
+ fprintf (dest_doc, "@rem Source: %s\n", src_name);
+ fprintf (dest_doc, "@rem " COMMENT_ROBODOC);
+ fprintf (dest_doc, "@rem " COMMENT_COPYRIGHT);
+ fprintf (dest_doc, "@node Main %s\n", name);
+ fprintf (dest_doc, "@{jcenter}\n");
+ fprintf (dest_doc,
+ "@{fg highlight}@{b}TABLE OF CONTENTS@{ub}@{fg text}\n\n");
+
+ max_len = 0;
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header)
+ {
+ if (cur_header->name)
+ {
+ cur_len = strlen (cur_header->name);
+ if (cur_len > max_len)
+ max_len = cur_len;
+ }
+ }
+
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header)
+ {
+ if (cur_header->name && cur_header->function_name)
+ {
+ fprintf (dest_doc, "@{\"%s", cur_header->name);
+
+ for (cur_len = strlen (cur_header->name);
+ cur_len < max_len;
+ ++cur_len)
+ fputc (' ', dest_doc);
+ fprintf (dest_doc, "\" Link \"%s\"}\n", cur_header->function_name);
+ }
+ }
+
+ fprintf (dest_doc, "@{jleft}\n");
+ fprintf (dest_doc, "@endnode\n");
+ break;
+
+ case HTML:
+ /* Append document type and title */
+ fprintf (dest_doc,
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
+ fprintf (dest_doc, "<HTML><HEAD>\n<TITLE>%s</TITLE>\n", name);
+
+ /* append SGML-comment with document- and copyright-info. This code
+ * ensures that every line has an own comment to avoid problems with
+ * buggy browsers */
+ fprintf (dest_doc, "<!-- Source: %s -->\n", src_name);
+ {
+ static const char copyright_text[]
+ = COMMENT_ROBODOC COMMENT_COPYRIGHT;
+ size_t i = 0;
+ char previous_char = '\n';
+ char current_char = copyright_text[i];
+
+ while (current_char)
+ {
+ if (previous_char == '\n')
+ {
+ fprintf (dest_doc, "<!-- ");
+ }
+ if (current_char == '\n')
+ {
+ fprintf (dest_doc, " -->");
+ }
+ else if ((current_char == '-') && (previous_char == '-'))
+ {
+ /* avoid "--" inside SGML-comment, and use "-_" instead; this
+ * looks a bit strange, but one should still be able to figure
+ * out what is meant when reading the output */
+ current_char = '_';
+ }
+ fputc (current_char, dest_doc);
+ i += 1;
+ previous_char = current_char;
+ current_char = copyright_text[i];
+ }
+ }
+
+ /* append heading and start list of links to functions */
+ fprintf (dest_doc, "</HEAD><BODY BGCOLOR=\"#FFFFFF\">\n");
+#if 0
+ fprintf (dest_doc, "<A NAME=\"%s\">Generated from %s</A> with ROBODoc v"
+ VERSION
+ " on ",
+ src_name, src_name);
+ RB_TimeStamp (dest_doc);
+#endif
+ fprintf (dest_doc, "<BR>\n");
+ if (toc)
+ {
+ int expc = 0;
+ char iname[256];
+ FILE *index;
+
+ /* do toc if not in fold */
+#if 0
+ fprintf (dest_doc,
+ "<H3 ALIGN=\"center\">TABLE OF CONTENTS</H3>\n");
+#endif
+ fprintf (dest_doc, "<OL>\n");
+
+ /* Generate quick index file, for fast referencing */
+ sprintf(iname, "%s_index.html", doc_base);
+ index = fopen(iname, "w");
+
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header)
+ {
+ char fname[256];
+
+ sprintf(fname, "%s_exp_%d.html", doc_base, expc);
+
+ if (cur_header->name && cur_header->function_name)
+ {
+ if (expc == 0)
+ {
+ int item_type;
+ char *next_line, *item_line = NULL;
+
+ RB_Generate_Header_Start (dest_doc, cur_header);
+
+ next_line = cur_header->contents;
+ item_type = RB_Find_Item (&next_line, &item_line);
+
+ if (item_type != NO_ITEM)
+ {
+ int old_item_type;
+ char *old_next_line;
+
+ do
+ {
+ if (course_of_action & DO_TELL)
+ printf ("[%s] ", item_names[item_type]);
+
+ if (!((item_type == SOURCE_ITEM) &&
+ (course_of_action & DO_NOSOURCE)))
+ RB_Generate_Item_Name (dest_doc, item_type);
+
+ old_next_line = next_line;
+ old_item_type = item_type;
+
+ item_type = RB_Find_Item (&next_line,
+ &item_line);
+
+ if (!((old_item_type == SOURCE_ITEM) &&
+ (course_of_action & DO_NOSOURCE)))
+ RB_Generate_Item_Doc(dest_doc, name,
+ old_next_line, item_line,
+ cur_header->function_name,
+ old_item_type);
+ }
+ while (item_type != NO_ITEM);
+ if (course_of_action & DO_TELL)
+ putchar ('\n');
+ }
+
+ if (index)
+ {
+ fprintf (index, "<A HREF=\"%s\">%s</A><BR>\n",
+ name, cur_header->function_name);
+ }
+ }
+ else
+ {
+ fprintf (dest_doc, "<LI><A HREF=\"%s\">%s</A>\n",
+ fname, cur_header->name);
+ if (index)
+ fprintf (index, "<A HREF=\"%s\">%s</A><BR>\n",
+ fname, cur_header->function_name);
+ }
+
+ expc++;
+ }
+ }
+
+ fprintf (dest_doc, "</OL>\n");
+
+ if (index)
+ fclose(index);
+ }
+ break;
+
+ case LATEX:
+ fprintf (dest_doc, "%% Document: %s\n", name);
+ fprintf (dest_doc, "%% Source: %s\n", src_name);
+ fprintf (dest_doc, "%% " COMMENT_ROBODOC);
+ fprintf (dest_doc, "%% " COMMENT_COPYRIGHT);
+ if (course_of_action & DO_SINGLEDOC) {
+ fprintf (dest_doc, "\\section{%s}\n", src_name);
+ } else {
+ fprintf (dest_doc, "\\documentclass{article}\n");
+ fprintf (dest_doc, "\\usepackage{makeidx}\n");
+ fprintf (dest_doc, "\\oddsidemargin 0.15 in\n");
+ fprintf (dest_doc, "\\evensidemargin 0.35 in\n");
+ fprintf (dest_doc, "\\marginparwidth 1 in \n");
+ fprintf (dest_doc, "\\oddsidemargin 0.25 in \n");
+ fprintf (dest_doc, "\\evensidemargin 0.25 in\n");
+ fprintf (dest_doc, "\\marginparwidth 0.75 in\n");
+ fprintf (dest_doc, "\\textwidth 5.875 in\n");
+
+ fprintf (dest_doc, "\\setlength{\\parindent}{0in}\n");
+ fprintf (dest_doc, "\\setlength{\\parskip}{.08in}\n\n");
+
+ /* changed default header to use boldface (vs slant) */
+ fprintf (dest_doc, "\\pagestyle{headings}\n");
+
+ if (document_title) {
+ fprintf (dest_doc, "\\title{%s}\n",
+ document_title);
+ } else {
+ fprintf (dest_doc, "\\title{API Reference}\n");
+ }
+ fprintf (dest_doc, "\\author{%s}\n", COMMENT_ROBODOC);
+ fprintf (dest_doc, "\\makeindex\n");
+ fprintf (dest_doc, "\\begin{document}\n");
+ fprintf (dest_doc, "\\maketitle\n");
+ /* autogenerate table of contents! */
+ fprintf (dest_doc, "\\printindex\n");
+ fprintf (dest_doc, "\\tableofcontents\n");
+ fprintf (dest_doc, "\\newpage\n");
+ /* trick to disable the autogenerated \newpage */
+ fprintf (dest_doc, "\n");
+ }
+ break;
+
+ case RTF:
+ {
+ char *cook_link;
+
+ /* RTF header */
+ fprintf (dest_doc, "{\\rtf1\\ansi \\deff0"
+ "{\\fonttbl;"
+ "\\f0\\fswiss MS Sans Serif;"
+ "\\f1\\fmodern Courier New;"
+ "\\f2\\ftech Symbol;"
+ "}"
+ "{\\colortbl;"
+ "\\red255\\green255\\blue255;"
+ "\\red0\\green0\\blue0;"
+ "\\red0\\green0\\blue255;"
+ "}");
+
+ /* RTF document info */
+ fprintf (dest_doc, "{\\info"
+ "{\\title %s}"
+ "{\\comment\n"
+ " Source: %s\n"
+ " " COMMENT_ROBODOC
+ " " COMMENT_COPYRIGHT
+ "}"
+ "}", name, src_name);
+
+ /* RTF document format */
+ fprintf (dest_doc, "{\\margl1440\\margr1440}\n");
+
+ /* RTF document section */
+ fprintf (dest_doc, "\\f0\\cb1\\cf3\\fs28\\b1\\qc"
+ "{\\super #{\\footnote{\\super #}%s_TOC}}"
+ "{\\super ${\\footnote{\\super $}Contents}}"
+ "{TABLE OF CONTENTS}\\ql\\b0\\fs20\\cf2\\par\n", src_name);
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header)
+ {
+ if (cur_header->name && cur_header->function_name)
+ {
+ cook_link = RB_CookStr (cur_header->function_name);
+ fprintf (dest_doc, "{\\uldb %s}{\\v %s}\\line\n",
+ cur_header->name, cook_link);
+ free (cook_link);
+ }
+ }
+ fprintf (dest_doc, "\\par\n");
+ }
+ break;
+ case ASCII:
+ if (course_of_action & DO_TOC)
+ {
+ fprintf (dest_doc, "TABLE OF CONTENTS\n");
+ for (cur_header = first_header, header_nr = 1;
+ cur_header;
+ cur_header = cur_header->next_header, header_nr++)
+ {
+ if (cur_header->name && cur_header->function_name)
+ {
+ fprintf (dest_doc, "%4.4d %s\n",
+ header_nr, cur_header->name);
+ }
+ }
+ fputc ('\f', dest_doc);
+ }
+ default:
+ break;
+ }
+}
+
+/***************/
+
+
+/****f* ROBODoc/RB_Generate_Doc_End [3.0h]
+ * NAME
+ * RB_Generate_Doc_End -- generate document trailer.
+ * SYNOPSIS
+ * RB_Generate_Doc_End (dest_doc, name)
+ *
+ * RB_Generate_Doc_End (FILE *, char *)
+ * FUNCTION
+ * Generates for depending on the output_mode the text that
+ * will be at the end of a document.
+ * INPUTS
+ * dest_doc - pointer to the file to which the output will
+ * be written.
+ * name - the name of this file.
+ * output_mode - global variable that indicates the output
+ * mode.
+ * NOTES
+ * Doesn't do anything with its arguments, but that might
+ * change in the future.
+ * BUGS
+ * SOURCE
+ */
+
+void
+RB_Generate_Doc_End (FILE * dest_doc, char *name)
+{
+ switch (output_mode)
+ {
+ case AMIGAGUIDE:
+ fputc ('\n', dest_doc);
+ break;
+ case HTML:
+ fprintf (dest_doc, "</BODY></HTML>\n");
+ break;
+ case LATEX:
+ if (!(course_of_action & DO_SINGLEDOC)) {
+ fprintf (dest_doc, "\\end{document}\n");
+ }
+ break;
+ case RTF:
+ fputc ('}', dest_doc);
+ break;
+ case ASCII:
+ break;
+ }
+}
+
+/************/
+
+
+/****f* ROBODoc/RB_Generate_Header_Start [3.0h]
+ * NAME
+ * RB_Generate_Header_Start -- generate header start text.
+ * SYNOPSIS
+ * void RB_Generate_Header_Start (dest_doc, cur_header)
+ *
+ * void RB_Generate_Header_Start (FILE *, struct RB_header *)
+ * FUNCTION
+ * Generates depending on the output_mode the text that
+ * will be at the end of each header.
+ * INPUTS
+ * dest_doc - pointer to the file to which the output will
+ * be written.
+ * cur_header - pointer to a RB_header structure.
+ * SEE ALSO
+ * RB_Generate_Header_End
+ * SOURCE
+ */
+
+void
+RB_Generate_Header_Start (FILE * dest_doc, struct RB_header *cur_header)
+{
+ char *cook_link;
+
+ switch (output_mode)
+ { /* switch by *koessi */
+ case AMIGAGUIDE:
+ if (cur_header->name && cur_header->function_name)
+ {
+ fprintf (dest_doc, "@Node \"%s\" \"%s\"\n",
+ cur_header->function_name,
+ cur_header->name);
+ fprintf (dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, "%s", cur_header->name);
+ fprintf (dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, "\n\n");
+ }
+ break;
+ case HTML:
+ if (cur_header->name && cur_header->function_name)
+ {
+#if 0
+ fprintf (dest_doc, "<HR>\n");
+#endif
+ if (cur_header->type == FUNCTION_HEADER)
+ fprintf (dest_doc,
+ "\n<FONT SIZE=\"+3\" COLOR=\"#000044\"><B>"
+ "Function <A NAME=\"%s\">%s</A>"
+ "</FONT></B><BR><BR>\n\n",
+ cur_header->function_name,
+ cur_header->function_name);
+ else if (cur_header->type == STRUCT_HEADER)
+ fprintf (dest_doc,
+ "\n<FONT SIZE=\"+3\" COLOR=\"#000044\"><B>"
+ "Structure <A NAME=\"%s\">%s</A>"
+ "</FONT></B><BR><BR>\n\n",
+ cur_header->function_name,
+ cur_header->function_name);
+ else if (cur_header->type == VARIABLE_HEADER)
+ fprintf (dest_doc,
+ "\n<FONT SIZE=\"+3\" COLOR=\"#000044\"><B>"
+ "Variable <A NAME=\"%s\">%s</A>"
+ "</FONT></B><BR><BR>\n\n",
+ cur_header->function_name,
+ cur_header->function_name);
+ else
+ fprintf (dest_doc,
+ "\n<FONT SIZE=\"+3\" COLOR=\"#000044\"><B>"
+ "<A NAME=\"%s\">%s</A>"
+ "</FONT></B><BR><BR>\n\n",
+ cur_header->function_name,
+ cur_header->function_name);
+ }
+ break;
+ case LATEX:
+ cook_link = RB_CookStr (cur_header->name);
+ if (!(course_of_action & DO_SINGLEDOC)) {
+ fprintf (dest_doc, "\\newpage\n");
+ }
+ fprintf (dest_doc, "\\subsection{%s}\n", cook_link);
+ free (cook_link);
+ if (cur_header->function_name) {
+ cook_link = RB_CookStr (cur_header->function_name);
+ fprintf (dest_doc, "\\index{unsorted!%s}\\index{%s!%s}\n", cook_link,
+ RB_header_type_names[cur_header->type], cook_link);
+ free (cook_link);
+ }
+ break;
+ case RTF:
+ if (cur_header->name && cur_header->function_name)
+ {
+ cook_link = RB_CookStr (cur_header->function_name);
+ fprintf (dest_doc, "\\page"
+ "{\\super #{\\footnote{\\super #}%s}}"
+ "{\\super ${\\footnote{\\super $}%s}}"
+ "\\cf3 %s\\cf2\\line\n",
+ cur_header->function_name,
+ cur_header->name,
+ cur_header->name);
+ free (cook_link);
+ }
+ break;
+ case ASCII:
+ {
+ fprintf (dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, "%s", cur_header->name);
+ fprintf (dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, "\n\n");
+ }
+ break;
+ }
+}
+
+/******/
+
+
+/****f* ROBODoc/RB_Generate_Header_End [3.0h]
+ * NAME
+ * RB_Generate_Header_End
+ * SYNOPSIS
+ * void RB_Generate_Header_End (dest_doc, cur_header)
+ *
+ * void RB_Generate_Header_End (FILE *, struct RB_header *)
+ * FUNCTION
+ * Generates for depending on the output_mode the text that
+ * will be at the end of a header.
+ * INPUTS
+ * dest_doc - pointer to the file to which the output will
+ * be written.
+ * cur_header - pointer to a RB_header structure.
+ * SEE ALSO
+ * RB_Generate_Header_Start
+ * SOURCE
+ */
+
+void
+RB_Generate_Header_End (FILE * dest_doc, struct RB_header *cur_header)
+{
+ switch (output_mode)
+ { /* switch by *koessi */
+ case AMIGAGUIDE:
+ if (cur_header->name && cur_header->function_name)
+ fprintf (dest_doc, "@endnode\n");
+ break;
+ case HTML:
+ case LATEX:
+ fputc ('\n', dest_doc);
+ break;
+ case RTF:
+ fprintf (dest_doc, "\\par\n");
+ break;
+ case ASCII:
+ fputc ('\f', dest_doc);
+ default:
+ break;
+ }
+}
+
+/*****/
+
+
+/****f* ROBODoc/RB_Generate_Header_Name [3.0c]
+ * NAME
+ * RB_Generate_Header_Name
+ * SYNOPSIS
+ * RB_Generate_Header_Name (dest_doc, name)
+ *
+ * RB_Generate_Header_Name (FILE *, char *)
+ * INPUTS
+ * dest_doc - pointer to the file to which the output will
+ * be written.
+ * name - pointer to the header name.
+ * SOURCE
+ */
+
+void
+RB_Generate_Header_Name (FILE * dest_doc, char *name)
+{
+ char format_str[] = "%s";
+
+ fprintf (dest_doc, format_str, att_start_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, format_str, name);
+ fprintf (dest_doc, format_str, att_stop_command[MAKE_SHINE][output_mode]);
+ fprintf (dest_doc, "\n\n");
+}
+
+/*** RB_Generate_Header_Name ***/
+
+
+/****** ROBODoc/RB_Generate_Item_Name [2.01]
+ * NAME
+ * RB_Generate_Item_Name -- fast&easy
+ * SYNOPSIS
+ * void RB_Generate_Item_Name( FILE * dest_doc, int item_type )
+ * FUNCTION
+ * write the items name to the doc
+ * INPUTS
+ * FILE * dest_doc -- document in progress
+ * int item_type -- this leads to the name and makes colors
+ * AUTHOR
+ * Koessi
+ * NOTES
+ * uses globals: output_mode, item_names[]
+ * SOURCE
+ */
+
+void
+RB_Generate_Item_Name (FILE * dest_doc, int item_type)
+{
+ char format_str[] = "%s";
+
+ if (item_attributes[item_type] & ITEM_NAME_LARGE_FONT)
+ {
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_LARGE][output_mode]);
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_BOLD][output_mode]);
+ if (output_mode == HTML)
+ fprintf (dest_doc, "\n<FONT COLOR=\"#000044\">");
+ fprintf (dest_doc, format_str, item_names[item_type]);
+ if (output_mode == HTML)
+ fprintf (dest_doc, "\n</FONT>");
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_BOLD][output_mode]);
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_LARGE][output_mode]);
+ }
+ else
+ fprintf (dest_doc, format_str, item_names[item_type]);
+
+ fputc ('\n', dest_doc);
+}
+
+/*****/
+
+
+
+/****f* ROBODoc/RB_Generate_Item_Doc [3.0j]
+ * NAME
+ * RB_Generate_Item_Doc
+ * SYNOPSIS
+ * void RB_Generate_Item_Doc(FILE * dest_doc, char *dest_name,
+ * char *begin_of_item,
+ * char *end_of_item,
+ * char *function_name,
+ * int item_type)
+ * FUNCTION
+ * Generates the body text of an item, applying predefined attributes
+ * to the text.
+ * NOTES
+ * Body text is always non-proportional for several reasons:
+ * 1) text is rarely written with prop spacing and text wrapping
+ * in mind -- e.g., see SYNOPSIS above
+ * 2) source code looks better
+ * 3) it simplifies LaTeX handling
+ * SOURCE
+ */
+
+void
+RB_Generate_Item_Doc (FILE * dest_doc, char *dest_name,
+ char *begin_of_item,
+ char *end_of_item,
+ char *function_name,
+ int item_type)
+{
+ char format_str[] = "%s";
+
+ if (begin_of_item == end_of_item)
+ {
+ switch (output_mode)
+ {
+ case HTML:
+ fprintf (dest_doc, "<BR>\n");
+ break;
+ case LATEX:
+ fprintf (dest_doc, "\\\\\n");
+ break;
+ case RTF:
+ fprintf (dest_doc, "\n");
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+ /* For text body in HTML, change to non-prop _before_ changing font
+ * style. * To conform to DTD, this avoids <B><PRE> and instead uses
+ * <PRE><B> */
+ if (output_mode == HTML)
+ {
+ fprintf (dest_doc, "<PRE>");
+ }
+ /* change font style */
+ if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_LARGE][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_ITALICS)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_ITALICS][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_NON_PROP][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_SMALL][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_BOLD)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_BOLD][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_UNDERLINE][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_SHINE)
+ fprintf (dest_doc, format_str,
+ att_start_command[MAKE_SHINE][output_mode]);
+
+ /*
+ * For some modes, the text body is always non-prop
+ */
+ switch (output_mode)
+ {
+ case LATEX:
+ fprintf (dest_doc, "\\begin{verbatim}\n");
+ break;
+ case RTF:
+ fprintf (dest_doc, "{\\f1{}");
+ break;
+ default:
+ break;
+ }
+
+ RB_Generate_Item_Body (dest_doc, dest_name, begin_of_item, end_of_item,
+ function_name, item_type, 0);
+
+ switch (output_mode)
+ {
+ case LATEX:
+ /* split the text so LaTeX doesn't get confused ;) */
+ fprintf (dest_doc, "\\" "end{verbatim}\n");
+ break;
+ case RTF:
+ fputc ('}', dest_doc);
+ default:
+ break;
+ }
+
+ /* restore font style */
+ if (item_attributes[item_type] & TEXT_BODY_SHINE)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_SHINE][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_UNDERLINE][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_BOLD)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_BOLD][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_SMALL][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_NON_PROP][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_ITALICS)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_ITALICS][output_mode]);
+ if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
+ fprintf (dest_doc, format_str,
+ att_stop_command[MAKE_LARGE][output_mode]);
+
+ if (output_mode != HTML)
+ {
+ fputc ('\n', dest_doc);
+ }
+ /* for HTML, switch back to prop-font after restoring font style */
+ if (output_mode == HTML)
+ {
+ fprintf (dest_doc, "</PRE>");
+ }
+}
+
+/******/
+
+
+
+/****f* ROBODoc/RB_Generate_Item_Body [3.0h]
+ * NAME
+ * RB_Generate_Item_Body
+ * SYNOPSIS
+ * char * RB_Generate_Item_Body(FILE * dest_doc, char *dest_name,
+ * char *begin_of_item, char *end_of_item,
+ * char *function_name,
+ * int item_type, int tabs_to_skip)
+ *
+ * FUNCTION
+ * Generates body of an item in output-specific form
+ * INPUTS
+ * dest_doc - pointer to the file to which
+ * the output will be written.
+ * dest_name - the name of this file.
+ * begin_of_item -
+ * end_of_item -
+ * function_name -
+ * item_type -
+ * tabs_to_skip - how many tabs to skip in this fold.
+ * BUGS
+ * o Unbalanced fold marks lead to crash.
+ * NOTES
+ * o Almost completely rewritten by koessi
+ * o Almost completely Re-Rewritten by Slothouber :)
+ * o Folding mode by PetteriK.
+ * o Linking fixed inside folds / PetteriK 08.04.2000
+ * SOURCE
+ */
+
+char *
+RB_Generate_Item_Body (FILE * dest_doc, char *dest_name,
+ char *begin_of_item, char *end_of_item,
+ char *function_name,
+ int item_type, int tabs_to_skip)
+{
+ char *cur_char, old_char, c;
+ int html_incr;
+ char fname[128], foldname[128];
+ static int in_fold = 0; /* PetteriK 08.04.2000 */
+
+ cur_char = begin_of_item;
+
+ if (item_type == SOURCE_ITEM)
+ {
+ /* skip end_comment_marker */
+ for (; *cur_char && *cur_char != '\n'; cur_char++);
+
+ /* skip blank lines leading up to source code */
+ while (*cur_char == '\n')
+ cur_char++;
+
+ /* trim blanks following source code */
+ do
+ {
+ end_of_item--;
+ }
+ while (end_of_item > cur_char && isspace (*end_of_item));
+ end_of_item++; /* advance 1 for placement of the NUL */
+ }
+ old_char = *end_of_item;
+ *end_of_item = '\0';
+
+ for (; *cur_char; cur_char++)
+ {
+ int tb = tab_size;
+ int do_search = TRUE;
+ int was_link = FALSE;
+ int tabs = 0;
+
+ if (item_type != SOURCE_ITEM)
+ {
+ /* Skip empty lines */
+ while (*cur_char == '\n') {
+ cur_char++;
+ }
+ cur_char = RB_Skip_Remark_Marker (cur_char);
+ }
+ else
+ {
+ /* indent source */
+ switch (output_mode)
+ {
+ case RTF:
+ fprintf (dest_doc, "\\tab ");
+ break;
+
+ case AMIGAGUIDE:
+ case HTML:
+ case LATEX:
+ default:
+ fprintf (dest_doc, " ");
+ }
+ }
+
+ while (((c = *cur_char) != '\0') && (c != '\n'))
+ {
+ char *label_name, *file_name;
+ char found = 0;
+ int tmp;
+
+ if (!do_search)
+ {
+ if (!isalnum (c) && (c != '_'))
+ {
+ do_search = TRUE;
+ }
+ }
+ else
+ {
+ if (isalpha (c) || (c == '_'))
+ {
+ if (((was_link = RB_Find_Link (cur_char, &label_name,
+ &file_name)) == FALSE))
+ {
+ do_search = FALSE;
+ }
+ }
+ else
+ was_link = FALSE;
+ }
+
+ if (!was_link)
+ {
+ switch (output_mode)
+ {
+ case AMIGAGUIDE:
+ switch (c)
+ {
+ case '\n':
+ --cur_char;
+ break;
+ case '\t':
+ for (tb %= tab_size; tb < tab_size; ++tb)
+ fputc (' ', dest_doc);
+ break;
+ case '@':
+ fprintf (dest_doc, "\\@");
+ tb++;
+ break;
+ case '\\':
+ fprintf (dest_doc, "\\\\");
+ tb++;
+ break;
+ default:
+ fputc (c, dest_doc);
+ tb++;
+ }
+ break;
+
+ case HTML:
+ /* PetteriK 26.07.1999 */
+ if (extra_flags & FOLD)
+ {
+ cur_char = RB_Check_Fold_Start (cur_char,
+ foldname, &found);
+ }
+ if ((extra_flags & FOLD) && found)
+ {
+ FILE *fp;
+
+ RB_Say ("fold name %s\n", foldname);
+ RB_Say ("fold begin %d\n", ++fold);
+ RB_Say ("tabs %d\n", tabs);
+ sprintf (fname, "%s_fold_%d.html", doc_base, fold);
+ RB_Say ("opening file %s\n", fname);
+ fp = fopen (fname, "w");
+ RB_Generate_Doc_Start (fp, foldname, foldname, 0);
+ fprintf (fp, "<PRE>\n");
+ fprintf (dest_doc, "<A HREF=\"%s\">... %s</A>",
+ fname, foldname);
+ in_fold++; /* PetteriK 08.04.2000 */
+ cur_char = RB_Generate_Item_Body (fp, dest_name,
+ cur_char, end_of_item,
+ function_name,
+ item_type, tabs);
+ in_fold--; /* PetteriK 08.04.2000 */
+ /* skip chars until newline */
+ while (*cur_char != '\n')
+ {
+ cur_char++;
+ }
+ cur_char--;
+ fprintf (fp, "\n</PRE>\n");
+ RB_Generate_Doc_End (fp, foldname);
+ fclose (fp);
+ }
+ else if ((extra_flags & FOLD) && RB_Check_Fold_End (cur_char))
+ {
+ RB_Say ("fold end found\n");
+ return cur_char;
+ }
+ else if ((html_incr = RB_HTML_Extra (dest_doc,
+ item_type, cur_char)))
+ {
+ cur_char += html_incr;
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\n':
+ --cur_char;
+ break;
+ case '\t':
+ if (extra_flags & FOLD)
+ {
+ if (tabs >= tabs_to_skip)
+ {
+ for (tb %= tab_size; tb < tab_size; ++tb)
+ {
+ fputc (' ', dest_doc);
+ }
+ }
+ tabs++;
+ }
+ else
+ {
+ for (tb %= tab_size; tb < tab_size; ++tb)
+ {
+ fputc (' ', dest_doc);
+ }
+ }
+ break;
+ case '<':
+ fprintf (dest_doc, "<");
+ tb++;
+ break;
+ case '>':
+ fprintf (dest_doc, ">");
+ tb++;
+ break;
+ case '&':
+ fprintf (dest_doc, "&");
+ tb++;
+ break;
+ default:
+ fputc (c, dest_doc);
+ tb++;
+ }
+ }
+ break; /* end case HTML */
+
+ case LATEX:
+ switch (c)
+ {
+ case '\n':
+ --cur_char;
+ break;
+ case '\t':
+ for (tb %= tab_size; tb < tab_size; ++tb)
+ fputc (' ', dest_doc);
+ break;
+#if 0
+ /* not used in LaTeX's verbatim environment */
+ case '$':
+ case '&':
+ case '%':
+ case '#':
+ case '_':
+ case '{':
+ case '}':
+ fputc ('\\', dest_doc);
+ fputc (c, dest_doc);
+ tb++;
+ break;
+ case '\\':
+ fprintf (dest_doc, "$\\backslash$");
+ tb++;
+ break;
+ case '~':
+ fprintf (dest_doc, "$\\tilde$");
+ tb++;
+ break;
+ case '^':
+ fprintf (dest_doc, "$\\,\\!^{\\sim}$");
+ tb++;
+ break;
+#endif
+ default:
+ fputc (c, dest_doc);
+ tb++;
+ }
+ break;
+
+ case RTF:
+ switch (c)
+ {
+ case '\n':
+ --cur_char;
+ break;
+ case '\t':
+ for (tb %= tab_size; tb < tab_size; ++tb)
+ fputc (' ', dest_doc);
+ break;
+ case '\\':
+ case '{':
+ case '}':
+ fputc ('\\', dest_doc);
+ fputc (c, dest_doc);
+ tb++;
+ break;
+ default:
+ fputc (c, dest_doc);
+ tb++;
+ }
+ break;
+
+ default:
+ fputc (c, dest_doc);
+ tb++;
+ }
+ cur_char++;
+ }
+ else
+ {
+ switch (output_mode)
+ {
+ case AMIGAGUIDE:
+ if (file_name && strcmp (file_name, dest_name))
+ fprintf (dest_doc, "@{\"%s\" Link \"%s/%s\"}",
+ label_name, file_name, label_name);
+ else
+ {
+ if (strcmp (label_name, function_name))
+ fprintf (dest_doc, "@{\"%s\" Link \"%s\"}",
+ label_name, label_name);
+ else
+ {
+ fprintf (dest_doc, "%s",
+ att_start_command[MAKE_BOLD][output_mode]);
+ fprintf (dest_doc, "%s", label_name);
+ fprintf (dest_doc, "%s",
+ att_stop_command[MAKE_BOLD][output_mode]);
+ }
+ }
+ break;
+
+ case HTML:
+ /* Include the file name in the link if we are in fold
+ * PetteriK 08.04.2000
+ */
+ if (in_fold)
+ {
+ /* We are in fold, always use the file name in the link,
+ * in file_name == NULL (i.e. the label is in the current file
+ * that we are processing), refer to value in dest_name.
+ * This also makes sure that we link correctly if function_name
+ * is the same as label_name.
+ */
+ fprintf (dest_doc, "<A HREF=\"%s#%s\">%s</A>",
+ (file_name ? file_name : dest_name),
+ label_name, label_name);
+ }
+ else if (file_name && strcmp (file_name, dest_name))
+ {
+ fprintf (dest_doc, "<A HREF=\"%s#%s\">%s</A>",
+ file_name, label_name, label_name);
+ }
+ else
+ {
+ if (strcmp (label_name, function_name))
+ {
+ fprintf (dest_doc, "<A HREF=\"#%s\">%s</A>",
+ label_name, label_name);
+ }
+ else
+ {
+ fprintf (dest_doc, "%s",
+ att_start_command[MAKE_BOLD][output_mode]);
+ fprintf (dest_doc, "%s", label_name);
+ fprintf (dest_doc, "%s",
+ att_stop_command[MAKE_BOLD][output_mode]);
+ }
+ }
+ break;
+
+ case RTF:
+ if (strcmp (label_name, function_name))
+ {
+ char *cook_link;
+
+ cook_link = RB_CookStr (label_name);
+ fprintf (dest_doc, "{\\uldb %s}{\\v %s}",
+ label_name, cook_link);
+ free (cook_link);
+ }
+ else
+ {
+ fprintf (dest_doc, "%s",
+ att_start_command[MAKE_BOLD][output_mode]);
+ fprintf (dest_doc, "%s", label_name);
+ fprintf (dest_doc, "%s",
+ att_stop_command[MAKE_BOLD][output_mode]);
+ }
+ break;
+ default:
+ fprintf (dest_doc, "%s", label_name);
+ }
+ tmp = strlen (label_name);
+ cur_char += tmp;
+ tb += tmp;
+ } /* end if */
+ }
+
+ if (*cur_char)
+ {
+ if (output_mode == RTF)
+ fprintf (dest_doc, "\\line");
+ fputc ('\n', dest_doc);
+ tabs = 0;
+ }
+ }
+ *end_of_item = old_char;
+ return (char *) 0;
+}
+
+
+/***************/
+
+
+/****f* ROBODoc/RB_HTML_Extra
+* NAME
+* RB_HTML_Extra
+* AUTHOR
+* PetteriK
+* HISTORY
+* 05/15/2000 Added mailto: support (Guillaume Etorre)
+* FUNCTION
+* Check and process embedded hyperlinks.
+* RETURN VAL* FUNCTION
+* Check and process embedded hyperlinks.
+* RETURN VALUE
+* Number of chars processed from *cur_char
+* TODO
+* Flag for C and other grammars.
+* BUGS
+* As the documentation generated for this functions shows, if
+* the C source code contains a string with " / * " in it, this
+* function fails :)
+* SOURCE
+*/
+
+int
+RB_HTML_Extra (FILE * dest_doc, int item_type, char *cur_char)
+{
+ int res = 0;
+ char link[1024];
+
+ if (strncmp ("http://", cur_char, strlen ("http://")) == 0)
+ {
+ sscanf (cur_char, "%s", link);
+ RB_Say ("found link %s\n", link);
+ res = (strlen (link) - 1);
+ fprintf (dest_doc, "<A HREF=\"%s\">%s</A>", link, link);
+ }
+ else if (strncmp ("href:", cur_char, strlen ("href:")) == 0)
+ {
+ /* handy in relative hyperlink paths, e.g. href:../../modulex/ */
+ sscanf ((cur_char + strlen ("href:")), "%s", link);
+ RB_Say ("found link %s\n", link);
+ res = (strlen (link) + strlen ("href:") - 1);
+ fprintf (dest_doc, "<A HREF=\"%s\">%s</A>", link, link);
+ }
+ else if (strncmp ("mailto:", cur_char, strlen ("mailto:")) == 0)
+ {
+ sscanf ((cur_char + strlen ("mailto:")), "%s", link);
+ RB_Say ("found mail to %s\n", link);
+ res = (strlen (link) + strlen ("mailto:") - 1);
+ fprintf (dest_doc, "<A HREF=\"mailto:%s\">%s</A>", link, link);
+ }
+ else if ((extra_flags & C_MODE) && (item_type == SOURCE_ITEM) &&
+ (strncmp ("/*", cur_char, 2) == 0))
+ {
+ /* start of C comment */
+ fprintf (dest_doc, "<FONT COLOR = \"#FF0000\">/*");
+ res = 1;
+ }
+ else if ((extra_flags & C_MODE) && (item_type == SOURCE_ITEM) &&
+ (strncmp ("*/", cur_char, 2) == 0))
+ {
+ /* end of C comment */
+ fprintf (dest_doc, "*/</FONT>");
+ res = 1;
+ }
+ return res;
+}
+
+/**********/
+
+
+/****f* ROBODoc/RB_Generate_Index
+ * NAME
+ * RB_Generate_Index -- generate index file based on xref files.
+ * SYNOPSIS
+ * void RB_Generate_Index(FILE *dest, char *name)
+ * FUNCTION
+ * Create a master index file. It contains pointers to the
+ * documentation generated for each source file, as well as all
+ * "objects" found in the source files.
+ ********
+ */
+
+void
+RB_Generate_Index (FILE * dest, char *source)
+{
+ RB_Slow_Sort_Links ();
+
+ switch (output_mode)
+ {
+ case HTML:
+ {
+ if (document_title) {
+ RB_Generate_Doc_Start (dest, source, document_title, 0);
+ fprintf (dest, "<H1>%s</H1>\n", document_title);
+ } else {
+ RB_Generate_Doc_Start (dest, source, "Master Index File", 0);
+ fprintf (dest, "<H1>Master Index File</H1>\n");
+ }
+ if (RB_Number_Of_Links (MAIN_HEADER, NULL))
+ RB_Generate_Index_Table (dest, MAIN_HEADER, "Project Modules");
+ RB_Generate_Index_Table (dest, NO_HEADER, "Source Files");
+ if (RB_Number_Of_Links (CLASS_HEADER, NULL))
+ RB_Generate_Index_Table (dest, CLASS_HEADER, "Classes");
+ if (RB_Number_Of_Links (METHOD_HEADER, NULL))
+ RB_Generate_Index_Table (dest, METHOD_HEADER, "Methods");
+ if (RB_Number_Of_Links (STRUCT_HEADER, NULL))
+ RB_Generate_Index_Table (dest, STRUCT_HEADER, "Structures");
+ if (RB_Number_Of_Links (FUNCTION_HEADER, NULL))
+ RB_Generate_Index_Table (dest, FUNCTION_HEADER, "Functions");
+ if (RB_Number_Of_Links (VARIABLE_HEADER, NULL))
+ RB_Generate_Index_Table (dest, VARIABLE_HEADER, "Variables");
+ if (RB_Number_Of_Links (CONSTANT_HEADER, NULL))
+ RB_Generate_Index_Table (dest, CONSTANT_HEADER, "Constants");
+ if (RB_Number_Of_Links (GENERIC_HEADER, NULL))
+ RB_Generate_Index_Table (dest, GENERIC_HEADER, "Generic");
+ if (RB_Number_Of_Links (INTERNAL_HEADER, NULL))
+ RB_Generate_Index_Table (dest, INTERNAL_HEADER, "Internal");
+ RB_Generate_Doc_End (dest, source);
+ } break;
+ case LATEX:
+ {
+ RB_Generate_Doc_Start (dest, source, "Master File", 0);
+ RB_Generate_LaTeX_Includes (dest);
+ RB_Generate_Doc_End (dest, source);
+ }
+ }
+}
+
+
+/****f* ROBODoc/Generate_LaTeX_Includes
+ * NAME
+ * Generate_LaTeX_Includes -- generate include commands
+ * SYNOPSIS
+ * void RB_Generate_LaTeX_Includes (FILE *dest)
+ * FUNCTION
+ * Generates a series of \include commands to include the
+ * documentation generated for each source file into one
+ * big file.
+ ****
+ */
+
+void
+RB_Generate_LaTeX_Includes (FILE *dest)
+{
+ struct RB_link *cur_link;
+ for (cur_link = first_link;
+ cur_link;
+ cur_link = cur_link->next_link) {
+ {
+ if (cur_link->type == NO_HEADER)
+ fprintf (dest, "\\include{%s}\n", cur_link->label_name);
+ }
+ }
+}
+
+/****f* ROBODoc/RB_Generate_Index_Table
+ * NAME
+ * RB_Generate_Index --
+ * SYNOPSIS
+ * void RB_Generate_Index_Table(FILE *, int type, char *title)
+ * RB_Generate_Index_Table(dest, type, title)
+ * FUNCTION
+ * Creates a table with index items of a particular type.
+ * If the type is NO_HEADER, then the table is a table of
+ * source files. In this case no link is added if the
+ * source file did not contain any documentation.
+ * INPUTS
+ * dest -- output file
+ * type -- kind of header index.
+ * title -- title for the table
+ * SOURCE
+ */
+
+void
+RB_Generate_Index_Table (FILE * dest, int type, char *title)
+{
+ struct RB_link *cur_link;
+ int number_of_columns;
+ int cur_column;
+
+ number_of_columns = 60 / RB_Max_Name_Length (type, NULL);
+
+ fprintf (dest, "<H2>%s</H2>\n", title);
+ fprintf (dest, "<TABLE>\n");
+ cur_column = 0;
+ for (cur_link = first_link;
+ cur_link;
+ cur_link = cur_link->next_link)
+ {
+ if (cur_link->type == type)
+ {
+ if (cur_column == 0)
+ {
+ fprintf (dest, "<TR>\n");
+ }
+ if (type == NO_HEADER)
+ {
+ if (RB_Number_Of_Links (NO_HEADER, cur_link->file_name) > 1)
+ {
+ fprintf (dest,
+ "<TD><A HREF=\"%s#%s\"><TT>%s</TT></A></TD>\n",
+ cur_link->file_name, cur_link->label_name,
+ cur_link->label_name);
+ }
+ else
+ {
+ fprintf (dest, "<TD>%s</TD>\n", cur_link->label_name);
+ }
+ }
+ else
+ {
+ fprintf (dest, "<TD><A HREF=\"%s#%s\"><TT>%s</TT></A></TD>\n",
+ cur_link->file_name, cur_link->label_name,
+ cur_link->label_name);
+ };
+ cur_column++;
+ if (cur_column > number_of_columns)
+ {
+ fprintf (dest, "</TR>\n");
+ cur_column = 0;
+ }
+ }
+ }
+ for (; cur_column <= number_of_columns;)
+ {
+ if (cur_column == 0)
+ {
+ fprintf (dest, "<TR>\n");
+ }
+ fprintf (dest, "<TD></TD>\n");
+ cur_column++;
+ }
+ fprintf (dest, "</TR>\n");
+ fprintf (dest, "</TABLE>\n");
+}
+
+/******* END RB_Generate_Index_Table *****/
+
+
+/****f* ROBODoc/RB_Number_Of_Links
+ * NAME
+ * RB_Number_Of_Links -- Count the number of links.
+ * FUNCTION
+ * Counts the number of links that are of a particular type
+ * and that can be found in a particular file.
+ * INPUTS
+ * type -- the header type of the header the link is pointing to.
+ * If NO_HEADER, all header types are counted.
+ * file_name -- name of the file the link comes from, can be NULL, in
+ * which case only the type is checked.
+ * RESULT
+ * number of links.
+ ******
+ */
+
+int
+RB_Number_Of_Links (int type, char *file_name)
+{
+ struct RB_link *cur_link;
+ int n = 0;
+
+ for (cur_link = first_link;
+ cur_link;
+ cur_link = cur_link->next_link)
+ {
+ if (cur_link->type == type || (type == NO_HEADER))
+ {
+ if (file_name)
+ {
+ if (strcmp (file_name, cur_link->file_name) == 0)
+ {
+ n++;
+ }
+ }
+ else
+ {
+ n++;
+ }
+ }
+ }
+
+ return n;
+}
+
+
+/****f* ROBODoc/RB_Max_Name_Length
+ * NAME
+ * RB_Max_Name_Length -- find longest label name.
+ * FUNCTION
+ * Find the length of the longest label name in a sub list
+ * of the list with links. This is used to determine how
+ * many columns can be displayed in a table.
+ * The sublist is specified by the type of header the link
+ * should point to, as well as by the name of the documentation
+ * file.
+ * EXAMPLE
+ * RB_Max_Name_Length(CLASS_HEADER, "muppets.c.html")
+ * longest label name in the list of links to class headers
+ * in muppets.c.html.
+ * RB_Max_Name_Length(CLASS_HEADER, NULL)
+ * longest label name in the list of links to class headers.
+ * INPUTS
+ * type -- type of header
+ * file_name -- file the header come from, can be NULL.
+ * In which links from all files are used.
+ * SOURCE
+ */
+
+int
+RB_Max_Name_Length (int type, char *file_name)
+{
+ struct RB_link *cur_link;
+ int n = 1;
+
+ for (cur_link = first_link;
+ cur_link;
+ cur_link = cur_link->next_link)
+ {
+ if (cur_link->type == type)
+ {
+ if (file_name)
+ {
+ if (strcmp (file_name, cur_link->file_name) == 0)
+ {
+ if (strlen (cur_link->label_name) > n)
+ {
+ n = strlen (cur_link->label_name);
+ }
+ }
+ }
+ else
+ {
+ if (strlen (cur_link->label_name) > n)
+ {
+ n = strlen (cur_link->label_name);
+ }
+ }
+ }
+ }
+ return n;
+}
+
+/*********/