FreeBASIC  0.91.0
parser-decl-typedef.bas
Go to the documentation of this file.
1 '' typedef (TYPE foo AS bar) declarations
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 
10 sub hPtrDecl(byref dtype as integer)
11  dim as integer ptr_cnt = 0
12 
13  '' (CONST (PTR|POINTER) | (PTR|POINTER))*
14  do
15  select case as const lexGetToken( )
16  '' CONST PTR?
17  case FB_TK_CONST
18  lexSkipToken( )
19 
20  select case lexGetToken( )
21  case FB_TK_PTR, FB_TK_POINTER
22  if( ptr_cnt >= FB_DT_PTRLEVELS ) then
23  errReport( FB_ERRMSG_TOOMANYPTRINDIRECTIONS )
24  else
25  dtype = typeSetIsConst( typeAddrOf( dtype ) )
26  ptr_cnt += 1
27  end if
28 
29  lexSkipToken( )
30 
31  case else
32  errReport( FB_ERRMSG_EXPECTEDPTRORPOINTER )
33  exit do
34  end select
35 
36  '' PTR|POINTER?
37  case FB_TK_PTR, FB_TK_POINTER
38  if( ptr_cnt >= FB_DT_PTRLEVELS ) then
39  errReport( FB_ERRMSG_TOOMANYPTRINDIRECTIONS )
40  else
41  dtype = typeAddrOf( dtype )
42  ptr_cnt += 1
43  end if
44 
45  lexSkipToken( )
46 
47  case else
48  exit do
49  end select
50  loop
51 end sub
52 
53 function hReadType _
54  ( _
55  byref dtype as integer, _
56  byref subtype as FBSYMBOL ptr, _
57  byref lgt as longint _
58  ) as zstring ptr
59 
60  static as zstring * FB_MAXNAMELEN+1 tname
61  dim as zstring ptr pfwdname = any
62 
63  function = NULL
64 
65  if( cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE ) = FALSE ) then
66  '' Everything not recognized by cSymbolType() is either still undefined,
67  '' so we'll make it a forward ref, or it's an existing forward ref, and
68  '' we'll look it up.
69  '' Note: cSymbolType() could have parsed a CONST before the unknown typname
70 
71  '' Get the forward ref's name
72  tname = *lexGetText( )
73  pfwdname = @tname
74 
75  lexSkipToken( )
76 
77  '' Parse any PTR's since cSymbolType() didn't handle it
78  '' dtype is modified as needed
79  hPtrDecl( dtype )
80 
81  function = pfwdname
82  end if
83 
84 end function
85 
86 sub hAddForwardRef _
87  ( _
88  byval pid as zstring ptr, _
89  byval pfwdname as zstring ptr, _
90  byref dtype as integer, _
91  byref subtype as FBSYMBOL ptr, _
92  byref lgt as longint _
93  )
94 
95  dim as integer ptrcount = typeGetPtrCnt( dtype )
96  dim as integer constmask = typeGetConstMask( dtype )
97 
98  '' Pointing to itself (TYPE X AS X)? Then it's a void...
99  hUcase( pfwdname, pfwdname )
100  hUcase( pid, pid )
101  if( *pfwdname = *pid ) then
102 
103  ''dtype = typeJoin( dtype, FB_DATATYPE_VOID )
104  dtype = FB_DATATYPE_VOID
105 
106 /'
107  dtype = (dtype and not FB_DT_TYPEMASK) or FB_DATATYPE_VOID
108  '/
109 
110  subtype = NULL
111  lgt = 0
112  else
113 
114  '' The typeJoin()'s will remove the PTR's off the typedef's type, but we
115  '' want to preserve them, so we need to restore them later.
116  '' But typeJoin() doesn't adjust the CONST mask -- that seems wrong...
117  '' (if PTR's are removed, their CONST should be removed aswell, if set)
118  '' Because of that the type will seem to be const even though it isn't
119  '' (CONST bits are set but ptrcount is 0),
120  '' and the typeMultAddrOf() will preserve this error when adding back the
121  '' pointer count...
122  ''dtype = typeJoin( dtype, FB_DATATYPE_FWDREF )
123 
124  '' So how about that: (dtype will be FB_DATATYPE_INVALID for fwdref's
125  '' anyways, at best cSymbolType() and/or hPtrDecl() added CONST's/PTR's)
126  dtype = FB_DATATYPE_FWDREF
127 
128 /'
129  '' Or this way: Replace only the type but preserve everything else
130  dtype = (dtype and not FB_DT_TYPEMASK) or FB_DATATYPE_FWDREF
131  '/
132 
133  '' Create a forward reference
134  subtype = symbAddFwdRef( pfwdname )
135  lgt = -1
136 
137  '' Already exists? (happens e.g. with the multiple declaration syntax)
138  if( subtype = NULL ) then
139  '' Lookup the existing one
140  subtype = symbLookupByNameAndClass( symbGetCurrentNamespc( ), _
141  pfwdname, _
142  FB_SYMBCLASS_FWDREF, _
143  TRUE, _
144  FALSE )
145 
146  if( subtype = NULL ) then
147  errReport( FB_ERRMSG_DUPDEFINITION )
148  '' error recovery: fake a symbol
149  subtype = symbAddFwdRef( symbUniqueLabel( ) )
150  end if
151  end if
152  end if
153 
154  '' Restore the PTR's & CONST's on the type
155  dtype = typeMultAddrOf( dtype, ptrcount ) or constmask
156 end sub
157 
158 sub hAddTypedef _
159  ( _
160  byval pid as zstring ptr, _
161  byval pfwdname as zstring ptr, _
162  byval dtype as integer, _
163  byval subtype as FBSYMBOL ptr, _
164  byval lgt as longint _
165  )
166 
167  '' Forward ref? Note: may update dtype & co
168  if( pfwdname <> NULL ) then
169  hAddForwardRef( pid, pfwdname, dtype, subtype, lgt )
170  end if
171 
172  dim as FBSYMBOL ptr typedef = symbAddTypedef( pid, dtype, subtype, lgt )
173  if( typedef = NULL ) then
174  '' check if the dup definition is different
175  dim as integer isdup = TRUE
176  dim as FBSYMBOL ptr sym = any
177 
178  sym = symbLookupByNameAndClass( symbGetCurrentNamespc( ), _
179  pid, _
180  FB_SYMBCLASS_TYPEDEF, _
181  FALSE, _
182  FALSE )
183 
184  if( sym <> NULL ) then
185  if( symbGetFullType( sym ) = dtype ) then
186  if( symbGetSubType( sym ) = subtype ) then
187  isdup = FALSE
188  end if
189  end if
190  end if
191 
192  if( isdup ) then
193  errReport( FB_ERRMSG_DUPDEFINITION, TRUE )
194  end if
195  end if
196 end sub
197 
198 function hReadId( ) as zstring ptr
199 
200  static as zstring * FB_MAXNAMELEN+1 id
201 
202  '' Namespace identifier if it matches the current namespace
204 
205  select case as const lexGetClass( )
206  case FB_TKCLASS_IDENTIFIER, FB_TKCLASS_KEYWORD, FB_TKCLASS_QUIRKWD
207 
208  if( fbLangOptIsSet( FB_LANG_OPT_PERIODS ) ) then
209  '' if inside a namespace, symbols can't contain periods (.)'s
210  if( symbIsGlobalNamespc( ) = FALSE ) then
211  if( lexGetPeriodPos( ) > 0 ) then
212  errReport( FB_ERRMSG_CANTINCLUDEPERIODS )
213  end if
214  end if
215  end if
216 
217  id = *lexGetText( )
218  lexSkipToken( )
219 
220  case else
221  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
222  '' error recovery: fake an id
223  id = *symbUniqueLabel( )
224  end select
225 
226  function = @id
227 
228 end function
229 
230 '' MultipleTypedef = TYPE AS SymbolType symbol (',' symbol)*
232  dim as zstring ptr pfwdname = any, pid = any
233  dim as integer dtype = any
234  dim as longint lgt = any
235  dim as FBSYMBOL ptr subtype = any
236 
237  if( cCompStmtIsAllowed( FB_CMPSTMT_MASK_DECL or FB_CMPSTMT_MASK_CODE ) = FALSE ) then
238  hSkipStmt( )
239  exit sub
240  end if
241 
242  '' AS
243  lexSkipToken( )
244 
245  '' SymtolType
246  pfwdname = hReadType( dtype, subtype, lgt )
247 
248  do
249  '' Parse the ID
250  pid = hReadId( )
251 
252  hAddTypedef( pid, pfwdname, dtype, subtype, lgt )
253 
254  '' ','?
255  if( lexGetToken( ) <> CHAR_COMMA ) then
256  exit do
257  end if
258 
259  lexSkipToken( )
260  loop
261 end sub
262 
263 '' SingleTypedef = TYPE symbol AS SymbolType (',' symbol AS SymbolType)*
264 sub cTypedefSingleDecl( byval pid as zstring ptr )
265  '' note: given id can be Ucase()'d
266 
267  if( cCompStmtIsAllowed( FB_CMPSTMT_MASK_DECL or FB_CMPSTMT_MASK_CODE ) = FALSE ) then
268  hSkipStmt( )
269  exit sub
270  end if
271 
272  dim as zstring ptr pfwdname = any
273  dim as integer dtype = any
274  dim as longint lgt = any
275  dim as FBSYMBOL ptr subtype = any
276 
277  do
278  '' AS?
279  if( lexGetToken( ) <> FB_TK_AS ) then
280  errReport( FB_ERRMSG_SYNTAXERROR )
281  else
282  lexSkipToken( )
283  end if
284 
285  '' SymtolType
286  pfwdname = hReadType( dtype, subtype, lgt )
287 
288  hAddTypedef( pid, pfwdname, dtype, subtype, lgt )
289 
290  '' ','?
291  if( lexGetToken( ) <> CHAR_COMMA ) then
292  exit do
293  end if
294 
295  lexSkipToken( )
296 
297  '' Parse the next ID
298  pid = hReadId( )
299  loop
300 end sub
301