#include "config.h"

/* $Id: phtoelm.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $
 */
#include <ctype.h>
#include <stdarg.h>
#include "useconfig.h"
#include "proto.h"
#include "elements.h"
#include "phfeat.h"
#include "darray.h"
#include "trie.h"
#include "phtoelm.h"
#include "holmes.h"
#include "nsynth.h"


trie_ptr phtoelm = NULL;

static Elm_ptr find_elm PROTO((const char *s));

static Elm_ptr find_elm( const char *s )
{
	Elm_ptr e = Elements;
	while (e < Elements + num_Elements)
	{
		if (!strcmp( s, e->name ))
		{
			return e;
		}
		e++;
	}
	return NULL;
}

static void enter( const char *p,... )
{
	va_list ap;
	const char *s;
	char buf[20];
	char *x = buf + 1;
	va_start( ap, p );
	while ((s = va_arg( ap, const char * )))
	{
		Elm_ptr e = find_elm( s );
		if (e)
			*x++ = (e - Elements);
		else
		{
//			fprintf(stderr, "Cannot find %s\n", s);
		}
	}
	va_end( ap );
	buf[0] = (x - buf) - 1;
	x = (char *)malloc( buf[0] + 1 );
	memcpy( x, buf, buf[0] + 1 );
	trie_insert( &phtoelm, p, x );
}

static void enter_phonemes( void )
{
#include "phtoelm.define"
}

int phone_append( darray_ptr p, int ch )
{
	char *s = (char *) darray_find( p, p->items );
	*s = ch;
	return ch;
}

#if 0
#define StressDur(e,s) ((e->ud + (e->du - e->ud) * s / 3)*speech_speed_)
#else
#define StressDur(e,s) ((void)s,((e->du + e->ud) / 2)*speech_speed_)
#endif

unsigned phone_to_elm(const char *phone,int n,darray_ptr elm )
{
	int stress = 0;
	const char *s = phone;
	unsigned t = 0;
	const char *limit = s + n;
	if (!phtoelm)
		enter_phonemes();
	while (s < limit && *s)
	{
		const char *e = (char *)trie_lookup( &phtoelm, &s );
		if (e)
		{
			int n = *e++;
			while (n-- > 0)
			{
				int x = *e++;
				Elm_ptr p = &Elements[x];
				/* This works because only vowels have ud != du,
				   and we set stress just before a vowel
				 */
				phone_append( elm, x );
				if (!(p->feat & vwl))
					stress = 0;
				t += phone_append( elm,StressDur( p,stress ));
				phone_append( elm, stress );
			}
		}
		else
		{
			char ch = *s++;
			switch (ch)
			{
			case '\'':           /* Primary stress */
				stress = 3;
				break;
			case ',':            /* Secondary stress */
				stress = 2;
				break;
			case '+':            /* Tertiary stress */
				stress = 1;
				break;
			case '-':            /* hyphen in input */
				break;
			default:
			//	fprintf(stderr, "Ignoring %c in '%.*s'\n", ch, n, phone);
				break;
			}
		}
	}
	return t;
}
