/*
 * Adobe type1 compiler
 * 
 * Author:
 *	Per Lindqvist, pgd@compuram.bbt.se
 */
#include <stdio.h>
#include <ctype.h>

FILE *ifp, *ofp;
int lenIV = 4;

main(argc, argv)
	int argc; char **argv;
{
	register int c;
	char line[100];
	int i, j, k;
	char *cp;

	argc--; argv++;		/* Skip program name */
	while (argc >= 0 && **argv == '-') {
		switch ((*argv)[1]) {
		default:
			fprintf(stderr, "Illegal switch %s\n", *argv);
			exit(1);
		}
		argc--;
		argv++;
	}
	if (argc < 1) {
		fprintf(stderr, "Usage: decomp infile {outfile}\n");
		exit(1);
	}
	ifp = fopen(argv[0], "r");
	if (ifp == NULL) {
		perror(argv[0]);
		exit(1);
	}
	if (argc > 1) {
		if ((ofp = fopen(argv[1], "w")) == NULL) {
			perror(argv[1]);
			exit(1);
		}
	} else
		ofp = stdout;
	
	/*
	 * Strategy is very simple.
	 * Copy everything, except for things in brackets
	 * which gets compiled
	 */
	while ((c = getc(ifp)) != -1) {
		putc(c, ofp);
		if (c == '<') {
			compile();
			putc('>', ofp);
		}
	}
	fclose(ofp);
	exit(0);
}

char *cmdtab[32] = {
	"C00",
	"Hstem",
	"C02",
	"Vstem",			/* 3 */
	"Vmoveto",			/* 4 */
	"Rlineto",			/* 5 */
	"Hlineto",			/* 6 */
	"Vlineto",			/* 7 */
	"Rrcurveto",			/* 8 */
	"Closepath",			/* 9 */
	"Callsubr",			/* 10 */
	"Return",			/* 11 */
	"Escape",			/* 12 */
	"Hsbw",				/* 13 */
	"Endchar",			/* 14 */
	"C15",
	"C16",
	"C17",
	"C18",
	"C19",
	"C20",
	"Rmoveto",			/* 21 */
	"Hmoveto",			/* 22 */
	"C23",
	"C24",
	"C25",
	"C26",
	"C27",
	"C28",
	"C29",
	"Vhcurveto",			/* 30 */
	"Hvcurveto"			/* 31 */
	};

/*
 * Compile to hex
 */
compile()
{
	register int v;
	int l;
	int i, c;
	char ident[40];
	char *idp;
	long n;

	icencrypt();
	for (i = 0; i < lenIV; i++)
		putenc(0);
	c = getc(ifp);
	while (c != '>') {
		if (isspace(c)) {
			do c = getc(ifp); while (isspace(c));
		} else if (isdigit(c) || c == '-') {
			idp = ident;
			do {
				*idp++ = c;
				c = getc(ifp);
			} while (isdigit(c));
			*idp = '\0';
			n = atoi(ident);
			if (n >= -107 && n <= 107)
				putenc(n + 139);
			else if (n >= 108 && n <= 1131) {
				n -= 108;
				putenc((n >> 8) + 247);
				putenc(n & 0xff);
			} else if (n >= -1131 && n <= -108) {
				n = -(n - -108);
				putenc((n >> 8) + 251);
				putenc(n & 0xff);
			} else {
				putenc(255);
				putenc((n & 0xff000000) >> 24);
				putenc((n & 0x00ff0000) >> 16);
				putenc((n & 0x0000ff00) >> 8);
				putenc((n & 0x000000ff)     );
			}
		} else if (isalpha(c)) {
			idp = ident;
			do {
				*idp++ = c;
				c = getc(ifp);
			} while (isalnum(c));
			*idp = '\0';
			for (i = 0; i < 32; i++)
				if (strcmp(ident, cmdtab[i]) == 0) {
					putenc(i);
					break;
				}
			if (i == 32) {
				if (strcmp(ident, "Dotsection") == 0) {
					putenc(12); putenc(0);
				} else if (strcmp(ident, "Vstem3") == 0) {
					putenc(12); putenc(1);
				} else if (strcmp(ident, "Hstem3") == 0) {
					putenc(12); putenc(2);
				} else if (strcmp(ident, "Seac") == 0) {
					putenc(12); putenc(6);
				} else if (strcmp(ident, "Sbw") == 0) {
					putenc(12); putenc(7);
				} else if (strcmp(ident, "Div") == 0) {
					putenc(12); putenc(12);
				} else if (strcmp(ident, "Callothersubr") == 0) {
					putenc(12); putenc(16);
				} else if (strcmp(ident, "Pop") == 0) {
					putenc(12); putenc(17);
				} else if (strcmp(ident, "Setcurrentpoint") == 0) {
					putenc(12); putenc(33);
				} else {
					fprintf(stderr, "Illegal symbol in font file: %s\n", ident);
					exit(1);
				}
			}
		}
	}
}

putenc(c)
{
	puthex(encrypt(c));
}


puthex(c)
{
	register int c1, c2;

	if (c < 0 || c > 255) {
		fprintf(stderr, "puthex error: c = %d\n", c);
		exit(1);
	}
	c1 = (c & 0xf0) >> 4;
	c2 = c & 0xf;
	putc(c1 <= 9 ? c1+'0' : c1-10+'A', ofp);
	putc(c2 <= 9 ? c2+'0' : c2-10+'A', ofp);
}

unsigned short cencrypt_r;

icencrypt()
{
	cencrypt_r = 4330;
}

int
encrypt(plain)
	int plain;
{
	unsigned short int c1 = 52845;
	unsigned short int c2 = 22719;
	static unsigned char cipher;

	cipher = (plain ^ (cencrypt_r>>8));
	cencrypt_r = (cipher + cencrypt_r)*c1 + c2;
	return cipher;
}

