1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
/*
* Copyright 1995,96 Thierry Bousch
* Licensed under the Gnu Public License, Version 2
*
* $Id: Literal.c,v 2.3 1996/07/18 17:37:04 bousch Exp $
*
* Literals are really just strings. Unlike other types, each object is
* unique: different mnodes will never contain the same string.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "saml.h"
#include "mnode.h"
#include "builtin.h"
typedef struct _literal {
struct mnode_header hdr;
struct _literal *next;
char name[0];
} literal;
#define INITIAL_HASHSIZE 59
static literal **hashtable = NULL;
static unsigned int hashsize = 0;
static unsigned int entries = 0;
static void literal_free (literal*);
static s_mnode* literal_build (const char*);
static gr_string* literal_stringify (literal*);
static int literal_differ (literal*, literal*);
static int literal_lessthan (literal*, literal*);
static unsafe_s_mtype MathType_Literal = {
"Literal",
literal_free, literal_build, literal_stringify,
NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, literal_differ, literal_lessthan,
NULL, NULL, NULL, NULL, NULL
};
static unsigned int hash_value (const char *str)
{
unsigned int hash = 0;
char c;
while ((c = *str++) != '\0')
hash += (hash<<2) + (unsigned char)c;
return hash % hashsize;
}
static void resize_htable (unsigned int new_size)
{
literal *list, *p, *q;
unsigned int i, h;
#ifdef DEBUG_LITERALS
fprintf(stderr, "Resizing literal hash-table from %d to %d slots\n",
lit_hsize, new_size);
#endif
/* First step: link all nodes on the "list" */
list = NULL;
for (i = 0; i < hashsize; i++)
for (p = hashtable[i]; p; p = q) {
q = p->next;
p->next = list;
list = p;
}
hashtable = realloc(hashtable, new_size * sizeof(literal*));
if (hashtable == NULL)
panic_out_of_memory();
hashsize = new_size;
memset(hashtable, 0, hashsize * sizeof(literal*));
/* And insert them again in the new table */
for (p = list; p; p = q) {
q = p->next;
h = hash_value(p->name);
p->next = hashtable[h];
hashtable[h] = p;
}
}
void init_MathType_Literal (void)
{
register_mtype(ST_LITERAL, &MathType_Literal);
resize_htable(INITIAL_HASHSIZE);
}
static void literal_free (literal *mn)
{
literal *q, **old;
unsigned int h = hash_value(mn->name);
for (old = &hashtable[h]; (q = *old) != NULL; old = &q->next)
if (q == mn) {
*old = q->next;
break;
}
assert(mn == q);
free(mn);
--entries;
}
static s_mnode* literal_build (const char *str)
{
unsigned int h = hash_value(str);
size_t length;
literal *p;
for (p = hashtable[h]; p; p = p->next)
if (strcmp(str, p->name) == 0)
return copy_mnode((s_mnode*)p);
/*
* Not found: create a new literal
*/
length = sizeof(literal) + strlen(str) + 1;
p = (literal*) __mnalloc(ST_LITERAL, length);
strcpy(p->name, str);
p->next = hashtable[h];
hashtable[h] = p;
if (++entries > hashsize)
resize_htable(2*hashsize+1);
return (s_mnode*) p;
}
static gr_string* literal_stringify (literal* p)
{
char *name = p->name;
gr_string *grs = new_gr_string(0);
return grs_append(grs, name, strlen(name));
}
static int literal_differ (literal* p1, literal* p2)
{
return (p1 != p2);
}
static int literal_lessthan (literal* p1, literal* p2)
{
return (p1 < p2);
}
|