/* $Header: /afs/athena.mit.edu/astaff/project/atdev/src/fmax/RCS/util.c,v 1.8 91/03/05 09:13:41 dot Exp $ */

/*******************************************************************
  Copyright (C) 1990 by the Massachusetts Institute of Technology

   Export of this software from the United States of America is assumed
   to require a specific license from the United States Government.
   It is the responsibility of any person or organization contemplating
   export to obtain such a license before exporting.

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
distribute this software and its documentation for any purpose and
without fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright notice and
this permission notice appear in supporting documentation, and that
the name of M.I.T. not be used in advertising or publicity pertaining
to distribution of the software without specific, written prior
permission.  M.I.T. makes no representations about the suitability of
this software for any purpose.  It is provided "as is" without express
or implied warranty.

***************************************************************** */

/*
 *
 *    G N U P L O T  --	 util.c
 *
 *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 */

#include <ctype.h>
#include <setjmp.h>
#include <memory.h>
#include <errno.h>
#include "datatypes.h"
#include "fmax.h"
#include "fmaxplot.h"

extern int setOptFlag;
extern BOOLEAN screen_ok;
    /* TRUE if command just typed; becomes FALSE whenever we
	send some other output to screen.  If FALSE, the command line
	will be echoed to the screen before the ^ error message. */

dispval(fp,val)
FILE *fp;
Value *val;
{
  int i;
  
  if (setOptFlag & (1 << DISPLAYVAL)) {
       switch(val->type) {
	  case integer:
	    fprintf(fp,"%d",val->i.i);
	    break;
	  case real:
	    fprintf(fp,"%g",val->r.r);
	    break;
	  case complex:
	    if (val->c.c.i != 0.0 )
		 fprintf(fp,"{%g, %g}",
			 val->c.c.r,val->c.c.i);
	    else
		 fprintf(fp,"%g", val->c.c.r);
	    break;
	  case array:
	    fprintf(fp,"[");
	    for(i=0; i<val->a.N-1; i++) {
		 dispval(fp,&(val->a.vals[i]));
		 fprintf(fp,", "); }
	    dispval(fp,&(val->a.vals[i]));
	    fprintf(fp,"]");
	    break;
	  case deffunc:
	    fprintf(fp,"user defined function");
	    break;
	  case primfunc:
	    fprintf(fp,"primitive function");
	    break;
	  default:
	    internalerr("unknown type in dispval()");
       }
  }
}


double
realpart(val)	/* returns the real part of val */
Value *val;
{
    switch(val->type) {
	case integer:
	    return((double) val->i.i);
	case complex:
	    return(val->c.c.r);
    }
    internalerr("unknown type in realpart()");
    /* NOTREACHED */
}


double
imagpart(val)	/* returns the imag part of val */
Value *val;
{
    switch(val->type) {
	case integer:
	    return(0.0);
	case complex:
	    return(val->c.c.i);
    }
    internalerr("unknown type in imagpart()");
    /* NOTREACHED */
}



double
magnitude(val)	    /* returns the magnitude of val */
Value *val;
{
    double sqrt();

    switch(val->type) {
	case integer:
	    return((double) abs(val->i.i));
	case complex:
	    return(sqrt(val->c.c.r * val->c.c.r +
			val->c.c.i * val->c.c.i));
    }
    internalerr("unknown type in magnitude()");
    /* NOTREACHED */
}



double
angle(val)	/* returns the angle of val */
Value *val;
{
    double atan2();

    switch(val->type) {
	case integer:
	    return((val->i.i > 0) ? 0.0 : Pi);
	case complex:
	    if (val->c.c.i == 0.0) {
		if (val->c.c.r >= 0.0)
		    return(0.0);
		else
		    return(Pi);
	    }
	    return(atan2(val->c.c.i,val->c.c.r));
    }
    internalerr("unknown type in angle()");
    /* NOTREACHED */
}


Value *
makecmplx(a,realpart,imagpart)
Value *a;
double realpart, imagpart;
{
    a->type = complex;
    a->c.c.r = realpart;
    a->c.c.i = imagpart;
    return(a);
}


Value *
makereal(a,r)
Value *a;
double r;
{
  a->type = real;
  a->r.r = r;
  return(a);
}

Value *
makeint(a,i)
Value *a;
int i;
{
    a->type = integer;
    a->i.i = i;
    return(a);
}

Value *
makearray(a,n)
Value *a;
int n;
{
  a->type = array;
  a->a.N = n;
  a->a.vals = (Value *) malloc(n * sizeof(Value));
  return(a);
}

/* if the value is an array, recursively frees up allocated memory 
 * does NOT free the node *a itself. */
freevalue(a)
Value *a;
{
  register int i;

  if ((a->type == array) && (a->a.N != 0) && (a->a.vals != NULL)) {
    for(i=0;i<a->a.N;i++)
      freevalue(&a->a.vals[i]);
    free(a->a.vals);
  }
}



extern jmp_buf errenv; 

void streamerr(s,err)
Stream *s;
char *err;
{
  int i;

  if (s->type == filestream) {
    fprintf(s->err,"\nError in file %s, line %d, pos %d\n\t%s\n",
	    s->fname,s->linenum,s->charnum,err);
    s->line[s->charnum] = '\0';  /* force ignore rest of this line */
  }
  else {
    fputs(s->line,s->err);
    /* putc('\n',s->err); */
    for(i=0; i<s->charnum; i++) putc((s->line[i] == '\t')?'\t':' ',s->err);
    putc('^',s->err);
    putc('\n',s->err);
    fputs(err,s->err);
    fputs("\n",s->err);
    longjmp(errenv,TRUE);
  }
}
 

void oserr(str)
char str[];
{
  extern int errno,sys_nerr;
  extern char *sys_errlist[];

    fprintf(stderr,"\tfmax: Operating system error: %s\n",str);

    if (errno >= sys_nerr)
	fprintf(stderr, "\tunknown errno %d\n\n", errno);
    else
	fprintf(stderr,"\t(%s)\n\n",sys_errlist[errno]);

    longjmp(errenv, TRUE); /* bail out to command line */
}


void internalerr(str)
char str[];
{
    fprintf(stderr,"\tfmax: Internal error: %s\n\n",str);
    longjmp(errenv, TRUE); /* bail out to command line */
}


void runerr(str)
char str[];
{
    fprintf(stderr,"\tfmax: Runtime error: %s\n\n",str);
    longjmp(errenv, TRUE); /* bail out to command line */
}

extern Fmaxplot *plotList;

void removePlot(AtPlotWidget *p)
{

     Fmaxplot *tempPlot, *prev;

     /* We don't have to worry about the plot not being in the list */
     for (tempPlot = plotList, prev = (Fmaxplot *)NULL; 
	  tempPlot->theplot != *p;
	  prev = tempPlot, tempPlot = tempPlot->next)
	  ;

     if (prev != (Fmaxplot *)NULL) 
	  prev->next = tempPlot->next;
     else 
	  plotList = tempPlot->next;
     if (tempPlot->xpts)
	  XtFree(tempPlot->xpts);
     if (tempPlot->ypts)
	  XtFree(tempPlot->ypts);

     XtDestroyWidget (*p);
}


