int temp_label(void)
{
  static int next = 999;
  next += 1;
  return next;
}

void assign_loop_labels(int p, int break_lab, int continue_lab, int branch_back_lab)
{ // (It's really "loop and switch" due to need to handle "break" keyword)
  int i;
  int disp;
  int this;

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

  // Put source-level tests here in common code, not in code-generator where they were before.
  // If I can't find a way to get the source line here, maybe even move it back up to grammar.c
  if (astop(p) == AST_C_Continue) {
    if (continue_lab == -1) {fprintf(stderr, "* ERROR: continue not in a loop\n"); exit(1);}
    leftchild(p) = continue_lab;
    return;
  } else if (astop(p) == AST_C_Break) {
    if (break_lab == -1) {fprintf(stderr, "* ERROR: break not in a loop or switch\n"); exit(1);}
    leftchild(p) = break_lab;
    return;
  }

  // When a loop or switch body is found, set up the parameters
  // for any continues or breaks inside those statements.

  // Nested switch statements take priority over loops for a "break"

  if ((astop(p) == AST_C_While) || (astop(p) == AST_C_DoWhile)) {
    break_lab = nthchild(p, 2+0);
    continue_lab = nthchild(p, 2+1);
    branch_back_lab = nthchild(p, 2+2); // actually in while() it is used for the start of the code body
    if (break_lab == -1) nthchild(p, 2+0) = break_lab = temp_label();
    if (continue_lab == -1) nthchild(p, 2+1) = continue_lab = temp_label();
    if (branch_back_lab == -1) nthchild(p, 2+2) = branch_back_lab = temp_label(); // again, body_lab
    assign_loop_labels(rightchild(p), break_lab, continue_lab, branch_back_lab);
  } else if (astop(p) == AST_C_ForLoop) {
    break_lab = nthchild(p, 4+0);
    continue_lab = nthchild(p, 4+1);
    branch_back_lab = nthchild(p, 4+2);
    if (break_lab == -1) nthchild(p, 4+0) = break_lab = temp_label();
    if (continue_lab == -1) nthchild(p, 4+1) = continue_lab = temp_label();
    if (branch_back_lab == -1) nthchild(p, 4+2) = branch_back_lab = temp_label();
    nthchild(p, 4+3) = temp_label(); // body lab
    assign_loop_labels(nthchild(p, 3), break_lab, continue_lab, branch_back_lab);
  } else if (astop(p) == AST_Switch) {
    int case_lab_chain;
    int default_lab;
    break_lab = nthchild(p, 2+0); // <cond> <body> break_lab
    case_lab_chain = nthchild(p, 2+1); // chain of 'case <n>' labels
    default_lab = nthchild(p, 2+2); // default label.

    if (break_lab == -1) {
      nthchild(p, 2) = break_lab = temp_label();
    }
    assign_loop_labels(rightchild(p), break_lab, continue_lab, branch_back_lab);

  }

  // recursively search for more loops and switch bodies throughout the code:

  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)) {
      assign_loop_labels(nthchild(p, i), break_lab, continue_lab, branch_back_lab);
    }
    this = this>>1;
  }

}
