--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "robodoc.h"
+#include "headers.h"
+#include "util.h"
+#include "links.h"
+#include "folds.h"
+
+
+FILE *xreffiles_file = NULL;
+FILE *xref_file = NULL;
+int link_index_size = 0;
+struct RB_link **link_index = NULL;
+
+/****f* ROBODoc/RB_Analyse_Xrefs [3.0b]
+ * NAME
+ * RB_Analyse_Xrefs -- scan the xref files.
+ * SYNOPSIS
+ * RB_Analyse_Xrefs (xreffiles_file)
+ * RB_Analyse_Xrefs (FILE *)
+ * FUNCTION
+ * Scan the file xreffiles_file. This file contains the
+ * names of one or more xref files. All the references in the
+ * files are scaned and stored in a link list of the type
+ * RB_link. These xref files can be generated with robodoc.
+ * INPUTS
+ * xreffiles_file - a file pointer to the file with xref file
+ * names.
+ * RESULT
+ * none
+ * BUGS
+ * Might fail if there are syntax errors in one of the xref
+ * files.
+ * Bad use of feof() and fgets().
+ * SEE ALSO
+ * RB_Generate_xrefs, RB_Add_Link
+ * SOURCE
+ */
+
+void
+RB_Analyse_Xrefs (FILE * xreffiles_file)
+{
+ while (!feof (xreffiles_file))
+ {
+ fgets (line_buffer, MAX_LINE_LEN, xreffiles_file);
+ if (!feof (xreffiles_file))
+ {
+ char *cur_char;
+
+ cur_char = line_buffer;
+ find_eol;
+ if (*cur_char == '\n')
+ *cur_char = '\0';
+ if (strlen (line_buffer) > 1)
+ {
+ for (cur_char--;
+ (cur_char != line_buffer) && isspace (*cur_char);
+ cur_char--)
+ *cur_char = '\0';
+ if ((xref_file = fopen (line_buffer, "r")) != NULL)
+ {
+ int xrefs_found = FALSE;
+ int end_of_xrefs = FALSE;
+
+ while (!feof (xref_file) && !xrefs_found)
+ {
+ fgets (line_buffer, MAX_LINE_LEN, xref_file);
+ if (!feof (xref_file) && !strncmp ("XREF:",
+ line_buffer, 5))
+ xrefs_found = TRUE;
+ }
+
+ while (!feof (xref_file) && !end_of_xrefs)
+ {
+ fgets (line_buffer, MAX_LINE_LEN, xref_file);
+ if (!feof (xref_file))
+ {
+ cur_char = line_buffer;
+ find_quote;
+ if (*cur_char == '\"')
+ RB_Add_Link ();
+ else
+ end_of_xrefs = TRUE;
+ }
+ }
+ fclose (xref_file);
+ xref_file = NULL;
+ }
+ else
+ RB_Panic ("could not open xref file \"%s\"\n", line_buffer);
+ }
+ }
+ }
+}
+
+/*************/
+
+
+/****f* ROBODoc/RB_Slow_Sort_Links
+ * NAME
+ * RB_Slow_Sort_Links -- sort all links according to label name.
+ ******
+ */
+
+void
+RB_Slow_Sort_Links (void)
+{
+ struct RB_link *cur_link, *unsorted_links, *bigger_link;
+
+ if ((unsorted_links = first_link) != NULL)
+ { /* additional check koessi */
+ for (first_link = NULL;
+ unsorted_links->next_link;)
+ {
+ for (bigger_link = unsorted_links,
+ cur_link = bigger_link->next_link;
+ cur_link;
+ cur_link = cur_link->next_link)
+ {
+ if (strcmp (cur_link->label_name, bigger_link->label_name) > 0)
+ bigger_link = cur_link;
+ }
+ RB_Remove_From_List ((struct RB_header **) &unsorted_links,
+ (struct RB_header *) bigger_link);
+ RB_Insert_In_List ((struct RB_header **) &first_link,
+ (struct RB_header *) bigger_link);
+ }
+ RB_Insert_In_List ((struct RB_header **) &first_link,
+ (struct RB_header *) unsorted_links);
+ }
+}
+
+
+/****f* ROBODoc/RB_Add_Link [3.0b]
+ * NAME
+ * RB_Add_Link -- add a reference link to the list
+ * SYNOPSIS
+ * void RB_Add_Link ()
+ * FUNCTION
+ * Adds a reference from a xref file to the linked list
+ * with references.
+ * INPUTS
+ * Uses the global variable line_buffer and first_link.
+ * NOTES
+ * Makes sneaky use of the function RB_Insert_In_List.
+ * SEE ALSO
+ * RB_Analyse_Xrefs, RB_link.
+ * SOURCE
+ */
+
+void
+RB_Add_Link ()
+{
+ char *label_name, *file_name;
+ struct RB_link *new_link;
+ char *cur_char = line_buffer;
+
+ find_quote;
+ label_name = ++cur_char;
+ find_quote;
+ *cur_char++ = '\0';
+ find_quote;
+ file_name = ++cur_char;
+ find_quote;
+ *cur_char = '\0';
+ ++cur_char;
+
+ RB_Say ("adding xref link \"%s\"->\"%s\"\n", label_name, file_name);
+
+ new_link = RB_Alloc_Link (label_name, file_name);
+ new_link->type = atoi (cur_char);
+ RB_Insert_In_List ((struct RB_header **) &first_link,
+ (struct RB_header *) new_link);
+}
+
+/*** RB_Add_Link ***/
+
+
+
+/****f* ROBODoc/RB_Generate_xrefs [2.0]
+ * NAME
+ * RB_Generate_xrefs
+ * SYNOPSIS
+ * RB_Generate_xrefs (dest_doc, source_name, dest_name)
+ *
+ * RB_Generate_xrefs (FILE *, char *, char *)
+ * FUNCTION
+ * Generates a xref file for the document that has been
+ * analysed by ROBODoc.
+ * INPUTS
+ * dest_doc - pointer to the file to which the xrefs will be
+ * written.
+ * source_name - pointer to the name of the document that has
+ * been analysed by robodoc
+ * dest_name - pointer to the name of the document robodoc will
+ * write the documentation to.
+ * first_header - global variable, the list with function
+ * headers.
+ * SOURCE
+ */
+
+void
+RB_Generate_xrefs (FILE * dest_doc, char *source_name, char *dest_name)
+{
+ struct RB_header *cur_header;
+
+ fprintf (dest_doc, "/* XREF-File generated by ROBODoc v" VERSION
+ " */\n");
+ fprintf (dest_doc, "\nXREF:\n");
+ fprintf (dest_doc, " \"%s\" \"%s\" 0\n", source_name, dest_name);
+ for (cur_header = first_header;
+ cur_header;
+ cur_header = cur_header->next_header
+ )
+ {
+ if (cur_header->function_name)
+ fprintf (dest_doc, " \"%s\" \"%s\" %d\n",
+ cur_header->function_name, dest_name, cur_header->type);
+ }
+ fprintf (dest_doc, "\n/* End of XREF-File */\n");
+}
+
+/*** RB_Generate_xrefs ***/
+
+
+
+/****f* ROBODoc/RB_Find_Link [3.0h]
+ * NAME
+ * RB_Find_Link -- try to match word with a link
+ * SYNOPSIS
+ * result = RB_Find_Link (word_begin, label_name, file_name)
+ * int RB_Find_Link (char *, char **, char **)
+ * FUNCTION
+ * Searches for the given word in the list of links and
+ * headers. There are three passes (or four, when the C option
+ * is selected). Each pass uses a different definition of "word".
+ * In the first pass it is any thing that ends with a 'space', a '.'
+ * or a ','.
+ * In the second pass it is any string that consists of alpha
+ * numerics, '_', ':', '.', or '-'.
+ * In the third pass (for C) it is any string that consists
+ * of alpha numerics or '_'.
+ * In the last pass it is any string that consists of alpha
+ * numerics.
+ * INPUTS
+ * word_begin - pointer to a word (a string).
+ * label_name - pointer to a pointer to a string
+ * file_name - pointer to a pointer to a string
+ * SIDE EFFECTS
+ * label_name & file_name are modified
+ * RESULT
+ * label_name -- points to the label if a match was found,
+ * NULL otherwise.
+ * file_name -- points to the file name if a match was found,
+ * NULL otherwise.
+ * TRUE -- a match was found.
+ * FALSE -- no match was found.
+ * NOTES
+ * This is a rather sensitive algorithm.
+ * BUGS
+ ******
+ */
+
+int
+RB_Find_Link (char *word_begin, char **label_name, char **file_name)
+{
+ char *cur_char, old_char;
+ int low_index, high_index, cur_index, state, pass;
+
+
+ for (pass = 0; pass < 4; pass++)
+ {
+
+ switch (pass)
+ {
+ case 0:
+ {
+ for (cur_char = word_begin;
+ isalnum (*cur_char) || ispunct (*cur_char);
+ cur_char++);
+ if (((*(cur_char-1)) == ',') || ((*(cur_char-1)) == '.'))
+ cur_char--;
+ break;
+ }
+ case 1:
+ {
+ for (cur_char = word_begin;
+ isalnum (*cur_char) || (*cur_char == '_') ||
+ (*cur_char == '-') || (*cur_char == '.') ||
+ (*cur_char == ':');
+ cur_char++);
+ break;
+ }
+ case 2:
+ {
+ if (extra_flags & C_MODE) {
+ for (cur_char = word_begin;
+ isalnum(*cur_char) || (*cur_char == '_');
+ cur_char++);
+ break;
+ }
+ else continue;
+ }
+ case 3:
+ {
+ for (cur_char = word_begin;
+ isalnum (*cur_char);
+ cur_char++);
+ break;
+ }
+ }
+
+ old_char = *cur_char;
+ *cur_char = '\0'; /* End the word with a '\0' */
+/* RB_Say ("Testing \"%s\"\n", word_begin); */
+
+ /* Search in header table */
+ for (cur_index = 0, low_index = 0, high_index = header_index_size - 1;
+ high_index >= low_index;)
+ {
+ cur_index = (high_index - low_index) / 2 + low_index;
+ state = strcmp (word_begin, header_index[cur_index]->function_name);
+ if (state < 0)
+ high_index = cur_index - 1;
+ else if (state > 0)
+ low_index = cur_index + 1;
+ else
+ {
+ *label_name = header_index[cur_index]->function_name;
+ *file_name = NULL;
+ RB_Say ("linking \"%s\"->\"%s\"\n", word_begin, *label_name);
+ *cur_char = old_char;
+ return (TRUE);
+ }
+ }
+
+ /* Search in the link table */
+ for (cur_index = 0, low_index = 0, high_index = link_index_size - 1;
+ high_index >= low_index;)
+ {
+ cur_index = (high_index - low_index) / 2 + low_index;
+ state = strcmp (word_begin, link_index[cur_index]->label_name);
+ if (state < 0)
+ {
+ high_index = cur_index - 1;
+ }
+ else if (state == 0)
+ {
+ *label_name = link_index[cur_index]->label_name;
+ *file_name = link_index[cur_index]->file_name;
+ RB_Say ("linking \"%s\"->\"%s\" form \"%s\"\n",
+ word_begin, *label_name, *file_name);
+ *cur_char = old_char;
+ return (TRUE);
+ }
+ else if (state > 0)
+ {
+ low_index = cur_index + 1;
+ }
+ }
+ *cur_char = old_char;
+ *file_name = NULL;
+ *label_name = NULL;
+ }
+
+ return (FALSE);
+}
+
+
+
+
+
+/****f* ROBODoc/RB_Alloc_Link [2.01]
+ * NAME
+ * RB_Alloc_Link -- oop
+ * SYNOPSIS
+ * struct RB_link *RB_Alloc_Link( char *label_name, char *file_name )
+ * FUNCTION
+ * allocate struct + strings
+ * INPUTS
+ * char *label_name -- strings to copy into the link
+ * char *file_name
+ * RESULT
+ * struct RB_link * -- ready-to-use
+ * AUTHOR
+ * Koessi
+ * SEE ALSO
+ * RB_StrDup(), RB_Free_Link()
+ *******
+ */
+
+struct RB_link *
+RB_Alloc_Link (char *label_name, char *file_name)
+{
+ struct RB_link *new_link;
+ if ((new_link = malloc (sizeof (struct RB_link))) != NULL)
+ {
+ memset (new_link, 0, sizeof (struct RB_link));
+
+ if (file_name)
+ new_link->file_name = RB_StrDup (file_name);
+ if (label_name)
+ new_link->label_name = RB_StrDup (label_name);
+ }
+ else
+ RB_Panic ("out of memory! [Alloc Link]\n");
+
+ return (new_link);
+}
+
+
+/****f* ROBODoc/RB_Free_Link [2.01]
+ * NAME
+ * RB_Free_Link -- oop
+ * SYNOPSIS
+ * void RB_Free_Link( struct RB_link *link )
+ * FUNCTION
+ * free struct + strings
+ * INPUTS
+ * struct RB_link *link
+ * AUTHOR
+ * Koessi
+ * SEE ALSO
+ * RB_Alloc_Link(), RB_Close_The_Shop()
+ * SOURCE
+ ******
+ */
+
+void
+RB_Free_Link (struct RB_link *link)
+{
+ if (link)
+ {
+ if (link->label_name)
+ free (link->label_name);
+ if (link->file_name)
+ free (link->file_name);
+ free (link);
+ }
+}