From 125adb4bcd29df7b74d5e5aa34c527c2f68826c6 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Wed, 24 Feb 2016 03:14:25 -0500 Subject: research: New stack management test script --- diff --git a/research/research5.sh b/research/research5.sh new file mode 100644 index 0000000..49d8548 --- /dev/null +++ b/research/research5.sh @@ -0,0 +1,308 @@ +set -e +__ESC="$(printf '\033.')"; __ESC="${__ESC%.}" + __RS="$(printf '\036.')"; __RS="${__RS%.}" + __US="$(printf '\037.')"; __US="${__US%.}" +__sp=0 +__fn_name= +__fn_tu= +__fn_vars= +__fn_var_vals= +__fn= +__prev_tu= +__prev_vars= +__var= +__val= +__fn_frame= + +__sp_inc() +{ + __sp=$((${__sp} + 1)) +} + +__sp_dec() +{ + __sp=$((${__sp} - 1)) +} + +__frame_set() +{ + eval "__frame_${__sp}_name=\${__fn_name}" + eval "__frame_${__sp}_tu=\${__fn_tu}" + eval "__frame_${__sp}_vars=\${__fn_vars}" + eval "__frame_${__sp}_var_vals=\${__fn_var_vals}" +} + +__frame_get() +{ + eval "__fn_name=\${__frame_${__sp}_name}" + eval "__fn_tu=\${__frame_${__sp}_tu}" + eval "__fn_vars=\${__frame_${__sp}_vars}" + eval "__fn_var_vals=\${__frame_${__sp}_var_vals}" +} + +__fn_ctxsw() +{ + unset IFS + case "${__prev_tu}" in + ${__fn_tu});; + ?*) + # Unset static variables and functions from previous TU. + eval "unset \${__${__prev_tu}_static_vars}" + for __fn in $(eval printf '%s' \ + "\"\${__${__prev_tu}_static_fns}\""); do + unset -f "${__fn%:*}" + done + ;; esac + case "${__fn_tu}" in + ${__prev_tu});; + ?*) + # Set static variables and function for the current TU. + eval "$(eval printf '%s' "\"$(eval printf '%s' \ + "'\${__${__fn_tu}_static_var_vals}'")\"")" + for __fn in $(eval printf '%s' \ + "\"\${__${__fn_tu}_static_fns}\""); do + eval "${__fn%:*}() { ${__fn#*:}; }" + done + ;; esac + unset ${__prev_vars} + eval "${__fn_var_vals}" +} + +__fn_update_vars() +{ + for __var in ${__fn_vars}; do + __val="$(eval "printf '%s' \"\${${__var}}\"" | \ + sed "s|'|'\\\\''|g;")" + __fn_var_vals="${__fn_var_vals} ${__var}='${__val}'" + done +} + +__fn_start() +{ + # Old state. + __prev_tu="${__fn_tu}" + __prev_vars="${__fn_vars}" + + # Update local vars in stack. + __fn_update_vars + __frame_set + + # Set stack pointer. + __sp_inc + + # New state. + __fn_name="${2}" + __fn_tu="${1}" + __fn_vars= + __fn_var_vals= + __frame_set + + # Switch. + __fn_ctxsw +} + +__fn_end() +{ + # Old state. + __prev_tu="${__fn_tu}" + __prev_vars="${__fn_vars}" + + # Set stack pointer. + __sp_dec + + # New state. + __frame_get + + # Switch. + __fn_ctxsw +} + +__tu_end() +{ + # Save TU static vars. + for __var in $(eval "printf '%s' \"\${__${__tu}_static_vars}\""); do + __val="$(eval "printf '%s' \"\${${__var}}\"" | \ + sed "s|'|'\\\\''|g")" + eval "__${__tu}_static_var_vals=\"\${__${__tu}_static_var_vals}\ + ${__var}='\${__val}'\"" + unset ${__var} + done + + __tu='' +} + +__stack_trace() +{ + __fn_frame=0 + while [ ${__fn_frame} -le ${__sp} ]; do + eval "printf '%s\n' \"\${__frame_${__fn_frame}_name}\"" + __fn_frame=$((${__fn_frame} + 1)) + done +} + +__local() +{ + for __var in "${@}"; do + case "${__var}" in + *=*) + __val="${__var#*=}" + __var="${__var%%=*}" + ;; + *) + __val='' + ;; + esac + case "${__var}" in [!A-Za-z_]* | *[!0-9A-Za-z_]*) + printf 'Syntax error: %s %s\n' \ + 'illegal static variable name:' "${__var}" >&2 + exit 1 + ;; esac + eval "${__var}=\${__val}" + __fn_vars="${__fn_vars} ${__var}" + done +} + +static() +{ + case "${__tu}" in '') + printf 'Error: Cannot declare static variables in functions' >&2 + exit 1 + ;; esac + for __var in "${@}"; do + case "${__var}" in + *=*) + __val="${__var#*=}" + __var="${__var%%=*}" + ;; + *) + __val='' + ;; + esac + case "${__var}" in [!A-Za-z_]* | *[!0-9A-Za-z_]*) + printf 'Syntax error: %s %s\n' \ + 'illegal static variable name:' "${__var}" >&2 + exit 1 + ;; esac + eval "${__var}=\${__val}" + eval "__${__tu}_static_vars=\"\${__${__tu}_static_vars} \ + ${__var}\"" + done +} + +EOF(){ :; } + +#: <<'EOF' +################################################################################ +# Stack trace test +################################################################################ +__tu=tu0 +__tu0_static_vars= +__tu0_static_var_vals= +__tu0_static_fns= + +a(){ __fn_start tu0 a; b; __fn_end; } +b(){ __fn_start tu0 b; c; __fn_end; } +c(){ __fn_start tu0 c; printf 'Stack trace:\n'; + printf ' * %s()\n' $(__stack_trace); __fn_end; } +a + +__tu_end +EOF + +#: <<'EOF' +################################################################################ +# TU 0 +################################################################################ +__tu=tu0 +__tu0_static_vars= +__tu0_static_var_vals= +__tu0_static_fns= + +static v=1 + +foo() +{ + __fn_start tu0 foo + + echo "v (should be 1): $v" + + __fn_end +} + +__tu_end + +################################################################################ +# TU 1 +################################################################################ +__tu=tu1 +__tu1_static_vars= +__tu1_static_var_vals= +__tu1_static_fns= + +bar() +{ + __fn_start tu1 bar + + echo "v (should not be 1): $v" + foo + echo "v (should not be 1): $v" + + __fn_end +} + +__tu_end + +bar +EOF + +#: <<'EOF' +################################################################################ +# TU 0 +################################################################################ +__tu=tu0 +__tu0_static_vars= +__tu0_static_var_vals= +__tu0_static_fns= + +a() +{ + __fn_start tu0 a + __local v=1 + echo "v (should be 1): $v" + b + echo "v (should be 1): $v" + __fn_end +} + +b() +{ + __fn_start tu0 b + echo "v (should be empty): $v" + __fn_end +} + +__tu_end + +a +EOF + +: <<'EOF' +################################################################################ +# TU 0 +################################################################################ +__tu=tu0 +__tu0_static_vars= +__tu0_static_var_vals= +__tu0_static_fns= + +a() +{ + __fn_start tu0 a + static v=1 + __fn_end +} + +__tu_end + +a +EOF -- cgit v0.9.1