aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/tunits/unhash.x
blob: 3ae9c24e9db97449bbf354ed293a87531b7ecd3d (plain) (blame)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# A set of procedures that implement a generic hash table. The hash table
# stores the key, plus a pointer to the value structure. It should be 
# wrapped  in a more specific set of calls that can read the value structure

define	LEN_UNHSTRUCT	5

define	UNH_SIZE	Memi[$1]
define	UNH_NEXT	Memi[$1+1]
define	UNH_KEYBUF	Memi[$1+2]
define	UNH_VALBUF	Memi[$1+3]
define	UNH_STRBUF	Memi[$1+4]

define	UNH_KEY		Memi[UNH_KEYBUF($1)+$2]
define	UNH_VALUE	Memi[UNH_VALBUF($1)+$2]

#* HISTORY *
#* B.Simon	07-Jan-99	Original

# ADD_UNHASH -- Add a new keyword and value to the hash table

procedure add_unhash (hash, keyword, value)

pointer	hash		# i: Descriptor of hash table
char	keyword[ARB]	# i: Keyword to add to hash table
pointer	value		# i: Value descriptor
#--
int	index, nc

string	duplicate  "Cannot add duplicate keyword to hash table"

int	gstrcpy(), loc_unhash()

begin
	# Find where keyword should be inserted

	index = loc_unhash (hash, keyword)

	# Adding duplicate keywords is not allowed

	if (UNH_KEY(hash,index) != NULL) {
	    call tuniterr (duplicate, keyword)

	} else {
	    UNH_KEY(hash,index) = UNH_NEXT(hash)
	    UNH_VALUE(hash,index) = value

	    nc = gstrcpy (keyword, Memc[UNH_NEXT(hash)], ARB)
	    UNH_NEXT(hash) = UNH_NEXT(hash) + nc + 1
	}
end

# CALC_UNHASH -- Calculate hash index and step size from keyword

procedure calc_unhash (hash, keyword, index, step)

pointer	hash		# i: Descriptor of hash table
char	keyword[ARB]	# i: Keyword to search for in hash table
int	index		# o: Location to place keyword at in hash
int	step		# o: Step size in case location is filled
#--
int	ic

begin
	# Standard hash table function based on munging characters
 
	index = 0
	step = 0

	for (ic = 1; keyword[ic] != EOS; ic = ic + 1) {
	    index = 2 * index + keyword[ic]
	    step = step + keyword[ic]
	}

	# This line ensures the step size is odd

	step = step - mod (step, 2) + 1
end

# EACH_UNHASH -- Retrieve values from hash table serially

int procedure each_unhash (hash, index, keyword, value, maxch)

pointer	hash		# i: Descriptor of hash table
int	index		# u: Index of next slot in hash table to examine
char	keyword[ARB]	# o: Keyword name
pointer	value		# o: Keyword value
int	maxch		# i: Maximum length of keyword
#--

begin
	while (index < UNH_SIZE(hash)) {
	    if (UNH_KEY(hash,index) != NULL) {
		call strcpy (Memc[UNH_KEY(hash,index)], keyword, maxch)
		value = UNH_VALUE(hash,index)
		index = index + 1
		return (OK)
	    }

	    index = index + 1
	}

	return (EOF)
end

# FREE_UNHASH -- Free a hash table

procedure free_unhash (hash)

pointer	hash		# i: hash table descriptor
#--

begin
	# This code assumes that all memory associated 
	# with the values has already been freed

	call mfree (UNH_STRBUF(hash), TY_CHAR)
	call mfree (UNH_VALBUF(hash), TY_INT)
	call mfree (UNH_KEYBUF(hash), TY_INT)
	call mfree (hash, TY_INT)
end

# GET_UNHASH -- Return a keyword's value from a hash

int procedure get_unhash (hash, keyword, value)

pointer	hash		# i: Descriptor of hash table
char	keyword[ARB]	# i: Keyword to add to hash table
pointer	value		# o: pointer to hash table value
#--
int	index, status

int	loc_unhash ()

begin
	# The keyword is found if its slot is not null

	index = loc_unhash (hash, keyword)

	if (UNH_KEY(hash,index) == NULL) {
	    value = NULL
	    status = NO
	} else {
	    value = UNH_VALUE(hash,index)
	    status = YES
	}

	return (status)
end

# LOC_UNHASH -- Return index of location where a key should be inserted

int procedure loc_unhash (hash, keyword)

pointer	hash		# i: Descriptor of hash table
char	keyword[ARB]	# i: Keyword to add to hash table
#--
int	index, step

bool	streq()

begin
	# Calculate initial guess at position in hash table
	# and step size in case guessed position is already filled

	call calc_unhash (hash, keyword, index, step)
	index = mod (index, UNH_SIZE(hash))

	# Loop until an empty slot is found or the keyword is matched

	repeat {
	    if (UNH_KEY(hash,index) == NULL) {
		break

	    } else if (streq (Memc[UNH_KEY(hash,index)], keyword)) {
		break
	    }

	    index = mod (index + step, UNH_SIZE(hash))
	}

	return (index)
end

# NEW_UNHASH -- Create a new hash table

pointer procedure new_unhash (nkey, keysize)

int	nkey		# i: number of keywords in the hash
int	keysize		# i: maximum length of a key
#--
int	size
pointer	hash

begin
	# Find a power of two greater than the number of keywords

	for (size = 1; size < 2 * nkey; size = 2 * size)
	    ;

	# Allocate structure for hash and set initial values

	call malloc (hash, LEN_UNHSTRUCT, TY_INT)
	call calloc (UNH_KEYBUF(hash), size, TY_INT)
	call calloc (UNH_VALBUF(hash), size, TY_INT)
	call malloc (UNH_STRBUF(hash), size*(keysize+1), TY_CHAR)

	UNH_SIZE(hash) = size
	UNH_NEXT(hash) = UNH_STRBUF(hash)

	return (hash)
end