Revived the GEN_C_SRCS variable to support wrc lex/yacc sources.
[wine/multimedia.git] / tools / makedep.c
blob11cbc8d97822c69125f40ab173c4e95b9aba5431
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 );
232 fclose(file);
236 /*******************************************************************
237 * output_include
239 static void output_include( FILE *file, INCL_FILE *pFile,
240 INCL_FILE *owner, int *column )
242 int i;
244 if (pFile->owner == owner) return;
245 pFile->owner = owner;
246 if (*column + strlen(pFile->filename) + 1 > 70)
248 fprintf( file, " \\\n" );
249 *column = 0;
251 fprintf( file, " %s", pFile->filename );
252 *column += strlen(pFile->filename) + 1;
253 for (i = 0; i < MAX_INCLUDES; i++)
254 if (pFile->files[i]) output_include( file, pFile->files[i],
255 owner, column );
259 /*******************************************************************
260 * output_src
262 static void output_src( FILE *file, INCL_FILE *pFile, int *column )
264 char *obj = xstrdup( pFile->name );
265 char *ext = strrchr( obj, '.' );
266 if (ext)
268 if (!strcmp( ext, ".y" )) /* yacc file */
270 fprintf( file, "y.tab.o: y.tab.c" );
271 *column += 16;
273 else if (!strcmp( ext, ".l" )) /* lex file */
275 fprintf( file, "lex.yy.o: lex.yy.c" );
276 *column += 18;
278 else if (!strcmp( ext, ".rc" )) /* resource file */
280 strcpy( ext, ".s" );
281 fprintf( file, "%s: %s", obj, pFile->filename );
282 *column += strlen(obj) + strlen(pFile->filename);
284 else
286 strcpy( ext, ".o" );
287 fprintf( file, "%s: %s", obj, pFile->filename );
288 *column += strlen(obj) + strlen(pFile->filename) + 2;
291 free( obj );
295 /*******************************************************************
296 * output_dependencies
298 static void output_dependencies(void)
300 INCL_FILE *pFile;
301 int i, column;
302 FILE *file = NULL;
303 char buffer[1024];
305 if (Separator && ((file = fopen( OutputFileName, "r+" ))))
307 while (fgets( buffer, sizeof(buffer), file ))
308 if (!strncmp( buffer, Separator, strlen(Separator) )) break;
309 ftruncate( fileno(file), ftell(file) );
310 fseek( file, 0L, SEEK_END );
312 if (!file)
314 if (!(file = fopen( OutputFileName, "a" )))
316 perror( OutputFileName );
317 exit(1);
320 for( pFile = firstSrc; pFile; pFile = pFile->next)
322 column = 0;
323 output_src( file, pFile, &column );
324 for (i = 0; i < MAX_INCLUDES; i++)
325 if (pFile->files[i]) output_include( file, pFile->files[i],
326 pFile, &column );
327 fprintf( file, "\n" );
329 fclose(file);
333 /*******************************************************************
334 * parse_option
336 static void parse_option( const char *opt )
338 switch(opt[1])
340 case 'I':
341 if (opt[2]) add_include_path( opt + 2 );
342 break;
343 case 'C':
344 if (opt[2]) SrcDir = opt + 2;
345 else SrcDir = NULL;
346 break;
347 case 'f':
348 if (opt[2]) OutputFileName = opt + 2;
349 break;
350 case 's':
351 if (opt[2]) Separator = opt + 2;
352 else Separator = NULL;
353 break;
354 default:
355 fprintf( stderr, "Unknown option '%s'\n", opt );
356 fprintf( stderr, Usage, ProgramName );
357 exit(1);
362 /*******************************************************************
363 * main
365 int main( int argc, char *argv[] )
367 INCL_FILE *pFile;
369 ProgramName = argv[0];
370 while (argc > 1)
372 if (*argv[1] == '-') parse_option( argv[1] );
373 else
375 pFile = add_src_file( argv[1] );
376 parse_file( pFile, 1 );
378 argc--;
379 argv++;
381 for (pFile = firstInclude; pFile; pFile = pFile->next)
382 parse_file( pFile, 0 );
383 output_dependencies();
384 return 0;