From d6cadad67550bc9ca6e180de9384f8e4ad74988f Mon Sep 17 00:00:00 2001 From: Sven Gestegard Robertz <sven.robertz@cs.lth.se> Date: Mon, 26 Jan 2015 15:23:17 +0100 Subject: [PATCH] C code sending type defs and bindings. --- compiler/2014/C_CodeGen.jrag | 43 ++++- lib/c/2014/Makefile | 1 + lib/c/2014/labcomm.c | 5 + lib/c/2014/labcomm.h | 53 ------ lib/c/2014/labcomm_decoder.c | 6 +- lib/c/2014/labcomm_encoder.c | 250 ++++++++++++++++++++++++++-- lib/c/2014/labcomm_private.h | 14 +- lib/c/2014/labcomm_type_signature.c | 128 ++++++++++++++ lib/c/2014/labcomm_type_signature.h | 155 +++++++++++++++++ 9 files changed, 580 insertions(+), 75 deletions(-) create mode 100644 lib/c/2014/labcomm_type_signature.c create mode 100644 lib/c/2014/labcomm_type_signature.h diff --git a/compiler/2014/C_CodeGen.jrag b/compiler/2014/C_CodeGen.jrag index c4c934b..b4709aa 100644 --- a/compiler/2014/C_CodeGen.jrag +++ b/compiler/2014/C_CodeGen.jrag @@ -1130,11 +1130,34 @@ aspect C_Encoder { " not declared"); } + protected void Decl.C_emitEncoderTypeRegister(C_env env) { + env.println("int labcomm"+env.verStr+"_encoder_type_register_" + + env.prefix + getName() + "("); + env.indent(); + env.println("struct labcomm"+env.verStr+"_encoder *e"); + env.unindent(); + env.println(")"); + env.println("{"); + env.indent(); + env.println("//TODO: add error handling for dependencies"); + C_emitUserTypeDeps(env, null, true); //XXX HERE BE DRAGONS + //currently set to false to turn off + //outputting of code + env.println("return labcomm"+env.verStr+"_internal_encoder_type_register("); + env.indent(); + env.println("e,"); + env.println("&signature_" + env.prefix + getName() + ""); + env.unindent(); + env.println(");"); + env.unindent(); + env.println("}"); + } public void TypeDecl.C_emitEncoderRegisterHandler(C_env env) { - // do nothing for type decls + C_emitEncoderTypeRegister(env); } public void SampleDecl.C_emitEncoderRegisterHandler(C_env env) { + C_emitEncoderTypeRegister(env); env.println("int labcomm"+env.verStr+"_encoder_register_" + env.prefix + getName() + "("); env.indent(); @@ -1146,17 +1169,23 @@ aspect C_Encoder { C_emitUserTypeDeps(env, null, false); //XXX HERE BE DRAGONS //currently set to false to turn off //outputting of code - env.println("return labcomm"+env.verStr+"_internal_encoder_register("); + env.println("int result = labcomm"+env.verStr+"_internal_encoder_register("); env.indent(); env.println("e,"); env.println("&signature_" + env.prefix + getName() + ","); env.println("(labcomm"+env.verStr+"_encoder_function)encode_" + env.prefix + getName()); env.unindent(); env.println(");"); + env.println("labcomm"+env.verStr+"_encoder_type_register_" + env.prefix + getName()+"(e);"); + env.println("labcomm"+env.verStr+"_internal_encoder_type_bind("); + env.indent(); + env.println("e,"); + env.println("&signature_" + env.prefix + getName() + ");"); + env.unindent(); + env.println("return result;"); env.unindent(); env.println("}"); } - } aspect C_EncoderIoctl { @@ -1206,7 +1235,7 @@ aspect C_TypeDependencies { t.C_emitUserTypeDeps(env, t.getName(), outputCode); if(outputCode) { System.out.println("Decl.C_emitUserTypeDeps registering "+t.getName()); - env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);"); + env.println("labcomm"+env.verStr+"_encoder_type_register_"+env.prefix + t.getName()+"(e);"); } else { // Just output a comment String refpath = (via == null) ? "directly" : "indirectly via "+via; env.println(" //Depends ("+refpath+") on "+t.getName() ); @@ -1222,7 +1251,7 @@ aspect C_TypeDependencies { t.C_emitUserTypeRefs(env, t.getName(), outputCode); if(outputCode) { - env.println("labcomm"+env.verStr+"_encoder_register_"+env.prefix + t.getName()+"(e);"); + env.println("labcomm"+env.verStr+"_encoder_type_register_"+env.prefix + t.getName()+"(e);"); } else { // Just output a comment String refpath = (via == null) ? "directly" : "indirectly via "+via; env.println(" //Is referenced ("+refpath+") by "+t.getName() ); @@ -1454,9 +1483,9 @@ aspect C_Constructor { } public void Decl.C_emitConstructor(C_env env) { - } +// } //XXX - public void SampleDecl.C_emitConstructor(C_env env) { +// public void SampleDecl.C_emitConstructor(C_env env) { env.println("labcomm"+env.verStr+"_set_local_index(&signature_" + env.prefix + getName() + ");"); } diff --git a/lib/c/2014/Makefile b/lib/c/2014/Makefile index 6742429..f71c292 100644 --- a/lib/c/2014/Makefile +++ b/lib/c/2014/Makefile @@ -20,6 +20,7 @@ OBJS=labcomm$(VERSION).o \ labcomm$(VERSION)_decoder.o \ labcomm$(VERSION)_dynamic_buffer_writer.o \ labcomm$(VERSION)_fd_reader.o \ + labcomm$(VERSION)_type_signature.o \ labcomm$(VERSION)_fd_writer.o \ labcomm$(VERSION)_pthread_scheduler.o diff --git a/lib/c/2014/labcomm.c b/lib/c/2014/labcomm.c index a1994af..22da2e1 100644 --- a/lib/c/2014/labcomm.c +++ b/lib/c/2014/labcomm.c @@ -257,6 +257,11 @@ int labcomm_get_local_index(const struct labcomm_signature *signature) return signature->index; } +int labcomm_get_local_type_index(const struct labcomm_signature *signature) +{ + return labcomm_get_local_index(signature); +} + int labcomm_internal_sizeof(const struct labcomm_signature *signature, void *v) { diff --git a/lib/c/2014/labcomm.h b/lib/c/2014/labcomm.h index 5499184..8018c5b 100644 --- a/lib/c/2014/labcomm.h +++ b/lib/c/2014/labcomm.h @@ -39,59 +39,6 @@ struct labcomm_encoder; struct labcomm_decoder; -/* - * Signature entry - */ -#ifndef LABCOMM_NO_TYPEDECL -#ifdef USE_UNIONS - -/* Useful for C99 and up (or GCC without -pedantic) */ - -#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ - union { \ - char *bytes; \ - struct labcomm_signature* signature; \ - } u; - -#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b } -#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[] -#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 } - -#else - -#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ - struct { \ - char *bytes; \ - const struct labcomm_signature *signature; \ - } u; - -#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } } -#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } } -#define LABCOMM_SIGDEF_END { -1, { 0, 0 } } - -#endif - -struct labcomm_signature_data { - int length; - LABCOMM_SIGDEF_BYTES_OR_SIGNATURE -}; - -#endif -struct labcomm_signature { - char *name; - int (*encoded_size)(void *); /* void* refers to sample_data */ - int size; - unsigned char *signature; - int index; -#ifndef LABCOMM_NO_TYPEDECL - int tdsize; - struct labcomm_signature_data *treedata; -#endif -#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE - int cached_encoded_size; // -1 if not initialized or type is variable size -#endif -}; - #include "labcomm_type_signature.h" /* * Error handling. diff --git a/lib/c/2014/labcomm_decoder.c b/lib/c/2014/labcomm_decoder.c index 54575ee..1d3c1f0 100644 --- a/lib/c/2014/labcomm_decoder.c +++ b/lib/c/2014/labcomm_decoder.c @@ -374,11 +374,15 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d) result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_DEF); } else if (remote_index == LABCOMM_SAMPLE_REF) { result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_REF); + } else if (remote_index == LABCOMM_TYPE_DEF) { + result = decoder_skip(d, length, remote_index); + } else if (remote_index == LABCOMM_TYPE_BINDING) { + result = decoder_skip(d, length, remote_index); } else if (remote_index == LABCOMM_PRAGMA) { result = decode_pragma(d, d, length); } else if (remote_index < LABCOMM_USER) { 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); } diff --git a/lib/c/2014/labcomm_encoder.c b/lib/c/2014/labcomm_encoder.c index 4085bbd..f8fd9ae 100644 --- a/lib/c/2014/labcomm_encoder.c +++ b/lib/c/2014/labcomm_encoder.c @@ -24,6 +24,7 @@ #include "labcomm.h" #include "labcomm_private.h" #include "labcomm_ioctl.h" +#include "labcomm_dynamic_buffer_writer.h" struct labcomm_encoder { struct labcomm_writer *writer; @@ -32,13 +33,15 @@ struct labcomm_encoder { struct labcomm_scheduler *scheduler; LABCOMM_SIGNATURE_ARRAY_DEF(registered, int); LABCOMM_SIGNATURE_ARRAY_DEF(sample_ref, int); + LABCOMM_SIGNATURE_ARRAY_DEF(typedefs, int); }; -struct labcomm_encoder *labcomm_encoder_new( +static struct labcomm_encoder *internal_encoder_new( struct labcomm_writer *writer, struct labcomm_error_handler *error, struct labcomm_memory *memory, - struct labcomm_scheduler *scheduler) + struct labcomm_scheduler *scheduler, + labcomm_bool outputVer) { struct labcomm_encoder *result; @@ -58,25 +61,36 @@ struct labcomm_encoder *labcomm_encoder_new( result->scheduler = scheduler; LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int); LABCOMM_SIGNATURE_ARRAY_INIT(result->sample_ref, int); + LABCOMM_SIGNATURE_ARRAY_INIT(result->typedefs, int); labcomm_writer_alloc(result->writer, result->writer->action_context); - labcomm_writer_start(result->writer, - result->writer->action_context, - LABCOMM_VERSION, NULL, CURRENT_VERSION); - labcomm_write_packed32(result->writer, LABCOMM_VERSION); + if(outputVer) { + labcomm_writer_start(result->writer, + result->writer->action_context, + LABCOMM_VERSION, NULL, CURRENT_VERSION); + labcomm_write_packed32(result->writer, LABCOMM_VERSION); #ifdef LENGTH_INCL_TAG - length = (labcomm_size_packed32(LABCOMM_VERSION) + - labcomm_size_string(CURRENT_VERSION)); + length = (labcomm_size_packed32(LABCOMM_VERSION) + + labcomm_size_string(CURRENT_VERSION)); #else - length = labcomm_size_string(CURRENT_VERSION); + length = labcomm_size_string(CURRENT_VERSION); #endif - labcomm_write_packed32(result->writer, length); - labcomm_write_string(result->writer, CURRENT_VERSION); - labcomm_writer_end(result->writer, result->writer->action_context); + labcomm_write_packed32(result->writer, length); + labcomm_write_string(result->writer, CURRENT_VERSION); + labcomm_writer_end(result->writer, result->writer->action_context); + } } return result; } +struct labcomm_encoder *labcomm_encoder_new( + struct labcomm_writer *writer, + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler) +{ + return internal_encoder_new(writer,error,memory,scheduler,TRUE); +} void labcomm_encoder_free(struct labcomm_encoder* e) { struct labcomm_memory *memory = e->memory; @@ -86,7 +100,219 @@ void labcomm_encoder_free(struct labcomm_encoder* e) LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->sample_ref, int); labcomm_memory_free(memory, 0, e); } +//================ +static struct labcomm_encoder * wrapped_begin( + struct labcomm_encoder *e) { + struct labcomm_writer *dyn_writer = labcomm_dynamic_buffer_writer_new( + e->memory); + struct labcomm_encoder *wrapped = internal_encoder_new(dyn_writer, + e->error, + e->memory, + e->scheduler, + FALSE); + return wrapped; +} +//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 wrapped_end(struct labcomm_encoder *e, int tag, struct labcomm_encoder* wrapped) +{ +//HERE BE DRAGONS! +//We assume that the writer is a dynamic_buffer_writer + char* wrapped_data; + int err,len; + labcomm_writer_end(wrapped->writer, wrapped->writer->action_context); + err = writer_ioctl(wrapped->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? +// +// wrapped->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(wrapped->writer, + LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER, + &wrapped_data); + if (err < 0) { +// wrapped->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 i; + err = labcomm_writer_start(e->writer, e->writer->action_context, + LABCOMM_TYPE_DEF, NULL, NULL); + if(err < 0) { + goto free_encoder; + } + labcomm_write_packed32(e->writer, tag); + labcomm_write_packed32(e->writer, len); + for(i=0; i<len;i++){ + labcomm_write_byte(e->writer, wrapped_data[i]); + } + labcomm_writer_end(e->writer, e->writer->action_context); + err = e->writer->error; + } +free_encoder: + //labcomm_memory_free(wrapped->memory, 1, ctx); + labcomm_encoder_free(wrapped); + return err; +} +//================ + +// -------------- +#define TEST_MAP + +#ifdef TEST_MAP +static void write_sig_byte(char b, const struct labcomm_signature *signature, + void *context) +{ + struct labcomm_encoder *e = context; + if(signature) { + labcomm_write_packed32(e->writer, labcomm_get_local_index(signature)); + }else { + if (e->writer->pos >= e->writer->count) { + labcomm_writer_flush(e->writer, e->writer->action_context); + } + e->writer->data[e->writer->pos] = b; + e->writer->pos++; + } +} +#endif + +static void do_write_signature(struct labcomm_encoder * e, const struct labcomm_signature *signature, unsigned char flatten) +{ +#ifdef TEST_MAP + map_signature(write_sig_byte, e, signature, flatten); +#else + struct labcomm_signature_data* p = signature->signature; + while (p->length != -1) { + if (p->length) { + int i; + for ( i = 0 ; i < p->length ; i++) { + if (e->writer->pos >= e->writer->count) { + labcomm_writer_flush(e->writer, e->writer->action_context); + } + e->writer->data[e->writer->pos] = p->u.bytes[i]; + e->writer->pos++; + } + } else { + if(p->u.signature == 0) printf("p->u.signature == null\n"); + if(flatten) { + do_write_signature(e, p->u.signature, flatten); + } else { + labcomm_write_packed32(e->writer, labcomm_get_local_index(p->u.signature)); + } + } + p+=1; + } +#endif +} + +static int internal_reg_type( + struct labcomm_encoder *e, + const struct labcomm_signature *signature, + labcomm_bool flatten) +{ + int result = -EINVAL; + int index, *done, err; + //int i: + + index = labcomm_get_local_index(signature); + labcomm_scheduler_writer_lock(e->scheduler); + if (index <= 0) { goto out; } + done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->typedefs, int, index); + if (*done) { goto out; } + *done = 1; + err = labcomm_writer_start(e->writer, e->writer->action_context, + index, signature, NULL); + if (err == -EALREADY) { result = 0; goto out; } + if (err != 0) { result = err; goto out; } + labcomm_write_packed32(e->writer, index); + labcomm_write_string(e->writer, signature->name); + //XXX flush for debugging, can be removed when working + // labcomm_writer_flush(e->writer, e->writer->action_context); + do_write_signature(e, signature, FALSE); +// for (i = 0 ; i < signature->size ; i++) { +// if (e->writer->pos >= e->writer->count) { +// labcomm_writer_flush(e->writer, e->writer->action_context); +// } +// e->writer->data[e->writer->pos] = signature->signature[i]; +// e->writer->pos++; +// } + labcomm_writer_end(e->writer, e->writer->action_context); + result = e->writer->error; +out: + labcomm_scheduler_writer_unlock(e->scheduler); + return result; +} +//-------------- +int labcomm_internal_encoder_type_register( + struct labcomm_encoder *e, + const struct labcomm_signature *signature) +{ + struct labcomm_encoder *w = wrapped_begin(e); + internal_reg_type(w, signature, FALSE); + return wrapped_end(e, LABCOMM_TYPE_DEF, w); +} +int labcomm_internal_encoder_type_bind( + struct labcomm_encoder *e, + const struct labcomm_signature *signature) +{ + int result = -EINVAL; + int err; + int sindex = labcomm_get_local_index(signature); + int tindex = labcomm_get_local_type_index(signature); + labcomm_scheduler_writer_lock(e->scheduler); + if(sindex <= 0 || tindex <= 0) {goto out;} + err = labcomm_writer_start(e->writer, e->writer->action_context, + LABCOMM_TYPE_BINDING, signature, NULL); + if (err == -EALREADY) { result = 0; goto out; } + if (err != 0) { result = err; goto out; } + int length = (labcomm_size_packed32(sindex) + + labcomm_size_packed32(tindex)); + labcomm_write_packed32(e->writer, LABCOMM_TYPE_BINDING); + labcomm_write_packed32(e->writer, length); + labcomm_write_packed32(e->writer, sindex); + labcomm_write_packed32(e->writer, tindex); + labcomm_writer_end(e->writer, e->writer->action_context); + result = e->writer->error; + +out: + labcomm_scheduler_writer_unlock(e->scheduler); + return result; +} int labcomm_internal_encoder_register( struct labcomm_encoder *e, const struct labcomm_signature *signature, diff --git a/lib/c/2014/labcomm_private.h b/lib/c/2014/labcomm_private.h index 95900fe..a1792d0 100644 --- a/lib/c/2014/labcomm_private.h +++ b/lib/c/2014/labcomm_private.h @@ -42,8 +42,8 @@ #define LABCOMM_VERSION 0x01 #define LABCOMM_SAMPLE_DEF 0x02 #define LABCOMM_SAMPLE_REF 0x03 -#define LABCOMM_TYPEDEF 0x04 -#define LABCOMM_TYPEBINDING 0x05 +#define LABCOMM_TYPE_DEF 0x04 +#define LABCOMM_TYPE_BINDING 0x05 #define LABCOMM_PRAGMA 0x3f #define LABCOMM_USER 0x40 /* ..0xffffffff */ @@ -364,6 +364,14 @@ int labcomm_writer_ioctl(struct labcomm_writer *w, int index, const struct labcomm_signature *signature, uint32_t ioctl_action, va_list args); +int labcomm_internal_encoder_type_register( + struct labcomm_encoder *e, + const struct labcomm_signature *signature); + +int labcomm_internal_encoder_type_bind( + struct labcomm_encoder *e, + const struct labcomm_signature *signature); + int labcomm_internal_encoder_register( struct labcomm_encoder *encoder, const struct labcomm_signature *signature, @@ -543,4 +551,6 @@ void labcomm_set_local_index(struct labcomm_signature *signature); /* Get the local index for a signature */ int labcomm_get_local_index(const struct labcomm_signature *s); +int labcomm_get_local_type_index(const struct labcomm_signature *s); + #endif diff --git a/lib/c/2014/labcomm_type_signature.c b/lib/c/2014/labcomm_type_signature.c new file mode 100644 index 0000000..3cb9cc3 --- /dev/null +++ b/lib/c/2014/labcomm_type_signature.c @@ -0,0 +1,128 @@ +#include "labcomm.h" +#include <string.h> // for memcmp +#include <stdio.h> // for debug printf + +/* Dump signature bytes on stdout + */ + +void labcomm_signature_print(struct labcomm_signature_data *signature) +{ + struct labcomm_signature_data *p = signature ; + while (p->length != -1) { + if (p->length) { + int i; + for ( i = 0 ; i < p->length ; i++) { + printf("%02x ", p->u.bytes[i]); + } + } else if(p->u.signature){ + labcomm_signature_print(p->u.signature->treedata); + } else { + printf("neither data nor ref, bailing out.\n"); + return; + } + p+=1; + } + printf("\n"); +} +static labcomm_bool sig_dump_checked(struct labcomm_signature_data *signature, + char *buf, int *len, int buflen); + +/* buf (out) : byte array to write signature into + len (in/out): input: buf size, out: signature length + + return TRUE if aborted due to overrun + */ +labcomm_bool labcomm_signature_dump(struct labcomm_signature_data *signature, + char *buf, int *len) +{ + int buflen = *len; + *len = 0; + return sig_dump_checked(signature, buf, len, buflen); +} + +/* internal function with bounds checking for buf. + * buflen: capacity of buf + */ +static labcomm_bool sig_dump_checked(struct labcomm_signature_data *signature, + char *buf, int *len, int buflen) +{ + struct labcomm_signature_data *p = signature; + while ( (p->length != -1) && (*len < buflen)) { + if (p->length) { + int i; + for ( i = 0 ; (i < p->length) && (*len < buflen); i++) { + *buf++ = p->u.bytes[i]; + ++*len; + } + } else if(p->u.signature){ + int tmplen=*len; + //recursing. c.f. dump() + sig_dump_checked(p->u.signature->treedata, buf, len, buflen); + int inner_len = *len-tmplen; + buf += inner_len; + } else { + //printf("neither data nor ref, bailing out.\n"); + return TRUE; + } + p+=1; + } + return (*len >= buflen); +} + +/* compare signature (flattened, if needed) to other + return TRUE if equal +*/ +labcomm_bool labcomm_signature_cmp( struct labcomm_signature_data *s1, + struct labcomm_signature_data *s2) +{ + int buflen=512; + char buf1[buflen]; + int len1=buflen; + char buf2[buflen]; + int len2=buflen; + labcomm_bool res1 = labcomm_signature_dump(s1, buf1, &len1); + labcomm_bool res2 = labcomm_signature_dump(s2, buf2, &len2); + if(res1 || res2) { + printf("WARNING: OVERRUN\n"); + return FALSE; + } else { + return(len1 == len2 && memcmp(buf1, buf2, len1)==0); + } +} +/* maps a function f(char b, struct labcomm_signature *s, void *context) + * on each byte (or type ref) in the signature. + * + * If flatten, the signature is flattened to a byte array, and the + * second argument to f is always zero. + * + * Otherwise, when a type ref is encountered, f is called with the first + * argument zero and the referenced type as the second argument. + * + * The context parameter is passed on, unaltered, to f + */ +void map_signature( void(*f)(char, const struct labcomm_signature *, void *), + void *context, + const struct labcomm_signature *signature, labcomm_bool flatten) +{ + struct labcomm_signature_data* p = signature->treedata; + while (p->length != -1) { + //fprintf(stderr, "%p %x\n", p, p->length); + if (p->length) { + int i; + for ( i = 0 ; i < p->length ; i++) { + (*f)(p->u.bytes[i], 0, context); + } + } else if (p->u.signature) { + if(p->u.signature == 0) printf("p->u.signature == null\n"); + if(flatten) { + map_signature(f, context, p->u.signature, flatten); + } else { + (*f)(0, p->u.signature, context); + } + } else { + fprintf(stderr, "neither data nor ref, bailing out.\n"); + return; + } + p+=1; + } +} diff --git a/lib/c/2014/labcomm_type_signature.h b/lib/c/2014/labcomm_type_signature.h new file mode 100644 index 0000000..44549aa --- /dev/null +++ b/lib/c/2014/labcomm_type_signature.h @@ -0,0 +1,155 @@ +#ifndef LABCOMM_TYPE_SIGNATURE_H +#define LABCOMM_TYPE_SIGNATURE_H + +//XXX move to common.h +#ifndef labcomm_bool +#define labcomm_bool char +#define TRUE 1 +#define FALSE 0 +#endif + +/* + * Signature entry + */ +#ifndef LABCOMM_NO_TYPEDECL +#ifdef USE_UNIONS + +/* Useful for C99 and up (or GCC without -pedantic) */ + +#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ + union { \ + char *bytes; \ + struct labcomm_signature* signature; \ + } u; + +#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b } +#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[] +#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 } + +#else + +#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ + struct { \ + char *bytes; \ + const struct labcomm_signature *signature; \ + } u; + +#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } } +#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } } +#define LABCOMM_SIGDEF_END { -1, { 0, 0 } } + +#endif + +struct labcomm_signature_data { + int length; + LABCOMM_SIGDEF_BYTES_OR_SIGNATURE +}; + +#endif +struct labcomm_signature { + char *name; + int (*encoded_size)(void *); /* void* refers to sample_data */ + int size; + unsigned char *signature; + int index; +#ifndef LABCOMM_NO_TYPEDECL + int tdsize; + struct labcomm_signature_data *treedata; +#endif +#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE + int cached_encoded_size; // -1 if not initialized or type is variable size +#endif +}; + +#if 0 +/* + * Signature entry + */ + +#ifdef USE_UNIONS + +/* Useful for C99 and up (or GCC without -pedantic) */ + +#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ + union { \ + char *bytes; \ + struct labcomm_signature* signature; \ + } u; + +#define LABCOMM_SIGDEF_BYTES(l, b) { l, .u.bytes=b } +#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, .u.signature=&s } // addressof, as s is pointing at the sig struct, not directly the the sig_bytes[] +#define LABCOMM_SIGDEF_END { -1, .u.bytes=0 } + +#else + +#define LABCOMM_SIGDEF_BYTES_OR_SIGNATURE \ + struct { \ + char *bytes; \ + struct labcomm_signature *signature; \ + } u; + +#define LABCOMM_SIGDEF_BYTES(l, b) { l, { b, 0 } } +#define LABCOMM_SIGDEF_SIGNATURE(s) { 0, { 0, &s } } +#define LABCOMM_SIGDEF_END { -1, { 0, 0 } } + +#endif + +struct labcomm_signature_data { + int length; + LABCOMM_SIGDEF_BYTES_OR_SIGNATURE +}; + +struct labcomm_signature { + int type; + char *name; + int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample * + struct { + int size; + unsigned char *data; + } flat; + struct { + int size; + struct labcomm_signature_data *data; + } tree; + int index; +#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE + int cached_encoded_size; // -1 if not initialized or type is variable size +#endif +}; +#endif +/* + * functions + */ + + +/* Dump signature bytes on stdout + */ + +void labcomm_signature_print(struct labcomm_signature_data *signature); + +/* compare signatures (flattened, if needed) to other +* return TRUE if equal +*/ +labcomm_bool labcomm_signature_cmp( struct labcomm_signature_data *s2, + struct labcomm_signature_data *s1); + +/* flatten and dump signature to a byte array. + * buf (out) : byte array to write signature into + * len (in/out): input: buf size, out: signature length + * + * return TRUE if aborted due to overrun + */ +labcomm_bool labcomm_signature_dump(struct labcomm_signature_data *signature, + char *buf, int *len); + +/* maps function f on each byte in the signature + * if flatten, the signature is flattened, and the second argument of + * f is always zero + * otherwise, when a type ref is encountered, f is called with the first + * argument zero and the type ref as the second argument. + */ +void map_signature( void(*f)(char, const struct labcomm_signature *, void *), + void *context, + const struct labcomm_signature *signature, labcomm_bool flatten); + +#endif -- GitLab