shithub: fork

Download patch

ref: e4db1403541ca7f092046154a7a88eaaf5828e64
parent: a18bf6d737025e05989a826895a5c332897cf492
author: qwx <qwx@sciops.net>
date: Mon Oct 16 00:07:11 EDT 2023

remove file.c, troff: merged

--- a/sys/src/cmd/file.c
+++ /dev/null
@@ -1,1771 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ctype.h>
-#include <mach.h>
-
-/*
- * file - determine type of file
- */
-#define	LENDIAN(p)	((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
-
-uchar	buf[6001];
-short	cfreq[140];
-short	wfreq[50];
-int	nbuf;
-Dir*	mbuf;
-int	fd;
-char 	*fname;
-char	*slash;
-
-enum
-{
-	Cword,
-	Fword,
-	Aword,
-	Alword,
-	Lword,
-	I1,
-	I2,
-	I3,
-	Clatin	= 128,
-	Cbinary,
-	Cnull,
-	Ceascii,
-	Cutf,
-};
-struct
-{
-	char*	word;
-	int	class;
-} dict[] =
-{
-	"PATH",		Lword,
-	"TEXT",		Aword,
-	"adt",		Alword,
-	"aggr",		Alword,
-	"alef",		Alword,
-	"array",	Lword,
-	"block",	Fword,
-	"char",		Cword,
-	"common",	Fword,
-	"con",		Lword,
-	"data",		Fword,
-	"dimension",	Fword,
-	"double",	Cword,
-	"extern",	Cword,
-	"bio",		I2,
-	"float",	Cword,
-	"fn",		Lword,
-	"function",	Fword,
-	"h",		I3,
-	"implement",	Lword,
-	"import",	Lword,
-	"include",	I1,
-	"int",		Cword,
-	"integer",	Fword,
-	"iota",		Lword,
-	"libc",		I2,
-	"long",		Cword,
-	"module",	Lword,
-	"real",		Fword,
-	"ref",		Lword,
-	"register",	Cword,
-	"self",		Lword,
-	"short",	Cword,
-	"static",	Cword,
-	"stdio",	I2,
-	"struct",	Cword,
-	"subroutine",	Fword,
-	"u",		I2,
-	"void",		Cword,
-};
-
-/* codes for 'mode' field in language structure */
-enum	{
-		Normal	= 0,
-		First,		/* first entry for language spanning several ranges */
-		Multi,		/* later entries "   "       "  ... */
-		Shared,		/* codes used in several languages */
-	};
-
-struct
-{
-	int	mode;		/* see enum above */
-	int 	count;
-	int	low;
-	int	high;
-	char	*name;
-
-} language[] =
-{
-	Normal,	0,	0x0100,	0x01FF,	"Extended Latin",
-	Normal,	0,	0x0370,	0x03FF,	"Greek",
-	Normal,	0,	0x0400,	0x04FF,	"Cyrillic",
-	Normal,	0,	0x0530,	0x058F,	"Armenian",
-	Normal,	0,	0x0590,	0x05FF,	"Hebrew",
-	Normal,	0,	0x0600,	0x06FF,	"Arabic",
-	Normal,	0,	0x0900,	0x097F,	"Devanagari",
-	Normal,	0,	0x0980,	0x09FF,	"Bengali",
-	Normal,	0,	0x0A00,	0x0A7F,	"Gurmukhi",
-	Normal,	0,	0x0A80,	0x0AFF,	"Gujarati",
-	Normal,	0,	0x0B00,	0x0B7F,	"Oriya",
-	Normal,	0,	0x0B80,	0x0BFF,	"Tamil",
-	Normal,	0,	0x0C00,	0x0C7F,	"Telugu",
-	Normal,	0,	0x0C80,	0x0CFF,	"Kannada",
-	Normal,	0,	0x0D00,	0x0D7F,	"Malayalam",
-	Normal,	0,	0x0E00,	0x0E7F,	"Thai",
-	Normal,	0,	0x0E80,	0x0EFF,	"Lao",
-	Normal,	0,	0x1000,	0x105F,	"Tibetan",
-	Normal,	0,	0x10A0,	0x10FF,	"Georgian",
-	Normal,	0,	0x3040,	0x30FF,	"Japanese",
-	Normal,	0,	0x3100,	0x312F,	"Chinese",
-	First,	0,	0x3130,	0x318F,	"Korean",
-	Multi,	0,	0x3400,	0x3D2F,	"Korean",
-	Shared,	0,	0x4e00,	0x9fff,	"CJK",
-	Normal,	0,	0,	0,	0,		/* terminal entry */
-};
-
-
-enum
-{
-	Fascii,		/* printable ascii */
-	Flatin,		/* latin 1*/
-	Futf,		/* UTF character set */
-	Fbinary,	/* binary */
-	Feascii,	/* ASCII with control chars */
-	Fnull,		/* NULL in file */
-} guess;
-
-void	bump_utf_count(Rune);
-int	cistrncmp(char*, char*, int);
-void	filetype(int);
-int	getfontnum(uchar*, uchar**);
-int	isas(void);
-int	isc(void);
-int	iscint(void);
-int	isenglish(void);
-int	ishp(void);
-int	ishtml(void);
-int	isrfc822(void);
-int	ismbox(void);
-int	islimbo(void);
-int	istga(void);
-int	ismp3(void);
-int	ismp4(void);
-int	isoggvorbis(void);
-int	isoggopus(void);
-int	ismung(void);
-int	isp9bit(void);
-int	isp9font(void);
-int	isrtf(void);
-int	ismsdos(void);
-int	isicocur(void);
-int	iself(void);
-int	istring(void);
-int	isoffstr(void);
-int	iff(void);
-int	long0(void);
-int	longoff(void);
-int	istar(void);
-int	isface(void);
-int	isexec(void);
-int	isudiff(void);
-int	isexecscript(void);
-int	p9bitnum(char*, int*);
-int	p9subfont(uchar*);
-void	print_utf(void);
-void	type(char*, int);
-int	utf_count(void);
-void	wordfreq(void);
-
-int	(*call[])(void) =
-{
-	long0,		/* recognizable by first 4 bytes */
-	istring,	/* recognizable by first string */
-	iself,		/* ELF (foreign) executable */
-	isexec,		/* native executables */
-	isexecscript,	/* executable scripts */
-	iff,		/* interchange file format (strings) */
-	longoff,	/* recognizable by 4 bytes at some offset */
-	isoffstr,	/* recognizable by string at some offset */
-	isudiff,	/* unified diff output */
-	isrfc822,	/* email file */
-	ismbox,		/* mail box */
-	istar,		/* recognizable by tar checksum */
-	iscint,		/* compiler/assembler intermediate */
-	ishtml,		/* html keywords */
-	islimbo,	/* limbo source */
-	isc,		/* c & alef compiler key words */
-	isas,		/* assembler key words */
-	isp9font,	/* plan 9 font */
-	isp9bit,	/* plan 9 image (as from /dev/window) */
-	isrtf,		/* rich text format */
-	ismsdos,	/* msdos exe (virus file attachement) */
-	isicocur,		/* windows icon or cursor file */
-	isface,		/* ascii face file */
-	istga,
-	isoggvorbis,
-	isoggopus,
-	ismp4,
-	ismp3,
-
-	/* last resorts */
-	ismung,		/* entropy compressed/encrypted */
-	isenglish,	/* char frequency English */
-	0
-};
-
-int mime;
-
-char OCTET[] =	"application/octet-stream";
-char PLAIN[] =	"text/plain";
-
-void
-main(int argc, char *argv[])
-{
-	int i, j, maxlen;
-	char *cp;
-	Rune r;
-
-	ARGBEGIN{
-	case 'm':
-		mime = 1;
-		break;
-	default:
-		fprint(2, "usage: file [-m] [file...]\n");
-		exits("usage");
-	}ARGEND;
-
-	maxlen = 0;
-	if(mime == 0 || argc > 1){
-		for(i = 0; i < argc; i++) {
-			for (j = 0, cp = argv[i]; *cp; j++, cp += chartorune(&r, cp))
-					;
-			if(j > maxlen)
-				maxlen = j;
-		}
-	}
-	if (argc <= 0) {
-		if(!mime)
-			print ("stdin: ");
-		filetype(0);
-	}
-	else {
-		for(i = 0; i < argc; i++)
-			type(argv[i], maxlen);
-	}
-	exits(0);
-}
-
-void
-type(char *file, int nlen)
-{
-	Rune r;
-	int i;
-	char *p;
-
-	if(nlen > 0){
-		slash = 0;
-		for (i = 0, p = file; *p; i++) {
-			if (*p == '/')			/* find rightmost slash */
-				slash = p;
-			p += chartorune(&r, p);		/* count runes */
-		}
-		print("%s:%*s",file, nlen-i+1, "");
-	}
-	fname = file;
-	if ((fd = open(file, OREAD)) < 0) {
-		fprint(2, "cannot open: %r\n");
-		return;
-	}
-	filetype(fd);
-	close(fd);
-}
-
-void
-utfconv(void)
-{
-	Rune r;
-	uchar *rb;
-	char *p, *e;
-	int i;
-
-	if(nbuf < 4)
-		return;
-
-	if(memcmp(buf, "\x00\x00\xFE\xFF", 4) == 0){
-		if(!mime)
-			print("utf-32be ");
-		return;
-	} else
-	if(memcmp(buf, "\xFE\xFF\x00\x00", 4) == 0){
-		if(!mime)
-			print("utf-32le ");
-		return;
-	} else
-	if(memcmp(buf, "\xEF\xBB\xBF", 3) == 0){
-		memmove(buf, buf+3, nbuf-3);
-		nbuf -= 3;
-		return;
-	} else
-	if(memcmp(buf, "\xFE\xFF", 2) == 0){
-		if(!mime)
-			print("utf-16be ");
-
-		nbuf -= 2;
-		rb = malloc(nbuf+1);
-		memmove(rb, buf+2, nbuf);
-		p = (char*)buf;
-		e = p+sizeof(buf)-UTFmax-1;
-		for(i=0; i<nbuf && p < e; i+=2){
-			r = rb[i+1] | rb[i]<<8;
-			p += runetochar(p, &r);
-		}
-		*p = 0;
-		free(rb);
-		nbuf = p - (char*)buf;
-	} else
-	if(memcmp(buf, "\xFF\xFE", 2) == 0){
-		if(!mime)
-			print("utf-16le ");
-
-		nbuf -= 2;
-		rb = malloc(nbuf+1);
-		memmove(rb, buf+2, nbuf);
-		p = (char*)buf;
-		e = p+sizeof(buf)-UTFmax-1;
-		for(i=0; i<nbuf && p < e; i+=2){
-			r = rb[i] | rb[i+1]<<8;
-			p += runetochar(p, &r);
-		}
-		*p = 0;
-		free(rb);
-		nbuf = p - (char*)buf;
-	}
-}
-
-void
-filetype(int fd)
-{
-	Rune r;
-	int i, f, n;
-	char *p, *eob;
-
-	free(mbuf);
-	mbuf = dirfstat(fd);
-	if(mbuf == nil){
-		fprint(2, "cannot stat: %r\n");
-		return;
-	}
-	if(mbuf->mode & DMDIR) {
-		print("%s\n", mime ? OCTET : "directory");
-		return;
-	}
-	if(mbuf->type != 'M' && mbuf->type != '|') {
-		if(mime)
-			print("%s\n", OCTET);
-		else
-			print("special file #%C/%s\n", mbuf->type, mbuf->name);
-		return;
-	}
-	/* may be reading a pipe on standard input */
-	nbuf = readn(fd, buf, sizeof(buf)-1);
-	if(nbuf < 0) {
-		fprint(2, "cannot read: %r\n");
-		return;
-	}
-	if(nbuf == 0) {
-		print("%s\n", mime ? PLAIN : "empty file");
-		return;
-	}
-	buf[nbuf] = 0;
-
-	utfconv();
-
-	/*
-	 * build histogram table
-	 */
-	memset(cfreq, 0, sizeof(cfreq));
-	for (i = 0; language[i].name; i++)
-		language[i].count = 0;
-	eob = (char *)buf+nbuf;
-	for(n = 0, p = (char *)buf; p < eob; n++) {
-		if (!fullrune(p, eob-p) && eob-p < UTFmax)
-			break;
-		p += chartorune(&r, p);
-		if (r == 0)
-			f = Cnull;
-		else if (r <= 0x7f) {
-			if (!isprint(r) && !isspace(r))
-				f = Ceascii;	/* ASCII control char */
-			else f = r;
-		} else if (r == 0x80) {
-			bump_utf_count(r);
-			f = Cutf;
-		} else if (r < 0xA0)
-			f = Cbinary;	/* Invalid Runes */
-		else if (r <= 0xff)
-			f = Clatin;	/* Latin 1 */
-		else {
-			bump_utf_count(r);
-			f = Cutf;		/* UTF extension */
-		}
-		cfreq[f]++;			/* ASCII chars peg directly */
-	}
-	/*
-	 * gross classify
-	 */
-	if (cfreq[Cbinary])
-		guess = Fbinary;
-	else if (cfreq[Cutf])
-		guess = Futf;
-	else if (cfreq[Clatin])
-		guess = Flatin;
-	else if (cfreq[Ceascii])
-		guess = Feascii;
-	else if (cfreq[Cnull])
-		guess = Fbinary;
-	else
-		guess = Fascii;
-	/*
-	 * lookup dictionary words
-	 */
-	memset(wfreq, 0, sizeof(wfreq));
-	if(guess == Fascii || guess == Flatin || guess == Futf)
-		wordfreq();
-	/*
-	 * call individual classify routines
-	 */
-	for(i=0; call[i]; i++)
-		if((*call[i])())
-			return;
-
-	/*
-	 * if all else fails,
-	 * print out gross classification
-	 */
-	if (nbuf < 100 && !mime)
-		print(mime ? PLAIN : "short ");
-	if (guess == Fascii)
-		print("%s\n", mime ? PLAIN : "Ascii");
-	else if (guess == Feascii)
-		print("%s\n", mime ? PLAIN : "extended ascii");
-	else if (guess == Flatin)
-		print("%s\n", mime ? PLAIN : "latin ascii");
-	else if (guess == Futf && utf_count() < 4)
-		print_utf();
-	else print("%s\n", mime ? OCTET : "binary");
-}
-
-void
-bump_utf_count(Rune r)
-{
-	int low, high, mid;
-
-	high = sizeof(language)/sizeof(language[0])-1;
-	for (low = 0; low < high;) {
-		mid = (low+high)/2;
-		if (r >= language[mid].low) {
-			if (r <= language[mid].high) {
-				language[mid].count++;
-				break;
-			} else low = mid+1;
-		} else high = mid;
-	}
-}
-
-int
-utf_count(void)
-{
-	int i, count;
-
-	count = 0;
-	for (i = 0; language[i].name; i++)
-		if (language[i].count > 0)
-			switch (language[i].mode) {
-			case Normal:
-			case First:
-				count++;
-				break;
-			default:
-				break;
-			}
-	return count;
-}
-
-int
-chkascii(void)
-{
-	int i;
-
-	for (i = 'a'; i < 'z'; i++)
-		if (cfreq[i])
-			return 1;
-	for (i = 'A'; i < 'Z'; i++)
-		if (cfreq[i])
-			return 1;
-	return 0;
-}
-
-int
-find_first(char *name)
-{
-	int i;
-
-	for (i = 0; language[i].name != 0; i++)
-		if (language[i].mode == First
-			&& strcmp(language[i].name, name) == 0)
-			return i;
-	return -1;
-}
-
-void
-print_utf(void)
-{
-	int i, printed, j;
-
-	if(mime){
-		print("%s\n", PLAIN);
-		return;
-	}
-	if (chkascii()) {
-		printed = 1;
-		print("Ascii");
-	} else
-		printed = 0;
-	for (i = 0; language[i].name; i++)
-		if (language[i].count) {
-			switch(language[i].mode) {
-			case Multi:
-				j = find_first(language[i].name);
-				if (j < 0)
-					break;
-				if (language[j].count > 0)
-					break;
-				/* Fall through */
-			case Normal:
-			case First:
-				if (printed)
-					print(" & ");
-				else printed = 1;
-				print("%s", language[i].name);
-				break;
-			case Shared:
-			default:
-				break;
-			}
-		}
-	if(!printed)
-		print("UTF");
-	print(" text\n");
-}
-
-void
-wordfreq(void)
-{
-	int low, high, mid, r;
-	uchar *p, *p2, c;
-
-	p = buf;
-	for(;;) {
-		while (p < buf+nbuf && !isalpha(*p))
-			p++;
-		if (p >= buf+nbuf)
-			return;
-		p2 = p;
-		while(p < buf+nbuf && isalpha(*p))
-			p++;
-		c = *p;
-		*p = 0;
-		high = sizeof(dict)/sizeof(dict[0]);
-		for(low = 0;low < high;) {
-			mid = (low+high)/2;
-			r = strcmp(dict[mid].word, (char*)p2);
-			if(r == 0) {
-				wfreq[dict[mid].class]++;
-				break;
-			}
-			if(r < 0)
-				low = mid+1;
-			else
-				high = mid;
-		}
-		*p++ = c;
-	}
-}
-
-typedef struct Filemagic Filemagic;
-struct Filemagic {
-	ulong x;
-	ulong mask;
-	char *desc;
-	char *mime;
-};
-
-/*
- * integers in this table must be as seen on a little-endian machine
- * when read from a file.
- */
-Filemagic long0tab[] = {
-	0xF16DF16D,	0xFFFFFFFF,	"pac1 audio file",	OCTET,
-	/* "pac1" */
-	0x31636170,	0xFFFFFFFF,	"pac3 audio file",	OCTET,
-	/* "pXc2 */
-	0x32630070,	0xFFFF00FF,	"pac4 audio file",	OCTET,
-	0xBA010000,	0xFFFFFFFF,	"mpeg system stream",	OCTET,
-	0x43614c66,	0xFFFFFFFF,	"FLAC audio file",	"audio/flac",
-	0x30800CC0,	0xFFFFFFFF,	"inferno .dis executable", OCTET,
-	0x04034B50,	0xFFFFFFFF,	"zip archive", "application/zip",
-	070707,		0xFFFF,		"cpio archive", "application/x-cpio",
-	0x2F7,		0xFFFF,		"tex dvi", "application/dvi",
-	0xfaff,		0xfeff,		"mp3 audio",	"audio/mpeg",
-	0xf0ff,		0xf6ff,		"aac audio",	"audio/aac",
-	/* 0xfeedface: this could alternately be a Next Plan 9 boot image */
-	0xcefaedfe,	0xFFFFFFFF,	"32-bit power Mach-O executable", OCTET,
-	/* 0xfeedfacf */
-	0xcffaedfe,	0xFFFFFFFF,	"64-bit power Mach-O executable", OCTET,
-	/* 0xcefaedfe */
-	0xfeedface,	0xFFFFFFFF,	"386 Mach-O executable", OCTET,
-	/* 0xcffaedfe */
-	0xfeedfacf,	0xFFFFFFFF,	"amd64 Mach-O executable", OCTET,
-	/* 0xcafebabe */
-	0xbebafeca,	0xFFFFFFFF,	"Mach-O universal executable", OCTET,
-	/*
-	 * venti & fossil magic numbers are stored big-endian on disk,
-	 * thus the numbers appear reversed in this table.
-	 */
-	0xad4e5cd1,	0xFFFFFFFF,	"venti arena", OCTET,
-	0x2bb19a52,	0xFFFFFFFF,	"paq archive", OCTET,
-	0x1a53454e,	0xFFFFFFFF,	"NES ROM", OCTET,
-	/* tcpdump pcap file */
-	0xa1b2c3d4,	0xFFFFFFFF,	"pcap file",	"application/vnd.tcpdump.pcap",
-	0xd4c3b2a1,	0xFFFFFFFF,	"pcap file",	"application/vnd.tcpdump.pcap",
-	0xa1b23c4d,	0xFFFFFFFF,	"pcap file",	"application/vnd.tcpdump.pcap",
-	0x4d3cb2a1,	0xFFFFFFFF,	"pcap file",	"application/vnd.tcpdump.pcap",
-};
-
-int
-filemagic(Filemagic *tab, int ntab, ulong x)
-{
-	int i;
-
-	for(i=0; i<ntab; i++)
-		if((x&tab[i].mask) == tab[i].x){
-			print("%s\n", mime ? tab[i].mime : tab[i].desc);
-			return 1;
-		}
-	return 0;
-}
-
-int
-long0(void)
-{
-	return filemagic(long0tab, nelem(long0tab), LENDIAN(buf));
-}
-
-typedef struct Fileoffmag Fileoffmag;
-struct Fileoffmag {
-	ulong	off;
-	Filemagic;
-};
-
-/*
- * integers in this table must be as seen on a little-endian machine
- * when read from a file.
- */
-Fileoffmag longofftab[] = {
-	/*
-	 * venti & fossil magic numbers are stored big-endian on disk,
-	 * thus the numbers appear reversed in this table.
-	 */
-	256*1024, 0xe7a5e4a9, 0xFFFFFFFF, "venti arenas partition", OCTET,
-	256*1024, 0xc75e5cd1, 0xFFFFFFFF, "venti index section", OCTET,
-	128*1024, 0x89ae7637, 0xFFFFFFFF, "fossil write buffer", OCTET,
-	4,	  0x31647542, 0xFFFFFFFF, "OS X finder properties", OCTET,
-	0x100,	  0x41474553, 0xFFFFFFFF, "SEGA ROM", OCTET,
-	0x1fc,	  0xAA550000, 0xFFFF0000, "bootable disk image", OCTET,
-};
-
-int
-fileoffmagic(Fileoffmag *tab, int ntab)
-{
-	int i;
-	ulong x;
-	Fileoffmag *tp;
-	uchar buf[sizeof(long)];
-
-	for(i=0; i<ntab; i++) {
-		tp = tab + i;
-		seek(fd, tp->off, 0);
-		if (readn(fd, buf, sizeof buf) != sizeof buf)
-			continue;
-		x = LENDIAN(buf);
-		if((x&tp->mask) == tp->x){
-			print("%s\n", mime ? tp->mime : tp->desc);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-int
-longoff(void)
-{
-	return fileoffmagic(longofftab, nelem(longofftab));
-}
-
-int
-isexec(void)
-{
-	Fhdr f;
-
-	seek(fd, 0, 0);		/* reposition to start of file */
-	if(crackhdr(fd, &f)) {
-		print("%s\n", mime ? OCTET : f.name);
-		return 1;
-	}
-	return 0;
-}
-
-/* executable scripts */
-int
-isexecscript(void)
-{
-	char tmp[128+1], *p;
-	
-	if (memcmp("#!", buf, 2) != 0)
-		return 0;
-	memmove(tmp, buf+2, sizeof(tmp) - 1);
-	tmp[sizeof(tmp) - 1] = 0;
-	if ((p = strchr(tmp, '\n')) != nil)
-		*p = 0;
-	if ((p = strpbrk(tmp, " \t")) != nil)
-		*p = 0;
-	if ((p = strrchr(tmp, '/')) != nil)
-		p++;
-	else
-		p = tmp;
-
-	if (strcmp("rc", p) == 0)
-		print("%s\n", mime ? PLAIN : "rc executable file");
-	else if (strcmp("sh", p) == 0)
-		print("%s\n", mime ? "application/x-sh" : "sh executable file");
-	else if (strcmp("bash", p) == 0)
-		print("%s\n", mime ? "application/x-sh" : "bash executable file");
-	else if (strcmp("awk", p) == 0)
-		print("%s\n", mime ? PLAIN : "awk executable file");
-	else if (strcmp("sed", p) == 0)
-		print("%s\n", mime ? PLAIN : "sed executable file");
-	else if (strcmp("perl", p) == 0)
-		print("%s\n", mime ? PLAIN : "perl executable file");
-	else
-		print("%s\n", mime ? PLAIN : "unknown executable file");
-	return 1;
-}
-
-/* from tar.c */
-enum { NAMSIZ = 100, TBLOCK = 512 };
-
-union	hblock
-{
-	char	dummy[TBLOCK];
-	struct	header
-	{
-		char	name[NAMSIZ];
-		char	mode[8];
-		char	uid[8];
-		char	gid[8];
-		char	size[12];
-		char	mtime[12];
-		char	chksum[8];
-		char	linkflag;
-		char	linkname[NAMSIZ];
-		/* rest are defined by POSIX's ustar format; see p1003.2b */
-		char	magic[6];	/* "ustar" */
-		char	version[2];
-		char	uname[32];
-		char	gname[32];
-		char	devmajor[8];
-		char	devminor[8];
-		char	prefix[155];  /* if non-null, path = prefix "/" name */
-	} dbuf;
-};
-
-int
-checksum(union hblock *hp)
-{
-	int i;
-	char *cp;
-	struct header *hdr = &hp->dbuf;
-
-	for (cp = hdr->chksum; cp < &hdr->chksum[sizeof hdr->chksum]; cp++)
-		*cp = ' ';
-	i = 0;
-	for (cp = hp->dummy; cp < &hp->dummy[TBLOCK]; cp++)
-		i += *cp & 0xff;
-	return i;
-}
-
-int
-istar(void)
-{
-	int chksum;
-	char tblock[TBLOCK];
-	union hblock *hp = (union hblock *)tblock;
-	struct header *hdr = &hp->dbuf;
-
-	seek(fd, 0, 0);		/* reposition to start of file */
-	if (readn(fd, tblock, sizeof tblock) != sizeof tblock)
-		return 0;
-	chksum = strtol(hdr->chksum, 0, 8);
-	if (hdr->name[0] != '\0' && checksum(hp) == chksum) {
-		if (strcmp(hdr->magic, "ustar") == 0)
-			print(mime? "application/x-ustar\n": "posix tar archive\n");
-		else
-			print(mime? "application/x-tar\n": "tar archive\n");
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * initial words to classify file
- */
-struct	FILE_STRING
-{
-	char 	*key;
-	char	*filetype;
-	int	length;
-	char	*mime;
-} file_string[] =
-{
-	"\x1f\x9d",		"compressed",			2,	"application/x-compress",
-	"\x1f\x8b",		"gzip compressed",		2,	"application/x-gzip",
-	"BZh",			"bzip2 compressed",		3,	"application/x-bzip2",
-	"!<arch>\n__.SYMDEF",	"archive random library",	16,	OCTET,
-	"!<arch>\n",		"archive",			8,	OCTET,
-	"070707",		"cpio archive - ascii header",	6,	OCTET,
-	"QFI\xfb",		"QCOW disk image",		4,	OCTET,
-	"%!",			"postscript",			2,	"application/postscript",
-	"\004%!",		"postscript",			3,	"application/postscript",
-	"x T post",		"troff output for post",	8,	"application/troff",
-	"x T Latin1",		"troff output for Latin1",	10,	"application/troff",
-	"x T utf",		"troff output for UTF",		7,	"application/troff",
-	"x T 202",		"troff output for 202",		7,	"application/troff",
-	"x T aps",		"troff output for aps",		7,	"application/troff",
-	"x T ",			"troff output",			4,	"application/troff",
-	"GIF",			"GIF image", 			3,	"image/gif",
-	"\0PC Research, Inc\0",	"ghostscript fax file",		18,	"application/ghostscript",
-	"%PDF",			"PDF",				4,	"application/pdf",
-	"<!DOCTYPE",		"HTML file",			9,	"text/html",
-	"<!doctype",		"HTML file",			9,	"text/html",
-	"<!--",			"XML file",			4,	"text/xml",
-	"<html>",		"HTML file",			6,	"text/html",
-	"<HTML>",		"HTML file",			6,	"text/html",
-	"<?xml",		"HTML file",			5,	"text/html",
-	"\111\111\052\000",	"tiff",				4,	"image/tiff",
-	"\115\115\000\052",	"tiff",				4,	"image/tiff",
-	"\377\330\377\340",	"jpeg",				4,	"image/jpeg",
-	"\377\330\377\341",	"jpeg",				4,	"image/jpeg",
-	"\377\330\377\333",	"jpeg",				4,	"image/jpeg",
-	"\xff\xd8",		"jpeg",				2,	"image/jpeg",
-	"BM",			"bmp",				2,	"image/bmp", 
-	"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1",	"microsoft office document",	8,	"application/doc",
-	"<MakerFile ",		"FrameMaker file",		11,	"application/framemaker",
-	"\033E\033",		"HP PCL printer data",		3,	OCTET,
-	"\033&",		"HP PCL printer data",		2,	OCTET,
-	"\033%-12345X",		"HPJCL file",		9,	"application/hpjcl",
-	"\033Lua",		"Lua bytecode",		4,	OCTET,
-	"ID3",			"mp3 audio with id3",	3,	"audio/mpeg",
-	".snd",			"sun audio",		4,	"audio/basic",
-	"\211PNG",		"PNG image",		4,	"image/png",
-	"P1\n",			"ppm",			3,	"image/ppm",
-	"P2\n",			"ppm",			3,	"image/ppm",
-	"P3\n",			"ppm",			3,	"image/ppm",
-	"P4\n",			"ppm",			3,	"image/ppm",
-	"P5\n",			"ppm",			3,	"image/ppm",
-	"P6\n",			"ppm",			3,	"image/ppm",
-	"/* XPM */\n",	"xbm",				10,	"image/xbm",
-	".HTML ",		"troff -ms input",	6,	"text/troff",
-	".LP",			"troff -ms input",	3,	"text/troff",
-	".ND",			"troff -ms input",	3,	"text/troff",
-	".PP",			"troff -ms input",	3,	"text/troff",
-	".TL",			"troff -ms input",	3,	"text/troff",
-	".TR",			"troff -ms input",	3,	"text/troff",
-	".TH",			"manual page",		3,	"text/troff",
-	".\\\"",		"troff input",		3,	"text/troff",
-	".de",			"troff input",		3,	"text/troff",
-	".if",			"troff input",		3,	"text/troff",
-	".nr",			"troff input",		3,	"text/troff",
-	".tr",			"troff input",		3,	"text/troff",
-	"vac:",			"venti score",		4,	PLAIN,
-	"-----BEGIN CERTIFICATE-----\n",
-				"pem certificate",	-1,	PLAIN,
-	"-----BEGIN TRUSTED CERTIFICATE-----\n",
-				"pem trusted certificate", -1,	PLAIN,
-	"-----BEGIN X509 CERTIFICATE-----\n",
-				"pem x.509 certificate", -1,	PLAIN,
-	"subject=/C=",		"pem certificate with header", -1, PLAIN,
-	"process snapshot ",	"process snapshot",	-1,	"application/snapfs",
-	"d8:announce",		"torrent file",		11,	"application/x-bittorrent",
-	"[playlist]",		"playlist",		10,	"application/x-scpls",
-	"#EXTM3U",		"playlist",		7,	"audio/x-mpegurl",
-	"BEGIN:VCARD\r\n",	"vCard",		13,	"text/directory;profile=vcard",
-	"BEGIN:VCARD\n",	"vCard",		12,	"text/directory;profile=vcard",
-	"AT&T",			"DjVu document",	4,	"image/vnd.djvu",
-	"Extended module: ",	"XM audio",		17,	"audio/xm",
-	"MThd",			"midi audio",		4,	"audio/midi",
-	"MUS\x1a",		"mus audio",		4,	"audio/mus",
-	"Creative Voice File\x1a",	"voc audio",	20,	"audio/x-voc",
-	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\x00\x00\x00\xbb\x11\x22\x00\x44\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\xaa\x99\x55\x66", "Xilinx bitstream (not byteswappped)", 52, OCTET,
-	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\xbb\x00\x00\x00\x44\x00\x22\x11\xff\xff\xff\xff\xff\xff\xff\xff"
-	"\x66\x55\x99\xaa", "Xilinx bitstream (byteswappped)", 52, OCTET,
-	0,0,0,0
-};
-
-int
-istring(void)
-{
-	int i, l;
-	struct FILE_STRING *p;
-
-	for(p = file_string; p->key; p++) {
-		l = p->length;
-		if(l == -1)
-			l = strlen(p->key);
-		if(nbuf >= l && memcmp(buf, p->key, l) == 0) {
-			print("%s\n", mime ? p->mime : p->filetype);
-			return 1;
-		}
-	}
-	if(strncmp((char*)buf, "TYPE=", 5) == 0) {	/* td */
-		for(i = 5; i < nbuf; i++)
-			if(buf[i] == '\n')
-				break;
-		if(mime)
-			print("%s\n", OCTET);
-		else
-			print("%.*s picture\n", utfnlen((char*)buf+5, i-5), (char*)buf+5);
-		return 1;
-	}
-	return 0;
-}
-
-struct offstr
-{
-	ulong	off;
-	struct FILE_STRING;
-} offstrs[] = {
-	32*1024, "\001CD001\001",	"ISO9660 CD image",	7,	"application/x-iso9660-image",
-	32*4, "DICM",	"DICOM medical imaging data",	4,	"application/dicom",
-	1080, "M.K.",	"Amiga module",	4,	"audio/mod",
-	0, 0, 0, 0, 0
-};
-
-int
-isoffstr(void)
-{
-	int n;
-	char buf[256];
-	struct offstr *p;
-
-	for(p = offstrs; p->key; p++) {
-		seek(fd, p->off, 0);
-		n = p->length;
-		if (n > sizeof buf)
-			n = sizeof buf;
-		if (readn(fd, buf, n) != n)
-			continue;
-		if(memcmp(buf, p->key, n) == 0) {
-			print("%s\n", mime ? p->mime : p->filetype);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-int
-iff(void)
-{
-	if (strncmp((char*)buf, "FORM", 4) == 0 &&
-	    strncmp((char*)buf+8, "AIFF", 4) == 0) {
-		print("%s\n", mime? "audio/x-aiff": "aiff audio");
-		return 1;
-	}
-	if (strncmp((char*)buf, "RIFF", 4) == 0) {
-		if (strncmp((char*)buf+8, "WAVE", 4) == 0)
-			print("%s\n", mime? "audio/wave": "wave audio");
-		else if (strncmp((char*)buf+8, "AVI ", 4) == 0)
-			print("%s\n", mime? "video/avi": "avi video");
-		else if (strncmp((char*)buf+8, "WEBP", 4) == 0)
-			print("%s\n", mime? "image/webp": "webp image");
-		else
-			print("%s\n", mime? OCTET : "riff file");
-		return 1;
-	}
-	return 0;
-}
-
-char*	html_string[] = {
-	"blockquote",
-	"!DOCTYPE", "![CDATA[", "basefont", "frameset", "noframes", "textarea",
-	"caption",
-	"button", "center", "iframe", "object", "option", "script",
-	"select", "strong",
-	"blink", "embed", "frame", "input", "label", "param", "small",
-	"style", "table", "tbody", "tfoot", "thead", "title",
-	"?xml", "body", "code", "font", "form", "head", "html",
-	"link", "menu", "meta", "span",
-	"!--", "big", "dir", "div", "img", "pre", "sub", "sup",
-	"br", "dd", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5",
-	"h6", "hr", "li", "ol", "td", "th", "tr", "tt", "ul",
-	"a", "b", "i", "p", "q", "u",
-	0,
-};
-
-int
-isudiff(void)
-{
-	char *p;
-
-	p = (char*)buf;
-	if((p = strstr(p, "diff")) != nil)
-	if((p = strchr(p, '\n')) != nil)
-	if(strncmp(++p, "--- ", 4) == 0)
-	if((p = strchr(p, '\n')) != nil)
-	if(strncmp(++p, "+++ ", 4) == 0)
-	if((p = strchr(p, '\n')) != nil)
-	if(strncmp(++p, "@@ ", 3) == 0){
-		print("%s\n", mime ? "text/plain" : "unified diff output");
-		return 1;
-	}
-	return 0;
-}
-
-int
-ishtml(void)
-{
-	int i, n, count;
-	uchar *p;
-
-	count = 0;
-	p = buf;
-	for(;;) {
-		while(p < buf+nbuf && *p != '<')
-			p++;
-		p++;
-		if (p >= buf+nbuf)
-			break;
-		if(*p == '/')
-			p++;
-		if(p >= buf+nbuf)
-			break;
-		for(i = 0; html_string[i]; i++){
-			n = strlen(html_string[i]);
-			if(p + n > buf+nbuf)
-				continue;
-			if(cistrncmp(html_string[i], (char*)p, n) == 0) {
-				p += n;
-				if(p < buf+nbuf && strchr("\t\r\n />", *p)){
-					if(++count > 2) {
-						print("%s\n", mime ? "text/html" : "HTML file");
-						return 1;
-					}
-				}
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-char*	rfc822_string[] =
-{
-	"from:",
-	"date:",
-	"to:",
-	"subject:",
-	"received:",
-	"reply to:",
-	"sender:",
-	0,
-};
-
-int
-isrfc822(void)
-{
-
-	char *p, *q, *r;
-	int i, count;
-
-	count = 0;
-	p = (char*)buf;
-	for(;;) {
-		q = strchr(p, '\n');
-		if(q == nil)
-			break;
-		*q = 0;
-		if(p == (char*)buf && strncmp(p, "From ", 5) == 0 && strstr(p, " remote from ")){
-			count++;
-			*q = '\n';
-			p = q+1;
-			continue;
-		}
-		*q = '\n';
-		if(*p != '\t' && *p != ' '){
-			r = strchr(p, ':');
-			if(r == 0 || r > q)
-				break;
-			for(i = 0; rfc822_string[i]; i++) {
-				if(cistrncmp(p, rfc822_string[i], strlen(rfc822_string[i])) == 0){
-					count++;
-					break;
-				}
-			}
-		}
-		p = q+1;
-	}
-	if(count >= 3){
-		print("%s\n", mime ? "message/rfc822" : "email file");
-		return 1;
-	}
-	return 0;
-}
-
-int
-ismbox(void)
-{
-	char *p, *q;
-
-	p = (char*)buf;
-	q = strchr(p, '\n');
-	if(q == nil)
-		return 0;
-	*q = 0;
-	if(strncmp(p, "From ", 5) == 0 && strstr(p, " remote from ") == nil){
-		print("%s\n", mime ? "application/mbox" : "mail box");
-		return 1;
-	}
-	*q = '\n';
-	return 0;
-}
-
-int
-iscint(void)
-{
-	int type;
-	char *name;
-	Biobuf b;
-
-	if(Binit(&b, fd, OREAD) == Beof)
-		return 0;
-	seek(fd, 0, 0);
-	type = objtype(&b, &name);
-	if(type < 0)
-		return 0;
-	if(mime)
-		print("%s\n", OCTET);
-	else
-		print("%s intermediate\n", name);
-	return 1;
-}
-
-int
-isc(void)
-{
-	int n;
-
-	n = wfreq[I1];
-	/*
-	 * includes
-	 */
-	if(n >= 2 && wfreq[I2] >= n && wfreq[I3] >= n && cfreq['.'] >= n)
-		goto yes;
-	if(n >= 1 && wfreq[Alword] >= n && wfreq[I3] >= n && cfreq['.'] >= n)
-		goto yes;
-	/*
-	 * declarations
-	 */
-	if(wfreq[Cword] >= 5 && cfreq[';'] >= 5)
-		goto yes;
-	/*
-	 * assignments
-	 */
-	if(cfreq[';'] >= 10 && cfreq['='] >= 10 && wfreq[Cword] >= 1)
-		goto yes;
-	return 0;
-
-yes:
-	if(mime){
-		print("%s\n", PLAIN);
-		return 1;
-	}
-	if(wfreq[Alword] > 0)
-		print("alef program\n");
-	else
-		print("c program\n");
-	return 1;
-}
-
-int
-islimbo(void)
-{
-	/*
-	 * includes
-	 */
-	if(wfreq[Lword] < 4)
-		return 0;
-	print("%s\n", mime ? PLAIN : "limbo program");
-	return 1;
-}
-
-int
-isas(void)
-{
-	/*
-	 * includes
-	 */
-	if(wfreq[Aword] < 2)
-		return 0;
-	print("%s\n", mime ? PLAIN : "as program");
-	return 1;
-}
-
-int
-istga(void)
-{
-	uchar *p;
-
-	p = buf;
-	if(nbuf < 18)
-		return 0;
-	if((p[12] | p[13]<<8) == 0)	/* width */
-		return 0;
-	if((p[14] | p[15]<<8) == 0)	/* height */
-		return 0;
-	if(p[16] != 8 && p[16] != 15 && p[16] != 16 && p[16] != 24 && p[16] != 32)	/* bpp */
-		return 0;
-	if(((p[2]|(1<<3)) & (~3)) != (1<<3))	/* rle flag */
-		return 0;
-	if(p[1] == 0){	/* non color-mapped */
-		if((p[2]&3) != 2 && (p[2]&3) != 3)	
-			return 0;
-		if((p[5] | p[6]<<8) != 0)	/* palette length */
-			return 0;
-	} else
-	if(p[1] == 1){	/* color-mapped */
-		if((p[2]&3) != 1 || p[7] == 0)	
-			return 0;
-		if((p[5] | p[6]<<8) == 0)	/* palette length */
-			return 0;
-	} else
-		return 0;
-	print("%s\n", mime ? "image/tga" : "targa image");
-	return 1;
-}
-
-int
-ismp3(void)
-{
-	uchar *p, *e;
-
-	p = buf;
-	e = p + nbuf-1;
-	while((p < e) && (p = memchr(p, 0xFF, e - p))){
-		if((p[1] & 0xFE) == 0xFA){
-			print("%s\n", mime ? "audio/mpeg" : "mp3 audio");
-			return 1;
-		}
-		p++;
-	}
-	return 0;
-}
-
-int
-ismp4(void)
-{
-	if(nbuf <= 12)
-		return 0;
-	if(memcmp(&buf[4], "ftyp", 4) != 0)
-		return 0;
-	if(memcmp(&buf[8], "isom", 4) == 0 || memcmp(&buf[8], "mp4", 3) == 0){
-		print("%s\n", mime ? "video/mp4" : "mp4 video");
-		return 1;
-	}
-	if(memcmp(&buf[8], "M4A ", 4) == 0){
-		print("%s\n", mime ? "audio/m4a" : "m4a audio");
-		return 1;
-	}
-	return 0;
-}
-
-int
-isoggvorbis(void)
-{
-	if(memcmp(&buf[0], "OggS", 4) != 0)
-		return 0;
-	if(memcmp(&buf[29], "vorbis", 6) != 0)
-		return 0;
-	print("%s\n", mime ? "audio/ogg;codecs=vorbis" : "ogg audio");
-	return 1;
-}
-
-int
-isoggopus(void)
-{
-	if(memcmp(&buf[0], "OggS", 4) != 0)
-		return 0;
-	if(memcmp(&buf[28], "OpusHead", 8) != 0)
-		return 0;
-	print("%s\n", mime ? "audio/ogg;codecs=opus" : "ogg audio");
-	return 1;
-}
-
-/*
- * low entropy means encrypted
- */
-int
-ismung(void)
-{
-	int i, bucket[8];
-	float cs;
-
-	if(nbuf < 64)
-		return 0;
-	memset(bucket, 0, sizeof(bucket));
-	for(i=nbuf-64; i<nbuf; i++)
-		bucket[(buf[i]>>5)&07] += 1;
-
-	cs = 0.;
-	for(i=0; i<8; i++)
-		cs += (bucket[i]-8)*(bucket[i]-8);
-	cs /= 8.;
-	if(cs <= 24.322) {
-		if(buf[0]==0x1f && buf[1]==0x9d)
-			print("%s\n", mime ? "application/x-compress" : "compressed");
-		else
-		if(buf[0]==0x1f && buf[1]==0x8b)
-			print("%s\n", mime ? "application/x-gzip" : "gzip compressed");
-		else
-		if(buf[0]=='B' && buf[1]=='Z' && buf[2]=='h')
-			print("%s\n", mime ? "application/x-bzip2" : "bzip2 compressed");
-		else
-		if(buf[0]==0x78 && buf[1]==0x9c)
-			print("%s\n", mime ? "application/x-deflate" : "zlib compressed");
-		else
-			print("%s\n", mime ? OCTET : "encrypted");
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * english by punctuation and frequencies
- */
-int
-isenglish(void)
-{
-	int vow, comm, rare, badpun, punct;
-	char *p;
-
-	if(guess != Fascii && guess != Feascii)
-		return 0;
-	badpun = 0;
-	punct = 0;
-	for(p = (char *)buf; p < (char *)buf+nbuf-1; p++)
-		switch(*p) {
-		case '.':
-		case ',':
-		case ')':
-		case '%':
-		case ';':
-		case ':':
-		case '?':
-			punct++;
-			if(p[1] != ' ' && p[1] != '\n')
-				badpun++;
-		}
-	if(badpun*5 > punct)
-		return 0;
-	if(cfreq['>']+cfreq['<']+cfreq['/'] > cfreq['e'])	/* shell file test */
-		return 0;
-	if(2*cfreq[';'] > cfreq['e'])
-		return 0;
-
-	vow = 0;
-	for(p="AEIOU"; *p; p++) {
-		vow += cfreq[*p];
-		vow += cfreq[tolower(*p)];
-	}
-	comm = 0;
-	for(p="ETAION"; *p; p++) {
-		comm += cfreq[*p];
-		comm += cfreq[tolower(*p)];
-	}
-	rare = 0;
-	for(p="VJKQXZ"; *p; p++) {
-		rare += cfreq[*p];
-		rare += cfreq[tolower(*p)];
-	}
-	if(vow*5 >= nbuf-cfreq[' '] && comm >= 10*rare) {
-		print("%s\n", mime ? PLAIN : "English text");
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * pick up a number with
- * syntax _*[0-9]+_
- */
-#define	P9BITLEN	12
-int
-p9bitnum(char *s, int *v)
-{
-	char *es;
-
-	if(s[P9BITLEN-1] != ' ')
-		return -1;
-	s[P9BITLEN-1] = '\0';
-	*v = strtol(s, &es, 10);
-	s[P9BITLEN-1] = ' ';
-	if(es != &s[P9BITLEN-1])
-		return -1;
-	return 0;
-}
-
-int
-depthof(char *s, int *newp)
-{
-	char *es;
-	int d;
-
-	*newp = 0;
-	es = s+12;
-	while(s<es && *s==' ')
-		s++;
-	if(s == es)
-		return -1;
-	if('0'<=*s && *s<='9')
-		return 1<<strtol(s, nil, 0);
-
-	*newp = 1;
-	d = 0;
-	while(s<es && *s!=' '){
-		if(strchr("rgbkamx", *s) == nil)
-			return -1;
-		s++;
-		if('0'<=*s && *s<='9')
-			d += strtoul(s, &s, 10);
-		else
-			return -1;
-	}
-
-	if(d % 8 == 0 || 8 % d == 0)
-		return d;
-	else
-		return -1;
-}
-
-int
-isp9bit(void)
-{
-	int dep, lox, loy, hix, hiy, px, new, cmpr;
-	long len;
-	char *newlabel;
-	uchar *cp;
-
-	cp = buf;
-	cmpr = 0;
-	if(memcmp(cp, "compressed\n", 11) == 0) {
-		cmpr = 1;
-		cp = buf + 11;
-	}
-
-	if((dep = depthof((char*)cp + 0*P9BITLEN, &new)) < 0)
-		return 0;
-	newlabel = new ? "" : "old ";
-	if(p9bitnum((char*)cp + 1*P9BITLEN, &lox) < 0)
-		return 0;
-	if(p9bitnum((char*)cp + 2*P9BITLEN, &loy) < 0)
-		return 0;
-	if(p9bitnum((char*)cp + 3*P9BITLEN, &hix) < 0)
-		return 0;
-	if(p9bitnum((char*)cp + 4*P9BITLEN, &hiy) < 0)
-		return 0;
-
-	hix -= lox;
-	hiy -= loy;
-	if(hix <= 0 || hiy <= 0)
-		return 0;
-
-	if(dep < 8){
-		px = 8/dep;		/* pixels per byte */
-		/* set l to number of bytes of data per scan line */
-		len = (hix+px-1)/px;
-	}else
-		len = hix*dep/8;
-	len *= hiy;			/* col length */
-	len += 5 * P9BITLEN;		/* size of initial ascii */
-
-	/*
-	 * for compressed images, don't look any further. otherwise:
-	 * for image file, length is non-zero and must match calculation above.
-	 * for /dev/window and /dev/screen the length is always zero.
-	 * for subfont, the subfont header should follow immediately.
-	 */
-	if (cmpr) {
-		print(mime ? "image/p9bit\n" : "Compressed %splan 9 image or subfont, depth %d, size %dx%d\n",
-			newlabel, dep, hix, hiy);
-		return 1;
-	}
-	/*
-	 * mbuf->length == 0 probably indicates reading a pipe.
-	 * Ghostscript sometimes produces a little extra on the end.
-	 */
-	if (len != 0 && (mbuf->length == 0 || mbuf->length == len ||
-	    mbuf->length > len && mbuf->length < len+P9BITLEN)) {
-		print(mime ? "image/p9bit\n" : "%splan 9 image, depth %d, size %dx%d\n",
-			newlabel, dep, hix, hiy);
-		return 1;
-	}
-	if (p9subfont(buf+len)) {
-		print(mime ? "image/p9bit\n" : "%ssubfont file, depth %d, size %dx%d\n",
-			newlabel, dep, hix, hiy);
-		return 1;
-	}
-	return 0;
-}
-
-int
-p9subfont(uchar *p)
-{
-	int n, h, a;
-
-	/* if image too big, assume it's a subfont */
-	if (p+3*P9BITLEN > buf+sizeof(buf))
-		return 1;
-
-	if (p9bitnum((char*)p + 0*P9BITLEN, &n) < 0)	/* char count */
-		return 0;
-	if (p9bitnum((char*)p + 1*P9BITLEN, &h) < 0)	/* height */
-		return 0;
-	if (p9bitnum((char*)p + 2*P9BITLEN, &a) < 0)	/* ascent */
-		return 0;
-	if(n > 0 && h > 0 && a >= 0)
-		return 1;
-	return 0;
-}
-
-#define	WHITESPACE(c)		((c) == ' ' || (c) == '\t' || (c) == '\n')
-
-int
-isp9font(void)
-{
-	uchar *cp, *p;
-	int i, n;
-	char pathname[1024];
-
-	cp = buf;
-	if (!getfontnum(cp, &cp))	/* height */
-		return 0;
-	if (!getfontnum(cp, &cp))	/* ascent */
-		return 0;
-	for (i = 0; cp=(uchar*)strchr((char*)cp, '\n'); i++) {
-		if (!getfontnum(cp, &cp))	/* min */
-			break;
-		if (!getfontnum(cp, &cp))	/* max */
-			return 0;
-		getfontnum(cp, &cp);	/* optional offset */
-		while (WHITESPACE(*cp))
-			cp++;
-		for (p = cp; *cp && !WHITESPACE(*cp); cp++)
-				;
-			/* construct a path name, if needed */
-		n = 0;
-		if (*p != '/' && slash) {
-			n = slash-fname+1;
-			if (n < sizeof(pathname))
-				memcpy(pathname, fname, n);
-			else n = 0;
-		}
-		if (n+cp-p+4 < sizeof(pathname)) {
-			memcpy(pathname+n, p, cp-p);
-			n += cp-p;
-			pathname[n] = 0;
-			if (access(pathname, AEXIST) < 0) {
-				strcpy(pathname+n, ".0");
-				if (access(pathname, AEXIST) < 0)
-					return 0;
-			}
-		}
-	}
-	if (i) {
-		print("%s\n", mime ? PLAIN : "font file");
-		return 1;
-	}
-	return 0;
-}
-
-int
-getfontnum(uchar *cp, uchar **rp)
-{
-	while (WHITESPACE(*cp))		/* extract ulong delimited by whitespace */
-		cp++;
-	if (*cp < '0' || *cp > '9')
-		return 0;
-	strtoul((char *)cp, (char **)rp, 0);
-	if (!WHITESPACE(**rp)) {
-		*rp = cp;
-		return 0;
-	}
-	return 1;
-}
-
-int
-isrtf(void)
-{
-	if(strstr((char *)buf, "\\rtf1")){
-		print(mime ? "application/rtf\n" : "rich text format\n");
-		return 1;
-	}
-	return 0;
-}
-
-int
-ismsdos(void)
-{
-	if (buf[0] == 0x4d && buf[1] == 0x5a){
-		print(mime ? "application/x-msdownload\n" : "MSDOS executable\n");
-		return 1;
-	}
-	return 0;
-}
-
-int
-isicocur(void)
-{
-	if(buf[0] || buf[1] || buf[3] || buf[9])
-		return 0;
-	if(buf[4] == 0x00 && buf[5] == 0x00)
-		return 0;
-	switch(buf[2]){
-	case 1:
-		print(mime ? "image/x-icon\n" : "Microsoft icon file\n");
-		return 1;
-	case 2:
-		print(mime ? "image/x-icon\n" : "Microsoft cursor file\n");
-		return 1;
-	}
-	return 0;
-}
-
-int
-iself(void)
-{
-	static char *cpu[] = {		/* NB: incomplete and arbitary list */
-	[1]	"WE32100",
-	[2]	"SPARC",
-	[3]	"i386",
-	[4]	"M68000",
-	[5]	"M88000",
-	[6]	"i486",
-	[7]	"i860",
-	[8]	"R3000",
-	[9]	"S370",
-	[10]	"R4000",
-	[15]	"HP-PA",
-	[18]	"sparc v8+",
-	[19]	"i960",
-	[20]	"PPC-32",
-	[21]	"PPC-64",
-	[40]	"ARM",
-	[41]	"Alpha",
-	[43]	"sparc v9",
-	[50]	"IA-64",
-	[62]	"AMD64",
-	[75]	"VAX",
-	};
-	static char *type[] = {
-	[1]	"relocatable object",
-	[2]	"executable",
-	[3]	"shared library",
-	[4]	"core dump",
-	};
-
-	if (memcmp(buf, "\x7fELF", 4) == 0){
-		if (!mime){
-			int isdifend = 0;
-			int n = (buf[19] << 8) | buf[18];
-			char *p = "unknown";
-			char *t = "unknown";
-
-			if (n > 0 && n < nelem(cpu) && cpu[n])
-				p = cpu[n];
-			else {
-				/* try the other byte order */
-				isdifend = 1;
-				n = (buf[18] << 8) | buf[19];
-				if (n > 0 && n < nelem(cpu) && cpu[n])
-					p = cpu[n];
-			}
-			if(isdifend)
-				n = (buf[16]<< 8) | buf[17];
-			else
-				n = (buf[17]<< 8) | buf[16];
-
-			if(n>0 && n < nelem(type) && type[n])
-				t = type[n];
-			print("%s ELF %s\n", p, t);
-		}
-		else
-			print("application/x-elf-executable\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-isface(void)
-{
-	int i, j, ldepth, l;
-	char *p;
-
-	ldepth = -1;
-	for(j = 0; j < 3; j++){
-		for(p = (char*)buf, i=0; i<3; i++){
-			if(p[0] != '0' || p[1] != 'x')
-				return 0;
-			if(buf[2+8] == ',')
-				l = 2;
-			else if(buf[2+4] == ',')
-				l = 1;
-			else
-				return 0;
-			if(ldepth == -1)
-				ldepth = l;
-			if(l != ldepth)
-				return 0;
-			strtoul(p, &p, 16);
-			if(*p++ != ',')
-				return 0;
-			while(*p == ' ' || *p == '\t')
-				p++;
-		}
-		if (*p++ != '\n')
-			return 0;
-	}
-
-	if(mime)
-		print("application/x-face\n");
-	else
-		print("face image depth %d\n", ldepth);
-	return 1;
-}
--- a/sys/src/cmd/troff/tdef.h
+++ /dev/null
@@ -1,670 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <ctype.h>
-#include <string.h>
-
-#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 (12*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	(64*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<<SHORT))
-
-
-extern	int	Inch, Hor, Vert, Unitwidth;
-
-struct	Spnames
-{
-	int	*n;
-	char	*v;
-};
-
-extern	Spnames	spnames[];
-
-/*
-	String and macro definitions are stored conceptually in a giant array
-	indexed by type Offset.  In olden times, this array was real, and thus
-	both huge and limited in size, leading to the "Out of temp file space"
-	error.  In this version, the array is represented by a list of blocks,
-	pointed to by blist[].bp.  Each block is of size BLK Tchars, and BLK
-	MUST be a power of 2 for the macros below to work.
-	
-	The blocks associated with a particular string or macro are chained
-	together in the array blist[].  Each blist[i].nextoff contains the
-	Offset associated with the next block in the giant array, or -1 if
-	this is the last block in the chain.  If .nextoff is 0, the block is
-	free.
-	
-	To find the right index in blist for an Offset, divide by BLK.
-*/
-
-#define	NBLIST	2048	/* starting number of blocks in all definitions */
-
-#define	BLK	128	/* number of Tchars in a block; must be 2^N with defns below */
-
-#define	rbf0(o)		(blist[bindex(o)].bp[boffset(o)])
-#define	bindex(o)	((o) / BLK)
-#define	boffset(o)	((o) & (BLK-1))
-#define	pastend(o)	(((o) & (BLK-1)) == 0)
-/* #define	incoff(o)	( (++o & (BLK-1)) ? o : blist[bindex(o-1)].nextoff ) */
-#define	incoff(o)	( (((o)+1) & (BLK-1)) ? o+1 : blist[bindex(o)].nextoff )
-
-#define	skipline(f)	while (getc(f) != '\n')
-#define is(s)		(strcmp(cmd, s) == 0)
-#define	eq(s1, s2)	(strcmp(s1, s2) == 0)
-
-
-typedef	unsigned long	Offset;		/* an offset in macro/string storage */
-
-struct Blockp {		/* info about a block: */
-	Tchar	*bp;		/* the data */
-	Offset	nextoff;	/* offset of next block in a chain */
-};
-
-extern	Blockp	*blist;
-
-#define	RD_OFFSET	(1 * BLK)	/* .rd command uses block 1 */
-
-struct Diver {		/* diversion */
-	Offset	op;
-	int	dnl;
-	int	dimac;
-	int	ditrap;
-	int	ditf;
-	int	alss;
-	int	blss;
-	int	nls;
-	int	mkline;
-	int	maxl;
-	int	hnl;
-	int	curd;
-};
-
-struct Stack {		/* stack frame */
-	int	nargs;
-	Stack	*pframe;
-	Offset	pip;
-	int	pnchar;
-	Tchar	prchar;
-	int	ppendt;
-	Tchar	pch;
-	Tchar	*lastpbp;
-	int	mname;
-};
-
-extern	Stack	s;
-
-struct Divsiz {
-	int dix;
-	int diy;
-};
-
-struct Contab {		/* command or macro */
-	unsigned int	rq;
-	Contab	*link;
-	void	(*f)(void);
-	Offset	mx;
-	Offset	emx;
-	Divsiz	*divsiz;
-};
-
-#define	C(a,b)	{a, 0, b, 0, 0}		/* how to initialize a contab entry */
-
-extern	Contab	contab[NM];
-
-struct Numtab {	/* number registers */
-	unsigned int	r;		/* name */
-	int	val;
-	short	fmt;
-	short	inc;
-	Numtab	*link;
-};
-
-extern	Numtab	numtab[NN];
-
-#define	PN	0
-#define	NL	1
-#define	YR	2
-#define	HP	3
-#define	CT	4
-#define	DN	5
-#define	MO	6
-#define	DY	7
-#define	DW	8
-#define	LN	9
-#define	DL	10
-#define	ST	11
-#define	SB	12
-#define	CD	13
-#define	PID	14
-
-struct	Wcache {	/* width cache, indexed by character */
-	short	fontpts;
-	short	width;
-};
-
-struct	Tbuf {		/* growable Tchar buffer */
-	Tchar *_bufp;
-	unsigned int _size;
-};
-
-/* the infamous environment block */
-
-#define	ics	envp->_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 */
-};