| #!/usr/bin/wish |
| |
| # This file provides many valuable stack inquiry procedures like get_file_proc_names, get_stack_var, etc.. |
| |
| my_source [list print.tcl] |
| |
| |
| proc get_file_proc_names { file_path { name_regex "" } } { |
| |
| # Get all proc names from the file indicated by file_path and return them as a list. |
| |
| # Description of argument(s): |
| # file_path The path to the file whose proc names are to be retrieved. |
| # name_regex A regular expression to be used to narrow the result to just the desired |
| # procs. |
| |
| # The first sed command serves to eliminate curly braces from the target file. They are a distraction to |
| # what we are trying to do. |
| # TCL proc lines begin with... |
| # - Zero or more spaces... |
| # - The "proc" keyword... |
| # - One or more spaces... |
| set proc_regex "^\[ \]*proc\[ \]+" |
| set cmd_buf "sed -re 's/\[\\\{\\\}]//g' $file_path | egrep" |
| append cmd_buf " '${proc_regex}${name_regex}[ ]' | sed -re" |
| append cmd_buf " 's/${proc_regex}(\[^ \]+).*/\\1/g'" |
| return [split [eval exec bash -c {$cmd_buf}] "\n"] |
| |
| } |
| |
| |
| proc get_stack_var { var_name { default {} } { init_stack_ix 1 } } { |
| |
| # Starting with the caller's stack level, search upward in the call stack, for a variable named |
| # "${var_name}" and return its value. If the variable cannot be found, return ${default}. |
| |
| # Description of argument(s): |
| # var_name The name of the variable be searched for. |
| # default The value to return if the the variable cannot be found. |
| |
| for {set stack_ix $init_stack_ix} {$stack_ix <= [info level]} \ |
| {incr stack_ix} { |
| upvar $stack_ix $var_name var_ref |
| if { [info exists var_ref] } { return $var_ref } |
| } |
| |
| return $default |
| |
| } |
| |
| |
| proc get_stack_var_level { var_name { init_stack_ix 1 } { fail_on_err 1 } } { |
| |
| # Starting with the caller's stack level, search upward in the call stack, for a variable named |
| # "${var_name}" and return its associated stack level. If the variable cannot be found, return -1. |
| |
| # Description of argument(s): |
| # var_name The name of the variable be searched for. |
| # init_stack_ix The level of the stack where the search should start. The default is 1 |
| # which is the caller's stack level. |
| # fail_on_err Indicates that if the variable cannot be found on the stack, this proc |
| # should write to stderr and exit with a non-zero return code. |
| |
| for {set stack_ix $init_stack_ix} {$stack_ix <= [info level]} \ |
| {incr stack_ix} { |
| upvar $stack_ix $var_name var_ref |
| set stack_level [expr $stack_ix - $init_stack_ix] |
| if { [info exists var_ref] } { return $stack_level } |
| } |
| |
| if { $fail_on_err } { |
| append message "Programmer error - Couldn't find variable \"${var_name}\"" |
| append message " on the stack." |
| print_error_report $message |
| exit 1 |
| } |
| |
| return -1 |
| |
| } |
| |
| |
| proc get_stack_proc_name { { level -1 } { include_args 0 } } { |
| |
| # Get the name of the procedure at the indicated call stack level and return it. |
| |
| # Description of argument(s): |
| # level The call stack level: 0 would mean this procedure's level (i.e. |
| # get_stack_proc_name's level), -1 would indicate the caller's level, etc. |
| # include_args Indicates whether proc arg values should be included in the result. |
| |
| # Set default. |
| set_var_default level -1 |
| |
| if { $include_args } { |
| set cmd_buf "set proc_name \[info level $level\]" |
| } else { |
| set cmd_buf "set proc_name \[lindex \[info level $level\] 0\]" |
| } |
| |
| if { [ catch $cmd_buf result ] } { |
| # The command failed most likely due to being called from "main". |
| set proc_name "main" |
| } |
| |
| return $proc_name |
| |
| } |
| |
| |
| proc get_call_stack { { stack_top_ix -1 } { include_args 0 } } { |
| |
| # Return the call stack as a list of procedure names. |
| |
| # Example: |
| # set call_stack [get_call_stack 0] |
| # call_stack: get_call_stack calc_wrap_stack_ix_adjust sprint_var sprint_vars print_vars |
| |
| # Description of argument(s): |
| # stack_top_ix The index to the bottom of the stack to be returned. 0 means include the |
| # entire stack. 1 means include the entire stack with the exception of |
| # this procedure itself, etc. |
| # include_args Indicates whether proc args should be included in the result. |
| |
| set_var_default stack_top_ix -1 |
| |
| # Get the current stack size. |
| set stack_size [info level] |
| # Calculate stack_bottom_ix. Example: if stack_size is 5, stack_bottom_ix is -4. |
| set stack_bottom_ix [expr 1 - $stack_size] |
| for {set stack_ix $stack_top_ix} {$stack_ix >= $stack_bottom_ix} \ |
| {incr stack_ix -1} { |
| if { $include_args } { |
| set proc_name [info level $stack_ix] |
| } else { |
| set proc_name [lindex [info level $stack_ix] 0] |
| } |
| lappend call_stack $proc_name |
| } |
| |
| return $call_stack |
| |
| } |