#!/usr/local/bin/python # # $Id: rbgen.in,v 1.3 2003/10/24 01:31:21 damo Exp $ # # rbgen -- generate a redblack customized search library # # $Log: rbgen.in,v $ # Revision 1.3 2003/10/24 01:31:21 damo # Patches from Eric Raymond: %prefix is other small # changes avoid stepping on global namespaces and improve the documentation. # # Revision 1.2 2003/10/23 04:18:47 damo # Fixed up the rbgen stuff ready for the 1.3 release # # Revision 1.1 2002/08/26 03:11:40 damo # Fixed up a bunch of compiler warnings when compiling example4 # # Tidies up the Makefile.am & Specfile. # # Renamed redblack to rbgen # # import sys, string, os fpin = sys.stdin lineno = 0 def error(msg, warning=0): sys.stderr.write('"%s", line %d: %s\n\n' % (fpin.name, lineno, msg)) if not warning: raise SyntaxError def startswith(line, prefix): return line[:len(prefix)] == prefix def include(file, fpout): try: fp = open(file) fpout.write(fp.read()) fp.close() except IOError: error("missing skeleton file %s!" % file) def redblack(filename, lines): rb_type = rb_cmp = rb_alloc = rb_free = rb_access = None rb_prefix = "rb" sbrk = static = 0 global lineno ext = string.find(filename, ".rb") if ext == -1: sys.stderr.write("redblack: extension on %s doesn't look right.\n" % filename) raise SyntaxError else: outfile = filename[:ext] + ".c" fpin = open(filename, "r") fpout = open(outfile, "w") if lines: fpout.write('#line 1 "%s"\n' % filename) while 1: line = fpin.readline() lineno = lineno + 1 if not line: break if startswith(line, "%%rbgen"): fpout.write("/* rbgen generated code begins here */\n") fpout.write("/* rbgen: $Id: rbgen.in,v 1.3 2003/10/24 01:31:21 damo Exp $ */\n") while 1: line = fpin.readline() lineno = lineno + 1 if not line: break comment = string.find(line, "//") if comment > -1: line = line[:comment] + "\n" if line[0] == "\n": continue elif startswith(line, "%%rbgen"): fpout.write("#define RB_CUSTOMIZE\n") if not rb_type: error("%type directive is required.") else: fpout.write("#define %sdata_t %s\n" % (rb_prefix, rb_type)) if not rb_cmp: error("%cmp directive is required.") else: fpout.write("#define RB_CMP(s, t) %s(s, t)\n" % rb_cmp) if rb_alloc: fpout.write("#define RB_ALLOC %s\n" % rb_alloc) if rb_free: fpout.write("#define RB_FREE %s\n"% rb_free) if rb_prefix: fpout.write("#define RB_ENTRY(name) %s##name\n" % rb_prefix) if rb_access is None or rb_access == "pointer": fpout.write("#undef RB_INLINE\n") elif rb_access == "inline": fpout.write("#define RB_INLINE\n") for func in rb_omit: fpout.write("#define no_%s\n" % func) if static: fpout.write("#define RB_STATIC static\n") else: fpout.write("#define RB_STATIC\n") if sbrk: fpout.write("#define RB_USE_SBRK\n") if lines: fpout.write('#line 1 "%s"\n' % outfile) include(h_skel, fpout) include(c_skel, fpout) fpout.write("/* rbgen generated code ends here */\n") if lines: fpout.write('#line %d "%s"\n' % (lineno, filename)) fpout.write(fpin.read()) return elif line[0] == "%": tokens = string.split(line) if tokens[0] in("%type","%cmp","%alloc","%free","%prefix"): exec "rb_" + tokens[0][1:] + " = '" + tokens[1] + "'" elif tokens[0] == "%access": if tokens[1] in ("inline", "pointer"): rb_access = tokens[1] else: error("unknown access type") elif tokens[0] == "%omit": omittable = ("destroy", "search", "find", "delete", "walk", "readlist", "lookup", "destroy", "delete", "readlist") rb_omit = tokens[1:] for func in rb_omit: if func not in omittable: error("%s cannot be omitted" % func) elif tokens[0] == "%sbrk": sbrk = 1 elif tokens[0] == "%static": static = 1 else: error("unknown directive %s" % string.split(line)[0]) else: error("garbage on line beginning %s." % line[0]) else: sys.stderr.write("rbgen: no end on directives section.\n") else: fpout.write(line) sys.stderr.write("rbgen: no directives found.\n") raise SyntaxError if __name__ == "__main__": import getopt (options, arguments) = getopt.getopt(sys.argv[1:], "lS:") lines = 1; skelpath = [".", "/share/libredblack" "/share/redblack"] for (switch, val) in options: if (switch == '-l'): lines = 0 elif (switch == '-S'): skeldir = val for skeldir in skelpath: h_skel = os.path.join(skeldir, "redblack.h") c_skel = os.path.join(skeldir, "redblack.c") if os.path.exists(h_skel) and os.path.exists(c_skel): break else: sys.stderr.write("rbgen: can't find skeleton file\n") for file in arguments: try: redblack(file, lines) raise SystemExit, 0 except SyntaxError: raise SystemExit, 1 # The following sets edit modes for GNU EMACS # Local Variables: # mode:python # End: