labcomm_sig_parser.c 24.5 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
19
20
21
 * - 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
22
 */
23

Sven Robertz's avatar
Sven Robertz committed
24
25


26
27
28
29
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

30
#include "labcomm_sig_parser.h"
Sven Robertz's avatar
Sven Robertz committed
31

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

/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
39
40
41
42
43
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
44
45
46

       return  b0 | b1 | b2 | b3;
}
47

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


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

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

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

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

99
void push_val(labcomm_sig_parser_t *b, unsigned int e) {
100
101
	b->val_stack[b->val_top]=e;
	b->val_top=b->val_top-1;
102
103
	if(b->val_top<0) error("value stack overrun");
#if defined DEBUG && !defined QUIET_STACK
104
	dumpValStack(b);
Sven Robertz's avatar
Sven Robertz committed
105
#endif
106
}
107
unsigned int pop_val(labcomm_sig_parser_t *b) {
108
	b->val_top=b->val_top+1;
109
110
111
112
	if(b->val_top>b->stacksize) error("value stack underrun");
#if defined DEBUG && !defined QUIET_STACK
	dumpValStack(b);
#endif
113
114
	return b->val_stack[b->val_top];
}
115
void push_ptr(labcomm_sig_parser_t *b, void* e) {
116
117
	b->ptr_stack[b->ptr_top]=e;
	b->ptr_top=b->ptr_top-1;
118
	if(b->ptr_top<0) error("pointer stack overrun");
Sven Robertz's avatar
Sven Robertz committed
119
#ifdef DEBUG
120
	dumpPtrStack(b);
Sven Robertz's avatar
Sven Robertz committed
121
#endif
122
}
123
void* pop_ptr(labcomm_sig_parser_t *b) {
124
	b->ptr_top=b->ptr_top+1;
125
126
127
128
	if(b->ptr_top>b->stacksize) error("pointer stack underrun");
#ifdef DEBUG
	dumpPtrStack(b);
#endif
129
	return b->ptr_stack[b->ptr_top];
130
}
131
132

int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size,
133
                            size_t stacksize, size_t num_signatures,
134
                            size_t max_name_len, size_t max_sig_len)
135
136
137
{
	b->c = malloc(buffer_size);
	b->capacity = buffer_size;
138
	b->size = 0;
139
140
	b->idx = 0;

141
	b->stacksize = stacksize;
142

143
144
145
146
147
148
	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;

149
150
151
152
153
154
155
	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
156
	b->sig_ts=calloc(num_signatures, sizeof(struct labcomm_signature));
157
158
159
160
161
162
163
164
165
166
	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
167
	return b->c == NULL || b->val_stack == NULL || b->ptr_stack == NULL;
168
169
}

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

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

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

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

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

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

198
int peek_varint(labcomm_sig_parser_t *b, size_t *size) {
Sven Robertz's avatar
Sven Robertz committed
199
        return unpack_varint(b->c, b->idx, size);
200
201
}

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

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

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

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

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

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

247
void dump_signature(labcomm_sig_parser_t *p, unsigned int uid){
248
	int i;
249
250
251
	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);
252
253
	for(i=0; i<len; i++) {
		printf("%2.2x ",sig[i]);
254
		if( i < len-1 && (i+1)%8==0 ) printf("\n");
255
256
257
258
	}
	printf("\n");
}

259
static inline void labcomm_sig_parser_t_set_varsize(labcomm_sig_parser_t *b)
260
261
262
{
	b->current_decl_is_varsize = TRUE;
}
263
static size_t labcomm_sizeof_primitive(unsigned int type)
264
265
266
{
	switch(type) {
		case TYPE_BOOLEAN :
267
		case TYPE_BYTE :
268
			return 1;
269
		case TYPE_SHORT :
270
271
			return 2;
		case TYPE_INTEGER :
272
		case TYPE_FLOAT :
273
		case TYPE_SAMPLE_REF :
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
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
static int accept_signature(labcomm_sig_parser_t *d, 
                            labcomm_type type,
                            unsigned int start,
                            unsigned int uid, char *name)
{
    get_varint(d); // ignore sig len
    VERBOSE_PRINTF("\ntype = ");
    accept_type(d);
    //printf(" : ");
    //unsigned int dt = pop(d);
#ifdef USE_TYPE_AND_SIZE
    unsigned int type = pop_val(d);
    unsigned int enc_size = pop_val(d);
#else
    pop_val(d); // unsigned int type
    pop_val(d); // unsigned int enc_size
#endif
    if(type != PKG_SAMPLE_DECL) {
        if(type == PKG_SAMPLE_REF) {
            INFO_PRINTF("accept_signature: ignoring sample ref\n");
            return TRUE;
        } else if (type == PKG_TYPE_DECL) {
            INFO_PRINTF("accept_signature: ignoring typedef\n");
            return TRUE;
        } else {
            error("decl is neither sample, ref, or typedef???");
            return FALSE;
        }
    }
    unsigned int end = d->idx;
    unsigned int len = end-start;

    struct labcomm_signature *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];
        newsig->name = name;
    } else {
        error("sig longer than max length (this ought to be dynamic...)");
    }
    VERBOSE_PRINTF("signature for uid %x: %s (start=%x,end=%x,len=%d)\n", uid, get_signature_name(d, uid), start,end, len);
    INFO_PRINTF("accept_signature: %s\n", newsig->name);
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
    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");
    }
#endif
    return TRUE;
}
static int accept_decl(labcomm_sig_parser_t *d, labcomm_type type)
402
403
404
405
406
407
408
409
410
411
412
413
414
415
{
	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);

416
417
418
419
420
421
        if(type != PKG_SAMPLE_DECL) {
            // don't record typedefs and samplerefs (for now)
            // to avoid number clashes with sample defs
            // in the parser struct 
            return accept_signature(d, type, start, uid, (char *) &d->c[nstart+lenlen]);
        }
422
		if(nlen < d->max_name_len) { // leave 1 byte for terminating NULL
423
            char *name;
424
425
426
			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;
427
428
			name = d->signatures_name[uid-LABCOMM_USER];
            return accept_signature(d, type, start, uid, name);
429
430
		} else {
			error("sig name longer than max length (this ought to be dynamic...");
431
            return FALSE;
432
433
		}
	} else {
434
		error("sample_decl with uid < LABCOMM_USER");
435
436
437
438
		return FALSE;
	}
}

439
// HERE BE DRAGONS! what does the return value mean?
440
int accept_packet(labcomm_sig_parser_t *d) {
441
        size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
442
        unsigned int type = peek_varint(d, &nbytes) ;
443
    if(type == PKG_VERSION ) {
444
445
446
447
448
449
450
451
452
		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
453
454
	} else if (type == PKG_SAMPLE_DECL) {
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
Sven Robertz's avatar
Sven Robertz committed
455
		advancen(d, nbytes);
456
457
458
459
		VERBOSE_PRINTF("sample_decl ");
        get_varint(d); //ignore length field
		accept_decl(d, type);
	} else if (type == PKG_SAMPLE_REF) {
460
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
461
462
		advancen(d, nbytes);
		VERBOSE_PRINTF("sample_ref ");
463
        get_varint(d); //ignore length field
464
465
		accept_decl(d, type);
    }else if(type == PKG_TYPE_DECL ) {
466
		d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
467
468
469
470
471
472
		advancen(d, nbytes);//consume type field
		VERBOSE_PRINTF("type_decl ");
        get_varint(d); //ignore length field
		accept_decl(d, type);
	} else if (type == PKG_TYPE_BINDING) {
		VERBOSE_PRINTF("type_binding ");
Sven Robertz's avatar
Sven Robertz committed
473
		advancen(d, nbytes);
474
        get_varint(d); //ignore length field
475
476
477
478
479
480
481
482
483
#ifdef VERBOSE        
        int sid = 
#endif            
            get_varint(d); //ignore sample id field
#ifdef VERBOSE        
        int tid =
#endif            
            get_varint(d); //ignore type id field
		VERBOSE_PRINTF("sid=0x%x, tid=0x%x\n ", sid, tid);
484
	} else if(type >= LABCOMM_USER) {
485
#ifdef EXIT_WHEN_RECEIVING_DATA
486
487
		printf("*** got sample data, exiting\n");
		exit(0);
488
489
490
#else
		accept_sample_data(d);
#endif
491
	} else {
492
493
#ifdef EXIT_ON_UNKNOWN_TAG
        error("got unknown type (<LABCOMM_USER)");
494
		exit(1);
495
#else
496
        int len = get_varint(d); // length field
497
498
499
        printf("got unknown tag: 0x%x, skipping %d bytes\n",type, len);
        advancen(d, len);
#endif
500
	}
501
    return TRUE;
502
503
}

504
static int accept_user_id(labcomm_sig_parser_t *d){
505
506
    size_t nbytes;
	int uid = peek_varint(d, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
507
508
	if(uid >= LABCOMM_USER) {
		advancen(d, nbytes);
509
		VERBOSE_PRINTF("uid = 0x%x ", uid);
510
		push_val(d, uid);
511
512
		return TRUE;
	} else {
513
        error("uid < LABCOMM_USER");
514
515
516
517
		return FALSE;
	}
}

518
static int accept_string(labcomm_sig_parser_t *d){
Sven Robertz's avatar
Sven Robertz committed
519
	unsigned int len = get_varint(d);
520
	unsigned char *str=malloc(len+1); // len is without terminating null
521
	getStr(d, str, len);
522
	VERBOSE_PRINTF("%s", str);
523
#ifdef RETURN_STRINGS
524
	push_ptr(d, str);
525
526
527
#else
	free(str);
#endif
528
	push_val(d, len);
529
530
	return TRUE;
}
Sven Robertz's avatar
Sven Robertz committed
531
/* pushes size and type id */
532
static int accept_type(labcomm_sig_parser_t *d){
533
	size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
534
        unsigned int type = peek_varint(d, &nbytes) ;
535
536
	switch(type) {
		case TYPE_BOOLEAN :
537
			VERBOSE_PRINTF("boolean\n");
Sven Robertz's avatar
Sven Robertz committed
538
			advancen(d, nbytes);
539
			push_val(d, 1);
540
541
			break;
		case TYPE_BYTE :
542
			VERBOSE_PRINTF("byte\n");
Sven Robertz's avatar
Sven Robertz committed
543
			advancen(d, nbytes);
544
			push_val(d,  1);
545
546
			break;
		case TYPE_SHORT :
547
			VERBOSE_PRINTF("short\n");
Sven Robertz's avatar
Sven Robertz committed
548
			advancen(d, nbytes);
549
			push_val(d,  2);
550
551
			break;
		case TYPE_INTEGER :
552
			VERBOSE_PRINTF("integer\n");
Sven Robertz's avatar
Sven Robertz committed
553
			advancen(d, nbytes);
554
			push_val(d,  4);
555
556
			break;
		case TYPE_LONG :
557
			VERBOSE_PRINTF("long\n");
Sven Robertz's avatar
Sven Robertz committed
558
			advancen(d, nbytes);
559
			push_val(d,  8);
560
561
			break;
		case TYPE_FLOAT :
562
			VERBOSE_PRINTF("float\n");
Sven Robertz's avatar
Sven Robertz committed
563
			advancen(d, nbytes);
564
			push_val(d,  4);
565
566
			break;
		case TYPE_DOUBLE :
567
			VERBOSE_PRINTF("double\n");
Sven Robertz's avatar
Sven Robertz committed
568
			advancen(d, nbytes);
569
			push_val(d,  8);
570
571
			break;
		case TYPE_STRING :
572
			VERBOSE_PRINTF("string\n");
Sven Robertz's avatar
Sven Robertz committed
573
			advancen(d, nbytes);
574
			labcomm_sig_parser_t_set_varsize(d);
575
			push_val(d, 0);
576
			break;
577
578
579
580
581
		case TYPE_SAMPLE_REF :
			VERBOSE_PRINTF("sample\n");
			advancen(d, nbytes);
			push_val(d,  4);
			break;
582
583
		case ARRAY_DECL :
			accept_array_decl(d);
Sven Robertz's avatar
Sven Robertz committed
584
585
			pop_val(d); // ignore element type
			// push(d, pop(d) is a NOP --> leave size on stack
586
587
588
			break;
		case STRUCT_DECL :
			accept_struct_decl(d);
Sven Robertz's avatar
Sven Robertz committed
589
			// push(d, pop(d) is a NOP --> leave size on stack
590
591
			break;
		default :
592
593
594
595
            //should we distinguish between SAMPLE_DEF and TYPE_DEF here?
			//printf("accept_type default (type==%x) should not happen\n", type);
			VERBOSE_PRINTF("user type 0x%x\n",type);
			advancen(d, nbytes);
596
			push_val(d, 0);
Sven Robertz's avatar
Sven Robertz committed
597
			push_val(d, type);
598
599
			return FALSE;
	}
600
	push_val(d, type);
601
602
603
	return TRUE;
}

Sven Robertz's avatar
Sven Robertz committed
604
/* pushes size and element type */
605
static int accept_array_decl(labcomm_sig_parser_t *d){
606
607
        size_t nbytes;
        int tid = peek_varint(d, &nbytes) ;
608
	if(tid == ARRAY_DECL) {
Sven Robertz's avatar
Sven Robertz committed
609
610
		advancen(d, nbytes);
		unsigned int nidx = get_varint(d);
611
		VERBOSE_PRINTF("%d dim array", nidx);
612
613
614
615
		int i;
		unsigned int numVar=0;
		unsigned int size=1;
		for(i=0; i<nidx; i++) {
Sven Robertz's avatar
Sven Robertz committed
616
			unsigned int idx = get_varint(d);
617
618
			if(idx == 0) {
				numVar++;
619
				VERBOSE_PRINTF("[_] ");
620
				labcomm_sig_parser_t_set_varsize(d);
621
			} else {
622
				VERBOSE_PRINTF("[%d] ", idx);
623
624
625
				size*=idx;
			}
		}
626
		VERBOSE_PRINTF(" of ");
627
		accept_type(d);
628
629
		unsigned int et= pop_val(d);  // type
		unsigned int es= pop_val(d);  // (encoded) size
630
631
632
633
634
#ifdef DEBUG
		printf("accept_array_decl: et = %x\n", et);
#endif
		if(numVar == 0) {
#ifdef DEBUG
635
			printf("size=%d, es=%d\n", size, es);
636
#endif
637
			push_val(d,  (size*es));
638
		} else {
Sven Robertz's avatar
Sven Robertz committed
639
640
//HERE BE DRAGONS! push a (non-) size for variable size arrays?
			push_val(d, 0);
641
		}
Sven Robertz's avatar
Sven Robertz committed
642
		push_val(d, et);
643
644
645
		return TRUE;
	} else {
		printf("accept_array_decl: type=%x, should not happen\n",tid);
646
647
		push_val(d, 0);
		push_val(d, tid);
648
649
650
		return FALSE;
	}
}
651
652

/* pushes size */
653
static int accept_struct_decl(labcomm_sig_parser_t *d){
654
655
	size_t nbytes;
        int tid = peek_varint(d, &nbytes) ;
656
	if(tid == STRUCT_DECL) {
Sven Robertz's avatar
Sven Robertz committed
657
658
		advancen(d, nbytes);
		unsigned int nf = get_varint(d);
659
660
661
662
663
        if(nf == 0) {
            VERBOSE_PRINTF("void\n");
        } else {
            VERBOSE_PRINTF("%d field struct:\n", nf);
        }
664
		int i;
665
#ifdef USE_UNUSED_VARS
666
667
		int numVar=0;
		int size=0;
668
#endif
669
		unsigned int fieldsizes=0;
670
671
		for(i=0; i<nf; i++) {
			accept_field(d);
672
			fieldsizes += pop_val(d);
673
		}
674
		push_val(d, fieldsizes);
675
676
677
		return TRUE;
	} else {
		printf("accept_struct_decl: type=%x, should not happen\n",tid);
678
		push_val(d, 0);
679
680
681
		return FALSE;
	}
}
682

Sven Robertz's avatar
Sven Robertz committed
683
/* pushes field size */
684
static int accept_field(labcomm_sig_parser_t *d){
685
	VERBOSE_PRINTF("\tfield name: ");
686
	accept_string(d);
687
	pop_val(d); // ignore length, for now
Sven Robertz's avatar
Sven Robertz committed
688
#ifdef RETURN_STRINGS
689
		char *str = (char *) pop_ptr(d);
Sven Robertz's avatar
Sven Robertz committed
690
691
		free(str);
#endif
692
	VERBOSE_PRINTF("\n\ttype: ");
693
	accept_type(d);
694
	pop_val(d); // ignore type, for now
Sven Robertz's avatar
Sven Robertz committed
695
	// push(pop() is really a NOP , leave size on the stack when debugging done
696
	VERBOSE_PRINTF("\n");
697
	return TRUE;
698
}
699
static int accept_sample_data(labcomm_sig_parser_t *d){
700
	accept_user_id(d);
701
	unsigned int uid = pop_val(d);
702
	printf("sample data... uid=0x%x\n", uid);
703
    int len = get_varint(d); //length field
704
#ifdef DEBUG
705
	dump_signature(d, uid);
706
#endif
707
#ifdef SKIP_BY_PARSING
708
709
	struct labcomm_signature *sigt = get_sig_t(d, uid);
	int encoded_size = sigt->encoded_size(NULL);
710
	INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
711
	struct labcomm_signature *sig = get_sig_t(d, uid);
712
	skip_packed_sample_data(d, sig);
713
714
715
#else
	advancen(d, len);
#endif
716
717
718
	return TRUE;
}

719
static int skip_type(unsigned int,labcomm_sig_parser_t*,unsigned char*,unsigned int,int*) ;
720

721
static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, int len, int *pos) {
722
723
	unsigned int skip = 0;
	unsigned int tot_nbr_elem_tmp = 1;
724
	size_t nbytes;
Sven Robertz's avatar
Sven Robertz committed
725
	unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
726
	VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
Sven Robertz's avatar
Sven Robertz committed
727
	*pos +=nbytes;
728
729
730
731
732
733
	unsigned int idx[nIdx];
	unsigned int nVar=0;

	unsigned int i;

	for(i=0; i<nIdx; i++) {
Sven Robertz's avatar
Sven Robertz committed
734
735
		idx[i] = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
736
		VERBOSE_PRINTF("skip_array: idx[%d]=%d (from sig)\n", i, idx[i]);
737
738
739
740
741
742
		if(idx[i] == 0) {
			nVar++;
		} else {
			tot_nbr_elem_tmp *= idx[i];
		}
	}
743
	int var[nVar];
744

Sven Robertz's avatar
Sven Robertz committed
745
	unsigned char varSize=0; // total number of bytes required for var size fields
746
	for(i=0; i<nVar; i++) {
747
		var[i] = get_varint_size(d, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
748
		varSize += nbytes;
749
		VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
Sven Robertz's avatar
Sven Robertz committed
750
		tot_nbr_elem_tmp *= var[i];
751
752
	}

753
	int type = unpack_varint(sig, *pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
754
	*pos+=nbytes;
755

756
	unsigned int elemSize = labcomm_sizeof_primitive(type);
757
758
759

	skip = elemSize * tot_nbr_elem_tmp;

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

762
763
	advancen(d, skip);

Sven Robertz's avatar
Sven Robertz committed
764
765
	//return skip + 4*nVar;
	return skip + varSize;
766
767
}

768
769
int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, int *pos) {
	size_t nbytes;
770
	int nFields = unpack_varint(sig,*pos, &nbytes);
Sven Robertz's avatar
Sven Robertz committed
771
	*pos += nbytes;
772
773
	unsigned int i;
	unsigned int skipped=0;
774
	VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
775
	for(i=0; i<nFields; i++) {
776
		//skip name
Sven Robertz's avatar
Sven Robertz committed
777
		unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
778
#ifdef DEBUG
779
		VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
Sven Robertz's avatar
Sven Robertz committed
780
		char name[namelen+1]; //HERE BE DRAGONS. alloca?
781
		strncpy(name, (const char *)sig+*pos+nbytes, namelen);
782
		name[namelen]=0;
783
		VERBOSE_PRINTF("----name = %s\n",name);
784
#endif
Sven Robertz's avatar
Sven Robertz committed
785
		*pos += (nbytes+namelen); // 32bit len + actual string
Sven Robertz's avatar
Sven Robertz committed
786

Sven Robertz's avatar
Sven Robertz committed
787
788
		unsigned int type = unpack_varint(sig, *pos, &nbytes);
		*pos += nbytes;
789
#ifdef DEBUG
790
		VERBOSE_PRINTF("----type == %x\n", type);
791
792
793
794
795
796
797
#endif
		skipped += skip_type(type, d, sig, len, pos);
	}
	return skipped;
}
#ifndef QUIET
/* print and skip */
798
799
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
		unsigned char *sig, unsigned int len, int *pos)
800
801
802
803
804
805
806
807
{
	int skipped=0;
	printf("skip_type %x:", type);
	switch(type) {
		case TYPE_BOOLEAN :
			printf("boolean [%d]\n", get(d));
			skipped++;
			break;
808
		case TYPE_BYTE :
809
810
811
			printf("byte [%d]\n", get(d));
			skipped++;
			break;
812
		case TYPE_SHORT :
813
			//XXX not supported
814
			advancen(d,2);
815
816
817
818
819
820
			skipped+=2;
			break;
		case TYPE_INTEGER :
			printf("integer [%d]\n", get32(d));
			skipped +=4;
			break;
821
		case TYPE_FLOAT :
822
			//XXX not supported
823
			advancen(d,4);
824
825
826
			skipped+=4;
			break;
		case TYPE_LONG :
827
		case TYPE_DOUBLE :
828
			//XXX not supported
829
			advancen(d,8);
830
831
832
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
833
			{
834
835
			size_t nbytes;
			int len = get_varint_size(d, &nbytes);
836
837
838
839
840
			int i;
			printf("string [");
			for(i=0; i<len; i++)
				printf("%c", get(d));
			printf("]\n");
Sven Robertz's avatar
Sven Robertz committed
841
			skipped+=len+nbytes;
842
843
844
845
			break;}
		case ARRAY_DECL :
			printf("array\n");
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
846
			break;
847
848
849
850
851
852
853
854
855
856
857
		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
858
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
859
		const char *sig, unsigned int len, int *pos)
860
861
{
	int skipped=0;
862
	VERBOSE_PRINTF("skip_type %x\n", type);
863
864
	switch(type) {
		case TYPE_BOOLEAN :
865
866
		case TYPE_BYTE :
			advancen(d,1);
867
868
			skipped++;
			break;
869
870
		case TYPE_SHORT :
			advancen(d,2);
871
872
873
			skipped+=2;
			break;
		case TYPE_INTEGER :
874
875
		case TYPE_FLOAT :
			advancen(d,4);
876
877
878
			skipped+=4;
			break;
		case TYPE_LONG :
879
880
		case TYPE_DOUBLE :
			advancen(d,8);
881
882
883
			skipped+=8;
			break;
		case TYPE_STRING :
Sven Robertz's avatar
Sven Robertz committed
884
			{
885
886
			size_t nbytes;
			int len = get_varint_size(d, &nbytes);
887
			advancen(d,len);
Sven Robertz's avatar
Sven Robertz committed
888
			skipped+=len+nbytes;
889
890
891
			break;}
		case ARRAY_DECL :
			skipped += skip_array(d, sig, len, pos);
Sven Robertz's avatar
Sven Robertz committed
892
			break;
893
894
895
896
897
898
899
900
901
902
903
		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