mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
123 lines
4.4 KiB
Swift
123 lines
4.4 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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<Int32>)
|
|
-> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
|
|
|
|
/// 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<UnsafeMutablePointer<Int8>?>
|
|
= 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<UnsafeMutablePointer<Int8>?> {
|
|
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 <number>
|
|
/// """
|
|
/// )
|
|
/// }
|
|
///
|
|
/// 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 <number>
|
|
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
|