1 /*
2    Copyright (c) 1991-1999 Thomas T. Wetmore IV
3 
4    Permission is hereby granted, free of charge, to any person
5    obtaining a copy of this software and associated documentation
6    files (the "Software"), to deal in the Software without
7    restriction, including without limitation the rights to use, copy,
8    modify, merge, publish, distribute, sublicense, and/or sell copies
9    of the Software, and to permit persons to whom the Software is
10    furnished to do so, subject to the following conditions:
11 
12    The above copyright notice and this permission notice shall be
13    included in all copies or substantial portions of the Software.
14 
15    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22    SOFTWARE.
23 */
24 /*=============================================================
25  * symtab.c -- Symbol tables (lexical scopes)
26  * Copyright(c) 1991-95 by T.T. Wetmore IV; all rights reserved
27  * Created: 2002.02.17 by Perry Rapp, out of pvalue.c
28  *===========================================================*/
29 
30 #include "llstdlib.h"
31 #include "table.h"
32 #include "translat.h"
33 #include "gedcom.h"
34 #include "cache.h"
35 #include "interpi.h"
36 #include "liflines.h"
37 #include "feedback.h"
38 #include "vtable.h"
39 
40 
41 /*********************************************
42  * local types
43  *********************************************/
44 
45 struct tag_symtab_iter {
46 	struct tag_vtable *vtable; /* generic object */
47 	INT refcnt; /* ref-countable object */
48 	TABLE_ITER tabit; /* iterator over our table of symbols */
49 };
50 /* typedef struct tag_symtab_iter *SYMTAB_ITER; */ /* in interpi.h */
51 
52 /*********************************************
53  * local function prototypes
54  *********************************************/
55 
56 /* alphabetical */
57 static SYMTAB create_symtab(CNSTRING title, SYMTAB parstab);
58 static void free_symtable_iter(SYMTAB_ITER symtabit);
59 static void record_dead_symtab(SYMTAB symtab);
60 static void record_live_symtab(SYMTAB symtab);
61 static void symtabit_destructor(VTABLE *obj);
62 
63 /*********************************************
64  * local variables
65  *********************************************/
66 
67 static struct tag_vtable vtable_for_symtabit = {
68 	VTABLE_MAGIC
69 	, "symtab_iter"
70 	, &symtabit_destructor
71 	, &refcountable_isref
72 	, &refcountable_addref
73 	, &refcountable_release
74 	, 0 /* copy_fnc */
75 	, &generic_get_type_name
76 };
77 
78 LIST live_symtabs=0; /* list of symbol tables, to check for leaks */
79 
80 /*********************************************
81  * local function definitions
82  * body of module
83  *********************************************/
84 
85 /*======================================================
86  * insert_symtab -- Update symbol table with PVALUE
87  *  stab: [I/O] symbol table
88  *  iden: [IN] variable in symbol table
89  *  val:  [IN]  already created PVALUE
90  *====================================================*/
91 void
insert_symtab(SYMTAB stab,CNSTRING iden,PVALUE val)92 insert_symtab (SYMTAB stab, CNSTRING iden, PVALUE val)
93 {
94 	insert_table_ptr(stab->tab, iden, val);
95 }
96 /*======================================================
97  * delete_symtab_element -- Delete a value from a symbol table
98  *  stab: [I/O] symbol table
99  *  iden: [IN]  variable in symbol table
100  *====================================================*/
101 void
delete_symtab_element(SYMTAB stab,STRING iden)102 delete_symtab_element (SYMTAB stab, STRING iden)
103 {
104 	delete_table_element(stab->tab, iden);
105 }
106 /*========================================
107  * remove_symtab -- Remove symbol table
108  *  @stab:  [IN] symbol table to remove
109  *======================================*/
110 void
remove_symtab(SYMTAB stab)111 remove_symtab (SYMTAB stab)
112 {
113 	ASSERT(stab);
114 
115 	record_dead_symtab(stab);
116 
117 	destroy_table(stab->tab);
118 
119 	stdfree(stab);
120 }
121 /*======================================================
122  * create_symtab_proc -- Create a symbol table for a procedure
123  *  returns allocated SYMTAB
124  *====================================================*/
125 SYMTAB
create_symtab_proc(CNSTRING procname,SYMTAB parstab)126 create_symtab_proc (CNSTRING procname, SYMTAB parstab)
127 {
128 	char title[128];
129 	llstrncpyf(title, sizeof(title), uu8, "proc: %s", procname);
130 	return create_symtab(title, parstab);
131 }
132 /*======================================================
133  * create_symtab_global -- Create a global symbol table
134  *  returns allocated SYMTAB
135  *====================================================*/
136 SYMTAB
create_symtab_global(void)137 create_symtab_global (void)
138 {
139 	return create_symtab("global", NULL);
140 }
141 /*======================================================
142  * create_symtab -- Create a symbol table
143  *  @title:    [IN]  title (procedure or func name)
144  *  @parstab:  [IN]  (dynamic) parent symbol table
145  *                    only for debugging, not for scope
146  *  returns allocated SYMTAB
147  *====================================================*/
148 static SYMTAB
create_symtab(CNSTRING title,SYMTAB parstab)149 create_symtab (CNSTRING title, SYMTAB parstab)
150 {
151 	SYMTAB symtab = (SYMTAB)stdalloc(sizeof(*symtab));
152 	memset(symtab, 0, sizeof(*symtab));
153 
154 	symtab->tab = create_table_custom_vptr(delete_vptr_pvalue);
155 	symtab->parent = parstab;
156 	llstrncpyf(symtab->title, sizeof(symtab->title), uu8, title);
157 
158 	record_live_symtab(symtab);
159 
160 	return symtab;
161 }
162 /*======================================================
163  * record_live_symtab -- Add symbol table to live list
164  *====================================================*/
165 static void
record_live_symtab(SYMTAB symtab)166 record_live_symtab (SYMTAB symtab)
167 {
168 	if (!live_symtabs)
169 		live_symtabs = create_list2(LISTNOFREE);
170 	enqueue_list(live_symtabs, symtab);
171 }
172 /*======================================================
173  * record_dead_symtab -- Remove symbol table from live list
174  *====================================================*/
175 static void
record_dead_symtab(SYMTAB symtab)176 record_dead_symtab (SYMTAB symtab)
177 {
178 	LIST newlist = create_list2(LISTNOFREE);
179 	ASSERT(live_symtabs);
180 	ASSERT(length_list(live_symtabs)>0);
181 
182 	/* hard to delete an element, so create a new shorter list */
183 	FORLIST(live_symtabs, e)
184 		if (e != symtab)
185 			enqueue_list(newlist, e);
186 	ENDLIST
187 	destroy_list(live_symtabs);
188 	live_symtabs = newlist;
189 }
190 /*=================================================
191  * symbol_tables_end -- interpreter just finished running report
192  *===============================================*/
193 void
symbol_tables_end(void)194 symbol_tables_end (void)
195 {
196 	/* for debugging check that no symbol tables leaked */
197 	INT leaked_symtabs = length_list(live_symtabs);
198 	leaked_symtabs = leaked_symtabs; /* remove unused warning */
199 	/* 2005-02-06, 2200Z, Perry: No leaks here */
200 }
201 /*======================================================
202  * in_symtab -- Does symbol table have this entry ?
203  *  @stab: [IN]  symbol table
204  *  @key:  [IN]  key sought
205  *====================================================*/
206 BOOLEAN
in_symtab(SYMTAB stab,CNSTRING key)207 in_symtab (SYMTAB stab, CNSTRING key)
208 {
209 	return in_table(stab->tab, key);
210 }
211 /*======================================================
212  * symtab_valueofbool -- Convert pvalue to boolean if present
213  *  @stab:   [IN]  symbol table
214  *  @key:    [IN] key desired
215  *  @there:  [OUT] whether or not key was found
216  *  returns PVALUE assigned to key in symbol table, if found
217  *====================================================*/
218 PVALUE
symtab_valueofbool(SYMTAB stab,CNSTRING key,BOOLEAN * there)219 symtab_valueofbool (SYMTAB stab, CNSTRING key, BOOLEAN *there)
220 {
221 	return (PVALUE)valueofbool_ptr(stab->tab, key, there);
222 }
223 /*======================================================
224  * begin_symtab_iter -- Begin iterating a symbol table
225  *  @stab:   [IN]  symbol table to iterate
226  * returns iterator object ready to start
227  *====================================================*/
228 SYMTAB_ITER
begin_symtab_iter(SYMTAB stab)229 begin_symtab_iter (SYMTAB stab)
230 {
231 	SYMTAB_ITER symtabit = (SYMTAB_ITER)stdalloc(sizeof(*symtabit));
232 	memset(symtabit, 0, sizeof(*symtabit));
233 	symtabit->vtable = &vtable_for_symtabit;
234 	++symtabit->refcnt;
235 	symtabit->tabit = begin_table_iter(stab->tab);
236 	return symtabit;
237 }
238 /*======================================================
239  * next_symtab_entry -- Continue iterating a symbol table
240  *  @tabit: [I/O]  symbol table iterator
241  *  @pkey:  [OUT]  key of next value
242  *  @ppval: [OUT]  next value
243  *====================================================*/
244 BOOLEAN
next_symtab_entry(SYMTAB_ITER symtabit,CNSTRING * pkey,PVALUE * ppval)245 next_symtab_entry (SYMTAB_ITER symtabit, CNSTRING *pkey, PVALUE *ppval)
246 {
247 	VPTR vptr=0;
248 	*pkey=0;
249 	*ppval=0;
250 	if (!next_table_ptr(symtabit->tabit, pkey, &vptr))
251 		return FALSE;
252 	*ppval = vptr;
253 	return TRUE;
254 }
255 /*=================================================
256  * end_symtab_iter -- Release reference to symbol table iterator object
257  *===============================================*/
258 void
end_symtab_iter(SYMTAB_ITER * psymtabit)259 end_symtab_iter (SYMTAB_ITER * psymtabit)
260 {
261 	ASSERT(psymtabit);
262 	ASSERT(*psymtabit);
263 	end_table_iter(&(*psymtabit)->tabit);
264 	--(*psymtabit)->refcnt;
265 	if (!(*psymtabit)->refcnt) {
266 		free_symtable_iter(*psymtabit);
267 	}
268 	*psymtabit = 0;
269 }
270 /*=================================================
271  * free_symtable_iter -- Delete & free symbol table iterator object
272  *===============================================*/
273 static void
free_symtable_iter(SYMTAB_ITER symtabit)274 free_symtable_iter (SYMTAB_ITER symtabit)
275 {
276 	if (!symtabit) return;
277 	ASSERT(!symtabit->refcnt);
278 	memset(symtabit, 0, sizeof(*symtabit));
279 	stdfree(symtabit);
280 }
281 /*=================================================
282  * symtabit_destructor -- destructor for symbol table iterator
283  *  (destructor entry in vtable)
284  *===============================================*/
285 static void
symtabit_destructor(VTABLE * obj)286 symtabit_destructor (VTABLE *obj)
287 {
288 	SYMTAB_ITER symtabit = (SYMTAB_ITER)obj;
289 	ASSERT((*obj) == &vtable_for_symtabit);
290 	free_symtable_iter(symtabit);
291 }
292