]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
checkin of Jack's original version
authorGuido van Rossum <guido@python.org>
Thu, 2 Mar 1995 14:05:29 +0000 (14:05 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 2 Mar 1995 14:05:29 +0000 (14:05 +0000)
27 files changed:
Tools/modulator/EXAMPLE.py [new file with mode: 0644]
Tools/modulator/README [new file with mode: 0644]
Tools/modulator/ScrolledListbox.py [new file with mode: 0644]
Tools/modulator/Templates/copyright [new file with mode: 0644]
Tools/modulator/Templates/module_head [new file with mode: 0644]
Tools/modulator/Templates/module_method [new file with mode: 0644]
Tools/modulator/Templates/module_tail [new file with mode: 0644]
Tools/modulator/Templates/object_head [new file with mode: 0644]
Tools/modulator/Templates/object_method [new file with mode: 0644]
Tools/modulator/Templates/object_mlist [new file with mode: 0644]
Tools/modulator/Templates/object_new [new file with mode: 0644]
Tools/modulator/Templates/object_structure [new file with mode: 0644]
Tools/modulator/Templates/object_tail [new file with mode: 0644]
Tools/modulator/Templates/object_tp_as_mapping [new file with mode: 0644]
Tools/modulator/Templates/object_tp_as_number [new file with mode: 0644]
Tools/modulator/Templates/object_tp_as_sequence [new file with mode: 0644]
Tools/modulator/Templates/object_tp_compare [new file with mode: 0644]
Tools/modulator/Templates/object_tp_dealloc [new file with mode: 0644]
Tools/modulator/Templates/object_tp_getattr [new file with mode: 0644]
Tools/modulator/Templates/object_tp_hash [new file with mode: 0644]
Tools/modulator/Templates/object_tp_print [new file with mode: 0644]
Tools/modulator/Templates/object_tp_repr [new file with mode: 0644]
Tools/modulator/Templates/object_tp_setattr [new file with mode: 0644]
Tools/modulator/Tkextra.py [new file with mode: 0755]
Tools/modulator/genmodule.py [new file with mode: 0755]
Tools/modulator/modulator.py [new file with mode: 0755]
Tools/modulator/varsubst.py [new file with mode: 0644]

diff --git a/Tools/modulator/EXAMPLE.py b/Tools/modulator/EXAMPLE.py
new file mode 100644 (file)
index 0000000..4043699
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Example input file for modulator if you don't have tk.
+#
+# You may also have to strip some imports out of modulator to make
+# it work.
+#
+# Generate code for a simple object with a method called sample
+
+o = genmodule.object()
+o.name = 'simple object'
+o.abbrev = 'simp'
+o.methodlist = ['sample']
+o.funclist = ['new']
+
+#
+# Generate code for an object that looks numberish
+#
+o2 = genmodule.object()
+o2.name = 'number-like object'
+o2.abbrev = 'nl'
+o2.typelist = ['tp_as_number']
+o2.funclist = ['new', 'tp_repr', 'tp_compare']
+
+#
+# Generate code for a method with a full complement of functions,
+# some methods, accessible as sequence and allowing structmember.c type
+# structure access as well.
+#
+o3 = genmodule.object()
+o3.name = 'over-the-top object'
+o3.abbrev = 'ot'
+o3.methodlist = ['method1', 'method2']
+o3.funclist = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
+           'tp_compare', 'tp_repr', 'tp_hash']
+o3.typelist = ['tp_as_sequence', 'structure']
+
+#
+# Now generate code for a module that incorporates these object types.
+# Also add the boilerplates for functions to create instances of each
+# type.
+#
+m = genmodule.module()
+m.name = 'sample'
+m.abbrev = 'sample'
+m.methodlist = ['newsimple', 'newnumberish', 'newott']
+m.objects = [o, o2, o3]
diff --git a/Tools/modulator/README b/Tools/modulator/README
new file mode 100644 (file)
index 0000000..7ed09c8
--- /dev/null
@@ -0,0 +1,17 @@
+This is release 1.0 of modulator, a generator of boilerplate code for
+modules to be written in C.
+
+Usage when you have tk is *reall* simple: start modulator, fill out
+the forms specifying all the objects and methods, tell modulator
+whether objects should also be accessible as sequences, etc and press
+'generate code'. It will write a complete skeleton module for you.
+
+Usage when you don't have tk is slightly more difficult. Look at
+EXAMPLE.py for some details.
+
+Oh yeah: you'll probably want to change Templates/copyright, or all
+your code ends up as being copyrighted to CWI:-)
+
+Let me know what you think,
+                               Jack Jansen, jack@cwi.nl
+                               
diff --git a/Tools/modulator/ScrolledListbox.py b/Tools/modulator/ScrolledListbox.py
new file mode 100644 (file)
index 0000000..89686ef
--- /dev/null
@@ -0,0 +1,37 @@
+# A ScrolledList widget feels like a list widget but also has a
+# vertical scroll bar on its right.  (Later, options may be added to
+# add a horizontal bar as well, to make the bars disappear
+# automatically when not needed, to move them to the other side of the
+# window, etc.)
+#
+# Configuration options are passed to the List widget.
+# A Frame widget is inserted between the master and the list, to hold
+# the Scrollbar widget.
+# Most methods calls are inherited from the List widget; Pack methods
+# are redirected to the Frame widget however.
+
+from Tkinter import *
+from Tkinter import _cnfmerge
+
+class ScrolledListbox(Listbox):
+       def __init__(self, master=None, cnf={}):
+               cnf = _cnfmerge(cnf)
+               fcnf = {}
+               vcnf = {'name': 'vbar',
+                       Pack: {'side': 'right', 'fill': 'y'},}
+               for k in cnf.keys():
+                       if type(k) == ClassType or k == 'name':
+                               fcnf[k] = cnf[k]
+                               del cnf[k]
+               self.frame = Frame(master, fcnf)
+               self.vbar = Scrollbar(self.frame, vcnf)
+               cnf[Pack] = {'side': 'left', 'fill': 'both', 'expand': 'yes'}
+               cnf['name'] = 'list'
+               Listbox.__init__(self, self.frame, cnf)
+               self['yscrollcommand'] = (self.vbar, 'set')
+               self.vbar['command'] = (self, 'yview')
+
+               # Copy Pack methods of self.frame -- hack!
+               for m in Pack.__dict__.keys():
+                       if m[0] != '_' and m != 'config':
+                               setattr(self, m, getattr(self.frame, m))
diff --git a/Tools/modulator/Templates/copyright b/Tools/modulator/Templates/copyright
new file mode 100644 (file)
index 0000000..86206c3
--- /dev/null
@@ -0,0 +1,23 @@
+/***********************************************************
+Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
+The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
diff --git a/Tools/modulator/Templates/module_head b/Tools/modulator/Templates/module_head
new file mode 100644 (file)
index 0000000..d1fafdc
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "allobjects.h"
+#include "modsupport.h"                /* For getargs() etc. */
+
+static object *ErrorObject;
+
+/* ----------------------------------------------------- */
diff --git a/Tools/modulator/Templates/module_method b/Tools/modulator/Templates/module_method
new file mode 100644 (file)
index 0000000..bf64e79
--- /dev/null
@@ -0,0 +1,12 @@
+
+static object *
+$abbrev$_$method$(self, args)
+       object *self;   /* Not used */
+       object *args;
+{
+
+       if (!newgetargs(args, ""))
+               return NULL;
+       INCREF(None);
+       return None;
+}
diff --git a/Tools/modulator/Templates/module_tail b/Tools/modulator/Templates/module_tail
new file mode 100644 (file)
index 0000000..466c84a
--- /dev/null
@@ -0,0 +1,30 @@
+
+/* List of methods defined in the module */
+
+static struct methodlist $abbrev$_methods[] = {
+ $methodlist$
+ {NULL,                NULL}           /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called init$name$) */
+
+void
+init$name$()
+{
+       object *m, *d;
+
+       /* Create the module and add the functions */
+       m = initmodule("$name$", $abbrev$_methods);
+
+       /* Add some symbolic constants to the module */
+       d = getmoduledict(m);
+       ErrorObject = newstringobject("$name$.error");
+       dictinsert(d, "error", ErrorObject);
+
+       /* XXXX Add constants here */
+       
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module $name$");
+}
diff --git a/Tools/modulator/Templates/object_head b/Tools/modulator/Templates/object_head
new file mode 100644 (file)
index 0000000..bf69a51
--- /dev/null
@@ -0,0 +1,12 @@
+/* Declarations for objects of type $name$ */
+
+typedef struct {
+       OB_HEAD
+       /* XXXX Add your own stuff here */
+} $abbrev$object;
+
+staticforward typeobject $Abbrev$type;
+
+#define is_$abbrev$object(v)           ((v)->ob_type == &$Abbrev$type)
+
+/* ---------------------------------------------------------------- */
diff --git a/Tools/modulator/Templates/object_method b/Tools/modulator/Templates/object_method
new file mode 100644 (file)
index 0000000..20896de
--- /dev/null
@@ -0,0 +1,11 @@
+
+static object *
+$abbrev$_$method$(self, args)
+       $abbrev$object *self;
+       object *args;
+{
+       if (!newgetargs(args, ""))
+               return NULL;
+       INCREF(None);
+       return None;
+}
diff --git a/Tools/modulator/Templates/object_mlist b/Tools/modulator/Templates/object_mlist
new file mode 100644 (file)
index 0000000..62d5894
--- /dev/null
@@ -0,0 +1,7 @@
+
+static struct methodlist $abbrev$_methods[] = {
+ $methodlist$
+ {NULL,                NULL}           /* sentinel */
+};
+
+/* ---------- */
diff --git a/Tools/modulator/Templates/object_new b/Tools/modulator/Templates/object_new
new file mode 100644 (file)
index 0000000..1817a55
--- /dev/null
@@ -0,0 +1,12 @@
+
+static $abbrev$object *
+new$abbrev$object()
+{
+       $abbrev$object *self;
+       
+       self = NEWOBJ($abbrev$object, &$Abbrev$type);
+       if (self == NULL)
+               return NULL;
+       /* XXXX Add your own initializers here */
+       return self;
+}
diff --git a/Tools/modulator/Templates/object_structure b/Tools/modulator/Templates/object_structure
new file mode 100644 (file)
index 0000000..6a54518
--- /dev/null
@@ -0,0 +1,41 @@
+/* Code to access structure members by accessing attributes */
+
+#include "structmember.h"
+
+#define OFF(x) offsetof(XXXXobject, x)
+
+static struct memberlist $abbrev$_memberlist[] = {
+       /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO }  */
+       {NULL}  /* Sentinel */
+};
+
+static object *
+$abbrev$_getattr(self, name)
+       $abbrev$object *self;
+       char *name;
+{
+       object *rv;
+       
+       /* XXXX Add your own getattr code here */
+       rv = getmember((char *)/*XXXX*/0, $abbrev$_memberlist, name);
+       if (rv)
+               return rv;
+       err_clear();
+       return findmethod($abbrev$_methods, (object *)self, name);
+}
+
+
+static int
+$abbrev$_setattr(self, name, v)
+       $abbrev$object *self;
+       char *name;
+       object *v;
+{
+       /* XXXX Add your own setattr code here */
+       if ( v == NULL ) {
+               err_setstr(AttributeError, "Cannot delete attribute");
+               return -1;
+       }
+       return setmember((char *)/*XXXX*/0, $abbrev$_memberlist, name, v);
+}
+
diff --git a/Tools/modulator/Templates/object_tail b/Tools/modulator/Templates/object_tail
new file mode 100644 (file)
index 0000000..9bc78ca
--- /dev/null
@@ -0,0 +1,22 @@
+
+static typeobject $Abbrev$type = {
+       OB_HEAD_INIT(&Typetype)
+       0,                              /*ob_size*/
+       "$name$",                       /*tp_name*/
+       sizeof($abbrev$object),         /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)$tp_dealloc$,       /*tp_dealloc*/
+       (printfunc)$tp_print$,          /*tp_print*/
+       (getattrfunc)$tp_getattr$,      /*tp_getattr*/
+       (setattrfunc)$tp_setattr$,      /*tp_setattr*/
+       (cmpfunc)$tp_compare$,          /*tp_compare*/
+       (reprfunc)$tp_repr$,            /*tp_repr*/
+       $tp_as_number$,                 /*tp_as_number*/
+       $tp_as_sequence$,               /*tp_as_sequence*/
+       $tp_as_mapping$,                /*tp_as_mapping*/
+       (hashfunc)$tp_hash$,            /*tp_hash*/
+};
+
+/* End of code for $name$ objects */
+/* -------------------------------------------------------- */
diff --git a/Tools/modulator/Templates/object_tp_as_mapping b/Tools/modulator/Templates/object_tp_as_mapping
new file mode 100644 (file)
index 0000000..c5edf3e
--- /dev/null
@@ -0,0 +1,33 @@
+/* Code to access $name$ objects as mappings */
+
+static int
+$abbrev$_length(self)
+       $abbrev$object *self;
+{
+       /* XXXX Return the size of the mapping */
+}
+
+static object *
+$abbrev$_subscript(self, key)
+       $abbrev$object *self;
+       object *key;
+{
+       /* XXXX Return the item of self indexed by key */
+}
+
+static int
+$abbrev$_ass_sub(self, v, w)
+       $abbrev$object *self;
+       object *v, *w;
+{
+       /* XXXX Put w in self under key v */
+       return 0;
+}
+
+static mapping_methods $abbrev$_as_mapping = {
+       (inquiry)$abbrev$_length,               /*mp_length*/
+       (binaryfunc)$abbrev$_subscript,         /*mp_subscript*/
+       (objobjargproc)$abbrev$_ass_sub,        /*mp_ass_subscript*/
+};
+
+/* -------------------------------------------------------- */
diff --git a/Tools/modulator/Templates/object_tp_as_number b/Tools/modulator/Templates/object_tp_as_number
new file mode 100644 (file)
index 0000000..b97d473
--- /dev/null
@@ -0,0 +1,249 @@
+/* Code to access $name$ objects as numbers */
+
+static object *
+$abbrev$_add(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX Add them */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_sub(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX Subtract them */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_mul(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX Multiply them */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_div(x, y)
+       $abbrev$object *x;
+       $abbrev$object *y;
+{
+       /* XXXX Divide them */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_mod(x, y)
+       $abbrev$object *x;
+       $abbrev$object *y;
+{
+       /* XXXX Modulo them */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_divmod(x, y)
+       $abbrev$object *x;
+       $abbrev$object *y;
+{
+       /* XXXX Return 2-tuple with div and mod */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_pow(v, w, z)
+       $abbrev$object *v;
+       $abbrev$object *w;
+       $abbrev$object *z;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}                              
+
+static object *
+$abbrev$_neg(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_pos(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_abs(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static int
+$abbrev$_nonzero(v)
+       $abbrev$object *v;
+{
+       /* XXXX Return 1 if non-zero */
+       err_setstr(SystemError, "not implemented");
+       return -1;
+}
+
+static object *
+$abbrev$_invert(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_lshift(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_rshift(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_and(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_xor(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_or(v, w)
+       $abbrev$object *v;
+       $abbrev$object *w;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static int
+$abbrev$_coerce(pv, pw)
+       object **pv;
+       object **pw;
+{
+       /* XXXX I haven't a clue... */
+       return 1;
+}
+
+static object *
+$abbrev$_int(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_long(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_float(v)
+       $abbrev$object *v;
+{
+       /* XXXX */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_oct(v)
+       $abbrev$object *v;
+{
+       /* XXXX Return object as octal stringobject */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static object *
+$abbrev$_hex(v)
+       $abbrev$object *v;
+{
+       /* XXXX Return object as hex stringobject */
+       err_setstr(SystemError, "not implemented");
+       return NULL;
+}
+
+static number_methods $abbrev$_as_number = {
+       (binaryfunc)$abbrev$_add,       /*nb_add*/
+       (binaryfunc)$abbrev$_sub,       /*nb_subtract*/
+       (binaryfunc)$abbrev$_mul,       /*nb_multiply*/
+       (binaryfunc)$abbrev$_div,       /*nb_divide*/
+       (binaryfunc)$abbrev$_mod,       /*nb_remainder*/
+       (binaryfunc)$abbrev$_divmod,    /*nb_divmod*/
+       (ternaryfunc)$abbrev$_pow,      /*nb_power*/
+       (unaryfunc)$abbrev$_neg,        /*nb_negative*/
+       (unaryfunc)$abbrev$_pos,        /*nb_positive*/
+       (unaryfunc)$abbrev$_abs,        /*nb_absolute*/
+       (inquiry)$abbrev$_nonzero,      /*nb_nonzero*/
+       (unaryfunc)$abbrev$_invert,     /*nb_invert*/
+       (binaryfunc)$abbrev$_lshift,    /*nb_lshift*/
+       (binaryfunc)$abbrev$_rshift,    /*nb_rshift*/
+       (binaryfunc)$abbrev$_and,       /*nb_and*/
+       (binaryfunc)$abbrev$_xor,       /*nb_xor*/
+       (binaryfunc)$abbrev$_or,        /*nb_or*/
+       (coercion)$abbrev$_coerce,      /*nb_coerce*/
+       (unaryfunc)$abbrev$_int,        /*nb_int*/
+       (unaryfunc)$abbrev$_long,       /*nb_long*/
+       (unaryfunc)$abbrev$_float,      /*nb_float*/
+       (unaryfunc)$abbrev$_oct,        /*nb_oct*/
+       (unaryfunc)$abbrev$_hex,        /*nb_hex*/
+};
+
+/* ------------------------------------------------------- */
diff --git a/Tools/modulator/Templates/object_tp_as_sequence b/Tools/modulator/Templates/object_tp_as_sequence
new file mode 100644 (file)
index 0000000..50f2f91
--- /dev/null
@@ -0,0 +1,73 @@
+
+/* Code to handle accessing $name$ objects as sequence objects */
+
+static int
+$abbrev$_length(self)
+       $abbrev$object *self;
+{
+       /* XXXX Return the size of the object */
+}
+
+static object *
+$abbrev$_concat(self, bb)
+       $abbrev$object *self;
+       object *bb;
+{
+       /* XXXX Return the concatenation of self and bb */
+}
+
+static object *
+$abbrev$_repeat(self, n)
+       $abbrev$object *self;
+       int n;
+{
+       /* XXXX Return a new object that is n times self */
+}
+
+static object *
+$abbrev$_item(self, i)
+       $abbrev$object *self;
+       int i;
+{
+       /* XXXX Return the i-th object of self */
+}
+
+static object *
+$abbrev$_slice(self, ilow, ihigh)
+       $abbrev$object *self;
+       int ilow, ihigh;
+{
+       /* XXXX Return the ilow..ihigh slice of self in a new object */
+}
+
+static int
+$abbrev$_ass_item(self, i, v)
+       $abbrev$object *self;
+       int i;
+       object *v;
+{
+       /* XXXX Assign to the i-th element of self */
+       return 0;
+}
+
+static int
+$abbrev$_ass_slice(self, ilow, ihigh, v)
+       listobject *self;
+       int ilow, ihigh;
+       object *v;
+{
+       /* XXXX Replace ilow..ihigh slice of self with v */
+       return 0;
+}
+
+static sequence_methods $abbrev$_as_sequence = {
+       (inquiry)$abbrev$_length,               /*sq_length*/
+       (binaryfunc)$abbrev$_concat,            /*sq_concat*/
+       (intargfunc)$abbrev$_repeat,            /*sq_repeat*/
+       (intargfunc)$abbrev$_item,              /*sq_item*/
+       (intintargfunc)$abbrev$_slice,          /*sq_slice*/
+       (intobjargproc)$abbrev$_ass_item,       /*sq_ass_item*/
+       (intintobjargproc)$abbrev$_ass_slice,   /*sq_ass_slice*/
+};
+
+/* -------------------------------------------------------------- */
diff --git a/Tools/modulator/Templates/object_tp_compare b/Tools/modulator/Templates/object_tp_compare
new file mode 100644 (file)
index 0000000..a2e2e9d
--- /dev/null
@@ -0,0 +1,7 @@
+
+static int
+$abbrev$_compare(v, w)
+       $abbrev$object *v, *w;
+{
+       /* XXXX Compare objects and return -1, 0 or 1 */
+}
diff --git a/Tools/modulator/Templates/object_tp_dealloc b/Tools/modulator/Templates/object_tp_dealloc
new file mode 100644 (file)
index 0000000..b4d573e
--- /dev/null
@@ -0,0 +1,8 @@
+
+static void
+$abbrev$_dealloc(self)
+       $abbrev$object *self;
+{
+       /* XXXX Add your own cleanup code here */
+       DEL(self);
+}
diff --git a/Tools/modulator/Templates/object_tp_getattr b/Tools/modulator/Templates/object_tp_getattr
new file mode 100644 (file)
index 0000000..3e5542f
--- /dev/null
@@ -0,0 +1,9 @@
+
+static object *
+$abbrev$_getattr(self, name)
+       $abbrev$object *self;
+       char *name;
+{
+       /* XXXX Add your own getattr code here */
+       return findmethod($abbrev$_methods, (object *)self, name);
+}
diff --git a/Tools/modulator/Templates/object_tp_hash b/Tools/modulator/Templates/object_tp_hash
new file mode 100644 (file)
index 0000000..1681b4a
--- /dev/null
@@ -0,0 +1,7 @@
+
+static long
+$abbrev$_hash(self)
+       $abbrev$object *self;
+{
+       /* XXXX Return a hash of self (or -1) */
+}
diff --git a/Tools/modulator/Templates/object_tp_print b/Tools/modulator/Templates/object_tp_print
new file mode 100644 (file)
index 0000000..017712e
--- /dev/null
@@ -0,0 +1,10 @@
+
+static int
+$abbrev$_print(self, fp, flags)
+       $abbrev$object *self;
+       FILE *fp;
+       int flags;
+{
+       /* XXXX Add code here to print self to fp */
+       return 0;
+}
diff --git a/Tools/modulator/Templates/object_tp_repr b/Tools/modulator/Templates/object_tp_repr
new file mode 100644 (file)
index 0000000..45c78df
--- /dev/null
@@ -0,0 +1,10 @@
+
+static object *
+$abbrev$_repr(self)
+       $abbrev$object *self;
+{
+       object *s;
+
+       /* XXXX Add code here to put self into s */
+       return s;
+}
diff --git a/Tools/modulator/Templates/object_tp_setattr b/Tools/modulator/Templates/object_tp_setattr
new file mode 100644 (file)
index 0000000..d4da0ce
--- /dev/null
@@ -0,0 +1,10 @@
+
+static int
+$abbrev$_setattr(self, name, v)
+       $abbrev$object *self;
+       char *name;
+       object *v;
+{
+       /* XXXX Add your own setattr code here */
+       return -1;
+}
diff --git a/Tools/modulator/Tkextra.py b/Tools/modulator/Tkextra.py
new file mode 100755 (executable)
index 0000000..25681ae
--- /dev/null
@@ -0,0 +1,235 @@
+#! /usr/local/bin/python
+
+# A Python function that generates dialog boxes with a text message,
+# optional bitmap, and any number of buttons.
+# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
+
+from Tkinter import *
+
+mainWidget = None
+
+def dialog(master, title, text, bitmap, default, *args):
+
+    # 1. Create the top-level window and divide it into top
+    # and bottom parts.
+
+    w = Toplevel(master, {'class': 'Dialog'})
+    w.title(title)
+    w.iconname('Dialog')
+
+    top = Frame(w, {'relief': 'raised', 'bd': 1,
+                   Pack: {'side': 'top', 'fill': 'both'}})
+    bot = Frame(w, {'relief': 'raised', 'bd': 1,
+                   Pack: {'side': 'bottom', 'fill': 'both'}})
+
+    # 2. Fill the top part with the bitmap and message.
+
+    msg = Message(top,
+                 {'width': '3i',
+                  'text': text,
+                  'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
+                  Pack: {'side': 'right', 'expand': 1,
+                         'fill': 'both',
+                         'padx': '3m', 'pady': '3m'}})
+    if bitmap:
+       bm = Label(top, {'bitmap': bitmap,
+                        Pack: {'side': 'left',
+                               'padx': '3m', 'pady': '3m'}})
+
+    # 3. Create a row of buttons at the bottom of the dialog.
+
+    buttons = []
+    i = 0
+    for but in args:
+       b = Button(bot, {'text': but,
+                        'command': ('set', 'button', i)})
+       buttons.append(b)
+       if i == default:
+           bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
+                            Pack: {'side': 'left', 'expand': 1,
+                                   'padx': '3m', 'pady': '2m'}})
+           b.lift()
+           b.pack ({'in': bd, 'side': 'left',
+                    'padx': '2m', 'pady': '2m',
+                    'ipadx': '2m', 'ipady': '1m'})
+       else:
+           b.pack ({'side': 'left', 'expand': 1,
+                    'padx': '3m', 'pady': '3m',
+                    'ipady': '2m', 'ipady': '1m'})
+       i = i+1
+
+    # 4. Set up a binding for <Return>, if there's a default,
+    # set a grab, and claim the focus too.
+
+    if default >= 0:
+       w.bind('<Return>',
+              lambda e, b=buttons[default], i=default:
+              (b.flash(),
+               b.setvar('button', i)))
+
+    oldFocus = w.tk.call('focus') # XXX
+    w.grab_set()
+    w.focus()
+
+    # 5. Wait for the user to respond, then restore the focus
+    # and return the index of the selected button.
+
+    w.waitvar('button')
+    w.destroy()
+    w.tk.call('focus', oldFocus) # XXX
+    return w.getint(w.getvar('button'))
+
+def strdialog(master, title, text, bitmap, default, *args):
+
+    # 1. Create the top-level window and divide it into top
+    # and bottom parts.
+
+    w = Toplevel(master, {'class': 'Dialog'})
+    w.title(title)
+    w.iconname('Dialog')
+
+    top = Frame(w, {'relief': 'raised', 'bd': 1,
+                   Pack: {'side': 'top', 'fill': 'both'}})
+    if args:
+       bot = Frame(w, {'relief': 'raised', 'bd': 1,
+                   Pack: {'side': 'bottom', 'fill': 'both'}})
+
+    # 2. Fill the top part with the bitmap, message and input field.
+
+    if bitmap:
+       bm = Label(top, {'bitmap': bitmap,
+                        Pack: {'side': 'left',
+                               'padx': '3m', 'pady': '3m'}})
+
+    msg = Message(top,
+                 {'width': '3i',
+                  'text': text,
+                  'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
+                  Pack: {'side': 'left', 
+                         'fill': 'both',
+                         'padx': '3m', 'pady': '3m'}})
+
+    field = Entry(top,
+                 {'relief':'sunken',
+                  Pack:{'side':'left',
+                        'fill':'x',
+                        'expand':1,
+                        'padx':'3m', 'pady':'3m'}})
+    # 3. Create a row of buttons at the bottom of the dialog.
+
+    buttons = []
+    i = 0
+    for but in args:
+       b = Button(bot, {'text': but,
+                        'command': ('set', 'button', i)})
+       buttons.append(b)
+       if i == default:
+           bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
+                            Pack: {'side': 'left', 'expand': 1,
+                                   'padx': '3m', 'pady': '2m'}})
+           b.lift()
+           b.pack ({'in': bd, 'side': 'left',
+                    'padx': '2m', 'pady': '2m',
+                    'ipadx': '2m', 'ipady': '1m'})
+       else:
+           b.pack ({'side': 'left', 'expand': 1,
+                    'padx': '3m', 'pady': '3m',
+                    'ipady': '2m', 'ipady': '1m'})
+       i = i+1
+
+    # 4. Set up a binding for <Return>, if there's a default,
+    # set a grab, and claim the focus too.
+
+    if not args:
+       w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
+       field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
+    elif default >= 0:
+       w.bind('<Return>',
+              lambda e, b=buttons[default], i=default:
+              (b.flash(),
+               b.setvar('button', i)))
+       field.bind('<Return>',
+              lambda e, b=buttons[default], i=default:
+              (b.flash(),
+               b.setvar('button', i)))
+
+    oldFocus = w.tk.call('focus') # XXX
+    w.grab_set()
+    field.focus()
+
+    # 5. Wait for the user to respond, then restore the focus
+    # and return the index of the selected button.
+
+    w.waitvar('button')
+    v = field.get()
+    w.destroy()
+    w.tk.call('focus', oldFocus) # XXX
+    if args:
+       return v, w.getint(w.getvar('button'))
+    else:
+       return v
+
+def message(str):
+    i = dialog(mainWidget, 'Message', str, '', 0, 'OK')
+
+def askyn(str):
+    i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes')
+    return i
+
+def askync(str):
+    i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes')
+    return i-1
+
+def askstr(str):
+    i = strdialog(mainWidget, 'Question', str, '', 0)
+    return i
+
+def askfile(str):      # XXXX For now...
+    i = strdialog(mainWidget, 'Question', str, '', 0)
+    return i
+    
+# The rest is the test program.
+
+def _go():
+    i = dialog(mainWidget,
+              'Not Responding',
+              "The file server isn't responding right now; "
+              "I'll keep trying.",
+              '',
+              -1,
+              'OK')
+    print 'pressed button', i
+    i = dialog(mainWidget,
+              'File Modified',
+              'File "tcl.h" has been modified since '
+              'the last time it was saved. '
+              'Do you want to save it before exiting the application?',
+              'warning',
+              0,
+              'Save File',
+              'Discard Changes',
+              'Return To Editor')
+    print 'pressed button', i
+    print message('Test of message')
+    print askyn('Test of yes/no')
+    print askync('Test of yes/no/cancel')
+    print askstr('Type a string:')
+    print strdialog(mainWidget, 'Question', 'Another string:', '',
+                 0, 'Save', 'Save as text')
+
+def _test():
+    import sys
+    global mainWidget
+    mainWidget = Frame()
+    Pack.config(mainWidget)
+    start = Button(mainWidget,
+                  {'text': 'Press Here To Start', 'command': _go})
+    start.pack()
+    endit = Button(mainWidget,
+                  {'text': 'Exit',
+                   'command': 'exit',
+                   Pack: {'fill' : 'both'}})
+    mainWidget.mainloop()
+
+if __name__ == '__main__':
+    _test()
diff --git a/Tools/modulator/genmodule.py b/Tools/modulator/genmodule.py
new file mode 100755 (executable)
index 0000000..1c4cd1f
--- /dev/null
@@ -0,0 +1,157 @@
+#
+# Genmodule - A python program to help you build (template) modules.
+#
+# Usage:
+#
+# o = genmodule.object()
+# o.name = 'dwarve object'
+# o.abbrev = 'dw'
+# o.funclist = ['new', 'dealloc', 'getattr', 'setattr']
+# o.methodlist = ['dig']
+#
+# m = genmodule.module()
+# m.name = 'beings'
+# m.abbrev = 'be'
+# m.methodlist = ['newdwarve']
+# m.objects = [o]
+#
+# genmodule.write(sys.stdout, m)
+#
+import sys
+import os
+import varsubst
+import string
+
+error = 'genmodule.error'
+
+#
+# Names of functions in the object-description struct.
+#
+FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
+           'tp_compare', 'tp_repr', 'tp_hash']
+TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
+
+#
+# writer is a base class for the object and module classes
+# it contains code common to both.
+#
+class writer:
+    def __init__(self):
+       self._subst = None
+
+    def makesubst(self):
+       if not self._subst:
+           if not self.__dict__.has_key('abbrev'):
+               self.abbrev = self.name
+           self.Abbrev = string.upper(self.abbrev[0])+self.abbrev[1:]
+           subst = varsubst.Varsubst(self.__dict__)
+           subst.useindent(1)
+           self._subst = subst.subst
+
+    def addcode(self, name, fp):
+       ifp = self.opentemplate(name)
+       self.makesubst()
+       d = ifp.read()
+       d = self._subst(d)
+       fp.write(d)
+
+    def opentemplate(self, name):
+       for p in sys.path:
+           fn = os.path.join(p, name)
+           if os.path.exists(fn):
+               return open(fn, 'r')
+           fn = os.path.join(p, 'Templates')
+           fn = os.path.join(fn, name)
+           if os.path.exists(fn):
+               return open(fn, 'r')
+       raise error, 'Template '+name+' not found for '+self._type+' '+ \
+                    self.name
+       
+class module(writer):
+    _type = 'module'
+
+    def writecode(self, fp):
+       self.addcode('copyright', fp)
+       self.addcode('module_head', fp)
+       for o in self.objects:
+           o.writehead(fp)
+       for o in self.objects:
+           o.writebody(fp)
+       new_ml = ''
+       for fn in self.methodlist:
+           self.method = fn
+           self.addcode('module_method', fp)
+           new_ml = new_ml + ('{"%s",\t%s_%s,\t1},\n'%(fn, self.abbrev, fn))
+       self.methodlist = new_ml
+       self.addcode('module_tail', fp)
+
+class object(writer):
+    _type = 'object'
+    def __init__(self):
+       self.typelist = []
+       self.methodlist = []
+       self.funclist = ['new']
+       writer.__init__(self)
+
+    def writecode(self, fp):
+       self.addcode('copyright', fp)
+       self.writehead(fp)
+       self.writebody(fp)
+
+    def writehead(self, fp):
+       self.addcode('object_head', fp)
+
+    def writebody(self, fp):
+       new_ml = ''
+       for fn in self.methodlist:
+           self.method = fn
+           self.addcode('object_method', fp)
+           new_ml = new_ml + ('{"%s",\t%s_%s,\t1},\n'%(fn, self.abbrev, fn))
+       self.methodlist = new_ml
+       self.addcode('object_mlist', fp)
+
+       # Add getattr if we have methods
+       if self.methodlist and not 'tp_getattr' in self.funclist:
+           self.funclist.insert(0, 'tp_getattr')
+           
+       for fn in FUNCLIST:
+           setattr(self, fn, '0')
+
+       #
+       # Special case for structure-access objects: put getattr in the
+       # list of functions but don't generate code for it directly,
+       # the code is obtained from the object_structure template.
+       # The same goes for setattr.
+       #
+       if 'structure' in self.typelist:
+           if 'tp_getattr' in self.funclist:
+               self.funclist.remove('tp_getattr')
+           if 'tp_setattr' in self.funclist:
+               self.funclist.remove('tp_setattr')
+           self.tp_getattr = self.abbrev + '_getattr'
+           self.tp_setattr = self.abbrev + '_setattr'
+       for fn in self.funclist:
+           self.addcode('object_'+fn, fp)
+           setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
+       for tn in TYPELIST:
+           setattr(self, tn, '0')
+       for tn in self.typelist:
+           self.addcode('object_'+tn, fp)
+           setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
+       self.addcode('object_tail', fp)
+
+def write(fp, obj):
+    obj.writecode(fp)
+
+if __name__ == '__main__':
+    o = object()
+    o.name = 'dwarve object'
+    o.abbrev = 'dw'
+    o.funclist = ['new', 'tp_dealloc']
+    o.methodlist = ['dig']
+    m = module()
+    m.name = 'beings'
+    m.abbrev = 'be'
+    m.methodlist = ['newdwarve']
+    m.objects = [o]
+    write(sys.stdout, m)
diff --git a/Tools/modulator/modulator.py b/Tools/modulator/modulator.py
new file mode 100755 (executable)
index 0000000..b569ac6
--- /dev/null
@@ -0,0 +1,379 @@
+#! /usr/local/bin/python
+#
+# Modulator - Generate skeleton modules.
+#
+# The user fills out some forms with information about what the module
+# should support (methods, objects), names of these things, prefixes to
+# use for C code, whether the objects should also support access as numbers,
+# etc etc etc.
+# When the user presses 'Generate code' we generate a complete skeleton
+# module in C.
+#
+# Alternatively, the selections made can be save to a python sourcefile and
+# this sourcefile can be passed on the command line (resulting in the same
+# skeleton C code).
+#
+# Jack Jansen, CWI, October 1994.
+#
+
+import sys, os
+sys.path.append(os.path.join(os.environ['HOME'], 'src/python/Demo/modulator'))
+
+from Tkinter import *
+from Tkextra import *
+import tkinter
+from ScrolledListbox import ScrolledListbox
+import sys
+import genmodule
+import string
+
+oops = 'oops'
+
+# Check that string is a legal C identifier
+def checkid(str):
+    if not str: return 0
+    if not str[0] in string.letters+'_':
+       return 0
+    for c in str[1:]:
+       if not c in string.letters+string.digits+'_':
+           return 0
+    return 1
+
+def getlistlist(list):
+    rv = []
+    n = list.size()
+    for i in range(n):
+       rv.append(list.get(i))
+    return rv
+    
+class UI:
+    def __init__(self):
+       self.main = Frame()
+       self.main.pack()
+       self.main.master.title('Modulator: Module view')
+       self.cmdframe = Frame(self.main, {'relief':'raised', 'bd':'0.5m',
+                                         Pack:{'side':'top',
+                                                'fill':'x'}})
+       self.objframe = Frame(self.main, {Pack:{'side':'top', 'fill':'x',
+                                               'expand':1}})
+
+
+       self.check_button = Button(self.cmdframe,
+                                 {'text':'Check', 'command':self.cb_check,
+                                  Pack:{'side':'left', 'padx':'0.5m'}})
+       self.save_button = Button(self.cmdframe,
+                                 {'text':'Save...', 'command':self.cb_save,
+                                  Pack:{'side':'left', 'padx':'0.5m'}})
+       self.code_button = Button(self.cmdframe,
+                                 {'text':'Generate code...',
+                                  'command':self.cb_gencode,
+                                  Pack:{'side':'left', 'padx':'0.5m'}})
+       self.quit_button = Button(self.cmdframe,
+                                 {'text':'Quit',
+                                  'command':self.cb_quit,
+                                  Pack:{'side':'right', 'padx':'0.5m'}})
+
+       self.module = UI_module(self)
+       self.objects = []
+       self.modified = 0
+
+    def run(self):
+       self.main.mainloop()
+
+    def cb_quit(self, *args):
+       if self.modified:
+           if not askyn('You have not saved\nAre you sure you want to quit?'):
+               return
+       sys.exit(0)
+
+    def cb_check(self, *args):
+       try:
+           self.module.synchronize()
+           for o in self.objects:
+               o.synchronize()
+       except oops:
+           pass
+       
+    def cb_save(self, *args):
+       try:
+           pycode = self.module.gencode('m', self.objects)
+       except oops:
+           return
+
+       fn = askfile('Python file name: ')
+       if not fn:
+           return
+
+       fp = open(fn, 'w')
+
+       fp.write(pycode)
+       fp.close()
+
+    def cb_gencode(self, *args):
+       try:
+           pycode = self.module.gencode('m', self.objects)
+       except oops:
+           pass
+
+       fn = askfile('C file name: ')
+       if not fn:
+           return
+
+       fp = open(fn, 'w')
+
+       try:
+           exec pycode
+       except:
+           message('An error occurred:-)')
+           return
+       genmodule.write(fp, m)
+       fp.close()
+
+class UI_module:
+    def __init__(self, parent):
+       self.parent = parent
+       self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
+                                            Pack:{'side':'top',
+                                                  'fill':'x'}})
+       self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+
+       self.l1 = Label(self.f1, {'text':'Module:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.name_entry = Entry(self.f1, {'relief':'sunken',
+                             Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+       self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
+                             Pack:{'side':'left', 'padx':'0.5m'}})
+
+       self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
+                                     Pack:{'side':'left', 'expand':1,
+                                           'padx':'0.5m', 'fill':'both'}})
+
+       self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
+                                                             'padx':'0.5m'}})
+       self.method_entry = Entry(self.f3, {'relief':'sunken',
+                            Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+       self.method_entry.bind('<Return>', self.cb_method)
+       self.delete_button = Button(self.f3, {'text':'Delete method',
+                                             'command':self.cb_delmethod,
+                                             Pack:{'side':'left',
+                                                   'padx':'0.5m'}})
+
+       self.newobj_button = Button(self.f4, {'text':'new object',
+                                             'command':self.cb_newobj,
+                                             Pack:{'side':'left',
+                                                   'padx':'0.5m'}})
+       
+    def cb_delmethod(self, *args):
+       list = self.method_list.curselection()
+       for i in list:
+           self.method_list.delete(i)
+       
+    def cb_newobj(self, *arg):
+       self.parent.objects.append(UI_object(self.parent))
+
+    def cb_method(self, *arg):
+       name = self.method_entry.get()
+       if not name:
+           return
+       self.method_entry.delete('0', 'end')
+       self.method_list.insert('end', name)
+
+    def synchronize(self):
+       n = self.name_entry.get()
+       if not n:
+           message('Module name not set')
+           raise oops
+       if not checkid(n):
+           message('Module name not an identifier:\n'+n)
+           raise oops
+       if not self.abbrev_entry.get():
+           self.abbrev_entry.insert('end', n)
+       m = getlistlist(self.method_list)
+       for n in m:
+           if not checkid(n):
+               message('Method name not an identifier:\n'+n)
+               raise oops
+           
+    def gencode(self, name, objects):
+       rv = ''
+       self.synchronize()
+       for o in objects:
+           o.synchronize()
+       onames = []
+       for i in range(len(objects)):
+           oname = 'o'+`i+1`
+           rv = rv + objects[i].gencode(oname)
+           onames.append(oname)
+       rv = rv + (name+' = genmodule.module()\n')
+       rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
+       rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
+       rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
+       rv = rv + (name+'.objects = ['+string.joinfields(onames, ',')+']\n')
+       rv = rv + ('\n')
+       return rv
+       
+object_number = 0
+
+class UI_object:
+    def __init__(self, parent):
+       global object_number
+
+       object_number = object_number + 1
+       self.num = object_number
+       self.vpref = 'o'+`self.num`+'_'
+       self.frame = Toplevel(parent.objframe)
+#      self.frame.pack()
+       self.frame.title('Modulator: object view')
+#      self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
+#                                           Pack:{'side':'top',
+#                                                 'fill':'x'}})
+       self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+                                          'fill':'x'}})
+       
+
+       self.l1 = Label(self.f1, {'text':'Object:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.name_entry = Entry(self.f1, {'relief':'sunken',
+                             Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+       self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
+                             Pack:{'side':'left', 'padx':'0.5m'}})
+
+       self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
+                                                       'padx':'0.5m'}})
+       self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
+                                     Pack:{'side':'left', 'expand':1,
+                                           'padx':'0.5m', 'fill':'both'}})
+
+       self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
+                                                             'padx':'0.5m'}})
+       self.method_entry = Entry(self.f3, {'relief':'sunken',
+                            Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+       self.method_entry.bind('<Return>', self.cb_method)
+       self.delete_button = Button(self.f3, {'text':'Delete method',
+                                             'command':self.cb_delmethod,
+                                             Pack:{'side':'left',
+                                                   'padx':'0.5m'}})
+
+
+       self.l5 = Label(self.f4, {'text':'functions:',
+                                 Pack:{'side':'left',
+                                       'padx':'0.5m'}})
+       self.f5 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
+                                          'fill':'both'}})
+       self.l6 = Label(self.f4, {'text':'Types:',
+                                 Pack:{'side':'left', 'padx':'0.5m'}})
+       self.f6 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
+                                          'fill':'x'}})
+       self.funcs = {}
+       for i in genmodule.FUNCLIST:
+           vname = self.vpref+i
+           self.f5.setvar(vname, 0)
+           b = Checkbutton(self.f5, {'variable':vname, 'text':i,
+                                     Pack:{'side':'top', 'pady':'0.5m',
+                                           'anchor':'w','expand':1}})
+           self.funcs[i] = b
+       self.f5.setvar(self.vpref+'new', 1)
+
+       self.types = {}
+       for i in genmodule.TYPELIST:
+           vname = self.vpref + i
+           self.f6.setvar(vname, 0)
+           b = Checkbutton(self.f6, {'variable':vname, 'text':i,
+                                     Pack:{'side':'top', 'pady':'0.5m',
+                                           'anchor':'w'}})
+           self.types[i] = b
+       
+    def cb_method(self, *arg):
+       name = self.method_entry.get()
+       if not name:
+           return
+       self.method_entry.delete('0', 'end')
+       self.method_list.insert('end', name)
+
+    def cb_delmethod(self, *args):
+       list = self.method_list.curselection()
+       for i in list:
+           self.method_list.delete(i)
+       
+    def synchronize(self):
+       n = self.name_entry.get()
+       if not n:
+           message('Object name not set')
+           raise oops
+       if not self.abbrev_entry.get():
+           self.abbrev_entry.insert('end', n)
+       n = self.abbrev_entry.get()
+       if not checkid(n):
+           message('Abbreviation not an identifier:\n'+n)
+           raise oops
+       m = getlistlist(self.method_list)
+       for n in m:
+           if not checkid(n):
+               message('Method name not an identifier:\n'+n)
+               raise oops
+       if m:
+           self.f5.setvar(self.vpref+'tp_getattr', 1)
+       pass
+       
+    def gencode(self, name):
+       rv = ''
+       rv = rv + (name+' = genmodule.object()\n')
+       rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
+       rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
+       rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
+       fl = []
+       for fn in genmodule.FUNCLIST:
+           vname = self.vpref + fn
+           if self.f5.getvar(vname) == '1':
+               fl.append(fn)
+       rv = rv + (name+'.funclist = '+`fl`+'\n')
+
+       fl = []
+       for fn in genmodule.TYPELIST:
+           vname = self.vpref + fn
+           if self.f5.getvar(vname) == '1':
+               fl.append(fn)
+               
+       rv = rv + (name+'.typelist = '+`fl`+'\n')
+
+       rv = rv + ('\n')
+       return rv
+       
+
+def main():
+    if len(sys.argv) < 2:
+       ui = UI()
+       ui.run()
+    elif len(sys.argv) == 2:
+       fp = open(sys.argv[1])
+       pycode = fp.read()
+       try:
+           exec pycode
+       except:
+           sys.stderr.write('An error occurred:-)\n')
+           sys.exit(1)
+       genmodule.write(sys.stdout, m)
+    else:
+       sys.stderr.write('Usage: modulator [file]\n')
+       sys.exit(1)
+       
+main()
diff --git a/Tools/modulator/varsubst.py b/Tools/modulator/varsubst.py
new file mode 100644 (file)
index 0000000..ec89fe3
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# Variable substitution. Variables are $delimited$
+#
+import string
+import regex
+import regsub
+
+error = 'varsubst.error'
+
+class Varsubst:
+    def __init__(self, dict):
+       self.dict = dict
+       self.prog = regex.compile('\$[a-zA-Z0-9_]*\$')
+       self.do_useindent = 0
+
+    def useindent(self, onoff):
+       self.do_useindent = onoff
+       
+    def subst(self, str):
+       rv = ''
+       while 1:
+           pos = self.prog.search(str)
+           if pos < 0:
+               return rv + str
+           if pos:
+               rv = rv + str[:pos]
+               str = str[pos:]
+           len = self.prog.match(str)
+           if len == 2:
+               # Escaped dollar
+               rv = rv + '$'
+               str = str[2:]
+               continue
+           name = str[1:len-1]
+           str = str[len:]
+           if not self.dict.has_key(name):
+               raise error, 'No such variable: '+name
+           value = self.dict[name]
+           if self.do_useindent and '\n' in value:
+               value = self._modindent(value, rv)
+           rv = rv + value
+
+    def _modindent(self, value, old):
+       lastnl = string.rfind(old, '\n', 0) + 1
+       lastnl = len(old) - lastnl
+       sub = '\n' + (' '*lastnl)
+       return regsub.gsub('\n', sub, value)
+
+def _test():
+    import sys
+    import os
+
+    sys.stderr.write('-- Copying stdin to stdout with environment map --\n')
+    c = Varsubst(os.environ)
+    c.useindent(1)
+    d = sys.stdin.read()
+    sys.stdout.write(c.subst(d))
+    sys.exit(1)
+
+if __name__ == '__main__':
+    _test()