parse.c 52.3 KB
Newer Older
Bernhard Link's avatar
Bernhard Link committed
1
/*  This file is part of "xtrace"
2
 *  Copyright (C) 2005,2006,2009,2010,2011 Bernhard R. Link
Bernhard Link's avatar
Bernhard Link committed
3
 *  This program is free software; you can redistribute it and/or modify
4 5
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
Bernhard Link's avatar
Bernhard Link committed
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <config.h>

#include <assert.h>
19
#include <stdint.h>
Bernhard Link's avatar
Bernhard Link committed
20
#include <sys/types.h>
21
#include <sys/time.h>
22
#include <limits.h>
Bernhard Link's avatar
Bernhard Link committed
23 24
#include <stdbool.h>
#include <stdint.h>
25
#include <stdarg.h>
Bernhard Link's avatar
Bernhard Link committed
26 27 28 29 30
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <unistd.h>
31 32
#include <time.h>
#include <errno.h>
Bernhard Link's avatar
Bernhard Link committed
33 34

#include "xtrace.h"
35
#include "parse.h"
Bernhard Link's avatar
Bernhard Link committed
36

37 38 39 40
enum package_direction { TO_SERVER, TO_CLIENT };

static void startline(struct connection *c, enum package_direction d, const char *format, ...) FORMAT(printf,3,4);

41 42
const bool print_counts;
const bool print_offsets;
Bernhard Link's avatar
Bernhard Link committed
43 44 45 46 47

static inline unsigned int padded(unsigned int s) {
	return (s+3)&(~3);
}

48 49
static void startline(struct connection *c, enum package_direction d, const char *format, ...) {
	va_list ap;
50
	struct timeval tv;
51

52 53 54
	if( (print_timestamps || print_reltimestamps)
			&& gettimeofday(&tv, NULL) == 0 ) {
		if( print_timestamps )
55
			fprintf(out, "%lu.%03u ", (unsigned long)tv.tv_sec,
56 57 58 59
					(unsigned int)(tv.tv_usec/1000));
		if( print_reltimestamps ) {
			unsigned long long tt = ((unsigned long long)1000)*tv.tv_sec +
						(tv.tv_usec/1000);
60
			fprintf(out, "%lu.%03u ",
61 62 63 64
				(unsigned long)((tt - c->starttime)/1000),
				(unsigned int)((tt - c->starttime)%1000));
		}
	}
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#ifdef HAVE_MONOTONIC_CLOCK
	if( print_uptimestamps ) {
		static bool already_warned = false;
		struct timespec ts;
		int i;
		i = clock_gettime(CLOCK_MONOTONIC, &ts);
		if( i == 0 ) {
			fprintf(out, "%lu.%03u ",
					(unsigned long)ts.tv_sec,
					(unsigned int)(ts.tv_nsec/1000000L));
		} else if (!already_warned) {
			int e = errno;
			fprintf(stderr, "Error %d from clock_gettime(CLOCK_MONOTIC,): %s\n",
					e, strerror(e));
			already_warned = true;
		}
	}
#endif
83 84 85 86 87 88
	va_start(ap, format);
	fprintf(out, "%03d:%c:", c->id, (d == TO_SERVER)?'<':'>');
	vfprintf(out, format, ap);
	va_end(ap);
}

89 90 91 92
#define U256 ((unsigned int)256)
#define UL256 ((unsigned long)256)
#define CARD16(bigendian,buffer,ofs) ((bigendian)?(buffer[ofs]*U256+buffer[ofs+1]):(buffer[ofs+1]*U256+buffer[ofs]))
#define CARD32(bigendian,buffer,ofs) ((bigendian)?(((buffer[ofs]*U256+buffer[ofs+1])*UL256+buffer[ofs+2])*UL256+buffer[ofs+3]):(buffer[ofs]+UL256*(buffer[ofs+1]+UL256*(buffer[ofs+2]+U256*buffer[ofs+3]))))
Bernhard Link's avatar
Bernhard Link committed
93 94 95 96 97 98
#define clientCARD32(ofs) CARD32(c->bigendian,c->clientbuffer,ofs)
#define clientCARD16(ofs) CARD16(c->bigendian,c->clientbuffer,ofs)
#define clientCARD8(ofs) c->clientbuffer[ofs]
#define serverCARD32(ofs) CARD32(c->bigendian,c->serverbuffer,ofs)
#define serverCARD16(ofs) CARD16(c->bigendian,c->serverbuffer,ofs)
#define serverCARD8(ofs) c->serverbuffer[ofs]
Bernhard Link's avatar
Bernhard Link committed
99 100
#define getCARD32(ofs) CARD32(c->bigendian,buffer,ofs)
#define getCARD16(ofs) CARD16(c->bigendian,buffer,ofs)
Bernhard Link's avatar
Bernhard Link committed
101
#define getCARD8(ofs) buffer[ofs]
Bernhard Link's avatar
Bernhard Link committed
102
#define getCARD32(ofs) CARD32(c->bigendian,buffer,ofs)
Bernhard Link's avatar
Bernhard Link committed
103

Bernhard Link's avatar
Bernhard Link committed
104
#define getBE32(ofs) (((buffer[ofs]*UL256+buffer[ofs+1])*UL256+buffer[ofs+2])*UL256+buffer[ofs+3])
Bernhard Link's avatar
Bernhard Link committed
105

Bernhard Link's avatar
Bernhard Link committed
106 107 108 109 110 111
struct usedextension {
	struct usedextension *next;
	const struct extension *extension;
	unsigned char major_opcode;
	unsigned char first_event;
	unsigned char first_error;
Bernhard Link's avatar
Bernhard Link committed
112
};
Bernhard Link's avatar
Bernhard Link committed
113

Bernhard Link's avatar
Bernhard Link committed
114 115 116 117 118 119 120 121
void free_usedextensions(struct usedextension *e) {
	while( e != NULL ) {
		struct usedextension *h = e->next;
		free(e);
		e = h;
	}
}

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
struct unknownextension {
	struct unknownextension *next;
	const char *name;
	size_t namelen;
	unsigned char major_opcode;
	unsigned char first_event;
	unsigned char first_error;
};

void free_unknownextensions(struct unknownextension *e) {
	while( e != NULL ) {
		struct unknownextension *h = e->next;
		free(e);
		e = h;
	}
}

static struct unknownextension *register_unknown_extension(struct connection *c, const unsigned char *name, size_t namelen) {
	const struct unknownextension *e;
	struct unknownextension *n;

	for( e = c->unknownextensions ; e != NULL ; e = e->next ) {
		if( e->namelen != namelen )
			continue;
		if( strncmp((char*)name, e->name, namelen) != 0 )
			continue;
		return NULL;
	}
	for( n = c->waiting ; n != NULL ; n = n->next ) {
		if( n->namelen != namelen )
			continue;
		if( strncmp((char*)name, n->name, namelen) != 0 )
			continue;
		return n;
	}
	n = malloc(sizeof(struct unknownextension));
	if( n == NULL )
		abort();
	n->name = strndup((char*)name, namelen);
	if( n->name == NULL )
		abort();
	n->namelen = namelen;
	n->next = c->waiting;
	c->waiting = n;
	return n;
}

Bernhard Link's avatar
Bernhard Link committed
169 170
struct expectedreply {
	struct expectedreply *next;
171
	uint64_t seq;
Bernhard Link's avatar
Bernhard Link committed
172
	const struct request *from;
173 174 175 176
	enum datatype { dt_NONE = 0,
		dt_UNKNOWN_EXTENSION, /* uextension used */
		dt_EXTENSION, /* extension used */
		dt_ATOM, /* atom used */
177
		dt_CARD32, /* card32 used */
178 179 180 181 182 183
	} data_type;
	union {
		void *data;
		struct atom *atom;
		const struct extension *extension;
		struct unknownextension *uextension;
184
		uint32_t card32;
185
	} data;
186
	unsigned long values[];
Bernhard Link's avatar
Bernhard Link committed
187 188
};

189
const struct extension *find_extension(const uint8_t *name,size_t len);
Bernhard Link's avatar
Bernhard Link committed
190

Bernhard Link's avatar
Bernhard Link committed
191 192 193 194 195 196 197
static void print_bitfield(const char *name,const struct constant *constants, unsigned long l){
	const struct constant *c;
	const char *zeroname = "0";
	bool first = true;

	/* bitmasks should have some */
	assert(constants != NULL);
198
	fprintf(out,"%s=",name);
Bernhard Link's avatar
Bernhard Link committed
199 200 201 202 203 204

	for( c = constants; c->name != NULL ; c++ ) {
		if( c->value == 0 )
			zeroname = c->name;
		else if( (l & c->value) != 0 ) {
			if( !first )
205
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
206
			first = false;
207
			fputs(c->name,out);
Bernhard Link's avatar
Bernhard Link committed
208 209 210
		}
	}
	if( first )
211
		fputs(zeroname,out);
Bernhard Link's avatar
Bernhard Link committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
};

static const char *findConstant(const struct constant *constants, unsigned long l){
	const struct constant *c;

	if( constants == NULL )
		return NULL;

	for( c = constants; c->name != NULL ; c++ ) {
		if( c->value == l )
			return c->name;
	}
	return NULL;
};

#define OFS_LATER ((size_t)-1)
Bernhard Link's avatar
Bernhard Link committed
228 229
#define ROUND_32 ((size_t)-1)
#define ROUND { ROUND_32, "", ft_LASTMARKER, NULL}
Bernhard Link's avatar
Bernhard Link committed
230 231


Bernhard Link's avatar
Bernhard Link committed
232
static size_t printSTRING8(const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len,size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
233 234 235 236 237 238 239
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( buflen - ofs <= len )
		len = buflen - ofs;

Bernhard Link's avatar
Bernhard Link committed
240
	if( print_offsets )
241 242
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s='",p->name);
Bernhard Link's avatar
Bernhard Link committed
243 244
	while( len > 0 ) {
		if( nr == maxshownlistlen ) {
245
			fputs("'...",out);
Bernhard Link's avatar
Bernhard Link committed
246
		} else if( nr < maxshownlistlen ) {
Bernhard Link's avatar
Bernhard Link committed
247 248
			unsigned char c = getCARD8(ofs);
			if( c == '\n' ) {
249
				putc('\\',out);putc('n',out);
Bernhard Link's avatar
Bernhard Link committed
250
			} else if( c == '\t' ) {
251
				putc('\\',out);putc('t',out);
Bernhard Link's avatar
Bernhard Link committed
252
			} else if( (c >= ' ' && c <= '~' ) )
253
				putc(c,out);
Bernhard Link's avatar
Bernhard Link committed
254
			else
255
				fprintf(out,"\\%03hho", c);
Bernhard Link's avatar
Bernhard Link committed
256 257 258 259
		}
		ofs++;len--;nr++;
	}
	if( nr <= maxshownlistlen )
260
		putc('\'',out);
Bernhard Link's avatar
Bernhard Link committed
261 262 263
	return ofs;
}

264
static size_t printLISTofCARD8(const uint8_t *buffer, size_t buflen, const char *name, const struct constant *constants, size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
265 266 267 268 269 270 271 272
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( buflen - ofs <= len )
		len = buflen - ofs;

Bernhard Link's avatar
Bernhard Link committed
273
	if( print_offsets )
274
		fprintf(out,"[%d]",(int)ofs);
275
	fprintf(out, "%s=", name);
Bernhard Link's avatar
Bernhard Link committed
276 277 278 279 280
	while( len > 0 ) {
		const char *value;
		unsigned char u8;

		if( nr == maxshownlistlen ) {
281
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
282 283
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
284
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
285 286
			notfirst = true;
			u8 = getCARD8(ofs);
287
			value = findConstant(constants, u8);
Bernhard Link's avatar
Bernhard Link committed
288
			if( value )
289
				fprintf(out,"%s(0x%hhx)",value,u8);
Bernhard Link's avatar
Bernhard Link committed
290
			else
291
				fprintf(out,"0x%02hhx",u8);
Bernhard Link's avatar
Bernhard Link committed
292 293 294
		}
		len--;ofs++;nr++;
	}
295
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
296 297 298
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
299
static size_t printLISTofCARD16(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
300 301 302 303 304 305 306 307
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/2 <= len )
		len = (buflen - ofs)/2;

Bernhard Link's avatar
Bernhard Link committed
308
	if( print_offsets )
309 310
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
311 312
	while( len > 0 ) {
		const char *value;
313
		uint16_t u16;
Bernhard Link's avatar
Bernhard Link committed
314 315

		if( nr == maxshownlistlen ) {
316
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
317 318
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
319
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
320 321
			notfirst = true;
			u16 = getCARD16(ofs);
322
			value = findConstant(p->o.constants, u16);
Bernhard Link's avatar
Bernhard Link committed
323
			if( value )
324
				fprintf(out,"%s(0x%hx)",value,(unsigned short int)u16);
Bernhard Link's avatar
Bernhard Link committed
325
			else
326
				fprintf(out,"0x%04hx",(unsigned short int)u16);
Bernhard Link's avatar
Bernhard Link committed
327 328 329
		}
		len--;ofs+=2;nr++;
	}
330
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
331 332 333
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
334
static size_t printLISTofCARD32(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
335 336 337 338 339 340 341 342
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

Bernhard Link's avatar
Bernhard Link committed
343
	if( print_offsets )
344 345
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
346 347
	while( len > 0 ) {
		const char *value;
348
		uint32_t u32;
Bernhard Link's avatar
Bernhard Link committed
349 350

		if( nr == maxshownlistlen ) {
351
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
352 353
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
354
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
355 356
			notfirst = true;
			u32 = getCARD32(ofs);
357
			value = findConstant(p->o.constants, u32);
Bernhard Link's avatar
Bernhard Link committed
358
			if( value )
359
				fprintf(out,"%s(0x%x)",value,(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
360
			else
361
				fprintf(out,"0x%08x",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
362 363 364
		}
		len--;ofs+=4;nr++;
	}
365
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
366 367 368
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
369
static size_t printLISTofFIXED(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
370 371 372 373 374 375 376 377 378 379 380 381
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

	if( print_offsets )
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
	while( len > 0 ) {
382
		int32_t i32;
383 384 385 386 387 388 389 390
		double d;

		if( nr == maxshownlistlen ) {
			fputs(",...",out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',',out);
			notfirst = true;
391 392
			i32 = getCARD32(ofs);
			d = i32 / 65536.0;
393 394 395 396 397 398 399 400
			fprintf(out,"%.6f", d);
		}
		len--;ofs+=4;nr++;
	}
	putc(';',out);
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
static size_t printLISTofFIXED3232(struct connection *c, const uint8_t *buffer, size_t buflen, const struct parameter *p, size_t len, size_t ofs){
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/8 <= len )
		len = (buflen - ofs)/8;

	if( print_offsets )
		fprintf(out,"[%d]", (int)ofs);
	fprintf(out, "%s=", p->name);
	while( len > 0 ) {
		int32_t i32;
		uint32_t u32;
		double d;

		if( nr == maxshownlistlen ) {
			fputs(",...", out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',', out);
			notfirst = true;
			i32 = getCARD32(ofs);
			u32 = getCARD32(ofs + 4);
			d = i32 + (u32 / ((double)65536.0 * (double)65536.0)) ;
			fprintf(out, "%.11f", d);
		}
		len--; ofs += 8; nr++;
	}
	putc(';', out);
	return ofs;
}


436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
static size_t printLISTofFLOAT32(struct connection *c, const uint8_t *buffer, size_t buflen, const struct parameter *p, size_t len, size_t ofs){
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

	if( print_offsets )
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
	while( len > 0 ) {
		uint32_t u32;
		float f;

		if( nr == maxshownlistlen ) {
			fputs(",...",out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',',out);
			notfirst = true;
			u32 = getCARD32(ofs);
			memcpy(&f, &u32, 4);
			fprintf(out, "%f", f);
		}
		len--;ofs+=4;nr++;
	}
	putc(';',out);
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
468
static size_t printLISTofATOM(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
469 470 471 472 473 474 475 476 477
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

	if( print_offsets )
478 479
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
480 481
	while( len > 0 ) {
		const char *value;
482
		uint32_t u32;
Bernhard Link's avatar
Bernhard Link committed
483 484

		if( nr == maxshownlistlen ) {
485
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
486 487
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
488
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
489 490
			notfirst = true;
			u32 = getCARD32(ofs);
491
			value = findConstant(p->o.constants, u32);
Bernhard Link's avatar
Bernhard Link committed
492
			if( value )
493
				fprintf(out,"%s(0x%x)",value,(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
494
			else if( (value = getAtom(c,u32)) == NULL )
495
				fprintf(out,"0x%x",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
496
			else
497
				fprintf(out,"0x%x(\"%s\")",(unsigned int)u32,value);
Bernhard Link's avatar
Bernhard Link committed
498 499 500
		}
		len--;ofs+=4;nr++;
	}
501
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
502 503 504
	return ofs;
}

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
static size_t printLISTofINT8(const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( buflen - ofs <= len )
		len = buflen - ofs;

	if( print_offsets )
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
	while( len > 0 ) {
		const char *value;
		signed char i8;

		if( nr == maxshownlistlen ) {
			fputs(",...",out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',',out);
			notfirst = true;
			i8 = getCARD8(ofs);
528
			value = findConstant(p->o.constants, i8);
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
			if( value )
				fprintf(out,"%s(%d)",value,(int)i8);
			else
				fprintf(out,"%d",(int)i8);
		}
		len--;ofs++;nr++;
	}
	putc(';',out);
	return ofs;
}

static size_t printLISTofINT16(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/2 <= len )
		len = (buflen - ofs)/2;

	if( print_offsets )
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
	while( len > 0 ) {
		const char *value;
		int16_t i16;

		if( nr == maxshownlistlen ) {
			fputs(",...",out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',',out);
			notfirst = true;
			i16 = getCARD16(ofs);
563
			value = findConstant(p->o.constants, i16);
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
			if( value )
				fprintf(out,"%s(%d)",value,(int)i16);
			else
				fprintf(out,"%d",(int)i16);
		}
		len--;ofs+=2;nr++;
	}
	putc(';',out);
	return ofs;
}

static size_t printLISTofINT32(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

	if( print_offsets )
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
	while( len > 0 ) {
		const char *value;
		int32_t i32;

		if( nr == maxshownlistlen ) {
			fputs(",...",out);
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
				putc(',',out);
			notfirst = true;
			i32 = getCARD32(ofs);
598
			value = findConstant(p->o.constants, i32);
599 600 601 602 603 604 605 606 607 608 609
			if( value )
				fprintf(out,"%s(%d)",value,(int)i32);
			else
				fprintf(out,"%d",(int)i32);
		}
		len--;ofs+=4;nr++;
	}
	putc(';',out);
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
610
static size_t printLISTofUINT8(const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
611 612 613 614 615 616 617 618 619
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( buflen - ofs <= len )
		len = buflen - ofs;

	if( print_offsets )
620 621
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
622 623 624 625 626
	while( len > 0 ) {
		const char *value;
		unsigned char u8;

		if( nr == maxshownlistlen ) {
627
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
628 629
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
630
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
631 632
			notfirst = true;
			u8 = getCARD8(ofs);
633
			value = findConstant(p->o.constants, u8);
Bernhard Link's avatar
Bernhard Link committed
634
			if( value )
635
				fprintf(out,"%s(%u)",value,(unsigned int)u8);
Bernhard Link's avatar
Bernhard Link committed
636
			else
637
				fprintf(out,"%u",(unsigned int)u8);
Bernhard Link's avatar
Bernhard Link committed
638 639 640
		}
		len--;ofs++;nr++;
	}
641
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
642 643 644
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
645
static size_t printLISTofUINT16(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
646 647 648 649 650 651 652 653 654
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/2 <= len )
		len = (buflen - ofs)/2;

	if( print_offsets )
655 656
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
657 658
	while( len > 0 ) {
		const char *value;
659
		uint16_t u16;
Bernhard Link's avatar
Bernhard Link committed
660 661

		if( nr == maxshownlistlen ) {
662
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
663 664
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
665
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
666 667
			notfirst = true;
			u16 = getCARD16(ofs);
668
			value = findConstant(p->o.constants, u16);
Bernhard Link's avatar
Bernhard Link committed
669
			if( value )
670
				fprintf(out,"%s(%u)",value,(unsigned int)u16);
Bernhard Link's avatar
Bernhard Link committed
671
			else
672
				fprintf(out,"%u",(unsigned int)u16);
Bernhard Link's avatar
Bernhard Link committed
673 674 675
		}
		len--;ofs+=2;nr++;
	}
676
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
677 678 679
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
680
static size_t printLISTofUINT32(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
681 682 683 684 685 686 687 688 689
	bool notfirst = false;
	size_t nr = 0;

	if( buflen < ofs )
		return ofs;
	if( (buflen - ofs)/4 <= len )
		len = (buflen - ofs)/4;

	if( print_offsets )
690 691
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
692 693
	while( len > 0 ) {
		const char *value;
694
		uint32_t u32;
Bernhard Link's avatar
Bernhard Link committed
695 696

		if( nr == maxshownlistlen ) {
697
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
698 699
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
700
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
701 702
			notfirst = true;
			u32 = getCARD32(ofs);
703
			value = findConstant(p->o.constants, u32);
Bernhard Link's avatar
Bernhard Link committed
704
			if( value )
705
				fprintf(out,"%s(%u)",value,(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
706
			else
707
				fprintf(out,"%u",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
708 709 710
		}
		len--;ofs+=4;nr++;
	}
711
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
712 713 714
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
715
static size_t printLISTofVALUE(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *param,unsigned long valuemask, size_t ofs){
Bernhard Link's avatar
Bernhard Link committed
716

717
	const struct value *v = param->o.values;
Bernhard Link's avatar
Bernhard Link committed
718
	const char *atom;
Bernhard Link's avatar
Bernhard Link committed
719 720 721 722 723 724
	bool notfirst = false;

	assert( v != NULL );

	if( ofs > buflen )
		return ofs;
Bernhard Link's avatar
Bernhard Link committed
725
	if( print_offsets )
726 727
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s={",param->name);
Bernhard Link's avatar
Bernhard Link committed
728
	while( buflen > ofs && buflen-ofs >= 4 ) {
729
		uint32_t u32; uint16_t u16; uint8_t u8;
Bernhard Link's avatar
Bernhard Link committed
730
		int32_t i32; int16_t i16; int8_t i8;
Bernhard Link's avatar
Bernhard Link committed
731 732 733 734 735 736 737 738 739
		const char *constant;

		if( v->name == NULL ) /* EOV */
			break;
		if( (valuemask & v->flag) == 0 ) {
			v++;
			continue;
		}
		if( notfirst )
740
			putc(' ',out);
Bernhard Link's avatar
Bernhard Link committed
741 742
		notfirst = true;
		/* this is funny, but that is the protocol... */
Bernhard Link's avatar
Bernhard Link committed
743 744 745
		u32 = getCARD32(ofs); i32 = u32;
		u16 = u32 & 65535; i16 = u16;
		u8 = u32 & 255; i8 = u8;
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
		if( v->type == ft_INT32_32 ) {
			long long ll;

			/* XSync suddenly has 64 bit values allowed in
			 * VALUES... */
			if( buflen-ofs < 8 ) {
				c++;
				continue;
			}
			u32 = getCARD32(ofs + 4);
			ll = (((long long)i32)<< 32LL) + (long long)u32;
			fprintf(out, "%s=%lld", v->name, ll);
			ofs += 8;v++;
			continue;
		}
Bernhard Link's avatar
Bernhard Link committed
761 762 763 764 765 766
		if( v->type >= ft_BITMASK8 ) {
			assert(v->type <= ft_BITMASK32 );
			print_bitfield(v->name,v->constants,u32);
			ofs += 4;v++;
			continue;
		}
Bernhard Link's avatar
Bernhard Link committed
767 768
		assert( v->type < ft_STORE8 || v->type == ft_ATOM );
		switch( (v->type==ft_ATOM)?2:(v->type % 3) ) {
Bernhard Link's avatar
Bernhard Link committed
769 770 771 772 773 774 775 776 777 778
		 case 0:
			constant = findConstant(v->constants,u8);
			break;
		 case 1:
			constant = findConstant(v->constants,u16);
			break;
		 default:
			constant = findConstant(v->constants,u32);
			break;
		}
779
		fputs(v->name,out);putc('=',out);
Bernhard Link's avatar
Bernhard Link committed
780
		if( constant != NULL ) {
781 782
			fputs(constant,out);
			putc('(',out);
Bernhard Link's avatar
Bernhard Link committed
783 784 785
		}
		switch( v->type ) {
		 case ft_INT8:
786
			 fprintf(out,"%d",(int)i8);
Bernhard Link's avatar
Bernhard Link committed
787 788
			 break;
		 case ft_INT16:
789
			 fprintf(out,"%d",(int)i16);
Bernhard Link's avatar
Bernhard Link committed
790 791
			 break;
		 case ft_INT32:
792
			 fprintf(out,"%d",(int)i32);
Bernhard Link's avatar
Bernhard Link committed
793 794
			 break;
		 case ft_UINT8:
795
			 fprintf(out,"%u",(unsigned int)u8);
Bernhard Link's avatar
Bernhard Link committed
796 797
			 break;
		 case ft_UINT16:
798
			 fprintf(out,"%u",(unsigned int)u16);
Bernhard Link's avatar
Bernhard Link committed
799 800
			 break;
		 case ft_UINT32:
801
			 fprintf(out,"%u",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
802 803 804
			 break;
		 case ft_ENUM8:
			 if( constant == NULL )
805
				 fputs("unknown:",out);
806
			 __attribute__ ((fallthrough));
Bernhard Link's avatar
Bernhard Link committed
807
		 case ft_CARD8:
808
			 fprintf(out,"0x%02x",(unsigned int)u8);
Bernhard Link's avatar
Bernhard Link committed
809 810 811
			 break;
		 case ft_ENUM16:
			 if( constant == NULL )
812
				 fputs("unknown:",out);
813
			 __attribute__ ((fallthrough));
Bernhard Link's avatar
Bernhard Link committed
814
		 case ft_CARD16:
815
			 fprintf(out,"0x%04x",(unsigned int)u16);
Bernhard Link's avatar
Bernhard Link committed
816
			 break;
Bernhard Link's avatar
Bernhard Link committed
817
		 case ft_ATOM:
818
			 fprintf(out,"0x%x",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
819 820
			 atom = getAtom(c, u32);
			 if( atom != NULL )
821
				 fprintf(out,"(\"%s\")", atom);
Bernhard Link's avatar
Bernhard Link committed
822
			 break;
Bernhard Link's avatar
Bernhard Link committed
823 824
		 case ft_ENUM32:
			 if( constant == NULL )
825
				 fputs("unknown:",out);
826
			 __attribute__ ((fallthrough));
Bernhard Link's avatar
Bernhard Link committed
827
		 case ft_CARD32:
828
			 fprintf(out,"0x%08x",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
829 830 831 832 833
			 break;
		 default:
			 assert(0);
		}
		if( constant != NULL ) {
834
			putc(')',out);
Bernhard Link's avatar
Bernhard Link committed
835 836 837
		}
		ofs += 4; v++;
	}
838
	putc('}',out);
Bernhard Link's avatar
Bernhard Link committed
839 840 841 842
	/* TODO: print error if flags left or v!=EOV? */
	return ofs;
}

Bernhard Link's avatar
Bernhard Link committed
843 844 845 846 847 848 849
struct stack {
	unsigned long *base;
	int num;
	int ofs;
};

static unsigned long getFromStack(struct stack *stack, size_t depth) {
850
	assert(stack != NULL && stack->ofs > (int)depth );
Bernhard Link's avatar
Bernhard Link committed
851 852 853 854 855 856 857 858
	return stack->base[stack->ofs - 1 - depth];
}

static void push(struct stack *stack, unsigned long value) {
	stack->base[stack->ofs] = value;
	stack->ofs++;
	assert(stack->ofs<stack->num);
}
Bernhard Link's avatar
Bernhard Link committed
859
static void pop(struct stack *stack UNUSED, struct stack *oldstack UNUSED) {
Bernhard Link's avatar
Bernhard Link committed
860 861
}

862
static size_t print_parameters(struct connection *c, const unsigned char *buffer, unsigned int len, const struct parameter *parameters, bool bigrequest, struct stack *oldstack, bool returnstack);
Bernhard Link's avatar
Bernhard Link committed
863

Bernhard Link's avatar
Bernhard Link committed
864
static size_t printLISTofStruct(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t count, size_t ofs, struct stack *stack){
Bernhard Link's avatar
Bernhard Link committed
865
	bool notfirst = false;
866
	const struct parameter *substruct = p->o.parameters;
Bernhard Link's avatar
Bernhard Link committed
867 868 869 870 871 872 873 874
	size_t len;
	size_t nr = 0;

	/* and the first item includes the length of an item */
	assert( substruct != NULL && substruct->name == NULL && substruct->offse > 0);
	len = substruct->offse;
	substruct++;

Bernhard Link's avatar
Bernhard Link committed
875
	if( print_offsets )
876 877
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
878 879 880
	while( buflen > ofs && buflen-ofs >= len && count > 0) {

		if( nr == maxshownlistlen ) {
881
			fputs(",...",out);
Bernhard Link's avatar
Bernhard Link committed
882 883 884 885 886
			if( len == 0 )
				ofs = SIZE_MAX;
			break;
		} else if( nr < maxshownlistlen ) {
			if( notfirst )
887
				putc(',',out);
Bernhard Link's avatar
Bernhard Link committed
888
			notfirst = true;
889
			putc('{',out);
Bernhard Link's avatar
Bernhard Link committed
890

891 892
			print_parameters(c, buffer+ofs, len, substruct, false,
					stack, false);
Bernhard Link's avatar
Bernhard Link committed
893

894
			putc('}',out);
Bernhard Link's avatar
Bernhard Link committed
895 896 897
		}
		ofs += len; count--; nr++;
	}
898
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
899 900
	return ofs;
}
Bernhard Link's avatar
Bernhard Link committed
901
static size_t printLISTofVarStruct(struct connection *c,const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t count, size_t ofs, struct stack *stack){
Bernhard Link's avatar
Bernhard Link committed
902 903
	bool notfirst = false;
//	size_t ofs = (p->offset<0)?lastofs:p->offset;
904
	const struct parameter *substruct = p->o.parameters;
Bernhard Link's avatar
Bernhard Link committed
905 906 907 908 909 910 911 912
	size_t len;
	size_t nr = 0;

	/* in this case this is only the minimum value */
	assert( substruct != NULL && substruct->name == NULL && substruct->offse > 0);
	len = substruct->offse;
	substruct++;

Bernhard Link's avatar
Bernhard Link committed
913
	if( print_offsets )
914 915
		fprintf(out,"[%d]",(int)ofs);
	fprintf(out,"%s=",p->name);
Bernhard Link's avatar
Bernhard Link committed
916 917 918 919
	while( buflen > ofs && buflen-ofs >= len && count > 0) {
		size_t lentoadd;

		if( nr >= maxshownlistlen ) {
920
			fputs(",...;",out);
Bernhard Link's avatar
Bernhard Link committed
921 922 923 924
			/* there is nothing here to calculate the rest,
			 * so just return the unreachable */
			return SIZE_MAX;
		}
925
		if( notfirst ) {
926
			putc(',',out);
927 928 929
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
		}
Bernhard Link's avatar
Bernhard Link committed
930
		notfirst = true;
931
		putc('{',out);
Bernhard Link's avatar
Bernhard Link committed
932

933 934
		lentoadd = print_parameters(c, buffer+ofs, buflen-ofs,
				substruct, false, stack, false);
Bernhard Link's avatar
Bernhard Link committed
935

936
		putc('}',out);
Bernhard Link's avatar
Bernhard Link committed
937 938
		ofs += lentoadd; count--; nr++;
	}
939
	putc(';',out);
Bernhard Link's avatar
Bernhard Link committed
940 941 942 943
	return ofs;
}

/* buffer must have at least 32 valid bytes */
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
static const struct event *find_event(struct connection *c, const unsigned char *buffe, const char **extension_name);
static void print_event_data(struct connection *c, const unsigned char *buffer, size_t len, const struct event *event, const char *extension);

static inline void print_event(struct connection *c, const unsigned char *buffer, size_t len) {
	const struct event *event;
	const char *name;
	size_t l;

	event = find_event(c, buffer, &name);
	if( event != NULL && event->type == event_xge)
		l = 32 + 4*getCARD32(4);
	else
		l = 32;

	if( len < l ) {
		// TODO: warn about incomplete?
		return;
	}

	print_event_data(c, buffer, l, event, name);
}
Bernhard Link's avatar
Bernhard Link committed
965

966
static size_t print_parameters(struct connection *c, const unsigned char *buffer, unsigned int len, const struct parameter *parameters, bool bigrequest, struct stack *oldstack, bool returnstack) {
Bernhard Link's avatar
Bernhard Link committed
967 968 969
	const struct parameter *p;
	unsigned long stored = INT_MAX;
	unsigned char format = 0;
970
	bool printspace = false;
Bernhard Link's avatar
Bernhard Link committed
971
	size_t lastofs = 0;
Bernhard Link's avatar
Bernhard Link committed
972
	struct stack newstack = *oldstack;
973
	bool sizeset = false;
Bernhard Link's avatar
Bernhard Link committed
974 975

	for( p = parameters; p->name != NULL; p++ ) {
976
		size_t s;
Bernhard Link's avatar
Bernhard Link committed
977
		int8_t i8; int16_t i16; int32_t i32;
Bernhard Link's avatar
Bernhard Link committed
978
		uint32_t uu;
Bernhard Link's avatar
Bernhard Link committed
979
#ifdef STUPIDCC
980
		uint8_t u8=0; uint16_t u16=0; uint32_t u32=0;
Bernhard Link's avatar
Bernhard Link committed
981 982
		unsigned long l=0;
#else
983
		uint8_t u8; uint16_t u16; uint32_t u32;
Bernhard Link's avatar
Bernhard Link committed
984 985 986 987
		unsigned long l;
#endif
		size_t ofs;
		const char *value;
Bernhard Link's avatar
Bernhard Link committed
988
		const char *atom;
989
		double d;
990
		float f;
Bernhard Link's avatar
Bernhard Link committed
991
		long long ll;
Bernhard Link's avatar
Bernhard Link committed
992 993 994 995 996 997 998 999 1000 1001

		if( p->offse == OFS_LATER )
			ofs = lastofs;
		else if( bigrequest && p->offse >= 4 )
			/* jump over 32 bit extended length */
			ofs = p->offse+4;
		else
			ofs = p->offse;

		if( p->type == ft_IF8 ) {
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
			unsigned char v;

			if( p->offse == OFS_LATER )
				v = stored & 0xFF;
			else if( ofs <len )
				v = getCARD8(ofs);
			else
				continue;
			/* some more overloading: */
			if( v == (unsigned char)(p->name[0]) )
1012
				p = (p->o.parameters)-1;
Bernhard Link's avatar
Bernhard Link committed
1013
			continue;
Bernhard Link's avatar
Bernhard Link committed
1014
		} else if( p->type == ft_IF16 ) {
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
			unsigned int v;

			if( p->offse == OFS_LATER )
				v = stored & 0xFFFF;
			else if( ofs+1 <len )
				v = getCARD16(ofs);
			else
				continue;
			if( v == (unsigned char)(p->name[1])
			  + (unsigned int)0x100*(unsigned char)(p->name[0]) )
1025
				p = (p->o.parameters)-1;
1026 1027
			continue;
		} else if( p->type == ft_IF32 ) {
1028 1029 1030 1031 1032 1033 1034 1035 1036
			unsigned long v;

			if( p->offse == OFS_LATER )
				v = stored;
			else if( ofs+3 <len )
				v = getCARD32(ofs);
			else
				continue;
			if( v == (unsigned char)(p->name[3])
Bernhard Link's avatar
Bernhard Link committed
1037 1038 1039
			  + (((unsigned long)((unsigned char)(p->name[2])))<<8)
			  + (((unsigned long)((unsigned char)(p->name[1])))<<16)
			  + (((unsigned long)((unsigned char)(p->name[0])))<<24) )
1040
				p = (p->o.parameters)-1;
Bernhard Link's avatar
Bernhard Link committed
1041
			continue;
Bernhard Link's avatar
Bernhard Link committed
1042
		} else if( p->type == ft_IFATOM ) {
Bernhard Link's avatar
Bernhard Link committed
1043
			const char *atomname;
1044 1045 1046
			if( p->offse == OFS_LATER )
				atomname = getAtom(c, stored);
			else if( ofs+4 >= len )
Bernhard Link's avatar
Bernhard Link committed
1047
				continue;
1048 1049
			else
				atomname = getAtom(c, getCARD32(ofs));
Bernhard Link's avatar
Bernhard Link committed
1050
			if( atomname == NULL )
Bernhard Link's avatar
Bernhard Link committed
1051
				continue;
Bernhard Link's avatar
Bernhard Link committed
1052
			if( strcmp(atomname, p->name) == 0 )
1053
				p = (p->o.parameters)-1;
Bernhard Link's avatar
Bernhard Link committed
1054
			continue;
Bernhard Link's avatar
Bernhard Link committed
1055 1056
		}

1057 1058 1059 1060
		if( printspace )
			putc(' ', out);
		printspace = true;

Bernhard Link's avatar
Bernhard Link committed
1061 1062
		switch( p->type ) {
		 case ft_LASTMARKER:
1063
			 if( p->offse == ROUND_32 )
Bernhard Link's avatar
Bernhard Link committed
1064 1065 1066
				 lastofs = (lastofs+3)& ~3;
			 else
				 lastofs = ofs;
1067
			 printspace = false;
Bernhard Link's avatar
Bernhard Link committed
1068
			 continue;
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
		 case ft_SET_SIZE:
			printspace = false;
			sizeset = true;
			if( p->offse == (size_t)-1 )
				s = stored;
			else if( (p->offse & 0x80000000U) != 0 )
				s = getFromStack(&newstack,
						p->offse - 0x80000000U);
			else
				s =  p->offse;
			if( p->name != NULL && p->name[0] != '\0' )
				s *= (unsigned char)(p->name[0]);
			if( len > s )
				len = s;
			continue;
Bernhard Link's avatar
Bernhard Link committed
1084 1085 1086
		 case ft_FORMAT8:
			 if( ofs < len )
				 format = getCARD8(ofs);
1087
			printspace = false;
Bernhard Link's avatar
Bernhard Link committed
1088 1089
			 continue;
		 case ft_STRING8:
Bernhard Link's avatar
Bernhard Link committed
1090
			lastofs = printSTRING8(buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1091 1092
			continue;
		 case ft_LISTofCARD8:
1093
			lastofs = printLISTofCARD8(buffer, len,
1094
					p->name, p->o.constants,
1095
					stored, ofs);
Bernhard Link's avatar
Bernhard Link committed
1096 1097
			continue;
		 case ft_LISTofCARD16:
Bernhard Link's avatar
Bernhard Link committed
1098
			lastofs = printLISTofCARD16(c,buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1099 1100
			continue;
		 case ft_LISTofCARD32:
Bernhard Link's avatar
Bernhard Link committed
1101
			lastofs = printLISTofCARD32(c,buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1102
			continue;
Bernhard Link's avatar
Bernhard Link committed
1103 1104 1105
		 case ft_LISTofATOM:
			lastofs = printLISTofATOM(c,buffer,len,p,stored,ofs);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1106 1107 1108 1109 1110 1111 1112 1113 1114
		 case ft_LISTofUINT8:
			lastofs = printLISTofUINT8(buffer,len,p,stored,ofs);
			continue;
		 case ft_LISTofUINT16:
			lastofs = printLISTofUINT16(c,buffer,len,p,stored,ofs);
			continue;
		 case ft_LISTofUINT32:
			lastofs = printLISTofUINT32(c,buffer,len,p,stored,ofs);
			continue;
1115 1116 1117 1118 1119 1120 1121 1122 1123
		 case ft_LISTofINT8:
			lastofs = printLISTofINT8(buffer,len,p,stored,ofs);
			continue;
		 case ft_LISTofINT16:
			lastofs = printLISTofINT16(c,buffer,len,p,stored,ofs);
			continue;
		 case ft_LISTofINT32:
			lastofs = printLISTofINT32(c,buffer,len,p,stored,ofs);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1124 1125 1126
		 case ft_LISTofFormat:
			switch( format ) {
			 case 8:
1127
				lastofs = printLISTofCARD8(buffer, len,
1128
						p->name, p->o.constants,
1129
						stored, ofs);
Bernhard Link's avatar
Bernhard Link committed
1130 1131
				break;
			 case 16:
Bernhard Link's avatar
Bernhard Link committed
1132
				lastofs = printLISTofCARD16(c,buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1133 1134
				break;
			 case 32:
Bernhard Link's avatar
Bernhard Link committed
1135
				lastofs = printLISTofCARD32(c,buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1136 1137 1138 1139 1140 1141 1142
				break;
			 default:
				lastofs = ofs;
				break;
			}
			continue;
		 case ft_Struct:
Bernhard Link's avatar
Bernhard Link committed
1143
			printLISTofStruct(c,buffer,len,p,1,ofs,&newstack);
Bernhard Link's avatar
Bernhard Link committed
1144 1145
			continue;
		 case ft_LISTofStruct:
Bernhard Link's avatar
Bernhard Link committed
1146
			lastofs = printLISTofStruct(c,buffer,len,p,stored,ofs,&newstack);
Bernhard Link's avatar
Bernhard Link committed
1147 1148
			continue;
		 case ft_LISTofVarStruct:
Bernhard Link's avatar
Bernhard Link committed
1149
			lastofs = printLISTofVarStruct(c,buffer,len,p,stored,ofs,&newstack);
Bernhard Link's avatar
Bernhard Link committed
1150 1151
			continue;
		 case ft_LISTofVALUE:
Bernhard Link's avatar
Bernhard Link committed
1152
			lastofs = printLISTofVALUE(c,buffer,len,p,stored,ofs);
Bernhard Link's avatar
Bernhard Link committed
1153
			continue;
1154 1155 1156 1157 1158 1159
		 case ft_FIXED:
			if( ofs + 4 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
1160 1161
			i32 = getCARD32(ofs);
			d = i32 / 65536.0;
1162 1163 1164 1165 1166
			fprintf(out,"%.6f", d);
			continue;
		 case ft_LISTofFIXED:
			lastofs = printLISTofFIXED(c,buffer,len,p,stored,ofs);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
		 case ft_FIXED3232:
			if( ofs + 8 > len )
				continue;
			if( print_offsets )
				fprintf(out, "[%d]", (int)ofs);
			fputs(p->name, out); putc('=', out);
			i32 = getCARD32(ofs);
			u32 = getCARD32(ofs + 4);
			d = i32 + (u32 / ((double)65536.0 * (double)65536.0));
			fprintf(out, "%.11f", d);
			continue;
		 case ft_LISTofFIXED3232:
			lastofs = printLISTofFIXED3232(c, buffer, len, p,
					stored, ofs);
			continue;
1182 1183 1184 1185 1186 1187
		 case ft_FLOAT32:
			if( ofs + 4 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
1188
			/* how exactly is this float transfered? */
1189
			u32 = getCARD32(ofs);
1190 1191
			memcpy(&f, &u32, 4);
			fprintf(out,"%f", f);
1192 1193
			continue;
		 case ft_LISTofFLOAT32:
1194
			lastofs = printLISTofFLOAT32(c,buffer,len,p,stored,ofs);
1195
			continue;
1196 1197 1198 1199 1200 1201
		 case ft_FRACTION16_16:
			if( ofs + 4 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
1202 1203
			i16 = getCARD16(ofs);
			u16 = getCARD16(ofs + 2);
1204 1205
			fprintf(out,"%hd/%hu", i16, u16);
			continue;
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
		 case ft_FRACTION32_32:
			if( ofs + 8 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
			i32 = getCARD32(ofs);
			u32 = getCARD32(ofs + 4);
			fprintf(out,"%d/%u", i32, u32);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
		 case ft_UFRACTION32_32:
			if( ofs + 8 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
			uu = getCARD32(ofs);
			u32 = getCARD32(ofs + 4);
			fprintf(out,"%u/%u", uu, u32);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
		 case ft_INT32_32:
			if( ofs + 8 > len )
				continue;
			if( print_offsets )
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
			i32 = getCARD32(ofs);
			u32 = getCARD32(ofs + 4);
			ll = (((long long)i32)<< 32LL) + (long long)u32;
			fprintf(out, "%lld",  ll);
			continue;
Bernhard Link's avatar
Bernhard Link committed
1237 1238
		 case ft_EVENT:
			if( len >= ofs + 32 )
1239 1240
				print_event(c, buffer + ofs, len - ofs);
			// TODO: do something with the size here?
Bernhard Link's avatar
Bernhard Link committed
1241
			continue;
Bernhard Link's avatar
Bernhard Link committed
1242 1243 1244 1245
		 case ft_ATOM:
			if( ofs + 4 > len )
				continue;
			if( print_offsets )
1246 1247
				fprintf(out,"[%d]",(int)ofs);
			fputs(p->name,out);putc('=',out);
Bernhard Link's avatar
Bernhard Link committed
1248
			u32 = getCARD32(ofs);
1249
			value = findConstant(p->o.constants, u32);
Bernhard Link's avatar
Bernhard Link committed
1250 1251
			atom = getAtom(c, u32);
			if( value != NULL )
1252
				fprintf(out,"%s(0x%x)",value, (unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
1253
			else if( atom == NULL )
1254
				fprintf(out,"0x%x(unrecognized atom)",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
1255
			else
1256
				fprintf(out,"0x%x(\"%s\")",(unsigned int)u32, atom);
Bernhard Link's avatar
Bernhard Link committed
1257
			continue;
Bernhard Link's avatar
Bernhard Link committed
1258 1259 1260
		 case ft_BE32:
			if( ofs + 4 > len )
				continue;
1261 1262
			fputs(p->name,out);putc('=',out);
			fprintf(out,"0x%08x",(unsigned int)getBE32(ofs));
Bernhard Link's avatar
Bernhard Link committed
1263
			continue;
Bernhard Link's avatar
Bernhard Link committed
1264 1265
		 case ft_GET:
			stored = getFromStack(&newstack,p->offse);
1266
			printspace = false;
Bernhard Link's avatar
Bernhard Link committed
1267
			continue;
1268 1269 1270 1271 1272
		 case ft_DECREMENT_STORED:
			if( stored < p->offse )
				stored = 0;
			else
				stored -= p->offse;
1273
			printspace = false;
1274
			continue;
1275 1276 1277 1278 1279 1280
		 case ft_DIVIDE_STORED:
			if (stored % p->offse)
				fprintf(stderr, "count (%lu) not divisible by %zu\n", stored, p->offse);
			stored /= p->offse;
			printspace = false;
			continue;
1281 1282
		 case ft_SET:
			stored = p->offse;
1283
			printspace = false;
1284
			continue;
Bernhard Link's avatar
Bernhard Link committed
1285 1286 1287 1288
		 default:
			break;
		}
		assert( p->type <= ft_BITMASK32);
1289

Bernhard Link's avatar
Bernhard Link committed
1290 1291
		switch( p->type % 3) {
		 case 0:
1292 1293 1294
			 if( (ofs+1) > len )
				 /* this field is missing */
				 continue;
Bernhard Link's avatar
Bernhard Link committed
1295 1296 1297 1298
			 u8 = getCARD8(ofs);
			 l = u8;
			 break;
		 case 1:
1299 1300 1301
			 if( (ofs+2) > len )
				 /* this field is missing */
				 continue;
Bernhard Link's avatar
Bernhard Link committed
1302 1303 1304 1305
			 u16 = getCARD16(ofs);
			 l = u16;
			 break;
		 case 2:
1306 1307 1308
			 if( (ofs+4) > len )
				 /* this field is missing */
				 continue;
Bernhard Link's avatar
Bernhard Link committed
1309 1310 1311 1312 1313 1314
			 u32 = getCARD32(ofs);
			 l = u32;
			 break;
		}
		if( p->type >= ft_BITMASK8 ) {
			assert(p->type <= ft_BITMASK32 );
1315
			print_bitfield(p->name, p->o.constants, l);
Bernhard Link's avatar
Bernhard Link committed
1316 1317
			continue;
		}
Bernhard Link's avatar
Bernhard Link committed
1318 1319 1320
		if( p->type >= ft_PUSH8 ) {
			assert(p->type <= ft_PUSH32 );
			push(&newstack,l);
1321 1322
			if( !print_counts) {
				printspace = false;
Bernhard Link's avatar
Bernhard Link committed
1323
				continue;
1324
			}
Bernhard Link's avatar
Bernhard Link committed
1325
		} else if( p->type >= ft_STORE8 ) {
Bernhard Link's avatar
Bernhard Link committed
1326 1327
			assert(p->type <= ft_STORE32);
			stored = l;
1328 1329
			if( !print_counts) {
				printspace = false;
Bernhard Link's avatar
Bernhard Link committed
1330
				continue;
1331
			}
Bernhard Link's avatar
Bernhard Link committed
1332
		}
1333
		value = findConstant(p->o.constants, l);
Bernhard Link's avatar
Bernhard Link committed
1334
		if( print_offsets )
1335 1336
			fprintf(out,"[%d]",(int)ofs);
		fputs(p->name,out);putc('=',out);
Bernhard Link's avatar
Bernhard Link committed
1337
		if( value != NULL ) {
1338 1339
			fputs(value,out);
			putc('(',out);
Bernhard Link's avatar
Bernhard Link committed
1340 1341 1342
		}
		switch( p->type ) {
		 case ft_INT8:
Bernhard Link's avatar
Bernhard Link committed
1343
			 i8 = u8;
1344
			 fprintf(out,"%d",(int)i8);
Bernhard Link's avatar
Bernhard Link committed
1345 1346
			 break;
		 case ft_INT16:
Bernhard Link's avatar
Bernhard Link committed
1347
			 i16 = u16;
1348
			 fprintf(out,"%d",(int)i16);
Bernhard Link's avatar
Bernhard Link committed
1349 1350
			 break;
		 case ft_INT32:
Bernhard Link's avatar
Bernhard Link committed
1351
			 i32 = u32;
1352
			 fprintf(out,"%d",(int)i32);
Bernhard Link's avatar
Bernhard Link committed
1353
			 break;
Bernhard Link's avatar
Bernhard Link committed
1354 1355
		 case ft_PUSH8:
		 case ft_STORE8:
Bernhard Link's avatar
Bernhard Link committed
1356
		 case ft_UINT8:
1357
			 fprintf(out,"%u",(unsigned int)u8);
Bernhard Link's avatar
Bernhard Link committed
1358
			 break;
Bernhard Link's avatar
Bernhard Link committed
1359 1360
		 case ft_PUSH16:
		 case ft_STORE16:
Bernhard Link's avatar
Bernhard Link committed
1361
		 case ft_UINT16:
1362
			 fprintf(out,"%u",(unsigned int)u16);
Bernhard Link's avatar
Bernhard Link committed
1363
			 break;
Bernhard Link's avatar
Bernhard Link committed
1364 1365
		 case ft_PUSH32:
		 case ft_STORE32:
Bernhard Link's avatar
Bernhard Link committed
1366
		 case ft_UINT32:
1367
			 fprintf(out,"%u",(unsigned int)u32);
Bernhard Link's avatar
Bernhard Link committed
1368 1369 1370
			 break;
		 case ft_ENUM8:
			 if( value == NULL )