chiark / gitweb /
str: New str_matchx function optionally reports possible prefix.
[mLib] / atom.c
1 /* -*-c-*-
2  *
3  * $Id$
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 /*----- 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"
39 #include "unihash.h"
40
41 /*----- Static variables --------------------------------------------------*/
42
43 static 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
65 void 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
85 void 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
97 /* --- @atom_intern@, @atom_nintern@ --- *
98  *
99  * Arguments:   @atom_table *t@ = pointer to an atom table
100  *              @const char *p@ = pointer to the string to intern
101  *              @size_t n@ = size of the string (for @atom_nintern)
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
109 atom *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
121 atom *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
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
144 atom *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);
156   a->b.len = sz - 1;
157   a->b.b.hash = UNIHASH(&unihash_global, buf, sz);
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
174 const 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
186 size_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
197 uint32 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
209 void 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
217 atom *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 -------------------------------------------------*/