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