 /*
  * Khoros: $Id: print.c,v 1.3 1992/03/25 17:31:18 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: print.c,v 1.3 1992/03/25 17:31:18 dkhoros Exp $";
#endif

 /*
  * $Log: print.c,v $
 * Revision 1.3  1992/03/25  17:31:18  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "expr.h"
#include "y.tab.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    	    file name: print.c			      <<<<
   >>>>                                                       <<<<
   >>>>		Various Private Print Routines		      <<<<
   >>>>		For the xvexpr Library			      <<<<
   >>>>                                                       <<<<
   >>>>             _xve_print_symbol()			      <<<<
   >>>>             _xve_print_symlist()		      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



static     int _xve_recursive();

/************************************************************
*
*  Routine Name: print_symlist()
*
*       Purpose: print_symlist() is called to actually print
*		 out the symbols.  print_symlist() is called
*		 recursively just like eval_symlist() to print
*		 out the symbols that are used to represent an
*		 expression.
*
*        Input:  file     - the file stream to print to
*		 symlist  - the current symbol to be printed
*		 abort	  - whether to abort when an undefined variable
*			    is found
*
*       Output:  prints to stderr the symbol & symlist
*
*   Written By:  Mark Young
*
*
************************************************************/


static SymbolList *print_symlist(file, symlist, abort)

FILE	   *file;
SymbolList *symlist;
int	   abort;
{
	int	   i;
	Symbol	   *symbol, *temp;
	char	   error[LENGTH];


	/*
	 *  If the current symlist is NULL then the endlist will become
	 *  the beginning of the symbol list, so we just return it.
	 */
	if (symlist == NULL)
	{
	   sprintf(error,"Error! end of symbol list encountered, but more \
expected.");
	   vexpr_error(error);
	}

	symbol = symlist->symbol;
	switch (symbol->type)
	{
	   case NUMBER:
		fprintf(file,"%g", symbol->Value);
		symlist = symlist->next;
		break;

	   case STRING:
		fprintf(file,"%s", symbol->String);
		symlist = symlist->next;
		break;

	   case VARIABLE:
	   case CONSTANT:
	   case EXPRESSION:
		fprintf(file,"%s", symbol->name);
		symlist = symlist->next;
		break;

	   case UFUNCTION:
	   case FUNCTION:
		fprintf(file,"%s(", symbol->name);

		symlist = symlist->next;
	        for (i = 0; i < symbol->num; i++)
		{
		    symlist = print_symlist(file, symlist, abort);

		    if (i+1 < symbol->num)
		       fprintf(file,",");
		}

		fprintf(file,")");
		break;

	   case OPERATOR:
		symlist = symlist->next;

		if (symbol->Operator == STRCAT)
		{
		   temp = symlist->symbol;
		   if (temp->type != STRING && temp->type != OPERATOR)
		      fprintf(file,"$");
		   symlist = print_symlist(file, symlist, abort);

		   temp = symlist->symbol;
		   if (temp->type != STRING && temp->type != OPERATOR)
		      fprintf(file,"$");
		   symlist = print_symlist(file, symlist, abort);
		}
		else
		{
		   fprintf(file,"(");
		   symlist = print_symlist(file, symlist, abort);

		   fprintf(file,"%s", symbol->name);
		   symlist = print_symlist(file, symlist, abort);

		   fprintf(file,")");
		}
		break;

	   case UOPERATOR:
		fprintf(file,"%s", symbol->name);
		symlist = symlist->next;
		symlist = print_symlist(file, symlist, abort);
		break;

	   case INSTRUCTION:
	        if (symbol->Instruction == IF)
		{
		   fprintf(file,"(");
		   symlist = symlist->next;
		   symlist = print_symlist(file, symlist, abort);
		   fprintf(file,") ? (");
		   symlist = print_symlist(file, symlist, abort);
		   fprintf(file,") : (");
		   symlist = print_symlist(file, symlist, abort);
		   fprintf(file,")");
		}
		break;

	   case UNDEFINED:
		if (abort)
		{
		   sprintf(error,"Error! Unknown variable or constant '%s'",
				symbol->name);
		   vexpr_error(error);
		}
		fprintf(file,"%s", symbol->name);
		symlist = symlist->next;
		break;

	   default:
		sprintf(error,"Error!  Unknown symbol type '%d'", symbol->type);
		vexpr_error(error);
		break;
	}
	return(symlist);
}



/************************************************************
*
*  Routine Name: _xve_print_symbol()
*
*       Purpose: _xve_print_symbol() is called when we want to print
*		 out a symbol.
*
*        Input:  file     - the file stream to print to
*		 symbol   - the current symbol to be printed
*		 abort	  - whether to abort when an undefined variable
*			    is found
*
*       Output:  prints to stderr the symbol & symlist
*
*   Written By:  Mark Young
*
*
************************************************************/


_xve_print_symbol(file, symbol, abort)

FILE   *file;
Symbol *symbol;
int    abort;
{
	int	   i;
	Symbol     *arg, result;
	SymbolList list, *symlist;
	char       error[LENGTH];


	/*
	 *  If the current symbol is NULL then print out an error
	 *  and abort.
	 */
	if (symbol == NULL)
	{
	   sprintf(error,"Error! NULL symbol list encountered.\n");
	   vexpr_error(error);
	}

 	if (symbol->type == VARIABLE)
	{
	   _xve_eval_symlist(symbol->symlist, &result, FALSE);

	   fprintf(file,"# Dependant expression '%s'\n", symbol->name);
	   fprintf(file,"# current evaluated value = %g\n", result.Value);
	   if (_xve_recursive(symbol))
	   {
	      fprintf(file,"# recursive base value = %g\n",
			result.Value, symbol->Value);
	   }
	   fprintf(file,"  %s = ", symbol->name);
	   (void) print_symlist(file, symbol->symlist, abort);
	   fprintf(file,"\n\n");
	}
	else if (symbol->type == EXPRESSION)
	{
	   fprintf(file,"# Simple expression '%s'\n", symbol->name);
	   if (symbol->symlist->symbol->type != NUMBER)
	   {
	      list.symbol = symbol;
	      list.next   = NULL;
	      _xve_eval_symlist(&list, &result, FALSE);
	      fprintf(file,"# current evaluated value = %g\n", result.Value);
	   }
	   fprintf(file,"%s = ", symbol->name);
	   (void) print_symlist(file, symbol->symlist, abort);
	   fprintf(file,"\n\n");
	}
	else if (symbol->type == UFUNCTION)
	{
	   fprintf(file,"# User defined function '%s()'\n", symbol->name);
	   fprintf(file,"  %s(", symbol->name);
	   symlist = symbol->symlist;
	   for (i = 0; i < symbol->num; i++)
	   {
	      arg = symlist->symbol; 
	      fprintf(file,"%s", arg->name);

	      if (i+1 < symbol->num)
	         fprintf(file,",");

	      symlist = symlist->next;
	   }
	   fprintf(file,") = ");
	   (void) print_symlist(file, symlist, abort);
	   fprintf(file,"\n\n");
	}
	else if (symbol->type == FUNCTION)
	{
	   fprintf(file,"# Pre-defined function '%s()'\n", symbol->name);
	   fprintf(file,"  %s(", symbol->name);
	   symlist = symbol->symlist;
	   for (i = 0; i < symbol->num; i++)
	   {
	      fprintf(file,"arg%1d", i);

	      if (i+1 < symbol->num)
	         fprintf(file,",");
	   }
	   fprintf(file,")\n\n");
	}
	else if (symbol->type == UNDEFINED)
	{
	   fprintf(file,"# Currently Undefined symbol '%s'\n", symbol->name);
	   list.symbol = symbol;
	   list.next   = NULL;
	   (void) print_symlist(file, &list, abort);
	   fprintf(file,"\n\n");
	}
	else
	{
	   fprintf(file,"# Unknown symbol type\n");
	   list.symbol = symbol;
	   list.next   = NULL;
	   (void) print_symlist(file, &list, abort);
	}
}

static int _xve_recursive(symbol, symlist)

Symbol *symbol;
Symbol *symlist;
{
	return(FALSE);
}



/************************************************************
*
*  Routine Name: _xve_print_symlist()
*
*       Purpose: _xve_print_symlist() is called when we want to print
*		 out the symbol list.
*
*        Input:  file     - the file stream to print to
*		 symlist  - the current symbol list to be printed
*		 abort	  - whether to abort when an undefined variable
*			    is found
*
*       Output:  prints to stderr the symlist
*
*   Written By:  Mark Young
*
*
************************************************************/


_xve_print_symlist(file, symlist, abort)

FILE	   *file;
SymbolList *symlist;
int	   abort;
{
	char  error[LENGTH];


	/*
	 *  If the current symlist is NULL then the endlist will become
	 *  the beginning of the symbol list, so we just return it.
	 */
	if (symlist == NULL)
	{
	   sprintf(error,"Error! NULL symbol list encountered.\n");
	   vexpr_error(error);
	}
	fprintf(file,"expression: ");
	(void) print_symlist(file, symlist, abort);
	fprintf(file,"\n");
}
