labcomm_sig_parser.c 21.6 KB
Newer Older
Sven Robertz's avatar
Sven Robertz committed
1
/* labcomm_sig_parser.c:
2
3
4
5
6
7
 * an example parser for labcomm signatures, illustrating how to skip samples
 * based on their signature. Intended as an embryo for introducing this 
 * functionality into the lib to allow a channel to survive types with no
 * registered handler.
 */

Sven Robertz's avatar
Sven Robertz committed
8
9
10
11
12
13
14
15

/* TODO, and notes about strange quirks
 *
 * - the return values for the accept_ functions are not really used anymore
 *   as the parser "peeks" and calls the correct accept function instead. 
 *   This should be refactored
 *
 * - The RETURN_STRINGS and where/if to allocate strings is to be decided, it
Sven Robertz's avatar
comment    
Sven Robertz committed
16
 *   is currently not used
17
 * 
Sven Robertz's avatar
comment    
Sven Robertz committed
18
19
20
21
22
23
 * - TYPE_DECL is not tested (is it ever sent?)
 * 
 * - The dynamic allocation of the parser is not quite dynamic, the sizes are
 *   set through the init function, and are then static.
 *   This should be adapted when allocation is parameterized/user-definable
 *   for the entire lib.
Sven Robertz's avatar
Sven Robertz committed
24
25
26
27
 */
      


28
29
30
31
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

32
#include "labcomm_sig_parser.h"
Sven Robertz's avatar
Sven Robertz committed
33

34
static void error(char *s) {
35
	fprintf(stderr, "ERROR: %s", s);
36
37
38
39
40
	fprintf(stderr, "\nexiting\n");
	exit(1);
}

/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
Sven Robertz's avatar
Sven Robertz committed
41
42
43
44
45
46
47
48
static unsigned int unpack32(unsigned char *c, unsigned int idx) {
       unsigned int b0=(c[idx]) << 3 ; 
       unsigned int b1=(c[idx+1]) << 2 ;
       unsigned int b2=(c[idx+2]) << 1 ;
       unsigned int b3=c[idx+3];

       return  b0 | b1 | b2 | b3;
}
49

50
static inline unsigned int get32(labcomm_sig_parser_t *b) {
Sven Robertz's avatar
Sven Robertz committed
51
52
53
54
55
56
57
58
59
       unsigned int res = unpack32(b->c, b->idx);
       b->idx+=4;
       return res;
}


/* aux method for reading labcomm varint from a char* 
   size is an out parameter: if not NULL the number of bytes read will be written here
*/
60
61
62
63
static unsigned int unpack_varint(unsigned char *buf, 
				  unsigned int idx, 
				  unsigned char *size) 
{
Sven Robertz's avatar
Sven Robertz committed
64
65
66
67
68
69
        unsigned int res = 0;
        unsigned int i=0;
        unsigned char cont = TRUE;

        do {
                unsigned char c = buf[idx+i];
70
                res = (res << 7) | (c & 0x7f);
Sven Robertz's avatar
Sven Robertz committed
71
72
73
74
75
76
77
                cont = c & 0x80;
                i++;
        } while(cont);

	if(size != NULL)
		*size = i; 
        return res;
78
79
}

80
void dumpValStack(labcomm_sig_parser_t *b) {
81
	int i;
82
	printf("=== value stack: ");
83
#ifdef DEBUG_STACK_VERBOSE
84
	for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
85
		printf("%2.2x ", b->val_stack[i]);
86
	}
87
#endif
88
	printf("    top==%d\n", b->val_top);
89
}
90
void dumpPtrStack(labcomm_sig_parser_t *b) {
91
92
	int i;
	printf("=== pointer stack: ");
93
#ifdef DEBUG_STACK_VERBOSE
94
95
96
	for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
		printf("%2.2x ", b->ptr_stack[i]);
	}
97
#endif
98
	printf("    top==%d\n", b->ptr_top);
99
100
}

101
void push_val(labcomm_sig_parser_t *b, unsigned int e) {
102
103
	b->val_stack[b->val_top]=e;
	b->val_top=b->val_top-1;
104
105
	if(b->val_top<0) error("value stack overrun");
#if defined DEBUG && !defined QUIET_STACK
106
	dumpValStack(b);
Sven Robertz's avatar
Sven Robertz committed
107
#endif
108
}
109
unsigned int pop_val(labcomm_sig_parser_t *b) {
110
	b->val_top=b->val_top+1;
111
112
113
114
	if(b->val_top>b->stacksize) error("value stack underrun");
#if defined DEBUG && !defined QUIET_STACK
	dumpValStack(b);
#endif
115
116
	return b->val_stack[b->val_top];
}
117
void push_ptr(labcomm_sig_parser_t *b, void* e) {
118
119
	b->ptr_stack[b->ptr_top]=e;
	b->ptr_top=b->ptr_top-1;
120
	if(b->ptr_top<0) error("pointer stack overrun");
Sven Robertz's avatar
Sven Robertz committed
121
#ifdef DEBUG
122
	dumpPtrStack(b);
Sven Robertz's avatar
Sven Robertz committed
123
#endif
124
}
125
void* pop_ptr(labcomm_sig_parser_t *b) {
126
	b->ptr_top=b->ptr_top+1;
127
128
129
130
	if(b->ptr_top>b->stacksize) error("pointer stack underrun");
#ifdef DEBUG
	dumpPtrStack(b);
#endif
131
	return b->ptr_stack[b->ptr_top];
132
133
}
	
134
135
136
137
138
139
int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size, 
                            size_t stacksize, size_t num_signatures,
                            size_t max_name_len, size_t max_sig_len) 
{
	b->c = malloc(buffer_size);
	b->capacity = buffer_size;
140
	b->size = 0;
141
142
	b->idx = 0;

143
	b->stacksize = stacksize;
144

145
146
147
148
149
150
	b->val_stack = calloc(stacksize, sizeof(b->val_stack));
	b->val_top = stacksize-1;

	b->ptr_stack = calloc(stacksize, sizeof(b->ptr_stack));
	b->ptr_top = stacksize-1;

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
	b->max_signatures = num_signatures;
	b->max_name_len = max_name_len;
	b->max_sig_len = max_sig_len;

#ifdef STATIC_ALLOCATION
	printf("warning: labcomm_sig_parser_t_init: size params ignored, using defaults from .h file \n");
#else
	b->sig_ts=calloc(num_signatures, sizeof(labcomm_signature_t));
	b->signatures_length=calloc(num_signatures, sizeof(int));
	b->signatures_name_length=calloc(num_signatures, sizeof(int));
	b->signatures_name=calloc(num_signatures, sizeof(void *)); //HERE BE DRAGONS: add range checks
	b->signatures=calloc(num_signatures, sizeof(void *));
	int i;
	for(i = 0; i<num_signatures; i++) {
		b->signatures[i] = calloc(b->max_sig_len, sizeof(char));
		b->signatures_name[i] = calloc(b->max_name_len, sizeof(char));
	}
#endif
169
	return b->c == NULL || b->val_stack == NULL || b->ptr_stack == NULL;
170
171
}

172
int labcomm_sig_parser_read_file(labcomm_sig_parser_t *b, FILE *f) {
173
174
175
176
177
178
        int s = fread(b->c, sizeof(char), b->capacity, f);
        b->size = s;
        b->idx=0;
        return s;
}

179
int more(labcomm_sig_parser_t *b) 
180
181
182
183
{
	return b->idx < b->size;
}

184
unsigned char get(labcomm_sig_parser_t *b) {
185
186
187
	return b->c[b->idx++];
}

188
unsigned char peek(labcomm_sig_parser_t *b) {
189
190
191
	return b->c[b->idx];
}

192
void advance(labcomm_sig_parser_t *b) {
193
194
195
	b->idx++;
}

196
void advancen(labcomm_sig_parser_t *b, size_t n) {
197
198
199
	b->idx+=n;
}

200
unsigned int peek_varint(labcomm_sig_parser_t *b, unsigned char *size) {
Sven Robertz's avatar
Sven Robertz committed
201
        return unpack_varint(b->c, b->idx, size);
202
203
}

204
unsigned int get_varint(labcomm_sig_parser_t *b) {
Sven Robertz's avatar
Sven Robertz committed
205
206
207
208
        unsigned char size;
        unsigned int res = peek_varint(b, &size);
        advancen(b, size);
        return res;
209
}
210
unsigned int get_varint_size(labcomm_sig_parser_t *b, unsigned char *size) {
Sven Robertz's avatar
Sven Robertz committed
211
212
213
        unsigned int res = peek_varint(b, size);
        advancen(b, *size);
        return res;
214
215
}

216
void getStr(labcomm_sig_parser_t *b, char *dest, size_t size) {
217
218
219
220
221
222
223
	int rem = b->size - b->idx;
	if( size > rem ) 
		size = rem;
	strncpy(dest, &b->c[b->idx], size);
	b->idx += size;
}

224
labcomm_signature_t *get_sig_t(labcomm_sig_parser_t *p, unsigned int uid) 
225
{
226
	return &(p->sig_ts[uid-LABCOMM_USER]);
227
228
}

229
unsigned int get_signature_len(labcomm_sig_parser_t *p, unsigned int uid){
230
	//return signatures_length[uid-LABCOMM_USER];
231
	return p->sig_ts[uid-LABCOMM_USER].size;
232
}
233
unsigned char* get_signature(labcomm_sig_parser_t *p, unsigned int uid){
234
	//return signatures[uid-LABCOMM_USER];
235
	return p->sig_ts[uid-LABCOMM_USER].signature;
236
237
}

238
//is this needed?
239
//unsigned int get_signature_name_len(labcomm_sig_parser_t *p, unsigned int uid){
240
241
//	return signatures_name_length[uid-LABCOMM_USER];
//}
242

243
unsigned char* get_signature_name(labcomm_sig_parser_t *p, unsigned int uid){
244
	//return signatures_name[uid-LABCOMM_USER];
245
	return p->sig_ts[uid-LABCOMM_USER].name;
246
247
}

248
void dump_signature(labcomm_sig_parser_t *p, unsigned int uid){
249
	int i;
250
251
252
	unsigned int len = get_signature_len(p, uid);
	printf("signature for uid %x : %s (len=%d):\n", uid, get_signature_name(p, uid), len);
	unsigned char* sig = get_signature(p, uid);
253
254
	for(i=0; i<len; i++) {
		printf("%2.2x ",sig[i]);
255
		if( i < len-1 && (i+1)%8==0 ) printf("\n");
256
257
258
259
	}
	printf("\n");
}

260
static inline void labcomm_sig_parser_t_set_varsize(labcomm_sig_parser_t *b)
261
262
263
{
	b->current_decl_is_varsize = TRUE;
}
264
static size_t labcomm_sizeof_primitive(unsigned int type)
265
266
267
268
269
270
271
272
273
274
275
276
277
278
{
	switch(type) {
		case TYPE_BOOLEAN :
		case TYPE_BYTE : 
			return 1;
		case TYPE_SHORT : 
			return 2;
		case TYPE_INTEGER :
		case TYPE_FLOAT : 
			return 4;
		case TYPE_LONG :
		case TYPE_DOUBLE : 
			return 8;
		default:
279
280
			printf("labcomm_sizeof_primitive(%x)\n", type);
		 	error("labcomm_sizeof_primitive should only be called for primitive types");
281
282
283
	}
}

284
//these are inlined in do_accept_packet
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
//static int accept_type_decl(labcomm_sig_parser_t *d);
//static int accept_sample_decl(labcomm_sig_parser_t *d);
static int accept_user_id(labcomm_sig_parser_t *d);
static int accept_string(labcomm_sig_parser_t *d);
static int accept_string_length(labcomm_sig_parser_t *d);
static int accept_char(labcomm_sig_parser_t *d);
static int accept_type(labcomm_sig_parser_t *d);
static int accept_array_decl(labcomm_sig_parser_t *d);
static int accept_number_of_indices(labcomm_sig_parser_t *d);
static int accept_indices(labcomm_sig_parser_t *d);
static int accept_variable_index(labcomm_sig_parser_t *d);
static int accept_fixed_index(labcomm_sig_parser_t *d);
static int accept_struct_decl(labcomm_sig_parser_t *d);
static int accept_number_of_fields(labcomm_sig_parser_t *d);
static int accept_field(labcomm_sig_parser_t *d);
static int accept_sample_data(labcomm_sig_parser_t *d);
301

Sven Robertz's avatar
Sven Robertz committed
302
303
304
305
306
307
308
309
310
311
312
313
static unsigned char labcomm_varint_sizeof(unsigned int i)
{
	if(i < 128) {
		return 1;
	} else {
		unsigned char res = 1;
		while (i >>= 7) ++res;

		return res;
	}
}

314
315
int encoded_size_static(labcomm_signature_t *sig, void *unused)
{
316
	if(sig->cached_encoded_size == -1) {
317
		error("encoded_size_static called for var_size sample or uninitialized signature");
318
	}
319
	return sig->cached_encoded_size;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
}

/* This function probably never will be implemented, as it would be 
   similar to skip_packed_sample_data. And if unregistered variable size 
   samples is to be handled, the proper way is to generate and register
   a handler. Thus, the most probable use of the encoded_size function
   on the receiver side, is to skip unhandled samples.
*/
  
int encoded_size_parse_sig(labcomm_signature_t *sig, void *sample)
{
	printf("Warning: encoded_size_parse_sig not implemented\n");
	return -1;
}

335
336
337
338
339
340
341
342
343
344
345
346
347
348
static int accept_signature(labcomm_sig_parser_t *d)
{
	if(accept_user_id(d)) {
		unsigned int uid = pop_val(d);
		unsigned int nstart = d->idx;
		VERBOSE_PRINTF(", name = ");
		accept_string(d);
		unsigned int start = d->idx;
		unsigned int nlen = pop_val(d);
#ifdef RETURN_STRINGS
		char *str = (char *) pop_ptr(d);
		free(str);
#endif
		unsigned char lenlen = labcomm_varint_sizeof(nlen);
349
		VERBOSE_PRINTF("\ntype = ");
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
		accept_type(d);
		//printf(" : ");
		//unsigned int dt = pop(d);
		unsigned int type = pop_val(d);
		unsigned int enc_size = pop_val(d);
		unsigned int end = d->idx;
		unsigned int len = end-start;

		labcomm_signature_t *newsig = get_sig_t(d, uid);
		newsig->type = type;
		if(len <= d->max_sig_len) {
			d->signatures_length[uid-LABCOMM_USER] = len;
			memcpy(d->signatures[uid-LABCOMM_USER], &d->c[start], len);
			newsig->size = len;
			newsig->signature = d->signatures[uid-LABCOMM_USER];
		} else {
			error("sig longer than max length (this ought to be dynamic...)");
		}

		if(nlen < d->max_name_len) { // leave 1 byte for terminating NULL
			d->signatures_name_length[uid-LABCOMM_USER] = nlen;
			memcpy(d->signatures_name[uid-LABCOMM_USER], &d->c[nstart+lenlen], nlen);
			d->signatures_name[uid-LABCOMM_USER][nlen]=0;
			newsig->name = d->signatures_name[uid-LABCOMM_USER];
		} else {
			error("sig name longer than max length (this ought to be dynamic...");
		}
377
		VERBOSE_PRINTF("signature for uid %x: %s (start=%x,end=%x, nlen=%d,len=%d)\n", uid, get_signature_name(d, uid), start,end, nlen, len);
378
379
380
381
382
383
384
385
386
387
388
389
		INFO_PRINTF("SIG: %s\n", newsig->name);	
		if(! d->current_decl_is_varsize) {
			newsig->cached_encoded_size = enc_size;
			newsig->encoded_size = encoded_size_static;
			INFO_PRINTF(".... is static size = %d\n", enc_size);
		} else {
			newsig->cached_encoded_size = -1;
			newsig->encoded_size = encoded_size_parse_sig;
			INFO_PRINTF(".... is variable size\n");
		}
		return TRUE;
	} else {
390
		error("sample_decl with uid < LABCOMM_USER");	
391
392
393
394
		return FALSE;
	}
}

395
// HERE BE DRAGONS! what does the return value mean?
396
int accept_packet(labcomm_sig_parser_t *d) {
Sven Robertz's avatar
Sven Robertz committed
397
398
        unsigned char nbytes;
        unsigned int type = peek_varint(d, &nbytes) ;
399
	if(type == TYPE_DECL ) {
400
		//XXX is this used? If so, is it correct?
Sven Robertz's avatar
Sven Robertz committed
401
		advancen(d, nbytes);
402
403
404
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
		VERBOSE_PRINTF("type_decl ");
		accept_signature(d);
405
	} else if (type == SAMPLE_DECL) {
406
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
Sven Robertz's avatar
Sven Robertz committed
407
		advancen(d, nbytes);
408
		VERBOSE_PRINTF("sample_decl ");
409
		accept_signature(d);
410
	} else if(type >= LABCOMM_USER) {
411
#ifdef EXIT_WHEN_RECEIVING_DATA
412
413
		printf("*** got sample data, exiting\n");
		exit(0);
414
415
416
#else
		accept_sample_data(d);
#endif
417
	} else {
418
		error("got unknown type (<LABCOMM_USER)");
419
		exit(1);
420
421
422
	}
}

423
static int accept_user_id(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
424
425
426
427
        unsigned char nbytes;
	unsigned int uid = peek_varint(d, &nbytes);
	if(uid >= LABCOMM_USER) {
		advancen(d, nbytes);
428
		VERBOSE_PRINTF("uid = %x ", uid);
429
		push_val(d, uid);
430
431
432
433
434
435
		return TRUE;
	} else {
		return FALSE;
	}
}

436
static int accept_string(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
437
	unsigned int len = get_varint(d);
438
	char *str=malloc(len);
439
440
	getStr(d, str, len); 
	VERBOSE_PRINTF("%s", str);
441
#ifdef RETURN_STRINGS
442
	push_ptr(d, str);
443
444
445
#else
	free(str);
#endif
446
	push_val(d, len);
447
448
	return TRUE;
}
Sven Robertz's avatar
Sven Robertz committed
449
/* pushes size and type id */
450
static int accept_type(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
451
452
	unsigned char nbytes;
        unsigned int type = peek_varint(d, &nbytes) ;
453
454
	switch(type) {
		case TYPE_BOOLEAN :
455
			VERBOSE_PRINTF("boolean\n");
Sven Robertz's avatar
Sven Robertz committed
456
			advancen(d, nbytes);
457
			push_val(d, 1);
458
459
			break;
		case TYPE_BYTE :
460
			VERBOSE_PRINTF("byte\n");
Sven Robertz's avatar
Sven Robertz committed
461
			advancen(d, nbytes);
462
			push_val(d,  1);
463
464
			break;
		case TYPE_SHORT :
465
			VERBOSE_PRINTF("short\n");
Sven Robertz's avatar
Sven Robertz committed
466
			advancen(d, nbytes);
467
			push_val(d,  2);
468
469
			break;
		case TYPE_INTEGER :
470
			VERBOSE_PRINTF("integer\n");
Sven Robertz's avatar
Sven Robertz committed
471
			advancen(d, nbytes);
472
			push_val(d,  4);
473
474
			break;
		case TYPE_LONG :
475
			VERBOSE_PRINTF("long\n");
Sven Robertz's avatar
Sven Robertz committed
476
			advancen(d, nbytes);
477
			push_val(d,  8);
478
479
			break;
		case TYPE_FLOAT :
480
			VERBOSE_PRINTF("float\n");
Sven Robertz's avatar
Sven Robertz committed
481
			advancen(d, nbytes);
482
			push_val(d,  4);
483
484
			break;
		case TYPE_DOUBLE :
485
			VERBOSE_PRINTF("double\n");
Sven Robertz's avatar
Sven Robertz committed
486
			advancen(d, nbytes);
487
			push_val(d,  8);
488
489
			break;
		case TYPE_STRING :
490
			VERBOSE_PRINTF("string\n");
Sven Robertz's avatar
Sven Robertz committed
491
			advancen(d, nbytes);
492
			labcomm_sig_parser_t_set_varsize(d);
493
			push_val(d, 0);
494
495
496
			break;
		case ARRAY_DECL :
			accept_array_decl(d);
Sven Robertz's avatar
Sven Robertz committed
497
498
			pop_val(d); // ignore element type
			// push(d, pop(d) is a NOP --> leave size on stack
499
500
501
			break;
		case STRUCT_DECL :
			accept_struct_decl(d);
Sven Robertz's avatar
Sven Robertz committed
502
			// push(d, pop(d) is a NOP --> leave size on stack
503
504
			break;
		default :
505
			printf("accept_type default (type==%x) should not happen\n", type);
506
			push_val(d, 0);
Sven Robertz's avatar
Sven Robertz committed
507
			push_val(d, type);
508
509
			return FALSE;
	}
510
	push_val(d, type);
511
512
513
	return TRUE;
}

Sven Robertz's avatar
Sven Robertz committed
514
/* pushes size and element type */
515
static int accept_array_decl(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
516
517
        unsigned char nbytes;
        unsigned int tid = peek_varint(d, &nbytes) ;
518
	if(tid == ARRAY_DECL) {
Sven Robertz's avatar
Sven Robertz committed
519
520
		advancen(d, nbytes);
		unsigned int nidx = get_varint(d);
521
		VERBOSE_PRINTF("%d dim array", nidx);
522
523
524
525
		int i;
		unsigned int numVar=0;
		unsigned int size=1;
		for(i=0; i<nidx; i++) {
Sven Robertz's avatar
Sven Robertz committed
526
			unsigned int idx = get_varint(d);
527
528
			if(idx == 0) {
				numVar++;
529
				VERBOSE_PRINTF("[_] ");
530
				labcomm_sig_parser_t_set_varsize(d);
531
			} else {
532
				VERBOSE_PRINTF("[%d] ", idx);
533
534
535
				size*=idx;
			}
		}
536
		VERBOSE_PRINTF(" of ");
537
		accept_type(d);
538
539
		unsigned int et= pop_val(d);  // type
		unsigned int es= pop_val(d);  // (encoded) size
540
541
542
543
544
#ifdef DEBUG
		printf("accept_array_decl: et = %x\n", et);
#endif
		if(numVar == 0) {
#ifdef DEBUG
545
			printf("size=%d, es=%d\n", size, es);
546
#endif
547
			push_val(d,  (size*es));
548
		} else {
Sven Robertz's avatar
Sven Robertz committed
549
550
//HERE BE DRAGONS! push a (non-) size for variable size arrays?
			push_val(d, 0);
551
		}
Sven Robertz's avatar
Sven Robertz committed
552
		push_val(d, et);
553
554
555
		return TRUE;
	} else {
		printf("accept_array_decl: type=%x, should not happen\n",tid);
556
557
		push_val(d, 0);
		push_val(d, tid);
558
559
560
		return FALSE;
	}
}
561
562

/* pushes size */
563
static int accept_struct_decl(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
564
565
	unsigned char nbytes;
        unsigned int tid = peek_varint(d, &nbytes) ;
566
	if(tid == STRUCT_DECL) {
Sven Robertz's avatar
Sven Robertz committed
567
568
		advancen(d, nbytes);
		unsigned int nf = get_varint(d);
569
		VERBOSE_PRINTF("%d field struct:\n", nf);
570
571
572
		int i;
		int numVar=0;
		int size=0;
573
		unsigned int fieldsizes=0;
574
575
		for(i=0; i<nf; i++) {
			accept_field(d);
576
			fieldsizes += pop_val(d);
577
		}
578
		push_val(d, fieldsizes);
579
580
581
		return TRUE;
	} else {
		printf("accept_struct_decl: type=%x, should not happen\n",tid);
582
		push_val(d, 0);
583
584
585
		return FALSE;
	}
}
586

Sven Robertz's avatar
Sven Robertz committed
587
/* pushes field size */
588
static int accept_field(labcomm_sig_parser_t *d){
589
	VERBOSE_PRINTF("\tfield name: ");
590
	accept_string(d);
591
	pop_val(d); // ignore length, for now
Sven Robertz's avatar
Sven Robertz committed
592
#ifdef RETURN_STRINGS
593
		char *str = (char *) pop_ptr(d);
Sven Robertz's avatar
Sven Robertz committed
594
595
		free(str);
#endif
596
	VERBOSE_PRINTF("\n\ttype: ");
597
	accept_type(d);
598
	pop_val(d); // ignore type, for now
Sven Robertz's avatar
Sven Robertz committed
599
	// push(pop() is really a NOP , leave size on the stack when debugging done
600
	VERBOSE_PRINTF("\n");
601
}
602
static int accept_sample_data(labcomm_sig_parser_t *d){
603
	accept_user_id(d);
604
	unsigned int uid = pop_val(d);	
605
	printf("sample data... uid=0x%x\n", uid);
606
#ifdef DEBUG
607
	dump_signature(d, uid);
608
#endif
609
	labcomm_signature_t *sigt = get_sig_t(d, uid);
610
611
	int encoded_size = sigt->encoded_size(sigt, NULL);
	INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
612
	labcomm_signature_t *sig = get_sig_t(d, uid);
613
	skip_packed_sample_data(d, sig);
614
615
616
	return TRUE;
}

617
static int skip_type(unsigned int,labcomm_sig_parser_t*,unsigned char*,unsigned int,unsigned int*) ;
618

619
static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
620
621
	unsigned int skip = 0;
	unsigned int tot_nbr_elem_tmp = 1;
Sven Robertz's avatar
Sven Robertz committed
622
623
	unsigned char nbytes;
	unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
624
	VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
Sven Robertz's avatar
Sven Robertz committed
625
	*pos +=nbytes;
626
627
628
629
630
631
	unsigned int idx[nIdx];
	unsigned int nVar=0;

	unsigned int i;

	for(i=0; i<nIdx; i++) {
Sven Robertz's avatar
Sven Robertz committed
632
633
		idx[i] = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
634
		VERBOSE_PRINTF("skip_array: idx[%d]=%d (from sig)\n", i, idx[i]);
635
636
637
638
639
640
641
642
		if(idx[i] == 0) {
			nVar++;
		} else {
			tot_nbr_elem_tmp *= idx[i];
		}
	}
	unsigned int var[nVar];

Sven Robertz's avatar
Sven Robertz committed
643
	unsigned char varSize=0; // total number of bytes required for var size fields
644
	for(i=0; i<nVar; i++) {
Sven Robertz's avatar
Sven Robertz committed
645
646
		var[i] = get_varint_size(d, &nbytes);	
		varSize += nbytes;
647
		VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
Sven Robertz's avatar
Sven Robertz committed
648
		tot_nbr_elem_tmp *= var[i];
649
650
	}

Sven Robertz's avatar
Sven Robertz committed
651
652
	unsigned int type = unpack_varint(sig, *pos, &nbytes);
	*pos+=nbytes;
653

654
	unsigned int elemSize = labcomm_sizeof_primitive(type);
655
656
657

	skip = elemSize * tot_nbr_elem_tmp;

658
	VERBOSE_PRINTF("skip_array: skip: %d * %d = %d\n", tot_nbr_elem_tmp, elemSize ,skip);
659
660
661
	
	advancen(d, skip);

Sven Robertz's avatar
Sven Robertz committed
662
663
	//return skip + 4*nVar;
	return skip + varSize;
664
665
}

666
int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
Sven Robertz's avatar
Sven Robertz committed
667
668
669
	unsigned char nbytes;
	unsigned int nFields = unpack_varint(sig,*pos, &nbytes);
	*pos += nbytes;
670
671
	unsigned int i;
	unsigned int skipped=0;
672
	VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
673
674
	for(i=0; i<nFields; i++) {
		//skip name 
Sven Robertz's avatar
Sven Robertz committed
675
		unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
676
#ifdef DEBUG
677
		VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
Sven Robertz's avatar
Sven Robertz committed
678
		char name[namelen+1]; //HERE BE DRAGONS. alloca?
Sven Robertz's avatar
Sven Robertz committed
679
		strncpy(name, sig+*pos+nbytes, namelen);
680
		name[namelen]=0;
681
		VERBOSE_PRINTF("----name = %s\n",name);
682
#endif
Sven Robertz's avatar
Sven Robertz committed
683
		*pos += (nbytes+namelen); // 32bit len + actual string
Sven Robertz's avatar
Sven Robertz committed
684

Sven Robertz's avatar
Sven Robertz committed
685
686
		unsigned int type = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
687
#ifdef DEBUG
688
		VERBOSE_PRINTF("----type == %x\n", type);
689
690
691
692
693
694
695
#endif
		skipped += skip_type(type, d, sig, len, pos);
	}
	return skipped;
}
#ifndef QUIET
/* print and skip */
696
int skip_type(unsigned int type, labcomm_sig_parser_t *d, 
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
		unsigned char *sig, unsigned int len, unsigned int *pos) 
{
	int skipped=0;
	printf("skip_type %x:", type);
	switch(type) {
		case TYPE_BOOLEAN :
			printf("boolean [%d]\n", get(d));
			skipped++;
			break;
		case TYPE_BYTE : 
			printf("byte [%d]\n", get(d));
			skipped++;
			break;
		case TYPE_SHORT : 
			//XXX not supported
			advancen(d,2); 
			skipped+=2;
			break;
		case TYPE_INTEGER :
			printf("integer [%d]\n", get32(d));
			skipped +=4;
			break;
		case TYPE_FLOAT : 
			//XXX not supported
			advancen(d,4); 
			skipped+=4;
			break;
		case TYPE_LONG :
		case TYPE_DOUBLE : 
			//XXX not supported
			advancen(d,8); 
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
731
732
733
			{
			unsigned char nbytes;
			unsigned int len = get_varint_size(d, &nbytes);
734
735
736
737
738
			int i;
			printf("string [");
			for(i=0; i<len; i++)
				printf("%c", get(d));
			printf("]\n");
Sven Robertz's avatar
Sven Robertz committed
739
			skipped+=len+nbytes;
740
741
742
743
			break;}
		case ARRAY_DECL :
			printf("array\n");
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
744
			break;
745
746
747
748
749
750
751
752
753
754
755
		case STRUCT_DECL :
			printf("struct\n");
			skipped += skip_struct(d, sig, len, pos);
			break;
		default:
			printf("ERROR: skip_type: type = %x\n", type);
			exit(1);
	}
	return skipped;
}
#else
756
int skip_type(unsigned int type, labcomm_sig_parser_t *d, 
757
758
759
		unsigned char *sig, unsigned int len, unsigned int *pos) 
{
	int skipped=0;
760
	VERBOSE_PRINTF("skip_type %x\n", type);
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
	switch(type) {
		case TYPE_BOOLEAN :
		case TYPE_BYTE : 
			advancen(d,1); 
			skipped++;
			break;
		case TYPE_SHORT : 
			advancen(d,2); 
			skipped+=2;
			break;
		case TYPE_INTEGER :
		case TYPE_FLOAT : 
			advancen(d,4); 
			skipped+=4;
			break;
		case TYPE_LONG :
		case TYPE_DOUBLE : 
			advancen(d,8); 
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
782
783
784
			{
			unsigned char nbytes;
			unsigned int len = get_varint_size(d, &nbytes);
785
			advancen(d,len);
Sven Robertz's avatar
Sven Robertz committed
786
			skipped+=len+nbytes;
787
788
789
			break;}
		case ARRAY_DECL :
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
790
			break;
791
792
793
794
795
796
797
798
799
800
801
		case STRUCT_DECL :
			skipped += skip_struct(d, sig, len, pos);
			break;
		default:
			printf("ERROR: skip_type: type = %x\n", type);
			exit(1);
	}
	return skipped;
}
#endif

802
/* parse signature and skip the corresponding bytes in the labcomm_sig_parser_t 
803
 */
804
int skip_packed_sample_data(labcomm_sig_parser_t *d, labcomm_signature_t *sig) {
805
806
	unsigned int pos = 0; 		//current position in signature
	unsigned int skipped = 0;	//skipped byte counter
807
	while(pos < sig->size) {
Sven Robertz's avatar
Sven Robertz committed
808
		unsigned char nbytes;
809
		unsigned int type = unpack_varint(sig->signature,pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
810
		pos+=nbytes;
811
		skipped += skip_type(type, d, sig->signature, sig->size, &pos);
812
813
814
815
	}	
	printf("skipped %d bytes\n", skipped);
	return TRUE;
}