Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/symsout/
Upload File :
Current File : /usr/home/beeson/MathXpert/symsout/mstring.c

/*  convert a term to a string  for one-line display.
Returns a string beginning and ending with $.
As of 10.20.23, no OEM characters are ever used.
*/
/*
9.13.90  original date
6.21.99 last modified.
9.2.04  changed ultoa to sprintf for ANSI C compatibility
3.20.06 modified raw_mstring to not produce OEM characters for superscript 2 and superscript n for exponents,
        and to not produce OEM characters for \le and \ge, but produce those Tex codes instead. 
3.27.06 corrected that modification, using ksymbol.         
9.8.11  cast result of strlen to int  for 64-bit compilation without warnings
5.6.13  changed %d to %lu  in raw_mstring
3.14.23  added braces at line 538 to avoid dangling else
10.29.23  eliminated OEM characters in favor of UTF-8
12.11.23 changed oem_atom_string to atom_string in raw_mstring
2.3.24   used \\sqrt instead of old character code 251 in raw_mstring
4.24.24  made raw_mstring reject nested exponents at line 498
4.25.24  changed MAX_MSTRING to 256 from 100
4.25.24  made mstring use pstring to return display math.
5.14.24  made raw_mstring use \\int for INTEGRAL
6.14.24 eliminated some (hopefully all) non-ascii characters in favor of backslash codes
1.24.25  corrected raw_mstring on ABS to use '|'
*/

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

#include "terms.h"
#include "mstring.h"
#include "dispfunc.h"      /* atom_string */
#include "mygcvt.h"
#include "pstring.h"       /* pstring */
#include "svgSymbolText.h"

static int interval_as_and2(term u);
static int raw_mstring(term t, char *ans);
static int long_identifiers = 0;
/* You could possibly make this variable global in the
future; mstring uses it to control spacing, e.g. if
long_identifiers is nonzero,  we get "x y z" instead
of "xyz", because "xyz" might be one identifier. */

#define ISTWO(x)  (ISINTEGER(x) && INTDATA(x)==2L)
#define MAX_MSTRING 2048
/*__________________________________________________________________*/
static int precision = 6;
/* controls number of digits in decimals displayed by mstring */

void set_mprecision(int n)
{ precision = n;
}

/*__________________________________________________________________*/
static int separator = 2;
/* controls display of bignums by mstring */

void set_mseparator(int n)
{ separator = n;
}

/*___________________________________________________________________*/
int mstring(term t, char *ans)
/* enclose the result of raw_mstring in $ signs,
if raw_mstring succees.  Otherwise, convert
t to a parseable string and return that string
enclosed in $$. */

/* Assumes ans points to at least MAX_MSTRING bytes */

{ int err;
  ans[0] = '$';
  err = raw_mstring(t,ans+1);
  if(err)
     { strcpy(ans, "$$");
       int nbytes = pstring(t,ans+2,MAX_MSTRING-4);
       if (nbytes == 0)
          { printf("Term too big in mstring.\n");
            return 1;
          }
       strcat(ans, "$$");
       return 0;
     }
  else  // if raw_mstring succeeded
    {
      strcat(ans,"$");
      return 0;
    }
}
/*___________________________________________________________________*/
static int raw_mstring(term t, char *ans)

/*   nonzero return is out of space, or string too long,
   or exponents that svgSymboText can't handle.
 */
{
    /* assumed to have space allocated already.  No more than 82
       chars will ever be used; but now, some of those may be UTF-8
       characters requiring more than one byte, so one should allocate
       MAX_MSTRING bytes.
    */
  char temp[MAX_MSTRING];
  char temp1[MAX_MSTRING];
  char temp2[MAX_MSTRING];
  char *temp4;
  term arg;
  int i,k,k1,k2,ksymbol,stashit;
  unsigned short f,hbase;
  unsigned short h = FUNCTOR(t);
  if (ISATOM(t))
     { temp4 = atom_string(t);
       if((int) strlen(temp4)>80)
          return 1;
       strcpy(ans,temp4);
       return 0;
     }
  if (OBJECT(t))
     switch(TYPE(t))
       { case DOUBLE:
            my_gcvt(DOUBLEDATA(t),precision,ans);
            return 0;
         case INTEGER:
            sprintf(ans,"%lu",INTDATA(t));
            return 0;
         case BIGNUM:
            temp4 = bignum_string(BIGNUMDATA(t),separator);
            if((int) strlen(temp4)>80)
               return 1;
            strcpy(ans,temp4);
            return 0;
       }

  if(h== '-')
     { ans[0] = '-';
       if(raw_mstring(ARG(0,t),ans+1))
          return 1;
         /* so conceivably we might have need ans to have 82 spaces */
       if((int) strlen(ans) > 80)
          return 1;
       return 0;
     }
  /* postfix functions */
  if(h == FACTORIAL || h == DEG)
     { if(raw_mstring(ARG(0,t),ans))
          return 1;
       k = (int) strlen(ans);
       if(k > 79)
          return 1;
       switch(h)
          { case FACTORIAL :
               strcpy(ans+k,"!");
               return 0;
            case DEG :
               strcpy(ans+k,"ΓΈ");
               return 0;
          }
     }
  if(ARITY(t) == 1 && h != SQRT && h != ABSFUNCTOR && h != AND)
     { if(raw_mstring(ARG(0,t),temp))
          return 1;
       functor_string(h,SCREEN,ans);
       k = (int) strlen(ans);
       if(ATOMIC(ARG(0,t)) && PREFIX(h))
          { ans[k] = 32;
            ++k;
            if((int) strlen(temp) + k > 80)
               return 1;
            strcpy(ans+k,temp);
            return 0;
          }
       else
          { ans[k] = '(';
            ++k;
            if((stashit = (int) strlen(temp)) +k > 79)
               return 1;
            strcpy(ans + k,temp);
            k += stashit;
            ans[k] = ')';
            ans[k+1] = '\0';
            return 0;
          }
     }
  if(h==DIFF && ARITY(t)==2)
     { if(raw_mstring(ARG(0,t),temp1))
          return 1;
       if(raw_mstring(ARG(1,t),temp2))
          return 1;
       k1 = (int) strlen(temp1);
       k2 = (int) strlen(temp2);
       if(ISATOM(ARG(0,t)) && ISATOM(ARG(1,t)) )  /*  du/dx */
         { if(k1+k2+3 > 80)
              return 1;
           ans[0] = 'd';
           strcpy(ans+1,temp1);
           ans[k1+1] = '/'; ans[k1+2] = 'd';
           strcpy(ans+k1+3,temp2);
           return 0;
         }
       else                               /* d/dx (u + v)  */
         { if(k1+k2+5>80)
              return 1;
           strcpy(ans,"d/d");
           strcpy(ans+3,temp2);
           ans[k2+3]='(';
           strcpy(ans + k2+4,temp1);
           strcpy(ans+k1+4+k2,")");
           return 0;
         }
     }
  if(h==DIFF && ARITY(t)==3 && (ISTWO(ARG(1,t)) || (ISATOM(ARG(1,t)) && FUNCTOR(ARG(1,t))== 'n')))
     { if(raw_mstring(ARG(0,t),temp1))
          return 1;
       if(raw_mstring(ARG(2,t),temp2))
          return 1;
       k1 = (int) strlen(temp1);
       k2 = (int) strlen(temp2);
       if(ISATOM(ARG(0,t)) && ISATOM(ARG(2,t)) )  /*  d^2u/dx^2 */
         { if(k1+k2+5 > 78)
              return 1;
           strcpy(ans, "d^2");
           strcat(ans,temp1);
           strcat(ans,"/d");
           strcat(ans,temp2);
           strcat(ans,"^2");
           return 0;
         }
       else                               /* d^2/dx^2 (u + v)  */
         { if(k1+k2+7>78)
              return 1;
           if(ISTWO(ARG(1,t)))
              { strcpy(ans,"d^2/d");
                strcat(ans,temp2);
                strcat(ans,"^2");
                return 0;
              }
           if(ISATOM(ARG(1,t)))
              { char buffer[20];
                functor_string(FUNCTOR(ARG(1,t)),1,buffer);
                if((int) strlen(buffer) == 1)
                   { strcpy(ans,"d^");
                     strcat(ans,buffer);
                     strcat(ans,"/d");
                     strcat(ans,temp2);
                     strcat(ans,"^");
                     strcat(ans,buffer);
                     return 0;
                   }
                else
                   { strcpy(ans,"d^(");
                     strcat(ans,buffer);
                     strcat(ans,")");
                     strcat(ans,"/d");
                     strcat(ans,temp2);
                     strcat(ans,"^(");
                     strcat(ans,buffer);
                     strcat(ans,")");
                     return 0;
                   }
              }
           else   /* usually an integer exponent, but this code handles more complicated exponents */
              { char buffer[84];
                raw_mstring(ARG(1,t),buffer);
                if((int) strlen(buffer) == 1)
                   { strcpy(ans,"d^");
                     strcat(ans,buffer);
                     strcat(ans,"/d");
                     strcat(ans,temp2);
                     strcat(ans,"^");
                     strcat(ans,buffer);
                     return 0;
                   }
                else if((int) strlen(buffer) <= 30)
                   { strcpy(ans,"d^(");
                     strcat(ans,buffer);
                     strcat(ans,")/d");
                     strcat(ans,buffer);
                     strcat(ans,"^(");
                     strcat(ans,temp2);
                     strcat(ans,")");
                     return 0;
                   }
                else 
                  return 1; /* too long */
              }
         }
     }
  if(h == INTEGRAL && ARITY(t) == 2)  /* indefinite integral */
     { if(raw_mstring(ARG(0,t),temp))
           return 1;
       k = (int) strlen(temp);
       if(raw_mstring(ARG(1,t),temp2))
          return 1;
       k2 = (int) strlen(temp2);
       if (k + k2 + 3 > 80)
          return 1;
       strcpy(ans,"\\int "); // later UTF-8 will be put in for \\int and height of SVG will be increased
                             // but if you put UTF-8 in here, height will not be adjusted properly
       strcat(ans,temp);
       strcat(ans, " d");
       strcat(ans, temp2);
       return 0;
     }
  if(h==ROOT) /* produce ^(index) \\sqrt arg */
     { int kk;
       if(raw_mstring(ARG(1,t),temp))
          return 1;
       ans[0] = '^';
       if(ISINTEGER(ARG(0,t)) && INTDATA(ARG(0,t)) < 10)
          { ans[1] = (char) (48 + INTDATA(ARG(0,t)));
            ans[2] = '\0';
            strcat(ans,"\\sqrt ");
          }
       else
          { ans[1] = '(';
            if(raw_mstring(ARG(0,t),ans+2))
               return 1;
            kk = (int) strlen(ans);
            ans[kk] = ')';
            ans[kk+1] = '\0';
            strcat(ans,"\\sqrt ");
          }
       kk = (int) strlen(ans);
       if(!ATOMIC(ARG(1,t)))
          { ans[kk] = '(';
            if(raw_mstring(ARG(1,t),ans+kk+1))
               return 1;
            strcat(ans,")");
            return 0;
          }
       return raw_mstring(ARG(1,t),ans+kk);
     }
  switch(h)   /* now it's a compound term */
     { case LE:   /* fall-through */
       case GE:
       case '<':
       case '>':
       case NE :
       case '=':
       case ARROW:
          ksymbol = (h == LE || h == GE) ? 3 : 1;
          if(raw_mstring(ARG(0,t),temp1))
             return 1;
          if(raw_mstring(ARG(1,t),temp2))
             return 1;
          k1 = (int) strlen(temp1);
          k2 = (int) strlen(temp2);
          if(k1+k2+ksymbol + 2>80)
             return 1;
          strcpy(ans,temp1);
          switch(h)
             { case '<' :
                  strcpy(ans + k1, " < ");
                  break;
               case LE  :
                  strcpy(ans + k1, " \\le ");
                  break;
               case GE  :
                  strcpy(ans + k1, " \\ge ");
                  break;
               case '>' :
                  strcpy(ans + k1, " > ");
                  break;
               case '=' :
                  strcpy(ans + k1, " = ");
                  break;
               case NE  :
                  strcpy(ans + k1, " # ");
                  break;
               case ARROW:
                  ans[k1] = -16;   /* SymbolTextOut expects OEM character set; but in this case OEM
                                      character is 26, which is also end-of-file, so we use 240,
                                      which SymbolTextOut knows how to handle. */
                  ans[k1+1] = 0;
                  strcat(ans,temp2);
                  return 0;
             }
          strcpy(ans+k1+ksymbol+2,temp2);
          return 0;
       case '/' :
          if(raw_mstring(ARG(0,t),temp1))
             return 1;
          if(raw_mstring(ARG(1,t),temp2))
             return 1;
          k1 = (int) strlen(temp1);
          k2 = (int) strlen(temp2);
          if( ARITY(ARG(1,t))==1 || ATOMIC(ARG(1,t))) /* no parens in denom */
             { if(FUNCTOR(ARG(0,t))=='+')
                { if(k1+k2+3>80)
                     return 1;
                  ans[0] = '(';
                  strcpy(ans + 1, temp1);
                  strcpy(ans + 1 + k1, ")/");
                  strcpy(ans + 1 + k1 + 2, temp2);
                  return 0;
                }
             else
                { if(k1+k2+1>80)
                     return 1;
                  strcpy(ans,temp1);
                  ans[k1] = '/';
                  strcpy(ans + k1+1,temp2);
                  return 0;
                }
            }
            /* now denom needs parens */
            if( FUNCTOR(ARG(0,t))== '+')
               { if(k1+k2+5>80)
                    return 1;
                 ans[0] = '(';
                 strcpy(ans + 1, temp1);
                 strcpy(ans + 1 + k1, ")/(");
                 strcpy(ans + 1 + k1 + 3, temp2);
                 strcpy(ans + 1 + k1 + 3 + k2,")");
                 return 0;
               }
            else
               { if(k1+k2+3>80)
                    return 1;
                 strcpy(ans,temp1);
                 strcpy(ans+k1,"/(");
                 strcpy(ans+k1+2,temp2);
                 strcpy(ans+k1+2+k2,")");
                 return 0;
               }
       case ABSFUNCTOR :
          ans[0] = '|';
          if(raw_mstring(ARG(0,t),ans+1))
             return 1;
          k = (int) strlen(ans);
          ans[k] = '|';
          ans[k+1] = '\0';
          return 0;
       case SQRT:
          raw_mstring(ARG(0,t),temp);
          k = (int) strlen(temp);
          if(k + 3 > 80)
             return 1;
          if(ATOMIC(ARG(0,t)))
             { strcpy(ans,"\\sqrt ") ;
               strcat(ans,temp);
               return 0;
             }
          strcpy(ans,"\\sqrt(");
          strcat(ans,temp);
          strcat(ans,")");
          return 0;
       case '^':
          hbase = FUNCTOR(ARG(0,t));
          if(ISTWO(ARG(1,t)) && TRIGFUNCTOR(hbase))
             { functor_string(hbase,SCREEN,ans);
               if(ATOMIC(ARG(0,ARG(0,t))))
                  strcat(ans,"^2 ");
               else
                  strcat(ans,"^2(");
               k = (int) strlen(ans);
               if(raw_mstring(ARG(0,ARG(0,t)),ans+k))
                  return 1;
               if(!ATOMIC(ARG(0,ARG(0,t))))
                  strcat(ans,")");
               if((int) strlen(ans) > 80)
                  return 1;
               return 0;
             }
          if(FUNCTOR(ARG(1,t)) == 'n' && TRIGFUNCTOR(hbase))
             { functor_string(hbase,SCREEN,ans);
               if(ATOMIC(ARG(0,ARG(0,t))))
                  strcat(ans,"^n ");
               else
                  strcat(ans,"^n(");
               k = (int) strlen(ans);
               if(raw_mstring(ARG(0,ARG(0,t)),ans+k))
                  return 1;
               if(!ATOMIC(ARG(0,ARG(0,t))))
                  strcat(ans,")");
               if((int) strlen(ans) > 80)
                  return 1;
               return 0;
             }
          if(ISTWO(ARG(1,t)))
             { raw_mstring(ARG(0,t),temp);
               k = (int) strlen(temp);
               if(ATOMIC(ARG(0,t)))
                 { if (k > 79)
                      return 1;
                   strcpy(ans,temp);
                   strcpy(ans+k,"^2");
                   return 0;
                 }
               else
                 { if(k + 3 > 80)
                      return 1;
                   ans[0] = '(';
                   strcpy(ans+1,temp);
                   strcpy(ans+1+k,")^2");
                   return 0;
                 }
             }
          if(ISATOM(ARG(1,t)) && FUNCTOR(ARG(1,t))=='n')
             { raw_mstring(ARG(0,t),temp);
               k = (int) strlen(temp);
               if(ATOMIC(ARG(0,t)))
                  { if (k > 79)
                       return 1;
                    strcpy(ans,temp);
                    strcpy(ans+k,"^n");
                    return 0;
                  }
               else
                  { if(k + 3 > 80)
                       return 1;
                    ans[0] = '(';
                    strcpy(ans+1,temp);
                    strcpy(ans+1+k,")^n");
                    return 0;
                  }
             }
              /* now dealing with a^b where b isn't 2 or 'n' */
          term a = ARG(0,t);
          term b = ARG(1,t);
          if(raw_mstring(a,temp1))
             return 1;
          if(contains(b, '^'))
             return 1;   // reject 2^(2^3)  for example
          // we need to reject exponents that svgSymbolText  can't handle.
          if(
              !(ATOMIC(b) ||
                (FUNCTOR(b) == '*' && ARITY(b) == 2 && ATOMIC(ARG(0,b)) && ATOMIC(ARG(1,b)))
               )
            )
             return 1;
         /* Now b is atomic or a product of two atomic terms. */
          raw_mstring(b,temp2); // it will work
          k1 = (int) strlen(temp1);
          k2 = (int) strlen(temp2);
          if( ATOMIC(a) && ATOMIC(b))
             { if(k1 + k2 + 1 > 80 )
                  return 1;
               strcpy(ans,temp1);
               ans[k1] = '^';
               strcpy(ans+1+k1,temp2);
               ans[k1+k2+1]= '\0';
               return 0;
             }
          if( ATOMIC(a))
             { if(k1 + k2 + 3 > 80)
                  return 1;
               strcpy(ans,temp1);
               strcpy(ans+k1,"^(");
               strcpy(ans + k1 + 2, temp2);
               strcpy(ans + k1 + 2 + k2, ")");
               return 0;
             }
          if( ATOMIC(b))
             { if(k1 + k2 + 3 > 80)
                  return 1;
               ans[0] = '(';
               strcpy(ans+1,temp1);
               strcpy(ans+1+k1,")^");
               strcpy(ans+1+k1 + 2, temp2);
               return 0;
             }
          else
             { if(k1+k2+5 > 80)
                  return 1;
               ans[0] = '(';
               strcpy(ans+1,temp1);
               strcpy(ans+1+k1,")^(");
               strcpy(ans+1+k1+3,temp2);
               strcpy(ans+1+k1+3+k2,")");
               return 0;
             }
       case AND :
          if(interval_as_and2(t))
             { /* print as x < y < z */
               unsigned short ff;
               if(raw_mstring(ARG(0,t),temp))
                  return 1;
               if(80 < (k = (int) strlen(temp)))
                  return 1;
               strcpy(ans, temp);
               ff = FUNCTOR(ARG(1,t));
               strcat(ans, ff == '<' ? " < " :
                           ff == '>' ? " > " :
                           ff == LE ?  " \\le " :
                                       " \\ge ");
               k += 3;
               if(raw_mstring(ARG(1,ARG(1,t)),temp))
                  return 1;
               if(80-k < (stashit = (int) strlen(temp)))
                  return 1;
               strcat(ans,temp);
               return 0;
             }

          /* print as arg0, arg1, arg2  */
          for(i=k=0;i<ARITY(t);i++)
             { if(raw_mstring(ARG(i,t),temp))
                  return 1;
               if(i>0)
                  { ans[k] = ',';
                    ans[k+1] = 32;
                    k+=2;
                  }
               if(80-k < (stashit = (int) strlen(temp)))
                  return 1;
               strcpy(ans+k,temp);
               k += stashit;
             }
          return 0;
       case OR:  /* print as arg0; arg1; arg2 */
          for(i=k=0;i<ARITY(t);i++)
             { if(raw_mstring(ARG(i,t),temp))
                  return 1;
               if(i>0)
                  { ans[k] = ';';
                    ans[k] = ' ';
                    k += 2;
                  }
               if(80-k < (stashit = (int) strlen(temp)))
                  return 1;
               strcpy(ans+k,temp);
               k += stashit;
             }
          return 0;
       case '*' :
          for(i=k=0;i<ARITY(t);i++)
             { if(raw_mstring(ARG(i,t),temp))
                  return 1;
               f = FUNCTOR(ARG(i,t));
               if(  /* parentheses required */
                   !ATOMIC(ARG(i,t)) &&
                    (f == '*' ||
                     (PREFIX(f) && f != SQRT && f != ABSFUNCTOR && k < ARITY(t) - 1)
                     || f == '+' || f== '-' || f == '/' || f == FACTORIAL
                     || (f == LIMIT && k < ARITY(t)-1)
                    )
                 )
                  { ans[k] = '(';
                    k++;
                    if(79-k < (stashit = (int) strlen(temp)))
                       return 1;
                    strcpy(ans+k,temp);
                    k += stashit;
                    strcpy(ans+k,")");
                    k++;
                  }
               else
                  { if(80-k-2 < (stashit = (int) strlen(temp)))
                       return 1;
                    if(i>0 && ans[k-1] != ')' &&
                       (UNARY(f) || (long_identifiers && !ISINTEGER(ARG(i-1,t))))
                      )
                       { ans[k] = 32;  /* space if no parens,
                                          but not after an integer,
                                          unless what follows the integer
                                          is a unary function, e.g.
                                          2 sin x rather than 2sin x */
                         k++;
                       }
                    strcpy(ans+k,temp);
                    k+= stashit;
                  }
             }
          return 0;
       case '+' :
          for(i=k=0;i<ARITY(t);i++)
             { arg = ARG(i,t);
               if(FUNCTOR(arg) == '-')
                  { ans[k] = '-';
                    k++;
                    arg = ARG(0,arg);
                  }
               else if(i>0)
                  { ans[k] = '+';
                    k++;
                  }
               if( raw_mstring(arg,temp))
                   return 1;
               if(  /* parentheses required */
                   FUNCTOR(arg) == '+'
                   || FUNCTOR(arg) == '/'
                   || FUNCTOR(arg) == LIMIT
                 )
                  { ans[k] = '(';
                    k++;
                    if(79-k < (stashit = (int) strlen(temp)))
                       return 1;
                    strcpy(ans+k,temp);
                    k += stashit;
                    ans[k] = ')';    /* wiping out the null terminator */
                    k++;
                    ans[k] = '\0';   /* restore a null terminator */
                  }
               else
                  { if(80-k < (stashit = (int) strlen(temp)))
                       return 1;
                    strcpy(ans+k,temp);
                    k+= stashit;
                  }
             }
          return 0;
       case PR:
          assert(ISINTEGER(ARG(1,t)));
          if(ISATOM(ARG(0,t)))
             { if(raw_mstring(ARG(0,t),temp1))
                  return 1;
               k = (int) strlen(temp1);
               if(k + INTDATA(ARG(1,t)) > 80)
                  return 1;
               strcpy(ans,temp1);
               for(i=0;i<INTDATA(ARG(1,t));i++)
                  ans[i+k] = 39;  /* ascii code of apostrophe */
               ans[i+k] = '\0';   /* don't forget to make it a string */
               return 0;
             }
          functor_string(FUNCTOR(ARG(0,t)),SCREEN,ans);
          k = (int) strlen(ans);
          for(i=0;i<INTDATA(ARG(1,t));i++)
              { if(i+k > 80)
                   return 1;
                ans[i+k] = 39;  /* ascii code of apostrophe */
              }
          i = i+k;
          ans[i] = '\0';
          assert(ARITY(ARG(0,t))==1);
          if(raw_mstring(ARG(0,ARG(0,t)),temp))
             return 1;
          if((int) strlen(temp) + i > 78)
             return 1;
          strcat(ans,"(");
          strcat(ans,temp);
          strcat(ans,")");
          return 0;
      case LIMIT:
          strcpy(ans,"lim(");
          k=4;
          for(i=0;i<ARITY(t);i++)
             { if(ARITY(t)==3 && i==1)
                  { ans[k] = (char)(FUNCTOR(ARG(1,t)) == RIGHT ? '+' : '-');
                    ++k;
                    ans[k] = ',';
                    ++k;
                    continue;
                  }
               if( raw_mstring(ARG(i,t),temp))
                  return 1;
               if(80-k < (stashit = (int) strlen(temp)))
                  return 1;
               strcpy(ans+k,temp);
               k += stashit;
               if(ARITY(t)==2 && i==0)
                  { ans[k] = ',';
                    ++k;
                  }
               else if(i==ARITY(t)-1)
                  { ans[k] = ')';
                    ++k;
                  }
             }
          ans[k] = '\0';
          return 0;
      case MATRIX:
          assert(0);   /* should not pass MATRIX to mstring!  */ 
      default:
          functor_string(h,SCREEN,ans);
          k= (int) strlen(ans);
          ans[k] = '(';
          k++;
          for(i=0;i<ARITY(t);i++)
             { if( raw_mstring(ARG(i,t),temp))
                  return 1;
               if(80-k < (stashit = (int) strlen(temp)))
                  return 1;
               strcpy(ans+k,temp);
               k += stashit;
               if(i < ARITY(t)-1)
                  ans[k] = ',';
               else
                  ans[k] = ')';
               k++;
             }
          ans[k] = '\0';
          return 0;
     }
}
/*_____________________________________________________________*/
int mstrlen(char *x)
/* return an estimate of the length string x will take when printed by
SymbolTextOut.  This differs from (int) strlen(x) in the following ways:

Don't count '$' and '^';
subtract an extra 3 for every "^(" that occurs in the string (one for the
^ and one each for two parentheses).
Don't count isalpha characters after a backslash;
*/

{ unsigned char *marker;
  int count = 0;
  int doublecount = 0;
  int ans;
  for(marker = (unsigned char *) x; *marker; ++marker)
     { if(*marker == '^' && marker[1] == '(')
          ++doublecount;
       if(*marker == '_' && marker[1] == '(')
          ++doublecount;
       if(*marker != '^' && *marker != '_' && *marker != '$')
          ++count;
       if(*marker == '\\')  /* example:  \sqrt counts only 1  */
          { ++marker;
            while(isalpha(*marker))
               ++marker;
            if(*marker == 32)
               ++marker;  /* skip one space after \sqrt */
          }
     }
  ans = count - 3*doublecount;
  assert(ans >= 0);
  return ans;
 }

/*___________________________________________________________________*/
static int interval_as_and2(term u)
/* static copy of interval_as_and in prover.c */
/* return 1 if u is an interval, that is, an AND of two inequalities
with the same middle term, as  a < x && x < b.  Return 0 if not. */
{ unsigned short f,g;
  if(FUNCTOR(u) != AND)
     return 0;
  if(ARITY(u) != 2)
     return 0;
  f = FUNCTOR(ARG(0,u));
  if(f != '<' && f != LE)
     return 0;
  g = FUNCTOR(ARG(1,u));
  if(g != '<' && g != LE)
     return 0;
  return equals(ARG(1,ARG(0,u)),ARG(0,ARG(1,u)));
}

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