summaryrefslogtreecommitdiffstats
path: root/tcl8.6/tools/man2tcl.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-18 17:31:11 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-18 17:31:11 (GMT)
commit066971b1e6e77991d9161bb0216a63ba94ea04f9 (patch)
tree6de02f79b7a4bb08a329581aa67b444fb9001bfd /tcl8.6/tools/man2tcl.c
parentba065c2de121da1c1dfddd0aa587d10e7e150f05 (diff)
parent9966985d896629eede849a84f18e406d1164a16c (diff)
downloadblt-066971b1e6e77991d9161bb0216a63ba94ea04f9.zip
blt-066971b1e6e77991d9161bb0216a63ba94ea04f9.tar.gz
blt-066971b1e6e77991d9161bb0216a63ba94ea04f9.tar.bz2
Merge commit '9966985d896629eede849a84f18e406d1164a16c' as 'tcl8.6'
Diffstat (limited to 'tcl8.6/tools/man2tcl.c')
-rw-r--r--tcl8.6/tools/man2tcl.c424
1 files changed, 424 insertions, 0 deletions
diff --git a/tcl8.6/tools/man2tcl.c b/tcl8.6/tools/man2tcl.c
new file mode 100644
index 0000000..8e59bea
--- /dev/null
+++ b/tcl8.6/tools/man2tcl.c
@@ -0,0 +1,424 @@
+/*
+ * 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.
+ */
+
+static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+/*
+ * Imported things that aren't defined in header files:
+ */
+
+/*
+ * Some <errno.h> define errno to be something complex and thread-aware; in
+ * that case we definitely do not want to declare errno ourselves!
+ */
+
+#ifndef errno
+extern int errno;
+#endif
+
+/*
+ * 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;
+
+#define PRINT(args) if (writeOutput) { printf args; }
+#define PRINTC(chr) if (writeOutput) { putc((chr), stdout); }
+
+/*
+ * Prototypes for functions defined in this file:
+ */
+
+static void DoMacro(char *line);
+static void DoText(char *line);
+static void QuoteText(char *string, int count);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * This function 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(
+ int argc, /* Number of command-line arguments. */
+ char **argv) /* Values of command-line arguments. */
+{
+ FILE *f;
+#define MAX_LINE_SIZE 4000
+ 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[0] == '\'')) && (line[1] == '\\') && (line[2] == '\"')) {
+ /*
+ * This line is a comment. Ignore it.
+ */
+
+ continue;
+ }
+
+ if (strlen(line) >= MAX_LINE_SIZE -1) {
+ fprintf(stderr, "Too long line. Max is %d chars.\n",
+ MAX_LINE_SIZE - 1);
+ exit(1);
+ }
+
+ 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 function 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(
+ char *line) /* The line of text that contains the macro
+ * invocation. */
+{
+ char *p, *end;
+ int quote;
+
+ /*
+ * If there is no macro name, then just skip the whole line.
+ */
+
+ if ((line[1] == 0) || (isspace(line[1]))) {
+ return;
+ }
+
+ PRINT(("macro"));
+ if (*line != '.') {
+ PRINT(("2"));
+ }
+
+ /*
+ * Parse the arguments to the macro (including the name), in order.
+ */
+
+ p = line+1;
+ while (1) {
+ PRINTC(' ');
+ 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 {
+ quote = 0;
+ for (end = p+1; (*end != 0) && (quote || !isspace(*end)); end++) {
+ if (*end == '\'') {
+ quote = !quote;
+ }
+ }
+ 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;
+ }
+ }
+ PRINTC('\n');
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoText --
+ *
+ * This function 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(
+ 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') {
+ PRINT(("tab\n"));
+ p++;
+ } else if (*p != '\\') {
+ /*
+ * Ordinary text.
+ */
+
+ for (end = p+1; (*end != '\\') && (*end != 0); end++) {
+ /* Empty loop body. */
+ }
+ PRINT(("text "));
+ QuoteText(p, end-p);
+ PRINTC('\n');
+ 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.
+ */
+
+ PRINT(("font %c\n", p[1]));
+ p += 2;
+ } else if (*p == '-') {
+ PRINT(("dash\n"));
+ p++;
+ } else if (*p == 'e') {
+ PRINT(("text \\\\\n"));
+ p++;
+ } else if (*p == '.') {
+ PRINT(("text .\n"));
+ p++;
+ } else if (*p == '&') {
+ p++;
+ } else if (*p == '0') {
+ PRINT(("text { }\n"));
+ p++;
+ } else if (*p == '(') {
+ if ((p[1] == 0) || (p[2] == 0)) {
+ fprintf(stderr, "Bad \\( sequence on line %d.\n",
+ lineNumber);
+ status = 1;
+ } else {
+ PRINT(("char {\\(%c%c}\n", p[1], p[2]));
+ p += 3;
+ }
+ } else if (*p == 'N' && *(p+1) == '\'') {
+ int ch;
+
+ p += 2;
+ sscanf(p,"%d",&ch);
+ PRINT(("text \\u%04x\n", ch));
+ while(*p&&*p!='\'') p++;
+ p++;
+ } else if (*p != 0) {
+ PRINT(("char {\\%c}\n", *p));
+ p++;
+ }
+ }
+ }
+ PRINT(("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(
+ char *string, /* The line of text. */
+ int count) /* Number of characters to write from
+ * string. */
+{
+ if (count == 0) {
+ PRINT(("{}"));
+ return;
+ }
+ for ( ; count > 0; string++, count--) {
+ switch (*string) {
+ case '\\':
+ if (*(string+1) == 'N' && *(string+2) == '\'') {
+ int ch;
+
+ string += 3;
+ count -= 3;
+ sscanf(string,"%d",&ch);
+ PRINT(("\\u%04x", ch));
+ while(count>0&&*string!='\'') {string++;count--;}
+ continue;
+ } else if (*(string+1) == '0') {
+ PRINT(("\\ "));
+ string++;
+ count--;
+ continue;
+ }
+ case '$': case '[': case '{': case ' ': case ';':
+ case '"': case '\t':
+ PRINTC('\\');
+ default:
+ PRINTC(*string);
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */