// qod.cc - // // ##Copyright## // // Copyright 2000-2016 Peter Robinson (pjr@itee.uq.edu.au) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.00 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // ##Copyright## // // $Id: qod.cc,v 1.6 2005/03/08 00:35:13 qp Exp $ #include #include #include #include #include "code.h" #include "defs.h" #include "defaults.h" #include "errors.h" #include "instructions.h" #include "int.h" const char *Program = "qod"; // // Handler for out of memory via new // typedef void (*new_handler) (); new_handler set_new_handler(new_handler p) throw(); void noMoreMemory() { cerr << "No more memory available for " << Program << endl; abort(); } static void dump_instruction(istream&, wordlong&, wordlong&, char *[], const size_t); static void dump_predicate(istream&, wordlong&, char *[], const size_t); static void advance(const wordlong, wordlong&, wordlong&); static void dump_constant(const Code::ConstantSizedType, char *[], const size_t); static void dump_table_constant(const Code::ConstantSizedType, char *[], const size_t); static void dump_table_atom_arity(const Code::ConstantSizedType, const Code::NumberSizedType, char *[], const size_t); static void dump_table_label(const Code::OffsetSizedType, const wordlong); int main(int argc, char **argv) { // set the out-of-memory handler #ifdef WIN32 std::set_new_handler(noMoreMemory); #else set_new_handler(noMoreMemory); #endif if (argc != 2) { Usage("qod", "input-file"); } ifstream ifstrm(argv[1]); if (ifstrm.bad()) { FatalS(__FUNCTION__, "Couldn't open ", argv[1]); } // Initialise wordlong byte_count = 0; // Read the string table char *strings[1024]; wordlong string_count = 0; printf("% 8lx: ", byte_count); Code::AddressSizedType string_table_size = IntLoad(ifstrm); byte_count += Code::SIZE_OF_ADDRESS; printf("String table size = %ld bytes\n", string_table_size); while (string_table_size > 0) { wordlong len = 0; printf("% 8lx: ", byte_count); char *str = new char[ATOM_LENGTH]; // Read a string char c; do { if (ifstrm.bad()) { Fatal(__FUNCTION__, "Bad news from the input file"); } ifstrm.get(c); str[len] = c; len++; byte_count++; } while (c != '\0'); printf("% 4ld %s\n", string_count, str); strings[string_count] = str; string_count++; string_table_size -= len; } Code::OffsetSizedType query_block_size = IntLoad(ifstrm); if (query_block_size > 0) { wordlong size = query_block_size; cout << ' ' << endl; printf("% 8lx: ", byte_count); printf("Query block size = %ld bytes\n", query_block_size); while (size > 0) { dump_instruction(ifstrm, byte_count, size, strings, string_count); } } else { cout << "--------------------------------------------------" << endl; printf("% 8lx: ", byte_count); printf("Query block size = %ld bytes\n", query_block_size); } byte_count += Code::SIZE_OF_OFFSET; while (ifstrm.peek() != EOF) { cout << ' ' << endl; dump_predicate(ifstrm, byte_count, strings, string_count); } ifstrm.close(); exit(0); } void advance(const wordlong bytes, wordlong& byte_count, wordlong& size) { byte_count += bytes; size -= bytes; } void dump_table_constant(const Code::ConstantSizedType constant, char *strings[], const size_t string_count) { if (constant == (Code::ConstantSizedType) -1) { cout << "$default"; } else { dump_constant(constant, strings, string_count); } } void dump_table_label(const Code::OffsetSizedType label, const wordlong end_addr) { if (label == (Code::OffsetSizedType) -1) { cout << "$fail"; } else { printf("%lx=%lx", label, label + end_addr); } } void dump_table_atom_arity(const Code::ConstantSizedType atom, const Code::NumberSizedType arity, char *strings[], const size_t string_count) { if (atom == (Code::ConstantSizedType) -1 && arity == 0) { cout << "$default"; } else { Cell cell; cell.set(atom); if (cell.isAtom()) { const wordlong atom_loc = cell.restOfAtomic(); printf("%ld=%s/%ld", atom_loc, strings[atom_loc], arity); } else { printf("%lx=?atom?/%ld", atom, arity); } } } void dump_constant(const Code::ConstantSizedType constant, char *strings[], const size_t string_count) { printf("%lx=", constant); Cell cell; cell.set(constant); if (cell.isShort()) { printf("%ld short", cell.shortOf()); } else if (cell.isAtom()) { const wordlong atom_loc = cell.restOfAtomic(); if (atom_loc < string_count) { printf("%ld '%s'", atom_loc, strings[atom_loc]); } else { printf("%lx ?atom?", atom_loc); } } else { printf("%lx ?constant?", constant); } } void dump_instruction(istream& istrm, wordlong& byte_count, wordlong& size, char *strings[], const size_t string_count) { const wordlong instr_start = byte_count; printf("% 8lx: ", byte_count); const Code::InstructionSizedType instruction = IntLoad(istrm); advance(Code::SIZE_OF_INSTRUCTION, byte_count, size); if (instruction == 0 || instruction > UNIFY_Y_REF) { Fatal(__FUNCTION, "Bad instruction: "); } printf("%s[%s]", opnames[instruction], operands[instruction]); const char *args = operands[instruction]; const size_t num_args = strlen(args); Code::TableSizeSizedType table_size = 0; if (num_args > 0) { cout << '('; for (size_t i = 0; i < num_args; i++) { switch (args[i]) { case 'c': { const Code::ConstantSizedType constant = IntLoad(istrm); advance(Code::SIZE_OF_CONSTANT, byte_count, size); dump_constant(constant, strings, string_count); } break; case 'n': { const Code::NumberSizedType number = IntLoad(istrm); advance(Code::SIZE_OF_NUMBER, byte_count, size); printf("%ld", number); } break; case 'o': { size_t offset_adjust = 0; switch (instruction) { case TRY: case TRY_ME_ELSE: offset_adjust = Code::SIZE_OF_INSTRUCTION + Code::SIZE_OF_NUMBER + Code::SIZE_OF_OFFSET; break; case RETRY: case RETRY_ME_ELSE: offset_adjust = Code::SIZE_OF_INSTRUCTION + Code::SIZE_OF_OFFSET; break; case TRUST: offset_adjust = Code::SIZE_OF_INSTRUCTION + Code::SIZE_OF_OFFSET; break; } const Code::OffsetSizedType offset = IntLoad(istrm); advance(Code::SIZE_OF_OFFSET, byte_count, size); printf("%lx %lx", offset, offset + instr_start + offset_adjust); } break; case 'p': { const Code::PredSizedType predicate = IntLoad(istrm); advance(Code::SIZE_OF_PRED, byte_count, size); printf("%ld=%s", predicate, strings[predicate]); } break; case 'r': { const Code::RegisterSizedType reg = IntLoad(istrm); advance(Code::SIZE_OF_REGISTER, byte_count, size); printf("%ld", reg); } break; case 't': { table_size = IntLoad(istrm); advance(Code::SIZE_OF_TABLE_SIZE, byte_count, size); printf("%ld", table_size); } break; default: Fatal(__FUNCTION__, "Uncaught operand case "); break; } if (i < num_args - 1) { cout << ", "; } } cout << ')'; } const wordlong instr_size = byte_count - instr_start; const wordlong instr_end = byte_count; printf(" (%ld bytes)", instr_size); if (instr_size != opsizes[instruction]) { Fatal(__FUNCTION__, "Wrong instruction size"); } if (instruction == SWITCH_ON_TERM || instruction == SWITCH_ON_CONSTANT || instruction == SWITCH_ON_STRUCTURE || instruction == SWITCH_ON_QUANTIFIER) { switch (instruction) { case SWITCH_ON_TERM: { const char *branch = "VOLSQC"; const wordlong table_bytes = 6 * Code::SIZE_OF_OFFSET; const wordlong table_end = instr_end + table_bytes; cout << endl; printf("% 8lx: ", byte_count); for (wordlong i = 0; i < 6; i++) { const Code::OffsetSizedType label = IntLoad(istrm); advance(Code::SIZE_OF_OFFSET, byte_count, size); cout << branch[i] << " "; dump_table_label(label, table_end); if (i < 5) { cout << ", "; } } const wordlong bytes = byte_count - instr_end; printf(" (%ld bytes)", bytes); if (bytes != table_bytes) { Fatal(__FUNCTION__, "Table size: computed=%ld != actual=%ld", table_bytes, bytes); } } break; case SWITCH_ON_CONSTANT: { const wordlong table_bytes = table_size * (Code::SIZE_OF_CONSTANT + Code::SIZE_OF_OFFSET); for (size_t entry = 0; entry < table_size; entry++) { if (entry % 4 == 0) { cout << endl; printf("% 8lx: % 4ld ", byte_count, entry); } const Code::ConstantSizedType constant = IntLoad(istrm); advance(Code::SIZE_OF_CONSTANT, byte_count, size); const Code::OffsetSizedType label = IntLoad(istrm); advance(Code::SIZE_OF_OFFSET, byte_count, size); dump_table_constant(constant, strings, string_count); cout << ":"; dump_table_label(label, instr_end); if (entry + 1 < table_size) { cout << ", "; } } const wordlong bytes = byte_count - instr_end; printf(" (%ld bytes)", bytes); if (bytes != table_bytes) { Fatal(__FUNCTION__, "Table size: computed=%ld != actual=%ld", table_bytes, bytes); } } break; case SWITCH_ON_STRUCTURE: { const wordlong table_bytes = table_size * (Code::SIZE_OF_CONSTANT + Code::SIZE_OF_NUMBER + Code::SIZE_OF_OFFSET); for (wordlong entry = 0; entry < table_size; entry++) { if (entry % 4 == 0) { cout << endl; printf("% 8lx: % 4ld ", byte_count, entry); } const Code::ConstantSizedType atom = IntLoad(istrm); advance(Code::SIZE_OF_CONSTANT, byte_count, size); const Code::NumberSizedType arity = IntLoad(istrm); advance(Code::SIZE_OF_NUMBER, byte_count, size); const Code::OffsetSizedType label = IntLoad(istrm); advance(Code::SIZE_OF_OFFSET, byte_count, size); dump_table_atom_arity(atom, arity, strings, string_count); cout << ":"; dump_table_label(label, instr_end); if (entry + 1 < table_size) { cout << ", "; } } const wordlong bytes = byte_count - instr_end; printf(" (%ld bytes)", bytes); if (bytes != table_bytes) { Fatal(__FUNCTION__, "Table size: computed=%ld != actual=%ld", table_bytes, bytes); } } break; case SWITCH_ON_QUANTIFIER: { const wordlong table_bytes = table_size * (Code::SIZE_OF_CONSTANT + Code::SIZE_OF_OFFSET); for (wordlong entry = 0; entry < table_size; entry++) { if (entry % 4 == 0) { cout << endl; printf("% 8lx: % 4ld ", byte_count, entry); } const Code::ConstantSizedType atom = IntLoad(istrm); advance(Code::SIZE_OF_CONSTANT, byte_count, size); const Code::OffsetSizedType label = IntLoad(istrm); advance(Code::SIZE_OF_OFFSET, byte_count, size); printf("%ld:", atom); dump_table_label(label, instr_end); if (entry + 1 < table_size) { cout << ", "; } } const wordlong bytes = byte_count - instr_end; printf(" (%ld bytes)", bytes); if (bytes != table_bytes) { Fatal(__FUNCTION__, "Table size: computed=%ld != actual=%ld", table_bytes, bytes); } } break; } } cout << endl; } void dump_predicate(istream& istrm, wordlong& byte_count, char *strings[], const size_t string_count) { printf("% 8lx: ", byte_count); const Code::AddressSizedType string_num = IntLoad(istrm); byte_count += Code::SIZE_OF_ADDRESS; const Code::NumberSizedType arity = IntLoad(istrm); byte_count += Code::SIZE_OF_NUMBER; const Code::OffsetSizedType pred_size = IntLoad(istrm); wordlong bytes = pred_size; byte_count += Code::SIZE_OF_OFFSET; const wordlong pred_start = byte_count; printf("%ld=%s/%ld (%ld bytes, next pred=%lx)\n", string_num, strings[string_num], arity, pred_size, pred_start + pred_size); while (bytes > 0) { dump_instruction(istrm, byte_count, bytes, strings, string_count); } const wordlong size = byte_count - pred_start; if (pred_size != size) { Fatal(__FUNCTION__, "Predicate size: computed=%ld != actual=%ld", pred_size, size); } }