This is debug.c in view mode; [Download] [Up]
/* * PCN Abstract Machine Emulator * Authors: Steve Tuecke and Ian Foster * Argonne National Laboratory * * Please see the DISCLAIMER file in the top level directory of the * distribution regarding the provisions under which this software * is distributed. * * debug.c - Various debug routines that are used throughout the emulator */ #include "pcn.h" static void print_term3(file, term, n, deref) FILE *file; cell_t *term; int n; bool_t deref; { data_header_t *dh, *real_dh; int i; cell_t *cp1; u_int_t tag, size; if (deref) { Dereference((data_header_t *), term, dh); } else { dh = (data_header_t *) term; } cp1 = ((cell_t *) dh) + 1; /* * If this is called during a garbage collection (i.e., by * the orphaned process printer or other debugging code), * then there may be reversed pointers on the heap. * So follow the reversed pointers to find the real data * header cell, and extract the necessary information out of it. */ real_dh = dh; while(IsReversed(real_dh)) real_dh = (data_header_t *) ClearReversed(*((cell_t **)real_dh)); tag = real_dh->tag; size = real_dh->size; switch(tag) { case TUPLE_TAG: if (n >= _p_print_tuple_depth) { fprintf(file, "{...}"); break; } if (size == 0) { fprintf(file, "[]"); } else { if (_p_print_tuple_width <= 0) { fprintf(file, "{...}"); } else { fprintf(file, "{"); #ifdef DEBUG fflush(file); #endif /* DEBUG */ for (i = 0; i < _p_print_tuple_width && i < size; i++) { if (i != 0) { fprintf(file, ", "); #ifdef DEBUG fflush(file); #endif /* DEBUG */ } print_term3(file, cp1++, n+1, TRUE); } if (i < size) fprintf(file, ", ..."); fprintf(file, "}"); } } break; #ifdef STREAMS case STREAM_TAG: #endif case INT_TAG: case DOUBLE_TAG: if (size == 0) { fprintf(file, "***ERROR: %s with size 0***", #ifdef STREAMS (tag == INT_TAG ? "INT_TAG" : (tag == DOUBLE_TAG ? "DOUBLE_TAG" : (tag == STREAM_TAG ? "STREAM_TAG" : "UNKNOWN_TAG"))) #else (tag == INT_TAG ? "INT_TAG" : (tag == DOUBLE_TAG ? "DOUBLE_TAG" : "UNKNOWN_TAG")) #endif ); } else if (size == 1) { if (tag == INT_TAG) fprintf(file, "%ld", (long) *((int_t *) (cp1))); else if (tag == DOUBLE_TAG) fprintf(file, "%.16f", *((double_t *) cp1)); #ifdef STREAMS else /* tag == STREAM_TAG */ { stream_t *streamp = (stream_t *) cp1; if (streamp->send) fprintf(file, "%_SS%ld", (long) streamp->id); else fprintf(file, "%_RS%ld", (long) streamp->id); } #endif /* STREAMS */ } else /* size > 1 */ { if (_p_print_array_size <= 0) fprintf(file, "(...)"); else { fprintf(file, "("); #ifdef DEBUG fflush(file); #endif /* DEBUG */ for (i = 0; i < _p_print_array_size && i < size; i++) { if (i != 0) { fprintf(file, ", "); #ifdef DEBUG fflush(file); #endif /* DEBUG */ } if (tag == INT_TAG) { fprintf(file, "%ld", (long) *((int_t *) (cp1))); cp1++; } else if (tag == DOUBLE_TAG) { fprintf(file, "%.16f", *((double_t *) cp1)); cp1 += CELLS_PER_DOUBLE; } #ifdef STREAMS else /* tag == STREAM_TAG */ { stream_t *streamp = (stream_t *) cp1; if (streamp->send) fprintf(file, "%_SS%ld", (long) streamp->id); else fprintf(file, "%_RS%ld", (long) streamp->id); } #endif /* STREAMS */ #ifdef DEBUG fflush(file); #endif /* DEBUG */ } if (i < size) fprintf(file, ", ..."); fprintf(file, ")"); } } break; case STRING_TAG: fprintf(file, "%s", (char *) (cp1)); break; case UNDEF_TAG: fprintf(file, "_U%s%lx", (SuspensionsAt(real_dh) ? "*" : ""), (unsigned long) dh); break; case RREF_TAG: fprintf(file, "_R%s_w%lu_l%lu_n%lu", (SuspensionsAt(real_dh) ? "*" : ""), (unsigned long) ((rref_t *) dh)->weight, (unsigned long) ((rref_t *) dh)->location, (unsigned long) ((rref_t *) dh)->node); break; case PROC_RECORD_TAG: fprintf(file, "_P%lx", (unsigned long) dh); break; case VALUE_NOTE_TAG: fprintf(file, "_V%lx_l%lu_n%lu", (unsigned long) dh, (unsigned long) ((value_note_t *) dh)->location, (unsigned long) ((value_note_t *) dh)->node); break; default: fprintf(file, "***ERROR: Undefine tag***"); break; } #ifdef DEBUG fflush(file); #endif /* DEBUG */ } /* print_term3() */ void _p_print_term(file, term) FILE *file; cell_t *term; { print_term3(file, term, 0, TRUE); } /* _p_print_term() */ #ifdef DEBUG /* * _p_print_proc_record() * * Print the string 'c' followed by the 'proc_record'. */ void _p_print_proc_record(c, proc_record) char *c; proc_record_t *proc_record; { int_t i, a; cell_t *cp; proc_header_t *proc_header; if (proc_record == (proc_record_t *) NULL) { fprintf(_p_stdout, "(%lu,%lu) %s _p_print_proc_record called with a NULL process structure pointer", (unsigned long) _p_my_id, (unsigned long) _p_reduction, c); return; } fprintf(_p_stdout, "(%lu,%lu) %s", (unsigned long) _p_my_id, (unsigned long) _p_reduction, c); proc_header = proc_record->proc; if (proc_header != (proc_header_t *) NULL) /* process */ { a = proc_header->arity; fprintf(_p_stdout, "%s:%s(", proc_header->module_name, proc_header->proc_name); cp = (cell_t *) proc_record->args; for (i = 0 ; i < a; i++) { _p_print_term(_p_stdout, cp++); if (i != a-1) fprintf(_p_stdout, ", "); } fprintf(_p_stdout, ")\n"); } else /* value note */ { fprintf(_p_stdout, "value note location %lu, node %lu\n", (unsigned long) ((value_note_t *) proc_record)->location, (unsigned long) ((value_note_t *) proc_record)->node); } fflush(_p_stdout); } /* _p_print_proc_record() */ /* * _p_print_proc() * * Print the string 'c' followed by the procedure 'proc_header'. * If 'print_args' is TRUE then print the arguments to the * program, as found in the first N registers. */ void _p_print_proc(c, proc_header, print_args) char *c; proc_header_t *proc_header; bool_t print_args; { u_int_t i, a; fprintf(_p_stdout, "(%lu,%lu) %s", (unsigned long) _p_my_id, (unsigned long) _p_reduction, c); a = proc_header->arity; fprintf(_p_stdout, "%s:%s/%lu", proc_header->module_name, proc_header->proc_name, (unsigned long) a); if (print_args) { fprintf(_p_stdout, "("); for (i = 0 ; i < a; i++) { _p_print_term(_p_stdout, _p_a_reg[i]); if (i != a-1) fprintf(_p_stdout, ", "); } fprintf(_p_stdout, ") : (_p_heap_ptr=0x%lx)\n", (unsigned long) _p_heap_ptr); } else fprintf(_p_stdout, "\n"); fflush(_p_stdout); } /* _p_print_proc() */ #ifdef STREAMS static void print_stream_from_registers(stream_reg, index_reg) u_int_t stream_reg, index_reg; { stream_t *streamp = _p_get_stream_record(_p_a_reg[stream_reg], _p_a_reg[index_reg]); if (streamp->send) fprintf(_p_stdout, "%_SS%ld(", (long) streamp->id); else fprintf(_p_stdout, "%_RS%ld(", (long) streamp->id); fprintf(_p_stdout, "_p_a_reg[%ld]=", (long) stream_reg); _p_print_term(_p_stdout, _p_a_reg[stream_reg]); fprintf(_p_stdout, ",_p_a_reg[%ld]=", (long) index_reg); _p_print_term(_p_stdout, _p_a_reg[index_reg]); fprintf(_p_stdout, ")\n"); } /* print_stream_from_registers() */ #endif /* STREAMS */ void _p_print_instruction(instr) instruction_t *instr; { proc_header_t *proc_header; switch(instr->I_OPCODE) { case I_FORK: proc_header = (proc_header_t *) instr->I_FORK_PROC; fprintf(_p_stdout, " 0x%lx: %s(%s:%s (ptr=0x%lx),%lu)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], proc_header->module_name, proc_header->proc_name, (unsigned long) instr->I_FORK_PROC, (unsigned long) instr->I_FORK_ARITY); break; case I_RECURSE: proc_header = (proc_header_t *) instr->I_RECURSE_PROC; fprintf(_p_stdout, " 0x%lx: %s(%s:%s (ptr=0x%lx),%lu,counter_ptr=0x%lx)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], proc_header->module_name, proc_header->proc_name, (unsigned long) instr->I_RECURSE_PROC, (unsigned long) instr->I_RECURSE_ARITY, #ifdef GAUGE (unsigned long) instr->I_RECURSE_COUNTER #else 0 #endif ); break; case I_HALT: fprintf(_p_stdout, " 0x%lx: %s(counter_ptr=0x%lx)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], #ifdef GAUGE (unsigned long) instr->I_HALT_COUNTER #else 0 #endif ); break; case I_DEFAULT: fprintf(_p_stdout, " 0x%lx: %s(%lu, counter_ptr=0x%lx)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_DEFAULT_ARITY, #ifdef GAUGE (unsigned long) instr->I_DEFAULT_COUNTER #else 0 #endif ); break; case I_TRY: fprintf(_p_stdout, " 0x%lx: %s(0x%lx)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_TRY_LOCATION); break; case I_BUILD_STATIC: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu],%s(%lu),%lu)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_BUILD_STATIC_DEST_R, _p_tag_name[instr->I_BUILD_STATIC_TAG], (unsigned long) instr->I_BUILD_STATIC_TAG, (unsigned long) instr->I_BUILD_STATIC_SIZE); break; case I_BUILD_DYNAMIC: fprintf(_p_stdout, " 0x%lx: %s(%s(%lu),_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], _p_tag_name[instr->I_BUILD_DYNAMIC_TAG], (unsigned long) instr->I_BUILD_DYNAMIC_TAG, (unsigned long) instr->I_BUILD_DYNAMIC_SIZE_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_BUILD_DYNAMIC_SIZE_R]); fprintf(_p_stdout, ",_p_a_reg[%lu])\n", (unsigned long) instr->I_BUILD_DYNAMIC_DEST_R); break; case I_BUILD_DEF: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu])\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_BUILD_DEF_DEST_R); break; case I_PUT_DATA: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu],%s(%lu),", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_PUT_DATA_DEST_R, _p_tag_name[instr->I_PUT_DATA_TAG], (unsigned long) instr->I_PUT_DATA_TAG); print_term3(_p_stdout, ((cell_t *) (instr->I_PUT_DATA_PTR) + 1), 1, FALSE); fprintf(_p_stdout, ")\n"); break; case I_COPY: case I_LENGTH: case I_COPY_MUT: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->t1.op0.b1); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b1]); fprintf(_p_stdout, ",_p_a_reg[%lu])\n", (unsigned long) instr->t1.op0.b2); break; case I_GET_TUPLE: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_GET_TUPLE_SRC_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_GET_TUPLE_SRC_R]); fprintf(_p_stdout, ",%lu,_p_a_reg[%lu])\n", (unsigned long) instr->I_GET_TUPLE_ARITY, (unsigned long) instr->I_GET_TUPLE_DEST_R); break; case I_TYPE: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_TYPE_SRC_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_TYPE_SRC_R]); fprintf(_p_stdout, ",%s(%lu))\n", _p_tag_name[instr->I_TYPE_TAG], (unsigned long) instr->I_TYPE_TAG); break; case I_LE: case I_LT: case I_EQUAL: case I_NEQ: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->t1.op0.b1); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b1]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->t1.op0.b2); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b2]); fprintf(_p_stdout, ")\n"); break; case I_PUT_VALUE: case I_DATA: case I_UNKNOWN: case I_PUT_FOREIGN: case I_PRINT_TERM: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->t1.op0.b1); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b1]); fprintf(_p_stdout, ")\n"); break; case I_DEFINE: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu],_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_DEFINE_TO_R, (unsigned long) instr->I_DEFINE_FROM_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_DEFINE_FROM_R]); fprintf(_p_stdout, ")\n"); break; case I_GET_ELEMENT: case I_ADD: case I_SUB: case I_MUL: case I_DIV: case I_MOD: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->t1.op0.b1); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b1]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->t1.op0.b2); _p_print_term(_p_stdout, _p_a_reg[instr->t1.op0.b2]); fprintf(_p_stdout, ",_p_a_reg[%lu])\n", (unsigned long) instr->t1.op0.b3); break; case I_RUN: fprintf(_p_stdout, " 0x%lx: %s(vt_tuple(_p_a_reg[%lu])=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_RUN_VT_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_RUN_VT_R]); fprintf(_p_stdout, ",target(_p_a_reg[%lu])=", (unsigned long) instr->I_RUN_TARGET_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_RUN_TARGET_R]); fprintf(_p_stdout, ",caller_mod(_p_a_reg[%lu])=", (unsigned long) instr->I_RUN_MOD_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_RUN_MOD_R]); fprintf(_p_stdout, ",caller_proc(_p_a_reg[%lu])=", (unsigned long) instr->I_RUN_PROC_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_RUN_PROC_R]); fprintf(_p_stdout, ",sync_var(_p_a_reg[%lu])=", (unsigned long) instr->I_RUN_SYNC_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_RUN_SYNC_R]); fprintf(_p_stdout, ")\n"); break; case I_PUT_ELEMENT: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu]=", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_PUT_ELEMENT_DINDEX_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_PUT_ELEMENT_DINDEX_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_PUT_ELEMENT_DEST_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_PUT_ELEMENT_DEST_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_PUT_ELEMENT_SRC_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_PUT_ELEMENT_SRC_R]); fprintf(_p_stdout, ")\n"); break; case I_CALL_FOREIGN: fprintf(_p_stdout, " 0x%lx: %s(%s,%lu)\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], _p_foreign_lookup((u_int_t) instr->I_CALL_FOREIGN_FOR), (unsigned long) instr->I_CALL_FOREIGN_N_ARGS); break; case I_EXIT: fprintf(_p_stdout, " 0x%lx: %s()\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE]); break; #ifdef STREAMS case I_INIT_SEND: case I_INIT_RECV: fprintf(_p_stdout, " 0x%lx: %s(_p_a_reg[%lu],", (unsigned long) instr, _p_instr_names[instr->I_OPCODE], (unsigned long) instr->I_INIT_SEND_CON_ARRAY_R); print_stream_from_registers(instr->I_INIT_SEND_STREAM_R, instr->I_INIT_SEND_SINDEX_R); fprintf(_p_stdout, ")\n"); break; case I_CLOSE_STREAM: fprintf(_p_stdout, " 0x%lx: %s(", (unsigned long) instr, _p_instr_names[instr->I_OPCODE]); print_stream_from_registers(instr->I_CLOSE_STREAM_STREAM_R, instr->I_CLOSE_STREAM_SINDEX_R); fprintf(_p_stdout, ")\n"); break; case I_STREAM_SEND: fprintf(_p_stdout, " 0x%lx: %s(", (unsigned long) instr, _p_instr_names[instr->I_OPCODE]); print_stream_from_registers(instr->I_STREAM_SEND_STREAM_R, instr->I_STREAM_SEND_SINDEX_R); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_SEND_ARRAY_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_SEND_ARRAY_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_SEND_OFFSET_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_SEND_OFFSET_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_SEND_SIZE_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_SEND_SIZE_R]); fprintf(_p_stdout, ")\n"); break; case I_STREAM_RECV: fprintf(_p_stdout, " 0x%lx: %s(", (unsigned long) instr, _p_instr_names[instr->I_OPCODE]); print_stream_from_registers(instr->I_STREAM_RECV_STREAM_R, instr->I_STREAM_RECV_SINDEX_R); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_RECV_ARRAY_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_RECV_ARRAY_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_RECV_OFFSET_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_RECV_OFFSET_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_RECV_SIZE_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_RECV_SIZE_R]); fprintf(_p_stdout, ",_p_a_reg[%lu]=", (unsigned long) instr->I_STREAM_RECV_STATUS_R); _p_print_term(_p_stdout, _p_a_reg[instr->I_STREAM_RECV_STATUS_R]); fprintf(_p_stdout, ")\n"); break; #else /* STREAMS */ case I_INIT_SEND: case I_INIT_RECV: case I_CLOSE_STREAM: case I_STREAM_SEND: case I_STREAM_RECV: fprintf(_p_stdout, " 0x%lx: %s(...) -- Not yet implemented\n", (unsigned long) instr, _p_instr_names[instr->I_OPCODE]); break; #endif /* STREAMS */ default: fprintf(_p_stdout, " 0x%lx: Illegal instruction (%lu,%lu,%lu,%lu:%lu)\n", (unsigned long) instr, (unsigned long) instr->t1.op0.b0, (unsigned long) instr->t1.op0.b1, (unsigned long) instr->t1.op0.b2, (unsigned long) instr->t1.op0.b3, (unsigned long) instr->t1.p1); break; } fflush(_p_stdout); } void d_print_term(cp) cell_t *cp; { _p_print_term(stdout, cp); fprintf(stdout, "\n"); fflush(stdout); } void d_print_cell(cp) data_header_t *cp; { printf("Tag=%lu(%s), Size=%lu, Mark=%lu\n", (unsigned long) cp->tag, _p_tag_name[cp->tag], (unsigned long) cp->size, (unsigned long) cp->mark); if (IsRef(cp)) printf("\tRef ptr=0x%lx\n", (unsigned long) *((int_t *) cp)); else if (IsUndef(cp) || IsRref(cp)) printf("\tSusp offset=0x%lx, Susp address=%lx\n", (unsigned long) ((data_header_t *) cp)->size, (unsigned long) SuspendedProcs(cp)); fflush(stdout); } void d_print_bytes(cp) cell_t *cp; { printf("Bytes = 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", (unsigned long) *((char *) cp), (unsigned long) *(((char *) cp) + 1), (unsigned long) *(((char *) cp) + 2), (unsigned long) *(((char *) cp) + 3)); fflush(stdout); } void d_print_proc_header(proc_header) proc_header_t *proc_header; { printf("%s:%s(): arity=%lu, code=0x%lx\n", proc_header->module_name, proc_header->proc_name, (unsigned long) proc_header->arity, (unsigned long) proc_header->code); #ifdef GAUGE printf("\tn_counters=%lu(0x%lx), n_timers=%lu(0x%lx)\n", (unsigned long) proc_header->n_counters, (unsigned long) proc_header->counters, (unsigned long) proc_header->n_timers, (unsigned long) proc_header->timers); #endif /* GAUGE */ #ifdef PDB printf("\tdebugable=%lu, debug=%lu, break_num=%ld\n", (unsigned long) proc_header->debugable, (unsigned long) proc_header->debug, (long) proc_header->break_num); #endif /* PDB */ } void d_print_proc_record(proc_record) proc_record_t *proc_record; { _p_print_proc_record("", proc_record); } #endif /* DEBUG */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.