/*======================================================================*/
/*  Calculator Internal Symbol Routine(s)                               */
/*======================================================================*/

#include stdio
#include ctype

/* calculator common definitions */

#include "calc_include.h"

/* global flags and variables */

extern int    debug_flag;
extern int    error_flag;
extern int    exit_flag;
extern int    format_precision;
extern struct token_struct numeric_value;

/* local flags and variabels */

static int    slast = -1;                 /* last stored symbol         */
static char   sstring[symmax][strsize];   /* symbol string storage array*/
static struct token_struct sdata[symmax]; /* symbol value storage array */


/*----------------------------------------------------------------------*/
/*  A Symbols First Character Must Be Alphebetic                        */
/*                                                                      */
/*  Parameter  Description                                              */
/*                                                                      */
/*  options    processing option flags                                  */
/*  stringcnt  length of input string                                   */
/*  stringptr  address of input string                                  */
/*  tokencnt   length of current token                                  */
/*  tokenptr   address of current token                                 */
/*  character  character value of character token                       */
/*  number     binary value of numeric token                            */
/*  parameter  user supplied argument                                   */
/*                                                                      */
/*----------------------------------------------------------------------*/

int test_symbol (options,stringcnt,stringptr,tokencnt,
                 tokenptr,character,number,parameter)
int  options,stringcnt,tokencnt,number,parameter;
char character,stringptr[],tokenptr[];
{
   if ((tokenptr[0] >= 'a') && (tokenptr[0] <= 'z') ||
       (tokenptr[0] >= 'A') && (tokenptr[0] <= 'Z'))
      return TRUE;
   else
      return FALSE;
}


/*----------------------------------------------------------------------*/
/*  Search In The Symbol String Array For A Given String                */
/*                                                                      */
/*  This routine return TRUE if the string was located and FALSE if     */
/*  if it was not found.  If the string was found IDX sis et to the     */
/*  array index of the located string, otherwise it is unchanged.       */
/*                                                                      */
/*  Parameter  Description                                              */
/*                                                                      */
/*  idx        array index of located string returned to caller         */
/*  str        string to be located                                     */
/*                                                                      */
/*----------------------------------------------------------------------*/

int locate_symbol (idx,str)
int  *idx;
char str[];
{
   int i,j;

   /* test if symbol array(s) are empty */

   if (slast < 0) return FALSE;

   /* search array for string (array is always in sort order) */

   for (i=0;i<=slast;i++)
      {
      j = strcmp(str,sstring[i]);
      if (j<0) return FALSE;
      if (j==0)
        {
        *idx = i;
        return TRUE;
        }
      }

   /* string was not found */

   return FALSE;
}


/*----------------------------------------------------------------------*/
/*  Insert A Symbol Into The Symbol Data Array(s) Or If It Already      */
/*  Exists, Insert A New Value                                          */
/*                                                                      */
/*  This routine return TRUE if the string was inserted into the        */
/*  sysbol data array(s) and FALSE if the string was not inserted.      */
/*                                                                      */
/*  Parameter  Description                                              */
/*                                                                      */
/*  idx        array index of inserted string returned to caller        */
/*  dat        data to be inserted into the symbol data array           */
/*  str        string to be inserted into the symbol string array       */
/*                                                                      */
/*----------------------------------------------------------------------*/

int insert_symbol (idx,dat,str)
int  *idx;
char str[];
struct token_struct dat;
{
   int i,j,k;

   /* test for overflow */

   if (slast + 1 >= symmax)
      {
      printf("-- Maximum number of symbols exceeded\n");
      error_flag = TRUE;
      return FALSE;
      }

   /* if array(s) are empty, insert symbol into slot zero */

   if (slast<0)
      {
      strncpy(sstring[0],str,strsize-1);
      sstring[0][strsize-1] = '\0';
      sdata[0] = dat;
      *idx = 0;
      slast = 0;
      return TRUE;
      }

   /* Insert symbol into array(s) maintaining sort order */

   for (i=0;i<=slast;i++)
      {
      /* compare string */

      j = strcmp(str,sstring[i]);

      /* match found, updata data */

      if (j==0)
         {
         sdata[i] = dat;
         *idx = i;
         return TRUE;
         }

      /* insert string greater than current symbol string */

      if (j<0)
         {

         /* move existing symbol up up */

         for (k=slast;k>=i;k--)
            {
            strcpy(sstring[k+1],sstring[k]);
            sdata[k+1] = sdata[k];
            }

         slast = slast + 1;

         /* insert symbol into the current position */

         strncpy(sstring[i],str,strsize-1);
         sstring[i][strsize-1] = '\0';
         sdata[i] = dat;
         *idx = i;
         return TRUE;
         }
      }

   /* insert symbol at the end if the list */

   slast = slast + 1;
   strncpy(sstring[slast],str,strsize-1);
   sstring[slast][strsize-1] = '\0';
   sdata[slast] = dat;
   *idx = slast;
   return TRUE;
}


/*----------------------------------------------------------------------*/
/*  Display All Existing Symbols and Their Values                       */
/*                                                                      */
/*----------------------------------------------------------------------*/

int display_all_symbols ()
{
   int i;

   if (slast < 0)
      printf("-- No symbols are currently defined\n");
   else
      for (i=0;i<=slast;i++) display_a_symbol(i);

   return TRUE;
}


/*----------------------------------------------------------------------*/
/*  Display A Symbol and Its Value                                      */
/*                                                                      */
/*  Parameter  Description                                              */
/*                                                                      */
/*  idx        array index of the Symbol to be displayed                */
/*                                                                      */
/*----------------------------------------------------------------------*/

int display_a_symbol (idx)
int idx;
{
   if ((idx < 0) || (idx > slast))
      {
      printf("-- Internal error, illegal symbol index (%d)\n",idx);
      error_flag = TRUE;
      return FALSE;
      }
   else
      if (sdata[idx].type == INTEGER)
         printf("%s = %d\n",sstring[idx],sdata[idx].idata);
      else if (sdata[idx].type == FLOAT)
         printf("%s = %.*f\n",sstring[idx],format_precision,
           sdata[idx].fdata);
      else
         {
         printf("-- Internal error, symbol %s has an unknown data type\n",
               sstring[idx]);
         error_flag = TRUE;
         return FALSE;
         }

   return TRUE;
}


/*----------------------------------------------------------------------*/
/*  Return A Specified Symbols Value                                    */
/*                                                                      */
/*  Parameter  Description                                              */
/*                                                                      */
/*  idx        array index of the symbol to be displayed                */
/*  dat        address data structure to recieve the symbol data        */
/*                                                                      */
/*----------------------------------------------------------------------*/

int return_symbol_value (idx,dat)
int idx;
struct token_struct *dat;
{
   if ((idx < 0) || (idx > slast))
      {
      printf("-- Internal error, illegal symbol index (%d)\n",idx);
      error_flag = TRUE;
      return FALSE;
      }

   if (debug_flag) display_a_symbol(idx);
    
   *dat = sdata[idx];

   return TRUE;
}
