//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import SwiftShims #if SWIFT_STDLIB_HAS_COMMANDLINE @_silgen_name("_swift_stdlib_getUnsafeArgvArgc") internal func _swift_stdlib_getUnsafeArgvArgc(_: UnsafeMutablePointer) -> UnsafeMutablePointer?> /// Command-line arguments for the current process. @frozen // namespace public enum CommandLine: ~BitwiseCopyable {} extension CommandLine { /// The backing static variable for argument count may come either from the /// entry point or it may need to be computed e.g. if we're in the REPL. @usableFromInline internal static var _argc: Int32 = 0 /// The backing static variable for arguments may come either from the /// entry point or it may need to be computed e.g. if we're in the REPL. /// /// Care must be taken to ensure that `_swift_stdlib_getUnsafeArgvArgc` is /// not invoked more times than is necessary (at most once). @usableFromInline internal static var _unsafeArgv: UnsafeMutablePointer?> = unsafe _swift_stdlib_getUnsafeArgvArgc(&_argc) /// Access to the raw argc value from C. public static var argc: Int32 { // We intentionally ignore the argc value given to us from // '_swift_stdlib_getUnsafeArgvArgc' because argv and argc are mutable, so // someone can mutate the contents of argv and never update the argc value. // This results in an out of sync argc which can lead to crashes on first // access to 'CommandLine.arguments' due to attempting to read '0 ..< argc' // strings. // // Note: It's still entirely possible that someone may update argv after // this iteration and before we actually read argv, but we have no control // over synchronizing access to argc and argv. var argc: Int32 = 0 while let _ = unsafe _unsafeArgv[Int(argc)] { argc += 1 } return argc } /// Access to the raw argv value from C. /// /// The value of this property is a `nil`-terminated C array. Including the /// trailing `nil`, there are ``argc`` `+ 1` elements in the array. /// /// - Note: Accessing the argument vector through this pointer is unsafe. /// Where possible, use ``arguments`` instead. public static var unsafeArgv: UnsafeMutablePointer?> { return unsafe _unsafeArgv } // This is extremely unsafe and allows for concurrent writes with no // synchronization to the underlying data. In a future version of Swift you // will not be able to write to 'CommandLine.arguments'. static nonisolated(unsafe) var _arguments: [String] = (0 ..< Int(argc)).map { unsafe String(cString: _unsafeArgv[$0]!) } /// An array that provides access to this program's command line arguments. /// /// Use `CommandLine.arguments` to access the command line arguments used /// when executing the current program. The name of the executed program is /// the first argument. /// /// The following example shows a command line executable that squares the /// integer given as an argument. /// /// if CommandLine.arguments.count == 2, /// let number = Int(CommandLine.arguments[1]) { /// print("\(number) x \(number) is \(number * number)") /// } else { /// print( /// """ /// Error: Please provide a number to square. /// Usage: command /// """ /// ) /// } /// /// Running the program results in the following output: /// /// $ command 5 /// 5 x 5 is 25 /// $ command ZZZ /// Error: Please provide a number to square. /// Usage: command public static var arguments: [String] { get { _arguments } @available(*, deprecated, message: "Do not modify CommandLine.arguments. It will become read-only in a future version of Swift.") @available(swift, obsoleted: 6.0) set { _arguments = newValue } } } #endif // SWIFT_STDLIB_HAS_COMMANDLINE