Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Show changes
Showing
with 1786 additions and 10 deletions
SUBDIRS=c csharp java python
.PHONY: all
all: $(SUBDIRS:%=make-%)
.PHONY: make-%
make-%:
$(MAKE) -C $*
.PHONY: test
test: $(SUBDIRS:%=test-%)
.PHONY: test-%
test-%:
$(MAKE) -C $* test
.PHONY: clean
clean: $(SUBDIRS:%=clean-%)
.PHONY: clean-%
clean-%:
$(MAKE) -C $* clean
.PHONY: distclean
distclean: clean $(SUBDIRS:%=distclean-%)
.PHONY: distclean-%
distclean-%:
$(MAKE) -C $* distclean
MODULE LabComm(SYSMODULE)
RECORD LabComm_Stream
socketdev soc;
ENDRECORD
RECORD LabComm_Decoder_Sample
string prefix;
string name;
num user_id;
string handler;
ENDRECORD
RECORD LabComm_Encoder_Sample
string prefix;
string name;
num user_id;
ENDRECORD
RECORD Decoder
num user_id;
ENDRECORD
RECORD Encoder
num next_user_id;
ENDRECORD
! LabComm constants
CONST string LabCommVersion := "LabComm2013";
CONST num SAMPLE_DECL:=2;
CONST num SAMPLE_DATA:=64;
CONST num STRUCT_TYPE := 17;
CONST num ARRAY_TYPE := 16;
CONST num BYTE_TYPE := 37;
CONST num BOOL_TYPE := 37;
CONST num SHORT_TYPE := 34;
CONST num INT_TYPE := 37;
CONST num LONG_TYPE := 37;
CONST num FLOAT_TYPE := 37;
! Error declarations
CONST errnum INCORRECT_LABCOMM_VERSION := 50;
CONST errnum UNKNOWN_PACKET_TYPE := 51;
CONST errnum UNKNOWN_SAMPLE_TYPE := 52;
CONST errnum INCORRECT_SAMPLE_SIGNATURE := 53;
CONST errnum SAMPLE_TYPE_NOT_REGISTERED := 54;
CONST errnum IMPLEMENTATION_LIMIT_REACHED := 55;
PROC Decode_Packed(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,v,\IntX:=USINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Packed(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=USINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Boolean(VAR LabComm_Stream s, VAR bool v, \ VAR rawbytes collect)
VAR rawbytes buffer;
VAR num tmp;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,tmp,\IntX:=USINT;
IF tmp = 0 THEN
v := FALSE;
ELSE
v := TRUE;
ENDIF
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Boolean(VAR LabComm_Stream s, bool v)
VAR rawbytes buffer;
VAR num tmp;
IF v THEN
tmp := 1;
ELSE
tmp := 0;
ENDIF
PackRawBytes tmp,buffer,\Network,1,\IntX:=USINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Byte(VAR LabComm_Stream s, VAR byte v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,v,\Hex1;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Byte(VAR LabComm_Stream s, byte v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\Hex1;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Short(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=2;
UnpackRawBytes buffer,\Network,1,v,\IntX:=INT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Short(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v, buffer, \Network, 1, \IntX:=INT;
SocketSend s.soc, \RawData:=buffer, \NoOfBytes:=2;
ERROR
RAISE ;
ENDPROC
PROC Decode_Integer(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
UnpackRawBytes buffer,\Network,1,v,\IntX:=DINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Integer(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=DINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
ERROR
RAISE ;
ENDPROC
PROC Decode_Long(VAR LabComm_Stream s, VAR dnum v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=8;
UnpackRawBytes buffer,\Network,1,v,\IntX:=LINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Long(VAR LabComm_Stream s, dnum v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=LINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=8;
ERROR
RAISE ;
ENDPROC
PROC Decode_Float(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
UnpackRawBytes buffer,\Network,1,v,\Float4;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Float(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v, buffer,\Network,1,\Float4;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
ERROR
RAISE ;
ENDPROC
PROC Decode_String(VAR LabComm_Stream st,VAR string s, \ VAR rawbytes collect)
VAR rawbytes buffer;
VAR num length;
IF Present(collect) THEN
Decode_Packed st, length, \collect:=collect;
ELSE
Decode_Packed st, length;
ENDIF
SocketReceive st.soc,\Str:=s,\ReadNoOfBytes:=length;
IF Present(collect) THEN
PackRawBytes s, collect, (RawBytesLen(collect)+1), \ASCII;
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_String(VAR LabComm_Stream st, string s)
VAR rawbytes buffer;
VAR num length;
length := StrLen(s);
Encode_Packed st, length;
SocketSend st.soc,\Str:=s,\NoOfBytes:=length;
ERROR
RAISE ;
ENDPROC
PROC Encoder_Register_Sample(VAR Encoder e, VAR LabComm_Stream st, VAR LabComm_Encoder_Sample s)
s.user_id := e.next_user_id;
e.next_user_id := e.next_user_id + 1;
Encode_Packed st, SAMPLE_DECL;
Encode_Packed st, s.user_id;
Encode_String st, s.name;
% s.prefix + ":Encode_Signature_" + s.name % e, st;
ERROR
RAISE ;
ENDPROC
PROC Collect_Array(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num num_dim;
VAR num dims;
Decode_Packed s, num_dim, \collect:=sig;
FOR i FROM 1 TO num_dim DO
Decode_Packed s, dims, \collect:=sig;
ENDFOR
Collect_Signature s, sig;
ERROR
RAISE ;
ENDPROC
PROC Collect_Struct(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num num_elements;
VAR string tmp;
Decode_Packed s, num_elements, \collect:=sig;
FOR i FROM 1 TO num_elements DO
Decode_String s, tmp, \collect:=sig;
Collect_Signature s, sig;
ENDFOR
ERROR
RAISE ;
ENDPROC
PROC Collect_Signature(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num type_id;
Decode_Packed s, type_id, \collect:=sig;
TEST type_id
CASE STRUCT_TYPE:
Collect_Struct s, sig;
CASE ARRAY_TYPE:
Collect_Array s, sig;
CASE BYTE_TYPE, BOOL_TYPE, SHORT_TYPE, INT_TYPE, LONG_TYPE, SHORT_TYPE:
DEFAULT:
RAISE IMPLEMENTATION_LIMIT_REACHED;
ENDTEST
ERROR
RAISE ;
ENDPROC
PROC Decode_One(VAR Decoder d, VAR LabComm_Stream s, VAR LabComm_Decoder_Sample samples{*})
VAR rawbytes buffer;
VAR num packet_type;
VAR num user_id;
VAR string type_name;
Decode_Packed s, packet_type;
WHILE packet_type = SAMPLE_DECL DO
Decode_Packed s, user_id;
Decode_String s, type_name;
Collect_Signature s, buffer;
FOR i FROM 1 TO Dim(samples, 1) DO
% samples{i}.prefix + ":Reg_If_Signature_Of_" + samples{i}.name % samples{i}, buffer, user_id;
ENDFOR
Decode_Packed s, packet_type;
ENDWHILE
IF packet_type >= SAMPLE_DATA THEN
FOR i FROM 1 TO Dim(samples, 1) DO
IF samples{i}.user_id = packet_type THEN
% samples{i}.prefix + ":Decode_And_Handle_" + samples{i}.name % d, s, samples{i};
ENDIF
ENDFOR
RETURN ;
ENDIF
RAISE UNKNOWN_PACKET_TYPE;
ERROR
RAISE ;
ENDPROC
PROC Init_Decoder(VAR Decoder d, VAR LabComm_Stream s)
VAR string version;
Decode_String s,version;
IF version<>LabCommVersion THEN
RAISE INCORRECT_LABCOMM_VERSION;
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Init_Encoder(VAR Encoder e, VAR LabComm_Stream s)
Encode_String s, LabCommVersion;
e.next_user_id := SAMPLE_DATA;
ERROR
RAISE ;
ENDPROC
ENDMODULE
The implementation of LabComm in RAPID
Limitations of this implementation:
- The type double is not available due to limitations in RAPID. There is a
non-integer type with 64 bits but there is not marshalling utilities for it.
- Variable sized arrays is not available. There is no dynamic allocation,
possible solution is a max-size array (1024) and a integervalue denoting the
size.
- A RECORD (struct) cannot contain an array, but fixed size arrays are
available both in structs and stand alone. The current implementation creates
a RECORD with one member for each index in the array. Not an omptimal
solution, the alternativ would be a seperate variable.
- Decoding and encoding is done directly from a TCP socket.
- Every generated procedure is namespaced by declaring them LOCAL to the
generated module. They must be called by using runtime binding of procedure
names ( % proc_name % arg1, arg2, ...;). The generated types are not
declared local.
Usage:
# Declare a stream, LabComm_Stream:
$ VAR LabComm_Stream st;
This contains a socketdev wich must be created and connected or instatiated
through an accept.
$ SocketCreate st.soc;
$ SocketConnect st.soc, "127.0.0.1", 55555;
or
$ SocketAccept server_socket, st.soc;
# Initiate Encoder and/or Decoder with the stream:
$ VAR Decoder d;
$ Init_Decoder d, st;
$ VAR Encoder e;
$ Init_Encoder e, st;
This will read/write the version of LabComm to ensure compatibility, current
version is "LabComm2014".
# Initiate the labcomm samples:
LabComm trusts the application to manage each sample. It requests the samples,
as a list, when performing decoding or encoding.
This is done through the generated code which implies the procedures are LOCAL
and must be called with runtime bindings.
When initiating a decoder sample the name of the callback procedure to receive
such samples is suplied as a string.
$ PROC handle_samplename(prefix_samplename val)
$ ...
$ ENDPROC
$ VAR LabComm_Decoder_Sample ds{1};
$ % prefix:Dec_Reg_samplename % ds{1}, "handle_samplename";
NOTE: The callback must be of type procedure and not function. Functions cannot
be called with runtime bindings.
When initiating an encoder sample the stream must be supplied to let the
encoder send the sample signature.
$ VAR LabComm_Encoder_Sample es{1};
$ % prefix:Enc_Reg_samplename % e, st, es{1};
# Encode and/or decode samples:
$ Decode_One d, st, ds;
It returns as soon as any sample is decoded. The decoded sample is supplied as
argument to the callback procedure registered with the corresponding sample.
$ VAR prefix_samplename val;
$ <init val>
$ % prefix:Encode_samplename % e, st, es{1}, val;
# Complete example:
## LabComm definition:
example.lc >>
sample struct {
short sum;
short terms[2];
} foo;
<< EOF
## RAPID CODE
PROC handle_foo(example_foo val)
IF val.sum = val.terms.e1 + val.terms.e2 THEN
TPWrite "Verification successfull!";
ELSE
TPWrite "Verification failed!";
ENDIF
ENDPROC
PROC main()
VAR Decoder d;
VAR Encoder e;
VAR LabComm_Stream st;
VAR LabComm_Encoder_Sample es{1};
VAR LabComm_Decoder_Sample ds{1};
VAR example_foo val := [2,[1,1]];
SocketCreate st.soc;
SocketConnect st.soc, "127.0.0.1", 55555;
Init_Decoder d, st;
Init_Encoder e, st;
% "example:Enc_Reg_foo" % e, st, es{1};
% "example:Dec_Reg_foo" % ds{1}, "handle_foo";
% "example:Encode_foo" % e, st, es{1}, val;
Decode_One d, st, ds;
SocketClose st.soc;
ENDPROC
liblabcomm.a
liblabcomm.so
liblabcomm.so.1
liblabcomm2006.so.1
liblabcomm2006.so
liblabcomm2006.a
liblabcomm2014.so.1
liblabcomm2014.so
liblabcomm2014.a
## Macros
VERSION=2014
LIBVERSION=2014
include ../os_compat.mk
ALL_DEPS=../liblabcomm$(LIBVERSION).a ../liblabcomm$(LIBVERSION).so
# TODO: Support for Codesourcery ARM toolchain.
OBJS=labcomm$(VERSION).o \
labcomm$(VERSION)_memory.o \
labcomm$(VERSION)_error.o \
labcomm$(VERSION)_default_error_handler.o \
labcomm$(VERSION)_default_memory.o \
labcomm$(VERSION)_default_scheduler.o \
labcomm$(VERSION)_time.o \
labcomm$(VERSION)_scheduler.o \
labcomm$(VERSION)_encoder.o \
labcomm$(VERSION)_decoder.o \
labcomm$(VERSION)_dynamic_buffer_writer.o \
labcomm$(VERSION)_fd_reader.o \
labcomm$(VERSION)_type_signature.o \
labcomm$(VERSION)_fd_writer.o \
labcomm$(VERSION)_pthread_scheduler.o \
labcomm$(VERSION)_renaming.o \
labcomm$(VERSION)_renaming_registry.o \
labcomm$(VERSION)_renaming_encoder.o \
labcomm$(VERSION)_renaming_decoder.o
# Enable experimental objects by `make LABCOMM_EXPERIMENTAL=true`
ifeq ($(LABCOMM_EXPERIMENTAL),true)
OBJS += experimental/udp_hack.o experimental/ethaddr.o \
experimental/labcomm_thr_reader_writer.o \
experimental/ThrottleDrv/ethernet_drv.o \
experimental/ThrottleDrv/throttle_drv.o \
experimental/labcomm_udp_reader_writer.o
endif
# Enable experimental objects by `make LABCOMM_SIG_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
OBJS += experimental/labcomm2014_sig_parser.o
endif
LABCOMM_JAR=../../../compiler/labcomm$(LIBVERSION)_compiler.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding \
test_labcomm_generated_encoding \
test_signature_numbers \
test_labcomm \
test_labcomm_pthread_scheduler \
test_labcomm_copy \
test_labcomm_renaming_registry \
test_labcomm_renaming_encoder \
test_labcomm_renaming_decoder
#FIXME: test_labcomm_errors
TEST_DIR=test
## Targets
.PHONY: all
all: $(ALL_DEPS)
.PHONY: test
test: all $(TESTS:%=run-test-%)
.PHONY: clean
clean:
$(RM) *.o
$(RM) experimental/*.o
$(RM) experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) test/testdata/gen/*.[cho]
$(RM) test/gen/*.[cho]
$(RM) -rf test/gen
.PHONY: distclean
distclean: clean
$(RM) ../liblabcomm$(LIBVERSION).so.1
$(RM) ../liblabcomm$(LIBVERSION).a
# rules invoked by 'all'
../liblabcomm$(LIBVERSION).so: ../liblabcomm$(LIBVERSION).so.1
if [ -h $@ ] ; then rm $@ ; fi
ln -s $(<:../%=%) $@
../liblabcomm$(LIBVERSION).so.1: $(OBJS:%.o=%.pic.o)
$(call MAKESHARED,$@,$(@:../%=%),$^)
../liblabcomm$(LIBVERSION).a: $(OBJS)
ar -r $@ $^
# Enable sig parser objects by `make labcomm2014_sig_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
experimental/test_sig_parser : experimental/labcomm2014_sig_parser.o experimental/test_sig_parser.c
endif
# compilation rules
%.pic.o: %.c
$(CC) -fPIC $(CFLAGS) -c -o $@ $<
%.o: %.c %.h
$(CC) $(CFLAGS) -c -o $@ $<
# rules invoked by 'test'
.PHONY: run-test-%
run-test-%: $(TEST_DIR)/gen/% | $(TEST_DIR)/gen
$(VALGRIND) $<
.PRECIOUS: $(TEST_DIR)/gen/%
$(TEST_DIR)/gen/%: $(TEST_DIR)/gen/%.o | $(TEST_DIR)/gen
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(TEST_DIR)/gen/%.o: $(TEST_DIR)/%.c | $(TEST_DIR)/gen
$(CC) $(CFLAGS_TEST) -o $@ -c $<
.PRECIOUS: $(TEST_DIR)/gen/%.c
.PRECIOUS: $(TEST_DIR)/gen/%.h
$(TEST_DIR)/gen/%.c $(TEST_DIR)/gen/%.h: $(TEST_DIR)/%.lc | $(TEST_DIR)/gen
$(LABCOMM) \
--c=$(TEST_DIR)/gen/$*.c \
--h=$(TEST_DIR)/gen/$*.h \
$<
$(LABCOMM_JAR):
@echo "======Building LabComm compiler======"
cd $(shell dirname $(LABCOMM_JAR)); ant jar
@echo "======End building LabComm compiler======"
$(TEST_DIR)/gen:
mkdir -p $@
# Extra compilation dependencies
labcomm$(VERSION).o: \
labcomm$(VERSION).c \
labcomm$(VERSION).h \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_reader.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_writer.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_dynamic_buffer_writer.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_basic_type_encoding.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding.o: \
labcomm$(VERSION)_private.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_signature_numbers.c: \
$(TEST_DIR)/gen/another_encoding.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_signature_numbers: \
$(TEST_DIR)/gen/another_encoding.o \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm: \
$(TEST_DIR)/gen/test_sample.o
$(TEST_DIR)/gen/test_labcomm_copy: \
$(TEST_DIR)/gen/generated_encoding.o \
$(TEST_DIR)/gen/test_sample.o \
$(TEST_DIR)/gen/more_types.o
$(TEST_DIR)/gen/test_labcomm_renaming_registry: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_encoder: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_decoder: \
$(TEST_DIR)/gen/generated_encoding.o
/* labcomm_sig_parser.c:
/* labcomm2014_sig_parser.c:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* 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.
*/
......@@ -9,27 +9,25 @@
/* 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.
* 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
* is currently not used
*
* - 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "labcomm_sig_parser.h"
#include "labcomm2014_sig_parser.h"
static void error(char *s) {
fprintf(stderr, "ERROR: %s", s);
......@@ -38,56 +36,59 @@ static void error(char *s) {
}
/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
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];
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];
return b0 | b1 | b2 | b3;
}
static inline unsigned int get32(labcomm_sig_parser_t *b) {
unsigned int res = unpack32(b->c, b->idx);
static inline int get32(labcomm2014_sig_parser_t *b) {
int res = unpack32(b->c, b->idx);
b->idx+=4;
return res;
}
/* aux method for reading labcomm varint from a char*
/* 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
*/
static int unpack_varint(unsigned char *buf, unsigned int idx, unsigned char *size) {
unsigned int res = 0;
static int unpack_varint(unsigned char *buf,
int idx,
size_t *size)
{
int res = 0;
unsigned int i=0;
unsigned char cont = TRUE;
unsigned char cont = LABCOMM2014_TRUE;
do {
unsigned char c = buf[idx+i];
res |= (c & 0x7f) << 7*i;
res = (res << 7) | (c & 0x7f);
cont = c & 0x80;
i++;
} while(cont);
if(size != NULL)
*size = i;
*size = i;
return res;
}
void dumpValStack(labcomm_sig_parser_t *b) {
int i;
void dumpValStack(labcomm2014_sig_parser_t *b) {
printf("=== value stack: ");
#ifdef DEBUG_STACK_VERBOSE
int i;
for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
printf("%2.2x ", b->val_stack[i]);
}
#endif
printf(" top==%d\n", b->val_top);
}
void dumpPtrStack(labcomm_sig_parser_t *b) {
int i;
void dumpPtrStack(labcomm2014_sig_parser_t *b) {
printf("=== pointer stack: ");
#ifdef DEBUG_STACK_VERBOSE
int i;
for(i=0; i<STACK_SIZE; i++) { //HERE BE DRAGONS
printf("%2.2x ", b->ptr_stack[i]);
}
......@@ -95,7 +96,7 @@ void dumpPtrStack(labcomm_sig_parser_t *b) {
printf(" top==%d\n", b->ptr_top);
}
void push_val(labcomm_sig_parser_t *b, unsigned int e) {
void push_val(labcomm2014_sig_parser_t *b, unsigned int e) {
b->val_stack[b->val_top]=e;
b->val_top=b->val_top-1;
if(b->val_top<0) error("value stack overrun");
......@@ -103,7 +104,7 @@ void push_val(labcomm_sig_parser_t *b, unsigned int e) {
dumpValStack(b);
#endif
}
unsigned int pop_val(labcomm_sig_parser_t *b) {
unsigned int pop_val(labcomm2014_sig_parser_t *b) {
b->val_top=b->val_top+1;
if(b->val_top>b->stacksize) error("value stack underrun");
#if defined DEBUG && !defined QUIET_STACK
......@@ -111,7 +112,7 @@ unsigned int pop_val(labcomm_sig_parser_t *b) {
#endif
return b->val_stack[b->val_top];
}
void push_ptr(labcomm_sig_parser_t *b, void* e) {
void push_ptr(labcomm2014_sig_parser_t *b, void* e) {
b->ptr_stack[b->ptr_top]=e;
b->ptr_top=b->ptr_top-1;
if(b->ptr_top<0) error("pointer stack overrun");
......@@ -119,7 +120,7 @@ void push_ptr(labcomm_sig_parser_t *b, void* e) {
dumpPtrStack(b);
#endif
}
void* pop_ptr(labcomm_sig_parser_t *b) {
void* pop_ptr(labcomm2014_sig_parser_t *b) {
b->ptr_top=b->ptr_top+1;
if(b->ptr_top>b->stacksize) error("pointer stack underrun");
#ifdef DEBUG
......@@ -127,10 +128,10 @@ void* pop_ptr(labcomm_sig_parser_t *b) {
#endif
return b->ptr_stack[b->ptr_top];
}
int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size,
int labcomm2014_sig_parser_init(labcomm2014_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)
size_t max_name_len, size_t max_sig_len)
{
b->c = malloc(buffer_size);
b->capacity = buffer_size;
......@@ -150,9 +151,9 @@ int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size,
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");
printf("warning: labcomm2014_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->sig_ts=calloc(num_signatures, sizeof(struct labcomm2014_signature));
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
......@@ -166,83 +167,105 @@ int labcomm_sig_parser_init(labcomm_sig_parser_t *b, size_t buffer_size,
return b->c == NULL || b->val_stack == NULL || b->ptr_stack == NULL;
}
int labcomm_sig_parser_read_file(labcomm_sig_parser_t *b, FILE *f) {
/* free the objects allocated by labcomm_sig_parser_init(b)
* NB! does not free b itself */
void labcomm2014_sig_parser_free(labcomm2014_sig_parser_t *b)
{
int i;
free(b->c);
free(b->val_stack);
free(b->ptr_stack);
#ifndef STATIC_ALLOCATION
for(i = 0; i<b->max_signatures; i++) {
free(b->signatures[i]);
free(b->signatures_name[i]);
}
free(b->signatures);
free(b->signatures_name);
free(b->signatures_name_length);
free(b->signatures_length);
free(b->sig_ts);
#endif
}
int labcomm2014_sig_parser_read_file(labcomm2014_sig_parser_t *b, FILE *f) {
int s = fread(b->c, sizeof(char), b->capacity, f);
b->size = s;
b->idx=0;
return s;
}
int more(labcomm_sig_parser_t *b)
int more(labcomm2014_sig_parser_t *b)
{
return b->idx < b->size;
}
unsigned char get(labcomm_sig_parser_t *b) {
unsigned char get(labcomm2014_sig_parser_t *b) {
return b->c[b->idx++];
}
unsigned char peek(labcomm_sig_parser_t *b) {
unsigned char peek(labcomm2014_sig_parser_t *b) {
return b->c[b->idx];
}
void advance(labcomm_sig_parser_t *b) {
void advance(labcomm2014_sig_parser_t *b) {
b->idx++;
}
void advancen(labcomm_sig_parser_t *b, size_t n) {
void advancen(labcomm2014_sig_parser_t *b, size_t n) {
b->idx+=n;
}
unsigned int peek_varint(labcomm_sig_parser_t *b, unsigned char *size) {
int peek_varint(labcomm2014_sig_parser_t *b, size_t *size) {
return unpack_varint(b->c, b->idx, size);
}
unsigned int get_varint(labcomm_sig_parser_t *b) {
unsigned char size;
unsigned int res = peek_varint(b, &size);
int get_varint(labcomm2014_sig_parser_t *b) {
size_t size;
int res = peek_varint(b, &size);
advancen(b, size);
return res;
}
unsigned int get_varint_size(labcomm_sig_parser_t *b, unsigned char *size) {
int get_varint_size(labcomm2014_sig_parser_t *b, size_t *size) {
unsigned int res = peek_varint(b, size);
advancen(b, *size);
return res;
}
void getStr(labcomm_sig_parser_t *b, char *dest, size_t size) {
void getStr(labcomm2014_sig_parser_t *b, unsigned char *dest, size_t size) {
int rem = b->size - b->idx;
if( size > rem )
if( size > rem )
size = rem;
strncpy(dest, &b->c[b->idx], size);
strncpy((char *)dest, (char *)&b->c[b->idx], size);
dest[size] = 0;
b->idx += size;
}
labcomm_signature_t *get_sig_t(labcomm_sig_parser_t *p, unsigned int uid)
struct labcomm2014_signature *get_sig_t(labcomm2014_sig_parser_t *p, unsigned int uid)
{
return &(p->sig_ts[uid-LABCOMM_USER]);
}
unsigned int get_signature_len(labcomm_sig_parser_t *p, unsigned int uid){
unsigned int get_signature_len(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures_length[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].size;
}
unsigned char* get_signature(labcomm_sig_parser_t *p, unsigned int uid){
unsigned char* get_signature(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].signature;
}
//is this needed?
//unsigned int get_signature_name_len(labcomm_sig_parser_t *p, unsigned int uid){
//unsigned int get_signature_name_len(labcomm2014_sig_parser_t *p, unsigned int uid){
// return signatures_name_length[uid-LABCOMM_USER];
//}
unsigned char* get_signature_name(labcomm_sig_parser_t *p, unsigned int uid){
char* get_signature_name(labcomm2014_sig_parser_t *p, unsigned int uid){
//return signatures_name[uid-LABCOMM_USER];
return p->sig_ts[uid-LABCOMM_USER].name;
}
void dump_signature(labcomm_sig_parser_t *p, unsigned int uid){
void dump_signature(labcomm2014_sig_parser_t *p, unsigned int uid){
int i;
unsigned int len = get_signature_len(p, uid);
printf("signature for uid %x : %s (len=%d):\n", uid, get_signature_name(p, uid), len);
......@@ -254,49 +277,55 @@ void dump_signature(labcomm_sig_parser_t *p, unsigned int uid){
printf("\n");
}
static inline void labcomm_sig_parser_t_set_varsize(labcomm_sig_parser_t *b)
static inline void labcomm2014_sig_parser_t_set_varsize(labcomm2014_sig_parser_t *b)
{
b->current_decl_is_varsize = TRUE;
b->current_decl_is_varsize = LABCOMM2014_TRUE;
}
static size_t labcomm_sizeof_primitive(unsigned int type)
static size_t labcomm2014_sizeof_primitive(unsigned int type)
{
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
case TYPE_BYTE :
return 1;
case TYPE_SHORT :
case TYPE_SHORT :
return 2;
case TYPE_INTEGER :
case TYPE_FLOAT :
case TYPE_FLOAT :
case TYPE_SAMPLE_REF :
return 4;
case TYPE_LONG :
case TYPE_DOUBLE :
case TYPE_DOUBLE :
return 8;
default:
printf("labcomm_sizeof_primitive(%x)\n", type);
error("labcomm_sizeof_primitive should only be called for primitive types");
printf("labcomm2014_sizeof_primitive(%x)\n", type);
error("labcomm2014_sizeof_primitive should only be called for primitive types");
return 0;
}
}
//these are inlined in do_accept_packet
//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);
static unsigned char labcomm_varint_sizeof(unsigned int i)
//static int accept_type_decl(labcomm2014_sig_parser_t *d);
//static int accept_sample_decl(labcomm2014_sig_parser_t *d);
static int accept_user_id(labcomm2014_sig_parser_t *d);
static int accept_string(labcomm2014_sig_parser_t *d);
static int accept_type(labcomm2014_sig_parser_t *d);
static int accept_array_decl(labcomm2014_sig_parser_t *d);
static int accept_intentions(labcomm2014_sig_parser_t *d);
#if 0
// UNUSED declarations
static int accept_string_length(labcomm2014_sig_parser_t *d);
static int accept_char(labcomm2014_sig_parser_t *d);
static int accept_number_of_indices(labcomm2014_sig_parser_t *d);
static int accept_indices(labcomm2014_sig_parser_t *d);
static int accept_variable_index(labcomm2014_sig_parser_t *d);
static int accept_fixed_index(labcomm2014_sig_parser_t *d);
static int accept_number_of_fields(labcomm2014_sig_parser_t *d);
#endif
static int accept_struct_decl(labcomm2014_sig_parser_t *d);
static int accept_field(labcomm2014_sig_parser_t *d);
static int accept_sample_data(labcomm2014_sig_parser_t *d);
static unsigned char labcomm2014_varint_sizeof(unsigned int i)
{
if(i < 128) {
return 1;
......@@ -307,103 +336,173 @@ static unsigned char labcomm_varint_sizeof(unsigned int i)
return res;
}
}
int encoded_size_static(labcomm_signature_t *sig, void *unused)
int encoded_size_static(struct labcomm2014_signature *sig, void *unused)
{
#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
if(sig->cached_encoded_size == -1) {
error("encoded_size_static called for var_size sample or uninitialized signature");
}
return sig->cached_encoded_size;
#else
printf("Warning: encoded_size_static currently broken\n");
return -1;
#endif
}
/* This function probably never will be implemented, as it would be
similar to skip_packed_sample_data. And if unregistered variable size
/* 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)
int encoded_size_parse_sig(struct labcomm2014_signature *sig, void *sample)
{
printf("Warning: encoded_size_parse_sig not implemented\n");
return -1;
}
static int accept_signature(labcomm_sig_parser_t *d)
static int accept_signature(labcomm2014_sig_parser_t *d,
labcomm2014_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 LABCOMM2014_TRUE;
} else if (type == PKG_TYPE_DECL) {
INFO_PRINTF("accept_signature: ignoring typedef\n");
return LABCOMM2014_TRUE;
} else {
error("decl is neither sample, ref, or typedef???");
return LABCOMM2014_FALSE;
}
}
unsigned int end = d->idx;
unsigned int len = end-start;
struct labcomm2014_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 LABCOMM2014_TRUE;
}
static int accept_decl(labcomm2014_sig_parser_t *d, labcomm2014_type type)
{
if(accept_user_id(d)) {
unsigned int uid = pop_val(d);
unsigned int nstart = d->idx;
VERBOSE_PRINTF(", name = ");
accept_string(d);
VERBOSE_PRINTF(", intentions = ");
accept_intentions(d);
unsigned int start = d->idx;
unsigned int nstart = pop_val(d);
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);
VERBOSE_PRINTF("\ntype = ");
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...)");
}
unsigned char lenlen = labcomm2014_varint_sizeof(nlen);
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]);
}
if(nlen < d->max_name_len) { // leave 1 byte for terminating NULL
char *name;
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];
name = d->signatures_name[uid-LABCOMM_USER];
return accept_signature(d, type, start, uid, name);
} else {
error("sig name longer than max length (this ought to be dynamic...");
return LABCOMM2014_FALSE;
}
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);
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 {
error("sample_decl with uid < LABCOMM_USER");
return FALSE;
error("sample_decl with uid < LABCOMM_USER");
return LABCOMM2014_FALSE;
}
}
// HERE BE DRAGONS! what does the return value mean?
int accept_packet(labcomm_sig_parser_t *d) {
unsigned char nbytes;
int accept_packet(labcomm2014_sig_parser_t *d) {
size_t nbytes;
unsigned int type = peek_varint(d, &nbytes) ;
if(type == TYPE_DECL ) {
//XXX is this used? If so, is it correct?
if(type == PKG_VERSION ) {
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
} else if (type == PKG_SAMPLE_DECL) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);
VERBOSE_PRINTF("sample_decl ");
get_varint(d); //ignore length field
accept_decl(d, type);
} else if (type == PKG_SAMPLE_REF) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);
d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
VERBOSE_PRINTF("sample_ref ");
get_varint(d); //ignore length field
accept_decl(d, type);
}else if(type == PKG_TYPE_DECL ) {
d->current_decl_is_varsize = LABCOMM2014_FALSE; // <-- a conveniance flag in labcomm2014_sig_parser_t
advancen(d, nbytes);//consume type field
VERBOSE_PRINTF("type_decl ");
accept_signature(d);
} else if (type == SAMPLE_DECL) {
d->current_decl_is_varsize = FALSE; // <-- a conveniance flag in labcomm_sig_parser_t
get_varint(d); //ignore length field
accept_decl(d, type);
} else if (type == PKG_TYPE_BINDING) {
VERBOSE_PRINTF("type_binding ");
advancen(d, nbytes);
VERBOSE_PRINTF("sample_decl ");
accept_signature(d);
get_varint(d); //ignore length field
#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);
} else if(type >= LABCOMM_USER) {
#ifdef EXIT_WHEN_RECEIVING_DATA
printf("*** got sample data, exiting\n");
......@@ -412,28 +511,88 @@ int accept_packet(labcomm_sig_parser_t *d) {
accept_sample_data(d);
#endif
} else {
error("got unknown type (<LABCOMM_USER)");
#ifdef EXIT_ON_UNKNOWN_TAG
error("got unknown type (<LABCOMM_USER)");
exit(1);
#else
int len = get_varint(d); // length field
printf("got unknown tag: 0x%x, skipping %d bytes\n",type, len);
advancen(d, len);
#endif
}
return LABCOMM2014_TRUE;
}
static int accept_user_id(labcomm_sig_parser_t *d){
unsigned char nbytes;
unsigned int uid = peek_varint(d, &nbytes);
static int accept_user_id(labcomm2014_sig_parser_t *d){
size_t nbytes;
int uid = peek_varint(d, &nbytes);
if(uid >= LABCOMM_USER) {
advancen(d, nbytes);
VERBOSE_PRINTF("uid = %x ", uid);
VERBOSE_PRINTF("uid = 0x%x ", uid);
push_val(d, uid);
return TRUE;
return LABCOMM2014_TRUE;
} else {
return FALSE;
error("uid < LABCOMM_USER");
return LABCOMM2014_FALSE;
}
}
static int accept_string(labcomm_sig_parser_t *d){
/** pushes (index in stream of name) and (length of name) */
static int accept_intentions(labcomm2014_sig_parser_t *d){
unsigned int num = get_varint(d);
int i;
int npos = 0;
int nlen = 0;
for(i=0; i<num; i++) {
int klen, vlen;
printf("( ");
#ifdef RETURN_STRINGS
char *key;
char *val;
#endif
accept_string(d);
klen = pop_val(d);
if(klen==0) {
npos = d->idx;
}
#ifdef RETURN_STRINGS
key = (char *) pop_ptr(d);
if(klen!=0) {
printf("%s] : ",key);
}
free(key);
#else
if(klen!=0) {
printf(": ");
} else {
printf("name: ");
}
#endif
accept_string(d);
printf(" ");
vlen = pop_val(d);
if(klen==0) {
nlen = vlen;
}
#ifdef RETURN_STRINGS
val = (char *) pop_ptr(d);
printf("%s %s",(klen?",val : ":""), val);
free(val);
#endif
printf(") ");
}
push_val(d, nlen);
push_val(d, npos);
return LABCOMM2014_TRUE;
}
static int accept_string(labcomm2014_sig_parser_t *d){
unsigned int len = get_varint(d);
char *str=malloc(len);
getStr(d, str, len);
unsigned char *str=malloc(len+1); // len is without terminating null
getStr(d, str, len);
VERBOSE_PRINTF("%s", str);
#ifdef RETURN_STRINGS
push_ptr(d, str);
......@@ -441,11 +600,11 @@ static int accept_string(labcomm_sig_parser_t *d){
free(str);
#endif
push_val(d, len);
return TRUE;
return LABCOMM2014_TRUE;
}
/* pushes size and type id */
static int accept_type(labcomm_sig_parser_t *d){
unsigned char nbytes;
static int accept_type(labcomm2014_sig_parser_t *d){
size_t nbytes;
unsigned int type = peek_varint(d, &nbytes) ;
switch(type) {
case TYPE_BOOLEAN :
......@@ -486,9 +645,14 @@ static int accept_type(labcomm_sig_parser_t *d){
case TYPE_STRING :
VERBOSE_PRINTF("string\n");
advancen(d, nbytes);
labcomm_sig_parser_t_set_varsize(d);
labcomm2014_sig_parser_t_set_varsize(d);
push_val(d, 0);
break;
case TYPE_SAMPLE_REF :
VERBOSE_PRINTF("sample\n");
advancen(d, nbytes);
push_val(d, 4);
break;
case ARRAY_DECL :
accept_array_decl(d);
pop_val(d); // ignore element type
......@@ -499,19 +663,22 @@ static int accept_type(labcomm_sig_parser_t *d){
// push(d, pop(d) is a NOP --> leave size on stack
break;
default :
printf("accept_type default (type==%x) should not happen\n", type);
//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);
push_val(d, 0);
push_val(d, type);
return FALSE;
return LABCOMM2014_FALSE;
}
push_val(d, type);
return TRUE;
return LABCOMM2014_TRUE;
}
/* pushes size and element type */
static int accept_array_decl(labcomm_sig_parser_t *d){
unsigned char nbytes;
unsigned int tid = peek_varint(d, &nbytes) ;
static int accept_array_decl(labcomm2014_sig_parser_t *d){
size_t nbytes;
int tid = peek_varint(d, &nbytes) ;
if(tid == ARRAY_DECL) {
advancen(d, nbytes);
unsigned int nidx = get_varint(d);
......@@ -524,7 +691,7 @@ static int accept_array_decl(labcomm_sig_parser_t *d){
if(idx == 0) {
numVar++;
VERBOSE_PRINTF("[_] ");
labcomm_sig_parser_t_set_varsize(d);
labcomm2014_sig_parser_t_set_varsize(d);
} else {
VERBOSE_PRINTF("[%d] ", idx);
size*=idx;
......@@ -547,45 +714,52 @@ static int accept_array_decl(labcomm_sig_parser_t *d){
push_val(d, 0);
}
push_val(d, et);
return TRUE;
return LABCOMM2014_TRUE;
} else {
printf("accept_array_decl: type=%x, should not happen\n",tid);
push_val(d, 0);
push_val(d, tid);
return FALSE;
return LABCOMM2014_FALSE;
}
}
/* pushes size */
static int accept_struct_decl(labcomm_sig_parser_t *d){
unsigned char nbytes;
unsigned int tid = peek_varint(d, &nbytes) ;
static int accept_struct_decl(labcomm2014_sig_parser_t *d){
size_t nbytes;
int tid = peek_varint(d, &nbytes) ;
if(tid == STRUCT_DECL) {
advancen(d, nbytes);
unsigned int nf = get_varint(d);
VERBOSE_PRINTF("%d field struct:\n", nf);
if(nf == 0) {
VERBOSE_PRINTF("void\n");
} else {
VERBOSE_PRINTF("%d field struct:\n", nf);
}
int i;
#ifdef USE_UNUSED_VARS
int numVar=0;
int size=0;
#endif
unsigned int fieldsizes=0;
for(i=0; i<nf; i++) {
accept_field(d);
fieldsizes += pop_val(d);
}
push_val(d, fieldsizes);
return TRUE;
return LABCOMM2014_TRUE;
} else {
printf("accept_struct_decl: type=%x, should not happen\n",tid);
push_val(d, 0);
return FALSE;
return LABCOMM2014_FALSE;
}
}
/* pushes field size */
static int accept_field(labcomm_sig_parser_t *d){
VERBOSE_PRINTF("\tfield name: ");
accept_string(d);
pop_val(d); // ignore length, for now
static int accept_field(labcomm2014_sig_parser_t *d){
VERBOSE_PRINTF("\tfield: ");
accept_intentions(d);
pop_val(d); // ignore name pos, for now
pop_val(d); // ignore name length, for now
#ifdef RETURN_STRINGS
char *str = (char *) pop_ptr(d);
free(str);
......@@ -595,28 +769,34 @@ static int accept_field(labcomm_sig_parser_t *d){
pop_val(d); // ignore type, for now
// push(pop() is really a NOP , leave size on the stack when debugging done
VERBOSE_PRINTF("\n");
return LABCOMM2014_TRUE;
}
static int accept_sample_data(labcomm_sig_parser_t *d){
static int accept_sample_data(labcomm2014_sig_parser_t *d){
accept_user_id(d);
unsigned int uid = pop_val(d);
unsigned int uid = pop_val(d);
printf("sample data... uid=0x%x\n", uid);
int len = get_varint(d); //length field
#ifdef DEBUG
dump_signature(d, uid);
#endif
labcomm_signature_t *sigt = get_sig_t(d, uid);
int encoded_size = sigt->encoded_size(sigt, NULL);
#ifdef SKIP_BY_PARSING
struct labcomm2014_signature *sigt = get_sig_t(d, uid);
int encoded_size = sigt->encoded_size(NULL);
INFO_PRINTF("encoded_size from sig: %d\n", encoded_size);
labcomm_signature_t *sig = get_sig_t(d, uid);
struct labcomm2014_signature *sig = get_sig_t(d, uid);
skip_packed_sample_data(d, sig);
return TRUE;
#else
advancen(d, len);
#endif
return LABCOMM2014_TRUE;
}
static int skip_type(unsigned int,labcomm_sig_parser_t*,unsigned char*,unsigned int,unsigned int*) ;
static int skip_type(unsigned int,labcomm2014_sig_parser_t*,unsigned char*,unsigned int,int*) ;
static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
static int skip_array(labcomm2014_sig_parser_t *d, unsigned char *sig, int len, int *pos) {
unsigned int skip = 0;
unsigned int tot_nbr_elem_tmp = 1;
unsigned char nbytes;
size_t nbytes;
unsigned int nIdx = unpack_varint(sig, *pos, &nbytes);
VERBOSE_PRINTF("skip_array: nIdx = %d (from sig)\n", nIdx);
*pos +=nbytes;
......@@ -635,45 +815,45 @@ static int skip_array(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int
tot_nbr_elem_tmp *= idx[i];
}
}
unsigned int var[nVar];
int var[nVar];
unsigned char varSize=0; // total number of bytes required for var size fields
for(i=0; i<nVar; i++) {
var[i] = get_varint_size(d, &nbytes);
var[i] = get_varint_size(d, &nbytes);
varSize += nbytes;
VERBOSE_PRINTF("skip_array: var[%d]=%d (from sample)\n", i, var[i]);
tot_nbr_elem_tmp *= var[i];
}
unsigned int type = unpack_varint(sig, *pos, &nbytes);
int type = unpack_varint(sig, *pos, &nbytes);
*pos+=nbytes;
unsigned int elemSize = labcomm_sizeof_primitive(type);
unsigned int elemSize = labcomm2014_sizeof_primitive(type);
skip = elemSize * tot_nbr_elem_tmp;
VERBOSE_PRINTF("skip_array: skip: %d * %d = %d\n", tot_nbr_elem_tmp, elemSize ,skip);
advancen(d, skip);
//return skip + 4*nVar;
return skip + varSize;
}
int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, unsigned int *pos) {
unsigned char nbytes;
unsigned int nFields = unpack_varint(sig,*pos, &nbytes);
int skip_struct(labcomm2014_sig_parser_t *d, unsigned char *sig, unsigned int len, int *pos) {
size_t nbytes;
int nFields = unpack_varint(sig,*pos, &nbytes);
*pos += nbytes;
unsigned int i;
unsigned int skipped=0;
VERBOSE_PRINTF("skip_struct (%d fields)\n", nFields);
for(i=0; i<nFields; i++) {
//skip name
//skip name
unsigned int namelen = unpack_varint(sig, *pos, &nbytes);
#ifdef DEBUG
VERBOSE_PRINTF("field #%d:\n----namelen==%d\n",i,namelen);
char name[namelen+1]; //HERE BE DRAGONS. alloca?
strncpy(name, sig+*pos+nbytes, namelen);
strncpy(name, (const char *)sig+*pos+nbytes, namelen);
name[namelen]=0;
VERBOSE_PRINTF("----name = %s\n",name);
#endif
......@@ -690,8 +870,8 @@ int skip_struct(labcomm_sig_parser_t *d, unsigned char *sig, unsigned int len, u
}
#ifndef QUIET
/* print and skip */
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
unsigned char *sig, unsigned int len, unsigned int *pos)
int skip_type(unsigned int type, labcomm2014_sig_parser_t *d,
unsigned char *sig, unsigned int len, int *pos)
{
int skipped=0;
printf("skip_type %x:", type);
......@@ -700,34 +880,34 @@ int skip_type(unsigned int type, labcomm_sig_parser_t *d,
printf("boolean [%d]\n", get(d));
skipped++;
break;
case TYPE_BYTE :
case TYPE_BYTE :
printf("byte [%d]\n", get(d));
skipped++;
break;
case TYPE_SHORT :
case TYPE_SHORT :
//XXX not supported
advancen(d,2);
advancen(d,2);
skipped+=2;
break;
case TYPE_INTEGER :
printf("integer [%d]\n", get32(d));
skipped +=4;
break;
case TYPE_FLOAT :
case TYPE_FLOAT :
//XXX not supported
advancen(d,4);
advancen(d,4);
skipped+=4;
break;
case TYPE_LONG :
case TYPE_DOUBLE :
case TYPE_DOUBLE :
//XXX not supported
advancen(d,8);
advancen(d,8);
skipped+=8;
break;
case TYPE_STRING :
{
unsigned char nbytes;
unsigned int len = get_varint_size(d, &nbytes);
size_t nbytes;
int len = get_varint_size(d, &nbytes);
int i;
printf("string [");
for(i=0; i<len; i++)
......@@ -750,35 +930,35 @@ int skip_type(unsigned int type, labcomm_sig_parser_t *d,
return skipped;
}
#else
int skip_type(unsigned int type, labcomm_sig_parser_t *d,
unsigned char *sig, unsigned int len, unsigned int *pos)
int skip_type(unsigned int type, labcomm2014_sig_parser_t *d,
const char *sig, unsigned int len, int *pos)
{
int skipped=0;
VERBOSE_PRINTF("skip_type %x\n", type);
switch(type) {
case TYPE_BOOLEAN :
case TYPE_BYTE :
advancen(d,1);
case TYPE_BYTE :
advancen(d,1);
skipped++;
break;
case TYPE_SHORT :
advancen(d,2);
case TYPE_SHORT :
advancen(d,2);
skipped+=2;
break;
case TYPE_INTEGER :
case TYPE_FLOAT :
advancen(d,4);
case TYPE_FLOAT :
advancen(d,4);
skipped+=4;
break;
case TYPE_LONG :
case TYPE_DOUBLE :
advancen(d,8);
case TYPE_DOUBLE :
advancen(d,8);
skipped+=8;
break;
case TYPE_STRING :
{
unsigned char nbytes;
unsigned int len = get_varint_size(d, &nbytes);
size_t nbytes;
int len = get_varint_size(d, &nbytes);
advancen(d,len);
skipped+=len+nbytes;
break;}
......@@ -796,17 +976,17 @@ int skip_type(unsigned int type, labcomm_sig_parser_t *d,
}
#endif
/* parse signature and skip the corresponding bytes in the labcomm_sig_parser_t
/* parse signature and skip the corresponding bytes in the labcomm2014_sig_parser_t
*/
int skip_packed_sample_data(labcomm_sig_parser_t *d, labcomm_signature_t *sig) {
unsigned int pos = 0; //current position in signature
int skip_packed_sample_data(labcomm2014_sig_parser_t *d, struct labcomm2014_signature *sig) {
int pos = 0; //current position in signature
unsigned int skipped = 0; //skipped byte counter
while(pos < sig->size) {
unsigned char nbytes;
unsigned int type = unpack_varint(sig->signature,pos, &nbytes);
size_t nbytes;
int type = unpack_varint(sig->signature,pos, &nbytes);
pos+=nbytes;
skipped += skip_type(type, d, sig->signature, sig->size, &pos);
}
}
printf("skipped %d bytes\n", skipped);
return TRUE;
return LABCOMM2014_TRUE;
}
/* labcomm_sig_parser.h:
/* labcomm2014_sig_parser.h:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* 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.
*/
......@@ -8,22 +8,27 @@
#ifndef LABCOMM_SIG_PARSER_H
#define LABCOMM_SIG_PARSER_H
#include "../labcomm_private.h"
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#undef DEBUG
#undef QUIET_STACK // don't print anything for push/pop
#undef DEBUG
#define QUIET_STACK // don't print anything for push/pop
#undef DEBUG_STACK_VERBOSE // dump stack, otherwise just print value of top
#undef QUIET //just print type and size when skipping data
#undef VERBOSE // print in great detail
#define VERBOSE // print in great detail
#undef SKIP_BY_PARSING
#undef STATIC_ALLOCATION //dynamic allocation not completely implemented
#ifdef STATIC_ALLOCATION
#define MAX_SIGNATURES 16
#define MAX_NAME_LEN 32
#define MAX_SIGNATURES 100
#define MAX_NAME_LEN 32
#define MAX_SIG_LEN 128
#define TYPEDEF_BASE MAX_SIGNATURES
#endif
......@@ -32,7 +37,7 @@ typedef struct {
unsigned char* c;
size_t size;
size_t capacity;
unsigned int idx;
int idx;
int val_top;
int * val_stack;
int ptr_top;
......@@ -42,48 +47,55 @@ typedef struct {
size_t max_signatures; // set by init(...)
size_t max_name_len;
size_t max_sig_len;
size_t max_sig_len;
// arrays for signatures and typedefs
// signatures start at index 0
// typedefs start at index MAX_SIGNATURES
#ifdef STATIC_ALLOCATION
labcomm_signature_t sig_ts[MAX_SIGNATURES];
struct labcomm2014_signature sig_ts[2*MAX_SIGNATURES];
unsigned int signatures_length[MAX_SIGNATURES];
unsigned int signatures_name_length[MAX_SIGNATURES];
unsigned char signatures_name[MAX_SIGNATURES][MAX_NAME_LEN];
unsigned char signatures[MAX_SIGNATURES][MAX_SIG_LEN];
unsigned int signatures_length[2*MAX_SIGNATURES];
unsigned int signatures_name_length[2*MAX_SIGNATURES];
unsigned char signatures_name[2*MAX_SIGNATURES][MAX_NAME_LEN];
unsigned char signatures[2*MAX_SIGNATURES][MAX_SIG_LEN];
#else
labcomm_signature_t *sig_ts; // [MAX_SIGNATURES]
struct labcomm2014_signature *sig_ts; // [2*MAX_SIGNATURES]
unsigned int *signatures_length; // [MAX_SIGNATURES]
unsigned char **signatures; // [MAX_SIGNATURES][MAX_SIG_LEN];
unsigned int *signatures_length; // [2*MAX_SIGNATURES]
unsigned char **signatures; // [2*MAX_SIGNATURES][MAX_SIG_LEN];
unsigned int *signatures_name_length; // [MAX_SIGNATURES]
unsigned char **signatures_name; // [MAX_SIGNATURES][MAX_NAME_LEN];
unsigned int *signatures_name_length; // [2*MAX_SIGNATURES]
char **signatures_name; // [2*MAX_SIGNATURES][MAX_NAME_LEN];
#endif
} labcomm_sig_parser_t;
} labcomm2014_sig_parser_t;
int labcomm_sig_parser_init(labcomm_sig_parser_t *p, size_t size,
size_t stacksize, size_t max_num_signatures,
int labcomm2014_sig_parser_init(labcomm2014_sig_parser_t *p, size_t size,
size_t stacksize, size_t max_num_signatures,
size_t max_name_len, size_t max_sig_len);
int labcomm_sig_parser_read_file(labcomm_sig_parser_t *p, FILE *f);
void labcomm2014_sig_parser_free(labcomm2014_sig_parser_t *b);
int labcomm2014_sig_parser_read_file(labcomm2014_sig_parser_t *p, FILE *f);
int accept_packet(labcomm2014_sig_parser_t *p);
struct labcomm2014_signature *get_sig_t(labcomm2014_sig_parser_t *p,unsigned int uid);
int accept_packet(labcomm_sig_parser_t *p);
unsigned int get_signature_len(labcomm2014_sig_parser_t *p,unsigned int uid);
char* get_signature_name(labcomm2014_sig_parser_t *p,unsigned int uid);
unsigned char* get_signature(labcomm2014_sig_parser_t *p,unsigned int uid);
void dump_signature(labcomm2014_sig_parser_t *p,unsigned int uid);
labcomm_signature_t *get_sig_t(labcomm_sig_parser_t *p,unsigned int uid);
unsigned int get_signature_len(labcomm_sig_parser_t *p,unsigned int uid);
unsigned char* get_signature_name(labcomm_sig_parser_t *p,unsigned int uid);
unsigned char* get_signature(labcomm_sig_parser_t *p,unsigned int uid);
void dump_signature(labcomm_sig_parser_t *p,unsigned int uid);
int more(labcomm2014_sig_parser_t *b);
/* parse signature and skip the corresponding bytes in the labcomm_sig_parser
/* parse signature and skip the corresponding bytes in the labcomm2014_sig_parser
*/
int skip_packed_sample_data(labcomm_sig_parser_t *p, labcomm_signature_t *sig);
int skip_packed_sample_data(labcomm2014_sig_parser_t *p, struct labcomm2014_signature *sig);
#ifdef QUIET
#define INFO_PRINTF(format, args...)
#define INFO_PRINTF(format, args...)
#undef VERBOSE
#else
#define INFO_PRINTF(format, args...) \
......@@ -94,23 +106,19 @@ int skip_packed_sample_data(labcomm_sig_parser_t *p, labcomm_signature_t *sig);
#define VERBOSE_PRINTF(format, args...) \
printf (format , ## args)
#else
#define VERBOSE_PRINTF(format, args...)
#define VERBOSE_PRINTF(format, args...)
#endif
#undef EXIT_WHEN_RECEIVING_DATA
#undef EXIT_WHEN_RECEIVING_DATA
#undef RETURN_STRINGS // not really tested
#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif
typedef enum{
TYPE_DECL = LABCOMM_TYPEDEF,
SAMPLE_DECL = LABCOMM_SAMPLE,
PKG_VERSION = LABCOMM_VERSION,
PKG_SAMPLE_DECL = LABCOMM_SAMPLE_DEF,
PKG_SAMPLE_REF = LABCOMM_SAMPLE_REF,
PKG_TYPE_DECL = LABCOMM_TYPE_DEF,
PKG_TYPE_BINDING = LABCOMM_TYPE_BINDING,
ARRAY_DECL = LABCOMM_ARRAY,
STRUCT_DECL = LABCOMM_STRUCT,
......@@ -122,6 +130,7 @@ typedef enum{
TYPE_LONG = LABCOMM_LONG,
TYPE_FLOAT = LABCOMM_FLOAT,
TYPE_DOUBLE = LABCOMM_DOUBLE,
TYPE_STRING = LABCOMM_STRING
} labcomm_type ;
TYPE_STRING = LABCOMM_STRING,
TYPE_SAMPLE_REF = LABCOMM_REF
} labcomm2014_type ;
#endif
/* labcomm_sig_parser.c:
/* labcomm2014_sig_parser.c:
* a main program for the example labcomm signatures parser
*/
#include <stdio.h>
#include <stdlib.h>
#include "labcomm_sig_parser.h"
#include "experimental/labcomm2014_sig_parser.h"
#undef DEBUG_READ
#define DEBUG_READ
#define BUF_SIZE 1024
#define STACK_SIZE 16
#define MAX_NUM_SIGNATURES 10
#define MAX_SIGNATURES 16
#define MAX_NAME_LEN 32
#define MAX_SIG_LEN 128
#define MAX_SIGNATURES 100
#define MAX_NAME_LEN 64
#define MAX_SIG_LEN 512
void test_read(labcomm_sig_parser_t *p) {
int r = labcomm_sig_parser_read_file(p, stdin);
void test_read(labcomm2014_sig_parser_t *p) {
int r = labcomm2014_sig_parser_read_file(p, stdin);
#ifdef DEBUG_READ
printf("read %d bytes:\n\n", r);
int i;
......@@ -28,9 +29,9 @@ void test_read(labcomm_sig_parser_t *p) {
#endif
}
int main() {
labcomm_sig_parser_t p;
labcomm2014_sig_parser_t p;
if(labcomm_sig_parser_init(&p, BUF_SIZE, STACK_SIZE,
if(labcomm2014_sig_parser_init(&p, BUF_SIZE, STACK_SIZE,
MAX_NUM_SIGNATURES, MAX_NAME_LEN, MAX_SIG_LEN) ) {
printf("failed to init buffer\n");
exit(1);
......@@ -40,5 +41,6 @@ int main() {
printf("--------------------------------------------- new packet: \n");
} while(more(&p) && accept_packet(&p));
printf("EOF\n");
labcomm2014_sig_parser_free(&p);
}