]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
initial version
authorGuido van Rossum <guido@python.org>
Wed, 18 Jan 1995 23:45:01 +0000 (23:45 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 18 Jan 1995 23:45:01 +0000 (23:45 +0000)
Tools/bgen/bgen/bgen.py [new file with mode: 0644]
Tools/bgen/bgen/bgenGenerator.py [new file with mode: 0644]
Tools/bgen/bgen/bgenGeneratorGroup.py [new file with mode: 0644]
Tools/bgen/bgen/bgenModule.py [new file with mode: 0644]
Tools/bgen/bgen/bgenObjectDefinition.py [new file with mode: 0644]
Tools/bgen/bgen/bgenOutput.py [new file with mode: 0644]
Tools/bgen/bgen/bgenType.py [new file with mode: 0644]

diff --git a/Tools/bgen/bgen/bgen.py b/Tools/bgen/bgen/bgen.py
new file mode 100644 (file)
index 0000000..aab35de
--- /dev/null
@@ -0,0 +1,7 @@
+"Export everything in the various bgen submodules."
+
+from bgenType import *
+from bgenOutput import *
+from bgenGenerator import *
+from bgenModule import *
+from bgenObjectDefinition import *
diff --git a/Tools/bgen/bgen/bgenGenerator.py b/Tools/bgen/bgen/bgenGenerator.py
new file mode 100644 (file)
index 0000000..ce38763
--- /dev/null
@@ -0,0 +1,173 @@
+from bgenOutput import *
+from bgenType import *
+
+
+Error = "bgenGenerator.Error"
+
+
+# Strings to specify argument transfer modes in generator calls
+IN = "in"
+OUT = "out"
+INOUT = IN_OUT = "in-out"
+
+
+class Generator:
+
+       # XXX There are some funny things with the argument list.
+       # XXX It would be better to get rid of this and require
+       # XXX each argument to be a type object or a tuple of the form
+       # XXX (inoutmode, typeobject, argumentname)
+       # XXX or possibly even a Variable() instance...
+
+       def __init__(self, *argumentList):
+               apply(self.parseArguments, argumentList)
+               self.prefix     = "XXX"    # Will be changed by setprefix() call
+               self.objecttype = "object" # Type of _self argument to function
+               self.itselftype = None     # Type of _self->ob_itself, if defined
+
+       def setprefix(self, prefix):
+               self.prefix = prefix
+
+       def setselftype(self, selftype, itselftype):
+               self.objecttype = selftype
+               self.itselftype = itselftype
+
+       def parseArguments(self, returnType, name, *argumentList):
+               if returnType:
+                       self.rv = Variable(returnType, "_rv", OutMode)
+               else:
+                       self.rv = None
+               self.name = name
+               self.argumentList = []
+               if self.rv:
+                       self.argumentList.append(rv)
+               self.parseArgumentList(argumentList)
+
+       def parseArgumentList(self, argumentList):
+               from types import *
+               iarg = 0
+               for arg in argumentList:
+                       # Arguments can either be:
+                       # - a type
+                       # - a tuple (type, [name, [mode]])
+                       # - a variable
+                       iarg = iarg + 1
+                       if hasattr(arg, 'typeName'):
+                               arg = Variable(arg)
+                       elif type(arg) == TupleType:
+                               arg = apply(Variable, arg)
+                       if arg.name is None:
+                               arg.name = "_arg%d" % iarg
+                       self.argumentList.append(arg)
+
+       def reference(self, name = None):
+               if name is None:
+                       name = self.name
+               Output("{\"%s\", (PyCFunction)%s_%s, 1},",
+                      name, self.prefix, self.name)
+
+       def generate(self):
+               self.functionheader()
+               self.declarations()
+               self.getargs()
+               self.callit()
+               self.checkit()
+               self.returnvalue()
+               self.functiontrailer()
+
+       def functionheader(self):
+               Output()
+               Output("static PyObject *%s_%s(_self, _args)",
+                      self.prefix, self.name)
+               IndentLevel()
+               Output("%s *_self;", self.objecttype)
+               Output("PyObject *_args;")
+               DedentLevel()
+               OutLbrace()
+
+       def declarations(self):
+               for arg in self.argumentList:
+                       arg.declare()
+
+       def getargs(self):
+               fmt = ""
+               lst = ""
+               for arg in self.argumentList:
+                       if arg.flags == SelfMode:
+                               continue
+                       if arg.mode in (InMode, InOutMode):
+                               fmt = fmt + arg.getargsFormat()
+                               lst = lst + ", " + arg.getargsArgs()
+               Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
+               IndentLevel()
+               Output("return NULL;")
+               DedentLevel()
+               for arg in self.argumentList:
+                       if arg.flags == SelfMode:
+                               continue
+                       if arg.mode in (InMode, InOutMode):
+                               arg.getargsCheck()
+
+       def callit(self):
+               args = ""
+               for arg in self.argumentList:
+                       if arg is self.rv:
+                               continue
+                       s = arg.passArgument()
+                       if args: s = ", " + s
+                       args = args + s
+               if self.rv:
+                       Output("%s = %s(%s);",
+                              self.rv.name, self.name, args)
+               else:
+                       Output("%s(%s);", self.name, args)
+
+       def checkit(self):
+               for arg in self.argumentList:
+                       arg.errorCheck()
+
+       def returnvalue(self):
+               fmt = ""
+               lst = ""
+               for arg in self.argumentList:
+                       if not arg: continue
+                       if arg.flags == ErrorMode: continue
+                       if arg.mode in (OutMode, InOutMode):
+                               fmt = fmt + arg.mkvalueFormat()
+                               lst = lst + ", " + arg.mkvalueArgs()
+               if fmt == "":
+                       Output("Py_INCREF(Py_None);")
+                       Output("return Py_None;");
+               else:
+                       Output("return Py_BuildValue(\"%s\"%s);", fmt, lst)
+
+       def functiontrailer(self):
+               OutRbrace()
+
+
+class ManualGenerator(Generator):
+
+       def __init__(self, name, body):
+               self.name = name
+               self.body = body
+
+       def definition(self):
+               self.functionheader()
+               Output("%s", self.body)
+               self.functiontrailer()
+
+
+def _test():
+       void = None
+       eggs = Generator(void, "eggs",
+                        Variable(stringptr, 'cmd'),
+                        Variable(int, 'x'),
+                        Variable(double, 'y', InOutMode),
+                        Variable(int, 'status', ErrorMode),
+                       )
+       eggs.setprefix("spam")
+       print "/* START */"
+       eggs.generate()
+
+if __name__ == "__main__":
+       _test()
diff --git a/Tools/bgen/bgen/bgenGeneratorGroup.py b/Tools/bgen/bgen/bgenGeneratorGroup.py
new file mode 100644 (file)
index 0000000..b8cd72e
--- /dev/null
@@ -0,0 +1,35 @@
+from bgenOutput import *
+
+class GeneratorGroup:
+
+       def __init__(self, prefix):
+               self.prefix = prefix
+               self.generators = []
+
+       def add(self, g):
+               g.setprefix(self.prefix)
+               self.generators.append(g)
+
+       def generate(self):
+               for g in self.generators:
+                       g.generate()
+               Output()
+               Output("static struct methodlist %s_methods[] = {", self.prefix)
+               IndentLevel()
+               for g in self.generators:
+                       g.reference()
+               Output("{NULL, NULL, 0}")
+               DedentLevel()
+               Output("};")
+
+
+def _test():
+       from bgenGenerator import Generator
+       group = GeneratorGroup("spam")
+       eggs = Generator(void, "eggs")
+       group.add(eggs)
+       print "/* START */"
+       group.generate()
+
+if __name__ == "__main__":
+       _test()
diff --git a/Tools/bgen/bgen/bgenModule.py b/Tools/bgen/bgen/bgenModule.py
new file mode 100644 (file)
index 0000000..8f23004
--- /dev/null
@@ -0,0 +1,69 @@
+from bgenOutput import *
+from bgenGeneratorGroup import GeneratorGroup
+
+class Module(GeneratorGroup):
+
+       def __init__(self, name, prefix = None,
+                    includestuff = None,
+                    initstuff = None):
+               GeneratorGroup.__init__(self, prefix or name)
+               self.name = name
+               self.includestuff = includestuff
+               self.initstuff = initstuff
+
+       def addobject(self, od):
+               self.generators.append(od)
+
+       def generate(self):
+               OutHeader1("Module " + self.name)
+               Output("#include <Python.h>")
+               Output()
+
+               if self.includestuff:
+                       Output()
+                       Output("%s", self.includestuff)
+
+               self.declareModuleVariables()
+
+               GeneratorGroup.generate(self)
+
+               Output()
+               Output("void init%s()", self.name)
+               OutLbrace()
+               Output("object *m;")
+               Output("object *d;")
+               Output()
+
+               if self.initstuff:
+                       Output("%s", self.initstuff)
+                       Output()
+
+               Output("m = initmodule(\"%s\", %s_methods);",
+                      self.name, self.prefix)
+               Output("d = getmoduledict(m);")
+               self.createModuleVariables()
+               OutRbrace()
+               OutHeader1("End module " + self.name)
+
+       def declareModuleVariables(self):
+               self.errorname = self.prefix + "_Error"
+               Output("static object *%s;", self.errorname)
+
+       def createModuleVariables(self):
+               Output("""if ((%s = newstringobject("%s.Error")) == NULL ||""",
+                              self.errorname,       self.name)
+               Output("""    dictinsert(d, "Error", %s) != 0)""",
+                                                    self.errorname)
+               Output("""\tfatal("can't initialize %s.Error");""",
+                                                   self.name)
+
+
+def _test():
+       from bgenGenerator import Generator
+       m = Module("spam", "", "#include <stdio.h>")
+       g = Generator(None, "bacon")
+       m.add(g)
+       m.generate()
+
+if __name__ == "__main__":
+       _test()
diff --git a/Tools/bgen/bgen/bgenObjectDefinition.py b/Tools/bgen/bgen/bgenObjectDefinition.py
new file mode 100644 (file)
index 0000000..6573fd4
--- /dev/null
@@ -0,0 +1,130 @@
+from bgenOutput import *
+from bgenGeneratorGroup import GeneratorGroup
+
+class ObjectDefinition(GeneratorGroup):
+
+       def __init__(self, name, prefix, itselftype):
+               import string
+               GeneratorGroup.__init__(self, prefix or name)
+               self.name = name
+               self.itselftype = itselftype
+               self.objecttype = name + 'Object'
+               self.typename = self.prefix + '_' + \
+                               string.upper(name[:1]) + \
+                               string.lower(name[1:]) + '_Type'
+
+       def add(self, g):
+               g.setselftype(self.objecttype, self.itselftype)
+               GeneratorGroup.add(self, g)
+
+       def reference(self):
+               # In case we are referenced from a module
+               pass
+
+       def generate(self):
+               # XXX This should use long strings and %(varname)s substitution!
+
+               OutHeader2("Object type " + self.name)
+
+               Output("staticforward PyTypeObject %s;", self.typename)
+               Output()
+
+               Output("#define is_%sobject(x) ((x)->ob_type == %s)",
+                      self.name, self.typename)
+               Output()
+
+               Output("typedef struct {")
+               IndentLevel()
+               Output("OB_HEAD")
+               Output("%s ob_itself;", self.itselftype)
+               DedentLevel()
+               Output("} %s;", self.objecttype)
+               Output()
+
+               Output("static %s *new%s(itself)", self.objecttype, self.objecttype)
+               IndentLevel()
+               Output("%s itself;", self.itselftype)
+               DedentLevel()
+               OutLbrace()
+               Output("%s *it;", self.objecttype)
+               Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
+               Output("if (it == NULL) return NULL;")
+               Output("it->ob_itself = itself;")
+               Output("return it;")
+               OutRbrace()
+               Output()
+
+               Output("static void %s_dealloc(self)", self.prefix)
+               IndentLevel()
+               Output("%s *self;", self.objecttype)
+               DedentLevel()
+               OutLbrace()
+##             Output("if (self->ob_itself != NULL)")
+##             OutLbrace()
+##             self.outputFreeIt("self->ob_itself")
+##             OutRbrace()
+               Output("DEL(self);")
+               OutRbrace()
+               Output()
+
+##             Output("static int %s_converter(p_itself, p_it)", self.prefix)
+##             IndentLevel()
+##             Output("%s *p_itself;", self.itselftype)
+##             Output("%s **p_it;", self.objecttype)
+##             DedentLevel()
+##             OutLbrace()
+##             Output("if (**p_it == NULL)")
+##             OutLbrace()
+##             Output("*p_it = new%s(*p_itself);", self.objecttype)
+##             OutRbrace()
+##             Output("else")
+##             OutLbrace()
+##             Output("*p_itself = (*p_it)->ob_itself;")
+##             OutRbrace()
+##             Output("return 1;")
+##             OutRbrace()
+##             Output()
+
+               GeneratorGroup.generate(self)
+
+               self.outputGetattr()
+
+               self.outputSetattr()
+
+               Output("static PyTypeObject %s = {", self.typename)
+               IndentLevel()
+               Output("PyObject_HEAD_INIT(&PyType_Type)")
+               Output("0, /*ob_size*/")
+               Output("\"%s\", /*tp_name*/", self.name)
+               Output("sizeof(%s), /*tp_basicsize*/", self.objecttype)
+               Output("0, /*tp_itemsize*/")
+               Output("/* methods */")
+               Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix)
+               Output("0, /*tp_print*/")
+               Output("(getattrfunc) %s_getattr, /*tp_getattr*/", self.prefix)
+               Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix)
+               DedentLevel()
+               Output("};")
+
+               OutHeader2("End object type " + self.name)
+
+       def outputFreeIt(self, name):
+               Output("DEL(%s); /* XXX */", name)
+
+       def outputGetattr(self):
+               Output("static PyObject *%s_getattr(self, name)", self.prefix)
+               IndentLevel()
+               Output("%s *self;", self.objecttype)
+               Output("char *name;")
+               DedentLevel()
+               OutLbrace()
+               self.outputGetattrBody()
+               OutRbrace()
+               Output()
+
+       def outputGetattrBody(self):
+               Output("return findmethod(self, %s_methods, name);", self.prefix)
+
+       def outputSetattr(self):
+               Output("#define %s_setattr NULL", self.prefix)
+               Output()
diff --git a/Tools/bgen/bgen/bgenOutput.py b/Tools/bgen/bgen/bgenOutput.py
new file mode 100644 (file)
index 0000000..06ca3ed
--- /dev/null
@@ -0,0 +1,129 @@
+"""Output primitives for the binding generator classes.
+
+This should really be a class, but then everybody would be passing
+the output object to each other.  I chose for the simpler approach
+of a module with a global variable.  Use SetOutputFile() to change
+the output file.
+"""
+
+def SetOutputFile(file = None):
+       """Call this with an open file object to make that the output file.
+
+       Call it without arguments to reset the output file to sys.stdout.
+       """
+       global _File
+       if file is None:
+               import sys
+               file = sys.stdout
+       _File = file
+
+SetOutputFile()        # Initialize _File
+
+_Level = 0             # Indentation level
+
+def GetLevel():
+       """"Return the current indentation level."""
+       return _Level
+
+def SetLevel(level):
+       """Set the current indentation level.
+
+       This does no type or range checking -- use at own risk.
+       """
+       global _Level
+       _Level = level
+
+def Output(format = "", *args):
+       """Call this with a format string and arguments for the format.
+
+       A newline is always added.  Each line in the output is indented
+       to the proper indentation level -- even if the result of the
+       format expansion contains embedded newlines.  Exception: lines
+       beginning with '#' are not indented -- these are assumed to be
+       C preprprocessor lines.
+       """
+       text = format % args
+       if _Level > 0:
+               indent = '\t' * _Level
+               import string
+               lines = string.splitfields(text, '\n')
+               for i in range(len(lines)):
+                       if lines[i] and lines[i][0] != '#':
+                               lines[i] = indent + lines[i]
+               text = string.joinfields(lines, '\n')
+       _File.write(text + '\n')
+
+def IndentLevel(by = 1):
+       """Increment the indentation level by one.
+
+       When called with an argument, adds it to the indentation level.
+       """
+       global _Level
+       if _Level+by < 0:
+               raise Error, "indentation underflow (internal error)"
+       _Level = _Level + by
+
+def DedentLevel(by = 1):
+       """Decfrement the indentation level by one.
+
+       When called with an argument, subtracts it from the indentation level.
+       """
+       IndentLevel(-by)
+
+def OutLbrace():
+       """Output a '{' on a line by itself and increase the indentation level."""
+       Output("{")
+       IndentLevel()
+
+def OutRbrace():
+       """Decrease the indentation level and output a '}' on a line by itself."""
+       DedentLevel()
+       Output("}")
+
+def OutHeader(text, dash):
+       """Output a header comment using a given dash character."""
+       n = 64 - len(text)
+       Output()
+       Output("/* %s %s %s */", dash * (n/2), text, dash * (n - n/2))
+       Output()
+
+def OutHeader1(text):
+       """Output a level 1 header comment (uses '=' dashes)."""
+       OutHeader(text, "=")
+
+def OutHeader2(text):
+       """Output a level 2 header comment (uses '-' dashes)."""
+       OutHeader(text, "-")
+
+
+def _test():
+       """Test program.  Run when the module is run as a script."""
+       OutHeader1("test bgenOutput")
+       Output("""
+#include <Python.h>
+#include <stdio.h>
+""")
+       Output("main(argc, argv)")
+       IndentLevel()
+       Output("int argc;")
+       Output("char **argv;")
+       DedentLevel()
+       OutLbrace()
+       Output("int i;")
+       Output()
+       Output("""\
+/* Here are a few comment lines.
+   Just to test indenting multiple lines.
+
+   End of the comment lines. */
+""")
+       Output("for (i = 0; i < argc; i++)")
+       OutLbrace()
+       Output('printf("argv[%%d] = %%s\\n", i, argv[i]);')
+       OutRbrace()
+       Output("exit(0)")
+       OutRbrace()
+       OutHeader2("end test")
+
+if __name__ == '__main__':
+       _test()
diff --git a/Tools/bgen/bgen/bgenType.py b/Tools/bgen/bgen/bgenType.py
new file mode 100644 (file)
index 0000000..66f78eb
--- /dev/null
@@ -0,0 +1,362 @@
+"""Type and Variable classes and a modest collection of standard types."""
+
+from bgenOutput import *
+
+
+# Values to represent argument transfer modes
+InMode    = 1 # input-only argument
+OutMode   = 2 # output-only argument
+InOutMode = 3 # input-output argument
+ModeMask  = 3 # bits to keep for mode
+
+
+# Special cases for mode/flags argument
+# XXX This is still a mess!
+SelfMode   =  4+InMode  # this is 'self' -- don't declare it
+ReturnMode =  8+OutMode # this is the function return value
+ErrorMode  = 16+OutMode # this is an error status -- turn it into an exception
+
+
+class Type:
+
+       """Define the various things you can do with a C type.
+
+       Most methods are intended to be extended or overridden.
+       """
+
+       def __init__(self, typeName, fmt):
+               """Call with the C name and getargs format for the type.
+
+               Example: int = Type("int", "i")
+               """
+               self.typeName = typeName
+               self.fmt = fmt
+
+       def declare(self, name):
+               """Declare a variable of the type with a given name.
+
+               Example: int.declare('spam') prints "int spam;"
+               """
+               Output("%s %s;", self.typeName, name)
+
+       def getargsFormat(self):
+               """Return the format for this type for use with [new]getargs().
+
+               Example: int.getargsFormat() returns the string "i".
+               """
+               return self.fmt
+
+       def getargsArgs(self, name):
+               """Return an argument for use with [new]getargs().
+
+               Example: int.getargsArgs("spam") returns the string "&spam".
+               """
+               return "&" + name
+
+       def getargsCheck(self, name):
+               """Perform any needed post-[new]getargs() checks.
+
+               This is type-dependent; the default does not check for errors.
+               An example would be a check for a maximum string length."""
+
+       def passInput(self, name):
+               """Return an argument for passing a variable into a call.
+
+               Example: int.passInput("spam") returns the string "spam".
+               """
+               return name
+
+       def passOutput(self, name):
+               """Return an argument for returning a variable out of a call.
+
+               Example: int.passOutput("spam") returns the string "&spam".
+               """
+               return "&" + name
+
+       def errorCheck(self, name):
+               """Check for an error returned in the variable.
+
+               This is type-dependent; the default does not check for errors.
+               An example would be a check for a NULL pointer.
+               If an error is found, the generated routine should
+               raise an exception and return NULL.
+
+               XXX There should be a way to add error clean-up code.
+               """
+               Output("/* XXX no err check for %s %s */", self.typeName, name)
+
+       def mkvalueFormat(self):
+               """Return the format for this type for use with mkvalue().
+
+               This is normally the same as getargsFormat() but it is
+               a separate function to allow future divergence.
+               """
+               return self.getargsFormat()
+
+       def mkvalueArgs(self, name):
+               """Return an argument for use with mkvalue().
+
+               Example: int.mkvalueArgs("spam") returns the string "spam".
+               """
+               return name
+
+
+# A modest collection of standard C types.
+void = None
+short = Type("short", "h")
+int = Type("int", "i")
+long = Type("long", "l")
+float = Type("float", "f")
+double = Type("double", "d")
+stringptr = Type("char*", "s")
+char = Type("char", "c")
+
+
+# Some Python related types.
+objectptr = Type("object*", "O")
+stringobjectptr = Type("stringobject*", "S")
+# Etc.
+
+
+# Buffers are character arrays that may contain null bytes.
+# Their length is either Fixed or Sized (i.e. given by a separate argument).
+
+class SizedInputBuffer:
+
+       "Sized input buffer -- buffer size is an input parameter"
+
+       def __init__(self, size):
+               self.size = size
+
+       def declare(self, name):
+               Output("char *%s;", name)
+               Output("int %s__len__;", name)
+
+       def getargsFormat(self):
+               return "s#"
+
+       def getargsArgs(self, name):
+               return "%s, %s__len__" % (name, name)
+
+       def getargsCheck(self, name):
+               pass
+
+       def passInput(self, name):
+               return "%s, %s__len__" % (name, name)
+
+
+class FixedInputBuffer(SizedInputBuffer):
+
+       "Fixed input buffer -- buffer size is a constant"
+
+       def getargsCheck(self, name):
+               Output("if (%s__len__ != %s)", name, str(self.size))
+               IndentLevel()
+               Output('err_setstr(TypeError, "bad string length");')
+               DedentLevel()
+
+       def passInput(self, name):
+               return name
+
+
+class SizedOutputBuffer:
+
+       "Sized output buffer -- buffer size is an input-output parameter"
+
+       def __init__(self, maxsize):
+               self.maxsize = maxsize
+
+       def declare(self, name):
+               Output("char %s[%s];", name, str(self.maxsize))
+               Output("int %s__len__ = %s;", name, str(self.maxsize))
+
+       def passOutput(self, name):
+               return "%s, &%s__len__" % (name, name)
+
+       def errorCheck(self, name):
+               pass
+
+       def mkvalueFormat(self):
+               return "s#"
+
+       def mkvalueArgs(self, name):
+               return "%s, %s__len__" % (name, name)
+
+
+class FixedOutputBuffer:
+
+       "Fixed output buffer -- buffer size is a constant"
+
+       def __init__(self, size):
+               self.size = size
+
+       def declare(self, name):
+               Output("char %s[%s];", name, str(self.size))
+
+       def passOutput(self, name):
+               return name
+
+       def errorCheck(self, name):
+               pass
+
+       def mkvalueFormat(self):
+               return "s#"
+
+       def mkvalueArgs(self, name):
+               return "%s, %s" % (name, str(self.size))
+
+
+# Strings are character arrays terminated by a null byte.
+# For input, this is covered by stringptr.
+# For output, there are again two variants: Fixed (size is a constant
+# given in the documentation) or Sized (size is given by a variable).
+# (Note that this doesn't cover output parameters in which a string
+# pointer is returned.)
+
+class SizedOutputString:
+
+       "Null-terminated output string -- buffer size is an input parameter"
+
+       def __init__(self, bufsize):
+               self.bufsize = bufsize
+
+       def declare(self, name):
+               Output("char %s[%s];", name, str(self.bufsize))
+
+       def passOutput(self, name):
+               return "%s, %s" % (name, str(self.bufsize))
+
+       def errorCheck(self, name):
+               pass
+
+       def mkvalueFormat(self):
+               return "s"
+
+       def mkvalueArgs(self, name):
+               return name
+
+
+class FixedOutputString(SizedOutputString):
+
+       "Null-terminated output string -- buffer size is a constant"
+
+       def passOutput(self, name):
+               return name
+
+
+class StructureByValue:
+
+       "Structure passed by value -- mapped to a Python string (for now)"
+
+       def __init__(self, typeName):
+               self.typeName = typeName
+
+       def declare(self, name):
+               n = len(self.typeName)
+               Output("%-*s %s;",        n, self.typeName, name)
+               Output("%-*s*%s__str__;", n, "char",        name)
+               Output("%-*s %s__len__;", n, "int",         name)
+
+       def getargsFormat(self):
+               return "s#"
+
+       def getargsArgs(self, name):
+               return "&%s__str__, &%s__len__" % (name, name)
+
+       def getargsCheck(self, name):
+               Output("if (%s__len__ != sizeof %s)", name, name)
+               IndentLevel()
+               Output('err_setstr(TypeError, "bad structure length");')
+               DedentLevel()
+               Output("memcpy(&%s, %s__str__, %s__len__);",
+                      name, name, name)
+
+       def passInput(self, name):
+               return "%s" % name
+
+       def passOutput(self, name):
+               return "&%s" % name
+
+       def errorCheck(self, name):
+               pass
+
+       def mkvalueFormat(self):
+               return "s#"
+
+       def mkvalueArgs(self, name):
+               return "(char *)&%s, (int)sizeof %s" % (name, name)
+
+
+class StructureByAddress(StructureByValue):
+
+       def passInput(self, name):
+               return "&%s" % name
+
+
+class Variable:
+
+       """A Variable holds a type, a name, a transfer mode and flags.
+
+       Most of its methods call the correponding type method with the
+       variable name.
+       """
+
+       def __init__(self, type, name = None, flags = InMode):
+               """Call with a type, a name and flags.
+
+               If name is None, it muse be set later.
+               flags defaults to InMode.
+               """
+               self.type = type
+               self.name = name
+               self.flags = flags
+               self.mode = flags & ModeMask
+
+       def declare(self):
+               """Declare the variable if necessary.
+
+               If it is "self", it is not declared.
+               """
+               if self.flags != SelfMode:
+                       self.type.declare(self.name)
+
+       def getargsFormat(self):
+               """Call the type's getargsFormatmethod."""
+               return self.type.getargsFormat()
+
+       def getargsArgs(self):
+               """Call the type's getargsArgsmethod."""
+               return self.type.getargsArgs(self.name)
+
+       def getargsCheck(self):
+               return self.type.getargsCheck(self.name)
+
+       def passArgument(self):
+               """Return the string required to pass the variable as argument.
+
+               For "in" arguments, return the variable name.
+               For "out" and "in out" arguments,
+               return its name prefixed with "&".
+               """
+               if self.mode == InMode:
+                       return self.type.passInput(self.name)
+               if self.mode in (OutMode, InOutMode):
+                       return self.type.passOutput(self.name)
+               # XXX Shouldn't get here
+               return "/*mode?*/" + self.type.passInput(self.name)
+
+       def errorCheck(self):
+               """Check for an error if necessary.
+
+               This only generates code if the variable's mode is ErrorMode.
+               """
+               if self.flags == ErrorMode:
+                       self.type.errorCheck(self.name)
+
+       def mkvalueFormat (self):
+               """Call the type's mkvalueFormatmethod."""
+               return self.type.mkvalueFormat()
+
+       def mkvalueArgs(self):
+               """Call the type's mkvalueArgs method."""
+               return self.type.mkvalueArgs(self.name)