10 #include "mrdberror.h"
12 #include <mruby/compile.h>
13 #include <mruby/irep.h>
14 #include <mruby/debug.h>
16 #define LINE_BUF_SIZE MAX_COMMAND_LINE
18 typedef struct source_file
{
25 source_file_free(mrb_state
*mrb
, source_file
*file
)
28 if (file
->path
!= NULL
) {
29 mrb_free(mrb
, file
->path
);
31 if (file
->fp
!= NULL
) {
40 build_path(mrb_state
*mrb
, const char *dir
, const char *base
)
45 len
= strlen(base
) + 1;
47 if (strcmp(dir
, ".")) {
48 len
+= strlen(dir
) + sizeof("/") - 1;
51 path
= (char*)mrb_malloc(mrb
, len
);
54 if (strcmp(dir
, ".")) {
64 dirname(mrb_state
*mrb
, const char *path
)
74 p
= strrchr(path
, '/');
75 len
= p
!= NULL
? (size_t)(p
- path
) : strlen(path
);
77 dir
= (char*)mrb_malloc(mrb
, len
+ 1);
78 strncpy(dir
, path
, len
);
85 source_file_new(mrb_state
*mrb
, mrb_debug_context
*dbg
, char *filename
)
89 file
= (source_file
*)mrb_malloc(mrb
, sizeof(source_file
));
91 memset(file
, '\0', sizeof(source_file
));
92 file
->fp
= fopen(filename
, "rb");
94 if (file
->fp
== NULL
) {
95 source_file_free(mrb
, file
);
100 file
->path
= (char*)mrb_malloc(mrb
, strlen(filename
) + 1);
101 strcpy(file
->path
, filename
);
106 remove_newlines(char *s
, FILE *fp
)
112 if ((len
= strlen(s
)) == 0) {
118 if (*p
!= '\r' && *p
!= '\n') {
123 /* peek the next character and skip '\n' */
124 if ((c
= fgetc(fp
)) != '\n') {
129 /* remove trailing newline characters */
130 while (s
<= p
&& (*p
== '\r' || *p
== '\n')) {
138 show_lines(source_file
*file
, uint16_t line_min
, uint16_t line_max
)
140 char buf
[LINE_BUF_SIZE
];
141 int show_lineno
= 1, found_newline
= 0, is_printed
= 0;
143 if (file
->fp
== NULL
) {
147 while (fgets(buf
, sizeof(buf
), file
->fp
) != NULL
) {
148 found_newline
= remove_newlines(buf
, file
->fp
);
150 if (line_min
<= file
->lineno
) {
152 printf("%-8d", file
->lineno
);
154 show_lineno
= found_newline
;
155 printf(found_newline
? "%s\n" : "%s", buf
);
160 if (line_max
< ++file
->lineno
) {
166 if (is_printed
&& !found_newline
) {
172 mrb_debug_get_source(mrb_state
*mrb
, mrdb_state
*mrdb
, const char *srcpath
, const char *filename
)
176 const char *search_path
[3];
178 const char *srcname
= strrchr(filename
, '/');
180 if (srcname
) srcname
++;
181 else srcname
= filename
;
183 search_path
[0] = srcpath
;
184 search_path
[1] = dirname(mrb
, mrb_debug_get_filename(mrb
, mrdb
->dbg
->irep
, 0));
185 search_path
[2] = ".";
187 for (i
= 0; i
< 3; i
++) {
188 if (search_path
[i
] == NULL
) {
192 if ((path
= build_path(mrb
, search_path
[i
], srcname
)) == NULL
) {
196 if ((fp
= fopen(path
, "rb")) == NULL
) {
205 mrb_free(mrb
, (void *)search_path
[1]);
211 mrb_debug_list(mrb_state
*mrb
, mrb_debug_context
*dbg
, char *filename
, uint16_t line_min
, uint16_t line_max
)
216 if (mrb
== NULL
|| dbg
== NULL
|| filename
== NULL
) {
217 return MRB_DEBUG_INVALID_ARGUMENT
;
220 ext
= strrchr(filename
, '.');
222 if (ext
== NULL
|| strcmp(ext
, ".rb")) {
223 printf("List command only supports .rb file.\n");
224 return MRB_DEBUG_INVALID_ARGUMENT
;
227 if (line_min
> line_max
) {
228 return MRB_DEBUG_INVALID_ARGUMENT
;
231 if ((file
= source_file_new(mrb
, dbg
, filename
)) != NULL
) {
232 show_lines(file
, line_min
, line_max
);
233 source_file_free(mrb
, file
);
237 printf("Invalid source file named %s.\n", filename
);
238 return MRB_DEBUG_INVALID_ARGUMENT
;