math/mpgen, symm/multigen: Fix the various build scripts for Python 3.
[catacomb] / math / mpgen
index 7d11bfd..c7dbf88 100644 (file)
@@ -28,10 +28,9 @@ from __future__ import with_statement
 
 import re as RX
 import optparse as OP
+import sys as SYS; stdout = SYS.stdout
 import types as TY
 
-from sys import stdout
-
 ###--------------------------------------------------------------------------
 ### Random utilities.
 
@@ -65,6 +64,22 @@ def fix_name(name):
   """Replace non-alphanumeric characters in NAME with underscores."""
   return R_IDBAD.sub('_', name)
 
+if SYS.version_info >= (3,):
+  def func_name(func): return func.__name__
+  xrange = range
+  long = int
+else:
+  def func_name(func): return func.func_name
+
+def with_metaclass(meta, *supers):
+  return meta('#<anonymous base %s>' % meta.__name__,
+              supers or (object,), dict())
+
+def load(file, mod):
+  with open(file) as f: text = f.read()
+  code = compile(text, file, 'exec')
+  exec(code, mod)
+
 ###--------------------------------------------------------------------------
 ### Determining the appropriate types.
 
@@ -83,7 +98,7 @@ class IntClass (type):
     except AttributeError: pass
     return c
 
-class BasicIntType (object):
+class BasicIntType (with_metaclass(IntClass)):
   """
   A base class for integer-type classes, providing defaults and protocol.
 
@@ -195,7 +210,7 @@ class TypeChoice (object):
 
     ## Load the captured type information.
     me.ti = TY.ModuleType('typeinfo')
-    execfile(opts.typeinfo, me.ti.__dict__)
+    load(opts.typeinfo, me.ti.__dict__)
 
     ## Build a map of the available types.
     tymap = {}
@@ -226,14 +241,14 @@ class TypeChoice (object):
 
     ## Make sure we've not ended up somewhere really silly.
     if mpwbits < 16:
-      raise Exception, "`mpw' type is too small: your C environment is weird"
+      raise Exception("`mpw' type is too small: your C environment is weird")
 
     ## Now figure out suitable types for `mpw' and `mpd'.
     def find_type(bits, what):
       for ty in byrank:
         if ty.bits >= bits: return ty
-      raise Exception, \
-          "failed to find suitable %d-bit type, for %s" % (bits, what)
+      raise Exception \
+        ("failed to find suitable %d-bit type, for %s" % (bits, what))
 
     ## Store our decisions.
     me.mpwbits = mpwbits
@@ -327,7 +342,7 @@ def defmode(func):
   arguments from the command and are expected to write their output to
   stdout.
   """
-  name = func.func_name
+  name = func_name(func)
   if name.startswith('m_'): name = name[2:]
   MODEMAP[name] = func
   return func
@@ -483,7 +498,7 @@ class GroupTableClass (type):
     else: MODEMAP[c.mode] = c.run
     return c
 
-class GroupTable (object):
+class GroupTable (with_metaclass(GroupTableClass)):
   """
   Base class for group tables objects.
 
@@ -568,8 +583,6 @@ class GroupTable (object):
   ## _slotmap           A dictionary mapping slot names to their
   ##                    descriptions.
 
-  __metaclass__ = GroupTableClass
-
   ## Default values.
   keyword = 'group'
   slots = []
@@ -644,7 +657,7 @@ class GroupTable (object):
 
         if ff[0] == 'alias':
           ## An alias.  Just remember this.
-          if len(ff) != 3: raise Exception, "wrong number of alias arguments"
+          if len(ff) != 3: raise Exception("wrong number of alias arguments")
           me._flush()
           me._names.append((ff[1], ff[2]))
 
@@ -654,7 +667,7 @@ class GroupTable (object):
           ## Check the headline syntax.  Headline slots may be set here, or
           ## later by name.
           if len(ff) < 2 or len(ff) > 2 + len(me._headslots):
-            raise Exception, "bad number of headline arguments"
+            raise Exception("bad number of headline arguments")
 
           ## Flush out the previous stanza.
           me._flush()
@@ -670,14 +683,14 @@ class GroupTable (object):
         elif ff[0] in me._slotmap:
           ## A slot assignment.  Get the slot to store a value.
           if me.st.name is None:
-            raise Exception, "no group currently being defined"
+            raise Exception("no group currently being defined")
           if len(ff) != 2:
-            raise Exception, "bad number of values for slot `%s'" % ff[0]
+            raise Exception("bad number of values for slot `%s'" % ff[0])
           me._slotmap[ff[0]].set(me.st, ff[1])
 
         else:
           ## Something incomprehensible.
-          raise Exception, "unknown keyword `%s'" % ff[0]
+          raise Exception("unknown keyword `%s'" % ff[0])
 
     ## End of the input.  Write out the final stanza.
     me._flush()
@@ -687,7 +700,7 @@ class GroupTable (object):
     stdout.write("\nconst %s %s[] = {\n" % (me.entry_t, me.tabname))
     for a, n in me._names:
       if n not in me._defs:
-        raise Exception, "alias `%s' refers to unknown group `%s'" % (a, n)
+        raise Exception("alias `%s' refers to unknown group `%s'" % (a, n))
       stdout.write('  { "%s", &c_%s },\n' % (a, fix_name(n)))
     stdout.write("  { 0, 0 }\n};\n\n")
 
@@ -747,7 +760,7 @@ class BaseSlot (object):
     Store a VALUE for the slot.
     """
     if me._allowp and not me._allowp(st, value):
-      raise Exception, "slot `%s' not allowed here" % me.name
+      raise Exception("slot `%s' not allowed here" % me.name)
     st.d[me] = value
 
   def setup(me, st):
@@ -755,7 +768,7 @@ class BaseSlot (object):
     Prepare the slot for output, checking its value and so on.
     """
     if me not in st.d and (not me._omitp or not me._omitp(st)):
-      raise Exception, "missing slot `%s'" % me.name
+      raise Exception("missing slot `%s'" % me.name)
 
 class EnumSlot (BaseSlot):
   """
@@ -781,7 +794,7 @@ class EnumSlot (BaseSlot):
     Check that the VALUE is one of the ones we know.
     """
     if value not in me._values:
-      raise Exception, "invalid %s value `%s'" % (me.name, value)
+      raise Exception("invalid %s value `%s'" % (me.name, value))
     super(EnumSlot, me).set(st, value)
 
   def write(me, st):