Annotation of OpenXM_contrib/gnuplot/docs/doc2info.c, Revision 1.1.1.3
1.1 maekawa 1: /*
1.1.1.3 ! ohara 2: * $Id: doc2info.c,v 1.9.2.2 2002/02/25 19:37:00 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\
1.1.1.3 ! ohara 154: INFO-DIR-SECTION Math\n\
1.1.1.2 maekawa 155: START-INFO-DIR-ENTRY\n\
156: * Gnuplot: (gnuplot). Gnuplot plotting program\n\
157: END-INFO-DIR-ENTRY\n\n",
158: ofile, ifile);
1.1 maekawa 159:
160: /* and Top node */
161: node_head(NULL, NULL, head->next->string, NULL, b);
162:
163: while (get_line(line, sizeof(line), a)) {
164: process_line(line, b);
165: }
166: list_free();
167: free(refhead);
168: }
169:
170: /*
171: * scans the lines for xrefs, creates new nodes and prints or ignores
172: * the rest.
173: *
174: * Info xrefs are visible. Therefore we have to reformat the paragraphs
175: * containing them. All lines of the paragraph are written into a buffer
176: * and printed at the end of the paragraph.
177: */
178: void process_line(line, b)
179: char *line;
180: FILE *b;
181: {
182: static int line_count = 0;
183: struct LIST *node; /* current node */
184: static struct LIST *prev = NULL; /* previous node */
185: int level; /* current level */
186: static char **up = NULL; /* Array with node names */
187: static char **pre = NULL;
188: char topic[MAX_LINE_LEN+1]; /* for xrefs */
189: int i, j, k, l;
190: static int inref = FALSE; /* flags */
191: static int inbold = FALSE;
192: static struct BUFFER *buffer; /* buffer to hold the lines of a paragraph */
193: static struct BUFFER *buf_head = NULL;
194: int inbuf = 0; /* offset into buffer */
195: char line2[3*MAX_LINE_LEN+1]; /* line of text with added xrefs */
196: struct LIST *reflist;
197: static struct XREFLIST *lastref = NULL; /* xrefs that are already mentioned in this node */
198:
199: line2[0] = NUL;
200: if (!prev) /* last node visited */
201: prev = head;
202: if (!lastref)
203: lastref = refhead;
204: if (!up) { /* Names of `Prev:' and `Up:' nodes */
205: up = name_alloc();
206: pre = name_alloc();
207: strcpy(up[0], "(dir)");
208: strcpy(up[1], "Top");
209: strcpy(pre[1], "(dir)");
210: strcpy(pre[2], "Top");
211: }
212: line_count++;
213:
214: if (line[0] == ' ') /* scan line for xrefs */
215: for (i = 0; line[i] != NUL; ++i)
216: if (line[i] == '`') { /* Reference or boldface (ignore the latter) */
217: if (!inref && !inbold) {
218: k = i + 1; /* next character */
219: j = 0; /* index into topic */
220: while (line[k] != '`' && line[k] != NUL)
221: topic[j++] = line[k++];
222: topic[j] = NUL;
223:
224: /* try to find the xref */
225: reflist = lookup(topic);
226: if (reflist) {
227: /* now we have the (key-)list-entry */
228: /* convert it to a list-entry that represents a node */
229: reflist = lkup_by_number(reflist->line);
230: }
231: /* not interested in xrefs pointing to `Top' or same node */
232: /* we want only one reference per topic in node */
233: if (reflist && reflist->level != 0 && reflist != prev && !inxreflist(reflist)) {
234: /* new entry to xreflist */
235: lastref->next = (struct XREFLIST *) xmalloc(sizeof(struct XREFLIST));
236: lastref->next->prev = lastref;
237: lastref = lastref->next;
238: lastref->ref = reflist;
239: lastref->next = NULL;
240: if (!buf_head) { /* No buffer yet */
241: buf_head = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
242: buffer = buf_head;
243: buffer->prev = NULL;
244: buffer->next = NULL;
245: }
246: /* eliminate leading spaces of topic */
247: for (j = 0; isspace((int) reflist->string[j]); ++j);
248: /* encountered end of line */
249: if (line[k] == NUL) {
250: if (line[k - 1] == '\n') /* throw away new-lines */
251: line[--k] = NUL;
252: /* insert xref into line */
253: sprintf(line2, "%s%s (*note %s:: )", line2, line + inbuf, reflist->string + j);
254: inref = TRUE;
255: /* line is done */
256: break;
257: }
258: /* eliminate spaces before the second ` */
259: if (isspace((int) line[k - 1]))
260: for (l = k - 1; line[l] != NUL; ++l)
261: line[l] = line[l + 1];
262:
263: /* let `plot`s look nicer */
264: if (isalpha((int) line[k + 1]))
265: ++k;
266: sprintf(line2, "%s%.*s (*note %s:: )", line2, k - inbuf + 1, line + inbuf, reflist->string + j);
267: /* line2 contains first inbuf characters of line */
268: i = inbuf = k;
269: } else { /* found no reference */
270: inbold = TRUE;
271: }
272: } else {
273: if (inref) /* inref || inbold */
274: inref = FALSE;
275: else
276: inbold = FALSE;
277: }
278: }
279: /* just copy normal characters of line with xref */
280: else if (inbuf) {
281: strncat(line2, line + i, 1);
282: inbuf++;
283: }
284: switch (line[0]) { /* control character */
285: case '?':{ /* interactive help entry */
286: break; /* ignore */
287: }
288: case '@':{ /* start/end table */
289: break; /* ignore */
290: }
291: case '#':{ /* latex table entry */
292: break; /* ignore */
293: }
294: case '%':{ /* troff table entry */
295: break; /* ignore */
296: }
297: case '^':{ /* html entry */
298: break; /* ignore */
299: }
300: case '\n': /* empty text line */
301: if (buf_head) { /* do we have a buffer? */
302: /* paragraph finished, print it */
303: clear_buffer(buf_head, b);
304: buffer = buf_head = NULL;
305: } else /* just copy the blank line */
306: fputs(line, b);
307: break;
308: case ' ':{ /* normal text line */
309: if (buf_head) { /* must be inserted in buffer ? */
310: buffer->next = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
311: buffer->next->prev = buffer;
312: buffer = buffer->next;
313: buffer->next = NULL;
314: if (line2[0] == NUL) { /* line doesn't contain xref */
315: buffer->content = (char *) xmalloc(strlen(line) + 1);
316: strcpy(buffer->content, line);
317: } else { /* line contains xref */
318: buffer->content = (char *) xmalloc(strlen(line2) + 1);
319: strcpy(buffer->content, line2);
320: }
321: } else /* no buffer, just copy */
322: fputs(line, b);
323: break;
324: }
325: default:
326: if (isdigit((int) line[0])) { /* start of section */
327: /* clear xref-list */
328: xref_free();
329: lastref = 0;
330: if (buf_head) { /* do we have a buffer */
331: /* paragraphs are not allways separated by a blank line */
332: clear_buffer(buf_head, b);
333: buffer = buf_head = NULL;
334: }
335: level = line[0] - '0';
336:
337: if (level > prev->level) /* going down */
338: /* so write menu of previous node */
339: refs(prev->line, b, "\n* Menu:\n\n", NULL, "* %s::\n");
340: node = prev->next;
341: if (!node->next) { /* last node ? */
342: node_head(node->string, pre[level + 1], NULL, up[level], b);
343: name_free(up);
344: name_free(pre);
345:
346: /* next node will go up, no 'Next:' node */
347: } else if (node->next->level < level)
348: node_head(node->string, pre[level + 1], NULL, up[level], b);
349:
350: else {
351: node_head(node->string, pre[level + 1], node->next->string, up[level], b);
352: strcpy(pre[level + 1], node->string);
353:
354: /* next node will go down */
355: if (level < node->next->level) {
356: strcpy(up[level + 1], node->string);
357: strcpy(pre[node->next->level + 1], node->string);
358: }
359: }
360: prev = node;
361: } else
362: fprintf(stderr, "unknown control code '%c' in column 1, line %d\n",
363: line[0], line_count);
364: break;
365: }
366: }
367:
368: /*
369: * write the header of an Info node, treat Top node specially
370: */
371: void node_head(node, prev, next, up, b)
372: char *node, *prev, *next, *up;
373: FILE *b;
374: {
375: /* eliminate leading spaces */
376: while (node && isspace((int) *node))
377: node++;
378: while (next && isspace((int) *next))
379: next++;
380: while (prev && isspace((int) *prev))
381: prev++;
382: while (up && isspace((int) *up))
383: up++;
384:
385: if (!prev) { /* Top node */
386: int i;
387: fprintf(b, "\nFile: %s, Node: Top, Prev: (dir), Next: %s, Up: (dir)\n\n", ofile, next);
388: fprintf(b, "%s\n", title);
389: for (i = 0; i < strlen(title); ++i)
390: fprintf(b, "*");
391: fprintf(b, "\n\n");
392: return;
393: }
394: fprintf(b, "\n\nFile: %s, ", ofile);
395: fprintf(b, "Node: %s, Prev: %s, Up: %s", node, prev, up);
396:
397: if (next)
398: fprintf(b, ", Next: %s\n\n", next);
399: else
400: fputs("\n\n", b);
401: }
402:
403: /*
404: * allocate memory for the node titles (up and prev)
405: * need at most maxlevel+Top+(dir) entries
406: */
407: char **name_alloc __PROTO((void))
408: {
409: char **a;
410: int i;
411:
412: a = (char **) xmalloc((maxlevel + 2) * sizeof(char *));
413: for (i = 0; i <= maxlevel + 1; i++)
414: a[i] = (char *) xmalloc(MAX_LINE_LEN+1);
415: return a;
416: }
417:
418: /*
419: * free node names
420: */
421: void name_free(names)
422: char **names;
423: {
424: int i;
425:
426: for (i = 0; i <= maxlevel + 1; i++)
427: free(names[i]);
428: free(names);
429: }
430:
431: /*
432: * reformat the buffered lines
433: */
434: void clear_buffer(buf_head, b)
435: struct BUFFER *buf_head;
436: FILE *b;
437: {
438: struct BUFFER *run;
439: int in_line = 0; /* offset into current line */
440: int in_buf = 0; /* offset into buffer */
441: int i, todo;
442: char c;
443:
444: /* for all buffer entries */
445: for (run = buf_head; run->next; run = run->next) {
446:
447: /* unprinted characters */
448: todo = strlen(run->next->content);
449:
450: /* eliminate new-lines */
451: if (run->next->content[todo - 1] == '\n')
452: run->next->content[--todo] = NUL;
453:
454: while (todo)
455: if (79 - in_line > todo) { /* buffer fits into line */
456: fprintf(b, "%s", run->next->content + in_buf);
457: in_line += todo;
458: todo = in_buf = 0;
459:
460: } else { /* buffer must be split over lines */
461:
462: /* search for whitespace to split at */
463: for (i = 79 - in_line; i > 2; --i)
464: if (isspace((int) (run->next->content[in_buf + i]))) {
465: char *beginnote, *linestart;
466: c = run->next->content[in_buf + i - 1];
467: if (c == '.') /* don't split at end of sentence */
468: continue;
469: if (c == ' ') /* ditto */
470: continue;
471:
472: /* dont break xref */
473: /* search for xref in current line */
474: linestart = run->next->content + in_buf;
475: beginnote = strstr(linestart, "(*note");
476: while (beginnote && beginnote < linestart + i) {
477: /* don't split if it didn't fit into the line as a whole */
478: if (strchr(beginnote, ')') > linestart + i)
479: break;
480: /* xref is complete, maybe there's another one? */
481: beginnote = strstr(beginnote + 1, "(*note");
482: }
483:
484: /* unbalanced xref ? */
485: if (beginnote && beginnote < linestart + i)
486: continue;
487:
488: break;
489: }
490: if (i > 2) { /* found a point to split buffer */
491: fprintf(b, "%.*s\n", i, run->next->content + in_buf);
492: todo -= i;
493: in_buf += i;
494: in_line = 0;
495: } else { /* try with a new line */
496: fputs("\n", b);
497: in_line = 0;
498: }
499: }
500: }
501: if (in_line) /* paragraph ended incomplete line */
502: fputs("\n", b);
503: fputs("\n", b);
504:
505: /* free the buffer */
506: for (run = run->prev; run->prev; run = run->prev) {
507: free(run->next->content);
508: free(run->next);
509: run->next = NULL;
510: }
511: if (buf_head->next) {
512: free(buf_head->next->content);
513: free(buf_head->next);
514: buf_head->next = NULL;
515: }
516: free(buf_head);
517: }
518:
519: /*
520: * test whether topic is allready referenced in node
521: */
522: int inxreflist(reflist)
523: struct LIST *reflist;
524: {
525: struct XREFLIST *run;
526:
527: for (run = refhead; run->next; run = run->next)
528: if (run->next->ref == reflist)
529: return TRUE;
530: return FALSE;
531: }
532:
533: /*
534: * free the list of xrefs
535: */
536: void xref_free __PROTO((void))
537: {
538: struct XREFLIST *lastref;
539:
540: for (lastref = refhead; lastref->next; lastref = lastref->next);
541: if (lastref != refhead)
542: for (lastref = lastref->prev; lastref->prev; lastref = lastref->prev)
543: free(lastref->next);
544: if (refhead->next)
545: free(refhead->next);
546: refhead->next = NULL;
547: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>