root/sapi/phpdbg/phpdbg_out.c

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

DEFINITIONS

This source file includes following definitions.
  1. format_converter
  2. strx_printv
  3. phpdbg_xml_vsnprintf
  4. phpdbg_xml_vasprintf
  5. _phpdbg_xml_asprintf
  6. _phpdbg_asprintf
  7. phpdbg_encode_xml
  8. phpdbg_encode_ctrl_chars
  9. phpdbg_process_print
  10. phpdbg_vprint
  11. phpdbg_free_err_buf
  12. phpdbg_activate_err_buf
  13. phpdbg_output_err_buf
  14. phpdbg_print
  15. phpdbg_xml_internal
  16. phpdbg_log_internal
  17. phpdbg_out_internal
  18. phpdbg_rlog_internal

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   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 "zend.h"
  22 #include "php.h"
  23 #include "spprintf.h"
  24 #include "phpdbg.h"
  25 #include "phpdbg_io.h"
  26 #include "phpdbg_eol.h"
  27 #include "ext/standard/html.h"
  28 
  29 #ifdef _WIN32
  30 #       include "win32/time.h"
  31 #endif
  32 
  33 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  34 
  35 /* copied from php-src/main/snprintf.c and slightly modified */
  36 /*
  37  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  38  *
  39  * XXX: this is a magic number; do not decrease it
  40  * Emax = 1023
  41  * NDIG = 320
  42  * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
  43  */
  44 #define NUM_BUF_SIZE        2048
  45 
  46 /*
  47  * Descriptor for buffer area
  48  */
  49 struct buf_area {
  50         char *buf_end;
  51         char *nextb; /* pointer to next byte to read/write   */
  52 };
  53 
  54 typedef struct buf_area buffy;
  55 
  56 /*
  57  * The INS_CHAR macro inserts a character in the buffer and writes
  58  * the buffer back to disk if necessary
  59  * It uses the char pointers sp and bep:
  60  *      sp points to the next available character in the buffer
  61  *      bep points to the end-of-buffer+1
  62  * While using this macro, note that the nextb pointer is NOT updated.
  63  *
  64  * NOTE: Evaluation of the c argument should not have any side-effects
  65  */
  66 #define INS_CHAR(c, sp, bep, cc) \
  67         {                            \
  68                 if (sp < bep)            \
  69                 {                        \
  70                         *sp++ = c;           \
  71                 }                        \
  72                 cc++;                    \
  73         }
  74 
  75 #define NUM( c )                        ( c - '0' )
  76 
  77 #define STR_TO_DEC( str, num )          \
  78     num = NUM( *str++ ) ;               \
  79     while ( isdigit((int)*str ) )               \
  80     {                                   \
  81         num *= 10 ;                     \
  82         num += NUM( *str++ ) ;          \
  83     }
  84 
  85 /*
  86  * This macro does zero padding so that the precision
  87  * requirement is satisfied. The padding is done by
  88  * adding '0's to the left of the string that is going
  89  * to be printed.
  90  */
  91 #define FIX_PRECISION( adjust, precision, s, s_len )    \
  92     if ( adjust )                                       \
  93         while ( s_len < precision )                     \
  94         {                                               \
  95             *--s = '0' ;                                \
  96             s_len++ ;                                   \
  97         }
  98 
  99 /*
 100  * Macro that does padding. The padding is done by printing
 101  * the character ch.
 102  */
 103 #define PAD( width, len, ch )   do              \
 104         {                                       \
 105             INS_CHAR( ch, sp, bep, cc ) ;       \
 106             width-- ;                           \
 107         }                                       \
 108         while ( width > len )
 109 
 110 /*
 111  * Prefix the character ch to the string str
 112  * Increase length
 113  * Set the has_prefix flag
 114  */
 115 #define PREFIX( str, length, ch )        *--str = ch ; length++ ; has_prefix = YES
 116 
 117 
 118 #ifdef HAVE_LOCALE_H
 119 #include <locale.h>
 120 #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
 121 #else
 122 #define LCONV_DECIMAL_POINT '.'
 123 #endif
 124 #define NUL '\0'
 125 #define S_NULL "(null)"
 126 #define S_NULL_LEN 6
 127 #define FLOAT_DIGITS 6
 128 
 129 /*
 130  * Do format conversion placing the output in buffer
 131  */
 132 static int format_converter(register buffy *odp, const char *fmt, zend_bool escape_xml, va_list ap) {
 133         char *sp;
 134         char *bep;
 135         int cc = 0;
 136         int i;
 137 
 138         char *s = NULL, *free_s = NULL;
 139         size_t s_len;
 140         zend_bool free_zcopy;
 141         zval *zvp, zcopy;
 142 
 143         int min_width = 0;
 144         int precision = 0;
 145         enum {
 146                 LEFT, RIGHT
 147         } adjust;
 148         char pad_char;
 149         char prefix_char;
 150 
 151         double fp_num;
 152         wide_int i_num = (wide_int) 0;
 153         u_wide_int ui_num;
 154 
 155         char num_buf[NUM_BUF_SIZE];
 156         char char_buf[2];                       /* for printing %% and %<unknown> */
 157 
 158 #ifdef HAVE_LOCALE_H
 159         struct lconv *lconv = NULL;
 160 #endif
 161 
 162         /*
 163          * Flag variables
 164          */
 165         length_modifier_e modifier;
 166         boolean_e alternate_form;
 167         boolean_e print_sign;
 168         boolean_e print_blank;
 169         boolean_e adjust_precision;
 170         boolean_e adjust_width;
 171         bool_int is_negative;
 172 
 173         sp = odp->nextb;
 174         bep = odp->buf_end;
 175 
 176         while (*fmt) {
 177                 if (*fmt != '%') {
 178                         INS_CHAR(*fmt, sp, bep, cc);
 179                 } else {
 180                         /*
 181                          * Default variable settings
 182                          */
 183                         adjust = RIGHT;
 184                         alternate_form = print_sign = print_blank = NO;
 185                         pad_char = ' ';
 186                         prefix_char = NUL;
 187                         free_zcopy = 0;
 188 
 189                         fmt++;
 190 
 191                         /*
 192                          * Try to avoid checking for flags, width or precision
 193                          */
 194                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
 195                                 /*
 196                                  * Recognize flags: -, #, BLANK, +
 197                                  */
 198                                 for (;; fmt++) {
 199                                         if (*fmt == '-')
 200                                                 adjust = LEFT;
 201                                         else if (*fmt == '+')
 202                                                 print_sign = YES;
 203                                         else if (*fmt == '#')
 204                                                 alternate_form = YES;
 205                                         else if (*fmt == ' ')
 206                                                 print_blank = YES;
 207                                         else if (*fmt == '0')
 208                                                 pad_char = '0';
 209                                         else
 210                                                 break;
 211                                 }
 212 
 213                                 /*
 214                                  * Check if a width was specified
 215                                  */
 216                                 if (isdigit((int)*fmt)) {
 217                                         STR_TO_DEC(fmt, min_width);
 218                                         adjust_width = YES;
 219                                 } else if (*fmt == '*') {
 220                                         min_width = va_arg(ap, int);
 221                                         fmt++;
 222                                         adjust_width = YES;
 223                                         if (min_width < 0) {
 224                                                 adjust = LEFT;
 225                                                 min_width = -min_width;
 226                                         }
 227                                 } else
 228                                         adjust_width = NO;
 229 
 230                                 /*
 231                                  * Check if a precision was specified
 232                                  */
 233                                 if (*fmt == '.') {
 234                                         adjust_precision = YES;
 235                                         fmt++;
 236                                         if (isdigit((int)*fmt)) {
 237                                                 STR_TO_DEC(fmt, precision);
 238                                         } else if (*fmt == '*') {
 239                                                 precision = va_arg(ap, int);
 240                                                 fmt++;
 241                                                 if (precision < 0)
 242                                                         precision = 0;
 243                                         } else
 244                                                 precision = 0;
 245 
 246                                         if (precision > FORMAT_CONV_MAX_PRECISION && *fmt != 's' && *fmt != 'v' && *fmt != 'b') {
 247                                                 precision = FORMAT_CONV_MAX_PRECISION;
 248                                         }
 249                                 } else
 250                                         adjust_precision = NO;
 251                         } else
 252                                 adjust_precision = adjust_width = NO;
 253 
 254                         /*
 255                          * Modifier check
 256                          */
 257                         switch (*fmt) {
 258                                 case 'L':
 259                                         fmt++;
 260                                         modifier = LM_LONG_DOUBLE;
 261                                         break;
 262                                 case 'I':
 263                                         fmt++;
 264 #if SIZEOF_LONG_LONG
 265                                         if (*fmt == '6' && *(fmt+1) == '4') {
 266                                                 fmt += 2;
 267                                                 modifier = LM_LONG_LONG;
 268                                         } else
 269 #endif
 270                                                 if (*fmt == '3' && *(fmt+1) == '2') {
 271                                                         fmt += 2;
 272                                                         modifier = LM_LONG;
 273                                                 } else {
 274 #ifdef _WIN64
 275                                                         modifier = LM_LONG_LONG;
 276 #else
 277                                                         modifier = LM_LONG;
 278 #endif
 279                                                 }
 280                                         break;
 281                                 case 'l':
 282                                         fmt++;
 283 #if SIZEOF_LONG_LONG
 284                                         if (*fmt == 'l') {
 285                                                 fmt++;
 286                                                 modifier = LM_LONG_LONG;
 287                                         } else
 288 #endif
 289                                                 modifier = LM_LONG;
 290                                         break;
 291                                         case 'z':
 292                                         fmt++;
 293                                         modifier = LM_SIZE_T;
 294                                         break;
 295                                 case 'j':
 296                                         fmt++;
 297 #if SIZEOF_INTMAX_T
 298                                         modifier = LM_INTMAX_T;
 299 #else
 300                                         modifier = LM_SIZE_T;
 301 #endif
 302                                         break;
 303                                 case 't':
 304                                         fmt++;
 305 #if SIZEOF_PTRDIFF_T
 306                                         modifier = LM_PTRDIFF_T;
 307 #else
 308                                         modifier = LM_SIZE_T;
 309 #endif
 310                                         break;
 311                                 case 'h':
 312                                         fmt++;
 313                                         if (*fmt == 'h') {
 314                                                 fmt++;
 315                                         }
 316                                         /* these are promoted to int, so no break */
 317                                 default:
 318                                         modifier = LM_STD;
 319                                         break;
 320                         }
 321 
 322                         /*
 323                          * Argument extraction and printing.
 324                          * First we determine the argument type.
 325                          * Then, we convert the argument to a string.
 326                          * On exit from the switch, s points to the string that
 327                          * must be printed, s_len has the length of the string
 328                          * The precision requirements, if any, are reflected in s_len.
 329                          *
 330                          * NOTE: pad_char may be set to '0' because of the 0 flag.
 331                          *   It is reset to ' ' by non-numeric formats
 332                          */
 333                         switch (*fmt) {
 334                                 case 'Z':
 335                                         zvp = (zval *) va_arg(ap, zval *);
 336                                         free_zcopy = zend_make_printable_zval(zvp, &zcopy);
 337                                         if (free_zcopy) {
 338                                                 zvp = &zcopy;
 339                                         }
 340                                         s_len = Z_STRLEN_P(zvp);
 341                                         s = Z_STRVAL_P(zvp);
 342                                         if (adjust_precision && precision < s_len) {
 343                                                 s_len = precision;
 344                                         }
 345                                         break;
 346                                 case 'u':
 347                                         switch(modifier) {
 348                                                 default:
 349                                                         i_num = (wide_int) va_arg(ap, unsigned int);
 350                                                         break;
 351                                                 case LM_LONG_DOUBLE:
 352                                                         goto fmt_error;
 353                                                 case LM_LONG:
 354                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
 355                                                         break;
 356                                                 case LM_SIZE_T:
 357                                                         i_num = (wide_int) va_arg(ap, size_t);
 358                                                         break;
 359 #if SIZEOF_LONG_LONG
 360                                                 case LM_LONG_LONG:
 361                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
 362                                                         break;
 363 #endif
 364 #if SIZEOF_INTMAX_T
 365                                                 case LM_INTMAX_T:
 366                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
 367                                                         break;
 368 #endif
 369 #if SIZEOF_PTRDIFF_T
 370                                                 case LM_PTRDIFF_T:
 371                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
 372                                                         break;
 373 #endif
 374                                         }
 375                                         /*
 376                                          * The rest also applies to other integer formats, so fall
 377                                          * into that case.
 378                                          */
 379                                 case 'd':
 380                                 case 'i':
 381                                         /*
 382                                          * Get the arg if we haven't already.
 383                                          */
 384                                         if ((*fmt) != 'u') {
 385                                                 switch(modifier) {
 386                                                         default:
 387                                                                 i_num = (wide_int) va_arg(ap, int);
 388                                                                 break;
 389                                                         case LM_LONG_DOUBLE:
 390                                                                 goto fmt_error;
 391                                                         case LM_LONG:
 392                                                                 i_num = (wide_int) va_arg(ap, long int);
 393                                                                 break;
 394                                                         case LM_SIZE_T:
 395 #if SIZEOF_SSIZE_T
 396                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
 397 #else
 398                                                                 i_num = (wide_int) va_arg(ap, size_t);
 399 #endif
 400                                                                 break;
 401 #if SIZEOF_LONG_LONG
 402                                                         case LM_LONG_LONG:
 403                                                                 i_num = (wide_int) va_arg(ap, wide_int);
 404                                                                 break;
 405 #endif
 406 #if SIZEOF_INTMAX_T
 407                                                         case LM_INTMAX_T:
 408                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
 409                                                                 break;
 410 #endif
 411 #if SIZEOF_PTRDIFF_T
 412                                                         case LM_PTRDIFF_T:
 413                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
 414                                                                 break;
 415 #endif
 416                                                 }
 417                                         }
 418                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
 419                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
 420                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
 421 
 422                                         if (*fmt != 'u') {
 423                                                 if (is_negative) {
 424                                                         prefix_char = '-';
 425                                                 } else if (print_sign) {
 426                                                         prefix_char = '+';
 427                                                 } else if (print_blank) {
 428                                                         prefix_char = ' ';
 429                                                 }
 430                                         }
 431                                         break;
 432 
 433 
 434                                 case 'o':
 435                                         switch(modifier) {
 436                                                 default:
 437                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
 438                                                         break;
 439                                                 case LM_LONG_DOUBLE:
 440                                                         goto fmt_error;
 441                                                 case LM_LONG:
 442                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
 443                                                         break;
 444                                                 case LM_SIZE_T:
 445                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
 446                                                         break;
 447 #if SIZEOF_LONG_LONG
 448                                                 case LM_LONG_LONG:
 449                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
 450                                                         break;
 451 #endif
 452 #if SIZEOF_INTMAX_T
 453                                                 case LM_INTMAX_T:
 454                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
 455                                                         break;
 456 #endif
 457 #if SIZEOF_PTRDIFF_T
 458                                                 case LM_PTRDIFF_T:
 459                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
 460                                                         break;
 461 #endif
 462                                         }
 463                                         s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
 464                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
 465                                         if (alternate_form && *s != '0') {
 466                                                 *--s = '0';
 467                                                 s_len++;
 468                                         }
 469                                         break;
 470 
 471 
 472                                 case 'x':
 473                                 case 'X':
 474                                         switch(modifier) {
 475                                                 default:
 476                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
 477                                                         break;
 478                                                 case LM_LONG_DOUBLE:
 479                                                         goto fmt_error;
 480                                                 case LM_LONG:
 481                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
 482                                                         break;
 483                                                 case LM_SIZE_T:
 484                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
 485                                                         break;
 486 #if SIZEOF_LONG_LONG
 487                                                 case LM_LONG_LONG:
 488                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
 489                                                         break;
 490 #endif
 491 #if SIZEOF_INTMAX_T
 492                                                 case LM_INTMAX_T:
 493                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
 494                                                         break;
 495 #endif
 496 #if SIZEOF_PTRDIFF_T
 497                                                 case LM_PTRDIFF_T:
 498                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
 499                                                         break;
 500 #endif
 501                                         }
 502                                         s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
 503                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
 504                                         if (alternate_form && i_num != 0) {
 505                                                 *--s = *fmt;    /* 'x' or 'X' */
 506                                                 *--s = '0';
 507                                                 s_len += 2;
 508                                         }
 509                                         break;
 510 
 511 
 512                                 case 's':
 513                                 case 'v':
 514                                         s = va_arg(ap, char *);
 515                                         if (s != NULL) {
 516                                                 if (adjust_precision) {
 517                                                         s_len = precision;
 518                                                 } else {
 519                                                         s_len = strlen(s);
 520                                                 }
 521 
 522                                                 if (escape_xml) {
 523                                                         /* added: support for xml escaping */
 524 
 525                                                         int old_slen = s_len, i = 0;
 526                                                         char *old_s = s, *s_ptr;
 527                                                         free_s = s_ptr = s = emalloc(old_slen * 6 + 1);
 528                                                         do {
 529                                                                 if (old_s[i] == '&' || old_s[i] == '"' || old_s[i] == '<') {
 530                                                                         *s_ptr++ = '&';
 531                                                                         switch (old_s[i]) {
 532                                                                                 case '"':
 533                                                                                         s_len += 5;
 534                                                                                         *s_ptr++ = 'q';
 535                                                                                         *s_ptr++ = 'u';
 536                                                                                         *s_ptr++ = 'o';
 537                                                                                         *s_ptr++ = 't';
 538                                                                                         break;
 539                                                                                 case '<':
 540                                                                                         s_len += 3;
 541                                                                                         *s_ptr++ = 'l';
 542                                                                                         *s_ptr++ = 't';
 543                                                                                         break;
 544                                                                                 case '&':
 545                                                                                         s_len += 4;
 546                                                                                         *s_ptr++ = 'a';
 547                                                                                         *s_ptr++ = 'm';
 548                                                                                         *s_ptr++ = 'p';
 549                                                                                         break;
 550                                                                         }
 551                                                                         *s_ptr++ = ';';
 552                                                                 } else {
 553                                                                         *s_ptr++ = old_s[i];
 554                                                                 }
 555                                                         } while (i++ < old_slen);
 556                                                 }
 557                                         } else {
 558                                                 s = S_NULL;
 559                                                 s_len = S_NULL_LEN;
 560                                         }
 561                                         pad_char = ' ';
 562                                         break;
 563 
 564 
 565                                 case 'b':
 566                                         if (escape_xml) {
 567                                                 s = PHPDBG_G(err_buf).xml;
 568                                         } else {
 569                                                 s = PHPDBG_G(err_buf).msg;
 570                                         }
 571 
 572                                         if (s != NULL) {
 573                                                 if (escape_xml) {
 574                                                         s_len = PHPDBG_G(err_buf).xmllen;
 575                                                 } else {
 576                                                         s_len = PHPDBG_G(err_buf).msglen;
 577                                                 }
 578 
 579                                                 if (adjust_precision && precision != s_len) {
 580                                                         s_len = precision;
 581                                                 }
 582                                         } else {
 583                                                 s = "";
 584                                                 s_len = 0;
 585                                         }
 586                                         pad_char = ' ';
 587                                         break;
 588 
 589 
 590                                 case 'r':
 591                                         if (PHPDBG_G(req_id)) {
 592                                                 s_len = spprintf(&s, 0, "req=\"%lu\"", PHPDBG_G(req_id));
 593                                                 free_s = s;
 594                                         } else {
 595                                                 s = "";
 596                                                 s_len = 0;
 597                                         }
 598                                         break;
 599 
 600 
 601                                 case 'f':
 602                                 case 'F':
 603                                 case 'e':
 604                                 case 'E':
 605 
 606                                         switch(modifier) {
 607                                                 case LM_LONG_DOUBLE:
 608                                                         fp_num = (double) va_arg(ap, long double);
 609                                                         break;
 610                                                 case LM_STD:
 611                                                         fp_num = va_arg(ap, double);
 612                                                         break;
 613                                                 default:
 614                                                         goto fmt_error;
 615                                         }
 616 
 617                                         if (zend_isnan(fp_num)) {
 618                                                 s = "NAN";
 619                                                 s_len = 3;
 620                                         } else if (zend_isinf(fp_num)) {
 621                                                 s = "INF";
 622                                                 s_len = 3;
 623                                         } else {
 624 #ifdef HAVE_LOCALE_H
 625                                                 if (!lconv) {
 626                                                         lconv = localeconv();
 627                                                 }
 628 #endif
 629                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
 630                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
 631                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
 632                                                                         &is_negative, &num_buf[1], &s_len);
 633                                                 if (is_negative)
 634                                                         prefix_char = '-';
 635                                                 else if (print_sign)
 636                                                         prefix_char = '+';
 637                                                 else if (print_blank)
 638                                                         prefix_char = ' ';
 639                                         }
 640                                         break;
 641 
 642 
 643                                 case 'g':
 644                                 case 'k':
 645                                 case 'G':
 646                                 case 'H':
 647                                         switch(modifier) {
 648                                                 case LM_LONG_DOUBLE:
 649                                                         fp_num = (double) va_arg(ap, long double);
 650                                                         break;
 651                                                 case LM_STD:
 652                                                         fp_num = va_arg(ap, double);
 653                                                         break;
 654                                                 default:
 655                                                         goto fmt_error;
 656                                         }
 657 
 658                                         if (zend_isnan(fp_num)) {
 659                                                 s = "NAN";
 660                                                 s_len = 3;
 661                                                 break;
 662                                         } else if (zend_isinf(fp_num)) {
 663                                                 if (fp_num > 0) {
 664                                                         s = "INF";
 665                                                         s_len = 3;
 666                                                 } else {
 667                                                         s = "-INF";
 668                                                         s_len = 4;
 669                                                 }
 670                                                 break;
 671                                         }
 672 
 673                                         if (adjust_precision == NO) {
 674                                                 precision = FLOAT_DIGITS;
 675                                         } else if (precision == 0) {
 676                                                 precision = 1;
 677                                         }
 678                                         /*
 679                                          * * We use &num_buf[ 1 ], so that we have room for the sign
 680                                          */
 681 #ifdef HAVE_LOCALE_H
 682                                         if (!lconv) {
 683                                                 lconv = localeconv();
 684                                         }
 685 #endif
 686                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
 687                                         if (*s == '-') {
 688                                                 prefix_char = *s++;
 689                                         } else if (print_sign) {
 690                                                 prefix_char = '+';
 691                                         } else if (print_blank) {
 692                                                 prefix_char = ' ';
 693                                         }
 694 
 695                                         s_len = strlen(s);
 696 
 697                                         if (alternate_form && (strchr(s, '.')) == NULL) {
 698                                                 s[s_len++] = '.';
 699                                         }
 700                                         break;
 701 
 702 
 703                                 case 'c':
 704                                         char_buf[0] = (char) (va_arg(ap, int));
 705                                         s = &char_buf[0];
 706                                         s_len = 1;
 707                                         pad_char = ' ';
 708                                         break;
 709 
 710 
 711                                 case '%':
 712                                         char_buf[0] = '%';
 713                                         s = &char_buf[0];
 714                                         s_len = 1;
 715                                         pad_char = ' ';
 716                                         break;
 717 
 718 
 719                                 case 'n':
 720                                         *(va_arg(ap, int *)) = cc;
 721                                         goto skip_output;
 722 
 723                                         /*
 724                                          * Always extract the argument as a "char *" pointer. We
 725                                          * should be using "void *" but there are still machines
 726                                          * that don't understand it.
 727                                          * If the pointer size is equal to the size of an unsigned
 728                                          * integer we convert the pointer to a hex number, otherwise
 729                                          * we print "%p" to indicate that we don't handle "%p".
 730                                          */
 731                                 case 'p':
 732                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
 733                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
 734                                                 s = ap_php_conv_p2(ui_num, 4, 'x',
 735                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
 736                                                 if (ui_num != 0) {
 737                                                         *--s = 'x';
 738                                                         *--s = '0';
 739                                                         s_len += 2;
 740                                                 }
 741                                         } else {
 742                                                 s = "%p";
 743                                                 s_len = 2;
 744                                         }
 745                                         pad_char = ' ';
 746                                         break;
 747 
 748 
 749                                 case NUL:
 750                                         /*
 751                                          * The last character of the format string was %.
 752                                          * We ignore it.
 753                                          */
 754                                         continue;
 755 
 756 
 757 fmt_error:
 758                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
 759                                         /*
 760                                          * The default case is for unrecognized %'s.
 761                                          * We print %<char> to help the user identify what
 762                                          * option is not understood.
 763                                          * This is also useful in case the user wants to pass
 764                                          * the output of format_converter to another function
 765                                          * that understands some other %<char> (like syslog).
 766                                          * Note that we can't point s inside fmt because the
 767                                          * unknown <char> could be preceded by width etc.
 768                                          */
 769                                 default:
 770                                         char_buf[0] = '%';
 771                                         char_buf[1] = *fmt;
 772                                         s = char_buf;
 773                                         s_len = 2;
 774                                         pad_char = ' ';
 775                                         break;
 776                         }
 777 
 778                         if (prefix_char != NUL) {
 779                                 *--s = prefix_char;
 780                                 s_len++;
 781                         }
 782                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
 783                                 if (pad_char == '0' && prefix_char != NUL) {
 784                                         INS_CHAR(*s, sp, bep, cc)
 785                                                 s++;
 786                                         s_len--;
 787                                         min_width--;
 788                                 }
 789                                 PAD(min_width, s_len, pad_char);
 790                         }
 791                         /*
 792                          * Print the string s.
 793                          */
 794                         for (i = s_len; i != 0; i--) {
 795                                 INS_CHAR(*s, sp, bep, cc);
 796                                 s++;
 797                         }
 798 
 799                         if (adjust_width && adjust == LEFT && min_width > s_len)
 800                                 PAD(min_width, s_len, pad_char);
 801                         if (free_zcopy) {
 802                                 zval_dtor(&zcopy);
 803                         }
 804                 }
 805 skip_output:
 806                 if (free_s) {
 807                         efree(free_s);
 808                         free_s = NULL;
 809                 }
 810 
 811                 fmt++;
 812         }
 813         odp->nextb = sp;
 814         return (cc);
 815 }
 816 
 817 static void strx_printv(int *ccp, char *buf, size_t len, const char *format, zend_bool escape_xml, va_list ap) {
 818         buffy od;
 819         int cc;
 820 
 821         /*
 822          * First initialize the descriptor
 823          * Notice that if no length is given, we initialize buf_end to the
 824          * highest possible address.
 825          */
 826         if (len == 0) {
 827                 od.buf_end = (char *) ~0;
 828                 od.nextb   = (char *) ~0;
 829         } else {
 830                 od.buf_end = &buf[len-1];
 831                 od.nextb   = buf;
 832         }
 833 
 834         /*
 835          * Do the conversion
 836          */
 837         cc = format_converter(&od, format, escape_xml, ap);
 838         if (len != 0 && od.nextb <= od.buf_end) {
 839                 *(od.nextb) = '\0';
 840         }
 841         if (ccp) {
 842                 *ccp = cc;
 843         }
 844 }
 845 
 846 static int phpdbg_xml_vsnprintf(char *buf, size_t len, const char *format, zend_bool escape_xml, va_list ap) {
 847         int cc;
 848 
 849         strx_printv(&cc, buf, len, format, escape_xml, ap);
 850         return (cc);
 851 }
 852 
 853 PHPDBG_API int phpdbg_xml_vasprintf(char **buf, const char *format, zend_bool escape_xml, va_list ap) {
 854         va_list ap2;
 855         int cc;
 856 
 857         va_copy(ap2, ap);
 858         cc = phpdbg_xml_vsnprintf(NULL, 0, format, escape_xml, ap2);
 859         va_end(ap2);
 860 
 861         *buf = NULL;
 862 
 863         if (cc >= 0) {
 864                 if ((*buf = emalloc(++cc)) != NULL) {
 865                         if ((cc = phpdbg_xml_vsnprintf(*buf, cc, format, escape_xml, ap)) < 0) {
 866                                 efree(*buf);
 867                                 *buf = NULL;
 868                         }
 869                 }
 870         }
 871 
 872         return cc;
 873 }
 874 /* copy end */
 875 
 876 PHPDBG_API int _phpdbg_xml_asprintf(char **buf, const char *format, zend_bool escape_xml, ...) {
 877         int ret;
 878         va_list va;
 879 
 880         va_start(va, escape_xml);
 881         ret = phpdbg_xml_vasprintf(buf, format, escape_xml, va);
 882         va_end(va);
 883 
 884         return ret;
 885 }
 886 
 887 PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...) {
 888         int ret;
 889         va_list va;
 890 
 891         va_start(va, format);
 892         ret = phpdbg_xml_vasprintf(buf, format, 0, va);
 893         va_end(va);
 894 
 895         return ret;
 896 }
 897 
 898 static int phpdbg_encode_xml(char **buf, char *msg, int msglen, int from, char *to) {
 899         int i;
 900         int tolen = to ? strlen(to) : 5;
 901         char *tmp = *buf = emalloc(msglen * tolen);
 902         for (i = 0; i++ < msglen; msg++) {
 903                 if (*msg == '&') {
 904                         memcpy(tmp, ZEND_STRL("&amp;"));
 905                         tmp += sizeof("&amp;") - 1;
 906                 } else if (*msg == '<') {
 907                         memcpy(tmp, ZEND_STRL("&lt;"));
 908                         tmp += sizeof("&lt;") - 1;
 909                 } else if (((int) *msg) == from) {
 910                         memcpy(tmp, to, tolen);
 911                         tmp += tolen;
 912                 } else {
 913                         *tmp++ = *msg;
 914                 }
 915         }
 916 
 917         {
 918                 int len = tmp - *buf;
 919                 *buf = erealloc(*buf, len + 1);
 920                 return len;
 921         }
 922 }
 923 
 924 static void phpdbg_encode_ctrl_chars(char **buf, int *buflen) {
 925         char *tmp, *tmpptr;
 926         int len;
 927         int i;
 928 
 929         tmp = tmpptr = emalloc(*buflen * 5);
 930 
 931         for (i = 0; i < *buflen; i++) {
 932                 if ((*buf)[i] < 0x20) {
 933                         *tmpptr++ = '&';
 934                         *tmpptr++ = '#';
 935                         if ((unsigned int) ((*buf)[i]) > 9) {
 936                                 *tmpptr++ = ((*buf)[i] / 10) + '0';
 937                         }
 938                         *tmpptr++ = ((*buf)[i] % 10) + '0';
 939                         *tmpptr++ = ';';
 940                 } else {
 941                         *tmpptr++ = (*buf)[i];
 942                 }
 943         }
 944 
 945         len = tmpptr - tmp;
 946 
 947         efree(*buf);
 948         *buf = erealloc(tmp, len + 1);
 949         *buflen = len;
 950 }
 951 
 952 static int phpdbg_process_print(int fd, int type, const char *tag, const char *msg, int msglen, const char *xml, int xmllen) {
 953         char *msgout = NULL, *buf;
 954         int msgoutlen, xmloutlen, buflen;
 955         const char *severity;
 956 
 957         if ((PHPDBG_G(flags) & PHPDBG_WRITE_XML) && PHPDBG_G(in_script_xml) && PHPDBG_G(in_script_xml) != type) {
 958                 phpdbg_mixed_write(fd, ZEND_STRL("</stream>"));
 959                 PHPDBG_G(in_script_xml) = 0;
 960         }
 961 
 962         switch (type) {
 963                 case P_ERROR:
 964                         severity = "error";
 965                         if (!PHPDBG_G(last_was_newline)) {
 966                                 if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
 967                                         phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>\n" "</phpdbg>"));
 968                                 } else {
 969                                         phpdbg_mixed_write(fd, ZEND_STRL("\n"));
 970                                 }
 971                                 PHPDBG_G(last_was_newline) = 1;
 972                         }
 973                         if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
 974                                 msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_ERROR]->code, msglen, msg);
 975                         } else {
 976                                 msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg);
 977                         }
 978                         break;
 979 
 980                 case P_NOTICE:
 981                         severity = "notice";
 982                         if (!PHPDBG_G(last_was_newline)) {
 983                                 if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
 984                                         phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>\n" "</phpdbg>"));
 985                                 } else {
 986                                         phpdbg_mixed_write(fd, ZEND_STRL("\n"));
 987                                 }
 988                                 PHPDBG_G(last_was_newline) = 1;
 989                         }
 990                         if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
 991                                 msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_NOTICE]->code, msglen, msg);
 992                         } else {
 993                                 msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg);
 994                         }
 995                         break;
 996 
 997                 case P_WRITELN:
 998                         severity = "normal";
 999                         if (msg) {
1000                                 msgoutlen = phpdbg_asprintf(&msgout, "%.*s\n", msglen, msg);
1001                         } else {
1002                                 msgoutlen = 1;
1003                                 msgout = estrdup("\n");
1004                         }
1005                         PHPDBG_G(last_was_newline) = 1;
1006                         break;
1007 
1008                 case P_WRITE:
1009                         severity = "normal";
1010                         if (msg) {
1011                                 msgout = estrndup(msg, msglen);
1012                                 msgoutlen = msglen;
1013                                 PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n';
1014                         } else {
1015                                 msgoutlen = 0;
1016                                 msgout = estrdup("");
1017                         }
1018                         break;
1019 
1020                 case P_STDOUT:
1021                 case P_STDERR:
1022                         if (msg) {
1023                                 PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n';
1024                                 if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1025                                         zend_string *encoded;
1026 
1027                                         if (PHPDBG_G(in_script_xml) != type) {
1028                                                 char *stream_buf;
1029                                                 int stream_buflen = phpdbg_asprintf(&stream_buf, "<stream type=\"%s\">", type == P_STDERR ? "stderr" : "stdout");
1030                                                 phpdbg_mixed_write(fd, stream_buf, stream_buflen);
1031                                                 efree(stream_buf);
1032                                                 PHPDBG_G(in_script_xml) = type;
1033                                         }
1034                                         encoded = php_escape_html_entities((unsigned char *) msg, msglen, 0, ENT_NOQUOTES, PG(internal_encoding) && PG(internal_encoding)[0] ? PG(internal_encoding) : (SG(default_charset) ? SG(default_charset) : "UTF-8"));
1035                                         buflen = ZSTR_LEN(encoded);
1036                                         memcpy(buf = emalloc(buflen + 1), ZSTR_VAL(encoded), buflen);
1037                                         phpdbg_encode_ctrl_chars(&buf, &buflen);
1038                                         phpdbg_mixed_write(fd, buf, buflen);
1039                                         efree(buf);
1040                                 } else {
1041                                         phpdbg_mixed_write(fd, msg, msglen);
1042                                 }
1043                                 return msglen;
1044                         }
1045                 break;
1046 
1047                 /* no formatting on logging output */
1048                 case P_LOG:
1049                         severity = "log";
1050                         if (msg) {
1051                                 struct timeval tp;
1052                                 if (gettimeofday(&tp, NULL) == SUCCESS) {
1053                                         msgoutlen = phpdbg_asprintf(&msgout, "[%ld %.8F]: %.*s\n", tp.tv_sec, tp.tv_usec / 1000000., msglen, msg);
1054                                 } else {
1055                                         msgoutlen = FAILURE;
1056                                 }
1057                         }
1058                         break;
1059         }
1060 
1061         if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1062                 char *xmlout;
1063 
1064                 if (PHPDBG_G(req_id)) {
1065                         char *xmlbuf = NULL;
1066                         xmllen = phpdbg_asprintf(&xmlbuf, "req=\"%lu\" %.*s", PHPDBG_G(req_id), xmllen, xml);
1067                         xml = xmlbuf;
1068                 }
1069                 if (msgout) {
1070                         buflen = phpdbg_encode_xml(&buf, msgout, msgoutlen, '"', "&quot;");
1071                         xmloutlen = phpdbg_asprintf(&xmlout, "<%s severity=\"%s\" %.*s msgout=\"%.*s\" />", tag, severity, xmllen, xml, buflen, buf);
1072 
1073                         efree(buf);
1074                 } else {
1075                         xmloutlen = phpdbg_asprintf(&xmlout, "<%s severity=\"%s\" %.*s msgout=\"\" />", tag, severity, xmllen, xml);
1076                 }
1077 
1078                 phpdbg_encode_ctrl_chars(&xmlout, &xmloutlen);
1079                 phpdbg_eol_convert(&xmlout, &xmloutlen);
1080                 phpdbg_mixed_write(fd, xmlout, xmloutlen);
1081                 efree(xmlout);
1082         } else if (msgout) {
1083                 phpdbg_eol_convert(&msgout, &msgoutlen);
1084                 phpdbg_mixed_write(fd, msgout, msgoutlen);
1085         }
1086 
1087         if (PHPDBG_G(req_id) && (PHPDBG_G(flags) & PHPDBG_WRITE_XML)) {
1088                 efree((char *) xml);
1089         }
1090 
1091         if (msgout) {
1092                 efree(msgout);
1093         }
1094 
1095         return msgout ? msgoutlen : xmloutlen;
1096 } /* }}} */
1097 
1098 PHPDBG_API int phpdbg_vprint(int type, int fd, const char *tag, const char *xmlfmt, const char *strfmt, va_list args) {
1099         char *msg = NULL, *xml = NULL;
1100         int msglen = 0, xmllen = 0;
1101         int len;
1102         va_list argcpy;
1103 
1104         if (strfmt != NULL && strlen(strfmt) > 0L) {
1105                 va_copy(argcpy, args);
1106                 msglen = phpdbg_xml_vasprintf(&msg, strfmt, 0, argcpy);
1107                 va_end(argcpy);
1108         }
1109 
1110         if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1111                 if (xmlfmt != NULL && strlen(xmlfmt) > 0L) {
1112                         va_copy(argcpy, args);
1113                         xmllen = phpdbg_xml_vasprintf(&xml, xmlfmt, 1, argcpy);
1114                         va_end(argcpy);
1115                 } else {
1116                         xml = estrdup("");
1117                 }
1118         }
1119 
1120         if (PHPDBG_G(err_buf).active && type != P_STDOUT && type != P_STDERR) {
1121                 phpdbg_free_err_buf();
1122 
1123                 PHPDBG_G(err_buf).type = type;
1124                 PHPDBG_G(err_buf).fd = fd;
1125                 PHPDBG_G(err_buf).tag = estrdup(tag);
1126                 PHPDBG_G(err_buf).msg = msg;
1127                 PHPDBG_G(err_buf).msglen = msglen;
1128                 if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1129                         PHPDBG_G(err_buf).xml = xml;
1130                         PHPDBG_G(err_buf).xmllen = xmllen;
1131                 }
1132 
1133                 return msglen;
1134         }
1135 
1136         len = phpdbg_process_print(fd, type, tag, msg, msglen, xml, xmllen);
1137 
1138         if (msg) {
1139                 efree(msg);
1140         }
1141 
1142         if (xml) {
1143                 efree(xml);
1144         }
1145 
1146         return len;
1147 }
1148 
1149 PHPDBG_API void phpdbg_free_err_buf(void) {
1150         if (PHPDBG_G(err_buf).type == 0) {
1151                 return;
1152         }
1153 
1154         PHPDBG_G(err_buf).type = 0;
1155 
1156         efree(PHPDBG_G(err_buf).tag);
1157         efree(PHPDBG_G(err_buf).msg);
1158         if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1159                 efree(PHPDBG_G(err_buf).xml);
1160         }
1161 }
1162 
1163 PHPDBG_API void phpdbg_activate_err_buf(zend_bool active) {
1164         PHPDBG_G(err_buf).active = active;
1165 }
1166 
1167 PHPDBG_API int phpdbg_output_err_buf(const char *tag, const char *xmlfmt, const char *strfmt, ...) {
1168         int len;
1169         va_list args;
1170         int errbuf_active = PHPDBG_G(err_buf).active;
1171 
1172         if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
1173                 return 0;
1174         }
1175 
1176         PHPDBG_G(err_buf).active = 0;
1177 
1178         va_start(args, strfmt);
1179         len = phpdbg_vprint(PHPDBG_G(err_buf).type, PHPDBG_G(err_buf).fd, tag ? tag : PHPDBG_G(err_buf).tag, xmlfmt, strfmt, args);
1180         va_end(args);
1181 
1182         PHPDBG_G(err_buf).active = errbuf_active;
1183         phpdbg_free_err_buf();
1184 
1185         return len;
1186 }
1187 
1188 PHPDBG_API int phpdbg_print(int type, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) {
1189         va_list args;
1190         int len;
1191 
1192         if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
1193                 return 0;
1194         }
1195 
1196         va_start(args, strfmt);
1197         len = phpdbg_vprint(type, fd, tag, xmlfmt, strfmt, args);
1198         va_end(args);
1199 
1200         return len;
1201 }
1202 
1203 PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) {
1204         int len = 0;
1205 
1206         if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
1207                 return 0;
1208         }
1209 
1210         if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1211                 va_list args;
1212                 char *buffer;
1213                 int buflen;
1214 
1215                 va_start(args, fmt);
1216                 buflen = phpdbg_xml_vasprintf(&buffer, fmt, 1, args);
1217                 va_end(args);
1218 
1219                 phpdbg_encode_ctrl_chars(&buffer, &buflen);
1220 
1221                 if (PHPDBG_G(in_script_xml)) {
1222                         phpdbg_mixed_write(fd, ZEND_STRL("</stream>"));
1223                         PHPDBG_G(in_script_xml) = 0;
1224                 }
1225 
1226                 len = phpdbg_mixed_write(fd, buffer, buflen);
1227                 efree(buffer);
1228         }
1229 
1230         return len;
1231 }
1232 
1233 PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) {
1234         va_list args;
1235         char *buffer;
1236         int buflen;
1237         int len = 0;
1238 
1239         va_start(args, fmt);
1240         buflen = phpdbg_xml_vasprintf(&buffer, fmt, 0, args);
1241         va_end(args);
1242 
1243         len = phpdbg_mixed_write(fd, buffer, buflen);
1244         efree(buffer);
1245 
1246         return len;
1247 }
1248 
1249 PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) {
1250         va_list args;
1251         char *buffer;
1252         int buflen;
1253         int len = 0;
1254 
1255         if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
1256                 return 0;
1257         }
1258 
1259         va_start(args, fmt);
1260         buflen = phpdbg_xml_vasprintf(&buffer, fmt, 0, args);
1261         va_end(args);
1262 
1263         if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
1264                 char *msg;
1265                 int msglen;
1266 
1267                 msglen = phpdbg_encode_xml(&msg, buffer, buflen, 256, NULL);
1268                 phpdbg_encode_ctrl_chars(&msg, &msglen);
1269                 phpdbg_eol_convert(&msg, &msglen);
1270 
1271                 if (PHPDBG_G(in_script_xml)) {
1272                         phpdbg_mixed_write(fd, ZEND_STRL("</stream>"));
1273                         PHPDBG_G(in_script_xml) = 0;
1274                 }
1275 
1276                 phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>"));
1277                 len = phpdbg_mixed_write(fd, msg, msglen);
1278                 phpdbg_mixed_write(fd, ZEND_STRL("</phpdbg>"));
1279         } else {
1280                 phpdbg_eol_convert(&buffer, &buflen);
1281                 len = phpdbg_mixed_write(fd, buffer, buflen);
1282         }
1283 
1284         efree(buffer);
1285         return len;
1286 }
1287 
1288 
1289 PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) { /* {{{ */
1290         int rc = 0;
1291 
1292         va_list args;
1293         struct timeval tp;
1294 
1295         va_start(args, fmt);
1296         if (gettimeofday(&tp, NULL) == SUCCESS) {
1297                 char friendly[100];
1298                 char *format = NULL, *buffer = NULL, *outbuf = NULL;
1299                 const time_t tt = tp.tv_sec;
1300 
1301 #ifdef PHP_WIN32
1302                 strftime(friendly, 100, "%a %b %d %H.%%04d %Y", localtime(&tt));
1303 #else
1304                 strftime(friendly, 100, "%a %b %d %T.%%04d %Y", localtime(&tt));
1305 #endif
1306                 phpdbg_asprintf(&buffer, friendly, tp.tv_usec/1000);
1307                 phpdbg_asprintf(&format, "[%s]: %s\n", buffer, fmt);
1308                 rc = phpdbg_xml_vasprintf(&outbuf, format, 0, args);
1309 
1310                 if (outbuf) {
1311                         rc = phpdbg_mixed_write(fd, outbuf, rc);
1312                         efree(outbuf);
1313                 }
1314 
1315                 efree(format);
1316                 efree(buffer);
1317         }
1318         va_end(args);
1319 
1320         return rc;
1321 } /* }}} */

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