
/*
 *  VAR.C
 *
 *  Variables and Macros
 */

#include "defs.h"

#define MACNODE struct _MACNODE

MACNODE {
    MNODE Node;
    char *Name;     /*	variable name	*/
    char *MacName;  /*	replace with..	*/
    short MacLen;
    short NameLen;
    short NormalEntry;
};


MLIST	MacList = { (MNODE *)&MacList.mlh_Tail, NULL, (MNODE *)&MacList.mlh_Head };
MLIST	ColList = { (MNODE *)&ColList.mlh_Tail, NULL, (MNODE *)&ColList.mlh_Head };

/*
 *  var points to begining, str points to the '='
 */

void
MacroAssign(var, str)
char *var, *str;
{
    MACNODE *node = malloc(sizeof(MACNODE));

    while (str != var && (*str == '=' || *str == ' ' || *str == '\t'))
	--str;
    ++str;
    node->NameLen = str - var;
    node->Name = malloc(node->NameLen + 1);
    movmem(var, node->Name, node->NameLen);
    node->Name[node->NameLen] = 0;
    while (*str && *str != '=')
	++str;
    if (*str == '=')
	++str;
    while (*str && (*str == ' ' || *str == '\t'))
	++str;
    node->MacLen = strlen(str);
    node->MacName = malloc(node->MacLen + 1);
    strcpy(node->MacName, str);
    AddHead(&MacList, node);
}

MacroReplace(spec, buf)
register char *buf;
{
    char *base = buf;
    char cext;
    short error = 8192;

    while (*buf && --error) {
	register short i;
	char *found = NULL;
	short falloced = 0;

	if ((buf[0] != '$' && buf[0] != '%') || buf[1] != '(') {
	    ++buf;
	    continue;
	}
	for (i = 2; buf[i] && buf[i] != ')' && buf[i] != ':'; ++i) {
	    if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		MacroReplace(spec, buf + i);
	}
	if (buf[i] != ')' && buf[i] != ':') {
	    ++buf;
	    continue;
	}
	cext = (buf[i] == ':');
	{
	    register MACNODE *node;
	    register short len = i - 2;
	    char *search = buf + 2;

	    /*
	     *	Check normal macro variables
	     */

	    for (node = GetHead(&MacList); node; node = GetSucc(node)) {
		if (node->NameLen == len && strncmp(node->Name, search, len) == 0) {
		    found = node->MacName;
		    break;
		}
	    }
percind:
	    if (found && buf[0] == '%') {
		search = found;
		len = strlen(found);
		if (falloced) {
		    free(found);
		    falloced = 0;
		}
		node = NULL;
		found = NULL;
	    }

	    /*
	     *	Check collections
	     */

	    if (!found && spec) {
		for (node = GetHead(&ColList); node; node = GetSucc(node)) {
		    if (node->NameLen == len && strncmp(node->Name, search, len) == 0) {
			found = node->MacName;
			break;
		    }
		}
	    }

	    /*
	     *	Still nothing!	If it is a wildcard, try to find a match
	     *	with item(s) on the collection list.  Else check the
	     *	enviroment.
	     */

	    if (!found) {
		char c = search[len];
		search[len] = 0;
		if (IsWildCard(search)) {
		    for (node = GetHead(&ColList); node; node = GetSucc(node)) {
			if (node->NormalEntry && WildCmp(search, node->MacName)) {
			    if (found) {
				char *new = malloc(strlen(found) + strlen(node->MacName) + 2);
				strcpy(new, found);
				strcat(new, " ");
				strcat(new, node->MacName);
				if (falloced)
				    free(found);
				found = new;
				falloced = 1;
			    } else {
				found = node->MacName;
			    }
			}
		    }
		} else {
		    found = NULL;
		    /*
		    mountrequest(0);
		    if (found = GetDEnv(search))
			falloced = 1;
		    mountrequest(1);
		    */
		}
		search[len] = c;
		if (found)
		    goto percind;
	    }
	}
	if (found && cext) {    /*  found the string & extension    */
	    char *w1, *w2;
	    char *xbuf = malloc(256);
	    char *res;
	    char *rstr = malloc(1);
	    register char *ptr;
	    register short len;

	    rstr[0] = 0;
	    ++i;
	    if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		MacroReplace(spec, buf + i);
	    if (buf[i] != '\"') {
		printf("Quote missing: %s\n", buf);
		xexit(30);
	    }
	    ++i;
	    w1 = buf + i;
	    while (buf[i] && buf[i] != '\"') {
		if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		    MacroReplace(spec, buf + i);
		else
		    ++i;
	    }
	    if (buf[i] != '\"') {
		printf("Quote missing: %s\n", buf);
		xexit(30);
	    }
	    buf[i++] = 0;
	    if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		MacroReplace(spec, buf + i);
	    if (buf[i++] != ':') {
		printf("Colon missing: %s\n", buf);
		xexit(30);
	    }
	    if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		MacroReplace(spec, buf + i);
	    if (buf[i++] != '\"') {
		puts("QM");
		xexit(30);
	    }
	    w2 = buf + i;
	    while (buf[i] && buf[i] != '\"') {
		if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		    MacroReplace(spec, buf + i);
		else
		    ++i;
	    }
	    if (buf[i] != '\"') {
		puts("QM2");
		xexit(30);
	    }
	    buf[i++] = 0;
	    if ((buf[i] == '$' || buf[i] == '%') && buf[i+1] == '(')
		MacroReplace(spec, buf + i);
	    if (buf[i] != ')') {
		puts("QM3");
		xexit(30);
	    }
	    /*
	     *	Now parse found string and call VirtuoExpand(w2, w1, file)
	     */

	    for (ptr = found; *ptr;) {
		while (*ptr == ' ' || *ptr == '\t')
		    ++ptr;
		if (!ptr[0])
		    break;
		for (len = 0; ptr[len] && ptr[len] != ' ' && ptr[len] != '\t'; ++len);
		movmem(ptr, xbuf, len);
		ptr += len;
		xbuf[len] = 0;
		/*
		printf("VEXT '%s' '%s' '%s'\n", w2, w1, xbuf);
		*/
		if (res = VirtuoExpand(w2, w1, xbuf)) {
		    char *tmp = malloc(strlen(rstr) + strlen(res) + 2);
		    strcpy(tmp, rstr);
		    if (tmp[0])
			strcat(tmp, " ");
		    strcat(tmp, res);
		    free(rstr);
		    rstr = tmp;
		}
	    }
	    if (falloced)
		free(found);
	    found = rstr;
	    falloced = 1;
	    free(xbuf);
	}

	/*
	 *  replace the area buf + 0; < buf + i + 1	(len i + 1)
	 *  with 'found'
	 */

	if (found) {
	    register short flen = strlen(found);
	    register short len = i + 1;

	    movmem(buf + len, buf + flen, strlen(buf + len) + 1);
	    movmem(found, buf, flen);
	} else {
	    buf += i + 1;
	}
	if (falloced)
	    free(found);
    }
    return(buf - base);
}

ResetVarCollector()
{
    register MACNODE *node;

#ifdef DEBUG2
    puts("RESETVARCOL");
#endif
    while (node = RemHead(&ColList)) {
	free(node->Name);
	free(node->MacName);
	free(node);
    }
}

AddVarCollector(str, basestr, normal)
char *str, *basestr;
{
    register MACNODE *node;
    register char *ptr;
    short newlen = strlen(str);

#ifdef DEBUG2
    printf("ADDVARCOLLECTOR: %s += %s\n", basestr, str);
#endif

    for (node = GetHead(&ColList); node; node = GetSucc(node)) {
	if (strcmp(node->Name, basestr) == 0)
	    break;
    }
    if (!node) {
	node = malloc(sizeof(MACNODE));
	node->NameLen = strlen(basestr);
	node->Name = malloc(node->NameLen+1);
	strcpy(node->Name, basestr);
	node->MacLen = 0;
	node->MacName = malloc(1);
	node->MacName[0] = 0;
	AddTail(&ColList, node);
    }
    node->NormalEntry = normal;
    ptr = malloc(node->MacLen + newlen + 2);
    strcpy(ptr, node->MacName);
    if (node->MacLen)
	strcat(ptr, " ");
    strcat(ptr, str);
    free(node->MacName);
    node->MacName = ptr;
    node->MacLen = strlen(ptr);
}



