| #!@PATH_PYTHON_PROG@ |
| # |
| # $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 implemented. Various 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 = [".", "@prefix@/share/@PACKAGE@" "/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: |