Hello i am new in perl scripting.I have to write a script to check for .c file and then go in to the ,c file and find all function and insert line1 after { and line2 before } or before return( if return is present). Can any1 plz help me in it.

Ex:

   Function(.........)
   {
    insert line1;
    ..................
    ...................
    insert line2;
    # if return is present add before it
   }

Recommended Answers

All 23 Replies

You have to read .c file and write to some other file, while checking the requirements.

i have done till there. i am reading .c files in the folder but i am not sure how to check if it a function or not becoz there is noo regular pattern for the functions in the .c file. Do u know any method or so to check it out

Thanks & Regards

easiest way is to

(1) do a dir (ls) listing of directory contents, parse each one for a .c extention. start with the first .c file...

(2) open the .c file for READ, to a file handle.

(3) open a new .c file to WRITE to a different file handle and make it's filename similar to the original one being read from in step 2 (like using same name, but adding a "-mod" after the filename)

(4) read each line of original file.

(5) search for each function, and keep strict count of number of opening brackets, and number of closing brackets ( '{' and '}' )

(6) write each of the the lines read from the original file to the new file, exactly as read.

(7) write an additional "extra line 1" only after the first opening bracket '{', and write teh additional "extra line 2" right before the last closing bracket '}'

(8) repeat steps 5 - 7 until all functions are completed and end of file is reached

(9) close both the read file and write file, and then move to the next .c file in your directory.

(10) repeat steps #2 - #10 for the next .c file, until all .c files are completed.


.

as for checking whether or not it is a function... each subroutine in C starts with one or more return type:

int, long, short, double, float, void, char, unsigned ...

then it has a single word for the function name (simply: \w+ )

then it will have an open parenthesis '(' followed eventually by a closed parenthesis ')' ....

and then there will be the opening bracket '{'

thats all you have to parse on to find that it is a function... of course be sure to ignore function "prototypes"... they will be distinguished by a semicolon ';' after the closing parenthesis

the problem for you will be that a function declaration can spread across multiple lines... very often that first opening bracket is on a line by itself. like so:

void myExample_Function (int argument, char * value)
{
    blah;
    blah;
    blah;
}

Thanks for the help
I am doing the same but then i am not able to match for "{" for the function.
I am doing it as below.
if ($_ =~ /^\{/)
{
}
Some thing is wrong with it.Plz let me know

it isn't "necessarily" always at the first spot.

but the regex should be correct.

post more code. use tags, please[code=c] tags, please

hey i am trying to put line2 at the end of the function .But am not able to take up the " {" and "}" count. Plz let me know how to check for that

do
  {
#   print "inside do while\n";    
   if ($_ =~  /return/)
   {
           print OUT "$fotter";
           print "hey am inside return if\n";
           $foundReturn=1;
           $funInside=0;
           return;
   }
  if($_ =~ /^\{ || \{$/)
    {
     $openCount++;
     print "openCount1=", $openCount ,"\n";
     }#End of   if($_ =~ /[^\{]/) 

   elsif($_ =~ /(^\}) || (\}$)/ )
    {
     $closeCount++;
     print "closeCount=", $closeCount,"\n";

    }# End of   else if($_ =~ /[^\}] | (\}$)/ )

   else
    {
            #print "inside else \n";
            return;
    }#End of else

   if($openCount=$closeCount)

     {
       print "its the end of the function";
     }#End of  if($openCount=$closeCount)

  } #End of do while ($openCount=$closeCount)

Sorry i can not put entair code becoz of security issues.I have tried till here.
am not able to match for "{". can u plz correct where i have gone wrong.

for one thing, you cant put the begin/end of line operators (^ and $) inside parentheses. they must be immediately adjacent to the match operator like this

/^  ...regex...  $/

for another thing, you can't put the LOGICAL OR inside a regex. you need to break it down into separate expressions like this

if (($var =~ /^  ...  $/) || ($var =~ /^ ... $/))
{
    do stuff
}

also, can you ever think of a function that will never match the regex

/return/

perhaps a function like this:

void myStupidFunction (void) 
{  
     printf("hi world!\n");
     foo = bar;
}

finally, you can't guarantee that the open or close braces are ALWAYS going to be either at the beginning or end of a line. that would then fail to find any indented brace that had spurious whitespace afterwards, much less a brace that was preceded and followed by more code. like this:

for (a=1; a<10; a++) {     // only call 9 times!
     myFunction(a); 
}

your method (as I interpret it from the apparent intent of your code) will fail to find the opening brace, and only count the closing brace. thereby getting your counting algorithm hopelessly lost.

Thank you very much for the suggestion. I am taking the brace count to check the end of the function for functions which does not have return value. I have tried with the below code but elsif(($_ =~ /^\}/) || ($_=~ /\}$/ )) part is going to infinate loop and is not giving the count.

if(($_ =~ /^\{/) || ($_ =~ /\{$/))
    {
     $openCount++;
     print "openCount1=", $openCount ,"\n";
    }
elsif(($_ =~ /^\}/) || ($_=~ /\}$/ ))

    {
     $closeCount++;
     print "closeCount=", $closeCount,"\n";

    }# End of   else if($_ =~ /[^\}] | (\}$)/ )

If u have any other algorithm to check for the end of the function plz let me know.I am stuck up with this from 3 days now and dont know what to do next.

1) i noticed in your earlier code you were using = when you should have been using ==

2) you also had a do statement without a corresponding while condition. avoid do/while's for this and other reasons. you should stick with "while" loops unless you have compelling reason to use "do/while"

3) you should not be "return"-ing in the "else" statement.

4) you should not attempt to define the end of a function by the appearance of "return"... besides the fact that void types do not return a value, a function can have any number of return statements.

otherwise, this sort of works in a basic sense:

use strict;

my $openCount;
my $closeCount;
my $foundReturn;
my $myCfile;

die "usage: perl $0 <filename>\n" 
    if (!($ARGV[0]));

die "file: <",$ARGV[0],"> does not exist\n" 
    if (! -e ($myCfile = $ARGV[0]));

open(fp,$myCfile);
open(writeme,">output.txt");

print "reading <",$myCfile,"> ...\n";

$openCount = $closeCount = $foundReturn = 0;
while(<fp>)
{
    if ($_ =~  /return/)  {
        print "hey am inside return if\n";
        $foundReturn=1;
    }
    elsif(($_ =~ /^\{/) || ($_ =~ /\{$/)) {
        $openCount++;
        print "openCount1=", $openCount ,"\n";
    }
    elsif(($_ =~ /^\}/) || ($_=~ /\}$/ )) {
        $closeCount++;
        print "closeCount=", $closeCount,"\n";
    }
    if($openCount==$closeCount) {
        print "count is equal\n";
    }
}

you STILL have the problem that if a brace is both preceded and followed by any combination of whitespace, comments, or additional code -- which is a VERY likely prospect -- your counting code will become immediately and irretreivably lost.

for instance:

int main (int argc, char *argv[])
{
	unsigned *tempString, *tempPtr;
	unsigned i=0, opers=0, ptr=0, key;
	FILE *fp;
	typedef struct Operator_s {
		char Name[26];
		char Oin[11];
		char Password[16];
	} Operator_t;

in case it's not clear...

your parsing method will count the opening brace in line 6, but not the closing brace in line 10

Hey thank for taking ur time and helping me out.

1)I have replaced = with == where ever nesessary.

2) Few functions does not return any value for those ,to check the end of the functions i am taking brace count.

3) a) if(..) { // comment
b) else(..) } //comment
For cases like a) and b) i dont know what to do as the way i am checking wil not workout

4) Ex1: if(...) {
i dont know why but the below condition does not holds true in case of Ex1.
elsif(($_ =~ /^\{/) || ($_ =~ /\{$/))

5)There is always a curser pbm like if i am checking for return in the function(there can b multiple returns in a single function) line wil be inserted after return as curser wil be in the return statment.But it has to go back and insert line before return. Even the same case when i insert line at the start of the function.

(1) do not just blindly replace = with == , there was only one place where this was an issue if($openCount==$closeCount) (2) SOME functions can have NO "return" statements (void) ... but ANY function can have MANY returns (even void). you can NOT rely on the existence of "return" statements. if you try to, you will inevitably fail.

3) that is the very problem ive been telling you about. the method behind your choice of regex is flawed. this is the root of your problem. you need to think about another pattern by which you can find open and close braces without relying the "Beginning of Line" and "End of Line" operators (^ and $)

4) you probably have some whitespace (one or more spaces and/or tabs) after the brace. this is the same problem that is plaguing you in 3)

5) i dont understand what you mean

heres some more hints:

(1) do not attempt to look for "return" statements. at all.

(2) only use the open/close brace counting method.

(3) you need to change your regex method. merely looking for a brace at the beginning or end of the line WILL NOT cut it -- as you have already experienced.

(4) instead, look for ANY AND ALL braces, with the EXCEPTION of braces that are found within quotations (ie, braces to be printed.

this means that you can not just merely look for and count braces.... you have to look for and keep track of quotation marks ("), but disregard escaped quotation marks that are themselves being printed (\")

Hey thanks a lot for your help. Now my perl pgm is working. I want to try this pgm in windows. i have installed perlIDE and DzSoft perl editor. As i was giving the file path as command line argument in linex i don’t know how to give it in windows. i tried giving direct path in the pgm but its not working. can u just let me know how to give the path

I tried with this(context is the folder name which contains .c and .h files)

$path=\context;

$path="\context";

$path =C:\Documents and Settings\bindiya.d\Desktop\example\context;

Its not taking the path in this way.

replace '\'(single slash) with '\\' double slash for proper intrepretation. Because '\' is a escape character in Perl.

$path = "C:\\Documents and Settings\\bindiya.d\\Desktop\\example\\context";
which is nothing but C:\Documents and Settings\bindiya.d\Desktop\example\context

kath.

hey thank u very much for ur response.My pgm is working fine with the path
$path="C:/Documents and Settings/bindiya.d/Desktop/example/context/model";
Thanku very much for helping me out

glad you got it figured out :)

for Perl in Windows, i highly recommend that you use ActiveState Perl. It's the industry standard, and has a ton of modules and great community support.

http://www.activestate.com/solutions/perl/

they sell development kits, IDE's and whatnot, but the basic distribution is free (Active Perl)

Thanks a lot. I am sorry to bother u again but i still have a small pbm with my script.

1)i want to eleminate comment lines being processed.For exp
// if (..) {

above line should not be processed. i tryed with this

if ($_ =~ / \ / \ / /)

but its not working.
2) And evevn i want to remove blank line but noe able to know how to do that

Let me know where i am going wrong.

Thanks and regards

hey i think this should work fine for blank line if($_ =~ /^\s*$/ )

Hey most of the things i have figure out including blank line and the commt (//).
But i am stuck up with the condition like

/*
if () {
....
...
}
*/

It counts the open and close bracket in the comment
i want to ignore whole comments.

i tried with this

if($_ =~ /^\/\*/)
{
print "----Inside /* comment----\n";
&insideComment;
return 1;
}


sub insideComment
{
print "----Inside insideComment----\n";
while ( $_ =~ /\*\// )
{
print "---inside while loop---\n";
print OUT "$_";
$_=<IN>;
}


}#End of subrotuin

which is not working.

Do u have any suggestion for the above pbm

Hi Ray

lets do this in a new thread, if you dont mind.

start a new thread and describe what you're trying to do and your attempt so far to do it.

you can post the link to the new thread in here, if you feel like it.

thanks

OUTTER: while(<DATA>){
   if(m#^/\*#){
      while (<DATA>) {
         next OUTTER if (m#^\*/# );
      }
   }
   print;
}
__DATA__
foo bar
/*
if () {
....
...
}
*/
bash baz
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.