chiark / gitweb /
Make ADNS wait for the event loop before collecting replies.
[mLib] / atom.c
CommitLineData
c1c43500 1/* -*-c-*-
2 *
6f444bda 3 * $Id: atom.c,v 1.4 2003/12/15 20:53:47 mdw Exp $
c1c43500 4 *
5 * Atom management
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the mLib utilities library.
13 *
14 * mLib is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * mLib is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with mLib; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: atom.c,v $
6f444bda 33 * Revision 1.4 2003/12/15 20:53:47 mdw
34 * Add global unihash table; use universal hashing instead of CRC.
35 *
5479cb54 36 * Revision 1.3 2001/01/25 21:13:15 mdw
37 * New function allowing an atom's length to be specified at intern time.
38 *
0ae5e7b3 39 * Revision 1.2 2001/01/21 19:04:51 mdw
40 * Include `crc32.h' for @CRC32@ macro.
41 *
c1c43500 42 * Revision 1.1 2001/01/20 11:50:16 mdw
43 * Implementation of atom tables (for example, as found in X11).
44 *
45 */
46
47/*----- Header files ------------------------------------------------------*/
48
49#include <stdio.h>
50#include <string.h>
51
52#include "alloc.h"
53#include "atom.h"
54#include "hash.h"
55#include "sym.h"
6f444bda 56#include "unihash.h"
c1c43500 57
58/*----- Static variables --------------------------------------------------*/
59
60static atom_table atoms;
61
62/*----- Handy macros ------------------------------------------------------*/
63
64#define ATOM_RESOLVE(t) do { \
65 if (t == ATOM_GLOBAL) \
66 t = &atoms; \
67 if (!t->t.t.v) \
68 atom_createtable(t); \
69} while (0)
70
71/*----- Main code ---------------------------------------------------------*/
72
73/* --- @atom_createtable@ --- *
74 *
75 * Arguments: @atom_table *t@ = pointer to an atom table
76 *
77 * Returns: ---
78 *
79 * Use: Initializes an atom table.
80 */
81
82void atom_createtable(atom_table *t)
83{
84 sym_create(&t->t);
85 t->g = 0;
86 t->gseq = 0;
87}
88
89/* --- @atom_destroytable@ --- *
90 *
91 * Arguments: @atom_table *t@ = pointer to an atom table
92 *
93 * Returns: ---
94 *
95 * Use: Destroys all of the atoms in an atom table. All of the atoms
96 * (including uninterned atoms) are freed. Any references to
97 * atoms from the table become invalid, and any association
98 * tables dependent on the atom table are unusable, except that
99 * they may be destroyed safely.
100 */
101
102void atom_destroytable(atom_table *t)
103{
104 atom *a, *aa;
105
106 ATOM_RESOLVE(t);
107 for (a = (atom *)t->g; a; a = aa) {
108 aa = (atom *)a->b.b.next;
109 x_free(t->t.t.a, a);
110 }
111 sym_destroy(&t->t);
112}
113
5479cb54 114/* --- @atom_intern@, @atom_nintern@ --- *
c1c43500 115 *
116 * Arguments: @atom_table *t@ = pointer to an atom table
117 * @const char *p@ = pointer to the string to intern
5479cb54 118 * @size_t n@ = size of the string (for @atom_nintern)
c1c43500 119 *
120 * Returns: A pointer to the atom block for the given symbol string.
121 *
122 * Use: Interns an atom, returning the atom block. The string can be
123 * extracted from the atom by means of the @ATOM_NAME@ macro.
124 */
125
126atom *atom_intern(atom_table *t, const char *p)
127{
128 atom *a;
129 unsigned f;
130
131 ATOM_RESOLVE(t);
132 a = sym_find(&t->t, p, -1, sizeof(atom), &f);
133 if (!f)
134 a->f = 0;
135 return (a);
136}
137
5479cb54 138atom *atom_nintern(atom_table *t, const char *p, size_t n)
139{
140 atom *a;
141 unsigned f;
142
143 ATOM_RESOLVE(t);
144 a = sym_find(&t->t, p, n, sizeof(atom), &f);
145 if (!f)
146 a->f = 0;
147 return (a);
148}
149
c1c43500 150/* --- @atom_gensym@ --- *
151 *
152 * Arguments: @atom_table *t@ = pointer to a symbol table
153 *
154 * Returns: A pointer to a new atom block, not previously interned.
155 *
156 * Use: Creates a new, uninterned atom. This atom will never be
157 * returned by either @atom_intern@ or any other call to
158 * @atom_gensym@, while the symbol table exists.
159 */
160
161atom *atom_gensym(atom_table *t)
162{
163 atom *a;
164 char buf[64];
165 size_t sz;
166
167 ATOM_RESOLVE(t);
168 sprintf(buf, "*gen-%lu*", t->gseq++);
169 sz = strlen(buf) + 1;
170 a = x_alloc(t->t.t.a, sizeof(atom) + sz);
171 a->b.name = (char *)(a + 1);
172 memcpy(a->b.name, buf, sz);
173 a->b.len = sz;
6f444bda 174 a->b.b.hash = UNIHASH(&unihash_global, buf, sz);
c1c43500 175 a->f = ATOMF_GENSYM;
176 a->b.b.next = t->g;
177 t->g = &a->b.b;
178 return (a);
179}
180
181/* --- @atom_name@ --- *
182 *
183 * Arguments: @atom *a@ = pointer to an atom
184 *
185 * Returns: The atom's textual name.
186 *
187 * Use: Given an atom, returns the name with which it was interned
188 * (or a made-up name if it was created using @gensym@.
189 */
190
191const char *atom_name(const atom *a) { return ATOM_NAME(a); }
192
193/* --- @atom_len@ --- *
194 *
195 * Arguments: @atom *a@ = pointer to an atom
196 *
197 * Returns: The atom string's length.
198 *
199 * Use: Given an atom, return the length of its textual
200 * representation.
201 */
202
203size_t atom_len(const atom *a) { return ATOM_LEN(a); }
204
205/* --- @atom_hash@ --- *
206 *
207 * Arguments: @atom *a@ = pointer to an atom
208 *
209 * Returns: The atom's hash.
210 *
211 * Use: Given an atom, returns its hash.
212 */
213
214uint32 atom_hash(const atom *a) { return ATOM_HASH(a); }
215
216/* --- @atom_mkiter@ , @atom_next@ --- *
217 *
218 * Arguments: @atom_table *t@ = pointer to an atom table
219 * @atom_iter *i@ = pointer to an iterator structure
220 *
221 * Returns: Next atom, for @atom_next@; nothing for @atom_mkiter@.
222 *
223 * Use: Iterates over atoms (both interned and uninterned).
224 */
225
226void atom_mkiter(atom_iter *i, atom_table *t)
227{
228 ATOM_RESOLVE(t);
229 i->i.i.t = &t->t.t;
230 i->i.i.p = t->g;
231 i->i.i.i = 0;
232}
233
234atom *atom_next(atom_iter *i)
235{
236 atom *a;
237 SYM_NEXT(&i->i, a);
238 return (a);
239}
240
241/*----- That's all, folks -------------------------------------------------*/