Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/parser/
Upload File :
Current File : /usr/home/beeson/MathXpert/parser/dispfunc.c

/*  M. Beeson, for Mathpert
7.28.93 modified
3.12.99 last modified
1.9.00  removed pragma argsused; modified newfunctor.
7.22.00 added GreekString
10.02.02 modified GreekString on LITTLEGAMMA
9.14.03 removed include conio.h
6.30.04 changed "lam" to "lambda" to facilitate communication with Otter-lambda
9.5.04 modified atom_string to handle subscripts directly, eliminating dependence on varinfo.
       Moved the file to parser.dll
       5:20 pm modified atom_string again, to handle subscripts on Greek atoms.  
       and again at 9:15.
9.10.04  Added a case for FLOOR to functor_string.       
2.28.07  modified atom_string to subtract 1 from SUBSCRIPT, since e.g. x_0 has SUBSCRIPT bits 1.
         See SUBSCRIPTFUNCTOR in terms.h        
2.28.07  modified oem_atom_string similarly         
8.19.07  added EULERGAMMA to oem_atom_string and to atom_string.
8.28.07  made raw_mstring handle SUM. 
9.8.11  cast result of strlen to int  for 64-bit compilation without warnings
5.15.13 added BERNOULLI
5.21.13 added EULERNUMBER, rewrote GreekString
10.29.23 eliminated Iso-Latin1 for SEQ in favor of UTF-8
11.25.23 UTF-8 for LE, GE, and function names in functor_string; also
used UTF-8 for Greek atoms in atom_string and got rid of GreekString.
12.23.23  ARROWSTR, ZETASTR, etc.
12.30.23  missing "return" in atom_string at PI_ATOM
6.30.24 added APPROXEQ
11.14.24  made functor_string produce sgn for SG instead of sg
12.15.24  made functor_string produce "log", not "logb", regardless of the value of 'where'
*/

#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>    /* atoi  */


#include "charstr.h"  /* ALPHACHAR etc. */
#include "terms.h"
#include "constant.h"   /* externs for constant terms zero, one, etc. */
#include "functors.h"
#include "dispfunc.h" 
#define MAXATOMS 16
#define MAXFUNCTORS 16

/*___________________________________________________________________*/
static char *symbols[MAXATOMS];
static int nextatom;
static char *functors[MAXFUNCTORS];

static int nextfunctor;
/*______________________________________________________________________*/
static char latoms[] = {'a',0,'b',0,'c',0,'d',0,'e',0,'f',0,'g',0,
                        'h',0,'i',0,'j',0,'k',0,'l',0,'m',0,'n',0,
                        'o',0,'p',0,'q',0,'r',0,'s',0,'t',0,'u',0,
                        'v',0,'w',0,'x',0,'y',0,'z',0,'?',0};

static char uatoms[] = {'A',0,'B',0,'C',0,'D',0,'E',0,'F',0,'G',0,
                        'H',0,'I',0,'J',0,'K',0,'L',0,'M',0,'N',0,
                        'O',0,'P',0,'Q',0,'R',0,'S',0,'T',0,'U',0,
                        'V',0,'W',0,'X',0,'Y',0,'Z',0};


/*__________________________________________________________________*/

/* get the string to be printed when the atom 'atom' is printed */
/* It returns a static string, using UTF-8 character codes,
   except for subscripted variables, in which case it mallocates a string.
*/
char *atom_string(term atom)
{  short f = FUNCTOR(atom);
   char *ans;
   char buf[40];
   if(SUBSCRIPT(f))
      { /* Then the atom should usually be a single character followed by a subscript,
           but a Greek atom could be subscripted too, and that sort of variable is 
           created by fillbinders.  It shouldn't ever need to be written though,
           so we don't need to handle it here. */
        buf[0] = (char) VARNAME(f);
        sprintf(buf+1,"%d",SUBSCRIPT(f)-1);
        ans = (char *) mallocate((int) strlen(buf)+1);
        strcpy(ans,buf);
        return ans;
      }    
   if(PREDEFINED_ATOM(f))
      switch(f)
          { case FALSEFUNCTOR:
               return "false";
            case TRUEFUNCTOR:
               return "true";
            case ALPHA: return "\xCE\xB1";
            case BETA:  return "\xCE\xB2";
            case EULERGAMMA:  // fall through 
            case LITTLEGAMMA: return "\xCE\xB3";
            case SIGMA: return  "\xCF\x83";
            case MU: return "\xCE\xBC";
            case THETA:  return "\xCE\xB8";
            case DELTA: return "\xCE\xB4";
            case INFINITYFUNCTOR: return "\xE2\x88\x9E";
            case PHI:  return "\xCF\x86";
            case PSI:  return "\xCF\x88";
            case RHO:  return "\xCF\x81";
            case EPSILON: return "\xCE\xB5";
            case PI_ATOM:  return "\xCF\x80";
            case LAMBDA: return "\xCE\xBB";
            case TAU: return "\xCF\x84";
            case NU:  return "\xCE\xBD" ;
            case OMEGA: return "\xCF\x89";
            case LEFT:  return "-";
            case RIGHT: return "+";
/* These functors are not defined:
            case NU:  return "\xCE\xBD";
            case BIGPSI: return "\xCE\xA8";
            case PSI:  return "\xCF\x88";  // used for digamma function
            case OMEGA: return "\xCF\x89";
            case BIGOMEGA: return  "\xCE\xA9";
*/
            case BOUNDED_OSCILLATIONS:  /* fall-through */
            case UNBOUNDED_OSCILLATIONS: /* fall-through */
            case UNDEFINED: return  "undefined";
            default:
               assert(0);
          }
   if (DIRECT_ATOM(f))
      { if('a'<= f && f <= 'z')
           ans = latoms + 2*(f - 'a');
        else if('A' <= f && f <= 'Z')
           ans = uatoms + 2*(f - 'A');
        else if(f == '?')  /* needed in certain menu strings */
           ans = latoms + 52;
        else if(f == PSEUDOATOM)
           /* used in displaying some terms, such as PR terms */
           ans = (char *) ARGPTR(atom);
        else
           { switch(f)
                { case '=' : return "=";
                  case '<' : return "<";
                  case '>' : return ">";
                  case LE  : return "\xE2\x89\xA4";
                  case GE  : return "\xE2\x89\xA5";
                  case '\'': return "\xE2\x80\xB2";  // UTF-8 prime symbol
                            /* this comes in printing  y'  */
                }
             assert(0);
           }
      }
   else
      { if(ATOMINDEX(f) >= MAXATOMS)
           assert(0);
        ans = symbols[ATOMINDEX(f)];
      }
   return ans;
}
/*_________________________________________________________________________*/
void functor_string(unsigned short f, int where , char *name)
/* f is the integer in the first eight bits of the functor field of a term.
   The string to be displayed will be written in space pointed to by 'name'.
   The 'where' parameter controls whether the string produced is the one
   needed for screen display (where = 1)
   or for generating a parseable internal form (where = 0).
   Only seven-bit ascii should be used when where == 0, since these strings
   will be used in saving .mxp files.
*/

{ int k;
  if(LITERALFUNCTOR(f))
     { name[0] = (char) f;
       name[1] = '\0';
       return;
     }
  if(f < GAMMA)  /* not a special function */
     { switch(f)
          { case ABSFUNCTOR:
               strcpy(name,"abs");
               return;
            case AND :
               strcpy(name,"and");  /* not used for display */
               return;
            case ACOS:
               strcpy(name,"arccos");
               return;
            case ASIN:
               strcpy(name,"arcsin");
               return;
            case ATAN:
               strcpy(name,"arctan");
               return;
            case ACOT:
               strcpy(name,"arccot");
               return;
            case ASEC:
               strcpy(name,"arcsec");
               return;
            case ACSC:
               strcpy(name,"arccsc");
               return;
            case ACOSH:
               strcpy(name,"arccosh");
               return;
            case ASINH:
               strcpy(name,"arcsinh");
               return;
            case ATANH:
               strcpy(name,"arctanh");
               return;
            case ACOTH:
               strcpy(name,"arccoth");
               return;
            case ASECH:
               strcpy(name,"arcsech");
               return;
            case ACSCH:
               strcpy(name,"arccsch");
               return;
            case ARROW:
               if(where)
                  { strcpy(name, ARROWSTR);
                    return;
                  }
               strcpy(name,"->");
               return;
            case BIGOH: strcpy(name,"O");
               return;
            case BINOMIAL:
               strcpy(name,"binomial");     /* not used for display */
               return;
            case CIS:
               strcpy(name,"cis");  /* not used for display */
               return;
            case COS:
               strcpy(name,"cos");
               return;
            case COSH:
               strcpy(name,"cosh");
               return;
            case COT:
               strcpy(name,"cot");
               return;
            case COTH:
               strcpy(name,"coth");
               return;
            case CSC:
               strcpy(name,"csc");
               return;
            case CSCH:
               strcpy(name,"csch");
               return;
            case CASES:
               strcpy(name,"cases");  /* not used for display */
               return;
            case DEFINED:
               strcpy(name,"defined");
               return;
            case DEG:
               if(where)
                  {
                     strcpy(name, DEGREESTR);
                  }
               else
                  strcpy(name,"deg");
               return;
            case DET:
               strcpy(name,"det");
               return;     /* not used for display */
            case DIFF:
               strcpy(name,"diff");
               return;    /* not used for display */
            case EVAL:
               strcpy(name,"eval");
               return;    /* not used for display */
            case EVEN1:
               strcpy(name,"even");
               return;
            case FACTORIAL:
               if( where )
                  strcpy(name,"!");
               else
                  strcpy(name, "factorial");
               return;
            case FLOOR:
               strcpy(name,"floor");
               return;
            case GE:
               if(where)
                  { strcpy(name,GESTR);
                    return;
                  }
               strcpy(name,">=");
               return;
            case GCD:
               strcpy(name,"gcd");
               return;
            case MAXFUNCTOR:
               strcpy(name,"max");
               return;
            case MINFUNCTOR:
               strcpy(name,"min");
               return;
            case INTEGRAL:
               strcpy(name,"integral");
               return; /* not used for display */
            case IF:
               strcpy(name,"if");
               return;
            case IMAGPART:
               strcpy(name,"Im");
               return;
            case BESSELJ:
               strcpy(name,"J");
               return;
            case BESSELK:
               strcpy(name,"K");
               return;
            case BESSELY:
               strcpy(name,"Y");
               return;
            case BESSELI:
               strcpy(name,"I");
               return;
            case LIMIT:
               strcpy(name,"lim");
               return;
            case LE:
               if(where)
                  {
                    strcpy(name, LESTR);
                    return;
                  }
               strcpy(name,"<=");
               return;
            case LOG:
               strcpy(name,"log");
               return;
            case LN:
               strcpy(name,"ln");
               return;
            case LOGB:
               strcpy(name,"log");
               return;
            case MOD:
               strcpy(name,"mod");
               return;
            case MATRIX:
               if(where == 0)
                  strcpy(name,"matrix");
               return;  /* not used for display */
            case MATRIXINVERSE:
               if(where == 0)
                  strcpy(name,"inverse");
               return;  /* used only in saving documents */
            case MULTIPLICITY:
               strcpy(name,"multiplicity");
               return;
            case NE:
               if(where)
                  { strcpy(name,"\xe2\x89\xa0");
                    return;
                  }
               strcpy(name,"!=");
               return;
            case NOT:
               if (where)
                 { strcpy(name, "\xc2\xac");
                   return;
                 }
               strcpy(name,"not");
               return;
            case ODD1:
               strcpy(name,"odd");
               return;
            case OR:
               strcpy(name,"or");
               return;
            case PR:
               if(!where)
                  strcpy(name,"prime");
               return; 
            case REALPART:
               strcpy(name,"Re");
               return;
            case ROOT:
               strcpy(name,"root");
               return;
            case SG:
               strcpy(name,"sgn");
               return;
            case SIN:
               strcpy(name,"sin");
               return;
            case SINH:
               strcpy(name,"sinh");
               return;
            case SQRT:
               strcpy(name,"sqrt");
               return;
            case SEC:
               strcpy(name,"sec");
               return;
            case SECH:
               strcpy(name,"sech");
               return;
            case SEQ:
               if(where)
                  strcpy(name,SEQSTR);   // UTF-8 for ⊢ "
               else
                  strcpy(name,"seq");
               return;
            case SUM:
               if(!where)
                  strcpy(name,"sum");
               else 
                  strcpy(name,"\\sigma");
               return;
            case PRODUCT:
               if(!where)
                  strcpy(name,"product");
               return;
            case TAN:
               strcpy(name,"tan");
               return;
            case TANH:
               strcpy(name,"tanh");
               return;
            case VECTOR:
               strcpy(name,"vector");
               return; /* not used for display */
            case ':' :
               strcpy(name,SETMEMBERSHIPSTR);   /* That's UTF-8 for ∈ */
               return;
          }
     }
  switch(f)
     {
       case EXISTS:
          if(where)
             {
               strcpy(name,EXISTSSTR);
             }
          else
             strcpy(name,"exists");
          return;
       case ALL:
          if(where)
             {
               strcpy(name, FORALLSTR);
             }
          else
             strcpy(name,"all");
          return;
       case LAM:
          if(where)
             {
               strcpy(name,LAMBDASTR);
             }
          else
             strcpy(name,"lambda"); // 6.30.04, now that parser can handle it
          return;
       case AP:
          strcpy(name,"ap");
          return;
       case NUMERATOR:
          strcpy(name,"numerator");
          return;
       case DENOM:
          strcpy(name,"denom");
          return;
      case CONSTANTOFINTEGRATION:
          if(where)
             strcpy(name,"c");
          else
             strcpy(name,"cofi");
          return;
     }
  if(isalpha(f))
     {  /* a one-character function name like 'f' */
        name[0]  = (char) f;
        name[1]  = '\0';
        return;
     }
  if(PREDEFINED_FUNCTOR(f))  /* a special function (but not Bessel) */
     { switch(f)
          { case POLY:
               /* used by writeterm and readterm for saving and opening documents;
                  otherwise POLY terms are never displayed. */
               strcpy(name,"polynomial");
               return;
            case INCOMPLETEGAMMA: /*fall-through */
            case GAMMA:
               if (where)
                  {
                    strcpy(name, BIGGAMMASTR);  // uppercase Greek Gamma
                  }
               else
                  strcpy(name,"Gamma");
               return;
            case INCOMPLETEBETA:
               strcpy(name, where ? "B" : "IncompleteBeta");
               return;
            case BETAFUNCTION:
               strcpy(name, where ? "B" : "Beta");  // Not actually used in MathXpert, so no conflict with BERNOULLI
               return;
            case BERNOULLI:
               strcpy(name, where ? "B" : "bernoulli");  
               return;
            case EULERNUMBER:
               strcpy(name, where ? "E" : "eulernumber");
               return;
            case DIGAMMA:
               strcpy(name,where ? "\xCE\xA8" : "Digamma");   // uppercase Psi
               return;
            case POLYGAMMA:
               strcpy(name, where ? "\xCE\xA8": PSISTR);  // uppercase Psi
               return;
            case ERF:
               strcpy(name,"Erf");
               return;
            case ERFC:
               strcpy(name,"Erfc");
               return;
            case INCOMPLETEGAMMAP:
               strcpy(name,where ? "P" : "IncompleteGammaP");
               return;
            case COSINTEGRAL:
               strcpy(name,where? "Ci" : "CosIntegral");
               return;
            case SININTEGRAL:
               strcpy(name,where ? "Si" : "SinIntegral");
               return;
            case LOGINTEGRAL:
               strcpy(name, where ? "Li" : "LogIntegral");
               return;
            case EXPINTEGRALI:
               strcpy(name, where ? "Ei" : "ExpIntegralI");
               return;
            case EXPINTEGRALE:
               strcpy(name,where ? "E" : "ExpIntegralE");
               return;
            case RIEMANNZETA:
               strcpy(name, where ? ZETASTR: "zeta");
               return;
            case WEIERSTRASSP:
               strcpy(name,"Pe");
               return;
            case APPROXEQ:
               strcpy(name,APPROXEQSTR);
               return;
            case ILLEGAL:
               // assert(0);
               strcpy(name,"illegal");
               return;
            case VAR:  // metavariable, not to be parsed
               strcpy(name,"?");
                    // this happens when using 2-d display on a menu
                    // item containing "?"   Note: "?" will parse to VAR
               return;
            default:
               assert(0);
          }
     }
  k = INDEX(f);
  if(k >= nextfunctor)
     assert(0);
  strcpy(name,functors[k]);
  return;
}

/* _________________________________________________________________*/
/* Print names of user-defined atoms and functors are kept in
parser.dll  and shared by all documents.  The actual character
strings are stored in the following static array: */

#define MAXSTRINGSPACE 256
char stringspace[MAXSTRINGSPACE];
int nextstring;   /*  stringspace[nextstring] is available */

/* _________________________________________________________________*/
/* Enter string 'fname' as a new functor and return the functor
to be used, namely INDEX_TO_FUNCTOR(nextfunctor).
If the functor was already there, just return the functor that
was already entered.  This is called by the parser, which can be
called at getarg, so it better use permalloc instead of callocate */

unsigned short newfunctor(char *fname, unsigned short arity)
{ unsigned short j,ans;
  int length;
  if(fname[1] == 0)
     { /* one-character function name */
       return (unsigned short) fname[0];    /* just use 'f' as the functor for "f" */
     }
  for(j=0;j<nextfunctor;j++)
     { if(!strcmp(fname,functors[j]))
          return (unsigned short) INDEX_TO_FUNCTOR(j);
     }
  if (nextfunctor == MAXFUNCTORS)
     return ILLEGAL;
  length = (int) strlen(fname) + 1;
  if(nextstring + length > MAXSTRINGSPACE)
     return ILLEGAL;
  functors[nextfunctor] =  stringspace + nextstring;
  nextstring += length;
  strcpy(functors[nextfunctor],fname);
  ans = (unsigned short) INDEX_TO_FUNCTOR(nextfunctor);
  ++nextfunctor;
  return ans;
}

/*_________________________________________________________________*/

/* Given a character string meant to determine an atom, return
the functor that should be used for that atom.  Predefined
functors are not sent to this function; it must deal with
single letters, subscripted variables such as x3, and user-defined
atoms such as 'mass'.
   In the case of a user-defined atom, first check if x is already
present in the symbols array; if so it isn't necessary to enter it.
If not, enter string x as a new atom
and return FIRST_DEFINED_ATOM + newatom, incrementing newatom.
If there is no more space for the strings, or if too many atoms
are already defined, just return an ILLEGAL atom.
   Subscripted variables involving subscripts > MAXSUBSCRIPT
will be processed, but the subscript will be incorrect.
The parser and getnewvar have to not create such variables.
*/
unsigned short newatom(char *x)
{ unsigned short ans;
  int i,length;
  char *marker;
  if(x[1] == '\0' && isalpha(x[0]))
     return x[0];  /* a single letter */

  /* Check for a subscripted variable */
  for(marker = x+1; *marker; ++marker)
     { if(!isdigit(*marker))
          break;
     }
  if(*marker == '\0')
     { /* a subscripted variable */
       unsigned subscript = atoi(x+1);
       if(subscript > MAXSUBSCRIPT)
          subscript = subscript % (MAXSUBSCRIPT+1);
          /* truncate, see comments above */
       return (unsigned short) SUBSCRIPTEDFUNCTOR(x[0],subscript);
     }

  for(i=0;i<nextatom;i++)
     { if(!strcmp(symbols[i],x))
          return (unsigned short) (i + FIRST_DEFINED_ATOM);    /* this atom is already recorded */
     }
  if(nextatom == MAXATOMS)
     return ILLEGAL;
  length = (int) strlen(x)+1;
  if(nextstring + length > MAXSTRINGSPACE)
     return ILLEGAL;
  symbols[nextatom] = stringspace + nextstring;
  nextstring += length;
  strcpy(symbols[nextatom],x);
  ans = (unsigned short) (nextatom + FIRST_DEFINED_ATOM);
  ++nextatom;
  return ans;
}

/*_______________________________________________________________*/
char * functorname(unsigned f)
/* return the print name of a multi-character functor */
{ if(isalpha(f) || PREDEFINED_FUNCTOR(f))
      return NULL;
  return functors[INDEX(f)];
}

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