home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / misc / eval / source / src.lha / eval.c < prev    next >
C/C++ Source or Header  |  1993-04-13  |  25KB  |  924 lines

  1. /*
  2. **
  3. ** EVAL.C      A floating point expression evaluator.
  4. **             Main source module.
  5. **
  6. ** Eval is a floating point expression evaluator.
  7. ** This file last updated in version 1.13
  8. ** For the version number, see eval.h
  9. ** Copyright (C) 1993  Will Menninger
  10. **
  11. ** To add a new constant to the Eval program
  12. ** -----------------------------------------
  13. ** 1.  Update the size of MAXC in eval.h
  14. ** 2.  Add your constant to the clist[] array below.  Please keep the
  15. **     list in alphabetic order, and make sure that your contant's
  16. **     name does not exceed MAXNAMELEN (from eval.h)
  17. ** 3.  If your constant is a physical constant with no indication
  18. **     of units in the name, either make sure it is in SI units, or change
  19. **     the print statement that claims all constants are in SI units.
  20. ** 4.  Recompile ALL source modules.
  21. **
  22. **
  23. ** This program is free software; you can redistribute it and/or modify it
  24. ** under the terms of the GNU General Public License as published by the
  25. ** Free Software Foundation; either version 2 of the License, or any
  26. ** later version.
  27. **
  28. ** This program is distributed in the hope that it will be useful, but
  29. ** WITHOUT ANY WARRANTY; without even the implied warranty of
  30. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  31. ** General Public License for more details.
  32. **
  33. ** You should have received a copy of the GNU General Public License along
  34. ** with this program; if not, write to the Free Software Foundation, Inc.,
  35. ** 675 Mass Ave, Cambridge, MA 02139, USA.
  36. **
  37. ** The author until 9/93 can be contacted at:
  38. ** e-mail:     willus@ilm.pfc.mit.edu
  39. ** U.S. mail:  Will Menninger, 45 River St., #2, Boston, MA 02108-1124
  40. **
  41. **
  42. ** Originally written 5/89 in ANSI C
  43. **
  44. */
  45.  
  46. #include   "eval.h"
  47.  
  48. static char    tempname[80];
  49. static char    wdir[100];
  50. static char    rpath[200];
  51. static FILE   *tempfile;
  52. static int     linecount;
  53.  
  54. static VAR     clist[MAXC]=  {
  55.                 {"_acres_per_sq_km",247.1},
  56.                 {"_air_density",1.293},
  57.                 {"_air_mol_mass",.02897},
  58.                 {"_atm_per_psi",.06804},
  59.                 {"_avagadro",6.0220e23},
  60.                 {"_boltzmann",1.3807e-23},
  61.                 {"_c",2.997925e8},
  62.                 {"_cm_per_in",2.54},
  63.                 {"_coulomb_const",8.98755e9},
  64.                 {"_deg_per_rad",57.2958},
  65.                 {"_earth_esc_spd",1.12e4},
  66.                 {"_earth_grav",9.80665},
  67.                 {"_earth_mass",5.98e24},
  68.                 {"_earth_radius",6.37e6},
  69.                 {"_earth_to_moon",3.844e8},
  70.                 {"_earth_to_sun",1.496e11},
  71.                 {"_eps0",8.85419e-12},
  72.                 {"_erg_per_joule",1e7},
  73.                 {"_eulers_const",.57721566490153286061},
  74.                 {"_ft_per_m",3.280839895},
  75.                 {"_g",6.672e-11},
  76.                 {"_gas_const",8.314},
  77.                 {"_gauss_per_tesla",1e4},
  78.                 {"_gm_per_oz",28.34952313},
  79.                 {"_golden_ratio",1.6180339887498948482},
  80.                 {"_h",6.6262e-34},
  81.                 {"_hbar",1.05459e-34},
  82.                 {"_joule_per_btu",1054.35},
  83.                 {"_joule_per_cal",4.184},
  84.                 {"_joule_per_ftlb",1.356},
  85.                 {"_joule_per_kwh",3.6e6},
  86.                 {"_kg_per_slug",14.59},
  87.                 {"_km_per_mi",1.609344},
  88.                 {"_knots_per_mph",.86897624},
  89.                 {"_lbs_per_kg",2.204622622},
  90.                 {"_lit_per_gal",3.785411784},
  91.                 {"_me",9.1095e-31},
  92.                 {"_mn",1.67495e-27},
  93.                 {"_moon_grav",1.62},
  94.                 {"_moon_mass",7.35e22},
  95.                 {"_moon_period",2360448.},
  96.                 {"_moon_radius",1.738e6},
  97.                 {"_mp",1.67265e-27},
  98.                 {"_mu0",1.256637e-6},
  99.                 {"_oz_per_gal",128.},
  100.                 {"_pasc_per_atm",101325.},
  101.                 {"_pasc_per_psi",6895.},
  102.                 {"_pasc_per_torr",133.32},
  103.                 {"_pi",3.14159265358979323846},
  104.                 {"_qe",1.60219e-19},
  105.                 {"_solar_const",1350.},
  106.                 {"_speed_sound",331.},
  107.                 {"_sun_mass",1.99e30},
  108.                 {"_sun_radius",6.96e8},
  109.                 {"_watts_per_hp",745.712},
  110.                 {"_zero_deg_cels",273.15}
  111.                      };
  112.  
  113. static char *license =
  114.     "Eval, a floating point expression evaluator, version %s\n"
  115.     "Copyright (C) 1993  Will Menninger\n"
  116.     "This program is freely redistributable under certain restrictions.\n"
  117.     "It comes with absolutely no warranty.\n"
  118.     "Type '\x3f\x3f' for more information, or '?' for brief help.\n";
  119.  
  120.  
  121. static int process_file(char *filename,int bequiet,VARPTR vlist,VARPTR clist);
  122. static BOOLEAN process_line(FILE *stream,int showinp,int showout,VARPTR vlist,
  123.                             VARPTR clist,char *pinput);
  124. static void init_varlist(VARPTR vlist);
  125. static void var_copy(VARPTR dest,VARPTR source);
  126. static int print_help(FILE *stream,int extended,int page,char *s);
  127. static int more(char *text,char *input,int pause);
  128. static void print_oplist(void);
  129. static int  print_varlist(FILE *s,char *input,VARPTR list,int max);
  130. static void print_stats(void);
  131. static int nextline(char *s,FILE *stream);
  132. static void close_temp(int showout);
  133. static int srchpath(char *name);
  134. static void cwdir(char *name);
  135.  
  136.  
  137. int main(int argc,char *argv[])
  138.  
  139.     {
  140.     VAR     vlist[MAXV];
  141.     char    arg[MAXINPUT+1];
  142.     int     i,nargs,c;
  143.  
  144.  
  145.     init_varlist(vlist);
  146.     wdir[0]=EOS;
  147.     rpath[0]=EOS;
  148.     setobase(10);
  149.     setibase(10);
  150.     set_scinote(0);
  151.     set_fix(0);
  152.     set_sigfig(10);
  153.     set_dplace(10);
  154.     set_maxexp(5);
  155.     tempfile=NULL;
  156.     arg[0]=EOS;
  157.     for (i=1;i<argc;i++)
  158.         {
  159.         if (strlen(arg)+strlen(argv[i])>MAXINPUT-1)
  160.             break;
  161.         if (i>1)
  162.             strcat(arg," ");
  163.         strcat(arg,argv[i]);
  164.         }
  165.     nargs=i-1;
  166.     if (arg[0]=='@')
  167.         {
  168.         for (i=1;arg[i]==' ';i++);
  169.         c=arg[i];
  170.         }
  171.     else
  172.         c=arg[0];
  173.     if (c==EOS)
  174.         nargs=0;
  175.     if (nargs && c!='<')
  176.         {
  177.         process_line(NULL,0,1,vlist,clist,arg);
  178.         close_temp(1);
  179.         return(0);
  180.         }
  181.     printf(license,VERSION);
  182.     if (nargs)
  183.         process_line(NULL,1,1,vlist,clist,arg);
  184.     while (!process_line(stdin,0,1,vlist,clist,""));
  185.     close_temp(1);
  186.     return(0);
  187.     }
  188.  
  189.  
  190. /*
  191. ** process_file
  192. **
  193. ** Sends all of the lines from file, filename, to Eval for processing.
  194. **
  195. ** Returns 1 if a quit was encountered in the file, 0 otherwise
  196. **
  197. */
  198.  
  199. static int process_file(char *filename,int bequiet,VARPTR vlist,VARPTR clist)
  200.  
  201.     {
  202.     FILE   *s;
  203.     int     status;
  204.  
  205.     s=fopen(filename,"r");
  206.     if (s==NULL)
  207.         {
  208.         printf("File %s not found.\n",filename);
  209.         return(0);
  210.         }
  211.     while (1)
  212.         {
  213.         status=process_line(s,!bequiet,!bequiet,vlist,clist,"");
  214.         if (status==1 || status==2)
  215.             break;
  216.         }
  217.     fclose(s);
  218.     return(status==1 ? 1 : 0);
  219.     }
  220.  
  221.  
  222. /*
  223. ** process_line
  224. **
  225. ** Processes one line of input from stream.
  226. ** If showinp is NZ, the input is printed to stdout.
  227. ** If showout is NZ, all output is printed to stdout.
  228. **
  229. ** If stream==NULL, input is taken from string: pinput
  230. **
  231. ** Returns:   1 if "quit" (or similar command) is read.
  232. **            2 if end of file
  233. **            0 otherwise.
  234. **
  235. */
  236.  
  237. static BOOLEAN process_line(FILE *stream,int showinp,int showout,VARPTR vlist,
  238.                             VARPTR clist,char *pinput)
  239.  
  240.     {
  241.     char    rname[100];
  242.     char    input[MAXINPUT+1];
  243.     int     bequiet,i,m0,m1,m2,n,nargs;
  244.  
  245.     input[0]=EOS;
  246.     if (stream!=NULL)
  247.         {
  248.         if (!nextline(input,stream))
  249.             return(2);
  250.         }
  251.     else
  252.         strcpy(input,pinput);
  253.  
  254.     while (1)
  255.         {
  256.         if (input[0]=='@')
  257.             {
  258.             bequiet=1;
  259.             for (i=1;input[i]==' ' || input[i]=='\t';i++);
  260.             }
  261.         else
  262.             {
  263.             bequiet=0;
  264.             i=0;
  265.             }
  266.         if (input[i]!='<' && input[i]!='>' && tempfile!=NULL)
  267.             {
  268.             fprintf(tempfile,"%s\n",&input[i]);
  269.             linecount++;
  270.             }
  271.         if (showinp && !bequiet && input[i]!=EOS)
  272.             printf("%s%s\n",PROMPT,input);
  273.         if (!strcmp(&input[i],"stop") || !strcmp(&input[i],"quit") ||
  274.             !strcmp(&input[i],"exit") || !strcmp(&input[i],"end"))
  275.             return(1);
  276.         if (input[i]==EOS)
  277.             {
  278.             if (!showinp && !bequiet && showout)
  279.                 printf("Type '?' or 'help' for help.\n");
  280.             return(0);
  281.             }
  282.         if (!strncmp(&input[i],"help",4) &&
  283.               (input[i+4]==' ' || input[i+4]=='\t' || input[i+4]==EOS))
  284.             {
  285.             if (input[i+4]!=EOS)
  286.                 n=atoi(&input[i+4]);
  287.             else
  288.                 n=0;
  289.             if (showout && !bequiet && print_help(stream,1,n,input))
  290.                 continue;
  291.             else
  292.                 break;
  293.             }
  294.         if (input[i]=='<' || input[i]=='>')
  295.             {
  296.             n=input[i];
  297.             for (i++;input[i]==' ' || input[i]=='\t';i++);
  298.             if (n=='<')
  299.                 {
  300.                 if (input[i]==EOS)
  301.                     {
  302.                     printf("Must specify a file name after <.\n");
  303.                     return(0);
  304.                     }
  305.                 strcpy(rname,&input[i]);
  306.                 if (!srchpath(rname))
  307.                     {
  308.                     printf("Cannot find %s in read path.\n",rname);
  309.                     return(0);
  310.                     }
  311.                 return(process_file(rname,bequiet || !showout,vlist,clist));
  312.                 }
  313.             close_temp(showout && !bequiet);
  314.             if (input[i]!=EOS)
  315.                 {
  316.                 strcpy(tempname,&input[i]);
  317.                 cwdir(tempname);
  318.                 tempfile=fopen(tempname,"w");
  319.                 linecount=0;
  320.                 if (tempfile==NULL)
  321.                     printf("Cannot open %s for output.\n",tempname);
  322.                 else
  323.                     if (showout && !bequiet)
  324.                         printf("Script file %s begun.\n",tempname);
  325.                 }
  326.             return(0);
  327.             }
  328.         nargs=1;
  329.         m0=i;
  330.         showout=(showout && !bequiet);
  331.         while (1)
  332.             {
  333.             for (;!isspace(input[i]) && input[i]!=EOS;i++);
  334.             if (nargs==1)
  335.                 m1=i-m0;
  336.             if (input[i]==EOS)
  337.                 break;
  338.             for (;isspace(input[i]);i++);
  339.             if (input[i]==EOS)
  340.                 break;
  341.             nargs++;
  342.             if (nargs==2)
  343.                 m2=i;
  344.             if (nargs>2)
  345.                 break;
  346.             }
  347.         if (nargs==2)
  348.             n=atoi(&input[m2]);
  349.         if (!strncmp(&input[m0],"rpath",m1))
  350.             {
  351.             if (nargs==2)
  352.                 {
  353.                 strcpy(rpath,&input[m2]);
  354.                 if (showout)
  355.                     printf("Read path set to %s\n",rpath);
  356.                 }
  357.             else
  358.                 {
  359.                 rpath[0]=EOS;
  360.                 if (showout)
  361.                     printf("Read path cleared.\n");
  362.                 }
  363.             break;
  364.             }
  365.         if (!strncmp(&input[m0],"wdir",m1))
  366.             {
  367.             if (nargs==2)
  368.                 {
  369.                 strcpy(wdir,&input[m2]);
  370.                 if (showout)
  371.                     printf("Write dir set to %s\n",wdir);
  372.                 }
  373.             else
  374.                 {
  375.                 wdir[0]=EOS;
  376.                 if (showout)
  377.                     printf("Write dir set to current dir.\n");
  378.                 }
  379.             break;
  380.             }
  381.         if (!strncmp(&input[m0],"obase",m1) && nargs==2 && n>0)
  382.             {
  383.             if (n<2 || n>36)
  384.                 {
  385.                 printf("Output base must be between 2 and 36.\n");
  386.                 break;
  387.                 }
  388.             setobase(n);
  389.             if (showout)
  390.                 printf("Output base set to %d.\n",n);
  391.             break;
  392.             }
  393.         if (!strncmp(&input[m0],"ibase",m1) && nargs==2 && n>0)
  394.             {
  395.             if (n<2 || n>36)
  396.                 {
  397.                 printf("Input base must be between 2 and 36.\n");
  398.                 break;
  399.                 }
  400.             setibase(n);
  401.             if (showout)
  402.                 printf("Input base set to %d.\n",n);
  403.             break;
  404.             }
  405.         if (!strncmp(&input[m0],"sci",m1) && nargs<2)
  406.             {
  407.             set_scinote(!get_scinote());
  408.             if (showout)
  409.                 printf("Scientific notation %s.\n",get_scinote() ? "ON":"OFF");
  410.             break;
  411.             }
  412.         if (!strncmp(&input[m0],"fix",m1) && nargs<2)
  413.             {
  414.             set_fix(!get_fix());
  415.             if (showout)
  416.                 printf("Fixed precision %s.\n",get_fix() ? "ON":"OFF");
  417.             break;
  418.             }
  419.         if (!strncmp(&input[m0],"sigfig",m1) && nargs==2)
  420.             {
  421.             if (n>DBL_MANT_DIG)
  422.                 printf("Significant figures limited to %d.\n",
  423.                         DBL_MANT_DIG);
  424.             else
  425.                 {
  426.                 set_sigfig(n);
  427.                 if (showout)
  428.                     {
  429.                     printf("Significant figures = ");
  430.                     if (n>0)
  431.                         printf("%d\n",n);
  432.                     else
  433.                         printf("max\n");
  434.                     }
  435.                 }
  436.             break;
  437.             }
  438.         if (!strncmp(&input[m0],"maxexp",m1) && nargs==2)
  439.             {
  440.             set_maxexp(n);
  441.             if (showout)
  442.                 {
  443.                 if (n<0)
  444.                     printf("Exponent limit turned off.\n");
  445.                 else
  446.                     printf("Exponent limit = %d\n",n);
  447.                 }
  448.             break;
  449.             }
  450.         if (!strncmp(&input[m0],"dplace",m1) && nargs==2)
  451.             {
  452.             if (n<-70 || n>70)
  453.                 printf("Decimal place must be between -70 and 70.\n");
  454.             else
  455.                 {
  456.                 set_dplace(n);
  457.                 if (showout)
  458.                     printf("Decimal place = %d\n",n);
  459.                 }
  460.             break;
  461.             }
  462.         if (input[m0]!='?')
  463.             {
  464.             evaluate(&input[m0],showout,vlist,clist);
  465.             break;
  466.             }
  467.         if (!strcmp(&input[m0],"?"))
  468.             if (showout && print_help(stream,0,0,input))
  469.                 continue;
  470.             else
  471.                 break;
  472.         for (i=m0+1;isspace(input[i]);i++);
  473.         if (input[i]=='?')
  474.             {
  475.             if (input[i+1]!=EOS)
  476.                 n=atoi(&input[i+1]);
  477.             else
  478.                 n=0;
  479.             if (showout && print_help(stream,1,n,input))
  480.                 continue;
  481.             else
  482.                 break;
  483.             }
  484.         switch (tolower((int)input[i]))
  485.             {
  486.             case 'v':
  487.                 if (showout && print_varlist(stream,input,vlist,MAXV))
  488.                     continue;
  489.                 break;
  490.             case 'c':
  491.                 if (showout)
  492.                     {
  493.                     printf("All physical constants are in SI units unless the "
  494.                            "name of the variable\nindicates otherwise.\n");
  495.                     if (print_varlist(stream,input,clist,MAXC))
  496.                         continue;
  497.                     }
  498.                 break;
  499.             case 'f':
  500.                 if (showout)
  501.                 if (print_funclist(stream,input,tolower((int)input[i+1])=='l'))
  502.                     continue;
  503.                 break;
  504.             case 'o':
  505.                 if (showout)
  506.                     print_oplist();
  507.                 break;
  508.             case 's':
  509.                 if (showout)
  510.                     print_stats();
  511.                 break;
  512.             default:
  513.                 printf("\"%s\" is an unknown query.\n",&input[i]);
  514.                 break;
  515.             }
  516.         break;
  517.         }
  518.     return(0);
  519.     }
  520.  
  521.  
  522. /*
  523. ** insert_var(VARPTR new,VARPTR vlist)
  524. **
  525. ** Inserts a the new variable into the current list of variables.
  526. ** Returns 1 if successful, 0 if list is full.
  527. **
  528. */
  529.  
  530. BOOLEAN insert_var(VARPTR new,VARPTR vlist)
  531.  
  532.    {
  533.    BOOLEAN found;
  534.    int     i,j,k;
  535.  
  536.    found=search_varlist(new,vlist,&i,MAXV);
  537.    if (!found && vlist[MAXV-1].name[0]!=EOS)
  538.        return(0);
  539.    if (found)
  540.        var_copy(&vlist[i],new);
  541.    else
  542.        {
  543.        for (j=i;j<MAXV-1 && vlist[j].name[0]!=EOS;j++);
  544.        for (k=j;k>i;k--)
  545.            var_copy(&vlist[k],&vlist[k-1]);
  546.        var_copy(&vlist[i],new);
  547.        }
  548.    return(1);
  549.    }
  550.  
  551.  
  552. /*
  553. ** init_varlist(VARPTR vlist)
  554. **
  555. ** Sets all variable names to EOS, representing empty spaces
  556. **
  557. */
  558.  
  559. static void init_varlist(VARPTR vlist)
  560.  
  561.    {
  562.    int     i;
  563.  
  564.    for (i=0;i<MAXV;i++)
  565.        vlist[i].name[0]=EOS;
  566.    }
  567.  
  568. /*
  569. ** var_copy(VARPTR dest,VARPTR source)
  570. **
  571. ** copies one variable to another
  572. **
  573. */
  574.  
  575. static void var_copy(VARPTR dest,VARPTR source)
  576.  
  577.    {
  578.    strcpy(dest->name,source->name);
  579.    dest->value=source->value;
  580.    }
  581.  
  582.  
  583. /*
  584. ** search_varlist(VARPTR var,VARPTR vlist,int *n,int max)
  585. **
  586. ** Searches through a variable list for the variable specified.  If
  587. ** found, returns 1 else returns 0.  The position for insertion is
  588. ** returned in (*n).  The search is binary for fast response.
  589. **
  590. */
  591.  
  592. BOOLEAN search_varlist(VARPTR var,VARPTR vlist,int *n,int max)
  593.  
  594.    {
  595.    int     step,c;
  596.  
  597.    (*n)=step=max>>1;
  598.    while (1)
  599.        {
  600.        if (step>1)
  601.            step>>=1;
  602.        if (vlist[(*n)].name[0]==EOS)
  603.            {
  604.            if ((*n)==0)
  605.                return(0);
  606.            (*n)=(*n)-step;
  607.            continue;
  608.            }
  609.        if (!(c=strcmp(var->name,vlist[(*n)].name)))
  610.            break;
  611.        if (c>0)
  612.            {
  613.            if ((*n)==max-2 || vlist[(*n)+1].name[0]==EOS)
  614.                {
  615.                (*n)=(*n)+1;
  616.                if (vlist[(*n)].name[0]!=EOS)
  617.                    return(!strcmp(var->name,vlist[(*n)].name));
  618.                else
  619.                    return(0);
  620.                }
  621.            (*n)=(*n)+step;
  622.            continue;
  623.            }
  624.        if ((*n)==0 || strcmp(var->name,vlist[(*n)-1].name)>0)
  625.            return(0);
  626.        (*n)=(*n)-step;
  627.        }
  628.    return(1);
  629.    }
  630.  
  631.  
  632. /*
  633. ** print_help(void)
  634. **
  635. ** Prints instructions on how to use the expression evaluator.
  636. **
  637. */
  638.  
  639. static int print_help(FILE *stream,int extended,int page,char *s)
  640.  
  641.     {
  642.     extern char *bhelp;
  643.     extern char *ehelp;
  644.     int     i,j;
  645.  
  646.     if (extended)
  647.         for (i=0,j=0;ehelp[j]!=EOS && i<page-1;j++)
  648.             if (ehelp[j]=='\f')
  649.                 {
  650.                 j++;
  651.                 i++;
  652.                 }
  653.  
  654.     return (more(extended ? &ehelp[j] : bhelp,s,stream==stdin));
  655.     }
  656.  
  657.  
  658. static int more(char *text,char *input,int pause)
  659.  
  660.     {
  661.     int     nl;
  662.     int     c,in,istart;
  663.  
  664.     in=-1;
  665.     while (1)
  666.         {
  667.         istart=in+1;
  668.         for (nl=0;nl<NLINES;nl++)
  669.             {
  670.             for (in++;text[in]!='\f' && text[in]!='\n' && text[in]!=EOS;in++);
  671.             if (text[in]==EOS || text[in]=='\f')
  672.                 break;
  673.             }
  674.         if (text[in]==EOS || text[in+1]==EOS)
  675.             {
  676.             printf("%s\n",&text[istart]);
  677.             break;
  678.             }
  679.         if (text[in]=='\f')
  680.             in--;
  681.         c=text[in+1];
  682.         text[in+1]=EOS;
  683.         printf("%s\n",&text[istart]);
  684.         text[in+1]=c;
  685.         if (pause)
  686.             {
  687.             printf("Press <ENTER> for more...\n");
  688.             input[0]=EOS;
  689.             nextline(input,stdin);
  690.             if (input[0]!=EOS)
  691.                 return(1);
  692.             printf("\n");
  693.             }
  694.         if (c=='\f')
  695.             in+=2;
  696.         }
  697.     return(0);
  698.     }
  699.  
  700.  
  701. /*
  702. ** print_oplist(void)
  703. **
  704. ** Prints list of operands
  705. **
  706. */
  707.  
  708. static void print_oplist(void)
  709.  
  710.     {
  711.     static char *oplist =
  712.     "\nUnary operators:\n"
  713.     "                  +      positive\n"
  714.     "                  -      negative\n"
  715.     "                  ~      bit-wise NOT\n\n"
  716.     "Binary operators: (in order of precedence)\n"
  717.     "                  ^      power*\n"
  718.     "                  * / %  multiply, divide, modulo\n"
  719.     "                  + -    add, subtract\n"
  720.     "                  << >>  bit-shift left, right\n"
  721.     "                  &      bit-wise AND\n"
  722.     "                  ?      bit-wise XOR*\n"
  723.     "                  |      bit-wise OR\n\n"
  724.     "* - different from C\n\n";
  725.     printf("%s",oplist);
  726.     }
  727.  
  728.  
  729. /*
  730. ** print_varlist(FILE *s,char *input,VARPTR list,int max)
  731. **
  732. ** Prints out a list of constants or variables and their values
  733. **
  734. */
  735.  
  736. static int print_varlist(FILE *s,char *input,VARPTR list,int max)
  737.  
  738.     {
  739.     char    bigbuf[MAXOUTLEN];
  740.     char    bigline[MAXOUTLEN];
  741.     int     i,j,k,l,n,m1,m2,nc,cw,nr,li,c;
  742.  
  743.     for (m1=m2=0,i=0;i<max && list[i].name[0]!=EOS;i++)
  744.         {
  745.         if ((l=strlen(list[i].name))>m1)
  746.             m1=l;
  747.         baseconv(list[i].value,bigbuf);
  748.         if ((l=strlen(bigbuf))>m2)
  749.             m2=l;
  750.         }
  751.     n=i;
  752.     if (!n)
  753.         {
  754.         printf("There are no currently assigned variables.\n");
  755.         return(0);
  756.         }
  757.     cw=m1+m2+7;
  758.     nc=(SCRWIDTH+3)/cw;
  759.     if (nc<=0)
  760.         nc=1;
  761.     nr=(i+nc-1)/nc;
  762.     for (i=0;i<nr;i++)
  763.         {
  764.         li=0;
  765.         for (j=0;j<nc;j++)
  766.             {
  767.             k=i+j*nr;
  768.             if (k>=n)
  769.                 break;
  770.             for (l=0;(c=list[k].name[l])!=EOS;l++)
  771.                 bigline[li++]=c;
  772.             for (;l<m1;l++)
  773.                 bigline[li++]=' ';
  774.             baseconv(list[k].value,bigbuf);
  775.             bigline[li++]=' ';
  776.             bigline[li++]='=';
  777.             bigline[li++]=' ';
  778.             for (l=0;(c=bigbuf[l])!=EOS;l++)
  779.                 bigline[li++]=c;
  780.             if (j<nc-1)
  781.                 for (;l<m2+4;l++)
  782.                     bigline[li++]=' ';
  783.             }
  784.         bigline[li]=EOS;
  785.         printf("%s\n",bigline);
  786.         if (s==stdin && i!=nr-1 && ((i+3)%NLINES)==0)
  787.             {
  788.             printf("\nPress <ENTER> for more...\n");
  789.             input[0]=EOS;
  790.             nextline(input,s);
  791.             if (input[0]!=EOS)
  792.                 return(1);
  793.             printf("\n");
  794.             }
  795.         }
  796.     printf("\n");
  797.     return(0);
  798.     }
  799.  
  800.  
  801. static void print_stats(void)
  802.  
  803.     {
  804.     int     ib,ob;
  805.  
  806.     ib=getibase();
  807.     ob=getobase();
  808.     printf("\nExpression evaluator, version %s\n",VERSION);
  809.     print_outtype();
  810.     printf("Default input base:   %d\n",ib);
  811.     printf("Default output base:  %d\n\n",ob);
  812.     printf("Base %d accuracy:     %d digits\n",ib,precision(ib));
  813.     if (ob!=ib)
  814.         printf("Base %d accuracy:     %d digits\n",ob,precision(ob));
  815.     printf("\n");
  816.     printf("Read path:  %s\n",rpath[0]==EOS ? "None" : rpath);
  817.     printf("Write dir:  %s\n",wdir[0]==EOS ? "Current dir" : wdir);
  818.     printf("\n");
  819.     }
  820.  
  821.  
  822. /*
  823. ** void fixup(char *s)
  824. **
  825. ** Removes white space from beginning and end of string.  Also removes
  826. ** \n from end of string, and converts entire string to lower case.
  827. **
  828. */
  829.  
  830. void fixup(char *s)
  831.  
  832.     {
  833.     int     i,j;
  834.  
  835.     for (i=0;isspace(s[i]);i++);
  836.     for (j=0;s[i]!='\n' && s[i]!=EOS;j++,i++)
  837.         s[j]=tolower((int)s[i]);
  838.     for (j--;j>=0 && isspace(s[j]);j--);
  839.     s[j+1]=EOS;
  840.     }
  841.  
  842.  
  843. static int nextline(char *s,FILE *stream)
  844.  
  845.     {
  846.     while (1)
  847.  
  848.         {
  849.         if (stream==stdin)
  850.             printf("%s",PROMPT);
  851.         if (fgets(s,MAXINPUT,stream)==NULL)
  852.             return(0);
  853.         fixup(s);
  854.         if (s[0]!=';')
  855.             break;
  856.         }
  857.     return(1);
  858.     }
  859.  
  860.  
  861. static void close_temp(int showout)
  862.  
  863.     {
  864.     if (tempfile!=NULL)
  865.         {
  866.         fclose(tempfile);
  867.         tempfile=NULL;
  868.         if (showout)
  869.             printf("%d lines written to %s.\n",linecount,tempname);
  870.         }
  871.     }
  872.  
  873.  
  874. static int srchpath(char *name)
  875.  
  876.     {
  877.     char    buf[100];
  878.     int     i,j;
  879.     int     checked;
  880.     FILE   *f;
  881.  
  882.     i=0;
  883.     strcpy(buf,name);
  884.     checked=0;
  885.     while (1)
  886.         {
  887.         for (j=0;rpath[i]!=EOS && rpath[i]!=';';i++,j++)
  888.             buf[j]=rpath[i];
  889.         buf[j]=EOS;
  890.         if (checked && !j && rpath[i]==EOS)
  891.             return(0);
  892.         while (rpath[i]==';')
  893.             i++;
  894.         strcat(buf,name);
  895.         if (j || !checked)
  896.             {
  897.             if (!j)
  898.                 checked=1;
  899.             f=fopen(buf,"r");
  900.             if (f!=NULL)
  901.                 break;
  902.             }
  903.         }
  904.     fclose(f);
  905.     strcpy(name,buf);
  906.     return(1);
  907.     }
  908.  
  909.  
  910. static void cwdir(char *name)
  911.  
  912.     {
  913.     char    buf[100];
  914.     FILE   *f;
  915.  
  916.     strcpy(buf,wdir);
  917.     strcat(buf,name);
  918.     f=fopen(buf,"w");
  919.     if (f==NULL)
  920.         return;
  921.     fclose(f);
  922.     strcpy(name,buf);
  923.     }
  924.