2 static char *RCSid() { return RCSid("$Id: xref.c,v 1.11 2005/04/22 21:40:37 broeker Exp $"); }
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
38 * this file is used by doc2ipf, doc2html, doc2rtf and doc2info
40 * MUST be included after termdoc.c (since termdoc.c redefines fgets() )
42 * it contains functions needed to handle xrefs, most of them from
43 * doc2rtf (most likely) by Maurice Castro
44 * or doc2ipf by Roger Fearick
45 * or doc2html by Russel Lang
47 * I have modified the functions a little to make them more flexible
48 * (lookup returns list instead of list->line) or let them work with all
49 * four programs (adding three parameters to refs).
51 * I switched the search order of lookup. Makes more sense to me
53 * Stefan Bodewig 1/29/1996
60 #define DOCS_XREF_MAIN
67 struct LIST *list = NULL;
68 struct LIST *head = NULL;
70 struct LIST *keylist = NULL;
71 struct LIST *keyhead = NULL;
73 void dump_list __PROTO((void));
75 int maxlevel = 0; /* how deep are the topics nested? */
76 int listitems = 0; /* number of topics */
78 /* for debugging (invoke from gdb !) */
82 struct LIST *element = head;
84 fprintf(stderr, "%p level %d, line %d, \"%s\"\n", element,
85 element->level, element->line, element->string);
86 element = element->next;
94 generic *p = malloc(size);
97 fprintf(stderr, "Malloc failed\n");
103 /* scan the file and build a list of line numbers where particular levels are */
107 static char line[MAX_LINE_LEN+1];
112 /* insert a special level 0 listitem
113 * this one is the starting point for the table of contents in the html
114 * version and the Top-Node of the info version.
116 * Added this to support multiple level 1 items. --SB
119 head = (list = (struct LIST *) xmalloc(sizeof(struct LIST)));
123 /* I would prefer list->string = NULL, but don't know if free(NULL) is OK
124 * with all supported plattforms. */
125 list->string = (char *) xmalloc(1);
128 while (get_line(line, sizeof(line), a)) {
130 if (isdigit((int)line[0])) { /* start of new section */
133 if (list == NULL) { /* impossible with the new level 0 item */
134 head = (list = (struct LIST *) xmalloc(sizeof(struct LIST)));
137 list->next = (struct LIST *) xmalloc(sizeof(struct LIST));
138 list->next->prev = list;
143 list->line = lastline = lineno;
144 list->level = line[0] - '0';
145 list->string = (char *) xmalloc(strlen(line) + 1);
146 c = strtok(&(line[1]), "\n");
147 strcpy(list->string, c);
149 if (list->level > maxlevel)
150 maxlevel = list->level;
152 if (line[0] == '?') { /* keywords */
153 if (keylist == NULL) {
154 keyhead = (keylist = (struct LIST *) xmalloc(sizeof(struct LIST)));
155 keylist->prev = NULL;
157 keylist->next = (struct LIST *) xmalloc(sizeof(struct LIST));
158 keylist->next->prev = keylist;
159 keylist = keylist->next;
162 keylist->line = lastline;
163 keylist->level = list->level;
164 c = strtok(&(line[1]), "\n");
165 if (c == NULL || *c == '\0')
167 keylist->string = (char *) malloc(strlen(c) + 1);
168 strcpy(keylist->string, c);
169 keylist->next = NULL;
175 /* look up a topic in text reference */
177 * Original version from doc2rtf (|| ipf || html) scanned keylist before list.
178 * This way we get a reference to `plot` for the topic `splot` instead
179 * of one to `splot`. Switched the search order -SB.
185 char tokstr[MAX_LINE_LEN+1];
191 /* first try titles */
192 match = strtok(tokstr, " \n\t");
194 fprintf(stderr, "Error in lookup(\"%s\")\n", s);
196 /* there should a line number, but it is local to parse() */
198 "Possible missing link character (`) near above line number\n");
204 while (list != NULL) {
206 while (isspace((int)(*c)))
208 if (!strcmp(match, c)) {
210 match = strtok(NULL, "\n\t ");
220 /* then try the ? keyword entries */
222 while (keylist != NULL) {
224 while (isspace((int)(*c)))
228 keylist = keylist->next;
235 * find title-entry for keyword-entry
238 lkup_by_number(int line)
240 struct LIST *run = head;
242 while (run->next && run->next->line <= line)
252 * free the whole list (I never trust the OS -SB)
259 for (run = head; run->next; run = run->next)
262 for (run = run->prev; run; run = run->prev) {
263 free(run->next->string);
269 for (run = keyhead; run->next; run = run->next)
271 for (run = run->prev; run; run = run->prev) {
272 free(run->next->string);
275 free(keyhead->string);
280 /* search through the list to find any references */
282 * writes a menu of all subtopics of the topic located at l
283 * format must contain %s for the title of the subtopic and may contain
284 * a %d for the line number of the subtopic (used by doc2html and doc2rtf
285 * The whole menu is preceeded by start and gets the trailer end
288 refs( int l, FILE *f, char *start, char *end, char *format)
294 /* find current line */
296 while (list->line != l)
298 curlevel = list->level;
299 list = list->next; /* look at next element before going on */
301 if (start != NULL && list != NULL) {
302 /* don't write start if there's no menue at all */
304 fprintf(f, "%s", start);
306 while (list != NULL) {
307 /* we are onto the next topic so stop */
308 if (list->level == curlevel)
310 /* these are the next topics down the list */
311 if (list->level == curlevel + 1) {
313 while (isspace((int)(*c)))
314 c++; /* strip leading whitespace */
316 if (format != NULL) {
317 for (i = 0; format[i] != '%' && format[i] != '\0'; i++);
318 if (format[i] != '\0') {
319 if (format[i + 1] == 'd') {
320 /* line number has to be printed first */
321 fprintf(f, format, list->line, c);
325 for (; format[i] != '%' && format[i] != '\0'; i++);
326 if (format[i] != '\0') /* line number is second */
327 fprintf(f, format, c, list->line);
328 else /* no line number at all */
329 fprintf(f, format, c);
336 if (inlist && end) /* trailer */
337 fprintf(f, "%s", end);