This source file includes following definitions.
- phpdbg_is_numeric
- phpdbg_is_empty
- phpdbg_is_addr
- phpdbg_is_class_method
- phpdbg_resolve_path
- phpdbg_current_file
- phpdbg_get_function
- phpdbg_trim
- phpdbg_print
- phpdbg_rlog
- phpdbg_get_color
- phpdbg_set_color
- phpdbg_set_color_ex
- phpdbg_get_colors
- phpdbg_get_element
- phpdbg_set_prompt
- phpdbg_get_prompt
- phpdbg_rebuild_symtable
- phpdbg_get_terminal_width
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include "zend.h"
25 #include "php.h"
26 #include "spprintf.h"
27 #include "phpdbg.h"
28 #include "phpdbg_opcode.h"
29 #include "phpdbg_utils.h"
30
31 #ifdef _WIN32
32 # include "win32/time.h"
33 #elif defined(HAVE_SYS_IOCTL_H)
34 # include "sys/ioctl.h"
35 # ifndef GWINSZ_IN_SYS_IOCTL
36 # include <termios.h>
37 # endif
38 #endif
39
40 ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
41
42
43 const static phpdbg_color_t colors[] = {
44 PHPDBG_COLOR_D("none", "0;0"),
45
46 PHPDBG_COLOR_D("white", "0;64"),
47 PHPDBG_COLOR_D("white-bold", "1;64"),
48 PHPDBG_COLOR_D("white-underline", "4;64"),
49 PHPDBG_COLOR_D("red", "0;31"),
50 PHPDBG_COLOR_D("red-bold", "1;31"),
51 PHPDBG_COLOR_D("red-underline", "4;31"),
52 PHPDBG_COLOR_D("green", "0;32"),
53 PHPDBG_COLOR_D("green-bold", "1;32"),
54 PHPDBG_COLOR_D("green-underline", "4;32"),
55 PHPDBG_COLOR_D("yellow", "0;33"),
56 PHPDBG_COLOR_D("yellow-bold", "1;33"),
57 PHPDBG_COLOR_D("yellow-underline", "4;33"),
58 PHPDBG_COLOR_D("blue", "0;34"),
59 PHPDBG_COLOR_D("blue-bold", "1;34"),
60 PHPDBG_COLOR_D("blue-underline", "4;34"),
61 PHPDBG_COLOR_D("purple", "0;35"),
62 PHPDBG_COLOR_D("purple-bold", "1;35"),
63 PHPDBG_COLOR_D("purple-underline", "4;35"),
64 PHPDBG_COLOR_D("cyan", "0;36"),
65 PHPDBG_COLOR_D("cyan-bold", "1;36"),
66 PHPDBG_COLOR_D("cyan-underline", "4;36"),
67 PHPDBG_COLOR_D("black", "0;30"),
68 PHPDBG_COLOR_D("black-bold", "1;30"),
69 PHPDBG_COLOR_D("black-underline", "4;30"),
70 PHPDBG_COLOR_END
71 };
72
73
74 const static phpdbg_element_t elements[] = {
75 PHPDBG_ELEMENT_D("prompt", PHPDBG_COLOR_PROMPT),
76 PHPDBG_ELEMENT_D("error", PHPDBG_COLOR_ERROR),
77 PHPDBG_ELEMENT_D("notice", PHPDBG_COLOR_NOTICE),
78 PHPDBG_ELEMENT_END
79 };
80
81 PHPDBG_API int phpdbg_is_numeric(const char *str)
82 {
83 if (!str)
84 return 0;
85
86 for (; *str; str++) {
87 if (isspace(*str) || *str == '-') {
88 continue;
89 }
90 return isdigit(*str);
91 }
92 return 0;
93 }
94
95 PHPDBG_API int phpdbg_is_empty(const char *str)
96 {
97 if (!str)
98 return 1;
99
100 for (; *str; str++) {
101 if (isspace(*str)) {
102 continue;
103 }
104 return 0;
105 }
106 return 1;
107 }
108
109 PHPDBG_API int phpdbg_is_addr(const char *str)
110 {
111 return str[0] && str[1] && memcmp(str, "0x", 2) == 0;
112 }
113
114 PHPDBG_API int phpdbg_is_class_method(const char *str, size_t len, char **class, char **method)
115 {
116 char *sep = NULL;
117
118 if (strstr(str, "#") != NULL)
119 return 0;
120
121 if (strstr(str, " ") != NULL)
122 return 0;
123
124 sep = strstr(str, "::");
125
126 if (!sep || sep == str || sep+2 == str+len-1) {
127 return 0;
128 }
129
130 if (class != NULL) {
131
132 if (str[0] == '\\') {
133 str++;
134 len--;
135 }
136
137 *class = estrndup(str, sep - str);
138 (*class)[sep - str] = 0;
139 }
140
141 if (method != NULL) {
142 *method = estrndup(sep+2, str + len - (sep + 2));
143 }
144
145 return 1;
146 }
147
148 PHPDBG_API char *phpdbg_resolve_path(const char *path TSRMLS_DC)
149 {
150 char resolved_name[MAXPATHLEN];
151
152 if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
153 return NULL;
154 }
155
156 return estrdup(resolved_name);
157 }
158
159 PHPDBG_API const char *phpdbg_current_file(TSRMLS_D)
160 {
161 const char *file = zend_get_executed_filename(TSRMLS_C);
162
163 if (memcmp(file, "[no active file]", sizeof("[no active file]")) == 0) {
164 return PHPDBG_G(exec);
165 }
166
167 return file;
168 }
169
170 PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname TSRMLS_DC)
171 {
172 zend_function *func = NULL;
173 size_t fname_len = strlen(fname);
174 char *lcname = zend_str_tolower_dup(fname, fname_len);
175
176 if (cname) {
177 zend_class_entry **ce;
178 size_t cname_len = strlen(cname);
179 char *lc_cname = zend_str_tolower_dup(cname, cname_len);
180 int ret = zend_lookup_class(lc_cname, cname_len, &ce TSRMLS_CC);
181
182 efree(lc_cname);
183
184 if (ret == SUCCESS) {
185 zend_hash_find(&(*ce)->function_table, lcname, fname_len+1,
186 (void**)&func);
187 }
188 } else {
189 zend_hash_find(EG(function_table), lcname, fname_len+1,
190 (void**)&func);
191 }
192
193 efree(lcname);
194 return func;
195 }
196
197 PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len)
198 {
199 const char *p = str;
200 char *new = NULL;
201
202 while (p && isspace(*p)) {
203 ++p;
204 --len;
205 }
206
207 while (*p && isspace(*(p + len -1))) {
208 --len;
209 }
210
211 if (len == 0) {
212 new = estrndup("", sizeof(""));
213 *new_len = 0;
214 } else {
215 new = estrndup(p, len);
216 *(new + len) = '\0';
217
218 if (new_len) {
219 *new_len = len;
220 }
221 }
222
223 return new;
224
225 }
226
227 PHPDBG_API int phpdbg_print(int type TSRMLS_DC, FILE *fp, const char *format, ...)
228 {
229 int rc = 0;
230 char *buffer = NULL;
231 va_list args;
232
233 if (format != NULL && strlen(format) > 0L) {
234 va_start(args, format);
235 vspprintf(&buffer, 0, format, args);
236 va_end(args);
237 }
238
239
240
241 switch (type) {
242 case P_ERROR:
243 if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
244 rc = fprintf(fp,
245 "\033[%sm[%s]\033[0m\n",
246 PHPDBG_G(colors)[PHPDBG_COLOR_ERROR]->code, buffer);
247 } else {
248 rc = fprintf(fp, "[%s]\n", buffer);
249 }
250 break;
251
252 case P_NOTICE:
253 if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
254 rc = fprintf(fp,
255 "\033[%sm[%s]\033[0m\n",
256 PHPDBG_G(colors)[PHPDBG_COLOR_NOTICE]->code, buffer);
257 } else {
258 rc = fprintf(fp, "[%s]\n", buffer);
259 }
260 break;
261
262 case P_WRITELN: {
263 if (buffer) {
264 rc = fprintf(fp, "%s\n", buffer);
265 } else {
266 rc = fprintf(fp, "\n");
267 }
268 } break;
269
270 case P_WRITE:
271 if (buffer) {
272 rc = fprintf(fp, "%s", buffer);
273 }
274 break;
275
276
277 case P_LOG:
278 if (buffer) {
279 struct timeval tp;
280 if (gettimeofday(&tp, NULL) == SUCCESS) {
281 rc = fprintf(fp, "[%ld %.8F]: %s\n", tp.tv_sec, tp.tv_usec / 1000000.00, buffer);
282 } else {
283 rc = FAILURE;
284 }
285 }
286 break;
287 }
288
289 if (buffer) {
290 efree(buffer);
291 }
292
293 return rc;
294 }
295
296 PHPDBG_API int phpdbg_rlog(FILE *fp, const char *fmt, ...) {
297 int rc = 0;
298
299 va_list args;
300 struct timeval tp;
301
302 va_start(args, fmt);
303 if (gettimeofday(&tp, NULL) == SUCCESS) {
304 char friendly[100];
305 char *format = NULL, *buffer = NULL;
306 const time_t tt = tp.tv_sec;
307
308 strftime(friendly, 100, "%a %b %d %T.%%04d %Y", localtime(&tt));
309 asprintf(
310 &buffer, friendly, tp.tv_usec/1000);
311 asprintf(
312 &format, "[%s]: %s\n", buffer, fmt);
313 rc = vfprintf(
314 fp, format, args);
315
316 free(format);
317 free(buffer);
318 }
319 va_end(args);
320
321 return rc;
322 }
323
324 PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length TSRMLS_DC)
325 {
326 const phpdbg_color_t *color = colors;
327
328 while (color && color->name) {
329 if (name_length == color->name_length &&
330 memcmp(name, color->name, name_length) == SUCCESS) {
331 phpdbg_debug(
332 "phpdbg_get_color(%s, %lu): %s", name, name_length, color->code);
333 return color;
334 }
335 ++color;
336 }
337
338 phpdbg_debug(
339 "phpdbg_get_color(%s, %lu): failed", name, name_length);
340
341 return NULL;
342 }
343
344 PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color TSRMLS_DC)
345 {
346 PHPDBG_G(colors)[element] = color;
347 }
348
349 PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length TSRMLS_DC)
350 {
351 const phpdbg_color_t *color = phpdbg_get_color(name, name_length TSRMLS_CC);
352
353 if (color) {
354 phpdbg_set_color(element, color TSRMLS_CC);
355 } else PHPDBG_G(colors)[element] = colors;
356 }
357
358 PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(TSRMLS_D)
359 {
360 return colors;
361 }
362
363 PHPDBG_API int phpdbg_get_element(const char *name, size_t len TSRMLS_DC) {
364 const phpdbg_element_t *element = elements;
365
366 while (element && element->name) {
367 if (len == element->name_length) {
368 if (strncasecmp(name, element->name, len) == SUCCESS) {
369 return element->id;
370 }
371 }
372 element++;
373 }
374
375 return PHPDBG_COLOR_INVALID;
376 }
377
378 PHPDBG_API void phpdbg_set_prompt(const char *prompt TSRMLS_DC)
379 {
380
381 if (PHPDBG_G(prompt)[1]) {
382 free(PHPDBG_G(prompt)[1]);
383 PHPDBG_G(prompt)[1] = NULL;
384 }
385
386 if (PHPDBG_G(prompt)[0]) {
387 free(PHPDBG_G(prompt)[0]);
388 PHPDBG_G(prompt)[0] = NULL;
389 }
390
391
392 PHPDBG_G(prompt)[0] = strdup(prompt);
393 }
394
395 PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D)
396 {
397
398 if (PHPDBG_G(prompt)[1]) {
399 return PHPDBG_G(prompt)[1];
400 }
401
402
403 #ifndef HAVE_LIBEDIT
404
405 if ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED)) {
406 asprintf(
407 &PHPDBG_G(prompt)[1], "\033[%sm%s\033[0m ",
408 PHPDBG_G(colors)[PHPDBG_COLOR_PROMPT]->code,
409 PHPDBG_G(prompt)[0]);
410 } else
411 #endif
412 {
413 asprintf(
414 &PHPDBG_G(prompt)[1], "%s ",
415 PHPDBG_G(prompt)[0]);
416 }
417
418 return PHPDBG_G(prompt)[1];
419 }
420
421 int phpdbg_rebuild_symtable(TSRMLS_D) {
422 if (!EG(active_op_array)) {
423 phpdbg_error("No active op array!");
424 return FAILURE;
425 }
426
427 if (!EG(active_symbol_table)) {
428 zend_rebuild_symbol_table(TSRMLS_C);
429
430 if (!EG(active_symbol_table)) {
431 phpdbg_error("No active symbol table!");
432 return FAILURE;
433 }
434 }
435
436 return SUCCESS;
437 }
438
439 PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D)
440 {
441 int columns;
442 #ifdef _WIN32
443 CONSOLE_SCREEN_BUFFER_INFO csbi;
444
445 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
446 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
447 #elif defined(HAVE_SYS_IOCTL_H) && defined (TIOCGWINSZ)
448 struct winsize w;
449
450 columns = ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_col : 80;
451 #else
452 columns = 80;
453 #endif
454 return columns;
455 }