]> granicus.if.org Git - python/commitdiff
Jim Fulton's version 2.2.
authorGuido van Rossum <guido@python.org>
Wed, 9 Apr 1997 17:36:32 +0000 (17:36 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 9 Apr 1997 17:36:32 +0000 (17:36 +0000)
Modules/cPickle.c

index b80548ec7484329fa05a46b5c5bf294046672964..3be9282712b9538cee2a7ed155a2c0a5f5320cb7 100644 (file)
@@ -59,59 +59,60 @@ static char cPickle_module_documentation[] =
 #include "Python.h"
 #include "cStringIO.h"
 #include "graminit.h"
+#include "mymath.h"
 
 #include <errno.h>
 
-static PyObject *ErrorObject;
+#define UNLESS(E) if (!(E))
 
-#ifdef __cplusplus
-#define ARG(T, N) T N
-#define ARGDECL(T, N)
-#else
-#define ARG(T, N) N
-#define ARGDECL(T, N) T N;
-#endif
+#define DEL_LIST_SLICE(list, from, to) (PyList_SetSlice(list, from, to, NULL))
 
-#define UNLESS(E) if (!(E))
-#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
-#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
-
-#define DEL_LIST_SLICE(list, from, to) \
-        (PyList_SetSlice(list, from, to, empty_list))
-
-#define APPEND    'a'
-#define BUILD     'b'
-#define DUP       '2'
-#define GET       'g'
-#define BINGET    'h'
-#define INST      'i'
-#define OBJ       'o'
-#define MARK      '('
-static char MARKv = MARK;
-#define PUT       'p'
-#define BINPUT    'q'
-#define POP       '0'
-#define SETITEM   's'
-#define STOP      '.'
-#define CLASS     'c'
-#define DICT      'd'
-#define LIST      'l'
-#define TUPLE     't'
-#define NONE      'N'
-#define INT       'I'
-#define BININT    'J'
-#define BININT1   'K'
-#define BININT2   'M'
-#define BININT3   'O'
-#define LONG      'L'
-#define FLOAT     'F'
-#define STRING    'S'
-#define BINSTRING 'T'
-#define SHORT_BINSTRING 'U'
-#define PERSID    'P'
+#define WRITE_BUF_SIZE 256
 
 
-PyTypeObject *BuiltinFunctionType;
+#define MARK        '('
+#define STOP        '.'
+#define POP         '0'
+#define POP_MARK    '1'
+#define DUP         '2'
+#define FLOAT       'F'
+#ifdef  FORMAT_1_3
+#define BINFLOAT    'G'
+#endif
+#define INT         'I'
+#define BININT      'J'
+#define BININT1     'K'
+#define LONG        'L'
+#define BININT2     'M'
+#define NONE        'N'
+#define PERSID      'P'
+#define BINPERSID   'Q'
+#define REDUCE      'R'
+#define STRING      'S'
+#define BINSTRING   'T'
+#define SHORT_BINSTRING 'U'
+#define APPEND      'a'
+#define BUILD       'b'
+#define GLOBAL      'c'
+#define DICT        'd'
+#define EMPTY_DICT  '}'
+#define APPENDS     'e'
+#define GET         'g'
+#define BINGET      'h'
+#define INST        'i'
+#define LONG_BINGET 'j'
+#define LIST        'l'
+#define EMPTY_LIST  ']'
+#define OBJ         'o'
+#define PUT         'p'
+#define BINPUT      'q'
+#define LONG_BINPUT 'r'
+#define SETITEM     's'
+#define TUPLE       't'
+#define EMPTY_TUPLE ')'
+#define SETITEMS    'u'
+
+static char MARKv = MARK;
 
 /* atol function from string module */
 static PyObject *atol_func;
@@ -119,3645 +120,3765 @@ static PyObject *atol_func;
 static PyObject *PicklingError;
 static PyObject *UnpicklingError;
 
+static PyObject *dispatch_table;
+static PyObject *safe_constructors;
 static PyObject *class_map;
-static PyObject *empty_list, *empty_tuple;
-
-static PyObject *save();
+static PyObject *empty_tuple;
+
+static PyObject *__class___str, *__getinitargs___str, *__dict___str,
+  *__getstate___str, *__setstate___str, *__name___str, *__reduce___str,
+  *write_str, *__safe_for_unpickling___str, *append_str,
+  *read_str, *readline_str;
+
+/* __builtins__ module */
+static PyObject *builtins;
+
+static int save();
+static int put2();
+
+typedef struct {
+     PyObject_HEAD
+     FILE *fp;
+     PyObject *write;
+     PyObject *file;
+     PyObject *memo;
+     PyObject *arg;
+     PyObject *pers_func;
+     PyObject *inst_pers_func;
+     int bin;
+     int (*write_func)();
+     char *write_buf;
+     int buf_size;
+} Picklerobject;
 
+static PyTypeObject Picklertype;
+
+
+typedef struct {
+    PyObject_HEAD
+    FILE *fp;
+    PyObject *file;
+    PyObject *readline;
+    PyObject *read;
+    PyObject *memo;
+    PyObject *arg;
+    PyObject *stack;
+    PyObject *mark;
+    PyObject *pers_func;
+    PyObject *last_string;
+    int *marks;
+    int num_marks;
+    int marks_size;
+    int (*read_func)();
+    int (*readline_func)();
+    int buf_size;
+    char *buf;
+} Unpicklerobject;
+static PyTypeObject Unpicklertype;
 
-typedef struct
+int 
+cPickle_PyMapping_HasKey(o, key)
+  PyObject *o;
+  PyObject *key;
 {
-  PyObject_HEAD
-  FILE *fp;
-  PyObject *write;
-  PyObject *file;
-  PyObject *memo;
-  PyObject *arg;
-  PyObject *pers_func;
-  char *mark;
-  int bin;
-  int (*write_func)();
-} Picklerobject;
+    PyObject *v;
 
-staticforward PyTypeObject Picklertype;
+    if (v = PyObject_GetItem(o,key))
+    {
+        Py_DECREF(v);
+        return 1;
+    }
 
+    PyErr_Clear();
+    return 0;
+}
 
-typedef struct
+PyObject *
+#ifdef HAVE_STDARG_PROTOTYPES
+/* VARARGS 2 */
+PyErr_Format(PyObject *ErrType, char *stringformat, char *format, ...)
+#else
+/* VARARGS */
+PyErr_Format(va_alist) va_dcl
+#endif
 {
-  PyObject_HEAD
-  FILE *fp;
-  PyObject *file;
-  PyObject *readline;
-  PyObject *read;
-  PyObject *memo;
-  PyObject *arg;
-  PyObject *stack;
-  PyObject *mark;
-  PyObject *pers_func;
-  int *marks;
-  int num_marks;
-  int marks_size;
-  int (*read_func)();
-  int (*readline_func)();
-} Unpicklerobject;
-staticforward PyTypeObject Unpicklertype;
+  va_list va;
+  PyObject *args=0, *retval=0;
+#ifdef HAVE_STDARG_PROTOTYPES
+  va_start(va, format);
+#else
+  PyObject *ErrType;
+  char *stringformat, *format;
+  va_start(va);
+  ErrType = va_arg(va, PyObject *);
+  stringformat   = va_arg(va, char *);
+  format   = va_arg(va, char *);
+#endif
+  
+  if(format) args = Py_VaBuildValue(format, va);
+  va_end(va);
+  if(format && ! args) return NULL;
+  if(stringformat && !(retval=PyString_FromString(stringformat))) return NULL;
 
+  if(retval)
+    {
+      if(args)
+       {
+         PyObject *v;
+         v=PyString_Format(retval, args);
+         Py_DECREF(retval);
+         Py_DECREF(args);
+         if(! v) return NULL;
+         retval=v;
+       }
+    }
+  else
+    if(args) retval=args;
+    else
+      {
+       PyErr_SetObject(ErrType,Py_None);
+       return NULL;
+      }
+  PyErr_SetObject(ErrType,retval);
+  Py_DECREF(retval);
+  return NULL;
+}
 
 static int 
-write_file(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(char *, s)
-    ARGDECL(int, n)
-{
-  if (fwrite(s, sizeof(char), n, self->fp) != n)
-  {
-    PyErr_SetFromErrno(PyExc_IOError);
-    return -1;
-  }
+write_file(Picklerobject *self, char *s, int  n) {
+    if (s == NULL) {
+        return 0;
+    }
+
+    if ((int)fwrite(s, sizeof(char), n, self->fp) != n) {
+        PyErr_SetFromErrno(PyExc_IOError);
+        return -1;
+    }
 
-  return n;
+    return n;
 }
 
 
 static int 
-write_cStringIO(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(char *, s)
-    ARGDECL(int, n)
-{
-  if ((*PycStringIO_cwrite)((PyObject *)self->file, s, n) != n)
-  {
-    return -1;
-  }
+write_cStringIO(Picklerobject *self, char *s, int  n) {
+    if (s == NULL) {
+        return 0;
+    }
+
+    if (PycStringIO->cwrite((PyObject *)self->file, s, n) != n) {
+        return -1;
+    }
 
-  return n;
+    return n;
 }
 
 
 static int 
-write_other(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(char *, s)
-    ARGDECL(int, n)
-{
-  PyObject *py_str, *junk;
-
-  UNLESS(py_str = PyString_FromStringAndSize(s, n))
-    return -1;
+write_other(Picklerobject *self, char *s, int  n) {
+    PyObject *py_str = 0, *junk = 0;
+    int res = -1;
+
+    if (s == NULL) {
+        UNLESS(self->buf_size) return 0;
+        UNLESS(py_str = 
+            PyString_FromStringAndSize(self->write_buf, self->buf_size))
+            goto finally;
+    }
+    else {
+        if (self->buf_size && (n + self->buf_size) > WRITE_BUF_SIZE) {
+            if (write_other(self, NULL, 0) < 0)
+                goto finally;
+        }
 
-  UNLESS(self->arg)
-    UNLESS(self->arg = PyTuple_New(1))
-    {
-      Py_DECREF(py_str);
-      return -1;
+        if (n > WRITE_BUF_SIZE) {    
+            UNLESS(py_str = 
+                PyString_FromStringAndSize(s, n))
+                goto finally;
+        }
+        else {
+            memcpy(self->write_buf + self->buf_size, s, n);
+            self->buf_size += n;
+            res = n;
+            goto finally;
+        }
     }
 
-  if (PyTuple_SetItem(self->arg, 0, py_str) == -1)
-  {
-    Py_DECREF(py_str);
-    return -1;
-  }
+    UNLESS(self->arg)
+        UNLESS(self->arg = PyTuple_New(1))
+            goto finally;
 
-  Py_INCREF(py_str);
-  UNLESS(junk = PyObject_CallObject(self->write, self->arg))
-  {
-    Py_DECREF(py_str);
-    return -1;
-  }
+    Py_INCREF(py_str);
+    if (PyTuple_SetItem(self->arg, 0, py_str) < 0)
+        goto finally;
+
+    UNLESS(junk = PyObject_CallObject(self->write, self->arg))
+        goto finally;
+    Py_DECREF(junk);
+
+    self->buf_size = 0;
+    res = n;
 
-  Py_DECREF(junk);
+finally:
+    Py_XDECREF(py_str);
 
-  return n;
+    return res;
 }
 
 
 static int 
-read_file(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-    ARGDECL(int, n)
-{
-  if (fread(*s, sizeof(char), n, self->fp) != n)
-  {  
-    if (feof(self->fp))
-    {
-      PyErr_SetNone(PyExc_EOFError);
-      return -1;
+read_file(Unpicklerobject *self, char **s, int  n) {
+
+    if (self->buf_size == 0) {
+        int size;
+
+        size = ((n < 32) ? 32 : n); 
+        UNLESS(self->buf = (char *)malloc(size * sizeof(char))) {
+            PyErr_NoMemory();
+            return -1;
+        }
+
+        self->buf_size = size;
+    }
+    else if (n > self->buf_size) {
+        UNLESS(self->buf = (char *)realloc(self->buf, n * sizeof(char))) {
+            PyErr_NoMemory();
+            return -1;
+        }
+        self->buf_size = n;
     }
+            
+    if ((int)fread(self->buf, sizeof(char), n, self->fp) != n) {  
+        if (feof(self->fp)) {
+            PyErr_SetNone(PyExc_EOFError);
+            return -1;
+        }
 
-    PyErr_SetFromErrno(PyExc_IOError);
-    return -1;
-  }
+        PyErr_SetFromErrno(PyExc_IOError);
+        return -1;
+    }
 
-  return n;
+    *s = self->buf;
+
+    return n;
 }
 
 
 static int 
-readline_file(ARG(Unpicklerobject *, self), ARG(char **, s))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-{
-  int size, i;
-  char *str;
+readline_file(Unpicklerobject *self, char **s) {
+    int i;
 
-  UNLESS(str = (char *)malloc(100))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return -1;
-  }
+    if (self->buf_size == 0) {
+        UNLESS(self->buf = (char *)malloc(40 * sizeof(char))) {
+            PyErr_NoMemory();
+            return -1;
+        }
+   
+        self->buf_size = 40;
+    }
+
+    i = 0;
+    while (1) {
+        for (; i < (self->buf_size - 1); i++) {
+            if (feof(self->fp) || (self->buf[i] = getc(self->fp)) == '\n') {
+                self->buf[i + 1] = '\0';
+                *s = self->buf;
+                return i + 1;
+            }
+        }
 
-  size = 100;
-  i = 0;
+        UNLESS(self->buf = (char *)realloc(self->buf, 
+            (self->buf_size * 2) * sizeof(char))) {
+            PyErr_NoMemory();
+            return -1;
+        }
 
-  while (1)
-  {
-    for (; i < size; i++)
-    {
-      if (feof(self->fp) || (str[i] = getc(self->fp)) == '\n')
-      {
-        str[i] = 0;
-        *s = str;
-        return i;
-      }
+        self->buf_size *= 2;
     }
 
-    UNLESS(str = realloc(str, size += 100))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return -1;
-    }
-  }
 }    
 
 
 static int 
-read_cStringIO(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-    ARGDECL(int, n)
-{
-  char *ptr;
+read_cStringIO(Unpicklerobject *self, char **s, int  n) {
+    char *ptr;
 
-  if ((*PycStringIO_cread)((PyObject *)self->file, &ptr, n) != n)
-  {
-    PyErr_SetNone(PyExc_EOFError);
-    return -1;
-  }
+    if (PycStringIO->cread((PyObject *)self->file, &ptr, n) != n) {
+        PyErr_SetNone(PyExc_EOFError);
+        return -1;
+    }
+
+    *s = ptr;
 
-  memcpy(*s, ptr, n);
-  return n;
+    return n;
 }
 
 
 static int 
-readline_cStringIO(ARG(Unpicklerobject *, self), ARG(char **, s))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-{
-  int n;
-  char *ptr, *str;
-
-  if ((n = (*PycStringIO_creadline)((PyObject *)self->file, &ptr)) == -1)
-  {
-    return -1;
-  }
-
-  UNLESS(str = (char *)malloc(n * sizeof(char) + 1))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return -1;
-  }
+readline_cStringIO(Unpicklerobject *self, char **s) {
+    int n;
+    char *ptr;
 
-  memcpy(str, ptr, n);
+    if ((n = PycStringIO->creadline((PyObject *)self->file, &ptr)) < 0) {
+        return -1;
+    }
 
-  str[((str[n - 1] == '\n') ? --n : n)] = 0;
+    *s = ptr;
 
-  *s = str;
-  return n;
+    return n;
 }
 
 
 static int 
-read_other(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-    ARGDECL(int, n)
-{
-  PyObject *bytes, *str;
+read_other(Unpicklerobject *self, char **s, int  n) {
+    PyObject *bytes, *str;
+    int res = -1;
 
-  UNLESS(bytes = PyInt_FromLong(n))
-  {
-    if (!PyErr_Occurred())
-      PyErr_SetNone(PyExc_EOFError);
-
-    return -1;
-  }
+    UNLESS(bytes = PyInt_FromLong(n)) {
+        if (!PyErr_Occurred())
+            PyErr_SetNone(PyExc_EOFError);
 
-  UNLESS(self->arg)
-    UNLESS(self->arg = PyTuple_New(1))
-    {
-      Py_DECREF(bytes);
-      return -1;
+        goto finally;
     }
 
-  if (PyTuple_SetItem(self->arg, 0, bytes) == -1)
-  {
-    Py_DECREF(bytes);
-    return -1;
-  }
-  Py_INCREF(bytes);
+    UNLESS(self->arg)
+        UNLESS(self->arg = PyTuple_New(1))
+            goto finally;
 
-  UNLESS(str = PyObject_CallObject(self->read, self->arg))
-  {
-    Py_DECREF(bytes);
-    return -1;
-  }
+    Py_INCREF(bytes);
+    if (PyTuple_SetItem(self->arg, 0, bytes) < 0)
+        goto finally;
 
-  memcpy(*s, PyString_AsString(str), n);
+    UNLESS(str = PyObject_CallObject(self->read, self->arg))
+        goto finally;
 
-  Py_DECREF(bytes);
-  Py_DECREF(str);
+    Py_XDECREF(self->last_string);
+    self->last_string = str;
 
-  return n;
+    *s = PyString_AsString(str);
+
+    res = n;
+
+finally:
+     Py_XDECREF(bytes);
+
+     return res;
 }
 
 
 static int 
-readline_other(ARG(Unpicklerobject *, self), ARG(char **, s))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char **, s)
-{
-  PyObject *str;
-  char *c_str;
-  int size;
-
-  UNLESS(str = PyObject_CallObject(self->readline, empty_tuple))
-  {
-    return -1;
-  }
+readline_other(Unpicklerobject *self, char **s) {
+    PyObject *str;
+    int str_size;
 
-  size = PyString_Size(str);
+    UNLESS(str = PyObject_CallObject(self->readline, empty_tuple)) {
+        return -1;
+    }
 
-  UNLESS(c_str = (char *)malloc((size + 1) * sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return -1;
-  }
+    str_size = PyString_Size(str);
 
-  memcpy(c_str, PyString_AsString(str), size);
+    Py_XDECREF(self->last_string);
+    self->last_string = str;
 
-  if (size > 0)
-  {
-    c_str[((c_str[size - 1] == '\n') ? --size : size)] = 0;
-  }
+    *s = PyString_AsString(str);
 
-  *s = c_str;
+    return str_size;
+}
 
-  Py_DECREF(str);
 
-  return size;
+static char *
+strndup(char *s, int l)
+{
+  char *r;
+  UNLESS(r=malloc((l+1)*sizeof(char))) return (char*)PyErr_NoMemory();
+  memcpy(r,s,l);
+  r[l]=0;
+  return r;
 }
 
 
 static int
-put(ARG(Picklerobject *, self), ARG(PyObject *, ob))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, ob)
-{
-  char c_str[30];
-  int p, len;
-  PyObject *py_ob_id = 0, *memo_len = 0;
+get(Picklerobject *self, PyObject *id) {
+    PyObject *value = 0;
+    long c_value;
+    char s[30];
+    int len;
 
-  if ((p = PyDict_Size(self->memo)) == -1)
-    return -1;
+    UNLESS(value = PyDict_GetItem(self->memo, id))
+        return -1;
 
-  if (!self->bin || (p >= 256))
-  {
-    c_str[0] = PUT;
-    sprintf(c_str + 1, "%d\n", p);
-    len = strlen(c_str);
-  }
-  else
-  {
-    c_str[0] = BINPUT;
-    c_str[1] = p;
-    len = 2;
-  }
+    UNLESS(value = PyTuple_GetItem(value, 0))
+        return -1;
+        
+    c_value = PyInt_AsLong(value);
 
-  if ((*self->write_func)(self, c_str, len) == -1)
-    return -1;
+    if (!self->bin) {
+        s[0] = GET;
+        sprintf(s + 1, "%ld\n", c_value);
+        len = strlen(s);
+    }
+    else {
+        if (c_value < 256) {
+            s[0] = BINGET;
+            s[1] = (int)(c_value & 0xff);
+            len = 2;
+        }
+        else {
+            s[0] = LONG_BINGET;
+            s[1] = (int)(c_value & 0xff);
+            s[2] = (int)((c_value >> 8)  & 0xff);
+            s[3] = (int)((c_value >> 16) & 0xff);
+            s[4] = (int)((c_value >> 24) & 0xff);
+            len = 5;
+        }
+    }
 
-  UNLESS(py_ob_id = PyInt_FromLong((long)ob))
-    return -1;
+    if ((*self->write_func)(self, s, len) < 0)
+        return -1;
 
-  UNLESS(memo_len = PyInt_FromLong(p))
-    goto err;
+    return 0;
+}
+    
 
-  if (PyDict_SetItem(self->memo, py_ob_id, memo_len) == -1)
-    goto err;
+static int
+put(Picklerobject *self, PyObject *ob) {
+    if (ob->ob_refcnt < 2)
+        return 0;
 
-  Py_DECREF(py_ob_id);
-  Py_DECREF(memo_len);
+    return put2(self, ob);
+}
 
-  return 1;
+  
+static int
+put2(Picklerobject *self, PyObject *ob) {
+    char c_str[30];
+    int p, len, res = -1;
+    PyObject *py_ob_id = 0, *memo_len = 0, *t = 0;
+    if ((p = PyDict_Size(self->memo)) < 0)
+        goto finally;
+
+    if (!self->bin) {
+        c_str[0] = PUT;
+        sprintf(c_str + 1, "%d\n", p);
+        len = strlen(c_str);
+    }
+    else {
+        if (p >= 256) {
+            c_str[0] = LONG_BINPUT;
+            c_str[1] = (int)(p & 0xff);
+            c_str[2] = (int)((p >> 8)  & 0xff);
+            c_str[3] = (int)((p >> 16) & 0xff);
+            c_str[4] = (int)((p >> 24) & 0xff);
+            len = 5;
+        }
+        else {
+            c_str[0] = BINPUT;
+            c_str[1] = p;
+            len = 2; 
+        }
+    }
 
-err:
-  Py_XDECREF(py_ob_id);
-  Py_XDECREF(memo_len);
+    if ((*self->write_func)(self, c_str, len) < 0)
+        goto finally;
 
-  return -1;
-}
+    UNLESS(py_ob_id = PyInt_FromLong((long)ob))
+        goto finally;
 
+    UNLESS(memo_len = PyInt_FromLong(p))
+        goto finally;
 
-static int
-safe(ARG(PyObject *, ob))
-    ARGDECL(PyObject *, ob)
-{
-  PyTypeObject *type;
-  PyObject *this_item;
-  int len, res, i;
-  
-  type = ob->ob_type;
+    UNLESS(t = PyTuple_New(2))
+        goto finally;
 
-  if (type == &PyInt_Type    || 
-      type == &PyFloat_Type  || 
-      type == &PyString_Type ||
-      ob == Py_None)
-  {
-    return 1;
-  }
+    PyTuple_SET_ITEM(t, 0, memo_len);
+    Py_INCREF(memo_len);
+    PyTuple_SET_ITEM(t, 1, ob);
+    Py_INCREF(ob);
 
-  if (type == &PyTuple_Type)
-  {
-    len = PyTuple_Size(ob);
-    for (i = 0; i < len; i++)
-    {
-      UNLESS(this_item = PyTuple_GET_ITEM((PyTupleObject *)ob, i))
-        return -1;
-    
-      if ((res = safe(this_item)) == 1)
-        continue;
+    if (PyDict_SetItem(self->memo, py_ob_id, t) < 0)
+        goto finally;
 
-      return res;
-    }
+    res = 0;
 
-    return 1;
-  }
+finally:
+    Py_XDECREF(py_ob_id);
+    Py_XDECREF(memo_len);
+    Py_XDECREF(t);
 
-  return 0;
+    return res;
 }
 
 
 static PyObject *
-whichmodule(ARG(PyObject *, class))
-    ARGDECL(PyObject *, class)
-{
-  int has_key, i, j;
-  PyObject *module = 0, *modules_dict = 0, *class_name = 0, *class_name_attr = 0, 
-      *name = 0;
-  char *name_str, *class_name_str;
+whichmodule(PyObject *global, PyObject *global_name) {
+    int i, j;
+    PyObject *module = 0, *modules_dict = 0,
+        *global_name_attr = 0, *name = 0;
+
+    if (module = PyDict_GetItem(class_map, global)) {
+        Py_INCREF(module);
+        return module;
+    }
+    else {
+        PyErr_Clear();
+    }
 
-  static PyObject *__main__str;
+    UNLESS(modules_dict = PySys_GetObject("modules"))
+        return NULL;
 
-  if ((has_key = PyMapping_HasKey(class_map, class)) == -1)
-    return NULL;
+    i = 0;
+    while (j = PyDict_Next(modules_dict, &i, &name, &module)) {
+        UNLESS(global_name_attr = PyObject_GetAttr(module, global_name)) {
+            PyErr_Clear();
+            continue;
+        }
 
-  if (has_key)
-  {
-    return ((module = PyDict_GetItem(class_map, class)) ? module : NULL);
-  }
+        if (global_name_attr != global) {
+            Py_DECREF(global_name_attr);
+            continue;
+        }
 
-  UNLESS(modules_dict = PySys_GetObject("modules"))
-    return NULL;
+        Py_DECREF(global_name_attr);
 
-  UNLESS(class_name = ((PyClassObject *)class)->cl_name)
-  {
-    PyErr_SetString(PicklingError, "class has no name");
-    return NULL;
-  }
+        break;
+    }
+    
+    if (!j) {
+        PyErr_Format(PicklingError, "Could not find module for %s.", 
+            "O", global_name);
+        return NULL;
+    }
 
-  UNLESS(class_name_str = PyString_AsString(class_name))
-    return NULL;
+    PyDict_SetItem(class_map, global, name);
 
-  i = 0;
-  while ((j = PyDict_Next(modules_dict, &i, &name, &module)))
-  {
-    UNLESS(name_str = PyString_AsString(name))
-      return NULL;
+    Py_INCREF(name);
+    return name;
+}
 
-    if (!strcmp(name_str, "__main__"))
-      continue;
 
-    UNLESS(class_name_attr = PyObject_GetAttr(module, class_name))
-    {
-      PyErr_Clear();
-      continue;
+static int
+save_none(Picklerobject *self, PyObject *args) {
+    static char none = NONE;
+    if ((*self->write_func)(self, &none, 1) < 0)  
+        return -1;
+
+    return 0;
+}
+
+      
+static int
+save_int(Picklerobject *self, PyObject *args) {
+    char c_str[32];
+    long l = PyInt_AS_LONG((PyIntObject *)args);
+    int len = 0;
+
+    if (!self->bin || sizeof(long) == 8 && (l >> 32)) {
+               /* Save extra-long ints in non-binary mode, so that
+                  we can use python long parsing code to restore,
+                  if necessary. */
+        c_str[0] = INT;
+        sprintf(c_str + 1, "%ld\n", l);
+        if ((*self->write_func)(self, c_str, strlen(c_str)) < 0)
+            return -1;
     }
+    else {
+        c_str[1] = (int)( l        & 0xff);
+        c_str[2] = (int)((l >> 8)  & 0xff);
+        c_str[3] = (int)((l >> 16) & 0xff);
+        c_str[4] = (int)((l >> 24) & 0xff);
+
+        if ((c_str[4] == 0) && (c_str[3] == 0)) {
+            if (c_str[2] == 0) {
+                c_str[0] = BININT1;
+                len = 2;
+            }
+            else {
+                c_str[0] = BININT2;
+                len = 3;
+            }
+        }
+        else {
+            c_str[0] = BININT;
+            len = 5;
+        }
 
-    if (class_name_attr != class)
-    {
-      Py_DECREF(class_name_attr);
-      continue;
+        if ((*self->write_func)(self, c_str, len) < 0)
+            return -1;
     }
 
-    Py_DECREF(class_name_attr);
+    return 0;
+}
 
-    break;
-  }
-    
-  if (!j) /* previous while exited normally */
-  {
-    UNLESS(__main__str)
-      UNLESS(__main__str = PyString_FromString("__main__"))
-        return NULL;
 
-    name = __main__str;
-  }
-  else    /* previous while exited via break */
-  {
-    Py_INCREF(name);
-  }
-  
-  PyDict_SetItem(class_map, class, name);
+static int
+save_long(Picklerobject *self, PyObject *args) {
+    int size, res = -1;
+    PyObject *repr = 0;
 
-  return name;
-}
+    static char l = LONG;
 
+    UNLESS(repr = PyObject_Repr(args))
+        goto finally;
 
-static PyObject *
-save_none(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  static char none[] = { NONE };
+    if ((size = PyString_Size(repr)) < 0)
+        goto finally;
 
-  if ((*self->write_func)(self, none, 1) == -1)  
-    return NULL;
+    if ((*self->write_func)(self, &l, 1) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+    if ((*self->write_func)(self, 
+        PyString_AS_STRING((PyStringObject *)repr), size) < 0)
+        goto finally;
 
-      
-static PyObject *
-save_int(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  char c_str[25];
-  long l = PyInt_AS_LONG((PyIntObject *)args);
-  int len;
+    if ((*self->write_func)(self, "\n", 1) < 0)
+        goto finally;
 
-  if (!self->bin)
-  {
-    c_str[0] = INT;
-    sprintf(c_str + 1, "%ld\n", l);
-    if ((*self->write_func)(self, c_str, strlen(c_str)) == -1)
-      return NULL;
-  }
-  else
-  {
-    c_str[1] = (int)(l & 0xff);
-    c_str[2] = (int)((l >> 8)  & 0xff);
-    c_str[3] = (int)((l >> 16) & 0xff);
-    c_str[4] = (int)((l >> 24) & 0xff);
+    res = 0;
 
-    if (!c_str[4])
-    {
-      if (!c_str[3])
-      {
-        if (!c_str[2])
-        {
-          c_str[0] = BININT3;
-          len = 2;
+finally:
+    Py_XDECREF(repr);
+
+    return res;
+}
+
+
+static int
+save_float(Picklerobject *self, PyObject *args) {
+    double x = PyFloat_AS_DOUBLE((PyFloatObject *)args);
+
+#ifdef FORMAT_1_3
+    if (self->bin) {
+        int s, e, i = -1;
+        double f;
+        long fhi, flo;
+        char str[9], *p = str;
+
+        *p = BINFLOAT;
+        p++;
+
+        if (x < 0) {
+            s = 1;
+            x = -x;
         }
         else
-        {
-          c_str[0] = BININT2;
-          len = 3;
-        }
-      }
-      else 
-      {
-        c_str[0] = BININT1;
-        len = 4;
-      }
-    }
-    else
-    {
-      c_str[0] = BININT;
-      len = 5;
-    }
+            s = 0;
 
-    if ((*self->write_func)(self, c_str, len) == -1)
-      return NULL;
-  }
+        f = frexp(x, &e);
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+        /* Normalize f to be in the range [1.0, 2.0) */
+        if (0.5 <= f && f < 1.0) {
+            f *= 2.0;
+            e--;
+        }
+        else if (f == 0.0) {
+            e = 0;
+        }
+        else {
+            PyErr_SetString(PyExc_SystemError,
+                            "frexp() result out of range");
+            return -1;
+        }
 
+        if (e >= 1024) {
+            /* XXX 1024 itself is reserved for Inf/NaN */
+            PyErr_SetString(PyExc_OverflowError,
+                            "float too large to pack with d format");
+            return -1;
+        }
+        else if (e < -1022) {
+            /* Gradual underflow */
+            f = ldexp(f, 1022 + e);
+            e = 0;
+        }
+        else {
+            e += 1023;
+            f -= 1.0; /* Get rid of leading 1 */
+        }
 
-static PyObject *
-save_long(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  char *c_str;
-  int size;
-  PyObject *repr = 0;
+        /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
+        f *= 268435456.0; /* 2**28 */
+        fhi = (long) floor(f); /* Truncate */
+        f -= (double)fhi;
+        f *= 16777216.0; /* 2**24 */
+        flo = (long) floor(f + 0.5); /* Round */
 
-  UNLESS(repr = PyObject_Repr(args))
-    return NULL;
+        /* First byte */
+        *p = (s<<7) | (e>>4);
+        p++;
 
-  if ((size = PyString_Size(repr)) == -1)
-  {
-    Py_DECREF(repr);
-    return NULL;
-  }
+        /* Second byte */
+        *p = ((e&0xF)<<4) | (fhi>>24);
+        p++;
 
-  UNLESS(c_str = (char *)malloc((size + 2) * sizeof(char)))
-  {
-    Py_DECREF(repr);
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+        /* Third byte */
+        *p = (fhi>>16) & 0xFF;
+        p++;
 
-  c_str[0] = LONG;
-  memcpy(c_str + 1, PyString_AS_STRING((PyStringObject *)repr), size);
-  c_str[size + 1] = '\n';
+        /* Fourth byte */
+        *p = (fhi>>8) & 0xFF;
+        p++;
 
-  Py_DECREF(repr);
+        /* Fifth byte */
+        *p = fhi & 0xFF;
+        p++;
 
-  if ((*self->write_func)(self, c_str, size + 2) == -1)
-  {
-    free(c_str);
-    return NULL;
-  }
+        /* Sixth byte */
+        *p = (flo>>16) & 0xFF;
+        p++;
 
-  free(c_str);
+        /* Seventh byte */
+        *p = (flo>>8) & 0xFF;
+        p++;
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+        /* Eighth byte */
+        *p = flo & 0xFF;
 
+        if ((*self->write_func)(self, str, 9) < 0)
+            return -1;
+    }
+    else
+#endif
+    {
+        char c_str[250];
+        c_str[0] = FLOAT;
+        sprintf(c_str + 1, "%f\n", x);
 
-static PyObject *
-save_float(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  char c_str[250];
+        if ((*self->write_func)(self, c_str, strlen(c_str)) < 0)
+            return -1;
+    }
 
-  c_str[0] = FLOAT;
-  sprintf(c_str + 1, "%f\n", PyFloat_AS_DOUBLE((PyFloatObject *)args));
+    return 0;
+}
 
-  if ((*self->write_func)(self, c_str, strlen(c_str)) == -1)
-    return NULL;
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+static int
+save_string(Picklerobject *self, PyObject *args) {
+    int size, len;
 
+    size = PyString_Size(args);
 
-static PyObject *
-save_string(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  char *c_str;
-  int size, len;
+    if (!self->bin) {
+        PyObject *repr;
+        char *repr_str;
 
-  if (!self->bin)
-  {
-    PyObject *repr;
-    char *repr_str;
+        static char string = STRING;
 
-    UNLESS(repr = PyObject_Repr(args))
-      return NULL;
+        UNLESS(repr = PyObject_Repr(args))
+            return -1;
 
-    repr_str = PyString_AS_STRING((PyStringObject *)repr);
-    size = PyString_Size(repr);
+        repr_str = PyString_AS_STRING((PyStringObject *)repr);
+        len = PyString_Size(repr);
 
-    UNLESS(c_str = (char *)malloc((size + 2) * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
-   
-    c_str[0] = STRING;
-    memcpy(c_str + 1, repr_str, size);
-    c_str[size + 1] = '\n';
+        if ((*self->write_func)(self, &string, 1) < 0)
+            return -1;
 
-    len = size + 2;
+        if ((*self->write_func)(self, repr_str, len) < 0)
+            return -1;
 
-    Py_XDECREF(repr);
-  }
-  else
-  {
-    size = PyString_Size(args);
+        if ((*self->write_func)(self, "\n", 1) < 0)
+            return -1;
 
-    UNLESS(c_str = (char *)malloc((size + 30) * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
+        Py_XDECREF(repr);
     }
+    else {
+        int i;
+        char c_str[5];
 
-    if (size < 256)
-    {
-      c_str[0] = SHORT_BINSTRING;
-      c_str[1] = size;
-      len = 2;
-    }
-    else  
-    {
-      c_str[0] = BINSTRING;
-      sprintf(c_str + 1, "%d\n", size);
-      len = strlen(c_str);
-    }
+        size = PyString_Size(args);
 
-    memcpy(c_str + len, PyString_AS_STRING((PyStringObject *)args), size);
+        if (size < 256) {
+            c_str[0] = SHORT_BINSTRING;
+            c_str[1] = size;
+            len = 2;
+        }
+        else {
+            c_str[0] = BINSTRING;
+            for (i = 1; i < 5; i++)
+                c_str[i] = (int)(size >> ((i - 1) * 8));
+            len = 5;
+        }
 
-    len += size;
-  }
+        if ((*self->write_func)(self, c_str, len) < 0)
+            return -1;
 
-  if ((*self->write_func)(self, c_str, len) == -1)
-  {
-    free(c_str);
-    return NULL;
-  }
+        if ((*self->write_func)(self, 
+            PyString_AS_STRING((PyStringObject *)args), size) < 0)
+            return -1;
+    }
 
-  free(c_str);
+    if (size > 1)
+        if (put(self, args) < 0)
+            return -1;
 
-  if (args->ob_refcnt > 1)
-  {
-    if (put(self, args) == -1)
-    {
-      return NULL;
-    }
-  }
-  
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 }
 
 
-static PyObject *
-save_tuple(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *element = 0, *junk = 0, *py_tuple_id = 0;
-  int len, i, dict_size;
-
-  static char tuple = TUPLE;
+static int
+save_tuple(Picklerobject *self, PyObject *args) {
+    PyObject *element = 0, *py_tuple_id = 0;
+    int len, i, has_key, res = -1;
 
-  if ((*self->write_func)(self, &MARKv, 1) == -1)
-    return NULL;
+    static char tuple = TUPLE;
 
-  UNLESS(py_tuple_id = PyInt_FromLong((long)args))  return NULL;
+    if ((*self->write_func)(self, &MARKv, 1) < 0)
+        goto finally;
 
-  if ((len = PyTuple_Size(args)) == -1)  
-    goto err;
+    if ((len = PyTuple_Size(args)) < 0)  
+        goto finally;
 
-  for (i = 0; i < len; i++)
-  {
-    UNLESS(element = PyTuple_GET_ITEM((PyTupleObject *)args, i))  
-      goto err;
+    for (i = 0; i < len; i++) {
+        UNLESS(element = PyTuple_GET_ITEM((PyTupleObject *)args, i))  
+            goto finally;
     
-    dict_size = PyDict_Size(self->memo);
-
-    UNLESS(junk = save(self, element))
-      goto err;
-    Py_DECREF(junk);
-
-    if (((PyDict_Size(self->memo) - dict_size) > 1)  && 
-        PyMapping_HasKey(self->memo, py_tuple_id))
-    {
-      char c_str[30];
-      long c_value;
-      int c_str_len;
-      PyObject *value;
-      static char pop = POP;
-
-      while (i-- >= 0)
-      {
-        if ((*self->write_func)(self, &pop, 1) == -1)
-          goto err;
-      }
-
-      UNLESS(value = PyDict_GetItem(self->memo, py_tuple_id))
-        goto err;
+        if (save(self, element, 0) < 0)
+            goto finally;
+    }
 
-      c_value = PyInt_AsLong(value);
+    UNLESS(py_tuple_id = PyInt_FromLong((long)args))
+        goto finally;
 
-      if (self->bin && (c_value < 256))
-      {
-        c_str[0] = BINGET;
-        c_str[1] = c_value;
-        c_str_len = 2;
-      }
-      else
-      {
-        c_str[0] = GET;
-        sprintf(c_str + 1, "%ld\n", c_value);
-        c_str_len = strlen(c_str);
-      }
+    if (len) {
+        if (has_key = cPickle_PyMapping_HasKey(self->memo, py_tuple_id) < 0)
+            goto finally;
 
-      if ((*self->write_func)(self, c_str, c_str_len) == -1)
-        goto err;
+        if (has_key) {
+            if (self->bin) {
+                static char pop_mark = POP_MARK;
+  
+                if ((*self->write_func)(self, &pop_mark, 1) < 0)
+                    goto finally;
+            }
+            else {
+                static char pop = POP;
+       
+                for (i = 0; i <= len; i++) {
+                    if ((*self->write_func)(self, &pop, 1) < 0)
+                        goto finally;
+                } 
+            }
+        
+            if (get(self, py_tuple_id) < 0)
+                goto finally;
 
-      break;
+            res = 0;
+            goto finally;
+        }
     }
-  }
 
-  if (i >= len)
-  {
-    if ((*self->write_func)(self, &tuple, 1) == -1)
-      goto err;
-    
-    if (args->ob_refcnt > 1)
-    {
-      if (put(self, args) == -1)
-      {
-        goto err;
-      }
+    if ((*self->write_func)(self, &tuple, 1) < 0) {
+        goto finally;
     }
-  }
-  Py_DECREF(py_tuple_id);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if (put(self, args) < 0)
+        goto finally;
+    res = 0;
 
-err:
-  Py_XDECREF(py_tuple_id);
+finally:
+    Py_XDECREF(py_tuple_id);
 
-  return NULL;
+    return res;
 }
 
+static int
+save_empty_tuple(Picklerobject *self, PyObject *args) {
+    static char tuple = EMPTY_TUPLE;
 
-static PyObject *
-save_list(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *element = 0, *junk = 0;
-  int len, i, safe_val;
-  static char append = APPEND, list = LIST;
-
-  if ((*self->write_func)(self, &MARKv, 1) == -1)
-    return NULL;
+    return (*self->write_func)(self, &tuple, 1);
+}
 
-  if ((len = PyList_Size(args)) == -1)
-    return NULL;
 
-  for (i = 0; i < len; i++)
-  {
-    UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i))  
-      return NULL;
+static int
+save_list(Picklerobject *self, PyObject *args) {
+    PyObject *element = 0;
+    int s_len, len, i, using_appends, res = -1;
+    char s[3];
+
+    static char append = APPEND, appends = APPENDS;
+
+    if(self->bin) {
+        s[0] = EMPTY_LIST;
+        s_len = 1;
+    } 
+    else {
+        s[0] = MARK;
+        s[1] = LIST;
+        s_len = 2;
+    }
 
-    if ((safe_val = safe(element)) == -1)  
-      return NULL;
-    UNLESS(safe_val)
-      break;
+    if ((len = PyList_Size(args)) < 0)
+        goto finally;
 
-    UNLESS(junk = save(self, element))  
-      return NULL;
-    Py_DECREF(junk);
-  }
+    if ((*self->write_func)(self, s, s_len) < 0)
+        goto finally;
 
-  if (args->ob_refcnt > 1)
-  {
-    if (put(self, args) == -1)
+    if (len == 0)
     {
-      return NULL;
+        if (put(self, args) < 0)
+            goto finally;
+    }
+    else
+    {
+        if (put2(self, args) < 0)
+            goto finally;
     }
-  }
 
-  if ((*self->write_func)(self, &list, 1) == -1)
-    return NULL;
+    if (using_appends = (self->bin && (len > 1)))
+        if ((*self->write_func)(self, &MARKv, 1) < 0)
+            goto finally;
 
-  for (; i < len; i++)
-  {
-    UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i))  
-      return NULL;
+    for (i = 0; i < len; i++) {
+        UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i))  
+            goto finally;
 
-    UNLESS(junk = save(self, element))  
-      return NULL;
-    Py_DECREF(junk);
+        if (save(self, element, 0) < 0)  
+            goto finally;      
 
-    if ((*self->write_func)(self, &append, 1) == -1)
-      return NULL;
-  }
+        if (!using_appends) {
+            if ((*self->write_func)(self, &append, 1) < 0)
+                goto finally;
+        }
+    }
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+    if (using_appends) {
+        if ((*self->write_func)(self, &appends, 1) < 0)
+            goto finally;
+    }
 
+    res = 0;
 
-static PyObject *
-save_dict(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *key = 0, *value = 0, *junk = 0;
-  int i, safe_key, safe_value;
+finally:
 
-  static char setitem = SETITEM, dict = DICT;
+    return res;
+}
 
-  if ((*self->write_func)(self, &MARKv, 1) == -1)
-    return NULL;
 
-  i = 0;
-  
-  while (PyDict_Next(args, &i, &key, &value))
-  {
-    if ((safe_key = safe(key)) == -1)  
-      return NULL;
+static int
+save_dict(Picklerobject *self, PyObject *args) {
+    PyObject *key = 0, *value = 0;
+    int i, len, res = -1, using_setitems;
+    char s[3];
 
-    UNLESS(safe_key)  
-      break;
-   
-    if ((safe_value = safe(value)) == -1)  
-      return NULL;
-   
-    UNLESS(safe_value)  
-      break;
+    static char setitem = SETITEM, setitems = SETITEMS;
 
-    UNLESS(junk = save(self, key))
-      return NULL;
-    Py_DECREF(junk);
+    if (self->bin) {
+       s[0] = EMPTY_DICT;
+       len = 1;
+    }
+    else {
+        s[0] = MARK;
+        s[1] = DICT;
+        len = 2;
+    }
 
-    UNLESS(junk = save(self, value))
-      return NULL;
-    Py_DECREF(junk);
-  }
+    if ((*self->write_func)(self, s, len) < 0)
+        goto finally;
 
-  if ((*self->write_func)(self, &dict, 1) == -1)
-    return NULL;
+    if ((len = PyDict_Size(args)) < 0)
+        goto finally;
 
-  if (args->ob_refcnt > 1)
-  {
-    if (put(self, args) == -1)
+    if (len == 0)
     {
-      return NULL;
+        if (put(self, args) < 0)
+            goto finally;
+    }
+    else
+    {
+        if (put2(self, args) < 0)
+            goto finally;
     }
-  }
 
-  while (PyDict_Next(args, &i, &key, &value))
-  {
-    UNLESS(junk = save(self, key))
-      return NULL;
-    Py_DECREF(junk);
+    if (using_setitems = (self->bin && (PyDict_Size(args) > 1)))
+        if ((*self->write_func)(self, &MARKv, 1) < 0)
+            goto finally;
 
-    UNLESS(junk = save(self, value))
-      return NULL;
-    Py_DECREF(junk);
+    i = 0;
+    while (PyDict_Next(args, &i, &key, &value)) {
+        if (save(self, key, 0) < 0)
+            goto finally;
 
-    if ((*self->write_func)(self, &setitem, 1) == -1)
-      return NULL;
-  }
+        if (save(self, value, 0) < 0)
+            goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+        if (!using_setitems) {
+            if ((*self->write_func)(self, &setitem, 1) < 0)
+                goto finally;
+        }
+    }
 
+    if (using_setitems) {
+        if ((*self->write_func)(self, &setitems, 1) < 0)
+            goto finally;
+    }
 
-static PyObject *  
-save_inst(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *class = 0, *module = 0, *name = 0,
-           *junk = 0, *state = 0, *getinitargs_func = 0, *getstate_func = 0;
-  char *module_str, *name_str, *c_str;
-  int module_size, name_size, size;
-  static char build = BUILD;
+    res = 0;
 
-  if ((*self->write_func)(self, &MARKv, 1) == -1)
-    return NULL;
+finally:
 
-  UNLESS(class = PyObject_GetAttrString(args, "__class__"))
-    return NULL;
+    return res;
+}
 
-  if (self->bin)
-  {
-    UNLESS(junk = save(self, class))
-      goto err;
-    Py_DECREF(junk);
-  }
 
-  if ((getinitargs_func = PyObject_GetAttrString(args, "__getinitargs__")))
-  {
-    PyObject *class_args = 0, *element = 0;
-    int i, len;
+static int  
+save_inst(Picklerobject *self, PyObject *args) {
+    PyObject *class = 0, *module = 0, *name = 0, *state = 0, 
+             *getinitargs_func = 0, *getstate_func = 0, *class_args = 0;
+    char *module_str, *name_str;
+    int module_size, name_size, res = -1;
 
-    UNLESS(class_args = PyObject_CallObject(getinitargs_func, empty_tuple))
-    {
-      Py_DECREF(getinitargs_func);
-      goto err;
-    }
+    static char inst = INST, obj = OBJ, build = BUILD;
 
-    if ((len = PyObject_Length(class_args)) == -1)  
-    {
-      Py_DECREF(class_args);
-      goto err;
+    if ((*self->write_func)(self, &MARKv, 1) < 0)
+        goto finally;
+
+    UNLESS(class = PyObject_GetAttr(args, __class___str))
+        goto finally;
+
+    if (self->bin) {
+        if (save(self, class, 0) < 0)
+            goto finally;
     }
 
-    for (i = 0; i < len; i++)
-    {
-      UNLESS(element = PySequence_GetItem(class_args, i)) 
-      { 
-        Py_DECREF(class_args); 
-        goto err;
-      }
+    if (getinitargs_func = PyObject_GetAttr(args, __getinitargs___str)) {
+        PyObject *element = 0;
+        int i, len;
 
-      UNLESS(junk = save(self, element))
-      {
-        Py_DECREF(element); Py_DECREF(class_args);
-        goto err;
-      }
+        UNLESS(class_args = 
+            PyObject_CallObject(getinitargs_func, empty_tuple))
+            goto finally;
 
-      Py_DECREF(junk);
-      Py_DECREF(element);
-    }
+        if ((len = PyObject_Length(class_args)) < 0)  
+            goto finally;
 
-    Py_DECREF(class_args);
-  }
-  else
-  {
-    PyErr_Clear();
-  }
+        for (i = 0; i < len; i++) {
+            UNLESS(element = PySequence_GetItem(class_args, i)) 
+                goto finally;
 
-  if (!self->bin)
-  {
-    UNLESS(module = whichmodule(class))
-      goto err;
-    
-    UNLESS(name = ((PyClassObject *)class)->cl_name)
-    {
-      PyErr_SetString(PicklingError, "class has no name");
-      goto err;
+            if (save(self, element, 0) < 0) {
+                Py_DECREF(element);
+                goto finally;
+            }
+
+            Py_DECREF(element);
+        }
+    }
+    else {
+        PyErr_Clear();
     }
 
-    module_str = PyString_AS_STRING((PyStringObject *)module);
-    module_size = PyString_Size(module);
-    name_str   = PyString_AS_STRING((PyStringObject *)name);
-    name_size = PyString_Size(name);
+    if (!self->bin) {
+        UNLESS(name = ((PyClassObject *)class)->cl_name) {
+            PyErr_SetString(PicklingError, "class has no name");
+            goto finally;
+        }
 
-    size = name_size + module_size + 3;
+        UNLESS(module = whichmodule(class, name))
+            goto finally;
+    
+        module_str = PyString_AS_STRING((PyStringObject *)module);
+        module_size = PyString_Size(module);
+        name_str   = PyString_AS_STRING((PyStringObject *)name);
+        name_size = PyString_Size(name);
 
-    UNLESS(c_str = (char *)malloc(size * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
+        if ((*self->write_func)(self, &inst, 1) < 0)
+            goto finally;
 
-    c_str[0] = INST;
-    memcpy(c_str + 1, module_str, module_size);
-    c_str[module_size + 1] = '\n';
-    memcpy(c_str + module_size + 2, name_str, name_size);
-    c_str[module_size + name_size + 2] = '\n';
+        if ((*self->write_func)(self, module_str, module_size) < 0)
+            goto finally;
 
-    if ((*self->write_func)(self, c_str, size) == -1)
-    {
-      free(c_str);
-      goto err;
-                                                                                                                                                                      }
+        if ((*self->write_func)(self, "\n", 1) < 0)
+            goto finally;
 
-    free(c_str);
-  }
+        if ((*self->write_func)(self, name_str, name_size) < 0)
+            goto finally;
 
-  if (args->ob_refcnt > 1)
-  {
-    if (put(self, args) == -1)
-    {
-      goto err;
+        if ((*self->write_func)(self, "\n", 1) < 0)
+            goto finally;
     }
-  }
-
-  if ((getstate_func = PyObject_GetAttrString(args, "__getstate__")))
-  {
-    UNLESS(state = PyObject_CallObject(getstate_func, empty_tuple))
-    {
-      Py_DECREF(getstate_func);
-      goto err;
+    else if ((*self->write_func)(self, &obj, 1) < 0) {
+        goto finally;
     }
-  }
-  else
-  {
-    PyErr_Clear();
 
-    UNLESS(state = PyObject_GetAttrString(args, "__dict__"))
-      goto err;
-  }
+    if (getstate_func = PyObject_GetAttr(args, __getstate___str)) {
+        UNLESS(state = PyObject_CallObject(getstate_func, empty_tuple))
+            goto finally;
+    }
+    else {
+        PyErr_Clear();
 
-  UNLESS(junk = save(self, state))
-    goto err;
-  Py_DECREF(junk);
+        UNLESS(state = PyObject_GetAttr(args, __dict___str)) {
+            PyErr_Clear();
+            res = 0;
+            goto finally;
+        }
+    }
 
-  Py_XDECREF(getinitargs_func);
-  Py_XDECREF(getstate_func);
-  Py_XDECREF(module);
-  Py_XDECREF(state);
+    if (!PyDict_Check(state)) {
+        if (put2(self, args) < 0)
+            goto finally;
+    }
+    else {
+        if (put(self, args) < 0)
+            goto finally;
+    }
+  
+    if (save(self, state, 0) < 0)
+        goto finally;
 
-  if ((*self->write_func)(self, &build, 1) == -1)
-    return NULL;
+    if ((*self->write_func)(self, &build, 1) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(getinitargs_func);
-  Py_XDECREF(getstate_func);
-  Py_XDECREF(module);
-  Py_XDECREF(state);
+finally:
+    Py_XDECREF(module);
+    Py_XDECREF(class);
+    Py_XDECREF(state);
+    Py_XDECREF(getinitargs_func);
+    Py_XDECREF(getstate_func);
+    Py_XDECREF(class_args);
 
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-save_class(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *module = 0, *name = 0;
-  char *name_str, *module_str, *c_str;
-  int module_size, name_size, size;
+static int
+save_global(Picklerobject *self, PyObject *args, PyObject *name) {
+    PyObject *global_name = 0, *module = 0;
+    char *name_str, *module_str; 
+    int module_size, name_size, res = -1;
 
-  UNLESS(module = whichmodule(args))
-    return NULL;
+    static char global = GLOBAL;
 
-  UNLESS(name = ((PyClassObject *)args)->cl_name)
-  {
-    PyErr_SetString(PicklingError, "class has no name");
-    goto err;
-  }
+    if (name)
+    {
+        global_name = name;
+        Py_INCREF(global_name);
+    }
+    else
+    {
+        UNLESS(global_name = PyObject_GetAttr(args, __name___str))
+            goto finally;
+    }
+
+    UNLESS(module = whichmodule(args, global_name))
+        goto finally;
 
-  module_str = PyString_AS_STRING((PyStringObject *)module);
-  module_size = PyString_Size(module);
-  name_str   = PyString_AS_STRING((PyStringObject *)name);
-  name_size = PyString_Size(name);
+    module_str = PyString_AS_STRING((PyStringObject *)module);
+    module_size = PyString_Size(module);
+    name_str   = PyString_AS_STRING((PyStringObject *)global_name);
+    name_size = PyString_Size(global_name);
 
-  size = name_size + module_size + 3;
+    if ((*self->write_func)(self, &global, 1) < 0)
+        goto finally;
 
-  UNLESS(c_str = (char *)malloc(size * sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    if ((*self->write_func)(self, module_str, module_size) < 0)
+        goto finally;
 
-  c_str[0] = CLASS;
-  memcpy(c_str + 1, module_str, module_size);
-  c_str[module_size + 1] = '\n';
-  memcpy(c_str + module_size + 2, name_str, name_size);
-  c_str[module_size + name_size + 2] = '\n';
+    if ((*self->write_func)(self, "\n", 1) < 0)
+        goto finally;
 
-  if ((*self->write_func)(self, c_str, size) == -1)
-  {
-    free(c_str);
-    goto err;
-  }
-  free(c_str);
+    if ((*self->write_func)(self, name_str, name_size) < 0)
+        goto finally;
 
-  if (args->ob_refcnt > 1)
-  {
-    if (put(self, args) == -1)
-    {
-      goto err;
-    }
-  }
+    if ((*self->write_func)(self, "\n", 1) < 0)
+        goto finally;
 
-  Py_DECREF(module);
+    if (put(self, args) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(module);
+finally:
+    Py_XDECREF(module);
+    Py_XDECREF(global_name);
 
-  return NULL;
+    return res;
 }
 
+static int
+save_pers(Picklerobject *self, PyObject *args, PyObject *f) {
+    PyObject *pid = 0;
+    int size, res = -1;
 
-static PyObject *
-save(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyTypeObject *type;
-  char *error_str, *name_c;
-  PyObject *name, *name_repr;
+    static char persid = PERSID, binpersid = BINPERSID;
 
-  if (self->pers_func)
-  {
-    PyObject *pid;
-    int size;
-    
     UNLESS(self->arg)
-      UNLESS(self->arg = PyTuple_New(1))
-        return NULL;
+        UNLESS(self->arg = PyTuple_New(1))
+            goto finally;
     
-    if (PyTuple_SetItem(self->arg, 0, args) == -1)
-      return NULL;
-    Py_INCREF(args);
+    Py_INCREF(args);      
+    if (PyTuple_SetItem(self->arg, 0, args) < 0)
+        goto finally;
     
-    UNLESS(pid = PyObject_CallObject(self->pers_func, self->arg))
-      return NULL;
+    UNLESS(pid = PyObject_CallObject(f, self->arg))
+        goto finally;
+
+    if (pid != Py_None) {
+        if (!self->bin) {
+            if (!PyString_Check(pid)) {
+                PyErr_SetString(PicklingError, 
+                    "persistent id must be string");
+                goto finally;
+            }
+
+            if ((*self->write_func)(self, &persid, 1) < 0)
+                goto finally;
+
+            if ((size = PyString_Size(pid)) < 0)
+                goto finally;
+
+            if ((*self->write_func)(self, 
+                PyString_AS_STRING((PyStringObject *)pid), size) < 0)
+                goto finally;
+
+            if ((*self->write_func)(self, "\n", 1) < 0)
+                goto finally;
+     
+            res = 1;
+            goto finally;
+        }
+        else if (save(self, pid, 1) >= 0) {
+            if ((*self->write_func)(self, &binpersid, 1) < 0)
+                res = -1;
+            else
+                res = 1;
+        }
 
-    if (pid != Py_None)
-    {
-      char *pid_str;
+        goto finally;              
+    }
 
-      if ((size = PyString_Size(pid)) == -1)
-      {
-        Py_DECREF(pid);
-        return NULL;
-      }
+    res = 0;
 
-      UNLESS(pid_str = (char *)malloc((2 + size) * sizeof(char)))
-      {
-        PyErr_SetString(PyExc_MemoryError, "out of memory");
-        Py_DECREF(pid);
-        return NULL;
-      }
+finally:
+    Py_XDECREF(pid);
 
-      pid_str[0] = PERSID;
-      memcpy(pid_str + 1, PyString_AS_STRING((PyStringObject *)pid), size);
-      pid_str[size + 1] = '\n';
+    return res;
+}
 
-      Py_DECREF(pid);
-  
-      if ((*self->write_func)(self, pid_str, size + 2) == -1)
-      {
-        free(pid_str);
-        return NULL;
-      }
 
-      free(pid_str);
+static int 
+save_reduce(Picklerobject *self, PyObject *callable,
+            PyObject *tup, PyObject *state, PyObject *ob) {
+    static char reduce = REDUCE, build = BUILD;
 
-      Py_INCREF(Py_None);
-      return Py_None;
-    }
+    if (save(self, callable, 0) < 0)
+        return -1;
 
-    Py_DECREF(pid);
-  }
+    if (save(self, tup, 0) < 0)
+        return -1;
 
-  if (args == Py_None)
-  {
-    return save_none(self, args);
-  }
+    if ((*self->write_func)(self, &reduce, 1) < 0)
+        return -1;
 
-  type = args->ob_type;
+    if (ob != NULL)
+    {
+        if (state && !PyDict_Check(state)) {
+            if (put2(self, ob) < 0)
+                return -1;
+        }
+        else {
+            if (put(self, ob) < 0)
+                return -1;
+        }
+    }
+    
+    if (state)
+    {
+        if (save(self, state, 0) < 0)
+            return -1;
 
-  if (type == &PyInt_Type)
-  {
-    return save_int(self, args);
-  }
+        if ((*self->write_func)(self, &build, 1) < 0)
+            return -1;
+    }
 
-  if (type == &PyLong_Type)
-  {
-    return save_long(self, args);
-  }
+    return 0;
+}
 
-  if (type == &PyFloat_Type)
-  {
-    return save_float(self, args);
-  }
 
-  if (args->ob_refcnt > 1)
-  {
-    long ob_id;
-    int  has_key;
-    PyObject *py_ob_id;
+static int
+save(Picklerobject *self, PyObject *args, int  pers_save) {
+    PyTypeObject *type;
+    PyObject *py_ob_id = 0, *__reduce__ = 0, *t = 0, *arg_tup = 0,
+             *callable = 0, *state = 0, *junk = 0;
+    int res = -1, tmp, size;
+
+    if (!pers_save && self->pers_func) {
+        if ((tmp = save_pers(self, args, self->pers_func)) != 0) {
+            res = tmp;
+            goto finally;
+        }
+    }
 
-    ob_id = (long)args;
-  
-    UNLESS(py_ob_id = PyInt_FromLong(ob_id))
-      return NULL;
+    if (args == Py_None) {
+        res = save_none(self, args);
+        goto finally;
+    }
 
-    if ((has_key = PyMapping_HasKey(self->memo, py_ob_id)) == -1)
-    {
-      Py_DECREF(py_ob_id);
-      return NULL;
+    type = args->ob_type;
+
+    switch (type->tp_name[0]) {
+        case 'i':
+            if (type == &PyInt_Type) {
+                res = save_int(self, args);
+                goto finally;
+            }
+            break;
+
+        case 'l':
+            if (type == &PyLong_Type) {
+                res = save_long(self, args);
+                goto finally;
+            }
+            break;
+
+        case 'f':
+            if (type == &PyFloat_Type) {
+                res = save_float(self, args);
+                goto finally;
+            }
+           break;
+
+        case 't':
+            if (type == &PyTuple_Type && PyTuple_Size(args)==0) {
+               if(self->bin) res = save_empty_tuple(self, args);
+               else          res = save_tuple(self, args);
+                goto finally;
+            }
+
+        case 's':
+            if ((type == &PyString_Type) && (PyString_Size(args) < 2)) {
+                res = save_string(self, args);
+                goto finally;
+            }
     }
 
-    if (has_key)
-    {
-      PyObject *value;
-      long c_value;
-      char get_str[30];
-      int len;
+    if (args->ob_refcnt > 1) {
+        long ob_id;
+        int  has_key;
 
-      UNLESS(value = PyDict_GetItem(self->memo, py_ob_id))
-      {
-        Py_DECREF(py_ob_id);
-        return NULL;
-      }
+        ob_id = (long)args;
 
-      Py_DECREF(py_ob_id);
+        UNLESS(py_ob_id = PyInt_FromLong(ob_id))
+            goto finally;
 
-      c_value = PyInt_AsLong(value);
+        if ((has_key = cPickle_PyMapping_HasKey(self->memo, py_ob_id)) < 0)
+            goto finally;
 
-      if (self->bin && (c_value < 256))
-      {
-        get_str[0] = BINGET;
-        get_str[1] = c_value;
-        len = 2;
-      }
-      else
-      {
-        get_str[0] = GET;
-        sprintf(get_str + 1, "%ld\n", c_value);
-        len = strlen(get_str);
-      }
+        if (has_key) {
+            if (get(self, py_ob_id) < 0)
+                goto finally;
 
-      if ((*self->write_func)(self, get_str, len) == -1)
-        return NULL;
+            res = 0;
+            goto finally;
+        }
+    }
 
-      Py_INCREF(Py_None);
-      return Py_None;
+    switch (type->tp_name[0]) {
+        case 's':
+            if (type == &PyString_Type) {
+                res = save_string(self, args);
+                goto finally;
+            }
+
+        case 't':
+            if (type == &PyTuple_Type) {
+                res = save_tuple(self, args);
+                goto finally;
+           }
+
+        case 'l':
+            if (type == &PyList_Type) {
+                res = save_list(self, args);
+                goto finally;
+            }
+
+        case 'd':
+            if (type == &PyDict_Type) {
+                res = save_dict(self, args);
+                goto finally; 
+            }
+
+        case 'i':
+            if (type == &PyInstance_Type) {
+                res = save_inst(self, args);
+                goto finally;
+            }
+
+        case 'c':
+            if (type == &PyClass_Type) {
+                res = save_global(self, args, NULL);
+                goto finally;
+            }
+
+        case 'f':
+            if (type == &PyFunction_Type) {
+                res = save_global(self, args, NULL);
+                goto finally;
+            }
+
+        case 'b':
+            if (type == &PyCFunction_Type) {
+                res = save_global(self, args, NULL);
+                goto finally;
+            }
     }
 
-    Py_DECREF(py_ob_id);
-  }
+    if (!pers_save && self->inst_pers_func) {
+        if ((tmp = save_pers(self, args, self->inst_pers_func)) != 0) {
+            res = tmp;
+            goto finally;
+        }
+    }
 
-  if (type == &PyString_Type)
-  {
-    return save_string(self, args);
-  }
+    if (__reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type)) {
+        Py_INCREF(__reduce__);
 
-  if (type == &PyTuple_Type)
-  {
-    return save_tuple(self, args);
-  }
+        UNLESS(self->arg)
+            UNLESS(self->arg = PyTuple_New(1))
+                goto finally;
 
-  if (type == &PyList_Type)
-  {
-    return save_list(self, args);
-  }
+        Py_INCREF(args);
+        if (PyTuple_SetItem(self->arg, 0, args) < 0)
+            goto finally;
 
-  if (type == &PyDict_Type)
-  {
-    return save_dict(self, args);
-  }
+        UNLESS(t = PyObject_CallObject(__reduce__, self->arg))
+            goto finally;
+    }        
+    else {
+        PyErr_Clear();
 
-  if (type == &PyInstance_Type)
-  {
-    return save_inst(self, args);
-  }
+        if (__reduce__ = PyObject_GetAttr(args, __reduce___str)) {
+            UNLESS(t = PyObject_CallObject(__reduce__, empty_tuple))
+                goto finally;
+        }
+        else {
+            PyErr_Clear();
+        }
+    }
 
-  if (type == &PyClass_Type)
-  {
-    return save_class(self, args);
-  }
+    if (t) {
+        if (PyString_Check(t)) {
+            res = save_global(self, args, t);
+            goto finally;
+        }
+        if (!PyTuple_Check(t)) {
+            PyErr_Format(PicklingError, "Value returned by %s must "
+                "be a tuple", "O", __reduce__);
+            goto finally;
+        }
 
-  if (PyObject_HasAttrString(args, "__class__"))
-  {
-    return save_inst(self, args);
-  }
+        size = PyTuple_Size(t);
+        
+        if ((size != 3) && (size != 2)) {
+            PyErr_Format(PicklingError, "tuple returned by %s must "     
+                "contain only two or three elements", "O", __reduce__);
+                goto finally;
+        }
+        
+        callable = PyTuple_GET_ITEM(t, 0);
+        arg_tup = PyTuple_GET_ITEM(t, 1);
 
-  UNLESS(name = PyObject_GetAttrString((PyObject *)type, "__name__"))
-    return NULL;
+        if (size > 2) {
+            state = PyTuple_GET_ITEM(t, 2);
+        }
 
-  UNLESS(name_repr = PyObject_Repr(name))
-  {
-    Py_DECREF(name);
-  }
+        UNLESS(PyTuple_Check(arg_tup)) {
+            PyErr_Format(PicklingError, "Second element of tuple "
+                "returned by %s must be a tuple", "O", __reduce__);
+            goto finally;
+        }
 
-  name_c = PyString_AsString(name_repr);
+        res = save_reduce(self, callable, arg_tup, state, args);
+        goto finally;
+    }
 
-  UNLESS(error_str = (char *)malloc((strlen(name_c) + 25) * sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    Py_DECREF(name);
-    Py_DECREF(name_repr);
-    return NULL;
-  }
+    /*
+    if (PyObject_HasAttrString(args, "__class__")) {
+        res = save_inst(self, args);
+        goto finally;
+    }
+    */
 
-  sprintf(error_str, "Cannot pickle %s objects.", name_c);
+    PyErr_Format(PicklingError, "Cannot pickle %s objects.", 
+        "O", (PyObject *)type);
 
-  Py_DECREF(name);
-  Py_DECREF(name_repr);
+finally:
+    Py_XDECREF(py_ob_id);
+    Py_XDECREF(__reduce__);
+    Py_XDECREF(t);
+   
+    return res;
+}
 
-  PyErr_SetString(PicklingError, error_str);
 
-  free(error_str);
-  
-  return NULL;
-}
+static int
+dump(Picklerobject *self, PyObject *args) {
+    static char stop = STOP;
 
+    if (save(self, args, 0) < 0)
+        return -1;
 
-static PyObject *
-Pickler_dump(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *junk;
-  static char stop = STOP;
+    if ((*self->write_func)(self, &stop, 1) < 0)
+        return -1;
 
-  UNLESS(PyArg_Parse(args, "O", &args))  return NULL;
+    if ((*self->write_func)(self, NULL, 0) < 0)
+        return -1;
 
-  UNLESS(junk = save(self, args))  return NULL;
-  Py_DECREF(junk);
+    return 0;
+}
 
-  if ((*self->write_func)(self, &stop, 1) == -1)
-    return NULL;
+static PyObject *
+Pickler_dump(Picklerobject *self, PyObject *args) {
+    PyObject *ob;
+
+    UNLESS(PyArg_ParseTuple(args, "O", &ob))
+        return NULL;
+
+    if (dump(self, ob) < 0)
+        return NULL;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 
 static PyObject *
-write(ARG(Picklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  char *ptr;
-  int size;
+dump_special(Picklerobject *self, PyObject *args) {
+    static char stop = STOP;
 
-  UNLESS(ptr = PyString_AsString(args))
-    return NULL;
+    PyObject *callable, *arg_tup, *state = NULL;
+    
+    UNLESS(PyArg_ParseTuple(args, "OO|O", &callable, &arg_tup, &state))
+        return NULL;
 
-  if ((size = PyString_Size(args)) == -1)
-    return NULL;
+    UNLESS(PyTuple_Check(arg_tup)) {
+        PyErr_SetString(PicklingError, "Second arg to dump_special must "
+            "be tuple");
+        return NULL;
+    }
 
-  if ((*self->write_func)(self, ptr, size) == -1)
-    return NULL;
+    if (save_reduce(self, callable, arg_tup, state, NULL) < 0)
+        return NULL;
+
+    if ((*self->write_func)(self, &stop, 1) < 0)
+        return NULL;
+
+    if ((*self->write_func)(self, NULL, 0) < 0)
+        return NULL;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 
 static struct PyMethodDef Pickler_methods[] = {
-  {"save",          (PyCFunction)save,          0, ""},
-  {"dump",          (PyCFunction)Pickler_dump,  0, ""},
-  {"save_none",     (PyCFunction)save_none,     0, ""},
-  {"save_int",      (PyCFunction)save_int,      0, ""},
-  {"save_long",     (PyCFunction)save_long,     0, ""},
-  {"save_float",    (PyCFunction)save_float,    0, ""},
-  {"save_string",   (PyCFunction)save_string,   0, ""},
-  {"save_tuple",    (PyCFunction)save_tuple,    0, ""},
-  {"save_list",     (PyCFunction)save_list,     0, ""},
-  {"save_dict",     (PyCFunction)save_dict,     0, ""},
-  {"save_inst",     (PyCFunction)save_inst,     0, ""},
-  {"save_class",    (PyCFunction)save_class,    0, ""},
-  {"write",         (PyCFunction)write,         0, ""},
-  {NULL,               NULL}           /* sentinel */
+  {"dump",          (PyCFunction)Pickler_dump,  1, ""},
+  {"dump_special",  (PyCFunction)dump_special,  1, ""},
+  {NULL,                NULL}           /* sentinel */
 };
 
 
 static Picklerobject *
-newPicklerobject(ARG(PyObject *, file), ARG(int, bin))
-    ARGDECL(PyObject *, file)
-    ARGDECL(int, bin)
-{
-  Picklerobject *self;
-  PyObject *memo = 0;
-
-  UNLESS(memo = PyDict_New())  goto err;
+newPicklerobject(PyObject *file, int bin) {
+    Picklerobject *self;
 
-  UNLESS(self = PyObject_NEW(Picklerobject, &Picklertype))  
-    goto err;
+    UNLESS(self = PyObject_NEW(Picklerobject, &Picklertype))
+        return NULL;
 
-  if (PyFile_Check(file))
-  {
-    self->fp = PyFile_AsFile(file);
-    self->write_func = write_file;
-    self->write = NULL;
-  }
-  else if (PycStringIO_OutputCheck(file))
-  {
     self->fp = NULL;
-    self->write_func = write_cStringIO;
     self->write = NULL;
-  }
-  else
-  {
-    PyObject *write; 
-
-    self->fp = NULL;
-    self->write_func = write_other;
-
-    UNLESS(write = PyObject_GetAttrString(file, "write"))
-      goto err;
-
-    self->write = write;
-  }
+    self->memo = NULL;
+    self->arg = NULL;
+    self->pers_func = NULL;
+    self->inst_pers_func = NULL;
+    self->write_buf = NULL;
+    self->bin = bin;
+    self->buf_size = 0;
+
+    Py_INCREF(file);
+    self->file = file;
+
+    UNLESS(self->memo = PyDict_New()) {
+       Py_XDECREF((PyObject *)self);
+       return NULL;
+    }
 
-  Py_INCREF(file);
+    if (PyFile_Check(file)) {
+        self->fp = PyFile_AsFile(file);
+        self->write_func = write_file;
+    }
+    else if (PycStringIO_OutputCheck(file)) {
+        self->write_func = write_cStringIO;
+    }
+    else {
+        self->write_func = write_other;
 
-  self->file  = file;
-  self->bin   = bin;
-  self->memo  = memo;
-  self->arg   = NULL;
-  self->pers_func = NULL;
+        UNLESS(self->write = PyObject_GetAttr(file, write_str))
+        {
+            PyErr_Clear();
+            PyErr_SetString(PyExc_TypeError, "argument must have 'write' "
+                "attribute");
+            Py_XDECREF((PyObject *)self);
+            return NULL;
+        }
 
-  return self;
+        UNLESS(self->write_buf = 
+            (char *)malloc(WRITE_BUF_SIZE * sizeof(char))) { 
+            PyErr_NoMemory();
+            Py_XDECREF((PyObject *)self);
+            return NULL;
+        }
+    }
 
-err:
-  Py_XDECREF((PyObject *)self);
-  Py_XDECREF(memo);
-  return NULL;
+    return self;
 }
 
 
 static PyObject *
-get_Pickler(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *file;
-  int bin = 0;
+get_Pickler(PyObject *self, PyObject *args) {
+    PyObject *file;
+    int bin = 0;
 
-  UNLESS(PyArg_ParseTuple(args, "O|i", &file, &bin))  return NULL;
-  return (PyObject *)newPicklerobject(file, bin);
+    UNLESS(PyArg_ParseTuple(args, "O|i", &file, &bin))  return NULL;
+    return (PyObject *)newPicklerobject(file, bin);
 }
 
 
 static void
-Pickler_dealloc(ARG(Picklerobject *, self))
-    ARGDECL(Picklerobject *, self)
-{
-  Py_XDECREF(self->write);
-  Py_XDECREF(self->memo);
-  Py_XDECREF(self->arg);
-  Py_XDECREF(self->file);
-  Py_XDECREF(self->pers_func);
-  PyMem_DEL(self);
+Pickler_dealloc(Picklerobject *self) {
+    Py_XDECREF(self->write);
+    Py_XDECREF(self->memo);
+    Py_XDECREF(self->arg);
+    Py_XDECREF(self->file);
+    Py_XDECREF(self->pers_func);
+    Py_XDECREF(self->inst_pers_func);
+
+    if (self->write_buf) {    
+        free(self->write_buf);
+    }
+
+    PyMem_DEL(self);
 }
 
 
 static PyObject *
-Pickler_getattr(ARG(Picklerobject *, self), ARG(char *, name))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(char *, name)
-{
-  if (!strcmp(name, "persistent_id"))
-  {
-    if (!self->pers_func)
-    {
-      PyErr_SetString(PyExc_NameError, name);
-      return NULL;
+Pickler_getattr(Picklerobject *self, char *name) {
+    if (strcmp(name, "persistent_id") == 0) {
+        if (!self->pers_func) {
+            PyErr_SetString(PyExc_AttributeError, name);
+            return NULL;
+        }
+
+        Py_INCREF(self->pers_func);
+        return self->pers_func;
     }
 
-    Py_INCREF(self->pers_func);
-    return self->pers_func;
-  }
+    if (strcmp(name, "memo") == 0) {
+        if (!self->memo) {
+            PyErr_SetString(PyExc_AttributeError, name);
+            return NULL;
+        }
 
-  if (!strcmp(name, "memo"))
-  {
-    if (!self->memo)
-    {
-      PyErr_SetString(PyExc_NameError, name);
-      return NULL;
+        Py_INCREF(self->memo);
+        return self->memo;
     }
 
-    Py_INCREF(self->memo);
-    return self->memo;
-  }
-
-  if (!strcmp(name, "PicklingError"))
-  {
-    Py_INCREF(PicklingError);
-    return PicklingError;
-  }
+    if (strcmp(name, "PicklingError") == 0) {
+        Py_INCREF(PicklingError);
+        return PicklingError;
+    }
   
-  return Py_FindMethod(Pickler_methods, (PyObject *)self, name);
+    return Py_FindMethod(Pickler_methods, (PyObject *)self, name);
 }
 
 
 int 
-Pickler_setattr(ARG(Picklerobject *, self), ARG(char *, name), ARG(PyObject *, value))
-    ARGDECL(Picklerobject *, self)
-    ARGDECL(char *, name)
-    ARGDECL(PyObject *, value)
-{
-  if (!strcmp(name, "persistent_id"))
-  {
-    Py_XDECREF(self->pers_func);
-    self->pers_func = value;
-    Py_INCREF(value);
-    return 0;
-  }
+Pickler_setattr(Picklerobject *self, char *name, PyObject *value) {
+    if (strcmp(name, "persistent_id") == 0) {
+        Py_XDECREF(self->pers_func);
+        self->pers_func = value;
+        Py_INCREF(value);
+        return 0;
+    }
 
-  return -1;
+    if (strcmp(name, "inst_persistent_id") == 0) {
+        Py_XDECREF(self->inst_pers_func);
+        self->inst_pers_func = value;
+        Py_INCREF(value);
+        return 0;
+    }
+
+    PyErr_SetString(PyExc_AttributeError, name);
+    return -1;
 }
 
 
 static char Picklertype__doc__[] = "";
 
-static PyTypeObject Picklertype = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,                              /*ob_size*/
-       "Pickler",                      /*tp_name*/
-       sizeof(Picklerobject),          /*tp_basicsize*/
-       0,                              /*tp_itemsize*/
-       /* methods */
-       (destructor)Pickler_dealloc,    /*tp_dealloc*/
-       (printfunc)0,           /*tp_print*/
-       (getattrfunc)Pickler_getattr,   /*tp_getattr*/
-       (setattrfunc)Pickler_setattr,   /*tp_setattr*/
-       (cmpfunc)0,             /*tp_compare*/
-       (reprfunc)0,            /*tp_repr*/
-       0,                      /*tp_as_number*/
-       0,              /*tp_as_sequence*/
-       0,              /*tp_as_mapping*/
-       (hashfunc)0,            /*tp_hash*/
-       (ternaryfunc)0,         /*tp_call*/
-       (reprfunc)0,            /*tp_str*/
-
-       /* Space for future expansion */
-       0L,0L,0L,0L,
-       Picklertype__doc__ /* Documentation string */
-};
-
-
-static PyObject *
-find_class(ARG(char *, module_name), ARG(char *, class_name))
-    ARGDECL(char *, module_name)
-    ARGDECL(char *, class_name)
-{
-  PyObject *import = 0, *class = 0, *py_module_name = 0, *py_class_name = 0,
-           *t = 0;
-  char *error_str;
-  int has_key;
+static PyTypeObject Picklertype_value() {
+  PyTypeObject Picklertype = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,                            /*ob_size*/
+    "Pickler",                    /*tp_name*/
+    sizeof(Picklerobject),                /*tp_basicsize*/
+    0,                            /*tp_itemsize*/
+    /* methods */
+    (destructor)Pickler_dealloc,  /*tp_dealloc*/
+    (printfunc)0,         /*tp_print*/
+    (getattrfunc)Pickler_getattr, /*tp_getattr*/
+    (setattrfunc)Pickler_setattr, /*tp_setattr*/
+    (cmpfunc)0,           /*tp_compare*/
+    (reprfunc)0,          /*tp_repr*/
+    0,                    /*tp_as_number*/
+    0,            /*tp_as_sequence*/
+    0,            /*tp_as_mapping*/
+    (hashfunc)0,          /*tp_hash*/
+    (ternaryfunc)0,               /*tp_call*/
+    (reprfunc)0,          /*tp_str*/
+
+    /* Space for future expansion */
+    0L,0L,0L,0L,
+    Picklertype__doc__ /* Documentation string */
+  };
+  return Picklertype;
+}
+
+
+PyObject *
+PyImport_ImportModuleNi(char *module_name)
+{
+    char *import_str;
+    int size, i;
+    PyObject *import;
+
+    static PyObject *eval_dict = 0;
+
+    size = strlen(module_name);
+    for (i = 0; i < size; i++) {
+        if (((module_name[i] < 'A') || (module_name[i] > 'z')) &&
+            (module_name[i] != '_')) {
+            PyErr_SetString(PyExc_ImportError, "module name contains "
+                "invalid characters.");
+            return NULL;
+        }
+    }
 
-  UNLESS(py_module_name = PyString_FromString(module_name))
-    return NULL;
+    UNLESS(import_str = 
+        (char *)malloc((strlen(module_name) + 15) * sizeof(char))) {
+        PyErr_NoMemory();
+        return NULL;
+    }
 
-  UNLESS(py_class_name = PyString_FromString(class_name))
-    goto err;
+    sprintf(import_str, "__import__('%s')", module_name);
 
-  UNLESS(t = PyTuple_New(2))
-    goto err;
+    UNLESS(eval_dict)
+        UNLESS(eval_dict = Py_BuildValue("{sO}", "__builtins__", builtins))
+            return NULL;
 
-  UNLESS(PyTuple_SET_ITEM((PyTupleObject *)t, 0, py_module_name))
-    goto err;
-  Py_INCREF(py_module_name);
-  
-  UNLESS(PyTuple_SET_ITEM((PyTupleObject *)t, 1, py_class_name))
-    goto err;
-  Py_INCREF(py_module_name);
-
-  if ((has_key = PyMapping_HasKey(class_map, t)) == -1)
-    goto err;
+    if (!(import = 
+        PyRun_String(import_str, eval_input, eval_dict, eval_dict))) {
+        free(import_str);
+        return NULL;
+    }
 
-  if (has_key)
-  {    
-    UNLESS(class = PyDict_GetItem(class_map, t))
-      goto err;
+    free(import_str);
 
-    Py_INCREF(class);
-  
-    Py_DECREF(py_module_name);
-    Py_DECREF(py_class_name);
-    Py_DECREF(t);
+    return import;
+}
 
-    return class;
-  }
 
-  if (!(import = PyImport_ImportModule(module_name)) ||
-      !(class = PyObject_GetAttrString(import, class_name)))
-  {
-    UNLESS(error_str = (char *)malloc((strlen(module_name) + 
-        strlen(class_name)  + 40) * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      goto err;
-    }
+static PyObject *
+find_class(PyObject *py_module_name, PyObject *py_class_name) {
+    PyObject *import = 0, *class = 0, *t = 0;
+    char *module_name, *class_name;
+    PyObject *res = NULL;
 
-    sprintf(error_str, "Failed to import class %s from module %s",
-        class_name, module_name);
+    static PyObject *eval_dict = 0;
 
-    PyErr_SetString(PyExc_SystemError, error_str);
-   
-    free(error_str);
-    goto err;
-  }
+    module_name = PyString_AS_STRING((PyStringObject *)py_module_name);
+    class_name  = PyString_AS_STRING((PyStringObject *)py_class_name);
 
-  if (class->ob_type == BuiltinFunctionType)
-  {
-    UNLESS(error_str = (char *)malloc((strlen(module_name) + 
-        strlen(class_name)  + 45) * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      goto err;
-    }
+    UNLESS(t = PyTuple_New(2))
+        goto finally;
 
-    sprintf(error_str, "Imported object %s from module %s is not a class",
-        class_name, module_name);
+    PyTuple_SET_ITEM((PyTupleObject *)t, 0, py_module_name);
+    Py_INCREF(py_module_name);
+  
+    PyTuple_SET_ITEM((PyTupleObject *)t, 1, py_class_name);
+    Py_INCREF(py_class_name);
 
-    PyErr_SetString(PyExc_SystemError, error_str);
-   
-    free(error_str);
-    goto err;
-  }
+    if (class = PyDict_GetItem(class_map, t)) {
+        res = class;
+       Py_INCREF(class);
+        goto finally;
+    }
 
-  if (PyDict_SetItem(class_map, t, class) == -1)
-    goto err;
+    PyErr_Clear();
 
-  Py_DECREF(t);
-  Py_DECREF(py_module_name);
-  Py_DECREF(py_class_name);
-  Py_DECREF(import);
+    if (!(import = PyImport_ImportModuleNi(module_name)) ||    
+        !(class = PyObject_GetAttr(import, py_class_name))) {
+        PyErr_Format(PyExc_SystemError, "Failed to import global %s "
+            "from module %s", "ss", class_name, module_name);
+        goto finally;
+    }  
 
-  return class;
+    if (PyDict_SetItem(class_map, t, class) < 0)
+        goto finally;
 
-err:
-  Py_XDECREF(import);
-  Py_XDECREF(class);
-  Py_XDECREF(t);
-  Py_XDECREF(py_module_name);
-  Py_XDECREF(py_class_name);
+    res = class;
+
+finally:
+    Py_XDECREF(import);
+    Py_XDECREF(t);
  
-  return NULL;
+    return res;
 }
 
 
-int
-marker(ARG(Unpicklerobject *, self))
-    ARGDECL(Unpicklerobject *, self)
-{
-  if (!self->num_marks)
-    return -1;
+static int
+marker(Unpicklerobject *self) {
+    if (self->num_marks < 1)
+    {
+        PyErr_SetString(UnpicklingError, "could not find MARK");
+        return -1;
+    }
 
-  return self->marks[--self->num_marks];
+    return self->marks[--self->num_marks];
 }
 
     
-static PyObject *
-load_none(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  if (PyList_Append(self->stack, Py_None) == -1)
-    return NULL;
+static int
+load_none(Unpicklerobject *self) {
+    if (PyList_Append(self->stack, Py_None) < 0)
+        return -1;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 }
 
 
-static PyObject *
-load_int(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_int = 0;
-  char *s, *endptr;
-  int len;
-  long l;
-
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+static int
+load_int(Unpicklerobject *self) {
+    PyObject *py_int = 0;
+    char *endptr, *s;
+    int len, res = -1;
+    long l;
+
+    if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
+    UNLESS(s=strndup(s,len)) return -1;
+
+    errno = 0;
+    l = strtol(s, &endptr, 0);
+
+    if (errno || (*endptr != '\n') || (endptr[1] != '\0')) {
+        /* Hm, maybe we've got something long.  Let's try reading
+          it as a Python long object. */
+        errno=0;
+        UNLESS(py_int=PyLong_FromString(s,&endptr,0)) goto finally;
+
+       if ((*endptr != '\n') || (endptr[1] != '\0')) {
+           PyErr_SetString(PyExc_ValueError,
+                           "could not convert string to int");
+           goto finally;
+       }
+    }
+    else {
+        UNLESS(py_int = PyInt_FromLong(l)) goto finally;
+    }
 
-  errno = 0;
-  l = strtol(s, &endptr, 0);
+    if (PyList_Append(self->stack, py_int) < 0) goto finally;
 
-  free(s);
-  
-  if (errno || strlen(endptr))
-  {
-    PyErr_SetString(PyExc_ValueError, "could not convert string to int");
-    goto err;
-  }
+    res = 0;
 
-  UNLESS(py_int = PyInt_FromLong(l))
-    goto err;
+finally:
+    free(s);
+    Py_XDECREF(py_int);
 
-  if (PyList_Append(self->stack, py_int) == -1)
-    goto err;
+    return res;
+}
 
-  Py_DECREF(py_int);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+static long 
+calc_binint(char *s, int  x) {
+    unsigned char c;
+    int i;
+    long l;
 
-err:
-  Py_XDECREF(py_int);
+    for (i = 0, l = 0L; i < x; i++) {
+        c = (unsigned char)s[i];
+        l |= (long)c << (i * 8);
+    }
 
-  return NULL;
+    return l;
 }
 
 
-static PyObject *
-load_binint(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_int = 0;
-  char *s;
-  unsigned char c;
-  long l;
-
-  UNLESS(s = (char *)malloc(4 * sizeof(char)))
-  {
-   PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
-
-  if ((*self->read_func)(self, &s, 4) == -1)
-  {
-    free(s);
-    return NULL;
-  }
-
-  c = (unsigned char)s[0];
-  l  = (long)c;
-  c = (unsigned char)s[1];
-  l |= (long)c << 8;
-  c = (unsigned char)s[2];
-  l |= (long)c << 16;
-  c = (unsigned char)s[3];
-  l |= (long)c << 24;
+static int
+load_binintx(Unpicklerobject *self, char *s, int  x) {
+    PyObject *py_int = 0;
+    long l;
 
-  free(s);
+    l = calc_binint(s, x);
 
-  UNLESS(py_int = PyInt_FromLong(l))
-    return NULL;
+    UNLESS(py_int = PyInt_FromLong(l))
+        return -1;
+    
+    if (PyList_Append(self->stack, py_int) < 0) {
+        Py_DECREF(py_int);
+        return -1;
+    }
 
-  if (PyList_Append(self->stack, py_int) == -1)
-  {
     Py_DECREF(py_int);
-    return NULL;
-  }
-
-  Py_DECREF(py_int);
     
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 }
 
 
-static PyObject *
-load_binint1(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_int = 0;
-  char *s;
-  unsigned char c;
-  long l;
+static int
+load_binint(Unpicklerobject *self) {
+    char *s;
 
-  UNLESS(s = (char *)malloc(3 * sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    if ((*self->read_func)(self, &s, 4) < 0)
+        return -1;
 
-  if ((*self->read_func)(self, &s, 3) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+    return load_binintx(self, s, 4);
+}
 
-  c = (unsigned char)s[0];
-  l  = (long)c;
-  c = (unsigned char)s[1];
-  l |= (long)c << 8;
-  c = (unsigned char)s[2];
-  l |= (long)c << 16;
 
-  free(s);
+static int
+load_binint1(Unpicklerobject *self) {
+    char *s;
 
-  UNLESS(py_int = PyInt_FromLong(l))
-    return NULL;
+    if ((*self->read_func)(self, &s, 1) < 0)
+        return -1;
 
-  if (PyList_Append(self->stack, py_int) == -1)
-  {
-    Py_DECREF(py_int);
-    return NULL;
-  }
+    return load_binintx(self, s, 1);
+}
 
-  Py_DECREF(py_int);
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+static int
+load_binint2(Unpicklerobject *self) {
+    char *s;
 
+    if ((*self->read_func)(self, &s, 2) < 0)
+        return -1;
 
-static PyObject *
-load_binint2(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_int = 0;
-  char *s;
-  unsigned char c;
-  long l;
+    return load_binintx(self, s, 2);
+}
+    
+static int
+load_long(Unpicklerobject *self) {
+    PyObject *l = 0;
+    char *end, *s;
+    int len, res = -1;
 
-  UNLESS(s = (char *)malloc(2 * sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    static PyObject *arg = 0;
 
-  if ((*self->read_func)(self, &s, 2) == -1)
-    return NULL;
+    if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
+    UNLESS(s=strndup(s,len)) return -1;
 
-  c = (unsigned char)s[0];
-  l  = (long)c;
-  c = (unsigned char)s[1];
-  l |= (long)c << 8;
+    UNLESS(l = PyLong_FromString(s, &end, 0))
+        goto finally;
 
-  free(s);
+    if (PyList_Append(self->stack, l) < 0)
+        goto finally;
 
-  UNLESS(py_int = PyInt_FromLong(l))
-    return NULL;
+    res = 0;
 
-  if (PyList_Append(self->stack, py_int) == -1)
-  {
-    Py_DECREF(py_int);
-    return NULL;
-  }
+finally:
+    free(s);
+    Py_XDECREF(l);
 
-  Py_DECREF(py_int);
-    
-  Py_INCREF(Py_None);
-  return Py_None;
+    return res;
 }
 
+static int
+load_float(Unpicklerobject *self) {
+    PyObject *py_float = 0;
+    char *endptr, *s;
+    int len, res = -1;
+    double d;
+
+    if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
+    UNLESS(s=strndup(s,len)) return -1;
+
+    errno = 0;
+    d = strtod(s, &endptr);
+
+    if (errno || (endptr[0] != '\n') || (endptr[1] != '\0')) {
+        PyErr_SetString(PyExc_ValueError, 
+        "could not convert string to float");
+        goto finally;
+    }
 
-static PyObject *
-load_binint3(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_int = 0;
-  char *s;
-  unsigned char c;
-  long l;
+    UNLESS(py_float = PyFloat_FromDouble(d))
+        goto finally;
 
-  UNLESS(s = (char *)malloc(sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    if (PyList_Append(self->stack, py_float) < 0)
+        goto finally;
 
-  if ((*self->read_func)(self, &s, 1) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+    res = 0;
 
-  c = (unsigned char)s[0];
-  l  = (long)c;
+finally:
+    free(s);
+    Py_XDECREF(py_float);
 
-  free(s);
+    return res;
+}
 
-  UNLESS(py_int = PyInt_FromLong(l))
-    return NULL;
+#ifdef FORMAT_1_3
+static int
+load_binfloat(Unpicklerobject *self) {
+    PyObject *py_float = 0;
+    int s, e, res = -1;
+    long fhi, flo;
+    double x;
+    char *p;
+
+    if ((*self->read_func)(self, &p, 8) < 0)
+        return -1;
 
-  if (PyList_Append(self->stack, py_int) == -1)
-  {
-    Py_DECREF(py_int);
-    return NULL;
-  }
+    /* First byte */
+    s = (*p>>7) & 1;
+    e = (*p & 0x7F) << 4;
+    p++;
 
-  Py_DECREF(py_int);
-    
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+    /* Second byte */
+    e |= (*p>>4) & 0xF;
+    fhi = (*p & 0xF) << 24;
+    p++;
 
+    /* Third byte */
+    fhi |= (*p & 0xFF) << 16;
+    p++;
 
-static PyObject *
-load_long(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_str = 0, *l = 0;
-  char *s;
-  int len;
+    /* Fourth byte */
+    fhi |= (*p & 0xFF) << 8;
+    p++;
 
-  static PyObject *arg;
+    /* Fifth byte */
+    fhi |= *p & 0xFF;
+    p++;
 
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+    /* Sixth byte */
+    flo = (*p & 0xFF) << 16;
+    p++;
 
-  UNLESS(py_str = PyString_FromStringAndSize(s, len))
-  {
-    free(s);
-    return NULL;
-  }
+    /* Seventh byte */
+    flo |= (*p & 0xFF) << 8;
+    p++;
 
-  free(s);
+    /* Eighth byte */
+    flo |= *p & 0xFF;
 
-  UNLESS(arg)
-  {
-    UNLESS(arg = Py_BuildValue("(Oi)", py_str, 0))
-      return NULL;
-  }
-  else
-  {
-    if (PyTuple_SetItem(arg, 0, py_str) == -1)
-      goto err;
-    Py_INCREF(py_str);
-  }
+    x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
+    x /= 268435456.0; /* 2**28 */
 
-  UNLESS(l = PyObject_CallObject(atol_func, arg))
-    goto err;
-  
-  if (PyList_Append(self->stack, l) == -1)
-    goto err;
+    /* XXX This sadly ignores Inf/NaN */
+    if (e == 0)
+        e = -1022;
+    else {
+        x += 1.0;
+        e -= 1023;
+    }
+    x = ldexp(x, e);
 
-  Py_DECREF(py_str);
-  Py_DECREF(l);
+    if (s)
+        x = -x;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    UNLESS(py_float = PyFloat_FromDouble(x))
+        goto finally;
 
-err:
-  Py_XDECREF(l);
-  Py_XDECREF(py_str);
+    if (PyList_Append(self->stack, py_float) < 0) 
+        goto finally;
 
-  return NULL;
-}
+    res = 0;
 
-static PyObject *
-load_float(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_float = 0;
-  char *s, *endptr;
-  int len;
-  double d;
+finally:
+    Py_XDECREF(py_float);
 
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+    return res;
+}
+#endif
 
-  errno = 0;
-  d = strtod(s, &endptr);
+static int
+load_string(Unpicklerobject *self) {
+    PyObject *str = 0;
+    int len, res = -1;
+    char *s;
 
-  free(s);
-  
-  if (errno || strlen(endptr))
-  {
-    PyErr_SetString(PyExc_ValueError, "could not convert string to long");
-    goto err;
-  }
+    static PyObject *eval_dict = 0;
 
-  UNLESS(py_float = PyFloat_FromDouble(d))
-    goto err;
+    if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
+    UNLESS(s=strndup(s,len)) return -1;
 
-  if (PyList_Append(self->stack, py_float) == -1)
-    goto err;
+    UNLESS(eval_dict)
+        UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__"))
+            goto finally;
 
-  Py_DECREF(py_float);
+    UNLESS(str = PyRun_String(s, eval_input, eval_dict, eval_dict))
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if (PyList_Append(self->stack, str) < 0)
+        goto finally;
 
-err:
-  Py_XDECREF(py_float);
+    res = 0;
 
-  return NULL;
-}
+finally:
+    free(s);
+    Py_XDECREF(str);
 
+    return res;
+} 
 
-static PyObject *
-load_string(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *str = 0;
-  char *s;
-  int len;
-  static PyObject *eval_dict = 0;
 
-  UNLESS(eval_dict)
-    UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__"))
-      return NULL;
+static int
+load_binstring(Unpicklerobject *self) {
+    PyObject *py_string = 0;
+    long l;
+    int res = -1;
+    char *s;
 
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+    if ((*self->read_func)(self, &s, 4) < 0)
+        goto finally;
 
-  UNLESS(str = PyRun_String(s, eval_input, eval_dict, eval_dict))
-  {
-    free(s);
-    goto err;
-  }
+    l = calc_binint(s, 4);
 
-  free(s);
+    if ((*self->read_func)(self, &s, l) < 0)
+        goto finally;
 
-  if (PyList_Append(self->stack, str) == -1)
-    goto err;
+    UNLESS(py_string = PyString_FromStringAndSize(s, l))
+        goto finally;
 
-  Py_DECREF(str);
+    if (PyList_Append(self->stack, py_string) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(str);
+finally:
+    Py_XDECREF(py_string);
 
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-load_binstring(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_string = 0;
-  char *s;
-  int len, i;
-
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+static int
+load_short_binstring(Unpicklerobject *self) {
+    PyObject *py_string = 0;
+    unsigned char l;  
+    int res = -1;
+    char *s;
 
-  i = atoi(s);
+    if ((*self->read_func)(self, &s, 1) < 0)
+        return -1;
 
-  if (i > len)
-  {
-    free(s);
+    l = (unsigned char)s[0];
 
-    UNLESS(s = (char *)malloc(i * sizeof(char)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
-  }
+    if ((*self->read_func)(self, &s, l) < 0)
+        goto finally;
 
-  if ((*self->read_func)(self, &s, i) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+    UNLESS(py_string = PyString_FromStringAndSize(s, l))
+        goto finally;
 
-  UNLESS(py_string = PyString_FromStringAndSize(s, i))
-  {
-    free(s);
-    return NULL;
-  }
+    if (PyList_Append(self->stack, py_string) < 0)
+        goto finally;
 
-  free(s);
+    res = 0;
 
-  if (PyList_Append(self->stack, py_string) == -1)
-    goto err;
+finally:
+    Py_XDECREF(py_string);
 
-  Py_DECREF(py_string);
+    return res;
+} 
 
-  Py_INCREF(Py_None);
-  return Py_None;
 
-err:
-  Py_XDECREF(py_string);
+static int
+load_tuple(Unpicklerobject *self) {
+    PyObject *tup = 0, *slice = 0, *list = 0;
+    int i, j, res = -1;
 
-  return NULL;
-}
+    if ((i = marker(self)) < 0)
+        goto finally;
 
+    if ((j = PyList_Size(self->stack)) < 0)  
+        goto finally;
 
-static PyObject *
-load_short_binstring(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_string = 0;
-  char *s;
-  unsigned char l;  
+    UNLESS(slice = PyList_GetSlice(self->stack, i, j))
+        goto finally;
+  
+    UNLESS(tup = PySequence_Tuple(slice))
+        goto finally;
 
+    UNLESS(list = PyList_New(1))
+        goto finally;
 
-  UNLESS(s = (char *)malloc(sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    Py_INCREF(tup);
+    if (PyList_SetItem(list, 0, tup) < 0)
+        goto finally;
 
-  if ((*self->read_func)(self, &s, 1) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+    if (PyList_SetSlice(self->stack, i, j, list) < 0)
+        goto finally;
 
-  l = (unsigned char)s[0];
+    res = 0;
 
-  if (l > 1)
-  {
-    free(s);
+finally:
+    Py_XDECREF(tup);
+    Py_XDECREF(list);
+    Py_XDECREF(slice);
 
-    UNLESS(s = (char *)malloc(l * sizeof(char)))
-    {  
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
-  }
+    return res;
+}
 
-  if ((*self->read_func)(self, &s, l) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+static int
+load_empty_tuple(Unpicklerobject *self) {
+    PyObject *tup = 0;
+    int res;
 
-  UNLESS(py_string = PyString_FromStringAndSize(s, l))
-  {
-    free(s);
-    return NULL;
-  }
+    UNLESS(tup=PyTuple_New(0)) return -1;
+    res=PyList_Append(self->stack, tup);
+    Py_DECREF(tup);
+    return res;
+}
 
-  free(s);
+static int
+load_empty_list(Unpicklerobject *self) {
+    PyObject *list = 0;
+    int res;
 
-  if (PyList_Append(self->stack, py_string) == -1)
-  {
-    Py_DECREF(py_string);
-    return NULL;
-  }
+    UNLESS(list=PyList_New(0)) return -1;
+    res=PyList_Append(self->stack, list);
+    Py_DECREF(list);
+    return res;
+}
 
-  Py_DECREF(py_string);
+static int
+load_empty_dict(Unpicklerobject *self) {
+    PyObject *dict = 0;
+    int res;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    UNLESS(dict=PyDict_New()) return -1;
+    res=PyList_Append(self->stack, dict);
+    Py_DECREF(dict);
+    return res;
 }
 
 
-static PyObject *
-load_tuple(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *tup = 0, *slice = 0, *list = 0;
-  int i, j;
+static int
+load_list(Unpicklerobject *self) {
+    PyObject *list = 0, *slice = 0;
+    int i, j, l, res = -1;
 
-  if ((i = marker(self)) == -1)
-    return NULL;
+    if ((i = marker(self)) < 0)
+        goto finally;
 
-  if ((j = PyList_Size(self->stack)) == -1)  
-    goto err;
+    if ((j = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-  UNLESS(slice = PyList_GetSlice(self->stack, i, j))
-    goto err;
-  
-  UNLESS(tup = PySequence_Tuple(slice))
-    goto err;
+    UNLESS(slice = PyList_GetSlice(self->stack, i, j))
+        goto finally;
 
-  UNLESS(list = PyList_New(1))
-    goto err;
+    if((l=PyList_Size(slice)) < 0)
+        goto finally;
 
-  if (PyList_SetItem(list, 0, tup) == -1)
-    goto err;
+    if(l) {
+      UNLESS(list = PyList_New(1))
+        goto finally;
 
-  Py_INCREF(tup);
+      Py_INCREF(slice);
+      if (PyList_SetItem(list, 0, slice) < 0)
+        goto finally;
+      
+      if (PyList_SetSlice(self->stack, i, j, list) < 0)
+        goto finally;
+    } else {
+      if(PyList_Append(self->stack,slice) < 0)
+       goto finally;
+    }
 
-  if (PyList_SetSlice(self->stack, i, j, list) == -1)
-    goto err;
+    res = 0;
 
-  Py_DECREF(tup);
-  Py_DECREF(list);
-  Py_DECREF(slice);
+finally:
+    Py_XDECREF(list);
+    Py_XDECREF(slice);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    return res;
+}
 
-err:
-  Py_XDECREF(tup);
-  Py_XDECREF(list);
-  Py_XDECREF(slice);
+static int
+load_dict(Unpicklerobject *self) {
+    PyObject *list = 0, *dict = 0, *key = 0, *value = 0;
+    int i, j, k, res = -1;
 
-  return NULL;
-}
+    if ((i = marker(self)) < 0)
+        goto finally;
 
+    if ((j = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-static PyObject *
-load_list(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *list = 0, *slice = 0;
-  int i, j;
+    UNLESS(dict = PyDict_New())
+        goto finally;
 
-  if ((i = marker(self)) == -1)
-    return NULL;
+    for (k = i; k < j; k += 2) {
+        UNLESS(key = PyList_GET_ITEM((PyListObject *)self->stack, k))
+            goto finally;
 
-  if ((j = PyList_Size(self->stack)) == -1)
-    goto err;
+        UNLESS(value = PyList_GET_ITEM((PyListObject *)self->stack, k + 1))
+            goto finally;
 
-  UNLESS(slice = PyList_GetSlice(self->stack, i, j))
-    goto err;
+        if (PyDict_SetItem(dict, key, value) < 0)
+            goto finally;
+    }
 
-  UNLESS(list = PyList_New(1))
-    goto err;
+    if(j) {
 
-  if (PyList_SetItem(list, 0, slice) == -1)
-    goto err;
-  Py_INCREF(slice);
+      UNLESS(list = PyList_New(1))
+        goto finally;
 
-  if (PyList_SetSlice(self->stack, i, j, list) == -1)
-    goto err;
+      Py_INCREF(dict);
+      if (PyList_SetItem(list, 0, dict) < 0)
+        goto finally;
 
-  Py_DECREF(list);
-  Py_DECREF(slice);
+      if (PyList_SetSlice(self->stack, i, j, list) < 0)
+        goto finally;
+    }
+    else 
+      if(PyList_Append(self->stack, dict) < 0)
+       goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(list);
-  Py_XDECREF(slice);
+finally:
+    Py_XDECREF(dict);
+    Py_XDECREF(list);
 
-  return NULL;
+    return res;
 }
 
-
 static PyObject *
-load_dict(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
+Instance_New(PyObject *cls, PyObject *args)
 {
-  PyObject *list = 0, *dict = 0, *key = 0, *value = 0;
-  int i, j, k;
-
-  if ((i = marker(self)) == -1)
-    return NULL;
-
-  if ((j = PyList_Size(self->stack)) == -1)
-    goto err;
+  int has_key;
+  PyObject *safe=0, *r=0;
 
-  UNLESS(dict = PyDict_New())
+  if (PyClass_Check(cls))
+    if(r=PyInstance_New(cls, args, NULL)) return r;
+    else goto err;
+       
+  
+  if ((has_key = cPickle_PyMapping_HasKey(safe_constructors, cls)) < 0)
     goto err;
+    
+  if (!has_key)
+    if(!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) ||
+       !PyObject_IsTrue(safe)) {
+      PyErr_Format(UnpicklingError, "%s is not safe for unpickling", "O", cls);
+      Py_XDECREF(safe);
+      return NULL;
+  }
 
-  for (k = i; k < j; k += 2)
+  if(r=PyObject_CallObject(cls, args)) return r;
+err:
   {
-    UNLESS(key = PyList_GET_ITEM((PyListObject *)self->stack, k))
-      goto err;
-
-    UNLESS(value = PyList_GET_ITEM((PyListObject *)self->stack, k + 1))
-      goto err;
+    PyObject *tp, *v, *tb;
 
-    if (PyDict_SetItem(dict, key, value) == -1)
-      goto err;
+    PyErr_Fetch(&tp, &v, &tb);
+    if(r=Py_BuildValue("OOO",v,cls,args))
+      {
+       Py_XDECREF(v);
+       v=r;
+      }
+    PyErr_Restore(tp,v,tb);
   }
+  return NULL;
+}
+  
 
-  UNLESS(list = PyList_New(1))
-    goto err;
-
-  if (PyList_SetItem(list, 0, dict) == -1)
-    goto err;
-  Py_INCREF(dict);
+static int
+load_obj(Unpicklerobject *self) {
+    PyObject *class = 0, *slice = 0, *tup = 0, *obj = 0;
+    int i, len, res = -1;
 
-  if (PyList_SetSlice(self->stack, i, j, list) == -1)
-    goto err;
+    if ((i = marker(self)) < 0)
+        goto finally;
 
-  Py_DECREF(list);
-  Py_DECREF(dict);
+    class = PyList_GET_ITEM((PyListObject *)self->stack, i);
+    Py_INCREF(class);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-err:
-  Py_XDECREF(dict);
-  Py_XDECREF(list);
+    UNLESS(slice = PyList_GetSlice(self->stack, i + 1, len))
+        goto finally;
 
-  return NULL;
-}
+    UNLESS(tup = PySequence_Tuple(slice))
+        goto finally;
 
+    UNLESS(obj = Instance_New(class, tup))
+        goto finally;
 
-static PyObject *
-load_obj(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *class = 0, *slice = 0, *tup = 0, *obj = 0;
-  long i;
-  int len;
+    if (DEL_LIST_SLICE(self->stack, i, len) < 0)
+        goto finally;
 
-  if ((i = marker(self)) == -1)
-    return NULL;
+    if (PyList_Append(self->stack, obj) < 0)
+        goto finally;
+  
+    res = 0;
 
-  class = PyList_GET_ITEM((PyListObject *)self->stack, i);
-  Py_INCREF(class);
+finally:
+    
+    Py_XDECREF(class);
+    Py_XDECREF(slice);
+    Py_XDECREF(tup);
+    Py_XDECREF(obj);
 
-  if ((len = PyList_Size(self->stack)) == -1)
-    goto err;
+    return res;
+}
 
-  UNLESS(slice = PyList_GetSlice(self->stack, i + 1, len))
-    goto err;
 
-  UNLESS(tup = PySequence_Tuple(slice))
-    goto err;
+static int
+load_inst(Unpicklerobject *self) {
+    PyObject *arg_tup = 0, *arg_slice = 0, *class = 0, *obj = 0,
+             *module_name = 0, *class_name = 0;
+    int i, j, len, res = -1;
+    char *s;
 
-  if (DEL_LIST_SLICE(self->stack, i, len) == -1)
-    goto err;
+    if ((i = marker(self)) < 0)
+        goto finally;
 
-  UNLESS(obj = PyInstance_New(class, tup, NULL))
-    goto err;
+    if ((j = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-  if (PyList_Append(self->stack, obj) == -1)
-    goto err;
+    UNLESS(arg_slice = PyList_GetSlice(self->stack, i, j))
+        goto finally;
 
-  Py_DECREF(class);
-  Py_DECREF(slice);
-  Py_DECREF(tup);
-  Py_DECREF(obj);
+    UNLESS(arg_tup = PySequence_Tuple(arg_slice))
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if (DEL_LIST_SLICE(self->stack, i, j) < 0)
+        goto finally;
 
-err:
-  Py_XDECREF(class);
-  Py_XDECREF(slice);
-  Py_XDECREF(tup);
-  Py_XDECREF(obj);
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-  return NULL;
-}
+    UNLESS(module_name = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
 
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-static PyObject *
-load_inst(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *arg_tup = 0, *arg_slice = 0, *class = 0, *obj = 0;
-  int i, j;
-  char *s, *module_name, *class_name;
+    UNLESS(class_name = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
 
-  if ((i = marker(self)) == -1)
-    return NULL;
+    UNLESS(class = find_class(module_name, class_name))
+        goto finally;
 
-  if ((j = PyList_Size(self->stack)) == -1)
-    goto err;
+    UNLESS(obj = Instance_New(class, arg_tup))
+        goto finally;
 
-  UNLESS(arg_slice = PyList_GetSlice(self->stack, i, j))
-    goto err;
+    if (PyList_Append(self->stack, obj) < 0)
+        goto finally;
 
-  UNLESS(arg_tup = PySequence_Tuple(arg_slice))
-    goto err;
+    res = 0;
 
-  if (DEL_LIST_SLICE(self->stack, i, j) == -1)
-    goto err;
+finally:
+    Py_XDECREF(class);
+    Py_XDECREF(arg_slice);
+    Py_XDECREF(arg_tup);
+    Py_XDECREF(obj);
+    Py_XDECREF(module_name);
+    Py_XDECREF(class_name);
 
-  if ((*self->readline_func)(self, &s) == -1)
-    goto err;
+    return res;
+}
 
-  module_name = s;
 
-  if ((*self->readline_func)(self, &s) == -1)
-  {
-    free(module_name);
-    goto err;
-  }
+static int
+load_global(Unpicklerobject *self) {
+    PyObject *class = 0, *module_name = 0, *class_name = 0;
+    int res = -1, len;
+    char *s;
 
-  class_name = s;
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-  UNLESS(class = find_class(module_name, class_name))
-  {
-    free(module_name);
-    free(class_name);
-    goto err;
-  }
+    UNLESS(module_name = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
 
-  free(module_name);
-  free(class_name);
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-  UNLESS(obj = PyInstance_New(class, arg_tup, NULL))
-    goto err;
+    UNLESS(class_name = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
 
-  if (PyList_Append(self->stack, obj) == -1)
-    goto err;
+    UNLESS(class = find_class(module_name, class_name))
+        goto finally;
 
-  Py_DECREF(arg_slice);
-  Py_DECREF(arg_tup);
-  Py_DECREF(class);
-  Py_DECREF(obj);
+    if (PyList_Append(self->stack, class) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(arg_slice);
-  Py_XDECREF(arg_tup);
-  Py_XDECREF(class);
-  Py_XDECREF(obj);
+finally:
+    Py_XDECREF(class);
+    Py_XDECREF(module_name);
+    Py_XDECREF(class_name);
 
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-load_class(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *class = 0;
-  char *s, *module_name, *class_name;
+static int
+load_persid(Unpicklerobject *self) {
+    PyObject *pid = 0, *pers_load_val = 0;
+    int len, res = -1;
+    char *s;
+
+    if (self->pers_func) {
+        if ((len = (*self->readline_func)(self, &s)) < 0)
+            goto finally;
+  
+        UNLESS(pid = PyString_FromStringAndSize(s, len - 1))
+           goto finally;
 
-  if ((*self->readline_func)(self, &s) == -1)
-    return NULL;
+        UNLESS(self->arg)
+            UNLESS(self->arg = PyTuple_New(1))
+                goto finally;
 
-  module_name = s;
+        Py_INCREF(pid);
+        if (PyTuple_SetItem(self->arg, 0, pid) < 0)
+            goto finally;
+      
+        UNLESS(pers_load_val = 
+            PyObject_CallObject(self->pers_func, self->arg))
+            goto finally;
 
-  if ((*self->readline_func)(self, &s) == -1)
-  {
-    free(module_name);
-    return NULL;
-  }
+        if (PyList_Append(self->stack, pers_load_val) < 0)
+            goto finally;
+    }
 
-  class_name = s;
+    res = 0;
 
-  UNLESS(class = find_class(module_name, class_name))
-  {
-    free(module_name);
-    free(class_name);
-    return NULL;
-  }
+finally:
+    Py_XDECREF(pid);
+    Py_XDECREF(pers_load_val);
 
-  free(module_name);
-  free(class_name);
+    return res;
+}
 
-  if (PyList_Append(self->stack, class) == -1)
-    goto err;
 
-  Py_DECREF(class);
+static int
+load_binpersid(Unpicklerobject *self) {
+    PyObject *pid = 0, *pers_load_val = 0;
+    int len, res = -1;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if (self->pers_func) {
+        if ((len = PyList_Size(self->stack)) < 0)
+            goto finally;
 
-err:
-  Py_XDECREF(class);
+        pid = PyList_GET_ITEM((PyListObject *)self->stack, len - 1);
+        Py_INCREF(pid);
+        if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0)
+            goto finally;
 
-  return NULL;
-}
+        UNLESS(self->arg)
+            UNLESS(self->arg = PyTuple_New(1))
+                goto finally;
 
+        Py_INCREF(pid);
+        if (PyTuple_SetItem(self->arg, 0, pid) < 0)
+            goto finally;
 
-static PyObject *
-load_persid(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *pid = 0, *pers_load_val = 0;
-  char *s;
-  int len;
+        UNLESS(pers_load_val = 
+            PyObject_CallObject(self->pers_func, self->arg))
+            goto finally;
 
-  if (self->pers_func)
-  {
-    if ((len = (*self->readline_func)(self, &s)) == -1)
-      return NULL;
-  
-    UNLESS(pid = PyString_FromStringAndSize(s, len))
-    { 
-      free(s);
-      return NULL;
+        if (PyList_Append(self->stack, pers_load_val) < 0)
+            goto finally;
     }
 
-    free(s);
+    res = 0;
 
-    UNLESS(self->arg)
-      UNLESS(self->arg = PyTuple_New(1))
-        goto err;
+finally:
+    Py_XDECREF(pid);
+    Py_XDECREF(pers_load_val);
 
-    if (PyTuple_SetItem(self->arg, 0, pid) == -1)
-      goto err;
-    Py_INCREF(pid);
-      
-    UNLESS(pers_load_val = PyObject_CallObject(self->pers_func, self->arg))
-      goto err;
+    return res;
+}
 
-    if (PyList_Append(self->stack, pers_load_val) == -1)
-      goto err;
 
-    Py_DECREF(pid);
-    Py_DECREF(pers_load_val);
-  
-    Py_INCREF(Py_None);
-    return Py_None;
-  }
+static int
+load_pop(Unpicklerobject *self) {
+    int len;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    if ((len = PyList_Size(self->stack)) < 0)  
+        return -1;
 
-err:
-  Py_XDECREF(pid);
-  Py_XDECREF(pers_load_val);
+    if ((self->num_marks > 0) && 
+        (self->marks[self->num_marks - 1] == len))
+        self->num_marks--;
+    else if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0)  
+        return -1;
 
-  return NULL;
+    return 0;
 }
 
 
-static PyObject *
-load_pop(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  int len;
+static int
+load_pop_mark(Unpicklerobject *self) {
+    int i, len;
 
-  if ((len = PyList_Size(self->stack)) == -1)  
-    return NULL;
+    if ((i = marker(self)) < 0)
+        return -1;
 
-  if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1)  
-    return NULL;
+    if ((len = PyList_Size(self->stack)) < 0)
+        return -1;
+
+    if (DEL_LIST_SLICE(self->stack, i, len) < 0)
+        return -1;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 }
 
 
-static PyObject *
-load_dup(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *last;
-  int len;
+static int
+load_dup(Unpicklerobject *self) {
+    PyObject *last;
+    int len;
 
-  if ((len = PyList_Size(self->stack)) == -1)
-    return NULL;
+    if ((len = PyList_Size(self->stack)) < 0)
+        return -1;
   
-  UNLESS(last = PyList_GetItem(self->stack, len - 1))  
-    return NULL;
+    UNLESS(last = PyList_GetItem(self->stack, len - 1))  
+        return -1;
 
-  if (PyList_Append(self->stack, last) == -1)
-    return NULL;
+    if (PyList_Append(self->stack, last) < 0)
+        return -1;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 }
 
 
-static PyObject *
-load_get(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_str = 0, *value = 0;
-  char *s;
-  int len;
-
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+static int
+load_get(Unpicklerobject *self) {
+    PyObject *py_str = 0, *value = 0;
+    int len, res = -1;
+    char *s;
 
-  UNLESS(py_str = PyString_FromStringAndSize(s, len))
-  {
-    free(s);
-    return NULL;
-  }
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-  free(s);
+    UNLESS(py_str = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
   
-  UNLESS(value = PyDict_GetItem(self->memo, py_str))  
-    goto err;
-
-  if (PyList_Append(self->stack, value) == -1)
-    goto err;
+    UNLESS(value = PyDict_GetItem(self->memo, py_str))  
+        goto finally;
 
-  Py_DECREF(py_str);
+    if (PyList_Append(self->stack, value) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(py_str);
+finally:
+    Py_XDECREF(py_str);
 
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-load_binget(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_key = 0, *value = 0;
-  char *s;
-  unsigned char key;
-
-  UNLESS(s = (char *)malloc(sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
-
-  if ((*self->read_func)(self, &s, 1) == -1)
-  {
-    free(s);
-    return NULL;
-  }
+static int
+load_binget(Unpicklerobject *self) {
+    PyObject *py_key = 0, *value = 0;
+    unsigned char key;
+    int res = -1;
+    char *s;
 
-  key = (unsigned char)s[0];
-  free(s);
+    if ((*self->read_func)(self, &s, 1) < 0)
+        goto finally;
 
-  UNLESS(py_key = PyInt_FromLong((long)key))
-    return NULL;
+    key = (unsigned char)s[0];
 
-  UNLESS(value = PyDict_GetItem(self->memo, py_key))  
-    goto err;
+    UNLESS(py_key = PyInt_FromLong((long)key))
+        goto finally;
 
-  if (PyList_Append(self->stack, value) == -1)
-    return NULL;
+    UNLESS(value = PyDict_GetItem(self->memo, py_key))  
+        goto finally;
 
-  Py_DECREF(py_key);
+    if (PyList_Append(self->stack, value) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(py_key);
+finally:
+    Py_XDECREF(py_key);
 
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-load_put(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_str = 0, *value = 0;
-  int len;
-  char *s;
+static int
+load_long_binget(Unpicklerobject *self) {
+    PyObject *py_key = 0, *value = 0;
+    unsigned char c, *s;
+    long key;
+    int res = -1;
 
-  if ((len = (*self->readline_func)(self, &s)) == -1)
-    return NULL;
+    if ((*self->read_func)(self, &s, 4) < 0)
+        goto finally;
 
-  UNLESS(py_str = PyString_FromStringAndSize(s, len))
-  {
-    free(s);
-    return NULL;
-  }
+    c = (unsigned char)s[0];
+    key = (long)c;
+    c = (unsigned char)s[1];
+    key |= (long)c << 8;
+    c = (unsigned char)s[2];
+    key |= (long)c << 16;
+    c = (unsigned char)s[3];
+    key |= (long)c << 24;
 
-  free(s);
+    UNLESS(py_key = PyInt_FromLong(key))
+        goto finally;
 
-  if ((len = PyList_Size(self->stack)) == -1)
-    goto err;
+    UNLESS(value = PyDict_GetItem(self->memo, py_key))  
+        goto finally;
 
-  UNLESS(value = PyList_GetItem(self->stack, len - 1))  
-    goto err;
+    if (PyList_Append(self->stack, value) < 0)
+        goto finally;
 
-  if (PyDict_SetItem(self->memo, py_str, value) == -1)  
-    goto err;
+    res = 0;
 
-  Py_DECREF(py_str);
+finally:
+    Py_XDECREF(py_key);
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    return res;
+}
 
-err:
-  Py_XDECREF(py_str);
 
-  return NULL;
-}
+static int
+load_put(Unpicklerobject *self) {
+    PyObject *py_str = 0, *value = 0;
+    int len, res = -1;
+    char *s;
 
+    if ((len = (*self->readline_func)(self, &s)) < 0)
+        goto finally;
 
-static PyObject *
-load_binput(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *py_key = 0, *value = 0;
-  char *s;
-  unsigned char key;
-  int len;
+    UNLESS(py_str = PyString_FromStringAndSize(s, len - 1))
+        goto finally;
 
-  UNLESS(s = (char *)malloc(sizeof(char)))
-  {
-    PyErr_SetString(PyExc_MemoryError, "out of memory");
-    return NULL;
-  }
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-  if ((*self->read_func)(self, &s, 1) == -1)
-    return NULL;
+    UNLESS(value = PyList_GetItem(self->stack, len - 1))  
+        goto finally;
 
-  key = (unsigned char)s[0];
+    if (PyDict_SetItem(self->memo, py_str, value) < 0)  
+        goto finally;
 
-  free(s);
+    res = 0;
 
-  UNLESS(py_key = PyInt_FromLong((long)key))
-    return NULL;
+finally:
+    Py_XDECREF(py_str);
 
-  if ((len = PyList_Size(self->stack)) == -1)
-    goto err;
+    return res;
+}
 
-  UNLESS(value = PyList_GetItem(self->stack, len - 1))  
-    goto err;
 
-  if (PyDict_SetItem(self->memo, py_key, value) == -1)  
-    goto err;
+static int
+load_binput(Unpicklerobject *self) {
+    PyObject *py_key = 0, *value = 0;
+    unsigned char key, *s;
+    int len, res = -1;
 
-  Py_DECREF(py_key);
+    if ((*self->read_func)(self, &s, 1) < 0)
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    key = (unsigned char)s[0];
 
-err:
-  Py_XDECREF(py_key);
+    UNLESS(py_key = PyInt_FromLong((long)key))
+        goto finally;
 
-  return NULL;
-}
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
+    UNLESS(value = PyList_GetItem(self->stack, len - 1))  
+        goto finally;
 
-static PyObject *
-load_append(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *value = 0, *list = 0;
-  int len;
-  static PyObject *append_str = 0;
+    if (PyDict_SetItem(self->memo, py_key, value) < 0)  
+        goto finally;
 
-  UNLESS(append_str)
-    UNLESS(append_str = PyString_FromString("append"))
-      return NULL;
+    res = 0;
 
-  if ((len = PyList_Size(self->stack)) == -1)  
-    return NULL;
+finally:
+    Py_XDECREF(py_key);
 
-  UNLESS(value = PyList_GetItem(self->stack, len - 1))  
-    return NULL;
-  Py_INCREF(value);
+    return res;
+}
 
-  if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1)  
-    goto err;
 
-  UNLESS(list = PyList_GetItem(self->stack, len - 2))  
-    goto err;
+static int
+load_long_binput(Unpicklerobject *self) {
+    PyObject *py_key = 0, *value = 0;
+    long key;
+    unsigned char c, *s;
+    int len, res = -1;
 
-  if (PyList_Check(list))
-  {
-    if (PyList_Append(list, value) == -1)
-      goto err;
-  }
-  else
-  {
-    PyObject *append_method, *junk;
+    if ((*self->read_func)(self, &s, 4) < 0)
+        goto finally;
 
-    UNLESS(append_method = PyObject_GetAttr(list, append_str))
-      return NULL;
+    c = (unsigned char)s[0];
+    key = (long)c;
+    c = (unsigned char)s[1];
+    key |= (long)c << 8;
+    c = (unsigned char)s[2];
+    key |= (long)c << 16;
+    c = (unsigned char)s[3];
+    key |= (long)c << 24;
 
-    UNLESS(self->arg)
-      UNLESS(self->arg = PyTuple_New(1))
-      {
-        Py_DECREF(append_method);
-        goto err;
-      }
+    UNLESS(py_key = PyInt_FromLong(key))
+        goto finally;
 
-    if (PyTuple_SetItem(self->arg, 0, value) == -1)
-    {
-      Py_DECREF(append_method);
-      goto err;
-    }
-    Py_INCREF(value);
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-    UNLESS(junk = PyObject_CallObject(append_method, self->arg))
-    {
-      Py_DECREF(append_method);
-      goto err;
-    }
-    Py_DECREF(junk);
+    UNLESS(value = PyList_GetItem(self->stack, len - 1))  
+        goto finally;
 
-    Py_DECREF(append_method);
-  }
+    if (PyDict_SetItem(self->memo, py_key, value) < 0)  
+        goto finally;
 
-  Py_DECREF(value);
+    res = 0;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+finally:
+    Py_XDECREF(py_key);
 
-err:
-  Py_XDECREF(value);
-  return NULL;
+    return res;
 }
 
 
-static PyObject *
-load_setitem(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *value = 0, *key = 0, *dict = 0;
-  int len;
+static int 
+do_append(Unpicklerobject *self, int  x) {
+    PyObject *value = 0, *list = 0, *append_method = 0;
+    int len, i;
 
-  if ((len = PyList_Size(self->stack)) == -1)  
-    return NULL;
+    if ((len = PyList_Size(self->stack)) < 0)  
+        return -1;
 
-  UNLESS(value = PyList_GetItem(self->stack, len - 1))
-    return NULL;
-  Py_INCREF(value);
+    UNLESS(list = PyList_GetItem(self->stack, x - 1))  
+        goto err;
 
-  UNLESS(key = PyList_GetItem(self->stack, len - 2))  
-    goto err;
-  Py_INCREF(key);
+    if (PyList_Check(list)) {
+        PyObject *slice = 0;
+        int list_len;
+       
+        UNLESS(slice = PyList_GetSlice(self->stack, x, len))
+            return -1;
+  
+        list_len = PyList_Size(list);
+        if (PyList_SetSlice(list, list_len, list_len, slice) < 0) {
+            Py_DECREF(slice);
+            return -1;
+        }
 
-  if (DEL_LIST_SLICE(self->stack, len - 2, len) == -1)  
-    goto err;
+        Py_DECREF(slice);
+    }
+    else {
+
+        UNLESS(append_method = PyObject_GetAttr(list, append_str))
+            return -1;
+         
+        for (i = x; i < len; i++) {
+           PyObject *junk;
+
+            UNLESS(value = PyList_GetItem(self->stack, i))  
+                return -1;
+
+           UNLESS(self->arg)
+             UNLESS(self->arg = PyTuple_New(1)) 
+               goto err;
+           
+           Py_INCREF(value);
+           if (PyTuple_SetItem(self->arg, 0, value) < 0) 
+             goto err;
+           
+           UNLESS(junk = PyObject_CallObject(append_method, self->arg)) 
+             goto err;
+           Py_DECREF(junk);
+        }
+    }
 
-  UNLESS(dict = PyList_GetItem(self->stack, len - 3))  
-    goto err;
+    if (DEL_LIST_SLICE(self->stack, x, len) < 0)  
+        goto err;
 
-  if (PyObject_SetItem(dict, key, value) == -1)  
-    goto err;
+    Py_XDECREF(append_method);
 
-  Py_DECREF(value);
-  Py_DECREF(key);
-  
-  Py_INCREF(Py_None);
-  return Py_None;
+    return 0;
 
 err:
-  Py_XDECREF(value);
-  Py_XDECREF(key);
+    Py_XDECREF(append_method);
+    return -1;
+}
 
-  return NULL;
+    
+static int
+load_append(Unpicklerobject *self) {
+    return do_append(self, PyList_Size(self->stack) - 1);
 }
 
 
-static PyObject *
-load_build(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *value = 0, *inst = 0, *instdict = 0, *d_key = 0, *d_value = 0, 
-           *junk = 0;
-  static PyObject *py_string__dict__;
-  int len, i;
+static int
+load_appends(Unpicklerobject *self) {
+    return do_append(self, marker(self));
+}
 
-  UNLESS(py_string__dict__)
-    UNLESS(py_string__dict__ = PyString_FromString("__dict__"))
-      return NULL;
 
-  if ((len = PyList_Size(self->stack)) == -1)
-    goto err;
+static int
+do_setitems(Unpicklerobject *self, int  x) {
+    PyObject *value = 0, *key = 0, *dict = 0;
+    int len, i, res = -1;
 
-  UNLESS(value = PyList_GetItem(self->stack, len - 1))
-    goto err; 
-  Py_INCREF(value);
+    if ((len = PyList_Size(self->stack)) < 0)  
+        goto finally;
 
-  if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1)
-    goto err;
+    UNLESS(dict = PyList_GetItem(self->stack, x - 1))
+        goto finally;
 
-  UNLESS(inst = PyList_GetItem(self->stack, len - 2))
-    goto err;
+    for (i = x; i < len; i += 2) {
+        UNLESS(key = PyList_GetItem(self->stack, i))  
+            goto finally;
 
-  UNLESS(PyObject_HasAttrString(inst, "__setstate__"))
-  {
-    UNLESS(instdict = PyObject_GetAttr(inst, py_string__dict__))
-      goto err;
+        UNLESS(value = PyList_GetItem(self->stack, i + 1))
+            goto finally;
 
-    i = 0;
-    while (PyDict_Next(value, &i, &d_key, &d_value))
-    {
-      if (PyObject_SetItem(instdict, d_key, d_value) == -1)
-        goto err;
+        if (PyObject_SetItem(dict, key, value) < 0)  
+            goto finally;
     }
-  }
-  else
-  {
-    UNLESS(junk = PyObject_CallMethod(inst, "__setstate__", "O", value))
-      goto err;
-    Py_DECREF(junk);
-  }
 
-  Py_DECREF(value);
-  Py_XDECREF(instdict);
+    if (DEL_LIST_SLICE(self->stack, x, len) < 0)  
+        goto finally;
 
-  Py_INCREF(Py_None);
-  return Py_None;
+    res = 0;
 
-err:
-  Py_XDECREF(value);
-  Py_XDECREF(instdict);
-  
-  return NULL;
+finally:
+
+    return res;
 }
 
 
-static PyObject *
-load_mark(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  int len;
-  
-  if ((len = PyList_Size(self->stack)) == -1)
-    return NULL;
+static int
+load_setitem(Unpicklerobject *self) {
+    return do_setitems(self, PyList_Size(self->stack) - 2);
+}
 
-  if (!self->num_marks)
-  {
-    UNLESS(self->marks = (int *)malloc(20 * sizeof(int)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
-    self->marks_size = 20;
-  }
-  else if ((self->num_marks + 1) > self->marks_size)
-  {
-    UNLESS(self->marks = (int *)realloc(self->marks, (self->marks_size + 20) * sizeof(int)))
-    {
-      PyErr_SetString(PyExc_MemoryError, "out of memory");
-      return NULL;
-    }
 
-    self->marks_size += 20;
-  }
+static int
+load_setitems(Unpicklerobject *self) {
+    return do_setitems(self, marker(self));
+}
 
-  self->marks[self->num_marks++] = len;
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+static int
+load_build(Unpicklerobject *self) {
+    PyObject *value = 0, *inst = 0, *instdict = 0, *d_key = 0, *d_value = 0, 
+             *junk = 0, *__setstate__ = 0;
+    int len, i, res = -1;
 
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-static PyObject *  
-load_eof(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyErr_SetNone(PyExc_EOFError);
-  return NULL;
-}
+    UNLESS(value = PyList_GetItem(self->stack, len - 1))
+        goto finally; 
+    Py_INCREF(value);
 
+    if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0)
+        goto finally;
 
-static PyObject *
-Unpickler_load(ARG(Unpicklerobject *, self), ARG(PyObject *, args))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *stack = 0, *key = 0, *junk = 0, *err = 0,
-           *val = 0, *str = 0, *key_repr = 0;
-  char c;
-  char *c_str;
-  int len;
+    UNLESS(inst = PyList_GetItem(self->stack, len - 2))
+        goto finally;
 
-  c_str=&c;
+    UNLESS(__setstate__ = PyObject_GetAttr(inst, __setstate___str)) 
+    {
+        PyErr_Clear();
 
-  UNLESS(stack = PyList_New(0))
-    goto err;
+        UNLESS(instdict = PyObject_GetAttr(inst, __dict___str))
+            goto finally;
 
-  self->stack = stack;
-  self->num_marks = 0;
+        i = 0;
+        while (PyDict_Next(value, &i, &d_key, &d_value)) {
+            if (PyObject_SetItem(instdict, d_key, d_value) < 0)
+                goto finally;
+        }
+    }
+    else {
+        UNLESS(self->arg)
+            UNLESS(self->arg = PyTuple_New(1))
+                goto finally;
 
-  while (1)
-  {
-    if ((*self->read_func)(self, &c_str, 1) == -1)
-      break;
+        Py_INCREF(value);
+        if (PyTuple_SetItem(self->arg, 0, value) < 0)
+            goto finally;
 
-    switch (c_str[0])
-    {
-      case NONE:
-        UNLESS(junk = load_none(self, NULL))
-          break;
-        continue;
-
-      case BININT:
-        UNLESS(junk = load_binint(self, NULL))
-          break;
-        continue;
-
-      case BININT1:
-        UNLESS(junk = load_binint1(self, NULL))
-          break;
-        continue;
-
-      case BININT2:
-        UNLESS(junk = load_binint2(self, NULL))
-          break;
-        continue;
-
-      case BININT3:
-        UNLESS(junk = load_binint3(self, NULL))
-          break;
-        continue;
-      case INT:
-        UNLESS(junk = load_int(self, NULL))
-          break;
-        continue;
-      
-      case LONG:
-        UNLESS(junk = load_long(self, NULL))
-          break;
-        continue;
-
-      case FLOAT:
-        UNLESS(junk = load_float(self, NULL))
-          break;
-        continue;
-
-      case BINSTRING:
-        UNLESS(junk = load_binstring(self, NULL))
-          break;
-        continue;
-
-      case SHORT_BINSTRING:
-        UNLESS(junk = load_short_binstring(self, NULL))
-          break;
-        continue;
-
-      case STRING:
-        UNLESS(junk = load_string(self, NULL))
-          break;
+        UNLESS(junk = PyObject_CallObject(__setstate__, self->arg))
+            goto finally;
         Py_DECREF(junk);
-        continue;
+    }
 
-      case TUPLE:
-        UNLESS(junk = load_tuple(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    res = 0;
 
-      case LIST:
-        UNLESS(junk = load_list(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+finally:
+  Py_XDECREF(value);
+  Py_XDECREF(instdict);
+  Py_XDECREF(__setstate__);
+  
+  return res;
+}
 
-      case DICT:
-        UNLESS(junk = load_dict(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
 
-      case OBJ:
-        UNLESS(junk = load_obj(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+static int
+load_mark(Unpicklerobject *self) {
+    int len;
 
-      case INST:
-        UNLESS(junk = load_inst(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    if ((len = PyList_Size(self->stack)) < 0)
+        return -1;
 
-      case CLASS:
-        UNLESS(junk = load_class(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    if (!self->marks_size) {
+        self->marks_size = 20;
+        UNLESS(self->marks = (int *)malloc(self->marks_size * sizeof(int))) {
+            PyErr_NoMemory();
+            return -1;
+        } 
+    }
+    else if ((self->num_marks + 1) >= self->marks_size) {
+        UNLESS(self->marks = (int *)realloc(self->marks,
+            (self->marks_size + 20) * sizeof(int))) {
+            PyErr_NoMemory();
+            return -1;
+        }
 
-      case APPEND:
-        UNLESS(junk = load_append(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+        self->marks_size += 20;
+    }
 
-      case BUILD:
-        UNLESS(junk = load_build(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
-  
-      case DUP:
-        UNLESS(junk = load_dup(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    self->marks[self->num_marks++] = len;
 
-      case BINGET:
-        UNLESS(junk = load_binget(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    return 0;
+}
 
-      case GET:
-        UNLESS(junk = load_get(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+static int
+load_reduce(Unpicklerobject *self) {
+    PyObject *callable = 0, *arg_tup = 0, *ob = 0;
+    int len, res = -1;
 
-      case MARK:
-        UNLESS(junk = load_mark(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    if ((len = PyList_Size(self->stack)) < 0)
+        goto finally;
 
-      case BINPUT:
-        UNLESS(junk = load_binput(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    UNLESS(arg_tup = PyList_GetItem(self->stack, len - 1))
+        goto finally;
 
-      case PUT:
-        UNLESS(junk = load_put(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    UNLESS(callable = PyList_GetItem(self->stack, len - 2))
+        goto finally;
 
-      case POP:
-        UNLESS(junk = load_pop(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    UNLESS(ob = Instance_New(callable, arg_tup))
+        goto finally;
 
-      case SETITEM:
-        UNLESS(junk = load_setitem(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    if (PyList_Append(self->stack, ob) < 0)
+        goto finally;
 
-      case STOP:
-        break;
+    if (DEL_LIST_SLICE(self->stack, len - 2, len) < 0)
+        goto finally;
 
-      case PERSID:
-        UNLESS(junk = load_persid(self, NULL))
-          break;
-        Py_DECREF(junk);
-        continue;
+    res = 0;
 
-      default: 
-        UNLESS(key = PyString_FromStringAndSize(c_str, 1))
-          return NULL;
-  
-        UNLESS(key_repr = PyObject_Repr(key))
-          return NULL;
-        
-        UNLESS(str = PyString_FromStringAndSize(NULL, 19 + PyString_Size(key_repr)))
-          return NULL;
+finally:
+    Py_XDECREF(ob);
+
+    return res;
+}
+    
+static PyObject *
+load(Unpicklerobject *self)
+{
+    PyObject *stack = 0, *err = 0, *exc = 0, *val = 0, *tb = 0;
+    int len;
+    char *s;
 
-        sprintf(PyString_AS_STRING((PyStringObject *)str), 
-            "invalid load key, \%s.", PyString_AS_STRING((PyStringObject *)key_repr));
+    UNLESS(stack = PyList_New(0))
+        goto err;
 
-        PyErr_SetObject(UnpicklingError, str);
+    self->stack = stack;
+    self->num_marks = 0;
+
+    while (1) {
+        if ((*self->read_func)(self, &s, 1) < 0)
+            break;
+
+        switch (s[0]) {
+            case NONE:
+                if (load_none(self) < 0)
+                    break;
+                continue;
+
+            case BININT:
+                 if (load_binint(self) < 0)
+                     break;
+                 continue;
+
+            case BININT1:
+                if (load_binint1(self) < 0)
+                    break;
+                continue;
+
+            case BININT2:
+                if (load_binint2(self) < 0)
+                    break;
+                continue;
+
+            case INT:
+                if (load_int(self) < 0)
+                    break;
+                continue;
+
+            case LONG:
+                if (load_long(self) < 0)
+                    break;
+                continue;
+
+            case FLOAT:
+                if (load_float(self) < 0)
+                    break;
+                continue;
+
+#ifdef FORMAT_1_3
+            case BINFLOAT:
+                if (load_binfloat(self) < 0)
+                    break;
+                continue;
+#endif
 
-        Py_DECREF(str);
-        Py_DECREF(key);
-        Py_DECREF(key_repr);
+            case BINSTRING:
+                if (load_binstring(self) < 0)
+                    break;
+                continue;
+
+            case SHORT_BINSTRING:
+                if (load_short_binstring(self) < 0)
+                    break;
+                continue;
+
+            case STRING:
+                if (load_string(self) < 0)
+                    break;
+                continue;
+
+            case EMPTY_TUPLE:
+                if (load_empty_tuple(self) < 0)
+                    break;
+                continue;
+
+            case TUPLE:
+                if (load_tuple(self) < 0)
+                    break;
+                continue;
+
+            case EMPTY_LIST:
+                if (load_empty_list(self) < 0)
+                    break;
+                continue;
+
+            case LIST:
+                if (load_list(self) < 0)
+                    break;
+                continue;
+
+            case EMPTY_DICT:
+                if (load_empty_dict(self) < 0)
+                    break;
+                continue;
+
+            case DICT:
+                if (load_dict(self) < 0)
+                    break;
+                continue;
+
+            case OBJ:
+                if (load_obj(self) < 0)
+                    break;
+                continue;
+
+            case INST:
+                if (load_inst(self) < 0)
+                    break;
+                continue;
+
+            case GLOBAL:
+                if (load_global(self) < 0)
+                    break;
+                continue;
+
+            case APPEND:
+                if (load_append(self) < 0)
+                    break;
+                continue;
+
+            case APPENDS:
+                if (load_appends(self) < 0)
+                    break;
+                continue;
+   
+            case BUILD:
+                if (load_build(self) < 0)
+                    break;
+                continue;
+  
+            case DUP:
+                if (load_dup(self) < 0)
+                    break;
+                continue;
+
+            case BINGET:
+                if (load_binget(self) < 0)
+                    break;
+                continue;
+
+            case LONG_BINGET:
+                if (load_long_binget(self) < 0)
+                    break;
+                continue;
+         
+            case GET:
+                if (load_get(self) < 0)
+                    break;
+                continue;
+
+            case MARK:
+                if (load_mark(self) < 0)
+                    break;
+                continue;
+
+            case BINPUT:
+                if (load_binput(self) < 0)
+                    break;
+                continue;
+
+            case LONG_BINPUT:
+                if (load_long_binput(self) < 0)
+                    break;
+                continue;
+         
+            case PUT:
+                if (load_put(self) < 0)
+                    break;
+                continue;
+
+            case POP:
+                if (load_pop(self) < 0)
+                    break;
+                continue;
+
+            case POP_MARK:
+                if (load_pop_mark(self) < 0)
+                    break;
+                continue;
+
+            case SETITEM:
+                if (load_setitem(self) < 0)
+                    break;
+                continue;
+
+            case SETITEMS:
+                if (load_setitems(self) < 0)
+                    break;
+                continue;
+
+            case STOP:
+                break;
+
+            case PERSID:
+                if (load_persid(self) < 0)
+                    break;
+                continue;
+
+            case BINPERSID:
+                if (load_binpersid(self) < 0)
+                    break;
+                continue;
+
+            case REDUCE:
+                if (load_reduce(self) < 0)
+                    break;
+                continue;
+
+            default: 
+                PyErr_Format(UnpicklingError, "invalid load key, '%s'.", 
+                    "c", s[0]);
+                goto err;
+        }
 
-        return NULL;
+        break;
     }
 
-    break;
-  }
-
-  if ((err = PyErr_Occurred()) == PyExc_EOFError)
-  {
-    return load_eof(self, NULL);
-  }    
+    if ((err = PyErr_Occurred()) == PyExc_EOFError) {
+        PyErr_SetNone(PyExc_EOFError);
+        goto err;
+    }    
 
-  if (err)    
-    return NULL;
+    if (err) goto err;
 
-  if ((len = PyList_Size(self->stack)) == -1)  
-    return NULL;
+    if ((len = PyList_Size(stack)) < 0) goto err;
 
-  UNLESS(val = PyList_GetItem(self->stack, len - 1))  
-    return NULL;
-  Py_INCREF(val);
+    UNLESS(val = PyList_GetItem(stack, len - 1)) goto err;
+    Py_INCREF(val);
 
-  if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1)
-  {
-    Py_DECREF(val);
-    return NULL;
-  }
+    Py_DECREF(stack);
 
-  return val;
+    self->stack=NULL;
+    return val;
 
 err:
-  Py_XDECREF(stack);
+    self->stack=NULL;
+    Py_XDECREF(stack);
 
-  return NULL;
+    return NULL;
 }
+    
 
+static PyObject *
+Unpickler_load(Unpicklerobject *self, PyObject *args) {
+    UNLESS(PyArg_ParseTuple(args, "")) 
+        return NULL;
 
-static struct PyMethodDef Unpickler_methods[] = 
-{
-  {"load",         (PyCFunction)Unpickler_load,   0, ""},
-  {"load_none",    (PyCFunction)load_none,        0, ""},
-  {"load_int",     (PyCFunction)load_int,         0, ""},
-  {"load_long",    (PyCFunction)load_long,        0, ""},
-  {"load_float",   (PyCFunction)load_float,       0, ""},
-  {"load_string",  (PyCFunction)load_string,      0, ""},
-  {"load_tuple",   (PyCFunction)load_tuple,       0, ""},
-  {"load_list",    (PyCFunction)load_list,        0, ""},
-  {"load_dict",    (PyCFunction)load_dict,        0, ""},
-  {"load_inst",    (PyCFunction)load_inst,        0, ""},
-  {"load_class",   (PyCFunction)load_class,       0, ""},
-  {"load_persid",  (PyCFunction)load_persid,      0, ""},
-  {"load_pop",     (PyCFunction)load_pop,         0, ""},
-  {"load_dup",     (PyCFunction)load_dup,         0, ""},
-  {"load_get",     (PyCFunction)load_get,         0, ""},
-  {"load_put",     (PyCFunction)load_put,         0, ""},
-  {"load_append",  (PyCFunction)load_append,      0, ""},
-  {"load_setitem", (PyCFunction)load_setitem,     0, ""},
-  {"load_build",   (PyCFunction)load_build,       0, ""},
-  {"load_mark",    (PyCFunction)load_mark,        0, ""},
-  {"load_eof",     (PyCFunction)load_eof,         0, ""},
-  {NULL,               NULL}           /* sentinel */
+    return load(self);
+}
+
+
+static struct PyMethodDef Unpickler_methods[] = {
+  {"load",         (PyCFunction)Unpickler_load,   1, ""},
+  {NULL,              NULL}           /* sentinel */
 };
 
 
 static Unpicklerobject *
-newUnpicklerobject(ARG(PyObject *, f))
-    ARGDECL(PyObject *, f)
-{
-  Unpicklerobject *self;
-  PyObject *memo = 0;
-       
-  UNLESS(memo = PyDict_New())
-    goto err;
+newUnpicklerobject(PyObject *f) {
+    Unpicklerobject *self;
 
-  UNLESS(self = PyObject_NEW(Unpicklerobject, &Unpicklertype))  goto err;
+    UNLESS(self = PyObject_NEW(Unpicklerobject, &Unpicklertype))
+        return NULL;
 
-  if (PyFile_Check(f))
-  {
-    self->fp = PyFile_AsFile(f);
-    self->read_func = read_file;
-    self->readline_func = readline_file;
-    self->read = NULL;
-    self->readline = NULL;
-  }
-  else if (PycStringIO_InputCheck(f))
-  {
-    self->fp = NULL;
-    self->read_func = read_cStringIO;
-    self->readline_func = readline_cStringIO;
+    self->file = NULL;
+    self->arg = NULL;
+    self->stack = NULL;
+    self->pers_func = NULL;
+    self->last_string = NULL;
+    self->marks = NULL;
+    self->num_marks = 0;
+    self->marks_size = 0;
+    self->buf_size = 0;
     self->read = NULL;
-    self->readline = NULL;
-  }
-  else
-  {
-    PyObject *readline, *read;
+    self->readline = NULL;    
 
-    self->fp = NULL;
-    self->read_func = read_other;
-    self->readline_func = readline_other;
+    UNLESS(self->memo = PyDict_New()) {
+       Py_XDECREF((PyObject *)self);
+       return NULL;
+    }
 
-    UNLESS(readline = PyObject_GetAttrString(f, "readline"))
-      goto err;
+    Py_INCREF(f);
+    self->file = f;
 
-    UNLESS(read = PyObject_GetAttrString(f, "read"))
-    {
-      Py_DECREF(readline);
-      goto err;
+    /* Set read, readline based on type of f */
+    if (PyFile_Check(f)) {
+        self->fp = PyFile_AsFile(f);
+        self->read_func = read_file;
+        self->readline_func = readline_file;
     }
-  
-    self->read = read; 
-    self->readline = readline;
-  }
-
-  Py_INCREF(f);
-  
-  self->file = f;
-  self->memo   = memo;
-  self->arg    = NULL;
-  self->stack  = NULL;
-  self->pers_func = NULL;
-  self->marks = NULL;
-  self->num_marks = 0;
-  self->marks_size = 0;
+    else if (PycStringIO_InputCheck(f)) {
+        self->fp = NULL;
+        self->read_func = read_cStringIO;
+        self->readline_func = readline_cStringIO;
+    }
+    else {
 
-  return self;
+        self->fp = NULL;
+        self->read_func = read_other;
+        self->readline_func = readline_other;
 
-err:
-  Py_XDECREF(memo);
-  Py_XDECREF((PyObject *)self);
+        UNLESS((self->readline = PyObject_GetAttr(f, readline_str)) &&
+            (self->read = PyObject_GetAttr(f, read_str))) 
+        {
+            PyErr_Clear();
+            PyErr_SetString( PyExc_TypeError, "argument must have 'read' and "
+                "'readline' attributes" );
+            Py_XDECREF((PyObject *)self);
+            return NULL;
+        }
+    }
 
-  return NULL;
+    return self;
 }
 
 
 static PyObject *
-get_Unpickler(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *file;
-
-  UNLESS(PyArg_Parse(args, "O", &file))  return NULL;
-  return (PyObject *)newUnpicklerobject(file);
+get_Unpickler(PyObject *self, PyObject *args) {
+    PyObject *file;
+  
+    UNLESS(PyArg_ParseTuple(args, "O", &file))
+        return NULL;
+    return (PyObject *)newUnpicklerobject(file);
 }
 
 
 static void
-Unpickler_dealloc(ARG(Unpicklerobject *, self))
-    ARGDECL(Unpicklerobject *, self)
-{
-  Py_XDECREF(self->readline);
-  Py_XDECREF(self->read);
-  Py_XDECREF(self->file);
-  Py_XDECREF(self->memo);
-  Py_XDECREF(self->stack);
-  Py_XDECREF(self->pers_func);
-  Py_XDECREF(self->arg);
-  free(self->marks);
-  PyMem_DEL(self);
+Unpickler_dealloc(Unpicklerobject *self) {
+    Py_XDECREF(self->readline);
+    Py_XDECREF(self->read);
+    Py_XDECREF(self->file);
+    Py_XDECREF(self->memo);
+    Py_XDECREF(self->stack);
+    Py_XDECREF(self->pers_func);
+    Py_XDECREF(self->arg);
+    Py_XDECREF(self->last_string);
+
+    if (self->marks) {
+        free(self->marks);
+    }
+
+    if (self->buf_size) {
+        free(self->buf);
+    }
+    
+    PyMem_DEL(self);
 }
 
 
 static PyObject *
-Unpickler_getattr(ARG(Unpicklerobject *, self), ARG(char *, name))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char *, name)
-{
-  if (!strcmp(name, "persistent_load"))
-  {
-    if (!self->pers_func)
-    {
-      PyErr_SetString(PyExc_NameError, name);
-      return NULL;
+Unpickler_getattr(Unpicklerobject *self, char *name) {
+    if (!strcmp(name, "persistent_load")) {
+        if (!self->pers_func) {
+            PyErr_SetString(PyExc_AttributeError, name);
+            return NULL;
+        }
+
+        Py_INCREF(self->pers_func);
+        return self->pers_func;
     }
 
-    Py_INCREF(self->pers_func);
-    return self->pers_func;
-  }
+    if (!strcmp(name, "memo")) {
+        if (!self->memo) {
+            PyErr_SetString(PyExc_AttributeError, name);
+            return NULL;
+        }
 
-  if (!strcmp(name, "memo"))
-  {
-    if (!self->memo)
-    {
-      PyErr_SetString(PyExc_NameError, name);
-      return NULL;
+        Py_INCREF(self->memo);
+        return self->memo;
     }
 
-    Py_INCREF(self->memo);
-    return self->memo;
-  }
+    if (!strcmp(name, "stack")) {
+        if (!self->stack) {
+            PyErr_SetString(PyExc_AttributeError, name);
+            return NULL;
+        }
 
-  if (!strcmp(name, "UnpicklingError"))
-  {
-    Py_INCREF(UnpicklingError);
-    return UnpicklingError;
-  }
+        Py_INCREF(self->stack);
+        return self->stack;
+    }
+
+    if (!strcmp(name, "UnpicklingError")) {
+        Py_INCREF(UnpicklingError);
+        return UnpicklingError;
+    }
 
-  return Py_FindMethod(Unpickler_methods, (PyObject *)self, name);
+    return Py_FindMethod(Unpickler_methods, (PyObject *)self, name);
 }
 
 
 static int
-Unpickler_setattr(ARG(Unpicklerobject *, self), ARG(char *, name), ARG(PyObject *, value))
-    ARGDECL(Unpicklerobject *, self)
-    ARGDECL(char *, name)
-    ARGDECL(PyObject *, value)
-{
-  if (!strcmp(name, "persistent_load"))
-  {
-    Py_XDECREF(self->pers_func);
-    self->pers_func = value;
-    Py_INCREF(value);
-    return 0;
-  }
+Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) {
+    if (!strcmp(name, "persistent_load")) {
+        Py_XDECREF(self->pers_func);
+        self->pers_func = value;
+        Py_INCREF(value);
+        return 0;
+    }
 
-  return -1;
+    PyErr_SetString(PyExc_AttributeError, name);
+    return -1;
 }
 
 
 static PyObject *
-dump(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *ob, *file, *ret_val;
-  Picklerobject *pickler;
-  int bin = 0;
+cpm_dump(PyObject *self, PyObject *args) {
+    PyObject *ob, *file, *res = NULL;
+    Picklerobject *pickler = 0;
+    int bin = 0;
 
-  UNLESS(PyArg_ParseTuple(args, "OO|i", &ob, &file, &bin))
-    return NULL;
+    UNLESS(PyArg_ParseTuple(args, "OO|i", &ob, &file, &bin))
+        goto finally;
 
-  UNLESS(pickler = newPicklerobject(file, bin))
-    return NULL;
+    UNLESS(pickler = newPicklerobject(file, bin))
+        goto finally;
 
-  UNLESS(ret_val = Pickler_dump(pickler, ob))
-  {
-    Pickler_dealloc(pickler);
-    return NULL;
-  }
+    if (dump(pickler, ob) < 0)
+        goto finally;
+
+    Py_INCREF(Py_None);
+    res = Py_None;
 
-  Pickler_dealloc(pickler);
+finally:
+    Py_XDECREF(pickler);
 
-  return ret_val;
+    return res;
 }
 
 
 static PyObject *
-dumps(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *ob, *file, *pickle_str;
-  Picklerobject *pickler;
-  int bin = 0;
+cpm_dumps(PyObject *self, PyObject *args) {
+    PyObject *ob, *file = 0, *res = NULL;
+    Picklerobject *pickler = 0;
+    int bin = 0;
 
-  UNLESS(PyArg_ParseTuple(args, "O|i", &ob, &bin))
-    return NULL;
-
-  UNLESS(file = (*PycStringIO_NewOutput)(128))
-    return NULL;
+    UNLESS(PyArg_ParseTuple(args, "O|i", &ob, &bin))
+        goto finally;
 
-  UNLESS(pickler = newPicklerobject(file, bin))
-  {
-    Py_DECREF(file);
-    return NULL;
-  }
+    UNLESS(file = PycStringIO->NewOutput(128))
+        goto finally;
 
-  UNLESS(Pickler_dump(pickler, ob))
-  {
-    Pickler_dealloc(pickler);
-    Py_DECREF(file);
-    return NULL;
-  }
+    UNLESS(pickler = newPicklerobject(file, bin))
+        goto finally;
 
-  Pickler_dealloc(pickler);
+    if (dump(pickler, ob) < 0)
+        goto finally;
 
-  UNLESS(pickle_str = (*PycStringIO_cgetvalue)((PyObject *)file))
-  {
-    Py_DECREF(file);
-    return NULL;
-  }
+    res = PycStringIO->cgetvalue(file);
 
-  Py_DECREF(file);
+finally:
+    Py_XDECREF(pickler);
+    Py_XDECREF(file);
 
-  return pickle_str;
+    return res;
 }  
   
 
 static PyObject *
-cpm_load(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  Unpicklerobject *unpickler;
-  PyObject *load_result;
+cpm_load(PyObject *self, PyObject *args) {
+    Unpicklerobject *unpickler = 0;
+    PyObject *ob, *res = NULL;
 
-  UNLESS(PyArg_Parse(args, "O", &args))
-    return NULL;
+    UNLESS(PyArg_ParseTuple(args, "O", &ob))
+        goto finally;
 
-  UNLESS(unpickler = newUnpicklerobject(args))
-    return NULL;
+    UNLESS(unpickler = newUnpicklerobject(ob))
+        goto finally;
 
-  UNLESS(load_result = Unpickler_load(unpickler, NULL))
-  {
-    Unpickler_dealloc(unpickler);
-    return NULL;
-  }
+    res = load(unpickler);
 
-  Py_DECREF(unpickler);
+finally:
+    Py_XDECREF(unpickler);
 
-  return load_result;
+    return res;
 }
 
 
 static PyObject *
-loads(ARG(PyObject *, self), ARG(PyObject *, args))
-    ARGDECL(PyObject *, self)
-    ARGDECL(PyObject *, args)
-{
-  PyObject *file, *load_result;
-  Unpicklerobject *unpickler;
+cpm_loads(PyObject *self, PyObject *args) {
+    PyObject *ob, *file = 0, *res = NULL;
+    Unpicklerobject *unpickler = 0;
 
-  UNLESS(PyArg_Parse(args, "O", &args))
-    return NULL;
+    UNLESS(PyArg_ParseTuple(args, "O", &ob))
+        goto finally;
 
-  UNLESS(file = (*PycStringIO_NewInput)(args))
-    return NULL;
+    UNLESS(file = PycStringIO->NewInput(ob))
+        goto finally;
   
-  UNLESS(unpickler = newUnpicklerobject(file))
-  {
-    Py_DECREF(file);
-    return NULL;
-  }
+    UNLESS(unpickler = newUnpicklerobject(file))
+        goto finally;
 
-  UNLESS(load_result = Unpickler_load(unpickler, NULL))
-  {
-    Unpickler_dealloc(unpickler);
-    Py_DECREF(file);
-    return NULL;
-  }
+    res = load(unpickler);
 
-  Py_DECREF(file);
-  Unpickler_dealloc(unpickler);
+finally:
+    Py_XDECREF(file);
+    Py_XDECREF(unpickler);
 
-  return load_result;
+    return res;
 }
 
 
 static char Unpicklertype__doc__[] = "";
 
-static PyTypeObject Unpicklertype = 
-{
-  PyObject_HEAD_INIT(&PyType_Type)
-  0,                           /*ob_size*/
-  "Unpickler",                 /*tp_name*/
-  sizeof(Unpicklerobject),             /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  /* methods */
-  (destructor)Unpickler_dealloc,       /*tp_dealloc*/
-  (printfunc)0,                /*tp_print*/
-  (getattrfunc)Unpickler_getattr,      /*tp_getattr*/
-  (setattrfunc)Unpickler_setattr,      /*tp_setattr*/
-  (cmpfunc)0,          /*tp_compare*/
-  (reprfunc)0,         /*tp_repr*/
-  0,                   /*tp_as_number*/
-  0,           /*tp_as_sequence*/
-  0,           /*tp_as_mapping*/
-  (hashfunc)0,         /*tp_hash*/
-  (ternaryfunc)0,              /*tp_call*/
-  (reprfunc)0,         /*tp_str*/
-
-  /* Space for future expansion */
-  0L,0L,0L,0L,
-  Unpicklertype__doc__ /* Documentation string */
-};
-
-
-static struct PyMethodDef cPickle_methods[] =
-{
-  {"dump",         (PyCFunction)dump,             1, ""},
-  {"dumps",        (PyCFunction)dumps,            1, ""},
-  {"load",         (PyCFunction)cpm_load,         0, ""},
-  {"loads",        (PyCFunction)loads,            0, ""},
+static PyTypeObject Unpicklertype_value() {
+  PyTypeObject Unpicklertype = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,                            /*ob_size*/
+    "Unpickler",                  /*tp_name*/
+    sizeof(Unpicklerobject),              /*tp_basicsize*/
+    0,                            /*tp_itemsize*/
+    /* methods */
+    (destructor)Unpickler_dealloc,        /*tp_dealloc*/
+    (printfunc)0,         /*tp_print*/
+    (getattrfunc)Unpickler_getattr,       /*tp_getattr*/
+    (setattrfunc)Unpickler_setattr,       /*tp_setattr*/
+    (cmpfunc)0,           /*tp_compare*/
+    (reprfunc)0,          /*tp_repr*/
+    0,                    /*tp_as_number*/
+    0,            /*tp_as_sequence*/
+    0,            /*tp_as_mapping*/
+    (hashfunc)0,          /*tp_hash*/
+    (ternaryfunc)0,               /*tp_call*/
+    (reprfunc)0,          /*tp_str*/
+
+    /* Space for future expansion */
+    0L,0L,0L,0L,
+    Unpicklertype__doc__ /* Documentation string */
+  };
+  return Unpicklertype;
+}
+
+static struct PyMethodDef cPickle_methods[] = {
+  {"dump",         (PyCFunction)cpm_dump,         1, ""},
+  {"dumps",        (PyCFunction)cpm_dumps,        1, ""},
+  {"load",         (PyCFunction)cpm_load,         1, ""},
+  {"loads",        (PyCFunction)cpm_loads,        1, ""},
   {"Pickler",      (PyCFunction)get_Pickler,      1, ""},
-  {"Unpickler",    (PyCFunction)get_Unpickler,    0, ""},
+  {"Unpickler",    (PyCFunction)get_Unpickler,    1, ""},
   { NULL, NULL }
 };
 
 
-static int
-init_stuff()
-{
-  PyObject *builtins, *apply_func, *string;
+#define CHECK_FOR_ERRORS(MESS) \
+if(PyErr_Occurred()) { \
+    PyObject *__sys_exc_type, *__sys_exc_value, *__sys_exc_traceback; \
+    PyErr_Fetch( &__sys_exc_type, &__sys_exc_value, &__sys_exc_traceback); \
+    fprintf(stderr, # MESS ":\n\t"); \
+    PyObject_Print(__sys_exc_type, stderr,0); \
+    fprintf(stderr,", "); \
+    PyObject_Print(__sys_exc_value, stderr,0); \
+    fprintf(stderr,"\n"); \
+    fflush(stderr); \
+    Py_FatalError(# MESS); \
+}
 
-  UNLESS(builtins = PyImport_ImportModule("__builtin__"))
-    return 1;
 
-  UNLESS(apply_func = PyObject_GetAttrString(builtins, "apply"))
-    return 1;
+static int
+init_stuff(PyObject *module, PyObject *module_dict) {
+    PyObject *string, *copy_reg;
+
+#define INIT_STR(S) UNLESS(S ## _str=PyString_FromString(#S)) return -1;
+
+    INIT_STR(__class__);
+    INIT_STR(__getinitargs__);
+    INIT_STR(__dict__);
+    INIT_STR(__getstate__);
+    INIT_STR(__setstate__);
+    INIT_STR(__name__);
+    INIT_STR(__reduce__);
+    INIT_STR(write);
+    INIT_STR(__safe_for_unpickling__);
+    INIT_STR(append);
+    INIT_STR(read);
+    INIT_STR(readline);
+
+    UNLESS(builtins = PyImport_ImportModule("__builtin__"))
+        return -1;
 
-  BuiltinFunctionType = apply_func->ob_type;
+    UNLESS(copy_reg = PyImport_ImportModule("copy_reg"))
+        return -1;
 
-  Py_DECREF(apply_func);
+    UNLESS(dispatch_table = PyObject_GetAttrString(copy_reg, 
+        "dispatch_table"))
+        return -1;
 
-  Py_DECREF(builtins);
+    UNLESS(safe_constructors = PyObject_GetAttrString(copy_reg, 
+        "safe_constructors"))
+        return -1;
 
-  UNLESS(string = PyImport_ImportModule("string"))
-    return 1;
+    Py_DECREF(copy_reg);
 
-  UNLESS(atol_func = PyObject_GetAttrString(string, "atol"))
-    return 1;
+    UNLESS(string = PyImport_ImportModule("string"))
+        return -1;
 
-  Py_DECREF(string);
+    UNLESS(atol_func = PyObject_GetAttrString(string, "atol"))
+        return -1;
 
-  UNLESS(empty_list = PyList_New(0))
-    return 1;
+    Py_DECREF(string);
 
-  UNLESS(empty_tuple = PyTuple_New(0))
-    return 1;
+    UNLESS(empty_tuple = PyTuple_New(0))
+        return -1;
 
-  UNLESS(class_map = PyDict_New())
-    return 1;
+    UNLESS(class_map = PyDict_New())
+        return -1;
 
-  UNLESS(PicklingError = PyString_FromString("cPickle.PicklingError"))
-    return 1;
+    UNLESS(PicklingError = PyString_FromString("cPickle.PicklingError"))
+        return -1;
 
-  UNLESS(UnpicklingError = PyString_FromString("cPickle.UnpicklingError"))
-    return 1;
+    if (PyDict_SetItemString(module_dict, "PicklingError", 
+        PicklingError) < 0)
+        return -1;
 
-  PycString_IMPORT;
-  return 0;
-}
+    UNLESS(UnpicklingError = PyString_FromString("cPickle.UnpicklingError"))
+        return -1;
 
+    if (PyDict_SetItemString(module_dict, "UnpicklingError",
+        UnpicklingError) < 0)
+        return -1;
 
-#define CHECK_FOR_ERRORS(MESS) \
-if(PyErr_Occurred()) { \
-  PyObject *__sys_exc_type, *__sys_exc_value, *__sys_exc_traceback; \
-  PyErr_Fetch( &__sys_exc_type, &__sys_exc_value, &__sys_exc_traceback); \
-  fprintf(stderr, # MESS ":\n\t"); \
-  PyObject_Print(__sys_exc_type, stderr,0); \
-  fprintf(stderr,", "); \
-  PyObject_Print(__sys_exc_value, stderr,0); \
-  fprintf(stderr,"\n"); \
-  fflush(stderr); \
-  Py_FatalError(# MESS); \
+    PycString_IMPORT;
+    return 0;
 }
 
 
 /* Initialization function for the module (*must* be called initcPickle) */
 void
-initcPickle()
-{
-  PyObject *m, *d;
+initcPickle() {
+    PyObject *m, *d;
+    char *rev="$Revision$";
+    PyObject *format_version;
+    PyObject *compatible_formats;
 
-  /* Create the module and add the functions */
-  m = Py_InitModule4("cPickle", cPickle_methods,
-      cPickle_module_documentation,
-      (PyObject*)NULL,PYTHON_API_VERSION);
 
-  /* Add some symbolic constants to the module */
-  d = PyModule_GetDict(m);
-  ErrorObject = PyString_FromString("cPickle.error");
-  PyDict_SetItemString(d, "error", ErrorObject);
+    /* Create the module and add the functions */
+    m = Py_InitModule4("cPickle", cPickle_methods,
+                     cPickle_module_documentation,
+                     (PyObject*)NULL,PYTHON_API_VERSION);
 
-  /* XXXX Add constants here */
+    Picklertype=Picklertype_value();
+    Unpicklertype=Unpicklertype_value();
 
-  if (init_stuff())
-         Py_FatalError("can't initialize module cPickle");
+    /* Add some symbolic constants to the module */
+    d = PyModule_GetDict(m);
+    PyDict_SetItemString(d,"__version__",
+                        PyString_FromStringAndSize(rev+11,strlen(rev+11)-2));
 
-  CHECK_FOR_ERRORS("can't initialize module cPickle");
+#ifdef FORMAT_1_3
+    format_version = PyString_FromString("1.3");
+    compatible_formats = Py_BuildValue("[sss]", "1.0", "1.1", "1.2");
+#else
+    format_version = PyString_FromString("1.2");
+    compatible_formats = Py_BuildValue("[ss]", "1.0", "1.1");
+#endif
 
-  PyDict_SetItemString(d, "PicklingError", PicklingError);
-  CHECK_FOR_ERRORS("can't initialize module cPickle:  error creating PicklingError");
+    PyDict_SetItemString(d, "format_version", format_version);
+    PyDict_SetItemString(d, "compatible_formats", compatible_formats);
 
-  PyDict_SetItemString(d, "UnpicklingError", UnpicklingError);
-  CHECK_FOR_ERRORS("can't initialize module cPickle:  error creating UnpicklingError");  
+    init_stuff(m, d);
+    CHECK_FOR_ERRORS("can't initialize module cPickle");
 }
+
+/****************************************************************************
+ $Log$
+ Revision 2.3  1997/04/09 17:36:32  guido
+ Jim Fulton's version 2.2.
+
+ Revision 1.36  1997/03/11 22:05:02  chris
+ write POP rather than POPMARK in non-binary mode
+ use put2() in save_reduce() and save_inst() only if state is not a dictionary
+ removed put2() from save_tuple()
+
+ Revision 1.35  1997/03/11 20:03:30  jim
+ Added log comment at bottom.
+
+
+
+ ****************************************************************************/