/* * $Id: xref.c,v 1.9 1998/03/22 23:31:53 drd Exp $ * */ /* GNUPLOT - xref.c */ /*[ * Copyright 1986 - 1993, 1998 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 "ansichek.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; 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; } } #ifdef PROTOTYPES void *xmalloc(size_t size) { void *p = malloc(size); #else char *xmalloc(size) /* think this is correct for K&R C */ unsigned int size; { char *p = malloc(size); #endif if (p) return p; fprintf(stderr, "Malloc failed\n"); exit(1); return NULL; /* HBB 980317: kill superfluous warnings */ } /* scan the file and build a list of line numbers where particular levels are */ void parse(a) 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(s) 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(line) 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 __PROTO((void)) { struct LIST *run; for (run = head; run->next; run = run->next); 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); 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(l, f, start, end, format) int l; FILE *f; char *start, *end, *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 wrie 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); }