@@ -2955,14 +2955,7 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie
2955
2955
}
2956
2956
}
2957
2957
2958
- class PropertyInfo extends VariableLike
2959
- {
2960
- private /* readonly */ int $ classFlags ;
2961
- public /* readonly */ PropertyName $ name ;
2962
- private /* readonly */ ?Expr $ defaultValue ;
2963
- private /* readonly */ ?string $ defaultValueString ;
2964
- private /* readonly */ bool $ isDocReadonly ;
2965
- private /* readonly */ bool $ isVirtual ;
2958
+ class StringBuilder {
2966
2959
2967
2960
// Map possible variable names to the known string constant, see
2968
2961
// ZEND_KNOWN_STRINGS
@@ -3065,8 +3058,90 @@ class PropertyInfo extends VariableLike
3065
3058
"username " => "ZEND_STR_USERNAME " ,
3066
3059
"password " => "ZEND_STR_PASSWORD " ,
3067
3060
"clone " => "ZEND_STR_CLONE " ,
3061
+ '8.0 ' => 'ZEND_STR_8_DOT_0 ' ,
3062
+ '8.1 ' => 'ZEND_STR_8_DOT_1 ' ,
3063
+ '8.2 ' => 'ZEND_STR_8_DOT_2 ' ,
3064
+ '8.3 ' => 'ZEND_STR_8_DOT_3 ' ,
3065
+ '8.4 ' => 'ZEND_STR_8_DOT_4 ' ,
3066
+ '8.5 ' => 'ZEND_STR_8_DOT_5 ' ,
3068
3067
];
3069
3068
3069
+ /**
3070
+ * Get an array of three strings:
3071
+ * - declaration of zend_string, if needed, or empty otherwise
3072
+ * - usage of that zend_string, or usage with ZSTR_KNOWN()
3073
+ * - freeing the zend_string, if needed
3074
+ *
3075
+ * @param string $varName
3076
+ * @param string $strContent
3077
+ * @param ?int $minPHPCompatibility
3078
+ * @param bool $interned
3079
+ * @return string[]
3080
+ */
3081
+ public static function getString (
3082
+ string $ varName ,
3083
+ string $ content ,
3084
+ ?int $ minPHPCompatibility ,
3085
+ bool $ interned = false
3086
+ ): array {
3087
+ // Generally strings will not be known
3088
+ $ initFn = $ interned ? 'zend_string_init_interned ' : 'zend_string_init ' ;
3089
+ $ result = [
3090
+ "\tzend_string * $ varName = $ initFn( \"$ content \", sizeof( \"$ content \") - 1, 1); \n" ,
3091
+ $ varName ,
3092
+ "\tzend_string_release( $ varName); \n"
3093
+ ];
3094
+ // For attribute values that are not freed
3095
+ if ($ varName === '' ) {
3096
+ $ result [0 ] = "$ initFn( \"$ content \", sizeof( \"$ content \") - 1, 1); \n" ;
3097
+ }
3098
+ // If not set, use the current latest version
3099
+ $ allVersions = ALL_PHP_VERSION_IDS ;
3100
+ $ minPhp = $ minPHPCompatibility ?? end ($ allVersions );
3101
+ if ($ minPhp < PHP_80_VERSION_ID ) {
3102
+ // No known strings in 7.0
3103
+ return $ result ;
3104
+ }
3105
+ $ include = self ::PHP_80_KNOWN ;
3106
+ switch ($ minPhp ) {
3107
+ case PHP_85_VERSION_ID :
3108
+ $ include = array_merge ($ include , self ::PHP_85_KNOWN );
3109
+ // Intentional fall through
3110
+
3111
+ case PHP_84_VERSION_ID :
3112
+ $ include = array_merge ($ include , self ::PHP_84_KNOWN );
3113
+ // Intentional fall through
3114
+
3115
+ case PHP_83_VERSION_ID :
3116
+ case PHP_82_VERSION_ID :
3117
+ $ include = array_merge ($ include , self ::PHP_82_KNOWN );
3118
+ // Intentional fall through
3119
+
3120
+ case PHP_81_VERSION_ID :
3121
+ $ include = array_merge ($ include , self ::PHP_81_KNOWN );
3122
+ break ;
3123
+ }
3124
+ if (array_key_exists ($ content , $ include )) {
3125
+ $ knownStr = $ include [$ content ];
3126
+ return [
3127
+ '' ,
3128
+ "ZSTR_KNOWN( $ knownStr) " ,
3129
+ '' ,
3130
+ ];
3131
+ }
3132
+ return $ result ;
3133
+ }
3134
+ }
3135
+
3136
+ class PropertyInfo extends VariableLike
3137
+ {
3138
+ private /* readonly */ int $ classFlags ;
3139
+ public /* readonly */ PropertyName $ name ;
3140
+ private /* readonly */ ?Expr $ defaultValue ;
3141
+ private /* readonly */ ?string $ defaultValueString ;
3142
+ private /* readonly */ bool $ isDocReadonly ;
3143
+ private /* readonly */ bool $ isVirtual ;
3144
+
3070
3145
/**
3071
3146
* @param AttributeInfo[] $attributes
3072
3147
*/
@@ -3147,7 +3222,11 @@ public function getDeclaration(array $allConstInfos): string {
3147
3222
$ code .= $ defaultValue ->initializeZval ($ zvalName );
3148
3223
}
3149
3224
3150
- [$ stringInit , $ nameCode , $ stringRelease ] = $ this ->getString ($ propertyName );
3225
+ [$ stringInit , $ nameCode , $ stringRelease ] = StringBuilder::getString (
3226
+ "property_ {$ propertyName }_name " ,
3227
+ $ propertyName ,
3228
+ $ this ->phpVersionIdMinimumCompatibility
3229
+ );
3151
3230
$ code .= $ stringInit ;
3152
3231
3153
3232
if ($ this ->exposedDocComment ) {
@@ -3182,60 +3261,6 @@ public function getDeclaration(array $allConstInfos): string {
3182
3261
return $ code ;
3183
3262
}
3184
3263
3185
- /**
3186
- * Get an array of three strings:
3187
- * - declaration of zend_string, if needed, or empty otherwise
3188
- * - usage of that zend_string, or usage with ZSTR_KNOWN()
3189
- * - freeing the zend_string, if needed
3190
- *
3191
- * @param string $propName
3192
- * @return string[]
3193
- */
3194
- private function getString (string $ propName ): array {
3195
- // Generally strings will not be known
3196
- $ nameCode = "property_ {$ propName }_name " ;
3197
- $ result = [
3198
- "\tzend_string * $ nameCode = zend_string_init( \"$ propName \", sizeof( \"$ propName \") - 1, 1); \n" ,
3199
- $ nameCode ,
3200
- "\tzend_string_release( $ nameCode); \n"
3201
- ];
3202
- // If not set, use the current latest version
3203
- $ allVersions = ALL_PHP_VERSION_IDS ;
3204
- $ minPhp = $ this ->phpVersionIdMinimumCompatibility ?? end ($ allVersions );
3205
- if ($ minPhp < PHP_80_VERSION_ID ) {
3206
- // No known strings in 7.0
3207
- return $ result ;
3208
- }
3209
- $ include = self ::PHP_80_KNOWN ;
3210
- switch ($ minPhp ) {
3211
- case PHP_85_VERSION_ID :
3212
- $ include = array_merge ($ include , self ::PHP_85_KNOWN );
3213
- // Intentional fall through
3214
-
3215
- case PHP_84_VERSION_ID :
3216
- $ include = array_merge ($ include , self ::PHP_84_KNOWN );
3217
- // Intentional fall through
3218
-
3219
- case PHP_83_VERSION_ID :
3220
- case PHP_82_VERSION_ID :
3221
- $ include = array_merge ($ include , self ::PHP_82_KNOWN );
3222
- // Intentional fall through
3223
-
3224
- case PHP_81_VERSION_ID :
3225
- $ include = array_merge ($ include , self ::PHP_81_KNOWN );
3226
- break ;
3227
- }
3228
- if (array_key_exists ($ propName , $ include )) {
3229
- $ knownStr = $ include [$ propName ];
3230
- return [
3231
- '' ,
3232
- "ZSTR_KNOWN( $ knownStr) " ,
3233
- '' ,
3234
- ];
3235
- }
3236
- return $ result ;
3237
- }
3238
-
3239
3264
/**
3240
3265
* @return array<int, string[]>
3241
3266
*/
@@ -3326,40 +3351,52 @@ public function __construct(string $class, array $args) {
3326
3351
3327
3352
/** @param array<string, ConstInfo> $allConstInfos */
3328
3353
public function generateCode (string $ invocation , string $ nameSuffix , array $ allConstInfos , ?int $ phpVersionIdMinimumCompatibility ): string {
3329
- $ php82MinimumCompatibility = $ phpVersionIdMinimumCompatibility === null || $ phpVersionIdMinimumCompatibility >= PHP_82_VERSION_ID ;
3330
- $ php84MinimumCompatibility = $ phpVersionIdMinimumCompatibility === null || $ phpVersionIdMinimumCompatibility >= PHP_84_VERSION_ID ;
3331
- /* see ZEND_KNOWN_STRINGS in Zend/strings.h */
3332
- $ knowns = [
3333
- "message " => "ZEND_STR_MESSAGE " ,
3334
- ];
3335
- if ($ php82MinimumCompatibility ) {
3336
- $ knowns ["SensitiveParameter " ] = "ZEND_STR_SENSITIVEPARAMETER " ;
3337
- }
3338
- if ($ php84MinimumCompatibility ) {
3339
- $ knowns ["Deprecated " ] = "ZEND_STR_DEPRECATED_CAPITALIZED " ;
3340
- $ knowns ["since " ] = "ZEND_STR_SINCE " ;
3341
- }
3342
-
3343
- $ code = "\n" ;
3344
3354
$ escapedAttributeName = strtr ($ this ->class , '\\' , '_ ' );
3345
- if (isset ($ knowns [$ escapedAttributeName ])) {
3346
- $ code .= "\t" . ($ this ->args ? "zend_attribute *attribute_ {$ escapedAttributeName }_ $ nameSuffix = " : "" ) . "$ invocation, ZSTR_KNOWN( {$ knowns [$ escapedAttributeName ]}), " . count ($ this ->args ) . "); \n" ;
3347
- } else {
3348
- $ code .= "\tzend_string *attribute_name_ {$ escapedAttributeName }_ $ nameSuffix = zend_string_init_interned( \"" . addcslashes ($ this ->class , "\\" ) . "\", sizeof( \"" . addcslashes ($ this ->class , "\\" ) . "\") - 1, 1); \n" ;
3349
- $ code .= "\t" . ($ this ->args ? "zend_attribute *attribute_ {$ escapedAttributeName }_ $ nameSuffix = " : "" ) . "$ invocation, attribute_name_ {$ escapedAttributeName }_ $ nameSuffix, " . count ($ this ->args ) . "); \n" ;
3350
- $ code .= "\tzend_string_release(attribute_name_ {$ escapedAttributeName }_ $ nameSuffix); \n" ;
3351
- }
3355
+ [$ stringInit , $ nameCode , $ stringRelease ] = StringBuilder::getString (
3356
+ "attribute_name_ {$ escapedAttributeName }_ $ nameSuffix " ,
3357
+ addcslashes ($ this ->class , "\\" ),
3358
+ $ phpVersionIdMinimumCompatibility ,
3359
+ true
3360
+ );
3361
+ $ code = "\n" ;
3362
+ $ code .= $ stringInit ;
3363
+ $ code .= "\t" . ($ this ->args ? "zend_attribute *attribute_ {$ escapedAttributeName }_ $ nameSuffix = " : "" ) . "$ invocation, $ nameCode, " . count ($ this ->args ) . "); \n" ;
3364
+ $ code .= $ stringRelease ;
3365
+
3352
3366
foreach ($ this ->args as $ i => $ arg ) {
3353
- $ value = EvaluatedValue::createFromExpression ($ arg ->value , null , null , $ allConstInfos );
3354
- $ zvalName = "attribute_ {$ escapedAttributeName }_ {$ nameSuffix }_arg $ i " ;
3355
- $ code .= $ value ->initializeZval ($ zvalName );
3356
- $ code .= "\tZVAL_COPY_VALUE(&attribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].value, & $ zvalName); \n" ;
3367
+ $ initValue = '' ;
3368
+ if ($ arg ->value instanceof Node \Scalar \String_) {
3369
+ $ strVal = $ arg ->value ->value ;
3370
+ [$ strInit , $ strUse , $ strRelease ] = StringBuilder::getString (
3371
+ 'unused ' ,
3372
+ $ strVal ,
3373
+ $ phpVersionIdMinimumCompatibility
3374
+ );
3375
+ if ($ strInit === '' ) {
3376
+ $ initValue = "\tZVAL_STR(&attribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].value, $ strUse); \n" ;
3377
+ }
3378
+ }
3379
+ if ($ initValue === '' ) {
3380
+ $ value = EvaluatedValue::createFromExpression ($ arg ->value , null , null , $ allConstInfos );
3381
+ $ zvalName = "attribute_ {$ escapedAttributeName }_ {$ nameSuffix }_arg $ i " ;
3382
+ $ code .= $ value ->initializeZval ($ zvalName );
3383
+ $ code .= "\tZVAL_COPY_VALUE(&attribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].value, & $ zvalName); \n" ;
3384
+ } else {
3385
+ $ code .= $ initValue ;
3386
+ }
3357
3387
if ($ arg ->name ) {
3358
- if (isset ($ knowns [$ arg ->name ->name ])) {
3359
- $ code .= "\tattribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].name = ZSTR_KNOWN( {$ knowns [$ arg ->name ->name ]}); \n" ;
3388
+ [$ stringInit , $ nameCode , $ stringRelease ] = StringBuilder::getString (
3389
+ "" ,
3390
+ $ arg ->name ->name ,
3391
+ $ phpVersionIdMinimumCompatibility ,
3392
+ true
3393
+ );
3394
+ if ($ stringInit === '' ) {
3395
+ $ nameCode .= "; \n" ;
3360
3396
} else {
3361
- $ code .= "\t attribute_ { $ escapedAttributeName } _ { $ nameSuffix } ->args[ $ i ].name = zend_string_init_interned( \"{ $ arg -> name -> name }\" , sizeof( \"{ $ arg -> name -> name }\" ) - 1, 1); \n" ;
3397
+ $ nameCode = $ stringInit ;
3362
3398
}
3399
+ $ code .= "\tattribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].name = $ nameCode " ;
3363
3400
}
3364
3401
}
3365
3402
return $ code ;
0 commit comments