8 #define COMPARE(A,B) ( ! strncmp ( A , B , strlen( B ) ) )
9 #define COMPARE2(A,B) ( ! strcmp ( A , B ) )
10 #define INLINELEN (4*8192)
12 #define MAXARGS (4*8192)
15 #define DBDIR "tools/code_dbase"
20 main( int argc
, char *argv
[] )
24 char fname
[VARLEN
], syscom
[VARLEN
] ;
26 if ( argc
< 2 || argc
> 5 || ( argc
== 2 && ! COMPARE2( argv
[1] , "rebuild" ) ) ) {
27 printf("usage : wrfvar varname routinename\n" ) ;
28 printf(" wrfvar rebuild\n" ) ;
33 if ( argc
== 4 && argv
[3] != NULL
) {
34 if ( COMPARE2( argv
[3] , "all" ) ) sw_all
= 1 ;
36 sprintf( fname
, "%s/calls", DBDIR
) ;
37 if (( fp
= fopen ( fname
, "r" )) == NULL
|| COMPARE2( argv
[1], "rebuild" ) ) {
39 printf("Building code database ... please wait\n") ;
40 sprintf( syscom
, "cd tools/CodeBase ; make" ) ;
41 rc
= system( syscom
) ;
42 if ( WEXITSTATUS( rc
) ) { exit(3) ; }
43 sprintf( syscom
, "tools/build_codebase" ) ;
44 rc
= system( syscom
) ;
45 if ( WEXITSTATUS( rc
) ) { exit(3) ; }
46 sprintf( syscom
, "ln -sf tools/wrfvar ." ) ;
47 sprintf( syscom
, "ln -sf tools/subinfo ." ) ;
48 if ( COMPARE2( argv
[1] , "rebuild" ) ) exit
;
51 lower_case_str ( vname
) ;
52 lower_case_str ( rout
) ;
53 printf("<h4>Trace upwards through call tree for %s</h4><p>\n",vname
) ;
54 wrfvar ( vname
, rout
, 0 ) ;
57 wrfvar ( char * vname
, char *rout
, int recursion_level
)
66 char inln
[INLINELEN
], inln2
[INLINELEN
], inln3
[INLINELEN
] ;
68 char fname
[VARLEN
], fname2
[VARLEN
], sf
[VARLEN
] ;
69 char vv
[VARLEN
], vv2
[VARLEN
] ;
70 char u0
[VARLEN
] , u1
[VARLEN
] , u2
[VARLEN
] ;
71 char v0
[VARLEN
] , v1
[VARLEN
] , v2
[VARLEN
] ;
72 char r
[12][VARLEN
], t
[12][VARLEN
], u
[12][VARLEN
], v
[12][VARLEN
] ;
73 char routfile
[VARLEN
] ;
74 char tmp
[VARLEN
], darg
[VARLEN
], dintent
[VARLEN
] ;
76 char rout1
[VARLEN
], rout2
[VARLEN
], rout3
[VARLEN
] ;
77 char sourcefile
[VARLEN
], sourcefile_caller
[VARLEN
] ;
78 char s1
[VARLEN
], s2
[VARLEN
], s3
[VARLEN
] ;
79 char * p
, * q
, * q1
, prev
;
80 int found_var
, nargs_rout
, argn
, callno
, more_calls
, first_time
;
81 int contains_i1_declarations
;
83 if (( dir
= opendir ( DBDIR
)) == NULL
) {
84 fprintf(stderr
, "Must be in top level WRF directory\n") ; exit(2) ;
87 strcpy( rout1
, rout
) ;
89 strcpy( vv2
, vname
) ;
90 remove_whitespace( vv2
) ;
91 /* remove arguments */
92 if ((q
= strchr( vv2
, '(' )) != NULL
) *q
= '\0' ;
93 /* remove time level if there */
94 if (( q
= strrchr( vv2
, '_' )) != NULL
) {
95 if ( COMPARE2( q
, "_1" ) || COMPARE2( q
, "_2" ) || COMPARE2( q
, "_3" ) ) *q
= '\0' ;
97 if ( COMPARE( vv2
, "grid%" ) || !strcmp( rout
, "registry_i1" )) {
98 if (( REGISTRY
= fopen( "Registry/Registry" , "r" )) == NULL
) {
99 fprintf(stderr
,"can not open Registry/Registry\n") ; exit(2) ; }
101 while ( fgets( inln2
, INLINELEN
, REGISTRY
) != NULL
) {
103 strcat( inln
, inln2
) ;
104 if (( q
= strrchr ( inln
, '\\' )) != NULL
) { /* continuation */
105 *q
= '\0' ; continue ;
107 if (( q
= strchr( inln
, '#' )) != NULL
) *q
= '\0' ;
109 for ( p
= inln
, q
= inln2
; *p
; p
++, q
++ ) {
110 if ( ! inquote
&& *p
== '"' ) { inquote
= 1 ; *p
= ' ' ; }
111 else if ( inquote
&& *p
== '"' ) { inquote
= 0 ; *p
= ' ' ; }
112 if ( *p
== ' ' && inquote
) { *q
= '`' ; }
116 for ( i
= 0 ; i
< 11 ; i
++ ) {
117 strcpy( r
[i
] , "" ) ;
118 get_token_n( inln2
, " ", i
, r
[i
] ) ; remove_nl(r
[i
]) ;
119 if ( i
< 10 ) lower_case_str( r
[i
] ) ;
121 if ( COMPARE2 ( r
[0], "state" ) ) {
122 if ( COMPARE ( r
[4], "dyn_" ) ) {
123 /* if core associated */
124 sprintf(s1
,"%s_",&(r
[4][4])) ;
125 i
= strlen(&(r
[4][4])) ;
127 { char *x
, *y
; int j
;
128 for ( x
= vv2
+5 , y
= s3
, j
= 0 ; j
< i
; j
++ ) { *y
++ = *x
++ ; }
132 /* is there a bug in this?? */
133 strncpy( s3
, vv2
+5, i
) ;
134 fprintf(stderr
,"X %s <- %s %d\n", s3
, vv2
, i
) ;
136 sprintf(s2
,"%s_",s3
) ;
137 if ( COMPARE2 ( s1
, s2
) &&
138 COMPARE2 ( vv2
+5+(strlen(r
[4])-3), r
[2] ) ) {
139 for (p
= r
[9] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
140 for (p
= r
[10] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
141 printf("%3d. <b>Registry-defined</b>: <class> %s <type> %s <varname> %s <description> \"%s\" <units> \"%s\"<br>\n",
142 recursion_level
+1, r
[0], r
[1], r
[2], r
[9], r
[10] ) ;
145 /* if not core associated */
146 if ( COMPARE2 ( vv2
+5, r
[2] ) ) {
147 for (p
= r
[9] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
148 for (p
= r
[10] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
149 printf("%3d. <b>Registry-defined</b>: <class> %s <type> %s <varname> %s <description> \"%s\" <units> \"%s\"<br>\n",
150 recursion_level
+1, r
[0], r
[1], r
[2], r
[9], r
[10] ) ;
153 } else if ( COMPARE2 ( r
[0], "rconfig" ) ) {
154 if ( COMPARE2 ( vv2
+5, r
[2] ) ) {
155 for (p
= r
[8] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
156 printf("%3d. <b>Registry-defined</b>: <class> %s <type> %s <varname> %s <description> \"%s\" <br>\n",
157 recursion_level
+1, r
[0], r
[1], r
[2], r
[8] ) ;
159 } else if ( COMPARE2 ( r
[0], "i1" ) && !strcmp( rout
, "registry_i1" )) {
160 if ( COMPARE2 ( vv2
, r
[2] ) ) {
161 for (p
= r
[9] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
162 for (p
= r
[10] ; *p
; p
++ ) { if ( *p
== '`' ) *p
= ' ' ; }
163 printf("%3d. <b>Registry-defined</b>: <class> %s <type> %s <varname> %s <description> \"%s\" <units> \"%s\"<br>\n",
164 recursion_level
+1, r
[0], r
[1], r
[2], r
[9], r
[10] ) ;
174 sprintf( routfile
, "%s/%s", DBDIR
, rout
) ;
175 strcpy ( sourcefile
, "" ) ;
178 if (( ROUT
= fopen( routfile
, "r" )) == NULL
) return ;
180 contains_i1_declarations
= 0 ;
181 while ( fgets( inln
, INLINELEN
, ROUT
) != NULL
) {
183 /* find first non space */
184 for ( p
= inln
; *p
; p
++ ) { if ( *p
!= ' ' ) break ; }
185 /* change multiple spaces to single space */
186 for ( q
= p
, q1
= q
, prev
= *p
; *q
; q
++ )
187 { if ( prev
== ' ' && *q
== ' ' ) { continue ; } else { prev
= *q
; *q1
++ = *q
; } }
189 for ( i
= 0 ; i
< 11 ; i
++ ) {
190 strcpy( t
[i
] , "" ) ;
191 get_token_n( inln
, " ", i
, t
[i
] ) ; remove_nl(t
[i
]) ; lower_case_str( t
[i
] ) ;
193 if ( COMPARE2( "contains_i1_declarations", t
[0] ) ) {
194 contains_i1_declarations
= 1 ;
195 } else if ( COMPARE2( "sourcefile" , t
[0] ) ) {
196 strcpy ( sourcefile
, t
[1] ) ;
197 } else if ( COMPARE2( "arg" , t
[0] ) ) {
199 if ( COMPARE2( t
[3] , vname
) && ! COMPARE2( t
[9] , "registry" ) ) {
200 argn
= atoi( t
[1] ) ;
201 printf("%3d. <b>%s</b> is dummy arg %d of %s (%s);\n", recursion_level
+1, vname
, argn
+1, rout
, sourcefile
) ;
204 sprintf(fname
,"%s/calls", DBDIR
) ;
205 strcpy( rout2
, rout
) ;
206 if (( CALLERS
= fopen( fname
, "r" )) == NULL
) return ;
207 while ( fgets( inln2
, INLINELEN
, CALLERS
) != NULL
) {
208 for ( i
= 0 ; i
< 11 ; i
++ ) {
209 strcpy( u
[i
] , "" ) ;
210 get_token_n( inln2
, " ", i
, u
[i
] ) ; remove_nl(u
[i
]) ; lower_case_str( u
[i
] ) ;
212 if ( COMPARE2( u
[2], rout2
) ) {
213 strcpy( rout
, u
[0] ) ;
214 sprintf( fname
, "%s/%s", DBDIR
, rout
) ;
215 if (( ROUT
= fopen( fname
, "r" )) == NULL
) return ;
216 strcpy ( sourcefile_caller
, "" ) ;
219 while ( fgets( inln3
, INLINELEN
, ROUT
) != NULL
) {
220 for ( i
= 0 ; i
< 11 ; i
++ ) {
221 strcpy( v
[i
] , "" ) ;
222 get_token_n( inln3
, " ", i
, v
[i
] ) ; remove_nl(v
[i
]) ; lower_case_str( v
[i
] ) ;
224 if ( COMPARE2( v
[0] , "sourcefile" ) ) {
225 strcpy( sourcefile_caller
, v
[1] ) ;
226 } else if ( COMPARE2( v
[0] , "actarg") && ( COMPARE2( v
[4] , rout2
) && atoi( v
[1] ) == argn
)) {
227 if ( callno
== 1 || sw_all
) {
228 printf(" corresponding actual arg is <b>%s</b>, arg number %d in call %d by %s (%s).<br>\n",
229 v
[6],argn
,callno
,rout2
,sourcefile_caller
) ;
231 wrfvar ( v
[6], rout
, recursion_level
+1 ) ;
232 } else if ( callno
>= 2 ) {
233 more_calls
= callno
;
239 if ( more_calls
> 1 && recursion_level
== 0 ) {
240 printf(" there are %d more calls to %s from %s. Try 'wrfvar %s %s all' to see all.\n", more_calls
, rout2
, rout
, vname
, rout2
) ;
245 } else if ( COMPARE2( t
[3] , vname
) && COMPARE2( t
[9] , "registry" ) ) {
247 sprintf(tmp
, "grid%%s", vname
) ;
248 wrfvar ( vname
, "registry", recursion_level
+1 ) ;
254 if ( found_var
== 0 ) {
255 if ( contains_i1_declarations
) {
256 /* take a look in the registry for i1 vars that might match */
257 wrfvar ( vname
, "registry_i1", recursion_level
) ; /* recursion level does not increase here, since we're checking the registry */
259 printf("%s is not an argument to %s. May be local or use-associated.\n",vname
,rout1
) ;
260 printf("%s has %d arguments\n",rout1
,nargs_rout
) ;
262 if (( ROUT
= fopen( routfile
, "r" )) == NULL
) return ;
263 while ( fgets( inln2
, INLINELEN
, ROUT
) != NULL
) {
265 /* find first non space */
266 for ( p
= inln2
; *p
; p
++ ) { if ( *p
!= ' ' ) break ; }
267 /* change multiple spaces to single space */
268 for ( q
= p
, q1
= q
, prev
= *p
; *q
; q
++ ) { if ( prev
== ' ' && *q
== ' ' ) { continue ; } else { prev
= *q
; *q1
++ = *q
; } }
269 for ( i
= 0 ; i
< 11 ; i
++ ) {
270 strcpy( r
[i
] , "" ) ;
271 get_token_n( inln2
, " ", i
, r
[i
] ) ; remove_nl(r
[i
]) ; lower_case_str( r
[i
] ) ;
273 if ( COMPARE2( r
[0] , "arg" ) ) {
276 printf("%s of type %s intent %s\n",r
[3],r
[5],r
[7]) ;
283 /* get a list of the routines this guy calls */
285 if ( recursion_level
== 0 ) {
287 if (( BBB
= fopen( routfile
, "r" )) == NULL
) return ;
288 while ( fgets( inln2
, INLINELEN
, BBB
) != NULL
) {
290 /* find first non space */
291 for ( p
= inln2
; *p
; p
++ ) { if ( *p
!= ' ' ) break ; }
292 /* change multiple spaces to single space */
293 for ( q
= p
, q1
= q
, prev
= *p
; *q
; q
++ )
294 { if ( prev
== ' ' && *q
== ' ' ) { continue ; } else { prev
= *q
; *q1
++ = *q
; } }
295 for ( i
= 0 ; i
< 11 ; i
++ ) {
296 strcpy( t
[i
] , "" ) ;
297 get_token_n( inln2
, " ", i
, t
[i
] ) ; remove_nl(t
[i
]) ; lower_case_str( t
[i
] ) ;
299 if ( COMPARE2( t
[0] , rout1
) && COMPARE2( t
[1] , "calls" ) ) {
300 strcpy( hamuna
, t
[2] ) ;
301 } else if ( COMPARE2( t
[0] , "actarg" ) && COMPARE2( t
[6] , vname
) ) {
303 printf("\n<h4>%s is an actual arg in calls to these routines from %s</h4>\n",vname
,rout1
) ;
306 sprintf(fname
,"%s/%s",DBDIR
,hamuna
) ;
307 if (( ELEF
= fopen ( fname
, "r" )) == NULL
) continue ;
308 while ( fgets( inln3
, INLINELEN
, ELEF
) != NULL
) {
310 /* find first non space */
311 for ( p
= inln3
; *p
; p
++ ) { if ( *p
!= ' ' ) break ; }
312 /* change multiple spaces to single space */
313 for ( q
= p
, q1
= q
, prev
= *p
; *q
; q
++ )
314 { if ( prev
== ' ' && *q
== ' ' ) { continue ; } else { prev
= *q
; *q1
++ = *q
; } }
315 for ( i
= 0 ; i
< 11 ; i
++ ) {
316 strcpy( u
[i
] , "" ) ;
317 get_token_n( inln3
, " ", i
, u
[i
] ) ; remove_nl(u
[i
]) ; lower_case_str( u
[i
] ) ;
319 if ( COMPARE2( u
[0] , "arg" ) && COMPARE2( u
[1] , t
[1] ) ) {
320 strcpy( darg
, u
[3] ) ;
321 strcpy( dintent
, u
[7] ) ;
326 printf(" %s (argument %d ; matching dummy arg is %s with intent %s)\n",hamuna
,atoi(t
[1])+1,darg
,dintent
) ;
339 $dbdir
= "tools/code_dbase" ;
341 if ( ! opendir( TOOLDIR
, "tools") ) {
342 print
"\nMust be in top level WRF directory\n" ;
347 if ( (scalar @ARGV
< 1 || scalar @ARGV
> 3) || (scalar @ARGV
== 1 && @ARGV
[0] ne
"rebuild") ) {
348 print
"usage: wrfvar varname routinename \n" ;
349 print
" wrfvar rebuild \n" ;
354 if ( ! open( XXX
, "$dbdir/calls" ) || $ARGV
[0] eq
"rebuild" )
356 print
"Building code database ... please wait.\n" ;
357 system( "cd tools/CodeBase ; make" ) ;
358 $rc
= system( "tools/build_codebase" ) ;
360 if ( ($rc
>> 8) == 99 ) { exit
; }
361 system( "ln -sf tools/wrfvar ." ) ;
362 system( "ln -sf tools/subinfo ." ) ;
364 if ( $ARGV
[0] eq
"rebuild" ) { exit
; }
368 $vname
= lc $ARGV
[0] ;
370 $rout1
= lc $ARGV
[1] ;
371 $recursion_level
= $ARGV
[2] ;
380 if ( substr($vv
,0,5) eq
"grid%" ) {
381 open REGISTRY
, "< Registry/Registry" or die
"cannot open Registry/Registry" ;
382 while ( <REGISTRY
> ) {
386 next
if ( $line eq
"" ) ;
387 $line
=~ s
/[ \t][ \t]*/
/g
;
389 # fill in the blanks in quote delimited strings then remove
390 # the quotes so we can split on white space
394 for ( $i
= 0 ; $i
< length($line
) ; $i
++ )
396 $ccc
= substr($line
,$i
,1) ;
397 if ( ! $inquote
&& $ccc eq
'"' ) { $inquote
= 1 ; }
398 elsif ( $inquote
&& $ccc eq
'"' ) { $inquote
= 0 ; }
399 if ( $ccc eq
" " && $inquote
) { $newline
= $newline
.$spc
; }
400 else { $newline
= $newline
.$ccc
; }
405 @r
= split ( ' ',$line
) ;
406 if ( ($r
[0] eq state
) ) {
407 if (( substr($r
[4],0,4) eq
"dyn_" &&
408 substr($r
[4],4,length($r
[4])-4)."_" eq
substr($vv
,5,length($r
[4])-4)."_" &&
409 substr($vv
,5+length($r
[4])-4+1,length($r
[2]))) eq $r
[2] ) {
415 print
"** Registry Definition: <class> $r[0] <type> $r[1] <varname> ", uc $r
[2]," <decription> \"$r[9]\" <units> \"$r[10]\"\n"
423 $routfile
= $dbdir
."/".$rout
;
424 open ROUT
, "< $routfile" or die
"can not open $routfile" ;
434 if ( $t
[0] eq
"sourcefile" ) {
435 $sourcefile
= $t
[1] ;
436 } elsif ( $t
[0] eq
"arg" ) {
438 if ( $t
[3] eq $vname
&& $t
[9] ne
"registry" ) {
440 print
" ",uc $vname
," is dummy argument $argn of $rout ($sourcefile)\n" ;
443 system( "sort -u $dbdir/calls > /tmp/wrfvar-sort ; /bin/mv /tmp/wrfvar-sort $dbdir/calls" ) ;
444 open CALLERS
, "< $dbdir/calls" ;
446 while ( <CALLERS
> ) {
448 if ( $u
[2] eq $rout2
)
451 $routfile
= $dbdir
."/".$rout
;
452 open ROUT
, "< $routfile" or die
"can not open $routfile" ;
453 $sourcefile_caller
= "" ;
457 if ( $v
[0] eq
"sourcefile" ) {
458 $sourcefile_caller
= $v
[1] ;
459 } elsif ( $v
[0] eq
'actarg' && $v
[4] eq $rout2
&& $v
[1] eq $argn
) {
460 print ucfirst $rout2
," call $callno by $rout ($sourcefile_caller) with actual argument $argn: ",uc $v
[6],"\n" ;
463 ############## RECURSION ##############
464 @sysargs
= ( "tools/wrfvar" , $v
[6], $rout
, $recursion_level
+1 ) ;
472 } elsif ( $t
[3] eq $vname
&& $t
[9] eq
"registry" ) {
473 @sysargs
= ( "tools/wrfvar" , "grid%".$vname
, "registry", $recursion_level
+1 ) ;
474 ############## RECURSION ##############
481 if ( $found_var
== 0 ) {
482 print uc $vname
, " is not an argument to ${rout1}. May be local or use-associated.\n" ;
483 print ucfirst $rout1
," has $nargs_rout arguments.\n" ;
485 open ROUT
, "< $routfile" or die
"can not open $routfile" ;
491 if ( $t
[0] eq
"arg" ) {
494 print uc $t
[3]," of type ", uc $t
[5],", intent ",uc $t
[7],"\n" ;
500 # get a list of the routines this guy calls
502 if ( $recursion_level
== 0 ) {
504 open BBB
, "< $dbdir/$rout1" or die
" cannot open $dbdir/$rout1" ;
507 if ( $t
[0] eq
"$rout1" && $t
[1] eq calls
) {
509 } elsif ( $t
[0] eq
"actarg" && $t
[6] eq $vname1
) {
510 if ( $first_time
== 1 ) {
511 print
"\n",uc $vname1
," is an actual argument in calls to these routines from ",uc $rout1
," :\n" ;
514 open ELEF
,"< $dbdir/$hamuna" or die
"cannot open $dbdir/$hamuna" ;
517 if ( $u
[0] eq arg
&& $u
[1] eq $t
[1] ) {
523 print
" ", $hamuna
," (argument ",$t
[1]+1," ; matching dummy arg is ",uc $darg
," with intent ",uc $dintent
,") \n" ;