chiark / gitweb /
*/*.3: Align arguments properly to the right of the opening `('.
[mLib] / struct / sym.3
1 .\" -*-nroff-*-
2 .de VS
3 .sp 1
4 .RS
5 .nf
6 .ft B
7 ..
8 .de VE
9 .ft R
10 .fi
11 .RE
12 .sp 1
13 ..
14 .TH sym 3 "8 May 1999" "Straylight/Edgeware" "mLib utilities library"
15 .SH NAME
16 sym \- symbol table manager
17 .\" @sym_create
18 .\" @sym_destroy
19 .\" @sym_find
20 .\" @sym_remove
21 .\" @sym_mkiter
22 .\" @sym_next
23 .\"
24 .\" @SYM_NAME
25 .\" @SYM_LEN
26 .\" @SYM_HASH
27 .\"
28 .SH SYNOPSIS
29 .nf
30 .B "#include <mLib/sym.h>"
31
32 .BI "void sym_create(sym_table *" t );
33 .BI "void sym_destroy(sym_table *" t );
34
35 .ds mT \fBvoid *sym_find(
36 .BI "\*(mTsym_table *" t ,
37 .BI "\h'\w'\*(mT'u'const char *" n ", long " l ,
38 .BI "\h'\w'\*(mT'u'size_t " sz ", unsigned *" f );
39 .BI "void sym_remove(sym_table *" t ", void *" b );
40
41 .BI "const char *SYM_NAME(const void *" p );
42 .BI "size_t SYM_LEN(const void *" p );
43 .BI "uint32 SYM_HASH(const void *" p );
44
45 .BI "void sym_mkiter(sym_iter *" i ", sym_table *" t );
46 .BI "void *sym_next(sym_iter *" i );
47 .fi
48 .SH "DESCRIPTION"
49 The
50 .B sym
51 functions implement a data structure often described as a dictionary, a
52 finite map, an associative array, or a symbol table.  It associates
53 .I values
54 with
55 .I keys
56 such that the value corresponding to a given key can be found quickly.
57 Additionally, all stored associations can be enumerated.
58 .PP
59 The interface provides an
60 .I intrusive
61 symbol table.  The data objects stored in the table must include a small
62 header used by the symbol table manager.  This reduces the amount of
63 pointer fiddling that needs to be done, and in practice doesn't seem to
64 be much of a problem.  It's also fairly easy to construct a
65 non-intrusive interface if you really want one.
66 .PP
67 There are three main data structures involved in the interface:
68 .TP
69 .B sym_table
70 Keeps track of the information associated with a particular table.
71 .TP
72 .B sym_base
73 The header which must be attached to the front of all the value
74 objects.
75 .TP
76 .B sym_iter
77 An iterator object, used for enumerating all of the associations stored
78 in a symbol table.
79 .PP
80 All of the above data structures should be considered
81 .IR opaque :
82 don't try looking inside.  Representations have changed in the past, and
83 they may change again in the future.
84 .SS "Creation and destruction"
85 The
86 .B sym_table
87 object itself needs to be allocated by the caller.  It is initialized by
88 passing it to the function
89 .BR sym_create .
90 After initialization, the table contains no entries.
91 .PP
92 Initializing a symbol table involves allocating some memory.  If this
93 allocation fails, an
94 .B EXC_NOMEM
95 exception is raised.
96 .PP
97 When a symbol table is no longer needed, the memory occupied by the
98 values and other maintenance structures can be reclaimed by calling
99 .BR sym_destroy .
100 Any bits of user data attached to values should previously have been
101 destroyed.
102 .SS "Adding, searching and removing"
103 Most of the actual work is done by the function
104 .BR sym_find .
105 It does both lookup and creation, depending on its arguments.  To do its
106 job, it needs to know the following bits of information:
107 .TP
108 .BI "sym_table *" t
109 A pointer to a symbol table to manipulate.
110 .TP
111 .BI "const char *" n
112 The address of the
113 .I key
114 to look up or create.  Usually this will be a simple text string,
115 although it can actually be any arbitrary binary data.
116 .TP
117 .BI "long " l
118 The length of the key.  If this is \-1,
119 .B sym_find
120 assumes that the key is a null-terminated string, and calculates its
121 length itself.  This is entirely equivalent to passing
122 .BI strlen( n )\fR.
123 .TP
124 .BI "size_t " sz
125 The size of the value block to allocate if the key could not be found.
126 If this is zero, no value is allocated, and a null pointer is returned
127 to indicate an unsuccessful lookup.
128 .TP
129 .BI "unsigned *" f
130 The address of a `found' flag to set.  This is an output parameter.  On
131 exit,
132 .B sym_find
133 will set the value of
134 .BI * f
135 to zero if the key could not be found, or nonzero if it was found.  This
136 can be used to tell whether the value returned has been newly allocated,
137 or whether it was already in the table.
138 .PP
139 A terminating null byte is appended to the copy of the symbol's name in
140 memory.  This is not considered to be a part of the symbol's name, and
141 does not contribute to the name's length as reported by the
142 .B SYM_LEN
143 macro.
144 .PP
145 A symbol can be removed from the table by calling
146 .BR sym_remove ,
147 passing the symbol table itself, and the value block that needs
148 removing.
149 .SS "Enquiries about symbols"
150 Three macros are provided to enable simple enquiries about a symbol.
151 Given a pointer
152 .I s
153 to a symbol table entry,
154 .BI SYM_LEN( s )
155 returns the length of the symbol's name (excluding any terminating null
156 byte);
157 .BI SYM_NAME( s )
158 returns a pointer to the symbol's name; and
159 .BI SYM_HASH( s )
160 returns the symbol's hash value.
161 .SS "Enumerating symbols"
162 Enumerating the values in a symbol table is fairly simple.  Allocate a
163 .B sym_iter
164 object from somewhere.  Attach it to a symbol table by calling
165 .BR sym_mkiter ,
166 and passing in the addresses of the iterator and the symbol table.
167 Then, each call to
168 .B sym_next
169 will return a different value from the symbol table, until all of them
170 have been enumerated, at which point,
171 .B sym_next
172 returns a null pointer.
173 .PP
174 It's safe to remove the symbol you've just been returned by
175 .BR sym_next .
176 However, it's not safe to remove any other symbol.  So don't do that.
177 .PP
178 When you've finished with an iterator, it's safe to just throw it away.
179 You don't need to call any functions beforehand.
180 .SS "Use in practice"
181 In normal use, the keys are simple strings (usually identifiers from
182 some language), and the values are nontrivial structures providing
183 information about types and values.
184 .PP
185 In this case, you'd define something like the following structure for
186 your values:
187 .VS
188 typedef struct val {
189   sym_base _base;       /* Symbol header */
190   unsigned type;        /* Type of this symbol */
191   int dispoff;          /* Which display variable is in */
192   size_t frameoff;      /* Offset of variable in frame */
193 } val;
194 .VE
195 Given a pointer
196 .I v
197 to a
198 .BR val ,
199 you can find the variable's name by calling
200 .BI SYM_NAME( v )\fR.
201 .PP
202 You can look up a name in the table by saying something like:
203 .VS
204 val *v = sym_find(t, name, -1, 0, 0);
205 if (!v)
206   error("unknown variable `%s'", name);
207 .VE
208 You can add in a new variable by saying something like
209 .VS
210 unsigned f;
211 val *v = sym_find(t, name, -1, sizeof(val), &f);
212 if (f)
213   error("variable `%s' already exists", name);
214 /* fill in v */
215 .VE
216 You can examine all the variables in your symbol table by saying
217 something like:
218 .VS
219 sym_iter i;
220 val *v;
221
222 for (sym_mkiter(&i, t); (v = sym_next(&i)) != 0; ) {
223   /* ... */
224 }
225 .VE
226 That ought to be enough examples to be getting on with.
227 .SS Implementation
228 The symbol table is an extensible hashtable, using the universal hash
229 function described in
230 .BR unihash (3)
231 and the global hashing key.  The hash chains are kept very short
232 (probably too short, actually).  Every time a symbol is found, its block
233 is promoted to the front of its bin chain so it gets found faster next
234 time.
235 .SH SEE ALSO
236 .BR hash (3),
237 .BR mLib (3).
238 .SH AUTHOR
239 Mark Wooding, <mdw@distorted.org.uk>