1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// This file is part of yash, an extended POSIX shell.
// Copyright (C) 2023 WATANABE Yuki
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Read built-in
//!
//! The **`read`** built-in reads a line into variables.
//!
//! # Synopsis
//!
//! ```sh
//! read [-r] variable…
//! ```
//!
//! # Description
//!
//! The read built-in reads a line from the standard input and assigns it to the
//! variables named by the operands. Field splitting is performed on the line
//! read to produce as many fields as there are variables. If there are fewer
//! fields than variables, the remaining variables are set to empty strings. If
//! there are more fields than variables, the last variable receives all
//! remaining fields, including the field separators, but not trailing
//! whitespace separators.
//!
//! ## Escaping
//!
//! By default, backslashes in the input are treated as quoting characters that
//! prevent the following character from being interpreted as a field separator.
//! Backslash-newline pairs are treated as line continuations.
//!
//! The `-r` option disables this behavior.
//!
//! ## Prompting
//!
//! By default, the read built-in does not display a prompt before reading a
//! line. (TODO: Options to display a prompt)
//!
//! When reading lines after the first line, the read built-in displays the
//! value of the `PS2` variable as a prompt if the shell is interactive and the
//! input is from a terminal.
//!
//! # Options
//!
//! The **`-r`** option disables the interpretation of backslashes.
//!
//! # Operands
//!
//! One or more operands are required.
//! Each operand is the name of a variable to be assigned.
//!
//! # Errors
//!
//! It is an error if the standard input is not readable.
//!
//! It is an error if any variable to be assigned is read-only.
//!
//! # Exit status
//!
//! The exit status is zero if a line was read successfully and non-zero
//! otherwise. If the built-in reaches the end of the input before finding a
//! newline, it returns non-zero, but the variables are still assigned with the
//! line read so far.
//!
//! # Portability
//!
//! The read built-in is defined in the POSIX standard. The `-r` option is the
//! only option defined in the POSIX standard.
//!
//! In this implementation, the value of the `PS2` variable is subject to
//! parameter expansion, command substitution, and arithmetic expansion. Other
//! implementations may not perform these expansions.
//!
//! # Implementation notes
//!
//! Reading from an unseekable input may be slow because the built-in reads the
//! input byte by byte to make sure it does not read past the end of the line.
use cratereport_error;
use cratereport_failure;
use crateto_single_message;
use ExitStatus;
use Field;
use Env;
/// Abstract command line arguments of the `read` built-in
///
/// An instance of this struct is created by parsing command line arguments
/// using the [`syntax`] module.
/// Entry point of the `read` built-in
pub async