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