OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [Open8 Tools/] [open8_src/] [open8_as/] [stack.c] - Rev 210

Go to most recent revision | Compare with Previous | Blame | View Log

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "defines.h"
 
#include "parse.h"
#include "pass_1.h"
#include "stack.h"
#include "include_file.h"
 
 
extern int input_number_error_msg, bankheader_status, input_float_mode;
extern int i, size, d, macro_active, string_size, section_status, parse_floats;
extern char xyz[256], *buffer, tmp[4096], expanded_macro_string[256], label[MAX_NAME_LENGTH];
extern struct definition *defines, *tmp_def, *next_def;
extern struct active_file_info *active_file_info_first, *active_file_info_last, *active_file_info_tmp;
extern struct macro_runtime *macro_runtime_current;
extern struct section_def *sec_tmp;
extern double flo;
 
int latest_stack = 0, stacks_inside = 0, stacks_outside = 0, stack_id = 0;
struct stack *stacks_first = NULL, *stacks_tmp = NULL, *stacks_last = NULL;
struct stack *stacks_header_first = NULL, *stacks_header_last = NULL;
 
extern int stack_inserted;
 
extern int operand_hint;
 
static int _stack_insert(void) {
 
  /* outside bankheader sections */
  if (bankheader_status == OFF) {
    if (stacks_first == NULL) {
      stacks_first = stacks_tmp;
      stacks_last = stacks_tmp;
    }
    else {
      stacks_last->next = stacks_tmp;
      stacks_last = stacks_tmp;
    }
    stacks_outside++;
 
    stack_inserted = STACK_OUTSIDE;
  }
  /* inside a bankheader section */
  else {
    if (stacks_header_first == NULL) {
      stacks_header_first = stacks_tmp;
      stacks_header_last = stacks_tmp;
    }
    else {
      stacks_header_last->next = stacks_tmp;
      stacks_header_last = stacks_tmp;
    }
    stacks_inside++;
 
    stack_inserted = STACK_INSIDE;
  }
 
  stacks_tmp->id = stack_id;
  stacks_tmp->section_status = section_status;
  if (section_status == ON)
    stacks_tmp->section_id = sec_tmp->id;
  else
    stacks_tmp->section_id = 0;
 
  latest_stack = stack_id;
  stack_id++;
 
  return SUCCEEDED;
}
 
 
int stack_calculate(char *in, int *value) {
 
  int q = 0, b = 0, d, k, op[256], n, o, l;
  struct stack_item si[256], ta[256];
  struct stack s;
  unsigned char e;
  double dou, dom;
 
 
  /* slice the data into infix format */
  while (*in != 0x0A) {
    /* init the stack item */
    si[q].type = 0x123456;
    si[q].sign = 0x123456;
    si[q].value = 0x123456;
    si[q].string[0] = 0;
 
    if (*in == ' ') {
      in++;
      continue;
    }
    else if (*in == '-') {
      if (*(in + 1) == '-') {
	si[q].type = STACK_ITEM_TYPE_STRING;
	si[q].sign = SI_SIGN_POSITIVE;
	for (k = 0; *in == '-' && k < 32; k++, in++) {
	  si[q].string[k] = '-';
	}
	si[q].string[k] = 0;
      }
      else {
	si[q].type = STACK_ITEM_TYPE_OPERATOR;
	si[q].value = SI_OP_MINUS;
	in++;
      }
      q++;
    }
    else if (*in == '+') {
      if (*(in + 1) == '+') {
	si[q].type = STACK_ITEM_TYPE_STRING;
	si[q].sign = SI_SIGN_POSITIVE;
	for (k = 0; *in == '+' && k < 32; k++, in++)
	  si[q].string[k] = '+';
	si[q].string[k] = 0;
      }
      else {
	si[q].type = STACK_ITEM_TYPE_OPERATOR;
	si[q].value = SI_OP_PLUS;
	in++;
      }
      q++;
    }
    else if (*in == '*') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_MULTIPLY;
      q++;
      in++;
    }
    else if (*in == '/') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_DIVIDE;
      q++;
      in++;
    }
    else if (*in == '|') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_OR;
      q++;
      in++;
    }
    else if (*in == '&') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_AND;
      q++;
      in++;
    }
    else if (*in == '^') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_POWER;
      q++;
      in++;
    }
    else if (*in == '#') {
      if (q == 0) {
	if (input_number_error_msg == YES)
	  print_error("Syntax error. Invalid use of modulo.\n", ERROR_STC);
	return FAILED;
      }
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_MODULO;
      q++;
      in++;
    }
    else if (*in == '<' && *(in + 1) == '<') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_SHIFT_LEFT;
      q++;
      in += 2;
    }
    else if (*in == '<') {
      /* should we end parsing here? */
      if (b == 0 && q > 0) {
	if ((si[q-1].type == STACK_ITEM_TYPE_OPERATOR && si[q-1].value == SI_OP_RIGHT) ||
	    si[q-1].type == STACK_ITEM_TYPE_VALUE || si[q-1].type == STACK_ITEM_TYPE_STRING)
	  break;
      }
 
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_LOW_BYTE;
      q++;
      in++;
    }
    else if (*in == '>' && *(in + 1) == '>') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_SHIFT_RIGHT;
      q++;
      in += 2;
    }
    else if (*in == '>') {
      /* should we end parsing here? */
      if (b == 0 && q > 0) {
	if ((si[q-1].type == STACK_ITEM_TYPE_OPERATOR && si[q-1].value == SI_OP_RIGHT) ||
	    si[q-1].type == STACK_ITEM_TYPE_VALUE || si[q-1].type == STACK_ITEM_TYPE_STRING)
	  break;
      }
 
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_HIGH_BYTE;
      q++;
      in++;
    }
    else if (*in == '~') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_XOR;
      q++;
      in++;
    }
    else if (*in == '=' && *(in + 1) == '=')
      break;
    else if (*in == '!' && *(in + 1) == '=')
      break;
    else if (*in == '(') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_LEFT;
      q++;
      b++;
      in++;
    }
    else if (*in == '.') {
      in++;
      d = operand_hint;
      if (*in == 'b' || *in == 'B') {
	operand_hint = HINT_8BIT;
	in++;
      }
      else if (*in == 'w' || *in == 'W') {
	operand_hint = HINT_16BIT;
	in++;
      }
      else
	break;
 
      if (d != HINT_NONE && d != operand_hint) {
	print_error("Confusing operand hint!\n", ERROR_STC);
	in++;
      }
    }
    else if (*in == ')') {
      si[q].type = STACK_ITEM_TYPE_OPERATOR;
      si[q].value = SI_OP_RIGHT;
      /* end of expression? */
      if (b == 0)
	break;
      b--;
      q++;
      in++;
    }
    else if (*in == ',')
      break;
    else if (*in == ']')
      break;
    else if (*in == '%') {
      d = 0;
      for (k = 0; k < 31; k++, d = d<<1) {
	in++;
	e = *in;
	if (e == '0' || e == '1')
	  d += e - '0';
	else if (e == ' ' || e == ')' || e == '|' || e == '&' || e == '+' || e == '-' || e == '*' ||
		 e == '/' || e == ',' || e == '^' || e == '<' || e == '>' || e == '#' || e == '~' ||
		 e == ']' || e == '.' || e == 0x0A)
	  break;
	else {
	  if (input_number_error_msg == YES) {
	    sprintf(xyz, "Got '%c' (%d) when expected (0/1).\n", e, e);
	    print_error(xyz, ERROR_NUM);
	  }
	  return FAILED;
	}
      }
 
      d = d>>1;
 
      si[q].type = STACK_ITEM_TYPE_VALUE;
      si[q].value = d;
      si[q].sign = SI_SIGN_POSITIVE;
      q++;
    }
    else if (*in == '\'') {
      in++;
      d = *in;
      in++;
      if (*in != '\'') {
        sprintf(xyz, "Got '%c' (%d) when expected \"'\".\n", *in, *in);
        print_error(xyz, ERROR_NUM);
	return FAILED;
      }
      in++;
 
      si[q].type = STACK_ITEM_TYPE_VALUE;
      si[q].value = d;
      si[q].sign = SI_SIGN_POSITIVE;
      q++;
    }
    else if (*in == '$') {
      d = 0;
      for (k = 0; k < 8; k++, d = d << 4) {
	in++;
	e = *in;
	if (e >= '0' && e <= '9')
	  d += e - '0';
	else if (e >= 'A' && e <= 'F')
	  d += e - 'A' + 10;
	else if (e >= 'a' && e <= 'f')
	  d += e - 'a' + 10;
	else if (e == ' ' || e == ')' || e == '|' || e == '&' || e == '+' || e == '-' ||
		 e == '*' || e == '/' || e == ',' || e == '^' || e == '<' || e == '>' ||
		 e == '#' || e == '~' || e == ']' || e == '.' || e == 0x0A)
	  break;
	else {
	  if (input_number_error_msg == YES) {
	    sprintf(xyz, "Got '%c' (%d) when expected (0-F).\n", e, e);
	    print_error(xyz, ERROR_NUM);
	  }
	  return FAILED;
	}
      }
 
      d = d >> 4;
 
      si[q].type = STACK_ITEM_TYPE_VALUE;
      si[q].value = d;
      si[q].sign = SI_SIGN_POSITIVE;
      q++;
    }
    else if (*in >= '0' && *in <= '9') {
      /* is it a hexadecimal value after all? */
      n = 0;
      for (k = 0; k < 9; k++) {
	if (in[k] >= '0' && in[k] <= '9')
	  continue;
	if (in[k] >= 'a' && in[k] <= 'f') {
	  n = 1;
	  break;
	}
	if (in[k] >= 'A' && in[k] <= 'F') {
	  n = 1;
	  break;
	}
	if (in[k] == 'h' || in[k] == 'H') {
	  n = 1;
	  break;
	}
	break;
      }
 
      if (n == 1) {
	/* it's hex */
	d = 0;
	for (k = 0; k < 8; k++, d = d << 4) {
	  e = *(in++);
	  if (e >= '0' && e <= '9')
	    d += e - '0';
	  else if (e >= 'A' && e <= 'F')
	    d += e - 'A' + 10;
	  else if (e >= 'a' && e <= 'f')
	    d += e - 'a' + 10;
	  else if (e == ' ' || e == ')' || e == '|' || e == '&' || e == '+' || e == '-' ||
		   e == '*' || e == '/' || e == ',' || e == '^' || e == '<' || e == '>' ||
		   e == '#' || e == '~' || e == ']' || e == '.' || e == 'h' || e == 'H' || e == 0x0A)
	    break;
	  else {
	    if (input_number_error_msg == YES) {
	      sprintf(xyz, "Got '%c' (%d) when expected (0-F).\n", e, e);
	      print_error(xyz, ERROR_NUM);
	    }
	    return FAILED;
	  }
	}
 
	d = d >> 4;
 
	si[q].type = STACK_ITEM_TYPE_VALUE;
	si[q].value = d;
	si[q].sign = SI_SIGN_POSITIVE;
	q++;
      }
      else {
	/* it's decimal */
	dou = (*in - '0')*10.0;
	dom = 1.0;
	n = 0;
	for (k = 0; k < 9; k++) {
	  in++;
	  e = *in;
	  if (e >= '0' && e <= '9') {
	    if (n == 0) {
	      dou += e - '0';
	      dou *= 10.0;
	    }
	    else if (n == 1) {
	      dou += dom*(e - '0');
	      dom /= 10.0;
	    }
	  }
	  else if (e == ' ' || e == ')' || e == '|' || e == '&' || e == '+' || e == '-' || e == '*' ||
		   e == '/' || e == ',' || e == '^' || e == '<' || e == '>' || e == '#' || e == '~' ||
		   e == ']' || e == 0x0A)
	    break;
	  else if (e == '.') {
	    if (*(in+1) == 'b' || *(in+1) == 'B' || *(in+1) == 'w' || *(in+1) == 'W')
	      break;
	    if (parse_floats == NO)
	      break;
	    if (n == 1) {
	      if (input_number_error_msg == YES)
		print_error("Syntax error.\n", ERROR_NUM);
	      return FAILED;
	    }
	    n = 1;
	  }
	  else {
	    if (input_number_error_msg == YES) {
	      sprintf(xyz, "Got '%c' (%d) when expected (0-9).\n", e, e);
	      print_error(xyz, ERROR_NUM);
	    }
	    return FAILED;
	  }
	}
 
	dou /= 10;
 
	si[q].type = STACK_ITEM_TYPE_VALUE;
	si[q].value = dou;
	si[q].sign = SI_SIGN_POSITIVE;
	q++;
      }
    }
    else {
      /* it must be a string! */
      si[q].sign = SI_SIGN_POSITIVE;
      for (k = 0; k < 63; k++) {
	e = *in;
	if (e == ' ' || e == ')' || e == '|' || e == '&' || e == '+' || e == '-' || e == '*' ||
	    e == '/' || e == ',' || e == '^' || e == '<' || e == '>' || e == '#' || e == ']' ||
	    e == '~' || e == 0xA)
	  break;
	if (e == '.' && (*(in+1) == 'b' || *(in+1) == 'B' || *(in+1) == 'w' || *(in+1) == 'W' || *(in+1) == 'l' || *(in+1) == 'L') &&
	    (*(in+2) == ' ' || *(in+2) == ')' || *(in+2) == '|' || *(in+2) == '&' || *(in+2) == '+' || *(in+2) == '-' || *(in+2) == '*' ||
	     *(in+2) == '/' || *(in+2) == ',' || *(in+2) == '^' || *(in+2) == '<' || *(in+2) == '>' || *(in+2) == '#' || *(in+2) == ']' ||
	     *(in+2) == '~' || *(in+2) == 0xA))
	  break;
	si[q].string[k] = e;
	in++;
      }
      si[q].string[k] = 0;
 
      si[q].type = STACK_ITEM_TYPE_STRING;
      q++;
    }
 
    if (q == 255) {
      print_error("Out of stack space.\n", ERROR_STC);
      return FAILED;
    }
  }
 
  if (b != 0) {
    print_error("Unbalanced parentheses.\n", ERROR_STC);
    return FAILED;
  }
 
  /* only one item found -> let the item parser handle it */
  if (q == 1)
    return STACK_CALCULATE_DELAY;
 
  /* check if there was data before the computation */
  if (q > 1 && (si[0].type == STACK_ITEM_TYPE_STRING || si[0].type == STACK_ITEM_TYPE_VALUE)) {
    if (si[1].type == STACK_ITEM_TYPE_STRING || si[1].type == STACK_ITEM_TYPE_VALUE)
      return STACK_CALCULATE_DELAY;
    if (si[1].type == STACK_ITEM_TYPE_OPERATOR) {
      if (si[1].value == SI_OP_LEFT)
	return STACK_CALCULATE_DELAY;
    }
  }
 
  /* check if the computation is of the form "+-..." and remove that leading "+" */
  if (q > 2 && si[0].type == STACK_ITEM_TYPE_OPERATOR && si[0].value == SI_OP_PLUS &&
      si[1].type == STACK_ITEM_TYPE_OPERATOR && si[1].value == SI_OP_MINUS) {
    si[0].type = STACK_ITEM_TYPE_DELETED;
  }
 
  /* update the source pointer */
  i = in - buffer;
 
  /* fix the sign in every operand */
  for (b = 1, k = 0; k < q; k++) {
    if ((q - k) != 1 && si[k].type == STACK_ITEM_TYPE_OPERATOR && si[k + 1].type == STACK_ITEM_TYPE_OPERATOR) {
      if (si[k].value != SI_OP_LEFT && si[k].value != SI_OP_RIGHT && si[k + 1].value != SI_OP_LEFT && si[k + 1].value != SI_OP_RIGHT) {
	print_error("Error in computation syntax.\n", ERROR_STC);
	return FAILED;
      }
    }
    if (si[k].type == STACK_ITEM_TYPE_OPERATOR && si[k].value == SI_OP_MINUS && b == 1) {
      if (si[k + 1].type == STACK_ITEM_TYPE_VALUE || si[k + 1].type == STACK_ITEM_TYPE_STRING) {
	if (si[k + 1].sign == SI_SIGN_POSITIVE)
	  si[k + 1].sign = SI_SIGN_NEGATIVE;
	else
	  si[k + 1].sign = SI_SIGN_POSITIVE;
	/* it wasn't a minus operator, it was a sign */
	si[k].type = STACK_ITEM_TYPE_DELETED;
      }
      else if (si[k + 1].type == STACK_ITEM_TYPE_OPERATOR && si[k + 1].value == SI_OP_LEFT) {
	o = 1;
	l = k + 2;
	while (o > 0 && l < q) {
	  if (si[l].type == STACK_ITEM_TYPE_VALUE || si[l].type == STACK_ITEM_TYPE_STRING) {
	    if (si[l].sign == SI_SIGN_POSITIVE)
	      si[l].sign = SI_SIGN_NEGATIVE;
	    else
	      si[l].sign = SI_SIGN_POSITIVE;
	  }
	  else if (si[l].type == STACK_ITEM_TYPE_OPERATOR) {
	    if (si[l].value == SI_OP_LEFT)
	      o++;
	    else if (si[l].value == SI_OP_RIGHT)
	      o--;
	  }
	  l++;
	}
 
	if (o != 0) {
	  print_error("Unbalanced parentheses.\n", ERROR_STC);
	  return FAILED;
	}
 
	si[k].type = STACK_ITEM_TYPE_DELETED;
      }
    }
    /* remove unnecessary + */
    if (si[k].type == STACK_ITEM_TYPE_OPERATOR && si[k].value == SI_OP_PLUS && b == 1) {
      if (si[k + 1].type == STACK_ITEM_TYPE_VALUE || si[k + 1].type == STACK_ITEM_TYPE_STRING)
	si[k].type = STACK_ITEM_TYPE_DELETED;
      else if (si[k + 1].type == STACK_ITEM_TYPE_OPERATOR && si[k + 1].value == SI_OP_LEFT)
	si[k].type = STACK_ITEM_TYPE_DELETED;
    }
    else if (si[k].type == STACK_ITEM_TYPE_VALUE || si[k].type == STACK_ITEM_TYPE_STRING)
      b = 0;
    else if (si[k].type == STACK_ITEM_TYPE_OPERATOR && si[k].value == SI_OP_LEFT)
      b = 1;
  }
 
  /* convert infix stack into postfix stack */
  for (b = 0, k = 0, d = 0; k < q; k++) {
    /* operands pass through */
    if (si[k].type == STACK_ITEM_TYPE_VALUE) {
      ta[d].type = si[k].type;
      ta[d].value = si[k].value;
      ta[d].sign = si[k].sign;
      d++;
    }
    else if (si[k].type == STACK_ITEM_TYPE_STRING) {
      ta[d].type = si[k].type;
      strcpy(ta[d].string, si[k].string);
      ta[d].sign = si[k].sign;
      d++;
    }
    /* operators get inspected */
    else if (si[k].type == STACK_ITEM_TYPE_OPERATOR) {
      if (b == 0) {
	op[0] = si[k].value;
	b++;
      }
      else {
	if (si[k].value == SI_OP_PLUS) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_PLUS;
	  b++;
	}
	else if (si[k].value == SI_OP_MINUS) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_MINUS;
	  b++;
	}
	else if (si[k].value == SI_OP_LOW_BYTE) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_LOW_BYTE;
	  b++;
	}
	else if (si[k].value == SI_OP_HIGH_BYTE) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_HIGH_BYTE;
	  b++;
	}
	else if (si[k].value == SI_OP_XOR) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_XOR;
	  b++;
	}
	else if (si[k].value == SI_OP_MULTIPLY) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_MULTIPLY;
	  b++;
	}
	else if (si[k].value == SI_OP_DIVIDE) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_DIVIDE;
	  b++;
	}
	else if (si[k].value == SI_OP_MODULO) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_MODULO;
	  b++;
	}
	else if (si[k].value == SI_OP_POWER) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_POWER;
	  b++;
	}
	else if (si[k].value == SI_OP_SHIFT_LEFT) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_SHIFT_LEFT;
	  b++;
	}
	else if (si[k].value == SI_OP_SHIFT_RIGHT) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_SHIFT_RIGHT;
	  b++;
	}
	else if (si[k].value == SI_OP_AND) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_AND;
	  b++;
	}
	else if (si[k].value == SI_OP_OR) {
	  b--;
	  while (b != -1 && op[b] != SI_OP_LEFT && op[b] != SI_OP_PLUS && op[b] != SI_OP_MINUS) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	  b++;
	  op[b] = SI_OP_OR;
	  b++;
	}
	else if (si[k].value == SI_OP_LEFT) {
	  op[b] = SI_OP_LEFT;
	  b++;
	}
	else if (si[k].value == SI_OP_RIGHT) {
	  b--;
	  while (op[b] != SI_OP_LEFT) {
	    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
	    ta[d].value = op[b];
	    b--;
	    d++;
	  }
	}
      }
    }
  }
 
  /* empty the operator stack */
  while (b > 0) {
    b--;
    ta[d].type = STACK_ITEM_TYPE_OPERATOR;
    ta[d].value = op[b];
    d++;
  }
 
  /* DEBUG output
  printf("STACK ID %d LINE %d\n", stack_id, active_file_info_last->line_current);
  for (k = 0; k < d; k++) {
    char ar[] = "+-*()|&/^«»%~<>";
 
    if (ta[k].type == STACK_ITEM_TYPE_OPERATOR)
      printf("%c ", ar[((int)ta[k].value)]);
    else if (ta[k].type == STACK_ITEM_TYPE_VALUE)
      printf("V(%f) ", ta[k].value);
    else
      printf("S(%s) ", ta[k].string);
  }
  printf("\n");
  */
 
  /* are all the symbols known? */
  if (resolve_stack(ta, d) == SUCCEEDED) {
    s.stack = ta;
    s.linenumber = active_file_info_last->line_current;
    s.filename_id = active_file_info_last->filename_id;
 
    if (compute_stack(&s, d, &dou) == FAILED)
      return FAILED;
 
    if (input_float_mode == ON) {
      flo = dou;
      return INPUT_NUMBER_FLOAT;
    }
 
    *value = (int)dou;
 
    return SUCCEEDED;
  }
 
  /* only one string? */
  if (d == 1 && ta[0].type == STACK_ITEM_TYPE_STRING) {
    strcpy(label, ta[0].string);
    return STACK_RETURN_LABEL;
  }
 
  /* we have a stack full of computation and we save it for wlalink */
  stacks_tmp = malloc(sizeof(struct stack));
  if (stacks_tmp == NULL) {
    print_error("Out of memory error while allocating room for a new stack.\n", ERROR_STC);
    return FAILED;
  }
  stacks_tmp->next = NULL;
  stacks_tmp->type = STACKS_TYPE_UNKNOWN;
  stacks_tmp->bank = -123456;
  stacks_tmp->stacksize = d;
  stacks_tmp->stack = malloc(sizeof(struct stack_item) * d);
  if (stacks_tmp->stack == NULL) {
    free(stacks_tmp);
    print_error("Out of memory error while allocating room for a new stack.\n", ERROR_STC);
    return FAILED;
  }
 
  stacks_tmp->linenumber = active_file_info_last->line_current;
  stacks_tmp->filename_id = active_file_info_last->filename_id;
 
  /* all stacks will be definition stacks by default. pass_4 will mark
     those that are referenced to be STACK_POSITION_CODE stacks */
  stacks_tmp->position = STACK_POSITION_DEFINITION;
 
  for (q = 0; q < d; q++) {
    if (ta[q].type == STACK_ITEM_TYPE_OPERATOR) {
      stacks_tmp->stack[q].type = STACK_ITEM_TYPE_OPERATOR;
      stacks_tmp->stack[q].value = ta[q].value;
    }
    else if (ta[q].type == STACK_ITEM_TYPE_VALUE) {
      stacks_tmp->stack[q].type = STACK_ITEM_TYPE_VALUE;
      stacks_tmp->stack[q].value = ta[q].value;
      stacks_tmp->stack[q].sign = ta[q].sign;
    }
    else if (ta[q].type == STACK_ITEM_TYPE_STACK) {
      stacks_tmp->stack[q].type = STACK_ITEM_TYPE_STACK;
      stacks_tmp->stack[q].value = ta[q].value;
      stacks_tmp->stack[q].sign = ta[q].sign;
    }
    else {
      stacks_tmp->stack[q].type = STACK_ITEM_TYPE_STRING;
      stacks_tmp->stack[q].sign = ta[q].sign;
      strcpy(stacks_tmp->stack[q].string, ta[q].string);
    }
  }
 
  _stack_insert();
 
  return INPUT_NUMBER_STACK;
}
 
 
int resolve_stack(struct stack_item s[], int x) {
 
  struct macro_argument *ma;
  struct stack_item *st;
  int a, b, k, q = x;
  char c;
 
 
  st = s;
  while (x > 0) {
    if (s->type == STACK_ITEM_TYPE_STRING) {
      if (macro_active != 0 && s->string[0] == '\\') {
	if (s->string[1] == '@' && s->string[2] == 0) {
	  s->type = STACK_ITEM_TYPE_VALUE;
	  s->value = macro_runtime_current->macro->calls - 1;
	}
	else {
	  for (a = 0, b = 0; s->string[a + 1] != 0 && a < 10; a++) {
	    c = s->string[a + 1];
	    if (c < '0' && c > '9') {
	      print_error("Error in MACRO argument number definition.\n", ERROR_DIR);
	      return FAILED;
	    }
	    b = (b * 10) + (c - '0');
	  }
 
	  if (b > macro_runtime_current->supplied_arguments) {
	    sprintf(xyz, "Reference to MACRO argument number %d is out of range.\n", b);
	    print_error(xyz, ERROR_STC);
	    return FAILED;
	  }
 
	  /* return the macro argument */
	  ma = macro_runtime_current->argument_data[b - 1];
	  k = ma->type;
 
	  if (k == INPUT_NUMBER_ADDRESS_LABEL)
	    strcpy(label, ma->string);
	  else if (k == INPUT_NUMBER_STRING) {
	    strcpy(label, ma->string);
	    string_size = strlen(ma->string);
	  }
	  else if (k == INPUT_NUMBER_STACK)
	    latest_stack = ma->value;
	  else if (k == SUCCEEDED)
	    d = ma->value;
 
	  if (!(k == SUCCEEDED || k == INPUT_NUMBER_ADDRESS_LABEL || k == INPUT_NUMBER_STACK))
	    return FAILED;
 
	  if (k == SUCCEEDED) {
	    s->type = STACK_ITEM_TYPE_VALUE;
	    s->value = d;
	  }
	  else if (k == INPUT_NUMBER_STACK) {
	    s->type = STACK_ITEM_TYPE_STACK;
	    s->value = latest_stack;
	  }
	  else
	    strcpy(s->string, label);
	}
      }
      else {
	if (macro_active != 0) {
	  /* expand e.g., \1 and \@ */
	  d = 0;
	  if (expand_macro_arguments(s->string, &d) == FAILED)
	    return FAILED;
	  strcpy(s->string, expanded_macro_string);
	}
 
	tmp_def = defines;
	while (tmp_def != NULL) {
	  if (strcmp(tmp_def->alias, s->string) == 0) {
	    if (tmp_def->type == DEFINITION_TYPE_STRING) {
	      sprintf(xyz, "Definition \"%s\" is a string definition.\n", tmp_def->alias);
	      print_error(xyz, ERROR_STC);
	      return FAILED;
	    }
	    else if (tmp_def->type == DEFINITION_TYPE_STACK) {
	      /* skip stack definitions -> use its name instead */
	    }
	    else {
	      s->type = STACK_ITEM_TYPE_VALUE;
	      s->value = tmp_def->value;
	      break;
	    }
	  }
	  tmp_def = tmp_def->next;
	}
      }
    }
    s++;
    x--;
  }
 
  /* find a string or a stack and fail */
  while (q > 0) {
    if (st->type == STACK_ITEM_TYPE_STRING || st->type == STACK_ITEM_TYPE_STACK)
      return FAILED;
    q--;
    st++;
  }
 
  return SUCCEEDED;
}
 
 
int compute_stack(struct stack *sta, int x, double *result) {
 
  struct stack_item *s;
  double v[256], q;
  int r, t, z;
 
 
  s = sta->stack;
  for (r = 0, t = 0; r < x; r++, s++) {
    if (s->type == STACK_ITEM_TYPE_VALUE) {
      if (s->sign == SI_SIGN_NEGATIVE)
	v[t] = -s->value;
      else
	v[t] = s->value;
      t++;
    }
    else {
      switch ((int)s->value) {
      case SI_OP_PLUS:
	v[t - 2] += v[t - 1];
	t--;
	break;
      case SI_OP_MINUS:
	v[t - 2] -= v[t - 1];
	t--;
	break;
      case SI_OP_MULTIPLY:
	v[t - 2] *= v[t - 1];
	t--;
	break;
      case SI_OP_LOW_BYTE:
	z = (int)v[t - 1];
	v[t - 1] = z & 0xFF;
	break;
      case SI_OP_HIGH_BYTE:
	z = (int)v[t - 1];
	v[t - 1] = (z>>8) & 0xFF;
	break;
      case SI_OP_XOR:
	/* 16bit XOR? */
	if (v[t - 2] > 0xFF || v[t - 2] < -128 || v[t - 1] > 0xFF || v[t - 1] < -128)
	  v[t - 2] = ((int)v[t - 1] ^ (int)v[t - 2]) & 0xFFFF;
	/* 8bit XOR */
	else
	  v[t - 2] = ((int)v[t - 1] ^ (int)v[t - 2]) & 0xFF;
	t--;
	break;
      case SI_OP_OR:
	v[t - 2] = (int)v[t - 1] | (int)v[t - 2];
	t--;
	break;
      case SI_OP_AND:
	v[t - 2] = (int)v[t - 1] & (int)v[t - 2];
	t--;
	break;
      case SI_OP_MODULO:
	if (((int)v[t - 1]) == 0) {
	  fprintf(stderr, "%s:%d: COMPUTE_STACK: Modulo by zero.\n", get_file_name(sta->filename_id), sta->linenumber);
	  return FAILED;
	}
	v[t - 2] = (int)v[t - 2] % (int)v[t - 1];
	t--;
	break;
      case SI_OP_DIVIDE:
	if (((int)v[t - 1]) == 0) {
	  fprintf(stderr, "%s:%d: COMPUTE_STACK: Division by zero.\n", get_file_name(sta->filename_id), sta->linenumber);
	  return FAILED;
	}
	v[t - 2] /= v[t - 1];
	t--;
	break;
      case SI_OP_POWER:
	q = 1;
	for (z = 0; z < v[t - 1]; z++)
	  q *= v[t - 2];
	v[t - 2] = q;
	t--;
	break;
      case SI_OP_SHIFT_LEFT:
	v[t - 2] = (int)v[t - 2] << (int)v[t - 1];
	t--;
	break;
      case SI_OP_SHIFT_RIGHT:
	v[t - 2] = (int)v[t - 2] >> (int)v[t - 1];
	t--;
	break;
      }
    }
  }
 
  if (v[0] < -32768 || v[0] > 65536) {
    print_error("Out of 16bit range.\n", ERROR_STC);
    return FAILED;
  }
 
  *result = v[0];
 
  return SUCCEEDED;
}
 
 
int stack_create_label_stack(char *label) {
 
  if (label == NULL)
    return FAILED;
 
  /* we need to create a stack that holds just one label */
  stacks_tmp = malloc(sizeof(struct stack));
  if (stacks_tmp == NULL) {
    print_error("Out of memory error while allocating room for a new stack.\n", ERROR_STC);
    return FAILED;
  }
  stacks_tmp->next = NULL;
  stacks_tmp->type = STACKS_TYPE_UNKNOWN;
  stacks_tmp->bank = -123456;
  stacks_tmp->stacksize = 1;
  stacks_tmp->stack = malloc(sizeof(struct stack_item) * 1);
  if (stacks_tmp->stack == NULL) {
    free(stacks_tmp);
    print_error("Out of memory error while allocating room for a new stack.\n", ERROR_STC);
    return FAILED;
  }
 
  stacks_tmp->linenumber = active_file_info_last->line_current;
  stacks_tmp->filename_id = active_file_info_last->filename_id;
 
  /* all stacks will be definition stacks by default. pass_4 will mark
     those that are referenced to be STACK_POSITION_CODE stacks */
  stacks_tmp->position = STACK_POSITION_DEFINITION;
 
  stacks_tmp->stack[0].type = STACK_ITEM_TYPE_STRING;
  stacks_tmp->stack[0].sign = SI_SIGN_POSITIVE;
  strcpy(stacks_tmp->stack[0].string, label);
 
  _stack_insert();
 
  return SUCCEEDED;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.