home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Press 1997 July
/
Sezamfile97_1.iso
/
msdos
/
c
/
cbase11.a03
/
CBASE11.ZIP
/
MANX
/
MANX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-01
|
12KB
|
431 lines
/*
* Copyright (c) 1989-1992 Citadel Software, Inc.
* All Rights Reserved
*/
/* #ident "@(#)manx.c 1.5 - 93/01/01" */
#include <port.h>
/* standard headers */
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#ifdef AC_STDLIB
#include <stdlib.h>
#endif
#ifdef AC_STRING
#include <string.h>
#endif
/* function declarations */
#ifdef AC_PROTO
static int manputs(const char *cs, FILE *fp, long *pagep, long *linep);
#else
static int manputs();
#endif
/* constants */
#define PAGELEN (60) /* default page length */
#define BACKSLASH ('\\') /* char to begin escape sequence */
#define PAGINATOR "\f" /* string to use as page separator */
#define LINELEN_MAX (256) /* maximum line length */
#define PROGNAME "manx" /* default program name */
#define USAGE "usage: %s [language] [page-length]\n"
/* usage message */
typedef struct { /* language definition structure */
char option[11]; /* language command line option */
char begin[21]; /* marker for beginning of manual entry */
char end[21]; /* marker for end of manual entry */
char comment[11]; /* character sequence that begins comment */
int flags; /* flags */
} lang_t;
/* lang_t bit flags */
#define LINECMT (1)
#define BLOCKCMT (2)
/* language definitions */
lang_t langs[] = {
{"a", "--man", "--end", "--", LINECMT}, /* Ada */
{"as", ";man", ";end", ";", LINECMT}, /* ASM */
{"c", "/*man", "*/", "/*", BLOCKCMT}, /* C */
{"f", "Cman", "Cend", "C", LINECMT}, /* Fortran */
{"l", ";man", ";end", ";", LINECMT}, /* Lisp */
{"m", "(*man", "*)", "(*", BLOCKCMT}, /* Modula-2 */
{"p", "{man", "}", "{", BLOCKCMT}, /* Pascal */
{"pl", "\"man", "\"", "\"", BLOCKCMT}, /* Prolog */
{"st", "\"man", "\"", "\"", BLOCKCMT}, /* Smalltalk */
};
/* index into langs array for each language */
#define ADA (1)
#define ASM (2)
#define C (3)
#define FORTRAN (4)
#define LISP (5)
#define MODULA_2 (6)
#define PASCAL (7)
#define PROLOG (8)
#define SMALLTALK (9)
#define LANG C /* default language */
/*man---------------------------------------------------------------------------
NAME
manx - manual entry extracter
SYNOPSIS
manx [language] [page-length]
DESCRIPTION
The manx command extracts manual entries from source files. The
source files are read from stdin and the manual entries are
written to stdout. Each individual manual entry is separated
into pages by form feeds and terminated with a form feed.
The language option specifies the language of the source file.
The languages supported are:
Ada -a
assembly -as
C -c
Fortran -f
Lisp -l
Modula-2 -m
Pascal -p
Prolog -pl
Smalltalk -st
The default language is C.
The page-length argument can be used to set the page length.
Pagination may be disabled by specifying a page length of 0.
The default page length is 60.
The beginning of a manual entry is marked by the character
sequence (language dependent) to start a comment immediately
followed by the characters 'man'. This marker must appear in the
leftmost column allowed by the language. For block comments, the
end of the manual entry is marked by the end of the comment. For
line comments, the end of a manual entry is marked by the
character sequence to end a comment immediately followed by the
characters 'end'. All lines between but not including these
constitute the manual entry.
The following escape sequences can be used within a manual entry:
audible alert BEL \\a
backspace BS \\b
form feed FF \\f
carriage return CR \\r
horizontal tab HT \\t
backslash \\ \\\\
EXAMPLES
On a UNIX system, the following command would extract the manual
pages from all C files in the current UNIX directory, paginate
them to 52 lines, and place the results in a file called manual.
$ cat *.c | manx -c 52 > manual
Catenating files is much for difficult in DOS. For that system,
the following sequence of commands is required.
> copy file.c/a+file2.c+file3.c+file4.c tmp
> type tmp | manx -c 52 > manual
> del tmp
It is strongly recommended that a DOS version of cat be obtained
for use with manx.
NOTES
manx is particularly convenient when used in conjunction with a
make utility. Below are the relevant parts of the UNIX makefile
of an actual C library for which manx is used to extract the
reference manual.
LIB = blkio
MAN = $(LIB).man
MANS = blkio.h \\
bclose.c bexit.c bflpop.c bflpush.c \\
bflush.c bgetb.c bgetbf.c bgeth.c \\
bgethf.c bopen.c bputb.c bputbf.c \\
bputh.c bputhf.c bsetbuf.c bsetvbuf.c \\
bsync.c lockb.c
man: $(MAN)
$(MAN): $(MANS)
cat $(MANS) | manx -c > $@
The reference manual for this library is generated with the
command
make man
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int main(int argc, char *argv[])
#else
int main(argc, argv)
int argc;
char *argv[];
#endif
{
char * endptr = NULL; /* pointer for strtol fct */
int i = 0; /* loop index */
int lang = LANG; /* default language */
long line = 0; /* line number */
long page = 0; /* page number */
long pagelen = PAGELEN; /* default page length */
char * progname = PROGNAME; /* program name */
char s[LINELEN_MAX + 1]; /* input line */
/* process command line options and arguments */
if (argc > 0) { /* program name */
progname = *argv;
--argc;
++argv;
}
if (argc > 0 && *argv[0] == '-') { /* language option */
lang = 0;
for (i = 0; i < sizeof(langs) / sizeof(*langs); ++i) {
if (strcmp(*argv + 1, langs[i].option) == 0) {
lang = i + 1;
break;
}
}
if (lang == 0) {
fprintf(stderr, "%s: illegal option -- %s\n", progname, *argv + 1);
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
--argc;
++argv;
}
if (argc > 0) { /* page length argument */
errno = 0;
pagelen = strtol(*argv, &endptr, 10);
if (errno == ERANGE) {
fprintf(stderr, "%s: page length %s too large", progname, *argv);
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
if (endptr != NULL) {
if (endptr[0] != '\0') {
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
}
if (pagelen < 0) {
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
--argc;
++argv;
}
if (argc != 0) {
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
/* main loop */
for (;;) {
/* read next line of input */
if (fgets(s, (int)sizeof(s), stdin) == NULL) {
if (ferror(stdin) != 0) {
fprintf(stderr, "%s: *** Error reading input. Exiting.\n", progname);
exit(EXIT_FAILURE);
}
break;
}
/* check for manual entry marker at beginning of line */
if (strncmp(s, langs[lang - 1].begin, strlen(langs[lang - 1].begin)) != 0) {
continue;
}
if (langs[lang - 1].flags & BLOCKCMT) {
if (strstr(s, langs[lang - 1].end) != NULL) {
continue;
}
}
/* inner loop */
line = 0;
page = 1;
for (;;) {
++line;
/* read next line of manual entry */
if (fgets(s, (int)sizeof(s), stdin) == NULL) {
if (ferror(stdin) != 0) {
fprintf(stderr, "%s: *** Error reading standard input. Exiting.\n", progname);
exit(EXIT_FAILURE);
}
break;
}
/* check for end of entry marker */
if (langs[lang - 1].flags & LINECMT) {
if (strncmp(s, langs[lang - 1].end, strlen(langs[lang - 1].end)) == 0) {
break;
}
if (strncmp(s, langs[lang - 1].comment, strlen(langs[lang - 1].comment)) != 0) {
break;
}
} else {
if (strstr(s, langs[lang - 1].end) != NULL) {
break;
}
}
if (s[strlen(s) - 1] != '\n') {
fprintf(stderr, "%s: *** Warning. Maximum line length of %d exceeded. Page %ld, line %ld.\n", progname, (int)(sizeof(s) - 2), page, line);
s[strlen(s) - 1] = '\n';
}
if (langs[lang - 1].flags & LINECMT) {
if (manputs(s + strlen(langs[lang - 1].comment) , stdout, &page, &line) == -1) {
fprintf(stderr, "%s: *** Error writing line %ld, of page %ld. Exiting\n", progname, line, page);
exit(EXIT_FAILURE);
}
} else {
if (manputs(s, stdout, &page, &line) == -1) {
fprintf(stderr, "%s: *** Error writing line %ld, of page %ld. Exiting\n", progname, line, page);
exit(EXIT_FAILURE);
}
}
if (line >= pagelen && pagelen != 0) {
if (fputs(PAGINATOR, stdout) == EOF) {
fprintf(stderr, "%s: *** Error writing paginator to standard output. Exiting.\n", progname);
exit(EXIT_FAILURE);
}
line = 0;
++page;
}
}
/* write last paginator */
if (line != 1 && pagelen != 0) {
if (fputs(PAGINATOR, stdout) == EOF) {
fprintf(stderr, "%s: *** Error writing paginator to standard output. Exiting.\n", progname);
exit(EXIT_FAILURE);
}
++page;
}
/* check if end of file */
if (feof(stdin) != 0) {
break;
}
}
exit(EXIT_SUCCESS);
}
/*------------------------------------------------------------------------------
NAME
manputs - manual entry put
SYNOPSIS
static int manputs(cs, fp, pagep, linep)
const char *cs;
FILE *fp;
long *pagep;
long *linep;
DESCRIPTION
The manputs function writes the null-terminated string pointed to
by cs to the named output stream. Any manx escape sequence found
in the string is converted to the character it represents before
being output.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
static int manputs(const char *cs, FILE *fp, long *pagep, long *linep)
#else
static int manputs(cs, fp, pagep, linep)
const char *cs;
FILE *fp;
long *pagep;
long *linep;
#endif
{
char t[LINELEN_MAX + 1]; /* target string */
int i = 0; /* index into target string */
char c = '\0';
/* convert string to output format */
for (i = 0; *cs != '\0'; ++i) {
if (i > sizeof(t)) {
return -1;
}
c = *cs++;
/* check for escape sequence */
if (c == BACKSLASH && *cs != '\0') {
c = *cs++;
switch (c) {
#ifdef AC_ESCAPE
case 'a': /* audible alert */
c = '\a';
break;
#endif
case 'b': /* backspace */
c = '\b';
break;
case 'f': /* form feed */
c = '\f';
*linep = 0;
++*pagep;
break;
case 'r': /* carriage return */
c = '\r';
break;
case 't': /* horizontal tab */
c = '\t';
break;
case '\\': /* backslash */
c = '\\';
break;
default: /* ignore backslash */
break;
}
}
t[i] = c;
}
t[i] = '\0';
/* write converted string to fp */
if (fputs(t, fp) == EOF) {
return -1;
}
return 0;
}
#ifndef AC_STRING
#ifdef AC_PROTO
static char *strstr(const char *cs, const char *ct)
#else
static char *strstr(cs, ct)
const char *cs;
const char *ct;
#endif
{
int ctlen = 0;
if (cs == NULL || ct == NULL) {
return NULL;
}
ctlen = strlen(ct);
while (*cs != '\0') {
if (strncmp(cs, ct, ctlen) == 0) {
return cs;
}
++cs;
}
return NULL;
}
#endif