diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 83000d5b099b7..b107cb29dbb07 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -966,6 +966,7 @@ function fprintf($stream, string $format, mixed ...$values): int {} /** @param resource $stream */ function vfprintf($stream, string $format, array $values): int {} +function println(string $data = ''): int {} /* fsock.c */ /** diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index f44a32226736b..cb22f28e8c4a1 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: 97edf8c87780c892984099e52ad1c6c745b919f8 */ + * Stub hash: 0909e41211d2c51032e107c7829979dff46a6944 */ 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) @@ -1489,6 +1489,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_vfprintf, 0, 3, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, values, IS_ARRAY, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_println, 0, 0, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, data, IS_STRING, 0, "\'\'") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_fsockopen, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "-1") @@ -2621,6 +2625,7 @@ ZEND_FUNCTION(vprintf); ZEND_FUNCTION(vsprintf); ZEND_FUNCTION(fprintf); ZEND_FUNCTION(vfprintf); +ZEND_FUNCTION(println); ZEND_FUNCTION(fsockopen); ZEND_FUNCTION(pfsockopen); ZEND_FUNCTION(http_build_query); @@ -3261,6 +3266,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(vsprintf, arginfo_vsprintf) ZEND_FE(fprintf, arginfo_fprintf) ZEND_FE(vfprintf, arginfo_vfprintf) + ZEND_FE(println, arginfo_println) ZEND_FE(fsockopen, arginfo_fsockopen) ZEND_FE(pfsockopen, arginfo_pfsockopen) ZEND_FE(http_build_query, arginfo_http_build_query) diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index ab205feb6fa32..5dec684b9da23 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -919,3 +919,26 @@ PHP_FUNCTION(vfprintf) zend_string_efree(result); } /* }}} */ + +/* {{{ Output a string followed by a unix newline */ +PHP_FUNCTION(println) +{ + char* input = NULL; + size_t input_len = 0; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STRING(input, input_len) + ZEND_PARSE_PARAMETERS_END(); + + if (input_len > 0) { + size_t rlen = PHPWRITE(input, input_len); + if (UNEXPECTED(rlen != input_len)) { + RETURN_LONG(rlen); + } + rlen += PHPWRITE("\n", 1); + RETURN_LONG(rlen); + } + RETURN_LONG(PHPWRITE("\n", 1)); +} +/* }}} */ diff --git a/ext/standard/tests/general_functions/formatted_print1.phpt b/ext/standard/tests/general_functions/formatted_print1.phpt new file mode 100644 index 0000000000000..d16095ae807c5 --- /dev/null +++ b/ext/standard/tests/general_functions/formatted_print1.phpt @@ -0,0 +1,42 @@ +--TEST-- +println() function with strict_types=0 +--FILE-- +getMessage()}\n"; +} +try { + println('test', 'too many'); +} catch (ArgumentCountError $e) { + echo "Caught ArgumentCountError {$e->getMessage()}\n"; +} + +?> +--EXPECT-- +println always adds a newline +the above string was 30 bytes including the newline, the below appends \n to \n + + +strict_types=0 allows string coercion the exact same way as any other function +1 +1 + +println byte lengths +[1,30,2,79,2,2,1] +Caught TypeError println(): Argument #1 ($data) must be of type string, array given +Caught ArgumentCountError println() expects at most 1 argument, 2 given \ No newline at end of file diff --git a/ext/standard/tests/general_functions/formatted_print2.phpt b/ext/standard/tests/general_functions/formatted_print2.phpt new file mode 100644 index 0000000000000..f7e2ee069c578 --- /dev/null +++ b/ext/standard/tests/general_functions/formatted_print2.phpt @@ -0,0 +1,28 @@ +--TEST-- +println() function with strict_types=1 throws for non-string +--FILE-- +getMessage()); +} +println(); // valid +try { + println(null); +} catch (TypeError $e) { + println("Caught: " . $e->getMessage()); +} + +?> +--EXPECT-- +println always adds a newline +wrote 30 bytes +Caught: println(): Argument #1 ($data) must be of type string, int given + +Caught: println(): Argument #1 ($data) must be of type string, null given