home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
miscutil
/
lit_073.lzh
/
LIT
/
LIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-16
|
9KB
|
376 lines
#include <stdio.h>
#include <exec/types.h>
/*
* Lit Text Utility - Filter a file to stdout showing all characters in
* an unambiguous format. See Lit Text Utility Manual for specification.
*
* Version 2.0 - 11/16/86, Copyright (C) 1986 Donald J Irving
*
* Author: Donald J. Irving
* 9812 Gardenwood Way
* Sacramento, CA 96827
* (916) 366-3225
* CIS: 73547,1335
* PLINK: ops158
*
* Lit may be freely distributed for personal use.
* Lit may not be sold or placed on a disk offered for sale without written
* permission from the author. Written permission will normally be granted
* at no charge for inclusion on so called "public domain disks" which are
* sold for nominal medium and handling fees. Lit may be modified for
* personal use, and trivial modifications such as changing defaults or
* specifying include files may be made for distribution, but lit is not to
* be modified substantially for distribution without written consent of the
* author. The lit.c source, lit manual file , and this copyright notice must
* be included on all distributions.
*
* Here is the overall algorithm, minus some of the details:
*
* if unable to interpret command line arguments
* print an error message and a Usage line;
* else
* set options and open files;
* if line specified to start on is not the first line
* throw out input file lines until the line specified;
* while read next char from input file
* if the char is printable
* print it;
* else
* represent it in a special format;
* if the char is a line feed
* output a linefeed;
* if there was a number of lines to print specified
* and ++line count equals that number
* return;
*
* Functions not returning values are not typed. Functions returning values
* are explicitly typed.
*
*/
/* The four possible settings for representation mode. */
#define BSLASH 1 /* use backslash rep else numeric */
#define CONTROL 2 /* use control char reps else numeric */
#define ALLREPS 3 /* use backslash else control else numeric */
#define NUMERIC 4 /* use numeric value reps only */
/* The three possible settings for numeric number base */
#define OCT 1 /* use octal representations as in \033 */
#define HEX 2 /* use hex representations as in \1B */
#define DEC 3 /* use decimal representations as in \027 */
/* The most likely setting for how many lines to print */
#define ALL_LINES 32767 /* print all the lines in the file */
/*
* Here are the default option settings. If you don't like them, please
* change them here. The comments on the define lines show the the default
* settings chosen by the author and upon which the manual is based. Please
* leave the comments as they are.
*/
/* original */
#define DEFAULT_START 1 /* 1 */
#define DEFAULT_PRINT ALL_LINES /* ALL_LINES */
#define DEFAULT_OUTMODE BSLASH /* BSLASH */
#define DEFAULT_BASE OCT /* OCT */
/* Non-printing characters which require special handling in the code */
#define DEL '\177'
struct opt {
short start;
short print;
short outmode;
short base;
};
typedef struct opt opt_t;
main(argc, argv)
int argc;
char *argv[];
{
FILE *ifp = NULL;
register short c;
static opt_t opt = {
DEFAULT_START,
DEFAULT_PRINT,
DEFAULT_OUTMODE,
DEFAULT_BASE
};
if (! process_args(argc, argv, &ifp, &opt))
printf("Usage: lit [<filename>] [-s<n>] [-p<n>] [-[bcan][ohd]]\n");
else {
if (opt.start != 1 && ! find_start_line(ifp, opt.start))
return;
while ((c = getc(ifp)) != EOF) {
if (! print_char(c, opt.outmode))
represent_char(c, opt.outmode, opt.base);
if (c == '\n') {
putchar('\n');
if (opt.print != ALL_LINES && last_line(opt.print))
break;
}
}
if (c != '\n')
putchar('\n');
}
}
/*
* process_args -- Process all the command line arguments. Each argument is
* expected to be either a minus sign option or an input file name. If an
* input file is already open, a subsequent input file name argument is an
* error.
*/
BOOL process_args(argc, argv, ifp, opt)
int argc;
char *argv[];
FILE **ifp;
opt_t *opt;
{
register short i;
for (i = 1; i < argc; i++) {
if (*argv[i] == '-') {
if (! process_opt(argv[i]+1, opt))
return (FALSE);
}
else if (*ifp != NULL) {
printf("Invalid argument %s, Input file already specified\n",
argv[i]);
return (FALSE);
}
else if ((*ifp = fopen(argv[i], "r")) == NULL) {
printf("Unable to open input file %s\n", argv[i]);
return (FALSE);
}
}
if (*ifp == NULL)
*ifp = stdin;
return (TRUE);
}
/*
* process_opt -- Process a minus-sign command line argument. The options
* s<linenum> and p<numlines> must stand alone with their own minus signs;
* The options b,c,a,n,o,h,d may be stacked after a single minus sign.
*/
BOOL process_opt(arg, opt)
char *arg;
opt_t *opt;
{
switch (*arg) {
case 's':
opt->start = atoi(arg+1); /* set starting linenum */
break;
case 'p':
opt->print = atoi(arg+1); /* set linenums to print */
break;
default:
for (; *arg; arg++) {
switch (*arg) {
case 'b':
opt->outmode = BSLASH; /* use backslash rep else */
break; /* numeric rep */
case 'c':
opt->outmode = CONTROL; /* use control char rep */
break; /* else numeric rep */
case 'a':
opt->outmode = ALLREPS; /* use backslash else */
break; /* control else numeric */
case 'n':
opt->outmode = NUMERIC; /* use numeric rep only */
break;
case 'o':
opt->base = OCT; /* numeric rep base is octal */
break;
case 'h':
opt->base = HEX; /* numeric rep base is hex */
break;
case 'd':
opt->base = DEC; /* numeric rep base is decimal */
break;
default:
printf("Unknown option: %c\n", *arg);
return (FALSE);
}
}
}
return (TRUE);
}
/*
* find_start_line -- Find the first line to start printing on, throwing
* out all the lines along the way.
*/
BOOL find_start_line(ifp, start)
FILE *ifp;
short start;
{
register short c, lineno = 1;
while (lineno < start) {
while ((c = getc(ifp)) != EOF && c != '\n')
;
if (c == EOF)
return (FALSE);
lineno++;
}
return (TRUE);
}
/*
* last_line -- Return true if the line just printed was the last line
* to print.
*/
BOOL last_line(print)
short print;
{
static short printed = 0;
if (++printed == print)
return (TRUE);
return (FALSE);
}
/*
* print_char -- Print a printable character. If it's a \, or if
* it's a ^ and control codes are enabled, then preface it with a \.
*/
BOOL print_char(c, outmode)
short c, outmode;
{
if (c < ' ' || c > '~')
return (FALSE);
if (c == '\\'
|| (c == '^' && (outmode == CONTROL || outmode == ALLREPS)))
putchar('\\');
putchar(c);
return (TRUE);
}
/*
* represent_char -- Represent a non-printable character using whichever
* representation format is appropriate for the outmode selected. The
* rep_xxx functions called try to represent the char in a particular
* format, and return false if the the character is not applicable.
*/
represent_char(c, outmode, base)
short c, outmode, base;
{
switch (outmode) {
case BSLASH:
if (rep_bslash(c))
return;
break;
case CONTROL:
if (rep_control(c))
return;
break;
case ALLREPS:
if (rep_bslash(c) || rep_control(c))
return;
break;
case NUMERIC:
break;
}
rep_numeric(c, base);
}
/*
* rep_bslash - Represent a non-printable char if possible using its
* C Language backslash construct, else return false. '\0' is not included.
*/
BOOL rep_bslash(c)
short c;
{
switch (c) {
case '\n': putchar('\\'); putchar('n'); break;
case '\t': putchar('\\'); putchar('t'); break;
case '\b': putchar('\\'); putchar('b'); break;
case '\r': putchar('\\'); putchar('r'); break;
case '\f': putchar('\\'); putchar('f'); break;
default :
return (FALSE);
}
return (TRUE);
}
/*
* rep_control -- represent a non-printable char if possible using its
* control character representation, else return false. All non-printing
* ascii chars are representable as control chars (with DEL arbitrarily
* assigned the representation ^?). Characters rejected are those outside
* the range of ascii (ie, left most bit on).
*/
BOOL rep_control(c)
short c;
{
if (c < '\0' || c > '\177')
return (FALSE);
putchar('^');
switch (c) {
case DEL:
putchar('?');
break;
default:
putchar(c | 0x40);
break;
}
return (TRUE);
}
/*
* rep_numeric - Unconditionally represent a character as a numeric value
* using the number base specified.
*/
rep_numeric(c, base)
short c, base;
{
char buf[4];
switch (base) {
case OCT:
printf("\\%03o", c);
break;
case HEX:
sprintf(buf, "\\%02x\0", c); /* make it upper case, %X */
if (buf[1] >= 'a') /* doesn't seem to work on */
buf[1] &= 0x5F; /* my compiler. */
if (buf[2] >= 'a')
buf[2] &= 0x5F;
printf("%s", buf);
break;
case DEC:
printf("\\%03d", c);
break;
}
}