Initial revision
[silc.git] / util / robodoc / Source / links.c
diff --git a/util/robodoc/Source/links.c b/util/robodoc/Source/links.c
new file mode 100644 (file)
index 0000000..7609a6d
--- /dev/null
@@ -0,0 +1,442 @@
+#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);
+    }
+}