#ifndef lint
static const char rcsid[] = "$Header: /sun1/lcc/misc_g/RCS/embedded.cpp,v 1.2 1993/10/16 01:14:36 tom Exp $";
#endif

/*
 * $Log: embedded.cpp,v $
# Revision 1.2  1993/10/16  01:14:36  tom
# fix to default DEBUG setting
#
# Revision 1.1  1993/10/16  00:48:02  tom
# Initial revision
#
 */

#include "som.ch"
#ifndef DEBUG
#define DEBUG 0
#endif
typedef struct {
    SOMClass **copp;// & class object for the embedded object.
    long cnt;	// How many of such objects are there?
		    // Replaced by the offset to in whole object where
		    // this embedded thing goes.
    long offset;	// Offset to pointer (to the embedded object(s))
    } embedded;

typedef struct {
    int version;	// 1 for now (?)
    long size;		// true size, dynamically computed.
    long alignment;	// true alignment, dynamically computed.
		    	// Initially or-ed with 0x8000_0000
		    	// to say I've not been here.
    embedded *p;
    } dynamic_info;

// Generate this table at compile time; terminate with 0:
// embedded X::__embedded_tab[] = { ... , 0};
#define Align(x,y_boundary) (((x) + ((y_boundary)-1)) & ~((y_boundary)-1) )

extern "C" void __compute_embedded_table(dynamic_info *dip) {
    // This routine has to know that it was already called,
    // in case XNewClass was called again.
    if (dip->alignment > 0) return; // already done.
    long off = dip->size;	// Initially, just my local size.
    long maxal = dip->alignment ^ 0x8000_0000;
#if DEBUG
    printf("embedded table init size=%x\n",off);
#endif
    for (embedded *p = dip->p; p->copp; p++) {
#if DEBUG
	printf("Looking at entry %x in embedded table: %x %x %x\n",
		p, p->copp, p->cnt, p->offset);
#endif
	int al = 4; 
	al = (*p->copp)->somGetDataAlignment();
	off = Align(off, al);
	maxal = _max(al,maxal);
	SOMClass *member_type = *p->copp;
	int cnt = p->cnt;
	p->cnt = off;	// Offset for the first guy.
	off = cnt * member_type->somGetInstanceSize() + off;
#if DEBUG
	printf("Object pointer is at offset %x, "
		"storage at offset %x rltv to idata; isize=%x of type %s\n",
		p->offset,off,
		member_type->somGetInstanceSize(),
		member_type->somGetName()
		);
#endif
	}
#if DEBUG
    printf("leaving compute_et, final size=%x al=%x\n",off,maxal);
#endif
    // Store back the updated size/alignment.
    dip->size = off;
    dip->alignment = maxal;
    }

#if 0
In a constructor:

X::X() {
    setup_embeddeds(
	somDataResolve(this,X_instance_data_token),
	X_mtab->embedded_tab	// Stored in the mtab.
	);
    ...
    }
#endif

extern "C" void __setup_embedded(char *start_of_my_instance_data, embedded *p) {
#if DEBUG
    printf("In setup_embedded, ids=%x embedded=%x\n",
	start_of_my_instance_data, p);
#endif
    for (; p->copp; p++) {
	void **locn = (void**)(start_of_my_instance_data+p->offset);
	void *objptr = start_of_my_instance_data+p->cnt;
#if DEBUG
    printf("Store object ptr %x=%x+%x at location %x (offset=%x)\n",
	objptr, start_of_my_instance_data,p->cnt,
	locn,
	p->offset);
#endif
	*locn = objptr;
	}
    }
