
int printable_token(int x) {
  return (symbolp(x) == Mtrue) || (stringp(x) == Mtrue)
    || (numberp(x) == Mtrue) || (charp(x) == Mtrue)
    || (x == Mtrue) || (x == Mfalse)
    || (procedurep(x) == Mtrue);
}

int write_chr(int x) {
  if (charp(x) == Mtrue)
    putchar(MgetChar(x));
  else
    putchar('?');
  return x;
}

void write_symbol(int x) {
  int temp;
  int i;
  int l;
  l = MstrSizeRef(x);
  for (i = 0; i < l; i++)
    temp = write_chr(symbol_ref(x, i));
  return;
}

void write_string(int x, int mode) {
  int temp;
  int i;
  int c;
  for (i = 0; i < MstrSizeRef(x); i++) {
    c = string_ref(x, i);
    if (mode)
      if ((MgetChar(c) == '\\') || (MgetChar(c) == '"'))
        putchar('\\');
    temp = write_chr(c);
  }
  return;
}

void print_token(int x, int mode) {
  int temp; // used by print macro
  if ((x == Mtrue))
    printf("#t");
  else if ((x == Mfalse))
    printf("#f");
  else if (numberp(x) == Mtrue)
    print_number(x);
  else if (stringp(x) == Mtrue) {
    if (mode)
      putchar('"');
    write_string(x, mode);
    if (mode)
      putchar('"');
  }
  else if (charp(x) == Mtrue) {
    if (mode) {
      printf("#\\");
      if (MgetChar(x) == ' ')
        printf("space");
      else if (MgetChar(x) == newline_char)
        printf("newline");
      else
        temp = write_chr(x);
    }
    else
      temp = write_chr(x);
  }
  else if (procedurep(x) == Mtrue)
    print_token(procedureatom, mode);
  else
    write_symbol(x);
  return;
}

void print_list(int x, int mode) {
  int lst;
  int y;
  putchar('(');
  lst = x;
  while (lst != 0) {
    y = Mcar(lst);
    if (vectorp(y) == Mtrue)
      print_vector(y, mode);
    else if (Mnull(y))
      printf("()");
    else if (printable_token(y))
      print_token(y, mode);
    else
      print_list(y, mode);

    if (Mcdr(lst) != 0)
      putchar(' ');
    lst = Mcdr(lst);
    if (printable_token(lst)) {
      printf(". ");
      print_token(lst, mode);
      lst = 0;
    }
  }
  putchar(')');
  return;
}

void print_vector(int v, int mode) {
  int size;
  int n;
  int x;
  printf("#(");
  size = Mveclength(v);
  for (n = 0; n < size; n++) {
    x = vector_ref(v, n);
    if (vectorp(x) == Mtrue)
      print_vector(x, mode);
    else
      princ(x, mode);
    if (n != size - 1)
      putchar(' ');
  }
  putchar(')');
  return;
}

void princ(int x, int mode) {
  if (Mnull(x))
    print_list(x, mode);
  else if (printable_token(x))
    print_token(x, mode);
  else if (vectorp(x) == Mtrue)
    print_vector(x, mode);
  else
    print_list(x, mode);
  return;
}

int display_(int x) {
  princ(x, 0);
  return x;
}

int writeout(int x) {
  princ(x, 1);
  return x;
}

int newline_() {
  writeln();
  return 0;
}
