<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki.lostsouls.org/w/skins/common/feed.css"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://wiki.lostsouls.org/w/index.php?action=history&amp;feed=atom&amp;title=Man_descriptors_core</id>
		<title>Man descriptors core - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.lostsouls.org/w/index.php?action=history&amp;feed=atom&amp;title=Man_descriptors_core"/>
		<link rel="alternate" type="text/html" href="http://wiki.lostsouls.org/w/index.php?title=Man_descriptors_core&amp;action=history"/>
		<updated>2026-05-03T11:41:45Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.8.2</generator>

	<entry>
		<id>http://wiki.lostsouls.org/w/index.php?title=Man_descriptors_core&amp;diff=3983&amp;oldid=prev</id>
		<title>Laine at 21:44, 11 June 2007</title>
		<link rel="alternate" type="text/html" href="http://wiki.lostsouls.org/w/index.php?title=Man_descriptors_core&amp;diff=3983&amp;oldid=prev"/>
				<updated>2007-06-11T21:44:20Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Files==&lt;br /&gt;
&lt;br /&gt;
 /daemon/descriptor.c&lt;br /&gt;
 /std/def/descriptor.c&lt;br /&gt;
 /def/descriptor/&lt;br /&gt;
&lt;br /&gt;
==Description==&lt;br /&gt;
&lt;br /&gt;
This document describes the internal workings of the descriptor system for&lt;br /&gt;
core systems developers who need to maintain existing descriptor types or&lt;br /&gt;
create new ones.  If you are not familiar with the user-level perspective on&lt;br /&gt;
descriptors as described in 'man descriptors', you should probably review it&lt;br /&gt;
before proceeding.&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
&lt;br /&gt;
Descriptors are array-based data structures that closely resemble MudOS&lt;br /&gt;
classes or C structs in applicability, with some object-like functionality&lt;br /&gt;
layered on through the availability of functions implemented in the descriptor&lt;br /&gt;
definition object, somewhat like Perl's object support.  Each descriptor type&lt;br /&gt;
definition in /def/descriptor determines the characteristics of a class of&lt;br /&gt;
descriptors, and each has a corresponding automatically-generated header file&lt;br /&gt;
in /lib/descriptors.  (These header files should not be manually edited; if&lt;br /&gt;
they are, the changes will be lost the next time the descriptor definition&lt;br /&gt;
loads.)&lt;br /&gt;
&lt;br /&gt;
===Adding a New Descriptor Type===&lt;br /&gt;
&lt;br /&gt;
Like other /def mechanisms, descriptors have a header file, in this case&lt;br /&gt;
/lib/descriptors.h, and a broker daemon, /daemon/descriptor.c.  When adding a&lt;br /&gt;
new descriptor type, it is necessary to give it a macro code (as seen in the&lt;br /&gt;
list at the top of descriptors.h).  Follow these steps:&lt;br /&gt;
&lt;br /&gt;
1) Create a line that #defines the value of the new descriptor type's&lt;br /&gt;
macros as the current value of Descriptors_Count plus one.&lt;br /&gt;
&lt;br /&gt;
2) Insert this line into the macro list according to alphabetical order.&lt;br /&gt;
&lt;br /&gt;
3) Increment the values of Descriptors_Count and Descriptors_Array_Size&lt;br /&gt;
by one.&lt;br /&gt;
&lt;br /&gt;
It is important that you resist any temptation to renumber the existing&lt;br /&gt;
descriptor types, because the integer tags that identify descriptors as of a&lt;br /&gt;
particular type are determined from these codes, and those tags are, in some&lt;br /&gt;
cases, saved and restored.  Changing these codes would, therefore, cause a&lt;br /&gt;
great deal of trouble.  Be aware that the same kind of trouble can be caused&lt;br /&gt;
by adding fields to or removing fields from descriptors; when doing so, you&lt;br /&gt;
need to be aware of whether the descriptor type you're working with is saved&lt;br /&gt;
or not.&lt;br /&gt;
&lt;br /&gt;
===Descriptor Definitions===&lt;br /&gt;
&lt;br /&gt;
The meat of the descriptor type, of course, is in the descriptor definition&lt;br /&gt;
itself.  These all inherit /std/def/descriptor and are configured using the&lt;br /&gt;
following functions:&lt;br /&gt;
&lt;br /&gt;
void set_descriptor(int code)&lt;br /&gt;
&lt;br /&gt;
Sets the definition's descriptor code, using the appropriate macro from&lt;br /&gt;
descriptors.h.  (Required.)&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_name(string name)&lt;br /&gt;
&lt;br /&gt;
Sets the string name of the descriptor.  This should correspond to the&lt;br /&gt;
macro and the name of the definition file; that is, if your name is &amp;quot;example&amp;quot;,&lt;br /&gt;
your macro should be Descriptor_Example and your filename should be example.c.&lt;br /&gt;
If either the filename or the macro does not match, pervasive errors will make&lt;br /&gt;
your descriptor type almost completely unusable.  A warning will be issued if&lt;br /&gt;
the filename does not match.  (Required.)&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_public_field_names(string array names)&lt;br /&gt;
&lt;br /&gt;
Sets the string names of the descriptor's public fields.  The system will&lt;br /&gt;
automatically generate the corresponding macro names from these.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_internal_field_names(string array names)&lt;br /&gt;
&lt;br /&gt;
Sets the string names of the descriptor's internal fields.  The system will&lt;br /&gt;
automatically generate the corresponding macro names from these.  Be aware that&lt;br /&gt;
an extra, standard internal field named &amp;quot;tag&amp;quot; is generated for all descriptors;&lt;br /&gt;
because of this, the field name &amp;quot;tag&amp;quot; is reserved.  The tag field is always&lt;br /&gt;
defined so that it is the last non-virtual field in the descriptor.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_virtual_field_names(string array names)&lt;br /&gt;
&lt;br /&gt;
Sets the string names of the descriptor's virtual fields.  The system will&lt;br /&gt;
automatically generate the corresponding macro names from these.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_preload_field_names(string array names)&lt;br /&gt;
&lt;br /&gt;
Sets a list of fields that need to be &amp;quot;high-priority&amp;quot; loaded, before other&lt;br /&gt;
fields are processed.  An example is the shape descriptor's type field, which&lt;br /&gt;
must be preloaded so it can control which virtual fields are available.  These&lt;br /&gt;
must be public fields.  If you specify virtual or internal fields or unknown&lt;br /&gt;
field names, an error will be raised.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_field_aliases(mapping aliases)&lt;br /&gt;
&lt;br /&gt;
Defines a set of alternate names which you wish one or more fields to be&lt;br /&gt;
addressable by.  The keys in the mapping are the string field names of the&lt;br /&gt;
aliases and the values are the string field names of the target fields.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_field_validate(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure which can be used to control the values that can be&lt;br /&gt;
assigned to fields.  The closure given will receive arguments of 1) the&lt;br /&gt;
descriptor data structure 2) the field 3) the value being assigned.  Any value&lt;br /&gt;
but True will cause an error to be raised; if the return value is a string,&lt;br /&gt;
that will be used as the error message, otherwise one will be generated.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_field_convert(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure which can be used to alter the value being assigned to a&lt;br /&gt;
field.  The closure given will receive arguments of 1) the descriptor data&lt;br /&gt;
structure 2) the field 3) the value being assigned.  The return value will be&lt;br /&gt;
used as the actual value of the field (or, in the case of virtual fields, will&lt;br /&gt;
be passed to the virtual-field-set procedure instead of the original value).&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_query_convert(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure which can be used to alter the value being queried from&lt;br /&gt;
a field.  The closure given will receive arguments of 1) the descriptor data&lt;br /&gt;
structure 2) the field 3) the value being returned.  The return value will be&lt;br /&gt;
used as the actual return value of the query.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_field_interpret(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure which can provide debugging interpretation information&lt;br /&gt;
on descriptor content.  When a debug dump of a given field is being performed,&lt;br /&gt;
the closure given will be called with arguments of 1) the descriptor data&lt;br /&gt;
structure 2) the field 3) the value for the field.  If the return value is a&lt;br /&gt;
string, this will be interpreted as an explanation of the value in the field,&lt;br /&gt;
and will be displayed after the value.  If the return value is an array or&lt;br /&gt;
mapping, this will be interpreted as a set of labels for an array or mapping&lt;br /&gt;
value, and the labels will be displayed before the corresponding elements of&lt;br /&gt;
the value.  To see this mechanism in action, together with the debugging&lt;br /&gt;
support provided by the descriptor mechanism, type 'eval me-&amp;gt;query_shape()'.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_set_virtual(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets the procedure used to set the descriptor's virtual fields.  When a&lt;br /&gt;
virtual field is to be set, the closure given will be called with arguments of&lt;br /&gt;
1) the descriptor data structure 2) the field 3) the value specified.  Return&lt;br /&gt;
values are ignored.  If the descriptor has virtual fields and this procedure is &lt;br /&gt;
not specified, errors will be raised when and if code attempts to set the&lt;br /&gt;
virtual fields.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_query_virtual(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets the procedure used to query the descriptor's virtual fields.  When a&lt;br /&gt;
virtual field is queried, the closure given will be called with arguments of&lt;br /&gt;
1) the descriptor data structure 2) the field.  The return value will be passed&lt;br /&gt;
back as the result of the query.  If the descriptor has virtual fields and this&lt;br /&gt;
procedure is not specified, errors will be raised when and if code attempts to&lt;br /&gt;
query the virtual fields.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_virtual_list(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure which can be used to determine which virtual fields are&lt;br /&gt;
considered part of the descriptor's field order for purposes of a descriptor&lt;br /&gt;
specification in array form, single element form, or multiple element form.&lt;br /&gt;
The closure given will be passed the descriptor data structure as argument,&lt;br /&gt;
and its return value is expected to be an array of field codes or 0.  If&lt;br /&gt;
nonzero, the return value will be added to the descriptor's public field list&lt;br /&gt;
to construct the final field order.  When this procedure is not specified, the&lt;br /&gt;
entire virtual field list is simply added to the public field list in creating&lt;br /&gt;
the field order.  Note that this procedure does not come into play when dealing&lt;br /&gt;
with mapping-form descriptor specifications, and for that reason virtual-set&lt;br /&gt;
and virtual-query procedures cannot assume they will only be dealing with the&lt;br /&gt;
fields returned by the virtual-list procedure.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_preconfigure(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure to be called when a descriptor is first instantiated,&lt;br /&gt;
after preload fields have been loaded but before any other operations.  The&lt;br /&gt;
closure given will receive the descriptor data structure as argument.  Return&lt;br /&gt;
values are ignored.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_initialize(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure to be called when a descriptor has just been constructed,&lt;br /&gt;
after fully loading its fields.  The closure given will receive the descriptor&lt;br /&gt;
data structure as argument.  Return values are ignored.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_convert(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure that can be used to replace an entire descriptor with&lt;br /&gt;
another one as it is generated.  The closure given is called after the&lt;br /&gt;
initialization procedure, if any, and just before returning the descriptor to&lt;br /&gt;
the code requesting it.  The descriptor data structure is passed as argument.&lt;br /&gt;
If the return value is non-zero, the descriptor is replaced with that value,&lt;br /&gt;
which is expected to be another valid descriptor of the same type.  This is&lt;br /&gt;
generally used to implement descriptor caching/sharing schemes.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_specification_convert(closure proc)&lt;br /&gt;
&lt;br /&gt;
Sets a procedure that can be used to preprocess the specification of a&lt;br /&gt;
to-be-created descriptor.  The closure is called at the beginning of the&lt;br /&gt;
process of descriptor assembly, and is passed the descriptor specification&lt;br /&gt;
as its argument.  This specification may be any data type, including an&lt;br /&gt;
already-assembled descriptor (which normally would be returned unchanged).&lt;br /&gt;
This mechanism rarely needs to be or should be used.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_definitions(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor as referring to definitions.  The keys&lt;br /&gt;
in the mapping passed are the names of fields, and the values are definition&lt;br /&gt;
type identifiers (generally macros from /lib/definition_types.h).  The values&lt;br /&gt;
for the indicated fields will be required to be either zero or a valid&lt;br /&gt;
definition specification for the type specified, will have its stored value&lt;br /&gt;
coerced into the appropriate identifier for the definition type (generally an&lt;br /&gt;
integer code for definitions that have them, a string key otherwise), and the&lt;br /&gt;
descriptor will automatically be able to interpret these fields as being a&lt;br /&gt;
definition of the relevant type.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_definition_groups(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor as referring to arrays of definitions.&lt;br /&gt;
The keys in the mapping passed are the names of fields, and the values are&lt;br /&gt;
definition type identifiers.  The values for the indicated fields will be&lt;br /&gt;
required to be either zero, a definition specification for the type specified,&lt;br /&gt;
or an array of these, and will have its stored value coerced into an array of&lt;br /&gt;
the appropriate identifiers for the definition type.  The descriptor will&lt;br /&gt;
automatically be able to interpret these fields as being arrays of definitions&lt;br /&gt;
of the relevant type.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_descriptors(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor as referring to descriptors.  The keys&lt;br /&gt;
in the mapping passed are the names of fields, and the values are descriptor&lt;br /&gt;
type codes (macros from /lib/descriptors.h).  The values for the indicated&lt;br /&gt;
fields will, if not zero, be coerced into an instance of the descriptor type.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_descriptor_groups(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor as referring to arrays of descriptors.&lt;br /&gt;
The keys in the mapping passed are the names of fields, and the values are&lt;br /&gt;
descriptor type codes (macros from /lib/descriptors.h).  The values for the&lt;br /&gt;
indicated fields will, if not zero, be coerced into an array of instances of&lt;br /&gt;
the descriptor type.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_enumerations(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor as having enumerated values.  The keys&lt;br /&gt;
in the mapping passed are the names of fields, and the values are arrays of&lt;br /&gt;
strings which provide the names of the possible values for that field.  Macros&lt;br /&gt;
will be automatically constructed for these and integer values assigned to&lt;br /&gt;
them.  The names will look like &amp;quot;Descriptor_Field_Value&amp;quot;, where &amp;quot;Descriptor&amp;quot;&lt;br /&gt;
is the name of the descriptor type, &amp;quot;Field&amp;quot; is the name of the field, and&lt;br /&gt;
&amp;quot;Value&amp;quot; is the string value name provided.  The descriptor will automatically&lt;br /&gt;
be able to interpret these fields back to their names, and will normally&lt;br /&gt;
restrict the field to being set to one of the enumerated values.  If you embed&lt;br /&gt;
an integer in the value name list, the integer values for subsequent items will&lt;br /&gt;
be indexed from that number.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_bitmasks(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Defines fields in the descriptor which are used for bitmask flags.  The&lt;br /&gt;
keys in the mapping passed are the names of fields, and the values are arrays&lt;br /&gt;
of strings which provide the names of the bitmask values for that field.&lt;br /&gt;
Macros will be automatically constructed for these and bit values assigned to&lt;br /&gt;
them.  The names will look like &amp;quot;Descriptor_Field_Value&amp;quot;, where &amp;quot;Descriptor&amp;quot;&lt;br /&gt;
is the name of the descriptor type, &amp;quot;Field&amp;quot; is the name of the field (converted&lt;br /&gt;
to a singular if it appears to be a plural), and &amp;quot;Value&amp;quot; is the string bitmask&lt;br /&gt;
name provide.  The descriptor will automatically be able to interpret these&lt;br /&gt;
fields, and will restrict the field to being set to valid combinations of the&lt;br /&gt;
bitmasks defined.  A given bitmask field cannot have more than 32 possible&lt;br /&gt;
bitmask values, since we have 32-bit integers.  The names &amp;quot;all&amp;quot; and &amp;quot;except&amp;quot;&lt;br /&gt;
may not be used for bitmasks values, since they are used for standard bitmask&lt;br /&gt;
manipulation macros.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_optionality(mapping spec)&lt;br /&gt;
&lt;br /&gt;
Affects definition, definition group, descriptor, descriptor group, and&lt;br /&gt;
enumeration fields.  For the first four, fields mapping to a True value in the&lt;br /&gt;
specification can have a zero value to be specified for the field without&lt;br /&gt;
causing an error.  For enumeration fields, allows fields to have non-integer&lt;br /&gt;
values, which will be simply stored in the field; integer values will still&lt;br /&gt;
be checked against the enumerated list.&lt;br /&gt;
&lt;br /&gt;
void set_descriptor_additional_macros(mixed array list)&lt;br /&gt;
&lt;br /&gt;
Defines additional macros to be included in the descriptor's header file.&lt;br /&gt;
Each element of the list may be one of the following:&lt;br /&gt;
&lt;br /&gt;
    A two-element string array: Results in a macro definition where the&lt;br /&gt;
    first element of the array, with the descriptor name prepended, is used&lt;br /&gt;
    as the macro name, and the second element is used as the macro value&lt;br /&gt;
    (and will be aligned horizontally as generally appropriate to the&lt;br /&gt;
    header file).  For example, the list element ({ &amp;quot;Usage_None&amp;quot;, &amp;quot;1&amp;quot; }) in&lt;br /&gt;
    /def/descriptor/belonging.c results in a line resembling &amp;quot;#define&lt;br /&gt;
    Belonging_Usage_None 1&amp;quot; in belonging.h.&lt;br /&gt;
&lt;br /&gt;
    Zero: Results in a blank line in the header file.&lt;br /&gt;
&lt;br /&gt;
    A string: Results in the string being included in the header file&lt;br /&gt;
    exactly as is, except for having a newline appended.  Try to use the&lt;br /&gt;
    two-element string array form instead of the string form whenever&lt;br /&gt;
    possible.&lt;br /&gt;
&lt;br /&gt;
void set_description_additional_includes(string array list)&lt;br /&gt;
&lt;br /&gt;
Defines additional includes which should be placed in the generated header&lt;br /&gt;
file for the descriptor type.  These should be the bare filenames to be used.&lt;br /&gt;
&lt;br /&gt;
===Support Functions===&lt;br /&gt;
&lt;br /&gt;
Beyond these configuration functions, the descriptor definition may also&lt;br /&gt;
contain arbitrary functions for use with its descriptors.  Any function defined&lt;br /&gt;
in the definition object which is not private or static, and whose name begins&lt;br /&gt;
with the descriptor name or its plural, spaces replaced by underscores, and&lt;br /&gt;
an underscore, will automatically have a corresponding macro defined for its&lt;br /&gt;
use by the header file.  For example, if /def/descriptor/belonging.c had a&lt;br /&gt;
function 'void belonging_check(mixed array dxr)', this would cause a macro&lt;br /&gt;
'Belonging_Check(x)' to appear in belonging.h, defined so as to call the&lt;br /&gt;
function in the descriptor definition.  These functions are automatically&lt;br /&gt;
examined for the number of arguments they take and whether they are defined&lt;br /&gt;
varargs, so as to create a macro that is fully appropriate to the function.&lt;br /&gt;
&lt;br /&gt;
===Further Information===&lt;br /&gt;
&lt;br /&gt;
It is highly recommended to familiarize yourself with existing descriptor&lt;br /&gt;
implementations to better understand how they operate.  Belonging descriptors&lt;br /&gt;
are a good place to start; they are relatively simple and straightforward, yet&lt;br /&gt;
use many of the more advanced features of the system to some extent.  Shape&lt;br /&gt;
descriptors are an example of heavy use of virtual fields and the close linking&lt;br /&gt;
of a definition class (geometries) to a descriptor type.  Many of the other&lt;br /&gt;
descriptors are very simple in their definition, though their usage may be&lt;br /&gt;
complex.  Look around.&lt;/div&gt;</summary>
		<author><name>Laine</name></author>	</entry>

	</feed>