text: /*
      File: exprobj.c
      Auth: Brian Allen Vanderburg II
      Date: Tuesday, April 29, 2003
      Desc: Functions for the exprObj type
  
      This file is part of ExprEval.
  */
  
  /* Includes */
  #include "exprincl.h"
  
  #include "exprpriv.h"
  #include "exprmem.h"
  
  /* Internal functions */
  static void exprFreeNodeData(exprNode * node);
  
  
  /* Function to create an expression object */
  int exprCreate(exprObj ** obj, exprFuncList * flist, exprValList * vlist, exprValList * clist, exprBreakFuncType breaker, void *userdata)
  {
  	exprObj *tmp;
  
  	/* Allocate memory for the object */
  	tmp = exprAllocMem(sizeof(exprObj));
  
  	if (tmp == NULL)
  		return EXPR_ERROR_MEMORY;
  
  
  	/* Assign data */
  	tmp->flist = flist;
  	tmp->vlist = vlist;
  	tmp->clist = clist;
  	tmp->breakerfunc = breaker;
  	tmp->userdata = userdata;
  	tmp->breakcount = 100000;	/* Default breaker count setting */
  	tmp->breakcur = 0;
  
  	/* Update pointer */
  	*obj = tmp;
  
  	return EXPR_ERROR_NOERROR;
  }
  
  
  /* Free the expression */
  int exprFree(exprObj * obj)
  {
  	if (obj == NULL)
  		return EXPR_ERROR_NOERROR;
  
  	/* First free the node data */
  	exprFreeNodeData(obj->headnode);
  	exprFreeMem(obj->headnode);
  
  	/* Free ourself */
  	exprFreeMem(obj);
  
  	return EXPR_ERROR_NOERROR;
  }
  
  /* Clear expression, keep lists, etc */
  int exprClear(exprObj * obj)
  {
  	if (obj == NULL)
  		return EXPR_ERROR_NOERROR;
  
  	/* Free the node data only, keep function, variable, constant lists */
  	exprFreeNodeData(obj->headnode);
  	exprFreeMem(obj->headnode);
  
  	obj->headnode = NULL;
  	obj->parsedbad = 0;
  	obj->parsedgood = 0;
  
  	return EXPR_ERROR_NOERROR;
  }
  
  
  /* Get functions to get information about the expression object */
  
  /* Get the function list */
  exprFuncList *exprGetFuncList(exprObj * obj)
  {
  	return (obj == NULL) ? NULL : obj->flist;
  }
  
  /* Get the variable list */
  exprValList *exprGetVarList(exprObj * obj)
  {
  	return (obj == NULL) ? NULL : obj->vlist;
  }
  
  /* Get the constant list */
  exprValList *exprGetConstList(exprObj * obj)
  {
  	return (obj == NULL) ? NULL : obj->clist;
  }
  
  /* Get the breaker function */
  exprBreakFuncType exprGetBreakFunc(exprObj * obj)
  {
  	return (obj == NULL) ? NULL : obj->breakerfunc;
  }
  
  /* Check for break status */
  int exprGetBreakResult(exprObj * obj)
  {
  	if (obj == NULL)
  		return 0;
  
  	if (obj->breakerfunc == NULL)
  		return 0;
  
  	return (*(obj->breakerfunc)) (obj);
  }
  
  /* Get the user data */
  void *exprGetUserData(exprObj * obj)
  {
  	return (obj == NULL) ? NULL : obj->userdata;
  }
  
  
  /* Set functions to set certain data */
  
  /* Set user data */
  void exprSetUserData(exprObj * obj, void *userdata)
  {
  	if (obj)
  		obj->userdata = userdata;
  }
  
  
  /* Set breaker count */
  void exprSetBreakCount(exprObj * obj, int count)
  {
  	if (obj) {
  		/* If count is negative, make it positive */
  		if (count < 0)
  			count = -count;
  
  		obj->breakcount = count;
  
  		/* Make sure the current value is not bigger than count */
  		if (obj->breakcur > count)
  			obj->breakcur = count;
  	}
  }
  
  /* Get error position */
  void exprGetErrorPosition(exprObj * obj, int *start, int *end)
  {
  	if (obj) {
  		if (start)
  			*start = obj->starterr;
  
  		if (end)
  			*end = obj->enderr;
  	}
  }
  
  /* This function will free a node's data */
  static void exprFreeNodeData(exprNode * node)
  {
  	int pos;
  
  	if (node == NULL)
  		return;
  
  	/* free data based on type */
  	switch (node->type) {
  	case EXPR_NODETYPE_ADD:
  	case EXPR_NODETYPE_SUBTRACT:
  	case EXPR_NODETYPE_MULTIPLY:
  	case EXPR_NODETYPE_DIVIDE:
  	case EXPR_NODETYPE_EXPONENT:
  	case EXPR_NODETYPE_NEGATE:
  	case EXPR_NODETYPE_MULTI:
  		/* Free operation data */
  		if (node->data.oper.nodes) {
  			for (pos = 0; pos < node->data.oper.nodecount; pos++)
  				exprFreeNodeData(&(node->data.oper.nodes[pos]));
  
  			exprFreeMem(node->data.oper.nodes);
  		}
  
  		break;
  
  
  	case EXPR_NODETYPE_VALUE:
  		/* Nothing to free for value */
  		break;
  
  	case EXPR_NODETYPE_VARIABLE:
  		/* Nothing to free for variable */
  		break;
  
  	case EXPR_NODETYPE_FUNCTION:
  		/* Free data of each subnode */
  		if (node->data.function.nodes) {
  			for (pos = 0; pos < node->data.function.nodecount; pos++)
  				exprFreeNodeData(&(node->data.function.nodes[pos]));
  
  			/* Free the subnode array */
  			exprFreeMem(node->data.function.nodes);
  		}
  
  		/* Free reference variable list */
  		if (node->data.function.refs)
  			exprFreeMem(node->data.function.refs);
  
  		break;
  
  	case EXPR_NODETYPE_ASSIGN:
  		/* Free subnode data */
  		if (node->data.assign.node) {
  			exprFreeNodeData(node->data.assign.node);
  
  			/* Free the subnode */
  			exprFreeMem(node->data.assign.node);
  		}
  
  		break;
  	}
  }
  