FreeBASIC  0.91.0
symb.bas
Go to the documentation of this file.
1 '' symbol table core module
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "parser.bi"
9 #include once "hash.bi"
10 #include once "list.bi"
11 #include once "pool.bi"
12 
13 declare sub symbDelGlobalTb ( )
14 
15 declare sub symbKeywordInit ( )
16 
17 declare sub symbDefineInit ( _
18  byval ismain as integer _
19  )
20 
21 declare sub symbDefineEnd ( )
22 
23 declare sub symbFwdRefInit ( )
24 
25 declare sub symbFwdRefEnd ( )
26 
27 declare sub symbVarInit ( )
28 
29 declare sub symbVarEnd ( )
30 
31 declare sub symbProcInit ( )
32 
33 declare sub symbProcEnd ( )
34 
35 declare sub symbMangleInit ( )
36 
37 declare sub symbMangleEnd ( )
38 
39 declare sub symbCompInit ( )
40 
41 declare sub symbCompEnd ( )
42 
43 declare sub symbCompRTTIInit ( )
44 
45 declare sub symbCompRTTIEnd ( )
46 
47 
48 ''globals
49  dim shared as SYMBCTX symb
50 
51  dim shared as integer deftypeTB( 0 to (asc("_" ) - asc( "A" ) + 1) - 1 )
52 
53 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
54 '' init/end
55 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
56 
57 '':::::
58 sub symbInitSymbols static
59 
60  '' symbols list
61  listInit( @symb.symlist, FB_INITSYMBOLNODES, len( FBSYMBOL ), LIST_FLAGS_NOCLEAR )
62 
63  '' symbol id string pool
64  poolInit( @symb.namepool, FB_INITSYMBOLNODES \ 8, FB_MAXNAMELEN\8+1, FB_MAXNAMELEN+1 )
65 
66  symb.chainpoolhead = 0
67 
68  '' namespace extension's list
69  listInit( @symb.nsextlist, FB_INITSYMBOLNODES \ 16, len( FBNAMESPC_EXT ), LIST_FLAGS_CLEAR )
70 
71  '' global namespace - not complete, just a mock symbol
72  symb.globnspc.class = FB_SYMBCLASS_NAMESPACE
73  symb.globnspc.scope = FB_MAINSCOPE
74 
75  with symb.globnspc.nspc
76  symbSymbTbInit( .ns.symtb, @symb.globnspc )
77  symbHashTbInit( .ns.hashtb, @symb.globnspc, FB_INITSYMBOLNODES )
78  .ns.ext = symbCompAllocExt( )
79  end with
80 
81  ''
82  symb.namespc = @symb.globnspc
83  symb.symtb = @symb.globnspc.nspc.ns.symtb
84  symb.hashtb = @symb.globnspc.nspc.ns.hashtb
85 
86  ''
87  symb.hashlist.head = NULL
88  symb.hashlist.tail = NULL
89 
90  symbHashListAdd( symb.hashtb )
91 
92  '' import (USING) shared hash/list
93  hashInit( @symb.imphashtb, FB_INITSYMBOLNODES )
94  listInit( @symb.imphashlist, FB_INITSYMBOLNODES \ 2, len( FBSYMCHAIN ), LIST_FLAGS_NOCLEAR )
95 
96  ''
97  symb.lastlbl = NULL
98 
99  symbDataInit( )
100 
101 end sub
102 
103 '':::::
105  dim as integer dtype, i
106 
107  if( fbLangIsSet( FB_LANG_QB ) ) then
108  dtype = FB_DATATYPE_SINGLE
109  else
110  dtype = FB_DATATYPE_INTEGER
111  end if
112 
113  ''
114  for i = 0 to (asc("_")-asc("A")+1)-1
115  deftypeTB(i) = dtype
116  next
117 
118 end sub
119 
120 '':::::
121 sub symbInit _
122  ( _
123  byval ismain as integer _
124  )
125 
126  ''
127  if( symb.inited ) then
128  exit sub
129  end if
130 
131  '' vars, arrays, procs & consts
132  symbInitSymbols( )
133 
134  ''
135  symbCompInit( )
136 
137  ''
138  symbMangleInit( )
139 
140  '' keywords
141  symbKeywordInit( )
142 
143  '' defines
144  symbDefineInit( ismain )
145 
146  '' forward refs
147  symbFwdRefInit( )
148 
149  '' arrays dim tb
150  symbVarInit( )
151 
152  ''
153  symbProcInit( )
154 
155  ''
156  hInitDefTypeTb( )
157 
158  ''
160 
161  ''
162  symb.inited = TRUE
163 
164 end sub
165 
166 '':::::
168 
169  if( symb.inited = FALSE ) then
170  exit sub
171  end if
172 
173  ''
174  symbDelGlobalTb( )
175 
176  symbGetGlobalTb( ).head = NULL
177  symbGetGlobalTb( ).tail = NULL
178  symb.symtb = NULL
179 
180  ''
181  listEnd( @symb.imphashlist )
182  hashEnd( @symb.imphashtb )
183 
184  hashEnd( @symb.globnspc.nspc.ns.hashtb.tb )
185 
186  ''
187  symbCompRTTIEnd( )
188 
189  ''
190  symbProcEnd( )
191 
192  symbVarEnd( )
193 
194  symbFwdRefEnd( )
195 
196  symbDefineEnd( )
197 
198  symbMangleEnd( )
199 
200  symbCompEnd( )
201 
202  ''
203  symbCompFreeExt( symb.globnspc.nspc.ns.ext )
204 
205  ''
206  listEnd( @symb.nsextlist )
207 
208  poolEnd( @symb.namepool )
209 
210  listEnd( @symb.symlist )
211 
212  ''
213  symb.inited = FALSE
214 
215 end sub
216 
217 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
218 '' add
219 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
220 
221 '':::::
222 function symbCanDuplicate _
223  ( _
224  byval head_sym as FBSYMBOL ptr, _
225  byval s as FBSYMBOL ptr _
226  ) as integer
227 
228  function = FALSE
229 
230  select case as const s->class
231  '' adding a define, keyword, namespace, class or field?
232  case FB_SYMBCLASS_DEFINE, FB_SYMBCLASS_KEYWORD, _
233  FB_SYMBCLASS_NAMESPACE, FB_SYMBCLASS_CLASS, _
234  FB_SYMBCLASS_FIELD
235 
236  '' no dups allowed
237  exit function
238 
239  '' struct, enum or typedef?
240  case FB_SYMBCLASS_STRUCT, FB_SYMBCLASS_ENUM, _
241  FB_SYMBCLASS_TYPEDEF
242 
243  '' note: if it's a struct, we don't have to check if it's unique,
244  '' because that will be only set after the symbol is added
245 
246  do
247  select case as const head_sym->class
248  '' anything but a define or themselves is allowed (keywords
249  '' (but quirk-keywords) are refused when parsing)
250  case FB_SYMBCLASS_DEFINE, FB_SYMBCLASS_NAMESPACE, _
251  FB_SYMBCLASS_STRUCT, FB_SYMBCLASS_ENUM, _
252  FB_SYMBCLASS_TYPEDEF, FB_SYMBCLASS_CLASS, _
253  FB_SYMBCLASS_FIELD
254 
255  exit function
256  end select
257 
258  head_sym = head_sym->hash.next
259  loop while( head_sym <> NULL )
260 
261  '' forward ref?
262  case FB_SYMBCLASS_FWDREF
263 
264  do
265  select case head_sym->class
266  '' anything but a define or another forward ref is allowed (keywords
267  '' (but quirk-keywords) are refused when parsing)
268  case FB_SYMBCLASS_DEFINE, FB_SYMBCLASS_NAMESPACE, _
269  FB_SYMBCLASS_FWDREF, FB_SYMBCLASS_CLASS
270 
271  exit function
272 
273  '' struct? only it's not unique
274  case FB_SYMBCLASS_STRUCT
275  if( symbGetIsUnique( head_sym ) ) then
276  exit function
277  end if
278  end select
279 
280  head_sym = head_sym->hash.next
281  loop while( head_sym <> NULL )
282 
283  '' constant or proc?
284  case FB_SYMBCLASS_CONST, FB_SYMBCLASS_PROC
285 
286  do
287  select case as const head_sym->class
288  '' only dup allowed are labels and UDTs
289  case FB_SYMBCLASS_LABEL, FB_SYMBCLASS_ENUM, _
290  FB_SYMBCLASS_TYPEDEF, FB_SYMBCLASS_FWDREF
291 
292  '' struct? only it's not unique
293  case FB_SYMBCLASS_STRUCT
294  if( symbGetIsUnique( head_sym ) ) then
295  exit function
296  end if
297 
298  '' only if the keyword or the rtl-proc has a string suffix
299  case FB_SYMBCLASS_KEYWORD, FB_SYMBCLASS_PROC
300  if( env.clopt.lang <> FB_LANG_QB ) then
301  exit function
302  end if
303 
304  '' only if it's a RTL function..
305  if( symbIsProc( head_sym ) ) then
306  if( symbGetIsRTL( head_sym ) = FALSE ) then
307  exit function
308  else
309  '' both RTL? don't allow dup so overloaded procs
310  '' will get chained
311  if( symbGetIsRTL( head_sym ) ) then
312  exit function
313  end if
314  end if
315  end if
316 
317  '' nothing else takes a suffix but rtl-funcs returning strings
318  if( symbIsSuffixed( s ) ) then
319  if( symbGetType( s ) = symbGetType( head_sym ) ) then
320  exit function
321  end if
322  else
323  if( symbGetType( head_sym ) <> FB_DATATYPE_STRING ) then
324  exit function
325  end if
326  end if
327 
328  case else
329  exit function
330  end select
331 
332  head_sym = head_sym->hash.next
333  loop while( head_sym <> NULL )
334 
335  '' variable?
336  case FB_SYMBCLASS_VAR
337 
338  do
339  select case as const head_sym->class
340  '' allow labels or UDTs as dups
341  case FB_SYMBCLASS_LABEL, FB_SYMBCLASS_ENUM, _
342  FB_SYMBCLASS_TYPEDEF, FB_SYMBCLASS_FWDREF
343 
344  '' struct? only it's not unique
345  case FB_SYMBCLASS_STRUCT
346  if( symbGetIsUnique( head_sym ) ) then
347  exit function
348  end if
349 
350  '' only if the keyword or the rtl-proc has a string suffix
351  case FB_SYMBCLASS_KEYWORD, FB_SYMBCLASS_PROC
352  if( env.clopt.lang <> FB_LANG_QB ) then
353  exit function
354  end if
355 
356  '' only if it's a RTL function..
357  if( symbIsProc( head_sym ) ) then
358  if( symbGetIsRTL( head_sym ) = FALSE ) then
359  exit function
360  end if
361  end if
362 
363  '' nothing else takes a suffix but rtl-funcs returning strings
364  if( symbIsSuffixed( s ) ) then
365  if( symbGetType( s ) = symbGetType( head_sym ) ) then
366  exit function
367  end if
368  else
369  if( symbGetType( head_sym ) <> FB_DATATYPE_STRING ) then
370  exit function
371  end if
372  end if
373 
374  '' allow fields dups, if in a different scope
375  case FB_SYMBCLASS_FIELD
376  '' same scope?
377  if( s->scope = head_sym->scope ) then
378  exit function
379  end if
380 
381  '' and other vars if they have different suffixes -- if any
382  '' with suffix exist, a suffix-less will not be accepted (and vice-versa)
383  case FB_SYMBCLASS_VAR
384  '' same scope?
385  if( s->scope = head_sym->scope ) then
386  if( env.clopt.lang = FB_LANG_FB ) then
387  exit function
388  end if
389 
390  '' same data type?
391  if( symbGetType( head_sym ) = symbGetType( s ) ) then
392  exit function
393  end if
394 
395  '' neither has a suffix?
396  if( ( symbIsSuffixed( head_sym ) = FALSE ) and ( symbIsSuffixed( s ) = FALSE ) ) then
397  exit function
398  end if
399 
400  end if
401 
402  case else
403  exit function
404  end select
405 
406  head_sym = head_sym->hash.next
407  loop while( head_sym <> NULL )
408 
409  '' label?
410  case FB_SYMBCLASS_LABEL
411 
412  do
413  select case as const head_sym->class
414  '' anything but a define, keyword or another label is allowed
415  case FB_SYMBCLASS_DEFINE, FB_SYMBCLASS_NAMESPACE, _
416  FB_SYMBCLASS_KEYWORD, FB_SYMBCLASS_LABEL, _
417  FB_SYMBCLASS_CLASS
418 
419  exit function
420 
421  '' struct? only it's not unique
422  case FB_SYMBCLASS_STRUCT
423  if( symbGetIsUnique( head_sym ) ) then
424  exit function
425  end if
426  end select
427 
428  head_sym = head_sym->hash.next
429  loop while( head_sym <> NULL )
430 
431  '' param?
432  case FB_SYMBCLASS_PARAM
433 
434  '' anything allowed, dups are only checked when adding params as variables
435 
436  end select
437 
438  function = TRUE
439 
440 end function
441 
442 '':::::
443 function symbNewSymbol _
444  ( _
445  byval options as FB_SYMBOPT, _
446  byval s as FBSYMBOL ptr, _
447  byval symtb as FBSYMBOLTB ptr, _
448  byval hashtb as FBHASHTB ptr, _
449  byval class_ as FB_SYMBCLASS, _
450  byval id as const zstring ptr, _
451  byval id_alias as const zstring ptr, _
452  byval dtype as integer, _
453  byval subtype as FBSYMBOL ptr, _
454  byval attrib as FB_SYMBATTRIB _
455  ) as FBSYMBOL ptr
456 
457  dim as integer slen = any, delok = any
458 
459  function = NULL
460 
461  if( symtb = NULL ) then
462  symtb = symb.symtb
463 
464  '' parsing main?
465  if( fbIsModLevel( ) ) then
466  '' add to global tb, unless it's inside a scope block..
467  if( parser.scope = FB_MAINSCOPE ) then
468  '' not inside a namespace?
469  if( symbIsGlobalNamespc( ) ) then
470  '' symb.symbtb is pointing to main's symtb (due the
471  '' implicit main function), so it can't be used
472  symtb = @symbGetGlobalTb( )
473  end if
474 
475  attrib and= not FB_SYMBATTRIB_LOCAL
476  else
477  attrib or= FB_SYMBATTRIB_LOCAL
478  end if
479  else
480  attrib or= FB_SYMBATTRIB_LOCAL
481  end if
482  end if
483 
484  if( hashtb = NULL ) then
485  hashtb = symb.hashtb
486  end if
487 
488  '' alloc symbol node?
489  delok = FALSE
490  if( s = NULL ) then
491  delok = TRUE
492  s = listNewNode( @symb.symlist )
493  end if
494 
495  ''
496  s->class = class_
497  s->attrib = attrib
498  s->stats = 0
499  s->mangling = parser.mangling
500 
501  s->typ = dtype
502  s->subtype = subtype
503 
504  '' QB quirks
505  if( (options and FB_SYMBOPT_UNSCOPE) <> 0 ) then
506  if( (parser.currproc->stats and (FB_SYMBSTATS_MAINPROC or _
507  FB_SYMBSTATS_MODLEVELPROC)) <> 0 ) then
508  s->scope = FB_MAINSCOPE
509  else
510  s->scope = parser.currproc->scope + 1
511  end if
512  else
513  s->scope = parser.scope
514  end if
515 
516  '' name
517  slen = iif( id <> NULL, len( *id ), 0 )
518  if( slen > 0 ) then
519  s->id.name = poolNewItem( @symb.namepool, slen + 1 ) 'ZstrAllocate( slen )
520  if( (options and FB_SYMBOPT_PRESERVECASE) = 0 ) then
521  hUcase( id, s->id.name )
522  else
523  *s->id.name = *id
524  end if
525  else
526  s->id.name = NULL
527  options and= not FB_SYMBOPT_DOHASH
528  end if
529 
530  '' alias
531  if( id_alias <> NULL ) then
532  s->id.alias = ZstrAllocate( len( *id_alias ) )
533  *s->id.alias = *id_alias
534  else
535  s->id.alias = NULL
536  end if
537 
538  s->id.mangled = NULL
539 
540  ''
541  s->lgt = 0
542  s->ofs = 0
543 
544  '' add to hash table
545  s->hash.tb = hashtb
546 
547  if( (options and FB_SYMBOPT_DOHASH) <> 0 ) then
548  dim as FBSYMBOL ptr head_sym = any
549 
550  s->hash.index = hashHash( s->id.name )
551 
552  '' doesn't exist yet?
553  head_sym = hashLookupEx( @hashtb->tb, s->id.name, s->hash.index )
554  if( head_sym = NULL ) then
555  '' add to hash table
556  s->hash.item = hashAdd( @hashtb->tb, s->id.name, s, s->hash.index )
557  s->hash.prev = NULL
558  s->hash.next = NULL
559 
560  else
561  '' can it be duplicated?
562  if( (options and FB_SYMBOPT_NODUPCHECK) = 0 ) then
563  if( symbCanDuplicate( head_sym, s ) = FALSE ) then
564  poolDelItem( @symb.namepool, s->id.name ) 'ZstrFree( s->id.name )
565  ZstrFree( s->id.alias )
566  ZstrFree( s->id.mangled )
567  if( delok ) then
568  listDelNode( @symb.symlist, s )
569  end if
570  exit function
571  end if
572  end if
573 
574  s->hash.item = head_sym->hash.item
575 
576  '' add to head so no scope resolution is needed
577 
578  '' QB mode?
579  if( env.clopt.lang = FB_LANG_QB ) then
580  '' keywords must stay at the head
581  dim as FBSYMBOL ptr prev = NULL
582  do while( symbIsKeyword( head_sym ) )
583  prev = head_sym
584  head_sym = head_sym->hash.next
585  if( head_sym = NULL ) then
586  exit do
587  end if
588  loop
589 
590  if( prev = NULL ) then
591  goto add_prev
592  endif
593 
594  prev->hash.next = s
595  s->hash.prev = prev
596  s->hash.next = head_sym
597  if( head_sym <> NULL ) then
598  head_sym->hash.prev = s
599  end if
600 
601  else
602 add_prev: head_sym->hash.item->data = s
603  head_sym->hash.item->name = s->id.name
604  head_sym->hash.prev = s
605  s->hash.prev = NULL
606  s->hash.next = head_sym
607  end if
608 
609  end if
610 
611  else
612  s->hash.item = NULL
613  s->hash.prev = NULL
614  s->hash.next = NULL
615  end if
616 
617  '' add to symbol table
618  if( symtb->tail <> NULL ) then
619  symtb->tail->next = s
620  else
621  symtb->head = s
622  end if
623 
624  s->prev = symtb->tail
625  s->next = NULL
626 
627  s->symtb = symtb
628 
629  symtb->tail = s
630 
631  s->parent = NULL
632 
633  '' forward type? add to the back-patch list..
634  if( typeGetDtOnly( dtype ) = FB_DATATYPE_FWDREF ) then
635  symbAddToFwdRef( subtype, s )
636  end if
637 
638  ''
639  function = s
640 
641 end function
642 
643 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
644 '' lookup
645 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
646 
647 '':::::
648 sub symbHashListAdd _
649  ( _
650  byval hashtb as FBHASHTB ptr _
651  )
652 
653  if( symb.hashlist.tail <> NULL ) then
654  symb.hashlist.tail->next = hashtb
655  else
656  symb.hashlist.head = hashtb
657  end If
658 
659  hashtb->prev = symb.hashlist.tail
660  hashtb->next = NULL
661 
662  symb.hashlist.tail = hashtb
663 
664 end sub
665 
666 '':::::
668  ( _
669  byval lasttb as FBHASHTB ptr, _
670  byval hashtb as FBHASHTB ptr _
671  )
672 
673  if( lasttb->prev = NULL ) then
674  symb.hashlist.head = hashtb
675  else
676  lasttb->prev->next = hashtb
677  end if
678 
679  hashtb->prev = lasttb->prev
680  hashtb->next = lasttb
681 
682  lasttb->prev = hashtb
683 
684 end sub
685 
686 '':::::
687 sub symbHashListDel _
688  ( _
689  byval hashtb as FBHASHTB ptr _
690  )
691 
692  assert( hashtb->prev <> NULL or hashtb->next <> NULL )
693 
694  if( hashtb->prev <> NULL ) then
695  hashtb->prev->next = hashtb->next
696  else
697  symb.hashlist.head = hashtb->next
698  end If
699 
700  if( hashtb->next <> NULL ) then
701  hashtb->next->prev = hashtb->prev
702  else
703  symb.hashlist.tail = hashtb->prev
704  end If
705 
706  hashtb->prev = NULL
707  hashtb->next = NULL
708 
709 end sub
710 
711 '':::::
713  ( _
714  byval ns as FBSYMBOL ptr, _
715  byval src_head as FBSYMBOL ptr _
716  )
717 
718  dim as FBSYMCHAIN ptr imp_head = symbGetCompExt( ns )->impsym_head
719  dim as FBSYMCHAIN ptr imp_tail = symbGetCompExt( ns )->impsym_tail
720 
721  '' for each symbol in the ns being imported..
722  dim as FBSYMBOL ptr s = src_head
723  do until( s = NULL )
724  '' if symbol has a name..
725  if( s->hash.item <> NULL ) then
726  '' only add the head symbol if it's duplicated
727  if( s->hash.prev = NULL ) then
728  dim as FBSYMCHAIN ptr chain_ = listNewNode( @symb.imphashlist )
729  chain_->sym = s
730  chain_->prev = NULL
731  chain_->isimport = TRUE
732 
733  dim as FBSYMCHAIN ptr head = hashLookupEx( @symb.imphashtb, _
734  s->id.name, _
735  s->hash.index )
736  '' not defined yet? create a new hash node
737  if( head = NULL ) then
738  chain_->item = hashAdd( @symb.imphashtb, _
739  s->id.name, _
740  chain_, _
741  s->hash.index )
742  chain_->next = NULL
743 
744  '' already defined..
745  else
746  chain_->item = head->item
747  '' add to head
748  head->item->data = chain_
749  head->prev = chain_
750  chain_->next = head
751  end if
752 
753  ''
754  if( imp_tail <> NULL ) then
755  imp_tail->imp_next = chain_
756  else
757  imp_head = chain_
758  end if
759  chain_->imp_next = NULL
760  imp_tail = chain_
761  end if
762  end if
763 
764  s = s->next
765  loop
766 
767  symbGetCompExt( ns )->impsym_head = imp_head
768  symbGetCompExt( ns )->impsym_tail = imp_tail
769 
770 end sub
771 
772 '':::::
774  ( _
775  byval ns as FBSYMBOL ptr _
776  )
777 
778  dim as FBSYMCHAIN ptr chain_ = symbGetCompExt( ns )->impsym_head
779 
780  do until( chain_ = NULL )
781  dim as FBSYMCHAIN ptr prv = any, nxt = any
782 
783  prv = chain_->prev
784  nxt = chain_->next
785 
786  if( prv <> NULL ) then
787  prv->next = nxt
788  if( nxt <> NULL ) then
789  nxt->prev = prv
790  end if
791  else
792  '' symbol was the head node?
793  if( nxt <> NULL ) then
794  nxt->prev = NULL
795 
796  '' update list head
797  chain_->item->data = nxt
798 
799  '' nothing left? remove from hash table
800  else
801  hashDel( @symb.imphashtb, chain_->item, chain_->sym->hash.index )
802  end if
803  end if
804 
805  nxt = chain_->imp_next
806  listDelNode( @symb.imphashlist, chain_ )
807  chain_ = nxt
808  loop
809 
810  symbGetCompExt( ns )->impsym_head = NULL
811  symbGetCompExt( ns )->impsym_tail = NULL
812 
813 end sub
814 
815 function chainpoolNext() as FBSYMCHAIN ptr
816  symb.chainpoolhead += 1
817  if (symb.chainpoolhead >= CHAINPOOL_SIZE) then
818  symb.chainpoolhead = 0
819  end if
820  return @symb.chainpool(symb.chainpoolhead)
821 end function
822 
823 '':::::
824 function symbLookup _
825  ( _
826  byval id as zstring ptr, _
827  byref tk as FB_TOKEN, _
828  byref tk_class as FB_TKCLASS, _
829  byval preserve_case as integer _
830  ) as FBSYMCHAIN ptr
831 
832  static as zstring * FB_MAXNAMELEN+1 sname
833 
834  '' assume it's an unknown identifier
835  tk = FB_TK_ID
836  tk_class = FB_TKCLASS_IDENTIFIER
837 
838  if( preserve_case = FALSE ) then
839  hUcase( *id, sname )
840  id = @sname
841  end if
842 
843  dim as uinteger index = hashHash( id )
844  dim as FBSYMCHAIN ptr chain_ = NULL
845 
846  '' for each nested hash tb, starting from last
847  dim as FBHASHTB ptr hashtb = symb.hashlist.tail
848 
849  do
850  dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
851  if( sym <> NULL ) then
853 
854  chain_->sym = sym
855  chain_->next = NULL
856  chain_->isimport = FALSE
857 
858  if( sym->class = FB_SYMBCLASS_KEYWORD ) then
859  tk = sym->key.id
860  tk_class = sym->key.tkclass
861  '' return if it's a KEYWORD or a OPERATOR token, they
862  '' can't never be redefined, even inside namespaces
863  if( tk_class <> FB_TKCLASS_QUIRKWD ) then
864  return chain_
865  end if
866  end if
867 
868  '' return if it's not the global ns (as in C++, any nested
869  '' symbol has precedence over any imported one, even if the
870  '' latter was imported in the current ns)
871  if( hashtb->owner <> @symbGetGlobalNamespc( ) ) then
872  return chain_
873  else
874  '' also if we are at the global ns, no need to check the imports
875  if( symbGetCurrentNamespc( ) = @symbGetGlobalNamespc( ) ) then
876  return chain_
877  end if
878 
879  '' check (and add) the imports..
880  exit do
881  end if
882  end if
883 
884  hashtb = hashtb->prev
885  loop while( hashtb <> NULL )
886 
887  '' now try the imported namespaces..
888  dim as FBSYMCHAIN ptr imp_chain = hashLookupEx( @symb.imphashtb, id, index )
889  if( chain_ = NULL ) then
890  return imp_chain
891  end if
892 
893  chain_->next = imp_chain
894 
895  return chain_
896 
897 end function
898 
899 '':::::
900 function hLookupImportHash _
901  ( _
902  byval ns as FBSYMBOL ptr, _
903  byval id as const zstring ptr, _
904  byval index as uinteger _
905  ) as FBSYMCHAIN ptr
906 
907  dim as FBSYMCHAIN ptr chain_head = hashLookupEx( @symb.imphashtb, id, index )
908  if( chain_head = NULL ) then
909  return NULL
910  end if
911 
912  dim as FBSYMCHAIN ptr head = NULL, tail = NULL
913 
914  '' for each namespace found..
915  dim as FBSYMCHAIN ptr chain_ = chain_head
916  do
917  '' for each namespace that imports that namespace..
918  dim as FBSYMBOL ptr exp_ = symbGetCompExportHead( symbGetNamespace( chain_->sym ) )
919  do
920  if( symbGetExportNamespc( exp_ ) = ns ) then
921  dim as FBSYMCHAIN ptr node = chainpoolNext()
922 
923  node->sym = chain_->sym
924  node->next = NULL
925  node->isimport = TRUE
926 
927  if( head = NULL ) then
928  head = node
929  else
930  tail->next = node
931  '' it's ambiguous, just return the first two
932  return head
933  end if
934 
935  tail = node
936  end if
937 
938  exp_ = symbGetExportNext( exp_ )
939  loop while( exp_ <> NULL )
940 
941  chain_ = chain_->next
942  loop while( chain_ <> NULL )
943 
944  return head
945 
946 end function
947 
948 '':::::
949 function hLookupImportList _
950  ( _
951  byval ns as FBSYMBOL ptr, _
952  byval id as const zstring ptr, _
953  byval index as uinteger _
954  ) as FBSYMCHAIN ptr
955 
956  dim as FBSYMCHAIN ptr head = NULL, tail = NULL
957 
958  '' for each namespace imported by this ns..
959  dim as FBSYMBOL ptr imp_ = symbGetCompImportHead( ns )
960  do while( imp_ <> NULL )
961  dim as FBSYMBOL ptr sym = hashLookupEx( _
962  @symbGetCompHashTb( _
963  symbGetImportNamespc( imp_ ) ).tb, _
964  id, _
965  index )
966  if( sym <> NULL ) then
967  dim as FBSYMCHAIN ptr chain_ = chainpoolNext()
968 
969  chain_->sym = sym
970  chain_->next = NULL
971  chain_->isimport = TRUE
972 
973  if( head = NULL ) then
974  head = chain_
975  else
976  tail->next = chain_
977  '' it's ambiguous, just return the first two
978  return head
979  end if
980 
981  tail = chain_
982  end if
983 
984  imp_ = symbGetImportNext( imp_ )
985  loop
986 
987  return head
988 
989 end function
990 
991 '':::::
992 function symbLookupAt _
993  ( _
994  byval ns as FBSYMBOL ptr, _
995  byval id as const zstring ptr, _
996  byval preserve_case as integer, _
997  byval search_imports as integer _
998  ) as FBSYMCHAIN ptr
999 
1000  static as zstring * FB_MAXNAMELEN+1 sname
1001 
1002  assert( symbIsStruct( ns ) or symbIsNamespace( ns ) or symbIsEnum( ns ) )
1003 
1004  if( preserve_case = FALSE ) then
1005  hUcase( *id, sname )
1006  id = @sname
1007  end if
1008 
1009  dim as uinteger index = hashHash( id )
1010 
1011  '' search in UDT's (NAMESPACE, TYPE, CLASS or ENUM) hash tb first
1012  dim as FBSYMBOL ptr sym = hashLookupEx( @symbGetCompHashTb( ns ).tb, id, index )
1013  if( sym = NULL ) then
1014  if( search_imports = FALSE ) then
1015  return NULL
1016  end if
1017 
1018  else
1019  dim as FBSYMCHAIN ptr chain_ = chainpoolNext()
1020  chain_->sym = sym
1021  chain_->next = NULL
1022  chain_->isimport = FALSE
1023  return chain_
1024  end if
1025 
1026  '' nothing found, now search the imports (if any)..
1027  if( symbGetCompExt( ns ) = NULL ) then
1028  return NULL
1029  end if
1030 
1031  if( symbGetCompImportHead( ns ) = NULL ) then
1032  return NULL
1033  end if
1034 
1035  '' special cases: the global ns
1036  if( ns = @symbGetGlobalNamespc( ) ) then
1037  return hLookupImportHash( ns, id, index )
1038 
1039  '' do a per-hash slow search..
1040  else
1041  return hLookupImportList( ns, id, index )
1042  end if
1043 
1044 end function
1045 
1046 '':::::
1047 function symbLookupByNameAndClass _
1048  ( _
1049  byval ns as FBSYMBOL ptr, _
1050  byval id as const zstring ptr, _
1051  byval class_ as integer, _
1052  byval preserve_case as integer, _
1053  byval search_imports as integer _
1054  ) as FBSYMBOL ptr
1055 
1056  dim as FBSYMCHAIN ptr chain_ = any
1057 
1058  chain_ = symbLookupAt( ns, id, preserve_case, search_imports )
1059 
1060  '' any found?
1061  if( chain_ <> NULL ) then
1062  '' check if classes match
1063  function = symbFindByClass( chain_, class_ )
1064  else
1065  function = NULL
1066  end if
1067 
1068 end function
1069 
1070 '':::::
1071 function symbLookupByNameAndSuffix _
1072  ( _
1073  byval ns as FBSYMBOL ptr, _
1074  byval id as zstring ptr, _
1075  byval suffix as integer, _
1076  byval preserve_case as integer, _
1077  byval search_imports as integer _
1078  ) as FBSYMBOL ptr
1079 
1080  dim as FBSYMCHAIN ptr chain_ = any
1081 
1082  chain_ = symbLookupAt( ns, id, preserve_case, search_imports )
1083 
1084  '' any found?
1085  if( chain_ <> NULL ) then
1086  '' check if types match
1087  if( suffix = FB_DATATYPE_INVALID ) then
1088  function = symbFindVarByDefType( chain_, symbGetDefType( id ) )
1089  else
1090  function = symbFindVarBySuffix( chain_, suffix )
1091  end if
1092 
1093  else
1094  function = NULL
1095  end if
1096 
1097 end function
1098 
1099 '':::::
1100 function symbFindByClass _
1101  ( _
1102  byval chain_ as FBSYMCHAIN ptr, _
1103  byval class_ as integer _
1104  ) as FBSYMBOL ptr
1105 
1106  dim as FBSYMBOL ptr sym = any
1107  dim as integer match = FALSE
1108 
1109  '' lookup a symbol with the same class
1110  do while( chain_ <> NULL )
1111  sym = chain_->sym
1112  do
1113  if( sym->class = class_ ) then
1114  match = TRUE
1115  exit do, do
1116  end if
1117 
1118  sym = sym->hash.next
1119  loop while( sym <> NULL )
1120 
1121  chain_ = chain_->next
1122  loop
1123 
1124  if( match = FALSE ) then
1125  return NULL
1126  end if
1127 
1128  '' check if symbol isn't a non-shared module level one
1129  if( symbIsVar( sym ) ) then
1130  if( symbVarCheckAccess( sym ) ) then
1131  return sym
1132  else
1133  return NULL
1134  end if
1135  end if
1136 
1137  function = sym
1138 
1139 end function
1140 
1141 '':::::
1142 function symbFindVarBySuffix _
1143  ( _
1144  byval chain_ as FBSYMCHAIN ptr, _
1145  byval suffix as integer _
1146  ) as FBSYMBOL ptr
1147 
1148  dim as FBSYMBOL ptr sym = any
1149 
1150  '' symbol has a suffix: lookup a symbol with the same type, suffixed or not
1151 
1152  '' QB quirk: fixed-len and zstrings referenced using '$' as suffix..
1153  if( suffix = FB_DATATYPE_STRING ) then
1154  do while( chain_ <> NULL )
1155  sym = chain_->sym
1156  do
1157  if( symbIsVar( sym ) ) then
1158  select case symbGetType( sym )
1159  case FB_DATATYPE_STRING, FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR
1160  goto check_var
1161  end select
1162  end if
1163 
1164  sym = sym->hash.next
1165  loop while( sym <> NULL )
1166 
1167  chain_ = chain_->next
1168  loop
1169 
1170  '' anything but strings..
1171  else
1172  do while( chain_ <> NULL )
1173  sym = chain_->sym
1174  do
1175  if( symbIsVar( sym ) ) then
1176  if( symbGetType( sym ) = suffix ) then
1177  goto check_var
1178  end if
1179  end if
1180 
1181  sym = sym->hash.next
1182  loop while( sym <> NULL )
1183 
1184  chain_ = chain_->next
1185  loop
1186  end if
1187 
1188  return NULL
1189 
1190 check_var:
1191  '' check if symbol isn't a non-shared module level one
1192  if( symbVarCheckAccess( sym ) ) then
1193  function = sym
1194  else
1195  function = NULL
1196  end if
1197 
1198 end function
1199 
1200 '':::::
1201 function symbFindVarByDefType _
1202  ( _
1203  byval chain_ as FBSYMCHAIN ptr, _
1204  byval def_dtype as integer _
1205  ) as FBSYMBOL ptr
1206 
1207  dim as FBSYMBOL ptr sym = any
1208 
1209  '' symbol has no suffix: lookup a symbol w/o suffix or with the
1210  '' same type as default type (last DEF###)
1211 
1212  '' QB quirk: see above
1213  if( def_dtype = FB_DATATYPE_STRING ) then
1214  do while( chain_ <> NULL )
1215  sym = chain_->sym
1216  do
1217  if( symbIsVar( sym ) ) then
1218  if( symbIsSuffixed( sym ) ) then
1219  select case sym->typ
1220  case FB_DATATYPE_STRING, FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR
1221  goto check_var
1222  end select
1223  else
1224  goto check_var
1225  end if
1226  end if
1227 
1228  sym = sym->hash.next
1229  loop while( sym <> NULL )
1230 
1231  chain_ = chain_->next
1232  loop
1233 
1234  '' anything but strings..
1235  else
1236  do while( chain_ <> NULL )
1237  sym = chain_->sym
1238  do
1239  if( symbIsVar( sym ) ) then
1240  if( symbIsSuffixed( sym ) ) then
1241  if( symbGetType( sym ) = def_dtype ) then
1242  goto check_var
1243  end if
1244  else
1245  goto check_var
1246  end if
1247  end if
1248 
1249  sym = sym->hash.next
1250  loop while( sym <> NULL )
1251 
1252  chain_ = chain_->next
1253  loop
1254  end if
1255 
1256  return NULL
1257 
1258 check_var:
1259  '' check if symbol isn't a non-shared module level one
1260  if( symbVarCheckAccess( sym ) ) then
1261  function = sym
1262  else
1263  function = NULL
1264  end if
1265 
1266 end function
1267 
1268 '':::::
1269 function symbFindVarByType _
1270  ( _
1271  byval chain_ as FBSYMCHAIN ptr, _
1272  byval dtype as integer _
1273  ) as FBSYMBOL ptr
1274 
1275  dim as FBSYMBOL ptr sym = any
1276 
1277  do while( chain_ <> NULL )
1278  sym = chain_->sym
1279  do
1280  if( symbIsVar( sym ) ) then
1281  if( symbGetFullType( sym ) = dtype ) then
1282  goto check_var
1283  end if
1284  end if
1285 
1286  sym = sym->hash.next
1287  loop while( sym <> NULL )
1288 
1289  chain_ = chain_->next
1290  loop
1291 
1292  return NULL
1293 
1294 check_var:
1295  '' check if symbol isn't a non-shared module level one
1296  if( symbVarCheckAccess( sym ) ) then
1297  function = sym
1298  else
1299  function = NULL
1300  end if
1301 
1302 end function
1303 
1304 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1305 '' del
1306 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1307 
1308 '':::::
1310  ( _
1311  byval s as FBSYMBOL ptr _
1312  )
1313 
1314  dim as FBSYMBOL ptr prv = any, nxt = any
1315 
1316  '' note: symbols declared inside namespaces can't be
1317  '' removed by #undef or OPTION NOKEYWORD so the import
1318  '' chain doesn't have to be updated
1319 
1320  '' relink
1321  prv = s->hash.prev
1322  nxt = s->hash.next
1323  if( prv <> NULL ) then
1324  prv->hash.next = nxt
1325 
1326  if( nxt <> NULL ) then
1327  nxt->hash.prev = prv
1328  end if
1329 
1330  else
1331  '' symbol was the head node?
1332  if( nxt <> NULL ) then
1333  nxt->hash.prev = NULL
1334 
1335  '' update list head
1336  s->hash.item->data = nxt
1337  s->hash.item->name = nxt->id.name
1338 
1339  '' nothing left? remove from hash table
1340  else
1341  hashDel( @s->hash.tb->tb, s->hash.item, s->hash.index )
1342  end if
1343  end if
1344 
1345 end sub
1346 
1347 '':::::
1348 sub symbDelFromHash _
1349  ( _
1350  byval s as FBSYMBOL ptr _
1351  )
1352 
1353  if( s->hash.item = NULL ) then
1354  exit sub
1355  end if
1356 
1358 
1359  s->hash.item = NULL
1360 
1361 end sub
1362 
1363 '':::::
1364 sub symbFreeSymbol _
1365  ( _
1366  byval s as FBSYMBOL ptr _
1367  )
1368 
1369  '' Symbol has forward type? That means it was added to the fwdref's list
1370  '' of references/users for backpatching later. If the fwdref type is
1371  '' still here, that means no backpatching happened yet, so the fwdref node
1372  '' still exists and may do backpatching later.
1373  '' This symbol must be removed from the fwdref's user list, otherwise the
1374  '' fwdref could backpatch a deleted node and would then corrupt any symbol
1375  '' allocated at that address.
1376  if( typeGetDtOnly( s->typ ) = FB_DATATYPE_FWDREF ) then
1377  assert( s->subtype->class = FB_SYMBCLASS_FWDREF )
1378  symbRemoveFromFwdRef( s->subtype, s )
1379  end if
1380 
1381  '' revove from hash tb
1382  symbDelFromHash( s )
1383 
1386 
1387 end sub
1388 
1389 '':::::
1391  ( _
1392  byval s as FBSYMBOL ptr _
1393  )
1394 
1395  '' remove from symbol tb
1396  poolDelItem( @symb.namepool, s->id.name ) 'ZstrFree( s->id.name )
1397 
1398  ZstrFree( s->id.alias )
1399  ZstrFree( s->id.mangled )
1400 
1401  listDelNode( @symb.symlist, s )
1402 
1403 end sub
1404 
1405 '':::::
1407  ( _
1408  byval s as FBSYMBOL ptr _
1409  )
1410 
1411  dim as FBSYMBOLTB ptr tb = any
1412  dim as FBSYMBOL ptr prv = any, nxt = any
1413 
1414  '' del from table
1415  tb = s->symtb
1416 
1417  prv = s->prev
1418  nxt = s->next
1419  if( prv <> NULL ) then
1420  prv->next = nxt
1421  else
1422  tb->head = nxt
1423  end if
1424 
1425  if( nxt <> NULL ) then
1426  nxt->prev = prv
1427  else
1428  tb->tail = prv
1429  end if
1430 
1431  s->prev = NULL
1432  s->next = NULL
1433 
1434 end sub
1435 
1436 sub symbDelSymbol _
1437  ( _
1438  byval s as FBSYMBOL ptr, _
1439  byval is_tbdel as integer _
1440  )
1441 
1442  '' is_tbdel: If the whole symbol table of a scope or namespace is
1443  '' being deleted, we don't need to bother deleting symbols recursively,
1444  '' such as array descriptors attached to variables, because the symbol
1445  '' table deletion will catch them already. In fact, when deleting a
1446  '' symbol table, any attached symbols might be deleted *before* their
1447  '' parents, which then can not use the dangling pointers...
1448 
1449  select case as const s->class
1450  case FB_SYMBCLASS_VAR
1451  symbDelVar( s, is_tbdel )
1452 
1453  case FB_SYMBCLASS_CONST
1454  symbDelConst( s )
1455 
1456  case FB_SYMBCLASS_PROC
1457  symbDelPrototype( s )
1458 
1459  case FB_SYMBCLASS_DEFINE
1460  symbDelDefine( s )
1461 
1462  case FB_SYMBCLASS_LABEL
1463  symbDelLabel( s )
1464 
1465  case FB_SYMBCLASS_ENUM
1466  symbDelEnum( s )
1467 
1468  case FB_SYMBCLASS_STRUCT
1469  symbDelStruct( s )
1470 
1471  case FB_SYMBCLASS_SCOPE
1472  symbDelScope( s )
1473 
1474  case FB_SYMBCLASS_NAMESPACE
1475  symbDelNamespace( s )
1476 
1477  case FB_SYMBCLASS_NSIMPORT
1478  symbNamespaceRemove( s, FALSE )
1479 
1480  case FB_SYMBCLASS_FIELD
1481  assert( is_tbdel ) '' symbDelField() assumption
1482  symbDelField( s )
1483 
1484  case else
1485  symbFreeSymbol( s )
1486 
1487  end select
1488 
1489 end sub
1490 
1491 function symbCloneSymbol( byval s as FBSYMBOL ptr ) as FBSYMBOL ptr
1492  '' assuming only non-complex symbols will be passed,
1493  '' for use by astTypeIniClone() mainly
1494 
1495  select case as const s->class
1496  case FB_SYMBCLASS_PROC
1497  '' Only procptr subtype PROC symbols, but no real PROCs,
1498  '' should appear in TYPEINI scopes.
1499  assert( symbGetIsFuncPtr( s ) )
1500  function = symbAddProcPtrFromFunction( s )
1501 
1502  case FB_SYMBCLASS_VAR
1503  function = symbCloneVar( s )
1504 
1505  case FB_SYMBCLASS_CONST
1506  function = symbCloneConst( s )
1507 
1508  case FB_SYMBCLASS_LABEL
1509  function = symbCloneLabel( s )
1510 
1511  case FB_SYMBCLASS_STRUCT
1512  function = symbCloneStruct( s )
1513 
1514  case else
1515  assert( FALSE )
1516  function = NULL
1517  end select
1518 
1519 end function
1520 
1521 '':::::
1523 
1524  do
1525  '' starting from last (an USING must be removed before
1526  '' the ns in the same scope it's referencing)
1527  dim as FBSYMBOL ptr s = symbGetGlobalTb( ).tail
1528  if( s = NULL ) then
1529  exit do
1530  end if
1531 
1532  symbDelSymbol( s, TRUE )
1533  loop
1534 
1535 end sub
1536 
1537 '':::::
1538 sub symbDelSymbolTb _
1539  ( _
1540  byval tb as FBSYMBOLTB ptr, _
1541  byval hashonly as integer _
1542  )
1543 
1544  '' del from hash tb only?
1545  if( hashonly ) then
1546  dim as FBSYMBOL ptr s = tb->head
1547  while( s )
1548  symbDelFromHash( s )
1549 
1550  if( s->class = FB_SYMBCLASS_NSIMPORT ) then
1551  symbNamespaceRemove( s, TRUE )
1552  end if
1553 
1554  s = s->next
1555  wend
1556  '' del from hash and symbol tb's
1557  else
1558  do
1559  '' starting from last because USING's can be referencing
1560  '' namespace symbols in the same scope block
1561  dim as FBSYMBOL ptr s = tb->tail
1562  if( s = NULL ) then
1563  exit do
1564  end if
1565 
1566  symbDelSymbol( s, TRUE )
1567  loop
1568 
1569  end if
1570 
1571 end sub
1572 
1573 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1574 '' misc
1575 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1576 
1577 function symbHasCtor( byval sym as FBSYMBOL ptr ) as integer
1578  '' shouldn't be called on structs - can directly use symbGetCompCtorHead()
1579  assert( symbIsStruct( sym ) = FALSE )
1580  '' Handle vars, params, function results, etc.
1581  function = typeHasCtor( sym->typ, sym->subtype )
1582 end function
1583 
1584 function symbHasDefCtor( byval sym as FBSYMBOL ptr ) as integer
1585  assert( symbIsStruct( sym ) = FALSE )
1586  function = typeHasDefCtor( sym->typ, sym->subtype )
1587 end function
1588 
1589 function symbHasDtor( byval sym as FBSYMBOL ptr ) as integer
1590  assert( symbIsStruct( sym ) = FALSE )
1591  function = typeHasDtor( sym->typ, sym->subtype )
1592 end function
1593 
1594 '':::::
1595 function symbIsArray _
1596  ( _
1597  byval sym as FBSYMBOL ptr _
1598  ) as integer
1599 
1600  select case sym->class
1601  case FB_SYMBCLASS_VAR, FB_SYMBCLASS_FIELD
1602  if (symbGetIsDynamic(sym)) then
1603  return TRUE
1604  else
1605  return symbGetArrayDimensions( sym ) <> 0
1606  end if
1607  end select
1608 
1609  function = FALSE
1610 
1611 end function
1612 
1613 '':::::
1614 function symbIsString _
1615  ( _
1616  byval dtype as integer _
1617  ) as integer
1618 
1619  select case as const dtype
1620  case FB_DATATYPE_STRING, FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
1621  function = TRUE
1622  case else
1623  function = FALSE
1624  end select
1625 
1626 end function
1627 
1628 '':::::
1629 function symbIsEqual _
1630  ( _
1631  byval sym1 as FBSYMBOL ptr, _
1632  byval sym2 as FBSYMBOL ptr _
1633  ) as integer
1634 
1635  dim as FBSYMBOL ptr paraml = any, paramr = any
1636 
1637  function = FALSE
1638 
1639  '' same symbol?
1640  if( sym1 = sym2 ) then
1641  return TRUE
1642  end if
1643 
1644  '' any NULL?
1645  if( (sym1 = NULL) or (sym2 = NULL) ) then
1646  exit function
1647  end if
1648 
1649  '' different classes?
1650  if( sym1->class <> sym2->class ) then
1651  exit function
1652  end if
1653 
1654  '' different types?
1655  if( sym1->typ <> sym2->typ ) then
1656  exit function
1657  end if
1658 
1659  select case sym1->class
1660  '' UDT?
1661  case FB_SYMBCLASS_STRUCT '', FB_SYMBCLASS_CLASS
1662  return symbGetUDTBaseLevel( sym1, sym2 ) > 0
1663 
1664  '' enum?
1665  case FB_SYMBCLASS_ENUM
1666  '' no check, they are pointing to different symbols
1667  exit function
1668 
1669  '' function? must check because a @foo will point to a different
1670  '' symbol than funptr, but both can have the same signature
1671  case FB_SYMBCLASS_PROC
1672  '' Check for return BYREF
1673  if( symbProcReturnsByref( sym1 ) <> symbProcReturnsByref( sym2 ) ) then
1674  exit function
1675  end if
1676 
1677  '' check calling convention
1678  if( symbAreProcModesEqual( sym1, sym2 ) = FALSE ) then
1679  exit function
1680  end if
1681 
1682  '' not the same number of args?
1683  if( symbGetProcParams( sym1 ) <> symbGetProcParams( sym2 ) ) then
1684 
1685  '' no args?
1686  if( symbGetProcParams( sym1 ) = 0 ) then
1687  exit function
1688  end if
1689 
1690  '' not vararg?
1691  if( symbGetProcTailParam( sym1 )->param.mode <> FB_PARAMMODE_VARARG ) then
1692  exit function
1693  end if
1694 
1695  '' not enough args?
1696  if( (symbGetProcParams( sym2 ) - symbGetProcParams( sym1 )) < -1 ) then
1697  exit function
1698  end if
1699  end if
1700 
1701  '' check each param
1702  paraml = symbGetProcHeadParam( sym1 )
1703  paramr = symbGetProcHeadParam( sym2 )
1704 
1705  do while( paraml <> NULL )
1706  '' vararg?
1707  if( paraml->param.mode = FB_PARAMMODE_VARARG ) then
1708  exit do
1709  end if
1710 
1711  '' mode?
1712  if( paraml->param.mode <> paramr->param.mode ) then
1713  exit function
1714  end if
1715 
1716  '' different types?
1717  if( paraml->typ <> paramr->typ ) then
1718  exit function
1719  end if
1720 
1721  '' sub-types?
1722  if( paraml->subtype <> paramr->subtype ) then
1723  exit function
1724  end if
1725 
1726  '' next arg..
1727  paraml = paraml->next
1728  paramr = paramr->next
1729  loop
1730  end select
1731 
1732  '' and sub type
1733  if( sym1->subtype <> sym2->subtype ) then
1734  function = symbIsEqual( sym1->subtype, sym2->subtype )
1735  else
1736  function = TRUE
1737  end if
1738 
1739 end function
1740 
1741 function symbTypeToStr _
1742  ( _
1743  byval dtype as integer, _
1744  byval subtype as FBSYMBOL ptr, _
1745  byval length as longint _
1746  ) as string
1747 
1748  dim as string s
1749  dim as integer dtypeonly = any, ptrcount = any
1750 
1751  if( dtype = FB_DATATYPE_INVALID ) then
1752  exit function
1753  end if
1754 
1755  ptrcount = typeGetPtrCnt( dtype )
1756  if( typeIsConstAt( dtype, ptrcount ) ) then
1757  s = "const "
1758  else
1759  s = ""
1760  end if
1761 
1762  dtypeonly = typeGetDtOnly( dtype )
1763 
1764  select case as const( dtypeonly )
1765  case FB_DATATYPE_FWDREF, FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM
1766  s += *symbGetName( subtype )
1767 
1768  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR, FB_DATATYPE_FIXSTR
1769  s += *symb_dtypeTB(dtypeonly).name
1770  if( length > 0 ) then
1771  select case( dtypeonly )
1772  case FB_DATATYPE_FIXSTR
1773  '' For STRING*N the null terminator is
1774  '' implicitly added, the length actually is N+1,
1775  '' unlike Z/WSTRING*N where N includes it.
1776  length -= 1
1777  case FB_DATATYPE_WCHAR
1778  '' Convert bytes back to chars
1779  length \= typeGetSize( FB_DATATYPE_WCHAR )
1780  end select
1781  s += " * " + str( length )
1782  end if
1783 
1784  case FB_DATATYPE_FUNCTION
1785  '' Procedure pointer
1786 
1787  '' The sub() or function() already implies one PTR
1788  assert( ptrcount > 0 )
1789  ptrcount -= 1
1790 
1791  '' If there are any more PTRs, i.e. a PTR to a proc PTR,
1792  '' then it must be emitted inside a typeof():
1793  '' typeof( function( ) as integer ) ptr
1794  '' otherwise, the PTR would be seen as part of the
1795  '' function result type:
1796  '' function( ) as integer ptr
1797  if( ptrcount > 0 ) then
1798  s += "typeof("
1799  end if
1800 
1801  s += symbProcPtrToStr( subtype )
1802 
1803  if( ptrcount > 0 ) then
1804  s += ")"
1805  end if
1806 
1807  case else
1808  s += *symb_dtypeTB(dtypeonly).name
1809  end select
1810 
1811  for i as integer = ptrcount-1 to 0 step -1
1812  if( typeIsConstAt( dtype, i ) ) then
1813  s += " const"
1814  end if
1815  s += " ptr"
1816  next
1817 
1818  function = s
1819 end function
1820 
1821 '':::::
1822 function symbGetDefType _
1823  ( _
1824  byval symbol as const zstring ptr _
1825  ) as integer
1826 
1827  dim as integer c = any
1828  dim as integer i = any
1829 
1830  c = symbol[0][0]
1831 
1832  '' to upper
1833  if( (c >= asc("a")) and (c <= asc("z")) ) then
1834  c -= (asc("a") - asc("A"))
1835  end if
1836 
1837  i = c - asc("A")
1838 
1839  '' if lead character is not on the table, use the dialect default
1840  '' (error recovery may create a temporary symbol name)
1841  if( (i < lbound(deftypeTB)) or (i > ubound(deftypeTB)) ) then
1842  if( fbLangIsSet( FB_LANG_QB ) ) then
1843  function = FB_DATATYPE_SINGLE
1844  else
1845  function = FB_DATATYPE_INTEGER
1846  end if
1847  else
1848  function = deftypeTB(i)
1849  end if
1850 
1851 end function
1852 
1853 '':::::
1854 sub symbSetDefType _
1855  ( _
1856  byval ichar as integer, _
1857  byval echar as integer, _
1858  byval dtype as integer _
1859  )
1860 
1861  dim as integer i = any
1862 
1863  if( ichar < asc("A") ) then
1864  ichar = asc("A")
1865  elseif( ichar > asc("_") ) then
1866  ichar = asc("_")
1867  end if
1868 
1869  if( echar < asc("A") ) then
1870  echar = asc("A")
1871  elseif( echar > asc("_") ) then
1872  echar = asc("_")
1873  end if
1874 
1875  if( ichar > echar ) then
1876  swap ichar, echar
1877  end if
1878 
1879  for i = ichar to echar
1880  deftypeTB(i - asc("A")) = dtype
1881  next
1882 
1883 end sub
1884 
1885 '' Recalculate the length, to be used after the symbol's type was set/changed
1886 sub symbRecalcLen( byval sym as FBSYMBOL ptr )
1887  if( sym->class = FB_SYMBCLASS_PARAM ) then
1888  sym->lgt = symbCalcParamLen( sym->typ, sym->subtype, sym->param.mode )
1889  else
1890  sym->lgt = symbCalcLen( sym->typ, sym->subtype )
1891  end if
1892 end sub
1893 
1894 sub symbSetType _
1895  ( _
1896  byval sym as FBSYMBOL ptr, _
1897  byval dtype as integer, _
1898  byval subtype as FBSYMBOL ptr _
1899  )
1900 
1901  sym->typ = dtype
1902  sym->subtype = subtype
1903 
1904  symbRecalcLen( sym )
1905 
1906  '' If it's a procedure, the real dtype must be updated too
1907  if( symbIsProc( sym ) ) then
1908  symbProcRecalcRealType( sym )
1909  end if
1910 
1911  '' If setting type to a fwdref, register symbol for back-patching
1912  '' (e.g. when substituting a fwdref by another fwdref)
1913  if( typeGetDtOnly( dtype ) = FB_DATATYPE_FWDREF ) then
1914  symbAddToFwdRef( subtype, sym )
1915  end if
1916 
1917 end sub
1918 
1919 function symbCalcLen _
1920  ( _
1921  byval dtype as integer, _
1922  byval subtype as FBSYMBOL ptr _
1923  ) as longint
1924 
1925  dtype = typeGet( dtype )
1926 
1927  select case as const( dtype )
1928  case FB_DATATYPE_FIXSTR
1929  function = 0 '' zero-length literal-strings
1930 
1931  case FB_DATATYPE_STRUCT, FB_DATATYPE_BITFIELD
1932  function = subtype->lgt
1933 
1934  case else
1935  function = typeGetSize( dtype )
1936  end select
1937 
1938 end function
1939 
1940 function symbCalcDerefLen _
1941  ( _
1942  byval dtype as integer, _
1943  byval subtype as FBSYMBOL ptr _
1944  ) as longint
1945 
1946  dim as longint length = any
1947 
1948  assert( typeIsPtr( dtype ) )
1949 
1950  length = symbCalcLen( typeDeref( dtype ), subtype )
1951 
1952  '' incomplete type?
1953  if( length = 0 ) then
1954  '' ANY PTR?
1955  if( dtype = typeAddrOf( FB_DATATYPE_VOID ) ) then
1956  '' treat as BYTE PTR
1957  length = 1
1958  end if
1959  '' (for anything else, we return 0 to indicate the error)
1960  end if
1961 
1962  function = length
1963 end function
1964 
1965 function symbCheckAccess( byval sym as FBSYMBOL ptr ) as integer
1966  dim as FBSYMBOL ptr parent = any, context = any
1967 
1968  '' Neither private nor protected? Always ok.
1969  if( (sym->attrib and (FB_SYMBATTRIB_VIS_PRIVATE or FB_SYMBATTRIB_VIS_PROTECTED)) = 0 ) then
1970  return TRUE
1971  end if
1972 
1973  '' Notes:
1974  '' - Only UDT members will have visibility flags
1975  '' - Private/protected members can *only* be accessed from inside
1976  '' member procedures or the UDT body
1977  '' - There may be nested namespaces inside those procedures,
1978  '' from which accesses are possible
1979  '' (e.g. enum constant initializers)
1980  '' - UDTs may contain nested namespaces whose members should be
1981  '' affected by visibility too (e.g. named enums)
1982  '' - There are no nested procedures
1983  '' - All UDTs are also namespaces
1984 
1985  '' Walk upwards the symbol's parent namespaces until we find the
1986  '' symbol's parent UDT. (Usually it's the first parent, but e.g. with
1987  '' named enums inside UDTs there can be another namespace in between)
1988  parent = sym
1989  do
1990  assert( parent <> @symbGetGlobalNamespc( ) )
1991  parent = symbGetNamespace( parent )
1992  loop while( not symbIsStruct( parent ) )
1993 
1994  '' Check against the current context, only allowing...
1995  '' - private access from inside the symbol's parent UDT namespace,
1996  '' i.e. the UDT body, a method, or a namespace nested inside either.
1997  '' - protected access from inside the namespace of an UDT that was
1998  '' derived from the symbol's real parent UDT.
1999 
2000  '' For all nested namespaces in the current parsing context,
2001  '' from the current namespace up to the toplevel one...
2002  context = symbGetCurrentNamespc( )
2003  while( context <> @symbGetGlobalNamespc( ) )
2004 
2005  '' Is it an UDT namespace? (i.e. a method or UDT body?)
2006  if( symbIsStruct( context ) ) then
2007  '' Ok if same namespace for private/protected
2008  if( context = parent ) then
2009  '' We're inside the parent
2010  return TRUE
2011  end if
2012 
2013  '' Protected additionally allows derived UDTs
2014  if( sym->attrib and FB_SYMBATTRIB_VIS_PROTECTED ) then
2015  if( symbGetUDTBaseLevel( context, parent ) > 0 ) then
2016  '' We're inside an UDT derived from the parent
2017  return TRUE
2018  end if
2019  end if
2020  end if
2021 
2022  context = symbGetNamespace( context )
2023  wend
2024 
2025  function = FALSE
2026 end function
2027 
2028 function symbCheckConstAssign _
2029  ( _
2030  byval ldtype as FB_DATATYPE, _
2031  byval rdtype as FB_DATATYPE, _
2032  byval lsubtype as FBSYMBOL ptr, _
2033  byval rsubtype as FBSYMBOL ptr, _
2034  byval mode as FB_PARAMMODE = 0, _
2035  byref matches as integer = 0 _
2036  ) as integer
2037 
2038  function = FALSE
2039  matches = 0
2040 
2041  '' no consts? short-circuit
2042  if( (typeGetConstMask( ldtype ) or typeGetConstMask( rdtype )) = 0 ) then
2043  return TRUE
2044  end if
2045 
2046  '' vararg? they aren't type safe anyway
2047  if( mode = FB_PARAMMODE_VARARG ) then
2048  return TRUE
2049  end if
2050 
2051  dim as integer l_cnt = typeGetPtrCnt( ldtype ), r_cnt = typeGetPtrCnt( rdtype ), start_at = any
2052 
2053  '' any ptr const on the right?
2054  if( typeGetConstMask( rdtype ) and typeIsPtr( rdtype ) ) then
2055 
2056  '' types and ptr depth HAVE to match
2057  if( typeGetDtAndPtrOnly( ldtype ) <> typeGetDtAndPtrOnly( rdtype ) ) then
2058 
2059  '' unless it's a ptr to an any ptr
2060  if( (typeGetDtAndPtrOnly( ldtype ) = typeAddrOf(FB_DATATYPE_VOID)) = FALSE ) then
2061  exit function
2062  end if
2063  end if
2064 
2065  if( lsubtype <> rsubtype ) then
2066  exit function
2067  end if
2068 
2069  if( l_cnt <> r_cnt ) then
2070  exit function
2071  end if
2072 
2073  end if
2074 
2075  '' add one for the non-ptr slot
2076  r_cnt += 1
2077 
2078  '' byval params need extra matching for
2079  '' overload resolution
2080  if( mode = FB_PARAMMODE_BYVAL ) then
2081  start_at = 1
2082  matches = r_cnt
2083 
2084  '' top-level const gets precedence...
2085  if( typeIsConst( ldtype ) ) then
2086  matches += 1
2087  end if
2088 
2089  else
2090 
2091  '' just a variable assignment?
2092  if( mode = 0 ) then
2093  start_at = 1
2094  else
2095 
2096  '' byref/bydesc param, check every level
2097  start_at = 0
2098  end if
2099 
2100  end if
2101 
2102  r_cnt -= start_at
2103 
2104  '' walk along all the const flags
2105  for i as integer = start_at to l_cnt
2106 
2107  '' same? update matches
2108  if( typeIsConstAt( ldtype, i ) = typeIsConstAt( rdtype, i ) ) then
2109  if( (r_cnt) > matches ) then
2110  matches = r_cnt
2111  end if
2112  end if
2113 
2114  '' if r is const and l isn't... (only pointers/refs checked here)
2115  if( typeIsConstAt( rdtype, i ) ) then
2116  if( typeIsConstAt( ldtype, i ) = FALSE ) then
2117  exit function
2118  end if
2119  end if
2120 
2121  r_cnt -= 1
2122  next
2123 
2124  function = TRUE
2125 
2126 end function
2127 
2128 #if __FB_DEBUG__
2129 static shared as zstring ptr classnames(FB_SYMBCLASS_VAR to FB_SYMBCLASS_NSIMPORT) = _
2130 { _
2131  @"var" , _
2132  @"const" , _
2133  @"proc" , _
2134  @"param" , _
2135  @"define" , _
2136  @"keyword" , _
2137  @"label" , _
2138  @"namespace", _
2139  @"enum" , _
2140  @"struct" , _
2141  @"class" , _
2142  @"field" , _
2143  @"bitfield" , _
2144  @"typedef" , _
2145  @"fwdref" , _
2146  @"scope" , _
2147  @"nsimport" _
2148 }
2149 
2150 '' For debugging
2151 function typeDump _
2152  ( _
2153  byval dtype as integer, _
2154  byval subtype as FBSYMBOL ptr _
2155  ) as string
2156 
2157  dim as string dump
2158  dim as integer ok = any, ptrcount = any
2159 
2160  dump = "["
2161 
2162  if( dtype and FB_DATATYPE_INVALID ) then
2163  dump += "invalid"
2164  ok = (subtype = NULL)
2165  else
2166  ptrcount = abs( typeGetPtrCnt( dtype ) )
2167 
2168  if( typeIsConstAt( dtype, ptrcount ) ) then
2169  dump += "const "
2170  end if
2171 
2172  select case( typeGetDtOnly( dtype ) )
2173  case FB_DATATYPE_STRUCT
2174  dump += "struct"
2175  case FB_DATATYPE_WCHAR
2176  dump += "wchar"
2177  case else
2178  dump += *symb_dtypeTB(typeGetDtOnly( dtype )).name
2179  end select
2180 
2181  '' UDT name
2182  select case( typeGetDtOnly( dtype ) )
2183  case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM
2184  if( subtype ) then
2185  if( symbIsStruct( subtype ) ) then
2186  dump += " " + *symbGetName( subtype )
2187  end if
2188  end if
2189  end select
2190 
2191  for i as integer = (ptrcount-1) to 0 step -1
2192  if( typeIsConstAt( dtype, i ) ) then
2193  dump += " const"
2194  end if
2195  dump += " ptr"
2196  next
2197 
2198  '' Report unusual subtypes
2199  if( subtype ) then
2200  select case( typeGetDtOnly( dtype ) )
2201  case FB_DATATYPE_STRUCT
2202  ok = symbIsStruct( subtype )
2203  case FB_DATATYPE_ENUM
2204  ok = symbIsEnum( subtype )
2205  case FB_DATATYPE_NAMESPC
2206  ok = symbIsNamespace( subtype )
2207  case FB_DATATYPE_BITFIELD
2208  ok = symbIsBitfield( subtype )
2209  case FB_DATATYPE_FUNCTION
2210  ok = symbIsProc( subtype )
2211  case FB_DATATYPE_FWDREF
2212  ok = symbIsFwdref( subtype )
2213  case else
2214  ok = FALSE
2215  end select
2216  else
2217  select case( typeGetDtOnly( dtype ) )
2218  case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM, _
2219  FB_DATATYPE_NAMESPC, FB_DATATYPE_BITFIELD, _
2220  FB_DATATYPE_FUNCTION, FB_DATATYPE_FWDREF
2221  ok = FALSE
2222  case else
2223  ok = TRUE
2224  end select
2225  end if
2226  end if
2227 
2228  if( ok = FALSE ) then
2229  dump += ", "
2230  if( subtype ) then
2231  if( (subtype->class >= FB_SYMBCLASS_VAR) and _
2232  (subtype->class < FB_SYMBCLASS_NSIMPORT) ) then
2233  dump += *classnames(subtype->class)
2234  else
2235  dump += str( subtype->class )
2236  end if
2237  else
2238  dump += "NULL"
2239  end if
2240  end if
2241 
2242  dump += "]"
2243 
2244  function = dump
2245 end function
2246 
2247 function hGetNamespacePrefix( byval sym as FBSYMBOL ptr ) as string
2248  dim as FBSYMBOL ptr ns = any
2249  dim as string s
2250 
2251  ns = symbGetNamespace( sym )
2252  while( ns <> @symbGetGlobalNamespc( ) )
2253  s = *symbGetName( ns ) + "." + s
2254 
2255  if( symbGetHashtb( ns ) = NULL ) then
2256  exit while
2257  end if
2258 
2259  ns = symbGetNamespace( ns )
2260  wend
2261 
2262  function = s
2263 end function
2264 
2265 function symbDump( byval sym as FBSYMBOL ptr ) as string
2266  dim as string s
2267 
2268  if( sym = NULL ) then
2269  return "<NULL>"
2270  end if
2271 
2272 #if 0
2273  s += "[" & hex( sym ) & "] "
2274 #endif
2275 
2276 #if 1
2277  if( (sym->class < FB_SYMBCLASS_VAR) or (sym->class > FB_SYMBCLASS_NSIMPORT) ) then
2278  s += "<bad class " + str( sym->class ) + "> "
2279  else
2280  s += *classnames(sym->class) + " "
2281  end if
2282 #endif
2283 
2284 #if 1
2285  #macro checkAttrib( ID )
2286  if( sym->attrib and FB_SYMBATTRIB_##ID ) then
2287  s += lcase( #ID ) + " "
2288  end if
2289  #endmacro
2290 
2291  checkAttrib( SHARED )
2292  checkAttrib( STATIC )
2293  checkAttrib( DYNAMIC )
2294  checkAttrib( COMMON )
2295  checkAttrib( EXTERN )
2296  checkAttrib( PUBLIC )
2297  checkAttrib( PRIVATE )
2298  checkAttrib( LOCAL )
2299  checkAttrib( EXPORT )
2300  checkAttrib( IMPORT )
2301  checkAttrib( OVERLOADED )
2302  if( symbIsProc( sym ) ) then
2303  checkAttrib( METHOD )
2304  else
2305  checkAttrib( PARAMINSTANCE )
2306  end if
2307  checkAttrib( CONSTRUCTOR )
2308  checkAttrib( DESTRUCTOR )
2309  checkAttrib( OPERATOR )
2310  checkAttrib( PROPERTY )
2311  checkAttrib( PARAMBYDESC )
2312  checkAttrib( PARAMBYVAL )
2313  checkAttrib( PARAMBYREF )
2314  checkAttrib( LITERAL )
2315  checkAttrib( CONST )
2316  if( symbIsProc( sym ) ) then
2317  checkAttrib( STATICLOCALS )
2318  else
2319  checkAttrib( OPTIONAL )
2320  end if
2321  checkAttrib( TEMP )
2322  checkAttrib( DESCRIPTOR )
2323  checkAttrib( FUNCRESULT )
2324  checkAttrib( RETURNSBYREF )
2325  checkAttrib( VIS_PRIVATE )
2326  checkAttrib( VIS_PROTECTED )
2327  if( symbIsProc( sym ) ) then
2328  checkAttrib( NAKED )
2329  else
2330  checkAttrib( SUFFIXED )
2331  end if
2332  checkAttrib( ABSTRACT )
2333  checkAttrib( VIRTUAL )
2334 #endif
2335 
2336 #if 1
2337  #macro checkStat( ID )
2338  if( sym->stats and FB_SYMBSTATS_##ID ) then
2339  s += lcase( #ID ) + " "
2340  end if
2341  #endmacro
2342 
2343  checkStat( VARALLOCATED )
2344  checkStat( ACCESSED )
2345  if( symbIsProc( sym ) ) then
2346  checkStat( CTORINITED )
2347  else
2348  checkStat( INITIALIZED )
2349  end if
2350  checkStat( DECLARED )
2351  checkStat( RTL )
2352  checkStat( THROWABLE )
2353  checkStat( PARSED )
2354  checkStat( HASALIAS )
2355  if( symbIsProc( sym ) ) then
2356  checkStat( EXCLPARENT )
2357  else
2358  checkStat( DONTINIT )
2359  end if
2360  checkStat( MAINPROC )
2361  checkStat( MODLEVELPROC )
2362  checkStat( FUNCPTR )
2363  checkStat( JUMPTB )
2364  checkStat( GLOBALCTOR )
2365  checkStat( GLOBALDTOR )
2366  checkStat( CANTDUP )
2367  if( symbIsProc( sym ) ) then
2368  checkStat( GCCBUILTIN )
2369  checkStat( IRHLCBUILTIN )
2370  end if
2371  checkStat( HASRTTI )
2372  checkStat( CANTUNDEF )
2373  if( symbIsField( sym ) ) then
2374  checkStat( UNIONFIELD )
2375  elseif( symbIsProc( sym ) ) then
2376  checkStat( PROCEMITTED )
2377  else
2378  checkStat( WSTRING )
2379  end if
2380  checkStat( RTL_CONST )
2381  checkStat( EMITTED )
2382  checkStat( BEINGEMITTED )
2383 #endif
2384 
2385  if( sym->class = FB_SYMBCLASS_NSIMPORT ) then
2386  s += "from: "
2387  s += symbDump( sym->nsimp.imp_ns )
2388  return s
2389  end if
2390 
2391 #if 1
2392  if( sym = @symbGetGlobalNamespc( ) ) then
2393  s += "<global namespace>"
2394  else
2395  s += hGetNamespacePrefix( sym )
2396  end if
2397 #endif
2398 
2399  if( symbIsProc( sym ) and symbIsOperator( sym ) ) then
2400  s += *astGetOpId( symbGetProcOpOvl( sym ) )
2401  else
2402  if( sym->id.name ) then
2403  s += *sym->id.name
2404  else
2405  s += "<unnamed>"
2406  end if
2407  end if
2408 
2409 #if 1
2410  if( sym->id.alias ) then
2411  s += " alias """ + *sym->id.alias + """"
2412  end if
2413 #endif
2414 
2415 #if 0
2416  '' Note: symbGetMangledName() will mangle the proc and set the
2417  '' "mangled" flag. If this is done too early though, before the proc is
2418  '' setup properly, then the mangled name will be empty or wrong.
2419  s += " mangled """ + *symbGetMangledName( sym ) + """"
2420 #endif
2421 
2422  s += " as "
2423 
2424  if( sym->typ and FB_DATATYPE_INVALID ) then
2425  if( sym->class = FB_SYMBCLASS_KEYWORD ) then
2426  s += "<keyword>"
2427  else
2428  s += "<invalid>"
2429  end if
2430  else
2431  '' UDTs themselves are FB_DATATYPE_STRUCT, but with NULL subtype,
2432  '' so treat that as special case, so symbTypeToStr() doesn't crash.
2433  if( sym->subtype = NULL ) then
2434  select case as const( sym->typ )
2435  case FB_DATATYPE_FWDREF
2436  s += "<fwdref>"
2437  case FB_DATATYPE_STRUCT
2438  if( symbIsStruct( sym ) ) then
2439  if( symbGetUDTIsUnion( sym ) ) then
2440  s += "<union>"
2441  else
2442  s += "<struct>"
2443  end if
2444  else
2445  s += "<struct>"
2446  end if
2447  case FB_DATATYPE_ENUM
2448  s += "<enum>"
2449  case else
2450  s += symbTypeToStr( sym->typ, NULL, sym->lgt )
2451  end select
2452  else
2453  s += symbTypeToStr( sym->typ, sym->subtype, sym->lgt )
2454  end if
2455  end if
2456 
2457  function = s
2458 end function
2459 
2460 sub symbDumpNamespace( byval ns as FBSYMBOL ptr )
2461  dim as FBSYMBOL ptr i = any
2462  dim as THASH ptr hash = any
2463  dim as HASHITEM ptr hashitem = any
2464 
2465  select case( ns->class )
2466  case FB_SYMBCLASS_STRUCT, FB_SYMBCLASS_ENUM, FB_SYMBCLASS_NAMESPACE
2467 
2468  case else
2469  print "symbDumpNamespace(): not a namespace"
2470  end select
2471 
2472  print symbDump( ns ) + ":"
2473 
2474  i = symbGetCompSymbTb( ns ).head
2475  while( i )
2476  print " symtb: " + symbDump( i )
2477  i = i->next
2478  wend
2479 
2480  hash = @symbGetCompHashTb( ns ).tb
2481  for index as integer = 0 to hash->nodes-1
2482  hashitem = hash->list[index].head
2483  while( hashitem )
2484  print " hashtb[" & index & "]: " + *hashitem->name + " = " + symbDump( hashitem->data )
2485  hashitem = hashitem->next
2486  wend
2487  next
2488 end sub
2489 #endif
2490