2 /*---------------------------------------------------------------------------*\
4 \\ / F ield | foam-extend: Open Source CFD
6 \\ / A nd | For copyright notice see file Copyright
8 ------------------------------------------------------------------------------
10 This file is part of foam-extend.
12 foam-extend 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 3 of the License, or (at your
15 option) any later version.
17 foam-extend is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
29 A fast dependency list generator that emulates the behaviour and
30 output of cpp -M. However, the output contains no duplications and
31 is ~40% faster than cpp.
33 The algorithm uses flex to scan for includes and searches the files
34 found. Each file is entered into a hash table so that files are scanned
35 only once. This is why this program is faster than cpp.
38 wmkdep [ -Idirectory ... -Idirectory ] filename
40 \*---------------------------------------------------------------------------*/
42 #define FILE_STACK_SIZE 300
43 #define HASH_TABLE_SIZE 500
47 #include <sys/types.h>
50 void nextFile(const char* fileName);
51 void importFile(const char* fileName);
52 void importDirectory(const char* dirName);
54 # undef yywrap /* sometimes a macro by default */
58 %x CMNT CFNAME SCFNAME JFNAME FFNAME
61 "//".*\n ; /* remove c++ style one line comments */
63 "/*" BEGIN(CMNT); /* start removing c style comment */
65 <CMNT>"*/" BEGIN(INITIAL); /* end removing c style comment */
67 ^[ \t]*#[ \t]*include[ \t]+\" BEGIN(CFNAME); /* c-file name */
68 <CFNAME>[^"\n ]* { BEGIN(INITIAL); nextFile(yytext); } /*"*/
70 ^[ \t]*import[ \t]+ BEGIN(JFNAME); /* java-file name */
71 <JFNAME>java.*; BEGIN(INITIAL);
72 <JFNAME>org.*; BEGIN(INITIAL);
73 <JFNAME>com.*; BEGIN(INITIAL);
74 <JFNAME>sunw.*; BEGIN(INITIAL);
75 <JFNAME>sun.*; BEGIN(INITIAL);
76 <JFNAME>launcher.*; BEGIN(INITIAL);
77 <JFNAME>[^"\n*]*; { BEGIN(INITIAL); importFile(yytext); } /*"*/
78 <JFNAME>[^"\n]*\*; { BEGIN(INITIAL); importDirectory(yytext); } /*"*/
80 " "include[ \t]+\' BEGIN(FFNAME); /* FORTRAN-file name */
81 <FFNAME>[^']* { BEGIN(INITIAL); nextFile(yytext); } /*'*/
90 char* sourceFile = NULL;
91 char* sourceExt = NULL;
92 char* objectFile = NULL;
93 char* classFile = NULL;
96 int main(int argc, char* argv[])
98 char *dotPtr, *slashPtr;
103 fprintf(stderr,"input file not supplied\n");
107 sourceFile = (char*)malloc(strlen(argv[argc-1]) + 1);
108 strcpy(sourceFile, argv[argc-1]);
109 fprintf(stderr, "Making dependency list for source file %s\n", sourceFile);
112 /* Get list of -I directories. */
115 for (i = 1; i < argc; i++)
117 if (strncmp(argv[i], "-I", 2) == 0)
123 directories = (char**)malloc(sizeof(char*)*nDirectories);
127 for (i = 1; i < argc; i++)
129 if (strncmp(argv[i], "-I", 2) == 0)
131 directories[nDirectories++] = strdup(argv[i] + 2);
137 if ((dotPtr = strrchr(sourceFile, '.')) == NULL)
142 "Cannot find extension in source file name %s\n",
148 if ((slashPtr = strrchr(sourceFile, '/')) == NULL)
150 slashPtr = sourceFile;
157 sourceExt = (char*)malloc(strlen(sourceFile));
163 (&sourceFile[strlen(sourceFile) - 1] - dotPtr)/sizeof(char)
166 /* initialise depFile to zero and use strncat rather than strncpy
167 because there is a bug in the SGI strncat that if 0 preceeds the .
168 it inserts a space */
169 depFile = (char*)malloc(strlen(sourceFile) + 3);
171 strncat(depFile, sourceFile, (dotPtr - sourceFile)/sizeof(char));
172 strcat(depFile, ".dep");
174 if (strcmp(sourceExt, "java") == 0)
176 classFile = (char*)malloc(strlen(sourceFile) + 17);
177 strcpy(classFile, "$(CLASSES_DIR)/");
178 strncat(classFile, sourceFile, (dotPtr - sourceFile)/sizeof(char));
179 strcat(classFile, ".class");
181 printf("%s: %s\n", classFile, depFile);
185 objectFile = (char*)malloc(strlen(sourceFile) + 16);
186 strcpy(objectFile, "$(OBJECTS_DIR)/");
187 strncat(objectFile, slashPtr, (dotPtr - slashPtr)/sizeof(char));
188 strcat(objectFile, ".o");
190 printf("%s: %s\n", objectFile, depFile);
193 nextFile(sourceFile);
197 for (i = 0; i < nDirectories; i++)
199 free(directories[i]);
213 int currentBuffer = 0; /* Buffer pointer stack counter */
214 YY_BUFFER_STATE buffers[FILE_STACK_SIZE]; /* Buffer pointer stack */
216 /* file name entry in hash table */
221 struct FileName* next;
224 struct FileName* fileHashTable[HASH_TABLE_SIZE]; /* File hash table */
225 struct FileName* dirHashTable[HASH_TABLE_SIZE]; /* Directory hash table */
228 /* lookup name in hash table, if not found insert in table */
230 int lookUp(struct FileName** hashTable, const char* p)
238 while (*pp) ii = ii<<1 ^ *pp++;
239 if (ii < 0) ii = -ii;
240 ii %= HASH_TABLE_SIZE;
243 for (n=hashTable[ii]; n; n=n->next)
245 if (strcmp(p, n->name) == 0)
247 /* entry found so return true */
253 nn = (struct FileName*)malloc(sizeof(struct FileName));
254 nn->name = (char*)malloc(strlen(p)+1);
256 nn->next = hashTable[ii];
259 /* entry not found, and therefore added. return false */
265 /* Add a directory name to the file name */
267 char* addDirectoryName(const char* directoryName, const char* fileName)
270 pathName = (char*)malloc(strlen(directoryName) + strlen(fileName) + 2);
272 strcpy(pathName, directoryName);
274 if (directoryName[strlen(directoryName)-1] != '/')
276 strcat(pathName, "/");
279 strcat(pathName, fileName);
285 /* open a file and create buffer and put on stack stack */
287 void nextFile(const char* fileName)
292 if (lookUp(fileHashTable, fileName)) return;
294 if (currentBuffer >= FILE_STACK_SIZE)
299 "depth of file search exceeds stack size %d "
300 "while opening %s for file %s\n",
301 FILE_STACK_SIZE, fileName, sourceFile
306 /* Pointer to new file which is set if the file is successfully opened */
307 FILE* newyyin = NULL;
309 if (!(newyyin = fopen(fileName, "r")))
311 for (d=0; d<nDirectories; d++)
313 pathName = addDirectoryName(directories[d], fileName);
315 if ((newyyin = fopen(pathName, "r")))
317 printf("%s: %s\n", depFile, pathName);
318 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
319 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
332 "could not open file %s for source file %s\n",
340 printf("%s: %s\n", depFile, fileName);
343 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
344 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
349 void dotToSlash(char* fileName)
353 len = strlen(fileName);
355 for (i=0; i<len; i++)
357 if (fileName[i] == '.') fileName[i] = '/';
362 void importFile(const char* fileName)
367 fileNameLen = strlen(fileName);
368 javaFileName = (char*)malloc(fileNameLen + 6);
370 strncat(javaFileName, fileName, fileNameLen - 1);
371 dotToSlash(javaFileName);
372 strcat(javaFileName, ".java");
374 nextFile(javaFileName);
380 void importDirectory(const char* dirName)
383 char *uDirName, *path;
387 if (lookUp(dirHashTable, dirName)) return;
389 dirNameLen = strlen(dirName);
390 uDirName = strdup(dirName);
391 dotToSlash(uDirName);
392 uDirName[dirNameLen-2] = 0;
394 if ((source = opendir(uDirName)) == NULL)
399 "could not open directory %s\n",
408 /* Read and parse all the entries in the directory */
409 while ((list = readdir(source)) != NULL)
413 strstr(list->d_name, ".java")
414 && !strstr(list->d_name, ".java~")
417 path = addDirectoryName(uDirName, list->d_name);
429 /* The lexer calls yywrap to handle EOF conditions */
433 /* Close the file for the buffer which has just reached EOF */
434 /* This causes strange problems
439 /* Delete the buffer */
440 yy_delete_buffer(YY_CURRENT_BUFFER);
442 /* Set buffer counter to previous buffer */
445 if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
447 /* reset input buffer to the previous buffer on the stack */
448 yy_switch_to_buffer(buffers[currentBuffer]);
450 /* Return to the normal state for the previous buffer on the stack */
453 /* return 0 to inform lex to continue reading */
456 else /* else there are no more buffers on the stack */
458 /* return 1 to inform lex finish now that all buffers have been read */
464 /*****************************************************************************/