AP_Scripting: Generator: support depends

This commit is contained in:
Iampete1 2020-11-03 00:43:35 +00:00 committed by Andrew Tridgell
parent 05fb14e5d9
commit 2a75432fa2

View File

@ -56,6 +56,7 @@ struct header {
struct header *next;
char *name; // name of the header to include (not sanatized)
int line; // line of the file declared on
char *dependency;
};
struct generator_state {
@ -255,6 +256,12 @@ void *allocate(const size_t size) {
return data;
}
// lazy helper that allocates a storage buffer and does strcpy for us
void string_copy(char **dest, const char * src) {
*dest = (char *)allocate(strlen(src) + 1);
strcpy(*dest, src);
}
void handle_header(void) {
trace(TRACE_HEADER, "Parsing a header");
@ -279,6 +286,22 @@ void handle_header(void) {
node->line = state.line_num;
node->name = (char *)allocate(strlen(name) + 1);
strcpy(node->name, name);
// add depedns
char * key_word = next_token();
char *depends = NULL;
if (key_word != NULL) {
if (strcmp(key_word, keyword_depends) == 0) {
depends = strtok(NULL, "");
if (depends == NULL) {
error(ERROR_HEADER, "Expected a depends string for %s", name);
}
string_copy(&(node->dependency), depends);
} else {
error(ERROR_HEADER, "Received an unsupported keyword on a header: %s", key_word);
}
}
headers = node;
trace(TRACE_HEADER, "Added header %s", name);
@ -340,27 +363,12 @@ struct userdata {
enum userdata_type ud_type;
uint32_t operations; // bitset of enum operation_types
int flags; // flags from the userdata_flags enum
char *dependency;
};
static struct userdata *parsed_userdata;
static struct userdata *parsed_ap_objects;
struct dependency {
struct dependency * next;
char *symbol; // dependency symbol to check
char *value; // value to target
char *error_msg; // message if the check fails
};
static struct dependency *parsed_dependencies;
// lazy helper that allocates a storage buffer and does strcpy for us
void string_copy(char **dest, const char * src) {
*dest = (char *)allocate(strlen(src) + 1);
strcpy(*dest, src);
}
void sanatize_name(char **dest, char *src) {
*dest = (char *)allocate(strlen(src) + 1);
strcpy(*dest, src);
@ -829,8 +837,17 @@ void handle_singleton(void) {
handle_method(node->name, &(node->methods));
} else if (strcmp(type, keyword_enum) == 0) {
handle_userdata_enum(node);
} else if (strcmp(type, keyword_depends) == 0) {
if (node->dependency != NULL) {
error(ERROR_SINGLETON, "Singletons only support a single depends");
}
char *depends = strtok(NULL, "");
if (depends == NULL) {
error(ERROR_DEPENDS, "Expected a depends string for %s",node->name);
}
string_copy(&(node->dependency), depends);
} else {
error(ERROR_SINGLETON, "Singletons only support aliases, methods or semaphore keyowrds (got %s)", type);
error(ERROR_SINGLETON, "Singletons only support aliases, methods, semaphore or depends keywords (got %s)", type);
}
// ensure no more tokens on the line
@ -901,36 +918,6 @@ void handle_ap_object(void) {
}
}
void handle_depends(void) {
trace(TRACE_DEPENDS, "Adding a dependency");
char *symbol = next_token();
if (symbol == NULL) {
error(ERROR_DEPENDS, "Expected a name symbol for the dependency");
}
// read value
char *value = next_token();
if (value == NULL) {
error(ERROR_DEPENDS, "Expected a required value for dependency on %s", symbol);
}
char *error_msg = strtok(NULL, "");
if (error_msg == NULL) {
error(ERROR_DEPENDS, "Expected a error message for dependency on %s", symbol);
}
trace(TRACE_SINGLETON, "Allocating new dependency for %s", symbol);
struct dependency * node = (struct dependency *)allocate(sizeof(struct dependency));
node->symbol = (char *)allocate(strlen(symbol) + 1);
strcpy(node->symbol, symbol);
node->value = (char *)allocate(strlen(value) + 1);
strcpy(node->value, value);
node->error_msg = (char *)allocate(strlen(error_msg) + 1);
strcpy(node->error_msg, error_msg);
node->next = parsed_dependencies;
parsed_dependencies = node;
}
void sanity_check_userdata(void) {
struct userdata * node = parsed_userdata;
while(node) {
@ -941,20 +928,24 @@ void sanity_check_userdata(void) {
}
}
void emit_headers(FILE *f) {
struct header *node = headers;
while (node) {
fprintf(f, "#include <%s>\n", node->name);
node = node->next;
void start_dependency(FILE *f, const char *dependency) {
if (dependency != NULL) {
fprintf(f, "#if %s\n", dependency);
}
}
void emit_dependencies(FILE *f) {
struct dependency *node = parsed_dependencies;
void end_dependency(FILE *f, const char *dependency) {
if (dependency != NULL) {
fprintf(f, "#endif // %s\n", dependency);
}
}
void emit_headers(FILE *f) {
struct header *node = headers;
while (node) {
fprintf(f, "#if !defined(%s) || (%s != %s)\n", node->symbol, node->symbol, node->value);
fprintf(f, " #error %s\n", node->error_msg);
fprintf(f, "#endif // !defined(%s) || (%s != %s)\n", node->symbol, node->symbol, node->value);
start_dependency(f, node->dependency);
fprintf(f, "#include <%s>\n", node->name);
end_dependency(f, node->dependency);
node = node->next;
}
}
@ -962,6 +953,7 @@ void emit_dependencies(FILE *f) {
void emit_userdata_allocators(void) {
struct userdata * node = parsed_userdata;
while (node) {
start_dependency(source, node->dependency);
fprintf(source, "int new_%s(lua_State *L) {\n", node->sanatized_name);
fprintf(source, " luaL_checkstack(L, 2, \"Out of stack\");\n"); // ensure we have sufficent stack to push the return
fprintf(source, " void *ud = lua_newuserdata(L, sizeof(%s));\n", node->name);
@ -970,7 +962,9 @@ void emit_userdata_allocators(void) {
fprintf(source, " luaL_getmetatable(L, \"%s\");\n", node->name);
fprintf(source, " lua_setmetatable(L, -2);\n");
fprintf(source, " return 1;\n");
fprintf(source, "}\n\n");
fprintf(source, "}\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
}
@ -978,6 +972,7 @@ void emit_userdata_allocators(void) {
void emit_ap_object_allocators(void) {
struct userdata * node = parsed_ap_objects;
while (node) {
start_dependency(source, node->dependency);
fprintf(source, "int new_%s(lua_State *L) {\n", node->sanatized_name);
fprintf(source, " luaL_checkstack(L, 2, \"Out of stack\");\n"); // ensure we have sufficent stack to push the return
fprintf(source, " void *ud = lua_newuserdata(L, sizeof(%s *));\n", node->name);
@ -985,7 +980,9 @@ void emit_ap_object_allocators(void) {
fprintf(source, " luaL_getmetatable(L, \"%s\");\n", node->name);
fprintf(source, " lua_setmetatable(L, -2);\n");
fprintf(source, " return 1;\n");
fprintf(source, "}\n\n");
fprintf(source, "}\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
}
@ -993,10 +990,13 @@ void emit_ap_object_allocators(void) {
void emit_userdata_checkers(void) {
struct userdata * node = parsed_userdata;
while (node) {
start_dependency(source, node->dependency);
fprintf(source, "%s * check_%s(lua_State *L, int arg) {\n", node->name, node->sanatized_name);
fprintf(source, " void *data = luaL_checkudata(L, arg, \"%s\");\n", node->name);
fprintf(source, " return (%s *)data;\n", node->name);
fprintf(source, "}\n\n");
fprintf(source, "}\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
}
@ -1004,10 +1004,13 @@ void emit_userdata_checkers(void) {
void emit_ap_object_checkers(void) {
struct userdata * node = parsed_ap_objects;
while (node) {
start_dependency(source, node->dependency);
fprintf(source, "%s ** check_%s(lua_State *L, int arg) {\n", node->name, node->sanatized_name);
fprintf(source, " void *data = luaL_checkudata(L, arg, \"%s\");\n", node->name);
fprintf(source, " return (%s **)data;\n", node->name);
fprintf(source, "}\n\n");
fprintf(source, "}\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
}
@ -1015,8 +1018,10 @@ void emit_ap_object_checkers(void) {
void emit_userdata_declarations(void) {
struct userdata * node = parsed_userdata;
while (node) {
start_dependency(header, node->dependency);
fprintf(header, "int new_%s(lua_State *L);\n", node->sanatized_name);
fprintf(header, "%s * check_%s(lua_State *L, int arg);\n", node->name, node->sanatized_name);
end_dependency(header, node->dependency);
node = node->next;
}
}
@ -1316,10 +1321,12 @@ void emit_userdata_fields() {
struct userdata * node = parsed_userdata;
while(node) {
struct userdata_field *field = node->fields;
start_dependency(source, node->dependency);
while(field) {
emit_userdata_field(node, field);
field = field->next;
}
end_dependency(source, node->dependency);
node = node->next;
}
}
@ -1378,6 +1385,8 @@ int emit_references(const struct argument *arg, const char * tab) {
void emit_userdata_method(const struct userdata *data, const struct method *method) {
int arg_count = 1;
start_dependency(source, data->dependency);
const char *access_name = data->alias ? data->alias : data->name;
// bind ud early if it's a singleton, so that we can use it in the range checks
fprintf(source, "static int %s_%s(lua_State *L) {\n", data->sanatized_name, method->name);
@ -1636,7 +1645,10 @@ void emit_userdata_method(const struct userdata *data, const struct method *meth
fprintf(source, " return %d;\n", return_count);
}
fprintf(source, "}\n\n");
fprintf(source, "}\n");
end_dependency(source, data->dependency);
fprintf(source, "\n");
}
const char * get_name_for_operation(enum operator_type op) {
@ -1722,6 +1734,7 @@ void emit_userdata_methods(struct userdata *node) {
void emit_userdata_metatables(void) {
struct userdata * node = parsed_userdata;
while(node) {
start_dependency(source, node->dependency);
fprintf(source, "const luaL_Reg %s_meta[] = {\n", node->sanatized_name);
struct userdata_field *field = node->fields;
@ -1745,8 +1758,9 @@ void emit_userdata_metatables(void) {
}
fprintf(source, " {NULL, NULL}\n");
fprintf(source, "};\n\n");
fprintf(source, "};\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
}
@ -1754,6 +1768,7 @@ void emit_userdata_metatables(void) {
void emit_singleton_metatables(struct userdata *head) {
struct userdata * node = head;
while(node) {
start_dependency(source, node->dependency);
fprintf(source, "const luaL_Reg %s_meta[] = {\n", node->sanatized_name);
struct method *method = node->methods;
@ -1763,7 +1778,9 @@ void emit_singleton_metatables(struct userdata *head) {
}
fprintf(source, " {NULL, NULL}\n");
fprintf(source, "};\n\n");
fprintf(source, "};\n");
end_dependency(source, node->dependency);
fprintf(source, "\n");
node = node->next;
}
@ -1772,13 +1789,16 @@ void emit_singleton_metatables(struct userdata *head) {
void emit_enums(struct userdata * data) {
while (data) {
if (data->enums != NULL) {
start_dependency(source, data->dependency);
fprintf(source, "struct userdata_enum %s_enums[] = {\n", data->sanatized_name);
struct userdata_enum *ud_enum = data->enums;
while (ud_enum != NULL) {
fprintf(source, " {\"%s\", %s::%s},\n", ud_enum->name, data->name, ud_enum->name);
ud_enum = ud_enum->next;
}
fprintf(source, " {NULL, 0}};\n\n");
fprintf(source, " {NULL, 0}};\n");
end_dependency(source, data->dependency);
fprintf(source, "\n");
}
data = data->next;
}
@ -1787,11 +1807,13 @@ void emit_enums(struct userdata * data) {
void emit_metas(struct userdata * data, char * meta_name) {
fprintf(source, "const struct userdata_meta %s_fun[] = {\n", meta_name);
while (data) {
start_dependency(source, data->dependency);
if (data->enums) {
fprintf(source, " {\"%s\", %s_meta, %s_enums},\n", data->alias ? data->alias : data->name, data->name, data->sanatized_name);
} else {
fprintf(source, " {\"%s\", %s_meta, NULL},\n", data->alias ? data->alias : data->name, data->sanatized_name);
}
end_dependency(source, data->dependency);
data = data->next;
}
fprintf(source, "};\n\n");
@ -1886,7 +1908,9 @@ void emit_sandbox(void) {
fprintf(source, " const lua_CFunction fun;\n");
fprintf(source, "} new_userdata[] = {\n");
while (data) {
start_dependency(source, data->dependency);
fprintf(source, " {\"%s\", new_%s},\n", data->name, data->sanatized_name);
end_dependency(source, data->dependency);
data = data->next;
}
data = parsed_ap_objects;
@ -1983,8 +2007,6 @@ int main(int argc, char **argv) {
handle_singleton();
} else if (strcmp (state.token, keyword_ap_object) == 0){
handle_ap_object();
} else if (strcmp (state.token, keyword_depends) == 0){
handle_depends();
} else {
error(ERROR_UNKNOWN_KEYWORD, "Expected a keyword, got: %s", state.token);
}
@ -2019,10 +2041,6 @@ int main(int argc, char **argv) {
fprintf(source, "\n\n");
emit_dependencies(source);
fprintf(source, "\n\n");
emit_argcheck_helper();
emit_userdata_allocators();
@ -2062,11 +2080,10 @@ int main(int argc, char **argv) {
free(file_name);
fprintf(header, "#pragma once\n");
fprintf(header, "// auto generated bindings, don't manually edit. See README.md for details.\n");
fprintf(header, "#include <AP_Vehicle/AP_Vehicle_Type.h> // needed for APM_BUILD_TYPE #if\n");
emit_headers(header);
fprintf(header, "#include <AP_Scripting/lua/src/lua.hpp>\n");
fprintf(header, "#include <new>\n\n");
emit_dependencies(header);
fprintf(header, "\n\n");
emit_userdata_declarations();
emit_ap_object_declarations();