|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)deroff.c 4.4 (Berkeley) 83/04/29";
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, const)
292: char *str;
293: int const;
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, const)
318: int (*pfunc)();
319: int const;
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, const);
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, const)
663: register char *s;
664: int const;
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+const && 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 ( (macline && nlet > 1)
723: || (!macline && nlet > 2
724: && chars[p1[0]] == LETTER
725: && chars[p1[1]] == LETTER) )
726: {
727: /*
728: * delete trailing ampersands and apostrophes
729: */
730: while( (p[-1]=='\'')
731: || (p[-1]=='&')
732: || (chars[p[-1]] == PUNCT) ){
733: --p;
734: }
735: while(p1 < p)
736: putchar(*p1++);
737: putchar('\n');
738: } else {
739: p1 = p;
740: }
741: }
742: }
743: /*
744: * put out a macro using the me conventions
745: */
746: #define SKIPBLANK(cp) while(*cp == ' ' || *cp == '\t') { cp++; }
747: #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
748:
749: meputmac(cp, const)
750: reg char *cp;
751: int const;
752: {
753: reg char *np;
754: int found;
755: int argno;
756: int last;
757: int inquote;
758:
759: if (wordflag) {
760: meputwords(YES);
761: return;
762: }
763: for (argno = 0; *cp; argno++){
764: SKIPBLANK(cp);
765: inquote = (*cp == '"');
766: if (inquote)
767: cp++;
768: for (np = cp; *np; np++){
769: switch(*np){
770: case '\n':
771: case '\0': break;
772: case '\t':
773: case ' ': if (inquote) {
774: continue;
775: } else {
776: goto endarg;
777: }
778: case '"': if(inquote && np[1] == '"'){
779: strcpy(np, np + 1);
780: np++;
781: continue;
782: } else {
783: *np = ' '; /* bye bye " */
784: goto endarg;
785: }
786: default: continue;
787: }
788: }
789: endarg: ;
790: /*
791: * cp points at the first char in the arg
792: * np points one beyond the last char in the arg
793: */
794: if ((argconcat == 0) || (argconcat != argno)) {
795: putchar(' ');
796: }
797: #ifdef FULLDEBUG
798: {
799: char *p;
800: printf("[%d,%d: ", argno, np - cp);
801: for (p = cp; p < np; p++) {
802: putchar(*p);
803: }
804: printf("]");
805: }
806: #endif FULLDEBUG
807: /*
808: * Determine if the argument merits being printed
809: *
810: * const is the cut off point below which something
811: * is not a word.
812: */
813: if ( ( (np - cp) > const)
814: && ( inquote
815: || (chars[cp[0]] == LETTER)) ){
816: for (cp = cp; cp < np; cp++){
817: putchar(*cp);
818: }
819: last = np[-1];
820: found++;
821: } else
822: if(found && (np - cp == 1) && chars[*cp] == PUNCT){
823: putchar(*cp);
824: } else {
825: last = np[-1];
826: }
827: cp = np;
828: }
829: if(msflag && chars[last] == PUNCT)
830: putchar(last);
831: putchar('\n');
832: }
833: /*
834: * put out words (for the -w option) with ms and mm conventions
835: */
836: meputwords(macline)
837: int macline;
838: {
839: msputwords(macline);
840: }
841: /*
842: *
843: * Skip over a nested set of macros
844: *
845: * Possible arguments to noblock are:
846: *
847: * fi end of unfilled text
848: * PE pic ending
849: * DE display ending
850: *
851: * for ms and mm only:
852: * KE keep ending
853: *
854: * NE undocumented match to NS (for mm?)
855: * LE mm only: matches RL or *L (for lists)
856: *
857: * for me:
858: * ([lqbzcdf]
859: */
860:
861: noblock(a1, a2)
862: char a1, a2;
863: {
864: register int c1,c2;
865: register int eqnf;
866: int lct;
867: lct = 0;
868: eqnf = 1;
869: SKIP;
870: while(1){
871: while(C != '.')
872: if(c == '\n')
873: continue;
874: else
875: SKIP;
876: if((c1=C) == '\n')
877: continue;
878: if((c2=C) == '\n')
879: continue;
880: if(c1==a1 && c2 == a2){
881: SKIP;
882: if(lct != 0){
883: lct--;
884: continue;
885: }
886: if(eqnf)
887: putchar('.');
888: putchar('\n');
889: return;
890: } else if(a1 == 'L' && c2 == 'L'){
891: lct++;
892: SKIP;
893: }
894: /*
895: * equations (EQ) nested within a display
896: */
897: else if(c1 == 'E' && c2 == 'Q'){
898: if ( (mac == ME && a1 == ')')
899: || (mac != ME && a1 == 'D') ) {
900: eqn();
901: eqnf=0;
902: }
903: }
904: /*
905: * turning on filling is done by the paragraphing
906: * macros
907: */
908: else if(a1 == 'f') { /* .fi */
909: if ( (mac == ME && (c2 == 'h' || c2 == 'p'))
910: ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
911: SKIP;
912: return;
913: }
914: } else {
915: SKIP;
916: }
917: }
918: }
919:
920: EQ()
921: {
922: eqn();
923: return(0);
924: }
925: domacro()
926: {
927: macro();
928: return(0);
929: }
930: PS()
931: {
932: if (!msflag) {
933: inpic();
934: } else {
935: noblock('P', 'E');
936: }
937: return(0);
938: }
939:
940: skip()
941: {
942: SKIP;
943: return(0);
944: }
945:
946: intbl()
947: {
948: if(msflag){
949: stbl();
950: }
951: else tbl();
952: return(0);
953: }
954:
955: outtbl(){ intable = NO; }
956:
957: so()
958: {
959: getfname();
960: if( fname[0] )
961: infile = *++filesp = opn( fname );
962: return(0);
963: }
964: nx()
965: {
966: getfname();
967: if(fname[0] == '\0') exit(0);
968: if(infile != stdin)
969: fclose(infile);
970: infile = *filesp = opn(fname);
971: return(0);
972: }
973: skiptocom(){ SKIP_TO_COM; return(COMX); }
974:
975: PP(c12)
976: pacmac c12;
977: {
978: int c1, c2;
979:
980: frommac(c12, c1, c2);
981: printf(".%c%c",c1,c2);
982: while(C != '\n')putchar(c);
983: putchar('\n');
984: return(0);
985: }
986: AU()
987: {
988: if(mac==MM) {
989: return(0);
990: } else {
991: SKIP_TO_COM;
992: return(COMX);
993: }
994: }
995:
996: SH(c12)
997: pacmac c12;
998: {
999: int c1, c2;
1000:
1001: frommac(c12, c1, c2);
1002:
1003: if(parag){
1004: printf(".%c%c",c1,c2);
1005: while(C != '\n')putchar(c);
1006: putchar(c);
1007: putchar('!');
1008: while(1){
1009: while(C != '\n')putchar(c);
1010: putchar('\n');
1011: if(C == '.')
1012: return(COM);
1013: putchar('!');
1014: putchar(c);
1015: }
1016: /*NOTREACHED*/
1017: } else {
1018: SKIP_TO_COM;
1019: return(COMX);
1020: }
1021: }
1022:
1023: UX()
1024: {
1025: if(wordflag)
1026: printf("UNIX\n");
1027: else
1028: printf("UNIX ");
1029: return(0);
1030: }
1031:
1032: MMHU(c12)
1033: pacmac c12;
1034: {
1035: int c1, c2;
1036:
1037: frommac(c12, c1, c2);
1038: if(parag){
1039: printf(".%c%c",c1,c2);
1040: while(C != '\n')putchar(c);
1041: putchar('\n');
1042: } else {
1043: SKIP;
1044: }
1045: return(0);
1046: }
1047:
1048: mesnblock(c12)
1049: pacmac c12;
1050: {
1051: int c1, c2;
1052:
1053: frommac(c12, c1, c2);
1054: noblock(')',c2);
1055: return(0);
1056: }
1057: mssnblock(c12)
1058: pacmac c12;
1059: {
1060: int c1, c2;
1061:
1062: frommac(c12, c1, c2);
1063: noblock(c1,'E');
1064: return(0);
1065: }
1066: nf()
1067: {
1068: noblock('f','i');
1069: return(0);
1070: }
1071:
1072: ce()
1073: {
1074: sce();
1075: return(0);
1076: }
1077:
1078: meip(c12)
1079: pacmac c12;
1080: {
1081: if(parag)
1082: mepp(c12);
1083: else if (wordflag) /* save the tag */
1084: regline(meputmac, ONE);
1085: else {
1086: SKIP;
1087: }
1088: return(0);
1089: }
1090: /*
1091: * only called for -me .pp or .sh, when parag is on
1092: */
1093: mepp(c12)
1094: pacmac c12;
1095: {
1096: PP(c12); /* eats the line */
1097: return(0);
1098: }
1099: /*
1100: * Start of a section heading; output the section name if doing words
1101: */
1102: mesh(c12)
1103: pacmac c12;
1104: {
1105: if (parag)
1106: mepp(c12);
1107: else if (wordflag)
1108: defcomline(c12);
1109: else {
1110: SKIP;
1111: }
1112: return(0);
1113: }
1114: /*
1115: * process a font setting
1116: */
1117: mefont(c12)
1118: pacmac c12;
1119: {
1120: argconcat = 1;
1121: defcomline(c12);
1122: argconcat = 0;
1123: return(0);
1124: }
1125: manfont(c12)
1126: pacmac c12;
1127: {
1128: return(mefont(c12));
1129: }
1130: manpp(c12)
1131: pacmac c12;
1132: {
1133: return(mepp(c12));
1134: }
1135:
1136: defcomline(c12)
1137: pacmac c12;
1138: {
1139: int c1, c2;
1140:
1141: frommac(c12, c1, c2);
1142: if(msflag && mac==MM && c2=='L'){
1143: if(disp || c1 == 'R') {
1144: noblock('L','E');
1145: } else {
1146: SKIP;
1147: putchar('.');
1148: }
1149: }
1150: else if(c1=='.' && c2=='.'){
1151: if(msflag){
1152: SKIP;
1153: return;
1154: }
1155: while(C == '.')
1156: /*VOID*/;
1157: }
1158: ++inmacro;
1159: /*
1160: * Process the arguments to the macro
1161: */
1162: switch(mac){
1163: default:
1164: case MM:
1165: case MS:
1166: if(c1 <= 'Z' && msflag)
1167: regline(msputmac, ONE);
1168: else
1169: regline(msputmac, TWO);
1170: break;
1171: case ME:
1172: regline(meputmac, ONE);
1173: break;
1174: }
1175: --inmacro;
1176: }
1177:
1178: comline()
1179: {
1180: reg int c1;
1181: reg int c2;
1182: pacmac c12;
1183: reg int mid;
1184: int lb, ub;
1185: int hit;
1186: static int tabsize = 0;
1187: static struct mactab *mactab = (struct mactab *)0;
1188: reg struct mactab *mp;
1189:
1190: if (mactab == 0){
1191: buildtab(&mactab, &tabsize);
1192: }
1193: com:
1194: while(C==' ' || c=='\t')
1195: ;
1196: comx:
1197: if( (c1=c) == '\n')
1198: return;
1199: c2 = C;
1200: if(c1=='.' && c2 !='.')
1201: inmacro = NO;
1202: if(msflag && c1 == '['){
1203: refer(c2);
1204: return;
1205: }
1206: if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
1207: printf(".P\n");
1208: return;
1209: }
1210: if(c2 == '\n')
1211: return;
1212: /*
1213: * Single letter macro
1214: */
1215: if (mac == ME && (c2 == ' ' || c2 == '\t') )
1216: c2 = ' ';
1217: c12 = tomac(c1, c2);
1218: /*
1219: * binary search through the table of macros
1220: */
1221: lb = 0;
1222: ub = tabsize - 1;
1223: while(lb <= ub){
1224: mid = (ub + lb) / 2;
1225: mp = &mactab[mid];
1226: if (mp->macname < c12)
1227: lb = mid + 1;
1228: else if (mp->macname > c12)
1229: ub = mid - 1;
1230: else {
1231: hit = 1;
1232: #ifdef FULLDEBUG
1233: printf("preliminary hit macro %c%c ", c1, c2);
1234: #endif FULLDEBUG
1235: switch(mp->condition){
1236: case NONE: hit = YES; break;
1237: case FNEST: hit = (filesp == files); break;
1238: case NOMAC: hit = !inmacro; break;
1239: case MAC: hit = inmacro; break;
1240: case PARAG: hit = parag; break;
1241: case NBLK: hit = !keepblock; break;
1242: default: hit = 0;
1243: }
1244: if (hit) {
1245: #ifdef FULLDEBUG
1246: printf("MATCH\n");
1247: #endif FULLDEBUG
1248: switch( (*(mp->func))(c12) ) {
1249: default: return;
1250: case COMX: goto comx;
1251: case COM: goto com;
1252: }
1253: }
1254: #ifdef FULLDEBUG
1255: printf("FAIL\n");
1256: #endif FULLDEBUG
1257: break;
1258: }
1259: }
1260: defcomline(c12);
1261: }
1262:
1263: int macsort(p1, p2)
1264: struct mactab *p1, *p2;
1265: {
1266: return(p1->macname - p2->macname);
1267: }
1268:
1269: int sizetab(mp)
1270: reg struct mactab *mp;
1271: {
1272: reg int i;
1273: i = 0;
1274: if (mp){
1275: for (; mp->macname; mp++, i++)
1276: /*VOID*/ ;
1277: }
1278: return(i);
1279: }
1280:
1281: struct mactab *macfill(dst, src)
1282: reg struct mactab *dst;
1283: reg struct mactab *src;
1284: {
1285: if (src) {
1286: while(src->macname){
1287: *dst++ = *src++;
1288: }
1289: }
1290: return(dst);
1291: }
1292:
1293: buildtab(r_back, r_size)
1294: struct mactab **r_back;
1295: int *r_size;
1296: {
1297: int size;
1298:
1299: struct mactab *p, *p1, *p2;
1300: struct mactab *back;
1301:
1302: size = sizetab(troffmactab);
1303: size += sizetab(ppmactab);
1304: p1 = p2 = (struct mactab *)0;
1305: if (msflag){
1306: switch(mac){
1307: case ME: p1 = memactab; break;
1308: case MM: p1 = msmactab;
1309: p2 = mmmactab; break;
1310:
1311: case MS: p1 = msmactab; break;
1312: case MA: p1 = manmactab; break;
1313: default: break;
1314: }
1315: }
1316: size += sizetab(p1);
1317: size += sizetab(p2);
1318: back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
1319:
1320: p = macfill(back, troffmactab);
1321: p = macfill(p, ppmactab);
1322: p = macfill(p, p1);
1323: p = macfill(p, p2);
1324:
1325: qsort(back, size, sizeof(struct mactab), macsort);
1326: *r_size = size;
1327: *r_back = back;
1328: }
1329:
1330: /*
1331: * troff commands
1332: */
1333: struct mactab troffmactab[] = {
1334: M(NONE, '\\','"', skip), /* comment */
1335: M(NOMAC, 'd','e', domacro), /* define */
1336: M(NOMAC, 'i','g', domacro), /* ignore till .. */
1337: M(NOMAC, 'a','m', domacro), /* append macro */
1338: M(NBLK, 'n','f', nf), /* filled */
1339: M(NBLK, 'c','e', ce), /* centered */
1340:
1341: M(NONE, 's','o', so), /* source a file */
1342: M(NONE, 'n','x', nx), /* go to next file */
1343:
1344: M(NONE, 't','m', skip), /* print string on tty */
1345: M(NONE, 'h','w', skip), /* exception hyphen words */
1346: M(NONE, 0,0, 0)
1347: };
1348: /*
1349: * Preprocessor output
1350: */
1351: struct mactab ppmactab[] = {
1352: M(FNEST, 'E','Q', EQ), /* equation starting */
1353: M(FNEST, 'T','S', intbl), /* table starting */
1354: M(FNEST, 'T','C', intbl), /* alternative table? */
1355: M(FNEST, 'T','&', intbl), /* table reformatting */
1356: M(NONE, 'T','E', outtbl),/* table ending */
1357: M(NONE, 'P','S', PS), /* picture starting */
1358: M(NONE, 0,0, 0)
1359: };
1360: /*
1361: * Particular to ms and mm
1362: */
1363: struct mactab msmactab[] = {
1364: M(NONE, 'T','L', skiptocom), /* title follows */
1365: M(NONE, 'F','S', skiptocom), /* start footnote */
1366: M(NONE, 'O','K', skiptocom), /* Other kws */
1367:
1368: M(NONE, 'N','R', skip), /* undocumented */
1369: M(NONE, 'N','D', skip), /* use supplied date */
1370:
1371: M(PARAG, 'P','P', PP), /* begin parag */
1372: M(PARAG, 'I','P', PP), /* begin indent parag, tag x */
1373: M(PARAG, 'L','P', PP), /* left blocked parag */
1374:
1375: M(NONE, 'A','U', AU), /* author */
1376: M(NONE, 'A','I', AU), /* authors institution */
1377:
1378: M(NONE, 'S','H', SH), /* section heading */
1379: M(NONE, 'S','N', SH), /* undocumented */
1380: M(NONE, 'U','X', UX), /* unix */
1381:
1382: M(NBLK, 'D','S', mssnblock), /* start display text */
1383: M(NBLK, 'K','S', mssnblock), /* start keep */
1384: M(NBLK, 'K','F', mssnblock), /* start float keep */
1385: M(NONE, 0,0, 0)
1386: };
1387:
1388: struct mactab mmmactab[] = {
1389: M(NONE, 'H',' ', MMHU), /* -mm ? */
1390: M(NONE, 'H','U', MMHU), /* -mm ? */
1391: M(PARAG, 'P',' ', PP), /* paragraph for -mm */
1392: M(NBLK, 'N','S', mssnblock), /* undocumented */
1393: M(NONE, 0,0, 0)
1394: };
1395:
1396: struct mactab memactab[] = {
1397: M(PARAG, 'p','p', mepp),
1398: M(PARAG, 'l','p', mepp),
1399: M(PARAG, 'n','p', mepp),
1400: M(NONE, 'i','p', meip),
1401:
1402: M(NONE, 's','h', mesh),
1403: M(NONE, 'u','h', mesh),
1404:
1405: M(NBLK, '(','l', mesnblock),
1406: M(NBLK, '(','q', mesnblock),
1407: M(NBLK, '(','b', mesnblock),
1408: M(NBLK, '(','z', mesnblock),
1409: M(NBLK, '(','c', mesnblock),
1410:
1411: M(NBLK, '(','d', mesnblock),
1412: M(NBLK, '(','f', mesnblock),
1413: M(NBLK, '(','x', mesnblock),
1414:
1415: M(NONE, 'r',' ', mefont),
1416: M(NONE, 'i',' ', mefont),
1417: M(NONE, 'b',' ', mefont),
1418: M(NONE, 'u',' ', mefont),
1419: M(NONE, 'q',' ', mefont),
1420: M(NONE, 'r','b', mefont),
1421: M(NONE, 'b','i', mefont),
1422: M(NONE, 'b','x', mefont),
1423: M(NONE, 0,0, 0)
1424: };
1425:
1426:
1427: struct mactab manmactab[] = {
1428: M(PARAG, 'B','I', manfont),
1429: M(PARAG, 'B','R', manfont),
1430: M(PARAG, 'I','B', manfont),
1431: M(PARAG, 'I','R', manfont),
1432: M(PARAG, 'R','B', manfont),
1433: M(PARAG, 'R','I', manfont),
1434:
1435: M(PARAG, 'P','P', manpp),
1436: M(PARAG, 'L','P', manpp),
1437: M(PARAG, 'H','P', manpp),
1438: M(NONE, 0,0, 0)
1439: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.