1 // Buffer variable binding interface
2 // Copyright (C) 2000 Core Technologies.
3 
4 // This file is part of e93.
5 //
6 // e93 is free software; you can redistribute it and/or modify
7 // it under the terms of the e93 LICENSE AGREEMENT.
8 //
9 // e93 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // e93 LICENSE AGREEMENT for more details.
13 //
14 // You should have received a copy of the e93 LICENSE AGREEMENT
15 // along with e93; see the file "LICENSE.TXT".
16 
17 #include	"includes.h"
18 
19 typedef struct variableBinding
20 {
21 	struct variableBinding
22 		*previousBinding,					// pointer to previous binding in the global binding list
23 		*nextBinding,						// pointer to next binding in the global binding list (in user defined order)
24 		*nextHashBinding;					// pointer to next binding in local hash list
25 	char
26 		*variableName,						// name of this variable
27 		*variableText;						// data contained in this variable
28 } VARIABLE_BINDING;
29 
GetBindingHashListHead(VARIABLE_TABLE * variableTable,char * variableName)30 static VARIABLE_BINDING **GetBindingHashListHead(VARIABLE_TABLE *variableTable,char *variableName)
31 // perform hashing function on variableName, return pointer to list head
32 // for bindings
33 {
34 	UINT32
35 		count,
36 		length,
37 		sum;
38 
39 	length=strlen(variableName);
40 	sum=0;
41 	for(count=0;count<length;count++)			// very crude hash function
42 	{
43 		sum+=variableName[count];
44 	}
45 	return(&(variableTable->variableBindingTable[sum&0xFF]));
46 }
47 
GetVariableBindingName(VARIABLE_BINDING * binding)48 char *GetVariableBindingName(VARIABLE_BINDING *binding)
49 // return a pointer to the variable binding name for binding
50 {
51 	return(binding->variableName);
52 }
53 
GetVariableBindingText(VARIABLE_BINDING * binding)54 char *GetVariableBindingText(VARIABLE_BINDING *binding)
55 // return a pointer to the variable binding text for binding
56 {
57 	return(binding->variableText);
58 }
59 
LocateVariableBindingLocation(VARIABLE_TABLE * variableTable,char * variableName,VARIABLE_BINDING *** hashListHead,VARIABLE_BINDING ** previousHashEntry,VARIABLE_BINDING ** entry)60 static bool LocateVariableBindingLocation(VARIABLE_TABLE *variableTable,char *variableName,VARIABLE_BINDING ***hashListHead,VARIABLE_BINDING **previousHashEntry,VARIABLE_BINDING **entry)
61 // locate a variable binding in the binding table, return pointers to important entries
62 {
63 	bool
64 		found;
65 	VARIABLE_BINDING
66 		*currentEntry;
67 
68 	currentEntry=*(*hashListHead=GetBindingHashListHead(variableTable,variableName));	// point to the head of the linked list at this hash entry
69 	*previousHashEntry=NULL;
70 	found=false;
71 	while(currentEntry&&!found)
72 	{
73 		if(strcmp(variableName,currentEntry->variableName)==0)
74 		{
75 			found=true;
76 			*entry=currentEntry;
77 		}
78 		else
79 		{
80 			*previousHashEntry=currentEntry;
81 			currentEntry=currentEntry->nextHashBinding;
82 		}
83 	}
84 	return(found);
85 }
86 
LocateNextVariableBinding(VARIABLE_BINDING * currentBinding)87 VARIABLE_BINDING *LocateNextVariableBinding(VARIABLE_BINDING *currentBinding)
88 // return the next variable binding from the current one
89 // if there is none, return NULL
90 {
91 	return(currentBinding->nextBinding);
92 }
93 
LocateVariableBinding(VARIABLE_TABLE * variableTable,char * variableName)94 VARIABLE_BINDING *LocateVariableBinding(VARIABLE_TABLE *variableTable,char *variableName)
95 // find a key binding that matches the variableName, and return it
96 // if there is none, return NULL
97 {
98 	bool
99 		found;
100 	VARIABLE_BINDING
101 		*currentEntry;
102 
103 	currentEntry=*GetBindingHashListHead(variableTable,variableName);	// point to the head of the linked list at this hash entry
104 	found=false;
105 	while(currentEntry&&!found)
106 	{
107 		if(strcmp(variableName,currentEntry->variableName)==0)
108 		{
109 			found=true;
110 		}
111 		else
112 		{
113 			currentEntry=currentEntry->nextHashBinding;
114 		}
115 	}
116 	return(currentEntry);
117 }
118 
DeleteVariableBinding(VARIABLE_TABLE * variableTable,char * variableName)119 bool DeleteVariableBinding(VARIABLE_TABLE *variableTable,char *variableName)
120 // attempt to locate the given binding in variableTable, and
121 // remove it if it is found
122 // if it is not located, return false
123 {
124 	VARIABLE_BINDING
125 		**hashListHead,
126 		*previousHashEntry,
127 		*entry;
128 
129 	if(LocateVariableBindingLocation(variableTable,variableName,&hashListHead,&previousHashEntry,&entry))
130 	{
131 		if(previousHashEntry)
132 		{
133 			previousHashEntry->nextHashBinding=entry->nextHashBinding;		// unlink the located entry
134 		}
135 		else
136 		{
137 			*hashListHead=entry->nextHashBinding;
138 		}
139 		if(entry->previousBinding)
140 		{
141 			if((entry->previousBinding->nextBinding=entry->nextBinding))
142 			{
143 				entry->nextBinding->previousBinding=entry->previousBinding;
144 			}
145 		}
146 		else
147 		{
148 			if((variableTable->variableBindingListHead=entry->nextBinding))
149 			{
150 				variableTable->variableBindingListHead->previousBinding=NULL;
151 			}
152 		}
153 		MDisposePtr(entry->variableName);
154 		MDisposePtr(entry->variableText);
155 		MDisposePtr(entry);
156 		return(true);
157 	}
158 	return(false);
159 }
160 
CreateVariableBinding(VARIABLE_TABLE * variableTable,char * variableName,char * variableText)161 bool CreateVariableBinding(VARIABLE_TABLE *variableTable,char *variableName,char *variableText)
162 // search the variable binding table for an entry that matches the one given, and delete it if
163 // it exists. Then add this entry to the table
164 // if there is a problem, SetError, and return false
165 {
166 	VARIABLE_BINDING
167 		**hashListHead,
168 		*newEntry;
169 
170 	DeleteVariableBinding(variableTable,variableName);					// try to delete one if it exists
171 	hashListHead=GetBindingHashListHead(variableTable,variableName);	// point to head of list in hash table where this binding will go
172 	if((newEntry=(VARIABLE_BINDING *)MNewPtr(sizeof(VARIABLE_BINDING))))
173 	{
174 		if((newEntry->variableName=(char *)MNewPtr(strlen(variableName)+1)))
175 		{
176 			if((newEntry->variableText=(char *)MNewPtr(strlen(variableText)+1)))
177 			{
178 				strcpy(newEntry->variableName,variableName);			// copy in name
179 				strcpy(newEntry->variableText,variableText);			// copy in text
180 				newEntry->nextHashBinding=*hashListHead;
181 				*hashListHead=newEntry;									// link to head of hash list
182 				newEntry->previousBinding=NULL;
183 				if((newEntry->nextBinding=variableTable->variableBindingListHead))	// point to the next entry
184 				{
185 					variableTable->variableBindingListHead->previousBinding=newEntry;
186 				}
187 				variableTable->variableBindingListHead=newEntry;
188 				return(true);
189 			}
190 			MDisposePtr(newEntry->variableName);
191 		}
192 		MDisposePtr(newEntry);
193 	}
194 	return(false);
195 }
196 
InitVariableBindingTable(VARIABLE_TABLE * variableTable)197 bool InitVariableBindingTable(VARIABLE_TABLE *variableTable)
198 // clear the variable binding table so that there are no bindings present
199 // if there is a problem, SetError, and return false
200 {
201 	int
202 		i;
203 
204 	for(i=0;i<256;i++)
205 	{
206 		variableTable->variableBindingTable[i]=NULL;
207 	}
208 	variableTable->variableBindingListHead=NULL;
209 	return(true);
210 }
211 
UnInitVariableBindingTable(VARIABLE_TABLE * variableTable)212 void UnInitVariableBindingTable(VARIABLE_TABLE *variableTable)
213 // remove all variable bindings from the bindings table
214 {
215 	int
216 		i;
217 	VARIABLE_BINDING
218 		*currentEntry,
219 		*nextEntry;
220 
221 	for(i=0;i<256;i++)
222 	{
223 		currentEntry=variableTable->variableBindingTable[i];
224 		while(currentEntry)
225 		{
226 			nextEntry=currentEntry->nextHashBinding;
227 			MDisposePtr(currentEntry->variableName);
228 			MDisposePtr(currentEntry->variableText);
229 			MDisposePtr(currentEntry);
230 			currentEntry=nextEntry;
231 		}
232 		variableTable->variableBindingTable[i]=NULL;
233 	}
234 	variableTable->variableBindingListHead=NULL;
235 }
236