diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index c14a2aaed28..a48d889c7e1 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -478,13 +478,13 @@ task hello0(type: RunKonanTest) { } task hello1(type: RunStandaloneKonanTest) { - goldValue = "Hello World\n" + goldValue = "Hello World" testData = "Hello World\n" source = "runtime/basic/hello1.kt" } task hello2(type: RunStandaloneKonanTest) { - goldValue = "you entered 'Hello World\n'" + goldValue = "you entered 'Hello World'" testData = "Hello World\n" source = "runtime/basic/hello2.kt" } @@ -518,6 +518,18 @@ task entry2(type: LinkKonanTest) { flags = ["-entry", "foo"] } +task readline0(type: RunStandaloneKonanTest) { + goldValue = "41" + testData = "41\r\n" + source = "runtime/basic/readline0.kt" +} + +task readline1(type: RunStandaloneKonanTest) { + goldValue = "" + testData = "\n" + source = "runtime/basic/readline1.kt" +} + task tostring0(type: RunKonanTest) { goldValue = "127\n-1\n239\nA\nЁ\nト\n1122334455\n112233445566778899\n3.14159265358\n1.0E27\n1.0E-300\ntrue\nfalse\n" source = "runtime/basic/tostring0.kt" diff --git a/backend.native/tests/runtime/basic/readline0.kt b/backend.native/tests/runtime/basic/readline0.kt new file mode 100644 index 00000000000..23f10f9de64 --- /dev/null +++ b/backend.native/tests/runtime/basic/readline0.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + print(readLine()!!.toInt()) +} \ No newline at end of file diff --git a/backend.native/tests/runtime/basic/readline1.kt b/backend.native/tests/runtime/basic/readline1.kt new file mode 100644 index 00000000000..f77c0aaaa00 --- /dev/null +++ b/backend.native/tests/runtime/basic/readline1.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + print(readLine()!!) +} \ No newline at end of file diff --git a/runtime/src/main/cpp/Console.cpp b/runtime/src/main/cpp/Console.cpp index a80fa0b9717..7812e262b61 100644 --- a/runtime/src/main/cpp/Console.cpp +++ b/runtime/src/main/cpp/Console.cpp @@ -49,7 +49,7 @@ void Kotlin_io_Console_println0() { OBJ_GETTER0(Kotlin_io_Console_readLine) { char data[4096]; - if (konan::consoleReadUtf8(data, sizeof(data)) == 0) { + if (konan::consoleReadUtf8(data, sizeof(data)) < 0) { RETURN_OBJ(nullptr); } RETURN_RESULT_OF(CreateStringFromCString, data); diff --git a/runtime/src/main/cpp/Porting.cpp b/runtime/src/main/cpp/Porting.cpp index be703a02f30..17f166bdb81 100644 --- a/runtime/src/main/cpp/Porting.cpp +++ b/runtime/src/main/cpp/Porting.cpp @@ -74,13 +74,29 @@ void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) { #endif } -uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) { +int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) { #ifdef KONAN_ZEPHYR return 0; -#else +#else char* result = ::fgets(reinterpret_cast(utf8), maxSizeBytes - 1, stdin); - if (result == nullptr) return 0; - return ::strlen(result); + if (result == nullptr) return -1; + int32_t length = ::strlen(result); + // fgets reads until EOF or newline so we need to remove linefeeds. + char* current = result + length - 1; + bool isTrimming = true; + while (current >= result && isTrimming) { + switch (*current) { + case '\n': + case '\r': + *current = 0; + length--; + break; + default: + isTrimming = false; + } + current--; + } + return length; #endif } diff --git a/runtime/src/main/cpp/Porting.h b/runtime/src/main/cpp/Porting.h index 781c81d9ea0..3ed6b55dd52 100644 --- a/runtime/src/main/cpp/Porting.h +++ b/runtime/src/main/cpp/Porting.h @@ -29,7 +29,8 @@ void consoleInit(); void consolePrintf(const char* format, ...); void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes); void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes); -uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes); +// Negative return value denotes that read wasn't successful. +int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes); // Process control. void abort(void);