Find function definition in a C file for a function with its name and starting line no. as input

Discussion in 'Perl Misc' started by jeniffer, Mar 24, 2006.

  1. jeniffer

    jeniffer Guest

    I am writing a perl code to find out the location (line number) of
    ending bracket of a function given its name and start line number .Do i
    just scan character by character (from start line number ) and
    increment a counter when I encounter { decrement the counter by 1 on
    getting } ,and when the counter = 0 ,I take the line number .This would
    free me from parsing the code .Is this method correct? or can i do it
    in a better way by regular expression ? I need to have a fast approach
    since the code has finally to work on thousands of C files.
     
    jeniffer, Mar 24, 2006
    #1
    1. Advertising

  2. jeniffer

    Sisyphus Guest

    "jeniffer" <> wrote in message
    news:...
    > I am writing a perl code to find out the location (line number) of
    > ending bracket of a function given its name and start line number .Do i
    > just scan character by character (from start line number ) and
    > increment a counter when I encounter { decrement the counter by 1 on
    > getting } ,and when the counter = 0 ,I take the line number .This would
    > free me from parsing the code .Is this method correct? or can i do it
    > in a better way by regular expression ? I need to have a fast approach
    > since the code has finally to work on thousands of C files.
    >


    Yeah - I've done stuff like that successfully - but it's in an environment
    that's not going to cause me any embarrassment if it breaks (and where I
    have control over what the C file looks like).

    I scanned line by line (rather than character by character) and kept count
    via a regex - something like:

    while(<READ>) {
    $open_count += $_ =~ tr/\{//;
    $close_count += $_ =~ tr/\}//;
     
    Sisyphus, Mar 24, 2006
    #2
    1. Advertising

  3. [A complimentary Cc of this posting was sent to
    jeniffer
    <>], who wrote in article <>:
    > I am writing a perl code to find out the location (line number) of
    > ending bracket of a function given its name and start line number .Do i
    > just scan character by character (from start line number ) and
    > increment a counter when I encounter { decrement the counter by 1 on
    > getting } ,and when the counter = 0 ,I take the line number .This would
    > free me from parsing the code .Is this method correct?


    Will not work. Too hard to distinguish what is a comment, what is a
    literal, etc.

    Either use C::Scan (directly - or it might be that you need to hook
    into lower level subroutines), or program in Emacs lisp, where this is
    trivial.

    Hope this helps,
    Ilya
     
    Ilya Zakharevich, Mar 24, 2006
    #3
  4. jeniffer

    Lukas Mai Guest

    jeniffer <> schrob:
    > I am writing a perl code to find out the location (line number) of
    > ending bracket of a function given its name and start line number .Do i
    > just scan character by character (from start line number ) and
    > increment a counter when I encounter { decrement the counter by 1 on
    > getting } ,and when the counter = 0 ,I take the line number .This would
    > free me from parsing the code .Is this method correct? or can i do it
    > in a better way by regular expression ? I need to have a fast approach
    > since the code has finally to work on thousands of C files.


    This is non-trivial as you have to deal with nesting, string literals,
    comments, etc. I think it's possible with irregular expressions:

    $bs = qr{\\|\Q??/\E}; # backslash
    $lbr = qr{\{|\Q??<\E}; # left brace
    $rbr = qr{\}|\Q??>\E}; # right brace
    $block = qr!
    $lbr
    (?>
    " (?> $bs . | [^"] )* "
    |
    ' (?> $bs . | [^'] )* '
    |
    / (?: $bs \n )* \*
    [^*]*
    \*+ (?: $bs \n )*
    (?:
    [^/*] [^*]*
    \*+ (?: $bs \n )*
    )*
    /
    |
    / (?: $bs \n )* /
    (?:
    $bs \n
    |
    [^\n]
    )*
    |
    (??{ $block })
    |
    [^{}"']
    )*
    $rbr
    !sx;

    Note that this uses several experimental features of the regex engine,
    some of which don't work (and I didn't test this code).

    To do it right, you have to somehow tokenize the input. Simply counting
    characters doesn't work.

    HTH, Lukas
     
    Lukas Mai, Mar 24, 2006
    #4
  5. jeniffer

    jeniffer Guest

    Ilya Zakharevich wrote:

    > [A complimentary Cc of this posting was sent to
    > jeniffer
    > <>], who wrote in article <>:
    > > I am writing a perl code to find out the location (line number) of
    > > ending bracket of a function given its name and start line number .Do i
    > > just scan character by character (from start line number ) and
    > > increment a counter when I encounter { decrement the counter by 1 on
    > > getting } ,and when the counter = 0 ,I take the line number .This would
    > > free me from parsing the code .Is this method correct?

    >
    > Will not work. Too hard to distinguish what is a comment, what is a
    > literal, etc.
    >
    > Either use C::Scan (directly - or it might be that you need to hook
    > into lower level subroutines), or program in Emacs lisp, where this is
    > trivial.
    >
    > Hope this helps,
    > Ilya



    I read abt C::Scan and tried using C::Scan ...Here's the code and the
    error :::Can you plz help me find out the reason??

    #!/usr/bin/perl

    use strict;
    use warnings;
    use C::Scan;

    my $c = new C::Scan 'filename' => $name;
    my $fdef = $c->get('inlines');
    print "\nfdefinition =$fdef";

    [u103@linux part2]$ perl cs.pl
    Can't locate C/Scan.pm in @INC (@INC contains:
    /usr/lib/perl5/5.8.0/i386-linux-t
    hread-multi /usr/lib/perl5/5.8.0
    /usr/lib/perl5/site_perl/5.8.0/i386-linux-threa
    d-multi /usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl
    /usr/lib/perl5/v
    endor_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.0 /usr/l
    ib/perl5/vendor_perl /usr/lib/perl5/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5
    /5.8.0 .) at cs.pl line 5.
    BEGIN failed--compilation aborted at cs.pl line 5.
     
    jeniffer, Mar 26, 2006
    #5
  6. [A complimentary Cc of this posting was sent to
    jeniffer
    <>], who wrote in article <>:
    > use strict;
    > use warnings;
    > use C::Scan;
    >
    > my $c = new C::Scan 'filename' => $name;


    Do not see where $name is defined. This should not even compile.

    > [u103@linux part2]$ perl cs.pl
    > Can't locate C/Scan.pm in @INC (@INC contains:


    As the message says, you did not install it yet.

    perl -MCPAN -e 'install C::Scan'

    Hope this helps,
    Ilya
     
    Ilya Zakharevich, Mar 26, 2006
    #6
  7. jeniffer

    Juha Laiho Guest

    "jeniffer" <> said:
    >I read abt C::Scan and tried using C::Scan ...Here's the code and the
    >error :::Can you plz help me find out the reason??
    >
    >#!/usr/bin/perl
    >
    >use strict;
    >use warnings;
    >use C::Scan;

    [...]
    >[u103@linux part2]$ perl cs.pl
    >Can't locate C/Scan.pm in @INC (@INC contains:

    [...]
    >at cs.pl line 5.
    >BEGIN failed--compilation aborted at cs.pl line 5.


    This very much looks like you don't have C::Scan installed at all,
    or alternatively, you don't have your perl library search path
    defined, if you made a private (as opposed to systemwide) installation
    of the module.
    --
    Wolf a.k.a. Juha Laiho Espoo, Finland
    (GC 3.0) GIT d- s+: a C++ ULSH++++$ P++@ L+++ E- W+$@ N++ !K w !O !M V
    PS(+) PE Y+ PGP(+) t- 5 !X R !tv b+ !DI D G e+ h---- r+++ y++++
    "...cancel my subscription to the resurrection!" (Jim Morrison)
     
    Juha Laiho, Mar 26, 2006
    #7
  8. jeniffer

    Bart Lateur Guest

    jeniffer wrote:

    >I am writing a perl code to find out the location (line number) of
    >ending bracket of a function given its name and start line number .Do i
    >just scan character by character (from start line number ) and
    >increment a counter when I encounter { decrement the counter by 1 on
    >getting } ,and when the counter = 0 ,I take the line number .This would
    >free me from parsing the code .Is this method correct?


    It's close, but not quite. You'll have to be able to recognize comments,
    and strings. You have to skip braces inside those. For the rest, it's
    just a matter of balancing the braces.

    >or can i do it
    >in a better way by regular expression ?


    Yeah, doing it character by character is how one would do it in C, but
    it most definitely isn't the fastest way in Perl. Scanning for the next
    brace with a regex would be lots faster. But likely not better,
    resultwise.

    At first I'm thinking of using Text::Balanced, it's more or less
    designed for things like that. But I remember reading an article on
    perl.com, on lexing your data (thus recognizing comments and strings).
    That might be of use to you:

    Lexing Your Data
    <http://www.perl.com/pub/a/2006/01/05/parsing.html>


    --
    Bart.
     
    Bart Lateur, Mar 26, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Apple
    Replies:
    3
    Views:
    319
    Apple
    Aug 1, 2005
  2. scad
    Replies:
    23
    Views:
    1,205
    Alf P. Steinbach
    May 17, 2009
  3. thunk
    Replies:
    1
    Views:
    347
    thunk
    Mar 30, 2010
  4. thunk
    Replies:
    0
    Views:
    522
    thunk
    Apr 1, 2010
  5. thunk
    Replies:
    14
    Views:
    655
    thunk
    Apr 3, 2010
Loading...

Share This Page