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 118 additions and 2071 deletions
## Macros
VERSIONS=2014
CC=gcc
#CFLAGS=-g -Wall -Werror -O3 -I. -Itest -DLABCOMM_ENCODER_LINEAR_SEARCH
CFLAGS=-g -Wall -Werror -O3 -I. -Itest
LDFLAGS=-L.
#LDLIBS_TEST=-Tlabcomm.linkscript -lcunit -llabcomm
LDLIBS_TEST=-lcunit -llabcomm -Tlabcomm.linkscript
all:
OBJS= labcomm.o \
labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o \
labcomm_pthread_mutex_lock.o
%:
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
#FIXME: labcomm_mem_reader.o labcomm_mem_writer.o
LABCOMM_JAR=../../compiler/labComm.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding test_labcomm_generated_encoding
#
#FIXME: test_labcomm test_labcomm_errors
TEST_DIR=test
TESTDATA_DIR=$(TEST_DIR)/testdata
TEST_GEN_DIR=$(TESTDATA_DIR)/gen
.PHONY: clean
clean:
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
VPATH=$(TEST_DIR)
.PHONY: distclean
distclean:
for v in $(VERSIONS) ; do $(MAKE) -C $${v} $@ || exit 1 ; done
rm -f *.o *.so *.so.1 *.a
CREATED_DIRS=$(TEST_DIR) $(TESTDATA_DIR) $(TEST_GEN_DIR)
# Enable experimental objects by invoking make like `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
## Targets
.PHONY: all run-test clean distclean
all: liblabcomm.a liblabcomm.so.1
liblabcomm.a: $(OBJS)
ar -r liblabcomm.a $^
liblabcomm.so.1: $(OBJS:%.o=%.pic.o)
gcc -shared -Wl,-soname,$@ -o $@ $^ -lc
labcomm.o : labcomm.c labcomm.h labcomm_private.h
labcomm_fd_reader_writer.o : labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h labcomm.h labcomm_private.h
#$(TEST_DIR)/labcomm_mem_reader.o: labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h
#$(TEST_DIR)/labcomm_mem_writer.o: labcomm_mem_writer.c labcomm_mem_writer.h cppmacros.h
ethaddr.o: ethaddr.c
$(CREATED_DIRS):
mkdir -p $@
## NB! the tests need CUnit to be installed
run-test: $(TESTS:%=run-test-%)
run-test-%: $(TEST_DIR)/% | $(TEST_DIR)
$<
$(TEST_DIR)/%.o: $(TEST_DIR)/%.c
$(CC) $(CFLAGS) -o $@ -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
$(LABCOMM) \
--c=$(TEST_DIR)/gen/$*.c \
--h=$(TEST_DIR)/gen/$*.h \
$<
$(TEST_GEN_DIR)/%.c $(TEST_GEN_DIR)/%.h: $(TESTDATA_DIR)/%.lc \
$(LABCOMM_JAR) | $(TEST_GEN_DIR)
$(LABCOMM) \
--c=$(patsubst %.h,%.c,$@) --h=$(patsubst %.c,%.h,$@) $<
$(LABCOMM_JAR):
@echo "======Building LabComm compiler======"
cd $(shell dirname $(LABCOMM_JAR)); ant jar
@echo "======End building LabComm compiler======"
%.pic.o: %.c
$(CC) -fPIC $(CFLAGS) -c -o $@ $<
%.o: %.c %.h
clean:
$(RM) *.o
$(RM) experimental/*.o experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(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.so.1
$(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
labcomm_fd_reader.o: labcomm_private.h
labcomm_fd_writer.o: labcomm_private.h
labcomm_dynamic_buffer_writer.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
#include <stdio.h>
#include <strings.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include "labcomm.h"
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
#define LABCOMM_VERSION "LabComm2013"
struct labcomm_decoder {
void *context;
struct labcomm_reader *reader;
struct labcomm_lock *lock;
labcomm_error_handler_callback on_error;
labcomm_handle_new_datatype_callback on_new_datatype;
LABCOMM_SIGNATURE_ARRAY_DEF(local_to_remote, int);
LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
};
struct labcomm_encoder {
void *context;
struct labcomm_writer *writer;
struct labcomm_lock *lock;
labcomm_error_handler_callback on_error;
LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
};
struct labcomm_sample_entry {
struct labcomm_sample_entry *next;
int index;
struct labcomm_signature *signature;
labcomm_decoder_function decoder;
labcomm_handler_function handler;
labcomm_encoder_function encode;
void *context;
};
#ifndef LABCOMM_ENCODER_LINEAR_SEARCH
extern struct labcomm_signature labcomm_first_signature;
extern struct labcomm_signature labcomm_last_signature;
#endif
struct labcomm_encoder_context {
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
struct labcomm_sample_entry *sample;
int index;
#else
struct labcomm_sample_entry *by_section;
#endif
};
struct labcomm_decoder_context {
struct labcomm_sample_entry *sample;
};
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback)
{
encoder->on_error = callback;
}
void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback)
{
decoder->on_error = callback;
}
static const char *labcomm_error_string[] = {
#define LABCOMM_ERROR(name, description) description ,
#include "labcomm_error.h"
#undef LABCOMM_ERROR
};
static const int labcomm_error_string_count = (sizeof(labcomm_error_string) /
sizeof(labcomm_error_string[0]));
const char *labcomm_error_get_str(enum labcomm_error error_id)
{
const char *error_str = NULL;
// Check if this is a known error ID.
if (0 <= error_id && error_id < labcomm_error_string_count) {
error_str = labcomm_error_string[error_id];
}
return error_str;
}
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d, labcomm_handle_new_datatype_callback on_new_datatype)
{
d->on_new_datatype = on_new_datatype;
}
int on_new_datatype(struct labcomm_decoder *d, struct labcomm_signature *sig)
{
d->on_error(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE, 4, "%s(): unknown datatype '%s'\n", __FUNCTION__, sig->name);
return 0;
}
void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...)
{
#ifndef LABCOMM_NO_STDIO
const char *err_msg = labcomm_error_get_str(error_id); // The final string to print.
if (err_msg == NULL) {
err_msg = "Error with an unknown error ID occured.";
}
fprintf(stderr, "%s\n", err_msg);
if (nbr_va_args > 0) {
va_list arg_pointer;
va_start(arg_pointer, nbr_va_args);
fprintf(stderr, "%s\n", "Extra info {");
char *print_format = va_arg(arg_pointer, char *);
vfprintf(stderr, print_format, arg_pointer);
fprintf(stderr, "}\n");
va_end(arg_pointer);
}
#else
; // If labcomm can't be compiled with stdio the user will have to make an own error callback functionif he/she needs error reporting.
#endif
}
static struct labcomm_sample_entry *get_sample_by_signature_address(
struct labcomm_sample_entry *head,
struct labcomm_signature *signature)
{
struct labcomm_sample_entry *p;
for (p = head ; p && p->signature != signature ; p = p->next) {
}
return p;
}
static struct labcomm_sample_entry *get_sample_by_signature_value(
struct labcomm_sample_entry *head,
struct labcomm_signature *signature)
{
struct labcomm_sample_entry *p;
for (p = head ; p ; p = p->next) {
if (p->signature->type == signature->type &&
p->signature->size == signature->size &&
strcmp(p->signature->name, signature->name) == 0 &&
bcmp((void*)p->signature->signature, (void*)signature->signature,
signature->size) == 0) {
break;
}
}
return p;
}
static struct labcomm_sample_entry *get_sample_by_index(
struct labcomm_sample_entry *head,
int index)
{
struct labcomm_sample_entry *p;
for (p = head ; p && p->index != index ; p = p->next) {
}
return p;
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int get_encoder_index_by_search(
struct labcomm_encoder *e,
struct labcomm_signature *s)
{
int result = 0;
struct labcomm_encoder_context *context = e->context;
struct labcomm_sample_entry *sample = context->sample;
while (sample) {
if (sample->signature == s) { break; }
sample = sample->next;
}
if (sample) {
result = sample->index;
}
return result;
}
#else
static int get_local_index(
struct labcomm_signature *s)
{
int result = -ENOENT;
if (&labcomm_first_signature <= s && s < &labcomm_last_signature) {
result = (int)(s - &labcomm_first_signature) + LABCOMM_USER;
}
return result;
}
#endif
static int get_encoder_index(
struct labcomm_encoder *e,
struct labcomm_signature *s)
{
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
return get_encoder_index_by_search(e, s);
#else
return get_local_index(s);
#endif
}
static void labcomm_encode_signature(struct labcomm_encoder *e,
struct labcomm_signature *signature)
{
int i, index;
index = get_encoder_index(e, signature);
e->writer->action->start(e->writer, e->writer->context,
e, index, signature, NULL);
labcomm_write_packed32(e->writer, signature->type);
labcomm_write_packed32(e->writer, index);
labcomm_write_string(e->writer, signature->name);
for (i = 0 ; i < signature->size ; i++) {
if (e->writer->pos >= e->writer->count) {
e->writer->action->flush(e->writer, e->writer->context);
}
e->writer->data[e->writer->pos] = signature->signature[i];
e->writer->pos++;
}
e->writer->action->end(e->writer, e->writer->context);
}
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
static int encoder_add_signature_by_search(struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
int result;
struct labcomm_encoder_context *context = e->context;
struct labcomm_sample_entry *sample;
sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample));
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
/*
static struct labcomm_sample_entry *encoder_get_sample_by_signature_address(
struct labcomm_encoder *encoder,
struct labcomm_signature *s)
{
struct labcomm_sample_entry *result = NULL;
struct labcomm_encoder_context *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;
}
*/
struct labcomm_encoder *labcomm_encoder_new(
struct labcomm_writer *writer,
struct labcomm_lock *lock)
{
struct labcomm_encoder *result = malloc(sizeof(*result));
if (result) {
struct labcomm_encoder_context *context;
context = malloc(sizeof(*context));
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
context->sample = NULL;
context->index = LABCOMM_USER;
#else
context->by_section = NULL;
#endif
result->context = context;
result->writer = writer;
result->writer->data = 0;
result->writer->data_size = 0;
result->writer->count = 0;
result->writer->pos = 0;
result->writer->error = 0;
result->lock = lock;
result->on_error = on_error_fprintf;
LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
result->writer->action->alloc(result->writer,result->writer->context,
result, LABCOMM_VERSION);
}
return result;
}
void labcomm_internal_encoder_register(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
if (signature->type == LABCOMM_SAMPLE) {
int index = get_local_index(signature);
if (index > 0) {
int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->registered, int, index);
if (! *registered) {
struct labcomm_ioctl_register_signature ioctl_data;
int err;
*registered = 1;
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);
}
}
}
}
}
int labcomm_internal_encode(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode,
void *value)
{
int result;
int index;
index = get_encoder_index(e, signature);
result = e->writer->action->start(e->writer, e->writer->context,
e, index, signature, value);
if (result == -EALREADY) { result = 0; goto no_end; }
if (result != 0) { goto out; }
result = labcomm_write_packed32(e->writer, index);
if (result != 0) { goto out; }
result = encode(e->writer, value);
out:
e->writer->action->end(e->writer, e->writer->context);
no_end:
return result;
}
void labcomm_encoder_free(struct labcomm_encoder* e)
{
struct labcomm_encoder_context *context;
context = (struct labcomm_encoder_context *) e->context;
e->writer->action->free(e->writer, e->writer->context);
LABCOMM_SIGNATURE_ARRAY_FREE(e->registered, int);
#ifdef LABCOMM_ENCODER_LINEAR_SEARCH
struct labcomm_sample_entry *entry = context->sample;
struct labcomm_sample_entry *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);
}
int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
uint32_t action,
...)
{
int result;
va_list va;
if (encoder->writer->action->ioctl == NULL) {
result = -ENOTSUP;
goto out;
}
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = encoder->writer->action->ioctl(encoder->writer,
encoder->writer->context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
static int labcomm_writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
{
int result;
va_list va;
if (writer->action->ioctl == NULL) {
result = -ENOTSUP;
goto out;
}
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = writer->action->ioctl(writer, writer->context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
uint32_t action, va_list va)
{
int result = -ENOTSUP;
if (encoder->writer->action->ioctl != NULL) {
result = encoder->writer->action->ioctl(encoder->writer,
encoder->writer->context,
-1, signature, action, va);
}
return result;
}
static void collect_flat_signature(
struct labcomm_decoder *decoder,
struct labcomm_writer *writer)
{
int type = labcomm_read_packed32(decoder->reader);
if (type >= LABCOMM_USER) {
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
"Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type);
} else {
labcomm_write_packed32(writer, type);
switch (type) {
case LABCOMM_ARRAY: {
int dimensions, i;
dimensions = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, dimensions);
for (i = 0 ; i < dimensions ; i++) {
int n = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, n);
}
collect_flat_signature(decoder, writer);
} break;
case LABCOMM_STRUCT: {
int fields, i;
fields = labcomm_read_packed32(decoder->reader);
labcomm_write_packed32(writer, fields);
for (i = 0 ; i < fields ; i++) {
char *name = labcomm_read_string(decoder->reader);
labcomm_write_string(writer, name);
free(name);
collect_flat_signature(decoder, writer);
}
} break;
case LABCOMM_BOOLEAN:
case LABCOMM_BYTE:
case LABCOMM_SHORT:
case LABCOMM_INT:
case LABCOMM_LONG:
case LABCOMM_FLOAT:
case LABCOMM_DOUBLE:
case LABCOMM_STRING: {
} break;
default: {
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
"Implement %s (2) for type 0x%x...\n", __FUNCTION__, type);
} break;
}
}
}
struct labcomm_decoder *labcomm_decoder_new(
struct labcomm_reader *reader,
struct labcomm_lock *lock)
{
struct labcomm_decoder *result = malloc(sizeof(*result));
if (result) {
struct labcomm_decoder_context *context =
(struct labcomm_decoder_context *)malloc(sizeof(*context));
context->sample = 0;
result->context = context;
result->reader = reader;
result->reader->data = 0;
result->reader->data_size = 0;
result->reader->count = 0;
result->reader->pos = 0;
result->reader->error = 0;
result->lock = lock;
result->on_error = on_error_fprintf;
result->on_new_datatype = on_new_datatype;
LABCOMM_SIGNATURE_ARRAY_INIT(result->local_to_remote, int);
LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
}
return result;
}
void labcomm_internal_decoder_register(
struct labcomm_decoder *d,
struct labcomm_signature *signature,
labcomm_decoder_function type_decoder,
labcomm_handler_function handler,
void *handler_context)
{
struct labcomm_decoder_context *context = d->context;
struct labcomm_sample_entry *sample;
sample = get_sample_by_signature_address(context->sample,
signature);
if (!sample) {
sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample));
sample->next = context->sample;
context->sample = sample;
sample->index = 0;
sample->signature = signature;
}
sample->decoder = type_decoder;
sample->handler = handler;
sample->context = handler_context;
}
int labcomm_decoder_decode_one(struct labcomm_decoder *d)
{
int result;
if (d->reader->data == NULL) {
result = d->reader->action->alloc(d->reader, d->reader->context,
d, LABCOMM_VERSION);
if (result <= 0) {
goto out;
}
}
result = d->reader->action->start(d->reader, d->reader->context);
if (result > 0) {
struct labcomm_decoder_context *context = d->context;
result = labcomm_read_packed32(d->reader);
if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
/* TODO: should the labcomm_dynamic_buffer_writer be
a permanent part of labcomm_decoder? */
struct labcomm_writer writer = {
.context = NULL,
.data = NULL,
.data_size = 0,
.count = 0,
.pos = 0,
.error = 0,
.action = labcomm_dynamic_buffer_writer_action,
};
struct labcomm_signature signature;
struct labcomm_sample_entry *entry = NULL;
int index, err;
writer.action->alloc(&writer, writer.context, NULL, "");
writer.action->start(&writer, writer.context, NULL, 0, NULL, NULL);
index = labcomm_read_packed32(d->reader); //int
signature.name = labcomm_read_string(d->reader);
signature.type = result;
collect_flat_signature(d, &writer);
writer.action->end(&writer, writer.context);
err = labcomm_writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&signature.size);
if (err < 0) {
printf("Failed to get size: %s\n", strerror(-err));
goto free_signature_name;
}
err = labcomm_writer_ioctl(&writer,
LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
&signature.signature);
if (err < 0) {
printf("Failed to get pointer: %s\n", strerror(-err));
goto free_signature_name;
}
entry = get_sample_by_signature_value(context->sample, &signature);
if (! entry) {
/* Unknown datatype, bail out */
d->on_new_datatype(d, &signature);
} else if (entry->index && entry->index != index) {
d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5,
"%s(): index mismatch '%s' (id=0x%x != 0x%x)\n",
__FUNCTION__, signature.name, entry->index, index);
} else {
int local_index;
int *local_to_remote, *remote_to_local;
// TODO unnessesary, since entry->index == index in above if statement
entry->index = index;
local_index = get_local_index(entry->signature);
local_to_remote = LABCOMM_SIGNATURE_ARRAY_REF(d->local_to_remote, int,
local_index);
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->remote_to_local, int,
index);
*local_to_remote = index;
*remote_to_local = local_index;
}
free_signature_name:
free(signature.name);
writer.action->free(&writer, writer.context);
if (!entry) {
// No handler for found type, bail out (after cleanup)
result = -ENOENT;
}
} else {
struct labcomm_sample_entry *entry;
entry = get_sample_by_index(context->sample, result);
if (!entry) {
// printf("Error: %s: type not found (id=0x%x)\n",
//__FUNCTION__, result);
d->on_error(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND, 3,
"%s(): type not found (id=0x%x)\n", __FUNCTION__, result);
result = -ENOENT;
} else {
entry->decoder(d->reader, entry->handler, entry->context);
}
}
}
d->reader->action->end(d->reader, d->reader->context);
out:
return result;
}
void labcomm_decoder_run(struct labcomm_decoder *d)
{
while (labcomm_decoder_decode_one(d) > 0) {
}
}
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_decoder_context *context = (struct labcomm_decoder_context *) d->context;
struct labcomm_sample_entry *entry = context->sample;
struct labcomm_sample_entry *entry_next;
d->reader->action->free(d->reader, d->reader->context);
LABCOMM_SIGNATURE_ARRAY_FREE(d->local_to_remote, int);
LABCOMM_SIGNATURE_ARRAY_FREE(d->remote_to_local, int);
while (entry != NULL) {
entry_next = entry->next;
free(entry);
entry = entry_next;
}
free(d->context);
free(d);
}
int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
uint32_t action,
...)
{
int result;
va_list va;
va_start(va, action);
result = decoder->reader->action->ioctl(decoder->reader,
decoder->reader->context,
0, NULL, action, va);
va_end(va);
return result;
}
int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
struct labcomm_signature *signature,
uint32_t action, va_list va)
{
int result;
int local_index, *remote_index;
local_index = get_local_index(signature);
remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->local_to_remote, int,
local_index);
if (*remote_index == 0) {
result = -EAGAIN;
} else {
result = decoder->reader->action->ioctl(decoder->reader,
decoder->reader->context,
*remote_index, signature,
action, va);
}
return result;
}
#if 0
static void dump(void *p, int size, int first, int last)
{
int i, j;
printf("%d %d (%p): ", first, last, p);
for (i = first ; i < last ; i++) {
for (j = 0 ; j < size ; j++) {
printf("%2.2d", ((char*)p)[(i-first)*size + j]);
}
printf(" ");
}
printf("\n");
}
#endif
void *labcomm_signature_array_ref(int *first, int *last, void **data,
int size, int index)
{
if (*first == 0 && *last == 0) {
*first = index;
*last = index + 1;
*data = malloc(size);
if (*data) {
memset(*data, 0, size);
}
} else if (index < *first || *last <= index) {
void *old_data = *data;
int old_first = *first;
int old_last = *last;
int n;
*first = (index<old_first)?index:old_first;
*last = (old_last<=index)?index+1:old_last;
n = (*last - *first);
*data = malloc(n * size);
if (*data) {
memset(*data, 0, n * size);
memcpy(*data + (old_first - *first) * size,
old_data,
(old_last - old_first) * size);
}
// dump(old_data, size, old_first, old_last);
free(old_data);
}
if (*data) {
// dump(*data, size, *first, *last);
return *data + (index - *first) * size;
} else {
return NULL;
}
}
#ifndef _LABCOMM_H_
#define _LABCOMM_H_
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>
#include <labcomm_error.h>
/* Forward declaration */
struct labcomm_encoder;
struct labcomm_decoder;
/*
* Signature entry
*/
struct labcomm_signature {
int type;
char *name;
int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample *
int size;
unsigned char *signature;
int cached_encoded_size; // -1 if not initialized or type is variable size
};
/*
* Error handling.
*/
/* The callback prototype for error handling.
* First parameter is the error ID.
* The second paramters is the number of va_args that comes after this
* one. If none it should be 0.
* Optionaly other paramters can be supplied depending on what is needed
* for this error ID.
*/
typedef void (*labcomm_error_handler_callback)(enum labcomm_error error_id,
size_t nbr_va_args, ...);
/* Default error handler, prints message to stderr.
* Extra info about the error can be supplied as char* as VA-args. Especially user defined errors should supply a describing string. if nbr_va_args > 1 the first variable argument must be a printf format string and the possibly following arguments are passed as va_args to vprintf.
*/
void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...);
/* Register a callback for the error handler for this encoder. */
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback);
/* Register a callback for the error handler for this decoder. */
void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback);
/* Get a string describing the supplied standrad labcomm error. */
const char *labcomm_error_get_str(enum labcomm_error error_id);
typedef int (*labcomm_handle_new_datatype_callback)(
struct labcomm_decoder *decoder,
struct labcomm_signature *sig);
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
labcomm_handle_new_datatype_callback on_new_datatype);
/*
* Locking support (optional)
*/
struct labcomm_lock;
/*
* Decoder
*/
struct labcomm_reader;
struct labcomm_decoder *labcomm_decoder_new(
struct labcomm_reader *reader,
struct labcomm_lock *lock);
int labcomm_decoder_decode_one(
struct labcomm_decoder *decoder);
void labcomm_decoder_run(
struct labcomm_decoder *decoder);
void labcomm_decoder_free(
struct labcomm_decoder *decoder);
/* See labcomm_ioctl.h for predefined ioctl_action values */
int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
uint32_t ioctl_action,
...);
/*
* Encoder
*/
struct labcomm_writer;
struct labcomm_encoder *labcomm_encoder_new(
struct labcomm_writer *writer,
struct labcomm_lock *lock);
void labcomm_encoder_free(
struct labcomm_encoder *encoder);
/* See labcomm_ioctl.h for predefined ioctl_action values */
int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
uint32_t ioctl_action,
...);
#endif
/* Hack to get a link error with (hopefully) useful information if not linked
with -Tlabcomm.linkscript */
"You need to link with '-Tlabcomm.linkscript'"=0;
SECTIONS {
labcomm : {
labcomm_first_signature = ABSOLUTE(.) ;
*(labcomm)
labcomm_last_signature = ABSOLUTE(.) ;
}
}
INSERT AFTER .data;
#ifndef _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
#define _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
#include "labcomm.h"
extern const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action;
#endif
#ifndef __LABCOMM_ERROR_H__
#define __LABCOMM_ERROR_H__
enum labcomm_error {
#define LABCOMM_ERROR(name, description) name ,
#include "labcomm_error.h"
#undef LABCOMM_ERROR
};
#endif
#ifdef LABCOMM_ERROR
LABCOMM_ERROR(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE,
"Encoder has no registration for this signature")
LABCOMM_ERROR(LABCOMM_ERROR_ENC_BUF_FULL,
"The labcomm buffer is full")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE,
"Decoder: Unknown datatype")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_INDEX_MISMATCH,
"Decoder: index mismatch")
LABCOMM_ERROR(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND,
"Decoder: type not found")
LABCOMM_ERROR(LABCOMM_ERROR_UNIMPLEMENTED_FUNC,
"This function is not yet implemented")
LABCOMM_ERROR(LABCOMM_ERROR_MEMORY,
"Could not allocate memory")
LABCOMM_ERROR(LABCOMM_ERROR_USER_DEF,
"User defined error")
#endif
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm_private.h"
#include "labcomm_fd_reader.h"
#define BUFFER_SIZE 2048
struct labcomm_fd_reader {
struct labcomm_reader reader;
int fd;
int close_fd_on_free;
};
static int fd_alloc(struct labcomm_reader *r, void *context,
struct labcomm_decoder *decoder,
char *version)
{
int result = 0;
r->count = 0;
r->pos = 0;
r->data = malloc(BUFFER_SIZE);
if (! r->data) {
r->data_size = 0;
result = -ENOMEM;
} else {
r->data_size = BUFFER_SIZE;
result = r->data_size;
if (version && version[0]) {
char *tmp;
tmp = labcomm_read_string(r);
if (strcmp(tmp, version) != 0) {
result = -EINVAL;
} else {
result = r->data_size;
}
free(tmp);
}
}
return result;
}
static int fd_free(struct labcomm_reader *r, void *context)
{
struct labcomm_fd_reader *fd_context = context;
free(r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
if (fd_context->close_fd_on_free) {
close(fd_context->fd);
}
free(fd_context);
return 0;
}
static int fd_fill(struct labcomm_reader *r, void *context)
{
int result = 0;
struct labcomm_fd_reader *fd_context = context;
if (r->pos < r->count) {
result = r->count - r->pos;
} else {
int err;
r->pos = 0;
err = read(fd_context->fd, r->data, r->data_size);
if (err <= 0) {
r->count = 0;
r->error = -EPIPE;
result = -EPIPE;
} else {
r->count = err;
result = r->count - r->pos;
}
}
return result;
}
static int fd_start(struct labcomm_reader *r, void *context)
{
int available;
available = r->count - r->pos;
if (available == 0) {
available = fd_fill(r, context);
}
return available;
}
static int fd_end(struct labcomm_reader *r, void *context)
{
return 0;
}
static int fd_ioctl(struct labcomm_reader *r, void *context,
int signature_index,
struct labcomm_signature *signature,
uint32_t action, va_list args)
{
return -ENOTSUP;
}
static const struct labcomm_reader_action action = {
.alloc = fd_alloc,
.free = fd_free,
.start = fd_start,
.fill = fd_fill,
.end = fd_end,
.ioctl = fd_ioctl
};
struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free)
{
struct labcomm_fd_reader *result;
result = malloc(sizeof(*result));
if (result == NULL) {
return NULL;
} else {
result->fd = fd;
result->close_fd_on_free = close_fd_on_free;
result->reader.context = result;
result->reader.action = &action;
return &result->reader;
}
}
#ifndef _LABCOMM_FD_READER_H_
#define _LABCOMM_FD_READER_H_
#include "labcomm.h"
struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free);
#endif
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "labcomm_private.h"
#include "labcomm_fd_writer.h"
#define BUFFER_SIZE 2048
struct labcomm_fd_writer {
struct labcomm_writer writer;
int fd;
int close_fd_on_free;
};
static int fd_flush(struct labcomm_writer *w, void *context);
static int fd_alloc(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
char *version)
{
w->data = malloc(BUFFER_SIZE);
if (! w->data) {
w->error = -ENOMEM;
w->data_size = 0;
w->count = 0;
w->pos = 0;
} else {
w->data_size = BUFFER_SIZE;
w->count = BUFFER_SIZE;
w->pos = 0;
if (version && version[0]) {
labcomm_write_string(w, version);
fd_flush(w, context);
}
}
return w->error;
}
static int fd_free(struct labcomm_writer *w, void *context)
{
struct labcomm_fd_writer *fd_context = context;
free(w->data);
w->data = 0;
w->data_size = 0;
w->count = 0;
w->pos = 0;
if (fd_context->close_fd_on_free) {
close(fd_context->fd);
}
return 0;
}
static int fd_start(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
int index,
struct labcomm_signature *signature,
void *value)
{
w->pos = 0;
return w->error;
}
static int fd_flush(struct labcomm_writer *w, void *context)
{
struct labcomm_fd_writer *fd_context = context;
int start, err;
start = 0;
err = 0;
while (start < w->pos) {
err = write(fd_context->fd, &w->data[start], w->pos - start);
if (err <= 0) {
break;
}
start = start + err;
}
if (err < 0) {
w->error = -errno;
} else if (err == 0) {
w->error = -EINVAL;
}
w->pos = 0;
return w->error;
}
static int fd_ioctl(struct labcomm_writer *w, void *context,
int signature_index, struct labcomm_signature *signature,
uint32_t action, va_list args)
{
return -ENOTSUP;
}
static const struct labcomm_writer_action action = {
.alloc = fd_alloc,
.free = fd_free,
.start = fd_start,
.end = fd_flush,
.flush = fd_flush,
.ioctl = fd_ioctl
};
struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_fd_on_free)
{
struct labcomm_fd_writer *result;
result = malloc(sizeof(*result));
if (result == NULL) {
return NULL;
} else {
result->fd = fd;
result->close_fd_on_free = close_fd_on_free;
result->writer.context = result;
result->writer.action = &action;
return &result->writer;
}
}
#ifndef _LABCOMM_FD_WRITER_H_
#define _LABCOMM_FD_WRITER_H_
#include "labcomm.h"
struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_on_free);
#endif
#ifndef _LABCOMM_PRIVATE_H_
#define _LABCOMM_PRIVATE_H_
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <endian.h>
#include <stdio.h>
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm.h"
/*
* Predeclared aggregate type indices
*/
#define LABCOMM_TYPEDEF 0x01
#define LABCOMM_SAMPLE 0x02
#define LABCOMM_ARRAY 0x10
#define LABCOMM_STRUCT 0x11
/*
* Predeclared primitive type indices
*/
#define LABCOMM_BOOLEAN 0x20
#define LABCOMM_BYTE 0x21
#define LABCOMM_SHORT 0x22
#define LABCOMM_INT 0x23
#define LABCOMM_LONG 0x24
#define LABCOMM_FLOAT 0x25
#define LABCOMM_DOUBLE 0x26
#define LABCOMM_STRING 0x27
/*
* Start index for user defined types
*/
#define LABCOMM_USER 0x40
/*
*
*/
#define LABCOMM_DECLARE_SIGNATURE(name) \
struct labcomm_signature __attribute__((section("labcomm"),aligned(1))) name
/*
* Semi private lock declarations
*/
struct labcomm_lock_action {
int (*alloc)(void *context);
int (*free)(void *context);
int (*read_lock)(void *context);
int (*read_unlock)(void *context);
int (*write_lock)(void *context);
int (*write_unlock)(void *context);
};
struct labcomm_lock {
const struct labcomm_lock_action action;
};
/*
* Semi private decoder declarations
*/
typedef void (*labcomm_handler_function)(void *value, void *context);
typedef void (*labcomm_decoder_function)(
struct labcomm_reader *r,
labcomm_handler_function handler,
void *context);
struct labcomm_reader_action {
int (*alloc)(struct labcomm_reader *r, void *context,
struct labcomm_decoder *decoder, char *labcomm_version);
int (*free)(struct labcomm_reader *r, void *context);
int (*start)(struct labcomm_reader *r, void *context);
int (*end)(struct labcomm_reader *r, void *context);
int (*fill)(struct labcomm_reader *r, void *context);
int (*ioctl)(struct labcomm_reader *r, void *context,
int signature_index, struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args);
};
struct labcomm_reader {
const struct labcomm_reader_action *action;
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int error;
};
/*
* Non typesafe registration function to be called from
* generated labcomm_decoder_register_* functions.
*/
void labcomm_internal_decoder_register(
struct labcomm_decoder *d,
struct labcomm_signature *s,
labcomm_decoder_function decoder,
labcomm_handler_function handler,
void *context);
int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(struct labcomm_reader *r) { \
type result; int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (r->pos >= r->count) { \
r->action->fill(r, r->context); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
}
#else
#define LABCOMM_DECODE(name, type) \
static inline type labcomm_read_##name(struct labcomm_reader *r) { \
type result; int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (r->pos >= r->count) { \
r->action->fill(r, r->context); \
} \
((unsigned char*)(&result))[i] = r->data[r->pos]; \
r->pos++; \
} \
return result; \
}
#endif
LABCOMM_DECODE(boolean, unsigned char)
LABCOMM_DECODE(byte, unsigned char)
LABCOMM_DECODE(short, short)
LABCOMM_DECODE(int, int)
LABCOMM_DECODE(long, long long)
LABCOMM_DECODE(float, float)
LABCOMM_DECODE(double, double)
static inline unsigned int labcomm_read_packed32(struct labcomm_reader *r)
{
unsigned int result = 0;
while (1) {
unsigned char tmp;
if (r->pos >= r->count) {
r->action->fill(r, r->context);
if (r->error != 0) {
goto out;
}
}
tmp = r->data[r->pos];
r->pos++;
result = (result << 7) | (tmp & 0x7f);
if ((tmp & 0x80) == 0) {
break;
}
}
out:
return result;
}
static inline char *labcomm_read_string(struct labcomm_reader *r)
{
char *result;
int length, i;
length = labcomm_read_packed32(r);
result = malloc(length + 1);
for (i = 0 ; i < length ; i++) {
if (r->pos >= r->count) {
r->action->fill(r, r->context);
}
result[i] = r->data[r->pos];
r->pos++;
}
result[length] = 0;
return result;
}
/*
* Semi private encoder declarations
*/
typedef int (*labcomm_encoder_function)(
struct labcomm_writer *,
void *value);
struct labcomm_writer;
struct labcomm_writer_action {
int (*alloc)(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder, char *labcomm_version);
int (*free)(struct labcomm_writer *w, void *context);
int (*start)(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
int index, struct labcomm_signature *signature,
void *value);
int (*end)(struct labcomm_writer *w, void *context);
int (*flush)(struct labcomm_writer *w, void *context);
int (*ioctl)(struct labcomm_writer *w, void *context,
int signature_index, struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args);
};
struct labcomm_writer {
const struct labcomm_writer_action *action;
void *context;
unsigned char *data;
int data_size;
int count;
int pos;
int error;
};
void labcomm_internal_encoder_register(
struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
labcomm_encoder_function encode);
int labcomm_internal_encode(
struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
labcomm_encoder_function encode,
void *value);
int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
struct labcomm_signature *signature,
uint32_t ioctl_action, va_list args);
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LABCOMM_ENCODE(name, type) \
static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
int i; \
for (i = sizeof(type) - 1 ; i >= 0 ; i--) { \
if (w->pos >= w->count) { /*buffer is full*/ \
int err; \
err = w->action->flush(w, w->context); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
}
#else
#define LABCOMM_ENCODE(name, type) \
static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
int i; \
for (i = 0 ; i < sizeof(type) ; i++) { \
if (w->pos >= w->count) { \
int err; \
err = w->action->flush(w, w->context); \
if (err != 0) { return err; } \
} \
w->data[w->pos] = ((unsigned char*)(&data))[i]; \
w->pos++; \
} \
return 0; \
}
#endif
LABCOMM_ENCODE(boolean, unsigned char)
LABCOMM_ENCODE(byte, unsigned char)
LABCOMM_ENCODE(short, short)
LABCOMM_ENCODE(int, int)
LABCOMM_ENCODE(long, long long)
LABCOMM_ENCODE(float, float)
LABCOMM_ENCODE(double, double)
static inline int labcomm_write_packed32(struct labcomm_writer *w,
unsigned int data)
{
unsigned char tmp[5];
int i;
for (i = 0 ; i == 0 || data ; i++, data = (data >> 7)) {
tmp[i] = data & 0x7f;
}
for (i = i - 1 ; i >= 0 ; i--) {
if (w->pos >= w->count) {
int err;
err = w->action->flush(w, w->context);
if (err != 0) { return err; }
}
w->data[w->pos++] = tmp[i] | (i?0x80:0x00);
}
return 0;
}
static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
{
int length, i, err;
length = strlen((char*)s);
err = labcomm_write_packed32(w, length);
if (err != 0) { return err; }
for (i = 0 ; i < length ; i++) {
if (w->pos >= w->count) {
int err;
err = w->action->flush(w, w->context);
if (err != 0) { return err; }
}
w->data[w->pos] = s[i];
w->pos++;
}
return 0;
}
/*
* Macros for handling arrays indexed by signature index
*/
#define LABCOMM_SIGNATURE_ARRAY_DEF(name, kind) \
struct { \
int first; \
int last; \
kind *data; \
} name
#define LABCOMM_SIGNATURE_ARRAY_DEF_INIT(name, kind) \
LABCOMM_SIGNATURE_ARRAY_DEF(name, kind) = { 0, 0, NULL }
#define LABCOMM_SIGNATURE_ARRAY_INIT(name, kind) \
name.first = 0; name.last = 0; name.data = NULL; \
name.data = (kind *)name.data; /* typechecking no-op */
#define LABCOMM_SIGNATURE_ARRAY_FREE(name, kind) \
if (name.data) { free(name.data); } \
name.data = (kind *)NULL; /* typechecking */
#define LABCOMM_SIGNATURE_ARRAY_REF(name, kind, index) \
(name.data = (kind *)name.data, /* typechecking no-op */ \
(kind *)(labcomm_signature_array_ref(&name.first, &name.last, \
(void **)&name.data, \
sizeof(kind), index)))
void *labcomm_signature_array_ref(int *first, int *last, void **data,
int size, int index);
#endif
#include "labcomm.h"
#include "labcomm_private.h"
struct labcomm_lock *labcomm_pthread_mutex_lock_new()
{
struct labcomm_lock *result;
result = malloc(sizeof(*result));
if (result == NULL) {
goto out;
}
out:
return result;
}
#ifndef _LABCOMM_PTHREAD_MUTEX_LOCK_H_
#define _LABCOMM_PTHREAD_MUTEX_LOCK_H_
#include "labcomm.h"
struct labcomm_lock *labcomm_pthread_mutex_lock_new();
#endif
INPUT(liblabcomm.so.1)
/* Hack to get a link error with (hopefully) useful information if not linked
with -Tlabcomm.linkscript */
"You need to link with '-Tlabcomm.linkscript'"+=1;
/*INPUT(liblabcomm.a)*/
## Macros
UNAME_S=$(shell uname -s)
VERSION=2014
LIBVERSION=2014
ifeq ($(UNAME_S),Linux)
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
CFLAGS=-std=c99 -g -Wall -Werror -O3 -I.
CFLAGS_TEST=$(CFLAGS) -Itest
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION) -lrt
LD_LIBRARY_PATH_NAME=LD_LIBRARY_PATH
MAKESHARED=gcc -o $1 -shared -Wl,-soname,$2 $3 -lc -lrt
else ifeq ($(UNAME_S),Darwin)
#CC=$(CROSS_COMPILE)clang
#LD=$(CROSS_COMPILE)ld
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
CFLAGS=-g -Wall -Werror -O3 -I. -Itest \
-DLABCOMM_COMPAT=\"labcomm$(VERSION)_compat_osx.h\" \
-DLABCOMM_OS_DARWIN=1 \
-Wno-unused-function
# -Wno-tautological-compare
CFLAGS+=-std=c99
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION)
LD_LIBRARY_PATH_NAME=DYLD_LIBRARY_PATH
MAKESHARED=clang -o $1 -shared -Wl,-install_name,$2 $3 -lc
else ifneq ($(findstring CYGWIN,$(UNAME_S)),)
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CFLAGS=-std=c99 -g -Wall -Werror -O3 -I.
LDFLAGS=-L..
LDLIBS=-llabcomm$(LIBVERSION) -lrt
ALL_DEPS:=$(filter-out %.so.1, $(ALL_DEPS)) # No -fPIC supported in windows?
else
$(error Unknown system $(UNAME_S))
endif
CFLAGS_TEST=$(CFLAGS) -Itest -DVERSION=$(VERSION)
ifeq ($(CROSS_COMPILE),i586-wrs-vxworks-)
ALL_DEPS:=$(filter-out %.so.1, $(ALL_DEPS)) # PIC is only supported for RTPs
CFLAGS:=$(CFLAGS) -DLABCOMM_COMPAT=\"labcomm_compat_vxworks.h\"
endif
#include "CUnit/Basic.h"
#include "CUnit/Console.h"
#include <stdbool.h>
#include <stdlib.h>
#include <labcomm.h>
#include <labcomm_mem_writer.h>
#include <labcomm_mem_reader.h>
#include "test/testdata/gen/test_sample.h"
#define TEST_BUFFER_SIZE (50)
void test_error_handler(enum labcomm_error error_id, size_t nbr_va_args, ...);
int init_suit_labcomm()
{
return 0;
}
int clean_suit_labcomm()
{
return 0;
}
void setup_connected_encoder_decoder(struct labcomm_encoder **enc,
labcomm_mem_writer_context_t *enc_ctx,
struct labcomm_decoder **dec,
labcomm_mem_reader_context_t *dec_ctx)
{
enc_ctx->write_pos = 0;
enc_ctx->buf = malloc(TEST_BUFFER_SIZE);
enc_ctx->length = TEST_BUFFER_SIZE;
*enc = labcomm_encoder_new(labcomm_mem_writer, enc_ctx);
dec_ctx->size = 0;
dec_ctx->enc_data = enc_ctx->buf;
*dec = labcomm_decoder_new(labcomm_mem_reader, dec_ctx);
labcomm_register_error_handler_decoder(*dec, test_error_handler);
labcomm_register_error_handler_encoder(*enc, test_error_handler);
}
static bool in_error = false;
static enum labcomm_error in_error_id = LABCOMM_ERROR_ENUM_BEGIN_GUARD;
void test_error_handler(enum labcomm_error error_id, size_t nbr_va_args, ...)
{
in_error = true;
in_error_id = error_id;
}
static bool got_sample = false;
void test_decoder_handle_test_sample_test_var(test_sample_test_var *v, void *ctx)
{
got_sample = true;
}
void test_decoder_decode_sig()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_register_test_sample_test_var(decoder,
test_decoder_handle_test_sample_test_var, NULL);
labcomm_decoder_decode_one(decoder);
CU_ASSERT_FALSE(in_error);
enc_ctx.write_pos = 0;
test_sample_test_var var = 1;
labcomm_encode_test_sample_test_var(encoder, &var);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_decode_one(decoder);
CU_ASSERT_FALSE(in_error);
CU_ASSERT_FALSE(got_sample);
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
in_error = false;
in_error_id = LABCOMM_ERROR_ENUM_BEGIN_GUARD;
got_sample = false;
}
static bool got_new_datatype = false;
static labcomm_signature_t new_sig;
int test_new_datatype(struct labcomm_decoder *decoder,
labcomm_signature_t *sig)
{
got_new_datatype = true;
memcpy(&new_sig, sig, sizeof(labcomm_signature_t));
return 0;
}
void test_decode_unreg_signature_handle()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_register_new_datatype_handler(decoder, test_new_datatype);
labcomm_decoder_decode_one(decoder);
CU_ASSERT_TRUE(got_new_datatype);
CU_ASSERT_EQUAL(
memcmp(new_sig.signature, dec_ctx.enc_data, dec_ctx.size), 0);
got_new_datatype = false;
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
}
void test_decode_unreg_signature_error()
{
labcomm_mem_writer_context_t enc_ctx;
struct labcomm_encoder *encoder;
labcomm_mem_reader_context_t dec_ctx;
struct labcomm_decoder *decoder;
setup_connected_encoder_decoder(&encoder, &enc_ctx, &decoder, &dec_ctx);
labcomm_encoder_register_test_sample_test_var(encoder);
dec_ctx.size = enc_ctx.write_pos;
labcomm_decoder_decode_one(decoder);
CU_ASSERT_TRUE(in_error);
CU_ASSERT_EQUAL(in_error_id, LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE);
got_new_datatype = false;
labcomm_decoder_free(decoder);
labcomm_encoder_free(encoder);
free(enc_ctx.buf);
}
int main()
{
CU_pSuite suite_decoder = NULL;
// Initialize CUnit test registry.
if (CUE_SUCCESS != CU_initialize_registry()) {
return CU_get_error();
}
// Add our test suites.
suite_decoder = CU_add_suite("transport_enc_dec",
init_suit_labcomm, clean_suit_labcomm);
if (suite_decoder == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (
(CU_add_test(suite_decoder, "test_decoder_decode_sig",
test_decoder_decode_sig) == NULL)
||
(CU_add_test(suite_decoder, "test_decode_unreg_signature_handle",
test_decode_unreg_signature_handle) == NULL)
||
(CU_add_test(suite_decoder, "test_decode_unreg_signature_error",
test_decode_unreg_signature_error) == NULL)
) {
CU_cleanup_registry();
return CU_get_error();
}
// Set verbosity.
CU_basic_set_mode(CU_BRM_VERBOSE);
/*CU_console_run_tests();*/
// Run all test suites.
CU_basic_run_tests();
// Clean up.
CU_cleanup_registry();
return CU_get_error();
}
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "labcomm_private.h"
#include "labcomm_private.h"
#include "test/gen/generated_encoding.h"
#define IOCTL_WRITER_ASSERT_BYTES 4096
#define IOCTL_WRITER_RESET 4097
static unsigned char buffer[128];
struct labcomm_writer *writer;
static int buf_writer_alloc(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
char *labcomm_version)
{
writer = w; /* Hack */
w->data_size = sizeof(buffer);
w->count = w->data_size;
w->data = buffer;
w->pos = 0;
return 0;
}
static int buf_writer_free(struct labcomm_writer *w, void *context)
{
return 0;
}
static int buf_writer_start(struct labcomm_writer *w, void *context,
struct labcomm_encoder *encoder,
int index,
struct labcomm_signature *signature,
void *value)
{
return 0;
}
static int buf_writer_end(struct labcomm_writer *w, void *context)
{
return 0;
}
static int buf_writer_flush(struct labcomm_writer *w, void *context)
{
fprintf(stderr, "Should not come here %s:%d\n", __FILE__, __LINE__);
exit(1);
return 0;
}
static int buf_writer_ioctl(
struct labcomm_writer *w, void *context,
int signature_index, struct labcomm_signature *signature,
uint32_t 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;
}
const struct labcomm_writer_action writer_action = {
.alloc = buf_writer_alloc,
.free = buf_writer_free,
.start = buf_writer_start,
.end = buf_writer_end,
.flush = buf_writer_flush,
.ioctl = buf_writer_ioctl
};
static struct labcomm_writer buffer_writer = {
.context = NULL,
.data = buffer,
.data_size = sizeof(buffer),
.count = sizeof(buffer),
.pos = 0,
.error = 0,
.action = &writer_action,
};
void dump_encoder(struct labcomm_encoder *encoder)
{
int i;
for (i = 0 ; i < writer->pos ; i++) {
printf("%2.2x ", writer->data[i]);
}
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;
generated_encoding_B B = 1;
struct labcomm_encoder *encoder = labcomm_encoder_new(&buffer_writer,
NULL);
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_V(encoder);
labcomm_encoder_register_generated_encoding_V(encoder);
EXPECT({ 0x02, -1, 0x01, 'V', 0x11, 0x00 });
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encoder_register_generated_encoding_B(encoder);
labcomm_encoder_register_generated_encoding_B(encoder);
EXPECT({0x02, -1, 0x01, 'B', 0x21});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_V(encoder, &V);
EXPECT({-1});
labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
labcomm_encode_generated_encoding_B(encoder, &B);
EXPECT({-1, 1});
return 0;
}
sample int test_var;
#!/usr/bin/python
import os
import sys
import difflib
import re
class File:
def __init__(self, path, match, replacement):
def replace(s):
r = re.sub('[ \t]+', ' ', s).replace(match, replacement)
r = r.strip() + '\n'
return r
self.name = path.replace(match, replacement)
self.path = path
with open(path) as f:
self.lines = map(replace, f.readlines())
def __cmp__(self, other):
if other == None:
return cmp(self.name, other)
return cmp(self.name, other.name)
def readfiles(root, match, replacement):
result = []
for n in os.listdir(root):
path = os.path.join(root, n)
if os.path.islink(path):
pass
elif os.path.isdir(path):
for f in filter(None, readfiles(path, match, replacement)):
result.append(f)
else:
result.append(File(path, match, replacement))
for f in sorted(result):
yield f
yield None
if __name__ == '__main__':
A = readfiles(*sys.argv[1:4])
B = readfiles(*sys.argv[4:7])
a = A.next()
b = B.next()
while a != None or b != None:
if b == None or a.name < b.name:
print "Only in %s:" %sys.argv[1], a.path
a = A.next()
elif a == None or a.name > b.name:
print "Only in %s:" %sys.argv[4], b.path
b = B.next()
else:
equal = True
for l in difflib.unified_diff(a.lines, b.lines, a.path, b.path):
print l,
equal = False
if equal:
print "Identical", a.path, b.path
a = A.next()
b = B.next()
labcomm2014.dll