Skip to content

Commit 06f072c

Browse files
author
Jani Taskinen
committed
MFH: Improved / fixed output buffering (Michael Wallner)
1 parent f60946e commit 06f072c

File tree

108 files changed

+4041
-3335
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+4041
-3335
lines changed

README.NEW-OUTPUT-API

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
$Id: README.NEW-OUTPUT-API 219039 2006-08-30 07:39:09Z mike $
2+
3+
4+
API adjustment to the old output control code:
5+
6+
Everything now resides beneath the php_output namespace,
7+
and there's an API call for every output handler op.
8+
9+
Checking output control layers status:
10+
// Using OG()
11+
php_output_get_status(TSRMLS_C);
12+
13+
Starting the default output handler:
14+
// php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
15+
php_output_start_default(TSRMLS_C);
16+
17+
Starting an user handler by zval:
18+
// php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC);
19+
php_output_start_user(zhandler, chunk_size, flags TSRMLS_CC);
20+
21+
Starting an internal handler whithout context:
22+
// php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC);
23+
php_output_start_internal(handler_name_zval, my_php_output_handler_func_t, chunk_size, flags TSRMLS_CC);
24+
25+
Starting an internal handler with context:
26+
// not possible with old API
27+
php_output_handler *h;
28+
h = php_output_handler_create_internal(handler_name_zval, my_php_output_handler_context_func_t, chunk_size, flags TSRMLS_CC);
29+
php_output_handler_set_context(h, my_context, my_context_dtor);
30+
php_output_handler_start(h TSRMLS_CC);
31+
32+
Testing whether a certain output handler has already been started:
33+
// php_ob_handler_used("output handler name" TSRMLS_CC);
34+
php_output_handler_started(handler_name_zval TSRMLS_CC);
35+
36+
Flushing one output buffer:
37+
// php_ob_end_buffer(1, 1 TSRMLS_CC);
38+
php_output_flush(TSRMLS_C);
39+
40+
Flushing all output buffers:
41+
// not possible with old API
42+
php_output_flush_all(TSRMLS_C);
43+
44+
Cleaning one output buffer:
45+
// php_ob_end_buffer(0, 1 TSRMLS_CC);
46+
php_output_clean(TSRMLS_C);
47+
48+
Cleaning all output buffers:
49+
// not possible with old API
50+
php_output_clean_all(TSRMLS_C);
51+
52+
Discarding one output buffer:
53+
// php_ob_end_buffer(0, 0 TSRMLS_CC);
54+
php_output_discard(TSRMLS_C);
55+
56+
Discarding all output buffers:
57+
// php_ob_end_buffers(0 TSRMLS_CC);
58+
php_output_discard_all(TSRMLS_C);
59+
60+
Stopping (and dropping) one output buffer:
61+
// php_ob_end_buffer(1, 0 TSRMLS_CC)
62+
php_output_end(TSRMLS_C);
63+
64+
Stopping (and dropping) all output buffers:
65+
// php_ob_end_buffers(1, 0 TSRMLS_CC);
66+
php_output_end_all(TSRMLS_C);
67+
68+
Retrieving output buffers contents:
69+
// php_ob_get_buffer(zstring TSRMLS_CC);
70+
php_output_get_contents(zstring TSRMLS_CC);
71+
72+
Retrieving output buffers length:
73+
// php_ob_get_length(zlength TSRMLS_CC);
74+
php_output_get_length(zlength TSRMLS_CC);
75+
76+
Retrieving output buffering level:
77+
// OG(nesting_level);
78+
php_output_get_level(TSRMLS_C);
79+
80+
Issue a warning because of an output handler conflict:
81+
// php_ob_init_conflict("to be started handler name", "to be tested if already started handler name" TSRMLS_CC);
82+
php_output_handler_conflict(new_handler_name_zval, set_handler_name_zval TSRMLS_CC);
83+
84+
Registering a conflict checking function, which will be checked prior starting the handler:
85+
// not possible with old API, unless hardcoding into output.c
86+
php_output_handler_conflict_register(handler_name_zval, my_php_output_handler_conflict_check_t TSRMLS_CC);
87+
88+
Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler:
89+
// not possible with old API
90+
php_output_handler_reverse_conflict_register(foreign_handler_name_zval, my_php_output_handler_conflict_check_t TSRMLS_CC);
91+
92+
Facilitating a context from within an output handler callable with ob_start():
93+
// not possible with old API
94+
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr TSRMLS_CC);
95+
96+
Disabling of the output handler by itself:
97+
//not possible with old API
98+
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL TSRMLS_CC);
99+
100+
Marking an output handler immutable by itself because of irreversibility of its operation:
101+
// not possible with old API
102+
php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
103+
104+
Restarting the output handler because of a CLEAN operation:
105+
// not possible with old API
106+
if (flags & PHP_OUTPUT_HANDLER_CLEAN) { ... }
107+
108+
Recognizing by the output handler itself if it gets discarded:
109+
// not possible with old API
110+
if ((flags & PHP_OUTPUT_HANDLER_CLEAN) && (flags & PHP_OUTPUT_HANDLER_FINAL)) { ... }
111+
112+
113+
Output handler hooks
114+
115+
The output handler can change its abilities at runtime. Eg. the gz handler can
116+
remove the CLEANABLE and REMOVABLE bits when the first output has passed through it;
117+
or handlers implemented in C to be used with ob_start() can contain a non-global
118+
context:
119+
PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ
120+
pass a void*** pointer as second arg to receive the address of a pointer
121+
pointer to the opaque field of the output handler context
122+
PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS
123+
pass a int* pointer as second arg to receive the flags set for the output handler
124+
PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL
125+
pass a int* pointer as second arg to receive the level of this output handler
126+
(starts with 0)
127+
PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE
128+
the second arg is ignored; marks the output handler to be neither cleanable
129+
nor removable
130+
PHP_OUTPUT_HANDLER_HOOK_DISABLE
131+
the second arg is ignored; marks the output handler as disabled
132+
133+
134+
Open questions
135+
136+
Should the userland API be adjusted and unified?
137+
138+
Many bits of the manual (and very first implementation) do not comply
139+
with the behaviour of the current (to be obsoleted) code, thus should
140+
the manual or the behaviour be adjusted?
141+
142+
END

Zend/zend_highlight.c

+23-22
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "zend_ptr_stack.h"
2727
#include "zend_globals.h"
2828

29-
ZEND_API void zend_html_putc(char c)
29+
ZEND_API void zend_html_putc(char c) /* {{{ */
3030
{
3131
switch (c) {
3232
case '\n':
@@ -52,9 +52,9 @@ ZEND_API void zend_html_putc(char c)
5252
break;
5353
}
5454
}
55+
/* }}} */
5556

56-
57-
ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC)
57+
ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) /* {{{ */
5858
{
5959
const char *ptr=s, *end=s+len;
6060

@@ -85,9 +85,9 @@ ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC)
8585
}
8686
#endif /* ZEND_MULTIBYTE */
8787
}
88+
/* }}} */
8889

89-
90-
ZEND_API void 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) /* {{{ */
9191
{
9292
zval token;
9393
int token_type;
@@ -97,7 +97,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
9797
zend_printf("<code>");
9898
zend_printf("<span style=\"color: %s\">\n", last_color);
9999
/* highlight stuff coming back from zendlex() */
100-
token.type = 0;
100+
Z_TYPE(token) = 0;
101101
while ((token_type=lex_scan(&token TSRMLS_CC))) {
102102
switch (token_type) {
103103
case T_INLINE_HTML:
@@ -121,11 +121,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
121121
break;
122122
case T_WHITESPACE:
123123
zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */
124-
token.type = 0;
124+
Z_TYPE(token) = 0;
125125
continue;
126126
break;
127127
default:
128-
if (token.type == 0) {
128+
if (Z_TYPE(token) == 0) {
129129
next_color = syntax_highlighter_ini->highlight_keyword;
130130
} else {
131131
next_color = syntax_highlighter_ini->highlight_default;
@@ -145,7 +145,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
145145

146146
zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
147147

148-
if (token.type == IS_STRING) {
148+
if (Z_TYPE(token) == IS_STRING) {
149149
switch (token_type) {
150150
case T_OPEN_TAG:
151151
case T_OPEN_TAG_WITH_ECHO:
@@ -155,13 +155,13 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
155155
case T_DOC_COMMENT:
156156
break;
157157
default:
158-
efree(token.value.str.val);
158+
efree(Z_STRVAL(token));
159159
break;
160160
}
161161
} else if (token_type == T_END_HEREDOC) {
162-
efree(token.value.str.val);
162+
efree(Z_STRVAL(token));
163163
}
164-
token.type = 0;
164+
Z_TYPE(token) = 0;
165165
}
166166

167167
if (last_color != syntax_highlighter_ini->highlight_html) {
@@ -170,14 +170,15 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
170170
zend_printf("</span>\n");
171171
zend_printf("</code>");
172172
}
173+
/* }}} */
173174

174-
ZEND_API void zend_strip(TSRMLS_D)
175+
ZEND_API void zend_strip(TSRMLS_D) /* {{{ */
175176
{
176177
zval token;
177178
int token_type;
178179
int prev_space = 0;
179180

180-
token.type = 0;
181+
Z_TYPE(token) = 0;
181182
while ((token_type=lex_scan(&token TSRMLS_CC))) {
182183
switch (token_type) {
183184
case T_WHITESPACE:
@@ -188,27 +189,27 @@ ZEND_API void zend_strip(TSRMLS_D)
188189
/* lack of break; is intentional */
189190
case T_COMMENT:
190191
case T_DOC_COMMENT:
191-
token.type = 0;
192+
Z_TYPE(token) = 0;
192193
continue;
193-
194+
194195
case T_END_HEREDOC:
195196
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
196-
efree(token.value.str.val);
197+
efree(Z_STRVAL(token));
197198
/* read the following character, either newline or ; */
198199
if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) {
199200
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
200201
}
201202
zend_write("\n", sizeof("\n") - 1);
202203
prev_space = 1;
203-
token.type = 0;
204+
Z_TYPE(token) = 0;
204205
continue;
205206

206207
default:
207208
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
208209
break;
209210
}
210211

211-
if (token.type == IS_STRING) {
212+
if (Z_TYPE(token) == IS_STRING) {
212213
switch (token_type) {
213214
case T_OPEN_TAG:
214215
case T_OPEN_TAG_WITH_ECHO:
@@ -219,13 +220,14 @@ ZEND_API void zend_strip(TSRMLS_D)
219220
break;
220221

221222
default:
222-
efree(token.value.str.val);
223+
efree(Z_STRVAL(token));
223224
break;
224225
}
225226
}
226-
prev_space = token.type = 0;
227+
prev_space = Z_TYPE(token) = 0;
227228
}
228229
}
230+
/* }}} */
229231

230232
/*
231233
* Local variables:
@@ -234,4 +236,3 @@ ZEND_API void zend_strip(TSRMLS_D)
234236
* indent-tabs-mode: t
235237
* End:
236238
*/
237-

Zend/zend_indent.c

+14-14
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@
3030
#define zendtext LANG_SCNG(yy_text)
3131
#define zendleng LANG_SCNG(yy_leng)
3232

33-
34-
static void handle_whitespace(int *emit_whitespace)
33+
static void handle_whitespace(unsigned int *emit_whitespace) /* {{{ */
3534
{
3635
unsigned char c;
37-
int i;
36+
unsigned int i;
3837

3938
for (c=0; c<128; c++) {
4039
if (emit_whitespace[c]>0) {
@@ -45,29 +44,29 @@ static void handle_whitespace(int *emit_whitespace)
4544
}
4645
memset(emit_whitespace, 0, sizeof(int)*256);
4746
}
47+
/* }}} */
4848

49-
50-
ZEND_API void zend_indent()
49+
ZEND_API void zend_indent(void) /* {{{ */
5150
{
5251
zval token;
5352
int token_type;
5453
int in_string=0;
55-
int nest_level=0;
56-
int emit_whitespace[256];
57-
int i;
54+
unsigned int nest_level=0;
55+
unsigned int emit_whitespace[256];
56+
unsigned int i;
5857
TSRMLS_FETCH();
5958

6059
memset(emit_whitespace, 0, sizeof(int)*256);
6160

6261
/* highlight stuff coming back from zendlex() */
63-
token.type = 0;
62+
Z_TYPE(token) = 0;
6463
while ((token_type=lex_scan(&token TSRMLS_CC))) {
6564
switch (token_type) {
6665
case T_INLINE_HTML:
6766
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
6867
break;
6968
case T_WHITESPACE: {
70-
token.type = 0;
69+
Z_TYPE(token) = 0;
7170
/* eat whitespace, emit newlines */
7271
for (i=0; i<LANG_SCNG(yy_leng); i++) {
7372
emit_whitespace[(unsigned char) LANG_SCNG(yy_text)[i]]++;
@@ -79,7 +78,7 @@ ZEND_API void zend_indent()
7978
in_string = !in_string;
8079
/* break missing intentionally */
8180
default:
82-
if (token.type==0) {
81+
if (Z_TYPE(token)==0) {
8382
/* keyword */
8483
switch (token_type) {
8584
case ',':
@@ -132,20 +131,21 @@ ZEND_API void zend_indent()
132131
}
133132
break;
134133
}
135-
if (token.type == IS_STRING) {
134+
if (Z_TYPE(token) == IS_STRING) {
136135
switch (token_type) {
137136
case T_OPEN_TAG:
138137
case T_CLOSE_TAG:
139138
case T_WHITESPACE:
140139
break;
141140
default:
142-
efree(token.value.str.val);
141+
efree(Z_STRVAL(token));
143142
break;
144143
}
145144
}
146-
token.type = 0;
145+
Z_TYPE(token) = 0;
147146
}
148147
}
148+
/* }}} */
149149

150150
/*
151151
* Local variables:

0 commit comments

Comments
 (0)