FreeBASIC  0.91.0
rtl-error.bas
Go to the documentation of this file.
1 '' intrinsic runtime lib error functions (ERROR, ERR, ERL, RESUME, ...)
2 ''
3 '' chng: oct/2004 written [v1ctor]
4 
5 #include once "fb.bi"
6 #include once "fbint.bi"
7 #include once "parser.bi"
8 #include once "ast.bi"
9 #include once "rtl.bi"
10 
11  dim shared as FB_RTL_PROCDEF funcdata( 0 to ... ) = _
12  { _
13 /' function fb_ErrorThrowAt cdecl _
14  ( _
15  byval linenum as long, _
16  byval fname as zstring ptr, _
17  byval reslabel as any ptr, _
18  byval resnxtlabel as any ptr _
19  ) as FB_ERRHANDLER '/ _
20  ( _
21  @FB_RTL_ERRORTHROW, NULL, _
22  typeAddrOf( FB_DATATYPE_VOID ), FB_FUNCMODE_CDECL, _
23  NULL, FB_RTL_OPT_NONE, _
24  4, _
25  { _
26  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
27  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
28  ( typeAddrOf( FB_DATATYPE_VOID ), FB_PARAMMODE_BYVAL, FALSE ), _
29  ( typeAddrOf( FB_DATATYPE_VOID ), FB_PARAMMODE_BYVAL, FALSE ) _
30  } _
31  ), _
32 /' function fb_ErrorThrowEx cdecl _
33  ( _
34  byval errnum long, _
35  byval linenum as long, _
36  byval fname as zstring ptr, _
37  byval reslabel as any ptr, _
38  byval resnxtlabel as any ptr _
39  ) as FB_ERRHANDLER '/ _
40  ( _
41  @FB_RTL_ERRORTHROWEX, NULL, _
42  typeAddrOf( FB_DATATYPE_VOID ), FB_FUNCMODE_CDECL, _
43  NULL, FB_RTL_OPT_NONE, _
44  5, _
45  { _
46  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
47  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
48  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ), _
49  ( typeAddrOf( FB_DATATYPE_VOID ),FB_PARAMMODE_BYVAL, FALSE ), _
50  ( typeAddrOf( FB_DATATYPE_VOID ),FB_PARAMMODE_BYVAL, FALSE ) _
51  } _
52  ), _
53 /' function fb_ErrorSetHandler( byval newhandler as FB_ERRHANDLER ) as FB_ERRHANDLER '/ _
54  ( _
55  @FB_RTL_ERRORSETHANDLER, NULL, _
56  typeAddrOf( FB_DATATYPE_VOID ), FB_FUNCMODE_FBCALL, _
57  NULL, FB_RTL_OPT_NONE, _
58  1, _
59  { _
60  ( typeAddrOf( FB_DATATYPE_VOID ),FB_PARAMMODE_BYVAL, FALSE ) _
61  } _
62  ), _
63 /' function fb_ErrorGetNum( ) as long '/ _
64  ( _
65  @FB_RTL_ERRORGETNUM, NULL, _
66  FB_DATATYPE_LONG, FB_FUNCMODE_FBCALL, _
67  NULL, FB_RTL_OPT_NONE, _
68  0 _
69  ), _
70 /' function fb_ErrorSetNum( byval errnum as long ) as long '/ _
71  ( _
72  @FB_RTL_ERRORSETNUM, NULL, _
73  FB_DATATYPE_LONG, FB_FUNCMODE_FBCALL, _
74  NULL, FB_RTL_OPT_NONE, _
75  1, _
76  { _
77  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ) _
78  } _
79  ), _
80 /' function fb_ErrorResume cdecl( ) as any ptr '/ _
81  ( _
82  @FB_RTL_ERRORRESUME, NULL, _
83  typeAddrOf( FB_DATATYPE_VOID ), FB_FUNCMODE_CDECL, _
84  NULL, FB_RTL_OPT_NONE, _
85  0 _
86  ), _
87 /' function fb_ErrorResumeNext cdecl( ) as any ptr '/ _
88  ( _
89  @FB_RTL_ERRORRESUMENEXT, NULL, _
90  typeAddrOf( FB_DATATYPE_VOID ), FB_FUNCMODE_CDECL, _
91  NULL, FB_RTL_OPT_NONE, _
92  0 _
93  ), _
94 /' function erl( ) as long '/ _
95  ( _
96  @"erl", @"fb_ErrorGetLineNum", _
97  FB_DATATYPE_LONG, FB_FUNCMODE_FBCALL, _
98  NULL, FB_RTL_OPT_NONE, _
99  0 _
100  ), _
101 /' function erfn( ) as zstring ptr '/ _
102  ( _
103  @"erfn", @"fb_ErrorGetFuncName", _
104  typeAddrOf( FB_DATATYPE_CHAR ), FB_FUNCMODE_FBCALL, _
105  NULL, FB_RTL_OPT_NOQB, _
106  0 _
107  ), _
108 /' function ermn( ) as zstring ptr '/ _
109  ( _
110  @"ermn", @"fb_ErrorGetModName", _
111  typeAddrOf( FB_DATATYPE_CHAR ), FB_FUNCMODE_FBCALL, _
112  NULL, FB_RTL_OPT_NOQB, _
113  0 _
114  ), _
115 /' function fb_ErrorSetModName( byval mod_name as zstring ptr ) as zstring ptr '/ _
116  ( _
117  @FB_RTL_ERRORSETMODNAME, NULL, _
118  typeAddrOf( FB_DATATYPE_CHAR ), FB_FUNCMODE_FBCALL, _
119  NULL, FB_RTL_OPT_NONE, _
120  1, _
121  { _
122  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ) _
123  } _
124  ), _
125 /' function fb_ErrorSetFuncName( byval fun_name as zstring ptr ) as zstring ptr '/ _
126  ( _
127  @FB_RTL_ERRORSETFUNCNAME, NULL, _
128  typeAddrOf( FB_DATATYPE_CHAR ), FB_FUNCMODE_FBCALL, _
129  NULL, FB_RTL_OPT_NONE, _
130  1, _
131  { _
132  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ) _
133  } _
134  ), _
135 /' sub fb_Assert overload _
136  ( _
137  byval filename as zstring ptr, _
138  byval linenum as long, _
139  byval funcname as zstring ptr, _
140  byval expression as zstring ptr _
141  ) '/ _
142  ( _
143  @"fb_Assert", NULL, _
144  FB_DATATYPE_VOID, FB_FUNCMODE_FBCALL, _
145  NULL, FB_RTL_OPT_OVER, _
146  4, _
147  { _
148  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
149  ( FB_DATATYPE_INTEGER,FB_PARAMMODE_BYVAL, FALSE ), _
150  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
151  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ) _
152  } _
153  ), _
154 /' sub fb_Assert overload alias "fb_AssertW" _
155  ( _
156  byval filename as zstring ptr, _
157  byval linenum as long, _
158  byval funcname as zstring ptr, _
159  byval expression as wstring ptr _
160  ) '/ _
161  ( _
162  @"fb_Assert", @"fb_AssertW", _
163  FB_DATATYPE_VOID, FB_FUNCMODE_FBCALL, _
164  NULL, FB_RTL_OPT_OVER, _
165  4, _
166  { _
167  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
168  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
169  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ), _
170  ( typeAddrOf( FB_DATATYPE_WCHAR ),FB_PARAMMODE_BYVAL, FALSE ) _
171  } _
172  ), _
173 /' sub fb_AssertWarn overload _
174  ( _
175  byval filename as zstring ptr, _
176  byval linenum as long, _
177  byval funcname as zstring ptr, _
178  byval expression as zstring ptr _
179  ) '/ _
180  ( _
181  @"fb_AssertWarn", NULL, _
182  FB_DATATYPE_VOID, FB_FUNCMODE_FBCALL, _
183  NULL, FB_RTL_OPT_OVER, _
184  4, _
185  { _
186  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ), _
187  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
188  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ), _
189  ( typeAddrOf( FB_DATATYPE_CHAR ),FB_PARAMMODE_BYVAL, FALSE ) _
190  } _
191  ), _
192 /' sub fb_AssertWarn overload alias "fb_AssertWarnW" _
193  ( _
194  byval fname as zstring ptr, _
195  byval linenum as long, _
196  byval funcname as zstring ptr, _
197  byval expression as wstring ptr _
198  ) '/ _
199  ( _
200  @"fb_AssertWarn", @"fb_AssertWarnW", _
201  FB_DATATYPE_VOID, FB_FUNCMODE_FBCALL, _
202  NULL, FB_RTL_OPT_OVER, _
203  4, _
204  { _
205  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
206  ( FB_DATATYPE_LONG, FB_PARAMMODE_BYVAL, FALSE ), _
207  ( typeAddrOf( FB_DATATYPE_CHAR ), FB_PARAMMODE_BYVAL, FALSE ), _
208  ( typeAddrOf( FB_DATATYPE_WCHAR ), FB_PARAMMODE_BYVAL, FALSE ) _
209  } _
210  ), _
211 /' EOL '/ _
212  ( _
213  NULL _
214  ) _
215  }
216 
217 '':::::
219 
221 
222 end sub
223 
224 '':::::
226 
227  '' procs will be deleted when symbEnd is called
228 
229 end sub
230 
231 function hErrorThrow _
232  ( _
233  byval reslabel as FBSYMBOL ptr, _
234  byval nxtlabel as FBSYMBOL ptr _
235  ) as ASTNODE ptr
236 
237  dim as ASTNODE ptr proc = any, param = any
238 
239  '' fb_ErrorThrow( linenum, module, reslabel, resnxtlabel )
240  proc = astNewCALL( PROCLOOKUP( ERRORTHROW ) )
241 
242  '' linenum
243  astNewARG( proc, astNewCONSTi( lexLineNum() ) )
244 
245  '' module
246  astNewARG( proc, astNewCONSTstr( env.inf.name ) )
247 
248  '' reslabel
249  if( reslabel ) then
250  param = astNewADDROF( astNewVAR( reslabel ) )
251  else
252  param = astNewCONSTi( NULL, FB_DATATYPE_UINT )
253  end if
254  astNewARG( proc, param )
255 
256  '' resnxtlabel
257  if( env.clopt.resumeerr ) then
258  param = astNewADDROF( astNewVAR( nxtlabel ) )
259  else
260  param = astNewCONSTi( NULL, FB_DATATYPE_UINT )
261  end if
262  astNewARG( proc, param )
263 
264  '' All the astNewARG()'s should succeed, they're hard-coded, not
265  '' supplied by the input code
266  assert( proc->call.args = 4 )
267 
268  function = proc
269 end function
270 
271 '' Note: The rtl error checking code needs to be LINKed with the statement it
272 '' checks, in order to ensure the resulting single astAdd() will clean up any
273 '' temp vars from the statement after the whole rtl error checking code,
274 '' not in the middle of it, where it'd be either too early (during the astAdd()
275 '' for the reslabel, that'd be before the statement even was executed), or
276 '' just on one code path of the IF (if it's the astAdd() for the IF check).
277 '' (astBuildBranch() could be used to fix the 2nd issue, but that still leaves
278 '' the 1st)
279 function rtlErrorCheck( byval expr as ASTNODE ptr ) as ASTNODE ptr
280  dim as FBSYMBOL ptr nxtlabel = any, reslabel = any
281  dim as ASTNODE ptr t = NULL
282 
283  if( env.clopt.resumeerr ) then
284  reslabel = symbAddLabel( NULL )
285  t = astNewLINK( t, astNewLABEL( reslabel ) )
286  else
287  reslabel = NULL
288  end if
289 
290  if( env.clopt.errorcheck ) then
291  '' if expr = 0 then
292  nxtlabel = symbAddLabel( NULL )
293  t = astNewLINK( t, astNewBOP( AST_OP_EQ, expr, astNewCONSTi( 0 ), nxtlabel, AST_OPOPT_NONE ) )
294 
295  '' fb_ErrorThrow()
296  t = astNewLINK( t, astNewBRANCH( AST_OP_JUMPPTR, NULL, hErrorThrow( reslabel, nxtlabel ) ) )
297 
298  '' end if
299  t = astNewLINK( t, astNewLABEL( nxtlabel ) )
300  else
301  t = astNewLINK( t, expr )
302  end if
303 
304  function = t
305 end function
306 
307 sub rtlErrorThrow _
308  ( _
309  byval errexpr as ASTNODE ptr, _
310  byval linenum as integer, _
311  byval module as zstring ptr _
312  )
313 
314  dim as ASTNODE ptr proc = any, param = any
315  dim as FBSYMBOL ptr nxtlabel = any, reslabel = any
316 
317  ''
318  proc = astNewCALL( PROCLOOKUP( ERRORTHROWEX ) )
319 
320  ''
321  reslabel = symbAddLabel( NULL )
322  astAdd( astNewLABEL( reslabel ) )
323 
324  nxtlabel = symbAddLabel( NULL )
325 
326  '' fb_ErrorThrowEx( errnum, linenum, module, reslabel, resnxtlabel );
327 
328  '' errnum
329  if( astNewARG( proc, errexpr ) = NULL ) then
330  exit sub
331  end if
332 
333  '' linenum
334  if( astNewARG( proc, astNewCONSTi( linenum ) ) = NULL ) then
335  exit sub
336  end if
337 
338  '' module
339  if( astNewARG( proc, astNewCONSTstr( module ) ) = NULL ) then
340  exit sub
341  end if
342 
343  '' reslabel
344  if( env.clopt.resumeerr ) then
345  param = astNewADDROF( astNewVAR( reslabel ) )
346  else
347  param = astNewCONSTi( NULL, FB_DATATYPE_UINT )
348  end if
349  if( astNewARG( proc, param ) = NULL ) then
350  exit sub
351  end if
352 
353  '' resnxtlabel
354  if( env.clopt.resumeerr ) then
355  param = astNewADDROF( astNewVAR( nxtlabel ) )
356  else
357  param = astNewCONSTi( NULL, FB_DATATYPE_UINT )
358  end if
359  if( astNewARG( proc, param ) = NULL ) then
360  exit sub
361  end if
362 
363  '' dst
364  astAdd( astNewBRANCH( AST_OP_JUMPPTR, NULL, proc ) )
365 
366  astAdd( astNewLABEL( nxtlabel ) )
367 end sub
368 
369 '':::::
370 sub rtlErrorSetHandler _
371  ( _
372  byval newhandler as ASTNODE ptr, _
373  byval savecurrent as integer _
374  )
375 
376  dim as ASTNODE ptr proc = any, expr = any
377 
378  ''
379  proc = astNewCALL( PROCLOOKUP( ERRORSETHANDLER ) )
380 
381  '' byval newhandler as uint
382  if( astNewARG( proc, newhandler ) = NULL ) then
383  exit sub
384  end if
385 
386  ''
387  expr = NULL
388  if( savecurrent ) then
389  if( fbIsModLevel( ) = FALSE ) then
390  with parser.currproc->proc.ext->err
391  if( .lasthnd = NULL ) then
392  .lasthnd = symbAddTempVar( typeAddrOf( FB_DATATYPE_VOID ) )
393  expr = astNewVAR( .lasthnd )
394  astAdd( astNewASSIGN( expr, proc ) )
395  end if
396  end with
397  end if
398  end if
399 
400  if( expr = NULL ) then
401  astAdd( proc )
402  end if
403 
404 end sub
405 
406 '':::::
407 function rtlErrorGetNum _
408  ( _
409  _
410  ) as ASTNODE ptr
411 
412  ''
413  function = astNewCALL( PROCLOOKUP( ERRORGETNUM ) )
414 
415 end function
416 
417 '':::::
418 sub rtlErrorSetNum _
419  ( _
420  byval errexpr as ASTNODE ptr _
421  )
422 
423  dim as ASTNODE ptr proc = any
424 
425  ''
426  proc = astNewCALL( PROCLOOKUP( ERRORSETNUM ) )
427 
428  '' byval errnum as integer
429  if( astNewARG( proc, errexpr ) = NULL ) then
430  exit sub
431  end if
432 
433  ''
434  astAdd( proc )
435 
436 end sub
437 
438 sub rtlErrorResume( byval isnext as integer )
439  dim as ASTNODE ptr proc = any
440  dim as FBSYMBOL ptr f = any
441 
442  if( isnext = FALSE ) then
443  f = PROCLOOKUP( ERRORRESUME )
444  else
445  f = PROCLOOKUP( ERRORRESUMENEXT )
446  end if
447 
448  proc = astNewCALL( f )
449 
450  astAdd( astNewBRANCH( AST_OP_JUMPPTR, NULL, proc ) )
451 end sub
452 
453 '':::::
454 function rtlErrorSetModName _
455  ( _
456  byval sym as FBSYMBOL ptr, _
457  byval modname as ASTNODE ptr _
458  ) as ASTNODE ptr
459 
460  dim as ASTNODE ptr proc = any, expr = any
461 
462  proc = astNewCALL( PROCLOOKUP( ERRORSETMODNAME ) )
463 
464  '' byval module as zstring ptr
465  if( astNewARG( proc, modname ) = NULL ) then
466  return NULL
467  end if
468 
469  if( sym <> NULL ) then
470  with sym->proc.ext->err
471  .lastmod = symbAddTempVar( typeAddrOf( FB_DATATYPE_CHAR ) )
472  expr = astNewVAR( .lastmod )
473  function = astNewASSIGN( expr, proc )
474  end with
475  else
476  function = proc
477  end if
478 
479 end function
480 
481 '':::::
482 function rtlErrorSetFuncName _
483  ( _
484  byval sym as FBSYMBOL ptr, _
485  byval funcname as ASTNODE ptr _
486  ) as ASTNODE ptr
487 
488  dim as ASTNODE ptr proc = any, expr = any
489 
490  proc = astNewCALL( PROCLOOKUP( ERRORSETFUNCNAME ) )
491 
492  '' byval function as zstring ptr
493  if( astNewARG( proc, funcname ) = NULL ) then
494  return NULL
495  end if
496 
497  if( sym <> NULL ) then
498  with sym->proc.ext->err
499  .lastfun = symbAddTempVar( typeAddrOf( FB_DATATYPE_CHAR ) )
500  expr = astNewVAR( .lastfun )
501  function = astNewASSIGN( expr, proc )
502  end with
503  else
504  function = proc
505  end if
506 
507 end function
508