/* assoc.c 2.9.0 92/07/06 - maintain association list alterable by the user
 *  Created by Damian Cugley <pdc@oxford.prg> Fri 12 Jan 1990
-----------------------------------------------------------------------
    This software module copyright (c) 1990,1991 Damian Cugley.  
    It is provided for free on an "as-is" basis.
    See the file COPYING for more information.
-----------------------------------------------------------------------
 */
#include "stdc.h"
#include "xstdio.h"		/* <stdio.h> plus prototypes */
#include "strmisc.h"
#include "assoc.h"

#define NEW(t) ((t *)xmalloc(sizeof (t)))

const char *			/* NULL if no definition */
assoc(al, s)
     Assoclist al;
     const char *s;
{
  const char *t, *u;
  
  for (; al; al = al->next)
    for (t = al->s, u = s; *t && *t++ == *u++; )
      if (!*u && *t == '=')
	return t + 1;
  return (char *)0;
}

Assoclist			/* always NULL */
assoc_destroylist(al)
     Assoclist al;
{
  Assoclist tnext;

  for (; al; al = tnext)
    {
      tnext = al->next;
      xfree(al->s);
      xfree(al);
    }
  return (Assoclist)0;
}

Assoclist
assoc_add(al, s)
     Assoclist al;
     char *s;			/* must already be malloc'd string */
{
  Assoclist tal = al;		/* temp copy of original value */
  const char *t, *u;
  
  for (; al; al = al->next)
    for (t = al->s, u = s; *t && *t++ == *u++; )
      if (!*u && *t == '=')
	{
	  xfree(al->s);		/* dispose old association */
	  al->s = s;
	  return tal;
	}
  /*  new association  */
  al = NEW(struct assoc_node);
  al->s = s;
  al->next = tal;
  return al;
}

void
assoc_print(al)
     Assoclist al;
{
  printf("{\n");
  for (; al; al = al->next)
    printf("\t%s\n", al->s);
  printf("}\n");
}

const char *
assoc_match_backwards(al, s, pe)
     Assoclist al;
     const char *s;
     const char **pe;
{
  const char   *t,		/*  scans back from "=" in al->s  */
	       *u,		/*  scans back from *pe in s  */
	       *v;		/*  pointer to after the "=" in al->s  */

  for (; al; al = al->next)
    {
      if (*al->s == '=') return al->s + 1; /* empty KEY matches anything */
      for (t = al->s; *t && *t != '='; t++)
	;
      v = t + 1;
      for (u = *pe; u > s && *--t == *--u; )
	if (t == al->s)
	  {
	    *pe = u;
	    return v;
	  }
    }
  return (char *)0;
}
