/*																				*/
/*																				*/
/*				File:		  	 munge.c										*/
/*				Returns:	  	 *main*										*/
/*				Parameters:	 												*/
/*																				*/
/*																				*/

#include <stdio.h>
#include <string.h>
#include <process.h>

#include "advm.h"
#include "arg.h"
#include "units.h"
#include "values.h"
#include "string.h"
#include "doubls.h"
#include "cif.h"
#include "xrflag.h"
#include "txtlen.h"
#include "initia.h"
#include "parse.h"
#include "find.h"
#include "snapit.h"
#include "define.h"
#include "write.h"
#include "setup.h"
#include "inrnge.h"
#include "eval.h"
#include "buffwr.h"
#include "sort.h"
#include "inskey.h"
#include "insput.h"
#include "endtxt.h"
#include "endins.h"


void main(argc, argv)
int argc;
char **argv;

{
	int contin, new;
	int flush,code,smelch,first,i,bp,where,high,low,isam,opt,value,io6,k,k3,j,i1,kk;
	char str_temp [141];

	printf("\n\nMunger, V1.0\n\n");

	xargc = argc;
	xargv = argv;

	inmain = stdin;

	textfi = fopen("advt.tmp","wb");
	instfi = fopen("advi.dat","wb");
	instkeyfi = fopen("advi.key","wb");
	textkeyfi = fopen("advtkey.tmp","wb");
	xreffi = fopen("xref.dat","wt");
	initia();

label_100:
	flush = FALSE;
	contin = 300;
	new = 400;

label_200:
	if (readin())
		switch (new)
			{
			case 400: goto label_400;
			case 3100: goto label_3100;
			default: assert(FALSE);
			}
	else
		switch (contin)
			{
			case 300: goto label_300;
			case 1300: goto label_1300;
			case 3000: goto label_3000;
			default: assert(FALSE);
			}

label_300:
	flush = TRUE; 
	goto label_200;
	
label_400:
	if (linex < 0)
		{
		if (inunit == inmain) goto label_9000;
		inunit = inmain;
		fclose(inincl);
		zfid[0] = 0;
		if (list) 
			printf("\n");
		goto label_200;
		}
	if (linex < 0) goto label_9000;
	contin = 300;
	new = 400;
	if (parse()) goto label_200;
	for (code=0; code<20; code++)
		if (!strncmp(zlex,zcomm[code],3))
			break;
	if (code == 20)
		{
		if (find(zlex) >= 0) goto label_2905;

label_415:
		snapit();
		printf("--Bad command: %s\n",zlex);
		troubl = TRUE;
		goto label_100;
		}
	code++;			/* codes are 1-20; indices are 0-19 */
	if (cif > 0)
		{
		if (code == 19) cif++;
		if (code == 20) cif--;
		goto label_100;
		}
	switch (code)
		{
		case 1: goto label_2000;
		case 2: goto label_2100;
		case 3: goto label_2200;
		case 4: goto label_2300;
		case 5: goto label_2400;
		case 6: goto label_2500;
		case 7: goto label_2600;
		case 8: goto label_2800;
		case 9: goto label_2900;
		case 10: goto label_3500;
		case 11: goto label_2700;
		case 12: goto label_3600;
		case 13: goto label_3700;
		case 14: goto label_3800;
		case 15: goto label_3900;
		case 16: goto label_4000;
		case 17: goto label_4200;
		case 18: goto label_4300;
		case 19: goto label_4400;
		case 20: goto label_4500;
		default: assert (FALSE);
		}

label_1000:
	contin = 1300;
	outkey = key2 + (key1 /1000.0);
	if (parse()) goto label_200;
	define(zlex, key2);
	smelch = find(zlex);
	if (zsep != ',') goto label_200;

label_1300:
	if (zline[linex] == '%' && linex == linend) goto label_1310;
	if (linex >= linend) goto label_1350;
	if (zline[linex] == '/') goto label_1320;
	if (zline[linex] != '%') goto label_1350;

label_1310:
	key1 = 10 * (1 + key1 / 10);

label_1320:
	linex++;

label_1350:
	if (linend < linex) linend = linex;
	strncpy(str_temp, zline+linex, linend-linex+1);
	str_temp[linend-linex+1] = 0;
	write_text(&key1, str_temp);
	auxval[smelch] = (key1 % 500) / 10;
/*
     FOR OBJECTS, AUXVAL WILL BE SET EQUAL TO THE NUMBER OF STATES
     THAT THE OBJECT HAS DEFINED (NOT INCLUDING IN-HAND STATUS) AND
     MAY BE FETCHED VIA THE @NAME CONSTRUCT.
*/
	if (list) snapit();
	key1++;
	goto label_200;

label_2000:
	setup(&key1, &nxttxt);
	goto label_1000;

label_2100:
	setup(&key1, &nxtobj);
	goto label_1000;

label_2200:
	setup(&key1, &nxtpla);
	goto label_1000;

label_2300:
	first = TRUE;
	setup(&key1, &nxtver);

label_2310:
	if (parse()) goto label_100;
	define(zlex, key2);
	if (!first)
		zunref[i=find(zlex)] = ' ';
	first = FALSE;
	goto label_2310;

label_2400:
	bp = 1;
	setup(&key1, &nxtini);
	goto label_2950;

label_2500:
	if (parse()) goto label_415;
	define(zlex, nxtlab);
	bp = 1;
	setup(&key1, &nxtlab);
	goto label_2950;

label_2600:
	bp = 1;
	setup(&key1, &nxtrep);
	goto label_2950;

label_2700:
	if (parse()) goto label_100;
	define(zlex, nxtvar++);
	goto label_2700;

label_2800:
	if (parse()) goto label_415;
	if ((where = find(zlex)) < 0 || !inrnge(2000, keys[where], 3000))
		{
		snapit();
		printf("-- That's no place: %s\n",zlex);
		troubl = TRUE;
		goto label_100;
		}
	if (auxval[where] < 500) auxval[where] = 500;
	goto label_2920;

label_2900:
	if (parse()) goto label_415;

label_2905:
	if ((where = find(zlex)) < 0)
		{
		define(zlex,nxtver);
		snapit();
		printf(">> Verb defined by default <<\n");
		nxtver++;
		goto label_2905;
		}
	if (inrnge(3000, keys[where], 4000)) goto label_2925;
	if (inrnge(1000, keys[where], 2000)) goto label_2920;
	snapit();
	printf("-- That's not a verb or object: %s\n",zlex);
	troubl = TRUE;
	goto label_100;

label_2920:
	if (auxval[where] < 500) auxval[where] = 500;

label_2925:
	key2 = keys[where];
	key1 = auxval[where]++;
	outkey = key2 + (key1 / 1000.0);
	bp = 1;

label_2941:
	if (parse()) goto label_2950;
	where = eval(zlex);
	buffer[bp-1] = 1;
	buffer[bp] = where;
	bp += 2;
	goto label_2941;

label_2950:
	contin = 3000;
	new = 3100;
	outkey = key2 + (key1 / 1000.0);
	if (list) snapit();
	goto label_200;

label_3000:
	if (parse()) goto label_200;
	for (low=0, high=55; strncmp(zlex, zopt[isam = (low+high)/2], 4);)
		{
		if (low >= high)
			{
			snapit();
			printf("--Bad option: %s\n", zlex);
			troubl = TRUE;
			goto label_200;
			}
		if (strncmp(zlex, zopt[isam], 4) > 0)
			low = isam + 1;
		else
			high = isam - 1;
		}
	opt = optval[isam];
	if (class[opt-1] < 0) 
		{
		while (!parse())
		 	{
			where = eval(zlex);
			buffer[bp-1] = opt;
			buffer[bp] = where;
			bp += 2;
			}
		goto label_200;
		}
	buffer[bp-1] = opt;
	if (class[opt-1])
		{
		for (i=1; i<=class[opt-1]; i++)
			{
			if (parse())
				{
				snapit();
				printf("--Missing required parameter\n");
				troubl = TRUE;
				goto label_200;
				}
			buffer[bp+i-1] = eval(zlex);
			}
		if (!parse())
			{
			snapit();
			printf("----Too many parameters\n");
			troubl = TRUE;
			goto label_200;
			}
		}
	/* 3061 */
	bp += 1 + class[opt-1];
	goto label_200;

label_3100:
	if (bp)
		{
		buffwr(--bp);
		bp = 0;
		}
	goto label_400;

label_3500:
	if (parse()) goto label_415;
	value = eval(zlex);
	while (!parse())
		{
		define(zlex, value);
		zunref[find(zlex)] = ' ';
		}
	goto label_100;

label_3600:
	while (!parse()) 
		define(zlex, nxtnul);
	goto label_100;

label_3700:
	list = TRUE;
	goto label_100;

label_3800:
	list = FALSE;
	goto label_100;

label_3900:
	while (!parse())
		if ((i = find(zlex)) >= 0)
			refit[i] = TRUE;
		else
			{
			snapit();
			printf("-- Undefined symbol: %s\n", zlex);
			}
	goto label_100;

label_4000:
	if (inunit == inincl)
		{
		snapit();
		printf("-- Includes may not be nested.\n");
		goto label_100;
		}
	if (parse()) goto label_415;
	strcpy(zfid, zlex);
	if (!(inincl = fopen(zfid, "rt")))
		{
		snapit();
		printf("--Unable to open include file: %s\n", zlex);
		goto label_100;
		}
	inunit = inincl;
	fnum++;
	goto label_100;

label_4200:
	xref = TRUE;
	goto label_100;

label_4300:				/* eject command no longer supported */
	goto label_100;

label_4400:
	if (parse())
		{
		snapit();
		printf("-- Missing required expression\n");
		troubl = TRUE;
		goto label_100;
		}
	if (!eval(zlex)) cif = 1;

label_4500:
	goto label_100;

label_9000:
	refdef[0] = TRUE;
	define("NOBJ", nxtobj % 1000);
	define("NPLACE", nxtpla % 1000);
	define("NREP", nxtrep % 1000);
	define("NINIT", nxtini % 1000);
	define("NVARS", nxtvar % 1000);
	symcnt = -1;				/* compress the hash table */
	for (i=0; i<2000; i++)
		{
		if (zname[i][0])
			if (++symcnt != i)
				{
				strcpy(zname[symcnt], zname[i]);
				keys[symcnt] = keys[i];
				zunref[symcnt] = zunref[i];
				refit[symcnt] = refit[i];
				}
		}
	io6 = symcnt+1;
	if (list)
		{
		sort(FALSE);
		printf("\f\n\n    **** SYMBOL TABLE SORTED BY NAME (BEFORE SELECTION) ****\n\n");
		for (k=0; k<=symcnt; k+=3)
			{
			for (k3=0; k3<3 && k3+k<=symcnt; k3++)
				printf("%6d %c %-12.12s   ",keys[k+k3],zunref[k+k3],zname[k+k3]);
			printf("\n");
			}
		}
	i = -1;
	for (j=0; j<=symcnt; j++)
		{
		if (refit[j])
			if (++i != j)
				{
				strcpy(zname[i], zname[j]);
				keys[i] = keys[j];
				zunref[i] = zunref[j];
				}
		}
	symcnt = i;
	if (!list) sort(FALSE);
	key2 = 9000;
	key1 = 0;
	inskey(&key1);
	insput(symcnt+1);
	cachhw++;
	cachdw++;
	key2 = 9001;
	key1 = 0;
	for (i1 = 0; i1<=symcnt; i1+=200)
		{
		char temp [13];
		int len;

		inskey(&key1);
		cachdw++;
		for (k=i1; k<i1+200 && k<=symcnt; k++)
			{
			strcpy(temp, zname[k]);			/* pad with blanks */
			if ((len = strlen(temp)) < 6)
				memset(temp+len, ' ', 6-len);
			for (kk=0; kk<6; kk+=2)
				insput(*((int *)&temp[kk]));
			insput(keys[k]);
			cachhw += 4;
			}
		key2++;
		}
	if (list)
		{
		printf("\f\n\n   **** SYMBOL TABLE SORTED BY NAME ****\n\n");
		for (k=0; k<=symcnt; k+=3)
			{
			for (k3=0; k3<3 && k3+k<=symcnt; k3++)
				printf("%6d %c %-12.12s   ",keys[k+k3],zunref[k+k3],zname[k+k3]);
			printf("\n");
			}
		sort(TRUE);
		printf("\f\n\n   **** SYMBOL TABLE SORTED BY VALUE ****\n\n");
		for (k=0; k<=symcnt; k+=3)
			{
			for (k3=0; k3<3 && k3+k<=symcnt; k3++)
				printf("%6d %c %-12.12s   ",keys[k+k3],zunref[k+k3],zname[k+k3]);
			printf("\n");
			}
		}
	/* 9401 */
	endtxt();
	fclose(textfi);
	endins();
	fclose(instfi);
	if (xrflag) fclose(xreffi);
	printf("\fMAXIMUM BUFFER LENGTH (MAX 500)       %6d\n\n",maxbuf+1);
	printf("VOCABULARY SIZE (MAX 500)             %6d\n",symcnt+1);
	printf("HASH TABLE SIZE (MAX 2000)            %6d  (%d%%)\n\n",io6,(int)(io6/20.0+0.5));
	printf("INSTRUCTION BYTES                    %7ld (%dK)\n",(long)cachhw*2,(cachhw+511)/512);
	printf("INSTRUCTION KEYS (MAX 2500)           %6d\n\n",cachdw);
	printf("TEXT BYTES                           %7ld (%ldK)\n",texthw,(texthw+1023)/1024);
	printf("TEXT KEYS (MAX 2500)                  %6d\n\n",textdw);
	printf("OBJECTS (MAX 150)                     %6d\n",nxtobj % 1000);
	printf("PLACES  (MAX 300)                     %6d\n",nxtpla % 1000);
	printf("VARIABLES (MAX 50)                    %6d\n\n\n\n\n",nxtvar % 1000);
	if (troubl) exit(1);
	execl("compress.exe",NULL);
	printf("Pass 2 (Compress) not found.\n\n");
	exit(1);
}

