Scripting with cscope

The cscope (and cscope-fast) tools provide an excellent way for us to search for particular instances of phrases, etc, inside the Solaris source code. The only downside is that the tool is interactive: it wants to use curses to ask for input and display its output. How then to make use of its knowledge in scripts?

Whilst the proper solution is to have cscope and cscope-fast modified to have a non-curses output format, a workaround that can be used in the mean time is to define a special "tty" that ensures no escape sequences (or other nasties) end up in the output.

  • 1. Create two directories $HOME/.terminfo and $HOME/.terminfo/c
  • 2. Create a termcap definition file, $HOME/.terminfo/c/cscope.termcap. For my first attempt on this, the file I created was a termcap definition by copying vt100's and making all of the escape sequences into tab's. The contents of this file look like this:
  • 
    cscope:\\
            :do=\^J:co#9999999:li#9999999:cl=\^I:sf=\^I:\\
            :le=\^H:bs:am:cm=\^I:nd=\^I:up=\^I:\\
            :ce=\^I:cd=\^I:so=\^I:se=\^I:us=\^I:ue=\^I:\\
            :md=\^I:mr=\^I:mb=\^I:me=\^I:is=\^I:\\
            :rs=\^I:ks=\^I=:ke=\^I:\\
            :ku=\^I:kd=\^I:kr=\^I:kl=\^I:kb=\^H:\\
            :ho=\^I:k1=\^I:k2=\^I:k3=\^I:k4=\^I:pt:sr=\^I:vt#3:xn:\\
            :sc=\^I:rc=\^I:cs=\^I:
    
    
  • 3. Convert the termcap into a terminfo file that can be used by curses, using captoinfo and then tic. To do this, I used the following script:
    
    #!/bin/sh
    cd $HOME/.terminfo/c
    setenv TERMINFO $HOME/.terminfo
    captoinfo cscope.termcap > cscope.terminfo
    tic cscope.terminfo
    
    
  • 4. Write a front end to cscope-fast.
    
    #!/bin/sh
    TERMINFO=$HOME/.terminfo
    export TERMINFO
    TERM=cscope
    export TERM
    cat /dev/null | cscope-fast -d -0 $1 | egrep '\^[1-9]'
    
    

And the end result is I can do this:


$ ~/bin/cscope-grep ip_input
1       ip.c    <global>        15017   ip_input(ill_t  \*ill,   ill_rx_ring_t  \*ip_ring,        mblk_t  \*mp_chain,
2       ip.h    <global>        3225    extern  void    ip_input(ill_t  \*,     ill_rx_ring_t    \*,      mblk_t  \*,
3       ip_if.c ill_capability_dls_capabl       2925    dls.dls_rx      =      (uintptr_t)ip_input;
4       ip.c    ip_rput 14993   ip_input(ill,   NULL,   mp,     NULL);
5       ip_netinfo.c    ip_ni_queue_func_impl   1293    ip_input(ill,   NULL,  packet->ni_packet,       0);
6       ip_squeue.c     ip_soft_ring_assignment 754     ip_input(ill,   NULL,   mp_chain,       mhip);                          

Update

As Alan Burlinson mentioned below, cscope-fast has a command line option, "-l", that allows for it to generate output that is not screen orientated. This can be used like this:


$ cscope-fast -l -d -0 ip_input
uts/common/inet/ip/ip.c <global> 15017 ip_input(ill_t \*ill, ill_rx_ring_t \*ip_ring, mblk_t \*mp_chain,
uts/common/inet/ip.h <global> 3225 extern void ip_input(ill_t \*, ill_rx_ring_t \*, mblk_t \*,
uts/common/inet/ip/ip_if.c ill_capability_dls_capable 2925 dls.dls_rx = (uintptr_t)ip_input;
uts/common/inet/ip/ip.c ip_rput 14993 ip_input(ill, NULL, mp, NULL);
uts/common/inet/ip/ip_netinfo.c ip_ni_queue_func_impl 1293 ip_input(ill, NULL, packet->ni_packet, 0);
uts/common/inet/ip/ip_squeue.c ip_soft_ring_assignment 754 ip_input(ill, NULL, mp_chain, mhip);
>>

While this gives us a leg up, there are two problems:

  • 1. It is still expecting input from the user so we need to do "cat /dev/null | cscope-fast -l..." to make it terminate.
  • 2. There is no clear field delimiters such as the TAB's in the other output. As long as none of the first 4 fields contains a space, this isn't too much of a problem as it can be worked around.

To wrap this up, I've used a perl script below because I'm more familiar with perl being able to carve up an array and print it out than I am with shell.


#!/bin/perl
$args = join(' ',@ARGV);
open(I, "cat /dev/null | cscope-fast -l -d $args|") || die $!;
while (<I>) {
        last if (/\^>>/);
        @F = split(/ /);
        @B = splice(@F,3,$#F);
        @A = splice(@F,0,3);
        print join("\\t",@A)."\\t".join(' ',@B)."\\n";
}
close(I);
exit(0);

Thanks Alan for the pointer and reminder.

Comments:

Ummm, why don't you just use the -l flag? Line-Oriented Interface The -l option lets you use cscope where a screen-oriented interface would not be useful, e.g., from another screen-oriented program.

Posted by Alan Burlison on July 17, 2007 at 06:33 AM PDT #

I'm sure I tried "-l" (or was it "-L"?) at some point but it didn't seem to do what I wanted...

Posted by Darren on July 17, 2007 at 06:20 PM PDT #

The UPDATE part of the post is useful.

The ">>" problem goes away if -L (uppercase L) is used.

Posted by Arun Saha on August 26, 2010 at 06:34 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

avalon

Search

Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today