Coverage Report

Created: 2026-06-02 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_highlight.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine                                                          |
4
   +----------------------------------------------------------------------+
5
   | Copyright © Zend Technologies Ltd., a subsidiary company of          |
6
   |     Perforce Software, Inc., and Contributors.                       |
7
   +----------------------------------------------------------------------+
8
   | This source file is subject to the Modified BSD License that is      |
9
   | bundled with this package in the file LICENSE, and is available      |
10
   | through the World Wide Web at <https://www.php.net/license/>.        |
11
   |                                                                      |
12
   | SPDX-License-Identifier: BSD-3-Clause                                |
13
   +----------------------------------------------------------------------+
14
   | Authors: Andi Gutmans <andi@php.net>                                 |
15
   |          Zeev Suraski <zeev@php.net>                                 |
16
   +----------------------------------------------------------------------+
17
*/
18
19
#include "zend.h"
20
#include <zend_language_parser.h>
21
#include "zend_compile.h"
22
#include "zend_highlight.h"
23
#include "zend_ptr_stack.h"
24
#include "zend_globals.h"
25
#include "zend_exceptions.h"
26
27
ZEND_API void zend_html_putc(char c)
28
45.7M
{
29
45.7M
  switch (c) {
30
945k
    case '<':
31
945k
      ZEND_PUTS("&lt;");
32
945k
      break;
33
134k
    case '>':
34
134k
      ZEND_PUTS("&gt;");
35
134k
      break;
36
99.8k
    case '&':
37
99.8k
      ZEND_PUTS("&amp;");
38
99.8k
      break;
39
205k
    case '\t':
40
205k
      ZEND_PUTS("    ");
41
205k
      break;
42
44.3M
    default:
43
44.3M
      ZEND_PUTC(c);
44
44.3M
      break;
45
45.7M
  }
46
45.7M
}
47
48
49
ZEND_API void zend_html_puts(const char *s, size_t len)
50
7.89M
{
51
7.89M
  const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len;
52
7.89M
  unsigned char *filtered = NULL;
53
7.89M
  size_t filtered_len;
54
55
7.89M
  if (LANG_SCNG(output_filter)) {
56
0
    LANG_SCNG(output_filter)(&filtered, &filtered_len, ptr, len);
57
0
    ptr = filtered;
58
0
    end = filtered + filtered_len;
59
0
  }
60
61
52.4M
  while (ptr<end) {
62
44.5M
    if (*ptr==' ') {
63
3.39M
      do {
64
3.39M
        zend_html_putc(*ptr);
65
3.39M
      } while ((++ptr < end) && (*ptr==' '));
66
42.3M
    } else {
67
42.3M
      zend_html_putc(*ptr++);
68
42.3M
    }
69
44.5M
  }
70
71
7.89M
  if (LANG_SCNG(output_filter)) {
72
0
    efree(filtered);
73
0
  }
74
7.89M
}
75
76
77
ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini)
78
24.2k
{
79
24.2k
  zval token;
80
24.2k
  int token_type;
81
24.2k
  const char *last_color = syntax_highlighter_ini->highlight_html;
82
24.2k
  const char *next_color;
83
84
24.2k
  zend_printf("<pre><code style=\"color: %s\">", last_color);
85
  /* highlight stuff coming back from zendlex() */
86
7.92M
  while ((token_type=lex_scan(&token, NULL))) {
87
7.89M
    switch (token_type) {
88
29.2k
      case T_INLINE_HTML:
89
29.2k
        next_color = syntax_highlighter_ini->highlight_html;
90
29.2k
        break;
91
64.5k
      case T_COMMENT:
92
67.6k
      case T_DOC_COMMENT:
93
67.6k
        next_color = syntax_highlighter_ini->highlight_comment;
94
67.6k
        break;
95
27.8k
      case T_OPEN_TAG:
96
28.1k
      case T_OPEN_TAG_WITH_ECHO:
97
35.2k
      case T_CLOSE_TAG:
98
35.3k
      case T_LINE:
99
35.4k
      case T_FILE:
100
35.4k
      case T_DIR:
101
35.6k
      case T_TRAIT_C:
102
36.0k
      case T_METHOD_C:
103
36.3k
      case T_FUNC_C:
104
36.3k
      case T_PROPERTY_C:
105
37.5k
      case T_NS_C:
106
37.8k
      case T_CLASS_C:
107
37.8k
        next_color = syntax_highlighter_ini->highlight_default;
108
37.8k
        break;
109
12.2k
      case '"':
110
65.0k
      case T_ENCAPSED_AND_WHITESPACE:
111
197k
      case T_CONSTANT_ENCAPSED_STRING:
112
197k
        next_color = syntax_highlighter_ini->highlight_string;
113
197k
        break;
114
1.17M
      case T_WHITESPACE:
115
1.17M
        zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));  /* no color needed */
116
1.17M
        ZVAL_UNDEF(&token);
117
1.17M
        continue;
118
0
        break;
119
6.39M
      default:
120
6.39M
        if (Z_TYPE(token) == IS_UNDEF) {
121
4.88M
          next_color = syntax_highlighter_ini->highlight_keyword;
122
4.88M
        } else {
123
1.51M
          next_color = syntax_highlighter_ini->highlight_default;
124
1.51M
        }
125
6.39M
        break;
126
7.89M
    }
127
128
6.72M
    if (last_color != next_color) {
129
2.90M
      if (last_color != syntax_highlighter_ini->highlight_html) {
130
2.87M
        zend_printf("</span>");
131
2.87M
      }
132
2.90M
      last_color = next_color;
133
2.90M
      if (last_color != syntax_highlighter_ini->highlight_html) {
134
2.89M
        zend_printf("<span style=\"color: %s\">", last_color);
135
2.89M
      }
136
2.90M
    }
137
138
6.72M
    zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
139
140
6.72M
    if (Z_TYPE(token) == IS_STRING) {
141
1.44M
      switch (token_type) {
142
0
        case T_OPEN_TAG:
143
0
        case T_OPEN_TAG_WITH_ECHO:
144
0
        case T_CLOSE_TAG:
145
0
        case T_WHITESPACE:
146
0
        case T_COMMENT:
147
0
        case T_DOC_COMMENT:
148
0
          break;
149
1.44M
        default:
150
1.44M
          zval_ptr_dtor_str(&token);
151
1.44M
          break;
152
1.44M
      }
153
1.44M
    }
154
6.72M
    ZVAL_UNDEF(&token);
155
6.72M
  }
156
157
24.2k
  if (last_color != syntax_highlighter_ini->highlight_html) {
158
21.1k
    zend_printf("</span>");
159
21.1k
  }
160
24.2k
  zend_printf("</code></pre>");
161
162
  /* Discard parse errors thrown during tokenization */
163
24.2k
  zend_clear_exception();
164
24.2k
}
165
166
ZEND_API void zend_strip(void)
167
0
{
168
0
  zval token;
169
0
  int token_type;
170
0
  int prev_space = 0;
171
172
0
  while ((token_type=lex_scan(&token, NULL))) {
173
0
    switch (token_type) {
174
0
      case T_WHITESPACE:
175
0
        if (!prev_space) {
176
0
          zend_write(" ", sizeof(" ") - 1);
177
0
          prev_space = 1;
178
0
        }
179
0
        ZEND_FALLTHROUGH;
180
0
      case T_COMMENT:
181
0
      case T_DOC_COMMENT:
182
0
        ZVAL_UNDEF(&token);
183
0
        continue;
184
185
0
      case T_END_HEREDOC:
186
0
        zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
187
        /* read the following character, either newline or ; */
188
0
        if (lex_scan(&token, NULL) != T_WHITESPACE) {
189
0
          zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
190
0
        }
191
0
        zend_write("\n", sizeof("\n") - 1);
192
0
        prev_space = 1;
193
0
        ZVAL_UNDEF(&token);
194
0
        continue;
195
196
0
      default:
197
0
        zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
198
0
        break;
199
0
    }
200
201
0
    if (Z_TYPE(token) == IS_STRING) {
202
0
      switch (token_type) {
203
0
        case T_OPEN_TAG:
204
0
        case T_OPEN_TAG_WITH_ECHO:
205
0
        case T_CLOSE_TAG:
206
0
        case T_WHITESPACE:
207
0
        case T_COMMENT:
208
0
        case T_DOC_COMMENT:
209
0
          break;
210
211
0
        default:
212
0
          zval_ptr_dtor_str(&token);
213
0
          break;
214
0
      }
215
0
    }
216
0
    prev_space = 0;
217
0
    ZVAL_UNDEF(&token);
218
0
  }
219
220
  /* Discard parse errors thrown during tokenization */
221
0
  zend_clear_exception();
222
0
}