FreeBASIC  0.91.0
symb-typedef.bas
Go to the documentation of this file.
1 '' symbol table module for typedef's
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 '' jan/2005 updated to use real linked-lists [v1ctor]
5 
6 
7 #include once "fb.bi"
8 #include once "fbint.bi"
9 #include once "parser.bi"
10 #include once "hash.bi"
11 #include once "list.bi"
12 
13 '':::::
15 
16  listInit( @symb.fwdlist, FB_INITFWDREFNODES, len( FBFWDREF ), LIST_FLAGS_NOCLEAR )
17 
18  symb.fwdrefcnt = 0
19 
20 end sub
21 
22 '':::::
24 
25  listEnd( @symb.fwdlist )
26 
27 end sub
28 
29 '':::::
30 sub symbAddToFwdRef _
31  ( _
32  byval f as FBSYMBOL ptr, _
33  byval ref as FBSYMBOL ptr _
34  )
35 
36  '' Add a symbol (ref) to the fwdref's list of references/users. The symbol
37  '' uses the fwdref as its subtype, and will need patching later when the
38  '' fwdref's actual type is known and can be filled in.
39 
40  dim as FBFWDREF ptr n = listNewNode( @symb.fwdlist )
41 
42  n->ref = ref
43  n->prev = f->fwd.tail
44  f->fwd.tail = n
45 
46 end sub
47 
48 '':::::
50  ( _
51  byval f as FBSYMBOL ptr, _
52  byval ref as FBSYMBOL ptr _
53  )
54 
55  dim as FBFWDREF ptr n = f->fwd.tail
56  dim as FBFWDREF ptr nxt = NULL
57 
58  do
59  '' The symbol should be in the fwdref's backpatching list, otherwise it
60  '' shouldn't have the fwdref datatype that got us here...
61  assert( n <> NULL )
62 
63  '' Found it?
64  if( n->ref = ref ) then
65  exit do
66  end if
67 
68  nxt = n
69  n = n->prev
70  loop
71 
72  if( nxt = NULL ) then
73  '' Removing the tail of the list
74  f->fwd.tail = n->prev
75  else
76  '' Link out of the middle
77  nxt->prev = n->prev
78  end if
79 
80  listDelNode( @symb.fwdlist, n )
81 
82 end sub
83 
85  ( _
86  byval s as FBSYMBOL ptr, _
87  byval dtype as integer, _
88  byval subtype as FBSYMBOL ptr _
89  )
90 
91  assert( typeGetDtOnly( symbGetFullType( s ) ) = FB_DATATYPE_FWDREF )
92 
93  '' If it's a parameter, fix up its initializer too (if any)
94  if( (s->class = FB_SYMBCLASS_PARAM) and symbGetIsOptional( s ) ) then
95  '' Replace old subtype by new subtype
96  astReplaceFwdref( s->param.optexpr, s->subtype, dtype, subtype )
97  end if
98 
99  dtype = typeMerge( symbGetFullType( s ), dtype )
100  symbSetType( s, dtype, subtype )
101 
102 end sub
103 
104 '':::::
105 sub hFixForwardRef _
106  ( _
107  byval fwd as FBSYMBOL ptr, _
108  byval sym as FBSYMBOL ptr _
109  )
110 
111  dim as FBFWDREF ptr node = any, prev = any
112  dim as FBSYMBOL ptr subtype = any
113  dim as integer dtype = any
114 
115  '' Replace all uses of this forward ref <fwd> with its actual
116  '' enum/struct/typedef replacement <sym>.
117  '' All symbols that use this fwdref were added to the fwdref's list of
118  '' references and now they can be updated.
119 
120  '' This is exactly what cSymbolType() is doing too:
121  select case as const symbGetClass( sym )
122  case FB_SYMBCLASS_STRUCT
123  dtype = FB_DATATYPE_STRUCT
124  subtype = sym
125 
126  case FB_SYMBCLASS_ENUM
127  dtype = FB_DATATYPE_ENUM
128  subtype = sym
129 
130  case else
131  assert(symbIsTypedef(sym))
132 
133  '' For an enum/struct the dtype will simply be FB_DATATYPE_ENUM/STRUCT,
134  '' but for a typedef, it can contain PTR's and CONST's, and the type
135  '' can be anything, even another FB_DATATYPE_FWDREF.
136  dtype = symbGetFullType( sym )
137 
138  '' For a typedef, its subtype (and not the typedef itself) is used to
139  '' replace the fwdref. Afterall there is no typedef data type.
140  subtype = symbGetSubtype( sym )
141 
142  end select
143 
144  '' Cycle through the forward ref's list of users
145  node = fwd->fwd.tail
146  do while( node <> NULL )
147 
148  '' Do the replacement in the user
149  symbReplaceForwardRef( node->ref, dtype, subtype )
150 
151  prev = node->prev
152  listDelNode( @symb.fwdlist, node )
153  node = prev
154  loop
155 
156  '' Delete the forward ref symbol -- since it's no longer used anywhere
157  symbFreeSymbol( fwd )
158 
159  symb.fwdrefcnt -= 1
160 
161 end sub
162 
163 '':::::
164 sub symbCheckFwdRef _
165  ( _
166  byval sym as FBSYMBOL ptr _
167  )
168 
169  dim as FBSYMBOL ptr fwd = any
170 
171  '' Find the fwdref that can be resolved with this <sym> (the new typedef/enum/type).
172 
173  '' to tail
174  fwd = sym
175  do
176  if( fwd->class = FB_SYMBCLASS_FWDREF ) then
177  hFixForwardRef( fwd, sym )
178  exit sub
179  end if
180 
181  fwd = fwd->hash.next
182  loop while( fwd <> NULL )
183 
184  '' to head
185  fwd = sym->hash.prev
186  do while( fwd <> NULL )
187 
188  if( fwd->class = FB_SYMBCLASS_FWDREF ) then
189  hFixForwardRef( fwd, sym )
190  exit sub
191  end if
192 
193  fwd = fwd->hash.prev
194  loop
195 
196 end sub
197 
198 '':::::
199 function symbAddTypedef _
200  ( _
201  byval id as zstring ptr, _
202  byval dtype as integer, _
203  byval subtype as FBSYMBOL ptr, _
204  byval lgt as longint _
205  ) as FBSYMBOL ptr
206 
207  dim as FBSYMBOL ptr t = any
208 
209  '' allocate new node
210  t = symbNewSymbol( FB_SYMBOPT_DOHASH, _
211  NULL, _
212  NULL, NULL, _
213  FB_SYMBCLASS_TYPEDEF, _
214  id, NULL, _
215  dtype, subtype )
216  if( t = NULL ) then
217  return NULL
218  end if
219 
220  ''
221  t->lgt = lgt
222 
223  '' check for forward references
224  if( symb.fwdrefcnt > 0 ) then
225  symbCheckFwdRef( t )
226  end if
227 
228  ''
229  function = t
230 
231 end function
232 
233 '':::::
234 function symbAddFwdRef _
235  ( _
236  byval id as zstring ptr _
237  ) as FBSYMBOL ptr
238 
239  dim as FBSYMBOL ptr f = any
240 
241  '' note: assuming id is already upper-cased
242 
243  '' allocate a new node
244  f = symbNewSymbol( FB_SYMBOPT_DOHASH or FB_SYMBOPT_PRESERVECASE, _
245  NULL, _
246  NULL, NULL, _
247  FB_SYMBCLASS_FWDREF, _
248  id, NULL, _
249  FB_DATATYPE_INVALID, NULL )
250  if( f = NULL ) then
251  return NULL
252  end if
253 
254  f->fwd.tail = NULL
255 
256  ''
257  symb.fwdrefcnt += 1
258 
259  function = f
260 
261 end function
262 
263 
264