source: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c@ 439

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

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 4.5 KB
Line 
1/*
2 * apilist.c
3 */
4
5#include <ctype.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "mrdb.h"
10#include "mrdberror.h"
11#include "apilist.h"
12#include <mruby/compile.h>
13#include <mruby/irep.h>
14#include <mruby/debug.h>
15
16#define LINE_BUF_SIZE MAX_COMMAND_LINE
17
18typedef struct source_file {
19 char *path;
20 uint16_t lineno;
21 FILE *fp;
22} source_file;
23
24static void
25source_file_free(mrb_state *mrb, source_file *file)
26{
27 if (file != NULL) {
28 if (file->path != NULL) {
29 mrb_free(mrb, file->path);
30 }
31 if (file->fp != NULL) {
32 fclose(file->fp);
33 file->fp = NULL;
34 }
35 mrb_free(mrb, file);
36 }
37}
38
39static char*
40build_path(mrb_state *mrb, const char *dir, const char *base)
41{
42 int len;
43 char *path = NULL;
44
45 len = strlen(base) + 1;
46
47 if (strcmp(dir, ".")) {
48 len += strlen(dir) + sizeof("/") - 1;
49 }
50
51 path = (char*)mrb_malloc(mrb, len);
52 memset(path, 0, len);
53
54 if (strcmp(dir, ".")) {
55 strcat(path, dir);
56 strcat(path, "/");
57 }
58 strcat(path, base);
59
60 return path;
61}
62
63static char*
64dirname(mrb_state *mrb, const char *path)
65{
66 size_t len;
67 const char *p;
68 char *dir;
69
70 if (path == NULL) {
71 return NULL;
72 }
73
74 p = strrchr(path, '/');
75 len = p != NULL ? (size_t)(p - path) : strlen(path);
76
77 dir = (char*)mrb_malloc(mrb, len + 1);
78 strncpy(dir, path, len);
79 dir[len] = '\0';
80
81 return dir;
82}
83
84static source_file*
85source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
86{
87 source_file *file;
88
89 file = (source_file*)mrb_malloc(mrb, sizeof(source_file));
90
91 memset(file, '\0', sizeof(source_file));
92 file->fp = fopen(filename, "rb");
93
94 if (file->fp == NULL) {
95 source_file_free(mrb, file);
96 return NULL;
97 }
98
99 file->lineno = 1;
100 file->path = (char*)mrb_malloc(mrb, strlen(filename) + 1);
101 strcpy(file->path, filename);
102 return file;
103}
104
105static mrb_bool
106remove_newlines(char *s, FILE *fp)
107{
108 int c;
109 char *p;
110 size_t len;
111
112 if ((len = strlen(s)) == 0) {
113 return FALSE;
114 }
115
116 p = s + len - 1;
117
118 if (*p != '\r' && *p != '\n') {
119 return FALSE;
120 }
121
122 if (*p == '\r') {
123 /* peek the next character and skip '\n' */
124 if ((c = fgetc(fp)) != '\n') {
125 ungetc(c, fp);
126 }
127 }
128
129 /* remove trailing newline characters */
130 while (s <= p && (*p == '\r' || *p == '\n')) {
131 *p-- = '\0';
132 }
133
134 return TRUE;
135}
136
137static void
138show_lines(source_file *file, uint16_t line_min, uint16_t line_max)
139{
140 char buf[LINE_BUF_SIZE];
141 int show_lineno = 1, found_newline = 0, is_printed = 0;
142
143 if (file->fp == NULL) {
144 return;
145 }
146
147 while (fgets(buf, sizeof(buf), file->fp) != NULL) {
148 found_newline = remove_newlines(buf, file->fp);
149
150 if (line_min <= file->lineno) {
151 if (show_lineno) {
152 printf("%-8d", file->lineno);
153 }
154 show_lineno = found_newline;
155 printf(found_newline ? "%s\n" : "%s", buf);
156 is_printed = 1;
157 }
158
159 if (found_newline) {
160 if (line_max < ++file->lineno) {
161 break;
162 }
163 }
164 }
165
166 if (is_printed && !found_newline) {
167 printf("\n");
168 }
169}
170
171char*
172mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, const char *filename)
173{
174 int i;
175 FILE *fp;
176 const char *search_path[3];
177 char *path = NULL;
178 const char *srcname = strrchr(filename, '/');
179
180 if (srcname) srcname++;
181 else srcname = filename;
182
183 search_path[0] = srcpath;
184 search_path[1] = dirname(mrb, mrb_debug_get_filename(mrb, mrdb->dbg->irep, 0));
185 search_path[2] = ".";
186
187 for (i = 0; i < 3; i++) {
188 if (search_path[i] == NULL) {
189 continue;
190 }
191
192 if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
193 continue;
194 }
195
196 if ((fp = fopen(path, "rb")) == NULL) {
197 mrb_free(mrb, path);
198 path = NULL;
199 continue;
200 }
201 fclose(fp);
202 break;
203 }
204
205 mrb_free(mrb, (void *)search_path[1]);
206
207 return path;
208}
209
210int32_t
211mrb_debug_list(mrb_state *mrb, mrb_debug_context *dbg, char *filename, uint16_t line_min, uint16_t line_max)
212{
213 char *ext;
214 source_file *file;
215
216 if (mrb == NULL || dbg == NULL || filename == NULL) {
217 return MRB_DEBUG_INVALID_ARGUMENT;
218 }
219
220 ext = strrchr(filename, '.');
221
222 if (ext == NULL || strcmp(ext, ".rb")) {
223 printf("List command only supports .rb file.\n");
224 return MRB_DEBUG_INVALID_ARGUMENT;
225 }
226
227 if (line_min > line_max) {
228 return MRB_DEBUG_INVALID_ARGUMENT;
229 }
230
231 if ((file = source_file_new(mrb, dbg, filename)) != NULL) {
232 show_lines(file, line_min, line_max);
233 source_file_free(mrb, file);
234 return MRB_DEBUG_OK;
235 }
236 else {
237 printf("Invalid source file named %s.\n", filename);
238 return MRB_DEBUG_INVALID_ARGUMENT;
239 }
240}
Note: See TracBrowser for help on using the repository browser.