/*---------------------------------------------------------------------------
sugar.c

syntactic sugar for accessing object subvariables (aliases)

Markus Zolliker, March 2005
----------------------------------------------------------------------------
*/

#include <stdio.h>
#include "sics.h"
#include "splitter.h"
#include "sugar.h"
#include "pardef.h"

typedef struct {
  pObjectDescriptor desc;
  char *name;
  char *alias;
} Sugar;

int SugarCommand(SConnection * con, SicsInterp * sics, void *data,
                 int argc, char *argv[])
{
  Sugar *sugar = data;
  char *cmd;
  char **args;
  char buf[256];
  int i;

  assert(sugar);
  if (argc < 1)
    return 0;
  args = calloc(argc, sizeof(char *));
  if (!args)
    return 0;
  args[0] = sugar->alias;
  for (i = 1; i < argc; i++) {
    args[i] = argv[i];
  }
  cmd = Arg2Tcl(argc + 1, args, buf, sizeof(buf));
  free(args);
  if (!cmd)
    return 0;
  i = SCInvoke(con, sics, cmd);
  if (cmd != buf)
    free(cmd);
  return i;
}

void SugarDelete(void *data)
{
  Sugar *sugar = data;

  assert(sugar);
  if (sugar->desc) {
    DeleteDescriptor(sugar->desc);
    sugar->desc = NULL;
  }
  if (sugar->name)
    free(sugar->name);
  if (sugar->alias)
    free(sugar->alias);
  free(sugar);
}

int SugarMake(char *name, char *alias)
{
  Sugar *sugar;

  sugar = FindCommandData(pServ->pSics, name, "Sugar");
  if (sugar == NULL) {
    if (FindCommand(pServ->pSics, name)) {
      return -2;
    }
    sugar = calloc(1, sizeof *sugar);
    if (!sugar)
      return -1;

    sugar->desc = CreateDescriptor("Sugar");
    if (!sugar->desc)
      goto release;
    sugar->name = strdup(name);
    sugar->alias = strdup(alias);
  } else {
    if (strcmp(name, sugar->name) != 0) {
      free(sugar->name);
      sugar->name = strdup(name);
    }
    if (strcmp(alias, sugar->alias) != 0) {
      free(sugar->alias);
      sugar->alias = strdup(alias);
    }
  }

  if (!sugar->name || !sugar->alias)
    goto release;

  if (0 ==
      AddCommand(pServ->pSics, name, SugarCommand, SugarDelete, sugar))
    goto release;
  return 1;

release:
  SugarDelete(sugar);
  return -1;
}
