// WARNING: a switch statement generates a "DEFAULT" opcode even though no "default:" was given.
// it should in that case send it to a piece of code that prints out the fact that a switch label
// was missing and there was no default.  Depending on how fancy the diags get, that can be specific
// about which switch it was (source line no) and what the index was.

void build_switch_table(int p, int enclosing_switch)
{
  int i;
  int disp;
  int this;

  if ((p == -1) || (astop(p) == -1)) return;

  if (astop(p) == AST_Switch) {

    // leftchild = switch value
    // rightchild = compound statement
    // 1st extra field is for target of "break" statement (integer)
    // 2nd extra field is link to chain of case statements (integer)
    // 3rd extra field is default case (integer)

    build_switch_table(rightchild(p), p);
    // Now we have all the case labels in a linked list, and we know
    // where the default is.

    if (nthchild(p, 3) == -1) {
      if (nthchild(p, 4) == -1) {
        fprintf(stderr, "* Error: switch block does not contain any case statements (or default:)\n");
      } else {
        fprintf(stderr, "? Warning: switch block does not contain any case statements\n");
      }
    }

  } else if (astop(p) == AST_Case) {

    // leftchild = <n>,
    // rightchild = link to next case
    // last = internal number for label

    if (enclosing_switch == -1) fprintf(stderr, "* ERROR: case with no switch?\n"); // move to point of call in grammar.c?

    nthchild(p, 2) = temp_label(); 
    rightchild(p) = nthchild(enclosing_switch, 2+1);
    nthchild(enclosing_switch, 2+1) = p;
  } else if (astop(p) == AST_DefaultCase) {

    if (enclosing_switch == -1) fprintf(stderr, "* ERROR: default with no switch?\n"); // move to point of call in grammar.c?

    leftchild(p) = enclosing_switch;
    rightchild(p) = temp_label();
    nthchild(enclosing_switch, 2+2) = p;
  } else {
    // recursively search for more switch bodies throughout the code:
    // We could alternatively call one level of this in grammar.c after
    // compiling the switch
    disp = op[astop(p)-AST_BASE].Display_Children;
    this = 1<<(children(p)-1);
    for (i = 0; i < children(p); i++) {
      if ((nthchild(p, i) != -1) && (disp&this)) {
        build_switch_table(nthchild(p, i), enclosing_switch);
      }
      this = this>>1;
    }
  }
}
