You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2017/11/20 20:33:28 UTC
[31/46] celix git commit: CELIX-417: Initial refactoring for CMake
usage
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/public/include/json_rpc.h
----------------------------------------------------------------------
diff --git a/dfi/public/include/json_rpc.h b/dfi/public/include/json_rpc.h
deleted file mode 100644
index 1cc1464..0000000
--- a/dfi/public/include/json_rpc.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements. See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership. The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-#ifndef __JSON_RPC_H_
-#define __JSON_RPC_H_
-
-#include <jansson.h>
-#include "dfi_log_util.h"
-#include "dyn_type.h"
-#include "dyn_function.h"
-#include "dyn_interface.h"
-
-//logging
-DFI_SETUP_LOG_HEADER(jsonRpc);
-
-int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, char **out);
-
-
-int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *args[], char **out);
-int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]);
-
-#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/public/include/json_serializer.h
----------------------------------------------------------------------
diff --git a/dfi/public/include/json_serializer.h b/dfi/public/include/json_serializer.h
deleted file mode 100644
index 2f91f2b..0000000
--- a/dfi/public/include/json_serializer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements. See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership. The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-#ifndef __JSON_SERIALIZER_H_
-#define __JSON_SERIALIZER_H_
-
-#include <jansson.h>
-#include "dfi_log_util.h"
-#include "dyn_type.h"
-#include "dyn_function.h"
-#include "dyn_interface.h"
-
-//logging
-DFI_SETUP_LOG_HEADER(jsonSerializer);
-
-int jsonSerializer_deserialize(dyn_type *type, const char *input, void **result);
-int jsonSerializer_deserializeJson(dyn_type *type, json_t *input, void **result);
-
-int jsonSerializer_serialize(dyn_type *type, const void* input, char **output);
-int jsonSerializer_serializeJson(dyn_type *type, const void* input, json_t **out);
-
-#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/dyn_common.c
----------------------------------------------------------------------
diff --git a/dfi/src/dyn_common.c b/dfi/src/dyn_common.c
new file mode 100644
index 0000000..ea8f425
--- /dev/null
+++ b/dfi/src/dyn_common.c
@@ -0,0 +1,151 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "dyn_common.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#if defined(BSD) || defined(__APPLE__) || defined(ANDROID)
+#include "open_memstream.h"
+#include "fmemopen.h"
+#endif
+
+static const int OK = 0;
+static const int ERROR = 1;
+
+DFI_SETUP_LOG(dynCommon)
+
+static bool dynCommon_charIn(int c, const char *acceptedChars);
+
+int dynCommon_parseName(FILE *stream, char **result) {
+ return dynCommon_parseNameAlsoAccept(stream, NULL, result);
+}
+
+int dynCommon_parseNameAlsoAccept(FILE *stream, const char *acceptedChars, char **result) {
+ int status = OK;
+
+ char *buf = NULL;
+ size_t size = 0;
+ int strLen = 0;
+ FILE *name = open_memstream(&buf, &size);
+
+ if (name != NULL) {
+ int c = getc(stream);
+ while (isalnum(c) || c == '_' || dynCommon_charIn(c, acceptedChars)) {
+ fputc(c, name);
+ c = getc(stream);
+ strLen += 1;
+ }
+ fflush(name);
+ fclose(name);
+ ungetc(c, stream);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error creating mem stream for name. %s", strerror(errno));
+ }
+
+ if (status == OK) {
+ if (strLen == 0) {
+ status = ERROR;
+ LOG_ERROR("Parsed empty name");
+ }
+ }
+
+ if (status == OK) {
+ LOG_DEBUG("Parsed name '%s'", buf);
+ *result = buf;
+ } else if (buf != NULL) {
+ free(buf);
+ }
+
+ return status;
+}
+
+int dynCommon_parseNameValue(FILE *stream, char **outName, char **outValue) {
+ int status;
+ char *name = NULL;
+ char *value = NULL;
+
+ status = dynCommon_parseName(stream, &name);
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+ if (status == OK) {
+ const char *valueAcceptedChars = ".<>{}[]?;:~!@#$%^&*()_+-=,./\\'\"";
+
+ status = dynCommon_parseNameAlsoAccept(stream, valueAcceptedChars, &value); //NOTE use different more lenient function e.g. only stop at '\n' ?
+ }
+
+ if (status == OK) {
+ *outName = name;
+ *outValue = value;
+ } else {
+ if (name != NULL) {
+ free(name);
+ }
+ if (value != NULL) {
+ free(value);
+ }
+ }
+ return status;
+}
+
+int dynCommon_eatChar(FILE *stream, int expected) {
+ int status = OK;
+ long loc = ftell(stream);
+ int c = fgetc(stream);
+ if (c != expected) {
+ status = ERROR;
+ LOG_ERROR("Error parsing, expected token '%c' got '%c' at position %li", expected, c, loc);
+ }
+ return status;
+}
+
+static bool dynCommon_charIn(int c, const char *acceptedChars) {
+ bool status = false;
+ if (acceptedChars != NULL) {
+ int i;
+ for (i = 0; acceptedChars[i] != '\0'; i += 1) {
+ if (c == acceptedChars[i]) {
+ status = true;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+void dynCommon_clearNamValHead(struct namvals_head *head) {
+ struct namval_entry *entry = TAILQ_FIRST(head);
+ while (entry != NULL) {
+ struct namval_entry *tmp = entry;
+
+ if (entry->name != NULL) {
+ free(entry->name);
+ }
+ if (entry->value != NULL) {
+ free(entry->value);
+ }
+ entry = TAILQ_NEXT(entry, entries);
+ free(tmp);
+ }
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/dyn_function.c
----------------------------------------------------------------------
diff --git a/dfi/src/dyn_function.c b/dfi/src/dyn_function.c
new file mode 100644
index 0000000..615ad16
--- /dev/null
+++ b/dfi/src/dyn_function.c
@@ -0,0 +1,331 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "dyn_function.h"
+
+#include <strings.h>
+#include <stdlib.h>
+#include <ffi.h>
+
+#include "dyn_common.h"
+
+struct _dyn_function_type {
+ char *name;
+ struct types_head *refTypes; //NOTE not owned
+ TAILQ_HEAD(,_dyn_function_argument_type) arguments;
+ ffi_type **ffiArguments;
+ dyn_type *funcReturn;
+ ffi_cif cif;
+
+ //closure part
+ ffi_closure *ffiClosure;
+ void (*fn)(void);
+ void *userData;
+ void (*bind)(void *userData, void *args[], void *ret);
+};
+
+typedef struct _dyn_function_argument_type dyn_function_argument_type;
+struct _dyn_function_argument_type {
+ int index;
+ char *name;
+ enum dyn_function_argument_meta argumentMeta;
+ dyn_type *type;
+ TAILQ_ENTRY(_dyn_function_argument_type) entries;
+};
+
+static const int OK = 0;
+static const int MEM_ERROR = 1;
+static const int PARSE_ERROR = 2;
+static const int ERROR = 2;
+
+DFI_SETUP_LOG(dynFunction)
+
+static int dynFunction_initCif(dyn_function_type *dynFunc);
+static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descriptor);
+static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData);
+
+extern ffi_type * dynType_ffiType(dyn_type *type);
+
+int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_function_type **out) {
+ int status = OK;
+ dyn_function_type *dynFunc = NULL;
+ LOG_DEBUG("Creating dyn function", descriptor);
+
+ dynFunc = calloc(1, sizeof(*dynFunc));
+
+ if (dynFunc != NULL) {
+ TAILQ_INIT(&dynFunc->arguments);
+ dynFunc->refTypes = refTypes;
+ status = dynFunction_parseDescriptor(dynFunc, descriptor);
+ if (status == 0) {
+ int rc = dynFunction_initCif(dynFunc);
+ if (rc != 0) {
+ LOG_ERROR("Error initializing cif");
+ status = ERROR;
+ }
+ }
+ } else {
+ LOG_ERROR("Error allocationg memory for dyn functipn\n");
+ status = MEM_ERROR;
+ }
+
+ if (status == OK) {
+ dyn_function_argument_type *arg = NULL;
+ TAILQ_FOREACH(arg, &dynFunc->arguments, entries) {
+ const char *meta = dynType_getMetaInfo(arg->type, "am");
+ if (meta == NULL) {
+ arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD;
+ } else if (strcmp(meta, "handle") == 0) {
+ arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__HANDLE;
+ } else if (strcmp(meta, "pre") == 0) {
+ arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT;
+ } else if (strcmp(meta, "out") == 0) {
+ arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__OUTPUT;
+ } else {
+ LOG_WARNING("unknown argument meta '%s' encountered", meta);
+ arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD;
+ }
+ }
+ }
+
+ if (status == OK) {
+ *out = dynFunc;
+ } else {
+ if (dynFunc != NULL) {
+ dynFunction_destroy(dynFunc);
+ }
+
+ }
+
+ return status;
+}
+
+int dynFunction_parseWithStr(const char *descriptor, struct types_head *refTypes, dyn_function_type **out) {
+ int status = OK;
+ FILE *stream = fmemopen((char *)descriptor, strlen(descriptor), "r");
+ if (stream != NULL) {
+ status = dynFunction_parse(stream, refTypes, out);
+ fclose(stream);
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error creating mem stream for descriptor string. %s", strerror(errno));
+ }
+ return status;
+}
+
+static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descriptor) {
+ int status = OK;
+ char *name = NULL;
+
+ status = dynCommon_parseName(descriptor, &name);
+
+ if (status == OK) {
+ dynFunc->name = name;
+ }
+
+ if (status == OK) {
+ int c = fgetc(descriptor);
+ if ( c != '(') {
+ status = PARSE_ERROR;
+ LOG_ERROR("Expected '(' token got '%c'", c);
+ }
+ }
+
+ int nextChar = fgetc(descriptor);
+ int index = 0;
+ dyn_type *type = NULL;
+ char argName[32];
+ while (nextChar != ')' && status == 0) {
+ ungetc(nextChar, descriptor);
+ type = NULL;
+
+ dyn_function_argument_type *arg = NULL;
+
+ status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &type);
+ if (status == OK) {
+ arg = calloc(1, sizeof(*arg));
+ if (arg != NULL) {
+ arg->index = index;
+ arg->type = type;
+ snprintf(argName, 32, "arg%04i", index);
+ arg->name = strdup(argName);
+
+ index += 1;
+ } else {
+ LOG_ERROR("Error allocating memory");
+ status = MEM_ERROR;
+ }
+ }
+
+ if (status == OK) {
+ TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries);
+ }
+
+ nextChar = fgetc(descriptor);
+ }
+
+ if (status == 0) {
+ status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &dynFunc->funcReturn);
+ }
+
+ return status;
+}
+
+enum dyn_function_argument_meta dynFunction_argumentMetaForIndex(dyn_function_type *dynFunc, int argumentNr) {
+ enum dyn_function_argument_meta result = 0;
+ dyn_function_argument_type *arg = NULL;
+ int index = 0;
+ TAILQ_FOREACH(arg, &dynFunc->arguments, entries) {
+ if (index == argumentNr) {
+ result = arg->argumentMeta;
+ break;
+ }
+ index += 1;
+ }
+ return result;
+}
+
+
+static int dynFunction_initCif(dyn_function_type *dynFunc) {
+ int status = 0;
+
+ int count = 0;
+ dyn_function_argument_type *entry = NULL;
+ TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+ count +=1;
+ }
+
+ dynFunc->ffiArguments = calloc(count, sizeof(ffi_type*));
+
+ TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+ dynFunc->ffiArguments[entry->index] = dynType_ffiType(entry->type);
+ }
+
+ ffi_type **args = dynFunc->ffiArguments;
+ ffi_type *returnType = dynType_ffiType(dynFunc->funcReturn);
+
+ int ffiResult = ffi_prep_cif(&dynFunc->cif, FFI_DEFAULT_ABI, count, returnType, args);
+ if (ffiResult != FFI_OK) {
+ status = 1;
+ }
+
+ return status;
+}
+
+void dynFunction_destroy(dyn_function_type *dynFunc) {
+ if (dynFunc != NULL) {
+ if (dynFunc->funcReturn != NULL) {
+ dynType_destroy(dynFunc->funcReturn);
+ }
+ if (dynFunc->ffiClosure != NULL) {
+ ffi_closure_free(dynFunc->ffiClosure);
+ }
+ if (dynFunc->name != NULL) {
+ free(dynFunc->name);
+ }
+ if (dynFunc->ffiArguments != NULL) {
+ free(dynFunc->ffiArguments);
+ }
+
+ dyn_function_argument_type *entry = NULL;
+ dyn_function_argument_type *tmp = NULL;
+ entry = TAILQ_FIRST(&dynFunc->arguments);
+ while (entry != NULL) {
+ if (entry->name != NULL) {
+ free(entry->name);
+ }
+ dynType_destroy(entry->type);
+ tmp = entry;
+ entry = TAILQ_NEXT(entry, entries);
+ free(tmp);
+ }
+
+ free(dynFunc);
+ }
+}
+
+int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnValue, void **argValues) {
+ ffi_call(&dynFunc->cif, fn, returnValue, argValues);
+ return 0;
+}
+
+static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) {
+ dyn_function_type *dynFunc = userData;
+ dynFunc->bind(dynFunc->userData, args, ret);
+}
+
+int dynFunction_createClosure(dyn_function_type *dynFunc, void (*bind)(void *, void **, void*), void *userData, void(**out)(void)) {
+ int status = 0;
+ void (*fn)(void);
+ dynFunc->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&fn);
+ if (dynFunc->ffiClosure != NULL) {
+ int rc = ffi_prep_closure_loc(dynFunc->ffiClosure, &dynFunc->cif, dynFunction_ffiBind, dynFunc, fn);
+ if (rc != FFI_OK) {
+ status = 1;
+ }
+ } else {
+ status = 2;
+ }
+
+ if (status == 0) {
+ dynFunc->userData = userData;
+ dynFunc->bind = bind;
+ dynFunc->fn = fn;
+ *out =fn;
+ }
+
+ return status;
+}
+
+int dynFunction_getFnPointer(dyn_function_type *dynFunc, void (**fn)(void)) {
+ int status = 0;
+ if (dynFunc != NULL && dynFunc->fn != NULL) {
+ (*fn) = dynFunc->fn;
+ } else {
+ status = 1;
+ }
+ return status;
+}
+
+int dynFunction_nrOfArguments(dyn_function_type *dynFunc) {
+ int count = 0;
+ dyn_function_argument_type *entry = NULL;
+ TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+ count += 1;
+ }
+ return count;
+}
+
+dyn_type *dynFunction_argumentTypeForIndex(dyn_function_type *dynFunc, int argumentNr) {
+ dyn_type *result = NULL;
+ int index = 0;
+ dyn_function_argument_type *entry = NULL;
+ TAILQ_FOREACH(entry, &dynFunc->arguments, entries) {
+ if (index == argumentNr) {
+ result = entry->type;
+ break;
+ }
+ index +=1;
+ }
+ return result;
+}
+
+dyn_type * dynFunction_returnType(dyn_function_type *dynFunction) {
+ return dynFunction->funcReturn;
+}
+
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/dyn_interface.c
----------------------------------------------------------------------
diff --git a/dfi/src/dyn_interface.c b/dfi/src/dyn_interface.c
new file mode 100644
index 0000000..63aafac
--- /dev/null
+++ b/dfi/src/dyn_interface.c
@@ -0,0 +1,444 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "dyn_interface.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dyn_interface.h"
+
+DFI_SETUP_LOG(dynInterface);
+
+struct _dyn_interface_type {
+ struct namvals_head header;
+ struct namvals_head annotations;
+ struct types_head types;
+ struct methods_head methods;
+ version_pt version;
+};
+
+static const int OK = 0;
+static const int ERROR = 1;
+
+static int dynInterface_parseSection(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseAnnotations(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseHeader(dyn_interface_type *intf, FILE *stream);
+static int dynInterface_parseNameValueSection(dyn_interface_type *intf, FILE *stream, struct namvals_head *head);
+static int dynInterface_checkInterface(dyn_interface_type *intf);
+static int dynInterface_getEntryForHead(struct namvals_head *head, const char *name, char **value);
+
+int dynInterface_parse(FILE *descriptor, dyn_interface_type **out) {
+ int status = OK;
+
+ dyn_interface_type *intf = calloc(1, sizeof(*intf));
+ if (intf != NULL) {
+ TAILQ_INIT(&intf->header);
+ TAILQ_INIT(&intf->annotations);
+ TAILQ_INIT(&intf->types);
+ TAILQ_INIT(&intf->methods);
+
+ char peek = (char)fgetc(descriptor);
+ while (peek == ':') {
+ ungetc(peek, descriptor);
+ status = dynInterface_parseSection(intf, descriptor);
+ if (status == OK) {
+ peek = (char)fgetc(descriptor);
+ } else {
+ break;
+ }
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(descriptor, EOF);
+ }
+
+ if (status == OK) {
+ status = dynInterface_checkInterface(intf);
+ }
+
+ if(status==OK){ /* We are sure that version field is present in the header */
+ char* version=NULL;
+ dynInterface_getVersionString(intf,&version);
+ if(version!=NULL){
+ status = (version_createVersionFromString(version,&(intf->version)) == CELIX_SUCCESS)?OK:ERROR;
+ }
+ if(status==ERROR){
+ LOG_ERROR("Invalid version (%s) in parsed descriptor\n",version);
+ }
+ }
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for dynamic interface\n");
+ }
+
+ if (status == OK) {
+ *out = intf;
+ } else if (intf != NULL) {
+ dynInterface_destroy(intf);
+ }
+ return status;
+}
+
+static int dynInterface_checkInterface(dyn_interface_type *intf) {
+ int status = OK;
+
+ //check header section
+ if (status == OK) {
+ bool foundType = false;
+ bool foundVersion = false;
+ bool foundName = false;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &intf->header, entries) {
+ if (strcmp(entry->name, "type") == 0) {
+ foundType = true;
+ } else if (strcmp(entry->name, "version") == 0) {
+ foundVersion = true;
+ } else if (strcmp(entry->name, "name") == 0) {
+ foundName = true;
+ }
+ }
+
+ if (!foundType || !foundVersion || !foundName) {
+ status = ERROR;
+ LOG_ERROR("Parse Error. There must be a header section with a type, version and name entry");
+ }
+
+ struct method_entry *mEntry = NULL;
+ TAILQ_FOREACH(mEntry, &intf->methods, entries) {
+ dyn_type *type = dynFunction_returnType(mEntry->dynFunc);
+ int descriptor = dynType_descriptorType(type);
+ if (descriptor != 'N') {
+ status = ERROR;
+ LOG_ERROR("Parse Error. Only method with a return type 'N' (native int) are supported. Got return type '%c'\n", descriptor);
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+static int dynInterface_parseSection(dyn_interface_type *intf, FILE *stream) {
+ int status = OK;
+ char *sectionName = NULL;
+
+ status = dynCommon_eatChar(stream, ':');
+
+ if (status == OK) {
+ status = dynCommon_parseName(stream, §ionName);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ if (status == OK) {
+ if (strcmp("header", sectionName) == 0) {
+ status = dynInterface_parseHeader(intf, stream);
+ } else if (strcmp("annotations", sectionName) == 0) {
+ status = dynInterface_parseAnnotations(intf, stream);
+ } else if (strcmp("types", sectionName) == 0) {
+ status = dynInterface_parseTypes(intf, stream);
+ } else if (strcmp("methods", sectionName) == 0) {
+ status = dynInterface_parseMethods(intf, stream);
+ } else {
+ status = ERROR;
+ LOG_ERROR("unsupported section '%s'", sectionName);
+ }
+ }
+
+ if (sectionName != NULL) {
+ free(sectionName);
+ }
+
+ return status;
+}
+
+static int dynInterface_parseHeader(dyn_interface_type *intf, FILE *stream) {
+ return dynInterface_parseNameValueSection(intf, stream, &intf->header);
+}
+
+static int dynInterface_parseAnnotations(dyn_interface_type *intf, FILE *stream) {
+ return dynInterface_parseNameValueSection(intf, stream, &intf->annotations);
+}
+
+static int dynInterface_parseNameValueSection(dyn_interface_type *intf, FILE *stream, struct namvals_head *head) {
+ int status = OK;
+
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name;
+ char *value;
+ status = dynCommon_parseNameValue(stream, &name, &value);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct namval_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->name = name;
+ entry->value = value;
+ TAILQ_INSERT_TAIL(head, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for namval entry");
+ }
+ }
+
+ if (status != OK) {
+ if (name != NULL) {
+ free(name);
+ }
+ if (value != NULL) {
+ free(value);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream) {
+ int status = OK;
+
+ //expected input (Name)=<Type>\n
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name;
+ status = dynCommon_parseName(stream, &name);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+
+ dyn_type *type = NULL;
+ if (status == OK) {
+ dynType_parse(stream, name, &intf->types, &type);
+ }
+ if (name != NULL) {
+ free(name);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct type_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->type = type;
+ TAILQ_INSERT_TAIL(&intf->types, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for type entry");
+ }
+ }
+
+ if (status != OK) {
+ if (type != NULL) {
+ dynType_destroy(type);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream) {
+ int status = OK;
+
+ //expected input (Name)=<Method>\n
+ int peek = fgetc(stream);
+ int index = 0;
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *id;
+ status = dynCommon_parseNameAlsoAccept(stream, ".();[{}/", &id);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+
+
+ dyn_function_type *func = NULL;
+ if (status == OK) {
+ status = dynFunction_parse(stream, &intf->types, &func);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct method_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->index = index++;
+ entry->id = id;
+ entry->dynFunc = func;
+ entry->name = strndup(id, 1024);
+ if (entry->name != NULL) {
+ int i;
+ for (i = 0; i < 1024; i += 1) {
+ if (entry->name[i] == '\0') {
+ break;
+ } else if (entry->name[i] == '(') {
+ entry->name[i] = '\0';
+ break;
+ }
+ }
+ }
+ TAILQ_INSERT_TAIL(&intf->methods, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for method entry");
+ }
+ }
+
+ if (status != OK) {
+ if (id != NULL) {
+ free(id);
+ }
+ if (func != NULL) {
+ dynFunction_destroy(func);
+ //TODO free strIdentier, name
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+void dynInterface_destroy(dyn_interface_type *intf) {
+ if (intf != NULL) {
+ dynCommon_clearNamValHead(&intf->header);
+ dynCommon_clearNamValHead(&intf->annotations);
+
+ struct method_entry *mInfo = TAILQ_FIRST(&intf->methods);
+ while (mInfo != NULL) {
+ struct method_entry *mTmp = mInfo;
+ mInfo = TAILQ_NEXT(mInfo, entries);
+
+ if (mTmp->id != NULL) {
+ free(mTmp->id);
+ }
+ if (mTmp->name != NULL) {
+ free(mTmp->name);
+ }
+ if (mTmp->dynFunc != NULL) {
+ dynFunction_destroy(mTmp->dynFunc);
+ }
+ free(mTmp);
+ }
+
+ struct type_entry *tInfo = TAILQ_FIRST(&intf->types);
+ while (tInfo != NULL) {
+ struct type_entry *tmp = tInfo;
+ tInfo = TAILQ_NEXT(tInfo, entries);
+ dynType_destroy(tmp->type);
+ free(tmp);
+ }
+
+ if(intf->version!=NULL){
+ version_destroy(intf->version);
+ }
+
+ free(intf);
+ }
+}
+
+int dynInterface_getName(dyn_interface_type *intf, char **out) {
+ return dynInterface_getEntryForHead(&intf->header, "name", out);
+}
+
+int dynInterface_getVersion(dyn_interface_type* intf , version_pt* version){
+ *version = intf->version;
+ if(*version==NULL){
+ return ERROR;
+ }
+ return OK;
+}
+
+int dynInterface_getVersionString(dyn_interface_type *intf, char **version) {
+ return dynInterface_getEntryForHead(&intf->header, "version", version);
+}
+
+int dynInterface_getHeaderEntry(dyn_interface_type *intf, const char *name, char **value) {
+ return dynInterface_getEntryForHead(&intf->header, name, value);
+}
+
+int dynInterface_getAnnotationEntry(dyn_interface_type *intf, const char *name, char **value) {
+ return dynInterface_getEntryForHead(&intf->annotations, name, value);
+}
+
+static int dynInterface_getEntryForHead(struct namvals_head *head, const char *name, char **out) {
+ int status = OK;
+ char *value = NULL;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, head, entries) {
+ if (strcmp(name, entry->name) == 0) {
+ value = entry->value;
+ break;
+ }
+ }
+ if (value != NULL) {
+ *out = value;
+ } else {
+ status = ERROR;
+ LOG_WARNING("Cannot find '%s' in list", name);
+ }
+ return status;
+}
+
+int dynInterface_methods(dyn_interface_type *intf, struct methods_head **list) {
+ int status = OK;
+ *list = &intf->methods;
+ return status;
+}
+
+int dynInterface_nrOfMethods(dyn_interface_type *intf) {
+ int count = 0;
+ struct method_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &intf->methods, entries) {
+ count +=1;
+ }
+ return count;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/dyn_message.c
----------------------------------------------------------------------
diff --git a/dfi/src/dyn_message.c b/dfi/src/dyn_message.c
new file mode 100644
index 0000000..652be83
--- /dev/null
+++ b/dfi/src/dyn_message.c
@@ -0,0 +1,358 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "dyn_message.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+
+DFI_SETUP_LOG(dynMessage);
+
+struct _dyn_message_type {
+ struct namvals_head header;
+ struct namvals_head annotations;
+ struct types_head types;
+ dyn_type *msgType;
+ version_pt msgVersion;
+};
+
+static const int OK = 0;
+static const int ERROR = 1;
+
+static int dynMessage_parseSection(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseNameValueSection(dyn_message_type *msg, FILE *stream, struct namvals_head *head);
+static int dynMessage_checkMessage(dyn_message_type *msg);
+static int dynMessage_getEntryForHead(struct namvals_head *head, const char *name, char **value);
+
+int dynMessage_parse(FILE *descriptor, dyn_message_type **out) {
+ int status = OK;
+
+ dyn_message_type *msg = calloc(1, sizeof(*msg));
+ if (msg != NULL) {
+ TAILQ_INIT(&msg->header);
+ TAILQ_INIT(&msg->annotations);
+ TAILQ_INIT(&msg->types);
+
+ char peek = (char)fgetc(descriptor);
+ while (peek == ':') {
+ ungetc(peek, descriptor);
+ status = dynMessage_parseSection(msg, descriptor);
+ if (status == OK) {
+ peek = (char)fgetc(descriptor);
+ } else {
+ break;
+ }
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(descriptor, EOF);
+ }
+
+ if (status == OK) {
+ status = dynMessage_checkMessage(msg);
+ }
+
+ if(status==OK){ /* We are sure that version field is present in the header */
+ char* version=NULL;
+ dynMessage_getVersionString(msg,&version);
+ if(version!=NULL){
+ status = (version_createVersionFromString(version,&(msg->msgVersion)) == CELIX_SUCCESS)?OK:ERROR;
+ }
+ if(status==ERROR){
+ LOG_ERROR("Invalid version (%s) in parsed descriptor\n",version);
+ }
+ }
+
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for dynamic message\n");
+ }
+
+ if (status == OK) {
+ *out = msg;
+ } else if (msg != NULL) {
+ LOG_ERROR("Error parsing msg\n");
+ dynMessage_destroy(msg);
+ }
+ return status;
+}
+
+static int dynMessage_checkMessage(dyn_message_type *msg) {
+ int status = OK;
+
+ //check header section
+ if (status == OK) {
+ bool foundType = false;
+ bool foundVersion = false;
+ bool foundName = false;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &msg->header, entries) {
+ if (strcmp(entry->name, "type") == 0) {
+ foundType = true;
+ } else if (strcmp(entry->name, "version") == 0) {
+ foundVersion = true;
+ } else if (strcmp(entry->name, "name") == 0) {
+ foundName = true;
+ }
+ }
+
+ if (!foundType || !foundVersion || !foundName) {
+ status = ERROR;
+ LOG_ERROR("Parse Error. There must be a header section with a type, version and name entry");
+ }
+ }
+
+ return status;
+}
+
+static int dynMessage_parseSection(dyn_message_type *msg, FILE *stream) {
+ int status;
+ char *sectionName = NULL;
+
+ status = dynCommon_eatChar(stream, ':');
+
+ if (status == OK) {
+ status = dynCommon_parseName(stream, §ionName);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ if (status == OK) {
+ if (strcmp("header", sectionName) == 0) {
+ status = dynMessage_parseHeader(msg, stream);
+ } else if (strcmp("annotations", sectionName) == 0) {
+ status = dynMessage_parseAnnotations(msg, stream);
+ } else if (strcmp("types", sectionName) == 0) {
+ status = dynMessage_parseTypes(msg, stream);
+ } else if (strcmp("message", sectionName) == 0) {
+ status = dynMessage_parseMessage(msg, stream);
+ } else {
+ status = ERROR;
+ LOG_ERROR("unsupported section '%s'", sectionName);
+ }
+ }
+
+ if (sectionName != NULL) {
+ free(sectionName);
+ }
+
+ return status;
+}
+
+static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream) {
+ return dynMessage_parseNameValueSection(msg, stream, &msg->header);
+}
+
+static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream) {
+ return dynMessage_parseNameValueSection(msg, stream, &msg->annotations);
+}
+
+static int dynMessage_parseNameValueSection(dyn_message_type *msg, FILE *stream, struct namvals_head *head) {
+ int status = OK;
+
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name;
+ char *value;
+ status = dynCommon_parseNameValue(stream, &name, &value);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct namval_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->name = name;
+ entry->value = value;
+ TAILQ_INSERT_TAIL(head, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for namval entry");
+ }
+ }
+
+ if (status != OK) {
+ if (name != NULL) {
+ free(name);
+ }
+ if (value != NULL) {
+ free(value);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream) {
+ int status = OK;
+
+ //expected input (Name)=<Type>\n
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name = NULL;
+ status = dynCommon_parseName(stream, &name);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+
+ dyn_type *type = NULL;
+ if (status == OK) {
+ status = dynType_parse(stream, name, &msg->types, &type);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct type_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ LOG_DEBUG("Adding type '%s' with pointer %p to types", name, type);
+ entry->type = type;
+ TAILQ_INSERT_TAIL(&msg->types, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for type entry");
+ }
+ }
+
+ if (name != NULL) {
+ free(name);
+ }
+
+ if (status != OK) {
+ if (type != NULL) {
+ dynType_destroy(type);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream) {
+ int status;
+
+ //expected input <dynType>\n
+ char *name = NULL;
+ status = dynMessage_getName(msg, &name);
+
+ if (status == OK) {
+ status = dynType_parse(stream, name, &(msg->types), &(msg->msgType));
+ }
+
+ return status;
+}
+
+void dynMessage_destroy(dyn_message_type *msg) {
+ if (msg != NULL) {
+ dynCommon_clearNamValHead(&msg->header);
+ dynCommon_clearNamValHead(&msg->annotations);
+
+ struct type_entry *tInfo = TAILQ_FIRST(&msg->types);
+ while (tInfo != NULL) {
+ struct type_entry *tmp = tInfo;
+ tInfo = TAILQ_NEXT(tInfo, entries);
+ dynType_destroy(tmp->type);
+ free(tmp);
+ }
+
+ if (msg->msgType != NULL) {
+ dynType_destroy(msg->msgType);
+ }
+
+ if(msg->msgVersion != NULL){
+ version_destroy(msg->msgVersion);
+ }
+
+ free(msg);
+ }
+}
+
+int dynMessage_getName(dyn_message_type *msg, char **out) {
+ return dynMessage_getEntryForHead(&msg->header, "name", out);
+}
+
+int dynMessage_getVersion(dyn_message_type *msg, version_pt* version){
+ *version = msg->msgVersion;
+ if(*version==NULL){
+ return ERROR;
+ }
+ return OK;
+}
+
+int dynMessage_getVersionString(dyn_message_type *msg, char **version) {
+ return dynMessage_getEntryForHead(&msg->header, "version", version);
+}
+
+int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **value) {
+ return dynMessage_getEntryForHead(&msg->header, name, value);
+}
+
+int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value) {
+ return dynMessage_getEntryForHead(&msg->annotations, name, value);
+}
+
+static int dynMessage_getEntryForHead(struct namvals_head *head, const char *name, char **out) {
+ int status = OK;
+ char *value = NULL;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, head, entries) {
+ if (strcmp(name, entry->name) == 0) {
+ value = entry->value;
+ break;
+ }
+ }
+ if (value != NULL) {
+ *out = value;
+ } else {
+ status = ERROR;
+ LOG_WARNING("Cannot find '%s' in list", name);
+ }
+ return status;
+}
+
+int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type) {
+ int status = OK;
+ *type = msg->msgType;
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/dyn_type.c
----------------------------------------------------------------------
diff --git a/dfi/src/dyn_type.c b/dfi/src/dyn_type.c
new file mode 100644
index 0000000..4fc79ff
--- /dev/null
+++ b/dfi/src/dyn_type.c
@@ -0,0 +1,1160 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "dyn_type.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ffi.h>
+
+#include "dyn_common.h"
+
+DFI_SETUP_LOG(dynType)
+
+static int dynType_parseWithStream(FILE *stream, const char *name, dyn_type *parent, struct types_head *refTypes, dyn_type **result);
+static void dynType_clear(dyn_type *type);
+static void dynType_clearComplex(dyn_type *type);
+static void dynType_clearSequence(dyn_type *type);
+static void dynType_clearTypedPointer(dyn_type *type);
+ffi_type * dynType_ffiType(dyn_type *type);
+
+static struct type_entry *dynType_allocTypeEntry(void);
+
+static ffi_type * dynType_ffiTypeFor(int c);
+static dyn_type * dynType_findType(dyn_type *type, char *name);
+static int dynType_parseAny(FILE *stream, dyn_type *type);
+static int dynType_parseComplex(FILE *stream, dyn_type *type);
+static int dynType_parseNestedType(FILE *stream, dyn_type *type);
+static int dynType_parseReference(FILE *stream, dyn_type *type);
+static int dynType_parseRefByValue(FILE *stream, dyn_type *type);
+static int dynType_parseSequence(FILE *stream, dyn_type *type);
+static int dynType_parseSimple(int c, dyn_type *type);
+static int dynType_parseTypedPointer(FILE *stream, dyn_type *type);
+static void dynType_prepCif(ffi_type *type);
+static unsigned short dynType_getOffset(dyn_type *type, int index);
+
+static void dynType_printAny(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printSequence(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printTypedPointer(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printDepth(int depth, FILE *stream);
+
+static void dynType_printTypes(dyn_type *type, FILE *stream);
+static void dynType_printComplexType(dyn_type *type, FILE *stream);
+static void dynType_printSimpleType(dyn_type *type, FILE *stream);
+
+static int dynType_parseText(FILE *stream, dyn_type *type);
+void dynType_freeComplexType(dyn_type *type, void *loc);
+void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf);
+void dynType_freeSequenceType(dyn_type *type, void *seqLoc);
+
+static int dynType_parseMetaInfo(FILE *stream, dyn_type *type);
+
+struct generic_sequence {
+ uint32_t cap;
+ uint32_t len;
+ void *buf;
+};
+
+TAILQ_HEAD(meta_properties_head, meta_entry);
+struct meta_entry {
+ char *name;
+ char *value;
+ TAILQ_ENTRY(meta_entry) entries;
+};
+
+
+struct _dyn_type {
+ char *name;
+ char descriptor;
+ int type;
+ ffi_type *ffiType;
+ dyn_type *parent;
+ struct types_head *referenceTypes; //NOTE: not owned
+ struct types_head nestedTypesHead;
+ struct meta_properties_head metaProperties;
+ union {
+ struct {
+ struct complex_type_entries_head entriesHead;
+ ffi_type structType; //dyn_type.ffiType points to this
+ dyn_type **types; //based on entriesHead for fast access
+ } complex;
+ struct {
+ ffi_type seqType; //dyn_type.ffiType points to this
+ dyn_type *itemType;
+ } sequence;
+ struct {
+ dyn_type *typedType;
+ } typedPointer;
+ struct {
+ dyn_type *ref;
+ } ref;
+ };
+};
+
+static const int OK = 0;
+static const int ERROR = 1;
+static const int MEM_ERROR = 2;
+static const int PARSE_ERROR = 3;
+
+int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type) {
+ return dynType_parseWithStream(descriptorStream, name, NULL, refTypes, type);
+}
+
+int dynType_parseWithStr(const char *descriptor, const char *name, struct types_head *refTypes, dyn_type **type) {
+ int status = OK;
+ FILE *stream = fmemopen((char *)descriptor, strlen(descriptor), "r");
+ if (stream != NULL) {
+ status = dynType_parseWithStream(stream, name, NULL, refTypes, type);
+ if (status == OK) {
+ int c = fgetc(stream);
+ if (c != '\0' && c != EOF) {
+ status = PARSE_ERROR;
+ LOG_ERROR("Expected EOF got %c", c);
+ }
+ }
+ fclose(stream);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error creating mem stream for descriptor string. %s", strerror(errno));
+ }
+ return status;
+}
+
+static int dynType_parseWithStream(FILE *stream, const char *name, dyn_type *parent, struct types_head *refTypes, dyn_type **result) {
+ int status = OK;
+ dyn_type *type = calloc(1, sizeof(*type));
+ if (type != NULL) {
+ type->parent = parent;
+ type->type = DYN_TYPE_INVALID;
+ type->referenceTypes = refTypes;
+ TAILQ_INIT(&type->nestedTypesHead);
+ TAILQ_INIT(&type->metaProperties);
+ if (name != NULL) {
+ type->name = strdup(name);
+ if (type->name == NULL) {
+ status = MEM_ERROR;
+ LOG_ERROR("Error strdup'ing name '%s'\n", name);
+ }
+ }
+ if (status == OK) {
+ status = dynType_parseAny(stream, type);
+ }
+ if (status == OK) {
+ *result = type;
+ } else {
+ dynType_destroy(type);
+ }
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for type");
+ }
+ return status;
+}
+
+static int dynType_parseAny(FILE *stream, dyn_type *type) {
+ int status = OK;
+
+ int c = fgetc(stream);
+ switch(c) {
+ case 'T' :
+ status = dynType_parseNestedType(stream, type);
+ if (status == OK) {
+ status = dynType_parseAny(stream, type);
+ }
+ break;
+ case 'L' :
+ status = dynType_parseReference(stream, type);
+ break;
+ case 'l' :
+ status = dynType_parseRefByValue(stream, type);
+ break;
+ case '{' :
+ status = dynType_parseComplex(stream, type);
+ break;
+ case '[' :
+ status = dynType_parseSequence(stream, type);
+ break;
+ case '*' :
+ status = dynType_parseTypedPointer(stream, type);
+ break;
+ case 't' :
+ status = dynType_parseText(stream, type);
+ break;
+ case '#' :
+ status = dynType_parseMetaInfo(stream, type);
+ if (status == OK) {
+ status = dynType_parseAny(stream, type);
+ }
+ break;
+ default :
+ status = dynType_parseSimple(c, type);
+ break;
+ }
+
+ return status;
+}
+
+static int dynType_parseMetaInfo(FILE *stream, dyn_type *type) {
+ int status = OK;
+ char *name = NULL;
+ char *value = NULL;
+
+ struct meta_entry *entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ status = ERROR;
+ }
+
+ if (status == OK) {
+ status = dynCommon_parseName(stream, &name);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+
+ if (status == OK) {
+ status = dynCommon_parseName(stream, &value);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, ';');
+ }
+
+ if (status == OK) {
+ entry->name = name;
+ entry->value = value;
+ TAILQ_INSERT_TAIL(&type->metaProperties, entry, entries);
+ LOG_DEBUG("Added meta properties '%s':'%s'", name, value)
+ } else {
+ free(name);
+ free(value);
+ free(entry);
+ }
+
+ return status;
+}
+
+static int dynType_parseText(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_TEXT;
+ type->descriptor = 't';
+ type->ffiType = &ffi_type_pointer;
+ return status;
+}
+
+static int dynType_parseComplex(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_COMPLEX;
+ type->descriptor = '{';
+ type->ffiType = &type->complex.structType;
+ TAILQ_INIT(&type->complex.entriesHead);
+
+ int c = fgetc(stream);
+ struct complex_type_entry *entry = NULL;
+ while (c != ' ' && c != '}') {
+ ungetc(c,stream);
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->type = calloc(1, sizeof(*entry->type));
+ }
+ if (entry != NULL && entry->type != NULL) {
+ entry->type->parent = type;
+ entry->type->type = DYN_TYPE_INVALID;
+ TAILQ_INIT(&entry->type->nestedTypesHead);
+ TAILQ_INIT(&entry->type->metaProperties);
+ TAILQ_INSERT_TAIL(&type->complex.entriesHead, entry, entries);
+ status = dynType_parseAny(stream, entry->type);
+ } else {
+ free(entry);
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for type");
+ }
+
+ if (status != OK) {
+ break;
+ }
+
+ c = fgetc(stream);
+ }
+
+
+ if (status == OK) {
+ entry = TAILQ_FIRST(&type->complex.entriesHead);
+ char *name = NULL;
+ while (c == ' ' && entry != NULL) {
+ status = dynCommon_parseName(stream, &name);
+ if (status == OK) {
+ entry->name = name;
+ entry = TAILQ_NEXT(entry, entries);
+ } else {
+ break;
+ }
+ c = getc(stream);
+ }
+ }
+
+ int count = 0;
+ if (status == OK) {
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ count +=1;
+ }
+ }
+
+ if (status == OK) {
+ type->complex.structType.type = FFI_TYPE_STRUCT;
+ type->complex.structType.elements = calloc(count + 1, sizeof(ffi_type*));
+ if (type->complex.structType.elements != NULL) {
+ type->complex.structType.elements[count] = NULL;
+ int index = 0;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ type->complex.structType.elements[index++] = dynType_ffiType(entry->type);
+ }
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for elements")
+ }
+ }
+
+ if (status == OK) {
+ type->complex.types = calloc(count, sizeof(dyn_type *));
+ if (type->complex.types != NULL) {
+ int index = 0;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ type->complex.types[index++] = entry->type;
+ }
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for type")
+ }
+ }
+
+ if (status == OK) {
+ dynType_prepCif(type->ffiType);
+ }
+
+
+ return status;
+}
+
+static int dynType_parseNestedType(FILE *stream, dyn_type *type) {
+ int status = OK;
+ char *name = NULL;
+ struct type_entry *entry = NULL;
+
+ entry = dynType_allocTypeEntry();
+ if (entry != NULL) {
+ entry->type->parent = type;
+ entry->type->type = DYN_TYPE_INVALID;
+ TAILQ_INIT(&entry->type->nestedTypesHead);
+ TAILQ_INIT(&entry->type->metaProperties);
+ TAILQ_INSERT_TAIL(&type->nestedTypesHead, entry, entries);
+ status = dynCommon_parseName(stream, &name);
+ entry->type->name = name;
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating entry");
+ }
+
+ if (status == OK) {
+ int c = fgetc(stream);
+ if (c != '=') {
+ status = PARSE_ERROR;
+ LOG_ERROR("Error parsing nested type expected '=' got '%c'", c);
+ }
+ }
+
+ if (status == OK) {
+ status = dynType_parseAny(stream, entry->type);
+ int c = fgetc(stream);
+ if (c != ';') {
+ status = PARSE_ERROR;
+ LOG_ERROR("Expected ';' got '%c'\n", c);
+ }
+ }
+
+ return status;
+}
+
+static int dynType_parseReference(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_TYPED_POINTER;
+ type->descriptor = '*';
+
+ type->ffiType = &ffi_type_pointer;
+ type->typedPointer.typedType = NULL;
+
+ dyn_type *subType = calloc(1, sizeof(*subType));
+
+ if (subType != NULL) {
+ type->typedPointer.typedType = subType;
+ subType->parent = type;
+ subType->type = DYN_TYPE_INVALID;
+ TAILQ_INIT(&subType->nestedTypesHead);
+ TAILQ_INIT(&subType->metaProperties);
+ status = dynType_parseRefByValue(stream, subType);
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for subtype\n");
+ }
+
+ return status;
+}
+
+static int dynType_parseRefByValue(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_REF;
+ type->descriptor = 'l';
+
+ char *name = NULL;
+ status = dynCommon_parseName(stream, &name);
+ if (status == OK) {
+ dyn_type *ref = dynType_findType(type, name);
+ if (ref != NULL) {
+ type->ref.ref = ref;
+ } else {
+ status = PARSE_ERROR;
+ LOG_ERROR("Error cannot find type '%s'", name);
+ }
+ free(name);
+ }
+
+ if (status ==OK) {
+ int c = fgetc(stream);
+ if (c != ';') {
+ status = PARSE_ERROR;
+ LOG_ERROR("Error expected ';' got '%c'", c);
+ }
+ }
+
+ return status;
+}
+
+static struct type_entry *dynType_allocTypeEntry(void) {
+ struct type_entry *entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->type = calloc(1, sizeof(*entry->type));
+ if (entry->type == NULL) {
+ free(entry);
+ entry = NULL;
+ }
+ }
+ return entry;
+}
+
+static ffi_type *seq_types[] = {&ffi_type_uint32, &ffi_type_uint32, &ffi_type_pointer, NULL};
+
+static int dynType_parseSequence(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_SEQUENCE;
+ type->descriptor = '[';
+
+ type->sequence.seqType.elements = seq_types;
+ type->sequence.seqType.type = FFI_TYPE_STRUCT;
+ type->sequence.seqType.size = 0;
+ type->sequence.seqType.alignment = 0;
+
+ status = dynType_parseWithStream(stream, NULL, type, NULL, &type->sequence.itemType);
+
+ if (status == OK) {
+ type->ffiType = &type->sequence.seqType;
+ dynType_prepCif(&type->sequence.seqType);
+ }
+
+ return status;
+}
+
+static int dynType_parseSimple(int c, dyn_type *type) {
+ int status = OK;
+ ffi_type *ffiType = dynType_ffiTypeFor(c);
+ if (ffiType != NULL) {
+ type->type = DYN_TYPE_SIMPLE;
+ type->descriptor = c;
+ type->ffiType = ffiType;
+ } else {
+ status = PARSE_ERROR;
+ LOG_ERROR("Error unsupported type '%c'", c);
+ }
+
+ return status;
+}
+
+static int dynType_parseTypedPointer(FILE *stream, dyn_type *type) {
+ int status = OK;
+ type->type = DYN_TYPE_TYPED_POINTER;
+ type->descriptor = '*';
+ type->ffiType = &ffi_type_pointer;
+
+ status = dynType_parseWithStream(stream, NULL, type, NULL, &type->typedPointer.typedType);
+
+ return status;
+}
+
+static void dynType_prepCif(ffi_type *type) {
+ ffi_cif cif;
+ ffi_type *args[1];
+ args[0] = type;
+ ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
+}
+
+void dynType_destroy(dyn_type *type) {
+ if (type != NULL) {
+ dynType_clear(type);
+ free(type);
+ }
+}
+
+static void dynType_clear(dyn_type *type) {
+ struct type_entry *entry = TAILQ_FIRST(&type->nestedTypesHead);
+ struct type_entry *tmp = NULL;
+ while (entry != NULL) {
+ tmp = entry;
+ entry = TAILQ_NEXT(entry, entries);
+ if (tmp->type != NULL) {
+ dynType_destroy(tmp->type);
+ tmp->type = NULL;
+ }
+ free(tmp);
+ }
+
+ struct meta_entry *mEntry = TAILQ_FIRST(&type->metaProperties);;
+ struct meta_entry *next = NULL;
+ while (mEntry != NULL) {
+ next = TAILQ_NEXT(mEntry, entries);
+ if (mEntry != NULL) {
+ free(mEntry->name);
+ free(mEntry->value);
+ free(mEntry);
+ }
+ mEntry = next;
+ }
+
+ switch (type->type) {
+ case DYN_TYPE_COMPLEX :
+ dynType_clearComplex(type);
+ break;
+ case DYN_TYPE_SEQUENCE :
+ dynType_clearSequence(type);
+ break;
+ case DYN_TYPE_TYPED_POINTER :
+ dynType_clearTypedPointer(type);
+ break;
+ }
+
+ if (type->name != NULL) {
+ free(type->name);
+ }
+}
+
+static void dynType_clearComplex(dyn_type *type) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ struct complex_type_entry *entry = TAILQ_FIRST(&type->complex.entriesHead);
+ struct complex_type_entry *tmp = NULL;
+ while (entry != NULL) {
+ dynType_destroy(entry->type);
+ if (entry->name != NULL) {
+ free(entry->name);
+ }
+ tmp = entry;
+ entry = TAILQ_NEXT(entry, entries);
+ free(tmp);
+ }
+ if (type->complex.types != NULL) {
+ free(type->complex.types);
+ }
+ if (type->complex.structType.elements != NULL) {
+ free(type->complex.structType.elements);
+ }
+}
+
+static void dynType_clearSequence(dyn_type *type) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ if (type->sequence.itemType != NULL) {
+ dynType_destroy(type->sequence.itemType);
+ }
+}
+
+static void dynType_clearTypedPointer(dyn_type *type) {
+ assert(type->type == DYN_TYPE_TYPED_POINTER);
+ if (type->typedPointer.typedType != NULL) {
+ dynType_destroy(type->typedPointer.typedType);
+ }
+}
+
+int dynType_alloc(dyn_type *type, void **bufLoc) {
+ assert(type->type != DYN_TYPE_REF);
+ assert(type->ffiType->size != 0);
+ int status = OK;
+
+ void *inst = calloc(1, type->ffiType->size);
+ if (inst != NULL) {
+ if (type->type == DYN_TYPE_TYPED_POINTER) {
+ void *ptr = NULL;
+ dyn_type *sub = NULL;
+ status = dynType_typedPointer_getTypedType(type, &sub);
+ if (status == OK) {
+ status = dynType_alloc(sub, &ptr);
+ if (status == OK) {
+ *(void **)inst = ptr;
+ }
+ }
+ }
+ *bufLoc = inst;
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
+ }
+
+ return status;
+}
+
+
+int dynType_complex_indexForName(dyn_type *type, const char *name) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ int i = 0;
+ int index = -1;
+ struct complex_type_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ if (strcmp(name, entry->name) == 0) {
+ index = i;
+ }
+ i +=1;
+ }
+ return index;
+}
+
+int dynType_complex_dynTypeAt(dyn_type *type, int index, dyn_type **result) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ assert(index >= 0);
+ dyn_type *sub = type->complex.types[index];
+ if (sub->type == DYN_TYPE_REF) {
+ sub = sub->ref.ref;
+ }
+ *result = sub;
+ return 0;
+}
+
+int dynType_complex_setValueAt(dyn_type *type, int index, void *start, void *in) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ char *loc = ((char *)start) + dynType_getOffset(type, index);
+ size_t size = type->complex.structType.elements[index]->size;
+ memcpy(loc, in, size);
+ return 0;
+}
+
+int dynType_complex_valLocAt(dyn_type *type, int index, void *inst, void **result) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ char *l = (char *)inst;
+ void *loc = (void *)(l + dynType_getOffset(type, index));
+ *result = loc;
+ return OK;
+}
+
+int dynType_complex_entries(dyn_type *type, struct complex_type_entries_head **entries) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ int status = OK;
+ *entries = &type->complex.entriesHead;
+ return status;
+}
+
+//sequence
+int dynType_sequence_alloc(dyn_type *type, void *inst, uint32_t cap) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ int status = OK;
+ struct generic_sequence *seq = inst;
+ if (seq != NULL) {
+ size_t size = dynType_size(type->sequence.itemType);
+ seq->buf = calloc(cap, size);
+ if (seq->buf != NULL) {
+ seq->cap = cap;
+ seq->len = 0;;
+ } else {
+ seq->cap = 0;
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for buf")
+ }
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for seq")
+ }
+ return status;
+}
+
+void dynType_free(dyn_type *type, void *loc) {
+ dynType_deepFree(type, loc, true);
+}
+
+void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf) {
+ if (loc != NULL) {
+ dyn_type *subType = NULL;
+ char *text = NULL;
+ switch (type->type) {
+ case DYN_TYPE_COMPLEX :
+ dynType_freeComplexType(type, loc);
+ break;
+ case DYN_TYPE_SEQUENCE :
+ dynType_freeSequenceType(type, loc);
+ break;
+ case DYN_TYPE_TYPED_POINTER:
+ dynType_typedPointer_getTypedType(type, &subType);
+ dynType_deepFree(subType, *(void **)loc, true);
+ break;
+ case DYN_TYPE_TEXT :
+ text = *(char **)loc;
+ free(text);
+ break;
+ }
+
+ if (alsoDeleteSelf) {
+ free(loc);
+ }
+ }
+}
+
+void dynType_freeSequenceType(dyn_type *type, void *seqLoc) {
+ struct generic_sequence *seq = seqLoc;
+ dyn_type *itemType = dynType_sequence_itemType(type);
+ void *itemLoc = NULL;
+ int i;
+ for (i = 0; i < seq->len; i += 1) {
+ dynType_sequence_locForIndex(type, seqLoc, i, &itemLoc);
+ dynType_deepFree(itemType, itemLoc, false);
+ }
+ free(seq->buf);
+}
+
+void dynType_freeComplexType(dyn_type *type, void *loc) {
+ struct complex_type_entry *entry = NULL;
+ int index = 0;
+ void *entryLoc = NULL;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ dynType_complex_valLocAt(type, index++, loc, &entryLoc);
+ dynType_deepFree(entry->type, entryLoc, false);
+ }
+}
+
+
+uint32_t dynType_sequence_length(void *seqLoc) {
+ struct generic_sequence *seq = seqLoc;
+ return seq->len;
+}
+
+int dynType_sequence_locForIndex(dyn_type *type, void *seqLoc, int index, void **out) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ int status = OK;
+
+ struct generic_sequence *seq = seqLoc;
+ char *valLoc = seq->buf;
+
+ size_t itemSize = dynType_size(type->sequence.itemType);
+
+ if (index >= seq->cap) {
+ status = ERROR;
+ LOG_ERROR("Requested index (%i) is greater than capacity (%u) of sequence", index, seq->cap);
+ }
+
+ if (index >= seq->len) {
+ LOG_WARNING("Requesting index (%i) outsize defined length (%u) but within capacity", index, seq->len);
+ }
+
+ if (status == OK) { }
+ int i;
+ for (i = 0; i < seq->cap; i += 1) {
+ if (index == i) {
+ break;
+ } else {
+ valLoc += itemSize;
+ }
+ }
+
+ (*out) = valLoc;
+
+ return status;
+}
+
+int dynType_sequence_increaseLengthAndReturnLastLoc(dyn_type *type, void *seqLoc, void **valLoc) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ int status = OK;
+ struct generic_sequence *seq = seqLoc;
+
+ int lastIndex = seq->len;
+ if (seq->len < seq->cap) {
+ seq->len += 1;
+ } else {
+ status = ERROR;
+ LOG_ERROR("Cannot increase sequence length beyond capacity (%u)", seq->cap);
+ }
+
+ if (status == OK) {
+ status = dynType_sequence_locForIndex(type, seqLoc, lastIndex, valLoc);
+ }
+
+ return status;
+}
+
+dyn_type * dynType_sequence_itemType(dyn_type *type) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ dyn_type *itemType = type->sequence.itemType;
+ if (itemType->type == DYN_TYPE_REF) {
+ itemType = itemType->ref.ref;
+ }
+ return itemType;
+}
+
+void dynType_simple_setValue(dyn_type *type, void *inst, void *in) {
+ size_t size = dynType_size(type);
+ memcpy(inst, in, size);
+}
+
+
+int dynType_descriptorType(dyn_type *type) {
+ return type->descriptor;
+}
+
+const char * dynType_getMetaInfo(dyn_type *type, const char *name) {
+ const char *result = NULL;
+ struct meta_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->metaProperties, entries) {
+ LOG_DEBUG("Checking '%s'", entry->name);
+ if (strcmp(entry->name, name) == 0) {
+ result = entry->value;
+ break;
+ }
+ }
+ return result;
+}
+
+ffi_type *dynType_ffiType(dyn_type *type) {
+ if (type->type == DYN_TYPE_REF) {
+ if (type->ref.ref == NULL) {
+ LOG_ERROR("Error. Ref for %s is not (yet) initialized", type->name);
+ return NULL;
+ }
+ return type->ref.ref->ffiType;
+ }
+ return type->ffiType;
+}
+
+static ffi_type * dynType_ffiTypeFor(int c) {
+ ffi_type *type = NULL;
+ switch (c) {
+ case 'Z' :
+ type = &ffi_type_uint8;
+ break;
+ case 'F' :
+ type = &ffi_type_float;
+ break;
+ case 'D' :
+ type = &ffi_type_double;
+ break;
+ case 'B' :
+ type = &ffi_type_sint8;
+ break;
+ case 'b' :
+ type = &ffi_type_uint8;
+ break;
+ case 'S' :
+ type = &ffi_type_sint16;
+ break;
+ case 's' :
+ type = &ffi_type_uint16;
+ break;
+ case 'I' :
+ type = &ffi_type_sint32;
+ break;
+ case 'i' :
+ type = &ffi_type_uint32;
+ break;
+ case 'J' :
+ type = &ffi_type_sint64;
+ break;
+ case 'j' :
+ type = &ffi_type_sint64;
+ break;
+ case 'N' :
+ type = &ffi_type_sint;
+ break;
+ case 'P' :
+ type = &ffi_type_pointer;
+ break;
+ case 'V' :
+ type = &ffi_type_void;
+ break;
+ }
+ return type;
+}
+
+static dyn_type * dynType_findType(dyn_type *type, char *name) {
+ dyn_type *result = NULL;
+
+ struct type_entry *entry = NULL;
+ if (type->referenceTypes != NULL) {
+ TAILQ_FOREACH(entry, type->referenceTypes, entries) {
+ LOG_DEBUG("checking ref type '%s' with name '%s'", entry->type->name, name);
+ if (strcmp(name, entry->type->name) == 0) {
+ result = entry->type;
+ break;
+ }
+ }
+ }
+
+ if (result == NULL) {
+ struct type_entry *nEntry = NULL;
+ TAILQ_FOREACH(nEntry, &type->nestedTypesHead, entries) {
+ LOG_DEBUG("checking nested type '%s' with name '%s'", nEntry->type->name, name);
+ if (strcmp(name, nEntry->type->name) == 0) {
+ result = nEntry->type;
+ break;
+ }
+ }
+ }
+
+ if (result == NULL && type->parent != NULL) {
+ result = dynType_findType(type->parent, name);
+ }
+
+ return result;
+}
+
+static unsigned short dynType_getOffset(dyn_type *type, int index) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ unsigned short offset = 0;
+
+ ffi_type *ffiType = &type->complex.structType;
+ int i;
+ for (i = 0; i <= index && ffiType->elements[i] != NULL; i += 1) {
+ size_t size = ffiType->elements[i]->size;
+ unsigned short alignment = ffiType->elements[i]->alignment;
+ int alignment_diff = offset % alignment;
+ if (alignment_diff > 0) {
+ offset += (alignment - alignment_diff);
+ }
+ if (i < index) {
+ offset += size;
+ }
+ }
+
+ return offset;
+}
+
+size_t dynType_size(dyn_type *type) {
+ dyn_type *rType = type;
+ if (type->type == DYN_TYPE_REF) {
+ rType = type->ref.ref;
+ }
+ return rType->ffiType->size;
+}
+
+int dynType_type(dyn_type *type) {
+ return type->type;
+}
+
+
+int dynType_typedPointer_getTypedType(dyn_type *type, dyn_type **out) {
+ assert(type->type == DYN_TYPE_TYPED_POINTER);
+ int status = 0;
+
+ dyn_type *typedType = type->typedPointer.typedType;
+ if (typedType->type == DYN_TYPE_REF) {
+ typedType = typedType->ref.ref;
+ }
+
+ *out = typedType;
+ return status;
+}
+
+
+int dynType_text_allocAndInit(dyn_type *type, void *textLoc, const char *value) {
+ assert(type->type == DYN_TYPE_TEXT);
+ int status = 0;
+ const char *str = strdup(value);
+ char const **loc = textLoc;
+ if (str != NULL) {
+ *loc = str;
+ } else {
+ status = ERROR;
+ LOG_ERROR("Cannot allocate memory for string");
+ }
+ return status;
+}
+
+
+
+
+
+void dynType_print(dyn_type *type, FILE *stream) {
+ if (type != NULL) {
+ dynType_printTypes(type, stream);
+
+ fprintf(stream, "main type:\n");
+ dynType_printAny("root", type, 0, stream);
+ } else {
+ fprintf(stream, "invalid type\n");
+ }
+}
+
+static void dynType_printDepth(int depth, FILE *stream) {
+ int i;
+ for (i = 0; i < depth; i +=1 ) {
+ fprintf(stream, "\t");
+ }
+}
+
+static void dynType_printAny(char *name, dyn_type *type, int depth, FILE *stream) {
+ dyn_type *toPrint = type;
+ if (toPrint->type == DYN_TYPE_REF) {
+ toPrint = toPrint->ref.ref;
+ }
+ switch(toPrint->type) {
+ case DYN_TYPE_COMPLEX :
+ dynType_printComplex(name, toPrint, depth, stream);
+ break;
+ case DYN_TYPE_SIMPLE :
+ dynType_printSimple(name, toPrint, depth, stream);
+ break;
+ case DYN_TYPE_SEQUENCE :
+ dynType_printSequence(name, toPrint, depth, stream);
+ break;
+ case DYN_TYPE_TYPED_POINTER :
+ dynType_printTypedPointer(name, toPrint, depth, stream);
+ break;
+ default :
+ fprintf(stream, "TODO Unsupported type %i\n", toPrint->type);
+ break;
+ }
+}
+
+static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *stream) {
+ if (type->name == NULL) {
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "%s: complex type (anon), size is %zu, alignment is %i, descriptor is '%c'. fields:\n", name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+
+ struct complex_type_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ dynType_printAny(entry->name, entry->type, depth + 1, stream);
+ }
+
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "}\n");
+ } else {
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "%s: complex type ('%s'), size is %zu, alignment is %i, descriptor is '%c'.\n", name, type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+ }
+}
+
+static void dynType_printSequence(char *name, dyn_type *type, int depth, FILE *stream) {
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "sequence, size is %zu, alignment is %i, descriptor is '%c'. fields:\n", type->ffiType->size, type->ffiType->alignment, type->descriptor);
+
+ dynType_printDepth(depth + 1, stream);
+ fprintf(stream, "cap: simple type, size is %zu, alignment is %i.\n", type->sequence.seqType.elements[0]->size, type->sequence.seqType.elements[0]->alignment);
+
+ dynType_printDepth(depth + 1, stream);
+ fprintf(stream, "len: simple type, size is %zu, alignment is %i.\n", type->sequence.seqType.elements[1]->size, type->sequence.seqType.elements[1]->alignment);
+
+ dynType_printDepth(depth + 1, stream);
+ fprintf(stream, "buf: array, size is %zu, alignment is %i. points to ->\n", type->sequence.seqType.elements[2]->size, type->sequence.seqType.elements[2]->alignment);
+ dynType_printAny("element", type->sequence.itemType, depth + 1, stream);
+}
+
+static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream) {
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "%s: simple type, size is %zu, alignment is %i, descriptor is '%c'.\n", name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+}
+
+static void dynType_printTypedPointer(char *name, dyn_type *type, int depth, FILE *stream) {
+ dynType_printDepth(depth, stream);
+ fprintf(stream, "%s: typed pointer, size is %zu, alignment is %i, points to ->\n", name, type->ffiType->size, type->ffiType->alignment);
+ char *subName = NULL;
+ char buf[128];
+ memset(buf,0,128);
+ if (name != NULL) {
+ snprintf(buf, 128, "*%s", name);
+ subName = buf;
+ }
+ dynType_printAny(subName, type->typedPointer.typedType, depth + 1, stream);
+}
+
+static void dynType_printTypes(dyn_type *type, FILE *stream) {
+
+ dyn_type *parent = type->parent;
+ struct type_entry *pentry = NULL;
+ while (parent != NULL) {
+ TAILQ_FOREACH(pentry, &parent->nestedTypesHead, entries) {
+ if (pentry->type == type) {
+ return;
+ }
+ }
+ parent = parent->parent;
+ }
+
+ struct type_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->nestedTypesHead, entries) {
+ dyn_type *toPrint = entry->type;
+ if (toPrint->type == DYN_TYPE_REF) {
+ toPrint = toPrint->ref.ref;
+ }
+
+ switch(toPrint->type) {
+ case DYN_TYPE_COMPLEX :
+ dynType_printComplexType(toPrint, stream);
+ break;
+ case DYN_TYPE_SIMPLE :
+ dynType_printSimpleType(toPrint, stream);
+ break;
+ default :
+ printf("TODO Print Type\n");
+ break;
+ }
+ }
+
+
+ struct complex_type_entry *centry = NULL;
+ switch(type->type) {
+ case DYN_TYPE_COMPLEX :
+ TAILQ_FOREACH(centry, &type->complex.entriesHead, entries) {
+ dynType_printTypes(centry->type, stream);
+ }
+ break;
+ case DYN_TYPE_SEQUENCE :
+ dynType_printTypes(type->sequence.itemType, stream);
+ break;
+ case DYN_TYPE_TYPED_POINTER :
+ dynType_printTypes(type->typedPointer.typedType, stream);
+ break;
+ }
+}
+
+static void dynType_printComplexType(dyn_type *type, FILE *stream) {
+ fprintf(stream, "type '%s': complex type, size is %zu, alignment is %i, descriptor is '%c'. fields:\n", type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+
+ struct complex_type_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ dynType_printAny(entry->name, entry->type, 2, stream);
+ }
+
+ fprintf(stream, "}\n");
+}
+
+static void dynType_printSimpleType(dyn_type *type, FILE *stream) {
+ fprintf(stream, "\ttype '%s': simple type, size is %zu, alignment is %i, descriptor is '%c'\n", type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+}
+