2 /*---------------------------------------------------------------------------*\
4 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
6 \\ / A nd | Copyright held by original author
8 ------------------------------------------------------------------------------
10 This file is part of OpenFOAM.
12 OpenFOAM is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2 of the License, or (at your
15 option) any later version.
17 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 You should have received a copy of the GNU General Public License
23 along with OpenFOAM; if not, write to the Free Software Foundation,
24 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 A fast dependency list generator that emulates the behaviour and
31 output of cpp -M. However, the output contains no duplications and
32 is ~40% faster than cpp.
34 The algorithm uses flex to scan for includes and searches the files
35 found. Each file is entered into a hash table so that files are scanned
36 only once. This is why this program is faster than cpp.
39 wmkdep [ -Idirectory ... -Idirectory ] filename
41 \*---------------------------------------------------------------------------*/
43 #define FILE_STACK_SIZE 300
44 #define HASH_TABLE_SIZE 500
48 #include <sys/types.h>
51 void nextFile(const char* fileName);
52 void importFile(const char* fileName);
53 void importDirectory(const char* dirName);
55 # undef yywrap /* sometimes a macro by default */
59 %x CMNT CFNAME SCFNAME JFNAME FFNAME
62 "//".*\n ; /* remove c++ style one line comments */
64 "/*" BEGIN(CMNT); /* start removing c style comment */
66 <CMNT>"*/" BEGIN(INITIAL); /* end removing c style comment */
68 ^[ \t]*#[ \t]*include[ \t]+\" BEGIN(CFNAME); /* c-file name */
69 <CFNAME>[^"\n ]* { BEGIN(INITIAL); nextFile(yytext); } /*"*/
71 ^[ \t]*import[ \t]+ BEGIN(JFNAME); /* java-file name */
72 <JFNAME>java.*; BEGIN(INITIAL);
73 <JFNAME>org.*; BEGIN(INITIAL);
74 <JFNAME>com.*; BEGIN(INITIAL);
75 <JFNAME>sunw.*; BEGIN(INITIAL);
76 <JFNAME>sun.*; BEGIN(INITIAL);
77 <JFNAME>launcher.*; BEGIN(INITIAL);
78 <JFNAME>[^"\n*]*; { BEGIN(INITIAL); importFile(yytext); } /*"*/
79 <JFNAME>[^"\n]*\*; { BEGIN(INITIAL); importDirectory(yytext); } /*"*/
81 " "include[ \t]+\' BEGIN(FFNAME); /* FORTRAN-file name */
82 <FFNAME>[^']* { BEGIN(INITIAL); nextFile(yytext); } /*'*/
91 char* sourceFile = NULL;
92 char* sourceExt = NULL;
93 char* objectFile = NULL;
94 char* classFile = NULL;
97 int main(int argc, char* argv[])
99 char *dotPtr, *slashPtr;
104 fprintf(stderr,"input file not supplied\n");
108 sourceFile = (char*)malloc(strlen(argv[argc-1]) + 1);
109 strcpy(sourceFile, argv[argc-1]);
110 fprintf(stderr, "Making dependency list for source file %s\n", sourceFile);
113 /* Get list of -I directories. */
116 for (i = 1; i < argc; i++)
118 if (strncmp(argv[i], "-I", 2) == 0)
124 directories = (char**)malloc(sizeof(char*)*nDirectories);
128 for (i = 1; i < argc; i++)
130 if (strncmp(argv[i], "-I", 2) == 0)
132 directories[nDirectories++] = strdup(argv[i] + 2);
138 if ((dotPtr = strrchr(sourceFile, '.')) == NULL)
143 "Cannot find extension in source file name %s\n",
149 if ((slashPtr = strrchr(sourceFile, '/')) == NULL)
151 slashPtr = sourceFile;
158 sourceExt = (char*)malloc(strlen(sourceFile));
164 (&sourceFile[strlen(sourceFile) - 1] - dotPtr)/sizeof(char)
167 /* initialise depFile to zero and use strncat rather than strncpy
168 because there is a bug in the SGI strncat that if 0 preceeds the .
169 it inserts a space */
170 depFile = (char*)malloc(strlen(sourceFile) + 3);
172 strncat(depFile, sourceFile, (dotPtr - sourceFile)/sizeof(char));
173 strcat(depFile, ".dep");
175 if (strcmp(sourceExt, "java") == 0)
177 classFile = (char*)malloc(strlen(sourceFile) + 17);
178 strcpy(classFile, "$(CLASSES_DIR)/");
179 strncat(classFile, sourceFile, (dotPtr - sourceFile)/sizeof(char));
180 strcat(classFile, ".class");
182 printf("%s: %s\n", classFile, depFile);
186 objectFile = (char*)malloc(strlen(sourceFile) + 16);
187 strcpy(objectFile, "$(OBJECTS_DIR)/");
188 strncat(objectFile, slashPtr, (dotPtr - slashPtr)/sizeof(char));
189 strcat(objectFile, ".o");
191 printf("%s: %s\n", objectFile, depFile);
194 nextFile(sourceFile);
198 for (i = 0; i < nDirectories; i++)
200 free(directories[i]);
214 int currentBuffer = 0; /* Buffer pointer stack counter */
215 YY_BUFFER_STATE buffers[FILE_STACK_SIZE]; /* Buffer pointer stack */
217 /* file name entry in hash table */
222 struct FileName* next;
225 struct FileName* fileHashTable[HASH_TABLE_SIZE]; /* File hash table */
226 struct FileName* dirHashTable[HASH_TABLE_SIZE]; /* Directory hash table */
229 /* lookup name in hash table, if not found insert in table */
231 int lookUp(struct FileName** hashTable, const char* p)
239 while (*pp) ii = ii<<1 ^ *pp++;
240 if (ii < 0) ii = -ii;
241 ii %= HASH_TABLE_SIZE;
244 for (n=hashTable[ii]; n; n=n->next)
246 if (strcmp(p, n->name) == 0)
248 /* entry found so return true */
254 nn = (struct FileName*)malloc(sizeof(struct FileName));
255 nn->name = (char*)malloc(strlen(p)+1);
257 nn->next = hashTable[ii];
260 /* entry not found, and therefore added. return false */
266 /* Add a directory name to the file name */
268 char* addDirectoryName(const char* directoryName, const char* fileName)
271 pathName = (char*)malloc(strlen(directoryName) + strlen(fileName) + 2);
273 strcpy(pathName, directoryName);
275 if (directoryName[strlen(directoryName)-1] != '/')
277 strcat(pathName, "/");
280 strcat(pathName, fileName);
286 /* open a file and create buffer and put on stack stack */
288 void nextFile(const char* fileName)
293 if (lookUp(fileHashTable, fileName)) return;
295 if (currentBuffer >= FILE_STACK_SIZE)
300 "depth of file search exceeds stack size %d "
301 "while opening %s for file %s\n",
302 FILE_STACK_SIZE, fileName, sourceFile
307 /* Pointer to new file which is set if the file is successfully opened */
308 FILE* newyyin = NULL;
310 if (!(newyyin = fopen(fileName, "r")))
312 for (d=0; d<nDirectories; d++)
314 pathName = addDirectoryName(directories[d], fileName);
316 if ((newyyin = fopen(pathName, "r")))
318 printf("%s: %s\n", depFile, pathName);
319 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
320 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
333 "could not open file %s for source file %s\n",
341 printf("%s: %s\n", depFile, fileName);
344 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
345 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
350 void dotToSlash(char* fileName)
354 len = strlen(fileName);
356 for (i=0; i<len; i++)
358 if (fileName[i] == '.') fileName[i] = '/';
363 void importFile(const char* fileName)
368 fileNameLen = strlen(fileName);
369 javaFileName = (char*)malloc(fileNameLen + 6);
371 strncat(javaFileName, fileName, fileNameLen - 1);
372 dotToSlash(javaFileName);
373 strcat(javaFileName, ".java");
375 nextFile(javaFileName);
381 void importDirectory(const char* dirName)
384 char *uDirName, *path;
388 if (lookUp(dirHashTable, dirName)) return;
390 dirNameLen = strlen(dirName);
391 uDirName = strdup(dirName);
392 dotToSlash(uDirName);
393 uDirName[dirNameLen-2] = 0;
395 if ((source = opendir(uDirName)) == NULL)
400 "could not open directory %s\n",
409 /* Read and parse all the entries in the directory */
410 while ((list = readdir(source)) != NULL)
414 strstr(list->d_name, ".java")
415 && !strstr(list->d_name, ".java~")
418 path = addDirectoryName(uDirName, list->d_name);
430 /* The lexer calls yywrap to handle EOF conditions */
434 /* Close the file for the buffer which has just reached EOF */
435 /* This causes strange problems
440 /* Delete the buffer */
441 yy_delete_buffer(YY_CURRENT_BUFFER);
443 /* Set buffer counter to previous buffer */
446 if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
448 /* reset input buffer to the previous buffer on the stack */
449 yy_switch_to_buffer(buffers[currentBuffer]);
451 /* Return to the normal state for the previous buffer on the stack */
454 /* return 0 to inform lex to continue reading */
457 else /* else there are no more buffers on the stack */
459 /* return 1 to inform lex finish now that all buffers have been read */
465 /*****************************************************************************/