Release 961023
[wine/multimedia.git] / tools / makedep.c
blob1d1bf3adddb4f5737916ba4fa0fdeb60372c4001
1 /*
2 * Generate include file dependencies
4 * Copyright 1996 Alexandre Julliard
5 */
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
13 /* Max first-level includes per file */
14 #define MAX_INCLUDES 124
16 typedef struct _INCL_FILE
18 struct _INCL_FILE *next;
19 char *name;
20 char *filename;
21 struct _INCL_FILE *owner;
22 struct _INCL_FILE *files[MAX_INCLUDES];
23 } INCL_FILE;
25 static INCL_FILE *firstSrc;
26 static INCL_FILE *firstInclude;
28 typedef struct _INCL_PATH
30 struct _INCL_PATH *next;
31 const char *name;
32 } INCL_PATH;
34 static INCL_PATH *firstPath;
36 static const char *SrcDir = NULL;
37 static const char *OutputFileName = "Makefile";
38 static const char *Separator = "### Dependencies";
39 static const char *ProgramName;
41 static const char Usage[] =
42 "Usage: %s [options] [files]\n"
43 "Options:\n"
44 " -Idir Search for include files in directory 'dir'\n"
45 " -Cdir Search for source files in directory 'dir'\n"
46 " -fxxx Store output in file 'xxx' (default: Makefile)\n"
47 " -sxxx Use 'xxx' as separator (default: \"### Dependencies\")\n";
50 /*******************************************************************
51 * xmalloc
53 static void *xmalloc( int size )
55 void *res;
56 if (!(res = malloc (size ? size : 1)))
58 fprintf( stderr, "%s: Virtual memory exhausted.\n", ProgramName );
59 exit(1);
61 return res;
65 /*******************************************************************
66 * xstrdup
68 static char *xstrdup( const char *str )
70 char *res = strdup( str );
71 if (!res)
73 fprintf( stderr, "%s: Virtual memory exhausted.\n", ProgramName );
74 exit(1);
76 return res;
80 /*******************************************************************
81 * add_include_path
83 * Add a directory to the include path.
85 static void add_include_path( const char *name )
87 INCL_PATH *path = xmalloc( sizeof(*path) );
88 INCL_PATH **p = &firstPath;
89 while (*p) p = &(*p)->next;
90 *p = path;
91 path->next = NULL;
92 path->name = name;
96 /*******************************************************************
97 * add_src_file
99 * Add a source file to the list.
101 static INCL_FILE *add_src_file( const char *name )
103 INCL_FILE **p = &firstSrc;
104 INCL_FILE *file = xmalloc( sizeof(*file) );
105 memset( file, 0, sizeof(*file) );
106 file->name = xstrdup(name);
107 while (*p) p = &(*p)->next;
108 *p = file;
109 return file;
113 /*******************************************************************
114 * add_include
116 * Add an include file if it doesn't already exists.
118 static INCL_FILE *add_include( INCL_FILE *pFile, const char *name )
120 INCL_FILE **p = &firstInclude;
121 int pos;
123 for (pos = 0; pos < MAX_INCLUDES; pos++) if (!pFile->files[pos]) break;
124 if (pos >= MAX_INCLUDES)
126 fprintf( stderr, "%s: %s: too many included files, please fix MAX_INCLUDES\n",
127 ProgramName, pFile->name );
128 exit(1);
131 while (*p && strcmp( name, (*p)->name )) p = &(*p)->next;
132 if (!*p)
134 *p = xmalloc( sizeof(INCL_FILE) );
135 memset( *p, 0, sizeof(INCL_FILE) );
136 (*p)->name = xstrdup(name);
138 pFile->files[pos] = *p;
139 return *p;
143 /*******************************************************************
144 * open_src_file
146 static FILE *open_src_file( INCL_FILE *pFile )
148 FILE *file;
150 if (SrcDir)
152 pFile->filename = xmalloc( strlen(SrcDir) + strlen(pFile->name) + 2 );
153 strcpy( pFile->filename, SrcDir );
154 strcat( pFile->filename, "/" );
155 strcat( pFile->filename, pFile->name );
157 else pFile->filename = xstrdup( pFile->name );
159 if (!(file = fopen( pFile->filename, "r" )))
161 perror( pFile->filename );
162 exit(1);
164 return file;
168 /*******************************************************************
169 * open_include_file
171 static FILE *open_include_file( INCL_FILE *pFile )
173 FILE *file = NULL;
174 INCL_PATH *path;
176 for (path = firstPath; path; path = path->next)
178 char *filename = xmalloc(strlen(path->name) + strlen(pFile->name) + 2);
179 strcpy( filename, path->name );
180 strcat( filename, "/" );
181 strcat( filename, pFile->name );
182 if ((file = fopen( filename, "r" )))
184 pFile->filename = filename;
185 break;
187 free( filename );
189 if (!file)
191 if (firstPath) perror( pFile->name );
192 else fprintf( stderr, "%s: %s: File not found\n",
193 ProgramName, pFile->name );
194 exit(1);
196 return file;
200 /*******************************************************************
201 * parse_file
203 static void parse_file( INCL_FILE *pFile, int src )
205 char buffer[1024];
206 char *include;
207 int line = 0;
209 FILE *file = src ? open_src_file( pFile ) : open_include_file( pFile );
210 while (fgets( buffer, sizeof(buffer)-1, file ))
212 char *p = buffer;
213 line++;
214 while (*p && isspace(*p)) p++;
215 if (*p++ != '#') continue;
216 while (*p && isspace(*p)) p++;
217 if (strncmp( p, "include", 7 )) continue;
218 p += 7;
219 while (*p && isspace(*p)) p++;
220 if (*p++ != '\"') continue;
221 include = p;
222 while (*p && (*p != '\"')) p++;
223 if (!*p)
225 fprintf( stderr, "%s:%d: Malformed #include directive\n",
226 pFile->filename, line );
227 exit(1);
229 *p = 0;
230 add_include( pFile, include );
235 /*******************************************************************
236 * output_include
238 static void output_include( FILE *file, INCL_FILE *pFile,
239 INCL_FILE *owner, int *column )
241 int i;
243 if (pFile->owner == owner) return;
244 pFile->owner = owner;
245 if (*column + strlen(pFile->filename) + 1 > 70)
247 fprintf( file, " \\\n" );
248 *column = 0;
250 fprintf( file, " %s", pFile->filename );
251 *column += strlen(pFile->filename) + 1;
252 for (i = 0; i < MAX_INCLUDES; i++)
253 if (pFile->files[i]) output_include( file, pFile->files[i],
254 owner, column );
258 /*******************************************************************
259 * output_dependencies
261 static void output_dependencies(void)
263 INCL_FILE *pFile;
264 int i, column;
265 FILE *file = NULL;
266 char buffer[1024];
268 if (Separator && ((file = fopen( OutputFileName, "r+" ))))
270 while (fgets( buffer, sizeof(buffer), file ))
271 if (!strncmp( buffer, Separator, strlen(Separator) )) break;
272 ftruncate( fileno(file), ftell(file) );
274 if (!file)
276 if (!(file = fopen( OutputFileName, "a" )))
278 perror( OutputFileName );
279 exit(1);
282 for( pFile = firstSrc; pFile; pFile = pFile->next)
284 char *name = strrchr( pFile->name, '/' );
285 char *obj = xstrdup( name ? name + 1 : pFile->name );
286 char *ext = strrchr( obj, '.' );
287 if (ext) strcpy( ext, ".o" );
288 fprintf( file, "%s: %s", obj, pFile->filename );
289 column = strlen(obj) + strlen(pFile->filename) + 2;
290 free( obj );
291 for (i = 0; i < MAX_INCLUDES; i++)
292 if (pFile->files[i]) output_include( file, pFile->files[i],
293 pFile, &column );
294 fprintf( file, "\n" );
299 /*******************************************************************
300 * parse_option
302 static void parse_option( const char *opt )
304 switch(opt[1])
306 case 'I':
307 if (opt[2]) add_include_path( opt + 2 );
308 break;
309 case 'C':
310 if (opt[2]) SrcDir = opt + 2;
311 else SrcDir = NULL;
312 break;
313 case 'f':
314 if (opt[2]) OutputFileName = opt + 2;
315 break;
316 case 's':
317 if (opt[2]) Separator = opt + 2;
318 else Separator = NULL;
319 break;
320 default:
321 fprintf( stderr, "Unknown option '%s'\n", opt );
322 fprintf( stderr, Usage, ProgramName );
323 exit(1);
328 /*******************************************************************
329 * main
331 int main( int argc, char *argv[] )
333 INCL_FILE *pFile;
335 ProgramName = argv[0];
336 while (argc > 1)
338 if (*argv[1] == '-') parse_option( argv[1] );
339 else
341 pFile = add_src_file( argv[1] );
342 parse_file( pFile, 1 );
344 argc--;
345 argv++;
347 for (pFile = firstInclude; pFile; pFile = pFile->next)
348 parse_file( pFile, 0 );
349 output_dependencies();
350 return 0;