[PDD] Add docs for the Parrot_PMC_push_* and Parrot_PMC_pop_* functions
[parrot.git] / examples / tools / pbc_checker.cpp
blobf8af20d5d127acf76b2f9a718fba90b7d53c5b8b
1 /*
2 * Copyright (C) 2009, Parrot Foundation.
3 * $Id$
4 */
6 // pbc_checker.cpp
7 // A multiplatform checker for pbc files
9 #include <iostream>
10 #include <fstream>
11 #include <iomanip>
12 #include <string>
13 #include <vector>
14 #include <algorithm>
15 #include <functional>
16 #include <stdexcept>
18 // Get most used symbols from std namespace
19 using std::cout;
20 using std::cerr;
21 using std::ifstream;
22 using std::string;
23 using std::hex;
24 using std::dec;
25 using std::setw;
26 using std::setfill;
27 using std::runtime_error;
29 //**********************************************************************
31 // Type used to read parrot opcodes
32 // You can use unsigned long here if your compiler does not support
33 // long long, but in that case the results might not be accurate.
35 typedef unsigned long long opcode;
37 // Constants used in pbc and his descriptions
39 const char unknown[] = "Unknown";
41 const unsigned char
42 ByteOrderLE = 0,
43 ByteOrderBE = 1;
45 const char * desc_byte_order(unsigned char c)
47 switch(c) {
48 case ByteOrderLE: return "Little endian";
49 case ByteOrderBE: return "Big endian";
50 default: return unknown;
54 const unsigned char
55 FpEncodingIEEE_754_8 = 0,
56 FpEncodingIEEE_i386_12 = 1,
57 FpEncodingIEEE_754_16 = 2;
59 const char * desc_fp_encoding(unsigned char c)
61 switch(c) {
62 case FpEncodingIEEE_754_8: return "IEEE 754 8 byte double";
63 case FpEncodingIEEE_i386_12: return "i386 little endian 12 byte long double";
64 case FpEncodingIEEE_754_16: return "IEEE 754 16 byte long double";
65 default: return unknown;
69 const char * desc_uuid_type(unsigned char c)
71 switch(c) {
72 case 0: return "none";
73 case 1: return "MD5";
74 default: return unknown;
78 const opcode
79 SegmentTypeDirectory = 0x00,
80 SegmentTypeDefault = 0x01,
81 SegmentTypeFixup = 0x02,
82 SegmentTypeConstantTable = 0x03,
83 SegmentTypeBytecode = 0x04,
84 SegmentTypePIRDebug = 0x05,
85 SegmentTypeAnnotations = 0x06,
86 SegmentTypePICData = 0x07,
87 SegmentTypeDependencies = 0x08;
89 const char * desc_segment_type(opcode t)
91 switch(t) {
92 case SegmentTypeDirectory: return "Directory";
93 case SegmentTypeDefault: return "Default";
94 case SegmentTypeFixup: return "Fixup";
95 case SegmentTypeConstantTable: return "Constant table";
96 case SegmentTypeBytecode: return "Bytecode";
97 case SegmentTypePIRDebug: return "PIR Debug";
98 case SegmentTypeAnnotations: return "Annotations";
99 case SegmentTypePICData: return "PIC Data";
100 case SegmentTypeDependencies: return "Dependencies";
101 default: return unknown;
105 const opcode
106 ConstantTypeNone = 0x00,
107 ConstantTypeNumber = 0x6E,
108 ConstantTypeString = 0x73,
109 ConstantTypePMC = 0x70,
110 ConstantTypeKey = 0x6B;
112 const char * desc_constant_type(opcode t)
114 switch(t) {
115 case ConstantTypeNone: return "None";
116 case ConstantTypeNumber: return "Number";
117 case ConstantTypeString: return "String";
118 case ConstantTypePMC: return "PMC";
119 case ConstantTypeKey: return "Key";
120 default: return unknown;
124 const opcode
125 KeyIntegerRegister = 0x00,
126 KeyStringRegister = 0x01,
127 KeyPMCRegister = 0x02,
128 KeyNumberRegister = 0x03,
129 KeyIntegerConstant = 0x10,
130 KeyStringConstant = 0x11,
131 KeyPMCConstant = 0x12,
132 KeyNumberConstant = 0x13;
134 const char * desc_key_type(opcode t)
136 switch (t) {
137 case KeyIntegerRegister: return "Integer register";
138 case KeyStringRegister: return "String register";
139 case KeyPMCRegister: return "PMC register";
140 case KeyNumberRegister: return "Number register";
141 case KeyIntegerConstant: return "Integer constant";
142 case KeyStringConstant: return "String constant";
143 case KeyPMCConstant: return "PMC constant";
144 case KeyNumberConstant: return "Number constant";
145 default: return unknown;
149 const opcode
150 AnnotationTypeInteger = 0x00,
151 AnnotationTypeString = 0x01,
152 AnnotationTypeNumber = 0x02,
153 AnnotationTypePMC = 0x03;
155 const char * desc_annotation_type(opcode t)
157 switch(t) {
158 case AnnotationTypeInteger: return "Integer";
159 case AnnotationTypeString: return "String";
160 case AnnotationTypeNumber: return "Number";
161 case AnnotationTypePMC: return "PMC";
162 default: return unknown;
166 //**********************************************************************
168 class ReadError : public runtime_error
170 public:
171 ReadError(const string &msg);
174 ReadError::ReadError(const string &msg) :
175 runtime_error("Error reading " + msg)
179 //**********************************************************************
181 void signature(ifstream &pbcfile)
183 static const char pbc_signature [] = {
184 0xFE, 0x50, 0x42, 0x43, 0x0D, 0x0A, 0x1A, 0x0A
186 char signature [sizeof (pbc_signature)];
187 pbcfile.read(signature, sizeof (signature));
188 if (pbcfile.gcount() != sizeof (signature))
189 throw ReadError("pbc signature");
190 if (! std::equal(pbc_signature, pbc_signature + sizeof(pbc_signature),
191 signature))
192 throw runtime_error("Invalid pbc signature");
195 //**********************************************************************
197 // Emit a open tag in the constructor
198 // and his closing in the destructor.
200 class TagEmit
202 public:
203 TagEmit(const string & name_n, std::ostream &os_n);
204 ~TagEmit();
205 private:
206 string name;
207 std::ostream &os;
210 TagEmit::TagEmit(const string & name_n, std::ostream &os_n) :
211 name(name_n), os(os_n)
213 os << '<' << name << ">\n";
216 TagEmit::~TagEmit()
218 os << "</" << name << ">\n";
221 //**********************************************************************
223 class DirEntry
225 public:
226 DirEntry(string name_n, opcode type_n,
227 opcode offset_n, opcode length_n);
228 string getName() const;
229 opcode getType() const;
230 opcode getOffset() const;
231 opcode getLength() const;
232 private:
233 string name;
234 opcode type;
235 opcode offset;
236 opcode length;
239 DirEntry::DirEntry(string name_n, opcode type_n,
240 opcode offset_n, opcode length_n) :
241 name(name_n),
242 type(type_n),
243 offset(offset_n),
244 length(length_n)
248 string DirEntry::getName() const
250 return name;
253 opcode DirEntry::getType() const
255 return type;
258 opcode DirEntry::getOffset() const
260 return offset;
263 opcode DirEntry::getLength() const
265 return length;
268 bool operator < (const DirEntry & de1, const DirEntry & de2)
270 return de1.getOffset() < de2.getOffset();
273 //**********************************************************************
275 // Check that segments does not overlap
277 void check_overlap(const std::vector<DirEntry> & directory)
279 unsigned int entries = directory.size();
280 for (unsigned int i= 0; i < entries; ++i)
282 opcode offset = directory[i].getOffset();
283 opcode length = directory[i].getLength();
284 opcode after = offset + length;
285 for (unsigned int j= i + 1; j < entries; ++j) {
286 opcode offset2 = directory[j].getOffset();
287 if (offset2 >= offset && offset2 < after)
288 throw runtime_error("overlap");
289 opcode after2 = offset2 + directory[j].getLength();
290 if (offset >= offset2 && offset < after2)
291 throw runtime_error("overlap");
296 //**********************************************************************
298 class PbcFile
300 public:
301 PbcFile();
302 void read(const char *filename);
303 void read_header(ifstream &pbcfile);
304 void check_directory_format(ifstream &pbcfile);
305 void read_directory(ifstream &pbcfile);
306 void dump_segment(const DirEntry & entry, ifstream &pbcfile);
307 void dump_segment_default(ifstream &pbcfile);
308 void dump_segment_fixup(ifstream &pbcfile);
309 void dump_segment_constant(ifstream &pbcfile);
310 void dump_segment_bytecode(ifstream &pbcfile);
311 void dump_segment_pir_debug(ifstream &pbcfile);
312 void dump_segment_annotations(ifstream &pbcfile);
313 void dump_segment_pic_data(ifstream &pbcfile);
314 void dump_segment_dependencies(ifstream &pbcfile);
315 void dump_constant_string(ifstream &pbcfile);
316 void dump_constant_number(ifstream &pbcfile);
317 void dump_constant_key(ifstream &pbcfile);
318 void dump_bytes_hex(ifstream &pbcfile, opcode length);
319 string read_cstring(ifstream &pbcfile);
320 opcode read_opcode(ifstream &pbcfile);
321 private:
322 unsigned int opcode_size;
323 unsigned int pbc_version;
325 unsigned char byte_order;
326 unsigned char fp_encoding;
328 std::vector<DirEntry> directory;
331 PbcFile::PbcFile()
333 opcode_size = 0;
336 void PbcFile::read(const char *filename)
338 ifstream pbcfile(filename);
339 if (! pbcfile.is_open())
340 throw runtime_error("Can't open file");
342 TagEmit filetag("PbcFile", cout);
344 read_header(pbcfile);
346 check_directory_format(pbcfile);
347 read_directory(pbcfile);
348 check_overlap(directory);
350 std::sort(directory.begin(), directory.end());
352 TagEmit tag("Segments", cout);
353 for (size_t i= 0; i < directory.size(); ++i)
354 dump_segment(directory[i], pbcfile);
357 void PbcFile::read_header(ifstream &pbcfile)
359 TagEmit tag("Header", cout);
361 signature(pbcfile);
362 unsigned char opcode_size = pbcfile.get();
363 unsigned char byte_order = pbcfile.get();
364 unsigned char fp_encoding = pbcfile.get();
365 unsigned char major = pbcfile.get();
366 unsigned char minor = pbcfile.get();
367 unsigned char patch = pbcfile.get();
368 unsigned char pbc_major = pbcfile.get();
369 unsigned char pbc_minor = pbcfile.get();
371 if (!pbcfile)
372 throw ReadError("pbc header data");
374 cout <<
375 "Opcode size : " << (int) opcode_size << '\n' <<
376 "Byte order : " << desc_byte_order(byte_order) <<
377 " (" << (int) byte_order << ")\n" <<
378 "Floating point encoding: " << desc_fp_encoding(fp_encoding) <<
379 " (" << (int) fp_encoding << ")\n" <<
380 "Parrot version : " <<
381 (int) major << '.' << (int) minor << '.' << (int) patch << '\n' <<
382 "PBC version : " <<
383 (int) pbc_major << '.' << (int) pbc_minor << '\n'
386 if (opcode_size > sizeof(opcode))
387 cerr << "*** Warning: opcode size too big for this program ***\n";
389 this->opcode_size = opcode_size;
390 this->pbc_version = ((unsigned int) pbc_major) * 8 + pbc_minor;
391 this->byte_order = byte_order;
392 this->fp_encoding = fp_encoding;
393 if (byte_order != ByteOrderLE && byte_order != ByteOrderBE)
394 throw runtime_error("Invalid byte order");
396 unsigned char uuid_type = pbcfile.get();
397 cout <<
398 "UUID type : " << desc_uuid_type(uuid_type) <<
399 " (" << (int) uuid_type << ")\n"
401 unsigned char uuid_length = pbcfile.get();
402 cout <<
403 "UUID length : " << (int) uuid_length << '\n'
405 unsigned int curpos = 18 + uuid_length;
406 unsigned int endheader = ((curpos + 15) / 16) * 16;
407 pbcfile.ignore(endheader - 18);
410 void PbcFile::check_directory_format(ifstream &pbcfile)
412 TagEmit tag("DirectoryFormat", cout);
414 opcode dir_format = read_opcode(pbcfile);
415 cout << "Directory format: " << dir_format << '\n';
416 if (dir_format != 1)
417 throw runtime_error("Unknown directory format");
419 opcode unused = read_opcode(pbcfile);
420 unused = read_opcode(pbcfile);
421 unused = read_opcode(pbcfile);
423 for (opcode n = opcode_size * 4; n % 16; ++n)
424 pbcfile.ignore(1);
427 void PbcFile::read_directory(ifstream &pbcfile)
429 TagEmit tag("Directory", cout);
431 opcode size = read_opcode(pbcfile);
432 cout << "Directory segment size: " << size << '\n';
434 pbcfile.ignore(16 - opcode_size);
435 if (pbc_version <= 0x0325 && opcode_size == 8)
436 pbcfile.ignore(16);
438 opcode entries = read_opcode(pbcfile);
439 cout << "Directory entries: " << entries << '\n';
441 for (unsigned int n= 0; n < entries; ++n)
443 opcode type = read_opcode(pbcfile);
444 cout <<
445 n << ": Type: '" << desc_segment_type(type) <<
446 " (" << type << ") "
447 "' Name: '";
448 string name = read_cstring(pbcfile);
449 cout << name;
450 opcode offset = read_opcode(pbcfile);
451 opcode length = read_opcode(pbcfile);
452 cout <<
453 "'\n Offset: " << offset << " Length: " << length << '\n';
454 DirEntry entry(name, type, offset, length);
455 directory.push_back(entry);
459 void PbcFile::dump_segment(const DirEntry &entry, ifstream &pbcfile)
461 cout << "Segment '" << entry.getName() << "'\n";
462 opcode const type = entry.getType();
463 cout << "Type: " << desc_segment_type(type) <<
464 " (0x" << hex << type << dec << ")\n";
466 // Set file read position to segment's start
467 pbcfile.seekg(entry.getOffset() * opcode_size);
469 switch(type)
471 case SegmentTypeDirectory:
472 cout << "*** Unexpected directory segment ***\n";
473 break;
474 case SegmentTypeDefault:
475 dump_segment_default(pbcfile);
476 break;
477 case SegmentTypeFixup:
478 dump_segment_fixup(pbcfile);
479 break;
480 case SegmentTypeConstantTable:
481 dump_segment_constant(pbcfile);
482 break;
483 case SegmentTypeBytecode:
484 dump_segment_bytecode(pbcfile);
485 break;
486 case SegmentTypePIRDebug:
487 dump_segment_pir_debug(pbcfile);
488 break;
489 case SegmentTypeAnnotations:
490 dump_segment_annotations(pbcfile);
491 break;
492 case SegmentTypePICData:
493 dump_segment_pic_data(pbcfile);
494 break;
495 case SegmentTypeDependencies:
496 dump_segment_dependencies(pbcfile);
497 break;
498 default:
499 cout << "*** Unknown segment type ***\n";
500 break;
504 void PbcFile::dump_segment_default(ifstream &/*pbcfile*/)
506 TagEmit tag("SegmentDefault", cout);
507 cout << "*** UNIMPLEMENTED ***\n";
510 void PbcFile::dump_segment_fixup(ifstream &pbcfile)
512 TagEmit tag("SegmentFixup", cout);
514 opcode segsize = read_opcode(pbcfile);
515 cout << "Segment size: " << segsize;
517 opcode itype = read_opcode(pbcfile);
518 cout << " itype: " << itype;
519 opcode id = read_opcode(pbcfile);
520 cout << " id: " << id;
521 opcode size = read_opcode(pbcfile);
522 cout << " size: " << size;
524 opcode tablelength = read_opcode(pbcfile);
525 cout << " Number of fixups: " << tablelength << '\n';
527 for (opcode n= 0; n < tablelength; ++n) {
528 cout << "Fixup " << n;
529 opcode type = read_opcode(pbcfile);
530 cout << " Type: " <<
531 " (0x" << hex << type << dec << ')';
532 switch (type) {
533 case 0x01:
535 opcode label = read_opcode(pbcfile);
536 cout << " Label: " << label;
537 opcode sub = read_opcode(pbcfile);
538 cout << " Sub: " << sub;
540 break;
541 case 0x02:
543 string label = read_cstring(pbcfile);
544 cout << " Label: '" << label << '\'';
545 opcode sub = read_opcode(pbcfile);
546 cout << " Sub: " << sub;
548 break;
549 default:
550 throw runtime_error("Invalid fixup");
552 cout << '\n';
556 void PbcFile::dump_segment_constant(ifstream &pbcfile)
558 TagEmit tag("SegmentConstantTable", cout);
560 opcode segsize = read_opcode(pbcfile);
561 cout << "Segment size: " << segsize;
563 opcode itype = read_opcode(pbcfile);
564 cout << " itype: " << itype;
565 opcode id = read_opcode(pbcfile);
566 cout << " id: " << id;
567 opcode size = read_opcode(pbcfile);
568 cout << " size: " << size;
570 opcode tablelength = read_opcode(pbcfile);
571 cout << " Number of constants: " << tablelength << '\n';
573 for (opcode n= 0; n < tablelength; ++n) {
574 cout << "Constant " << n;
575 opcode type = read_opcode(pbcfile);
576 cout << " Type: " << desc_constant_type(type) <<
577 " (0x" << hex << type << dec << ") ";
578 switch(type) {
579 case ConstantTypeString:
580 case ConstantTypePMC:
581 dump_constant_string(pbcfile);
582 break;
583 case ConstantTypeNumber:
584 dump_constant_number(pbcfile);
585 break;
586 case ConstantTypeKey:
587 dump_constant_key(pbcfile);
588 break;
589 default:
590 throw runtime_error("Unknown constant type");
595 void PbcFile::dump_segment_bytecode(ifstream &pbcfile)
597 TagEmit tag("SegmentBytecode", cout);
599 opcode segsize = read_opcode(pbcfile);
600 cout << "Segment size: " << segsize;
602 opcode itype = read_opcode(pbcfile);
603 cout << " itype: " << itype;
604 opcode id = read_opcode(pbcfile);
605 cout << " id: " << id;
606 opcode size = read_opcode(pbcfile);
607 cout << " size: " << size;
608 cout << hex;
610 for (opcode n= 0; n < size; ++n) {
611 opcode code = read_opcode(pbcfile);
612 if ((n % 8) == 0)
613 cout << '\n' << setfill('0') << setw (7) << n << ':';
614 else
615 cout << ' ';
616 cout << setfill('0') << setw(opcode_size * 2) << code;
618 cout << dec << '\n';
621 void PbcFile::dump_segment_pir_debug(ifstream &pbcfile)
623 TagEmit tag("SegmentPIRDebug", cout);
625 opcode segsize = read_opcode(pbcfile);
626 cout << "Segment size: " << segsize;
628 opcode itype = read_opcode(pbcfile);
629 cout << " itype: " << itype;
630 opcode id = read_opcode(pbcfile);
631 cout << " id: " << id;
632 opcode size = read_opcode(pbcfile);
633 cout << " size: " << size;
634 cout << '\n';
636 opcode tablelength = size;
637 for (opcode n= 0; n < tablelength; ++n) {
638 opcode linenum = read_opcode(pbcfile);
639 cout << " Line: " << linenum;
641 cout << '\n';
643 opcode mappings = read_opcode(pbcfile);
644 cout << "Mappings: " << mappings << '\n';
645 for (opcode n= 0; n < mappings; ++n) {
646 cout << " " << n;
647 opcode offset = read_opcode(pbcfile);
648 cout << " Offset: " << offset;
649 opcode filename = read_opcode(pbcfile);
650 cout << " File: " << filename;
651 cout << '\n';
655 void PbcFile::dump_segment_annotations(ifstream &pbcfile)
657 TagEmit tag("SegmentAnnotations", cout);
659 opcode segsize = read_opcode(pbcfile);
660 cout << "Segment size: " << segsize;
662 opcode itype = read_opcode(pbcfile);
663 cout << " itype: " << itype;
664 opcode id = read_opcode(pbcfile);
665 cout << " id: " << id;
666 opcode size = read_opcode(pbcfile);
667 cout << " size: " << size;
668 cout << '\n';
670 opcode tablelength = read_opcode(pbcfile);
671 cout << "Number of annotations: " << tablelength << '\n';
673 for (opcode i= 0; i < tablelength; ++i) {
674 cout << i;
675 opcode name = read_opcode(pbcfile);
676 cout << " Name: " << name;
677 opcode type = read_opcode(pbcfile);
678 cout << " Type: " << desc_annotation_type(type) << '\n';
681 opcode grouplength = read_opcode(pbcfile);
682 cout << "Number of annotation groups: " << grouplength << '\n';
683 for (opcode i= 0; i < grouplength; ++i) {
684 cout << i;
685 opcode bcpos = read_opcode(pbcfile);
686 cout << " Bytecode offset: " << bcpos;
687 opcode value = read_opcode(pbcfile);
688 cout << " Value: " << value << '\n';
691 opcode mappings = read_opcode(pbcfile);
692 cout << "Number of mappings: " << mappings << '\n';
693 for (opcode i= 0; i < mappings; ++i) {
694 cout << i;
695 opcode bcpos = read_opcode(pbcfile);
696 cout << " Bytecode offset: " << bcpos;
697 opcode annotation = read_opcode(pbcfile);
698 cout << " Annotation key: " << annotation;
699 opcode value = read_opcode(pbcfile);
700 cout << " Value: " << value << '\n';
704 void PbcFile::dump_segment_pic_data(ifstream &/*pbcfile*/)
706 TagEmit tag("SegmentPICData", cout);
707 cout << "*** UNIMPLEMENTED ***\n";
710 void PbcFile::dump_segment_dependencies(ifstream &/*pbcfile*/)
712 TagEmit tag("SegmentDependencies", cout);
713 cout << "*** UNIMPLEMENTED ***\n";
716 void PbcFile::dump_constant_string(ifstream &pbcfile)
718 opcode flags = read_opcode(pbcfile);
719 cout << "Flags: 0x" << hex << flags << dec;
720 opcode charset = read_opcode(pbcfile);
721 cout << " Charset: " << charset;
723 //opcode encoding = read_opcode(pbcfile);
724 //cout << " Encoding: "<< encoding;
726 opcode length = read_opcode(pbcfile);
727 cout << " Length: "<< length;
728 cout << " \'";
729 for (opcode i= 0; i < length; ++i) {
730 unsigned char c = pbcfile.get();
731 if (c >= 32 && c < 128)
732 cout << c;
733 else
734 cout << "\\x" << hex << setw(2) << setfill('0') <<
735 (unsigned int) c << dec;
737 cout << "'\n";
738 for (unsigned int i= length; i % opcode_size; ++i) {
739 pbcfile.ignore(1);
743 void PbcFile::dump_constant_number(ifstream &pbcfile)
745 cout << "Number constant: ";
746 switch(fp_encoding) {
747 case FpEncodingIEEE_754_8:
748 dump_bytes_hex(pbcfile, 8);
749 break;
750 case FpEncodingIEEE_i386_12:
751 dump_bytes_hex(pbcfile, 12);
752 break;
753 case FpEncodingIEEE_754_16:
754 dump_bytes_hex(pbcfile, 16);
755 break;
756 default:
757 // This must have been catched before reaching this point
758 throw std::logic_error("Bad number type");
762 void PbcFile::dump_constant_key(ifstream &pbcfile)
764 opcode components = read_opcode(pbcfile);
765 cout << "Key components: " << components << '\n';
766 for (opcode i= 0; i < components; ++i) {
767 cout << " " << i << ' ';
768 opcode type = read_opcode(pbcfile);
769 cout << "Type: " << desc_key_type (type) <<
770 " (0x" << hex << type << dec << ") ";
771 opcode value = read_opcode(pbcfile);
772 cout << "Value: " << value << '\n';
776 void PbcFile::dump_bytes_hex(ifstream &pbcfile, opcode length)
778 cout << "0x" << hex;
779 for (opcode i= 0; i < length; ++i) {
780 unsigned char c = pbcfile.get();
781 cout << setw(2) << setfill('0') << (unsigned int) c;
783 cout << dec << '\n';
786 string PbcFile::read_cstring(ifstream &pbcfile)
788 string r;
789 char c;
790 while ((c= pbcfile.get())) {
791 r+= c;
794 // cstrings are padded with trailing zeroes to opcode size
795 for (opcode l = r.size() + 1; l % opcode_size; ++l)
796 pbcfile.ignore(1);
798 if(! pbcfile)
799 throw ReadError("cstring");
800 return r;
803 opcode PbcFile::read_opcode(ifstream &pbcfile)
805 unsigned char buffer [32]; // Allow 256 bits opcode size
806 pbcfile.read((char *)buffer, opcode_size);
807 if (static_cast<unsigned int>(pbcfile.gcount()) != opcode_size)
808 throw ReadError("opcode");
810 opcode result = 0;
811 switch(byte_order)
813 case ByteOrderLE:
814 for (unsigned int i= 0; i < opcode_size; ++i) {
815 result <<= 8;
816 result += buffer [opcode_size - 1 - i];
818 break;
819 case ByteOrderBE:
820 for (unsigned int i= 0; i < opcode_size; ++i) {
821 result <<= 8;
822 result += buffer [i];
824 break;
825 default:
826 // This must have been catched before reaching this point
827 throw std::logic_error("Bad byte order");
829 return result;
832 //**********************************************************************
834 void pbc_checker_main(int argc, char **argv)
836 if (argc < 2)
837 throw runtime_error("Bad args");
839 PbcFile pbcfile;
840 pbcfile.read(argv[1]);
843 //**********************************************************************
845 int main(int argc, char **argv)
849 pbc_checker_main(argc, argv);
850 return 0;
852 catch(std::
853 exception &e)
855 cerr << "FAILED: " << e.what() << '\n';
857 return 1;
860 // End of pbc_checker.cpp
862 * Local variables:
863 * c-file-style: "parrot"
864 * End:
865 * vim: expandtab shiftwidth=4: