Ruby  1.9.3p429(2013-05-15revision40747)
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
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
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();
47  return proc;
48 }
49 
50 struct end_proc_data {
51  void (*func) ();
53  int safe;
55 };
56 
58 
59 void
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
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 void
98 {
99  struct end_proc_data *volatile link;
100  int status;
101  volatile int safe = rb_safe_level();
102  rb_thread_t *th = GET_THREAD();
103  VALUE errinfo = th->errinfo;
104 
105  while (ephemeral_end_procs) {
106  link = ephemeral_end_procs;
107  ephemeral_end_procs = link->next;
108 
109  PUSH_TAG();
110  if ((status = EXEC_TAG()) == 0) {
112  (*link->func) (link->data);
113  }
114  POP_TAG();
115  if (status) {
116  error_handle(status);
117  if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
118  }
119  xfree(link);
120  }
121 
122  while (end_procs) {
123  link = end_procs;
124  end_procs = link->next;
125 
126  PUSH_TAG();
127  if ((status = EXEC_TAG()) == 0) {
129  (*link->func) (link->data);
130  }
131  POP_TAG();
132  if (status) {
133  error_handle(status);
134  if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
135  }
136  xfree(link);
137  }
139  th->errinfo = errinfo;
140 }
141 
142 void
144 {
146 }
147