/*
 *                        --- EON SOFTWARE ---
 *
 *         19 Stapleton Road. Headington. Oxford. OX3 7LX UK.
 *                   Phone or Fax: +44 (0)865 741452
 *                    eMail: eonsw@eonsw.demon.co.uk
 *
 *                   Eon/Eiffel (c) 1994 Eon Software
 *     This is the unpublished proprietary source code of Eon Software
 *
 *             See the accompanying NOTICE file for details.
*/

#include <stdio.h>
#include <stdlib.h>


class GENERAL {
public:
	int id;

	GENERAL() {
		c_object_address = (void*)this;
		c_ob = (void*)this;
		id = 10;
		class_id = id;
	}
	int a;
	int b;
	void *c_object_address;
	void *c_ob;
	int class_id;
};

class ANY : public virtual GENERAL {
public:
	int id;

	ANY() {
		c_object_address = (void*)this;
		c_ob = (void*)this;
		id = 1;
		class_id = id;
	}
	void *c_ob;
};

class SUPPLIER : public virtual ANY {
public:
	char *identifer;
	int id;
	SUPPLIER () { 
		id = 5;
		class_id = id;
	}

	virtual set(char *s) { 
		identifer = s; 
	}
	
	virtual int show () {
		return 100;
	}
};

class SHAPE : public virtual ANY {
public:
	SHAPE() { 
		c_object_address = (void*)this;
		id = 2;
		class_id = id;
		c_ob = (void*)this;
		s = new SUPPLIER;
		s->set ( "shape");
	}
	int id;
	virtual int sides  () { return -1; };
	void *c_ob;

	virtual info() {
		printf ( "INFO: ID=%d  Class id %d  c_ob=%x\n", id, 
				class_id, c_object_address);
	}

	virtual char *name () {
		return "SHAPE";
	}

	virtual char *basename () {
		return "SHAPE";
	}

	SUPPLIER *s;

/*
	void * pcvt( int n) {
		SHAPE *sh;
		case 1:
			break;
		case 2:
			sh = (SHAPE *) a;
			break;
	}

	ret = (void *) sh;

	return ret;
	}

*/
};

class POLYGON : public virtual SHAPE {
public:
	POLYGON () {
		id = 6;
		class_id = id;
		c_object_address = (void*)this;
		c_ob = (void*)this;
	}
};

class SQUARE : public virtual POLYGON {
public:
	ANY *a;
	SQUARE () {
		id = 3;
		class_id = id;
		c_object_address = (void*)this;
		c_ob = (void*)this;
		s = new SUPPLIER;
		s->set ( "shape");
	}
	int id;
	void *c_ob;

	virtual int sides  () { return 4; };
	virtual char *name () {
		return "SQUARE";
	}

	SUPPLIER *s;

	void * pcvt( int n) {
		SHAPE *sh;

		switch ( n) {
		case 1:
			break;
		case 2:
			sh = (SHAPE *) this;
			break;
		}

		return (void *) sh;
	}
};

class ARRAY : public virtual ANY
{
public:
	int id;
	ARRAY () {
		c_object_address = (void*)this;	
		c_ob = (void*)this;
		id = 4;
		class_id = id;
	}

	void *addr;
	void *c_ob;
	push ( ANY *a) {
		addr = a;
	}
	ANY *pop () {
		return (ANY *) addr;
	}
	

	virtual put ( ANY *x) {
		push ( x);
	}

	virtual ANY *item () {
		ANY *a;
	
		a = pop();

		return a;
	}
};

void * cvt( ANY *a);

main()
{
	SQUARE *square;
	SQUARE *new_square;
	ARRAY *store;
	SHAPE *shape;

	square = new SQUARE;
	store = new ARRAY;

	if ( strcmp ( "SHAPE", square->basename())) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	if ( strcmp ( "SQUARE", square->name())) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	if ( square->sides() != 4) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	shape = square;

	if ( strcmp ( "SQUARE", square->name())) {
		printf ( "Failed!\n");
		exit ( 1);
	}
	if ( strcmp ( "SQUARE", shape->name())) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	if ( square->SHAPE::sides() != -1) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	if ( square->sides() != 4) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	store->put ( square);

	shape = (SHAPE*) cvt ( store->item());

	if ( strcmp ( "SQUARE", ((SHAPE*) cvt ( store->item()))->name())) {
		printf ( "Failed!\n");
		exit ( 1);
	}
	
	if ( 4 != ((SHAPE*) cvt ( store->item()))->sides()) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	if ( 100 != ((SHAPE*) cvt ( store->item()))->s->show()) {
		printf ( "Failed!\n");
		exit ( 1);
	}

	return 0;
}

void *
cvt( ANY *a)
{
	int aid = a->class_id;

	switch ( aid) {

		case 1:
			break;
		case 2:					/* SHAPE  */
				
			SHAPE _shape;
			break;
		case 3:					/* SQUARE */

			return ((SQUARE *)a->c_object_address)->pcvt ( 2);

			break;
		case 4:
			break;
		case 5:
			break;
	}

	return (void *) 0;
}
