/* -*-c-*- */

/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.

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.

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.

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.  */

/* 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 to be covered by the GNU General Public License.
   This exception does not however invalidate any other reasons why
   the executable file might be covered by the GNU General Public License.  */

/* 
  $Header: /usr/user/dennis_glatting/ObjC/c-runtime/dispatch.common/RCS/Object.m,v 0.19 1992/04/18 01:11:50 dennisg Exp $
  $Author: dennisg $
  $Date: 1992/04/18 01:11:50 $
  $Log: Object.m,v $
# Revision 0.19  1992/04/18  01:11:50  dennisg
# changes some name accesses to use functions.
#
# Revision 0.18  1992/04/18  00:43:06  dennisg
# Changed -hash.
# It returned 'self' casted to a unsigned int.
#
# Revision 0.17  1992/04/13  11:43:08  dennisg
# Check in after array version of run-time works.
# Expect more changes as hash version and other changes are made.
#
# Revision 0.16  1992/02/25  11:16:03  dennisg
# ??? I lost track.
#
# Revision 0.15  1992/01/03  02:55:03  dennisg
# modified to handle new initialization scheme.
# fixed code structure.
#
# Revision 0.14  1991/12/31  20:13:03  dennisg
# Deleted index variable stuff.  Index variables are a hack to the language.
#
# Revision 0.13  1991/12/10  12:04:55  dennisg
# Cleaned up file format for a distribution.
#
# Revision 0.12  1991/12/07  00:49:28  dennisg
# deleted +description:.
#
# Revision 0.11  1991/12/06  00:35:05  dennisg
# deleted perform:with:: method.
# changes the other perform: methods to use objc_msgSend() correctly.
#
# Revision 0.10  1991/11/30  14:19:18  dennisg
# implemented archiving.
#
# Revision 0.9  1991/11/29  21:59:32  dennisg
# modified to implement set functions.
#
# Revision 0.8  1991/11/29  20:01:29  dennisg
# fixed several const decls.  bozo.
#
# Revision 0.7  1991/11/29  14:09:51  dennisg
# changed some methods to implement functions contained in the core code.
#
# Revision 0.6  1991/11/26  02:45:16  dennisg
# commiting a copy of the source to rcs before i implement
# changes to fix posing.
#
# Revision 0.5  1991/11/20  02:06:30  dennisg
# returned doesNotRecognize:
#
# Revision 0.4  1991/11/19  12:37:24  dennisg
# minr changes.  still in a state of flux.
#
# Revision 0.3  1991/11/16  13:32:58  dennisg
# changed #import statements to #include.
# this should make gcc2 happy -- geez.
#
# Revision 0.2  1991/11/07  22:30:54  dennisg
# added copyleft
#
# Revision 0.1  1991/10/24  00:45:39  dennisg
# Initial check in.  Preliminary development stage.
#
*/
 

#include <Object.h>
#include <objc-proto.h>
#include <objc-protoP.h>

#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>


#define CLASS( class )  (( Class_t )class )


@implementation Object


+ new {


  return class_createInstance( CLASS( self ));
}


+ free {  return nil; }
- free {  return object_dispose( self ); }


- copy {  return [ self shallowCopy ]; }


- shallowCopy {


  return object_copy ( self );
}


- deepCopy {

  
  return class_createInstance ([ self class ]);
}


+ ( Class_t )class      { return CLASS( self ); }
+ ( Class_t )superClass { return CLASS( self )->super_class; }
- ( Class_t )class      { return isa; }
- ( Class_t )superClass { return isa->super_class; }
- ( const char * )name  { return object_getClassName (self); }
- self                  { return self; }


- ( u_int )hash {

  
  return ( u_int )self; /* gak!  Not portable. */
}


- ( BOOL )isEqual:anObject {

  
  return self == anObject ;
}


- ( BOOL )isKindOf:( Class_t )aClassObject {


  return [ self isKindOfGivenName:class_getClassName (aClassObject)];
}


- ( BOOL )isMemberOf:( Class_t )aClassObject {


  return isa == aClassObject ;
}


- ( BOOL )isKindOfGivenName:( const char* )aClassName {

  Class_t   class;
  
  
  for( class = isa; class; class = class->super_class )
    if( !strcmp( class_getClassName (class), aClassName ))
      return YES;
  
  return NO;
}


- ( BOOL )isMemberOfGivenName:( const char* )aClassName {


  return !strcmp([ self name ], aClassName );
}


+ ( BOOL )instancesRespondTo:( SEL )aSel {

  
  if( class_getInstanceMethod( CLASS( self ), aSel ))
    return YES;
  
  return NO;
}


- ( BOOL )respondsTo:( SEL )aSel {


  if( class_getInstanceMethod( isa, aSel ))
    return YES;

  return NO;
}


- perform:( SEL )aSel {

  
  return (*((IMP)objc_msgSend( self, aSel )))(self, aSel);
}


- perform:( SEL )aSel with:aObject {

  
  return (*((IMP)objc_msgSend( self, aSel )))(self, aSel, aObject);
}


+ poseAs:( Class_t )aClassObject {


  return class_poseAs (self, aClassObject);
}

 
- subclassResponsibility:( SEL )aSel {

  
  return [ self error:"subclass should override %s", aSel ];
}


- notImplemented:(SEL)aSel {


  return [ self error:"method %s not implemented", aSel ];
}


- doesNotRecognize:( SEL )aSel {


  return [ self error:"%s does not recognize %s", [ self name ], aSel ];
}

- error:( const char* )aString, ... {

#define FMT "error: %s (instance)\n%s\n"

  char  fmt[ strlen (FMT) + 
              strlen (isa->name) +
              strlen (aString) + 8 ];
  va_list ap;
  
  
  sprintf (fmt, FMT, isa->name, aString);
  va_start (ap, aString);
  (*_error)(self, fmt, ap);
  va_end (ap);

#undef FMT
  return self;
}


+ error:( const char* )aString, ... {

#define FMT "error: %s (class)\n%s\n"

  char  fmt[ strlen (FMT) + 
              strlen (isa->name) +
              strlen (aString) + 8 ];
  va_list ap;
  
  
  sprintf (fmt, FMT, isa->name, aString);
  va_start (ap, aString);
  (*_error)(self, fmt, ap);
  va_end (ap);

#undef FMT
  return self;
}


- storeOn:( int )aFd {

  int   len;
  long  version = [[ self class ] version ];
  
  
  if ((len = write (aFd, "#", strlen ("#"))) != -1)
    if ((len = write (aFd, [ self name ], strlen ([ self name ]) + 1)) != -1)
      len = write (aFd, &version, sizeof (version));
  
  if (len == -1)
    [ self error:"error passivating object, errno=%d", errno ];

  return self;
}


+ readFrom:( int )aFd {

  id    aObj = nil;
  char  objName[256];
  int   len;
  
  
  if ((len = read (aFd, &objName, strlen ("#"))) != -1)
    if (objName[0] == '#') {
      long  version;
      int   i = 0;
      
                                                /* Read the object's class. */
      do {
        len = read (aFd, &objName[i], sizeof (char));
      } while (objName[ i++ ] && (len != -1));
    
                                                /* Get its version. */
      if (len != -1)
        len = read (aFd, &version, sizeof (version));
      
                                                /* No errors???
                                                  Then create a object. */
      if (len != -1) {
          aObj = class_createInstance (objc_getClass (objName));
          
                                                /* If the object was 
                                                  successfully created then
                                                  tell it to dearchive
                                                  itself. */
          if (aObj)
            [ aObj readFrom:aFd ];
      }
    }
    
  if (len == -1)
    [ self error:"error activating object, errno=%d", errno ];
  
  return aObj;
}


- readFrom:( int )aFd { return self; }


+ ( int )version {


  return class_getVersion (CLASS (self));
}


+ setVersion:( int )aVersion {


  class_setVersion (CLASS (self), aVersion);
  
  return self;
}


@end


