Bugfix: memory overwrite bug.
[wine/multimedia.git] / tools / makedep.c
blobc45eb0c50c830353e5158b026ac1bd1dc109a604
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 *name = strrchr( pFile->name, '/' );
265 char *obj = xstrdup( name ? name + 1 : pFile->name );
266 char *ext = strrchr( obj, '.' );
267 if (ext)
269 if (!strcmp( ext, ".y" )) /* yacc file */
271 fprintf( file, "y.tab.o: y.tab.c" );
272 *column += 16;
274 else if (!strcmp( ext, ".l" )) /* lex file */
276 fprintf( file, "lex.yy.o: lex.yy.c" );
277 *column += 18;
279 else if (!strcmp( ext, ".rc" )) /* resource file */
281 *ext = '\0';
282 fprintf( file, "%s.s: %s", obj, pFile->filename );
283 *column += 2 * strlen(obj) + strlen(pFile->filename) + 7;
285 else
287 strcpy( ext, ".o" );
288 fprintf( file, "%s: %s", obj, pFile->filename );
289 *column += strlen(obj) + strlen(pFile->filename) + 2;
292 free( obj );
296 /*******************************************************************
297 * output_dependencies
299 static void output_dependencies(void)
301 INCL_FILE *pFile;
302 int i, column;
303 FILE *file = NULL;
304 char buffer[1024];
306 if (Separator && ((file = fopen( OutputFileName, "r+" ))))
308 while (fgets( buffer, sizeof(buffer), file ))
309 if (!strncmp( buffer, Separator, strlen(Separator) )) break;
310 ftruncate( fileno(file), ftell(file) );
311 fseek( file, 0L, SEEK_END );
313 if (!file)
315 if (!(file = fopen( OutputFileName, "a" )))
317 perror( OutputFileName );
318 exit(1);
321 for( pFile = firstSrc; pFile; pFile = pFile->next)
323 column = 0;
324 output_src( file, pFile, &column );
325 for (i = 0; i < MAX_INCLUDES; i++)
326 if (pFile->files[i]) output_include( file, pFile->files[i],
327 pFile, &column );
328 fprintf( file, "\n" );
330 fclose(file);
334 /*******************************************************************
335 * parse_option
337 static void parse_option( const char *opt )
339 switch(opt[1])
341 case 'I':
342 if (opt[2]) add_include_path( opt + 2 );
343 break;
344 case 'C':
345 if (opt[2]) SrcDir = opt + 2;
346 else SrcDir = NULL;
347 break;
348 case 'f':
349 if (opt[2]) OutputFileName = opt + 2;
350 break;
351 case 's':
352 if (opt[2]) Separator = opt + 2;
353 else Separator = NULL;
354 break;
355 default:
356 fprintf( stderr, "Unknown option '%s'\n", opt );
357 fprintf( stderr, Usage, ProgramName );
358 exit(1);
363 /*******************************************************************
364 * main
366 int main( int argc, char *argv[] )
368 INCL_FILE *pFile;
370 ProgramName = argv[0];
371 while (argc > 1)
373 if (*argv[1] == '-') parse_option( argv[1] );
374 else
376 pFile = add_src_file( argv[1] );
377 parse_file( pFile, 1 );
379 argc--;
380 argv++;
382 for (pFile = firstInclude; pFile; pFile = pFile->next)
383 parse_file( pFile, 0 );
384 output_dependencies();
385 return 0;