commit 5cedca1b69d020c32466f70843a11767773d7e3b from: rsc date: Sat May 15 23:24:00 2004 UTC Let's try this. It's BUGGERED. commit - 76e6aca867e3e48ea04fbcf7284c45369a69829e commit + 5cedca1b69d020c32466f70843a11767773d7e3b blob - /dev/null blob + 10dc8c75c0d6ab96a6106fba5dd4ce2aaf902ad7 (mode 644) --- /dev/null +++ src/cmd/eqn/diacrit.c @@ -0,0 +1,75 @@ +#include "e.h" +#include "y.tab.h" + +extern double Dvshift, Dhshift, Dh2shift, Dheight, Barv, Barh, Ubarv, Ubarh; + +void diacrit(int p1, int type) +{ + int c, t; + + c = salloc(); + t = salloc(); + nrwid(p1, ps, p1); + printf(".nr 10 %gm\n", max(REL(eht[p1]-ebase[p1]-1,ps), 0)); /* vert shift if high */ + if (type == HIGHBAR) + printf(".nr 10 \\n(10+%gm\n", Dvshift); + else if (type == LOWBAR) + printf(".nr 10 0\n"); + else + printf(".if \\n(ct>1 .nr 10 \\n(10+%gm\n", Dvshift); + printf(".nr %d %gm\n", t, Dhshift); /* horiz shift if high */ + printf(".if \\n(ct>1 .nr %d %gm\n", t, Dh2shift); /* was .1 and .15 */ + switch (type) { + case VEC: + printf(".ds %d %s\n", c, lookup(deftbl, "vec_def")->cval); + break; + case DYAD: + printf(".ds %d %s\n", c, lookup(deftbl, "dyad_def")->cval); + break; + case HAT: + printf(".ds %d %s\n", c, lookup(deftbl, "hat_def")->cval); + break; + case TILDE: + printf(".ds %d %s\n", c, lookup(deftbl, "tilde_def")->cval); + break; + case DOT: + printf(".ds %d %s\n", c, lookup(deftbl, "dot_def")->cval); + break; + case DOTDOT: + printf(".ds %d %s\n", c, lookup(deftbl, "dotdot_def")->cval); + break; + case BAR: + case LOWBAR: + case HIGHBAR: + printf(".ds %d \\v'%gm'\\h'%gm'\\l'\\n(%du-%gm'\\h'%gm'\\v'%gm'\n", + c, -Barv, Barh, p1, 2*Barh, Barh, Barv); + break; + case UNDER: + printf(".ds %d \\v'%gm'\\l'\\n(%du-%gm\\(ul'\\h'%gm'\\v'%gm'\n", + c, -Ubarv, p1, Ubarh, Ubarh, Ubarv); + /* printf(".ds %d \\v'-%gm'\\l'\\n(%du\\(ul'\\v'%gm'\n", + c, Ubarv, p1, Ubarv); + */ + printf(".nr %d 0\n", t); + printf(".nr 10 0-.1m-%gm\n", REL(ebase[p1],ps)); + printf(".if \\n(ct%%2=1 .nr 10 0\\n(10-.1m\n"); + break; + case UTILDE: + printf(".ds %d %s\n", c, lookup(deftbl, "utilde_def")->cval); + printf(".nr %d 0\n", t); + printf(".nr 10 0-%gm\n", REL(ebase[p1],ps)); + printf(".if \\n(ct%%2=1 .nr 10 0\\n(10-%gm\n", 0.1); + break; + } + nrwid(c, ps, c); + if (lfont[p1] != ITAL) + printf(".nr %d 0\n", t); + printf(".as %d \\h'-\\n(%du-\\n(%du/2u+\\n(%du'\\v'0-\\n(10u'\\*(%d", + p1, p1, c, t, c); + printf("\\v'\\n(10u'\\h'-\\n(%du+\\n(%du/2u-\\n(%du'\n", c, p1, t); + if (type != UNDER && type != UTILDE) + eht[p1] += EM(Dheight, ps); /* was .15 */ + dprintf(".\tdiacrit: %c over S%d, lf=%c, rf=%c, h=%g, b=%g\n", + type, p1, lfont[p1], rfont[p1], eht[p1], ebase[p1]); + sfree(c); sfree(t); +} blob - /dev/null blob + 70c47023b16c0470779bca25f15f37314f8cceb8 (mode 644) --- /dev/null +++ src/cmd/eqn/e.h @@ -0,0 +1,166 @@ +#include +#include +#include + +enum charclass { + OTHER, OLET, ILET, DIG, LPAR, RPAR, SLASH, PLUS, ILETF, ILETJ, VBAR, + NONE, LAST +}; +extern int class[LAST][LAST]; + +#define dprintf if (dbg) printf +#define max(x,y) (((x) >= (y)) ? (x) : (y)) /* beware of side effects */ +#define min(x,y) (((x) <= (y)) ? (x) : (y)) + +extern char errbuf[200]; +extern char *cmdname; +#define ERROR sprintf(errbuf, +#define FATAL ), error(1, errbuf) +#define WARNING ), error(0, errbuf) +#define SYNTAX ), yyerror(errbuf) + +#define ROM '1' +#define ITAL '2' +#define BLD '3' +#define BDIT '4' + +#define DEFGAP -999 /* default gap in piles */ + +extern int dbg; +extern int ct; +extern int lp[]; +extern int used[]; /* available registers */ +extern int ps; /* dflt init pt size */ +extern int deltaps; /* default change in ps */ +extern int dps_set; /* 1 => -p option used */ +extern int gsize; /* global size */ +extern int ft; /* default font */ +extern int display; /* 1 => inline, 0 => .EQ/.EN */ +extern int synerr; /* 1 if syntax error in this eqn */ + +extern char *typesetter; /* typesetter name for -T... */ +extern int minsize; /* min size it can print */ +extern int ttype; /* actual type of typesetter: */ + +#define DEVCAT 1 +#define DEV202 2 +#define DEVAPS 3 +#define DEVPOST 4 + +extern double eht[]; +extern double ebase[]; +extern int lfont[]; +extern int rfont[]; +extern int lclass[]; +extern int rclass[]; +extern int yyval; +extern int yylval; +extern int eqnreg; +extern double eqnht; +extern int lefteq, righteq; +extern int markline; /* 1 if this EQ/EN contains mark or lineup */ + +#define TBLSIZE 100 + +typedef struct s_tbl { + char *name; /* e.g., "max" or "sum" */ + char *cval; /* e.g., "\\f1max\\fP" */ + int ival; /* or SUM */ + struct s_tbl *next; +} tbl; + +extern char *spaceval; /* use in place of normal \x (for pic) */ + +#define String 01 +#define Macro 02 +#define File 04 +#define Char 010 +#define Free 040 + +typedef struct infile { + FILE *fin; + char *fname; + int lineno; +} Infile; + +typedef struct { /* input source */ + int type; /* Macro, String, File */ + char *sp; /* if String or Macro */ +} Src; + +extern Src src[], *srcp; /* input source stack */ + +#define MAXARGS 20 +typedef struct { /* argument stack */ + char *argstk[MAXARGS]; /* pointers to args */ + char *argval; /* points to space containing args */ +} Arg; + +typedef struct { /* font number and name */ + int ft; + char name[10]; +} Font; + +extern Font ftstack[]; +extern Font *ftp; + +extern int szstack[]; +extern int nszstack; + +extern Infile infile[10]; +extern Infile *curfile; + +extern tbl *lookup(tbl **tblp, char *name); +extern void install(tbl **tblp, char *name, char *cval, int ival); +extern tbl *keytbl[], *deftbl[], *restbl[], *ftunetbl[]; + +extern int salloc(void); +extern void sfree(int); +extern void nrwid(int, int, int); +extern char *ABSPS(int); +extern char *DPS(int, int); +extern int EFFPS(int); +extern double EM(double, int); +extern double REL(double, int); +extern char *pad(int); +extern void getstr(char *, int); +extern char *strsave(char *); + +extern int input(void); +extern int unput(int); +extern void pbstr(char *); +extern void error(int, char *); +extern void yyerror(char *); + +extern void diacrit(int, int); +extern void eqnbox(int, int, int); +extern void setfont(char *); +extern void font(int, int); +extern void globfont(void); +extern void fatbox(int); +extern void fromto(int, int, int); +extern void funny(int); +extern void integral(int, int, int); +extern void setintegral(void); +extern void pushsrc(int, char *); +extern void popsrc(void); +extern void putout(int); +extern void text(int, char *); +extern void subsup(int, int, int); +extern void bshiftb(int, int, int); +extern void shift2(int, int, int); +extern void setsize(char *); +extern void size(int, int); +extern void globsize(void); +#define sqrt esqrt +extern void sqrt(int); +extern void text(int, char *); +extern void boverb(int, int); +extern void lineup(int); +extern void mark(int); +extern void paren(int, int, int); +extern void move(int, int, int); +extern void pile(int); +extern int startcol(int); +extern void column(int, int); +extern void matrix(int); blob - /dev/null blob + 527e5e084d4fb8e08b685be74388fe76943d3b8b (mode 644) --- /dev/null +++ src/cmd/eqn/eqn.c @@ -0,0 +1,741 @@ +#define CONTIG 57346 +#define QTEXT 57347 +#define SPACE 57348 +#define THIN 57349 +#define TAB 57350 +#define MATRIX 57351 +#define LCOL 57352 +#define CCOL 57353 +#define RCOL 57354 +#define COL 57355 +#define ABOVE 57356 +#define MARK 57357 +#define LINEUP 57358 +#define SUM 57359 +#define INT 57360 +#define PROD 57361 +#define UNION 57362 +#define INTER 57363 +#define DEFINE 57364 +#define TDEFINE 57365 +#define NDEFINE 57366 +#define DELIM 57367 +#define GSIZE 57368 +#define GFONT 57369 +#define INCLUDE 57370 +#define IFDEF 57371 +#define DOTEQ 57372 +#define DOTEN 57373 +#define FROM 57374 +#define TO 57375 +#define OVER 57376 +#define SQRT 57377 +#define SUP 57378 +#define SUB 57379 +#define SIZE 57380 +#define FONT 57381 +#define ROMAN 57382 +#define ITALIC 57383 +#define BOLD 57384 +#define FAT 57385 +#define UP 57386 +#define DOWN 57387 +#define BACK 57388 +#define FWD 57389 +#define LEFT 57390 +#define RIGHT 57391 +#define DOT 57392 +#define DOTDOT 57393 +#define HAT 57394 +#define TILDE 57395 +#define BAR 57396 +#define LOWBAR 57397 +#define HIGHBAR 57398 +#define UNDER 57399 +#define VEC 57400 +#define DYAD 57401 +#define UTILDE 57402 + +#line 17 "/usr/local/plan9/src/cmd/eqn/eqn.y" +#include "e.h" + +int yylex(void); +extern int yyerrflag; +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 150 +#endif +#ifndef YYSTYPE +#define YYSTYPE int +#endif +YYSTYPE yylval; +YYSTYPE yyval; +#define YYEOFCODE 1 +#define YYERRCODE 2 + +#line 140 "/usr/local/plan9/src/cmd/eqn/eqn.y" + +short yyexca[] = +{-1, 0, + 1, 3, + -2, 0, +-1, 1, + 1, -1, + -2, 0, +}; +#define YYNPROD 90 +#define YYPRIVATE 57344 +#define YYLAST 469 +short yyact[] = +{ + 4, 103, 119, 45, 27, 118, 104, 2, 102, 41, + 42, 43, 44, 65, 80, 81, 79, 66, 67, 68, + 69, 70, 50, 49, 74, 75, 76, 77, 105, 73, + 40, 80, 81, 80, 81, 114, 61, 64, 54, 62, + 57, 58, 59, 60, 55, 56, 63, 78, 91, 92, + 82, 26, 83, 85, 86, 87, 88, 90, 51, 52, + 48, 124, 50, 49, 117, 25, 45, 117, 72, 71, + 80, 81, 113, 24, 45, 23, 61, 64, 54, 62, + 57, 58, 59, 60, 55, 56, 63, 53, 89, 100, + 84, 22, 96, 95, 106, 107, 108, 109, 99, 110, + 111, 41, 42, 43, 44, 45, 98, 115, 21, 94, + 93, 18, 130, 123, 17, 116, 121, 46, 112, 125, + 127, 128, 1, 129, 126, 0, 0, 45, 8, 7, + 9, 10, 11, 28, 41, 42, 43, 44, 0, 16, + 47, 12, 34, 13, 14, 15, 61, 64, 54, 62, + 57, 58, 59, 60, 55, 56, 63, 0, 0, 20, + 0, 0, 29, 33, 30, 31, 32, 19, 37, 39, + 38, 36, 35, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 97, 8, 7, 9, + 10, 11, 28, 41, 42, 43, 44, 0, 16, 47, + 12, 34, 13, 14, 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, + 0, 29, 33, 30, 31, 32, 19, 37, 39, 38, + 36, 35, 101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 6, 8, 7, 9, 10, 11, + 28, 41, 42, 43, 44, 0, 16, 5, 12, 34, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 29, + 33, 30, 31, 32, 19, 37, 39, 38, 36, 35, + 0, 0, 8, 7, 9, 10, 11, 28, 41, 42, + 43, 44, 6, 16, 47, 12, 34, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 0, 29, 33, 30, 31, + 32, 19, 37, 39, 38, 36, 35, 0, 0, 8, + 7, 9, 10, 11, 28, 41, 42, 43, 44, 6, + 16, 5, 12, 34, 13, 14, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 0, 0, 29, 33, 30, 31, 32, 19, 37, + 39, 38, 36, 35, 8, 7, 9, 10, 11, 28, + 41, 42, 43, 44, 0, 16, 6, 12, 34, 13, + 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 0, 0, 29, 33, + 30, 31, 32, 19, 37, 39, 38, 36, 35, 51, + 122, 48, 0, 50, 49, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 120, 49, 0, 61, 64, 54, + 62, 57, 58, 59, 60, 55, 56, 63, 61, 64, + 54, 62, 57, 58, 59, 60, 55, 56, 63 +}; +short yypact[] = +{ + 241,-1000, 288,-1000, 26,-1000, 335,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 380, 380, 380, 380, + 380, 32, 335, 380, 380, 380, 380,-1000,-1000, 66, +-1000,-1000,-1000, 66,-1000, 29, 66, 66, 66, 66, + 27,-1000,-1000,-1000,-1000, 26,-1000, 380, 380,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000, 124, 26, 96, 96, 96, + -14,-1000,-1000, 183, 96, 96, 96, 96, -53,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 335, +-1000, 26, -14, 380, 380, 380, 380,-1000, 380, 380, +-1000, 10, 91, 53, 288, -56, 408, -14, 397, 26, + 408, -14,-1000,-1000, -1,-1000,-1000, 335, 335,-1000, + 380,-1000, 380,-1000,-1000,-1000, 288, 50, -14, 26, +-1000 +}; +short yypgo[] = +{ + 0, 122, 6, 0, 117, 2, 116, 114, 111, 110, + 109, 108, 106, 98, 93, 92, 91, 89, 87, 75, + 73, 65, 51, 4, 47, 35, 16, 30, 1, 28 +}; +short yyr1[] = +{ + 0, 1, 1, 1, 2, 2, 2, 2, 4, 5, + 5, 6, 6, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 9, + 3, 10, 3, 12, 3, 13, 3, 3, 14, 3, + 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 24, 3, 11, 19, 20, 21, 22, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 16, 16, + 17, 17, 25, 25, 23, 29, 23, 27, 27, 27, + 27, 28, 28, 7, 8, 8, 8, 8, 26, 26 +}; +short yyr2[] = +{ + 0, 1, 1, 0, 1, 2, 2, 1, 2, 2, + 0, 2, 0, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 2, 2, 2, 2, 2, 0, + 5, 0, 4, 0, 5, 0, 4, 1, 0, 5, + 0, 4, 3, 2, 2, 2, 2, 2, 2, 1, + 0, 5, 1, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 1, 2, 4, 0, 6, 1, 1, 1, + 1, 1, 3, 2, 1, 1, 1, 2, 1, 1 +}; +short yychk[] = +{ +-1000, -1, -2, 2, -3, 16, 61, 5, 4, 6, + 7, 8, 17, 19, 20, 21, 15, -7, -8, 43, + 35, -11, -16, -19, -20, -21, -22, -23, 9, 38, + 40, 41, 42, 39, 18, 48, 47, 44, 46, 45, + -27, 10, 11, 12, 13, -3, -4, 16, 34, 37, + 36, 32, 33, -18, 52, 58, 59, 54, 55, 56, + 57, 50, 53, 60, 51, -2, -3, -3, -3, -3, + -3, 37, 36, -2, -3, -3, -3, -3, -24, -26, + 4, 5, -26, -26, 61, -26, -26, -26, -26, 61, + -26, -3, -3, -9, -10, -14, -15, 62, -12, -13, + -17, 49, 61, -28, -2, -29, -3, -3, -3, -3, + -3, -3, -26, 62, -25, -23, 62, 14, 61, -5, + 36, -6, 33, -5, 62, -23, -2, -28, -3, -3, + 62 +}; +short yydef[] = +{ + -2, -2, 1, 2, 4, 7, 0, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 0, 37, 0, 0, 0, 0, 0, 49, 50, 0, + 84, 85, 86, 0, 52, 0, 0, 0, 0, 0, + 0, 77, 78, 79, 80, 5, 6, 0, 0, 29, + 31, 38, 40, 44, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 0, 24, 25, 26, 27, + 28, 33, 35, 43, 45, 46, 47, 48, 0, 83, + 88, 89, 87, 68, 69, 53, 54, 55, 56, 0, + 75, 8, 23, 0, 0, 0, 0, 13, 0, 0, + 42, 0, 0, 0, 81, 0, 10, 32, 12, 41, + 10, 36, 70, 71, 0, 72, 74, 0, 0, 30, + 0, 39, 0, 34, 51, 73, 82, 0, 9, 11, + 76 +}; +short yytok1[] = +{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 61, 0, 62 +}; +short yytok2[] = +{ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60 +}; +long yytok3[] = +{ + 0 +}; +#define YYFLAG -1000 +#define YYERROR goto yyerrlab +#define YYACCEPT return(0) +#define YYABORT return(1) +#define yyclearin yychar = -1 +#define yyerrok yyerrflag = 0 + +#ifdef yydebug +#include "y.debug" +#else +#define yydebug 0 +char* yytoknames[1]; /* for debugging */ +char* yystates[1]; /* for debugging */ +#endif + +/* parser for yacc output */ + +int yynerrs = 0; /* number of errors */ +int yyerrflag = 0; /* error recovery flag */ + +char* +yytokname(int yyc) +{ + static char x[10]; + + if(yyc > 0 && yyc <= sizeof(yytoknames)/sizeof(yytoknames[0])) + if(yytoknames[yyc-1]) + return yytoknames[yyc-1]; + sprintf(x, "<%d>", yyc); + return x; +} + +char* +yystatname(int yys) +{ + static char x[10]; + + if(yys >= 0 && yys < sizeof(yystates)/sizeof(yystates[0])) + if(yystates[yys]) + return yystates[yys]; + sprintf(x, "<%d>\n", yys); + return x; +} + +long +yylex1(void) +{ + long yychar; + long *t3p; + int c; + + yychar = yylex(); + if(yychar <= 0) { + c = yytok1[0]; + goto out; + } + if(yychar < sizeof(yytok1)/sizeof(yytok1[0])) { + c = yytok1[yychar]; + goto out; + } + if(yychar >= YYPRIVATE) + if(yychar < YYPRIVATE+sizeof(yytok2)/sizeof(yytok2[0])) { + c = yytok2[yychar-YYPRIVATE]; + goto out; + } + for(t3p=yytok3;; t3p+=2) { + c = t3p[0]; + if(c == yychar) { + c = t3p[1]; + goto out; + } + if(c == 0) + break; + } + c = 0; + +out: + if(c == 0) + c = yytok2[1]; /* unknown char */ + if(yydebug >= 3) + printf("lex %.4lX %s\n", yychar, yytokname(c)); + return c; +} + +int +yyparse(void) +{ + struct + { + YYSTYPE yyv; + int yys; + } yys[YYMAXDEPTH], *yyp, *yypt; + short *yyxi; + int yyj, yym, yystate, yyn, yyg; + YYSTYPE save1, save2; + int save3, save4; + long yychar; + + save1 = yylval; + save2 = yyval; + save3 = yynerrs; + save4 = yyerrflag; + + yystate = 0; + yychar = -1; + yynerrs = 0; + yyerrflag = 0; + yyp = &yys[-1]; + goto yystack; + +ret0: + yyn = 0; + goto ret; + +ret1: + yyn = 1; + goto ret; + +ret: + yylval = save1; + yyval = save2; + yynerrs = save3; + yyerrflag = save4; + return yyn; + +yystack: + /* put a state and value onto the stack */ + if(yydebug >= 4) + printf("char %s in %s", yytokname(yychar), yystatname(yystate)); + + yyp++; + if(yyp >= &yys[YYMAXDEPTH]) { + yyerror("yacc stack overflow"); + goto ret1; + } + yyp->yys = yystate; + yyp->yyv = yyval; + +yynewstate: + yyn = yypact[yystate]; + if(yyn <= YYFLAG) + goto yydefault; /* simple state */ + if(yychar < 0) + yychar = yylex1(); + yyn += yychar; + if(yyn < 0 || yyn >= YYLAST) + goto yydefault; + yyn = yyact[yyn]; + if(yychk[yyn] == yychar) { /* valid shift */ + yychar = -1; + yyval = yylval; + yystate = yyn; + if(yyerrflag > 0) + yyerrflag--; + goto yystack; + } + +yydefault: + /* default state action */ + yyn = yydef[yystate]; + if(yyn == -2) { + if(yychar < 0) + yychar = yylex1(); + + /* look through exception table */ + for(yyxi=yyexca;; yyxi+=2) + if(yyxi[0] == -1 && yyxi[1] == yystate) + break; + for(yyxi += 2;; yyxi += 2) { + yyn = yyxi[0]; + if(yyn < 0 || yyn == yychar) + break; + } + yyn = yyxi[1]; + if(yyn < 0) + goto ret0; + } + if(yyn == 0) { + /* error ... attempt to resume parsing */ + switch(yyerrflag) { + case 0: /* brand new error */ + yyerror("syntax error"); + if(yydebug >= 1) { + printf("%s", yystatname(yystate)); + printf("saw %s\n", yytokname(yychar)); + } +yyerrlab: + yynerrs++; + + case 1: + case 2: /* incompletely recovered error ... try again */ + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + while(yyp >= yys) { + yyn = yypact[yyp->yys] + YYERRCODE; + if(yyn >= 0 && yyn < YYLAST) { + yystate = yyact[yyn]; /* simulate a shift of "error" */ + if(yychk[yystate] == YYERRCODE) + goto yystack; + } + + /* the current yyp has no shift onn "error", pop stack */ + if(yydebug >= 2) + printf("error recovery pops state %d, uncovers %d\n", + yyp->yys, (yyp-1)->yys ); + yyp--; + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1; + + case 3: /* no shift yet; clobber input char */ + if(yydebug >= YYEOFCODE) + printf("error recovery discards %s\n", yytokname(yychar)); + if(yychar == YYEOFCODE) + goto ret1; + yychar = -1; + goto yynewstate; /* try again in the same state */ + } + } + + /* reduction by production yyn */ + if(yydebug >= 2) + printf("reduce %d in:\n\t%s", yyn, yystatname(yystate)); + + yypt = yyp; + yyp -= yyr2[yyn]; + yyval = (yyp+1)->yyv; + yym = yyn; + + /* consult goto table to find next state */ + yyn = yyr1[yyn]; + yyg = yypgo[yyn]; + yyj = yyg + yyp->yys + 1; + + if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn) + yystate = yyact[yyg]; + switch(yym) { + +case 1: +#line 24 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ putout(yypt[-0].yyv); } break; +case 2: +#line 25 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ ERROR "syntax error" WARNING; } break; +case 3: +#line 26 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ eqnreg = 0; } break; +case 5: +#line 30 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ eqnbox(yypt[-1].yyv, yypt[-0].yyv, 0); } break; +case 6: +#line 31 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ eqnbox(yypt[-1].yyv, yypt[-0].yyv, 1); } break; +case 7: +#line 32 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ lineup(0); } break; +case 8: +#line 35 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = yypt[-0].yyv; lineup(1); } break; +case 9: +#line 38 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = yypt[-0].yyv; } break; +case 10: +#line 39 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = 0; } break; +case 11: +#line 42 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = yypt[-0].yyv; } break; +case 12: +#line 43 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = 0; } break; +case 13: +#line 46 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = yypt[-1].yyv; } break; +case 14: +#line 47 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ text(QTEXT, (char *) yypt[-0].yyv); } break; +case 15: +#line 48 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ text(CONTIG, (char *) yypt[-0].yyv); } break; +case 16: +#line 49 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ text(SPACE, (char *) 0); } break; +case 17: +#line 50 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ text(THIN, (char *) 0); } break; +case 18: +#line 51 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ text(TAB, (char *) 0); } break; +case 19: +#line 52 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ funny(SUM); } break; +case 20: +#line 53 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ funny(PROD); } break; +case 21: +#line 54 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ funny(UNION); } break; +case 22: +#line 55 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ funny(INTER); } break; +case 23: +#line 56 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ boverb(yypt[-2].yyv, yypt[-0].yyv); } break; +case 24: +#line 57 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ mark(yypt[-0].yyv); } break; +case 25: +#line 58 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ size(yypt[-1].yyv, yypt[-0].yyv); } break; +case 26: +#line 59 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ font(yypt[-1].yyv, yypt[-0].yyv); } break; +case 27: +#line 60 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ fatbox(yypt[-0].yyv); } break; +case 28: +#line 61 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ sqrt(yypt[-0].yyv); } break; +case 29: +#line 62 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 30: +#line 62 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ subsup(yypt[-4].yyv, yypt[-1].yyv, yypt[-0].yyv); } break; +case 31: +#line 63 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 32: +#line 63 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ subsup(yypt[-3].yyv, 0, yypt[-0].yyv); } break; +case 33: +#line 64 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 34: +#line 64 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ integral(yypt[-4].yyv, yypt[-1].yyv, yypt[-0].yyv); } break; +case 35: +#line 65 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 36: +#line 65 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ integral(yypt[-3].yyv, 0, yypt[-0].yyv); } break; +case 37: +#line 66 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ integral(yypt[-0].yyv, 0, 0); } break; +case 38: +#line 67 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 39: +#line 67 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ fromto(yypt[-4].yyv, yypt[-1].yyv, yypt[-0].yyv); } break; +case 40: +#line 68 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ps -= deltaps;} break; +case 41: +#line 68 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ fromto(yypt[-3].yyv, 0, yypt[-0].yyv); } break; +case 42: +#line 69 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ paren(yypt[-2].yyv, yypt[-1].yyv, yypt[-0].yyv); } break; +case 43: +#line 70 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ paren(yypt[-1].yyv, yypt[-0].yyv, 0); } break; +case 44: +#line 71 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ diacrit(yypt[-1].yyv, yypt[-0].yyv); } break; +case 45: +#line 72 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ move(FWD, yypt[-1].yyv, yypt[-0].yyv); } break; +case 46: +#line 73 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ move(UP, yypt[-1].yyv, yypt[-0].yyv); } break; +case 47: +#line 74 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ move(BACK, yypt[-1].yyv, yypt[-0].yyv); } break; +case 48: +#line 75 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ move(DOWN, yypt[-1].yyv, yypt[-0].yyv); } break; +case 49: +#line 76 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ pile(yypt[-0].yyv); ct = yypt[-0].yyv; } break; +case 50: +#line 77 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{yyval=ct;} break; +case 51: +#line 77 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ matrix(yypt[-3].yyv); ct = yypt[-3].yyv; } break; +case 52: +#line 80 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ setintegral(); } break; +case 53: +#line 83 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = atoi((char *) yypt[-1].yyv); } break; +case 54: +#line 84 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = atoi((char *) yypt[-1].yyv); } break; +case 55: +#line 85 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = atoi((char *) yypt[-1].yyv); } break; +case 56: +#line 86 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = atoi((char *) yypt[-1].yyv); } break; +case 57: +#line 88 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = HAT; } break; +case 58: +#line 89 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = VEC; } break; +case 59: +#line 90 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = DYAD; } break; +case 60: +#line 91 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = BAR; } break; +case 61: +#line 92 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = LOWBAR; } break; +case 62: +#line 93 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = HIGHBAR; } break; +case 63: +#line 94 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = UNDER; } break; +case 64: +#line 95 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = DOT; } break; +case 65: +#line 96 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = TILDE; } break; +case 66: +#line 97 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = UTILDE; } break; +case 67: +#line 98 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = DOTDOT; } break; +case 68: +#line 101 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = ((char *)yypt[-0].yyv)[0]; } break; +case 69: +#line 102 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = '{'; } break; +case 70: +#line 105 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = ((char *)yypt[-0].yyv)[0]; } break; +case 71: +#line 106 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = '}'; } break; +case 74: +#line 113 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ column(yypt[-3].yyv, DEFGAP); } break; +case 75: +#line 114 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{yyval=atoi((char*)yypt[-0].yyv);} break; +case 76: +#line 114 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ column(yypt[-5].yyv, yypt[-3].yyv); } break; +case 77: +#line 117 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = startcol(LCOL); } break; +case 78: +#line 118 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = startcol(CCOL); } break; +case 79: +#line 119 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = startcol(RCOL); } break; +case 80: +#line 120 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = startcol(COL); } break; +case 81: +#line 123 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ lp[ct++] = yypt[-0].yyv; } break; +case 82: +#line 124 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ lp[ct++] = yypt[-0].yyv; } break; +case 83: +#line 127 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ yyval = ps; setsize((char *) yypt[-0].yyv); } break; +case 84: +#line 130 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ static char R[]="R"; setfont(R); } break; +case 85: +#line 131 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ static char I[]="I"; setfont(I); } break; +case 86: +#line 132 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ static char B[]="B"; setfont(B); } break; +case 87: +#line 133 "/usr/local/plan9/src/cmd/eqn/eqn.y" +{ setfont((char *)yypt[-0].yyv); } break; + } + goto yystack; /* stack new state and value */ +} blob - /dev/null blob + 74796d7fa5b5e80b3d762d2d9dd3dd0b8b4922b6 (mode 644) --- /dev/null +++ src/cmd/eqn/eqn.y @@ -0,0 +1,140 @@ +%term CONTIG QTEXT SPACE THIN TAB +%term MATRIX LCOL CCOL RCOL COL ABOVE +%term MARK LINEUP +%term SUM INT PROD UNION INTER +%term DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT INCLUDE SPACE IFDEF +%term DOTEQ DOTEN + +%right FROM TO +%left OVER SQRT +%right SUP SUB +%right SIZE FONT ROMAN ITALIC BOLD FAT +%right UP DOWN BACK FWD +%left LEFT RIGHT +%right DOT DOTDOT HAT TILDE BAR LOWBAR HIGHBAR UNDER VEC DYAD UTILDE + +%{ +#include "e.h" + +int yylex(void); +%} + +%% + +stuff : eqn { putout($1); } + | error { ERROR "syntax error" WARNING; } /* should be SYNTAX */ + | { eqnreg = 0; } + ; + +eqn : box + | eqn box { eqnbox($1, $2, 0); } + | eqn lineupbox { eqnbox($1, $2, 1); } + | LINEUP { lineup(0); } + ; + +lineupbox: LINEUP box { $$ = $2; lineup(1); } + ; + +sbox : SUP box %prec SUP { $$ = $2; } + | %prec SUP { $$ = 0; } + ; + +tbox : TO box %prec TO { $$ = $2; } + | %prec FROM { $$ = 0; } + ; + +box : '{' eqn '}' { $$ = $2; } + | QTEXT { text(QTEXT, (char *) $1); } + | CONTIG { text(CONTIG, (char *) $1); } + | SPACE { text(SPACE, (char *) 0); } + | THIN { text(THIN, (char *) 0); } + | TAB { text(TAB, (char *) 0); } + | SUM { funny(SUM); } + | PROD { funny(PROD); } + | UNION { funny(UNION); } + | INTER { funny(INTER); } + | box OVER box { boverb($1, $3); } + | MARK box { mark($2); } + | size box %prec SIZE { size($1, $2); } + | font box %prec FONT { font($1, $2); } + | FAT box { fatbox($2); } + | SQRT box { sqrt($2); } + | box SUB {ps -= deltaps;} box sbox %prec SUB { subsup($1, $4, $5); } + | box SUP {ps -= deltaps;} box %prec SUP { subsup($1, 0, $4); } + | int SUB {ps -= deltaps;} box sbox %prec SUB { integral($1, $4, $5); } + | int SUP {ps -= deltaps;} box %prec SUP { integral($1, 0, $4); } + | int { integral($1, 0, 0); } + | box FROM {ps -= deltaps;} box tbox %prec FROM { fromto($1, $4, $5); } + | box TO {ps -= deltaps;} box %prec TO { fromto($1, 0, $4); } + | left eqn right { paren($1, $2, $3); } + | left eqn { paren($1, $2, 0); } + | box diacrit { diacrit($1, $2); } + | fwd box %prec UP { move(FWD, $1, $2); } + | up box %prec UP { move(UP, $1, $2); } + | back box %prec UP { move(BACK, $1, $2); } + | down box %prec UP { move(DOWN, $1, $2); } + | column { pile($1); ct = $1; } + | MATRIX {$$=ct;} '{' collist '}' { matrix($2); ct = $2; } + ; + +int : INT { setintegral(); } + ; + +fwd : FWD text { $$ = atoi((char *) $1); } ; +up : UP text { $$ = atoi((char *) $1); } ; +back : BACK text { $$ = atoi((char *) $1); } ; +down : DOWN text { $$ = atoi((char *) $1); } ; + +diacrit : HAT { $$ = HAT; } + | VEC { $$ = VEC; } + | DYAD { $$ = DYAD; } + | BAR { $$ = BAR; } + | LOWBAR { $$ = LOWBAR; } + | HIGHBAR { $$ = HIGHBAR; } + | UNDER { $$ = UNDER; } /* underbar */ + | DOT { $$ = DOT; } + | TILDE { $$ = TILDE; } + | UTILDE { $$ = UTILDE; } + | DOTDOT { $$ = DOTDOT; } /* umlaut = double dot */ + ; + +left : LEFT text { $$ = ((char *)$2)[0]; } + | LEFT '{' { $$ = '{'; } + ; + +right : RIGHT text { $$ = ((char *)$2)[0]; } + | RIGHT '}' { $$ = '}'; } + ; + +collist : column + | collist column + ; + +column : col '{' list '}' { column($1, DEFGAP); } + | col text {$$=atoi((char*)$2);} '{' list '}' { column($1, $3); } + ; + +col : LCOL { $$ = startcol(LCOL); } + | CCOL { $$ = startcol(CCOL); } + | RCOL { $$ = startcol(RCOL); } + | COL { $$ = startcol(COL); } + ; + +list : eqn { lp[ct++] = $1; } + | list ABOVE eqn { lp[ct++] = $3; } + ; + +size : SIZE text { $$ = ps; setsize((char *) $2); } + ; + +font : ROMAN { static char R[]="R"; setfont(R); } + | ITALIC { static char I[]="I"; setfont(I); } + | BOLD { static char B[]="B"; setfont(B); } + | FONT text { setfont((char *)$2); } + ; + +text : CONTIG + | QTEXT + ; + +%% blob - /dev/null blob + 7dd0b867c8182839e68a38b17be9ac64be49db5b (mode 644) --- /dev/null +++ src/cmd/eqn/eqnbox.c @@ -0,0 +1,24 @@ +#include "e.h" + +void eqnbox(int p1, int p2, int lu) +{ + double b, h; + char *sh; + extern char *IRspace; + + yyval = p1; + b = max(ebase[p1], ebase[p2]); + eht[yyval] = h = b + max(eht[p1]-ebase[p1], + eht[p2]-ebase[p2]); + ebase[yyval] = b; + dprintf(".\tS%d <- %d %d; b=%g, h=%g\n", yyval, p1, p2, b, h); + sh = pad(class[rclass[p1]][lclass[p2]]); + if (lu) { + printf(".nr %d \\w'\\*(%d%s'\n", p1, p1, sh); + printf(".ds %d \\h'|\\n(09u-\\n(%du'\\*(%d\n", p1, p1, p1); + } + printf(".as %d \"%s\\*(%d\n", yyval, sh, p2); + rfont[p1] = rfont[p2]; + rclass[p1] = rclass[p2]; + sfree(p2); +} blob - /dev/null blob + 3fb01119cc69e9a78b43df030fee71ec2a24fa2b (mode 644) --- /dev/null +++ src/cmd/eqn/font.c @@ -0,0 +1,70 @@ +# include "e.h" + +void setfont(char *ch1) +{ + yyval = ft; + if (strcmp(ch1, "I") == 0) { /* I and italic mean merely position 2 */ + *ch1 = '2'; + ft = ITAL; + } else if (strcmp(ch1, "B") == 0) { /* and similarly for B & bold */ + *ch1 = '3'; + ft = BLD; + } else if (strcmp(ch1, "R") == 0) { /* and R and roman */ + *ch1 = '1'; + ft = ROM; + } else { + ft = ROM; /* assume it's a roman style */ + } + ftp++; + if (ftp >= &ftstack[10]) + ERROR "font stack overflow (10)" FATAL; + ftp->ft = ft; + if (ch1[1] == 0) { /* 1-char name */ + ftp->name[0] = *ch1; + ftp->name[1] = '\0'; + } else + sprintf(ftp->name, "(%s", ch1); + dprintf(".\tsetfont %s %c\n", ch1, ft); +} + +void font(int p1, int p2) +{ + /* old font in p1, new in ft */ + yyval = p2; + lfont[yyval] = rfont[yyval] = ft==ITAL ? ITAL : ROM; + ftp--; + ft = p1; +} + +void globfont(void) +{ + char temp[20]; + + getstr(temp, sizeof(temp)); + yyval = eqnreg = 0; + if (strcmp(temp, "I") == 0 || strncmp(temp, "it", 2) == 0) { + ft = ITAL; + strcpy(temp, "2"); + } else if (strcmp(temp, "B") == 0 || strncmp(temp, "bo", 2) == 0) { + ft = BLD; + strcpy(temp, "3"); + } else if (strcmp(temp, "R") == 0 || strncmp(temp, "ro", 2) == 0) { + ft = ROM; + strcpy(temp, "1"); + } else { + ft = ROM; /* assume it's a roman style */ + } + ftstack[0].ft = ft; + if (temp[1] == 0) /* 1-char name */ + strcpy(ftstack[0].name, temp); + else + sprintf(ftstack[0].name, "(%.2s", temp); +} + +void fatbox(int p) +{ + extern double Fatshift; + + yyval = p; + printf(".ds %d \\*(%d\\h'-\\w'\\*(%d'u+%gm'\\*(%d\n", p, p, p, Fatshift, p); +} blob - /dev/null blob + 2d4d7f7445799fbf67533e62185ec673861937ea (mode 644) --- /dev/null +++ src/cmd/eqn/fromto.c @@ -0,0 +1,52 @@ +# include "e.h" + +void fromto(int p1, int p2, int p3) +{ + double b, h1, b1, t; + int subps; + + yyval = salloc(); + lfont[yyval] = rfont[yyval] = 0; + h1 = eht[yyval] = eht[p1]; + b1 = ebase[p1]; + b = 0; + subps = ps; + ps += deltaps; + nrwid(p1, ps, p1); + printf(".nr %d \\n(%d\n", yyval, p1); + if (p2 > 0) { + nrwid(p2, subps, p2); + printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2); + eht[yyval] += eht[p2]; + b = eht[p2]; + } + if (p3 > 0) { + nrwid(p3, subps, p3); + printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyval, yyval, p3); + eht[yyval] += eht[p3]; + } + printf(".ds %d ", yyval); /* bottom of middle box */ + if (p2 > 0) { + t = eht[p2]-ebase[p2]+b1; + printf("\\v'%gm'\\h'\\n(%du-\\n(%du/2u'%s\\*(%d%s", + REL(t,ps), yyval, p2, DPS(ps,subps), p2, DPS(subps,ps)); + printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%gm'\\\n", + yyval, p2, REL(-t,ps)); + } + printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du/2u'\\\n", + yyval, p1, p1, yyval, p1); + if (p3 >0) { + t = h1-b1+ebase[p3]; + printf("\\v'%gm'\\h'-\\n(%du-\\n(%du/2u'%s\\*(%d%s\\h'\\n(%du-\\n(%du/2u'\\v'%gm'\\\n", + REL(-t,ps), yyval, p3, DPS(ps,subps), p3, DPS(subps,ps), yyval, p3, REL(t,ps)); + } + printf("\n"); + ebase[yyval] = b + b1; + dprintf(".\tS%d <- %d from %d to %d; h=%g b=%g\n", + yyval, p1, p2, p3, eht[yyval], ebase[yyval]); + sfree(p1); + if (p2 > 0) + sfree(p2); + if (p3 > 0) + sfree(p3); +} blob - /dev/null blob + 85955fceb4cfb617b3978f123204bd82248ff8fb (mode 644) --- /dev/null +++ src/cmd/eqn/funny.c @@ -0,0 +1,30 @@ +#include "e.h" +#include "y.tab.h" + +extern int Funnyps; +extern double Funnyht, Funnybase; + +void funny(int n) +{ + char *f = 0; + + yyval = salloc(); + switch (n) { + case SUM: + f = lookup(deftbl, "sum_def")->cval; break; + case UNION: + f = lookup(deftbl, "union_def")->cval; break; + case INTER: /* intersection */ + f = lookup(deftbl, "inter_def")->cval; break; + case PROD: + f = lookup(deftbl, "prod_def")->cval; break; + default: + ERROR "funny type %d in funny", n FATAL; + } + printf(".ds %d %s\n", yyval, f); + eht[yyval] = EM(1.0, ps+Funnyps) - EM(Funnyht, ps); + ebase[yyval] = EM(Funnybase, ps); + dprintf(".\tS%d <- %s; h=%g b=%g\n", + yyval, f, eht[yyval], ebase[yyval]); + lfont[yyval] = rfont[yyval] = ROM; +} blob - /dev/null blob + 6ca1a1da6838041e6ec59f16fe525e992cbaa7de (mode 644) --- /dev/null +++ src/cmd/eqn/glob.c @@ -0,0 +1,35 @@ +#include "e.h" + + /* YOU MAY WANT TO CHANGE THIS */ +char *typesetter = "post"; /* type of typesetter today */ +int ttype = DEVPOST; +int minsize = 4; /* min size it can handle */ + + +int dbg; /* debugging print if non-zero */ +int lp[200]; /* stack for things like piles and matrices */ +int ct; /* pointer to lp */ +int used[100]; /* available registers */ +int ps; /* default init point size */ +int deltaps = 3; /* default change in ps */ +int dps_set = 0; /* 1 => -p option used */ +int gsize = 10; /* default initial point size */ +int ft = '2'; +Font ftstack[10] = { '2', "2" }; /* bottom is global font */ +Font *ftp = ftstack; +int szstack[10]; /* non-zero if absolute size set at this level */ +int nszstack = 0; +int display = 0; /* 1=>display, 0=>.EQ/.EN */ + +int synerr; /* 1 if syntax err in this eqn */ +double eht[100]; /* height in ems at gsize */ +double ebase[100]; /* base: where one enters above bottom */ +int lfont[100]; /* leftmost and rightmost font associated with this thing */ +int rfont[100]; +int lclass[100]; /* leftmost and rightmost class associated with this thing */ +int rclass[100]; +int eqnreg; /* register where final string appears */ +double eqnht; /* final height of equation */ +int lefteq = '\0'; /* left in-line delimiter */ +int righteq = '\0'; /* right in-line delimiter */ +int markline = 0; /* 1 if this EQ/EN contains mark; 2 if lineup */ blob - /dev/null blob + 3b8656714a381fea23ca2dc8397c3cdb6d624c4d (mode 644) --- /dev/null +++ src/cmd/eqn/input.c @@ -0,0 +1,289 @@ +#include "e.h" +#include "y.tab.h" +#include +#include + +Infile infile[10]; +Infile *curfile = infile; + +#define MAXSRC 50 +Src src[MAXSRC]; /* input source stack */ +Src *srcp = src; + +extern int getarg(char *); +extern void eprint(void); + +void pushsrc(int type, char *ptr) /* new input source */ +{ + if (++srcp >= src + MAXSRC) + ERROR "inputs nested too deep" FATAL; + srcp->type = type; + srcp->sp = ptr; + if (dbg > 1) { + printf("\n%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("push file %s\n", ((Infile *)ptr)->fname); + break; + case Macro: + printf("push macro <%s>\n", ptr); + break; + case Char: + printf("push char <%c>\n", *ptr); + break; + case String: + printf("push string <%s>\n", ptr); + break; + case Free: + printf("push free <%s>\n", ptr); + break; + default: + ERROR "pushed bad type %d\n", srcp->type FATAL; + } + } +} + +void popsrc(void) /* restore an old one */ +{ + if (srcp <= src) + ERROR "too many inputs popped" FATAL; + if (dbg > 1) { + printf("%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("pop file\n"); + break; + case Macro: + printf("pop macro\n"); + break; + case Char: + printf("pop char <%c>\n", *srcp->sp); + break; + case String: + printf("pop string\n"); + break; + case Free: + printf("pop free\n"); + break; + default: + ERROR "pop weird input %d\n", srcp->type FATAL; + } + } + srcp--; +} + +Arg args[10]; /* argument frames */ +Arg *argfp = args; /* frame pointer */ +int argcnt; /* number of arguments seen so far */ + +void dodef(tbl *stp) /* collect args and switch input to defn */ +{ + int i, len; + char *p; + Arg *ap; + + ap = argfp+1; + if (ap >= args+10) + ERROR "more than arguments\n" FATAL; + argcnt = 0; + if (input() != '(') + ERROR "disaster in dodef\n"FATAL; + if (ap->argval == 0) + ap->argval = malloc(1000); + for (p = ap->argval; (len = getarg(p)) != -1; p += len) { + ap->argstk[argcnt++] = p; + if (input() == ')') + break; + } + for (i = argcnt; i < MAXARGS; i++) + ap->argstk[i] = ""; + if (dbg) + for (i = 0; i < argcnt; i++) + printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); + argfp = ap; + pushsrc(Macro, stp->cval); +} + +getarg(char *p) /* pick up single argument, store in p, return length */ +{ + int n, c, npar; + + n = npar = 0; + for ( ;; ) { + c = input(); + if (c == EOF) + ERROR "end of file in getarg!\n" FATAL; + if (npar == 0 && (c == ',' || c == ')')) + break; + if (c == '"') /* copy quoted stuff intact */ + do { + *p++ = c; + n++; + } while ((c = input()) != '"' && c != EOF); + else if (c == '(') + npar++; + else if (c == ')') + npar--; + n++; + *p++ = c; + } + *p = 0; + unput(c); + return(n + 1); +} + +#define PBSIZE 2000 +char pbuf[PBSIZE]; /* pushback buffer */ +char *pb = pbuf-1; /* next pushed back character */ + +char ebuf[200]; /* collect input here for error reporting */ +char *ep = ebuf; + +input(void) +{ + register int c = 0; + + loop: + switch (srcp->type) { + case File: + c = getc(curfile->fin); + if (c == EOF) { + if (curfile == infile) + break; + if (curfile->fin != stdin) { + fclose(curfile->fin); + free(curfile->fname); /* assumes allocated */ + } + curfile--; + printf(".lf %d %s\n", curfile->lineno, curfile->fname); + popsrc(); + goto loop; + } + if (c == '\n') + curfile->lineno++; + break; + case Char: + if (pb >= pbuf) { + c = *pb--; + popsrc(); + break; + } else { /* can't happen? */ + popsrc(); + goto loop; + } + case String: + c = *srcp->sp++; + if (c == '\0') { + popsrc(); + goto loop; + } else { + if (*srcp->sp == '\0') /* empty, so pop */ + popsrc(); + break; + } + case Macro: + c = *srcp->sp++; + if (c == '\0') { + if (--argfp < args) + ERROR "argfp underflow" FATAL; + popsrc(); + goto loop; + } else if (c == '$' && isdigit(*srcp->sp)) { + int n = 0; + while (isdigit(*srcp->sp)) + n = 10 * n + *srcp->sp++ - '0'; + if (n > 0 && n <= MAXARGS) + pushsrc(String, argfp->argstk[n-1]); + goto loop; + } + break; + case Free: /* free string */ + free(srcp->sp); + popsrc(); + goto loop; + } + if (ep >= ebuf + sizeof ebuf) + ep = ebuf; + *ep++ = c; + return c; +} + + +unput(int c) +{ + if (++pb >= pbuf + sizeof pbuf) + ERROR "pushback overflow\n"FATAL; + if (--ep < ebuf) + ep = ebuf + sizeof(ebuf) - 1; + *pb = c; + pushsrc(Char, pb); + return c; +} + +void pbstr(char *s) +{ + pushsrc(String, s); +} + +void error(int die, char *s) +{ + extern char *cmdname; + + if (synerr) + return; + fprintf(stderr, "%s: ", cmdname); + fprintf(stderr, s); + if (errno > 0) + perror("???"); + if (curfile->fin) + fprintf(stderr, " near %s:%d", + curfile->fname, curfile->lineno+1); + fprintf(stderr, "\n"); + eprint(); + synerr = 1; + errno = 0; + if (die) { + if (dbg) + abort(); + else + exit(1); + } +} + +void yyerror(char *s) +{ + error(0, s); /* temporary */ +} + +char errbuf[200]; + +void eprint(void) /* try to print context around error */ +{ + char *p, *q; + + if (ep == ebuf) + return; /* no context */ + p = ep - 1; + if (p > ebuf && *p == '\n') + p--; + for ( ; p >= ebuf && *p != '\n'; p--) + ; + while (*p == '\n') + p++; + fprintf(stderr, " context is\n\t"); + for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) + ; + while (p < q) + putc(*p++, stderr); + fprintf(stderr, " >>> "); + while (p < ep) + putc(*p++, stderr); + fprintf(stderr, " <<< "); + while (pb >= pbuf) + putc(*pb--, stderr); + if (curfile->fin) + fgets(ebuf, sizeof ebuf, curfile->fin); + fprintf(stderr, "%s", ebuf); + pbstr("\n.EN\n"); /* safety first */ + ep = ebuf; +} blob - /dev/null blob + 2b1c9e3f306fa82f402d9b932e389d97e9f69e85 (mode 644) --- /dev/null +++ src/cmd/eqn/integral.c @@ -0,0 +1,30 @@ +#include "e.h" +#include "y.tab.h" + +extern int Intps; +extern double Intht, Intbase, Int1h, Int1v, Int2h, Int2v; + +void integral(int p, int p1, int p2) +{ + if (p1 != 0) + printf(".ds %d \\h'%gm'\\v'%gm'\\*(%d\\v'%gm'\n", p1, -Int1h, Int1v, p1, -Int1v); + if (p2 != 0) + printf(".ds %d \\v'%gm'\\h'%gm'\\*(%d\\v'%gm'\n", p2, -Int2v, Int2h, p2, Int2v); + if (p1 != 0 && p2 != 0) + shift2(p, p1, p2); + else if (p1 != 0) + bshiftb(p, SUB, p1); + else if (p2 != 0) + bshiftb(p, SUP, p2); + dprintf(".\tintegral: S%d; h=%g b=%g\n", p, eht[p], ebase[p]); + lfont[p] = ROM; +} + +void setintegral(void) +{ + yyval = salloc(); + printf(".ds %d %s\n", yyval, lookup(deftbl, "int_def")->cval); + eht[yyval] = EM(Intht, ps+Intps); + ebase[yyval] = EM(Intbase, ps); + lfont[yyval] = rfont[yyval] = ROM; +} blob - /dev/null blob + e535b8699b5551b117ec024618ac53046aae1d5e (mode 644) --- /dev/null +++ src/cmd/eqn/lex.c @@ -0,0 +1,265 @@ +#include "e.h" +#include "y.tab.h" +#include + +#define SSIZE 1000 +char token[SSIZE]; +int sp; + +void space(void); +void dodef(tbl *); +void define(int); +void ifdef(void); +void include(void); +void delim(void); + +yylex(void) +{ + register int c; + tbl *tp; + + begin: + while ((c = input()) == ' ' || c == '\n' || c == '\t') + ; + yylval = c; + switch (c) { + case EOF: + ERROR "unexpected end of input inside equation" WARNING; + return(EOF); + case '~': + return(SPACE); + case '^': + return(THIN); + /* case '\t': + return(TAB); + */ + case '{': + return('{'); + case '}': + return('}'); + case '"': + for (sp = 0; (c=input())!='"' && c != '\n'; ) { + if (c == '\\') + if ((c = input()) != '"') + token[sp++] = '\\'; + token[sp++] = c; + if (sp >= SSIZE) + ERROR "quoted string %.20s... too long", token FATAL; + } + token[sp] = '\0'; + yylval = (int) &token[0]; + if (c == '\n') + ERROR "missing \" in %.20s", token WARNING; + return(QTEXT); + } + if (!display && c == righteq) + return(EOF); + + unput(c); + getstr(token, SSIZE); + dprintf(".\tlex token = |%s|\n", token); + if ((tp = lookup(deftbl, token)) != NULL) { /* defined term */ + c = input(); + unput(c); + if (c == '(') /* macro with args */ + dodef(tp); + else { /* no args */ + unput(' '); + pbstr(tp->cval); + dprintf(".\tfound %s|=%s|\n", token, tp->cval); + } + goto begin; + } + + if ((tp = lookup(keytbl, token)) == NULL) /* not a keyword */ + return CONTIG; + + switch (tp->ival) { /* some kind of keyword */ + case DEFINE: case TDEFINE: case NDEFINE: + define(tp->ival); + break; + case IFDEF: + ifdef(); + break; + case DELIM: + delim(); + break; + case GSIZE: + globsize(); + break; + case GFONT: + globfont(); + break; + case INCLUDE: + include(); + break; + case SPACE: + space(); + break; + case DOTEQ: + /* .EQ inside equation -- should warn if at bottom level */ + break; + case DOTEN: + if (curfile == infile) + return EOF; + /* else ignore nested .EN */ + break; + default: + return tp->ival; + } + goto begin; +} + +void getstr(char *s, int n) +{ + register int c; + register char *p; + + p = s; + while ((c = input()) == ' ' || c == '\n') + ; + if (c == EOF) { + *s = 0; + return; + } + while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}' + && c != '"' && c != '~' && c != '^') { + if (!display && c == righteq) + break; + if (c == '(' && p > s) { /* might be defined(...) */ + *p = '\0'; + if (lookup(deftbl, s) != NULL) + break; + } + if (c == '\\') + if ((c = input()) != '"') + *p++ = '\\'; + *p++ = c; + if (--n <= 0) + ERROR "token %.20s... too long", s FATAL; + c = input(); + } + unput(c); + *p = '\0'; + yylval = (int) s; +} + +cstr(char *s, int quote, int maxs) +{ + int del, c, i; + + s[0] = 0; + while ((del=input()) == ' ' || del == '\t') + ; + if (quote) + for (i=0; (c=input()) != del && c != EOF;) { + s[i++] = c; + if (i >= maxs) + return(1); /* disaster */ + } + else { + if (del == '\n') + return(1); + s[0] = del; + for (i=1; (c=input())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) { + s[i++] = c; + if (i >= maxs) + return(1); /* disaster */ + } + } + s[i] = '\0'; + if (c == EOF) + ERROR "Unexpected end of input at %.20s", s FATAL; + return(0); +} + +void define(int type) +{ + char *p1, *p2; + extern int ftune(char *, char *); + + getstr(token, SSIZE); /* get name */ + if (type != DEFINE) { + cstr(token, 1, SSIZE); /* skip the definition too */ + return; + } + p1 = strsave(token); + if (cstr(token, 1, SSIZE)) + ERROR "Unterminated definition at %.20s", token FATAL; + if (lookup(ftunetbl, p1) != NULL) { /* double tuning param */ + dprintf(".\ttune %s %s\n", p1, token); + ftune(p1, token); + } else { + p2 = strsave(token); + install(deftbl, p1, p2, 0); + dprintf(".\tname %s defined as %s\n", p1, p2); + } +} + +void ifdef(void) /* do body if name is defined */ +{ + char name[100], *p; + + getstr(name, sizeof(name)); /* get name */ + cstr(token, 1, SSIZE); /* and body */ + if (lookup(deftbl, name) != NULL) { /* found it */ + p = strsave(token); + pushsrc(Free, p); + pushsrc(String, p); + } +} + +char *spaceval = NULL; + +void space(void) /* collect line of form "space amt" to replace \x in output */ +{ + getstr(token, SSIZE); + spaceval = strsave(token); + dprintf(".\tsetting spaceval to %s\n", token); +} + +char *strsave(char *s) +{ + register char *q; + + q = malloc(strlen(s)+1); + if (q == NULL) + ERROR "out of space in strsave on %s", s FATAL; + strcpy(q, s); + return(q); +} + +void include(void) +{ + char name[100]; + FILE *fin; + int c; + extern int errno; + + while ((c = input()) == ' ') + ; + unput(c); + cstr(name, c == '"', sizeof(name)); /* gets it quoted or not */ + if ((fin = fopen(name, "r")) == NULL) + ERROR "can't open file %s", name FATAL; + errno = 0; + curfile++; + curfile->fin = fin; + curfile->fname = strsave(name); + curfile->lineno = 0; + printf(".lf 1 %s\n", curfile->fname); + pushsrc(File, curfile->fname); +} + +void delim(void) +{ + yyval = eqnreg = 0; + if (cstr(token, 0, SSIZE)) + ERROR "Bizarre delimiters" FATAL; + lefteq = token[0]; + righteq = token[1]; + if (!isprint(lefteq) || !isprint(righteq)) + ERROR "Bizarre delimiters" FATAL; + if (lefteq == 'o' && righteq == 'f') + lefteq = righteq = '\0'; +} blob - /dev/null blob + 4eb94373641f98f847a283e7e0656120afe87e7d (mode 644) --- /dev/null +++ src/cmd/eqn/lookup.c @@ -0,0 +1,219 @@ +#include "e.h" +#include "y.tab.h" + +tbl *keytbl[TBLSIZE]; /* key words */ +tbl *restbl[TBLSIZE]; /* reserved words */ +tbl *deftbl[TBLSIZE]; /* user-defined names */ + +struct keyword { + char *key; + int keyval; +} keyword[] ={ + "sub", SUB, + "sup", SUP, + ".EN", DOTEN, + ".EQ", DOTEQ, + "from", FROM, + "to", TO, + "sum", SUM, + "hat", HAT, + "vec", VEC, + "dyad", DYAD, + "dot", DOT, + "dotdot", DOTDOT, + "bar", BAR, + "lowbar", LOWBAR, + "highbar", HIGHBAR, + "tilde", TILDE, + "utilde", UTILDE, + "under", UNDER, + "prod", PROD, + "int", INT, + "integral", INT, + "union", UNION, + "inter", INTER, + "matrix", MATRIX, + "col", COL, + "lcol", LCOL, + "ccol", CCOL, + "rcol", RCOL, + "pile", COL, /* synonyms ... */ + "lpile", LCOL, + "cpile", CCOL, + "rpile", RCOL, + "over", OVER, + "sqrt", SQRT, + "above", ABOVE, + "size", SIZE, + "font", FONT, + "fat", FAT, + "roman", ROMAN, + "italic", ITALIC, + "bold", BOLD, + "left", LEFT, + "right", RIGHT, + "delim", DELIM, + "define", DEFINE, + "tdefine", DEFINE, + "ndefine", NDEFINE, + "ifdef", IFDEF, + "gsize", GSIZE, + ".gsize", GSIZE, + "gfont", GFONT, + "include", INCLUDE, + "copy", INCLUDE, + "space", SPACE, + "up", UP, + "down", DOWN, + "fwd", FWD, + "back", BACK, + "mark", MARK, + "lineup", LINEUP, + 0, 0 +}; + +struct resword { + char *res; + char *resval; +} resword[] ={ + ">=", "\\(>=", + "<=", "\\(<=", + "==", "\\(==", + "!=", "\\(!=", + "+-", "\\(+-", + "->", "\\(->", + "<-", "\\(<-", + "inf", "\\(if", + "infinity", "\\(if", + "partial", "\\(pd", + "half", "\\f1\\(12\\fP", + "prime", "\\f1\\v'.5m'\\s+3\\(fm\\s-3\\v'-.5m'\\fP", + "dollar", "\\f1$\\fP", + "nothing", "", + "times", "\\(mu", + "del", "\\(gr", + "grad", "\\(gr", + "approx", "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'", + "cdot", "\\v'-.3m'.\\v'.3m'", + "...", "\\v'-.25m'\\ .\\ .\\ .\\ \\v'.25m'", + ",...,", "\\f1,\\fP\\ .\\ .\\ .\\ \\f1,\\fP\\|", + "alpha", "α", + "ALPHA", "Α", + "beta", "β", + "BETA", "Β", + "gamma", "γ", + "GAMMA", "Γ", + "delta", "δ", + "DELTA", "Δ", + "epsilon", "ε", + "EPSILON", "Ε", + "omega", "ω", + "OMEGA", "Ω", + "lambda", "λ", + "LAMBDA", "Λ", + "mu", "μ", + "MU", "Μ", + "nu", "ν", + "NU", "Ν", + "theta", "θ", + "THETA", "Θ", + "phi", "φ", + "PHI", "Φ", + "pi", "π", + "PI", "Π", + "sigma", "σ", + "SIGMA", "Σ", + "xi", "ξ", + "XI", "Ξ", + "zeta", "ζ", + "ZETA", "Ζ", + "iota", "ι", + "IOTA", "Ι", + "eta", "η", + "ETA", "Η", + "kappa", "κ", + "KAPPA", "Κ", + "rho", "ρ", + "RHO", "Ρ", + "tau", "τ", + "TAU", "Τ", + "omicron", "ο", + "OMICRON", "Ο", + "upsilon", "υ", + "UPSILON", "Υ", + "psi", "ψ", + "PSI", "Ψ", + "chi", "χ", + "CHI", "Χ", + "and", "\\f1and\\fP", + "for", "\\f1for\\fP", + "if", "\\f1if\\fP", + "Re", "\\f1Re\\fP", + "Im", "\\f1Im\\fP", + "sin", "\\f1sin\\fP", + "cos", "\\f1cos\\fP", + "tan", "\\f1tan\\fP", + "arc", "\\f1arc\\fP", + "sinh", "\\f1sinh\\fP", + "coth", "\\f1coth\\fP", + "tanh", "\\f1tanh\\fP", + "cosh", "\\f1cosh\\fP", + "lim", "\\f1lim\\fP", + "log", "\\f1log\\fP", + "ln", "\\f1ln\\fP", + "max", "\\f1max\\fP", + "min", "\\f1min\\fP", + "exp", "\\f1exp\\fP", + "det", "\\f1det\\fP", + 0, 0 +}; + +int hash(char *s) +{ + register unsigned int h; + + for (h = 0; *s != '\0'; ) + h += *s++; + h %= TBLSIZE; + return h; +} + +tbl *lookup(tbl **tblp, char *name) /* find name in tbl */ +{ + register tbl *p; + + for (p = tblp[hash(name)]; p != NULL; p = p->next) + if (strcmp(name, p->name) == 0) + return(p); + return(NULL); +} + +void install(tbl **tblp, char *name, char *cval, int ival) /* install name, vals in tblp */ +{ + register tbl *p; + int h; + + if ((p = lookup(tblp, name)) == NULL) { + p = (tbl *) malloc(sizeof(tbl)); + if (p == NULL) + ERROR "out of space in install" FATAL; + h = hash(name); /* bad visibility here */ + p->name = name; + p->next = tblp[h]; + tblp[h] = p; + } + p->cval = cval; + p->ival = ival; +} + +void init_tbl(void) /* initialize tables */ +{ + int i; + extern int init_tune(void); + + for (i = 0; keyword[i].key != NULL; i++) + install(keytbl, keyword[i].key, (char *) 0, keyword[i].keyval); + for (i = 0; resword[i].res != NULL; i++) + install(restbl, resword[i].res, resword[i].resval, 0); + init_tune(); /* tuning table done in tuning.c */ +} blob - /dev/null blob + a06fd165acd404abf8339c3ecf3a5b35b83341a7 (mode 644) --- /dev/null +++ src/cmd/eqn/main.c @@ -0,0 +1,333 @@ +#include "e.h" + +#define MAXLINE 3600 /* maximum input line */ + +char *version = "version Oct 24, 1991"; + +char in[MAXLINE]; /* input buffer */ +int noeqn; +char *cmdname; + +int yyparse(void); +void settype(char *); +int getdata(void); +int getline(char *); +#define inline einline +void inline(void); +void init(void); +void init_tbl(void); + +void +main(int argc, char *argv[]) +{ + char *p, buf[20]; + + cmdname = argv[0]; + if (p = getenv("TYPESETTER")) + typesetter = p; + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + + case 'd': + if (argv[1][2] == '\0') { + dbg++; + printf("...\teqn %s\n", version); + } else { + lefteq = argv[1][2]; + righteq = argv[1][3]; + } + break; + case 's': szstack[0] = gsize = atoi(&argv[1][2]); break; + case 'p': deltaps = atoi(&argv[1][2]); dps_set = 1; break; + case 'm': minsize = atoi(&argv[1][2]); break; + case 'f': strcpy(ftstack[0].name,&argv[1][2]); break; + case 'e': noeqn++; break; + case 'T': typesetter = &argv[1][2]; break; + default: + fprintf(stderr, "%s: unknown option %s\n", cmdname, argv[1]); + break; + } + argc--; + argv++; + } + settype(typesetter); + sprintf(buf, "\"%s\"", typesetter); + install(deftbl, strsave(typesetter), strsave(buf), 0); + init_tbl(); /* install other keywords in tables */ + curfile = infile; + pushsrc(File, curfile->fname); + if (argc <= 1) { + curfile->fin = stdin; + curfile->fname = strsave("-"); + getdata(); + } else + while (argc-- > 1) { + if (strcmp(*++argv, "-") == 0) + curfile->fin = stdin; + else if ((curfile->fin = fopen(*argv, "r")) == NULL) + ERROR "can't open file %s", *argv FATAL; + curfile->fname = strsave(*argv); + getdata(); + if (curfile->fin != stdin) + fclose(curfile->fin); + } + exit(0); +} + +void settype(char *s) /* initialize data for particular typesetter */ + /* the minsize could profitably come from the */ +{ /* troff description file /usr/lib/font/dev.../DESC.out */ + if (strcmp(s, "202") == 0) + { minsize = 5; ttype = DEV202; } + else if (strcmp(s, "aps") == 0) + { minsize = 5; ttype = DEVAPS; } + else if (strcmp(s, "cat") == 0) + { minsize = 6; ttype = DEVCAT; } + else if (strcmp(s, "post") == 0) + { minsize = 4; ttype = DEVPOST; } + else + { minsize = 5; ttype = DEV202; } +} + +getdata(void) +{ + int i, type, ln; + char fname[100]; + extern int errno; + + errno = 0; + curfile->lineno = 0; + printf(".lf 1 %s\n", curfile->fname); + while ((type = getline(in)) != EOF) { + if (in[0] == '.' && in[1] == 'E' && in[2] == 'Q') { + for (i = 11; i < 100; i++) + used[i] = 0; + printf("%s", in); + if (markline) { /* turn off from last time */ + printf(".nr MK 0\n"); + markline = 0; + } + display = 1; + init(); + yyparse(); + if (eqnreg > 0) { + if (markline) + printf(".nr MK %d\n", markline); /* for -ms macros */ + printf(".if %gm>\\n(.v .ne %gm\n", eqnht, eqnht); + printf(".rn %d 10\n", eqnreg); + if (!noeqn) + printf("\\&\\*(10\n"); + } + printf(".EN"); + while (putchar(input()) != '\n') + ; + printf(".lf %d\n", curfile->lineno+1); + } + else if (type == lefteq) + inline(); + else if (in[0] == '.' && in[1] == 'l' && in[2] == 'f') { + if (sscanf(in+3, "%d %s", &ln, fname) == 2) { + free(curfile->fname); + printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = strsave(fname)); + } else + printf(".lf %d\n", curfile->lineno = ln); + } else + printf("%s", in); + } + return(0); +} + +getline(char *s) +{ + register c; + + while ((c=input()) != '\n' && c != EOF && c != lefteq) { + if (s >= in+MAXLINE) { + ERROR "input line too long: %.20s\n", in WARNING; + in[MAXLINE] = '\0'; + break; + } + *s++ = c; + } + if (c != lefteq) + *s++ = c; + *s = '\0'; + return(c); +} + +void inline(void) +{ + int ds, n, sz1 = 0; + + n = curfile->lineno; + if (szstack[0] != 0) + printf(".nr %d \\n(.s\n", sz1 = salloc()); + ds = salloc(); + printf(".rm %d \n", ds); + display = 0; + do { + if (*in) + printf(".as %d \"%s\n", ds, in); + init(); + yyparse(); + if (eqnreg > 0) { + printf(".as %d \\*(%d\n", ds, eqnreg); + sfree(eqnreg); + printf(".lf %d\n", curfile->lineno+1); + } + } while (getline(in) == lefteq); + if (*in) + printf(".as %d \"%s", ds, in); + if (sz1) + printf("\\s\\n(%d", sz1); + printf("\\*(%d\n", ds); + printf(".lf %d\n", curfile->lineno+1); + if (curfile->lineno > n+3) + fprintf(stderr, "eqn warning: multi-line %c...%c, file %s:%d,%d\n", + lefteq, righteq, curfile->fname, n, curfile->lineno); + sfree(ds); + if (sz1) sfree(sz1); +} + +void putout(int p1) +{ + double before, after; + extern double BeforeSub, AfterSub; + + dprintf(".\tanswer <- S%d, h=%g,b=%g\n",p1, eht[p1], ebase[p1]); + eqnht = eht[p1]; + before = eht[p1] - ebase[p1] - BeforeSub; /* leave room for sub or superscript */ + after = ebase[p1] - AfterSub; + if (spaceval || before > 0.01 || after > 0.01) { + printf(".ds %d ", p1); /* used to be \\x'0' here: why? */ + if (spaceval != NULL) + printf("\\x'0-%s'", spaceval); + else if (before > 0.01) + printf("\\x'0-%gm'", before); + printf("\\*(%d", p1); + if (spaceval == NULL && after > 0.01) + printf("\\x'%gm'", after); + putchar('\n'); + } + if (szstack[0] != 0) + printf(".ds %d %s\\*(%d\\s\\n(99\n", p1, DPS(gsize,gsize), p1); + eqnreg = p1; + if (spaceval != NULL) { + free(spaceval); + spaceval = NULL; + } +} + +void init(void) +{ + synerr = 0; + ct = 0; + ps = gsize; + ftp = ftstack; + ft = ftp->ft; + nszstack = 0; + if (szstack[0] != 0) /* absolute gsize in effect */ + printf(".nr 99 \\n(.s\n"); +} + +salloc(void) +{ + int i; + + for (i = 11; i < 100; i++) + if (used[i] == 0) { + used[i]++; + return(i); + } + ERROR "no eqn strings left (%d)", i FATAL; + return(0); +} + +void sfree(int n) +{ + used[n] = 0; +} + +void nrwid(int n1, int p, int n2) +{ + printf(".nr %d 0\\w'%s\\*(%d'\n", n1, DPS(gsize,p), n2); /* 0 defends against - width */ +} + +char *ABSPS(int dn) /* absolute size dn in printable form \sd or \s(dd (dd >= 40) */ +{ + static char buf[100], *lb = buf; + char *p; + + if (lb > buf + sizeof(buf) - 10) + lb = buf; + p = lb; + *lb++ = '\\'; + *lb++ = 's'; + if (dn >= 10) { /* \s(dd only works in new troff */ + if (dn >= 40) + *lb++ = '('; + *lb++ = dn/10 + '0'; + *lb++ = dn%10 + '0'; + } else { + *lb++ = dn + '0'; + } + *lb++ = '\0'; + return p; +} + +char *DPS(int f, int t) /* delta ps (t-f) in printable form \s+d or \s-d or \s+-(dd */ +{ + static char buf[100], *lb = buf; + char *p; + int dn; + + if (lb > buf + sizeof(buf) - 10) + lb = buf; + p = lb; + *lb++ = '\\'; + *lb++ = 's'; + dn = EFFPS(t) - EFFPS(f); + if (szstack[nszstack] != 0) /* absolute */ + dn = EFFPS(t); /* should do proper \s(dd */ + else if (dn >= 0) + *lb++ = '+'; + else { + *lb++ = '-'; + dn = -dn; + } + if (dn >= 10) { /* \s+(dd only works in new troff */ + *lb++ = '('; + *lb++ = dn/10 + '0'; + *lb++ = dn%10 + '0'; + } else { + *lb++ = dn + '0'; + } + *lb++ = '\0'; + return p; +} + +EFFPS(int n) /* effective value of n */ +{ + if (n >= minsize) + return n; + else + return minsize; +} + +double EM(double m, int ps) /* convert m to ems in gsize */ +{ + m *= (double) EFFPS(ps) / gsize; + if (m <= 0.001 && m >= -0.001) + return 0; + else + return m; +} + +double REL(double m, int ps) /* convert m to ems in ps */ +{ + m *= (double) gsize / EFFPS(ps); + if (m <= 0.001 && m >= -0.001) + return 0; + else + return m; +} blob - /dev/null blob + f02e677942141c732151dfb09d222f145196c7f3 (mode 644) --- /dev/null +++ src/cmd/eqn/mark.c @@ -0,0 +1,19 @@ +#include "e.h" + +void mark(int p1) +{ + markline = 1; + printf(".ds %d \\k(09\\*(%d\n", p1, p1); + yyval = p1; + dprintf(".\tmark %d\n", p1); +} + +void lineup(int p1) +{ + markline = 2; + if (p1 == 0) { + yyval = salloc(); + printf(".ds %d \\h'|\\n(09u'\n", yyval); + } + dprintf(".\tlineup %d\n", p1); +} blob - /dev/null blob + 9df6cff2f99d4dc688db9bd63ca6964597d612e4 (mode 644) --- /dev/null +++ src/cmd/eqn/matrix.c @@ -0,0 +1,78 @@ +#include "e.h" + +startcol(int type) /* mark start of column in lp[] array */ +{ + int oct = ct; + + lp[ct++] = type; + lp[ct++] = 0; /* count, to come */ + lp[ct++] = 0; /* separation, to come */ + return oct; +} + +void column(int oct, int sep) /* remember end of column that started at lp[oct] */ +{ + int i, type; + + lp[oct+1] = ct - oct - 3; + lp[oct+2] = sep; + type = lp[oct]; + if (dbg) { + printf(".\t%d column of", type); + for (i = oct+3; i < ct; i++ ) + printf(" S%d", lp[i]); + printf(", rows=%d, sep=%d\n", lp[oct+1], lp[oct+2]); + } +} + +void matrix(int oct) /* matrix is list of columns */ +{ + int nrow, ncol, i, j, k, val[100]; + double b, hb; + char *space; + extern char *Matspace; + + space = Matspace; /* between columns of matrix */ + nrow = lp[oct+1]; /* disaster if rows inconsistent */ + /* also assumes just columns */ + /* fix when add other things */ + ncol = 0; + for (i = oct+1; i < ct; i += lp[i]+3 ) { + ncol++; + dprintf(".\tcolct=%d\n", lp[i]); + } + for (k=1; k <= nrow; k++) { + hb = b = 0; + j = oct + k + 2; + for (i=0; i < ncol; i++) { + hb = max(hb, eht[lp[j]]-ebase[lp[j]]); + b = max(b, ebase[lp[j]]); + j += nrow + 3; + } + dprintf(".\trow %d: b=%g, hb=%g\n", k, b, hb); + j = oct + k + 2; + for (i=0; i\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2); + printf(".nr %d \\n(%d+%gm\n", treg, treg, Overwid); + d2 = eht[p2]-ebase[p2]-d; /* denom */ + printf(".ds %d \\v'%gm'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\v'%gm'\\\n", + yyval, REL(d2,ps), treg, p2, p2, REL(-d2,ps)); + d1 = 2 * d + ebase[p1]; /* num */ + printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%gm'\\*(%d\\v'%gm'\\\n", + p2, p1, REL(-d1,ps), p1, REL(d1,ps)); + printf("\\h'-\\n(%du-\\n(%du/2u+%gm'\\v'%gm'\\l'\\n(%du-%gm'\\h'%gm'\\v'%gm'\n", + treg, p1, Overline, REL(-d,ps), + treg, 2*Overline, Overline, REL(d,ps)); + ebase[yyval] = b; + eht[yyval] = h; + lfont[yyval] = rfont[yyval] = 0; + sfree(p2); + sfree(treg); +} blob - /dev/null blob + bb019bf750c4e0e105efd635c2e6c554dedcd95f (mode 644) --- /dev/null +++ src/cmd/eqn/paren.c @@ -0,0 +1,135 @@ +#include "e.h" + +#define abs(x) ((x) > 0 ? (x) : (-(x))) + +extern void brack(int, char *, char *, char *); + +void paren(int leftc, int p1, int rightc) +{ + int n, m, j; + double h1, b1; + double v, bv; /* v = shift of inside, bv = shift of brackets */ + extern double Parenbase, Parenshift, Parenheight; + + bv = ttype == DEVPOST ? Parenshift : 0; /* move brackets down this much */ + h1 = eht[p1]; + b1 = ebase[p1]; + yyval = p1; + lfont[yyval] = rfont[yyval] = 0; + n = REL(h1,ps) + 0.99; /* ceiling */ + if (n < 2) + n = 1; + m = n - 2; + if (leftc == '{' || rightc == '}') { + n = n%2 ? n : ++n; + if (n < 3) + n = 3; + m = n-3; + } + eht[yyval] = EM((double) n + Parenheight, ps); + ebase[yyval] = eht[yyval]/2 - EM(Parenbase, ps); + + /* try to cope with things that are badly centered */ + /* (top heavy or bottom heavy) */ + if (abs(h1/2 - b1) >= EM(0.5, ps)) + v = REL(-ebase[yyval] + (eht[yyval]-h1)/2 + b1, ps); + else + v = 0; /* don't shift it at all */ + + printf(".ds %d \\^", yyval); /* was \| */ + if (bv) + printf("\\v'%gm'", bv); + switch (leftc) { + case 'n': /* nothing */ + case '\0': + break; + case 'f': /* floor */ + if (n <= 1) + printf("\\(lf"); + else + brack(m, "\\(bv", "\\(bv", "\\(lf"); + break; + case 'c': /* ceiling */ + if (n <= 1) + printf("\\(lc"); + else + brack(m, "\\(lc", "\\(bv", "\\(bv"); + break; + case '{': + printf("\\b'\\(lt"); + for(j = 0; j < m; j += 2) printf("\\(bv"); + printf("\\(lk"); + for(j = 0; j < m; j += 2) printf("\\(bv"); + printf("\\(lb'"); + break; + case '(': + brack(m, "\\(lt", "\\(bv", "\\(lb"); + break; + case '[': + brack(m, "\\(lc", "\\(bv", "\\(lf"); + break; + case '|': + brack(m, "|", "|", "|"); + break; + default: + brack(m, (char *) &leftc, (char *) &leftc, (char *) &leftc); + break; + } + if (bv) + printf("\\v'%gm'", -bv); + if (v) + printf("\\v'%gm'\\*(%d\\v'%gm'", -v, p1, v); + else + printf("\\*(%d", p1); + if (rightc) { + if (bv) + printf("\\v'%gm'", bv); + switch (rightc) { + case 'f': /* floor */ + if (n <= 1) + printf("\\(rf"); + else + brack(m, "\\(bv", "\\(bv", "\\(rf"); + break; + case 'c': /* ceiling */ + if (n <= 1) + printf("\\(rc"); + else + brack(m, "\\(rc", "\\(bv", "\\(bv"); + break; + case '}': + printf("\\b'\\(rt"); + for(j = 0; j < m; j += 2) printf("\\(bv"); + printf("\\(rk"); + for(j = 0; j < m; j += 2) printf("\\(bv"); + printf("\\(rb'"); + break; + case ']': + brack(m, "\\(rc", "\\(bv", "\\(rf"); + break; + case ')': + brack(m, "\\(rt", "\\(bv", "\\(rb"); + break; + case '|': + brack(m, "|", "|", "|"); + break; + default: + brack(m, (char *) &rightc, (char *) &rightc, (char *) &rightc); + break; + } + if (bv) + printf("\\v'%gm'", -bv); + } + printf("\n"); + dprintf(".\tcurly: h=%g b=%g n=%d v=%g l=%c, r=%c\n", + eht[yyval], ebase[yyval], n, v, leftc, rightc); +} + +void brack(int m, char *t, char *c, char *b) +{ + int j; + printf("\\b'%s", t); + for( j=0; j < m; j++) + printf("%s", c); + printf("%s'", b); +} blob - /dev/null blob + a2d16239c877569f17bfaa41675cd4451b6287c5 (mode 644) --- /dev/null +++ src/cmd/eqn/pile.c @@ -0,0 +1,76 @@ +#include "e.h" +#include "y.tab.h" + +void pile(int oct) +{ + int i, nlist, nlist2, mid; + double bi, h, b, gap, sb; + extern double Pilegap, Pilebase; + int type, p1, p2; + + yyval = salloc(); + type = lp[oct]; + p1 = oct + 3; /* first entry */ + p2 = p1 + lp[oct+1]; /* 1 after last */ + gap = lp[oct+2]; + if (gap != DEFGAP) + gap = EM(gap/100.0, ps); + else if (type == COL) + gap = 0; + else + gap = EM(Pilegap, ps); /* 0.4 m between LCOL, etc. */ + nlist = p2 - p1; + nlist2 = (nlist+1)/2; + mid = p1 + nlist2 - 1; + h = 0; + for (i = p1; i < p2; i++) + h += eht[lp[i]]; + eht[yyval] = h + (nlist-1)*gap; + b = 0; + for (i = p2-1; i > mid; i--) + b += eht[lp[i]] + gap; + ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]] + : b - EM(Pilebase, ps) - gap; + if (dbg) { + printf(".\tS%d <- %d pile of:", yyval, type); + for (i = p1; i < p2; i++) + printf(" S%d", lp[i]); + printf("; h=%g b=%g\n", eht[yyval], ebase[yyval]); + } + nrwid(lp[p1], ps, lp[p1]); + printf(".nr %d \\n(%d\n", yyval, lp[p1]); + for (i = p1+1; i < p2; i++) { + nrwid(lp[i], ps, lp[i]); + printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", + lp[i], yyval, yyval, lp[i]); + } + printf(".ds %d \\v'%gm'\\h'%du*\\n(%du'\\\n", yyval, REL(ebase[yyval],ps), + type==RCOL ? 1 : 0, yyval); + sb = 0; /* sum of box hts */ + for (i = p2-1; i >= p1; i--) { + bi = sb + ebase[lp[i]]; + switch (type) { + case LCOL: + printf("\\v'%gm'\\*(%d\\h'-\\n(%du'\\v'%gm'\\\n", + REL(-bi,ps), lp[i], lp[i], REL(bi,ps)); + break; + case RCOL: + printf("\\v'%gm'\\h'-\\n(%du'\\*(%d\\v'%gm'\\\n", + REL(-bi,ps), lp[i], lp[i], REL(bi,ps)); + break; + case CCOL: + case COL: + printf("\\v'%gm'\\h'\\n(%du-\\n(%du/2u'\\*(%d", + REL(-bi,ps), yyval, lp[i], lp[i]); + printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%gm'\\\n", + yyval, lp[i], REL(bi,ps)); + break; + } + sb += eht[lp[i]] + gap; + } + printf("\\v'%gm'\\h'%du*\\n(%du'\n", REL(-ebase[yyval],ps), + type!=RCOL ? 1 : 0, yyval); + for (i = p1; i < p2; i++) + sfree(lp[i]); + lfont[yyval] = rfont[yyval] = 0; +} blob - /dev/null blob + 1f6d3c718dc69a167a48bdaa376132ca3e8be589 (mode 644) --- /dev/null +++ src/cmd/eqn/prevy.tab.h @@ -0,0 +1,57 @@ +#define CONTIG 57346 +#define QTEXT 57347 +#define SPACE 57348 +#define THIN 57349 +#define TAB 57350 +#define MATRIX 57351 +#define LCOL 57352 +#define CCOL 57353 +#define RCOL 57354 +#define COL 57355 +#define ABOVE 57356 +#define MARK 57357 +#define LINEUP 57358 +#define SUM 57359 +#define INT 57360 +#define PROD 57361 +#define UNION 57362 +#define INTER 57363 +#define DEFINE 57364 +#define TDEFINE 57365 +#define NDEFINE 57366 +#define DELIM 57367 +#define GSIZE 57368 +#define GFONT 57369 +#define INCLUDE 57370 +#define IFDEF 57371 +#define DOTEQ 57372 +#define DOTEN 57373 +#define FROM 57374 +#define TO 57375 +#define OVER 57376 +#define SQRT 57377 +#define SUP 57378 +#define SUB 57379 +#define SIZE 57380 +#define FONT 57381 +#define ROMAN 57382 +#define ITALIC 57383 +#define BOLD 57384 +#define FAT 57385 +#define UP 57386 +#define DOWN 57387 +#define BACK 57388 +#define FWD 57389 +#define LEFT 57390 +#define RIGHT 57391 +#define DOT 57392 +#define DOTDOT 57393 +#define HAT 57394 +#define TILDE 57395 +#define BAR 57396 +#define LOWBAR 57397 +#define HIGHBAR 57398 +#define UNDER 57399 +#define VEC 57400 +#define DYAD 57401 +#define UTILDE 57402 blob - /dev/null blob + dbac530b40b1493fd6a57dff497767d547670f1f (mode 644) --- /dev/null +++ src/cmd/eqn/shift.c @@ -0,0 +1,116 @@ +#include "e.h" +#include "y.tab.h" + +void subsup(int p1, int p2, int p3) +{ + if (p2 != 0 && p3 != 0) + shift2(p1, p2, p3); + else if (p2 != 0) + bshiftb(p1, SUB, p2); + else if (p3 != 0) + bshiftb(p1, SUP, p3); +} + +extern double Subbase, Supshift; +extern char *Sub1space, *Sup1space, *Sub2space; +extern char *SS1space, *SS2space; + +void bshiftb(int p1, int dir, int p2) +{ + int subps, n; + double shval, d1, h1, b1, h2, b2; + char *sh1, *sh2; + + yyval = p1; + h1 = eht[p1]; + b1 = ebase[p1]; + h2 = eht[p2]; + b2 = ebase[p2]; + subps = ps; + ps += deltaps; + if (dir == SUB) { + /* base .2m below bottom of main box */ + shval = b1 + EM(Subbase, ps); + ebase[yyval] = shval + b2; + eht[yyval] = max(h1-b1+shval+b2, h2); + if (rfont[p1] == ITAL && lfont[p2] == ROM) + n = 2; /* Sub1space */ + else + n = max(2, class[rclass[p1]][lclass[p2]]); + sh1 = pad(n); + rclass[p1] = OTHER; /* OTHER leaves too much after sup */ + } else { /* superscript */ + /* 4/10 up main box */ + d1 = EM(Subbase, subps); + ebase[yyval] = b1; + shval = -(Supshift * (h1-b1)) - b2; + if (Supshift*(h1-b1) + h2 < h1-b1) /* raise little super */ + shval = -(h1-b1) + h2-b2 - d1; + eht[yyval] = h1 + max(0, h2 - (1-Supshift)*(h1-b1)); + if (rclass[p1] == ILETF) + n = 4; + else if (rfont[p1] == ITAL) + n = 2; /* Sup1space */ + else + n = max(1, class[rclass[p1]][lclass[p2]]); + sh1 = pad(n); + rclass[p1] = rclass[p2]; /* OTHER leaves too much after sup */ + } + dprintf(".\tS%d <- %d shift %g %d; b=%g, h=%g, ps=%d, subps=%d\n", + yyval, p1, shval, p2, ebase[yyval], eht[yyval], ps, subps); + sh2 = Sub2space; /* was Sub2space; */ + printf(".as %d \\v'%gm'%s%s\\*(%d%s%s\\v'%gm'\n", + yyval, REL(shval,ps), DPS(ps,subps), sh1, p2, + DPS(subps,ps), sh2, REL(-shval,ps)); + rfont[p1] = 0; + sfree(p2); +} + +void shift2(int p1, int p2, int p3) +{ + int subps; + double h1, h2, h3, b1, b2, b3, subsh, d2, supsh; + int treg; + char *sh2; + + treg = salloc(); + yyval = p1; + subps = ps; /* sub and sup at this size */ + ps += deltaps; /* outer size */ + h1 = eht[p1]; b1 = ebase[p1]; + h2 = eht[p2]; b2 = ebase[p2]; + h3 = eht[p3]; b3 = ebase[p3]; + subsh = EM(Subbase, ps); + if (b1 > b2 + subsh) /* move little sub down */ + subsh += b1; + eht[yyval] = max(subsh+b2-b1+h1, h2); + supsh = -Supshift*(h1-b1) - b3; + d2 = EM(Subbase, subps); + if (h3 < (1-Supshift)*(h1-b1)) + supsh = -(h1-b1) + (h3-b3) - d2; + ebase[yyval] = subsh + b2 - b1; + eht[yyval] = h1 + subsh+b2-b1 + max(0, h3-(1-Supshift)*(h1-b1)); + dprintf(".\tS%d <- %d sub %d sup %d, ps=%d, subps=%d, h=%g, b=%g\n", + yyval, p1, p2, p3, ps, subps, eht[yyval], ebase[yyval]); + if (rclass[p1] == ILETF) + sh2 = "\\|\\|"; + else + sh2 = SS2space; + /*n = max(class[rclass[p1]][lclass[p2]], class[rclass[p1]][lclass[p3]]); + /*sh2 = pad(max(2, n)); + */ + printf(".ds %d %s\\*(%d\n", p2, SS1space, p2); + nrwid(p2, subps, p2); + printf(".ds %d %s\\*(%d\n", p3, sh2, p3); + nrwid(p3, subps, p3); + printf(".nr %d \\n(%d\n", treg, p3); + printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2); + printf(".as %d %s\\v'%gm'\\*(%d\\v'%gm'\\h'-\\n(%du'\\\n", + p1, DPS(ps,subps), REL(subsh,subps), p2, REL(-subsh,subps), p2); + printf("\\v'%gm'\\*(%d\\v'%gm'\\h'-\\n(%du+\\n(%du'%s%s\n", + REL(supsh,subps), p3, REL(-supsh,subps), p3, treg, DPS(subps,ps), Sub2space); + if (rfont[p2] == ITAL) + rfont[yyval] = 0; /* lie */ + rclass[yyval] = rclass[p3]; /* was OTHER */ + sfree(p2); sfree(p3); sfree(treg); +} blob - /dev/null blob + 59bf3f20b4322d30a07a82a09b3a3747d3106e7e (mode 644) --- /dev/null +++ src/cmd/eqn/size.c @@ -0,0 +1,70 @@ +#include "e.h" +#include + +void setsize(char *p) /* set size as found in p */ +{ + nszstack++; + szstack[nszstack] = 0; /* assume relative */ + if (*p == '+') { + ps += atoi(p+1); + if (szstack[nszstack-1] != 0) /* propagate absolute size */ + szstack[nszstack] = ps; + } else if (*p == '-') { + ps -= atoi(p+1); + if (szstack[nszstack-1] != 0) + szstack[nszstack] = ps; + } else if (isdigit(*p)) { + if (szstack[nszstack-1] == 0) + printf(".nr %d \\n(.s\n", 99-nszstack); + else + printf(".nr %d %d\n", 99-nszstack, ps); + szstack[nszstack] = ps = atoi(p); + } else { + ERROR "illegal size %s ignored", p WARNING; + } + dprintf(".\tsetsize %s; ps = %d\n", p, ps); +} + +void size(int p1, int p2) +{ + /* old size in p1, new in ps */ + yyval = p2; + dprintf(".\tS%d <- \\s%d %d \\s%d; b=%g, h=%g\n", + yyval, ps, p2, p1, ebase[yyval], eht[yyval]); + if (szstack[nszstack] != 0) { + printf(".ds %d %s\\*(%d\\s\\n(%d\n", yyval, ABSPS(ps), p2, 99-nszstack); + } else + printf(".ds %d %s\\*(%d%s\n", yyval, DPS(p1,ps), p2, DPS(ps,p1)); + nszstack--; + ps = p1; +} + +void globsize(void) +{ + char temp[20]; + + getstr(temp, sizeof(temp)); + if (temp[0] == '+') { + gsize += atoi(temp+1); + if (szstack[0] != 0) + szstack[0] = gsize; + } else if (temp[0] == '-') { + gsize -= atoi(temp+1); + if (szstack[0] != 0) + szstack[0] = gsize; + } else if (isdigit(temp[0])) { + gsize = atoi(temp); + szstack[0] = gsize; + printf(".nr 99 \\n(.s\n"); + } else { + ERROR "illegal gsize %s ignored", temp WARNING; + } + yyval = eqnreg = 0; + ps = gsize; + if (gsize < 12 && !dps_set) /* sub and sup size change */ + deltaps = gsize / 3; + else if (gsize < 20) + deltaps = gsize / 4; + else + deltaps = gsize / 5; +} blob - /dev/null blob + 391d924e2d0f6d73b0dc53510041b59737d1b12c (mode 644) --- /dev/null +++ src/cmd/eqn/sqrt.c @@ -0,0 +1,35 @@ +#include "e.h" + +void sqrt(int p2) +{ + static int af = 0; + int nps; /* point size for radical */ + double radscale = 0.95; + + if (ttype == DEVPOST) + radscale = 1.05; + nps = ps * radscale * eht[p2] / EM(1.0,ps) + 0.99; /* kludgy */ + nps = max(EFFPS(nps), ps); + yyval = p2; + if (ttype == DEVCAT || ttype == DEVAPS) + eht[yyval] = EM(1.2, nps); + else if (ttype == DEVPOST) + eht[yyval] = EM(1.15, nps); + else /* DEV202, DEVPOST */ + eht[yyval] = EM(1.15, nps); + dprintf(".\tS%d <- sqrt S%d;b=%g, h=%g, nps=%d\n", + yyval, p2, ebase[yyval], eht[yyval], nps); + printf(".as %d \\|\n", yyval); + nrwid(p2, ps, p2); + if (af++ == 0) + printf(".af 10 01\n"); /* make it two digits when it prints */ + printf(".nr 10 %.3fu*\\n(.su/10\n", 9.2*eht[p2]); /* this nonsense */ + /* guesses point size corresponding to height of stuff */ + printf(".ds %d \\v'%gm'\\s(\\n(10", yyval, REL(ebase[p2],ps)); + if (ttype == DEVCAT || ttype == DEVAPS) + printf("\\v'-.2m'\\(sr\\l'\\n(%du\\(rn'\\v'.2m'", p2); + else /* DEV202, DEVPOST so far */ + printf("\\(sr\\l'\\n(%du\\(rn'", p2); + printf("\\s0\\v'%gm'\\h'-\\n(%du'\\^\\*(%d\n", REL(-ebase[p2],ps), p2, p2); + lfont[yyval] = rfont[yyval] = ROM; +} blob - /dev/null blob + 261c7fbfc33180f6a68b4abcb05fee01bcbe3fa0 (mode 644) --- /dev/null +++ src/cmd/eqn/text.c @@ -0,0 +1,318 @@ +#include "e.h" +#include "y.tab.h" +#include + +#define CSSIZE 1000 +char cs[CSSIZE+20]; /* text string converted into this */ +char *csp; /* next spot in cs[] */ +char *psp; /* next character in input token */ + +int lf, rf; /* temporary spots for left and right fonts */ +int lastft; /* last \f added */ +int nextft; /* next \f to be added */ + +int pclass; /* class of previous character */ +int nclass; /* class of next character */ + +int class[LAST][LAST] ={ /* guesswork, tuned to times roman postscript */ + + /*OT OL IL DG LP RP SL PL IF IJ VB */ +/*OT*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OTHER */ +/*OL*/ { 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 0 }, /* OLET */ +/*IL*/ { 1, 1, 0, 1, 1, 1, 1, 3, 2, 1, 0 }, /* ILET */ +/*DG*/ { 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 0 }, /* DIG */ +/*LP*/ { 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 0 }, /* LPAR */ +/*RP*/ { 2, 2, 2, 1, 1, 1, 1, 2, 3, 3, 0 }, /* RPAR */ +/*SL*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0 }, /* SLASH */ +/*PL*/ { 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 0 }, /* PLUS */ +/*IF*/ { 3, 3, 1, 2, 2, 3, 2, 3, 0, 1, 1 }, /* ILETF */ +/*IJ*/ { 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0 }, /* ILETJ */ +/*VB*/ { 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 1 }, /* VBAR */ + +}; + +extern void shim(int, int); +extern void roman(int); +extern void sadd(char *); +extern void cadd(int); +extern int trans(int, char *); + +int textc(void) /* read next UTF rune from psp */ +{ + wchar_t r; + int w; + + w = mbtowc(&r, psp, 3); + if(w == 0){ + psp++; + return 0; + } + if(w < 0){ + psp += 1; + return 0x80; /* Plan 9-ism */ + } + psp += w; + return r; +} + +void text(int t, char *p1) /* convert text string p1 of type t */ +{ + int c; + char *p; + tbl *tp; + + yyval = salloc(); + ebase[yyval] = 0; + eht[yyval] = EM(1.0, ps); /* ht in ems of orig size */ + lfont[yyval] = rfont[yyval] = ROM; + lclass[yyval] = rclass[yyval] = OTHER; + if (t == QTEXT) { + for (p = p1; *p; p++) /* scan for embedded \f's */ + if (*p == '\\' && *(p+1) == 'f') + break; + if (*p) /* if found \f, leave it alone and hope */ + p = p1; + else { + sprintf(cs, "\\f%s%s\\fP", ftp->name, p1); + p = cs; + } + } else if (t == SPACE) + p = "\\ "; + else if (t == THIN) + p = "\\|"; + else if (t == TAB) + p = "\\t"; + else if ((tp = lookup(restbl, p1)) != NULL) { + p = tp->cval; + } else { + lf = rf = 0; + lastft = 0; + nclass = NONE; /* get started with no class == no pad */ + csp = cs; + for (psp = p1; (c = textc()) != '\0'; ) { + nextft = ft; + pclass = nclass; + rf = trans(c, p1); + if (lf == 0) { + lf = rf; /* left stuff is first found */ + lclass[yyval] = nclass; + } + if (csp-cs > CSSIZE) + ERROR "converted token %.25s... too long", p1 FATAL ; + } + sadd("\\fP"); + *csp = '\0'; + p = cs; + lfont[yyval] = lf; + rfont[yyval] = rf; + rclass[yyval] = nclass; + } + dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n", + t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval], ps); + printf(".ds %d \"%s\n", yyval, p); +} + +int isalpharune(int c) +{ + return ('a'<=c && c<='z') || ('A'<=c && c<='Z'); +} + +int isdigitrune(int c) +{ + return ('0'<=c && c<='9'); +} + +trans(int c, char *p1) +{ + int f; + + if (isalpharune(c) && ft == ITAL && c != 'f' && c != 'j') { /* italic letter */ + shim(pclass, nclass = ILET); + cadd(c); + return ITAL; + } + if (isalpharune(c) && ft != ITAL) { /* other letter */ + shim(pclass, nclass = OLET); + cadd(c); + return ROM; + } + if (isdigitrune(c)) { + shim(pclass, nclass = DIG); + roman(c); + return ROM; /* this is the right side font of this object */ + } + f = ROM; + nclass = OTHER; + switch (c) { + case ':': case ';': case '!': case '%': case '?': + shim(pclass, nclass); + roman(c); + return f; + case '(': case '[': + shim(pclass, nclass = LPAR); + roman(c); + return f; + case ')': case ']': + shim(pclass, nclass = RPAR); + roman(c); + return f; + case ',': + shim(pclass, nclass = OTHER); + roman(c); + return f; + case '.': + if (rf == ROM) + roman(c); + else + cadd(c); + return f; + case '|': /* postscript needs help with default width! */ + shim(pclass, nclass = VBAR); + sadd("\\v'.17m'\\z|\\v'-.17m'\\|"); /* and height */ + return f; + case '=': + shim(pclass, nclass = PLUS); + sadd("\\(eq"); + return f; + case '+': + shim(pclass, nclass = PLUS); + sadd("\\(pl"); + return f; + case '>': + case '<': /* >, >=, >>, <, <-, <=, << */ + shim(pclass, nclass = PLUS); + if (*psp == '=') { + sadd(c == '<' ? "\\(<=" : "\\(>="); + psp++; + } else if (c == '<' && *psp == '-') { /* <- only */ + sadd("\\(<-"); + psp++; + } else if (*psp == c) { /* << or >> */ + cadd(c); + cadd(c); + psp++; + } else { + cadd(c); + } + return f; + case '-': + shim(pclass, nclass = PLUS); /* probably too big for ->'s */ + if (*psp == '>') { + sadd("\\(->"); + psp++; + } else { + sadd("\\(mi"); + } + return f; + case '/': + shim(pclass, nclass = SLASH); + cadd('/'); + return f; + case '~': + case ' ': + sadd("\\|\\|"); + return f; + case '^': + sadd("\\|"); + return f; + case '\\': /* troff - pass only \(xx without comment */ + shim(pclass, nclass); + cadd('\\'); + cadd(c = *psp++); + if (c == '(' && *psp && *(psp+1)) { + cadd(*psp++); + cadd(*psp++); + } else + fprintf(stderr, "eqn warning: unquoted troff command \\%c, file %s:%d\n", + c, curfile->fname, curfile->lineno); + return f; + case '\'': + shim(pclass, nclass); + sadd("\\(fm"); + return f; + + case 'f': + if (ft == ITAL) { + shim(pclass, nclass = ILETF); + cadd('f'); + f = ITAL; + } else + cadd('f'); + return f; + case 'j': + if (ft == ITAL) { + shim(pclass, nclass = ILETJ); + cadd('j'); + f = ITAL; + } else + cadd('j'); + return f; + default: + shim(pclass, nclass); + cadd(c); + return ft==ITAL ? ITAL : ROM; + } +} + +char *pad(int n) /* return the padding as a string */ +{ + static char buf[20]; + + buf[0] = 0; + if (n < 0) { + sprintf(buf, "\\h'-%du*\\w'\\^'u'", -n); + return buf; + } + for ( ; n > 1; n -= 2) + strcat(buf, "\\|"); + if (n > 0) + strcat(buf, "\\^"); + return buf; +} + +void shim(int lc, int rc) /* add padding space suitable to left and right classes */ +{ + sadd(pad(class[lc][rc])); +} + +void roman(int c) /* add char c in "roman" font */ +{ + nextft = ROM; + cadd(c); +} + +void sadd(char *s) /* add string s to cs */ +{ + while (*s) + cadd(*s++); +} + +void cadd(int c) /* add character c to end of cs */ +{ + char *p; + int w; + + if (lastft != nextft) { + if (lastft != 0) { + *csp++ = '\\'; + *csp++ = 'f'; + *csp++ = 'P'; + } + *csp++ = '\\'; + *csp++ = 'f'; + if (ftp == ftstack) { /* bottom level */ + if (ftp->ft == ITAL) /* usual case */ + *csp++ = nextft; + else /* gfont set, use it */ + for (p = ftp->name; *csp = *p++; ) + csp++; + } else { /* inside some kind of font ... */ + for (p = ftp->name; *csp = *p++; ) + csp++; + } + lastft = nextft; + } + w = wctomb(csp, c); + if(w > 0) /* ignore bad characters */ + csp += w; +} blob - /dev/null blob + 99718db3e8d335012211007157a808e1756dd579 (mode 644) --- /dev/null +++ src/cmd/eqn/tuning.c @@ -0,0 +1,153 @@ +#include "e.h" + +/* + +This file contains parameter values for many of the +tuning parameters in eqn. Names are defined words. + +Strings are plugged in verbatim. +Floats are usually in ems. + +*/ + +/* In main.c: */ + +double BeforeSub = 1.2; /* line space before a subscript */ +double AfterSub = 0.2; /* line space after a subscript */ + +/* diacrit.c: */ + +double Dvshift = 0.25; /* vertical shift for diacriticals on tall letters */ +double Dhshift = 0.025; /* horizontal shift for tall letters */ +double Dh2shift = 0.05; /* horizontal shift for small letters */ +double Dheight = 0.25; /* increment to height for diacriticals */ +double Barv = 0.68; /* vertical shift for bar */ +double Barh = 0.05; /* 1/2 horizontal shrink for bar */ +double Ubarv = 0.1; /* shift underbar up this much ems */ +double Ubarh = 0.05; /* 1/2 horizontal shrink for underbar */ + +/* Also: + Vec, Dyad, Hat, Tilde, Dot, Dotdot, Utilde */ + +/* eqnbox.c: */ + +char *IRspace = "\\^"; /* space between italic & roman boxes */ + +/* fat.c: */ + +double Fatshift = 0.05; /* fattening shifts by Fatshift ems */ + +/* funny.c: */ + +int Funnyps = 5; /* point size change (== 5 above) */ +double Funnyht = 0.2; /* height correction */ +double Funnybase = 0.3; /* base correction */ + +/* integral.c: */ + +int Intps = 4; /* point size change for integral (== 4 above) */ +double Intht = 1.15; /* ht of integral in ems */ +double Intbase = 0.3; /* base in ems */ +double Int1h = 0.4; /* lower limit left */ +double Int1v = 0.2; /* lower limit down */ +double Int2h = 0.05; /* upper limit right was 8 */ +double Int2v = 0.1; /* upper limit up */ + +/* matrix.c: */ + +char *Matspace = "\\ \\ "; /* space between matrix columns */ + +/* over.c: */ + +double Overgap = 0.3; /* gap between num and denom */ +double Overwid = 0.5; /* extra width of box */ +double Overline = 0.1; /* extra length of fraction bar */ + +/* paren.c* */ + +double Parenbase = 0.4; /* shift of base for even count */ +double Parenshift = 0.13; /* how much to shift parens down in left ... */ + /* ignored unless postscript */ +double Parenheight = 0.3; /* extra height above builtups */ + +/* pile.c: */ + +double Pilegap = 0.4; /* gap between pile elems */ +double Pilebase = 0.5; /* shift base of even # of piled elems */ + +/* shift.c: */ + +double Subbase = 0.2; /* subscript base belowe main base */ +double Supshift = 0.4; /* superscript .4 up main box */ +char *Sub1space = "\\|"; /* italic sub roman space */ +char *Sup1space = "\\|"; /* italic sup roman space */ +char *Sub2space = "\\^"; /* space after subscripted thing */ +char *SS1space = "\\^"; /* space before sub in x sub i sup j */ +char *SS2space = "\\^"; /* space before sup */ + +/* sqrt.c: */ + /* sqrt is hard! punt for now. */ + /* part of the problem is that every typesetter does it differently */ + /* and we have several typesetters to run. */ + +/* text.c: */ + /* ought to be done by a table */ + +struct tune { + char *name; + char *cval; +} tune[] ={ + /* diacrit.c */ + "vec_def", "\\f1\\v'-.5m'\\s-3\\(->\\s0\\v'.5m'\\fP", /* was \s-2 & .45m */ + "dyad_def", "\\f1\\v'-.5m'\\s-3\\z\\(<-\\|\\(->\\s0\\v'.5m'\\fP", + "hat_def", "\\f1\\v'-.05m'\\s+1^\\s0\\v'.05m'\\fP", /* was .1 */ + "tilde_def", "\\f1\\v'-.05m'\\s+1~\\s0\\v'.05m'\\fP", + "dot_def", "\\f1\\v'-.67m'.\\v'.67m'\\fP", + "dotdot_def", "\\f1\\v'-.67m'..\\v'.67m'\\fP", + "utilde_def", "\\f1\\v'1.0m'\\s+2~\\s-2\\v'-1.0m'\\fP", + /* funny.c */ + "sum_def", "\\|\\v'.3m'\\s+5\\(*S\\s-5\\v'-.3m'\\|", + "union_def", "\\|\\v'.3m'\\s+5\\(cu\\s-5\\v'-.3m'\\|", + "inter_def", "\\|\\v'.3m'\\s+5\\(ca\\s-5\\v'-.3m'\\|", + "prod_def", "\\|\\v'.3m'\\s+5\\(*P\\s-5\\v'-.3m'\\|", + /* integral.c */ + "int_def", "\\v'.1m'\\s+4\\(is\\s-4\\v'-.1m'", + 0, 0 +}; + +tbl *ftunetbl[TBLSIZE]; /* user-defined names */ + +char *ftunes[] ={ /* this table intentionally left small */ + "Subbase", + "Supshift", + 0 +}; + +void init_tune(void) +{ + int i; + + for (i = 0; tune[i].name != NULL; i++) + install(deftbl, tune[i].name, tune[i].cval, 0); + for (i = 0; ftunes[i] != NULL; i++) + install(ftunetbl, ftunes[i], (char *) 0, 0); +} + +#define eq(s, t) (strcmp(s,t) == 0) + +void ftune(char *s, char *t) /* brute force for now */ +{ + double f = atof(t); + double *target; + + while (*t == ' ' || *t == '\t') + t++; + if (eq(s, "Subbase")) + target = &Subbase; + else if (eq(s, "Supshift")) + target = &Supshift; + if (t[0] == '+' || t[0] == '-') + *target += f; + else + *target = f; +} blob - /dev/null blob + 1f6d3c718dc69a167a48bdaa376132ca3e8be589 (mode 644) --- /dev/null +++ src/cmd/eqn/y.tab.h @@ -0,0 +1,57 @@ +#define CONTIG 57346 +#define QTEXT 57347 +#define SPACE 57348 +#define THIN 57349 +#define TAB 57350 +#define MATRIX 57351 +#define LCOL 57352 +#define CCOL 57353 +#define RCOL 57354 +#define COL 57355 +#define ABOVE 57356 +#define MARK 57357 +#define LINEUP 57358 +#define SUM 57359 +#define INT 57360 +#define PROD 57361 +#define UNION 57362 +#define INTER 57363 +#define DEFINE 57364 +#define TDEFINE 57365 +#define NDEFINE 57366 +#define DELIM 57367 +#define GSIZE 57368 +#define GFONT 57369 +#define INCLUDE 57370 +#define IFDEF 57371 +#define DOTEQ 57372 +#define DOTEN 57373 +#define FROM 57374 +#define TO 57375 +#define OVER 57376 +#define SQRT 57377 +#define SUP 57378 +#define SUB 57379 +#define SIZE 57380 +#define FONT 57381 +#define ROMAN 57382 +#define ITALIC 57383 +#define BOLD 57384 +#define FAT 57385 +#define UP 57386 +#define DOWN 57387 +#define BACK 57388 +#define FWD 57389 +#define LEFT 57390 +#define RIGHT 57391 +#define DOT 57392 +#define DOTDOT 57393 +#define HAT 57394 +#define TILDE 57395 +#define BAR 57396 +#define LOWBAR 57397 +#define HIGHBAR 57398 +#define UNDER 57399 +#define VEC 57400 +#define DYAD 57401 +#define UTILDE 57402 blob - /dev/null blob + 72f0fc3ae8d1573fab3d8819c23803b151db4037 (mode 644) --- /dev/null +++ src/cmd/grap/coord.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +char *dflt_coord = "gg"; +char *curr_coord = "gg"; +int ncoord = 0; /* number of explicit coord's given */ + +Point xcoord; +Point ycoord; +int xcflag = 0; /* 1 if xcoord set */ +int ycflag = 0; +int logcoord = 0; + +void coord_x(Point pt) /* remember x coord */ +{ + xcoord = pt; + xcflag = 1; + margin = 0; /* no extra space around picture if explicit coords */ +} + +void coord_y(Point pt) +{ + ycoord = pt; + ycflag = 1; + margin = 0; /* no extra space if explicit coords */ +} + +void coordlog(int n) /* remember log scaling */ +{ + logcoord = n; +} + +void coord(Obj *p) /* set coord range */ +{ + static char buf[10]; + + ncoord++; + if (ncoord > 1 && strcmp(p->name, dflt_coord) == 0) { + /* resetting default coordinate by implication */ + sprintf(buf, "gg%d", ncoord); + dflt_coord = buf; + p = lookup(dflt_coord, 1); + } + if (xcflag) { + p->coord |= XFLAG; + p->pt.x = min(xcoord.x,xcoord.y); /* "xcoord" is xmin, xmax */ + p->pt1.x = max(xcoord.x,xcoord.y); + if ((logcoord&XFLAG) && p->pt.x <= 0.0) + ERROR "can't have log of x coord %g,%g", p->pt.x, p->pt1.x FATAL; + xcflag = 0; + } + if (ycflag) { + p->coord |= YFLAG; + p->pt.y = min(ycoord.x,ycoord.y); /* "ycoord" is ymin, ymax */ + p->pt1.y = max(ycoord.x,ycoord.y); + if ((logcoord&YFLAG) && p->pt.y <= 0.0) + ERROR "can't have log of y coord %g,%g", p->pt.y, p->pt1.y FATAL; + ycflag = 0; + } + p->log = logcoord; + logcoord = 0; + auto_x = 0; +} + +void resetcoord(Obj *p) /* reset current coordinate */ +{ + curr_coord = p->name; +} blob - /dev/null blob + 1c2e905b7e41715703979478a52c125416fd29b7 (mode 644) --- /dev/null +++ src/cmd/grap/find @@ -0,0 +1 @@ +exec /usr/bin/egrep -n "$1" *.[chyl] blob - /dev/null blob + 84de388d4d7ac4f8b82e5e1b2eb344e58640839b (mode 644) --- /dev/null +++ src/cmd/grap/for.c @@ -0,0 +1,89 @@ +#include +#include +#include "grap.h" +#include "y.tab.h" + +typedef struct { + Obj *var; /* index variable */ + double to; /* limit */ + double by; + int op; /* operator */ + char *str; /* string to push back */ +} For; + +#define MAXFOR 10 + +For forstk[MAXFOR]; /* stack of for loops */ +For *forp = forstk; /* pointer to current top */ + +void forloop(Obj *var, double from, double to, int op, double by, char *str) /* set up a for loop */ +{ + fprintf(tfd, "# for %s from %g to %g by %c %g \n", + var->name, from, to, op, by); + if (++forp >= forstk+MAXFOR) + ERROR "for loop nested too deep" FATAL; + forp->var = var; + forp->to = to; + forp->op = op; + forp->by = by; + forp->str = str; + setvar(var, from); + nextfor(); + unput('\n'); +} + +void nextfor(void) /* do one iteration of a for loop */ +{ + /* BUG: this should depend on op and direction */ + if (forp->var->fval > SLOP * forp->to) { /* loop is done */ + free(forp->str); + if (--forp < forstk) + ERROR "forstk popped too far" FATAL; + } else { /* another iteration */ + pushsrc(String, "\nEndfor\n"); + pushsrc(String, forp->str); + } +} + +void endfor(void) /* end one iteration of for loop */ +{ + switch (forp->op) { + case '+': + case ' ': + forp->var->fval += forp->by; + break; + case '-': + forp->var->fval -= forp->by; + break; + case '*': + forp->var->fval *= forp->by; + break; + case '/': + forp->var->fval /= forp->by; + break; + } + nextfor(); +} + +char *ifstat(double expr, char *thenpart, char *elsepart) +{ + dprintf("if %g then <%s> else <%s>\n", expr, thenpart, elsepart? elsepart : ""); + if (expr) { + unput('\n'); + pushsrc(Free, thenpart); + pushsrc(String, thenpart); + unput('\n'); + if (elsepart) + free(elsepart); + return thenpart; /* to be freed later */ + } else { + free(thenpart); + if (elsepart) { + unput('\n'); + pushsrc(Free, elsepart); + pushsrc(String, elsepart); + unput('\n'); + } + return elsepart; + } +} blob - /dev/null blob + a00a9d8d05678a3a4d0d869a5b379f89b71042f5 (mode 644) --- /dev/null +++ src/cmd/grap/frame.c @@ -0,0 +1,71 @@ +#include +#include +#include "grap.h" +#include "y.tab.h" + +double frame_ht; /* default frame height */ +double frame_wid; /* and width */ + +int nsides = 0; /* how many sides given on this frame */ +char *sides[] = { + "\tline from Frame.nw to Frame.ne", + "\tline from Frame.sw to Frame.se", + "\tline from Frame.sw to Frame.nw", + "\tline from Frame.se to Frame.ne" +}; +char *newsides[4] = { 0, 0, 0, 0 }; /* filled in later */ + +void frame(void) /* pump out frame definition, reset for next */ +{ + int i; + + fprintf(tfd, "\tframeht = %g\n", frame_ht); + fprintf(tfd, "\tframewid = %g\n", frame_wid); + fprintf(tfd, "Frame:\tbox ht frameht wid framewid with .sw at 0,0 "); + if (nsides == 0) + fprintf(tfd, "\n"); + else { + fprintf(tfd, "invis\n"); + for (i = 0; i < 4; i++) { + if (newsides[i]) { + fprintf(tfd, "%s\n", newsides[i]); + free(newsides[i]); + newsides[i] = 0; + } else + fprintf(tfd, "%s\n", sides[i]); + } + nsides = 0; + } +} + +void frameht(double f) /* set height of frame */ +{ + frame_ht = f; +} + +void framewid(double f) /* set width of frame */ +{ + frame_wid = f; +} + +void frameside(int type, Attr *desc) /* create and remember sides */ +{ + int n; + char buf[100]; + + nsides++; + switch (type) { + case 0: /* no side specified; kludge up all */ + frameside(TOP, desc); + frameside(BOT, desc); + frameside(LEFT, desc); + frameside(RIGHT, desc); + return; + case TOP: n = 0; break; + case BOT: n = 1; break; + case LEFT: n = 2; break; + case RIGHT: n = 3; break; + } + sprintf(buf, "%s %s", sides[n], desc_str(desc)); + newsides[n] = tostring(buf); +} blob - /dev/null blob + 65c7f83f28e078ac011e6ff63e9949b4620554ef (mode 644) --- /dev/null +++ src/cmd/grap/grap.h @@ -0,0 +1,236 @@ +extern char errbuf[200]; +#define ERROR sprintf(errbuf, +#define FATAL ), yyerror(errbuf), exit(1) +#define WARNING ), yyerror(errbuf) + +#define dprintf if(dbg)printf + +#define String 01 +#define Macro 02 +#define File 04 +#define Char 010 +#define Thru 020 +#define Free 040 + +#define MARGIN 0.07 /* default margin around data */ +#define SLOP 1.001 /* slop for limits of for loops */ +#define FRAMEWID 3 /* default width for boxes and ellipses */ +#define FRAMEHT 2 /* default height and line length */ +#define TICKLEN 0.1 + +#define MAXNUM 200 + +#define XFLAG 01 +#define YFLAG 02 + +#define INTICK 01 +#define OUTICK 02 + +#define BOT 01 +#define TOP 02 +#define RIGHT 04 +#define LEFT 010 + +#define RJUST 01 +#define LJUST 02 +#define ABOVE 04 +#define BELOW 010 + +typedef struct infile { + FILE *fin; + char *fname; + int lineno; +} Infile; + +typedef struct { /* input source */ + int type; /* Macro, String, File */ + char *sp; /* if String or Macro */ +} Src; + +extern Src src[], *srcp; /* input source stack */ + +#define MAXARGS 100 +typedef struct { /* argument stack */ + char *argstk[MAXARGS]; /* pointers to args */ + char *argval; /* points to space containing args */ +} Arg; + +extern Infile infile[10]; +extern Infile *curfile; + +typedef struct { + struct obj *obj; + double x, y; +} Point; + +typedef struct attr { /* e.g., DASH 1.1 or "..." rjust size *.5 */ + int type; + double fval; + char *sval; + int just; /* justification, for STRING type */ + int op; /* optional operator, ditto */ + struct attr *next; +} Attr; + +typedef struct obj { /* a name and its properties */ + char *name; + char *val; /* body of define, etc. */ + double fval; /* if a numeric variable */ + Point pt; /* usually for max and min */ + Point pt1; + int type; /* NAME, DEFNAME, ... */ + int first; /* 1 after 1st item seen */ + int coord; /* 1 if coord system specified for this name */ + int log; /* x, y, or z (= x+y) */ + Attr *attr; /* DASH, etc., for now */ + struct obj *next; +} Obj; + +typedef union { /* the yacc stack type */ + int i; + char *p; + double f; + Point pt; + Obj *op; + Attr *ap; +} YYSTYPE; + +extern YYSTYPE yylval, yyval; + +extern int dbg; + +extern int ntext; +extern double num[MAXNUM]; +extern int nnum; +extern int ntick, tside; + +extern char *tostring(char *); +extern char *grow(char *, char *, int, int); + +extern int lineno; +extern int synerr; +extern int codegen; +extern char tempfile[]; +extern FILE *tfd; + +extern Point ptmin, ptmax; + +extern char *dflt_coord; +extern char *curr_coord; +extern int ncoord; +extern int auto_x; +extern double margin; +extern int autoticks; +extern int pointsize, ps_set; + + +#define logit(x) (x) = log10(x) +#define Log10(x) errcheck(log10(x), "log") +#define Exp(x) errcheck(exp(x), "exp") +#define Sqrt(x) errcheck(sqrt(x), "sqrt") + +#define min(x,y) (((x) <= (y)) ? (x) : (y)) +#define max(x,y) (((x) >= (y)) ? (x) : (y)) + +extern void yyerror(char *); +extern void coord_x(Point); +extern void coord_y(Point); +extern void coordlog(int); +extern void coord(Obj *); +extern void resetcoord(Obj *); +extern void savenum(int, double); +extern void setjust(int); +extern void setsize(int, double); +extern void range(Point); +extern void halfrange(Obj *, int, double); +extern Obj *lookup(char *, int); +extern double getvar(Obj *); +extern double setvar(Obj *, double); +extern Point makepoint(Obj *, double, double); +extern Attr *makefattr(int, double); +extern Attr *makesattr(char *); +extern Attr *makeattr(int, double, char *, int, int); +extern Attr *addattr(Attr *, Attr *); +extern void freeattr(Attr *); +extern char *slprint(Attr *); +extern char *juststr(int); +extern char *sprntf(char *, Attr *); +extern void forloop(Obj *, double, double, int, double, char *); +extern void nextfor(void); +extern void endfor(void); +extern char *ifstat(double, char *, char *); +extern void frame(void); +extern void frameht(double); +extern void framewid(double); +extern void frameside(int, Attr *); +extern void pushsrc(int, char *); +extern void popsrc(void); +extern void definition(char *); +extern char *delimstr(char *); +extern int baldelim(int, char *); +extern void dodef(Obj *); +extern int getarg(char *); +extern int input(void); +extern int nextchar(void); +extern void do_thru(void); +extern int unput(int); +extern void pbstr(char *); +extern double errcheck(double, char *); +extern void yyerror(char *); +extern void eprint(void); +extern int yywrap(void); +extern void copyfile(char *); +extern void copydef(Obj *); +extern Obj *copythru(char *); +extern char *addnewline(char *); +extern void copyuntil(char *); +extern void copy(void); +extern void shell_init(void); +extern void shell_text(char *); +extern void shell_exec(void); +extern void labelwid(double); +extern void labelmove(int, double); +extern void label(int, Attr *); +extern void lab_adjust(void); +extern char *sizeit(Attr *); +extern void line(int, Point, Point, Attr *); +extern void circle(double, Point); +extern char *xyname(Point); +extern void pic(char *); +extern void numlist(void); +extern void plot(Attr *, Point); +extern void plotnum(double, char *, Point); +extern void drawdesc(int, Obj *, Attr *, char *); +extern void next(Obj *, Point, Attr *); +extern void print(void); +extern void endstat(void); +extern void graph(char *); +extern void setup(void); +extern void do_first(void); +extern void reset(void); +extern void opentemp(void); +extern void savetick(double, char *); +extern void dflt_tick(double); +extern void tickside(int); +extern void tickoff(int); +extern void gridtickoff(void); +extern void setlist(void); +extern void tickdir(int, double, int); +extern void ticks(void); +extern double modfloor(double, double); +extern double modceil(double, double); +extern void do_autoticks(Obj *); +extern void logtick(double, double, double); +extern Obj *setauto(void); +extern void autoside(Obj *, int); +extern void autolog(Obj *, int); +extern void iterator(double, double, int, double, char *); +extern void ticklist(Obj *, int); +extern void print_ticks(int, int, Obj *, char *, char *); +extern void maketick(int, char *, int, int, double, char *, char *, char *); +extern void griddesc(Attr *); +extern void gridlist(Obj *); +extern char *desc_str(Attr *); +extern int sidelog(int, int); + +extern Obj *objlist; blob - /dev/null blob + 6d96b2f18e51d075edfc856ed2e3f82458a660a5 (mode 644) --- /dev/null +++ src/cmd/grap/grap.y @@ -0,0 +1,396 @@ +%{ +#include +#include +#include +#include +#include "grap.h" + +//#define RAND_MAX 32767 /* if your rand() returns bigger, change this too */ + +extern int yylex(void); +extern int yyparse(void); + +%} + +%token FRAME TICKS GRID LABEL COORD +%token LINE ARROW CIRCLE DRAW NEW PLOT NEXT +%token

PIC +%token COPY THRU UNTIL +%token FOR FROM TO BY AT WITH +%token IF +%token

GRAPH THEN ELSE DOSTR +%token DOT DASH INVIS SOLID +%token TEXT JUST SIZE +%token LOG EXP SIN COS ATAN2 SQRT RAND MAX MIN INT PRINT SPRINTF +%token X Y SIDE IN OUT OFF UP DOWN ACROSS +%token HEIGHT WIDTH RADIUS +%token NUMBER +%token NAME VARNAME DEFNAME +%token

STRING +%token ST '(' ')' ',' + +%right '=' +%left OR +%left AND +%nonassoc GT LT LE GE EQ NE +%left '+' '-' +%left '*' '/' '%' +%right UMINUS NOT +%right '^' + +%type expr optexpr if_expr number assign +%type optop +%type

optstring if +%type optname iterator name +%type point +%type side optside numlist comma linetype drawtype +%type linedesc optdesc stringlist string stringattr sattrlist exprlist +%type frameitem framelist coordlog +%type string_expr + +%% + +top: + graphseq { if (codegen && !synerr) graph((char *) 0); } + | /* empty */ { codegen = 0; } + | error { codegen = 0; ERROR "syntax error" WARNING; } + ; + +graphseq: + statlist + | graph statlist + | graphseq graph statlist + ; +graph: + GRAPH { graph($1); endstat(); } + ; + +statlist: + ST + | stat ST { endstat(); } + | statlist stat ST { endstat(); } + ; + +stat: + FRAME framelist { codegen = 1; } + | ticks { codegen = 1; } + | grid { codegen = 1; } + | label { codegen = 1; } + | coord + | plot { codegen = 1; } + | line { codegen = 1; } + | circle { codegen = 1; } + | draw + | next { codegen = 1; } + | PIC { codegen = 1; pic($1); } + | for + | if + | copy + | numlist { codegen = 1; numlist(); } + | assign + | PRINT expr { fprintf(stderr, "\t%g\n", $2); } + | PRINT string { fprintf(stderr, "\t%s\n", $2->sval); freeattr($2); } + | /* empty */ + ; + +numlist: + number { savenum(0, $1); $$ = 1; } + | numlist number { savenum($1, $2); $$ = $1+1; } + | numlist comma number { savenum($1, $3); $$ = $1+1; } + ; +number: + NUMBER + | '-' NUMBER %prec UMINUS { $$ = -$2; } + | '+' NUMBER %prec UMINUS { $$ = $2; } + ; + +label: + LABEL optside stringlist lablist { label($2, $3); } + ; +lablist: + labattr + | lablist labattr + | /* empty */ + ; +labattr: + UP expr { labelmove($1, $2); } + | DOWN expr { labelmove($1, $2); } + | SIDE expr { labelmove($1, $2); /* LEFT or RIGHT only */ } + | WIDTH expr { labelwid($2); } + ; + +framelist: + framelist frameitem + | /* empty */ { $$ = 0; } + ; +frameitem: + HEIGHT expr { frameht($2); } + | WIDTH expr { framewid($2); } + | side linedesc { frameside($1, $2); } + | linedesc { frameside(0, $1); } + ; +side: + SIDE + ; +optside: + side + | /* empty */ { $$ = 0; } + ; + +linedesc: + linetype optexpr { $$ = makeattr($1, $2, (char *) 0, 0, 0); } + ; +linetype: + DOT | DASH | SOLID | INVIS + ; +optdesc: + linedesc + | /* empty */ { $$ = makeattr(0, 0.0, (char *) 0, 0, 0); } + ; + +ticks: + TICKS tickdesc { ticks(); } + ; +tickdesc: + tickattr + | tickdesc tickattr + ; +tickattr: + side { tickside($1); } + | IN expr { tickdir(IN, $2, 1); } + | OUT expr { tickdir(OUT, $2, 1); } + | IN { tickdir(IN, 0.0, 0); } + | OUT { tickdir(OUT, 0.0, 0); } + | AT optname ticklist { setlist(); ticklist($2, AT); } + | iterator { setlist(); ticklist($1, AT); } + | side OFF { tickoff($1); } + | OFF { tickoff(LEFT|RIGHT|TOP|BOT); } + | labattr + ; +ticklist: + tickpoint + | ticklist comma tickpoint + ; +tickpoint: + expr { savetick($1, (char *) 0); } + | expr string { savetick($1, $2->sval); } + ; +iterator: + FROM optname expr TO optname expr BY optop expr optstring + { iterator($3, $6, $8, $9, $10); $$ = $2; } + | FROM optname expr TO optname expr optstring + { iterator($3, $6, '+', 1.0, $7); $$ = $2; } + ; +optop: + '+' { $$ = '+'; } + | '-' { $$ = '-'; } + | '*' { $$ = '*'; } + | '/' { $$ = '/'; } + | /* empty */ { $$ = ' '; } + ; +optstring: + string { $$ = $1->sval; } + | /* empty */ { $$ = (char *) 0; } + ; + +grid: + GRID griddesc { ticks(); } + ; +griddesc: + gridattr + | griddesc gridattr + ; +gridattr: + side { tickside($1); } + | X { tickside(BOT); } + | Y { tickside(LEFT); } + | linedesc { griddesc($1); } + | AT optname ticklist { setlist(); gridlist($2); } + | iterator { setlist(); gridlist($1); } + | TICKS OFF { gridtickoff(); } + | OFF { gridtickoff(); } + | labattr + ; + +line: + LINE FROM point TO point optdesc { line($1, $3, $5, $6); } + | LINE optdesc FROM point TO point { line($1, $4, $6, $2); } + ; +circle: + CIRCLE RADIUS expr AT point { circle($3, $5); } + | CIRCLE AT point RADIUS expr { circle($5, $3); } + | CIRCLE AT point { circle(0.0, $3); } + ; + +stringlist: + string + | stringlist string { $$ = addattr($1, $2); } + ; +string: + STRING sattrlist { $$ = makesattr($1); } + | SPRINTF '(' STRING ')' sattrlist + { $$ = makesattr(sprntf($3, (Attr*) 0)); } + | SPRINTF '(' STRING ',' exprlist ')' sattrlist + { $$ = makesattr(sprntf($3, $5)); } + ; +exprlist: + expr { $$ = makefattr(NUMBER, $1); } + | exprlist ',' expr { $$ = addattr($1, makefattr(NUMBER, $3)); } + ; +sattrlist: + stringattr + | sattrlist stringattr + | /* empty */ { $$ = (Attr *) 0; } + ; +stringattr: + JUST { setjust($1); } + | SIZE optop expr { setsize($2, $3); } + ; + +coord: + COORD optname coordlist { coord($2); } + | COORD optname { resetcoord($2); } + ; +coordlist: + coorditem + | coordlist coorditem + ; +coorditem: + coordlog { coordlog($1); } + | X point { coord_x($2); } + | Y point { coord_y($2); } + | X optname expr TO expr { coord_x(makepoint($2, $3, $5)); } + | Y optname expr TO expr { coord_y(makepoint($2, $3, $5)); } + | X FROM optname expr TO expr { coord_x(makepoint($3, $4, $6)); } + | Y FROM optname expr TO expr { coord_y(makepoint($3, $4, $6)); } + ; +coordlog: + LOG X { $$ = XFLAG; } + | LOG Y { $$ = YFLAG; } + | LOG X LOG Y { $$ = XFLAG|YFLAG; } + | LOG Y LOG X { $$ = XFLAG|YFLAG; } + | LOG LOG { $$ = XFLAG|YFLAG; } + ; + +plot: + stringlist AT point { plot($1, $3); } + | PLOT stringlist AT point { plot($2, $4); } + | PLOT expr optstring AT point { plotnum($2, $3, $5); } + ; + +draw: + drawtype optname linedesc { drawdesc($1, $2, $3, (char *) 0); } + | drawtype optname optdesc string { drawdesc($1, $2, $3, $4->sval); } + | drawtype optname string optdesc { drawdesc($1, $2, $4, $3->sval); } + ; +drawtype: + DRAW + | NEW + ; + +next: + NEXT optname AT point optdesc { next($2, $4, $5); } + +copy: + COPY copylist { copy(); } + ; +copylist: + copyattr + | copylist copyattr + ; +copyattr: + string { copyfile($1->sval); } + | THRU DEFNAME { copydef($2); } + | UNTIL string { copyuntil($2->sval); } + ; + +for: + FOR name FROM expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name FROM expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + | FOR name '=' expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name '=' expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + ; + +if: + IF if_expr THEN ELSE { $$ = ifstat($2, $3, $4); } + | IF if_expr THEN { $$ = ifstat($2, $3, (char *) 0); } + ; +if_expr: + expr + | string_expr + | if_expr AND string_expr { $$ = $1 && $3; } + | if_expr OR string_expr { $$ = $1 || $3; } + ; +string_expr: + STRING EQ STRING { $$ = strcmp($1,$3) == 0; free($1); free($3); } + | STRING NE STRING { $$ = strcmp($1,$3) != 0; free($1); free($3); } + ; + +point: + optname expr comma expr { $$ = makepoint($1, $2, $4); } + | optname '(' expr comma expr ')' { $$ = makepoint($1, $3, $5); } + ; +comma: + ',' { $$ = ','; } + ; + +optname: + NAME { $$ = $1; } + | /* empty */ { $$ = lookup(curr_coord, 1); } + ; + +expr: + NUMBER + | assign + | '(' string_expr ')' { $$ = $2; } + | VARNAME { $$ = getvar($1); } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { if ($3 == 0.0) { + ERROR "division by 0" WARNING; $3 = 1; } + $$ = $1 / $3; } + | expr '%' expr { if ((long)$3 == 0) { + ERROR "mod division by 0" WARNING; $3 = 1; } + $$ = (long)$1 % (long)$3; } + | '-' expr %prec UMINUS { $$ = -$2; } + | '+' expr %prec UMINUS { $$ = $2; } + | '(' expr ')' { $$ = $2; } + | LOG '(' expr ')' { $$ = Log10($3); } + | EXP '(' expr ')' { $$ = Exp($3 * log(10.0)); } + | expr '^' expr { $$ = pow($1, $3); } + | SIN '(' expr ')' { $$ = sin($3); } + | COS '(' expr ')' { $$ = cos($3); } + | ATAN2 '(' expr ',' expr ')' { $$ = atan2($3, $5); } + | SQRT '(' expr ')' { $$ = Sqrt($3); } + | RAND '(' ')' { $$ = (double)rand() / (double)RAND_MAX; } + | MAX '(' expr ',' expr ')' { $$ = $3 >= $5 ? $3 : $5; } + | MIN '(' expr ',' expr ')' { $$ = $3 <= $5 ? $3 : $5; } + | INT '(' expr ')' { $$ = (long) $3; } + | expr GT expr { $$ = $1 > $3; } + | expr LT expr { $$ = $1 < $3; } + | expr LE expr { $$ = $1 <= $3; } + | expr GE expr { $$ = $1 >= $3; } + | expr EQ expr { $$ = $1 == $3; } + | expr NE expr { $$ = $1 != $3; } + | expr AND expr { $$ = $1 && $3; } + | expr OR expr { $$ = $1 || $3; } + | NOT expr { $$ = !($2); } + ; +assign: + name '=' expr { $$ = setvar($1, $3); } + ; + +name: + NAME + | VARNAME + ; + +optexpr: + expr + | /* empty */ { $$ = 0.0; } + ; blob - /dev/null blob + 0023aded84cb6a1f0062372cc82c2469aab7bc66 (mode 644) --- /dev/null +++ src/cmd/grap/grapl.lx @@ -0,0 +1,213 @@ +%Start A str def thru sh + +%{ +#undef input +#undef unput +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +extern struct symtab symtab[]; + +int yyback(int *, int); +int yylook(void); +int yywrap(void); +void shell_init(void), shell_exec(void), shell_text(char *); + +#define CADD cbuf[clen++] = yytext[0]; \ + if (clen >= CBUFLEN-1) { \ + ERROR "string too long", cbuf WARNING; BEGIN A; } +#define CBUFLEN 1500 +char cbuf[CBUFLEN]; +int clen, cflag; +int c, delim, shcnt; +%} + +A [a-zA-Z_] +B [a-zA-Z0-9_] +D [0-9] +WS [ \t] + +%% + if (yybgin-yysvec-1 == 0) { /* witchcraft */ + BEGIN A; + } + +{WS} ; +"\\"\n ; +\n return(ST); +";" return(ST); + +line return(yylval.i = LINE); +arrow { yylval.i = ARROW; return(LINE); } +circle return(yylval.i = CIRCLE); +frame return(FRAME); +tick(s)? return(TICKS); +grid(line)?(s)? return(GRID); +coord(s)? return(COORD); +log return(LOG); +exp return(EXP); +sin return(SIN); +cos return(COS); +atan2 return(ATAN2); +sqrt return(SQRT); +rand return(RAND); +max return(MAX); +min return(MIN); +int return(INT); +print return(PRINT); +sprintf return(SPRINTF); +pic{WS}.* { yylval.p = tostring(yytext+3); return(PIC); } +graph{WS}.* { yylval.p = tostring(yytext+5); return(GRAPH); } + +for return(FOR); +^Endfor\n { endfor(); } +do { yylval.p = delimstr("loop body"); BEGIN A; return(DOSTR); } + +copy|include { return(COPY); } +thru|through { BEGIN thru; return(THRU); } +{WS}+ ; +{A}{B}*|. { yylval.op = copythru(yytext); BEGIN A; return(DEFNAME); } +until return(UNTIL); + +if return(IF); +then { yylval.p = delimstr("then part"); BEGIN A; return(THEN); } +else { yylval.p = delimstr("else part"); BEGIN A; return(ELSE); } + +next return(NEXT); +draw return(yylval.i = DRAW); +new return(yylval.i = NEW); +plot return(yylval.i = PLOT); +label(s)? return(LABEL); +x return(X); +y return(Y); + +top { yylval.i = TOP; return SIDE; } +bot(tom)? { yylval.i = BOT; return SIDE; } +left { yylval.i = LEFT; return SIDE; } +right { yylval.i = RIGHT; return SIDE; } +up return(yylval.i = UP); +down return(yylval.i = DOWN); +across return(yylval.i = ACROSS); +height|ht return(yylval.i = HEIGHT); +wid(th)? return(yylval.i = WIDTH); +rad(ius)? return(yylval.i = RADIUS); +invis return(yylval.i = INVIS); +dot(ted) return(yylval.i = DOT); +dash(ed) return(yylval.i = DASH); +solid return(yylval.i = SOLID); + +ljust { yylval.i = LJUST; return JUST; } +rjust { yylval.i = RJUST; return JUST; } +above { yylval.i = ABOVE; return JUST; } +below { yylval.i = BELOW; return JUST; } +size return(yylval.i = SIZE); + +from return(yylval.i = FROM); +to return(yylval.i = TO); +by|step return(yylval.i = BY); +at return(yylval.i = AT); +with return(yylval.i = WITH); +in return(yylval.i = IN); +out return(yylval.i = OUT); +off return(yylval.i = OFF); + +sh{WS}+ { BEGIN sh; + if ((delim = input()) == '{') { + shcnt = 1; + delim = '}'; + } + shell_init(); + } +{A}{B}* { + int c; + Obj *p; + if (yytext[0] == delim) { + shell_exec(); + BEGIN A; + } else { + p = lookup(yytext, 0); + if (p != NULL && p->type == DEFNAME) { + c = input(); + unput(c); + if (c == '(') + dodef(p); + else + pbstr(p->val); + } else + shell_text(yytext); + } + } +"{" { shcnt++; shell_text(yytext); } +"}" { if (delim != '}' || --shcnt > 0) + shell_text(yytext); + else { + shell_exec(); + BEGIN A; + } + } +.|\n { if (yytext[0] == delim) { + shell_exec(); + BEGIN A; + } else + shell_text(yytext); + } + +define{WS}+ { BEGIN def; } +{A}{B}* { definition(yytext); BEGIN A; } + +({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)?i? { + yylval.f = atof(yytext); return(NUMBER); } + +^"."[^0-9].* { if (yytext[1] == 'G' && yytext[2] == '2') { + yylval.i = yytext[2]; + return(EOF); + } else { + yylval.p = tostring(yytext); + return(PIC); + } + } + +{A}{B}* { + int c; + Obj *p; + p = lookup(yytext, 1); + if (p->type == DEFNAME) { + c = input(); + unput(c); + if (c == '(') /* it's name(...) */ + dodef(p); + else /* no argument list */ + pbstr(p->val); + } else { + yylval.op = p; + return p->type; /* NAME or VARNAME */ + } + } + +"==" return(EQ); +">=" return(GE); +"<=" return(LE); +"!=" return(NE); +">" return(GT); +"<" return(LT); +"&&" return(AND); +"||" return(OR); +"!" return(NOT); + +\" { BEGIN str; clen = 0; } + +#.* ; + +. { yylval.i = yytext[0]; return(yytext[0]); } + +\" { BEGIN A; cbuf[clen] = 0; + yylval.p = tostring(cbuf); return(STRING); } +\n { ERROR "newline in string" WARNING; BEGIN A; return(ST); } +"\\\"" { cbuf[clen++] = '\\'; cbuf[clen++] = '"'; } +"\\\\" { cbuf[clen++] = '\\'; cbuf[clen++] = '\\'; } +. { CADD; } + +%% blob - /dev/null blob + f558145e1c68aad167714828cf3e488562958162 (mode 644) --- /dev/null +++ src/cmd/grap/input.c @@ -0,0 +1,580 @@ +#include +#include +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +Infile infile[10]; +Infile *curfile = infile; + +#define MAXSRC 50 +Src src[MAXSRC]; /* input source stack */ +Src *srcp = src; + +void pushsrc(int type, char *ptr) /* new input source */ +{ + if (++srcp >= src + MAXSRC) + ERROR "inputs nested too deep" FATAL; + srcp->type = type; + srcp->sp = ptr; + if (dbg) { + printf("\n%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("push file %s\n", ((Infile *)ptr)->fname); + break; + case Macro: + printf("push macro <%s>\n", ptr); + break; + case Char: + printf("push char <%c>\n", *ptr); + break; + case Thru: + printf("push thru\n"); + break; + case String: + printf("push string <%s>\n", ptr); + break; + case Free: + printf("push free <%s>\n", ptr); + break; + default: + ERROR "pushed bad type %d", srcp->type FATAL; + } + } +} + +void popsrc(void) /* restore an old one */ +{ + if (srcp <= src) + ERROR "too many inputs popped" FATAL; + if (dbg) { + printf("%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("pop file\n"); + break; + case Macro: + printf("pop macro\n"); + break; + case Char: + printf("pop char <%c>\n", *srcp->sp); + break; + case Thru: + printf("pop thru\n"); + break; + case String: + printf("pop string\n"); + break; + case Free: + printf("pop free\n"); + break; + default: + ERROR "pop weird input %d", srcp->type FATAL; + } + } + srcp--; +} + +void definition(char *s) /* collect definition for s and install */ + /* definitions picked up lexically */ +{ + char *p; + Obj *stp; + + p = delimstr("definition"); + stp = lookup(s, 0); + if (stp != NULL) { /* it's there before */ + if (stp->type != DEFNAME) { + ERROR "%s used as variable and definition", s WARNING; + return; + } + free(stp->val); + } else { + stp = lookup(s, 1); + stp->type = DEFNAME; + } + stp->val = p; + dprintf("installing %s as `%s'\n", s, p); +} + +char *delimstr(char *s) /* get body of X ... X */ + /* message if too big */ +{ + int c, delim, rdelim, n, deep; + static char *buf = NULL; + static int nbuf = 0; + char *p; + + if (buf == NULL) + buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); + while ((delim = input()) == ' ' || delim == '\t' || delim == '\n') + ; + rdelim = baldelim(delim, "{}"); /* could be "(){}[]`'" */ + deep = 1; + for (p = buf; ; ) { + c = input(); + if (c == rdelim) + if (--deep == 0) + break; + if (c == delim) + deep++; + if (p >= buf + nbuf) { + n = p - buf; + buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); + p = buf + n; + } + if (c == EOF) + ERROR "end of file in %s %c %.20s... %c", s, delim, buf, delim FATAL; + *p++ = c; + } + *p = '\0'; + dprintf("delimstr %s %c <%s> %c\n", s, delim, buf, delim); + return tostring(buf); +} + +baldelim(int c, char *s) /* replace c by balancing entry in s */ +{ + for ( ; *s; s += 2) + if (*s == c) + return s[1]; + return c; +} + +Arg args[10]; /* argument frames */ +Arg *argfp = args; /* frame pointer */ +int argcnt; /* number of arguments seen so far */ + +void dodef(Obj *stp) /* collect args and switch input to defn */ +{ + int i, len; + char *p; + Arg *ap; + + ap = argfp+1; + if (ap >= args+10) + ERROR "arguments too deep" FATAL; + argcnt = 0; + if (input() != '(') + ERROR "disaster in dodef" FATAL; + if (ap->argval == 0) + ap->argval = malloc(1000); + for (p = ap->argval; (len = getarg(p)) != -1; p += len) { + ap->argstk[argcnt++] = p; + if (input() == ')') + break; + } + for (i = argcnt; i < MAXARGS; i++) + ap->argstk[i] = ""; + if (dbg) + for (i = 0; i < argcnt; i++) + printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); + argfp = ap; + pushsrc(Macro, stp->val); +} + +getarg(char *p) /* pick up single argument, store in p, return length */ +{ + int n, c, npar; + + n = npar = 0; + for ( ;; ) { + c = input(); + if (c == EOF) + ERROR "end of file in getarg!" FATAL; + if (npar == 0 && (c == ',' || c == ')')) + break; + if (c == '"') /* copy quoted stuff intact */ + do { + *p++ = c; + n++; + } while ((c = input()) != '"' && c != EOF); + else if (c == '(') + npar++; + else if (c == ')') + npar--; + n++; + *p++ = c; + } + *p = 0; + unput(c); + return(n + 1); +} + +#define PBSIZE 2000 +char pbuf[PBSIZE]; /* pushback buffer */ +char *pb = pbuf-1; /* next pushed back character */ + +char ebuf[200]; /* collect input here for error reporting */ +char *ep = ebuf; + +int begin = 0; +extern int thru; +extern Obj *thrudef; +extern char *untilstr; + +input(void) +{ + register int c; + + if (thru && begin) { + do_thru(); + begin = 0; + } + c = nextchar(); + dprintf(" <%c>", c); + if (ep >= ebuf + sizeof ebuf) + ep = ebuf; + return *ep++ = c; +} + +nextchar(void) +{ + register int c; + + loop: + switch (srcp->type) { + case Free: /* free string */ + free(srcp->sp); + popsrc(); + goto loop; + case Thru: /* end of pushed back line */ + begin = 1; + popsrc(); + c = '\n'; + break; + case Char: + if (pb >= pbuf) { + c = *pb--; + popsrc(); + break; + } else { /* can't happen? */ + popsrc(); + goto loop; + } + case String: + c = *srcp->sp++; + if (c == '\0') { + popsrc(); + goto loop; + } else { + if (*srcp->sp == '\0') /* empty, so pop */ + popsrc(); + break; + } + case Macro: + c = *srcp->sp++; + if (c == '\0') { + if (--argfp < args) + ERROR "argfp underflow" FATAL; + popsrc(); + goto loop; + } else if (c == '$' && isdigit(*srcp->sp)) { /* $3 */ + int n = 0; + while (isdigit(*srcp->sp)) + n = 10 * n + *srcp->sp++ - '0'; + if (n > 0 && n <= MAXARGS) + pushsrc(String, argfp->argstk[n-1]); + goto loop; + } + break; + case File: + c = getc(curfile->fin); + if (c == EOF) { + if (curfile == infile) + ERROR "end of file inside .G1/.G2" FATAL; + if (curfile->fin != stdin) { + fclose(curfile->fin); + free(curfile->fname); /* assumes allocated */ + } + curfile--; + printf(".lf %d %s\n", curfile->lineno, curfile->fname); + popsrc(); + thru = 0; /* chicken out */ + thrudef = 0; + if (untilstr) { + free(untilstr); + untilstr = 0; + } + goto loop; + } + if (c == '\n') + curfile->lineno++; + break; + } + return c; +} + +void do_thru(void) /* read one line, make into a macro expansion */ +{ + int c, i; + char *p; + Arg *ap; + + ap = argfp+1; + if (ap >= args+10) + ERROR "arguments too deep" FATAL; + if (ap->argval == NULL) + ap->argval = malloc(1000); + p = ap->argval; + argcnt = 0; + c = nextchar(); + if (thru == 0) { /* end of file was seen, so thru is done */ + unput(c); + return; + } + for ( ; c != '\n' && c != EOF; ) { + if (c == ' ' || c == '\t') { + c = nextchar(); + continue; + } + if (argcnt >= MAXARGS) + ERROR "too many fields on input line" FATAL; + ap->argstk[argcnt++] = p; + if (c == '"') { + do { + *p++ = c; + if ((c = nextchar()) == '\\') { + *p++ = c; + *p++ = nextchar(); + c = nextchar(); + } + } while (c != '"' && c != '\n' && c != EOF); + *p++ = '"'; + if (c == '"') + c = nextchar(); + } else { + do { + *p++ = c; + } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF); + if (c == ',') + c = nextchar(); + } + *p++ = '\0'; + } + if (c == EOF) + ERROR "unexpected end of file in do_thru" FATAL; + if (argcnt == 0) { /* ignore blank line */ + pushsrc(Thru, (char *) 0); + return; + } + for (i = argcnt; i < MAXARGS; i++) + ap->argstk[i] = ""; + if (dbg) + for (i = 0; i < argcnt; i++) + printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); + if (strcmp(ap->argstk[0], ".G2") == 0) { + thru = 0; + thrudef = 0; + pushsrc(String, "\n.G2\n"); + return; + } + if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) { + thru = 0; + thrudef = 0; + free(untilstr); + untilstr = 0; + return; + } + pushsrc(Thru, (char *) 0); + dprintf("do_thru pushing back <%s>\n", thrudef->val); + argfp = ap; + pushsrc(Macro, thrudef->val); +} + +unput(int c) +{ + if (++pb >= pbuf + sizeof pbuf) + ERROR "pushback overflow" FATAL; + if (--ep < ebuf) + ep = ebuf + sizeof(ebuf) - 1; + *pb = c; + pushsrc(Char, pb); + return c; +} + +void pbstr(char *s) +{ + pushsrc(String, s); +} + +double errcheck(double x, char *s) +{ + extern int errno; + + if (errno == EDOM) { + errno = 0; + ERROR "%s argument out of domain", s WARNING; + } else if (errno == ERANGE) { + errno = 0; + ERROR "%s result out of range", s WARNING; + } + return x; +} + +char errbuf[200]; + +void yyerror(char *s) +{ + extern char *cmdname; + int ern = errno; /* cause some libraries clobber it */ + + if (synerr) + return; + fflush(stdout); + fprintf(stderr, "%s: %s", cmdname, s); + if (ern > 0) { + errno = ern; + perror("???"); + } + fprintf(stderr, " near %s:%d\n", + curfile->fname, curfile->lineno+1); + eprint(); + synerr = 1; + errno = 0; +} + +void eprint(void) /* try to print context around error */ +{ + char *p, *q; + + p = ep - 1; + if (p > ebuf && *p == '\n') + p--; + for ( ; p >= ebuf && *p != '\n'; p--) + ; + while (*p == '\n') + p++; + fprintf(stderr, " context is\n\t"); + for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) + ; + for (; p < q; p++) + if (isprint(*p)) + putc(*p, stderr); + fprintf(stderr, " >>> "); + for (; p < q; p++) + if (isprint(*p)) + putc(*p, stderr); + fprintf(stderr, " <<< "); + while (pb >= pbuf) + putc(*pb--, stderr); + fgets(ebuf, sizeof ebuf, curfile->fin); + fprintf(stderr, "%s", ebuf); + pbstr("\n.G2\n"); /* safety first */ + ep = ebuf; +} + +int yywrap(void) {return 1;} + +char *newfile = 0; /* filename for file copy */ +char *untilstr = 0; /* string that terminates a thru */ +int thru = 0; /* 1 if copying thru macro */ +Obj *thrudef = 0; /* macro being used */ + +void copyfile(char *s) /* remember file to start reading from */ +{ + newfile = s; +} + +void copydef(Obj *p) /* remember macro Obj */ +{ + thrudef = p; +} + +Obj *copythru(char *s) /* collect the macro name or body for thru */ +{ + Obj *p; + char *q; + + p = lookup(s, 0); + if (p != NULL) { + if (p->type == DEFNAME) { + p->val = addnewline(p->val); + return p; + } else + ERROR "%s used as define and name", s FATAL; + } + /* have to collect the definition */ + pbstr(s); /* first char is the delimiter */ + q = delimstr("thru body"); + p = lookup("nameless", 1); + if (p != NULL) + if (p->val) + free(p->val); + p->type = DEFNAME; + p->val = q; + p->val = addnewline(p->val); + dprintf("installing nameless as `%s'\n", p->val); + return p; +} + +char *addnewline(char *p) /* add newline to end of p */ +{ + int n; + + n = strlen(p); + if (p[n-1] != '\n') { + p = realloc(p, n+2); + p[n] = '\n'; + p[n+1] = '\0'; + } + return p; +} + +void copyuntil(char *s) /* string that terminates a thru */ +{ + untilstr = s; +} + +void copy(void) /* begin input from file, etc. */ +{ + FILE *fin; + + if (newfile) { + if ((fin = fopen(unsharp(newfile), "r")) == NULL) + ERROR "can't open file %s", newfile FATAL; + curfile++; + curfile->fin = fin; + curfile->fname = tostring(newfile); + curfile->lineno = 0; + printf(".lf 1 %s\n", curfile->fname); + pushsrc(File, curfile->fname); + newfile = 0; + } + if (thrudef) { + thru = 1; + begin = 1; /* wrong place */ + } +} + +char shellbuf[1000], *shellp; + +void shell_init(void) /* set up to interpret a shell command */ +{ + fprintf(tfd, "# shell cmd...\n"); + sprintf(shellbuf, "rc -c '"); + shellp = shellbuf + strlen(shellbuf); +} + +void shell_text(char *s) /* add string to command being collected */ +{ + /* fprintf(tfd, "#add <%s> to <%s>\n", s, shellbuf); */ + while (*s) { + if (*s == '\'') { /* protect interior quotes */ + *shellp++ = '\''; + *shellp++ = '\\'; + *shellp++ = '\''; + } + *shellp++ = *s++; + } +} + +void shell_exec(void) /* do it */ +{ + /* fprintf(tfd, "# run <%s>\n", shellbuf); */ + *shellp++ = '\''; + *shellp = '\0'; + system(shellbuf); +} blob - /dev/null blob + e788dd9d9d21102ec53f62e8955cd5e7e489e0c6 (mode 644) --- /dev/null +++ src/cmd/grap/label.c @@ -0,0 +1,123 @@ +#include +#include +#include "grap.h" +#include "y.tab.h" + +int pointsize = 10; /* assumed pointsize to start */ +int ps_set = 0; /* someone has set pointsize explicitly */ + +double textht = 1.0/6.0; /* 6 lines/inch */ +double textwid = 1; /* width of text box for vertical */ + +double lab_up = 0.0; /* extra motion for label */ +double lab_rt = 0.0; /* extra motion for label */ +double lab_wid = 0.0; /* override default width computation */ + +void labelwid(double amt) +{ + lab_wid = amt + .00001; +} + +void labelmove(int dir, double amt) /* record direction & motion of position corr */ +{ + switch (dir) { + case UP: lab_up += amt; break; + case DOWN: lab_up -= amt; break; + case LEFT: lab_rt -= amt; break; + case RIGHT: lab_rt += amt; break; + } +} + +void label(int label_side, Attr *stringlist) /* stick label on label_side */ +{ + int m; + Attr *ap; + + fprintf(tfd, "\ttextht = %g\n", textht); + if (lab_wid != 0.0) { + fprintf(tfd, "\ttextwid = %g\n", lab_wid); + lab_wid = 0; + } else if (label_side == LEFT || label_side == RIGHT) { + textwid = 0; + for (ap = stringlist; ap != NULL; ap = ap->next) + if ((m = strlen(ap->sval)) > textwid) + textwid = m; + textwid /= 15; /* estimate width at 15 chars/inch */ + fprintf(tfd, "\ttextwid = %g\n", textwid); + } + fprintf(tfd, "Label:\t%s", slprint(stringlist)); + freeattr(stringlist); + switch (label_side) { + case BOT: + case 0: + fprintf(tfd, " with .n at Frame.s - (0,2 * textht)"); + break; + case LEFT: + fprintf(tfd, " wid textwid with .e at Frame.w - (0.2,0)"); + break; + case RIGHT: + fprintf(tfd, " wid textwid with .w at Frame.e + (0.2,0)"); + break; + case TOP: + fprintf(tfd, " with .s at Frame.n + (0,2 * textht)"); + break; + } + lab_adjust(); + fprintf(tfd, "\n"); + label_side = BOT; +} + +void lab_adjust(void) /* add a string to adjust labels, ticks, etc. */ +{ + if (lab_up != 0.0 || lab_rt != 0.0) + fprintf(tfd, " + (%g,%g)", lab_rt, lab_up); +} + +char *sizeit(Attr *ap) /* add \s..\s to ap->sval */ +{ + int n; + static char buf[1000]; + + if (!ap->op) { /* no explicit size command */ + if (ps_set) { + sprintf(buf, "\\s%d%s\\s0", pointsize, ap->sval); + return buf; + } else + return ap->sval; + } else if (!ps_set) { /* explicit size but no global size */ + n = (int) ap->fval; + switch (ap->op) { + case ' ': /* absolute size */ + sprintf(buf, "\\s%d%s\\s0", n, ap->sval); + break; + case '+': /* better be only one digit! */ + sprintf(buf, "\\s+%d%s\\s-%d", n, ap->sval, n); + break; + case '-': + sprintf(buf, "\\s-%d%s\\s+%d", n, ap->sval, n); + break; + case '*': + case '/': + return ap->sval; /* ignore for now */ + } + return buf; + } else { + /* explicit size and a global background size */ + n = (int) ap->fval; + switch (ap->op) { + case ' ': /* absolute size */ + sprintf(buf, "\\s%d%s\\s0", n, ap->sval); + break; + case '+': + sprintf(buf, "\\s%d%s\\s0", pointsize+n, ap->sval); + break; + case '-': + sprintf(buf, "\\s%d%s\\s0", pointsize-n, ap->sval); + break; + case '*': + case '/': + return ap->sval; /* ignore for now */ + } + return buf; + } +} blob - /dev/null blob + 0aa674176e8f752ea61a9a3fd81303fa391aac47 (mode 644) --- /dev/null +++ src/cmd/grap/main.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +int dbg = 0; + +#ifndef GRAPDEFINES +#define GRAPDEFINES "#9/sys/lib/grap.defines" +#endif +char *lib_defines = GRAPDEFINES; + +int lib = 1; /* 1 to include lib_defines */ +FILE *tfd = NULL; +char tempfile[L_tmpnam]; + +int synerr = 0; +int codegen = 0; /* 1=>output for this picture; 0=>no output */ +char *cmdname; + +Obj *objlist = NULL; /* all names stored here */ + +#define BIG 1e30 +Point ptmin = { NULL, -BIG, -BIG }; +Point ptmax = { NULL, BIG, BIG }; + +char *version = "version Dec 30, 1995"; + +extern int yyparse(void); +extern void setdefaults(void); +extern void getdata(void); +extern int unlink(char *); + +main(int argc, char *argv[]) +{ + extern void onintr(int), fpecatch(int); + + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, onintr); + signal(SIGFPE, fpecatch); + cmdname = argv[0]; + tmpnam(tempfile); + while (argc > 1 && *argv[1] == '-') { + switch (argv[1][1]) { + case 'd': + dbg = 1; + tfd = stdout; + strcpy(tempfile, "grap.temp"); + unlink(tempfile); + fprintf(stderr, "%s\n", version); + break; + case 'l': /* turn off /usr/lib inclusion */ + lib = 0; + break; + } + argc--; + argv++; + } + setdefaults(); + curfile = infile; + if (argc <= 1) { + curfile->fin = stdin; + curfile->fname = tostring("-"); + pushsrc(File, curfile->fname); + getdata(); + } else + while (argc-- > 1) { + if ((curfile->fin = fopen(*++argv, "r")) == NULL) { + fprintf(stderr, "grap: can't open %s\n", *argv); + onintr(0); + } + curfile->fname = tostring(*argv); + pushsrc(File, curfile->fname); + getdata(); + fclose(curfile->fin); + free(curfile->fname); + } + if (!dbg) + unlink(tempfile); + exit(0); +} + +void onintr(int n) +{ + n; + if (!dbg) + unlink(tempfile); + exit(1); +} + +void fpecatch(int n) +{ + ERROR "floating point exception" WARNING; + onintr(n); +} + +char *grow(char *ptr, char *name, int num, int size) /* make array bigger */ +{ + char *p; + + if (ptr == NULL) + p = malloc(num * size); + else + p = realloc(ptr, num * size); + if (p == NULL) + ERROR "can't grow %s to %d", name, num * size FATAL; + return p; +} + +static struct { + char *name; + double val; +} defaults[] ={ + "frameht", FRAMEHT, + "framewid", FRAMEWID, + "ticklen", TICKLEN, + "slop", SLOP, + NULL, 0 +}; + +void setdefaults(void) /* set default sizes for variables */ +{ + int i; + Obj *p; + + for (i = 0; defaults[i].name != NULL; i++) { + p = lookup(defaults[i].name, 1); + setvar(p, defaults[i].val); + } +} + +void getdata(void) /* read input */ +{ + register FILE *fin; + char buf[1000], buf1[100]; + int ln; + + fin = curfile->fin; + curfile->lineno = 0; + printf(".lf 1 %s\n", curfile->fname); + while (fgets(buf, sizeof buf, fin) != NULL) { + curfile->lineno++; + if (*buf == '.' && *(buf+1) == 'G' && *(buf+2) == '1') { + setup(); + fprintf(stdout, ".PS%s", &buf[3]); /* maps .G1 [w] to .PS w */ + printf("scale = 1\n"); /* defends against cip users */ + printf(".lf %d\n", curfile->lineno+1); + yyparse(); + fprintf(stdout, ".PE\n"); + printf(".lf %d\n", curfile->lineno+1); + fflush(stdout); + } else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') { + if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) { + free(curfile->fname); + printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = tostring(buf1)); + } else + printf(".lf %d\n", curfile->lineno = ln); + } else + fputs(buf, stdout); + } +} blob - /dev/null blob + 7a68a69277f0bdf1473ea2912fdeac3ae663fe69 (mode 644) --- /dev/null +++ src/cmd/grap/misc.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +int nnum = 0; /* number of saved numbers */ +double num[MAXNUM]; + +int just; /* current justification mode (RJUST, etc.) */ +int sizeop; /* current optional operator for size change */ +double sizexpr; /* current size change expression */ + +void savenum(int n, double f) /* save f in num[n] */ +{ + num[n] = f; + nnum = n+1; + if (nnum >= MAXNUM) + ERROR "too many numbers" WARNING; +} + +void setjust(int j) +{ + just |= j; +} + +void setsize(int op, double expr) +{ + sizeop = op; + sizexpr = expr; +} + +char *tostring(char *s) +{ + register char *p; + + p = malloc(strlen(s)+1); + if (p == NULL) + ERROR "out of space in tostring on %s", s FATAL; + strcpy(p, s); + return(p); +} + +void range(Point pt) /* update the range for point pt */ +{ + Obj *p = pt.obj; + + if (!(p->coord & XFLAG)) { + if (pt.x > p->pt1.x) + p->pt1.x = pt.x; + if (pt.x < p->pt.x) + p->pt.x = pt.x; + } + if (!(p->coord & YFLAG)) { + if (pt.y > p->pt1.y) + p->pt1.y = pt.y; + if (pt.y < p->pt.y) + p->pt.y = pt.y; + } +} + +void halfrange(Obj *p, int side, double val) /* record max and min for one direction */ +{ + if (!(p->coord&XFLAG) && (side == LEFT || side == RIGHT)) { + if (val < p->pt.y) + p->pt.y = val; + if (val > p->pt1.y) + p->pt1.y = val; + } else if (!(p->coord&YFLAG) && (side == TOP || side == BOT)) { + if (val < p->pt.x) + p->pt.x = val; + if (val > p->pt1.x) + p->pt1.x = val; + } +} + + +Obj *lookup(char *s, int inst) /* find s in objlist, install if inst */ +{ + Obj *p; + int found = 0; + + for (p = objlist; p; p = p->next){ + if (strcmp(s, p->name) == 0) { + found = 1; + break; + } + } + if (p == NULL && inst != 0) { + p = (Obj *) calloc(1, sizeof(Obj)); + if (p == NULL) + ERROR "out of space in lookup" FATAL; + p->name = tostring(s); + p->type = NAME; + p->pt = ptmax; + p->pt1 = ptmin; + p->fval = 0.0; + p->next = objlist; + objlist = p; + } + dprintf("lookup(%s,%d) = %d\n", s, inst, found); + return p; +} + +double getvar(Obj *p) /* return value of variable */ +{ + return p->fval; +} + +double setvar(Obj *p, double f) /* set value of variable to f */ +{ + if (strcmp(p->name, "pointsize") == 0) { /* kludge */ + pointsize = f; + ps_set = 1; + } + p->type = VARNAME; + return p->fval = f; +} + +Point makepoint(Obj *s, double x, double y) /* make a Point */ +{ + Point p; + + dprintf("makepoint: %s, %g,%g\n", s->name, x, y); + p.obj = s; + p.x = x; + p.y = y; + return p; +} + +Attr *makefattr(int type, double fval) /* set double in attribute */ +{ + return makeattr(type, fval, (char *) 0, 0, 0); +} + +Attr *makesattr(char *s) /* make an Attr cell containing s */ +{ + Attr *ap = makeattr(STRING, sizexpr, s, just, sizeop); + just = sizeop = 0; + sizexpr = 0.0; + return ap; +} + +Attr *makeattr(int type, double fval, char *sval, int just, int op) +{ + Attr *a; + + a = (Attr *) malloc(sizeof(Attr)); + if (a == NULL) + ERROR "out of space in makeattr" FATAL; + a->type = type; + a->fval = fval; + a->sval = sval; + a->just = just; + a->op = op; + a->next = NULL; + return a; +} + +Attr *addattr(Attr *a1, Attr *ap) /* add attr ap to end of list a1 */ +{ + Attr *p; + + if (a1 == 0) + return ap; + if (ap == 0) + return a1; + for (p = a1; p->next; p = p->next) + ; + p->next = ap; + return a1; +} + +void freeattr(Attr *ap) /* free an attribute list */ +{ + Attr *p; + + while (ap) { + p = ap->next; /* save next */ + if (ap->sval) + free(ap->sval); + free((char *) ap); + ap = p; + } +} + +char *slprint(Attr *stringlist) /* print strings from stringlist */ +{ + int ntext, n, last_op, last_just; + double last_fval; + static char buf[1000]; + Attr *ap; + + buf[0] = '\0'; + last_op = last_just = 0; + last_fval = 0.0; + for (ntext = 0, ap = stringlist; ap != NULL; ap = ap->next) + ntext++; + sprintf(buf, "box invis wid 0 ht %d*textht", ntext); + n = strlen(buf); + for (ap = stringlist; ap != NULL; ap = ap->next) { + if (ap->op == 0) { /* propagate last value */ + ap->op = last_op; + ap->fval = last_fval; + } else { + last_op = ap->op; + last_fval = ap->fval; + } + sprintf(buf+n, " \"%s\"", ps_set || ap->op ? sizeit(ap) : ap->sval); + if (ap->just) + last_just = ap->just; + if (last_just) + strcat(buf+n, juststr(last_just)); + n = strlen(buf); + } + return buf; /* watch it: static */ +} + +char *juststr(int j) /* convert RJUST, etc., into string */ +{ + static char buf[50]; + + buf[0] = '\0'; + if (j & RJUST) + strcat(buf, " rjust"); + if (j & LJUST) + strcat(buf, " ljust"); + if (j & ABOVE) + strcat(buf, " above"); + if (j & BELOW) + strcat(buf, " below"); + return buf; /* watch it: static */ +} + +char *sprntf(char *s, Attr *ap) /* sprintf(s, attrlist ap) */ +{ + char buf[500]; + int n; + Attr *p; + + for (n = 0, p = ap; p; p = p->next) + n++; + switch (n) { + case 0: + return s; + case 1: + sprintf(buf, s, ap->fval); + break; + case 2: + sprintf(buf, s, ap->fval, ap->next->fval); + break; + case 3: + sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval); + break; + case 5: + ERROR "too many expressions in sprintf" WARNING; + case 4: + sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval, ap->next->next->next->fval); + break; + } + free(s); + return tostring(buf); +} blob - /dev/null blob + 872497d1222c20eda3c7ec8a2ebe186b38f6f8e8 (mode 644) --- /dev/null +++ src/cmd/grap/mkfile @@ -0,0 +1,37 @@ +<$PLAN9/src/mkhdr + +TARG=grap +OFILES=\ + grap.$O\ + grapl.$O\ + main.$O\ + input.$O\ + print.$O\ + frame.$O\ + for.$O\ + coord.$O\ + ticks.$O\ + plot.$O\ + label.$O\ + misc.$O\ + +HFILES=grap.h\ + y.tab.h\ + +YFILES=grap.y\ + +LFILES=grapl.lx\ + +SHORTLIB=bio 9 +<$PLAN9/src/mkone +YFLAGS = -d -S +LEX=9lex + +grap.c: y.tab.c + mv $prereq $target + +grapl.c: $LFILES + $LEX -t $prereq > $target + +clean:V: + rm -f [$OS].out *.[$OS] y.tab.? lex.yy.c grapl.c grap.c grap blob - /dev/null blob + ab375953618e1da406827341fa5d8ec3b3453ec3 (mode 644) --- /dev/null +++ src/cmd/grap/plot.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +void line(int type, Point p1, Point p2, Attr *desc) /* draw a line segment */ +{ + fprintf(tfd, "%s %s from %s", + type==LINE ? "line" : "arrow", desc_str(desc), xyname(p1)); + fprintf(tfd, " to %s", xyname(p2)); /* 'cause xyname is botched */ + fprintf(tfd, "\n"); + range(p1); + range(p2); +} + +void circle(double r, Point pt) /* draw a circle */ +{ + if (r > 0.0) + fprintf(tfd, "circle rad %g at %s\n", r, xyname(pt)); + else + fprintf(tfd, "\"\\s-3\\(ob\\s0\" at %s\n", xyname(pt)); + range(pt); +} + +char *xyname(Point pt) /* generate xy name macro for point p */ +{ + static char buf[200]; + Obj *p; + + p = pt.obj; + if (p->log & XFLAG) { + if (pt.x <= 0.0) + ERROR "can't take log of x coord %g", pt.x FATAL; + logit(pt.x); + } + if (p->log & YFLAG) { + if (pt.y <= 0.0) + ERROR "can't take log of y coord %g", pt.y FATAL; + logit(pt.y); + } + sprintf(buf, "xy_%s(%g,%g)", p->name, pt.x, pt.y); + return buf; /* WATCH IT: static */ +} + +void pic(char *s) /* fire out pic stuff directly */ +{ + while (*s == ' ') + s++; + fprintf(tfd, "%s\n", s); +} + +int auto_x = 0; /* counts abscissa if none provided */ + +void numlist(void) /* print numbers in default way */ +{ + Obj *p; + Point pt; + int i; + static char *spot = "\\(bu"; + Attr *ap; + + p = pt.obj = lookup(curr_coord, 1); + if (nnum == 1) { + nnum = 2; + num[1] = num[0]; + num[0] = ++auto_x; + } + pt.x = num[0]; + if (p->attr && p->attr->sval) + spot = p->attr->sval; + for (i = 1; i < nnum; i++) { + pt.y = num[i]; + if (p->attr == 0 || p->attr->type == 0) { + ap = makesattr(tostring(spot)); + plot(ap, pt); + } else + next(p, pt, p->attr); + } + nnum = 0; +} + +void plot(Attr *sl, Point pt) /* put stringlist sl at point pt */ +{ + fprintf(tfd, "%s at %s\n", slprint(sl), xyname(pt)); + range(pt); + freeattr(sl); +} + +void plotnum(double f, char *fmt, Point pt) /* plot value f at point */ +{ + char buf[100]; + + if (fmt) { + sprintf(buf, fmt, f); + free(fmt); + } else if (f >= 0.0) + sprintf(buf, "%g", f); + else + sprintf(buf, "\\-%g", -f); + fprintf(tfd, "\"%s\" at %s\n", buf, xyname(pt)); + range(pt); +} + +void drawdesc(int type, Obj *p, Attr *desc, char *s) /* set line description for p */ +{ + p->attr = desc; + p->attr->sval = s; + if (type == NEW) { + p->first = 0; /* so it really looks new */ + auto_x = 0; + } +} + +void next(Obj *p, Point pt, Attr *desc) /* add component to a path */ +{ + char *s; + + if (p->first == 0) { + p->first++; + fprintf(tfd, "L%s: %s\n", p->name, xyname(pt)); + } else { + fprintf(tfd, "line %s from L%s to %s; L%s: Here\n", + desc_str(desc->type ? desc : p->attr), + p->name, xyname(pt), p->name); + } + if (p->attr && (s=p->attr->sval)) { + /* BUG: should fix size here */ + fprintf(tfd, "\"%s\" at %s\n", s, xyname(pt)); + } + range(pt); +} blob - /dev/null blob + 8f553c8f3b3b6a1481144290ce09b4fa1414e9e5 (mode 644) --- /dev/null +++ src/cmd/grap/print.c @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +double margin = MARGIN; /* extra space around edges */ +extern double frame_ht, frame_wid, ticklen; +extern int just, sizeop, tick_dir; +extern double sizexpr, lab_up, lab_rt; + +char graphname[50] = "Graph"; +char graphpos[200] = ""; + +void print(void) /* arrange final output */ +{ + FILE *fd; + Obj *p, *dfp; + int c; + double dx, dy, xfac, yfac; + + if (tfd != NULL) { + fclose(tfd); /* end the temp file */ + tfd = stdout; + } + + if ((p=lookup("margin",0)) != NULL) + margin = p->fval; + if (frame_ht < 0) /* wasn't set explicitly, so use default */ + frame_ht = getvar(lookup("frameht", 0)); + if (frame_wid < 0) + frame_wid = getvar(lookup("framewid", 0)); + dfp = NULL; + for (p = objlist; p; p = p->next) { + dprintf("print: name = <%s>, type = %d\n", p->name, p->type); + if (p->type == NAME) { + Point pt, pt1; + pt = p->pt; + pt1 = p->pt1; + fprintf(tfd, "\t# %s %g .. %g, %g .. %g\n", + p->name, pt.x, pt1.x, pt.y, pt1.y); + if (p->log & XFLAG) { + if (pt.x <= 0.0) + ERROR "can't take log of x coord %g", pt.x FATAL; + logit(pt.x); + logit(pt1.x); + } + if (p->log & YFLAG) { + if (pt.y <= 0.0) + ERROR "can't take log of y coord %g", pt.y FATAL; + logit(pt.y); + logit(pt1.y); + } + if (!(p->coord & XFLAG)) { + dx = pt1.x - pt.x; + pt.x -= margin * dx; + pt1.x += margin * dx; + } + if (!(p->coord & YFLAG)) { + dy = pt1.y - pt.y; + pt.y -= margin * dy; + pt1.y += margin * dy; + } + if (autoticks && strcmp(p->name, dflt_coord) == 0) { + p->pt = pt; + p->pt1 = pt1; + if (p->log & XFLAG) { + p->pt.x = pow(10.0, pt.x); + p->pt1.x = pow(10.0, pt1.x); + } + if (p->log & YFLAG) { + p->pt.y = pow(10.0, pt.y); + p->pt1.y = pow(10.0, pt1.y); + } + dfp = setauto(); + } + dx = pt1.x - pt.x; + dy = pt1.y - pt.y; + xfac = dx > 0 ? frame_wid/dx : frame_wid/2; + yfac = dy > 0 ? frame_ht/dy : frame_ht/2; + + fprintf(tfd, "define xy_%s @ ", p->name); + if (dx > 0) + fprintf(tfd, "\t(($1)-(%g))*%g", pt.x, xfac); + else + fprintf(tfd, "\t%g", xfac); + if (dy > 0) + fprintf(tfd, ", (($2)-(%g))*%g @\n", pt.y, yfac); + else + fprintf(tfd, ", %g @\n", yfac); + fprintf(tfd, "define x_%s @ ", p->name); + if (dx > 0) + fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.x, xfac); + else + fprintf(tfd, "\t%g @\n", xfac); + fprintf(tfd, "define y_%s @ ", p->name); + if (dy > 0) + fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.y, yfac); + else + fprintf(tfd, "\t%g @\n", yfac); + } + } + if (codegen) + frame(); + if (codegen && autoticks && dfp) + do_autoticks(dfp); + + if ((fd = fopen(tempfile, "r")) != NULL) { + while ((c = getc(fd)) != EOF) + putc(c, tfd); + fclose(fd); + } + tfd = NULL; +} + +void endstat(void) /* clean up after each statement */ +{ + + just = sizeop = 0; + lab_up = lab_rt = 0.0; + sizexpr = 0.0; + nnum = 0; + ntick = 0; + tside = 0; + tick_dir = OUT; + ticklen = TICKLEN; +} + +void graph(char *s) /* graph statement */ +{ + char *p, *os; + int c; + + if (codegen) { + fprintf(stdout, "%s: [\n", graphname); + print(); /* pump out previous graph */ + fprintf(stdout, "\n] %s\n", graphpos); + reset(); + } + if (s) { + dprintf("into graph with <%s>\n", s); + opentemp(); + os = s; + while ((c = *s) == ' ' || c == '\t') + s++; + if (c == '\0') + ERROR "no name on graph statement" WARNING; + if (!isupper(s[0])) + ERROR "graph name %s must be capitalized", s WARNING; + for (p=graphname; (c = *s) != ' ' && c != '\t' && c != '\0'; ) + *p++ = *s++; + *p = '\0'; + strcpy(graphpos, s); + dprintf("graphname = <%s>, graphpos = <%s>\n", graphname, graphpos); + free(os); + } +} + +void setup(void) /* done at each .G1 */ +{ + static int firstG1 = 0; + + reset(); + opentemp(); + frame_ht = frame_wid = -1; /* reset in frame() */ + ticklen = getvar(lookup("ticklen", 0)); + if (firstG1++ == 0) + do_first(); + codegen = synerr = 0; + strcpy(graphname, "Graph"); + strcpy(graphpos, ""); +} + +void do_first(void) /* done at first .G1: definitions, etc. */ +{ + extern int lib; + extern char *lib_defines; + static char buf[50], buf1[50]; /* static because pbstr uses them */ + FILE *fp; + extern int getpid(void); + + sprintf(buf, "define pid /%d/\n", getpid()); + pbstr(buf); + if (lib != 0) { + if ((fp = fopen(unsharp(lib_defines), "r")) != NULL) { + sprintf(buf1, "copy \"%s\"\n", lib_defines); + pbstr(buf1); + fclose(fp); + } else { + fprintf(stderr, "grap warning: can't open %s\n", lib_defines); + } + } +} + +void reset(void) /* done at each "graph ..." statement */ +{ + Obj *p, *np, *deflist; + extern int tlist, toffside, autodir; + + curr_coord = dflt_coord; + ncoord = auto_x = 0; + autoticks = LEFT|BOT; + autodir = 0; + tside = tlist = toffside = 0; + tick_dir = OUT; + margin = MARGIN; + deflist = NULL; + for (p = objlist; p; p = np) { + np = p->next; + if (p->type == DEFNAME || p->type == VARNAME) { + p->next = deflist; + deflist = p; + } else { + free(p->name); + freeattr(p->attr); + free((char *) p); + } + } + objlist = deflist; +} + +void opentemp(void) +{ + if (tfd != NULL) + fclose(tfd); + if (tfd != stdout) { +// if (tfd != NULL) +// fclose(tfd); + if ((tfd = fopen(tempfile, "w")) == NULL) { + fprintf(stderr, "grap: can't open %s\n", tempfile); + exit(1); + } + } +} blob - /dev/null blob + 72fc06f54bf2cfa4b73f12033ab099faa6254053 (mode 644) --- /dev/null +++ src/cmd/grap/ticks.c @@ -0,0 +1,492 @@ +#include +#include +#include +#include +#include "grap.h" +#include "y.tab.h" + +#define MAXTICK 200 +int ntick = 0; +double tickval[MAXTICK]; /* tick values (one axis at a time */ +char *tickstr[MAXTICK]; /* and labels */ + +int tside = 0; +int tlist = 0; /* 1 => explicit values given */ +int toffside = 0; /* no ticks on these sides */ +int goffside = 0; /* no ticks on grid on these sides */ +int tick_dir = OUT; +double ticklen = TICKLEN; /* default tick length */ +int autoticks = LEFT|BOT; +int autodir = 0; /* set LEFT, etc. if automatic ticks go in */ + +void savetick(double f, char *s) /* remember tick location and label */ +{ + if (ntick >= MAXTICK) + ERROR "too many ticks (%d)", MAXTICK FATAL; + tickval[ntick] = f; + tickstr[ntick] = s; + ntick++; +} + +void dflt_tick(double f) +{ + if (f >= 0.0) + savetick(f, tostring("%g")); + else + savetick(f, tostring("\\%g")); +} + +void tickside(int n) /* remember which side these ticks/gridlines go on */ +{ + tside |= n; +} + +void tickoff(int side) /* remember explicit sides */ +{ + toffside |= side; +} + +void gridtickoff(void) /* turn grid ticks off on the side previously specified (ugh) */ +{ + goffside = tside; +} + +void setlist(void) /* remember that there was an explicit list */ +{ + tlist = 1; +} + +void tickdir(int dir, double val, int explicit) /* remember in/out [expr] */ +{ + tick_dir = dir; + if (explicit) + ticklen = val; +} + +void ticks(void) /* set autoticks after ticks statement */ +{ + /* was there an explicit "ticks [side] off"? */ + if (toffside) + autoticks &= ~toffside; + /* was there an explicit list? (eg "ticks at ..." or "ticks from ...") */ + if (tlist) { + if (tside & (BOT|TOP)) + autoticks &= ~(BOT|TOP); + if (tside & (LEFT|RIGHT)) + autoticks &= ~(LEFT|RIGHT); + } + /* was there a side without a list? (eg "ticks left in") */ + if (tside && !tlist) { + if (tick_dir == IN) + autodir |= tside; + if (tside & (BOT|TOP)) + autoticks = (autoticks & ~(BOT|TOP)) | (tside & (BOT|TOP)); + if (tside & (LEFT|RIGHT)) + autoticks = (autoticks & ~(LEFT|RIGHT)) | (tside & (LEFT|RIGHT)); + } + tlist = tside = toffside = goffside = 0; + tick_dir = OUT; +} + +double modfloor(double f, double t) +{ + t = fabs(t); + return floor(f/t) * t; +} + +double modceil(double f, double t) +{ + t = fabs(t); + return ceil(f/t) * t; +} + +double xtmin, xtmax; /* range of ticks */ +double ytmin, ytmax; +double xquant, xmult; /* quantization & scale for auto x ticks */ +double yquant, ymult; +double lograt = 5; + +void do_autoticks(Obj *p) /* make set of ticks for default coord only */ +{ + double x, xl, xu, q; + + if (p == NULL) + return; + fprintf(tfd, "Autoticks:\t# x %g..%g, y %g..%g", + p->pt.x, p->pt1.x, p->pt.y, p->pt1.y); + fprintf(tfd, "; xt %g,%g, yt %g,%g, xq,xm = %g,%g, yq,ym = %g,%g\n", + xtmin, xtmax, ytmin, ytmax, xquant, xmult, yquant, ymult); + if ((autoticks & (BOT|TOP)) && p->pt1.x >= p->pt.x) { /* make x ticks */ + q = xquant; + xl = p->pt.x; + xu = p->pt1.x; + if (xl >= xu) + dflt_tick(xl); + else if ((p->log & XFLAG) && xu/xl >= lograt) { + for (x = q; x < xu; x *= 10) { + logtick(x, xl, xu); + if (xu/xl <= 100) { + logtick(2*x, xl, xu); + logtick(5*x, xl, xu); + } + } + } else { + xl = modceil(xtmin - q/100, q); + xu = modfloor(xtmax + q/100, q) + q/2; + for (x = xl; x <= xu; x += q) + dflt_tick(x); + } + tside = autoticks & (BOT|TOP); + ticklist(p, 0); + } + if ((autoticks & (LEFT|RIGHT)) && p->pt1.y >= p->pt.y) { /* make y ticks */ + q = yquant; + xl = p->pt.y; + xu = p->pt1.y; + if (xl >= xu) + dflt_tick(xl); + else if ((p->log & YFLAG) && xu/xl >= lograt) { + for (x = q; x < xu; x *= 10) { + logtick(x, xl, xu); + if (xu/xl <= 100) { + logtick(2*x, xl, xu); + logtick(5*x, xl, xu); + } + } + } else { + xl = modceil(ytmin - q/100, q); + xu = modfloor(ytmax + q/100, q) + q/2; + for (x = xl; x <= xu; x += q) + dflt_tick(x); + } + tside = autoticks & (LEFT|RIGHT); + ticklist(p, 0); + } +} + +void logtick(double v, double lb, double ub) +{ + float slop = 1.0; /* was 1.001 */ + + if (slop * lb <= v && ub >= slop * v) + dflt_tick(v); +} + +Obj *setauto(void) /* compute new min,max, and quant & mult */ +{ + Obj *p, *q; + + if ((q = lookup("lograt",0)) != NULL) + lograt = q->fval; + for (p = objlist; p; p = p->next) + if (p->type == NAME && strcmp(p->name,dflt_coord) == 0) + break; + if (p) { + if ((p->log & XFLAG) && p->pt1.x/p->pt.x >= lograt) + autolog(p, 'x'); + else + autoside(p, 'x'); + if ((p->log & YFLAG) && p->pt1.y/p->pt.y >= lograt) + autolog(p, 'y'); + else + autoside(p, 'y'); + } + return p; +} + +void autoside(Obj *p, int side) +{ + double r, s, d, ub, lb; + + if (side == 'x') { + xtmin = lb = p->pt.x; + xtmax = ub = p->pt1.x; + } else { + ytmin = lb = p->pt.y; + ytmax = ub = p->pt1.y; + } + if (ub <= lb) + return; /* cop out on little ranges */ + d = ub - lb; + r = s = 1; + while (d * s < 10) + s *= 10; + d *= s; + while (10 * r < d) + r *= 10; + if (r > d/3) + r /= 2; + else if (r <= d/6) + r *= 2; + if (side == 'x') { + xquant = r / s; + } else { + yquant = r / s; + } +} + +void autolog(Obj *p, int side) +{ + double r, s, t, ub, lb; + int flg; + + if (side == 'x') { + xtmin = lb = p->pt.x; + xtmax = ub = p->pt1.x; + flg = p->coord & XFLAG; + } else { + ytmin = lb = p->pt.y; + ytmax = ub = p->pt1.y; + flg = p->coord & YFLAG; + } + for (s = 1; lb * s < 1; s *= 10) + ; + lb *= s; + ub *= s; + for (r = 1; 10 * r < lb; r *= 10) + ; + for (t = 1; t < ub; t *= 10) + ; + if (side == 'x') + xquant = r / s; + else + yquant = r / s; + if (flg) + return; + if (ub / lb < 100) { + if (lb >= 5 * r) + r *= 5; + else if (lb >= 2 * r) + r *= 2; + if (ub * 5 <= t) + t /= 5; + else if (ub * 2 <= t) + t /= 2; + if (side == 'x') { + xtmin = r / s; + xtmax = t / s; + } else { + ytmin = r / s; + ytmax = t / s; + } + } +} + +void iterator(double from, double to, int op, double by, char *fmt) /* create an iterator */ +{ + double x; + + /* should validate limits, etc. */ + /* punt for now */ + + dprintf("iterate from %g to %g by %g, op = %c, fmt=%s\n", + from, to, by, op, fmt ? fmt : ""); + switch (op) { + case '+': + case ' ': + for (x = from; x <= to + (SLOP-1) * by; x += by) + if (fmt) + savetick(x, tostring(fmt)); + else + dflt_tick(x); + break; + case '-': + for (x = from; x >= to; x -= by) + if (fmt) + savetick(x, tostring(fmt)); + else + dflt_tick(x); + break; + case '*': + for (x = from; x <= SLOP * to; x *= by) + if (fmt) + savetick(x, tostring(fmt)); + else + dflt_tick(x); + break; + case '/': + for (x = from; x >= to; x /= by) + if (fmt) + savetick(x, tostring(fmt)); + else + dflt_tick(x); + break; + } + if (fmt) + free(fmt); +} + +void ticklist(Obj *p, int explicit) /* fire out the accumulated ticks */ + /* 1 => list, 0 => auto */ +{ + if (p == NULL) + return; + fprintf(tfd, "Ticks_%s:\n\tticklen = %g\n", p->name, ticklen); + print_ticks(TICKS, explicit, p, "ticklen", ""); +} + +void print_ticks(int type, int explicit, Obj *p, char *lenstr, char *descstr) +{ + int i, logflag, inside; + char buf[100]; + double tv; + + for (i = 0; i < ntick; i++) /* any ticks given explicitly? */ + if (tickstr[i] != NULL) + break; + if (i >= ntick && type == TICKS) /* no, so use values */ + for (i = 0; i < ntick; i++) { + if (tickval[i] >= 0.0) + sprintf(buf, "%g", tickval[i]); + else + sprintf(buf, "\\-%g", -tickval[i]); + tickstr[i] = tostring(buf); + } + else + for (i = 0; i < ntick; i++) { + if (tickstr[i] != NULL) { + sprintf(buf, tickstr[i], tickval[i]); + free(tickstr[i]); + tickstr[i] = tostring(buf); + } + } + logflag = sidelog(p->log, tside); + for (i = 0; i < ntick; i++) { + tv = tickval[i]; + halfrange(p, tside, tv); + if (logflag) { + if (tv <= 0.0) + ERROR "can't take log of tick value %g", tv FATAL; + logit(tv); + } + if (type == GRID) + inside = LEFT|RIGHT|TOP|BOT; + else if (explicit) + inside = (tick_dir == IN) ? tside : 0; + else + inside = autodir; + if (tside & BOT) + maketick(type, p->name, BOT, inside, tv, tickstr[i], lenstr, descstr); + if (tside & TOP) + maketick(type, p->name, TOP, inside, tv, tickstr[i], lenstr, descstr); + if (tside & LEFT) + maketick(type, p->name, LEFT, inside, tv, tickstr[i], lenstr, descstr); + if (tside & RIGHT) + maketick(type, p->name, RIGHT, inside, tv, tickstr[i], lenstr, descstr); + if (tickstr[i]) { + free(tickstr[i]); + tickstr[i] = NULL; + } + } + ntick = 0; +} + +void maketick(int type, char *name, int side, int inflag, double val, char *lab, char *lenstr, char *descstr) +{ + char *sidestr, *td; + + fprintf(tfd, "\tline %s ", descstr); + inflag &= side; + switch (side) { + case BOT: + case 0: + td = inflag ? "up" : "down"; + fprintf(tfd, "%s %s from (x_%s(%g),0)", td, lenstr, name, val); + break; + case TOP: + td = inflag ? "down" : "up"; + fprintf(tfd, "%s %s from (x_%s(%g),frameht)", td, lenstr, name, val); + break; + case LEFT: + td = inflag ? "right" : "left"; + fprintf(tfd, "%s %s from (0,y_%s(%g))", td, lenstr, name, val); + break; + case RIGHT: + td = inflag ? "left" : "right"; + fprintf(tfd, "%s %s from (framewid,y_%s(%g))", td, lenstr, name, val); + break; + } + fprintf(tfd, "\n"); + if (type == GRID && (side & goffside)) /* wanted no ticks on grid */ + return; + sidestr = tick_dir == IN ? "start" : "end"; + if (lab != NULL) { + /* BUG: should fix size of lab here */ + double wid = strlen(lab)/7.5 + (tick_dir == IN ? 0 : 0.1); /* estimate width at 15 chars/inch */ + switch (side) { + case BOT: case 0: + /* can drop "box invis" with new pic */ + fprintf(tfd, "\tbox invis \"%s\" ht .25 wid 0 with .n at last line.%s", + lab, sidestr); + break; + case TOP: + fprintf(tfd, "\tbox invis \"%s\" ht .2 wid 0 with .s at last line.%s", + lab, sidestr); + break; + case LEFT: + fprintf(tfd, "\t\"%s \" wid %.2f rjust at last line.%s", + lab, wid, sidestr); + break; + case RIGHT: + fprintf(tfd, "\t\" %s\" wid %.2f ljust at last line.%s", + lab, wid, sidestr); + break; + } + /* BUG: works only if "down x" comes before "at wherever" */ + lab_adjust(); + fprintf(tfd, "\n"); + } +} + +Attr *grid_desc = 0; + +void griddesc(Attr *a) +{ + grid_desc = a; +} + +void gridlist(Obj *p) +{ + char *framestr; + + if ((tside & (BOT|TOP)) || tside == 0) + framestr = "frameht"; + else + framestr = "framewid"; + fprintf(tfd, "Grid_%s:\n", p->name); + tick_dir = IN; + print_ticks(GRID, 0, p, framestr, desc_str(grid_desc)); + if (grid_desc) { + freeattr(grid_desc); + grid_desc = 0; + } +} + +char *desc_str(Attr *a) /* convert DOT to "dotted", etc. */ +{ + static char buf[50], *p; + + if (a == NULL) + return p = ""; + switch (a->type) { + case DOT: p = "dotted"; break; + case DASH: p = "dashed"; break; + case INVIS: p = "invis"; break; + default: p = ""; + } + if (a->fval != 0.0) { + sprintf(buf, "%s %g", p, a->fval); + return buf; + } else + return p; +} + +sidelog(int logflag, int side) /* figure out whether to scale a side */ +{ + if ((logflag & XFLAG) && ((side & (BOT|TOP)) || side == 0)) + return 1; + else if ((logflag & YFLAG) && (side & (LEFT|RIGHT))) + return 1; + else + return 0; +} blob - e5ddf684f839346b10ff014df984c36a3a20c1af blob + d08461e90c24753cd296545260dc03f5b43febbd --- src/cmd/mkfile +++ src/cmd/mkfile @@ -5,7 +5,7 @@ SHORTLIB=sec fs mux regexp9 thread bio 9 <$PLAN9/src/mkmany -BUGGERED='CVS|faces|factotum|mailfs|scat|upas|vac|venti|lex|vncv' +BUGGERED='CVS|faces|factotum|mailfs|scat|upas|vac|venti|lex|vncv|grap|eqn|troff|pic|tbl' DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"` <$PLAN9/src/mkdirs blob - /dev/null blob + d1b64224d24862cd717d3ebe74eb15864ba2a3f4 (mode 644) --- /dev/null +++ src/cmd/pic/arcgen.c @@ -0,0 +1,221 @@ +#include +#include +#include "pic.h" +#include "y.tab.h" + +void arc_extreme(double, double, double, double, double, double); +int quadrant(double x, double y); + +obj *arcgen(int type) /* handles circular and (eventually) elliptical arcs */ +{ + static double prevw = HT10; + static double prevh = HT5; + static double prevrad = HT2; + static int dtox[2][4] ={ 1, -1, -1, 1, 1, 1, -1, -1 }; + static int dtoy[2][4] ={ 1, 1, -1, -1, -1, 1, 1, -1 }; + static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 }; + static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 }; + static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR }; + double dx2, dy2, ht, phi, r, d; + int i, head, to, at, cw, invis, ddtype, battr; + obj *p, *ppos; + double fromx, fromy, tox, toy, fillval = 0; + Attr *ap; + + prevrad = getfval("arcrad"); + prevh = getfval("arrowht"); + prevw = getfval("arrowwid"); + fromx = curx; + fromy = cury; + head = to = at = cw = invis = ddtype = battr = 0; + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + case HEAD: + head += ap->a_val.i; + break; + case INVIS: + invis = INVIS; + break; + case HEIGHT: /* length of arrowhead */ + prevh = ap->a_val.f; + break; + case WIDTH: /* width of arrowhead */ + prevw = ap->a_val.f; + break; + case RADIUS: + prevrad = ap->a_val.f; + break; + case DIAMETER: + prevrad = ap->a_val.f / 2; + break; + case CW: + cw = 1; + break; + case FROM: /* start point of arc */ + ppos = ap->a_val.o; + fromx = ppos->o_x; + fromy = ppos->o_y; + break; + case TO: /* end point of arc */ + ppos = ap->a_val.o; + tox = ppos->o_x; + toy = ppos->o_y; + to++; + break; + case AT: /* center of arc */ + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + at = 1; + break; + case UP: + hvmode = U_DIR; + break; + case DOWN: + hvmode = D_DIR; + break; + case RIGHT: + hvmode = R_DIR; + break; + case LEFT: + hvmode = L_DIR; + break; + case FILL: + battr |= FILLBIT; + if (ap->a_sub == DEFAULT) + fillval = getfval("fillval"); + else + fillval = ap->a_val.f; + break; + } + } + if (!at && !to) { /* the defaults are mostly OK */ + curx = fromx + prevrad * dctrx[cw][hvmode]; + cury = fromy + prevrad * dctry[cw][hvmode]; + tox = fromx + prevrad * dtox[cw][hvmode]; + toy = fromy + prevrad * dtoy[cw][hvmode]; + hvmode = nexthv[cw][hvmode]; + } + else if (!at) { + dx2 = (tox - fromx) / 2; + dy2 = (toy - fromy) / 2; + phi = atan2(dy2, dx2) + (cw ? -PI/2 : PI/2); + if (prevrad <= 0.0) + prevrad = dx2*dx2+dy2*dy2; + for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2) + ; /* this kludge gets around too-small radii */ + prevrad = r; + ht = sqrt(d); + curx = fromx + dx2 + ht * cos(phi); + cury = fromy + dy2 + ht * sin(phi); + dprintf("dx2,dy2=%g,%g, phi=%g, r,ht=%g,%g\n", + dx2, dy2, phi, r, ht); + } + else if (at && !to) { /* do we have all the cases??? */ + tox = fromx + prevrad * dtox[cw][hvmode]; + toy = fromy + prevrad * dtoy[cw][hvmode]; + hvmode = nexthv[cw][hvmode]; + } + if (cw) { /* interchange roles of from-to and heads */ + double temp; + temp = fromx; fromx = tox; tox = temp; + temp = fromy; fromy = toy; toy = temp; + if (head == HEAD1) + head = HEAD2; + else if (head == HEAD2) + head = HEAD1; + } + p = makenode(type, 7); + arc_extreme(fromx, fromy, tox, toy, curx, cury); + p->o_val[0] = fromx; + p->o_val[1] = fromy; + p->o_val[2] = tox; + p->o_val[3] = toy; + if (cw) { + curx = fromx; + cury = fromy; + } else { + curx = tox; + cury = toy; + } + p->o_val[4] = prevw; + p->o_val[5] = prevh; + p->o_val[6] = prevrad; + p->o_attr = head | (cw ? CW_ARC : 0) | invis | ddtype | battr; + p->o_fillval = fillval; + if (head) + p->o_nhead = getfval("arrowhead"); + dprintf("arc rad %g at %g %g from %g %g to %g %g head %g %g\n", + prevrad, p->o_x, p->o_y, + p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]); + return(p); +} + +/*************************************************************************** + bounding box of a circular arc Eric Grosse 24 May 84 + +Conceptually, this routine generates a list consisting of the start, +end, and whichever north, east, south, and west points lie on the arc. +The bounding box is then the range of this list. + list = {start,end} + j = quadrant(start) + k = quadrant(end) + if( j==k && long way 'round ) append north,west,south,east + else + while( j != k ) + append center+radius*[j-th of north,west,south,east unit vectors] + j += 1 (mod 4) + return( bounding box of list ) +The following code implements this, with simple optimizations. +***********************************************************************/ + + +void arc_extreme(double x0, double y0, double x1, double y1, double xc, double yc) + /* start, end, center */ +{ + /* assumes center isn't too far out */ + double r, xmin, ymin, xmax, ymax; + int j, k; + x0 -= xc; y0 -= yc; /* move to center */ + x1 -= xc; y1 -= yc; + xmin = (x0x1)?x0:x1; ymax = (y0>y1)?y0:y1; + r = sqrt(x0*x0 + y0*y0); + if (r > 0.0) { + j = quadrant(x0,y0); + k = quadrant(x1,y1); + if (j == k && y1*x0 < x1*y0) { + /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */ + if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r; + if( xmax < r) xmax = r; if( ymax < r) ymax = r; + } else { + while (j != k) { + switch (j) { + case 1: if( ymax < r) ymax = r; break; /* north */ + case 2: if( xmin > -r) xmin = -r; break; /* west */ + case 3: if( ymin > -r) ymin = -r; break; /* south */ + case 4: if( xmax < r) xmax = r; break; /* east */ + } + j = j%4 + 1; + } + } + } + xmin += xc; ymin += yc; + xmax += xc; ymax += yc; + extreme(xmin, ymin); + extreme(xmax, ymax); +} + +quadrant(double x, double y) +{ + if ( x>=0.0 && y> 0.0) return(1); + else if( x< 0.0 && y>=0.0) return(2); + else if( x<=0.0 && y< 0.0) return(3); + else if( x> 0.0 && y<=0.0) return(4); + else return 0; /* shut up lint */ +} + blob - /dev/null blob + 9015d56d2ae001131c56a825e7f631a0c2834559 (mode 644) --- /dev/null +++ src/cmd/pic/blockgen.c @@ -0,0 +1,226 @@ +#include +#include +#include "pic.h" +#include "y.tab.h" + +#define NBRACK 20 /* depth of [...] */ +#define NBRACE 20 /* depth of {...} */ + +struct pushstack stack[NBRACK]; +int nstack = 0; +struct pushstack bracestack[NBRACE]; +int nbstack = 0; + +void blockadj(obj *); + +obj *leftthing(int c) /* called for {... or [... */ + /* really ought to be separate functions */ +{ + obj *p; + + if (c == '[') { + if (nstack >= NBRACK) + ERROR "[...] nested too deep" FATAL; + stack[nstack].p_x = curx; + stack[nstack].p_y = cury; + stack[nstack].p_hvmode = hvmode; + curx = cury = 0; + stack[nstack].p_xmin = xmin; + stack[nstack].p_xmax = xmax; + stack[nstack].p_ymin = ymin; + stack[nstack].p_ymax = ymax; + nstack++; + xmin = ymin = 30000; + xmax = ymax = -30000; + p = makenode(BLOCK, 7); + p->o_val[4] = nobj; /* 1st item within [...] */ + if (p->o_nobj != nobj-1) + fprintf(stderr, "nobjs wrong%d %d\n", p->o_nobj, nobj); + } else { + if (nbstack >= NBRACK) + ERROR "{...} nested too deep" FATAL; + bracestack[nbstack].p_x = curx; + bracestack[nbstack].p_y = cury; + bracestack[nbstack].p_hvmode = hvmode; + nbstack++; + p = NULL; + } + return(p); +} + +obj *rightthing(obj *p, int c) /* called for ... ] or ... } */ +{ + obj *q; + + if (c == '}') { + nbstack--; + curx = bracestack[nbstack].p_x; + cury = bracestack[nbstack].p_y; + hvmode = bracestack[nbstack].p_hvmode; + q = makenode(MOVE, 0); + dprintf("M %g %g\n", curx, cury); + } else { + nstack--; + curx = stack[nstack].p_x; + cury = stack[nstack].p_y; + hvmode = stack[nstack].p_hvmode; + q = makenode(BLOCKEND, 7); + q->o_val[4] = p->o_nobj + 1; /* back pointer */ + p->o_val[5] = q->o_nobj - 1; /* forward pointer */ + if (xmin > xmax) /* nothing happened */ + xmin = xmax; + if (ymin > ymax) + ymin = ymax; + p->o_val[0] = xmin; p->o_val[1] = ymin; + p->o_val[2] = xmax; p->o_val[3] = ymax; + p->o_symtab = q->o_symtab = stack[nstack+1].p_symtab; + xmin = stack[nstack].p_xmin; + ymin = stack[nstack].p_ymin; + xmax = stack[nstack].p_xmax; + ymax = stack[nstack].p_ymax; + } + return(q); +} + +obj *blockgen(obj *p, obj *q) /* handles [...] */ +{ + int i, invis, at, with; + double ddval, h, w, xwith, ywith; + double x0, y0, x1, y1, cx, cy; + obj *ppos; + Attr *ap; + + invis = at = 0; + with = xwith = ywith = 0; + ddval = 0; + w = p->o_val[2] - p->o_val[0]; + h = p->o_val[3] - p->o_val[1]; + cx = (p->o_val[2] + p->o_val[0]) / 2; /* geom ctr of [] wrt local orogin */ + cy = (p->o_val[3] + p->o_val[1]) / 2; + dprintf("cx,cy=%g,%g\n", cx, cy); + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case HEIGHT: + h = ap->a_val.f; + break; + case WIDTH: + w = ap->a_val.f; + break; + case WITH: + with = ap->a_val.i; /* corner */ + break; + case PLACE: /* actually with position ... */ + ppos = ap->a_val.o; + xwith = cx - ppos->o_x; + ywith = cy - ppos->o_y; + with = PLACE; + break; + case AT: + case FROM: + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + at++; + break; + case INVIS: + invis = INVIS; + break; + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + } + } + if (with) { + switch (with) { + case NORTH: ywith = -h / 2; break; + case SOUTH: ywith = h / 2; break; + case EAST: xwith = -w / 2; break; + case WEST: xwith = w / 2; break; + case NE: xwith = -w / 2; ywith = -h / 2; break; + case SE: xwith = -w / 2; ywith = h / 2; break; + case NW: xwith = w / 2; ywith = -h / 2; break; + case SW: xwith = w / 2; ywith = h / 2; break; + } + curx += xwith; + cury += ywith; + } + if (!at) { + if (isright(hvmode)) + curx += w / 2; + else if (isleft(hvmode)) + curx -= w / 2; + else if (isup(hvmode)) + cury += h / 2; + else + cury -= h / 2; + } + x0 = curx - w / 2; + y0 = cury - h / 2; + x1 = curx + w / 2; + y1 = cury + h / 2; + extreme(x0, y0); + extreme(x1, y1); + p->o_x = curx; + p->o_y = cury; + p->o_nt1 = ntext1; + p->o_nt2 = ntext; + ntext1 = ntext; + p->o_val[0] = w; + p->o_val[1] = h; + p->o_val[2] = cx; + p->o_val[3] = cy; + p->o_val[5] = q->o_nobj - 1; /* last item in [...] */ + p->o_ddval = ddval; + p->o_attr = invis; + dprintf("[] %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); + if (isright(hvmode)) + curx = x1; + else if (isleft(hvmode)) + curx = x0; + else if (isup(hvmode)) + cury = y1; + else + cury = y0; + for (i = 0; i <= 5; i++) + q->o_val[i] = p->o_val[i]; + stack[nstack+1].p_symtab = NULL; /* so won't be found again */ + blockadj(p); /* fix up coords for enclosed blocks */ + return(p); +} + +void blockadj(obj *p) /* adjust coords in block starting at p */ +{ + double dx, dy; + int n, lev; + + dx = p->o_x - p->o_val[2]; + dy = p->o_y - p->o_val[3]; + n = p->o_nobj + 1; + dprintf("into blockadj: dx,dy=%g,%g\n", dx, dy); + for (lev = 1; lev > 0; n++) { + p = objlist[n]; + if (p->o_type == BLOCK) + lev++; + else if (p->o_type == BLOCKEND) + lev--; + dprintf("blockadj: type=%d o_x,y=%g,%g;", p->o_type, p->o_x, p->o_y); + p->o_x += dx; + p->o_y += dy; + dprintf(" becomes %g,%g\n", p->o_x, p->o_y); + switch (p->o_type) { /* other absolute coords */ + case LINE: + case ARROW: + case SPLINE: + p->o_val[0] += dx; + p->o_val[1] += dy; + break; + case ARC: + p->o_val[0] += dx; + p->o_val[1] += dy; + p->o_val[2] += dx; + p->o_val[3] += dy; + break; + } + } +} blob - /dev/null blob + b575cd2f4251383fff6bb332bc76ac33ccbc3b4a (mode 644) --- /dev/null +++ src/cmd/pic/boxgen.c @@ -0,0 +1,115 @@ +#include +#include "pic.h" +#include "y.tab.h" + +obj *boxgen(void) +{ + static double prevh = HT; + static double prevw = WID; /* golden mean, sort of */ + int i, at, battr, with; + double ddval, fillval, xwith, ywith; + double h, w, x0, y0, x1, y1; + obj *p, *ppos; + Attr *ap; + + h = getfval("boxht"); + w = getfval("boxwid"); + at = battr = with = 0; + ddval = fillval = xwith = ywith = 0; + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case HEIGHT: + h = ap->a_val.f; + break; + case WIDTH: + w = ap->a_val.f; + break; + case SAME: + h = prevh; + w = prevw; + break; + case WITH: + with = ap->a_val.i; /* corner */ + break; + case AT: + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + at++; + break; + case INVIS: + battr |= INVIS; + break; + case NOEDGE: + battr |= NOEDGEBIT; + break; + case DOT: + case DASH: + battr |= ap->a_type==DOT ? DOTBIT : DASHBIT; + if (ap->a_sub == DEFAULT) + ddval = getfval("dashwid"); + else + ddval = ap->a_val.f; + break; + case FILL: + battr |= FILLBIT; + if (ap->a_sub == DEFAULT) + fillval = getfval("fillval"); + else + fillval = ap->a_val.f; + break; + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + } + } + if (with) { + switch (with) { + case NORTH: ywith = -h / 2; break; + case SOUTH: ywith = h / 2; break; + case EAST: xwith = -w / 2; break; + case WEST: xwith = w / 2; break; + case NE: xwith = -w / 2; ywith = -h / 2; break; + case SE: xwith = -w / 2; ywith = h / 2; break; + case NW: xwith = w / 2; ywith = -h / 2; break; + case SW: xwith = w / 2; ywith = h / 2; break; + } + curx += xwith; + cury += ywith; + } + if (!at) { + if (isright(hvmode)) + curx += w / 2; + else if (isleft(hvmode)) + curx -= w / 2; + else if (isup(hvmode)) + cury += h / 2; + else + cury -= h / 2; + } + x0 = curx - w / 2; + y0 = cury - h / 2; + x1 = curx + w / 2; + y1 = cury + h / 2; + extreme(x0, y0); + extreme(x1, y1); + p = makenode(BOX, 2); + p->o_val[0] = w; + p->o_val[1] = h; + p->o_attr = battr; + p->o_ddval = ddval; + p->o_fillval = fillval; + dprintf("B %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); + if (isright(hvmode)) + curx = x1; + else if (isleft(hvmode)) + curx = x0; + else if (isup(hvmode)) + cury = y1; + else + cury = y0; + prevh = h; + prevw = w; + return(p); +} blob - /dev/null blob + f40bae9a1e03953f32275fdcdb25f9a1fda18989 (mode 644) --- /dev/null +++ src/cmd/pic/circgen.c @@ -0,0 +1,126 @@ +#include +#include "pic.h" +#include "y.tab.h" + +obj *circgen(int type) +{ + static double rad[2] = { HT2, WID2 }; + static double rad2[2] = { HT2, HT2 }; + int i, at, t, with, battr; + double xwith, ywith; + double r, r2, ddval, fillval; + obj *p, *ppos; + Attr *ap; + + battr = at = 0; + with = xwith = ywith = fillval = ddval = 0; + t = (type == CIRCLE) ? 0 : 1; + if (type == CIRCLE) + r = r2 = getfval("circlerad"); + else if (type == ELLIPSE) { + r = getfval("ellipsewid") / 2; + r2 = getfval("ellipseht") / 2; + } + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + case RADIUS: + r = ap->a_val.f; + break; + case DIAMETER: + case WIDTH: + r = ap->a_val.f / 2; + break; + case HEIGHT: + r2 = ap->a_val.f / 2; + break; + case SAME: + r = rad[t]; + r2 = rad2[t]; + break; + case WITH: + with = ap->a_val.i; + break; + case AT: + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + at++; + break; + case INVIS: + battr |= INVIS; + break; + case NOEDGE: + battr |= NOEDGEBIT; + break; + case DOT: + case DASH: + battr |= ap->a_type==DOT ? DOTBIT : DASHBIT; + if (ap->a_sub == DEFAULT) + ddval = getfval("dashwid"); + else + ddval = ap->a_val.f; + break; + case FILL: + battr |= FILLBIT; + if (ap->a_sub == DEFAULT) + fillval = getfval("fillval"); + else + fillval = ap->a_val.f; + break; + } + } + if (type == CIRCLE) + r2 = r; /* probably superfluous */ + if (with) { + switch (with) { + case NORTH: ywith = -r2; break; + case SOUTH: ywith = r2; break; + case EAST: xwith = -r; break; + case WEST: xwith = r; break; + case NE: xwith = -r * 0.707; ywith = -r2 * 0.707; break; + case SE: xwith = -r * 0.707; ywith = r2 * 0.707; break; + case NW: xwith = r * 0.707; ywith = -r2 * 0.707; break; + case SW: xwith = r * 0.707; ywith = r2 * 0.707; break; + } + curx += xwith; + cury += ywith; + } + if (!at) { + if (isright(hvmode)) + curx += r; + else if (isleft(hvmode)) + curx -= r; + else if (isup(hvmode)) + cury += r2; + else + cury -= r2; + } + p = makenode(type, 2); + p->o_val[0] = rad[t] = r; + p->o_val[1] = rad2[t] = r2; + if (r <= 0 || r2 <= 0) { + ERROR "%s has invalid radius %g\n", (type==CIRCLE) ? "circle" : "ellipse", ro_attr = battr; + p->o_ddval = ddval; + p->o_fillval = fillval; + extreme(curx+r, cury+r2); + extreme(curx-r, cury-r2); + if (type == CIRCLE) + dprintf("C %g %g %g\n", curx, cury, r); + if (type == ELLIPSE) + dprintf("E %g %g %g %g\n", curx, cury, r, r2); + if (isright(hvmode)) + curx += r; + else if (isleft(hvmode)) + curx -= r; + else if (isup(hvmode)) + cury += r2; + else + cury -= r2; + return(p); +} blob - /dev/null blob + cece48b573589ae5db4c4e9c3b990fa1fa939332 (mode 644) --- /dev/null +++ src/cmd/pic/for.c @@ -0,0 +1,95 @@ +#include +#include +#include "pic.h" +#include "y.tab.h" + +#define SLOP 1.001 + +typedef struct { + char *var; /* index variable */ + double to; /* limit */ + double by; + int op; /* operator */ + char *str; /* string to push back */ +} For; + +For forstk[10]; /* stack of for loops */ +For *forp = forstk; /* pointer to current top */ + +void setfval(char *, double); +void nextfor(void); + +void forloop(char *var, double from, double to, int op, + double by, char *str) /* set up a for loop */ +{ + dprintf("# for %s from %g to %g by %c %g \n", + var, from, to, op, by); + if (++forp >= forstk+10) + ERROR "for loop nested too deep" FATAL; + forp->var = var; + forp->to = to; + forp->op = op; + forp->by = by; + forp->str = str; + setfval(var, from); + nextfor(); + unput('\n'); +} + +void nextfor(void) /* do one iteration of a for loop */ +{ + /* BUG: this should depend on op and direction */ + if (getfval(forp->var) > SLOP * forp->to) { /* loop is done */ + free(forp->str); + if (--forp < forstk) + ERROR "forstk popped too far" FATAL; + } else { /* another iteration */ + pushsrc(String, "\nEndfor\n"); + pushsrc(String, forp->str); + } +} + +void endfor(void) /* end one iteration of for loop */ +{ + struct symtab *p = lookup(forp->var); + + switch (forp->op) { + case '+': + case ' ': + p->s_val.f += forp->by; + break; + case '-': + p->s_val.f -= forp->by; + break; + case '*': + p->s_val.f *= forp->by; + break; + case '/': + p->s_val.f /= forp->by; + break; + } + nextfor(); +} + +char *ifstat(double expr, char *thenpart, char *elsepart) +{ + dprintf("if %g then <%s> else <%s>\n", expr, thenpart, elsepart? elsepart : ""); + if (expr) { + unput('\n'); + pushsrc(Free, thenpart); + pushsrc(String, thenpart); + unput('\n'); + if (elsepart) + free(elsepart); + return thenpart; /* to be freed later */ + } else { + free(thenpart); + if (elsepart) { + unput('\n'); + pushsrc(Free, elsepart); + pushsrc(String, elsepart); + unput('\n'); + } + return elsepart; + } +} blob - /dev/null blob + 875b1868a7838074048ffd5b4d7b883786a38626 (mode 644) --- /dev/null +++ src/cmd/pic/input.c @@ -0,0 +1,593 @@ +#include +#include +#include +#include +#include +#include "pic.h" +#include "y.tab.h" + +Infile infile[10]; +Infile *curfile = infile; + +#define MAXSRC 50 +Src src[MAXSRC]; /* input source stack */ +Src *srcp = src; + +void do_thru(void); +int nextchar(void); +int getarg(char *); +void freedef(char *); +int baldelim(int, char *); + +void pushsrc(int type, char *ptr) /* new input source */ +{ + if (++srcp >= src + MAXSRC) + ERROR "inputs nested too deep" FATAL; + srcp->type = type; + srcp->sp = ptr; + if (dbg > 1) { + printf("\n%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("push file %s\n", ((Infile *)ptr)->fname); + break; + case Macro: + printf("push macro <%s>\n", ptr); + break; + case Char: + printf("push char <%c>\n", *ptr); + break; + case Thru: + printf("push thru\n"); + break; + case String: + printf("push string <%s>\n", ptr); + break; + case Free: + printf("push free <%s>\n", ptr); + break; + default: + ERROR "pushed bad type %d", srcp->type FATAL; + } + } +} + +void popsrc(void) /* restore an old one */ +{ + if (srcp <= src) + ERROR "too many inputs popped" FATAL; + if (dbg > 1) { + printf("%3d ", srcp - src); + switch (srcp->type) { + case File: + printf("pop file\n"); + break; + case Macro: + printf("pop macro\n"); + break; + case Char: + printf("pop char <%c>\n", *srcp->sp); + break; + case Thru: + printf("pop thru\n"); + break; + case String: + printf("pop string\n"); + break; + case Free: + printf("pop free\n"); + break; + default: + ERROR "pop weird input %d", srcp->type FATAL; + } + } + srcp--; +} + +void definition(char *s) /* collect definition for s and install */ + /* definitions picked up lexically */ +{ + char *p; + struct symtab *stp; + + p = delimstr("definition"); + stp = lookup(s); + if (stp != NULL) { /* it's there before */ + if (stp->s_type != DEFNAME) { + ERROR "%s used as variable and definition", s WARNING; + return; + } + free(stp->s_val.p); + stp->s_val.p = p; + } else { + YYSTYPE u; + u.p = p; + makevar(tostring(s), DEFNAME, u); + } + dprintf("installing %s as `%s'\n", s, p); +} + +char *delimstr(char *s) /* get body of X ... X */ + /* message if too big */ +{ + int c, delim, rdelim, n, deep; + static char *buf = NULL; + static int nbuf = 0; + char *p; + + if (buf == NULL) + buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); + while ((delim = input()) == ' ' || delim == '\t' || delim == '\n') + ; + rdelim = baldelim(delim, "{}"); /* could be "(){}[]`'" */ + deep = 1; + for (p = buf; ; ) { + c = input(); + if (c == rdelim) + if (--deep == 0) + break; + if (c == delim) + deep++; + if (p >= buf + nbuf) { + n = p - buf; + buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); + p = buf + n; + } + if (c == EOF) + ERROR "end of file in %s %c %.20s... %c", s, delim, buf, delim FATAL; + *p++ = c; + } + *p = '\0'; + dprintf("delimstr %s %c <%s> %c\n", s, delim, buf, delim); + return tostring(buf); +} + +baldelim(int c, char *s) /* replace c by balancing entry in s */ +{ + for ( ; *s; s += 2) + if (*s == c) + return s[1]; + return c; +} + +void undefine(char *s) /* undefine macro */ +{ + while (*s != ' ' && *s != '\t') /* skip "undef..." */ + s++; + while (*s == ' ' || *s == '\t') + s++; + freedef(s); +} + + +Arg args[10]; /* argument frames */ +Arg *argfp = args; /* frame pointer */ +int argcnt; /* number of arguments seen so far */ + +void dodef(struct symtab *stp) /* collect args and switch input to defn */ +{ + int i, len; + char *p; + Arg *ap; + + ap = argfp+1; + if (ap >= args+10) + ERROR "arguments too deep" FATAL; + argcnt = 0; + if (input() != '(') + ERROR "disaster in dodef" FATAL; + if (ap->argval == 0) + ap->argval = malloc(1000); + for (p = ap->argval; (len = getarg(p)) != -1; p += len) { + ap->argstk[argcnt++] = p; + if (input() == ')') + break; + } + for (i = argcnt; i < MAXARGS; i++) + ap->argstk[i] = ""; + if (dbg) + for (i = 0; i < argcnt; i++) + printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); + argfp = ap; + pushsrc(Macro, stp->s_val.p); +} + +getarg(char *p) /* pick up single argument, store in p, return length */ +{ + int n, c, npar; + + n = npar = 0; + for ( ;; ) { + c = input(); + if (c == EOF) + ERROR "end of file in getarg" FATAL; + if (npar == 0 && (c == ',' || c == ')')) + break; + if (c == '"') /* copy quoted stuff intact */ + do { + *p++ = c; + n++; + } while ((c = input()) != '"' && c != EOF); + else if (c == '(') + npar++; + else if (c == ')') + npar--; + n++; + *p++ = c; + } + *p = 0; + unput(c); + return(n + 1); +} + +#define PBSIZE 2000 +char pbuf[PBSIZE]; /* pushback buffer */ +char *pb = pbuf-1; /* next pushed back character */ + +char ebuf[200]; /* collect input here for error reporting */ +char *ep = ebuf; + +int begin = 0; +extern int thru; +extern struct symtab *thrudef; +extern char *untilstr; + +input(void) +{ + register int c; + + if (thru && begin) { + do_thru(); + begin = 0; + } + c = nextchar(); + if (dbg > 1) + printf(" <%c>", c); + if (ep >= ebuf + sizeof ebuf) + ep = ebuf; + return *ep++ = c; +} + +nextchar(void) +{ + register int c; + + loop: + switch (srcp->type) { + case Free: /* free string */ + free(srcp->sp); + popsrc(); + goto loop; + case Thru: /* end of pushed back line */ + begin = 1; + popsrc(); + c = '\n'; + break; + case Char: + if (pb >= pbuf) { + c = *pb--; + popsrc(); + break; + } else { /* can't happen? */ + popsrc(); + goto loop; + } + case String: + c = *srcp->sp++; + if (c == '\0') { + popsrc(); + goto loop; + } else { + if (*srcp->sp == '\0') /* empty, so pop */ + popsrc(); + break; + } + case Macro: + c = *srcp->sp++; + if (c == '\0') { + if (--argfp < args) + ERROR "argfp underflow" FATAL; + popsrc(); + goto loop; + } else if (c == '$' && isdigit(*srcp->sp)) { + int n = 0; + while (isdigit(*srcp->sp)) + n = 10 * n + *srcp->sp++ - '0'; + if (n > 0 && n <= MAXARGS) + pushsrc(String, argfp->argstk[n-1]); + goto loop; + } + break; + case File: + c = getc(curfile->fin); + if (c == EOF) { + if (curfile == infile) + ERROR "end of file inside .PS/.PE" FATAL; + if (curfile->fin != stdin) { + fclose(curfile->fin); + free(curfile->fname); /* assumes allocated */ + } + curfile--; + printlf(curfile->lineno, curfile->fname); + popsrc(); + thru = 0; /* chicken out */ + thrudef = 0; + if (untilstr) { + free(untilstr); + untilstr = 0; + } + goto loop; + } + if (c == '\n') + curfile->lineno++; + break; + } + return c; +} + +void do_thru(void) /* read one line, make into a macro expansion */ +{ + int c, i; + char *p; + Arg *ap; + + ap = argfp+1; + if (ap >= args+10) + ERROR "arguments too deep" FATAL; + if (ap->argval == NULL) + ap->argval = malloc(1000); + p = ap->argval; + argcnt = 0; + c = nextchar(); + if (thru == 0) { /* end of file was seen, so thru is done */ + unput(c); + return; + } + for ( ; c != '\n' && c != EOF; ) { + if (c == ' ' || c == '\t') { + c = nextchar(); + continue; + } + ap->argstk[argcnt++] = p; + if (c == '"') { + do { + *p++ = c; + if ((c = nextchar()) == '\\') { + *p++ = c; + *p++ = nextchar(); + c = nextchar(); + } + } while (c != '"' && c != '\n' && c != EOF); + *p++ = '"'; + if (c == '"') + c = nextchar(); + } else { + do { + *p++ = c; + } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF); + if (c == ',') + c = nextchar(); + } + *p++ = '\0'; + } + if (c == EOF) + ERROR "unexpected end of file in do_thru" FATAL; + if (argcnt == 0) { /* ignore blank line */ + pushsrc(Thru, (char *) 0); + return; + } + for (i = argcnt; i < MAXARGS; i++) + ap->argstk[i] = ""; + if (dbg) + for (i = 0; i < argcnt; i++) + printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); + if (strcmp(ap->argstk[0], ".PE") == 0) { + thru = 0; + thrudef = 0; + pushsrc(String, "\n.PE\n"); + return; + } + if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) { + thru = 0; + thrudef = 0; + free(untilstr); + untilstr = 0; + return; + } + pushsrc(Thru, (char *) 0); + dprintf("do_thru pushing back <%s>\n", thrudef->s_val.p); + argfp = ap; + pushsrc(Macro, thrudef->s_val.p); +} + +unput(int c) +{ + if (++pb >= pbuf + sizeof pbuf) + ERROR "pushback overflow" FATAL; + if (--ep < ebuf) + ep = ebuf + sizeof(ebuf) - 1; + *pb = c; + pushsrc(Char, pb); + return c; +} + +void pbstr(char *s) +{ + pushsrc(String, s); +} + +double errcheck(double x, char *s) +{ + extern int errno; + + if (errno == EDOM) { + errno = 0; + ERROR "%s argument out of domain", s WARNING; + } else if (errno == ERANGE) { + errno = 0; + ERROR "%s result out of range", s WARNING; + } + return x; +} + +char errbuf[200]; + +void eprint(void); + +void yyerror(char *s) +{ + extern char *cmdname; + int ern = errno; /* cause some libraries clobber it */ + + if (synerr) + return; + fflush(stdout); + fprintf(stderr, "%s: %s", cmdname, s); + if (ern > 0) { + errno = ern; + perror("???"); + } + fprintf(stderr, " near %s:%d\n", + curfile->fname, curfile->lineno+1); + eprint(); + synerr = 1; + errno = 0; +} + +void eprint(void) /* try to print context around error */ +{ + char *p, *q; + + p = ep - 1; + if (p > ebuf && *p == '\n') + p--; + for ( ; p >= ebuf && *p != '\n'; p--) + ; + while (*p == '\n') + p++; + fprintf(stderr, " context is\n\t"); + for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) + ; + while (p < q) + putc(*p++, stderr); + fprintf(stderr, " >>> "); + while (p < ep) + putc(*p++, stderr); + fprintf(stderr, " <<< "); + while (pb >= pbuf) + putc(*pb--, stderr); + fgets(ebuf, sizeof ebuf, curfile->fin); + fprintf(stderr, "%s", ebuf); + pbstr("\n.PE\n"); /* safety first */ + ep = ebuf; +} + +void yywrap(void) {} + +char *newfile = 0; /* filename for file copy */ +char *untilstr = 0; /* string that terminates a thru */ +int thru = 0; /* 1 if copying thru macro */ +struct symtab *thrudef = 0; /* macro being used */ + +void copyfile(char *s) /* remember file to start reading from */ +{ + newfile = s; +} + +void copydef(struct symtab *p) /* remember macro symtab ptr */ +{ + thrudef = p; +} + +struct symtab *copythru(char *s) /* collect the macro name or body for thru */ +{ + struct symtab *p; + char *q, *addnewline(char *); + + p = lookup(s); + if (p != NULL) { + if (p->s_type == DEFNAME) { + p->s_val.p = addnewline(p->s_val.p); + return p; + } else + ERROR "%s used as define and name", s FATAL; + } + /* have to collect the definition */ + pbstr(s); /* first char is the delimiter */ + q = delimstr("thru body"); + s = "nameless"; + p = lookup(s); + if (p != NULL) { + if (p->s_val.p) + free(p->s_val.p); + p->s_val.p = q; + } else { + YYSTYPE u; + u.p = q; + p = makevar(tostring(s), DEFNAME, u); + } + p->s_val.p = addnewline(p->s_val.p); + dprintf("installing %s as `%s'\n", s, p->s_val.p); + return p; +} + +char *addnewline(char *p) /* add newline to end of p */ +{ + int n; + + n = strlen(p); + if (p[n-1] != '\n') { + p = realloc(p, n+2); + p[n] = '\n'; + p[n+1] = '\0'; + } + return p; +} + +void copyuntil(char *s) /* string that terminates a thru */ +{ + untilstr = s; +} + +void copy(void) /* begin input from file, etc. */ +{ + FILE *fin; + + if (newfile) { + if ((fin = fopen(newfile, "r")) == NULL) + ERROR "can't open file %s", newfile FATAL; + curfile++; + curfile->fin = fin; + curfile->fname = newfile; + curfile->lineno = 0; + printlf(1, curfile->fname); + pushsrc(File, curfile->fname); + newfile = 0; + } + if (thrudef) { + thru = 1; + begin = 1; /* wrong place */ + } +} + +char shellbuf[1000], *shellp; + +void shell_init(void) /* set up to interpret a shell command */ +{ + sprintf(shellbuf, "rc -c '"); + shellp = shellbuf + strlen(shellbuf); +} + +void shell_text(char *s) /* add string to command being collected */ +{ + while (*shellp++ = *s++) + ; + shellp--; +} + +void shell_exec(void) /* do it */ +{ + *shellp++ = '\''; + *shellp = '\0'; + system(shellbuf); +} blob - /dev/null blob + eab268f5c4b14124d35f83a564ab36adf2657d63 (mode 644) --- /dev/null +++ src/cmd/pic/linegen.c @@ -0,0 +1,240 @@ +#include +#include +#include "pic.h" +#include "y.tab.h" + +obj *linegen(int type) +{ + static double prevdx = HT; + static double prevdy = 0; + static double prevw = HT10; + static double prevh = HT5; + int i, j, some, head, ddtype, invis, chop, battr, with; + double ddval, chop1, chop2, x0, y0, x1, y1; + double fillval = 0; + double theta; + double defx, defy, xwith, ywith; + obj *p, *ppos; + static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ + static int ytab[] = { 0, 1, 0, -1 }; + double dx[500], dy[500]; + int ndxy; + double nx, ny; + Attr *ap, *chop_ap[4]; + + nx = curx; + ny = cury; + defx = getfval("linewid"); + defy = getfval("lineht"); + prevh = getfval("arrowht"); + prevw = getfval("arrowwid"); + dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0; + chop = chop1 = chop2 = 0; + ddtype = ddval = xwith = ywith = 0; + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + case HEAD: + head += ap->a_val.i; + break; + case INVIS: + invis = INVIS; + break; + case NOEDGE: + battr |= NOEDGEBIT; + break; + case DOT: + case DASH: + ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; + if (ap->a_sub == DEFAULT) + ddval = getfval("dashwid"); + else + ddval = ap->a_val.f; + break; + case SAME: + dx[ndxy] = prevdx; + dy[ndxy] = prevdy; + some++; + break; + case LEFT: + dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; + some++; + hvmode = L_DIR; + break; + case RIGHT: + dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; + some++; + hvmode = R_DIR; + break; + case UP: + dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; + some++; + hvmode = U_DIR; + break; + case DOWN: + dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; + some++; + hvmode = D_DIR; + break; + case HEIGHT: /* length of arrowhead */ + prevh = ap->a_val.f; + break; + case WIDTH: /* width of arrowhead */ + prevw = ap->a_val.f; + break; + case TO: + if (some) { + nx += dx[ndxy]; + ny += dy[ndxy]; + ndxy++; + dx[ndxy] = dy[ndxy] = some = 0; + } + ppos = attr[i].a_val.o; + dx[ndxy] = ppos->o_x - nx; + dy[ndxy] = ppos->o_y - ny; + some++; + break; + case BY: + if (some) { + nx += dx[ndxy]; + ny += dy[ndxy]; + ndxy++; + dx[ndxy] = dy[ndxy] = some = 0; + } + ppos = ap->a_val.o; + dx[ndxy] = ppos->o_x; + dy[ndxy] = ppos->o_y; + some++; + break; + case THEN: /* turn off any previous accumulation */ + if (some) { + nx += dx[ndxy]; + ny += dy[ndxy]; + ndxy++; + dx[ndxy] = dy[ndxy] = some = 0; + } + break; + case FROM: + case AT: + ppos = ap->a_val.o; + nx = curx = ppos->o_x; + ny = cury = ppos->o_y; + break; + case WITH: + with = ap->a_val.i; + break; + case CHOP: + if (ap->a_sub != PLACENAME) { + if( chop == 0) + chop1 = chop2 = ap->a_val.f; + else + chop2 = ap->a_val.f; + } + chop_ap[chop++] = ap; + break; + case FILL: + battr |= FILLBIT; + if (ap->a_sub == DEFAULT) + fillval = getfval("fillval"); + else + fillval = ap->a_val.f; + break; + } + } + if (with) { /* this doesn't work at all */ + switch (with) { + case CENTER: + xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break; + } + for (i = 0; i < ndxy; i++) { + dx[i] -= xwith; + dy[i] -= ywith; + } + curx += xwith; + cury += ywith; + } + if (some) { + nx += dx[ndxy]; + ny += dy[ndxy]; + ndxy++; + defx = dx[ndxy-1]; + defy = dy[ndxy-1]; + } else { + defx *= xtab[hvmode]; + defy *= ytab[hvmode]; + dx[ndxy] = defx; + dy[ndxy] = defy; + ndxy++; + nx += defx; + ny += defy; + } + prevdx = defx; + prevdy = defy; + if (chop) { + if (chop == 1 && chop1 == 0) /* just said "chop", so use default */ + chop1 = chop2 = getfval("circlerad"); + theta = atan2(dy[0], dx[0]); + x0 = chop1 * cos(theta); + y0 = chop1 * sin(theta); + curx += x0; + cury += y0; + dx[0] -= x0; + dy[0] -= y0; + + theta = atan2(dy[ndxy-1], dx[ndxy-1]); + x1 = chop2 * cos(theta); + y1 = chop2 * sin(theta); + nx -= x1; + ny -= y1; + dx[ndxy-1] -= x1; + dy[ndxy-1] -= y1; + dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n", + x0, y0, x1, y1, curx, cury, nx, ny); + } + p = makenode(type, 5 + 2 * ndxy); + curx = p->o_val[0] = nx; + cury = p->o_val[1] = ny; + if (head || type == ARROW) { + p->o_nhead = getfval("arrowhead"); + p->o_val[2] = prevw; + p->o_val[3] = prevh; + if (head == 0) + head = HEAD2; /* default arrow head */ + } + p->o_attr = head | invis | ddtype | battr; + p->o_fillval = fillval; + p->o_val[4] = ndxy; + nx = p->o_x; + ny = p->o_y; + for (i = 0, j = 5; i < ndxy; i++, j += 2) { + p->o_val[j] = dx[i]; + p->o_val[j+1] = dy[i]; + if (type == LINE || type == ARROW) + extreme(nx += dx[i], ny += dy[i]); + else if (type == SPLINE && i < ndxy-1) { + /* to compute approx extreme of spline at p, + /* compute midway between p-1 and p+1, + /* then go 3/4 from there to p */ + double ex, ey, xi, yi, xi1, yi1; + xi = nx + dx[i]; yi = ny + dy[i]; /* p */ + xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */ + ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */ + ex += 0.75*(xi-ex); ey += 0.75*(yi-ey); + extreme(ex, ey); + nx = xi; ny = yi; + } + + } + p->o_ddval = ddval; + if (dbg) { + printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); + for (i = 0, j = 5; i < ndxy; i++, j += 2) + printf("%g %g\n", p->o_val[j], p->o_val[j+1]); + } + extreme(p->o_x, p->o_y); + extreme(curx, cury); + return(p); +} blob - /dev/null blob + ab9966503475b451b9dd675433f397e3c6e9eab1 (mode 644) --- /dev/null +++ src/cmd/pic/main.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include "pic.h" +#include "y.tab.h" + +char *version = "version July 5, 1993"; + +obj **objlist = 0; /* store the elements here */ +int nobjlist = 0; /* size of objlist array */ +int nobj = 0; + +Attr *attr; /* attributes stored here as collected */ +int nattrlist = 0; +int nattr = 0; /* number of entries in attr_list */ + +Text *text = 0; /* text strings stored here as collected */ +int ntextlist = 0; /* size of text[] array */ +int ntext = 0; +int ntext1 = 0; /* record ntext here on entry to each figure */ + +double curx = 0; +double cury = 0; + +int hvmode = R_DIR; /* R => join left to right, D => top to bottom, etc. */ + +int codegen = 0; /* 1=>output for this picture; 0=>no output */ +char *PEstring; /* "PS" or "PE" picked up by lexer */ + +double deltx = 6; /* max x value in output, for scaling */ +double delty = 6; /* max y value in output, for scaling */ +int dbg = 0; +int lineno = 0; +char *filename = "-"; +int synerr = 0; +int anyerr = 0; /* becomes 1 if synerr ever 1 */ +char *cmdname; + +double xmin = 30000; /* min values found in actual data */ +double ymin = 30000; +double xmax = -30000; /* max */ +double ymax = -30000; + +void fpecatch(int); +void getdata(void), setdefaults(void); +void setfval(char *, double); +int getpid(void); + +main(int argc, char *argv[]) +{ + char buf[20]; + + signal(SIGFPE, fpecatch); + cmdname = argv[0]; + while (argc > 1 && *argv[1] == '-') { + switch (argv[1][1]) { + case 'd': + dbg = atoi(&argv[1][2]); + if (dbg == 0) + dbg = 1; + fprintf(stderr, "%s\n", version); + break; + case 'V': + fprintf(stderr, "%s\n", version); + return 0; + } + argc--; + argv++; + } + setdefaults(); + objlist = (obj **) grow((char *)objlist, "objlist", nobjlist += 1000, sizeof(obj *)); + text = (Text *) grow((char *)text, "text", ntextlist += 1000, sizeof(Text)); + attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr)); + + sprintf(buf, "/%d/", getpid()); + pushsrc(String, buf); + definition("pid"); + + curfile = infile; + pushsrc(File, curfile->fname); + if (argc <= 1) { + curfile->fin = stdin; + curfile->fname = tostring("-"); + getdata(); + } else + while (argc-- > 1) { + if ((curfile->fin = fopen(*++argv, "r")) == NULL) { + fprintf(stderr, "%s: can't open %s\n", cmdname, *argv); + exit(1); + } + curfile->fname = tostring(*argv); + getdata(); + fclose(curfile->fin); + free(curfile->fname); + } + return anyerr; +} + +void fpecatch(int n) +{ + ERROR "floating point exception %d", n FATAL; +} + +char *grow(char *ptr, char *name, int num, int size) /* make array bigger */ +{ + char *p; + + if (ptr == NULL) + p = malloc(num * size); + else + p = realloc(ptr, num * size); + if (p == NULL) + ERROR "can't grow %s to %d", name, num * size FATAL; + return p; +} + +static struct { + char *name; + double val; + short scalable; /* 1 => adjust when "scale" changes */ +} defaults[] ={ + "scale", SCALE, 1, + "lineht", HT, 1, + "linewid", HT, 1, + "moveht", HT, 1, + "movewid", HT, 1, + "dashwid", HT10, 1, + "boxht", HT, 1, + "boxwid", WID, 1, + "circlerad", HT2, 1, + "arcrad", HT2, 1, + "ellipseht", HT, 1, + "ellipsewid", WID, 1, + "arrowht", HT5, 1, + "arrowwid", HT10, 1, + "arrowhead", 2, 0, /* arrowhead style */ + "textht", 0.0, 1, /* 6 lines/inch is also a useful value */ + "textwid", 0.0, 1, + "maxpsht", MAXHT, 0, + "maxpswid", MAXWID, 0, + "fillval", 0.7, 0, /* gray value for filling boxes */ + NULL, 0, 0 +}; + +void setdefaults(void) /* set default sizes for variables like boxht */ +{ + int i; + YYSTYPE v; + + for (i = 0; defaults[i].name != NULL; i++) { + v.f = defaults[i].val; + makevar(tostring(defaults[i].name), VARNAME, v); + } +} + +void resetvar(void) /* reset variables listed */ +{ + int i, j; + + if (nattr == 0) { /* none listed, so do all */ + setdefaults(); + return; + } + for (i = 0; i < nattr; i++) { + for (j = 0; defaults[j].name != NULL; j++) + if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) { + setfval(defaults[j].name, defaults[j].val); + free(attr[i].a_val.p); + break; + } + } +} + +void checkscale(char *s) /* if s is "scale", adjust default variables */ +{ + int i; + double scale; + + if (strcmp(s, "scale") == 0) { + scale = getfval("scale"); + for (i = 1; defaults[i].name != NULL; i++) + if (defaults[i].scalable) + setfval(defaults[i].name, defaults[i].val * scale); + } +} + +void getdata(void) +{ + char *p, buf[1000], buf1[100]; + int ln; + void reset(void), openpl(char *), closepl(char *), print(void); + int yyparse(void); + + curfile->lineno = 0; + printlf(1, curfile->fname); + while (fgets(buf, sizeof buf, curfile->fin) != NULL) { + curfile->lineno++; + if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') { + for (p = &buf[3]; *p == ' '; p++) + ; + if (*p++ == '<') { + Infile svfile; + svfile = *curfile; + sscanf(p, "%s", buf1); + if ((curfile->fin=fopen(buf1, "r")) == NULL) + ERROR "can't open %s", buf1 FATAL; + curfile->fname = tostring(buf1); + getdata(); + fclose(curfile->fin); + free(curfile->fname); + *curfile = svfile; + printlf(curfile->lineno, curfile->fname); + continue; + } + reset(); + yyparse(); + anyerr += synerr; + deltx = (xmax - xmin) / getfval("scale"); + delty = (ymax - ymin) / getfval("scale"); + if (buf[3] == ' ') { /* next things are wid & ht */ + if (sscanf(&buf[4],"%lf %lf", &deltx, &delty) < 2) + delty = deltx * (ymax-ymin) / (xmax-xmin); + /* else { + /* double xfac, yfac; */ + /* xfac = deltx / (xmax-xmin); + /* yfac = delty / (ymax-ymin); + /* if (xfac <= yfac) + /* delty = xfac * (ymax-ymin); + /* else + /* deltx = yfac * (xmax-xmin); + /*} + */ + } + dprintf("deltx = %g, delty = %g\n", deltx, delty); + if (codegen && !synerr) { + openpl(&buf[3]); /* puts out .PS, with ht & wid stuck in */ + printlf(curfile->lineno+1, NULL); + print(); /* assumes \n at end */ + closepl(PEstring); /* does the .PE/F */ + free(PEstring); + } + printlf(curfile->lineno+1, NULL); + fflush(stdout); + } else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') { + if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) { + free(curfile->fname); + printlf(curfile->lineno = ln, curfile->fname = tostring(buf1)); + } else + printlf(curfile->lineno = ln, NULL); + } else + fputs(buf, stdout); + } +} + +void reset(void) +{ + obj *op; + int i; + extern int nstack; + extern void freesymtab(struct symtab *); + + for (i = 0; i < nobj; i++) { + op = objlist[i]; + if (op->o_type == BLOCK) + freesymtab(op->o_symtab); + free((char *)objlist[i]); + } + nobj = 0; + nattr = 0; + for (i = 0; i < ntext; i++) + if (text[i].t_val) + free(text[i].t_val); + ntext = ntext1 = 0; + codegen = synerr = 0; + nstack = 0; + curx = cury = 0; + PEstring = 0; + hvmode = R_DIR; + xmin = ymin = 30000; + xmax = ymax = -30000; +} blob - /dev/null blob + 92d733a0143ea2f58543b85ec33a5470b7e12daa (mode 644) --- /dev/null +++ src/cmd/pic/makefile @@ -0,0 +1,39 @@ +CC = cc # the usual situation +CFLAGS = # the usual situation + +CC = lcc # you will probably want to remove this +CFLAGS = -g -N -I/usr/include/lcc -I/usr/include # and this + +YFLAGS = -d + +OFILES = picl.o main.o print.o misc.o symtab.o blockgen.o boxgen.o \ + circgen.o arcgen.o linegen.o movegen.o textgen.o \ + input.o for.o pltroff.o $(ALLOC) +CFILES = main.c print.c misc.c symtab.c blockgen.c boxgen.c circgen.c \ + arcgen.c linegen.c movegen.c textgen.c \ + input.c for.c pltroff.c +SRCFILES = picy.y picl.l pic.h $(CFILES) makefile FIXES README PS-PEmacros + +pic: picy.o $(OFILES) pic.h + $(CC) $(CFLAGS) picy.o $(OFILES) -lm + +$(OFILES): pic.h prevy.tab.h + +picy.o: pic.h + +prevy.tab.h: y.tab.h + -cmp -s y.tab.h prevy.tab.h || cp y.tab.h prevy.tab.h + +bundle: + @bundle $(SRCFILES) + +bowell: $(SRCFILES) pictest.a + push bowell $? /usr/src/cmd/pic + touch bowell + +clean: + rm *.o a.out *y.tab.h + +install: + cp a.out /usr/bin/pic + strip /usr/bin/pic blob - /dev/null blob + 0a33c67229ace61f5e93d95457b8ba0536340b4b (mode 644) --- /dev/null +++ src/cmd/pic/misc.c @@ -0,0 +1,436 @@ +#include +#include +#include +#include +#include "pic.h" +#include "y.tab.h" + +int whatpos(obj *p, int corner, double *px, double *py); +void makeattr(int type, int sub, YYSTYPE val); +YYSTYPE getblk(obj *, char *); + +setdir(int n) /* set direction (hvmode) from LEFT, RIGHT, etc. */ +{ + switch (n) { + case UP: hvmode = U_DIR; break; + case DOWN: hvmode = D_DIR; break; + case LEFT: hvmode = L_DIR; break; + case RIGHT: hvmode = R_DIR; break; + } + return(hvmode); +} + +curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */ +{ + switch (hvmode) { + case R_DIR: return RIGHT; + case L_DIR: return LEFT; + case U_DIR: return UP; + case D_DIR: return DOWN; + } + ERROR "can't happen curdir" FATAL; + return 0; +} + +double getcomp(obj *p, int t) /* return component of a position */ +{ + switch (t) { + case DOTX: + return p->o_x; + case DOTY: + return p->o_y; + case DOTWID: + switch (p->o_type) { + case BOX: + case BLOCK: + case TEXT: + return p->o_val[0]; + case CIRCLE: + case ELLIPSE: + return 2 * p->o_val[0]; + case LINE: + case ARROW: + return p->o_val[0] - p->o_x; + case PLACE: + return 0; + } + case DOTHT: + switch (p->o_type) { + case BOX: + case BLOCK: + case TEXT: + return p->o_val[1]; + case CIRCLE: + case ELLIPSE: + return 2 * p->o_val[1]; + case LINE: + case ARROW: + return p->o_val[1] - p->o_y; + case PLACE: + return 0; + } + case DOTRAD: + switch (p->o_type) { + case CIRCLE: + case ELLIPSE: + return p->o_val[0]; + } + } + ERROR "you asked for a weird dimension or position" WARNING; + return 0; +} + +double exprlist[100]; +int nexpr = 0; + +void exprsave(double f) +{ + exprlist[nexpr++] = f; +} + +char *sprintgen(char *fmt) +{ + char buf[1000]; + + sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]); + nexpr = 0; + free(fmt); + return tostring(buf); +} + +void makefattr(int type, int sub, double f) /* double attr */ +{ + YYSTYPE val; + val.f = f; + makeattr(type, sub, val); +} + +void makeoattr(int type, obj *o) /* obj* attr */ +{ + YYSTYPE val; + val.o = o; + makeattr(type, 0, val); +} + +void makeiattr(int type, int i) /* int attr */ +{ + YYSTYPE val; + val.i = i; + makeattr(type, 0, val); +} + +void maketattr(int sub, char *p) /* text attribute: takes two */ +{ + YYSTYPE val; + val.p = p; + makeattr(TEXTATTR, sub, val); +} + +void addtattr(int sub) /* add text attrib to existing item */ +{ + attr[nattr-1].a_sub |= sub; +} + +void makevattr(char *p) /* varname attribute */ +{ + YYSTYPE val; + val.p = p; + makeattr(VARNAME, 0, val); +} + +void makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */ +{ + if (type == 0 && val.i == 0) { /* clear table for next stat */ + nattr = 0; + return; + } + if (nattr >= nattrlist) + attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr)); + dprintf("attr %d: %d %d %d\n", nattr, type, sub, val.i); + attr[nattr].a_type = type; + attr[nattr].a_sub = sub; + attr[nattr].a_val = val; + nattr++; +} + +void printexpr(double f) /* print expression for debugging */ +{ + printf("%g\n", f); +} + +void printpos(obj *p) /* print position for debugging */ +{ + printf("%g, %g\n", p->o_x, p->o_y); +} + +char *tostring(char *s) +{ + register char *p; + + p = malloc(strlen(s)+1); + if (p == NULL) + ERROR "out of space in tostring on %s", s FATAL; + strcpy(p, s); + return(p); +} + +obj *makepos(double x, double y) /* make a position cell */ +{ + obj *p; + + p = makenode(PLACE, 0); + p->o_x = x; + p->o_y = y; + return(p); +} + +obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */ +{ + obj *p; + + dprintf("fraction = %.2f\n", f); + p = makenode(PLACE, 0); + p->o_x = p1->o_x + f * (p2->o_x - p1->o_x); + p->o_y = p1->o_y + f * (p2->o_y - p1->o_y); + return(p); +} + +obj *getpos(obj *p, int corner) /* find position of point */ +{ + double x, y; + + whatpos(p, corner, &x, &y); + return makepos(x, y); +} + +int whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */ +{ + double x, y, x1, y1; + + dprintf("whatpos %o %d %d\n", p, p->o_type, corner); + x = p->o_x; + y = p->o_y; + if (p->o_type != PLACE && p->o_type != MOVE) { + x1 = p->o_val[0]; + y1 = p->o_val[1]; + } + switch (p->o_type) { + case PLACE: + break; + case BOX: + case BLOCK: + case TEXT: + switch (corner) { + case NORTH: y += y1 / 2; break; + case SOUTH: y -= y1 / 2; break; + case EAST: x += x1 / 2; break; + case WEST: x -= x1 / 2; break; + case NE: x += x1 / 2; y += y1 / 2; break; + case SW: x -= x1 / 2; y -= y1 / 2; break; + case SE: x += x1 / 2; y -= y1 / 2; break; + case NW: x -= x1 / 2; y += y1 / 2; break; + case START: + if (p->o_type == BLOCK) + return whatpos(objlist[(int)p->o_val[2]], START, px, py); + case END: + if (p->o_type == BLOCK) + return whatpos(objlist[(int)p->o_val[3]], END, px, py); + } + break; + case ARC: + switch (corner) { + case START: + if (p->o_attr & CW_ARC) { + x = p->o_val[2]; y = p->o_val[3]; + } else { + x = x1; y = y1; + } + break; + case END: + if (p->o_attr & CW_ARC) { + x = x1; y = y1; + } else { + x = p->o_val[2]; y = p->o_val[3]; + } + break; + } + if (corner == START || corner == END) + break; + x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y)); + /* Fall Through! */ + case CIRCLE: + case ELLIPSE: + switch (corner) { + case NORTH: y += y1; break; + case SOUTH: y -= y1; break; + case EAST: x += x1; break; + case WEST: x -= x1; break; + case NE: x += 0.707 * x1; y += 0.707 * y1; break; + case SE: x += 0.707 * x1; y -= 0.707 * y1; break; + case NW: x -= 0.707 * x1; y += 0.707 * y1; break; + case SW: x -= 0.707 * x1; y -= 0.707 * y1; break; + } + break; + case LINE: + case SPLINE: + case ARROW: + switch (corner) { + case START: break; /* already in place */ + case END: x = x1; y = y1; break; + default: /* change! */ + case CENTER: x = (x+x1)/2; y = (y+y1)/2; break; + case NORTH: if (y1 > y) { x = x1; y = y1; } break; + case SOUTH: if (y1 < y) { x = x1; y = y1; } break; + case EAST: if (x1 > x) { x = x1; y = y1; } break; + case WEST: if (x1 < x) { x = x1; y = y1; } break; + } + break; + case MOVE: + /* really ought to be same as line... */ + break; + } + dprintf("whatpos returns %g %g\n", x, y); + *px = x; + *py = y; + return 1; +} + +obj *gethere(void) /* make a place for curx,cury */ +{ + dprintf("gethere %g %g\n", curx, cury); + return(makepos(curx, cury)); +} + +obj *getlast(int n, int t) /* find n-th previous occurrence of type t */ +{ + int i, k; + obj *p; + + k = n; + for (i = nobj-1; i >= 0; i--) { + p = objlist[i]; + if (p->o_type == BLOCKEND) { + i = p->o_val[4]; + continue; + } + if (p->o_type != t) + continue; + if (--k > 0) + continue; /* not there yet */ + dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y); + return(p); + } + ERROR "there is no %dth last", n FATAL; + return(NULL); +} + +obj *getfirst(int n, int t) /* find n-th occurrence of type t */ +{ + int i, k; + obj *p; + + k = n; + for (i = 0; i < nobj; i++) { + p = objlist[i]; + if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */ + i = p->o_val[5] + 1; + continue; + } + if (p->o_type != t) + continue; + if (--k > 0) + continue; /* not there yet */ + dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y); + return(p); + } + ERROR "there is no %dth ", n FATAL; + return(NULL); +} + +double getblkvar(obj *p, char *s) /* find variable s2 in block p */ +{ + YYSTYPE y; + + y = getblk(p, s); + return y.f; +} + +obj *getblock(obj *p, char *s) /* find variable s in block p */ +{ + YYSTYPE y; + + y = getblk(p, s); + return y.o; +} + +YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */ +{ + static YYSTYPE bug; + struct symtab *stp; + + if (p->o_type != BLOCK) { + ERROR ".%s is not in that block", s WARNING; + return(bug); + } + for (stp = p->o_symtab; stp != NULL; stp = stp->s_next) + if (strcmp(s, stp->s_name) == 0) { + dprintf("getblk %s found x,y= %g,%g\n", + s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y); + return(stp->s_val); + } + ERROR "there is no .%s in that []", s WARNING; + return(bug); +} + +obj *fixpos(obj *p, double x, double y) +{ + dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y); + return makepos(p->o_x + x, p->o_y + y); +} + +obj *addpos(obj *p, obj *q) +{ + dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y); + return makepos(p->o_x+q->o_x, p->o_y+q->o_y); +} + +obj *subpos(obj *p, obj *q) +{ + dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y); + return makepos(p->o_x-q->o_x, p->o_y-q->o_y); +} + +obj *makenode(int type, int n) +{ + obj *p; + + p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat)); + if (p == NULL) + ERROR "out of space in makenode" FATAL; + p->o_type = type; + p->o_count = n; + p->o_nobj = nobj; + p->o_mode = hvmode; + p->o_x = curx; + p->o_y = cury; + p->o_nt1 = ntext1; + p->o_nt2 = ntext; + ntext1 = ntext; /* ready for next caller */ + if (nobj >= nobjlist) + objlist = (obj **) grow((char *) objlist, "objlist", + nobjlist *= 2, sizeof(obj *)); + objlist[nobj++] = p; + return(p); +} + +void extreme(double x, double y) /* record max and min x and y values */ +{ + if (x > xmax) + xmax = x; + if (y > ymax) + ymax = y; + if (x < xmin) + xmin = x; + if (y < ymin) + ymin = y; +} blob - /dev/null blob + b27e07db67680144a69093106f84285e7042053a (mode 644) --- /dev/null +++ src/cmd/pic/mkfile @@ -0,0 +1,38 @@ +<$PLAN9/src/mkhdr + +TARG=pic +OFILES=picy.$O\ + picl.$O\ + main.$O\ + print.$O\ + misc.$O\ + symtab.$O\ + blockgen.$O\ + boxgen.$O\ + circgen.$O\ + arcgen.$O\ + linegen.$O\ + movegen.$O\ + textgen.$O\ + input.$O\ + for.$O\ + pltroff.$O\ + +HFILES=pic.h\ + y.tab.h\ + +YFILES=picy.y\ + +SHORTLIB=bio 9 +<$PLAN9/src/mkone +YFLAGS=-S -d +LEX=9lex + +picy.c: y.tab.c + mv $prereq $target + +picl.c: picl.lx + $LEX -t $prereq > $target + +clean:V: + rm -f *.[$OS] [$OS].out y.tab.? y.debug $TARG picy.c picl.c blob - /dev/null blob + 5ff44d46b01dcca94e57d5a0f90faa83b78b043d (mode 644) --- /dev/null +++ src/cmd/pic/movegen.c @@ -0,0 +1,86 @@ +#include +#include "pic.h" +#include "y.tab.h" + +obj *movegen(void) +{ + static double prevdx, prevdy; + int i, some; + double defx, defy, dx, dy; + obj *p; + obj *ppos; + static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ + static int ytab[] = { 0, 1, 0, -1 }; + Attr *ap; + + defx = getfval("movewid"); + defy = getfval("moveht"); + dx = dy = some = 0; + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case TEXTATTR: + savetext(ap->a_sub, ap->a_val.p); + break; + case SAME: + dx = prevdx; + dy = prevdy; + some++; + break; + case LEFT: + dx -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; + some++; + hvmode = L_DIR; + break; + case RIGHT: + dx += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; + some++; + hvmode = R_DIR; + break; + case UP: + dy += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; + some++; + hvmode = U_DIR; + break; + case DOWN: + dy -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; + some++; + hvmode = D_DIR; + break; + case TO: + ppos = ap->a_val.o; + dx = ppos->o_x - curx; + dy = ppos->o_y - cury; + some++; + break; + case BY: + ppos = ap->a_val.o; + dx = ppos->o_x; + dy = ppos->o_y; + some++; + break; + case FROM: + case AT: + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + break; + } + } + if (some) { + defx = dx; + defy = dy; + } else { + defx *= xtab[hvmode]; + defy *= ytab[hvmode]; + } + prevdx = defx; + prevdy = defy; + extreme(curx, cury); + curx += defx; + cury += defy; + extreme(curx, cury); + p = makenode(MOVE, 0); + dprintf("M %g %g\n", curx, cury); + return(p); +} blob - /dev/null blob + a4f7a6a49284a148f10355e7462832855bdb414c (mode 644) --- /dev/null +++ src/cmd/pic/pic.h @@ -0,0 +1,219 @@ +#ifndef PI +#define PI 3.1415926535897932384626433832795028841971693993751 +#endif + +#define MAXWID 8.5 /* default limits max picture to 8.5 x 11; */ +#define MAXHT 11 /* change to taste without peril */ + +#define dprintf if(dbg)printf + +extern void yyerror(char *); + +extern char errbuf[200]; +#define ERROR sprintf(errbuf, +#define FATAL ), yyerror(errbuf), exit(1) +#define WARNING ), yyerror(errbuf) + +#define DEFAULT 0 + +#define HEAD1 1 +#define HEAD2 2 +#define HEAD12 (HEAD1+HEAD2) +#define INVIS 4 +#define CW_ARC 8 /* clockwise arc */ +#define DOTBIT 16 /* line styles */ +#define DASHBIT 32 +#define FILLBIT 64 /* gray-fill on boxes, etc. */ +#define NOEDGEBIT 128 /* no edge on filled object */ + +#define CENTER 01 /* text attributes */ +#define LJUST 02 +#define RJUST 04 +#define ABOVE 010 +#define BELOW 020 +#define SPREAD 040 + +#define SCALE 1.0 /* default scale: units/inch */ +#define WID 0.75 /* default width for boxes and ellipses */ +#define WID2 0.375 +#define HT 0.5 /* default height and line length */ +#define HT2 (HT/2) +#define HT5 (HT/5) +#define HT10 (HT/10) + +/* these have to be like so, so that we can write */ +/* things like R & V, etc. */ +#define H 0 +#define V 1 +#define R_DIR 0 +#define U_DIR 1 +#define L_DIR 2 +#define D_DIR 3 +#define ishor(n) (((n) & V) == 0) +#define isvert(n) (((n) & V) != 0) +#define isright(n) ((n) == R_DIR) +#define isleft(n) ((n) == L_DIR) +#define isdown(n) ((n) == D_DIR) +#define isup(n) ((n) == U_DIR) + +typedef float ofloat; /* for o_val[] in obj; could be double */ + +typedef struct obj { /* stores various things in variable length */ + int o_type; + int o_count; /* number of things */ + int o_nobj; /* index in objlist */ + int o_mode; /* hor or vert */ + float o_x; /* coord of "center" */ + float o_y; + int o_nt1; /* 1st index in text[] for this object */ + int o_nt2; /* 2nd; difference is #text strings */ + int o_attr; /* HEAD, CW, INVIS, etc., go here */ + int o_size; /* linesize */ + int o_nhead; /* arrowhead style */ + struct symtab *o_symtab; /* symtab for [...] */ + float o_ddval; /* value of dot/dash expression */ + float o_fillval; /* gray scale value */ + ofloat o_val[1]; /* actually this will be > 1 in general */ + /* type is not always FLOAT!!!! */ +} obj; + +typedef union { /* the yacc stack type */ + int i; + char *p; + obj *o; + double f; + struct symtab *st; +} YYSTYPE; + +extern YYSTYPE yylval, yyval; + +struct symtab { + char *s_name; + int s_type; + YYSTYPE s_val; + struct symtab *s_next; +}; + +typedef struct { /* attribute of an object */ + int a_type; + int a_sub; + YYSTYPE a_val; +} Attr; + +typedef struct { + int t_type; /* CENTER, LJUST, etc. */ + char t_op; /* optional sign for size changes */ + char t_size; /* size, abs or rel */ + char *t_val; +} Text; + +#define String 01 +#define Macro 02 +#define File 04 +#define Char 010 +#define Thru 020 +#define Free 040 + +typedef struct { /* input source */ + int type; /* Macro, String, File */ + char *sp; /* if String or Macro */ +} Src; + +extern Src src[], *srcp; /* input source stack */ + +typedef struct { + FILE *fin; + char *fname; + int lineno; +} Infile; + +extern Infile infile[], *curfile; + +#define MAXARGS 20 +typedef struct { /* argument stack */ + char *argstk[MAXARGS]; /* pointers to args */ + char *argval; /* points to space containing args */ +} Arg; + +extern int dbg; +extern obj **objlist; +extern int nobj, nobjlist; +extern Attr *attr; +extern int nattr, nattrlist; +extern Text *text; +extern int ntextlist; +extern int ntext; +extern int ntext1; +extern double curx, cury; +extern int hvmode; +extern int codegen; +extern char *PEstring; + +char *tostring(char *); +char *grow(char *, char *, int, int); +double getfval(char *), getcomp(obj *, int), getblkvar(obj *, char *); +YYSTYPE getvar(char *); +struct symtab *lookup(char *), *makevar(char *, int, YYSTYPE); +char *ifstat(double, char *, char *), *delimstr(char *), *sprintgen(char *); +void forloop(char *var, double from, double to, int op, double by, char *_str); +int setdir(int), curdir(void); +void resetvar(void); +void checkscale(char *); +void pushsrc(int, char *); +void copy(void); +void copyuntil(char *); +void copyfile(char *); +void copydef(struct symtab *); +void definition(char *); +struct symtab *copythru(char *); +int input(void); +int unput(int); +void extreme(double, double); + +extern double deltx, delty; +extern int lineno; +extern int synerr; + +extern double xmin, ymin, xmax, ymax; + +obj *leftthing(int), *boxgen(void), *circgen(int), *arcgen(int); +obj *linegen(int), *splinegen(void), *movegen(void); +obj *textgen(void), *plotgen(void); +obj *troffgen(char *), *rightthing(obj *, int), *blockgen(obj *, obj *); +obj *makenode(int, int), *makepos(double, double); +obj *fixpos(obj *, double, double); +obj *addpos(obj *, obj *), *subpos(obj *, obj *); +obj *makebetween(double, obj *, obj *); +obj *getpos(obj *, int), *gethere(void), *getfirst(int, int); +obj *getlast(int, int), *getblock(obj *, char *); +void savetext(int, char *); +void makeiattr(int, int); +void makevattr(char *); +void makefattr(int type, int sub, double f); +void maketattr(int, char *); +void makeoattr(int, obj *); +void makeattr(int type, int sub, YYSTYPE val); +void printexpr(double); +void printpos(obj *); +void exprsave(double); +void addtattr(int); +void printlf(int, char *); + +struct pushstack { + double p_x; + double p_y; + int p_hvmode; + double p_xmin; + double p_ymin; + double p_xmax; + double p_ymax; + struct symtab *p_symtab; +}; +extern struct pushstack stack[]; +extern int nstack; +extern int cw; + +extern double errcheck(double, char *); +#define Log10(x) errcheck(log10(x), "log") +#define Exp(x) errcheck(exp(x), "exp") +#define Sqrt(x) errcheck(sqrt(x), "sqrt") blob - /dev/null blob + dbe2a3d5c86c3a18b1c66c9383ec360a630d7a22 (mode 644) --- /dev/null +++ src/cmd/pic/picl.lx @@ -0,0 +1,273 @@ +%Start A str def sc br thru sh +%e 1700 +%k 120 +%a 1800 +%o 1500 +%p 5000 +%n 700 + +%{ +#undef input +#undef unput +/* #include lex puts one out for us */ +#include +#include +#include "pic.h" +#include "y.tab.h" + +extern char *filename; +extern struct symtab symtab[]; + +void pbstr(char *); +void dodef(struct symtab *stp); +void undefine(char *s); +void shell_init(void), shell_exec(void), shell_text(char *); +void endfor(void); + +int yyback(int *, int); +int yylook(void); +int yywrap(void); + +#define CADD cbuf[clen++]=yytext[0]; \ + if (clen>=CBUFLEN-1) { ERROR "string too long", cbuf WARNING; BEGIN A; } +#define CBUFLEN 500 +char cbuf[CBUFLEN]; +int c, clen, cflag, delim; +int ifsw = 0; /* 1 if if statement in progress */ +%} + +A [a-zA-Z_] +B [a-zA-Z0-9_] +D [0-9] +WS [ \t] + +%% + switch (yybgin-yysvec-1) { /* witchcraft */ + case 0: + BEGIN A; + break; + case sc: + BEGIN A; + return('}'); + case br: + BEGIN A; + return(']'); + } + +{WS} ; +"\\"\n ; +\n { return(ST); } +";" { return(ST); } +"}" { BEGIN sc; return(ST); } +"]" { BEGIN br; return(ST); } +"{"{WS}*(#.*)?\n+ { return(yylval.i = yytext[0]); } + +^".PS".* { if (curfile == infile) ERROR ".PS found inside .PS/.PE" WARNING; } +^".PE".* { if (curfile == infile) { + yylval.p = PEstring = tostring(yytext); + return(EOF); + } + } +^".".* { yylval.p = tostring(yytext); return(TROFF); } + +print return(yylval.i = PRINT); +box return(yylval.i = BOX); +circle return(yylval.i = CIRCLE); +arc return(yylval.i = ARC); +ellipse return(yylval.i = ELLIPSE); +arrow return(yylval.i = ARROW); +spline return(yylval.i = SPLINE); +line return(yylval.i = LINE); +move return(yylval.i = MOVE); +"[]" return(yylval.i = BLOCK); +reset return(RESET); +sprintf return(SPRINTF); + +same return(SAME); +between return(BETWEEN); +and return(AND); + +of ; +the ; +way ; + +"."(e|east) { yylval.i = EAST; return(CORNER); } +"."(r|right) { yylval.i = EAST; return(CORNER); } +"."(w|west) { yylval.i = WEST; return(CORNER); } +"."(l|left) { yylval.i = WEST; return(CORNER); } +"."(n|north) { yylval.i = NORTH; return(CORNER); } +"."(t|top) { yylval.i = NORTH; return(CORNER); } +"."(s|south) { yylval.i = SOUTH; return(CORNER); } +"."(b|bot|bottom) { yylval.i = SOUTH; return(CORNER); } +"."(c|center) { yylval.i = CENTER; return(CORNER); } +".start" { yylval.i = START; return(CORNER); } +".end" { yylval.i = END; return(CORNER); } +".ne" { yylval.i = NE; return(CORNER); } +".se" { yylval.i = SE; return(CORNER); } +".nw" { yylval.i = NW; return(CORNER); } +".sw" { yylval.i = SW; return(CORNER); } + +top" "+of { yylval.i = NORTH; return(CORNER); } +north" "+of { yylval.i = NORTH; return(CORNER); } +bottom" "+of { yylval.i = SOUTH; return(CORNER); } +south" "+of { yylval.i = SOUTH; return(CORNER); } +left" "+of { yylval.i = WEST; return(CORNER); } +west" "+of { yylval.i = WEST; return(CORNER); } +right" "+of { yylval.i = EAST; return(CORNER); } +east" "+of { yylval.i = EAST; return(CORNER); } +center" "+of { yylval.i = CENTER; return(CORNER); } +start" "+of { yylval.i = START; return(CORNER); } +end" "+of { yylval.i = END; return(CORNER); } + +height|ht { yylval.i = HEIGHT; return(ATTR); } +width|wid { yylval.i = WIDTH; return(ATTR); } +radius|rad { yylval.i = RADIUS; return(ATTR); } +diameter|diam { yylval.i = DIAMETER; return(ATTR); } +size { yylval.i = SIZE; return(ATTR); } +left { yylval.i = LEFT; return(DIR); } +right { yylval.i = RIGHT; return(DIR); } +up { yylval.i = UP; return(DIR); } +down { yylval.i = DOWN; return(DIR); } +cw { yylval.i = CW; return(ATTR); } +clockwise { yylval.i = CW; return(ATTR); } +ccw { yylval.i = CCW; return(ATTR); } +invis(ible)? { yylval.i = INVIS; return(ATTR); } +noedge { yylval.i = INVIS; return ATTR; } +fill return(yylval.i = FILL); +solid ; +dot(ted)? return(yylval.i = DOT); +dash(ed)? return(yylval.i = DASH); +chop return(yylval.i = CHOP); + +spread { yylval.i = SPREAD; return TEXTATTR; } +ljust { yylval.i = LJUST; return TEXTATTR; } +rjust { yylval.i = RJUST; return TEXTATTR; } +above { yylval.i = ABOVE; return TEXTATTR; } +below { yylval.i = BELOW; return TEXTATTR; } +center { yylval.i = CENTER; return TEXTATTR; } + +"<-" { yylval.i = HEAD1; return(HEAD); } +"->" { yylval.i = HEAD2; return(HEAD); } +"<->" { yylval.i = HEAD12; return(HEAD); } + +".x" return(yylval.i = DOTX); +".y" return(yylval.i = DOTY); +"."(ht|height) return(yylval.i = DOTHT); +"."(wid|width) return(yylval.i = DOTWID); +"."(rad|radius) return(yylval.i = DOTRAD); + +from return(yylval.i = FROM); +to return(yylval.i = TO); +at return(yylval.i = AT); +by return(yylval.i = BY); +with return(yylval.i = WITH); +last return(yylval.i = LAST); + +log return(LOG); +exp return(EXP); +sin return(SIN); +cos return(COS); +atan2 return(ATAN2); +sqrt return(SQRT); +rand return(RAND); +max return(MAX); +min return(MIN); +int return(INT); + +"==" return(EQ); +">=" return(GE); +"<=" return(LE); +"!=" return(NEQ); +">" return(GT); +"<" return(LT); +"&&" return(ANDAND); +"||" return(OROR); +"!" return(NOT); + +Here return(yylval.i = HERE); + +for return(FOR); +^Endfor\n { endfor(); } +do { yylval.p = delimstr("loop body"); return(DOSTR); } + +copy|include return(COPY); +(thru|through){WS}+ { BEGIN thru; return(THRU); } +{A}{B}*|. { yylval.st = copythru(yytext); BEGIN A; return(DEFNAME); } +until return(UNTIL); + +if { ifsw = 1; return(IF); } +then { if (!ifsw) { yylval.i = THEN; return(ATTR); } + yylval.p = delimstr("then part"); ifsw = 0; + return(THENSTR); } +else { yylval.p = delimstr("else part"); return(ELSESTR); } + +sh{WS}+ { BEGIN sh; + if ((delim = input()) == '{') delim = '}'; /* no nested {} */ + shell_init(); } +{A}{B}* { struct symtab *p; + if (yytext[0] == delim) { + shell_exec(); + BEGIN A; + } else { + p = lookup(yytext); + if (p != NULL && p->s_type == DEFNAME) { + c = input(); + unput(c); + if (c == '(') + dodef(p); + else + pbstr(p->s_val.p); + } else + shell_text(yytext); + } + } +.|\n { if (yytext[0] == delim) { + shell_exec(); + BEGIN A; + } else + shell_text(yytext); + } + +define{WS}+ { BEGIN def; } +{A}{B}* { definition(yytext); BEGIN A; } +undef(ine)?{WS}+{A}{B}* { undefine(yytext); } + +first { yylval.i = 1; return(NTH); } +{D}+(th|nd|rd|st) { yylval.i = atoi(yytext); return(NTH); } +({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)?i? { + yylval.f = atof(yytext); return(NUMBER); } + +{A}{B}* { struct symtab *p; + p = lookup(yytext); + if (p != NULL && p->s_type == DEFNAME) { + c = input(); + unput(c); + if (c == '(') /* it's name(...) */ + dodef(p); + else { /* no argument list */ + pbstr(p->s_val.p); + dprintf("pushing back `%s'\n", p->s_val.p); + } + } else if (islower(yytext[0])) { + yylval.p = tostring(yytext); + return(VARNAME); + } else { + yylval.p = tostring(yytext); + return(PLACENAME); + } + } + +\" { BEGIN str; clen=0; } +\" { cbuf[clen]=0; yylval.p = tostring(cbuf); BEGIN A; return(TEXT); } +\n { cbuf[clen]=0; ERROR "missing quote in string \"%s\"", cbuf WARNING; + BEGIN A; return(ST); } +"\\\"" { cbuf[clen++]='"'; } +"\\"t { cbuf[clen++]='\t'; } +"\\\\" { cbuf[clen++]='\\'; } +. { CADD; } + +#.* ; + +. return(yylval.i = yytext[0]); + +%% blob - /dev/null blob + b534b5a53e437f63849a6d153eb01f39a22c9868 (mode 644) --- /dev/null +++ src/cmd/pic/picy.y @@ -0,0 +1,328 @@ +%{ +#include +#include "pic.h" +#include +#include +#include + +YYSTYPE y; + +extern void yyerror(char *); +extern int yylex(void); +%} + +%token BOX 1 /* DON'T CHANGE THESE! */ +%token LINE 2 +%token ARROW 3 +%token CIRCLE 4 +%token ELLIPSE 5 +%token ARC 6 +%token SPLINE 7 +%token BLOCK 8 +%token

TEXT 9 +%token

TROFF 10 +%token MOVE 11 +%token BLOCKEND 12 +%token PLACE 13 +%token PRINT RESET THRU UNTIL +%token FOR IF COPY +%token

THENSTR ELSESTR DOSTR PLACENAME VARNAME SPRINTF +%token DEFNAME +%token ATTR TEXTATTR +%token LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN +%token HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE +%token CORNER HERE LAST NTH SAME BETWEEN AND +%token EAST WEST NORTH SOUTH NE NW SE SW START END +%token DOTX DOTY DOTHT DOTWID DOTRAD +%token NUMBER +%token LOG EXP SIN COS ATAN2 SQRT RAND MIN MAX INT +%token DIR +%token DOT DASH CHOP FILL NOEDGE +%token ST /* statement terminator */ + +%right '=' +%left OROR +%left ANDAND +%nonassoc GT LT LE GE EQ NEQ +%left '+' '-' +%left '*' '/' '%' +%right UMINUS NOT +%right '^' + +%type expr if_expr asgn +%type

name text +%type optop exprlist +%type if for copy + +/* this is a lie: picture and position are really the whole union */ +%type leftbrace picture piclist position lbracket +%type prim place blockname +%type textlist textattr /* not a sensible value */ +%type last type + +%% + +top: + piclist + | /* empty */ + | error { ERROR "syntax error" WARNING; } + ; + +piclist: + picture + | piclist picture + ; + +picture: + prim ST { codegen = 1; makeiattr(0, 0); } + | leftbrace piclist '}' { rightthing($1, '}'); $$ = $2; } + | PLACENAME ':' picture { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; } + | PLACENAME ':' ST picture { y.o=$4; makevar($1,PLACENAME,y); $$ = $4; } + | PLACENAME ':' position ST { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; } + | asgn ST { y.f = $1; $$ = y.o; $$ = makenode(PLACE, 0); } + | DIR { setdir($1); $$ = makenode(PLACE, 0); } + | PRINT expr ST { printexpr($2); $$ = makenode(PLACE, 0); } + | PRINT position ST { printpos($2); $$ = makenode(PLACE, 0); } + | PRINT text ST { printf("%s\n", $2); free($2); $$ = makenode(PLACE, 0); } + | RESET varlist ST { resetvar(); makeiattr(0, 0); $$ = makenode(PLACE, 0); } + | copy + | for + | if + | ST + ; + +varlist: + /* empty */ + | VARNAME { makevattr($1); } + | varlist VARNAME { makevattr($2); } + | varlist ',' VARNAME { makevattr($3); } + ; + +asgn: + VARNAME '=' expr { $$=y.f=$3; makevar($1,VARNAME,y); checkscale($1); } + ; + +copy: + COPY copylist { copy(); } + ; +copylist: + copyattr + | copylist copyattr + ; +copyattr: + text { copyfile($1); } + | THRU DEFNAME { copydef($2); } + | UNTIL text { copyuntil($2); } + ; + +for: + FOR name FROM expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name FROM expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + | FOR name '=' expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name '=' expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + ; + +if: + IF if_expr THENSTR ELSESTR { ifstat($2, $3, $4); } + | IF if_expr THENSTR { ifstat($2, $3, (char *) 0); } + ; +if_expr: + expr + | text EQ text { $$ = strcmp($1,$3) == 0; free($1); free($3); } + | text NEQ text { $$ = strcmp($1,$3) != 0; free($1); free($3); } + ; + +name: + VARNAME { y.f = 0; makevar($1, VARNAME, y); } + ; +optop: + '+' { $$ = '+'; } + | '-' { $$ = '-'; } + | '*' { $$ = '*'; } + | '/' { $$ = '/'; } + | /* empty */ { $$ = ' '; } + ; + + +leftbrace: + '{' { $$ = leftthing('{'); } + ; + +prim: + BOX attrlist { $$ = boxgen(); } + | CIRCLE attrlist { $$ = circgen($1); } + | ELLIPSE attrlist { $$ = circgen($1); } + | ARC attrlist { $$ = arcgen($1); } + | LINE attrlist { $$ = linegen($1); } + | ARROW attrlist { $$ = linegen($1); } + | SPLINE attrlist { $$ = linegen($1); } + | MOVE attrlist { $$ = movegen(); } + | textlist attrlist { $$ = textgen(); } + | TROFF { $$ = troffgen($1); } + | lbracket piclist ']' { $$=rightthing($1,']'); } attrlist + { $$ = blockgen($1, $4); } + ; + +lbracket: + '[' { $$ = leftthing('['); } + ; + +attrlist: + attrlist attr + | /* empty */ + ; + +attr: + ATTR expr { makefattr($1, !DEFAULT, $2); } + | ATTR { makefattr($1, DEFAULT, 0.0); } + | expr { makefattr(curdir(), !DEFAULT, $1); } + | DIR expr { makefattr($1, !DEFAULT, $2); } + | DIR { makefattr($1, DEFAULT, 0.0); } + | FROM position { makeoattr($1, $2); } + | TO position { makeoattr($1, $2); } + | AT position { makeoattr($1, $2); } + | BY position { makeoattr($1, $2); } + | WITH CORNER { makeiattr(WITH, $2); } + | WITH '.' PLACENAME { makeoattr(PLACE, getblock(getlast(1,BLOCK), $3)); } + | WITH '.' PLACENAME CORNER + { makeoattr(PLACE, getpos(getblock(getlast(1,BLOCK), $3), $4)); } + | WITH position { makeoattr(PLACE, $2); } + | SAME { makeiattr(SAME, $1); } + | TEXTATTR { maketattr($1, (char *) 0); } + | HEAD { makeiattr(HEAD, $1); } + | DOT expr { makefattr(DOT, !DEFAULT, $2); } + | DOT { makefattr(DOT, DEFAULT, 0.0); } + | DASH expr { makefattr(DASH, !DEFAULT, $2); } + | DASH { makefattr(DASH, DEFAULT, 0.0); } + | CHOP expr { makefattr(CHOP, !DEFAULT, $2); } + | CHOP { makefattr(CHOP, DEFAULT, 0.0); } + | CHOP PLACENAME { makeattr(CHOP, PLACENAME, getvar($2)); } + | FILL expr { makefattr(FILL, !DEFAULT, $2); } + | FILL { makefattr(FILL, DEFAULT, 0.0); } + | NOEDGE { makeiattr(NOEDGE, 0); } + | textlist + ; + +textlist: + textattr + | textlist textattr + ; +textattr: + text { maketattr(CENTER, $1); } + | text TEXTATTR { maketattr($2, $1); } + | textattr TEXTATTR { addtattr($2); } + ; +text: + TEXT + | SPRINTF '(' text ')' { $$ = sprintgen($3); } + | SPRINTF '(' text ',' exprlist ')' { $$ = sprintgen($3); } + ; + +exprlist: + expr { exprsave($1); $$ = 0; } + | exprlist ',' expr { exprsave($3); } + ; + +position: /* absolute, not relative */ + place + | '(' position ')' { $$ = $2; } + | expr ',' expr { $$ = makepos($1, $3); } + | position '+' expr ',' expr { $$ = fixpos($1, $3, $5); } + | position '-' expr ',' expr { $$ = fixpos($1, -$3, -$5); } + | position '+' '(' expr ',' expr ')' { $$ = fixpos($1, $4, $6); } + | position '-' '(' expr ',' expr ')' { $$ = fixpos($1, -$4, -$6); } + | position '+' place { $$ = addpos($1, $3); } + | position '-' place { $$ = subpos($1, $3); } + | '(' place ',' place ')' { $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); } + | expr LT position ',' position GT { $$ = makebetween($1, $3, $5); } + | expr BETWEEN position AND position { $$ = makebetween($1, $3, $5); } + ; + +place: + PLACENAME { y = getvar($1); $$ = y.o; } + | PLACENAME CORNER { y = getvar($1); $$ = getpos(y.o, $2); } + | CORNER PLACENAME { y = getvar($2); $$ = getpos(y.o, $1); } + | HERE { $$ = gethere(); } + | last type { $$ = getlast($1, $2); } + | last type CORNER { $$ = getpos(getlast($1, $2), $3); } + | CORNER last type { $$ = getpos(getlast($2, $3), $1); } + | NTH type { $$ = getfirst($1, $2); } + | NTH type CORNER { $$ = getpos(getfirst($1, $2), $3); } + | CORNER NTH type { $$ = getpos(getfirst($2, $3), $1); } + | blockname + | blockname CORNER { $$ = getpos($1, $2); } + | CORNER blockname { $$ = getpos($2, $1); } + ; + +blockname: + last BLOCK '.' PLACENAME { $$ = getblock(getlast($1,$2), $4); } + | NTH BLOCK '.' PLACENAME { $$ = getblock(getfirst($1,$2), $4); } + | PLACENAME '.' PLACENAME { y = getvar($1); $$ = getblock(y.o, $3); } + ; + +last: + last LAST { $$ = $1 + 1; } + | NTH LAST { $$ = $1; } + | LAST { $$ = 1; } + ; + +type: + BOX + | CIRCLE + | ELLIPSE + | ARC + | LINE + | ARROW + | SPLINE + | BLOCK + ; + +expr: + NUMBER + | VARNAME { $$ = getfval($1); } + | asgn + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { if ($3 == 0.0) { + ERROR "division by 0" WARNING; $3 = 1; } + $$ = $1 / $3; } + | expr '%' expr { if ((long)$3 == 0) { + ERROR "mod division by 0" WARNING; $3 = 1; } + $$ = (long)$1 % (long)$3; } + | '-' expr %prec UMINUS { $$ = -$2; } + | '+' expr %prec UMINUS { $$ = $2; } + | '(' expr ')' { $$ = $2; } + | place DOTX { $$ = getcomp($1, $2); } + | place DOTY { $$ = getcomp($1, $2); } + | place DOTHT { $$ = getcomp($1, $2); } + | place DOTWID { $$ = getcomp($1, $2); } + | place DOTRAD { $$ = getcomp($1, $2); } + | PLACENAME '.' VARNAME { y = getvar($1); $$ = getblkvar(y.o, $3); } + | last BLOCK '.' VARNAME { $$ = getblkvar(getlast($1,$2), $4); } + | NTH BLOCK '.' VARNAME { $$ = getblkvar(getfirst($1,$2), $4); } + | expr GT expr { $$ = $1 > $3; } + | expr LT expr { $$ = $1 < $3; } + | expr LE expr { $$ = $1 <= $3; } + | expr GE expr { $$ = $1 >= $3; } + | expr EQ expr { $$ = $1 == $3; } + | expr NEQ expr { $$ = $1 != $3; } + | expr ANDAND expr { $$ = $1 && $3; } + | expr OROR expr { $$ = $1 || $3; } + | NOT expr { $$ = !($2); } + | LOG '(' expr ')' { $$ = Log10($3); } + | EXP '(' expr ')' { $$ = Exp($3 * log(10.0)); } + | expr '^' expr { $$ = pow($1, $3); } + | SIN '(' expr ')' { $$ = sin($3); } + | COS '(' expr ')' { $$ = cos($3); } + | ATAN2 '(' expr ',' expr ')' { $$ = atan2($3, $5); } + | SQRT '(' expr ')' { $$ = Sqrt($3); } + | RAND '(' ')' { $$ = (float)rand() / 32767.0; /* might be 2^31-1 */ } + | MAX '(' expr ',' expr ')' { $$ = $3 >= $5 ? $3 : $5; } + | MIN '(' expr ',' expr ')' { $$ = $3 <= $5 ? $3 : $5; } + | INT '(' expr ')' { $$ = (long) $3; } + ; blob - /dev/null blob + d3e3151bac28b062f5fae01dce5ffa20ddc75bce (mode 644) --- /dev/null +++ src/cmd/pic/pltroff.c @@ -0,0 +1,357 @@ +#include +#include +#include +#include "pic.h" +extern int dbg; + +#define abs(n) (n >= 0 ? n : -(n)) +#define max(x,y) ((x)>(y) ? (x) : (y)) + +char *textshift = "\\v'.2m'"; /* move text this far down */ + +/* scaling stuff defined by s command as X0,Y0 to X1,Y1 */ +/* output dimensions set by -l,-w options to 0,0 to hmax, vmax */ +/* default output is 6x6 inches */ + + +double xscale; +double yscale; + +double hpos = 0; /* current horizontal position in output coordinate system */ +double vpos = 0; /* current vertical position; 0 is top of page */ + +double htrue = 0; /* where we really are */ +double vtrue = 0; + +double X0, Y0; /* left bottom of input */ +double X1, Y1; /* right top of input */ + +double hmax; /* right end of output */ +double vmax; /* top of output (down is positive) */ + +extern double deltx; +extern double delty; +extern double xmin, ymin, xmax, ymax; + +double xconv(double), yconv(double), xsc(double), ysc(double); +void space(double, double, double, double); +void hgoto(double), vgoto(double), hmot(double), vmot(double); +void move(double, double), movehv(double, double); +void cont(double, double); + +void openpl(char *s) /* initialize device; s is residue of .PS invocation line */ +{ + double maxw, maxh, ratio = 1; + double odeltx = deltx, odelty = delty; + + hpos = vpos = 0; + maxw = getfval("maxpswid"); + maxh = getfval("maxpsht"); + if (deltx > maxw) { /* shrink horizontal */ + ratio = maxw / deltx; + deltx *= ratio; + delty *= ratio; + } + if (delty > maxh) { /* shrink vertical */ + ratio = maxh / delty; + deltx *= ratio; + delty *= ratio; + } + if (ratio != 1) { + fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty); + fprintf(stderr, " %g X %g\n", deltx, delty); + } + space(xmin, ymin, xmax, ymax); + printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax); + printf("... %.3fi %.3fi %.3fi %.3fi\n", + xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax)); + printf(".nr 00 \\n(.u\n"); + printf(".nf\n"); + printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s); + /* assumes \n comes as part of s */ +} + +void space(double x0, double y0, double x1, double y1) /* set limits of page */ +{ + X0 = x0; + Y0 = y0; + X1 = x1; + Y1 = y1; + xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0); + yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0); +} + +double xconv(double x) /* convert x from external to internal form */ +{ + return (x-X0) * xscale; +} + +double xsc(double x) /* convert x from external to internal form, scaling only */ +{ + + return (x) * xscale; +} + +double yconv(double y) /* convert y from external to internal form */ +{ + return (Y1-y) * yscale; +} + +double ysc(double y) /* convert y from external to internal form, scaling only */ +{ + return (y) * yscale; +} + +void closepl(char *PEline) /* clean up after finished */ +{ + movehv(0.0, 0.0); /* get back to where we started */ + if (strchr(PEline, 'F') == NULL) { + printf(".sp 1+%.3fi\n", yconv(ymin)); + } + printf("%s\n", PEline); + printf(".if \\n(00 .fi\n"); +} + +void move(double x, double y) /* go to position x, y in external coords */ +{ + hgoto(xconv(x)); + vgoto(yconv(y)); +} + +void movehv(double h, double v) /* go to internal position h, v */ +{ + hgoto(h); + vgoto(v); +} + +void hmot(double n) /* generate n units of horizontal motion */ +{ + hpos += n; +} + +void vmot(double n) /* generate n units of vertical motion */ +{ + vpos += n; +} + +void hgoto(double n) +{ + hpos = n; +} + +void vgoto(double n) +{ + vpos = n; +} + +double fabs(double x) +{ + return x < 0 ? -x : x; +} + +void hvflush(void) /* get to proper point for output */ +{ + if (fabs(hpos-htrue) >= 0.0005) { + printf("\\h'%.3fi'", hpos - htrue); + htrue = hpos; + } + if (fabs(vpos-vtrue) >= 0.0005) { + printf("\\v'%.3fi'", vpos - vtrue); + vtrue = vpos; + } +} + +void flyback(void) /* return to upper left corner (entry point) */ +{ + printf(".sp -1\n"); + htrue = vtrue = 0; +} + +void printlf(int n, char *f) +{ + if (f) + printf(".lf %d %s\n", n, f); + else + printf(".lf %d\n", n); +} + +void troff(char *s) /* output troff right here */ +{ + printf("%s\n", s); +} + +void label(char *s, int t, int nh) /* text s of type t nh half-lines up */ +{ + int q; + char *p; + + if (!s) + return; + hvflush(); + dprintf("label: %s %o %d\n", s, t, nh); + printf("%s", textshift); /* shift down and left */ + if (t & ABOVE) + nh++; + else if (t & BELOW) + nh--; + if (nh) + printf("\\v'%du*\\n(.vu/2u'", -nh); + /* just in case the text contains a quote: */ + q = 0; + for (p = s; *p; p++) + if (*p == '\'') { + q = 1; + break; + } + t &= ~(ABOVE|BELOW); + if (t & LJUST) { + printf("%s", s); + } else if (t & RJUST) { + if (q) + printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s); + else + printf("\\h'-\\w'%s'u'%s", s, s); + } else { /* CENTER */ + if (q) + printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s); + else + printf("\\h'-\\w'%s'u/2u'%s", s, s); + } + printf("\n"); + flyback(); +} + +void line(double x0, double y0, double x1, double y1) /* draw line from x0,y0 to x1,y1 */ +{ + move(x0, y0); + cont(x1, y1); +} + +void arrow(double x0, double y0, double x1, double y1, double w, double h, + double ang, int nhead) /* draw arrow (without shaft) */ +{ + double alpha, rot, drot, hyp; + double dx, dy; + int i; + + rot = atan2(w / 2, h); + hyp = sqrt(w/2 * w/2 + h * h); + alpha = atan2(y1-y0, x1-x0) + ang; + if (nhead < 2) + nhead = 2; + dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha); + for (i = nhead-1; i >= 0; i--) { + drot = 2 * rot / (double) (nhead-1) * (double) i; + dx = hyp * cos(alpha + PI - rot + drot); + dy = hyp * sin(alpha + PI - rot + drot); + dprintf("dx,dy = %g,%g\n", dx, dy); + line(x1+dx, y1+dy, x1, y1); + } +} + +double lastgray = 0; + +void fillstart(double v) /* this works only for postscript, obviously. */ +{ /* uses drechsler's dpost conventions... */ + hvflush(); + printf("\\X'BeginObject %g setgray'\n", v); + lastgray = v; + flyback(); +} + +void fillend(int vis, int fill) +{ + hvflush(); + printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n", + !vis ? lastgray : 0.0, + vis ? "stroke" : ""); + /* for dashed: [50] 0 setdash just before stroke. */ + lastgray = 0; + flyback(); +} + +void box(double x0, double y0, double x1, double y1) +{ + move(x0, y0); + cont(x0, y1); + cont(x1, y1); + cont(x1, y0); + cont(x0, y0); +} + +void cont(double x, double y) /* continue line from here to x,y */ +{ + double h1, v1; + double dh, dv; + + h1 = xconv(x); + v1 = yconv(y); + dh = h1 - hpos; + dv = v1 - vpos; + hvflush(); + printf("\\D'l%.3fi %.3fi'\n", dh, dv); + flyback(); /* expensive */ + hpos = h1; + vpos = v1; +} + +void circle(double x, double y, double r) +{ + move(x-r, y); + hvflush(); + printf("\\D'c%.3fi'\n", xsc(2 * r)); + flyback(); +} + +void spline(double x, double y, double n, ofloat *p, int dashed, double ddval) +{ + int i; + double dx, dy; + double xerr, yerr; + + move(x, y); + hvflush(); + xerr = yerr = 0.0; + printf("\\D'~"); + for (i = 0; i < 2 * n; i += 2) { + dx = xsc(xerr += p[i]); + xerr -= dx/xscale; + dy = ysc(yerr += p[i+1]); + yerr -= dy/yscale; + printf(" %.3fi %.3fi", dx, -dy); /* WATCH SIGN */ + } + printf("'\n"); + flyback(); +} + +void ellipse(double x, double y, double r1, double r2) +{ + double ir1, ir2; + + move(x-r1, y); + hvflush(); + ir1 = xsc(r1); + ir2 = ysc(r2); + printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2)); + flyback(); +} + +void arc(double x, double y, double x0, double y0, double x1, double y1) /* draw arc with center x,y */ +{ + + move(x0, y0); + hvflush(); + printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n", + xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y)); /* WATCH SIGNS */ + flyback(); +} + +void dot(void) { + hvflush(); + /* what character to draw here depends on what's available. */ + /* on the 202, l. is good but small. */ + /* in general, use a smaller, shifted period and hope */ + + printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n"); + flyback(); +} blob - /dev/null blob + 4782af9bdb49c4c3537c1810ae457924ce32f66b (mode 644) --- /dev/null +++ src/cmd/pic/prevy.tab.h @@ -0,0 +1,97 @@ +# define BOX 1 +# define LINE 2 +# define ARROW 3 +# define CIRCLE 4 +# define ELLIPSE 5 +# define ARC 6 +# define SPLINE 7 +# define BLOCK 8 +# define TEXT 9 +# define TROFF 10 +# define MOVE 11 +# define BLOCKEND 12 +# define PLACE 13 +# define PRINT 270 +# define RESET 271 +# define THRU 272 +# define UNTIL 273 +# define FOR 274 +# define IF 275 +# define COPY 276 +# define THENSTR 277 +# define ELSESTR 278 +# define DOSTR 279 +# define PLACENAME 280 +# define VARNAME 281 +# define SPRINTF 282 +# define DEFNAME 283 +# define ATTR 284 +# define TEXTATTR 285 +# define LEFT 286 +# define RIGHT 287 +# define UP 288 +# define DOWN 289 +# define FROM 290 +# define TO 291 +# define AT 292 +# define BY 293 +# define WITH 294 +# define HEAD 295 +# define CW 296 +# define CCW 297 +# define THEN 298 +# define HEIGHT 299 +# define WIDTH 300 +# define RADIUS 301 +# define DIAMETER 302 +# define LENGTH 303 +# define SIZE 304 +# define CORNER 305 +# define HERE 306 +# define LAST 307 +# define NTH 308 +# define SAME 309 +# define BETWEEN 310 +# define AND 311 +# define EAST 312 +# define WEST 313 +# define NORTH 314 +# define SOUTH 315 +# define NE 316 +# define NW 317 +# define SE 318 +# define SW 319 +# define START 320 +# define END 321 +# define DOTX 322 +# define DOTY 323 +# define DOTHT 324 +# define DOTWID 325 +# define DOTRAD 326 +# define NUMBER 327 +# define LOG 328 +# define EXP 329 +# define SIN 330 +# define COS 331 +# define ATAN2 332 +# define SQRT 333 +# define RAND 334 +# define MIN 335 +# define MAX 336 +# define INT 337 +# define DIR 338 +# define DOT 339 +# define DASH 340 +# define CHOP 341 +# define FILL 342 +# define ST 343 +# define OROR 344 +# define ANDAND 345 +# define GT 346 +# define LT 347 +# define LE 348 +# define GE 349 +# define EQ 350 +# define NEQ 351 +# define UMINUS 352 +# define NOT 353 blob - /dev/null blob + ad21e0d70ed99b3df401e6156a36c425061934f7 (mode 644) --- /dev/null +++ src/cmd/pic/print.c @@ -0,0 +1,238 @@ +#include +#include +#include "pic.h" +#include "y.tab.h" + +void dotext(obj *); +void dotline(double, double, double, double, int, double); +void dotbox(double, double, double, double, int, double); +void ellipse(double, double, double, double); +void circle(double, double, double); +void arc(double, double, double, double, double, double); +void arrow(double, double, double, double, double, double, double, int); +void line(double, double, double, double); +void box(double, double, double, double); +void spline(double x, double y, double n, ofloat *p, int dashed, double ddval); +void move(double, double); +void troff(char *); +void dot(void); +void fillstart(double), fillend(int vis, int noedge); + +void print(void) +{ + obj *p; + int i, j, k, m; + int fill, vis, invis; + double x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy; + + for (i = 0; i < nobj; i++) { + p = objlist[i]; + ox = p->o_x; + oy = p->o_y; + if (p->o_count >= 1) + x1 = p->o_val[0]; + if (p->o_count >= 2) + y1 = p->o_val[1]; + m = p->o_mode; + fill = p->o_attr & FILLBIT; + invis = p->o_attr & INVIS; + vis = !invis; + switch (p->o_type) { + case TROFF: + troff(text[p->o_nt1].t_val); + break; + case BOX: + case BLOCK: + x0 = ox - x1 / 2; + y0 = oy - y1 / 2; + x1 = ox + x1 / 2; + y1 = oy + y1 / 2; + if (fill) { + move(x0, y0); + fillstart(p->o_fillval); + } + if (p->o_type == BLOCK) + ; /* nothing at all */ + else if (invis && !fill) + ; /* nothing at all */ + else if (p->o_attr & (DOTBIT|DASHBIT)) + dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval); + else + box(x0, y0, x1, y1); + if (fill) + fillend(vis, fill); + move(ox, oy); + dotext(p); /* if there are any text strings */ + if (ishor(m)) + move(isright(m) ? x1 : x0, oy); /* right side */ + else + move(ox, isdown(m) ? y0 : y1); /* bottom */ + break; + case BLOCKEND: + break; + case CIRCLE: + if (fill) + fillstart(p->o_fillval); + if (vis || fill) + circle(ox, oy, x1); + if (fill) + fillend(vis, fill); + move(ox, oy); + dotext(p); + if (ishor(m)) + move(ox + isright(m) ? x1 : -x1, oy); + else + move(ox, oy + isup(m) ? x1 : -x1); + break; + case ELLIPSE: + if (fill) + fillstart(p->o_fillval); + if (vis || fill) + ellipse(ox, oy, x1, y1); + if (fill) + fillend(vis, fill); + move(ox, oy); + dotext(p); + if (ishor(m)) + move(ox + isright(m) ? x1 : -x1, oy); + else + move(ox, oy - isdown(m) ? y1 : -y1); + break; + case ARC: + if (fill) { + move(ox, oy); + fillstart(p->o_fillval); + } + if (p->o_attr & HEAD1) + arrow(x1 - (y1 - oy), y1 + (x1 - ox), + x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead); + if (invis && !fill) + /* probably wrong when it's cw */ + move(x1, y1); + else + arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]); + if (p->o_attr & HEAD2) + arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox), + p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5], -p->o_val[5]/p->o_val[6]/2, p->o_nhead); + if (fill) + fillend(vis, fill); + if (p->o_attr & CW_ARC) + move(x1, y1); /* because drawn backwards */ + move(ox, oy); + dotext(p); + break; + case LINE: + case ARROW: + case SPLINE: + if (fill) { + move(ox, oy); + fillstart(p->o_fillval); + } + if (vis && p->o_attr & HEAD1) + arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); + if (invis && !fill) + move(x1, y1); + else if (p->o_type == SPLINE) + spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval); + else { + dx = ox; + dy = oy; + for (k=0, j=5; k < p->o_val[4]; k++, j += 2) { + ndx = dx + p->o_val[j]; + ndy = dy + p->o_val[j+1]; + if (p->o_attr & (DOTBIT|DASHBIT)) + dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval); + else + line(dx, dy, ndx, ndy); + dx = ndx; + dy = ndy; + } + } + if (vis && p->o_attr & HEAD2) { + dx = ox; + dy = oy; + for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) { + dx += p->o_val[j]; + dy += p->o_val[j+1]; + } + arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); + } + if (fill) + fillend(vis, fill); + move((ox + x1)/2, (oy + y1)/2); /* center */ + dotext(p); + break; + case MOVE: + move(ox, oy); + break; + case TEXT: + move(ox, oy); + if (vis) + dotext(p); + break; + } + } +} + +void dotline(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted line */ +{ + static double prevval = 0.05; /* 20 per inch by default */ + int i, numdots; + double a, b, dx, dy; + + if (ddval == 0) + ddval = prevval; + prevval = ddval; + /* don't save dot/dash value */ + dx = x1 - x0; + dy = y1 - y0; + if (ddtype & DOTBIT) { + numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5; + if (numdots > 0) + for (i = 0; i <= numdots; i++) { + a = (double) i / (double) numdots; + move(x0 + (a * dx), y0 + (a * dy)); + dot(); + } + } else if (ddtype & DASHBIT) { + double d, dashsize, spacesize; + d = sqrt(dx*dx + dy*dy); + if (d <= 2 * prevval) { + line(x0, y0, x1, y1); + return; + } + numdots = d / (2 * prevval) + 1; /* ceiling */ + dashsize = prevval; + spacesize = (d - numdots * dashsize) / (numdots - 1); + for (i = 0; i < numdots-1; i++) { + a = i * (dashsize + spacesize) / d; + b = a + dashsize / d; + line(x0 + (a*dx), y0 + (a*dy), x0 + (b*dx), y0 + (b*dy)); + a = b; + b = a + spacesize / d; + move(x0 + (a*dx), y0 + (a*dy)); + } + line(x0 + (b * dx), y0 + (b * dy), x1, y1); + } + prevval = 0.05; +} + +void dotbox(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted or dashed box */ +{ + dotline(x0, y0, x1, y0, ddtype, ddval); + dotline(x1, y0, x1, y1, ddtype, ddval); + dotline(x1, y1, x0, y1, ddtype, ddval); + dotline(x0, y1, x0, y0, ddtype, ddval); +} + +void dotext(obj *p) /* print text strings of p in proper vertical spacing */ +{ + int i, nhalf; + void label(char *, int, int); + + nhalf = p->o_nt2 - p->o_nt1 - 1; + for (i = p->o_nt1; i < p->o_nt2; i++) { + label(text[i].t_val, text[i].t_type, nhalf); + nhalf -= 2; + } +} blob - /dev/null blob + 879075c6854b3083ccc2f4f09e530bbc0151a8c5 (mode 644) --- /dev/null +++ src/cmd/pic/symtab.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include "pic.h" +#include "y.tab.h" + +YYSTYPE getvar(char *s) /* return value of variable s (usually pointer) */ +{ + struct symtab *p; + static YYSTYPE bug; + + p = lookup(s); + if (p == NULL) { + if (islower(s[0])) + ERROR "no such variable as %s", s WARNING; + else + ERROR "no such place as %s", s WARNING; + return(bug); + } + return(p->s_val); +} + +double getfval(char *s) /* return float value of variable s */ +{ + YYSTYPE y; + + y = getvar(s); + return y.f; +} + +void setfval(char *s, double f) /* set variable s to f */ +{ + struct symtab *p; + + if ((p = lookup(s)) != NULL) + p->s_val.f = f; +} + +struct symtab *makevar(char *s, int t, YYSTYPE v) /* make variable named s in table */ + /* assumes s is static or from tostring */ +{ + struct symtab *p; + + for (p = stack[nstack].p_symtab; p != NULL; p = p->s_next) + if (strcmp(s, p->s_name) == 0) + break; + if (p == NULL) { /* it's a new one */ + p = (struct symtab *) malloc(sizeof(struct symtab)); + if (p == NULL) + ERROR "out of symtab space with %s", s FATAL; + p->s_next = stack[nstack].p_symtab; + stack[nstack].p_symtab = p; /* stick it at front */ + } + p->s_name = s; + p->s_type = t; + p->s_val = v; + return(p); +} + +struct symtab *lookup(char *s) /* find s in symtab */ +{ + int i; + struct symtab *p; + + for (i = nstack; i >= 0; i--) /* look in each active symtab */ + for (p = stack[i].p_symtab; p != NULL; p = p->s_next) + if (strcmp(s, p->s_name) == 0) + return(p); + return(NULL); +} + +void freesymtab(struct symtab *p) /* free space used by symtab at p */ +{ + struct symtab *q; + + for ( ; p != NULL; p = q) { + q = p->s_next; + free(p->s_name); /* assumes done with tostring */ + free((char *)p); + } +} + +void freedef(char *s) /* free definition for string s */ +{ + struct symtab *p, *q, *op; + + for (p = op = q = stack[nstack].p_symtab; p != NULL; p = p->s_next) { + if (strcmp(s, p->s_name) == 0) { /* got it */ + if (p->s_type != DEFNAME) + break; + if (p == op) /* 1st elem */ + stack[nstack].p_symtab = p->s_next; + else + q->s_next = p->s_next; + free(p->s_name); + free(p->s_val.p); + free((char *)p); + return; + } + q = p; + } + /* ERROR "%s is not defined at this point", s WARNING; */ +} blob - /dev/null blob + 98dfbb57b2dc67bb234edd85c45296ab2ff1eaff (mode 644) --- /dev/null +++ src/cmd/pic/textgen.c @@ -0,0 +1,115 @@ +#include +#include "pic.h" +#include "y.tab.h" + +obj *textgen(void) +{ + int i, sub, nstr, at, with, hset, invis; + double xwith, ywith, h, w, x0, y0, x1, y1; + obj *p, *ppos; + static double prevh = 0; + static double prevw = 0; + Attr *ap; + + at = with = nstr = hset = invis = 0; + h = getfval("textht"); + w = getfval("textwid"); + for (i = 0; i < nattr; i++) { + ap = &attr[i]; + switch (ap->a_type) { + case HEIGHT: + h = ap->a_val.f; + hset++; + break; + case WIDTH: + w = ap->a_val.f; + break; + case WITH: + with = ap->a_val.i; + break; + case INVIS: + invis = INVIS; + break; + case AT: + ppos = ap->a_val.o; + curx = ppos->o_x; + cury = ppos->o_y; + at++; + break; + case TEXTATTR: + sub = ap->a_sub; + if (ap->a_val.p == NULL) /* an isolated modifier */ + text[ntext-1].t_type = sub; + else { + savetext(sub, ap->a_val.p); + nstr++; + } + break; + } + } + if (hset == 0) /* no explicit ht cmd */ + h *= nstr; + if (with) { + xwith = ywith = 0.0; + switch (with) { + case NORTH: ywith = -h / 2; break; + case SOUTH: ywith = h / 2; break; + case EAST: xwith = -w / 2; break; + case WEST: xwith = w / 2; break; + case NE: xwith = -w / 2; ywith = -h / 2; break; + case SE: xwith = -w / 2; ywith = h / 2; break; + case NW: xwith = w / 2; ywith = -h / 2; break; + case SW: xwith = w / 2; ywith = h / 2; break; + } + curx += xwith; + cury += ywith; + } + if (!at) { + if (isright(hvmode)) + curx += w / 2; + else if (isleft(hvmode)) + curx -= w / 2; + else if (isup(hvmode)) + cury += h / 2; + else + cury -= h / 2; + } + x0 = curx - w / 2; + y0 = cury - h / 2; + x1 = curx + w / 2; + y1 = cury + h / 2; + extreme(x0, y0); + extreme(x1, y1); + dprintf("Text h %g w %g at %g,%g\n", h, w, curx, cury); + p = makenode(TEXT, 2); + p->o_attr = invis; + p->o_val[0] = w; + p->o_val[1] = h; + if (isright(hvmode)) + curx = x1; + else if (isleft(hvmode)) + curx = x0; + else if (isup(hvmode)) + cury = y1; + else + cury = y0; + prevh = h; + prevw = w; + return(p); +} + +obj *troffgen(char *s) /* save away a string of troff commands */ +{ + savetext(CENTER, s); /* use the existing text mechanism */ + return makenode(TROFF, 0); +} + +void savetext(int t, char *s) /* record text elements for current object */ +{ + if (ntext >= ntextlist) + text = (Text *) grow((char *) text, "text", ntextlist += 200, sizeof(Text)); + text[ntext].t_type = t; + text[ntext].t_val = s; + dprintf("saving %d text %s at %d\n", t, s, ntext); + ntext++; +} blob - /dev/null blob + cdaf4a7ebd04cb8578d652d9e72c4f4dd80598fd (mode 644) --- /dev/null +++ src/cmd/tbl/mkfile @@ -0,0 +1,32 @@ +<$PLAN9/src/mkhdr + +TARG=tbl +OFILES=\ + t8.$O\ + t4.$O\ + t6.$O\ + tu.$O\ + t5.$O\ + t7.$O\ + tv.$O\ + tg.$O\ + t3.$O\ + tb.$O\ + tt.$O\ + t9.$O\ + t1.$O\ + tf.$O\ + tc.$O\ + ti.$O\ + tm.$O\ + t0.$O\ + tr.$O\ + te.$O\ + ts.$O\ + t2.$O\ + +HFILES=\ + t.h\ + +SHORTLIB=bio 9 +<$PLAN9/src/mkone blob - /dev/null blob + efcab373f705f3b8b96d840376df732599d7423b (mode 644) --- /dev/null +++ src/cmd/tbl/t.h @@ -0,0 +1,192 @@ +/* t..c : external declarations */ + +#include +#include +#include +# include + +# define MAXLIN 250 +# define MAXHEAD 44 +# define MAXCOL 30 + /* Do NOT make MAXCOL bigger with adjusting nregs[] in tr.c */ +# define MAXCHS 2000 +#define MAXLINLEN 300 +# define MAXRPT 100 +# define CLLEN 10 +# define SHORTLINE 4 +extern int nlin, ncol, iline, nclin, nslin; + +extern int (*style)[MAXHEAD]; +extern char (*font)[MAXHEAD][2]; +extern char (*csize)[MAXHEAD][4]; +extern char (*vsize)[MAXHEAD][4]; +extern char (*cll)[CLLEN]; +extern int (*flags)[MAXHEAD]; +# define ZEROW 001 +# define HALFUP 002 +# define CTOP 004 +# define CDOWN 010 +extern int stynum[]; +extern int qcol; +extern int *doubled, *acase, *topat; +extern int F1, F2; +extern int (*lefline)[MAXHEAD]; +extern int fullbot[]; +extern char *instead[]; +extern int expflg; +extern int ctrflg; +extern int evenflg; +extern int *evenup; +extern int boxflg; +extern int dboxflg; +extern int linsize; +extern int tab; +extern int pr1403; +extern int linsize, delim1, delim2; +extern int allflg; +extern int textflg; +extern int left1flg; +extern int rightl; +struct colstr {char *col, *rcol;}; +extern struct colstr *table[]; +extern char *cspace, *cstore; +extern char *exstore, *exlim, *exspace; +extern int *sep; +extern int *used, *lused, *rused; +extern int linestop[]; +extern char *leftover; +extern char *last, *ifile; +extern int texname; +extern int texct, texmax; +extern char texstr[]; +extern int linstart; + + +extern Biobuf *tabin, tabout; +# define CRIGHT 2 +# define CLEFT 0 +# define CMID 1 +# define S1 31 +# define S2 32 +# define S3 33 +# define TMP 38 +#define S9 39 +# define SF 35 +# define SL 34 +# define LSIZE 33 +# define SIND 37 +# define SVS 36 +/* this refers to the relative position of lines */ +# define LEFT 1 +# define RIGHT 2 +# define THRU 3 +# define TOP 1 +# define BOT 2 + +int tbl(int argc,char *argv[]); /*t1.c*/ +void setinp(int, char **); +int swapin(void); + +void tableput(void); /*t2.c*/ + +void getcomm(void); /*t3.c*/ +void backrest(char *); + +void getspec(void); /*t4.c*/ +void readspec(void); +int findcol(void); +void garray(int); +char *getcore(int, int); +void freearr(void); + +void gettbl(void); /*t5.c*/ +int nodata(int); +int oneh(int); +int vspand(int, int, int); +int vspen(char *); +void permute(void); + +void maktab(void); /*t6.c*/ +void wide(char *, char *, char *); +int filler(char *); + +void runout(void); /*t7.c*/ +void runtabs(int, int); +int ifline(char *); +void need(void); +void deftail(void); + +void putline(int, int); /*t8.c*/ +void puttext(char *, char *, char *); +void funnies(int, int); +void putfont(char *); +void putsize(char *); + +void yetmore(void); /*t9.c*/ +int domore(char *); + +void checkuse(void); /*tb.c*/ +int real(char *); +char *chspace(void); +int *alocv(int); +void release(void); + +void choochar(void); /*tc.c*/ +int point(char *); + +void error(char *); /*te.c*/ +char *gets1(char *, int); +void un1getc(int); +int get1char(void); + +void savefill(void); /*tf.c*/ +void rstofill(void); +void endoff(void); +void freearr(void); +void saveline(void); +void ifdivert(void); +void restline(void); +void cleanfc(void); + +int gettext(char *, int, int, char *, char *); /*tg.c*/ +void untext(void); + +int interv(int, int); /*ti.c*/ +int interh(int, int); +int up1(int); + +char *maknew(char *); /*tm.c*/ +int ineqn (char *, char *); + +char *reg(int, int); /*tr.c*/ + +int match (char *, char *); /*ts.c*/ +int prefix(char *, char *); +int letter (int); +int numb(char *); +int digit(int); +int max(int, int); +void tcopy (char *, char *); + +int ctype(int, int); /*tt.c*/ +int min(int, int); +int fspan(int, int); +int lspan(int, int); +int ctspan(int, int); +void tohcol(int); +int allh(int); +int thish(int, int); + +void makeline(int, int, int); /*tu.c*/ +void fullwide(int, int); +void drawline(int, int, int, int, int, int); +void getstop(void); +int left(int, int, int *); +int lefdata(int, int); +int next(int); +int prev(int); + +void drawvert(int, int, int, int); /*tv.c*/ +int midbar(int, int); +int midbcol(int, int); +int barent(char *); blob - /dev/null blob + 0c0895bdee83d9a322e069f0227a4785d872a3aa (mode 644) --- /dev/null +++ src/cmd/tbl/t0.c @@ -0,0 +1,49 @@ + /* t0.c: storage allocation */ +# +# include "t.h" +int expflg = 0; +int ctrflg = 0; +int boxflg = 0; +int dboxflg = 0; +int tab = '\t'; +int linsize; +int pr1403; +int delim1, delim2; +int evenflg; +int *evenup; +int F1 = 0; +int F2 = 0; +int allflg = 0; +char *leftover = 0; +int textflg = 0; +int left1flg = 0; +int rightl = 0; +char *cstore, *cspace; +char *last; +struct colstr *table[MAXLIN]; +int stynum[MAXLIN+1]; +int fullbot[MAXLIN]; +char *instead[MAXLIN]; +int linestop[MAXLIN]; +int (*style)[MAXHEAD]; +char (*font)[MAXHEAD][2]; +char (*csize)[MAXHEAD][4]; +char (*vsize)[MAXHEAD][4]; +int (*lefline)[MAXHEAD]; +char (*cll)[CLLEN]; +int (*flags)[MAXHEAD]; +int qcol; +int *doubled, *acase, *topat; +int nslin, nclin; +int *sep; +int *used, *lused, *rused; +int nlin, ncol; +int iline = 1; +char *ifile = "Input"; +int texname = 'a'; +int texct = 0; +char texstr[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYXZ0123456789"; +int linstart; +char *exstore, *exlim, *exspace; +Biobuf *tabin /*= stdin */; +Biobuf tabout /* = stdout */; blob - /dev/null blob + 1e6cbf1140ce358f8c5f800685cb984bff664afd (mode 644) --- /dev/null +++ src/cmd/tbl/t1.c @@ -0,0 +1,95 @@ +/* t1.c: main control and input switching */ +# +# include "t.h" + +# define MACROS "/usr/lib/tmac.s" +# define PYMACS "/usr/lib/tmac.m" + + +# define ever (;;) + +void +main(int argc, char *argv[]) +{ + exits(tbl(argc, argv)? "error" : 0); +} + + +int +tbl(int argc, char *argv[]) +{ + char line[5120]; + /*int x;*/ + /*x=malloc((char *)0); uncomment when allocation breaks*/ + Binit(&tabout, 1, OWRITE); + setinp(argc, argv); + while (gets1(line, sizeof(line))) { + Bprint(&tabout, "%s\n", line); + if (prefix(".TS", line)) + tableput(); + } + Bterm(tabin); + return(0); +} + + +int sargc; +char **sargv; + +void +setinp(int argc, char **argv) +{ + sargc = argc; + sargv = argv; + sargc--; + sargv++; + if (sargc > 0) + swapin(); + else { + tabin = (Biobuf*)getcore(sizeof(Biobuf), 1); + Binit(tabin, 0, OREAD); + } +} + + +int +swapin(void) +{ + char *name; + while (sargc > 0 && **sargv == '-') { + if (match("-ms", *sargv)) { + *sargv = MACROS; + break; + } + if (match("-mm", *sargv)) { + *sargv = PYMACS; + break; + } + if (match("-TX", *sargv)) + pr1403 = 1; + if (match("-", *sargv)) + break; + sargc--; + sargv++; + } + if (sargc <= 0) + return(0); + /* file closing is done by GCOS troff preprocessor */ + if(tabin) + Bterm(tabin); + ifile = *sargv; + name = ifile; + if (match(ifile, "-")) { + tabin = (Biobuf*)getcore(sizeof(Biobuf), 1); + Binit(tabin, 0, OREAD); + } else + tabin = Bopen(ifile, OREAD); + iline = 1; + Bprint(&tabout, ".ds f. %s\n", ifile); + Bprint(&tabout, ".lf %d %s\n", iline, name); + if (tabin == 0) + error("Can't open file"); + sargc--; + sargv++; + return(1); +} blob - /dev/null blob + 6d2d7414a77b3275a4860b7d23ffe7095454c534 (mode 644) --- /dev/null +++ src/cmd/tbl/t2.c @@ -0,0 +1,25 @@ +/* t2.c: subroutine sequencing for one table */ +# include "t.h" +void +tableput(void) +{ + saveline(); + savefill(); + ifdivert(); + cleanfc(); + getcomm(); + getspec(); + gettbl(); + getstop(); + checkuse(); + choochar(); + maktab(); + runout(); + release(); + rstofill(); + endoff(); + freearr(); + restline(); +} + + blob - /dev/null blob + a4dc9f9f536e615eef305576b3e84837c7549b90 (mode 644) --- /dev/null +++ src/cmd/tbl/t3.c @@ -0,0 +1,104 @@ +/* t3.c: interpret commands affecting whole table */ +# include "t.h" +struct optstr { + char *optnam; + int *optadd; +} options [] = { + "expand", &expflg, + "EXPAND", &expflg, + "center", &ctrflg, + "CENTER", &ctrflg, + "box", &boxflg, + "BOX", &boxflg, + "allbox", &allflg, + "ALLBOX", &allflg, + "doublebox", &dboxflg, + "DOUBLEBOX", &dboxflg, + "frame", &boxflg, + "FRAME", &boxflg, + "doubleframe", &dboxflg, + "DOUBLEFRAME", &dboxflg, + "tab", &tab, + "TAB", &tab, + "linesize", &linsize, + "LINESIZE", &linsize, + "delim", &delim1, + "DELIM", &delim1, + 0, 0}; + + +void +getcomm(void) +{ + char line[200], *cp, nb[25], *t; + struct optstr *lp; + int c, ci, found; + + for (lp = options; lp->optnam; lp++) + *(lp->optadd) = 0; + texname = texstr[texct=0]; + tab = '\t'; + Bprint(&tabout, ".nr %d \\n(.s\n", LSIZE); + gets1(line, sizeof(line)); + /* see if this is a command line */ + if (strchr(line, ';') == 0) { + backrest(line); + return; + } + for (cp = line; (c = *cp) != ';'; cp++) { + if (!letter(c)) + continue; + found = 0; + for (lp = options; lp->optadd; lp++) { + if (prefix(lp->optnam, cp)) { + *(lp->optadd) = 1; + cp += strlen(lp->optnam); + if (letter(*cp)) + error("Misspelled global option"); + while (*cp == ' ') + cp++; + t = nb; + if ( *cp == '(') + while ((ci = *++cp) != ')') + *t++ = ci; + else + cp--; + *t++ = 0; + *t = 0; + if (lp->optadd == &tab) { + if (nb[0]) + *(lp->optadd) = nb[0]; + } + if (lp->optadd == &linsize) + Bprint(&tabout, ".nr %d %s\n", LSIZE, nb); + if (lp->optadd == &delim1) { + delim1 = nb[0]; + delim2 = nb[1]; + } + found = 1; + break; + } + } + if (!found) + error("Illegal option"); + } + cp++; + backrest(cp); + return; +} + + +void +backrest(char *cp) +{ + char *s; + + for (s = cp; *s; s++) + ; + un1getc('\n'); + while (s > cp) + un1getc(*--s); + return; +} + + blob - /dev/null blob + 558d3ba3ab9246e78901081cf0b6159f69d12343 (mode 644) --- /dev/null +++ src/cmd/tbl/t4.c @@ -0,0 +1,405 @@ +/* t4.c: read table specification */ +# include "t.h" +int oncol; + +void +getspec(void) +{ + int icol, i; + + qcol = findcol() + 1;/* must allow one extra for line at right */ + garray(qcol); + sep[-1] = -1; + for (icol = 0; icol < qcol; icol++) { + sep[icol] = -1; + evenup[icol] = 0; + cll[icol][0] = 0; + for (i = 0; i < MAXHEAD; i++) { + csize[icol][i][0] = 0; + vsize[icol][i][0] = 0; + font[icol][i][0] = lefline[icol][i] = 0; + flags[icol][i] = 0; + style[icol][i] = 'l'; + } + } + for (i = 0; i < MAXHEAD; i++) + lefline[qcol][i] = 0; /* fixes sample55 looping */ + nclin = ncol = 0; + oncol = 0; + left1flg = rightl = 0; + readspec(); + Bprint(&tabout, ".rm"); + for (i = 0; i < ncol; i++) + Bprint(&tabout, " %2s", reg(i, CRIGHT)); + Bprint(&tabout, "\n"); +} + + +void +readspec(void) +{ + int icol, c, sawchar, stopc, i; + char sn[10], *snp, *temp; + + sawchar = icol = 0; + while (c = get1char()) { + switch (c) { + default: + if (c != tab) { + char buf[64]; + sprint(buf, "bad table specification character %c", c); + error(buf); + } + case ' ': /* note this is also case tab */ + continue; + case '\n': + if (sawchar == 0) + continue; + case ',': + case '.': /* end of table specification */ + ncol = max(ncol, icol); + if (lefline[ncol][nclin] > 0) { + ncol++; + rightl++; + }; + if (sawchar) + nclin++; + if (nclin >= MAXHEAD) + error("too many lines in specification"); + icol = 0; + if (ncol == 0 || nclin == 0) + error("no specification"); + if (c == '.') { + while ((c = get1char()) && c != '\n') + if (c != ' ' && c != '\t') + error("dot not last character on format line"); + /* fix up sep - default is 3 except at edge */ + for (icol = 0; icol < ncol; icol++) + if (sep[icol] < 0) + sep[icol] = icol + 1 < ncol ? 3 : 2; + if (oncol == 0) + oncol = ncol; + else if (oncol + 2 < ncol) + error("tried to widen table in T&, not allowed"); + return; + } + sawchar = 0; + continue; + case 'C': + case 'S': + case 'R': + case 'N': + case 'L': + case 'A': + c += ('a' - 'A'); + case '_': + if (c == '_') + c = '-'; + case '=': + case '-': + case '^': + case 'c': + case 's': + case 'n': + case 'r': + case 'l': + case 'a': + style[icol][nclin] = c; + if (c == 's' && icol <= 0) + error("first column can not be S-type"); + if (c == 's' && style[icol-1][nclin] == 'a') { + Bprint(&tabout, ".tm warning: can't span a-type cols, changed to l\n"); + style[icol-1][nclin] = 'l'; + } + if (c == 's' && style[icol-1][nclin] == 'n') { + Bprint(&tabout, ".tm warning: can't span n-type cols, changed to c\n"); + style[icol-1][nclin] = 'c'; + } + icol++; + if (c == '^' && nclin <= 0) + error("first row can not contain vertical span"); + if (icol > qcol) + error("too many columns in table"); + sawchar = 1; + continue; + case 'b': + case 'i': + c += 'A' - 'a'; + case 'B': + case 'I': + if (icol == 0) + continue; + snp = font[icol-1][nclin]; + snp[0] = (c == 'I' ? '2' : '3'); + snp[1] = 0; + continue; + case 't': + case 'T': + if (icol > 0) + flags[icol-1][nclin] |= CTOP; + continue; + case 'd': + case 'D': + if (icol > 0) + flags[icol-1][nclin] |= CDOWN; + continue; + case 'f': + case 'F': + if (icol == 0) + continue; + snp = font[icol-1][nclin]; + snp[0] = snp[1] = stopc = 0; + for (i = 0; i < 2; i++) { + c = get1char(); + if (i == 0 && c == '(') { + stopc = ')'; + c = get1char(); + } + if (c == 0) + break; + if (c == stopc) { + stopc = 0; + break; + } + if (stopc == 0) + if (c == ' ' || c == tab ) + break; + if (c == '\n' || c == '|') { + un1getc(c); + break; + } + snp[i] = c; + if (c >= '0' && c <= '9') + break; + } + if (stopc) + if (get1char() != stopc) + error("Nonterminated font name"); + continue; + case 'P': + case 'p': + if (icol <= 0) + continue; + temp = snp = csize[icol-1][nclin]; + while (c = get1char()) { + if (c == ' ' || c == tab || c == '\n') + break; + if (c == '-' || c == '+') + if (snp > temp) + break; + else + *snp++ = c; + else if (digit(c)) + *snp++ = c; + else + break; + if (snp - temp > 4) + error("point size too large"); + } + *snp = 0; + if (atoi(temp) > 36) + error("point size unreasonable"); + un1getc (c); + continue; + case 'V': + case 'v': + if (icol <= 0) + continue; + temp = snp = vsize[icol-1][nclin]; + while (c = get1char()) { + if (c == ' ' || c == tab || c == '\n') + break; + if (c == '-' || c == '+') + if (snp > temp) + break; + else + *snp++ = c; + else if (digit(c)) + *snp++ = c; + else + break; + if (snp - temp > 4) + error("vertical spacing value too large"); + } + *snp = 0; + un1getc(c); + continue; + case 'w': + case 'W': + snp = cll [icol-1]; + /* Dale Smith didn't like this check - possible to have two text blocks + of different widths now .... + if (*snp) + { + Bprint(&tabout, "Ignored second width specification"); + continue; + } + /* end commented out code ... */ + stopc = 0; + while (c = get1char()) { + if (snp == cll[icol-1] && c == '(') { + stopc = ')'; + continue; + } + if ( !stopc && (c > '9' || c < '0')) + break; + if (stopc && c == stopc) + break; + *snp++ = c; + } + *snp = 0; + if (snp - cll[icol-1] > CLLEN) + error ("column width too long"); + if (!stopc) + un1getc(c); + continue; + case 'e': + case 'E': + if (icol < 1) + continue; + evenup[icol-1] = 1; + evenflg = 1; + continue; + case 'z': + case 'Z': /* zero width-ignre width this item */ + if (icol < 1) + continue; + flags[icol-1][nclin] |= ZEROW; + continue; + case 'u': + case 'U': /* half line up */ + if (icol < 1) + continue; + flags[icol-1][nclin] |= HALFUP; + continue; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + sn[0] = c; + snp = sn + 1; + while (digit(*snp++ = c = get1char())) + ; + un1getc(c); + sep[icol-1] = max(sep[icol-1], numb(sn)); + continue; + case '|': + lefline[icol][nclin]++; + if (icol == 0) + left1flg = 1; + continue; + } + } + error("EOF reading table specification"); +} + + +int +findcol(void) +{ +# define FLNLIM 200 + /* this counts the number of columns and then puts the line back*/ + char *s, line[FLNLIM+2], *p; + int c, n = 0, inpar = 0; + + while ((c = get1char()) != 0 && c == ' ') + ; + if (c != '\n') + un1getc(c); + for (s = line; *s = c = get1char(); s++) { + if (c == ')') + inpar = 0; + if (inpar) + continue; + if (c == '\n' || c == 0 || c == '.' || c == ',') + break; + else if (c == '(') + inpar = 1; + else if (s >= line + FLNLIM) + error("too long spec line"); + } + for (p = line; p < s; p++) + switch (*p) { + case 'l': + case 'r': + case 'c': + case 'n': + case 'a': + case 's': + case 'L': + case 'R': + case 'C': + case 'N': + case 'A': + case 'S': + case '-': + case '=': + case '_': + n++; + } + while (p >= line) + un1getc(*p--); + return(n); +} + + +void +garray(int qcol) +{ + style = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int)); + evenup = (int *) getcore(qcol, sizeof(int)); + lefline = (int (*)[]) getcore(MAXHEAD * (qcol + 1), sizeof (int)); /*+1 for sample55 loop - others may need it too*/ + font = (char (*)[][2]) getcore(MAXHEAD * qcol, 2); + csize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4); + vsize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4); + flags = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int)); + cll = (char (*)[])getcore(qcol, CLLEN); + sep = (int *) getcore(qcol + 1, sizeof(int)); + sep++; /* sep[-1] must be legal */ + used = (int *) getcore(qcol + 1, sizeof(int)); + lused = (int *) getcore(qcol + 1, sizeof(int)); + rused = (int *) getcore(qcol + 1, sizeof(int)); + doubled = (int *) getcore(qcol + 1, sizeof(int)); + acase = (int *) getcore(qcol + 1, sizeof(int)); + topat = (int *) getcore(qcol + 1, sizeof(int)); +} + + +char * +getcore(int a, int b) +{ + char *x; + x = calloc(a, b); + if (x == 0) + error("Couldn't get memory"); + return(x); +} + + +void +freearr(void) +{ + free(style); + free(evenup); + free(lefline); + free(flags); + free(font); + free(csize); + free(vsize); + free(cll); + free(--sep); /* netnews says this should be --sep because incremented earlier! */ + free(used); + free(lused); + free(rused); + free(doubled); + free(acase); + free(topat); +} + + blob - /dev/null blob + 8b7a65d8ffc9083baaee45d75d95aa3f83b053d3 (mode 644) --- /dev/null +++ src/cmd/tbl/t5.c @@ -0,0 +1,198 @@ +/* t5.c: read data for table */ +# include "t.h" + +void +gettbl(void) +{ + int icol, ch; + + cstore = cspace = chspace(); + textflg = 0; + for (nlin = nslin = 0; gets1(cstore, MAXCHS - (cstore - cspace)); nlin++) { + stynum[nlin] = nslin; + if (prefix(".TE", cstore)) { + leftover = 0; + break; + } + if (prefix(".TC", cstore) || prefix(".T&", cstore)) { + readspec(); + nslin++; + } + if (nlin >= MAXLIN) { + leftover = cstore; + break; + } + fullbot[nlin] = 0; + if (cstore[0] == '.' && !isdigit(cstore[1])) { + instead[nlin] = cstore; + while (*cstore++) + ; + continue; + } else + instead[nlin] = 0; + if (nodata(nlin)) { + if (ch = oneh(nlin)) + fullbot[nlin] = ch; + table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0])); + for (icol = 0; icol < ncol; icol++) { + table[nlin][icol].rcol = ""; + table[nlin][icol].col = ""; + } + nlin++; + nslin++; + fullbot[nlin] = 0; + instead[nlin] = (char *) 0; + } + table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0])); + if (cstore[1] == 0) + switch (cstore[0]) { + case '_': + fullbot[nlin] = '-'; + continue; + case '=': + fullbot[nlin] = '='; + continue; + } + stynum[nlin] = nslin; + nslin = min(nslin + 1, nclin - 1); + for (icol = 0; icol < ncol; icol++) { + table[nlin][icol].col = cstore; + table[nlin][icol].rcol = 0; + ch = 1; + if (match(cstore, "T{")) { /* text follows */ + table[nlin][icol].col = + (char *)gettext(cstore, nlin, icol, + font[icol][stynum[nlin]], + csize[icol][stynum[nlin]]); + } else + { + for (; (ch = *cstore) != '\0' && ch != tab; cstore++) + ; + *cstore++ = '\0'; + switch (ctype(nlin, icol)) /* numerical or alpha, subcol */ { + case 'n': + table[nlin][icol].rcol = maknew(table[nlin][icol].col); + break; + case 'a': + table[nlin][icol].rcol = table[nlin][icol].col; + table[nlin][icol].col = ""; + break; + } + } + while (ctype(nlin, icol + 1) == 's') /* spanning */ + table[nlin][++icol].col = ""; + if (ch == '\0') + break; + } + while (++icol < ncol + 2) { + table[nlin][icol].col = ""; + table [nlin][icol].rcol = 0; + } + while (*cstore != '\0') + cstore++; + if (cstore - cspace + MAXLINLEN > MAXCHS) + cstore = cspace = chspace(); + } + last = cstore; + permute(); + if (textflg) + untext(); + return; +} + + +int +nodata(int il) +{ + int c; + + for (c = 0; c < ncol; c++) { + switch (ctype(il, c)) { + case 'c': + case 'n': + case 'r': + case 'l': + case 's': + case 'a': + return(0); + } + } + return(1); +} + + +int +oneh(int lin) +{ + int k, icol; + + k = ctype(lin, 0); + for (icol = 1; icol < ncol; icol++) { + if (k != ctype(lin, icol)) + return(0); + } + return(k); +} + + +# define SPAN "\\^" + +void +permute(void) +{ + int irow, jcol, is; + char *start, *strig; + + for (jcol = 0; jcol < ncol; jcol++) { + for (irow = 1; irow < nlin; irow++) { + if (vspand(irow, jcol, 0)) { + is = prev(irow); + if (is < 0) + error("Vertical spanning in first row not allowed"); + start = table[is][jcol].col; + strig = table[is][jcol].rcol; + while (irow < nlin && vspand(irow, jcol, 0)) + irow++; + table[--irow][jcol].col = start; + table[irow][jcol].rcol = strig; + while (is < irow) { + table[is][jcol].rcol = 0; + table[is][jcol].col = SPAN; + is = next(is); + } + } + } + } +} + + +int +vspand(int ir, int ij, int ifform) +{ + if (ir < 0) + return(0); + if (ir >= nlin) + return(0); + if (instead[ir]) + return(0); + if (ifform == 0 && ctype(ir, ij) == '^') + return(1); + if (table[ir][ij].rcol != 0) + return(0); + if (fullbot[ir]) + return(0); + return(vspen(table[ir][ij].col)); +} + + +int +vspen(char *s) +{ + if (s == 0) + return(0); + if (!point(s)) + return(0); + return(match(s, SPAN)); +} + + blob - /dev/null blob + a78368fcc564fb2cc8e3b79b3afc1fc60a19f311 (mode 644) --- /dev/null +++ src/cmd/tbl/t6.c @@ -0,0 +1,223 @@ +/* t6.c: compute tab stops */ +# define tx(a) (a>0 && a<128) +# include "t.h" +# define FN(i,c) font[c][stynum[i]] +# define SZ(i,c) csize[c][stynum[i]] +# define TMP1 S1 +# define TMP2 S2 + +void +maktab(void) /* define the tab stops of the table */ +{ + int icol, ilin, tsep, k, ik, vforml, il, text; + char *s; + + for (icol = 0; icol < ncol; icol++) { + doubled[icol] = acase[icol] = 0; + Bprint(&tabout, ".nr %2s 0\n", reg(icol, CRIGHT)); + for (text = 0; text < 2; text++) { + if (text) + Bprint(&tabout, ".%2s\n.rm %2s\n", reg(icol, CRIGHT), + reg(icol, CRIGHT)); + for (ilin = 0; ilin < nlin; ilin++) { + if (instead[ilin] || fullbot[ilin]) + continue; + vforml = ilin; + for (il = prev(ilin); il >= 0 && vspen(table[il][icol].col); il = prev(il)) + vforml = il; + if (fspan(vforml, icol)) + continue; + if (filler(table[ilin][icol].col)) + continue; + if ((flags[icol][stynum[ilin]] & ZEROW) != 0) + continue; + switch (ctype(vforml, icol)) { + case 'a': + acase[icol] = 1; + s = table[ilin][icol].col; + if ((int)s > 0 && (int)s < 128 && text) { + if (doubled[icol] == 0) + Bprint(&tabout, ".nr %d 0\n.nr %d 0\n", + S1, S2); + doubled[icol] = 1; + Bprint(&tabout, ".if \\n(%c->\\n(%d .nr %d \\n(%c-\n", + (int)s, S2, S2, (int)s); + } + case 'n': + if (table[ilin][icol].rcol != 0) { + if (doubled[icol] == 0 && text == 0) + Bprint(&tabout, ".nr %d 0\n.nr %d 0\n", + S1, S2); + doubled[icol] = 1; + if (real(s = table[ilin][icol].col) && !vspen(s)) { + if (tx((int)s) != text) + continue; + Bprint(&tabout, ".nr %d ", TMP); + wide(s, FN(vforml, icol), SZ(vforml, icol)); + Bprint(&tabout, "\n"); + Bprint(&tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n", + S1, TMP, S1, TMP); + } + if (text == 0 && real(s = table[ilin][icol].rcol) && !vspen(s) && !barent(s)) { + Bprint(&tabout, ".nr %d \\w%c%s%c\n", + TMP, F1, s, F1); + Bprint(&tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n", S2, TMP, S2, + TMP); + } + continue; + } + case 'r': + case 'c': + case 'l': + if (real(s = table[ilin][icol].col) && !vspen(s)) { + if (tx((int)s) != text) + continue; + Bprint(&tabout, ".nr %d ", TMP); + wide(s, FN(vforml, icol), SZ(vforml, icol)); + Bprint(&tabout, "\n"); + Bprint(&tabout, ".if \\n(%2s<\\n(%d .nr %2s \\n(%d\n", + reg(icol, CRIGHT), TMP, reg(icol, CRIGHT), TMP); + } + } + } + } + if (acase[icol]) { + Bprint(&tabout, ".if \\n(%d>=\\n(%2s .nr %2s \\n(%du+2n\n", + S2, reg(icol, CRIGHT), reg(icol, CRIGHT), S2); + } + if (doubled[icol]) { + Bprint(&tabout, ".nr %2s \\n(%d\n", reg(icol, CMID), S1); + Bprint(&tabout, ".nr %d \\n(%2s+\\n(%d\n", TMP, reg(icol, CMID), S2); + Bprint(&tabout, ".if \\n(%d>\\n(%2s .nr %2s \\n(%d\n", TMP, + reg(icol, CRIGHT), reg(icol, CRIGHT), TMP); + Bprint(&tabout, ".if \\n(%d<\\n(%2s .nr %2s +(\\n(%2s-\\n(%d)/2\n", + TMP, reg(icol, CRIGHT), reg(icol, CMID), reg(icol, CRIGHT), TMP); + } + if (cll[icol][0]) { + Bprint(&tabout, ".nr %d %sn\n", TMP, cll[icol]); + Bprint(&tabout, ".if \\n(%2s<\\n(%d .nr %2s \\n(%d\n", + reg(icol, CRIGHT), TMP, reg(icol, CRIGHT), TMP); + } + for (ilin = 0; ilin < nlin; ilin++) + if (k = lspan(ilin, icol)) { + s = table[ilin][icol-k].col; + if (!real(s) || barent(s) || vspen(s) ) + continue; + Bprint(&tabout, ".nr %d ", TMP); + wide(table[ilin][icol-k].col, FN(ilin, icol - k), SZ(ilin, icol - k)); + for (ik = k; ik >= 0; ik--) { + Bprint(&tabout, "-\\n(%2s", reg(icol - ik, CRIGHT)); + if (!expflg && ik > 0) + Bprint(&tabout, "-%dn", sep[icol-ik]); + } + Bprint(&tabout, "\n"); + Bprint(&tabout, ".if \\n(%d>0 .nr %d \\n(%d/%d\n", TMP, + TMP, TMP, k); + Bprint(&tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP); + for (ik = 1; ik <= k; ik++) { + if (doubled[icol-k+ik]) + Bprint(&tabout, ".nr %2s +\\n(%d/2\n", + reg(icol - k + ik, CMID), TMP); + Bprint(&tabout, ".nr %2s +\\n(%d\n", + reg(icol - k + ik, CRIGHT), TMP); + } + } + } + if (textflg) + untext(); + /* if even requested, make all columns widest width */ + if (evenflg) { + Bprint(&tabout, ".nr %d 0\n", TMP); + for (icol = 0; icol < ncol; icol++) { + if (evenup[icol] == 0) + continue; + Bprint(&tabout, ".if \\n(%2s>\\n(%d .nr %d \\n(%2s\n", + reg(icol, CRIGHT), TMP, TMP, reg(icol, CRIGHT)); + } + for (icol = 0; icol < ncol; icol++) { + if (evenup[icol] == 0) + /* if column not evened just retain old interval */ + continue; + if (doubled[icol]) + Bprint(&tabout, ".nr %2s (100*\\n(%2s/\\n(%2s)*\\n(%d/100\n", + reg(icol, CMID), reg(icol, CMID), reg(icol, CRIGHT), TMP); + /* that nonsense with the 100's and parens tries + to avoid overflow while proportionally shifting + the middle of the number */ + Bprint(&tabout, ".nr %2s \\n(%d\n", reg(icol, CRIGHT), TMP); + } + } + /* now adjust for total table width */ + for (tsep = icol = 0; icol < ncol; icol++) + tsep += sep[icol]; + if (expflg) { + Bprint(&tabout, ".nr %d 0", TMP); + for (icol = 0; icol < ncol; icol++) + Bprint(&tabout, "+\\n(%2s", reg(icol, CRIGHT)); + Bprint(&tabout, "\n"); + Bprint(&tabout, ".nr %d \\n(.l-\\n(%d\n", TMP, TMP); + if (boxflg || dboxflg || allflg) + /* tsep += 1; */ {} + else + tsep -= sep[ncol-1]; + Bprint(&tabout, ".nr %d \\n(%d/%d\n", TMP, TMP, tsep); + Bprint(&tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP); + } else + Bprint(&tabout, ".nr %d 1n\n", TMP); + Bprint(&tabout, ".nr %2s 0\n", reg(-1, CRIGHT)); + tsep = (boxflg || allflg || dboxflg || left1flg) ? 2 : 0; + if (sep[-1] >= 0) + tsep = sep[-1]; + for (icol = 0; icol < ncol; icol++) { + Bprint(&tabout, ".nr %2s \\n(%2s+((%d*\\n(%d)/2)\n", reg(icol, CLEFT), + reg(icol - 1, CRIGHT), tsep, TMP); + Bprint(&tabout, ".nr %2s +\\n(%2s\n", reg(icol, CRIGHT), reg(icol, CLEFT)); + if (doubled[icol]) { + /* the next line is last-ditch effort to avoid zero field width */ + /*Bprint(&tabout, ".if \\n(%2s=0 .nr %2s 1\n",reg(icol,CMID), reg(icol,CMID));*/ + Bprint(&tabout, ".nr %2s +\\n(%2s\n", reg(icol, CMID), + reg(icol, CLEFT)); + /* Bprint(&tabout, ".if n .if \\n(%s%%24>0 .nr %s +12u\n",reg(icol,CMID), reg(icol,CMID)); */ + } + tsep = sep[icol] * 2; + } + if (rightl) + Bprint(&tabout, ".nr %s (\\n(%s+\\n(%s)/2\n", reg(ncol - 1, CRIGHT), + reg(ncol - 1, CLEFT), reg(ncol - 2, CRIGHT)); + Bprint(&tabout, ".nr TW \\n(%2s\n", reg(ncol - 1, CRIGHT)); + tsep = sep[ncol-1]; + if (boxflg || allflg || dboxflg) + Bprint(&tabout, ".nr TW +((%d*\\n(%d)/2)\n", tsep, TMP); + Bprint(&tabout, + ".if t .if (\\n(TW+\\n(.o)>7.65i .tm Table at line %d file %s is too wide - \\n(TW units\n", iline - 1, ifile); + return; +} + + +void +wide(char *s, char *fn, char *size) +{ + if (point(s)) { + Bprint(&tabout, "\\w%c", F1); + if (*fn > 0) + putfont(fn); + if (*size) + putsize(size); + Bprint(&tabout, "%s", s); + if (*fn > 0) + putfont("P"); + if (*size) + putsize("0"); + Bprint(&tabout, "%c", F1); + } else + Bprint(&tabout, "\\n(%c-", (int)s); +} + + +int +filler(char *s) +{ + return (point(s) && s[0] == '\\' && s[1] == 'R'); +} + + blob - /dev/null blob + 2fa9de53bbfcc30b7b04135f7d22bf590983795f (mode 644) --- /dev/null +++ src/cmd/tbl/t7.c @@ -0,0 +1,150 @@ +/* t7.c: control to write table entries */ +# include "t.h" +# define realsplit ((ct=='a'||ct=='n') && table[ldata][c].rcol) + +void +runout(void) +{ + int i; + + if (boxflg || allflg || dboxflg) + need(); + if (ctrflg) { + Bprint(&tabout, ".nr #I \\n(.i\n"); + Bprint(&tabout, ".in +(\\n(.lu-\\n(TWu-\\n(.iu)/2u\n"); + } + Bprint(&tabout, ".fc %c %c\n", F1, F2); + Bprint(&tabout, ".nr #T 0-1\n"); + deftail(); + for (i = 0; i < nlin; i++) + putline(i, i); + if (leftover) + yetmore(); + Bprint(&tabout, ".fc\n"); + Bprint(&tabout, ".nr T. 1\n"); + Bprint(&tabout, ".T# 1\n"); + if (ctrflg) + Bprint(&tabout, ".in \\n(#Iu\n"); +} + + +void +runtabs(int lform, int ldata) +{ + int c, ct, vforml, lf; + + Bprint(&tabout, ".ta "); + for (c = 0; c < ncol; c++) { + vforml = lform; + for (lf = prev(lform); lf >= 0 && vspen(table[lf][c].col); lf = prev(lf)) + vforml = lf; + if (fspan(vforml, c)) + continue; + switch (ct = ctype(vforml, c)) { + case 'n': + case 'a': + if (table[ldata][c].rcol) + if (lused[c]) /*Zero field width*/ + Bprint(&tabout, "\\n(%2su ", reg(c, CMID)); + case 'c': + case 'l': + case 'r': + if (realsplit ? rused[c] : (used[c] + lused[c])) + Bprint(&tabout, "\\n(%2su ", reg(c, CRIGHT)); + continue; + case 's': + if (lspan(lform, c)) + Bprint(&tabout, "\\n(%2su ", reg(c, CRIGHT)); + continue; + } + } + Bprint(&tabout, "\n"); +} + + +int +ifline(char *s) +{ + if (!point(s)) + return(0); + if (s[0] == '\\') + s++; + if (s[1] ) + return(0); + if (s[0] == '_') + return('-'); + if (s[0] == '=') + return('='); + return(0); +} + + +void +need(void) +{ + int texlin, horlin, i; + + for (texlin = horlin = i = 0; i < nlin; i++) { + if (fullbot[i] != 0) + horlin++; + else if (instead[i] != 0) + continue; + else + texlin++; + } + Bprint(&tabout, ".ne %dv+%dp\n", texlin, 2 * horlin); +} + + +void +deftail(void) +{ + int i, c, lf, lwid; + + for (i = 0; i < MAXHEAD; i++) + if (linestop[i]) + Bprint(&tabout, ".nr #%c 0-1\n", linestop[i] + 'a' - 1); + Bprint(&tabout, ".nr #a 0-1\n"); + Bprint(&tabout, ".eo\n"); + Bprint(&tabout, ".de T#\n"); + Bprint(&tabout, ".nr 35 1m\n"); + Bprint(&tabout, ".ds #d .d\n"); + Bprint(&tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n"); + Bprint(&tabout, ".mk ##\n"); + Bprint(&tabout, ".nr ## -1v\n"); + Bprint(&tabout, ".ls 1\n"); + for (i = 0; i < MAXHEAD; i++) + if (linestop[i]) + Bprint(&tabout, ".if \\n(#T>=0 .nr #%c \\n(#T\n", + linestop[i] + 'a' - 1); + if (boxflg || allflg || dboxflg) /* bottom of table line */ + if (fullbot[nlin-1] == 0) { + if (!pr1403) + Bprint(&tabout, ".if \\n(T. .vs \\n(.vu-\\n(.sp\n"); + Bprint(&tabout, ".if \\n(T. "); + drawline(nlin, 0, ncol, dboxflg ? '=' : '-', 1, 0); + Bprint(&tabout, "\n.if \\n(T. .vs\n"); + /* T. is really an argument to a macro but because of + eqn we don't dare pass it as an argument and reference by $1 */ + } + for (c = 0; c < ncol; c++) { + if ((lf = left(nlin - 1, c, &lwid)) >= 0) { + Bprint(&tabout, ".if \\n(#%c>=0 .sp -1\n", linestop[lf] + 'a' - 1); + Bprint(&tabout, ".if \\n(#%c>=0 ", linestop[lf] + 'a' - 1); + tohcol(c); + drawvert(lf, nlin - 1, c, lwid); + Bprint(&tabout, "\\h'|\\n(TWu'\n"); + } + } + if (boxflg || allflg || dboxflg) /* right hand line */ { + Bprint(&tabout, ".if \\n(#a>=0 .sp -1\n"); + Bprint(&tabout, ".if \\n(#a>=0 \\h'|\\n(TWu'"); + drawvert (0, nlin - 1, ncol, dboxflg ? 2 : 1); + Bprint(&tabout, "\n"); + } + Bprint(&tabout, ".ls\n"); + Bprint(&tabout, "..\n"); + Bprint(&tabout, ".ec\n"); +} + + blob - /dev/null blob + 92277e2a8c4453ba7654c789acba4176f76a2328 (mode 644) --- /dev/null +++ src/cmd/tbl/t8.c @@ -0,0 +1,367 @@ +/* t8.c: write out one line of output table */ +# include "t.h" +# define realsplit ((ct=='a'||ct=='n') && table[nl][c].rcol) +int watchout; +int once; + +void +putline(int i, int nl) + /* i is line number for deciding format */ + /* nl is line number for finding data usually identical */ +{ + int c, lf, ct, form, lwid, vspf, ip, cmidx, exvspen, vforml; + int vct, chfont, uphalf; + char *s, *size, *fn, *rct; + + cmidx = watchout = vspf = exvspen = 0; + if (i == 0) + once = 0; + if (i == 0 && ( allflg || boxflg || dboxflg)) + fullwide(0, dboxflg ? '=' : '-'); + if (instead[nl] == 0 && fullbot[nl] == 0) + for (c = 0; c < ncol; c++) { + s = table[nl][c].col; + if (s == 0) + continue; + if (vspen(s)) { + for (ip = nl; ip < nlin; ip = next(ip)) + if (!vspen(s = table[ip][c].col)) + break; + if ((int)s > 0 && (int)s < 128) + Bprint(&tabout, ".ne \\n(%c|u+\\n(.Vu\n", (int)s); + continue; + } + if (point(s)) + continue; + Bprint(&tabout, ".ne \\n(%c|u+\\n(.Vu\n", (int)s); + watchout = 1; + } + if (linestop[nl]) + Bprint(&tabout, ".mk #%c\n", linestop[nl] + 'a' - 1); + lf = prev(nl); + if (instead[nl]) { + Bprint(&tabout, "%s\n", instead[nl]); + return; + } + if (fullbot[nl]) { + switch (ct = fullbot[nl]) { + case '=': + case '-': + fullwide(nl, ct); + } + return; + } + for (c = 0; c < ncol; c++) { + if (instead[nl] == 0 && fullbot[nl] == 0) + if (vspen(table[nl][c].col)) + vspf = 1; + if (lf >= 0) + if (vspen(table[lf][c].col)) + vspf = 1; + } + if (vspf) { + Bprint(&tabout, ".nr #^ \\n(\\*(#du\n"); + Bprint(&tabout, ".nr #- \\n(#^\n"); /* current line position relative to bottom */ + } + vspf = 0; + chfont = 0; + for (c = 0; c < ncol; c++) { + s = table[nl][c].col; + if (s == 0) + continue; + chfont |= (int)(font[c][stynum[nl]]); + if (point(s) ) + continue; + lf = prev(nl); + if (lf >= 0 && vspen(table[lf][c].col)) + Bprint(&tabout, + ".if (\\n(%c|+\\n(^%c-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(^%c-\\n(#--1v)\n", + (int)s, 'a' + c, (int)s, 'a' + c); + else + Bprint(&tabout, + ".if (\\n(%c|+\\n(#^-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(#^-\\n(#--1v)\n", + (int)s, (int)s); + } + if (allflg && once > 0 ) + fullwide(i, '-'); + once = 1; + runtabs(i, nl); + if (allh(i) && !pr1403) { + Bprint(&tabout, ".nr %d \\n(.v\n", SVS); + Bprint(&tabout, ".vs \\n(.vu-\\n(.sp\n"); + Bprint(&tabout, ".nr 35 \\n(.vu\n"); + } else + Bprint(&tabout, ".nr 35 1m\n"); + if (chfont) + Bprint(&tabout, ".nr %2d \\n(.f\n", S1); + Bprint(&tabout, "\\&"); + vct = 0; + for (c = 0; c < ncol; c++) { + uphalf = 0; + if (watchout == 0 && i + 1 < nlin && (lf = left(i, c, &lwid)) >= 0) { + tohcol(c); + drawvert(lf, i, c, lwid); + vct += 2; + } + if (rightl && c + 1 == ncol) + continue; + vforml = i; + for (lf = prev(nl); lf >= 0 && vspen(table[lf][c].col); lf = prev(lf)) + vforml = lf; + form = ctype(vforml, c); + if (form != 's') { + rct = reg(c, CLEFT); + if (form == 'a') + rct = reg(c, CMID); + if (form == 'n' && table[nl][c].rcol && lused[c] == 0) + rct = reg(c, CMID); + Bprint(&tabout, "\\h'|\\n(%2su'", rct); + } + s = table[nl][c].col; + fn = font[c][stynum[vforml]]; + size = csize[c][stynum[vforml]]; + if (*size == 0) + size = 0; + if ((flags[c][stynum[nl]] & HALFUP) != 0 && pr1403 == 0) + uphalf = 1; + switch (ct = ctype(vforml, c)) { + case 'n': + case 'a': + if (table[nl][c].rcol) { + if (lused[c]) /*Zero field width*/ { + ip = prev(nl); + if (ip >= 0) + if (vspen(table[ip][c].col)) { + if (exvspen == 0) { + Bprint(&tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c + 'a'); + if (cmidx) +/* code folded from here */ + Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a'); +/* unfolding */ + vct++; + if (pr1403) /* must round to whole lines */ +/* code folded from here */ + Bprint(&tabout, "/1v*1v"); +/* unfolding */ + Bprint(&tabout, "'"); + exvspen = 1; + } + } + Bprint(&tabout, "%c%c", F1, F2); + if (uphalf) + Bprint(&tabout, "\\u"); + puttext(s, fn, size); + if (uphalf) + Bprint(&tabout, "\\d"); + Bprint(&tabout, "%c", F1); + } + s = table[nl][c].rcol; + form = 1; + break; + } + case 'c': + form = 3; + break; + case 'r': + form = 2; + break; + case 'l': + form = 1; + break; + case '-': + case '=': + if (real(table[nl][c].col)) + fprint(2, "%s: line %d: Data ignored on table line %d\n", ifile, iline - 1, i + 1); + makeline(i, c, ct); + continue; + default: + continue; + } + if (realsplit ? rused[c] : used[c]) /*Zero field width*/ { + /* form: 1 left, 2 right, 3 center adjust */ + if (ifline(s)) { + makeline(i, c, ifline(s)); + continue; + } + if (filler(s)) { + Bprint(&tabout, "\\l'|\\n(%2su\\&%s'", reg(c, CRIGHT), s + 2); + continue; + } + ip = prev(nl); + cmidx = (flags[c][stynum[nl]] & (CTOP | CDOWN)) == 0; + if (ip >= 0) + if (vspen(table[ip][c].col)) { + if (exvspen == 0) { + Bprint(&tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c + 'a'); + if (cmidx) + Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a'); + vct++; + if (pr1403) /* round to whole lines */ + Bprint(&tabout, "/1v*1v"); + Bprint(&tabout, "'"); + } + } + Bprint(&tabout, "%c", F1); + if (form != 1) + Bprint(&tabout, "%c", F2); + if (vspen(s)) + vspf = 1; + else + { + if (uphalf) + Bprint(&tabout, "\\u"); + puttext(s, fn, size); + if (uphalf) + Bprint(&tabout, "\\d"); + } + if (form != 2) + Bprint(&tabout, "%c", F2); + Bprint(&tabout, "%c", F1); + } + ip = prev(nl); + if (ip >= 0) + if (vspen(table[ip][c].col)) { + exvspen = (c + 1 < ncol) && vspen(table[ip][c+1].col) && + (topat[c] == topat[c+1]) && + (cmidx == (flags[c+1] [stynum[nl]] & (CTOP | CDOWN) == 0)) + && (left(i, c + 1, &lwid) < 0); + if (exvspen == 0) { + Bprint(&tabout, "\\v'(\\n(\\*(#du-\\n(^%cu", c + 'a'); + if (cmidx) + Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a'); + vct++; + if (pr1403) /* round to whole lines */ + Bprint(&tabout, "/1v*1v"); + Bprint(&tabout, "'"); + } + } + else + exvspen = 0; + /* if lines need to be split for gcos here is the place for a backslash */ + if (vct > 7 && c < ncol) { + Bprint(&tabout, "\n.sp-1\n\\&"); + vct = 0; + } + } + Bprint(&tabout, "\n"); + if (allh(i) && !pr1403) + Bprint(&tabout, ".vs \\n(%du\n", SVS); + if (watchout) + funnies(i, nl); + if (vspf) { + for (c = 0; c < ncol; c++) + if (vspen(table[nl][c].col) && (nl == 0 || (lf = prev(nl)) < 0 || + !vspen(table[lf][c].col))) { + Bprint(&tabout, ".nr ^%c \\n(#^u\n", 'a' + c); + topat[c] = nl; + } + } +} + + +void +puttext(char *s, char *fn, char *size) +{ + if (point(s)) { + putfont(fn); + putsize(size); + Bprint(&tabout, "%s", s); + if (*fn > 0) + Bprint(&tabout, "\\f\\n(%2d", S1); + if (size != 0) + putsize("0"); + } +} + + +void +funnies(int stl, int lin) +{ + /* write out funny diverted things */ + int c, s, pl, lwid, dv, lf, ct; + char *fn, *ss; + + Bprint(&tabout, ".mk ##\n"); /* rmember current vertical position */ + Bprint(&tabout, ".nr %d \\n(##\n", S1); /* bottom position */ + for (c = 0; c < ncol; c++) { + ss = table[lin][c].col; + if (point(ss)) + continue; + if (ss == 0) + continue; + s = (int)ss; + Bprint(&tabout, ".sp |\\n(##u-1v\n"); + Bprint(&tabout, ".nr %d ", SIND); + ct = 0; + for (pl = stl; pl >= 0 && !isalpha(ct = ctype(pl, c)); pl = prev(pl)) + ; + switch (ct) { + case 'n': + case 'c': + Bprint(&tabout, "(\\n(%2su+\\n(%2su-\\n(%c-u)/2u\n", reg(c, CLEFT), + reg(c - 1 + ctspan(lin, c), CRIGHT), + s); + break; + case 'l': + Bprint(&tabout, "\\n(%2su\n", reg(c, CLEFT)); + break; + case 'a': + Bprint(&tabout, "\\n(%2su\n", reg(c, CMID)); + break; + case 'r': + Bprint(&tabout, "\\n(%2su-\\n(%c-u\n", reg(c, CRIGHT), s); + break; + } + Bprint(&tabout, ".in +\\n(%du\n", SIND); + fn = font[c][stynum[stl]]; + putfont(fn); + pl = prev(stl); + if (stl > 0 && pl >= 0 && vspen(table[pl][c].col)) { + Bprint(&tabout, ".sp |\\n(^%cu\n", 'a' + c); + if ((flags[c][stynum[stl]] & (CTOP | CDOWN)) == 0) { + Bprint(&tabout, ".nr %d \\n(#-u-\\n(^%c-\\n(%c|+1v\n", + TMP, 'a' + c, s); + Bprint(&tabout, ".if \\n(%d>0 .sp \\n(%du/2u", TMP, TMP); + if (pr1403) /* round */ + Bprint(&tabout, "/1v*1v"); + Bprint(&tabout, "\n"); + } + } + Bprint(&tabout, ".%c+\n", s); + Bprint(&tabout, ".in -\\n(%du\n", SIND); + if (*fn > 0) + putfont("P"); + Bprint(&tabout, ".mk %d\n", S2); + Bprint(&tabout, ".if \\n(%d>\\n(%d .nr %d \\n(%d\n", S2, S1, S1, S2); + } + Bprint(&tabout, ".sp |\\n(%du\n", S1); + for (c = dv = 0; c < ncol; c++) { + if (stl + 1 < nlin && (lf = left(stl, c, &lwid)) >= 0) { + if (dv++ == 0) + Bprint(&tabout, ".sp -1\n"); + tohcol(c); + dv++; + drawvert(lf, stl, c, lwid); + } + } + if (dv) + Bprint(&tabout, "\n"); +} + + +void +putfont(char *fn) +{ + if (fn && *fn) + Bprint(&tabout, fn[1] ? "\\f(%.2s" : "\\f%.2s", fn); +} + + +void +putsize(char *s) +{ + if (s && *s) + Bprint(&tabout, "\\s%s", s); +} + + blob - /dev/null blob + bf1978a990029d51e7be38db1dd043d6361b9c99 (mode 644) --- /dev/null +++ src/cmd/tbl/t9.c @@ -0,0 +1,76 @@ +/* t9.c: write lines for tables over 200 lines */ +# include "t.h" +static useln; + +void +yetmore(void) +{ + for (useln = 0; useln < MAXLIN && table[useln] == 0; useln++) + ; + if (useln >= MAXLIN) + error("Wierd. No data in table."); + table[0] = table[useln]; + for (useln = nlin - 1; useln >= 0 && (fullbot[useln] || instead[useln]); useln--) + ; + if (useln < 0) + error("Wierd. No real lines in table."); + domore(leftover); + while (gets1(cstore = cspace, MAXCHS) && domore(cstore)) + ; + last = cstore; + return; +} + + +int +domore(char *dataln) +{ + int icol, ch; + + if (prefix(".TE", dataln)) + return(0); + if (dataln[0] == '.' && !isdigit(dataln[1])) { + Bprint(&tabout, "%s\n", dataln); + return(1); + } + fullbot[0] = 0; + instead[0] = (char *)0; + if (dataln[1] == 0) + switch (dataln[0]) { + case '_': + fullbot[0] = '-'; + putline(useln, 0); + return(1); + case '=': + fullbot[0] = '='; + putline(useln, 0); + return(1); + } + for (icol = 0; icol < ncol; icol++) { + table[0][icol].col = dataln; + table[0][icol].rcol = 0; + for (; (ch = *dataln) != '\0' && ch != tab; dataln++) + ; + *dataln++ = '\0'; + switch (ctype(useln, icol)) { + case 'n': + table[0][icol].rcol = maknew(table[0][icol].col); + break; + case 'a': + table[0][icol].rcol = table[0][icol].col; + table[0][icol].col = ""; + break; + } + while (ctype(useln, icol + 1) == 's') /* spanning */ + table[0][++icol].col = ""; + if (ch == '\0') + break; + } + while (++icol < ncol) + table[0][icol].col = ""; + putline(useln, 0); + exstore = exspace; /* reuse space for numerical items */ + return(1); +} + + blob - /dev/null blob + 5cc59880165974a8ef51d2d1af76c235754e3869 (mode 644) --- /dev/null +++ src/cmd/tbl/tb.c @@ -0,0 +1,101 @@ +/* tb.c: check which entries exist, also storage allocation */ +# include "t.h" + +void +checkuse(void) +{ + int i, c, k; + + for (c = 0; c < ncol; c++) { + used[c] = lused[c] = rused[c] = 0; + for (i = 0; i < nlin; i++) { + if (instead[i] || fullbot[i]) + continue; + k = ctype(i, c); + if (k == '-' || k == '=') + continue; + if ((k == 'n' || k == 'a')) { + rused[c] |= real(table[i][c].rcol); + if ( !real(table[i][c].rcol)) + used[c] |= real(table[i][c].col); + if (table[i][c].rcol) + lused[c] |= real(table[i][c].col); + } else + used[c] |= real(table[i][c].col); + } + } +} + + +int +real(char *s) +{ + if (s == 0) + return(0); + if (!point(s)) + return(1); + if (*s == 0) + return(0); + return(1); +} + + +int spcount = 0; +# define MAXVEC 20 +char *spvecs[MAXVEC]; + +char * +chspace(void) +{ + char *pp; + + if (spvecs[spcount]) + return(spvecs[spcount++]); + if (spcount >= MAXVEC) + error("Too many characters in table"); + spvecs[spcount++] = pp = calloc(MAXCHS + MAXLINLEN, 1); + if (pp == (char *) - 1 || pp == (char *)0) + error("no space for characters"); + return(pp); +} + + +# define MAXPC 50 +char *thisvec; +int tpcount = -1; +char *tpvecs[MAXPC]; + +int * +alocv(int n) +{ + int *tp, *q; + + if (tpcount < 0 || thisvec + n > tpvecs[tpcount] + MAXCHS) { + tpcount++; + if (tpvecs[tpcount] == 0) { + tpvecs[tpcount] = calloc(MAXCHS, 1); + } + thisvec = tpvecs[tpcount]; + if (thisvec == (char *)0) + error("no space for vectors"); + } + tp = (int *)thisvec; + thisvec += n; + for (q = tp; q < (int *)thisvec; q++) + *q = 0; + return(tp); +} + + +void +release(void) +{ + /* give back unwanted space in some vectors */ + /* this should call free; it does not because + alloc() is so buggy */ + spcount = 0; + tpcount = -1; + exstore = 0; +} + + blob - /dev/null blob + 635dbf8ad17a91593fe1788b95dc077f00e82e27 (mode 644) --- /dev/null +++ src/cmd/tbl/tc.c @@ -0,0 +1,65 @@ +/* tc.c: find character not in table to delimit fields */ +# include "t.h" + +void +choochar(void) +{ + /* choose funny characters to delimit fields */ + int had[128], ilin, icol, k; + char *s; + + for (icol = 0; icol < 128; icol++) + had[icol] = 0; + F1 = F2 = 0; + for (ilin = 0; ilin < nlin; ilin++) { + if (instead[ilin]) + continue; + if (fullbot[ilin]) + continue; + for (icol = 0; icol < ncol; icol++) { + k = ctype(ilin, icol); + if (k == 0 || k == '-' || k == '=') + continue; + s = table[ilin][icol].col; + if (point(s)) + while (*s) + had[*s++] = 1; + s = table[ilin][icol].rcol; + if (point(s)) + while (*s) + had[*s++] = 1; + } + } + /* choose first funny character */ + for ( + s = "\002\003\005\006\007!%&#/?,:;<=>@`^~_{}+-*ABCDEFGHIJKMNOPQRSTUVWXYZabcdefgjkoqrstwxyz"; + *s; s++) { + if (had[*s] == 0) { + F1 = *s; + had[F1] = 1; + break; + } + } + /* choose second funny character */ + for ( + s = "\002\003\005\006\007:_~^`@;,<=>#%&!/?{}+-*ABCDEFGHIJKMNOPQRSTUVWXZabcdefgjkoqrstuwxyz"; + *s; s++) { + if (had[*s] == 0) { + F2 = *s; + break; + } + } + if (F1 == 0 || F2 == 0) + error("couldn't find characters to use for delimiters"); + return; +} + + +int +point(char *s) +{ + int ss = (int)s; + return(ss >= 128 || ss < 0); +} + + blob - /dev/null blob + 3df8d445d4463329c46b451afbc6a8ea99279f0b (mode 644) --- /dev/null +++ src/cmd/tbl/te.c @@ -0,0 +1,75 @@ +/* te.c: error message control, input line count */ +# include "t.h" + +void +error(char *s) +{ + fprint(2, "\n%s:%d: %s\n", ifile, iline, s); + fprint(2, "tbl quits\n"); + exits(s); +} + + +char * +gets1(char *s, int size) +{ + char *p, *ns; + int nbl; + + iline++; + ns = s; + p = Brdline(tabin, '\n'); + while (p == 0) { + if (swapin() == 0) + return(0); + p = Brdline(tabin, '\n'); + } + nbl = Blinelen(tabin)-1; + if(nbl >= size) + error("input buffer too small"); + p[nbl] = 0; + strcpy(s, p); + s += nbl; + for (nbl = 0; *s == '\\' && s > ns; s--) + nbl++; + if (linstart && nbl % 2) /* fold escaped nl if in table */ + gets1(s + 1, size - (s-ns)); + + return(p); +} + + +# define BACKMAX 500 +char backup[BACKMAX]; +char *backp = backup; + +void +un1getc(int c) +{ + if (c == '\n') + iline--; + *backp++ = c; + if (backp >= backup + BACKMAX) + error("too much backup"); +} + + +int +get1char(void) +{ + int c; + if (backp > backup) + c = *--backp; + else + c = Bgetc(tabin); + if (c == 0) /* EOF */ { + if (swapin() == 0) + error("unexpected EOF"); + c = Bgetc(tabin); + } + if (c == '\n') + iline++; + return(c); +} + + blob - /dev/null blob + 3791c32fe25ffc0804444615064a174ec1b81ad5 (mode 644) --- /dev/null +++ src/cmd/tbl/tf.c @@ -0,0 +1,74 @@ +/* tf.c: save and restore fill mode around table */ +# include "t.h" + +void +savefill(void) +{ + /* remembers various things: fill mode, vs, ps in mac 35 (SF) */ + Bprint(&tabout, ".de %d\n", SF); + Bprint(&tabout, ".ps \\n(.s\n"); + Bprint(&tabout, ".vs \\n(.vu\n"); + Bprint(&tabout, ".in \\n(.iu\n"); + Bprint(&tabout, ".if \\n(.u .fi\n"); + Bprint(&tabout, ".if \\n(.j .ad\n"); + Bprint(&tabout, ".if \\n(.j=0 .na\n"); + Bprint(&tabout, "..\n"); + Bprint(&tabout, ".nf\n"); + /* set obx offset if useful */ + Bprint(&tabout, ".nr #~ 0\n"); + Bprint(&tabout, ".if \\n(.T .if n .nr #~ 0.6n\n"); +} + + +void +rstofill(void) +{ + Bprint(&tabout, ".%d\n", SF); +} + + +void +endoff(void) +{ + int i; + + for (i = 0; i < MAXHEAD; i++) + if (linestop[i]) + Bprint(&tabout, ".nr #%c 0\n", linestop[i] + 'a' - 1); + for (i = 0; i < texct; i++) + Bprint(&tabout, ".rm %c+\n", texstr[i]); + Bprint(&tabout, "%s\n", last); +} + + +void +ifdivert(void) +{ + Bprint(&tabout, ".ds #d .d\n"); + Bprint(&tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n"); +} + + +void +saveline(void) +{ + Bprint(&tabout, ".if \\n+(b.=1 .nr d. \\n(.c-\\n(c.-1\n"); + linstart = iline; +} + + +void +restline(void) +{ + Bprint(&tabout, ".if \\n-(b.=0 .nr c. \\n(.c-\\n(d.-%d\n", iline - linstart); + linstart = 0; +} + + +void +cleanfc(void) +{ + Bprint(&tabout, ".fc\n"); +} + + blob - /dev/null blob + 6abb149081ca6383bd67ce17ffd4af57191e2453 (mode 644) --- /dev/null +++ src/cmd/tbl/tg.c @@ -0,0 +1,81 @@ +/* tg.c: process included text blocks */ +# include "t.h" + +int +gettext(char *sp, int ilin, int icol, char *fn, char *sz) +{ + /* get a section of text */ + char line[4096]; + int oname; + char *vs; + + if (texname == 0) + error("Too many text block diversions"); + if (textflg == 0) { + Bprint(&tabout, ".nr %d \\n(.lu\n", SL); /* remember old line length */ + textflg = 1; + } + Bprint(&tabout, ".eo\n"); + Bprint(&tabout, ".am %s\n", reg(icol, CRIGHT)); + Bprint(&tabout, ".br\n"); + Bprint(&tabout, ".di %c+\n", texname); + rstofill(); + if (fn && *fn) + Bprint(&tabout, ".nr %d \\n(.f\n.ft %s\n", S1, fn); + Bprint(&tabout, ".ft \\n(.f\n"); /* protect font */ + vs = vsize[icol][stynum[ilin]]; + if ((sz && *sz) || (vs && *vs)) { + Bprint(&tabout, ".nr %d \\n(.v\n", S9); + if (vs == 0 || *vs == 0) + vs = "\\n(.s+2"; + if (sz && *sz) + Bprint(&tabout, ".ps %s\n", sz); + Bprint(&tabout, ".vs %s\n", vs); + Bprint(&tabout, ".if \\n(%du>\\n(.vu .sp \\n(%du-\\n(.vu\n", S9, S9); + } + if (cll[icol][0]) + Bprint(&tabout, ".ll %sn\n", cll[icol]); + else + Bprint(&tabout, ".ll \\n(%du*%du/%du\n", SL, ctspan(ilin, icol), ncol + 1); + Bprint(&tabout, ".if \\n(.l<\\n(%2s .ll \\n(%2su\n", reg(icol, CRIGHT), + reg(icol, CRIGHT)); + if (ctype(ilin, icol) == 'a') + Bprint(&tabout, ".ll -2n\n"); + Bprint(&tabout, ".in 0\n"); + while (gets1(line, sizeof(line))) { + if (line[0] == 'T' && line[1] == '}' && line[2] == tab) + break; + if (match("T}", line)) + break; + Bprint(&tabout, "%s\n", line); + } + if (fn && *fn) + Bprint(&tabout, ".ft \\n(%d\n", S1); + if (sz && *sz) + Bprint(&tabout, ".br\n.ps\n.vs\n"); + Bprint(&tabout, ".br\n"); + Bprint(&tabout, ".di\n"); + Bprint(&tabout, ".nr %c| \\n(dn\n", texname); + Bprint(&tabout, ".nr %c- \\n(dl\n", texname); + Bprint(&tabout, "..\n"); + Bprint(&tabout, ".ec \\\n"); + /* copy remainder of line */ + if (line[2]) + tcopy (sp, line + 3); + else + *sp = 0; + oname = texname; + texname = texstr[++texct]; + return(oname); +} + + +void +untext(void) +{ + rstofill(); + Bprint(&tabout, ".nf\n"); + Bprint(&tabout, ".ll \\n(%du\n", SL); +} + + blob - /dev/null blob + ef995bbb35e0237a497ced61647d691de3c7f3fd (mode 644) --- /dev/null +++ src/cmd/tbl/ti.c @@ -0,0 +1,75 @@ +/* ti.c: classify line intersections */ +# include "t.h" +/* determine local environment for intersections */ + +int +interv(int i, int c) +{ + int ku, kl; + + if (c >= ncol || c == 0) { + if (dboxflg) { + if (i == 0) + return(BOT); + if (i >= nlin) + return(TOP); + return(THRU); + } + if (c >= ncol) + return(0); + } + ku = i > 0 ? lefdata(i - 1, c) : 0; + if (i + 1 >= nlin && allh(i)) + kl = 0; + else + kl = lefdata(allh(i) ? i + 1 : i, c); + if (ku == 2 && kl == 2) + return(THRU); + if (ku == 2) + return(TOP); + if (kl == BOT) + return(2); + return(0); +} + + +int +interh(int i, int c) +{ + int kl, kr; + + if (fullbot[i] == '=' || (dboxflg && (i == 0 || i >= nlin - 1))) { + if (c == ncol) + return(LEFT); + if (c == 0) + return(RIGHT); + return(THRU); + } + if (i >= nlin) + return(0); + kl = c > 0 ? thish (i, c - 1) : 0; + if (kl <= 1 && i > 0 && allh(up1(i))) + kl = c > 0 ? thish(up1(i), c - 1) : 0; + kr = thish(i, c); + if (kr <= 1 && i > 0 && allh(up1(i))) + kr = c > 0 ? thish(up1(i), c) : 0; + if (kl == '=' && kr == '=') + return(THRU); + if (kl == '=') + return(LEFT); + if (kr == '=') + return(RIGHT); + return(0); +} + + +int +up1(int i) +{ + i--; + while (instead[i] && i > 0) + i--; + return(i); +} + + blob - /dev/null blob + 8fa4e497222abd7fcd085cc1a5445d7a1c2bdfb7 (mode 644) --- /dev/null +++ src/cmd/tbl/tm.c @@ -0,0 +1,65 @@ +/* tm.c: split numerical fields */ +# include "t.h" + +char * +maknew(char *str) +{ + /* make two numerical fields */ + int dpoint, c; + char *p, *q, *ba; + + p = str; + for (ba = 0; c = *str; str++) + if (c == '\\' && *(str + 1) == '&') + ba = str; + str = p; + if (ba == 0) { + for (dpoint = 0; *str; str++) { + if (*str == '.' && !ineqn(str, p) && + (str > p && digit(*(str - 1)) || + digit(*(str + 1)))) + dpoint = (int)str; + } + if (dpoint == 0) + for (; str > p; str--) { + if (digit( *(str - 1) ) && !ineqn(str, p)) + break; + } + if (!dpoint && p == str) /* not numerical, don't split */ + return(0); + if (dpoint) + str = (char *)dpoint; + } else + str = ba; + p = str; + if (exstore == 0 || exstore > exlim) { + exstore = exspace = chspace(); + exlim = exstore + MAXCHS; + } + q = exstore; + while (*exstore++ = *str++) + ; + *p = 0; + return(q); +} + + +int +ineqn (char *s, char *p) +{ + /* true if s is in a eqn within p */ + int ineq = 0, c; + + while (c = *p) { + if (s == p) + return(ineq); + p++; + if ((ineq == 0) && (c == delim1)) + ineq = 1; + else if ((ineq == 1) && (c == delim2)) + ineq = 0; + } + return(0); +} + + blob - /dev/null blob + 7d586e8b8388622eb1f651460a936bb16da1dcdc (mode 644) --- /dev/null +++ src/cmd/tbl/tr.c @@ -0,0 +1,28 @@ +# include "t.h" +/* tr.c: number register allocation */ +char *nregs[] = { + /* this array must have at least 3*qcol entries + or illegal register names will result */ + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "4q", "4r", + "4s", "4t", "4u", "4v", "4w", "4x", "4y", "4z", "4;", "4.", + "4a", "4b", "4c", "4d", "4e", "4f", "4g", "4h", "4i", "4j", + "4k", "4l", "4m", "4n", "4o", "4p", "5a", "5b", "5c", "5d", + "5e", "5f", "5g", "5h", "5i", "5j", "5k", "5l", "5m", "5n", + "5o", "5p", "5q", "5r", "5s", "5t", "5u", "5v", "5w", "5x", + 0}; + + +char * +reg(int col, int place) +{ + if (sizeof(nregs) < 2 * 3 * qcol) + error("Too many columns for registers"); + return (nregs[qcol*place+col]); +} + + blob - /dev/null blob + 43cc84ecdf85ab5021de973c4d5e28572364d073 (mode 644) --- /dev/null +++ src/cmd/tbl/ts.c @@ -0,0 +1,71 @@ +/* ts.c: minor string processing subroutines */ +#include "t.h" + +int +match (char *s1, char *s2) +{ + while (*s1 == *s2) + if (*s1++ == '\0') + return(1); + else + s2++; + return(0); +} + + +int +prefix(char *small, char *big) +{ + int c; + + while ((c = *small++) == *big++) + if (c == 0) + return(1); + return(c == 0); +} + + +int +letter (int ch) +{ + if (ch >= 'a' && ch <= 'z') + return(1); + if (ch >= 'A' && ch <= 'Z') + return(1); + return(0); +} + + +int +numb(char *str) +{ + /* convert to integer */ + int k; + for (k = 0; *str >= '0' && *str <= '9'; str++) + k = k * 10 + *str - '0'; + return(k); +} + + +int +digit(int x) +{ + return(x >= '0' && x <= '9'); +} + + +int +max(int a, int b) +{ + return( a > b ? a : b); +} + + +void +tcopy (char *s, char *t) +{ + while (*s++ = *t++) + ; +} + + blob - /dev/null blob + 96270b7580ae4955da049991ce787dc831ca9895 (mode 644) --- /dev/null +++ src/cmd/tbl/tt.c @@ -0,0 +1,127 @@ +/* tt.c: subroutines for drawing horizontal lines */ +# include "t.h" + +int +ctype(int il, int ic) +{ + if (instead[il]) + return(0); + if (fullbot[il]) + return(0); + il = stynum[il]; + return(style[ic][il]); +} + + +int +min(int a, int b) +{ + return(a < b ? a : b); +} + + +int +fspan(int i, int c) +{ + c++; + return(c < ncol && ctype(i, c) == 's'); +} + + +int +lspan(int i, int c) +{ + int k; + + if (ctype(i, c) != 's') + return(0); + c++; + if (c < ncol && ctype(i, c) == 's') + return(0); + for (k = 0; ctype(i, --c) == 's'; k++) + ; + return(k); +} + + +int +ctspan(int i, int c) +{ + int k; + c++; + for (k = 1; c < ncol && ctype(i, c) == 's'; k++) + c++; + return(k); +} + + +void +tohcol(int ic) +{ + if (ic == 0) + Bprint(&tabout, "\\h'|0'"); + else + Bprint(&tabout, "\\h'(|\\n(%2su+|\\n(%2su)/2u'", reg(ic, CLEFT), + reg(ic - 1, CRIGHT)); +} + + +int +allh(int i) +{ + /* return true if every element in line i is horizontal */ + /* also at least one must be horizontl */ + int c, one, k; + + if (fullbot[i]) + return(1); + if (i >= nlin) + return(dboxflg || boxflg); + for (one = c = 0; c < ncol; c++) { + k = thish(i, c); + if (k == 0) + return(0); + if (k == 1) + continue; + one = 1; + } + return(one); +} + + +int +thish(int i, int c) +{ + int t; + char *s; + struct colstr *pc; + + if (c < 0) + return(0); + if (i < 0) + return(0); + t = ctype(i, c); + if (t == '_' || t == '-') + return('-'); + if (t == '=') + return('='); + if (t == '^') + return(1); + if (fullbot[i] ) + return(fullbot[i]); + if (t == 's') + return(thish(i, c - 1)); + if (t == 0) + return(1); + pc = &table[i][c]; + s = (t == 'a' ? pc->rcol : pc->col); + if (s == 0 || (point(s) && *s == 0)) + return(1); + if (vspen(s)) + return(1); + if (t = barent( s)) + return(t); + return(0); +} + + blob - /dev/null blob + 217869e1a46759cae0e91957d6043354f0e03b90 (mode 644) --- /dev/null +++ src/cmd/tbl/tu.c @@ -0,0 +1,257 @@ +/* tu.c: draws horizontal lines */ +# include "t.h" + +void +makeline(int i, int c, int lintype) +{ + int cr, type, shortl; + + type = thish(i, c); + if (type == 0) + return; + shortl = (table[i][c].col[0] == '\\'); + if (c > 0 && !shortl && thish(i, c - 1) == type) + return; + if (shortl == 0) + for (cr = c; cr < ncol && (ctype(i, cr) == 's' || type == thish(i, cr)); cr++) + ; + else + for (cr = c + 1; cr < ncol && ctype(i, cr) == 's'; cr++) + ; + drawline(i, c, cr - 1, lintype, 0, shortl); +} + + +void +fullwide(int i, int lintype) +{ + int cr, cl; + + if (!pr1403) + Bprint(&tabout, ".nr %d \\n(.v\n.vs \\n(.vu-\\n(.sp\n", SVS); + cr = 0; + while (cr < ncol) { + cl = cr; + while (i > 0 && vspand(prev(i), cl, 1)) + cl++; + for (cr = cl; cr < ncol; cr++) + if (i > 0 && vspand(prev(i), cr, 1)) + break; + if (cl < ncol) + drawline(i, cl, (cr < ncol ? cr - 1 : cr), lintype, 1, 0); + } + Bprint(&tabout, "\n"); + if (!pr1403) + Bprint(&tabout, ".vs \\n(%du\n", SVS); +} + + +void +drawline(int i, int cl, int cr, int lintype, int noheight, int shortl) +{ + char *exhr, *exhl, *lnch; + int lcount, ln, linpos, oldpos, nodata; + + lcount = 0; + exhr = exhl = ""; + switch (lintype) { + case '-': + lcount = 1; + break; + case '=': + lcount = pr1403 ? 1 : 2; + break; + case SHORTLINE: + lcount = 1; + break; + } + if (lcount <= 0) + return; + nodata = cr - cl >= ncol || noheight || allh(i); + if (!nodata) + Bprint(&tabout, "\\v'-.5m'"); + for (ln = oldpos = 0; ln < lcount; ln++) { + linpos = 2 * ln - lcount + 1; + if (linpos != oldpos) + Bprint(&tabout, "\\v'%dp'", linpos - oldpos); + oldpos = linpos; + if (shortl == 0) { + tohcol(cl); + if (lcount > 1) { + switch (interv(i, cl)) { + case TOP: + exhl = ln == 0 ? "1p" : "-1p"; + break; + case BOT: + exhl = ln == 1 ? "1p" : "-1p"; + break; + case THRU: + exhl = "1p"; + break; + } + if (exhl[0]) + Bprint(&tabout, "\\h'%s'", exhl); + } else if (lcount == 1) { + switch (interv(i, cl)) { + case TOP: + case BOT: + exhl = "-1p"; + break; + case THRU: + exhl = "1p"; + break; + } + if (exhl[0]) + Bprint(&tabout, "\\h'%s'", exhl); + } + if (lcount > 1) { + switch (interv(i, cr + 1)) { + case TOP: + exhr = ln == 0 ? "-1p" : "+1p"; + break; + case BOT: + exhr = ln == 1 ? "-1p" : "+1p"; + break; + case THRU: + exhr = "-1p"; + break; + } + } else if (lcount == 1) { + switch (interv(i, cr + 1)) { + case TOP: + case BOT: + exhr = "+1p"; + break; + case THRU: + exhr = "-1p"; + break; + } + } + } else + Bprint(&tabout, "\\h'|\\n(%2su'", reg(cl, CLEFT)); + Bprint(&tabout, "\\s\\n(%d", LSIZE); + if (linsize) + Bprint(&tabout, "\\v'-\\n(%dp/6u'", LSIZE); + if (shortl) + Bprint(&tabout, "\\l'|\\n(%2su'", reg(cr, CRIGHT)); + else + { + lnch = "\\(ul"; + if (pr1403) + lnch = lintype == 2 ? "=" : "\\(ru"; + if (cr + 1 >= ncol) + Bprint(&tabout, "\\l'|\\n(TWu%s%s'", exhr, lnch); + else + Bprint(&tabout, "\\l'(|\\n(%2su+|\\n(%2su)/2u%s%s'", reg(cr, CRIGHT), + reg(cr + 1, CLEFT), exhr, lnch); + } + if (linsize) + Bprint(&tabout, "\\v'\\n(%dp/6u'", LSIZE); + Bprint(&tabout, "\\s0"); + } + if (oldpos != 0) + Bprint(&tabout, "\\v'%dp'", -oldpos); + if (!nodata) + Bprint(&tabout, "\\v'+.5m'"); +} + + +void +getstop(void) +{ + int i, c, k, junk, stopp; + + stopp = 1; + for (i = 0; i < MAXLIN; i++) + linestop[i] = 0; + for (i = 0; i < nlin; i++) + for (c = 0; c < ncol; c++) { + k = left(i, c, &junk); + if (k >= 0 && linestop[k] == 0) + linestop[k] = ++stopp; + } + if (boxflg || allflg || dboxflg) + linestop[0] = 1; +} + + +int +left(int i, int c, int *lwidp) +{ + int kind, li, lj; + /* returns -1 if no line to left */ + /* returns number of line where it starts */ + /* stores into lwid the kind of line */ + *lwidp = 0; + if (i < 0) + return(-1); + kind = lefdata(i, c); + if (kind == 0) + return(-1); + if (i + 1 < nlin) + if (lefdata(next(i), c) == kind) + return(-1); + li = i; + while (i >= 0 && lefdata(i, c) == kind) + i = prev(li = i); + if (prev(li) == -1) + li = 0; + *lwidp = kind; + for (lj = i + 1; lj < li; lj++) + if (instead[lj] && strcmp(instead[lj], ".TH") == 0) + return(li); + for (i = i + 1; i < li; i++) + if (fullbot[i]) + li = i; + return(li); +} + + +int +lefdata(int i, int c) +{ + int ck; + + if (i >= nlin) + i = nlin - 1; + if (ctype(i, c) == 's') { + for (ck = c; ctype(i, ck) == 's'; ck--) + ; + if (thish(i, ck) == 0) + return(0); + } + i = stynum[i]; + i = lefline[c][i]; + if (i > 0) + return(i); + if (dboxflg && c == 0) + return(2); + if (allflg) + return(1); + if (boxflg && c == 0) + return(1); + return(0); +} + + +int +next(int i) +{ + while (i + 1 < nlin) { + i++; + if (!fullbot[i] && !instead[i]) + break; + } + return(i); +} + + +int +prev(int i) +{ + while (--i >= 0 && (fullbot[i] || instead[i])) + ; + return(i); +} + + blob - /dev/null blob + 19a4b03fda16cf4977869fc761af16e0a159c98b (mode 644) --- /dev/null +++ src/cmd/tbl/tv.c @@ -0,0 +1,183 @@ +/* tv.c: draw vertical lines */ +# include "t.h" + +void +drawvert(int start, int end, int c, int lwid) +{ + char *exb = 0, *ext = 0; + int tp = 0, sl, ln, pos, epb, ept, vm; + + end++; + vm = 'v'; + /* note: nr 35 has value of 1m outside of linesize */ + while (instead[end]) + end++; + for (ln = 0; ln < lwid; ln++) { + epb = ept = 0; + pos = 2 * ln - lwid + 1; + if (pos != tp) + Bprint(&tabout, "\\h'%dp'", pos - tp); + tp = pos; + if (end < nlin) { + if (fullbot[end] || (!instead[end] && allh(end))) + epb = 2; + else + switch (midbar(end, c)) { + case '-': + exb = "1v-.5m"; + break; + case '=': + exb = "1v-.5m"; + epb = 1; + break; + } + } + if (lwid > 1) + switch (interh(end, c)) { + case THRU: + epb -= 1; + break; + case RIGHT: + epb += (ln == 0 ? 1 : -1); + break; + case LEFT: + epb += (ln == 1 ? 1 : -1); + break; + } + if (lwid == 1) + switch (interh(end, c)) { + case THRU: + epb -= 1; + break; + case RIGHT: + case LEFT: + epb += 1; + break; + } + if (start > 0) { + sl = start - 1; + while (sl >= 0 && instead[sl]) + sl--; + if (sl >= 0 && (fullbot[sl] || allh(sl))) + ept = 0; + else if (sl >= 0) + switch (midbar(sl, c)) { + case '-': + ext = ".5m"; + break; + case '=': + ext = ".5m"; + ept = -1; + break; + default: + vm = 'm'; + break; + } + else + ept = -4; + } else if (start == 0 && allh(0)) { + ept = 0; + vm = 'm'; + } + if (lwid > 1) + switch (interh(start, c)) { + case THRU: + ept += 1; + break; + case LEFT: + ept += (ln == 0 ? 1 : -1); + break; + case RIGHT: + ept += (ln == 1 ? 1 : -1); + break; + } + else if (lwid == 1) + switch (interh(start, c)) { + case THRU: + ept += 1; + break; + case LEFT: + case RIGHT: + ept -= 1; + break; + } + if (exb) + Bprint(&tabout, "\\v'%s'", exb); + if (epb) + Bprint(&tabout, "\\v'%dp'", epb); + Bprint(&tabout, "\\s\\n(%d", LSIZE); + if (linsize) + Bprint(&tabout, "\\v'-\\n(%dp/6u'", LSIZE); + Bprint(&tabout, "\\h'-\\n(#~u'"); /* adjustment for T450 nroff boxes */ + Bprint(&tabout, "\\L'|\\n(#%cu-%s", linestop[start] + 'a' - 1, + vm == 'v' ? "1v" : "\\n(35u"); + if (ext) + Bprint(&tabout, "-(%s)", ext); + if (exb) + Bprint(&tabout, "-(%s)", exb); + pos = ept - epb; + if (pos) + Bprint(&tabout, "%s%dp", pos >= 0 ? "+" : "", pos); + /* the string #d is either "nl" or ".d" depending + on diversions; on GCOS not the same */ + Bprint(&tabout, "'\\s0\\v'\\n(\\*(#du-\\n(#%cu+%s", + linestop[start] + 'a' - 1, vm == 'v' ? "1v" : "\\n(35u"); + if (ext) + Bprint(&tabout, "+%s", ext); + if (ept) + Bprint(&tabout, "%s%dp", (-ept) > 0 ? "+" : "", (-ept)); + Bprint(&tabout, "'"); + if (linsize) + Bprint(&tabout, "\\v'\\n(%dp/6u'", LSIZE); + } +} + + +int +midbar(int i, int c) +{ + int k; + + k = midbcol(i, c); + if (k == 0 && c > 0) + k = midbcol(i, c - 1); + return(k); +} + + +int +midbcol(int i, int c) +{ + int ct; + + while ( (ct = ctype(i, c)) == 's') + c--; + if (ct == '-' || ct == '=') + return(ct); + if (ct = barent(table[i][c].col)) + return(ct); + return(0); +} + + +int +barent(char *s) +{ + if (s == 0) + return (1); + if (!point(s)) + return(0); + if (s[0] == '\\') + s++; + if (s[1] != 0) + return(0); + switch (s[0]) { + case '_': + return('-'); + case '=': + return('='); + } + return(0); +} + + blob - /dev/null blob + 5765832c36a98cb3e1910e55075c7ae934a081e8 (mode 644) --- /dev/null +++ src/cmd/troff/FIXES @@ -0,0 +1,821 @@ +March 11, 1994 + + If we are just plain old nroff (and not doing UNICODE) we should + only Lookup characters, not Install when we don't know them. + If we are troff, we Install them anyway + +March 8, 1994 + + Nroff had problems with parsing quoted white space as options or + character code in some terminals tables. Changed by having scanf + include white space when necessary as suggested by Rich. + +March 1, 1994 + + Made sanity check for terminal type depending on the trace level; + trace level set with -tn flag at start up + +22 Feb, 1994 + + More pointer shuffling fixes. + +18 Feb, 1994 + + More disabling of multibyte stuff. Fixed bug in n5.c: casetm didn' + know about the new format in the fontables. + +Feb 17, 1994 + + Removed extra include from n1.c + + Fixed dubious pointer shuffling in n7.c, t10.c & n8.c. Thanks Rich! + +Feb 10, 1994 + + Disabled the multybyte stuff; only plan 9 will get it. + +Jan 24, 1994 + + Fixed nasty bug discovered by td, which caused core dumps on + \D'l-0.002775i 0i' and apparently all numbers closer to 0 + than -.002775. Fixed in storeline() and storeword() (n7.c). + +Dec 16, 1993 + + nroff & troff -N were looking for the TYPESETTER variable, causing + + troff: cannot open /sys/lib/troff/term/tab.202; line 1, file stdin + + fixed my moving getenv("TYPESETTER") to t10.c in t_ptinit(void). + +Dec 3, 1993: + + The sequence \s+2\H'+10' came sometimes out in the wrong order + (x H before s), so there wasn't a difference bewteen \s+2\H'+10' + and \H'+10'\s+2. Now the fonts bits of the CHARHT are used to + register the current pontsize, so we can issue a s10 in t10.c + if needed. A bit sneaky. + + Try to prevent double slashes in path names. Especially under + plan9 things started to look ugly. + + Exception word list now grows dynamic. + +Nov 30, 1993: + + Allow multiple calls to .pi, requested by Rob. + .pi cat + .pi dogs + is now equivalent with + .pi cat | dogs + + + .ab now takes also optional error code: + .ab [n] [string] + If n and string, n is exit code, string is message + If n, n is exit code, ``User Abort, exit code n" is message + If !n and string, standard exit code, string is message + If !n and ! string, standard exit code, "User Abort" is message + +Nov 24, 1993: + + Reordered code to keep the UNASNI scripts happy. + + Nroff dumped core reading terminal tables: apparenty under plan 9, + scanf includes the '\n'; added test for '\0' in parse in n10.c. + + Relative tab settings (.ta +1C +2C) didn't work; anding the + previous value with TABMASK fixes this (caseta). + +Nov 23, 1993: + + Included code, originally done by bwk for plan 9, to handle + multi-byte characters. + +Nov 3, 1993: + + ``pair internal'' two char names by shifting 16 bits. Will allow + the use of 16 bit characters sets (Unicode in plan9 etc.) for + macro's etc. + +Oct 20, 1993: + + Word & line buffers are now dynamic: No more word or line overflow + unless when we run out of memory. + +Oct 11, 1993: + + lost diversion warning pops up regularly with man macro's. Due + to a possible macro coding problem. Triggered by something like + troff -man: + .TP + .TP + foo + .ex + Minimal code: + .di aa + throw away this diversion (aa) while being defined. + .rm aa + .br + .di + + Fixed by disallowing .rm to throw away current diversion. The + rn request will complain with: + + cannot remove diversion aa during definition; etc. + +Sep 29, 1993: + + Some long standing fixes which never went back in the source. + Thanks to Janet & Rich. + +Sep 28, 1993: + + Changed getach() (n1.c), so it does't consider truncated + special characters as (8-bit) ascii. STX ETX ENQ ACK and BELL + are still allowed for the ultimate backwards compatibility. + + Some code changes, so real ANSI compilers like the SGI version + (acc from Sun is a poor excuse for an ANSI compiler) don't + barf. Some compromises (static Tchar wbuf in n9.c) allowed so + the unansified stuff for non-ansi compilers (cc on Sun's) will + work as well. + +Sep 9, 1993: + + Be nice to Gerard. Now also word spaces in .tl and after + tabs/fleids etc. + +Aug 12, 1993: + + Tabs setting can now be humongous. We also allow 99 tabs to + accomodate tbl. As a side effect, NTM buffers are now 1K + +Aug 11, 1993: + + .R register, now contains maximum number of addessable + registers minus the number actually used. + + Small esthetic changes in error messages; removed a statement + which wasn't reached anyway. + +Aug 10, 1993: + + Some more speed hacks: be smarter doing the linear table + lookups in alloc() and finds(). + + The real name of the det diversion size macro is now gd. + +Aug 9, 1993: + + A much faster way to find the end of a string/macro, by + remembering that when defined. + +Aug 6, 1993: + + Slightly more eficient way of skipping to the end of a + string/macro + +Aug 5, 1993: + + Prevent character sign extension for 8-bit charnames diversions + etc. by unpair + +Aug 4, 1993: + + Growing the dynamical macro/strings name space and registers + space (See the experiment of 21 July) now with bigger + increments. Casts added to satisfy non-ANSI compilers. + +Aug 3, 1993: + + Should check return value in alloc (n3.c), to prevent core dump + when memory gets tight. + +July 28, 1993: + + New request: .sg

sets the dn and dl registers to the size + of the diversion named in the argument. Doesn't do anything + when the named diversion doesn't exist. The name sg is + temporary until we find a better one. + +July 21, 1993: + + Experiment: Macro space & registers name allocated + dynamically. Note that current reallocation occurs in + increments of 1, to force the code to be executed a lot; a kind + of stress testing. Also, eight bit characters allowed in + macro/string names. + +July 21, 1993: + + Turn on the escape mode if the end macro is called. + +July 20, 1993: + + Tracing mode now default off + + Don't print s stackdump either when a file specfied on the + command line argument cannot be opened + +July 15, 1993: + + Don't print useless line & current file informations when a + file specfied on the command line argument cannot be opened. + + Sun ansi compiler doesn't default adhere to standards. Undid + the kludge in tdef.h + +July 14, 1993: + + Coding error made the tab type R not function properly + +July 12, 1993: + + Fixed a typo in the version stuff, noticed by Rich + +July 9, 1993: + + Added the dwb home configuration stuff, thanks RIch. Also, + NCHARS is big enough. Added a fflush to casetm, so .fm + will be up to date. + +June 25, 1993 (Rich): + + -t option + + reinstated for the sake of compatibility. Some old + shells scripts and man(1) from SunOs want this, sigh + + Compiler and system dependencies + + Some systems pull in sys/types.h via #include and then + the compiler complains about two ushort typedefs. Therefore, + ushort is now Ushort (and uchar Uchar). + + The SVID specifies a strdup, POSIX doesn't, anyway, troff + provides its own version, slightly different then the standard + one. A To prevent name clashes with that definion, renamed to + strdupl. + +June 24, 1993 (Rich): + + -V option added for DWB3.4 (rich) + +May 18, 1993: + + Trivial fix (.cf) request for troff -a + + issuing + + .cf /dev/null + + with troff -a gives some spurious output: + + H720 + H720 + s10 + f1 + + fixed by checking for ascii mode it ptesc(), ptps() and + ptfont() in t10.c + + + Enhancement + + Added a .tm request to roff. Works just like .tm, but now + it will do it to file. The name is coined by Carmela. Great + for creating indeces & toc's (we hope). + +May 18 1993: + + Compatibilty change + + Somebody complained that his favorite macro didn't work: + it had a BELL (^G) in the name. This was a non-documented + feature of earlier versions of troff (although the + documentation actually doesn't say that you can. (They can + only be used for delimiters or with the tr request), so it + isn't that important). + + But the sake of eternal backward compatibilaty I allowed + some control characters like, STX, ACK, etc. also be part + of a macro/string name. + + While at it, I made it also possible to have eight bit + characters be part of the name. It might be that this screws + up the way users think about these things. For UNICODE + versions, they probably want to do that as well, and that + won't work as easy, (because these characters are 16-bits + wide), so it is dubious whether we actually want this. + + BTW. Now + + .de \(ts\ts + .tm terminal sigma macro + .. + .\(ts\(ts + + also works, as long the internal cookie for ts isn't more then + eight bits. + +May 12, 1993: + + Syntax change + + Some requests accept tabs as a separator, some don't and + this can be a nuisance. Now a tab is also recognized as + an argument separator for requests, this makes + + .so /dev/null + + works. + + To be more precise, any motion character is allowed, so + + .so\h'5i'/dev/null + + will work as well, if one really wants that. + + It will be a problem for users who really relied on this as in + + .ds x string + + and expect the tab to become part of the string a, but I haven't + seen any use of that (obscure trick). + +May 6, 1993: + + Eileen count fixed + + Troff sometimes went in a loop, and exited with: ``job + looping; check abuse of macros'' (also known as the Eileen's + loop). It can be forced with the next trivial programme: + + .de ff + .di xx + .. + .wh -1 ff + .bp + + Basically what happens is that a page transition now will + happen in a diversion, which doesn't make sense. Wat really + happens is that eject() (in n7.c) doesn't eject the frame + because we are in a diversion. This cause the loop in n1.c + (because now always stack->pname <= ejl). Adding check on + whether we are not in a diversion takes care of the problem. + +March 30, 1993: + + Need request, .ne + + When there is a begin of page trap set, and the first thing + in the file is a .ne request, the trap gets fired, but, + the x font R etc. cookies doen't come out, because the + troff thinks that the first page pseudo transition already + took place. Fixed by forcing the start of the first page + in the casene request with the same code as in casetl (which + caused a similar problem quite some time ago). + + Change to .cf request ``Here document'' + + If the argument of .cf starts with a <<, the rest of it is taken + as an EOF token. It will reat the rest of the input until it hits + the EOF token and copies it to the output. This is similar as + the shell's ``here document'' mechanisme and put in place to + improve the kludgy way picasso, picpack etc. now include + postscript. + + Using troff -TLatin1 (DWB version) and \N'...' caused core dump + + In t11, in chadd, it should test on NCHARS - ALPHABET to see + whether we run out of table space (and we probably should beaf + up NCHARS for the DWB version). + +March 16, 1993: + + Diversion rename bug fix + + It is possible to get troff in an infinite loop by renaming a + diversion in progress, and calling it later with the + new name (as in .di xx, .rn xx yy, .yy). The effect depends on + whether troff already put stuff in the diversion or not. + + Fix by having .rn also rename the current diversion (if + there is any and when appropriate). If the diversion calls + itself by the new name and given the fix made on 11 nov + 1992, this will now result in an error. (BTW, the fix from + 11 nov is improved: diversions nest, so we have to account + for that). + +December 18, 1992: + Some people have complete novels as comments, so we need + to skip comments while checking the legality of font files. + thaks Rixh + +December 16, 1992 + + Some people rely on the order that -r arguments are given, + so that troff -rC1 -rC3 ends up setting register C to 3. + Because cpushback() pushes things in a LIFO order back, we + have to do the same to get -r args in a FIFO order. + +Nov 17, 1992: + + Giving a -rL8 option cuased the string .nr L 8 to be printed + on the output, using the wonderful 3b2. Some garbage was + left in buf[100] in main(). Fixed by setting buf[0] explicitly + to 0 (because some C-compilers complain about ``no automatic + aggregate initialization''). + +Nov 11, 1992: + + Diversion bug fix + + If a diversion was being read and the input is faulty so + the diversion was reading in itself, it caused troff to + loop undefinitely. This was easily fixed by a test in + control(a,b) in n1.c. + + Something similar things might happen with macros causing + the ``eileenct problem'', but I didn't look for that. We + have to wait until it happens. + +Oct 26, 1992: + + Numeric arguments: + + Illegal argments are treated as missing arguments. This + changed the semantics of .ll, .ls, .in, .lg, .ul, .cu .lt + (which acted as if the argument was 0) and .ps which was + simply ignored with an illegal argument. + + Tidied up number parsing in atoi1(). This prevents arguments + like .x or 1.2.3.4 being interpret as a legal number (nonumb = 0) + + Numeric arguments error reporting: + + Controlled by .pt, illegal numbers are now reported (default + trace mode is 1). This is also true for the escapes: + \h'..', \v'..' \H'..', \S'..', \N'..', \D'..', \l'.., \L'.. + and \x'..'. + + \D'c' is the only drawing request which doesn't take a pair + of numbers as arguments, so a special case is put here in + setdraw() (This code actually could use an overhaul to get + better parsing. As long as the \D'..' cookies are machine + generated it is low on the priority list). + + Don't generate an error if the illegal argument to a request + is a \}. It is too painful to do right (although it can be + done, but it would clutter getch() and getcho() even more). + + Input line numbers (.c register) bug fixes: + + In not taken branches of .if or .ie, the input line # + (numtab[CD].val) should be raised when necessary (in eatblk()). + + For concealed newlines, we still should count the line for input. + + Setfield (n9.c) sometimes pushes the rest of the line back to + the input (including \n), without adjusting numtab[CD].val + + Because .c (and so numtab[CD].val) is the number of lines read + and the error might actually happen in the current line + (before seeing the '\n), we need to apply correction in + errprint when nlflg set. (This correction needs to be undone + when inside a macro because the nlflg is set by reading the + args to the macro). + + Line number setting (.lf) request bug fixes: + + I interpret that the .c register will contain the number of + read lines, not including the current one. + + Also, don't change the input line number when the first + argument of .lf is not a number. + + As a net effect, the next input + + .EQ + .EN + .ab + + will generate the same output whether eqn has been used or not. + + If request bug fix: + + A ``.if page .tm foo'' caused the next line being ignored; + This bcause when the 2nd delimiter of a string couldn't be + found in cmpstr, the next line was always eaten. Solution: + in caseif1, if the condition is false, we should check + nlflg before eating a block. (Note: We might have eaten + \{\ as well. We could disallow the \{\ in a string to be + compared to prevent that but that might break other things). + + Enhancement to .pt: + + The .pt now pops the previous values when no argument is + specified. Turned out to be handy when chasing for problems. + Just ``bracked'' the code with .pt 7 and .pt and you get + a trace of only that block. The meaning of the arguments + is now: + 01 trace numeric arguments (default on) + 02 trace requests + 04 trace macros + + Abort request (.ab) beautification: + + Don't print the extra carriage return when .ab is called + without an argument. + +Oct 12, 1992: + + (Comments & spelling errors from this day on by jaap) + + replaced 32767 by INT_MAX in several places to allow for very + long pages (on 32-but machines). + + The ``.fp 1 R \"COMMENT'' complains about ``./troff: Can't + open font file /usr/lib/font/devpost/h'' on some systems. It + sees the tab as part of the optional font file. Apparently it + is system dependent whether isgraph() includes the tab + character. Fixed by using getach() in getname() in n1.c + instead. + +Aug 28, 1992: + removed call to popi from rdtty(); it was eating up the + rest of the macro if it was used from within one. (thanks, jaap) + + +Jul 21, 1992: + added extra test in nextfile() to pop current input file + only if not in .nx command. thanks to jaap. + + added test in getword() to avoid hyphenating after \z character, + which prevents any hyphenation inside \X'...'. thanks to jaap. + + added, then removed, code in getword() to prevent hyphenating + anything shorter than 6 characters. looks like it changed a + lot more than i thought. + +Jul 12, 1992: + added .pt request to trace macros and requests (from jaap). + .pt N Print trace of macros (N=1), requests (N=2) or both (N=3) + +Jun 5, 1992: + added tests to t.twrest and t.twinit to avoid 0 deref in + n2 and n10, for nroff -t xxxxx. thanks to Rich Drechsler. + +May 22, 1992: + added extern decls to e.g., void Tchar (*hmot)(void) in tdef.h + and added definition to ni.c, so pointers are defined explicitly. + makes it work on turbo c++ and probably others. + + changed a couple of isdigit's and isgraph(getch()) to avoid + multiple evaluation (even though it shouldn't happen). + + Made /usr/bin/nroff a shell script. + +May 12, 1992: + n1.c: need p++ after strrchr to skip / in program name. + thanks to Rich Drechsler. + +Apr 17, 1992: + casefi(), n5.c: .u register should be 0 or 1, not incremented + with each .fi. + +Apr 5, 1992: + fiddled n7.c and added _nmwid to the environment, to add a + 5th argument to .nm: the maximum number of digits in any + line number. default is 3, which was previously hardwired in. + + added jaap's code for yet another register which actually delivers + a string, called .S (so it can easily go in the switch in setn() + in n4.c); it delivers the current tabstop and alignment modes in + a format suitable for a subsequent .ta \n(.S command: + .ds T \n(.S + ... + .ta \*T + +Mar 30, 1992: + added test in getword to avoid hyphenating things with motions + (and avoid a core dump sometimes too). + +Mar 13, 1992: + \n(sb initialized wrong in setwd(). + + TYPESETTER=foo troff -Tpost used foo instead of post. + +Mar 12, 1992: + rearranged tests in popf so that .so is closed properly before + moving on to the next macro package. + +Mar 1, 1992: + input mechanism rearranged to use getc() instead of stack of + explicit input buffers. 5-10% slowdown. + +Jan 28, 1992: + fixed .tm \(mi to print something sensible. thanks to jaap. + +Jan 2, 1992: + fiddle setfp so doesn't put out font stuff if -a turned on. + +Dec 17, 1991: + copy 3rd argument in .fp commands to x font ... lines when it contains + a /, for testing fonts locally. + +Dec 13, 1991: + parameterize the font directories, etc., so can be set in makefiles. + added -N argument to run as nroff. + +Nov 8, 1991: + add a maplow(towlower...) in n8.c to handle brain-damaged libraries. + +Nov 2, 1991: + merged nroff into troff, based on Ken's plan 9 version. + merged nii.c into ni.c, removed tw.h, etc. more work needed + to make this stuff cleaner. + +July 27, 1991: + added test in setn in n4 to fix bug that permitted things like + \n (ab to work "properly". thanks to jaap for finding and fixing. + + added paranoid testing in t11 to make sure font files look ok. + +May 13, 1991: + moved evaluation of \(xx from copy mode to non-copy mode, so that + weird character names wouldn't get reevaluated in argument parsing. + installed july 27. + +May 6, 1991: + increased size of hyphenation exception buffer to 512 from 128 + +Apr 14, 1991: + added an extra redundant call of ptfont in setfp, since it appears + that some versions of adobe transcript assume that an "x font" command + means to change the actual font as well. the fix preserves the current font. + thanks to david brailsford and friends for spotting the problem. + + fixed up tests in alpha() in n8 to defend isalpha() against too-big inputs. + punct() argument had wrong type too. thanks to rich drexler and peter nelson. + +Mar 19, 1991: + fixed bug that prevented .rd from working with new corebuf organization. + + fixed bug that caused .ig inside diversions to give bad storage + allocation. thanks to arthur david olson, whose fix was on netnews + 3 years earlier. + +Mar 5, 1991: + huge table sizes for kanji. + +Feb ??, 1991: + working on dealing with large alphabets, notably kanji. + added "defaultwidth" to font descriptions, for characters + not given an explicit width. + +Jan, 1991: + added tex hyphenation, using standard tex data files, but not the + elaborate compressed trie, which is a lot of trouble to save maybe + 40k bytes. this appears to run at exactly the same speed as before. + + so far this stuff reads into a fixed size array; that should change. + it should also be possible to deal with multiple languages. + + the command .ha sets the algorithm. .ha 1 => tex, with troff rules + if tex doesn't hyphenate; .ha 0 gives troff rules, and .ha resets + to the default, which is tex. the hyphenation algorithm is part of + the environment, a nod to a future in which i handle more than one + language. + + replaced the fixed size corebuf array for string/macro storage by + a dynamic structure that can grow. + + this appears to slow things down by maybe 3%. the code is about + the same complexity. + +Dec 27, 1990: + converted to ansi c, based on some work by ken thompson, but not + as thoroughly as he did. there is a shell script unansi and an awk + program cvt that will help you step back in time if you do not have + an ansi c compiler. + + moved the special-name characters up to 256 instead of 128, although + done in terms of ALPHABET, so one can pass 8 bit characters through. + removed lots of 0177's and similar numbers. input is now not filtered, + and if a character with the 8th bit on comes in, it will go out again. + + fixed t11.c to read character names in hex or octal as well as + single-character ascii. + + unknown characters are now carried through with width = spacewidth. + needs a way to set widths. + + removed all signal handling from troff. you signal, you die. + + added -d option to print version number. + +Dec 7, 1990: + .fp 3 V VERYLONGNAME used to truncate the name to 10 chars; fixed. + + increased the limit on FBUFSZ for tables with very long fields. + + changed atoi1() to use double to avoid intermediate overflow. + + moved filenames like /usr/lib/font into tdef.h for easy change. + removed some dreggish definitions. + + cleaned up non-portable error printing stuff; fixed up some messages. + +Dec 12, 1989: + Removed the .! command, an undocumented synonym for .sy. + +Dec 4, 1989: + Another wart to the \X code, to try to preserve blanks in all situations. + +Nov 17, 1989: + A number of small changes preparatory to getting rid of nroff. + The argument -Tnroff or -Tnroff-12 changes some internal values + so that the predicate .if n is true and certain arithmetic operations + are done as if nroff. This design is not yet final. + +Nov 7, 1989: + Fixed hyphenation for nov-ice, ad-vice, de-vice, ser-vice, *-vice. + +Oct 11, 1989: + It is now permitted to do an explicit change to font S. + It is not clear what will break (though nothing seems to have). + +Oct 10, 1989: + Modified flush code to always put out \nH instead of sometimes h. + This makes it easier to parse the output for positioning. + +Sep 9, 1989: + Fixed internal representation of \D'~...' so that it + is immune to .tr ~ and variations. No external change. + +Aug 9, 1989: + Changed .tm so it outputs \e, \%, \-, \&, \(blank). + This might break indexing code. + Only in the new version, as are all subsequent fixes. + +July, 1989: + A major internal change: font information is read in ascii + instead of the weird binary format of makedev (which is now dead). + character names need not all appear in DESC; new names that + appear when a font is used become part of the set of known names. + + There are some flaky bits here (it's conceivable that some \N + number will collide with a real name), and it's probably 10-15% + slower. Tant pis. + + As a by-product, nroff no longer compiles. I'll probably get + back to this, but an alternative is to bag it once and for all. + +May 25, 1989: + Another bug in \l, this time when width is 0. Not installed, + since it's in the new font version. + +Apr 23, 1989: + Fixed bug in n9 that caused core dump with unterminated + \l command, like \l'1.5i + + ptflush no longer called when -a is on. + +Apr 12, 1989: + fixed bug in n2 that failed to suppress printing of \! + output when a -o was in effect. + +Apr 5, 1989: + .fl and \X now cause output of size, font, hpos and vpos. + this is necesary for postprocessors that intend to insert + independent material, such as postscript. + +Feb 1, 1989: + wait for .pi pipe to empty before exiting + +Oct 2, 1988: + default is now -Tpost + +Sep 19, 1988: + added abortive code to handle built-up characters by + passing something through as \D'b...'. never used. + +Jul 4, 1988: + replaced the sbrk nonsense in n3.c by calls to malloc. + + \N now tests against proper font size. + + installed Jaap Akkerhuis's code (mutatis mutandis) for + permitting up to 99 fonts, swapping them into font pos 0 + as needed. fixes the long-standing problem of having + multiple font changes on a single output line. + +Jul 2, 1988: + \X now preserves spaces even when contents are diverted. + + \N code safer -- NTRTAB and NWIDCACHE enlarged. + +Jul 14, 1987: + Fixed obscure bug causing incorrect indentation of .mc output. blob - /dev/null blob + 6dc8fa0953a7bb5411dd02f8fd459949019124cb (mode 644) --- /dev/null +++ src/cmd/troff/README @@ -0,0 +1,31 @@ +To make troff (actually a.out): + + make + +You will also need to write a driver for your favorite output device. +d202.c provides a model, although it is specialized to a machine no +one has. There are also a variety of postscript drivers that are the +best thing to use if you have a postscript device. + +You will also have to make a DESC file for your typesetter and some +font description files; see dev202 for examples. These describe the +named characters, widths, kerning information, and output codes. + +Nroff is the same program as troff, so you should + + cp a.out /usr/bin/troff + ln /usr/bin/troff /usr/bin/nroff + +or the equivalent. + +You will also need terminal description files for your terminals; see +tab.37, tab.450 and tab.lp for examples. + +Troff uses files that are normally stored in /usr/lib/font; +macro packages are in /usr/lib/tmac; and nroff tables are in +/usr/lib/term. You can edit tdef.h to change these assumptions. + +There have been a few features since the last version, and a number of +significant internal changes. Not all are improvements, of course. +Most of the more recent changes, including bug fixes, are in FIXES, +which you should read also. blob - /dev/null blob + 3426d626676923632f3d5ee921746a5a77c25af7 (mode 644) --- /dev/null +++ src/cmd/troff/cvt @@ -0,0 +1,45 @@ + +awk ' + +/^{/ { + if (prev != "") { + # comments can be trouble (e.g. ffree()) + if ( (c = match(prev, /\/\*.*\*\/$/)) != 0 ) { + comment = substr(prev, c) + sub(/\/\*.*\*\/$/, "", prev) + } else comment = "" + + x = prev + + # isolate argument list + sub(/^[^(]*\(/, "", x) + sub(/\)[^)]*$/, "", x) + + # find the names in it + n = split(x, args) + arglist = "" + for (i = 2; i <= n; i += 2) + arglist = arglist args[i] + gsub(/\(\*f\)\(Tchar\)/, "f", arglist) # special case for n4.c + gsub(/\[[0-9]+\]/, "", arglist) # for n8.c + gsub(/[*()\[\]]/, "", arglist) # discard noise characters *()[] + gsub(/,/, ", ", arglist) # space nicely + sub(/\(.*\)/, "(" arglist ")", prev) # reconstruct + print prev comment + + # argument declarations + gsub(/,/, ";", x) + gsub(/\(\*f\)\(Tchar\)/, "(*f)()", x) # special case for n4.c + if (x != "") + print "\t" x ";" + } + prev = $0 + next +} + +{ print prev + prev = $0 +} + +END { print prev } +' $* blob - /dev/null blob + a63e5fdeed896d5f27aba63425ee25aa2d1bc931 (mode 644) --- /dev/null +++ src/cmd/troff/dwbinit.c @@ -0,0 +1,313 @@ +/* + * + * Pathname management routines for DWB C programs. + * + * Applications should initialize a dwbinit array with the string + * pointers and arrays that need to be updated, and then hand that + * array to DWBinit before much else happens in their main program. + * DWBinit calls DWBhome to get the current home directory. DWBhome + * uses the last definition of DWBENV (usually "DWBHOME") in file + * DWBCONFIG (e.g., /usr/lib/dwb3.4) or the value assigned to that + * variable in the environment if the DWBCONFIG file doesn't exist, + * can't be read, or doesn't define DWBENV. + * + * DWBCONFIG must be a simple shell script - comments, a definition + * of DWBHOME, and perhaps an export or echo is about all that's + * allowed. The parsing in DWBhome is simple and makes no attempt + * to duplicate the shell. It only looks for DWBHOME= as the first + * non-white space string on a line, so + * + * # + * # A sample DWBCONFIG shell script + * # + * + * DWBHOME=/usr/add-on/dwb3.4 + * export DWBHOME + * + * means DWBhome would return "/usr/add-on/dwb3.4" for the DWB home + * directory. A DWBCONFIG file means there can only be one working + * copy of a DWB release on a system, which seems like a good idea. + * Using DWBCONFIG also means programs will always include correct + * versions of files (e.g., prologues or macro packages). + * + * Relying on an environment variable guarantees nothing. You could + * execute a version of dpost, but your environment might point at + * incorrect font tables or prologues. Despite the obvious problems + * we've also implemented an environment variable approach, but it's + * only used if there's no DWBCONFIG file. + * + * DWBinit calls DWBhome to get the DWB home directory prefix and + * then marches through its dwbinit argument, removing the default + * home directory and prepending the new home. DWBinit stops when + * it reaches an element that has NULL for its address and value + * fields. Pointers in a dwbinit array are reallocated and properly + * initialized; arrays are simply reinitialized if there's room. + * All pathnames that are to be adjusted should be relative. For + * example, + * + * char *fontdir = "lib/font"; + * char xyzzy[25] = "etc/xyzzy"; + * + * would be represented in a dwbinit array as, + * + * dwbinit allpaths[] = { + * &fontdir, NULL, 0, + * NULL, xyzzy, sizeof(xyzzy), + * NULL, NULL, 0 + * }; + * + * The last element must have NULL entries for the address and + * value fields. The main() routine would then do, + * + * #include "dwbinit.h" + * + * main() { + * + * DWBinit("program name", allpaths); + * ... + * } + * + * Debugging is enabled if DWBDEBUG is in the environment and has + * the value ON. Output is occasionally useful and probably should + * be documented. + * + */ + +#include +#include +#include +#include + +#include "dwbinit.h" + +#ifndef DWBCONFIG +#define DWBCONFIG "/dev/null" +#endif + +#ifndef DWBENV +#define DWBENV "DWBHOME" +#endif + +#ifndef DWBHOME +#define DWBHOME "" +#endif + +#ifndef DWBDEBUG +#define DWBDEBUG "DWBDEBUG" +#endif + +#ifndef DWBPREFIX +#define DWBPREFIX "\\*(.P" +#endif + +/*****************************************************************************/ + +void DWBdebug(dwbinit *ptr, int level) +{ + + char *path; + char *home; + static char *debug = NULL; + +/* + * + * Debugging output, but only if DWBDEBUG is defined to be ON in the + * environment. Dumps general info the first time through. + * + */ + + if ( debug == NULL && (debug = getenv(DWBDEBUG)) == NULL ) + debug = "OFF"; + + if ( strcmp(debug, "ON") == 0 ) { + if ( level == 0 ) { + fprintf(stderr, "Environment variable: %s\n", DWBENV); + fprintf(stderr, "Configuration file: %s\n", DWBCONFIG); + fprintf(stderr, "Default home: %s\n", DWBHOME); + if ( (home = DWBhome()) != NULL ) + fprintf(stderr, "Current home: %s\n", home); + } /* End if */ + + fprintf(stderr, "\n%s pathnames:\n", level == 0 ? "Original" : "Final"); + for ( ; ptr->value != NULL || ptr->address != NULL; ptr++ ) { + if ( (path = ptr->value) == NULL ) { + path = *ptr->address; + fprintf(stderr, " pointer: %s\n", path); + } else fprintf(stderr, " array[%d]: %s\n", ptr->length, path); + if ( level == 0 && *path == '/' ) + fprintf(stderr, " WARNING - absolute path\n"); + } /* End for */ + } /* End if */ + +} /* End of DWBdebug */ + +/*****************************************************************************/ + +char *DWBhome(void) +{ + + FILE *fp; + char *ptr; + char *path; + int len; + char buf[200]; + char *home = NULL; + +/* + * + * Return the DWB home directory. Uses the last definition of DWBENV + * (usually "DWBHOME") in file DWBCONFIG (perhaps /usr/lib/dwb3.4) or + * the value assigned to the variable named by the DWBENV string in + * the environment if DWBCONFIG doesn't exist or doesn't define DWBENV. + * Skips the file lookup if DWBCONFIG can't be read. Returns NULL if + * there's no home directory. + * + */ + + if ( (fp = fopen(DWBCONFIG, "r")) != NULL ) { + len = strlen(DWBENV); + while ( fgets(buf, sizeof(buf), fp) != NULL ) { + for ( ptr = buf; isspace(*ptr); ptr++ ) ; + if ( strncmp(ptr, DWBENV, len) == 0 && *(ptr+len) == '=' ) { + path = ptr + len + 1; + for ( ptr = path; !isspace(*ptr) && *ptr != ';'; ptr++ ) ; + *ptr = '\0'; + if ( home != NULL ) + free(home); + if ( (home = malloc(strlen(path)+1)) != NULL ) + strcpy(home, path); + } /* End if */ + } /* End while */ + fclose(fp); + } /* End if */ + + if ( home == NULL ) { + if ( (home = getenv(DWBENV)) == NULL ) { + if ( (home = DWBHOME) == NULL || *home == '\0' || *home == ' ' ) + home = NULL; + } /* End if */ + } /* End if */ + + while (home && *home == '/' && *(home +1) == '/') /* remove extra slashes */ + home++; + return(home); + +} /* End of DWBhome */ + +/*****************************************************************************/ + +void DWBinit(char *prog, dwbinit *paths) +{ + + char *prefix; + char *value; + char *path; + int plen; + int length; + dwbinit *opaths = paths; + +/* + * + * Adjust the pathnames listed in paths, using the home directory + * returned by DWBhome(). Stops when it reaches an element that has + * NULL address and value fields. Assumes pathnames are relative, + * but changes everything. DWBdebug issues a warning if an original + * path begins with a /. + * + * A non-NULL address refers to a pointer, which is reallocated and + * then reinitialized. A NULL address implies a non-NULL value field + * and describes a character array that we only reinitialize. The + * length field for an array is the size of that array. The length + * field of a pointer is an increment that's added to the length + * required to store the new pathname string - should help when we + * want to change character arrays to pointers in applications like + * troff. + * + */ + + if ( (prefix = DWBhome()) == NULL ) { + fprintf(stderr, "%s: no DWB home directory\n", prog); + exit(1); + } /* End if */ + + DWBdebug(opaths, 0); + plen = strlen(prefix); + + for ( ; paths->value != NULL || paths->address != NULL; paths++ ) { + if ( paths->address == NULL ) { + length = 0; + value = paths->value; + } else { + length = paths->length; + value = *paths->address; + } /* End else */ + + length += plen + 1 + strlen(value); /* +1 is for the '/' */ + + if ( (path = malloc(length+1)) == NULL ) { + fprintf(stderr, "%s: can't allocate pathname memory\n", prog); + exit(1); + } /* End if */ + + if ( *value != '\0' ) { + char *eop = prefix; + while(*eop++) + ; + eop -= 2; + if (*value != '/' && *eop != '/') { + sprintf(path, "%s/%s", prefix, value); + } else if (*value == '/' && *eop == '/') { + value++; + sprintf(path, "%s%s", prefix, value); + } else + sprintf(path, "%s%s", prefix, value); + } else + sprintf(path, "%s", prefix); + + if ( paths->address == NULL ) { + if ( strlen(path) >= paths->length ) { + fprintf(stderr, "%s: no room for %s\n", prog, path); + exit(1); + } /* End if */ + strcpy(paths->value, path); + free(path); + } else *paths->address = path; + } /* End for */ + + DWBdebug(opaths, 1); + +} /* End of DWBinit */ + +/*****************************************************************************/ + +void DWBprefix( char *prog, char *path, int length) +{ + + char *home; + char buf[512]; + int len = strlen(DWBPREFIX); + +/* + * + * Replace a leading DWBPREFIX string in path by the current DWBhome(). + * Used by programs that pretend to handle .so requests. Assumes path + * is an array with room for length characters. The implementation is + * not great, but should be good enough for now. Also probably should + * have DWBhome() only do the lookup once, and remember the value if + * called again. + * + */ + + if ( strncmp(path, DWBPREFIX, len) == 0 ) { + if ( (home = DWBhome()) != NULL ) { + if ( strlen(home) + strlen(path+len) < length ) { + sprintf(buf, "%s%s", home, path+len); + strcpy(path, buf); /* assuming there's room in path */ + } else fprintf(stderr, "%s: no room to grow path %s", prog, path); + } /* End if */ + } /* End if */ + +} /* End of DWBprefix */ + +/*****************************************************************************/ + blob - /dev/null blob + acb1476cc17c1495fa77e9b26ef6174212328da9 (mode 644) --- /dev/null +++ src/cmd/troff/dwbinit.h @@ -0,0 +1,19 @@ +/* + * + * A structure used to adjust pathnames in DWB C code. Pointers + * set the address field, arrays use the value field and must + * also set length to the number elements in the array. Pointers + * are always reallocated and then reinitialized; arrays are only + * reinitialized, if there's room. + * + */ + +typedef struct { + char **address; + char *value; + int length; +} dwbinit; + +extern void DWBinit(char *, dwbinit *); +extern char* DWBhome(void); +extern void DWBprefix(char *, char *, int); blob - /dev/null blob + 42147880128836d939ce2fe7f42d2162425fe0e1 (mode 644) --- /dev/null +++ src/cmd/troff/ext.h @@ -0,0 +1,184 @@ +extern int TROFF; + +extern int alphabet; +extern char **argp; +extern char *eibuf; +extern char *ibufp; +extern char *obufp; +extern char *unlkp; +extern char *xbufp; +extern char *xeibuf; +extern char cfname[NSO+1][NS]; +extern int trace; +extern char devname[]; +extern char ibuf[IBUFSZ]; +extern char mfiles[NMF][NS]; +extern char nextf[]; +extern char obuf[]; +extern char termtab[]; +extern char fontdir[]; +extern Font fonts[MAXFONTS+1]; +extern char xbuf[IBUFSZ]; +extern Offset apptr; +extern Offset ip; +extern Offset nextb; +extern Offset offset; +extern Offset woff; +extern Numerr numerr; +extern int *pnp; +extern int pstab[]; +extern int nsizes; +extern int app; +extern int ascii; +extern int bd; +extern int bdtab[]; +extern int ccs; +extern char *chnames[]; /* chnames[n-ALPHABET] -> name of char n */ +extern int copyf; +extern int cs; +extern int dfact; +extern int dfactd; +extern int diflg; +extern int dilev; +extern int donef; +extern int dotT; +extern int dpn; +extern int ds; +extern int ejf; +extern int em; +extern int eqflg; +extern int error; +extern int esc; +extern int eschar; +extern int ev; +extern int evi; +extern int evlist[EVLSZ]; +extern int fc; +extern int flss; +extern int fontlab[]; +extern int hflg; +extern int ibf; +extern int ifi; +extern int iflg; +extern int init; +extern int lead; +extern int lg; +extern int lgf; +extern int macerr; +extern int mflg; +extern int mfont; +extern int mlist[NTRAP]; +extern int mpts; +extern int nchnames; +extern int ndone; +extern int newmn; +extern int nflush; +extern int nfo; +extern int nfonts; +extern int nform; +extern int nhyp; +extern int nlflg; +extern int nlist[NTRAP]; +extern int nmfi; +extern int nonumb; +extern int noscale; +extern int npn; +extern int npnflg; +extern int nx; +extern int oldbits; +extern int oldmn; +extern int over; +extern int padc; +extern int pfont; +extern int pfrom; +extern int pipeflg; +extern int pl; +extern int pnlist[]; +extern int po1; +extern int po; +extern int ppts; +extern int print; +extern FILE *ptid; +extern int pto; +extern int quiet; +extern int ralss; +extern int rargc; +extern int raw; +extern int res; +extern int sbold; +extern int setwdf; +extern int sfont; +extern int smnt; +extern int stdi; +extern int stop; +extern int sv; +extern int tabch, ldrch; +extern int tflg; +extern int totout; +extern int trap; +extern Ushort trtab[]; +extern int tty; +extern int ulfont; +extern int vflag; +extern int whichroff; +extern int widthp; +extern int xfont; +extern int xpts; +extern Stack *ejl; +extern Stack *frame; +extern Stack *stk; +extern Stack *nxf; +extern Tchar **hyp; +extern Tchar *olinep; +extern Tchar pbbuf[NC]; +extern Tchar *pbp; +extern Tchar *lastpbp; +extern Tchar ch; +extern Tchar nrbits; +extern Tbuf _oline; +extern Wcache widcache[]; +extern char gchtab[]; +extern Diver d[NDI]; +extern Diver *dip; + + +extern char xchname[]; +extern short xchtab[]; +extern char *codestr; +extern char *chnamep; +extern short *chtab; +extern int nchtab; + +extern Numtab *numtabp; + +/* these characters are used as various signals or values +/* in miscellaneous places. +/* values are set in specnames in t10.c +*/ + +extern int c_hyphen; +extern int c_emdash; +extern int c_rule; +extern int c_minus; +extern int c_fi; +extern int c_fl; +extern int c_ff; +extern int c_ffi; +extern int c_ffl; +extern int c_acute; +extern int c_grave; +extern int c_under; +extern int c_rooten; +extern int c_boxrule; +extern int c_lefthand; +extern int c_dagger; +extern int c_isalnum; + +/* + * String pointers for DWB pathname management. + */ + +extern char *DWBfontdir; +extern char *DWBntermdir; +extern char *DWBalthyphens; + blob - /dev/null blob + eccbfbdb655be1402020ec4c28a5cd7cfc76af70 (mode 644) --- /dev/null +++ src/cmd/troff/find @@ -0,0 +1 @@ +grep $1 *.[ch] blob - /dev/null blob + 6bd94ada6d478a7ac4b580a24285575888f84363 (mode 644) --- /dev/null +++ src/cmd/troff/fns.h @@ -0,0 +1,384 @@ +/* + * other + */ +int pclose(FILE*); +long filesize(int fd); +int open(char *, int); +int read(int, char *, int); +int lseek(int, long, int); +int close(int); +int getpid(void); + +/* + * c1.c + */ +void init0(void); +void init2(void); +void cvtime(void); +void errprint(void); +int control(int a, int b); +void casept(void); +int getrq(void); +Tchar getch(void); +void setxon(void); +Tchar getch0(void); +Tchar get1ch(FILE *); +void pushback(Tchar *b); +void cpushback(char *b); +int nextfile(void); +int popf(void); +void flushi(void); +int getach(void); +void casenx(void); +int getname(void); +void caseso(void); +void caself(void); +void casecf(void); +void getline(char *s, int n); +void casesy(void); +void getpn(char *a); +void setrpt(void); + +/* + * n2.c + */ +int pchar(Tchar i); +void pchar1(Tchar i); +int pchar2(Tchar i); +int flusho(void); +void casedone(void); +void caseex(void); +void done(int x); +void done1(int x); +void done2(int x); +void done3(int x); +void edone(int x); +void casepi(void); + +/* + * c3.c + */ +void blockinit(void); +char* grow(char *, int, int); +void mnspace(void); +void caseig(void); +void casern(void); +void maddhash(Contab *rp); +void munhash(Contab *mp); +void mrehash(void); +void caserm(void); +void caseas(void); +void caseds(void); +void caseam(void); +void casede(void); +int findmn(int i); +void clrmn(int i); +Offset finds(int mn); +int skip(void); +int copyb(void); +void copys(void); +Offset alloc(void); +void ffree(Offset i); +void wbf(Tchar i); +Tchar rbf(void); +Tchar popi(void); +Offset pushi(Offset newip, int mname); +void* setbrk(int x); +int getsn(void); +Offset setstr(void); +void collect(void); +void seta(void); +void caseda(void); +void casegd(void); +void casedi(void); +void casedt(void); +void casetl(void); +void casepc(void); +void casepm(void); +void stackdump(void); + +/* + * c4.c + */ +void setn(void); +int wrc(Tchar i); +void setn1(int i, int form, Tchar bits); +void nnspace(void); +void nrehash(void); +void nunhash(Numtab *rp); +int findr(int i); +int usedr(int i); +int fnumb(int i, int (*f)(Tchar)); +int decml(int i, int (*f)(Tchar)); +int roman(int i, int (*f)(Tchar)); +int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp); +int abc(int i, int (*f)(Tchar)); +int abc0(int i, int (*f)(Tchar)); +long atoi0(void); +long ckph(void); +long atoi1(Tchar ii); +void caserr(void); +void casenr(void); +void caseaf(void); +void setaf(void); +int vnumb(int *i); +int hnumb(int *i); +int inumb(int *n); +int quant(int n, int m); + +/* + * c5.c + */ +void casead(void); +void casena(void); +void casefi(void); +void casenf(void); +void casers(void); +void casens(void); +int chget(int c); +void casecc(void); +void casec2(void); +void casehc(void); +void casetc(void); +void caselc(void); +void casehy(void); +int max(int aa, int bb); +void casenh(void); +void casece(void); +void casein(void); +void casell(void); +void caselt(void); +void caseti(void); +void casels(void); +void casepo(void); +void casepl(void); +void casewh(void); +void casech(void); +int findn(int i); +void casepn(void); +void casebp(void); +void casextm(void); +void casetm(void); +void casefm(void); +void casetm1(int ab, FILE *out); +void casesp(void); +void casesp1(int a); +void casert(void); +void caseem(void); +void casefl(void); +void caseev(void); +void envcopy(Env *e1, Env *e2); +void caseel(void); +void caseie(void); +void casexif(void); +void caseif(void); +void caseif1(int); +void eatblk(int inblk); +int cmpstr(Tchar c); +void caserd(void); +int rdtty(void); +void caseec(void); +void caseeo(void); +void caseta(void); +void casene(void); +void casetr(void); +void casecu(void); +void caseul(void); +void caseuf(void); +void caseit(void); +void casemc(void); +void casemk(void); +void casesv(void); +void caseos(void); +void casenm(void); +void getnm(int *p, int min); +void casenn(void); +void caseab(void); +void save_tty(void); +void restore_tty(void); +void set_tty(void); +void echo_off(void); +void echo_on(void); + +/* + * t6.c + */ +int t_width(Tchar j); +void zapwcache(int s); +int onfont(int n, int f); +int getcw(int i); +void xbits(Tchar i, int bitf); +Tchar t_setch(int c); +Tchar t_setabs(void); +int t_findft(int i); +void caseps(void); +void casps1(int i); +int findps(int i); +void t_mchbits(void); +void t_setps(void); +Tchar t_setht(void); +Tchar t_setslant(void); +void caseft(void); +void t_setfont(int a); +void t_setwd(void); +Tchar t_vmot(void); +Tchar t_hmot(void); +Tchar t_mot(void); +Tchar t_sethl(int k); +Tchar t_makem(int i); +Tchar getlg(Tchar i); +void caselg(void); +void casefp(void); +char *strdupl(const char *); +int setfp(int pos, int f, char *truename, int print); +void casecs(void); +void casebd(void); +void casevs(void); +void casess(void); +Tchar t_xlss(void); +Uchar* unpair(int i); +void outascii(Tchar i); + +/* + * c7.c + */ +void tbreak(void); +void donum(void); +void text(void); +void nofill(void); +void callsp(void); +void ckul(void); +void storeline(Tchar c, int w); +void newline(int a); +int findn1(int a); +void chkpn(void); +int findt(int a); +int findt1(void); +void eject(Stack *a); +int movword(void); +void horiz(int i); +void setnel(void); +int getword(int x); +void storeword(Tchar c, int w); +Tchar gettch(void); + +/* + * c8.c + */ +void hyphen(Tchar *wp); +int punct(Tchar i); +int alph(int i); +void caseha(void); +void caseht(void); +void casehw(void); +int exword(void); +int suffix(void); +int maplow(int i); +int vowel(int i); +Tchar* chkvow(Tchar *w); +void digram(void); +int dilook(int a, int b, char t[26][13]); + +/* + * c9.c + */ +Tchar setz(void); +void setline(void); +int eat(int c); +void setov(void); +void setbra(void); +void setvline(void); +void setdraw(void); +void casefc(void); +Tchar setfield(int x); + +/* + * t10.c + */ +void t_ptinit(void); +void t_specnames(void); +void t_ptout(Tchar i); +int ptout0(Tchar *pi); +void ptchname(int); +void ptflush(void); +void ptps(void); +void ptfont(void); +void ptfpcmd(int f, char *s, char *fn); +void t_ptlead(void); +void ptesc(void); +void ptpage(int n); +void pttrailer(void); +void ptstop(void); +void t_ptpause(void); + +/* + * t11.c + */ +int getdesc(char *name); +int getfont(char *name, int pos); +int chadd(char *s, int, int); +char* chname(int n); +int getlig(FILE *fin); + +/* + * n6.c + */ +int n_width(Tchar j); +Tchar n_setch(int c); +Tchar n_setabs(void); +int n_findft(int i); +void n_mchbits(void); +void n_setps(void); +Tchar n_setht(void); +Tchar n_setslant(void); +void n_caseft(void); +void n_setfont(int a); +void n_setwd(void); +Tchar n_vmot(void); +Tchar n_hmot(void); +Tchar n_mot(void); +Tchar n_sethl(int k); +Tchar n_makem(int i); +void n_casefp(void); +void n_casebd(void); +void n_casevs(void); +Tchar n_xlss(void); + +/* + * n10.c + */ +void n_ptinit(void); +char* skipstr(char *s); +char* getstr(char *s, char *t); +char* getint(char *s, int *pn); +void twdone(void); +void n_specnames(void); +int findch(char *s); +void n_ptout(Tchar i); +void ptout1(void); +char* plot(char *x); +void move(void); +void n_ptlead(void); +void n_ptpause(void); + +/* + * indirect calls on TROFF/!TROFF. these are variables! + */ +extern Tchar (*hmot)(void); +extern Tchar (*makem)(int i); +extern Tchar (*setabs)(void); +extern Tchar (*setch)(int c); +extern Tchar (*sethl)(int k); +extern Tchar (*setht)(void); +extern Tchar (*setslant)(void); +extern Tchar (*vmot)(void); +extern Tchar (*xlss)(void); +extern int (*findft)(int i); +extern int (*width)(Tchar j); +extern void (*mchbits)(void); +extern void (*ptlead)(void); +extern void (*ptout)(Tchar i); +extern void (*ptpause)(void); +extern void (*setfont)(int a); +extern void (*setps)(void); +extern void (*setwd)(void); blob - /dev/null blob + 623637fc7f420a8a2868ec7d9e56d19254a6a5bf (mode 644) --- /dev/null +++ src/cmd/troff/hytab.c @@ -0,0 +1,126 @@ +/* + * Hyphenation digram tables + */ + +typedef unsigned char Uchar; + + +Uchar bxh[26][13] = { + 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0040,0000,0040 +}; + +Uchar hxx[26][13] = { + 0006,0042,0041,0123,0021,0024,0063,0042,0002,0043,0021,0001,0022, + 0140,0000,0200,0003,0260,0006,0000,0160,0007,0000,0140,0000,0320, + 0220,0000,0160,0005,0240,0010,0000,0100,0006,0000,0200,0000,0320, + 0240,0000,0120,0003,0140,0000,0000,0240,0010,0000,0220,0000,0160, + 0042,0023,0041,0040,0040,0022,0043,0041,0030,0064,0021,0000,0041, + 0100,0000,0140,0000,0220,0006,0000,0140,0003,0000,0200,0000,0000, + 0200,0000,0120,0002,0220,0010,0000,0160,0006,0000,0140,0000,0320, + 0020,0000,0020,0000,0020,0000,0000,0020,0000,0000,0020,0000,0000, + 0043,0163,0065,0044,0022,0043,0104,0042,0061,0146,0061,0000,0007, + 0100,0000,0140,0000,0040,0000,0000,0100,0000,0000,0120,0000,0000, + 0140,0000,0040,0011,0060,0004,0001,0120,0003,0000,0140,0000,0040, + 0200,0000,0100,0000,0140,0000,0000,0140,0000,0000,0140,0000,0240, + 0200,0000,0140,0000,0160,0000,0000,0220,0000,0000,0140,0000,0240, + 0200,0000,0140,0000,0160,0000,0000,0220,0000,0000,0060,0000,0240, + 0021,0043,0041,0121,0040,0023,0042,0003,0142,0042,0061,0001,0022, + 0120,0000,0140,0010,0140,0010,0000,0140,0002,0000,0120,0000,0120, + 0000,0000,0000,0000,0360,0000,0000,0000,0000,0000,0160,0000,0000, + 0100,0000,0040,0005,0120,0000,0000,0100,0000,0000,0060,0000,0140, + 0140,0040,0100,0001,0240,0041,0000,0242,0000,0002,0140,0000,0100, + 0240,0000,0120,0002,0200,0000,0000,0320,0007,0000,0240,0000,0340, + 0101,0021,0041,0020,0040,0005,0042,0121,0002,0021,0201,0000,0020, + 0160,0000,0100,0000,0140,0000,0000,0160,0006,0000,0220,0000,0140, + 0140,0000,0020,0001,0020,0000,0000,0100,0001,0000,0300,0000,0000, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0106,0041,0040,0147,0040,0000,0063,0041,0001,0102,0160,0002,0002, + 0300,0000,0040,0017,0140,0017,0000,0240,0000,0000,0140,0000,0120, +}; + +Uchar bxxh[26][13] = { + 0005,0150,0153,0062,0062,0246,0152,0127,0146,0203,0310,0017,0206, + 0100,0000,0120,0000,0140,0000,0000,0100,0000,0000,0120,0000,0060, + 0100,0000,0040,0000,0060,0000,0000,0060,0000,0000,0220,0000,0040, + 0100,0000,0120,0000,0200,0000,0000,0100,0000,0000,0140,0000,0060, + 0043,0142,0046,0140,0062,0147,0210,0131,0046,0106,0246,0017,0111, + 0060,0000,0020,0000,0060,0000,0000,0040,0000,0000,0100,0000,0000, + 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0100,0000,0040, + 0100,0000,0100,0000,0100,0000,0000,0040,0000,0000,0100,0000,0140, + 0066,0045,0145,0140,0000,0070,0377,0030,0130,0103,0003,0017,0006, + 0040,0000,0040,0000,0020,0000,0000,0040,0000,0000,0100,0000,0000, + 0200,0000,0020,0000,0140,0000,0000,0120,0000,0000,0120,0000,0040, + 0120,0000,0040,0000,0060,0000,0000,0060,0000,0000,0160,0000,0040, + 0120,0000,0040,0000,0120,0000,0000,0040,0000,0000,0160,0000,0040, + 0120,0000,0020,0000,0140,0000,0000,0120,0000,0000,0140,0000,0040, + 0051,0126,0150,0140,0060,0210,0146,0006,0006,0165,0003,0017,0244, + 0120,0000,0040,0000,0160,0000,0000,0140,0000,0000,0060,0000,0140, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0140,0000,0140,0000,0060,0000,0000,0100,0000,0000,0140,0000,0020, + 0120,0000,0020,0000,0060,0000,0000,0060,0000,0000,0060,0000,0040, + 0140,0000,0020,0000,0100,0000,0000,0140,0000,0000,0140,0000,0020, + 0070,0125,0051,0162,0120,0105,0126,0104,0006,0044,0000,0017,0052, + 0140,0000,0020,0000,0140,0000,0000,0060,0000,0000,0060,0000,0040, + 0020,0000,0000,0000,0020,0000,0000,0000,0000,0000,0000,0000,0060, + 0140,0000,0160,0000,0200,0000,0000,0140,0000,0000,0000,0000,0240, + 0065,0042,0060,0200,0000,0210,0222,0146,0006,0204,0220,0012,0003, + 0240,0000,0020,0000,0120,0000,0000,0200,0000,0000,0200,0000,0240, +}; + +Uchar xhx[26][13] = { + 0032,0146,0042,0107,0076,0102,0042,0146,0202,0050,0006,0000,0051, + 0036,0377,0057,0013,0057,0366,0377,0057,0001,0377,0057,0000,0040, + 0037,0377,0020,0000,0100,0022,0377,0057,0362,0116,0100,0000,0017, + 0057,0377,0057,0031,0137,0363,0377,0037,0362,0270,0077,0000,0117, + 0074,0142,0012,0236,0076,0125,0063,0165,0341,0046,0047,0000,0024, + 0020,0017,0075,0377,0040,0001,0377,0017,0001,0204,0020,0000,0040, + 0057,0017,0057,0340,0140,0362,0314,0117,0003,0302,0100,0000,0057, + 0057,0357,0077,0017,0100,0366,0314,0057,0342,0346,0037,0000,0060, + 0252,0145,0072,0157,0377,0165,0063,0066,0164,0050,0363,0000,0362, + 0000,0000,0020,0000,0020,0000,0000,0017,0000,0000,0020,0000,0000, + 0117,0017,0237,0377,0200,0354,0125,0110,0004,0257,0000,0000,0300, + 0057,0367,0054,0357,0157,0216,0314,0114,0217,0353,0053,0000,0057, + 0077,0213,0077,0077,0177,0317,0377,0114,0377,0352,0077,0000,0076, + 0077,0213,0077,0077,0157,0177,0377,0054,0377,0352,0117,0000,0075, + 0125,0230,0065,0216,0057,0066,0063,0047,0345,0126,0011,0000,0033, + 0057,0377,0051,0360,0120,0361,0273,0056,0001,0256,0057,0000,0060, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0076,0310,0056,0310,0137,0174,0273,0055,0335,0266,0033,0000,0155, + 0077,0157,0057,0360,0057,0063,0042,0024,0077,0206,0020,0000,0040, + 0057,0037,0077,0360,0100,0365,0377,0037,0362,0176,0050,0000,0026, + 0167,0146,0042,0112,0077,0110,0062,0254,0366,0052,0377,0000,0163, + 0060,0000,0040,0000,0120,0000,0377,0060,0012,0000,0037,0000,0257, + 0037,0232,0157,0361,0040,0003,0125,0010,0001,0256,0000,0000,0340, + 0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0017,0277, + 0253,0315,0257,0216,0377,0206,0146,0306,0371,0126,0232,0000,0004, + 0057,0012,0100,0360,0160,0360,0000,0040,0000,0017,0157,0000,0176, +}; + +Uchar xxh[26][13] = { + 0045,0150,0154,0162,0042,0246,0210,0147,0152,0103,0230,0017,0206, + 0100,0000,0040,0000,0140,0000,0000,0100,0000,0021,0120,0017,0060, + 0100,0000,0040,0002,0140,0320,0000,0060,0000,0001,0220,0017,0040, + 0100,0001,0120,0001,0241,0000,0000,0100,0000,0020,0140,0017,0060, + 0023,0162,0046,0142,0022,0207,0210,0131,0052,0106,0250,0017,0110, + 0060,0000,0042,0000,0160,0000,0000,0040,0000,0212,0100,0017,0000, + 0140,0000,0040,0002,0140,0000,0000,0120,0000,0040,0120,0017,0040, + 0100,0000,0100,0000,0140,0001,0021,0140,0000,0046,0100,0017,0140, + 0066,0045,0025,0201,0020,0130,0146,0030,0130,0103,0025,0017,0006, + 0100,0000,0040,0000,0020,0000,0000,0040,0000,0000,0200,0017,0000, + 0200,0000,0020,0001,0140,0000,0000,0140,0000,0000,0120,0017,0040, + 0120,0026,0042,0020,0140,0161,0042,0143,0000,0022,0162,0017,0040, + 0121,0042,0060,0020,0140,0200,0000,0123,0000,0021,0220,0017,0041, + 0121,0042,0060,0120,0140,0200,0000,0123,0000,0021,0160,0017,0041, + 0051,0126,0150,0141,0060,0210,0146,0066,0026,0165,0026,0017,0247, + 0120,0000,0040,0003,0160,0000,0000,0140,0000,0021,0100,0017,0140, + 0000,0000,0000,0000,0200,0000,0000,0000,0000,0000,0000,0017,0000, + 0141,0023,0122,0040,0160,0143,0042,0142,0000,0047,0143,0017,0020, + 0120,0000,0040,0006,0140,0060,0000,0141,0000,0026,0100,0017,0040, + 0140,0000,0020,0007,0100,0000,0000,0140,0000,0001,0140,0017,0020, + 0110,0125,0051,0162,0120,0125,0127,0104,0006,0104,0000,0017,0052, + 0140,0000,0040,0000,0160,0000,0000,0140,0000,0000,0060,0017,0000, + 0040,0005,0020,0000,0040,0313,0231,0030,0000,0140,0000,0017,0056, + 0140,0000,0160,0000,0200,0000,0000,0140,0000,0000,0000,0017,0240, + 0065,0042,0060,0040,0000,0206,0231,0146,0006,0224,0220,0017,0004, + 0240,0000,0020,0000,0140,0000,0000,0220,0000,0000,0200,0017,0141, +}; blob - /dev/null blob + 66a98219366827439082bccd8d01a5f2904a6d8d (mode 644) --- /dev/null +++ src/cmd/troff/mbwc.c @@ -0,0 +1,165 @@ +#include + +/* + * Use the FSS-UTF transformation proposed by posix. + * We define 7 byte types: + * T0 0xxxxxxx 7 free bits + * Tx 10xxxxxx 6 free bits + * T1 110xxxxx 5 free bits + * T2 1110xxxx 4 free bits + * + * Encoding is as follows. + * From hex Thru hex Sequence Bits + * 00000000 0000007F T0 7 + * 00000080 000007FF T1 Tx 11 + * 00000800 0000FFFF T2 Tx Tx 16 + */ + +int +mblen(const char *s, size_t n) +{ + + return mbtowc(0, s, n); +} + +int +mbtowc(wchar_t *pwc, const char *s, size_t n) +{ + int c, c1, c2; + long l; + + if(!s) + return 0; + + if(n < 1) + goto bad; + c = s[0] & 0xff; + if((c & 0x80) == 0x00) { + if(pwc) + *pwc = c; + if(c == 0) + return 0; + return 1; + } + + if(n < 2) + goto bad; + c1 = (s[1] ^ 0x80) & 0xff; + if((c1 & 0xC0) != 0x00) + goto bad; + if((c & 0xE0) == 0xC0) { + l = ((c << 6) | c1) & 0x7FF; + if(l < 0x080) + goto bad; + if(pwc) + *pwc = l; + return 2; + } + + if(n < 3) + goto bad; + c2 = (s[2] ^ 0x80) & 0xff; + if((c2 & 0xC0) != 0x00) + goto bad; + if((c & 0xF0) == 0xE0) { + l = ((((c << 6) | c1) << 6) | c2) & 0xFFFF; + if(l < 0x0800) + goto bad; + if(pwc) + *pwc = l; + return 3; + } + + /* + * bad decoding + */ +bad: + return -1; + +} + +int +wctomb(char *s, wchar_t wchar) +{ + long c; + + if(!s) + return 0; + + c = wchar & 0xFFFF; + if(c < 0x80) { + s[0] = c; + return 1; + } + + if(c < 0x800) { + s[0] = 0xC0 | (c >> 6); + s[1] = 0x80 | (c & 0x3F); + return 2; + } + + s[0] = 0xE0 | (c >> 12); + s[1] = 0x80 | ((c >> 6) & 0x3F); + s[2] = 0x80 | (c & 0x3F); + return 3; +} + +size_t +mbstowcs(wchar_t *pwcs, const char *s, size_t n) +{ + int i, d, c; + + for(i=0; i < n; i++) { + c = *s & 0xff; + if(c < 0x80) { + *pwcs = c; + if(c == 0) + break; + s++; + } else { + d = mbtowc(pwcs, s, 3); + if(d <= 0) + return (size_t)((d<0) ? -1 : i); + s += d; + } + pwcs++; + } + return i; +} + +size_t +wcstombs(char *s, const wchar_t *pwcs, size_t n) +{ + int i, d; + long c; + char *p, *pe; + char buf[3]; + + p = s; + pe = p+n-3; + while(p < pe) { + c = *pwcs++; + if(c < 0x80) + *p++ = c; + else + p += wctomb(p, c); + if(c == 0) + return p-s; + } + while(p < pe+3) { + c = *pwcs++; + d = wctomb(buf, c); + if(p+d <= pe+3) { + *p++ = buf[0]; + if(d > 1) { + *p++ = buf[2]; + if(d > 2) + *p++ = buf[3]; + } + } + if(c == 0) + break; + } + return p-s; +} + blob - /dev/null blob + 26b610d6dca329fb9343f912a8dcd39f10e15b47 (mode 644) --- /dev/null +++ src/cmd/troff/mk.log @@ -0,0 +1,136 @@ +9c -c -DUNICODE -DFONTDIR="sys/lib/troff/font" -DNTERMDIR="sys/lib/troff/term/tab." -DTEXHYPHENS="#9/sys/lib/texmf/tex/generic/hyphen/hyphen.tex" -DALTHYPHENS="sys/lib/texmf/tex/generic/hyphen/hyphen.tex" -DDWBHOME="#9/" n1.c +n1.c:51: warning: return type defaults to `int' +n1.c: In function `getch0': +n1.c:676: warning: unused variable `j' +n1.c:719: warning: label `g2' defined but not used +n1.c: In function `get1ch': +n1.c:745: warning: `n' might be used uninitialized in this function +n1.c:745: warning: `c' might be used uninitialized in this function +n1.c: In function `nextfile': +n1.c:830: warning: implicit declaration of function `unsharp' +n1.c:830: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n1.c: At top level: +n1.c:842: warning: return type defaults to `int' +n1.c:875: warning: return type defaults to `int' +n1.c:915: warning: return type defaults to `int' +n1.c: In function `getname': +n1.c:917: warning: unused variable `i' +n1.c: In function `caseso': +n1.c:939: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n1.c:935: warning: unused variable `p' +n1.c:935: warning: unused variable `q' +n1.c:934: warning: `fp' might be used uninitialized in this function +n1.c: In function `casecf': +n1.c:1008: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +9c -c -DUNICODE n2.c +n2.c: In function `outascii': +n2.c:140: warning: unused variable `p' +9c -c -DUNICODE n3.c +n3.c: In function `grow': +n3.c:67: warning: unused variable `new' +n3.c: In function `finds': +n3.c:310: warning: unused variable `j' +n3.c: In function `copyb': +n3.c:372: warning: `savoff' might be used uninitialized in this function +9c -c -DUNICODE n4.c +n4.c: In function `setn': +n4.c:144: warning: int format, long unsigned int arg (arg 3) +9c -c -DUNICODE n5.c +n5.c:83: warning: return type defaults to `int' +n5.c: In function `chget': +n5.c:84: warning: `i' might be used uninitialized in this function +n5.c: At top level: +n5.c:147: warning: return type defaults to `int' +n5.c:338: warning: return type defaults to `int' +n5.c: In function `casefm': +n5.c:411: warning: implicit declaration of function `unsharp' +n5.c:411: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n5.c: At top level: +n5.c:747: warning: return type defaults to `int' +n5.c:835: warning: return type defaults to `int' +9c -c -DUNICODE t6.c +t6.c:18: warning: return type defaults to `int' +t6.c:79: warning: return type defaults to `int' +t6.c:112: warning: return type defaults to `int' +t6.c: In function `t_setch': +t6.c:217: warning: unused variable `j' +t6.c: At top level: +t6.c:288: warning: return type defaults to `int' +t6.c:367: warning: return type defaults to `int' +t6.c: In function `t_setps': +t6.c:397: warning: `j' might be used uninitialized in this function +t6.c: At top level: +t6.c:707: warning: return type defaults to `int' +t6.c: In function `setfp': +t6.c:708: warning: unused variable `sl' +t6.c: In function `casebd': +t6.c:781: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE n6.c +n6.c:11: warning: return type defaults to `int' +n6.c: In function `n_casebd': +n6.c:295: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE n7.c +n7.c: In function `newline': +n7.c:354: warning: `nlss' might be used uninitialized in this function +n7.c: At top level: +n7.c:450: warning: return type defaults to `int' +n7.c:482: warning: return type defaults to `int' +n7.c:509: warning: return type defaults to `int' +n7.c:544: warning: return type defaults to `int' +n7.c:653: warning: return type defaults to `int' +n7.c: In function `getword': +n7.c:654: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE -DTEXHYPHENS="#9/sys/lib/texmf/tex/generic/hyphen/hyphen.tex" n8.c +n8.c:76: warning: return type defaults to `int' +n8.c:87: warning: return type defaults to `int' +n8.c:222: warning: return type defaults to `int' +n8.c:274: warning: return type defaults to `int' +n8.c:282: warning: return type defaults to `int' +n8.c: In function `digram': +n8.c:310: warning: `maxw' might be used uninitialized in this function +n8.c: At top level: +n8.c:346: warning: return type defaults to `int' +n8.c: In function `readpats': +n8.c:469: warning: implicit declaration of function `unsharp' +n8.c:469: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n8.c:470: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +9c -c -DUNICODE n9.c +n9.c:80: warning: return type defaults to `int' +n9.c: In function `setfield': +n9.c:340: warning: `rchar' might be used uninitialized in this function +9c -c -DUNICODE -DTDEVNAME="utf" t10.c +t10.c: In function `ptout0': +t10.c:179: warning: int format, long int arg (arg 3) +t10.c:183: warning: int format, long unsigned int arg (arg 3) +t10.c:303: warning: int format, long int arg (arg 3) +t10.c:157: warning: `w' might be used uninitialized in this function +9c -c -DUNICODE -DTDEVNAME="utf" n10.c +n10.c: In function `getnrfont': +n10.c:77: warning: unused variable `fin' +n10.c:81: warning: unused variable `cmd' +n10.c:80: warning: `code' might be used uninitialized in this function +n10.c: In function `n_ptinit': +n10.c:189: warning: implicit declaration of function `unsharp' +n10.c:189: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n10.c:142: warning: unused variable `cp' +9c -c -DUNICODE t11.c +t11.c:21: warning: return type defaults to `int' +t11.c: In function `getdesc': +t11.c:26: warning: implicit declaration of function `unsharp' +t11.c:26: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c: In function `checkfont': +t11.c:67: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c: At top level: +t11.c:89: warning: return type defaults to `int' +t11.c: In function `getfont': +t11.c:100: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c:94: warning: `nw' might be used uninitialized in this function +t11.c:94: warning: `code' might be used uninitialized in this function +t11.c: At top level: +t11.c:193: warning: return type defaults to `int' +t11.c:235: warning: return type defaults to `int' +9c -c -DUNICODE -DTMACDIR="sys/lib/tmac/tmac." ni.c +9c -c -DUNICODE hytab.c +9c -c -DUNICODE suftab.c +9c -c -DUNICODE -DDWBHOME="#9/" dwbinit.c +9l -o o.troff n1.o n2.o n3.o n4.o n5.o t6.o n6.o n7.o n8.o n9.o t10.o n10.o t11.o ni.o hytab.o suftab.o dwbinit.o /usr/local/plan9/lib/libbio.a /usr/local/plan9/lib/lib9.a blob - /dev/null blob + c02084e7f897fd8b499ba33e0f20fa443086f592 (mode 644) --- /dev/null +++ src/cmd/troff/mkfile @@ -0,0 +1,58 @@ +<$PLAN9/src/mkhdr + +TARG=troff +OFILES=n1.$O\ + n2.$O\ + n3.$O\ + n4.$O\ + n5.$O\ + t6.$O\ + n6.$O\ + n7.$O\ + n8.$O\ + n9.$O\ + t10.$O\ + n10.$O\ + t11.$O\ + ni.$O\ + hytab.$O\ + suftab.$O\ + dwbinit.$O\ + mbwc.$O + +HFILES=tdef.h\ + fns.h\ + ext.h\ + dwbinit.h\ + + +SHORTLIB=bio 9 +<$PLAN9/src/mkone +CFLAGS=-c -DUNICODE + +TMACDIR='"tmac/tmac."' +FONTDIR='"troff/font"' +NTERMDIR='"troff/term/tab."' +ALTHYPHENS='"lib/hyphen.tex"' +TEXHYPHENS='"#9/lib/hyphen.tex"' +DWBHOME='"#9/"' +TDEVNAME='"utf"' +NDEVNAME='"utf"' + +ni.$O: ni.c $HFILES + $CC $CFLAGS -DTMACDIR=$TMACDIR ni.c + +t10.$O: t10.c $HFILES + $CC $CFLAGS -DTDEVNAME=$TDEVNAME t10.c + +n1.$O: n1.c $HFILES + $CC $CFLAGS -DFONTDIR=$FONTDIR -DNTERMDIR=$NTERMDIR -DTEXHYPHENS=$TEXHYPHENS -DALTHYPHENS=$ALTHYPHENS -DDWBHOME=$DWBHOME n1.c + +n10.$O: n10.c $HFILES + $CC $CFLAGS -DTDEVNAME=$NDEVNAME n10.c + +n8.$O: n8.c $HFILES + $CC $CFLAGS -DTEXHYPHENS=$TEXHYPHENS n8.c + +dwbinit.$O: dwbinit.c + $CC $CFLAGS -DDWBHOME=$DWBHOME dwbinit.c blob - /dev/null blob + d0949fe290040b9f947ff871334911a4be5599de (mode 644) --- /dev/null +++ src/cmd/troff/n1.c @@ -0,0 +1,1136 @@ +/* + * n1.c + * + * consume options, initialization, main loop, + * input routines, escape function calling + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" +#include "dwbinit.h" + +#undef MB_CUR_MAX +#define MB_CUR_MAX 3 + +#include +#include + +char *Version = "March 11, 1994"; + +#ifndef DWBVERSION +#define DWBVERSION "???" +#endif + +char *DWBfontdir = FONTDIR; +char *DWBntermdir = NTERMDIR; +char *DWBalthyphens = ALTHYPHENS; +char *DWBhomedir = ""; + +dwbinit dwbpaths[] = { + &DWBfontdir, NULL, 0, + &DWBntermdir, NULL, 0, + &DWBalthyphens, NULL, 0, + &DWBhomedir, NULL, 0, + NULL, nextf, NS, + NULL, NULL, 0 +}; + +int TROFF = 1; /* assume we started in troff... */ + +jmp_buf sjbuf; +Offset ipl[NSO]; + +static FILE *ifile; +static FILE *ifl[NSO]; /* open input file pointers */ +char cfname[NSO+1][NS] = { "stdin" }; /* file name stack */ +int cfline[NSO]; /* input line count stack */ +char *progname; /* program name (troff or nroff) */ + +int trace = 0; /* tracing mode: default off */ +int trace1 = 0; + +main(int argc, char *argv[]) +{ + char *p; + int j; + Tchar i; + char buf[100]; + + ifile = stdin; + ptid = stdout; + + buf[0] = '\0'; /* make sure it's empty (silly 3b2) */ + progname = argv[0]; + if ((p = strrchr(progname, '/')) == NULL) + p = progname; + else + p++; + DWBinit(progname, dwbpaths); + if (strcmp(p, "nroff") == 0) + TROFF = 0; +#ifdef UNICODE + alphabet = 128; /* unicode for plan 9 */ +#endif /*UNICODE*/ + mnspace(); + nnspace(); + mrehash(); + nrehash(); + numtabp[NL].val = -1; + + while (--argc > 0 && (++argv)[0][0] == '-') + switch (argv[0][1]) { + + case 'N': /* ought to be used first... */ + TROFF = 0; + break; + case 'd': + fprintf(stderr, "troff/nroff version %s\n", Version); + break; + case 'F': /* switch font tables from default */ + if (argv[0][2] != '\0') { + strcpy(termtab, &argv[0][2]); + strcpy(fontdir, &argv[0][2]); + } else { + argv++; argc--; + strcpy(termtab, argv[0]); + strcpy(fontdir, argv[0]); + } + break; + case 0: + goto start; + case 'i': + stdi++; + break; + case 'n': + npn = atoi(&argv[0][2]); + break; + case 'u': /* set emboldening amount */ + bdtab[3] = atoi(&argv[0][2]); + if (bdtab[3] < 0 || bdtab[3] > 50) + bdtab[3] = 0; + break; + case 's': + if (!(stop = atoi(&argv[0][2]))) + stop++; + break; + case 'r': + sprintf(buf + strlen(buf), ".nr %c %s\n", + argv[0][2], &argv[0][3]); + /* not yet cpushback(buf);*/ + /* dotnr(&argv[0][2], &argv[0][3]); */ + break; + case 'm': + if (mflg++ >= NMF) { + ERROR "Too many macro packages: %s", argv[0] WARN; + break; + } + strcpy(mfiles[nmfi], nextf); + strcat(mfiles[nmfi++], &argv[0][2]); + break; + case 'o': + getpn(&argv[0][2]); + break; + case 'T': + strcpy(devname, &argv[0][2]); + dotT++; + break; + case 'a': + ascii = 1; + break; + case 'h': + hflg++; + break; + case 'e': + eqflg++; + break; + case 'q': + quiet++; + save_tty(); + break; + case 'V': + fprintf(stdout, "%croff: DWB %s\n", + TROFF ? 't' : 'n', DWBVERSION); + exit(0); + case 't': + if (argv[0][2] != '\0') + trace = trace1 = argv[0][2]; + break; /* for the sake of compatibility */ + default: + ERROR "unknown option %s", argv[0] WARN; + done(02); + } + +start: + /* + * cpushback maintains a LIFO, so push pack the -r arguments + * in reverse order to maintain a FIFO in case someone did -rC1 -rC3 + */ + if (buf[0]) { + char *p = buf; + while(*p++) + ; + while(p > buf) { + while(strncmp(p, ".nr", 3) != 0) + p--; + cpushback(p); + *p-- = '\0'; + } + } + argp = argv; + rargc = argc; + nmfi = 0; + init2(); + setjmp(sjbuf); +loop: + copyf = lgf = nb = nflush = nlflg = 0; + if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl && dip == d) { + nflush++; + trap = 0; + eject((Stack *)0); + goto loop; + } + i = getch(); + if (pendt) + goto Lt; + if ((j = cbits(i)) == XPAR) { + copyf++; + tflg++; + while (cbits(i) != '\n') + pchar(i = getch()); + tflg = 0; + copyf--; + goto loop; + } + if (j == cc || j == c2) { + if (j == c2) + nb++; + copyf++; + while ((j = cbits(i = getch())) == ' ' || j == '\t') + ; + ch = i; + copyf--; + control(getrq(), 1); + flushi(); + goto loop; + } +Lt: + ch = i; + text(); + if (nlflg) + numtabp[HP].val = 0; + goto loop; +} + + + +void init2(void) +{ + int i; + char buf[100]; + + for (i = NTRTAB; --i; ) + trtab[i] = i; + trtab[UNPAD] = ' '; + iflg = 0; + obufp = obuf; + if (TROFF) + t_ptinit(); + else + n_ptinit(); + mchbits(); + cvtime(); + numtabp[PID].val = getpid(); + numtabp[HP].val = init = 0; + numtabp[NL].val = -1; + nfo = 0; + copyf = raw = 0; + sprintf(buf, ".ds .T %s\n", devname); + cpushback(buf); + sprintf(buf, ".ds .P %s\n", DWBhomedir); + cpushback(buf); + numtabp[CD].val = -1; /* compensation */ + nx = mflg; + frame = stk = (Stack *)setbrk(STACKSIZE); + dip = &d[0]; + nxf = frame + 1; + for (i = 1; i < NEV; i++) /* propagate the environment */ + envcopy(&env[i], &env[0]); + for (i = 0; i < NEV; i++) { + if ((env[i]._word._bufp = (Tchar *)calloc(WDSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for word buffers" WARN; + done2(1); + } + env[i]._word._size = WDSIZE; + if ((env[i]._line._bufp = (Tchar *)calloc(LNSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for line buffers" WARN; + done2(1); + } + env[i]._line._size = LNSIZE; + } + if ((oline = (Tchar *)calloc(OLNSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for line buffers" WARN; + done2(1); + } + olinep = oline; + olnsize = OLNSIZE; + blockinit(); +} + +void cvtime(void) +{ + long tt; + struct tm *ltime; + + time(&tt); + ltime = localtime(&tt); + numtabp[YR].val = ltime->tm_year % 100; + numtabp[YR].fmt = 2; + numtabp[MO].val = ltime->tm_mon + 1; /* troff uses 1..12 */ + numtabp[DY].val = ltime->tm_mday; + numtabp[DW].val = ltime->tm_wday + 1; /* troff uses 1..7 */ +} + + + +char errbuf[200]; + +void errprint(void) /* error message printer */ +{ + int savecd = numtabp[CD].val; + + if (!nlflg) + numtabp[CD].val++; + + fprintf(stderr, "%s: ", progname); + fputs(errbuf, stderr); + if (cfname[ifi][0]) + fprintf(stderr, "; %s:%d", cfname[ifi], numtabp[CD].val); + fputs("\n", stderr); + if (cfname[ifi][0]) + stackdump(); + numtabp[CD].val = savecd; +} + + +int control(int a, int b) +{ + int j, k; + extern Contab *contabp; + + numerr.type = RQERR; + numerr.req = a; + if (a == 0 || (j = findmn(a)) == -1) + return(0); + if (contabp[j].f == 0) { + if (trace & TRMAC) + fprintf(stderr, "invoke macro %s\n", unpair(a)); + if (dip != d) + for (k = dilev; k; k--) + if (d[k].curd == a) { + ERROR "diversion %s invokes itself during diversion", + unpair(a) WARN; + edone(0100); + } + nxf->nargs = 0; + if (b) + collect(); + flushi(); + return pushi(contabp[j].mx, a); /* BUG??? all that matters is 0/!0 */ + } + if (b) { + if (trace & TRREQ) + fprintf(stderr, "invoke request %s\n", unpair(a)); + (*contabp[j].f)(); + } + return(0); +} + +void casept(void) +{ + int i; + + noscale++; + if (skip()) + i = trace1; + else { + i = max(inumb(&trace), 0); + if (nonumb) + i = trace1; + } + trace1 = trace; + trace = i; + noscale = 0; +} + + +int getrq(void) +{ + int i, j; + + if ((i = getach()) == 0 || (j = getach()) == 0) + goto rtn; + i = PAIR(i, j); +rtn: + return(i); +} + +/* + * table encodes some special characters, to speed up tests + * in getch, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch + */ + +char gchtab[NCHARS] = { + 000,004,000,000,010,000,000,000, /* fc, ldr */ + 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */ + 000,000,000,000,000,000,000,000, + 000,001,000,001,000,000,000,000, /* FLSS, ESC */ + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,001,000, /* f */ + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, +}; + +int realcbits(Tchar c) /* return character bits, or MOTCH if motion */ +{ + if (ismot(c)) + return MOTCH; + else + return c & 0xFFFF; +} + +Tchar getch(void) +{ + int k; + Tchar i, j; + +g0: + if (ch) { + i = ch; + if (cbits(i) == '\n') + nlflg++; + ch = 0; + return(i); + } + + if (nlflg) + return('\n'); + i = getch0(); + if (ismot(i)) + return(i); + k = cbits(i); + if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0) /* nothing special */ + return(i); + if (k != ESC) { + if (k == '\n') { + nlflg++; + if (ip == 0) + numtabp[CD].val++; /* line number */ + return(k); + } + if (k == FLSS) { + copyf++; + raw++; + i = getch0(); + if (!fi) + flss = i; + copyf--; + raw--; + goto g0; + } + if (k == RPT) { + setrpt(); + goto g0; + } + if (!copyf) { + if (k == 'f' && lg && !lgf) { + i = getlg(i); + return(i); + } + if (k == fc || k == tabch || k == ldrch) { + if ((i = setfield(k)) == 0) + goto g0; + else + return(i); + } + if (k == '\b') { + i = makem(-width(' ' | chbits)); + return(i); + } + } + return(i); + } + + k = cbits(j = getch0()); + if (ismot(j)) + return(j); + + switch (k) { + case 'n': /* number register */ + setn(); + goto g0; + case '$': /* argument indicator */ + seta(); + goto g0; + case '*': /* string indicator */ + setstr(); + goto g0; + case '{': /* LEFT */ + i = LEFT; + goto gx; + case '}': /* RIGHT */ + i = RIGHT; + goto gx; + case '"': /* comment */ + while (cbits(i = getch0()) != '\n') + ; + if (ip == 0) + numtabp[CD].val++; /* line number */ + nlflg++; + return(i); + +/* experiment: put it here instead of copy mode */ + case '(': /* special char name \(xx */ + case 'C': /* \C'...' */ + if ((i = setch(k)) == 0) + goto g0; + goto gx; + + case ESC: /* double backslash */ + i = eschar; + goto gx; + case 'e': /* printable version of current eschar */ + i = PRESC; + goto gx; + case '\n': /* concealed newline */ + numtabp[CD].val++; + goto g0; + case ' ': /* unpaddable space */ + i = UNPAD; + goto gx; + case '\'': /* \(aa */ + i = ACUTE; + goto gx; + case '`': /* \(ga */ + i = GRAVE; + goto gx; + case '_': /* \(ul */ + i = UNDERLINE; + goto gx; + case '-': /* current font minus */ + i = MINUS; + goto gx; + case '&': /* filler */ + i = FILLER; + goto gx; + case 'c': /* to be continued */ + i = CONT; + goto gx; + case '!': /* transparent indicator */ + i = XPAR; + goto gx; + case 't': /* tab */ + i = '\t'; + return(i); + case 'a': /* leader (SOH) */ +/* old: *pbp++ = LEADER; goto g0; */ + i = LEADER; + return i; + case '%': /* ohc */ + i = OHC; + return(i); + case 'g': /* return format of a number register */ + setaf(); /* should this really be in copy mode??? */ + goto g0; + case '.': /* . */ + i = '.'; +gx: + setsfbits(i, sfbits(j)); + return(i); + } + if (copyf) { + *pbp++ = j; + return(eschar); + } + switch (k) { + + case 'f': /* font indicator */ + setfont(0); + goto g0; + case 's': /* size indicator */ + setps(); + goto g0; + case 'v': /* vert mot */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = vmot()) { + return(i); + } + goto g0; + case 'h': /* horiz mot */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = hmot()) + return(i); + goto g0; + case '|': /* narrow space */ + if (NROFF) + goto g0; + return(makem((int)(EM)/6)); + case '^': /* half narrow space */ + if (NROFF) + goto g0; + return(makem((int)(EM)/12)); + case 'w': /* width function */ + setwd(); + goto g0; + case 'p': /* spread */ + spread++; + goto g0; + case 'N': /* absolute character number */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if ((i = setabs()) == 0) + goto g0; + return i; + case 'H': /* character height */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + return(setht()); + case 'S': /* slant */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + return(setslant()); + case 'z': /* zero with char */ + return(setz()); + case 'l': /* hor line */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setline(); + goto g0; + case 'L': /* vert line */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setvline(); + goto g0; + case 'D': /* drawing function */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setdraw(); + goto g0; + case 'X': /* \X'...' for copy through */ + setxon(); + goto g0; + case 'b': /* bracket */ + setbra(); + goto g0; + case 'o': /* overstrike */ + setov(); + goto g0; + case 'k': /* mark hor place */ + if ((k = findr(getsn())) != -1) { + numtabp[k].val = numtabp[HP].val; + } + goto g0; + case '0': /* number space */ + return(makem(width('0' | chbits))); + case 'x': /* extra line space */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = xlss()) + return(i); + goto g0; + case 'u': /* half em up */ + case 'r': /* full em up */ + case 'd': /* half em down */ + return(sethl(k)); + default: + return(j); + } + /* NOTREACHED */ +} + +void setxon(void) /* \X'...' for copy through */ +{ + Tchar xbuf[NC]; + Tchar *i; + Tchar c; + int delim, k; + + if (ismot(c = getch())) + return; + delim = cbits(c); + i = xbuf; + *i++ = XON | chbits; + while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) { + if (k == ' ') + setcbits(c, WORDSP); + *i++ = c | ZBIT; + } + *i++ = XOFF | chbits; + *i = 0; + pushback(xbuf); +} + + +char ifilt[32] = { 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012 }; + +Tchar getch0(void) +{ + int j; + Tchar i; + +again: + if (pbp > lastpbp) + i = *--pbp; + else if (ip) { + /* i = rbf(); */ + i = rbf0(ip); + if (i == 0) + i = rbf(); + else { + ++ip; + if (pastend(ip)) { + --ip; + rbf(); + } + } + } else { + if (donef || ndone) + done(0); + if (nx || 1) { /* BUG: was ibufp >= eibuf, so EOF test is wrong */ + if (nfo < 0) + ERROR "in getch0, nfo = %d", nfo WARN; + if (nfo == 0) { +g0: + if (nextfile()) { + if (ip) + goto again; + } + } + nx = 0; +#ifdef UNICODE + if (MB_CUR_MAX > 1) + i = get1ch(ifile); + else +#endif /*UNICODE*/ + i = getc(ifile); + if (i == EOF) + goto g0; + if (ip) + goto again; + } +g2: + if (i >= 040) /* zapped: && i < 0177 */ + goto g4; + i = ifilt[i]; + } + if (cbits(i) == IMP && !raw) + goto again; + if (i == 0 && !init && !raw) { /* zapped: || i == 0177 */ + goto again; + } +g4: + if (ismot(i)) + return i; + if (copyf == 0 && sfbits(i) == 0) + i |= chbits; + if (cbits(i) == eschar && !raw) + setcbits(i, ESC); + return(i); +} + + +#ifdef UNICODE +Tchar get1ch(FILE *fp) /* get one "character" from input, figure out what alphabet */ +{ + wchar_t wc; + char buf[100], *p; + int i, n, c; + + for (i = 0, p = buf; i < MB_CUR_MAX; i++) { + if ((c = getc(fp)) == EOF) + return c; + *p++ = c; + if ((n = mbtowc(&wc, buf, p-buf)) >= 0) + break; + } + if (n == 1) /* real ascii, presumably */ + return wc; + if (n == 0) + return p[-1]; /* illegal, but what else to do? */ + if (c == EOF) + return EOF; + *p = 0; + return chadd(buf, MBchar, Install); /* add name even if haven't seen it */ +} +#endif /*UNICODE*/ + +void pushback(Tchar *b) +{ + Tchar *ob = b; + + while (*b++) + ; + b--; + while (b > ob && pbp < &pbbuf[NC-3]) + *pbp++ = *--b; + if (pbp >= &pbbuf[NC-3]) { + ERROR "pushback overflow" WARN; + done(2); + } +} + +void cpushback(char *b) +{ + char *ob = b; + + while (*b++) + ; + b--; + while (b > ob && pbp < &pbbuf[NC-3]) + *pbp++ = *--b; + if (pbp >= &pbbuf[NC-3]) { + ERROR "cpushback overflow" WARN; + done(2); + } +} + +int nextfile(void) +{ + char *p; + +n0: + if (ifile != stdin) + fclose(ifile); + if (ifi > 0 && !nx) { + if (popf()) + goto n0; /* popf error */ + return(1); /* popf ok */ + } + if (nx || nmfi < mflg) { + p = mfiles[nmfi++]; + if (*p != 0) + goto n1; + } + if (rargc-- <= 0) { + if ((nfo -= mflg) && !stdi) { + done(0); +} + nfo++; + numtabp[CD].val = stdi = mflg = 0; + ifile = stdin; + strcpy(cfname[ifi], "stdin"); + return(0); + } + p = (argp++)[0]; + if (rargc >= 0) + cfname[ifi][0] = 0; +n1: + numtabp[CD].val = 0; + if (p[0] == '-' && p[1] == 0) { + ifile = stdin; + strcpy(cfname[ifi], "stdin"); + } else if ((ifile = fopen(unsharp(p), "r")) == NULL) { + ERROR "cannot open file %s", p WARN; + nfo -= mflg; + done(02); + } else + strcpy(cfname[ifi],p); + nfo++; + return(0); +} + + +popf(void) +{ + --ifi; + if (ifi < 0) { + ERROR "popf went negative" WARN; + return 1; + } + numtabp[CD].val = cfline[ifi]; /* restore line counter */ + ip = ipl[ifi]; /* input pointer */ + ifile = ifl[ifi]; /* input FILE * */ + return(0); +} + + +void flushi(void) +{ + if (nflush) + return; + ch = 0; + copyf++; + while (!nlflg) { + if (donef && frame == stk) + break; + getch(); + } + copyf--; +} + +/* + * return 16-bit, ascii/alphabetic character, ignore chars with more bits, + * (internal names), spaces and special cookies (below 040). + * Leave STX ETX ENQ ACK and BELL in to maintain compatibility with v7 troff. + */ +getach(void) +{ + Tchar i; + int j; + + lgf++; + j = cbits(i = getch()); + if (ismot(i) + || j > SHORTMASK + || (j <= 040 && j != 002 /*STX*/ + && j != 003 /*ETX*/ + && j != 005 /*ENQ*/ + && j != 006 /*ACK*/ + && j != 007)) { /*BELL*/ + ch = i; + j = 0; + } + lgf--; + return j; +} + + +void casenx(void) +{ + lgf++; + skip(); + getname(); + nx++; + if (nmfi > 0) + nmfi--; + strcpy(mfiles[nmfi], nextf); + nextfile(); + nlflg++; + ip = 0; + pendt = 0; + frame = stk; + nxf = frame + 1; +} + + +getname(void) +{ + int j, k; + Tchar i; + + lgf++; + for (k = 0; k < NS - 1; k++) { + j = getach(); + if (!j) + break; + nextf[k] = j; + } + nextf[k] = 0; + lgf--; + return(nextf[0]); +} + + +void caseso(void) +{ + FILE *fp; + char *p, *q; + + lgf++; + nextf[0] = 0; + if (skip() || !getname() || (fp = fopen(unsharp(nextf), "r")) == NULL || ifi >= NSO) { + ERROR "can't open file %s", nextf WARN; + done(02); + } + strcpy(cfname[ifi+1], nextf); + cfline[ifi] = numtabp[CD].val; /*hold line counter*/ + numtabp[CD].val = 0; + flushi(); + ifl[ifi] = ifile; + ifile = fp; + ipl[ifi] = ip; + ip = 0; + nx++; + nflush++; + ifi++; +} + +void caself(void) /* set line number and file */ +{ + int n; + + if (skip()) + return; + n = atoi0(); + if (!nonumb) + cfline[ifi] = numtabp[CD].val = n - 1; + if (!skip()) + if (getname()) { /* eats '\n' ? */ + strcpy(cfname[ifi], nextf); + if (!nonumb) + numtabp[CD].val--; + } +} + +void cpout(FILE *fin, char *token) +{ + int n; + char buf[1024]; + + if (token) { /* BUG: There should be no NULL bytes in input */ + char *newl = buf; + while ((fgets(buf, sizeof buf, fin)) != NULL) { + if (newl) { + numtabp[CD].val++; /* line number */ + if (strcmp(token, buf) == 0) + return; + } + newl = strchr(buf, '\n'); + fputs(buf, ptid); + } + } else { + while ((n = fread(buf, sizeof *buf, sizeof buf, fin)) > 0) + fwrite(buf, n, 1, ptid); + fclose(fin); + } +} + +void casecf(void) +{ /* copy file without change */ + FILE *fd; + char *eof, *p; + extern int hpos, esc, po; + + /* this may not make much sense in nroff... */ + + lgf++; + nextf[0] = 0; + if (!skip() && getname()) { + if (strncmp("<<", nextf, 2) != 0) { + if ((fd = fopen(unsharp(nextf), "r")) == NULL) { + ERROR "can't open file %s", nextf WARN; + done(02); + } + eof = (char *) NULL; + } else { /* current file */ + if (pbp > lastpbp || ip) { + ERROR "casecf: not reading from file" WARN; + done(02); + } + eof = &nextf[2]; + if (!*eof) { + ERROR "casecf: missing end of input token" WARN; + done(02); + } + p = eof; + while(*++p) + ; + *p++ = '\n'; + *p = 0; + fd = ifile; + } + } else { + ERROR "casecf: no argument" WARN; + lgf--; + return; + } + lgf--; + + /* make it into a clean state, be sure that everything is out */ + tbreak(); + hpos = po; + esc = 0; + ptesc(); /* to left margin */ + esc = un; + ptesc(); + ptlead(); + ptps(); + ptfont(); + flusho(); + cpout(fd, eof); + ptps(); + ptfont(); +} + +void getline(char *s, int n) /* get rest of input line into s */ +{ + int i; + + lgf++; + copyf++; + skip(); + for (i = 0; i < n-1; i++) + if ((s[i] = cbits(getch())) == '\n' || s[i] == RIGHT) + break; + s[i] = 0; + copyf--; + lgf--; +} + +void casesy(void) /* call system */ +{ + char sybuf[NTM]; + + getline(sybuf, NTM); + system(sybuf); +} + + +void getpn(char *a) +{ + int n, neg; + + if (*a == 0) + return; + neg = 0; + for ( ; *a; a++) + switch (*a) { + case '+': + case ',': + continue; + case '-': + neg = 1; + continue; + default: + n = 0; + if (isdigit(*a)) { + do + n = 10 * n + *a++ - '0'; + while (isdigit(*a)); + a--; + } else + n = 9999; + *pnp++ = neg ? -n : n; + neg = 0; + if (pnp >= &pnlist[NPN-2]) { + ERROR "too many page numbers" WARN; + done3(-3); + } + } + if (neg) + *pnp++ = -9999; + *pnp = -INT_MAX; + print = 0; + pnp = pnlist; + if (*pnp != -INT_MAX) + chkpn(); +} + + +void setrpt(void) +{ + Tchar i, j; + + copyf++; + raw++; + i = getch0(); + copyf--; + raw--; + if ((long) i < 0 || cbits(j = getch0()) == RPT) + return; + while (i > 0 && pbp < &pbbuf[NC-3]) { + i--; + *pbp++ = j; + } +} blob - /dev/null blob + 0183cadc41cc2d88f9e34bb4787ae2bb5814faa3 (mode 644) --- /dev/null +++ src/cmd/troff/n10.c @@ -0,0 +1,549 @@ +/* +n10.c + +Device interfaces +*/ + +#include "tdef.h" +#include "ext.h" +#include "fns.h" +#include + +Term t; /* terminal characteristics */ + +int dtab; +int plotmode; +int esct; + +enum { Notype = 0, Type = 1 }; + +static char *parse(char *s, int typeit) /* convert \0, etc to nroff driving table format */ +{ /* typeit => add a type id to the front for later use */ + static char buf[100], *t, *obuf; + int quote = 0; + wchar_t wc; + + obuf = typeit == Type ? buf : buf+1; +#ifdef UNICODE + if (mbtowc(&wc, s, strlen(s)) > 1) { /* it's multibyte, */ + buf[0] = MBchar; + strcpy(buf+1, s); + return obuf; + } /* so just hand it back */ +#endif /*UNICODE*/ + buf[0] = Troffchar; + t = buf + 1; + if (*s == '"') { + s++; + quote = 1; + } + for (;;) { + if (quote && *s == '"') { + s++; + break; + } + if (!quote && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\0')) + break; + if (*s != '\\') + *t++ = *s++; + else { + s++; /* skip \\ */ + if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) { + *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; + s += 2; + } else if (isdigit(s[0])) { + *t++ = *s - '0'; + } else if (*s == 'b') { + *t++ = '\b'; + } else if (*s == 'n') { + *t++ = '\n'; + } else if (*s == 'r') { + *t++ = '\r'; + } else if (*s == 't') { + *t++ = '\t'; + } else { + *t++ = *s; + } + s++; + } + } + *t = '\0'; + return obuf; +} + + +static int getnrfont(FILE *fp) /* read the nroff description file */ +{ + FILE *fin; + Chwid chtemp[NCHARS]; + static Chwid chinit; + int i, nw, n, wid, code, type; + char buf[100], ch[100], s1[100], s2[100], cmd[300]; + wchar_t wc; + + + chinit.wid = 1; + chinit.str = ""; + for (i = 0; i < ALPHABET; i++) { + chtemp[i] = chinit; /* zero out to begin with */ + chtemp[i].num = chtemp[i].code = i; /* every alphabetic character is itself */ + chtemp[i].wid = 1; /* default ascii widths */ + } + skipline(fp); + nw = ALPHABET; + while (fgets(buf, sizeof buf, fp) != NULL) { + sscanf(buf, "%s %s %[^\n]", ch, s1, s2); + if (!eq(s1, "\"")) { /* genuine new character */ + sscanf(s1, "%d", &wid); + } /* else it's a synonym for prev character, */ + /* so leave previous values intact */ + + /* decide what kind of alphabet it might come from */ + + if (strlen(ch) == 1) { /* it's ascii */ + n = ch[0]; /* origin includes non-graphics */ + chtemp[n].num = ch[0]; + } else if (ch[0] == '\\' && ch[1] == '0') { + n = strtol(ch+1, 0, 0); /* \0octal or \0xhex */ + chtemp[n].num = n; +#ifdef UNICODE + } else if (mbtowc(&wc, ch, strlen(ch)) > 1) { + chtemp[nw].num = chadd(ch, MBchar, Install); + n = nw; + nw++; +#endif /*UNICODE*/ + } else { + if (strcmp(ch, "---") == 0) { /* no name */ + sprintf(ch, "%d", code); + type = Number; + } else + type = Troffchar; +/* BUG in here somewhere when same character occurs twice in table */ + chtemp[nw].num = chadd(ch, type, Install); + n = nw; + nw++; + } + chtemp[n].wid = wid; + chtemp[n].str = strdupl(parse(s2, Type)); + } + t.tfont.nchars = nw; + t.tfont.wp = (Chwid *) malloc(nw * sizeof(Chwid)); + if (t.tfont.wp == NULL) + return -1; + for (i = 0; i < nw; i++) + t.tfont.wp[i] = chtemp[i]; + return 1; +} + + +void n_ptinit(void) +{ + int i; + char *p, *cp; + char opt[50], cmd[100]; + FILE *fp; + + hmot = n_hmot; + makem = n_makem; + setabs = n_setabs; + setch = n_setch; + sethl = n_sethl; + setht = n_setht; + setslant = n_setslant; + vmot = n_vmot; + xlss = n_xlss; + findft = n_findft; + width = n_width; + mchbits = n_mchbits; + ptlead = n_ptlead; + ptout = n_ptout; + ptpause = n_ptpause; + setfont = n_setfont; + setps = n_setps; + setwd = n_setwd; + + if ((p = getenv("NROFFTERM")) != 0) + strcpy(devname, p); + if (termtab[0] == 0) + strcpy(termtab,DWBntermdir); + if (fontdir[0] == 0) + strcpy(fontdir, ""); + if (devname[0] == 0) + strcpy(devname, NDEVNAME); + pl = 11*INCH; + po = PO; + hyf = 0; + ascii = 1; + lg = 0; + fontlab[1] = 'R'; + fontlab[2] = 'I'; + fontlab[3] = 'B'; + fontlab[4] = PAIR('B','I'); + fontlab[5] = 'D'; + bdtab[3] = 3; + bdtab[4] = 3; + + /* hyphalg = 0; /* for testing */ + + strcat(termtab, devname); + if ((fp = fopen(unsharp(termtab), "r")) == NULL) { + ERROR "cannot open %s", termtab WARN; + exit(-1); + } + + +/* this loop isn't robust about input format errors. */ +/* it assumes name, name-value pairs..., charset */ +/* god help us if we get out of sync. */ + + fscanf(fp, "%s", cmd); /* should be device name... */ + if (!is(devname) && trace) + ERROR "wrong terminal name: saw %s, wanted %s", cmd, devname WARN; + for (;;) { + fscanf(fp, "%s", cmd); + if (is("charset")) + break; + fscanf(fp, " %[^\n]", opt); + if (is("bset")) t.bset = atoi(opt); + else if (is("breset")) t.breset = atoi(opt); + else if (is("Hor")) t.Hor = atoi(opt); + else if (is("Vert")) t.Vert = atoi(opt); + else if (is("Newline")) t.Newline = atoi(opt); + else if (is("Char")) t.Char = atoi(opt); + else if (is("Em")) t.Em = atoi(opt); + else if (is("Halfline")) t.Halfline = atoi(opt); + else if (is("Adj")) t.Adj = atoi(opt); + else if (is("twinit")) t.twinit = strdupl(parse(opt, Notype)); + else if (is("twrest")) t.twrest = strdupl(parse(opt, Notype)); + else if (is("twnl")) t.twnl = strdupl(parse(opt, Notype)); + else if (is("hlr")) t.hlr = strdupl(parse(opt, Notype)); + else if (is("hlf")) t.hlf = strdupl(parse(opt, Notype)); + else if (is("flr")) t.flr = strdupl(parse(opt, Notype)); + else if (is("bdon")) t.bdon = strdupl(parse(opt, Notype)); + else if (is("bdoff")) t.bdoff = strdupl(parse(opt, Notype)); + else if (is("iton")) t.iton = strdupl(parse(opt, Notype)); + else if (is("itoff")) t.itoff = strdupl(parse(opt, Notype)); + else if (is("ploton")) t.ploton = strdupl(parse(opt, Notype)); + else if (is("plotoff")) t.plotoff = strdupl(parse(opt, Notype)); + else if (is("up")) t.up = strdupl(parse(opt, Notype)); + else if (is("down")) t.down = strdupl(parse(opt, Notype)); + else if (is("right")) t.right = strdupl(parse(opt, Notype)); + else if (is("left")) t.left = strdupl(parse(opt, Notype)); + else + ERROR "bad tab.%s file, %s %s", devname, cmd, opt WARN; + } + + getnrfont(fp); + fclose(fp); + + sps = EM; + ics = EM * 2; + dtab = 8 * t.Em; + for (i = 0; i < 16; i++) + tabtab[i] = dtab * (i + 1); + pl = 11 * INCH; + po = PO; + spacesz = SS; + lss = lss1 = VS; + ll = ll1 = lt = lt1 = LL; + smnt = nfonts = 5; /* R I B BI S */ + n_specnames(); /* install names like "hyphen", etc. */ + if (eqflg) + t.Adj = t.Hor; +} + + +void n_specnames(void) +{ + + int i; + + for (i = 0; spnames[i].n; i++) + *spnames[i].n = chadd(spnames[i].v, Troffchar, Install); + if (c_isalnum == 0) + c_isalnum = NROFFCHARS; +} + +void twdone(void) +{ + if (!TROFF && t.twrest) { + obufp = obuf; + oputs(t.twrest); + flusho(); + if (pipeflg) { + pclose(ptid); + } + restore_tty(); + } +} + + +void n_ptout(Tchar i) +{ + *olinep++ = i; + if (olinep >= &oline[LNSIZE]) + olinep--; + if (cbits(i) != '\n') + return; + olinep--; + lead += dip->blss + lss - t.Newline; + dip->blss = 0; + esct = esc = 0; + if (olinep > oline) { + move(); + ptout1(); + oputs(t.twnl); + } else { + lead += t.Newline; + move(); + } + lead += dip->alss; + dip->alss = 0; + olinep = oline; +} + + +void ptout1(void) +{ + int k; + char *codep; + int w, j, phyw; + Tchar *q, i; + static int oxfont = FT; /* start off in roman */ + + for (q = oline; q < olinep; q++) { + i = *q; + if (ismot(i)) { + j = absmot(i); + if (isnmot(i)) + j = -j; + if (isvmot(i)) + lead += j; + else + esc += j; + continue; + } + if ((k = cbits(i)) <= ' ') { + switch (k) { + case ' ': /*space*/ + esc += t.Char; + break; + case '\033': + case '\007': + case '\016': + case '\017': + oput(k); + break; + } + continue; + } + phyw = w = t.Char * t.tfont.wp[k].wid; + if (iszbit(i)) + w = 0; + if (esc || lead) + move(); + esct += w; + xfont = fbits(i); + if (xfont != oxfont) { + switch (oxfont) { + case ULFONT: oputs(t.itoff); break; + case BDFONT: oputs(t.bdoff); break; + case BIFONT: oputs(t.itoff); oputs(t.bdoff); break; + } + switch (xfont) { + case ULFONT: + if (*t.iton & 0377) oputs(t.iton); break; + case BDFONT: + if (*t.bdon & 0377) oputs(t.bdon); break; + case BIFONT: + if (*t.bdon & 0377) oputs(t.bdon); + if (*t.iton & 0377) oputs(t.iton); + break; + } + oxfont = xfont; + } + if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) { + for (j = w / t.Char; j > 0; j--) + oput('_'); + for (j = w / t.Char; j > 0; j--) + oput('\b'); + } + if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT)) + j++; + else + j = 1; /* number of overstrikes for bold */ + if (k < ALPHABET) { /* ordinary ascii */ + oput(k); + while (--j > 0) { + oput('\b'); + oput(k); + } + } else if (k >= t.tfont.nchars) { /* BUG -- not really understood */ +/* fprintf(stderr, "big char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str == 0) { +/* fprintf(stderr, "nostr char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str[0] == MBchar) { /* parse() puts this on */ +/* fprintf(stderr, "MBstr char %d, name %s\n", k, chname(k)); /* */ + oputs(t.tfont.wp[k].str+1); + } else { + int oj = j; +/* fprintf(stderr, "str char %d, name %s\n", k, chname(k)); /* */ + codep = t.tfont.wp[k].str+1; /* Troffchar by default */ + while (*codep != 0) { + if (*codep & 0200) { + codep = plot(codep); + oput(' '); + } else { + if (*codep == '%') /* escape */ + codep++; + oput(*codep); + if (*codep == '\033') + oput(*++codep); + else if (*codep != '\b') + for (j = oj; --j > 0; ) { + oput('\b'); + oput(*codep); + } + codep++; + } + } + } + if (!w) + for (j = phyw / t.Char; j > 0; j--) + oput('\b'); + } +} + + +char *plot(char *x) +{ + int i; + char *j, *k; + + oputs(t.ploton); + k = x; + if ((*k & 0377) == 0200) + k++; + for (; *k; k++) { + if (*k == '%') { /* quote char within plot mode */ + oput(*++k); + } else if (*k & 0200) { + if (*k & 0100) { + if (*k & 040) + j = t.up; + else + j = t.down; + } else { + if (*k & 040) + j = t.left; + else + j = t.right; + } + if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ + ++k; + break; + } + while (i--) + oputs(j); + } else + oput(*k); + } + oputs(t.plotoff); + return(k); +} + + +void move(void) +{ + int k; + char *i, *j; + char *p, *q; + int iesct, dt; + + iesct = esct; + if (esct += esc) + i = "\0"; + else + i = "\n\0"; + j = t.hlf; + p = t.right; + q = t.down; + if (lead) { + if (lead < 0) { + lead = -lead; + i = t.flr; + /* if(!esct)i = t.flr; else i = "\0";*/ + j = t.hlr; + q = t.up; + } + if (*i & 0377) { + k = lead / t.Newline; + lead = lead % t.Newline; + while (k--) + oputs(i); + } + if (*j & 0377) { + k = lead / t.Halfline; + lead = lead % t.Halfline; + while (k--) + oputs(j); + } else { /* no half-line forward, not at line begining */ + k = lead / t.Newline; + lead = lead % t.Newline; + if (k > 0) + esc = esct; + i = "\n"; + while (k--) + oputs(i); + } + } + if (esc) { + if (esc < 0) { + esc = -esc; + j = "\b"; + p = t.left; + } else { + j = " "; + if (hflg) + while ((dt = dtab - (iesct % dtab)) <= esc) { + if (dt % t.Em) + break; + oput(TAB); + esc -= dt; + iesct += dt; + } + } + k = esc / t.Em; + esc = esc % t.Em; + while (k--) + oputs(j); + } + if ((*t.ploton & 0377) && (esc || lead)) { + oputs(t.ploton); + esc /= t.Hor; + lead /= t.Vert; + while (esc--) + oputs(p); + while (lead--) + oputs(q); + oputs(t.plotoff); + } + esc = lead = 0; +} + + +void n_ptlead(void) +{ + move(); +} + + +void n_ptpause(void ) +{ + char junk; + + flusho(); + read(2, &junk, 1); +} blob - /dev/null blob + 8164c0387ca2cc8077c19111e02fb52fffe1a51f (mode 644) --- /dev/null +++ src/cmd/troff/n2.c @@ -0,0 +1,325 @@ +/* + * n2.c + * + * output, cleanup + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" +#include + +#ifdef STRICT + /* not in ANSI or POSIX */ +FILE* popen(char*, char*); +#endif + + +extern jmp_buf sjbuf; +int toolate; +int error; + +char obuf[2*BUFSIZ]; +char *obufp = obuf; + + /* pipe command structure; allows redicously long commends for .pi */ +struct Pipe { + char *buf; + int tick; + int cnt; +} Pipe; + + +int xon = 0; /* records if in middle of \X */ + +int pchar(Tchar i) +{ + int j; + static int hx = 0; /* records if have seen HX */ + + if (hx) { + hx = 0; + j = absmot(i); + if (isnmot(i)) { + if (j > dip->blss) + dip->blss = j; + } else { + if (j > dip->alss) + dip->alss = j; + ralss = dip->alss; + } + return 0; + } + if (ismot(i)) { + pchar1(i); + return 0; + } + switch (j = cbits(i)) { + case 0: + case IMP: + case RIGHT: + case LEFT: + return 0; + case HX: + hx = 1; + return 0; + case XON: + xon++; + break; + case XOFF: + xon--; + break; + case PRESC: + if (!xon && !tflg && dip == &d[0]) + j = eschar; /* fall through */ + default: + setcbits(i, trtab[j]); + } + if (NROFF & xon) /* rob fix for man2html */ + return 0; + pchar1(i); + return 0; +} + + +void pchar1(Tchar i) +{ + int j; + + j = cbits(i); + if (dip != &d[0]) { + wbf(i); + dip->op = offset; + return; + } + if (!tflg && !print) { + if (j == '\n') + dip->alss = dip->blss = 0; + return; + } + if (j == FILLER && !xon) + return; + if (tflg) { /* transparent mode, undiverted */ + if (print) /* assumes that it's ok to print */ + /* OUT "%c", j PUT; /* i.e., is ascii */ + outascii(i); + return; + } + if (TROFF && ascii) + outascii(i); + else + ptout(i); +} + + +void outweird(int k) /* like ptchname() but ascii */ +{ + char *chn = chname(k); + + switch (chn[0]) { + case MBchar: + OUT "%s", chn+1 PUT; /* \n not needed? */ + break; + case Number: + OUT "\\N'%s'", chn+1 PUT; + break; + case Troffchar: + if (strlen(chn+1) == 2) + OUT "\\(%s", chn+1 PUT; + else + OUT "\\C'%s'", chn+1 PUT; + break; + default: + OUT " %s? ", chn PUT; + break; + } +} + +void outascii(Tchar i) /* print i in best-guess ascii */ +{ + char *p; + int j = cbits(i); + +/* is this ever called with NROFF set? probably doesn't work at all. */ + + if (ismot(i)) + oput(' '); + else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t') + oput(j); + else if (j == DRAWFCN) + oputs("\\D"); + else if (j == HYPHEN) + oput('-'); + else if (j == MINUS) /* special pleading for strange encodings */ + oputs("\\-"); + else if (j == PRESC) + oputs("\\e"); + else if (j == FILLER) + oputs("\\&"); + else if (j == UNPAD) + oputs("\\ "); + else if (j == OHC) /* this will never occur; stripped out earlier */ + oputs("\\%"); + else if (j == XON) + oputs("\\X"); + else if (j == XOFF) + oputs(" "); + else if (j == LIG_FI) + oputs("fi"); + else if (j == LIG_FL) + oputs("fl"); + else if (j == LIG_FF) + oputs("ff"); + else if (j == LIG_FFI) + oputs("ffi"); + else if (j == LIG_FFL) + oputs("ffl"); + else if (j == WORDSP) { /* nothing at all */ + if (xon) /* except in \X */ + oput(' '); + + } else + outweird(j); +} + +int flusho(void) +{ + if (NROFF && !toolate && t.twinit) + fwrite(t.twinit, strlen(t.twinit), 1, ptid); + + if (obufp > obuf) { + if (pipeflg && !toolate) { + /* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */ + if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL) + ERROR "pipe %s not created.", Pipe.buf WARN; + if (Pipe.buf) + free(Pipe.buf); + } + if (!toolate) + toolate++; + *obufp = 0; + fputs(obuf, ptid); + fflush(ptid); + obufp = obuf; + } + return 1; +} + + +void caseex(void) +{ + done(0); +} + + +void done(int x) +{ + int i; + + error |= x; + app = ds = lgf = 0; + if (i = em) { + donef = -1; + eschar = '\\'; + em = 0; + if (control(i, 0)) + longjmp(sjbuf, 1); + } + if (!nfo) + done3(0); + mflg = 0; + dip = &d[0]; + if (woff) /* BUG!!! This isn't set anywhere */ + wbf((Tchar)0); + if (pendw) + getword(1); + pendnf = 0; + if (donef == 1) + done1(0); + donef = 1; + ip = 0; + frame = stk; + nxf = frame + 1; + if (!ejf) + tbreak(); + nflush++; + eject((Stack *)0); + longjmp(sjbuf, 1); +} + + +void done1(int x) +{ + error |= x; + if (numtabp[NL].val) { + trap = 0; + eject((Stack *)0); + longjmp(sjbuf, 1); + } + if (!ascii) + pttrailer(); + done2(0); +} + + +void done2(int x) +{ + ptlead(); + if (TROFF && !ascii) + ptstop(); + flusho(); + done3(x); +} + +void done3(int x) +{ + error |= x; + flusho(); + if (NROFF) + twdone(); + if (pipeflg) + pclose(ptid); + exit(error); +} + + +void edone(int x) +{ + frame = stk; + nxf = frame + 1; + ip = 0; + done(x); +} + + +void casepi(void) +{ + int j; + char buf[NTM]; + + if (Pipe.buf == NULL) { + if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) { + ERROR "No buf space for pipe cmd" WARN; + return; + } + Pipe.tick = 1; + } else + Pipe.buf[Pipe.cnt++] = '|'; + + getline(buf, NTM); + j = strlen(buf); + if (toolate) { + ERROR "Cannot create pipe to %s", buf WARN; + return; + } + Pipe.cnt += j; + if (j >= NTM +1) { + Pipe.tick++; + if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) { + ERROR "No more buf space for pipe cmd" WARN; + return; + } + } + strcat(Pipe.buf, buf); + pipeflg++; +} blob - /dev/null blob + 6918d06de4ea5055da78dea45fdfc2a166b7a34c (mode 644) --- /dev/null +++ src/cmd/troff/n3.c @@ -0,0 +1,954 @@ +/* + * troff3.c + * + * macro and string routines, storage allocation + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +Tchar *argtop; +int pagech = '%'; +int strflg; + +#define MHASHSIZE 128 /* must be 2**n */ +#define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1) +Contab *mhash[MHASHSIZE]; + + +Blockp *blist; /* allocated blocks for macros and strings */ +int nblist; /* how many there are */ +int bfree = -1; /* first (possible) free block in the list */ + +Contab *contabp = NULL; +#define MDELTA 500 +int nm = 0; + +int savname; /* name of macro/string being defined */ +int savslot; /* place in Contab of savname */ +int freeslot = -1; /* first (possible) free slot in contab */ + +void prcontab(Contab *p) +{ + int i; + for (i = 0; i < nm; i++) + if (p) + if (p[i].rq != 0) + fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq)); + else + fprintf(stderr, "slot %d empty\n", i); + else + fprintf(stderr, "slot %d empty\n", i); +} + + +void blockinit(void) +{ + blist = (Blockp *) calloc(NBLIST, sizeof(Blockp)); + if (blist == NULL) { + ERROR "not enough room for %d blocks", NBLIST WARN; + done2(1); + } + nblist = NBLIST; + blist[0].nextoff = blist[1].nextoff = -1; + blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + /* -1 prevents blist[0] from being used; temporary fix */ + /* for a design botch: offset==0 is overloaded. */ + /* blist[1] reserved for .rd indicator -- also unused. */ + /* but someone unwittingly looks at these, so allocate something */ + bfree = 2; +} + + +char *grow(char *ptr, int num, int size) /* make array bigger */ +{ + char *p, new; + + if (ptr == NULL) + p = (char *) calloc(num, size); + else + p = (char *) realloc(ptr, num * size); + return p; +} + +void mnspace(void) +{ + nm = sizeof(contab)/sizeof(Contab) + MDELTA; + freeslot = sizeof(contab)/sizeof(Contab) + 1; + contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab)); + if (contabp == NULL) { + ERROR "not enough memory for namespace of %d marcos", nm WARN; + exit(1); + } + contabp = (Contab *) memcpy((char *) contabp, (char *)contab, + sizeof(contab)); + if (contabp == NULL) { + ERROR "Cannot reinitialize macro/request name list" WARN; + exit(1); + } + +} + +void caseig(void) +{ + int i; + Offset oldoff = offset; + + offset = 0; + i = copyb(); + offset = oldoff; + if (i != '.') + control(i, 1); +} + + +void casern(void) +{ + int i, j, k; + + lgf++; + skip(); + if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0) + return; + skip(); + clrmn(findmn(j = getrq())); + if (j) { + munhash(&contabp[oldmn]); + contabp[oldmn].rq = j; + maddhash(&contabp[oldmn]); + if (dip != d ) + for (k = dilev; k; k--) + if (d[k].curd == i) + d[k].curd = j; + } +} + +void maddhash(Contab *rp) +{ + Contab **hp; + + if (rp->rq == 0) + return; + hp = &mhash[MHASH(rp->rq)]; + rp->link = *hp; + *hp = rp; +} + +void munhash(Contab *mp) +{ + Contab *p; + Contab **lp; + + if (mp->rq == 0) + return; + lp = &mhash[MHASH(mp->rq)]; + p = *lp; + while (p) { + if (p == mp) { + *lp = p->link; + p->link = 0; + return; + } + lp = &p->link; + p = p->link; + } +} + +void mrehash(void) +{ + Contab *p; + int i; + + for (i=0; i < MHASHSIZE; i++) + mhash[i] = 0; + for (p=contabp; p < &contabp[nm]; p++) + p->link = 0; + for (p=contabp; p < &contabp[nm]; p++) { + if (p->rq == 0) + continue; + i = MHASH(p->rq); + p->link = mhash[i]; + mhash[i] = p; + } +} + +void caserm(void) +{ + int j; + int k = 0; + + lgf++; +g0: + while (!skip() && (j = getrq()) != 0) { + if (dip != d) + for (k = dilev; k; k--) + if (d[k].curd == j) { + ERROR "cannot remove diversion %s during definition", + unpair(j) WARN; + goto g0; + } + clrmn(findmn(j)); + } + lgf--; +} + + +void caseas(void) +{ + app++; + caseds(); +} + + +void caseds(void) +{ + ds++; + casede(); +} + + +void caseam(void) +{ + app++; + casede(); +} + + +void casede(void) +{ + int i, req; + Offset savoff; + + req = '.'; + lgf++; + skip(); + if ((i = getrq()) == 0) + goto de1; + if ((offset = finds(i)) == 0) + goto de1; + if (newmn) + savslot = newmn; + else + savslot = findmn(i); + savname = i; + if (ds) + copys(); + else + req = copyb(); + clrmn(oldmn); + if (newmn) { + if (contabp[newmn].rq) + munhash(&contabp[newmn]); + contabp[newmn].rq = i; + maddhash(&contabp[newmn]); + + } + if (apptr) { + savoff = offset; + offset = apptr; + wbf((Tchar) IMP); + offset = savoff; + } + offset = dip->op; + if (req != '.') + control(req, 1); +de1: + ds = app = 0; +} + + +int findmn(int i) +{ + Contab *p; + + for (p = mhash[MHASH(i)]; p; p = p->link) + if (i == p->rq) + return(p - contabp); + return(-1); +} + + +void clrmn(int i) +{ + if (i >= 0) { + if (contabp[i].mx) + ffree(contabp[i].mx); + munhash(&contabp[i]); + contabp[i].rq = 0; + contabp[i].mx = 0; + contabp[i].emx = 0; + contabp[i].f = 0; + if (contabp[i].divsiz != NULL) { + free(contabp[i].divsiz); + contabp[i].divsiz = NULL; + } + if (freeslot > i) + freeslot = i; + } +} + +void growcontab(void) +{ + nm += MDELTA; + contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab)); + if (contabp == NULL) { + ERROR "Too many (%d) string/macro names", nm WARN; + done2(02); + } else { + memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab), + 0, MDELTA * sizeof(Contab)); + mrehash(); + } +} + + +Offset finds(int mn) +{ + int i; + Tchar j = IMP; + Offset savip; + + oldmn = findmn(mn); + newmn = 0; + apptr = 0; + if (app && oldmn >= 0 && contabp[oldmn].mx) { + savip = ip; + ip = contabp[oldmn].emx; + oldmn = -1; + apptr = ip; + if (!diflg) + ip = incoff(ip); + nextb = ip; + ip = savip; + } else { + for (i = freeslot; i < nm; i++) { + if (contabp[i].rq == 0) + break; + } + if (i == nm) + growcontab(); + freeslot = i + 1; + if ((nextb = alloc()) == -1) { + app = 0; + if (macerr++ > 1) + done2(02); + if (nextb == 0) + ERROR "Not enough space for string/macro names" WARN; + edone(04); + return(offset = 0); + } + contabp[i].mx = nextb; + if (!diflg) { + newmn = i; + if (oldmn == -1) + contabp[i].rq = -1; + } else { + contabp[i].rq = mn; + maddhash(&contabp[i]); + } + } + app = 0; + return(offset = nextb); +} + +int skip(void) +{ + Tchar i; + + while (cbits(i = getch()) == ' ' || ismot(i)) + ; + ch = i; + return(nlflg); +} + + +int copyb(void) +{ + int i, j, state; + Tchar ii; + int req, k; + Offset savoff; + Uchar *p; + + if (skip() || !(j = getrq())) + j = '.'; + req = j; + p = unpair(j); + /* was: k = j >> BYTE; j &= BYTEMASK; */ + j = p[0]; + k = p[1]; + copyf++; + flushi(); + nlflg = 0; + state = 1; + +/* state 0 eat up + * state 1 look for . + * state 2 look for first char of end macro + * state 3 look for second char of end macro + */ + + while (1) { + i = cbits(ii = getch()); + if (state == 3) { + if (i == k) + break; + if (!k) { + ch = ii; + i = getach(); + ch = ii; + if (!i) + break; + } + state = 0; + goto c0; + } + if (i == '\n') { + state = 1; + nlflg = 0; + goto c0; + } + if (state == 1 && i == '.') { + state++; + savoff = offset; + goto c0; + } + if (state == 2 && i == j) { + state++; + goto c0; + } + state = 0; +c0: + if (offset) + wbf(ii); + } + if (offset) { + offset = savoff; + wbf((Tchar)0); + } + copyf--; + return(req); +} + + +void copys(void) +{ + Tchar i; + + copyf++; + if (skip()) + goto c0; + if (cbits(i = getch()) != '"') + wbf(i); + while (cbits(i = getch()) != '\n') + wbf(i); +c0: + wbf((Tchar)0); + copyf--; +} + + +Offset alloc(void) /* return free Offset in nextb */ +{ + int i, j; + + for (i = bfree; i < nblist; i++) + if (blist[i].nextoff == 0) + break; + if (i == nblist) { + blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp)); + if (blist == NULL) { + ERROR "can't grow blist for string/macro defns" WARN; + done2(2); + } + nblist *= 2; + for (j = i; j < nblist; j++) { + blist[j].nextoff = 0; + blist[j].bp = 0; + } + } + blist[i].nextoff = -1; /* this block is the end */ + bfree = i + 1; + if (blist[i].bp == 0) + blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + if (blist[i].bp == NULL) { + ERROR "can't allocate memory for string/macro definitions" WARN; + done2(2); + } + nextb = (Offset) i * BLK; + return nextb; +} + + +void ffree(Offset i) /* free list of blocks starting at blist(o) */ +{ /* (doesn't actually free the blocks, just the pointers) */ + int j; + + for ( ; blist[j = bindex(i)].nextoff != -1; ) { + if (bfree > j) + bfree = j; + i = blist[j].nextoff; + blist[j].nextoff = 0; + } + blist[j].nextoff = 0; +} + + +void wbf(Tchar i) /* store i into offset, get ready for next one */ +{ + int j, off; + + if (!offset) + return; + j = bindex(offset); + if (i == 0) + contabp[savslot].emx = offset; + off = boffset(offset); + blist[j].bp[off++] = i; + offset++; + if (pastend(offset)) { /* off the end of this block */ + if (blist[j].nextoff == -1) { + if ((nextb = alloc()) == -1) { + ERROR "Out of temp file space" WARN; + done2(01); + } + blist[j].nextoff = nextb; + } + offset = blist[j].nextoff; + } +} + + +Tchar rbf(void) /* return next char from blist[] block */ +{ + Tchar i, j; + + if (ip == RD_OFFSET) { /* for rdtty */ + if (j = rdtty()) + return(j); + else + return(popi()); + } + + i = rbf0(ip); + if (i == 0) { + if (!app) + i = popi(); + return(i); + } + ip = incoff(ip); + return(i); +} + + +Offset xxxincoff(Offset p) /* get next blist[] block */ +{ + p++; + if (pastend(p)) { /* off the end of this block */ + if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */ + ERROR "Bad storage allocation" WARN; + done2(-5); + } + } + return(p); +} + + +Tchar popi(void) +{ + Stack *p; + + if (frame == stk) + return(0); + if (strflg) + strflg--; + p = nxf = frame; + p->nargs = 0; + frame = p->pframe; + ip = p->pip; + pendt = p->ppendt; + lastpbp = p->lastpbp; + return(p->pch); +} + +/* + * test that the end of the allocation is above a certain location + * in memory + */ +#define SPACETEST(base, size) \ + if ((char*)base + size >= (char*)stk+STACKSIZE) \ + ERROR "Stacksize overflow in n3" WARN + +Offset pushi(Offset newip, int mname) +{ + Stack *p; + + SPACETEST(nxf, sizeof(Stack)); + p = nxf; + p->pframe = frame; + p->pip = ip; + p->ppendt = pendt; + p->pch = ch; + p->lastpbp = lastpbp; + p->mname = mname; + lastpbp = pbp; + pendt = ch = 0; + frame = nxf; + if (nxf->nargs == 0) + nxf += 1; + else + nxf = (Stack *)argtop; + return(ip = newip); +} + + +void *setbrk(int x) +{ + char *i; + + if ((i = (char *) calloc(x, 1)) == 0) { + ERROR "Core limit reached" WARN; + edone(0100); + } + return(i); +} + + +int getsn(void) +{ + int i; + + if ((i = getach()) == 0) + return(0); + if (i == '(') + return(getrq()); + else + return(i); +} + + +Offset setstr(void) +{ + int i, j; + + lgf++; + if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) { + lgf--; + return(0); + } else { + SPACETEST(nxf, sizeof(Stack)); + nxf->nargs = 0; + strflg++; + lgf--; + return pushi(contabp[j].mx, i); + } +} + + + +void collect(void) +{ + int j; + Tchar i, *strp, *lim, **argpp, **argppend; + int quote; + Stack *savnxf; + + copyf++; + nxf->nargs = 0; + savnxf = nxf; + if (skip()) + goto rtn; + + { + char *memp; + memp = (char *)savnxf; + /* + * 1 s structure for the macro descriptor + * APERMAC Tchar *'s for pointers into the strings + * space for the Tchar's themselves + */ + memp += sizeof(Stack); + /* + * CPERMAC = the total # of characters for ALL arguments + */ +#define CPERMAC 200 +#define APERMAC 9 + memp += APERMAC * sizeof(Tchar *); + memp += CPERMAC * sizeof(Tchar); + nxf = (Stack *)memp; + } + lim = (Tchar *)nxf; + argpp = (Tchar **)(savnxf + 1); + argppend = &argpp[APERMAC]; + SPACETEST(argppend, sizeof(Tchar *)); + strp = (Tchar *)argppend; + /* + * Zero out all the string pointers before filling them in. + */ + for (j = 0; j < APERMAC; j++) + argpp[j] = 0; + /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x", + * savnxf, nxf, argpp, strp, lim WARN; + */ + strflg = 0; + while (argpp != argppend && !skip()) { + *argpp++ = strp; + quote = 0; + if (cbits(i = getch()) == '"') + quote++; + else + ch = i; + while (1) { + i = getch(); +/* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */ + if (nlflg || (!quote && argpp != argppend && cbits(i) == ' ')) + break; /* collects rest into $9 */ + if ( quote + && cbits(i) == '"' + && cbits(i = getch()) != '"') { + ch = i; + break; + } + *strp++ = i; + if (strflg && strp >= lim) { + /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */ + ERROR "Macro argument too long" WARN; + copyf--; + edone(004); + } + SPACETEST(strp, 3 * sizeof(Tchar)); + } + *strp++ = 0; + } + nxf = savnxf; + nxf->nargs = argpp - (Tchar **)(savnxf + 1); + argtop = strp; +rtn: + copyf--; +} + + +void seta(void) +{ + int i; + + i = cbits(getch()) - '0'; + if (i > 0 && i <= APERMAC && i <= frame->nargs) + pushback(*(((Tchar **)(frame + 1)) + i - 1)); +} + + +void caseda(void) +{ + app++; + casedi(); +} + +void casegd(void) +{ + int i, j; + + skip(); + if ((i = getrq()) == 0) + return; + if ((j = findmn(i)) >= 0) { + if (contabp[j].divsiz != NULL) { + numtabp[DN].val = contabp[j].divsiz->dix; + numtabp[DL].val = contabp[j].divsiz->diy; + } + } +} + +#define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \ + ERROR "lost diversion %s", unpair(dip->curd) WARN + +void casedi(void) +{ + int i, j, *k; + + lgf++; + if (skip() || (i = getrq()) == 0) { + if (dip != d) { + FINDDIV(savslot); + wbf((Tchar)0); + } + if (dilev > 0) { + numtabp[DN].val = dip->dnl; + numtabp[DL].val = dip->maxl; + FINDDIV(j); + if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) { + ERROR "Cannot alloc diversion size" WARN; + done2(1); + } else { + contabp[j].divsiz->dix = numtabp[DN].val; + contabp[j].divsiz->diy = numtabp[DL].val; + } + dip = &d[--dilev]; + offset = dip->op; + } + goto rtn; + } + if (++dilev == NDI) { + --dilev; + ERROR "Diversions nested too deep" WARN; + edone(02); + } + if (dip != d) { + FINDDIV(j); + savslot = j; + wbf((Tchar)0); + } + diflg++; + dip = &d[dilev]; + dip->op = finds(i); + dip->curd = i; + clrmn(oldmn); + k = (int *) & dip->dnl; + for (j = 0; j < 10; j++) + k[j] = 0; /*not op and curd*/ +rtn: + app = 0; + diflg = 0; +} + + +void casedt(void) +{ + lgf++; + dip->dimac = dip->ditrap = dip->ditf = 0; + skip(); + dip->ditrap = vnumb((int *)0); + if (nonumb) + return; + skip(); + dip->dimac = getrq(); +} + +#define LNSIZE 4000 +void casetl(void) +{ + int j; + int w[3]; + Tchar buf[LNSIZE]; + Tchar *tp; + Tchar i, delim; + + /* + * bug fix + * + * if .tl is the first thing in the file, the p1 + * doesn't come out, also the pagenumber will be 0 + * + * tends too confuse the device filter (and the user as well) + */ + if (dip == d && numtabp[NL].val == -1) + newline(1); + dip->nls = 0; + skip(); + if (ismot(delim = getch())) { + ch = delim; + delim = '\''; + } else + delim = cbits(delim); + tp = buf; + numtabp[HP].val = 0; + w[0] = w[1] = w[2] = 0; + j = 0; + while (cbits(i = getch()) != '\n') { + if (cbits(i) == cbits(delim)) { + if (j < 3) + w[j] = numtabp[HP].val; + numtabp[HP].val = 0; + if (w[j] != 0) + *tp++ = WORDSP; + j++; + *tp++ = 0; + } else { + if (cbits(i) == pagech) { + setn1(numtabp[PN].val, numtabp[findr('%')].fmt, + i&SFMASK); + continue; + } + numtabp[HP].val += width(i); + if (tp < &buf[LNSIZE-10]) { + if (cbits(i) == ' ' && *tp != WORDSP) + *tp++ = WORDSP; + *tp++ = i; + } else { + ERROR "Overflow in casetl" WARN; + } + } + } + if (j<3) + w[j] = numtabp[HP].val; + *tp++ = 0; + *tp++ = 0; + *tp = 0; + tp = buf; + if (NROFF) + horiz(po); + while (i = *tp++) + pchar(i); + if (w[1] || w[2]) + horiz(j = quant((lt - w[1]) / 2 - w[0], HOR)); + while (i = *tp++) + pchar(i); + if (w[2]) { + horiz(lt - w[0] - w[1] - w[2] - j); + while (i = *tp++) + pchar(i); + } + newline(0); + if (dip != d) { + if (dip->dnl > dip->hnl) + dip->hnl = dip->dnl; + } else { + if (numtabp[NL].val > dip->hnl) + dip->hnl = numtabp[NL].val; + } +} + + +void casepc(void) +{ + pagech = chget(IMP); +} + + +void casepm(void) +{ + int i, k; + int xx, cnt, tcnt, kk, tot; + Offset j; + + kk = cnt = tcnt = 0; + tot = !skip(); + stackdump(); + for (i = 0; i < nm; i++) { + if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0) + continue; + tcnt++; + j = contabp[i].mx; + for (k = 1; (j = blist[bindex(j)].nextoff) != -1; ) + k++; + cnt++; + kk += k; + if (!tot) + fprintf(stderr, "%-2.2s %d\n", unpair(xx), k); + } + fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk); +} + +void stackdump(void) /* dumps stack of macros in process */ +{ + Stack *p; + + if (frame != stk) { + fprintf(stderr, "stack: "); + for (p = frame; p != stk; p = p->pframe) + fprintf(stderr, "%s ", unpair(p->mname)); + fprintf(stderr, "\n"); + } +} blob - /dev/null blob + 3b3698e4c3160c29dd26bc3622ec5e39f1c0a12a (mode 644) --- /dev/null +++ src/cmd/troff/n4.c @@ -0,0 +1,828 @@ +/* + * troff4.c + * + * number registers, conversion, arithmetic + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + + +int regcnt = NNAMES; +int falsef = 0; /* on if inside false branch of if */ + +#define NHASHSIZE 128 /* must be 2**n */ +#define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1) +Numtab *nhash[NHASHSIZE]; + +Numtab *numtabp = NULL; +#define NDELTA 400 +int ncnt = 0; + +void setn(void) +{ + int i, j, f; + Tchar ii; + Uchar *p; + char buf[NTM]; /* for \n(.S */ + + f = nform = 0; + if ((i = cbits(ii = getach())) == '+') + f = 1; + else if (i == '-') + f = -1; + else if (ii) /* don't put it back if it's already back (thanks to jaap) */ + ch = ii; + if (falsef) + f = 0; + if ((i = getsn()) == 0) + return; + p = unpair(i); + if (p[0] == '.') + switch (p[1]) { + case 's': + i = pts; + break; + case 'v': + i = lss; + break; + case 'f': + i = font; + break; + case 'p': + i = pl; + break; + case 't': + i = findt1(); + break; + case 'o': + i = po; + break; + case 'l': + i = ll; + break; + case 'i': + i = in; + break; + case '$': + i = frame->nargs; + break; + case 'A': + i = ascii; + break; + case 'c': + i = numtabp[CD].val; + break; + case 'n': + i = lastl; + break; + case 'a': + i = ralss; + break; + case 'h': + i = dip->hnl; + break; + case 'd': + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + break; + case 'u': + i = fi; + break; + case 'j': + i = ad + 2 * admod; + break; + case 'w': + i = widthp; + break; + case 'x': + i = nel; + break; + case 'y': + i = un; + break; + case 'T': + i = dotT; + break; /* -Tterm used in nroff */ + case 'V': + i = VERT; + break; + case 'H': + i = HOR; + break; + case 'k': + i = ne; + break; + case 'P': + i = print; + break; + case 'L': + i = ls; + break; + case 'R': /* maximal # of regs that can be addressed */ + i = 255*256 - regcnt; + break; + case 'z': + p = unpair(dip->curd); + *pbp++ = p[1]; /* watch order */ + *pbp++ = p[0]; + return; + case 'b': + i = bdtab[font]; + break; + case 'F': + cpushback(cfname[ifi]); + return; + case 'S': + buf[0] = j = 0; + for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { + if (i > 0) + buf[j++] = ' '; + sprintf(&buf[j], "%d", tabtab[i] & TABMASK); + j = strlen(buf); + if ( tabtab[i] & RTAB) + sprintf(&buf[j], "uR"); + else if (tabtab[i] & CTAB) + sprintf(&buf[j], "uC"); + else + sprintf(&buf[j], "uL"); + j += 2; + } + cpushback(buf); + return; + default: + goto s0; + } + else { +s0: + if ((j = findr(i)) == -1) + i = 0; + else { + i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f; + nform = numtabp[j].fmt; + } + } + setn1(i, nform, (Tchar) 0); +} + +Tchar numbuf[25]; +Tchar *numbufp; + +int wrc(Tchar i) +{ + if (numbufp >= &numbuf[24]) + return(0); + *numbufp++ = i; + return(1); +} + + + +/* insert into input number i, in format form, with size-font bits bits */ +void setn1(int i, int form, Tchar bits) +{ + numbufp = numbuf; + nrbits = bits; + nform = form; + fnumb(i, wrc); + *numbufp = 0; + pushback(numbuf); +} + +void prnumtab(Numtab *p) +{ + int i; + for (i = 0; i < ncnt; i++) + if (p) + if (p[i].r != 0) + fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val); + else + fprintf(stderr, "slot %d empty\n", i); + else + fprintf(stderr, "slot %d empty\n", i); +} + +void nnspace(void) +{ + ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA; + numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab)); + if (numtabp == NULL) { + ERROR "not enough memory for registers (%d)", ncnt WARN; + exit(1); + } + numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab, + sizeof(numtab)); + if (numtabp == NULL) { + ERROR "Cannot initialize registers" WARN; + exit(1); + } +} + +void grownumtab(void) +{ + ncnt += NDELTA; + numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab)); + if (numtabp == NULL) { + ERROR "Too many number registers (%d)", ncnt WARN; + done2(04); + } else { + memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab), + 0, NDELTA * sizeof(Numtab)); + nrehash(); + } +} + +void nrehash(void) +{ + Numtab *p; + int i; + + for (i=0; ilink = 0; + for (p=numtabp; p < &numtabp[ncnt]; p++) { + if (p->r == 0) + continue; + i = NHASH(p->r); + p->link = nhash[i]; + nhash[i] = p; + } +} + +void nunhash(Numtab *rp) +{ + Numtab *p; + Numtab **lp; + + if (rp->r == 0) + return; + lp = &nhash[NHASH(rp->r)]; + p = *lp; + while (p) { + if (p == rp) { + *lp = p->link; + p->link = 0; + return; + } + lp = &p->link; + p = p->link; + } +} + +int findr(int i) +{ + Numtab *p; + int h = NHASH(i); + + if (i == 0) + return(-1); +a0: + for (p = nhash[h]; p; p = p->link) + if (i == p->r) + return(p - numtabp); + for (p = numtabp; p < &numtabp[ncnt]; p++) { + if (p->r == 0) { + p->r = i; + p->link = nhash[h]; + nhash[h] = p; + regcnt++; + return(p - numtabp); + } + } + grownumtab(); + goto a0; +} + +int usedr(int i) /* returns -1 if nr i has never been used */ +{ + Numtab *p; + + if (i == 0) + return(-1); + for (p = nhash[NHASH(i)]; p; p = p->link) + if (i == p->r) + return(p - numtabp); + return -1; +} + + +int fnumb(int i, int (*f)(Tchar)) +{ + int j; + + j = 0; + if (i < 0) { + j = (*f)('-' | nrbits); + i = -i; + } + switch (nform) { + default: + case '1': + case 0: + return decml(i, f) + j; + case 'i': + case 'I': + return roman(i, f) + j; + case 'a': + case 'A': + return abc(i, f) + j; + } +} + + +int decml(int i, int (*f)(Tchar)) +{ + int j, k; + + k = 0; + nform--; + if ((j = i / 10) || (nform > 0)) + k = decml(j, f); + return(k + (*f)((i % 10 + '0') | nrbits)); +} + + +int roman(int i, int (*f)(Tchar)) +{ + + if (!i) + return((*f)('0' | nrbits)); + if (nform == 'i') + return(roman0(i, f, "ixcmz", "vldw")); + else + return(roman0(i, f, "IXCMZ", "VLDW")); +} + + +int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp) +{ + int q, rem, k; + + if (!i) + return(0); + k = roman0(i / 10, f, onesp + 1, fivesp + 1); + q = (i = i % 10) / 5; + rem = i % 5; + if (rem == 4) { + k += (*f)(*onesp | nrbits); + if (q) + i = *(onesp + 1); + else + i = *fivesp; + return(k += (*f)(i | nrbits)); + } + if (q) + k += (*f)(*fivesp | nrbits); + while (--rem >= 0) + k += (*f)(*onesp | nrbits); + return(k); +} + + +int abc(int i, int (*f)(Tchar)) +{ + if (!i) + return((*f)('0' | nrbits)); + else + return(abc0(i - 1, f)); +} + + +int abc0(int i, int (*f)(Tchar)) +{ + int j, k; + + k = 0; + if (j = i / 26) + k = abc0(j - 1, f); + return(k + (*f)((i % 26 + nform) | nrbits)); +} + +long atoi0(void) +{ + int c, k, cnt; + Tchar ii; + long i, acc; + + acc = 0; + nonumb = 0; + cnt = -1; +a0: + cnt++; + ii = getch(); + c = cbits(ii); + switch (c) { + default: + ch = ii; + if (cnt) + break; + case '+': + i = ckph(); + if (nonumb) + break; + acc += i; + goto a0; + case '-': + i = ckph(); + if (nonumb) + break; + acc -= i; + goto a0; + case '*': + i = ckph(); + if (nonumb) + break; + acc *= i; + goto a0; + case '/': + i = ckph(); + if (nonumb) + break; + if (i == 0) { + flusho(); + ERROR "divide by zero." WARN; + acc = 0; + } else + acc /= i; + goto a0; + case '%': + i = ckph(); + if (nonumb) + break; + acc %= i; + goto a0; + case '&': /*and*/ + i = ckph(); + if (nonumb) + break; + if ((acc > 0) && (i > 0)) + acc = 1; + else + acc = 0; + goto a0; + case ':': /*or*/ + i = ckph(); + if (nonumb) + break; + if ((acc > 0) || (i > 0)) + acc = 1; + else + acc = 0; + goto a0; + case '=': + if (cbits(ii = getch()) != '=') + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (i == acc) + acc = 1; + else + acc = 0; + goto a0; + case '>': + k = 0; + if (cbits(ii = getch()) == '=') + k++; + else + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (acc > (i - k)) + acc = 1; + else + acc = 0; + goto a0; + case '<': + k = 0; + if (cbits(ii = getch()) == '=') + k++; + else + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (acc < (i + k)) + acc = 1; + else + acc = 0; + goto a0; + case ')': + break; + case '(': + acc = atoi0(); + goto a0; + } + return(acc); +} + + +long ckph(void) +{ + Tchar i; + long j; + + if (cbits(i = getch()) == '(') + j = atoi0(); + else { + j = atoi1(i); + } + return(j); +} + + +/* + * print error about illegal numeric argument; + */ +void prnumerr(void) +{ + char err_buf[40]; + static char warn[] = "Numeric argument expected"; + int savcd = numtabp[CD].val; + + if (numerr.type == RQERR) + sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc), + unpair(numerr.req), warn); + else + sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg, + warn); + if (frame != stk) /* uncertainty correction */ + numtabp[CD].val--; + ERROR err_buf WARN; + numtabp[CD].val = savcd; +} + + +long atoi1(Tchar ii) +{ + int i, j, digits; + double acc; /* this is the only double in troff! */ + int neg, abs, field, decpnt; + extern int ifnum; + + + neg = abs = field = decpnt = digits = 0; + acc = 0; + for (;;) { + i = cbits(ii); + switch (i) { + default: + break; + case '+': + ii = getch(); + continue; + case '-': + neg = 1; + ii = getch(); + continue; + case '|': + abs = 1 + neg; + neg = 0; + ii = getch(); + continue; + } + break; + } +a1: + while (i >= '0' && i <= '9') { + field++; + digits++; + acc = 10 * acc + i - '0'; + ii = getch(); + i = cbits(ii); + } + if (i == '.' && !decpnt++) { + field++; + digits = 0; + ii = getch(); + i = cbits(ii); + goto a1; + } + if (!field) { + ch = ii; + goto a2; + } + switch (i) { + case 'u': + i = j = 1; /* should this be related to HOR?? */ + break; + case 'v': /*VSs - vert spacing*/ + j = lss; + i = 1; + break; + case 'm': /*Ems*/ + j = EM; + i = 1; + break; + case 'n': /*Ens*/ + j = EM; + if (TROFF) + i = 2; + else + i = 1; /*Same as Ems in NROFF*/ + break; + case 'p': /*Points*/ + j = INCH; + i = 72; + break; + case 'i': /*Inches*/ + j = INCH; + i = 1; + break; + case 'c': /*Centimeters*/ + /* if INCH is too big, this will overflow */ + j = INCH * 50; + i = 127; + break; + case 'P': /*Picas*/ + j = INCH; + i = 6; + break; + default: + j = dfact; + ch = ii; + i = dfactd; + } + if (neg) + acc = -acc; + if (!noscale) { + acc = (acc * j) / i; + } + if (field != digits && digits > 0) + while (digits--) + acc /= 10; + if (abs) { + if (dip != d) + j = dip->dnl; + else + j = numtabp[NL].val; + if (!vflag) { + j = numtabp[HP].val; + } + if (abs == 2) + j = -j; + acc -= j; + } +a2: + nonumb = (!field || field == decpnt); + if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) { + if (cbits(ii) != RIGHT ) /* Too painful to do right */ + prnumerr(); + } + return(acc); +} + + +void caserr(void) +{ + int i, j; + Numtab *p; + + lgf++; + while (!skip() && (i = getrq()) ) { + j = usedr(i); + if (j < 0) + continue; + p = &numtabp[j]; + nunhash(p); + p->r = p->val = p->inc = p->fmt = 0; + regcnt--; + } +} + +/* + * .nr request; if tracing, don't check optional + * 2nd argument because tbl generates .in 1.5n + */ +void casenr(void) +{ + int i, j; + int savtr = trace; + + lgf++; + skip(); + if ((i = findr(getrq())) == -1) + goto rtn; + skip(); + j = inumb(&numtabp[i].val); + if (nonumb) + goto rtn; + numtabp[i].val = j; + skip(); + trace = 0; + j = atoi0(); /* BUG??? */ + trace = savtr; + if (nonumb) + goto rtn; + numtabp[i].inc = j; +rtn: + return; +} + +void caseaf(void) +{ + int i, k; + Tchar j; + + lgf++; + if (skip() || !(i = getrq()) || skip()) + return; + k = 0; + j = getch(); + if (!isalpha(cbits(j))) { + ch = j; + while ((j = cbits(getch())) >= '0' && j <= '9') + k++; + } + if (!k) + k = j; + numtabp[findr(i)].fmt = k; /* was k & BYTEMASK */ +} + +void setaf(void) /* return format of number register */ +{ + int i, j; + + i = usedr(getsn()); + if (i == -1) + return; + if (numtabp[i].fmt > 20) /* it was probably a, A, i or I */ + *pbp++ = numtabp[i].fmt; + else + for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--) + *pbp++ = '0'; +} + + +int vnumb(int *i) +{ + vflag++; + dfact = lss; + res = VERT; + return(inumb(i)); +} + + +int hnumb(int *i) +{ + dfact = EM; + res = HOR; + return(inumb(i)); +} + + +int inumb(int *n) +{ + int i, j, f; + Tchar ii; + + f = 0; + if (n) { + if ((j = cbits(ii = getch())) == '+') + f = 1; + else if (j == '-') + f = -1; + else + ch = ii; + } + i = atoi0(); + if (n && f) + i = *n + f * i; + i = quant(i, res); + vflag = 0; + res = dfactd = dfact = 1; + if (nonumb) + i = 0; + return(i); +} + + +int quant(int n, int m) +{ + int i, neg; + + neg = 0; + if (n < 0) { + neg++; + n = -n; + } + /* better as i = ((n + m/2)/m)*m */ + i = n / m; + if (n - m * i > m / 2) + i += 1; + i *= m; + if (neg) + i = -i; + return(i); +} blob - /dev/null blob + c2801e4709d31dd2dac33ce79a56d72356a3735b (mode 644) --- /dev/null +++ src/cmd/troff/n5.c @@ -0,0 +1,1149 @@ +/* + * troff5.c + * + * misc processing requests + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +int iflist[NIF]; +int ifx; +int ifnum = 0; /* trying numeric expression for .if or .ie condition */ + +void casead(void) +{ + int i; + + ad = 1; + /* leave admod alone */ + if (skip()) + return; + switch (i = cbits(getch())) { + case 'r': /* right adj, left ragged */ + admod = 2; + break; + case 'l': /* left adj, right ragged */ + admod = ad = 0; /* same as casena */ + break; + case 'c': /*centered adj*/ + admod = 1; + break; + case 'b': + case 'n': + admod = 0; + break; + case '0': + case '2': + case '4': + ad = 0; + case '1': + case '3': + case '5': + admod = (i - '0') / 2; + } +} + + +void casena(void) +{ + ad = 0; +} + + +void casefi(void) +{ + tbreak(); + fi = 1; + pendnf = 0; +} + + +void casenf(void) +{ + tbreak(); + fi = 0; +} + + +void casers(void) +{ + dip->nls = 0; +} + + +void casens(void) +{ + dip->nls++; +} + + +chget(int c) +{ + Tchar i; + + if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') { + ch = i; + return(c); + } else + return cbits(i); /* was (i & BYTEMASK) */ +} + + +void casecc(void) +{ + cc = chget('.'); +} + + +void casec2(void) +{ + c2 = chget('\''); +} + + +void casehc(void) +{ + ohc = chget(OHC); +} + + +void casetc(void) +{ + tabc = chget(0); +} + + +void caselc(void) +{ + dotc = chget(0); +} + + +void casehy(void) +{ + int i; + + hyf = 1; + if (skip()) + return; + noscale++; + i = atoi0(); + noscale = 0; + if (nonumb) + return; + hyf = max(i, 0); +} + + +void casenh(void) +{ + hyf = 0; +} + + +max(int aa, int bb) +{ + if (aa > bb) + return(aa); + else + return(bb); +} + + +void casece(void) +{ + int i; + + noscale++; + skip(); + i = max(atoi0(), 0); + if (nonumb) + i = 1; + tbreak(); + ce = i; + noscale = 0; +} + + +void casein(void) +{ + int i; + + if (skip()) + i = in1; + else { + i = max(hnumb(&in), 0); + if (nonumb) + i = in1; + } + tbreak(); + in1 = in; + in = i; + if (!nc) { + un = in; + setnel(); + } +} + + +void casell(void) +{ + int i; + + if (skip()) + i = ll1; + else { + i = max(hnumb(&ll), INCH / 10); + if (nonumb) + i = ll1; + } + ll1 = ll; + ll = i; + setnel(); +} + + +void caselt(void) +{ + int i; + + if (skip()) + i = lt1; + else { + i = max(hnumb(<), 0); + if (nonumb) + i = lt1; + } + lt1 = lt; + lt = i; +} + + +void caseti(void) +{ + int i; + + if (skip()) + return; + i = max(hnumb(&in), 0); + tbreak(); + un1 = i; + setnel(); +} + + +void casels(void) +{ + int i; + + noscale++; + if (skip()) + i = ls1; + else { + i = max(inumb(&ls), 1); + if (nonumb) + i = ls1; + } + ls1 = ls; + ls = i; + noscale = 0; +} + + +void casepo(void) +{ + int i; + + if (skip()) + i = po1; + else { + i = max(hnumb(&po), 0); + if (nonumb) + i = po1; + } + po1 = po; + po = i; + if (TROFF & !ascii) + esc += po - po1; +} + + +void casepl(void) +{ + int i; + + skip(); + if ((i = vnumb(&pl)) == 0) + pl = 11 * INCH; /*11in*/ + else + pl = i; + if (numtabp[NL].val > pl) + numtabp[NL].val = pl; +} + + +void casewh(void) +{ + int i, j, k; + + lgf++; + skip(); + i = vnumb((int *)0); + if (nonumb) + return; + skip(); + j = getrq(); + if ((k = findn(i)) != NTRAP) { + mlist[k] = j; + return; + } + for (k = 0; k < NTRAP; k++) + if (mlist[k] == 0) + break; + if (k == NTRAP) { + flusho(); + ERROR "cannot plant trap." WARN; + return; + } + mlist[k] = j; + nlist[k] = i; +} + + +void casech(void) +{ + int i, j, k; + + lgf++; + skip(); + if (!(j = getrq())) + return; + else + for (k = 0; k < NTRAP; k++) + if (mlist[k] == j) + break; + if (k == NTRAP) + return; + skip(); + i = vnumb((int *)0); + if (nonumb) + mlist[k] = 0; + nlist[k] = i; +} + + +findn(int i) +{ + int k; + + for (k = 0; k < NTRAP; k++) + if ((nlist[k] == i) && (mlist[k] != 0)) + break; + return(k); +} + + +void casepn(void) +{ + int i; + + skip(); + noscale++; + i = max(inumb(&numtabp[PN].val), 0); + noscale = 0; + if (!nonumb) { + npn = i; + npnflg++; + } +} + + +void casebp(void) +{ + int i; + Stack *savframe; + + if (dip != d) + return; + savframe = frame; + skip(); + if ((i = inumb(&numtabp[PN].val)) < 0) + i = 0; + tbreak(); + if (!nonumb) { + npn = i; + npnflg++; + } else if (dip->nls) + return; + eject(savframe); +} + +void casetm(void) +{ + casetm1(0, stderr); +} + + +void casefm(void) +{ + static struct fcache { + char *name; + FILE *fp; + } fcache[15]; + int i; + + if ( skip() || !getname()) { + ERROR "fm: missing filename" WARN; + return; + } + + for (i = 0; i < 15 && fcache[i].fp != NULL; i++) { + if (strcmp(nextf, fcache[i].name) == 0) + break; + } + if (i >= 15) { + ERROR "fm: too many streams" WARN; + return; + } + if (fcache[i].fp == NULL) { + if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) { + ERROR "fm: cannot open %s", nextf WARN; + return; + } + fcache[i].name = strdupl(nextf); + } + casetm1(0, fcache[i].fp); +} + +void casetm1(int ab, FILE *out) +{ + int i, j, c; + char *p; + char tmbuf[NTM]; + + lgf++; + copyf++; + if (ab) { + if (skip()) + ERROR "User Abort" WARN; + else { + extern int error; + int savtrac = trace; + i = trace = 0; + noscale++; + i = inumb(&trace); + noscale--; + if (i) { + error = i; + if (nlflg || skip()) + ERROR "User Abort, exit code %d", i WARN; + } + trace = savtrac; + } + } else + skip(); + for (i = 0; i < NTM - 2; ) { + if ((c = cbits(getch())) == '\n' || c == RIGHT) + break; + else if (c == MINUS) { /* special pleading for strange encodings */ + tmbuf[i++] = '\\'; + tmbuf[i++] = '-'; + } else if (c == PRESC) { + tmbuf[i++] = '\\'; + tmbuf[i++] = 'e'; + } else if (c == FILLER) { + tmbuf[i++] = '\\'; + tmbuf[i++] = '&'; + } else if (c == UNPAD) { + tmbuf[i++] = '\\'; + tmbuf[i++] = ' '; + } else if (c == OHC) { + tmbuf[i++] = '\\'; + tmbuf[i++] = '%'; + } else if (c >= ALPHABET) { + p = chname(c); + switch (*p) { + case MBchar: + sprintf(&tmbuf[i], p+1); + break; + case Number: + sprintf(&tmbuf[i], "\\N'%s'", p+1); + break; + case Troffchar: + if ((j = strlen(p+1)) == 2) + sprintf(&tmbuf[i], "\\(%s", p+1); + else + sprintf(&tmbuf[i], "\\C'%s'", p+1); + break; + default: + sprintf(&tmbuf[i]," %s? ", p); + break; + } + j = strlen(&tmbuf[i]); + i += j; + } else + tmbuf[i++] = c; + } + tmbuf[i] = 0; + if (ab) /* truncate output */ + obufp = obuf; /* should be a function in n2.c */ + flusho(); + if (i) + fprintf(out, "%s\n", tmbuf); + fflush(out); + copyf--; + lgf--; +} + + +void casesp(void) +{ + casesp1(0); +} + +void casesp1(int a) +{ + int i, j, savlss; + + tbreak(); + if (dip->nls || trap) + return; + i = findt1(); + if (!a) { + skip(); + j = vnumb((int *)0); + if (nonumb) + j = lss; + } else + j = a; + if (j == 0) + return; + if (i < j) + j = i; + savlss = lss; + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + if ((i + j) < 0) + j = -i; + lss = j; + newline(0); + lss = savlss; +} + + +void casert(void) +{ + int a, *p; + + skip(); + if (dip != d) + p = &dip->dnl; + else + p = &numtabp[NL].val; + a = vnumb(p); + if (nonumb) + a = dip->mkline; + if ((a < 0) || (a >= *p)) + return; + nb++; + casesp1(a - *p); +} + + +void caseem(void) +{ + lgf++; + skip(); + em = getrq(); +} + + +void casefl(void) +{ + tbreak(); + if (!ascii) + ptflush(); + flusho(); +} + + +void caseev(void) +{ + int nxev; + + if (skip()) { +e0: + if (evi == 0) + return; + nxev = evlist[--evi]; + goto e1; + } + noscale++; + nxev = atoi0(); + noscale = 0; + if (nonumb) + goto e0; + flushi(); + if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) { + flusho(); + ERROR "cannot do .ev %d", nxev WARN; + if (error) + done2(040); + else + edone(040); + return; + } + evlist[evi++] = ev; +e1: + if (ev == nxev) + return; + ev = nxev; + envp = &env[ev]; +} + +void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */ +{ + *e1 = *e2; /* rumor hath that this fails on some machines */ +} + + +void caseel(void) +{ + if (--ifx < 0) { + ifx = 0; + iflist[0] = 0; + } + caseif1(2); +} + + +void caseie(void) +{ + if (ifx >= NIF) { + ERROR "if-else overflow." WARN; + ifx = 0; + edone(040); + } + caseif1(1); + ifx++; +} + + +void caseif(void) +{ + caseif1(0); +} + +void caseif1(int x) +{ + extern int falsef; + int notflag, true; + Tchar i; + + if (x == 2) { + notflag = 0; + true = iflist[ifx]; + goto i1; + } + true = 0; + skip(); + if ((cbits(i = getch())) == '!') { + notflag = 1; + } else { + notflag = 0; + ch = i; + } + ifnum++; + i = atoi0(); + ifnum = 0; + if (!nonumb) { + if (i > 0) + true++; + goto i1; + } + i = getch(); + switch (cbits(i)) { + case 'e': + if (!(numtabp[PN].val & 01)) + true++; + break; + case 'o': + if (numtabp[PN].val & 01) + true++; + break; + case 'n': + if (NROFF) + true++; + break; + case 't': + if (TROFF) + true++; + break; + case ' ': + break; + default: + true = cmpstr(i); + } +i1: + true ^= notflag; + if (x == 1) + iflist[ifx] = !true; + if (true) { +i2: + while ((cbits(i = getch())) == ' ') + ; + if (cbits(i) == LEFT) + goto i2; + ch = i; + nflush++; + } else { + if (!nlflg) { + copyf++; + falsef++; + eatblk(0); + copyf--; + falsef--; + } + } +} + +void eatblk(int inblk) +{ + int cnt, i; + + cnt = 0; + do { + if (ch) { + i = cbits(ch); + ch = 0; + } else + i = cbits(getch0()); + if (i == ESC) + cnt++; + else { + if (cnt == 1) + switch (i) { + case '{': i = LEFT; break; + case '}': i = RIGHT; break; + case '\n': i = 'x'; break; + } + cnt = 0; + } + if (i == LEFT) eatblk(1); + } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT))); + if (i == '\n') { + nlflg++; + if (ip == 0) + numtabp[CD].val++; + } +} + + +cmpstr(Tchar c) +{ + int j, delim; + Tchar i; + int val; + int savapts, savapts1, savfont, savfont1, savpts, savpts1; + Tchar string[1280]; + Tchar *sp; + + if (ismot(c)) + return(0); + delim = cbits(c); + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + sp = string; + while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1]) + *sp++ = i; + if (sp >= string + 1280) { + ERROR "too-long string compare." WARN; + edone(0100); + } + if (nlflg) { + val = sp==string; + goto rtn; + } + *sp = 0; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + val = 1; + sp = string; + while ((j = cbits(i = getch())) != delim && j != '\n') { + if (*sp != i) { + eat(delim); + val = 0; + goto rtn; + } + sp++; + } + if (*sp) + val = 0; +rtn: + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + return(val); +} + + +void caserd(void) +{ + + lgf++; + skip(); + getname(); + if (!iflg) { + if (quiet) { + if (NROFF) { + echo_off(); + flusho(); + } + fprintf(stderr, "\007"); /*bell*/ + } else { + if (nextf[0]) { + fprintf(stderr, "%s:", nextf); + } else { + fprintf(stderr, "\007"); /*bell*/ + } + } + } + collect(); + tty++; + pushi(RD_OFFSET, PAIR('r','d')); +} + + +rdtty(void) +{ + char onechar; + + onechar = 0; + if (read(0, &onechar, 1) == 1) { + if (onechar == '\n') + tty++; + else + tty = 1; + if (tty != 3) + return(onechar); + } + tty = 0; + if (NROFF && quiet) + echo_on(); + return(0); +} + + +void caseec(void) +{ + eschar = chget('\\'); +} + + +void caseeo(void) +{ + eschar = 0; +} + + +void caseta(void) +{ + int i, j, k; + + tabtab[0] = nonumb = 0; + for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) { + if (skip()) + break; + k = tabtab[max(i-1, 0)] & TABMASK; + if ((j = max(hnumb(&k), 0)) > TABMASK) { + ERROR "Tab too far away" WARN; + j = TABMASK; + } + tabtab[i] = j & TABMASK; + if (!nonumb) + switch (cbits(ch)) { + case 'C': + tabtab[i] |= CTAB; + break; + case 'R': + tabtab[i] |= RTAB; + break; + default: /*includes L*/ + break; + } + nonumb = ch = 0; + } + if (!skip()) + ERROR "Too many tab stops" WARN; + tabtab[i] = 0; +} + + +void casene(void) +{ + int i, j; + + skip(); + i = vnumb((int *)0); + if (nonumb) + i = lss; + if (dip == d && numtabp[NL].val == -1) { + newline(1); + return; + } + if (i > (j = findt1())) { + i = lss; + lss = j; + dip->nls = 0; + newline(0); + lss = i; + } +} + + +void casetr(void) +{ + int i, j; + Tchar k; + + lgf++; + skip(); + while ((i = cbits(k=getch())) != '\n') { + if (ismot(k)) + return; + if (ismot(k = getch())) + return; + if ((j = cbits(k)) == '\n') + j = ' '; + trtab[i] = j; + } +} + + +void casecu(void) +{ + cu++; + caseul(); +} + + +void caseul(void) +{ + int i; + + noscale++; + skip(); + i = max(atoi0(), 0); + if (nonumb) + i = 1; + if (ul && (i == 0)) { + font = sfont; + ul = cu = 0; + } + if (i) { + if (!ul) { + sfont = font; + font = ulfont; + } + ul = i; + } + noscale = 0; + mchbits(); +} + + +void caseuf(void) +{ + int i, j; + + if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1) + ulfont = ULFONT; /*default underline position*/ + else + ulfont = j; + if (NROFF && ulfont == FT) + ulfont = ULFONT; +} + + +void caseit(void) +{ + int i; + + lgf++; + it = itmac = 0; + noscale++; + skip(); + i = atoi0(); + skip(); + if (!nonumb && (itmac = getrq())) + it = i; + noscale = 0; +} + + +void casemc(void) +{ + int i; + + if (icf > 1) + ic = 0; + icf = 0; + if (skip()) + return; + ic = getch(); + icf = 1; + skip(); + i = max(hnumb((int *)0), 0); + if (!nonumb) + ics = i; +} + + +void casemk(void) +{ + int i, j; + + if (dip != d) + j = dip->dnl; + else + j = numtabp[NL].val; + if (skip()) { + dip->mkline = j; + return; + } + if ((i = getrq()) == 0) + return; + numtabp[findr(i)].val = j; +} + + +void casesv(void) +{ + int i; + + skip(); + if ((i = vnumb((int *)0)) < 0) + return; + if (nonumb) + i = 1; + sv += i; + caseos(); +} + + +void caseos(void) +{ + int savlss; + + if (sv <= findt1()) { + savlss = lss; + lss = sv; + newline(0); + lss = savlss; + sv = 0; + } +} + + +void casenm(void) +{ + int i; + + lnmod = nn = 0; + if (skip()) + return; + lnmod++; + noscale++; + i = inumb(&numtabp[LN].val); + if (!nonumb) + numtabp[LN].val = max(i, 0); + getnm(&ndf, 1); + getnm(&nms, 0); + getnm(&ni, 0); + getnm(&nmwid, 3); /* really kludgy! */ + noscale = 0; + nmbits = chbits; +} + +/* + * .nm relies on the fact that illegal args are skipped; don't warn + * for illegality of these + */ +void getnm(int *p, int min) +{ + int i; + int savtr = trace; + + eat(' '); + if (skip()) + return; + trace = 0; + i = atoi0(); + if (nonumb) + return; + *p = max(i, min); + trace = savtr; +} + + +void casenn(void) +{ + noscale++; + skip(); + nn = max(atoi0(), 1); + noscale = 0; +} + + +void caseab(void) +{ + casetm1(1, stderr); + done3(0); +} + + +/* nroff terminal handling has been pretty well excised */ +/* as part of the merge with troff. these are ghostly remnants, */ +/* called, but doing nothing. restore them at your peril. */ + + +void save_tty(void) /*save any tty settings that may be changed*/ +{ +} + + +void restore_tty(void) /*restore tty settings from beginning*/ +{ +} + + +void set_tty(void) +{ +} + + +void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/ +{ +} + + +void echo_on(void) /*restore ECHO after .rd in "-q" mode*/ +{ +} blob - /dev/null blob + e4affa17d3a0a72583823b9745043adec806a182 (mode 644) --- /dev/null +++ src/cmd/troff/n6.c @@ -0,0 +1,362 @@ +#include "tdef.h" +#include "ext.h" +#include "fns.h" +#include + +/* + * n6.c -- width functions, sizes and fonts +*/ + +n_width(Tchar j) +{ + int i, k; + + if (iszbit(j)) + return 0; + if (ismot(j)) { + if (isvmot(j)) + return(0); + k = absmot(j); + if (isnmot(j)) + k = -k; + return(k); + } + i = cbits(j); + if (i < ' ') { + if (i == '\b') + return(-widthp); + if (i == PRESC) + i = eschar; + else if (i == HX) + return(0); + } + if (i == ohc) + return(0); + i = trtab[i]; + if (i < ' ') + return(0); + if (i >= t.tfont.nchars) /* not on the font */ + k = t.Char; /* really ought to check properly */ + else + k = t.tfont.wp[i].wid * t.Char; + widthp = k; + return(k); +} + + +Tchar n_setch(int c) +{ + return t_setch(c); +} + +Tchar n_setabs(void) /* set absolute char from \N'...' */ +{ /* for now, a no-op */ + return t_setabs(); +} + +int n_findft(int i) +{ + int k; + + if ((k = i - '0') >= 0 && k <= nfonts && k < smnt) + return(k); + for (k = 0; fontlab[k] != i; k++) + if (k > nfonts) + return(-1); + return(k); +} + + + +void n_mchbits(void) +{ + chbits = 0; + setfbits(chbits, font); + sps = width(' ' | chbits); +} + + +void n_setps(void ) +{ + int i, j; + + i = cbits(getch()); + if (isdigit(i)) { /* \sd or \sdd */ + i -= '0'; + if (i == 0) /* \s0 */ + ; + else if (i <= 3 && (ch=getch()) && isdigit(cbits(ch))) { /* \sdd */ + ch = 0; + } + } else if (i == '(') { /* \s(dd */ + getch(); + getch(); + } else if (i == '+' || i == '-') { /* \s+, \s- */ + j = cbits(getch()); + if (isdigit(j)) { /* \s+d, \s-d */ + ; + } else if (j == '(') { /* \s+(dd, \s-(dd */ + getch(); + getch(); + } + } +} + + +Tchar n_setht(void) /* set character height from \H'...' */ +{ + + getch(); + inumb(&apts); + getch(); + return(0); +} + + +Tchar n_setslant(void) /* set slant from \S'...' */ +{ + int n; + + getch(); + n = 0; + n = inumb(&n); + getch(); + return(0); +} + + +void n_caseft(void) +{ + skip(); + setfont(1); +} + + +void n_setfont(int a) +{ + int i, j; + + if (a) + i = getrq(); + else + i = getsn(); + if (!i || i == 'P') { + j = font1; + goto s0; + } + if (i == 'S' || i == '0') + return; + if ((j = findft(i)) == -1) + return; +s0: + font1 = font; + font = j; + mchbits(); +} + + +void n_setwd(void) +{ + int base, wid; + Tchar i; + int delim, emsz, k; + int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; + + base = numtabp[ST].val = numtabp[ST].val = wid = numtabp[CT].val = 0; + if (ismot(i = getch())) + return; + delim = cbits(i); + savhp = numtabp[HP].val; + numtabp[HP].val = 0; + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + setwdf++; + while (cbits(i = getch()) != delim && !nlflg) { + k = width(i); + wid += k; + numtabp[HP].val += k; + if (!ismot(i)) { + emsz = (INCH * pts + 36) / 72; + } else if (isvmot(i)) { + k = absmot(i); + if (isnmot(i)) + k = -k; + base -= k; + emsz = 0; + } else + continue; + if (base < numtabp[SB].val) + numtabp[SB].val = base; + if ((k = base + emsz) > numtabp[ST].val) + numtabp[ST].val = k; + } + setn1(wid, 0, (Tchar) 0); + numtabp[HP].val = savhp; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + setwdf = 0; +} + + +Tchar n_vmot(void) +{ + dfact = lss; + vflag++; + return n_mot(); +} + + +Tchar n_hmot(void) +{ + dfact = EM; + return n_mot(); +} + + +Tchar n_mot(void) +{ + int j, n; + Tchar i; + + j = HOR; + getch(); /*eat delim*/ + if (n = atoi0()) { + if (vflag) + j = VERT; + i = makem(quant(n, j)); + } else + i = 0; + getch(); + vflag = 0; + dfact = 1; + return(i); +} + + +Tchar n_sethl(int k) +{ + int j; + Tchar i; + + j = t.Halfline; + if (k == 'u') + j = -j; + else if (k == 'r') + j = -2 * j; + vflag++; + i = makem(j); + vflag = 0; + return(i); +} + + +Tchar n_makem(int i) +{ + Tchar j; + + if (i >= 0) + j = i; + else + j = -i; + j |= MOT; + if (i < 0) + j |= NMOT; + if (vflag) + j |= VMOT; + return(j); +} + + +void n_casefp(void) +{ + int i, j; + + skip(); + if ((i = cbits(getch()) - '0') < 0 || i > nfonts) + return; + if (skip() || !(j = getrq())) + return; + fontlab[i] = j; +} + + + +void n_casebd(void) +{ + int i, j, k; + + k = 0; +bd0: + if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { + if (k) + goto bd1; + else + return; + } + if (j == smnt) { + k = smnt; + goto bd0; + } + if (k) { + sbold = j; + j = k; + } +bd1: + skip(); + noscale++; + bdtab[j] = atoi0(); + noscale = 0; +} + + +void n_casevs(void) +{ + int i; + + skip(); + vflag++; + dfact = INCH; /*default scaling is points!*/ + dfactd = 72; + res = VERT; + i = inumb(&lss); + if (nonumb) + i = lss1; + if (i < VERT) + i = VERT; /* was VERT */ + lss1 = lss; + lss = i; +} + + + + +Tchar n_xlss(void) +{ + /* stores \x'...' into + /* two successive Tchars. + /* the first contains HX, the second the value, + /* encoded as a vertical motion. + /* decoding is done in n2.c by pchar(). + */ + int i; + + getch(); + dfact = lss; + i = quant(atoi0(), VERT); + dfact = 1; + getch(); + if (i >= 0) + *pbp++ = MOT | VMOT | i; + else + *pbp++ = MOT | VMOT | NMOT | -i; + return(HX); +} blob - /dev/null blob + c22a485c40500041447e5b5fb9ac181f76df109e (mode 644) --- /dev/null +++ src/cmd/troff/n7.c @@ -0,0 +1,834 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#ifdef STRICT + /* not in ANSI or POSIX */ +#define isascii(a) ((a) >= 0 && (a) <= 127) +#endif + +#define GETCH gettch +Tchar gettch(void); + + +/* + * troff7.c + * + * text + */ + +int brflg; + +void tbreak(void) +{ + int pad, k; + Tchar *i, j; + int resol; + int un0 = un; + + trap = 0; + if (nb) + return; + if (dip == d && numtabp[NL].val == -1) { + newline(1); + return; + } + if (!nc) { + setnel(); + if (!wch) + return; + if (pendw) + getword(1); + movword(); + } else if (pendw && !brflg) { + getword(1); + movword(); + } + *linep = dip->nls = 0; + if (NROFF && dip == d) + horiz(po); + if (lnmod) + donum(); + lastl = ne; + if (brflg != 1) { + totout = 0; + } else if (ad) { + if ((lastl = ll - un) < ne) + lastl = ne; + } + if (admod && ad && (brflg != 2)) { + lastl = ne; + adsp = adrem = 0; + if (admod == 1) + un += quant(nel / 2, HOR); + else if (admod == 2) + un += nel; + } + totout++; + brflg = 0; + if (lastl + un > dip->maxl) + dip->maxl = lastl + un; + horiz(un); + if (NROFF) { + if (adrem % t.Adj) + resol = t.Hor; + else + resol = t.Adj; + } else + resol = HOR; + + lastl = ne + (nwd-1) * adsp + adrem; + for (i = line; nc > 0; ) { + if ((cbits(j = *i++)) == ' ') { + pad = 0; + do { + pad += width(j); + nc--; + } while ((cbits(j = *i++)) == ' '); + i--; + pad += adsp; + --nwd; + if (adrem) { + if (adrem < 0) { + pad -= resol; + adrem += resol; + } else if ((totout & 01) || adrem / resol >= nwd) { + pad += resol; + adrem -= resol; + } + } + pchar((Tchar) WORDSP); + horiz(pad); + } else { + pchar(j); + nc--; + } + } + if (ic) { + if ((k = ll - un0 - lastl + ics) > 0) + horiz(k); + pchar(ic); + } + if (icf) + icf++; + else + ic = 0; + ne = nwd = 0; + un = in; + setnel(); + newline(0); + if (dip != d) { + if (dip->dnl > dip->hnl) + dip->hnl = dip->dnl; + } else { + if (numtabp[NL].val > dip->hnl) + dip->hnl = numtabp[NL].val; + } + for (k = ls - 1; k > 0 && !trap; k--) + newline(0); + spread = 0; +} + +void donum(void) +{ + int i, nw; + int lnv = numtabp[LN].val; + + nrbits = nmbits; + nw = width('1' | nrbits); + if (nn) { + nn--; + goto d1; + } + if (lnv % ndf) { + numtabp[LN].val++; +d1: + un += nw * (nmwid + nms + ni); + return; + } + i = 0; + do { /* count digits in numtabp[LN].val */ + i++; + } while ((lnv /= 10) > 0); + horiz(nw * (ni + max(nmwid-i, 0))); + nform = 0; + fnumb(numtabp[LN].val, pchar); + un += nw * nms; + numtabp[LN].val++; +} + + +void text(void) +{ + Tchar i; + static int spcnt; + + nflush++; + numtabp[HP].val = 0; + if ((dip == d) && (numtabp[NL].val == -1)) { + newline(1); + return; + } + setnel(); + if (ce || !fi) { + nofill(); + return; + } + if (pendw) + goto t4; + if (pendt) + if (spcnt) + goto t2; + else + goto t3; + pendt++; + if (spcnt) + goto t2; + while ((cbits(i = GETCH())) == ' ') { + spcnt++; + numtabp[HP].val += sps; + widthp = sps; + } + if (nlflg) { +t1: + nflush = pendt = ch = spcnt = 0; + callsp(); + return; + } + ch = i; + if (spcnt) { +t2: + tbreak(); + if (nc || wch) + goto rtn; + un += spcnt * sps; + spcnt = 0; + setnel(); + if (trap) + goto rtn; + if (nlflg) + goto t1; + } +t3: + if (spread) + goto t5; + if (pendw || !wch) +t4: + if (getword(0)) + goto t6; + if (!movword()) + goto t3; +t5: + if (nlflg) + pendt = 0; + adsp = adrem = 0; + if (ad) { + if (nwd == 1) + adsp = nel; + else + adsp = nel / (nwd - 1); + adsp = (adsp / HOR) * HOR; + adrem = nel - adsp*(nwd-1); + } + brflg = 1; + tbreak(); + spread = 0; + if (!trap) + goto t3; + if (!nlflg) + goto rtn; +t6: + pendt = 0; + ckul(); +rtn: + nflush = 0; +} + + +void nofill(void) +{ + int j; + Tchar i; + + if (!pendnf) { + over = 0; + tbreak(); + if (trap) + goto rtn; + if (nlflg) { + ch = nflush = 0; + callsp(); + return; + } + adsp = adrem = 0; + nwd = 10000; + } + while ((j = (cbits(i = GETCH()))) != '\n') { + if (j == ohc) + continue; + if (j == CONT) { + pendnf++; + nflush = 0; + flushi(); + ckul(); + return; + } + j = width(i); + widthp = j; + numtabp[HP].val += j; + storeline(i, j); + } + if (ce) { + ce--; + if ((i = quant(nel / 2, HOR)) > 0) + un += i; + } + if (!nc) + storeline((Tchar)FILLER, 0); + brflg = 2; + tbreak(); + ckul(); +rtn: + pendnf = nflush = 0; +} + + +void callsp(void) +{ + int i; + + if (flss) + i = flss; + else + i = lss; + flss = 0; + casesp1(i); +} + + +void ckul(void) +{ + if (ul && (--ul == 0)) { + cu = 0; + font = sfont; + mchbits(); + } + if (it && --it == 0 && itmac) + control(itmac, 0); +} + + +void storeline(Tchar c, int w) +{ + int diff; + + if (linep >= line + lnsize - 2) { + lnsize += LNSIZE; + diff = linep - line; + if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) { + if (linep && diff) + linep = line + diff; + } else { + if (over) { + return; + } else { + flusho(); + ERROR "Line overflow." WARN; + over++; + *linep++ = LEFTHAND; + w = width(LEFTHAND); + nc++; + c = '\n'; + } + } + } + *linep++ = c; + ne += w; + nel -= w; + nc++; +} + + +void newline(int a) +{ + int i, j, nlss; + int opn; + + if (a) + goto nl1; + if (dip != d) { + j = lss; + pchar1((Tchar)FLSS); + if (flss) + lss = flss; + i = lss + dip->blss; + dip->dnl += i; + pchar1((Tchar)i); + pchar1((Tchar)'\n'); + lss = j; + dip->blss = flss = 0; + if (dip->alss) { + pchar1((Tchar)FLSS); + pchar1((Tchar)dip->alss); + pchar1((Tchar)'\n'); + dip->dnl += dip->alss; + dip->alss = 0; + } + if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac) + if (control(dip->dimac, 0)) { + trap++; + dip->ditf++; + } + return; + } + j = lss; + if (flss) + lss = flss; + nlss = dip->alss + dip->blss + lss; + numtabp[NL].val += nlss; + if (TROFF && ascii) { + dip->alss = dip->blss = 0; + } + pchar1((Tchar)'\n'); + flss = 0; + lss = j; + if (numtabp[NL].val < pl) + goto nl2; +nl1: + ejf = dip->hnl = numtabp[NL].val = 0; + ejl = frame; + if (donef) { + if ((!nc && !wch) || ndone) + done1(0); + ndone++; + donef = 0; + if (frame == stk) + nflush++; + } + opn = numtabp[PN].val; + numtabp[PN].val++; + if (npnflg) { + numtabp[PN].val = npn; + npn = npnflg = 0; + } +nlpn: + if (numtabp[PN].val == pfrom) { + print++; + pfrom = -1; + } else if (opn == pto) { + print = 0; + opn = -1; + chkpn(); + goto nlpn; + } + if (print) + ptpage(numtabp[PN].val); /* supposedly in a clean state so can pause */ + if (stop && print) { + dpn++; + if (dpn >= stop) { + dpn = 0; + ptpause(); + } + } +nl2: + trap = 0; + if (numtabp[NL].val == 0) { + if ((j = findn(0)) != NTRAP) + trap = control(mlist[j], 0); + } else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) { + if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) { + flusho(); + ERROR "Trap botch." WARN; + done2(-5); + } + trap = control(mlist[j], 0); + } +} + + +findn1(int a) +{ + int i, j; + + for (i = 0; i < NTRAP; i++) { + if (mlist[i]) { + if ((j = nlist[i]) < 0) + j += pl; + if (j == a) + break; + } + } + return(i); +} + + +void chkpn(void) +{ + pto = *(pnp++); + pfrom = pto>=0 ? pto : -pto; + if (pto == -INT_MAX) { + flusho(); + done1(0); + } + if (pto < 0) { + pto = -pto; + print++; + pfrom = 0; + } +} + + +findt(int a) +{ + int i, j, k; + + k = INT_MAX; + if (dip != d) { + if (dip->dimac && (i = dip->ditrap - a) > 0) + k = i; + return(k); + } + for (i = 0; i < NTRAP; i++) { + if (mlist[i]) { + if ((j = nlist[i]) < 0) + j += pl; + if ((j -= a) <= 0) + continue; + if (j < k) + k = j; + } + } + i = pl - a; + if (k > i) + k = i; + return(k); +} + + +findt1(void) +{ + int i; + + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + return(findt(i)); +} + + +void eject(Stack *a) +{ + int savlss; + + if (dip != d) + return; + ejf++; + if (a) + ejl = a; + else + ejl = frame; + if (trap) + return; +e1: + savlss = lss; + lss = findt(numtabp[NL].val); + newline(0); + lss = savlss; + if (numtabp[NL].val && !trap) + goto e1; +} + + +movword(void) +{ + int w; + Tchar i, *wp; + int savwch, hys; + + over = 0; + wp = wordp; + if (!nwd) { + while (cbits(*wp++) == ' ') { + wch--; + wne -= sps; + } + wp--; + } + if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) && + (!(hyf & 02) || (findt1() > lss))) + hyphen(wp); + savwch = wch; + hyp = hyptr; + nhyp = 0; + while (*hyp && *hyp <= wp) + hyp++; + while (wch) { + if (hyoff != 1 && *hyp == wp) { + hyp++; + if (!wdstart || (wp > wdstart + 1 && wp < wdend && + (!(hyf & 04) || wp < wdend - 1) && /* 04 => last 2 */ + (!(hyf & 010) || wp > wdstart + 2))) { /* 010 => 1st 2 */ + nhyp++; + storeline((Tchar)IMP, 0); + } + } + i = *wp++; + w = width(i); + wne -= w; + wch--; + storeline(i, w); + } + if (nel >= 0) { + nwd++; + return(0); /* line didn't fill up */ + } + if (TROFF) + xbits((Tchar)HYPHEN, 1); + hys = width((Tchar)HYPHEN); +m1: + if (!nhyp) { + if (!nwd) + goto m3; + if (wch == savwch) + goto m4; + } + if (*--linep != IMP) + goto m5; + if (!(--nhyp)) + if (!nwd) + goto m2; + if (nel < hys) { + nc--; + goto m1; + } +m2: + if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) { + *linep = (*(linep - 1) & SFMASK) | HYPHEN; + w = width(*linep); + nel -= w; + ne += w; + linep++; + } +m3: + nwd++; +m4: + wordp = wp; + return(1); /* line filled up */ +m5: + nc--; + w = width(*linep); + ne -= w; + nel += w; + wne += w; + wch++; + wp--; + goto m1; +} + + +void horiz(int i) +{ + vflag = 0; + if (i) + pchar(makem(i)); +} + + +void setnel(void) +{ + if (!nc) { + linep = line; + if (un1 >= 0) { + un = un1; + un1 = -1; + } + nel = ll - un; + ne = adsp = adrem = 0; + } +} + + +getword(int x) +{ + int j, k; + Tchar i, *wp; + int noword; + int obits; + + noword = 0; + if (x) + if (pendw) { + *pendw = 0; + goto rtn; + } + if (wordp = pendw) + goto g1; + hyp = hyptr; + wordp = word; + over = wne = wch = 0; + hyoff = 0; + obits = chbits; + while (1) { /* picks up 1st char of word */ + j = cbits(i = GETCH()); + if (j == '\n') { + wne = wch = 0; + noword = 1; + goto rtn; + } + if (j == ohc) { + hyoff = 1; /* 1 => don't hyphenate */ + continue; + } + if (j == ' ') { + numtabp[HP].val += sps; + widthp = sps; + storeword(i, sps); + continue; + } + break; + } + storeword(' ' | obits, sps); + if (spflg) { + storeword(' ' | obits, sps); + spflg = 0; + } +g0: + if (j == CONT) { + pendw = wordp; + nflush = 0; + flushi(); + return(1); + } + if (hyoff != 1) { + if (j == ohc) { + hyoff = 2; + *hyp++ = wordp; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + goto g1; + } + if (((j == '-' || j == EMDASH)) && !(i & ZBIT)) /* zbit avoids \X */ + if (wordp > word + 1) { + hyoff = 2; + *hyp++ = wordp + 1; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + } + } + j = width(i); + numtabp[HP].val += j; + storeword(i, j); +g1: + j = cbits(i = GETCH()); + if (j != ' ') { + static char *sentchar = ".?!"; /* sentence terminators */ + if (j != '\n') + goto g0; + wp = wordp-1; /* handle extra space at end of sentence */ + while (wp >= word) { + j = cbits(*wp--); + if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER) + continue; + for (k = 0; sentchar[k]; k++) + if (j == sentchar[k]) { + spflg++; + break; + } + break; + } + } + *wordp = 0; + numtabp[HP].val += sps; +rtn: + for (wp = word; *wp; wp++) { + if (ismot(j)) + break; /* drechsler */ + j = cbits(*wp); + if (j == ' ') + continue; + if (!(isascii(j) && isdigit(j)) && j != '-') + break; + } + if (*wp == 0) /* all numbers, so don't hyphenate */ + hyoff = 1; + wdstart = 0; + wordp = word; + pendw = 0; + *hyp++ = 0; + setnel(); + return(noword); +} + + +void storeword(Tchar c, int w) +{ + Tchar *savp; + int i; + + if (wordp >= word + wdsize - 2) { + wdsize += WDSIZE; + savp = word; + if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) { + if (wordp) + wordp = word + (wordp - savp); + if (pendw) + pendw = word + (pendw - savp); + if (wdstart) + wdstart = word + (wdstart - savp); + if (wdend) + wdend = word + (wdend - savp); + for (i = 0; i < NHYP; i++) + if (hyptr[i]) + hyptr[i] = word + (hyptr[i] - savp); + } else { + if (over) { + return; + } else { + flusho(); + ERROR "Word overflow." WARN; + over++; + c = LEFTHAND; + w = width(LEFTHAND); + } + } + } + widthp = w; + wne += w; + *wordp++ = c; + wch++; +} + + +Tchar gettch(void) +{ + extern int c_isalnum; + Tchar i; + int j; + + if (TROFF) + return getch(); + + i = getch(); + j = cbits(i); + if (ismot(i) || fbits(i) != ulfont) + return(i); + if (cu) { + if (trtab[j] == ' ') { + setcbits(i, '_'); + setfbits(i, FT); /* default */ + } + return(i); + } + /* should test here for characters that ought to be underlined */ + /* in the old nroff, that was the 200 bit on the width! */ + /* for now, just do letters, digits and certain special chars */ + if (j <= 127) { + if (!isalnum(j)) + setfbits(i, FT); + } else { + if (j < c_isalnum) + setfbits(i, FT); + } + return(i); +} blob - /dev/null blob + d1be50805bb6eb7336ed94638c7fb20870e0c683 (mode 644) --- /dev/null +++ src/cmd/troff/n8.c @@ -0,0 +1,540 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#define HY_BIT 0200 /* stuff in here only works for 7-bit ascii */ + /* this value is used (as a literal) in suftab.c */ + /* to encode possible hyphenation points in suffixes. */ + /* it could be changed, by widening the tables */ + /* to be shorts instead of chars. */ + +/* + * troff8.c + * + * hyphenation + */ + +int hexsize = 0; /* hyphenation exception list size */ +char *hbufp = NULL; /* base of list */ +char *nexth = NULL; /* first free slot in list */ +Tchar *hyend; + +#define THRESH 160 /* digram goodness threshold */ +int thresh = THRESH; + +int texhyphen(void); +static int alpha(Tchar); + +void hyphen(Tchar *wp) +{ + int j; + Tchar *i; + + i = wp; + while (punct((*i++))) + ; + if (!alpha(*--i)) + return; + wdstart = i++; + while (alpha(*i++)) + ; + hyend = wdend = --i - 1; + while (punct((*i++))) + ; + if (*--i) + return; + if (wdend - wdstart < 4) /* 4 chars is too short to hyphenate */ + return; + hyp = hyptr; + *hyp = 0; + hyoff = 2; + + /* for now, try exceptions first, then tex (if hyphalg is non-zero), + then suffix and digram if tex didn't hyphenate it at all. + */ + + if (!exword() && !texhyphen() && !suffix()) + digram(); + + /* this appears to sort hyphenation points into increasing order */ + *hyp++ = 0; + if (*hyptr) + for (j = 1; j; ) { + j = 0; + for (hyp = hyptr + 1; *hyp != 0; hyp++) { + if (*(hyp - 1) > *hyp) { + j++; + i = *hyp; + *hyp = *(hyp - 1); + *(hyp - 1) = i; + } + } + } +} + +static alpha(Tchar i) /* non-zero if really alphabetic */ +{ + if (ismot(i)) + return 0; + else if (cbits(i) >= ALPHABET) /* this isn't very elegant, but there's */ + return 0; /* no good way to make sure i is in range for */ + else /* the call of isalpha */ + return isalpha(cbits(i)); +} + + +punct(Tchar i) +{ + if (!i || alpha(i)) + return(0); + else + return(1); +} + + +void caseha(void) /* set hyphenation algorithm */ +{ + hyphalg = HYPHALG; + if (skip()) + return; + noscale++; + hyphalg = atoi0(); + noscale = 0; +} + + +void caseht(void) /* set hyphenation threshold; not in manual! */ +{ + thresh = THRESH; + if (skip()) + return; + noscale++; + thresh = atoi0(); + noscale = 0; +} + + +char *growh(char *where) +{ + char *new; + + hexsize += NHEX; + if ((new = grow(hbufp, hexsize, sizeof(char))) == NULL) + return NULL; + if (new == hbufp) { + return where; + } else { + int diff; + diff = where - hbufp; + hbufp = new; + return new + diff; + } +} + + +void casehw(void) +{ + int i, k; + char *j; + Tchar t; + + if (nexth == NULL) { + if ((nexth = hbufp = grow(hbufp, NHEX, sizeof(char))) == NULL) { + ERROR "No space for exception word list." WARN; + return; + } + hexsize = NHEX; + } + k = 0; + while (!skip()) { + if ((j = nexth) >= hbufp + hexsize - 2) + if ((j = nexth = growh(j)) == NULL) + goto full; + for (;;) { + if (ismot(t = getch())) + continue; + i = cbits(t); + if (i == ' ' || i == '\n') { + *j++ = 0; + nexth = j; + *j = 0; + if (i == ' ') + break; + else + return; + } + if (i == '-') { + k = HY_BIT; + continue; + } + *j++ = maplow(i) | k; + k = 0; + if (j >= hbufp + hexsize - 2) + if ((j = growh(j)) == NULL) + goto full; + } + } + return; +full: + ERROR "Cannot grow exception word list." WARN; + *nexth = 0; +} + + +int exword(void) +{ + Tchar *w; + char *e, *save; + + e = hbufp; + while (1) { + save = e; + if (e == NULL || *e == 0) + return(0); + w = wdstart; + while (*e && w <= hyend && (*e & 0177) == maplow(cbits(*w))) { + e++; + w++; + } + if (!*e) { + if (w-1 == hyend || (w == wdend && maplow(cbits(*w)) == 's')) { + w = wdstart; + for (e = save; *e; e++) { + if (*e & HY_BIT) + *hyp++ = w; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + w++; + } + return(1); + } else { + e++; + continue; + } + } else + while (*e++) + ; + } +} + + +suffix(void) +{ + Tchar *w; + char *s, *s0; + Tchar i; + extern char *suftab[]; + +again: + i = cbits(*hyend); + if (!alpha(i)) + return(0); + if (i < 'a') + i -= 'A' - 'a'; + if ((s0 = suftab[i-'a']) == 0) + return(0); + for (;;) { + if ((i = *s0 & 017) == 0) + return(0); + s = s0 + i - 1; + w = hyend - 1; + while (s > s0 && w >= wdstart && (*s & 0177) == maplow(cbits(*w))) { + s--; + w--; + } + if (s == s0) + break; + s0 += i; + } + s = s0 + i - 1; + w = hyend; + if (*s0 & HY_BIT) + goto mark; + while (s > s0) { + w--; + if (*s-- & HY_BIT) { +mark: + hyend = w - 1; + if (*s0 & 0100) /* 0100 used in suftab to encode something too */ + continue; + if (!chkvow(w)) + return(0); + *hyp++ = w; + } + } + if (*s0 & 040) + return(0); + if (exword()) + return(1); + goto again; +} + + +maplow(int i) +{ + if (isupper(i)) + i = tolower(i); + return(i); +} + + +vowel(int i) +{ + switch (i) { + case 'a': case 'A': + case 'e': case 'E': + case 'i': case 'I': + case 'o': case 'O': + case 'u': case 'U': + case 'y': case 'Y': + return(1); + default: + return(0); + } +} + + +Tchar *chkvow(Tchar *w) +{ + while (--w >= wdstart) + if (vowel(cbits(*w))) + return(w); + return(0); +} + + +void digram(void) +{ + Tchar *w; + int val; + Tchar *nhyend, *maxw; + int maxval; + extern char bxh[26][13], bxxh[26][13], xxh[26][13], xhx[26][13], hxx[26][13]; + +again: + if (!(w = chkvow(hyend + 1))) + return; + hyend = w; + if (!(w = chkvow(hyend))) + return; + nhyend = w; + maxval = 0; + w--; + while (++w < hyend && w < wdend - 1) { + val = 1; + if (w == wdstart) + val *= dilook('a', cbits(*w), bxh); + else if (w == wdstart + 1) + val *= dilook(cbits(*(w-1)), cbits(*w), bxxh); + else + val *= dilook(cbits(*(w-1)), cbits(*w), xxh); + val *= dilook(cbits(*w), cbits(*(w+1)), xhx); + val *= dilook(cbits(*(w+1)), cbits(*(w+2)), hxx); + if (val > maxval) { + maxval = val; + maxw = w + 1; + } + } + hyend = nhyend; + if (maxval > thresh) + *hyp++ = maxw; + goto again; +} + + +dilook(int a, int b, char t[26][13]) +{ + int i, j; + + i = t[maplow(a)-'a'][(j = maplow(b)-'a')/2]; + if (!(j & 01)) + i >>= 4; + return(i & 017); +} + + +/* here beginneth the tex hyphenation code, as interpreted freely */ +/* the main difference is that there is no attempt to squeeze space */ +/* as tightly at tex does. */ + +static int texit(Tchar *, Tchar *); +static int readpats(void); +static void install(char *); +static void fixup(void); +static int trieindex(int, int); + +static char pats[50000]; /* size ought to be computed dynamically */ +static char *nextpat = pats; +static char *trie[27*27]; /* english-specific sizes */ + +int texhyphen(void) +{ + static int loaded = 0; /* -1: couldn't find tex file */ + + if (hyphalg == 0 || loaded == -1) /* non-zero => tex for now */ + return 0; + if (loaded == 0) { + if (readpats()) + loaded = 1; + else + loaded = -1; + } + return texit(wdstart, wdend); +} + +static int texit(Tchar *start, Tchar *end) /* hyphenate as in tex, return # found */ +{ + int nw, i, k, equal, cnt[500]; + char w[500+1], *np, *pp, *wp, *xpp, *xwp; + + w[0] = '.'; + for (nw = 1; start <= end && nw < 500-1; nw++, start++) + w[nw] = maplow(tolower(cbits(*start))); + start -= (nw - 1); + w[nw++] = '.'; + w[nw] = 0; +/* + * printf("try %s\n", w); +*/ + for (i = 0; i <= nw; i++) + cnt[i] = '0'; + + for (wp = w; wp < w + nw; wp++) { + for (pp = trie[trieindex(*wp, *(wp+1))]; pp < nextpat; ) { + if (pp == 0 /* no trie entry */ + || *pp != *wp /* no match on 1st letter */ + || *(pp+1) != *(wp+1)) /* no match on 2nd letter */ + break; /* so move to next letter of word */ + equal = 1; + for (xpp = pp+2, xwp = wp+2; *xpp; ) + if (*xpp++ != *xwp++) { + equal = 0; + break; + } + if (equal) { + np = xpp+1; /* numpat */ + for (k = wp-w; *np; k++, np++) + if (*np > cnt[k]) + cnt[k] = *np; +/* + * printf("match: %s %s\n", pp, xpp+1); +*/ + } + pp += *(pp-1); /* skip over pattern and numbers to next */ + } + } +/* + * for (i = 0; i < nw; i++) printf("%c", w[i]); + * printf(" "); + * for (i = 0; i <= nw; i++) printf("%c", cnt[i]); + * printf("\n"); +*/ +/* + * for (i = 1; i < nw - 1; i++) { + * if (i > 2 && i < nw - 3 && cnt[i] % 2) + * printf("-"); + * if (cbits(start[i-1]) != '.') + * printf("%c", cbits(start[i-1])); + * } + * printf("\n"); +*/ + for (i = 1; i < nw -1; i++) + if (i > 2 && i < nw - 3 && cnt[i] % 2) + *hyp++ = start + i - 1; + return hyp - hyptr; /* non-zero if a hyphen was found */ +} + +/* + This code assumes that hyphen.tex looks like + % some comments + \patterns{ % more comments + pat5ter4ns, 1 per line, SORTED, nothing else + } + more goo + \hyphenation{ % more comments + ex-cep-tions, one per line; i ignore this part for now + } + + this code is NOT robust against variations. unfortunately, + it looks like every local language version of this file has + a different format. i have also made no provision for weird + characters. sigh. +*/ + +static int readpats(void) +{ + FILE *fp; + char buf[200], buf1[200]; + + if ((fp = fopen(unsharp(TEXHYPHENS), "r")) == NULL + && (fp = fopen(unsharp(DWBalthyphens), "r")) == NULL) { + ERROR "warning: can't find hyphen.tex" WARN; + return 0; + } + + while (fgets(buf, sizeof buf, fp) != NULL) { + sscanf(buf, "%s", buf1); + if (strcmp(buf1, "\\patterns{") == 0) + break; + } + while (fgets(buf, sizeof buf, fp) != NULL) { + if (buf[0] == '}') + break; + install(buf); + } + fclose(fp); + fixup(); + return 1; +} + +static void install(char *s) /* map ab4c5de to: 12 abcde \0 00405 \0 */ +{ + int npat, lastpat; + char num[500], *onextpat = nextpat; + + num[0] = '0'; + *nextpat++ = ' '; /* fill in with count later */ + for (npat = lastpat = 0; *s != '\n' && *s != '\0'; s++) { + if (isdigit(*s)) { + num[npat] = *s; + lastpat = npat; + } else { + *nextpat++ = *s; + npat++; + num[npat] = '0'; + } + } + *nextpat++ = 0; + if (nextpat > pats + sizeof(pats)-20) { + ERROR "tex hyphenation table overflow, tail end ignored" WARN; + nextpat = onextpat; + } + num[lastpat+1] = 0; + strcat(nextpat, num); + nextpat += strlen(nextpat) + 1; +} + +static void fixup(void) /* build indexes of where . a b c ... start */ +{ + char *p, *lastc; + int n; + + for (lastc = pats, p = pats+1; p < nextpat; p++) + if (*p == ' ') { + *lastc = p - lastc; + lastc = p; + } + *lastc = p - lastc; + for (p = pats+1; p < nextpat; ) { + n = trieindex(p[0], p[1]); + if (trie[n] == 0) + trie[n] = p; + p += p[-1]; + } + /* printf("pats = %d\n", nextpat - pats); */ +} + +static int trieindex(int d1, int d2) +{ + return 27 * (d1 == '.' ? 0 : d1 - 'a' + 1) + (d2 == '.' ? 0 : d2 - 'a' + 1); +} blob - /dev/null blob + 5cd70648cd77a9a560f1d1d02c5520df02ac76ef (mode 644) --- /dev/null +++ src/cmd/troff/n9.c @@ -0,0 +1,488 @@ +#include "tdef.h" +#include "ext.h" +#include "fns.h" + +/* + * troff9.c + * + * misc functions + */ + +Tchar setz(void) +{ + Tchar i; + + if (!ismot(i = getch())) + i |= ZBIT; + return(i); +} + +void setline(void) +{ + Tchar *i; + Tchar c; + int length; + int j, w, cnt, delim, rem, temp; + Tchar linebuf[NC]; + + if (ismot(c = getch())) + return; + delim = cbits(c); + vflag = 0; + dfact = EM; + length = quant(atoi0(), HOR); + dfact = 1; + if (!length) { + eat(delim); + return; + } +s0: + if ((j = cbits(c = getch())) == delim || j == '\n') { + ch = c; + c = RULE | chbits; + } else if (cbits(c) == FILLER) + goto s0; + w = width(c); + if (w <= 0) { + ERROR "zero-width underline character ignored" WARN; + c = RULE | chbits; + w = width(c); + } + i = linebuf; + if (length < 0) { + *i++ = makem(length); + length = -length; + } + if (!(cnt = length / w)) { + *i++ = makem(-(temp = ((w - length) / 2))); + *i++ = c; + *i++ = makem(-(w - length - temp)); + goto s1; + } + if (rem = length % w) { + if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN) + *i++ = c | ZBIT; + *i++ = makem(rem); + } + if (cnt) { + *i++ = RPT; + *i++ = cnt; + *i++ = c; + } +s1: + *i = 0; + eat(delim); + pushback(linebuf); +} + + +eat(int c) +{ + int i; + + while ((i = cbits(getch())) != c && i != '\n') + ; + return(i); +} + + +void setov(void) +{ + int j, k; + Tchar i, o[NOV+1]; + int delim, w[NOV+1]; + + if (ismot(i = getch())) + return; + delim = cbits(i); + for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) { + o[k] = i; + w[k] = width(i); + } + o[k] = w[k] = 0; + if (o[0]) + for (j = 1; j; ) { + j = 0; + for (k = 1; o[k] ; k++) { + if (w[k-1] < w[k]) { + j++; + i = w[k]; + w[k] = w[k-1]; + w[k-1] = i; + i = o[k]; + o[k] = o[k-1]; + o[k-1] = i; + } + } + } + else + return; + *pbp++ = makem(w[0] / 2); + for (k = 0; o[k]; k++) + ; + while (k>0) { + k--; + *pbp++ = makem(-((w[k] + w[k+1]) / 2)); + *pbp++ = o[k]; + } +} + + +void setbra(void) +{ + int k; + Tchar i, *j, dwn; + int cnt, delim; + Tchar brabuf[NC]; + + if (ismot(i = getch())) + return; + delim = cbits(i); + j = brabuf + 1; + cnt = 0; + if (NROFF) + dwn = (2 * t.Halfline) | MOT | VMOT; + else + dwn = EM | MOT | VMOT; + while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) { + *j++ = i | ZBIT; + *j++ = dwn; + cnt++; + } + if (--cnt < 0) + return; + else if (!cnt) { + ch = *(j - 2); + return; + } + *j = 0; + if (NROFF) + *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; + else + *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; + *--j &= ~ZBIT; + pushback(brabuf); +} + + +void setvline(void) +{ + int i; + Tchar c, rem, ver, neg; + int cnt, delim, v; + Tchar vlbuf[NC]; + Tchar *vlp; + + if (ismot(c = getch())) + return; + delim = cbits(c); + dfact = lss; + vflag++; + i = quant(atoi0(), VERT); + dfact = 1; + if (!i) { + eat(delim); + vflag = 0; + return; + } + if ((cbits(c = getch())) == delim) { + c = BOXRULE | chbits; /*default box rule*/ + } else + getch(); + c |= ZBIT; + neg = 0; + if (i < 0) { + i = -i; + neg = NMOT; + } + if (NROFF) + v = 2 * t.Halfline; + else { + v = EM; + if (v < VERT) /* ATT EVK hack: Erik van Konijnenburg, */ + v = VERT; /* hvlpb!evkonij, ATT NSI Hilversum, Holland */ + } + + cnt = i / v; + rem = makem(i % v) | neg; + ver = makem(v) | neg; + vlp = vlbuf; + if (!neg) + *vlp++ = ver; + if (absmot(rem) != 0) { + *vlp++ = c; + *vlp++ = rem; + } + while (vlp < vlbuf + NC - 3 && cnt--) { + *vlp++ = c; + *vlp++ = ver; + } + *(vlp - 2) &= ~ZBIT; + if (!neg) + vlp--; + *vlp = 0; + pushback(vlbuf); + vflag = 0; +} + +#define NPAIR (NC/2-6) /* max pairs in spline, etc. */ + +void setdraw(void) /* generate internal cookies for a drawing function */ +{ + int i, j, k, dx[NPAIR], dy[NPAIR], delim, type; + Tchar c, drawbuf[NC]; + int drawch = '.'; /* character to draw with */ + + /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */ + /* this does drawing function f with character c and the */ + /* specified dx,dy pairs interpreted as appropriate */ + /* pairs are deltas from last point, except for radii */ + + /* l dx dy: line from here by dx,dy */ + /* c x: circle of diameter x, left side here */ + /* e x y: ellipse of diameters x,y, left side here */ + /* a dx1 dy1 dx2 dy2: + ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */ + /* ~ dx1 dy1 dx2 dy2...: + spline to dx1,dy1 to dx2,dy2 ... */ + /* b x c: + built-up character of type c, ht x */ + /* f dx dy ...: f is any other char: like spline */ + + if (ismot(c = getch())) + return; + delim = cbits(c); + numerr.escarg = type = cbits(getch()); + if (type == '~') /* head off the .tr ~ problem */ + type = 's'; + for (i = 0; i < NPAIR ; i++) { + skip(); + vflag = 0; + dfact = EM; + dx[i] = quant(atoi0(), HOR); + if (dx[i] > MAXMOT) + dx[i] = MAXMOT; + else if (dx[i] < -MAXMOT) + dx[i] = -MAXMOT; + skip(); + if (type == 'c') { + dy[i] = 0; + goto eat; + } + vflag = 1; + dfact = lss; + dy[i] = quant(atoi0(), VERT); + if (dy[i] > MAXMOT) + dy[i] = MAXMOT; + else if (dy[i] < -MAXMOT) + dy[i] = -MAXMOT; +eat: + if (cbits(c = getch()) != ' ') { /* must be the end */ + if (cbits(c) != delim) { + drawch = cbits(c); + getch(); + } + i++; + break; + } + } + dfact = 1; + vflag = 0; + if (TROFF) { + drawbuf[0] = DRAWFCN | chbits | ZBIT; + drawbuf[1] = type | chbits | ZBIT; + drawbuf[2] = drawch | chbits | ZBIT; + for (k = 0, j = 3; k < i; k++) { + drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k])); + drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k])); + } + if (type == DRAWELLIPSE) { + drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */ + j = 6; + } else if (type == DRAWBUILD) { + drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */ + drawbuf[2] &= ~ZBIT; /* width taken from drawing char */ + j = 5; + } + drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */ + drawbuf[j] = 0; + pushback(drawbuf); + } +} + + +void casefc(void) +{ + int i; + Tchar j; + + gchtab[fc] &= ~FCBIT; + fc = IMP; + padc = ' '; + if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n') + return; + fc = i; + gchtab[fc] |= FCBIT; + if (skip() || ismot(ch) || (ch = cbits(ch)) == fc) + return; + padc = ch; +} + + +Tchar setfield(int x) +{ + Tchar ii, jj, *fp; + int i, j; + int length, ws, npad, temp, type; + Tchar **pp, *padptr[NPP]; + Tchar fbuf[FBUFSZ]; + int savfc, savtc, savlc; + Tchar rchar; + int savepos; + static Tchar wbuf[] = { WORDSP, 0}; + + if (x == tabch) + rchar = tabc | chbits; + else if (x == ldrch) + rchar = dotc | chbits; + temp = npad = ws = 0; + savfc = fc; + savtc = tabch; + savlc = ldrch; + tabch = ldrch = fc = IMP; + savepos = numtabp[HP].val; + gchtab[tabch] &= ~TABBIT; + gchtab[ldrch] &= ~LDRBIT; + gchtab[fc] &= ~FCBIT; + gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; + for (j = 0; ; j++) { + if ((tabtab[j] & TABMASK) == 0) { + if (x == savfc) + ERROR "zero field width." WARN; + jj = 0; + goto rtn; + } + if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 ) + break; + } + type = tabtab[j] & ~TABMASK; + fp = fbuf; + pp = padptr; + if (x == savfc) { + while (1) { + j = cbits(ii = getch()); + jj = width(ii); + widthp = jj; + numtabp[HP].val += jj; + if (j == padc) { + npad++; + *pp++ = fp; + if (pp > padptr + NPP - 1) + break; + goto s1; + } else if (j == savfc) + break; + else if (j == '\n') { + temp = j; + if (nlflg && ip == 0) { + numtabp[CD].val--; + nlflg = 0; + } + break; + } + ws += jj; +s1: + *fp++ = ii; + if (fp > fbuf + FBUFSZ - 3) + break; + } + if (ws) + *fp++ = WORDSP; + if (!npad) { + npad++; + *pp++ = fp; + *fp++ = 0; + } + *fp++ = temp; + *fp = 0; + temp = i = (j = length - ws) / npad; + i = (i / HOR) * HOR; + if ((j -= i * npad) < 0) + j = -j; + ii = makem(i); + if (temp < 0) + ii |= NMOT; + for (; npad > 0; npad--) { + *(*--pp) = ii; + if (j) { + j -= HOR; + (*(*pp)) += HOR; + } + } + pushback(fbuf); + jj = 0; + } else if (type == 0) { + /*plain tab or leader*/ + if ((j = width(rchar)) > 0) { + int nchar = length / j; + while (nchar-->0 && pbp < &pbbuf[NC-3]) { + numtabp[HP].val += j; + widthp = j; + *pbp++ = rchar; + } + length %= j; + } + if (length) + jj = length | MOT; + else + jj = getch0(); + if (savepos > 0) + pushback(wbuf); + } else { + /*center tab*/ + /*right tab*/ + while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) { + jj = width(ii); + ws += jj; + numtabp[HP].val += jj; + widthp = jj; + *fp++ = ii; + if (fp > fbuf + FBUFSZ - 3) + break; + } + *fp++ = ii; + *fp = 0; + if (type == RTAB) + length -= ws; + else + length -= ws / 2; /*CTAB*/ + pushback(fbuf); + if ((j = width(rchar)) != 0 && length > 0) { + int nchar = length / j; + while (nchar-- > 0 && pbp < &pbbuf[NC-3]) + *pbp++ = rchar; + length %= j; + } + if (savepos > 0) + pushback(wbuf); + length = (length / HOR) * HOR; + jj = makem(length); + if (nlflg) { + if (ip == 0) + numtabp[CD].val--; + nlflg = 0; + } + } +rtn: + gchtab[fc] &= ~FCBIT; + gchtab[tabch] &= ~TABBIT; + gchtab[ldrch] &= ~LDRBIT; + fc = savfc; + tabch = savtc; + ldrch = savlc; + gchtab[fc] |= FCBIT; + gchtab[tabch] = TABBIT; + gchtab[ldrch] |= LDRBIT; + numtabp[HP].val = savepos; + return(jj); +} blob - /dev/null blob + a80cec6437edd23dfd4e7ec144b8a0d061e126b7 (mode 644) --- /dev/null +++ src/cmd/troff/ni.c @@ -0,0 +1,390 @@ +#include +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +char termtab[NS]; /* term type added in ptinit() */ +char fontdir[NS]; /* added in casefp; not used by nroff */ +char devname[20]; /* default output device */ + +Numtab numtab[NN] = { + { PAIR('%', 0) }, + { PAIR('n', 'l') }, + { PAIR('y', 'r') }, + { PAIR('h', 'p') }, + { PAIR('c', 't') }, + { PAIR('d', 'n') }, + { PAIR('m', 'o') }, + { PAIR('d', 'y') }, + { PAIR('d', 'w') }, + { PAIR('l', 'n') }, + { PAIR('d', 'l') }, + { PAIR('s', 't') }, + { PAIR('s', 'b') }, + { PAIR('c', '.') }, + { PAIR('$', '$') }, +}; + + +int alphabet = 256; /* latin-1 */ +int pto = 10000; +int pfrom = 1; +int print = 1; +char nextf[NS] = TMACDIR; +char mfiles[NMF][NS]; +int nmfi = 0; +int oldbits = -1; +int init = 1; +int fc = IMP; /* field character */ +int eschar = '\\'; +int pl; +int po; +FILE *ptid; + +int dfact = 1; +int dfactd = 1; +int res = 1; +int smnt = 0; /* beginning of special fonts */ +int ascii = 0; /* ascii normally off for troff, on for nroff; -a turns on */ +int lg; +int pnlist[NPN] = { -1 }; + + +int *pnp = pnlist; +int npn = 1; +int npnflg = 1; +int dpn = -1; +int totout = 1; +int ulfont = ULFONT; +int tabch = TAB; +int ldrch = LEADER; + + +Contab contab[NM] = { + C(PAIR('d', 's'), caseds), + C(PAIR('a', 's'), caseas), + C(PAIR('s', 'p'), casesp), + C(PAIR('f', 't'), caseft), + C(PAIR('p', 's'), caseps), + C(PAIR('v', 's'), casevs), + C(PAIR('n', 'r'), casenr), + C(PAIR('i', 'f'), caseif), + C(PAIR('i', 'e'), caseie), + C(PAIR('e', 'l'), caseel), + C(PAIR('p', 'o'), casepo), + C(PAIR('t', 'l'), casetl), + C(PAIR('t', 'm'), casetm), + C(PAIR('f', 'm'), casefm), + C(PAIR('b', 'p'), casebp), + C(PAIR('c', 'h'), casech), + C(PAIR('p', 'n'), casepn), + C(PAIR('b', 'r'), tbreak), + C(PAIR('t', 'i'), caseti), + C(PAIR('n', 'e'), casene), + C(PAIR('n', 'f'), casenf), + C(PAIR('c', 'e'), casece), + C(PAIR('f', 'i'), casefi), + C(PAIR('i', 'n'), casein), + C(PAIR('l', 'l'), casell), + C(PAIR('n', 's'), casens), + C(PAIR('m', 'k'), casemk), + C(PAIR('r', 't'), casert), + C(PAIR('a', 'm'), caseam), + C(PAIR('d', 'e'), casede), + C(PAIR('d', 'i'), casedi), + C(PAIR('d', 'a'), caseda), + C(PAIR('w', 'h'), casewh), + C(PAIR('d', 't'), casedt), + C(PAIR('i', 't'), caseit), + C(PAIR('r', 'm'), caserm), + C(PAIR('r', 'r'), caserr), + C(PAIR('r', 'n'), casern), + C(PAIR('a', 'd'), casead), + C(PAIR('r', 's'), casers), + C(PAIR('n', 'a'), casena), + C(PAIR('p', 'l'), casepl), + C(PAIR('t', 'a'), caseta), + C(PAIR('t', 'r'), casetr), + C(PAIR('u', 'l'), caseul), + C(PAIR('c', 'u'), casecu), + C(PAIR('l', 't'), caselt), + C(PAIR('n', 'x'), casenx), + C(PAIR('s', 'o'), caseso), + C(PAIR('i', 'g'), caseig), + C(PAIR('t', 'c'), casetc), + C(PAIR('f', 'c'), casefc), + C(PAIR('e', 'c'), caseec), + C(PAIR('e', 'o'), caseeo), + C(PAIR('l', 'c'), caselc), + C(PAIR('e', 'v'), caseev), + C(PAIR('r', 'd'), caserd), + C(PAIR('a', 'b'), caseab), + C(PAIR('f', 'l'), casefl), + C(PAIR('e', 'x'), caseex), + C(PAIR('s', 's'), casess), + C(PAIR('f', 'p'), casefp), + C(PAIR('c', 's'), casecs), + C(PAIR('b', 'd'), casebd), + C(PAIR('l', 'g'), caselg), + C(PAIR('h', 'c'), casehc), + C(PAIR('h', 'y'), casehy), + C(PAIR('n', 'h'), casenh), + C(PAIR('n', 'm'), casenm), + C(PAIR('n', 'n'), casenn), + C(PAIR('s', 'v'), casesv), + C(PAIR('o', 's'), caseos), + C(PAIR('l', 's'), casels), + C(PAIR('c', 'c'), casecc), + C(PAIR('c', '2'), casec2), + C(PAIR('e', 'm'), caseem), + C(PAIR('a', 'f'), caseaf), + C(PAIR('h', 'a'), caseha), + C(PAIR('h', 'w'), casehw), + C(PAIR('m', 'c'), casemc), + C(PAIR('p', 'm'), casepm), + C(PAIR('p', 'i'), casepi), + C(PAIR('u', 'f'), caseuf), + C(PAIR('p', 'c'), casepc), + C(PAIR('h', 't'), caseht), + C(PAIR('c', 'f'), casecf), + C(PAIR('s', 'y'), casesy), + C(PAIR('l', 'f'), caself), + C(PAIR('p', 't'), casept), + C(PAIR('g', 'd'), casegd), +}; + + +Tbuf _oline; + +/* + * troff environment block + */ + +Env env[NEV] = { { /* this sets up env[0] */ +/* int ics */ 0, /* insertion character space, set by .mc */ +/* int sps */ 0, +/* int spacesz */ 0, +/* int lss */ 0, +/* int lss1 */ 0, +/* int ll */ 0, +/* int ll1 */ 0, +/* int lt */ 0, +/* int lt1 */ 0, +/* Tchar ic */ 0, /* insertion character (= margin character) */ +/* int icf */ 0, /* insertion character flag */ +/* Tchar chbits */ 0, /* size+font bits for current character */ +/* Tchar spbits */ 0, +/* Tchar nmbits */ 0, /* size+font bits for number from .nm */ +/* int apts */ PS, /* actual point size -- as requested by user */ +/* int apts1 */ PS, /* need not match an existent size */ +/* int pts */ PS, /* hence, this is the size that really exists */ +/* int pts1 */ PS, +/* int font */ FT, +/* int font1 */ FT, +/* int ls */ 1, +/* int ls1 */ 1, +/* int ad */ 1, +/* int nms */ 1, /* .nm multiplier */ +/* int ndf */ 1, /* .nm separator */ +/* int nmwid */ 3, /* max width of .nm numbers */ +/* int fi */ 1, +/* int cc */ '.', +/* int c2 */ '\'', +/* int ohc */ OHC, +/* int tdelim */ IMP, +/* int hyf */ 1, +/* int hyoff */ 0, +/* int hyphalg */ HYPHALG, +/* int un1 */ -1, +/* int tabc */ 0, +/* int dotc */ '.', +/* int adsp */ 0, /* add this much space to each padding point */ +/* int adrem */ 0, /* excess space to add until it runs out */ +/* int lastl */ 0, /* last text on current output line */ +/* int nel */ 0, /* how much space left on current output line */ +/* int admod */ 0, /* adjust mode */ +/* Tchar *wordp */ 0, +/* int spflg */ 0, /* probably to indicate space after punctuation needed */ +/* Tchar *linep */ 0, +/* Tchar *wdend */ 0, +/* Tchar *wdstart */ 0, +/* int wne */ 0, +/* int ne */ 0, /* how much space taken on current output line */ +/* int nc */ 0, /* #characters (incl blank) on output line */ +/* int nb */ 0, +/* int lnmod */ 0, /* line number mode, set by .nm */ +/* int nwd */ 0, /* number of words on current output line */ +/* int nn */ 0, /* from .nn command */ +/* int ni */ 0, /* indent of .nm numbers, probably */ +/* int ul */ 0, +/* int cu */ 0, +/* int ce */ 0, +/* int in */ 0, /* indent and previous value */ +/* int in1 */ 0, +/* int un */ 0, /* unindent of left margin in some way */ +/* int wch */ 0, +/* int pendt */ 0, +/* Tchar *pendw */ (Tchar *)0, +/* int pendnf */ 0, +/* int spread */ 0, +/* int it */ 0, /* input trap count */ +/* int itmac */ 0, +} }; + +Env *envp = env; /* start off in env 0 */ + +Numerr numerr; + +Stack *frame, *stk, *ejl; +Stack *nxf; + +int pipeflg; +int hflg; /* used in nroff only */ +int eqflg; /* used in nroff only */ + +int xpts; +int ppts; +int pfont; +int mpts; +int mfont; +int cs; +int ccs; +int bd; + +int stdi; +int quiet; +int stop; +char ibuf[IBUFSZ]; +char xbuf[IBUFSZ]; +char *ibufp; +char *xbufp; +char *eibuf; +char *xeibuf; +Tchar pbbuf[NC]; /* pushback buffer for arguments, \n, etc. */ +Tchar *pbp = pbbuf; /* next free slot in pbbuf */ +Tchar *lastpbp = pbbuf; /* pbp in previous stack frame */ +int nx; +int mflg; +Tchar ch = 0; +int ibf; +int ifi; +int iflg; +int rargc; +char **argp; +Ushort trtab[NTRTAB]; +int lgf; +int copyf; +Offset ip; +int nlflg; +int donef; +int nflush; +int nfo; +int padc; +int raw; +int flss; +int nonumb; +int trap; +int tflg; +int ejf; +int dilev; +Offset offset; +int em; +int ds; +Offset woff; +int app; +int ndone; +int lead; +int ralss; +Offset nextb; +Tchar nrbits; +int nform; +int oldmn; +int newmn; +int macerr; +Offset apptr; +int diflg; +int evi; +int vflag; +int noscale; +int po1; +int nlist[NTRAP]; +int mlist[NTRAP]; +int evlist[EVLSZ]; +int ev; +int tty; +int sfont = FT; /* appears to be "standard" font; used by .ul */ +int sv; +int esc; +int widthp; +int xfont; +int setwdf; +int over; +int nhyp; +Tchar **hyp; +Tchar *olinep; +int dotT; +char *unlkp; +Wcache widcache[NWIDCACHE]; +Diver d[NDI]; +Diver *dip; + +int c_hyphen; +int c_emdash; +int c_rule; +int c_minus; +int c_fi; +int c_fl; +int c_ff; +int c_ffi; +int c_ffl; +int c_acute; +int c_grave; +int c_under; +int c_rooten; +int c_boxrule; +int c_lefthand; +int c_dagger; +int c_isalnum; + +Spnames spnames[] = +{ + &c_hyphen, "hy", + &c_emdash, "em", + &c_rule, "ru", + &c_minus, "\\-", + &c_fi, "fi", + &c_fl, "fl", + &c_ff, "ff", + &c_ffi, "Fi", + &c_ffl, "Fl", + &c_acute, "aa", + &c_grave, "ga", + &c_under, "ul", + &c_rooten, "rn", + &c_boxrule, "br", + &c_lefthand, "lh", + &c_dagger, "dg", /* not in nroff?? */ + &c_isalnum, "__", + 0, 0 +}; + + +Tchar (*hmot)(void); +Tchar (*makem)(int i); +Tchar (*setabs)(void); +Tchar (*setch)(int c); +Tchar (*sethl)(int k); +Tchar (*setht)(void); +Tchar (*setslant)(void); +Tchar (*vmot)(void); +Tchar (*xlss)(void); +int (*findft)(int i); +int (*width)(Tchar j); +void (*mchbits)(void); +void (*ptlead)(void); +void (*ptout)(Tchar i); +void (*ptpause)(void); +void (*setfont)(int a); +void (*setps)(void); +void (*setwd)(void); + blob - /dev/null blob + 1aa8a009b7a6671bb1e25ae76119285ed6a88b74 (mode 644) --- /dev/null +++ src/cmd/troff/suftab.c @@ -0,0 +1,612 @@ +/* + * Suffix table + */ + +typedef unsigned char Uchar; + +static Uchar sufa[] = { + 02,0200+'t', /* -TA */ + 02,0200+'s', /* -SA */ + 03,0200+'t','r', /* -TRA */ + 03,0200+'d','r', /* -DRA */ + 03,0200+'b','r', /* -BRA */ + 02,0200+'p', /* -PA */ + 02,0200+'n', /* -NA */ + 02,0200+'m', /* -MA */ + 03,0200+'p','l', /* -PLA */ + 02,0200+'l', /* -LA */ + 02,0200+'k', /* -KA */ + 03,0200+'t','h', /* -THA */ + 03,0200+'s','h', /* -SHA */ + 02,0200+'g', /* -GA */ + 02,0200+'d', /* -DA */ + 02,0200+'c', /* -CA */ + 02,0200+'b', /* -BA */ + 00 +}; + +static Uchar sufc[] = { + 04,'e','t',0200+'i', /* ET-IC */ + 07,'a','l',0200+'i','s',0200+'t','i', /* AL-IS-TIC */ + 04,'s',0200+'t','i', /* S-TIC */ + 04,'p',0200+'t','i', /* P-TIC */ + 05,0200+'l','y','t',0200+'i', /* -LYT-IC */ + 04,'o','t',0200+'i', /* OT-IC */ + 05,'a','n',0200+'t','i', /* AN-TIC */ + 04,'n',0200+'t','i', /* N-TIC */ + 04,'c',0200+'t','i', /* C-TIC */ + 04,'a','t',0200+'i', /* AT-IC */ + 04,'h',0200+'n','i', /* H-NIC */ + 03,'n',0200+'i', /* N-IC */ + 03,'m',0200+'i', /* M-IC */ + 04,'l',0200+'l','i', /* L-LIC */ + 04,'b',0200+'l','i', /* B-LIC */ + 04,0200+'c','l','i', /* -CLIC */ + 03,'l',0200+'i', /* L-IC */ + 03,'h',0200+'i', /* H-IC */ + 03,'f',0200+'i', /* F-IC */ + 03,'d',0200+'i', /* D-IC */ + 03,0200+'b','i', /* -BIC */ + 03,'a',0200+'i', /* A-IC */ + 03,0200+'m','a', /* -MAC */ + 03,'i',0200+'a', /* I-AC */ + 00 +}; + +static Uchar sufd[] = { + 04,0200+'w','o','r', /* -WORD */ + 04,0200+'l','o','r', /* -LORD */ + 04,0200+'f','o','r', /* -FORD */ + 04,0200+'y','a','r', /* -YARD */ + 04,0200+'w','a','r', /* -WARD */ + 05,0200+'g','u','a','r', /* -GUARD */ + 04,0200+'t','a','r', /* -TARD */ + 05,0200+'b','o','a','r', /* -BOARD */ + 04,0200+'n','a','r', /* -NARD */ + 05,0200+'l','i','a','r', /* -LIARD */ + 04,0200+'i','a','r', /* -IARD */ + 04,0200+'g','a','r', /* -GARD */ + 04,0200+'b','a','r', /* -BARD */ + 03,0200+'r','o', /* -ROD */ + 04,0200+'w','o','o', /* -WOOD */ + 04,0200+'h','o','o', /* -HOOD */ + 04,0200+'m','o','n', /* -MOND */ + 04,0200+'t','e','n', /* -TEND */ + 05,0200+'s','t','a','n', /* -STAND */ + 04,0200+'l','a','n', /* -LAND */ + 04,0200+'h','a','n', /* -HAND */ + 04,0200+'h','o','l', /* -HOLD */ + 04,0200+'f','o','l', /* -FOLD */ + 05,0200+'f','i','e','l', /* -FIELD */ + 03,0200+'v','i', /* -VID */ + 03,0200+'c','i', /* -CID */ + 04,0200+'s','a','i', /* -SAID */ + 04,0200+'m','a','i', /* -MAID */ + 04,'t',0200+'t','e', /* T-TED */ + 03,'t',0200+'e', /* T-ED */ + 04,0200+'d','r','e', /* -DRED */ + 04,0200+'c','r','e', /* -CRED */ + 04,0200+'b','r','e', /* -BRED */ + 05,'v',0200+'e','l','e', /* V-ELED */ + 0100+04,'a','l',0200+'e', /* AL/ED */ + 0140+03,0200+'e','e', /* /EED */ + 040+05,'e','d',0200+'d','e', /* ED-DED */ + 04,'d',0200+'d','e', /* D-DED */ + 040+04,'e','d',0200+'e', /* ED-ED */ + 03,'d',0200+'e', /* D-ED */ + 05,0200+'d','u','c','e', /* -DUCED */ + 0300+02,'e', /* E/D */ + 05,0200+'s','t','e','a', /* -STEAD */ + 05,0200+'a','h','e','a', /* -AHEAD */ + 04,0200+'h','e','a', /* -HEAD */ + 00 +}; + +static Uchar sufe[] = { + 05,'a','r',0200+'i','z', /* AR-IZE */ + 05,'a','n',0200+'i','z', /* AN-IZE */ + 05,'a','l',0200+'i','z', /* AL-IZE */ + 06,0200+'a','r','d',0200+'i','z', /* -ARD-IZE */ + 05,0200+'s','e','l','v', /* -SELVE */ + 05,0200+'k','n','i','v', /* -KNIVE */ + 05,0200+'l','i','e','v', /* -LIEVE */ + 0100+03,0200+'q','u', /* /QUE */ + 07,'o','n',0200+'t','i','n',0200+'u', /* ON-TIN-UE */ + 03,0200+'n','u', /* -NUE */ + 03,0200+'d','u', /* -DUE */ + 0300+02,'u', /* U/E */ + 0300+05,'q','u','a','t', /* QUAT/E */ + 04,'u',0200+'a','t', /* U-ATE */ + 05,0200+'s','t','a','t', /* -STATE */ + 04,0200+'t','a','t', /* -TATE */ + 06,0200+'t','o','r',0200+'a','t', /* -TOR-ATE */ + 05,'e','n',0200+'a','t', /* EN-ATE */ + 04,0200+'m','a','t', /* -MATE */ + 05,0200+'h','o','u','s', /* -HOUSE */ + 05,0200+'c','l','o','s', /* -CLOSE */ + 04,'i',0200+'o','s', /* I-OSE */ + 04,0200+'w','i','s', /* -WISE */ + 05,'a','s',0200+'u','r', /* AS-URE */ + 040+04,0200+'s','u','r', /* -SURE */ + 06,0200+'f','i','g',0200+'u','r', /* -FIG-URE */ + 040+03,0200+'t','r', /* -TRE */ + 05,0200+'s','t','o','r', /* -STORE */ + 04,0200+'f','o','r', /* -FORE */ + 05,0200+'w','h','e','r', /* -WHERE */ + 06,0200+'s','p','h','e','r', /* -SPHERE */ + 03,0200+'d','r', /* -DRE */ + 03,0200+'c','r', /* -CRE */ + 03,0200+'b','r', /* -BRE */ + 05,0200+'s','c','o','p', /* -SCOPE */ + 04,'y',0200+'o','n', /* Y-ONE */ + 05,0200+'s','t','o','n', /* -STONE */ + 05,0200+'p','h','o','n', /* -PHONE */ + 04,0200+'g','o','n', /* -GONE */ + 04,'e',0200+'o','n', /* E-ONE */ + 040+04,0200+'e','n','n', /* -ENNE */ + 040+05,'a',0200+'r','i','n', /* A-RINE */ + 05,0200+'c','l','i','n', /* -CLINE */ + 04,0200+'l','i','n', /* -LINE */ + 007,00200+'r','o','u',00200+'t','i','n', /*-ROU-TINE */ + 04,0200+'s','o','m', /* -SOME */ + 04,0200+'c','o','m', /* -COME */ + 04,0200+'t','i','m', /* -TIME */ + 03,0200+'z','l', /* -ZLE */ + 03,0200+'t','l', /* -TLE */ + 03,0200+'s','l', /* -SLE */ + 03,0200+'p','l', /* -PLE */ + 05,0200+'v','i','l','l', /* -VILLE */ + 04,'c','k',0200+'l', /* CK-LE */ + 03,0200+'k','l', /* -KLE */ + 03,0200+'g','l', /* -GLE */ + 03,0200+'f','l', /* -FLE */ + 03,0200+'d','l', /* -DLE */ + 03,0200+'c','l', /* -CLE */ + 05,0200+'p','a',0200+'b','l', /* -PA-BLE */ + 05,'f','a',0200+'b','l', /* FA-BLE */ + 05,0200+'c','a',0200+'b','l', /* -CA-BLE */ + 06,0200+'s','t','a','b','l', /* -STABLE */ + 04,0200+'a','b','l', /* -ABLE */ + 03,0200+'b','l', /* -BLE */ + 04,0200+'d','a','l', /* -DALE */ + 04,0200+'m','a','l', /* -MALE */ + 04,0200+'s','a','l', /* -SALE */ + 04,0200+'l','i','k', /* -LIKE */ + 0340+05,'g',0200+'u','a','g', /* -G/UAGE */ + 05,0200+'r','i','a','g', /* -RIAGE */ + 05,'e','r',0200+'a','g', /* ER-AGE */ + 04,'m',0200+'a','g', /* M-AGE */ + 04,'k',0200+'a','g', /* K-AGE */ + 04,'d',0200+'a','g', /* D-AGE */ + 04,0200+'w','i','f', /* -WIFE */ + 05,0200+'k','n','i','f', /* -KNIFE */ + 03,0200+'s','e', /* -SEE */ + 04,0200+'f','r','e', /* -FREE */ + 0340+02,'e', /* EE */ + 04,0200+'w','i','d', /* -WIDE */ + 04,0200+'t','i','d', /* -TIDE */ + 04,0200+'s','i','d', /* -SIDE */ + 06,0200+'q','u','e','n','c', /* -QUENCE */ + 07,0200+'f','l','u',0200+'e','n','c', /* -FLU-ENCE */ + 040+06,'e','s',0200+'e','n','c', /* ES-ENCE */ + 06,'e','r',0200+'e','n','c', /* ER-ENCE */ + 05,'i',0200+'e','n','c', /* I-ENCE */ + 040+05,0200+'s','a','n','c', /* -SANCE */ + 06,'e','r',0200+'a','n','c', /* ER-ANCE */ + 06,'a','r',0200+'a','n','c', /* AR-ANCE */ + 05,0200+'n','a','n','c', /* -NANCE */ + 07,0200+'b','a','l',0200+'a','n','c', /* -BAL-ANCE */ + 05,'i',0200+'a','n','c', /* I-ANCE */ + 07,0200+'j','u','s',0200+'t','i','c', /* -JUS-TICE */ + 05,0200+'s','t','i','c', /* -STICE */ + 06,0200+'n','o','v',0200+'i','c', /* NOV-ICE */ + 04,0200+'v','i','c', /* -VICE */ + 05,0200+'p','i','e','c', /* -PIECE */ + 05,0200+'p','l','a','c', /* -PLACE */ + 0340+01, /* /E */ + 00 +}; + +static Uchar suff[] = { + 03,0200+'o','f', /* -OFF */ + 05,0200+'p','r','o','o', /* -PROOF */ + 04,0200+'s','e','l', /* -SELF */ + 03,0200+'r','i', /* -RIF */ + 040+04,0200+'l','i','e', /* -LIEF */ + 00 +}; + +static Uchar sufg[] = { + 03,0200+'l','o', /* -LOG */ + 04,0200+'l','o','n', /* -LONG */ + 05,'t',0200+'t','i','n', /* T-TING */ + 06,0200+'s','t','r','i','n', /* -STRING */ + 05,'r',0200+'r','i','n', /* R-RING */ + 05,'p',0200+'p','i','n', /* P-PING */ + 05,'n',0200+'n','i','n', /* N-NING */ + 05,'m',0200+'m','i','n', /* M-MING */ + 05,'l',0200+'l','i','n', /* L-LING */ + 05,0200+'z','l','i','n', /* -ZLING */ + 05,0200+'t','l','i','n', /* -TLING */ + 040+05,'s',0200+'l','i','n', /* S-LING */ + 05,'r',0200+'l','i','n', /* R-LING */ + 05,0200+'p','l','i','n', /* -PLING */ + 06,'n',0200+'k','l','i','n', /* N-KLING */ + 05,'k',0200+'l','i','n', /* K-LING */ + 05,0200+'g','l','i','n', /* -GLING */ + 05,0200+'f','l','i','n', /* -FLING */ + 05,0200+'d','l','i','n', /* -DLING */ + 05,0200+'c','l','i','n', /* -CLING */ + 05,0200+'b','l','i','n', /* -BLING */ + 06,'y',0200+'t','h','i','n', /* Y-THING */ + 07,'e','e','t','h',0200+'i','n', /* EETH-ING */ + 06,'e',0200+'t','h','i','n', /* E-THING */ + 05,'g',0200+'g','i','n', /* G-GING */ + 05,'d',0200+'d','i','n', /* D-DING */ + 05,'b',0200+'b','i','n', /* B-BING */ + 03,0200+'i','n', /* -ING */ + 00 +}; + +static Uchar sufh[] = { + 05,0200+'m','o','u','t', /* -MOUTH */ + 05,0200+'w','o','r','t', /* -WORTH */ + 04,0200+'w','i','t', /* -WITH */ + 05,'t',0200+'t','i','s', /* T-TISH */ + 05,'e',0200+'t','i','s', /* E-TISH */ + 05,'p',0200+'p','i','s', /* P-PISH */ + 05,'r',0200+'n','i','s', /* R-NISH */ + 05,'n',0200+'n','i','s', /* N-NISH */ + 05,0200+'p','l','i','s', /* -PLISH */ + 05,0200+'g','u','i','s', /* -GUISH */ + 05,0200+'g','l','i','s', /* -GLISH */ + 05,'b',0200+'l','i','s', /* B-LISH */ + 05,'g',0200+'g','i','s', /* G-GISH */ + 05,'d',0200+'d','i','s', /* D-DISH */ + 03,0200+'i','s', /* -ISH */ + 05,0200+'g','r','a','p', /* -GRAPH */ + 07,0200+'b','o','r',0200+'o','u','g', /* -BOR-OUGH */ + 05,0200+'b','u','r','g', /* -BURGH */ + 04,0200+'v','i','c', /* -VICH */ + 03,0200+'n','a', /* -NAH */ + 03,0200+'l','a', /* -LAH */ + 04,0200+'m','i',0200+'a', /* -MI-AH */ + 00 +}; + +static Uchar sufi[] = { + 03,0200+'t','r', /* -TRI */ + 03,0200+'c','h', /* -CHI */ + 0200+03,'i','f', /* IF-I */ + 0200+03,'e','d', /* ED-I */ + 05,0200+'a','s','c','i', /* -ASCII */ + 04,0200+'s','e','m', /* -SEMI */ + 00 +}; + +static Uchar sufk[] = { + 04,0200+'w','o','r', /* -WORK */ + 04,0200+'m','a','r', /* -MARK */ + 04,0200+'b','o','o', /* -BOOK */ + 04,0200+'w','a','l', /* -WALK */ + 05,0200+'c','r','a','c', /* -CRACK */ + 04,0200+'b','a','c', /* -BACK */ + 00 +}; + +static Uchar sufl[] = { + 03,0200+'f','u', /* -FUL */ + 05,'s',0200+'w','e','l', /* S-WELL */ + 04,0200+'t','e','l', /* -TELL */ + 05,0200+'s','h','e','l', /* -SHELL */ + 05,0200+'s','t','a','l', /* -STALL */ + 04,'s',0200+'t','a', /* S-TAL */ + 04,0200+'b','a','l', /* -BALL */ + 04,0200+'c','a','l', /* -CALL */ + 03,'v',0200+'e', /* V-EL */ + 03,'u',0200+'e', /* U-EL */ + 03,'k',0200+'e', /* K-EL */ + 04,'t','h',0200+'e', /* TH-EL */ + 05,'t','c','h',0200+'e', /* TCH-EL */ + 03,'a',0200+'e', /* A-EL */ + 0140+04,0200+'q','u','a', /* /QUAL */ + 040+03,'u',0200+'a', /* U-AL */ + 03,0200+'t','a', /* -TAL */ + 04,'u','r',0200+'a', /* UR-AL */ + 040+05,'g',0200+'o',0200+'n','a', /* G-O-NAL */ + 04,'o','n',0200+'a', /* ON-AL */ + 03,0200+'n','a', /* -NAL */ + 04,0200+'t','i','a', /* -TIAL */ + 04,0200+'s','i','a', /* -SIAL */ + 040+05,0200+'t','r','i',0200+'a', /* -TRI-AL */ + 04,'r','i',0200+'a', /* RI-AL */ + 04,0200+'n','i',0200+'a', /* -NI-AL */ + 04,0200+'d','i',0200+'a', /* -DI-AL */ + 04,0200+'c','i','a', /* -CIAL */ + 03,0200+'g','a', /* -GAL */ + 04,0200+'m','e','a', /* -MEAL */ +/* 040+04,0200+'r','e',0200+'a', /* -RE-AL */ + 040+04,0200+'r','e','a', /* -REAL */ + 06,'c',0200+'t','i',0200+'c','a', /* C-TI-CAL */ + 05,0200+'s','i',0200+'c','a', /* -SI-CAL */ + 04,0200+'i',0200+'c','a', /* -I-CAL */ + 03,0200+'c','a', /* -CAL */ + 03,0200+'b','a', /* -BAL */ + 06,0200+'n','o',0200+'m','i',0200+'a', /* -NO-MI-AL */ + 00 +}; + +static Uchar sufm[] = { + 03,0200+'n','u', /* -NUM */ + 05,'o',0200+'r','i',0200+'u', /* O-RI-UM */ + 040+03,'i',0200+'u', /* I-UM */ + 040+03,'e',0200+'u', /* E-UM */ + 05,'i','v',0200+'i','s', /* IV-ISM */ + 04,0200+'t','i','s', /* -TISM */ + 05,'i',0200+'m','i','s', /* I-MISM */ + 05,'a','l',0200+'i','s', /* AL-ISM */ + 040+04,'e',0200+'i','s', /* E-ISM */ + 040+04,'a',0200+'i','s', /* A-ISM */ + 04,0200+'r','o','o', /* -ROOM */ + 03,0200+'d','o', /* -DOM */ + 03,0200+'h','a', /* -HAM */ + 06,0200+'a',0200+'r','i','t','h', /* -A-RITHM */ + 05,0200+'r','i','t','h', /* -RITHM */ + 00 +}; + +static Uchar sufn[] = { + 05,0200+'k','n','o','w', /* -KNOWN */ + 04,0200+'t','o','w', /* -TOWN */ + 04,0200+'d','o','w', /* -DOWN */ + 04,0200+'t','u','r', /* -TURN */ + 05,0200+'s','p','o','o', /* -SPOON */ + 04,0200+'n','o','o', /* -NOON */ + 04,0200+'m','o','o', /* -MOON */ + 011,'a','l',0200+'i',0200+'z','a',0200+'t','i','o', /* AL-I-ZA-TION */ + 07,0200+'i',0200+'z','a',0200+'t','i','o', /* -I-ZA-TION */ + 07,'l',0200+'i',0200+'a',0200+'t','i','o', /* L-I-A-TION */ + 04,0200+'t','i','o', /* -TION */ + 040+05,'s',0200+'s','i','o', /* S-SION */ + 04,0200+'s','i','o', /* -SION */ + 04,'n',0200+'i','o', /* N-ION */ + 04,0200+'g','i','o', /* -GION */ + 04,0200+'c','i','o', /* -CION */ + 03,0200+'c','o', /* -CON */ + 05,0200+'c','o','l','o', /* -COLON */ + 03,0200+'t','o', /* -TON */ + 04,'i','s',0200+'o', /* IS-ON */ + 03,0200+'s','o', /* -SON */ + 03,0200+'r','i', /* -RIN */ + 03,0200+'p','i', /* -PIN */ + 03,0200+'n','i', /* -NIN */ + 03,0200+'m','i', /* -MIN */ + 03,0200+'l','i', /* -LIN */ + 03,0200+'k','i', /* -KIN */ + 05,0200+'s','t','e','i', /* -STEIN */ + 04,0200+'t','a','i', /* -TAIN */ + 05,'g','h','t',0200+'e', /* GHT-EN */ + 05,0200+'w','o','m',0200+'e', /* -WOM-EN */ + 03,0200+'m','e', /* -MEN */ + 04,'o',0200+'k','e', /* O-KEN */ + 03,'k',0200+'e', /* K-EN */ + 04,0200+'t','e','e', /* -TEEN */ + 04,0200+'s','e','e', /* -SEEN */ + 040+03,0200+'s','a', /* -SAN */ + 05,0200+'w','o','m',0200+'a', /* -WOM-AN */ + 03,0200+'m','a', /* -MAN */ + 04,0200+'t','i','a', /* -TIAN */ + 04,0200+'s','i','a', /* -SIAN */ + 040+04,'e',0200+'i','a', /* E-IAN */ + 04,0200+'c','i','a', /* -CIAN */ + 0300+03,'i','a', /* IA/N */ + 05,0200+'c','l','e','a', /* -CLEAN */ + 04,0200+'m','e','a', /* -MEAN */ + 040+03,'e',0200+'a', /* E-AN */ + 00 +}; + +static Uchar sufo[] = { + 05,0200+'m','a','c',0200+'r', /* -MAC-RO */ + 00 +}; + +static Uchar sufp[] = { + 05,0200+'g','r','o','u', /* -GROUP */ + 02,0200+'u', /* -UP */ + 04,0200+'s','h','i', /* -SHIP */ + 04,0200+'k','e','e', /* -KEEP */ + 00 +}; + +static Uchar sufr[] = { + 04,0200+'z','a','r', /* -ZARR */ + 0300+02,'r', /* R/R */ + 03,0200+'t','o', /* -TOR */ + 040+03,0200+'s','o', /* -SOR */ + 040+04,0200+'r','i',0200+'o', /* -RI-OR */ + 04,'i','z',0200+'e', /* IZ-ER */ + 05,0200+'c','o','v',0200+'e', /* -COV-ER */ + 04,0200+'o','v','e', /* -OVER */ + 04,0200+'e','v',0200+'e', /* -EV-ER */ + 8,0200+'c','o','m',0200+'p','u','t',0200+'e', /* -COM-PUT-ER */ + 040+05,'u','s',0200+'t','e', /* US-TER */ + 05,'o','s','t',0200+'e', /* OST-ER */ + 040+05,0200+'a','c',0200+'t','e', /* -AC-TER */ + 06,0200+'w','r','i','t',0200+'e', /* -WRIT-ER */ + 040+05,'i','s',0200+'t','e', /* IS-TER */ + 040+05,'e','s',0200+'t','e', /* ES-TER */ + 040+05,'a','s',0200+'t','e', /* AS-TER */ + 04,0200+'s','t','e', /* -STER */ + 05,'a','r',0200+'t','e', /* AR-TER */ + 04,'r','t',0200+'e', /* RT-ER */ + 040+05,'m',0200+'e',0200+'t','e', /* M-E-TER */ + 05,0200+'w','a',0200+'t','e', /* -WA-TER */ + 03,'r',0200+'e', /* R-ER */ + 04,'o','p',0200+'e', /* OP-ER */ + 05,0200+'p','a',0200+'p','e', /* -PA-PER */ + 04,'w','n',0200+'e', /* WN-ER */ + 040+04,'s',0200+'n','e', /* S-NER */ + 04,'o','n',0200+'e', /* ON-ER */ + 04,'r','m',0200+'e', /* RM-ER */ + 03,0200+'m','e', /* -MER */ + 04,'l','l',0200+'e', /* LL-ER */ + 05,'d',0200+'d','l','e', /* D-DLER */ + 04,0200+'b','l','e', /* -BLER */ + 03,'k',0200+'e', /* K-ER */ + 05,'n',0200+'t','h','e', /* N-THER */ + 06,0200+'f','a',0200+'t','h','e', /* -FA-THER */ + 06,'e','i',0200+'t','h','e', /* EI-THER */ + 04,'t','h',0200+'e', /* TH-ER */ + 04,'s','h',0200+'e', /* SH-ER */ + 04,0200+'p','h','e', /* -PHER */ + 04,'c','h',0200+'e', /* CH-ER */ + 04,'d','g',0200+'e', /* DG-ER */ + 04,'r','d',0200+'e', /* RD-ER */ + 06,'o','u','n','d',0200+'e', /* OUND-ER */ + 04,'l','d',0200+'e', /* LD-ER */ + 04,'i','d',0200+'e', /* ID-ER */ + 05,0200+'d','u','c',0200+'e', /* -DUC-ER */ + 04,'n','c',0200+'e', /* NC-ER */ + 0100+02, 0200+'e', /* /ER */ + 03,0200+'s','a', /* -SAR */ + 040+06,'a','c',0200+'u',0200+'l','a', /* AC-U-LAR */ + 040+06,'e','c',0200+'u',0200+'l','a', /* EC-U-LAR */ + 040+06,'i','c',0200+'u',0200+'l','a', /* IC-U-LAR */ + 040+06,'e','g',0200+'u',0200+'l','a', /* EG-U-LAR */ + 00 +}; + +static Uchar sufs[] = { + 040+04,'u',0200+'o','u', /* U-OUS */ + 05,0200+'t','i','o','u', /* -TIOUS */ + 05,0200+'g','i','o','u', /* -GIOUS */ + 05,0200+'c','i','o','u', /* -CIOUS */ + 040+04,'i',0200+'o','u', /* I-OUS */ + 05,0200+'g','e','o','u', /* -GEOUS */ + 05,0200+'c','e','o','u', /* -CEOUS */ + 04,'e',0200+'o','u', /* E-OUS */ + 0140+02,0200+'u', /* /US */ + 04,0200+'n','e','s', /* -NESS */ + 04,0200+'l','e','s', /* -LESS */ + 0140+02,0200+'s', /* /SS */ + 040+05,'p',0200+'o',0200+'l','i', /* P-O-LIS */ + 0140+02,0200+'i', /* /IS */ + 0100+03,0200+'x','e', /* X/ES */ + 0100+03,0200+'s','e', /* S/ES */ + 0100+04,'s','h',0200+'e', /* SH/ES */ + 0100+04,'c','h',0200+'e', /* CH/ES */ + 0300+01, /* /S */ + 00 +}; + +static Uchar suft[] = { + 05,0200+'l','i','m',0200+'i', /* -LIM-IT */ + 06,'i','o','n',0200+'i','s', /* ION-IST */ + 05,'i','n',0200+'i','s', /* IN-IST */ + 05,'a','l',0200+'i','s', /* AL-IST */ + 06,'l',0200+'o',0200+'g','i','s', /* L-O-GIST */ + 05,'h','t',0200+'e','s', /* HT-EST */ + 04,'i',0200+'e','s', /* I-EST */ + 05,'g',0200+'g','e','s', /* G-GEST */ + 04,'g',0200+'e','s', /* G-EST */ + 05,'d',0200+'d','e','s', /* D-DEST */ + 04,'d',0200+'e','s', /* D-EST */ + 04,0200+'c','a','s', /* -CAST */ + 05,0200+'h','e','a','r', /* -HEART */ + 04,0200+'f','o','o', /* -FOOT */ + 03,'i',0200+'o', /* I-OT */ + 05,0200+'f','r','o','n', /* -FRONT */ + 05,0200+'p','r','i','n', /* -PRINT */ + 04,0200+'m','e','n', /* -MENT */ + 05,0200+'c','i','e','n', /* -CIENT */ + 04,'i',0200+'a','n', /* I-ANT */ + 06,0200+'w','r','i','g','h', /* -WRIGHT */ + 06,0200+'b','r','i','g','h', /* -BRIGHT */ + 06,0200+'f','l','i','g','h', /* -FLIGHT */ + 06,0200+'w','e','i','g','h', /* -WEIGHT */ + 05,0200+'s','h','i','f', /* -SHIFT */ + 05,0200+'c','r','a','f', /* -CRAFT */ + 040+04,'d','g',0200+'e', /* DG-ET */ + 04,0200+'g','o','a', /* -GOAT */ + 04,0200+'c','o','a', /* -COAT */ + 04,0200+'b','o','a', /* -BOAT */ + 04,0200+'w','h','a', /* -WHAT */ + 04,0200+'c','u','i', /* -CUIT */ + 00 +}; + +static Uchar sufy[] = { + 040+04,'e','s',0200+'t', /* ES-TY */ + 040+05,'q','u','i',0200+'t', /* QUI-TY */ + 04,0200+'t','i',0200+'t', /* -TI-TY */ + 040+05,'o','s',0200+'i',0200+'t', /* OS-I-TY */ + 04,0200+'s','i',0200+'t', /* -SI-TY */ + 05,'i','n',0200+'i',0200+'t', /* IN-I-TY */ + 04,'n','i',0200+'t', /* NI-TY */ + 040+010,'f','a',0200+'b','i','l',0200+'i',0200+'t', /* FA-BIL-I-TY */ + 010,0200+'c','a',0200+'b','i','l',0200+'i',0200+'t', /* -CA-BIL-I-TY */ + 010,0200+'p','a',0200+'b','i','l',0200+'i',0200+'t', /* -PA-BIL-I-TY */ + 06,0200+'b','i','l',0200+'i',0200+'t', /* -BIL-I-TY */ + 03,'i',0200+'t', /* I-TY */ + 04,0200+'b','u','r', /* -BUR-Y */ + 04,0200+'t','o',0200+'r', /* -TO-RY */ + 05,0200+'q','u','a','r', /* -QUAR-Y */ + 040+04,'u',0200+'a','r', /* U-ARY */ + 07,0200+'m','e','n',0200+'t','a',0200+'r', /* -MEN-TA-RY */ + 06,'i','o','n',0200+'a','r', /* ION-ARY */ + 04,'i',0200+'a','r', /* I-ARY */ + 04,'n',0200+'o',0200+'m', /* N-O-MY */ + 03,0200+'p','l', /* -PLY */ + 04,'g',0200+'g','l', /* G-GLY */ + 05,0200+'p','a',0200+'b','l', /* -PA-BLY */ + 05,'f','a',0200+'b','l', /* FA-BLY */ + 05,0200+'c','a',0200+'b','l', /* -CA-BLY */ + 04,0200+'a','b','l', /* -ABLY */ + 03,0200+'b','l', /* -BLY */ + 02,0200+'l', /* -LY */ + 03,0200+'s','k', /* -SKY */ + 040+06,'g',0200+'r','a',0200+'p','h', /* G-RA-PHY */ + 04,'l',0200+'o',0200+'g', /* L-O-GY */ + 02,0200+'f', /* -FY */ + 03,0200+'n','e', /* -NEY */ + 03,0200+'l','e', /* -LEY */ + 04,'c','k',0200+'e', /* CK-EY */ + 03,0200+'k','e', /* -KEY */ + 04,0200+'b','o','d', /* -BODY */ + 05,0200+'s','t','u','d', /* -STUDY */ + 0340+04,'e','e','d', /* EEDY */ + 02,0200+'b', /* -BY */ + 03,0200+'w','a', /* -WAY */ + 03,0200+'d','a', /* -DAY */ + 00 +}; + +Uchar *suftab[] = { + sufa, + 0, + sufc, + sufd, + sufe, + suff, + sufg, + sufh, + sufi, + 0, + sufk, + sufl, + sufm, + sufn, + sufo, + sufp, + 0, + sufr, + sufs, + suft, + 0, + 0, + 0, + 0, + sufy, + 0, +}; blob - /dev/null blob + 3e8026d1178c6c7ff28d4bc6f632439662b16114 (mode 644) --- /dev/null +++ src/cmd/troff/t10.c @@ -0,0 +1,512 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +/* + * troff10.c + * + * typesetter interface + */ + +int vpos = 0; /* absolute vertical position on page */ +int hpos = 0; /* ditto horizontal */ + +extern Font fonts[MAXFONTS+1]; + +int Inch; +int Hor; +int Vert; +int Unitwidth; +int nfonts; + + + +void t_ptinit(void) +{ + int i; + char buf[100], *p; + + hmot = t_hmot; + makem = t_makem; + setabs = t_setabs; + setch = t_setch; + sethl = t_sethl; + setht = t_setht; + setslant = t_setslant; + vmot = t_vmot; + xlss = t_xlss; + findft = t_findft; + width = t_width; + mchbits = t_mchbits; + ptlead = t_ptlead; + ptout = t_ptout; + ptpause = t_ptpause; + setfont = t_setfont; + setps = t_setps; + setwd = t_setwd; + + /* open table for device, */ + /* read in resolution, size info, font info, etc., set params */ + if ((p = getenv("TYPESETTER")) != 0) + strcpy(devname, p); + if (termtab[0] == 0) + strcpy(termtab, DWBfontdir); + if (fontdir[0] == 0) + strcpy(fontdir, DWBfontdir); + if (devname[0] == 0) + strcpy(devname, TDEVNAME); + hyf = 1; + lg = 1; + + sprintf(buf, "/dev%s/DESC", devname); + strcat(termtab, buf); + if (getdesc(termtab) < 0) { + ERROR "can't open DESC file %s", termtab WARN; + done3(1); + } + if (!ascii) { + OUT "x T %s\n", devname PUT; + OUT "x res %d %d %d\n", Inch, Hor, Vert PUT; + OUT "x init\n" PUT; + } + for (i = 1; i <= nfonts; i++) + setfp(i, fontlab[i], (char *) 0, 0); + sps = EM/3; /* space size */ + ics = EM; /* insertion character space */ + for (i = 0; i < (NTAB - 1) && DTAB * (i + 1) < TABMASK; i++) + tabtab[i] = DTAB * (i + 1); + tabtab[NTAB] = 0; + pl = 11 * INCH; /* paper length */ + po = PO; /* page offset */ + spacesz = SS; + lss = lss1 = VS; + ll = ll1 = lt = lt1 = LL; + t_specnames(); /* install names like "hyphen", etc. */ +} + +void t_specnames(void) +{ + int i; + + for (i = 0; spnames[i].n; i++) + *spnames[i].n = chadd(spnames[i].v, Troffchar, Install); +} + +void t_ptout(Tchar i) +{ + int dv; + Tchar *k; + int temp, a, b; + int diff; + + if (cbits(i) != '\n') { + if (olinep >= oline + olnsize) { + diff = olinep - oline; + olnsize += OLNSIZE; + if ((oline = (Tchar *)realloc((char *)oline, olnsize * sizeof(Tchar))) != NULL) { + if (diff && olinep) + olinep = oline + diff; + } else { + ERROR "Output line overflow." WARN; + done(2); + } + } + *olinep++ = i; + return; + } + if (olinep == oline) { + lead += lss; + return; + } + + hpos = po; /* ??? */ + esc = 0; /* ??? */ + ptesc(); /* the problem is to get back to the left end of the line */ + dv = 0; + for (k = oline; k < olinep; k++) { + if (ismot(*k) && isvmot(*k)) { + temp = absmot(*k); + if (isnmot(*k)) + temp = -temp; + dv += temp; + } + } + if (dv) { + vflag++; + *olinep++ = makem(-dv); + vflag = 0; + } + + b = dip->blss + lss; + lead += dip->blss + lss; + dip->blss = 0; + for (k = oline; k < olinep; ) + k += ptout0(k); /* now passing a pointer! */ + olinep = oline; + lead += dip->alss; + a = dip->alss; + dip->alss = 0; + /* + OUT "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos PUT; +*/ + OUT "n%d %d\n", b, a PUT; /* be nice to chuck */ +} + +int ptout0(Tchar *pi) +{ + int j, k, w; + int z, dx, dy, dx2, dy2, n; + Tchar i; + int outsize; /* size of object being printed */ + + outsize = 1; /* default */ + i = *pi; + k = cbits(i); + if (ismot(i)) { + j = absmot(i); + if (isnmot(i)) + j = -j; + if (isvmot(i)) + lead += j; + else + esc += j; + return(outsize); + } + if (k == CHARHT) { + xpts = fbits(i); /* sneaky, font bits as size bits */ + if (xpts != mpts) + ptps(); + OUT "x H %d\n", sbits(i) PUT; + return(outsize); + } + if (k == SLANT) { + OUT "x S %d\n", sfbits(i)-180 PUT; + return(outsize); + } + if (k == WORDSP) { + oput('w'); + return(outsize); + } + if (sfbits(i) == oldbits) { + xfont = pfont; + xpts = ppts; + } else + xbits(i, 2); + if (k == XON) { + extern int xon; + ptflush(); /* guarantee that everything is out */ + if (esc) + ptesc(); + if (xfont != mfont) + ptfont(); + if (xpts != mpts) + ptps(); + if (lead) + ptlead(); + OUT "x X " PUT; + xon++; + for (j = 1; cbits(pi[j]) != XOFF; j++) + outascii(pi[j]); + oput('\n'); + xon--; + return j+1; + } + if (k < 040 && k != DRAWFCN) + return(outsize); + j = z = 0; + if (k != DRAWFCN) { + if (widcache[k].fontpts == (xfont<<8) + xpts && !setwdf) { + w = widcache[k].width; + bd = 0; + cs = 0; + } else + w = getcw(k); + if (cs) { + if (bd) + w += (bd - 1) * HOR; + j = (cs - w) / 2; + w = cs - j; + if (bd) + w -= (bd - 1) * HOR; + } + if (iszbit(i)) { + if (cs) + w = -j; + else + w = 0; + z = 1; + } + } + esc += j; + if (xfont != mfont) + ptfont(); + if (xpts != mpts) + ptps(); + if (lead) + ptlead(); + /* put out the real character here */ + if (k == DRAWFCN) { + if (esc) + ptesc(); + w = 0; + dx = absmot(pi[3]); + if (isnmot(pi[3])) + dx = -dx; + dy = absmot(pi[4]); + if (isnmot(pi[4])) + dy = -dy; + switch (cbits(pi[1])) { + case DRAWCIRCLE: /* circle */ + OUT "D%c %d\n", DRAWCIRCLE, dx PUT; /* dx is diameter */ + hpos += dx; + break; + case DRAWELLIPSE: + OUT "D%c %d %d\n", DRAWELLIPSE, dx, dy PUT; + hpos += dx; + break; + case DRAWBUILD: + k = cbits(pi[2]); + OUT "D%c %d ", DRAWBUILD, dx PUT; + if (k < ALPHABET) + OUT "%c\n", k PUT; + else + ptchname(k); + hpos += dx; + break; + case DRAWLINE: /* line */ + k = cbits(pi[2]); + OUT "D%c %d %d ", DRAWLINE, dx, dy PUT; + if (k < ALPHABET) + OUT "%c\n", k PUT; + else + ptchname(k); + hpos += dx; + vpos += dy; + break; + case DRAWARC: /* arc */ + dx2 = absmot(pi[5]); + if (isnmot(pi[5])) + dx2 = -dx2; + dy2 = absmot(pi[6]); + if (isnmot(pi[6])) + dy2 = -dy2; + OUT "D%c %d %d %d %d\n", DRAWARC, + dx, dy, dx2, dy2 PUT; + hpos += dx + dx2; + vpos += dy + dy2; + break; + + case 's': /* using 's' internally to avoid .tr ~ */ + pi[1] = '~'; + case DRAWSPLINE: /* spline */ + default: /* something else; copy it like spline */ + OUT "D%c %d %d", cbits(pi[1]), dx, dy PUT; + hpos += dx; + vpos += dy; + if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) { + /* it was somehow defective */ + OUT "\n" PUT; + break; + } + for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) { + dx = absmot(pi[n]); + if (isnmot(pi[n])) + dx = -dx; + dy = absmot(pi[n+1]); + if (isnmot(pi[n+1])) + dy = -dy; + OUT " %d %d", dx, dy PUT; + hpos += dx; + vpos += dy; + } + OUT "\n" PUT; + break; + } + for (n = 3; cbits(pi[n]) != DRAWFCN; n++) + ; + outsize = n + 1; + } else if (k < ALPHABET) { + /* try to go faster and compress output */ + /* by printing nnc for small positive motion followed by c */ + /* kludgery; have to make sure set all the vars too */ + if (esc > 0 && esc < 100) { + oput(esc / 10 + '0'); + oput(esc % 10 + '0'); + oput(k); + hpos += esc; + esc = 0; + } else { + if (esc) + ptesc(); + oput('c'); + oput(k); + oput('\n'); + } + } else { + if (esc) + ptesc(); + ptchname(k); + } + if (bd) { + bd -= HOR; + if (esc += bd) + ptesc(); + if (k < ALPHABET) + OUT "c%c\n", k PUT; + else + ptchname(k); + if (z) + esc -= bd; + } + esc += w; + return(outsize); +} + +void ptchname(int k) +{ + char *chn = chname(k); + + switch (chn[0]) { + case MBchar: + OUT "c%s\n", chn+1 PUT; /* \n not needed? */ + break; + case Number: + OUT "N%s\n", chn+1 PUT; + break; + case Troffchar: + OUT "C%s\n", chn+1 PUT; + break; + default: + ERROR "illegal char type %s", chn WARN; + break; + } +} + +void ptflush(void) /* get us to a clean output state */ +{ + if (TROFF) { + /* ptesc(); but always H, no h */ + hpos += esc; + OUT "\nH%d\n", hpos PUT; + esc = 0; + ptps(); + ptfont(); + ptlead(); + } +} + +void ptps(void) +{ + int i, j, k; + + i = xpts; + for (j = 0; i > (k = pstab[j]); j++) + if (!k) { + k = pstab[--j]; + break; + } + if (!ascii) + OUT "s%d\n", k PUT; /* really should put out string rep of size */ + mpts = i; +} + +void ptfont(void) +{ + mfont = xfont; + if (ascii) + return; + if (xfont > nfonts) { + ptfpcmd(0, fonts[xfont].longname, 0); /* Put the desired font in the + * fontcache of the filter */ + OUT "f0\n" PUT; /* make sure that it gets noticed */ + } else + OUT "f%d\n", xfont PUT; +} + +void ptfpcmd(int f, char *s, char *longname) +{ + if (f > nfonts) /* a bit risky? */ + f = 0; + if (longname) { + OUT "x font %d %s %s\n", f, s, longname PUT; + } else { + OUT "x font %d %s\n", f, s PUT; + } +/* OUT "f%d\n", xfont PUT; /* need this for buggy version of adobe transcript */ + /* which apparently believes that x font means */ + /* to set the font, not just the position. */ +} + +void t_ptlead(void) +{ + vpos += lead; + if (!ascii) + OUT "V%d\n", vpos PUT; + lead = 0; +} + +void ptesc(void) +{ + hpos += esc; + if (!ascii) + if (esc > 0) { + oput('h'); + if (esc>=10 && esc<100) { + oput(esc/10 + '0'); + oput(esc%10 + '0'); + } else + OUT "%d", esc PUT; + } else + OUT "H%d\n", hpos PUT; + esc = 0; +} + +void ptpage(int n) /* called at end of each output page, we hope */ +{ + int i; + + if (NROFF) + return; + ptlead(); + vpos = 0; + if (ascii) + return; + OUT "p%d\n", n PUT; /* new page */ + for (i = 0; i <= nfonts; i++) + if (fontlab[i]) { + if (fonts[i].truename) + OUT "x font %d %s %s\n", i, fonts[i].longname, fonts[i].truename PUT; + else + OUT "x font %d %s\n", i, fonts[i].longname PUT; + } + ptps(); + ptfont(); +} + +void pttrailer(void) +{ + if (TROFF) + OUT "x trailer\n" PUT; +} + +void ptstop(void) +{ + if (TROFF) + OUT "x stop\n" PUT; +} + +void t_ptpause(void) +{ + if (ascii) + return; + ptlead(); + vpos = 0; + pttrailer(); + ptlead(); + OUT "x pause\n" PUT; + flusho(); + mpts = mfont = 0; + ptesc(); + esc = po; + hpos = vpos = 0; /* probably in wrong place */ +} blob - /dev/null blob + 5511748c6c85bbc3b53e19a20dcf4f796c68c839 (mode 644) --- /dev/null +++ src/cmd/troff/t11.c @@ -0,0 +1,255 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#define MAXCH NCHARS /* maximum number of global char names */ +char *chnames[MAXCH]; /* chnames[n-ALPHABET] -> name of char n */ +int nchnames; /* number of Cxy names currently seen */ + +#define MAXPS 100 /* max number of point sizes */ +int pstab[MAXPS]; /* point sizes */ +int nsizes; /* number in DESC */ + +Font fonts[MAXFONTS+1]; /* font info + ptr to width info */ + + +#define skipline(f) while (getc(f) != '\n') + +#define eq(s1, s2) (strcmp(s1, s2) == 0) + +getdesc(char *name) +{ + FILE *fin; + char cmd[100], s[100]; + int i, v; + + if ((fin = fopen(unsharp(name), "r")) == NULL) + return -1; + while (fscanf(fin, "%s", cmd) != EOF) { + if (strcmp(cmd, "res") == 0) { + fscanf(fin, "%d", &Inch); + } else if (strcmp(cmd, "hor") == 0) { + fscanf(fin, "%d", &Hor); + } else if (strcmp(cmd, "vert") == 0) { + fscanf(fin, "%d", &Vert); + } else if (strcmp(cmd, "unitwidth") == 0) { + fscanf(fin, "%d", &Unitwidth); + } else if (strcmp(cmd, "sizes") == 0) { + nsizes = 0; + while (fscanf(fin, "%d", &v) != EOF && v != 0 && nsizes < MAXPS) + pstab[nsizes++] = v; + } else if (strcmp(cmd, "fonts") == 0) { + fscanf(fin, "%d", &nfonts); + for (i = 1; i <= nfonts; i++) { + fscanf(fin, "%s", s); + fontlab[i] = PAIR(s[0], s[1]); + } + } else if (strcmp(cmd, "charset") == 0) { /* add any names */ + while (fscanf(fin, "%s", s) != EOF) + chadd(s, Troffchar, Install); + break; + } + /* else + just skip anything else */ + skipline(fin); + } + fclose(fin); + return 1; +} + +static int checkfont(char *name) +{ /* in case it's not really a font description file */ + /* really paranoid, but consider \f. */ + FILE *fp; + char buf[300], buf2[300]; + int i, status = -1; + + if ((fp = fopen(unsharp(name), "r")) == NULL) + return -1; + for (i = 1; i <= 10; i++) { + if (fgets(buf, sizeof buf, fp) == NULL) + break; + sscanf(buf, "%s", buf2); + if (buf2[0] == '#') { + i--; + continue; + } + if (eq(buf2, "name") || eq(buf2, "fontname") || + eq(buf2, "special") || eq(buf2, "charset")) { + status = 1; + break; + } + } + fclose(fp); + return status; + +} + +getfont(char *name, int pos) /* create width tab for font */ +{ + FILE *fin; + Font *ftemp = &fonts[pos]; + Chwid chtemp[MAXCH]; + static Chwid chinit; + int i, nw, n, wid, kern, code, type; + char buf[100], ch[100], s1[100], s2[100], s3[100], cmd[300]; + + /* fprintf(stderr, "read font %s onto %d\n", name, pos); */ + if (checkfont(name) == -1) + return -1; + if ((fin = fopen(unsharp(name), "r")) == NULL) + return -1; + for (i = 0; i < ALPHABET; i++) + chtemp[i] = chinit; /* zero out to begin with */ + ftemp->specfont = ftemp->ligfont = 0; + ftemp->defaultwidth = ftemp->spacewidth = Inch * Unitwidth / 72 / 3; /* should be rounded */ + while (fscanf(fin, "%s", cmd) != EOF) { + if (strcmp(cmd, "name") == 0) + fscanf(fin, "%s", ftemp->longname); + else if (strcmp(cmd, "special") == 0) + ftemp->specfont = 1; + else if (strcmp(cmd, "ligatures") == 0) { + ftemp->ligfont = getlig(fin); + } else if (strcmp(cmd, "spacewidth") == 0) { + fscanf(fin, "%d", &ftemp->spacewidth); + } else if (strcmp(cmd, "defaultwidth") == 0) { + fscanf(fin, "%d", &ftemp->defaultwidth); + } else if (strcmp(cmd, "charset") == 0) { + wchar_t wc; + skipline(fin); + nw = ALPHABET; + while (fgets(buf, sizeof buf, fin) != NULL) { + sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); + if (s1[0] != '"') { /* genuine new character */ + sscanf(s1, "%d", &wid); + sscanf(s2, "%d", &kern); + code = strtol(s3, 0, 0); /* dec/oct/hex */ + } + /* otherwise it's a synonym for prev character, */ + /* so leave previous values intact */ + + + /* decide what kind of alphabet it might come from here */ + + + if (strlen(ch) == 1) { /* it's ascii */ + n = ch[0]; /* origin includes non-graphics */ + chtemp[n].num = ch[0]; + } else if (ch[0] == '\\' && ch[1] == '0') { + n = strtol(ch+1, 0, 0); /* \0octal or \0xhex */ + chtemp[n].num = n; +#ifdef UNICODE + } else if (mbtowc(&wc, ch, strlen(ch)) > 1) { + chtemp[nw].num = chadd(ch, MBchar, Install); + n = nw; + nw++; +#endif /*UNICODE*/ + } else { + if (strcmp(ch, "---") == 0) { /* no name */ + sprintf(ch, "%d", code); + type = Number; + } else + type = Troffchar; + chtemp[nw].num = chadd(ch, type, Install); + n = nw; + nw++; + } + chtemp[n].wid = wid; + chtemp[n].kern = kern; + chtemp[n].code = code; + /*fprintf(stderr, "font %2.2s char %4.4s num %3d wid %2d code %3d\n", + ftemp->longname, ch, n, wid, code); + */ + } + break; + } + skipline(fin); + } + fclose(fin); + chtemp[' '].wid = ftemp->spacewidth; /* width of space on this font */ + ftemp->nchars = nw; + if (ftemp->wp) + free(ftemp->wp); /* god help us if this wasn't allocated */ + ftemp->wp = (Chwid *) malloc(nw * sizeof(Chwid)); + if (ftemp->wp == NULL) + return -1; + for (i = 0; i < nw; i++) + ftemp->wp[i] = chtemp[i]; +/* + * printf("%d chars: ", nw); + * for (i = 0; i < nw; i++) + * if (ftemp->wp[i].num > 0 && ftemp->wp[i].num < ALPHABET) { + * printf("%c %d ", ftemp->wp[i].num, ftemp->wp[i].wid); + * else if (i >= ALPHABET) + * printf("%d (%s) %d ", ftemp->wp[i].num, + * chnames[ftemp->wp[i].num-ALPHABET], ftemp->wp[i].wid); + * } + * printf("\n"); + */ + return 1; +} + +chadd(char *s, int type, int install) /* add s to global character name table; */ +{ /* or just look it up */ + + /* a temporary kludge: store the "type" as the first character */ + /* of the string, so we can remember from whence it came */ + + char *p; + int i; + +/* fprintf(stderr, "into chadd %s %c %c\n", s, type, install); /* */ + for (i = 0; i < nchnames; i++) + if (type == chnames[i][0] && eq(s, chnames[i]+1)) /* +1 since type at front */ + break; +/* fprintf(stderr, "i %d, nchnames %d\n", i, nchnames); /* */ + if (i < nchnames) /* found same type and bytes at position i */ + return ALPHABET + i; + else if (install == Lookup) /* not found, and we were just looking */ + return -1; + + chnames[nchnames] = p = (char *) malloc(strlen(s)+1+1); /* type + \0 */ + if (p == NULL) { + ERROR "out of space adding character %s", s WARN; + return LEFTHAND; + } + if (nchnames >= NCHARS - ALPHABET) { + ERROR "out of table space adding character %s", s WARN; + return LEFTHAND; + } + strcpy(chnames[nchnames]+1, s); + chnames[nchnames][0] = type; +/* fprintf(stderr, "installed %c%s at %d\n", type, s, nchnames); /* */ + return nchnames++ + ALPHABET; +} + +char *chname(int n) /* return string for char with index n */ +{ /* includes type char at front, to be peeled off elsewhere */ + if (n >= ALPHABET && n < nchnames + ALPHABET) + return chnames[n-ALPHABET]; + else + return ""; +} + +getlig(FILE *fin) /* pick up ligature list */ +{ + int lig; + char temp[200]; + + lig = 0; + while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) { + if (strcmp(temp, "fi") == 0) + lig |= LFI; + else if (strcmp(temp, "fl") == 0) + lig |= LFL; + else if (strcmp(temp, "ff") == 0) + lig |= LFF; + else if (strcmp(temp, "ffi") == 0) + lig |= LFFI; + else if (strcmp(temp, "ffl") == 0) + lig |= LFFL; + else + fprintf(stderr, "illegal ligature %s ignored\n", temp); + } + return lig; +} blob - /dev/null blob + b778916c852d713638fe42e121e9bbba080e048d (mode 644) --- /dev/null +++ src/cmd/troff/t6.c @@ -0,0 +1,881 @@ +/* + * t6.c + * + * width functions, sizes and fonts + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +int fontlab[MAXFONTS+1]; +int cstab[MAXFONTS+1]; +int ccstab[MAXFONTS+1]; +int bdtab[MAXFONTS+1]; +int sbold = 0; + +t_width(Tchar j) +{ + int i, k; + + if (iszbit(j)) + return 0; + if (ismot(j)) { + if (isvmot(j)) + return(0); + k = absmot(j); + if (isnmot(j)) + k = -k; + return(k); + } + i = cbits(j); + if (i < ' ') { + if (i == '\b') + return(-widthp); + if (i == PRESC) + i = eschar; + else if (i == HX) + return(0); + } + if (i == ohc) + return(0); + i = trtab[i]; + if (i < ' ') + return(0); + if (sfbits(j) == oldbits) { + xfont = pfont; + xpts = ppts; + } else + xbits(j, 0); + if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf) + k = widcache[i].width; + else { + k = getcw(i); + if (bd) + k += (bd - 1) * HOR; + if (cs) + k = cs; + } + widthp = k; + return(k); +} + +/* + * clear width cache-- s means just space + */ +void zapwcache(int s) +{ + int i; + + if (s) { + widcache[' '].fontpts = 0; + return; + } + for (i=0; iwp[n].num == n) /* ascii at front */ + return n; + else + return -1; + } + cp = &fp->wp[ALPHABET]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) /* search others */ + if (cp->num == n) + return cp - &fp->wp[0]; + /* maybe it was a \N... */ + np = chname(n); + if (*np == Number) { + i = atoi(np+1); /* sscanf(np+1, "%d", &i); */ + cp = &fp->wp[0]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) { /* search others */ + if (cp->code == i) + return cp - &fp->wp[0]; + } + return -2; /* a \N that doesn't have an entry */ + } + return -1; /* vanilla not found */ +} + +getcw(int i) +{ + int k, n, x; + Font *fp; + int nocache = 0; + if (i < ' ') + return 0; + bd = 0; + fp = &fonts[xfont]; + if (i == ' ') { /* a blank */ + k = (fp->spacewidth * spacesz + 6) / 12; + /* this nonsense because .ss cmd uses 1/36 em as its units */ + /* and default is 12 */ + } else if ((n = onfont(i, xfont)) >= 0) { /* on this font at n */ + k = fp->wp[n].wid; + if (setwdf) + numtabp[CT].val |= fp->wp[n].kern; + } else if (n == -2) { /* \N with default width */ + + k = fp->defaultwidth; + } else { /* not on current font */ + nocache = 1; + k = fp->defaultwidth; /* default-size space */ + if (smnt) { + int ii, jj; + for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) { + if ((n = onfont(i, ii)) >= 0) { + k = fonts[ii].wp[n].wid; + if (xfont == sbold) + bd = bdtab[ii]; + if (setwdf) + numtabp[CT].val |= fonts[ii].wp[n].kern; + break; + } + } + } + } + if (!bd) + bd = bdtab[xfont]; + if (cs = cstab[xfont]) { + nocache = 1; + if (ccs = ccstab[xfont]) + x = ccs; + else + x = xpts; + cs = (cs * EMPTS(x)) / 36; + } + /* was (k & BYTEMASK); since .wid is unsigned, should never happen */ + if (k < 0) + ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN; + k = (k * xpts + (Unitwidth / 2)) / Unitwidth; + if (nocache|bd) + widcache[i].fontpts = 0; + else { + widcache[i].fontpts = (xfont<<8) + xpts; + widcache[i].width = k; + } + return(k); + /* Unitwidth is Units/Point, where + /* Units is the fundamental digitization + /* of the character set widths, and + /* Point is the number of goobies in a point + /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6 + /* In effect, it's the size at which the widths + /* translate directly into units. + */ +} + +void xbits(Tchar i, int bitf) +{ + int k; + + if(TROFF) { + xfont = fbits(i); + k = sbits(i); + if(k) { + xpts = pstab[k-1]; + oldbits = sfbits(i); + pfont = xfont; + ppts = xpts; + return; + } + switch(bitf) { + case 0: + xfont = font; + xpts = pts; + break; + case 1: + xfont = pfont; + xpts = ppts; + break; + case 2: + xfont = mfont; + xpts = mpts; + } + } +} + + +/* these next two functions ought to be the same in troff and nroff, */ +/* but the data structures they search are different. */ +/* silly historical problem. */ + + +Tchar t_setch(int c) +{ + int j; + char temp[50]; + char *s; + + s = temp; + if (c == '(') { /* \(xx */ + if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) + return(0); + } else { /* \C'...' */ + c = getach(); + while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1) + s++; + } + *s = '\0'; +#ifdef UNICODE + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ +#else + if (NROFF) { + j = chadd(temp, Troffchar, Lookup); + if ( j == -1) + return 0; + else + return j | chbits; + } else + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ + +#endif /*UNICODE*/ +} + +Tchar t_setabs(void) /* set absolute char from \N'...' */ +{ + int n; + char temp[10]; + + getch(); /* delim */ + n = 0; + n = inumb(&n); + getch(); /* delim */ + if (nonumb) + return 0; + sprintf(temp, "%d", n); /* convert into "#n" */ + n = chadd(temp, Number, Install); + return n | chbits; +} + + +/* + * fontlab[] is a cache that contains font information + * for each font. + * fontlab[] contains the 1- or 2-character name of the + * font current associated with that font. + * fonts 1..nfonts correspond to the mounted fonts; + * the last of these are the special fonts. + * If we don't use the (named) font in one of the + * standard positions, we install the name in the next + * free slot of fontlab[] and font[]. + * Whenever we need info about the font, we + * read in the data into the next free slot with getfont. + * The ptfont() (t10.c) routine will tell + * the device filter to put the font always at position + * zero if xfont > nfonts, so no need to change these filters. + * Yes, this is a bit kludgy. + * + * This gives the new specs of findft: + * find the font name i, where i also can be a number. + * Installs the font(name) i when not present + * returns -1 on error + */ + + +t_findft(int i) +{ + int k; + Uchar *p; + + p = unpair(i); + + if (isdigit(p[0])) { /* first look for numbers */ + k = p[0] - '0'; + if (p[1] > 0 && isdigit(p[1])) + k = 10 * k + p[1] - '0'; + if (k > 0 && k <= nfonts && k < smnt) + return(k); /* mounted font: .ft 3 */ + if (fontlab[k] && k <= MAXFONTS) { /* translate */ + return(k); /*number to a name */ + } else { + fprintf(stderr, "troff: no font at position %d\n", k); + return(-1); /* wild number */ + } + } + + /* + * Now we look for font names + */ + for (k = 1; fontlab[k] != i; k++) { + if (k > MAXFONTS) + return(-1); /* running out of fontlab space */ + if (fontlab[k] == 0) { /* passed all existing names */ + if (setfp(k, i, (char *) 0, 1) == -1) + return(-1); + else { + fontlab[k] = i; /* install the name */ + return(k); + } + } + } + return(k); /* was one of the existing names */ +} + + +void caseps(void) +{ + int i; + + if (TROFF) { + if(skip()) + i = apts1; + else { + noscale++; + i = inumb(&apts); /* this is a disaster for fractional point sizes */ + noscale = 0; + if(nonumb) + i = apts1; + } + casps1(i); + } +} + + +void casps1(int i) +{ + +/* + * in olden times, it used to ignore changes to 0 or negative. + * this is meant to allow the requested size to be anything, + * in particular so eqn can generate lots of \s-3's and still + * get back by matching \s+3's. + + if (i <= 0) + return; +*/ + apts1 = apts; + apts = i; + pts1 = pts; + pts = findps(i); + mchbits(); +} + + +findps(int i) +{ + int j, k; + + for (j=k=0 ; pstab[j] != 0 ; j++) + if (abs(pstab[j]-i) < abs(pstab[k]-i)) + k = j; + + return(pstab[k]); +} + + +void t_mchbits(void) +{ + int i, j, k; + + i = pts; + for (j = 0; i > (k = pstab[j]); j++) + if (!k) { + j--; + break; + } + chbits = 0; + setsbits(chbits, ++j); + setfbits(chbits, font); + sps = width(' ' | chbits); + zapwcache(1); +} + +void t_setps(void) +{ + int i, j; + + i = cbits(getch()); + if (isdigit(i)) { /* \sd or \sdd */ + i -= '0'; + if (i == 0) /* \s0 */ + j = apts1; + else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */ + j = 10 * i + j - '0'; + ch = 0; + } else /* \sd */ + j = i; + } else if (i == '(') { /* \s(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + if (j == 0) /* \s(00 */ + j = apts1; + } else if (i == '+' || i == '-') { /* \s+, \s- */ + j = cbits(getch()); + if (isdigit(j)) { /* \s+d, \s-d */ + j -= '0'; + } else if (j == '(') { /* \s+(dd, \s-(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + } + if (i == '-') + j = -j; + j += apts; + } + casps1(j); +} + + +Tchar t_setht(void) /* set character height from \H'...' */ +{ + int n; + Tchar c; + + getch(); + n = inumb(&apts); + getch(); + if (n == 0 || nonumb) + n = apts; /* does this work? */ + c = CHARHT; + c |= ZBIT; + setsbits(c, n); + setfbits(c, pts); /* sneaky, CHARHT font bits are size bits */ + return(c); +} + +Tchar t_setslant(void) /* set slant from \S'...' */ +{ + int n; + Tchar c; + + getch(); + n = 0; + n = inumb(&n); + getch(); + if (nonumb) + n = 0; + c = SLANT; + c |= ZBIT; + setsfbits(c, n+180); + return(c); +} + + +void caseft(void) +{ + if (!TROFF) { + n_caseft(); + return; + } + skip(); + setfont(1); +} + + +void t_setfont(int a) +{ + int i, j; + + if (a) + i = getrq(); + else + i = getsn(); + if (!i || i == 'P') { + j = font1; + goto s0; + } + if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */ + return; + if ((j = findft(i)) == -1) + if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */ + return; +s0: + font1 = font; + font = j; + mchbits(); +} + + +void t_setwd(void) +{ + int base, wid; + Tchar i; + int delim, emsz, k; + int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; + + base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0; + if (ismot(i = getch())) + return; + delim = cbits(i); + savhp = numtabp[HP].val; + numtabp[HP].val = 0; + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + setwdf++; + while (cbits(i = getch()) != delim && !nlflg) { + k = width(i); + wid += k; + numtabp[HP].val += k; + if (!ismot(i)) { + emsz = (INCH/72) * xpts; + } else if (isvmot(i)) { + k = absmot(i); + if (isnmot(i)) + k = -k; + base -= k; + emsz = 0; + } else + continue; + if (base < numtabp[SB].val) + numtabp[SB].val = base; + if ((k = base + emsz) > numtabp[ST].val) + numtabp[ST].val = k; + } + setn1(wid, 0, (Tchar) 0); + numtabp[HP].val = savhp; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + setwdf = 0; +} + + +Tchar t_vmot(void) +{ + dfact = lss; + vflag++; + return t_mot(); +} + + +Tchar t_hmot(void) +{ + dfact = EM; + return t_mot(); +} + + +Tchar t_mot(void) +{ + int j, n; + Tchar i; + + j = HOR; + getch(); /*eat delim*/ + if (n = atoi0()) { + if (vflag) + j = VERT; + i = makem(quant(n, j)); + } else + i = 0; + getch(); + vflag = 0; + dfact = 1; + return(i); +} + + +Tchar t_sethl(int k) +{ + int j; + Tchar i; + + j = EM / 2; + if (k == 'u') + j = -j; + else if (k == 'r') + j = -2 * j; + vflag++; + i = makem(j); + vflag = 0; + return(i); +} + + +Tchar t_makem(int i) +{ + Tchar j; + + if (i >= 0) + j = i; + else + j = -i; + if (Hor > 1 && !vflag) + j = (j + Hor/2)/Hor * Hor; + j |= MOT; + if (i < 0) + j |= NMOT; + if (vflag) + j |= VMOT; + return(j); +} + + +Tchar getlg(Tchar i) +{ + Tchar j, k; + int lf; + + if (!TROFF) + return i; + if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */ + return(i); + j = getch0(); + if (cbits(j) == 'i' && (lf & LFI)) + j = LIG_FI; + else if (cbits(j) == 'l' && (lf & LFL)) + j = LIG_FL; + else if (cbits(j) == 'f' && (lf & LFF)) { + if ((lf & (LFFI|LFFL)) && lg != 2) { + k = getch0(); + if (cbits(k)=='i' && (lf&LFFI)) + j = LIG_FFI; + else if (cbits(k)=='l' && (lf&LFFL)) + j = LIG_FFL; + else { + *pbp++ = k; + j = LIG_FF; + } + } else + j = LIG_FF; + } else { + *pbp++ = j; + j = i; + } + return(i & SFMASK | j); +} + + +void caselg(void) +{ + + if(TROFF) { + skip(); + lg = atoi0(); + if (nonumb) + lg = 1; + } +} + +void casefp(void) +{ + int i, j; + + if (!TROFF) { + n_casefp(); + return; + } + skip(); + i = cbits(getch()); + if (isdigit(i)) { + i -= '0'; + j = cbits(getch()); + if (isdigit(j)) + i = 10 * i + j - '0'; + } + if (i <= 0 || i > nfonts) + ERROR "fp: bad font position %d", i WARN; + else if (skip() || !(j = getrq())) + ERROR "fp: no font name" WARN; + else if (skip() || !getname()) + setfp(i, j, (char*) 0, 1); + else /* 3rd argument = filename */ + setfp(i, j, nextf, 1); +} + +char *strdupl(const char *s) /* make a copy of s */ +{ + char *t; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) + ERROR "out of space in strdupl(%s)", s FATAL; + strcpy(t, s); + return t; +} + +setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */ +{ + char pathname[NS], shortname[NS], *sl; + + zapwcache(0); + if (truename) + strcpy(shortname, truename); + else + strcpy(shortname, (char *) unpair(f)); + if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */ + sprintf(pathname, "%s", truename); + if (fonts[pos].truename) + free(fonts[pos].truename); + fonts[pos].truename = strdupl(truename); + } else if (truename) { /* synonym: .fp 1 R Avant */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename); + truename = 0; /* so doesn't get repeated by ptfpcmd */ + } else /* vanilla: .fp 5 XX */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname); + if (truename == 0 && fonts[pos].truename != 0) { + free(fonts[pos].truename); + fonts[pos].truename = 0; + } + if (getfont(pathname, pos) < 0) { + ERROR "Can't open font file %s", pathname WARN; + return -1; + } + if (print && !ascii) { + ptfpcmd(pos, fonts[pos].longname, truename); + ptfont(); + } + if (pos == smnt) { + smnt = 0; + sbold = 0; + } + fontlab[pos] = f; + if (smnt == 0 && fonts[pos].specfont) + smnt = pos; + bdtab[pos] = cstab[pos] = ccstab[pos] = 0; + return pos; +} + +/* + * .cs request; don't check legality of optional arguments + */ +void casecs(void) +{ + int i, j; + + if (TROFF) { + int savtr = trace; + + trace = 0; + noscale++; + skip(); + if (!(i = getrq()) || (i = findft(i)) < 0) + goto rtn; + skip(); + cstab[i] = atoi0(); + skip(); + j = atoi0(); + if(nonumb) + ccstab[i] = 0; + else + ccstab[i] = findps(j); + rtn: + zapwcache(0); + noscale = 0; + trace = savtr; + } +} + + +void casebd(void) +{ + int i, j, k; + + if (!TROFF) { + n_casebd(); + return; + } + zapwcache(0); + k = 0; +bd0: + if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { + if (k) + goto bd1; + else + return; + } + if (j == smnt) { + k = smnt; + goto bd0; + } + if (k) { + sbold = j; + j = k; + } +bd1: + skip(); + noscale++; + bdtab[j] = atoi0(); + noscale = 0; +} + + +void casevs(void) +{ + int i; + + if (!TROFF) { + n_casevs(); + return; + } + skip(); + vflag++; + dfact = INCH; /* default scaling is points! */ + dfactd = 72; + res = VERT; + i = inumb(&lss); + if (nonumb) + i = lss1; + if (i < VERT) + i = VERT; + lss1 = lss; + lss = i; +} + + +void casess(void) +{ + int i; + + if(TROFF) { + noscale++; + skip(); + if(i = atoi0()) { + spacesz = i & 0177; + zapwcache(0); + sps = width(' ' | chbits); + } + noscale = 0; + } +} + + +Tchar t_xlss(void) +{ + /* stores \x'...' into two successive Tchars. + /* the first contains HX, the second the value, + /* encoded as a vertical motion. + /* decoding is done in n2.c by pchar(). + */ + int i; + + getch(); + dfact = lss; + i = quant(atoi0(), VERT); + dfact = 1; + getch(); + if (i >= 0) + *pbp++ = MOT | VMOT | i; + else + *pbp++ = MOT | VMOT | NMOT | -i; + return(HX); +} + +Uchar *unpair(int i) +{ + static Uchar name[3]; + + name[0] = i & SHORTMASK; + name[1] = (i >> SHORT) & SHORTMASK; + name[2] = 0; + return name; +} blob - /dev/null blob + e9e1f65caad9fd56067794751a639c2f67c3bb46 (mode 644) --- /dev/null +++ src/cmd/troff/tdef.h @@ -0,0 +1,670 @@ +#include +#include +#include +#include +#include + +#define NROFF (!TROFF) + + +/* Site dependent definitions */ + +#ifndef TMACDIR +#define TMACDIR "lib/tmac/tmac." +#endif +#ifndef FONTDIR +#define FONTDIR "lib/font" +#endif +#ifndef NTERMDIR +#define NTERMDIR "lib/term/tab." +#endif +#ifndef TDEVNAME +#define TDEVNAME "post" +#endif +#ifndef NDEVNAME +#define NDEVNAME "37" +#endif +#ifndef TEXHYPHENS +#define TEXHYPHENS "/usr/lib/tex/macros/hyphen.tex" +#endif +#ifndef ALTHYPHENS +#define ALTHYPHENS "lib/tmac/hyphen.tex" /* another place to look */ +#endif + +typedef unsigned char Uchar; +typedef unsigned short Ushort; + +typedef /*unsigned*/ long Tchar; + +typedef struct Blockp Blockp; +typedef struct Diver Diver; +typedef struct Stack Stack; +typedef struct Divsiz Divsiz; +typedef struct Contab Contab; +typedef struct Numtab Numtab; +typedef struct Numerr Numerr; +typedef struct Env Env; +typedef struct Term Term; +typedef struct Chwid Chwid; +typedef struct Font Font; +typedef struct Spnames Spnames; +typedef struct Wcache Wcache; +typedef struct Tbuf Tbuf; + +/* this simulates printf into a buffer that gets flushed sporadically */ +/* the BSD goo is because SunOS sprintf doesn't return anything useful */ + +#ifdef BSD4_2 +#define OUT (obufp += strlen(sprintf(obufp, +#define PUT ))) > obuf+BUFSIZ ? flusho() : 1 +#else +#define OUT (obufp += sprintf(obufp, +#define PUT )) > obuf+BUFSIZ ? flusho() : 1 +#endif + +#define oputs(a) OUT "%s", a PUT +#define oput(c) ( *obufp++ = (c), obufp > obuf+BUFSIZ ? flusho() : 1 ) + +extern char errbuf[]; +#define ERROR sprintf(errbuf, +#define WARN ), errprint() +#define FATAL ), errprint(), exit(1) + +/* starting values for typesetting parameters: */ + +#define PS 10 /* default point size */ +#define FT 1 /* default font position */ +#define ULFONT 2 /* default underline font */ +#define BDFONT 3 /* default emboldening font */ +#define BIFONT 4 /* default bold italic font */ +#define LL (unsigned) 65*INCH/10 /* line length; 39picas=6.5in */ +#define VS ((12*INCH)/72) /* initial vert space */ + + +#define EMPTS(pts) (((long)Inch*(pts) + 36) / 72) +#define EM (TROFF? EMPTS(pts): t.Em) +#define INCH (TROFF? Inch: 240) +#define HOR (TROFF? Hor: t.Adj) +#define VERT (TROFF? Vert: t.Vert) +#define PO (TROFF? Inch: 0) +#define SPS (TROFF? EMPTS(pts)/3: INCH/10) +#define SS (TROFF? 12: INCH/10) +#define ICS (TROFF? EMPTS(pts): 2*INCH/10) +#define DTAB (TROFF? (INCH/2): 0) + +/* These "characters" are used to encode various internal functions +/* Some make use of the fact that most ascii characters between +/* 0 and 040 don't have any graphic or other function. +/* The few that do have a purpose (e.g., \n, \b, \t, ... +/* are avoided by the ad hoc choices here. +/* See ifilt[] in n1.c for others -- 1, 2, 3, 5, 6, 7, 010, 011, 012 +*/ + +#define LEADER 001 +#define IMP 004 /* impossible char; glues things together */ +#define TAB 011 +#define RPT 014 /* next character is to be repeated many times */ +#define CHARHT 015 /* size field sets character height */ +#define SLANT 016 /* size field sets amount of slant */ +#define DRAWFCN 017 /* next several chars describe arb drawing fcns */ +# define DRAWLINE 'l' /* line: 'l' dx dy char */ +# define DRAWCIRCLE 'c' /* circle: 'c' r */ +# define DRAWELLIPSE 'e' /* ellipse: 'e' rx ry */ +# define DRAWARC 'a' /* arc: 'a' dx dy dx dy */ +# define DRAWSPLINE '~' /* quadratic B spline: '~' dx dy dx dy ... */ + /* other splines go thru too */ +/* NOTE: the use of ~ is a botch since it's often used in .tr commands */ +/* better to use a letter like s, but change it in the postprocessors too */ +/* for now, this is taken care of in n9.c and t10.c */ +# define DRAWBUILD 'b' /* built-up character (e.g., { */ + +#define LEFT 020 /* \{ */ +#define RIGHT 021 /* \} */ +#define FILLER 022 /* \& and similar purposes */ +#define XON 023 /* \X'...' starts here */ +#define OHC 024 /* optional hyphenation character \% */ +#define CONT 025 /* \c character */ +#define PRESC 026 /* printable escape */ +#define UNPAD 027 /* unpaddable blank */ +#define XPAR 030 /* transparent mode indicator */ +#define FLSS 031 /* next Tchar contains vertical space */ + /* used when recalling diverted text */ +#define WORDSP 032 /* paddable word space */ +#define ESC 033 /* current escape character */ +#define XOFF 034 /* \X'...' ends here */ + /* matches XON, but they will probably never nest */ + /* so could drop this when another control is needed */ +#define HX 035 /* next character is value of \x'...' */ +#define MOTCH 036 /* this "character" is really motion; used by cbits() */ + +#define HYPHEN c_hyphen +#define EMDASH c_emdash /* \(em */ +#define RULE c_rule /* \(ru */ +#define MINUS c_minus /* minus sign on current font */ +#define LIG_FI c_fi /* \(ff */ +#define LIG_FL c_fl /* \(fl */ +#define LIG_FF c_ff /* \(ff */ +#define LIG_FFI c_ffi /* \(Fi */ +#define LIG_FFL c_ffl /* \(Fl */ +#define ACUTE c_acute /* acute accent \(aa */ +#define GRAVE c_grave /* grave accent \(ga */ +#define UNDERLINE c_under /* \(ul */ +#define ROOTEN c_rooten /* root en \(rn */ +#define BOXRULE c_boxrule /* box rule \(br */ +#define LEFTHAND c_lefthand /* left hand for word overflow */ +#define DAGGER c_dagger /* dagger for end of sentence/footnote */ + +#define HYPHALG 1 /* hyphenation algorithm: 0=>good old troff, 1=>tex */ + + +/* array sizes, and similar limits: */ + +#define MAXFONTS 99 /* Maximum number of fonts in fontab */ +#define NM 90 /* requests + macros */ +#define NN NNAMES /* number registers */ +#define NNAMES 15 /* predefined reg names */ +#define NIF 15 /* if-else nesting */ +#define NS 128 /* name buffer */ +#define NTM 1024 /* tm buffer */ +#define NEV 3 /* environments */ +#define EVLSZ 10 /* size of ev stack */ + +#define STACKSIZE (6*1024) /* stack for macros and strings in progress */ +#define NHYP 10 /* max hyphens per word */ +#define NHEX 512 /* byte size of exception word list */ +#define NTAB 100 /* tab stops */ +#define NSO 5 /* "so" depth */ +#define NMF 5 /* number of -m flags */ +#define WDSIZE 500 /* word buffer click size */ +#define LNSIZE 4000 /* line buffer click size */ +#define OLNSIZE 5000 /* output line buffer click; bigger for 'w', etc. */ +#define NDI 5 /* number of diversions */ + +#define ALPHABET alphabet /* number of characters in basic alphabet. */ + /* 128 for parochial USA 7-bit ascii, */ + /* 256 for "European" mode with e.g., Latin-1 */ + + /* NCHARS must be greater than + ALPHABET (ascii stuff) + total number of distinct char names + from all fonts that will be run in this job (including + unnamed ones and \N's) + */ + +#define NCHARS (8*1024) /* maximum size of troff character set*/ + + + /* However for nroff you want only : + 1. number of special codes in charset of DESC, which ends up being the + value of nchtab and which must be less than 512. + 2. ALPHABET, which apparently is the size of the portion of the tables reserved + for special control symbols + Apparently the max N of \N is irrelevant; */ + /* to allow \N of up to 254 with up to 338 special characters + you need NCHARS of 338 + ALPHABET = 466 */ + +#define NROFFCHARS 1024 /* maximum size of nroff character set */ + +#define NTRTAB NCHARS /* number of items in trtab[] */ +#define NWIDCACHE NCHARS /* number of items in widcache[] */ + +#define NTRAP 20 /* number of traps */ +#define NPN 20 /* numbers in "-o" */ +#define FBUFSZ 512 /* field buf size words */ +#define IBUFSZ 4096 /* bytes */ +#define NC 1024 /* cbuf size words */ +#define NOV 10 /* number of overstrike chars */ +#define NPP 10 /* pads per field */ + +/* + Internal character representation: + Internally, every character is carried around as + a 32 bit cookie, called a "Tchar" (typedef long). + Bits are numbered 31..0 from left to right. + If bit 15 is 1, the character is motion, with + if bit 16 it's vertical motion + if bit 17 it's negative motion + If bit 15 is 0, the character is a real character. + if bit 31 zero motion + bits 30..24 size + bits 23..16 font +*/ + +/* in the following, "L" should really be a Tchar, but ... */ +/* numerology leaves room for 16 bit chars */ + +#define MOT (01uL << 16) /* motion character indicator */ +#define VMOT (01uL << 30) /* vertical motion bit */ +#define NMOT (01uL << 29) /* negative motion indicator */ +/* #define MOTV (MOT|VMOT|NMOT) /* motion flags */ +/* #define MAXMOT (~MOTV) /* maximum motion permitted */ +#define MAXMOT 0xFFFF + +#define ismot(n) ((n) & MOT) +#define isvmot(n) (((n) & (MOT|VMOT)) == (MOT|VMOT)) /* must have tested MOT previously */ +#define isnmot(n) (((n) & (MOT|NMOT)) == (MOT|NMOT)) /* ditto */ +#define absmot(n) ((n) & 0xFFFF) + +#define ZBIT (01uL << 31) /* zero width char */ +#define iszbit(n) ((n) & ZBIT) + +#define FSHIFT 17 +#define SSHIFT (FSHIFT+7) +#define SMASK (0177uL << SSHIFT) /* 128 distinct sizes */ +#define FMASK (0177uL << FSHIFT) /* 128 distinct fonts */ +#define SFMASK (SMASK|FMASK) /* size and font in a Tchar */ +#define sbits(n) (((n) >> SSHIFT) & 0177) +#define fbits(n) (((n) >> FSHIFT) & 0177) +#define sfbits(n) (((n) & SFMASK) >> FSHIFT) +#define cbits(n) ((n) & 0x1FFFF) /* isolate character bits, */ + /* but don't include motions */ +extern int realcbits(Tchar); + +#define setsbits(n,s) n = (n & ~SMASK) | (Tchar)(s) << SSHIFT +#define setfbits(n,f) n = (n & ~FMASK) | (Tchar)(f) << FSHIFT +#define setsfbits(n,sf) n = (n & ~SFMASK) | (Tchar)(sf) << FSHIFT +#define setcbits(n,c) n = (n & ~0xFFFFuL | (c)) /* set character bits */ + +#define BYTEMASK 0377 +#define BYTE 8 + +#define SHORTMASK 0XFFFF +#define SHORT 16 + +#define TABMASK ((unsigned) INT_MAX >> 1) +#define RTAB ((TABMASK << 1) & ~TABMASK) +#define CTAB (RTAB << 1) + +#define TABBIT 02 /* bits in gchtab */ +#define LDRBIT 04 +#define FCBIT 010 + +#define PAIR(A,B) (A|(B<_ics +#define sps envp->_sps +#define spacesz envp->_spacesz +#define lss envp->_lss +#define lss1 envp->_lss1 +#define ll envp->_ll +#define ll1 envp->_ll1 +#define lt envp->_lt +#define lt1 envp->_lt1 +#define ic envp->_ic +#define icf envp->_icf +#define chbits envp->_chbits +#define spbits envp->_spbits +#define nmbits envp->_nmbits +#define apts envp->_apts +#define apts1 envp->_apts1 +#define pts envp->_pts +#define pts1 envp->_pts1 +#define font envp->_font +#define font1 envp->_font1 +#define ls envp->_ls +#define ls1 envp->_ls1 +#define ad envp->_ad +#define nms envp->_nms +#define ndf envp->_ndf +#define nmwid envp->_nmwid +#define fi envp->_fi +#define cc envp->_cc +#define c2 envp->_c2 +#define ohc envp->_ohc +#define tdelim envp->_tdelim +#define hyf envp->_hyf +#define hyoff envp->_hyoff +#define hyphalg envp->_hyphalg +#define un1 envp->_un1 +#define tabc envp->_tabc +#define dotc envp->_dotc +#define adsp envp->_adsp +#define adrem envp->_adrem +#define lastl envp->_lastl +#define nel envp->_nel +#define admod envp->_admod +#define wordp envp->_wordp +#define spflg envp->_spflg +#define linep envp->_linep +#define wdend envp->_wdend +#define wdstart envp->_wdstart +#define wne envp->_wne +#define ne envp->_ne +#define nc envp->_nc +#define nb envp->_nb +#define lnmod envp->_lnmod +#define nwd envp->_nwd +#define nn envp->_nn +#define ni envp->_ni +#define ul envp->_ul +#define cu envp->_cu +#define ce envp->_ce +#define in envp->_in +#define in1 envp->_in1 +#define un envp->_un +#define wch envp->_wch +#define pendt envp->_pendt +#define pendw envp->_pendw +#define pendnf envp->_pendnf +#define spread envp->_spread +#define it envp->_it +#define itmac envp->_itmac +#define hyptr envp->_hyptr +#define tabtab envp->_tabtab +#define line envp->_line._bufp +#define lnsize envp->_line._size +#define word envp->_word._bufp +#define wdsize envp->_word._size + +#define oline _oline._bufp +#define olnsize _oline._size + +/* + * Note: + * If this structure changes in ni.c, you must change + * this as well, and vice versa. + */ + +struct Env { + int _ics; + int _sps; + int _spacesz; + int _lss; + int _lss1; + int _ll; + int _ll1; + int _lt; + int _lt1; + Tchar _ic; + int _icf; + Tchar _chbits; + Tchar _spbits; + Tchar _nmbits; + int _apts; + int _apts1; + int _pts; + int _pts1; + int _font; + int _font1; + int _ls; + int _ls1; + int _ad; + int _nms; + int _ndf; + int _nmwid; + int _fi; + int _cc; + int _c2; + int _ohc; + int _tdelim; + int _hyf; + int _hyoff; + int _hyphalg; + int _un1; + int _tabc; + int _dotc; + int _adsp; + int _adrem; + int _lastl; + int _nel; + int _admod; + Tchar *_wordp; + int _spflg; + Tchar *_linep; + Tchar *_wdend; + Tchar *_wdstart; + int _wne; + int _ne; + int _nc; + int _nb; + int _lnmod; + int _nwd; + int _nn; + int _ni; + int _ul; + int _cu; + int _ce; + int _in; + int _in1; + int _un; + int _wch; + int _pendt; + Tchar *_pendw; + int _pendnf; + int _spread; + int _it; + int _itmac; + Tchar *_hyptr[NHYP]; + long _tabtab[NTAB]; + Tbuf _line; + Tbuf _word; +}; + +extern Env env[]; +extern Env *envp; + +enum { MBchar = 'U', Troffchar = 'C', Number = 'N', Install = 'i', Lookup = 'l' }; + /* U => utf, for instance; C => \(xx, N => \N'...' */ + + + +struct Chwid { /* data on one character */ + Ushort num; /* character number: + 0 -> not on this font + >= ALPHABET -> its number among all Cxy's */ + Ushort code; /* char code for actual device. used for \N */ + char *str; /* code string for nroff */ + Uchar wid; /* width */ + Uchar kern; /* ascender/descender */ +}; + +struct Font { /* characteristics of a font */ + int name; /* int name, e.g., BI (2 chars) */ + char longname[64]; /* long name of this font (e.g., "Bembo" */ + char *truename; /* path name of table if not in standard place */ + int nchars; /* number of width entries for this font */ + char specfont; /* 1 == special font */ + int spacewidth; /* width of space on this font */ + int defaultwidth; /* default width of characters on this font */ + Chwid *wp; /* widths, etc., of the real characters */ + char ligfont; /* 1 == ligatures exist on this font */ +}; + +/* ligatures, ORed into ligfont */ + +#define LFF 01 +#define LFI 02 +#define LFL 04 +#define LFFI 010 +#define LFFL 020 + +/* tracing modes */ +#define TRNARGS 01 /* trace legality of numeric arguments */ +#define TRREQ 02 /* trace requests */ +#define TRMAC 04 /* trace macros */ +#define RQERR 01 /* processing request/macro */ + +/* typewriter driving table structure */ + + +extern Term t; +struct Term { + int bset; /* these bits have to be on */ + int breset; /* these bits have to be off */ + int Hor; /* #units in minimum horiz motion */ + int Vert; /* #units in minimum vert motion */ + int Newline; /* #units in single line space */ + int Char; /* #units in character width */ + int Em; /* ditto */ + int Halfline; /* half line units */ + int Adj; /* minimum units for horizontal adjustment */ + char *twinit; /* initialize terminal */ + char *twrest; /* reinitialize terminal */ + char *twnl; /* terminal sequence for newline */ + char *hlr; /* half-line reverse */ + char *hlf; /* half-line forward */ + char *flr; /* full-line reverse */ + char *bdon; /* turn bold mode on */ + char *bdoff; /* turn bold mode off */ + char *iton; /* turn italic mode on */ + char *itoff; /* turn italic mode off */ + char *ploton; /* turn plot mode on */ + char *plotoff; /* turn plot mode off */ + char *up; /* sequence to move up in plot mode */ + char *down; /* ditto */ + char *right; /* ditto */ + char *left; /* ditto */ + + Font tfont; /* widths and other info, as in a troff font */ +}; + +extern Term t; + +/* + * for error reporting; keep track of escapes/requests with numeric arguments + */ +struct Numerr { + char type; /* request or escape? */ + char esc; /* was escape sequence named esc */ + char escarg; /* argument of esc's like \D'l' */ + unsigned int req; /* was request or macro named req */ +}; blob - /dev/null blob + 67aed817b4e4fffc6f1f9121b5e0617014c966f8 (mode 644) --- /dev/null +++ src/cmd/troff/unansi @@ -0,0 +1,49 @@ +# The awk program cvt will convert the relatively sterotyped ansi c +# in this troff distribution into older-style c, by munging function +# declarations. + +# You will also have to edit fns.h, by +# sed 's/(.*)/()/g' fns.h >foo; mv foo fns.h +# check this before doing the move! + +# you will also have to make some editing changes in +# tdef.h in the Contab structure: s/(void)/()/ +# you may have to fix up some function declarations +# in n4.c, the ones with (*f)(Tchar). + +# you will surely also have header files to deal with. + +# the most obvious cases are dealt with by the following +# commands. make sure you do this stuff on a copy! + +# function prototypes in n8.c probably belong in fns.h. readpats(void) must +# be readpats() before cvt runs. + +sed \ + -e 's/(void)/()/' \ + -e 's/(Tchar[^)]*);/();/' \ + -e 's/(char[^)]*);/();/' \ + -e 's/(int[^)]*);/();/' \ +n8.c >foo +mv foo n8.c + +for i in *.c +do + cvt $i >foo + mv foo $i +done + +sed 's/(.*)/()/g' fns.h >foo +mv foo fns.h + +sed -e 's/(void)/()/g' -e '/stdlib/d' tdef.h >foo +mv foo tdef.h + +# Compliers may not approve of void *setbrk() in fns.h and n3.c. + +sed 's/^void\*[ ]setbrk/char* setbrk/' fns.h >foo +mv foo fns.h + +sed 's/^void \*setbrk/char *setbrk/' n3.c >foo +mv foo n3.c +