diff --git a/lcmgen/emit_lua.c b/lcmgen/emit_lua.c index f4298346..6f29c86d 100644 --- a/lcmgen/emit_lua.c +++ b/lcmgen/emit_lua.c @@ -44,6 +44,32 @@ #define err(...) fprintf(stderr, __VA_ARGS__) +// LCM lets a member or constant be named after a Lua keyword (ROS's +// geographic_msgs.RouteSegment has a field called "end", for example). Those +// cannot be reached with dot notation, so they are emitted as t["end"]. +static const char *const lua_reserved_words[] = { + "and", "break", "do", "else", "elseif", "end", "false", "for", + "function", "goto", "if", "in", "local", "nil", "not", "or", + "repeat", "return", "then", "true", "until", "while", NULL}; + +static int lua_is_reserved_word(const char *name) +{ + for (int i = 0; lua_reserved_words[i] != NULL; i++) { + if (!strcmp(name, lua_reserved_words[i])) + return 1; + } + return 0; +} + +// Returns ".", or "
[\"\"]" when is a Lua +// keyword. Caller must g_free() the result. +static char *lua_member_ref(const char *table, const char *name) +{ + if (lua_is_reserved_word(name)) + return g_strdup_printf("%s[\"%s\"]", table, name); + return g_strdup_printf("%s.%s", table, name); +} + static void mkdir_with_parents(const char *path, mode_t mode) { #ifdef WIN32 @@ -241,16 +267,17 @@ static void _emit_decode_list(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls, lc emit(indent, "%s = {lcm._pack.unpack('>%s%c', data:read(%d))}", accessor, len, _struct_format(lm), atoi(len) * _primitive_type_size(tn)); } else { + char *lenref = lua_member_ref("obj", len); if (_primitive_type_size(tn) > 1) { emit(indent, - "%s = {lcm._pack.unpack(string.format('>%%d%c', obj.%s), data:read(obj.%s * " + "%s = {lcm._pack.unpack(string.format('>%%d%c', %s), data:read(%s * " "%d))}", - accessor, _struct_format(lm), len, len, _primitive_type_size(tn)); + accessor, _struct_format(lm), lenref, lenref, _primitive_type_size(tn)); } else { - emit(indent, - "%s = {lcm._pack.unpack(string.format('>%%d%c', obj.%s), data:read(obj.%s))}", - accessor, _struct_format(lm), len, len); + emit(indent, "%s = {lcm._pack.unpack(string.format('>%%d%c', %s), data:read(%s))}", + accessor, _struct_format(lm), lenref, lenref); } + g_free(lenref); } } else { assert(0); @@ -268,7 +295,9 @@ static void _flush_read_struct_fmt(const lcmgen_t *lcm, FILE *f, GQueue *formats int fmtsize = 0; while (!g_queue_is_empty(members)) { lcm_member_t *lm = (lcm_member_t *) g_queue_pop_head(members); - emit_continue("obj.%s", lm->membername); + char *ref = lua_member_ref("obj", lm->membername); + emit_continue("%s", ref); + g_free(ref); if (!g_queue_is_empty(members)) { emit_continue(", "); } @@ -305,14 +334,16 @@ static void emit_lua_decode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) g_queue_push_tail(struct_members, lm); } else { _flush_read_struct_fmt(lcm, f, struct_fmt, struct_members); - char *accessor = g_strdup_printf("obj.%s", lm->membername); + char *accessor = lua_member_ref("obj", lm->membername); _emit_decode_one(lcm, f, ls, lm, accessor, 1); g_free(accessor); } } else { _flush_read_struct_fmt(lcm, f, struct_fmt, struct_members); GString *accessor = g_string_new(""); - g_string_append_printf(accessor, "obj.%s", lm->membername); + char *accessor_base = lua_member_ref("obj", lm->membername); + g_string_append(accessor, accessor_base); + g_free(accessor_base); // iterate through the dimensions of the member, building up // an accessor string, and emitting for loops @@ -324,7 +355,9 @@ static void emit_lua_decode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) if (dim->mode == LCM_CONST) { emit(1 + n, "for i%d = 1, %s do", n, dim->size); } else { - emit(1 + n, "for i%d = 1, obj.%s do", n, dim->size); + char *dimref = lua_member_ref("obj", dim->size); + emit(1 + n, "for i%d = 1, %s do", n, dimref); + g_free(dimref); } g_string_append_printf(accessor, "[i%d]", n); } @@ -348,7 +381,9 @@ static void emit_lua_decode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) if (last_dim_fixed_len) { emit(1 + n, "for i%d = 1, %s do", n, last_dim->size); } else { - emit(1 + n, "for i%d = 1, obj.%s do", n, last_dim->size); + char *dimref = lua_member_ref("obj", last_dim->size); + emit(1 + n, "for i%d = 1, %s do", n, dimref); + g_free(dimref); } g_string_append_printf(accessor, "[i%d]", n); _emit_decode_one(lcm, f, ls, lm, accessor->str, n + 2); @@ -430,10 +465,12 @@ static void _emit_encode_list(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls, lc emit(indent, "table.insert(buf_table, lcm._pack.pack('>%s%c', unpack(%s)))", len, _struct_format(lm), accessor); } else { + char *lenref = lua_member_ref("self", len); emit(indent, - "table.insert(buf_table, lcm._pack.pack(string.format('>%%d%c', self.%s), " + "table.insert(buf_table, lcm._pack.pack(string.format('>%%d%c', %s), " "unpack(%s)))", - _struct_format(lm), len, accessor); + _struct_format(lm), lenref, accessor); + g_free(lenref); } } else { assert(0); @@ -453,7 +490,9 @@ static void _flush_write_struct_fmt(FILE *f, GQueue *formats, GQueue *members) emit_continue("', "); while (!g_queue_is_empty(members)) { lcm_member_t *lm = (lcm_member_t *) g_queue_pop_head(members); - emit_continue("self.%s", lm->membername); + char *ref = lua_member_ref("self", lm->membername); + emit_continue("%s", ref); + g_free(ref); if (!g_queue_is_empty(members)) { emit_continue(", "); } @@ -493,7 +532,7 @@ static void emit_lua_encode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) } else { // XXX not a primitive _flush_write_struct_fmt(f, struct_fmt, struct_members); - char *accessor = g_strdup_printf("self.%s", lm->membername); + char *accessor = lua_member_ref("self", lm->membername); _emit_encode_one(lcm, f, ls, lm, accessor, 1); g_free(accessor); } @@ -501,7 +540,9 @@ static void emit_lua_encode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) // XXX this is an array _flush_write_struct_fmt(f, struct_fmt, struct_members); GString *accessor = g_string_new(""); - g_string_append_printf(accessor, "self.%s", lm->membername); + char *accessor_base = lua_member_ref("self", lm->membername); + g_string_append(accessor, accessor_base); + g_free(accessor_base); int n; for (n = 0; n < lm->dimensions->len - 1; n++) { @@ -511,7 +552,9 @@ static void emit_lua_encode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) if (dim->mode == LCM_CONST) { emit(1 + n, "for i%d = 1, %s do", n, dim->size); } else { - emit(1 + n, "for i%d = 1, self.%s do", n, dim->size); + char *dimref = lua_member_ref("self", dim->size); + emit(1 + n, "for i%d = 1, %s do", n, dimref); + g_free(dimref); } } @@ -528,7 +571,9 @@ static void emit_lua_encode_one(const lcmgen_t *lcm, FILE *f, lcm_struct_t *ls) if (last_dim_fixed_len) { emit(1 + n, "for i%d = 1, %s do", n, last_dim->size); } else { - emit(1 + n, "for i%d = 1, self.%s do", n, last_dim->size); + char *dimref = lua_member_ref("self", last_dim->size); + emit(1 + n, "for i%d = 1, %s do", n, dimref); + g_free(dimref); } g_string_append_printf(accessor, "[i%d]", n); _emit_encode_one(lcm, f, ls, lm, accessor->str, n + 2); @@ -578,7 +623,9 @@ static void emit_member_initializer(const lcmgen_t *lcm, FILE *f, lcm_member_t * } else { emit_end("{}"); emit(dim_num + 1, "for d%d = 1, %s do", dim_num, dim->size); - emit_start(dim_num + 2, "obj.%s", lm->membername); + char *ref = lua_member_ref("obj", lm->membername); + emit_start(dim_num + 2, "%s", ref); + g_free(ref); for (int i = 0; i < dim_num + 1; i++) { emit_continue("[d%d]", i); } @@ -598,7 +645,9 @@ static void emit_lua_new(const lcmgen_t *lcm, FILE *f, lcm_struct_t *lr) unsigned int member; for (member = 0; member < lr->members->len; member++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(lr->members, member); - fprintf(f, " obj.%s = ", lm->membername); + char *ref = lua_member_ref("obj", lm->membername); + fprintf(f, " %s = ", ref); + g_free(ref); // XXX this might need alot of work because lua doesn't have list comprehension emit_member_initializer(lcm, f, lm, 0); } @@ -1096,7 +1145,9 @@ static int emit_package(lcmgen_t *lcm, _package_contents_t *pc) for (unsigned int cn = 0; cn < g_ptr_array_size(ls->constants); cn++) { lcm_constant_t *lc = (lcm_constant_t *) g_ptr_array_index(ls->constants, cn); assert(lcm_is_legal_const_type(lc->lctypename)); - emit(1, "%s.%s = %s", ls->structname->shortname, lc->membername, lc->val_str); + char *ref = lua_member_ref(ls->structname->shortname, lc->membername); + emit(1, "%s = %s", ref, lc->val_str); + g_free(ref); } if (g_ptr_array_size(ls->constants) > 0) emit(0, "");