chiark / gitweb /
New function allowing an atom's length to be specified at intern time.
[mLib] / atom.c
... / ...
CommitLineData
1/* -*-c-*-
2 *
3 * $Id: atom.c,v 1.3 2001/01/25 21:13:15 mdw Exp $
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 $
33 * Revision 1.3 2001/01/25 21:13:15 mdw
34 * New function allowing an atom's length to be specified at intern time.
35 *
36 * Revision 1.2 2001/01/21 19:04:51 mdw
37 * Include `crc32.h' for @CRC32@ macro.
38 *
39 * Revision 1.1 2001/01/20 11:50:16 mdw
40 * Implementation of atom tables (for example, as found in X11).
41 *
42 */
43
44/*----- Header files ------------------------------------------------------*/
45
46#include <stdio.h>
47#include <string.h>
48
49#include "alloc.h"
50#include "atom.h"
51#include "crc32.h"
52#include "hash.h"
53#include "sym.h"
54
55/*----- Static variables --------------------------------------------------*/
56
57static atom_table atoms;
58
59/*----- Handy macros ------------------------------------------------------*/
60
61#define ATOM_RESOLVE(t) do { \
62 if (t == ATOM_GLOBAL) \
63 t = &atoms; \
64 if (!t->t.t.v) \
65 atom_createtable(t); \
66} while (0)
67
68/*----- Main code ---------------------------------------------------------*/
69
70/* --- @atom_createtable@ --- *
71 *
72 * Arguments: @atom_table *t@ = pointer to an atom table
73 *
74 * Returns: ---
75 *
76 * Use: Initializes an atom table.
77 */
78
79void atom_createtable(atom_table *t)
80{
81 sym_create(&t->t);
82 t->g = 0;
83 t->gseq = 0;
84}
85
86/* --- @atom_destroytable@ --- *
87 *
88 * Arguments: @atom_table *t@ = pointer to an atom table
89 *
90 * Returns: ---
91 *
92 * Use: Destroys all of the atoms in an atom table. All of the atoms
93 * (including uninterned atoms) are freed. Any references to
94 * atoms from the table become invalid, and any association
95 * tables dependent on the atom table are unusable, except that
96 * they may be destroyed safely.
97 */
98
99void atom_destroytable(atom_table *t)
100{
101 atom *a, *aa;
102
103 ATOM_RESOLVE(t);
104 for (a = (atom *)t->g; a; a = aa) {
105 aa = (atom *)a->b.b.next;
106 x_free(t->t.t.a, a);
107 }
108 sym_destroy(&t->t);
109}
110
111/* --- @atom_intern@, @atom_nintern@ --- *
112 *
113 * Arguments: @atom_table *t@ = pointer to an atom table
114 * @const char *p@ = pointer to the string to intern
115 * @size_t n@ = size of the string (for @atom_nintern)
116 *
117 * Returns: A pointer to the atom block for the given symbol string.
118 *
119 * Use: Interns an atom, returning the atom block. The string can be
120 * extracted from the atom by means of the @ATOM_NAME@ macro.
121 */
122
123atom *atom_intern(atom_table *t, const char *p)
124{
125 atom *a;
126 unsigned f;
127
128 ATOM_RESOLVE(t);
129 a = sym_find(&t->t, p, -1, sizeof(atom), &f);
130 if (!f)
131 a->f = 0;
132 return (a);
133}
134
135atom *atom_nintern(atom_table *t, const char *p, size_t n)
136{
137 atom *a;
138 unsigned f;
139
140 ATOM_RESOLVE(t);
141 a = sym_find(&t->t, p, n, sizeof(atom), &f);
142 if (!f)
143 a->f = 0;
144 return (a);
145}
146
147/* --- @atom_gensym@ --- *
148 *
149 * Arguments: @atom_table *t@ = pointer to a symbol table
150 *
151 * Returns: A pointer to a new atom block, not previously interned.
152 *
153 * Use: Creates a new, uninterned atom. This atom will never be
154 * returned by either @atom_intern@ or any other call to
155 * @atom_gensym@, while the symbol table exists.
156 */
157
158atom *atom_gensym(atom_table *t)
159{
160 atom *a;
161 char buf[64];
162 size_t sz;
163
164 ATOM_RESOLVE(t);
165 sprintf(buf, "*gen-%lu*", t->gseq++);
166 sz = strlen(buf) + 1;
167 a = x_alloc(t->t.t.a, sizeof(atom) + sz);
168 a->b.name = (char *)(a + 1);
169 memcpy(a->b.name, buf, sz);
170 a->b.len = sz;
171 CRC32(a->b.b.hash, 0, buf, sz);
172 a->f = ATOMF_GENSYM;
173 a->b.b.next = t->g;
174 t->g = &a->b.b;
175 return (a);
176}
177
178/* --- @atom_name@ --- *
179 *
180 * Arguments: @atom *a@ = pointer to an atom
181 *
182 * Returns: The atom's textual name.
183 *
184 * Use: Given an atom, returns the name with which it was interned
185 * (or a made-up name if it was created using @gensym@.
186 */
187
188const char *atom_name(const atom *a) { return ATOM_NAME(a); }
189
190/* --- @atom_len@ --- *
191 *
192 * Arguments: @atom *a@ = pointer to an atom
193 *
194 * Returns: The atom string's length.
195 *
196 * Use: Given an atom, return the length of its textual
197 * representation.
198 */
199
200size_t atom_len(const atom *a) { return ATOM_LEN(a); }
201
202/* --- @atom_hash@ --- *
203 *
204 * Arguments: @atom *a@ = pointer to an atom
205 *
206 * Returns: The atom's hash.
207 *
208 * Use: Given an atom, returns its hash.
209 */
210
211uint32 atom_hash(const atom *a) { return ATOM_HASH(a); }
212
213/* --- @atom_mkiter@ , @atom_next@ --- *
214 *
215 * Arguments: @atom_table *t@ = pointer to an atom table
216 * @atom_iter *i@ = pointer to an iterator structure
217 *
218 * Returns: Next atom, for @atom_next@; nothing for @atom_mkiter@.
219 *
220 * Use: Iterates over atoms (both interned and uninterned).
221 */
222
223void atom_mkiter(atom_iter *i, atom_table *t)
224{
225 ATOM_RESOLVE(t);
226 i->i.i.t = &t->t.t;
227 i->i.i.p = t->g;
228 i->i.i.i = 0;
229}
230
231atom *atom_next(atom_iter *i)
232{
233 atom *a;
234 SYM_NEXT(&i->i, a);
235 return (a);
236}
237
238/*----- That's all, folks -------------------------------------------------*/