home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1985, 1986, 1987, 1988 Chris Lewis
- All Rights Reserved
-
- Permission to copy and further distribute is freely given provided
- this copyright notice remains intact and that this software is not
- sold for profit.
-
- Project: Generic Troff drivers
- Module: troff2.c
- Author: Chris Lewis
- Specs: Troff interpreter, needs a driver to work.
- */
-
- #include "defs.h"
-
- #ifndef lint
- static char SCCSid[] =
- "@(#)troff2.c: 2.2 Copyright 90/08/10 15:15:35 Chris Lewis";
- #endif
-
- #define ESC 0x80
- #define FLASH 0x00
- #define CONTROL 0x40
- #define LEAD 0x60
- #define SIZE 0x50
-
- #define DOWN 0
- #define UP 1
- #define LOWER 2
- #define UPPER 3
- #define FORWARD 4
- #define BACKWARD 5
-
- #ifdef BSDHACK
- int magnify_lead = 0;
- #endif
-
- char ptab[15] = { 7, 8, 10, 11, 12, 14, 18, 9, 6, 16, 20, 22, 24, 28, 36};
- int points;
-
- int xpos, ypos;
-
- #ifdef VDEBUG
- char *words[] = {
- "down", "up", "lower", "upper", "forward", "backwards"
- };
- #endif
-
-
- #define CTOINT(val,sig) ((~c)&sig)
-
- int pagelength;
- int pageoffset;
- int pageyoffset;
-
- char *version, *shortversion;
-
- int dumpflag = 0;
-
- #define CFONT (((mag == UPPER)<<2)|((rail == UPPER)<<1)|(tilt==DOWN))
- #ifdef FONT4
- #define calcfont font = (CFONT >> 1)
- #else
- #define calcfont font = CFONT
- #endif
-
- char *progname;
- char *printer;
- char *device = {"alw"};
- char **prologs = (char **) NULL;
- #define PROCHUNK 20
- int procount;
-
- #ifdef L_cuserid
- #define nmMAX L_cuserid
- #else
- #define nmMAX 16
- #endif
-
- char username[nmMAX];
-
- double calc();
-
- char *driver = "ps";
- #ifdef OPT
- char *widthtables = (char *)NULL;
- char *widthptr;
- int optimize = 0;
- #endif
-
- extern char *realloc();
-
- #define OPTLIST "d:O:Y:T:VD:l:MR:P::zp:W:Z"
-
- /* On 386/ix 1.0.6 profiling has a bug in it that leaves
- two extra longs on the stack between the stack frame and
- arguments on entry to main */
- #ifdef PROFBUG
-
- main(j1, j2, argc, argv)
- long j1, j2;
- int argc;
- char **argv; {
-
- #else
-
- main(argc, argv)
- int argc;
- char **argv; {
-
- #endif
- register int nc, c;
- register int units;
- register int font, rail, mag, tilt, half, escape, lead;
-
- extern int getopt();
- extern char *optarg;
-
- #ifdef L_cuserid
- extern char *cuserid();
-
- (void) cuserid(username);
- if (!username[0])
- #else
-
- extern char *getlogin();
-
- progname = getlogin();
- if (progname)
- strcpy(username, progname);
- else
- /* I could read /etc/passwd, but hell, why? */
- #endif
- sprintf(username, "uid=%d", getuid());
-
- /* some compilers complain about floating point in initializers... */
- pagelength = DEFPL * TROFFRESOLUTION;
- pageoffset = DEFOFF * TROFFRESOLUTION;
- pageyoffset = DEFYOFF * TROFFRESOLUTION;
-
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- version = T2VERSION + 4;
- shortversion = strchr(version, '-') + 2;
-
- while((c = getopt(argc, argv, OPTLIST)) != EOF)
- switch (c) {
- #ifdef OPT
- case 'Z':
- optimize = 1;
- break;
- case 'W':
- widthtables = mustmalloc(strlen(optarg) + 10, "widthname");
- strcpy(widthtables, optarg);
- strcat(widthtables, "/");
- break;
- #else
- case 'Z':
- case 'W':
- fprintf(stderr,
- "%s: optimization disabled; -Z/-W ignored (%s)\n",
- progname, "see OPT in defs.h");
- break;
- #endif
- case 'P':
- if (!prologs) {
- prologs = (char **) mustmalloc(PROCHUNK * sizeof(char*),
- "prologs");
- procount = 0;
- }
- prologs[procount++] = optarg;
- /* insert the null */
- if ((procount % PROCHUNK) == 0) {
- prologs = (char **) realloc((char *) prologs,
- (procount + PROCHUNK) * sizeof(char *));
- }
- prologs[procount] = (char *) NULL;
- break;
- case 'p':
- printer = optarg;
- break;
- case 'd':
- device = optarg;
- break;
- case 'z':
- dumpflag++;
- break;
- case 'T':
- driver = optarg;
- break;
- case 'R':
- #if defined(DT)
- {
- extern int dtresolution;
- dtresolution = atoi(optarg);
- if (dtresolution == 0) {
- fprintf(stderr, "%s: Invalid resolution: %s\n",
- progname, optarg);
- exit(1);
- }
- }
- break;
- #else
- fprintf(stderr, "%s: Resolution not supported\n",
- progname);
- exit(1);
- #endif
- case 'M':
- metrics = 1;
- break;
- case 'V':
- printf("%s: %s\n", progname, version);
- exit(0);
- case 'D':
- #ifdef DEBUG
- setdebug(optarg, "diagnostics");
- break;
- #else
- fprintf(stderr, "%s: DEBUG disabled - recompile\n",
- progname);
- exit(1);
- #endif
- case 'O':
- pageoffset = calc(optarg);
- break;
- case 'Y':
- pageyoffset = calc(optarg);
- break;
- case 'l':
- pagelength = calc(optarg);
- if (pagelength == 0) {
- fprintf(stderr, "%s: Bad pagelength %s\n", progname,
- optarg);
- exit(1);
- }
- break;
- case '?':
- default:
- usage();
- exit(1);
- }
-
- getdriver(driver);
-
- if (!printer)
- printer = driver;
-
- #ifdef OPT
- if (!widthtables) {
- widthtables = mustmalloc(strlen(driver) + strlen(FONTDIR) + 20,
- "widthname");
- sprintf(widthtables, "%s/%s/", FONTDIR, driver);
- }
- widthptr = widthtables + strlen(widthtables);
- #endif
-
- loadfont(be->bestdfont, be->besymfont);
- #ifdef DEBUG
- if (debug & D_SPEC) {
- for (c = 0; c < procount; c++) {
- DBP((D_SPEC, "Prolog %d: %s\n", c, prologs[c]));
- }
- }
- #endif
-
- if (dumpflag) {
-
- printf("Font table:\n\n");
- for (c = 0; fonttable[c].tab[0]; c++)
- printf("%-3s %-20s %-20s %-20s\n",
- fonttable[c].tab[0],
- fonttable[c].tab[1],
- fonttable[c].tab[2],
- fonttable[c].tab[3]);
-
- dumptables(be);
- exit(0);
- }
-
- resetState();
- if (be->beprolog)
- (*be->beprolog)();
-
- /* An Initialize sequence *usually* comes in first, but what the
- hey ... */
- xpos = 0;
- ypos = -153;
- escape = FORWARD;
- lead = FORWARD;
- half = LOWER;
- rail = LOWER;
- mag = LOWER;
- tilt = DOWN;
- calcfont;
-
- while ((c = getc(stdin)) != EOF) {
- switch(c) {
- case 0x00:
- DBP((D_CAT,"NOP\n"));
- break;
- /* Flash (print character) codes */
- case 0x01: case 0x02: case 0x03: case 0x04:
- case 0x05: case 0x06: case 0x07: case 0x08:
- case 0x09: case 0x0a: case 0x0b: case 0x0c:
- case 0x0d: case 0x0e: case 0x0f: case 0x10:
- case 0x11: case 0x12: case 0x13: case 0x14:
- case 0x15: case 0x16: case 0x17: case 0x18:
- case 0x19: case 0x1a: case 0x1b: case 0x1c:
- case 0x1d: case 0x1e: case 0x1f: case 0x20:
- case 0x21: case 0x22: case 0x23: case 0x24:
- case 0x25: case 0x26: case 0x27: case 0x28:
- case 0x29: case 0x2a: case 0x2b: case 0x2c:
- case 0x2d: case 0x2e: case 0x2f: case 0x30:
- case 0x31: case 0x32: case 0x33: case 0x34:
- case 0x35: case 0x36: case 0x37: case 0x38:
- case 0x39: case 0x3a: case 0x3b: case 0x3c:
- case 0x3d: case 0x3e: case 0x3f:
- /* This is terribly kludgey:
- In 432 units per inch, 4752 is 11 inches.
- When we go beyond this, we subtract 4752
- continually until we're back in range.
- */
- while (ypos >= pagelength) {
- ypos -= pagelength;
- DBP((D_CAT,"Page break\n"));
- if (be->bepage)
- (*be->bepage) ();
- }
- /*c = c&0x3f; Isn't necessary */
- /* Find the C/A/T code */
- if (half == UPPER) {
- if (c > 46) {
- fprintf(stderr, "%s: Illegal upper flash: %d\n",
- progname, c);
- exit(1);
- }
- nc = c + 62;
- } else
- nc = c - 1;
-
- DBP((D_CAT,"nc=%d;pnts=%d;x,y=%d,%d;fnt=%d;\n",
- nc,points,xpos,ypos,font));
- #ifdef VDEBUG
- DBP((D_CAT," rail=%s;mag=%s;tilt=%s;half=%s\n",
- words[rail], words[mag],words[tilt], words[half]));
- #endif
-
- #ifdef OPT
- canoninsert(xpos, ypos, font, points, nc);
- #else
- if (be->beputchar)
- (*be->beputchar)(xpos, ypos, font, points, nc,
- (char *) NULL);
- #endif
-
- break;
- /* Control codes */
- case 0x40:
- DBP((D_CAT,"Initialize\n"));
- xpos = 0;
- ypos = -153;
- escape = FORWARD;
- lead = FORWARD;
- half = LOWER;
- rail = LOWER;
- mag = LOWER;
- tilt = DOWN;
- calcfont;
- break;
- case 0x41:
- DBP((D_CAT,"Rail lower\n"));
- rail = LOWER;
- calcfont;
- break;
- case 0x42:
- DBP((D_CAT,"Rail upper\n"));
- rail = UPPER;
- calcfont;
- break;
- case 0x43:
- DBP((D_CAT,"Mag upper\n"));
- mag = UPPER;
- calcfont;
- break;
- case 0x44:
- DBP((D_CAT,"Mag lower\n"));
- mag = LOWER;
- calcfont;
- break;
- case 0x45:
- DBP((D_CAT,"half lower\n"));
- half = LOWER;
- break;
- case 0x46:
- DBP((D_CAT,"half upper\n"));
- half = UPPER;
- break;
- case 0x47:
- DBP((D_CAT,"Escape forward\n"));
- escape = FORWARD;
- break;
- case 0x48:
- DBP((D_CAT,"Escape backward\n"));
- escape = BACKWARD;
- break;
- case 0x49:
- DBP((D_CAT,"STOP\n"));
- break;
- case 0x4a:
- DBP((D_CAT,"Lead forward\n"));
- lead = FORWARD;
- break;
- case 0x4b:
- DBP((D_CAT,"Software cut!\n"));
- break;
- case 0x4c:
- DBP((D_CAT,"Lead backward\n"));
- lead = BACKWARD;
- break;
- case 0x4d:
- #ifdef SPECIAL
- #define SPSIZ 256
- {
- static char specialbuf[SPSIZ], *sbp;
- sbp = specialbuf;
- #ifdef OPT
- canonflush();
- #endif
- while((c = getc(stdin)) != EOF && c != '\n') {
- if (!c) /* some troff's add NOP's when
- the internal output buffer is
- flushed */
- continue;
- if (sbp < &specialbuf[SPSIZ]-2)
- *sbp++ = c;
- }
- *sbp = '\0';
-
- DBP((D_SPEC,"SPECIAL SEQUENCE: %s!\n", specialbuf));
- dospecial(specialbuf);
- break;
- }
- #else
- fprintf(stderr, "%s: Illegal C/A/T code - %s\n",
- progname, "special sequences are disabled");
- exit(1);
- #endif
- #ifdef BSDHACK
- case 0x4e:
- magnify_lead = 1;
- break;
- #endif
- #ifdef FONT8
- case 0x4e:
- DBP((D_CAT,"Tilt up\n"));
- tilt = UP;
- calcfont;
- break;
- case 0x4f:
- DBP((D_CAT,"Tilt down\n"));
- tilt = DOWN;
- calcfont;
- break;
- #endif
-
- /* Size changes */
- case 0x50: case 0x51: case 0x52: case 0x53:
- case 0x54: case 0x55: case 0x56: case 0x57:
- case 0x58: case 0x59: case 0x5a: case 0x5b:
- case 0x5c: case 0x5d: case 0x5e: case 0x5f:
- /* basic code is the points = ptab[c] line.
- The rest of the brain-damage is due to the
- fact that switching from some of the fonts
- to some of the others blow the horizontal
- position - see the cat(5) manual page
- about single vs. doubler point sizes. */
- { static lastc = 0;
- c &= 0xf;
- points = ptab[c];
-
- DBP((D_CAT,"SPoints:%d;lastc:%5d;c:%d;xpos:%d\n",
- points, lastc, c, xpos));
- if (lastc <= 8 && c > 8) /* single -> doubler */
- xpos -= 55;
- else if (lastc > 8 && c <= 8) /* doubler -> single */
- xpos += 55;
-
- DBP((D_CAT,"EPoints:%d;lastc:%5d;c:%d;xpos:%d\n",
- points, lastc, c, xpos));
- lastc = c;
- break;
- }
- /* Lead (vertical motion) codes */
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x65: case 0x66: case 0x67:
- case 0x68: case 0x69: case 0x6a: case 0x6b:
- case 0x6c: case 0x6d: case 0x6e: case 0x6f:
- case 0x70: case 0x71: case 0x72: case 0x73:
- case 0x74: case 0x75: case 0x76: case 0x77:
- case 0x78: case 0x79: case 0x7a: case 0x7b:
- case 0x7c: case 0x7d: case 0x7e: case 0x7f:
-
- #ifdef OPT
- canonflush();
- #endif
-
- DBP((D_CAT,"Lead(vertical) %02x\n", c&0x1f));
- units = CTOINT(c,0x1f);
- #ifdef BSDHACK
- if (magnify_lead) {
- units *= 64;
- magnify_lead = 0;
- }
- #endif
- if (lead == FORWARD)
- ypos += 3*units;
- else
- ypos -= 3*units;
- break;
- /* Escape (horizontal motion) codes */
- case 0x80: case 0x81: case 0x82: case 0x83:
- #ifndef lint
- case 0x84: case 0x85: case 0x86: case 0x87:
- case 0x88: case 0x89: case 0x8a: case 0x8b:
- case 0x8c: case 0x8d: case 0x8e: case 0x8f:
- case 0x90: case 0x91: case 0x92: case 0x93:
- case 0x94: case 0x95: case 0x96: case 0x97:
- case 0x98: case 0x99: case 0x9a: case 0x9b:
- case 0x9c: case 0x9d: case 0x9e: case 0x9f:
- case 0xa0: case 0xa1: case 0xa2: case 0xa3:
- case 0xa4: case 0xa5: case 0xa6: case 0xa7:
- case 0xa8: case 0xa9: case 0xaa: case 0xab:
- case 0xac: case 0xad: case 0xae: case 0xaf:
- case 0xb0: case 0xb1: case 0xb2: case 0xb3:
- case 0xb4: case 0xb5: case 0xb6: case 0xb7:
- case 0xb8: case 0xb9: case 0xba: case 0xbb:
- case 0xbc: case 0xbd: case 0xbe: case 0xbf:
- case 0xc0: case 0xc1: case 0xc2: case 0xc3:
- case 0xc4: case 0xc5: case 0xc6: case 0xc7:
- case 0xc8: case 0xc9: case 0xca: case 0xcb:
- case 0xcc: case 0xcd: case 0xce: case 0xcf:
- case 0xd0: case 0xd1: case 0xd2: case 0xd3:
- case 0xd4: case 0xd5: case 0xd6: case 0xd7:
- case 0xd8: case 0xd9: case 0xda: case 0xdb:
- case 0xdc: case 0xdd: case 0xde: case 0xdf:
- case 0xe0: case 0xe1: case 0xe2: case 0xe3:
- case 0xe4: case 0xe5: case 0xe6: case 0xe7:
- case 0xe8: case 0xe9: case 0xea: case 0xeb:
- case 0xec: case 0xed: case 0xee: case 0xef:
- case 0xf0: case 0xf1: case 0xf2: case 0xf3:
- case 0xf4: case 0xf5: case 0xf6: case 0xf7:
- case 0xf8: case 0xf9: case 0xfa: case 0xfb:
- case 0xfc: case 0xfd: case 0xfe:
- #endif
-
- units = CTOINT(c,0x7f);
- if (escape == FORWARD)
- xpos += units;
- else
- xpos -= units;
- DBP((D_CAT,"ESC (hor): %02x\n", c&0x7f));
- break;
-
- case 0xff:
- DBP((D_CAT,"Illegal: %02x\n", c));
- break;
- }
- }
- #ifdef OPT
- canonflush();
- #endif
- if (be->bepage)
- (*be->bepage)();
- if (be->beepilog)
- (*be->beepilog) ();
- exit(0);
- /* NOTREACHED */
- }
-
- usage() {
- fprintf(stderr, "usage: %s [-Ttype][-V]\n", progname);
- fprintf(stderr, " ... see troff2ps manpage for full description of %s\n",
- OPTLIST);
- }
-
- double
- calc(s)
- register char *s; {
- double retval = 0.0;
- char scale;
- switch (sscanf(s, "%lf%c", &retval, &scale)) {
- case 0:
- case EOF:
- retval = 0.0;
- case 1:
- retval *= TROFFRESOLUTION; /* default is inches */
- break;
- case 2:
- switch(scale) {
- default:
- fprintf(stderr, "%s: bad scale %c\n", progname, scale);
- retval = 0.0;
- case 'i':
- retval *= TROFFRESOLUTION;
- case 'u':
- break;
- case 'c':
- retval *= TROFFRESOLUTION * 50. / 127.;
- break;
- case 'P':
- retval *= 72.;
- break;
- }
- break;
- }
- return(retval);
- }
-
- #ifdef SPECIAL
-
- dospecial(string)
- char *string; {
- char buffer[512];
- buffer[0] = '\0';
-
- DBP((D_SPEC,"Dospecial: (%d) %s\n", strlen(string), string));
- while (*string)
- switch(*string) {
- case 'D':
- if (be->bedraw)
- (*be->bedraw)(specXPos, specYPos, string+1);
- *string = '\0';
- return;
- case 'E':
- fprintf(stderr, "%s\n", string+1);
- *string = '\0';
- return;
- case 'P':
- if (be->bepassthru)
- (*be->bepassthru)(string+1);
- else
- printf("%s\n", string+1);
- /* reset driver state! */
- resetState();
- *string = '\0';
- return;
- case 'S': {
-
- register FILE *fin;
- register int rc, n;
- char buf[BUFSIZ];
- DBP((D_SPEC,"SYSTEM: %s\n", string+1));
-
- rc = -1;
- n = 0;
- fin = popen(string+1, "r");
-
- if (fin) {
- while(rc = fread(buf, sizeof(char), BUFSIZ, fin)) {
- n += rc;
- fwrite(buf, sizeof(char), rc, stdout);
- }
- DBP((D_SPEC,"System: %d bytes read\n", n));
- rc = pclose(fin);
- }
- if (!fin || rc) {
- fprintf(stderr,
- "%s: SYSTEM request failed, command:\n '%s'\n",
- progname, string+1);
- exit(1);
- }
- /* reset driver state! */
- resetState();
- *string = '\0';
- return;
- }
- case 'F':
- if (be->befontsel)
- (*be->befontsel)(*(string+1), string+2);
- *string ='\0';
- return;
- #ifdef FORM
- case 'L':
- strcpy(buffer+2, string+1);
- buffer[1] = '+';
- *string = '\0';
- string = buffer;
- case 'O':
- if (be->beoverlay)
- (*be->beoverlay)(string+1);
- *string = '\0';
- return;
- #endif
- case 'i':
- strcpy(buffer, "b");
-
- case 'I':
- strcat(buffer, "include ");
- strcat(buffer, string+1);
- interp(buffer, (be->bexlat && *string == 'F') ? be->bexlat:
- FNULL, driver);
- return;
-
- default:
- fprintf(stderr, "%s: Illegal special sequence %s\n", progname, string);
- return;
- }
- }
-
- #endif
-