1 |
# Run with
|
2 |
#
|
3 |
# $ test/spec.sh nameref
|
4 |
|
5 |
|
6 |
show_value() {
|
7 |
local -n array_name=$1
|
8 |
local idx=$2
|
9 |
echo "${array_name[$idx]}"
|
10 |
}
|
11 |
shadock=(ga bu zo meu)
|
12 |
show_value shadock 2
|
13 |
## stdout: zo
|
14 |
|
15 |
|
16 |
set1() {
|
17 |
local -n array_name=$1
|
18 |
local val=$2
|
19 |
array_name[1]=$val
|
20 |
}
|
21 |
shadock=(a b c d)
|
22 |
set1 shadock ZZZ
|
23 |
echo ${shadock[@]}
|
24 |
## STDOUT:
|
25 |
a ZZZ c d
|
26 |
## END
|
27 |
|
28 |
|
29 |
show_value() {
|
30 |
local -n array_name=$1
|
31 |
local idx=$2
|
32 |
echo "${array_name[$idx]}"
|
33 |
}
|
34 |
days=([monday]=eggs [tuesday]=bread [sunday]=jam)
|
35 |
show_value days sunday
|
36 |
## stdout: jam
|
37 |
## BUG mksh stdout: [monday]=eggs
|
38 |
# mksh note: it coerces "days" to 0? Horrible.
|
39 |
|
40 |
|
41 |
show_value() {
|
42 |
local -n array_name=$1
|
43 |
local idx=$2
|
44 |
echo "${array_name[$idx]}"
|
45 |
}
|
46 |
caller() {
|
47 |
local shadock=(ga bu zo meu)
|
48 |
show_value shadock 2
|
49 |
}
|
50 |
caller
|
51 |
## stdout: zo
|
52 |
# mksh appears not to have local arrays!
|
53 |
## BUG mksh stdout-json: ""
|
54 |
## BUG mksh status: 1
|
55 |
|
56 |
|
57 |
|
58 |
x=foo
|
59 |
|
60 |
ref=x
|
61 |
|
62 |
echo ref=$ref
|
63 |
|
64 |
typeset -n ref
|
65 |
echo ref=$ref
|
66 |
|
67 |
# mutate underlying var
|
68 |
x=bar
|
69 |
echo ref=$ref
|
70 |
|
71 |
typeset +n ref
|
72 |
echo ref=$ref
|
73 |
|
74 |
## STDOUT:
|
75 |
ref=x
|
76 |
ref=foo
|
77 |
ref=bar
|
78 |
ref=x
|
79 |
## END
|
80 |
|
81 |
|
82 |
x=XX
|
83 |
y=YY
|
84 |
|
85 |
ref=x
|
86 |
ref=y
|
87 |
echo 1 ref=$ref
|
88 |
|
89 |
# now it's a reference
|
90 |
typeset -n ref
|
91 |
|
92 |
echo 2 ref=$ref # prints YY
|
93 |
|
94 |
ref=XXXX
|
95 |
echo 3 ref=$ref # it actually prints y, which is XXXX
|
96 |
|
97 |
# now Y is mutated!
|
98 |
echo 4 y=$y
|
99 |
|
100 |
## STDOUT:
|
101 |
1 ref=y
|
102 |
2 ref=YY
|
103 |
3 ref=XXXX
|
104 |
4 y=XXXX
|
105 |
## END
|
106 |
|
107 |
|
108 |
|
109 |
foo=FOO # should NOT use this
|
110 |
|
111 |
x=foo
|
112 |
ref=x
|
113 |
|
114 |
echo ref=$ref
|
115 |
echo "!ref=${!ref}"
|
116 |
|
117 |
echo 'NOW A NAMEREF'
|
118 |
|
119 |
typeset -n ref
|
120 |
echo ref=$ref
|
121 |
echo "!ref=${!ref}"
|
122 |
|
123 |
## STDOUT:
|
124 |
ref=x
|
125 |
!ref=foo
|
126 |
NOW A NAMEREF
|
127 |
ref=foo
|
128 |
!ref=x
|
129 |
## END
|
130 |
## N-I mksh STDOUT:
|
131 |
ref=x
|
132 |
!ref=ref
|
133 |
NOW A NAMEREF
|
134 |
ref=foo
|
135 |
!ref=x
|
136 |
## END
|
137 |
|
138 |
|
139 |
set -- one two three
|
140 |
|
141 |
ref='#'
|
142 |
echo ref=$ref
|
143 |
typeset -n ref
|
144 |
echo ref=$ref
|
145 |
|
146 |
## STDOUT:
|
147 |
ref=#
|
148 |
ref=#
|
149 |
## END
|
150 |
|
151 |
# mksh does respect it!! Gah.
|
152 |
## OK mksh STDOUT:
|
153 |
ref=#
|
154 |
ref=3
|
155 |
## END
|
156 |
|
157 |
|
158 |
|
159 |
shopt -s strict_nameref
|
160 |
|
161 |
ref='#'
|
162 |
echo ref=$ref
|
163 |
typeset -n ref
|
164 |
echo ref=$ref
|
165 |
## STDOUT:
|
166 |
ref=#
|
167 |
## END
|
168 |
## status: 1
|
169 |
## N-I bash status: 0
|
170 |
## N-I bash STDOUT:
|
171 |
ref=#
|
172 |
ref=#
|
173 |
## END
|
174 |
## N-I mksh status: 0
|
175 |
## N-I mksh STDOUT:
|
176 |
ref=#
|
177 |
ref=0
|
178 |
## END
|
179 |
|
180 |
|
181 |
set -- one two three
|
182 |
|
183 |
x=X
|
184 |
|
185 |
ref='1'
|
186 |
echo ref=$ref
|
187 |
typeset -n ref
|
188 |
echo ref=$ref
|
189 |
|
190 |
# BUG: This is really assigning '1', which is INVALID
|
191 |
# with strict_nameref that degrades!!!
|
192 |
ref2='$1'
|
193 |
echo ref2=$ref2
|
194 |
typeset -n ref2
|
195 |
echo ref2=$ref2
|
196 |
|
197 |
x=foo
|
198 |
|
199 |
ref3='x'
|
200 |
echo ref3=$ref3
|
201 |
typeset -n ref3
|
202 |
echo ref3=$ref3
|
203 |
|
204 |
## STDOUT:
|
205 |
ref=1
|
206 |
ref=1
|
207 |
ref2=$1
|
208 |
ref2=$1
|
209 |
ref3=x
|
210 |
ref3=foo
|
211 |
## END
|
212 |
## BUG mksh status: 1
|
213 |
## BUG mksh STDOUT:
|
214 |
ref=1
|
215 |
ref=one
|
216 |
ref2=$1
|
217 |
## END
|
218 |
|
219 |
|
220 |
ref=1 # mksh makes this READ-ONLY! Because it's not valid.
|
221 |
|
222 |
echo ref=$ref
|
223 |
typeset -n ref
|
224 |
echo ref=$ref
|
225 |
|
226 |
ref=foo
|
227 |
echo ref=$ref
|
228 |
## STDOUT:
|
229 |
ref=1
|
230 |
ref=1
|
231 |
ref=foo
|
232 |
## END
|
233 |
## OK mksh status: 2
|
234 |
## OK mksh STDOUT:
|
235 |
ref=1
|
236 |
ref=
|
237 |
## END
|
238 |
|
239 |
|
240 |
case $SH in *bash|*mksh) exit ;; esac
|
241 |
|
242 |
shopt -s strict_nameref
|
243 |
|
244 |
ref=1
|
245 |
|
246 |
echo ref=$ref
|
247 |
typeset -n ref
|
248 |
echo ref=$ref
|
249 |
|
250 |
ref=foo
|
251 |
echo ref=$ref
|
252 |
## status: 1
|
253 |
## STDOUT:
|
254 |
ref=1
|
255 |
## END
|
256 |
## N-I bash/mksh status: 0
|
257 |
## N-I bash/mksh stdout-json: ""
|
258 |
|
259 |
|
260 |
typeset -n ref
|
261 |
|
262 |
# This is technically incorrect: an undefined name shouldn't evaluate to empty
|
263 |
# string. mksh doesn't allow it.
|
264 |
echo ref=$ref
|
265 |
|
266 |
echo nounset
|
267 |
set -o nounset
|
268 |
echo ref=$ref
|
269 |
## status: 1
|
270 |
## STDOUT:
|
271 |
ref=
|
272 |
nounset
|
273 |
## END
|
274 |
## OK mksh stdout-json: ""
|
275 |
|
276 |
|
277 |
typeset -n ref
|
278 |
echo ref=$ref
|
279 |
|
280 |
# this is a no-op in bash, should be stricter
|
281 |
ref=x
|
282 |
echo ref=$ref
|
283 |
|
284 |
typeset -n ref2=undef
|
285 |
echo ref2=$ref2
|
286 |
ref2=x
|
287 |
echo ref2=$ref2
|
288 |
|
289 |
## STDOUT:
|
290 |
ref=
|
291 |
ref=
|
292 |
ref2=
|
293 |
ref2=x
|
294 |
## END
|
295 |
|
296 |
# mksh gives a good error: empty nameref target
|
297 |
## OK mksh status: 1
|
298 |
## OK mksh stdout-json: ""
|
299 |
|
300 |
|
301 |
typeset -n ref
|
302 |
|
303 |
echo ref=$ref
|
304 |
|
305 |
# Now that it's a string, it still has the -n attribute
|
306 |
x=XX
|
307 |
ref=x
|
308 |
echo ref=$ref
|
309 |
|
310 |
## STDOUT:
|
311 |
ref=
|
312 |
ref=XX
|
313 |
## END
|
314 |
## N-I mksh status: 1
|
315 |
## N-I mksh stdout-json: ""
|
316 |
|
317 |
|
318 |
x=X
|
319 |
typeset -n ref #=x
|
320 |
echo hi
|
321 |
|
322 |
# bash prints warning: REMOVES the nameref attribute here!
|
323 |
ref=(x y)
|
324 |
echo ref=$ref
|
325 |
|
326 |
## status: 1
|
327 |
## STDOUT:
|
328 |
hi
|
329 |
## END
|
330 |
## N-I mksh status: 1
|
331 |
## N-I mksh stdout-json: ""
|
332 |
## BUG bash status: 0
|
333 |
## BUG bash STDOUT:
|
334 |
hi
|
335 |
ref=x
|
336 |
## END
|
337 |
|
338 |
|
339 |
x=foo
|
340 |
typeset -n -x ref=x
|
341 |
|
342 |
# hm bash ignores it but mksh doesn't. maybe disallow it.
|
343 |
printenv.py x ref
|
344 |
echo ---
|
345 |
export x
|
346 |
printenv.py x ref
|
347 |
## STDOUT:
|
348 |
None
|
349 |
x
|
350 |
---
|
351 |
foo
|
352 |
x
|
353 |
## END
|
354 |
## OK mksh STDOUT:
|
355 |
None
|
356 |
None
|
357 |
---
|
358 |
foo
|
359 |
None
|
360 |
## END
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
# hm bash also ignores -r when -n is set
|
366 |
|
367 |
x=XX
|
368 |
typeset -n -r ref=x
|
369 |
|
370 |
echo ref=$ref
|
371 |
|
372 |
# it feels like I shouldn't be able to mutate this?
|
373 |
ref=XXXX
|
374 |
echo ref=$ref
|
375 |
|
376 |
x=X
|
377 |
echo x=$x
|
378 |
|
379 |
## STDOUT:
|
380 |
ref=XX
|
381 |
ref=XXXX
|
382 |
x=X
|
383 |
## END
|
384 |
|
385 |
|
386 |
|
387 |
x=X
|
388 |
typeset -n -r ref=x
|
389 |
|
390 |
echo ref=$ref
|
391 |
|
392 |
# it feels like I shouldn't be able to mutate this?
|
393 |
ref=XX
|
394 |
echo ref=$ref
|
395 |
|
396 |
# now the underling variable is immutable
|
397 |
typeset -r x
|
398 |
|
399 |
ref=XXX
|
400 |
echo ref=$ref
|
401 |
echo x=$x
|
402 |
|
403 |
## status: 1
|
404 |
## OK mksh status: 2
|
405 |
## STDOUT:
|
406 |
ref=X
|
407 |
ref=XX
|
408 |
## END
|
409 |
|
410 |
## OK bash status: 0
|
411 |
## OK bash STDOUT:
|
412 |
ref=X
|
413 |
ref=XX
|
414 |
ref=XX
|
415 |
x=XX
|
416 |
## END
|
417 |
|
418 |
|
419 |
x=X
|
420 |
typeset -n ref=x
|
421 |
echo ref=$ref
|
422 |
|
423 |
# this works
|
424 |
unset ref
|
425 |
echo ref=$ref
|
426 |
echo x=$x
|
427 |
|
428 |
## STDOUT:
|
429 |
ref=X
|
430 |
ref=
|
431 |
x=
|
432 |
## END
|
433 |
|
434 |
|
435 |
x=foo
|
436 |
typeset -n ref=x
|
437 |
typeset -n ref_to_ref=ref
|
438 |
echo ref_to_ref=$ref_to_ref
|
439 |
echo ref=$ref
|
440 |
## STDOUT:
|
441 |
ref_to_ref=foo
|
442 |
ref=foo
|
443 |
## END
|
444 |
|
445 |
|
446 |
typeset -n ref1=ref2
|
447 |
typeset -n ref2=ref1
|
448 |
echo defined
|
449 |
echo ref1=$ref1
|
450 |
echo ref2=$ref1
|
451 |
## status: 1
|
452 |
## STDOUT:
|
453 |
defined
|
454 |
## END
|
455 |
## OK mksh stdout-json: ""
|
456 |
## BUG bash status: 0
|
457 |
## BUG bash STDOUT:
|
458 |
defined
|
459 |
ref1=
|
460 |
ref2=
|
461 |
## END
|
462 |
|
463 |
|
464 |
typeset -n ref1=ref2
|
465 |
typeset -n ref2=ref1 # not detected here
|
466 |
echo defined $?
|
467 |
ref1=z # detected here
|
468 |
echo mutated $?
|
469 |
## status: 1
|
470 |
## STDOUT:
|
471 |
defined 0
|
472 |
## END
|
473 |
## OK mksh stdout-json: ""
|
474 |
## BUG bash status: 0
|
475 |
## BUG bash STDOUT:
|
476 |
defined 0
|
477 |
mutated 1
|
478 |
## END
|
479 |
|
480 |
|
481 |
|
482 |
f3() {
|
483 |
local -n ref=$1
|
484 |
ref=x
|
485 |
}
|
486 |
|
487 |
f2() {
|
488 |
f3 "$@"
|
489 |
}
|
490 |
|
491 |
f1() {
|
492 |
local F1=F1
|
493 |
echo F1=$F1
|
494 |
f2 F1
|
495 |
echo F1=$F1
|
496 |
}
|
497 |
f1
|
498 |
|
499 |
## STDOUT:
|
500 |
F1=F1
|
501 |
F1=x
|
502 |
## END
|
503 |
|
504 |
|
505 |
|
506 |
x=XX
|
507 |
y=YY
|
508 |
typeset -n ref=x
|
509 |
echo ref=$ref
|
510 |
echo x=$x
|
511 |
echo y=$y
|
512 |
|
513 |
echo ----
|
514 |
typeset -n ref=y
|
515 |
echo ref=$ref
|
516 |
echo x=$x
|
517 |
echo y=$y
|
518 |
echo ----
|
519 |
ref=z
|
520 |
echo ref=$ref
|
521 |
echo x=$x
|
522 |
echo y=$y
|
523 |
|
524 |
## STDOUT:
|
525 |
ref=XX
|
526 |
x=XX
|
527 |
y=YY
|
528 |
----
|
529 |
ref=YY
|
530 |
x=XX
|
531 |
y=YY
|
532 |
----
|
533 |
ref=z
|
534 |
x=XX
|
535 |
y=z
|
536 |
## END
|
537 |
|
538 |
|
539 |
|
540 |
typeset -n ref='a[2]'
|
541 |
a=(zero one two three)
|
542 |
echo ref=$ref
|
543 |
## STDOUT:
|
544 |
ref=two
|
545 |
## END
|
546 |
|
547 |
|
548 |
|
549 |
# this confuses code and data
|
550 |
typeset -n ref='a[$(echo 2) + 1]'
|
551 |
a=(zero one two three)
|
552 |
echo ref=$ref
|
553 |
## STDOUT:
|
554 |
ref=three
|
555 |
## END
|
556 |
|
557 |
|
558 |
|
559 |
# this confuses code and data
|
560 |
typeset -n ref='a[@]'
|
561 |
a=('A B' C)
|
562 |
argv.py ref "$ref" # READ through ref works
|
563 |
ref=(X Y Z) # WRITE through doesn't work
|
564 |
echo status=$?
|
565 |
argv.py 'ref[@]' "${ref[@]}"
|
566 |
argv.py ref "$ref" # JOINING mangles the array?
|
567 |
argv.py 'a[@]' "${a[@]}"
|
568 |
## STDOUT:
|
569 |
['ref', 'A B C']
|
570 |
status=1
|
571 |
['ref[@]']
|
572 |
['ref', 'A B C']
|
573 |
['a[@]', 'A B', 'C']
|
574 |
## END
|
575 |
## OK mksh status: 1
|
576 |
## OK mksh stdout-json: ""
|
577 |
|
578 |
|
579 |
|
580 |
# This is DIFFERENT than the nameref itself being 'array[0]' !
|
581 |
|
582 |
array=(X Y Z)
|
583 |
typeset -n ref=array
|
584 |
ref[0]=xx
|
585 |
echo ${array[@]}
|
586 |
## STDOUT:
|
587 |
xx Y Z
|
588 |
## END
|
589 |
|
590 |
|
591 |
array=(X Y Z)
|
592 |
typeset -n ref='array[0]'
|
593 |
ref[0]=foo # error in bash: 'array[0]': not a valid identifier
|
594 |
echo status=$?
|
595 |
echo ${array[@]}
|
596 |
## STDOUT:
|
597 |
status=1
|
598 |
X Y Z
|
599 |
## END
|
600 |
## BUG mksh STDOUT:
|
601 |
status=0
|
602 |
foo Y Z
|
603 |
## END
|
604 |
|
605 |
|
606 |
|
607 |
set -- A B
|
608 |
typeset -n ref='@' # bash gives an error here
|
609 |
echo status=$?
|
610 |
|
611 |
echo ref=$ref # bash doesn't give an error here
|
612 |
echo status=$?
|
613 |
## status: 1
|
614 |
## stdout-json: ""
|
615 |
## OK bash status: 0
|
616 |
## OK bash STDOUT:
|
617 |
status=1
|
618 |
ref=
|
619 |
status=0
|
620 |
## END
|
621 |
|
622 |
|
623 |
typeset -A bashup_ev_r
|
624 |
bashup_ev_r['foo']=bar
|
625 |
|
626 |
p() {
|
627 |
local s=foo
|
628 |
local -n e=bashup_ev["$s"] f=bashup_ev_r["$s"]
|
629 |
# Different!
|
630 |
#local e=bashup_ev["$s"] f=bashup_ev_r["$s"]
|
631 |
argv.py "$f"
|
632 |
}
|
633 |
p
|
634 |
## STDOUT:
|
635 |
['bar']
|
636 |
## END
|
637 |
## N-I mksh stdout-json: ""
|
638 |
## N-I mksh status: 1
|