Added sample config file in the new format.
[wine/multimedia.git] / tools / makedep.c
blob97d25416efe76ab86059a734ebd301138195eb19
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 *included_by; /* file that included this one */
22 int included_line; /* line where this file was included */
23 struct _INCL_FILE *owner;
24 struct _INCL_FILE *files[MAX_INCLUDES];
25 } INCL_FILE;
27 static INCL_FILE *firstSrc;
28 static INCL_FILE *firstInclude;
30 typedef struct _INCL_PATH
32 struct _INCL_PATH *next;
33 const char *name;
34 } INCL_PATH;
36 static INCL_PATH *firstPath;
38 static const char *SrcDir = NULL;
39 static const char *OutputFileName = "Makefile";
40 static const char *Separator = "### Dependencies";
41 static const char *ProgramName;
43 static const char Usage[] =
44 "Usage: %s [options] [files]\n"
45 "Options:\n"
46 " -Idir Search for include files in directory 'dir'\n"
47 " -Cdir Search for source files in directory 'dir'\n"
48 " -fxxx Store output in file 'xxx' (default: Makefile)\n"
49 " -sxxx Use 'xxx' as separator (default: \"### Dependencies\")\n";
52 /*******************************************************************
53 * xmalloc
55 static void *xmalloc( int size )
57 void *res;
58 if (!(res = malloc (size ? size : 1)))
60 fprintf( stderr, "%s: Virtual memory exhausted.\n", ProgramName );
61 exit(1);
63 return res;
67 /*******************************************************************
68 * xstrdup
70 static char *xstrdup( const char *str )
72 char *res = strdup( str );
73 if (!res)
75 fprintf( stderr, "%s: Virtual memory exhausted.\n", ProgramName );
76 exit(1);
78 return res;
82 /*******************************************************************
83 * is_generated
85 * Test if a given file type is generated during the make process
87 static int is_generated( const char *name )
89 static const char * const extensions[] = { ".tab.h", ".mc.rc" };
90 size_t i, len = strlen(name);
91 for (i = 0; i < sizeof(extensions)/sizeof(extensions[0]); i++)
93 if (len <= strlen(extensions[i])) continue;
94 if (!strcmp( name + len - strlen(extensions[i]), extensions[i] )) return 1;
96 return 0;
99 /*******************************************************************
100 * add_include_path
102 * Add a directory to the include path.
104 static void add_include_path( const char *name )
106 INCL_PATH *path = xmalloc( sizeof(*path) );
107 INCL_PATH **p = &firstPath;
108 while (*p) p = &(*p)->next;
109 *p = path;
110 path->next = NULL;
111 path->name = name;
115 /*******************************************************************
116 * add_src_file
118 * Add a source file to the list.
120 static INCL_FILE *add_src_file( const char *name )
122 INCL_FILE **p = &firstSrc;
123 INCL_FILE *file = xmalloc( sizeof(*file) );
124 memset( file, 0, sizeof(*file) );
125 file->name = xstrdup(name);
126 while (*p) p = &(*p)->next;
127 *p = file;
128 return file;
132 /*******************************************************************
133 * add_include
135 * Add an include file if it doesn't already exists.
137 static INCL_FILE *add_include( INCL_FILE *pFile, const char *name, int line )
139 INCL_FILE **p = &firstInclude;
140 int pos;
142 for (pos = 0; pos < MAX_INCLUDES; pos++) if (!pFile->files[pos]) break;
143 if (pos >= MAX_INCLUDES)
145 fprintf( stderr, "%s: %s: too many included files, please fix MAX_INCLUDES\n",
146 ProgramName, pFile->name );
147 exit(1);
150 while (*p && strcmp( name, (*p)->name )) p = &(*p)->next;
151 if (!*p)
153 *p = xmalloc( sizeof(INCL_FILE) );
154 memset( *p, 0, sizeof(INCL_FILE) );
155 (*p)->name = xstrdup(name);
156 (*p)->included_by = pFile;
157 (*p)->included_line = line;
159 pFile->files[pos] = *p;
160 return *p;
164 /*******************************************************************
165 * open_src_file
167 static FILE *open_src_file( INCL_FILE *pFile )
169 FILE *file;
171 if (SrcDir)
173 pFile->filename = xmalloc( strlen(SrcDir) + strlen(pFile->name) + 2 );
174 strcpy( pFile->filename, SrcDir );
175 strcat( pFile->filename, "/" );
176 strcat( pFile->filename, pFile->name );
178 else pFile->filename = xstrdup( pFile->name );
180 if (!(file = fopen( pFile->filename, "r" )))
182 perror( pFile->filename );
183 exit(1);
185 return file;
189 /*******************************************************************
190 * open_include_file
192 static FILE *open_include_file( INCL_FILE *pFile )
194 FILE *file = NULL;
195 INCL_PATH *path;
197 for (path = firstPath; path; path = path->next)
199 char *filename = xmalloc(strlen(path->name) + strlen(pFile->name) + 2);
200 strcpy( filename, path->name );
201 strcat( filename, "/" );
202 strcat( filename, pFile->name );
203 if ((file = fopen( filename, "r" )))
205 pFile->filename = filename;
206 break;
208 free( filename );
210 if (!file)
212 if (firstPath) perror( pFile->name );
213 else fprintf( stderr, "%s: %s: File not found\n",
214 ProgramName, pFile->name );
215 while (pFile->included_by)
217 fprintf( stderr, " %s was first included from %s:%d\n",
218 pFile->name, pFile->included_by->name, pFile->included_line );
219 pFile = pFile->included_by;
221 exit(1);
223 return file;
227 /*******************************************************************
228 * parse_file
230 static void parse_file( INCL_FILE *pFile, int src )
232 char buffer[1024];
233 char *include;
234 int line = 0;
235 FILE *file;
237 if (is_generated( pFile->name ))
239 /* file is generated during make, don't try to open it */
240 pFile->filename = xstrdup( pFile->name );
241 return;
244 file = src ? open_src_file( pFile ) : open_include_file( pFile );
246 while (fgets( buffer, sizeof(buffer)-1, file ))
248 char *p = buffer;
249 line++;
250 while (*p && isspace(*p)) p++;
251 if (*p++ != '#') continue;
252 while (*p && isspace(*p)) p++;
253 if (strncmp( p, "include", 7 )) continue;
254 p += 7;
255 while (*p && isspace(*p)) p++;
256 if (*p++ != '\"') continue;
257 include = p;
258 while (*p && (*p != '\"')) p++;
259 if (!*p)
261 fprintf( stderr, "%s:%d: Malformed #include directive\n",
262 pFile->filename, line );
263 exit(1);
265 *p = 0;
266 add_include( pFile, include, line );
268 fclose(file);
272 /*******************************************************************
273 * output_include
275 static void output_include( FILE *file, INCL_FILE *pFile,
276 INCL_FILE *owner, int *column )
278 int i;
280 if (pFile->owner == owner) return;
281 pFile->owner = owner;
282 if (*column + strlen(pFile->filename) + 1 > 70)
284 fprintf( file, " \\\n" );
285 *column = 0;
287 fprintf( file, " %s", pFile->filename );
288 *column += strlen(pFile->filename) + 1;
289 for (i = 0; i < MAX_INCLUDES; i++)
290 if (pFile->files[i]) output_include( file, pFile->files[i],
291 owner, column );
295 /*******************************************************************
296 * output_src
298 static void output_src( FILE *file, INCL_FILE *pFile, int *column )
300 char *obj = xstrdup( pFile->name );
301 char *ext = strrchr( obj, '.' );
302 if (ext && strchr( ext, '/' )) ext = NULL;
303 if (ext)
305 *ext++ = 0;
306 if (!strcmp( ext, "y" )) /* yacc file */
308 *column += fprintf( file, "y.tab.o: y.tab.c" );
310 else if (!strcmp( ext, "l" )) /* lex file */
312 *column += fprintf( file, "lex.yy.o: lex.yy.c" );
314 else if (!strcmp( ext, "rc" )) /* resource file */
316 *column += fprintf( file, "%s.res: %s", obj, pFile->filename );
318 else if (!strcmp( ext, "mc" )) /* message file */
320 *column += fprintf( file, "%s.mc.rc: %s", obj, pFile->filename );
322 else
324 *column += fprintf( file, "%s.o: %s", obj, pFile->filename );
327 free( obj );
331 /*******************************************************************
332 * output_dependencies
334 static void output_dependencies(void)
336 INCL_FILE *pFile;
337 int i, column;
338 FILE *file = NULL;
339 char buffer[1024];
341 if (Separator && ((file = fopen( OutputFileName, "r+" ))))
343 while (fgets( buffer, sizeof(buffer), file ))
344 if (!strncmp( buffer, Separator, strlen(Separator) )) break;
345 ftruncate( fileno(file), ftell(file) );
346 fseek( file, 0L, SEEK_END );
348 if (!file)
350 if (!(file = fopen( OutputFileName, Separator ? "a" : "w" )))
352 perror( OutputFileName );
353 exit(1);
356 for( pFile = firstSrc; pFile; pFile = pFile->next)
358 column = 0;
359 output_src( file, pFile, &column );
360 for (i = 0; i < MAX_INCLUDES; i++)
361 if (pFile->files[i]) output_include( file, pFile->files[i],
362 pFile, &column );
363 fprintf( file, "\n" );
365 fclose(file);
369 /*******************************************************************
370 * parse_option
372 static void parse_option( const char *opt )
374 switch(opt[1])
376 case 'I':
377 if (opt[2]) add_include_path( opt + 2 );
378 break;
379 case 'C':
380 if (opt[2]) SrcDir = opt + 2;
381 else SrcDir = NULL;
382 break;
383 case 'f':
384 if (opt[2]) OutputFileName = opt + 2;
385 break;
386 case 's':
387 if (opt[2]) Separator = opt + 2;
388 else Separator = NULL;
389 break;
390 default:
391 fprintf( stderr, "Unknown option '%s'\n", opt );
392 fprintf( stderr, Usage, ProgramName );
393 exit(1);
398 /*******************************************************************
399 * main
401 int main( int argc, char *argv[] )
403 INCL_FILE *pFile;
405 ProgramName = argv[0];
406 while (argc > 1)
408 if (*argv[1] == '-') parse_option( argv[1] );
409 else
411 pFile = add_src_file( argv[1] );
412 parse_file( pFile, 1 );
414 argc--;
415 argv++;
417 for (pFile = firstInclude; pFile; pFile = pFile->next)
418 parse_file( pFile, 0 );
419 if( firstSrc ) output_dependencies();
420 return 0;