#include <stdio.h>
#include "utype.h"
#include "umem.h"
#include "register.h"
#include "macros.h"
#include "input.h"
#include "interp.h"
#include "phash.h"

extern HASHREC **hashtable;

static void BadRepExt(void)
{
	Error("Bad Replacement String");
}
REGISTRY *FindMacro(short *name)
{
	REGISTRY **r = LookupPhiHash(hashtable, name);
	if (r && (*r) && (*r)->type == R_MACRO && (*r)->isdef)
		return(*r);
	return(0);
}
short *ExpandString(short *string)
{
	BOOL changed;
	short *ibuf;
	ibuf = AllocateMemory(INTERNALBUFSIZE * sizeof(short));
 do {
	short *d=ibuf,*s=string;
	short macname[100], ext1[100], ext2[100], *n;
	REGISTRY *r;
	changed = FALSE;
	while (*s) {
		if (*s == MACROSTART && *(s+1) == MACROLEFT1) {
			s+=2;
			goto macroexpand;
		}
		else {
			if (*s == MACROLEFT2) {
				s++;
macroexpand:
				changed = TRUE;
				n = macname;
				while (*s && *s != MACRORIGHT1 && *s != MACRORIGHT2 && *s != COLON
							&& *s != COLON2)
					*n++ = *s++;
				*n = 0;
				switch (*s) {
					case MACRORIGHT1:
					case MACRORIGHT2:
								s++;
							  r = FindMacro(macname);
								if (r) {
									short *s =r->x.macro;
									while(*s)
										*d++ = *s++;
								}
								break;
					case COLON:
					case COLON2:
								s++;
							  r = FindMacro(macname);
								n = ext1;
								while(*s && (*s != EQUAL && *s != ALTEQUAL && n-ext1<19))
									*n++ = *s++;
								*n = 0;
								if (*s != EQUAL && *s != ALTEQUAL)
									BadRepExt();
								if (*s) {
									s++;
									n = ext2;
									while(*s && (*s != MACRORIGHT1 && *s != MACRORIGHT2 && n-ext2<19))
										*n++ = *s++;
									*n = 0;
								}
								if (*s)
									s++;
								n = d;
								if (r) {
									short *s =r->x.macro;
									while(*s) {
										if (!pstrncmp(s,ext1,pstrlen(ext1))) {
											pstrncpy(d,ext2,pstrlen(ext2));
											d+= pstrlen(ext2);
											s+= pstrlen(ext1);
										}
										else
											*d++ = *s++;
									}
								}
								*d = 0;
								break ;
					default:
						Error("Unterminated macro");
				}
			}
			else {
				*d++ = *s++;
			}
		}
	}
	*d = 0;
	pstrcpy(string,ibuf);
 } while (changed);
 DeallocateMemory(ibuf);
  return(string);
}