FreeBASIC  0.91.0
symb-namespace.bas
Go to the documentation of this file.
1 '' symbol table module for namespaces
2 '' (note: all functions but Add() and Del() can be used with any UDT)
3 ''
4 '' chng: may/2006 written [v1ctor]
5 
6 
7 #include once "fb.bi"
8 #include once "fbint.bi"
9 #include once "parser.bi"
10 
11 declare sub symbCompAddToImportList _
12  ( _
13  byval imp_ as FBSYMBOL ptr _
14  )
15 
16 declare sub symbCompDelFromImportList _
17  ( _
18  byval imp_ as FBSYMBOL ptr _
19  )
20 
21 declare sub symbCompAddToExportList _
22  ( _
23  byval imp_ as FBSYMBOL ptr _
24  )
25 
26 declare sub symbCompDelFromExportList _
27  ( _
28  byval imp_ as FBSYMBOL ptr _
29  )
30 
31 '':::::
32 function symbAddNamespace _
33  ( _
34  byval id as zstring ptr, _
35  byval id_alias as zstring ptr _
36  ) as FBSYMBOL ptr
37 
38  dim as FBSYMBOL ptr s = any
39 
40  '' no explict alias given?
41  if( id_alias = NULL ) then
42  '' only preserve a case-sensitive version if in BASIC mangling
43  if( parser.mangling <> FB_MANGLING_BASIC ) then
44  id_alias = id
45  end if
46  end if
47 
48  s = symbNewSymbol( FB_SYMBOPT_DOHASH, _
49  NULL, _
50  NULL, NULL, _
51  FB_SYMBCLASS_NAMESPACE, _
52  id, id_alias, _
53  FB_DATATYPE_NAMESPC, NULL )
54  if( s = NULL ) then
55  return NULL
56  end if
57 
58  symbSymbTbInit( s->nspc.ns.symtb, s )
59  symbHashTbInit( s->nspc.ns.hashtb, s, FB_INITSYMBOLNODES \ 10 )
60 
61  s->nspc.ns.ext = NULL
62  s->nspc.cnt = 0
63  s->nspc.last_tail = NULL
64 
65  function = s
66 
67 end function
68 
70  ( _
71  byval s as FBSYMBOL ptr, _
72  byval delete_hashtb as integer _
73  )
74 
75  '' The namespace can be a NAMESPACE, STRUCT or ENUM, assuming that
76  '' FBS_STRUCT, FBS_ENUM and FBS_NAMESPACE all extend FBNAMESPC.
77 
79 
80  '' Delete all member symbols, starting from last because of the USING's
81  '' that could be referencing a namespace in the same scope block
82  while( symbGetCompSymbTb( s ).tail )
83  symbDelSymbol( symbGetCompSymbTb( s ).tail, TRUE )
84  wend
85 
86  if( s->nspc.ns.ext ) then
87  symbCompFreeExt( s->nspc.ns.ext )
88  s->nspc.ns.ext = NULL
89  end if
90 
91  if( delete_hashtb ) then
92  hashEnd( @s->nspc.ns.hashtb.tb )
93  end if
94 end sub
95 
96 sub symbDelNamespace( byval s as FBSYMBOL ptr )
97  symbDelNamespaceMembers( s, TRUE )
98  symbFreeSymbol( s )
99 end sub
100 
101 '':::::
102 function hAddImport _
103  ( _
104  byval dst_ns as FBSYMBOL ptr _
105  ) as FBSYMBOL ptr
106 
107  dim as FBSYMBOLTB ptr symbtb = any
108  dim as FBHASHTB ptr hashtb = any
109  dim as integer is_local = any
110 
111  if( dst_ns = symbGetCurrentNamespc( ) ) then
112  symbtb = NULL
113  hashtb = NULL
114  is_local = 0
115  else
116  symbtb = @symbGetCompSymbTb( dst_ns )
117  hashtb = @symbGetCompHashTb( dst_ns )
118  is_local = symbIsLocal( dst_ns )
119  end if
120 
121  '' easier to be added as a symbol because it will be removed
122  '' respecting the scope blocks (or procs)
123  function = symbNewSymbol( FB_SYMBOPT_NONE, _
124  NULL, _
125  symbtb, hashtb, _
126  FB_SYMBCLASS_NSIMPORT, _
127  NULL, NULL, _
128  FB_DATATYPE_INVALID, NULL, _
129  is_local )
130 end function
131 
132 '':::::
133 sub hAddToHashTbList _
134  ( _
135  byval ns as FBSYMBOL ptr _
136  )
137 
138  '' add it to hash tb list
139  symbGetCompExt( ns )->cnt += 1
140  if( symbGetCompExt( ns )->cnt = 1 ) then
141  symbHashListInsertNamespace( ns, symbGetCompSymbTb( ns ).head )
142  end if
143 
144 end sub
145 
146 '':::::
147 sub hDelFromHashTbList _
148  ( _
149  byval ns as FBSYMBOL ptr _
150  )
151 
152  '' del the ns from hash tb list
153  symbGetCompExt( ns )->cnt -= 1
154  if( symbGetCompExt( ns )->cnt = 0 ) then
156  end if
157 
158 end sub
159 
160 '':::::
161 function hIsOnParentList _
162  ( _
163  byval src_ns as FBSYMBOL ptr, _
164  byval dst_ns as FBSYMBOL ptr _
165  ) as integer
166 
167  dim as FBSYMBOL ptr parent = dst_ns
168  do until( parent = @symbGetGlobalNamespc( ) )
169  if( src_ns = parent ) then
170  return TRUE
171  end if
172  parent = symbGetNamespace( parent )
173  loop
174 
175  function = FALSE
176 
177 end function
178 
179 '':::::
180 function hIsOnImportList _
181  ( _
182  byval src_ns as FBSYMBOL ptr, _
183  byval dst_ns as FBSYMBOL ptr _
184  ) as integer
185 
186  if( symbGetCompExt( dst_ns ) <> NULL ) Then
187 
188  dim as FBSYMBOL ptr imp_ = symbGetCompImportHead( dst_ns )
189 
190  do while( imp_ <> NULL )
191  if( symbGetImportNamespc( imp_ ) = src_ns ) then
192  return TRUE
193  end if
194  imp_ = symbGetImportNext( imp_ )
195  Loop
196 
197  End if
198 
199  function = FALSE
200 
201 end function
202 
203 '':::::
204 function symbNamespaceImportEx _
205  ( _
206  byval ns as FBSYMBOL ptr, _
207  byval to_ns as FBSYMBOL ptr _
208  ) as integer
209 
210  '' importing itself or a parent?
211  if( hIsOnParentList( ns, to_ns ) ) then
212  return FALSE
213  end if
214 
215  if( symbGetCompExt( ns ) = NULL ) then
216  symbGetCompExt( ns ) = symbCompAllocExt( )
217  end if
218 
219  '' not already on list?
220  if( hIsOnImportList( ns, to_ns ) = FALSE ) then
221  dim as FBSYMBOL ptr imp_ = any
222 
223  imp_ = hAddImport( to_ns )
224  if( imp_ = NULL ) then
225  return FALSE
226  end if
227 
228  imp_->nsimp.imp_ns = ns
229  imp_->nsimp.exp_ns = to_ns
230 
231  '' add to the import list of the dst ns
233 
234  '' add to the export list of the src ns
236 
237  '' recurse into the imported ns, importing its imports too
238  imp_ = symbGetCompImportHead( ns )
239  do while( imp_ <> NULL )
240  symbNamespaceImportEx( symbGetImportNamespc( imp_ ), to_ns )
241  imp_ = symbGetImportNext( imp_ )
242  loop
243 
244  '' add to hash tb list
245  hAddToHashTbList( ns )
246  end if
247 
248  function = TRUE
249 
250 end function
251 
252 '':::::
253 function symbNamespaceImport _
254  ( _
255  byval ns as FBSYMBOL ptr _
256  ) as integer
257 
258  function = symbNamespaceImportEx( ns, symbGetCurrentNamespc( ) )
259 
260 end function
261 
262 '':::::
264  ( _
265  byval imp_ as FBSYMBOL ptr, _
266  byval hashonly as integer _
267  )
268 
269  if( symbGetImportNamespc( imp_ ) <> NULL ) then
270  '' remove all USING's
271  hDelFromHashTbList( symbGetImportNamespc( imp_ ) )
274  symbGetImportNamespc( imp_ ) = NULL
275  end if
276 
277  if( hashonly = FALSE ) then
278  '' del node
279  symbFreeSymbol( imp_ )
280  end if
281 
282 end sub
283 
284 '':::::
286  ( _
287  byval ns as FBSYMBOL ptr _
288  )
289 
290  '' currently at the import hash tb?
291  if( symbGetCompExt( ns )->impsym_head <> NULL ) then
292  dim as FBSYMBOL ptr head = symbGetNamespaceLastTail( ns )
293  if( head = NULL ) then
294  head = symbGetNamespaceTbHead( ns )
295  else
296  '' skip the last (already added)
297  head = head->next
298  end if
299 
300  if( head <> NULL ) then
301  symbHashListInsertNamespace( ns, head )
302  end if
303  end if
304 
305  '' for each namespace importing this namespace, update
306  '' their import lists with our import list (that could
307  '' have been updated in the re-implementation)
308  dim as FBSYMBOL ptr exp_ = symbGetCompExportHead( ns )
309  do while( exp_ <> NULL )
310  dim as FBSYMBOL ptr imp_ = symbGetCompImportHead( ns )
311  do while( imp_ <> NULL )
312  symbNamespaceImportEx( symbGetImportNamespc( imp_ ), _
313  symbGetExportNamespc( exp_ ) )
314  imp_ = symbGetImportNext( imp_ )
315  loop
316  exp_ = symbGetExportNext( exp_ )
317  loop
318 
319 end sub
320 
321