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