man2tcl.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:8k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * man2tcl.c --
  3.  *
  4.  * This file contains a program that turns a man page of the
  5.  * form used for Tcl and Tk into a Tcl script that invokes
  6.  * a Tcl command for each construct in the man page.  The
  7.  * script can then be eval'ed to translate the manual entry
  8.  * into some other format such as MIF or HTML.
  9.  *
  10.  * Usage:
  11.  *
  12.  * man2tcl ?fileName?
  13.  *
  14.  * Copyright (c) 1995 Sun Microsystems, Inc.
  15.  *
  16.  * See the file "license.terms" for information on usage and redistribution
  17.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  18.  *
  19.  * RCS: @(#) $Id: man2tcl.c,v 1.7.2.1 2003/12/09 15:32:20 dkf Exp $
  20.  */
  21. static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08";
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #ifndef NO_ERRNO_H
  26. #include <errno.h>
  27. #endif
  28. /*
  29.  * Imported things that aren't defined in header files:
  30.  */
  31. /*
  32.  * Some <errno.h> define errno to be something complex and
  33.  * thread-aware; in that case we definitely do not want to declare
  34.  * errno ourselves!
  35.  */
  36. #ifndef errno
  37. extern int errno;
  38. #endif
  39. /*
  40.  * Current line number, used for error messages.
  41.  */
  42. static int lineNumber;
  43. /*
  44.  * The variable below is set to 1 if an error occurs anywhere
  45.  * while reading in the file.
  46.  */
  47. static int status;
  48. /*
  49.  * The variable below is set to 1 if output should be generated.
  50.  * If it's 0, it means we're doing a pre-pass to make sure that
  51.  * the file can be properly parsed.
  52.  */
  53. static int writeOutput;
  54. /*
  55.  * Prototypes for procedures defined in this file:
  56.  */
  57. static void DoMacro(char *line);
  58. static void DoText(char *line);
  59. static void QuoteText(char *string, int count);
  60. /*
  61.  *----------------------------------------------------------------------
  62.  *
  63.  * main --
  64.  *
  65.  * This procedure is the main program, which does all of the work
  66.  * of the program.
  67.  *
  68.  * Results:
  69.  * None: exits with a 0 return status to indicate success, or
  70.  * 1 to indicate that there were problems in the translation.
  71.  *
  72.  * Side effects:
  73.  * A Tcl script is output to standard output.  Error messages may
  74.  * be output on standard error.
  75.  *
  76.  *----------------------------------------------------------------------
  77.  */
  78. int
  79. main(argc, argv)
  80.     int argc; /* Number of command-line arguments. */
  81.     char **argv; /* Values of command-line arguments. */
  82. {
  83.     FILE *f;
  84. #define MAX_LINE_SIZE 1000
  85.     char line[MAX_LINE_SIZE];
  86.     char *p;
  87.     /*
  88.      * Find the file to read, and open it if it isn't stdin.
  89.      */
  90.     if (argc == 1) {
  91. f = stdin;
  92.     } else if (argc == 2) {
  93. f = fopen(argv[1], "r");
  94. if (f == NULL) {
  95.     fprintf(stderr, "Couldn't read "%s": %sn", argv[1],
  96.     strerror(errno));
  97.     exit(1);
  98. }
  99.     } else {
  100. fprintf(stderr, "Usage: %s ?fileName?n", argv[0]);
  101.     }
  102.     /*
  103.      * Make two passes over the file.  In the first pass, just check
  104.      * to make sure we can handle everything.  If there are problems,
  105.      * generate output and stop.  If everything is OK, make a second
  106.      * pass to actually generate output.
  107.      */
  108.     for (writeOutput = 0; writeOutput < 2; writeOutput++) {
  109. lineNumber = 0;
  110. status = 0;
  111. while (fgets(line, MAX_LINE_SIZE, f) != NULL) {
  112.     for (p = line; *p != 0; p++) {
  113. if (*p == 'n') {
  114.     *p = 0;
  115.     break;
  116. }
  117.     }
  118.     lineNumber++;
  119.     
  120.     if ((line[0] == ''') && (line[1] == '\') && (line[2] == '"')) {
  121. /* 
  122.  * This line is a comment.  Ignore it.
  123.  */
  124.     
  125. continue;
  126.     }
  127.     
  128.     if (strlen(line) >= MAX_LINE_SIZE -1) {
  129. fprintf(stderr, "Too long line. Max is %d chars.n",
  130. MAX_LINE_SIZE - 1);
  131. exit(1);
  132.     }
  133.     if ((line[0] == '.') || (line[0] == ''')) {
  134. /*
  135.  * This line is a macro invocation.
  136.  */
  137.     
  138. DoMacro(line);
  139.     } else {
  140. /*
  141.  * This line is text, possibly with formatting characters
  142.  * embedded in it.
  143.  */
  144.     
  145. DoText(line);
  146.     }
  147. }
  148. if (status != 0) {
  149.     break;
  150. }
  151. fseek(f, 0, SEEK_SET);
  152.     }
  153.     exit(status);
  154. }
  155. /*
  156.  *----------------------------------------------------------------------
  157.  *
  158.  * DoMacro --
  159.  *
  160.  * This procedure is called to handle a macro invocation.
  161.  * It parses the arguments to the macro and generates a
  162.  * Tcl command to handle the invocation.
  163.  *
  164.  * Results:
  165.  * None.
  166.  *
  167.  * Side effects:
  168.  * A Tcl command is written to stdout.
  169.  *
  170.  *----------------------------------------------------------------------
  171.  */
  172. static void
  173. DoMacro(line)
  174.     char *line; /* The line of text that contains the
  175.  * macro invocation. */
  176. {
  177.     char *p, *end;
  178.     /*
  179.      * If there is no macro name, then just skip the whole line.
  180.      */
  181.     if ((line[1] == 0) || (isspace(line[1]))) {
  182. return;
  183.     }
  184.     if (writeOutput) {
  185. printf("macro");
  186.     }
  187.     if (*line != '.') {
  188. if (writeOutput) {
  189.     printf("2");
  190. }
  191.     }
  192.     /*
  193.      * Parse the arguments to the macro (including the name), in order.
  194.      */
  195.     p = line+1;
  196.     while (1) {
  197. if (writeOutput) {
  198.     putc(' ', stdout);
  199. }
  200. if (*p == '"')  {
  201.     /*
  202.      * The argument is delimited by quotes.
  203.      */
  204.     for (end = p+1; *end != '"'; end++) {
  205. if (*end == 0) {
  206.     fprintf(stderr,
  207. "Unclosed quote in macro call on line %d.n",
  208. lineNumber);
  209.     status = 1;
  210.     break;
  211. }
  212.     }
  213.     QuoteText(p+1, (end-(p+1)));
  214. } else {
  215.     for (end = p+1;  (*end != 0) && !isspace(*end); end++) {
  216. /* Empty loop body. */
  217.     }
  218.     QuoteText(p, end-p);
  219. }
  220. if (*end == 0) {
  221.     break;
  222. }
  223. p = end+1;
  224. while (isspace(*p)) {
  225.     /*
  226.      * Skip empty space before next argument.
  227.      */
  228.     p++;
  229. }
  230. if (*p == 0) {
  231.     break;
  232. }
  233.     }
  234.     if (writeOutput) {
  235. putc('n', stdout);
  236.     }
  237. }
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * DoText --
  242.  *
  243.  * This procedure is called to handle a line of troff text.
  244.  * It parses the text, generating Tcl commands for text and
  245.  * for formatting stuff such as font changes.
  246.  *
  247.  * Results:
  248.  * None.
  249.  *
  250.  * Side effects:
  251.  * Tcl commands are written to stdout.
  252.  *
  253.  *----------------------------------------------------------------------
  254.  */
  255. static void
  256. DoText(line)
  257.     char *line; /* The line of text. */
  258. {
  259.     char *p, *end;
  260.     /*
  261.      * Divide the line up into pieces consisting of backslash sequences,
  262.      * tabs, and other text.
  263.      */
  264.     p = line;
  265.     while (*p != 0) {
  266. if (*p == 't') {
  267.     if (writeOutput) {
  268. printf("tabn");
  269.     }
  270.     p++;
  271. } else if (*p != '\') {
  272.     /*
  273.      * Ordinary text.
  274.      */
  275.     for (end = p+1; (*end != '\') && (*end != 0); end++) {
  276. /* Empty loop body. */
  277.     }
  278.     if (writeOutput) {
  279. printf("text ");
  280.     }
  281.     QuoteText(p, end-p);
  282.     if (writeOutput) {
  283. putc('n', stdout);
  284.     }
  285.     p = end;
  286. } else {
  287.     /*
  288.      * A backslash sequence.  There are particular ones
  289.      * that we understand;  output an error message for
  290.      * anything else and just ignore the backslash.
  291.      */
  292.     p++;
  293.     if (*p == 'f') {
  294. /*
  295.  * Font change.
  296.  */
  297. if (writeOutput) {
  298.     printf("font %cn", p[1]);
  299. }
  300. p += 2;
  301.     } else if (*p == '-') {
  302. if (writeOutput) {
  303.     printf("dashn");
  304. }
  305. p++;
  306.     } else if (*p == 'e') {
  307. if (writeOutput) {
  308.     printf("text \\n");
  309. }
  310. p++;
  311.     } else if (*p == '.') {
  312. if (writeOutput) {
  313.     printf("text .n");
  314. }
  315. p++;
  316.     } else if (*p == '&') {
  317. p++;
  318.     } else if (*p == '(') {
  319. if ((p[1] == 0) || (p[2] == 0)) {
  320.     fprintf(stderr, "Bad \( sequence on line %d.n",
  321.     lineNumber);
  322.     status = 1;
  323. } else {
  324.     if (writeOutput) {
  325. printf("char {\(%c%c}n", p[1], p[2]);
  326.     }
  327.     p += 3;
  328. }
  329.     } else if (*p != 0) {
  330. if (writeOutput) {
  331.     printf("char {\%c}n", *p);
  332. }
  333. p++;
  334.     }
  335. }
  336.     }
  337.     if (writeOutput) {
  338. printf("newlinen");
  339.     }
  340. }
  341. /*
  342.  *----------------------------------------------------------------------
  343.  *
  344.  * QuoteText --
  345.  *
  346.  * Copy the "string" argument to stdout, adding quote characters
  347.  * around any special Tcl characters so that they'll just be treated
  348.  * as ordinary text.
  349.  *
  350.  * Results:
  351.  * None.
  352.  *
  353.  * Side effects:
  354.  * Text is written to stdout.
  355.  *
  356.  *----------------------------------------------------------------------
  357.  */
  358. static void
  359. QuoteText(string, count)
  360.     char *string; /* The line of text. */
  361.     int count; /* Number of characters to write from string. */
  362. {
  363.     if (count == 0) {
  364. if (writeOutput) {
  365.     printf("{}");
  366. }
  367. return;
  368.     }
  369.     for ( ; count > 0; string++, count--) {
  370. if ((*string == '$') || (*string == '[') || (*string == '{')
  371. || (*string == ' ') || (*string == ';') || (*string == '\')
  372. || (*string == '"') || (*string == 't')) {
  373.     if (writeOutput) {
  374. putc('\', stdout);
  375.     }
  376. }
  377. if (writeOutput) {
  378.     putc(*string, stdout);
  379. }
  380.     }
  381. }