/********************************************************************/
/*                                                                  */
/*    MODUL              : CCALC.C                                  */
/*    VERSION            : 1.0                                      */
/*    DATE               : 24/09/91                                 */
/*    WRITTEN BY         : Christoph Bohle                          */
/* ---------------------------------------------------------------- */
/*    LANGUAGE           : C                                        */
/*    OS                 : UNIX                                     */
/*                                                                  */
/********************************************************************/

/********************************************************************/
/*   INCLUDE-Files                                                  */
/********************************************************************/

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
              
/********************************************************************/
/*    Functions                                                     */
/********************************************************************/


float expression();

char *end_of_brackets( str )
char *str;  
{                                   
  int i;
  i=1;
  do
  {	
    str++;
    switch( *str )
    {
      case '('  : i++;
                  break;
      case ')'  : i--;
	  	            break;
      case '\0' : i=0;
    }
  }
  while( i>0 );
  return( str );
}
		
float factor( facstr )
char *facstr;
{
  char *help, c;
  
  /* Float */
  if( isdigit(*facstr) || *facstr=='.' || *facstr=='-' || *facstr=='+' )
    return( atof(facstr) );
  
  /* Expression in brackets */
  if( *facstr=='(' )
  {
    *(end_of_brackets( ++facstr )) = '\0';
    return( expression( facstr ) );
  }
  
  /* Function */
  help = facstr;
  while( isalnum(*help) || *help == '_' || *help == '.' )
    help++;
  if( help != facstr )
  {
    c = *help;
    *help = '\0';
    
    /* Function */
    if( strcmp( facstr , "exp" ) == 0 )
    {
      *help = c;
      return( exp( factor( help ) ) );
    }
    if( strcmp( facstr , "log" ) == 0 )
    {
      *help = c;
      return( log( factor( help ) ) );
    }
    if( strcmp( facstr , "log10" ) == 0 )
    {
      *help = c;
      return( log10( factor( help ) ) );
    }
    if( strcmp( facstr , "sin" ) == 0 )
    {
      *help = c;
      return( sin( factor( help ) ) );
    }
    if( strcmp( facstr , "cos" ) == 0 )
    {
      *help = c;
      return( cos( factor( help ) ) );
    }
    if( strcmp( facstr , "tan" ) == 0 )
    {
      *help = c;
      return( tan( factor( help ) ) );
    }
    if( strcmp( facstr , "asin" ) == 0 )
    {
      *help = c;
      return( asin( factor( help ) ) );
    }
    if( strcmp( facstr , "acos" ) == 0 )
    {
      *help = c;
      return( acos( factor( help ) ) );
    }
    if( strcmp( facstr , "atan" ) == 0 )
    {
      *help = c;
      return( atan( factor( help ) ) );
    }
    if( strcmp( facstr , "sinh" ) == 0 )
    {
      *help = c;
      return( sinh( factor( help ) ) );
    }
    if( strcmp( facstr , "cosh" ) == 0 )
    {
      *help = c;
      return( cosh( factor( help ) ) );
    }
    if( strcmp( facstr , "tanh" ) == 0 )
    {
      *help = c;
      return( tanh( factor( help ) ) );
    }
  }
  
  /* Default */
  if( *facstr == '\0' )
    return( 0.0 );
  else
    return( factor( facstr+1 ) ); 
}

float po( postr )
char postr[];
{
  char *help;
  help = postr;
  
  while( (*help != '^') && (*help != '\0' ) )
  {
    if( *help == '(' )
    	help = end_of_brackets( help );
    help++;
  }
  
  switch( *help )
  {
	  case '^' : *help = '\0';
               return( pow( factor( postr ) , po( help+1 ) ));
    case '\0' : if( help == postr ) 
                  return( 0.0 );
                else
                  return( factor( postr ) );
  }
}

float term( termstr )
char termstr[];
{
  char *help;
  help = termstr;
  
  while( (*help != '*') && (*help != '/') && (*help != '\0' ) )
  {
    if( *help == '(' )
    	help = end_of_brackets( help );
    help++;
  }
  
  switch( *help )
  {
	  case '*' : *help = '\0';
               return( po( termstr ) * term( help+1 ) );
    case '/' : *help = '\0';
               return( po( termstr ) / term( help+1 ) );
    case '\0' : if( help == termstr ) 
                  return( 0.0 );
                else
                  return( po( termstr ) );
  }
}

float expression( exprstr )
char exprstr[];
{
  char *help;
  help = exprstr;
  
  while( (*help != '+') && (*help != '-') && (*help != '\0' ) )
  {
    if( *help == '(' )
    	help = end_of_brackets( help );
    help++;
  }
  
  switch( *help )
  {
	  case '+' : *help = '\0';
               return( term( exprstr ) + expression( help+1 ) );
    case '-' : *help = '\0';
               return( term( exprstr ) - expression( help+1 ) );
    case '\0' : if( help == exprstr ) 
                  return( 0.0 );
                else
                  return( term( exprstr ) );
  }
}

float analyse_function( funstr )
char *funstr;
{
  char *help;
  float res;
  
  help=malloc( strlen(funstr)+1 );
  strcpy( help , funstr );
  res = expression( help );
  free( help );
  return( res );  
}

/********************************************************************/
/* Main-function                                                    */
/********************************************************************/

main( argc , argv  )
int argc;
char *argv[];              
{
  int i, l;
  char *fun;
  
  l = 1;
  for( i=1 ; i < argc ; i++ )
  {
    l += strlen( argv[i] ) + 1;
  }
  fun = malloc( l+3 ); *fun = '\0';
  for( i=1 ; i < argc ; i++ )
  {
    strcat( fun , argv[i] );
    strcat( fun , " ");
  }
  printf("%f\n", (double)analyse_function( fun ) );
  return(0);
}

/********************************************************************/
