xref: /llvm-project/libc/src/stdio/generic/puts.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
1d2024bbcSJoseph Huber //===-- Implementation of puts --------------------------------------------===//
2d2024bbcSJoseph Huber //
3d2024bbcSJoseph Huber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d2024bbcSJoseph Huber // See https://llvm.org/LICENSE.txt for license information.
5d2024bbcSJoseph Huber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d2024bbcSJoseph Huber //
7d2024bbcSJoseph Huber //===----------------------------------------------------------------------===//
8d2024bbcSJoseph Huber 
9d2024bbcSJoseph Huber #include "src/stdio/puts.h"
10d2024bbcSJoseph Huber #include "src/__support/CPP/string_view.h"
11d2024bbcSJoseph Huber #include "src/__support/File/file.h"
12d2024bbcSJoseph Huber 
135aed6d67SMichael Jones #include "hdr/types/FILE.h"
14*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
15d2024bbcSJoseph Huber #include "src/errno/libc_errno.h"
165aed6d67SMichael Jones #include <stddef.h>
17d2024bbcSJoseph Huber 
18*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
19d2024bbcSJoseph Huber 
201bb85fa9SJoseph Huber namespace {
211bb85fa9SJoseph Huber 
221bb85fa9SJoseph Huber // Simple helper to unlock the file once destroyed.
231bb85fa9SJoseph Huber struct ScopedLock {
241bb85fa9SJoseph Huber   ScopedLock(LIBC_NAMESPACE::File *stream) : stream(stream) { stream->lock(); }
251bb85fa9SJoseph Huber   ~ScopedLock() { stream->unlock(); }
261bb85fa9SJoseph Huber 
271bb85fa9SJoseph Huber private:
281bb85fa9SJoseph Huber   LIBC_NAMESPACE::File *stream;
291bb85fa9SJoseph Huber };
301bb85fa9SJoseph Huber 
311bb85fa9SJoseph Huber } // namespace
321bb85fa9SJoseph Huber 
33d2024bbcSJoseph Huber LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) {
34d2024bbcSJoseph Huber   cpp::string_view str_view(str);
351bb85fa9SJoseph Huber 
361bb85fa9SJoseph Huber   // We need to lock the stream to ensure the newline is always appended.
371bb85fa9SJoseph Huber   ScopedLock lock(LIBC_NAMESPACE::stdout);
381bb85fa9SJoseph Huber 
391bb85fa9SJoseph Huber   auto result = LIBC_NAMESPACE::stdout->write_unlocked(str, str_view.size());
40d2024bbcSJoseph Huber   if (result.has_error())
41d2024bbcSJoseph Huber     libc_errno = result.error;
42d2024bbcSJoseph Huber   size_t written = result.value;
43d2024bbcSJoseph Huber   if (str_view.size() != written) {
44d2024bbcSJoseph Huber     // The stream should be in an error state in this case.
45d2024bbcSJoseph Huber     return EOF;
46d2024bbcSJoseph Huber   }
471bb85fa9SJoseph Huber   result = LIBC_NAMESPACE::stdout->write_unlocked("\n", 1);
48d2024bbcSJoseph Huber   if (result.has_error())
49d2024bbcSJoseph Huber     libc_errno = result.error;
50d2024bbcSJoseph Huber   written = result.value;
51d2024bbcSJoseph Huber   if (1 != written) {
52d2024bbcSJoseph Huber     // The stream should be in an error state in this case.
53d2024bbcSJoseph Huber     return EOF;
54d2024bbcSJoseph Huber   }
55d2024bbcSJoseph Huber   return 0;
56d2024bbcSJoseph Huber }
57d2024bbcSJoseph Huber 
58*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
59