home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / DOOG / CBASE09.ZIP / BLKIO10.ZIP / MANX10.ZIP / MANX.C next >
Text File  |  1989-08-30  |  10KB  |  345 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "manx.c    1.1 - 89/08/29" */
  5.  
  6. #include <errno.h>
  7. #include <limits.h>
  8. #include <stdio.h>
  9. /* #include <stdlib.h> */
  10. void exit();            /* delete if you have stdlib.h */
  11. #define EXIT_SUCCESS    (0)
  12. #define EXIT_FAILURE    (1)
  13. /*#include <string.h>*/
  14. char *strstr();            /* delete if you have string.h */
  15. int strncmp();
  16. int strcmp();
  17. unsigned strlen();
  18.  
  19. #define PAGELEN        (60)        /* default page length */
  20. #define BACKSLASH    ('\\')        /* char to begin escape sequence */
  21. #define PAGINATOR    ("\f")        /* string to use as page separator */
  22. #define MAXLINE        (256)        /* maximum line length */
  23.  
  24. /* command syntax */
  25. #define USAGE        ("Usage: manx [language] [page-length]")
  26.  
  27. /* language type definition */
  28. typedef struct {
  29.     char option[11];    /* language command line option */
  30.     char begin[21];        /* marker for beginning of manual entry */
  31.     char end[21];        /* marker for end of manual entry */
  32.     char comment[11];    /* character sequence that begins comment */
  33.     int  flags;        /* bit flags */
  34. } lang_t;
  35.  
  36. /* lang_t flag bits */
  37. #define SINGLELINE    (1)
  38. #define MULTILINE    (2)
  39.  
  40. lang_t langs[] = {
  41.     {"a",  "--man", "--end", "--", SINGLELINE},    /* Ada */
  42.     {"c",  "/*man", "*/",    "/*", MULTILINE},    /* C */
  43.     {"f",  "Cman", "Cend",   "C",  SINGLELINE},    /* Fortran */
  44.     {"l",  ";man", ";end",   ";",  SINGLELINE},    /* Lisp */
  45.     {"m",  "(*man", "*)",    "(*", MULTILINE},    /* Modula-2 */
  46.     {"p",  "{man",  "}",     "{",  MULTILINE},    /* Pascal */
  47.     {"pl", "\"man", "\"",    "\"", MULTILINE},    /* Prolog */
  48.     {"st", "\"man", "\"",    "\"", MULTILINE}    /* Smalltalk */
  49. };
  50.  
  51. /* index into langs array for each language */
  52. #define ADA        (1)
  53. #define C        (2)
  54. #define FORTRAN        (3)
  55. #define LISP        (4)
  56. #define MODULA_2    (5)
  57. #define PASCAL        (6)
  58. #define PROLOG        (7)
  59. #define SMALLTALK    (8)
  60.  
  61. #define LANG        C        /* default language */
  62.  
  63. static int manputs(/*const char *cs, FILE *stream*/);
  64.  
  65. /*man---------------------------------------------------------------------------
  66. NAME
  67.      manx - manual entry extracter
  68.  
  69. SYNOPSIS
  70.      manx [language] [page-length]
  71.  
  72. DESCRIPTION
  73.      The manx command extracts manual entries from source files.  The
  74.      files are read from stdin and the manual entries are written to
  75.      stdout.  Each individual manual entry is broken into pages
  76.      separated by form feeds and terminated with a form feed.
  77.  
  78.      The language option specifies which language the source file is
  79.      written in.  The languages supported are:
  80.  
  81.                               Ada            -a
  82.                               C              -c
  83.                               Fortran        -f
  84.                               Lisp           -l
  85.                               Modula-2       -m
  86.                               Pascal         -p
  87.                               Prolog         -pl
  88.                               Smalltalk      -st
  89.  
  90.      The default language is C.
  91.  
  92.      The page-length argument can be used to set the page length.
  93.      Pagination may be disabled by specifying a page length of 0.
  94.      The default page length is 60.
  95.  
  96.      The beginning of a manual entry is marked by the character
  97.      sequence (language dependent) to start a comment immediately
  98.      followed by the characters man.  This marker must appear in the
  99.      leftmost column allowed by the language.  For multiple-line
  100.      comments, the end of the manual entry is marked by the character
  101.      sequence terminating the comment.  For single-line comments, the
  102.      end of a manual entry is marked by the character sequence to end
  103.      a comment immediately followed by the characters end.  All lines
  104.      between but not including these constitute the manual entry.
  105.  
  106.      The following escape sequences can be used within a manual entry:
  107.  
  108.                        audible alert       BEL       \\a
  109.                        backspace           BS        \\b
  110.                        carriage return     CR        \\r
  111.                        horizontal tab      HT        \\t
  112.                        backslash           \\         \\\\
  113.  
  114. EXAMPLE
  115.      The following command would extract the manual pages from all C
  116.      files in the current UNIX directory, paginate them every 24
  117.      lines, and place them in a file called manual.
  118.  
  119.           cat *.c | manx -c 24 > manual
  120.  
  121. ------------------------------------------------------------------------------*/
  122. /*int main(int argc, char *argv[])*/
  123. int main(argc, argv)
  124. int    argc;
  125. char * argv[];
  126. {
  127.     int    lang        = LANG;        /* default language */
  128.     long    pagelen        = PAGELEN;    /* default page length */
  129.     int    page        = 0;        /* page number */
  130.     long    line        = 0;        /* line number */
  131.     int    i        = 0;        /* index variable */
  132.     char    s[MAXLINE]    /*= ""*/;    /* line storage */
  133.     char *    endptr        = NULL;        /* pointer for strtol fct */
  134.  
  135.     /* process command line options and arguments */
  136.     /* language option */
  137.     if ((argc > 1) && (*argv[1] == '-')) {
  138.         argc--;
  139.         argv++;
  140.         lang = 0;
  141.         for (i = 0; i < sizeof(langs)/sizeof(langs[0]); i++) {
  142.             if (strcmp(*argv + 1, langs[i].option) == 0) {
  143.                 lang = i + 1;
  144.                 break;
  145.             }
  146.         }
  147.         if (lang == 0) {
  148.             printf("manx: invalid language option\n");
  149.             printf("%s\n", USAGE);
  150.             exit(EXIT_FAILURE);
  151.         }
  152.     }
  153.     /* page length argument */
  154.     if (argc > 1) {
  155.         argc--;
  156.         argv++;
  157.         errno = 0;
  158.         pagelen = strtol(*argv, &endptr, 10);
  159.         if (errno == ERANGE) {
  160.             printf("manx: page length argument out of range\n");
  161.             printf("%s\n", USAGE);
  162.             exit(EXIT_FAILURE);
  163.         }
  164.         if (endptr != NULL) {
  165.             if (endptr[0] != '\0') {
  166.                 printf("%s\n", USAGE);
  167.                 exit(EXIT_FAILURE);
  168.             }
  169.         }
  170.         if (pagelen < 0) {
  171.             printf("%s\n", USAGE);
  172.             exit(EXIT_FAILURE);
  173.         }
  174.     }
  175.     if (argc != 1) {
  176.         printf("%s\n", USAGE);
  177.         exit(EXIT_FAILURE);
  178.     }
  179.  
  180.     /* main loop */
  181.     while (1) {
  182.         /* read next line of input */
  183.         if (fgets(s, sizeof(s), stdin) == NULL) {
  184.             if (ferror(stdin) != 0) {
  185.                 fprintf(stderr, "*** Error reading standard input.  Exiting.\n");
  186.                 exit(EXIT_FAILURE);
  187.             }
  188.             break;
  189.         }
  190.         /* check for manual entry marker at beginning of line */
  191.         if (strncmp(s, langs[lang - 1].begin, strlen(langs[lang - 1].begin)) != 0) {
  192.             continue;
  193.         }
  194.         if (langs[lang - 1].flags & MULTILINE) {
  195.             if (strstr(s, langs[lang - 1].end) != NULL) {
  196.                 continue;
  197.             }
  198.         }
  199.         /* inner loop */
  200.         line = 0;
  201.         page = 1;
  202.         while (1) {
  203.             line++;
  204.             /* read next line of manual entry */
  205.             if (fgets(s, sizeof(s), stdin) == NULL) {
  206.                 if (ferror(stdin) != 0) {
  207.                     fprintf(stderr, "*** Error reading standard input.  Exiting.\n");
  208.                     exit(EXIT_FAILURE);
  209.                 }
  210.                 break;
  211.             }
  212.             /* check for end of entry marker */
  213.             if (langs[lang - 1].flags & SINGLELINE) {
  214.                 if (strncmp(s, langs[lang - 1].end, strlen(langs[lang - 1].end)) == 0) {
  215.                     break;
  216.                 }
  217.                 if (strncmp(s, langs[lang - 1].comment, strlen(langs[lang - 1].comment)) != 0) {
  218.                     break;
  219.                 }
  220.             } else {
  221.                 if (strstr(s, langs[lang - 1].end) != NULL) {
  222.                     break;
  223.                 }
  224.             }
  225.             if (s[strlen(s) - 1] != '\n') {
  226.                 fprintf(stderr, "*** Warning.  Maximum line length of %d exceeded.  Page %ld, line %ld.\n", (int)(sizeof(s) - 2), page, line);
  227.                 s[strlen(s) - 1] = '\n';
  228.             }
  229.             if (langs[lang - 1].flags & SINGLELINE) {
  230.                 if (manputs(s + strlen(langs[lang - 1].comment) , stdout) == EOF) {
  231.                     exit(EXIT_FAILURE);
  232.                 }
  233.             } else {
  234.                 if (manputs(s, stdout) == EOF) {
  235.                     exit(EXIT_FAILURE);
  236.                 }
  237.             }
  238.             if ((line >= pagelen) && (pagelen != 0)) {
  239.                 if (fputs(PAGINATOR, stdout) == EOF) {
  240.                     exit(EXIT_FAILURE);
  241.                 }
  242.                 line = 0;
  243.                 page++;
  244.             }
  245.         }
  246.         /* write last paginator */
  247.         if ((line != 1) && (pagelen != 0)) {
  248.             if (fputs(PAGINATOR, stdout) == EOF) {
  249.                 exit(EXIT_FAILURE);
  250.             }
  251.             page++;
  252.         }
  253.         /* check if end of file */
  254.         if (feof(stdin) != 0) {
  255.             break;
  256.         }
  257.     }
  258.  
  259.     exit(EXIT_SUCCESS);
  260. }
  261.  
  262. /*------------------------------------------------------------------------------
  263. DESCRIPTION
  264.      The manputs function writes the null-terminated string pointed to by
  265.      cs to the named output stream.  Any manx escape sequence found in
  266.      the string is converted to the character it represents before being
  267.      output.
  268.  
  269. DIAGNOSTICS
  270.      Upon successful completion, a value of 0 is returned.  Otherwise, a
  271.      value of EOF is returned.
  272.  
  273. ------------------------------------------------------------------------------*/
  274. /*static int manputs(const char *cs, FILE *stream)*/
  275. static int manputs(cs, stream)
  276. char *cs;
  277. FILE *stream;
  278. {
  279.     char         t[MAXLINE]    /*= ""*/;    /* target string */
  280.     int         i        = 0;    /* index into target string */
  281.     char         c        = '\0';
  282.  
  283.     /* convert string to output format */
  284.     for (i = 0; *cs != '\0'; i++) {
  285.         if (i > sizeof(t)) {
  286.             return EOF;
  287.         }
  288.         c = *cs++;
  289.         /* check for escape sequence */
  290.         if ((c == BACKSLASH) && (*cs != '\0')) {
  291.             c = *cs++;
  292.             switch (c) {
  293.             case 'a':    /* audible alert */
  294.                 c = '\a';
  295.                 break;    /* case 'a': */
  296.             case 'b':    /* backspace */
  297.                 c = '\b';
  298.                 break;    /* case 'b': */
  299.             case 'r':    /* carriage return */
  300.                 c = '\r';
  301.                 break;    /* case 'r': */
  302.             case 't':    /* horizontal tab */
  303.                 c = '\t';
  304.                 break;    /* case 't': */
  305.             case '\\':    /* backslash */
  306.                 c = '\\';
  307.                 break;    /* case '\\': */
  308.             default:    /* ignore backslash */
  309.                 break;    /* default: */
  310.             }
  311.         }
  312.         t[i] = c;
  313.     }
  314.     t[i] = '\0';
  315.  
  316.     /* write converted string to stream */
  317.     if (fputs(t, stream) == EOF) {
  318.         return EOF;
  319.     }
  320.  
  321.     return 0;
  322. }
  323.  
  324. /* delete this function if it is included in your string library */
  325. char *strstr(cs, ct)
  326. char *cs;
  327. char *ct;
  328. {
  329.     unsigned int ctlen = 0;
  330.  
  331.     if ((cs == NULL) || (ct == NULL)) {
  332.         return NULL;
  333.     }
  334.  
  335.     ctlen = strlen(ct);
  336.     while (*cs != '\0') {
  337.         if (strncmp(cs, ct, ctlen) == 0) {
  338.             return cs;
  339.         }
  340.         cs++;
  341.     }
  342.  
  343.     return NULL;
  344. }
  345.