Commit 45c7b977 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Refactored code to not expose labcomm_encoder_start,

labcomm_encode_type_index, labcomm_encoder_end

Added test of generated C encoders.
parent dd7bfe04
......@@ -641,19 +641,9 @@ aspect C_Encoder {
env.println(")");
env.println("{");
env.indent();
env.println("labcomm_encoder_start(e, &labcomm_signature_" +
env.prefix + getName() + ");");
env.println("labcomm_encode_type_index(e, &labcomm_signature_" +
env.prefix + getName() + ");");
env.println("{");
env.indent();
getType().C_emitEncoder(env);
env.unindent();
env.println("}");
env.println("labcomm_encoder_end(e, &labcomm_signature_" +
env.prefix + getName() + ");");
env.unindent();
env.println("}");
// Typesafe encode wrapper
env.println("void labcomm_encode_" + env.prefix + getName() + "(");
......@@ -664,7 +654,9 @@ aspect C_Encoder {
env.println("{");
env.indent();
env.println("labcomm_internal_encode(e, &labcomm_signature_" +
env.prefix + getName() + ", v);");
env.prefix + getName() +
", (labcomm_encode_typecast_t)encode_" + getName() +
", v);");
env.unindent();
env.println("}");
}
......
......@@ -10,7 +10,8 @@ OBJS= labcomm.o labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_w
LABCOMMC_PATH=../../compiler
LABCOMMC_JAR=$(LABCOMMC_PATH)/labComm.jar
TESTS=test_labcomm_basic_type_encoding test_labcomm test_labcomm_errors
TESTS=test_labcomm_basic_type_encoding test_labcomm_generated_encoding test_labcomm
#FIXME: test_labcomm_errors
TEST_DIR=test
TESTDATA_DIR=$(TEST_DIR)/testdata
TEST_GEN_DIR=$(TESTDATA_DIR)/gen
......@@ -63,6 +64,15 @@ $(TEST_DIR)/%.o: $(TEST_DIR)/%.c
$(TEST_DIR)/%: $(TEST_DIR)/%.o liblabcomm.a
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(LDLIBS_TEST)
$(TEST_DIR)/gen:
mkdir -p $@
$(TEST_DIR)/gen/%.c $(TEST_DIR)/gen/%.h: $(TEST_DIR)/%.lc | $(TEST_DIR)/gen
java -jar $(LABCOMMC_JAR) \
--c=$(TEST_DIR)/gen/$*.c \
--h=$(TEST_DIR)/gen/$*.h \
$<
$(TEST_GEN_DIR)/%.c $(TEST_GEN_DIR)/%.h: $(TESTDATA_DIR)/%.lc \
$(LABCOMMC_JAR) | $(TEST_GEN_DIR)
java -jar $(LABCOMMC_JAR) \
......@@ -82,11 +92,14 @@ clean:
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) test/testdata/gen/*.[cho]
$(RM) test/gen/*.[cho]
$(RM) $(TEST_DIR)/test_labcomm
distclean: clean
$(RM) liblabcomm.a
# Extra dependencies
$(TEST_DIR)/test_labcomm_basic_type_encoding.o: labcomm_private.h
$(TEST_DIR)/test_labcomm_generated_encoding.o : $(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/test_labcomm_generated_encoding : $(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/test_labcomm: $(TEST_GEN_DIR)/test_sample.o
$(TEST_DIR)/test_labcomm_private.o: labcomm_private.h
/*
labcomm.c -- runtime for handling encoding and decoding of
labcomm samples.
Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
......@@ -26,9 +46,18 @@ typedef struct labcomm_sample_entry {
void *context;
} labcomm_sample_entry_t;
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
extern labcomm_signature_t labcomm_first_signature;
extern labcomm_signature_t labcomm_last_signature;
#endif
typedef struct labcomm_encoder_context {
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
labcomm_sample_entry_t *sample;
int index;
#else
labcomm_sample_entry_t *by_section;
#endif
} labcomm_encoder_context_t;
typedef struct labcomm_decoder_context {
......@@ -152,7 +181,7 @@ static labcomm_sample_entry_t *get_sample_by_index(
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int get_encoder_index(
static int get_encoder_index_by_search(
labcomm_encoder_t *e,
labcomm_signature_t *s)
{
......@@ -171,14 +200,11 @@ static int get_encoder_index(
#else
static int get_encoder_index(
static int get_encoder_index_by_section(
labcomm_encoder_t *e,
labcomm_signature_t *s)
{
int result = 0;
extern labcomm_signature_t labcomm_first_signature;
extern labcomm_signature_t labcomm_last_signature;
int result = -ENOENT;
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
//fprintf(stderr, "%d\n", (int)(s - &labcomm_start));
result = s - &labcomm_first_signature + LABCOMM_USER;
......@@ -187,6 +213,16 @@ static int get_encoder_index(
}
#endif
static int get_encoder_index(
labcomm_encoder_t *e,
labcomm_signature_t *s)
{
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
return get_encoder_index_by_search(e, s);
#else
return get_encoder_index_by_section(e, s);
#endif
}
void labcomm_encoder_start(struct labcomm_encoder *e,
labcomm_signature_t *s)
......@@ -225,50 +261,142 @@ void labcomm_encode_signature(struct labcomm_encoder *e,
e->writer.write(&e->writer, labcomm_writer_end_signature);
}
#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)
{
int result;
labcomm_encoder_context_t *context = e->context;
labcomm_sample_entry_t *sample;
sample = (labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t));
if (sample == NULL) {
result = -ENOMEM;
} else {
sample->next = context->sample;
sample->index = context->index;
sample->signature = signature;
sample->encode = encode;
context->index++;
context->sample = sample;
result = sample->index;
}
return result;
}
#endif
#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)
{
int result = -ENOENT;
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
/* Signature is in right linker section */
labcomm_encoder_context_t *context = e->context;
int index = s - &labcomm_first_signature;
if (context->by_section == NULL) {
int n = &labcomm_last_signature - &labcomm_first_signature;
context->by_section = malloc(n * sizeof(context->by_section[0]));
}
if (context->by_section == NULL) {
result = -ENOMEM;
goto out;
}
context->by_section[index].next = NULL;
context->by_section[index].index = index + LABCOMM_USER;
context->by_section[index].signature = s;
context->by_section[index].encode = encode;
result = context->by_section[index].index;
}
out:
return result;
}
#endif
static int encoder_add_signature(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
{
int index = -ENOENT;
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
index = encoder_add_signature_by_search(e, signature, encode);
#else
index = encoder_add_signature_by_section(e, signature, encode);
#endif
return index;
}
static void do_encoder_register(struct labcomm_encoder *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
{
if (signature->type == LABCOMM_SAMPLE) {
if (get_encoder_index(e, signature) == 0) {
labcomm_encoder_context_t *context = e->context;
labcomm_sample_entry_t *sample =
(labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t));
sample->next = context->sample;
sample->index = context->index;
sample->signature = signature;
sample->encode = encode;
context->index++;
context->sample = sample;
struct labcomm_ioctl_register_signature ioctl_data;
int err;
ioctl_data.index = sample->index;
ioctl_data.signature = signature;
err = labcomm_encoder_ioctl(e, LABCOMM_IOCTL_REGISTER_SIGNATURE,
&ioctl_data);
if (err != 0) {
labcomm_encode_signature(e, signature);
int index = encoder_add_signature(e, signature, encode);
if (index > 0) {
struct labcomm_ioctl_register_signature ioctl_data;
int err;
ioctl_data.index = index;
ioctl_data.signature = signature;
err = labcomm_encoder_ioctl(e, LABCOMM_IOCTL_REGISTER_SIGNATURE,
&ioctl_data);
if (err != 0) {
labcomm_encode_signature(e, signature);
}
}
}
}
}
static labcomm_sample_entry_t *encoder_get_sample_by_signature_address(
labcomm_encoder_t *encoder,
labcomm_signature_t *s)
{
labcomm_sample_entry_t *result = NULL;
labcomm_encoder_context_t *context = encoder->context;
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
if (&labcomm_first_signature <= s && s <= &labcomm_last_signature) {
result = &context->by_section[s - &labcomm_first_signature];
}
#else
result = get_sample_by_signature_address(context->sample, s);
#endif
return result;
}
static void do_encode(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
void *value)
{
labcomm_encoder_context_t *context = encoder->context;
labcomm_sample_entry_t *sample;
sample = get_sample_by_signature_address(context->sample,
signature);
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;
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);
}
*/
}
labcomm_encoder_t *labcomm_encoder_new(
......@@ -280,8 +408,12 @@ labcomm_encoder_t *labcomm_encoder_new(
labcomm_encoder_context_t *context;
context = malloc(sizeof(labcomm_encoder_context_t));
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
context->sample = NULL;
context->index = LABCOMM_USER;
#else
context->by_section = NULL;
#endif
result->context = context;
result->writer.context = writer_context;
result->writer.data = 0;
......@@ -316,11 +448,11 @@ void labcomm_internal_encoder_register(
void labcomm_internal_encode(
labcomm_encoder_t *e,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
void *value)
{
// Will segfault if e == NULL
if (e->do_encode) {
e->do_encode(e, signature, value);
e->do_encode(e, signature, encode, value);
} else {
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_ENCODE, 0);
}
......@@ -329,16 +461,19 @@ void labcomm_internal_encode(
void labcomm_encoder_free(labcomm_encoder_t* e)
{
e->writer.write(&e->writer, labcomm_writer_free);
labcomm_encoder_context_t *econtext = (labcomm_encoder_context_t *) e->context;
labcomm_sample_entry_t *sentry = econtext->sample;
labcomm_sample_entry_t *sentry_next;
while (sentry != NULL) {
sentry_next = sentry->next;
free(sentry);
sentry = sentry_next;
}
labcomm_encoder_context_t *context = (labcomm_encoder_context_t *) e->context;
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
labcomm_sample_entry_t *entry = context->sample;
labcomm_sample_entry_t *entry_next;
while (entry != NULL) {
entry_next = entry->next;
free(entry);
entry = entry_next;
}
#else
free(context->by_section);
#endif
free(e->context);
free(e);
}
......
......@@ -215,6 +215,7 @@ typedef struct labcomm_encoder {
labcomm_encode_typecast_t);
void (*do_encode)(struct labcomm_encoder *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
void *value);
labcomm_error_handler_callback on_error;
} labcomm_encoder_t;
......@@ -227,19 +228,9 @@ void labcomm_internal_encoder_register(
void labcomm_internal_encode(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode,
void *value);
void labcomm_encoder_start(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature);
//HERE BE DRAGONS: is the signature_t* needed here?
void labcomm_encoder_end(
labcomm_encoder_t *encoder,
labcomm_signature_t *signature);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_ENCODE(name, type) \
......@@ -384,6 +375,4 @@ static inline void labcomm_encode_string(labcomm_encoder_t *e,
labcomm_write_string(&e->writer, s);
}
void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s);
#endif
sample void V;
sample byte B;
sample struct {
int i;
} S1;
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "labcomm_private.h"
#include "labcomm_private.h"
#include "test/gen/generated_encoding.h"
int test_write(struct labcomm_writer *w, labcomm_writer_action_t a, ...)
{
fprintf(stderr, "test_write should not be called\n");
exit(1);
}
int test_read(struct labcomm_reader *r, labcomm_reader_action_t a, ...)
{
fprintf(stderr, "test_read should not be called\n");
exit(1);
}
#define IOCTL_WRITER_ASSERT_BYTES 4096
#define IOCTL_WRITER_RESET 4097
static unsigned char buffer[128];
static int buffer_writer_ioctl(
struct labcomm_writer *w, int action, va_list arg)
{
int result = -ENOTSUP;
switch (action) {
case IOCTL_WRITER_ASSERT_BYTES: {
int line = va_arg(arg, int);
int count = va_arg(arg, int);
int *expected = va_arg(arg, int *);
int i, mismatch;
if (w->pos != count) {
fprintf(stderr, "Invalid length encoded %d != %d (%s:%d)\n",
w->pos, count, __FILE__, line);
mismatch = 1;
}
for (mismatch = 0, i = 0 ; i < count ; i++) {
if (expected[i] >= 0 && expected[i] != buffer[i]) {
mismatch = 1;
}
}
if (mismatch) {
fprintf(stderr, "Encoder mismatch (%s:%d)\n",
__FILE__, line);
for (i = 0 ; i < w->pos ; i++) {
printf("%2.2x ", w->data[i]);
}
printf("\n");
for (i = 0 ; i < count ; i++) {
if (expected[i] < 0) {
printf(".. ");
} else {
printf("%2.2x ", expected[i] );
}
}
printf("\n");
exit(1);
}
result = 0;
} break;
case IOCTL_WRITER_RESET: {
w->pos = 0;
result = 0;
}
}
return result;
}
static int buffer_writer(
labcomm_writer_t *w,
labcomm_writer_action_t action,
...)
{
switch (action) {
case labcomm_writer_alloc: {
w->data_size = sizeof(buffer);
w->count = w->data_size;
w->data = buffer;
w->pos = 0;
w->ioctl = buffer_writer_ioctl;
} break;
case labcomm_writer_start:
case labcomm_writer_start_signature: {
} break;
case labcomm_writer_continue:
case labcomm_writer_continue_signature: {
fprintf(stderr, "Should not come here %s:%d\n", __FILE__, __LINE__);
exit(1);
} break;
case labcomm_writer_end:
case labcomm_writer_end_signature: {
} break;
case labcomm_writer_free: {
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} break;
}
return w->error;
}
void dump_encoder(labcomm_encoder_t *encoder)
{
int i;
for (i = 0 ; i < encoder->writer.pos ; i++) {
printf("%2.2x ", encoder->writer.data[i]);
}
printf("\n");
}
int main(void)
{
generated_encoding_V V;
generated_encoding_B B = 1;
labcomm_encoder_t *encoder = labcomm_encoder_new(buffer_writer, buffer);
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);
}
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);
}
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);
}
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);
}
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment