1 //===-- Implementation of puts --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/stdio/puts.h" 10 #include "src/__support/CPP/string_view.h" 11 #include "src/__support/File/file.h" 12 13 #include "hdr/types/FILE.h" 14 #include "src/__support/macros/config.h" 15 #include "src/errno/libc_errno.h" 16 #include <stddef.h> 17 18 namespace LIBC_NAMESPACE_DECL { 19 20 namespace { 21 22 // Simple helper to unlock the file once destroyed. 23 struct ScopedLock { ScopedLockLIBC_NAMESPACE_DECL::__anon5123db2a0111::ScopedLock24 ScopedLock(LIBC_NAMESPACE::File *stream) : stream(stream) { stream->lock(); } ~ScopedLockLIBC_NAMESPACE_DECL::__anon5123db2a0111::ScopedLock25 ~ScopedLock() { stream->unlock(); } 26 27 private: 28 LIBC_NAMESPACE::File *stream; 29 }; 30 31 } // namespace 32 33 LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) { 34 cpp::string_view str_view(str); 35 36 // We need to lock the stream to ensure the newline is always appended. 37 ScopedLock lock(LIBC_NAMESPACE::stdout); 38 39 auto result = LIBC_NAMESPACE::stdout->write_unlocked(str, str_view.size()); 40 if (result.has_error()) 41 libc_errno = result.error; 42 size_t written = result.value; 43 if (str_view.size() != written) { 44 // The stream should be in an error state in this case. 45 return EOF; 46 } 47 result = LIBC_NAMESPACE::stdout->write_unlocked("\n", 1); 48 if (result.has_error()) 49 libc_errno = result.error; 50 written = result.value; 51 if (1 != written) { 52 // The stream should be in an error state in this case. 53 return EOF; 54 } 55 return 0; 56 } 57 58 } // namespace LIBC_NAMESPACE_DECL 59