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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// This file is part of yash, an extended POSIX shell.
// Copyright (C) 2021 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/>.
//! Readonly built-in.
//!
//! The **`readonly`** built-in behaves differently depending on the arguments.
//!
//! TODO: **Only portable features are implemented for now.**
//!
//! # Making variables read-only
//!
//! If the `-p` (`--print`) or `-f` (`--functions`) option is not specified and
//! there are any operands, the built-in makes the specified variables
//! read-only.
//!
//! ## Synopsis
//!
//! ```sh
//! readonly name[=value]…
//! ```
//!
//! ## Options
//!
//! None.
//!
//! ## Operands
//!
//! Operands specify the names and values of the variables to be made read-only.
//! If an operand contains an equal sign (`=`), the operand is split into the
//! name and value at the first equal sign. The value is assigned to the
//! variable named by the name. Otherwise, the variable named by the operand is
//! created without a value unless it is already defined, in which case the
//! existing value is retained.
//!
//! If no operands are given, the built-in prints variables (see below).
//!
//! ## Standard output
//!
//! None.
//!
//! # Printing read-only variables
//!
//! If the `-p` (`--print`) option is specified and the `-f` (`--functions`)
//! option is not specified, the built-in prints the names and values of the
//! variables named by the operands in the format that can be
//! [evaluated](crate::eval) as shell code to recreate the variables.
//! If there are no operands and the `-f` (`--functions`) option is not
//! specified, the built-in prints all read-only variables in the same format.
//!
//! ## Synopsis
//!
//! ```sh
//! readonly -p [name…]
//! ```
//!
//! ```sh
//! readonly
//! ```
//!
//! # Options
//!
//! The **`-p`** (**`--print`**) option must be specified to print variables
//! unless there are no operands.
//!
//! # Operands
//!
//! Operands specify the names of the variables to be printed. If no operands
//! are given, all read-only variables are printed.
//!
//! ## Standard output
//!
//! A command string that invokes the readonly built-in to recreate the variable
//! is printed for each read-only variable. Note that the command does not
//! include options to restore the attributes of the variable, such as the `-x`
//! option to make variables exported.
//!
//! Also note that evaluating the printed commands in the current context will
//! fail (unless the variable is declared without a value) because the variable
//! is already defined and read-only.
//!
//! For array variables, the readonly built-in invocation is preceded by a
//! separate assignment command since the readonly built-in does not support
//! assigning values to array variables.
//!
//! # Making functions read-only
//!
//! If the `-f` (`--functions`) option is specified, the built-in makes the
//! specified functions read-only.
//!
//! ## Synopsis
//!
//! ```sh
//! readonly -f name…
//! ```
//!
//! ## Options
//!
//! The **`-f`** (**`--functions`**) option must be specified to make functions
//! read-only.
//!
//! ## Operands
//!
//! Operands specify the names of the functions to be made read-only.
//!
//! ## Standard output
//!
//! None.
//!
//! # Printing read-only functions
//!
//! If the `-f` (`--functions`) and `-p` (`--print`) options are specified, the
//! built-in prints the attributes and definitions of the shell functions named
//! by the operands in the format that can be [evaluated](crate::eval) as shell
//! code to recreate the functions.
//! If there are no operands and the `-f` (`--functions`) option is specified,
//! the built-in prints all read-only functions in the same format.
//!
//! ## Synopsis
//!
//! ```sh
//! readonly -fp [name…]
//! ```
//!
//! ```sh
//! readonly -f
//! ```
//!
//! ## Options
//!
//! The **`-f`** (**`--functions`**) and **`-p`** (**`--print`**) options must be
//! specified to print functions. The `-p` option may be omitted if there are no
//! operands.
//!
//! ## Operands
//!
//! Operands specify the names of the functions to be printed. If no operands
//! are given, all read-only functions are printed.
//!
//! ## Standard output
//!
//! A command string of a function definition command is printed for each
//! function, followed by a simple command invoking the readonly built-in to
//! make the function read-only.
//!
//! Note that executing the printed commands in the current context will fail
//! because the function is already defined and read-only.
//!
//! # Errors
//!
//! When making a variable read-only with a value, it is an error if the
//! variable is already read-only.
//!
//! It is an error to specify a non-existing function for making it read-only.
//!
//! When printing variables or functions, it is an error if an operand names a
//! non-existing variable or function.
//!
//! # Exit status
//!
//! Zero unless an error occurs.
//!
//! # Portability
//!
//! This built-in is part of the POSIX standard. Printing variables is portable
//! only when the `-p` option is used without operands. Operations on functions
//! with the `-f` option are non-portable extensions.
//!
//! # Implementation notes
//!
//! The implementation of this built-in depends on that of the
//! [`typeset`](crate::typeset) built-in. The readonly built-in basically works
//! like the typeset built-in with the `-r` (`--readonly`) option except that:
//! - The `-g` (`--global`) option is also implied when operating on variables.
//! - Printed commands name the readonly built-in instead of the typeset built-in.
//! - Printed commands do not include options that modify variable attributes.
use crateoutput;
use cratereport_error;
use cratereport_failure;
use crateto_single_message;
use crateinterpret;
use crateparse;
use crateOptionSpec;
use cratePRINT_OPTION;
use crateCommand;
use crateFunctionAttr;
use cratePrintContext;
use crateGlobal;
use crateVariableAttr;
use Result;
use On;
use Field;
use Env;
/// List of portable options applicable to the readonly built-in
pub const PORTABLE_OPTIONS: & = &;
/// Printing context for the readonly built-in
pub const PRINT_CONTEXT: = PrintContext ;
// TODO Split into syntax and semantics submodules
/// Entry point for executing the `readonly` built-in
pub async