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