#compdef valgrind -value-,VALGRIND_OPTS,-default- local curcontext="$curcontext" state line local -a cmd common common_{mem_null,read_varinfo} local -a args args_{addrcheck,drd,memcheck,cachegrind,helgrind,lackey,massif,none} cmd=( '1: : _command_names -e' '*::args :_normal' ) if [[ $service = *_OPTS* ]]; then compset -q words=( fake "$words[@]" ) (( CURRENT++ )) cmd=() fi common=( '--alignment=-[set minimum alignment of allocations]:number' ) common_read_varinfo=( '--read-var-info=-[read DWARF3 debug info]:enable:(yes no)' ) common_mem_null=( '--xml=-[output everything in XML]:enable:(yes no)' '--xml-user-comment=-[copy specified string verbatim to XML output]:string' ) args_addrcheck=( $common $common_mem_null '--partial-loads-ok=-:enable:(yes no)' '--freelist-vol=-[volume of freed blocks queue]:blocks' '--leak-check=-[search for memory leaks at exit]:enable:(yes no)' '--leak-resolution=-[how much bt merging in leak check]:level:(low med high)' '--show-reachable=-[show reachable blocks in leak check]:enable:(yes no)' '--workaround-gcc296-bugs=-:enable:(yes no)' ) args_drd=( '--check-stack-var=-[detect data races on stack variables]:enable [no]:(yes no)' '--exclusive-threshold=-[print an error if any mutex or writer lock is held longer than specified time]:time (ms)' '--first-race-only=-[report only the first detected data race]:enable [no]:(yes no)' '--free-is-write=-[report races between accessing memory and freeing memory]:enable [no]:(yes no)' '--join-list-vol=-[specify how many joined threads to retain memory access information for]:number of threads [10]' '--report-signal-unlocked=-[report calls to pthread_cond_signal etc where the mutex is not locked]:enable [yes]:(yes no)' '--segment-merging=-[control segment merging]:enable [yes]:(yes no)' '--segment-merging-interval=-[perform segment merging only after the specified number of new segments have been created]:number of segments [10]' '--shared-threshold=-[print an error if a reader lock is held longer than the specified time]:time (ms)' '--show-confl-seg=-[show conflicting segments in race reports]:enable [yes]:(yes no)' '--show-stack-usage=-[print stack usage at thread exit time]:enable [no]:(yes no)' '--ignore-thread-creation=-[control whether all activities during thread creation should be ignored]:enable [no]:(yes no)' '*--ptrace-addr=-[trace all load and store activity for specified address even after free]:address' '*--trace-addr=-[trace all load and store activity for specified address]:address' '--trace-alloc=-[trace all memory allocations and deallocations]:enable [no]:(yes no)' '--trace-barrier=-[trace all barrier activity]:enable [no]:(yes no)' '--trace-cond=-[trace all condition variable activity]:enable [no]:(yes no)' '--trace-fork-join=-[trace all thread creation and all thread termination events]:enable [no]:(yes no)' '--trace-hb=-[trace execution of the ANNOTATE_HAPPENS_BEFORE(), ANNOTATE_HAPPENS_AFTER() and ANNOTATE_HAPPENS_DONE() client requests]:enable [no]:(yes no)' '--trace-mutex=-[trace all mutex activity]:enable [no]:(yes no)' '--trace-rwlock=-[trace all reader-writer lock activity]:enable [no]:(yes no)' '--trace-semaphore=-[trace all semaphore activity]:enable [no]:(yes no)' ) args_memcheck=( $args_addrcheck $common_read_varinfo ) args_cachegrind=( '--I1=-[set I1 cache manually]:size,assoc,line_size' '--D1=-[set D1 cache manually]:size,assoc,line_size' '--L2=-[set L2 cache manually]:size,assoc,line_size' ) args_helgrind=( $common $common_read_varinfo '--free-is-write=-[treat heap frees as writes]:enable [no]:(yes no)' '--track-lockorders=-[show lock ordering errors]:enable [yes]:(no yes)' '--history-level=-[specify amount of history to show for data races]:level [full]:(( full\:show\ both\ stack\ traces\ for\ a\ data\ race\ \(slow\) approx\:full\ trace\ for\ one\ thread,\ approx\ for\ the\ other\ \(faster\) none\:only\ show\ trace\ for\ one\ thread\ in\ a\ race\ \(fastest\) ))' '--conflict-cache-size=-[specify size of full history cache]:size [2000000]' '--check-stack-refs=-[race-check reads and writes on the main stack and thread stacks]:enable [yes]:(no yes)' '--ignore-thread-creation=-[ignore activities during thread creation]:enable [no]:(yes no)' ) args_lackey=( '--fnname=-[count calls to specified name]:name' '--detailed-counts=-[count loads, stores and alu ops]:enable:(yes no)' ) args_massif=( $common '--heap=-[profile heap blocks]:enable:(yes no)' '--heap-admin=-[specify average admin bytes per heap block]:bytes' '--stacks=-[enable profile stacks]:enable:(yes no)' '--depth=-[depth of contexts]:depth' '--alloc-fn=-[specify alloc function]:function' '--format=-[specify format of textual output]:format:(text html)' ) args_none=( $common_mem_null ) args="args_${${words[(r)--tool=*]#*=}:-memcheck}" _arguments -C ${(P)args} $cmd \ '(--version)--tool=-[specify valgrind tool]:valgrind tool:->tools' \ '(-h --help)'{-h,--help}'[show help information]' \ '--help-debug[show help info including debugging options]' \ '(-)--version[show version]' \ '(-q --quiet)'{-q,--quiet}'[run silently; only print error msgs]' \ '(-v --verbose)'{-v,--verbose}'[be more verbose]' \ '--trace-children=-[valgrind-ise child processes]:enable:(yes no)' \ '--track-fds=-[track open file descriptors]:enable:(yes no)' \ '--time-stamp=-[add timestamps to log messages]:enable:(yes no)' \ '--log-fd=-[log messages to specified file descriptor]:file descriptor:_file_descriptors' \ '--log-file=-[log messages to specified file with pid appended]:file:_files' \ '--log-file-exactly=-[log messages to specified file]:file:_files' \ '--log-file-qualifier=-[log messages to filename given by specified environment variable]:variable:_parameters -g "*scalar*"' \ '--log-socket=-[log messages to socket]:ipaddr\:port' \ '--run-libc-freeres=-[free up glibc memory at exit]:enable:(yes no)' \ '--sim-hints=-[enable hint]:hint:(lax-ioctls enable-outer)' \ '--show-emwarns=-[show warnings about emulation limits]:enable:(yes no)' \ '--kernel-variant=-[handle non-standard kernel variants]:kernel variant:_values -s , kernel\ variant bproc' \ '--demangle=-[automatically demangle C++ names]:enable:(yes no)' \ '--num-callers=-[specify no of callers to show in stack traces]:number' \ '--error-limit=-[stop showing new errors if too many]:enable:(yes no)' \ '--show-below-main=-[continue stack traces below main()]:enable:(yes no)' \ '--suppressions=-[suppress errors described in specified file]:file:_files' \ '--gen-suppressions=-[print suppressions for errors detected]:enable:(yes no)' \ '--db-attach=-[start debugger when errors detected]:enable:(yes no)' \ '--db-command=-[specify command to start debugger]: : _command_names -e' \ '--input-fd=-[specify file descriptor for input]:file descriptor:_file_descriptors' \ '--max-stackframe=-[assume stack switch for SP changes larger than specified number of bytes]:bytes' \ && return typeset -a tools if [[ -n "$state" ]]; then # `valgrind --tool=` no longer works. # The method below is even more hackish, but the only one I could find. # Basically uses debug output to find out the directory where the tools are # present and lists all executables in that directory. # Hope the program provides a neater interface some day! () { setopt localoptions histsubstpattern tools=( ${${${(M)${(f)"$(_call_program tools valgrind --tool=something -d 2>&1)"}:#*launcher launching *something*}##*launcher launching }%%something*}*~*.*(*:t:s/-*//) ) typeset -U tools } _wanted tools exl 'valgrind tool' compadd $tools && return fi return 1