xref: /PHP-5.4/Zend/zend_highlight.c (revision 3f258e6b)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2014 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 
zend_html_putc(char c)29 ZEND_API void zend_html_putc(char c)
30 {
31 	switch (c) {
32 		case '\n':
33 			ZEND_PUTS("<br />");
34 			break;
35 		case '<':
36 			ZEND_PUTS("&lt;");
37 			break;
38 		case '>':
39 			ZEND_PUTS("&gt;");
40 			break;
41 		case '&':
42 			ZEND_PUTS("&amp;");
43 			break;
44 		case ' ':
45 			ZEND_PUTS("&nbsp;");
46 			break;
47 		case '\t':
48 			ZEND_PUTS("&nbsp;&nbsp;&nbsp;&nbsp;");
49 			break;
50 		default:
51 			ZEND_PUTC(c);
52 			break;
53 	}
54 }
55 
56 
zend_html_puts(const char * s,uint len TSRMLS_DC)57 ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC)
58 {
59 	const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len;
60 	unsigned char *filtered = NULL;
61 	size_t filtered_len;
62 
63 	if (LANG_SCNG(output_filter)) {
64 		LANG_SCNG(output_filter)(&filtered, &filtered_len, ptr, len TSRMLS_CC);
65 		ptr = filtered;
66 		end = filtered + filtered_len;
67 	}
68 
69 	while (ptr<end) {
70 		if (*ptr==' ') {
71 			do {
72 				zend_html_putc(*ptr);
73 			} while ((++ptr < end) && (*ptr==' '));
74 		} else {
75 			zend_html_putc(*ptr++);
76 		}
77 	}
78 
79 	if (LANG_SCNG(output_filter)) {
80 		efree(filtered);
81 	}
82 }
83 
84 
zend_highlight(zend_syntax_highlighter_ini * syntax_highlighter_ini TSRMLS_DC)85 ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC)
86 {
87 	zval token;
88 	int token_type;
89 	char *last_color = syntax_highlighter_ini->highlight_html;
90 	char *next_color;
91 
92 	zend_printf("<code>");
93 	zend_printf("<span style=\"color: %s\">\n", last_color);
94 	/* highlight stuff coming back from zendlex() */
95 	token.type = 0;
96 	while ((token_type=lex_scan(&token TSRMLS_CC))) {
97 		switch (token_type) {
98 			case T_INLINE_HTML:
99 				next_color = syntax_highlighter_ini->highlight_html;
100 				break;
101 			case T_COMMENT:
102 			case T_DOC_COMMENT:
103 				next_color = syntax_highlighter_ini->highlight_comment;
104 				break;
105 			case T_OPEN_TAG:
106 			case T_OPEN_TAG_WITH_ECHO:
107 				next_color = syntax_highlighter_ini->highlight_default;
108 				break;
109 			case T_CLOSE_TAG:
110 				next_color = syntax_highlighter_ini->highlight_default;
111 				break;
112 			case '"':
113 			case T_ENCAPSED_AND_WHITESPACE:
114 			case T_CONSTANT_ENCAPSED_STRING:
115 				next_color = syntax_highlighter_ini->highlight_string;
116 				break;
117 			case T_WHITESPACE:
118 				zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);  /* no color needed */
119 				token.type = 0;
120 				continue;
121 				break;
122 			default:
123 				if (token.type == 0) {
124 					next_color = syntax_highlighter_ini->highlight_keyword;
125 				} else {
126 					next_color = syntax_highlighter_ini->highlight_default;
127 				}
128 				break;
129 		}
130 
131 		if (last_color != next_color) {
132 			if (last_color != syntax_highlighter_ini->highlight_html) {
133 				zend_printf("</span>");
134 			}
135 			last_color = next_color;
136 			if (last_color != syntax_highlighter_ini->highlight_html) {
137 				zend_printf("<span style=\"color: %s\">", last_color);
138 			}
139 		}
140 
141 		zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
142 
143 		if (token.type == IS_STRING) {
144 			switch (token_type) {
145 				case T_OPEN_TAG:
146 				case T_OPEN_TAG_WITH_ECHO:
147 				case T_CLOSE_TAG:
148 				case T_WHITESPACE:
149 				case T_COMMENT:
150 				case T_DOC_COMMENT:
151 					break;
152 				default:
153 					efree(token.value.str.val);
154 					break;
155 			}
156 		} else if (token_type == T_END_HEREDOC) {
157 			efree(token.value.str.val);
158 		}
159 		token.type = 0;
160 	}
161 
162 	if (last_color != syntax_highlighter_ini->highlight_html) {
163 		zend_printf("</span>\n");
164 	}
165 	zend_printf("</span>\n");
166 	zend_printf("</code>");
167 }
168 
zend_strip(TSRMLS_D)169 ZEND_API void zend_strip(TSRMLS_D)
170 {
171 	zval token;
172 	int token_type;
173 	int prev_space = 0;
174 
175 	token.type = 0;
176 	while ((token_type=lex_scan(&token TSRMLS_CC))) {
177 		switch (token_type) {
178 			case T_WHITESPACE:
179 				if (!prev_space) {
180 					zend_write(" ", sizeof(" ") - 1);
181 					prev_space = 1;
182 				}
183 						/* lack of break; is intentional */
184 			case T_COMMENT:
185 			case T_DOC_COMMENT:
186 				token.type = 0;
187 				continue;
188 
189 			case T_END_HEREDOC:
190 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
191 				efree(token.value.str.val);
192 				/* read the following character, either newline or ; */
193 				if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) {
194 					zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
195 				}
196 				zend_write("\n", sizeof("\n") - 1);
197 				prev_space = 1;
198 				token.type = 0;
199 				continue;
200 
201 			default:
202 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
203 				break;
204 		}
205 
206 		if (token.type == IS_STRING) {
207 			switch (token_type) {
208 				case T_OPEN_TAG:
209 				case T_OPEN_TAG_WITH_ECHO:
210 				case T_CLOSE_TAG:
211 				case T_WHITESPACE:
212 				case T_COMMENT:
213 				case T_DOC_COMMENT:
214 					break;
215 
216 				default:
217 					efree(token.value.str.val);
218 					break;
219 			}
220 		}
221 		prev_space = token.type = 0;
222 	}
223 }
224 
225 /*
226  * Local variables:
227  * tab-width: 4
228  * c-basic-offset: 4
229  * indent-tabs-mode: t
230  * End:
231  */
232 
233