|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)deroff.c 4.7 (Berkeley) 88/04/24";
3: #endif not lint
4:
5: #include <stdio.h>
6:
7: /*
8: * Deroff command -- strip troff, eqn, and Tbl sequences from
9: * a file. Has two flags argument, -w, to cause output one word per line
10: * rather than in the original format.
11: * -mm (or -ms) causes the corresponding macro's to be interpreted
12: * so that just sentences are output
13: * -ml also gets rid of lists.
14: * Deroff follows .so and .nx commands, removes contents of macro
15: * definitions, equations (both .EQ ... .EN and $...$),
16: * Tbl command sequences, and Troff backslash constructions.
17: *
18: * All input is through the Cget macro;
19: * the most recently read character is in c.
20: *
21: * Modified by Robert Henry to process -me and -man macros.
22: */
23:
24: #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
25: #define C1get ( (c=getc(infile)) == EOF ? eof() : c)
26:
27: #ifdef DEBUG
28: # define C _C()
29: # define C1 _C1()
30: #else not DEBUG
31: # define C Cget
32: # define C1 C1get
33: #endif not DEBUG
34:
35: #define SKIP while(C != '\n')
36: #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
37:
38: #define YES 1
39: #define NO 0
40: #define MS 0 /* -ms */
41: #define MM 1 /* -mm */
42: #define ME 2 /* -me */
43: #define MA 3 /* -man */
44:
45: #ifdef DEBUG
46: char *mactab[] = {"-ms", "-mm", "-me", "-ma"};
47: #endif DEBUG
48:
49: #define ONE 1
50: #define TWO 2
51:
52: #define NOCHAR -2
53: #define SPECIAL 0
54: #define APOS 1
55: #define PUNCT 2
56: #define DIGIT 3
57: #define LETTER 4
58:
59: int wordflag;
60: int msflag; /* processing a source written using a mac package */
61: int mac; /* which package */
62: int disp;
63: int parag;
64: int inmacro;
65: int intable;
66: int keepblock; /* keep blocks of text; normally false when msflag */
67:
68: char chars[128]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
69:
70: char line[512];
71: char *lp;
72:
73: int c;
74: int pc;
75: int ldelim;
76: int rdelim;
77:
78:
79: int argc;
80: char **argv;
81:
82: char fname[50];
83: FILE *files[15];
84: FILE **filesp;
85: FILE *infile;
86: FILE *opn();
87: /*
88: * Flags for matching conditions other than
89: * the macro name
90: */
91: #define NONE 0
92: #define FNEST 1 /* no nested files */
93: #define NOMAC 2 /* no macro */
94: #define MAC 3 /* macro */
95: #define PARAG 4 /* in a paragraph */
96: #define MSF 5 /* msflag is on */
97: #define NBLK 6 /* set if no blocks to be kept */
98:
99: /*
100: * Return codes from macro minions, determine where to jump,
101: * how to repeat/reprocess text
102: */
103: #define COMX 1 /* goto comx */
104: #define COM 2 /* goto com */
105:
106: main(ac, av)
107: int ac;
108: char **av;
109: {
110: register int i;
111: int errflg = 0;
112: register optchar;
113: FILE *opn();
114: int kflag = NO;
115: char *p;
116:
117: wordflag = NO;
118: msflag = NO;
119: mac = ME;
120: disp = NO;
121: parag = NO;
122: inmacro = NO;
123: intable = NO;
124: ldelim = NOCHAR;
125: rdelim = NOCHAR;
126: keepblock = YES;
127:
128: for(argc = ac - 1, argv = av + 1;
129: ( (argc > 0)
130: && (argv[0][0] == '-')
131: && (argv[0][1] != '\0') );
132: --argc, ++argv
133: ){
134: for(p = argv[0]+1; *p; ++p) {
135: switch(*p) {
136: case 'p':
137: parag=YES;
138: break;
139: case 'k':
140: kflag = YES;
141: break;
142: case 'w':
143: wordflag = YES;
144: kflag = YES;
145: break;
146: case 'm':
147: msflag = YES;
148: keepblock = NO;
149: switch(p[1]){
150: case 'm': mac = MM; p++; break;
151: case 's': mac = MS; p++; break;
152: case 'e': mac = ME; p++; break;
153: case 'a': mac = MA; p++; break;
154: case 'l': disp = YES; p++; break;
155: default: errflg++; break;
156: }
157: break;
158: default:
159: errflg++;
160: }
161: }
162: }
163:
164: if (kflag)
165: keepblock = YES;
166: if (errflg)
167: fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n",
168: (char *) NULL);
169:
170: #ifdef DEBUG
171: printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
172: msflag, mactab[mac], keepblock, disp);
173: #endif DEBUG
174: if (argc == 0){
175: infile = stdin;
176: } else {
177: infile = opn(argv[0]);
178: --argc;
179: ++argv;
180: }
181:
182:
183: files[0] = infile;
184: filesp = &files[0];
185:
186: for(i='a'; i<='z' ; ++i)
187: chars[i] = LETTER;
188: for(i='A'; i<='Z'; ++i)
189: chars[i] = LETTER;
190: for(i='0'; i<='9'; ++i)
191: chars[i] = DIGIT;
192: chars['\''] = APOS;
193: chars['&'] = APOS;
194: chars['.'] = PUNCT;
195: chars[','] = PUNCT;
196: chars[';'] = PUNCT;
197: chars['?'] = PUNCT;
198: chars[':'] = PUNCT;
199: work();
200: }
201: char *calloc();
202:
203: skeqn()
204: {
205: while((c = getc(infile)) != rdelim)
206: if(c == EOF)
207: c = eof();
208: else if(c == '"')
209: while( (c = getc(infile)) != '"')
210: if(c == EOF)
211: c = eof();
212: else if(c == '\\')
213: if((c = getc(infile)) == EOF)
214: c = eof();
215: if(msflag)return(c='x');
216: return(c = ' ');
217: }
218:
219: FILE *opn(p)
220: register char *p;
221: {
222: FILE *fd;
223:
224: if( (fd = fopen(p, "r")) == NULL) {
225: fprintf(stderr, "Deroff: ");
226: perror(p);
227: exit(1);
228: }
229:
230: return(fd);
231: }
232:
233: eof()
234: {
235: if(infile != stdin)
236: fclose(infile);
237: if(filesp > files)
238: infile = *--filesp;
239: else if (argc > 0) {
240: infile = opn(argv[0]);
241: --argc;
242: ++argv;
243: } else
244: exit(0);
245: return(C);
246: }
247:
248: getfname()
249: {
250: register char *p;
251: struct chain {
252: struct chain *nextp;
253: char *datap;
254: } *chainblock;
255: register struct chain *q;
256: static struct chain *namechain = NULL;
257: char *copys();
258:
259: while(C == ' ') ;
260:
261: for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
262: C;
263: *p = '\0';
264: while(c != '\n')
265: C;
266:
267: /* see if this name has already been used */
268:
269: for(q = namechain ; q; q = q->nextp)
270: if( ! strcmp(fname, q->datap))
271: {
272: fname[0] = '\0';
273: return;
274: }
275:
276: q = (struct chain *) calloc(1, sizeof(*chainblock));
277: q->nextp = namechain;
278: q->datap = copys(fname);
279: namechain = q;
280: }
281:
282: fatal(s,p)
283: char *s, *p;
284: {
285: fprintf(stderr, "Deroff: ");
286: fprintf(stderr, s, p);
287: exit(1);
288: }
289:
290: /*ARGSUSED*/
291: textline(str, constant)
292: char *str;
293: int constant;
294: {
295: if (wordflag) {
296: msputwords(0);
297: return;
298: }
299: puts(str);
300: }
301:
302: work()
303: {
304: for( ;; )
305: {
306: C;
307: #ifdef FULLDEBUG
308: printf("Starting work with `%c'\n", c);
309: #endif FULLDEBUG
310: if(c == '.' || c == '\'')
311: comline();
312: else
313: regline(textline, TWO);
314: }
315: }
316:
317: regline(pfunc, constant)
318: int (*pfunc)();
319: int constant;
320: {
321: line[0] = c;
322: lp = line;
323: for( ; ; )
324: {
325: if(c == '\\') {
326: *lp = ' ';
327: backsl();
328: }
329: if(c == '\n')
330: break;
331: if(intable && c=='T') {
332: *++lp = C;
333: if(c=='{' || c=='}') {
334: lp[-1] = ' ';
335: *lp = C;
336: }
337: } else {
338: *++lp = C;
339: }
340: }
341:
342: *lp = '\0';
343:
344: if(line[0] != '\0')
345: (*pfunc)(line, constant);
346: }
347:
348: macro()
349: {
350: if(msflag){
351: do {
352: SKIP;
353: } while(C!='.' || C!='.' || C=='.'); /* look for .. */
354: if(c != '\n')SKIP;
355: return;
356: }
357: SKIP;
358: inmacro = YES;
359: }
360:
361: tbl()
362: {
363: while(C != '.');
364: SKIP;
365: intable = YES;
366: }
367: stbl()
368: {
369: while(C != '.');
370: SKIP_TO_COM;
371: if(c != 'T' || C != 'E'){
372: SKIP;
373: pc=c;
374: while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
375: }
376: }
377:
378: eqn()
379: {
380: register int c1, c2;
381: register int dflg;
382: char last;
383:
384: last=0;
385: dflg = 1;
386: SKIP;
387:
388: for( ;;)
389: {
390: if(C1 == '.' || c == '\'')
391: {
392: while(C1==' ' || c=='\t')
393: ;
394: if(c=='E' && C1=='N')
395: {
396: SKIP;
397: if(msflag && dflg){
398: putchar('x');
399: putchar(' ');
400: if(last){
401: putchar(last);
402: putchar('\n');
403: }
404: }
405: return;
406: }
407: }
408: else if(c == 'd') /* look for delim */
409: {
410: if(C1=='e' && C1=='l')
411: if( C1=='i' && C1=='m')
412: {
413: while(C1 == ' ');
414: if((c1=c)=='\n' || (c2=C1)=='\n'
415: || (c1=='o' && c2=='f' && C1=='f') )
416: {
417: ldelim = NOCHAR;
418: rdelim = NOCHAR;
419: }
420: else {
421: ldelim = c1;
422: rdelim = c2;
423: }
424: }
425: dflg = 0;
426: }
427:
428: if(c != '\n') while(C1 != '\n'){
429: if(chars[c] == PUNCT)last = c;
430: else if(c != ' ')last = 0;
431: }
432: }
433: }
434:
435: backsl() /* skip over a complete backslash construction */
436: {
437: int bdelim;
438:
439: sw:
440: switch(C)
441: {
442: case '"':
443: SKIP;
444: return;
445: case 's':
446: if(C == '\\') backsl();
447: else {
448: while(C>='0' && c<='9') ;
449: ungetc(c,infile);
450: c = '0';
451: }
452: --lp;
453: return;
454:
455: case 'f':
456: case 'n':
457: case '*':
458: if(C != '(')
459: return;
460:
461: case '(':
462: if(msflag){
463: if(C == 'e'){
464: if(C == 'm'){
465: *lp = '-';
466: return;
467: }
468: }
469: else if(c != '\n')C;
470: return;
471: }
472: if(C != '\n') C;
473: return;
474:
475: case '$':
476: C; /* discard argument number */
477: return;
478:
479: case 'b':
480: case 'x':
481: case 'v':
482: case 'h':
483: case 'w':
484: case 'o':
485: case 'l':
486: case 'L':
487: if( (bdelim=C) == '\n')
488: return;
489: while(C!='\n' && c!=bdelim)
490: if(c == '\\') backsl();
491: return;
492:
493: case '\\':
494: if(inmacro)
495: goto sw;
496: default:
497: return;
498: }
499: }
500:
501: char *copys(s)
502: register char *s;
503: {
504: register char *t, *t0;
505:
506: if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL)
507: fatal("Cannot allocate memory", (char *) NULL);
508:
509: while( *t++ = *s++ )
510: ;
511: return(t0);
512: }
513:
514: sce()
515: {
516: register char *ap;
517: register int n, i;
518: char a[10];
519: for(ap=a;C != '\n';ap++){
520: *ap = c;
521: if(ap == &a[9]){
522: SKIP;
523: ap=a;
524: break;
525: }
526: }
527: if(ap != a)n = atoi(a);
528: else n = 1;
529: for(i=0;i<n;){
530: if(C == '.'){
531: if(C == 'c'){
532: if(C == 'e'){
533: while(C == ' ');
534: if(c == '0'){
535: SKIP;
536: break;
537: }
538: else SKIP;
539: }
540: else SKIP;
541: }
542: else if(c == 'P' || C == 'P'){
543: if(c != '\n')SKIP;
544: break;
545: }
546: else if(c != '\n')SKIP;
547: }
548: else {
549: SKIP;
550: i++;
551: }
552: }
553: }
554:
555: refer(c1)
556: {
557: register int c2;
558: if(c1 != '\n')
559: SKIP;
560: while(1){
561: if(C != '.')
562: SKIP;
563: else {
564: if(C != ']')
565: SKIP;
566: else {
567: while(C != '\n')
568: c2=c;
569: if(chars[c2] == PUNCT)putchar(c2);
570: return;
571: }
572: }
573: }
574: }
575:
576: inpic()
577: {
578: register int c1;
579: register char *p1;
580: SKIP;
581: p1 = line;
582: c = '\n';
583: while(1){
584: c1 = c;
585: if(C == '.' && c1 == '\n'){
586: if(C != 'P'){
587: if(c == '\n')continue;
588: else { SKIP; c='\n'; continue;}
589: }
590: if(C != 'E'){
591: if(c == '\n')continue;
592: else { SKIP; c='\n';continue; }
593: }
594: SKIP;
595: return;
596: }
597: else if(c == '\"'){
598: while(C != '\"'){
599: if(c == '\\'){
600: if(C == '\"')continue;
601: ungetc(c,infile);
602: backsl();
603: }
604: else *p1++ = c;
605: }
606: *p1++ = ' ';
607: }
608: else if(c == '\n' && p1 != line){
609: *p1 = '\0';
610: if(wordflag)msputwords(NO);
611: else {
612: puts(line);
613: putchar('\n');
614: }
615: p1 = line;
616: }
617: }
618: }
619:
620: #ifdef DEBUG
621: _C1()
622: {
623: return(C1get);
624: }
625: _C()
626: {
627: return(Cget);
628: }
629: #endif DEBUG
630:
631: /*
632: * Macro processing
633: *
634: * Macro table definitions
635: */
636: #define reg register
637: typedef int pacmac; /* compressed macro name */
638: int argconcat = 0; /* concat arguments together (-me only) */
639:
640: #define tomac(c1, c2) ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
641: #define frommac(src, c1, c2) (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
642:
643: struct mactab{
644: int condition;
645: pacmac macname;
646: int (*func)();
647: };
648: struct mactab troffmactab[];
649: struct mactab ppmactab[];
650: struct mactab msmactab[];
651: struct mactab mmmactab[];
652: struct mactab memactab[];
653: struct mactab manmactab[];
654: /*
655: * macro table initialization
656: */
657: #define M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
658:
659: /*
660: * Put out a macro line, using ms and mm conventions.
661: */
662: msputmac(s, constant)
663: register char *s;
664: int constant;
665: {
666: register char *t;
667: register found;
668: int last;
669: found = 0;
670:
671: if (wordflag) {
672: msputwords(YES);
673: return;
674: }
675: while(*s)
676: {
677: while(*s==' ' || *s=='\t')
678: putchar(*s++);
679: for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
680: ;
681: if(*s == '\"')s++;
682: if(t>s+constant && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){
683: while(s < t)
684: if(*s == '\"')s++;
685: else
686: putchar(*s++);
687: last = *(t-1);
688: found++;
689: }
690: else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0')
691: putchar(*s++);
692: else{
693: last = *(t-1);
694: s = t;
695: }
696: }
697: putchar('\n');
698: if(msflag && chars[last] == PUNCT){
699: putchar(last);
700: putchar('\n');
701: }
702: }
703: /*
704: * put out words (for the -w option) with ms and mm conventions
705: */
706: msputwords(macline)
707: int macline; /* is this is a macro line */
708: {
709: register char *p, *p1;
710: int i, nlet;
711:
712: for(p1 = line ; ;) {
713: /*
714: * skip initial specials ampersands and apostrophes
715: */
716: while( chars[*p1] < DIGIT)
717: if(*p1++ == '\0') return;
718: nlet = 0;
719: for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
720: if(i == LETTER) ++nlet;
721:
722: if (nlet > 1 && chars[p1[0]] == LETTER) {
723: /*
724: * delete trailing ampersands and apostrophes
725: */
726: while( (i=chars[p[-1]]) == PUNCT || i == APOS )
727: --p;
728: while(p1 < p)
729: putchar(*p1++);
730: putchar('\n');
731: } else {
732: p1 = p;
733: }
734: }
735: }
736: /*
737: * put out a macro using the me conventions
738: */
739: #define SKIPBLANK(cp) while(*cp == ' ' || *cp == '\t') { cp++; }
740: #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
741:
742: meputmac(cp, constant)
743: reg char *cp;
744: int constant;
745: {
746: reg char *np;
747: int found;
748: int argno;
749: int last;
750: int inquote;
751:
752: if (wordflag) {
753: meputwords(YES);
754: return;
755: }
756: for (argno = 0; *cp; argno++){
757: SKIPBLANK(cp);
758: inquote = (*cp == '"');
759: if (inquote)
760: cp++;
761: for (np = cp; *np; np++){
762: switch(*np){
763: case '\n':
764: case '\0': break;
765: case '\t':
766: case ' ': if (inquote) {
767: continue;
768: } else {
769: goto endarg;
770: }
771: case '"': if(inquote && np[1] == '"'){
772: strcpy(np, np + 1);
773: np++;
774: continue;
775: } else {
776: *np = ' '; /* bye bye " */
777: goto endarg;
778: }
779: default: continue;
780: }
781: }
782: endarg: ;
783: /*
784: * cp points at the first char in the arg
785: * np points one beyond the last char in the arg
786: */
787: if ((argconcat == 0) || (argconcat != argno)) {
788: putchar(' ');
789: }
790: #ifdef FULLDEBUG
791: {
792: char *p;
793: printf("[%d,%d: ", argno, np - cp);
794: for (p = cp; p < np; p++) {
795: putchar(*p);
796: }
797: printf("]");
798: }
799: #endif FULLDEBUG
800: /*
801: * Determine if the argument merits being printed
802: *
803: * constant is the cut off point below which something
804: * is not a word.
805: */
806: if ( ( (np - cp) > constant)
807: && ( inquote
808: || (chars[cp[0]] == LETTER)) ){
809: for (cp = cp; cp < np; cp++){
810: putchar(*cp);
811: }
812: last = np[-1];
813: found++;
814: } else
815: if(found && (np - cp == 1) && chars[*cp] == PUNCT){
816: putchar(*cp);
817: } else {
818: last = np[-1];
819: }
820: cp = np;
821: }
822: if(msflag && chars[last] == PUNCT)
823: putchar(last);
824: putchar('\n');
825: }
826: /*
827: * put out words (for the -w option) with ms and mm conventions
828: */
829: meputwords(macline)
830: int macline;
831: {
832: msputwords(macline);
833: }
834: /*
835: *
836: * Skip over a nested set of macros
837: *
838: * Possible arguments to noblock are:
839: *
840: * fi end of unfilled text
841: * PE pic ending
842: * DE display ending
843: *
844: * for ms and mm only:
845: * KE keep ending
846: *
847: * NE undocumented match to NS (for mm?)
848: * LE mm only: matches RL or *L (for lists)
849: *
850: * for me:
851: * ([lqbzcdf]
852: */
853:
854: noblock(a1, a2)
855: char a1, a2;
856: {
857: register int c1,c2;
858: register int eqnf;
859: int lct;
860: lct = 0;
861: eqnf = 1;
862: SKIP;
863: while(1){
864: while(C != '.')
865: if(c == '\n')
866: continue;
867: else
868: SKIP;
869: if((c1=C) == '\n')
870: continue;
871: if((c2=C) == '\n')
872: continue;
873: if(c1==a1 && c2 == a2){
874: SKIP;
875: if(lct != 0){
876: lct--;
877: continue;
878: }
879: if(eqnf)
880: putchar('.');
881: putchar('\n');
882: return;
883: } else if(a1 == 'L' && c2 == 'L'){
884: lct++;
885: SKIP;
886: }
887: /*
888: * equations (EQ) nested within a display
889: */
890: else if(c1 == 'E' && c2 == 'Q'){
891: if ( (mac == ME && a1 == ')')
892: || (mac != ME && a1 == 'D') ) {
893: eqn();
894: eqnf=0;
895: }
896: }
897: /*
898: * turning on filling is done by the paragraphing
899: * macros
900: */
901: else if(a1 == 'f') { /* .fi */
902: if ( (mac == ME && (c2 == 'h' || c2 == 'p'))
903: ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
904: SKIP;
905: return;
906: }
907: } else {
908: SKIP;
909: }
910: }
911: }
912:
913: EQ()
914: {
915: eqn();
916: return(0);
917: }
918: domacro()
919: {
920: macro();
921: return(0);
922: }
923: PS()
924: {
925: for (C; c == ' ' || c == '\t'; C);
926: if (c == '<') { /* ".PS < file" -- don't expect a .PE */
927: SKIP;
928: return(0);
929: }
930: if (!msflag) {
931: inpic();
932: } else {
933: noblock('P', 'E');
934: }
935: return(0);
936: }
937:
938: skip()
939: {
940: SKIP;
941: return(0);
942: }
943:
944: intbl()
945: {
946: if(msflag){
947: stbl();
948: }
949: else tbl();
950: return(0);
951: }
952:
953: outtbl(){ intable = NO; }
954:
955: so()
956: {
957: getfname();
958: if( fname[0] )
959: infile = *++filesp = opn( fname );
960: return(0);
961: }
962: nx()
963: {
964: getfname();
965: if(fname[0] == '\0') exit(0);
966: if(infile != stdin)
967: fclose(infile);
968: infile = *filesp = opn(fname);
969: return(0);
970: }
971: skiptocom(){ SKIP_TO_COM; return(COMX); }
972:
973: PP(c12)
974: pacmac c12;
975: {
976: int c1, c2;
977:
978: frommac(c12, c1, c2);
979: printf(".%c%c",c1,c2);
980: while(C != '\n')putchar(c);
981: putchar('\n');
982: return(0);
983: }
984: AU()
985: {
986: if(mac==MM) {
987: return(0);
988: } else {
989: SKIP_TO_COM;
990: return(COMX);
991: }
992: }
993:
994: SH(c12)
995: pacmac c12;
996: {
997: int c1, c2;
998:
999: frommac(c12, c1, c2);
1000:
1001: if(parag){
1002: printf(".%c%c",c1,c2);
1003: while(C != '\n')putchar(c);
1004: putchar(c);
1005: putchar('!');
1006: while(1){
1007: while(C != '\n')putchar(c);
1008: putchar('\n');
1009: if(C == '.')
1010: return(COM);
1011: putchar('!');
1012: putchar(c);
1013: }
1014: /*NOTREACHED*/
1015: } else {
1016: SKIP_TO_COM;
1017: return(COMX);
1018: }
1019: }
1020:
1021: UX()
1022: {
1023: if(wordflag)
1024: printf("UNIX\n");
1025: else
1026: printf("UNIX ");
1027: return(0);
1028: }
1029:
1030: MMHU(c12)
1031: pacmac c12;
1032: {
1033: int c1, c2;
1034:
1035: frommac(c12, c1, c2);
1036: if(parag){
1037: printf(".%c%c",c1,c2);
1038: while(C != '\n')putchar(c);
1039: putchar('\n');
1040: } else {
1041: SKIP;
1042: }
1043: return(0);
1044: }
1045:
1046: mesnblock(c12)
1047: pacmac c12;
1048: {
1049: int c1, c2;
1050:
1051: frommac(c12, c1, c2);
1052: noblock(')',c2);
1053: return(0);
1054: }
1055: mssnblock(c12)
1056: pacmac c12;
1057: {
1058: int c1, c2;
1059:
1060: frommac(c12, c1, c2);
1061: noblock(c1,'E');
1062: return(0);
1063: }
1064: nf()
1065: {
1066: noblock('f','i');
1067: return(0);
1068: }
1069:
1070: ce()
1071: {
1072: sce();
1073: return(0);
1074: }
1075:
1076: meip(c12)
1077: pacmac c12;
1078: {
1079: if(parag)
1080: mepp(c12);
1081: else if (wordflag) /* save the tag */
1082: regline(meputmac, ONE);
1083: else {
1084: SKIP;
1085: }
1086: return(0);
1087: }
1088: /*
1089: * only called for -me .pp or .sh, when parag is on
1090: */
1091: mepp(c12)
1092: pacmac c12;
1093: {
1094: PP(c12); /* eats the line */
1095: return(0);
1096: }
1097: /*
1098: * Start of a section heading; output the section name if doing words
1099: */
1100: mesh(c12)
1101: pacmac c12;
1102: {
1103: if (parag)
1104: mepp(c12);
1105: else if (wordflag)
1106: defcomline(c12);
1107: else {
1108: SKIP;
1109: }
1110: return(0);
1111: }
1112: /*
1113: * process a font setting
1114: */
1115: mefont(c12)
1116: pacmac c12;
1117: {
1118: argconcat = 1;
1119: defcomline(c12);
1120: argconcat = 0;
1121: return(0);
1122: }
1123: manfont(c12)
1124: pacmac c12;
1125: {
1126: return(mefont(c12));
1127: }
1128: manpp(c12)
1129: pacmac c12;
1130: {
1131: return(mepp(c12));
1132: }
1133:
1134: defcomline(c12)
1135: pacmac c12;
1136: {
1137: int c1, c2;
1138:
1139: frommac(c12, c1, c2);
1140: if(msflag && mac==MM && c2=='L'){
1141: if(disp || c1 == 'R') {
1142: noblock('L','E');
1143: } else {
1144: SKIP;
1145: putchar('.');
1146: }
1147: }
1148: else if(c1=='.' && c2=='.'){
1149: if(msflag){
1150: SKIP;
1151: return;
1152: }
1153: while(C == '.')
1154: /*VOID*/;
1155: }
1156: ++inmacro;
1157: /*
1158: * Process the arguments to the macro
1159: */
1160: switch(mac){
1161: default:
1162: case MM:
1163: case MS:
1164: if(c1 <= 'Z' && msflag)
1165: regline(msputmac, ONE);
1166: else
1167: regline(msputmac, TWO);
1168: break;
1169: case ME:
1170: regline(meputmac, ONE);
1171: break;
1172: }
1173: --inmacro;
1174: }
1175:
1176: comline()
1177: {
1178: reg int c1;
1179: reg int c2;
1180: pacmac c12;
1181: reg int mid;
1182: int lb, ub;
1183: int hit;
1184: static int tabsize = 0;
1185: static struct mactab *mactab = (struct mactab *)0;
1186: reg struct mactab *mp;
1187:
1188: if (mactab == 0){
1189: buildtab(&mactab, &tabsize);
1190: }
1191: com:
1192: while(C==' ' || c=='\t')
1193: ;
1194: comx:
1195: if( (c1=c) == '\n')
1196: return;
1197: c2 = C;
1198: if(c1=='.' && c2 !='.')
1199: inmacro = NO;
1200: if(msflag && c1 == '['){
1201: refer(c2);
1202: return;
1203: }
1204: if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
1205: printf(".P\n");
1206: return;
1207: }
1208: if(c2 == '\n')
1209: return;
1210: /*
1211: * Single letter macro
1212: */
1213: if (mac == ME && (c2 == ' ' || c2 == '\t') )
1214: c2 = ' ';
1215: c12 = tomac(c1, c2);
1216: /*
1217: * binary search through the table of macros
1218: */
1219: lb = 0;
1220: ub = tabsize - 1;
1221: while(lb <= ub){
1222: mid = (ub + lb) / 2;
1223: mp = &mactab[mid];
1224: if (mp->macname < c12)
1225: lb = mid + 1;
1226: else if (mp->macname > c12)
1227: ub = mid - 1;
1228: else {
1229: hit = 1;
1230: #ifdef FULLDEBUG
1231: printf("preliminary hit macro %c%c ", c1, c2);
1232: #endif FULLDEBUG
1233: switch(mp->condition){
1234: case NONE: hit = YES; break;
1235: case FNEST: hit = (filesp == files); break;
1236: case NOMAC: hit = !inmacro; break;
1237: case MAC: hit = inmacro; break;
1238: case PARAG: hit = parag; break;
1239: case NBLK: hit = !keepblock; break;
1240: default: hit = 0;
1241: }
1242: if (hit) {
1243: #ifdef FULLDEBUG
1244: printf("MATCH\n");
1245: #endif FULLDEBUG
1246: switch( (*(mp->func))(c12) ) {
1247: default: return;
1248: case COMX: goto comx;
1249: case COM: goto com;
1250: }
1251: }
1252: #ifdef FULLDEBUG
1253: printf("FAIL\n");
1254: #endif FULLDEBUG
1255: break;
1256: }
1257: }
1258: defcomline(c12);
1259: }
1260:
1261: int macsort(p1, p2)
1262: struct mactab *p1, *p2;
1263: {
1264: return(p1->macname - p2->macname);
1265: }
1266:
1267: int sizetab(mp)
1268: reg struct mactab *mp;
1269: {
1270: reg int i;
1271: i = 0;
1272: if (mp){
1273: for (; mp->macname; mp++, i++)
1274: /*VOID*/ ;
1275: }
1276: return(i);
1277: }
1278:
1279: struct mactab *macfill(dst, src)
1280: reg struct mactab *dst;
1281: reg struct mactab *src;
1282: {
1283: if (src) {
1284: while(src->macname){
1285: *dst++ = *src++;
1286: }
1287: }
1288: return(dst);
1289: }
1290:
1291: buildtab(r_back, r_size)
1292: struct mactab **r_back;
1293: int *r_size;
1294: {
1295: int size;
1296:
1297: struct mactab *p, *p1, *p2;
1298: struct mactab *back;
1299:
1300: size = sizetab(troffmactab);
1301: size += sizetab(ppmactab);
1302: p1 = p2 = (struct mactab *)0;
1303: if (msflag){
1304: switch(mac){
1305: case ME: p1 = memactab; break;
1306: case MM: p1 = msmactab;
1307: p2 = mmmactab; break;
1308:
1309: case MS: p1 = msmactab; break;
1310: case MA: p1 = manmactab; break;
1311: default: break;
1312: }
1313: }
1314: size += sizetab(p1);
1315: size += sizetab(p2);
1316: back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
1317:
1318: p = macfill(back, troffmactab);
1319: p = macfill(p, ppmactab);
1320: p = macfill(p, p1);
1321: p = macfill(p, p2);
1322:
1323: qsort(back, size, sizeof(struct mactab), macsort);
1324: *r_size = size;
1325: *r_back = back;
1326: }
1327:
1328: /*
1329: * troff commands
1330: */
1331: struct mactab troffmactab[] = {
1332: M(NONE, '\\','"', skip), /* comment */
1333: M(NOMAC, 'd','e', domacro), /* define */
1334: M(NOMAC, 'i','g', domacro), /* ignore till .. */
1335: M(NOMAC, 'a','m', domacro), /* append macro */
1336: M(NBLK, 'n','f', nf), /* filled */
1337: M(NBLK, 'c','e', ce), /* centered */
1338:
1339: M(NONE, 's','o', so), /* source a file */
1340: M(NONE, 'n','x', nx), /* go to next file */
1341:
1342: M(NONE, 't','m', skip), /* print string on tty */
1343: M(NONE, 'h','w', skip), /* exception hyphen words */
1344: M(NONE, 0,0, 0)
1345: };
1346: /*
1347: * Preprocessor output
1348: */
1349: struct mactab ppmactab[] = {
1350: M(FNEST, 'E','Q', EQ), /* equation starting */
1351: M(FNEST, 'T','S', intbl), /* table starting */
1352: M(FNEST, 'T','C', intbl), /* alternative table? */
1353: M(FNEST, 'T','&', intbl), /* table reformatting */
1354: M(NONE, 'T','E', outtbl),/* table ending */
1355: M(NONE, 'P','S', PS), /* picture starting */
1356: M(NONE, 0,0, 0)
1357: };
1358: /*
1359: * Particular to ms and mm
1360: */
1361: struct mactab msmactab[] = {
1362: M(NONE, 'T','L', skiptocom), /* title follows */
1363: M(NONE, 'F','S', skiptocom), /* start footnote */
1364: M(NONE, 'O','K', skiptocom), /* Other kws */
1365:
1366: M(NONE, 'N','R', skip), /* undocumented */
1367: M(NONE, 'N','D', skip), /* use supplied date */
1368:
1369: M(PARAG, 'P','P', PP), /* begin parag */
1370: M(PARAG, 'I','P', PP), /* begin indent parag, tag x */
1371: M(PARAG, 'L','P', PP), /* left blocked parag */
1372:
1373: M(NONE, 'A','U', AU), /* author */
1374: M(NONE, 'A','I', AU), /* authors institution */
1375:
1376: M(NONE, 'S','H', SH), /* section heading */
1377: M(NONE, 'S','N', SH), /* undocumented */
1378: M(NONE, 'U','X', UX), /* unix */
1379:
1380: M(NBLK, 'D','S', mssnblock), /* start display text */
1381: M(NBLK, 'K','S', mssnblock), /* start keep */
1382: M(NBLK, 'K','F', mssnblock), /* start float keep */
1383: M(NONE, 0,0, 0)
1384: };
1385:
1386: struct mactab mmmactab[] = {
1387: M(NONE, 'H',' ', MMHU), /* -mm ? */
1388: M(NONE, 'H','U', MMHU), /* -mm ? */
1389: M(PARAG, 'P',' ', PP), /* paragraph for -mm */
1390: M(NBLK, 'N','S', mssnblock), /* undocumented */
1391: M(NONE, 0,0, 0)
1392: };
1393:
1394: struct mactab memactab[] = {
1395: M(PARAG, 'p','p', mepp),
1396: M(PARAG, 'l','p', mepp),
1397: M(PARAG, 'n','p', mepp),
1398: M(NONE, 'i','p', meip),
1399:
1400: M(NONE, 's','h', mesh),
1401: M(NONE, 'u','h', mesh),
1402:
1403: M(NBLK, '(','l', mesnblock),
1404: M(NBLK, '(','q', mesnblock),
1405: M(NBLK, '(','b', mesnblock),
1406: M(NBLK, '(','z', mesnblock),
1407: M(NBLK, '(','c', mesnblock),
1408:
1409: M(NBLK, '(','d', mesnblock),
1410: M(NBLK, '(','f', mesnblock),
1411: M(NBLK, '(','x', mesnblock),
1412:
1413: M(NONE, 'r',' ', mefont),
1414: M(NONE, 'i',' ', mefont),
1415: M(NONE, 'b',' ', mefont),
1416: M(NONE, 'u',' ', mefont),
1417: M(NONE, 'q',' ', mefont),
1418: M(NONE, 'r','b', mefont),
1419: M(NONE, 'b','i', mefont),
1420: M(NONE, 'b','x', mefont),
1421: M(NONE, 0,0, 0)
1422: };
1423:
1424:
1425: struct mactab manmactab[] = {
1426: M(PARAG, 'B','I', manfont),
1427: M(PARAG, 'B','R', manfont),
1428: M(PARAG, 'I','B', manfont),
1429: M(PARAG, 'I','R', manfont),
1430: M(PARAG, 'R','B', manfont),
1431: M(PARAG, 'R','I', manfont),
1432:
1433: M(PARAG, 'P','P', manpp),
1434: M(PARAG, 'L','P', manpp),
1435: M(PARAG, 'H','P', manpp),
1436: M(NONE, 0,0, 0)
1437: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.