shell problem

problem:
I give the source of a c program.. is required to indicate how many times is called each function defined in the program and line number
there is a call.

let's say i have lab2.c:

float dist(int *a,int *b,int n){
	int i=0;
	double d=0;
	for (i=1;i<=n;i++){
		d+=pow((a-b),2);
	}
	return sqrt(d);
}

void citire(int *sir,int n){
	int i;
	for (i=1;i<=n;i++){
		printf("dim[%d]=",i);
		scanf("%d",&sir);
	}
}

int main(){
	int n, **m,nr,i,j,a,b;
	printf("nr de puncte:");
	scanf("%d",&nr);
	printf("Dimensiuni:");
	scanf("%d",&n);
	m=(int **) calloc(nr,sizeof(int*));
	for (i=1;i<=nr; i++)
	    m = (int*) calloc(n,sizeof(int));
	for (i=1;i<=nr;i++)
		citire(m,n);
	float max=0;
	for (i=1;i<nr;i++)
		for (j=i+1;j<=nr;j++)
			if (dist(m,m[j],n)>max){
				a=i;
				b=j;
				max=dist(m,m[j],n);
			}
	printf("\n distanta maxima este intre punctele %d si %d",a,b);
	return 0;
}

the result will be:
dist
4 35 38
3

citire
23 31
2

i have these 2 files:

scen.awk

BEGIN { level=0; }
{
if (index($0,"{")<1) {
   if ((level==0) && (index($0,"(")>0) && (index($0,")")>0))
	print $0 | cut -d "(" -f1 | cut -d " " -f2;
   if (index($0,"{")>0) level++;
   if (index($0,"}")>0) level--;
   }
}

and sh1.sh

if [ $# -eq 0 ] ; 
  then echo "nu exista parametrii"
  else
  for i 
    do
    awk -f scen.awk $i | while read functie 
	do 
	echo $functie
        grep -n "$functie" $i
        nr=`grep -c $functie`
        echo $nr
	done      
    done
fi

when i try sh sh1.sh lab2.c it says

print $0 | cut -d "(" -f1 | cut -d " " -f2;
                                   ^ parse error

anyone knows how to make this problem work?

The print command:

BEGIN { level=0; }
{
if (index($0,"{")<1) {
   if ((level==0) && (index($0,"(")>0) && (index($0,")")>0))
	print $0 | cut -d "(" -f1 | cut -d " " -f2;
   if (index($0,"{")>0) level++;
   if (index($0,"}")>0) level--;
   }
}

should be something like:

BEGIN { level=0; }
{
if (index($0,"{")<1) {
   if ((level==0) && (index($0,"(")>0) && (index($0,")")>0))
        print $0 |"cut -d \"(\" -f1 | cut -d \" \" -f2"
   if (index($0,"{")>0) level++;
   if (index($0,"}")>0) level--;
   }
}

thanks

No problem!

Seems more efficient to let awk do the work rather than invoking two extra processes for each function encountered:

BEGIN { level=0; }
{
if (index($0,"{")<1) {
   if ((level==0) && (index($0,"(")>0) && (index($0,")")>0))
   {
       split( $0, a, "(" );
       n = split( a[1], b, " " );
       print b[n];
   }
   if (index($0,"{")>0) level++;
   if (index($0,"}")>0) level--;
   }
}

This also handles the case where the programmer used the more traditional style that places the function type on the previous line:

float
dist(int *a,int *b,int n){

---------- Post updated at 12:50 ---------- Previous update was at 11:58 ----------

Looking at your code a bit more closely, I'm not sure that it's going to do what you expected. In particular, this seems wrong:

if (index($0,"{")<1) {

This will execute the contents of the block only if the record does not have an opening (left) curly brace, but from the code it seems that you want the block to execute when there is an opening curly brace. The code also assumes that the programmer hasn't dropped the opening brace to the next line.

You could extend the awk a bit, and do everything in one pass across your C source with one awk programme. Something like this:

awk '
    /\(.*\)/ && level == 0 {        # capture each function name
        split( $0, a, "(" );
        n = split( a[1], b, " " );
        list[b[n]] = 1;
    }

    /{/ {
        if( ++level == 1 )          # don't need to process further if level 0
            next;
     }

    /}/ { level--; }

    level > 0 {                     # search for function use only if not a 0th level
        for( f in list )
            if( match( $0, f"[(]" ) )
            {
                loc[f] = loc[f] NR " ";
                num[f]++;
            }
    }

    END {                           # print each function, lines where its called and number of uses
        for( f in list )
            if( length( loc[f] ) )
                printf( "%s\n%s\n%d\n\n", f, loc[f], num[f] );
    }
' 

This also handles the case where the opening curly brace is dropped to the next line, the type is on the preceding line, and allows for prototype statements.