aboutsummaryrefslogtreecommitdiff
path: root/libgloss/m68k/atari/atari-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/m68k/atari/atari-write.c')
-rw-r--r--libgloss/m68k/atari/atari-write.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/libgloss/m68k/atari/atari-write.c b/libgloss/m68k/atari/atari-write.c
new file mode 100644
index 0000000..9d6e59e
--- /dev/null
+++ b/libgloss/m68k/atari/atari-write.c
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2025 Mikael Hildenborg
+ SPDX-License-Identifier: BSD-2-Clause
+*/
+
+#include <unistd.h>
+#include <_ansi.h>
+#include "atari-gem_errno.h"
+#include "atari-traps.h"
+
+const char* lineEnding = "\r\n";
+
+int writeUntilDoneOrError(int fd, size_t len, const char* buf)
+{
+ size_t written = 0;
+ if (len == 0)
+ {
+ return 0;
+ }
+ do
+ {
+ int n = trap1_40((unsigned short)fd, len, buf);
+ if (n < 0)
+ {
+ gem_error_to_errno(n);
+ return -1;
+ }
+ written += n;
+ buf += n;
+ } while (written < len);
+ return 0;
+}
+
+
+_READ_WRITE_RETURN_TYPE write(int fd, const void *buf, size_t nbytes)
+{
+ int numWritten = GEM_EIHNDL;
+ if (fd >= 0)
+ {
+ if (fd == 2)
+ {
+ fd = GSH_CONOUT; // Use console out for stderr.
+ }
+ if (fd == GSH_CONOUT)
+ {
+ // When we write to stdout on Atari, we must add a \r after \n to
+ // get the correct C output behaviour.
+ const char* stream = (const char*)buf;
+ size_t lastWrite = 0;
+ for (size_t i = 0; i < nbytes; ++i)
+ {
+ if (stream[i] == '\n')
+ {
+ int len = i - lastWrite; // length up to but not including \n
+ if (writeUntilDoneOrError(fd, len, stream + lastWrite) < 0)
+ {
+ return -1;
+ }
+ if (writeUntilDoneOrError(fd, 2, lineEnding) < 0)
+ {
+ return -1;
+ }
+ lastWrite = i + 1; // Include the \n
+ }
+ }
+ if (lastWrite < nbytes)
+ {
+ int len = nbytes - lastWrite;
+ if (writeUntilDoneOrError(fd, len, stream + lastWrite) < 0)
+ {
+ return -1;
+ }
+ }
+ numWritten = nbytes;
+ }
+ else
+ {
+ numWritten = trap1_40((unsigned short)fd, nbytes, buf);
+ }
+ }
+ if (numWritten < 0)
+ {
+ gem_error_to_errno(numWritten);
+ return -1;
+ }
+ return numWritten;
+}