summaryrefslogtreecommitdiff
path: root/sys/src/cmd/python/Tools/modulator
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-05-03 11:25:13 +0000
committercinap_lenrek <cinap_lenrek@localhost>2011-05-03 11:25:13 +0000
commit458120dd40db6b4df55a4e96b650e16798ef06a0 (patch)
tree8f82685be24fef97e715c6f5ca4c68d34d5074ee /sys/src/cmd/python/Tools/modulator
parent3a742c699f6806c1145aea5149bf15de15a0afd7 (diff)
add hg and python
Diffstat (limited to 'sys/src/cmd/python/Tools/modulator')
-rw-r--r--sys/src/cmd/python/Tools/modulator/EXAMPLE.py53
-rw-r--r--sys/src/cmd/python/Tools/modulator/README25
-rw-r--r--sys/src/cmd/python/Tools/modulator/ScrolledListbox.py37
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/copyright0
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/module_head6
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/module_method14
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/module_tail37
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_head13
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_method14
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_mlist8
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_new13
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_structure37
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tail33
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_mapping29
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_number169
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_sequence58
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_call7
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_compare6
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_dealloc7
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_getattr7
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_hash6
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_print7
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_repr9
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_setattr9
-rw-r--r--sys/src/cmd/python/Tools/modulator/Templates/object_tp_str10
-rwxr-xr-xsys/src/cmd/python/Tools/modulator/Tkextra.py235
-rwxr-xr-xsys/src/cmd/python/Tools/modulator/genmodule.py160
-rwxr-xr-xsys/src/cmd/python/Tools/modulator/modulator.py383
-rw-r--r--sys/src/cmd/python/Tools/modulator/varsubst.py56
29 files changed, 1448 insertions, 0 deletions
diff --git a/sys/src/cmd/python/Tools/modulator/EXAMPLE.py b/sys/src/cmd/python/Tools/modulator/EXAMPLE.py
new file mode 100644
index 000000000..b36a5a761
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/EXAMPLE.py
@@ -0,0 +1,53 @@
+#
+# 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.
+
+import genmodule
+
+#
+# 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]
+
+fp = open('EXAMPLEmodule.c', 'w')
+genmodule.write(fp, m)
+fp.close()
diff --git a/sys/src/cmd/python/Tools/modulator/README b/sys/src/cmd/python/Tools/modulator/README
new file mode 100644
index 000000000..aae86b4a7
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/README
@@ -0,0 +1,25 @@
+This is release 1.2 of modulator, a generator of boilerplate code for
+modules to be written in C.
+
+Difference between 1.2 and 1.1: __doc__ templates are now generated
+(thanks to Jim Fulton).
+
+Difference between 1.1 and 1.0: the templates now use "new-style"
+naming conventions. Many thanks to Chak Tan <tan@ee.rochester.edu> for
+supplying them.
+
+Usage when you have tk is *really* 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 (to run, use "python EXAMPLE.py"). Don't
+bother with EXAMPLE.py if you have Tkinter!!!
+
+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/sys/src/cmd/python/Tools/modulator/ScrolledListbox.py b/sys/src/cmd/python/Tools/modulator/ScrolledListbox.py
new file mode 100644
index 000000000..8bb5738f1
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/ScrolledListbox.py
@@ -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/sys/src/cmd/python/Tools/modulator/Templates/copyright b/sys/src/cmd/python/Tools/modulator/Templates/copyright
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/copyright
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/module_head b/sys/src/cmd/python/Tools/modulator/Templates/module_head
new file mode 100644
index 000000000..be001090b
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/module_head
@@ -0,0 +1,6 @@
+
+#include "Python.h"
+
+static PyObject *ErrorObject;
+
+/* ----------------------------------------------------- */
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/module_method b/sys/src/cmd/python/Tools/modulator/Templates/module_method
new file mode 100644
index 000000000..3048b1fc4
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/module_method
@@ -0,0 +1,14 @@
+
+static char $abbrev$_$method$__doc__[] =
+""
+;
+
+static PyObject *
+$abbrev$_$method$(PyObject *self /* Not used */, PyObject *args)
+{
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/module_tail b/sys/src/cmd/python/Tools/modulator/Templates/module_tail
new file mode 100644
index 000000000..59cc50b6c
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/module_tail
@@ -0,0 +1,37 @@
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef $abbrev$_methods[] = {
+ $methodlist$
+ {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called init$name$) */
+
+static char $name$_module_documentation[] =
+""
+;
+
+void
+init$name$()
+{
+ PyObject *m, *d;
+
+ /* Create the module and add the functions */
+ m = Py_InitModule4("$name$", $abbrev$_methods,
+ $name$_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ /* Add some symbolic constants to the module */
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("$name$.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ /* XXXX Add constants here */
+
+ /* Check for errors */
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module $name$");
+}
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_head b/sys/src/cmd/python/Tools/modulator/Templates/object_head
new file mode 100644
index 000000000..07d1f6a9f
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_head
@@ -0,0 +1,13 @@
+
+/* Declarations for objects of type $name$ */
+
+typedef struct {
+ PyObject_HEAD
+ /* XXXX Add your own stuff here */
+} $abbrev$object;
+
+static PyTypeObject $Abbrev$type;
+
+
+
+/* ---------------------------------------------------------------- */
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_method b/sys/src/cmd/python/Tools/modulator/Templates/object_method
new file mode 100644
index 000000000..b15162c31
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_method
@@ -0,0 +1,14 @@
+
+static char $abbrev$_$method$__doc__[] =
+""
+;
+
+static PyObject *
+$abbrev$_$method$($abbrev$object *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_mlist b/sys/src/cmd/python/Tools/modulator/Templates/object_mlist
new file mode 100644
index 000000000..a12a9e1be
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_mlist
@@ -0,0 +1,8 @@
+
+static struct PyMethodDef $abbrev$_methods[] = {
+ $methodlist$
+ {NULL, NULL} /* sentinel */
+};
+
+/* ---------- */
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_new b/sys/src/cmd/python/Tools/modulator/Templates/object_new
new file mode 100644
index 000000000..30c5e363e
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_new
@@ -0,0 +1,13 @@
+
+static $abbrev$object *
+new$abbrev$object()
+{
+ $abbrev$object *self;
+
+ self = PyObject_NEW($abbrev$object, &$Abbrev$type);
+ if (self == NULL)
+ return NULL;
+ /* XXXX Add your own initializers here */
+ return self;
+}
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_structure b/sys/src/cmd/python/Tools/modulator/Templates/object_structure
new file mode 100644
index 000000000..573ac8db9
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_structure
@@ -0,0 +1,37 @@
+
+/* 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 PyObject *
+$abbrev$_getattr($abbrev$object *self, char *name)
+{
+ PyObject *rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char *)/*XXXX*/0, $abbrev$_memberlist, name);
+ if (rv)
+ return rv;
+ PyErr_Clear();
+ return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
+}
+
+
+static int
+$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL ) {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+ return PyMember_Set((char *)/*XXXX*/0, $abbrev$_memberlist, name, v);
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tail b/sys/src/cmd/python/Tools/modulator/Templates/object_tail
new file mode 100644
index 000000000..1d1334c9f
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tail
@@ -0,0 +1,33 @@
+
+static char $Abbrev$type__doc__[] =
+""
+;
+
+static PyTypeObject $Abbrev$type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 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*/
+ (ternaryfunc)$tp_call$, /*tp_call*/
+ (reprfunc)$tp_str$, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ $Abbrev$type__doc__ /* Documentation string */
+};
+
+/* End of code for $name$ objects */
+/* -------------------------------------------------------- */
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_mapping b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_mapping
new file mode 100644
index 000000000..f9213b70e
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_mapping
@@ -0,0 +1,29 @@
+
+/* Code to access $name$ objects as mappings */
+
+static int
+$abbrev$_length($abbrev$object *self)
+{
+ /* XXXX Return the size of the mapping */
+}
+
+static PyObject *
+$abbrev$_subscript($abbrev$object *self, PyObject *key)
+{
+ /* XXXX Return the item of self indexed by key */
+}
+
+static int
+$abbrev$_ass_sub($abbrev$object *self, PyObject *v, PyObject *w)
+{
+ /* XXXX Put w in self under key v */
+ return 0;
+}
+
+static PyMappingMethods $abbrev$_as_mapping = {
+ (inquiry)$abbrev$_length, /*mp_length*/
+ (binaryfunc)$abbrev$_subscript, /*mp_subscript*/
+ (objobjargproc)$abbrev$_ass_sub, /*mp_ass_subscript*/
+};
+
+/* -------------------------------------------------------- */
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_number b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_number
new file mode 100644
index 000000000..e69aa9a55
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_number
@@ -0,0 +1,169 @@
+
+/* Code to access $name$ objects as numbers */
+
+static PyObject *
+$abbrev$_add($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX Add them */
+}
+
+static PyObject *
+$abbrev$_sub($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX Subtract them */
+}
+
+static PyObject *
+$abbrev$_mul($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX Multiply them */
+}
+
+static PyObject *
+$abbrev$_div($abbrev$object *x, $abbrev$object *y)
+{
+ /* XXXX Divide them */
+}
+
+static PyObject *
+$abbrev$_mod($abbrev$object *x, $abbrev$object *y)
+{
+ /* XXXX Modulo them */
+}
+
+static PyObject *
+$abbrev$_divmod($abbrev$object *x, $abbrev$object *y)
+{
+ /* XXXX Return 2-tuple with div and mod */
+}
+
+static PyObject *
+$abbrev$_pow($abbrev$object *v, $abbrev$object *w, $abbrev$object *z)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_neg($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_pos($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_abs($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static int
+$abbrev$_nonzero($abbrev$object *v)
+{
+ /* XXXX Return 1 if non-zero */
+}
+
+static PyObject *
+$abbrev$_invert($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_lshift($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_rshift($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_and($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_xor($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_or($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX */
+}
+
+static int
+$abbrev$_coerce(PyObject **pv, PyObject **pw)
+{
+ /* XXXX I haven't a clue... */
+ return 1;
+}
+
+static PyObject *
+$abbrev$_int($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_long($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_float($abbrev$object *v)
+{
+ /* XXXX */
+}
+
+static PyObject *
+$abbrev$_oct($abbrev$object *v)
+{
+ /* XXXX Return object as octal stringobject */
+}
+
+static PyObject *
+$abbrev$_hex($abbrev$object *v)
+{
+ /* XXXX Return object as hex stringobject */
+}
+
+static PyNumberMethods $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/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_sequence b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_sequence
new file mode 100644
index 000000000..54c0b9290
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_as_sequence
@@ -0,0 +1,58 @@
+
+/* Code to handle accessing $name$ objects as sequence objects */
+
+static int
+$abbrev$_length($abbrev$object *self)
+{
+ /* XXXX Return the size of the object */
+}
+
+static PyObject *
+$abbrev$_concat($abbrev$object *self, PyObject *bb)
+{
+ /* XXXX Return the concatenation of self and bb */
+}
+
+static PyObject *
+$abbrev$_repeat($abbrev$object *self, int n)
+{
+ /* XXXX Return a new object that is n times self */
+}
+
+static PyObject *
+$abbrev$_item($abbrev$object *self, int i)
+{
+ /* XXXX Return the i-th object of self */
+}
+
+static PyObject *
+$abbrev$_slice($abbrev$object *self, int ilow, int ihigh)
+{
+ /* XXXX Return the ilow..ihigh slice of self in a new object */
+}
+
+static int
+$abbrev$_ass_item($abbrev$object *self, int i, PyObject *v)
+{
+ /* XXXX Assign to the i-th element of self */
+ return 0;
+}
+
+static int
+$abbrev$_ass_slice(PyListObject *self, int ilow, int ihigh, PyObject *v)
+{
+ /* XXXX Replace ilow..ihigh slice of self with v */
+ return 0;
+}
+
+static PySequenceMethods $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/sys/src/cmd/python/Tools/modulator/Templates/object_tp_call b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_call
new file mode 100644
index 000000000..a93f17fd6
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_call
@@ -0,0 +1,7 @@
+
+static PyObject *
+$abbrev$_call($abbrev$object *self, PyObject *args, PyObject *kwargs)
+{
+ /* XXXX Return the result of calling self with argument args */
+}
+
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_compare b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_compare
new file mode 100644
index 000000000..153bae0bd
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_compare
@@ -0,0 +1,6 @@
+
+static int
+$abbrev$_compare($abbrev$object *v, $abbrev$object *w)
+{
+ /* XXXX Compare objects and return -1, 0 or 1 */
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_dealloc b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_dealloc
new file mode 100644
index 000000000..440419a52
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_dealloc
@@ -0,0 +1,7 @@
+
+static void
+$abbrev$_dealloc($abbrev$object *self)
+{
+ /* XXXX Add your own cleanup code here */
+ PyMem_DEL(self);
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_getattr b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_getattr
new file mode 100644
index 000000000..6a1b2e866
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_getattr
@@ -0,0 +1,7 @@
+
+static PyObject *
+$abbrev$_getattr($abbrev$object *self, char *name)
+{
+ /* XXXX Add your own getattr code here */
+ return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_hash b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_hash
new file mode 100644
index 000000000..2d63f6a8a
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_hash
@@ -0,0 +1,6 @@
+
+static long
+$abbrev$_hash($abbrev$object *self)
+{
+ /* XXXX Return a hash of self (or -1) */
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_print b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_print
new file mode 100644
index 000000000..76408d234
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_print
@@ -0,0 +1,7 @@
+
+static int
+$abbrev$_print($abbrev$object *self, FILE *fp, int flags)
+{
+ /* XXXX Add code here to print self to fp */
+ return 0;
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_repr b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_repr
new file mode 100644
index 000000000..f12222508
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_repr
@@ -0,0 +1,9 @@
+
+static PyObject *
+$abbrev$_repr($abbrev$object *self)
+{
+ PyObject *s;
+
+ /* XXXX Add code here to put self into s */
+ return s;
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_setattr b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_setattr
new file mode 100644
index 000000000..dfe4bc8c7
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_setattr
@@ -0,0 +1,9 @@
+
+static int
+$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
+{
+ /* Set attribute 'name' to value 'v'. v==NULL means delete */
+
+ /* XXXX Add your own setattr code here */
+ return -1;
+}
diff --git a/sys/src/cmd/python/Tools/modulator/Templates/object_tp_str b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_str
new file mode 100644
index 000000000..2e3648e83
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Templates/object_tp_str
@@ -0,0 +1,10 @@
+
+static PyObject *
+$abbrev$_str($abbrev$object *self)
+{
+ PyObject *s;
+
+ /* XXXX Add code here to put self into s */
+ return s;
+}
+
diff --git a/sys/src/cmd/python/Tools/modulator/Tkextra.py b/sys/src/cmd/python/Tools/modulator/Tkextra.py
new file mode 100755
index 000000000..8f557286f
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/Tkextra.py
@@ -0,0 +1,235 @@
+#! /usr/bin/env 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/sys/src/cmd/python/Tools/modulator/genmodule.py b/sys/src/cmd/python/Tools/modulator/genmodule.py
new file mode 100755
index 000000000..da3068472
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/genmodule.py
@@ -0,0 +1,160 @@
+#
+# 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
+
+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', 'tp_call', 'tp_str']
+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 = self.abbrev[0].upper()+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(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
+ %(fn, self.abbrev, 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(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
+ %(fn, self.abbrev, 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/sys/src/cmd/python/Tools/modulator/modulator.py b/sys/src/cmd/python/Tools/modulator/modulator.py
new file mode 100755
index 000000000..3e06bc237
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/modulator.py
@@ -0,0 +1,383 @@
+#! /usr/bin/env 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
+if os.name <> 'mac':
+ sys.path.append(os.path.join(os.environ['HOME'],
+ 'src/python/Tools/modulator'))
+
+from Tkinter import *
+from Tkextra import *
+from ScrolledListbox import ScrolledListbox
+import sys
+import genmodule
+import string
+
+oops = 'oops'
+
+IDENTSTARTCHARS = string.letters + '_'
+IDENTCHARS = string.letters + string.digits + '_'
+
+# Check that string is a legal C identifier
+def checkid(str):
+ if not str: return 0
+ if not str[0] in IDENTSTARTCHARS:
+ return 0
+ for c in str[1:]:
+ if not c in IDENTCHARS:
+ 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%d' % (i+1)
+ rv = rv + objects[i].gencode(oname)
+ onames.append(oname)
+ rv = rv + '%s = genmodule.module()\n' % (name,)
+ rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())
+ rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())
+ rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))
+ rv = rv + '%s.objects = [%s]\n' % (name, ','.join(onames))
+ 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%r_' % 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 + '%s = genmodule.object()\n' % (name,)
+ rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())
+ rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())
+ rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))
+ fl = []
+ for fn in genmodule.FUNCLIST:
+ vname = self.vpref + fn
+ if self.f5.getvar(vname) == '1':
+ fl.append(fn)
+ rv = rv + '%s.funclist = %r\n' % (name, fl)
+
+ fl = []
+ for fn in genmodule.TYPELIST:
+ vname = self.vpref + fn
+ if self.f5.getvar(vname) == '1':
+ fl.append(fn)
+
+ rv = rv + '%s.typelist = %r\n' % (name, fl)
+
+ 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/sys/src/cmd/python/Tools/modulator/varsubst.py b/sys/src/cmd/python/Tools/modulator/varsubst.py
new file mode 100644
index 000000000..3b3395065
--- /dev/null
+++ b/sys/src/cmd/python/Tools/modulator/varsubst.py
@@ -0,0 +1,56 @@
+#
+# Variable substitution. Variables are $delimited$
+#
+import re
+
+error = 'varsubst.error'
+
+class Varsubst:
+ def __init__(self, dict):
+ self.dict = dict
+ self.prog = re.compile('\$([a-zA-Z0-9_]*)\$')
+ self.do_useindent = 0
+
+ def useindent(self, onoff):
+ self.do_useindent = onoff
+
+ def subst(self, s):
+ rv = ''
+ while 1:
+ m = self.prog.search(s)
+ if not m:
+ return rv + s
+ rv = rv + s[:m.start()]
+ s = s[m.end():]
+ if m.end() - m.start() == 2:
+ # Escaped dollar
+ rv = rv + '$'
+ s = s[2:]
+ continue
+ name = m.group(1)
+ 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 = old.rfind('\n', 0) + 1
+ lastnl = len(old) - lastnl
+ sub = '\n' + (' '*lastnl)
+ return re.sub('\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()