#include "span.h"
/*
 * phon - phonemic translator
 *	Greg Lee, lee@uhccux.uhcc.hawaii.edu, 8/27/89
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

int debug = 0;

char *fbuf;

void interpret(char *name)
{
	unsigned i, size, readin(), apply();

	size = readin(name, &fbuf);

	for (i=4; i<size+4; i++)
		if (fbuf[i] >= 'A' && fbuf[i] <= 'Z' &&
		    fbuf[i+1] >= 'a' && fbuf[i+1] <= 'z')
		fbuf[i] += 32;

	for (i=4; i<size+4; ) i = apply(i);
	free(fbuf);
}

int main(int argc, char **argv)
{	int k;

	for (k = 1; --argc; k++) interpret(argv[k]);
        exit(0);
        return 0;
}

//FILE *fopen();

unsigned int readin(char *name, char **place)
{	FILE *f;
	struct stat statbuf;

	if (stat(name, &statbuf)) {
		perror(name);
		return(0);
    	}

	if ( (*place = (char *)malloc(statbuf.st_size+8)) == NULL ) {
		fprintf(stderr, "not enough memory for %s\n", name);
		exit(1);
	}

	if ( (f = fopen(name, "r")) == NULL ) {
		fprintf(stderr, "no file %s\n", name);
		exit(1);
	}

	int rc = fread(*place+4, 1, statbuf.st_size, f);

	fclose(f);

	return(statbuf.st_size);
}

unsigned int apply(int i)
{	int r;
	int match, c,j,k;
	char *lhs,*rhs,*lctx,*rctx;

    c = fbuf[i];
    if (c == ' ' || c == '\t' || c == '\n') {
	putchar(c);
	return(i+1);
    }

    for (r=1,match=0; !match && rules[r][0]; r += 4) {
	lctx = rules[r-1];
	lhs = rules[r];
	rctx = rules[r+1];
	rhs = rules[r+2];

	for (k=0; lhs[k] == fbuf[i+k]; k++) ;
	if (!lhs[k]) {
		int cf();

		match = k;
if (debug) printf("\nrule %d: [%s] -> [%s] /[%s]_[%s]\n",r,lhs,rhs,lctx,rctx);
if (debug) printf("at %d lhs m=%d;",i,match);
		j = i-1;
		while ((c = *lctx++) && match)
			if ((j = cf(j,-1,c)) < -1) match = 0;
if (debug) printf(" %s on left at %d;", match? "yes" : "no", j);
		j = i+match;
		while ((c = *rctx++) && match)
			if ((j = cf(j, 1,c)) < -1) match = 0;
if (debug) printf(" %s on right at %d;", match? "yes" : "no", j);
		if (match) while (c = *rhs++) putchar(c);
	}
    }
    if (!match) {
	putchar('?');
	putchar('?');
	putchar(fbuf[i]);
	return(i+1);
    }
    else return(i+match);
}

int cf(int pos, int inc, int c)
{   int r = 0;
    int vtest(), ctest(), ptest(), stest(), ztest(), dtest();

    if (pos < 0 && c == '#') return(pos+inc);
    switch (c) {
	case '#':
		while (pos >= 0 && (fbuf[pos] < 'a' || fbuf[pos] > 'z')) {
			pos += inc;
			r++;
		}
		if (pos < 0) r = 1;
		break;
	case 'V':
		while (pos >= 0 && vtest(fbuf[pos])) {
			pos += inc;
			r++;
		}
		break;
	case 'Q':
		if (ctest(fbuf[pos])) r = 1;
		pos += inc;
		break;
	case 'C':
		while (pos >= 0 && ctest(fbuf[pos]))
			pos += inc;
		r = 1;
		break;
	case 'P':
		if (ptest(fbuf[pos])) r = 1;
		pos += inc;
		break;
/* Z	[bdvgjlmnrwz]		*/
	case 'Z':
		if (ztest(fbuf[pos])) r = 1;
		pos += inc;
		break;
/* D	[tsrdlznj]|th|ch|sh		*/
	case 'D':
		if (inc == 1 && fbuf[pos+1] == 'h'
			&& (fbuf[pos] == 't' ||
			    fbuf[pos] == 'c' ||
			    fbuf[pos] == 's') ) {
			r = 1;
			pos += 2;
		}
		else if (inc == -1 && fbuf[pos] == 'h'
			&& (fbuf[pos-1] == 't' ||
			    fbuf[pos-1] == 'c' ||
			    fbuf[pos-1] == 's') ) {
			r = 1;
			pos -= 2;
		}
		else if (dtest(fbuf[pos])) {
			r = 1;
			pos += inc;
		}
		break;
/* S	[scgzxj]|ch|sh		*/
	case 'S':
		if (inc == 1 && fbuf[pos+1] == 'h'
			&& (fbuf[pos] == 'c' ||
			    fbuf[pos] == 's') ) {
			r = 1;
			pos += 2;
		}
		else if (inc == -1 && fbuf[pos] == 'h'
			&& (fbuf[pos-1] == 'c' ||
			    fbuf[pos-1] == 's') ) {
			r = 1;
			pos -= 2;
		}
		else if (stest(fbuf[pos])) {
			r = 1;
			pos += inc;
		}
		break;
/* A	er|e|es|ed|ing|ely		*/
	case 'A':
		if (fbuf[pos] == 'i'
			&& fbuf[pos+1] == 'n'
			&& fbuf[pos+2] == 'g') {
			r = 1;
			pos += 3;
		}
		else if (fbuf[pos] == 'e'
			&& fbuf[pos+1] == 'l'
			&& fbuf[pos+2] == 'y') {
			r = 1;
			pos += 3;
		}
		else if (fbuf[pos] == 'e'
			&& fbuf[pos+1] == 'r') {
			r = 1;
			pos += 2;
		}
		else if (fbuf[pos] == 'e'
			&& fbuf[pos+1] == 's') {
			r = 1;
			pos += 2;
		}
		else if (fbuf[pos] == 'e'
			&& fbuf[pos+1] == 'd') {
			r = 1;
			pos += 2;
		}
		else if (fbuf[pos] == 'e') {
			r = 1;
			pos += inc;
		}
		break;
	default:
		if (fbuf[pos] == c) r = 1;
		pos += inc;
		break;
    }
    if (r) return(pos);
    else return(-10);
}

/* V	[aeiouy]+		*/
int vtest(int c)
{
	if (c == 'a') return(1);
	if (c == 'e') return(1);
	if (c == 'i') return(1);
	if (c == 'o') return(1);
	if (c == 'u') return(1);
	if (c == 'y') return(1);
	return(0);
}

/* Q	[bcdfghjklmnpqrstvwxz]		*/
/* C	[bcdfghjklmnpqrstvwxz]*		*/
int ctest(int c)
{
	if (c == 'b') return(1);
	if (c == 'c') return(1);
	if (c == 'd') return(1);
	if (c == 'f') return(1);
	if (c == 'g') return(1);
	if (c == 'h') return(1);
	if (c == 'j') return(1);
	if (c == 'k') return(1);
	if (c == 'l') return(1);
	if (c == 'm') return(1);
	if (c == 'n') return(1);
	if (c == 'p') return(1);
	if (c == 'q') return(1);
	if (c == 'r') return(1);
	if (c == 's') return(1);
	if (c == 't') return(1);
	if (c == 'v') return(1);
	if (c == 'w') return(1);
	if (c == 'x') return(1);
	if (c == 'z') return(1);
	return(0);
}

/* P	[eiy]		*/
int ptest(int c)
{
	if (c == 'e') return(1);
	if (c == 'i') return(1);
	if (c == 'y') return(1);
	return(0);
}
/* Z	[bdvgjlmnrwz]		*/
int ztest(int c)
{
	if (c == 'b') return(1);
	if (c == 'd') return(1);
	if (c == 'v') return(1);
	if (c == 'g') return(1);
	if (c == 'j') return(1);
	if (c == 'l') return(1);
	if (c == 'm') return(1);
	if (c == 'n') return(1);
	if (c == 'r') return(1);
	if (c == 'w') return(1);
	if (c == 'z') return(1);
	return(0);
}
/* S	[scgzxj]|ch|sh		*/
int stest(int c)
{
	if (c == 's') return(1);
	if (c == 'c') return(1);
	if (c == 'g') return(1);
	if (c == 'z') return(1);
	if (c == 'x') return(1);
	if (c == 'j') return(1);
	return(0);
}
/* D	[tsrdlznj]|th|ch|sh		*/
int dtest(int c)
{
	if (c == 't') return(1);
	if (c == 's') return(1);
	if (c == 'r') return(1);
	if (c == 'd') return(1);
	if (c == 'l') return(1);
	if (c == 'z') return(1);
	if (c == 'n') return(1);
	if (c == 'j') return(1);
	return(0);
}
