File: Literal.c

package info (click to toggle)
saml 970418-4
  • links: PTS
  • area: main
  • in suites: potato
  • size: 1,208 kB
  • ctags: 1,706
  • sloc: ansic: 17,182; sh: 2,583; yacc: 497; perl: 264; makefile: 254; python: 242
file content (146 lines) | stat: -rw-r--r-- 3,277 bytes parent folder | download | duplicates (3)
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);
}