diff options
author | stanton <stanton> | 1998-04-28 18:53:49 (GMT) |
---|---|---|
committer | stanton <stanton> | 1998-04-28 18:53:49 (GMT) |
commit | 7a698c0488d99c0af42022714638ae1ba2afaa49 (patch) | |
tree | b25713e341ff09e21fb10bf1c3cd36c481067e3c /tools/man2tcl.c | |
parent | 72d823b9193f9ee2b0318563b49363cd08c11f24 (diff) | |
download | tcl-7a698c0488d99c0af42022714638ae1ba2afaa49.zip tcl-7a698c0488d99c0af42022714638ae1ba2afaa49.tar.gz tcl-7a698c0488d99c0af42022714638ae1ba2afaa49.tar.bz2 |
Initial revision
Diffstat (limited to 'tools/man2tcl.c')
-rw-r--r-- | tools/man2tcl.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/tools/man2tcl.c b/tools/man2tcl.c new file mode 100644 index 0000000..2b3c426 --- /dev/null +++ b/tools/man2tcl.c @@ -0,0 +1,400 @@ +/* + * man2tcl.c -- + * + * This file contains a program that turns a man page of the + * form used for Tcl and Tk into a Tcl script that invokes + * a Tcl command for each construct in the man page. The + * script can then be eval'ed to translate the manual entry + * into some other format such as MIF or HTML. + * + * Usage: + * + * man2tcl ?fileName? + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: %Z% $Id: man2tcl.c,v 1.1 1998/04/28 18:53:52 stanton Exp $ + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +/* + * Imported things that aren't defined in header files: + */ + +extern int errno; + +/* + * Current line number, used for error messages. + */ + +static int lineNumber; + +/* + * The variable below is set to 1 if an error occurs anywhere + * while reading in the file. + */ + +static int status; + +/* + * The variable below is set to 1 if output should be generated. + * If it's 0, it means we're doing a pre-pass to make sure that + * the file can be properly parsed. + */ + +static int writeOutput; + +/* + * Prototypes for procedures defined in this file: + */ + +static void DoMacro(char *line); +static void DoText(char *line); +static void QuoteText(char *string, int count); + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This procedure is the main program, which does all of the work + * of the program. + * + * Results: + * None: exits with a 0 return status to indicate success, or + * 1 to indicate that there were problems in the translation. + * + * Side effects: + * A Tcl script is output to standard output. Error messages may + * be output on standard error. + * + *---------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + FILE *f; +#define MAX_LINE_SIZE 500 + char line[MAX_LINE_SIZE]; + char *p; + + /* + * Find the file to read, and open it if it isn't stdin. + */ + + if (argc == 1) { + f = stdin; + } else if (argc == 2) { + f = fopen(argv[1], "r"); + if (f == NULL) { + fprintf(stderr, "Couldn't read \"%s\": %s\n", argv[1], + strerror(errno)); + exit(1); + } + } else { + fprintf(stderr, "Usage: %s ?fileName?\n", argv[0]); + } + + /* + * Make two passes over the file. In the first pass, just check + * to make sure we can handle everything. If there are problems, + * generate output and stop. If everything is OK, make a second + * pass to actually generate output. + */ + + for (writeOutput = 0; writeOutput < 2; writeOutput++) { + lineNumber = 0; + status = 0; + while (fgets(line, MAX_LINE_SIZE, f) != NULL) { + for (p = line; *p != 0; p++) { + if (*p == '\n') { + *p = 0; + break; + } + } + lineNumber++; + + if ((line[0] == '\'') && (line[1] == '\\') && (line[2] == '\"')) { + /* + * This line is a comment. Ignore it. + */ + + continue; + } + + if ((line[0] == '.') || (line[0] == '\'')) { + /* + * This line is a macro invocation. + */ + + DoMacro(line); + } else { + /* + * This line is text, possibly with formatting characters + * embedded in it. + */ + + DoText(line); + } + } + if (status != 0) { + break; + } + fseek(f, 0, SEEK_SET); + } + exit(status); +} + +/* + *---------------------------------------------------------------------- + * + * DoMacro -- + * + * This procedure is called to handle a macro invocation. + * It parses the arguments to the macro and generates a + * Tcl command to handle the invocation. + * + * Results: + * None. + * + * Side effects: + * A Tcl command is written to stdout. + * + *---------------------------------------------------------------------- + */ + +static void +DoMacro(line) + char *line; /* The line of text that contains the + * macro invocation. */ +{ + char *p, *end; + + /* + * If there is no macro name, then just skip the whole line. + */ + + if ((line[1] == 0) || (isspace(line[1]))) { + return; + } + + if (writeOutput) { + printf("macro"); + } + if (*line != '.') { + if (writeOutput) { + printf("2"); + } + } + + /* + * Parse the arguments to the macro (including the name), in order. + */ + + p = line+1; + while (1) { + if (writeOutput) { + putc(' ', stdout); + } + if (*p == '"') { + /* + * The argument is delimited by quotes. + */ + + for (end = p+1; *end != '"'; end++) { + if (*end == 0) { + fprintf(stderr, + "Unclosed quote in macro call on line %d.\n", + lineNumber); + status = 1; + break; + } + } + QuoteText(p+1, (end-(p+1))); + } else { + for (end = p+1; (*end != 0) && !isspace(*end); end++) { + /* Empty loop body. */ + } + QuoteText(p, end-p); + } + if (*end == 0) { + break; + } + p = end+1; + while (isspace(*p)) { + /* + * Skip empty space before next argument. + */ + + p++; + } + if (*p == 0) { + break; + } + } + if (writeOutput) { + putc('\n', stdout); + } +} + +/* + *---------------------------------------------------------------------- + * + * DoText -- + * + * This procedure is called to handle a line of troff text. + * It parses the text, generating Tcl commands for text and + * for formatting stuff such as font changes. + * + * Results: + * None. + * + * Side effects: + * Tcl commands are written to stdout. + * + *---------------------------------------------------------------------- + */ + +static void +DoText(line) + char *line; /* The line of text. */ +{ + char *p, *end; + + /* + * Divide the line up into pieces consisting of backslash sequences, + * tabs, and other text. + */ + + p = line; + while (*p != 0) { + if (*p == '\t') { + if (writeOutput) { + printf("tab\n"); + } + p++; + } else if (*p != '\\') { + /* + * Ordinary text. + */ + + for (end = p+1; (*end != '\\') && (*end != 0); end++) { + /* Empty loop body. */ + } + if (writeOutput) { + printf("text "); + } + QuoteText(p, end-p); + if (writeOutput) { + putc('\n', stdout); + } + p = end; + } else { + /* + * A backslash sequence. There are particular ones + * that we understand; output an error message for + * anything else and just ignore the backslash. + */ + + p++; + if (*p == 'f') { + /* + * Font change. + */ + + if (writeOutput) { + printf("font %c\n", p[1]); + } + p += 2; + } else if (*p == '-') { + if (writeOutput) { + printf("dash\n"); + } + p++; + } else if (*p == 'e') { + if (writeOutput) { + printf("text \\\\\n"); + } + p++; + } else if (*p == '.') { + if (writeOutput) { + printf("text .\n"); + } + p++; + } else if (*p == '&') { + p++; + } else if (*p == '(') { + if ((p[1] == 0) || (p[2] == 0)) { + fprintf(stderr, "Bad \\( sequence on line %d.\n", + lineNumber); + status = 1; + } else { + if (writeOutput) { + printf("char {\\(%c%c}\n", p[1], p[2]); + } + p += 3; + } + } else if (*p != 0) { + if (writeOutput) { + printf("char {\\%c}\n", *p); + } + p++; + } + } + } + if (writeOutput) { + printf("newline\n"); + } +} + +/* + *---------------------------------------------------------------------- + * + * QuoteText -- + * + * Copy the "string" argument to stdout, adding quote characters + * around any special Tcl characters so that they'll just be treated + * as ordinary text. + * + * Results: + * None. + * + * Side effects: + * Text is written to stdout. + * + *---------------------------------------------------------------------- + */ + +static void +QuoteText(string, count) + char *string; /* The line of text. */ + int count; /* Number of characters to write from string. */ +{ + if (count == 0) { + if (writeOutput) { + printf("{}"); + } + return; + } + for ( ; count > 0; string++, count--) { + if ((*string == '$') || (*string == '[') || (*string == '{') + || (*string == ' ') || (*string == ';') || (*string == '\\') + || (*string == '"') || (*string == '\t')) { + if (writeOutput) { + putc('\\', stdout); + } + } + if (writeOutput) { + putc(*string, stdout); + } + } +} |