root/sapi/phpdbg/phpdbg_utils.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. phpdbg_is_numeric
  2. phpdbg_is_empty
  3. phpdbg_is_addr
  4. phpdbg_is_class_method
  5. phpdbg_resolve_path
  6. phpdbg_current_file
  7. phpdbg_get_function
  8. phpdbg_trim
  9. phpdbg_print
  10. phpdbg_rlog
  11. phpdbg_get_color
  12. phpdbg_set_color
  13. phpdbg_set_color_ex
  14. phpdbg_get_colors
  15. phpdbg_get_element
  16. phpdbg_set_prompt
  17. phpdbg_get_prompt
  18. phpdbg_rebuild_symtable
  19. phpdbg_get_terminal_width

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Felipe Pena <felipe@php.net>                                |
  16    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
  17    | Authors: Bob Weinand <bwoebi@php.net>                                |
  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 /* {{{ color structures */
  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         /* TODO(anyone) colours */
 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                 /* no formatting on logging output */
 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         /* free formatted prompt */
 381         if (PHPDBG_G(prompt)[1]) {
 382                 free(PHPDBG_G(prompt)[1]);
 383                 PHPDBG_G(prompt)[1] = NULL;
 384         }
 385         /* free old prompt */
 386         if (PHPDBG_G(prompt)[0]) {
 387                 free(PHPDBG_G(prompt)[0]);
 388                 PHPDBG_G(prompt)[0] = NULL;
 389         }
 390 
 391         /* copy new prompt */
 392         PHPDBG_G(prompt)[0] = strdup(prompt);
 393 } /* }}} */
 394 
 395 PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */
 396 {
 397         /* find cached prompt */
 398         if (PHPDBG_G(prompt)[1]) {
 399                 return PHPDBG_G(prompt)[1];
 400         }
 401 
 402         /* create cached prompt */
 403 #ifndef HAVE_LIBEDIT
 404         /* TODO: libedit doesn't seems to support coloured prompt */
 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 } /* }}} */

/* [<][>][^][v][top][bottom][index][help] */