8 #define snprintf _snprintf
11 typedef struct _stub
{
17 void usage( char *name
) {
19 "Usage: %s [-n nm] [-m make] libs...\n"
20 "nm -- The command used to run nm on reactos objects\n"
21 "make -- The command used to build reactos\n\n"
22 "libs are import libraries (.a files) typically from\n"
23 "dk/lib/nkm and dk/lib/w32\n",
27 int main( int argc
, char **argv
) {
31 char *origin
= "unknown.a";
32 stub
*functions
= NULL
, *new_f
, *imports
= NULL
, *search
;
34 int i
, libstart
= argc
;
35 FILE *out
= fopen("tests/stubs.tst","w");
37 if( argc
== 1 ) { usage(argv
[0]); return 1; }
40 fprintf( stderr
, "Could not write file tests/stubs.tst\n" );
44 fprintf( out
, "# Automatically generated by stubgen\n" );
46 for( i
= 1; i
< argc
; i
++ ) {
47 if( !strcmp( argv
[i
], "-m" ) ) {
50 } else if( !strcmp( argv
[i
], "-n" ) ) {
53 } else { libstart
= i
; break; }
56 snprintf( line
, sizeof(line
), "%s test 2>&1", make
);
57 make_f
= popen( line
, "r" );
61 fprintf( stderr
, "Could not run %s test\n", make
);
65 while( fgets( line
, sizeof(line
), make_f
) ) {
66 char *end_of_location
;
67 char *begin_q
, *end_q
;
69 if( !strstr( line
, "undefined reference to" ) ) continue;
71 end_of_location
= strrchr( line
, ':' );
73 if( !end_of_location
) continue;
75 begin_q
= strchr( end_of_location
, '`' );
76 end_q
= strchr( end_of_location
, '\'' );
78 if( !begin_q
|| !end_q
) continue;
80 begin_q
+= 2; /* skip `_ */
82 memmove( line
, begin_q
, end_q
- begin_q
);
83 line
[end_q
- begin_q
] = 0;
85 for( new_f
= functions
; new_f
; new_f
= new_f
->next
)
86 if( !strcmp( new_f
->name
, line
) ) break;
90 new_f
= (stub
*)malloc( sizeof(stub
) );
91 if( !new_f
) {fprintf( stderr
, "Out of memory\n" ); return 1;}
93 new_f
->name
= strdup( line
);
94 new_f
->next
= functions
;
98 /* Scan libraries and collect available import sections */
99 for( i
= libstart
; i
< argc
; i
++ ) {
100 snprintf( line
, sizeof(line
), "%s %s", nm
, argv
[i
] );
101 nm_f
= popen( line
, "r" );
103 for( origin
= argv
[i
]; *argv
[i
]; argv
[i
]++ )
104 if( *argv
[i
] == '/' || *argv
[i
] == '\\' )
105 origin
= argv
[i
] + 1;
109 fprintf( stderr
, "Could not run %s\n", line
);
113 while( fgets( line
, sizeof(line
), nm_f
) ) {
114 char *import_sign
, *eol
;
116 if( !(import_sign
= strstr( line
, " I " )) ) continue;
119 while( *import_sign
&& isspace(*import_sign
) ) import_sign
++;
121 /* Strip ws after name */
122 for( eol
= import_sign
; *eol
&& !isspace(*eol
); eol
++ );
126 for( new_f
= imports
; new_f
; new_f
= new_f
->next
)
127 if( !strcmp( new_f
->name
, import_sign
) ) break;
129 if( new_f
) continue;
131 new_f
= (stub
*)malloc( sizeof(stub
) );
132 if( !new_f
) {fprintf( stderr
, "Out of memory\n" ); return 1;}
134 new_f
->name
= strdup( import_sign
+ 1 );
135 new_f
->origin
= origin
;
136 new_f
->next
= imports
;
143 /* Now we have a list of unique functions and a list of imports,
144 lookup each function and output the entry from the import list. */
145 for( new_f
= functions
; new_f
; new_f
= new_f
->next
) {
146 for( search
= imports
; search
; search
= search
->next
) {
147 if( !strcmp( new_f
->name
, search
->name
) ) {
148 fprintf( out
, "%s %s\n", search
->origin
, search
->name
);