Beispiel #1
0
// Has to be called whenever a method is compiled
void IdealGraphPrinter::begin_method() {

  ciMethod *method = C->method();
  assert(_output, "output stream must exist!");
  assert(method, "null methods are not allowed!");
  assert(!_current_method, "current method must be null!");

  head(GROUP_ELEMENT);

  head(PROPERTIES_ELEMENT);

  // Print properties
  // Add method name
  stringStream strStream;
  method->print_name(&strStream);
  print_prop(METHOD_NAME_PROPERTY, strStream.as_string());

  if (method->flags().is_public()) {
    print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE);
  }

  if (method->flags().is_static()) {
    print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE);
  }

  tail(PROPERTIES_ELEMENT);

  _should_send_method = true;
  this->_current_method = method;

  _xml->flush();
}
Beispiel #2
0
int __kinit__ bcm2835_info_init(void)
{
    SUBSYS_DEP(bcm2835_prop_init);
    SUBSYS_INIT("BCM2835_info");

    kputs("\n");
    print_prop("firmware", 0x00000001, 1);
    print_prop("board model", 0x00010001, 1);
    print_prop("board rev", 0x00010002, 1);
    print_prop("board serial", 0x00010004, 2);

    return 0;
}
Beispiel #3
0
int
main(void)
{
unsigned char buffer[1024];
while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
  {
  unsigned char name[24];
  unsigned char *s, *t;

  printf("%s", buffer);
  s = buffer;
  while (isspace(*s)) s++;
  if (*s == 0) continue;

  for (t = name; *s != 0 && !isspace(*s); s++) *t++ = *s;
  *t = 0;
  while (isspace(*s)) s++;

  if (strcmp(CS name, "findprop") == 0)
    {
    while (*s != 0)
      {
      unsigned char *endptr;
      int c = strtoul(CS s, CSS(&endptr), 16);
      print_prop(c);
      s = endptr;
      while (isspace(*s)) s++;
      }
    }

  else printf("Unknown test command %s\n", name);
  }

return 0;
}
Beispiel #4
0
void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {

  if (edges) {

    // Output edge
    node_idx_t dest_id = n->_idx;
    for ( uint i = 0; i < n->len(); i++ ) {
      if ( n->in(i) ) {
        Node *source = n->in(i);
        begin_elem(EDGE_ELEMENT);
        print_attr(FROM_PROPERTY, source->_idx);
        print_attr(TO_PROPERTY, dest_id);
        print_attr(INDEX_PROPERTY, i);
        end_elem();
      }
    }

  } else {

    // Output node
    begin_head(NODE_ELEMENT);
    print_attr(NODE_ID_PROPERTY, n->_idx);
    end_head();

    head(PROPERTIES_ELEMENT);

    Node *node = n;
#ifndef PRODUCT
    Compile::current()->_in_dump_cnt++;
    print_prop(NODE_NAME_PROPERTY, (const char *)node->Name());
    const Type *t = node->bottom_type();
    print_prop("type", t->msg());
    print_prop("idx", node->_idx);
#ifdef ASSERT
    print_prop("debug_idx", node->_debug_idx);
#endif

    if (C->cfg() != NULL) {
      Block* block = C->cfg()->get_block_for_node(node);
      if (block == NULL) {
        print_prop("block", C->cfg()->get_block(0)->_pre_order);
      } else {
        print_prop("block", block->_pre_order);
      }
    }

    const jushort flags = node->flags();
    if (flags & Node::Flag_is_Copy) {
      print_prop("is_copy", "true");
    }
    if (flags & Node::Flag_rematerialize) {
      print_prop("rematerialize", "true");
    }
    if (flags & Node::Flag_needs_anti_dependence_check) {
      print_prop("needs_anti_dependence_check", "true");
    }
    if (flags & Node::Flag_is_macro) {
      print_prop("is_macro", "true");
    }
    if (flags & Node::Flag_is_Con) {
      print_prop("is_con", "true");
    }
    if (flags & Node::Flag_is_cisc_alternate) {
      print_prop("is_cisc_alternate", "true");
    }
    if (flags & Node::Flag_is_dead_loop_safe) {
      print_prop("is_dead_loop_safe", "true");
    }
    if (flags & Node::Flag_may_be_short_branch) {
      print_prop("may_be_short_branch", "true");
    }
    if (flags & Node::Flag_has_call) {
      print_prop("has_call", "true");
    }

    if (C->matcher() != NULL) {
      if (C->matcher()->is_shared(node)) {
        print_prop("is_shared", "true");
      } else {
        print_prop("is_shared", "false");
      }
      if (C->matcher()->is_dontcare(node)) {
        print_prop("is_dontcare", "true");
      } else {
        print_prop("is_dontcare", "false");
      }

#ifdef ASSERT
      Node* old = C->matcher()->find_old_node(node);
      if (old != NULL) {
        print_prop("old_node_idx", old->_idx);
      }
#endif
    }

    if (node->is_Proj()) {
      print_prop("con", (int)node->as_Proj()->_con);
    }

    if (node->is_Mach()) {
      print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]);
    }

    buffer[0] = 0;
    stringStream s2(buffer, sizeof(buffer) - 1);

    node->dump_spec(&s2);
    if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
      const TypeInstPtr  *toop = t->isa_instptr();
      const TypeKlassPtr *tkls = t->isa_klassptr();
      ciKlass*           klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
      if( klass && klass->is_loaded() && klass->is_interface() ) {
        s2.print("  Interface:");
      } else if( toop ) {
        s2.print("  Oop:");
      } else if( tkls ) {
        s2.print("  Klass:");
      }
      t->dump_on(&s2);
    } else if( t == Type::MEMORY ) {
      s2.print("  Memory:");
      MemNode::dump_adr_type(node, node->adr_type(), &s2);
    }

    assert(s2.size() < sizeof(buffer), "size in range");
    print_prop("dump_spec", buffer);

    if (node->is_block_proj()) {
      print_prop("is_block_proj", "true");
    }

    if (node->is_block_start()) {
      print_prop("is_block_start", "true");
    }

    const char *short_name = "short_name";
    if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) {
      int index = node->as_Proj()->_con - TypeFunc::Parms;
      if (index >= 10) {
        print_prop(short_name, "PA");
      } else {
        sprintf(buffer, "P%d", index);
        print_prop(short_name, buffer);
      }
    } else if (strcmp(node->Name(), "IfTrue") == 0) {
      print_prop(short_name, "T");
    } else if (strcmp(node->Name(), "IfFalse") == 0) {
      print_prop(short_name, "F");
    } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) {

      if (t->base() == Type::Int && t->is_int()->is_con()) {
        const TypeInt *typeInt = t->is_int();
        assert(typeInt->is_con(), "must be constant");
        jint value = typeInt->get_con();

        // max. 2 chars allowed
        if (value >= -9 && value <= 99) {
          sprintf(buffer, "%d", value);
          print_prop(short_name, buffer);
        } else {
          print_prop(short_name, "I");
        }
      } else if (t == Type::TOP) {
        print_prop(short_name, "^");
      } else if (t->base() == Type::Long && t->is_long()->is_con()) {
        const TypeLong *typeLong = t->is_long();
        assert(typeLong->is_con(), "must be constant");
        jlong value = typeLong->get_con();

        // max. 2 chars allowed
        if (value >= -9 && value <= 99) {
          sprintf(buffer, JLONG_FORMAT, value);
          print_prop(short_name, buffer);
        } else {
          print_prop(short_name, "L");
        }
      } else if (t->base() == Type::KlassPtr) {
        const TypeKlassPtr *typeKlass = t->is_klassptr();
        print_prop(short_name, "CP");
      } else if (t->base() == Type::Control) {
        print_prop(short_name, "C");
      } else if (t->base() == Type::Memory) {
        print_prop(short_name, "M");
      } else if (t->base() == Type::Abio) {
        print_prop(short_name, "IO");
      } else if (t->base() == Type::Return_Address) {
        print_prop(short_name, "RA");
      } else if (t->base() == Type::AnyPtr) {
        print_prop(short_name, "P");
      } else if (t->base() == Type::RawPtr) {
        print_prop(short_name, "RP");
      } else if (t->base() == Type::AryPtr) {
        print_prop(short_name, "AP");
      }
    }

    JVMState* caller = NULL;
    if (node->is_SafePoint()) {
      caller = node->as_SafePoint()->jvms();
    } else {
      Node_Notes* notes = C->node_notes_at(node->_idx);
      if (notes != NULL) {
        caller = notes->jvms();
      }
    }

    if (caller != NULL) {
      stringStream bciStream;
      ciMethod* last = NULL;
      int last_bci;
      while(caller) {
        if (caller->has_method()) {
          last = caller->method();
          last_bci = caller->bci();
        }
        bciStream.print("%d ", caller->bci());
        caller = caller->caller();
      }
      print_prop("bci", bciStream.as_string());
      if (last != NULL && last->has_linenumber_table() && last_bci >= 0) {
        print_prop("line", last->line_number_from_bci(last_bci));
      }
    }

#ifdef ASSERT
    if (node->debug_orig() != NULL) {
      temp_set->Clear();
      stringStream dorigStream;
      Node* dorig = node->debug_orig();
      while (dorig && temp_set->test_set(dorig->_idx)) {
        dorigStream.print("%d ", dorig->_idx);
      }
      print_prop("debug_orig", dorigStream.as_string());
    }
#endif

    if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
      buffer[0] = 0;
      _chaitin->dump_register(node, buffer);
      print_prop("reg", buffer);
      uint lrg_id = 0;
      if (node->_idx < _chaitin->_lrg_map.size()) {
        lrg_id = _chaitin->_lrg_map.live_range_id(node);
      }
      print_prop("lrg", lrg_id);
    }

    Compile::current()->_in_dump_cnt--;
#endif

    tail(PROPERTIES_ELEMENT);
    tail(NODE_ELEMENT);
  }
}
Beispiel #5
0
void IdealGraphPrinter::print_prop(const char *name, int val) {
  stringStream stream;
  stream.print("%d", val);
  print_prop(name, stream.as_string());
}
Beispiel #6
0
static void
pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)
{
PCRE2_SPTR codestart, nametable, code;
uint32_t nesize = re->name_entry_size;
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;

nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));
code = codestart = nametable + re->name_count * re->name_entry_size;

for(;;)
  {
  PCRE2_SPTR ccode;
  uint32_t c;
  int i;
  const char *flag = "  ";
  unsigned int extra = 0;

  if (print_lengths)
    fprintf(f, "%3d ", (int)(code - codestart));
  else
    fprintf(f, "    ");

  switch(*code)
    {
/* ========================================================================== */
      /* These cases are never obeyed. This is a fudge that causes a compile-
      time error if the vectors OP_names or OP_lengths, which are indexed
      by opcode, are not the correct length. It seems to be the only way to do
      such a check at compile time, as the sizeof() operator does not work in
      the C preprocessor. */

      case OP_TABLE_LENGTH:
      case OP_TABLE_LENGTH +
        ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
        (sizeof(OP_lengths) == OP_TABLE_LENGTH)):
      break;
/* ========================================================================== */

    case OP_END:
    fprintf(f, "    %s\n", OP_names[*code]);
    fprintf(f, "------------------------------------------------------------------\n");
    return;

    case OP_CHAR:
    fprintf(f, "    ");
    do
      {
      code++;
      code += 1 + print_char(f, code, utf);
      }
    while (*code == OP_CHAR);
    fprintf(f, "\n");
    continue;

    case OP_CHARI:
    fprintf(f, " /i ");
    do
      {
      code++;
      code += 1 + print_char(f, code, utf);
      }
    while (*code == OP_CHARI);
    fprintf(f, "\n");
    continue;

    case OP_CBRA:
    case OP_CBRAPOS:
    case OP_SCBRA:
    case OP_SCBRAPOS:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));
    break;

    case OP_BRA:
    case OP_BRAPOS:
    case OP_SBRA:
    case OP_SBRAPOS:
    case OP_KETRMAX:
    case OP_KETRMIN:
    case OP_KETRPOS:
    case OP_ALT:
    case OP_KET:
    case OP_ASSERT:
    case OP_ASSERT_NOT:
    case OP_ASSERTBACK:
    case OP_ASSERTBACK_NOT:
    case OP_ONCE:
    case OP_ONCE_NC:
    case OP_COND:
    case OP_SCOND:
    case OP_REVERSE:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s", OP_names[*code]);
    break;

    case OP_CLOSE:
    fprintf(f, "    %s %d", OP_names[*code], GET2(code, 1));
    break;

    case OP_CREF:
    fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);
    break;

    case OP_DNCREF:
      {
      PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
      fprintf(f, " %s Cond ref <", flag);
      print_custring(f, entry);
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
      }
    break;

    case OP_RREF:
    c = GET2(code, 1);
    if (c == RREF_ANY)
      fprintf(f, "    Cond recurse any");
    else
      fprintf(f, "    Cond recurse %d", c);
    break;

    case OP_DNRREF:
      {
      PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
      fprintf(f, " %s Cond recurse <", flag);
      print_custring(f, entry);
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
      }
    break;

    case OP_FALSE:
    fprintf(f, "    Cond false");
    break;

    case OP_TRUE:
    fprintf(f, "    Cond true");
    break;

    case OP_STARI:
    case OP_MINSTARI:
    case OP_POSSTARI:
    case OP_PLUSI:
    case OP_MINPLUSI:
    case OP_POSPLUSI:
    case OP_QUERYI:
    case OP_MINQUERYI:
    case OP_POSQUERYI:
    flag = "/i";
    /* Fall through */
    case OP_STAR:
    case OP_MINSTAR:
    case OP_POSSTAR:
    case OP_PLUS:
    case OP_MINPLUS:
    case OP_POSPLUS:
    case OP_QUERY:
    case OP_MINQUERY:
    case OP_POSQUERY:
    case OP_TYPESTAR:
    case OP_TYPEMINSTAR:
    case OP_TYPEPOSSTAR:
    case OP_TYPEPLUS:
    case OP_TYPEMINPLUS:
    case OP_TYPEPOSPLUS:
    case OP_TYPEQUERY:
    case OP_TYPEMINQUERY:
    case OP_TYPEPOSQUERY:
    fprintf(f, " %s ", flag);

    if (*code >= OP_TYPESTAR)
      {
      if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
        {
        print_prop(f, code + 1, "", " ");
        extra = 2;
        }
      else fprintf(f, "%s", OP_names[code[1]]);
      }
    else extra = print_char(f, code+1, utf);
    fprintf(f, "%s", OP_names[*code]);
    break;

    case OP_EXACTI:
    case OP_UPTOI:
    case OP_MINUPTOI:
    case OP_POSUPTOI:
    flag = "/i";
    /* Fall through */
    case OP_EXACT:
    case OP_UPTO:
    case OP_MINUPTO:
    case OP_POSUPTO:
    fprintf(f, " %s ", flag);
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
    fprintf(f, "{");
    if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
      else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
    break;

    case OP_TYPEEXACT:
    case OP_TYPEUPTO:
    case OP_TYPEMINUPTO:
    case OP_TYPEPOSUPTO:
    if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
      {
      print_prop(f, code + IMM2_SIZE + 1, "    ", " ");
      extra = 2;
      }
    else fprintf(f, "    %s", OP_names[code[1 + IMM2_SIZE]]);
    fprintf(f, "{");
    if (*code != OP_TYPEEXACT) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
      else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
    break;

    case OP_NOTI:
    flag = "/i";
    /* Fall through */
    case OP_NOT:
    fprintf(f, " %s [^", flag);
    extra = print_char(f, code + 1, utf);
    fprintf(f, "]");
    break;

    case OP_NOTSTARI:
    case OP_NOTMINSTARI:
    case OP_NOTPOSSTARI:
    case OP_NOTPLUSI:
    case OP_NOTMINPLUSI:
    case OP_NOTPOSPLUSI:
    case OP_NOTQUERYI:
    case OP_NOTMINQUERYI:
    case OP_NOTPOSQUERYI:
    flag = "/i";
    /* Fall through */

    case OP_NOTSTAR:
    case OP_NOTMINSTAR:
    case OP_NOTPOSSTAR:
    case OP_NOTPLUS:
    case OP_NOTMINPLUS:
    case OP_NOTPOSPLUS:
    case OP_NOTQUERY:
    case OP_NOTMINQUERY:
    case OP_NOTPOSQUERY:
    fprintf(f, " %s [^", flag);
    extra = print_char(f, code + 1, utf);
    fprintf(f, "]%s", OP_names[*code]);
    break;

    case OP_NOTEXACTI:
    case OP_NOTUPTOI:
    case OP_NOTMINUPTOI:
    case OP_NOTPOSUPTOI:
    flag = "/i";
    /* Fall through */

    case OP_NOTEXACT:
    case OP_NOTUPTO:
    case OP_NOTMINUPTO:
    case OP_NOTPOSUPTO:
    fprintf(f, " %s [^", flag);
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
    fprintf(f, "]{");
    if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
    fprintf(f, "%d}", GET2(code,1));
    if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
      else
    if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
    break;

    case OP_RECURSE:
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
      else fprintf(f, "    ");
    fprintf(f, "%s", OP_names[*code]);
    break;

    case OP_REFI:
    flag = "/i";
    /* Fall through */
    case OP_REF:
    fprintf(f, " %s \\%d", flag, GET2(code,1));
    ccode = code + OP_lengths[*code];
    goto CLASS_REF_REPEAT;

    case OP_DNREFI:
    flag = "/i";
    /* Fall through */
    case OP_DNREF:
      {
      PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
      fprintf(f, " %s \\k<", flag);
      print_custring(f, entry);
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
      }
    ccode = code + OP_lengths[*code];
    goto CLASS_REF_REPEAT;

    case OP_CALLOUT:
    fprintf(f, "    %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],
      GET(code, 1), GET(code, 1 + LINK_SIZE));
    break;

    case OP_CALLOUT_STR:
    c = code[1 + 4*LINK_SIZE];
    fprintf(f, "    %s %c", OP_names[*code], c);
    extra = GET(code, 1 + 2*LINK_SIZE);
    print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);
    for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
      if (c == PRIV(callout_start_delims)[i])
        {
        c = PRIV(callout_end_delims)[i];
        break;
        }
    fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1),
      GET(code, 1 + LINK_SIZE));
    break;

    case OP_PROP:
    case OP_NOTPROP:
    print_prop(f, code, "    ", "");
    break;

    /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm
    in having this code always here, and it makes it less messy without all
    those #ifdefs. */

    case OP_CLASS:
    case OP_NCLASS:
    case OP_XCLASS:
      {
      unsigned int min, max;
      BOOL printmap;
      BOOL invertmap = FALSE;
      uint8_t *map;
      uint8_t inverted_map[32];

      fprintf(f, "    [");

      if (*code == OP_XCLASS)
        {
        extra = GET(code, 1);
        ccode = code + LINK_SIZE + 1;
        printmap = (*ccode & XCL_MAP) != 0;
        if ((*ccode & XCL_NOT) != 0)
          {
          invertmap = (*ccode & XCL_HASPROP) == 0;
          fprintf(f, "^");
          }
        ccode++;
        }
      else
        {
        printmap = TRUE;
        ccode = code + 1;
        }

      /* Print a bit map */

      if (printmap)
        {
        map = (uint8_t *)ccode;
        if (invertmap)
          {
          for (i = 0; i < 32; i++) inverted_map[i] = ~map[i];
          map = inverted_map;
          }

        for (i = 0; i < 256; i++)
          {
          if ((map[i/8] & (1 << (i&7))) != 0)
            {
            int j;
            for (j = i+1; j < 256; j++)
              if ((map[j/8] & (1 << (j&7))) == 0) break;
            if (i == '-' || i == ']') fprintf(f, "\\");
            if (PRINTABLE(i)) fprintf(f, "%c", i);
              else fprintf(f, "\\x%02x", i);
            if (--j > i)
              {
              if (j != i + 1) fprintf(f, "-");
              if (j == '-' || j == ']') fprintf(f, "\\");
              if (PRINTABLE(j)) fprintf(f, "%c", j);
                else fprintf(f, "\\x%02x", j);
              }
            i = j;
            }
          }
        ccode += 32 / sizeof(PCRE2_UCHAR);
        }

      /* For an XCLASS there is always some additional data */

      if (*code == OP_XCLASS)
        {
        PCRE2_UCHAR ch;
        while ((ch = *ccode++) != XCL_END)
          {
          BOOL not = FALSE;
          const char *notch = "";

          switch(ch)
            {
            case XCL_NOTPROP:
            not = TRUE;
            notch = "^";
            /* Fall through */

            case XCL_PROP:
              {
              unsigned int ptype = *ccode++;
              unsigned int pvalue = *ccode++;

              switch(ptype)
                {
                case PT_PXGRAPH:
                fprintf(f, "[:%sgraph:]", notch);
                break;

                case PT_PXPRINT:
                fprintf(f, "[:%sprint:]", notch);
                break;

                case PT_PXPUNCT:
                fprintf(f, "[:%spunct:]", notch);
                break;

                default:
                fprintf(f, "\\%c{%s}", (not? 'P':'p'),
                  get_ucpname(ptype, pvalue));
                break;
                }
              }
            break;

            default:
            ccode += 1 + print_char(f, ccode, utf);
            if (ch == XCL_RANGE)
              {
              fprintf(f, "-");
              ccode += 1 + print_char(f, ccode, utf);
              }
            break;
            }
          }
        }

      /* Indicate a non-UTF class which was created by negation */

      fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");

      /* Handle repeats after a class or a back reference */

      CLASS_REF_REPEAT:
      switch(*ccode)
        {
        case OP_CRSTAR:
        case OP_CRMINSTAR:
        case OP_CRPLUS:
        case OP_CRMINPLUS:
        case OP_CRQUERY:
        case OP_CRMINQUERY:
        case OP_CRPOSSTAR:
        case OP_CRPOSPLUS:
        case OP_CRPOSQUERY:
        fprintf(f, "%s", OP_names[*ccode]);
        extra += OP_lengths[*ccode];
        break;

        case OP_CRRANGE:
        case OP_CRMINRANGE:
        case OP_CRPOSRANGE:
        min = GET2(ccode,1);
        max = GET2(ccode,1 + IMM2_SIZE);
        if (max == 0) fprintf(f, "{%u,}", min);
        else fprintf(f, "{%u,%u}", min, max);
        if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
        else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");
        extra += OP_lengths[*ccode];
        break;

        /* Do nothing if it's not a repeat; this code stops picky compilers
        warning about the lack of a default code path. */

        default:
        break;
        }
      }
    break;

    case OP_MARK:
    case OP_PRUNE_ARG:
    case OP_SKIP_ARG:
    case OP_THEN_ARG:
    fprintf(f, "    %s ", OP_names[*code]);
    print_custring_bylen(f, code + 2, code[1]);
    extra += code[1];
    break;

    case OP_THEN:
    fprintf(f, "    %s", OP_names[*code]);
    break;

    case OP_CIRCM:
    case OP_DOLLM:
    flag = "/m";
    /* Fall through */

    /* Anything else is just an item with no data, but possibly a flag. */

    default:
    fprintf(f, " %s %s", flag, OP_names[*code]);
    break;
    }

  code += OP_lengths[*code] + extra;
  fprintf(f, "\n");
  }
}