/* %Z%%M% %I% %E% */

/*
 * Copyright (c) 1992, 1993, 1995 by Wayne C. Gramlich.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * for any purpose is hereby granted without fee provided that the above
 * copyright notice and this permission are retained.  The author makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

/* This file contains code for manipulating objects: */

#ifndef HEAP_EXPORTS_H
#include "heap_exports.h"
#endif

#ifndef CALL_DEFS_H
#include "call_defs.h"
#endif

#ifndef GEN_DEFS_H
#include "gen_defs.h"
#endif

#ifndef LINT_H
#include "lint.h"
#endif

#ifndef LIBC_EXPORTS_H
#include "libc_exports.h"
#endif

#ifndef MSG_EXPORTS_H
#include "msg_exports.h"
#endif

#ifndef OBJECT_DEFS_H
#include "object_defs.h"
#endif

#ifndef OUT_EXPORTS_H
#include "out_exports.h"
#endif

#ifndef STR_EXPORTS_H
#include "str_exports.h"
#endif

#ifndef TABLE_EXPORTS_H
#include "table_exports.h"
#endif

#ifndef TYPE_DEFS_H
#include "type_defs.h"
#endif

#ifndef UNIX_ASSERT_H
#include "unix_assert.h"
#endif

#ifndef UNIX_UNISTD_H
#include "unix_unistd.h"
#endif

#ifndef VECTOR_DEFS_H
#include "vector_defs.h"
#endif

LOCAL void		object_convert(Object, Convert);
LOCAL void		object_gen(Object, Gen);
LOCAL Object_need	object_need_create(Str, Type_ref, Str, Heap);
LOCAL void		object_needs_gen(Object, Vec(Object_need), int, Gen);
LOCAL void		object_parameter_need(Object, Str, Type_ref, Heap);
LOCAL void		object_static_need(Object, Str, Type_ref, Heap);
LOCAL Object_entry	object_entry_insert(Object_table, Str,
					    Type_ref, Type_ref, int);

/*
 * object_convert(object, convert)
 *	This routine will do all the conversion work needed for "object".
 */
LOCAL void
object_convert(
	Object		object,
	Convert		convert)
{
	Heap		heap;
	Type_def	type_def;

	heap = convert->heap;
	type_def = object->type_def;
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		break;
	    case Type_kind_record:
	      {
		Type_record	record;
		Type_field	field;
		Type_fields	fields;

		record = type_def->value.record;
		fields = record->fields;
		VEC_LOOP(Type_field, fields, field) {
			if (type_ref_is_parameterized(field->type_ref)) {
				object_parameter_need(object, field->name,
						     field->type_ref, heap);
			} else {
				object_static_need(object, field->name,
						   field->type_ref, heap);
			}
		}
		break;
	      }
	    case Type_kind_variant:
	      {
		Str		access;
		Type_variant	variant;
		Type_field	field;

		variant = type_def->value.variant;
		field = vec_fetch(Type_field, variant->fields, 0);
		if (type_ref_is_parameterized(field->type_ref)) {
			object_parameter_need(object, field->name,
					     field->type_ref, heap);
		} else {
			object_static_need(object, field->name,
					   field->type_ref, heap);
		}
		field = variant->tag_field;
		access = strprintf(heap, "_tag_.%s", field->name);
		object_static_need(object, access, field->type_ref, heap);
		break;
	      }
	    case Type_kind_external:
		break;
	    default:
		assert_fail();
	}
}

/*
 * object_create(object_table, name, type_ref, type_def)
 *	This routine will create and return an object with "name" and "type_ref"
 *	using "object_table".
 */
void
object_create(
	Object_table	object_table,
	Str		name,
	Type_ref	type_ref,
	Type_def	type_def,
	int		position)
{
	Heap		heap;
	Object		object;
	Object_entry	object_entry;

	heap = object_table->heap;
	object_entry = object_entry_insert(object_table, name, type_ref,
					   type_def->type_ref, position);
	object_entry->defined = 1;
	(void)object_ref_lookup(object_table, name, type_ref);
	object = heap_allocate(heap, Object);;
	object->name = name;
	object->type_def = type_def;
	object->type_ref = type_ref;
	object->static_needs = vec_create(Object_need, heap);
	object->parameter_needs = vec_create(Object_need, heap);
	object->object_entry = object_entry;
	vec_append(Object, object_table->objects, object);
}

/*
 * object_entry_equal(object_entry1, object_entry2)
 *	This object will return 1 if "object_entry1" is equal to
 *	"object_entry2".  They are equal if they have the same name and
 *	type reference name.
 */
LOCAL int
object_entry_equal(
	Object_entry	object_entry1,
	Object_entry	object_entry2)
{
	assert(object_entry1 != (Object_entry)0);
	assert(object_entry2 != (Object_entry)0);

	return strequal(object_entry1->name, object_entry2->name) &&
	       strequal(object_entry1->type_ref->name,
			object_entry2->type_ref->name);
}

/*
 * object_entry_hash(object_entry)
 *	This object will return a hash value for "object_entry".
 */
LOCAL int
object_entry_hash(
	Object_entry	object_entry)
{
	return strhash(object_entry->name) +
	       strhash(object_entry->type_ref->name);
}

/*
 * object_entry_insert(object_table, name, type_ref, actual_type_ref, position)
 *	This routine will insert "name"@"type_ref" into the entry table
 *	in "object_table" with a type of "actual_type_ref".
 */
LOCAL Object_entry
object_entry_insert(
	Object_table	object_table,
	Str		name,
	Type_ref	type_ref,
	Type_ref	actual_type_ref,
	int		position)
{
	Heap		heap;
	Object_entry	object_entry;

	heap = object_table->heap;
	object_entry = heap_allocate(heap, Object_entry);
	object_entry->name = name;
	object_entry->type_ref = type_ref;
	object_entry->object_refs = vec_create(Object_ref, heap);
	object_entry->deleted = 0;
	object_entry->defined = 0;
	object_entry->actual_type_ref = actual_type_ref;
	if (table_insert(Object_entry, Object_entry, object_table->entry_table,
			 object_entry, object_entry) != 0) {
		msg_out(object_table->msg, position, "%s%@ is duplicated",
			name, type_ref);
	}
	vec_append(Object_entry,
		   object_table->object_entrys, object_entry);
	return object_entry;
}

/*
 * object_entry_lookup(object_table, name, type_ref)
 *	This routine will return the object entry for "name"@"type_ref"
 *	from "object_table".  If there is no object entry, (Object_entry)0
 *	is returned.
 */		
LOCAL Object_entry
object_entry_lookup(
	Object_table	object_table,
	Str		name,
	Type_ref	type_ref)
{
	Object_entry	entry_key;
	Object_entry	object_entry;

	entry_key = object_table->entry_key;
	entry_key->name = name;
	entry_key->type_ref = type_ref;
	object_entry = table_lookup(Object_entry, Object_entry,
				    object_table->entry_table, entry_key);
	return object_entry;
}

/*
 * object_entry_print(object_entry, out_file)
 *	This object will print "object_entry" to "out_file" in human
 *	readable form.
 */
LOCAL void
object_entry_print(
	Object_entry	object_entry,
	Stdio		out_file)
{
	out(out_file, "%s@%s:: %s\n", object_entry->name,
	    object_entry->type_ref->name, object_entry->actual_type_ref->name);
}

#ifndef lint
/*
 * object_entry_show(object_entry)
 *	This object will print out "object_entry".
 */
void
object_entry_show(
	Object_entry	object_entry)
{
	object_entry_print(object_entry, stdout);
}
#endif /* lint */

/*
 * object_entrys_dump(object_table, out_file)
 *	This object will dump the object refs from "object_table" to 
 *	"out_file" in a human readable form.
 */
LOCAL void
object_entrys_dump(
	Object_table	object_table,
	Stdio		out_file)
{
	Object_entry	object_entry;
	Vec(Object_entry) object_entrys;

	out(out_file, "Object Entrys Table:\n");
	object_entrys = table_value_list_extract(Object_entry, Object_entry,
						 object_table->entry_table);
	VEC_LOOP(Object_entry, object_entrys, object_entry) {
		object_entry_print(object_entry, out_file);
	}
	out(out_file, "\n");
}

/*
 * object_gen(object, gen)
 *	This routine will output the object structure for "object" using "gen".
 */
LOCAL void
object_gen(
	Object		object,
	Gen		gen)
{
	Str		actual_name;
	int		is_initial;
	Str		name;
	int		size;
	Type_ref	type_ref;

	name = object->name;
	is_initial = strequal(name, "??");
	actual_name = is_initial ? "_initial" : name;
	type_ref = object->type_ref;

	/* Generate the need entry lists: */
	object_needs_gen(object, object->static_needs, 0, gen);
	object_needs_gen(object, object->parameter_needs, 1, gen);

	type_ref_gen(type_ref, gen);

	/* Generate the object___object data structure: */
	gen_out(gen, "static object___object %s%s__%s__object__object = {\n",
		gen->package_name, type_ref->name, actual_name);
	gen_out(gen, "%\t%\",\n", 1, gen->package_name);
	gen_out(gen, "%\t%\",\n", 1, type_ref->name);
	gen_out(gen, "%\t%\",\n", 1, name);
	gen_out(gen, "%\t&%m__type__reference,\n", 1, type_ref);
	if (type_ref_is_parameterized(type_ref)) {
		gen_out(gen, "%\t&%s__object__size,\n", 1, type_ref->name);
	} else {
		gen_out(gen, "%\t(int *)0,\n", 1); /* Size in bytes */
	}
	size = vec_size(Object_need, object->static_needs);
	if (size == 0) {
		gen_out(gen, "%\t0,\n", 1);
		gen_out(gen, "%\t(need___entry *)0,\n", 1);
	} else {
		gen_out(gen, "%\t%d,\n", 1, size);
		gen_out(gen, "%\t%s__%s__static__needs,\n",
			1, type_ref->name, actual_name);
	}
	size = vec_size(Object_need, object->parameter_needs);
	if (size == 0) {
		gen_out(gen, "%\t0,\n", 1);
		gen_out(gen, "%\t(need___entry *)0,\n", 1);
	} else {
		gen_out(gen, "%\t%d,\n", 1, size);
		gen_out(gen, "%\t%s__%s__parameter__needs,\n",
			1, type_ref->name, actual_name);
	}
	if (type_ref_is_parameterized(type_ref)) {
		gen_out(gen, "%\t(void **)0,\n", 1);
	} else {
		gen_out(gen, "%\t(void **)&%s%s__%s,\n", 1,
			gen->package_name, type_ref->name, actual_name);
	}
	gen_out(gen, "%\t(instantiation___object *)0\n", 1);
	gen_out(gen, "};\n");
	gen_out(gen, "\n");
}

/*
 * objects_gen(object_table, gen)
 *	This routine will generate the object structures for each object
 *	in "object_table" and output them using "gen".
 */
void
objects_gen(
	Object_table	object_table,
	Gen		gen)
{
	Object		object;
	Vec(Object)	objects;

	objects = object_table->objects;
	VEC_LOOP(Object, objects, object) {
		object_gen(object, gen);
	}
}

/*
 * object_need_create(name, type_ref, field_name, heap)
 *	This routine will create and return an object need object.
 */
LOCAL Object_need
object_need_create(
	Str		name,
	Type_ref	type_ref,
	Str		field_name,
	Heap		heap)
{
	Object_need	object_need;

	object_need = heap_allocate(heap, Object_need);
	object_need->name = name;
	object_need->type_ref = type_ref;
	object_need->field_name = field_name;
	return object_need;
}

/*
 * object_needs_gen(object, object_needs, parameterized, gen)
 *	This routine will generate the need entries need for "object_needs".
 */
LOCAL void
object_needs_gen(
	Object		object,
	Vec(Object_need) object_needs,
	int		parameterized,
	Gen		gen)
{
	Str		need_name;
	Type_ref	need_type_ref;
	Object_need	object_need;
	Type_refs	parameters;
	int		parameters_size;
	int		size;
	Type_ref	type_ref;

	size = vec_size(Object_needs, object_needs);
	if (size == 0) {
		return;
	}
	type_ref = object->type_ref;
	gen_out(gen, "static need___entry %s__%s__%s__needs[%d] = {\n",
		type_ref->name,
		strequal(object->name, "??") ? "_initial" : object->name,
		parameterized ? "parameter" : "static",
		size);
	VEC_LOOP(Object_need, object_needs, object_need) {
		need_name = object_need->name;
		need_type_ref = object_need->type_ref;
		parameters = need_type_ref->parameters;
		parameters_size = type_refs_size(parameters);
		gen_out(gen, "%\t%\", %\", ",
			1, need_name, need_type_ref->name);
		if (parameters_size == 0) {
			gen_out(gen, "0, (type___reference **)0,\n");
		} else {
			gen_out(gen, "%d, %M__type__references,\n",
				parameters_size, parameters);
		}
		gen_out(gen, "%\t0, (int)(&((%T)0)->%S),\n",
			2, type_ref->name, object_need->field_name);
	}
	gen_out(gen, "};\n");
	gen_out(gen, "\n");
}

/*
 * object_parameter_need(object, field_name, type_ref, heap)
 *	This routine will add the "field_name"/"type_ref" pair to "object"'s
 *	static need list.
 */
LOCAL void
object_parameter_need(
	Object		object,
	Str		field_name,
	Type_ref	type_ref,
	Heap		heap)
{
	Object_need	object_need;

	object_need = object_need_create("??", type_ref, field_name, heap);
	vec_append(Object_need, object->parameter_needs, object_need);
}



/*
 * object_ref_delete(object_ref)
 *	This routine will mark "object_ref" as deleted.
 */
void
object_ref_delete(
	Object_ref	object_ref)
{
	object_ref->deleted = 1;
}

/*
 * object_ref_equal(object_ref1, object_ref2)
 *	This object will return 1 if "object_ref1" is equal to
 *	"object_ref2".  They are equal if they have the same name and
 *	type reference name.
 */
LOCAL int
object_ref_equal(
	Object_ref	object_ref1,
	Object_ref	object_ref2)
{
	assert(object_ref1 != (Object_ref)0);
	assert(object_ref2 != (Object_ref)0);

	return strequal(object_ref1->name, object_ref2->name) &&
	       type_ref_equal(object_ref1->type_ref, object_ref2->type_ref);
}

/*
 * object_ref_hash(object_ref)
 *	This object will return a hash value for "object_ref".
 */
LOCAL int
object_ref_hash(
	Object_ref	object_ref)
{
	return strhash(object_ref->name) +
	       type_ref_hash(object_ref->type_ref);
}

/*
 * object_ref_insert(object_table, name, type_ref, int)
 *	This routine will insert "name"@"type_ref" into "object_table".
 */
Object_ref
object_ref_insert(
	Object_table	object_table,
	Str		name,
	Type_ref	type_ref,
	Type_ref	actual_type_ref,
	int		position)
{
	Heap		heap;
	Object_ref	object_ref;
	Object_ref	ref_key;
	Table(Object_ref, Object_ref) ref_table;

	heap = object_table->heap;
	ref_table = object_table->ref_table;
	ref_key = object_table->ref_key;
	ref_key->name = name;
	ref_key->type_ref = type_ref;
	object_ref = table_lookup(Object_ref, Object_ref, ref_table, ref_key);
	if (object_ref == (Object_ref)0) {
		Object_entry	object_entry;

		object_entry = object_entry_lookup(object_table,
						   name, type_ref);
		if (object_entry == (Object_entry)0) {
			object_entry = object_entry_insert(object_table,
							   name, type_ref,
							   actual_type_ref,
							   position);
		} else if (object_entry->deleted) {
			object_entry->deleted = 0;
		}

		object_ref = heap_allocate(heap, Object_ref);
		object_ref->name = name;
		object_ref->type_ref = type_ref;
		object_ref->actual_type_ref = actual_type_ref;
		object_ref->object_entry = object_entry;
		object_ref->deleted = 0;
		object_ref->used = 0;
		assert(table_insert(Object_ref, Object_ref,
				    ref_table, object_ref, object_ref) == 0);
		vec_append(Object_ref, object_entry->object_refs, object_ref);
	} else if (object_ref->deleted) {
		object_ref->deleted = 0;
		object_ref->object_entry->deleted = 0;
	}
	return object_ref;
}

/*
 * object_ref_lookup(object_table, name, type_ref)
 *	This routine will return the "name"@"type_ref"object reference
 *	from "object_table".  (Object_ref)0 is returned if "name"@"type_ref"
 *	can not be found.
 */
Object_ref
object_ref_lookup(
	Object_table	object_table,
	Str		name,
	Type_ref	type_ref)
{
	Object_entry	object_entry;
	Object_ref	object_ref;
	Object_ref	ref_key;
	Table(Object_ref, Object_ref) ref_table;

	ref_table = object_table->ref_table;
	ref_key = object_table->ref_key;
	ref_key->name = name;
	ref_key->type_ref = type_ref;
	object_ref = table_lookup(Object_ref, Object_ref, ref_table, ref_key);
	if (object_ref == (Object_ref)0) {
		object_entry = object_entry_lookup(object_table,
						   name, type_ref);
		if ((object_entry == (Object_entry)0) &&
		    strequal(name, "??") && type_ref_is_routine(type_ref)) {
			object_ref = object_ref_insert(object_table,
						       name,
						       type_ref,
						       type_ref, /*???*/
						       -1);
		}
		if (object_entry != (Object_entry)0) {
			object_ref = object_ref_insert(object_table,
						name,
						type_ref,
						object_entry->actual_type_ref,
						-1);
		}
	} else {
		if (object_ref->deleted) {
			object_ref = (Object_ref)0;
		}
	}
	return object_ref;
}

/*
 * object_ref_print(object_ref, out_file)
 *	This object will print "object_ref" to "out_file" in human
 *	readable form.
 */
LOCAL void
object_ref_print(
	Object_ref	object_ref,
	Stdio		out_file)
{
	out(out_file, "%s%@:: %r\n", object_ref->name,
	    object_ref->type_ref, object_ref->actual_type_ref);
}

#ifndef lint
/*
 * object_ref_show(object_ref)
 *	This object will print out "object_ref".
 */
void
object_ref_show(
	Object_ref	object_ref)
{
	object_ref_print(object_ref, stdout);
}
#endif /* lint */

/*
 * object_refs_dump(object_table, out_file)
 *	This object will dump the object refs from "object_table" to 
 *	"out_file" in a human readable form.
 */
LOCAL void
object_refs_dump(
	Object_table	object_table,
	Stdio		out_file)
{
	Object_ref	object_ref;
	Vec(Object_ref) object_refs;

	out(out_file, "Object References Table:\n");
	object_refs = table_value_list_extract(Object_ref, Object_ref,
					       object_table->ref_table);
	VEC_LOOP(Object_ref, object_refs, object_ref) {
		if (object_ref->deleted) {
			continue;
		}
		object_ref_print(object_ref, out_file);
	}
	out(out_file, "\n");
}

/*
 * object_static_need(object, field_name, type_ref, heap)
 *	This routine will add the "field_name"/"type_ref" pair to "object"'s
 *	static need list.
 */
LOCAL void
object_static_need(
	Object		object,
	Str		field_name,
	Type_ref	type_ref,
	Heap		heap)
{
	Object_need	object_need;

	object_need = object_need_create("??", type_ref, field_name, heap);
	vec_append(Object_need, object->static_needs, object_need);
}

/*
 * object_table_convert(object_table, convert)
 */
void
object_table_convert(
	Object_table	object_table,
	Convert		convert)
{
	Object		object;
	Vec(Object)	objects;

	objects = object_table->objects;
	VEC_LOOP(Object, objects, object) {
		object_convert(object, convert);
	}
}

/*
 * object_table_create(heap, msg)
 *	 This routine will create and return a new object table.
 */
Object_table
object_table_create(
	Msg		msg,
	Type_tables	type_tables,
	Heap		heap)
{
	Object_table	object_table;

	object_table = heap_allocate(heap, Object_table);
	object_table->entry_key = heap_allocate(heap, Object_entry);
	object_table->entry_table = table_create(Object_entry, Object_entry,
						 10, object_entry_equal,
						 object_entry_hash,
						 (Object_entry)0,
						 heap);
	object_table->heap = heap;
	object_table->msg = msg;
	object_table->object_entrys = vec_create(Object_entry, heap);
	object_table->objects = vec_create(Object, heap);
	object_table->ref_key = heap_allocate(heap, Object_ref);
	object_table->ref_table = table_create(Object_ref, Object_ref,
					       10, object_ref_equal,
					       object_ref_hash,
					       (Object_ref)0,
					       heap);
	object_table->type_tables = type_tables;
	return object_table;
}

/*
 * object_table_dump(object_table, out_file)
 *	This will dump all of the object entries and references in
 *	"object_table" to "out_file" in human readable form.
 */
void
object_table_dump(
	Object_table	object_table,
	Stdio		out_file)
{
	object_entrys_dump(object_table, out_file);
	object_refs_dump(object_table, out_file);
}

/*
 * object_table_extern_gen(object_table)
 *	This routine will generate the extern statements for all of the
 *	non-parameterized objects in "object".
 */
void
object_table_extern_gen(
	Object_table	object_table,
	Gen		gen)
{
	Heap		heap;
	int		is_initial;
	Str		name;
	Object_entry	object_entry;
	Vec(Object_entry) object_entrys;
	Object_ref	object_ref;
	Vec(Object_ref)	object_refs;
	Type_ref	type_ref;

	heap = gen->heap;
	object_entrys = object_table->object_entrys;
	VEC_LOOP(Object_entry, object_entrys, object_entry) {
		if (object_entry->deleted) {
			continue;
		}
		type_ref = object_entry->actual_type_ref;
		if (type_ref_is_parameter(type_ref) ||
		    type_ref_is_routine(type_ref)) {
			continue;
		}
		name = object_entry->name;
		if (strequal(name, "??")) {
			name = "_initial";
		}
		gen_out(gen, "extern %s %s__%s;\n",
			type_ref_string(type_ref, heap),
			type_ref->name, name);
#ifdef OLD
		object_refs = object_entry->object_refs;
		VEC_LOOP(Object_ref, object_refs, object_ref) {
			type_ref = object_ref->type_ref;
			if (object_ref->deleted ||
			    type_ref_is_parameterized(type_ref)) {
				continue;
			}
			name = object_ref->name;
			is_initial = strequal(name, "??");
			if (is_initial) {
				name = "_initial";
			}
			if (!is_initial || !type_ref_is_routine(type_ref)) {
				gen_out(gen, "extern %s %s__%s;\n",
					type_ref_string(type_ref, heap),
					type_ref->name, name);
			}
		}
#endif /* OLD */
	}
}

/*
 * object_table_module_objects_gen(object_table, gen)
 */
int
object_table_module_objects_gen(
	Object_table	 object_table,
	Gen		gen)
{
	int		count;
	Object		object;
	Vec(Object)	objects;
	int		size;

	count = 0;
	objects = object_table->objects;
	size = vec_size(Object, objects);
	if (size > 0) {
		gen_out(gen,
			"static object___object *module___objects[%d] = {\n",
			size);
		VEC_LOOP(Object, objects, object) {
			gen_out(gen, "%\t&%s__%s__object__object,\n", 1,
				object->type_ref->name,
				(strequal(object->name, "??") ?
					"_initial": object->name));
			count++;
		}
		gen_out(gen, "};\n");
		gen_out(gen, "\n");
	}
	return count;
}

/*
 * object_table_read(object_table, in_file)
 *	This routine will read in some constant objects from "in_file"
 *	into "object_table".
 */
void
object_table_read(
	Object_table	object_table,
	Stdio		in_file)
{
	Type_ref	actual_type_ref;
	Heap		heap;
	int		index;
	Str		name;
	int		size;
	Type_ref	type_ref;
	Type_tables	type_tables;

	out_marker_read(in_file, "objects");
	heap = object_table->heap;
	type_tables = object_table->type_tables;
	size = getw(in_file);
	for (index = 0; index < size; index++) {
		name = strread(in_file, heap);
		type_ref = type_ref_read(in_file, heap, type_tables);
		actual_type_ref = type_ref_read(in_file, heap, type_tables);
		(void)object_entry_insert(object_table, name, type_ref,
					  actual_type_ref, -1);
	}
}

/*
 * object_table_write(object_table, out_file, type_tables)
 *	This routine will write the contents of "object_table" to "out_file".
 */
void
object_table_write(
	Object_table	object_table,
	Stdio		out_file,
	Type_tables	type_tables)
{
	Object		object;
	Vec(Object)	objects;

	objects = object_table->objects;
	out_marker_write(out_file, "objects");
	(void)putw(vec_size(Object, objects), out_file);
	VEC_LOOP(Object, objects, object) {
		(void)strwrite(object->name, out_file);
		type_ref_write(object->type_ref, out_file, type_tables);
		type_ref_write(object->type_def->type_ref,
			       out_file, type_tables);
	}

#ifdef OLD 
	Object_entry	object_entry;
	Vec(Object_entry) object_entrys;

	out_marker_write(out_file, "object_entrys");
	object_entrys = object_table->object_entrys;
	(void)putw(vec_size(Object_entry, object_entrys), out_file);
	VEC_LOOP(Object_entry, object_entrys, object_entry) {
		(void)strwrite(object_entry->name, out_file);
		type_ref_write(object_entry->type_ref, out_file, type_tables);
		type_ref_write(object_entry->actual_type_ref,
			       out_file, type_tables);
	}
#endif /* OLD */
}

