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