 /*
  * Khoros: $Id: readpoly.c,v 1.3 1992/03/20 23:29:42 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: readpoly.c,v 1.3 1992/03/20 23:29:42 dkhoros Exp $";
#endif

 /*
  * $Log: readpoly.c,v $
 * Revision 1.3  1992/03/20  23:29:42  dkhoros
 * VirtualPatch5
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 *            Copyright 1990 University of New Mexico
 *  
 *  Permission to use, copy, modify, distribute, and sell this
 *  software and its documentation for any purpose is hereby
 *  granted without fee, provided that the above copyright
 *  notice appear in all copies and that both that copyright
 *  notice and this permission notice appear in supporting docu-
 *  mentation, and that the name of UNM not be used in advertis-
 *  ing or publicity pertaining to distribution of the software
 *  without specific, written prior permission.  UNM makes no
 *  representations about the suitability 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 DAMAGES WHATSOEVER
 *  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 PERFORMANCE
 *  OF THIS SOFTWARE.
 *  
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "vinclude.h"	

static int dumppoly();
static int add_term();

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name: readpoly.c                             <<<<
   >>>>                                                       <<<<
   >>>>   description: junk for reading polynomial ascii      <<<<
   >>>>                equations                              <<<<
   >>>>                                                       <<<<
   >>>>      routines: readpoly				      <<<<
   >>>>                                                       <<<<
   >>>> modifications: see below                       	      <<<<
   >>>>                                                       <<<<
   >>>>          NOTE: this routine is not for public use!    <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

/***********************************************************************
*
*  Routine Name: readpoly()
*
*          Date: Thu Aug 30 09:41:13 MDT 1990
*        
*       Purpose: reads a file of polynomials and returns a group of
*		 arrays that describe the polynomials contained. This
*		 routine assumes that the arrays passed in are already
*		 malloced.  If array bounds as specified in dimr,dimc, and
*		 dims are exceeded, then an error will be returned.
*
*         Input: char *fname       - name of polynomial file with explicit
*			    	     path if necessary. 
*
*		 int dimr          - number of rows in all arrays passed in
*				     to this function.
*
*	 Output: struct poly_struct *poly
*			a structure containing information on polynomials
*			in the specified file.
*
*		 int npolys
*			number of polynomials read in.
*
*    Written By: Jeremy Worley 
*
* Modifications: Jeremy Worley 19 Feb 1992 09:17 MST
*                       explicitly declared poly_parse().
*
*                Jeremy Worley 09 Mar 1992 19:44 MST
*                       changed poly_parse() calls to dspl_parse()
*                       because sed scripts were added to remove 
*                       duplicate variable.
*
*                Jeremy Worley 19 Mar 1992 17:13 MST
*                       added support for the k-routines related to
*                       transport.  Specifically changed all FILE
*                       operations to operations that deal with kfile.
*
***********************************************************************/

#include "y.tab.h"
#include "vpoly.h"

extern int func_count;
extern kfile *kflptr;

struct polystack *stack;

int readpoly(fname,poly,dimr,npolys)
   char *fname;
   struct poly_struct *poly;
   int dimr, *npolys;
{
    char *program = "readpoly()";
    int dspl_parse();

/*
** open the requested file
*/

    kflptr=kfopen(fname,"r");
    if(kflptr==NULL){ 
       fprintf(stderr,"%s:  the file \"%s\" cannot be found.\n",program,fname);
       return(0);
    }

/*
** call the parser.  it will return a -1 if an error condition is detected.
** in this case, we will place nothing in the poly structure.
*/

    if(dspl_parse()==-1){
       (void)kfclose(kflptr);
       return(0);
    }

/*
** dump all of the polynomials
*/

    func_count=0;
    while(dumppoly(&(poly[func_count]))){
         func_count++;

         if(func_count>dimr){
           fprintf(stderr,"%s:  array allocation (%d) is not sufficient.\n",
                   program,dimr);
           (void)kfclose(kflptr);
           return(0);
         }
    }

    (void)kfclose(kflptr);

    *npolys = func_count;

    return(1);
}


/***********************************************************************
*
*  Routine Name: dumppoly()
*
*          Date: Fri Sep 14 14:04:56 MDT 1990
*        
*       Purpose: just a little routine that makes life alot easier to
*		 deal with.  it rearranges the stack into the format
*		 that readpoly returns.  
*
*         Input: 
*
*        Output: 
*
*    Written By: Jeremy Worley 
*
* Modifications: Mon Sep 24 14:40:01 MDT 1990 Jeremy Worley
*			modified to operate on the new structure
*		 Mon Nov 26 15:39:39 MST 1990 Jeremy Worley
*			modified to handle the nested term structure.
*
***********************************************************************/

static int dumppoly(poly)
  struct poly_struct *poly;
{
  char *program = "dumppoly()";

  struct polystack *node;
  struct polystack *polypop();
  int polypush();
  int tcount=0,scount=0,start,i,indx;

/*
** pop the function name off of the stack
*/

  node = polypop();
  if(node==NULL){
     return(0);
  }

  if(node->type!=WORD){
     fprintf(stderr,"%s:  polynomial stored on stack in wrong format.\n",
             program);
     return(0);
  }
  strcpy(poly->func_name,node->string);

/*
** pop the independant variable off of the stack
*/

  node = polypop();
  if(node==NULL){
     fprintf(stderr,"%s:  [1]polynomial stored on stack in wrong format.\n",
             program);
     return(0);
  }
  if(node->type!=WORD){
     fprintf(stderr,"%s:  [2]polynomial stored on stack in wrong format.\n",
             program);
     return(0);
  }
  strcpy(poly->indep_var,node->string);

/*
** pop coefficient, etc information off of the stack
*/
 
  while((node = polypop())!=NULL && node->type!=WORD){
    switch(node->type){
       case FUNC:   if(tcount>poly->tdim){
                      fprintf(stderr,"%s: too many terms in polynomial(%d).\n",
                               program,tcount);
                       return(0);
                    }

                    if(!add_term(poly,tcount,_FUNCTION,node->value,0.0,
                       (int)node->order,node->string,node->fname)){
                       return(0);
                    }

                    tcount++;
                    break;

       case EXPON:  if(tcount>poly->tdim){
                      fprintf(stderr,"%s: too many terms in polynomial(%d).\n",
                               program,tcount);
                       return(0);
                    }
                    if(!add_term(poly,tcount,_STDTERM,node->value,node->order,
                       0,node->string,"none")){
                       return(0);
                    }

                    tcount++;
                    break;

       case '*':    break;

       case COUNT:  start = MAX(scount-1,0);
                    poly->nterms[2*start] = (int)node->value;
                    for(i=0;i<poly->nterms[2*start];i++){
                        node = polypop();

                        if(node->type==FUNC){
                           if(!add_term(poly,tcount,_FUNCTION,node->value,0.0,
                              (int)node->order,node->string,node->fname)){
                              return(0);
                           }
                        }else{
                           if(!add_term(poly,tcount,_STDTERM,node->value,
                              node->order, 0,node->string,"none")){
                              return(0);
                           }
                        }
                        tcount++;
                    }

                    break;

       case ']':    scount++;
                    break;

       case '/':    if(2*scount+1>poly->sdim){
                       fprintf(stderr,"%s:  too many stages in function.\n",
                               program);
                       return(0);
                    }

                    start = MAX(scount-1,0);

                    node = polypop();
                    poly->nterms[2*start+1] = (int)node->value;

                    node = polypop();
                    poly->nterms[2*start] = (int)node->value;
 
                    for(i=0;i<poly->nterms[2*start+1];i++){
                        node = polypop();
                        indx = tcount + poly->nterms[2*start]+i;
                        if(node->type==FUNC){
                           if(!add_term(poly,indx,_FUNCTION,node->value,0.0,
                              (int)node->order,node->string,node->fname)){
                              return(0);
                           }
                        }else{
                           if(!add_term(poly,indx,_STDTERM,node->value,
                              node->order, 0,node->string,"none")){
                              return(0);
                           }
                        }
                    }
                    for(i=0;i<poly->nterms[2*start];i++){
                        node = polypop();
                        indx = tcount + i;
                        if(node->type==FUNC){
                           if(!add_term(poly,indx,_FUNCTION,node->value,0.0,
                              (int)node->order,node->string,node->fname)){
                              return(0);
                           }
                        }else{
                           if(!add_term(poly,indx,_STDTERM,node->value,
                              node->order, 0,node->string,"none")){
                              return(0);
                           }
                        }
                    }
                    tcount += poly->nterms[2*start] + poly->nterms[2*start+1]; 
                    break;
                    
       default:     fprintf(stderr,"unknown type = %d\n",node->type);
                    break;
    }
  }

  poly->stages = scount;
  if(node!=NULL) (void)polypush(node);
 
  return(1);
}


/***********************************************************************
*
*  Routine Name: add_term()
*
*          Date: Mon Nov 26 23:16:29 MST 1990
*        
*       Purpose: adds a term semi-intelligently.  that is, it will adjust
*		 the size of the term array and change tdim if it is
*		 not big enough.  
*
*         Input: poly	- structure to act on
*		 pos	- position to place the term in poly->terms[]
*		 type	- type of term
*		 coef	- coefficient value
*		 expon	- exponent or power
*		 delay	- delay if it is a function term
*		 varname- variable name
*		 fname  - function name 
*
*        Output: 1 - successful
*		 0 - failed  
*
*    Written By: Jeremy Worley 
*
* Modifications:
*
***********************************************************************/

static int add_term(poly,pos,type,coef,expon,delay,varname,fname)
    struct poly_struct *poly;
    int    pos,type,delay;
    float  coef,expon;
    char   *varname,*fname;
{
    char *program = "readpoly.add_term";
    int  dims,newsize,j;

    dims = poly->sdim;

/*
** we won't allow null junk to be passed in initially...a basic
** poly is a must.
*/

    if(poly==NULL){
       fprintf(stderr,"%s:  NULL poly not allowed.\n",program);
       return(0);
    }

    if(varname==NULL){
       fprintf(stderr,"%s:  NULL varname not allowed.\n",program);
       return(0);
    }

/*
** check poly->tdim again pos...realloc if necessary.  we'll knock it up
** by, say, _ADJSIZE (probably about 10), each time its necessary, so we
** don't have to do it every time.
*/

    newsize = pos + _ADJSIZE;
    if(poly->terms==NULL){
        if((poly->terms = (struct term_struct *)kmalloc(newsize *
                        sizeof(struct term_struct)))==NULL){
           return(0);
        }
        for(j=0;j<newsize;j++){
            if((poly->terms[j].varname = (char *)kmalloc(dims*sizeof(char)
                 ))==NULL){
               return(0);
            }
            if((poly->terms[j].fname = (char *)kmalloc(dims*sizeof(char)
                 ))==NULL){
               return(0);
            }
        }
        poly->tdim = newsize;
    }else if(poly->tdim<=pos){
        poly->terms = (struct term_struct *)krealloc((char *)poly->terms,
                      newsize * sizeof(struct term_struct));
        if(poly->terms==NULL){
           fprintf(stderr,"%s:  memory reallocation failed.\n",program);
           return(0);
        }
        for(j=poly->tdim;j<newsize;j++){
            if((poly->terms[j].varname = (char *)kmalloc(dims*sizeof(char)
                 ))==NULL){
               return(0);
            }
            if((poly->terms[j].fname = (char *)kmalloc(dims*sizeof(char)
                 ))==NULL){
               return(0);
            }
        }
        poly->tdim = newsize;
    } 
    
/*
** now that all that nonsense is out of the way, copy the information
** into the appropriate locations
*/

 
     if(type==_FUNCTION){
        poly->terms[pos].type = _FUNCTION;
        poly->terms[pos].coef = coef;
        poly->terms[pos].delay = delay;
        strcpy(poly->terms[pos].varname,varname);
        strcpy(poly->terms[pos].fname,fname);
     }else{
        poly->terms[pos].type = _STDTERM;
        poly->terms[pos].coef = coef;
        poly->terms[pos].expon = expon;
        strcpy(poly->terms[pos].varname,varname);
     }
     
     return(1);
}
 
/***********************************************************************
*
*  Routine Name: polypush()
*
*          Date: Fri Sep 14 14:06:31 MDT 1990
*        
*       Purpose: pushes a polystack structure on to the stack.  
*
*         Input: 
*
*        Output: 
*
*    Written By: Jeremy Worley 
*
* Modifications: Mon Nov 26 15:38:23 MST 1990 Jeremy Worley
*			added support for the new structure which contains
*			an fname entry for function name.
*
***********************************************************************/

int polypush(element)
    struct polystack *element;
{
    struct polystack *temp;

    if(element!=NULL){
       temp = (struct polystack *)kmalloc(sizeof(struct polystack));
       temp->type = element->type;
       temp->value = element->value;
       temp->order = element->order;
       if(element->fname!=NULL){
          strcpy(temp->fname,element->fname);
       }
       if(element->string!=NULL){
          strcpy(temp->string,element->string);
       }
       temp->next = stack;
       stack = temp;
       return(1);
    } else {
       return(0);
    }
}

/***********************************************************************
*
*  Routine Name: polypop()
*
*          Date: Fri Sep 14 14:07:34 MDT 1990
*        
*       Purpose: removes top of polystack and returns it.  
*
*         Input: 
*
*        Output: 
*
*    Written By: Jeremy Worley 
*
* Modifications:
*
***********************************************************************/

struct polystack *polypop()
{
    struct polystack *element;

    if(stack!=NULL){
       element = stack;
       stack = stack->next;
       return(element);
    }else{
       element = NULL;
       return(element);
    }
}
