%{ #ident "$Id: pp.l,v 1.53 2003-07-09 10:35:30+03 rl Exp $" /* * pp - pretty printer * * Author: * Dr. Zvi Har'El, לארה יבצ ר"ד * Department of Mathematics, הקיטמתמל הטלוקפה * Technion, Israel Institute of Technology, ל"טמ - ןוינכטה * Haifa 32000, Israel. לארשי ,32000 הפיח * E-Mail: rl@math.technion.ac.il */ #include #include #include #include #include #ifndef TROFF # define TROFF "troff" #endif #ifndef VOIDHACK # ifdef __STDC__ # define VOIDHACK void # else # define VOIDHACK char # endif #endif #ifndef LEXEOF # ifdef FLEX_SCANNER # define LEXEOF EOF # else # define LEXEOF 0 # endif #endif #define out(x) fputs(x,yyout) #define ROMAN out("\\f1") #define ITALIC out("\\f2") #define BOLD out("\\f3") #define VAL (p[1] ? p+1 : (argc--, *++argv)) #define option(x) (fprintf(yyout, ".am OP\n.%s %s\n..\n", x, VAL), p = "-") #define errexit(x) (perror(x), exit(errno)) int cpp, arrow, mode, keep, clear, key, lineno, increment, force; char *fn, *hebrew = "", *name, lmargin[] = "\\f2\\h'-\\w'%d0'u'%d\\0\\fP", rmargin[] = "\\kx\\s+2\\f4\\h'|\\n(.lu-\\w'%s'u'%s\\f1\\s0\\h'|\\nxu'\n.ds r %s\n"; %} PP define|elif|endif|ident|ifdef|ifndef|include|line|undef AU auto|break|case|char|const|continue|default|do|double|else|enum|extern FL float|for|goto|if|int|long|register|return|short|sizeof|static|struct SW switch|typedef|union|unsigned|void|while JA abstract|boolean|break|byte|byvalue|case|cast|catch|char|class|const JB continue|default|do|double|else|extends|false|final|finally|float JC for|future|generic|goto|if|implements|import|inner|instanceof|int JD interface|long|native|new|null|operator|outer|package|private|protected JE public|rest|return|short|static|super|switch|synchronized|this|throw JF throws|transient|true|try|var|void|volatile|while C {AU}|{FL}|{SW}|{JA}|{JB}|{JC}|{JD}|{JE}|{JF} ID [_a-zA-Z][_a-zA-Z0-9]* %p 6000 %% ^({C})[ \t]*\( {key = 1; REJECT;} ^{ID}[ \t]*\( { char *s, *t; if (key || mode || cpp) {key = 0; REJECT;} name = (char*) realloc(name, yyleng + 1); for (t = name, s = yytext; !isspace(*s) && *s!='('; t++, s++) *t = *s; *t = 0; ECHO; } {C} {if (mode) REJECT; BOLD; ECHO; ROMAN;} {PP} {if (mode || !cpp) REJECT; BOLD; ECHO; ROMAN;} {ID} {if (mode) REJECT; ECHO;} ^# {if (!mode) cpp = 1; ECHO;} ^\} {if (!mode) clear = 1; ECHO;} \/\/ {ECHO; if (!mode) {ITALIC; mode = '$';}} \/\* {ECHO; if (!mode) {ITALIC; mode = '/';}} \*\/ {if (mode == '/') {ROMAN; mode = 0;} ECHO;} ^(\'|\.) {out("\\&"); REJECT;} \'|\" { if (mode == *yytext) {ROMAN; ECHO; mode = 0;} else {ECHO; if (!mode) {ITALIC; mode = *yytext;}} } \\\\|\\ {ECHO; ECHO;} \\.|- {out("\\"); ECHO;} \n|\f|\n\f|\f\n|\n\f\n { char *s; int c; for (s = yytext; *s; s++) if (*s == '\n') lineno++; if (*name) {fprintf(yyout, rmargin, name, name, name); *name = 0;} else if (clear) {out("\n.ds r\n"); clear = 0;} else out("\n"); if (*yytext == '\f' || yyleng > 1) out(".bp\n"); else if (!keep) out(".br\n"); if ((*yytext == '\n' || yyleng > 1) && increment && !(lineno % increment) && (c = input()) != LEXEOF) {fprintf(yyout, lmargin, lineno, lineno); unput(c);} cpp = 0; if (mode == '$') {ROMAN; mode = 0;} } (.\b)+. { if (yytext[yyleng-3] == yytext[yyleng-1]) BOLD; else if (yytext[yyleng-3] == '_') ITALIC; out(yytext + yyleng - 1); ROMAN; } ->|>=|<=|!=|== {if (arrow && !mode) out("\\("); ECHO;}  {out("\\(bu");} [\xe0-\xfa]+ {if (*hebrew) {out("\\f5"); ECHO; out("\\fP");} else ECHO;} (\xd7[\x90-\xaa])+ { unsigned char *s; out("\\f5"); for (s = yytext; *s; s++) fprintf(yyout, "%c", *++s + '\x50', yyout); out("\\fP"); } (\xc2[\xa0-\xbf])+ { unsigned char *s; for (s = yytext; *s; s++) fprintf(yyout, "%c", *++s, yyout); } (\xc3[\x80-\xbf])+ { unsigned char *s; for (s = yytext; *s; s++) fprintf(yyout, "%c", *++s + '\x40', yyout); } \xc5\x92 {out("\\(OE");} \xc5\x93 {out("\\(oe");} \xce\x91 {out("\\(*A");} \xce\x92 {out("\\(*B");} \xce\xb1 {out("\\(*a");} \xce\xb2 {out("\\(*b");} \xe2\x80\x93 {out("\\(en");} \xe2\x80\x94 {out("\\(em");} \xe2\x80\x98 {out("\\(oq");} \xe2\x80\x99 {out("\\(cq");} \xe2\x80\x9c {out("\\(lq");} \xe2\x80\x9d {out("\\(rq");} \xe2\x84\xa2 {out("\\(tm");} >>|<< {ECHO;} . { if (!force && !isprint(*yytext) && !isspace(*yytext)) {fprintf(stderr,"%s:%d: illegal character (%#x)\n", fn, lineno, (unsigned char)*yytext); exit(1);} ECHO; } %% main(int argc,char **argv) { extern char *ctime(), *getenv(); extern FILE *tmpfile(); int first = 1, date = 0, even = 0, file = 0; char *device = 0, *p; name = (char*) malloc(1); *name = 0; /* * Initialize temprorary file for troff text. */ if (yyout = tmpfile()) { extern char *tmac[]; char **s; for (s = tmac; *s; s++) out(*s); } if (!yyout || ferror (yyout)) errexit("tmpfile"); /* * Get environment options, replacing unquoted white space by nulls. */ if ((p = getenv("PPOPT")) && *p) { char **nargv; int nargc = 1; nargv = (char**) malloc(sizeof(char*)); *nargv = *argv++; while (*p) { nargv = (char**) realloc((char*) nargv, (nargc + 1) * sizeof(char*)); nargv[nargc++] = p; while (*p && !isspace(*p)) { char *q; if (*p == '\\') for (q = p; *q ; q++) *q = q[1]; p++; } while (*p && isspace(*p)) *p++ = 0; } if (--argc) { nargv = (char**) realloc((char*) nargv, (nargc + argc) * sizeof(char*)); while (argc--) nargv[nargc++] = *argv++; } argc = nargc; argv = nargv; } /* * Process command line options. */ while (--argc || !file) if (argc && *(p = *++argv) == '-' && p[1]) while (*++p) switch (*p) { case 'a': arrow ^= 1; break; case 'd': date ^= 1; break; case 'u': force ^= 1; break; case 'k': keep ^= 1; break; case 'x': mode ^= 'x'; break; case '2': even ^= 1; fprintf(yyout, ".nr e %d\n", even); break; case 'n': if ((increment = atoi(VAL)) < 0) increment = 0; p = "-"; break; case 'T': device = VAL; p = "-"; break; case '.': fprintf(yyout, ".am OP\n.%s\n..\n", VAL); p = "-"; break; case 'h': if (*(hebrew = VAL)) fprintf(yyout, ".am OP\n.HB %s\n..\n", hebrew); p = "-"; break; case 'f': option("FM"); break; case 'o': option("OF"); break; case 's': option("SZ"); break; case 't': option("TB"); break; case 'w': option("WD"); break; } else if(argc && *(fn=p) != '-' && !(yyin = fopen(fn, "r"))) errexit(fn); else { int c; struct stat buf; file = 1; if (!argc || *fn == '-') { fn = ""; yyin = stdin; } /* * Ignore empty files. */ if ((c = getc(yyin)) == EOF) { if (!argc) break; if (yyin != stdin) fclose(yyin); continue; } ungetc(c, yyin); /* * Save file-name for printing in the page header. */ if (yyin == stdin) out(".ds L\n.ds R\n"); else fprintf(yyout, ".ds L %s\n.ds R %s\n", fn, fn); /* * If not the first file, eject a page and reset page counter. */ if (!first) out(".bp 1\n"); else first = 0; /* * Control long lines breaking. */ if (keep) out(".nf\n"); else out(".na\n.nh\n.br\n"); /* * Save file-name and time for printing in the page footer. */ if (yyin == stdin) out(".ds N\n"); else fprintf(yyout, ".ds N \" of %s\n", fn); if (date) time(&buf.st_mtime); else fstat(fileno(yyin), &buf); fprintf(yyout, ".ds T %s", ctime(&buf.st_mtime)); /* * Process input file. */ lineno = 1; if (increment == 1) fprintf(yyout, lmargin, 1, 1); yylex(); /* * Tie up the loose ends. */ if( *yytext != '\n' && *yytext != '\f') out("\n"); if (mode && mode != 'x') { out(".ft 1\n"); mode = 0; } out(".ds r\n"); if (even) out(".if o .bp\n"); if (!argc) break; } /* * Process temporary file. */ rewind(yyout); if (device && !strcmp(device, "-")) { int c; while ((c = getc(yyout)) != EOF) putchar(c); if (ferror(stdout)) errexit("stdout"); if (ferror(yyout)) errexit("tmpfile"); exit(0); } if (!lineno) exit(0); close(0); dup(fileno(yyout)); if (!(p = getenv("PPROFF")) || !*p) p = TROFF; if (!device) execlp(p, p, (char *)0); else { name = (char*) realloc(name, strlen(device) + 3); sprintf(name, "-T%s", device); execlp(p, p, name, (char *)0); } errexit(p); } /* * Tmac - troff macros */ char *tmac[] = { ".\\\"pp troff macros version $Revision: 1.53 $ (rl) $Date: 2003-07-09 10:35:30+03 $\n", /* OP - "-." options (initially - none) */ ".de OP\n", "..\n", /* HD - process page header */ ".de HD\n", ".OP\n", /* set options ... */ ".de OP\n", /* ... and clear them */ "\\\\..\n", ".sp |3\n", /* leave 3 spaces from the top */ ".ie !\\\\ne .tl '\\f3\\s+4\\\\*L''\\\\*R\\s0\\fP'\n", /* print header */ ".el .ie o .tl '\\f3\\s+4\\\\*L''\\\\*R\\s0\\fP'\n", ".el .tl '\\f3\\s+4\\\\*R''\\\\*L\\s0\\fP'\n", ".if !'\\\\*r'' .tl '''\\f4\\s-1...\\\\*r\\s0\\\\fP'\n", /* sub-header */ ".sp |6\n", /* leave 1 more space. */ "..\n", /* FT - process page footer */ ".de FT\n", ".sp |\\\\n(.pu-3\n", /* leave 3 spaces from the bottom */ ".ie !\\\\ne .tl '\\f2\\s-1\\\\*T''Page %\\\\*N\\s0\\fP'\n", /* print page footer */ ".el .ie o .tl '\\f2\\s-1\\\\*T''Page %\\\\*N\\s0\\fP'\n", ".el .tl '\\f2\\s-1Page %\\\\*N''\\\\*T\\s0\\fP'\n", ".bp\n", /* begin new page */ "..\n", /* MT - set multiple tabs */ ".de MT\n", ".ie \\n(.g .ta T \\\\$1\n", ".el .ta \\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1", " +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1", " +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1", " +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1 +\\\\$1\n", "..\n", /* SZ - set sizes (-s option) */ ".de SZ\n", ".ps \\\\$1\n", /* set type size */ ".vs 1.2u*\\\\$1\n", /* set vertical spacing size */ ".ch FT -5v\n", /* set footer trap position */ ".MT 3.6\n", /* set default tab stops */ "..\n", /* TB - set tabulator stops (-t option) */ ".de TB\n", ".MT \\\\$1u*\\\\w'0'u\n", "..\n", /* WD - set widths (-w option) */ ".de WD\n", ".ll \\\\$1u*\\\\w'0'u\n", /* set line width */ ".lt \\\\$1u*\\\\w'0'u\n", /* set title width */ "..\n", /* OF - set page offset (-o option) */ ".de OF\n", ".po \\\\$1u*\\\\w'0'u\n", "..\n", /* F - mount fonts */ ".de F\n", ".fp 1 \\\\$1\n", ".fp 2 \\\\$2\n", ".fp 3 \\\\$3\n", ".fp 4 \\\\$4\n", "..\n", /* HB - mount a Hebrew font */ ".de HB\n", ".fp 5 \\\\$1\n", "..\n", /* FF - mount long fonts */ ".de FF\n", ".fp 1 R \\\\$1\n", ".fp 2 I \\\\$2\n", ".fp 3 B \\\\$3\n", ".fp 4 X \\\\$4\n", "..\n", /* FM - mount a font family (-f option) */ ".de FM\n", ".ie \\n(.g .fam \\\\$1\n", ".el \\{\\\n", #ifndef ALT_FONTS ".if '\\\\$1'A' .F AR AI AB AX\n", /* ITC AvantGarde Gothic */ ".if '\\\\$1'BM' .F KR KI KB KX\n", /* ITC Bookman */ ".if '\\\\$1'C' .F CW CI CB CX\n", /* Courier */ ".if '\\\\$1'H' .F H HI HB HX\n", /* Helvetica */ ".if '\\\\$1'HN' .F Hr Hi Hb Hx\n", /* Helvetica-Narrow */ ".if '\\\\$1'N' .F NR NI NB NX\n", /* NewCenturySchlbk */ ".if '\\\\$1'P' .F PA PI PB PX\n", /* Palatino */ #else ".if '\\\\$1'A' .F A AO AB AD\n", /* ITC AvantGarde Gothic */ ".if '\\\\$1'BM' .F K KI KB KD\n", /* ITC Bookman */ ".if '\\\\$1'C' .F C CO CB CD\n", /* Courier */ ".if '\\\\$1'H' .F H HO HB HD\n", /* Helvetica */ ".if '\\\\$1'HN' .F V VO VB VD\n", /* Helvetica-Narrow */ ".if '\\\\$1'N' .F NR NI NB ND\n", /* NewCenturySchlbk */ ".if '\\\\$1'P' .F PR PI PB PD\n", /* Palatino */ #endif ".if '\\\\$1'T' .F R I B BI\n", /* Times */ "\\}\n", "..\n", /* install traps */ ".wh 0 HD\n", /* for header */ ".wh -5v FT\n", /* for footer */ 0 }; #ifdef NO_TMPFILE /*define if tmpfile(3) is unavailable*/ FILE * tmpfile(void) /* * Tmpfile - open a temporary file descriptor. */ { extern char *tmpnam(); char *name; FILE *fp; fp = fopen(name = tmpnam((char*) 0), "w+"); unlink(name); return fp; } #endif