Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/automode/
Upload File :
Current File : /usr/home/beeson/MathXpert/automode/needsarg.c

/* M. Beeson, for Mathpert */
/* Determine which operators need an arg, and what the prompt for it is */
/*
10.19.90 original date
2.19.99 last modified
1.12.00  removed obsolete condition interval_as_inequality
1.12.00 modified needs_arg on advanced_factoring to take account of a new operator
       added to that menu.
1.26.00  added comment at return 5;
2.2.00  added notzerodiv, notzeromul, notzeropower, notzerobase to
        needs_arg and check_arg.
2.2.00  changed condition for taking the root of both sides of an equation
         from notzero to positive_integer.
4.20.00  modified check_arg on fundtiondefn
3.8.01  modified needs_arg for diveqn
6.24.04 check return values of enter_definition and replace_defn and provide error messages.
9.2.04  modified calls to enter_definition to take rhs_name.
1.19.06 modified includes
4.7.06  changed itoa to sprintf
5.5.13  changed index to condition_index
5.6.13  include stddef.h
5.17.13 passed third parameter to initialize_parameter as now required.
9.26.14 deleted unused function contains_in_exponent
3.18.23  changed comma to semicolon at line 1154
4.23.24  modified check_arg on tlist
6.10.24 modified needs_arg on swap_eqn
6.11.24 made needs_arg return condition 'intbyparts'  instead of 'anyterm' on integration_by_parts.
*/

#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>  // sprintf
#include <math.h>
#include "globals.h"
#include "checkarg.h"
#include "chkinput.h"    /* mathematical */
#include "operator.h"
#include "ops.h"
#include "probtype.h"
#include "mpminmax.h"
#include "relrates.h"
#include "graphstr.h" /* mpdoc.h needs it */
#include "display.h"
#include "mpdoc.h" /* automode.h and getarg.h need it */
#include "getarg.h"
#include "english.h"
#include "prover.h"
#include "errors.h"
#include "deval.h"
#include "algaux.h"  /* atomsin  */
#include "order.h"   /* constant */
#include "mathmode.h"  /* get_problemtype */
#include "userfunc.h"
#include "automode.h"  /* get_activeline */
#include "eqn.h"       /* get_ind_set */
#include "errbuf.h"
#include "matrix.h"    /* is_matrix_product */
#include "pvalaux.h"   /* isinteger, obviously_positive */
#include "nextline.h"  /* inconsistent */
#include "dcomplex.h"  /* needed by ceval.h */
#include "ceval.h"     /* complexnumerical */
#include "dispfunc.h"  /* functor_string */
#include "induct.h"    /* simple_select  */
#include "mstring.h"   

static int invalid_index(term);
static int no_new_vars(term);
static int evalsumarg_aux(unsigned short, term,term *);
static int valuesprompt(char *);
static int natoms; /* set by valuesprompt during needs_arg,
                      and used by check_arg */
/*______________________________________________________________*/
int needs_index_arg(operation op)

/* several equation_solving operators prompt for an "index arg"
if more than one equation is in history(currentline).  The
prompt asks "Work on which equation? (enter 1,2,3...)".  This
function returns 1 if op is one of these operators, 0 if not.
Such an operator may or may not need an ordinary arg as determined by
needs_arg.
   Remember op.choice starts at 1 for the top item in a menu,
not zero.
*/

{ switch (op.men)
     { case solve_equations :
          if (op.choice < 12)
             return 1;
          return 0;
       case quadratic_equations :
          if (op.choice == 5)
             return 1;  /* square root of both sides */
          if (op.choice == 6)
             return 1;  /* cross_multiply */
          return 0;
       case numerical_equations:
          if(op.choice == 1)
             return 1; /* evaluate numerically */
          if(op.choice == 2)
             return 1; /* solve numerically */
       case advanced_equations :
          if(op.choice < 6)
             return 1;
          return 0;
       case less_than :  /* fall-through */
       case greater_than:          /* fall-through */
       case less_than_or_equals:
       case greater_than_or_equals:
       case square_ineq1:
       case square_ineq2:
       case square_ineq3:
       case square_ineq4:
       case root_ineq1:             /* fall-through */
       case root_ineq2:            return 1;
       case root_ineq3:
       case root_ineq4:
       case zero_ineq1:
       case zero_ineq2:
       case zero_ineq3:
       case zero_ineq4:
       case absolute_value_ineq1:
       case absolute_value_ineq2:   return 1;
    }
  return 0;
}
/*_____________________________________________________________*/

condition needs_arg(operation op, char *prompt)
/* does op require an argument? 
Return 0 if it does not; return an integer that converts to a 'condition' as 
defined in checkarg otherwise, specifying what condition the arg must satisfy.
Fill in the buffer prompt with the prompt string for the getarg window.
*/
/* when called from top.c, the buffer is actually the title string for the
getarg window, so this function already prepares the prompt string in that
window without needing to copy it a second time.
*/

{ term *varlist = get_varlist();
  int currentline = get_activeline();
  if(op.men == numerical_calculation1)
     { if (op.choice == 7)  /* evalatpoint */
          { natoms = valuesprompt(prompt);
            if(natoms==0)
               return 0;    /* no variables in the problem */
            return (natoms==1 ? real : reallist);
          }
       return 0;
     }
  if(op.men == numerical_calculation2)
     { if (op.choice == 4) /* writenumberaspower */
          { strcpy(prompt, english(1881));  /* Enter the new exponent:  */
            return specific_positive_integer;
          }
       if (op.choice == 5) /* writenumberaspowerof */
          { strcpy(prompt, english(2360)); /* Enter the desired base: */
            return specific_positive_integer;
          }
       if (op.choice == 7) /* writeassum */
          { strcpy(prompt, english(1970));
            return anyterm;
          }
       return 0;
     }
  if(op.men == complex_arithmetic)
     { if (op.choice == 16)  /* evalatpoint */
          { natoms = valuesprompt(prompt);
            if(natoms==0)
               return 0;    /* no variables in the problem */
            return (natoms==1 ? real : reallist);
          }
       else
           return 0;
     }
  if(op.men == common_denominators)
     { if(op.choice == 12)  /* mult num and denom by ? */
          { strcpy(prompt,english(66));
            /* Multiply num and denom by what? */
            return notzerodenom;
          }
       else
          return 0;
     }
  if(op.men == advanced_square_roots)
     { if(op.choice == 10 || op.choice == 11)
          { strcpy(prompt, english(1587));
            /* Enter the exponent n */
            return positive_integer;
          }
       else
          return 0;
     }

  if(op.men == expand_powers)
     { if(op.choice == 4)  /* breakpower, a^n = a^?a^(n-?) */
          { strcpy(prompt, english(1917));
            /* Enter the first new exponent: */
            return anyterm;
          }
       if(op.choice == 10) /* reversepowertopower3, a^b? = (a^b)^? */
          { strcpy(prompt, english(1881));  /* Enter the new exponent:  */
            return anyterm;
          }
       return 0;
     }
  if(op.men == series_appearance)
     { if(op.choice == 6)  /* showmoreterms,  show ? more terms before ... */
          { strcpy(prompt, english(2323)); /* How many more terms do you want to see? */
            return positive_integer;
          }
       else
          return 0;
     }
  /* there are some stretches of many menus with no ops that need args: */

  if(op.men < factoring)
     return 0;
  if(op.men > change_base && op.men <= double_angle)
     return 0;
  if(op.men > verify_identities && op.men < chain_rule &&
     op.men != limits && op.men != advanced_limits &&
     op.men !=limits_of_quotients && op.men != lhopitalmenu &&
     op.men != infinite_limits
    )
     return 0;

  switch(op.men)
    { case multiple_angles:
         if(op.choice == 2)  /* querytrigarg, n\theta = ?\theta+(n-?)\theta  */
            { strcpy(prompt, english(123));
              /* Enter a positive integer, please: */
              return specific_positive_integer;
            }
         return 0;
      case binomial_theorem:
          if(op.choice == 9)  /* evaluate sum */
             goto there;
          return 0;
       case sigma_notation:
          if(op.choice == 10 ) /* showfirstterms */
             { strcpy(prompt, english(18));
                  /* How many terms do you want to see?  */
               return specific_positive_integer;
             }
          if(op.choice == 11 || op.choice == 12)  /* evaluate sum */
              there:   /* from binomial_theorem just above */
             { term k;
               if(evalsumarg_aux(SUM,history(currentline),&k))
                  return 0;
               strcpy(prompt, english(19)); /* "Enter value of " */
               strcat(prompt, atom_string(k));
               strcat(prompt, ":");
               return real;
             }
          return 0;
       case advanced_sigma_notation:
          if(op.choice == 1)  /* shift summation index */
             { strcpy(prompt, english(1325));  /* Add what to both upper and lower limits? */
               return integer;
             }
	      if(op.choice == 13) /* sumtodifofsums */
		     { strcpy(prompt, english(2506));    /* Enter the new lower limit of summation: */
			   return integer;
			 }
          return 0;
       case prove_by_induction:
          if(op.choice == 1)  /* select induction variable */
             { strcpy(prompt, english(20));
               /* Prove by induction on which variable? */
               return variable;
             }
          if(op.choice == 2)  /* basiscase */
             { int i = simple_select(history(currentline));
               if(i< 0)
                   return 0;  /* no induction variable yet */
               strcpy(prompt, english(21));
                 /* Enter starting value of  */
               strcat(prompt, atom_string(varlist[i]));
               return anyterm;
             }
          return 0;
       case factoring:
          if(op.choice == 14)  /* make_substitution */
             { strcpy(prompt, english(23));
               /* Enter your substitution (use = )  */
               return msubst; /* makesubstitution */
             }
          return 0;
       case advanced_factoring:
          if(op.choice == 1)
             { strcpy(prompt, english(24));
                 /*   Write it as a function of what?  */
               return anyterm;
             }
          if(op.choice == 2)
             { strcpy(prompt, english(25));
               /*  Enter two expressions separated by a comma: */
               return pair_of_terms;
             }
          if(op.choice == 4)  /* a^(?n) = (a^n)^? */
             { strcpy(prompt, english(1830));
               /* Enter the desired new exponent. */
               return specific_positive_integer;
             }
          if(op.choice == 13)  /* guess a factor */
             { strcpy(prompt, english(26));
               /*  Enter your proposed factor:  */
               return anyterm;
             }
          if(op.choice == 14) /* factorbypolydiv */
             { if(natoms > 1)
                  { strcpy(prompt,english(27));
                    /* Linear in which variable? */
                    return variable;
                  }
               else
                  return 0;
             }
          if(op.choice == 15) /* factorbygrouping*/
             { strcpy(prompt, english(28));
               /* Enter one of groups:  */
               return anyterm;
             }
          if(op.choice == 16) /* write it as a polynomial in */
             { strcpy(prompt, english(29));
                   /* Write it as a polynomial in what expression?  */
               return anyterm;
             }
          return 0;
       case solve_equations:
          if(op.choice == 3)  /*  add to both sides */
             { strcpy(prompt, english(30));
               /* Add what to both sides? " */
               return anyterm;
             }
          if(op.choice == 4)  /*  subtract from both sides */
             { strcpy(prompt, english(31));
               /* Subtract what from both sides? */
               return anyterm;
             }
          if(op.choice == 5)  /*  transfer1 */
             { strcpy(prompt,english(32));
               /* Transfer what term left to right?  */
               return anyterm;
             }
          if(op.choice == 6)  /*  transfer2 */
             { strcpy(prompt, english(33));
               /* Transfer what term right to left?  */
               return anyterm;
             }
          if(op.choice == 7)  /*  multiply both sides */
             { strcpy(prompt,english(34));
               /* Multiply both sides by what? */
               if(get_problemtype() == LINEAR_EQUATIONS)
                  return constant_condition;
               return anyterm;
               /* The operator itself will reject terms that can be
                  inferred to be zero; you do have to allow expressions
                  involving the variable that cannot necessarily be
                  inferred to be nonzero though. */
             }
          if(op.choice == 8)  /*  divide both sides */
             { strcpy(prompt, english(35));
                /* Divide both sides by what?  */
               if(get_problemtype() == LINEAR_EQUATIONS)
                  return nonzero_constant;
               if(get_problemtype() == TRIG_IDENTITY)
                  return anyterm; /* we don't want any assumptions made about the 
                               denominator being nonzero.  The operation only
                               works when no such assumption is necessary. */
               return notzerodiv;
             }
          return 0;
       case selection_mode_only:
          if(op.choice == 4)  /* solvelinearfor */
             { strcpy(prompt, english(639)); /* Solve for which variable? */
               return variable;
             }
          return 0;
       case quadratic_equations:
          if(op.choice == 9)  /*  selecteqn */
             { strcpy(prompt,english(36));
               /*  Work on which equation?  Enter 1,2,3... */
              return condition_index;
             }
          return 0;
       case numerical_equations:
          if(op.choice == 1) /*   evalatpoint */
             { natoms = valuesprompt(prompt);
               if(natoms==0)
                  return 0;    /* no variables in the problem */
               return (natoms==1 ? real : reallist);
             }
          if(op.choice == 2) /*  solvenumerically (need bracketing points) */
             { char localbuf[128];
               char *marker, *rest;
               natoms = valuesprompt(prompt);  /* This counts the eigenvariable */
               if(natoms==0)
                  return 0;  /* no variables in the problem */
               if(natoms == 1)
                  { strcpy(prompt,english(43));
                    /* Find root between what two numbers?  */
                    return tworeals;
                  }
               /* Now natoms > 1; we need the values of the parameters
                  AND the bracketing numbers.  We need to generate
                  TWO prompts, and put them into one string separated
                  by a $ character.  The first prompt is similar to
                  what is already in prompt (put there by valuesprompt)
                  but shouldn't mention the eigenvariable.  The
                  eigenvariable's name will just precede the first
                  comma in prompt.
                */
               strcpy(localbuf,prompt);  /* prompt will be the destination */
               strcpy(prompt, natoms==2 ? english(19) : english(42));
                  /* Enter value of ;  Enter values of  */
               marker = strchr(localbuf, ',');
               assert(*marker == ',');  /* there has to be a comma */
               rest = marker+1;
               strcat(prompt, rest);
               strcat(prompt,"$");  /* separate first and second prompts */
               strcat(prompt,english(43));
               /* Find root between what two numbers?  */
               return natoms == 2 ? twoprompts1 : twoprompts;
             }
          return 0;
       case advanced_equations:
          if(op.choice == 2)    /* powereqn */
             { unsigned short f,g;
               if(FUNCTOR(history(currentline)) != '=')
                  return 0;
               f = FUNCTOR(ARG(0,history(currentline)));
               g = FUNCTOR(ARG(1,history(currentline)));
               if(f==SQRT || f == ROOT || g == SQRT || g == ROOT)
                    return 0;   /* power will be chosen automatically */
               strcpy(prompt,english(37));
                  /* Raise both sides to what power? */
               return notzeropower;
             }
          if(op.choice == 4)    /* rooteqn */
             { unsigned short f,g;
               if(FUNCTOR(history(currentline)) != '=')
                  return 0;
               f = FUNCTOR(ARG(0,history(currentline)));
               g = FUNCTOR(ARG(1,history(currentline)));
               if(f== '^' || g == '^')
                    return 0;   /* arg will be chosen automatically, or op will fail */
               strcpy(prompt, english(39));
                 /* Take what root of both sides?  */
               return positive_integer;
             }
          if(op.choice == 5)    /*  apply_fn_to_both_sides */
             { strcpy(prompt, english(40));
                /*  Apply what function to both sides?  */
               return function;
             }
          if(op.choice == 9)   /*   selecteqn */
             { strcpy(prompt, english(36));
                /* Work on which equation?  Enter 1,2,3... */
               return condition_index;
             }
          if(op.choice == 12)  /* makesubstitution */
             { strcpy(prompt, english(23));
               return msubst;
             }
          return 0;
       case cubic_equations:
          if(op.choice == 8)  /* reversesub */
             { strcpy(prompt, english(23));
               return revsubst;
             }
          if(op.choice == 10) /* translatevar */
             { strcpy(prompt, english(1939));
               /* Enter  n = integer - k, where n is the variable to change. */
               return revsubst;
             }
          return 0;
       case logarithmic_equations:
          if(op.choice == 1)    /* raise arg to both sides */
             { unsigned short f,g;
               int k;
               term t = history(currentline);
               if(FUNCTOR(t) == OR)
                  { k = abs(get_selected_equation());
                    if(k)
                       t= ARG(k,t);
                  }
               if(FUNCTOR(t) != '=')
                  return 0;  /* operation will be inapplicable anyway */
               f = FUNCTOR(ARG(0,t));
               g = FUNCTOR(ARG(1,t));
               if(f==LN || f == LOG || f == LOGB || g == LN || g == LOG || g == LOGB)
                    return 0;   /* arg will be chosen automatically */
               strcpy(prompt,english(38));
                  /* Enter a in u=v => a^u = a^v: */
               return notzerobase;
             }
          return 0;
       case several_linear_equations:
          if(op.choice == 4)   /* add_two_eqns */
             { strcpy(prompt,english(44));
                  /* Add eqn no. ? to eqn no. ? " */
               return indexpair;
             }
          if(op.choice == 5)  /* sub_two_eqns */
             { strcpy(prompt,english(45));
                 /* Subtract eqn no. ? from eqn no. ? */
               return indexpair;
             }
          if(op.choice == 6)  /* muleqns */
             { strcpy(prompt,english(46));
                  /* Multiply equation number ? by ? */
               return index_and_term;
             }
          if(op.choice == 7)   /* diveqns */
             { strcpy(prompt, english(47));
                 /* Divide equation number ? by ?  */
               return index_and_nonzero_term;
             }
          if(op.choice == 8)   /* addmuleqns */
             { strcpy(prompt,english(48));
                 /* Add ? times eqn no. ? to eqn no. ?  */
               return term_and_indexpair;
             }
          if(op.choice == 9)    /* sub_multiple of eqn to eqn */
             { strcpy(prompt, english(49));
                /* Subtract ? times eqn no. ? from eqn ?  */
                return term_and_indexpair;
             }
          if(op.choice == 10)    /* swap two equations */
             { term problem = history(0);
               if(FUNCTOR(problem) == AND && ARITY(problem) == 2)
                  return 0;  /* only two equations, no choice needed */
               strcpy(prompt, english(51));
               /* Swap eqns ? and ? (enter 2 numbers)  */
                return indexpair;
             }
          if(op.choice == 13)   /*  "regard a variable as constant " */
             { strcpy(prompt, english(52));
               /* Regard which variable as constants? */
                return variable;
             }
          return 0;
       case linear_equations_by_selection:
          if(op.choice == 7) // swap_eqns, when only two equations exist
             return 0;
          // fall through is deliberate
          
       case linear_equations_by_substitution:
          if(op.choice == 2)   /* solve equation ? for ?  */
             { strcpy(prompt, english(1315));
               /* Solve equation ? for ? */
               return index_and_var;
             }
          if(op.choice == 5)   /* eqnsaddterm */
             { strcpy(prompt, english(1319));
               /* Add ? to both sides of equation ? */
               return term_and_index;
             }
          if(op.choice == 6)   /* eqnssubterm */
             { strcpy(prompt, english(1320));
               /* Subtract ? from both sides of equation ? */
               return term_and_index;
             }
          if(op.choice == 7)   /* diveqns */
             { strcpy(prompt, english(47));
                 /* Divide equation number ? by ?  */
               return index_and_nonzero_term;
             }
          if(op.choice == 8)  /* substforvar */
             { strcpy(prompt, english(50));
               /* Substitute for which variable? */
               return variable;
             }
          return 0;

       case matrix_methods:
          if(op.choice == 3) /*  swap two rows */
             { term problem = history(0);
               if(FUNCTOR(problem) == AND && ARITY(problem) == 2)
                  return 0;  /* only two equations, no choice needed */
               strcpy(prompt, english(53));
               /* Swap rows ? and ?  */
                return indexpair;
             }
          if(op.choice == 4)   /* add two rows */
             { strcpy(prompt, english(54));
                  /* Add row ? to row ?  */
                return indexpair;
             }
          if(op.choice == 5)   /*  sub one row from another */
             { strcpy(prompt, english(55));
                  /* Subtract row ? from row ?  */
               return indexpair;
             }
          if(op.choice == 6)  /*   multiply one row by a constant */
             { strcpy(prompt, english(56));
                 /* Multiply row ? by ? " */
               return index_and_term;
             }
          if(op.choice == 7)  /* divide one row by a constant */
             { strcpy(prompt, english(57));
                /*  Divide row ? by ?  */
               return index_and_nonzero_term;
             }

          if(op.choice == 8)  /*  add multiple of one row to another */
             { strcpy(prompt, english(58));
                     /* Add ? times eqn no. ? to eqn no. ? */
               return term_and_indexpair;
             }
          if(op.choice == 9)   /*  sub multiple of one row from another */
             { strcpy(prompt, english(59));
                  /* Subtract ? times eqn no. ? from eqn no. ?  */
               return term_and_indexpair;
             }
          return 0;

       case advanced_matrix_methods:  return 0;
       case absolute_value:           return 0;

       case less_than:
          if(op.choice == 2)    /*  addeqn1 */
             { strcpy(prompt,english(30));
                 /* Add what to both sides? */
               return anyterm;
             }
          if(op.choice == 3)    /*  subeq1 */
             { strcpy(prompt, english(31));
                 /* Subtract what from both sides?  */
               return anyterm;
             }
          if(op.choice == 6) /* mulineq */
             { strcpy(prompt, english(34));
                  /*  Multiply both sides by what? */
               return anyterm;
             }
          if(op.choice == 7)  /* mulineqsq */
             { strcpy(prompt,english(1562));
                  /*  Multiply both sides by the square of what?  */
               return anyterm;
             }
          if(op.choice == 8)     /*  div by positive */
             { strcpy(prompt, english(35));
                  /* Divide both sides by what?  */
               return notzerodiv;
             }
          return 0;

       case greater_than:
          return 0;
       case less_than_or_equals:
          if(op.choice == 2)   /*  addeqn2 */
             { strcpy(prompt, english(30));
                 /* Add what to both sides?" */
               return anyterm;
             }
          if(op.choice == 3)   /*  subeqn2 */
             { strcpy(prompt, english(31));
               /* Subtract what from both sides? */
               return anyterm;
             }
          if(op.choice == 6) /* mulineq */
             { strcpy(prompt, english(34));
                  /*  Multiply both sides by what? */
               return anyterm;
             }
          if(op.choice == 7)  /* mulineqsq */
             { strcpy(prompt,english(1562));
                  /*  Multiply both sides by the square of what?  */
               return anyterm;
             }
          if(op.choice == 8)     /*  div by positive */
             { strcpy(prompt, english(35));
                  /* Divide both sides by what?  */
               return notzerodiv;
             }
          return 0;
       case greater_than_or_equals:
          return 0;
       case root_ineq1:
          if(op.choice ==11)  /* powerineq16 */
             { strcpy(prompt, english(60));
                 /* Raise both sides to what positive odd power? */
               return positiveoddinteger;
             }
          if(op.choice ==12)  /* powerineq17 */
             { strcpy(prompt, english(511));
                 /* Raise both sides to what positive power? */
               return pos;
             }
          return 0;
       case root_ineq2:
          if(op.choice ==11)  /* powerineq26 */
             { strcpy(prompt,english(61));
                /* Raise both sides to what nonnegative odd power? */
               return nonnegativeoddinteger;
             }
          if(op.choice ==12)  /* powerineq27 */
             { strcpy(prompt, english(511));
                 /* Raise both sides to what positive power? */
               return pos;
             }
          return 0;
       case root_ineq3:
          if(op.choice ==9)  /* powerineq16 */
             { strcpy(prompt, english(60));
                 /* Raise both sides to what positive odd power? */
               return positiveoddinteger;
             }
          if(op.choice ==10)  /* powerineq17 */
             { strcpy(prompt, english(511));
                 /* Raise both sides to what positive power? */
               return pos;
             }
          return 0;
       case root_ineq4:
          if(op.choice ==9)  /* powerineq26 */
             { strcpy(prompt,english(61));
                /* Raise both sides to what nonnegative odd power? */
               return nonnegativeoddinteger;
             }
          if(op.choice ==10)  /* powerineq27 */
             { strcpy(prompt, english(511));
                 /* Raise both sides to what positive power? */
               return pos;
             }
          return 0;
       case log_ineq1:
          if(op.choice == 7)
             { strcpy(prompt, english(62));
                 /* Enter a in a^u < a^v ?  */
               return pos;
            }
       case log_ineq2:
          if(op.choice == 7)
             { strcpy(prompt, english(1647));
                 /* Enter a in a^u <= a^v ?  */
               return pos;
            }
       case log_ineq3:
          if(op.choice == 7)
             { strcpy(prompt, english(1648));
                 /* Enter a in a^u > a^v ?  */
               return pos;
            }
       case log_ineq4:
          if(op.choice == 7)
             { strcpy(prompt, english(1649));
                 /* Enter a in a^u >= a^v ?  */
               return pos;
            }
       case logarithms:
          if(op.choice == 14)
             { strcpy(prompt, english(1289));
               /* Enter a, the desired new exponent: */
               return anyterm;
             }
          return 0;
       case natural_logarithms:
          if(op.choice == 13)
             { strcpy(prompt, english(1289));
               /* Enter a, the desired new exponent: */
               return anyterm;
             }
          return 0;
       case complex_polar_form:
          return 0;
       case logs_to_any_base:
          return 0;
       case change_base:
          if(op.choice == 3)  /* changebase */
             { strcpy(prompt,english(63));
                /* Enter new base of logarithms: */
               return pos;
             }
          if(op.choice == 9)  /* introducelogbinexponent */
             { strcpy(prompt,english(63));
               return pos;
             }
          return 0;
       case verify_identities:
          if(op.choice == 3)    /* transfer1 */
             { strcpy(prompt,english(32));
                /* Transfer what term left to right? */
               return anyterm;
             }
          if(op.choice == 4)    /* transfer2 */
             { strcpy(prompt, english(33));
                /* Transfer what term right to left? */
               return anyterm;
             }
          if(op.choice == 5) /*   add_term */
             { strcpy(prompt, english(30));
                 /* Add what to both sides?  */
               return anyterm;
             }
          if(op.choice == 6) /*   sub_term */
             { strcpy(prompt,english(31));
                /* Subtract what from both sides? */
               return anyterm;
             }
          if(op.choice == 7)     /* multiply both sides */
             { strcpy(prompt, english(34));
                /*  Multiply both sides by what? */
               return notzeromul;
             }
          if(op.choice == 11) /* apply function */
             { strcpy(prompt,english(64));
                /*  Apply what function to both sides? */
               return function;
             }
          if(op.choice == 14) /* check numerically */
             { natoms = valuesprompt(prompt);
               if(natoms == 1)
                  return real;
               else
                  return reallist;
             }
          if(op.choice == 15)
             { strcpy(prompt, english(23));
               /* Enter your substitution (use = )  */
               return msubst; /* makesubstitution */
             }
          return 0;
       case limits:
          if(op.choice == 1)   /* testlimit */
             { strcpy(prompt, english(41));
                /* Evaluate at what value of  */
               strcat(prompt,atom_string(get_eigenvariable()));
               strcat(prompt,"?");
               return real;
             }
          return 0;
       case limits_of_quotients:
          if(op.choice == 8)  /* pulloutnonzerolimit */
             { strcpy(prompt,english(65));
                 /* Enter u in lim uv = lim u lim v  */
               return anyterm;
             }
          if(op.choice == 10)  /* multnumdenom */
             { strcpy(prompt,english(66));
                /* Multiply num and denom by what? */
               return notzeroinlimit;
             }
          if(op.choice == 11 || op.choice == 12) /* divnumdenom2, divnumdenom */
             { strcpy(prompt,english(67));
                  /* Divide num and denom by what?  */
               return notzeroinlimit;
             }
          if(op.choice == 13) /* limapartandfactor */
             { strcpy(prompt,english(533));
                 /* Enter the common factor (a in the formula): */
               return anyterm;
             }
          return 0;
       case quotients_of_roots:
          return 0;
       case special_limits:
          return 0;
       case infinite_limits:
          if(op.choice == 11 || op.choice == 12)  /* limprod2left, limprod2right */
             { strcpy(prompt, english(1948));
               /* Multiply one factor and divide the other by what? */
               return notzeroinlimit;
             }
          return 0;
       case lhopitalmenu:
          switch(op.choice)
             { case 8:   /* createcompoundfraction */
                  strcpy(prompt,english(69));
                     /*  Enter the term u to move to the denominator */
                  return notzerodenom;
             }
          return 0;
       case advanced_limits:
          switch(op.choice)
             { case 3:  /* changelimitvariable */
                  strcpy(prompt,english(68));
                     /* Enter u like this: u = x/h */
                  return msubst;
               case 6:   /* createcompoundfraction */
                  strcpy(prompt,english(69));
                     /*  Enter the term u to move to the denominator */
                  return notzerodenom;
             }
          return 0;
       case chain_rule:
          if(op.choice == 11) /*  "make a substitution" */
             { strcpy(prompt, english(23));
                /*  Enter your substitution.  Use =  */
               return msubst;
             }
          return 0;
       case minima_and_maxima:
          if(op.choice == EVALATPOINT)
             { natoms = valuesprompt(prompt);
               return real;  /*  evaluate_numerically */
             }
          return 0;
       case related_rates:
          return 0;
       case simplify:
          if(op.choice == 9)  /* writeaspoly */
             { strcpy(prompt, english(73));
                  /* Write as polynomial in what expression? */
               return anyterm;
             }
          return 0;
       case higher_derivatives:
          if (op.choice == 7)  /* evalatpoint */
             { natoms = valuesprompt(prompt);
               if(natoms==0)
                  return 0;    /* no variables in the problem */
               return (natoms==1 ? real : reallist);
             }
          return 0;
       case basic_integration:
          return 0;
       case trig_integration:
          return 0;
       case integrate_by_substitution:
          if(op.choice == 1  /*  make_substitution */
             || op.choice == 9  /* intsub */
            )
             { strcpy(prompt, english(23));
                 /* Enter your substitution.  Use =  */
               return msubst;
             }
          return 0;
       case integrate_by_parts:
          if(op.choice == 1)   /* one of the parts */
             { strcpy(prompt,english(75));
                /*   Enter your choice of u, the part to differentiate */
               return intbyparts1;
             }
          if(op.choice == 6)   /* intsub  */
             { strcpy(prompt, english(23));
                 /*  Enter your substitution (use = )  */
               return msubst; /* make_substitution */
             }
          return 0;
       case definite_integration:
          if(op.choice == 5)   /* insertpoint  (break up integral into two integrals) */
             { strcpy(prompt, english(76));
               /*  Enter the intermediate point (or points) b: */
                return tlist;
             }
          if(op.choice == 7)   /* numerical integration */
             { term k;
               if(evalsumarg_aux(SUM,history(currentline),&k))
                  return 0;
               strcpy(prompt, english(77));
                  /* Enter value of  */
               strcat(prompt, atom_string(k));
               strcat(prompt, ":");
               return real;
             }
          return 0;
       case trig_substitutions:
          if(op.choice==7)
             { strcpy(prompt, english(1528));
                /* Enter your substitution like this: x = sin u */
               return trigsubst;
             }
          return 0;
       case integrate_sqrtdenom:
          if(op.choice==5)
             { strcpy(prompt, english(78));
                /* Enter your substitution like this: u = sin x  */
               return trigsubst;
             }
          return 0;
       case simplify_calculus:
          if(op.choice == 11) /* intsub */
             { strcpy(prompt,english(23));
                 /* Enter your substitution.  Use =  */
               return msubst;
             }
          return 0;
       case series_manipulations:
          if(op.choice==1)  /* seriesfirstterms */
             { strcpy(prompt, english(2248));
                /* How many terms do you want explicitly written out? */
               return positive_integer;
             }
          if(op.choice == 2)  /* seriesmoreterms */
             { strcpy(prompt, english(2249));
               /* Decrease the lower limit of summation by how much? */
               return positive_integer;
             }
          if(op.choice == 3)  /* seriesaddindex */
             { strcpy(prompt, english(2250));
               /* Add what to the index variable? */
               return positive_integer;
             }
          if(op.choice == 4)  /* seriessubindex */
             { strcpy(prompt, english(2251));
               /* Subtract what from the index variable? */
               return positive_integer;
             }
          if(op.choice==11)  /* evalfirstterms */
             { strcpy(prompt, english(2311));
                /* Calculate the sum of the first how many terms? */
               return positive_integer;
             }
          return 0;
       case series_convergence_tests:
          if(op.choice == 5 || op.choice == 6 || op.choice == 7)
             /* comparison tests or limitcomparisontest */
             { strcpy(prompt, english(2277));
               /* Enter the general term of the comparison series:  */
               return anyterm;
             }
          return 0;

    }
   return 0;
}

/*______________________________________________________*/
static int invalid_index(term t)
/* check whether t is an integer between 1 and the arity of the current
set of equations, or number of rows of the matrix equation.
 Zero return means it's valid. */
/* Nonzero return values can be put into checkarg_msg(); */
{  int currentline = get_currentline();
   unsigned short f = FUNCTOR(history(currentline));
   unsigned long k;
   unsigned short n;
   if(! (OBJECT(t) && TYPE(t)==INTEGER) )
      return 7;
   if( f == AND || f == OR)
      n = ARITY(history(currentline));
   else if(f == '=' && is_matrix_product(ARG(1,history(currentline)),&n))
      ; /* do nothing */
   else
      assert(0);
   k = INTDATA(t);
   if( k > n) return 9;
   return 0;
}

/*_______________________________________________________________*/
static int no_new_vars(term t)
/* return 0 if all atoms in t (except 'pi', 'e', and
   if complex, 'i' ) already occur in varlist;
   return 1 otherwise. */
{ term *atomlist;
  unsigned natoms;
  unsigned nvariables = get_nvariables();
  term *varlist = get_varlist();
  unsigned i,j;
  unsigned short f;
  natoms = atomsin(t,&atomlist);   /* allocating space */
  for(i=0;i<natoms;i++)
    { f = FUNCTOR(atomlist[i]);
      if(f == 'e' || f == PI_ATOM || (get_complex() && f == 'i'))
         continue;
      for(j=0;j<nvariables;j++)
         { if(equals(varlist[j],atomlist[i]))
               break;
         }
      if(j==nvariables)
         { free2(atomlist);
           return 1;   /* can't find atomlist[i] in the varlist */
         }
    }
  free2(atomlist);
  return 0;   /* successfully found every atomlist[i] */
}
/*___________________________________________________________*/
static int evalsumarg_aux(unsigned short h, term t, term *ans)
/* see if t contains an indexed sum or product or definite integral,
whichever is specified by the formal parameter h.
If so, does it (specifically the leftmost sum or product)
contain an "extra" FREE variable? (not the index variable, and not a
variable which is bound in the summand, e.g. in the case of a double sum,
or of a sum of integrals, and not a variable which is bound OUTSIDE the
sum, as when a sum is in an integrand)
If so, return that variable in *ans, and return 0 for success.
If there is no such, or more than one such variable, return 1 for failure.
If t does not contain a SUM or PRODUCT, return 2.
*/
{ int natoms;
  term *atomlist;
  term index;
  int nvariables = get_nvariables();
  term *varlist = get_varlist();
  varinf *varinfo = get_varinfo();
  int i,j,cnt=0,err,k=-1;
  unsigned short f = FUNCTOR(t);
  unsigned short n = ARITY(t);
  if(ATOMIC(t))
     return 2;
  if(f != h)
    {for(i=0;i<n;i++)
       { err = evalsumarg_aux(h,ARG(i,t),ans);
         if(err < 2)
            return err;
       }
     return 2;  /* no sum or product encountered */
    }
  natoms = atomsin(t,&atomlist);
  index = ARG(1,t);
  for(i=0;i<natoms;i++)
    { f = FUNCTOR(atomlist[i]);
      if(f != 'e' && f != 'i' && f!= INFINITYFUNCTOR && f != PI_ATOM && f != FUNCTOR(index))
         { for(j=0;j<nvariables;j++)
              { if(FUNCTOR(varlist[j])==f)
                   { if(varinfo[j].scope != BOUND)
                        { *ans = atomlist[i];
                          ++cnt;
                          k = i;
                          break;
                        }
                   }
              }
           assert(j<nvariables);  /* must find the variable in varlist */
          }
    }
  free2(atomlist);  /* allocated by atomsin */
  if(cnt > 1)
    { errbuf(0,english(1186));
               /* More than one parameter is present, */
      errbuf(1, english(1187));
               /*  but only one is allowed. */
      return 1;   /* too many variables */
    }
  if(k < 0)
     return 1; /* no extra variables */
  return 0;
}
/*____________________________________________________________*/
static int valuesprompt(char *buffer)

/* list the atoms in order and create a prompt that asks for their values.
Return the number of atoms in question.
Don't count pi_term, e, and i (which is bound if it isn't complexi);
and don't count  other bound variables either. */

{ term t = history(get_activeline());
  int nvariables = get_nvariables();
  term x;
  int i,k;
  int natoms;
  term *atomlist;
  atomlist = (term *) callocate(nvariables, sizeof(term));
  natoms = get_ind_set(t,atomlist);
  if(natoms==1)
     { strcpy(buffer,english(41));
         /* Evaluate at what value of  */
       strcat(buffer,atom_string(atomlist[0]));
       strcat(buffer,"? ");
       free2(atomlist);
       return 1;
     }
  /* Now there are several variables.  Make sure the eigenvariable
  is mentioned first if it occurs. */

  x = get_eigenvariable();
  k=0;
  for(i=0;i<natoms;i++)
     { if(equals(x,atomlist[i]))
          { k=i;
            break;
          }
     }
  if(k != 0)
     { /* swap atomlist[0] and atomlist[k] */
       term temp = atomlist[0];
       atomlist[0] = atomlist[k];
       atomlist[k] = temp;
     }
  strcpy(buffer, english(42));
     /* Enter values of  */
  for(i=0;i<natoms;i++)
     { strcat(buffer,atom_string(atomlist[i]));
       if(i < natoms-1)
          strcat(buffer,",");
       else
          strcat(buffer,": ");
     }
  free2(atomlist);
  return natoms;
}
/*______________________________________________________*/
 int checkarg_msg(int i, char *buffer, int bufferlength)
/* error messages for incorrect argument entry */
/* maximum message length 'bufferlength' characters */
/* Copy the message into buffer. If it's too long, copy
at most bufferlength characters.
Return 0 for success, 1 for failure.
Too long message is not considered failure.
*/

{ int natoms=0;  // initialization to silence a warning
  assert(i > 0);
  if(i >=70 && i < 100)
     { natoms = i-70;
       i = 40;
     }
  if(i > 1000)
     { strncpy(buffer, english(i),bufferlength);
       /* these strings were added after the original strings were
       packed into the english array, and there was no more room
       to add more strings contiguously. */

       return 0;
     }
  if(i <= 62)
     switch(i)
        { case 40:
             strncpy(buffer,english(133),bufferlength);
             /* Please enter exactly 4 numbers.  */
			 sprintf(buffer+21,"%d",natoms);
             strcat(buffer,english(1285));
             /* " numbers." (buffer is long enough to receive it) */
             if(natoms <= 9)
               strcat(buffer," ");    /* write over final period remaining in
                 buffer from previous call, if previous call had natoms > 9 */
             return 0;  /* works even if natoms > 9 */
          case 41:
             strncpy(buffer,english(134),bufferlength);
             strcat(strchr(buffer,'*'),atom_string(get_eigenvariable()));
             strcat(buffer,". ");
             return 0;
          default:
             strncpy(buffer,english(93 + i),bufferlength);
             return 0;
        }
  if(i > 100)
     { strncpy(buffer,input_error_message(i-100),bufferlength);
        /* generated by 'mathematical', the condition for anyterm */
       return 0;
     }
  assert(0);   /* should never get here */
  return 1;    /* avoid a warning */
}

/*______________________________________________________*/
 int check_arg(term t, condition c)
 /* does the term satisfy the condition?  */
 /* return 0 if it does; nonzero return means it won't do,
 and is an index to an error message.  These messages
 are accessed by checkarg_msg; they are stored in
 english.c as part of the large array of strings there.
 */
{ int err,i,k,linenumber;
  int nvariables,problemtype;
  term *varlist;
  term ans;
  double a,b;
  int f = FUNCTOR(t);
  switch(c)
     {  case intbyparts1:
        case intbyparts2:
           if(FUNCTOR(t) == INTEGRAL)
              return 50;  // FINISH this, get english(786) somehow
            // fall through err = no_new_vars(t);
        case anyterm:
           err = no_new_vars(t);
           if(err)
              return 50;
           /* deliberate fall-through */
        case absolutelyanyterm:
           err = mathematical(t);
           if(!err)
              break;
           return 100 + err;
        case pair_of_terms:
           err = no_new_vars(t);
           if(err)
              return 50;
           if (f != AND && f != OR)
               return 1;
           if (ARITY(t) != 2)
               return 2;
           break;
        case variable:  /* fall-through */
           /* list box is used as input, but if the selected term is used for
              an argument, it could be any term, so we need to check it anyway;
              however, the return value will not be used for message, so it
              only has to be nonzero if there is an error. */
           return ISATOM(t) ? 0 : 1;
        case variables:
           if(ISATOM(t)) /* see comment just above. */
              return 0;
           if(FUNCTOR(t) == AND)
              { for(i=0;i<ARITY(t);i++)
                   { if(!ISATOM(t))
                        return 1;
                   }
                return 0;
              }
           return 1;
        case constant_condition:
           if(!constant(t))
              return 62;  /* Please enter a constant */
           return 0;
        case nonzero_constant:
           if(!constant(t))
              return 62;  /* Please enter a constant */
           /* fall through to notzero */
        case notzero:
        case notzerodiv:
        case notzeromul:
        case notzeropower:
        case notzerobase:
        case notzerodenom:
           problemtype = get_problemtype();
           if(ZERO(t))
              { if(c == notzerodiv)
                   return 2397;  /* Division by zero is not allowed. */
                if(c == notzeromul)
                   return 1726;  /* You are not allowed to multiply by zero. */
                if(c == notzeropower)
                   return 2398; /* That would produce the useless equation 1 = 1, since any nonzero number to the zero-th power is 1. */
                if(c == notzerobase)
                   return 2399; /* That would produce the useless equation 0 = 0, since zero raised to any nonzero power is zero. */
                if(c == notzerodenom)
                   return 2400;  /*  That would produce a fraction with zero in the denominator, which is not defined. */
              }
           if(seminumerical(t))
              { err = deval(t,&a);
                if(err == 0 && a == 0.0)
                   return 5; /* that expression evaluates to zero, please try again. */
                if(err == 0)
                   return 0; /* nonzero numerical value */
              }
           err = no_new_vars(t);
           if(err)
              return 50;
           /* Now dealing with a non-numerical term; pass it to infer */
           err = mathematical(t);
           if(err)
              return 100 + err;
           if(SOLVETYPE(problemtype) && contains(t,FUNCTOR(get_eigenvariable())))
              { short savenextassumption;
                int savenvariables, saveeigen;
                term pp;
                if(inconsistent(equation(t,zero)))
                   { err = 0;
                     break;
                   }
                if(inconsistent(ne(t,zero)))
                   return 6;
                savenvariables = get_nvariables();
                saveeigen = get_eigenindex();
                savenextassumption = get_nextassumption();
                pp = lpt(ne(t,zero));
                set_nvariables(savenvariables);
                set_eigenvariable(saveeigen);
                set_nextassumption(savenextassumption);
                if(inconsistent(pp))
                   return 6;
                break;    /* allow the division even though we haven't been
                          able to check that it's by a nonzero factor.
                          The operation will perform a more thorough check. */
              }
           ans = ne(zero,t);
           err = check1(ans);
           if(err)
              return 6;
           break;
        case notzeroinlimit:
           if(seminumerical(t))
              { err = deval(t,&a);
                if(err == 0 && a == 0.0)
                   return 5;
                if(err == 0)
                   return 0; /* nonzero numerical value */
              }
           err = no_new_vars(t);
           if(err)
              return 50;
           err = mathematical(t);
           if(err)
             return 100 + err;
           break;
           /* In case of a non-numerical term, we DO NOT pass it
           to infer as with 'notzero', because it probably contains
           a bound variable, and infer won't have the binder list
           properly set up and will miss the inference, generating
           an inappropriate assumption involving a bound variable.
           Just accept ANY symbolic expression. */

        case condition_index:
           return invalid_index(t);
        case indexpair:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 2;
           if (invalid_index(ARG(0,t)) || invalid_index(ARG(1,t)))
              return 9;
           if ( INTDATA(ARG(0,t)) == INTDATA(ARG(1,t)) )
              return 10;
           return 0;
        case reallist:
           if(natoms > 1)
              { int i;
                if(FUNCTOR(t) != AND)
                   return 1;
                if(ARITY(t) != natoms)
                   return 70+natoms;
                   /* The error code is really 40, but the
                      range 70-100 isn't used, and we need to
                      pass natoms, so we use this method;
                      checkarg decodes 70 + natoms to assign
                      natoms to a local variable */

                for(i=0;i<natoms;i++)
                   { err = check_arg(ARG(i,t),real);
                     if(err)
                        return err;
                   }
                return 0;
             }
          /* and if natoms == 1  fall through to the case real */
        case real:
           err = mathematical(t);  /* rule out AND etc. */
           if(err)
              return 100 + err;
           if(get_complex())  /* then actually complex values are allowed */
              return complexnumerical(t) ? 0 : 11;
           return seminumerical(t) ?  0 : 11;
        case positive_real:
           err = mathematical(t);
           if(err)
              return 100 + err;
           if(!seminumerical(t))
              return 11;
           err = deval(t,&a);
           if( err == 0 && a <=0.0)
              return 19;
           if( err )
              return 11;
           return 0;
        case nonzeroreal:
           err = mathematical(t);
           if(err)
              return 100 + err;
           if(!seminumerical(t))
              return 11;
           err = deval(t,&a);
           if (err == 0  && a== 0.0)
              return 15;
           if(err)
              return 11;
           return 0;
        case tworeals:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 12;
           if(!seminumerical(ARG(0,t)))
              return 13;
           err = deval(ARG(0,t),&a);
           if(err)
              return 13;
           if(!seminumerical(ARG(1,t)))
              return 13;
           err = deval(ARG(1,t),&b);
           if(err)
              return 13;
           return 0;
        case index_and_term:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 15;
           if (invalid_index(ARG(0,t)))
              return 17;
           if (!constant(ARG(1,t)))
              return 62;   /* Please enter a constant. */
           break;
        case index_and_var:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 15;
           if (invalid_index(ARG(0,t)))
              return 17;
           if(!ISATOM(ARG(1,t)))
              return 59;
           break;

        case term_and_index:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 15;
           if (invalid_index(ARG(1,t)))
              return 17;
           if(!constant(ARG(0,t)))
              return 62;
           break;

        case index_and_nonzero_term:
           if (f != AND && f != OR)
              return 1;
           if (ARITY(t) != 2)
              return 15;
           if (invalid_index(ARG(0,t)))
              return 17;
           if(!constant(ARG(1,t)))
              return 62;  /* please enter a constant */
           ans = ne(ARG(1,t),zero);
           err = check1(ans);
           if(err)
              return 18;
           break;
        case pos:
           err = no_new_vars(t);
           if(err)
              return 50;
           err = mathematical(t);
           if(err)
              return 100 + err;
           ans = make_term('<',2);
           ARGREP(ans,0,zero);
           ARGREP(ans,1,t);
           err = check1(ans);
           if(err)
              return 19;
           break;
        case neg:
           err = no_new_vars(t);
           if(err)
              return 50;
           err = mathematical(t);
           if(err)
              return 100 + err;
           ans = make_term('<',2);
           ARGREP(ans,0,t);
           ARGREP(ans,1,zero);
           err =check1(ans);
           if(err)
              return 20;
           break;
        case nonneg:
           err = no_new_vars(t);
           if(err)
              return 50;
           err = mathematical(t);
           if(err)
              return 100 + err;
           ans = make_term(LE,2);
           ARGREP(ans,0,zero);
           ARGREP(ans,1,t);
           err = check1(ans);
           if(err)
              return 21;
           break;
        case nonpos:
           err = no_new_vars(t);
           if(err)
              return 50;
           err = mathematical(t);
           if(err)
              return 100 + err;
           ans = make_term(LE,2);
           ARGREP(ans,0,t);
           ARGREP(ans,1,zero);
           err =check1(ans);
           if(err)
              return 22;
           break;
        case positive_integer:  /* symbolic value allowed */
           if(ISINTEGER(t))
              return 0;
           if(isinteger(t) && obviously_positive(t))
              return 0;
           if(OBJECT(t) && TYPE(t) == BIGNUM)
              return 34;
           return 30;

        case specific_positive_integer:
           if(!OBJECT(t))
              return 30;
           if(ISZERO(t))
              return 1876;
              /* Please enter a positive integer. Zero is not positive. */
           if( TYPE(t)== DOUBLE)
               { double x = DOUBLEDATA(t);
                 int m = (int) x;
                 if (x == (double) m)
                    return 0;  /* ok, it's a decimal integer */
                 else
                    return 30;
                }
           if( TYPE(t) == BIGNUM)
              return 34;
           if(!ISINTEGER(t))
              return 30;
           return 0;
        case integer:
           if(NEGATIVE(t))
               t = ARG(0,t);
           if( ! OBJECT(t))
              { err = infer(type(t,INTEGER));
                if(err)
                   return 30;
                return 0;
              }
           if( TYPE(t)== DOUBLE)
               { double x = DOUBLEDATA(t);
                 int m = (int) x;
                 if (x == (double) m)
                    return  m ? 0 : 15;  /* ok, it's a decimal integer */
                                         /* unless it's zero           */
                 else
                    return 30;
                }
           if( TYPE(t) == BIGNUM)
              return 34;
           if( ! ISINTEGER(t))
              return 30;
           if(ZERO(t))
              return 15;
           return 0;

        case positiveoddinteger:
           if( OBJECT(t) && TYPE(t)== DOUBLE)
               { double x = DOUBLEDATA(t);
                 int m = (int) x;
                 if (x != (double) m)
                    return 30;
                 else if( m <= 0)
                    return 19;
                 else if(!(m&1))
                    return 36;
                 else return 0;
               }
           if( TYPE(t) == BIGNUM)
              return 34;
           err = infer(type(t,INTEGER));
           if(err)
              return 30;
           err = infer(odd(t));
           if(err)
              return 36;
           return 0;

        case nonnegativeoddinteger:
           if( OBJECT(t) && TYPE(t)== DOUBLE)
               { double x = DOUBLEDATA(t);
                 int m = (int) x;
                 if (x != (double) m)
                    return 30;
                 else if( m < 0)
                    return 21;
                 else if(!(m&1))
                    return 36;
                 else
                    return 0;
               }
           if( TYPE(t) == BIGNUM)
              return 34;
           err = infer(type(t,INTEGER));
           if(err)
              return 30;
           err = infer(odd(t));
           if(err)
              return 36;
           return 0;

        case interval:  /* the condition for graph intervals */
           if(f != AND && f != OR)
              return 1;
           if( !seminumerical(ARG(0,t)))
              return 23;
           if( deval(ARG(0,t),&a))
              return 23;
           if( !seminumerical(ARG(1,t)))
              return 23;
           if( deval(ARG(1,t),&b))
              return 23;
           if( a==b)
              return 24;
           if( a > b)
              return 25;
           return 0;

        case revsubst:  /* the condition for reversesub */
           if(FUNCTOR(t) != '=')
              return 26;
           if(!ISATOM(ARG(0,t)))
              return 27;  /* Left side of = must be a variable name */
           err = no_new_vars(ARG(0,t));  /* left side must be an old variable */
           if(err)
               return 8; /* Left side of = must be a variable already in use. */
           err = mathematical(ARG(1,t));
           if(err)
               return 61;   /* Illegal symbols on the right */
           return 0;

        case msubst:    /* the condition for makesubstitution */
           if(f == AND)  /* simultaneous substitutions are legal */
              { if(ARITY(t) > 2)
                   return 60;   /* No more than two variables allowed in
                                   simultaneous substitutions */
                for(i=0;i<ARITY(t);i++)
                   { err = check_arg(ARG(i,t),msubst);
                     if(err)
                        return err;
                   }
                return 0;   /* each substitution is legal */
              }
           if(f != '=')
              { if(seminumerical(t))
                   return 1857;
                   /* Definition of a new variable cannot be constant. */
                err = no_new_vars(t);
                if(err)
                   return 35;
                return 0;
              }
           if(!ISATOM(ARG(0,t)))
              return 27;
           varlist = get_varlist();
           nvariables = get_nvariables();
           for(i=0;i<nvariables;i++)
              { if(equals(varlist[i],ARG(0,t)))
                   return 34;   /* variable already used */
              }
            /* Now check that no NEW variables have been introduced on the
               right hand side. */
           err = no_new_vars(ARG(1,t));
           if(err)
              return 35;
           return 0;
        case relrates_sub:   /* the condition for enterauxeqn */
           if(f == AND)  /* simultaneous substitutions are legal */
              { if(ARITY(t) > 2)
                   return 60;   /* No more than two variables allowed in
                                   simultaneous substitutions */
                for(i=0;i<ARITY(t);i++)
                   { err = check_arg(ARG(i,t),relrates_sub);
                     if(err)
                        return err;
                   }
                return 0;   /* each substitution is legal */
              }
           if(f != '=')
              return 26;
            /* Now check that no NEW variables have been introduced  */
           err = no_new_vars(t);
           if(err)
              return 50;
           return 0;
        case relrates1:   /* the condition for putnumbersin */
                          /* only already-solved equations allowed,
                             with an atom on the left */
           if(f == AND)  /* simultaneous substitutions are legal */
              { for(i=0;i<ARITY(t);i++)
                   { err = check_arg(ARG(i,t),relrates1);
                     if(err)
                        return err;
                   }
                return 0;   /* each substitution is legal */
              }
           if(f != '=')
              return 26;
           if( !ISATOM(ARG(0,t)))
               return 49;
           /* Now check that no NEW variables have been introduced  */
           err = no_new_vars(t);
           if(err)
              return 50;
           return 0;
        case relrates2:   /* the condition for enterderivs */
                          /* only already-solved equations allowed,
                             with a derivative on the left */
           if(f == AND)  /* simultaneous substitutions are legal */
              { for(i=0;i<ARITY(t);i++)
                   { err = check_arg(ARG(i,t),relrates2);
                     if(err)
                        return err;
                   }
                return 0;   /* each substitution is legal */
              }
           if(f != '=')
              return 26;
           if(!(FUNCTOR(ARG(0,t))==DIFF && ISATOM(ARG(0,ARG(0,t)))
                     && ISATOM(ARG(1,ARG(0,t)))
                    )
             )
                return 51;
            /* Now check that no NEW variables have been introduced  */
           err = no_new_vars(t);
           if(err)
              return 50;
           return 0;

        case trigsubst:    /* the condition for yourtrigsub */
           if(f != '=')
              return 26;
           if(! ISATOM(ARG(0,t)))
              return 27;
           if(! equals(ARG(0,t),get_eigenvariable()))
              return 42;
           /* Now check that the old variable of integration doesn't occur on the right */
           if(contains(ARG(1,t),FUNCTOR(get_eigenvariable())))
              return 41;   /* variable already used */
           return 0;

#if 0
        case functiondefn:   /* condition for defining  a function */
           { char printname[32];
             char rhs_name[128];
             term lhs,rhs,x;
             if(f != '=')
                return 43;
             lhs = ARG(0,t);
             rhs = ARG(1,t);
             if(ARITY(rhs) > 12)
                return 45;
             if(PREDEFINED_FUNCTOR(FUNCTOR(lhs)))
                return 55;
             /* That function is predefined, you can't define it. */
             for(i=0;i<ARITY(lhs);i++)
                { x = ARG(i,lhs);
                  if(!ISATOM(x))
                     return 44;
                  for(j=0;j<i;j++)
                     { if(FUNCTOR(ARG(j,lhs)) == FUNCTOR(x))
                          return 56; /* repeated variable on the left */
                     }
                }
             if(extra_vars(lhs,rhs))
                 return 57;  /*  Extra variable on the right side */
             functor_string(FUNCTOR(lhs),SCREEN,printname);
             mstring(rhs,rhs_name);
             err = enter_definition(lhs,rhs,printname,rhs_name);
             if(err == 3)
                return 1904;
                /* A function with that same name has already been defined.
                   You can redefine it or undefine it, but not define it. */
             if(err == 4)
                return 2477;
                /* There is a repeated variable on the left side. */
             if(err == 5)
                return 2255;  
                /* The function being defined cannot be used in the definition. */
             if(err == 6)
                return 2478; 
                /* You have already used that letter on the right side of another definition. */
             return 0;
           }

        case functionredefn:   /* condition for redefining  a function */
           { term lhs, rhs;
             if(f != '=')
               return 43;
             lhs = ARG(0,t);
             rhs = ARG(1,t);
             if(ARITY(rhs) > 12)
               return 45;
             for(i=0;i<ARITY(lhs);i++)
                { if(!ISATOM(ARG(i,lhs)))
                     return 44;
                  for(j=0;j<i;j++)
                     { if(FUNCTOR(ARG(j,lhs)) == FUNCTOR(ARG(i,lhs)))
                          return 56; /* repeated variable on the left */
                     }
                }
             if(extra_vars(lhs,rhs))
                 return 57;  /*  Extra variable on the right side */
             i = is_defined(FUNCTOR(lhs));
             if(i < 0)
                return 54;
                /* That function isn't defined, so you
                   can't redefine it */
             if(in_use(FUNCTOR(lhs)))
                return 2393;
             mstring(rhs,rhs_name);
             err = replace_definition(i,lhs,rhs, rhs_name);
             if(err == 4)
                return 2477;
                /* There is a repeated variable on the left side. */
             if(err == 5)
                return 2255;  
                /*The function being defined cannot be used in the definition. */
             return 0;
           }
#endif 
        case term_and_indexpair:  /* for "add multiple of one equation to another */
           if(f != AND && f!= OR)
              return 28;
           if(ARITY(t) != 3)
              return 29;
           if (invalid_index(ARG(1,t)) || invalid_index(ARG(2,t)))
              return 9;
           if(!constant(ARG(0,t)))
              return 62;
           break;
        case prod:
           if(f != '*')
              return 37;
           break;
        case twoprompts:    /* for solvenumerically with parameters present */
        case twoprompts1:
           assert(FUNCTOR(t) == AND);
           err = check_arg(ARG(0,t),natoms == 2 ? real : reallist);
           if(err)
              return err;
           return check_arg(ARG(1,t),tworeals);
        case function:   /* apply function to both sides of equation */
           /* The user types a function name, and it gets padded with
              a meaningless argument.  */
           if(ARITY(t) > 1 || !ZERO(ARG(0,t)))
              return 1722;  /* Enter the name of a function, for example "log" */
           return 0;
        case tlist:
           if(contains(t,INTEGRAL))
              return 62;  // Please enter a constant.
              // It doesn't matter what the return value here is, the point is
              // to prevent automode using the whole integral for the arg.  So this
              // message will never be seen, unless a use actually enters an integral
              // for the point breaking an integeral into two integrals.
           if(FUNCTOR(t)==AND)
              { int i;
                for(i=0;i<ARITY(t);i++)
                   { err = mathematical(ARG(i,t));
                     if(err)
                        return err;
                   }
                return 0;
              }
           return mathematical(t);

        default:  assert(0);   /* all cases covered */
   }
      /* Now it has passed the tests, but it may contain atoms which aren't
         in the problem so far, as when you want to multiply an equation by
         'a'  for some perverse reason.  */
   k = get_nvariables();
   vaux(t);  /* add any new variables to varlist, incrementing nvariables */
   nvariables = get_nvariables();
   linenumber = get_currentline();
   for(i=k;i<nvariables;i++)
      initialize_parameter(i,linenumber+1,1);  /* all new atoms will be considered constants */
   return 0;
}
/*____________________________________________________________________*/
condition needs_two_args(operation op, int *promptnumber)
/* Some operators, such as "add selected equation to equation ?",
need both a selected term and a user-entered arg.  If op is one
of these operators, return the condition that the user-entered
arg must satisfy, and make *promptnumber the index k such that
english(k) is the prompt to use to get the arg.   Return 0 if
op is not one of these operators.
*/
{ if(op.men == linear_equations_by_selection)
     { switch(op.choice)
          { case 1:  /* addselectedeqn */
               *promptnumber = 767; /* Add selected equation to which equation? */
               return condition_index;
            case 2:  /* subselectedeqn */
               *promptnumber = 769; /* Subtract selected equation from which equation? */
               return condition_index;
            case 3:  /* mulselectedeqn */
               *promptnumber = 1436;  /* Multiply selected equation by what? */
               return constant_condition;
            case 4: /* divselectedeqn */
               *promptnumber = 1437;   /* Divide selected equation by what?  */
               return nonzero_constant;
            case 5: /* addmulselectedeqn */
               *promptnumber = 1438;  /* Add ? times selected equation to equation ? */
               return term_and_index;
            case 6: /* submulselectedeqn */
               *promptnumber = 1439;  /* Subtract ? times selected equation from equation ? */
               return term_and_index;
            case 7: /* swapselectedeqn */
               { term problem = history(0);
                 if(FUNCTOR(problem) == AND && ARITY(problem) == 2)
                     return 0;  /* only two equations, no choice needed */
                 *promptnumber = 770; /* Swap selected equation with which equation? */
                  return condition_index;
               }
            case 8:  /* solveselectedeqn */
               *promptnumber = 1440; /* Solve selected equation for which variable? */
               return variable;
            case 9:  /* addselectedrow  */
               *promptnumber = 771; /* Add selected row to which row? */
               return condition_index;
            case 10: /* subselectedrow  */
               *promptnumber = 772; /* Subtract selected row from which row? */
               return condition_index;
            case 11: /* mulselectedrow  */
               *promptnumber = 1441;  /* Multiply selected row by what? */
               return constant_condition;
            case 12:  /* divselectedrow  */
               *promptnumber = 1442;  /* Divide selected row by what?  */
               return nonzero_constant;
            case 13:  /* addmulselectedrow */
               *promptnumber = 1443;  /* Add ? times selected row to row ? */
               return term_and_index;
            case 14:  /* submulselectedrow */
               *promptnumber = 1444; /* "Subtract ? times selected row from row ? */
               return term_and_index;
            case 15: /* swapselectedrow */
               *promptnumber = 1435; /* Swap selected row with which row? */
               return condition_index;
          }
     }
  return 0;
}

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