Ruby
2.1.3p242(2014-09-19revision47630)
Main Page
Modules
Data Structures
Files
File List
Globals
eval_jump.c
Go to the documentation of this file.
1
/* -*-c-*- */
2
/*
3
* from eval.c
4
*/
5
6
#include "
eval_intern.h
"
7
8
/* exit */
9
10
void
11
rb_call_end_proc
(
VALUE
data)
12
{
13
rb_proc_call
(data,
rb_ary_new
());
14
}
15
16
/*
17
* call-seq:
18
* at_exit { block } -> proc
19
*
20
* Converts _block_ to a +Proc+ object (and therefore
21
* binds it at the point of call) and registers it for execution when
22
* the program exits. If multiple handlers are registered, they are
23
* executed in reverse order of registration.
24
*
25
* def do_at_exit(str1)
26
* at_exit { print str1 }
27
* end
28
* at_exit { puts "cruel world" }
29
* do_at_exit("goodbye ")
30
* exit
31
*
32
* <em>produces:</em>
33
*
34
* goodbye cruel world
35
*/
36
37
static
VALUE
38
rb_f_at_exit
(
void
)
39
{
40
VALUE
proc;
41
42
if
(!
rb_block_given_p
()) {
43
rb_raise
(
rb_eArgError
,
"called without a block"
);
44
}
45
proc =
rb_block_proc
();
46
rb_set_end_proc
(
rb_call_end_proc
, proc);
47
return
proc;
48
}
49
50
struct
end_proc_data
{
51
void (*
func
) ();
52
VALUE
data
;
53
int
safe
;
54
struct
end_proc_data
*
next
;
55
};
56
57
static
struct
end_proc_data
*
end_procs
, *
ephemeral_end_procs
;
58
59
void
60
rb_set_end_proc
(
void
(*
func
)(
VALUE
),
VALUE
data
)
61
{
62
struct
end_proc_data
*
link
=
ALLOC
(
struct
end_proc_data
);
63
struct
end_proc_data
**
list
;
64
rb_thread_t
*th =
GET_THREAD
();
65
66
if
(th->
top_wrapper
) {
67
list = &
ephemeral_end_procs
;
68
}
69
else
{
70
list = &
end_procs
;
71
}
72
link->
next
= *
list
;
73
link->
func
=
func
;
74
link->
data
=
data
;
75
link->
safe
=
rb_safe_level
();
76
*list =
link
;
77
}
78
79
void
80
rb_mark_end_proc
(
void
)
81
{
82
struct
end_proc_data
*
link
;
83
84
link =
end_procs
;
85
while
(link) {
86
rb_gc_mark
(link->
data
);
87
link = link->
next
;
88
}
89
link =
ephemeral_end_procs
;
90
while
(link) {
91
rb_gc_mark
(link->
data
);
92
link = link->
next
;
93
}
94
}
95
96
static
void
97
exec_end_procs_chain
(
struct
end_proc_data
*
volatile
*procs)
98
{
99
struct
end_proc_data
volatile endproc;
100
struct
end_proc_data
*
link
;
101
102
while
((link = *procs) != 0) {
103
*procs = link->
next
;
104
endproc = *
link
;
105
xfree
(link);
106
rb_set_safe_level_force
(endproc.
safe
);
107
(*endproc.
func
) (endproc.
data
);
108
}
109
}
110
111
void
112
rb_exec_end_proc
(
void
)
113
{
114
int
status;
115
volatile
int
safe
=
rb_safe_level
();
116
rb_thread_t
*th =
GET_THREAD
();
117
volatile
VALUE
errinfo = th->
errinfo
;
118
119
PUSH_TAG
();
120
if
((status =
EXEC_TAG
()) == 0) {
121
again:
122
exec_end_procs_chain
(&ephemeral_end_procs);
123
exec_end_procs_chain
(&end_procs);
124
}
125
else
{
126
TH_TMPPOP_TAG
();
127
error_handle
(status);
128
if
(!
NIL_P
(th->
errinfo
)) errinfo = th->
errinfo
;
129
TH_REPUSH_TAG
();
130
goto
again;
131
}
132
POP_TAG
();
133
134
rb_set_safe_level_force
(safe);
135
th->
errinfo
= errinfo;
136
}
137
138
void
139
Init_jump
(
void
)
140
{
141
rb_define_global_function
(
"at_exit"
,
rb_f_at_exit
, 0);
142
}
143
Generated on Mon Sep 22 2014 11:05:20 for Ruby by
1.8.2