/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident "$Header: codegen.c 1.2 90/05/21 $@(#)colltbl:codegen.c	1.4 88/01/06 AT&T UEL"

#include "colltbl.h"
#include 	<ctype.h>
#include	<locale.h>

extern int	regexp_flag;
unsigned int 	currchar;
unsigned	short 	psarray[SZ_COLLATE/2] ; /* primary, secondary values */
unsigned	char	onetomany[SZ_SUBS];
unsigned	short	twoto1[SZ_SUBS]; 
unsigned	short	val2to1[SZ_SUBS]; 
int			cnt2to1;

void
codegen(setup)
struct {
	SYMNODE		*first_sym;
	SYMNODE		*first_repl;
	unsigned short	value;
	unsigned short	width;
} *setup;

{


	int	i = 0, j = 0;
	int	len1tomany, len2to1 ;
	unsigned char ch;
	SYMNODE	*np, *save_np, *save_first;
	BOOLEAN	switch_built = FALSE;
	BOOLEAN default_built = FALSE;
	BOOLEAN no_replace = FALSE;
	
/*	initialise psarray with "don't cares" */

for (i=0; i < SZ_COLLATE/2; i++)
	psarray[i] = 1;
if ((np = setup->first_repl) == NULL)
	TURNON(no_replace);


len1tomany = 0;

if (!no_replace) {
	/* 
	 *	print regular expression stuff (diphtongs and
	 *	ligatures)
	 */
	for(np = setup->first_repl; np != (SYMNODE *) NULL; i++, np = np->thread) {
		ch = np -> name[0];
		if (regexp_flag)
			GENERATE(np->name);
		else {
			onetomany[len1tomany++] = ch;

		}
			psarray[ch] |= 0x8000; /* this is the one to many flag */
			strcpy(&onetomany[len1tomany], np-> uval.replval.repl_string);
			len1tomany += strlen( np-> uval.replval.repl_string) + 1;
		}
	}
if(setup->width == 2)
	fprintf(stderr, "Width is 2\n");
	
	/*
	 *	Now we can generate primary/secondary
	 *	table.
	 */

	cnt2to1 = 0;
	np = setup->first_sym;
	while(np != (SYMNODE *) NULL) {
		FOUNDCH(*np->name);
		if (np->thread != (SYMNODE *)NULL
		&& *np->thread->name == *np->name && *(np->name+1) == '\0')
			{
			TURNON(default_built);
			save_first = np;
			}
		if(*(np->name+1) != '\0') {
			TURNON(switch_built);
			psarray[(0xff)&(*(np->name))] |= 0x4000; /* Mark as 2-to-1 */
			val2to1[cnt2to1] = np -> uval.symval.primary |
				((np -> uval.symval.secondary) << 8); 
			twoto1[cnt2to1++] = ((0xff)&(*np -> name)) | (*(np->name+1) << 8);
			}
		while(np->thread != (SYMNODE *) NULL && *np->thread->name == *np->name) {
			TURNON(switch_built);
			save_np = np;
			np = np->thread;
			psarray[((0xff) & *(np->name))] |= 0x4000; /* Mark as 2-to-1 */
			val2to1[cnt2to1] = np -> uval.symval.primary |
				((np -> uval.symval.secondary) << 8); 
			twoto1[cnt2to1++] = ((0xff)&(*np -> name)) | (*(np->name+1) << 8);
			}
		if(switch_built) {
			TURNOFF(switch_built);
			if (default_built) {
				psarray[(0xff)&(*(np->name))] |= 0x4000; /* Mark as 2-to-1 */
				put_value(save_first->uval.symval.primary, save_first->uval.symval.secondary, setup -> width, currchar);
				TURNOFF(default_built);
			}
				
		}
		else {
			put_value(np->uval.symval.primary, np->uval.symval.secondary, setup->width, currchar);
		}
		np = np->thread;
	}
		if(setup->width == 1) {
			for (i=0; i<SZ_COLLATE/2; i++) {
				printf("%c%c", psarray[i]>>8, psarray[i]);
				}
			for (i=0; i < len1tomany; i++) {
				printf("%c", onetomany[i++]);
				while (onetomany[i] != '\0') 
					printf("%c", onetomany[i++]);
				printf("%c", 0); /* null for real string*/
			}
			putchar(0); /* trailing null for section*/
			i = 0;
			while (twoto1[i] != '\0') {
				printf("%c%c", twoto1[i] >> 8, twoto1[i]);
				i++;
			}
			if (i != 0)
				putchar(0); /* trailing null */
			i = 0;
			while (val2to1[i] != '\0') {
				printf("%c%c", val2to1[i]>>8, val2to1[i]);
				i++;
			}
			fflush(stdout);
			putchar(0); putchar(0);
			
			fprintf(stderr, "Collation table generated\n");
			}
}

void
put_value(primary, secondary, width, index)
unsigned short	primary, secondary;
unsigned short	width;
unsigned short	index;
{
	switch(width) {
	case 1:
		psarray[index] &= 0xff00;
		psarray[index] |= primary;
		if (secondary)
			psarray[index] = psarray[index] | (secondary << 8);
		break;
	case 2:
		/* Multi-byte version */
		psarray[index] |= primary;
		if (secondary)
			psarray[index] = psarray[index] | (secondary << 8);
		break;
	}
}

FOUNDCH(c)
char	c;
{
	currchar = 0x0FF & c;
}

GENERATE(cp)
char	*cp;
{
	char	c;
	while( (c = *cp++) != 026)  
		printf("\\%o", c);
	printf("\\26");
}
