10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*381Smuffin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*381Smuffin /* All Rights Reserved */
29*381Smuffin
300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <assert.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <locale.h>
380Sstevel@tonic-gate #include <sys/varargs.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate * Deroff command -- strip troff, eqn, and Tbl sequences from a file.
420Sstevel@tonic-gate * Has three flags argument, -w, to cause output one word per line
430Sstevel@tonic-gate * rather than in the original format.
440Sstevel@tonic-gate * -mm (or -ms) causes the corresponding macro's to be interpreted
450Sstevel@tonic-gate * so that just sentences are output
460Sstevel@tonic-gate * -ml also gets rid of lists.
470Sstevel@tonic-gate * -i causes deroff to ignore .so and .nx commands.
480Sstevel@tonic-gate * Deroff follows .so and .nx commands, removes contents of macro
490Sstevel@tonic-gate * definitions, equations (both .EQ ... .EN and $...$),
500Sstevel@tonic-gate * Tbl command sequences, and Troff backslash constructions.
510Sstevel@tonic-gate *
520Sstevel@tonic-gate * All input is through the C macro; the most recently read character
530Sstevel@tonic-gate * is in c.
540Sstevel@tonic-gate */
550Sstevel@tonic-gate
560Sstevel@tonic-gate #define C ((c = getc(infile)) == EOF ? eof() : \
570Sstevel@tonic-gate ((c == ldelim) && (filesp == files) ? skeqn() : c))
580Sstevel@tonic-gate #define C1 ((c = getc(infile)) == EOF ? eof() : c)
590Sstevel@tonic-gate #define SKIP while (C != '\n')
600Sstevel@tonic-gate #define SKIP_TO_COM SKIP; SKIP; pc = c; \
610Sstevel@tonic-gate while ((C != '.') || (pc != '\n') || \
620Sstevel@tonic-gate (C > 'Z')) { \
630Sstevel@tonic-gate pc = c; \
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate #define YES 1
670Sstevel@tonic-gate #define NO 0
680Sstevel@tonic-gate #define MS 0
690Sstevel@tonic-gate #define MM 1
700Sstevel@tonic-gate #define ONE 1
710Sstevel@tonic-gate #define TWO 2
720Sstevel@tonic-gate
730Sstevel@tonic-gate #define NOCHAR -2
740Sstevel@tonic-gate #define SPECIAL 0
750Sstevel@tonic-gate #define APOS 1
760Sstevel@tonic-gate #define DIGIT 2
770Sstevel@tonic-gate #define LETTER 3
780Sstevel@tonic-gate
790Sstevel@tonic-gate #define MAXLINESZ 512
800Sstevel@tonic-gate
810Sstevel@tonic-gate static int wordflag = NO;
820Sstevel@tonic-gate static int msflag = NO;
830Sstevel@tonic-gate static int iflag = NO;
840Sstevel@tonic-gate static int mac = MM;
850Sstevel@tonic-gate static int disp = 0;
860Sstevel@tonic-gate static int inmacro = NO;
870Sstevel@tonic-gate static int intable = NO;
880Sstevel@tonic-gate static int lindx;
890Sstevel@tonic-gate static size_t linesize = MAXLINESZ;
900Sstevel@tonic-gate
910Sstevel@tonic-gate static char chars[128]; /* SPECIAL, APOS, DIGIT, or LETTER */
920Sstevel@tonic-gate
930Sstevel@tonic-gate static char *line = NULL;
940Sstevel@tonic-gate
950Sstevel@tonic-gate static char c;
960Sstevel@tonic-gate static int pc;
970Sstevel@tonic-gate static int ldelim = NOCHAR;
980Sstevel@tonic-gate static int rdelim = NOCHAR;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate static int argc;
1010Sstevel@tonic-gate static char **argv;
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate extern int optind;
1040Sstevel@tonic-gate extern char *optarg;
1050Sstevel@tonic-gate static char fname[50];
1060Sstevel@tonic-gate static FILE *files[15];
1070Sstevel@tonic-gate static FILE **filesp;
1080Sstevel@tonic-gate static FILE *infile;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static void backsl(void);
1110Sstevel@tonic-gate static void comline(void);
1120Sstevel@tonic-gate static char *copys(char *);
1130Sstevel@tonic-gate static int eof(void);
1140Sstevel@tonic-gate static void eqn(void);
1150Sstevel@tonic-gate static void fatal(const char *, ...);
1160Sstevel@tonic-gate static void fatal_msg(char *);
1170Sstevel@tonic-gate static void getfname(void);
1180Sstevel@tonic-gate static void macro(void);
1190Sstevel@tonic-gate static FILE *opn(char *);
1200Sstevel@tonic-gate static void putmac(char *, int);
1210Sstevel@tonic-gate static void putwords(int);
1220Sstevel@tonic-gate static void regline(int, int);
1230Sstevel@tonic-gate static void sce(void);
124*381Smuffin static int skeqn(void);
1250Sstevel@tonic-gate static void sdis(char, char);
1260Sstevel@tonic-gate static void stbl(void);
1270Sstevel@tonic-gate static void tbl(void);
1280Sstevel@tonic-gate static void usage(void);
129*381Smuffin static void work(void) __NORETURN;
1300Sstevel@tonic-gate
131*381Smuffin int
main(int ac,char ** av)1320Sstevel@tonic-gate main(int ac, char **av)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate int i;
1350Sstevel@tonic-gate int errflg = 0;
1360Sstevel@tonic-gate int optchar;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1390Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1400Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
1410Sstevel@tonic-gate #endif
1420Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
1430Sstevel@tonic-gate argc = ac;
1440Sstevel@tonic-gate argv = av;
1450Sstevel@tonic-gate while ((optchar = getopt(argc, argv, "wim:")) != EOF) {
1460Sstevel@tonic-gate switch (optchar) {
1470Sstevel@tonic-gate case 'w':
1480Sstevel@tonic-gate wordflag = YES;
1490Sstevel@tonic-gate break;
1500Sstevel@tonic-gate case 'm':
1510Sstevel@tonic-gate msflag = YES;
1520Sstevel@tonic-gate if (*optarg == 'm')
1530Sstevel@tonic-gate mac = MM;
1540Sstevel@tonic-gate else if (*optarg == 's')
1550Sstevel@tonic-gate mac = MS;
1560Sstevel@tonic-gate else if (*optarg == 'l')
1570Sstevel@tonic-gate disp = 1;
1580Sstevel@tonic-gate else
1590Sstevel@tonic-gate errflg++;
1600Sstevel@tonic-gate break;
1610Sstevel@tonic-gate case 'i':
1620Sstevel@tonic-gate iflag = YES;
1630Sstevel@tonic-gate break;
1640Sstevel@tonic-gate case '?':
1650Sstevel@tonic-gate errflg++;
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate }
168*381Smuffin if (errflg) {
1690Sstevel@tonic-gate usage();
170*381Smuffin return (1);
171*381Smuffin }
1720Sstevel@tonic-gate if (optind == argc)
1730Sstevel@tonic-gate infile = stdin;
1740Sstevel@tonic-gate else
1750Sstevel@tonic-gate infile = opn(argv[optind++]);
1760Sstevel@tonic-gate files[0] = infile;
1770Sstevel@tonic-gate filesp = &files[0];
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate for (i = 'a'; i <= 'z'; ++i)
1800Sstevel@tonic-gate chars[i] = LETTER;
1810Sstevel@tonic-gate for (i = 'A'; i <= 'Z'; ++i)
1820Sstevel@tonic-gate chars[i] = LETTER;
1830Sstevel@tonic-gate for (i = '0'; i <= '9'; ++i)
1840Sstevel@tonic-gate chars[i] = DIGIT;
1850Sstevel@tonic-gate chars['\''] = APOS;
1860Sstevel@tonic-gate chars['&'] = APOS;
1870Sstevel@tonic-gate work();
188*381Smuffin /* NOTREACHED */
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate static int
skeqn(void)193*381Smuffin skeqn(void)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate while ((c = getc(infile)) != rdelim) {
1960Sstevel@tonic-gate if (c == EOF) {
1970Sstevel@tonic-gate c = eof();
1980Sstevel@tonic-gate } else if (c == '"') {
1990Sstevel@tonic-gate while ((c = getc(infile)) != '"') {
2000Sstevel@tonic-gate if (c == EOF) {
2010Sstevel@tonic-gate c = eof();
2020Sstevel@tonic-gate } else if (c == '\\') {
2030Sstevel@tonic-gate if ((c = getc(infile)) == EOF) {
2040Sstevel@tonic-gate c = eof();
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate if (msflag) {
2110Sstevel@tonic-gate return (c = 'x');
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate return (c = ' ');
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate /* Functions calling opn() should ensure 'p' is non-null */
2180Sstevel@tonic-gate static FILE *
opn(char * p)2190Sstevel@tonic-gate opn(char *p)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate FILE *fd;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate assert(p != NULL);
2240Sstevel@tonic-gate if ((fd = fopen(p, "r")) == NULL)
2250Sstevel@tonic-gate fatal(gettext("Cannot open file %s: %s\n"), p, strerror(errno));
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate return (fd);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate static int
eof(void)2330Sstevel@tonic-gate eof(void)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate if (infile != stdin)
2360Sstevel@tonic-gate (void) fclose(infile);
2370Sstevel@tonic-gate if (filesp > files) {
2380Sstevel@tonic-gate infile = *--filesp;
2390Sstevel@tonic-gate } else if (optind < argc) {
2400Sstevel@tonic-gate infile = opn(argv[optind++]);
2410Sstevel@tonic-gate } else {
2420Sstevel@tonic-gate exit(0);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate return (C);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate static void
getfname(void)2510Sstevel@tonic-gate getfname(void)
2520Sstevel@tonic-gate {
2530Sstevel@tonic-gate char *p;
2540Sstevel@tonic-gate struct chain {
2550Sstevel@tonic-gate struct chain *nextp;
2560Sstevel@tonic-gate char *datap;
2570Sstevel@tonic-gate };
2580Sstevel@tonic-gate struct chain *q;
2590Sstevel@tonic-gate static struct chain *namechain = NULL;
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate while (C == ' ')
2620Sstevel@tonic-gate ;
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate for (p = fname; ((*p = c) != '\n') && (c != ' ') && (c != '\t') &&
2650Sstevel@tonic-gate (c != '\\'); ++p) {
2660Sstevel@tonic-gate (void) C;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate *p = '\0';
2690Sstevel@tonic-gate while (c != '\n') {
2700Sstevel@tonic-gate (void) C;
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate /* see if this name has already been used */
2740Sstevel@tonic-gate for (q = namechain; q; q = q->nextp)
2750Sstevel@tonic-gate if (strcmp(fname, q->datap) != 0) {
2760Sstevel@tonic-gate fname[0] = '\0';
2770Sstevel@tonic-gate return;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate q = (struct chain *)calloc(1, sizeof (*namechain));
2810Sstevel@tonic-gate q->nextp = namechain;
2820Sstevel@tonic-gate q->datap = copys(fname);
2830Sstevel@tonic-gate namechain = q;
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate /*
2880Sstevel@tonic-gate * Functions calling fatal() should ensure 'format' and
2890Sstevel@tonic-gate * arguments are non-null.
2900Sstevel@tonic-gate */
2910Sstevel@tonic-gate static void
fatal(const char * format,...)2920Sstevel@tonic-gate fatal(const char *format, ...)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate va_list alist;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate assert(format != NULL);
2970Sstevel@tonic-gate (void) fputs(gettext("deroff: "), stderr);
2980Sstevel@tonic-gate va_start(alist, format);
2990Sstevel@tonic-gate (void) vfprintf(stderr, format, alist);
3000Sstevel@tonic-gate exit(1);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate /* Functions calling fatal_msg() should ensure 's' is non-null */
3040Sstevel@tonic-gate static void
fatal_msg(char * s)3050Sstevel@tonic-gate fatal_msg(char *s)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate assert(s != NULL);
3080Sstevel@tonic-gate (void) fprintf(stderr, gettext("deroff: %s\n"), s);
3090Sstevel@tonic-gate exit(1);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate static void
usage(void)3130Sstevel@tonic-gate usage(void)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate (void) fputs(gettext(
3160Sstevel@tonic-gate "usage: deroff [ -w ] [ -m (m s l) ] [ -i ] "
3170Sstevel@tonic-gate "[ file ] ... \n"), stderr);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate static void
work(void)3210Sstevel@tonic-gate work(void)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate for (;;) {
3250Sstevel@tonic-gate if ((C == '.') || (c == '\''))
3260Sstevel@tonic-gate comline();
3270Sstevel@tonic-gate else
3280Sstevel@tonic-gate regline(NO, TWO);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate static void
regline(int macline,int cnst)3340Sstevel@tonic-gate regline(int macline, int cnst)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate if (line == NULL) {
3380Sstevel@tonic-gate if ((line = (char *)malloc(linesize * sizeof (char))) == NULL) {
3390Sstevel@tonic-gate fatal_msg(gettext("Cannot allocate memory"));
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate lindx = 0;
3440Sstevel@tonic-gate line[lindx] = c;
3450Sstevel@tonic-gate for (;;) {
3460Sstevel@tonic-gate if (c == '\\') {
3470Sstevel@tonic-gate line[lindx] = ' ';
3480Sstevel@tonic-gate backsl();
3490Sstevel@tonic-gate if (c == '%') { /* no blank for hyphenation char */
3500Sstevel@tonic-gate lindx--;
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate if (c == '\n') {
3540Sstevel@tonic-gate break;
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * We're just about to add another character to the line
3580Sstevel@tonic-gate * buffer so ensure we don't overrun it.
3590Sstevel@tonic-gate */
3600Sstevel@tonic-gate if (++lindx >= linesize - 1) {
3610Sstevel@tonic-gate linesize = linesize * 2;
3620Sstevel@tonic-gate if ((line = (char *)realloc(line,
3630Sstevel@tonic-gate linesize * sizeof (char))) == NULL) {
3640Sstevel@tonic-gate fatal_msg(gettext("Cannot allocate memory"));
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate if (intable && (c == 'T')) {
3680Sstevel@tonic-gate line[lindx] = C;
3690Sstevel@tonic-gate if ((c == '{') || (c == '}')) {
3700Sstevel@tonic-gate line[lindx - 1] = ' ';
3710Sstevel@tonic-gate line[lindx] = C;
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate } else {
3740Sstevel@tonic-gate line[lindx] = C;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate line[lindx] = '\0';
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if (line[0] != '\0') {
3810Sstevel@tonic-gate if (wordflag) {
3820Sstevel@tonic-gate putwords(macline);
3830Sstevel@tonic-gate } else if (macline) {
3840Sstevel@tonic-gate putmac(line, cnst);
3850Sstevel@tonic-gate } else {
3860Sstevel@tonic-gate (void) puts(line);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate static void
putmac(char * s,int cnst)3950Sstevel@tonic-gate putmac(char *s, int cnst)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate char *t;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate while (*s) {
4000Sstevel@tonic-gate while ((*s == ' ') || (*s == '\t')) {
4010Sstevel@tonic-gate (void) putchar(*s++);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate for (t = s; (*t != ' ') && (*t != '\t') && (*t != '\0'); ++t)
4040Sstevel@tonic-gate ;
4050Sstevel@tonic-gate if (*s == '\"')
4060Sstevel@tonic-gate s++;
4070Sstevel@tonic-gate if ((t > s + cnst) && (chars[s[0]] == LETTER) &&
4080Sstevel@tonic-gate (chars[s[1]] == LETTER)) {
4090Sstevel@tonic-gate while (s < t) {
4100Sstevel@tonic-gate if (*s == '\"')
4110Sstevel@tonic-gate s++;
4120Sstevel@tonic-gate else
4130Sstevel@tonic-gate (void) putchar(*s++);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate } else {
4160Sstevel@tonic-gate s = t;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate (void) putchar('\n');
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate static void
putwords(int macline)4250Sstevel@tonic-gate putwords(int macline) /* break into words for -w option */
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate char *p, *p1;
4280Sstevel@tonic-gate int i, nlet;
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate for (p1 = line; ; ) {
4310Sstevel@tonic-gate /* skip initial specials ampersands and apostrophes */
4320Sstevel@tonic-gate while (chars[*p1] < DIGIT) {
4330Sstevel@tonic-gate if (*p1++ == '\0')
4340Sstevel@tonic-gate return;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate nlet = 0;
4370Sstevel@tonic-gate for (p = p1; (i = chars[*p]) != SPECIAL; ++p) {
4380Sstevel@tonic-gate if (i == LETTER)
4390Sstevel@tonic-gate ++nlet;
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate if ((!macline && (nlet > 1)) /* MDM definition of word */ ||
4430Sstevel@tonic-gate (macline && (nlet > 2) && (chars[p1[0]] == LETTER) &&
4440Sstevel@tonic-gate (chars[p1[1]] == LETTER))) {
4450Sstevel@tonic-gate /* delete trailing ampersands and apostrophes */
4460Sstevel@tonic-gate while ((p[-1] == '\'') || (p[-1] == '&')) {
4470Sstevel@tonic-gate --p;
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate while (p1 < p) {
4500Sstevel@tonic-gate (void) putchar(*p1++);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate (void) putchar('\n');
4530Sstevel@tonic-gate } else {
4540Sstevel@tonic-gate p1 = p;
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate static void
comline(void)4620Sstevel@tonic-gate comline(void)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate int c1, c2;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate com:
4670Sstevel@tonic-gate while ((C == ' ') || (c == '\t'))
4680Sstevel@tonic-gate ;
4690Sstevel@tonic-gate comx:
4700Sstevel@tonic-gate if ((c1 = c) == '\n')
4710Sstevel@tonic-gate return;
4720Sstevel@tonic-gate c2 = C;
4730Sstevel@tonic-gate if ((c1 == '.') && (c2 != '.'))
4740Sstevel@tonic-gate inmacro = NO;
4750Sstevel@tonic-gate if (c2 == '\n')
4760Sstevel@tonic-gate return;
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate if ((c1 == 'E') && (c2 == 'Q') && (filesp == files)) {
4790Sstevel@tonic-gate eqn();
4800Sstevel@tonic-gate } else if ((c1 == 'T') && ((c2 == 'S') || (c2 == 'C') ||
4810Sstevel@tonic-gate (c2 == '&')) && (filesp == files)) {
4820Sstevel@tonic-gate if (msflag) {
4830Sstevel@tonic-gate stbl();
4840Sstevel@tonic-gate } else {
4850Sstevel@tonic-gate tbl();
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate } else if ((c1 == 'T') && (c2 == 'E')) {
4880Sstevel@tonic-gate intable = NO;
4890Sstevel@tonic-gate } else if (!inmacro && (c1 == 'd') && (c2 == 'e')) {
4900Sstevel@tonic-gate macro();
4910Sstevel@tonic-gate } else if (!inmacro && (c1 == 'i') && (c2 == 'g')) {
4920Sstevel@tonic-gate macro();
4930Sstevel@tonic-gate } else if (!inmacro && (c1 == 'a') && (c2 == 'm')) {
4940Sstevel@tonic-gate macro();
4950Sstevel@tonic-gate } else if ((c1 == 's') && (c2 == 'o')) {
4960Sstevel@tonic-gate if (iflag) {
4970Sstevel@tonic-gate SKIP;
4980Sstevel@tonic-gate } else {
4990Sstevel@tonic-gate getfname();
5000Sstevel@tonic-gate if (fname[0]) {
5010Sstevel@tonic-gate infile = *++filesp = opn(fname);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate } else if ((c1 == 'n') && (c2 == 'x')) {
5050Sstevel@tonic-gate if (iflag) {
5060Sstevel@tonic-gate SKIP;
5070Sstevel@tonic-gate } else {
5080Sstevel@tonic-gate getfname();
5090Sstevel@tonic-gate if (fname[0] == '\0') {
5100Sstevel@tonic-gate exit(0);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate if (infile != stdin) {
5130Sstevel@tonic-gate (void) fclose(infile);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate infile = *filesp = opn(fname);
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate } else if ((c1 == 'h') && (c2 == 'w')) {
5180Sstevel@tonic-gate SKIP;
5190Sstevel@tonic-gate } else if (msflag && (c1 == 'T') && (c2 == 'L')) {
5200Sstevel@tonic-gate SKIP_TO_COM;
5210Sstevel@tonic-gate goto comx;
5220Sstevel@tonic-gate } else if (msflag && (c1 == 'N') && (c2 == 'R')) {
5230Sstevel@tonic-gate SKIP;
5240Sstevel@tonic-gate } else if (msflag && (c1 == 'A') && ((c2 == 'U') || (c2 == 'I'))) {
5250Sstevel@tonic-gate if (mac == MM) {
5260Sstevel@tonic-gate SKIP;
5270Sstevel@tonic-gate } else {
5280Sstevel@tonic-gate SKIP_TO_COM;
5290Sstevel@tonic-gate goto comx;
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate } else if (msflag && (c1 == 'F') && (c2 == 'S')) {
5320Sstevel@tonic-gate SKIP_TO_COM;
5330Sstevel@tonic-gate goto comx;
5340Sstevel@tonic-gate } else if (msflag && (c1 == 'S') && (c2 == 'H')) {
5350Sstevel@tonic-gate SKIP_TO_COM;
5360Sstevel@tonic-gate goto comx;
5370Sstevel@tonic-gate } else if (msflag && (c1 == 'N') && (c2 == 'H')) {
5380Sstevel@tonic-gate SKIP_TO_COM;
5390Sstevel@tonic-gate goto comx;
5400Sstevel@tonic-gate } else if (msflag && (c1 == 'O') && (c2 == 'K')) {
5410Sstevel@tonic-gate SKIP_TO_COM;
5420Sstevel@tonic-gate goto comx;
5430Sstevel@tonic-gate } else if (msflag && (c1 == 'N') && (c2 == 'D')) {
5440Sstevel@tonic-gate SKIP;
5450Sstevel@tonic-gate } else if (msflag && (mac == MM) && (c1 == 'H') &&
5460Sstevel@tonic-gate ((c2 == ' ') || (c2 == 'U'))) {
5470Sstevel@tonic-gate SKIP;
5480Sstevel@tonic-gate } else if (msflag && (mac == MM) && (c2 == 'L')) {
5490Sstevel@tonic-gate if (disp || (c1 == 'R')) {
5500Sstevel@tonic-gate sdis('L', 'E');
5510Sstevel@tonic-gate } else {
5520Sstevel@tonic-gate SKIP;
5530Sstevel@tonic-gate (void) putchar('.');
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate } else if (msflag && ((c1 == 'D') || (c1 == 'N') ||
5560Sstevel@tonic-gate (c1 == 'K') || (c1 == 'P')) && (c2 == 'S')) {
5570Sstevel@tonic-gate sdis(c1, 'E'); /* removed RS-RE */
5580Sstevel@tonic-gate } else if (msflag && (c1 == 'K' && c2 == 'F')) {
5590Sstevel@tonic-gate sdis(c1, 'E');
5600Sstevel@tonic-gate } else if (msflag && (c1 == 'n') && (c2 == 'f')) {
5610Sstevel@tonic-gate sdis('f', 'i');
5620Sstevel@tonic-gate } else if (msflag && (c1 == 'c') && (c2 == 'e')) {
5630Sstevel@tonic-gate sce();
5640Sstevel@tonic-gate } else {
5650Sstevel@tonic-gate if ((c1 == '.') && (c2 == '.')) {
5660Sstevel@tonic-gate while (C == '.')
5670Sstevel@tonic-gate ;
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate ++inmacro;
5700Sstevel@tonic-gate if ((c1 <= 'Z') && msflag) {
5710Sstevel@tonic-gate regline(YES, ONE);
5720Sstevel@tonic-gate } else {
5730Sstevel@tonic-gate regline(YES, TWO);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate --inmacro;
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate static void
macro(void)5820Sstevel@tonic-gate macro(void)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate if (msflag) {
5850Sstevel@tonic-gate /* look for .. */
5860Sstevel@tonic-gate do {
5870Sstevel@tonic-gate SKIP;
5880Sstevel@tonic-gate } while ((C != '.') || (C != '.') || (C == '.'));
5890Sstevel@tonic-gate if (c != '\n') {
5900Sstevel@tonic-gate SKIP;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate return;
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate SKIP;
5950Sstevel@tonic-gate inmacro = YES;
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate static void
sdis(char a1,char a2)6020Sstevel@tonic-gate sdis(char a1, char a2)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate int c1, c2;
6050Sstevel@tonic-gate int eqnf;
6060Sstevel@tonic-gate int notdone = 1;
6070Sstevel@tonic-gate eqnf = 1;
6080Sstevel@tonic-gate SKIP;
6090Sstevel@tonic-gate while (notdone) {
6100Sstevel@tonic-gate while (C != '.')
6110Sstevel@tonic-gate SKIP;
6120Sstevel@tonic-gate if ((c1 = C) == '\n')
6130Sstevel@tonic-gate continue;
6140Sstevel@tonic-gate if ((c2 = C) == '\n')
6150Sstevel@tonic-gate continue;
6160Sstevel@tonic-gate if ((c1 == a1) && (c2 == a2)) {
6170Sstevel@tonic-gate SKIP;
6180Sstevel@tonic-gate if (eqnf)
6190Sstevel@tonic-gate (void) putchar('.');
6200Sstevel@tonic-gate (void) putchar('\n');
6210Sstevel@tonic-gate return;
6220Sstevel@tonic-gate } else if ((a1 == 'D') && (c1 == 'E') && (c2 == 'Q')) {
6230Sstevel@tonic-gate eqn();
6240Sstevel@tonic-gate eqnf = 0;
6250Sstevel@tonic-gate } else {
6260Sstevel@tonic-gate SKIP;
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate static void
tbl(void)6320Sstevel@tonic-gate tbl(void)
6330Sstevel@tonic-gate {
6340Sstevel@tonic-gate while (C != '.')
6350Sstevel@tonic-gate ;
6360Sstevel@tonic-gate SKIP;
6370Sstevel@tonic-gate intable = YES;
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate static void
stbl(void)6410Sstevel@tonic-gate stbl(void)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate while (C != '.')
6440Sstevel@tonic-gate ;
6450Sstevel@tonic-gate SKIP_TO_COM;
6460Sstevel@tonic-gate if ((c != 'T') || (C != 'E')) {
6470Sstevel@tonic-gate SKIP;
6480Sstevel@tonic-gate pc = c;
6490Sstevel@tonic-gate while ((C != '.') || (pc != '\n') ||
6500Sstevel@tonic-gate (C != 'T') || (C != 'E')) {
6510Sstevel@tonic-gate pc = c;
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate static void
eqn(void)6570Sstevel@tonic-gate eqn(void)
6580Sstevel@tonic-gate {
6590Sstevel@tonic-gate int c1, c2;
6600Sstevel@tonic-gate int dflg;
6610Sstevel@tonic-gate int last;
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate last = 0;
6640Sstevel@tonic-gate dflg = 1;
6650Sstevel@tonic-gate SKIP;
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate for (;;) {
6680Sstevel@tonic-gate if ((C1 == '.') || (c == '\'')) {
6690Sstevel@tonic-gate while ((C1 == ' ') || (c == '\t'))
6700Sstevel@tonic-gate ;
6710Sstevel@tonic-gate if ((c == 'E') && (C1 == 'N')) {
6720Sstevel@tonic-gate SKIP;
6730Sstevel@tonic-gate if (msflag && dflg) {
6740Sstevel@tonic-gate (void) putchar('x');
6750Sstevel@tonic-gate (void) putchar(' ');
6760Sstevel@tonic-gate if (last) {
6770Sstevel@tonic-gate (void) putchar('.');
6780Sstevel@tonic-gate (void) putchar(' ');
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate return;
6820Sstevel@tonic-gate }
6830Sstevel@tonic-gate } else if (c == 'd') { /* look for delim */
6840Sstevel@tonic-gate if ((C1 == 'e') && (C1 == 'l')) {
6850Sstevel@tonic-gate if ((C1 == 'i') && (C1 == 'm')) {
6860Sstevel@tonic-gate while (C1 == ' ')
6870Sstevel@tonic-gate ;
6880Sstevel@tonic-gate if (((c1 = c) == '\n') ||
6890Sstevel@tonic-gate ((c2 = C1) == '\n') ||
6900Sstevel@tonic-gate ((c1 == 'o') && (c2 == 'f') &&
6910Sstevel@tonic-gate (C1 == 'f'))) {
6920Sstevel@tonic-gate ldelim = NOCHAR;
6930Sstevel@tonic-gate rdelim = NOCHAR;
6940Sstevel@tonic-gate } else {
6950Sstevel@tonic-gate ldelim = c1;
6960Sstevel@tonic-gate rdelim = c2;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate dflg = 0;
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate if (c != '\n') {
7040Sstevel@tonic-gate while (C1 != '\n') {
7050Sstevel@tonic-gate if (c == '.') {
7060Sstevel@tonic-gate last = 1;
7070Sstevel@tonic-gate } else {
7080Sstevel@tonic-gate last = 0;
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate static void
backsl(void)7180Sstevel@tonic-gate backsl(void) /* skip over a complete backslash construction */
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate int bdelim;
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate sw: switch (C) {
7230Sstevel@tonic-gate case '"':
7240Sstevel@tonic-gate SKIP;
7250Sstevel@tonic-gate return;
7260Sstevel@tonic-gate case 's':
7270Sstevel@tonic-gate if (C == '\\') {
7280Sstevel@tonic-gate backsl();
7290Sstevel@tonic-gate } else {
7300Sstevel@tonic-gate while ((C >= '0') && (c <= '9'))
7310Sstevel@tonic-gate ;
7320Sstevel@tonic-gate (void) ungetc(c, infile);
7330Sstevel@tonic-gate c = '0';
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate lindx--;
7360Sstevel@tonic-gate return;
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate case 'f':
7390Sstevel@tonic-gate case 'n':
7400Sstevel@tonic-gate case '*':
7410Sstevel@tonic-gate if (C != '(')
7420Sstevel@tonic-gate return;
7430Sstevel@tonic-gate /* FALLTHROUGH */
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate case '(':
7460Sstevel@tonic-gate if (C != '\n') {
7470Sstevel@tonic-gate (void) C;
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate return;
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate case '$':
7520Sstevel@tonic-gate (void) C; /* discard argument number */
7530Sstevel@tonic-gate return;
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate case 'b':
7560Sstevel@tonic-gate case 'x':
7570Sstevel@tonic-gate case 'v':
7580Sstevel@tonic-gate case 'h':
7590Sstevel@tonic-gate case 'w':
7600Sstevel@tonic-gate case 'o':
7610Sstevel@tonic-gate case 'l':
7620Sstevel@tonic-gate case 'L':
7630Sstevel@tonic-gate if ((bdelim = C) == '\n')
7640Sstevel@tonic-gate return;
7650Sstevel@tonic-gate while ((C != '\n') && (c != bdelim))
7660Sstevel@tonic-gate if (c == '\\')
7670Sstevel@tonic-gate backsl();
7680Sstevel@tonic-gate return;
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate case '\\':
7710Sstevel@tonic-gate if (inmacro)
7720Sstevel@tonic-gate goto sw;
7730Sstevel@tonic-gate default:
7740Sstevel@tonic-gate return;
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate static char *
copys(char * s)7820Sstevel@tonic-gate copys(char *s)
7830Sstevel@tonic-gate {
7840Sstevel@tonic-gate char *t, *t0;
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate if ((t0 = t = calloc((unsigned)(strlen(s) + 1), sizeof (*t))) == NULL)
7870Sstevel@tonic-gate fatal_msg(gettext("Cannot allocate memory"));
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate while (*t++ = *s++)
7900Sstevel@tonic-gate ;
7910Sstevel@tonic-gate return (t0);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate static void
sce(void)7950Sstevel@tonic-gate sce(void)
7960Sstevel@tonic-gate {
7970Sstevel@tonic-gate char *ap;
7980Sstevel@tonic-gate int n, i;
7990Sstevel@tonic-gate char a[10];
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate for (ap = a; C != '\n'; ap++) {
8020Sstevel@tonic-gate *ap = c;
8030Sstevel@tonic-gate if (ap == &a[9]) {
8040Sstevel@tonic-gate SKIP;
8050Sstevel@tonic-gate ap = a;
8060Sstevel@tonic-gate break;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate if (ap != a) {
8100Sstevel@tonic-gate n = atoi(a);
8110Sstevel@tonic-gate } else {
8120Sstevel@tonic-gate n = 1;
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate for (i = 0; i < n; ) {
8150Sstevel@tonic-gate if (C == '.') {
8160Sstevel@tonic-gate if (C == 'c') {
8170Sstevel@tonic-gate if (C == 'e') {
8180Sstevel@tonic-gate while (C == ' ')
8190Sstevel@tonic-gate ;
8200Sstevel@tonic-gate if (c == '0') {
8210Sstevel@tonic-gate break;
8220Sstevel@tonic-gate } else {
8230Sstevel@tonic-gate SKIP;
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate } else {
8260Sstevel@tonic-gate SKIP;
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate } else {
8290Sstevel@tonic-gate SKIP;
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate } else {
8320Sstevel@tonic-gate SKIP;
8330Sstevel@tonic-gate i++;
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate }
837