xref: /PHP-5.5/Zend/zend_highlight.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2015 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 		}
157 		token.type = 0;
158 	}
159 
160 	if (last_color != syntax_highlighter_ini->highlight_html) {
161 		zend_printf("</span>\n");
162 	}
163 	zend_printf("</span>\n");
164 	zend_printf("</code>");
165 }
166 
zend_strip(TSRMLS_D)167 ZEND_API void zend_strip(TSRMLS_D)
168 {
169 	zval token;
170 	int token_type;
171 	int prev_space = 0;
172 
173 	token.type = 0;
174 	while ((token_type=lex_scan(&token TSRMLS_CC))) {
175 		switch (token_type) {
176 			case T_WHITESPACE:
177 				if (!prev_space) {
178 					zend_write(" ", sizeof(" ") - 1);
179 					prev_space = 1;
180 				}
181 						/* lack of break; is intentional */
182 			case T_COMMENT:
183 			case T_DOC_COMMENT:
184 				token.type = 0;
185 				continue;
186 
187 			case T_END_HEREDOC:
188 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
189 				/* read the following character, either newline or ; */
190 				if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) {
191 					zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
192 				}
193 				zend_write("\n", sizeof("\n") - 1);
194 				prev_space = 1;
195 				token.type = 0;
196 				continue;
197 
198 			default:
199 				zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
200 				break;
201 		}
202 
203 		if (token.type == IS_STRING) {
204 			switch (token_type) {
205 				case T_OPEN_TAG:
206 				case T_OPEN_TAG_WITH_ECHO:
207 				case T_CLOSE_TAG:
208 				case T_WHITESPACE:
209 				case T_COMMENT:
210 				case T_DOC_COMMENT:
211 					break;
212 
213 				default:
214 					efree(token.value.str.val);
215 					break;
216 			}
217 		}
218 		prev_space = token.type = 0;
219 	}
220 }
221 
222 /*
223  * Local variables:
224  * tab-width: 4
225  * c-basic-offset: 4
226  * indent-tabs-mode: t
227  * End:
228  */
229 
230