diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag index c352ce81e2aba3923ebbd538c8ad6988cf07ecb4..cb5f8b523b09e18703d24dd9e0d349812c757c40 100644 --- a/compiler/C_CodeGen.jrag +++ b/compiler/C_CodeGen.jrag @@ -351,7 +351,7 @@ aspect C_Declarations { env.println("struct labcomm_encoder *e);"); env.unindent(); - env.println("void labcomm_encode_" + env.prefix + getName() + "("); + env.println("int labcomm_encode_" + env.prefix + getName() + "("); env.indent(); env.println("struct labcomm_encoder *e,"); env.println(env.prefix + getName() + " *v"); @@ -633,7 +633,7 @@ aspect C_Encoder { public void SampleDecl.C_emitEncoder(C_env env) { env = env.nestStruct("(*v)"); - env.println("static void encode_" + getName() + "("); + env.println("static int encode_" + getName() + "("); env.indent(); env.println("labcomm_encoder_t *e,"); env.println(env.prefix + getName() + " *v"); @@ -641,21 +641,23 @@ aspect C_Encoder { env.println(")"); env.println("{"); env.indent(); + env.println("int result;"); getType().C_emitEncoder(env); + env.println("return result;"); env.unindent(); env.println("}"); // Typesafe encode wrapper - env.println("void labcomm_encode_" + env.prefix + getName() + "("); + env.println("int labcomm_encode_" + env.prefix + getName() + "("); env.println("labcomm_encoder_t *e,"); env.println(env.prefix + getName() + " *v"); env.unindent(); env.println(")"); env.println("{"); env.indent(); - env.println("labcomm_internal_encode(e, &labcomm_signature_" + + env.println("return labcomm_internal_encode(e, &labcomm_signature_" + env.prefix + getName() + - ", (labcomm_encode_typecast_t)encode_" + getName() + + ", (labcomm_encoder_function)encode_" + getName() + ", v);"); env.unindent(); env.println("}"); @@ -668,10 +670,13 @@ aspect C_Encoder { } public void VoidType.C_emitEncoder(C_env env) { + env.println("result = 0;"); } public void PrimType.C_emitEncoder(C_env env) { - env.println("labcomm_encode_" + getName() + "(e, " + env.qualid + ");"); + env.println("result = labcomm_encode_" + getName() + + "(e, " + env.qualid + ");"); + env.println("if (result != 0) { return result; }"); } public void UserType.C_emitEncoder(C_env env) { @@ -748,7 +753,7 @@ aspect C_Encoder { env.indent(); env.println("e,"); env.println("&labcomm_signature_" + env.prefix + getName() + ","); - env.println("(labcomm_encode_typecast_t)encode_" + getName()); + env.println("(labcomm_encoder_function)encode_" + getName()); env.unindent(); env.println(");"); env.unindent(); diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c index c571f168510254adbeef259e749b9bc0c97a021c..86dcfcc25099e5e9e26ca61e3be39b61bb78f3c3 100644 --- a/lib/c/labcomm.c +++ b/lib/c/labcomm.c @@ -42,7 +42,7 @@ typedef struct labcomm_sample_entry { labcomm_signature_t *signature; labcomm_decoder_typecast_t decoder; labcomm_handler_typecast_t handler; - labcomm_encode_typecast_t encode; + labcomm_encoder_function encode; void *context; } labcomm_sample_entry_t; @@ -224,32 +224,14 @@ static int get_encoder_index( #endif } -void labcomm_encoder_start(struct labcomm_encoder *e, - labcomm_signature_t *s) -{ - int index = get_encoder_index(e, s); - e->writer.write(&e->writer, labcomm_writer_start, index); -} - -void labcomm_encoder_end(struct labcomm_encoder *e, - labcomm_signature_t *s) -{ - e->writer.write(&e->writer, labcomm_writer_end); -} - -void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s) -{ - int index = get_encoder_index(e, s); - labcomm_encode_packed32(e, index); -} - void labcomm_encode_signature(struct labcomm_encoder *e, labcomm_signature_t *signature) { int i; e->writer.write(&e->writer, labcomm_writer_start_signature); labcomm_encode_packed32(e, signature->type); - labcomm_encode_type_index(e, signature); + labcomm_encode_packed32(e, get_encoder_index(e, signature)); + labcomm_encode_string(e, signature->name); for (i = 0 ; i < signature->size ; i++) { if (e->writer.pos >= e->writer.count) { @@ -264,7 +246,7 @@ void labcomm_encode_signature(struct labcomm_encoder *e, #ifdef LABCOMM_ENCODER_LINEAR_SEARCH static int encoder_add_signature_by_search(struct labcomm_encoder *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode) + labcomm_encoder_function encode) { int result; labcomm_encoder_context_t *context = e->context; @@ -289,7 +271,7 @@ static int encoder_add_signature_by_search(struct labcomm_encoder *e, #ifndef LABCOMM_ENCODER_LINEAR_SEARCH static int encoder_add_signature_by_section(struct labcomm_encoder *e, labcomm_signature_t *s, - labcomm_encode_typecast_t encode) + labcomm_encoder_function encode) { int result = -ENOENT; @@ -319,7 +301,7 @@ out: static int encoder_add_signature(struct labcomm_encoder *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode) + labcomm_encoder_function encode) { int index = -ENOENT; @@ -333,7 +315,7 @@ static int encoder_add_signature(struct labcomm_encoder *e, static void do_encoder_register(struct labcomm_encoder *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode) + labcomm_encoder_function encode) { if (signature->type == LABCOMM_SAMPLE) { if (get_encoder_index(e, signature) == 0) { @@ -355,6 +337,7 @@ static void do_encoder_register(struct labcomm_encoder *e, } } +/* static labcomm_sample_entry_t *encoder_get_sample_by_signature_address( labcomm_encoder_t *encoder, labcomm_signature_t *s) @@ -371,32 +354,30 @@ static labcomm_sample_entry_t *encoder_get_sample_by_signature_address( #endif return result; } +*/ -static void do_encode( - labcomm_encoder_t *encoder, +static int do_encode( + labcomm_encoder_t *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode, + labcomm_encoder_function encode, void *value) { - labcomm_sample_entry_t *sample; - sample = encoder_get_sample_by_signature_address(encoder, signature); - (void)sample; - - labcomm_encoder_start(encoder, signature); - labcomm_encode_type_index(encoder, signature); - encode(encoder, value); - labcomm_encoder_end(encoder, signature); -/* - labcomm_sample_entry_t *sample; - + int result; + labcomm_writer_start_t lws; - sample = encoder_get_sample_by_signature_address(encoder, signature); - if (sample && sample->encode) { - sample->encode(encoder, value); - } else { - encoder->on_error(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE, 2, "No registration for %s.\n", signature->name); - } -*/ + lws.encoder = e; + lws.index = get_encoder_index(e, signature); + lws.signature = signature; + lws.value = value; + result = e->writer.write(&e->writer, labcomm_writer_start, &lws); + if (result == -EALREADY) { result = 0; goto out; } + if (result != 0) { goto out; } + result = labcomm_encode_packed32(e, lws.index); + if (result != 0) { goto out; } + result = encode(e, value); +out: + e->writer.write(&e->writer, labcomm_writer_end, &lws); + return result; } labcomm_encoder_t *labcomm_encoder_new( @@ -435,7 +416,7 @@ labcomm_encoder_t *labcomm_encoder_new( void labcomm_internal_encoder_register( labcomm_encoder_t *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode) + labcomm_encoder_function encode) { // Will segfault if e == NULL. if (e->do_register) { @@ -445,17 +426,18 @@ void labcomm_internal_encoder_register( } } -void labcomm_internal_encode( +int labcomm_internal_encode( labcomm_encoder_t *e, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode, + labcomm_encoder_function encode, void *value) { if (e->do_encode) { - e->do_encode(e, signature, encode, value); + return e->do_encode(e, signature, encode, value); } else { e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_ENCODE, 0); } + return 0; } void labcomm_encoder_free(labcomm_encoder_t* e) diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h index 48d4cbe05b42c0981176acfc991b9252b65b6846..41420b6c760a362caea579ecbb673c9ec683e18a 100644 --- a/lib/c/labcomm.h +++ b/lib/c/labcomm.h @@ -11,7 +11,7 @@ struct labcomm_decoder; /* * Signature entry */ -typedef struct labcomm_signature{ +typedef struct labcomm_signature { int type; char *name; int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample * @@ -115,12 +115,20 @@ void labcomm_decoder_free( /* * Encoder */ +typedef struct { + struct labcomm_encoder *encoder; + int index; + labcomm_signature_t *signature; + void *value; +} labcomm_writer_start_t; typedef enum { labcomm_writer_alloc, /* (..., char *labcomm_version) Allocate all neccessary data */ labcomm_writer_free, /* Free all allocated data */ - labcomm_writer_start, /* Start writing an ordinary sample */ + labcomm_writer_start, /* (..., labcomm_writer_start_t *s) + -EALREADY skips further encoding + Start writing an ordinary sample */ labcomm_writer_continue, /* Buffer full during ordinary sample */ labcomm_writer_end, /* End writing ordinary sample */ labcomm_writer_start_signature, /* Start writing signature */ diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h index 301f590d2835a6fc6657c7b3f85d40d9b3944977..13761dda4745ad7644ed81db1b2f6f0652bbe5f5 100644 --- a/lib/c/labcomm_private.h +++ b/lib/c/labcomm_private.h @@ -203,7 +203,7 @@ static inline char *labcomm_decode_string(labcomm_decoder_t *d) /* * Semi private encoder declarations */ -typedef void (*labcomm_encode_typecast_t)( +typedef int (*labcomm_encoder_function)( struct labcomm_encoder *, void *value); @@ -212,10 +212,10 @@ typedef struct labcomm_encoder { labcomm_writer_t writer; void (*do_register)(struct labcomm_encoder *encoder, labcomm_signature_t *signature, - labcomm_encode_typecast_t); - void (*do_encode)(struct labcomm_encoder *encoder, + labcomm_encoder_function encode); + int (*do_encode)(struct labcomm_encoder *encoder, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode, + labcomm_encoder_function encode, void *value); labcomm_error_handler_callback on_error; } labcomm_encoder_t; @@ -223,46 +223,52 @@ typedef struct labcomm_encoder { void labcomm_internal_encoder_register( labcomm_encoder_t *encoder, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode); + labcomm_encoder_function encode); -void labcomm_internal_encode( +int labcomm_internal_encode( labcomm_encoder_t *encoder, labcomm_signature_t *signature, - labcomm_encode_typecast_t encode, + labcomm_encoder_function encode, void *value); #if __BYTE_ORDER == __LITTLE_ENDIAN #define LABCOMM_ENCODE(name, type) \ - static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \ + static inline int labcomm_write_##name(labcomm_writer_t *w, type data) { \ int i; \ for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \ if (w->pos >= w->count) { /*buffer is full*/ \ - w->write(w, labcomm_writer_continue); \ + int err; \ + err = w->write(w, labcomm_writer_continue); \ + if (err != 0) { return err; } \ } \ w->data[w->pos] = ((unsigned char*)(&data))[i]; \ w->pos++; \ } \ + return 0; \ } \ - static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ - labcomm_write_##name(&e->writer, data); \ + static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ + return labcomm_write_##name(&e->writer, data); \ } #else #define LABCOMM_ENCODE(name, type) \ - static inline void labcomm_write_##name(labcomm_writer_t *w, type data) { \ + static inline int labcomm_write_##name(labcomm_writer_t *w, type data) { \ int i; \ for (i = 0 ; i < sizeof(type) ; i++) { \ if (w->pos >= w->count) { \ - w->write(w, labcomm_writer_continue); \ + int err; \ + err = w->write(w, labcomm_writer_continue); \ + if (err != 0) { return err; } \ } \ w->data[w->pos] = ((unsigned char*)(&data))[i]; \ w->pos++; \ } \ + return 0; \ } \ - static inline void labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ - labcomm_write_##name(&e->writer, data); \ + static inline int labcomm_encode_##name(labcomm_encoder_t *e, type data) { \ + return labcomm_write_##name(&e->writer, data); \ } #endif @@ -287,7 +293,8 @@ LABCOMM_ENCODE(double, double) * 0b1110 - 4 bytes (0x00200000 - 0x0fffffff) * 0b11110 - 5 bytes (0x10000000 - 0xffffffff) [4 bits unused] */ -static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data) +static inline int labcomm_write_packed32(labcomm_writer_t *w, + unsigned int data) { int n; unsigned char tag; @@ -311,68 +318,86 @@ static inline void labcomm_pack32(labcomm_writer_t *w, unsigned int data) n = 5; tag = 0xf0; } - if (w->pos + n - 1 >= w->count) { + /* TODO: maybe? + if (w->pos + n - 1 >= w->count) { w->write(w, labcomm_writer_continue, n); - } + } + */ switch (n) { case 5: { - if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + if (w->pos >= w->count) { + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos++] = tag; tag = 0; } case 4: { if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos++] = tmp[0] | tag; tag = 0; } case 3: { if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos++] = tmp[1] | tag; tag = 0; } case 2: { if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos++] = tmp[2] | tag; tag = 0; } case 1: { if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos++] = tmp[3] | tag; } } + return 0; } -static inline void labcomm_encode_packed32(labcomm_encoder_t *e, unsigned int data) +static inline int labcomm_encode_packed32(labcomm_encoder_t *e, + unsigned int data) { - labcomm_pack32(&e->writer, data); + return labcomm_write_packed32(&e->writer, data); } -static inline void labcomm_write_string(labcomm_writer_t *w, char *s) +static inline int labcomm_write_string(labcomm_writer_t *w, char *s) { - int length, i; + int length, i, err; length = strlen((char*)s); - labcomm_pack32(w, length); + err = labcomm_write_packed32(w, length); + if (err != 0) { return err; } for (i = 0 ; i < length ; i++) { if (w->pos >= w->count) { - w->write(w, labcomm_writer_continue); + int err; + err = w->write(w, labcomm_writer_continue); + if (err != 0) { return err; } } w->data[w->pos] = s[i]; w->pos++; } + return 0; } -static inline void labcomm_encode_string(labcomm_encoder_t *e, +static inline int labcomm_encode_string(labcomm_encoder_t *e, char *s) { - labcomm_write_string(&e->writer, s); + return labcomm_write_string(&e->writer, s); } #endif diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c index 17efb239106e1b09a8be68a3720ba5af4bbf985f..1b174726e54a89d20ca73db14be31951c8a3ffe4 100644 --- a/lib/c/test/test_labcomm_generated_encoding.c +++ b/lib/c/test/test_labcomm_generated_encoding.c @@ -115,6 +115,15 @@ void dump_encoder(labcomm_encoder_t *encoder) printf("\n"); } +#define EXPECT(...) \ + { \ + int expected[] = __VA_ARGS__; \ + labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, \ + __LINE__, \ + sizeof(expected)/sizeof(expected[0]), \ + expected); \ + } + int main(void) { generated_encoding_V V; @@ -124,39 +133,19 @@ int main(void) labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encoder_register_generated_encoding_V(encoder); - { - int expected[] = { 0x02, -1, 0x01, 'V', 0x11, 0x00 }; - labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, - __LINE__, - 6, expected); - } + EXPECT({ 0x02, -1, 0x01, 'V', 0x11, 0x00 }); labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encoder_register_generated_encoding_B(encoder); - { - int expected[] = { 0x02, -1, 0x01, 'B', 0x21 }; - labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, - __LINE__, - 5, expected); - } + EXPECT({0x02, -1, 0x01, 'B', 0x21}); labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encode_generated_encoding_V(encoder, &V); - { - int expected[] = { -1 }; - labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, - __LINE__, - 1, expected); - } + EXPECT({-1}); labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encode_generated_encoding_B(encoder, &B); - { - int expected[] = { -1, 1 }; - labcomm_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES, - __LINE__, - 2, expected); - } + EXPECT({-1, 1}); return 0; }