OSDN Git Service

(objc_skip_typespec): Don't abort for _C_UNDEF.
[pf3gnuchains/gcc-fork.git] / gcc / objc / archive.c
index 17836e7..e9bdcbd 100644 (file)
@@ -1,22 +1,22 @@
 /* GNU Objective C Runtime archiving
-   Copyright (C) 1993 Free Software Foundation, Inc.
-
-Author: Kresten Krab Thorup
+   Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+   Contributed by Kresten Krab Thorup
 
 This file is part of GNU CC.
 
 GNU CC is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 2, or (at your option) any later version.
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
 
 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
-   details.
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+details.
 
 You should have received a copy of the GNU General Public License along with
-   GNU CC; see the file COPYING.  If not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+GNU CC; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* As a special exception, if you link this library with files compiled with
    GCC to produce an executable, this does not cause the resulting executable
@@ -24,40 +24,43 @@ You should have received a copy of the GNU General Public License along with
    however invalidate any other reasons why the executable file might be
    covered by the GNU General Public License.  */
 
-/*
-** Note: This version assumes that int and longs are both 32bit.
-*/
+#include "runtime.h"
+#include "typedstream.h"
+#include "encoding.h"
 
-#ifndef __alpha__
+extern int fflush(FILE*);
 
-#include "runtime.h"
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A);  \
+     __a*((__v+__a-1)/__a); })
+
+#define PTR2LONG(P) (((char*)(P))-(char*)0)
+#define LONG2PTR(L) (((char*)0)+(L))
 
 #define __objc_fatal(format, args...) \
- { fprintf(stderr, "archining: "); \
+ { fprintf(stderr, "archiving: "); \
    fprintf(stderr, format, ## args); \
    fprintf(stderr, "\n"); abort(); }
 
 /* Declare some functions... */
 
 static int
-objc_read_class (struct objc_typed_stream* stream, Class** class);
+objc_read_class (struct objc_typed_stream* stream, Class* class);
 
-static int
-objc_sizeof_type(const char* type);
+int objc_sizeof_type(const char* type);
 
 static int
-objc_write_use_common (struct objc_typed_stream* stream, unsigned int key);
+objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
 
 static int
 objc_write_register_common (struct objc_typed_stream* stream,
-                           unsigned int key);
+                           unsigned long key);
 
 static int 
 objc_write_class (struct objc_typed_stream* stream,
                         struct objc_class* class);
 
-static const char*
-__objc_skip_type (const char* type);
+const char* objc_skip_type (const char* type);
 
 static void __objc_finish_write_root_object(struct objc_typed_stream*);
 static void __objc_finish_read_root_object(struct objc_typed_stream*);
@@ -111,15 +114,29 @@ objc_write_char (struct objc_typed_stream* stream, char value)
 static __inline__ int
 __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
 {
-  if (val <= 0xffU)
-    return __objc_code_unsigned_char (buf, val);
-
+  if ((val&_B_VALUE) == val)
+    {
+      buf[0] = val|_B_SINT;
+      return 1;
+    }
   else 
     {
-      buf[0] = _B_NINT|0x02;
-      buf[1] = val/0x100;
-      buf[2] = val%0x100;
-      return 3;
+      int c, b;
+
+      buf[0] = _B_NINT;
+
+      for (c= sizeof(short); c != 0; c -= 1)
+       if (((val>>(8*(c-1)))%0x100) != 0)
+         break;
+
+      buf[0] |= c;
+
+      for (b = 1; c != 0; c--, b++)
+       {
+         buf[b] = (val >> (8*(c-1)))%0x100;
+       }
+
+      return b;
     }
 }
 
@@ -134,18 +151,11 @@ objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short valu
 static __inline__ int
 __objc_code_short (unsigned char* buf, short val)
 {
-  if (val > 0)
-    return __objc_code_unsigned_short (buf, val);
-
-  if (val > -0x7f)             /* val > -128 */
-    return __objc_code_char (buf, val);
-
-  else 
-    {
-      int len = __objc_code_unsigned_short (buf, -val);
-      buf[0] |= _B_SIGN;
-      return len;
-    }
+  int sign = (val < 0);
+  int size = __objc_code_unsigned_short (buf, sign ? -val : val);
+  if (sign)
+    buf[0] |= _B_SIGN;
+  return size;
 }
 
 int
@@ -160,26 +170,29 @@ objc_write_short (struct objc_typed_stream* stream, short value)
 static __inline__ int
 __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
 {
-  if (val < 0x10000)
-    return __objc_code_unsigned_short (buf, val%0x10000);
-
-  else if (val < 0x1000000)
+  if ((val&_B_VALUE) == val)
     {
-      buf[0] = _B_NINT|3;
-      buf[1] = val/0x10000;
-      buf[2] = (val%0x10000)/0x100;
-      buf[3] = val%0x100;
-      return 4;
+      buf[0] = val|_B_SINT;
+      return 1;
     }
-
   else 
     {
-      buf[0] = _B_NINT|4;
-      buf[1] = val/0x1000000;
-      buf[2] = (val%0x1000000)/0x10000;
-      buf[3] = (val%0x10000)/0x100;
-      buf[4] = val%0x100;
-      return 5;
+      int c, b;
+
+      buf[0] = _B_NINT;
+
+      for (c= sizeof(int); c != 0; c -= 1)
+       if (((val>>(8*(c-1)))%0x100) != 0)
+         break;
+
+      buf[0] |= c;
+
+      for (b = 1; c != 0; c--, b++)
+       {
+         buf[b] = (val >> (8*(c-1)))%0x100;
+       }
+
+      return b;
     }
 }
 
@@ -194,28 +207,77 @@ objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
 static __inline__ int
 __objc_code_int (unsigned char* buf, int val)
 {
-  if (val >= 0)
-    return __objc_code_unsigned_int (buf, val);
+  int sign = (val < 0);
+  int size = __objc_code_unsigned_int (buf, sign ? -val : val);
+  if (sign)
+    buf[0] |= _B_SIGN;
+  return size;
+}
 
-  if (val > -0x7f)
-    return __objc_code_char (buf, val);
+int
+objc_write_int (struct objc_typed_stream* stream, int value)
+{
+  unsigned char buf[sizeof(int)+1];
+  int len = __objc_code_int (buf, value);
+  return (*stream->write)(stream->physical, buf, len);
+}
 
+static __inline__ int
+__objc_code_unsigned_long (unsigned char* buf, unsigned long val)
+{
+  if ((val&_B_VALUE) == val)
+    {
+      buf[0] = val|_B_SINT;
+      return 1;
+    }
   else 
     {
-      int len = __objc_code_unsigned_int (buf, -val);
-      buf[0] |= _B_SIGN;
-      return len;
+      int c, b;
+
+      buf[0] = _B_NINT;
+
+      for (c= sizeof(long); c != 0; c -= 1)
+       if (((val>>(8*(c-1)))%0x100) != 0)
+         break;
+
+      buf[0] |= c;
+
+      for (b = 1; c != 0; c--, b++)
+       {
+         buf[b] = (val >> (8*(c-1)))%0x100;
+       }
+
+      return b;
     }
 }
 
 int
-objc_write_int (struct objc_typed_stream* stream, int value)
+objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
 {
-  unsigned char buf[sizeof(int)+1];
-  int len = __objc_code_int (buf, value);
+  unsigned char buf[sizeof(unsigned long)+1];
+  int len = __objc_code_unsigned_long (buf, value);
+  return (*stream->write)(stream->physical, buf, len);
+}
+
+static __inline__ int
+__objc_code_long (unsigned char* buf, long val)
+{
+  int sign = (val < 0);
+  int size = __objc_code_unsigned_long (buf, sign ? -val : val);
+  if (sign)
+    buf[0] |= _B_SIGN;
+  return size;
+}
+
+int
+objc_write_long (struct objc_typed_stream* stream, long value)
+{
+  unsigned char buf[sizeof(long)+1];
+  int len = __objc_code_long (buf, value);
   return (*stream->write)(stream->physical, buf, len);
 }
 
+
 int
 objc_write_string (struct objc_typed_stream* stream,
                   const unsigned char* string, unsigned int nbytes)
@@ -239,13 +301,13 @@ int
 objc_write_string_atomic (struct objc_typed_stream* stream,
                          unsigned char* string, unsigned int nbytes)
 {
-  unsigned int key;
-  if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string)))
+  unsigned long key;
+  if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
     return objc_write_use_common (stream, key);
   else
     {
       int length;
-      hash_add (&stream->stream_table, (void*)key=(unsigned int)string, string);
+      hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
       if ((length = objc_write_register_common (stream, key)))
        return objc_write_string (stream, string, nbytes);
       return length;
@@ -253,10 +315,10 @@ objc_write_string_atomic (struct objc_typed_stream* stream,
 }
 
 static int
-objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
+objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
 {
-  unsigned char buf[sizeof (unsigned int)+2];
-  int len = __objc_code_unsigned_int (buf+1, key);
+  unsigned char buf[sizeof (unsigned long)+2];
+  int len = __objc_code_unsigned_long (buf+1, key);
   if (len == 1)
     {
       buf[0] = _B_RCOMM|0x01;
@@ -271,10 +333,10 @@ objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
 }
 
 static int
-objc_write_use_common (struct objc_typed_stream* stream, unsigned int key)
+objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
 {
-  unsigned char buf[sizeof (unsigned int)+2];
-  int len = __objc_code_unsigned_int (buf+1, key);
+  unsigned char buf[sizeof (unsigned long)+2];
+  int len = __objc_code_unsigned_long (buf+1, key);
   if (len == 1)
     {
       buf[0] = _B_UCOMM|0x01;
@@ -304,7 +366,7 @@ __inline__ int
 __objc_write_object (struct objc_typed_stream* stream, id object)
 {
   unsigned char buf = '\0';
-  SEL write_sel = sel_get_uid ("write:");
+  SEL write_sel = sel_get_any_uid ("write:");
   if (object)
     {
       __objc_write_extension (stream, _BX_OBJECT);
@@ -319,12 +381,12 @@ __objc_write_object (struct objc_typed_stream* stream, id object)
 int 
 objc_write_object_reference (struct objc_typed_stream* stream, id object)
 {
-  unsigned int key;
-  if ((key = (unsigned int)hash_value_for_key (stream->object_table, object)))
+  unsigned long key;
+  if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
     return objc_write_use_common (stream, key);
 
   __objc_write_extension (stream, _BX_OBJREF);
-  return objc_write_unsigned_int (stream, (unsigned int)object);
+  return objc_write_unsigned_long (stream, PTR2LONG (object));
 }
 
 int 
@@ -347,8 +409,8 @@ objc_write_root_object (struct objc_typed_stream* stream, id object)
 int 
 objc_write_object (struct objc_typed_stream* stream, id object)
 {
-  unsigned int key;
-  if ((key = (unsigned int)hash_value_for_key (stream->object_table, object)))
+  unsigned long key;
+  if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
     return objc_write_use_common (stream, key);
 
   else if (object == nil)
@@ -357,20 +419,26 @@ objc_write_object (struct objc_typed_stream* stream, id object)
   else
     {
       int length;
-      hash_add (&stream->object_table, (void*)key=(unsigned int)object, object);
+      hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
       if ((length = objc_write_register_common (stream, key)))
        return __objc_write_object (stream, object);
       return length;
     }
 }
 
+#ifdef __alpha__
+extern int atoi (const char*);
+extern size_t strlen(const char*);
+extern size_t strcpy(char*, const char*);
+#endif
+
 __inline__ int
 __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
 {
   __objc_write_extension (stream, _BX_CLASS);
   objc_write_string_atomic(stream, (char*)class->name,
-                          strlen(class->name));
-  objc_write_unsigned_int (stream, CLS_GETNUMBER(class));
+                          strlen((char*)class->name));
+  return objc_write_unsigned_long (stream, class->version);
 }
 
 
@@ -378,13 +446,13 @@ static int
 objc_write_class (struct objc_typed_stream* stream,
                         struct objc_class* class)
 {
-  unsigned int key;
-  if ((key = (unsigned int)hash_value_for_key (stream->stream_table, class)))
+  unsigned long key;
+  if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
     return objc_write_use_common (stream, key);
   else
     {
       int length;
-      hash_add (&stream->stream_table, (void*)key=(unsigned int)class, class);
+      hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
       if ((length = objc_write_register_common (stream, key)))
        return __objc_write_class (stream, class);
       return length;
@@ -395,22 +463,32 @@ objc_write_class (struct objc_typed_stream* stream,
 __inline__ int 
 __objc_write_selector (struct objc_typed_stream* stream, SEL selector)
 {
-  const char* sel_name = sel_get_name (selector);
+  const char* sel_name;
   __objc_write_extension (stream, _BX_SEL);
-  return objc_write_string (stream, sel_name, strlen(sel_name));
+  /* to handle NULL selectors */
+  if ((SEL)0 == selector)
+    return objc_write_string (stream, "", 0);
+  sel_name = sel_get_name (selector);
+  return objc_write_string (stream, sel_name, strlen ((char*)sel_name));
 }
 
 int 
 objc_write_selector (struct objc_typed_stream* stream, SEL selector)
 {
-  const char* sel_name = sel_get_name (selector);
-  unsigned int key;
-  if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name)))
+  const char* sel_name;
+  unsigned long key;
+
+  /* to handle NULL selectors */
+  if ((SEL)0 == selector)
+    return __objc_write_selector (stream, selector);
+
+  sel_name = sel_get_name (selector);
+  if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
     return objc_write_use_common (stream, key);
   else
     {
       int length;
-      hash_add (&stream->stream_table, (void*)key=(unsigned int)sel_name, (char*)sel_name);
+      hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
       if ((length = objc_write_register_common (stream, key)))
        return __objc_write_selector (stream, selector);
       return length;
@@ -551,6 +629,33 @@ objc_read_int (struct objc_typed_stream* stream, int* value)
 }
 
 __inline__ int
+objc_read_long (struct objc_typed_stream* stream, long* value)
+{
+  unsigned char buf[sizeof(long)+1];
+  int len;
+  if ((len = (*stream->read)(stream->physical, buf, 1)))
+    {
+      if ((buf[0] & _B_CODE) == _B_SINT)
+       (*value) = (buf[0] & _B_VALUE);
+
+      else
+       {
+         int pos = 1;
+         int nbytes = buf[0] & _B_NUMBER;
+         if (nbytes > sizeof (long))
+           __objc_fatal("expected long, got bigger");
+         len = (*stream->read)(stream->physical, buf+1, nbytes);
+         (*value) = 0;
+         while (pos <= nbytes)
+           (*value) = ((*value)*0x100) + buf[pos++];
+         if (buf[0] & _B_SIGN)
+           (*value) = -(*value);
+       }
+    }
+  return len;
+}
+
+__inline__ int
 __objc_read_nbyte_uint (struct objc_typed_stream* stream,
                       unsigned int nbytes, unsigned int* val)
 {
@@ -586,6 +691,42 @@ objc_read_unsigned_int (struct objc_typed_stream* stream,
   return len;
 }
 
+int
+__objc_read_nbyte_ulong (struct objc_typed_stream* stream,
+                      unsigned int nbytes, unsigned long* val)
+{
+  int len, pos = 0;
+  unsigned char buf[sizeof(unsigned long)+1];
+
+  if (nbytes > sizeof (long))
+    __objc_fatal("expected long, got bigger");
+
+  len = (*stream->read)(stream->physical, buf, nbytes);
+  (*val) = 0;
+  while (pos < nbytes)
+    (*val) = ((*val)*0x100) + buf[pos++];
+  return len;
+}
+  
+
+__inline__ int
+objc_read_unsigned_long (struct objc_typed_stream* stream,
+                       unsigned long* value)
+{
+  unsigned char buf[sizeof(unsigned long)+1];
+  int len;
+  if ((len = (*stream->read)(stream->physical, buf, 1)))
+    {
+      if ((buf[0] & _B_CODE) == _B_SINT)
+       (*value) = (buf[0] & _B_VALUE);
+
+      else
+       len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
+
+    }
+  return len;
+}
+
 __inline__ int
 objc_read_string (struct objc_typed_stream* stream,
                  char** string)
@@ -594,11 +735,11 @@ objc_read_string (struct objc_typed_stream* stream,
   int len;
   if ((len = (*stream->read)(stream->physical, buf, 1)))
     {
-      unsigned int key = 0;
+      unsigned long key = 0;
 
       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
        {
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
          len = (*stream->read)(stream->physical, buf, 1);
        }
 
@@ -606,9 +747,9 @@ objc_read_string (struct objc_typed_stream* stream,
       case _B_SSTR:
        {
          int length = buf[0]&_B_VALUE;
-         (*string) = (char*)malloc(length+1);
+         (*string) = (char*)__objc_xmalloc(length+1);
          if (key)
-           hash_add (&stream->stream_table, (void*)key, *string);
+           hash_add (&stream->stream_table, LONG2PTR(key), *string);
          len = (*stream->read)(stream->physical, *string, length);
          (*string)[length] = '\0';
        }
@@ -616,8 +757,11 @@ objc_read_string (struct objc_typed_stream* stream,
 
       case _B_UCOMM:
        {
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
-         (*string) = hash_value_for_key (stream->stream_table, (void*)key);
+         char *tmp;
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+         tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
+         *string = __objc_xmalloc (strlen(tmp) + 1);
+         strcpy (*string, tmp);
        }
        break;
 
@@ -626,10 +770,10 @@ objc_read_string (struct objc_typed_stream* stream,
          unsigned int nbytes = buf[0]&_B_VALUE;
          len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
          if (len) {
-           (*string) = (char*)malloc(nbytes);
+           (*string) = (char*)__objc_xmalloc(nbytes+1);
            if (key)
-             hash_add (&stream->stream_table, (void*)key, *string);
-           len = (*stream->read)(stream->physical, *string, buf[0]&_B_VALUE);
+             hash_add (&stream->stream_table, LONG2PTR(key), *string);
+           len = (*stream->read)(stream->physical, *string, nbytes);
            (*string)[nbytes] = '\0';
          }
        }
@@ -651,18 +795,18 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
   int len;
   if ((len = (*stream->read)(stream->physical, buf, 1)))
     {
-      SEL read_sel = sel_get_uid ("read:");
-      unsigned int key = 0;
+      SEL read_sel = sel_get_any_uid ("read:");
+      unsigned long key = 0;
 
       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register common */
        {
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
          len = (*stream->read)(stream->physical, buf, 1);
        }
 
       if (buf[0] == (_B_EXT | _BX_OBJECT))
        {
-         Class* class;
+         Class class;
 
          /* get class */
          len = objc_read_class (stream, &class);
@@ -672,7 +816,7 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
 
          /* register? */
          if (key)
-           hash_add (&stream->object_table, (void*)key, *object);
+           hash_add (&stream->object_table, LONG2PTR(key), *object);
 
          /* send -read: */
          if (__objc_responds_to (*object, read_sel))
@@ -688,16 +832,16 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
        {
          if (key)
            __objc_fatal("cannot register use upcode...");
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
-         (*object) = hash_value_for_key (stream->object_table, (void*)key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+         (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
        }
 
       else if (buf[0] == (_B_EXT | _BX_OBJREF))        /* a forward reference */
        {
          struct objc_list* other;
-         len = objc_read_unsigned_int (stream, &key);
-         other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key);
-         hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other));
+         len = objc_read_unsigned_long (stream, &key);
+         other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
+         hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
        }
 
       else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
@@ -715,24 +859,24 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
 }
 
 static int
-objc_read_class (struct objc_typed_stream* stream, Class** class)
+objc_read_class (struct objc_typed_stream* stream, Class* class)
 {
   unsigned char buf[sizeof (unsigned int)];
   int len;
   if ((len = (*stream->read)(stream->physical, buf, 1)))
     {
-      unsigned int key = 0;
+      unsigned long key = 0;
 
       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
        {
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
          len = (*stream->read)(stream->physical, buf, 1);
        }
 
       if (buf[0] == (_B_EXT | _BX_CLASS))
        {
          char* class_name;
-         int version;
+         unsigned long version;
 
          /* get class */
          len = objc_read_string (stream, &class_name);
@@ -741,9 +885,9 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
 
          /* register */
          if (key)
-           hash_add (&stream->stream_table, (void*)key, *class);
+           hash_add (&stream->stream_table, LONG2PTR(key), *class);
 
-         objc_read_unsigned_int(stream, &version);
+         objc_read_unsigned_long(stream, &version);
          hash_add (&stream->class_table, (*class)->name, (void*)version);
        }
 
@@ -751,10 +895,10 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
        {
          if (key)
            __objc_fatal("cannot register use upcode...");
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
-         (*class) = hash_value_for_key (stream->stream_table, (void*)key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+         (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
          if (!*class)
-           __objc_fatal("cannot find class for key %x", key);
+           __objc_fatal("cannot find class for key %lu", key);
        }
 
       else
@@ -770,11 +914,11 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
   int len;
   if ((len = (*stream->read)(stream->physical, buf, 1)))
     {
-      unsigned int key = 0;
+      unsigned long key = 0;
 
       if ((buf[0]&_B_CODE) == _B_RCOMM)        /* register following */
        {
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
          len = (*stream->read)(stream->physical, buf, 1);
        }
 
@@ -784,20 +928,27 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
 
          /* get selector */
          len = objc_read_string (stream, &selector_name);
-         (*selector) = sel_get_uid(selector_name);
+         /* To handle NULL selectors */
+         if (0 == strlen(selector_name))
+           {
+             (*selector) = (SEL)0;
+             return 0;
+           }
+         else 
+           (*selector) = sel_get_any_uid(selector_name);
          free (selector_name);
 
          /* register */
          if (key)
-           hash_add (&stream->stream_table, (void*)key, *selector);
+           hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
        }
 
       else if ((buf[0]&_B_CODE) == _B_UCOMM)
        {
          if (key)
            __objc_fatal("cannot register use upcode...");
-         len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key);
-         (*selector) = hash_value_for_key (stream->stream_table, (void*)key);
+         len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
+         (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
        }
 
       else
@@ -806,96 +957,6 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
   return len;
 }
 
-static int
-objc_sizeof_type(const char* type)
-{
-  switch(*type) {
-  case _C_ID: return sizeof(id);
-    break;
-
-  case _C_CLASS:
-    return sizeof(Class*);
-    break;
-
-  case _C_SEL:
-    return sizeof(SEL);
-    break;
-
-  case _C_CHR:
-    return sizeof(char);
-    break;
-    
-  case _C_UCHR:
-    return sizeof(unsigned char);
-    break;
-
-  case _C_SHT:
-    return sizeof(short);
-    break;
-
-  case _C_USHT:
-    return sizeof(unsigned short);
-    break;
-
-  case _C_INT:
-  case _C_LNG:
-    return sizeof(int);
-    break;
-
-  case _C_UINT:
-  case _C_ULNG:
-    return sizeof(unsigned int);
-    break;
-
-  case _C_ATOM:
-  case _C_CHARPTR:
-    return sizeof(char*);
-    break;
-
-  default:
-    fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
-    abort();
-  }
-}
-
-
-static const char*
-__objc_skip_type (const char* type)
-{
-  switch (*type) {
-  case _C_ID:
-  case _C_CLASS:
-  case _C_SEL:
-  case _C_CHR:
-  case _C_UCHR:
-  case _C_CHARPTR:
-  case _C_ATOM:
-  case _C_SHT:
-  case _C_USHT:
-  case _C_INT:
-  case _C_UINT:
-  case _C_LNG:
-  case _C_ULNG:
-  case _C_FLT:
-  case _C_DBL:
-    return ++type;
-    break;
-
-  case _C_ARY_B:
-    while(isdigit(*++type));
-    type = __objc_skip_type(type);
-    if (*type == _C_ARY_E)
-      return ++type;
-    else
-      __objc_fatal("cannot parse typespec: %s", type);
-    break;
-
-  default:
-    fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
-    abort();
-  }
-}
-
 /*
 ** USER LEVEL FUNCTIONS
 */
@@ -914,7 +975,7 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
     break;
 
   case _C_CLASS:
-    return objc_write_class (stream, *(Class**)data);
+    return objc_write_class (stream, *(Class*)data);
     break;
 
   case _C_SEL:
@@ -938,31 +999,55 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
     break;
 
   case _C_INT:
-  case _C_LNG:
     return objc_write_int(stream, *(int*)data);
     break;
 
   case _C_UINT:
-  case _C_ULNG:
     return objc_write_unsigned_int(stream, *(unsigned int*)data);
     break;
 
+  case _C_LNG:
+    return objc_write_long(stream, *(long*)data);
+    break;
+
+  case _C_ULNG:
+    return objc_write_unsigned_long(stream, *(unsigned long*)data);
+    break;
+
   case _C_CHARPTR:
-    return objc_write_string (stream, (char*)data, strlen((char*)data));
+    return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
     break;
 
   case _C_ATOM:
-    return objc_write_string_atomic (stream, (char*)data, strlen((char*)data));
+    return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
     break;
 
   case _C_ARY_B:
     {
       int len = atoi(type+1);
-      while (isdigit(*++type));
+      while (isdigit(*++type))
+       ;
       return objc_write_array (stream, type, len, data);
     }
     break; 
 
+  case _C_STRUCT_B:
+    {
+      int acc_size = 0;
+      int align;
+      while (*type != _C_STRUCT_E && *type++ != '=')
+       ; /* skip "<name>=" */
+      while (*type != _C_STRUCT_E)
+       {
+         align = objc_alignof_type (type);       /* padd to alignment */
+         acc_size += ROUND (acc_size, align);
+         objc_write_type (stream, type, ((char*)data)+acc_size);
+         acc_size += objc_sizeof_type (type);   /* add component size */
+         type = objc_skip_typespec (type);      /* skip component */
+       }
+      return 1;
+    }
+
   default:
     fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
     abort();
@@ -986,7 +1071,7 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
     break;
 
   case _C_CLASS:
-    return objc_read_class (stream, (Class**)data);
+    return objc_read_class (stream, (Class*)data);
     break;
 
   case _C_SEL:
@@ -1010,15 +1095,21 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
     break;
 
   case _C_INT:
-  case _C_LNG:
     return objc_read_int (stream, (int*)data);
     break;
 
   case _C_UINT:
-  case _C_ULNG:
     return objc_read_unsigned_int (stream, (unsigned int*)data);
     break;
 
+  case _C_LNG:
+    return objc_read_long (stream, (long*)data);
+    break;
+
+  case _C_ULNG:
+    return objc_read_unsigned_long (stream, (unsigned long*)data);
+    break;
+
   case _C_CHARPTR:
   case _C_ATOM:
     return objc_read_string (stream, (char**)data);
@@ -1027,13 +1118,31 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
   case _C_ARY_B:
     {
       int len = atoi(type+1);
-      while (isdigit(*++type));
+      while (isdigit(*++type))
+       ;
       return objc_read_array (stream, type, len, data);
     }
     break; 
 
+  case _C_STRUCT_B:
+    {
+      int acc_size = 0;
+      int align;
+      while (*type != _C_STRUCT_E && *type++ != '=')
+       ; /* skip "<name>=" */
+      while (*type != _C_STRUCT_E)
+       {
+         align = objc_alignof_type (type);       /* padd to alignment */
+         acc_size += ROUND (acc_size, align);
+         objc_read_type (stream, type, ((char*)data)+acc_size);
+         acc_size += objc_sizeof_type (type);   /* add component size */
+         type = objc_skip_typespec (type);      /* skip component */
+       }
+      return 1;
+    }
+
   default:
-    fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
+    fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
     abort();
   }
 }
@@ -1057,7 +1166,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
 
   va_start(args, type);
 
-  for (c = type; *c; c = __objc_skip_type (c))
+  for (c = type; *c; c = objc_skip_typespec (c))
     {
       switch(*c) {
       case _C_ID:
@@ -1065,7 +1174,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
        break;
 
       case _C_CLASS:
-       res = objc_write_class (stream, *va_arg(args, Class**));
+       res = objc_write_class (stream, *va_arg(args, Class*));
        break;
 
       case _C_SEL:
@@ -1091,26 +1200,32 @@ objc_write_types (TypedStream* stream, const char* type, ...)
        break;
 
       case _C_INT:
-      case _C_LNG:
        res = objc_write_int(stream, *va_arg(args, int*));
        break;
        
       case _C_UINT:
-      case _C_ULNG:
        res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
        break;
 
+      case _C_LNG:
+       res = objc_write_long(stream, *va_arg(args, long*));
+       break;
+       
+      case _C_ULNG:
+       res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
+       break;
+
       case _C_CHARPTR:
        {
-         char* str = va_arg(args, char*);
-         res = objc_write_string (stream, str, strlen(str));
+         char** str = va_arg(args, char**);
+         res = objc_write_string (stream, *str, strlen(*str));
        }
        break;
 
       case _C_ATOM:
        {
-         char* str = va_arg(args, char*);
-         res = objc_write_string_atomic (stream, str, strlen(str));
+         char** str = va_arg(args, char**);
+         res = objc_write_string_atomic (stream, *str, strlen(*str));
        }
        break;
 
@@ -1118,16 +1233,17 @@ objc_write_types (TypedStream* stream, const char* type, ...)
        {
          int len = atoi(c+1);
          const char* t = c;
-         while (isdigit(*++t));
+         while (isdigit(*++t))
+           ;
          res = objc_write_array (stream, t, len, va_arg(args, void*));
-         t = __objc_skip_type (t);
+         t = objc_skip_typespec (t);
          if (*t != _C_ARY_E)
            __objc_fatal("expected `]', got: %s", t);
        }
        break; 
        
       default:
-       fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
+       fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
        abort();
       }
     }
@@ -1150,7 +1266,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
 
   va_start(args, type);
 
-  for (c = type; *c; c = __objc_skip_type(c))
+  for (c = type; *c; c = objc_skip_typespec(c))
     {
       switch(*c) {
       case _C_ID:
@@ -1158,7 +1274,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
        break;
 
       case _C_CLASS:
-       res = objc_read_class(stream, va_arg(args, Class**));
+       res = objc_read_class(stream, va_arg(args, Class*));
        break;
 
       case _C_SEL:
@@ -1182,15 +1298,21 @@ objc_read_types(TypedStream* stream, const char* type, ...)
        break;
 
       case _C_INT:
-      case _C_LNG:
        res = objc_read_int(stream, va_arg(args, int*));
        break;
        
       case _C_UINT:
-      case _C_ULNG:
        res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
        break;
 
+      case _C_LNG:
+       res = objc_read_long(stream, va_arg(args, long*));
+       break;
+       
+      case _C_ULNG:
+       res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
+       break;
+
       case _C_CHARPTR:
       case _C_ATOM:
        {
@@ -1203,16 +1325,17 @@ objc_read_types(TypedStream* stream, const char* type, ...)
        {
          int len = atoi(c+1);
          const char* t = c;
-         while (isdigit(*++t));
+         while (isdigit(*++t))
+           ;
          res = objc_read_array (stream, t, len, va_arg(args, void*));
-         t = __objc_skip_type (t);
+         t = objc_skip_typespec (t);
          if (*t != _C_ARY_E)
            __objc_fatal("expected `]', got: %s", t);
        }
        break; 
        
       default:
-       fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
+       fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
        abort();
       }
     }
@@ -1262,6 +1385,12 @@ objc_read_array (TypedStream* stream, const char* type,
   return 1;
 }
 
+static void
+__objc_free (void* p)
+{
+  free (p);
+}
+
 static int 
 __objc_fread(FILE* file, char* data, int len)
 {
@@ -1299,10 +1428,12 @@ __objc_read_typed_stream_signature (TypedStream* stream)
   int pos = 0;
   do
     (*stream->read)(stream->physical, buffer+pos, 1);
-  while (buffer[pos++] != '\0');
+  while (buffer[pos++] != '\0')
+    ;
   sscanf (buffer, "GNU TypedStream %d", &stream->version);
   if (stream->version != OBJC_TYPED_STREAM_VERSION)
     __objc_fatal ("cannot handle TypedStream version %d", stream->version);
+  return 1;
 }
 
 static int
@@ -1312,6 +1443,7 @@ __objc_write_typed_stream_signature (TypedStream* stream)
   sprintf(buffer, "GNU TypedStream %d", OBJC_TYPED_STREAM_VERSION);
   stream->version = OBJC_TYPED_STREAM_VERSION;
   (*stream->write)(stream->physical, buffer, strlen(buffer)+1);
+  return 1;
 }
 
 static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
@@ -1325,9 +1457,11 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
 static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
 {
   node_ptr node;
-  SEL awake_sel = sel_get_uid ("awake");
+  struct objc_list* free_list;
+  SEL awake_sel = sel_get_any_uid ("awake");
 
   /* resolve object forward references */
+  free_list = list_cons(NULL, NULL);
   for (node = hash_next (stream->object_refs, NULL); node;
        node = hash_next (stream->object_refs, node))
     {
@@ -1337,10 +1471,13 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
       while(reflist)
        {
          *((id*)reflist->head) = object;
+          if (list_find(&free_list, reflist) == NULL)
+           free_list = list_cons (reflist, free_list);
          reflist = reflist->tail;
        }
-      list_free (node->value);
     }
+  list_mapcar (free_list, __objc_free);
+  list_free (free_list);
 
   /* empty object reference table */
   hash_delete (stream->object_refs);
@@ -1373,9 +1510,7 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
 TypedStream* 
 objc_open_typed_stream (FILE* physical, int mode)
 {
-  int fflush(FILE*);
-
-  TypedStream* s = (TypedStream*)malloc(sizeof(TypedStream));
+  TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
 
   s->mode = mode;
   s->physical = physical;
@@ -1477,13 +1612,12 @@ objc_flush_typed_stream (TypedStream* stream)
   (*stream->flush)(stream->physical);
 }
 
-int 
-objc_get_stream_class_version (TypedStream* stream, Class* class)
+long
+objc_get_stream_class_version (TypedStream* stream, Class class)
 {
   if (stream->class_table)
-    return (int) hash_value_for_key (stream->class_table, class->name);
+    return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
   else
     return class_get_version (class);
 }
 
-#endif /* __alpha__ */