summaryrefslogtreecommitdiff
path: root/tools/upbc.c
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-08-24 21:44:22 -0700
committerJoshua Haberman <joshua@reverberate.org>2009-08-24 21:44:22 -0700
commit040f7e6ba2e2282b80f332a031b77d7d34b4fc85 (patch)
tree1d5e273fb9fcca51f6ce299b766ee0a97ee92863 /tools/upbc.c
parenta223f9af30738cf00c313fabee8de75d04fb9a1a (diff)
Significant memory-management refactoring any Python extension.
Diffstat (limited to 'tools/upbc.c')
-rw-r--r--tools/upbc.c124
1 files changed, 81 insertions, 43 deletions
diff --git a/tools/upbc.c b/tools/upbc.c
index a324971..885a259 100644
--- a/tools/upbc.c
+++ b/tools/upbc.c
@@ -15,6 +15,8 @@
#include "upb_enum.h"
#include "upb_msg.h"
#include "upb_text.h"
+#include "upb_array.h"
+#include "upb_mm.h"
/* These are in-place string transformations that do not change the length of
* the string (and thus never need to re-allocate). */
@@ -54,32 +56,24 @@ void *strtable_to_array(struct upb_strtable *t, int *size)
return array;
}
-/* The .h file defines structs for the types defined in the .proto file. It
- * also defines constants for the enum values.
- *
- * Assumes that d has been validated. */
-static void write_h(struct upb_symtab_entry *entries[], int num_entries,
- char *outfile_name, char *descriptor_cident, FILE *stream)
+/* The _const.h file defines the constants (enums) defined in the .proto
+ * file. */
+static void write_const_h(struct upb_symtab_entry *entries[], int num_entries,
+ char *outfile_name, FILE *stream)
{
/* Header file prologue. */
struct upb_string *include_guard_name = upb_strdupc(outfile_name);
to_preproc(include_guard_name);
+ /* A bit cheesy, but will do the job. */
+ include_guard_name->ptr[include_guard_name->byte_len-1] = 'C';
fputs("/* This file was generated by upbc (the upb compiler). "
"Do not edit. */\n\n", stream),
fprintf(stream, "#ifndef " UPB_STRFMT "\n", UPB_STRARG(include_guard_name));
fprintf(stream, "#define " UPB_STRFMT "\n\n", UPB_STRARG(include_guard_name));
- fputs("#include <upb_string.h>\n\n", stream);
- fputs("#include <upb_array.h>\n\n", stream);
fputs("#ifdef __cplusplus\n", stream);
fputs("extern \"C\" {\n", stream);
fputs("#endif\n\n", stream);
- if(descriptor_cident) {
- fputs("struct google_protobuf_FileDescriptorSet;\n", stream);
- fprintf(stream, "extern struct google_protobuf_FileDescriptorSet *%s;\n\n",
- descriptor_cident);
- }
-
/* Enums. */
fprintf(stream, "/* Enums. */\n\n");
for(int i = 0; i < num_entries; i++) { /* Foreach enum */
@@ -109,12 +103,45 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), v->number);
if(j != ed->value->len-1) fputc(',', stream);
fputc('\n', stream);
- upb_strfree(value_name);
+ upb_string_unref(value_name);
}
}
fprintf(stream, "} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name));
- upb_strfree(enum_name);
- upb_strfree(enum_val_prefix);
+ upb_string_unref(enum_name);
+ upb_string_unref(enum_val_prefix);
+ }
+
+ /* Epilogue. */
+ fputs("#ifdef __cplusplus\n", stream);
+ fputs("} /* extern \"C\" */\n", stream);
+ fputs("#endif\n\n", stream);
+ fprintf(stream, "#endif /* " UPB_STRFMT " */\n", UPB_STRARG(include_guard_name));
+ upb_string_unref(include_guard_name);
+}
+
+/* The .h file defines structs for the types defined in the .proto file. It
+ * also defines constants for the enum values.
+ *
+ * Assumes that d has been validated. */
+static void write_h(struct upb_symtab_entry *entries[], int num_entries,
+ char *outfile_name, char *descriptor_cident, FILE *stream)
+{
+ /* Header file prologue. */
+ struct upb_string *include_guard_name = upb_strdupc(outfile_name);
+ to_preproc(include_guard_name);
+ fputs("/* This file was generated by upbc (the upb compiler). "
+ "Do not edit. */\n\n", stream),
+ fprintf(stream, "#ifndef " UPB_STRFMT "\n", UPB_STRARG(include_guard_name));
+ fprintf(stream, "#define " UPB_STRFMT "\n\n", UPB_STRARG(include_guard_name));
+ fputs("#include <upb_struct.h>\n\n", stream);
+ fputs("#ifdef __cplusplus\n", stream);
+ fputs("extern \"C\" {\n", stream);
+ fputs("#endif\n\n", stream);
+
+ if(descriptor_cident) {
+ fputs("struct google_protobuf_FileDescriptorSet;\n", stream);
+ fprintf(stream, "extern struct google_protobuf_FileDescriptorSet *%s;\n\n",
+ descriptor_cident);
}
/* Forward declarations. */
@@ -131,7 +158,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
fprintf(stream, "struct " UPB_STRFMT ";\n", UPB_STRARG(msg_name));
fprintf(stream, "typedef struct " UPB_STRFMT "\n " UPB_STRFMT ";\n\n",
UPB_STRARG(msg_name), UPB_STRARG(msg_name));
- upb_strfree(msg_name);
+ upb_string_unref(msg_name);
}
/* Message Declarations. */
@@ -144,8 +171,8 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
struct upb_string *msg_name = upb_strdup(&entry->e.key);
to_cident(msg_name);
fprintf(stream, "struct " UPB_STRFMT " {\n", UPB_STRARG(msg_name));
+ fputs(" struct upb_mmhead mmhead;\n", stream);
fputs(" struct upb_msgdef *def;\n", stream);
- fputs(" void *gptr;\n", stream);
fputs(" union {\n", stream);
fprintf(stream, " uint8_t bytes[%" PRIu32 "];\n", m->set_flags_bytes);
fputs(" struct {\n", stream);
@@ -179,7 +206,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
fprintf(stream, " " UPB_STRFMT "* " UPB_STRFMT ";\n",
UPB_STRARG(type_name), UPB_STRARG(fd->name));
}
- upb_strfree(type_name);
+ upb_string_unref(type_name);
} else if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) {
static char* c_types[] = {
"", "struct upb_double_array*", "struct upb_float_array*",
@@ -208,7 +235,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
fputs("};\n", stream);
fprintf(stream, "UPB_DEFINE_MSG_ARRAY(" UPB_STRFMT ")\n\n",
UPB_STRARG(msg_name));
- upb_strfree(msg_name);
+ upb_string_unref(msg_name);
}
/* Epilogue. */
@@ -216,7 +243,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries,
fputs("} /* extern \"C\" */\n", stream);
fputs("#endif\n\n", stream);
fprintf(stream, "#endif /* " UPB_STRFMT " */\n", UPB_STRARG(include_guard_name));
- upb_strfree(include_guard_name);
+ upb_string_unref(include_guard_name);
}
/* Format of table entries that we use when analyzing data structures for
@@ -300,24 +327,28 @@ static void add_strings_from_msg(void *data, struct upb_msgdef *m,
struct typetable_entry *get_or_insert_typeentry(struct upb_strtable *t,
struct upb_msg_fielddef *f)
{
- struct upb_string type_name = upb_issubmsg(f) ? f->ref.msg->fqname :
- upb_type_info[f->type].ctype;
- struct typetable_entry *type_e = upb_strtable_lookup(t, &type_name);
+ struct upb_string *type_name = upb_issubmsg(f) ? upb_strdup(&f->ref.msg->fqname) :
+ upb_strdupc(upb_type_info[f->type].ctype);
+ struct typetable_entry *type_e = upb_strtable_lookup(t, type_name);
if(type_e == NULL) {
struct typetable_entry new_type_e = {
- .e = {.key = type_name}, .field = f, .cident = upb_strdup(&type_name),
+ .e = {.key = *type_name}, .field = f, .cident = upb_strdup(type_name),
.values = NULL, .values_size = 0, .values_len = 0,
.arrays = NULL, .arrays_size = 0, .arrays_len = 0
};
to_cident(new_type_e.cident);
+ assert(upb_strtable_lookup(t, type_name) == NULL);
+ assert(upb_strtable_lookup(t, &new_type_e.e.key) == NULL);
upb_strtable_insert(t, &new_type_e.e);
- type_e = upb_strtable_lookup(t, &type_name);
+ type_e = upb_strtable_lookup(t, type_name);
assert(type_e);
+ } else {
+ upb_string_unref(type_name);
}
return type_e;
}
-static void add_value(union upb_value value, struct upb_msg_fielddef *f,
+static void add_value(union upb_value_ptr p, struct upb_msg_fielddef *f,
struct upb_strtable *t)
{
struct typetable_entry *type_e = get_or_insert_typeentry(t, f);
@@ -325,7 +356,7 @@ static void add_value(union upb_value value, struct upb_msg_fielddef *f,
type_e->values_size = UPB_MAX(type_e->values_size * 2, 4);
type_e->values = realloc(type_e->values, sizeof(*type_e->values) * type_e->values_size);
}
- type_e->values[type_e->values_len++] = value;
+ type_e->values[type_e->values_len++] = upb_value_read(p, f->type);
}
static void add_submsgs(void *data, struct upb_msgdef *m, struct upb_strtable *t)
@@ -353,7 +384,7 @@ static void add_submsgs(void *data, struct upb_msgdef *m, struct upb_strtable *t
/* Add the individual values in the array. */
for(uint32_t j = 0; j < arr->len; j++)
- add_value(upb_array_getelement(arr, j, f->type), f, t);
+ add_value(upb_array_getelementptr(arr, j, f->type), f, t);
/* Add submsgs. We must do this separately so that the msgs in this
* array are contiguous (and don't have submsgs of the same type
@@ -362,7 +393,7 @@ static void add_submsgs(void *data, struct upb_msgdef *m, struct upb_strtable *t
add_submsgs(*upb_array_getelementptr(arr, j, f->type).msg, f->ref.msg, t);
} else {
if(!upb_issubmsg(f)) continue;
- add_value(upb_deref(p, f->type), f, t);
+ add_value(p, f, t);
add_submsgs(*p.msg, f->ref.msg, t);
}
}
@@ -445,7 +476,8 @@ static void write_message_c(void *data, struct upb_msgdef *m,
.type = GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE,
.ref = {.msg = m}
};
- add_value(val, &fake_field, &types);
+ union upb_value_ptr p = UPB_VALUE_ADDROF(val);
+ add_value(p, &fake_field, &types);
add_submsgs(data, m, &types);
/* Emit foward declarations for all msgs of all types, and define arrays. */
@@ -503,7 +535,7 @@ static void write_message_c(void *data, struct upb_msgdef *m,
for(unsigned int j = 0; j < m->num_fields; j++) {
struct upb_msg_fielddef *f = &m->fields[j];
google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j];
- union upb_value val = upb_msg_get(msgdata, f);
+ union upb_value val = upb_value_read(upb_msg_getptr(msgdata, f), f->type);
fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name));
if(!upb_msg_isset(msgdata, f)) {
fputs("0, /* Not set. */", stream);
@@ -571,7 +603,7 @@ static void write_message_c(void *data, struct upb_msgdef *m,
/* Free tables. */
for(e = upb_strtable_begin(&types); e; e = upb_strtable_next(&types, &e->e)) {
- upb_strfree(e->cident);
+ upb_string_unref(e->cident);
free(e->values);
free(e->arrays);
}
@@ -641,16 +673,17 @@ int main(int argc, char *argv[])
if(!outfile_base) outfile_base = input_file;
/* Read input file. */
- struct upb_string *descriptor = upb_strnew();
- if(!upb_strreadfile(input_file, descriptor))
+ struct upb_string *descriptor = upb_strreadfile(input_file);
+ if(!descriptor)
error("Couldn't read input file.");
/* Parse input file. */
struct upb_context *c = upb_context_new();
- struct upb_msg *fds_msg = upb_msg_parsenew(c->fds_msg, descriptor);
- google_protobuf_FileDescriptorSet *fds = (void*)fds_msg;
- if(!fds)
+ struct upb_msg *fds_msg = upb_msg_new(c->fds_msg);
+ if(upb_msg_parsestr(fds_msg, descriptor->ptr, descriptor->byte_len) != UPB_STATUS_OK)
error("Failed to parse input file descriptor.");
+ //upb_msg_print(fds_msg, false, stderr);
+ google_protobuf_FileDescriptorSet *fds = (void*)fds_msg;
if(!upb_context_addfds(c, fds))
error("Failed to resolve symbols in descriptor.\n");
@@ -666,17 +699,21 @@ int main(int argc, char *argv[])
/* Emit output files. */
const int maxsize = 256;
- char h_filename[maxsize], c_filename[maxsize];
+ char h_filename[maxsize], h_const_filename[maxsize], c_filename[maxsize];
if(snprintf(h_filename, maxsize, "%s.h", outfile_base) >= maxsize ||
- snprintf(c_filename, maxsize, "%s.c", outfile_base) >= maxsize)
+ snprintf(c_filename, maxsize, "%s.c", outfile_base) >= maxsize ||
+ snprintf(h_const_filename, maxsize, "%s_const.h", outfile_base) >= maxsize)
error("File base too long.\n");
FILE *h_file = fopen(h_filename, "w");
if(!h_file) error("Failed to open .h output file");
+ FILE *h_const_file = fopen(h_const_filename, "w");
+ if(!h_const_file) error("Failed to open _const.h output file");
int symcount;
struct upb_symtab_entry **entries = strtable_to_array(&c->symtab, &symcount);
write_h(entries, symcount, h_filename, cident, h_file);
+ write_const_h(entries, symcount, h_filename, h_const_file);
free(entries);
if(cident) {
FILE *c_file = fopen(c_filename, "w");
@@ -684,10 +721,11 @@ int main(int argc, char *argv[])
write_message_c(fds, c->fds_msg, cident, h_filename, argc, argv, input_file, c_file);
fclose(c_file);
}
- upb_msg_free(fds_msg);
+ upb_msg_unref(fds_msg);
upb_context_unref(c);
- upb_strfree(descriptor);
+ upb_string_unref(descriptor);
fclose(h_file);
+ fclose(h_const_file);
return 0;
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback