source: EcnlProtoTool/trunk/prototool/src/cmdbreak.c@ 279

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

ファイルを追加、更新。

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