/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 | 8.37M | { |
29 | 8.37M | switch (c) { |
30 | 187k | case '<': |
31 | 187k | ZEND_PUTS("<"); |
32 | 187k | break; |
33 | 12.8k | case '>': |
34 | 12.8k | ZEND_PUTS(">"); |
35 | 12.8k | break; |
36 | 12.7k | case '&': |
37 | 12.7k | ZEND_PUTS("&"); |
38 | 12.7k | break; |
39 | 30.6k | case '\t': |
40 | 30.6k | ZEND_PUTS(" "); |
41 | 30.6k | break; |
42 | 8.13M | default: |
43 | 8.13M | ZEND_PUTC(c); |
44 | 8.13M | break; |
45 | 8.37M | } |
46 | 8.37M | } |
47 | | |
48 | | |
49 | | ZEND_API void zend_html_puts(const char *s, size_t len) |
50 | 1.47M | { |
51 | 1.47M | const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len; |
52 | 1.47M | unsigned char *filtered = NULL; |
53 | 1.47M | size_t filtered_len; |
54 | | |
55 | 1.47M | 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 | 9.61M | while (ptr<end) { |
62 | 8.13M | if (*ptr==' ') { |
63 | 638k | do { |
64 | 638k | zend_html_putc(*ptr); |
65 | 638k | } while ((++ptr < end) && (*ptr==' ')); |
66 | 7.73M | } else { |
67 | 7.73M | zend_html_putc(*ptr++); |
68 | 7.73M | } |
69 | 8.13M | } |
70 | | |
71 | 1.47M | if (LANG_SCNG(output_filter)) { |
72 | 0 | efree(filtered); |
73 | 0 | } |
74 | 1.47M | } |
75 | | |
76 | | |
77 | | ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini) |
78 | 3.54k | { |
79 | 3.54k | zval token; |
80 | 3.54k | int token_type; |
81 | 3.54k | const char *last_color = syntax_highlighter_ini->highlight_html; |
82 | 3.54k | const char *next_color; |
83 | | |
84 | 3.54k | zend_printf("<pre><code style=\"color: %s\">", last_color); |
85 | | /* highlight stuff coming back from zendlex() */ |
86 | 1.48M | while ((token_type=lex_scan(&token, NULL))) { |
87 | 1.47M | switch (token_type) { |
88 | 4.05k | case T_INLINE_HTML: |
89 | 4.05k | next_color = syntax_highlighter_ini->highlight_html; |
90 | 4.05k | break; |
91 | 43.7k | case T_COMMENT: |
92 | 43.7k | case T_DOC_COMMENT: |
93 | 43.7k | next_color = syntax_highlighter_ini->highlight_comment; |
94 | 43.7k | break; |
95 | 3.65k | case T_OPEN_TAG: |
96 | 3.75k | case T_OPEN_TAG_WITH_ECHO: |
97 | 4.55k | case T_CLOSE_TAG: |
98 | 4.56k | case T_LINE: |
99 | 4.56k | case T_FILE: |
100 | 4.57k | case T_DIR: |
101 | 4.57k | case T_TRAIT_C: |
102 | 4.72k | case T_METHOD_C: |
103 | 4.75k | case T_FUNC_C: |
104 | 4.75k | case T_PROPERTY_C: |
105 | 4.75k | case T_NS_C: |
106 | 4.75k | case T_CLASS_C: |
107 | 4.75k | next_color = syntax_highlighter_ini->highlight_default; |
108 | 4.75k | break; |
109 | 1.27k | case '"': |
110 | 10.2k | case T_ENCAPSED_AND_WHITESPACE: |
111 | 26.5k | case T_CONSTANT_ENCAPSED_STRING: |
112 | 26.5k | next_color = syntax_highlighter_ini->highlight_string; |
113 | 26.5k | break; |
114 | 243k | case T_WHITESPACE: |
115 | 243k | zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); /* no color needed */ |
116 | 243k | ZVAL_UNDEF(&token); |
117 | 243k | continue; |
118 | 0 | break; |
119 | 1.15M | default: |
120 | 1.15M | if (Z_TYPE(token) == IS_UNDEF) { |
121 | 874k | next_color = syntax_highlighter_ini->highlight_keyword; |
122 | 874k | } else { |
123 | 279k | next_color = syntax_highlighter_ini->highlight_default; |
124 | 279k | } |
125 | 1.15M | break; |
126 | 1.47M | } |
127 | | |
128 | 1.23M | if (last_color != next_color) { |
129 | 547k | if (last_color != syntax_highlighter_ini->highlight_html) { |
130 | 543k | zend_printf("</span>"); |
131 | 543k | } |
132 | 547k | last_color = next_color; |
133 | 547k | if (last_color != syntax_highlighter_ini->highlight_html) { |
134 | 546k | zend_printf("<span style=\"color: %s\">", last_color); |
135 | 546k | } |
136 | 547k | } |
137 | | |
138 | 1.23M | zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); |
139 | | |
140 | 1.23M | if (Z_TYPE(token) == IS_STRING) { |
141 | 255k | 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 | 255k | default: |
150 | 255k | zval_ptr_dtor_str(&token); |
151 | 255k | break; |
152 | 255k | } |
153 | 255k | } |
154 | 1.23M | ZVAL_UNDEF(&token); |
155 | 1.23M | } |
156 | | |
157 | 3.54k | if (last_color != syntax_highlighter_ini->highlight_html) { |
158 | 2.97k | zend_printf("</span>"); |
159 | 2.97k | } |
160 | 3.54k | zend_printf("</code></pre>"); |
161 | | |
162 | | /* Discard parse errors thrown during tokenization */ |
163 | 3.54k | zend_clear_exception(); |
164 | 3.54k | } |
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 | } |