//--------------------------------------------------------------------
// ASCIINUM.CPP
// Keith Larson
// TMS320 DSP Applications
// (c) Copyright 1995, 1996, 1997
// Texas Instruments Incorporated
//
// This is unsupported freeware code with no implied warranties or
// liabilities.  See the disclaimer document for details
//--------------------------------------------------------------------
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "typedefs.h"
#include "assm_fun.h"
#include "argsplit.h"
#include "symbols.h"
#include "errormsg.h"
//----------------------------------------------------------------------
// ascii_num will convert an ascii string to a binary image for several
// possible format standards, depending on the contents of the string.
// If the string is a variable the symbol table is searched for a match
// and the return type is set for the type definition in the table.
//
// Supported syntax includes
//   floating point        3.1415,  1.01e32
//   decimal                 1234
//   C style hexadcimal    0x1234
//   TI style hexadcimal   01234h
//   Binary                01101b
//
// ascii_num returns
//   0 - failed to recognize as a number
//   1 - integer
//   2 - floating point (returned as 32 bit IEEE)
//----------------------------------------------------------------------
//int ref_value(char *ptr, long *value);
NUM_TYPE ascii_num(char *ptr, long *binv)
{
  NUM_TYPE rtrn;
  //chi float f;
  float f = 0;
  double d;
  //chi ulong  l;
  ulong  l = 0;
  char negate = 0, polar = 0;
  char hex[20], *ptr2;
  char buf[80];
  strncpy(buf,ptr,79);
  ptr = buf;
  //
  // remove leading ws chars - space, tab
  //
  for(;;)
  {
    if((*ptr ==  ' ') | (*ptr == '\t')) ptr++;
    else break;
  }
  //
  // Search for valid numeric modifiers
  //
  if(   isdigit(*ptr)
      || ((*ptr=='.' ) && (isdigit(*(ptr+1)))  ) // .1 vs .text
      || (*ptr=='+' )
      || (*ptr=='-' )
      || (*ptr=='!' )
      || (*ptr=='\'')
    )
  {
    while((*ptr == '!') || (*ptr == '-') || (*ptr == '+'))
    {
      if(*ptr == '!') negate ^= 1;
      if(*ptr == '-') polar  ^= 1;
      ptr++;
    };
    if(isdigit(*ptr) || (*ptr=='.') || (*ptr=='\''))
    {
      for(;;)  // dummy for(;;) loop is always broken
      {        // case statement code style form is not suitable
        // Check for char values expressed as 'c'
        //
        if(*ptr=='\'')
        {
          ptr++;
          if(*ptr=='\\') ptr++; // allow escape for comment ';' char
          l = *ptr++;
          l &= 0xFF;
//        rtrn = 1;
          rtrn = INTEGER;
          if(*ptr!='\'') rtrn = NOREF;
          break;
        }
        strupr(ptr);  // All others are numeric
        strupr(ptr);
        if((ptr2 = strstr(ptr,"H")) != NULL)  // TI style hex
        { *ptr2 = 0;
          strcpy(hex,"0x");
          strcat(hex,ptr);
          l = strtoul(hex,&ptr2,0);
          if(*ptr2 !=0) return NOREF;
          rtrn = INTEGER;
          break;
        }
        if((ptr2 = strstr(ptr,"X")) != NULL)  // C style hex
        { l = strtoul(ptr,&ptr2,0);
          if(*ptr2 !=0) return NOREF;
          rtrn = INTEGER;
          break;
        }
        if((ptr2 = strstr(ptr,"B")) != NULL)  // Binary
        { *ptr2 = 0;
          l = strtoul(ptr,&ptr2,2);
          if(*ptr2 !=0) return NOREF;
          rtrn = INTEGER;
          break;
        }
        if(((ptr2=strstr(ptr,"E"))!=NULL) || ((ptr2=strstr(ptr,"."))!=NULL))
        {
      // if(illegal_float_chars(ptr2)) return dir;
      // strchr
          d = strtod(ptr,&ptr2);
          if(d > MAX_FLOAT) d = MAX_FLOAT;
          if(d < MIN_FLOAT) d = MIN_FLOAT;
          f = d;
          if(*ptr2!=0) return NOREF;
      //  if(polar) f *= -1.0;
      //  f = IEEE_TMS(f);
          rtrn = FLOAT;
          break;
        }
        //
        //
        l = strtoul(ptr,&ptr2,0);      // default is unsigned long
        if(*ptr2 !=0) return NOREF;
        rtrn = INTEGER;
        break;
      }
    }
    else  // Look for the value of symbol in SYMe
    {
//    if(ref_value(ptr, &l)) return 0;
//    rtrn = 1;
      switch(ref_value(ptr, binv))
      { case FLOAT  :  return FLOAT;
        case INTEGER:  return INTEGER;
        case NOREF  :
        default     : return NOREF;
      }
    }
    if(rtrn == 1)
    { if(negate) l ^= 0xFFFFFFFFL;
      if(polar)  l  = -l;
      *((long *)binv) = l;   // pointer to bin is mangled to fit format
      return rtrn;
    }
    if(rtrn == 2)
    { if(polar) f *= -1.0;
      *((float *)binv) = f;  // pointer to bin is mangled to fit format
      return rtrn;
    }
  }
  else  // Look for the value of symbol in SYMe
  { switch(ref_value(ptr, binv))
    { case FLOAT  :  return FLOAT;
      case INTEGER:  return INTEGER;
      case NOREF  :
      default     : return NOREF;
    }
  }
  return NOREF;
}
