From aad459d447622d1813ac594a2f321b68dd2deda8 Mon Sep 17 00:00:00 2001 From: Iampete1 Date: Sun, 6 Jun 2021 19:56:05 +0100 Subject: [PATCH] AP_Scripting: support array userdata feilds --- libraries/AP_Scripting/generator/src/main.c | 64 ++++++++++++++++----- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/libraries/AP_Scripting/generator/src/main.c b/libraries/AP_Scripting/generator/src/main.c index 3756951267..8eb469d5b7 100644 --- a/libraries/AP_Scripting/generator/src/main.c +++ b/libraries/AP_Scripting/generator/src/main.c @@ -30,6 +30,7 @@ char keyword_attr_enum[] = "'enum"; char keyword_attr_literal[] = "'literal"; char keyword_attr_null[] = "'Null"; char keyword_attr_reference[] = "'Ref"; +char keyword_attr_array[] = "'array"; // type keywords char keyword_boolean[] = "boolean"; @@ -344,6 +345,7 @@ struct userdata_field { struct type type; // field type, points to a string int line; // line declared on unsigned int access_flags; + char * array_len; // literal array length }; enum userdata_flags { @@ -639,17 +641,26 @@ void handle_userdata_field(struct userdata *data) { trace(TRACE_USERDATA, "Adding a userdata field"); // find the field name - char * field_name = next_token(); - if (field_name == NULL) { + char * token = next_token(); + if (token == NULL) { error(ERROR_USERDATA, "Missing a field name for userdata %s", data->name); } - + + size_t split = strcspn(token, "\'"); + char * field_name; + if (split == strlen(token)) { + string_copy(&field_name, token); + } else { + field_name = (char *)allocate(split+1); + memcpy(field_name, token, split); + } + struct userdata_field * field = data->fields; while (field != NULL && strcmp(field->name, field_name)) { field = field-> next; } if (field != NULL) { - error(ERROR_USERDATA, "Field %s already exsists in userdata %s (declared on %d)", field_name, data->name, field->line); + error(ERROR_USERDATA, "Field %s already exists in userdata %s (declared on %d)", field_name, data->name, field->line); } trace(TRACE_USERDATA, "Adding field %s", field_name); @@ -659,6 +670,16 @@ void handle_userdata_field(struct userdata *data) { field->line = state.line_num; string_copy(&(field->name), field_name); + char *attribute = strchr(token, '\''); + if (attribute != NULL) { + if (strcmp(attribute, keyword_attr_array) != 0) { + error(ERROR_USERDATA, "Unknown feild attribute %s for userdata %s feild %s", attribute, data->name, field_name); + } + char * token = next_token(); + string_copy(&(field->array_len), token); + trace(TRACE_USERDATA, "userdata %s feild %s array length %s", data->name, field->name, field->array_len); + } + parse_type(&(field->type), TYPE_RESTRICTION_NOT_NULLABLE, RANGE_CHECK_NONE); field->access_flags = parse_access_flags(&(field->type)); } @@ -1309,16 +1330,31 @@ void emit_checker(const struct type t, int arg_number, int skipped, const char * void emit_userdata_field(const struct userdata *data, const struct userdata_field *field) { fprintf(source, "static int %s_%s(lua_State *L) {\n", data->sanatized_name, field->name); fprintf(source, " %s *ud = check_%s(L, 1);\n", data->name, data->sanatized_name); - fprintf(source, " switch(lua_gettop(L)) {\n"); + + char *index_string = ""; + int write_arg_number = 2; + if (field->array_len != NULL) { + index_string = "[index]"; + write_arg_number = 3; + + fprintf(source, "\n const lua_Integer raw_index = luaL_checkinteger(L, 2);\n"); + fprintf(source, " luaL_argcheck(L, ((raw_index >= 0) && (raw_index < MIN(%s, UINT8_MAX))), 2, \"index out of range\");\n",field->array_len); + fprintf(source, " const uint8_t index = static_cast(raw_index);\n\n"); + + fprintf(source, " switch(lua_gettop(L)-1) {\n"); + + } else { + fprintf(source, " switch(lua_gettop(L)) {\n"); + } if (field->access_flags & ACCESS_FLAG_READ) { fprintf(source, " case 1:\n"); switch (field->type.type) { case TYPE_BOOLEAN: - fprintf(source, " lua_pushinteger(L, ud->%s);\n", field->name); + fprintf(source, " lua_pushinteger(L, ud->%s%s);\n", field->name, index_string); break; case TYPE_FLOAT: - fprintf(source, " lua_pushnumber(L, ud->%s);\n", field->name); + fprintf(source, " lua_pushnumber(L, ud->%s%s);\n", field->name, index_string); break; case TYPE_INT8_T: case TYPE_INT16_T: @@ -1326,11 +1362,11 @@ void emit_userdata_field(const struct userdata *data, const struct userdata_fiel case TYPE_UINT8_T: case TYPE_UINT16_T: case TYPE_ENUM: - fprintf(source, " lua_pushinteger(L, ud->%s);\n", field->name); + fprintf(source, " lua_pushinteger(L, ud->%s%s);\n", field->name, index_string); break; case TYPE_UINT32_T: fprintf(source, " new_uint32_t(L);\n"); - fprintf(source, " *static_cast(luaL_checkudata(L, -1, \"uint32_t\")) = ud->%s;\n", field->name); + fprintf(source, " *static_cast(luaL_checkudata(L, -1, \"uint32_t\")) = ud->%s%s;\n", field->name, index_string); break; case TYPE_NONE: error(ERROR_INTERNAL, "Can't access a NONE field"); @@ -1339,13 +1375,13 @@ void emit_userdata_field(const struct userdata *data, const struct userdata_fiel error(ERROR_INTERNAL, "Can't access a literal field"); break; case TYPE_STRING: - fprintf(source, " lua_pushstring(L, ud->%s);\n", field->name); + fprintf(source, " lua_pushstring(L, ud->%s%s);\n", field->name, index_string); break; case TYPE_USERDATA: - error(ERROR_USERDATA, "Userdata does not currently support accss to userdata field's"); + error(ERROR_USERDATA, "Userdata does not currently support access to userdata field's"); break; case TYPE_AP_OBJECT: // FIXME: collapse the identical cases here, and use the type string function - error(ERROR_USERDATA, "AP_Object does not currently support accss to userdata field's"); + error(ERROR_USERDATA, "AP_Object does not currently support access to userdata field's"); break; } fprintf(source, " return 1;\n"); @@ -1353,8 +1389,8 @@ void emit_userdata_field(const struct userdata *data, const struct userdata_fiel if (field->access_flags & ACCESS_FLAG_WRITE) { fprintf(source, " case 2: {\n"); - emit_checker(field->type, 2, 0, " ", field->name); - fprintf(source, " ud->%s = data_2;\n", field->name); + emit_checker(field->type, write_arg_number, 0, " ", field->name); + fprintf(source, " ud->%s%s = data_%i;\n", field->name, index_string, write_arg_number); fprintf(source, " return 0;\n"); fprintf(source, " }\n"); }