📄 deroff.c
字号:
#ifndef lintstatic char *sccsid = "@(#)deroff.c 4.1 ULTRIX 7/17/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * 001 David L Ballenger, 14-Mar-1986 * Change use of "const" as an identifier, since it is now a keyword. * * Based on: deroff.c 4.4 (Berkeley) 83/04/29 * ************************************************************************/#include <stdio.h>/* * Deroff command -- strip troff, eqn, and Tbl sequences from * a file. Has two flags argument, -w, to cause output one word per line * rather than in the original format. * -mm (or -ms) causes the corresponding macro's to be interpreted * so that just sentences are output * -ml also gets rid of lists. * Deroff follows .so and .nx commands, removes contents of macro * definitions, equations (both .EQ ... .EN and $...$), * Tbl command sequences, and Troff backslash constructions. * * All input is through the Cget macro; * the most recently read character is in c. * * Modified by Robert Henry to process -me and -man macros. */#define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )#define C1get ( (c=getc(infile)) == EOF ? eof() : c)#ifdef DEBUG# define C _C()# define C1 _C1()#else not DEBUG# define C Cget# define C1 C1get#endif not DEBUG#define SKIP while(C != '\n') #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c#define YES 1#define NO 0#define MS 0 /* -ms */#define MM 1 /* -mm */#define ME 2 /* -me */#define MA 3 /* -man */#ifdef DEBUGchar *mactab[] = {"-ms", "-mm", "-me", "-ma"};#endif DEBUG#define ONE 1#define TWO 2#define NOCHAR -2#define SPECIAL 0#define APOS 1#define PUNCT 2#define DIGIT 3#define LETTER 4int wordflag;int msflag; /* processing a source written using a mac package */int mac; /* which package */int disp;int parag;int inmacro;int intable;int keepblock; /* keep blocks of text; normally false when msflag */char chars[128]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */char line[512];char *lp;int c;int pc;int ldelim;int rdelim;int argc;char **argv;char fname[50];FILE *files[15];FILE **filesp;FILE *infile;FILE *opn();/* * Flags for matching conditions other than * the macro name */#define NONE 0#define FNEST 1 /* no nested files */#define NOMAC 2 /* no macro */#define MAC 3 /* macro */#define PARAG 4 /* in a paragraph */#define MSF 5 /* msflag is on */#define NBLK 6 /* set if no blocks to be kept *//* * Return codes from macro minions, determine where to jump, * how to repeat/reprocess text */#define COMX 1 /* goto comx */#define COM 2 /* goto com */main(ac, av)int ac;char **av;{ register int i; int errflg = 0; register optchar; FILE *opn(); int kflag = NO; char *p; wordflag = NO; msflag = NO; mac = ME; disp = NO; parag = NO; inmacro = NO; intable = NO; ldelim = NOCHAR; rdelim = NOCHAR; keepblock = YES; for(argc = ac - 1, argv = av + 1; ( (argc > 0) && (argv[0][0] == '-') && (argv[0][1] != '\0') ); --argc, ++argv ){ for(p = argv[0]+1; *p; ++p) { switch(*p) { case 'p': parag=YES; break; case 'k': kflag = YES; break; case 'w': wordflag = YES; kflag = YES; break; case 'm': msflag = YES; keepblock = NO; switch(p[1]){ case 'm': mac = MM; p++; break; case 's': mac = MS; p++; break; case 'e': mac = ME; p++; break; case 'a': mac = MA; p++; break; case 'l': disp = YES; p++; break; default: errflg++; break; } break; default: errflg++; } } } if (kflag) keepblock = YES; if (errflg) fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n", (char *) NULL);#ifdef DEBUG printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n", msflag, mactab[mac], keepblock, disp);#endif DEBUG if (argc == 0){ infile = stdin; } else { infile = opn(argv[0]); --argc; ++argv; } files[0] = infile; filesp = &files[0]; for(i='a'; i<='z' ; ++i) chars[i] = LETTER; for(i='A'; i<='Z'; ++i) chars[i] = LETTER; for(i='0'; i<='9'; ++i) chars[i] = DIGIT; chars['\''] = APOS; chars['&'] = APOS; chars['.'] = PUNCT; chars[','] = PUNCT; chars[';'] = PUNCT; chars['?'] = PUNCT; chars[':'] = PUNCT; work();}char *calloc();skeqn(){ while((c = getc(infile)) != rdelim) if(c == EOF) c = eof(); else if(c == '"') while( (c = getc(infile)) != '"') if(c == EOF) c = eof(); else if(c == '\\') if((c = getc(infile)) == EOF) c = eof(); if(msflag)return(c='x'); return(c = ' ');}FILE *opn(p)register char *p;{ FILE *fd; if( (fd = fopen(p, "r")) == NULL) { fprintf(stderr, "Deroff: "); perror(p); exit(1); } return(fd);}eof(){ if(infile != stdin) fclose(infile); if(filesp > files) infile = *--filesp; else if (argc > 0) { infile = opn(argv[0]); --argc; ++argv; } else exit(0); return(C);}getfname(){ register char *p; struct chain { struct chain *nextp; char *datap; } *chainblock; register struct chain *q; static struct chain *namechain = NULL; char *copys(); while(C == ' ') ; for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p) C; *p = '\0'; while(c != '\n') C; /* see if this name has already been used */ for(q = namechain ; q; q = q->nextp) if( ! strcmp(fname, q->datap)) { fname[0] = '\0'; return; } q = (struct chain *) calloc(1, sizeof(*chainblock)); q->nextp = namechain; q->datap = copys(fname); namechain = q;}fatal(s,p)char *s, *p;{ fprintf(stderr, "Deroff: "); fprintf(stderr, s, p); exit(1);}/*ARGSUSED*/textline(str, const_val) char *str; int const_val;{ if (wordflag) { msputwords(0); return; } puts(str);}work(){ for( ;; ) { C;#ifdef FULLDEBUG printf("Starting work with `%c'\n", c);#endif FULLDEBUG if(c == '.' || c == '\'') comline(); else regline(textline, TWO); }}regline(pfunc, const_val) int (*pfunc)(); int const_val;{ line[0] = c; lp = line; for( ; ; ) { if(c == '\\') { *lp = ' '; backsl(); } if(c == '\n') break; if(intable && c=='T') { *++lp = C; if(c=='{' || c=='}') { lp[-1] = ' '; *lp = C; } } else { *++lp = C; } } *lp = '\0'; if(line[0] != '\0') (*pfunc)(line, const_val);}macro(){ if(msflag){ do { SKIP; } while(C!='.' || C!='.' || C=='.'); /* look for .. */ if(c != '\n')SKIP; return; } SKIP; inmacro = YES;}tbl(){ while(C != '.'); SKIP; intable = YES;}stbl(){ while(C != '.'); SKIP_TO_COM; if(c != 'T' || C != 'E'){ SKIP; pc=c; while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c; }}eqn(){ register int c1, c2; register int dflg; char last; last=0; dflg = 1; SKIP; for( ;;) { if(C1 == '.' || c == '\'') { while(C1==' ' || c=='\t') ; if(c=='E' && C1=='N') { SKIP; if(msflag && dflg){ putchar('x'); putchar(' '); if(last){ putchar(last); putchar('\n'); } } return; } } else if(c == 'd') /* look for delim */ { if(C1=='e' && C1=='l') if( C1=='i' && C1=='m') { while(C1 == ' '); if((c1=c)=='\n' || (c2=C1)=='\n' || (c1=='o' && c2=='f' && C1=='f') ) { ldelim = NOCHAR; rdelim = NOCHAR; } else { ldelim = c1; rdelim = c2; } } dflg = 0; } if(c != '\n') while(C1 != '\n'){ if(chars[c] == PUNCT)last = c; else if(c != ' ')last = 0; } }}backsl() /* skip over a complete backslash construction */{ int bdelim;sw: switch(C) { case '"': SKIP; return; case 's': if(C == '\\') backsl(); else { while(C>='0' && c<='9') ; ungetc(c,infile); c = '0'; } --lp; return; case 'f': case 'n': case '*': if(C != '(') return; case '(': if(msflag){ if(C == 'e'){ if(C == 'm'){ *lp = '-'; return; } } else if(c != '\n')C; return; } if(C != '\n') C; return; case '$': C; /* discard argument number */ return; case 'b': case 'x': case 'v': case 'h': case 'w': case 'o': case 'l': case 'L': if( (bdelim=C) == '\n') return; while(C!='\n' && c!=bdelim) if(c == '\\') backsl(); return; case '\\': if(inmacro) goto sw; default: return; }}char *copys(s)register char *s;{ register char *t, *t0; if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL) fatal("Cannot allocate memory", (char *) NULL); while( *t++ = *s++ ) ; return(t0);}sce(){ register char *ap; register int n, i; char a[10]; for(ap=a;C != '\n';ap++){ *ap = c; if(ap == &a[9]){ SKIP; ap=a; break; } } if(ap != a)n = atoi(a); else n = 1; for(i=0;i<n;){ if(C == '.'){ if(C == 'c'){ if(C == 'e'){ while(C == ' '); if(c == '0'){ SKIP; break; } else SKIP; } else SKIP; } else if(c == 'P' || C == 'P'){ if(c != '\n')SKIP; break; } else if(c != '\n')SKIP; } else { SKIP; i++; } }}refer(c1){ register int c2; if(c1 != '\n') SKIP; while(1){ if(C != '.') SKIP; else { if(C != ']') SKIP; else { while(C != '\n') c2=c; if(chars[c2] == PUNCT)putchar(c2); return; } } }}inpic(){ register int c1; register char *p1; SKIP; p1 = line; c = '\n'; while(1){ c1 = c; if(C == '.' && c1 == '\n'){ if(C != 'P'){ if(c == '\n')continue; else { SKIP; c='\n'; continue;} } if(C != 'E'){ if(c == '\n')continue; else { SKIP; c='\n';continue; } } SKIP; return; } else if(c == '\"'){ while(C != '\"'){ if(c == '\\'){ if(C == '\"')continue; ungetc(c,infile); backsl(); } else *p1++ = c; } *p1++ = ' '; } else if(c == '\n' && p1 != line){ *p1 = '\0'; if(wordflag)msputwords(NO); else { puts(line); putchar('\n'); } p1 = line; } }}#ifdef DEBUG_C1(){ return(C1get);}_C(){ return(Cget);}#endif DEBUG/* * Macro processing * * Macro table definitions */#define reg registertypedef int pacmac; /* compressed macro name */int argconcat = 0; /* concat arguments together (-me only) */#define tomac(c1, c2) ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))#define frommac(src, c1, c2) (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))struct mactab{ int condition; pacmac macname; int (*func)();};extern struct mactab troffmactab[];extern struct mactab ppmactab[];extern struct mactab msmactab[];extern struct mactab mmmactab[];extern struct mactab memactab[];extern struct mactab manmactab[];/* * macro table initialization */#define M(cond, c1, c2, func) {cond, tomac(c1, c2), func}/* * Put out a macro line, using ms and mm conventions. */msputmac(s, const_val) register char *s; int const_val;{ register char *t; register found; int last; found = 0; if (wordflag) { msputwords(YES); return; } while(*s) { while(*s==' ' || *s=='\t') putchar(*s++); for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t) ; if(*s == '\"')s++; if(t>s+const_val && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){ while(s < t) if(*s == '\"')s++; else putchar(*s++); last = *(t-1); found++; } else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0') putchar(*s++); else{ last = *(t-1); s = t; } } putchar('\n'); if(msflag && chars[last] == PUNCT){ putchar(last); putchar('\n'); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -