import subprocess

SCRIPTS = [
    # different ways to exit
    'trap "echo EXIT" EXIT',
    'trap "echo EXIT" EXIT; exit 1',
    'set -e; trap "echo EXIT" EXIT; false',
    'trap "echo EXIT" EXIT; kill -INT $$',
    'trap "echo EXIT" EXIT; kill -TERM $$',
    'trap "echo EXIT" EXIT; kill -KILL $$',

    # modify exit code during cleanup
    'trap "echo EXIT; true" EXIT; exit 1',
    'trap "echo EXIT; exit 2" EXIT; exit 1',

    # proposed solution 1
    'trap "echo EXIT" EXIT; trap "trap - INT; trap - EXIT; echo INT; kill -INT $$" INT; kill -INT $$',
    'trap "echo EXIT" EXIT; trap "trap - TERM; trap - EXIT; echo TERM; kill -TERM $$" TERM; kill -TERM $$',

    # proposed solution 2
    'trap "echo EXIT" EXIT; trap "exit 130" INT TERM; kill -INT $$',
    'trap "echo EXIT" EXIT; trap "exit 130" INT TERM; kill -TERM $$',

    # subshell
    'trap "echo EXIT" EXIT; (trap "echo SUBSHELL EXIT" EXIT)',

    # functions
    'trap "echo EXIT" EXIT; foo() { trap "echo INNER EXIT" EXIT; }; foo',
    'trap "echo EXIT" EXIT; foo() { trap "echo RETURN" RETURN; }; foo',
]

for script in SCRIPTS:
    results = {}
    for shell in ['dash', 'bash', 'zsh', 'busybox sh']:
        proc = subprocess.run(
            shell.split(), input=script, capture_output=True, encoding='utf-8'
        )
        key = f'[{proc.returncode}] {proc.stdout!r}'
        results.setdefault(key, [])
        results[key].append(shell)
    print(script)
    for stdout, shells in results.items():
        print(f'{stdout} ({", ".join(shells)})')
    print()
