readapt 0.3.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/CHANGELOG.md +4 -0
- data/ext/readapt/breakpoints.c +88 -0
- data/ext/readapt/breakpoints.h +12 -0
- data/ext/readapt/hash_table.c +216 -0
- data/ext/readapt/hash_table.h +32 -0
- data/ext/readapt/monitor.c +55 -92
- data/ext/readapt/monitor.h +5 -0
- data/ext/readapt/normalize.c +1 -0
- data/ext/readapt/normalize.h +5 -0
- data/ext/readapt/readapt.c +2 -0
- data/ext/readapt/threads.h +5 -2
- data/lib/readapt.rb +1 -3
- data/lib/readapt/debugger.rb +1 -7
- data/lib/readapt/message/set_breakpoints.rb +7 -12
- data/lib/readapt/monitor.rb +0 -16
- data/lib/readapt/version.rb +1 -1
- metadata +6 -4
- data/lib/readapt/breakpoint.rb +0 -16
- data/lib/readapt/breakpoints.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e935059da5afc7fe4f6a68e6574ad096dcf90c2b166b81f3c0e50260e3d740ba
|
4
|
+
data.tar.gz: 26f8dce0349345c4f0fa5953f179e833c8848e5cf90f57632661f97603967d4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 979309cb99c3e4eb81768965b2a564ae14dd057f424383b28ae4e9f4a38dded3a2afc135aaca70d04207e470fd241c195ed207ae4712e98e6efbf19ae79ec6a2
|
7
|
+
data.tar.gz: a22d57be02bb01fb3535cb7c6c3047dcb33ec6a132ead776dbea44022924cfe026de4e99eb28632e6690a3a0e920f78d2131f2a7f5dac70ecb6dda939b79e4fb
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,88 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "hash_table.h"
|
3
|
+
|
4
|
+
static VALUE m_Breakpoints;
|
5
|
+
ht_hash_table *ht;
|
6
|
+
|
7
|
+
void breakpoints_set(char *file, long *lines)
|
8
|
+
{
|
9
|
+
|
10
|
+
}
|
11
|
+
|
12
|
+
static VALUE breakpoints_set_s(VALUE self, VALUE file, VALUE lines)
|
13
|
+
{
|
14
|
+
long length = NUM2LONG(rb_funcall(lines, rb_intern("length"), 0));
|
15
|
+
long *ll;
|
16
|
+
long i;
|
17
|
+
|
18
|
+
ll = malloc(sizeof(long) * length);
|
19
|
+
for (i = 0; i < length; i++)
|
20
|
+
{
|
21
|
+
ll[i] = NUM2LONG(rb_ary_entry(lines, i));
|
22
|
+
}
|
23
|
+
ht_insert(ht, StringValueCStr(file), ll, length);
|
24
|
+
free(ll);
|
25
|
+
return Qnil;
|
26
|
+
}
|
27
|
+
|
28
|
+
void breakpoints_delete(char *file)
|
29
|
+
{
|
30
|
+
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE breakpoints_delete_s(VALUE self, VALUE file)
|
34
|
+
{
|
35
|
+
return Qnil;
|
36
|
+
}
|
37
|
+
|
38
|
+
int breakpoints_match(char *file, long line)
|
39
|
+
{
|
40
|
+
ht_long_array *lines;
|
41
|
+
long i;
|
42
|
+
|
43
|
+
lines = ht_search(ht, file);
|
44
|
+
if (lines != NULL)
|
45
|
+
{
|
46
|
+
for (i = 0; i < lines->size; i++)
|
47
|
+
{
|
48
|
+
if (lines->items[i] == line)
|
49
|
+
{
|
50
|
+
return 1;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
return 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
// int breakpoints_match(char *file, long line)
|
58
|
+
// {
|
59
|
+
// return breakpoints_match_id(rb_intern(file), line);
|
60
|
+
// }
|
61
|
+
|
62
|
+
static VALUE breakpoints_match_s(VALUE self, VALUE file, VALUE line)
|
63
|
+
{
|
64
|
+
return breakpoints_match(StringValueCStr(file), NUM2LONG(line)) == 0 ? Qfalse : Qtrue;
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE breakpoints_clear_s(VALUE self)
|
68
|
+
{
|
69
|
+
ht_del_hash_table(ht);
|
70
|
+
ht = ht_new();
|
71
|
+
return Qnil;
|
72
|
+
}
|
73
|
+
|
74
|
+
long breakpoints_files()
|
75
|
+
{
|
76
|
+
return ht->size;
|
77
|
+
}
|
78
|
+
|
79
|
+
void initialize_breakpoints(VALUE m_Readapt)
|
80
|
+
{
|
81
|
+
m_Breakpoints = rb_define_module_under(m_Readapt, "Breakpoints");
|
82
|
+
rb_define_singleton_method(m_Breakpoints, "set", breakpoints_set_s, 2);
|
83
|
+
rb_define_singleton_method(m_Breakpoints, "delete", breakpoints_delete_s, 1);
|
84
|
+
rb_define_singleton_method(m_Breakpoints, "match", breakpoints_match_s, 2);
|
85
|
+
rb_define_singleton_method(m_Breakpoints, "clear", breakpoints_clear_s, 0);
|
86
|
+
|
87
|
+
ht = ht_new(); // TODO Need to free?
|
88
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#ifndef BREAKPOINTS_H_
|
2
|
+
#define BREAKPOINTS_H_
|
3
|
+
|
4
|
+
void initialize_breakpoints(VALUE m_Readapt);
|
5
|
+
|
6
|
+
void breakpoints_set(char *file, long *lines);
|
7
|
+
void breakpoints_delete(char *file);
|
8
|
+
int breakpoints_match(char *file, long line);
|
9
|
+
// int breakpoints_match_id(ht_key file, long line);
|
10
|
+
long breakpoints_files();
|
11
|
+
|
12
|
+
#endif
|
@@ -0,0 +1,216 @@
|
|
1
|
+
#include <math.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
|
5
|
+
#include "hash_table.h"
|
6
|
+
#include "ruby.h"
|
7
|
+
|
8
|
+
static ht_long_array *copy_array(const long *value, const long size)
|
9
|
+
{
|
10
|
+
long i;
|
11
|
+
long *items = malloc(sizeof(long) * size);
|
12
|
+
ht_long_array *result;
|
13
|
+
|
14
|
+
for (i = 0; i < size; i++)
|
15
|
+
{
|
16
|
+
items[i] = value[i];
|
17
|
+
}
|
18
|
+
result = malloc(sizeof(ht_long_array));
|
19
|
+
result->items = (size ? items : NULL);
|
20
|
+
result->size = size;
|
21
|
+
return result;
|
22
|
+
}
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Initialize a new item
|
26
|
+
*/
|
27
|
+
static ht_item *ht_new_item(char *key, const long *value, const long size)
|
28
|
+
{
|
29
|
+
ht_item *i = malloc(sizeof(ht_item));
|
30
|
+
i->key = malloc(sizeof(char) * (strlen(key) + 1));
|
31
|
+
strcpy(i->key, key);
|
32
|
+
i->value = copy_array(value, size);
|
33
|
+
return i;
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
* Delete the ht_item
|
38
|
+
*/
|
39
|
+
static void ht_del_item(ht_item *i)
|
40
|
+
{
|
41
|
+
free(i->key);
|
42
|
+
free(i->value->items);
|
43
|
+
free(i);
|
44
|
+
}
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Initialize a new empty hash table
|
48
|
+
*/
|
49
|
+
ht_hash_table *ht_new()
|
50
|
+
{
|
51
|
+
ht_hash_table *ht = malloc(sizeof(ht_hash_table));
|
52
|
+
ht->items = NULL;
|
53
|
+
ht->size = 0;
|
54
|
+
return ht;
|
55
|
+
}
|
56
|
+
|
57
|
+
/*
|
58
|
+
* Delete the hash table
|
59
|
+
*/
|
60
|
+
void ht_del_hash_table(ht_hash_table *ht)
|
61
|
+
{
|
62
|
+
int i;
|
63
|
+
ht_item *item;
|
64
|
+
|
65
|
+
// Iterate through items and delete any that are found
|
66
|
+
for (i = 0; i < ht->size; i++)
|
67
|
+
{
|
68
|
+
item = ht->items[i];
|
69
|
+
ht_del_item(item);
|
70
|
+
}
|
71
|
+
free(ht->items);
|
72
|
+
free(ht);
|
73
|
+
}
|
74
|
+
|
75
|
+
static ht_long_array *ht_search_part(ht_hash_table *ht, char *key, long cursor, long next)
|
76
|
+
{
|
77
|
+
int cmp;
|
78
|
+
|
79
|
+
if (cursor >= ht->size)
|
80
|
+
{
|
81
|
+
return NULL;
|
82
|
+
}
|
83
|
+
|
84
|
+
cmp = strcmp(ht->items[cursor]->key, key);
|
85
|
+
if (cmp == 0)
|
86
|
+
{
|
87
|
+
return ht->items[cursor]->value;
|
88
|
+
}
|
89
|
+
if (next > cursor && next < ht->size)
|
90
|
+
{
|
91
|
+
cmp = strcmp(ht->items[next]->key, key);
|
92
|
+
if (cmp == 0)
|
93
|
+
{
|
94
|
+
return ht->items[next]->value;
|
95
|
+
}
|
96
|
+
else if (cmp < 0)
|
97
|
+
{
|
98
|
+
return ht_search_part(ht, key, next + 1, next + ((ht->size - next) / 2));
|
99
|
+
}
|
100
|
+
else
|
101
|
+
{
|
102
|
+
return ht_search_part(ht, key, cursor + 1, next / 2);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
return ht_search_part(ht, key, cursor + 1, next / 2);
|
106
|
+
}
|
107
|
+
|
108
|
+
static ht_long_array *ht_search_key(ht_hash_table *ht, char *key)
|
109
|
+
{
|
110
|
+
return ht_search_part(ht, key, 0, ht->size / 2);
|
111
|
+
}
|
112
|
+
|
113
|
+
static void ht_delete_key(ht_hash_table *ht, char *key)
|
114
|
+
{
|
115
|
+
ht_long_array *found;
|
116
|
+
ht_item **tmp;
|
117
|
+
long i;
|
118
|
+
long cursor = 0;
|
119
|
+
|
120
|
+
found = ht_search_key(ht, key);
|
121
|
+
if (found)
|
122
|
+
{
|
123
|
+
tmp = malloc(sizeof(ht_item) * (ht->size - 1));
|
124
|
+
for (i = 0; i < ht->size; i++)
|
125
|
+
{
|
126
|
+
if (ht->items[i]->key == key)
|
127
|
+
{
|
128
|
+
ht_del_item(ht->items[i]);
|
129
|
+
}
|
130
|
+
else
|
131
|
+
{
|
132
|
+
tmp[cursor] = ht->items[cursor];
|
133
|
+
cursor++;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
free(ht->items);
|
137
|
+
ht->items = tmp;
|
138
|
+
ht->size--;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
static void ht_insert_key(ht_hash_table *ht, char *key, const long *value, const long size)
|
143
|
+
{
|
144
|
+
ht_item *item;
|
145
|
+
ht_item **tmp;
|
146
|
+
long i;
|
147
|
+
long cursor = 0;
|
148
|
+
int inserted = 0;
|
149
|
+
int cmp;
|
150
|
+
|
151
|
+
ht_delete_key(ht, key);
|
152
|
+
|
153
|
+
if (size == 0)
|
154
|
+
{
|
155
|
+
return;
|
156
|
+
}
|
157
|
+
|
158
|
+
item = ht_new_item(key, value, size);
|
159
|
+
tmp = malloc(sizeof(ht_item) * (ht->size + 1));
|
160
|
+
|
161
|
+
for (i = 0; i <= ht->size; i++)
|
162
|
+
{
|
163
|
+
if (!inserted)
|
164
|
+
{
|
165
|
+
if (i == ht->size)
|
166
|
+
{
|
167
|
+
tmp[i] = item;
|
168
|
+
inserted = 1;
|
169
|
+
}
|
170
|
+
else
|
171
|
+
{
|
172
|
+
cmp = strcmp(item->key, ht->items[i]->key);
|
173
|
+
if (cmp > 0)
|
174
|
+
{
|
175
|
+
tmp[i] = item;
|
176
|
+
tmp[i + 1] = ht->items[cursor];
|
177
|
+
inserted = 1;
|
178
|
+
cursor++;
|
179
|
+
i++;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
else
|
184
|
+
{
|
185
|
+
tmp[i] = ht->items[cursor];
|
186
|
+
cursor++;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
free(ht->items);
|
190
|
+
ht->items = tmp;
|
191
|
+
ht->size++;
|
192
|
+
}
|
193
|
+
|
194
|
+
/*
|
195
|
+
* Add an item to the hash table
|
196
|
+
*/
|
197
|
+
void ht_insert(ht_hash_table *ht, char *key, const long *value, const long size)
|
198
|
+
{
|
199
|
+
ht_insert_key(ht, key, value, size);
|
200
|
+
}
|
201
|
+
|
202
|
+
/*
|
203
|
+
* Get the key's value or NULL if it doesn't exist
|
204
|
+
*/
|
205
|
+
ht_long_array *ht_search(ht_hash_table *ht, char *key)
|
206
|
+
{
|
207
|
+
return ht_search_key(ht, key);
|
208
|
+
}
|
209
|
+
|
210
|
+
/*
|
211
|
+
* Delete the key's item if it exists
|
212
|
+
*/
|
213
|
+
void ht_delete(ht_hash_table *ht, char *key)
|
214
|
+
{
|
215
|
+
ht_delete_key(ht, key);
|
216
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#ifndef HASH_TABLE_H_
|
2
|
+
#define HASH_TABLE_H_
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
typedef struct ht_long_array
|
7
|
+
{
|
8
|
+
long *items;
|
9
|
+
long size;
|
10
|
+
} ht_long_array;
|
11
|
+
|
12
|
+
// ht_item is an item in the hash table
|
13
|
+
typedef struct ht_item
|
14
|
+
{
|
15
|
+
char *key;
|
16
|
+
ht_long_array *value;
|
17
|
+
} ht_item;
|
18
|
+
|
19
|
+
typedef struct ht_hash_table
|
20
|
+
{
|
21
|
+
long size;
|
22
|
+
ht_item **items;
|
23
|
+
} ht_hash_table;
|
24
|
+
|
25
|
+
ht_hash_table *ht_new();
|
26
|
+
void ht_del_hash_table(ht_hash_table *ht);
|
27
|
+
|
28
|
+
void ht_insert(ht_hash_table *ht, char *key, const long *value, const long size);
|
29
|
+
ht_long_array *ht_search(ht_hash_table *ht, char *key);
|
30
|
+
void ht_delete(ht_hash_table *h, char *key);
|
31
|
+
|
32
|
+
#endif // HASH_TABLE_H_
|
data/ext/readapt/monitor.c
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "ruby/debug.h"
|
3
3
|
#include "threads.h"
|
4
4
|
#include "normalize.h"
|
5
|
+
#include "breakpoints.h"
|
5
6
|
|
6
7
|
static VALUE readapt;
|
7
8
|
static VALUE m_Monitor;
|
@@ -14,39 +15,16 @@ static VALUE tpReturn;
|
|
14
15
|
static VALUE tpThreadBegin;
|
15
16
|
static VALUE tpThreadEnd;
|
16
17
|
static VALUE debugProc;
|
17
|
-
static VALUE breakpoints;
|
18
|
-
static int knownBreakpoints;
|
19
18
|
static int firstLineEvent = 0;
|
19
|
+
static VALUE entryFile;
|
20
20
|
|
21
|
-
static
|
22
|
-
|
23
|
-
|
24
|
-
return 1;
|
25
|
-
}
|
26
|
-
return 0;
|
27
|
-
}
|
28
|
-
|
29
|
-
static int match_breakpoint(VALUE file, int line)
|
30
|
-
{
|
31
|
-
VALUE bps, b;
|
32
|
-
long len, i;
|
33
|
-
|
34
|
-
bps = rb_funcall(breakpoints, rb_intern("for"), 1, file);
|
35
|
-
len = rb_array_len(bps);
|
36
|
-
for (i = 0; i < len; i++)
|
37
|
-
{
|
38
|
-
b = rb_ary_entry(bps, i);
|
39
|
-
if (NUM2INT(rb_funcall(b, rb_intern("line"), 0)) == line)
|
40
|
-
{
|
41
|
-
return 1;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
return 0;
|
45
|
-
}
|
21
|
+
static ID id_continue;
|
22
|
+
static ID id_pause;
|
23
|
+
static ID id_entry;
|
46
24
|
|
47
25
|
static int match_step(thread_reference_t *ptr)
|
48
26
|
{
|
49
|
-
if (ptr->control ==
|
27
|
+
if (ptr->control == id_continue)
|
50
28
|
{
|
51
29
|
return 0;
|
52
30
|
}
|
@@ -66,7 +44,7 @@ static int match_step(thread_reference_t *ptr)
|
|
66
44
|
}
|
67
45
|
|
68
46
|
static ID
|
69
|
-
monitor_debug(VALUE file,
|
47
|
+
monitor_debug(VALUE file, long line, VALUE tracepoint, thread_reference_t *ptr, ID event)
|
70
48
|
{
|
71
49
|
VALUE bind, bid, snapshot, result;
|
72
50
|
|
@@ -90,8 +68,6 @@ monitor_debug(VALUE file, int line, VALUE tracepoint, thread_reference_t *ptr, I
|
|
90
68
|
ptr->cursor = ptr->depth;
|
91
69
|
ptr->control = result;
|
92
70
|
}
|
93
|
-
ptr->prev_file = file;
|
94
|
-
ptr->prev_line = line;
|
95
71
|
return result;
|
96
72
|
}
|
97
73
|
|
@@ -99,67 +75,57 @@ static void
|
|
99
75
|
process_line_event(VALUE tracepoint, void *data)
|
100
76
|
{
|
101
77
|
VALUE ref, tp_file;
|
102
|
-
|
78
|
+
long tp_line;
|
103
79
|
thread_reference_t *ptr;
|
104
80
|
rb_trace_arg_t *tp;
|
105
81
|
int threadPaused;
|
106
|
-
ID dapEvent
|
82
|
+
ID dapEvent;
|
107
83
|
|
108
84
|
ref = thread_current_reference();
|
109
85
|
if (ref != Qnil)
|
110
86
|
{
|
111
87
|
ptr = thread_reference_pointer(ref);
|
112
|
-
if (ptr->depth > 0
|
88
|
+
if (ptr->depth > 0)
|
113
89
|
{
|
114
|
-
threadPaused = (ptr->control ==
|
115
|
-
if (
|
90
|
+
threadPaused = (ptr->control == id_pause);
|
91
|
+
if (firstLineEvent && ptr->control == id_continue && breakpoints_files() == 0)
|
116
92
|
{
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
if (!firstLineEvent)
|
123
|
-
{
|
124
|
-
dapEvent = rb_intern("initialize");
|
125
|
-
}
|
126
|
-
else if (threadPaused)
|
127
|
-
{
|
128
|
-
dapEvent = rb_intern("pause");
|
129
|
-
}
|
130
|
-
else if (match_step(ptr))
|
131
|
-
{
|
132
|
-
dapEvent = rb_intern("step");
|
133
|
-
}
|
134
|
-
else if (match_breakpoint(tp_file, tp_line))
|
135
|
-
{
|
136
|
-
dapEvent = rb_intern("breakpoint");
|
137
|
-
}
|
138
|
-
else if (ptr->control == rb_intern("entry"))
|
139
|
-
{
|
140
|
-
dapEvent = rb_intern("entry");
|
141
|
-
}
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
tp = rb_tracearg_from_tracepoint(tracepoint);
|
96
|
+
tp_file = normalize_path(rb_tracearg_path(tp));
|
97
|
+
tp_line = NUM2LONG(rb_tracearg_lineno(tp));
|
142
98
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
{
|
148
|
-
firstLineEvent = 1;
|
149
|
-
ptr->control = rb_intern("entry");
|
150
|
-
process_line_event(tracepoint, data);
|
151
|
-
}
|
152
|
-
}
|
153
|
-
else
|
99
|
+
dapEvent = id_continue;
|
100
|
+
if (!firstLineEvent)
|
101
|
+
{
|
102
|
+
if (rb_str_equal(tp_file, entryFile))
|
154
103
|
{
|
155
|
-
|
156
|
-
ptr->
|
104
|
+
firstLineEvent = 1;
|
105
|
+
ptr->control = rb_intern("entry");
|
106
|
+
process_line_event(tracepoint, data);
|
157
107
|
}
|
158
108
|
}
|
159
|
-
else
|
109
|
+
else if (threadPaused)
|
110
|
+
{
|
111
|
+
dapEvent = id_pause;
|
112
|
+
}
|
113
|
+
else if (match_step(ptr))
|
114
|
+
{
|
115
|
+
dapEvent = rb_intern("step");
|
116
|
+
}
|
117
|
+
else if (breakpoints_match(StringValueCStr(tp_file), tp_line))
|
118
|
+
{
|
119
|
+
dapEvent = rb_intern("breakpoint");
|
120
|
+
}
|
121
|
+
else if (ptr->control == id_entry)
|
122
|
+
{
|
123
|
+
dapEvent = id_entry;
|
124
|
+
}
|
125
|
+
|
126
|
+
if (dapEvent != id_continue)
|
160
127
|
{
|
161
|
-
ptr
|
162
|
-
ptr->prev_line = Qnil;
|
128
|
+
monitor_debug(tp_file, tp_line, tracepoint, ptr, dapEvent);
|
163
129
|
}
|
164
130
|
}
|
165
131
|
}
|
@@ -214,7 +180,7 @@ process_thread_begin_event(VALUE tracepoint, void *data)
|
|
214
180
|
ptr = thread_reference_pointer(ref);
|
215
181
|
monitor_debug(
|
216
182
|
rb_funcall(tracepoint, rb_intern("path"), 0),
|
217
|
-
|
183
|
+
NUM2LONG(rb_funcall(tracepoint, rb_intern("lineno"), 0)),
|
218
184
|
tracepoint,
|
219
185
|
ptr,
|
220
186
|
rb_intern("thread_begin")
|
@@ -236,13 +202,13 @@ process_thread_end_event(VALUE tracepoint, void *data)
|
|
236
202
|
if (ref != Qnil)
|
237
203
|
{
|
238
204
|
ptr = thread_reference_pointer(ref);
|
239
|
-
monitor_debug(
|
205
|
+
monitor_debug(rb_funcall(tracepoint, rb_intern("path"), 0), NUM2LONG(rb_funcall(tracepoint, rb_intern("lineno"), 0)), tracepoint, ptr, rb_intern("thread_end"));
|
240
206
|
thread_delete_reference(thr);
|
241
207
|
}
|
242
208
|
}
|
243
209
|
|
244
210
|
static VALUE
|
245
|
-
monitor_enable_s(VALUE self)
|
211
|
+
monitor_enable_s(VALUE self, VALUE file)
|
246
212
|
{
|
247
213
|
VALUE previous, ref;
|
248
214
|
thread_reference_t *ptr;
|
@@ -254,7 +220,8 @@ monitor_enable_s(VALUE self)
|
|
254
220
|
rb_raise(rb_eArgError, "must be called with a block");
|
255
221
|
}
|
256
222
|
|
257
|
-
|
223
|
+
entryFile = file;
|
224
|
+
firstLineEvent = (entryFile == Qnil ? 1 : 0);
|
258
225
|
|
259
226
|
ref = thread_add_reference(rb_thread_current());
|
260
227
|
ptr = thread_reference_pointer(ref);
|
@@ -286,7 +253,7 @@ monitor_disable_s(VALUE self)
|
|
286
253
|
rb_tracepoint_disable(tpReturn);
|
287
254
|
rb_tracepoint_disable(tpThreadBegin);
|
288
255
|
rb_tracepoint_disable(tpThreadEnd);
|
289
|
-
|
256
|
+
|
290
257
|
return previous;
|
291
258
|
}
|
292
259
|
|
@@ -302,12 +269,6 @@ monitor_pause_s(VALUE self, VALUE id)
|
|
302
269
|
ptr = thread_reference_pointer(ref);
|
303
270
|
ptr->control = rb_intern("pause");
|
304
271
|
}
|
305
|
-
}
|
306
|
-
|
307
|
-
static VALUE
|
308
|
-
monitor_know_breakpoints_s(VALUE self)
|
309
|
-
{
|
310
|
-
knownBreakpoints = (rb_funcall(breakpoints, rb_intern("empty?"), 0) == Qfalse) ? 1 : 0;
|
311
272
|
return Qnil;
|
312
273
|
}
|
313
274
|
|
@@ -319,9 +280,8 @@ void initialize_monitor(VALUE m_Readapt)
|
|
319
280
|
|
320
281
|
initialize_threads();
|
321
282
|
|
322
|
-
rb_define_singleton_method(m_Monitor, "start", monitor_enable_s,
|
283
|
+
rb_define_singleton_method(m_Monitor, "start", monitor_enable_s, 1);
|
323
284
|
rb_define_singleton_method(m_Monitor, "stop", monitor_disable_s, 0);
|
324
|
-
rb_define_singleton_method(m_Monitor, "know_breakpoints", monitor_know_breakpoints_s, 0);
|
325
285
|
rb_define_singleton_method(m_Monitor, "pause", monitor_pause_s, 1);
|
326
286
|
|
327
287
|
tpLine = rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, process_line_event, NULL);
|
@@ -330,8 +290,10 @@ void initialize_monitor(VALUE m_Readapt)
|
|
330
290
|
tpThreadBegin = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_BEGIN, process_thread_begin_event, NULL);
|
331
291
|
tpThreadEnd = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_END, process_thread_end_event, NULL);
|
332
292
|
debugProc = Qnil;
|
333
|
-
|
334
|
-
|
293
|
+
|
294
|
+
id_continue = rb_intern("continue");
|
295
|
+
id_pause = rb_intern("pause");
|
296
|
+
id_entry = rb_intern("entry");
|
335
297
|
|
336
298
|
// Avoid garbage collection
|
337
299
|
rb_global_variable(&tpLine);
|
@@ -339,4 +301,5 @@ void initialize_monitor(VALUE m_Readapt)
|
|
339
301
|
rb_global_variable(&tpReturn);
|
340
302
|
rb_global_variable(&tpThreadBegin);
|
341
303
|
rb_global_variable(&tpThreadEnd);
|
304
|
+
rb_global_variable(&entryFile);
|
342
305
|
}
|
data/ext/readapt/monitor.h
CHANGED
data/ext/readapt/normalize.c
CHANGED
data/ext/readapt/normalize.h
CHANGED
data/ext/readapt/readapt.c
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "ruby/debug.h"
|
3
3
|
#include "monitor.h"
|
4
4
|
#include "normalize.h"
|
5
|
+
#include "breakpoints.h"
|
5
6
|
|
6
7
|
static VALUE m_Readapt;
|
7
8
|
|
@@ -10,5 +11,6 @@ void Init_readapt()
|
|
10
11
|
m_Readapt = rb_define_module("Readapt");
|
11
12
|
|
12
13
|
initialize_normalize(m_Readapt);
|
14
|
+
initialize_breakpoints(m_Readapt);
|
13
15
|
initialize_monitor(m_Readapt);
|
14
16
|
}
|
data/ext/readapt/threads.h
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
#ifndef THREADS_H_
|
2
|
+
#define THREADS_H_
|
3
|
+
|
1
4
|
typedef struct thread_reference_struct {
|
2
5
|
long id;
|
3
6
|
int depth;
|
4
7
|
int cursor;
|
5
|
-
VALUE prev_file;
|
6
|
-
int prev_line;
|
7
8
|
ID control;
|
8
9
|
} thread_reference_t;
|
9
10
|
|
@@ -16,3 +17,5 @@ VALUE thread_delete_reference(VALUE);
|
|
16
17
|
thread_reference_t *thread_reference_pointer(VALUE);
|
17
18
|
void thread_pause();
|
18
19
|
void thread_reset();
|
20
|
+
|
21
|
+
#endif
|
data/lib/readapt.rb
CHANGED
data/lib/readapt/debugger.rb
CHANGED
@@ -67,7 +67,7 @@ module Readapt
|
|
67
67
|
send_event('process', {
|
68
68
|
name: @file
|
69
69
|
})
|
70
|
-
Monitor.start do |snapshot|
|
70
|
+
Monitor.start @file do |snapshot|
|
71
71
|
debug snapshot
|
72
72
|
end
|
73
73
|
yield if block_given?
|
@@ -123,12 +123,6 @@ module Readapt
|
|
123
123
|
threadId: snapshot.thread_id
|
124
124
|
})
|
125
125
|
snapshot.control = :continue
|
126
|
-
elsif snapshot.event == :initialize
|
127
|
-
if snapshot.file != @file
|
128
|
-
snapshot.control = :wait
|
129
|
-
else
|
130
|
-
snapshot.control = :ready
|
131
|
-
end
|
132
126
|
elsif snapshot.event == :entry
|
133
127
|
snapshot.control = :continue
|
134
128
|
else
|
@@ -5,21 +5,16 @@ module Readapt
|
|
5
5
|
class SetBreakpoints < Base
|
6
6
|
def run
|
7
7
|
path = Readapt.normalize_path(arguments['source']['path'])
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Breakpoint.new(path, l, true)
|
12
|
-
end
|
13
|
-
Monitor.breakpoints.concat result
|
14
|
-
set_body({
|
15
|
-
breakpoints: result.map { |bp|
|
8
|
+
Breakpoints.set(path, arguments['lines'])
|
9
|
+
set_body(
|
10
|
+
breakpoints: arguments['lines'].map do |l|
|
16
11
|
{
|
17
|
-
verified:
|
12
|
+
verified: true, # @todo Verify
|
18
13
|
source: arguments['source'],
|
19
|
-
line:
|
14
|
+
line: l
|
20
15
|
}
|
21
|
-
|
22
|
-
|
16
|
+
end
|
17
|
+
)
|
23
18
|
end
|
24
19
|
end
|
25
20
|
end
|
data/lib/readapt/monitor.rb
CHANGED
@@ -11,21 +11,5 @@ module Readapt
|
|
11
11
|
# Disable tracepoints.
|
12
12
|
# @return [Boolean]
|
13
13
|
module Monitor
|
14
|
-
@@breakpoints = Breakpoints.new
|
15
|
-
|
16
|
-
# @return [Breakpoints]
|
17
|
-
def self.breakpoints
|
18
|
-
@@breakpoints
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.set_breakpoints bps
|
22
|
-
@@breakpoints = bps
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.update
|
26
|
-
know_breakpoints
|
27
|
-
end
|
28
|
-
|
29
|
-
@@breakpoints.add_observer self
|
30
14
|
end
|
31
15
|
end
|
data/lib/readapt/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: readapt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -116,7 +116,11 @@ files:
|
|
116
116
|
- bin/console
|
117
117
|
- bin/setup
|
118
118
|
- exe/readapt
|
119
|
+
- ext/readapt/breakpoints.c
|
120
|
+
- ext/readapt/breakpoints.h
|
119
121
|
- ext/readapt/extconf.rb
|
122
|
+
- ext/readapt/hash_table.c
|
123
|
+
- ext/readapt/hash_table.h
|
120
124
|
- ext/readapt/monitor.c
|
121
125
|
- ext/readapt/monitor.h
|
122
126
|
- ext/readapt/normalize.c
|
@@ -126,8 +130,6 @@ files:
|
|
126
130
|
- ext/readapt/threads.h
|
127
131
|
- lib/readapt.rb
|
128
132
|
- lib/readapt/adapter.rb
|
129
|
-
- lib/readapt/breakpoint.rb
|
130
|
-
- lib/readapt/breakpoints.rb
|
131
133
|
- lib/readapt/debugger.rb
|
132
134
|
- lib/readapt/finder.rb
|
133
135
|
- lib/readapt/frame.rb
|
data/lib/readapt/breakpoint.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Readapt
|
4
|
-
class Breakpoint < Location
|
5
|
-
attr_reader :verified
|
6
|
-
|
7
|
-
def initialize file, line, verified = true
|
8
|
-
super(file, line)
|
9
|
-
@verified = verified
|
10
|
-
end
|
11
|
-
|
12
|
-
def enabled?
|
13
|
-
@verified
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/readapt/breakpoints.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'observer'
|
2
|
-
|
3
|
-
module Readapt
|
4
|
-
class Breakpoints
|
5
|
-
include Observable
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@sources = {}
|
9
|
-
@concatting = false
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [Array<String>]
|
13
|
-
def sources
|
14
|
-
@sources.keys
|
15
|
-
end
|
16
|
-
|
17
|
-
# @param breakpoint [Breakpoint]
|
18
|
-
# @return [void]
|
19
|
-
def add breakpoint
|
20
|
-
@sources[breakpoint.file] ||= []
|
21
|
-
@sources[breakpoint.file].push breakpoint
|
22
|
-
changed
|
23
|
-
notify_observers unless @concatting
|
24
|
-
end
|
25
|
-
|
26
|
-
# @param breakpoints [Array<Breakpoint>]
|
27
|
-
# @return [void]
|
28
|
-
def concat breakpoints
|
29
|
-
@concatting = true
|
30
|
-
breakpoints.each { |bp| add bp }
|
31
|
-
@concatting = false
|
32
|
-
notify_observers
|
33
|
-
end
|
34
|
-
|
35
|
-
# @param file [String]
|
36
|
-
# @return [void]
|
37
|
-
def clear file
|
38
|
-
@sources.delete file
|
39
|
-
changed
|
40
|
-
notify_observers
|
41
|
-
end
|
42
|
-
|
43
|
-
# @param file [String]
|
44
|
-
# @return [Array<Breakpoint>]
|
45
|
-
def for file
|
46
|
-
@sources[file] || []
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [Array<Breakpoint>]
|
50
|
-
def all
|
51
|
-
@sources.values.flatten
|
52
|
-
end
|
53
|
-
|
54
|
-
def empty?
|
55
|
-
@sources.empty?
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|