From: mdw Date: Sat, 20 Jan 2001 11:50:16 +0000 (+0000) Subject: Implementation of atom tables (for example, as found in X11). X-Git-Tag: 2.0.4~134 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/commitdiff_plain/c1c43500c9dade4d8df9366ae602b08f04f95682 Implementation of atom tables (for example, as found in X11). --- diff --git a/atom.c b/atom.c new file mode 100644 index 0000000..66e9b57 --- /dev/null +++ b/atom.c @@ -0,0 +1,218 @@ +/* -*-c-*- + * + * $Id: atom.c,v 1.1 2001/01/20 11:50:16 mdw Exp $ + * + * Atom management + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: atom.c,v $ + * Revision 1.1 2001/01/20 11:50:16 mdw + * Implementation of atom tables (for example, as found in X11). + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +#include "alloc.h" +#include "atom.h" +#include "hash.h" +#include "sym.h" + +/*----- Static variables --------------------------------------------------*/ + +static atom_table atoms; + +/*----- Handy macros ------------------------------------------------------*/ + +#define ATOM_RESOLVE(t) do { \ + if (t == ATOM_GLOBAL) \ + t = &atoms; \ + if (!t->t.t.v) \ + atom_createtable(t); \ +} while (0) + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @atom_createtable@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * + * Returns: --- + * + * Use: Initializes an atom table. + */ + +void atom_createtable(atom_table *t) +{ + sym_create(&t->t); + t->g = 0; + t->gseq = 0; +} + +/* --- @atom_destroytable@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * + * Returns: --- + * + * Use: Destroys all of the atoms in an atom table. All of the atoms + * (including uninterned atoms) are freed. Any references to + * atoms from the table become invalid, and any association + * tables dependent on the atom table are unusable, except that + * they may be destroyed safely. + */ + +void atom_destroytable(atom_table *t) +{ + atom *a, *aa; + + ATOM_RESOLVE(t); + for (a = (atom *)t->g; a; a = aa) { + aa = (atom *)a->b.b.next; + x_free(t->t.t.a, a); + } + sym_destroy(&t->t); +} + +/* --- @atom_intern@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * @const char *p@ = pointer to the string to intern + * + * Returns: A pointer to the atom block for the given symbol string. + * + * Use: Interns an atom, returning the atom block. The string can be + * extracted from the atom by means of the @ATOM_NAME@ macro. + */ + +atom *atom_intern(atom_table *t, const char *p) +{ + atom *a; + unsigned f; + + ATOM_RESOLVE(t); + a = sym_find(&t->t, p, -1, sizeof(atom), &f); + if (!f) + a->f = 0; + return (a); +} + +/* --- @atom_gensym@ --- * + * + * Arguments: @atom_table *t@ = pointer to a symbol table + * + * Returns: A pointer to a new atom block, not previously interned. + * + * Use: Creates a new, uninterned atom. This atom will never be + * returned by either @atom_intern@ or any other call to + * @atom_gensym@, while the symbol table exists. + */ + +atom *atom_gensym(atom_table *t) +{ + atom *a; + char buf[64]; + size_t sz; + + ATOM_RESOLVE(t); + sprintf(buf, "*gen-%lu*", t->gseq++); + sz = strlen(buf) + 1; + a = x_alloc(t->t.t.a, sizeof(atom) + sz); + a->b.name = (char *)(a + 1); + memcpy(a->b.name, buf, sz); + a->b.len = sz; + CRC32(a->b.b.hash, 0, buf, sz); + a->f = ATOMF_GENSYM; + a->b.b.next = t->g; + t->g = &a->b.b; + return (a); +} + +/* --- @atom_name@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom's textual name. + * + * Use: Given an atom, returns the name with which it was interned + * (or a made-up name if it was created using @gensym@. + */ + +const char *atom_name(const atom *a) { return ATOM_NAME(a); } + +/* --- @atom_len@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom string's length. + * + * Use: Given an atom, return the length of its textual + * representation. + */ + +size_t atom_len(const atom *a) { return ATOM_LEN(a); } + +/* --- @atom_hash@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom's hash. + * + * Use: Given an atom, returns its hash. + */ + +uint32 atom_hash(const atom *a) { return ATOM_HASH(a); } + +/* --- @atom_mkiter@ , @atom_next@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * @atom_iter *i@ = pointer to an iterator structure + * + * Returns: Next atom, for @atom_next@; nothing for @atom_mkiter@. + * + * Use: Iterates over atoms (both interned and uninterned). + */ + +void atom_mkiter(atom_iter *i, atom_table *t) +{ + ATOM_RESOLVE(t); + i->i.i.t = &t->t.t; + i->i.i.p = t->g; + i->i.i.i = 0; +} + +atom *atom_next(atom_iter *i) +{ + atom *a; + SYM_NEXT(&i->i, a); + return (a); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/atom.h b/atom.h new file mode 100644 index 0000000..7adf195 --- /dev/null +++ b/atom.h @@ -0,0 +1,190 @@ +/* -*-c-*- + * + * $Id: atom.h,v 1.1 2001/01/20 11:50:16 mdw Exp $ + * + * Atom management + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: atom.h,v $ + * Revision 1.1 2001/01/20 11:50:16 mdw + * Implementation of atom tables (for example, as found in X11). + * + */ + +#ifndef MLIB_ATOM_H +#define MLIB_ATOM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef MLIB_SYM_H +# include "sym.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct atom_table { + sym_table t; /* Symbol table of interned atoms */ + hash_base *g; /* List of uninterned atoms */ + unsigned long gseq; /* Sequence number for @gensym@ */ +} atom_table; + +typedef struct atom { + sym_base b; /* Base structure for symbol table */ + unsigned f; /* Various useful flags */ +} atom; + +#define ATOMF_GENSYM 1u /* Atom is uninterned */ + +typedef struct { sym_iter i; } atom_iter; + +/*----- Global magic ------------------------------------------------------*/ + +#define ATOM_GLOBAL 0 + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @atom_createtable@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * + * Returns: --- + * + * Use: Initializes an atom table. + */ + +extern void atom_createtable(atom_table */*t*/); + +/* --- @atom_destroytable@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * + * Returns: --- + * + * Use: Destroys all of the atoms in an atom table. All of the atoms + * (including uninterned atoms) are freed. Any references to + * atoms from the table become invalid, and any association + * tables dependent on the atom table are unusable, except that + * they may be destroyed safely. + */ + +extern void atom_destroytable(atom_table */*t*/); + +/* --- @atom_intern@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * @const char *p@ = pointer to the string to intern + * + * Returns: A pointer to the atom block for the given symbol string. + * + * Use: Interns an atom, returning the atom block. The string can be + * extracted from the atom by means of the @ATOM_NAME@ macro. + */ + +#define INTERN(p) atom_intern(ATOM_GLOBAL, (p)) + +extern atom *atom_intern(atom_table */*t*/, const char */*p*/); + +/* --- @atom_gensym@ --- * + * + * Arguments: @atom_table *t@ = pointer to a symbol table + * + * Returns: A pointer to a new atom block, not previously interned. + * + * Use: Creates a new, uninterned atom. This atom will never be + * returned by either @atom_intern@ or any other call to + * @atom_gensym@, while the symbol table exists. + */ + +#define GENSYM atom_gensym(ATOM_GLOBAL) + +extern atom *atom_gensym(atom_table */*t*/); + +/* --- @atom_name@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom's textual name. + * + * Use: Given an atom, returns the name with which it was interned + * (or a made-up name if it was created using @gensym@. + */ + +#define ATOM_NAME(a) SYM_NAME(a) + +extern const char *atom_name(const atom */*a*/); + +/* --- @atom_len@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom string's length. + * + * Use: Given an atom, return the length of its textual + * representation. + */ + +#define ATOM_LEN(a) (SYM_LEN(a) - 1) + +extern size_t atom_len(const atom */*a*/); + +/* --- @atom_hash@ --- * + * + * Arguments: @atom *a@ = pointer to an atom + * + * Returns: The atom's hash. + * + * Use: Given an atom, returns its hash. + */ + +#define ATOM_HASH(a) SYM_HASH(a) + +extern uint32 atom_hash(const atom */*a*/); + +/* --- @atom_mkiter@ , @atom_next@ --- * + * + * Arguments: @atom_table *t@ = pointer to an atom table + * @atom_iter *i@ = pointer to an iterator structure + * + * Returns: Next atom, for @atom_next@; nothing for @atom_mkiter@. + * + * Use: Iterates over atoms (both interned and uninterned). + */ + +extern void atom_mkiter(atom_iter */*i*/, atom_table */*t*/); +extern atom *atom_next(atom_iter */*i*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif