PHP рдореЗрдВ рд╕рдЬреНрдЬрд╛рдХрд╛рд░ред рд╡рд┐рд╕реНрддрд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди

рдкрд╣рд▓реЗ рд▓реЗрдЦ рдореЗрдВ рд╕рд░реНрд╡реЗрдХреНрд╖рдг рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдореМрдЬреВрджрд╛ рдЖрдИрдбреАрдИ рдХреЛ рдЦреБрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдереЛрдбрд╝рд╛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рд╢рд╛рдпрдж рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдкрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдЧрдИ рдереАред
рдпрд╣ рдЕрднреА рддрдХ рдПрдХ рдФрд░ рд╣реИрд▓реЛ-рд╡рд░реНрд▓реНрдб-рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд▓реЗрдЦ рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЬреЛ рд▓реЛрдЧ рдореВрд▓ рдмрд╛рддреЗрдВ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡реЗ рдЖрд╕рд╛рдиреА рд╕реЗ Habr├й рдкрд░ рдФрд░ рд░реВрд╕реА-рднрд╛рд╖рд╛ RTFG рджреЛрдиреЛрдВ рдкрд░ рдмрд╣реБрдд рд╕рд╛рд░реА рд╕рд╛рдордЧреНрд░реА рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдкреВрд░реНрд╡рд╛рдкреЗрдХреНрд╖рд╛рдПрдБ, рдмрд┐рдХреНрд░реА рдФрд░ рдиреБрдХрд╕рд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦред рдпрд╣ рдереЛрдбрд╝рд╛ PHP рд╣реЛрдЧрд╛, рдЬреНрдпрд╛рджрд╛рддрд░ рд╕реАред


рдЖрд╡рд╢реНрдпрдХ рд╢рд░реНрддреЗрдВ


рдпрджрд┐ рдЖрдк tl; dr рдкрдврд╝рдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рддреБрд░рдВрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдореИрдВ рджреВрд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реВрдБрдЧрд╛
рдореБрдЭреЗ рдкрд╛рдпрдерди рдкрд╕рдВрдж рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд╕рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдореЗрдВ рдХреБрдЫ рдмрд┐рдВрджреБред рдФрд░ рдЬрдм рд╕реЗ рдореИрдВ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдкреАрдПрдЪрдкреА рдореЗрдВ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реВрдВ, рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЙрдкрдХрд░рдг рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдФрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реЛред рд╣рд╛рд▓ рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ PHP рдХрд╛рдлреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╣реА рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдЕрднреА рднреА рдЧрд╛рдпрдм рд╣реИрдВред рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рд╕рдм рдХреБрдЫ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рдореЗрдВ рд▓реЗрдирд╛ рд╣реЛрдЧрд╛ред рдкрд╣рд▓реЗ рдореБрдЦреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╛рдо рдФрд░ рдкрд╛рд╕рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХреАрдХрд░рдг рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдерд╛ ( рдореЗрд░рд╛ рдПрдХ рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░ , рдЬреЛ рдЕрднреА рднреА рдПрдХ рд╡рд┐рдЪрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рдЪрд░рдг рдореЗрдВ рд╣реИред рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рдореИрдВ рдЗрд╕рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реВрдВ ), рдЕрдм рдпрд╣рд╛рдВ рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдФрд░ рдХреБрдЫ рдЕрдиреНрдп рд╡рд┐рдХрд╛рд╕ рд╣реИрдВред

рдлрдВрдХреНрд╢рди рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕ (рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдпрд╣рд╛рдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╕рдЬрд╛рд╡рдЯ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИрдВ) рдЖрдкрдХреЛ рддрд░реНрдХ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░рдд рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рдХреЙрд▓ рдХреЛ рд▓рдкреЗрдЯрддреЗ рд╣реБрдП, рдмрд╛рдж рдХреЗ рдХрд╛рдо рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред рдШреЛрд╖рдгрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рд░реИрдкрд░ рдХреА рдПрдХ рд╕реВрдЪреА рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдЕрдВрддрддрдГ рдХреБрдЫ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдореВрд▓ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдмрджрд▓ рджреЗрдЧрд╛ред рдЕрдЬрдЧрд░ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдореЗрдВ рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд┐рд▓рддреЗ рд╣реИрдВ:
@decomaker(argA, argB, ...) def func(arg1, arg2, ...): # ... # : func = decomaker(argA, argB, ...)(func) 

PHP рдореЗрдВ рдРрд╕реА рдХреЛрдИ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдЗрд╕ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЛ рд▓реЗрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдмрджрд▓рд╛рд╡ рдХреЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ (рдЬрдм рдмреБрд▓рд╛рдпрд╛ рдбреЗрдХреЛрд░реЗрдЯрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдЙрд╕ рдкрд░ рдФрд░ рдЕрдзрд┐рдХ)ред рдкрд╣рд▓рд╛ рд▓реЗрдЦ рдмрд┐рд▓реНрдХреБрд▓ рдЗрд╕реА рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рд┐рдВрдЯреИрдХреНрд╕-рдЪреЗрдХрд┐рдВрдЧ рдЖрдИрдбреАрдИ рдФрд░ рджреЛ рдХрдореЗрдВрдЯреЗрдЯрд░ рд╢рд┐рд╡рд┐рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдиреЗ рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд░ рджрд┐рдпрд╛ред рдирддреАрдЬрддрди, рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЛ рдЕрдзрд┐рдХ рдкреЛрд░реНрдЯреЗрдмрд▓ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдм рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рд╡рд░реНрдгрди рдПрдХрд▓-рдкрдВрдХреНрддрд┐ рдЯрд┐рдкреНрдкрдгреА # рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

рд╡рд┐рд╡рд░рдг рдкреНрд░рд╛рд░реВрдк рдкрд░ рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдпрд╣ рддрдп рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдЦреБрдж рдХреИрд╕реЗ рд▓рд╛рдЧреВ рд╣реЛрдВрдЧреЗред рдбреЗрдХреЛрд░реЗрдЯрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдореВрд▓ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдмрджрд▓рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдБ рдЕрдирд╛рдо рдХрд╛рд░реНрдп рдФрд░ рдХреНрд▓реЛрдЬрд░ рдХрд╛рдо рдЖрддреЗ рд╣реИрдВ:
рдХреБрдЫ php рдХреЛрдб
 <?php function decor($func) { echo "Decorator!\n"; return function () use($func) { return call_user_func_array($func, func_get_args()); }; } function a($v) { var_dump($v); } $b = decor('a'); $b(42); /* : Decorator! int(42) */ 

PHP рдореЗрдВ, рдПрдХ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдЬреЛ рдЗрд╕реЗ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рд╣реИ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдХреНрд░рд┐рдпрд╛ рд╣реИ, рдЗрд╕реЗ рджреВрд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдкрд░рд┐рдгрд╛рдо рд▓реЗрдЦ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЫрд╡рд┐ рд╕реЗ рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рд╣реИ:
 <?php function decor($func) { return function(){} } # @decor function original() { // ... } 

рдФрд░ рдореИрдВ рдЗрд╕реЗ Zend рдХреЗ lexer рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рддрд╛рдХрд┐ рдЖрдкрдХреЛ PHP рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдирд╛ рди рдкрдбрд╝реЗ (рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдЗрд╕реЗ рд╕реНрдкрд░реНрд╢ рди рдХрд░реЗрдВ )ред


рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдпреЛрдЬрдирд╛ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рджреЛ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ:

рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк рдУрдкреЗрдХ рдХреИрд╢ рдФрд░ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рдХреЗ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдВрджрд┐рдЧреНрдз рд▓рдЧ рд░рд╣рд╛ рдерд╛ред рдФрд░ рдбреЗрдХреЛрд░реЗрдЯрд░ рд╕рд┐рдВрдЯреИрдХреНрд╕ (# рдЯрд┐рдкреНрдкрдгреА рдХреЗ рдмрд┐рдирд╛) рдХрд╛ рдореВрд▓ рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред
рдкрд╣рд▓рд╛ рд╡рд┐рдХрд▓реНрдк рдЪреБрдирд╛ рдЧрдпрд╛ рдерд╛ред
Zend рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рд░рд╛рдЬрд╕реНрд╡ рдХреЗ рджреЛ рд╕реНрд░реЛрдд рд╣реИрдВ:

рджреЛрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдХреЗрдд рд╣реИрдВред рдорд╛рдирдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди zend_startup рдореЗрдВ рд╢реБрд░реБрдЖрддреА рдмрд┐рдВрджреБрдУрдВ рдХреЛ рджреЗрдЦрдХрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

рджреЛрдиреЛрдВ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рд░реВрдк рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ _zend_op_array рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдУрдкрдХреЛрдб рдХреА рдПрдХ рд╕рд░рдгреА рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕рдорд╛рдирддрд╛ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдЙрдирдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЕрд▓рдЧ рд╣реИред рдЗрд╕рд▓рд┐рдП рд╣рдо рджреЛрдиреЛрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░реЗрдВрдЧреЗред

Zend рдФрд░ PHP рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдореЗрдВ рдРрд╕реЗ рдлрдВрдХреНрд╢рди рдкреЙрдЗрдВрдЯрд░реНрд╕ рдкрд░ рдкреНрд░рднрд╛рд╡ рд╕реНрдЯреНрд░реАрдо рдкрд░ рдбрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ZendAccelerator рдФрд░ Phar рдореЗрдВ рд╕рдорд╛рди zend_compile_file рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдпрд╣ рддреГрддреАрдп-рдкрдХреНрд╖ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреА рдЧрдгрдирд╛ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рдПрдирд╛рд▓реЙрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдореВрд▓ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рд╕реВрдЪрдХ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕рдм рдХреБрдЫ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рд╣реИред
рдЖрдкрдХреЛ рдирд┐рдореНрди рдЬреИрд╕рд╛ рдХреБрдЫ рдорд┐рд▓рддрд╛ рд╣реИ
 PHP_MINIT_FUNCTION(decorators); PHP_MSHUTDOWN_FUNCTION(decorators); zend_module_entry decorators_module_entry = { // ... decorators_functions, PHP_MINIT(decorators), PHP_MSHUTDOWN(decorators), // ... }; zend_op_array *(*decorators_orig_zend_compile_string)(zval *source_string, char *filename TSRMLS_DC); zend_op_array *(*decorators_orig_zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); zend_op_array* decorators_zend_compile_string(zval *source_string, char *filename TSRMLS_DC); zend_op_array* decorators_zend_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(decorators) { decorators_orig_zend_compile_string = zend_compile_string; zend_compile_string = decorators_zend_compile_string; decorators_orig_zend_compile_file = zend_compile_file; zend_compile_file = decorators_zend_compile_file; return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(decorators) { zend_compile_string = decorators_orig_zend_compile_string; zend_compile_file = decorators_orig_zend_compile_file; return SUCCESS; } /* }}} */ zend_op_array* decorators_zend_compile_string(zval *source_string, char *filename TSRMLS_DC) /* {{{ */ { return decorators_orig_zend_compile_string(source_string, filename TSRMLS_CC); } /* }}} */ zend_op_array* decorators_zend_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */ { return decorators_orig_zend_compile_file(file_handle, type TSRMLS_CC); } /* }}} */ 

рдЬрдм рдореЙрдбреНрдпреВрд▓ (рд╣рдорд╛рд░реЗ рд╡рд┐рд╕реНрддрд╛рд░) рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдХрд╛рдо рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, рд╡реЗ рд╕рдм рдХреБрдЫ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓реЗред рд╕реАрдзреЗ рдмрджрд▓реЗ рд╣реБрдП рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ, рд╣рдо рдореВрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╣рддреЗ рд╣реИрдВред
рдореЙрдбреНрдпреВрд▓ рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдХрд╛рдлреА рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред

рдФрд░ рдпрджрд┐ рдХрдВрдкрд╛рдЗрд▓_рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдЗрдирдкреБрдЯ рд▓рд╛рдЗрди рдореЗрдВ рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП) рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдХрдо рдпрд╛ рдЬреНрдпрд╛рджрд╛ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рддреЛ рдХрдВрдкрд╛рдЗрд▓_рдлрд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд░рд╕рд╛рддреНрдордХ рдирд╣реАрдВ рд╣реИ - рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реНрд░реЛрдд рдирд╣реАрдВ рд╣реИ, рдХреЗрд╡рд▓ zend_file_handle рдореЗрдВ рд╕реНрд░реЛрдд рдХрд╛ рд╡рд┐рд╡рд░рдг рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рднрд┐рдиреНрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЦреЗрддреЛрдВ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╕реЗрдЯреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╕реНрд░реЛрдд рдХрд╛ рдкреНрд░рддреНрдпрдХреНрд╖ рдкрдврд╝рдирд╛ рдХрд╛рдлреА рджреВрд░ рджрдлрди рд╣реИ
 ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { // ... open_file_for_scanning(file_handle TSRMLS_CC) // ... } ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC) { // ... zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) // ... } 

рдФрд░ рдпрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд zend_stream_fixup рд╣реИ , рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЗ рдЗрдирдкреБрдЯ рдХреЗ рд╕рднреА рд╕реНрд░реЛрддреЛрдВ рдХреЛ рдПрдХрдЬреБрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдПрдХ рд░реАрдб рдмрдлрд░ рдФрд░ рдЗрд╕рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдХреНрдпрд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рд╣рдо zend_stream_fixup рдФрд░ open_file_for_scanning рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ compile_file рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рд╣реИред рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдЕрдкрдиреЗ рд╕рднреА рдЖрд╢реНрд░рд┐рддреЛрдВ рдХреЛ рдЦреБрдж рдХреА рдирдХрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕реЗ рдЖрд╕рд╛рди рдмрдирд╛ рджреЗрдВрдЧреЗред рдпрджрд┐ рдЖрдк zend_stream_fixup рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдЕрдВрддрддрдГ рдПрдХ рд╣реА ZEND_HANDLE_MAPPED рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдлрд╝рд╛рдЗрд▓_рд╣реИрдВрдбрд▓-> рд╣реИрдВрдбрд▓ред ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдпрд╣ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА file_handle рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ, рддреЛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдХреБрдЫ рднреА рдмрджрд▓рдиреЗ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рд╕рдм рдХреБрдЫ рдЬреИрд╕рд╛ рд╣реИ рд╡реИрд╕рд╛ рд╣реА рд▓реМрдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдорд╛рди рдХреЗ рд╕рд╛рде ZEND_HANDLE_MAPPED рд╕реНрд╡рд░реВрдк рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрдВрдкрд╛рдЗрд▓_рдлрд╛рдЗрд▓ () zend_file_handle * file_handle рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ compile_file рдЗрд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд▓реЗрдЧрд╛ рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдерд╛ред рдФрд░ рд╣рдо рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ zend_stream_fixup (рдЬреЛ рдХрд┐ рдПрдХ Zend API рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рди рдХрд┐ рдПрдХ рдмрджрд▓реА рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд╕реВрдЪрдХ) рдХреЙрд▓ рдХрд░рдХреЗ compile_file рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдмрд╛рд░ред рдлрд┐рд░ open_file_for_scanning рдХреЗ рдЕрдВрджрд░ рдлрд┐рд░ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓реЗрдЧрд╛ред
рдХреЛрд╢рд┐рд╢
 zend_op_array* decorators_zend_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */ { char *buf; size_t size; if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) { return NULL; } //   file_handle    ZEND_HANDLE_MAPPED return decorators_orig_zend_compile_file(file_handle, type TSRMLS_CC); } /* }}} */ 

рд╣реБрд░реНрд░реЗ, рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, file_handle-> handle.stream.mmap.buf / len рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реНрд░реЛрдд рд╣реЛрддрд╛ рд╣реИ, рдЬрд╣рд╛рдБ рднреА PHP рдорд┐рд▓реЗрдЧреА: stdin, fd, http рд╕реНрдЯреНрд░реАрдо рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ ... рдпрд╣ рдХреЛрдб рдХреЗ рд╣рдорд╛рд░реЗ рд╕рдВрд╢реЛрдзрд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╡рд╣рд╛рдВ рд░рдЦрдирд╛ рдФрд░ рдореВрд▓ zend_compile_file рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИред

рдореИрдВ рдпрд╣ рдирд╣реАрдВ рд▓рд┐рдЦреВрдВрдЧрд╛ рдХрд┐ рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕_рдкрд░рдкреНрд░реЛрд╕реЗрд╕рд░ () рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рд╕реНрдкрд╖реНрдЯ рд░рд╕реАрдж, рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЛ рдЗрд╕рдХрд╛ рдЯреНрд░рд╛рдВрд╕рдорд┐рд╢рди, рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рд╡рд╛рдкрд╕реАред рдиреАрдЪреЗ рдФрд░ рдЗрд╕рд▓рд┐рдП рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдХреЛрдб рдХреЗ рдЯреБрдХрдбрд╝реЗ рд╣реЛрдВрдЧреЗред

рдпрд╣ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реА рд░рд╣рддрд╛ рд╣реИред
рдХрд┐рд╕реА рдПрдХрд▓ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЕрд╕рдорд╛рди рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдкрд╛рд╕ рдХрд░рдирд╛
 void preprocessor(zval *source_zv, zval *return_value TSRMLS_DC) { //    source_zv    return_value } /* {{{ DECORS_CALL_PREPROCESS */ #define DECORS_CALL_PREPROCESS(result_zv, buf, len) \ do { \ zval *source_zv; \ ALLOC_INIT_ZVAL(result_zv); \ ALLOC_INIT_ZVAL(source_zv); \ ZVAL_STRINGL(source_zv, (buf), (len), 1); \ preprocessor(source_zv, result_zv TSRMLS_CC); \ zval_dtor(source_zv); \ FREE_ZVAL(source_zv); \ } while (0); \ /* }}} */ /* {{{ proto string decorators_preprocessor(string $code) */ PHP_FUNCTION(decorators_preprocessor) { char *source; int source_len; zval *result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source, &source_len) == FAILURE) { return; } DECORS_CALL_PREPROCESS(result, source, source_len); // ... } /* }}} */ zend_op_array* decorators_zend_compile_string(zval *source_string, char *filename TSRMLS_DC) /* {{{ */ { zval *result; DECORS_CALL_PREPROCESS(result, Z_STRVAL_P(source_string), Z_STRLEN_P(source_string)); // ... } /* }}} */ zend_op_array* decorators_zend_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */ { // ... zval *result; DECORS_CALL_PREPROCESS(result, file_handle->handle.stream.mmap.buf, file_handle->handle.stream.mmap.len); // ... } /* }}} */ 


рдвреВрдБрдвреЗрдВ рдФрд░ рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ!


рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдХрд╛рд░реНрдп рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕ рдХреЗ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдЦреЛрдЬрдирд╛ рдФрд░ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХреЛрдб рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдбреЗрдХреЛрд░реЗрдЯрд░ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП, рд╕реНрд░реЛрдд рдкрд╛рда рдХреЗ рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реИред рдкрд╣рд┐рдпрд╛ рдХреЛ рд╕реБрджреГрдврд╝ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рджреЗрд╢реА рдЬрд╝реЗрдВрдб рдХреЗ lex_scan рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╕реНрдХреИрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг token_get_all рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЯреЛрдХрди , token_get_all рдХреЗ рдЕрдВрджрд░ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
  1. рд╣рдо рдЙрд╕ рд╕реНрдХреИрдирд░ рдХреЗ рд╡рд░реНрддрдорд╛рди рд╡рд╛рддрд╛рд╡рд░рдг рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдорд╛рд░рд╛ рдХреЛрдб рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
    zend_lex_state original_lex_state;
    zend_save_lexical_state (рдФрд░ original_lex_state TSRMLS_CC);

  2. рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реЛрд░реНрд╕ рд▓рд╛рдЗрди рддреИрдпрд╛рд░ рдХрд░реЗрдВ:
    zend_prepare_string_for_scanning (рдФрд░ source_z, "" TSRMLS_CC)

  3. рд╣рдордиреЗ рд▓реЗрдХреНрд╕рд░ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рд╣реИ (рд╕рднреА рд╡рд┐рдХрд▓реНрдк рдпрд╣рд╛рдВ рд╣реИрдВ ):
    LANG_SCNG (yy_state) = yycST_IN_SCRIPTING;

    Token_get_all рдХреЗ рд╡рд┐рдкрд░реАрдд, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА PHP рдХреЛрдб рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рдУрдкрдирд┐рдВрдЧ рдЯреИрдЧ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рддрджрдиреБрд╕рд╛рд░, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛ yycinitial рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди yycST_IN_SCRIPTING рд╣реИред
  4. рд▓реВрдк рдореЗрдВ рд╣рдореЗрдВ рд╕реНрд░реЛрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рднреА рдЯреЛрдХрди рдорд┐рд▓рддреЗ рд╣реИрдВ:
    zval token_zv;
    int token_type;
    рдЬрдмрдХрд┐ (token_type = lex_scan (& token_zv TSRMLS_CC)) {
    // ...
    }

    token_type - рдЯреЛрдХрди рдкреНрд░рдХрд╛рд░:
    • <256 - рдПрдХ рдЪрд░рд┐рддреНрд░ рд╡рд╛рд▓реЗ рдЯреЛрдХрди рдХрд╛ рдЪрд░рд┐рддреНрд░ рдХреЛрдб;
    • > = 256 рд╕реНрдерд┐рд░ T_ * рдХрд╛ рдорд╛рди рд╣реИред Token_type рдХрд╛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡рд┐рд╡рд░рдг PHP_FUNCTION (token_name) / get_token_type_name рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

    token_zv рдореЗрдВ рдЯреЛрдХрди рдХрд╛ рдЕрд░реНрде рд╕рдорд╛рд╣рд┐рдд рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк zend_lex_state рд╕рдВрд░рдЪрдирд╛ рдХреЗ yy_text рдФрд░ yy_leng рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рдХреЗ рдкрд╣рд▓реЗ рдмрд╛рдЗрдЯ рдХрд╛ рдкрддрд╛ рдФрд░ рдЗрд╕рдХреА рд▓рдВрдмрд╛рдИ рдХреНрд░рдорд╢рдГ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВред рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ, рдЬреИрд╕реЗ Zend рдореЗрдВ, рдЗрд╕реА рдореИрдХреНрд░реЛрдЬрд╝ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ:
    #define zendtext LANG_SCNG (yy_text)
    # рдбреЗрдлрд╝рд┐рди рдЬрд╝реЗрдВрдЧрд▓реЗрдВрдЧ LANG_SCNG (yy_leng)

    рдЕрдм рд╣рдо рдЪрд╛рд░ * zendtext рдФрд░ рдЕрд╣рд╕реНрддрд╛рдХреНрд╖рд░рд┐рдд int zendleng рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

    рдореЗрдореЛрд░реА рд▓реАрдХ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЯреЛрдХрди рдХрд╛ рдореВрд▓реНрдп рдХрднреА-рдХрднреА рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдореВрд▓ рдмрдлрд░ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдХрднреА-рдХрднреА рдЗрд╕рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред рдЬрд┐рд╕реЗ рдореБрдХреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд░реБрдЪрд┐ рд░рдЦрдиреЗ рд╡рд╛рд▓реЗ рд▓реЛрдЧ lex_scan () рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЕрдм token_get_all рд╕реЗ рддрд░реНрдХ рдХрд╛ рдЖрд╡рд╢реНрдпрдХ рдЯреБрдХрдбрд╝рд╛ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред
  5. рд╣рдо рдЙрд╕ рд╕реНрдХреИрдирд░ рдХреЗ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдорд╛рд░рд╛ рдХреЛрдб рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
    zend_restore_lexical_state (рдФрд░ original_lex_state TSRMLS_CC);


рдпрд╣ рд╕рдм рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реНрд░реЛрдд рдХреЛрдб рдХрд╛ рдПрдХ рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдХреБрдЫ рдФрд░ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдореБрджреНрджреЛрдВ рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред

рдпрджрд┐ PHP рдкрд╛рд░реНрд╕рд┐рдВрдЧ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ рд╣реИрдВрдбрд▓рд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдпрд╛ рдЕрдкрд╡рд╛рдж рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд╛рда рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдФрд░ рд▓рд╛рдЗрди рдирдВрдмрд░ _zend_compiler_globals рд╕реНрдерд┐рддрд┐ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрдХрд▓рд┐рдд_рдлрд┐рд▓рдиреЗрдо рдлрд╝реАрд▓реНрдб рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЬрд┐рд╕реЗ zend_prepare_string_for_scanning () рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ zend_error рдХреЗ рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (E_ * рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ; рдпрд╣ E_PARSE рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдореЗрдВ рднреА рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рд▓реЗрдХрд┐рди zend_error () рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд_filename рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рддрднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм Zend рдПрдХ рд╕рдВрдХрд▓рди рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реЛ (zend_bool in_compilation; рд╕рднреА рдПрдХ рд╣реА _zend_compiler_globals рдореЗрдВ)ред рдпрджрд┐ рд╣рдо рд╕реНрд░реЛрдд рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд╕реНрд╡рдпрдВ рд╕рдХреНрд░рд┐рдп рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рддреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо "рд╕рдВрдХрд▓рди" рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ:
zend_bool original_in_compilation = CG (in_compilation);
CG (in_compilation) = 1;

рдФрд░ рдЕрдВрдд рдореЗрдВ рд╣рдо рд╕рдм рдХреБрдЫ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрддреЗ рд╣реИрдВ:
CG (in_compilation) = original_in_compilation;

рдЕрдм, рдпрджрд┐ рд╣рдо zend_prepare_string_for_scanning рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдлрд╝рд╛рдЗрд▓рдирд╛рдо рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕рдВрднрд╛рд╡рд┐рдд рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рд╣реЛрдВрдЧреАред рдЖрдк рд╡рд░реНрддрдорд╛рди рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдХреЛ zend_get_compiled_filename () рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ, рд╣рд╛рд▓рд╛рдВрдХрд┐, NULL рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реЗ php (рдпрджрд┐ NULL рдХреЛ zend_prepare_string_for_scanning рдХреЛ segfault рдореЗрдВ рдЧрд┐рд░ рдЬрд╛рдПрдЧрд╛)ред
рдпрд╣ рдбреЗрдХреЛрд░реЗрдЯрд░_рдкрд░рдкреНрд░реЛрд╕реЗрд╕рд░ рдФрд░ рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕_рдЬрд╝реЗрдВрдб_рдХрдореНрдкрд╛рдЗрд▓_рдлрд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реА рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИ
 PHP_FUNCTION(decorators_preprocessor) { // ... char *prev_filename = zend_get_compiled_filename(TSRMLS_CC) ? zend_get_compiled_filename(TSRMLS_CC) : ""; zend_set_compiled_filename("-" TSRMLS_CC); DECORS_CALL_PREPROCESS(result, source, source_len); zend_set_compiled_filename(prev_filename TSRMLS_CC); // ... } zend_op_array* decorators_zend_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */ { // ... char *prev_filename = zend_get_compiled_filename(TSRMLS_CC) ? zend_get_compiled_filename(TSRMLS_CC) : ""; const char* filename = (file_handle->opened_path) ? file_handle->opened_path : file_handle->filename; zend_set_compiled_filename(filename TSRMLS_CC); zval *result; DECORS_CALL_PREPROCESS(result, file_handle->handle.stream.mmap.buf, file_handle->handle.stream.mmap.len); zend_set_compiled_filename(prev_filename TSRMLS_CC); // ... } 

рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕_рдЬрд╝реЗрдВрдб_рдХрдореНрдкрд╛рдЗрд▓_рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ, рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рд╣рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬреНрдЮрд╛рдд рд╣реИред


рд╕реНрд░реЛрдд рдХреЛрдб рд╕рдВрд╢реЛрдзрди


рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдЪреАрдЬрд╝реЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдЗрд╕рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд░рд╣рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдореА рдкрд╛рда рдореЗрдВ рдЪрдВрдХреНрд╕ (рдЯреЛрдХрди) рд╕реЗ рдмрдирд╛ рдкрд╛рда рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд╕реА рдореЗрдВ рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ gluing рдХреЗ рд╕рд╛рде рд╕рдХреНрд░рд┐рдп рдХрд╛рд░реНрдп рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, /PHP/ext/standard/php_smart_str.h рдореЗрдВ рд╕реНрдорд╛рд░реНрдЯ рд▓рд╛рдЗрдиреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред
рдХрдо
  smart_str str = {0}; smart_str str2 = {0}; smart_str_appendc(&str, '!'); smart_str_appendl(&str, "hello", 5); smart_str_append(&str, &str2); smart_str_append_long(&str, 42); //  .. //    size_t str.len     char* str.c //  : smart_str_free(&str); 

рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдЯреЛрдХрди рдХреЗ рдЪрдХреНрд░ рдореЗрдВ, рдЯреЛрдХрди (рдЬрд╝реЗрдВрдбрдЯреЗрдХреНрд╕реНрдЯ, рдЬрд╝реЗрдВрдбреНрд▓реЗрдВрдЧ) рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдЧреЛрдВрдж рдХрд░реЗрдВ, рдЬрд╣рд╛рдВ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдмрджрд▓рдиреЗ / рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд╕реАрдзреЗ рддреМрд░ рдкрд░ рдбреЗрдХреЛрд░реЗрдЯрд░, рдЖрдИрдПрдордПрдЪрдУ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдЗрддрдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╣реИред рд╕рдВрднрд╛рд╡рд┐рдд рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБ рд╕реЗ, рдпрд╣ рдЬрд╛рдВрдЪрдирд╛ рдХрд┐ рдЯрд╛рдЗрдк T_COMMENT рдХрд╛ рдЯреЛрдХрди рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рдорд╛рди рд╣реИ: рдирд┐рдпрдорд┐рддрддрд╛ рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛ ^ ^ [[\ t] * @ '(рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд▓реВрдк рдХреЗ рд╕рд╛рде, рдмрд┐рдирд╛ regexp рдХреЗ) рдФрд░ рдкрддрд╛ @ @ рд╡рд╛рдкрд╕ рдЖ рдЧрдпрд╛ рд╣реИред


рдЕрдВрдд рдореЗрдВ рдереЛрдбрд╝рд╛ PHP


рдбреЗрдХреЛрд░реЗрдЯрд░реНрд╕ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╕рдЬрд╛рдпрд╛ рдЧрдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдереЛрдбрд╝рд╛ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ: рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╢рд░реАрд░ рдПрдХ рдЕрдирд╛рдо рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдкреИрд░рд╛рдореАрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рдХрдЯрддрдо рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╛рдиреА рдХреЛрдб рдХреЗ рд▓рд┐рдП
 // comment @a(A) @b @c(C, D) /** * yet another comment */ function x(X) { Y } 

рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдирд┐рдореНрди рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛:
 // comment /** * yet another comment */ function x(X) { return call_user_func_array(a(b(c(function(X) { Y }, C, D)), A), func_get_args());} 

A, C, D, X рд╕реЗ рд╣рдорд╛рд░рд╛ рддрд╛рддреНрдкрд░реНрдп рд╣реИ рдордирдорд╛рдирд╛ рдХреЛрдб рдЬреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рд╕реЗ рдЖрддреЗ рд╣реИрдВ:


рдЦреИрд░, рдпрд╣ рдмрд╛рдд рд╣реИред рдпрджрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣рд╛рдБ рддрдХ рдкрдврд╝рддреЗ рд╣реИрдВ, рддреЛ рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рдерд╛ред

рдореИрдВ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ github рдХрд╛ рд▓рд┐рдВрдХ рджреВрдВрдЧрд╛ред

Source: https://habr.com/ru/post/In180939/


All Articles