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

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
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 } else {
263 if(body == args) {
264 printf(BREAK_ERR_MSG_INVALIDSTR, args);
265 return MRB_DEBUG_BPTYPE_NONE;
266 }
267 *body = '\0';
268 type = check_bptype(++body);
269 }
270
271 switch(type) {
272 case MRB_DEBUG_BPTYPE_LINE:
273 STRTOUL(l, body);
274 if( l <= 65535 ) {
275 *line = l;
276 *file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args;
277 } else {
278 puts(BREAK_ERR_MSG_RANGEOVER);
279 type = MRB_DEBUG_BPTYPE_NONE;
280 }
281 break;
282 case MRB_DEBUG_BPTYPE_METHOD:
283 if(body == args) {
284 /* method only */
285 if( ISUPPER(*body)||ISLOWER(*body)||(*body == '_') ) {
286 *method = body;
287 *cname = NULL;
288 } else {
289 printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
290 type = MRB_DEBUG_BPTYPE_NONE;
291 }
292 } else {
293 if( ISUPPER(*args) ) {
294 switch(*body) {
295 case '@': case '$': case '?': case '.': case ',': case ':':
296 case ';': case '#': case '\\': case '\'': case '\"':
297 printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
298 type = MRB_DEBUG_BPTYPE_NONE;
299 break;
300 default:
301 *method = body;
302 *cname = args;
303 break;
304 }
305 } else {
306 printf(BREAK_ERR_MSG_INVALIDCLASS, args);
307 type = MRB_DEBUG_BPTYPE_NONE;
308 }
309 }
310 break;
311 case MRB_DEBUG_BPTYPE_NONE:
312 default:
313 break;
314 }
315
316 return type;
317}
318
319dbgcmd_state
320dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
321{
322 mrb_debug_bptype type;
323 mrb_debug_context *dbg = mrdb->dbg;
324 const char *file = NULL;
325 uint32_t line = 0;
326 char *cname = NULL;
327 char *method = NULL;
328 int32_t ret;
329
330 type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
331 switch (type) {
332 case MRB_DEBUG_BPTYPE_LINE:
333 ret = mrb_debug_set_break_line(mrb, dbg, file, line);
334 break;
335 case MRB_DEBUG_BPTYPE_METHOD:
336 ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
337 break;
338 case MRB_DEBUG_BPTYPE_NONE:
339 default:
340 return DBGST_PROMPT;
341 }
342
343 if (ret >= 0) {
344 if (type == MRB_DEBUG_BPTYPE_LINE) {
345 printf(BREAK_SET_MSG_LINE, ret, file, line);
346 } else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) {
347 printf(BREAK_SET_MSG_METHOD, ret, method);
348 } else {
349 printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
350 }
351 } else {
352 switch (ret) {
353 case MRB_DEBUG_BREAK_INVALID_LINENO:
354 printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
355 break;
356 case MRB_DEBUG_BREAK_INVALID_FILE:
357 printf(BREAK_ERR_MSG_INVALIDFILE, file);
358 break;
359 case MRB_DEBUG_BREAK_NUM_OVER:
360 puts(BREAK_ERR_MSG_NUMOVER);
361 break;
362 case MRB_DEBUG_BREAK_NO_OVER:
363 puts(BREAK_ERR_MSG_NOOVER);
364 break;
365 case MRB_DEBUG_INVALID_ARGUMENT:
366 puts(BREAK_ERR_MSG_INVALIDARG);
367 break;
368 case MRB_DEBUG_NOBUF:
369 puts("T.B.D.");
370 break;
371 default:
372 break;
373 }
374 }
375
376 return DBGST_PROMPT;
377}
378
379dbgcmd_state
380dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb)
381{
382 if(mrdb->wcnt == 2) {
383 info_break_all(mrb, mrdb);
384 }
385 else {
386 info_break_select(mrb, mrdb);
387 }
388
389 return DBGST_PROMPT;
390}
391
392dbgcmd_state
393dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb)
394{
395 mrb_bool ret = FALSE;
396
397 ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
398 if(ret != TRUE) {
399 exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
400 }
401
402 return DBGST_PROMPT;
403}
404
405dbgcmd_state
406dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb)
407{
408 mrb_bool ret = FALSE;
409
410 ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
411 if(ret != TRUE) {
412 exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
413 }
414
415 return DBGST_PROMPT;
416}
417
418dbgcmd_state
419dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb)
420{
421 mrb_bool ret = FALSE;
422
423 ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
424 if(ret != TRUE) {
425 exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
426 }
427 return DBGST_PROMPT;
428}
Note: See TracBrowser for help on using the repository browser.