/* %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 routine_entry objects: */ #ifndef FILE_DEFS_H #include "file_defs.h" #endif #ifndef HEAP_EXPORTS_H #include "heap_exports.h" #endif #ifndef LINT_H #include "lint.h" #endif #ifndef MODULE_TYPES_H #include "module_types.h" #endif #ifndef MSG_EXPORTS_H #include "msg_exports.h" #endif #ifndef OUT_EXPORTS_H #include "out_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 VECTOR_DEFS_H #include "vector_defs.h" #endif LOCAL void routine_entry_print(Routine_entry, Stdio); /* * routine_entry_delete(routine_entry) */ void routine_entry_delete( Routine_entry routine_entry) { assert(!routine_entry->deleted); routine_entry->deleted = 1; } /* * routine_entry_equal(routine_entry1, routine_entry2) * This routine will return 1 if "routine_entry1" is equal to * "routine_entry2"; othwise 0 is returned. */ int routine_entry_equal( Routine_entry routine_entry1, Routine_entry routine_entry2) { return (strequal(routine_entry1->routine_name, routine_entry2->routine_name) && strequal(routine_entry1->type_name, routine_entry2->type_name)); } /* * routine_entry_hash(routine_entry) * This routine will return a hash value for "routine_entry". */ int routine_entry_hash( Routine_entry routine_entry) { return strhash(routine_entry->routine_name) + strhash(routine_entry->type_name); } /* * routine_entry_insert(routine_table, routine_name, type_ref, * type_proto, position, no_error) * This routine will create and insert a routine entry for * "routine_name"@"type_ref" with a prototype of "type_proto" into * "routine_table"; the resulting routine entry is returned. If * "routine_name"@"type_ref" is already in "routine_table", an error * msg is output using "position" and the previously defined * routine entry is returned. */ Routine_entry routine_entry_insert( Routine_table routine_table, Str routine_name, Type_ref type_ref, Type_proto type_proto, int position, int no_error) { Routine_entry entry; Routine_entry entry_key; Table(Routine_entry, Routine_entry) entry_table; Heap heap; Msg msg; Type_refs params; Type_refs parameters; int size; entry_key = routine_table->entry_key; entry_key->routine_name = routine_name; entry_key->type_name = type_ref->name; entry_table = routine_table->entry_table; entry = table_lookup(Routine_entry, Routine_entry, entry_table, entry_key); if (entry == (Routine_entry)0) { parameters = type_ref->parameters; size = type_refs_size(parameters); if (size > 0) { params = routine_table_parameters_get(routine_table, size); assert(type_refs_equal(parameters, params)); #ifdef OLD type_proto = type_proto_replace(type_proto, parameters, params, routine_table->type_tables); #endif /* OLD */ } heap = routine_table->heap; entry = heap_allocate(heap, Routine_entry); entry->deleted = 0; entry->routine = (Routine)0; entry->routine_name = routine_name; entry->type_name = type_ref->name; entry->type_proto = type_proto; entry->routine_refs = vec_create(Routine_ref, heap); entry->used = 0; assert(table_insert(Routine_entry, Routine_entry, entry_table, entry, entry) == 0); vec_append(Routine_entry, routine_table->entrys, entry); } else if (entry->deleted) { entry->deleted = 0; } else if (!no_error) { /* There seems to be a problem with the print routine for routine types. if (type_proto_equal(entry->type_proto, type_proto)) { (void)printf("The prototypes match\n"); } else { (void)printf("The prototypes do not match\n"); (void)printf("First one:\n"); type_proto_show(entry->type_proto); (void)printf("Second one:\n"); type_proto_show(type_proto); } */ msg = routine_table->msg; if (strequal(type_ref->name, "global__")) { /* msg_out(msg, position, */ (void)printf("Warning: Routine %s is being redefined!\n", routine_name); } else { /* msg_out(msg, position, */ (void)printf("Warning: Routine %s@%s is being redefined!\n", routine_name, type_ref->name); } } return entry; } /* * routine_entry_lookup(routine_table, routine_name, type_name, position) * This routine lookup and return the routine entry for * "name"@"type" from "routine_table". If there is no routine * entry for "name"@"type", an error message is output usin "position" * and (Routine_entry)0 is returned. */ Routine_entry routine_entry_lookup( Routine_table routine_table, Str routine_name, Str type_name, int position) { Routine_entry entry; Routine_entry entry_key; Msg msg; entry_key = routine_table->entry_key; entry_key->routine_name = routine_name; entry_key->type_name = type_name; entry = table_lookup(Routine_entry, Routine_entry, routine_table->entry_table, entry_key); if (entry == (Routine_entry)0) { msg = routine_table->msg; if (strequal(type_name, "global__")) { msg_out(msg, position, "Routine %s is undeclared!", routine_name); } else { msg_out(msg, position, "Routine %s@%s is undeclared!", routine_name, type_name); } } return entry; } /* * routine_entry_print(routine_entry, out_file) * This routine will print "routine_entry" to "out_file" in * human readable form. */ LOCAL void routine_entry_print( Routine_entry routine_entry, Stdio out_file) { if (strequal(routine_entry->type_name, "global__")) { out(out_file, "routine %s ", routine_entry->routine_name); } else { out(out_file, "routine %s@%s ", routine_entry->routine_name, routine_entry->type_name); } type_proto_print(routine_entry->type_proto, 1, out_file); } #ifndef lint /* * routine_entry_show(routine_entry) * This routine will print out "routine_entry". */ void routine_entry_show( Routine_entry routine_entry) { routine_entry_print(routine_entry, stdout); } #endif /* lint */ /* * routine_entry_replace(routine_table, name, type_ref, type_proto) * This routine will replace the "type_proto" for "name"@"type_ref" * in "routine_table". */ Routine_entry routine_entry_replace( Routine_table routine_table, Str name, Type_ref type_ref, Type_proto type_proto) { Routine_entry routine_entry; routine_entry = routine_entry_lookup(routine_table, name, type_ref->name, -1); assert(routine_entry != (Routine_entry)0); routine_entry->type_proto = type_proto; return routine_entry; } /* * Routine_entry_used(routine_entry, routine_table) * This routine will mark "routine_entry" as used. */ /* ARGSUSED */ void routine_entry_used( Routine_entry routine_entry, Routine_table routine_table) { routine_entry->used++; } /* * routine_entrys_dump(routine_table, out_file) * This routine will dump the routine entrys from "routine_table" to * "out_file" in a human readable form. */ void routine_entrys_dump( Routine_table routine_table, Stdio out_file) { Routine_entry entry; Vec(Routine_entry) entrys; out(out_file, "Routine Entry Table:\n"); entrys = routine_table->entrys; VEC_LOOP(Routine_entry, entrys, entry) { routine_entry_print(entry, out_file); } out(out_file, "\n"); } /* * routine_entrys_export(routine_table, out_file) * This routine will write out the routine entries in "routine_table" * to "out_file" such that they can be reread in by * "routine_entrys_import". */ void routine_entrys_export( Routine_table routine_table, Stdio out_file) { int index; Routine_entry entry; Vec(Routine_entry) entrys; int size; Type_tables type_tables; type_tables = routine_table->type_tables; entrys = routine_table->entrys; size = vec_size(Routine_entry, entrys); (void)putw(size, out_file); for (index = 0; index < size; index++) { entry = vec_fetch(Routine_entry, entrys, index); (void)strwrite(entry->routine_name, out_file); (void)strwrite(entry->type_name, out_file); type_proto_write(entry->type_proto, out_file, type_tables); } } /* * routine_entrys_import(routine_table, in_file, position) * This routine will import a bunch of routine entrys from "in_file" * into "routine_table". Any error messages are output using * "position". */ void routine_entrys_import( Routine_table routine_table, Stdio in_file, int position) { int count; Heap heap; int index; Str routine_name; Str type_name; Type_proto type_proto; Type_ref type_ref; Type_tables type_tables; count = getw(in_file); heap = routine_table->heap; type_tables = routine_table->type_tables; for (index = 0; index < count; index++) { routine_name = strread(in_file, heap); type_name = strread(in_file, heap); type_proto = type_proto_read(in_file, heap, type_tables); type_ref = type_ref_parameters_create(type_name, type_proto->params, type_tables); (void)routine_entry_insert(routine_table, routine_name, type_ref, type_proto, position, 0); } }