Annotation of OpenXM_contrib/gnuplot/docs/doc2info.c, Revision 1.1.1.2
1.1 maekawa 1: /*
1.1.1.2 ! maekawa 2: * $Id: doc2info.c,v 1.9.2.1 1999/08/19 14:31:53 lhecking Exp $
1.1 maekawa 3: *
4: */
5:
6: /* GNUPLOT - doc2info.c */
7:
8: /*[
9: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
10: *
11: * Permission to use, copy, and distribute this software and its
12: * documentation for any purpose with or without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and
14: * that both that copyright notice and this permission notice appear
15: * in supporting documentation.
16: *
17: * Permission to modify the software is granted, but not the right to
18: * distribute the complete modified source code. Modifications are to
19: * be distributed as patches to the released version. Permission to
20: * distribute binaries produced by compiling modified sources is granted,
21: * provided you
22: * 1. distribute the corresponding source modifications from the
23: * released version in the form of a patch file along with the binaries,
24: * 2. add special version identification to distinguish your version
25: * in addition to the base release version number,
26: * 3. provide your name and address as the primary contact for the
27: * support of your modified version, and
28: * 4. retain our contact information in regard to use of the base
29: * software.
30: * Permission to distribute the released version of the source code along
31: * with corresponding source modifications in the form of a patch file is
32: * granted with same provisions 2 through 4 for binary distributions.
33: *
34: * This software is provided "as is" without express or implied warranty
35: * to the extent permitted by applicable law.
36: ]*/
37:
38: /*
39: * doc2info.c -- program to convert Gnuplot .DOC format to
40: * (Emacs -) Info-file format
41: *
42: * Created by Stefan Bodewig from doc2gih by Thomas Williams
43: * and doc2html by Russel Lang
44: * 1/29/1996
45: *
46: * usage: doc2info gnuplot.doc gnuplot.info
47: *
48: */
49:
50: /* note that tables must begin in at least the second column to */
51: /* be formatted correctly and tabs are forbidden */
52:
53: #ifdef HAVE_CONFIG_H
54: # include "config.h"
55: #endif
56:
57: #include "ansichek.h"
58: #include "stdfn.h"
59:
60: #define MAX_LINE_LEN 1023
61:
62: #include "doc2x.h"
63: #include "xref.h"
64:
65: struct BUFFER { /* buffer to reformat paragraphs with xrefs */
66: char *content;
67: struct BUFFER *next;
68: struct BUFFER *prev;
69: };
70:
71: struct XREFLIST { /* a list of xrefs allready mentioned in this node */
72: struct LIST *ref;
73: struct XREFLIST *next;
74: struct XREFLIST *prev;
75: };
76:
77: /* xref.c */
78: extern struct LIST *list;
79: extern struct LIST *head;
80:
81: extern struct LIST *keylist;
82: extern struct LIST *keyhead;
83:
84: extern int maxlevel;
85: extern int listitems;
86:
87: char title[MAX_LINE_LEN+1];
88: char ifile[MAX_LINE_LEN+1];
89: char ofile[MAX_LINE_LEN+1];
90: struct XREFLIST *refhead = NULL;
91:
92: void convert __PROTO((FILE *, FILE *));
93: void process_line __PROTO((char *, FILE *));
94: void node_head __PROTO((char *, char *, char *, char *, FILE *));
95: void name_free __PROTO((char **));
96: char **name_alloc __PROTO(());
97: void clear_buffer __PROTO((struct BUFFER *, FILE *));
98: int inxreflist __PROTO((struct LIST *));
99: void xref_free __PROTO((void));
100:
101: int main(argc, argv)
102: int argc;
103: char **argv;
104: {
105: FILE *infile;
106: FILE *outfile;
107: infile = stdin;
108: outfile = stdout;
109:
110: if (argc > 3) {
111: fprintf(stderr, "Usage: %s [infile [outfile]]\n", argv[0]);
112: exit(EXIT_FAILURE);
113: }
114: if (argc >= 2) {
115: strcpy(ifile, argv[1]);
116: if ((infile = fopen(argv[1], "r")) == (FILE *) NULL) {
117: fprintf(stderr, "%s: Can't open %s for reading\n",
118: argv[0], argv[1]);
119: exit(EXIT_FAILURE);
120: }
121: } else
122: safe_strncpy(ifile, "gnuplot.doc", sizeof(ifile)); /* default value */
123: if (argc == 3) {
124: safe_strncpy(ofile, argv[2], sizeof(ofile));
125: if ((outfile = fopen(argv[2], "w")) == (FILE *) NULL) {
126: fprintf(stderr, "%s: Can't open %s for writing\n",
127: argv[0], argv[2]);
128: exit(EXIT_FAILURE);
129: }
130: } else
131: safe_strncpy(ofile, "gnuplot.info", sizeof(ofile)); /* default value */
132:
133: safe_strncpy(title, ofile, sizeof(title));
134: strtok(title, "."); /* without type */
135: convert(infile, outfile);
136: exit(EXIT_SUCCESS);
137: }
138:
139:
140: void convert(a, b)
141: FILE *a, *b;
142: {
143: static char line[MAX_LINE_LEN+1];
144:
145: parse(a);
146:
147: refhead = (struct XREFLIST *) xmalloc(sizeof(struct XREFLIST));
148: refhead->next = refhead->prev = NULL;
149:
150: /* Info header */
1.1.1.2 ! maekawa 151: fprintf(b, "\
! 152: This file is %s created by doc2info from %s.\n\
! 153: \n\
! 154: START-INFO-DIR-ENTRY\n\
! 155: * Gnuplot: (gnuplot). Gnuplot plotting program\n\
! 156: END-INFO-DIR-ENTRY\n\n",
! 157: ofile, ifile);
1.1 maekawa 158:
159: /* and Top node */
160: node_head(NULL, NULL, head->next->string, NULL, b);
161:
162: while (get_line(line, sizeof(line), a)) {
163: process_line(line, b);
164: }
165: list_free();
166: free(refhead);
167: }
168:
169: /*
170: * scans the lines for xrefs, creates new nodes and prints or ignores
171: * the rest.
172: *
173: * Info xrefs are visible. Therefore we have to reformat the paragraphs
174: * containing them. All lines of the paragraph are written into a buffer
175: * and printed at the end of the paragraph.
176: */
177: void process_line(line, b)
178: char *line;
179: FILE *b;
180: {
181: static int line_count = 0;
182: struct LIST *node; /* current node */
183: static struct LIST *prev = NULL; /* previous node */
184: int level; /* current level */
185: static char **up = NULL; /* Array with node names */
186: static char **pre = NULL;
187: char topic[MAX_LINE_LEN+1]; /* for xrefs */
188: int i, j, k, l;
189: static int inref = FALSE; /* flags */
190: static int inbold = FALSE;
191: static struct BUFFER *buffer; /* buffer to hold the lines of a paragraph */
192: static struct BUFFER *buf_head = NULL;
193: int inbuf = 0; /* offset into buffer */
194: char line2[3*MAX_LINE_LEN+1]; /* line of text with added xrefs */
195: struct LIST *reflist;
196: static struct XREFLIST *lastref = NULL; /* xrefs that are already mentioned in this node */
197:
198: line2[0] = NUL;
199: if (!prev) /* last node visited */
200: prev = head;
201: if (!lastref)
202: lastref = refhead;
203: if (!up) { /* Names of `Prev:' and `Up:' nodes */
204: up = name_alloc();
205: pre = name_alloc();
206: strcpy(up[0], "(dir)");
207: strcpy(up[1], "Top");
208: strcpy(pre[1], "(dir)");
209: strcpy(pre[2], "Top");
210: }
211: line_count++;
212:
213: if (line[0] == ' ') /* scan line for xrefs */
214: for (i = 0; line[i] != NUL; ++i)
215: if (line[i] == '`') { /* Reference or boldface (ignore the latter) */
216: if (!inref && !inbold) {
217: k = i + 1; /* next character */
218: j = 0; /* index into topic */
219: while (line[k] != '`' && line[k] != NUL)
220: topic[j++] = line[k++];
221: topic[j] = NUL;
222:
223: /* try to find the xref */
224: reflist = lookup(topic);
225: if (reflist) {
226: /* now we have the (key-)list-entry */
227: /* convert it to a list-entry that represents a node */
228: reflist = lkup_by_number(reflist->line);
229: }
230: /* not interested in xrefs pointing to `Top' or same node */
231: /* we want only one reference per topic in node */
232: if (reflist && reflist->level != 0 && reflist != prev && !inxreflist(reflist)) {
233: /* new entry to xreflist */
234: lastref->next = (struct XREFLIST *) xmalloc(sizeof(struct XREFLIST));
235: lastref->next->prev = lastref;
236: lastref = lastref->next;
237: lastref->ref = reflist;
238: lastref->next = NULL;
239: if (!buf_head) { /* No buffer yet */
240: buf_head = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
241: buffer = buf_head;
242: buffer->prev = NULL;
243: buffer->next = NULL;
244: }
245: /* eliminate leading spaces of topic */
246: for (j = 0; isspace((int) reflist->string[j]); ++j);
247: /* encountered end of line */
248: if (line[k] == NUL) {
249: if (line[k - 1] == '\n') /* throw away new-lines */
250: line[--k] = NUL;
251: /* insert xref into line */
252: sprintf(line2, "%s%s (*note %s:: )", line2, line + inbuf, reflist->string + j);
253: inref = TRUE;
254: /* line is done */
255: break;
256: }
257: /* eliminate spaces before the second ` */
258: if (isspace((int) line[k - 1]))
259: for (l = k - 1; line[l] != NUL; ++l)
260: line[l] = line[l + 1];
261:
262: /* let `plot`s look nicer */
263: if (isalpha((int) line[k + 1]))
264: ++k;
265: sprintf(line2, "%s%.*s (*note %s:: )", line2, k - inbuf + 1, line + inbuf, reflist->string + j);
266: /* line2 contains first inbuf characters of line */
267: i = inbuf = k;
268: } else { /* found no reference */
269: inbold = TRUE;
270: }
271: } else {
272: if (inref) /* inref || inbold */
273: inref = FALSE;
274: else
275: inbold = FALSE;
276: }
277: }
278: /* just copy normal characters of line with xref */
279: else if (inbuf) {
280: strncat(line2, line + i, 1);
281: inbuf++;
282: }
283: switch (line[0]) { /* control character */
284: case '?':{ /* interactive help entry */
285: break; /* ignore */
286: }
287: case '@':{ /* start/end table */
288: break; /* ignore */
289: }
290: case '#':{ /* latex table entry */
291: break; /* ignore */
292: }
293: case '%':{ /* troff table entry */
294: break; /* ignore */
295: }
296: case '^':{ /* html entry */
297: break; /* ignore */
298: }
299: case '\n': /* empty text line */
300: if (buf_head) { /* do we have a buffer? */
301: /* paragraph finished, print it */
302: clear_buffer(buf_head, b);
303: buffer = buf_head = NULL;
304: } else /* just copy the blank line */
305: fputs(line, b);
306: break;
307: case ' ':{ /* normal text line */
308: if (buf_head) { /* must be inserted in buffer ? */
309: buffer->next = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
310: buffer->next->prev = buffer;
311: buffer = buffer->next;
312: buffer->next = NULL;
313: if (line2[0] == NUL) { /* line doesn't contain xref */
314: buffer->content = (char *) xmalloc(strlen(line) + 1);
315: strcpy(buffer->content, line);
316: } else { /* line contains xref */
317: buffer->content = (char *) xmalloc(strlen(line2) + 1);
318: strcpy(buffer->content, line2);
319: }
320: } else /* no buffer, just copy */
321: fputs(line, b);
322: break;
323: }
324: default:
325: if (isdigit((int) line[0])) { /* start of section */
326: /* clear xref-list */
327: xref_free();
328: lastref = 0;
329: if (buf_head) { /* do we have a buffer */
330: /* paragraphs are not allways separated by a blank line */
331: clear_buffer(buf_head, b);
332: buffer = buf_head = NULL;
333: }
334: level = line[0] - '0';
335:
336: if (level > prev->level) /* going down */
337: /* so write menu of previous node */
338: refs(prev->line, b, "\n* Menu:\n\n", NULL, "* %s::\n");
339: node = prev->next;
340: if (!node->next) { /* last node ? */
341: node_head(node->string, pre[level + 1], NULL, up[level], b);
342: name_free(up);
343: name_free(pre);
344:
345: /* next node will go up, no 'Next:' node */
346: } else if (node->next->level < level)
347: node_head(node->string, pre[level + 1], NULL, up[level], b);
348:
349: else {
350: node_head(node->string, pre[level + 1], node->next->string, up[level], b);
351: strcpy(pre[level + 1], node->string);
352:
353: /* next node will go down */
354: if (level < node->next->level) {
355: strcpy(up[level + 1], node->string);
356: strcpy(pre[node->next->level + 1], node->string);
357: }
358: }
359: prev = node;
360: } else
361: fprintf(stderr, "unknown control code '%c' in column 1, line %d\n",
362: line[0], line_count);
363: break;
364: }
365: }
366:
367: /*
368: * write the header of an Info node, treat Top node specially
369: */
370: void node_head(node, prev, next, up, b)
371: char *node, *prev, *next, *up;
372: FILE *b;
373: {
374: /* eliminate leading spaces */
375: while (node && isspace((int) *node))
376: node++;
377: while (next && isspace((int) *next))
378: next++;
379: while (prev && isspace((int) *prev))
380: prev++;
381: while (up && isspace((int) *up))
382: up++;
383:
384: if (!prev) { /* Top node */
385: int i;
386: fprintf(b, "\nFile: %s, Node: Top, Prev: (dir), Next: %s, Up: (dir)\n\n", ofile, next);
387: fprintf(b, "%s\n", title);
388: for (i = 0; i < strlen(title); ++i)
389: fprintf(b, "*");
390: fprintf(b, "\n\n");
391: return;
392: }
393: fprintf(b, "\n\nFile: %s, ", ofile);
394: fprintf(b, "Node: %s, Prev: %s, Up: %s", node, prev, up);
395:
396: if (next)
397: fprintf(b, ", Next: %s\n\n", next);
398: else
399: fputs("\n\n", b);
400: }
401:
402: /*
403: * allocate memory for the node titles (up and prev)
404: * need at most maxlevel+Top+(dir) entries
405: */
406: char **name_alloc __PROTO((void))
407: {
408: char **a;
409: int i;
410:
411: a = (char **) xmalloc((maxlevel + 2) * sizeof(char *));
412: for (i = 0; i <= maxlevel + 1; i++)
413: a[i] = (char *) xmalloc(MAX_LINE_LEN+1);
414: return a;
415: }
416:
417: /*
418: * free node names
419: */
420: void name_free(names)
421: char **names;
422: {
423: int i;
424:
425: for (i = 0; i <= maxlevel + 1; i++)
426: free(names[i]);
427: free(names);
428: }
429:
430: /*
431: * reformat the buffered lines
432: */
433: void clear_buffer(buf_head, b)
434: struct BUFFER *buf_head;
435: FILE *b;
436: {
437: struct BUFFER *run;
438: int in_line = 0; /* offset into current line */
439: int in_buf = 0; /* offset into buffer */
440: int i, todo;
441: char c;
442:
443: /* for all buffer entries */
444: for (run = buf_head; run->next; run = run->next) {
445:
446: /* unprinted characters */
447: todo = strlen(run->next->content);
448:
449: /* eliminate new-lines */
450: if (run->next->content[todo - 1] == '\n')
451: run->next->content[--todo] = NUL;
452:
453: while (todo)
454: if (79 - in_line > todo) { /* buffer fits into line */
455: fprintf(b, "%s", run->next->content + in_buf);
456: in_line += todo;
457: todo = in_buf = 0;
458:
459: } else { /* buffer must be split over lines */
460:
461: /* search for whitespace to split at */
462: for (i = 79 - in_line; i > 2; --i)
463: if (isspace((int) (run->next->content[in_buf + i]))) {
464: char *beginnote, *linestart;
465: c = run->next->content[in_buf + i - 1];
466: if (c == '.') /* don't split at end of sentence */
467: continue;
468: if (c == ' ') /* ditto */
469: continue;
470:
471: /* dont break xref */
472: /* search for xref in current line */
473: linestart = run->next->content + in_buf;
474: beginnote = strstr(linestart, "(*note");
475: while (beginnote && beginnote < linestart + i) {
476: /* don't split if it didn't fit into the line as a whole */
477: if (strchr(beginnote, ')') > linestart + i)
478: break;
479: /* xref is complete, maybe there's another one? */
480: beginnote = strstr(beginnote + 1, "(*note");
481: }
482:
483: /* unbalanced xref ? */
484: if (beginnote && beginnote < linestart + i)
485: continue;
486:
487: break;
488: }
489: if (i > 2) { /* found a point to split buffer */
490: fprintf(b, "%.*s\n", i, run->next->content + in_buf);
491: todo -= i;
492: in_buf += i;
493: in_line = 0;
494: } else { /* try with a new line */
495: fputs("\n", b);
496: in_line = 0;
497: }
498: }
499: }
500: if (in_line) /* paragraph ended incomplete line */
501: fputs("\n", b);
502: fputs("\n", b);
503:
504: /* free the buffer */
505: for (run = run->prev; run->prev; run = run->prev) {
506: free(run->next->content);
507: free(run->next);
508: run->next = NULL;
509: }
510: if (buf_head->next) {
511: free(buf_head->next->content);
512: free(buf_head->next);
513: buf_head->next = NULL;
514: }
515: free(buf_head);
516: }
517:
518: /*
519: * test whether topic is allready referenced in node
520: */
521: int inxreflist(reflist)
522: struct LIST *reflist;
523: {
524: struct XREFLIST *run;
525:
526: for (run = refhead; run->next; run = run->next)
527: if (run->next->ref == reflist)
528: return TRUE;
529: return FALSE;
530: }
531:
532: /*
533: * free the list of xrefs
534: */
535: void xref_free __PROTO((void))
536: {
537: struct XREFLIST *lastref;
538:
539: for (lastref = refhead; lastref->next; lastref = lastref->next);
540: if (lastref != refhead)
541: for (lastref = lastref->prev; lastref->prev; lastref = lastref->prev)
542: free(lastref->next);
543: if (refhead->next)
544: free(refhead->next);
545: refhead->next = NULL;
546: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>