tag:blogger.com,1999:blog-50287003776132940322024-03-13T17:31:26.173-04:00toolchainguruTools, tips and tricks for programmers (especially embedded Linux developers)Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-5028700377613294032.post-29840553770069325222013-10-31T00:27:00.002-04:002013-10-31T00:27:49.259-04:00Licensing...Unless otherwise specified, any code I've written within this blog can be used (at your own risk!) however you'd like; If you're going to re-publish any (derivatives) of it though, I would appreciate a link back to the blog, and maybe a heads-up comment over here as well so I can see how you're making use of it!<div>
<br /></div>
<div>
Thanks,</div>
<div>
<br /></div>
<div>
Jason</div>
Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.com1tag:blogger.com,1999:blog-5028700377613294032.post-52838468258070022802011-03-02T11:50:00.002-05:002011-03-02T12:14:50.601-05:00C Calltrees in Bash, revisitedI've revised my "C Calltrees in Bash" tool, primarily to make it more efficient at discovering the call associations between many functions. ("call graph" (i.e. "relate N functions") used to be based on an O(N^2) application of "call_tree" (i.e. "relate 2 functions"); I realized there was a simple way to make "call_graph" O(N) and eliminate the need for "call_tree" at the same time.)<br /><br />Passing args vs. piping to the shell functions is handled more consistently now.<br /><br />There's a new "upndown" wrapper to generate a graph of all of a function's callers AND callees...<br /><br />And there's an experimental method for generating a subgraph of all C functions that refer to a particular variable. (Not particularly useful for a variable with a name like "i".) For a certain class of globals, it might be a <span style="font-style: italic;">little</span> useful.<br /><br />Here 'tis:<br /><pre><br /><span style="font-style: italic; color: rgb(128, 128, 128);">#!/bin/bash</span><br /><br /><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> calltree.sh</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);">#use cscope to build reference files (./cscope.out by default, use set_graphdb to override name or location)</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">set_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">export</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">GRAPHDB=$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">unset_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">unset</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">GRAPHDB</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">build_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope -bkRu </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> Created </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:-cscope.out}</span><span style="color: rgb(0, 0, 0);">...; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># cscope queries</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">lsyms()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L0 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -v </span><span style="color: rgb(221, 0, 0);">"<global>"</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"="</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">fdefine()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L1 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">callees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L2 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">callers()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L3 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># show which functions refer to a set of symbols</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">filter_syms()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">cscope_line</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> lsyms </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># given a set of function names, find out how they're related</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">filter_edges()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">cscope_line</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> fdefine </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">\t[href=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*fdefine*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> callees </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(221, 0, 0);">-></span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">\t[label=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*callee*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> callers </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">-></span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(221, 0, 0);">\t[label=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*caller*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># dump args one-per-line</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">largs()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">for</span><span style="color: rgb(0, 0, 0);"> a; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$a</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">toargs()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">symbol</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">symbol</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"%s "</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$symbol</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># present list of symbols to filter_syms properly</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">refs()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/refs.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(largs $@)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> filter_syms </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># present list of function names to filter_edges properly</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">edges()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/edges.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(largs $@)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> filter_edges </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># append unknown symbol names out of lines of cscope output</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">filter_cscope_lines()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">cscope_line</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-/dev/null}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);"> </span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># given a set of function names piped in, help spit out all their callers or callees that aren't already in the set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">descend()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">symbol</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">symbol</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$symbol</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> filter_cscope_lines </span><span style="color: rgb(0, 128, 0);">$2</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># discover functions upstream of initial set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callers()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/all_callers.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(largs $@)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> descend callers </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">>></span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># discover functions downstream of initial set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/all_callees.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(largs $@)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> descend callees </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">>></span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># all the ways to get from (a,b,...z) to (a,b,...z), i.e. intersect all_callers and all_callees of initial set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">call_graph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/subgraph.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">args=</span><span style="color: rgb(0, 0, 0);">/tmp/subgraph_args.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(largs $@)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$args</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$args</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> all_callers </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">comm</span><span style="color: rgb(0, 0, 0);"> -12 </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$args</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> all_callees </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$args</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># all functions downstream of callers of argument</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callerees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> callers </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> filter_cscope_lines </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> all_callees; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># odd experimental set of calls that might help spot potential memory leaks</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">call_leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/graph_filter.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> all_callerees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">comm</span><span style="color: rgb(0, 0, 0);"> -2 </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="color: rgb(0, 0, 0);">all_callers </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># wrap dot-format node and edge info with dot-format whole-graph description</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">graph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"digraph iftree {\ngraph [rankdir=LR, ratio=compress, concentrate=true];\nnode [shape=record, style=filled]\nedge [color="</span><span style="color: rgb(0, 0, 0);">navy</span><span style="color: rgb(221, 0, 0);">"];\n"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u; </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"}\n"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># filter out unwanted (as specified in “~/calltree.deny”) and/or unnecessary edges</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">graph_filter()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/graph_filter.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> fdefine </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -vf ~/calltree.deny </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cut</span><span style="color: rgb(0, 0, 0);"> -f1,3</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># how to invoke zgrviewer as a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">zgrviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> ~/bin/zgrviewer -Pdot </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># how to invoke xfig as a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">figviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> xfig </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="color: rgb(0, 0, 0);">dot -Tfig </span><span style="color: rgb(0, 128, 0);">$@</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># how to create and view a png image</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">pngviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tpng </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> -o /tmp/ct.png </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><span style="color: rgb(0, 0, 0);"> gqview -t /tmp/ct.png; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># specify a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">ctviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> pngviewer </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># add color to specified nodes</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">colornodes()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">for</span><span style="color: rgb(0, 0, 0);"> x </span><span style="font-weight: bold; color: rgb(0, 0, 0);">in</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">$x</span><span style="color: rgb(221, 0, 0);"> [color=red]"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);">;</span><span style="font-weight: bold; color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># generate dot files</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_upstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> all_callers </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${2:-caller}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_downstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> all_callees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${2:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_upndown()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">all_callers </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; all_callees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="font-weight: bold; color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${2:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_relate()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> call_graph </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter callee </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> call_leaks </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${3:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># generate dot files and invoke ctviewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">upstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _upstream </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">downstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _downstream </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">upndown()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _upndown </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">relate()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _relate </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _leaks </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># dot file conversions</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2png()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -s36 -Tpng -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2jpg()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tjpg -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2html()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tpng -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.png -Tcmapx -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.map; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"<IMG SRC="</span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.png</span><span style="color: rgb(221, 0, 0);">" USEMAP="</span><span style="color: rgb(0, 0, 0);">#iftree</span><span style="color: rgb(221, 0, 0);">" />"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.map</span><span style="font-weight: bold; color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.html; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /></pre>(Note to self: Code formatted via kdevelop, "File" -> "export to html")Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.com4tag:blogger.com,1999:blog-5028700377613294032.post-57322790480049978032010-09-30T11:46:00.005-04:002010-09-30T14:43:32.379-04:00RAII in C, too<span>I've been using a macro to encapsulate exactly what is going on in this </span><a href="http://vilimpoc.org/research/raii-in-c/">"RAII in C"</a><span> link, which abstracts out the more boilerplate aspects of writing code like this and leaving behind something far more clean and direct:</span><br /><br />(Lazy, i.e. non-compiling, near-C code...)<br /><pre><br />// lispy macros<br />#define CAR(first,rest...) first<br />#define CDR(first,rest...) rest<br /><br />// TRY macro easing the implementation of the RAII paradigm in C<br />// This implementation just scratches the surface...<br />#define TRY(_cond,_status,_exitpoint,_msg...)<br />{<br /> if (TRY_trace) printf(#_cond ": " CAR(_msg) "\n",CDR(_msg));<br /> if (_cond)<br /> {<br /> status=(_status);<br /> printf("Failed" CAR(_msg) ", status=%d\n",CDR(_msg),status);<br /> goto _exitpoint;<br /> }<br />}<br /></pre><br />where:<br /><br />"cond" is any expression that returns anything that can be interpreted as a boolean (i.e. "if (cond)..."),<br />"status" identifies the error if "cond" evaluates to non-zero/true,<br />"exitpoint" refers to a code label which will be goto'ed if "cond" is non-zero/true, and<br />"msg" documents what "cond" is supposed to do.<br /><br />Example usage:<br /><pre><br />int foo(int bufsize,char *filename)<br />{<br /> int status=0;<br /> char *buf;<br /> FILE *file;<br /><br /> TRY(!(buf=malloc(bufsize)), -1, done, "allocating %d byte buf",bufsize);<br /> TRY(!(file=fopen(filename,"r")), -1, deallocate_buf, "opening file %s",filename);<br /> TRY(status=bar(buf,file), status, close_file, "bar'ing buf[%d], file %s",bufsize,filename);<br /><br /> // could "goto done" here if not releasing resources immediately.<br /><br />close_file:<br /> fclose(file);<br />deallocate_buf:<br /> free(buf);<br />done:<br /> return status;<br />}<br /></pre><br />Niceties:<br />* RAII-like* paradigm, in a very compact and concise form<br />* Focus on what's important/unique, forget about boilerplate<br />* Every important line's purpose is auto-documented, as a side-effect of design<br /><br />But most importantly, every important line of code is wrapped in a macro(!). An entire application can be altered, instrumented, re-interpreted, or otherwise arbitrarily processed simply by changing the definition of TRY. Trivial examples would be changing how the messages are printed/logged, or only "tracing" TRY calls to a certain depth. A less-trivial example would be implementing a debugging feature that allowed you single-step through TRY-instrumented code on-demand.<br /><br />*I've never called this RAII myself, although it does make dealing with resource allocation/release <span style="font-style: italic;">consistently</span> very easy. It's more of a general control-flow method I use; a controlled way of using goto in a way that makes nested, vulnerable-to-failure resource allocations easy to control and clean up.Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.com0tag:blogger.com,1999:blog-5028700377613294032.post-49542989201274440802008-07-08T00:09:00.010-04:002008-07-11T09:58:03.143-04:00Bash: C Call Trees and Graphs<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_khWIaPE0rTU/SHdl7jzmc0I/AAAAAAAAAAg/GBzlLfR74OE/s1600-h/graph.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_khWIaPE0rTU/SHdl7jzmc0I/AAAAAAAAAAg/GBzlLfR74OE/s400/graph.png" alt="" id="BLOGGER_PHOTO_ID_5221754366857737026" border="0" /></a><br />One day I had a need. (Or was it a desire? I can't remember off the top of my head.) My need was to find all the pathways through a large set of code between one function call and another, i.e. how many ways can this code get from a() to b()?<br /><br />I googled around for a while and found some call-graphing tools out there, but none did exactly what I wanted, so I wrote my own.<br /><br />As with many of the other similar call-graphing tools, a lot of the grunt work can be performed with existing tools, such as <a href="http://cscope.sourceforge.net/">cscope</a> for determining the callers and callees of functions, and <a href="http://www.graphviz.org/">graphviz</a> for generating graph layouts and preparing them for display. (I recently heard of <a href="http://www.gson.org/egypt/egypt.html">Egypt</a> which uses gcc to generate an easier-to-parse intermediate representation of code, and the ubiquitous graphviz for the back-end visualization... While AFAIK it doesn't cull the graph down to a()->b(), its use of gcc is probably much quicker than my use of cscope. I will probably convert my implementation from cscope->bash->graphviz to gcc->X->graphviz at some point in the future, while I have an "X" in mind, that's a story for another entry...)<br /><br />My solution, whipped out over a weekend or so, simply teases information out of a cscope database and presents the results to graphviz for display using a dozen or so fairly simple bash functions. I thought it would take a lot more work and cleverness to generate the results I wanted, but the solution's brute force nature leaves some performance on the table, which I intend to remedy when I have time.<br /><br />My solution hammers on the filesystem with a lot of pipes and temporary files to shuffle intermediate results around. The most interesting part about it is probably the interplay between all_callees(), descend(), and filter_cscope_lines(). These combine to find out all the functions that are "downstream" of an initial set, i.e. all the functions the initial set calls, and the functions these call, and so on all the way down to the tips of this tree. (There is an equivalent mechanism for finding "upstream" functions.) It does this by:<br /><ol><li>Stashing the initial function(s) (specified as an argument or piped in) in a temporary "working set" file,</li><li>Iterating through each function name in the working set, calling cscope on each to find out what functions it calls,</li><li>Appending newly discovered downstream functions (that don't already exist in the working set) to the working set.</li></ol>As descend iterates through the working set, as long as new downstream functions are being found, they get appended to the working set where descend will eventually reach them. Descend will know when it's found all the downstream tips when it simply reaches the end of the working set.<br /><br />On to usage:<br /><br />First, you need to build a cscope database. A simple bash wrapper ("build_graphdb") for cscope takes care of most situations; simply running it in a directory will trigger cscope to parse source files it's natively aware of in that directory and it's subdirectories and build a database there named "cscope.out". If you want to instrument code in a read-only directory or need to change the name for any other reason, simply pick a new name via "set_graphdb <name>", and the calltree code will use that instead.<br /><br />Once a cscope database has been built, you can show:<br /></name><ol><li>all functions "downstream" of some function X, i.e. a tree of all functions called by X, ("downstream")<br /></li><li>all functions "upstream" of some function X, i.e. all the ways X could be called, ("upstream")<br /></li><li>all code paths that lead from function X to function Y. ("subgraph")</li><li>all code paths between an arbitrary set of functions A, B, C, [...] Z ("relate")<br /></li></ol>The functions themselves:<br /><blockquote>These produce raw dot-format files:<br /><ol><li>_downstream</li><li>_upstream</li><li>_subgraph</li><li>_relate</li></ol></blockquote><blockquote>These will generate, process and (maybe) display the dot-format files using graphviz tools to interpret the dot<br />files, and generate various vector- or image-file formats that can be displayed by yet other programs (I prefer<br /><a href="http://zvtm.sourceforge.net/zgrviewer.html">zgrviewer,</a> but had issues last time I tried it, so have settled for <a href="http://www.xfig.org/">xfig</a> lately):<br /><ol><li>downstream</li><li>upstream</li><li>subgraph</li><li>relate</li></ol></blockquote>As I mentioned, these will generate and display graphs in xfig format. You can easily substitute your own "viewer" by creating a variation of the bash function "figviewer" below, and having the generic "ctviewer" (i.e. "calltree viewer") call your variation instead. One variant, "zgrviewer", is already set up to invoke zgrviewer, and "dot2jpg", "dot2png" and "dot2html" turn dot-format files into .jpg, .png and .html files respectively as well.<br /><br />Here's I generated the graph above:<br /><br />bash-3.2$ . calltree.sh<br />bash-3.2$ cd jli<br />bash-3.2$ build_graphdb<br />bash-3.2$ _subgraph jli_parse malloc > graph.dot<br />bash-3.2$ cat graph.dot | dot2png graph.png<br /><br />If I want to view the images directly rather than generate an image file of it, I would simply replace the last two lines with "subgraph jli_parse malloc" to invoke the viewer referenced by the "ctviewer" shell function.<br /><br />There are some extra vestigial features within the shell code that I was experimenting with:<br /><ul><li>A quick and dirty attempt to generate graphs that would highlight possible memory leaks, and</li><li>A more complex set of transformations that would generate an image file and an html link mask, the idea being to gain some more interactivity by letting me click on a graph in a browser and update it with something useful via a simple netcat-and-bash-based http server... I made a some good progress before abandoning the effort due to not really having a clear use/goal for the capability.</li></ul>So without further ado, here is the bash script which implements call tree/graphs: simply paste it into a bash shell to use it (you'll also need to install at least cscope and graphviz to generate dot files, and maybe xfig or zgrviewer to view the graphs.):<a><br /><br /></a><pre><a><br /><span style="font-style: italic; color: rgb(128, 128, 128);">#!/bin/bash</span><br /><br /><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> calltree.sh</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);">#use cscope to build reference files (./cscope.out by default, use set_graphdb to override name or location)</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">set_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">export</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">GRAPHDB=$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">unset_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">unset</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">GRAPHDB</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">build_graphdb()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope -bkRu </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> Created </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:-cscope.out}</span><span style="color: rgb(0, 0, 0);">...; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># cscope queries</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">fdefine()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L1 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">callees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L2 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">callers()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> cscope </span><span style="color: rgb(0, 128, 0);">${GRAPHDB:+-f $GRAPHDB}</span><span style="color: rgb(0, 0, 0);"> -L3 </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># given a set of function names, find out how they're related</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">filter_edges()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">cscope_line</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">sym</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> fdefine </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">\t[href=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*fdefine*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> callees </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(221, 0, 0);">-></span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">\t[label=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*callee*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> callers </span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-<(echo)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">&&</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(221, 0, 0);">-></span><span style="color: rgb(0, 128, 0);">$sym</span><span style="color: rgb(221, 0, 0);">\t[label=</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(0, 128, 0);">${cscope_line[0]}</span><span style="color: rgb(221, 0, 0);">:</span><span style="color: rgb(0, 128, 0);">${cscope_line[2]}</span><span style="color: rgb(128, 0, 0);">\"</span><span style="color: rgb(221, 0, 0);">]\t/*caller*/\n"</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># present list of function names to filter_edges properly</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">edges()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/edges.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> filter_edges </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># append unknown symbol names out of lines of cscope output</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">filter_cscope_lines()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">cscope_line</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">cscope_line</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -wq </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:-/dev/null}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${cscope_line[1]}</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);"> </span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># given a set of function names piped in, help spit out all their callers or callees that aren't already in the set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">descend()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">symbol</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">read</span><span style="color: rgb(0, 0, 0);"> -a </span><span style="color: rgb(0, 128, 0);">symbol</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$symbol</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> filter_cscope_lines </span><span style="color: rgb(0, 128, 0);">$2</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># discover functions upstream of initial set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callers()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/all_callers.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(echo $1)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> descend callers </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">>></span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># discover functions downstream of initial set</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/all_callees.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">${1:+<(echo $1)}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> descend callees </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><</span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">>></span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># intersection of all_callees(a) and all_callers(b)</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">call_tree()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/graph_filter.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> all_callees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">comm</span><span style="color: rgb(0, 0, 0);"> -12 </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="color: rgb(0, 0, 0);">all_callers </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><span style="color: rgb(0, 0, 0);">;</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># all functions downstream of callers of argument</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">all_callerees()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> callers </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> filter_cscope_lines </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> all_callees; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># odd experimental set of calls that might help spot potential memory leaks</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">call_leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/graph_filter.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> all_callerees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">comm</span><span style="color: rgb(0, 0, 0);"> -2 </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="color: rgb(0, 0, 0);">all_callers </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># all the ways to get from (a,b,...z) to (a,b,...z)</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">call_graph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">for</span><span style="color: rgb(0, 0, 0);"> a; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">for</span><span style="color: rgb(0, 0, 0);"> b; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">if</span><span style="font-weight: bold; color: rgb(136, 0, 136);"> [</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$a</span><span style="color: rgb(0, 0, 0);"> != </span><span style="color: rgb(0, 128, 0);">$b</span><span style="font-weight: bold; color: rgb(136, 0, 136);"> ]</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">then</span><span style="color: rgb(0, 0, 0);"> call_tree </span><span style="color: rgb(0, 128, 0);">$a</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$b</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">fi</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># wrap dot-format node and edge info with dot-format whole-graph description</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">graph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"digraph iftree {\ngraph [rankdir=LR, concentrate=true];\nnode [shape=record];\nedge [];\n"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">sort</span><span style="color: rgb(0, 0, 0);"> -u; </span><span style="font-weight: bold; color: rgb(136, 0, 136);">printf</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"}\n"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># filter out unwanted (as specified in “~/calltree.deny”) and/or unnecessary edges</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">graph_filter()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">local</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">tfile=</span><span style="color: rgb(0, 0, 0);">/tmp/graph_filter.</span><span style="color: rgb(0, 128, 0);">$RANDOM</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> fdefine </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">grep</span><span style="color: rgb(0, 0, 0);"> -vf ~/calltree.deny </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cut</span><span style="color: rgb(0, 0, 0);"> -f1,3</span><br /><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$tfile</span><br /><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># how to invoke zgrviewer as a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">zgrviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> ~/bin/zgrviewer -Pdot </span><span style="color: rgb(0, 128, 0);">$*</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># how to invoke xfig as a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">figviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> xfig </span><span style="font-weight: bold; color: rgb(34, 51, 136);"><(</span><span style="color: rgb(0, 0, 0);">dot -Tfig </span><span style="color: rgb(0, 128, 0);">$*</span><span style="font-weight: bold; color: rgb(34, 51, 136);">)</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># specify a viewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">ctviewer()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> figviewer </span><span style="color: rgb(0, 128, 0);">$*</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># add color to specified nodes</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">colornodes()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">for</span><span style="color: rgb(0, 0, 0);"> x </span><span style="font-weight: bold; color: rgb(0, 0, 0);">in</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">do</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"</span><span style="color: rgb(0, 128, 0);">$x</span><span style="color: rgb(221, 0, 0);"> [color=red]"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">done</span><span style="color: rgb(0, 0, 0);">;</span><span style="font-weight: bold; color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># generate dot files</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_upstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> all_callers </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${2:-caller}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_downstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> all_callees </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${2:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_subgraph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> call_tree </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${3:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_relate()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> call_graph </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter callee </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">_leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> call_leaks </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> edges </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph_filter </span><span style="color: rgb(0, 128, 0);">${3:-callee}</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> colornodes </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$2</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"> graph; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># generate dot files and invoke ctviewer</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">upstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _upstream </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">downstream()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _downstream </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">subgraph()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _subgraph </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">relate()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _relate </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">leaks()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> _leaks </span><span style="color: rgb(0, 128, 0);">$@</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> /tmp/tfile; ctviewer /tmp/tfile; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">rm</span><span style="color: rgb(0, 0, 0);"> -f /tmp/tfile; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><br /><span style="font-style: italic; color: rgb(128, 128, 128);"># dot file conversions</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2png()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tpng -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2jpg()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tjpg -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /><span style="font-weight: bold; color: rgb(255, 0, 255);">dot2html()</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 0);"> dot -Tpng -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.png -Tcmapx -o </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.map; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(136, 0, 136);">echo</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(221, 0, 0);">"<IMG SRC="</span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.png</span><span style="color: rgb(221, 0, 0);">" USEMAP="</span><span style="color: rgb(0, 0, 0);">#iftree</span><span style="color: rgb(221, 0, 0);">" />"</span><span style="color: rgb(0, 0, 0);">; </span><span style="font-weight: bold; color: rgb(204, 0, 204);">cat</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.map</span><span style="font-weight: bold; color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);"> </span><span style="font-weight: bold; color: rgb(34, 51, 136);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">$1</span><span style="color: rgb(0, 0, 0);">.html; </span><span style="font-weight: bold; color: rgb(0, 0, 0);">}</span><br /></a></pre>Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.com12tag:blogger.com,1999:blog-5028700377613294032.post-88703936030243890032008-06-20T15:09:00.010-04:002008-06-25T16:04:37.196-04:00Birthday... (and what good is a fifo?)<span style="font-size:100%;">I've been a professional software engineer for almost 20 years and a net junkie for even longer, and I've never blogged.<br /><br />Until now, that is.<br /><br />I plan on posting about my history and MO as a programmer, and about some of the things I've come up with along the way to make my job easier and/or more fun.<br /><br />Also, I'm a total geek who loves movies, tech gadgets, politics, cars, etc. etc. etc... I'm sure I'll fold thoughts and observations completely unrelated to programming here as well.<br /><br />Here's a little morsel to kick things off...<br /><dir><br /><pre><br />#include <stdio.h><br /><br />#define MAXCMDLINE 1024<br />int simple_cli(char *filename,int (*parser)(char *cmdline),int count)<br />{<br /> FILE *ifile = NULL;<br /> char cmdline[MAXCMDLINE];<br /> int status = 0;<br /><br /> for (cmdline[0]=0;count-- && !status && (ifile = fopen(filename,"r")) != NULL;fclose(ifile),cmdline[0]=0)<br /> while (fgets(cmdline,sizeof(cmdline)-1,ifile) && (!(status=parser(cmdline))));<br /><br /> return status;<br />}<br /><br />int parser(char *cmdline)<br />{<br /> printf(">> %s",cmdline);<br /> return 0;<br />}<br /><br />main(int argc, char *argv[])<br />{<br /> char *filename=argc>1?argv[1]:"/tmp/test.in";<br /> simple_cli(filename,parser,1);<br />}<br /></pre><br /></dir><br /><br />(Note: My preferred environment is GNU/Linux, that's what I'll target in this blog.)<br /><br />This little program should compile with gcc into an executable with no problem...<br />The meat of it is the function "simple_cli". All it does is:<br /><br /></span><ul><li><span style="font-size:100%;">Given</span></li></ul><ol><li><span style="font-size:100%;">a filename,<br /></span></li><li><span style="font-size:100%;">a pointer to a function that takes a char* and returns an int (the line-processor),</span></li><li><span style="font-size:100%;">and a repetition count,<br /></span></li></ol><ul><li><span style="font-size:100%;">it opens the file,</span></li><li><span style="font-size:100%;">reads it line-by-line, executing the line-processor on each line,</span></li><li><span style="font-size:100%;">until it reaches either</span></li></ul><ol><li><span style="font-size:100%;">end-of-file, or</span></li><li><span style="font-size:100%;">the line-processor returns a non-zero value,</span></li></ol><ul><li><span style="font-size:100%;">whereupon it closes the file, and</span></li><li><span style="font-size:100%;">returns the last return value of the line-processor.</span></li></ul><span style="font-size:100%;">Simple, right? I know, you're asking yourself why you're wasting your time reading this.<br /><br />Well, the magic isn't really in this program, but in the environment it runs in, in the file it reads from to be precise;<br />A simple invocation could look like this:<br /><br /><blockquote>bash-3.2$ echo Hello, world\! > infile<br />bash-3.2$ cat infile<br />Hello, world!<br />bash-3.2$ a.out infile<br />>> Hello, world!</blockquote>But here's a trickier one:<br /><br /><blockquote>bash-3.2$ mkfifo infifo<br />bash-3.2$ a.out infifo &<br />[2] 29875<br />bash-3.2$ cat > infifo<br />Hello world!<br />>> Hello world!<br />Hello again!<br />>> Hello again!<br />[2]+ Done a.out infifo</blockquote>(Just before that last line, I hit <ctrl-d>, i.e. EOF, ending the "cat" process and subsequently the "a.out" process.)<br /><br />In the second example, the simple_cli function opens whatever filename you passed in, and in this case it's a special file known as a <a href="http://linux.about.com/library/cmd/blcmdl4_fifo.htm"><span style="font-style: italic;">fifo</span></a>, a.k.a. a "named pipe." The cool thing about fifos is that fifo readers and writers block (by default) until the peer attaches to the fifo; in that second run of a.out above, the program was sitting there waiting for me to type in "Hello world!" and "Hello again!", and used the "parser" function to immediately spit them back out.<br /><br />So, depending upon how smart your "parser" routine is, and where you call "simple_cli", you can do all kinds of neat tricks; Smart "asserts," simple config-file readers, embedded CLIs or extension languages... These are things I'll get into down the road.<br /><br /></ctrl-d></span>Jason Nyberghttp://www.blogger.com/profile/02829265983464062698noreply@blogger.com0