chiark / gitweb /
codec/{base32,hex}.h: Include `codec.h'.
[mLib] / struct / atom.c
1 /* -*-c-*-
2  *
3  * Atom management
4  *
5  * (c) 2000 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
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.
16  *
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.
21  *
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
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"
37 #include "unihash.h"
38
39 /*----- Static variables --------------------------------------------------*/
40
41 static 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
63 void 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
83 void 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
95 /* --- @atom_intern@, @atom_nintern@ --- *
96  *
97  * Arguments:   @atom_table *t@ = pointer to an atom table
98  *              @const char *p@ = pointer to the string to intern
99  *              @size_t n@ = size of the string (for @atom_nintern)
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
107 atom *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
119 atom *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
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
142 atom *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);
154   a->b.len = sz - 1;
155   a->b.b.hash = UNIHASH(&unihash_global, buf, sz);
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
172 const 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
184 size_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
195 uint32 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
207 void 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
215 atom *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 -------------------------------------------------*/