Initial release of Maemo 5 port of gnuplot
[gnuplot] / docs / xref.c
diff --git a/docs/xref.c b/docs/xref.c
new file mode 100644 (file)
index 0000000..e056ce1
--- /dev/null
@@ -0,0 +1,338 @@
+#ifndef lint
+static char *RCSid() { return RCSid("$Id: xref.c,v 1.11 2005/04/22 21:40:37 broeker Exp $"); }
+#endif
+
+/* GNUPLOT - xref.c */
+
+/*[
+ * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
+ *
+ * Permission to use, copy, and distribute this software and its
+ * documentation for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ *
+ * Permission to modify the software is granted, but not the right to
+ * distribute the complete modified source code.  Modifications are to
+ * be distributed as patches to the released version.  Permission to
+ * distribute binaries produced by compiling modified sources is granted,
+ * provided you
+ *   1. distribute the corresponding source modifications from the
+ *    released version in the form of a patch file along with the binaries,
+ *   2. add special version identification to distinguish your version
+ *    in addition to the base release version number,
+ *   3. provide your name and address as the primary contact for the
+ *    support of your modified version, and
+ *   4. retain our contact information in regard to use of the base
+ *    software.
+ * Permission to distribute the released version of the source code along
+ * with corresponding source modifications in the form of a patch file is
+ * granted with same provisions 2 through 4 for binary distributions.
+ *
+ * This software is provided "as is" without express or implied warranty
+ * to the extent permitted by applicable law.
+]*/
+
+/*
+ * this file is used by doc2ipf, doc2html, doc2rtf and doc2info
+ *
+ * MUST be included after termdoc.c (since termdoc.c redefines fgets() )
+ *
+ * it contains functions needed to handle xrefs, most of them from
+ *     doc2rtf (most likely) by Maurice Castro
+ *  or doc2ipf by Roger Fearick
+ *  or doc2html by Russel Lang
+ *
+ * I have modified the functions a little to make them more flexible
+ * (lookup returns list instead of list->line) or let them work with all
+ * four programs (adding three parameters to refs).
+ *
+ * I switched the search order of lookup. Makes more sense to me
+ *
+ * Stefan Bodewig 1/29/1996
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define DOCS_XREF_MAIN
+
+#include "syscfg.h"
+#include "stdfn.h"
+#include "doc2x.h"
+#include "xref.h"
+
+struct LIST *list = NULL;
+struct LIST *head = NULL;
+
+struct LIST *keylist = NULL;
+struct LIST *keyhead = NULL;
+
+void dump_list __PROTO((void));
+
+int maxlevel = 0;              /* how deep are the topics nested? */
+int listitems = 0;             /* number of topics */
+
+/* for debugging (invoke from gdb !) */
+void
+dump_list()
+{
+    struct LIST *element = head;
+    while (element) {
+       fprintf(stderr, "%p level %d, line %d, \"%s\"\n", element,
+               element->level, element->line, element->string);
+       element = element->next;
+    }
+}
+
+
+generic *
+xmalloc(size_t size)
+{
+    generic *p = malloc(size);
+
+    if (!p) {
+        fprintf(stderr, "Malloc failed\n");
+       exit(EXIT_FAILURE);
+    }
+    return p;
+}
+
+/* scan the file and build a list of line numbers where particular levels are */
+void
+parse(FILE *a)
+{
+    static char line[MAX_LINE_LEN+1];
+    char *c;
+    int lineno = 0;
+    int lastline = 0;
+
+    /* insert a special level 0 listitem
+     * this one is the starting point for the table of contents in the html
+     * version and the Top-Node of the info version.
+     *
+     * Added this to support multiple level 1 items.     --SB
+     */
+    listitems = 1;
+    head = (list = (struct LIST *) xmalloc(sizeof(struct LIST)));
+    list->prev = NULL;
+    list->line = 0;
+    list->level = 0;
+    /* I would prefer list->string = NULL, but don't know if free(NULL) is OK
+     * with all supported plattforms. */
+    list->string = (char *) xmalloc(1);
+    list->next = NULL;
+
+    while (get_line(line, sizeof(line), a)) {
+       lineno++;
+       if (isdigit((int)line[0])) {    /* start of new section */
+           listitems++;
+
+           if (list == NULL) { /* impossible with the new level 0 item */
+               head = (list = (struct LIST *) xmalloc(sizeof(struct LIST)));
+               list->prev = NULL;
+           } else {
+               list->next = (struct LIST *) xmalloc(sizeof(struct LIST));
+               list->next->prev = list;
+               list = list->next;
+               list->next = NULL;
+           }
+
+           list->line = lastline = lineno;
+           list->level = line[0] - '0';
+           list->string = (char *) xmalloc(strlen(line) + 1);
+           c = strtok(&(line[1]), "\n");
+           strcpy(list->string, c);
+           list->next = NULL;
+           if (list->level > maxlevel)
+               maxlevel = list->level;
+       }
+       if (line[0] == '?') {   /* keywords */
+           if (keylist == NULL) {
+               keyhead = (keylist = (struct LIST *) xmalloc(sizeof(struct LIST)));
+               keylist->prev = NULL;
+           } else {
+               keylist->next = (struct LIST *) xmalloc(sizeof(struct LIST));
+               keylist->next->prev = keylist;
+               keylist = keylist->next;
+           }
+
+           keylist->line = lastline;
+           keylist->level = list->level;
+           c = strtok(&(line[1]), "\n");
+           if (c == NULL || *c == '\0')
+               c = list->string;
+           keylist->string = (char *) malloc(strlen(c) + 1);
+           strcpy(keylist->string, c);
+           keylist->next = NULL;
+       }
+    }
+    rewind(a);
+}
+
+/* look up a topic in text reference */
+/*
+ * Original version from doc2rtf (|| ipf || html) scanned keylist before list.
+ * This way we get a reference to `plot` for the topic `splot` instead
+ * of one to `splot`. Switched the search order -SB.
+ */
+struct LIST *
+lookup(char *s)
+{
+    char *c;
+    char tokstr[MAX_LINE_LEN+1];
+    char *match;
+    int l;
+
+    strcpy(tokstr, s);
+
+    /* first try titles */
+    match = strtok(tokstr, " \n\t");
+    if (match == NULL) {
+       fprintf(stderr, "Error in lookup(\"%s\")\n", s);
+
+       /* there should a line number, but it is local to parse()  */
+       fprintf(stderr,
+               "Possible missing link character (`) near above line number\n");
+       exit(3);
+    }
+    l = 0;                     /* level */
+
+    list = head;
+    while (list != NULL) {
+       c = list->string;
+       while (isspace((int)(*c)))
+           c++;
+       if (!strcmp(match, c)) {
+           l = list->level;
+           match = strtok(NULL, "\n\t ");
+           if (match == NULL) {
+               return (list);
+           }
+       }
+       if (l > list->level)
+           break;
+       list = list->next;
+    }
+
+    /* then try the ? keyword entries */
+    keylist = keyhead;
+    while (keylist != NULL) {
+       c = keylist->string;
+       while (isspace((int)(*c)))
+           c++;
+       if (!strcmp(s, c))
+           return (keylist);
+       keylist = keylist->next;
+    }
+
+    return (NULL);
+}
+
+/*
+ * find title-entry for keyword-entry
+ */
+struct LIST *
+lkup_by_number(int line)
+{
+    struct LIST *run = head;
+
+    while (run->next && run->next->line <= line)
+       run = run->next;
+
+    if (run->next)
+       return run;
+    else
+       return NULL;
+}
+
+/*
+ * free the whole list (I never trust the OS -SB)
+ */
+void
+list_free()
+{
+    struct LIST *run;
+
+    for (run = head; run->next; run = run->next)
+       ; /* do nothing */
+
+    for (run = run->prev; run; run = run->prev) {
+       free(run->next->string);
+       free(run->next);
+    }
+    free(head->string);
+    free(head);
+
+    for (run = keyhead; run->next; run = run->next)
+       ; /* do nothing */
+    for (run = run->prev; run; run = run->prev) {
+       free(run->next->string);
+       free(run->next);
+    }
+    free(keyhead->string);
+    free(keyhead);
+}
+
+
+/* search through the list to find any references */
+/*
+ * writes a menu of all subtopics of the topic located at l
+ * format must contain %s for the title of the subtopic and may contain
+ * a %d for the line number of the subtopic (used by doc2html and doc2rtf
+ * The whole menu is preceeded by start and gets the trailer end
+ */
+void
+refs( int l, FILE *f, char *start, char *end, char *format)
+{
+    int curlevel, i;
+    char *c;
+    int inlist = FALSE;
+
+    /* find current line */
+    list = head;
+    while (list->line != l)
+       list = list->next;
+    curlevel = list->level;
+    list = list->next;         /* look at next element before going on */
+
+    if (start != NULL && list != NULL) {
+       /* don't write start if there's no menue at all */
+       inlist = TRUE;
+       fprintf(f, "%s", start);
+    }
+    while (list != NULL) {
+       /* we are onto the next topic so stop */
+       if (list->level == curlevel)
+           break;
+       /* these are the next topics down the list */
+       if (list->level == curlevel + 1) {
+           c = list->string;
+           while (isspace((int)(*c)))
+               c++;            /* strip leading whitespace */
+
+           if (format != NULL) {
+               for (i = 0; format[i] != '%' && format[i] != '\0'; i++);
+               if (format[i] != '\0') {
+                   if (format[i + 1] == 'd') {
+                       /* line number has to be printed first */
+                       fprintf(f, format, list->line, c);
+                   }
+                   else {
+                       ++i;
+                       for (; format[i] != '%' && format[i] != '\0'; i++);
+                       if (format[i] != '\0')  /* line number is second */
+                           fprintf(f, format, c, list->line);
+                       else    /* no line number at all */
+                           fprintf(f, format, c);
+                   }
+               }
+           }
+       }
+       list = list->next;
+    }
+    if (inlist && end)         /* trailer */
+       fprintf(f, "%s", end);
+}