labcomm_sig_parser.c 22.4 KB
Newer Older
Sven Robertz's avatar
Sven Robertz committed
1
/* labcomm_sig_parser.c:
2
 * an example parser for labcomm signatures, illustrating how to skip samples
3
 * based on their signature. Intended as an embryo for introducing this
4
5
6
7
 * 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

/* TODO, and notes about strange quirks
 *
 * - the return values for the accept_ functions are not really used anymore
12
 *   as the parser "peeks" and calls the correct accept function instead.
Sven Robertz's avatar
Sven Robertz committed
13
14
15
 *   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
 * - TYPE_DECL is not tested (is it ever sent?)
19
 *
Sven Robertz's avatar
comment    
Sven Robertz committed
20
21
22
23
 * - 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

Sven Robertz's avatar
Sven Robertz committed
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*) */
41
42
43
44
45
static int unpack32(unsigned char *c, int idx) {
       int b0=(c[idx]) << 3 ;
       int b1=(c[idx+1]) << 2 ;
       int b2=(c[idx+2]) << 1 ;
       int b3=c[idx+3];
Sven Robertz's avatar
Sven Robertz committed
46
47
48

       return  b0 | b1 | b2 | b3;
}
49

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


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

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

	if(size != NULL)
76
		*size = i;
Sven Robertz's avatar
Sven Robertz committed
77
        return res;
78
79
}

80
void dumpValStack(labcomm_sig_parser_t *b) {
81
	printf("=== value stack: ");
82
#ifdef DEBUG_STACK_VERBOSE
83
	int i;
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
	printf("=== pointer stack: ");
92
#ifdef DEBUG_STACK_VERBOSE
93
	int i;
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

int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size,
135
                            size_t stacksize, size_t num_signatures,
136
                            size_t max_name_len, size_t max_sig_len)
137
138
139
{
	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
	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
158
	b->sig_ts=calloc(num_signatures, sizeof(struct labcomm_signature));
159
160
161
162
163
164
165
166
167
168
	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
int peek_varint(labcomm_sig_parser_t *b, size_t *size) {
Sven Robertz's avatar
Sven Robertz committed
201
        return unpack_varint(b->c, b->idx, size);
202
203
}

204
205
206
int get_varint(labcomm_sig_parser_t *b) {
        size_t size;
        int res = peek_varint(b, &size);
Sven Robertz's avatar
Sven Robertz committed
207
208
        advancen(b, size);
        return res;
209
}
210
int get_varint_size(labcomm_sig_parser_t *b, size_t *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, unsigned char *dest, size_t size) {
217
	int rem = b->size - b->idx;
218
	if( size > rem )
219
		size = rem;
220
	strncpy((char *)dest, (char *)&b->c[b->idx], size);
221
222
223
	b->idx += size;
}

224
struct labcomm_signature *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
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
{
	switch(type) {
		case TYPE_BOOLEAN :
268
		case TYPE_BYTE :
269
			return 1;
270
		case TYPE_SHORT :
271
272
			return 2;
		case TYPE_INTEGER :
273
		case TYPE_FLOAT :
274
275
			return 4;
		case TYPE_LONG :
276
		case TYPE_DOUBLE :
277
278
			return 8;
		default:
279
280
			printf("labcomm_sizeof_primitive(%x)\n", type);
		 	error("labcomm_sizeof_primitive should only be called for primitive types");
281
            return 0;
282
283
284
	}
}

285
//these are inlined in do_accept_packet
286
287
288
289
290
291
//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_type(labcomm_sig_parser_t *d);
static int accept_array_decl(labcomm_sig_parser_t *d);
292
293
294
295
#if 0  
// UNUSED declarations
static int accept_string_length(labcomm_sig_parser_t *d);
static int accept_char(labcomm_sig_parser_t *d);
296
297
298
299
300
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_number_of_fields(labcomm_sig_parser_t *d);
301
302
#endif
static int accept_struct_decl(labcomm_sig_parser_t *d);
303
304
static int accept_field(labcomm_sig_parser_t *d);
static int accept_sample_data(labcomm_sig_parser_t *d);
305

Sven Robertz's avatar
Sven Robertz committed
306
307
308
309
310
311
312
313
314
315
316
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;
	}
}
317
int encoded_size_static(struct labcomm_signature *sig, void *unused)
318
{
319
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
320
	if(sig->cached_encoded_size == -1) {
321
		error("encoded_size_static called for var_size sample or uninitialized signature");
322
	}
323
	return sig->cached_encoded_size;
324
325
326
327
#else
	printf("Warning: encoded_size_static currently broken\n");
	return -1;
#endif
328
329
}

330
331
/* This function probably never will be implemented, as it would be
   similar to skip_packed_sample_data. And if unregistered variable size
332
333
334
335
   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.
*/
336

337
int encoded_size_parse_sig(struct labcomm_signature *sig, void *sample)
338
339
340
341
342
{
	printf("Warning: encoded_size_parse_sig not implemented\n");
	return -1;
}

343
344
345
346
347
348
349
350
351
352
353
354
355
356
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);
357
        get_varint(d); // ignore sig len
358
		VERBOSE_PRINTF("\ntype = ");
359
360
361
		accept_type(d);
		//printf(" : ");
		//unsigned int dt = pop(d);
362
#ifdef USE_TYPE_AND_SIZE
363
364
		unsigned int type = pop_val(d);
		unsigned int enc_size = pop_val(d);
365
366
367
368
#else
		pop_val(d); // unsigned int type
		pop_val(d); // unsigned int enc_size
#endif
369
370
371
		unsigned int end = d->idx;
		unsigned int len = end-start;

372
373
		struct labcomm_signature *newsig = get_sig_t(d, uid);
//		newsig->type = type;
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
		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...");
		}
391
		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);
392
		INFO_PRINTF("SIG: %s\n", newsig->name);
393
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
394
395
396
397
398
399
400
401
402
		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");
		}
403
#endif
404
405
		return TRUE;
	} else {
406
		error("sample_decl with uid < LABCOMM_USER");
407
408
409
410
		return FALSE;
	}
}

411
// HERE BE DRAGONS! what does the return value mean?
412
int accept_packet(labcomm_sig_parser_t *d) {
413
        size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
414
        unsigned int type = peek_varint(d, &nbytes) ;
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
415
    if(type == VERSION ) {
416
417
418
419
420
421
422
423
424
		advancen(d, nbytes);//consume type field
        get_varint(d); //ignore length field
		VERBOSE_PRINTF("got version.\n");
        accept_string(d);
	    pop_val(d); // ignore length, for now
#ifdef RETURN_STRINGS
            char *str = (char *) pop_ptr(d);
            free(str);
#endif
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
425
    }else if(type == TYPE_DECL ) {
426
		//XXX is this used? If so, is it correct?
Sven Robertz's avatar
Sven Robertz committed
427
		advancen(d, nbytes);
428
429
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
		VERBOSE_PRINTF("type_decl ");
430
        get_varint(d); //ignore length field
431
		accept_signature(d);
432
	} else if (type == SAMPLE_DECL) {
433
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
Sven Robertz's avatar
Sven Robertz committed
434
		advancen(d, nbytes);
435
		VERBOSE_PRINTF("sample_decl ");
436
        get_varint(d); //ignore length field
437
		accept_signature(d);
438
	} else if(type >= LABCOMM_USER) {
439
#ifdef EXIT_WHEN_RECEIVING_DATA
440
441
		printf("*** got sample data, exiting\n");
		exit(0);
442
443
444
#else
		accept_sample_data(d);
#endif
445
	} else {
446
447
#ifdef EXIT_ON_UNKNOWN_TAG
        error("got unknown type (<LABCOMM_USER)");
448
		exit(1);
449
450
451
452
453
#else
        int len = get_varint(d); //ignore length field
        printf("got unknown tag: 0x%x, skipping %d bytes\n",type, len);
        advancen(d, len);
#endif
454
	}
455
    return TRUE;
456
457
}

458
static int accept_user_id(labcomm_sig_parser_t *d){
459
460
    size_t nbytes;
	int uid = peek_varint(d, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
461
462
	if(uid >= LABCOMM_USER) {
		advancen(d, nbytes);
463
		VERBOSE_PRINTF("uid = 0x%x ", uid);
464
		push_val(d, uid);
465
466
467
468
469
470
		return TRUE;
	} else {
		return FALSE;
	}
}

471
static int accept_string(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
472
	unsigned int len = get_varint(d);
473
474
	unsigned char *str=malloc(len);
	getStr(d, str, len);
475
	VERBOSE_PRINTF("%s", str);
476
#ifdef RETURN_STRINGS
477
	push_ptr(d, str);
478
479
480
#else
	free(str);
#endif
481
	push_val(d, len);
482
483
	return TRUE;
}
Sven Robertz's avatar
Sven Robertz committed
484
/* pushes size and type id */
485
static int accept_type(labcomm_sig_parser_t *d){
486
	size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
487
        unsigned int type = peek_varint(d, &nbytes) ;
488
489
	switch(type) {
		case TYPE_BOOLEAN :
490
			VERBOSE_PRINTF("boolean\n");
Sven Robertz's avatar
Sven Robertz committed
491
			advancen(d, nbytes);
492
			push_val(d, 1);
493
494
			break;
		case TYPE_BYTE :
495
			VERBOSE_PRINTF("byte\n");
Sven Robertz's avatar
Sven Robertz committed
496
			advancen(d, nbytes);
497
			push_val(d,  1);
498
499
			break;
		case TYPE_SHORT :
500
			VERBOSE_PRINTF("short\n");
Sven Robertz's avatar
Sven Robertz committed
501
			advancen(d, nbytes);
502
			push_val(d,  2);
503
504
			break;
		case TYPE_INTEGER :
505
			VERBOSE_PRINTF("integer\n");
Sven Robertz's avatar
Sven Robertz committed
506
			advancen(d, nbytes);
507
			push_val(d,  4);
508
509
			break;
		case TYPE_LONG :
510
			VERBOSE_PRINTF("long\n");
Sven Robertz's avatar
Sven Robertz committed
511
			advancen(d, nbytes);
512
			push_val(d,  8);
513
514
			break;
		case TYPE_FLOAT :
515
			VERBOSE_PRINTF("float\n");
Sven Robertz's avatar
Sven Robertz committed
516
			advancen(d, nbytes);
517
			push_val(d,  4);
518
519
			break;
		case TYPE_DOUBLE :
520
			VERBOSE_PRINTF("double\n");
Sven Robertz's avatar
Sven Robertz committed
521
			advancen(d, nbytes);
522
			push_val(d,  8);
523
524
			break;
		case TYPE_STRING :
525
			VERBOSE_PRINTF("string\n");
Sven Robertz's avatar
Sven Robertz committed
526
			advancen(d, nbytes);
527
			labcomm_sig_parser_t_set_varsize(d);
528
			push_val(d, 0);
529
530
531
			break;
		case ARRAY_DECL :
			accept_array_decl(d);
Sven Robertz's avatar
Sven Robertz committed
532
533
			pop_val(d); // ignore element type
			// push(d, pop(d) is a NOP --> leave size on stack
534
535
536
			break;
		case STRUCT_DECL :
			accept_struct_decl(d);
Sven Robertz's avatar
Sven Robertz committed
537
			// push(d, pop(d) is a NOP --> leave size on stack
538
539
			break;
		default :
540
			printf("accept_type default (type==%x) should not happen\n", type);
541
			push_val(d, 0);
Sven Robertz's avatar
Sven Robertz committed
542
			push_val(d, type);
543
544
			return FALSE;
	}
545
	push_val(d, type);
546
547
548
	return TRUE;
}

Sven Robertz's avatar
Sven Robertz committed
549
/* pushes size and element type */
550
static int accept_array_decl(labcomm_sig_parser_t *d){
551
552
        size_t nbytes;
        int tid = peek_varint(d, &nbytes) ;
553
	if(tid == ARRAY_DECL) {
Sven Robertz's avatar
Sven Robertz committed
554
555
		advancen(d, nbytes);
		unsigned int nidx = get_varint(d);
556
		VERBOSE_PRINTF("%d dim array", nidx);
557
558
559
560
		int i;
		unsigned int numVar=0;
		unsigned int size=1;
		for(i=0; i<nidx; i++) {
Sven Robertz's avatar
Sven Robertz committed
561
			unsigned int idx = get_varint(d);
562
563
			if(idx == 0) {
				numVar++;
564
				VERBOSE_PRINTF("[_] ");
565
				labcomm_sig_parser_t_set_varsize(d);
566
			} else {
567
				VERBOSE_PRINTF("[%d] ", idx);
568
569
570
				size*=idx;
			}
		}
571
		VERBOSE_PRINTF(" of ");
572
		accept_type(d);
573
574
		unsigned int et= pop_val(d);  // type
		unsigned int es= pop_val(d);  // (encoded) size
575
576
577
578
579
#ifdef DEBUG
		printf("accept_array_decl: et = %x\n", et);
#endif
		if(numVar == 0) {
#ifdef DEBUG
580
			printf("size=%d, es=%d\n", size, es);
581
#endif
582
			push_val(d,  (size*es));
583
		} else {
Sven Robertz's avatar
Sven Robertz committed
584
585
//HERE BE DRAGONS! push a (non-) size for variable size arrays?
			push_val(d, 0);
586
		}
Sven Robertz's avatar
Sven Robertz committed
587
		push_val(d, et);
588
589
590
		return TRUE;
	} else {
		printf("accept_array_decl: type=%x, should not happen\n",tid);
591
592
		push_val(d, 0);
		push_val(d, tid);
593
594
595
		return FALSE;
	}
}
596
597

/* pushes size */
598
static int accept_struct_decl(labcomm_sig_parser_t *d){
599
600
	size_t nbytes;
        int tid = peek_varint(d, &nbytes) ;
601
	if(tid == STRUCT_DECL) {
Sven Robertz's avatar
Sven Robertz committed
602
603
		advancen(d, nbytes);
		unsigned int nf = get_varint(d);
604
		VERBOSE_PRINTF("%d field struct:\n", nf);
605
		int i;
606
#ifdef USE_UNUSED_VARS
607
608
		int numVar=0;
		int size=0;
609
#endif
610
		unsigned int fieldsizes=0;
611
612
		for(i=0; i<nf; i++) {
			accept_field(d);
613
			fieldsizes += pop_val(d);
614
		}
615
		push_val(d, fieldsizes);
616
617
618
		return TRUE;
	} else {
		printf("accept_struct_decl: type=%x, should not happen\n",tid);
619
		push_val(d, 0);
620
621
622
		return FALSE;
	}
}
623

Sven Robertz's avatar
Sven Robertz committed
624
/* pushes field size */
625
static int accept_field(labcomm_sig_parser_t *d){
626
	VERBOSE_PRINTF("\tfield name: ");
627
	accept_string(d);
628
	pop_val(d); // ignore length, for now
Sven Robertz's avatar
Sven Robertz committed
629
#ifdef RETURN_STRINGS
630
		char *str = (char *) pop_ptr(d);
Sven Robertz's avatar
Sven Robertz committed
631
632
		free(str);
#endif
633
	VERBOSE_PRINTF("\n\ttype: ");
634
	accept_type(d);
635
	pop_val(d); // ignore type, for now
Sven Robertz's avatar
Sven Robertz committed
636
	// push(pop() is really a NOP , leave size on the stack when debugging done
637
	VERBOSE_PRINTF("\n");
638
	return TRUE;
639
}
640
static int accept_sample_data(labcomm_sig_parser_t *d){
641
	accept_user_id(d);
642
	unsigned int uid = pop_val(d);
643
	printf("sample data... uid=0x%x\n", uid);
644
    int len = get_varint(d); //length field
645
#ifdef DEBUG
646
	dump_signature(d, uid);
647
#endif
648
#ifdef SKIP_BY_PARSING
649
650
	struct labcomm_signature *sigt = get_sig_t(d, uid);
	int encoded_size = sigt->encoded_size(NULL);
651
	INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
652
	struct labcomm_signature *sig = get_sig_t(d, uid);
653
	skip_packed_sample_data(d, sig);
654
655
656
#else
	advancen(d, len);
#endif
657
658
659
	return TRUE;
}

660
static int skip_type(unsigned int,labcomm_sig_parser_t*,unsigned char*,unsigned int,int*) ;
661

662
static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, int len, int *pos) {
663
664
	unsigned int skip = 0;
	unsigned int tot_nbr_elem_tmp = 1;
665
	size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
666
	unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
667
	VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
Sven Robertz's avatar
Sven Robertz committed
668
	*pos +=nbytes;
669
670
671
672
673
674
	unsigned int idx[nIdx];
	unsigned int nVar=0;

	unsigned int i;

	for(i=0; i<nIdx; i++) {
Sven Robertz's avatar
Sven Robertz committed
675
676
		idx[i] = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
677
		VERBOSE_PRINTF("skip_array: idx[%d]=%d (from sig)\n", i, idx[i]);
678
679
680
681
682
683
		if(idx[i] == 0) {
			nVar++;
		} else {
			tot_nbr_elem_tmp *= idx[i];
		}
	}
684
	int var[nVar];
685

Sven Robertz's avatar
Sven Robertz committed
686
	unsigned char varSize=0; // total number of bytes required for var size fields
687
	for(i=0; i<nVar; i++) {
688
		var[i] = get_varint_size(d, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
689
		varSize += nbytes;
690
		VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
Sven Robertz's avatar
Sven Robertz committed
691
		tot_nbr_elem_tmp *= var[i];
692
693
	}

694
	int type = unpack_varint(sig, *pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
695
	*pos+=nbytes;
696

697
	unsigned int elemSize = labcomm_sizeof_primitive(type);
698
699
700

	skip = elemSize * tot_nbr_elem_tmp;

701
	VERBOSE_PRINTF("skip_array: skip: %d * %d = %d\n", tot_nbr_elem_tmp, elemSize ,skip);
702

703
704
	advancen(d, skip);

Sven Robertz's avatar
Sven Robertz committed
705
706
	//return skip + 4*nVar;
	return skip + varSize;
707
708
}

709
710
int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, int *pos) {
	size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
711
712
	unsigned int nFields = unpack_varint(sig,*pos, &nbytes);
	*pos += nbytes;
713
714
	unsigned int i;
	unsigned int skipped=0;
715
	VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
716
	for(i=0; i<nFields; i++) {
717
		//skip name
Sven Robertz's avatar
Sven Robertz committed
718
		unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
719
#ifdef DEBUG
720
		VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
Sven Robertz's avatar
Sven Robertz committed
721
		char name[namelen+1]; //HERE BE DRAGONS. alloca?
Sven Robertz's avatar
Sven Robertz committed
722
		strncpy(name, sig+*pos+nbytes, namelen);
723
		name[namelen]=0;
724
		VERBOSE_PRINTF("----name = %s\n",name);
725
#endif
Sven Robertz's avatar
Sven Robertz committed
726
		*pos += (nbytes+namelen); // 32bit len + actual string
Sven Robertz's avatar
Sven Robertz committed
727

Sven Robertz's avatar
Sven Robertz committed
728
729
		unsigned int type = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
730
#ifdef DEBUG
731
		VERBOSE_PRINTF("----type == %x\n", type);
732
733
734
735
736
737
738
#endif
		skipped += skip_type(type, d, sig, len, pos);
	}
	return skipped;
}
#ifndef QUIET
/* print and skip */
739
740
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
		unsigned char *sig, unsigned int len, int *pos)
741
742
743
744
745
746
747
748
{
	int skipped=0;
	printf("skip_type %x:", type);
	switch(type) {
		case TYPE_BOOLEAN :
			printf("boolean [%d]\n", get(d));
			skipped++;
			break;
749
		case TYPE_BYTE :
750
751
752
			printf("byte [%d]\n", get(d));
			skipped++;
			break;
753
		case TYPE_SHORT :
754
			//XXX not supported
755
			advancen(d,2);
756
757
758
759
760
761
			skipped+=2;
			break;
		case TYPE_INTEGER :
			printf("integer [%d]\n", get32(d));
			skipped +=4;
			break;
762
		case TYPE_FLOAT :
763
			//XXX not supported
764
			advancen(d,4);
765
766
767
			skipped+=4;
			break;
		case TYPE_LONG :
768
		case TYPE_DOUBLE :
769
			//XXX not supported
770
			advancen(d,8);
771
772
773
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
774
			{
775
776
			size_t nbytes;
			int len = get_varint_size(d, &nbytes);
777
778
779
780
781
			int i;
			printf("string [");
			for(i=0; i<len; i++)
				printf("%c", get(d));
			printf("]\n");
Sven Robertz's avatar
Sven Robertz committed
782
			skipped+=len+nbytes;
783
784
785
786
			break;}
		case ARRAY_DECL :
			printf("array\n");
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
787
			break;
788
789
790
791
792
793
794
795
796
797
798
		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
799
800
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
		unsigned char *sig, unsigned int len, int *pos)
801
802
{
	int skipped=0;
803
	VERBOSE_PRINTF("skip_type %x\n", type);
804
805
	switch(type) {
		case TYPE_BOOLEAN :
806
807
		case TYPE_BYTE :
			advancen(d,1);
808
809
			skipped++;
			break;
810
811
		case TYPE_SHORT :
			advancen(d,2);
812
813
814
			skipped+=2;
			break;
		case TYPE_INTEGER :
815
816
		case TYPE_FLOAT :
			advancen(d,4);
817
818
819
			skipped+=4;
			break;
		case TYPE_LONG :
820
821
		case TYPE_DOUBLE :
			advancen(d,8);
822
823
824
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
825
			{
826
827
			size_t nbytes;
			int len = get_varint_size(d, &nbytes);
828
			advancen(d,len);
Sven Robertz's avatar
Sven Robertz committed
829
			skipped+=len+nbytes;
830
831
832
			break;}
		case ARRAY_DECL :
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
833
			break;
834
835
836
837
838
839
840
841
842
843
844
		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

845
/* parse signature and skip the corresponding bytes in the labcomm_sig_parser_t
846
 */
847
int skip_packed_sample_data(labcomm_sig_parser_t *d, struct labcomm_signature *sig) {
848
	int pos = 0; 		//current position in signature
849
	unsigned int skipped = 0;	//skipped byte counter
850
	while(pos < sig->size) {
851
		size_t nbytes;
852
		unsigned int type = unpack_varint(sig->signature,pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
853
		pos+=nbytes;
854
		skipped += skip_type(type, d, sig->signature, sig->size, &pos);
855
	}