Beispiel #1
0
static void
oput(int ch)

    /* int		ch;			/ * next output character */

{

/*
 *
 * Responsible for adding all printing characters from the input file to the
 * open string on top of the stack. The only other characters that end up in
 * that string are the quotes required for special characters. Reverse printing
 * mode hasn't been tested but it should be close. hpos and lastx should disagree
 * each time (except after startline() does something), and that should force a
 * call to endstring() for every character.
 *
 */

    if ( stringcount > 100 )		/* don't put too much on the stack */
	endline();

    if ( vpos != lasty )
	endline();

    if ( advance == -1 )		/* for reverse printing - move first */
	hmot(hmi);

    startline();

    if ( lastc != ch || hpos != prevx )  {
	if ( lastx != hpos )
	    endstring();

	if ( isascii(ch) && isprint(ch) ) {
	    if ( ch == '\\' || ch == '(' || ch == ')' )
		putc('\\', fp_out);
	    putc(ch, fp_out);
	} else fprintf(fp_out, "\\%.3o", ch & 0377);

	lastc = ch;
	prevx = hpos;
	lastx += lasthmi;
    }	/* End if */

    if ( advance != -1 )
	hmot(hmi);

    markedpage = TRUE;

}   /* End of oput */
Beispiel #2
0
static void
backspace(void)

{

/*
 *
 * Moves backwards a distance equal to the current value of hmi, but don't go
 * past the left margin.
 *
 */

    endline();

    if ( hpos - leftmargin >= hmi )
	hmot(-hmi);
    else hgoto(leftmargin);		/* maybe just ignore the backspace?? */

    lastx = hpos;

}   /* End of backspace */
Beispiel #3
0
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 */
}
Beispiel #4
0
void
drawline(int dx, int dy, char *s) /* draw line from here to dx, dy using s */
{
	int xd, yd;
	float val, slope;
	int i, numdots;
	int dirmot, perp;
	int motincr, perpincr;
	int ohpos, ovpos, osize;
	float incrway;

	int itemp; /*temp. storage for value returned byint function sgn*/
	osize = size;
	setsize(t_size(pstab[osize-1] / drawsize));
	ohpos = hpos;
	ovpos = vpos;
	xd = dx / DX;
	yd = dy / DX;
	if (xd == 0) {
		numdots = abs (yd);
		numdots = min(numdots, maxdots);
		motincr = DX * sgn (yd);
		for (i = 0; i < numdots; i++) {
			vmot(motincr);
			put1(drawdot);
		}
		vgoto(ovpos + dy);
		setsize(osize);
		return;
	}
	if (yd == 0) {
		numdots = abs (xd);
		motincr = DX * sgn (xd);
		for (i = 0; i < numdots; i++) {
			hmot(motincr);
			put1(drawdot);
		}
		hgoto(ohpos + dx);
		setsize(osize);
		return;
	}
	if (abs (xd) > abs (yd)) {
		val = slope = (float) xd/yd;
		numdots = abs (xd);
		numdots = min(numdots, maxdots);
		dirmot = 'h';
		perp = 'v';
		motincr = DX * sgn (xd);
		perpincr = DX * sgn (yd);
	}
	else {
		val = slope = (float) yd/xd;
		numdots = abs (yd);
		numdots = min(numdots, maxdots);
		dirmot = 'v';
		perp = 'h';
		motincr = DX * sgn (yd);
		perpincr = DX * sgn (xd);
	}
	incrway = itemp = sgn ((int) slope);
	for (i = 0; i < numdots; i++) {
		val -= incrway;
		if (dirmot == 'h')
			hmot(motincr);
		else
			vmot(motincr);
		if (val * slope < 0) {
			if (perp == 'h')
				hmot(perpincr);
			else
				vmot(perpincr);
			val += slope;
		}
		put1(drawdot);
	}
	hgoto(ohpos + dx);
	vgoto(ovpos + dy);
	setsize(osize);
}
Beispiel #5
0
void
conv(Biobuf *Bp) {
	long n;
	int r;
	char special[10];
	int save;

	inputlineno = 1;
	if (debug) Bprint(Bstderr, "conv(Biobufhdr *Bp=0x%x)\n", Bp);
	while ((r = Bgetrune(Bp)) >= 0) {
/* Bprint(Bstderr, "r=<%c>,0x%x\n", r, r); */
/*		Bflush(Bstderr); */
		switch (r) {
		case 's':	/* set point size */
			Bgetfield(Bp, 'd', &fontsize, 0);
			break;
		case 'f':	/* set font to postion */
			Bgetfield(Bp, 'd', &fontpos, 0);
			save = inputlineno;
			settrfont();
			inputlineno = save;	/* ugh */
			break;
		case 'c':	/* print rune */
			r = Bgetrune(Bp);
			runeout(r);
			break;
		case 'C':	/* print special character */
			Bgetfield(Bp, 's', special, 10);
			specialout(special);
			break;
		case 'N':	/* print character with numeric value from current font */
			Bgetfield(Bp, 'd', &n, 0);
			break;
		case 'H':	/* go to absolute horizontal position */
			Bgetfield(Bp, 'd', &n, 0);
			hgoto(n);
			break;
		case 'V':	/* go to absolute vertical position */
			Bgetfield(Bp, 'd', &n, 0);
			vgoto(n);
			break;
		case 'h':	/* go to relative horizontal position */
			Bgetfield(Bp, 'd', &n, 0);
			hmot(n);
			break;
		case 'v':	/* go to relative vertical position */
			Bgetfield(Bp, 'd', &n, 0);
			vmot(n);
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
				/* move right nn units, then print character c */
			n = (r - '0') * 10;
			r = Bgetrune(Bp);
			if (r < 0)
				error(FATAL, "EOF or error reading input\n");
			else if (r < '0' || r > '9')
				error(FATAL, "integer expected\n");
			n += r - '0';
			r = Bgetrune(Bp);
			hmot(n);
			runeout(r);
			break;
		case 'p':	/* begin page */
			Bgetfield(Bp, 'd', &n, 0);
			endpage();
			startpage();
			break;
		case 'n':	/* end of line (information only 'b a' follows) */
			Brdline(Bp, '\n');	/* toss rest of line */
			inputlineno++;
			break;
		case 'w':	/* paddable word space (information only) */
			break;
		case 'D':	/* graphics function */
			draw(Bp);
			break;
		case 'x':	/* device control functions */
			devcntl(Bp);
			break;
		case '#':	/* comment */
			Brdline(Bp, '\n');	/* toss rest of line */
		case '\n':
			inputlineno++;
			break;
		default:
			error(WARNING, "unknown troff function <%c>\n", r);
			break;
		}
	}
	endpage();
	if (debug) Bprint(Bstderr, "r=0x%x\n", r);
	if (debug) Bprint(Bstderr, "leaving conv\n");
}
Beispiel #6
0
void
main(void)
{
	int c, n;
	char str[100], *args[10];
	int jfont, curfont;

	if(initdraw(0, fontfile, 0) < 0){
		fprint(2, "mnihongo: can't initialize display: %r\n");
		exits("open");
	}
	Binit(&bin, 0, OREAD);
	Binit(&bout, 1, OWRITE);

	jfont = -1;
	curfont = 1;
	while ((c = Bgetc(&bin)) >= 0) {
		switch (c) {
		case '\n':	/* when input is text */
		case ' ':
		case '\0':		/* occasional noise creeps in */
			putchar(c);
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			/* two motion digits plus a character */
			putchar(c);	/* digit 1 */
			n = (c-'0')*10;
			c = Bgetc(&bin);
			putchar(c);	/* digit 2 */
			n += c - '0';
			hmot(n);
			putchar(Bgetc(&bin));	/* char itself */
			break;
		case 'c':	/* single character */
			c = Bgetrune(&bin);
			if(c==' ')	/* why does this happen? it's troff - bwk */
				break;
			else if(jfont == curfont){
				Bungetrune(&bin);
				Bgetstr(&bin, str);
				kanji(str);
			}else{
				putchar('c');
				putchar(c);
			}
			break;
		case 'C':
			Bgetstr(&bin, str);
			Bprint(&bout, "C%s", str);
			break;
		case 'f':
			Bgetstr(&bin, str);
			curfont = atoi(str);
			if(curfont < 0 || curfont > 20)
				curfont = 1;	/* sanity */
			Bprint(&bout, "%c%s", c, str);
			break;
		case 'N':	/* absolute character number */
		case 's':
		case 'p':	/* new page */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			break;
		case 'H':	/* absolute horizontal motion */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			hgoto(n);
			break;
		case 'h':	/* relative horizontal motion */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			hmot(n);
			break;
		case 'V':
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			vgoto(n);
			break;
		case 'v':
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			vmot(n);
			break;

		case 'w':	/* word space */
			putchar(c);
			break;

		case 'x':	/* device control */
			Bgetline(&bin, str);
			Bprint(&bout, "%c%s", c, str);
			if(tokenize(str, args, 10)>2 && args[0][0]=='f' && ('0'<=args[1][0] && args[1][0]<='9')){
				if(strncmp(args[2], "Jp", 2) == 0)
					jfont = atoi(args[1]);
				else if(atoi(args[1]) == jfont)
					jfont = -1;
			}
			break;

		case 'D':	/* draw function */
		case 'n':	/* end of line */
		case '#':	/* comment */
			Bgetline(&bin, str);
			Bprint(&bout, "%c%s", c, str);
			break;
		default:
			fprint(2, "mnihongo: unknown input character %o %c\n", c, c);
			exits("error");
		}
	}
}
Beispiel #7
0
/* output glyph.  Use first rune to look up character (hash)
 * then use stoken UTF string to find correct glyph in linked
 * list of glyphs in bucket.
 */
void
glyphout(Rune rune, char *stoken, BOOLEAN specialflag) {
	struct charent **cp;
	struct troffont *tfp;
	struct psfent *psfp;
	int i, t, mi, wid;
	int fontid;	/* this is the troff font table index, not the mounted font table index */
	Rune r;

	mi = 0;
	settrfont();

	/* check current font for the character, special or not */
	fontid = curtrofffontid;
	if (debug)
		fprint(2, "\tlooking through current font: trying %s\n",
			troffontab[fontid].trfontid);
	cp = findglyph(fontid, rune, stoken);
	if (*cp != 0)
		goto foundit;

	if (specialflag) {
		if (expecthmot)
			hmot(0);

		/* check special fonts for the special character */
		/* cycle through the (troff) mounted fonts starting at the next font */
		for (mi=0; mi<fontmnt; mi++) {
			if (troffontab[fontid].trfontid==0)
				error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",
					fontid, troffontab[fontid].trfontid);
			if (fontmtab[mi]==0) {
				if (debug)
					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",
						mi, fontmtab[mi], fontmnt);
				continue;
			}
			if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0)
				break;
		}
		if (mi==fontmnt)
			error(FATAL, "current troff font is not mounted, botch!\n");
		for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
			if (fontmtab[i]==0) {
				if (debug)
					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",
						i, fontmtab[i], fontmnt);
				continue;
			}
			fontid = findtfn(fontmtab[i], TRUE);
if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
			if (troffontab[fontid].special) {
				cp = findglyph(fontid, rune, stoken);
				if (*cp != 0)
					goto foundit;
			}
		}

		/* check font 1 (if current font is not font 1) for the special character */
		if (mi != 1) {
				fontid = findtfn(fontmtab[1], TRUE);;
if (debug) fprint(2, "	looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);
				cp = findglyph(fontid, rune, stoken);
				if (*cp != 0) goto foundit;
		}
	}

	if (*cp == 0) {
		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
			troffontab[curtrofffontid].trfontid);
		expecthmot = 0;
	}

	/* use the peter face in lieu of the character that we couldn't find */
	rune = 'p';	stoken = "pw";
	for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
		if (fontmtab[i]==0) {
			if (debug) fprint(2, "fontmtab[%d]=%#p\n", i, fontmtab[i]);
			continue;
		}
		fontid = findtfn(fontmtab[i], TRUE);
if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
		if (troffontab[fontid].special) {
			cp = findglyph(fontid, rune, stoken);
			if (*cp != 0) goto foundit;
		}
	}

	if (*cp == 0) {
		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n",
			rune, stoken, troffontab[curtrofffontid].trfontid);
		expecthmot = 0;
		return;
	}

foundit:
	t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff);
	if (debug)
		fprint(2, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n",
			rune, rune, (*cp)->postfontid, (*cp)->postcharid,
			(*cp)->troffcharwidth);

	tfp = &troffontab[fontid];
	psfp = nil;
	for (i=0; i<tfp->psfmapsize; i++) {
		psfp = &(tfp->psfmap[i]);
		if(t>=psfp->start && t<=psfp->end)
			break;
	}
	if (i >= tfp->psfmapsize)
		error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune);

	setpsfont(psfp->psftid, fontsize);

	if (t == 0x0001) {	/* character is in charlib */
		endstring();
		if (pageon()) {
			Bprint(Bstdout, "%d %d m ", hpos, vpos);
			/* if char is unicode character rather than name, clean up for postscript */
			wid = chartorune(&r, (*cp)->name);
			if(' '<r && r<0x7F)
				Bprint(Bstdout, "%d build_%s\n",
					(*cp)->troffcharwidth, (*cp)->name);
			else{
				if((*cp)->name[wid] != 0)
					error(FATAL, "character <%s> badly named\n", (*cp)->name);
				Bprint(Bstdout, "%d build_X%.4x\n",
					(*cp)->troffcharwidth, r);
			}

			/*
			 * stash charent pointer in a list so that we can
			 * print these character definitions in the prologue.
			 */
			for (i=0; i<build_char_cnt; i++)
				if (*cp == build_char_list[i])
					break;
			if (i == build_char_cnt) {
				build_char_list = galloc(build_char_list,
					sizeof(struct charent *)*++build_char_cnt,
					"build_char_list");
				build_char_list[build_char_cnt-1] = *cp;
			}
		}
		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
	} else if (isinstring() || rune != ' ') {
		startstring();
		if (pageon())
			if (rune == ' ')
				Bprint(Bstdout, " ");
			else
				Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str);
		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
	}
}
Beispiel #8
0
void
conv(register FILE *fp)
{
	register int c, k;
	int m, n, n1, m1;
	char str[4096], buf[4096];

	while ((c = getc(fp)) != EOF) {
		switch (c) {
		case '\n':	/* when input is text */
		case ' ':
		case 0:		/* occasional noise creeps in */
			break;
		case '{':	/* push down current environment */
			t_push();
			break;
		case '}':
			t_pop();
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			/* two motion digits plus a character */
			hmot((c-'0')*10 + getc(fp)-'0');
			put1(getc(fp));
			break;
		case 'c':	/* single ascii character */
			put1(getc(fp));
			break;
		case 'C':
			sget(str, sizeof str, fp);
			put1s(str);
			break;
		case 't':	/* straight text */
			fgets(buf, sizeof(buf), fp);
			t_text(buf);
			break;
		case 'D':	/* draw function */
			fgets(buf, sizeof(buf), fp);
			switch (buf[0]) {
			case 'l':	/* draw a line */
				sscanf(buf+1, "%d %d", &n, &m);
				drawline(n, m, ".");
				break;
			case 'c':	/* circle */
				sscanf(buf+1, "%d", &n);
				drawcirc(n);
				break;
			case 'e':	/* ellipse */
				sscanf(buf+1, "%d %d", &m, &n);
				drawellip(m, n);
				break;
			case 'a':	/* arc */
				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
				drawarc(n, m, n1, m1);
				break;
			case '~':	/* wiggly line */
				drawwig(buf+1);
				break;
			default:
				error(FATAL, "unknown drawing function %s\n", buf);
				break;
			}
			break;
		case 's':
			fscanf(fp, "%d", &n);
			if (n == -23) {
				float	f;
				fscanf(fp, "%f", &f);
				setsize(f);
			} else
				setsize(t_size(n));/* ignore fractional sizes */
			break;
		case 'f':
			sget(str, sizeof str, fp);
			setfont(t_font(str));
			break;
		case 'H':	/* absolute horizontal motion */
			/* fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			ungetc(c, fp);
			hgoto(k);
			break;
		case 'h':	/* relative horizontal motion */
			/* fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			ungetc(c, fp);
			hmot(k);
			break;
		case 'w':	/* word space */
			putc(' ', stdout);
			break;
		case 'V':
			fscanf(fp, "%d", &n);
			vgoto(n);
			break;
		case 'v':
			fscanf(fp, "%d", &n);
			vmot(n);
			break;
		case 'p':	/* new page */
			fscanf(fp, "%d", &n);
			t_page(n);
			break;
		case 'n':	/* end of line */
			while (getc(fp) != '\n')
				;
			t_newline();
			break;
		case '#':	/* comment */
			while (getc(fp) != '\n')
				;
			break;
		case 'x':	/* device control */
			devcntrl(fp);
			break;
		default:
			error(!FATAL, "unknown input character %o %c\n", c, c);
			done();
		}
	}
}