/* simplefuncs.c: -*- C -*-  DESCRIPTIVE TEXT. */

/* Author: Brian J. Fox (bfox@ai.mit.edu) Fri Mar 22 13:54:13 1996.

   This file is part of <Meta-HTML>(tm), a system for the rapid deployment
   of Internet and Intranet applications via the use of the Meta-HTML
   language.

   Copyright (c) 1995, 1996, Brian J. Fox (bfox@ai.mit.edu).
   Copyright (c) 1996, Universal Access Inc. (http://www.ua.com).

   Meta-HTML is free software; you can redistribute it and/or modify
   it under the terms of the UAI Free Software License as published
   by Universal Access Inc.; either version 1, or (at your option) any
   later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   UAI Free Software License for more details.

   You should have received a copy of the UAI Free Software License
   along with this program; if you have not, you may obtain one by
   writing to:

   Universal Access Inc.
   129 El Paseo Court
   Santa Barbara, CA
   93101  */

#include "language.h"

static void pf_prog (PFunArgs);
static void pf_concat (PFunArgs);
static void pf_string_eq (PFunArgs);
static void pf_defvar (PFunArgs);
static void pf_copy_var (PFunArgs);
static void pf_coerce_var (PFunArgs);

PFunDesc simplefunc_table[] = {
  { "PROG",		0, 0, pf_prog },
  { "GROUP",		0, 0, pf_prog },
  { "CONCAT",		0, 0, pf_concat },
  { "STRING-EQ",	0, 0, pf_string_eq },
  { "DEFVAR",		0, 0, pf_defvar },
  { "COPY-VAR",		0, 0, pf_copy_var },
  { "COERCE-VAR",	0, 0, pf_coerce_var },
  { (char *)NULL,	0, 0, (PFunHandler *)NULL }
};

PACKAGE_INITIALIZER (initialize_simple_functions)

void
initialize_simple_functions (Package *package)
{
  register int i;
  Symbol *sym;

  for (i = 0; simplefunc_table[i].tag != (char *)NULL; i++)
    {
      sym = symbol_intern_in_package (package, simplefunc_table[i].tag);
      sym->type = symtype_FUNCTION;
      sym->values = (char **)(&simplefunc_table[i]);
    }
}

static void
pf_prog (PFunArgs)
{
  if ((body != (PAGE *)NULL) && (!empty_string_p (body->buffer)))
    bprintf_insert (page, start, "%s", body->buffer + 1);
}

static void
pf_concat (PFunArgs)
{
  register int i = 0;
  char *temp;

  while ((temp = get_positional_arg (vars, i)) != (char *)NULL)
    {
      bprintf_insert (page, start, "%s", temp);
      start += strlen (temp);
      i++;
    }
}

static void
pf_string_eq (PFunArgs)
{
  char *arg1 = mhtml_evaluate_string (get_positional_arg (vars, 0));
  char *arg2 = mhtml_evaluate_string (get_positional_arg (vars, 1));
  int caseless_p = var_present_p (vars, "CASELESS");

  if (((empty_string_p (arg1)) && (empty_string_p (arg2))) ||
      ((arg1 && arg2) &&
       (((!caseless_p) && (strcmp (arg1, arg2) == 0)) ||
	((caseless_p) && (strcasecmp (arg1, arg2) == 0)))))
    {
      bprintf_insert (page, start, "true");
      *newstart = start + 4;
    }

  if (arg1) free (arg1);
  if (arg2) free (arg2);
}

static void
pf_defvar (PFunArgs)
{
  char *name = mhtml_evaluate_string (get_positional_arg (vars, 0));

  if (!empty_string_p (name))
    {
      char *current_value = pagefunc_get_variable (name);

      if (empty_string_p (current_value))
	{
	  char *new_value;

	  new_value = mhtml_evaluate_string (get_positional_arg (vars, 1));
	  if (!empty_string_p (new_value))
	    pagefunc_set_variable (name, new_value);

	  if (new_value) free (new_value);
	}
    }

  if (name) free (name);
}

/* <copy-var source dest dest dest dest> */
static void
pf_copy_var (PFunArgs)
{
  char *source_name = mhtml_evaluate_string (get_positional_arg (vars, 0));

  if (!empty_string_p (source_name))
    {
      Symbol *source = symbol_lookup (source_name);

      if (source != (Symbol *)NULL)
	{
	  register int i = 1;
	  char *dest_name = (char *)NULL;
	  int done = 0;

	  while (!done)
	    {
	      dest_name = mhtml_evaluate_string (get_positional_arg (vars, i));
	      i++;

	      if (dest_name == (char *)NULL)
		{
		  done = 1;
		  continue;
		}

	      if (!empty_string_p (dest_name))
		{
		  Symbol *dest = symbol_intern (dest_name);

		  if (dest != source)
		    {
		      Package *temp = symbol_get_package ((char *)NULL);
		      Symbol *copy = symbol_copy (source, temp);

		      copy = symbol_rename (copy, dest->name);
		      symbol_move (copy, dest->package);
		      symbol_destroy_package (temp);
		    }
		}
	      free (dest_name);
	    }
	}
    }

  if (source_name != (char *)NULL) free (source_name);
}

/* <coerce-var source type=BINARY|STRING> */
static void
pf_coerce_var (PFunArgs)
{
  char *source_name = mhtml_evaluate_string (get_positional_arg (vars, 0));

  if (!empty_string_p (source_name))
    {
      Symbol *source;

      source = symbol_lookup (source_name);

      if (source != (Symbol *)NULL)
	{
	  int dest_type = -1;

	  {
	    char *type_name = mhtml_evaluate_string (get_value (vars, "type"));

	    if (!empty_string_p (type_name))
	      {
		if (strcasecmp (type_name, "binary") == 0)
		  dest_type = symtype_BINARY;
		else if (strcasecmp (type_name, "string") == 0)
		  dest_type = symtype_STRING;
	      }

	    if (type_name != (char *)NULL) free (type_name);
	  }

	  if ((source->type != dest_type) && (dest_type != -1))
	    {
	      /* Do the coercion. */
	      switch (dest_type)
		{
		case symtype_STRING:
		  switch (source->type)
		    {
		    case symtype_STRING:
		    case symtype_FUNCTION:
		      break;

		    case symtype_BINARY:
		      {
			Datablock *block = (Datablock *)source->values;
			char *data = (char *)xmalloc (2 + block->length);

			memcpy (data, block->data, block->length);
			data[block->length] = '\0';
			free (block->data);
			free (block);
			source->values_index = 1;
			source->values_slots = 2;
			source->values =
			  (char **)xmalloc (2 * sizeof (char *));
			source->values[0] = data;
			source->values[1] = (char *)NULL;
			source->type = symtype_STRING;
		      }
		      break;
		    }
		  break;

		case symtype_BINARY:
		  switch (source->type)
		    {
		    case symtype_BINARY:
		    case symtype_FUNCTION:
		      break;

		    case symtype_STRING:
		      {
			register int i;
			Datablock *block;
			BPRINTF_BUFFER *buffer;
			  
			block = (Datablock *)xmalloc (sizeof (Datablock));
			buffer = bprintf_create_buffer ();
			
			for (i = 0; i < source->values_index; i++)
			  {
			    bprintf (buffer, "%s%s",
				     i != 0 ? "\n" : "", source->values[i]);
			    free (source->values[i]);
			  }
			  
			block->data = buffer->buffer;
			block->length = buffer->bindex;
			free (buffer);
			free (source->values);
			source->values_index = 0;
			source->values = (char **)block;
			source->type = symtype_BINARY;
		      }
		      break;
		    }
		  break;
		}
	    }
	}
    }

  if (source_name != (char *)NULL) free (source_name);
}



	  

	  
