FreeBASIC  0.91.0
rtl.bas
Go to the documentation of this file.
1 '' intrinsic runtime lib core routines
2 ''
3 '' chng: oct/2004 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "ast.bi"
9 #include once "rtl.bi"
10 
11 declare sub rtlArrayModInit ( )
12 declare sub rtlConsoleModInit ( )
13 declare sub rtlDataModInit ( )
14 declare sub rtlErrorModInit ( )
15 declare sub rtlFileModInit ( )
16 declare sub rtlGfxModInit ( )
17 declare sub rtlMacroModInit ( )
18 declare sub rtlMathModInit ( )
19 declare sub rtlMemModInit ( )
20 declare sub rtlPrintModInit ( )
21 declare sub rtlProfileModInit ( )
22 declare sub rtlStringModInit ( )
23 declare sub rtlSystemModInit ( )
24 declare sub rtlGosubModInit ( )
25 declare sub rtlOOPModInit ( )
26 
27 declare sub rtlArrayModEnd ( )
28 declare sub rtlConsoleModEnd ( )
29 declare sub rtlDataModEnd ( )
30 declare sub rtlErrorModEnd ( )
31 declare sub rtlFileModEnd ( )
32 declare sub rtlGfxModEnd ( )
33 declare sub rtlMacroModEnd ( )
34 declare sub rtlMathModEnd ( )
35 declare sub rtlMemModEnd ( )
36 declare sub rtlPrintModEnd ( )
37 declare sub rtlProfileModEnd ( )
38 declare sub rtlStringModEnd ( )
39 declare sub rtlSystemModEnd ( )
40 declare sub rtlGosubModEnd ( )
41 declare sub rtlOOPModEnd ( )
42 
43 
44 type RTLCTX
46 end type
47 
48 ''globals
49  dim shared ctx as RTLCTX
50  dim shared rtlLookupTB(0 to FB_RTL_INDEXES-1) as FBSYMBOL ptr
51 
52 
53 '':::::
54 sub rtlInit static
55 
56  listInit( @ctx.arglist, 8*4, len( FB_CALL_ARG ), LIST_FLAGS_NOCLEAR )
57 
63  rtlGfxModInit( )
66  rtlMemModInit( )
72  rtlOOPModInit( )
73 
74 end sub
75 
76 '':::::
77 sub rtlEnd
78 
79  rtlOOPModEnd( )
85  rtlMemModEnd( )
86  rtlMathModEnd( )
88  rtlGfxModEnd( )
89  rtlFileModEnd( )
91  rtlDataModEnd( )
94 
95  listEnd( @ctx.arglist )
96 
97  '' reset the table as the pointers will change if
98  '' the compiler is reinitialized
99  erase rtlLookupTB
100 
101 end sub
102 
103 sub rtlAddIntrinsicProcs( byval procdef as const FB_RTL_PROCDEF ptr )
104  dim as FBSYMBOL ptr param = any
105  dim as integer callconv = any
106 
107  '' for each proc..
108  do
109  if( procdef->name = NULL ) then
110  exit do
111  end if
112 
113  callconv = procdef->callconv
114 
115  '' Use the default FBCALL?
116  if( callconv = FB_FUNCMODE_FBCALL ) then
117  callconv = env.target.fbcall
118  end if
119 
120  dim as integer doadd = TRUE
121  if( procdef->options and FB_RTL_OPT_MT ) then
122  doadd = fbLangOptIsSet( FB_LANG_OPT_MT )
123  end if
124 
125  if( procdef->options and FB_RTL_OPT_X86ONLY ) then
126  doadd and= fbCpuTypeIsX86( )
127  end if
128 
129  if( doadd ) then
130  if( (procdef->options and FB_RTL_OPT_QBONLY) <> 0 ) then
131  doadd = ( env.clopt.lang = FB_LANG_QB )
132  end if
133  if( (procdef->options and FB_RTL_OPT_FBONLY) <> 0 ) then
134  doadd = ( env.clopt.lang = FB_LANG_FB )
135  end if
136  if( (procdef->options and FB_RTL_OPT_NOFB) <> 0 ) then
137  doadd = ( env.clopt.lang <> FB_LANG_FB )
138  end if
139  end if
140 
141  if( doadd ) then
142  dim as FBSYMBOL ptr proc = symbPreAddProc( NULL )
143 
144  '' for each parameter..
145  for i as integer = 0 to procdef->params-1
146  with procdef->paramTb(i)
147  dim as FBSYMBOL ptr subtype = NULL
148  dim as integer attrib = any, dtype = any
149  dim as ASTNODE ptr param_optval = any
150  if( .isopt ) then
151  attrib = FB_SYMBATTRIB_OPTIONAL
152 
153  select case as const .dtype
154  case FB_DATATYPE_STRING
155  '' only NULL can be used
156  param_optval = astNewCONSTstr( "" )
157 
158  case FB_DATATYPE_SINGLE, FB_DATATYPE_DOUBLE
159  param_optval = astNewCONSTf( .optval, .dtype )
160 
161  '' function pointers need a symbol built so they can check matches
162  case typeAddrOf( FB_DATATYPE_FUNCTION )
163  dim as integer inner_attrib = any, func_arg = any
164  dim as ASTNODE ptr inner_param_optval = any
165  dim as FBSYMBOL ptr inner_proc = any
166 
167  '' scan through the next args as child args
168  inner_proc = symbPreAddProc( NULL )
169  for func_arg = 0 to .optval-1
170  i += 1
171 
172  with procdef->paramTb(i)
173  if( .isopt ) then
174  inner_attrib = FB_SYMBATTRIB_OPTIONAL
175  select case as const .dtype
176  case FB_DATATYPE_STRING
177  '' only NULL can be used
178  inner_param_optval = astNewCONSTstr( "" )
179 
180  case FB_DATATYPE_SINGLE, FB_DATATYPE_DOUBLE
181  inner_param_optval = astNewCONSTf( .optval, .dtype )
182 
183  case else
184  inner_param_optval = astNewCONSTi( .optval, .dtype )
185  end select
186  else
187  inner_param_optval = NULL
188  inner_attrib = 0
189  end if
190 
191  param = symbAddProcParam( inner_proc, NULL, .dtype, NULL, .mode, inner_attrib )
192  symbMakeParamOptional( inner_proc, param, inner_param_optval )
193  end with
194  next
195 
196  '' next arg is result type
197 
198  i += 1
199  with procdef->paramTb(i)
200  '' add it
201  '' Note: using FBCALL for the function pointer.
202  '' Must match the function's declaration in the
203  '' rtlib. Currently only fb_ThreadCreate() is
204  '' affected.
205  subtype = symbAddProcPtr( inner_proc, .dtype, NULL, 0, env.target.fbcall )
206 
207  '' due to the ambiguity (need to say it's optional to
208  '' even get to this point), the symbol's return type will
209  '' be what specifies if the parent symbol is optional
210  if( .isopt = FALSE ) then
211  attrib = 0
212  end if
213  end with
214 
215  param_optval = NULL
216 
217  case else
218  param_optval = astNewCONSTi( .optval, .dtype )
219 
220  end select
221  else
222  attrib = 0
223  param_optval = NULL
224  end if
225 
226  dtype = .dtype
227  if( dtype = FB_DATATYPE_INVALID ) then
228  dtype = typeAddrOf( FB_DATATYPE_VOID )
229  end if
230 
231  param = symbAddProcParam( proc, NULL, dtype, subtype, .mode, attrib )
232 
233  if( .check_const ) then
234  symbSetIsRTLConst( param )
235  end if
236 
237  symbMakeParamOptional( proc, param, param_optval )
238  end with
239  next
240 
241  ''
242  dim as FB_SYMBATTRIB attrib = 0
243  if( (procdef->options and FB_RTL_OPT_OVER) <> 0 ) then
244  attrib = FB_SYMBATTRIB_OVERLOADED
245  end if
246 
247  if( (procdef->options and FB_RTL_OPT_STRSUFFIX) <> 0 ) then
248  attrib or= FB_SYMBATTRIB_SUFFIXED
249  end if
250 
251  '' Note: for operators, this is the AST_OP_* value, not a valid zstring ptr
252  dim as const zstring ptr pname = procdef->name
253  dim as const zstring ptr palias = procdef->alias
254 
255  '' ordinary proc?
256  if( (procdef->options and FB_RTL_OPT_OPERATOR) = 0 ) then
257  '' add the '__' prefix if the proc wasn't present in QB and we are in '-lang qb' mode
258  if( (procdef->options and FB_RTL_OPT_NOQB) <> 0 ) then
259  if( fbLangIsSet( FB_LANG_QB ) ) then
260  if( palias = NULL ) then
261  static as string tmp_alias
262  tmp_alias = *pname
263  palias = strptr( tmp_alias )
264  end if
265 
266  static as string tmp_name
267  tmp_name = "__" + *pname
268  pname = strptr( tmp_name )
269  end if
270  end if
271 
272  if( palias = NULL ) then
273  palias = pname
274  end if
275 
276  proc = symbAddProc( proc, pname, palias, _
277  procdef->dtype, NULL, attrib, callconv, _
278  FB_SYMBOPT_DECLARING or FB_SYMBOPT_RTL )
279 
280  '' operator..
281  else
282  proc = symbAddOperator( proc, cast(AST_OP, pname), NULL, _
283  procdef->dtype, NULL, attrib or FB_SYMBATTRIB_OPERATOR, callconv, _
284  FB_SYMBOPT_DECLARING or FB_SYMBOPT_RTL )
285 
286  if( proc <> NULL ) then
287  symbGetMangling( proc ) = FB_MANGLING_CPP
288  end if
289  end if
290 
291  if( proc <> NULL ) then
292  symbSetProcCallback( proc, procdef->callback )
293  if( (procdef->options and FB_RTL_OPT_ERROR) <> 0 ) then
294  symbSetIsThrowable( proc )
295  end if
296 
297  if( (procdef->options and FB_RTL_OPT_IRHLCBUILTIN) <> 0 ) then
298  symbSetIsIrHlcBuiltin( proc )
299  end if
300 
301  if( (procdef->options and FB_RTL_OPT_GCCBUILTIN) <> 0 ) then
302  symbSetIsGccBuiltin( proc )
303  end if
304  else
305  if( (procdef->options and FB_RTL_OPT_OPERATOR) = 0 ) then
306  errReportEx( FB_ERRMSG_DUPDEFINITION, *procdef->name )
307  else
308  errReport( FB_ERRMSG_DUPDEFINITION )
309  end if
310  end if
311  end if
312 
313  '' next
314  procdef += 1
315  loop
316 end sub
317 
318 '':::::
319 function rtlProcLookup _
320  ( _
321  byval pname as const zstring ptr, _
322  byval pidx as integer _
323  ) as FBSYMBOL ptr
324 
325  dim as FBSYMCHAIN ptr chain_ = any
326 
327  '' not cached yet? -- this won't work if #undef is used
328  '' what is pretty unlikely with internal fb_* procs
329  if( rtlLookupTB( pidx ) = NULL ) then
330  chain_ = symbLookupAt( @symbGetGlobalNamespc( ), pname, FALSE, FALSE )
331  if( chain_ = NULL ) then
332  '' try to prefix it with a '__' if in -lang qb mode
333  if( fbLangIsSet( FB_LANG_QB ) ) then
334  static as string tmp_name
335  tmp_name = "__" + *pname
336  pname = strptr( tmp_name )
337  chain_ = symbLookupAt( @symbGetGlobalNamespc( ), pname, FALSE, FALSE )
338  if( chain_ = NULL ) then
339  errReportEx( FB_ERRMSG_UNDEFINEDSYMBOL, *pname )
340  rtlLookupTB( pidx ) = NULL
341  else
342  rtlLookupTB( pidx ) = chain_->sym
343  end if
344 
345  else
346  errReportEx( FB_ERRMSG_UNDEFINEDSYMBOL, *pname )
347  rtlLookupTB( pidx ) = NULL
348  end if
349  else
350  rtlLookupTB( pidx ) = chain_->sym
351  end if
352  end if
353 
354  function = rtlLookupTB( pidx )
355 
356 end function
357 
358 '':::::
359 function rtlOvlProcCall _
360  ( _
361  byval sym as FBSYMBOL ptr, _
362  byval param1 as ASTNODE ptr, _
363  byval param2 as ASTNODE ptr _
364  ) as ASTNODE ptr
365 
366  dim as FB_ERRMSG err_num = any
367  dim as integer args = 0
368  dim as FB_CALL_ARG_LIST arg_list = ( 0, NULL, NULL )
369 
370  var arg = symbAllocOvlCallArg( @ctx.arglist, @arg_list, FALSE )
371  arg->expr = param1
372  arg->mode = FB_PARAMMODE_BYVAL
373  args += 1
374 
375  if( param2 <> NULL ) then
376  arg = symbAllocOvlCallArg( @ctx.arglist, @arg_list, FALSE )
377  arg->expr = param2
378  arg->mode = FB_PARAMMODE_BYVAL
379  args += 1
380  end if
381 
382  var proc = symbFindClosestOvlProc( sym, args, arg_list.head, @err_num, FB_SYMBLOOKUPOPT_NONE )
383 
384  if( proc = NULL ) then
385  symbFreeOvlCallArgs( @ctx.arglist, @arg_list )
386  return NULL
387  end if
388 
389  var procexpr = astNewCALL( proc, NULL )
390 
391  '' add to tree
392  arg = arg_list.head
393  do while( arg <> NULL )
394  var nxt = arg->next
395 
396  if( astNewARG( procexpr, arg->expr, , arg->mode ) = NULL ) then
397  return NULL
398  end if
399 
400  symbFreeOvlCallArg( @ctx.arglist, arg )
401 
402  '' next
403  arg = nxt
404  loop
405 
406  function = procexpr
407 
408 end function
409 
410 '':::::
411 '' note: this function must be called *before* astNewARG(e) because the
412 '' expression 'e' can be changed inside the former (address-of string's etc)
413 function rtlCalcExprLen( byval expr as ASTNODE ptr ) as longint
414  dim as FBSYMBOL ptr s = any
415  dim as integer dtype = any
416 
417  dtype = astGetDataType( expr )
418  select case as const dtype
419  case FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
420  function = rtlCalcStrLen( expr, dtype )
421 
422  case else
423  function = symbCalcLen( dtype, astGetSubtype( expr ) )
424  end select
425 end function
426 
427 '':::::
428 '' note: this function must be called *before* astNewARG(e) because the
429 '' expression 'e' can be changed inside the former (address-of string's etc)
430 function rtlCalcStrLen _
431  ( _
432  byval expr as ASTNODE ptr, _
433  byval dtype as integer _
434  ) as longint
435 
436  dim as FBSYMBOL ptr s
437 
438  select case as const typeGet( dtype )
439  case FB_DATATYPE_BYTE, FB_DATATYPE_UBYTE
440  function = 0
441 
442  case FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR
443  s = astGetSymbol( expr )
444  '' pointer?
445  if( s = NULL ) then
446  function = 0
447  else
448  if( symbGetType( s ) <> typeGetDtAndPtrOnly( dtype ) ) then
449  function = 0
450  else
451  function = symbGetStrLen( s )
452  end if
453  end if
454 
455  case FB_DATATYPE_WCHAR
456  s = astGetSymbol( expr )
457  '' pointer?
458  if( s = NULL ) then
459  function = 0
460  else
461  if( symbGetType( s ) <> typeGetDtAndPtrOnly( dtype ) ) then
462  function = 0
463  else
464  function = symbGetWStrLen( s )
465  end if
466  end if
467 
468  case else
469  function = -1
470  end select
471 
472 end function
473