[FFS] Silence some only-informative KdPrints.
[reactos.git] / sdk / tools / stubgen.c
1 #include <stdio.h>
2 #include <malloc.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #ifdef _WIN32
7 #define popen _popen
8 #define snprintf _snprintf
9 #endif
10
11 typedef struct _stub {
12 char *name;
13 char *origin;
14 struct _stub *next;
15 } stub;
16
17 void usage( char *name ) {
18 fprintf( stderr,
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",
24 name );
25 }
26
27 int main( int argc, char **argv ) {
28 char line[1024];
29 char *make = "make";
30 char *nm = "nm";
31 char *origin = "unknown.a";
32 stub *functions = NULL, *new_f, *imports = NULL, *search;
33 FILE *make_f, *nm_f;
34 int i, libstart = argc;
35 FILE *out = fopen("tests/stubs.tst","w");
36
37 if( argc == 1 ) {
38 if( out ) fclose( out );
39 usage(argv[0]);
40 return 1;
41 }
42
43 if( !out ) {
44 fprintf( stderr, "Could not write file tests/stubs.tst\n" );
45 return 1;
46 }
47
48 fprintf( out, "# Automatically generated by stubgen\n" );
49
50 for( i = 1; i < argc; i++ ) {
51 if( !strcmp( argv[i], "-m" ) ) {
52 make = argv[i+1];
53 i++;
54 } else if( !strcmp( argv[i], "-n" ) ) {
55 nm = argv[i+1];
56 i++;
57 } else { libstart = i; break; }
58 }
59
60 snprintf( line, sizeof(line), "%s test 2>&1", make );
61 make_f = popen( line, "r" );
62
63 if( !make_f ) {
64 fclose( out );
65 fprintf( stderr, "Could not run %s test\n", make );
66 return 1;
67 }
68
69 while( fgets( line, sizeof(line), make_f ) ) {
70 char *end_of_location;
71 char *begin_q, *end_q;
72
73 if( !strstr( line, "undefined reference to" ) ) continue;
74
75 end_of_location = strrchr( line, ':' );
76
77 if( !end_of_location ) continue;
78
79 begin_q = strchr( end_of_location, '`' );
80 end_q = strchr( end_of_location, '\'' );
81
82 if( !begin_q || !end_q ) continue;
83
84 begin_q += 2; /* skip `_ */
85
86 memmove( line, begin_q, end_q - begin_q );
87 line[end_q - begin_q] = 0;
88
89 for( new_f = functions; new_f; new_f = new_f->next )
90 if( !strcmp( new_f->name, line ) ) break;
91
92 if( new_f ) continue;
93
94 new_f = (stub *)malloc( sizeof(stub) );
95 if( !new_f )
96 {
97 fprintf( stderr, "Out of memory\n" );
98 fclose( out );
99 pclose( make_f );
100 return 1;
101 }
102
103 new_f->name = strdup( line );
104 new_f->next = functions;
105 functions = new_f;
106 }
107
108 /* Scan libraries and collect available import sections */
109 for( i = libstart; i < argc; i++ ) {
110 snprintf( line, sizeof(line), "%s %s", nm, argv[i] );
111 nm_f = popen( line, "r" );
112
113 for( origin = argv[i]; *argv[i]; argv[i]++ )
114 if( *argv[i] == '/' || *argv[i] == '\\' )
115 origin = argv[i] + 1;
116
117
118 if( !nm_f ) {
119 fprintf( stderr, "Could not run %s\n", line );
120 continue;
121 }
122
123 while( fgets( line, sizeof(line), nm_f ) ) {
124 char *import_sign, *eol;
125
126 if( !(import_sign = strstr( line, " I " )) ) continue;
127
128 import_sign += 3;
129 while( *import_sign && isspace(*import_sign) ) import_sign++;
130
131 /* Strip ws after name */
132 for( eol = import_sign; *eol && !isspace(*eol); eol++ );
133
134 *eol = 0;
135
136 for( new_f = imports; new_f; new_f = new_f->next )
137 if( !strcmp( new_f->name, import_sign ) ) break;
138
139 if( new_f ) continue;
140
141 new_f = (stub *)malloc( sizeof(stub) );
142 if( !new_f )
143 {
144 fprintf( stderr, "Out of memory\n" );
145 fclose( out );
146 pclose( make_f );
147 pclose( nm_f );
148 return 1;
149 }
150
151 new_f->name = strdup( import_sign + 1 );
152 new_f->origin = origin;
153 new_f->next = imports;
154 imports = new_f;
155 }
156
157 pclose( nm_f );
158 }
159
160 /* Now we have a list of unique functions and a list of imports,
161 lookup each function and output the entry from the import list. */
162 for( new_f = functions; new_f; new_f = new_f->next ) {
163 for( search = imports; search; search = search->next ) {
164 if( !strcmp( new_f->name, search->name ) ) {
165 fprintf( out, "%s %s\n", search->origin, search->name );
166 continue;
167 }
168 }
169 }
170
171 fclose( out );
172 pclose( make_f );
173 return 0;
174 }