source: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 10.8 KB
Line 
1/*
2** cmdbreak.c
3**
4*/
5
6#include <ctype.h>
7#include <string.h>
8#include <mruby.h>
9#include <mruby/dump.h>
10#include <mruby/debug.h>
11#include <mruby/string.h>
12#include "mrdb.h"
13#include "mrdberror.h"
14#include "apibreak.h"
15
16#define BREAK_SET_MSG_LINE "Breakpoint %d: file %s, line %d.\n"
17#define BREAK_SET_MSG_METHOD "Breakpoint %d: method %s.\n"
18#define BREAK_SET_MSG_CLASS_METHOD "Breakpoint %d: class %s, method %s.\n"
19#define BREAK_INFO_MSG_HEADER "Num Type Enb What"
20#define BREAK_INFO_MSG_LINEBREAK "%-8ubreakpoint %s at %s:%u\n"
21#define BREAK_INFO_MSG_METHODBREAK "%-8ubreakpoint %s in %s:%s\n"
22#define BREAK_INFO_MSG_METHODBREAK_NOCLASS "%-8ubreakpoint %s in %s\n"
23#define BREAK_INFO_MSG_ENABLE "y"
24#define BREAK_INFO_MSG_DISABLE "n"
25
26#define BREAK_ERR_MSG_INVALIDARG "Internal error."
27#define BREAK_ERR_MSG_BLANK "Try \'help break\' for more information."
28#define BREAK_ERR_MSG_RANGEOVER "The line number range is from 1 to 65535."
29#define BREAK_ERR_MSG_NUMOVER "Exceeded the setable number of breakpoint."
30#define BREAK_ERR_MSG_NOOVER "Breakno is over the available number.Please 'quit' and restart mrdb."
31#define BREAK_ERR_MSG_INVALIDSTR "String \'%s\' is invalid.\n"
32#define BREAK_ERR_MSG_INVALIDLINENO "Line %d in file \"%s\" is unavailable.\n"
33#define BREAK_ERR_MSG_INVALIDCLASS "Class name \'%s\' is invalid.\n"
34#define BREAK_ERR_MSG_INVALIDMETHOD "Method name \'%s\' is invalid.\n"
35#define BREAK_ERR_MSG_INVALIDFILE "Source file named \"%s\" is unavailable.\n"
36#define BREAK_ERR_MSG_INVALIDBPNO "warning: bad breakpoint number at or near '%s'\n"
37#define BREAK_ERR_MSG_INVALIDBPNO_INFO "Args must be numbers variables."
38#define BREAK_ERR_MSG_NOBPNO "No breakpoint number %d.\n"
39#define BREAK_ERR_MSG_NOBPNO_INFO "No breakpoint matching '%d'\n"
40#define BREAK_ERR_MSG_NOBPNO_INFOALL "No breakpoints."
41
42#define LINENO_MAX_DIGIT 6
43#define BPNO_LETTER_NUM 9
44
45typedef int32_t (*all_command_func)(mrb_state *, mrb_debug_context *);
46typedef int32_t (*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t);
47
48static void
49print_api_common_error(int32_t error)
50{
51 switch(error) {
52 case MRB_DEBUG_INVALID_ARGUMENT:
53 puts(BREAK_ERR_MSG_INVALIDARG);
54 break;
55 default:
56 break;
57 }
58}
59
60#undef STRTOUL
61#define STRTOUL(ul,s) { \
62 int i; \
63 ul = 0; \
64 for(i=0; ISDIGIT(s[i]); i++) ul = 10*ul + (s[i] -'0'); \
65}
66
67static int32_t
68parse_breakpoint_no(char* args)
69{
70 char* ps = args;
71 uint32_t l;
72
73 if ((*ps == '0')||(strlen(ps) >= BPNO_LETTER_NUM)) {
74 return 0;
75 }
76
77 while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
78 if (!ISDIGIT(*ps)) {
79 return 0;
80 }
81 ps++;
82 }
83
84 STRTOUL(l, args);
85 return l;
86}
87
88static mrb_bool
89exe_set_command_all(mrb_state *mrb, mrdb_state *mrdb, all_command_func func)
90{
91 int32_t ret = MRB_DEBUG_OK;
92
93 if (mrdb->wcnt == 1) {
94 ret = func(mrb, mrdb->dbg);
95 print_api_common_error(ret);
96 return TRUE;
97 }
98 return FALSE;
99}
100
101static void
102exe_set_command_select(mrb_state *mrb, mrdb_state *mrdb, select_command_func func)
103{
104 char* ps;
105 int32_t ret = MRB_DEBUG_OK;
106 int32_t bpno = 0;
107 int32_t i;
108
109 for(i=1; i<mrdb->wcnt; i++) {
110 ps = mrdb->words[i];
111 bpno = parse_breakpoint_no(ps);
112 if (bpno == 0) {
113 printf(BREAK_ERR_MSG_INVALIDBPNO, ps);
114 break;
115 }
116 ret = func(mrb, mrdb->dbg, (uint32_t)bpno);
117 if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
118 printf(BREAK_ERR_MSG_NOBPNO, bpno);
119 }
120 else if (ret != MRB_DEBUG_OK) {
121 print_api_common_error(ret);
122 }
123 }
124}
125
126mrb_debug_bptype
127check_bptype(char* args)
128{
129 char* ps = args;
130
131 if (ISBLANK(*ps)||ISCNTRL(*ps)) {
132 puts(BREAK_ERR_MSG_BLANK);
133 return MRB_DEBUG_BPTYPE_NONE;
134 }
135
136 if (!ISDIGIT(*ps)) {
137 return MRB_DEBUG_BPTYPE_METHOD;
138 }
139
140 while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
141 if (!ISDIGIT(*ps)) {
142 printf(BREAK_ERR_MSG_INVALIDSTR, args);
143 return MRB_DEBUG_BPTYPE_NONE;
144 }
145 ps++;
146 }
147
148 if ((*args == '0')||(strlen(args) >= LINENO_MAX_DIGIT)) {
149 puts(BREAK_ERR_MSG_RANGEOVER);
150 return MRB_DEBUG_BPTYPE_NONE;
151 }
152
153 return MRB_DEBUG_BPTYPE_LINE;
154}
155
156static void
157print_breakpoint(mrb_debug_breakpoint *bp)
158{
159 const char* enable_letter[] = {BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE};
160
161 if (bp->type == MRB_DEBUG_BPTYPE_LINE) {
162 printf(BREAK_INFO_MSG_LINEBREAK,
163 bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno);
164 }
165 else {
166 if (bp->point.methodpoint.class_name == NULL) {
167 printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS,
168 bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name);
169 }
170 else {
171 printf(BREAK_INFO_MSG_METHODBREAK,
172 bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name);
173 }
174 }
175}
176
177static void
178info_break_all(mrb_state *mrb, mrdb_state *mrdb)
179{
180 int32_t bpnum = 0;
181 int32_t i = 0;
182 int32_t ret = MRB_DEBUG_OK;
183 mrb_debug_breakpoint *bp_list;
184
185 bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg);
186 if (bpnum < 0) {
187 print_api_common_error(bpnum);
188 return;
189 }
190 else if (bpnum == 0) {
191 puts(BREAK_ERR_MSG_NOBPNO_INFOALL);
192 return;
193 }
194 bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint));
195
196 ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list);
197 if (ret < 0) {
198 print_api_common_error(ret);
199 return;
200 }
201 puts(BREAK_INFO_MSG_HEADER);
202 for(i = 0 ; i < bpnum ; i++) {
203 print_breakpoint(&bp_list[i]);
204 }
205
206 mrb_free(mrb, bp_list);
207}
208
209static void
210info_break_select(mrb_state *mrb, mrdb_state *mrdb)
211{
212 int32_t ret = MRB_DEBUG_OK;
213 int32_t bpno = 0;
214 char* ps = mrdb->command;
215 mrb_debug_breakpoint bp;
216 mrb_bool isFirst = TRUE;
217 int32_t i;
218
219 for(i=2; i<mrdb->wcnt; i++) {
220 ps = mrdb->words[i];
221 bpno = parse_breakpoint_no(ps);
222 if (bpno == 0) {
223 puts(BREAK_ERR_MSG_INVALIDBPNO_INFO);
224 break;
225 }
226
227 ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp);
228 if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
229 printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno);
230 break;
231 }
232 else if (ret != MRB_DEBUG_OK) {
233 print_api_common_error(ret);
234 break;
235 }
236 else if (isFirst == TRUE) {
237 isFirst = FALSE;
238 puts(BREAK_INFO_MSG_HEADER);
239 }
240 print_breakpoint(&bp);
241 }
242}
243
244mrb_debug_bptype
245parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
246{
247 mrb_debug_context *dbg = mrdb->dbg;
248 char *args;
249 char *body;
250 mrb_debug_bptype type;
251 uint32_t l;
252
253 if (mrdb->wcnt <= 1) {
254 puts(BREAK_ERR_MSG_BLANK);
255 return MRB_DEBUG_BPTYPE_NONE;
256 }
257
258 args = mrdb->words[1];
259 if ((body = strrchr(args, ':')) == NULL) {
260 body = args;
261 type = check_bptype(body);
262 }
263 else {
264 if (body == args) {
265 printf(BREAK_ERR_MSG_INVALIDSTR, args);
266 return MRB_DEBUG_BPTYPE_NONE;
267 }
268 *body = '\0';
269 type = check_bptype(++body);
270 }
271
272 switch(type) {
273 case MRB_DEBUG_BPTYPE_LINE:
274 STRTOUL(l, body);
275 if (l <= 65535) {
276 *line = l;
277 *file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args;
278 }
279 else {
280 puts(BREAK_ERR_MSG_RANGEOVER);
281 type = MRB_DEBUG_BPTYPE_NONE;
282 }
283 break;
284 case MRB_DEBUG_BPTYPE_METHOD:
285 if (body == args) {
286 /* method only */
287 if (ISUPPER(*body)||ISLOWER(*body)||(*body == '_')) {
288 *method = body;
289 *cname = NULL;
290 }
291 else {
292 printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
293 type = MRB_DEBUG_BPTYPE_NONE;
294 }
295 }
296 else {
297 if (ISUPPER(*args)) {
298 switch(*body) {
299 case '@': case '$': case '?': case '.': case ',': case ':':
300 case ';': case '#': case '\\': case '\'': case '\"':
301 printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
302 type = MRB_DEBUG_BPTYPE_NONE;
303 break;
304 default:
305 *method = body;
306 *cname = args;
307 break;
308 }
309 }
310 else {
311 printf(BREAK_ERR_MSG_INVALIDCLASS, args);
312 type = MRB_DEBUG_BPTYPE_NONE;
313 }
314 }
315 break;
316 case MRB_DEBUG_BPTYPE_NONE:
317 default:
318 break;
319 }
320
321 return type;
322}
323
324dbgcmd_state
325dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
326{
327 mrb_debug_bptype type;
328 mrb_debug_context *dbg = mrdb->dbg;
329 const char *file = NULL;
330 uint32_t line = 0;
331 char *cname = NULL;
332 char *method = NULL;
333 int32_t ret;
334
335 type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
336 switch (type) {
337 case MRB_DEBUG_BPTYPE_LINE:
338 ret = mrb_debug_set_break_line(mrb, dbg, file, line);
339 break;
340 case MRB_DEBUG_BPTYPE_METHOD:
341 ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
342 break;
343 case MRB_DEBUG_BPTYPE_NONE:
344 default:
345 return DBGST_PROMPT;
346 }
347
348 if (ret >= 0) {
349 if (type == MRB_DEBUG_BPTYPE_LINE) {
350 printf(BREAK_SET_MSG_LINE, ret, file, line);
351 }
352 else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) {
353 printf(BREAK_SET_MSG_METHOD, ret, method);
354 }
355 else {
356 printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
357 }
358 }
359 else {
360 switch (ret) {
361 case MRB_DEBUG_BREAK_INVALID_LINENO:
362 printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
363 break;
364 case MRB_DEBUG_BREAK_INVALID_FILE:
365 printf(BREAK_ERR_MSG_INVALIDFILE, file);
366 break;
367 case MRB_DEBUG_BREAK_NUM_OVER:
368 puts(BREAK_ERR_MSG_NUMOVER);
369 break;
370 case MRB_DEBUG_BREAK_NO_OVER:
371 puts(BREAK_ERR_MSG_NOOVER);
372 break;
373 case MRB_DEBUG_INVALID_ARGUMENT:
374 puts(BREAK_ERR_MSG_INVALIDARG);
375 break;
376 case MRB_DEBUG_NOBUF:
377 puts("T.B.D.");
378 break;
379 default:
380 break;
381 }
382 }
383
384 return DBGST_PROMPT;
385}
386
387dbgcmd_state
388dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb)
389{
390 if (mrdb->wcnt == 2) {
391 info_break_all(mrb, mrdb);
392 }
393 else {
394 info_break_select(mrb, mrdb);
395 }
396
397 return DBGST_PROMPT;
398}
399
400dbgcmd_state
401dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb)
402{
403 mrb_bool ret = FALSE;
404
405 ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
406 if (ret != TRUE) {
407 exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
408 }
409
410 return DBGST_PROMPT;
411}
412
413dbgcmd_state
414dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb)
415{
416 mrb_bool ret = FALSE;
417
418 ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
419 if (ret != TRUE) {
420 exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
421 }
422
423 return DBGST_PROMPT;
424}
425
426dbgcmd_state
427dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb)
428{
429 mrb_bool ret = FALSE;
430
431 ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
432 if (ret != TRUE) {
433 exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
434 }
435 return DBGST_PROMPT;
436}
Note: See TracBrowser for help on using the repository browser.