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

#ifndef ERROR_EXPORTS_H
#include "error_exports.h"
#endif

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

#ifndef GENERATE_EXPORTS_H
#include "generate_exports.h"
#endif

#ifndef HEAP_EXPORTS_H
#include "heap_exports.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_EXPORTS_H
#include "object_exports.h"
#endif

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

#ifndef PARSER_EXPORTS_H
#include "parser_exports.h"
#endif

#ifndef ROUTINE_DEFS_H
#include "routine_defs.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_CTYPE_H
#include "unix_ctype.h"
#endif

#ifndef UNIX_MEMORY_H
#include "unix_memory.h"
#endif

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

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

/* Local routines: */

LOCAL void		type_def_enumeration_gen(Type_def, Gen);
LOCAL void		type_def_external_gen(Type_def, Gen);
LOCAL void		type_def_initialization_gen(Type_def, Gen);
LOCAL Type_def		type_def_read(Stdio, Heap, Type_tables, int);
LOCAL void		type_def_structure_gen(Type_def, Gen);
LOCAL void		type_def_write(Type_def, Stdio, Type_tables);
LOCAL void		type_field_print(Type_field, Stdio);
LOCAL Type_field	type_field_read(Stdio, Heap, Type_tables);
LOCAL int		type_field_write(Type_field, Stdio, Type_tables);
LOCAL void		type_fields_print(Type_fields, Stdio, int);
LOCAL Type_fields	type_fields_read(Stdio, Heap, Type_tables);
LOCAL void		type_fields_write(Type_fields, Stdio, Type_tables);
LOCAL void		type_item_print(Type_item, Stdio, int);
LOCAL Type_item		type_item_read(Stdio, Heap, int);
LOCAL int		type_item_write(Type_item, Stdio, int);
LOCAL void		type_items_print(Vec(Type_item), Stdio, int);

/*
 * type_def_create(name, position, type_tables, heap)
 *	This routine will create and return a new type definition object
 *	with values of "name" and "position" allocated from "heap".
 */
/* ARGSUSED */
Type_def
type_def_create(
	Str		name,
	int		position,
	Type_tables	type_tables,
	Heap		heap)
{
	Type_def	type_def;

	type_def = heap_allocate(heap, Type_def);
	type_def->imported = 0;
	type_def->generates = vec_create(Type_predefined, heap);
	type_def->value.undefined = 0;
	type_def->name = name;
	type_def->position = position;
	type_def->routine_name = (Str)0;
	type_def->routine_types = vec_create(Type_routine, heap);
	type_def->structure_needed = 1;
	return type_def;
}

/*
 * type_def_enumeration_gen(type_def, gen)
 *	This routine will generate the structure declarations for "type_def"
 *	using "gen".
 */
LOCAL void
type_def_enumeration_gen(
	Type_def	type_def,
	Gen		gen)
{
	Str		type_def_name;
	int		imported;

	type_def_name = type_def->name;
	imported = type_def->imported;
	switch (type_def->kind) {
	    case Type_kind_enumeration:
	      {
		int		index;
		int		limit;
		Type_item	type_item;
		Str		type_item_name;
		Vec(Type_item)	type_items;
		int		size;

		type_items = type_def->value.enumeration->items;
		gen_out(gen, "enum %s___enum {\n", type_def_name);
		size = vec_size(Type_item, type_items);
		limit = imported ? size : size - 1;
		for (index = 0; index < limit; index++) {
			type_item = vec_fetch(Type_item, type_items, index);
			gen_out(gen, "%\t%s__item__%s,\n", 1,
				type_def_name, type_item->name);
		}
		if (imported) {
			type_item_name = "_none";
		} else {
			type_item = vec_fetch(Type_item, type_items, size - 1);
			type_item_name = type_item->name;
		}
		gen_out(gen, "%\t%s__item__%s\n",
			1, type_def_name, type_item_name);
		gen_out(gen, "};\n");
		break;
	      }
	}
}

/*
 * type_def_external_gen(type_def, gen)
 *	This routine will generate the external type declarations for
 *	"type_def" to "gen".
 */
LOCAL void
type_def_external_gen(
	Type_def	type_def,
	Gen		gen)
{
	Str		type_def_name;

	type_def_name = type_def->name;
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		if (type_def->imported && type_def->structure_needed) {
			gen_out(gen, "static %s___type *%s___convert;\n",
				type_def_name, type_def_name);
			gen_out(gen, "extern int %s__enumeration__size;\n",
				type_def_name);
		}
		break;
	    case Type_kind_external:
		gen_out(gen, "extern void %s__external__initialize(void);\n",
			type_def_name);
		break;
	}
	if (type_ref_is_parameterized(type_def->type_ref)) {
		gen_out(gen, "extern int  %s__object__size;\n", type_def_name);
	}
}

/*
 * type_def_initialization_gen(type_def, gen)
 *	This routine will generate initialization code for "type_def"
 *	to "gen".
 */
LOCAL void
type_def_initialization_gen(
	Type_def	type_def,
	Gen		gen)
{
	Type_enumeration enumeration;
	Str		name;
	int		imported;
	Str		item_name;
	Type_item	item;
	Vec(Type_item)	items;

	imported = type_def->imported;
	name = type_def->name;
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		if (imported && type_def->structure_needed) {
			enumeration = type_def->value.enumeration;
			items = enumeration->items;
			gen_out(gen, "%\t%s___convert = (%s___type *)"
				"run__time__convert__create("
				"%s__enumeration__size, "
				"(int)%s__item___none, %\");\n",
				 1, name, name, name, name, name, name);
			VEC_LOOP(Type_item, items, item) {
				item_name = item->name;
				gen_out(gen, "%\t%s___convert[(int)%s__%s]"
					" = %s__item__%s;\n", 1,
					name, name, item_name,
					name, item_name);
			}
		}
		break;
	    case Type_kind_external:
		if (!imported) {
			gen_out(gen, "%\t%s__external__initialize();\n",
				1, name);
		}
		break;
	    case Type_kind_record:
	    case Type_kind_variant:
		if (!imported &&
		    !type_ref_is_parameterized(type_def->type_ref)) {
			gen_out(gen, "%\t%s__erase(&%s___initial_object);\n",
				1, name, name);
		}
		break;
	}
}

/*
 * type_def_print(type_def, out_file)
 *	This routine will print "type_def" to "out_file".
 */
void
type_def_print(
	Type_def	type_def,
	Stdio		out_file)
{
	Generate	generate;
	Vec(Generate)	generates;
	int		index;
	int		size;

	out(out_file, "%s", type_def->name);
	if (type_ref_is_parameterized(type_def->type_ref)) {
		out(out_file, "[");
		type_refs_print(type_def->type_ref->parameters, out_file);
		out(out_file, "]");
	}
	if (type_def->routine_name != (Str)0) {
		out(out_file, "@%s", type_def->routine_name);
	}
	out(out_file, "%\n", type_def->comment);
	switch (type_def->kind) {
	    case Type_kind_enumeration:
	      {
		Type_enumeration enumeration;

		enumeration = type_def->value.enumeration;
		out(out_file, "%\tenumeration\n", 1);
		type_items_print(enumeration->items, out_file, 2);
		break;
	      }
	    case Type_kind_external:
		out(out_file, "%\texternal\n", 1);
		break;
	    case Type_kind_proto:
	      {
		Type_proto	type_proto;

		type_proto = type_def->value.proto;
		switch (type_proto->kind) {
		    case Type_proto_procedure:
			out(out_file, "%\tprocedure\n", 1);
			break;
		    case Type_proto_iterator:
			out(out_file, "%\titerator\n", 2);

			break;
		    default:
			assert_fail();
		}
		type_refs_keyword_print(type_proto->takes, out_file,
					"takes", 2);
		type_refs_keyword_print(type_proto->returns, out_file,
					"returns", 2);
		type_refs_keyword_print(type_proto->yields, out_file,
					"yields", 2);
		/*XXX: Signals and needs belong here: */
		break;
	      }
	    case Type_kind_record:
	      {
		Type_record	record;

		record = type_def->value.record;
		out(out_file, "%\trecord\n", 1);
		type_fields_print(record->fields, out_file, 2);
		break;
	      }
	    case Type_kind_variant:
	      {
		Type_variant	variant;

		variant = type_def->value.variant;
		out(out_file, "%\tvariant ", 1);
		type_field_print(variant->tag_field, out_file);
		out(out_file, "\n");
		type_fields_print(variant->fields, out_file, 2);
		break;
	      }
	    case Type_kind_undefined:
	    default:
		error_abort("Unknown type");
		break;
	}
	generates = type_def->generates;
	size = vec_size(Generate, generates);
	if (size > 0) {
		out(out_file, "%\tgenerate ", 1);
		for (index = 0; index < size; index++) {
			generate = vec_fetch(Generate,
					     generates, index);
			generate_print(generate, out_file);
			if (index + 1 == size) {
				out(out_file, "\n");
			} else {
				out(out_file, ", ");
			}
		}
	}
	out(out_file, "\n");
}

/*
 * type_def_read(in_file, heap, type_tables, position)
 *	This routine will read in a type from "in_file" using "type_tables'.
 */
LOCAL Type_def
type_def_read(
	Stdio		in_file,
	Heap		heap,
	Type_tables	type_tables,
	int		position)
{
	Type_def	type_def;
	Type_refs	parameters;

	type_def = heap_allocate(heap, Type_def);
	type_def->imported = 1;
	type_def->name = strread(in_file, heap);
	type_def->structure_needed = 0;
	type_def->position = position;
	type_def->generates = vec_create(Type_predefined, heap);
	parameters = type_refs_read(in_file, heap, type_tables);
	type_def->type_ref = type_ref_parameters_create(type_def->name,
							parameters,
							type_tables);
	type_def->kind = (Type_kind)(getc(in_file) & 0xff);
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		type_def->value.enumeration =
			heap_allocate(heap, Type_enumeration);
		type_def->value.enumeration->items =
			vec_read(Type_item, type_item_read, in_file, heap, 0);
		break;
	    case Type_kind_proto:
	      {
		type_def->value.proto = type_proto_read(in_file,
							heap, type_tables);
		break;
	      }
	    case Type_kind_simple:
		type_def->value.simple = 0;
		break;
	    case Type_kind_record:
	      {
		Type_record	record;

		record = heap_allocate(heap, Type_record);
		type_def->value.record = record;
		record->fields = type_fields_read(in_file, heap, type_tables);
		break;
	      }
	    case Type_kind_variant:
	      {
		Type_variant	variant;

		variant = heap_allocate(heap, Type_variant);
		type_def->value.variant = variant;
		variant->tag_field = type_field_read(in_file,
						     heap, type_tables);
		variant->fields = type_fields_read(in_file, heap, type_tables);
		break;
	      }
	    case Type_kind_undefined:
		break;
	    case Type_kind_external:
		break;
	    default:
		error_abort("type_read: unimplemented\n");
	}
	assert(type_def_table_insert(type_tables->type_def_table,
				     type_def) == 0);
	return type_def;
}

/*
 * type_def_structure_gen(type_def, gen)
 *	This routine will generate the structure declarations for "type_def"
 *	using "gen".
 */
LOCAL void
type_def_structure_gen(
	Type_def	type_def,
	Gen		gen)
{
	Str		type_def_name;
	int		imported;

	type_def_name = type_def->name;
	imported = type_def->imported;
	switch (type_def->kind) {
	    case Type_kind_record:
	      {
		Heap		heap;
		Type_field	field;
		Type_fields	fields;

		if (imported) {
			break;
		}
		heap = gen->heap;
		gen_out(gen, "struct %s___record {\n", type_def_name);
		fields = type_def->value.record->fields;
		VEC_LOOP(Type_field, fields, field) {
			if (type_ref_is_parameter(field->type_ref)) {
				gen_out(gen, "%\tvoid *%S;\n", 1, field->name);
			} else {
				gen_out(gen, "%\t%s %S;\n", 1,
				   type_ref_string(field->type_ref, heap),
				   field->name);
			}
		}
		gen_out(gen, "};\n");
		if (!imported) {
			gen_out(gen, "int %s__object__size = "
				"sizeof(struct %s___record);\n",
				type_def_name, type_def_name);
		}
		break;
	      }
	    case Type_kind_variant:
	      {
		Type_field	field;
		Type_variant	variant;

		variant = type_def->value.variant;
		gen_out(gen, "union %s___variant {\n", type_def_name);
		gen_out(gen, "%\tdouble _entire_;\n", 1);
		field = variant->tag_field;
		gen_out(gen, "%\tstruct {\n", 1);
		gen_out(gen, "%\tvoid *_value_;\n", 2);
		gen_out(gen, "%\t%T %s;\n",
			2, field->type_ref->name, field->name);
		gen_out(gen, "%\t} _tag_;\n", 1);
		VEC_LOOP(Type_field, variant->fields, field) {
			if (imported) {
				gen_out(gen, "%\tvoid *%S;\n", 1, field->name);
			} else {
				gen_out(gen, "%\t%T %S;\n",
					1, field->type_ref->name, field->name);
			}
		}
		gen_out(gen, "};\n");
		if (!imported) {
			gen_out(gen, "int %s__object__size = "
				"sizeof(union %s___variant);\n",
				type_def_name, type_def_name);
		}
		break;
	      }
	}
}

/*
 * type_def_structure_needed(type_def)
 *	This routine will mark "type_def" so that its structure is in the
 *	output file.
 */
void
type_def_structure_needed(
	Type_def	type_def)
{
	type_def->structure_needed = 1;
}

/*
 * type_def_typedef_gen(type_def, gen)
 *	This routine will output the typedef associated with "type_def"
 *	using "gen".
 */
LOCAL void
type_def_typedef_gen(
	Type_def	type_def,
	Gen		gen)
{
	Str		type_name;

	type_name = type_def->name;
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		gen_out(gen, "typedef enum %s___enum %T;\n",
			type_name, type_name);
		break;
	    case Type_kind_record:
		gen_out(gen, "typedef struct %s___record *%T;\n",
			type_name, type_name);
		break;
	    case Type_kind_variant:
		gen_out(gen, "typedef union %s___variant *%T;\n",
			type_name, type_name);
		break;
	    case Type_kind_external:
	      {
		Str	translated;
		int	size;

		translated = type_translate(type_name, gen->heap);
		size = strlen(type_name);
		if ((strncmp(translated, type_name, size) == 0) &&
		    (strequal(translated + size, "___type"))) {
			gen_out(gen, "typedef void *%T;\n", type_name);
		} else {
			gen_out(gen, "typedef %s %T;\n", translated, type_name);
		}
		break;
	      }
	    default:
		assert_fail();
	}
}

/*
 * type_def_write(type_def, out_file, type_tables)
 *	This routine will write "type_def" to "out_file".  0 is always
 *	returned.
 */
LOCAL void
type_def_write(
 	Type_def	type_def,
	Stdio		out_file,
	Type_tables	type_tables)
{
	(void)strwrite(type_def->name, out_file);
	type_refs_write(type_def->type_ref->parameters, out_file, type_tables);
	(void)putc((char)type_def->kind, out_file);
	switch (type_def->kind) {
	    case Type_kind_enumeration:
		vec_write(Type_item, type_def->value.enumeration->items,
			  type_item_write, out_file, 0);
		break;
	    case Type_kind_proto:
		type_proto_write(type_def->value.proto, out_file, type_tables);
		break;
	    case Type_kind_simple:
		break;
	    case Type_kind_record:
		type_fields_write(type_def->value.record->fields,
				  out_file, type_tables);
		break;
	    case Type_kind_variant:
		(void)type_field_write(type_def->value.variant->tag_field,
				       out_file, type_tables);
		type_fields_write(type_def->value.record->fields,
				  out_file, type_tables);
		break;
	    case Type_kind_undefined:
		break;
	    case Type_kind_external:
		break;
	    default:
		error_abort("type_def_write: unimplemented\n");
	}
}

/*
 * Type_defs routines:
 */

/*
 * type_defs_dump(type_defs, out_file)
 *	This routine will dump the contents of each type definition in
 *	"type_defs" to "out_file" in human readable form.	
 */
void
type_defs_dump(
	Type_defs	type_defs,
	Stdio		out_file)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_print(type_def, out_file);
	}
}

/*
 * type_defs_enumeration_gen(type_defs, gen)
 *	This will generate all of the enumeration type definitions for
 *	each type definition in "type_defs" to "gen".
 */
void
type_defs_enumeration_gen(
	Type_defs	type_defs,
	Gen		gen)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_enumeration_gen(type_def, gen);
	}
}

/*
 * type_defs_external_gen(type_defs, gen)
 *	This routine will generate the external type declarations for
 *	each type definition in "type_defs" to "gen".
 */
void
type_defs_external_gen(
	Type_defs	type_defs,
	Gen		gen)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_external_gen(type_def, gen);
	}
}

/*
 * type_defs_initializion_gen(type_defs, gen)
 *	This routine will generate any needed initialization code
 *	for each type definition in "type_defs" to "gen".
 */
void
type_defs_initialization_gen(
	Type_defs	type_defs,
	Gen		gen)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_initialization_gen(type_def, gen);
	}
}

/*
 * type_defs_insert(type_defs, type_tables, object_table, heap)
 *	This routine will insert each type definition in "type_defs"
 *	into the appropriate table in "type_tables".  Any implied
 *	types resulting from a variant are appended to "type_defs".
 */
void
type_defs_insert(
	Type_defs	type_defs,
	Type_tables	type_tables,
	Object_table	object_table,
	Msg		msg,
	Heap		heap)
{
	Type_def	previous_type_def;
	Type_def	type_def;
	Type_def_table	type_def_table;
	Type_defs	implied_type_defs;

	implied_type_defs = vec_create(Type_def, heap);
	type_def_table = type_tables->type_def_table;
	VEC_LOOP(Type_def, type_defs, type_def) {
		if (type_def->imported) {
			continue;
		}

		/* Deal with implied type definitions: */
		switch (type_def->kind) {
		    case Type_kind_enumeration:
		      {
			int			position;
			Type_enumeration	type_enumeration;
			Type_item		type_item;
			Vec(Type_item)		type_items;
			Type_ref		type_ref;

			type_ref = type_def->type_ref;
			position = type_def->position;
			type_enumeration = type_def->value.enumeration;
			type_items = type_enumeration->items;
			VEC_LOOP(Type_item, type_items, type_item) {
				object_create(object_table, type_item->name,
					      type_ref, type_def, position);
			}
			object_create(object_table, "first",
				      type_ref, type_def, position);
			object_create(object_table, "last",
				      type_ref, type_def, position);
			break;
		      }
		    case Type_kind_variant:
		      {
			Type_variant	variant;
			Type_field	tag_field;
			Str		tag_type_name;
			Type_def	tag_type_def;

			variant = type_def->value.variant;
			tag_field = variant->tag_field;
			tag_type_name = tag_field->type_ref->name;
			tag_type_def = type_def_table_lookup(type_def_table,
							     tag_type_name);
			if (tag_type_def == (Type_def)0) {
				/* Create the associated enumeration type: */
				Type_enumeration enumeration;
				Type_field	field;
				Type_fields	fields;
				Type_item	item;
				Vec(Type_item)	items;
				int		item_value;
				Type_ref	type_ref;

				tag_type_def = type_def_create(tag_type_name,
							type_def->position,
							type_tables,
							heap);
				item_value = 0;
				items = vec_create(Type_item, heap);
				fields = variant->fields;
				VEC_LOOP(Type_field, fields, field) {
					item = heap_allocate(heap, Type_item);
					item->comment = (Str)0;
					item->name = field->name;
					item->position = field->position;
					item->value = item_value++;
					vec_append(Type_item, items, item);
				}
				enumeration = heap_allocate(heap,
							    Type_enumeration);
				enumeration->items = items;
				tag_type_def->value.enumeration = enumeration;
				tag_type_def->kind = Type_kind_enumeration;
				type_ref = type_ref_create(tag_type_def->name,
							   type_tables);
				tag_type_def->type_ref = type_ref;
				vec_append(Type_def, implied_type_defs,
					   tag_type_def);
				assert(type_def_table_insert(type_def_table,
							tag_type_def) == 0);
			} else {
				/* Should check for consistency: */
			}
			break;
		      }
		}
	}

	if (!vec_empty(Type_def, implied_type_defs)) {
		type_defs_insert(implied_type_defs, type_tables,
				 object_table, msg, heap);
		vec_vec_append(Type_def, type_defs, implied_type_defs);
	}
}

/*
 * type_defs_read(in_file, heap, type_tables, position)
 *	This routine will read in and return a list of type definitions
 *	from "in_file" using "heap" and "type_tables" for allocation
 *	purposes.  "position" is the assigned to each type definition.
 */
Type_defs
type_defs_read(
	Stdio		in_file,
	Heap		heap,
	Type_tables	type_tables,
	int		position)
{
	int		index;
	int		size;
	Type_def	type_def;
	Type_defs	type_defs;

	type_defs = vec_create(Type_defs, heap);
	size = getw(in_file);
	for (index = 0; index < size; index++) {
		type_def = type_def_read(in_file, heap, type_tables, position);
		vec_append(Type_def, type_defs, type_def);
	}
	return type_defs;
}

/*
 * type_defs_structure_gen(type_defs, gen)
 *	This will generate all of the type defintions and get/set/new
 *	routines for each type defintion in "type_defs" using "gen".
 */
void
type_defs_structure_gen(
	Type_defs	type_defs,
	Gen		gen)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_structure_gen(type_def, gen);
	}
	gen_out(gen, "\n");

	VEC_LOOP(Type_def, type_defs, type_def) {
		if (!type_def->imported) {
			type_def_initial_object_gen(type_def, gen);
		}
	}
	gen_out(gen, "\n");
}

/*
 * type_defs_typedef_gen(type_defs, gen)
 *	This routine will generate all of the typedef's for each type
 *	definition in "typedefs" using "gen".
 */
void
type_defs_typedef_gen(
	Type_defs	type_defs,
	Gen		gen)
{
	Type_def	type_def;

	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_typedef_gen(type_def, gen);
	}
}

/*
 * Type_def_table routines:
 */

/*
 * type_def_table_create(heap)
 *	This routine will return a new type definition table allocated from
 *	"heap".
 */
Type_def_table
type_def_table_create(
	Heap		heap)
{
	Type_def_table	type_def_table;

	type_def_table = heap_allocate(heap, Type_def_table);
	type_def_table->table = table_create(Str, Type_def, 100,
					     strequal, strhash,
					     (Type_def)0, heap);
	return type_def_table;
}

/*
 * type_def_table_lookup(type_def_table, type_name)
 *	This routine will return the type defintion associated with "type_name"
 *	in "type_def_table"; otherwise, (Type_def)0 is returned.
 */
Type_def
type_def_table_lookup(
	Type_def_table	type_def_table,
	Str		type_name)
{
	return table_lookup(Str, Type_def, type_def_table->table, type_name);
}

/*
 * type_def_table_insert(type_def_table, type_name, type_def)
 *	This routine will insert "type_def" into "type_def_table" under
 *	"type_name".  1 is returned if "type_name" is already in
 *	"type_def_table"; otherwise, 0 is returned.
 */
int
type_def_table_insert(
	Type_def_table	type_def_table,
	Type_def	type_def)
{
	return table_insert(Str, Type_def,
			    type_def_table->table, type_def->name, type_def);
}

/*
 * type_defs_write(type_defs, out_file, type_tables)
 *	This routine will write each type definition in "type_defs"
 *	to "out_file" using "type_tables".
 */
void
type_defs_write(
	Type_defs	type_defs,
	Stdio		out_file,
	Type_tables	type_tables)
{
	Type_def	type_def;

	(void)putw(vec_size(Type_def, type_defs), out_file);
	VEC_LOOP(Type_def, type_defs, type_def) {
		type_def_write(type_def, out_file, type_tables);
	}
}

/*
 * Type_field routines;
 */

/*
 * type_field_print(type_field, out_file)
 *	This will print "type_field" to "out_file".
 */
LOCAL void
type_field_print(
	Type_field	type_field,
	Stdio		out_file)
{
	out(out_file, "%s %r", type_field->name, type_field->type_ref);
}

/*
 * type_field_read(in_file, heap, type_tables)
 *	This routine will read in and return a type field from "in_file" 
 *	using "type_tables".
 */
LOCAL Type_field
type_field_read(
	Stdio		in_file,
	Heap		heap,
	Type_tables	type_tables)
{
	Type_field	type_field;

	type_field = heap_allocate(heap, Type_field);
	type_field->name = strread(in_file, heap);
	type_field->type_ref = type_ref_read(in_file, heap, type_tables);
	return type_field;
}

/*
 * type_field_write(type_field, out_file, type_tables)
 *	This routine will write "type_field" to "out_file".  0 is always
 *	returned.
 */
/* ARGSUSED */
LOCAL int
type_field_write(
	Type_field	type_field,
	Stdio		out_file,
	Type_tables	type_tables)
{
	(void)strwrite(type_field->name, out_file);
	type_ref_write(type_field->type_ref, out_file, type_tables);
	return 0;
}

/*
 * Type_fields routines:
 */

/*
 * type_fields_print(type_fields, gen, indent)
 *	This routine will print each field in "type_fields" to "gen" indented
 *	by "indent".
 */
LOCAL void
type_fields_print(
	Type_fields	type_fields,
	Stdio		out_file,
	int		indent)
{
	Type_field	type_field;

	VEC_LOOP(Type_field, type_fields, type_field) {
		out(out_file, "%\t", indent);
		type_field_print(type_field, out_file);
		out(out_file, "\n");
	}
}

/*
 * type_fields_read(in_file, heap, type_tables)
 *	This routine will read in a vector of type fields from "in_file" 
 *	using "type_tables".
 */
LOCAL Type_fields
type_fields_read(
	Stdio		in_file,
	Heap		heap,
	Type_tables	type_tables)
{
	Type_fields	type_fields;

	type_fields = vec_read(Type_field, type_field_read,
			       in_file, heap, type_tables);
	return type_fields;
}

/*
 * type_fields_write(fields, out_file, type_tables)
 *	This routine will write "fields" to "out_file".
 */
LOCAL void
type_fields_write(
	Type_fields	type_fields,
	Stdio		out_file,
	Type_tables	type_tables)
{
	vec_write(Type_field, type_fields,
		  type_field_write, out_file, type_tables);
}

/*
 * Type_item routines:
 */

/*
 * type_item_print(type_item, out_file, indent)
 *	This routine will print "type_item" to "out_file indented by "indent".
 */
void
type_item_print(
	Type_item	type_item,
	Stdio		out_file,
	int		indent)
{
	out(out_file, "%\t%s\n", indent, type_item->name);
}

/*
 * type_item_read(in_file, heap, zilch)
 *	This routine will read in a type item from "in_file" allocated from
 *	"heap".
 */
/* ARGSUSED */
LOCAL Type_item
type_item_read(
	Stdio		in_file,
	Heap		heap,
	int		zilch)
{
	Type_item	type_item;

	type_item = heap_allocate(heap, Type_item);
	type_item->name = strread(in_file, heap);	
	type_item->value = getw(in_file);
	return type_item;
}

/*
 * type_item_write(type_item, out_file, zilch)
 *	This routine will write "type_item" to "out_file".  0 is
 *	always returned.
 */
/* ARGSUSED */
LOCAL int
type_item_write(
	Type_item	type_item,
	Stdio		out_file,
	int		zilch)
{
	(void)strwrite(type_item->name, out_file);
	(void)putw(type_item->value, out_file);
	return 0;
}

/*
 * Type_items routines:
 */

/*
 * type_items_print(type_items, out_file, indent)
 *	This routine will print out each type item in "type_items" to
 *	"out_file" indented by "indent".
 */
LOCAL void
type_items_print(
	Vec(Type_item)	type_items,
	Stdio		out_file,
	int		indent)
{
	Type_item	type_item;

	VEC_LOOP(Type_item, type_items, type_item) {
		type_item_print(type_item, out_file, indent);
	}
}

