Skip to content

Commit

Permalink
Amalgamated distribution (upb.c/upb.h) tool.
Browse files Browse the repository at this point in the history
There are a number of tweaks to get this to work:

- The #include dependence graph wasn't quite complete, and I had to add
  a few #includes to get the tool to work.

- I had to change a number of symbol names to avoid conflicts between
  'static' definitions in different .c files. This could be avoided if
  the tool were smart enough to rename static symbols to have unique
  prefixes instead, but (i) this requires semantic understanding of C,
  and (ii) the macro-defined static functions (e.g., handlers for
  primitive types in several places) would probably trip this up.

Verified that the resulting upb.h/upb.c compiles and doesn't have any
unresolved references.
  • Loading branch information
cfallin committed Dec 12, 2014
1 parent 56913be commit b3f6daf
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 116 deletions.
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# Threading:
# * -DUPB_THREAD_UNSAFE: remove all thread-safety.

.PHONY: all lib clean tests test benchmark descriptorgen
.PHONY: all lib clean tests test benchmark descriptorgen amalgamate
.PHONY: clean_leave_profile

# Prevents the deletion of intermediate files.
Expand Down Expand Up @@ -462,3 +462,13 @@ $(RUBYEXT): upb/bindings/ruby/upb.c upb/bindings/ruby/Makefile

rubytest: $(RUBYEXT) upb/descriptor/descriptor.pb
RUBYLIB="upb/bindings/ruby" ruby tests/bindings/ruby/upb.rb

# Amalgamated source (upb.c/upb.h) ############################################

AMALGAMATE_SRCS=$(upb_SRCS) $(upb_descriptor_SRCS) $(upb_pb_SRCS) $(upb_json_SRCS)

amalgamate: upb.c upb.h

upb.c upb.h: $(AMALGAMATE_SRCS)
$(E) AMALGAMATE $@
$(Q) ./tools/amalgamate.py "" "" $^
47 changes: 47 additions & 0 deletions tools/amalgamate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/python

import sys
import re

INCLUDE_RE = re.compile('^#include "([^"]*)"$')

def parse_include(line):
match = INCLUDE_RE.match(line)
return match.groups()[0] if match else None

class Amalgamator:
def __init__(self, include_path, output_path):
self.include_path = include_path
self.included = set()
self.output_h = open(output_path + "upb.h", "w")
self.output_c = open(output_path + "upb.c", "w")

self.output_c.write("// Amalgamated source file\n")
self.output_c.write('#include "upb.h"\n')

self.output_h.write("// Amalgamated source file\n")

def _process_file(self, infile_name, outfile):
for line in open(infile_name):
include = parse_include(line)
if include is not None and include.startswith("upb"):
if include not in self.included:
self.included.add(include)
self._add_header(self.include_path + include)
else:
outfile.write(line)

def _add_header(self, filename):
self._process_file(filename, self.output_h)

def add_src(self, filename):
self._process_file(filename, self.output_c)

# ---- main ----

include_path = sys.argv[1]
output_path = sys.argv[2]
amalgamator = Amalgamator(include_path, output_path)

for filename in sys.argv[3:]:
amalgamator.add_src(filename.strip())
24 changes: 14 additions & 10 deletions upb/handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
return sel;
}

static upb_selector_t getsel(upb_handlers *h, const upb_fielddef *f,
static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
upb_handlertype_t type) {
int32_t sel = trygetsel(h, f, type);
assert(sel >= 0);
Expand All @@ -129,7 +129,7 @@ static upb_selector_t getsel(upb_handlers *h, const upb_fielddef *f,

static const void **returntype(upb_handlers *h, const upb_fielddef *f,
upb_handlertype_t type) {
return &h->table[getsel(h, f, type)].attr.return_closure_type_;
return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_;
}

static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
Expand Down Expand Up @@ -213,18 +213,18 @@ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
if (upb_fielddef_isseq(f) &&
type != UPB_HANDLER_STARTSEQ &&
type != UPB_HANDLER_ENDSEQ &&
h->table[sel = getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
}

if (type == UPB_HANDLER_STRING &&
h->table[sel = getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
}

// The effective type of the submessage; not used yet.
// if (type == SUBMESSAGE &&
// h->table[sel = getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
// h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
// ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
// }

Expand All @@ -237,7 +237,7 @@ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
// the return closure type of this handler's attr.
bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
upb_status *status) {
upb_selector_t sel = getsel(h, f, type);
upb_selector_t sel = handlers_getsel(h, f, type);
if (h->table[sel].func) return true;
const void *closure_type = effective_closure_type(h, f, type);
const upb_handlerattr *attr = &h->table[sel].attr;
Expand Down Expand Up @@ -444,14 +444,18 @@ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {

if (upb_fielddef_issubmsg(f)) {
bool hashandler = false;
if (upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
if (upb_handlers_gethandler(
h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
upb_handlers_gethandler(
h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
hashandler = true;
}

if (upb_fielddef_isseq(f) &&
(upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
(upb_handlers_gethandler(
h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
upb_handlers_gethandler(
h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
hashandler = true;
}

Expand Down
1 change: 1 addition & 0 deletions upb/handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define UPB_HANDLERS_H

#include "upb/def.h"
#include "upb/table.int.h"

#ifdef __cplusplus
namespace upb {
Expand Down
Loading

0 comments on commit b3f6daf

Please sign in to comment.