Extracting printf(...) from (void) printf(....)

G

guru

HI all

How to search for (void) from the line.

ex: (void) printf(....)

I want to search if (void) is there at the beggining of the line.. if
exist then extract printf(....) function.

Please let me know how it can be done or tell me the reference so that
I can try.

Thanks & Regards
Gururaja
 
S

smallpond

HI all

How to search for (void) from the line.

ex: (void) printf(....)

I want to search if (void) is there at the beggining of the line.. if
exist then extract printf(....) function.

Please let me know how it can be done or tell me the reference so that
I can try.

Thanks & Regards
Gururaja


Run the command:
perldoc perlretut
 
S

sln

HI all

How to search for (void) from the line.

ex: (void) printf(....)

I want to search if (void) is there at the beggining of the line.. if
exist then extract printf(....) function.

Please let me know how it can be done or tell me the reference so that
I can try.

Thanks & Regards
Gururaja

I assume this is just an example, the key phrase is 'void' and printf has
nothing to do with it.

printf() from CRT returns type 'int', the number of characters written.
To cast the return value to type (void) serves no purpose since only pointers
can be of type 'void', ie: not variables.

So these produce errors ->
int ivar; // ok
void var; // invalid type
var = (void) printf(....); // invalid rvalue cast
ivar = (void) printf(....); // invalid rvalue cast
(void) printf(....); // ok, does nothing
void *ptr; // ok, its a pointer


As far as parsing a source file, functions can span lines and have
nested functions, requiring balanced text parsing:

printf("*The floor of 0.3/0.1-2 is %f\n",
floor(0.3/0.1-2) );

and be mixed with comments. A better solution is to get a C++ parser somewhere.

But, if this isn't real source code text and all you want to do is parse anything
in (void) "function(anything)" on a line by line basis, I guess you could adopt a quick and
dirty approach, something like this:


while (<DATA>) # no caching of lines, raw per-line basis
{
chomp;
if (/(\s*void\s*)\s*([a-z][\w-]*?\s*\(.*\)\s*)/ { # greedy () in liue of balanced parenthesis
print $1,"\n";
}
# Or, just grab everything past (void)
# if (/(\s*void\s*)\s*(.+)/ {
# print $1,"\n";
# }
}

sln
 
S

sln

HI all

How to search for (void) from the line.
[snip]
and be mixed with comments. A better solution is to get a C++ parser somewhere.

But, if this isn't real source code text and all you want to do is parse anything
in (void) "function(anything)" on a line by line basis, I guess you could adopt a quick and
dirty approach, something like this:


while (<DATA>) # no caching of lines, raw per-line basis
{
chomp;
if (/(\s*void\s*)\s*([a-z][\w-]*?\s*\(.*\)\s*)/ { # greedy () in liue of balanced parenthesis
^^^
I forgot to mention this is untested. After looking at it a bit, this may be better:

/\(\s*void\s*\)\s*([a-zA-Z][\w-]*\s*\(.*\))/

Gee, there are alot of paren's in this one..

sln
 
S

sln

HI all

How to search for (void) from the line.
[snip]
and be mixed with comments. A better solution is to get a C++ parser somewhere.

But, if this isn't real source code text and all you want to do is parse anything
in (void) "function(anything)" on a line by line basis, I guess you could adopt a quick and
dirty approach, something like this:


while (<DATA>) # no caching of lines, raw per-line basis
{
chomp;
if (/(\s*void\s*)\s*([a-z][\w-]*?\s*\(.*\)\s*)/ { # greedy () in liue of balanced parenthesis
^^^
I forgot to mention this is untested. After looking at it a bit, this may be better:

/\(\s*void\s*\)\s*([a-zA-Z][\w-]*\s*\(.*\))/

Gee, there are alot of paren's in this one..
Why not add some more ..
/\(\s*void\s*\)\s*((?:_[a-zA-Z]|[a-zA-Z])[\w-]*\s*\(.*\))/

sln
 
J

Jens Thoms Toerring

I assume this is just an example, the key phrase is 'void' and printf has
nothing to do with it.
printf() from CRT returns type 'int', the number of characters written.
To cast the return value to type (void) serves no purpose since only pointers
can be of type 'void', ie: not variables.

It may not serve any purpose to the C compiler, but there are code
testing tools like lint that complain when the return value of a
function isn't used. And to keep lint etc. from doing so in cases
where disregarding the return value is exactly what you want it is
not uncommon practise to cast the such return values to '(void)'
since lint only then understands that you don't want to do anything
with it and shuts up.

To the OP: Of course you can search for such lines with something
like

/^\s*\(\s*void\*\)\s*printf\(.*?\)\s*;/

or, if it's not just about printf() but all functions,

/^\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/

but there are more possible cases like

if (some_condition) (void) printf(...);

or

do_something(); (void) printf(...);

just to name a few - so just looking for the first piece of code
on a line won't catch all instances. You would have to use at least
(I probably forgot a few possibilities) something like the fol-
lowing (assuming the function call isn't split up into more than
one line):

/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/

But even that it still might get a few cases wrong (e.g. if you
have printf()s with weird format strings like "xyz);" etc.) or
produce false positives. To get it 100% right I guess you would
have to write a parser for C, regexps probably aren't good enough
for this since they just look at the input stream but without
"understanding" what it means. To see how hairy C code can look
like check out the winning entries of the obfuscated C contest;-)

Regards, Jens
 
S

sln

It may not serve any purpose to the C compiler, but there are code
testing tools like lint that complain when the return value of a
function isn't used. And to keep lint etc. from doing so in cases
where disregarding the return value is exactly what you want it is
not uncommon practise to cast the such return values to '(void)'
since lint only then understands that you don't want to do anything
with it and shuts up.

Years ago, I read the description of Lint, even tried a code checker once.
Later on (a couple of years ago), I tried the Bounds Checker suite of stuff.
Total hogwash!! Bogged down bloated, slow, erroneous piece of crap.

Casting a function return value to void does not cast anything unless its assigned
to an lvalue, and then only as (void *). Other than that, nothing can be cast as void
except in function prototypes. I'm not suprised a Lint type tool can't tell the difference.
Possibly because the compiler will let any non-assignment type void cast take place.
Don't think Lint doesent use compiler compliant constructs, it does.
Lint is just a stoopid usless tool.

Imagine seeing (void) function(....) all over the code, possibly surrounded by define's.
What a dream job that would be to have to maintane such crap. Same with unit test bull crap.
Imagine having to code review that.
To the OP: Of course you can search for such lines with something
like

/^\s*\(\s*void\*\)\s*printf\(.*?\)\s*;/

or, if it's not just about printf() but all functions,

/^\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^
The beginning of the line doesen't matter.
There is no capture in this regex.
but there are more possible cases like

if (some_condition) (void) printf(...);

Or var = (void) printf(...);
Oh, that won't compile.
or

do_something(); (void) printf(...);

just to name a few - so just looking for the first piece of code
on a line won't catch all instances. You would have to use at least
(I probably forgot a few possibilities) something like the fol-
lowing (assuming the function call isn't split up into more than
one line):

/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^ metachar, needs to be escaped
/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^^^^ capturing a quantifier and a foward slash, the regex delimeter
/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^^^^^^^^^^^^^^^^^ capturing, why? ^ ^ no capturing of function, why?
/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^^^^^^^^^^^^^
functions can't begin with numeric digits, only underscore pluls alpha or alpha alone.
Better this (?:_[a-zA-Z]|[a-zA-Z])[\w-]
/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^^^^^^^^^^ this is \w
/(^|;|\)|,|}|(*/))\s*\(\s*void\*\)\s*[A-Za-z0-9_]+\s*\(.*?\)\s*;/
^^^^^^^^^^^^^^^^^
This is the right approach, but this is only needed if the line were being parsed
on a line-based, multiple occurances of (void) fn(..); within a looping while in
global context. As we know this is still inadequate.
In its simplest form, something like this might be enough but its not even close.
/\(\s*void\s*\)\s*((?:_[a-zA-Z]|[a-zA-Z])[\w-]*\s*\(.*\))\s*;/
But even that it still might get a few cases wrong (e.g. if you
have printf()s with weird format strings like "xyz);" etc.) or
produce false positives. To get it 100% right I guess you would
have to write a parser for C, regexps probably aren't good enough
for this since they just look at the input stream but without
"understanding" what it means. To see how hairy C code can look
like check out the winning entries of the obfuscated C contest;-)

Regards, Jens

Still though, to parse this with other than a full on C/C++ parser would involve much
more complexities. Thats not saying it can't be done with regular expressions.
If you can do while(/./sg) {} , then you can parse anything on the planet. And it is
a regular expression.

sln
 
G

guru

HI all
How to search for (void) from the line.
[snip]
and be mixed with comments. A better solution is to get a C++ parser somewhere.
But, if this isn't real source code text and all you want to do is parseanything
in (void) "function(anything)" on a line by line basis, I guess you could adopt a quick and
dirty approach, something like this:
while (<DATA>)  # no caching of lines, raw per-line basis
{
   chomp;
   if (/(\s*void\s*)\s*([a-z][\w-]*?\s*\(.*\)\s*)/ { # greedy () inliue of balanced parenthesis

            ^^^
I forgot to mention this is untested. After looking at it a bit, this maybe better:

        /\(\s*void\s*\)\s*([a-zA-Z][\w-]*\s*\(.*\))/

Gee, there are alot of paren's in this one..

sln- Hide quoted text -

- Show quoted text -

HI

yes this is not a real example.

the acually the pattern will be of type

1. (void) function(....)
2. function(....)
3. return (function(....)........)

I want to extract the function(....) from the above type of lines.

Thanks & Regards
Gururaja
 
S

sln

How to search for (void) from the line.
[snip]
and be mixed with comments. A better solution is to get a C++ parser somewhere.
But, if this isn't real source code text and all you want to do is parse anything
in (void) "function(anything)" on a line by line basis, I guess you could adopt a quick and
dirty approach, something like this:
while (<DATA>)  # no caching of lines, raw per-line basis
{
   chomp;
   if (/(\s*void\s*)\s*([a-z][\w-]*?\s*\(.*\)\s*)/ { # greedy () in liue of balanced parenthesis

            ^^^
I forgot to mention this is untested. After looking at it a bit, this may be better:

        /\(\s*void\s*\)\s*([a-zA-Z][\w-]*\s*\(.*\))/

Gee, there are alot of paren's in this one..

sln- Hide quoted text -

- Show quoted text -

HI

yes this is not a real example.

the acually the pattern will be of type

1. (void) function(....)
2. function(....)
3. return (function(....)........)

I want to extract the function(....) from the above type of lines.

Thanks & Regards
Gururaja

Oh, I needed something to do for a few hours.
I guess the below should parse C/C++ functions any way desired.

sln

---------------------------------------------------------

## Idea - To parse out C/C++ style functions
## that have parenthetical closures (some don't)
## ===============================================
use strict;
use warnings;

my $Source = join '', <DATA>;

my @Funct = (); # Holds sequential functions info;
# ie: substr indexes to 'name', '(', and ')' segment positions
my @Ndx = (); # Index stack of current @Funct elements in find recursion

my $Preamble = "\\s*\\("; # constant
my $Compliance = "_*[a-zA-Z][\\w]*"; # constant

my $FName = $Compliance; # Gets all functions, uses the compliant pattern
#my $FName = "\\(\\s*void\\s*\\)\\s*function"; # Extended, non-compliant function pattern

# ***************************************
# Or, uncomment these to search for a specific function name that is compliant.
# (Warning! FName should resolve to a compliant function name)
# If you wish to use a custom regex for FName (non-compliant), skip this block and enter FName above.
# -------------------------
# my $FName = "atoi";
# die "Function name pattern: '$FName' is non-compliant!\n" if ($FName !~ /$Compliance/);
# ***************************************

# The main pre-compiled parser regular expression
my $FxParse = qr/(\/{2}.*?\n)|(\/\*.*?\*\/)|($FName$Preamble)|(\()|(\))/s;
# 1 1|2 2|3 3|4 4|5 5

# Parse out some functions
Find_Function(\$Source);

# Print functions found
if (!@Funct) { print "Function name pattern: '$FName' not found!\n" }
else { print "\nFound ".@Funct." matches.\nFunction pattern: '$FName' \n" }
for my $ref (@Funct)
{
# print "@{$ref}\n";
print "\n\@: ";
print substr($Source,$ref->[0],$ref->[2]-$ref->[0]),"\n";
# Here, each function name and/or parameter can be printed
# and/or examined separately.
}

# Finished!
#

# ---------------------------------------------------------
# Recursive procedure that finds C/C++ style functions
# (the engine)
#
sub Find_Function
{
my ($src,$spos,$closure) = @_;
$spos = 0 if (!defined $spos);
$closure = 0 if (!defined $closure);
pos($$src) = $spos;

while ($$src =~ /$FxParse/g)
{
# $1/$2 - comments

if (defined $3) # 'function name'
{
push @Ndx, scalar(@Funct);
# positions: function ( )
push @Funct , [$-[0], pos($$src), 0];
# recurse this procedure
pos($$src) = Find_Function ( $src, pos($$src), 1 );
}
elsif (defined $4) # '('
{
++$closure;
}
elsif (defined $5) # ')'
{
--$closure;
if ($closure <= 0)
{
if (@Ndx)
{
$Funct[pop @Ndx]->[2] = pos($$src);
return pos($$src);
}
$closure = 0;
}
}
}
}

__DATA__

1. (void) function(....)
2. function(....)
3. return ( // some comments
function(..(atoi("398"), (5 * x)..)..,
/* ) <-forget this parenth */......)
)

---------------------------------------------
Do not copy from here down...
---------------------------------------------

Some various input/output:

c:\temp>perl c_functionparser.pl

Found 5 matches.
Function pattern: '_*[a-zA-Z][\w]*'

@: function(....)

@: function(....)

@: return ( // some comments
function(..(atoi("398"), (5 * x)..)..,
/* ) <-forget this parenth */......)
)

@: function(..(atoi("398"), (5 * x)..)..,
/* ) <-forget this parenth */......)

@: atoi("398")

c:\temp>

----------------------------

c:\temp>perl c_functionparser.pl

Found 3 matches.
Function pattern: 'function'

@: function(....)

@: function(....)

@: function(..(atoi("398"), (5 * x)..)..,
/* ) <-forget this parenth */......)

c:\temp>

---------------------------

c:\temp>perl c_functionparser.pl

Found 1 matches.
Function pattern: 'atoi'

@: atoi("398")

c:\temp>

---------------------------

c:\temp>perl c_functionparser.pl

Found 1 matches.
Function pattern: '\(\s*void\s*\)\s*function'

@: (void) function(....)

c:\temp>
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top