Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `array_product` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `array_push` | yes | yes | yes | standard | doc: VM only; JIT PHPT; AOT PHPT |
| `array_rand` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `array_reduce` | yes | yes | yes | standard | callbacks: string user functions + VM closures; php-src-strict invalid callback TypeError (#6679); JIT PHPT |
| `array_reduce` | yes | yes | yes | standard | JIT PHPT |
| `array_replace` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `array_replace_recursive` | yes | yes | yes | standard | AOT PHPT |
| `array_reverse` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -80,7 +80,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `bin2hex` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `bindec` | yes | yes | yes | standard | |
| `boolval` | yes | yes | yes | standard | AOT PHPT |
| `ceil` | yes | yes | yes | standard | |
| `ceil` | yes | yes | yes | standard | JIT PHPT |
| `chdir` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `chgrp` | yes | yes | yes | standard | AOT PHPT |
| `chmod` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -141,7 +141,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `disktotalspace` | yes | yes | yes | standard | |
| `dl` | yes | yes | yes | standard | |
| `doubleval` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `end` | yes | yes | yes | standard | |
| `end` | yes | yes | yes | standard | JIT PHPT |
| `enum_exists` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `error_clear_last` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `error_get_last` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -177,12 +177,12 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `filesize` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `filetype` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `filter_id` | yes | yes | yes | filter | |
| `filter_input` | yes | yes | yes | standard | AOT PHPT |
| `filter_input` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `filter_list` | yes | yes | yes | filter | |
| `filter_var` | yes | yes | yes | filter | AOT PHPT |
| `floatval` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `flock` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `floor` | yes | yes | yes | standard | |
| `floor` | yes | yes | yes | standard | JIT PHPT |
| `flush` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `fmod` | yes | yes | yes | standard | |
| `fnmatch` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -437,7 +437,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `rewind` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `rewinddir` | yes | yes | yes | standard | JIT PHPT |
| `rmdir` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `round` | yes | yes | yes | standard | AOT PHPT |
| `round` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `rsort` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `rtrim` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `scandir` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -467,7 +467,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `soundex` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `spl_autoload_register` | yes | yes | yes | standard | JIT PHPT |
| `sprintf` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `sqrt` | yes | yes | yes | standard | |
| `sqrt` | yes | yes | yes | standard | JIT PHPT |
| `sscanf` | yes | yes | yes | standard | AOT PHPT |
| `stat` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_contains` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand All @@ -479,7 +479,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `str_pad` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_repeat` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_replace` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_rot13` | yes | yes | yes | standard | AOT PHPT |
| `str_rot13` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_shuffle` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_split` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `str_starts_with` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand All @@ -491,7 +491,8 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `stream_context_create` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `stream_get_contents` | yes | yes | yes | standard | AOT PHPT |
| `stream_get_line` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `stream_is_local` | yes | yes | yes | standard | AOT PHPT |
| `stream_is_local` | yes | yes | yes | standard | |
| `stream_isatty` | yes | yes | yes | standard | |
| `stream_set_chunk_size` | yes | yes | yes | standard | AOT PHPT |
| `stream_set_read_buffer` | yes | yes | yes | standard | AOT PHPT |
| `stream_set_timeout` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -556,7 +557,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `usleep` | yes | yes | yes | standard | JIT PHPT |
| `usort` | yes | yes | yes | standard | callbacks: strcmp JIT; strcasecmp VM; VM closure comparator (#3086, #1210); JIT PHPT |
| `utf8_decode` | yes | yes | yes | standard | AOT PHPT |
| `utf8_encode` | yes | yes | yes | standard | AOT PHPT |
| `utf8_encode` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `var_dump` | yes | yes | yes | standard | |
| `var_export` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `version_compare` | yes | yes | yes | standard | AOT PHPT |
Expand Down
25 changes: 25 additions & 0 deletions ext/standard/JitStreamIsatty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\standard;

use PHPCompiler\JIT\Context;
use PHPLLVM\Builder;
use PHPLLVM\Value;

/** LLVM lowering for stream_isatty() via __compiler_stream_isatty (issue #6035). */
final class JitStreamIsatty
{
/** @return Value */
public static function invoke(Context $context, Value $handleLong): Value
{
$ret = $context->builder->call(
$context->lookupFunction('__compiler_stream_isatty'),
$handleLong
);
$i32 = $context->getTypeFromString('int32');

return $context->builder->icmp(Builder::INT_EQ, $ret, $i32->constInt(1, false));
}
}
1 change: 1 addition & 0 deletions ext/standard/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ public function getFunctions(): array
new stream_supports(),
new stream_supports_lock(),
new stream_is_local(),
new stream_isatty(),
new fopen(),
new fread(),
new stream_get_contents(),
Expand Down
15 changes: 15 additions & 0 deletions ext/standard/VmFs.php
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,21 @@ public static function streamSetReadBuffer(int $handle, int $buffer) {
return (int) $previous;
}

/**
* stream_isatty() — php-src ext/standard/streamsfuncs.c (issue #6035).
*
* Returns true when the stream is connected to a terminal (php_stream_isatty).
*/
public static function streamIsatty(int $handle): bool
{
$fp = self::lookup($handle);
if (null === $fp) {
return false;
}

return \stream_isatty($fp);
}

/**
* stream_is_local() — php-src ext/standard/streamsfuncs.c (issue #6173).
*
Expand Down
51 changes: 51 additions & 0 deletions ext/standard/stream_isatty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\JitLongArg;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPLLVM\Value;

/** stream_isatty() — VM via VmFs; JIT/AOT via __compiler_stream_isatty (issue #6035). */
final class stream_isatty extends Internal
{
public function __construct()
{
parent::__construct('stream_isatty');
}

public function execute(Frame $frame): void
{
if (1 !== \count($frame->calledArgs)) {
throw new \LogicException('stream_isatty() requires exactly one argument in this compiler build');
}
$handle = VmStreamArg::requireStreamHandle(
$frame->calledArgs[0]->resolveIndirect(),
'stream_isatty'
);
if (null === $frame->returnVar) {
return;
}
$frame->returnVar->bool(VmFs::streamIsatty($handle));
}

public function call(Context $context, JITVariable ...$args): Value
{
if (1 !== \count($args)) {
throw new \LogicException('stream_isatty() requires exactly one argument in this compiler build');
}

return JitStreamIsatty::invoke(
$context,
$context->builder->truncOrBitCast(
JitLongArg::lower($context, $args[0], 'stream_isatty() stream'),
$context->getTypeFromString('int64')
)
);
}
}
22 changes: 22 additions & 0 deletions lib/AOT/runtime/phpc_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,28 @@ int __compiler_stream_is_local(int64_t handle)
return phpc_stream_is_url_path(path) ? 0 : 1;
}

int __compiler_stream_isatty(int64_t handle)
{
FILE *fp = __phpc_resolve_stream(handle);

if (NULL == fp) {
return 0;
}
#if defined(_WIN32)
return _isatty(_fileno(fp)) ? 1 : 0;
#else
{
int fd = fileno(fp);

if (fd < 0) {
return 0;
}

return isatty(fd) ? 1 : 0;
}
#endif
}

int __compiler_stream_supports(int64_t handle, int64_t feature)
{
FILE *fp;
Expand Down
3 changes: 3 additions & 0 deletions lib/JIT/Builtin/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ public function register(): void {
$fntypeStreamIsLocal = $this->context->context->functionType($i32, false, $i64);
$fnStreamIsLocal = $this->context->module->addFunction('__compiler_stream_is_local', $fntypeStreamIsLocal);
$this->context->registerFunction('__compiler_stream_is_local', $fnStreamIsLocal);
$fntypeStreamIsatty = $this->context->context->functionType($i32, false, $i64);
$fnStreamIsatty = $this->context->module->addFunction('__compiler_stream_isatty', $fntypeStreamIsatty);
$this->context->registerFunction('__compiler_stream_isatty', $fnStreamIsatty);
$fntypeFtruncate = $this->context->context->functionType($i32, false, $i64, $i64);
$fnFtruncate = $this->context->module->addFunction('__compiler_ftruncate', $fntypeFtruncate);
$this->context->registerFunction('__compiler_ftruncate', $fnFtruncate);
Expand Down
17 changes: 17 additions & 0 deletions test/compliance/cases/stdlib/stream_isatty.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
stream_isatty() on php://memory and plainfile (issue #6035, php-src streamsfuncs.c)
--FILE--
<?php
echo function_exists('stream_isatty') ? '1' : '0', "\n";
$memory = fopen('php://memory', 'r+');
echo stream_isatty($memory) ? '1' : '0', "\n";
fclose($memory);
$path = sys_get_temp_dir() . '/phpc_stream_isatty_' . (string) getmypid() . '.txt';
$fp = fopen($path, 'w');
echo stream_isatty($fp) ? '1' : '0', "\n";
fclose($fp);
@unlink($path);
--EXPECT--
1
0
0
14 changes: 14 additions & 0 deletions test/compliance/cases/stdlib/stream_isatty_enum_typeerror.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
stream_isatty() enum case stream operand TypeError (#6035, php-src-strict)
--FILE--
<?php
enum E: int { case A = 1; }

try {
stream_isatty(E::A);
echo "uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
--EXPECT--
stream_isatty(): Argument #1 ($stream) must be of type resource, E given
12 changes: 12 additions & 0 deletions test/compliance/cases/stdlib/stream_isatty_typeerror.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
stream_isatty() non-resource operand TypeError (#6035, php-src streamsfuncs.c)
--FILE--
<?php
try {
stream_isatty([]);
echo "uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
--EXPECT--
stream_isatty(): Argument #1 ($stream) must be of type resource, array given
5 changes: 5 additions & 0 deletions test/repro/stream_isatty_6035.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php
echo function_exists('stream_isatty') ? '1' : '0', "\n";
$memory = fopen('php://memory', 'r+');
echo stream_isatty($memory) ? '1' : '0', "\n";
fclose($memory);