New experimental modules -- signal and sybase
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
new file mode 100644
index 0000000..a2ed72a
--- /dev/null
+++ b/Modules/signalmodule.c
@@ -0,0 +1,355 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 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.
+
+******************************************************************/
+
+/* Signal module -- many thanks to Lance Ellinghouse */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include "ceval.h"
+#include "intrcheck.h"
+
+#include <signal.h>
+
+struct signalhandler_list {
+	int	tripped;
+	object *func;
+};
+
+static struct signalhandler_list sig_list[NSIG];
+
+static object *default_sig_object;
+static object *default_ignore_object;
+static object *default_int_object;
+
+static object *
+default_int_handler(self, arg)
+     object *self;
+     object *arg;
+{
+	err_set(KeyboardInterrupt);
+	return NULL;
+}
+
+static RETSIGTYPE
+signal_handler(sig_num)
+     int sig_num;
+{
+	sig_list[sig_num].tripped = 1;
+	(void *)signal(sig_num, &signal_handler);
+}
+ 
+
+static object *
+signal_signal(self, args)
+	object *self; /* Not used */
+	object *args;
+{
+        object *obj;
+	int sig_num;
+	object *old_handler;
+	RETSIGTYPE (*func)();
+	if (!getargs(args, "(iO)", &sig_num, &obj))
+		return NULL;
+	if (sig_num < 1 || sig_num >= NSIG) {
+		err_setstr(ValueError, "signal number out of range");
+		return NULL;
+	}
+	if (obj == default_ignore_object)
+		func = SIG_IGN;
+	else if (obj == default_sig_object)
+		func = SIG_DFL;
+	else if (!is_methodobject(obj) &&
+		 !is_funcobject(obj) &&
+		 !is_instancemethodobject(obj)) {
+		err_setstr(TypeError,
+"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
+		return NULL;
+	}
+	else
+		func = signal_handler;
+	old_handler = sig_list[sig_num].func;
+	/* XXX is it always correct to clear tripped? */
+	sig_list[sig_num].tripped = 0;
+	INCREF(obj);
+	sig_list[sig_num].func = obj;
+	signal(sig_num, func);
+	return old_handler;
+}
+
+static object *
+signal_getsignal(self, args)
+	object *self; /* Not used */
+	object *args;
+{
+	int sig_num;
+	object *old_handler;
+	if (!getargs(args, "i", &sig_num))
+		return NULL;
+	if (sig_num < 1 || sig_num >= NSIG) {
+		err_setstr(ValueError, "signal number out of range");
+		return NULL;
+	}
+	old_handler = sig_list[sig_num].func;
+	INCREF(old_handler);
+	return old_handler;
+}
+
+
+/* List of functions defined in the module */
+
+static struct methodlist signal_methods[] = {
+        {"signal",      signal_signal},
+        {"getsignal",      signal_getsignal},
+	{NULL,		NULL}		/* sentinel */
+};
+
+void
+initsignal()
+{
+	object *m, *d, *x;
+	object *b_dict;
+	int i;
+	/* Create the module and add the functions */
+	m = initmodule("signal", signal_methods);
+
+	/* Add some symbolic constants to the module */
+	d = getmoduledict(m);
+
+	default_sig_object = newintobject((long)SIG_DFL);
+	dictinsert(d, "SIG_IGN", default_sig_object);
+	default_ignore_object = newintobject((long)SIG_IGN);
+	dictinsert(d, "SIG_DFL", default_ignore_object);
+	default_int_object = newmethodobject("default_int_handler",
+					     default_int_handler,
+					     (object *)NULL,
+					     0);
+	dictinsert(d, "default_int_handler", default_int_object);
+
+	sig_list[0].tripped = 0;
+	for (i = 1; i < NSIG; i++) {
+		void *t; /* type cop-out */
+		t = signal(i, SIG_IGN);
+		signal(i, t);
+		sig_list[i].tripped = 0;
+		if (t == SIG_DFL)
+			sig_list[i].func = default_sig_object;
+		else if (t == SIG_IGN)
+			sig_list[i].func = default_ignore_object;
+		else
+			sig_list[i].func = None; /* None of our business */
+		INCREF(sig_list[i].func);
+	}
+	if (sig_list[SIGINT].func == default_sig_object) {
+		/* Install default int handler */
+		DECREF(sig_list[SIGINT].func);
+		sig_list[SIGINT].func = default_int_object;
+		INCREF(default_int_object);
+		signal(SIGINT, &signal_handler);
+	}
+
+#ifdef SIGHUP
+	x = newintobject(SIGHUP);
+	dictinsert(d, "SIGHUP", x);
+#endif
+#ifdef SIGINT
+	x = newintobject(SIGINT);
+	dictinsert(d, "SIGINT", x);
+#endif
+#ifdef SIGQUIT
+	x = newintobject(SIGQUIT);
+	dictinsert(d, "SIGQUIT", x);
+#endif
+#ifdef SIGILL
+	x = newintobject(SIGILL);
+	dictinsert(d, "SIGILL", x);
+#endif
+#ifdef SIGTRAP
+	x = newintobject(SIGTRAP);
+	dictinsert(d, "SIGTRAP", x);
+#endif
+#ifdef SIGIOT
+	x = newintobject(SIGIOT);
+	dictinsert(d, "SIGIOT", x);
+#endif
+#ifdef SIGABRT
+	x = newintobject(SIGABRT);
+	dictinsert(d, "SIGABRT", x);
+#endif
+#ifdef SIGEMT
+	x = newintobject(SIGEMT);
+	dictinsert(d, "SIGEMT", x);
+#endif
+#ifdef SIGFPE
+	x = newintobject(SIGFPE);
+	dictinsert(d, "SIGFPE", x);
+#endif
+#ifdef SIGKILL
+	x = newintobject(SIGKILL);
+	dictinsert(d, "SIGKILL", x);
+#endif
+#ifdef SIGBUS
+	x = newintobject(SIGBUS);
+	dictinsert(d, "SIGBUS", x);
+#endif
+#ifdef SIGSEGV
+	x = newintobject(SIGSEGV);
+	dictinsert(d, "SIGSEGV", x);
+#endif
+#ifdef SIGSYS
+	x = newintobject(SIGSYS);
+	dictinsert(d, "SIGSYS", x);
+#endif
+#ifdef SIGPIPE
+	x = newintobject(SIGPIPE);
+	dictinsert(d, "SIGPIPE", x);
+#endif
+#ifdef SIGALRM
+	x = newintobject(SIGALRM);
+	dictinsert(d, "SIGALRM", x);
+#endif
+#ifdef SIGTERM
+	x = newintobject(SIGTERM);
+	dictinsert(d, "SIGTERM", x);
+#endif
+#ifdef SIGUSR1
+	x = newintobject(SIGUSR1);
+	dictinsert(d, "SIGUSR1", x);
+#endif
+#ifdef SIGUSR2
+	x = newintobject(SIGUSR2);
+	dictinsert(d, "SIGUSR2", x);
+#endif
+#ifdef SIGCLD
+	x = newintobject(SIGCLD);
+	dictinsert(d, "SIGCLD", x);
+#endif
+#ifdef SIGCHLD
+	x = newintobject(SIGCHLD);
+	dictinsert(d, "SIGCHLD", x);
+#endif
+#ifdef SIGPWR
+	x = newintobject(SIGPWR);
+	dictinsert(d, "SIGPWR", x);
+#endif
+#ifdef SIGIO
+	x = newintobject(SIGIO);
+	dictinsert(d, "SIGIO", x);
+#endif
+#ifdef SIGURG
+	x = newintobject(SIGURG);
+	dictinsert(d, "SIGURG", x);
+#endif
+#ifdef SIGWINCH
+	x = newintobject(SIGWINCH);
+	dictinsert(d, "SIGWINCH", x);
+#endif
+#ifdef SIGPOLL
+	x = newintobject(SIGPOLL);
+	dictinsert(d, "SIGPOLL", x);
+#endif
+#ifdef SIGSTOP
+	x = newintobject(SIGSTOP);
+	dictinsert(d, "SIGSTOP", x);
+#endif
+#ifdef SIGTSTP
+	x = newintobject(SIGTSTP);
+	dictinsert(d, "SIGTSTP", x);
+#endif
+#ifdef SIGCONT
+	x = newintobject(SIGCONT);
+	dictinsert(d, "SIGCONT", x);
+#endif
+#ifdef SIGTTIN
+	x = newintobject(SIGTTIN);
+	dictinsert(d, "SIGTTIN", x);
+#endif
+#ifdef SIGTTOU
+	x = newintobject(SIGTTOU);
+	dictinsert(d, "SIGTTOU", x);
+#endif
+#ifdef SIGVTALRM
+	x = newintobject(SIGVTALRM);
+	dictinsert(d, "SIGVTALRM", x);
+#endif
+#ifdef SIGPROF
+	x = newintobject(SIGPROF);
+	dictinsert(d, "SIGPROF", x);
+#endif
+#ifdef SIGCPU
+	x = newintobject(SIGCPU);
+	dictinsert(d, "SIGCPU", x);
+#endif
+#ifdef SIGFSZ
+	x = newintobject(SIGFSZ);
+	dictinsert(d, "SIGFSZ", x);
+#endif
+	/* Check for errors */
+	if (err_occurred())
+		fatal("can't initialize module signal");
+}
+
+int
+sigcheck()
+{
+	int i;
+	object *f = getframe();
+	if (f == NULL)
+		f = None;
+	for (i = 1; i < NSIG; i++) {
+		if (sig_list[i].tripped) {
+			object *arglist, *result;
+			sig_list[i].tripped = 0;
+			arglist = mkvalue("(iO)", i, f);
+			if (arglist == NULL)
+				result = NULL;
+			else {
+				result = call_object(sig_list[i].func,arglist);
+				DECREF(arglist);
+			}
+			if (result == NULL) {
+				return 1;
+			} else {
+				DECREF(result);
+			}
+		}
+	}
+	return 0;
+}
+
+/* Replacement for intrcheck.c functionality */
+
+void
+initintr()
+{
+	initsignal();
+}
+
+int
+intrcheck()
+{
+	if (!sigcheck())
+		return 0;
+	err_clear();
+	return 1;
+}
diff --git a/Modules/sybasemodule.c b/Modules/sybasemodule.c
new file mode 100644
index 0000000..860203f
--- /dev/null
+++ b/Modules/sybasemodule.c
@@ -0,0 +1,309 @@
+/*
+Subject: Re: Sybase module -- input sought 
+From: jredford@lehman.com
+To: ags@uncompaghre.informatics.jax.org (Alexander G. Smith)
+Cc: python-list@cwi.nl
+Date: Tue, 10 May 94 11:53:13 -0400
+
+
+input sought? how about a complete module? :)
+
+This is a fairly incomplete work.. but I have done things dramatically
+differently than sybperl would. Given the nature of the language I
+find it is easier to simply get ALL results & then muck with the rows
+later as parts of the data. This is a subset of the functionality of a
+Modula-3 interface to Sybase that I wrote.. I could send you that if
+you are interested in a more complete picture.
+*/
+
+#include <stdio.h>
+
+#include <sybfront.h>
+#include <sybdb.h>
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+
+static object *SybaseError;	/* exception sybase.error */
+
+
+typedef struct {
+        OB_HEAD
+	LOGINREC *login;	/* login record */
+	DBPROCESS *dbproc;	/* login record */
+} sybdbobject;
+
+extern typeobject SybDbtype; /* Forward */
+
+
+static sybdbobject *
+  newsybdbobject(char *user, char *passwd, char *server)
+{
+  sybdbobject *s;
+
+  s = NEWOBJ(sybdbobject, &SybDbtype);
+  if (s != NULL) {
+    s->login = dblogin();
+    if (user) {
+      (void)DBSETLUSER(s->login, user);
+    }
+    if (passwd) {
+      (void)DBSETLPWD(s->login, passwd);
+    }
+    if(!(s->dbproc = dbopen(s->login, server))) {
+      dbloginfree(s->login);
+      DEL(s);
+      return (NULL);
+    }
+  }
+  return s;
+}
+
+/* OBJECT FUNCTIONS: sybdb */
+
+/* Common code for returning pending results */
+static object
+  *getresults (DBPROCESS *dbp)
+{
+  object *results;
+  object *list;
+  object *tuple;
+  object *o;
+  int retcode;
+  int cols;
+  int *fmt;
+  int i;
+
+  results = newlistobject(0);
+  while ((retcode = dbresults(dbp)) != NO_MORE_RESULTS) {
+    if (retcode == SUCCEED && DBROWS(dbp) == SUCCEED) {
+      list = newlistobject(0);
+      cols = dbnumcols(dbp);
+      fmt = (int *)malloc(sizeof(int) * cols);
+      for (i = 1; i <= cols; i++) {
+	switch(dbcoltype(dbp, i)) {
+	case SYBCHAR:
+	  fmt[i-1] = SYBCHAR;
+	  break;
+	case SYBINT1:
+	  fmt[i-1] = SYBINT1;
+	  break;
+	case SYBINT2:
+	  fmt[i-1] = SYBINT2;
+	  break;
+	case SYBINT4:
+	  fmt[i-1] = SYBINT4;
+	  break;
+	case SYBFLT8:
+	  fmt[i-1] = SYBFLT8;
+	  break;
+	}
+      }
+      while (dbnextrow(dbp) != NO_MORE_ROWS) {
+	tuple = newtupleobject(cols);
+	for (i = 1; i <= cols; i++) {
+	  switch(fmt[i-1]) {
+	  case SYBCHAR:
+	    o = newsizedstringobject((char *)dbdata(dbp, i), dbdatlen(dbp, i));
+	    settupleitem(tuple, i-1, o);
+	    break;
+	  case SYBINT1:
+	    o = newintobject(*((char *)dbdata(dbp, i)));
+	    settupleitem(tuple, i-1, o);
+	    break;
+	  case SYBINT2:
+	    o = newintobject(*((short *)dbdata(dbp, i)));
+	    settupleitem(tuple, i-1, o);
+	    break;
+	  case SYBINT4:
+	    o = newintobject(*((int *)dbdata(dbp, i)));
+	    settupleitem(tuple, i-1, o);
+	    break;
+	  case SYBFLT8:
+	    o = newfloatobject(*((double *)dbdata(dbp, i)));
+	    settupleitem(tuple, i-1, o);
+	    break;
+	  }
+	}
+	addlistitem(list,tuple);
+      }
+      free(fmt);
+      addlistitem(results,list);
+    }
+  }
+  return (results);
+}
+
+static object
+  *sybdb_sql (self, args)
+object *self;
+object *args;
+{
+  char *sql;
+  DBPROCESS *dbp;
+
+  dbp = ((sybdbobject *)self)->dbproc;
+  err_clear ();
+  if (!getargs (args, "s", &sql)) {
+    return NULL;
+  }
+  dbcancel(dbp);
+  dbcmd(dbp, sql);
+  dbsqlexec(dbp);
+  return getresults(dbp);
+}
+
+static object
+  *sybdb_sp (self, args)
+object *self;
+object *args;
+{
+  char *sp;
+  DBPROCESS *dbp;
+  object *spargs;
+  object *sparg;
+  object *results;
+  object *r;
+  int spargcnt;
+  int i;
+  int retstatus;
+
+  dbp = ((sybdbobject *)self)->dbproc;
+  err_clear ();
+  if (!getargs (args, "(sO)", &sp, &spargs)) {
+    return NULL;
+  }
+
+  dbcancel(dbp);
+  dbrpcinit(dbp, sp, 0);
+
+  if (is_tupleobject(spargs)) {
+    spargcnt=gettuplesize(spargs);
+    for (i=0; i < spargcnt; i++) {
+      sparg = gettupleitem(spargs,i);
+      if (is_intobject(sparg)) {
+	int i;
+	i = getintvalue(sparg);
+	dbrpcparam(dbp, NULL, 0, SYBINT4, -1, -1, &i);
+      } else if (is_floatobject(sparg)) {
+	double i;
+	i = getfloatvalue(sparg);
+	dbrpcparam(dbp, NULL, 0, SYBFLT8, -1, -1, &i);
+      } else if (is_stringobject(sparg)) {
+	dbrpcparam(dbp, NULL, 0, SYBCHAR, -1, getstringsize(sparg), getstringvalue(sparg));
+      } else {
+	err_setstr (SybaseError, "Could not handle paramaters to procedure.");
+	return NULL;
+      }
+    }
+  } else if (spargs != None) {
+    err_setstr (SybaseError, "Could not handle paramaters to procedure.");
+    return NULL;
+  }
+  dbrpcsend(dbp);
+  dbsqlok(dbp);
+
+  results = getresults(dbp);
+  retstatus = dbretstatus(dbp);
+
+  r = mkvalue("(iO)", retstatus, results);
+  DECREF(results);
+  return (r);
+}
+
+
+static struct methodlist sybdb_methods[] = {
+  {"sql",        sybdb_sql},
+  {"sp",         sybdb_sp},
+  {NULL,         NULL}		/* sentinel */
+};
+
+static void
+sybdb_dealloc(s)
+     sybdbobject *s;
+{
+  dbloginfree(s->login);
+  dbclose(s->dbproc);
+  DEL(s);
+}
+
+static object *
+sybdb_getattr(s, name)
+     sybdbobject *s;
+     char *name;
+{
+  return findmethod(sybdb_methods, (object *) s, name);
+}
+
+
+typeobject SybDbtype = {
+        OB_HEAD_INIT(&Typetype)
+        0,
+        "sybdb",
+        sizeof(sybdbobject),
+        0,
+        sybdb_dealloc,		/*tp_dealloc*/
+        0,			/*tp_print*/
+        sybdb_getattr,		/*tp_getattr*/
+        0,			/*tp_setattr*/
+        0,			/*tp_compare*/
+        0,			/*tp_repr*/
+        0,			/*tp_as_number*/
+        0,			/*tp_as_sequence*/
+        0,			/*tp_as_mapping*/
+};
+
+
+
+
+
+/* MODULE FUNCTIONS: sybase */
+
+static object
+  *sybase_new (self, args)
+object *self;		/* Not used */
+object *args;
+{
+  char *user, *passwd, *server;
+  object *db;
+
+  err_clear ();
+  if (!getargs (args, "(zzz)", &user, &passwd, &server)) {
+    return NULL;
+  }
+  db = (object *) newsybdbobject(user, passwd, server);
+  if (!db) {
+    /* XXX Should be setting some errstr stuff here based on sybase errors */
+    err_setstr (SybaseError, "Could not open connection to server.");
+    return NULL;
+  }
+  return db;
+}
+
+
+/* List of module functions */
+static struct methodlist sybase_methods[]=
+{
+  {"new", sybase_new},
+  {NULL, NULL}			/* sentinel */
+};
+
+/* Module initialisation */
+void initsybase ()
+{
+  object *m, *d;
+
+  /* Create the module and add the functions */
+  m = initmodule ("sybase", sybase_methods);
+  /* Add some symbolic constants to the module */
+  d = getmoduledict (m);
+  SybaseError = newstringobject ("sybase.error");
+  if (SybaseError == NULL || dictinsert (d, "error", SybaseError) != 0) {
+    fatal ("can't define sybase.error");
+  }
+  /* Check for errors */
+  if (err_occurred ()){
+    fatal ("can't initialize module sybase");
+  }
+}