Skip to content

Commit

Permalink
Fix using numbers with different bit widths (#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajalt authored Sep 1, 2024
1 parent 592d1f3 commit 06d0e35
Show file tree
Hide file tree
Showing 18 changed files with 289 additions and 49 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ jobs:
os: [macos-latest, windows-latest, ubuntu-latest]
include:
- os: ubuntu-latest
EXTRA_GRADLE_ARGS: :test:proguard:r8jar apiCheck
EXTRA_GRADLE_ARGS: apiCheck :test:proguard:r8jar
- os: macos-latest
EXTRA_GRADLE_ARGS: :mordant:compilePosixMainKotlinMetadata
EXTRA_GRADLE_ARGS: :mordant:compileNativeMainKotlinMetadata :mordant:compilePosixMainKotlinMetadata :mordant:compileAppleMainKotlinMetadata
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
Expand All @@ -39,11 +39,11 @@ jobs:
- name: Run tests
run: >-
./gradlew
${{matrix.EXTRA_GRADLE_ARGS}}
:mordant:check
:mordant-coroutines:check
:mordant-markdown:check
:test:graalvm:nativeTest
${{matrix.EXTRA_GRADLE_ARGS}}
--stacktrace
- name: Run R8 Jar
if: ${{ matrix.os == 'ubuntu-latest' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ kotlin {
tvosX64()
tvosArm64()
tvosSimulatorArm64()
watchosArm32()
watchosArm64()
watchosX64()
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.github.ajalt.mordant.internal

internal actual fun hasFileSystem(): Boolean = false
internal actual fun testsHaveFileSystem(): Boolean = false
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ internal expect fun exitProcessMpp(status: Int)

internal expect fun readFileIfExists(filename: String): String?

internal expect fun hasFileSystem(): Boolean
/** Whether tests running on this platform can access the filesystem */
internal expect fun testsHaveFileSystem(): Boolean

internal expect fun getStandardTerminalInterface(): TerminalInterface

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.github.ajalt.mordant.platform

import com.github.ajalt.mordant.internal.hasFileSystem
import com.github.ajalt.mordant.internal.testsHaveFileSystem
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldNotBeEmpty
Expand All @@ -13,7 +13,7 @@ class MultiplatformSystemTest {
// The kotlin.test plugin doesn't provide a way to set environment variables that works on
// all targets, so just pick a common one that should exist everywhere.
val actual = MultiplatformSystem.readEnvironmentVariable("PATH")
if (!hasFileSystem()) return
if (!testsHaveFileSystem()) return
actual.shouldNotBeNull().shouldNotBeEmpty()
}

Expand All @@ -26,7 +26,7 @@ class MultiplatformSystemTest {
// js targets have a cwd of $projectDir/build/js/packages/mordant-mordant-test
"../../../../mordant/src/commonTest/resources/multiplatform_system_test.txt"
)
if (!hasFileSystem()) return
if (!testsHaveFileSystem()) return
actual?.trim() shouldBe "pass"
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.github.ajalt.mordant.internal

import com.github.ajalt.mordant.terminal.TerminalInterface
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeApple
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeCopyPasted

internal actual fun getStandardTerminalInterface(): TerminalInterface {
return TerminalInterfaceNativeApple()
return TerminalInterfaceNativeCopyPasted()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import com.github.ajalt.mordant.rendering.Size
import kotlinx.cinterop.*
import platform.posix.*

// The source code for this file is identical between linux and apple targets, but they have
// different bit widths for some of the termios fields, so the compileMetadata task would fail if we
// don't use separate files.
// XXX: The source code for this file is identical between linux and the various apple targets, but
// they have different bit widths for some fields, so the compileMetadata task fails if we don't use
// separate files. Hopefully some day there will be solution that doesn't require copy-pasting.

internal class TerminalInterfaceNativeApple : TerminalInterfaceNativePosix() {
internal class TerminalInterfaceNativeCopyPasted : TerminalInterfaceNativePosix() {
override val termiosConstants: TermiosConstants = TermiosConstants(
VTIME = VTIME,
VMIN = VMIN,
Expand All @@ -32,7 +32,7 @@ internal class TerminalInterfaceNativeApple : TerminalInterfaceNativePosix() {

override fun getTerminalSize(): Size? = memScoped {
val size = alloc<winsize>()
if (ioctl(STDIN_FILENO, TIOCGWINSZ.toULong(), size) < 0) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ.convert(), size) < 0) {
null
} else {
Size(width = size.ws_col.toInt(), height = size.ws_row.toInt())
Expand All @@ -41,31 +41,31 @@ internal class TerminalInterfaceNativeApple : TerminalInterfaceNativePosix() {

override fun getStdinTermios(): Termios = memScoped {
val termios = alloc<termios>()
if (tcgetattr(STDIN_FILENO, termios.ptr) != 0) {
if (tcgetattr(platform.posix.STDIN_FILENO, termios.ptr) != 0) {
throw RuntimeException("Error reading terminal attributes")
}
return Termios(
iflag = termios.c_iflag.convert<UInt>(),
oflag = termios.c_oflag.convert<UInt>(),
cflag = termios.c_cflag.convert<UInt>(),
lflag = termios.c_lflag.convert<UInt>(),
cc = ByteArray(NCCS) { termios.c_cc[it].convert<Byte>() },
iflag = termios.c_iflag.convert(),
oflag = termios.c_oflag.convert(),
cflag = termios.c_cflag.convert(),
lflag = termios.c_lflag.convert(),
cc = ByteArray(NCCS) { termios.c_cc[it].convert() },
)
}

override fun setStdinTermios(termios: Termios) = memScoped {
val nativeTermios = alloc<termios>()
// different platforms have different fields in termios, so we need to read the current
// struct before we set the fields we care about.
if (tcgetattr(STDIN_FILENO, nativeTermios.ptr) != 0) {
if (tcgetattr(platform.posix.STDIN_FILENO, nativeTermios.ptr) != 0) {
throw RuntimeException("Error reading terminal attributes")
}
nativeTermios.c_iflag = termios.iflag.convert<tcflag_t>()
nativeTermios.c_oflag = termios.oflag.convert<tcflag_t>()
nativeTermios.c_cflag = termios.cflag.convert<tcflag_t>()
nativeTermios.c_lflag = termios.lflag.convert<tcflag_t>()
nativeTermios.c_iflag = termios.iflag.convert()
nativeTermios.c_oflag = termios.oflag.convert()
nativeTermios.c_cflag = termios.cflag.convert()
nativeTermios.c_lflag = termios.lflag.convert()
repeat(NCCS) { nativeTermios.c_cc[it] = termios.cc[it].convert<UByte>() }
if (tcsetattr(STDIN_FILENO, TCSADRAIN, nativeTermios.ptr) != 0) {
if (tcsetattr(platform.posix.STDIN_FILENO, TCSADRAIN, nativeTermios.ptr) != 0) {
throw RuntimeException("Error setting terminal attributes")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ internal actual fun sendInterceptedPrintRequest(
)
}

internal actual fun hasFileSystem(): Boolean = impls !is TerminalInterfaceBrowser
internal actual fun testsHaveFileSystem(): Boolean = impls !is TerminalInterfaceBrowser
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ internal actual fun getStandardTerminalInterface(): TerminalInterface {
}

internal actual val CR_IMPLIES_LF: Boolean = false
internal actual fun hasFileSystem(): Boolean = true
internal actual fun testsHaveFileSystem(): Boolean = true

internal actual fun exitProcessMpp(status: Int) {
exitProcess(status)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.github.ajalt.mordant.internal

import com.github.ajalt.mordant.terminal.TerminalInterface
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeLinux
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeCopyPasted

internal actual fun hasFileSystem(): Boolean = true
internal actual fun getStandardTerminalInterface(): TerminalInterface = TerminalInterfaceNativeLinux
internal actual fun testsHaveFileSystem(): Boolean = true
internal actual fun getStandardTerminalInterface(): TerminalInterface {
return TerminalInterfaceNativeCopyPasted()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import com.github.ajalt.mordant.rendering.Size
import kotlinx.cinterop.*
import platform.posix.*

// The source code for this file is identical between linux and apple targets, but they have
// different bit widths for some of the termios fields, so the compileMetadata task would fail if we
// don't use separate files.
// XXX: The source code for this file is identical between linux and the various apple targets, but
// they have different bit widths for some fields, so the compileMetadata task fails if we don't use
// separate files. Hopefully some day there will be solution that doesn't require copy-pasting.

internal object TerminalInterfaceNativeLinux : TerminalInterfaceNativePosix() {
internal class TerminalInterfaceNativeCopyPasted : TerminalInterfaceNativePosix() {
override val termiosConstants: TermiosConstants = TermiosConstants(
VTIME = VTIME,
VMIN = VMIN,
Expand All @@ -32,7 +32,7 @@ internal object TerminalInterfaceNativeLinux : TerminalInterfaceNativePosix() {

override fun getTerminalSize(): Size? = memScoped {
val size = alloc<winsize>()
if (ioctl(STDIN_FILENO, TIOCGWINSZ.toULong(), size) < 0) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ.convert(), size) < 0) {
null
} else {
Size(width = size.ws_col.toInt(), height = size.ws_row.toInt())
Expand All @@ -45,11 +45,11 @@ internal object TerminalInterfaceNativeLinux : TerminalInterfaceNativePosix() {
throw RuntimeException("Error reading terminal attributes")
}
return Termios(
iflag = termios.c_iflag.convert<UInt>(),
oflag = termios.c_oflag.convert<UInt>(),
cflag = termios.c_cflag.convert<UInt>(),
lflag = termios.c_lflag.convert<UInt>(),
cc = ByteArray(NCCS) { termios.c_cc[it].convert<Byte>() },
iflag = termios.c_iflag.convert(),
oflag = termios.c_oflag.convert(),
cflag = termios.c_cflag.convert(),
lflag = termios.c_lflag.convert(),
cc = ByteArray(NCCS) { termios.c_cc[it].convert() },
)
}

Expand All @@ -60,10 +60,10 @@ internal object TerminalInterfaceNativeLinux : TerminalInterfaceNativePosix() {
if (tcgetattr(platform.posix.STDIN_FILENO, nativeTermios.ptr) != 0) {
throw RuntimeException("Error reading terminal attributes")
}
nativeTermios.c_iflag = termios.iflag.convert<tcflag_t>()
nativeTermios.c_oflag = termios.oflag.convert<tcflag_t>()
nativeTermios.c_cflag = termios.cflag.convert<tcflag_t>()
nativeTermios.c_lflag = termios.lflag.convert<tcflag_t>()
nativeTermios.c_iflag = termios.iflag.convert()
nativeTermios.c_oflag = termios.oflag.convert()
nativeTermios.c_cflag = termios.cflag.convert()
nativeTermios.c_lflag = termios.lflag.convert()
repeat(NCCS) { nativeTermios.c_cc[it] = termios.cc[it].convert<UByte>() }
if (tcsetattr(platform.posix.STDIN_FILENO, TCSADRAIN, nativeTermios.ptr) != 0) {
throw RuntimeException("Error setting terminal attributes")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
package com.github.ajalt.mordant.internal

internal actual fun hasFileSystem(): Boolean = true
import com.github.ajalt.mordant.terminal.TerminalInterface
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeCopyPasted

internal actual fun testsHaveFileSystem(): Boolean = true
internal actual fun getStandardTerminalInterface(): TerminalInterface {
return TerminalInterfaceNativeCopyPasted()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.github.ajalt.mordant.terminal.terminalinterface

import com.github.ajalt.mordant.rendering.Size
import kotlinx.cinterop.*
import platform.posix.*

// XXX: The source code for this file is identical between linux and the various apple targets, but
// they have different bit widths for some fields, so the compileMetadata task fails if we don't use
// separate files. Hopefully some day there will be solution that doesn't require copy-pasting.

internal class TerminalInterfaceNativeCopyPasted : TerminalInterfaceNativePosix() {
override val termiosConstants: TermiosConstants = TermiosConstants(
VTIME = VTIME,
VMIN = VMIN,
INPCK = INPCK.convert(),
ISTRIP = ISTRIP.convert(),
INLCR = INLCR.convert(),
IGNCR = IGNCR.convert(),
ICRNL = ICRNL.convert(),
IXON = IXON.convert(),
OPOST = OPOST.convert(),
CS8 = CS8.convert(),
ISIG = ISIG.convert(),
ICANON = ICANON.convert(),
ECHO = ECHO.convert(),
IEXTEN = IEXTEN.convert(),
)

override fun readIntoBuffer(c: ByteVar): Long {
return read(platform.posix.STDIN_FILENO, c.ptr, 1u).convert()
}

override fun getTerminalSize(): Size? = memScoped {
val size = alloc<winsize>()
if (ioctl(STDIN_FILENO, TIOCGWINSZ.convert(), size) < 0) {
null
} else {
Size(width = size.ws_col.toInt(), height = size.ws_row.toInt())
}
}

override fun getStdinTermios(): Termios = memScoped {
val termios = alloc<termios>()
if (tcgetattr(platform.posix.STDIN_FILENO, termios.ptr) != 0) {
throw RuntimeException("Error reading terminal attributes")
}
return Termios(
iflag = termios.c_iflag.convert(),
oflag = termios.c_oflag.convert(),
cflag = termios.c_cflag.convert(),
lflag = termios.c_lflag.convert(),
cc = ByteArray(NCCS) { termios.c_cc[it].convert() },
)
}

override fun setStdinTermios(termios: Termios) = memScoped {
val nativeTermios = alloc<termios>()
// different platforms have different fields in termios, so we need to read the current
// struct before we set the fields we care about.
if (tcgetattr(platform.posix.STDIN_FILENO, nativeTermios.ptr) != 0) {
throw RuntimeException("Error reading terminal attributes")
}
nativeTermios.c_iflag = termios.iflag.convert()
nativeTermios.c_oflag = termios.oflag.convert()
nativeTermios.c_cflag = termios.cflag.convert()
nativeTermios.c_lflag = termios.lflag.convert()
repeat(NCCS) { nativeTermios.c_cc[it] = termios.cc[it].convert<UByte>() }
if (tcsetattr(platform.posix.STDIN_FILENO, TCSADRAIN, nativeTermios.ptr) != 0) {
throw RuntimeException("Error setting terminal attributes")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import com.github.ajalt.mordant.terminal.TerminalInterface
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeWindows

internal actual fun ttySetEcho(echo: Boolean) = TerminalInterfaceNativeWindows.ttySetEcho(echo)
internal actual fun hasFileSystem(): Boolean = true
internal actual fun testsHaveFileSystem(): Boolean = true
internal actual fun getStandardTerminalInterface(): TerminalInterface =
TerminalInterfaceNativeWindows
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.github.ajalt.mordant.internal

import com.github.ajalt.mordant.terminal.TerminalInterface
import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceNativeCopyPasted

internal actual fun getStandardTerminalInterface(): TerminalInterface {
return TerminalInterfaceNativeCopyPasted()
}
Loading

0 comments on commit 06d0e35

Please sign in to comment.