1/*
2
3PCL6 Disassembler
4
5Copyright (c) 2003 Haiku.
6
7Author:
8	Michael Pfeiffer
9
10Permission is hereby granted, free of charge, to any person obtaining a copy of
11this software and associated documentation files (the "Software"), to deal in
12the Software without restriction, including without limitation the rights to
13use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14of the Software, and to permit persons to whom the Software is furnished to do
15so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26THE SOFTWARE.
27
28*/
29
30#include <stdio.h>
31#include <ctype.h>
32#include "disasm.h"
33
34// Implementation of InputStream
35
36int InputStream::Read(void* buffer, int size) {
37	if (size > 0) {
38		uint8* b = (uint8*)buffer;
39		int s = 0;
40		if (fBufferSize > 0) {
41			*b = fBuffer;
42			b ++;
43			size --;
44			s = 1;
45			fBufferSize = 0;
46		}
47		s = s + RawRead(b, size);
48		fPos += s;
49		return s;
50	}
51	return 0;
52}
53
54bool InputStream::PutUByte(uint8 byte) {
55	if (fBufferSize != 0) return false;
56	fBufferSize = 1; fBuffer = byte; fPos --;
57	return true;
58}
59
60bool InputStream::ReadUByte(uint8& v) {
61	return sizeof(v) == Read(&v, sizeof(v));
62}
63
64bool InputStream::ReadUInt16(uint16& v) {
65	return sizeof(v) == Read(&v, sizeof(v));
66}
67
68bool InputStream::ReadUInt32(uint32& v) {
69	return sizeof(v) == Read(&v, sizeof(v));
70}
71
72bool InputStream::ReadSInt16(int16& v) {
73	return sizeof(v) == Read(&v, sizeof(v));
74}
75
76bool InputStream::ReadSInt32(int32& v) {
77	return sizeof(v) == Read(&v, sizeof(v));
78}
79
80bool InputStream::ReadReal32(float& v) {
81	return sizeof(v) == Read(&v, sizeof(v));
82}
83
84// Implementation of File
85
86File::File(const char* filename) {
87	fFile = fopen(filename, "r+b");
88}
89
90File::~File() {
91	if (fFile) {
92		fclose(fFile); fFile = NULL;
93	}
94}
95
96int File::RawRead(void* buffer, int size) {
97	return fread(buffer, 1, size, fFile);
98}
99
100// Implementation of Disasm
101
102void Disasm::Print() {
103	if (!ParsePJL()) {
104		Error("Error parsing PJL header");
105	} else if (!ParsePCL6()) {
106		Error("Error parsing PCL6");
107		fprintf(stderr, "File position %d\n", fStream->Pos());
108	}
109}
110
111void Disasm::Error(const char* text) {
112	fprintf(stderr, "%s\n", text);
113}
114
115bool Disasm::Expect(const char* text) {
116	uint8 byte;
117	for (uint8* t = (uint8*)text; *t != '\0'; t++) {
118		if (!fStream->ReadUByte(byte) || byte != *t) return false;
119	}
120	return true;
121}
122
123bool Disasm::SkipTo(const char* text) {
124	uint8 byte;
125	if (!fStream->ReadUByte(byte)) return false;
126	startagain:
127	for (;;) {
128		uint8* t = (uint8*)text;
129		// find first character
130		if (byte != *t) {
131			if (!fStream->ReadUByte(byte)) return false;
132			continue;
133		}
134		// compare rest
135		for (t ++; *t != '\0'; t ++) {
136			if (!fStream->ReadUByte(byte)) return false;
137			if (byte != *t) goto startagain;
138		}
139		return true;
140	}
141	return true;
142}
143
144bool Disasm::ReadNumber(int32& n) {
145	n = 0;
146	uint8 byte;
147	while (fStream->ReadUByte(byte)) {
148		if (isdigit(byte)) {
149			n = 10 * n + (byte - '0');
150		} else {
151			fStream->PutUByte(byte);
152			return true;
153		}
154	}
155	return false;
156}
157
158bool Disasm::ParsePJL() {
159	if (!Expect("\033%-12345X") || !SkipTo(") HP-PCL XL;")) return false;
160	// version";"minor";" ... \n
161	int32 version, minor;
162	if (ReadNumber(version) && Expect(";") && ReadNumber(minor) && Expect(";") && SkipTo("\n")) {
163		printf("PCL XL %d ; %d\n", (int)version, (int)minor);
164		return true;
165	}
166	return false;
167}
168
169void Disasm::DeleteAttr(struct ATTRIBUTE* attr) {
170	if (attr) {
171		switch (attr->Type) {
172		case  HP_UByteArray: delete attr->val.ubyte_array;
173			break;
174		case  HP_UInt16Array: delete attr->val.uint16_array;
175			break;
176		case  HP_UInt32Array: delete attr->val.uint32_array;
177			break;
178		case  HP_SInt16Array: delete attr->val.sint16_array;
179			break;
180		case  HP_SInt32Array: delete attr->val.sint32_array;
181			break;
182		case  HP_Real32Array: delete attr->val.real32_array;
183			break;
184		};
185		delete attr;
186	}
187}
188
189void Disasm::ClearAttrs() {
190	for (int i = 0; i < NumOfArgs(); i ++) {
191		DeleteAttr(ArgAt(i));
192	}
193	fArgs.MakeEmpty();
194}
195
196
197bool Disasm::DecodeOperator(uint8 byte) {
198	switch (byte) {
199		case HP_BeginSession: printf("BeginSession\n"); break;
200		case HP_EndSession: printf("EndSession\n"); break;
201		case HP_BeginPage: printf("BeginPage\n"); break;
202		case HP_EndPage: printf("EndPage\n"); break;
203		case HP_VendorUnique: printf("VendorUnique\n"); break;
204		case HP_Comment: printf("Comment\n"); break;
205		case HP_OpenDataSource: printf("OpenDataSource\n"); break;
206		case HP_CloseDataSource: printf("CloseDataSource\n"); break;
207		case HP_EchoComment: printf("EchoComment\n"); break;
208		case HP_Query: printf("Query\n"); break;
209		case HP_Diagnostic3: printf("Diagnostic3\n"); break;
210
211		case HP_BeginFontHeader: printf("BeginFontHeader\n"); break;
212		case HP_ReadFontHeader: printf("ReadFontHeader\n"); break;
213		case HP_EndFontHeader: printf("EndFontHeader\n"); break;
214		case HP_BeginChar: printf("BeginChar\n"); break;
215		case HP_ReadChar: printf("ReadChar\n"); break;
216		case HP_EndChar: printf("EndChar\n"); break;
217		case HP_RemoveFont: printf("RemoveFont\n"); break;
218		case HP_SetCharAttribute: printf("SetCharAttribute\n"); break;
219
220		case HP_SetDefaultGS: printf("SetDefaultGS\n"); break;
221		case HP_SetColorTreatment: printf("SetColorTreatment\n"); break;
222		case HP_SetGlobalAttributes: printf("SetGlobalAttributes\n"); break;
223		case HP_ClearGlobalAttributes: printf("ClearGlobalAttributes\n"); break;
224		case HP_BeginStream: printf("BeginStream\n"); break;
225		case HP_ReadStream: printf("ReadStream\n"); break;
226		case HP_EndStream: printf("EndStream\n"); break;
227		case HP_ExecStream: printf("ExecStream\n"); break;
228		case HP_RemoveStream: printf("RemoveStream\n"); break;
229
230		case HP_PopGS: printf("PopGS\n"); break;
231		case HP_PushGS: printf("PushGS\n"); break;
232		case HP_SetClipReplace: printf("SetClipReplace\n"); break;
233		case HP_SetBrushSource: printf("SetBrushSource\n"); break;
234		case HP_SetCharAngle: printf("SetCharAngle\n"); break;
235		case HP_SetCharScale: printf("SetCharScale\n"); break;
236		case HP_SetCharShear: printf("SetCharShear\n"); break;
237		case HP_SetClipIntersect: printf("SetClipIntersect\n"); break;
238		case HP_SetClipRectangle: printf("SetClipRectangle\n"); break;
239		case HP_SetClipToPage: printf("SetClipToPage\n"); break;
240		case HP_SetColorSpace: printf("SetColorSpace\n"); break;
241		case HP_SetCursor: printf("SetCursor\n"); break;
242		case HP_SetCursorRel: printf("SetCursorRel\n"); break;
243		case HP_SetHalftoneMethod: printf("SetHalftoneMethod\n"); break;
244		case HP_SetFillMode: printf("SetFillMode\n"); break;
245		case HP_SetFont: printf("SetFont\n"); break;
246		case HP_SetLineDash: printf("SetLineDash\n"); break;
247		case HP_SetLineCap: printf("SetLineCap\n"); break;
248		case HP_SetLineJoin: printf("SetLineJoin\n"); break;
249		case HP_SetMiterLimit: printf("SetMiterLimit\n"); break;
250		case HP_SetPageDefaultCTM: printf("SetPageDefaultCTM\n"); break;
251		case HP_SetPageOrigin: printf("SetPageOrigin\n"); break;
252		case HP_SetPageRotation: printf("SetPageRotation\n"); break;
253		case HP_SetPageScale: printf("SetPageScale\n"); break;
254		case HP_SetPaintTxMode: printf("SetPaintTxMode\n"); break;
255		case HP_SetPenSource: printf("SetPenSource\n"); break;
256		case HP_SetPenWidth: printf("SetPenWidth\n"); break;
257		case HP_SetROP: printf("SetROP\n"); break;
258		case HP_SetSourceTxMode: printf("SetSourceTxMode\n"); break;
259		case HP_SetCharBoldValue: printf("SetCharBoldValue\n"); break;
260		case HP_SetClipMode: printf("SetClipMode\n"); break;
261		case HP_SetPathToClip: printf("SetPathToClip\n"); break;
262		case HP_SetCharSubMode: printf("SetCharSubMode\n"); break;
263		case HP_BeginUserDefinedLineCap: printf("BeginUserDefinedLineCap\n"); break;
264		case HP_EndUserDefinedLineCap: printf("EndUserDefinedLineCap\n"); break;
265		case HP_CloseSubPath: printf("CloseSubPath\n"); break;
266		case HP_NewPath: printf("NewPath\n"); break;
267		case HP_PaintPath: printf("PaintPath\n"); break;
268		case HP_BeginBackground: printf("BeginBackground\n"); break;
269		case HP_EndBackground: printf("EndBackground\n"); break;
270		case HP_DrawBackground: printf("DrawBackground\n"); break;
271		case HP_RemoveBackground: printf("RemoveBackground\n"); break;
272		case HP_BeginForm: printf("BeginForm\n"); break;
273		case HP_EndForm: printf("EndForm\n"); break;
274		case HP_DrawForm: printf("DrawForm\n"); break;
275		case HP_RemoveForm: printf("RemoveForm\n"); break;
276		case HP_RegisterFormAsPattern: printf("RegisterFormAsPattern\n"); break;
277
278		case HP_ArcPath: printf("ArcPath\n"); break;
279
280		case HP_BezierPath: printf("BezierPath\n"); break;
281		case HP_BezierRelPath: printf("BezierRelPath\n"); break;
282		case HP_Chord: printf("Chord\n"); break;
283		case HP_ChordPath: printf("ChordPath\n"); break;
284		case HP_Ellipse: printf("Ellipse\n"); break;
285		case HP_EllipsePath: printf("EllipsePath\n"); break;
286
287		case HP_LinePath: printf("LinePath\n"); break;
288
289		case HP_LineRelPath: printf("LineRelPath\n"); break;
290		case HP_Pie: printf("Pie\n"); break;
291		case HP_PiePath: printf("PiePath\n"); break;
292
293		case HP_Rectangle: printf("Rectangle\n"); break;
294		case HP_RectanglePath: printf("RectanglePath\n"); break;
295		case HP_RoundRectangle: printf("RoundRectangle\n"); break;
296		case HP_RoundRectanglePath: printf("RoundRectanglePath\n"); break;
297
298		case HP_Text: printf("Text\n"); break;
299		case HP_TextPath: printf("TextPath\n"); break;
300
301		case HP_SystemText: printf("SystemText\n"); break;
302
303		case HP_BeginImage: printf("BeginImage\n"); break;
304		case HP_ReadImage: printf("ReadImage\n"); break;
305		case HP_EndImage: printf("EndImage\n"); break;
306		case HP_BeginRastPattern: printf("BeginRastPattern\n"); break;
307		case HP_ReadRastPattern: printf("ReadRastPattern\n"); break;
308		case HP_EndRastPattern: printf("EndRastPattern\n"); break;
309		case HP_BeginScan: printf("BeginScan\n"); break;
310		case HP_EndScan: printf("EndScan\n"); break;
311		case HP_ScanLineRel: printf("ScanLineRel\n"); break;
312
313		case HP_PassThrough: printf("PassThrough\n"); break;
314		default:
315			printf("Unsupported operator %d %x\n", (int)byte, (int)byte);
316			return false;
317	}
318	return true;
319}
320
321bool Disasm::ReadArrayLength(uint32& length) {
322	uint8 type;
323	if (fStream->ReadUByte(type)) {
324		struct ATTRIBUTE* attr = ReadData(type);
325		if (attr == NULL) return false;
326		if (attr->Type == HP_UByteData) {
327			length = attr->val.ubyte;
328		} else if (attr->Type == HP_UInt16Data) {
329			length = attr->val.uint16;
330		} else {
331			DeleteAttr(attr); return false;
332		}
333		DeleteAttr(attr);return true;
334	}
335	return false;
336}
337
338#define READ_ARRAY(array_name, c_type, type) \
339	attr->val.array_name = new c_type[length]; \
340	attr->arrayLen = length; \
341	for (uint32 i = 0; i < length; i ++) { \
342		c_type data; \
343		if (!fStream->Read##type(data)) { \
344			delete attr->val.array_name; return false; \
345		} \
346		attr->val.array_name[i] = data; \
347	}
348
349bool Disasm::ReadArray(uint8 type, uint32 length, struct ATTRIBUTE* attr) {
350	switch (type) {
351		case  HP_UByteArray: READ_ARRAY(ubyte_array, uint8, UByte);
352			break;
353		case  HP_UInt16Array: READ_ARRAY(uint16_array, uint16, UInt16);
354			break;
355		case  HP_UInt32Array: READ_ARRAY(uint32_array, uint32, UInt32);
356			break;
357		case  HP_SInt16Array: READ_ARRAY(sint16_array, int16, SInt16);
358			break;
359		case  HP_SInt32Array: READ_ARRAY(sint32_array, int32, SInt32);
360			break;
361		case  HP_Real32Array: READ_ARRAY(real32_array, float, Real32);
362			break;
363	}
364	return true;
365}
366
367#define PRINT_ARRAY(array_name, format, c_type, type) \
368			printf(array_name "[%u] = \n", (unsigned int)attr->arrayLen); \
369			for (uint32 i = 0; i < attr->arrayLen; i ++) { \
370				if (i > 0 && i % 16 == 0) printf("\n"); \
371				printf(format, (c_type)attr->val.type##_array[i]); \
372			} \
373			printf(";\n");
374
375
376
377
378void Disasm::PrintAttr(struct ATTRIBUTE* attr) {
379	switch (attr->Type) {
380		case  HP_UByteData: printf("ubyte %d ", (int)attr->val.ubyte);
381			break;
382		case  HP_UInt16Data: printf("uint16 %u ", (unsigned int)attr->val.uint16);
383			break;
384		case  HP_UInt32Data: printf("uint32 %u ", (unsigned int)attr->val.uint32);
385			break;
386		case  HP_SInt16Data: printf("uint16 %d ", (int)attr->val.sint16);
387			break;
388		case  HP_SInt32Data: printf("sint16 %d ", (int)attr->val.sint32);
389			break;
390		case  HP_Real32Data:  printf("real32 %f ", attr->val.real32);
391			break;
392
393		case  HP_String: fprintf(stderr, "HP_String not implemented!\n");
394			break;
395		case  HP_UByteArray: PRINT_ARRAY("ubyte_array", "%d ", int, ubyte);
396			break;
397		case  HP_UInt16Array: PRINT_ARRAY("uint16_array", "%u ", unsigned int, uint16);
398			break;
399		case  HP_UInt32Array: PRINT_ARRAY("uint32_array", "%u ", unsigned int, uint32);
400			break;
401		case  HP_SInt16Array: PRINT_ARRAY("sint16_array", "%d ", int, sint16);
402			break;
403		case  HP_SInt32Array: PRINT_ARRAY("sint32_array", "%d ", int, sint32);
404			break;
405		case  HP_Real32Array: PRINT_ARRAY("real32_array", "%f ", float, real32);
406			break;
407
408		case  HP_UByteXy:
409			printf("ubyte [%d, %d] ", (int)attr->val.UByte_XY.x, (int)attr->val.UByte_XY.y);
410			break;
411		case  HP_UInt16Xy:
412			printf("uint16 [%u, %u] ", (unsigned int)attr->val.UInt16_XY.x, (unsigned int)attr->val.UInt16_XY.y);
413			break;
414		case  HP_UInt32Xy:
415			printf("uint32 [%u, %u] ", (unsigned int)attr->val.UInt32_XY.x, (unsigned int)attr->val.UInt32_XY.y);
416			break;
417		case  HP_SInt16Xy:
418			printf("sint16 [%d, %d] ", (int)attr->val.SInt16_XY.x, (int)attr->val.SInt16_XY.y);
419			break;
420		case  HP_SInt32Xy:
421			printf("sint32 [%d, %d] ", (int)attr->val.SInt32_XY.x, (int)attr->val.SInt32_XY.y);
422			break;
423		case  HP_Real32Xy:
424			printf("real32 [%f, %f] ", (float)attr->val.Real32_XY.x, (float)attr->val.Real32_XY.y);
425			break;
426
427		case  HP_UByteBox:
428			printf("ubyte [%d, %d, %d, %d] ", (int)attr->val.UByte_BOX.x1, (int)attr->val.UByte_BOX.y1, (int)attr->val.UByte_BOX.x2, (int)attr->val.UByte_BOX.y2);
429			break;
430		case  HP_UInt16Box:
431			printf("uint16 [%u, %u, %u, %u] ", (unsigned int)attr->val.UInt16_BOX.x1, (unsigned int)attr->val.UInt16_BOX.y1, (unsigned int)attr->val.UInt16_BOX.x2, (unsigned int)attr->val.UInt16_BOX.y2);
432			break;
433		case  HP_UInt32Box:
434			printf("uint32 [%u, %u, %u, %u] ", (unsigned int)attr->val.UInt32_BOX.x1, (unsigned int)attr->val.UInt32_BOX.y1, (unsigned int)attr->val.UInt32_BOX.x2, (unsigned int)attr->val.UInt32_BOX.y2);
435			break;
436		case  HP_SInt16Box:
437			printf("sint16 [%d, %d, %d, %d] ", (int)attr->val.SInt16_BOX.x1, (int)attr->val.SInt16_BOX.y1, (int)attr->val.SInt16_BOX.x2, (int)attr->val.SInt16_BOX.y2);
438			break;
439		case  HP_SInt32Box:
440			printf("sint32 [%d, %d, %d, %d] ", (int)attr->val.SInt32_BOX.x1, (int)attr->val.SInt32_BOX.y1, (int)attr->val.SInt32_BOX.x2, (int)attr->val.SInt32_BOX.y2);
441			break;
442		case  HP_Real32Box:
443			printf("real32 [%f, %f, %f, %f] ", (float)attr->val.Real32_BOX.x1, (float)attr->val.Real32_BOX.y1, (float)attr->val.Real32_BOX.x2, (float)attr->val.Real32_BOX.y2);
444			break;
445	}
446}
447
448struct ATTRIBUTE* Disasm::ReadData(uint8 byte) {
449	struct ATTRIBUTE attr(0, byte);
450	uint32 length;
451	switch (byte) {
452		case  HP_UByteData:
453			if (!fStream->ReadUByte(attr.val.ubyte)) return NULL;
454			break;
455		case  HP_UInt16Data:
456			if (!fStream->ReadUInt16(attr.val.uint16)) return NULL;
457			break;
458		case  HP_UInt32Data:
459			if (!fStream->ReadUInt32(attr.val.uint32)) return NULL;
460			break;
461		case  HP_SInt16Data:
462			if (!fStream->ReadSInt16(attr.val.sint16)) return NULL;
463			break;
464		case  HP_SInt32Data:
465			if (!fStream->ReadSInt32(attr.val.sint32)) return NULL;
466			break;
467		case  HP_Real32Data:
468			if (!fStream->ReadReal32(attr.val.real32)) return NULL;
469			break;
470
471		case  HP_String: fprintf(stderr, "HP_String not implemented!\n"); return NULL;
472			break;
473		case  HP_UByteArray:
474		case  HP_UInt16Array:
475		case  HP_UInt32Array:
476		case  HP_SInt16Array:
477		case  HP_SInt32Array:
478		case  HP_Real32Array:
479			if (!ReadArrayLength(length) || !ReadArray(byte, length, &attr)) return NULL;
480			break;
481
482		case  HP_UByteXy:
483			if (!fStream->ReadUByte(attr.val.UByte_XY.x) || !fStream->ReadUByte(attr.val.UByte_XY.y)) return NULL;
484			break;
485		case  HP_UInt16Xy:
486			if (!fStream->ReadUInt16(attr.val.UInt16_XY.x) || !fStream->ReadUInt16(attr.val.UInt16_XY.y)) return NULL;
487			break;
488		case  HP_UInt32Xy:
489			if (!fStream->ReadUInt32(attr.val.UInt32_XY.x) || !fStream->ReadUInt32(attr.val.UInt32_XY.y)) return NULL;
490			break;
491		case  HP_SInt16Xy:
492			if (!fStream->ReadSInt16(attr.val.SInt16_XY.x) || !fStream->ReadSInt16(attr.val.SInt16_XY.y)) return NULL;
493			break;
494		case  HP_SInt32Xy:
495			if (!fStream->ReadSInt32(attr.val.SInt32_XY.x) || !fStream->ReadSInt32(attr.val.SInt32_XY.y)) return NULL;
496			break;
497		case  HP_Real32Xy:
498			if (!fStream->ReadReal32(attr.val.Real32_XY.x) || !fStream->ReadReal32(attr.val.Real32_XY.y)) return NULL;
499			break;
500
501		case  HP_UByteBox:
502			if (!fStream->ReadUByte(attr.val.UByte_BOX.x1) || !fStream->ReadUByte(attr.val.UByte_BOX.y1) ||
503				!fStream->ReadUByte(attr.val.UByte_BOX.x2) || !fStream->ReadUByte(attr.val.UByte_BOX.y2)) return NULL;
504			break;
505		case  HP_UInt16Box:
506			if (!fStream->ReadUInt16(attr.val.UInt16_BOX.x1) || !fStream->ReadUInt16(attr.val.UInt16_BOX.y1) ||
507				!fStream->ReadUInt16(attr.val.UInt16_BOX.x2) || !fStream->ReadUInt16(attr.val.UInt16_BOX.y2)) return NULL;
508			break;
509		case  HP_UInt32Box:
510			if (!fStream->ReadUInt32(attr.val.UInt32_BOX.x1) || !fStream->ReadUInt32(attr.val.UInt32_BOX.y1) ||
511				!fStream->ReadUInt32(attr.val.UInt32_BOX.x2) || !fStream->ReadUInt32(attr.val.UInt32_BOX.y2)) return NULL;
512			break;
513		case  HP_SInt16Box:
514			if (!fStream->ReadSInt16(attr.val.SInt16_BOX.x1) || !fStream->ReadSInt16(attr.val.SInt16_BOX.y1) ||
515				!fStream->ReadSInt16(attr.val.SInt16_BOX.x2) || !fStream->ReadSInt16(attr.val.SInt16_BOX.y2)) return NULL;
516			break;
517		case  HP_SInt32Box:
518			if (!fStream->ReadSInt32(attr.val.SInt32_BOX.x1) || !fStream->ReadSInt32(attr.val.SInt32_BOX.y1) ||
519				!fStream->ReadSInt32(attr.val.SInt32_BOX.x2) || !fStream->ReadSInt32(attr.val.SInt32_BOX.y2)) return NULL;
520			break;
521		case  HP_Real32Box:
522			if (!fStream->ReadReal32(attr.val.Real32_BOX.x1) || !fStream->ReadReal32(attr.val.Real32_BOX.y1) ||
523				!fStream->ReadReal32(attr.val.Real32_BOX.x2) || !fStream->ReadReal32(attr.val.Real32_BOX.y2)) return NULL;
524			break;
525		default:
526			fprintf(stderr, "Unknown data tag %d %x\n", (int)byte, (int)byte);
527			return NULL;
528	}
529	struct ATTRIBUTE* pAttr = new struct ATTRIBUTE(0, 0);
530	*pAttr = attr;
531	return pAttr;
532}
533
534bool Disasm::PushData(uint8 byte) {
535	struct ATTRIBUTE* attr = ReadData(byte);
536	if (attr) {
537		PushArg(attr); return true;
538	} else {
539		Error("Reading data");
540		return false;
541	}
542}
543
544const char* Disasm::AttributeName(uint8 id) {
545	switch (id) {
546		case HP_CMYColor: return "CMYColor";
547		case HP_PaletteDepth: return "PaletteDepth";
548		case HP_ColorSpace: return "ColorSpace";
549		case HP_NullBrush: return "NullBrush";
550		case HP_NullPen: return "NullPen";
551		case HP_PaletteData: return "PaletteData";
552		case HP_PaletteIndex: return "PaletteIndex";
553		case HP_PatternSelectID: return "PatternSelectID";
554		case HP_GrayLevel: return "GrayLevel";
555
556		case HP_RGBColor: return "RGBColor";
557		case HP_PatternOrigin: return "PatternOrigin";
558		case HP_NewDestinationSize: return "NewDestinationSize";
559
560		case HP_PrimaryArray: return "PrimaryArray";
561		case HP_PrimaryDepth: return "PrimaryDepth";
562		case HP_ColorimetricColorSpace: return "ColorimetricColorSpace";
563		case HP_XYChromaticities: return "XYChromaticities";
564		case HP_WhitePointReference: return "WhitePointReference";
565		case HP_CRGBMinMax: return "CRGBMinMax";
566		case HP_GammaGain: return "GammaGain";
567
568
569		case HP_DeviceMatrix: return "DeviceMatrix";
570		case HP_DitherMatrixDataType: return "DitherMatrixDataType";
571		case HP_DitherOrigin: return "DitherOrigin";
572		case HP_MediaDest: return "MediaDest";
573		case HP_MediaSize: return "MediaSize";
574		case HP_MediaSource: return "MediaSource";
575		case HP_MediaType: return "MediaType";
576		case HP_Orientation: return "Orientation";
577		case HP_PageAngle: return "PageAngle";
578		case HP_PageOrigin: return "PageOrigin";
579		case HP_PageScale: return "PageScale";
580		case HP_ROP3: return "ROP3";
581		case HP_TxMode: return "TxMode";
582		case HP_CustomMediaSize: return "CustomMediaSize";
583		case HP_CustomMediaSizeUnits: return "CustomMediaSizeUnits";
584		case HP_PageCopies: return "PageCopies";
585		case HP_DitherMatrixSize: return "DitherMatrixSize";
586		case HP_DitherMatrixDepth: return "DitherMatrixDepth";
587		case HP_SimplexPageMode: return "SimplexPageMode";
588		case HP_DuplexPageMode: return "DuplexPageMode";
589		case HP_DuplexPageSide: return "DuplexPageSide";
590
591		case HP_LineStartCapStyle: return "LineStartCapStyle";
592		case HP_LineEndCapStyle: return "LineEndCapStyle";
593		case HP_ArcDirection: return "ArcDirection";
594		case HP_BoundingBox: return "BoundingBox";
595		case HP_DashOffset: return "DashOffset";
596		case HP_EllipseDimension: return "EllipseDimension";
597		case HP_EndPoint: return "EndPoint";
598		case HP_FillMode: return "FillMode";
599		case HP_LineCapStyle: return "LineCapStyle";
600		case HP_LineJoinStyle: return "LineJoinStyle";
601		case HP_MiterLength: return "MiterLength";
602		case HP_LineDashStyle: return "LineDashStyle";
603		case HP_PenWidth: return "PenWidth";
604		case HP_Point: return "Point";
605		case HP_NumberOfPoints: return "NumberOfPoints";
606		case HP_SolidLine: return "SolidLine";
607		case HP_StartPoint: return "StartPoint";
608		case HP_PointType: return "PointType";
609		case HP_ControlPoint1: return "ControlPoint1";
610		case HP_ControlPoint2: return "ControlPoint2";
611		case HP_ClipRegion: return "ClipRegion";
612		case HP_ClipMode: return "ClipMode";
613
614
615		case HP_ColorDepthArray: return "ColorDepthArray";
616		case HP_ColorDepth: return "ColorDepth";
617		case HP_BlockHeight: return "BlockHeight";
618		case HP_ColorMapping: return "ColorMapping";
619		case HP_CompressMode: return "CompressMode";
620		case HP_DestinationBox: return "DestinationBox";
621		case HP_DestinationSize: return "DestinationSize";
622		case HP_PatternPersistence: return "PatternPersistence";
623		case HP_PatternDefineID: return "PatternDefineID";
624		case HP_SourceHeight: return "SourceHeight";
625		case HP_SourceWidth: return "SourceWidth";
626		case HP_StartLine: return "StartLine";
627		case HP_PadBytesMultiple: return "PadBytesMultiple";
628		case HP_BlockByteLength: return "BlockByteLength";
629		case HP_NumberOfScanLines: return "NumberOfScanLines";
630
631		case HP_ColorTreatment: return "ColorTreatment";
632		case HP_FileName: return "FileName";
633		case HP_BackgroundName: return "BackgroundName";
634		case HP_FormName: return "FormName";
635		case HP_FormType: return "FormType";
636		case HP_FormSize: return "FormSize";
637		case HP_UDLCName: return "UDLCName";
638
639		case HP_CommentData: return "CommentData";
640		case HP_DataOrg: return "DataOrg";
641		case HP_Measure: return "Measure";
642		case HP_SourceType: return "SourceType";
643		case HP_UnitsPerMeasure: return "UnitsPerMeasure";
644		case HP_QueryKey: return "QueryKey";
645		case HP_StreamName: return "StreamName";
646		case HP_StreamDataLength: return "StreamDataLength";
647
648		case HP_ErrorReport: return "ErrorReport";
649		case HP_IOReadTimeOut: return "IOReadTimeOut";
650
651		case HP_WritingMode: return "WritingMode";
652
653		case HP_VUExtension: return "VUExtension";
654		case HP_VUDataLength: return "VUDataLength";
655
656		case HP_VUAttr1: return "VUAttr1";
657		case HP_VUAttr2: return "VUAttr2";
658		case HP_VUAttr3: return "VUAttr3";
659		case HP_VUAttr4: return "VUAttr4";
660		case HP_VUAttr5: return "VUAttr5";
661		case HP_VUAttr6: return "VUAttr6";
662		case HP_VUAttr7: return "VUAttr7";
663		case HP_VUAttr8: return "VUAttr8";
664		case HP_VUAttr9: return "VUAttr9";
665		case HP_VUAttr10: return "VUAttr10";
666		case HP_VUAttr11: return "VUAttr11";
667		case HP_VUAttr12: return "VUAttr12";
668
669//		case HP_PassThroughCommand: return "PassThroughCommand";
670		case HP_PassThroughArray: return "PassThroughArray";
671		case HP_Diagnostics: return "Diagnostics";
672		case HP_CharAngle: return "CharAngle";
673		case HP_CharCode: return "CharCode";
674		case HP_CharDataSize: return "CharDataSize";
675		case HP_CharScale: return "CharScale";
676		case HP_CharShear: return "CharShear";
677		case HP_CharSize: return "CharSize";
678		case HP_FontHeaderLength: return "FontHeaderLength";
679		case HP_FontName: return "FontName";
680		case HP_FontFormat: return "FontFormat";
681		case HP_SymbolSet: return "SymbolSet";
682		case HP_TextData: return "TextData";
683		case HP_CharSubModeArray: return "CharSubModeArray";
684//		case HP_WritingMode: return "WritingMode";
685		case HP_BitmapCharScale: return "BitmapCharScale";
686		case HP_XSpacingData: return "XSpacingData";
687		case HP_YSpacingData: return "YSpacingData";
688		case HP_CharBoldValue: return "CharBoldValue";
689	}
690	return "Unknown Attribute";
691}
692
693
694static AttrValue gEnableEnum[] = {
695	{HP_eOn, "eOn"},
696	{HP_eOff, "eOff"}
697};
698
699static AttrValue gBooleanEnum[] = {
700	{HP_eFalse, "eFalse"},
701	{HP_eTrue, "eTrue"}
702};
703
704static AttrValue gWriteEnum[] = {
705	{HP_eWriteHorizontal, "eWriteHorizontal"},
706	{HP_eWriteVertical, "eWriteVertical"}
707};
708
709
710static AttrValue gBitmapCharScalingEnum[] = {
711	{HP_eDisable, "eDisable"},
712	{HP_eEnable, "eEnable"}
713};
714
715static AttrValue gUnitOfMeasureEnum[] = {
716	{HP_eInch, "eInch"},
717	{HP_eMillimeter, "eMillimeter"},
718	{HP_eTenthsOfAMillimeter, "eTenthsOfAMillimeter"}
719};
720
721static AttrValue gErrorReportingEnum[] = {
722	{HP_eNoReporting, "eNoReporting"},
723	{HP_eBackChannel, "eBackChannel"},
724	{HP_eErrorPage, "eErrorPage"},
725	{HP_eBackChAndErrPage, "eBackChAndErrPage"},
726	{HP_eBackChanAndErrPage, "eBackChanAndErrPage"},
727	{HP_eNWBackChannel, "eNWBackChannel"},
728	{HP_eNWErrorPage, "eNWErrorPage"},
729	{HP_eNWBackChAndErrPage, "eNWBackChAndErrPage"}
730};
731
732static AttrValue gDataOrganizationEnum[] = {
733	 {HP_eBinaryHighByteFirst, "eBinaryHighByteFirst"},
734	 {HP_eBinaryLowByteFirst, "eBinaryLowByteFirst"}
735};
736
737static AttrValue gDuplexPageModeEnum[] = {
738	 {HP_eDuplexHorizontalBinding, "eDuplexHorizontalBinding"},
739	 {HP_eDuplexVerticalBinding, "eDuplexVerticalBinding"}
740};
741
742static AttrValue gDuplexPageSideEnum[] = {
743	 {HP_eFrontMediaSide, "eFrontMediaSide"},
744	 {HP_eBackMediaSide, "eBackMediaSide"}
745};
746
747static AttrValue gSimplexPageModeEnum[] = {
748	 {HP_eSimplexFrontSide, "eSimplexFrontSide"}
749};
750
751static AttrValue gOrientationEnum[] = {
752	 {HP_ePortraitOrientation, "ePortraitOrientation"},
753	 {HP_eLandscapeOrientation, "eLandscapeOrientation"},
754	 {HP_eReversePortrait, "eReversePortrait"},
755	 {HP_eReverseLandscape, "eReverseLandscape"}
756};
757
758static AttrValue gMediaSizeEnum[] = {
759	 {HP_eLetterPaper, "eLetterPaper"},
760	 {HP_eLegalPaper, "eLegalPaper"},
761	 {HP_eA4Paper, "eA4Paper"},
762	 {HP_eExecPaper, "eExecPaper"},
763	 {HP_eLedgerPaper, "eLedgerPaper"},
764	 {HP_eA3Paper, "eA3Paper"},
765	 {HP_eCOM10Envelope, "eCOM10Envelope"},
766	 {HP_eMonarchEnvelope, "eMonarchEnvelope"},
767	 {HP_eC5Envelope, "eC5Envelope"},
768	 {HP_eDLEnvelope, "eDLEnvelope"},
769	 {HP_eJB4Paper, "eJB4Paper"},
770	 {HP_eJB5Paper, "eJB5Paper"},
771	 {HP_eB5Envelope, "eB5Envelope"},
772	 {HP_eB5Paper, "eB5Paper"},
773	 {HP_eJPostcard, "eJPostcard"},
774	 {HP_eJDoublePostcard, "eJDoublePostcard"},
775	 {HP_eA5Paper, "eA5Paper"},
776	 {HP_eA6Paper, "eA6Paper"},
777	 {HP_eJB6Paper, "eJB6Paper"},
778	 {HP_eJIS8KPaper, "eJIS8KPaper"},
779	 {HP_eJIS16KPaper, "eJIS16KPaper"},
780	 {HP_eJISExecPaper, "eJISExecPaper"}
781};
782
783static AttrValue gMediaSourceEnum[] = {
784	 {HP_eDefaultSource, "eDefaultSource"},
785	 {HP_eAutoSelect, "eAutoSelect"},
786	 {HP_eManualFeed, "eManualFeed"},
787	 {HP_eMultiPurposeTray, "eMultiPurposeTray"},
788	 {HP_eUpperCassette, "eUpperCassette"},
789	 {HP_eLowerCassette, "eLowerCassette"},
790	 {HP_eEnvelopeTray, "eEnvelopeTray"},
791	 {HP_eThirdCassette, "eThirdCassette"}
792};
793
794static AttrValue gMediaDestinationEnum[] = {
795	 {HP_eDefaultBin, "eDefaultBin"},
796	 {HP_eFaceDownBin, "eFaceDownBin"},
797	 {HP_eFaceUpBin, "eFaceUpBin"},
798	 {HP_eJobOffsetBin, "eJobOffsetBin"}
799};
800
801static AttrValue gCompressionEnum[] = {
802	 {HP_eNoCompression, "eNoCompression"},
803	 {HP_eRLECompression, "eRLECompression"},
804	 {HP_eJPEGCompression, "eJPEGCompression"},
805	 {HP_eDeltaRowCompression, "eDeltaRowCompression"}
806};
807
808static AttrValue gArcDirectionEnum[] = {
809	 {HP_eClockWise, "eClockWise"},
810	 {HP_eCounterClockWise, "eCounterClockWise"}
811};
812
813static AttrValue gFillModeEnum[] = {
814	 {HP_eNonZeroWinding, "eNonZeroWinding"},
815	 {HP_eEvenOdd, "eEvenOdd"}
816};
817
818static AttrValue gLineEndEnum[] = {
819	 {HP_eButtCap, "eButtCap"},
820	 {HP_eRoundCap, "eRoundCap"},
821	 {HP_eSquareCap, "eSquareCap"},
822	 {HP_eTriangleCap, "eTriangleCap"}
823//	 {HP_eButtEnd, "eButtEnd"},
824//	 {HP_eRoundEnd, "eRoundEnd"},
825//	 {HP_eSquareEnd, "eSquareEnd"},
826//	 {HP_eTriangleEnd, "eTriangleEnd"}
827};
828
829static AttrValue gCharSubModeEnum[] = {
830	 {HP_eNoSubstitution, "eNoSubstitution"},
831	 {HP_eVerticalSubstitution, "eVerticalSubstitution"}
832};
833
834static AttrValue gLineJoinEnum[] = {
835	 {HP_eMiterJoin, "eMiterJoin"},
836	 {HP_eRoundJoin, "eRoundJoin"},
837	 {HP_eBevelJoin, "eBevelJoin"},
838	 {HP_eNoJoin, "eNoJoin"}
839};
840
841static AttrValue gDitherMatrixEnum[] = {
842	 {HP_eDeviceBest, "eDeviceBest"},
843	 {HP_eDeviceIndependent, "eDeviceIndependent"}
844};
845
846static AttrValue gDataSourceEnum[] = {
847	 {HP_eDefaultDataSource, "eDefaultDataSource"}
848};
849
850static AttrValue gColorSpaceEnum[] = {
851	 {HP_eBiLevel, "eBiLevel"},
852	 {HP_eGray, "eGray"},
853	 {HP_eRGB, "eRGB"},
854	 {HP_eCMY, "eCMY"},
855	 {HP_eCIELab, "eCIELab"},
856	 {HP_eCRGB, "eCRGB"},
857	 {HP_eSRGB, "eSRGB"}
858};
859
860static AttrValue gColorDepthEnum[] = {
861	 {HP_e1Bit, "e1Bit"},
862	 {HP_e4Bit, "e4Bit"},
863	 {HP_e8Bit, "e8Bit"}
864};
865
866static AttrValue gColorMappingEnum[] = {
867	 {HP_eDirectPixel, "eDirectPixel"},
868	 {HP_eIndexedPixel, "eIndexedPixel"},
869	 {HP_eDirectPlane, "eDirectPlane"}
870};
871
872static AttrValue gDiagnosticEnum[] = {
873	 {HP_eNoDiag, "eNoDiag"},
874	 {HP_eFilterDiag, "eFilterDiag"},
875	 {HP_eCommandsDiag, "eCommandsDiag"},
876	 {HP_ePersonalityDiag, "ePersonalityDiag"},
877	 {HP_ePageDiag, "ePageDiag"}
878};
879
880static AttrValue gClipModeEnum[] = {
881	 {HP_eInterior, "eInterior"},
882	 {HP_eExterior, "eExterior"}
883};
884
885static AttrValue gDataTypeEnum[] = {
886	 {HP_eUByte, "eUByte"},
887	 {HP_eSByte, "eSByte"},
888	 {HP_eUInt16, "eUInt16"},
889	 {HP_eSInt16, "eSInt16"},
890	 {HP_eReal32, "eReal32"}
891};
892
893static AttrValue gPatternPersistenceEnum[] = {
894	 {HP_eTempPattern, "eTempPattern"},
895	 {HP_ePagePattern, "ePagePattern"},
896	 {HP_eSessionPattern, "eSessionPattern"}
897};
898
899static AttrValue gTransparancyEnum[] = {
900	 {HP_eOpaque, "eOpaque"},
901	 {HP_eTransparent, "eTransparent"}
902};
903
904static AttrValue gFormTypeEnum[] = {
905	 {HP_eQuality, "eQuality"},
906	 {HP_ePerformance, "ePerformance"},
907	 {HP_eStatic, "eStatic"},
908	 {HP_eBackground, "eBackground"}
909};
910
911static AttrValue gColorEnum[] = {
912	 {HP_eNoTreatment, "eNoTreatment"},
913	 {HP_eVivid, "eVivid"},
914	 {HP_eScreenMatch, "eScreenMatch"}
915};
916
917void Disasm::PrintAttributeValue(uint8 id, const AttrValue* table, int size) {
918	if (NumOfArgs() == 1 && ArgAt(0)->Type == HP_UByteData) {
919		uint8 value = ArgAt(0)->val.ubyte;
920		for (int i = 0; i < size; i ++, table ++) {
921			if (table->value == value) {
922				if (fVerbose) PrintAttr(ArgAt(0));
923				printf("%s %s\n", table->name, AttributeName(id));
924				return;
925			}
926		}
927	}
928	GenericPrintAttribute(id);
929}
930
931void Disasm::GenericPrintAttribute(uint8 id) {
932	for (int i = 0; i < NumOfArgs(); i ++) {
933		PrintAttr(ArgAt(i));
934	}
935	printf(" %s\n", AttributeName(id));
936}
937
938#define ATTR_ENUM(name) name, NUM_OF_ELEMS(name, AttrValue)
939
940bool Disasm::DecodeAttribute(uint8 byte) {
941	if (byte == HP_8BitAttrId) {
942		uint8 id;
943		if (!fStream->ReadUByte(id)) {
944			Error("Could not read attribute id");
945			return false;
946		}
947		switch (id) {
948			case HP_ArcDirection:
949				PrintAttributeValue(id, ATTR_ENUM(gArcDirectionEnum));
950				break;
951			case HP_CharSubModeArray:
952				PrintAttributeValue(id, ATTR_ENUM(gCharSubModeEnum));
953				break;
954			case HP_ClipMode:
955				PrintAttributeValue(id, ATTR_ENUM(gClipModeEnum));
956				break;
957			case HP_ClipRegion:
958				PrintAttributeValue(id, ATTR_ENUM(gClipModeEnum));
959				break;
960			case HP_ColorDepth:
961				PrintAttributeValue(id, ATTR_ENUM(gColorDepthEnum));
962				break;
963			case HP_ColorMapping:
964				PrintAttributeValue(id, ATTR_ENUM(gColorMappingEnum));
965				break;
966			case HP_ColorSpace:
967				PrintAttributeValue(id, ATTR_ENUM(gColorSpaceEnum));
968				break;
969			case HP_CompressMode:
970				PrintAttributeValue(id, ATTR_ENUM(gCompressionEnum));
971				break;
972			case HP_DataOrg:
973				PrintAttributeValue(id, ATTR_ENUM(gDataOrganizationEnum));
974				break;
975			case HP_SourceType:
976				PrintAttributeValue(id, ATTR_ENUM(gDataSourceEnum));
977				break;
978			// DataType?
979			case HP_DitherMatrixDataType:
980				PrintAttributeValue(id, ATTR_ENUM(gDataTypeEnum));
981				break;
982			case HP_DuplexPageMode:
983				PrintAttributeValue(id, ATTR_ENUM(gDuplexPageModeEnum));
984				break;
985			case HP_DuplexPageSide:
986				PrintAttributeValue(id, ATTR_ENUM(gDuplexPageSideEnum));
987				break;
988			case HP_ErrorReport:
989				PrintAttributeValue(id, ATTR_ENUM(gErrorReportingEnum));
990				break;
991			case HP_FillMode:
992				PrintAttributeValue(id, ATTR_ENUM(gFillModeEnum));
993				break;
994			case HP_LineStartCapStyle:
995				PrintAttributeValue(id, ATTR_ENUM(gLineEndEnum));
996				break;
997			case HP_LineEndCapStyle:
998				PrintAttributeValue(id, ATTR_ENUM(gLineEndEnum));
999				break;
1000			case HP_LineJoinStyle:
1001				PrintAttributeValue(id, ATTR_ENUM(gLineJoinEnum));
1002				break;
1003			case HP_Measure:
1004				PrintAttributeValue(id, ATTR_ENUM(gUnitOfMeasureEnum));
1005				break;
1006			case HP_MediaSize:
1007				PrintAttributeValue(id, ATTR_ENUM(gMediaSizeEnum));
1008				break;
1009			case HP_MediaSource:
1010				PrintAttributeValue(id, ATTR_ENUM(gMediaSourceEnum));
1011				break;
1012			case HP_MediaDest:
1013				PrintAttributeValue(id, ATTR_ENUM(gMediaDestinationEnum));
1014				break;
1015			case HP_Orientation:
1016				PrintAttributeValue(id, ATTR_ENUM(gOrientationEnum));
1017				break;
1018			case HP_PatternPersistence:
1019				PrintAttributeValue(id, ATTR_ENUM(gPatternPersistenceEnum));
1020				break;
1021			// Symbolset?
1022			case HP_SimplexPageMode:
1023				PrintAttributeValue(id, ATTR_ENUM(gSimplexPageModeEnum));
1024				break;
1025			case HP_TxMode:
1026				PrintAttributeValue(id, ATTR_ENUM(gTransparancyEnum));
1027				break;
1028			case HP_WritingMode:
1029				PrintAttributeValue(id, ATTR_ENUM(gWriteEnum));
1030				break;
1031			case HP_FormType:
1032				PrintAttributeValue(id, ATTR_ENUM(gFormTypeEnum));
1033				break;
1034			case HP_LineCapStyle:
1035				PrintAttributeValue(id, ATTR_ENUM(gLineEndEnum));
1036				break;
1037			case HP_Diagnostics:
1038				PrintAttributeValue(id, ATTR_ENUM(gDiagnosticEnum));
1039				break;
1040
1041			case HP_MediaType:
1042			case HP_UnitsPerMeasure:
1043			case HP_CMYColor:
1044			case HP_PaletteDepth:
1045			case HP_NullBrush:
1046			case HP_NullPen:
1047			case HP_PaletteData:
1048			case HP_PaletteIndex:
1049			case HP_PatternSelectID:
1050			case HP_GrayLevel:
1051
1052			case HP_RGBColor:
1053			case HP_PatternOrigin:
1054			case HP_NewDestinationSize:
1055
1056			case HP_PrimaryArray:
1057			case HP_PrimaryDepth:
1058			case HP_ColorimetricColorSpace:
1059			case HP_XYChromaticities:
1060			case HP_WhitePointReference:
1061			case HP_CRGBMinMax:
1062			case HP_GammaGain:
1063
1064
1065			case HP_DeviceMatrix:
1066			case HP_DitherOrigin:
1067			case HP_PageAngle:
1068			case HP_PageOrigin:
1069			case HP_PageScale:
1070			case HP_ROP3:
1071			case HP_CustomMediaSize:
1072			case HP_CustomMediaSizeUnits:
1073			case HP_PageCopies:
1074			case HP_DitherMatrixSize:
1075			case HP_DitherMatrixDepth:
1076
1077			case HP_BoundingBox:
1078			case HP_DashOffset:
1079			case HP_EllipseDimension:
1080			case HP_EndPoint:
1081			case HP_MiterLength:
1082			case HP_LineDashStyle:
1083			case HP_PenWidth:
1084			case HP_Point:
1085			case HP_NumberOfPoints:
1086			case HP_SolidLine:
1087			case HP_StartPoint:
1088			case HP_PointType:
1089			case HP_ControlPoint1:
1090			case HP_ControlPoint2:
1091
1092
1093			case HP_ColorDepthArray:
1094			case HP_BlockHeight:
1095			case HP_DestinationBox:
1096			case HP_DestinationSize:
1097			case HP_PatternDefineID:
1098			case HP_SourceHeight:
1099			case HP_SourceWidth:
1100			case HP_StartLine:
1101			case HP_PadBytesMultiple:
1102			case HP_BlockByteLength:
1103			case HP_NumberOfScanLines:
1104
1105			case HP_ColorTreatment:
1106			case HP_FileName:
1107			case HP_BackgroundName:
1108			case HP_FormName:
1109			case HP_FormSize:
1110			case HP_UDLCName:
1111
1112			case HP_CommentData:
1113			case HP_QueryKey:
1114			case HP_StreamName:
1115			case HP_StreamDataLength:
1116
1117			case HP_IOReadTimeOut:
1118
1119
1120/* Generic VI attributes */
1121
1122			case HP_VUExtension:
1123			case HP_VUDataLength:
1124
1125			case HP_VUAttr1:
1126			case HP_VUAttr2:
1127			case HP_VUAttr3:
1128			case HP_VUAttr4:
1129			case HP_VUAttr5:
1130			case HP_VUAttr6:
1131			case HP_VUAttr7:
1132			case HP_VUAttr8:
1133			case HP_VUAttr9:
1134			case HP_VUAttr10:
1135			case HP_VUAttr11:
1136			case HP_VUAttr12:
1137
1138//			case HP_PassThroughCommand:
1139			case HP_PassThroughArray:
1140			case HP_CharAngle:
1141			case HP_CharCode:
1142			case HP_CharDataSize:
1143			case HP_CharScale:
1144			case HP_CharShear:
1145			case HP_CharSize:
1146			case HP_FontHeaderLength:
1147			case HP_FontName:
1148			case HP_FontFormat:
1149			case HP_SymbolSet:
1150			case HP_TextData:
1151//			case HP_WritingMode:
1152			case HP_BitmapCharScale:
1153			case HP_XSpacingData:
1154			case HP_YSpacingData:
1155			case HP_CharBoldValue:
1156				GenericPrintAttribute(id);
1157				break;
1158			default:
1159				fprintf(stderr, "Unsupported attribute id %d %2.2x\nContinue...\n", (int)id, (int)id);
1160		}
1161		return true;
1162	} else {
1163		fprintf(stderr, "Unsupported attribute tag %d %2.2x\n", (int)byte, (int)byte);
1164	}
1165	return false;
1166}
1167
1168bool Disasm::DecodeEmbedData(uint8 byte) {
1169	uint32 length;
1170	if (byte == HP_EmbeddedData) {
1171		if (!fStream->ReadUInt32(length)) {
1172			Error("Could not read length of dataLength");
1173			return false;
1174		}
1175	} else {
1176		uint8 type;
1177		if (!fStream->ReadUByte(type)) {
1178			Error("Could not read type tag of length of dataLengthByte");
1179			return false;
1180		}
1181		struct ATTRIBUTE* attr = ReadData(type);
1182		if (attr == NULL) {
1183			Error("Could not read length of dataLengthByte");
1184			return false;
1185		}
1186		if (attr->Type == HP_UByteData) {
1187			length = attr->val.ubyte;
1188		} else if (attr->Type == HP_UInt32Data) {
1189			length = attr->val.uint32;
1190		} else {
1191			fprintf(stderr, "Unsupported datatype %d %x for embed data\n", (int)type, (int)type);
1192			DeleteAttr(attr); return false;
1193		}
1194		DeleteAttr(attr);
1195	}
1196	if (byte == HP_EmbeddedData) {
1197		printf("dataLength");
1198	} else if (byte == HP_EmbeddedDataByte) {
1199		printf("dataLengthByte");
1200	}
1201	printf(" size = %u [\n", (unsigned int)length);
1202	for (uint32 i = 0; i < length; i ++) {
1203		if (i > 0 && i % 16 == 15) printf("\n");
1204		uint8 data;
1205		if (!fStream->ReadUByte(data)) {
1206			Error("Out of data for dataLength[Byte]\n");
1207			return false;
1208		}
1209		printf("%2.2x ", (int)data);
1210	}
1211	printf("\n]\n");
1212	return true;
1213}
1214
1215bool Disasm::ParsePCL6() {
1216	uint8 byte;
1217	while (fStream->ReadUByte(byte)) {
1218		if (IsOperator(byte)) {
1219			if (!DecodeOperator(byte)) return false;
1220		} else if (IsDataType(byte)) {
1221			if (!PushData(byte)) return false;
1222		} else if (IsAttribute(byte)) {
1223			bool ok = DecodeAttribute(byte);
1224			ClearAttrs();
1225			if (!ok) return false;
1226		} else if (IsEmbedData(byte)) {
1227			if (!DecodeEmbedData(byte)) return false;
1228		} else if (IsWhiteSpace(byte)) {
1229			// nothing to do
1230		} else if (IsEsc(byte)) {
1231			return true;
1232		} else {
1233			Error("Unknown byte in input stream");
1234			return false;
1235		}
1236	}
1237	return true;
1238}
1239
1240// main entry
1241
1242int main(int argc, char* argv[]) {
1243	const char* program = argv[0];
1244	if (argc >= 2) {
1245		int i = 1;
1246		bool verbose = false;
1247		if (strcmp(argv[1], "-v") == 0) { verbose = true; i ++; }
1248		if (argc > i) {
1249			const char* filename = argv[i];
1250			File file(filename);
1251			if (file.InitCheck()) {
1252				Disasm disasm(&file);
1253				disasm.SetVerbose(verbose);
1254				disasm.Print();
1255				return 0;
1256			} else {
1257				fprintf(stderr, "%s error: could not open file '%s'\n", program, filename);
1258				return 0;
1259			}
1260		}
1261	}
1262	fprintf(stderr, "%s [-v] pcl6_filename\n", program);
1263}
1264