/*
// Full copyright information is available in the file ../doc/CREDITS
*/
#ifndef cdc_object_h
#define cdc_object_h
#include "file.h"
struct Obj {
cList * parents;
cList * children;
/* Variables are stored in a table, with index threads starting at the
* hash table entries. There is also an index thread for blanks. This
* way we can write the hash table to disk easily. */
struct {
Var * tab;
Int * hashtab;
Int blanks;
Int size;
} vars;
/* Methods are also stored in a table. Since methods are fairly big, we
* store a table of pointers to methods so that we don't waste lots of
* space. */
struct {
struct mptr {
Method * m;
Int next;
} * tab;
Int * hashtab;
Int blanks;
Int size;
} methods;
/* Table for string references in methods. */
String_entry *strings;
Int num_strings;
Int strings_size;
/* Table for identifier references in methods. */
Ident_entry *idents;
Int num_idents;
Int idents_size;
/* Information for the cache. */
cObjnum objnum;
Int refs;
char dirty; /* Flag: Object has been modified. */
char dead; /* Flag: Object has been destroyed. */
Int ucounter; /* counter: Object references */
uLong search; /* Last cache search to visit this */
Ident objname; /* object name */
/* Pointers to next and previous objects in cache chain. */
Obj * next;
Obj * prev;
/* i/o pointers for faster lookup, only valid in the cache */
Conn * conn;
filec_t * file;
};
/* The object string and identifier tables simplify storage of strings and
* identifiers for methods. When we want to free an object without destroying
* it, we don't need to scan the method code to determine what strings and
* identifiers to free, and we don't need to do any modification of method
* code to reflect a new identifier table when we reload the object. */
/* We keep a ref count on object string entries because we have to know when
* to delete it from the object. As far as the string is concerned, all these
* references are really just one reference, since we only duplicate or discard
* when we're adding or removing a string from an object. */
struct string_entry {
cStr *str;
Int refs;
};
/* Similar logic for identifier references. */
struct ident_entry {
Ident id;
Int refs;
};
struct var {
Ident name;
cObjnum cclass;
cData val;
Int next;
};
struct Method {
Ident name;
Obj *object;
Int num_args;
Object_ident *argnames;
Object_ident rest;
Int num_vars;
Object_ident *varnames;
Int num_opcodes;
Long *opcodes;
Int num_error_lists;
Error_list *error_lists;
/* if this is a native method, it is > 0 and is relative to the native
method's spot in the lookup table */
Int native;
/* consolidate the following into bit flags */
Int m_access; /* public, protected, private */
Int m_flags; /* overridable, synchronized, locked */
Int refs;
};
/* access: only one at a time */
#define MS_PUBLIC 1 /* public */
#define MS_PROTECTED 2 /* protected */
#define MS_PRIVATE 4 /* private */
#define MS_ROOT 8 /* root */
#define MS_DRIVER 16 /* sender() and caller() are 0 */
#define MS_FROB 32 /* called from a frob: (<$frob, #[]>).method() */
/* perhaps create a method reference to call a task on for perm
checking, with sender() and caller()? */
/* flags: any number of the following */
#define MF_NONE 0 /* No flags */
#define MF_NOOVER 1 /* not overridable */
#define MF_SYNC 2 /* synchronized */
#define MF_LOCK 4 /* locked */
#define MF_NATIVE 8 /* native */
#define MF_FORK 16 /* fork */
#define MF_UNDF2 32 /* undefined */
#define MF_UNDF3 64 /* undefined */
#define MF_UNDF4 128 /* undefined */
#define FROB_YES 1
#define FROB_NO 0
#define FROB_ANY 2
#define FROB_RETRY -1
struct error_list {
Int num_errors;
Int *error_ids;
};
#define START_SEARCH_AT 0 /* zero is the 'unsearched' number */
#define RESET_SEARCH_AT MAX_ULONG
#define SEARCHED(_obj__) (_obj__->search == cache_search)
#define HAVE_SEARCHED(_obj__) (_obj__->search = cache_search)
#define START_SEARCH() \
if (cache_search == RESET_SEARCH_AT) \
cache_search = START_SEARCH_AT; \
cache_search++
#define END_SEARCH()
#define RETRIEVE_ONCE_OR_RETURN(_obj__, _objnum__) \
_obj__ = cache_retrieve(_objnum__); \
if (SEARCHED(_obj__)) { \
cache_discard(_obj__); \
return; \
} \
HAVE_SEARCHED(_obj__)
/* ..................................................................... */
/* function prototypes */
#ifdef _object_
/* We use MALLOC_DELTA to keep table sizes to 32 bytes less than a power of
* two, if pointers and Longs are four bytes. */
/* HACKNOTE: ARRRG, BAD BAD BAD */
#define MALLOC_DELTA 8
#define ANCTEMP_STARTING_SIZE (32 - MALLOC_DELTA)
#define VAR_STARTING_SIZE (16 - MALLOC_DELTA - 1)
#define METHOD_STARTING_SIZE (16 - MALLOC_DELTA - 1)
#define STRING_STARTING_SIZE (16 - MALLOC_DELTA)
#define IDENTS_STARTING_SIZE (16 - MALLOC_DELTA)
#define METHOD_CACHE_SIZE 2551
/* ..................................................................... */
/* types and structures */
/* cData for method searches. */
typedef struct search_params Search_params;
struct search_params {
uLong name;
Long stop_at;
Int done;
Bool is_frob;
Method * last_method_found;
};
struct {
Long stamp;
cObjnum objnum;
Ident name;
Bool is_frob;
cObjnum after;
cObjnum loc;
} method_cache[METHOD_CACHE_SIZE];
/* ..................................................................... */
/* function prototypes */
static void object_update_parents(Obj *object,
cList *(*list_op)(cList *, cData *));
static Int object_has_ancestor_aux(Long objnum, Long ancestor);
static Var *object_create_var(Obj *object, Long cclass, Long name);
static Var *object_find_var(Obj *object, Long cclass, Long name);
static Method * method_cache_check(Long objnum, Long name, Long after, Bool is_frob);
static void method_cache_set(Long objnum, Long name, Long after, Long loc, Bool is_frob);
static void search_object(Long objnum, Search_params *params);
static void method_delete_code_refs(Method * method);
Obj *object_new(Long objnum, cList *parents);
void object_free(Obj *object);
void object_destroy(Obj *object);
void object_construct_ancprec(Obj *object);
Int object_change_parents(Obj *object, cList *parents);
cList * object_ancestors_breadth(Long objnum);
cList * object_ancestors_depth(Long objnum);
cList * object_descendants(Long objnum);
Int object_has_ancestor(Long objnum, Long ancestor);
void object_reconstruct_descendent_ancprec(Long objnum);
Int object_add_string(Obj *object, cStr *string);
void object_discard_string(Obj *object, Int ind);
cStr *object_get_string(Obj *object, Int ind);
Int object_add_ident(Obj *object, char *ident);
void object_discard_ident(Obj *object, Int ind);
Long object_get_ident(Obj *object, Int ind);
Long object_add_var(Obj *object, Long name);
Long object_del_var(Obj *object, Long name);
Long object_assign_var(Obj *object, Obj *cclass, Long name, cData *val);
Long object_delete_var(Obj *object, Obj *cclass, Long name);
Long object_retrieve_var(Obj *object, Obj *cclass, Long name,
cData *ret);
Long object_default_var(Obj *object, Obj *cclass, Long name,
cData *ret);
Long object_inherited_var(Obj *object, Obj *cclass, Long name,
cData *ret);
void object_put_var(Obj *object, Long cclass, Long name, cData *val);
Method * object_find_method(Long objnum, Long name, Bool is_frob);
Method * object_find_method_local(Obj *object, Long name, Bool is_frob);
Method * object_find_next_method(Long objnum, Long name, Long after, Bool is_frob);
Int object_rename_method(Obj * object, Long oname, Long nname);
void object_add_method(Obj *object, Long name, Method *method);
Int object_del_method(Obj *object, Long name);
cList *object_list_method(Obj *object, Long name, Int indent, int fflags);
Method * method_new(void);
void method_free(Method *method);
Method *method_dup(Method *method);
void method_discard(Method *method);
Int object_set_objname(Obj * object, Long name);
Int object_del_objname(Obj * object);
/* ..................................................................... */
/* global variables */
/* Count for keeping track of of already-searched objects during searches. */
uLong cache_search;
/* Keeps track of objnum for next object in database. */
Long db_top;
/* Validity count for method cache (incrementing this count invalidates all
* cache entries. */
static Int cur_stamp = 1;
#else /* _object_ */
extern Obj *object_new(Long objnum, cList *parents);
extern void object_free(Obj *object);
extern void object_destroy(Obj *object);
extern void object_construct_ancprec(Obj *object);
extern Int object_change_parents(Obj *object, cList *parents);
extern cList *object_ancestors_breadth(Long objnum);
extern cList *object_ancestors_depth(Long objnum);
extern cList *object_descendants(Long objnum);
extern Int object_has_ancestor(Long objnum, Long ancestor);
extern void object_reconstruct_descendent_ancprec(Long objnum);
extern Int object_add_string(Obj *object, cStr *string);
extern void object_discard_string(Obj *object, Int ind);
extern cStr *object_get_string(Obj *object, Int ind);
extern Int object_add_ident(Obj *object, char *ident);
extern void object_discard_ident(Obj *object, Int ind);
extern Long object_get_ident(Obj *object, Int ind);
extern Long object_add_var(Obj *object, Long name);
extern Long object_del_var(Obj *object, Long name);
extern Long object_assign_var(Obj *object, Obj *cclass, Long name,
cData *val);
extern Long object_delete_var(Obj *object, Obj *cclass, Long name);
extern Long object_retrieve_var(Obj *object, Obj *cclass, Long name,
cData *ret);
extern Long object_default_var(Obj *object, Obj *cclass, Long name,
cData *ret);
extern Long object_inherited_var(Obj *object, Obj *cclass, Long name,
cData *ret);
extern void object_put_var(Obj *object, Long cclass, Long name,
cData *val);
extern Method *object_find_method(Long objnum, Long name, Bool is_frob);
extern Method *object_find_method_local(Obj * obj, Long name, Bool is_frob);
extern Method *object_find_next_method(Long objnum, Long name, Long after, Bool is_frob);
extern Int object_rename_method(Obj * object, Long oname, Long nname);
extern void object_add_method(Obj *object, Long name, Method *method);
extern Int object_del_method(Obj *object, Long name);
extern cList *object_list_method(Obj *object, Long name, Int indent,
int fflags);
extern void method_free(Method *method);
extern Method *method_dup(Method *method);
extern void method_discard(Method *method);
extern Int object_set_objname(Obj * object, Long name);
extern Int object_del_objname(Obj * object);
extern Int object_get_method_flags(Obj * object, Long name);
extern Int object_get_method_access(Obj * object, Long name);
extern Int object_set_method_flags(Obj * object, Long name, Int flags);
extern Int object_set_method_access(Obj * object, Long name, Int access);
/* variables */
extern Long db_top;
extern uLong cache_search;
#endif /* _object_ */
#endif /* _object_h_ */