xref: /PHP-7.0/Zend/zend_highlight.c (revision 478f119a)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2017 Zend Technologies Ltd. (http://www.zend.com) |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #include "zend.h"
23 #include <zend_language_parser.h>
24 #include "zend_compile.h"
25 #include "zend_highlight.h"
26 #include "zend_ptr_stack.h"
27 #include "zend_globals.h"
28 #include "zend_exceptions.h"
29 
zend_html_putc(char c)30 ZEND_API void zend_html_putc(char c)
31 {
32 	switch (c) {
33 		case '\n':
34 			ZEND_PUTS("<br />");
35 			break;
36 		case '<':
37 			ZEND_PUTS("&lt;");
38 			break;
39 		case '>':
40 			ZEND_PUTS("&gt;");
41 			break;
42 		case '&':
43 			ZEND_PUTS("&amp;");
44 			break;
45 		case ' ':
46 			ZEND_PUTS("&nbsp;");
47 			break;
48 		case '\t':
49 			ZEND_PUTS("&nbsp;&nbsp;&nbsp;&nbsp;");
50 			break;
51 		default:
52 			ZEND_PUTC(c);
53 			break;
54 	}
55 }
56 
57 
zend_html_puts(const char * s,size_t len)58 ZEND_API void zend_html_puts(const char *s, size_t len)
59 {
60 	const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len;
61 	unsigned char *filtered = NULL;
62 	size_t filtered_len;
63 
64 	if (LANG_SCNG(output_filter)) {
65 		LANG_SCNG(output_filter)(&filtered, &filtered_len, ptr, len);
66 		ptr = filtered;
67 		end = filtered + filtered_len;
68 	}
69 
70 	while (ptr<end) {
71 		if (*ptr==' ') {
72 			do {
73 				zend_html_putc(*ptr);
74 			} while ((++ptr < end) && (*ptr==' '));
75 		} else {
76 			zend_html_putc(*ptr++);
77 		}
78 	}
79 
80 	if (LANG_SCNG(output_filter)) {
81 		efree(filtered);
82 	}
83 }
84 
85 
zend_highlight(zend_syntax_highlighter_ini * syntax_highlighter_ini)86 ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini)
87 {
88 	zval token;
89 	int token_type;
90 	char *last_color = syntax_highlighter_ini->highlight_html;
91 	char *next_color;
92 
93 	zend_printf("<code>");
94 	zend_printf("<span style=\"color: %s\">\n", last_color);
95 	/* highlight stuff coming back from zendlex() */
96 	ZVAL_UNDEF(&token);
97 	while ((token_type=lex_scan(&token))) {
98 		switch (token_type) {
99 			case T_INLINE_HTML:
100 				next_color = syntax_highlighter_ini->highlight_html;
101 				break;
102 			case T_COMMENT:
103 			case T_DOC_COMMENT:
104 				next_color = syntax_highlighter_ini->highlight_comment;
105 				break;
106 			case T_OPEN_TAG:
107 			case T_OPEN_TAG_WITH_ECHO:
108 			case T_CLOSE_TAG:
109 			case T_LINE:
110 			case T_FILE:
111 			case T_DIR:
112 			case T_TRAIT_C:
113 			case T_METHOD_C:
114 			case T_FUNC_C:
115 			case T_NS_C:
116 			case T_CLASS_C:
117 				next_color = syntax_highlighter_ini->highlight_default;
118 				break;
119 			case '"':
120 			case T_ENCAPSED_AND_WHITESPACE:
121 			case T_CONSTANT_ENCAPSED_STRING:
122 				next_color = syntax_highlighter_ini->highlight_string;
123 				break;
124 			case T_WHITESPACE:
125 				zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));  /* no color needed */
126 				ZVAL_UNDEF(&token);
127 				continue;
128 				break;
129 			default:
130 				if (Z_TYPE(token) == IS_UNDEF) {
131 					next_color = syntax_highlighter_ini->highlight_keyword;
132 				} else {
133 					next_color = syntax_highlighter_ini->highlight_default;
134 				}
135 				break;
136 		}
137 
138 		if (last_color != next_color) {
139 			if (last_color != syntax_highlighter_ini->highlight_html) {
140 				zend_printf("</span>");
141 			}
142 			last_color = next_color;
143 			if (last_color != syntax_highlighter_ini->highlight_html) {
144 				zend_printf("<span style=\"color: %s\">", last_color);
145 			}
146 		}
147 
148 		zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
149 
150 		if (Z_TYPE(token) == IS_STRING) {
151 			switch (token_type) {
152 				case T_OPEN_TAG:
153 				case T_OPEN_TAG_WITH_ECHO:
154 				case T_CLOSE_TAG:
155 				case T_WHITESPACE:
156 				case T_COMMENT:
157 				case T_DOC_COMMENT:
158 					break;
159 				default:
160 					zend_string_release(Z_STR(token));
161 					break;
162 			}
163 		}
164 		ZVAL_UNDEF(&token);
165 	}
166 
167 	if (last_color != syntax_highlighter_ini->highlight_html) {
168 		zend_printf("</span>\n");
169 	}
170 	zend_printf("</span>\n");
171 	zend_printf("</code>");
172 
173 	/* Discard parse errors thrown during tokenization */
174 	zend_clear_exception();
175 }
176 
zend_strip(void)177 ZEND_API void zend_strip(void)
178 {
179 	zval token;
180 	int token_type;
181 	int prev_space = 0;
182 
183 	ZVAL_UNDEF(&token);
184 	while ((token_type=lex_scan(&token))) {
185 		switch (token_type) {
186 			case T_WHITESPACE:
187 				if (!prev_space) {
188 					zend_write(" ", sizeof(" ") - 1);
189 					prev_space = 1;
190 				}
191 						/* lack of break; is intentional */
192 			case T_COMMENT:
193 			case T_DOC_COMMENT:
194 				ZVAL_UNDEF(&token);
195 				continue;
196 
197 			case T_END_HEREDOC:
198 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
199 				/* read the following character, either newline or ; */
200 				if (lex_scan(&token) != T_WHITESPACE) {
201 					zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
202 				}
203 				zend_write("\n", sizeof("\n") - 1);
204 				prev_space = 1;
205 				ZVAL_UNDEF(&token);
206 				continue;
207 
208 			default:
209 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
210 				break;
211 		}
212 
213 		if (Z_TYPE(token) == IS_STRING) {
214 			switch (token_type) {
215 				case T_OPEN_TAG:
216 				case T_OPEN_TAG_WITH_ECHO:
217 				case T_CLOSE_TAG:
218 				case T_WHITESPACE:
219 				case T_COMMENT:
220 				case T_DOC_COMMENT:
221 					break;
222 
223 				default:
224 					zend_string_release(Z_STR(token));
225 					break;
226 			}
227 		}
228 		prev_space = 0;
229 		ZVAL_UNDEF(&token);
230 	}
231 
232 	/* Discard parse errors thrown during tokenization */
233 	zend_clear_exception();
234 }
235 
236 /*
237  * Local variables:
238  * tab-width: 4
239  * c-basic-offset: 4
240  * indent-tabs-mode: t
241  * End:
242  */
243 
244