Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/polyval/
Upload File :
Current File : /usr/home/beeson/MathXpert/polyval/termstr.c

/* M. Beeson, for Mathpert
Code to convert terms to string form and back to terms
7.1.94 original date
9.23.95 code last modified
1.28.98
8.19.07 modified set_atom_valuepointer for EULERGAMMA
9.29.14 modified str_term and term_str to account for unsigned short not being 2 bytes on the Mac.
*/

#include <string.h> /* memset */
#include <assert.h>


#include "terms.h"
#include "constant.h"
#include "termstr.h"
#include "defns.h"
#include "vaux.h"

static void set_atom_valuepointer(term *t);
/*_____________________________________________________________*/
int termstr(term t, int n, unsigned short *buffer)
/* write a packed form of t into buffer that can be
read by strterm.  Don't use more than n bytes.
Return -1 for buffer not long enough.
Otherwise return the number of bytes of buffer used.
The packed form written into buffer is NOT null-terminated.
These strings CAN contain zeros, because numbers
can contain null bytes, and also because numbers are introduced by the zero
functor and atoms have zero arity byte.
   This representation is not suitable for use in writing
to files, because (i) it will not be portable to architectures
that write numbers with the other byte first, and (ii)
the strings produced can contain the EOF character as one
of the functors.
*/
{ unsigned short m,i,j;
  int k,count;
  if(ATOMIC(t))
     { if(n < 3*sizeof(short))
          return -1;
       buffer[0] = FUNCTOR(t);
       buffer[1] = ISATOM(t) ? 0 : 1;
       buffer[2] = t.info;
       if(ISATOM(t))
          return 3*sizeof(short);
       /* Now t is an object */
       buffer += 3;
       switch(TYPE(t))
          { case INTEGER:
               if(n < 3*sizeof(short) + sizeof(long))
                  return -1;
               *((long *) buffer) = INTDATA(t);
               return 3*sizeof(short) + sizeof(long);   // 10 if longs are 4 bytes, 14 if they are 8 bytes
            case BIGNUM:
               { bignum b = BIGNUMDATA(t);
                 if(n < (unsigned short)( 8 + b.ln * sizeof(digit)))
                    return -1;
                 *buffer = b.ln;
                 ++buffer;
                 memcpy(buffer,b.val,b.ln * sizeof(digit));
                 return b.ln * sizeof(digit) + 4*sizeof(short);
               }
            case DOUBLE:
               if(n < 3*sizeof(short)  + sizeof(double))
                  return -1;
               *((double *) buffer) = DOUBLEDATA(t);
               return 3*sizeof(short)  + sizeof(double);
            default:
               assert(0);
          }
     }
  m = ARITY(t);
  if(n < 8)
     return -1;
  buffer[0] = FUNCTOR(t);
  buffer[1] = ARITY(t);
  buffer[2] = t.info;
  buffer +=3;
  j = n-6;
  count = 6;
  for(i=0;i<m;i++)
    { k = termstr(ARG(i,t),j,buffer);
      if(k== -1)
         return -1;
      j -= (unsigned short) k;
      count +=k;
      buffer += k/sizeof(unsigned short);   /* k is in bytes, buffer is a pointer to unsigned short */
    }
  return count;
}

/*_______________________________________________________________*/
term strterm(unsigned short *buffer, unsigned short **rest)
/* buffer contains a string packed by termstr.  Recover
and return the term. Return in **rest a pointer to the
first unread part of the buffer. */
{ unsigned short i,f,n;
  term ans;
  unsigned short *next;
  long k;
  f = buffer[0];
  n = buffer[1];
  SETFUNCTOR(ans,f,n);
  if(n > 0 && f != 0)
     { /* a compound term */
       ans = make_term(f,n);
       /* have to do this before setting ans.info, else
          make_term wipes out ans.info */
     }
  ans.info = buffer[2];
  buffer +=3;
  if(n==0 && f != 0) /* an atom */
     { *rest = buffer;
       set_atom_valuepointer(&ans);
       return ans;
     }
  if(n==1 && f==0) /* an object */
     { switch(TYPE(ans))
          { case INTEGER:
               k = *((long *) buffer);
               //  on the Mac, longs are 8 and shorts are 2
               *rest = buffer + sizeof(long)/sizeof(unsigned short);
               return  make_int(k); /* uses static space for small k */
            case DOUBLE:
               *rest = buffer + sizeof(double)/sizeof(unsigned short);
               return make_double(*((double *) buffer));
            case BIGNUM:
               { bignum b;
                 b.ln = *buffer;
                 ++buffer;
                 b.val = callocate(b.ln,sizeof(digit));
                 if(b.val == NULL)
                    { nospace();
                      SETFUNCTOR(ans,ILLEGAL,0);
                      return ans;
                    }
                 memcpy(b.val,buffer,b.ln*sizeof(digit));
                 *rest = buffer + b.ln*sizeof(digit)/sizeof(unsigned short);
                 return make_bignum(b);
               }
            default: assert(0);
          }
     }
  /* Now it's a compound term */
  /* Space for the args has been allocated by make_term above */
  for(i=0;i<n;i++)
     { ARGREP(ans,i,strterm(buffer,&next));
       buffer = next;
     }
  *rest = buffer;
  return ans;
}

/*___________________________________________________________*/
unsigned termsize(term t)
/* return the number of bytes termstr will need to convert t
to a string */
{ unsigned ans;
  unsigned short n,i;
  if(ISATOM(t))
     return 6;
  if(OBJECT(t))
     { switch(TYPE(t))
          { case INTEGER:
               return 3*sizeof(short) + sizeof(long);
            case DOUBLE:
               return 3*sizeof(short)  + sizeof(double);
            case BIGNUM:
               return 4*sizeof(short) + BIGNUMDATA(t).ln * sizeof(digit);
            default:
               assert(0);
          }
     }
  n = ARITY(t);
  ans = 3*sizeof(short);
  for(i=0;i<n;i++)
     ans += termsize(ARG(i,t));
  return ans;
}

/*____________________________________________________________________*/
static void set_atom_valuepointer(term *t)
/* *t is an atom; set the t.args field to point to the
value of t.  See set_valuepointers in defns.c.  Since
this function is in polyval.dll, the values of pi and e
will be on the local heap of polyval.dll now instead of
on the local heap of automode.dll.
*/
{ int nvariables = get_nvariables();
  term *varlist = get_varlist();
  unsigned f = FUNCTOR(*t);
  int i;
  assert(ISATOM(*t));
  for(i=0;i<nvariables;i++)
      { if(f == FUNCTOR(varlist[i]))
           { t->args = varlist[i].args;
             return;
           }
      }
  switch(f)
      { case PI_ATOM:
           t->args = pi_term.args;
           return;
        case 'e':
           t->args = eulere.args;
           return;
        case EULERGAMMA:
           t->args = eulergamma.args;
           return;
        case 'i':
           t->args = complexi.args;
           return;
        case BOUNDED_OSCILLATIONS:
        case UNBOUNDED_OSCILLATIONS:
        case UNDEFINED:            /* no value pointer for undefined */
        case INFINITYFUNCTOR:             /* no value pointer for infinity  */
        case FALSEFUNCTOR:         /* no value pointer for false,true,left,right */
        case TRUEFUNCTOR:
        case LEFT:
        case RIGHT:
        case ILLEGAL:
        case VAR:
           return;     /* no value pointer */
        default:
           assert(0);  /* you should have found the atom in varlist */
      }
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists