Skip to content

Commit ae81003

Browse files
Merge pull request #6 from php/master
Update fork
2 parents 2b7b7cc + 54435c9 commit ae81003

File tree

9 files changed

+210
-153
lines changed

9 files changed

+210
-153
lines changed

NEWS

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ PHP NEWS
66
. Fixed bug #80121 (Null pointer deref if CurlHandle directly instantiated).
77
(Nikita)
88

9-
- SPL.
9+
- SPL:
1010
. Fixed bug #65387 (Circular references in SPL iterators are not garbage
1111
collected). (Nikita)
1212

13+
- Standard:
14+
. Fixed bug #64060 (lstat_stat_variation7.phpt fails on certain file systems).
15+
(M. Voelker, cmb)
16+
1317
01 Oct 2020, PHP 8.0.0rc1
1418

1519
- CLI:

build/gen_stub.php

Lines changed: 133 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -337,30 +337,73 @@ public function getDefaultValueString(): string {
337337
}
338338
}
339339

340-
class FunctionName {
341-
/** @var string|null */
340+
interface FunctionOrMethodName {
341+
public function getDeclaration(): string;
342+
public function getArgInfoName(): string;
343+
public function __toString(): string;
344+
}
345+
346+
class FunctionName implements FunctionOrMethodName {
347+
/** @var Name */
348+
private $name;
349+
350+
public function __construct(Name $name) {
351+
$this->name = $name;
352+
}
353+
354+
public function getNamespace(): ?string {
355+
if ($this->name->isQualified()) {
356+
return $this->name->slice(0, -1)->toString();
357+
}
358+
return null;
359+
}
360+
361+
public function getShortName(): string {
362+
return $this->name->getLast();
363+
}
364+
365+
public function getNonNamespacedName(): string {
366+
if ($this->name->isQualified()) {
367+
throw new Exception("Namespaced name not supported here");
368+
}
369+
return $this->name->toString();
370+
}
371+
372+
public function getDeclaration(): string {
373+
return "ZEND_FUNCTION({$this->name->getLast()});\n";
374+
}
375+
376+
public function getArgInfoName(): string {
377+
$underscoreName = implode('_', $this->name->parts);
378+
return "arginfo_$underscoreName";
379+
}
380+
381+
public function __toString(): string {
382+
return $this->name->toString();
383+
}
384+
}
385+
386+
class MethodName implements FunctionOrMethodName {
387+
/** @var string */
342388
public $className;
343389
/** @var string */
344390
public $name;
345391

346-
public function __construct(?string $className, string $name)
347-
{
392+
public function __construct(string $className, string $name) {
348393
$this->className = $className;
349394
$this->name = $name;
350395
}
351396

352-
public function getDeclaration(): string
353-
{
354-
if ($this->className) {
355-
return "ZEND_METHOD($this->className, $this->name);\n";
356-
}
397+
public function getDeclaration(): string {
398+
return "ZEND_METHOD($this->className, $this->name);\n";
399+
}
357400

358-
return "ZEND_FUNCTION($this->name);\n";
401+
public function getArgInfoName(): string {
402+
return "arginfo_class_{$this->className}_{$this->name}";
359403
}
360404

361-
public function __toString()
362-
{
363-
return $this->className ? "$this->className::$this->name" : $this->name;
405+
public function __toString(): string {
406+
return "$this->className::$this->name";
364407
}
365408
}
366409

@@ -382,7 +425,7 @@ public function equals(ReturnInfo $other): bool {
382425
}
383426

384427
class FuncInfo {
385-
/** @var FunctionName */
428+
/** @var FunctionOrMethodName */
386429
public $name;
387430
/** @var int */
388431
public $flags;
@@ -402,10 +445,10 @@ class FuncInfo {
402445
public $cond;
403446

404447
public function __construct(
405-
FunctionName $name,
448+
FunctionOrMethodName $name,
406449
int $flags,
407450
?string $aliasType,
408-
?FunctionName $alias,
451+
?FunctionOrMethodName $alias,
409452
bool $isDeprecated,
410453
array $args,
411454
ReturnInfo $return,
@@ -440,10 +483,7 @@ public function equalsApartFromName(FuncInfo $other): bool {
440483
}
441484

442485
public function getArgInfoName(): string {
443-
if ($this->name->className) {
444-
return 'arginfo_class_' . $this->name->className . '_' . $this->name->name;
445-
}
446-
return 'arginfo_' . $this->name->name;
486+
return $this->name->getArgInfoName();
447487
}
448488

449489
public function getDeclarationKey(): string
@@ -465,18 +505,21 @@ public function getDeclaration(): ?string
465505
}
466506

467507
public function getFunctionEntry(): string {
468-
if ($this->name->className) {
508+
if ($this->name instanceof MethodName) {
469509
if ($this->alias) {
470-
if ($this->alias->className) {
510+
if ($this->alias instanceof MethodName) {
471511
return sprintf(
472512
"\tZEND_MALIAS(%s, %s, %s, %s, %s)\n",
473513
$this->alias->className, $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString()
474514
);
475-
} else {
515+
} else if ($this->alias instanceof FunctionName) {
476516
return sprintf(
477517
"\tZEND_ME_MAPPING(%s, %s, %s, %s)\n",
478-
$this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString()
518+
$this->name->name, $this->alias->getNonNamespacedName(),
519+
$this->getArgInfoName(), $this->getFlagsAsString()
479520
);
521+
} else {
522+
throw new Error("Cannot happen");
480523
}
481524
} else {
482525
if ($this->flags & Class_::MODIFIER_ABSTRACT) {
@@ -491,26 +534,37 @@ public function getFunctionEntry(): string {
491534
$this->name->className, $this->name->name, $this->getArgInfoName(), $this->getFlagsAsString()
492535
);
493536
}
494-
} else {
537+
} else if ($this->name instanceof FunctionName) {
538+
$namespace = $this->name->getNamespace();
539+
$shortName = $this->name->getShortName();
540+
495541
if ($this->alias && $this->isDeprecated) {
496542
return sprintf(
497543
"\tZEND_DEP_FALIAS(%s, %s, %s)\n",
498-
$this->name, $this->alias->name, $this->getArgInfoName()
544+
$shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName()
499545
);
500546
}
501547

502548
if ($this->alias) {
503549
return sprintf(
504550
"\tZEND_FALIAS(%s, %s, %s)\n",
505-
$this->name, $this->alias->name, $this->getArgInfoName()
551+
$shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName()
506552
);
507553
}
508554

509555
if ($this->isDeprecated) {
510-
return sprintf("\tZEND_DEP_FE(%s, %s)\n", $this->name, $this->getArgInfoName());
556+
return sprintf("\tZEND_DEP_FE(%s, %s)\n", $shortName, $this->getArgInfoName());
511557
}
512558

513-
return sprintf("\tZEND_FE(%s, %s)\n", $this->name, $this->getArgInfoName());
559+
if ($namespace) {
560+
return sprintf(
561+
"\tZEND_NS_FE(\"%s\", %s, %s)\n",
562+
$namespace, $shortName, $this->getArgInfoName());
563+
} else {
564+
return sprintf("\tZEND_FE(%s, %s)\n", $shortName, $this->getArgInfoName());
565+
}
566+
} else {
567+
throw new Error("Cannot happen");
514568
}
515569
}
516570

@@ -565,18 +619,13 @@ public function __construct(string $name, array $funcInfos) {
565619

566620
class FileInfo {
567621
/** @var FuncInfo[] */
568-
public $funcInfos;
622+
public $funcInfos = [];
569623
/** @var ClassInfo[] */
570-
public $classInfos;
624+
public $classInfos = [];
571625
/** @var bool */
572-
public $generateFunctionEntries;
573-
574-
public function __construct(
575-
array $funcInfos, array $classInfos, bool $generateFunctionEntries) {
576-
$this->funcInfos = $funcInfos;
577-
$this->classInfos = $classInfos;
578-
$this->generateFunctionEntries = $generateFunctionEntries;
579-
}
626+
public $generateFunctionEntries = false;
627+
/** @var string */
628+
public $declarationPrefix = "";
580629

581630
/**
582631
* @return iterable<FuncInfo>
@@ -646,7 +695,7 @@ function parseDocComment(DocComment $comment): array {
646695

647696
function parseFunctionLike(
648697
PrettyPrinterAbstract $prettyPrinter,
649-
FunctionName $name,
698+
FunctionOrMethodName $name,
650699
int $flags,
651700
Node\FunctionLike $func,
652701
?string $cond
@@ -672,9 +721,9 @@ function parseFunctionLike(
672721
$aliasType = $tag->name;
673722
$aliasParts = explode("::", $tag->getValue());
674723
if (count($aliasParts) === 1) {
675-
$alias = new FunctionName(null, $aliasParts[0]);
724+
$alias = new FunctionName(new Name($aliasParts[0]));
676725
} else {
677-
$alias = new FunctionName($aliasParts[0], $aliasParts[1]);
726+
$alias = new MethodName($aliasParts[0], $aliasParts[1]);
678727
}
679728
} else if ($tag->name === 'deprecated') {
680729
$isDeprecated = true;
@@ -814,46 +863,27 @@ function getFileDocComment(array $stmts): ?DocComment {
814863
return null;
815864
}
816865

817-
function parseStubFile(string $code): FileInfo {
818-
$lexer = new PhpParser\Lexer();
819-
$parser = new PhpParser\Parser\Php7($lexer);
820-
$nodeTraverser = new PhpParser\NodeTraverser;
821-
$nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
822-
$prettyPrinter = new class extends Standard {
823-
protected function pName_FullyQualified(Name\FullyQualified $node) {
824-
return implode('\\', $node->parts);
825-
}
826-
};
827-
828-
$stmts = $parser->parse($code);
829-
$nodeTraverser->traverse($stmts);
830-
831-
$generateFunctionEntries = false;
832-
$fileDocComment = getFileDocComment($stmts);
833-
if ($fileDocComment) {
834-
if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) {
835-
$generateFunctionEntries = true;
836-
}
837-
}
838-
839-
$funcInfos = [];
840-
$classInfos = [];
866+
function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstract $prettyPrinter) {
841867
$conds = [];
842868
foreach ($stmts as $stmt) {
843-
$cond = handlePreprocessorConditions($conds, $stmt);
844869
if ($stmt instanceof Stmt\Nop) {
845870
continue;
846871
}
847872

873+
if ($stmt instanceof Stmt\Namespace_) {
874+
handleStatements($fileInfo, $stmt->stmts, $prettyPrinter);
875+
continue;
876+
}
877+
878+
$cond = handlePreprocessorConditions($conds, $stmt);
848879
if ($stmt instanceof Stmt\Function_) {
849-
$funcInfos[] = parseFunctionLike(
880+
$fileInfo->funcInfos[] = parseFunctionLike(
850881
$prettyPrinter,
851-
new FunctionName(null, $stmt->name->toString()),
882+
new FunctionName($stmt->namespacedName),
852883
0,
853884
$stmt,
854885
$cond
855886
);
856-
857887
continue;
858888
}
859889

@@ -881,21 +911,49 @@ protected function pName_FullyQualified(Name\FullyQualified $node) {
881911

882912
$methodInfos[] = parseFunctionLike(
883913
$prettyPrinter,
884-
new FunctionName($className, $classStmt->name->toString()),
914+
new MethodName($className, $classStmt->name->toString()),
885915
$flags,
886916
$classStmt,
887917
$cond
888918
);
889919
}
890920

891-
$classInfos[] = new ClassInfo($className, $methodInfos);
921+
$fileInfo->classInfos[] = new ClassInfo($className, $methodInfos);
892922
continue;
893923
}
894924

895925
throw new Exception("Unexpected node {$stmt->getType()}");
896926
}
927+
}
897928

898-
return new FileInfo($funcInfos, $classInfos, $generateFunctionEntries);
929+
function parseStubFile(string $code): FileInfo {
930+
$lexer = new PhpParser\Lexer();
931+
$parser = new PhpParser\Parser\Php7($lexer);
932+
$nodeTraverser = new PhpParser\NodeTraverser;
933+
$nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
934+
$prettyPrinter = new class extends Standard {
935+
protected function pName_FullyQualified(Name\FullyQualified $node) {
936+
return implode('\\', $node->parts);
937+
}
938+
};
939+
940+
$stmts = $parser->parse($code);
941+
$nodeTraverser->traverse($stmts);
942+
943+
$fileInfo = new FileInfo;
944+
$fileDocComment = getFileDocComment($stmts);
945+
if ($fileDocComment) {
946+
$fileTags = parseDocComment($fileDocComment);
947+
foreach ($fileTags as $tag) {
948+
if ($tag->name === 'generate-function-entries') {
949+
$fileInfo->generateFunctionEntries = true;
950+
$fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : "";
951+
}
952+
}
953+
}
954+
955+
handleStatements($fileInfo, $stmts, $prettyPrinter);
956+
return $fileInfo;
899957
}
900958

901959
function funcInfoToCode(FuncInfo $funcInfo): string {
@@ -1058,15 +1116,14 @@ function (FuncInfo $funcInfo) use(&$generatedFuncInfos) {
10581116
$generatedFunctionDeclarations = [];
10591117
$code .= generateCodeWithConditions(
10601118
$fileInfo->getAllFuncInfos(), "",
1061-
function (FuncInfo $funcInfo) use(&$generatedFunctionDeclarations) {
1119+
function (FuncInfo $funcInfo) use($fileInfo, &$generatedFunctionDeclarations) {
10621120
$key = $funcInfo->getDeclarationKey();
10631121
if (isset($generatedFunctionDeclarations[$key])) {
10641122
return null;
10651123
}
10661124

10671125
$generatedFunctionDeclarations[$key] = true;
1068-
1069-
return $funcInfo->getDeclaration();
1126+
return $fileInfo->declarationPrefix . $funcInfo->getDeclaration();
10701127
}
10711128
);
10721129

ext/ffi/ffi.stub.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
/** @generate-function-entries */
44

5+
namespace {
6+
57
final class FFI
68
{
79
public static function cdef(string $code = "", ?string $lib = null): FFI {}
@@ -62,6 +64,12 @@ public static function string(FFI\CData $ptr, ?int $size = null): ?string {}
6264
public static function isNull(FFI\CData $ptr): bool {}
6365
}
6466

67+
}
68+
69+
namespace FFI {
70+
6571
final class CType {
6672
public function getName() : string {}
6773
}
74+
75+
}

0 commit comments

Comments
 (0)