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
29ZEND_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
57ZEND_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
90ZEND_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
174ZEND_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