Commit 321cc67d authored by Oscar Olsson's avatar Oscar Olsson
Browse files

Added changes from firefly

parent 3e252daa
......@@ -4,7 +4,7 @@
clean - removes all generated files and class files
Targets for working from Eclipse:
gen - generates java files
genClean - removes all generated files and their class files
cleanGen - removes all generated files and their class files
-->
<project name="LabComm" default="build" basedir=".">
......@@ -77,7 +77,9 @@ classpath="tools/jastadd2.jar"/>
<!-- delete all .class files recursively -->
<delete>
<fileset dir="." includes="**/*.class"/>
<fileset dir="." includes="labComm.jar"/>
</delete>
</target>
......
CC = gcc
CFLAGS = -g -I .
## Macros
liblabcomm.a : labcomm.o labcomm_fd_reader_writer.o experimental/labcomm_udp_reader_writer.o \
experimental/udp_hack.o experimental/ethaddr.o \
experimental/labcomm_thr_reader_writer.o \
experimental/ThrottleDrv/ethernet_drv.o experimental/ThrottleDrv/throttle_drv.o
# Use LLVM clang if it's found.
CC = $(shell hash clang 2>/dev/null && echo clang || echo gcc)
CFLAGS = -g -Wall -I .
LDFLAGS = -L .
LDLIBS_TEST = -lcunit -llabcomm
OBJS= labcomm.o labcomm_fd_reader_writer.o labcomm_mem_reader.o labcomm_mem_writer.o
LABCOMMC_PATH=../../compiler
LABCOMMC_JAR=$(LABCOMMC_PATH)/labComm.jar
TEST_DIR=test
TESTDATA_DIR=$(TEST_DIR)/testdata
TEST_GEN_DIR=$(TESTDATA_DIR)/gen
CREATED_DIRS=$(TEST_DIR) $(TESTDATA_DIR) $(TEST_GEN_DIR)
# Disable experimental objects by invoking make like `make -e LABCOMM_NO_EXPERIMENTAL=true`
ifneq ($(LABCOMM_NO_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 test/test_labcomm_errors
liblabcomm.a: $(OBJS)
ar -r liblabcomm.a $^
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
labcomm_mem_reader.o: labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h
labcomm_mem_writer.o: labcomm_mem_writer.c labcomm_mem_writer.h cppmacros.h
ethaddr.o: ethaddr.c
%o: %c %h
$(CREATED_DIRS):
mkdir -p $@
run-test: $(TEST_DIR)/test_labcomm_errors |$(TEST_DIR)
test/test_labcomm_errors
$(TEST_DIR)/test_labcomm_errors: $(TEST_DIR)/test_labcomm_errors.o liblabcomm.a |$(TEST_DIR)
$(CC) $(CFLAGS) $(LDFLAGS) -llabcomm -o $@ $^
$(TEST_DIR)/test_labcomm_errors.o: $(TEST_DIR)/test_labcomm_errors.c $(TEST_DIR)/test_labcomm_errors.h |$(TEST_DIR)
cd test; $(CC) $(CFLAGS) -I .. -c $(patsubst $(TEST_DIR)/%, %, $^)
$(TEST_DIR)/test_labcomm.o: $(TEST_DIR)/test_labcomm.c $(TEST_GEN_DIR)/test_sample.h |$(TEST_DIR)
$(CC) -c $(CFLAGS) -o $@ $<
$(TEST_DIR)/test_labcomm: $(TEST_DIR)/test_labcomm.o $(TEST_GEN_DIR)/test_sample.o liblabcomm.a
$(CC) $(CFLAGS) $(LDFLAGS) $(filter-out %.a,$^) $(LDLIBS) $(LDLIBS_TEST) -o $@
$(TEST_GEN_DIR)/%.c $(TEST_GEN_DIR)/%.h: $(TESTDATA_DIR)/%.lc $(LABCOMMC_JAR) |$(TEST_GEN_DIR)
java -jar $(LABCOMMC_JAR) --c=$(patsubst %.h,%.c,$@) --h=$(patsubst %.c,%.h,$@) $<
$(LABCOMMC_JAR):
@echo "======Building LabComm compiler======"
cd $(LABCOMMC_PATH); ant jar
@echo "======End building LabComm compiler======"
%.o: %.c %.h
clean:
rm *.o experimental/*.o experimental/ThrottleDrv/*.o
$(RM) *.o
$(RM) experimental/*.o experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) $(TEST_DIR)/test_labcomm
distclean: clean
rm liblabcomm.a
$(RM) liblabcomm.a
// C Preprocessor macros.
#ifndef CPP_MACROS_H
#define CPP_MACROS_H
#define X_EMPTY(mac) var ## 1
#define EMPTY(mac) X_EMPTY(mac) // Returns 1 if macro mac is empty.
#endif
#define PC_MODE
#ifdef PC_MODE
#include <stdio.h>
#define DISPLAY_ERR(s) perror(s);
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#else
#define DISPLAY_ERR(s) ;
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
......@@ -14,6 +13,10 @@
#include "ethernet_drv.h"
#include "display.h"
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
/** LOCAL FUNCTIONS **/
......
#include <stdio.h>
#include "ethaddr.h"
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#if ETH_ALEN != 6
#warning "Assumption that ETH_ALEN == 6 appears false. Here be dragons."
#endif
......
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#define BUFLEN 512
#define NPACK 10
#define PORT 9930
......
#include <errno.h>
#include <string.h>
#include <stdio.h>
#ifndef __VXWORKS__
#include <strings.h>
#ifdef ARM_CORTEXM3_CODESOURCERY
#include <string.h>
#else
#include <strings.h>
#endif
#endif
#include <stdlib.h>
#ifdef __VXWORKS__
#if (CPU == PPC603)
#undef _LITTLE_ENDIAN
#ifndef ARM_CORTEXM3_CODESOURCERY
#include <stdlib.h>
#endif
#if (CPU == PENTIUM4)
#undef _BIG_ENDIAN
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#ifdef __VXWORKS__
#if (CPU == PPC603)
#undef _LITTLE_ENDIAN
#endif
#if (CPU == PENTIUM4)
#undef _BIG_ENDIAN
#endif
#endif
#include "labcomm.h"
#include "labcomm_private.h"
......@@ -35,6 +49,83 @@ typedef struct labcomm_decoder_context {
labcomm_sample_entry_t *sample;
} labcomm_decoder_context_t;
void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback)
{
encoder->on_error = callback;
encoder->writer.on_error = callback;
}
void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback)
{
decoder->on_error = callback;
decoder->reader.on_error = callback;
}
/* Error strings. _must_ be the same order as in enum labcomm_error */
const char *labcomm_error_strings[] = {
"Enum begin guard. DO NO use this as an error.",
"Encoder has no registration for this signature.",
"Encoder is missing do_register",
"Encoder is missing do_encode",
"The labcomm buffer is full and it.",
"Decoder is missing do_register",
"Decoder is missing do_decode_one",
"Decoder: Unknown datatype",
"Decoder: index mismatch",
"Decoder: type not found",
"This function is not yet implemented.",
"User defined error.",
"Could not allocate memory.",
"Enum end guard. DO NO use this as an error."
};
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 (error_id >= LABCOMM_ERROR_ENUM_BEGIN_GUARD && error_id <= LABCOMM_ERROR_ENUM_END_GUARD) {
error_str = labcomm_error_strings[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(labcomm_decoder_t *d, labcomm_signature_t *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 labcomm_sample_entry_t *get_sample_by_signature_address(
labcomm_sample_entry_t *head,
labcomm_signature_t *signature)
......@@ -135,7 +226,7 @@ static void do_encode(
if (sample && sample->encode) {
sample->encode(encoder, value);
} else {
printf("Encoder has no registration for %s\n", signature->name);
encoder->on_error(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE, 2, "No registration for %s.\n", signature->name);
}
}
......@@ -148,7 +239,7 @@ labcomm_encoder_t *labcomm_encoder_new(
labcomm_encoder_context_t *context;
context = malloc(sizeof(labcomm_encoder_context_t));
context->sample = 0;
context->sample = NULL;
context->index = LABCOMM_USER;
result->context = context;
result->writer.context = writer_context;
......@@ -158,8 +249,10 @@ labcomm_encoder_t *labcomm_encoder_new(
result->writer.pos = 0;
result->writer.write = writer;
result->writer.write(&result->writer, labcomm_writer_alloc);
result->writer.on_error = on_error_fprintf;
result->do_register = do_encoder_register;
result->do_encode = do_encode;
result->on_error = on_error_fprintf;
}
return result;
}
......@@ -169,10 +262,11 @@ void labcomm_internal_encoder_register(
labcomm_signature_t *signature,
labcomm_encode_typecast_t encode)
{
if (e && e->do_register) {
// Will segfault if e == NULL.
if (e->do_register) {
e->do_register(e, signature, encode);
} else {
printf("Encoder is missing do_register\n");
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_REG, 0);
}
}
......@@ -181,10 +275,11 @@ void labcomm_internal_encode(
labcomm_signature_t *signature,
void *value)
{
if (e && e->do_encode) {
// Will segfault if e == NULL
if (e->do_encode) {
e->do_encode(e, signature, value);
} else {
printf("Encoder is missing do_encode\n");
e->on_error(LABCOMM_ERROR_ENC_MISSING_DO_ENCODE, 0);
}
}
......@@ -196,8 +291,18 @@ void labcomm_internal_encoder_user_action(labcomm_encoder_t *e,
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;
}
free(e->context);
free(e);
}
......@@ -251,7 +356,7 @@ static void collect_flat_signature(
{
int type = labcomm_decode_int(decoder);
if (type >= LABCOMM_USER) {
printf("Implement %s ...\n", __FUNCTION__);
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 2, "Implement %s\n", __FUNCTION__);
} else {
labcomm_encode_int(signature_writer, type);
switch (type) {
......@@ -287,7 +392,7 @@ static void collect_flat_signature(
case LABCOMM_STRING: {
} break;
default: {
printf("Implement %s ...\n", __FUNCTION__);
decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 2, "Implement %s\n", __FUNCTION__);
} break;
}
}
......@@ -343,12 +448,12 @@ static int do_decode_one(labcomm_decoder_t *d)
entry = get_sample_by_signature_value(context->sample, &signature);
if (! entry) {
// Unknown datatype, bail out
fprintf(stderr, "%s: unknown datatype '%s' (id=0x%x)\n",
__FUNCTION__, signature.name, index);
/*d->on_error(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE, 4, "%s(): unknown datatype '%s' (id=0x%x)\n", __FUNCTION__, signature.name, index);*/
d->on_new_datatype(d, &signature);
} else if (entry->index && entry->index != index) {
fprintf(stderr, "%s: index mismatch '%s' (id=0x%x != 0x%x)\n",
__FUNCTION__, signature.name, 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 {
// TODO unnessesary, since entry->index == index in above if statement
entry->index = index;
}
free(signature.name);
......@@ -363,8 +468,9 @@ static int do_decode_one(labcomm_decoder_t *d)
entry = get_sample_by_index(context->sample, result);
if (!entry) {
fprintf(stderr, "%s: type not found (id=0x%x)\n",
__FUNCTION__, result);
// 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, entry->handler, entry->context);
......@@ -393,8 +499,11 @@ labcomm_decoder_t *labcomm_decoder_new(
result->reader.pos = 0;
result->reader.read = reader;
result->reader.read(&result->reader, labcomm_reader_alloc);
result->reader.on_error = on_error_fprintf;
result->do_register = do_decoder_register;
result->do_decode_one = do_decode_one;
result->on_error = on_error_fprintf;
result->on_new_datatype = on_new_datatype;
}
return result;
}
......@@ -406,23 +515,25 @@ void labcomm_internal_decoder_register(
labcomm_handler_typecast_t handler,
void *handler_context)
{
if (d && d->do_register) {
// Will segfault if d == NULL
if (d->do_register) {
d->do_register(d, signature, type_decoder, handler, handler_context);
} else {
printf("Decoder is missing do_register\n");
d->on_error(LABCOMM_ERROR_DEC_MISSING_DO_REG, 0);
}
}
int labcomm_decoder_decode_one(labcomm_decoder_t *d)
{
int result = -1;
if (d && d->do_decode_one)
// Will segfault if decoder == NULL.
if (d->do_decode_one)
{
result = d->do_decode_one(d);
}
else
{
printf("Decoder is missing do_decode_one\n");
d->on_error(LABCOMM_ERROR_DEC_MISSING_DO_DECODE_ONE, 0);
}
return result;
}
......@@ -436,5 +547,16 @@ void labcomm_decoder_run(labcomm_decoder_t *d)
void labcomm_decoder_free(labcomm_decoder_t* d)
{
d->reader.read(&d->reader, labcomm_reader_free);
labcomm_decoder_context_t *context = (labcomm_decoder_context_t *) d->context;
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;
}
free(d->context);
free(d);
}
#ifndef _LABCOMM_H_
#define _LABCOMM_H_
#include <endian.h>
#include <stdio.h>
#ifdef ARM_CORTEXM3_CODESOURCERY
#include <machine/endian.h>
#else
#include <endian.h>
#endif
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/* Forward declaration */
struct labcomm_encoder;
struct labcomm_decoder;
/*
* Signature entry
......@@ -17,11 +31,62 @@ typedef struct {
unsigned char *signature;
} labcomm_signature_t;
/*
* Error handling.
*/
/* Error IDs */
enum labcomm_error {
LABCOMM_ERROR_ENUM_BEGIN_GUARD, // _must_ be the first enum element. labcomm_error_get_str() depends on this.
LABCOMM_ERROR_ENC_NO_REG_SIGNATURE,
LABCOMM_ERROR_ENC_MISSING_DO_REG,
LABCOMM_ERROR_ENC_MISSING_DO_ENCODE,
LABCOMM_ERROR_ENC_BUF_FULL,
LABCOMM_ERROR_DEC_MISSING_DO_REG,
LABCOMM_ERROR_DEC_MISSING_DO_DECODE_ONE,
LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE,
LABCOMM_ERROR_DEC_INDEX_MISMATCH,
LABCOMM_ERROR_DEC_TYPE_NOT_FOUND,
LABCOMM_ERROR_UNIMPLEMENTED_FUNC,
LABCOMM_ERROR_MEMORY,
LABCOMM_ERROR_USER_DEF,
LABCOMM_ERROR_ENUM_END_GUARD // _must_ be the last enum element. labcomm_error_get_str() depends on this.
};
/* Error strings. _must_ be the same order as in enum labcomm_error */
extern const char *labcomm_error_strings[];
/* 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 noneit 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,
labcomm_signature_t *sig);
void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
labcomm_handle_new_datatype_callback on_new_datatype);
/*
* Decoder
*/
struct labcomm_decoder;
typedef enum {
labcomm_reader_alloc,
......@@ -38,6 +103,7 @@ typedef struct labcomm_reader {
int count;
int pos;
int (*read)(struct labcomm_reader *, labcomm_reader_action_t);
labcomm_error_handler_callback on_error;
} labcomm_reader_t;
struct labcomm_decoder *labcomm_decoder_new(
......@@ -53,7 +119,6 @@ void labcomm_decoder_free(
/*
* Encoder
*/
struct labcomm_encoder;
typedef enum {
labcomm_writer_alloc,
......@@ -71,9 +136,9 @@ typedef struct labcomm_writer {
int count;
int pos;
int (*write)(struct labcomm_writer *, labcomm_writer_action_t);
labcomm_error_handler_callback on_error;
} labcomm_writer_t;
struct labcomm_encoder;
struct labcomm_encoder *labcomm_encoder_new(
int (*writer)(labcomm_writer_t *, labcomm_writer_action_t),
void *writer_context);
......
#include "labcomm_mem_reader.h"
#include <errno.h>
/* This implementation assumes labcomm will call end exactly once after each start
* It is not allowed to save data in mcontext->enc_data,
* this pointer will be set to NULL after decoding.
*/
/* NOTE!!!!
* start will be run first, once a signature or a data section is decoded
* end will be run and then start again. If end of encoded data is reached this
* must be handled in start.
*/
// TODO make labcomm use result!
int labcomm_mem_reader(labcomm_reader_t *r, labcomm_reader_action_t action)
{
int result = -EINVAL;
labcomm_mem_reader_context_t *mcontext = (labcomm_mem_reader_context_t *) r->context;
switch (action) {
case labcomm_reader_alloc: {
r->data = NULL;
r->data_size = 0;
r->pos = 0;
r->count = 0;
} break;
case labcomm_reader_start: {
if (r->data == NULL && mcontext->enc_data != NULL) {
r->data = (unsigned char *) malloc(mcontext->size);
if(r->data != NULL) {
memcpy(r->data, mcontext->enc_data, mcontext->size);
r->data_size = mcontext->size;