Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow scalar form of BASH_LINENO and FUNCNAME #656

Conversation

akinomyoga
Copy link
Collaborator

Related to the second point in #653 (comment). I found that BASH_SOURCE is specially treated (de92fc5). BASH_LINENO and FUNCNAME are also members of the same family. They are original scalar variables and later extended to an array variable. They should allow both form of $X and ${X[0]}.

Note: When I create a test, I noticed that there is a difference between Bash and Oil for FUNCNAME in source contexts, i.e., FUNCNAME= in Bash and FUNCNAME=source in Oil. The added test is created for the Oil behavior.

@akinomyoga akinomyoga force-pushed the allow-scalar-form-of-bash_lineno-and-funcname branch from ba41d4a to bfc03fe Compare March 15, 2020 00:45
@andychu andychu merged commit 30211bf into oils-for-unix:master Mar 15, 2020
@andychu
Copy link
Contributor

andychu commented Mar 15, 2020

Great thank you for fixing this! And with great tests.

I don't see what you mean about a bash/Oil difference -- wouldn't the tests fail if that were the case? The test format has the ability to express those differences with OK bash STDOUT or OK osh STDOUT but I don't see that here?

FUNCNAME can be source in both?

@andychu
Copy link
Contributor

andychu commented Mar 15, 2020

Oh I see test case #2 does fail in bash... let me see why that is.

@andychu
Copy link
Contributor

andychu commented Mar 15, 2020

I moved it to case #1 to make the difference more clear.

http://www.oilshell.org/git-branch/dev/andy-21/c156b72b/spec/introspect.html

c156b72 (sorry for unrelated changes)

To me this feels like a bash bug because it breaks an invariant. Shouldn't ${FUNCNAME} == ${FUNCNAME[0]} or am I missing something?

(If I remove source in line 1324 of the core/state.py, different tests fail. Something like that is needed to match bash. BTW this is bash 4.4.)

@akinomyoga
Copy link
Collaborator Author

To me this feels like a bash bug because it breaks an invariant. Shouldn't ${FUNCNAME} == ${FUNCNAME[0]} or am I missing something?

Bash consistently produces the empty value for both $FUNCNAME and ${FUNCNAME[0]} in my environment in all the versions Bash 3.0-5.0. Does your Bash produce source for ${FUNCNAME[0]}?

# test1.sh

set1=unset set2=unset
[[ ${FUNCNAME+set} ]] && set1=set
[[ ${FUNCNAME[0]+set} ]] && set2=set
echo "\$FUNCNAME = '$FUNCNAME' ($set1)"
echo "\${FUNCNAME[0]} = '${FUNCNAME[0]}' ($set2)"
declare -p FUNCNAME
$ bash -c 'source test1.sh'
$FUNCNAME = '' (unset)
${FUNCNAME[0]} = '' (unset)
declare -a FUNCNAME

@andychu
Copy link
Contributor

andychu commented Mar 15, 2020

Yes bash 4.4 produces source. I clarified the tests and these pas:

https://github.com/oilshell/oil/blob/master/spec/introspect.test.sh#L60

Hopefully it's not too hard to read. But I claim bash's output in lines 91-94 for FUNCNAME is inconsistent with its output in lines 98-101 for array a. It doesn't behave like any other array.

Well in the other change you're showing that "$@" doesn't behave like any other array either! So I guess I shouldn't be surprised. This just annoys me :-/

@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Mar 15, 2020

Yes bash 4.4 produces source.

Ah.. OK, Bash sets source when source is made in a function scope, and unset FUNCNAME when source is made in a top-level context. Bash consistently produces the same result for $FUNCNAME and ${FUNCNAME[0]} in the same context. The reason why you see the inconsistency is that $FUNCNAME and ${FUNCNAME[0]} are evaluated in different contexts in the test:

$ bash -c '. test1.sh; f() { . test1.sh; }; f'
$FUNCNAME = '' (unset)
${FUNCNAME[0]} = '' (unset)
declare -a FUNCNAME
$FUNCNAME = 'source' (set)
${FUNCNAME[0]} = 'source' (set)
declare -a FUNCNAME=([0]="source" [1]="f")

I remembered it just now, but ble.sh code actually utilizes this difference here to discriminate whether ble.sh is sourced in a function scope or not. It is even documented (see boldfaced sentence below).

From Bash Variables (Bash Reference Manual) - FUNCNAME

FUNCNAME

An array variable containing the names of all shell functions currently in the execution call stack. The element with index 0 is the name of any currently-executing shell function. The bottom-most element (the one with the highest index) is "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.

@akinomyoga akinomyoga deleted the allow-scalar-form-of-bash_lineno-and-funcname branch March 15, 2020 04:25
@andychu
Copy link
Contributor

andychu commented Mar 15, 2020

Ah OK thanks. I see that it's documented but I don't see the rationale for the behavior!

I think there could be a different way to test if it's sourced as function scope... I have seen that issue before but I don't recall exactly where.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants