int emit_cpp(lcmgen_t *lcmgen) { // iterate through all defined message types for (unsigned int i = 0; i < g_ptr_array_size(lcmgen->structs); i++) { lcm_struct_t *lr = (lcm_struct_t *) g_ptr_array_index(lcmgen->structs, i); const char *tn = lr->structname->lctypename; char *tn_ = dots_to_slashes(tn); // compute the target filename char *header_name = g_strdup_printf("%s%s%s.hpp", getopt_get_string(lcmgen->gopt, "cpp-hpath"), strlen(getopt_get_string(lcmgen->gopt, "cpp-hpath")) > 0 ? G_DIR_SEPARATOR_S : "", tn_); // generate code if needed if (lcm_needs_generation(lcmgen, lr->lcmfile, header_name)) { make_dirs_for_file(header_name); FILE *f = fopen(header_name, "w"); if (f == NULL) return -1; emit_header_start(lcmgen, f, lr); emit_encode(lcmgen, f, lr); emit_decode(lcmgen, f, lr); emit_encoded_size(lcmgen, f, lr); emit_get_hash(lcmgen, f, lr); emit(0, "const char* %s::getTypeName()", lr->structname->shortname); emit(0, "{"); emit(1, "return \"%s\";", lr->structname->shortname); emit(0, "}"); emit(0, ""); emit_encode_nohash(lcmgen, f, lr); emit_decode_nohash(lcmgen, f, lr); emit_encoded_size_nohash(lcmgen, f, lr); emit_compute_hash(lcmgen, f, lr); emit_compare(lcmgen, f, lr); emit(0, "/// Testing (ignores dynamic arrays & affects only first and last elements of static arrays)"); emit(0, "/// {"); emit_print(lcmgen, f, lr); emit_init_test(lcmgen, f, lr); emit_inc_test(lcmgen, f, lr); emit_compare_test(lcmgen, f, lr); emit(0, "/// }"); emit_package_namespace_close(lcmgen, f, lr); emit(0, "#endif"); fclose(f); } g_free(header_name); free(tn_); } return 0; }
static int emit_package (lcmgen_t *lcm, _package_contents_t *pc) { // create the package directory, if necessary char **dirs = g_strsplit (pc->name, ".", 0); char *pdname = build_filenamev (dirs); char package_dir[PATH_MAX]; char package_dir_prefix[PATH_MAX]; int have_package = dirs[0] != NULL; int write_init_py = !getopt_get_bool(lcm->gopt, "python-no-init"); sprintf (package_dir_prefix, "%s%s", getopt_get_string(lcm->gopt, "ppath"), strlen(getopt_get_string(lcm->gopt, "ppath")) > 0 ? G_DIR_SEPARATOR_S : ""); sprintf(package_dir, "%s%s%s", package_dir_prefix, pdname, have_package ? G_DIR_SEPARATOR_S : ""); free (pdname); if (strlen (package_dir)) { if (! g_file_test (package_dir, G_FILE_TEST_EXISTS)) { // g_mkdir_with_parents (package_dir, 0755); mkdir_with_parents (package_dir, 0755); } if (!g_file_test (package_dir, G_FILE_TEST_IS_DIR)) { err ("Could not create directory %s\n", package_dir); return -1; } } // write the package __init__.py files, if necessary FILE *init_py_fp = NULL; GHashTable * init_py_imports = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); if (have_package && write_init_py) { int ndirs = 0; for (ndirs=0; dirs[ndirs]; ndirs++); for (int i=0 ; i<ndirs; i++) { char *initpy_fname_parts[1024]; assert(ndirs + 4 < 1024); initpy_fname_parts[0] = package_dir_prefix; for (int j=0; j<=i; j++) { initpy_fname_parts[j+1] = dirs[j]; } initpy_fname_parts[i+2] = "__init__.py"; initpy_fname_parts[i+3] = NULL; char *initpy_fname = build_filenamev (initpy_fname_parts); int created_initpy = 0; // close init_py_fp if already open if(init_py_fp) { fclose(init_py_fp); init_py_fp = NULL; } if (! g_file_test (initpy_fname, G_FILE_TEST_EXISTS)) { // __init__.py does not exist for this package. Create it. created_initpy = 1; init_py_fp = fopen(initpy_fname, "w"); } else { // open the existing __init__.py file, and make note of the // modules it imports created_initpy = 0; init_py_fp = fopen(initpy_fname, "r+"); } if (!init_py_fp) { perror ("fopen"); free (initpy_fname); return -1; } #ifndef WIN32 // lock __init__.py for exclusive write access // TODO do the equivalent in windows struct flock lockinfo; lockinfo.l_type = F_WRLCK; lockinfo.l_start = 0; lockinfo.l_whence = SEEK_SET; lockinfo.l_len = 0 ; lockinfo.l_pid = getpid(); if(0 != fcntl(fileno(init_py_fp), F_SETLKW, &lockinfo)) { perror("locking __init__.py"); free(initpy_fname); fclose(init_py_fp); return -1; } #endif if(created_initpy) { fprintf (init_py_fp, "\"\"\"LCM package __init__.py file\n" "This file automatically generated by lcm-gen.\n" "DO NOT MODIFY BY HAND!!!!\n" "\"\"\"\n\n"); } else { while(!feof(init_py_fp)) { char buf[4096]; memset(buf, 0, sizeof(buf)); char *result = fgets(buf, sizeof(buf)-1, init_py_fp); if(!result) break; g_strstrip(buf); char **words = g_strsplit(buf, " ", -1); if(!words[0] || !words[1] || !words[2] || !words[3]) continue; if(!strcmp(words[0], "from") && !strcmp(words[2], "import")) { char *module_name = strdup(words[1]+1); // ignore leading dot g_hash_table_replace(init_py_imports, module_name, module_name); } g_strfreev(words); } } free (initpy_fname); } } g_strfreev (dirs); //////////////////////////////////////////////////////////// // ENUMS for (int i=0; i<pc->enums->len; i++) { lcm_enum_t *le = (lcm_enum_t *) g_ptr_array_index (pc->enums, i); char path[PATH_MAX]; sprintf (path, "%s%s.py", package_dir, le->enumname->shortname); if(init_py_fp && !g_hash_table_lookup(init_py_imports, le->enumname->shortname)) fprintf(init_py_fp, "from .%s import %s\n", le->enumname->shortname, le->enumname->shortname); if (!lcm_needs_generation(lcm, le->lcmfile, path)) continue; FILE *f = fopen(path, "w"); if (f==NULL) return -1; fprintf(f, "\"\"\"LCM type definitions\n" "This file automatically generated by lcm.\n" "DO NOT MODIFY BY HAND!!!!\n" "\"\"\"\n" "\n" "try:\n" " import cStringIO.StringIO as BytesIO\n" "except ImportError:\n" " from io import BytesIO\n" "import struct\n\n"); // enums always encoded as int32 emit (0, "class %s(object):", le->enumname->shortname); emit (1, "__slots__ = [ \"value\" ]"); for (unsigned int v = 0; v < le->values->len; v++) { lcm_enum_value_t *lev = (lcm_enum_value_t *) g_ptr_array_index(le->values, v); emit(1, "%s = %i", lev->valuename, lev->value); } emit (1, "_packed_fingerprint = struct.pack(\">Q\", 0x%"PRIx64")", le->hash); fprintf (f, "\n"); emit (1, "def __init__ (self, value):"); emit (2, "self.value = value"); fprintf (f, "\n"); emit (1, "def _get_hash_recursive(parents):"); emit (2, "return 0x%"PRIx64, le->hash); emit (1, "_get_hash_recursive=staticmethod(_get_hash_recursive)"); emit (1, "def _get_packed_fingerprint():"); emit (2, "return %s._packed_fingerprint", le->enumname->shortname); emit (1, "_get_packed_fingerprint = staticmethod(_get_packed_fingerprint)"); fprintf (f, "\n"); emit (1, "def encode(self):"); emit (2, "return struct.pack(\">Qi\", 0x%"PRIx64", self.value)", le->hash); emit (1, "def _encode_one(self, buf):"); emit (2, "buf.write (struct.pack(\">i\", self.value))"); fprintf (f, "\n"); emit (1, "def decode(data):"); emit (2, "if hasattr (data, 'read'):"); emit (3, "buf = data"); emit (2, "else:"); emit (3, "buf = BytesIO(data)"); emit (2, "if buf.read(8) != %s._packed_fingerprint:", le->enumname->shortname); emit (3, "raise ValueError(\"Decode error\")"); emit (2, "return %s(struct.unpack(\">i\", buf.read(4))[0])", le->enumname->shortname); emit (1, "decode = staticmethod(decode)"); emit (1, "def _decode_one(buf):"); emit (2, "return %s(struct.unpack(\">i\", buf.read(4))[0])", le->enumname->shortname); emit (1, "_decode_one = staticmethod(_decode_one)"); fprintf (f, "\n"); fclose (f); } //////////////////////////////////////////////////////////// // STRUCTS for (int i = 0; i<pc->structs->len; i++) { lcm_struct_t *ls = (lcm_struct_t *) g_ptr_array_index(pc->structs, i); char path[PATH_MAX]; sprintf (path, "%s%s.py", package_dir, ls->structname->shortname); if(init_py_fp && !g_hash_table_lookup(init_py_imports, ls->structname->shortname)) fprintf(init_py_fp, "from .%s import %s\n", ls->structname->shortname, ls->structname->shortname); if (!lcm_needs_generation(lcm, ls->lcmfile, path)) continue; FILE *f = fopen(path, "w"); if (f==NULL) return -1; fprintf(f, "\"\"\"LCM type definitions\n" "This file automatically generated by lcm.\n" "DO NOT MODIFY BY HAND!!!!\n" "\"\"\"\n" "\n" "try:\n" " import cStringIO.StringIO as BytesIO\n" "except ImportError:\n" " from io import BytesIO\n" "import struct\n\n"); emit_python_dependencies (lcm, f, ls); fprintf(f, "class %s(object):\n", ls->structname->shortname); fprintf (f," __slots__ = ["); for (unsigned int member = 0; member < ls->members->len; member++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index (ls->members, member); fprintf (f, "\"%s\"%s", lm->membername, member < ls->members->len-1 ? ", " : ""); } fprintf (f, "]\n\n"); // CONSTANTS 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", lc->membername, lc->val_str); } if (g_ptr_array_size(ls->constants) > 0) emit(0, ""); emit_python_init (lcm, f, ls); emit_python_encode (lcm, f, ls); emit_python_encode_one (lcm, f, ls); emit_python_decode (lcm, f, ls); emit_python_decode_one (lcm, f, ls); emit_python_fingerprint (lcm, f, ls); fclose (f); } if(init_py_fp) fclose(init_py_fp); g_hash_table_destroy(init_py_imports); return 0; }
// XXX step 2, basically the main function static int emit_package (lcmgen_t *lcm, _package_contents_t *pc) { // create the package directory, if necessary char **dirs = g_strsplit (pc->name, ".", 0); char *pdname = build_filenamev (dirs); char package_dir[PATH_MAX]; char package_dir_prefix[PATH_MAX]; int have_package = dirs[0] != NULL; sprintf (package_dir_prefix, "%s%s", getopt_get_string(lcm->gopt, "lpath"), strlen(getopt_get_string(lcm->gopt, "lpath")) > 0 ? G_DIR_SEPARATOR_S : ""); sprintf(package_dir, "%s%s%s", package_dir_prefix, pdname, have_package ? G_DIR_SEPARATOR_S : ""); free (pdname); if (strlen (package_dir)) { if (! g_file_test (package_dir, G_FILE_TEST_EXISTS)) { // g_mkdir_with_parents (package_dir, 0755); mkdir_with_parents (package_dir, 0755); } if (!g_file_test (package_dir, G_FILE_TEST_IS_DIR)) { err ("Could not create directory %s\n", package_dir); return -1; } } // write the package init.lua files, if necessary FILE *init_lua_fp = NULL; GHashTable * initlua_requires = NULL; GHashTable * initlua_requires_subpack = NULL; if (have_package) { int ndirs = 0; for (ndirs=0; dirs[ndirs]; ndirs++); for (int i=0 ; i<ndirs; i++) { // make filename char *initlua_fname; { char *initlua_fname_parts[1024]; assert(ndirs + 4 < 1024); initlua_fname_parts[0] = package_dir_prefix; for (int j=0; j<=i; j++) { initlua_fname_parts[j+1] = dirs[j]; } initlua_fname_parts[i+2] = "init.lua"; initlua_fname_parts[i+3] = NULL; initlua_fname = build_filenamev (initlua_fname_parts); } // make current package name char * package_name; { char * name_parts[1024]; assert(i < 1024); for (int j = 0; j <= i; j++) { name_parts[j] = dirs[j]; } name_parts[i + 1] = NULL; package_name = g_strjoinv(".", name_parts); } if (initlua_requires) { g_hash_table_destroy(initlua_requires); initlua_requires = NULL; } if (initlua_requires_subpack) { g_hash_table_destroy(initlua_requires_subpack); initlua_requires_subpack = NULL; } initlua_requires = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); initlua_requires_subpack = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); // if the file already exists, read the contents if (g_file_test (initlua_fname, G_FILE_TEST_EXISTS)) { init_lua_fp = fopen(initlua_fname, "r"); if (!init_lua_fp) { perror ("fopen"); free (initlua_fname); g_free(package_name); return -1; } while(!feof(init_lua_fp)) { char buf[4096]; memset(buf, 0, sizeof(buf)); char *result = fgets(buf, sizeof(buf)-1, init_lua_fp); if(!result) break; // XXX get all of the previous types and packages // this regex works because the first part is greedy GRegex * regex = g_regex_new("require\\('([\\w+\\.]*\\.)(\\w+)'\\)( -- subpackage)?", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL); GMatchInfo * matchinfo; if(g_regex_match(regex, buf, (GRegexMatchFlags) 0, &matchinfo)){ if(g_match_info_get_match_count(matchinfo) == 3){ // not a subpackage gchar * classname = g_match_info_fetch(matchinfo, 2); g_hash_table_insert(initlua_requires, g_strdup(classname), g_strdup(classname)); }else if(g_match_info_get_match_count(matchinfo) == 4){ // this is a subpackage // XXX fprintf(stderr, "> buff: %s\n", buf); gchar * superpackage = g_match_info_fetch(matchinfo, 1); gchar * subpackage = g_match_info_fetch(matchinfo, 2); // XXX fprintf(stderr, "> super: %s, sub: %s\n", superpackage, subpackage); gchar * fullsubpackage = g_strjoin("", superpackage, subpackage, NULL); // XXX fprintf(stderr, "> [2] inserting: %s\n", fullsubpackage); g_hash_table_insert(initlua_requires_subpack, g_strdup(fullsubpackage), g_strdup(fullsubpackage)); g_free(fullsubpackage); } } g_match_info_free(matchinfo); g_regex_unref(regex); } fclose(init_lua_fp); init_lua_fp = NULL; } init_lua_fp = fopen(initlua_fname, "w"); // XXX fprintf(stderr, "> opened: %s\n", initlua_fname); if (!init_lua_fp) { perror ("fopen"); free (initlua_fname); g_free(package_name); return -1; } #ifndef WIN32 // lock init.lua for exclusive write access // TODO do the equivalent in windows struct flock lockinfo; lockinfo.l_type = F_WRLCK; lockinfo.l_start = 0; lockinfo.l_whence = SEEK_SET; lockinfo.l_len = 0 ; lockinfo.l_pid = getpid(); if(0 != fcntl(fileno(init_lua_fp), F_SETLKW, &lockinfo)) { perror("locking init.lua"); free(initlua_fname); g_free(package_name); fclose(init_lua_fp); return -1; } #endif fprintf (init_lua_fp, "--[[\n" "LCM package init.lua file\n" "This file automatically generated by lcm-gen.\n" "DO NOT MODIFY BY HAND!!!!\n" "--]]\n" "\n" "local M = {}\n" "\n"); // add in all previous types GList * package_types = g_hash_table_get_values(initlua_requires); for (int j = 0; j < g_list_length(package_types); j++) { char * tn = (char *) g_list_nth_data(package_types, j); char * fn = g_strjoin(".", package_name, tn, NULL); fprintf(init_lua_fp, "M.%s = require('%s')\n", tn, fn); g_free(fn); } g_list_free(package_types); // add in all previous packages GList * subpacks = g_hash_table_get_values(initlua_requires_subpack); for (int j = 0; j < g_list_length(subpacks); j++) { char * spn = (char *) g_list_nth_data(subpacks, j); // get the base of the package name char ** tmpsplit = g_strsplit(spn, ".", -1); char * sn = tmpsplit[g_strv_length(tmpsplit) - 1]; // XXX fprintf(stderr, "[1] sn: %s, spn: %s\n", sn, spn); fprintf(init_lua_fp, "M.%s = require('%s') -- subpackage\n", sn, spn); g_strfreev(tmpsplit); } g_list_free(subpacks); // if the current package has a subpackage (which eventually contains the target package) // add a `require` for that subpackage to the current (if it hasn't already) if (i + 1 < ndirs) { char *subpack_name = g_strjoin(".", package_name, dirs[i + 1], NULL); // check for the subpackage name if (!g_hash_table_lookup(initlua_requires_subpack, subpack_name)) { // add it if it didn't exist g_hash_table_insert(initlua_requires_subpack, g_strdup(subpack_name), g_strdup(subpack_name)); // XXX fprintf(stderr, "[2] sn: %s, spn: %s\n", dirs[i + 1], subpack_name); fprintf(init_lua_fp, "M.%s = require('%s') -- subpackage\n", dirs[i + 1], subpack_name); } g_free(subpack_name); } // not yet the target? if (i + 1 < ndirs) { // close it out fprintf(init_lua_fp, "\nreturn M\n\n"); fclose(init_lua_fp); init_lua_fp = NULL; } free (initlua_fname); g_free(package_name); } } g_strfreev (dirs); //////////////////////////////////////////////////////////// // STRUCTS for (int i = 0; i<pc->structs->len; i++) { lcm_struct_t *ls = (lcm_struct_t *) g_ptr_array_index(pc->structs, i); char path[PATH_MAX]; sprintf (path, "%s%s.lua", package_dir, ls->structname->shortname); if(init_lua_fp){ // XXX add the 'require' to the appropriate init.lua if (!g_hash_table_lookup(initlua_requires, ls->structname->shortname)) { fprintf(init_lua_fp, "M.%s = require('%s')\n", ls->structname->shortname, ls->structname->lctypename); } // XXX look for subpackages for (unsigned int m = 0; m < g_ptr_array_size(ls->members); m++) { lcm_member_t *lm = (lcm_member_t *) g_ptr_array_index(ls->members, m); if(g_str_has_prefix(lm->type->package, pc->name)){ // make a regex starting with the current package... gchar ** tmpsplit = g_strsplit(pc->name, ".", 0); gchar * regexpackage = g_strjoinv("\\.", tmpsplit); // only look for immediate submodules, not submodules of the submodules gchar * regexstr = g_strjoin("", "^", regexpackage, "\\.(\\w+)", NULL); GRegex * regex = g_regex_new(regexstr, (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL); GMatchInfo * matchinfo; g_strfreev(tmpsplit); g_free(regexpackage); g_free(regexstr); if (g_regex_match(regex, lm->type->package, (GRegexMatchFlags) 0, &matchinfo)) { if (g_match_info_get_match_count(matchinfo) == 2) { gchar * fullsubpackage = g_match_info_fetch(matchinfo, 0); gchar * subpackage = g_match_info_fetch(matchinfo, 1); // was it already in the file? if (!g_hash_table_lookup(initlua_requires_subpack, fullsubpackage)) { // XXX fprintf(stderr, "> [1] inserting: %s\n", fullsubpackage); g_hash_table_insert(initlua_requires_subpack, g_strdup(fullsubpackage), g_strdup(fullsubpackage)); fprintf(init_lua_fp, "M.%s = require('%s') -- subpackage\n", subpackage, fullsubpackage); } } } g_match_info_free(matchinfo); g_regex_unref(regex); } } } if (!lcm_needs_generation(lcm, ls->lcmfile, path)) continue; FILE *f = fopen(path, "w"); if (f==NULL) return -1; fprintf(f, "--[[\n" "LCM type definitions\n" "This file automatically generated by lcm.\n" "DO NOT MODIFY BY HAND!!!!\n" "--]]\n" "\n" "local lcm = require('lcm')\n\n"); emit_lua_dependencies (lcm, f, ls); // XXX added this... emit_lua_locals(lcm, f, ls); emit_lua_buffer_helper(lcm, f, ls); // XXX step 3, start making the object emit(0, "local %s = {}", ls->structname->shortname); emit(0, "%s.__index = %s", ls->structname->shortname, ls->structname->shortname); emit(0, ""); // CONSTANTS 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); } if (g_ptr_array_size(ls->constants) > 0) emit(0, ""); // NAMES emit(0, "%s.name = '%s'", ls->structname->shortname, ls->structname->lctypename); emit(0, "%s.packagename = '%s'", ls->structname->shortname, ls->structname->package); emit(0, "%s.shortname = '%s'", ls->structname->shortname, ls->structname->shortname); emit(0, ""); emit_lua_new (lcm, f, ls); emit_lua_fingerprint (lcm, f, ls); emit_lua_encode (lcm, f, ls); emit_lua_encode_one (lcm, f, ls); emit_lua_decode (lcm, f, ls); emit_lua_decode_one (lcm, f, ls); emit(0, "return %s", ls->structname->shortname); emit(0, ""); fclose (f); } if(init_lua_fp){ fprintf(init_lua_fp, "\nreturn M\n\n"); fclose(init_lua_fp); } g_hash_table_destroy(initlua_requires); return 0; }
int emit_enum(lcmgen_t *lcmgen, lcm_enum_t *le) { char *tn = le->enumname->lctypename; char *tn_ = dots_to_underscores(tn); char *header_name = g_strdup_printf("%s/%s.h", getopt_get_string(lcmgen->gopt, "c-hpath"), tn_); char *c_name = g_strdup_printf("%s/%s.c", getopt_get_string(lcmgen->gopt, "c-cpath"), tn_); // ENUM header file if (lcm_needs_generation(lcmgen, le->lcmfile, header_name)) { FILE *f = fopen(header_name, "w"); if (f == NULL) return -1; emit_header_top(lcmgen, f, tn_); char *tn_upper = g_ascii_strup (tn_, strlen (tn_)); /////////////////////////////////////////////////////////////////// // the enum declaration itself emit(0, "enum _%s {", tn_); for (unsigned int i = 0; i < g_ptr_array_size(le->values); i++) { lcm_enum_value_t *lev = (lcm_enum_value_t *) g_ptr_array_index(le->values, i); emit(1," %s_%s = %d%s", tn_upper, lev->valuename, lev->value, i==(g_ptr_array_size(le->values)-1) ? "" : ","); } free (tn_upper); emit(0, "};"); emit(0, ""); emit(0, "typedef enum _%s %s;", tn_, tn_); emit(0, ""); emit(0, "const char * %s_name(%s val);", tn_, tn_); emit(0, ""); /////////////////////////////////////////////////////////////////// emit(0, "static inline int64_t __%s_hash_recursive(const __lcm_hash_ptr *p)", tn_); emit(0, "{"); emit(1, "return 0x%016"PRIx64"LL;", le->hash); emit(0, "}"); emit(0, ""); emit(0, "static inline int64_t __%s_get_hash()", tn_); emit(0, "{"); emit(1, "return 0x%016"PRIx64"LL;", le->hash); emit(0, "}"); emit(0, ""); // enums are always "ints", but "ints" are not always int32_t. We // always store an enum as an int32_t, however. Consequently, we // jump through some hoops here in order to allow the compiler to // convert from an int32_t to whatever the native size of "int" // is. emit(0, "static inline int __%s_encode_array(void *_buf, int offset, int maxlen, const %s *p, int elements)", tn_, tn_); emit(0, "{"); emit(1, "int pos = 0, thislen, element;"); emit(1, "for (element = 0; element < elements; element++) {"); emit(2, "int32_t v = (int32_t) p[element];"); emit(2, "thislen = __int32_t_encode_array(_buf, offset + pos, maxlen - pos, &v, 1);"); emit(2, "if (thislen < 0) return thislen; else pos += thislen;"); emit(1, "}"); emit(1, "return thislen;"); emit(0, "}"); emit(0, ""); emit(0,"static inline int %s_encode(void *buf, int offset, int maxlen, const %s *p)", tn_, tn_); emit(0,"{"); emit(1, "int pos = 0, thislen;"); emit(1, "int64_t hash = 0x%016"PRIx64"LL;", le->hash); emit(0,""); emit(1, "thislen = __int64_t_encode_array(buf, offset + pos, maxlen - pos, &hash, 1);"); emit(1, "if (thislen < 0) return thislen; else pos += thislen;"); emit(0,""); emit(1, "thislen = __%s_encode_array(buf, offset + pos, maxlen - pos, p, 1);", tn_); emit(1, "if (thislen < 0) return thislen; else pos += thislen;"); emit(0,""); emit(1, "return pos;"); emit(0,"}"); emit(0,""); emit(0, "static inline int __%s_decode_array(const void *_buf, int offset, int maxlen, %s *p, int elements)", tn_, tn_); emit(0, "{"); emit(1, "int pos = 0, thislen, element;"); emit(1, "for (element = 0; element < elements; element++) {"); emit(2, "int32_t v;"); emit(2, "thislen = __int32_t_decode_array(_buf, offset + pos, maxlen - pos, &v, 1);"); emit(2, "if (thislen < 0) return thislen; else pos += thislen;"); emit(2, "p[element] = (%s) v;", tn_); emit(1, "}"); emit(1, "return thislen;"); emit(0, "}"); emit(0, ""); emit(0, "static inline int __%s_clone_array(const %s *p, %s *q, int elements)", tn_, tn_, tn_); emit(0, "{"); emit(1, "memcpy(q, p, elements * sizeof(%s));", tn_); emit(1, "return 0;"); emit(0, "}"); emit(0, ""); emit(0,"static inline int %s_decode(const void *buf, int offset, int maxlen, %s *p)", tn_, tn_); emit(0,"{"); emit(1, "int pos = 0, thislen;"); emit(1, "int64_t hash = 0x%016"PRIx64"LL;", le->hash); emit(0,""); emit(1, "int64_t this_hash;"); emit(1, "thislen = __int64_t_decode_array(buf, offset + pos, maxlen - pos, &this_hash, 1);"); emit(1, "if (thislen < 0) return thislen; else pos += thislen;"); emit(1, "if (this_hash != hash) return -1;"); emit(0,""); emit(1, "thislen = __%s_decode_array(buf, offset + pos, maxlen - pos, p, 1);", tn_); emit(1, "if (thislen < 0) return thislen; else pos += thislen;"); emit(0,""); emit(1, "return pos;"); emit(0,"}"); emit(0,""); emit(0, "static inline int __%s_decode_array_cleanup(%s *in, int elements)", tn_, tn_); emit(0, "{"); emit(1, "return 0;"); emit(0, "}"); emit(0, ""); emit(0,"static inline int %s_decode_cleanup(%s *p)", tn_, tn_); emit(0,"{"); emit(1, "return 0;"); emit(0,"}"); emit(0,""); emit(0, "static inline int __%s_encoded_array_size(const %s *p, int elements)", tn_, tn_); emit(0, "{"); emit(1, "return __int32_t_encoded_array_size((const int32_t*)p, elements);"); emit(0, "}"); emit(0, ""); emit(0, "static inline int %s_encoded_size(const %s *in)", tn_, tn_); emit(0, "{"); emit(1, "return int32_t_encoded_size((const int32_t*)in);"); emit(0, "}"); emit(0, ""); emit_header_bottom(lcmgen, f); fclose(f); } // ENUM C file if (lcm_needs_generation(lcmgen, le->lcmfile, c_name)) { char *tn_upper = g_ascii_strup (tn_, strlen (tn_)); FILE *f = fopen(c_name, "w"); emit_auto_generated_warning(f); fprintf(f, "#include \"%s%s%s.h\"\n", getopt_get_string(lcmgen->gopt, "cinclude"), strlen(getopt_get_string(lcmgen->gopt, "cinclude"))>0 ? "/" : "", tn_); emit(0, "const char * %s_name(%s val)", tn_, tn_); emit(0, "{"); emit(1, "switch (val) {"); for (unsigned int i = 0; i < g_ptr_array_size(le->values); i++) { lcm_enum_value_t *lev = (lcm_enum_value_t *) g_ptr_array_index(le->values, i); emit(2, "case %s_%s:", tn_upper, lev->valuename); emit(3, "return \"%s\";", lev->valuename); } emit(2, "default:"); emit(3, "return NULL;"); emit(1, "}"); emit(0, "}"); fclose(f); free (tn_upper); } return 0; }
int emit_struct(lcmgen_t *lcmgen, lcm_struct_t *lr) { char *tn = lr->structname->lctypename; char *tn_ = dots_to_underscores(tn); char *header_name = g_strdup_printf("%s/%s.h", getopt_get_string(lcmgen->gopt, "c-hpath"), tn_); char *c_name = g_strdup_printf("%s/%s.c", getopt_get_string(lcmgen->gopt, "c-cpath"), tn_); if (lcm_needs_generation(lcmgen, lr->lcmfile, header_name)) { FILE *f = fopen(header_name, "w"); if (f == NULL) return -1; emit_header_top(lcmgen, f, tn_); emit_header_struct(lcmgen, f, lr); emit_header_prototypes(lcmgen, f, lr); emit_header_bottom(lcmgen, f); fclose(f); } // STRUCT C file if (lcm_needs_generation(lcmgen, lr->lcmfile, c_name)) { FILE *f = fopen(c_name, "w"); if (f == NULL) return -1; emit_auto_generated_warning(f); fprintf(f, "#include <string.h>\n"); fprintf(f, "#include \"%s%s%s.h\"\n", getopt_get_string(lcmgen->gopt, "cinclude"), strlen(getopt_get_string(lcmgen->gopt, "cinclude"))>0 ? "/" : "", tn_); fprintf(f, "\n"); emit_c_struct_get_hash(lcmgen, f, lr); emit_c_encode_array(lcmgen, f, lr); emit_c_encode(lcmgen, f, lr); emit_c_encoded_array_size(lcmgen, f, lr); emit_c_encoded_size(lcmgen, f, lr); if(getopt_get_bool(lcmgen->gopt, "c-typeinfo")) { emit_c_struct_size(lcmgen, f, lr); emit_c_num_fields(lcmgen, f, lr); emit_c_get_field(lcmgen, f, lr); emit_c_get_type_info(lcmgen, f, lr); } emit_c_decode_array(lcmgen, f, lr); emit_c_decode_array_cleanup(lcmgen, f, lr); emit_c_decode(lcmgen, f, lr); emit_c_decode_cleanup(lcmgen, f, lr); emit_c_clone_array(lcmgen, f, lr); emit_c_copy(lcmgen, f, lr); emit_c_destroy(lcmgen, f, lr); if(!getopt_get_bool(lcmgen->gopt, "c-no-pubsub")) { emit_c_struct_publish(lcmgen, f, lr ); emit_c_struct_subscribe(lcmgen, f, lr ); } fclose(f); } return 0; }