/*
 * Adobe type1 decompile
 * 
 * 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 de-compiled
	 */
	while ((c = getc(ifp)) != -1) {
		putc(c, ofp);
		if (c == '<') {
			putc('\t', ofp);
			decompile();
			fprintf(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 */
	};

/*
 * Decompile a hex string
 */
decompile()
{
	register int v;
	int l;
	int i, c;

	icdecrypt();
	for (i = 0; i < lenIV; i++)
		(void)decrypt(gethex(0));
	while ((c = getc(ifp)) != '>') {
		if (c == -1) {
			fprintf(stderr, "Premature eof on input\n");
			exit(1);
		}
		v = decrypt(gethex(c));
		if (v < 32) {
			if (v == 12) {
				switch (v = decrypt(gethex(0))) {
				case 0: fprintf(ofp, "Dotsection"); break;
				case 1: fprintf(ofp, "Vstem3"); break;
				case 2: fprintf(ofp, "Hstem3"); break;
				case 6: fprintf(ofp, "Seac"); break;
				case 7: fprintf(ofp, "Sbw"); break;
				case 12: fprintf(ofp, "Div"); break;
				case 16: fprintf(ofp, "Callothersubr"); break;
				case 17: fprintf(ofp, "Pop"); break;
				case 33: fprintf(ofp, "Setcurrentpoint"); break;
				default:
					fprintf(ofp, "Escape %d", v);
				}
			} else
				fprintf(ofp, "%s", cmdtab[v]);
			fprintf(ofp, "\n\t\t");
		} else if (v <= 246)
			fprintf(ofp, "%d ", v-139);
		else if (v <= 250)
			fprintf(ofp, "%d ", ((v - 247)*256) + decrypt(gethex(0)) + 108);
		else if (v <= 254)
			fprintf(ofp, "%d ", -((v - 251)*256) - decrypt(gethex(0)) - 108);
		else if (v == 255) {
			l =  decrypt(gethex(0)) * 0x1000000;
			l += decrypt(gethex(0)) * 0x10000;
			l += decrypt(gethex(0)) * 0x100;
			l += decrypt(gethex(0));
			fprintf(ofp, "%ld ", l);
		}
	}
}


/*
 * Read a hex byte
 */
gethex(peekc)
	int peekc;
{
	register int c1, c2;

	c1 = peekc ? peekc : getc(ifp);
	c2 = getc(ifp);
	if (!isxdigit(c1) || !isxdigit(c2)) {
		fprintf(stderr, "Illegal hex digit in input\n");
		exit(1);
	}
	c1 = toupper(c1); c2 = toupper(c2);
	return ((c1 <= '9' ? c1 - '0' : c1 - 'A' + 10) << 4)
		| (c2 <= '9' ? c2 - '0' : c2 - 'A' + 10);
}

static unsigned short int cdecrypt_r =  4330;

icdecrypt()
{
	cdecrypt_r = 4330;
}

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

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

