
int reducesize(int size) {
  return ((size - 1) >> 2) + 1;
}

int symbol_ref(int symbol, int n) {
  int temp;
  if (n > MstrSizeRef(symbol) - 1) {
    temp = MstrSizeRef(symbol) - 1;
    printf("symbol reference out of range ");
    write_int(n);
    printf(" exceeds ");
    write_int(temp);
    writeln();
    cleanup_();
  }
  return MmakeChar(Mstrref(symbol, n));
}

void symbol_set(int symbol, int n, int int_ch) {
  int temp;

  if (n > MstrSizeRef(symbol) - 1) {
    temp = MstrSizeRef(symbol) - 1;
    printf("symbol reference out of range ");
    write_int(n);
    printf(" exceeds ");
    write_int(temp);
    printf(" character ");
    putchar(int_ch);
    writeln();
    cleanup_();
  }
  Mstrset(symbol, n, MgetChar(int_ch));
  return;
}

int symbol_hash(int symbol) { // a scheme extension
  int symbol_size;
  int hash;

  symbol_size = MstrSizeRef(symbol);
  if (symbol_size == 0)
    hash = 0;
  else // use 4 most significant packed characters as a hash
    hash = Mvecref(symbol, 2);
  return make_integer(hash);
}

int symboleq(int x, int y) {
  int length_x;
  int length_y;
  int i;

  length_x = MstrSizeRef(x);
  length_y = MstrSizeRef(y);
  if (length_x != length_y)
    return 0;
  else {
    i = 0;
    while (1) {
      if (i < length_x) {
        if (symbol_ref(x, i) != symbol_ref(y, i))
          return 0; // symbols not equal
      }
      else
        return 1; // symbols are equal
      i = i + 1;
    }
  }
}

int make_symbol(int n) {
  int symbol;
  symbol = make_vector_core(1 + reducesize(n), SYMBOLSUBTYPE);
  Mvecset(symbol, 1, n);
  return symbol;
}

int list_to_symbol(int l) {
  int s;
  int n;
  int size;

  size = list_length(l);
  s = make_symbol(size);
  for (n = 0; n < size; n++) {
    symbol_set(s, n, Mcar(l));
    l = kdr(l);
  }
  return s;
}
