diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 6ca402c61bf62..8ce832153a0b6 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -25,6 +25,7 @@ #include "zend_operators.h" #include "zend_globals.h" #include "zend_API.h" +#include "zend_constants_arginfo.h" /* Protection from recursive self-referencing class constants */ #define IS_CONSTANT_VISITED_MARK 0x80 @@ -108,23 +109,7 @@ void zend_startup_constants(void) void zend_register_standard_constants(void) { - REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS); - - REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); + register_zend_constants_consts(0); REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); diff --git a/Zend/zend_constants.stub.php b/Zend/zend_constants.stub.php new file mode 100644 index 0000000000000..191fbd2618778 --- /dev/null +++ b/Zend/zend_constants.stub.php @@ -0,0 +1,99 @@ +create_object = zend_error_exception_new; - /* Declared manually because it uses constant E_ERROR. */ - zval severity_default_value; - ZVAL_LONG(&severity_default_value, E_ERROR); - zend_declare_typed_property(zend_ce_error_exception, ZSTR_KNOWN(ZEND_STR_SEVERITY), &severity_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_ce_error = register_class_Error(zend_ce_throwable); zend_ce_error->create_object = zend_default_exception_new; diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index 48e668b110dd3..3ea0fc1afb5c0 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -259,6 +259,12 @@ static zend_class_entry *register_class_ErrorException(zend_class_entry *class_e INIT_CLASS_ENTRY(ce, "ErrorException", class_ErrorException_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_Exception); + zval property_severity_default_value; + ZVAL_LONG(&property_severity_default_value, E_ERROR); + zend_string *property_severity_name = zend_string_init("severity", sizeof("severity") - 1, 1); + zend_declare_typed_property(class_entry, property_severity_name, &property_severity_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(property_severity_name); + return class_entry; } diff --git a/build/gen_stub.php b/build/gen_stub.php index b4daed524128d..027b855db697e 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -15,6 +15,7 @@ use PhpParser\PrettyPrinterAbstract; error_reporting(E_ALL); +ini_set("precision", 17); /** * @return FileInfo[] @@ -51,8 +52,9 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo { throw new Exception("File $stubFile does not exist"); } - $arginfoFile = str_replace('.stub.php', '_arginfo.h', $stubFile); - $legacyFile = str_replace('.stub.php', '_legacy_arginfo.h', $stubFile); + $stubFilenameWithoutExtension = str_replace(".stub.php", "", $stubFile); + $arginfoFile = "{$stubFilenameWithoutExtension}_arginfo.h"; + $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; $stubCode = file_get_contents($stubFile); $stubHash = computeStubHash($stubCode); @@ -64,8 +66,15 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo { initPhpParser(); $fileInfo = parseStubFile($stubCode); - - $arginfoCode = generateArgInfoCode($fileInfo, $stubHash); + $constInfos = $fileInfo->getAllConstInfos(); + $context->allConstInfos = array_merge($context->allConstInfos, $constInfos); + + $arginfoCode = generateArgInfoCode( + basename($stubFilenameWithoutExtension), + $fileInfo, + $context->allConstInfos, + $stubHash + ); if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($arginfoFile, $arginfoCode)) { echo "Saved $arginfoFile\n"; } @@ -80,7 +89,12 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo { $propertyInfo->discardInfoForOldPhpVersions(); } - $arginfoCode = generateArgInfoCode($legacyFileInfo, $stubHash); + $arginfoCode = generateArgInfoCode( + basename($stubFilenameWithoutExtension), + $legacyFileInfo, + $context->allConstInfos, + $stubHash + ); if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($legacyFile, $arginfoCode)) { echo "Saved $legacyFile\n"; } @@ -115,6 +129,8 @@ class Context { public $forceParse = false; /** @var bool */ public $forceRegeneration = false; + /** @var iterable */ + public iterable $allConstInfos = []; } class ArrayType extends SimpleType { @@ -236,11 +252,66 @@ public static function fromString(string $typeString): SimpleType return new SimpleType($typeString, false); } + /** + * @param mixed $value + */ + public static function fromValue($value): SimpleType + { + switch (gettype($value)) { + case "NULL": + return SimpleType::null(); + case "boolean": + return SimpleType::bool(); + case "integer": + return SimpleType::int(); + case "double": + return SimpleType::float(); + case "string": + return SimpleType::string(); + case "array": + return SimpleType::array(); + case "object": + return SimpleType::object(); + default: + throw new Exception("Type \"" . gettype($value) . "\" cannot be inferred based on value"); + } + } + public static function null(): SimpleType { return new SimpleType("null", true); } + public static function bool(): SimpleType + { + return new SimpleType("bool", true); + } + + public static function int(): SimpleType + { + return new SimpleType("int", true); + } + + public static function float(): SimpleType + { + return new SimpleType("float", true); + } + + public static function string(): SimpleType + { + return new SimpleType("string", true); + } + + public static function array(): SimpleType + { + return new SimpleType("array", true); + } + + public static function object(): SimpleType + { + return new SimpleType("object", true); + } + public static function void(): SimpleType { return new SimpleType("void", true); @@ -259,6 +330,26 @@ public function isNull(): bool { return $this->isBuiltin && $this->name === 'null'; } + public function isBool(): bool { + return $this->isBuiltin && $this->name === 'bool'; + } + + public function isInt(): bool { + return $this->isBuiltin && $this->name === 'int'; + } + + public function isFloat(): bool { + return $this->isBuiltin && $this->name === 'float'; + } + + public function isString(): bool { + return $this->isBuiltin && $this->name === 'string'; + } + + public function isArray(): bool { + return $this->isBuiltin && $this->name === 'array'; + } + public function toTypeCode(): string { assert($this->isBuiltin); switch ($this->name) { @@ -749,6 +840,69 @@ private function setTypes(?Type $type, ?Type $phpDocType): void } } +interface ConstOrClassConstName { + public function __toString(): string; + public function equals(ConstOrClassConstName $const): bool; + public function isClassConst(): bool; + public function isUnknown(): bool; +} + +abstract class AbstractConstName implements ConstOrClassConstName +{ + public function equals(ConstOrClassConstName $const): bool + { + return $this->__toString() === $const->__toString(); + } + + public function isUnknown(): bool + { + return strtolower($this->__toString()) === "unknown"; + } +} + +class ConstName extends AbstractConstName { + /** @var string */ + public $const; + + public function __construct(string $const) + { + $this->const = $const; + } + + public function isClassConst(): bool + { + return false; + } + + public function __toString(): string + { + return $this->const; + } +} + +class ClassConstName extends AbstractConstName { + /** @var Name */ + public $class; + /** @var string */ + public $const; + + public function __construct(Name $class, string $const) + { + $this->class = $class; + $this->const = $const; + } + + public function isClassConst(): bool + { + return true; + } + + public function __toString(): string + { + return $this->class->toString() . "::" . $this->const; + } +} + class PropertyName { /** @var Name */ public $class; @@ -1339,82 +1493,517 @@ public function getMethodSynopsisElement(array $funcMap, array $aliasMap, DOMDoc } $methodSynopsis->appendChild(new DOMText("\n ")); - return $methodSynopsis; + return $methodSynopsis; + } + + public function __clone() + { + foreach ($this->args as $key => $argInfo) { + $this->args[$key] = clone $argInfo; + } + $this->return = clone $this->return; + } +} + +class EvaluatedValue +{ + /** @var mixed */ + public $value; + + /** @var SimpleType */ + public $type; + + /** @var string|null */ + public $cConstName; + + /** @var bool */ + public $isUnknownConstValue; + + /** @var ConstInfo|null */ + public $originatingConst; + + /** + * @param iterable $allConstInfos + */ + public static function createFromExpression(Expr $expr, ?SimpleType $constType, ?string $cConstName, iterable $allConstInfos): EvaluatedValue + { + $originatingConst = null; + $isUnknownConstValue = null; + + $evaluator = new ConstExprEvaluator( + function (Expr $expr) use ($allConstInfos, &$constType, &$originatingConst, &$isUnknownConstValue) { + if (!$expr instanceof Expr\ConstFetch && !$expr instanceof Expr\ClassConstFetch) { + throw new Exception($this->getVariableTypeName() . " " . $this->getVariableLikeName() . " has an unsupported value"); + } + + if ($expr instanceof Expr\ClassConstFetch) { + $originatingConstName = new ClassConstName($expr->class, $expr->name->toString()); + } else { + $originatingConstName = new ConstName($expr->name->toString()); + } + + if ($originatingConstName->isUnknown()) { + $originatingConst = null; + $isUnknownConstValue = true; + + return null; + } + + foreach ($allConstInfos as $const) { + if (!$originatingConstName->equals($const->name)) { + continue; + } + + if ($constType === null && $const->phpDocType) { + $constType = $const->phpDocType->tryToSimpleType(); + } + + $originatingConst = $const; + $isUnknownConstValue = false; + + return null; + } + + throw new Exception("Constant " . $originatingConstName->__toString() . " cannot be found"); + } + ); + + $result = $evaluator->evaluateDirectly($expr); + + return new EvaluatedValue( + $result, + $constType ?: SimpleType::fromValue($result), + $cConstName, + $originatingConst, + (bool) $isUnknownConstValue + ); + } + + public static function null(): EvaluatedValue + { + return new self(null, SimpleType::null(), null, null, false); + } + + /** + * @param mixed $value + */ + private function __construct($value, SimpleType $type, ?string $cConstName, ?ConstInfo $originatingConst, bool $isUnknownConstValue) + { + $this->value = $value; + $this->type = $type; + $this->cConstName = $cConstName; + $this->originatingConst = $originatingConst; + $this->isUnknownConstValue = $isUnknownConstValue; + } + + /** + * @param iterable $allConstInfos + */ + public function initializeZval(string $zvalName, iterable $allConstInfos): string + { + $cConstValue = $this->getCConstValue($allConstInfos); + + $code = "\tzval $zvalName;\n"; + + if ($this->type->isNull()) { + $code .= "\tZVAL_NULL(&$zvalName);\n"; + } elseif ($this->type->isBool()) { + $code .= "\tZVAL_BOOL(&$zvalName, " . ($cConstValue ?: ($this->value ? "true" : "false")) . ");\n"; + } elseif ($this->type->isInt()) { + $code .= "\tZVAL_LONG(&$zvalName, " . ($cConstValue ?: $this->value) . ");\n"; + } elseif ($this->type->isFloat()) { + $code .= "\tZVAL_DOUBLE(&$zvalName, " . ($cConstValue ?: $this->value) . ");\n"; + } elseif ($this->type->isString()) { + if (!$cConstValue && $this->value === "") { + $code .= "\tZVAL_EMPTY_STRING(&$zvalName);\n"; + } else { + $constValue = $cConstValue ?: '"' . addslashes($this->value) . '"'; + $code .= "\tzend_string *{$zvalName}_str = zend_string_init($constValue, sizeof($constValue) - 1, 1);\n"; + $code .= "\tZVAL_STR(&$zvalName, {$zvalName}_str);\n"; + } + } elseif ($this->type->isArray()) { + if (!$cConstValue && empty($this->value)) { + $code .= "\tZVAL_EMPTY_ARRAY(&$zvalName);\n"; + } else { + throw new Exception("Unimplemented default value"); + } + } else { + throw new Exception("Invalid default value"); + } + + return $code; + } + + /** + * @param iterable $allConstInfos + */ + public function getCConstValue(iterable $allConstInfos): ?string + { + if ($this->cConstName) { + return $this->cConstName; + } + + if ($this->originatingConst) { + return $this->originatingConst->getValue($allConstInfos)->getCConstValue($allConstInfos); + } + + return null; + } +} + +abstract class VariableLike +{ + /** @var Type|null */ + public $phpDocType; + + /** @var int */ + public $flags; + + /** @var string|null */ + public $link; + + abstract protected function getVariableTypeCode(): string; + + abstract protected function getVariableTypeName(): string; + + abstract protected function getVariableLikeName(): string; + + abstract protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void; + + abstract protected function getFieldSynopsisDefaultLinkend(): string; + + abstract protected function getFieldSynopsisName(): string; + + /** + * @param iterable $allConstInfos + */ + abstract protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string; + + protected function getFlagsAsString(): string + { + $flags = "ZEND_ACC_PUBLIC"; + if ($this->flags & Class_::MODIFIER_PROTECTED) { + $flags = "ZEND_ACC_PROTECTED"; + } elseif ($this->flags & Class_::MODIFIER_PRIVATE) { + $flags = "ZEND_ACC_PRIVATE"; + } + + return $flags; + } + + /** + * @param iterable $allConstInfos + */ + public function getFieldSynopsisElement(DOMDocument $doc, iterable $allConstInfos): DOMElement + { + $fieldsynopsisElement = $doc->createElement("fieldsynopsis"); + + $this->addModifiersToFieldSynopsis($doc, $fieldsynopsisElement); + + $this->addTypeToFieldSynopsis($doc, $fieldsynopsisElement); + + $varnameElement = $doc->createElement("varname", $this->getFieldSynopsisName()); + if ($this->link) { + $varnameElement->setAttribute("linkend", $this->link); + } else { + $varnameElement->setAttribute("linkend", $this->getFieldSynopsisDefaultLinkend()); + } + + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($varnameElement); + + $valueString = $this->getFieldSynopsisValueString($allConstInfos); + if ($valueString) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $initializerElement = $doc->createElement("initializer", $valueString); + $fieldsynopsisElement->appendChild($initializerElement); + } + + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + + return $fieldsynopsisElement; + } + + protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void + { + if ($this->flags & Class_::MODIFIER_PUBLIC) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "public")); + } elseif ($this->flags & Class_::MODIFIER_PROTECTED) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "protected")); + } elseif ($this->flags & Class_::MODIFIER_PRIVATE) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "private")); + } + } +} + +class ConstInfo extends VariableLike +{ + /** @var ConstOrClassConstName */ + public $name; + /** @var Expr */ + public $value; + /** @var bool */ + public $isDeprecated; + /** @var string|null */ + public $valueString; + /** @var string|null */ + public $cond; + /** @var string|null */ + public $cname; + + public function __construct( + ConstOrClassConstName $name, + int $flags, + Expr $value, + ?string $valueString, + ?Type $phpDocType, + bool $isDeprecated, + ?string $cond, + ?string $cname, + ?string $link + ) { + $this->name = $name; + $this->flags = $flags; + $this->value = $value; + $this->valueString = $valueString; + $this->phpDocType = $phpDocType; + $this->isDeprecated = $isDeprecated; + $this->cond = $cond; + $this->cname = $cname; + $this->link = $link; + } + + /** + * @param iterable $allConstInfos + */ + public function getValue(iterable $allConstInfos): EvaluatedValue + { + return EvaluatedValue::createFromExpression( + $this->value, + $this->phpDocType->tryToSimpleType(), + $this->cname, + $allConstInfos + ); + } + + protected function getVariableTypeName(): string + { + return "constant"; + } + + protected function getVariableLikeName(): string + { + return $this->name->const; + } + + protected function getVariableTypeCode(): string + { + return "const"; + } + + protected function getFieldSynopsisDefaultLinkend(): string + { + $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); + + return "$className.constants." . strtolower(str_replace("_", "-", $this->name->const)); + } + + protected function getFieldSynopsisName(): string + { + return $this->name->__toString(); + } + + protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void + { + if ($this->phpDocType) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($this->phpDocType->getTypeForDoc($doc)); + } + } + + /** + * @param iterable $allConstInfos + */ + protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string + { + $value = EvaluatedValue::createFromExpression($this->value, null, $this->cname, $allConstInfos); + if ($value->originatingConst) { + return $value->originatingConst->getFieldSynopsisValueString($allConstInfos); + } + + return $this->valueString; + } + + /** + * @param iterable $allConstInfos + */ + public function getDeclaration(iterable $allConstInfos): string + { + $type = $this->phpDocType->tryToSimpleType(); + if ($type === null || !$type->isBuiltin) { + throw new Exception("Constant " . $this->name->__toString() . " must have a simple built-in type"); + } + + $value = EvaluatedValue::createFromExpression($this->value, $type, $this->cname, $allConstInfos); + if ($value->isUnknownConstValue && !$value->cConstName) { + throw new Exception("Constant " . $this->name->__toString() . " must have a @cname annotation"); + } + + $code = ""; + + if ($this->cond) { + $code .= "#if {$this->cond}\n"; + } + + if ($this->name->isClassConst()) { + $code .= $this->getClassConstDeclaration($value, $allConstInfos); + } else { + $code .= $this->getGlobalConstDeclaration($value, $allConstInfos); + } + $code .= $this->getValueAssertion($value); + + if ($this->cond) { + $code .= "#endif\n"; + } + + return $code; + } + + /** + * @param iterable $allConstInfos + */ + private function getGlobalConstDeclaration(EvaluatedValue $value, iterable $allConstInfos): string + { + $constName = str_replace('\\', '\\\\', $this->name->__toString()); + $constValue = $value->value; + $cConstValue = $value->getCConstValue($allConstInfos); + + $flags = "CONST_CS | CONST_PERSISTENT"; + if ($this->isDeprecated) { + $flags .= " | CONST_DEPRECATED"; + } + if ($value->type->isNull()) { + return " REGISTER_NULL_CONSTANT(\"$constName\", $flags);\n"; + } + + if ($value->type->isBool()) { + return " REGISTER_BOOL_CONSTANT(\"$constName\", " . ($cConstValue ?: ($constValue ? "true" : "false")) . ", $flags);\n"; + } + + if ($value->type->isInt()) { + return " REGISTER_LONG_CONSTANT(\"$constName\", " . ($cConstValue ?: (int) $constValue) . ", $flags);\n"; + } + + if ($value->type->isFloat()) { + return " REGISTER_DOUBLE_CONSTANT(\"$constName\", " . ($cConstValue ?: (float) $constValue) . ", $flags);\n"; + } + + if ($value->type->isString()) { + return " REGISTER_STRING_CONSTANT(\"$constName\", " . ($cConstValue ?: '"' . addslashes($constValue) . '"') . ", $flags);\n"; + } + + throw new Exception("Unimplemented constant type");} + + /** + * @param iterable $allConstInfos + */ + private function getClassConstDeclaration(EvaluatedValue $value, iterable $allConstInfos): string + { + $constName = $this->getVariableLikeName(); + + $zvalCode = $value->initializeZval("const_{$constName}_value", $allConstInfos); + + $code = "\n" . $zvalCode; + + $code .= "\tzend_string *const_{$constName}_name = zend_string_init_interned(\"$constName\", sizeof(\"$constName\") - 1, 1);\n"; + $nameCode = "const_{$constName}_name"; + + $code .= "\tzend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, " . $this->getFlagsAsString() . ", NULL);\n"; + $code .= "\tzend_string_release(const_{$constName}_name);\n"; + + return $code; } - public function __clone() + private function getValueAssertion(EvaluatedValue $value): string { - foreach ($this->args as $key => $argInfo) { - $this->args[$key] = clone $argInfo; + if ($value->isUnknownConstValue || $value->originatingConst || $value->cConstName === null) { + return ""; } - $this->return = clone $this->return; - } -} -function initializeZval(string $zvalName, $value): string -{ - $code = "\tzval $zvalName;\n"; + $cName = $value->cConstName; + $constValue = $value->value; - switch (gettype($value)) { - case "NULL": - $code .= "\tZVAL_NULL(&$zvalName);\n"; - break; + if ($value->type->isNull()) { + return " ZEND_ASSERT($cName == NULL);\n"; + } - case "boolean": - $code .= "\tZVAL_BOOL(&$zvalName, " . ((int) $value) . ");\n"; - break; + if ($value->type->isBool()) { + $cValue = $constValue ? "true" : "false"; + return " ZEND_ASSERT($cName == $cValue);\n"; + } - case "integer": - $code .= "\tZVAL_LONG(&$zvalName, $value);\n"; - break; + if ($value->type->isInt()) { + $cValue = (int) $constValue; + return " ZEND_ASSERT($cName == $cValue);\n"; + } - case "double": - $code .= "\tZVAL_DOUBLE(&$zvalName, $value);\n"; - break; + if ($value->type->isFloat()) { + $cValue = (float) $constValue; + return " ZEND_ASSERT($cName == $cValue);\n"; + } - case "string": - if ($value === "") { - $code .= "\tZVAL_EMPTY_STRING(&$zvalName);\n"; - } else { - $strValue = addslashes($value); - $code .= "\tzend_string *{$zvalName}_str = zend_string_init(\"$strValue\", sizeof(\"$strValue\") - 1, 1);\n"; - $code .= "\tZVAL_STR(&$zvalName, {$zvalName}_str);\n"; - } - break; + if ($value->type->isString()) { + $cValue = '"' . addslashes($constValue) . '"'; + return " ZEND_ASSERT(strcmp($cName, $cValue) == 0);\n"; + } - case "array": - if (empty($value)) { - $code .= "\tZVAL_EMPTY_ARRAY(&$zvalName);\n"; - } else { - throw new Exception("Unimplemented default value"); - } - break; + throw new Exception("Unimplemented constant type"); + } - default: - throw new Exception("Invalid default value"); + protected function getFlagsAsString(): string + { + $flags = parent::getFlagsAsString(); + + if ($this->flags & Class_::MODIFIER_FINAL) { + $flags .= "|ZEND_ACC_FINAL"; + } + + if ($this->isDeprecated) { + $flags .= "|ZEND_ACC_DEPRECATED"; + } + + return $flags; } - return $code; + protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void + { + parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement); + + if ($this->flags & Class_::MODIFIER_FINAL) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "final")); + } + + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "const")); + } } -class PropertyInfo +class PropertyInfo extends VariableLike { /** @var PropertyName */ public $name; - /** @var int */ - public $flags; /** @var Type|null */ public $type; - /** @var Type|null */ - public $phpDocType; /** @var Expr|null */ public $defaultValue; /** @var string|null */ public $defaultValueString; /** @var bool */ public $isDocReadonly; - /** @var string|null */ - public $link; public function __construct( PropertyName $name, @@ -1436,25 +2025,61 @@ public function __construct( $this->link = $link; } + protected function getVariableTypeCode(): string + { + return "property"; + } + + protected function getVariableTypeName(): string + { + return "property"; + } + + protected function getVariableLikeName(): string + { + return $this->name->property; + } + + protected function getFieldSynopsisDefaultLinkend(): string + { + $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); + + return "$className.props." . strtolower(str_replace("_", "-", $this->name->property)); + } + + protected function getFieldSynopsisName(): string + { + return $this->name->property; + } + + /** + * @param iterable $allConstInfos + */ + protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string + { + return $this->defaultValueString; + } + public function discardInfoForOldPhpVersions(): void { $this->type = null; } - public function getDeclaration(): string { + /** + * @param iterable $allConstInfos + */ + public function getDeclaration(iterable $allConstInfos): string { $code = "\n"; $propertyName = $this->name->property; - $defaultValueConstant = false; if ($this->defaultValue === null) { - $defaultValue = null; + $defaultValue = EvaluatedValue::null(); } else { - $defaultValue = $this->evaluateDefaultValue($defaultValueConstant); - } - - if ($defaultValueConstant) { - echo "Skipping code generation for property $this->name, because it has a constant default value\n"; - return ""; + $defaultValue = EvaluatedValue::createFromExpression($this->defaultValue, null, null, $allConstInfos); + if ($defaultValue->isUnknownConstValue || ($defaultValue->originatingConst && $defaultValue->getCConstValue($allConstInfos) === null)) { + echo "Skipping code generation for property $this->name, because it has an unknown constant default value\n"; + return ""; + } } $typeCode = ""; @@ -1497,7 +2122,7 @@ public function getDeclaration(): string { if ($this->defaultValue === null && $this->type !== null) { $code .= "\tzval $zvalName;\n\tZVAL_UNDEF(&$zvalName);\n"; } else { - $code .= initializeZval($zvalName, $defaultValue); + $code .= $defaultValue->initializeZval($zvalName, $allConstInfos); } $code .= "\tzend_string *property_{$propertyName}_name = zend_string_init(\"$propertyName\", sizeof(\"$propertyName\") - 1, 1);\n"; @@ -1513,14 +2138,9 @@ public function getDeclaration(): string { return $code; } - private function getFlagsAsString(): string + protected function getFlagsAsString(): string { - $flags = "ZEND_ACC_PUBLIC"; - if ($this->flags & Class_::MODIFIER_PROTECTED) { - $flags = "ZEND_ACC_PROTECTED"; - } elseif ($this->flags & Class_::MODIFIER_PRIVATE) { - $flags = "ZEND_ACC_PRIVATE"; - } + $flags = parent::getFlagsAsString(); if ($this->flags & Class_::MODIFIER_STATIC) { $flags .= "|ZEND_ACC_STATIC"; @@ -1533,80 +2153,29 @@ private function getFlagsAsString(): string return $flags; } - public function getFieldSynopsisElement(DOMDocument $doc): DOMElement + protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void { - $fieldsynopsisElement = $doc->createElement("fieldsynopsis"); - - if ($this->flags & Class_::MODIFIER_PUBLIC) { - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($doc->createElement("modifier", "public")); - } elseif ($this->flags & Class_::MODIFIER_PROTECTED) { - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($doc->createElement("modifier", "protected")); - } elseif ($this->flags & Class_::MODIFIER_PRIVATE) { - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($doc->createElement("modifier", "private")); - } + parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement); if ($this->flags & Class_::MODIFIER_STATIC) { $fieldsynopsisElement->appendChild(new DOMText("\n ")); $fieldsynopsisElement->appendChild($doc->createElement("modifier", "static")); - } elseif ($this->flags & Class_::MODIFIER_READONLY || $this->isDocReadonly) { - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($doc->createElement("modifier", "readonly")); - } - - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($this->getFieldSynopsisType()->getTypeForDoc($doc)); - - $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); - $varnameElement = $doc->createElement("varname", $this->name->property); - if ($this->link) { - $varnameElement->setAttribute("linkend", $this->link); - } else { - $varnameElement->setAttribute("linkend", "$className.props." . strtolower(str_replace("_", "-", $this->name->property))); } - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($varnameElement); - if ($this->defaultValueString) { + if ($this->flags & Class_::MODIFIER_READONLY || $this->isDocReadonly) { $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $initializerElement = $doc->createElement("initializer", $this->defaultValueString); - $fieldsynopsisElement->appendChild($initializerElement); - } - - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - - return $fieldsynopsisElement; - } - - private function getFieldSynopsisType(): Type { - if ($this->phpDocType) { - return $this->phpDocType; - } - - if ($this->type) { - return $this->type; + $fieldsynopsisElement->appendChild($doc->createElement("modifier", "readonly")); } - - throw new Exception("A property must have a type"); } - /** @return mixed */ - private function evaluateDefaultValue(bool &$defaultValueConstant) + protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void { - $evaluator = new ConstExprEvaluator( - function (Expr $expr) use (&$defaultValueConstant) { - if ($expr instanceof Expr\ConstFetch) { - $defaultValueConstant = true; - return null; - } - - throw new Exception("Property $this->name has an unsupported default value"); - } - ); + $type = $this->phpDocType ?? $this->type; - return $evaluator->evaluateDirectly($this->defaultValue); + if ($type) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($type->getTypeForDoc($doc)); + } } public function __clone() @@ -1628,18 +2197,21 @@ public function __construct(string $name, ?Expr $value) { $this->value = $value; } - public function getDeclaration(): string { + /** + * @param iterable $allConstInfos + */ + public function getDeclaration(iterable $allConstInfos): string { $escapedName = addslashes($this->name); if ($this->value === null) { $code = "\n\tzend_enum_add_case_cstr(class_entry, \"$escapedName\", NULL);\n"; } else { - $evaluator = new ConstExprEvaluator(function (Expr $expr) { - throw new Exception("Enum case $this->name has an unsupported value"); - }); + $value = EvaluatedValue::createFromExpression($this->value, null, null, $allConstInfos); + $zvalName = "enum_case_{$escapedName}_value"; - $code = "\n" . initializeZval($zvalName, $evaluator->evaluateDirectly($this->value)); + $code = "\n" . $value->initializeZval($zvalName, $allConstInfos); $code .= "\tzend_enum_add_case_cstr(class_entry, \"$escapedName\", &$zvalName);\n"; } + return $code; } } @@ -1665,6 +2237,8 @@ class ClassInfo { public $extends; /** @var Name[] */ public $implements; + /** @var ConstInfo[] */ + public $constInfos; /** @var PropertyInfo[] */ public $propertyInfos; /** @var FuncInfo[] */ @@ -1675,6 +2249,7 @@ class ClassInfo { /** * @param Name[] $extends * @param Name[] $implements + * @param ConstInfo[] $constInfos * @param PropertyInfo[] $propertyInfos * @param FuncInfo[] $funcInfos * @param EnumCaseInfo[] $enumCaseInfos @@ -1690,6 +2265,7 @@ public function __construct( bool $isNotSerializable, array $extends, array $implements, + array $constInfos, array $propertyInfos, array $funcInfos, array $enumCaseInfos @@ -1704,12 +2280,16 @@ public function __construct( $this->isNotSerializable = $isNotSerializable; $this->extends = $extends; $this->implements = $implements; + $this->constInfos = $constInfos; $this->propertyInfos = $propertyInfos; $this->funcInfos = $funcInfos; $this->enumCaseInfos = $enumCaseInfos; } - public function getRegistration(): string + /** + * @param ConstInfo[] $allConstInfos + */ + public function getRegistration(iterable $allConstInfos): string { $params = []; foreach ($this->extends as $extends) { @@ -1766,12 +2346,16 @@ function (Name $item) { $code .= "\tzend_register_class_alias(\"" . str_replace("\\", "\\\\", $this->alias) . "\", class_entry);\n"; } + foreach ($this->constInfos as $const) { + $code .= $const->getDeclaration($allConstInfos); + } + foreach ($this->enumCaseInfos as $enumCase) { - $code .= $enumCase->getDeclaration(); + $code .= $enumCase->getDeclaration($allConstInfos); } foreach ($this->propertyInfos as $property) { - $code .= $property->getDeclaration(); + $code .= $property->getDeclaration($allConstInfos); } $code .= "\n\treturn class_entry;\n"; @@ -1818,12 +2402,14 @@ private function getFlagsAsString(): string /** * @param array $classMap + * @param iterable $allConstInfos + * @param iterable $allConstInfo */ - public function getClassSynopsisDocument(array $classMap): ?string { + public function getClassSynopsisDocument(array $classMap, iterable $allConstInfos): ?string { $doc = new DOMDocument(); $doc->formatOutput = true; - $classSynopsis = $this->getClassSynopsisElement($doc, $classMap); + $classSynopsis = $this->getClassSynopsisElement($doc, $classMap, $allConstInfos); if (!$classSynopsis) { return null; } @@ -1834,9 +2420,10 @@ public function getClassSynopsisDocument(array $classMap): ?string { } /** - * @param ClassInfo[] $classMap + * @param array $classMap + * @param iterable $allConstInfos */ - public function getClassSynopsisElement(DOMDocument $doc, array $classMap): ?DOMElement { + public function getClassSynopsisElement(DOMDocument $doc, array $classMap, iterable $allConstInfos): ?DOMElement { $classSynopsis = $doc->createElement("classsynopsis"); $classSynopsis->appendChild(new DOMText("\n ")); @@ -1895,44 +2482,62 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap): ?DOM } $classSynopsisInfo->appendChild(new DOMText("\n ")); + /** @var Name[] $parentsWithInheritedConstants */ + $parentsWithInheritedConstants = []; /** @var Name[] $parentsWithInheritedProperties */ $parentsWithInheritedProperties = []; /** @var Name[] $parentsWithInheritedMethods */ $parentsWithInheritedMethods = []; - $this->collectInheritedMembers($parentsWithInheritedProperties, $parentsWithInheritedMethods, $classMap); + $this->collectInheritedMembers( + $parentsWithInheritedConstants, + $parentsWithInheritedProperties, + $parentsWithInheritedMethods, + $classMap + ); + + $this->appendInheritedMemberSectionToClassSynopsis( + $doc, + $classSynopsis, + $parentsWithInheritedConstants, + "&Constants;", + "&InheritedConstants;" + ); - if (!empty($this->propertyInfos)) { + if (!empty($this->constInfos)) { $classSynopsis->appendChild(new DOMText("\n\n ")); - $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Properties;"); + $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Constants;"); $classSynopsisInfo->setAttribute("role", "comment"); $classSynopsis->appendChild($classSynopsisInfo); - foreach ($this->propertyInfos as $propertyInfo) { + foreach ($this->constInfos as $constInfo) { $classSynopsis->appendChild(new DOMText("\n ")); - $fieldSynopsisElement = $propertyInfo->getFieldSynopsisElement($doc); + $fieldSynopsisElement = $constInfo->getFieldSynopsisElement($doc, $allConstInfos); $classSynopsis->appendChild($fieldSynopsisElement); } } - if (!empty($parentsWithInheritedProperties)) { + if (!empty($this->propertyInfos)) { $classSynopsis->appendChild(new DOMText("\n\n ")); - $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&InheritedProperties;"); + $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Properties;"); $classSynopsisInfo->setAttribute("role", "comment"); $classSynopsis->appendChild($classSynopsisInfo); - foreach ($parentsWithInheritedProperties as $parent) { + foreach ($this->propertyInfos as $propertyInfo) { $classSynopsis->appendChild(new DOMText("\n ")); - $parentReference = self::getClassSynopsisReference($parent); - - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:partintro/db:section/db:classsynopsis/db:fieldsynopsis[preceding-sibling::db:classsynopsisinfo[1][@role='comment' and text()='&Properties;']]))" - ); - $classSynopsis->appendChild($includeElement); + $fieldSynopsisElement = $propertyInfo->getFieldSynopsisElement($doc, $allConstInfos); + $classSynopsis->appendChild($fieldSynopsisElement); } } + $this->appendInheritedMemberSectionToClassSynopsis( + $doc, + $classSynopsis, + $parentsWithInheritedProperties, + "&Properties;", + "&InheritedProperties;" + ); + if (!empty($this->funcInfos)) { $classSynopsis->appendChild(new DOMText("\n\n ")); $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); @@ -2040,18 +2645,27 @@ public static function getClassSynopsisReference(Name $name): string { } /** + * @param Name[] $parentsWithInheritedConstants * @param Name[] $parentsWithInheritedProperties * @param Name[] $parentsWithInheritedMethods * @param array $classMap */ - private function collectInheritedMembers(array &$parentsWithInheritedProperties, array &$parentsWithInheritedMethods, array $classMap): void - { + private function collectInheritedMembers( + array &$parentsWithInheritedConstants, + array &$parentsWithInheritedProperties, + array &$parentsWithInheritedMethods, + array $classMap + ): void { foreach ($this->extends as $parent) { $parentInfo = $classMap[$parent->toString()] ?? null; if (!$parentInfo) { throw new Exception("Missing parent class " . $parent->toString()); } + if (!empty($parentInfo->constInfos) && !isset($parentsWithInheritedConstants[$parent->toString()])) { + $parentsWithInheritedConstants[$parent->toString()] = $parent; + } + if (!empty($parentInfo->propertyInfos) && !isset($parentsWithInheritedProperties[$parent->toString()])) { $parentsWithInheritedProperties[$parent->toString()] = $parent; } @@ -2060,7 +2674,33 @@ private function collectInheritedMembers(array &$parentsWithInheritedProperties, $parentsWithInheritedMethods[$parent->toString()] = $parent; } - $parentInfo->collectInheritedMembers($parentsWithInheritedProperties, $parentsWithInheritedMethods, $classMap); + $parentInfo->collectInheritedMembers( + $parentsWithInheritedConstants, + $parentsWithInheritedProperties, + $parentsWithInheritedMethods, + $classMap + ); + } + + foreach ($this->implements as $parent) { + $parentInfo = $classMap[$parent->toString()] ?? null; + if (!$parentInfo) { + throw new Exception("Missing parent interface " . $parent->toString()); + } + + if (!empty($parentInfo->constInfos) && !isset($parentsWithInheritedConstants[$parent->toString()])) { + $parentsWithInheritedConstants[$parent->toString()] = $parent; + } + + $unusedParentsWithInheritedProperties = []; + $unusedParentsWithInheritedMethods = []; + + $parentInfo->collectInheritedMembers( + $parentsWithInheritedConstants, + $unusedParentsWithInheritedProperties, + $parentsWithInheritedMethods, + $classMap + ); } } @@ -2121,9 +2761,37 @@ public function __clone() $this->funcInfos[$key] = clone $funcInfo; } } + + /** + * @param Name[] $parents + */ + private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, DOMElement $classSynopsis, array $parents, string $label, string $inheritedLabel): void + { + if (empty($parents)) { + return; + } + + $classSynopsis->appendChild(new DOMText("\n\n ")); + $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "$inheritedLabel"); + $classSynopsisInfo->setAttribute("role", "comment"); + $classSynopsis->appendChild($classSynopsisInfo); + + foreach ($parents as $parent) { + $classSynopsis->appendChild(new DOMText("\n ")); + $parentReference = self::getClassSynopsisReference($parent); + + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:partintro/db:section/db:classsynopsis/db:fieldsynopsis[preceding-sibling::db:classsynopsisinfo[1][@role='comment' and text()='$label']]))" + ); + $classSynopsis->appendChild($includeElement); + } + } } class FileInfo { + /** @var ConstInfo[] */ + public $constInfos = []; /** @var FuncInfo[] */ public $funcInfos = []; /** @var ClassInfo[] */ @@ -2147,6 +2815,19 @@ public function getAllFuncInfos(): iterable { } } + /** + * @return iterable + */ + public function getAllConstInfos(): iterable { + $result = $this->constInfos; + + foreach ($this->classInfos as $classInfo) { + $result = array_merge($result, $classInfo->constInfos); + } + + return $result; + } + /** * @return iterable */ @@ -2393,6 +3074,50 @@ function parseFunctionLike( } } +function parseConstLike( + PrettyPrinterAbstract $prettyPrinter, + ConstOrClassConstName $name, + Node\Const_ $const, + int $flags, + ?DocComment $docComment, + ?string $cond +): ConstInfo { + $phpDocType = null; + $deprecated = false; + $cname = null; + $link = null; + if ($docComment) { + $tags = parseDocComment($docComment); + foreach ($tags as $tag) { + if ($tag->name === 'var') { + $phpDocType = $tag->getType(); + } elseif ($tag->name === 'deprecated') { + $deprecated = true; + } elseif ($tag->name === 'cname') { + $cname = $tag->value; + } elseif ($tag->name === 'link') { + $link = $tag->value; + } + } + } + + if ($phpDocType === null) { + throw new Exception("Missing type for constant " . $name->__toString()); + } + + return new ConstInfo( + $name, + $flags, + $const->value, + $prettyPrinter->prettyPrintExpr($const->value), + Type::fromString($phpDocType), + $deprecated, + $cond, + $cname, + $link + ); +} + function parseProperty( Name $class, int $flags, @@ -2447,12 +3172,18 @@ function parseProperty( } /** + * @param ConstInfo[] $consts * @param PropertyInfo[] $properties * @param FuncInfo[] $methods * @param EnumCaseInfo[] $enumCases */ function parseClass( - Name $name, Stmt\ClassLike $class, array $properties, array $methods, array $enumCases + Name $name, + Stmt\ClassLike $class, + array $consts, + array $properties, + array $methods, + array $enumCases ): ClassInfo { $flags = $class instanceof Class_ ? $class->flags : 0; $comment = $class->getDocComment(); @@ -2509,6 +3240,7 @@ function parseClass( $isNotSerializable, $extends, $implements, + $consts, $properties, $methods, $enumCases @@ -2573,6 +3305,21 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } $cond = handlePreprocessorConditions($conds, $stmt); + + if ($stmt instanceof Stmt\Const_) { + foreach ($stmt->consts as $const) { + $fileInfo->constInfos[] = parseConstLike( + $prettyPrinter, + new ConstName($const->name->toString()), + $const, + 0, + $stmt->getDocComment(), + $cond, + ); + } + continue; + } + if ($stmt instanceof Stmt\Function_) { $fileInfo->funcInfos[] = parseFunctionLike( $prettyPrinter, @@ -2587,6 +3334,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac if ($stmt instanceof Stmt\ClassLike) { $className = $stmt->namespacedName; + $constInfos = []; $propertyInfos = []; $methodInfos = []; $enumCaseInfos = []; @@ -2599,7 +3347,18 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $classFlags = $stmt instanceof Class_ ? $stmt->flags : 0; $abstractFlag = $stmt instanceof Stmt\Interface_ ? Class_::MODIFIER_ABSTRACT : 0; - if ($classStmt instanceof Stmt\Property) { + if ($classStmt instanceof Stmt\ClassConst) { + foreach ($classStmt->consts as $const) { + $constInfos[] = parseConstLike( + $prettyPrinter, + new ClassConstName($className, $const->name->toString()), + $const, + $classStmt->flags, + $classStmt->getDocComment(), + $cond + ); + } + } else if ($classStmt instanceof Stmt\Property) { if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { throw new Exception("Visibility modifier is required"); } @@ -2634,7 +3393,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } $fileInfo->classInfos[] = parseClass( - $className, $stmt, $propertyInfos, $methodInfos, $enumCaseInfos); + $className, $stmt, $constInfos, $propertyInfos, $methodInfos, $enumCaseInfos + ); continue; } @@ -2795,31 +3555,41 @@ function findEquivalentFuncInfo(array $generatedFuncInfos, FuncInfo $funcInfo): return null; } -/** @param iterable $funcInfos */ +/** @param iterable $infos */ function generateCodeWithConditions( - iterable $funcInfos, string $separator, Closure $codeGenerator): string { + iterable $infos, string $separator, Closure $codeGenerator): string { $code = ""; - foreach ($funcInfos as $funcInfo) { - $funcCode = $codeGenerator($funcInfo); - if ($funcCode === null) { + foreach ($infos as $info) { + $infoCode = $codeGenerator($info); + if ($infoCode === null) { continue; } $code .= $separator; - if ($funcInfo->cond) { - $code .= "#if {$funcInfo->cond}\n"; - $code .= $funcCode; + if ($info->cond) { + $code .= "#if {$info->cond}\n"; + $code .= $infoCode; $code .= "#endif\n"; } else { - $code .= $funcCode; + $code .= $infoCode; } } + return $code; } -function generateArgInfoCode(FileInfo $fileInfo, string $stubHash): string { +/** + * @param iterable $allConstInfos + */ +function generateArgInfoCode( + string $stubFilenameWithoutExtension, + FileInfo $fileInfo, + iterable $allConstInfos, + string $stubHash +): string { $code = "/* This is a generated file, edit the .stub.php file instead.\n" . " * Stub hash: $stubHash */\n"; + $generatedFuncInfos = []; $code .= generateCodeWithConditions( $fileInfo->getAllFuncInfos(), "\n", @@ -2866,17 +3636,31 @@ function (FuncInfo $funcInfo) use($fileInfo, &$generatedFunctionDeclarations) { } if ($fileInfo->generateClassEntries) { - $code .= generateClassEntryCode($fileInfo); + if (!empty($fileInfo->constInfos)) { + $code .= "\nstatic void register_{$stubFilenameWithoutExtension}_consts(int module_number)\n"; + $code .= "{\n"; + + foreach ($fileInfo->constInfos as $constInfo) { + $code .= $constInfo->getDeclaration($allConstInfos); + } + + $code .= "}\n"; + } + + $code .= generateClassEntryCode($fileInfo, $allConstInfos); } return $code; } -function generateClassEntryCode(FileInfo $fileInfo): string { +/** + * @param iterable $allConstInfos + */ +function generateClassEntryCode(FileInfo $fileInfo, iterable $allConstInfos): string { $code = ""; foreach ($fileInfo->classInfos as $class) { - $code .= "\n" . $class->getRegistration(); + $code .= "\n" . $class->getRegistration($allConstInfos); } return $code; @@ -2919,14 +3703,15 @@ function generateOptimizerInfo(array $funcInfos): string { } /** - * @param ClassInfo[] $classMap + * @param array $classMap + * @param iterable $allConstInfos * @return array */ -function generateClassSynopses(array $classMap): array { +function generateClassSynopses(array $classMap, iterable $allConstInfos): array { $result = []; foreach ($classMap as $classInfo) { - $classSynopsis = $classInfo->getClassSynopsisDocument($classMap); + $classSynopsis = $classInfo->getClassSynopsisDocument($classMap, $allConstInfos); if ($classSynopsis !== null) { $result[ClassInfo::getClassSynopsisFilename($classInfo->name) . ".xml"] = $classSynopsis; } @@ -2937,9 +3722,10 @@ function generateClassSynopses(array $classMap): array { /** * @param ClassInfo[] $classMap + * $param iterable $allConstInfos * @return array */ -function replaceClassSynopses(string $targetDirectory, array $classMap): array +function replaceClassSynopses(string $targetDirectory, array $classMap, iterable $allConstInfos): array { $classSynopses = []; @@ -2999,7 +3785,7 @@ function replaceClassSynopses(string $targetDirectory, array $classMap): array } $classInfo = $classMap[$className]; - $newClassSynopsis = $classInfo->getClassSynopsisElement($doc, $classMap); + $newClassSynopsis = $classInfo->getClassSynopsisElement($doc, $classMap, $allConstInfos); if ($newClassSynopsis === null) { continue; } @@ -3492,7 +4278,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($generateClassSynopses) { $classSynopsesDirectory = getcwd() . "/classsynopses"; - $classSynopses = generateClassSynopses($classMap); + $classSynopses = generateClassSynopses($classMap, $context->allConstInfos); if (!empty($classSynopses)) { if (!file_exists($classSynopsesDirectory)) { mkdir($classSynopsesDirectory); @@ -3507,7 +4293,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } if ($replaceClassSynopses) { - $classSynopses = replaceClassSynopses($targetSynopses, $classMap); + $classSynopses = replaceClassSynopses($targetSynopses, $classMap, $context->allConstInfos); foreach ($classSynopses as $filename => $content) { if (file_put_contents($filename, $content)) { diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 41521e27d0049..5d2fb5b79b260 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -71,6 +71,133 @@ PHPAPI time_t php_time(void) #endif } +/* + * RFC822, Section 5.1: http://www.ietf.org/rfc/rfc822.txt + * date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz + * day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" + * date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82 + * month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + * time = hour zone ; ANSI and Military + * hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59 + * zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" / "MST" / "MDT" / "PST" / "PDT" / 1ALPHA / ( ("+" / "-") 4DIGIT ) + */ +#define DATE_FORMAT_RFC822 "D, d M y H:i:s O" + +/* + * RFC850, Section 2.1.4: http://www.ietf.org/rfc/rfc850.txt + * Format must be acceptable both to the ARPANET and to the getdate routine. + * One format that is acceptable to both is Weekday, DD-Mon-YY HH:MM:SS TIMEZONE + * TIMEZONE can be any timezone name (3 or more letters) + */ +#define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T" + +/* + * RFC1036, Section 2.1.2: http://www.ietf.org/rfc/rfc1036.txt + * Its format must be acceptable both in RFC-822 and to the getdate(3) + * Wdy, DD Mon YY HH:MM:SS TIMEZONE + * There is no hope of having a complete list of timezones. Universal + * Time (GMT), the North American timezones (PST, PDT, MST, MDT, CST, + * CDT, EST, EDT) and the +/-hhmm offset specified in RFC-822 should be supported. + */ +#define DATE_FORMAT_RFC1036 "D, d M y H:i:s O" + +/* + * RFC1123, Section 5.2.14: http://www.ietf.org/rfc/rfc1123.txt + * RFC-822 Date and Time Specification: RFC-822 Section 5 + * The syntax for the date is hereby changed to: date = 1*2DIGIT month 2*4DIGIT + */ +#define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O" + +/* + * RFC7231, Section 7.1.1: http://tools.ietf.org/html/rfc7231 + */ +#define DATE_FORMAT_RFC7231 "D, d M Y H:i:s \\G\\M\\T" + +/* + * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt + * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + * CFWS = *([FWS] comment) (([FWS] comment) / FWS) + * + * date-time = [ day-of-week "," ] date FWS time [CFWS] + * day-of-week = ([FWS] day-name) + * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" + * date = day month year + * year = 4*DIGIT + * month = (FWS month-name FWS) + * month-name = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + * day = ([FWS] 1*2DIGIT) + * time = time-of-day FWS zone + * time-of-day = hour ":" minute [ ":" second ] + * hour = 2DIGIT + * minute = 2DIGIT + * second = 2DIGIT + * zone = (( "+" / "-" ) 4DIGIT) + */ +#define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O" +/* + * RFC3339, Section 5.6: http://www.ietf.org/rfc/rfc3339.txt + * date-fullyear = 4DIGIT + * date-month = 2DIGIT ; 01-12 + * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year + * + * time-hour = 2DIGIT ; 00-23 + * time-minute = 2DIGIT ; 00-59 + * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules + * + * time-secfrac = "." 1*DIGIT + * time-numoffset = ("+" / "-") time-hour ":" time-minute + * time-offset = "Z" / time-numoffset + * + * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] + * full-date = date-fullyear "-" date-month "-" date-mday + * full-time = partial-time time-offset + * + * date-time = full-date "T" full-time + */ +#define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP" + +#define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO" + +/* + * RFC3339, Appendix A: http://www.ietf.org/rfc/rfc3339.txt + * ISO 8601 also requires (in section 5.3.1.3) that a decimal fraction + * be proceeded by a "0" if less than unity. Annex B.2 of ISO 8601 + * gives examples where the decimal fractions are not preceded by a "0". + * This grammar assumes section 5.3.1.3 is correct and that Annex B.2 is + * in error. + */ +#define DATE_FORMAT_RFC3339_EXTENDED "Y-m-d\\TH:i:s.vP" + +/* + * This comes from various sources that like to contradict. I'm going with the + * format here because of: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa384321%28v=vs.85%29.aspx + * and http://curl.haxx.se/rfc/cookie_spec.html + */ +#define DATE_FORMAT_COOKIE "l, d-M-Y H:i:s T" + +#define SUNFUNCS_RET_TIMESTAMP 0 +#define SUNFUNCS_RET_STRING 1 +#define SUNFUNCS_RET_DOUBLE 2 + +#define PHP_DATE_TIMEZONE_GROUP_AFRICA 0x0001 +#define PHP_DATE_TIMEZONE_GROUP_AMERICA 0x0002 +#define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA 0x0004 +#define PHP_DATE_TIMEZONE_GROUP_ARCTIC 0x0008 +#define PHP_DATE_TIMEZONE_GROUP_ASIA 0x0010 +#define PHP_DATE_TIMEZONE_GROUP_ATLANTIC 0x0020 +#define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA 0x0040 +#define PHP_DATE_TIMEZONE_GROUP_EUROPE 0x0080 +#define PHP_DATE_TIMEZONE_GROUP_INDIAN 0x0100 +#define PHP_DATE_TIMEZONE_GROUP_PACIFIC 0x0200 +#define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400 +#define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF +#define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF +#define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000 + +#define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001 +#define PHP_DATE_PERIOD_INCLUDE_END_DATE 0x0002 + #include "php_date_arginfo.h" static char* guess_timezone(const timelib_tzdb *tzdb); @@ -272,157 +399,12 @@ ZEND_MODULE_POST_ZEND_DEACTIVATE_D(date) #define DATE_TIMEZONEDB php_date_global_timezone_db ? php_date_global_timezone_db : timelib_builtin_db() -/* - * RFC822, Section 5.1: http://www.ietf.org/rfc/rfc822.txt - * date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz - * day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" - * date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82 - * month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" - * time = hour zone ; ANSI and Military - * hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59 - * zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" / "MST" / "MDT" / "PST" / "PDT" / 1ALPHA / ( ("+" / "-") 4DIGIT ) - */ -#define DATE_FORMAT_RFC822 "D, d M y H:i:s O" - -/* - * RFC850, Section 2.1.4: http://www.ietf.org/rfc/rfc850.txt - * Format must be acceptable both to the ARPANET and to the getdate routine. - * One format that is acceptable to both is Weekday, DD-Mon-YY HH:MM:SS TIMEZONE - * TIMEZONE can be any timezone name (3 or more letters) - */ -#define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T" - -/* - * RFC1036, Section 2.1.2: http://www.ietf.org/rfc/rfc1036.txt - * Its format must be acceptable both in RFC-822 and to the getdate(3) - * Wdy, DD Mon YY HH:MM:SS TIMEZONE - * There is no hope of having a complete list of timezones. Universal - * Time (GMT), the North American timezones (PST, PDT, MST, MDT, CST, - * CDT, EST, EDT) and the +/-hhmm offset specified in RFC-822 should be supported. - */ -#define DATE_FORMAT_RFC1036 "D, d M y H:i:s O" - -/* - * RFC1123, Section 5.2.14: http://www.ietf.org/rfc/rfc1123.txt - * RFC-822 Date and Time Specification: RFC-822 Section 5 - * The syntax for the date is hereby changed to: date = 1*2DIGIT month 2*4DIGIT - */ -#define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O" - -/* - * RFC7231, Section 7.1.1: http://tools.ietf.org/html/rfc7231 - */ -#define DATE_FORMAT_RFC7231 "D, d M Y H:i:s \\G\\M\\T" - -/* - * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt - * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space - * CFWS = *([FWS] comment) (([FWS] comment) / FWS) - * - * date-time = [ day-of-week "," ] date FWS time [CFWS] - * day-of-week = ([FWS] day-name) - * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" - * date = day month year - * year = 4*DIGIT - * month = (FWS month-name FWS) - * month-name = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" - * day = ([FWS] 1*2DIGIT) - * time = time-of-day FWS zone - * time-of-day = hour ":" minute [ ":" second ] - * hour = 2DIGIT - * minute = 2DIGIT - * second = 2DIGIT - * zone = (( "+" / "-" ) 4DIGIT) - */ -#define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O" -/* - * RFC3339, Section 5.6: http://www.ietf.org/rfc/rfc3339.txt - * date-fullyear = 4DIGIT - * date-month = 2DIGIT ; 01-12 - * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year - * - * time-hour = 2DIGIT ; 00-23 - * time-minute = 2DIGIT ; 00-59 - * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules - * - * time-secfrac = "." 1*DIGIT - * time-numoffset = ("+" / "-") time-hour ":" time-minute - * time-offset = "Z" / time-numoffset - * - * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] - * full-date = date-fullyear "-" date-month "-" date-mday - * full-time = partial-time time-offset - * - * date-time = full-date "T" full-time - */ -#define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP" - -#define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO" - -/* - * RFC3339, Appendix A: http://www.ietf.org/rfc/rfc3339.txt - * ISO 8601 also requires (in section 5.3.1.3) that a decimal fraction - * be proceeded by a "0" if less than unity. Annex B.2 of ISO 8601 - * gives examples where the decimal fractions are not preceded by a "0". - * This grammar assumes section 5.3.1.3 is correct and that Annex B.2 is - * in error. - */ -#define DATE_FORMAT_RFC3339_EXTENDED "Y-m-d\\TH:i:s.vP" - -/* - * This comes from various sources that like to contradict. I'm going with the - * format here because of: - * http://msdn.microsoft.com/en-us/library/windows/desktop/aa384321%28v=vs.85%29.aspx - * and http://curl.haxx.se/rfc/cookie_spec.html - */ -#define DATE_FORMAT_COOKIE "l, d-M-Y H:i:s T" - -#define SUNFUNCS_RET_TIMESTAMP 0 -#define SUNFUNCS_RET_STRING 1 -#define SUNFUNCS_RET_DOUBLE 2 - /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(date) { REGISTER_INI_ENTRIES(); + register_php_date_consts(module_number); date_register_classes(); -/* - * RFC4287, Section 3.3: http://www.ietf.org/rfc/rfc4287.txt - * A Date construct is an element whose content MUST conform to the - * "date-time" production in [RFC3339]. In addition, an uppercase "T" - * character MUST be used to separate date and time, and an uppercase - * "Z" character MUST be present in the absence of a numeric time zone offset. - */ - REGISTER_STRING_CONSTANT("DATE_ATOM", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); -/* - * Preliminary specification: http://wp.netscape.com/newsref/std/cookie_spec.html - * "This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, - * with the variations that the only legal time zone is GMT - * and the separators between the elements of the date must be dashes." - */ - REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_COOKIE, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT); - - REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC7231", DATE_FORMAT_RFC7231, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED, CONST_CS | CONST_PERSISTENT); - -/* - * RSS 2.0 Specification: http://blogs.law.harvard.edu/tech/rss - * "All date-times in RSS conform to the Date and Time Specification of RFC 822, - * with the exception that the year may be expressed with two characters or four characters (four preferred)" - */ - REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_CS | CONST_PERSISTENT); php_date_global_timezone_db = NULL; php_date_global_timezone_db_enabled = 0; @@ -1414,25 +1396,6 @@ PHP_FUNCTION(getdate) } /* }}} */ -#define PHP_DATE_TIMEZONE_GROUP_AFRICA 0x0001 -#define PHP_DATE_TIMEZONE_GROUP_AMERICA 0x0002 -#define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA 0x0004 -#define PHP_DATE_TIMEZONE_GROUP_ARCTIC 0x0008 -#define PHP_DATE_TIMEZONE_GROUP_ASIA 0x0010 -#define PHP_DATE_TIMEZONE_GROUP_ATLANTIC 0x0020 -#define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA 0x0040 -#define PHP_DATE_TIMEZONE_GROUP_EUROPE 0x0080 -#define PHP_DATE_TIMEZONE_GROUP_INDIAN 0x0100 -#define PHP_DATE_TIMEZONE_GROUP_PACIFIC 0x0200 -#define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400 -#define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF -#define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF -#define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000 - -#define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001 -#define PHP_DATE_PERIOD_INCLUDE_END_DATE 0x0002 - - /* define an overloaded iterator structure */ typedef struct { zend_object_iterator intern; @@ -1644,23 +1607,6 @@ static void date_register_classes(void) /* {{{ */ date_ce_interface = register_class_DateTimeInterface(); date_ce_interface->interface_gets_implemented = implement_date_interface_handler; -#define REGISTER_DATE_INTERFACE_CONST_STRING(const_name, value) \ - zend_declare_class_constant_stringl(date_ce_interface, const_name, sizeof(const_name)-1, value, sizeof(value)-1); - - REGISTER_DATE_INTERFACE_CONST_STRING("ATOM", DATE_FORMAT_RFC3339); - REGISTER_DATE_INTERFACE_CONST_STRING("COOKIE", DATE_FORMAT_COOKIE); - REGISTER_DATE_INTERFACE_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC822", DATE_FORMAT_RFC822); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC850", DATE_FORMAT_RFC850); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC1036", DATE_FORMAT_RFC1036); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC1123", DATE_FORMAT_RFC1123); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC7231", DATE_FORMAT_RFC7231); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC2822", DATE_FORMAT_RFC2822); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC3339", DATE_FORMAT_RFC3339); - REGISTER_DATE_INTERFACE_CONST_STRING("RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED); - REGISTER_DATE_INTERFACE_CONST_STRING("RSS", DATE_FORMAT_RFC1123); - REGISTER_DATE_INTERFACE_CONST_STRING("W3C", DATE_FORMAT_RFC3339); - date_ce_date = register_class_DateTime(date_ce_interface); date_ce_date->create_object = date_object_new_date; memcpy(&date_object_handlers_date, &std_object_handlers, sizeof(zend_object_handlers)); @@ -1690,24 +1636,6 @@ static void date_register_classes(void) /* {{{ */ date_object_handlers_timezone.get_debug_info = date_object_get_debug_info_timezone; date_object_handlers_timezone.compare = date_object_compare_timezone; -#define REGISTER_TIMEZONE_CLASS_CONST_STRING(const_name, value) \ - zend_declare_class_constant_long(date_ce_timezone, const_name, sizeof(const_name)-1, value); - - REGISTER_TIMEZONE_CLASS_CONST_STRING("AFRICA", PHP_DATE_TIMEZONE_GROUP_AFRICA); - REGISTER_TIMEZONE_CLASS_CONST_STRING("AMERICA", PHP_DATE_TIMEZONE_GROUP_AMERICA); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ANTARCTICA", PHP_DATE_TIMEZONE_GROUP_ANTARCTICA); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ARCTIC", PHP_DATE_TIMEZONE_GROUP_ARCTIC); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ASIA", PHP_DATE_TIMEZONE_GROUP_ASIA); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ATLANTIC", PHP_DATE_TIMEZONE_GROUP_ATLANTIC); - REGISTER_TIMEZONE_CLASS_CONST_STRING("AUSTRALIA", PHP_DATE_TIMEZONE_GROUP_AUSTRALIA); - REGISTER_TIMEZONE_CLASS_CONST_STRING("EUROPE", PHP_DATE_TIMEZONE_GROUP_EUROPE); - REGISTER_TIMEZONE_CLASS_CONST_STRING("INDIAN", PHP_DATE_TIMEZONE_GROUP_INDIAN); - REGISTER_TIMEZONE_CLASS_CONST_STRING("PACIFIC", PHP_DATE_TIMEZONE_GROUP_PACIFIC); - REGISTER_TIMEZONE_CLASS_CONST_STRING("UTC", PHP_DATE_TIMEZONE_GROUP_UTC); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL", PHP_DATE_TIMEZONE_GROUP_ALL); - REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC", PHP_DATE_TIMEZONE_GROUP_ALL_W_BC); - REGISTER_TIMEZONE_CLASS_CONST_STRING("PER_COUNTRY", PHP_DATE_TIMEZONE_PER_COUNTRY); - date_ce_interval = register_class_DateInterval(); date_ce_interval->create_object = date_object_new_interval; memcpy(&date_object_handlers_interval, &std_object_handlers, sizeof(zend_object_handlers)); @@ -1734,12 +1662,6 @@ static void date_register_classes(void) /* {{{ */ date_object_handlers_period.get_gc = date_object_get_gc_period; date_object_handlers_period.read_property = date_period_read_property; date_object_handlers_period.write_property = date_period_write_property; - -#define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \ - zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value); - - REGISTER_PERIOD_CLASS_CONST_STRING("EXCLUDE_START_DATE", PHP_DATE_PERIOD_EXCLUDE_START_DATE); - REGISTER_PERIOD_CLASS_CONST_STRING("INCLUDE_END_DATE", PHP_DATE_PERIOD_INCLUDE_END_DATE); } /* }}} */ static zend_object *date_object_new_date(zend_class_entry *class_type) /* {{{ */ diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index 347dd6c99e622..68b16a07a12f1 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -2,6 +2,96 @@ /** @generate-class-entries */ +/** + * @var string + * @cname DATE_FORMAT_RFC3339 + */ +const DATE_ATOM = "Y-m-d\\TH:i:sP"; + +/** + * @var string + * @cname DATE_FORMAT_COOKIE + */ +const DATE_COOKIE = "l, d-M-Y H:i:s T"; + +/** + * @var string + * @cname DATE_FORMAT_ISO8601 + */ +const DATE_ISO8601 = "Y-m-d\\TH:i:sO"; + +/** + * @var string + * @cname DATE_FORMAT_RFC822 + */ +const DATE_RFC822 = "D, d M y H:i:s O"; + +/** + * @var string + * @cname DATE_FORMAT_RFC850 + */ +const DATE_RFC850 = "l, d-M-y H:i:s T"; + +/** + * @var string + * @cname DATE_FORMAT_RFC1036 + */ +const DATE_RFC1036 = "D, d M y H:i:s O"; + +/** + * @var string + * @cname DATE_FORMAT_RFC1123 + */ +const DATE_RFC1123 = "D, d M Y H:i:s O"; + +/** + * @var string + * @cname DATE_FORMAT_RFC7231 + */ +const DATE_RFC7231 = "D, d M Y H:i:s \\G\\M\\T"; + +/** + * @var string + * @cname DATE_FORMAT_RFC2822 + */ +const DATE_RFC2822 = "D, d M Y H:i:s O"; + +/** + * @var string + * @cname DATE_FORMAT_RFC3339 + */ +const DATE_RFC3339 = "Y-m-d\\TH:i:sP"; + +/** + * @var string + * @cname DATE_FORMAT_RFC3339_EXTENDED + */ +const DATE_RFC3339_EXTENDED = "Y-m-d\\TH:i:s.vP"; + +/** @var string */ +const DATE_RSS = DATE_RFC1123; + +/** @var string */ +const DATE_W3C = DATE_RFC3339; + +/** + * @var int + * @cname SUNFUNCS_RET_TIMESTAMP + */ +const SUNFUNCS_RET_TIMESTAMP = UNKNOWN; + +/** + * @var int + * @cname SUNFUNCS_RET_STRING + */ +const SUNFUNCS_RET_STRING = UNKNOWN; + +/** + * @var int + * @cname SUNFUNCS_RET_DOUBLE + */ +const SUNFUNCS_RET_DOUBLE = UNKNOWN; + function strtotime(string $datetime, ?int $baseTimestamp = null): int|false {} /** @refcount 1 */ @@ -188,6 +278,33 @@ function date_sun_info(int $timestamp, float $latitude, float $longitude): array interface DateTimeInterface { + /** @var string */ + public const ATOM = DATE_ATOM; + /** @var string */ + public const COOKIE = DATE_COOKIE; + /** @var string */ + public const ISO8601 = DATE_ISO8601; + /** @var string */ + public const RFC822 = DATE_RFC822; + /** @var string */ + public const RFC850 = DATE_RFC850; + /** @var string */ + public const RFC1036 = DATE_RFC1036; + /** @var string */ + public const RFC1123 = DATE_RFC1123; + /** @var string */ + public const RFC7231 = DATE_RFC7231; + /** @var string */ + public const RFC2822 = DATE_RFC2822; + /** @var string */ + public const RFC3339 = DATE_RFC3339; + /** @var string */ + public const RFC3339_EXTENDED = DATE_RFC3339_EXTENDED; + /** @var string */ + public const RSS = DATE_RSS; + /** @var string */ + public const W3C = DATE_W3C; + /** @tentative-return-type */ public function format(string $format): string; @@ -413,6 +530,77 @@ public static function createFromInterface(DateTimeInterface $object): DateTimeI class DateTimeZone { + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_AFRICA + */ + public const AFRICA = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_AMERICA + */ + public const AMERICA = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ANTARCTICA + */ + public const ANTARCTICA = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ARCTIC + */ + public const ARCTIC = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ASIA + */ + public const ASIA = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ATLANTIC + */ + public const ATLANTIC = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_AUSTRALIA + */ + public const AUSTRALIA = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_EUROPE + */ + public const EUROPE = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_INDIAN + */ + public const INDIAN = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_PACIFIC + */ + public const PACIFIC = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_UTC + */ + public const UTC = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ALL + */ + public const ALL = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_GROUP_ALL_W_BC + */ + public const ALL_WITH_BC = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_TIMEZONE_PER_COUNTRY + */ + public const PER_COUNTRY = UNKNOWN; + public function __construct(string $timezone) {} /** @@ -495,6 +683,17 @@ public static function __set_state(array $array): DateInterval {} class DatePeriod implements IteratorAggregate { + /** + * @var int + * @cname PHP_DATE_PERIOD_EXCLUDE_START_DATE + */ + public const EXCLUDE_START_DATE = UNKNOWN; + /** + * @var int + * @cname PHP_DATE_PERIOD_INCLUDE_END_DATE + */ + public const INCLUDE_END_DATE = UNKNOWN; + /** * @param DateTimeInterface|string $start * @param DateInterval|int $interval diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 3621fc331545d..2183458ec98fa 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: ca149a2efec878f0730eb744f4e11f6462d70d83 */ + * Stub hash: 2cdf90d626d020b7e746cbccdb87833720d87132 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0) @@ -748,6 +748,37 @@ static const zend_function_entry class_DatePeriod_methods[] = { ZEND_FE_END }; +static void register_php_date_consts(int module_number) +{ + REGISTER_STRING_CONSTANT("DATE_ATOM", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC3339, "Y-m-d\\TH:i:sP") == 0); + REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_COOKIE, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_COOKIE, "l, d-M-Y H:i:s T") == 0); + REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_ISO8601, "Y-m-d\\TH:i:sO") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC822, "D, d M y H:i:s O") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC850, "l, d-M-y H:i:s T") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC1036, "D, d M y H:i:s O") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC1123, "D, d M Y H:i:s O") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC7231", DATE_FORMAT_RFC7231, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC7231, "D, d M Y H:i:s \\G\\M\\T") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC2822, "D, d M Y H:i:s O") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC3339, "Y-m-d\\TH:i:sP") == 0); + REGISTER_STRING_CONSTANT("DATE_RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(strcmp(DATE_FORMAT_RFC3339_EXTENDED, "Y-m-d\\TH:i:s.vP") == 0); + REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_CS | CONST_PERSISTENT); +} + static zend_class_entry *register_class_DateTimeInterface(void) { zend_class_entry ce, *class_entry; @@ -755,6 +786,97 @@ static zend_class_entry *register_class_DateTimeInterface(void) INIT_CLASS_ENTRY(ce, "DateTimeInterface", class_DateTimeInterface_methods); class_entry = zend_register_internal_interface(&ce); + zval const_ATOM_value; + zend_string *const_ATOM_value_str = zend_string_init(DATE_FORMAT_RFC3339, sizeof(DATE_FORMAT_RFC3339) - 1, 1); + ZVAL_STR(&const_ATOM_value, const_ATOM_value_str); + zend_string *const_ATOM_name = zend_string_init_interned("ATOM", sizeof("ATOM") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATOM_name, &const_ATOM_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATOM_name); + + zval const_COOKIE_value; + zend_string *const_COOKIE_value_str = zend_string_init(DATE_FORMAT_COOKIE, sizeof(DATE_FORMAT_COOKIE) - 1, 1); + ZVAL_STR(&const_COOKIE_value, const_COOKIE_value_str); + zend_string *const_COOKIE_name = zend_string_init_interned("COOKIE", sizeof("COOKIE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_COOKIE_name, &const_COOKIE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_COOKIE_name); + + zval const_ISO8601_value; + zend_string *const_ISO8601_value_str = zend_string_init(DATE_FORMAT_ISO8601, sizeof(DATE_FORMAT_ISO8601) - 1, 1); + ZVAL_STR(&const_ISO8601_value, const_ISO8601_value_str); + zend_string *const_ISO8601_name = zend_string_init_interned("ISO8601", sizeof("ISO8601") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ISO8601_name, &const_ISO8601_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ISO8601_name); + + zval const_RFC822_value; + zend_string *const_RFC822_value_str = zend_string_init(DATE_FORMAT_RFC822, sizeof(DATE_FORMAT_RFC822) - 1, 1); + ZVAL_STR(&const_RFC822_value, const_RFC822_value_str); + zend_string *const_RFC822_name = zend_string_init_interned("RFC822", sizeof("RFC822") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC822_name, &const_RFC822_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC822_name); + + zval const_RFC850_value; + zend_string *const_RFC850_value_str = zend_string_init(DATE_FORMAT_RFC850, sizeof(DATE_FORMAT_RFC850) - 1, 1); + ZVAL_STR(&const_RFC850_value, const_RFC850_value_str); + zend_string *const_RFC850_name = zend_string_init_interned("RFC850", sizeof("RFC850") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC850_name, &const_RFC850_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC850_name); + + zval const_RFC1036_value; + zend_string *const_RFC1036_value_str = zend_string_init(DATE_FORMAT_RFC1036, sizeof(DATE_FORMAT_RFC1036) - 1, 1); + ZVAL_STR(&const_RFC1036_value, const_RFC1036_value_str); + zend_string *const_RFC1036_name = zend_string_init_interned("RFC1036", sizeof("RFC1036") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC1036_name, &const_RFC1036_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC1036_name); + + zval const_RFC1123_value; + zend_string *const_RFC1123_value_str = zend_string_init(DATE_FORMAT_RFC1123, sizeof(DATE_FORMAT_RFC1123) - 1, 1); + ZVAL_STR(&const_RFC1123_value, const_RFC1123_value_str); + zend_string *const_RFC1123_name = zend_string_init_interned("RFC1123", sizeof("RFC1123") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC1123_name, &const_RFC1123_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC1123_name); + + zval const_RFC7231_value; + zend_string *const_RFC7231_value_str = zend_string_init(DATE_FORMAT_RFC7231, sizeof(DATE_FORMAT_RFC7231) - 1, 1); + ZVAL_STR(&const_RFC7231_value, const_RFC7231_value_str); + zend_string *const_RFC7231_name = zend_string_init_interned("RFC7231", sizeof("RFC7231") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC7231_name, &const_RFC7231_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC7231_name); + + zval const_RFC2822_value; + zend_string *const_RFC2822_value_str = zend_string_init(DATE_FORMAT_RFC2822, sizeof(DATE_FORMAT_RFC2822) - 1, 1); + ZVAL_STR(&const_RFC2822_value, const_RFC2822_value_str); + zend_string *const_RFC2822_name = zend_string_init_interned("RFC2822", sizeof("RFC2822") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC2822_name, &const_RFC2822_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC2822_name); + + zval const_RFC3339_value; + zend_string *const_RFC3339_value_str = zend_string_init(DATE_FORMAT_RFC3339, sizeof(DATE_FORMAT_RFC3339) - 1, 1); + ZVAL_STR(&const_RFC3339_value, const_RFC3339_value_str); + zend_string *const_RFC3339_name = zend_string_init_interned("RFC3339", sizeof("RFC3339") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC3339_name, &const_RFC3339_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC3339_name); + + zval const_RFC3339_EXTENDED_value; + zend_string *const_RFC3339_EXTENDED_value_str = zend_string_init(DATE_FORMAT_RFC3339_EXTENDED, sizeof(DATE_FORMAT_RFC3339_EXTENDED) - 1, 1); + ZVAL_STR(&const_RFC3339_EXTENDED_value, const_RFC3339_EXTENDED_value_str); + zend_string *const_RFC3339_EXTENDED_name = zend_string_init_interned("RFC3339_EXTENDED", sizeof("RFC3339_EXTENDED") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RFC3339_EXTENDED_name, &const_RFC3339_EXTENDED_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RFC3339_EXTENDED_name); + + zval const_RSS_value; + zend_string *const_RSS_value_str = zend_string_init(DATE_FORMAT_RFC1123, sizeof(DATE_FORMAT_RFC1123) - 1, 1); + ZVAL_STR(&const_RSS_value, const_RSS_value_str); + zend_string *const_RSS_name = zend_string_init_interned("RSS", sizeof("RSS") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_RSS_name, &const_RSS_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_RSS_name); + + zval const_W3C_value; + zend_string *const_W3C_value_str = zend_string_init(DATE_FORMAT_RFC3339, sizeof(DATE_FORMAT_RFC3339) - 1, 1); + ZVAL_STR(&const_W3C_value, const_W3C_value_str); + zend_string *const_W3C_name = zend_string_init_interned("W3C", sizeof("W3C") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_W3C_name, &const_W3C_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_W3C_name); + return class_entry; } @@ -787,6 +909,90 @@ static zend_class_entry *register_class_DateTimeZone(void) INIT_CLASS_ENTRY(ce, "DateTimeZone", class_DateTimeZone_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); + zval const_AFRICA_value; + ZVAL_LONG(&const_AFRICA_value, PHP_DATE_TIMEZONE_GROUP_AFRICA); + zend_string *const_AFRICA_name = zend_string_init_interned("AFRICA", sizeof("AFRICA") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_AFRICA_name, &const_AFRICA_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_AFRICA_name); + + zval const_AMERICA_value; + ZVAL_LONG(&const_AMERICA_value, PHP_DATE_TIMEZONE_GROUP_AMERICA); + zend_string *const_AMERICA_name = zend_string_init_interned("AMERICA", sizeof("AMERICA") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_AMERICA_name, &const_AMERICA_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_AMERICA_name); + + zval const_ANTARCTICA_value; + ZVAL_LONG(&const_ANTARCTICA_value, PHP_DATE_TIMEZONE_GROUP_ANTARCTICA); + zend_string *const_ANTARCTICA_name = zend_string_init_interned("ANTARCTICA", sizeof("ANTARCTICA") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ANTARCTICA_name, &const_ANTARCTICA_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ANTARCTICA_name); + + zval const_ARCTIC_value; + ZVAL_LONG(&const_ARCTIC_value, PHP_DATE_TIMEZONE_GROUP_ARCTIC); + zend_string *const_ARCTIC_name = zend_string_init_interned("ARCTIC", sizeof("ARCTIC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ARCTIC_name, &const_ARCTIC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ARCTIC_name); + + zval const_ASIA_value; + ZVAL_LONG(&const_ASIA_value, PHP_DATE_TIMEZONE_GROUP_ASIA); + zend_string *const_ASIA_name = zend_string_init_interned("ASIA", sizeof("ASIA") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ASIA_name, &const_ASIA_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ASIA_name); + + zval const_ATLANTIC_value; + ZVAL_LONG(&const_ATLANTIC_value, PHP_DATE_TIMEZONE_GROUP_ATLANTIC); + zend_string *const_ATLANTIC_name = zend_string_init_interned("ATLANTIC", sizeof("ATLANTIC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ATLANTIC_name, &const_ATLANTIC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ATLANTIC_name); + + zval const_AUSTRALIA_value; + ZVAL_LONG(&const_AUSTRALIA_value, PHP_DATE_TIMEZONE_GROUP_AUSTRALIA); + zend_string *const_AUSTRALIA_name = zend_string_init_interned("AUSTRALIA", sizeof("AUSTRALIA") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_AUSTRALIA_name, &const_AUSTRALIA_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_AUSTRALIA_name); + + zval const_EUROPE_value; + ZVAL_LONG(&const_EUROPE_value, PHP_DATE_TIMEZONE_GROUP_EUROPE); + zend_string *const_EUROPE_name = zend_string_init_interned("EUROPE", sizeof("EUROPE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_EUROPE_name, &const_EUROPE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_EUROPE_name); + + zval const_INDIAN_value; + ZVAL_LONG(&const_INDIAN_value, PHP_DATE_TIMEZONE_GROUP_INDIAN); + zend_string *const_INDIAN_name = zend_string_init_interned("INDIAN", sizeof("INDIAN") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_INDIAN_name, &const_INDIAN_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_INDIAN_name); + + zval const_PACIFIC_value; + ZVAL_LONG(&const_PACIFIC_value, PHP_DATE_TIMEZONE_GROUP_PACIFIC); + zend_string *const_PACIFIC_name = zend_string_init_interned("PACIFIC", sizeof("PACIFIC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_PACIFIC_name, &const_PACIFIC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_PACIFIC_name); + + zval const_UTC_value; + ZVAL_LONG(&const_UTC_value, PHP_DATE_TIMEZONE_GROUP_UTC); + zend_string *const_UTC_name = zend_string_init_interned("UTC", sizeof("UTC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_UTC_name, &const_UTC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_UTC_name); + + zval const_ALL_value; + ZVAL_LONG(&const_ALL_value, PHP_DATE_TIMEZONE_GROUP_ALL); + zend_string *const_ALL_name = zend_string_init_interned("ALL", sizeof("ALL") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ALL_name, &const_ALL_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ALL_name); + + zval const_ALL_WITH_BC_value; + ZVAL_LONG(&const_ALL_WITH_BC_value, PHP_DATE_TIMEZONE_GROUP_ALL_W_BC); + zend_string *const_ALL_WITH_BC_name = zend_string_init_interned("ALL_WITH_BC", sizeof("ALL_WITH_BC") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_ALL_WITH_BC_name, &const_ALL_WITH_BC_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_ALL_WITH_BC_name); + + zval const_PER_COUNTRY_value; + ZVAL_LONG(&const_PER_COUNTRY_value, PHP_DATE_TIMEZONE_PER_COUNTRY); + zend_string *const_PER_COUNTRY_name = zend_string_init_interned("PER_COUNTRY", sizeof("PER_COUNTRY") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_PER_COUNTRY_name, &const_PER_COUNTRY_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_PER_COUNTRY_name); + return class_entry; } @@ -808,5 +1014,17 @@ static zend_class_entry *register_class_DatePeriod(zend_class_entry *class_entry class_entry = zend_register_internal_class_ex(&ce, NULL); zend_class_implements(class_entry, 1, class_entry_IteratorAggregate); + zval const_EXCLUDE_START_DATE_value; + ZVAL_LONG(&const_EXCLUDE_START_DATE_value, PHP_DATE_PERIOD_EXCLUDE_START_DATE); + zend_string *const_EXCLUDE_START_DATE_name = zend_string_init_interned("EXCLUDE_START_DATE", sizeof("EXCLUDE_START_DATE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_EXCLUDE_START_DATE_name, &const_EXCLUDE_START_DATE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_EXCLUDE_START_DATE_name); + + zval const_INCLUDE_END_DATE_value; + ZVAL_LONG(&const_INCLUDE_END_DATE_value, PHP_DATE_PERIOD_INCLUDE_END_DATE); + zend_string *const_INCLUDE_END_DATE_name = zend_string_init_interned("INCLUDE_END_DATE", sizeof("INCLUDE_END_DATE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_INCLUDE_END_DATE_name, &const_INCLUDE_END_DATE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_INCLUDE_END_DATE_name); + return class_entry; } diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index 2ac8ae45f2b26..8c7faebbabafd 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1268,7 +1268,7 @@ static zend_class_entry *register_class_DOMAttr(zend_class_entry *class_entry_DO zend_string_release(property_name_name); zval property_specified_default_value; - ZVAL_BOOL(&property_specified_default_value, 1); + ZVAL_BOOL(&property_specified_default_value, true); zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, 1); zend_declare_typed_property(class_entry, property_specified_name, &property_specified_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_specified_name); diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 7dd1c6b0ce886..9627f1a22deb1 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1118,7 +1118,7 @@ static zend_class_entry *register_class_mysqli_driver(void) zend_string_release(property_driver_version_name); zval property_reconnect_default_value; - ZVAL_BOOL(&property_reconnect_default_value, 0); + ZVAL_BOOL(&property_reconnect_default_value, false); zend_string *property_reconnect_name = zend_string_init("reconnect", sizeof("reconnect") - 1, 1); zend_declare_typed_property(class_entry, property_reconnect_name, &property_reconnect_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_reconnect_name); diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index 3cf1c19ada2a5..d5ebdcfeac1de 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -442,7 +442,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property_location_name); zval property_trace_default_value; - ZVAL_BOOL(&property_trace_default_value, 0); + ZVAL_BOOL(&property_trace_default_value, false); zend_string *property_trace_name = zend_string_init("trace", sizeof("trace") - 1, 1); zend_declare_typed_property(class_entry, property_trace_name, &property_trace_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_trace_name); @@ -490,7 +490,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__password_name); zval property__use_digest_default_value; - ZVAL_BOOL(&property__use_digest_default_value, 0); + ZVAL_BOOL(&property__use_digest_default_value, false); zend_string *property__use_digest_name = zend_string_init("_use_digest", sizeof("_use_digest") - 1, 1); zend_declare_typed_property(class_entry, property__use_digest_name, &property__use_digest_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__use_digest_name); @@ -526,7 +526,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__proxy_password_name); zval property__exceptions_default_value; - ZVAL_BOOL(&property__exceptions_default_value, 1); + ZVAL_BOOL(&property__exceptions_default_value, true); zend_string *property__exceptions_name = zend_string_init("_exceptions", sizeof("_exceptions") - 1, 1); zend_declare_typed_property(class_entry, property__exceptions_name, &property__exceptions_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__exceptions_name); @@ -568,7 +568,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__user_agent_name); zval property__keep_alive_default_value; - ZVAL_BOOL(&property__keep_alive_default_value, 1); + ZVAL_BOOL(&property__keep_alive_default_value, true); zend_string *property__keep_alive_name = zend_string_init("_keep_alive", sizeof("_keep_alive") - 1, 1); zend_declare_typed_property(class_entry, property__keep_alive_name, &property__keep_alive_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__keep_alive_name); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 15a0f83b9af8a..9ad1738e80036 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -292,6 +292,8 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ # endif #endif + register_basic_functions_consts(module_number); + php_ce_incomplete_class = register_class___PHP_Incomplete_Class(); php_register_incomplete_class_handlers(); @@ -322,7 +324,6 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ REGISTER_LONG_CONSTANT("PHP_QUERY_RFC3986", PHP_QUERY_RFC3986, CONST_CS | CONST_PERSISTENT); #define REGISTER_MATH_CONSTANT(x) REGISTER_DOUBLE_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT) - REGISTER_MATH_CONSTANT(M_E); REGISTER_MATH_CONSTANT(M_LOG2E); REGISTER_MATH_CONSTANT(M_LOG10E); REGISTER_MATH_CONSTANT(M_LN2); diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 540d88722c15c..672a5e975f4be 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2,6 +2,12 @@ /** @generate-class-entries */ +/** + * @var float + * @cname M_E + */ +const M_E = 2.7182818284590452354; + final class __PHP_Incomplete_Class { } diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 8b573cbe2dff3..7a0987f446997 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b1c51fabe59bba6706500365f3eb7d9676d625f6 */ + * Stub hash: 29f2ff95da2c07a61f23729da63ada536d2980d1 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -3515,6 +3515,12 @@ static const zend_function_entry class_AssertionError_methods[] = { ZEND_FE_END }; +static void register_basic_functions_consts(int module_number) +{ + REGISTER_DOUBLE_CONSTANT("M_E", M_E, CONST_CS | CONST_PERSISTENT); + ZEND_ASSERT(M_E == 2.7182818284590451); +} + static zend_class_entry *register_class___PHP_Incomplete_Class(void) { zend_class_entry ce, *class_entry;