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
Select Git revision

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Select Git revision
Show changes
Commits on Source (40)
Showing
with 843 additions and 125 deletions
......@@ -210,6 +210,21 @@ aspect Java_CodeGen {
public void Program.J_gen(PrintStream ps, String pack, int version) throws IOException {
Java_env env;
/*
// Registration class
env = new Java_env(version, ps);
if (pack != null && pack.length() > 0) {
env.println("package " + pack + ";");
}
env.println("public class LabCommRegister {");
env.println();
env.indent();
Java_emitTypeRegister(env);
env.unindent();
env.println();
env.println("}");
// env.close();
*/
env = new Java_env(version, ps);
for (int i = 0; i < getNumDecl(); i++) {
Decl d = getDecl(i);
......@@ -225,6 +240,21 @@ aspect Java_CodeGen {
public void Program.J_gen(String dir, String pack, int version) throws IOException {
Java_env env;
/*
// Registration class
env = new Java_env(version, new File(dir, "LabCommRegister.java"));
if (pack != null && pack.length() > 0) {
env.println("package " + pack + ";");
}
env.println("public class LabCommRegister {");
env.println();
env.indent();
Java_emitTypeRegister(env);
env.unindent();
env.println();
env.println("}");
env.close();
*/
for (int i = 0; i < getNumDecl(); i++) {
Decl d = getDecl(i);
try {
......@@ -257,7 +287,6 @@ aspect Java_CodeGen {
}
}
}
}
aspect Java_Class {
......@@ -280,40 +309,21 @@ aspect Java_Class {
}
public void Decl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
// XXX TODO will generate unnecessary recursion for types. fix this per commented out code
// XXX but ensure that types with references actually register themselves.. (i.e., add "nested" argument)
//public abstract void Decl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode);
//public void TypeDecl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
// // do nothing for type decls; sampledecl iterates over all dependencies and outputs
// // all type decls
//}
//public void SampleDecl.Java_emitUserTypeDeps(Java_env env, String via, boolean outputCode) {
if(env.versionHasMetaData() && hasDependencies() || isReferenced() ) {
if(env.versionHasMetaData() && isSampleDecl() && outputCode) {
env.println("if(sendMetaData){");
env.indent();
}
if( hasDependencies() ) {
Iterator<Decl> it = type_dependencies().iterator();
while(it.hasNext()) {
Decl t = it.next();
t.Java_emitUserTypeDeps(env, t.getName(), outputCode);
if( outputCode){// && t.getType().isUserType() ) {
env.println(t.getName()+".register(e);");
if( outputCode){// && t.getType().isUserType() )
//env.println(t.getName()+".register(e);");
} else { // Just output a comment
String refpath = (via == null) ? "directly" : "indirectly via "+via;
//env.println(" //Depends ("+refpath+") on "+t.getName() + " (" + t +") " );
//env.println(" //Depends ("+refpath+") on "+t.getName() );
env.println(" //Depends ("+refpath+") on "+t.getName()+" -- "+t.getType() );
}
env.println(" //Depends ("+refpath+") on "+t.getName() );
}
if(env.versionHasMetaData() && isSampleDecl() && outputCode) {
env.unindent();
env.println("}");
}
}
}
public void Decl.Java_emitUserTypeRefs(Java_env env, String via, boolean outputCode) {
if( isReferenced() ) {
Iterator<Decl> it = type_references().iterator();
......@@ -331,24 +341,12 @@ aspect Java_Class {
}
}
public void Decl.Java_emitRegisterEncoder(Java_env env) {
env.println("public static void register(Encoder e) throws IOException {");
env.indent();
env.println("register(e, true);");
env.unindent();
env.println("}");
env.println();
env.println("public static void register(Encoder e, boolean sendMetaData) throws IOException {");
env.indent();
Java_emitUserTypeDeps(env, null, true);
if(env.versionHasMetaData()) {
Java_emitUserTypeDeps(env, null, false); //XXX false -> generate no code
env.println("e.register(Dispatcher.singleton());");
} else {
env.println("e.register(Dispatcher.singleton());");
}
env.unindent();
env.println("}");
env.println();
......@@ -387,16 +385,14 @@ aspect Java_Class {
Java_emitDecoder(env);
}
//if(hasDependencies() || isReferenced()) {
//if( getType().isUserType() && isReferenced()) {
if( isReferenced()) {
Java_emitRegisterEncoder(env);
Java_emitDispatcher(env, false);
}
if(hasDependencies() || isReferenced()) {
// XXX Java_emitRegisterEncoder(env);
// XXX Java_emitDispatcher(env, false);
Java_emitSignature(env);
}
env.println("}");
env.unindent();
env.println("}");
env.println();
}
......@@ -444,7 +440,6 @@ aspect Java_Class {
env.println("}");
env.println();
Java_emitRegisterEncoder(env);
Java_emitDispatcher(env, true);
Java_emitEncoder(env);
......@@ -455,7 +450,6 @@ aspect Java_Class {
env.println("}");
env.println();
}
//public void TypeDecl.Java_emitSignature(Java_env env) {
// Signature signature = getSignature();
// signature.Java_emitSignature(env, true);
......@@ -603,7 +597,6 @@ aspect Java_Class {
}
public void TypeDecl.Java_emitEncoder(Java_env env) {
env.print("public static void encode(Encoder e");
if (!isVoid()) {
......
......@@ -30,7 +30,6 @@ aspect Type_References {
for parentDecl();
*/
// The references from other type declarations to a Decl.
coll Set<Decl> Decl.type_references() [new HashSet<Decl>()] with add;
......
Discussion 141023
TODO:
*** new labcomm packet types:
TYPE_DEF = 0x03 // for (possibly) hierarchical type definitions
TYPE_BINDING = 0x04 // binding a sample def to a type def
*** rewrite malloc of received samples to utilize the packet length field
to allocate a single object before parsing the sample byte stream
*** labcomm language: add type for type_ref to facilitate references to
labcomm sample_defs (and type_defs) in (primarily) pragmas
E.g., sample ... foo;
sample ... bar;
sample struct {
...
type[2] some_refs;
} some_pragma;
my_lc_some_pragma sp;
sp.some_refs = {&labcomm_signature_my_lc_foo,
&labcomm_signature_my_lc_bar};
labcomm_encode_my_lc_some_pragma(enc, &sp);
This is to avoid exposing local_to_remote and remote_to_local
*** refactor {encoder,decoder}registry to separate the actual encoder
from the registry
- currently, the assignment of local indices is done in the "constructor"
which means that the registries will be very thin
*** labcomm_pragma_builder(struct labcomm_encoder *enc);
- looks like an encoder to enable reuse of the generated encode functions
- allocates memory in the enclosing encoder, enc.
- deallocates memory when packet is sent
*** Pragma handler
- is a decoder, to which the user registers handlers for pragma samples
- has/gets a byte_array_reader in the context
- the "surrounding" decoder will deallocate the pragma packet when the
pragma handler returns
______________________________________________________________
______________preliminary sketch of pragma____________________
A pragma "packet" is a sequence of fields, where each field is
a labcomm sample (in order to keep labcomm in-band self-describing).
A pragma packet has a type, which is a globally unique string
(e.g., java package-like name, URI, or UUID)
One predefined pragma sample type is labcomm_type_ref, which is used to refer
to labcomm sample types in a way that is unique on a given encoder/channel.
Sending:
/* create a pragma packet for pragma type type
allocated in e->memory */
// (or, if that is visible to user code, should
// the parameter be a struct labcomm_memory*?)
struct labcom_pragma_packet * = labcomm_pragma_new(struct labcomm_encoder e*,
char *type);
/* add type reference field*/
void labcomm_pragma_add_ref(struct labcomm_signature sig);
// the semantics if more than one type reference field is undefined
// (as far as labcomm is concerned).
// One possible (pragma-type defined) semantic is that the latest type
// reference applies to the fields following it.
A pragma packet is (under the hood) a struct labcomm_encoder, so that we
can reuse the sample_type_encode() function for adding pragma fields.
// an example session
struct labcom_pragma_packet pp = labcomm_pragma_new(enc, some_type));
labcomm_pragma_add_ref(some_sig);
some_pragma_type_encode(pp, some_pragma_instance);
another_pragma_type_encode(pp, another_pragma_instance);
labcomm_pragma_send(pp, enc);
#define labcomm_pragma_add_field(some_pragma_sample_type, value) \
labcomm_encode_#some_pragma_sample_type, value)
int labcomm_encode_test_twoLines( struct labcomm_encoder *e,
test_twoLines *v)
{
return labcomm_internal_encode(e,
&labcomm_signature_test_twoLines,
(labcomm_enc oder_function) encode_test_twoLines,
v);
}
receiving:
alt 1. standard handlers, parameter pragma_type to handle function
-- this means adding a parameter to all handlers
(where null means not pragma)
void handle_some_pragma(some_pragma *v, void *context, char * pragma_type);
alt 2. standard handlers, but separate register_pragma_handler function
use the handler context to store and communicate pragma-specific data.
-- this means that the decoder interface needs to be extended,
and that the handler context for pragmas need to be specified
(by labcomm)
alt 3 have a single handler for pragma packets as the interface upwards
from the labcomm lib. That handler is then responsible for managing
and multiplexing pragma types based on the type field in the pragma
packet.
The labcomm libraries can provide a default implementation of a
pragma_handler, to facilitate the common cases and reduce the
amount of boilerplate code.
struct pragma_packet {
char *pragma_type;
char *packed_data;
}
void handle_pragma(struct pragma_packet *p, void *context);
......@@ -6,6 +6,15 @@ typedef struct {
sample TwoInts theTwoInts;
sample TwoInts anotherTwoInts;
typedef int AnInt;
sample AnInt theInt;
sample struct {
TwoInts ti1;
TwoInts ti2;
} twoTwoInts;
sample struct {
int x;
string s;
......
......@@ -5,7 +5,7 @@ import java.io.InputStream;
import se.lth.control.labcomm.DecoderChannel;
public class Decoder
implements twoLines.Handler
implements twoLines.Handler, theint.Handler, Comment.Handler//, Typedef.Handler
{
......@@ -16,6 +16,9 @@ public class Decoder
{
decoder = new DecoderChannel(in);
twoLines.register(decoder, this);
theint.register(decoder,this);
Comment.register(decoder, this);
//Typedef.register(decoder, this);
try {
System.out.println("Running decoder.");
......@@ -39,6 +42,20 @@ public class Decoder
System.out.println(" Line l2: "+genLine(d.l2));
}
public void handle_theint(int d) throws java.io.IOException {
System.out.println("Got theint: "+d);
}
public void handle_Comment(Comment c) throws java.io.IOException {
System.out.print("Decoder got Comment: ");
System.out.println("id: "+c.id);
System.out.println("comment: "+c.comment);
}
//public void handle_Typedef(Typedef t) throws java.io.IOException {
// System.out.print("Decoder got Typedef: ");
// t.dump();
//}
public static void main(String[] arg) throws Exception {
Decoder example = new Decoder(
......
......@@ -2,21 +2,35 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import se.lth.control.labcomm.Encoder;
import se.lth.control.labcomm.EncoderChannel;
/**
* Simple encoder
*/
public class Encoder
public class ExampleEncoder
{
EncoderChannel encoder;
public Encoder(OutputStream out)
public ExampleEncoder(OutputStream out)
throws Exception
{
encoder = new EncoderChannel(out);
twoLines.register(encoder);
theint.register(encoder);
Encoder.PragmaPacketBuilder t = encoder.newPragma("se.lth.cs.sven.pragma");
Comment.register(t);
Comment c = new Comment();
//c.id = encoder.getTypeId(twoLines.class);
c.id = 42;
c.comment = "Test comment";
Comment.encode(t,c);
t.send();
t = encoder.newPragma(null);
afoo.register(t);
afoo.encode(t, new foo());
t.send();
}
public void doEncode() throws java.io.IOException {
......@@ -74,12 +88,14 @@ public class Encoder
System.out.println("Encoding theTwoLines");
twoLines.encode(encoder, x);
theint.encode(encoder, 1337);
}
public static void main(String[] arg) throws Exception {
FileOutputStream fos = new FileOutputStream(arg[0]);
Encoder example = new Encoder(fos);
ExampleEncoder example = new ExampleEncoder(fos);
example.doEncode();
fos.close();
}
......
......@@ -2,7 +2,7 @@ LCDIR=../..
LCCJAR=${LCDIR}/compiler/labcomm_compiler.jar # the LabComm compiler
LCLJAR=${LCDIR}/lib/java/labcomm.jar # the LabComm library
EXECUTABLES=example_encoder example_decoder Encoder.class Decoder.class Encoder.exe Decoder.exe
EXECUTABLES=example_encoder example_decoder ExampleEncoder.class Decoder.class Encoder.exe Decoder.exe
include ${LCDIR}/lib/c/os_compat.mk
GENDIR=gen
......@@ -44,7 +44,7 @@ build :
mkdir -p ${GENDIR}
java -jar ${LCDIR}/compiler/labcomm_compiler.jar --java=${GENDIR} --c=${GENDIR}/test.c --h=${GENDIR}/test.h --python=${GENDIR}/test.py --cs=${GENDIR}/test.cs test.lc
javac -cp ${LCDIR}/lib/java/labcomm.jar:. ${GENDIR}/*.java Encoder.java Decoder.java
javac -cp ${LCDIR}/lib/java/labcomm.jar:. ${GENDIR}/*.java ExampleEncoder.java Decoder.java
${CC} ${CFLAGS} ${LDFLAGS} -Wall -Werror -Wno-unused-function \
-I. -I${LCDIR}/lib/c -L${LCDIR}/lib/c \
......@@ -65,7 +65,7 @@ run:
@echo "********************************************"
@echo
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Encoder encoded_data_j
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} ExampleEncoder encoded_data_j
@echo "************ running Java decoder: *****************"
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Decoder encoded_data_j
......@@ -108,7 +108,7 @@ runwcs: Encoder.exe Decoder.exe
@echo "********************************************"
@echo
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Encoder encoded_data_j
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} ExampleEncoder encoded_data_j
@echo "************ running Java decoder: *****************"
@java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Decoder encoded_data_j
......
......@@ -15,6 +15,14 @@ static void handle_test_twoLines(test_twoLines *v,void *context) {
v->l2.end.x.val, v->l2.end.y.val);
}
static void handle_test_theint(test_theint *v,void *context) {
printf("Got theint. %d\n", *v);
}
static void handle_test_Comment(test_Comment *v,void *context) {
printf("Got comment (0x%x): %s\n", v->id, v->comment);
}
int main(int argc, char *argv[]) {
int fd;
struct labcomm_decoder *decoder;
......@@ -34,6 +42,8 @@ int main(int argc, char *argv[]) {
}
labcomm_decoder_register_test_twoLines(decoder, handle_test_twoLines, context);
labcomm_decoder_register_test_theint(decoder, handle_test_theint, context);
labcomm_decoder_register_test_Comment(decoder, handle_test_Comment, context);
printf("Decoding:\n");
labcomm_decoder_run(decoder);
......
......@@ -8,6 +8,7 @@
#include "gen/test.h"
#include <stdio.h>
extern struct labcomm_signature labcomm_signature_test_twoLines;
int main(int argc, char *argv[]) {
int fd;
struct labcomm_encoder *encoder;
......@@ -22,6 +23,16 @@ int main(int argc, char *argv[]) {
labcomm_default_scheduler);
labcomm_encoder_register_test_twoLines(encoder);
#ifndef WITHOUT_PRAGMA
struct labcomm_encoder *pb = labcomm_pragma_builder_new(encoder,
"se.lth.cs.sven.pragma");
labcomm_encoder_register_test_Comment(pb);
test_Comment comment;
comment.id = 17;
comment.comment = "This is a metadata comment...";
labcomm_encode_test_Comment(pb, &comment);
labcomm_pragma_send(pb);
#endif
test_twoLines tl;
tl.l1.start.x.val = 11;
......
......@@ -12,14 +12,34 @@ typedef struct {
point end;
} line;
typedef int anint;
typedef struct {
int a;
int b;
anint a;
anint b;
boolean c;
} foo;
sample anint theint;
sample struct {
line l1;
line l2;
foo f;
} twoLines;
sample line fixedLineArray[2];
sample line varLineArray[_];
sample struct {
int x;
int y;
} structArray[2];
sample struct {
int id;
string comment;
} Comment; // For use in metadata
sample foo afoo; // to test unregistered metadata
......@@ -27,6 +27,7 @@ OBJS=labcomm_memory.o \
labcomm.o \
labcomm_dynamic_buffer_writer.o \
labcomm_fd_reader.o labcomm_fd_writer.o \
labcomm_bytearray_reader.o \
labcomm_pthread_scheduler.o
#FIXME: labcomm_mem_reader.o labcomm_mem_writer.o
......
......@@ -39,6 +39,8 @@
struct labcomm_encoder;
struct labcomm_decoder;
#include "labcomm_pragma.h"
/*
* Signature entry
*/
......@@ -117,7 +119,7 @@ void labcomm_decoder_free(
struct labcomm_decoder *decoder);
int labcomm_decoder_decode_one(
struct labcomm_decoder *decoder);
void labcomm_decoder_run(
int labcomm_decoder_run(
struct labcomm_decoder *decoder);
/* See labcomm_ioctl.h for predefined ioctl_action values */
......
/*
labcomm_bytearray_reader.c -- a reader for data in a byte array
Copyright 2014 Sen Gestegård Robertz <sven.robertz@cs.lth.se>
This file is part of LabComm.
LabComm 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.
LabComm 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/>.
*/
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "labcomm_private.h"
#include "labcomm_bytearray_reader.h"
struct labcomm_bytearray_reader {
struct labcomm_reader reader;
struct labcomm_reader_action_context action_context;
unsigned char *bytearray;
int bytearray_size;
};
#if 0
// XXX HERE BE DRAGONS: version removed?
static int bytearray_alloc(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context,
char *version)
#else
static int bytearray_alloc(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
#endif
{
int result = 0;
r->data = ((struct labcomm_bytearray_reader *)action_context->context)->bytearray;
r->count =((struct labcomm_bytearray_reader *)action_context->context)->bytearray_size;
r->pos = 0;
return result;
}
static int bytearray_free(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
struct labcomm_bytearray_reader *bytearray_reader = action_context->context;
struct labcomm_memory *memory = r->memory;
//HERE BE DRAGONS labcomm_memory_free(memory, 0, r->data);
r->data = 0;
r->data_size = 0;
r->count = 0;
r->pos = 0;
labcomm_memory_free(memory, 0, bytearray_reader);
return 0;
}
static int bytearray_fill(struct labcomm_reader *r,
struct labcomm_reader_action_context *action_context)
{
int result = 0;
if (r->pos < r->count) {
//printf("BAreader.fill: pos %d count: %d\n", r->pos, r->count);
result = r->count - r->pos;
} else {
r->pos = 0;
r->error = -EPIPE;
result = -EPIPE;
}
return result;
}
static const struct labcomm_reader_action action = {
.alloc = bytearray_alloc,
.free = bytearray_free,
.start = NULL,
.fill = bytearray_fill,
.end = NULL,
.ioctl = NULL
};
struct labcomm_reader *labcomm_bytearray_reader_new(struct labcomm_memory *memory,
unsigned char *data, int size)
{
struct labcomm_bytearray_reader *result;
result = labcomm_memory_alloc(memory, 0, sizeof(*result));
if (result == NULL) {
return NULL;
} else {
result->action_context.next = NULL;
result->action_context.action = &action;
result->action_context.context = result;
result->reader.action_context = &result->action_context;
result->reader.memory = memory;
result->bytearray = data;
result->bytearray_size = size;
struct labcomm_reader * res = &result->reader;
// printf("reader: %p, size: %d\n", res, res->data_size);
return res;
}
}
/*
labcomm_bytearray_reader.h -- a reader for data in a byte array
Copyright 2014 Sen Gestegård Robertz <sven.robertz@cs.lth.se>
This file is part of LabComm.
LabComm 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.
LabComm 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/>.
*/
#ifndef _LABCOMM_BYTEARRAY_READER_H_
#define _LABCOMM_BYTEARRAY_READER_H_
#include "labcomm.h"
struct labcomm_reader *labcomm_bytearray_reader_new(struct labcomm_memory *memory,
unsigned char *data, int size);
#endif
......@@ -25,6 +25,7 @@
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#include "labcomm_dynamic_buffer_writer.h"
#include "labcomm_bytearray_reader.h"
struct sample_entry {
int remote_index;
......@@ -34,6 +35,29 @@ struct sample_entry {
void *context;
};
static int internal_decoder_run(struct labcomm_decoder *d,
struct labcomm_decoder *registry);
static int internal_decode_one(struct labcomm_decoder *d,
struct labcomm_decoder *registry);
int default_pragma_handler(struct labcomm_decoder *d,
struct labcomm_decoder *registry,
char *pragma_type,
void *context)
{
printf("Default pragma handler got pragma: %s\n", pragma_type);
int res = internal_decoder_run(d, registry);
printf("... %d:%s\n",res,strerror(-res));
return LABCOMM_PRAGMA;
}
labcomm_pragma_handler_callback default_pragma_handler_lookup(
char *pragma_type,
struct labcomm_decoder *d,
void *context)
{
return default_pragma_handler;
}
struct labcomm_decoder {
struct labcomm_reader *reader;
int reader_allocated;
......@@ -45,6 +69,7 @@ struct labcomm_decoder {
labcomm_handle_new_datatype_callback on_new_datatype;
LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
labcomm_pragma_handler_lookup pragma_handler_lookup;
};
struct labcomm_decoder *labcomm_decoder_new(
......@@ -72,10 +97,31 @@ struct labcomm_decoder *labcomm_decoder_new(
result->on_error = on_error_fprintf;
LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
result->pragma_handler_lookup = default_pragma_handler_lookup;
}
return result;
}
#ifndef WITHOUT_PRAGMA
/* Internal aux function to allow temporary internal decoders
* to share the same memory.
* This function only frees the decoder, not the memory
*/
static void internal_labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
labcomm_reader_free(d->reader, d->reader->action_context);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry);
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
}
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
internal_labcomm_decoder_free(d);
labcomm_memory_free(memory, 0, d);
}
#else
void labcomm_decoder_free(struct labcomm_decoder* d)
{
struct labcomm_memory *memory = d->memory;
......@@ -85,8 +131,16 @@ void labcomm_decoder_free(struct labcomm_decoder* d)
LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
labcomm_memory_free(memory, 0, d);
}
#endif
static int decode_sample(struct labcomm_decoder *d, int kind)
/* d - decoder to read from
registry - decoder to lookup signatures (registry != d only if
nesting decoders, e.g., when decoding pragma)
kind - type to decode (sample 0x02, or TODO: typedef/binding )
*/
static int decode_sample_def(struct labcomm_decoder *d,
struct labcomm_decoder *registry,
int kind)
{
int result;
struct labcomm_signature signature, *local_signature;
......@@ -110,6 +164,7 @@ static int decode_sample(struct labcomm_decoder *d, int kind)
goto free_signature_name;
}
signature.signature = labcomm_memory_alloc(d->memory, 1, signature.size);
//XXX d->reader???
if (d->reader->error < 0) {
result = d->reader->error;
goto free_signature_name;
......@@ -121,14 +176,14 @@ static int decode_sample(struct labcomm_decoder *d, int kind)
goto free_signature_signature;
}
}
labcomm_scheduler_data_lock(d->scheduler);
LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) {
labcomm_scheduler_data_lock(registry->scheduler);
LABCOMM_SIGNATURE_ARRAY_FOREACH(registry->local, struct sample_entry, i) {
struct sample_entry *s;
int *remote_to_local;
result = -ENOENT;
s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->local, struct sample_entry, i);
s = LABCOMM_SIGNATURE_ARRAY_REF(registry->memory,
registry->local, struct sample_entry, i);
if (s->signature &&
s->signature->size == signature.size &&
strcmp(s->signature->name, signature.name) == 0 &&
......@@ -137,15 +192,15 @@ static int decode_sample(struct labcomm_decoder *d, int kind)
s->remote_index = remote_index;
local_signature = s->signature;
local_index = i;
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
d->remote_to_local, int,
remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(registry->memory,
registry->remote_to_local, int,
remote_index);
*remote_to_local = i;
result = remote_index;
break;
}
}
labcomm_scheduler_data_unlock(d->scheduler);
labcomm_scheduler_data_unlock(registry->scheduler);
if (local_signature) {
labcomm_reader_start(d->reader, d->reader->action_context,
local_index, remote_index, local_signature,
......@@ -189,6 +244,25 @@ static void reader_alloc(struct labcomm_decoder *d)
labcomm_reader_alloc(d->reader, d->reader->action_context);
}
}
static int decode_version(struct labcomm_decoder *d,
int remote_index)
{
int result;
char *version = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (strcmp(version, CURRENT_VERSION) == 0) {
result = LABCOMM_VERSION;
d->version_ok = 1;
} else {
result = -ECONNRESET;
}
labcomm_memory_free(d->memory, 1, version);
out:
return result;
}
static int decoder_skip(struct labcomm_decoder *d, int len, int tag)
{
......@@ -213,6 +287,7 @@ static int decode_pragma(struct labcomm_decoder *d,
{
char *pragma_type;
int result;
labcomm_pragma_handler_callback handler;
pragma_type = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
......@@ -220,7 +295,39 @@ static int decode_pragma(struct labcomm_decoder *d,
}
int bytes = labcomm_size_string(pragma_type);
int psize = len-bytes;
handler = d->pragma_handler_lookup(pragma_type, d, 0);
if(handler) {
//read the entire packet to a buffer and then run
// decode on that through a bytearray_reader.
// (to easily handle multiple labcomm packets in one metadata packet)
int i;
unsigned char pragma_data[psize] ;
for(i=0; i<psize; i++) {
pragma_data[i] = labcomm_read_byte(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
}
//TODO: add wrapped decoders, by adding a parameter
//struct labcomm_decoder *wrapped to all _internal_decode... functions
//incl internal_decode_one()
//and let the public function ...decode(d) call
//_internal_decode(d,d)
struct labcomm_reader *pr = labcomm_bytearray_reader_new(
d->reader->memory, pragma_data, psize);
struct labcomm_decoder *pd = labcomm_decoder_new(
pr, d->error, d->memory, d->scheduler);
pd->version_ok = 1;
void *pragma_context = 0;
printf("calling pragma_handler\n");
result = handler(pd, registry, pragma_type,pragma_context);
printf("returned from pragma_handler\n");
internal_labcomm_decoder_free(pd);
} else {
result = decoder_skip(d, psize, LABCOMM_PRAGMA);
}
out:
return result;
}
......@@ -281,6 +388,15 @@ static int decode_and_handle(struct labcomm_decoder *d,
return result;
}
int labcomm_decoder_decode_one(struct labcomm_decoder *d)
{
return internal_decode_one(d,d);
}
/* d - decoder to read from
registry - decoder to lookup signatures (registry != d only if
nesting decoders, e.g., when decoding pragma)
*/
int internal_decode_one(struct labcomm_decoder *d,
struct labcomm_decoder *registry)
{
int result, remote_index, length;
......@@ -296,39 +412,40 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
goto out;
}
if (remote_index == LABCOMM_VERSION) {
char *version = labcomm_read_string(d->reader);
if (d->reader->error < 0) {
result = d->reader->error;
goto out;
}
if (strcmp(version, CURRENT_VERSION) == 0) {
result = LABCOMM_VERSION;
d->version_ok = 1;
} else {
result = -ECONNRESET;
}
labcomm_memory_free(d->memory, 1, version);
result = decode_version(d, remote_index);
} else if (! d->version_ok) {
fprintf(stderr, "No VERSION %d %d\n", remote_index, length);
result = -ECONNRESET;
} else if (remote_index == LABCOMM_SAMPLE) {
result = decode_sample(d, remote_index);
} else if (remote_index == LABCOMM_SAMPLE_DEF) {
result = decode_sample_def(d, registry, remote_index);
} else if (remote_index == LABCOMM_PRAGMA ){
result = decode_pragma(d, d, length);
result = decode_pragma(d, registry, length);
} else if (remote_index < LABCOMM_USER) {
fprintf(stderr, "SKIP %d %d\n", remote_index, length);
result = remote_index;
//fprintf(stderr, "SKIP %d %d\n", remote_index, length);
//result = remote_index;
result = decoder_skip(d, length, remote_index);
} else {
result = decode_and_handle(d, d, remote_index);
result = decode_and_handle(d, registry, remote_index);
}
out:
return result;
}
void labcomm_decoder_run(struct labcomm_decoder *d)
int labcomm_decoder_run(struct labcomm_decoder *d)
{
return internal_decoder_run(d,d);
}
/* d - decoder to read from
registry - decoder to lookup signatures (registry != d only if
nesting decoders, e.g., when decoding pragma)
*/
int internal_decoder_run(struct labcomm_decoder *d,
struct labcomm_decoder *registry)
{
while (labcomm_decoder_decode_one(d) > 0) {
int res;
while ( (res=internal_decode_one(d, registry)) > 0) {
}
return res;
}
int labcomm_decoder_ioctl(struct labcomm_decoder *d,
......
......@@ -25,12 +25,19 @@
#include "labcomm_private.h"
#include "labcomm_ioctl.h"
#ifndef WITHOUT_PRAGMA
#include "labcomm_dynamic_buffer_writer.h"
#include "labcomm_bytearray_reader.h"
#endif
struct labcomm_encoder {
struct labcomm_writer *writer;
struct labcomm_error_handler *error;
struct labcomm_memory *memory;
struct labcomm_scheduler *scheduler;
LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
int context_type; //type tag for context. Currently only LABCOMM_PRAGMA
void *context; // for, e.g. parent of pragma packet builder
};
struct labcomm_encoder *labcomm_encoder_new(
......@@ -80,7 +87,136 @@ void labcomm_encoder_free(struct labcomm_encoder* e)
labcomm_memory_free(memory, 0, e);
}
int labcomm_internal_encoder_register(
#undef WITHOUT_PRAGMA
#ifndef WITHOUT_PRAGMA
struct pragma_packet_builder {
char * pragma_type;
struct labcomm_encoder* parent;
};
struct labcomm_encoder *labcomm_pragma_builder_new(
struct labcomm_encoder *e,
char * pragma_type)
{
struct labcomm_writer *dyn_writer = labcomm_dynamic_buffer_writer_new(
e->memory);
struct labcomm_encoder *pb = labcomm_encoder_new(dyn_writer,
e->error,
e->memory,
e->scheduler);
size_t tlen = 1+strlen(pragma_type);
char* ptype = labcomm_memory_alloc(
e->memory,
1,
tlen);
if(ptype) {
strncpy(ptype, pragma_type, tlen);
} //XXX TODO: and else?
struct pragma_packet_builder* ctxt = labcomm_memory_alloc(
e->memory,
1,
sizeof(struct pragma_packet_builder));
if(ctxt){
ctxt->pragma_type=ptype;
ctxt->parent=e;
}
pb->context_type = LABCOMM_PRAGMA;
pb->context = ctxt;
return pb;
}
//HERE BE DRAGONS! Copied from decoder.c
//Should this be moved to private_h?
static int writer_ioctl(struct labcomm_writer *writer,
uint32_t action,
...)
{
int result;
va_list va;
if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
result = -EINVAL;
goto out;
}
va_start(va, action);
result = labcomm_writer_ioctl(writer, writer->action_context,
0, NULL, action, va);
va_end(va);
out:
return result;
}
int labcomm_pragma_send(struct labcomm_encoder* e)
{
//HERE BE DRAGONS!
//We assume that the writer is a dynamic_buffer_writer
if(e->context_type != LABCOMM_PRAGMA) {
printf("context type != PRAGMA, bailing out\n");
return 1;
}
if(!e->context) {
printf("context == NULL, bailing out\n");
return 2;
}
struct pragma_packet_builder* ctx = e->context;
struct labcomm_encoder *p = ctx->parent;
char * pragma_type = ctx->pragma_type;
char* pragma_data;
int err,len;
labcomm_writer_end(e->writer, e->writer->action_context);
err = writer_ioctl(e->writer,
LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
&len);
if (err < 0) {
// HERE BE DRAGONS!
// What is the difference between error_handler (where is it defined?)
// and error_handler_callback. And why is the latter only in
// the decoder struct?
//
// e->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
// "Failed to get size: %s\n", strerror(-err));
fprintf(stderr, "BAD WRITER, Failed to get size> %s\n", strerror(-err));
err = -ENOENT;
goto free_encoder;
}
err = writer_ioctl(e->writer,
LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
&pragma_data);
if (err < 0) {
// e->on_error(LABCOMM_ERROR_BAD_WRITER, 2,
// "Failed to get pointer: %s\n", strerror(-err));
fprintf(stderr, "BAD WRITER, Failed to get pointer> %s\n", strerror(-err));
err = -ENOENT;
goto free_encoder;
}
{
int data_len = labcomm_size_string(pragma_type) + len;
int i;
labcomm_write_packed32(p->writer, LABCOMM_PRAGMA);
labcomm_write_packed32(p->writer, data_len);
labcomm_write_string(p->writer, pragma_type);
for(i=0; i<len;i++){
labcomm_write_byte(p->writer, pragma_data[i]);
}
labcomm_writer_end(p->writer, p->writer->action_context);
err = p->writer->error;
}
free_encoder:
//XXX are these needed, or is that done in encoder_free?
labcomm_memory_free(e->memory, 1, ctx->pragma_type);
labcomm_memory_free(e->memory, 1, ctx);
labcomm_encoder_free(e);
return err;
}
#endif
static int labcomm_internal_encoder_reg_type(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
......@@ -98,7 +234,7 @@ int labcomm_internal_encoder_register(
index, signature, NULL);
if (err == -EALREADY) { result = 0; goto out; }
if (err != 0) { result = err; goto out; }
labcomm_write_packed32(e->writer, LABCOMM_SAMPLE);
labcomm_write_packed32(e->writer, LABCOMM_SAMPLE_DEF);
length = (labcomm_size_packed32(index) +
labcomm_size_string(signature->name) +
labcomm_size_packed32(signature->size) +
......@@ -121,6 +257,18 @@ out:
return result;
}
int labcomm_internal_encoder_register(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
labcomm_encoder_function encode)
{
if(e->context_type == LABCOMM_PRAGMA && e->context){
e=((struct pragma_packet_builder *)e->context)->parent;
}
return labcomm_internal_encoder_reg_type(
e, signature, encode);
}
int labcomm_internal_encode(
struct labcomm_encoder *e,
struct labcomm_signature *signature,
......
/*
labcomm_pragma.h -- user interface for handling labcomm pragma packets.
Copyright 2014 Sven Gestegård Robertz <sven.robertz@cs.lth.se>
Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm 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.
LabComm 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/>.
*/
#ifndef _LABCOMM_PRAGMA_H
#define _LABCOMM_PRAGMA_H
typedef int (*labcomm_pragma_handler_callback)(
struct labcomm_decoder *decoder,
struct labcomm_decoder *registry,
char *pragma_type,
void *context);
typedef labcomm_pragma_handler_callback (*labcomm_pragma_handler_lookup)(
char *pragma_type,
struct labcomm_decoder *d,
void *context);
void labcomm_decoder_register_pragma_handler_lookup(struct labcomm_decoder *d,
labcomm_pragma_handler_lookup pragma_lookup,
void *context);
/*XXX TODO: rename to _callback? */
void labcomm_decoder_register_pragma_handler(struct labcomm_decoder *d,
labcomm_pragma_handler_callback pragma_dispatcher,
void *context);
/*XXX TODO: rename to _callback? */
int default_pragma_handler(struct labcomm_decoder *d,
struct labcomm_decoder *registry,
char *pragma_type,
void *context);
labcomm_pragma_handler_callback default_pragma_handler_lookup(
char *pragma_type,
struct labcomm_decoder *d,
void *context);
struct labcomm_encoder *labcomm_pragma_builder_new(
struct labcomm_encoder *e,
char * pragma_type) ;
int labcomm_pragma_send(struct labcomm_encoder* e);
#endif
......@@ -40,13 +40,12 @@
* Allowed packet tags
*/
#define LABCOMM_VERSION 0x01
#define LABCOMM_SAMPLE 0x02
#define LABCOMM_TYPEDEF 0x03
#define LABCOMM_TYPEBINDING 0x04
#define LABCOMM_SAMPLE_DEF 0x02
#define LABCOMM_TYPE_DEF 0x03
#define LABCOMM_TYPE_BINDING 0x04
#define LABCOMM_PRAGMA 0x3f
#define LABCOMM_USER 0x40 /* ..0xffffffff */
/*
* Predefined aggregate type indices
*/
......
......@@ -9,6 +9,7 @@ MODULES=Constant \
Sample \
SampleDispatcher \
SampleHandler \
Type \
SampleType \
Writer \
WriterWrapper
......
......@@ -3,6 +3,7 @@ package se.lth.control.labcomm;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.EOFException;
......@@ -44,12 +45,36 @@ public class DecoderChannel implements Decoder {
}
private void processPragma(int len) throws IOException {
System.out.println("Got Pragma: skipping "+len+" bytes");
for(int i=0; i<len; i++) {
decodeByte();
}
// String pt = decodeString();
// System.out.println("Pragma["+pt+"]: skipping "+plen+" bytes");
// for(int i=0; i<plen; i++) {
// decodeByte();
// }
String type = decodeString();
int plen = len - Encoder.Util.sizeof_string(type);
System.out.println("[ begin pragma ("+type+") ]");
//System.out.println("metadata : "+len + " bytes, ref: " + Integer.toHexString(typeRefId)+".");
byte buf[] = new byte[plen];
for(int i=0; i<plen; i++) {
buf[i]=decodeByte();
}
ByteArrayInputStream bis = new ByteArrayInputStream(buf);
DecoderChannel pd = new DecoderChannel(bis, registry);
try{
pd.run();
} catch(java.io.EOFException ex) {
// We're done.
} catch(Throwable e) {
// Something unexpected happened
// (an unregistered handler is OK, but still report it.
// TODO: implement exception handling here. Aborting is fine,
// that only means skipping the rest of the metadata packet.)
System.out.println("Exception while decoding pragma: "+e);
}
System.out.println("[ end pragma ]");
}
public void runOne() throws Exception {
boolean done = false;
while (!done) {
......@@ -78,7 +103,7 @@ public class DecoderChannel implements Decoder {
default: {
DecoderRegistry.Entry e = registry.get(tag);
if (e == null) {
throw new IOException("Unhandled tag " + tag);
throw new IOException("Unhandled tag 0x" + Integer.toHexString(tag));
}
SampleDispatcher d = e.getDispatcher();
if (d == null) {
......