2 /*---------------------------------*- C -*-----------------------------------*\
4 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
6 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
14 the Free Software Foundation, either version 3 of the License, or
15 (at your 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, see <http://www.gnu.org/licenses/>.
29 A fast dependency list generator that emulates the behaviour and the
30 output of cpp -M. However, the output contains no duplicates and
31 is approx. 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 [ -Idir ... -Idir ] [ -iheader .. -iheader ] 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 importDir(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); importDir(yytext); } /*"*/
80 " "include[ \t]+\' BEGIN(FFNAME); /* FORTRAN-file name */
81 <FFNAME>[^']* { BEGIN(INITIAL); nextFile(yytext); } /*'*/
88 /* char* entry in hash table */
92 struct HashEntry* next;
97 * lookup name in hash table.
99 * if not found - insert in table and return 0
101 int lookUp(struct HashEntry** hashTable, const char* p)
105 struct HashEntry* nn;
109 while (*pp) ii = ii<<1 ^ *pp++;
110 if (ii < 0) ii = -ii;
111 ii %= HASH_TABLE_SIZE;
114 for (n=hashTable[ii]; n; n=n->next)
116 if (strcmp(p, n->name) == 0)
118 /* entry found so return true */
124 nn = (struct HashEntry*)malloc(sizeof(struct HashEntry));
125 nn->name = strdup(p);
126 nn->next = hashTable[ii];
129 /* entry not found, and therefore added. return false */
134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 int nDirectories = 0;
139 char* sourceFile = NULL;
140 char* depFile = NULL;
142 /* Set of files already visited */
143 struct HashEntry* visitedFiles[HASH_TABLE_SIZE];
145 /* Set of (java) directories already visited */
146 struct HashEntry* visitedDirs[HASH_TABLE_SIZE];
149 int main(int argc, char* argv[])
151 char *basePos, *dotPos;
156 fprintf(stderr, "input file not supplied\n");
160 sourceFile = strdup(argv[argc-1]);
161 fprintf(stderr, "Making dependency list for source file %s\n", sourceFile);
164 if ((basePos = strrchr(sourceFile, '/')) == NULL)
166 basePos = sourceFile;
175 (dotPos = strrchr(sourceFile, '.')) == NULL
176 || (dotPos < basePos)
182 "cannot find extension in source file name %s\n",
188 /* count number of -I directories */
190 for (i = 1; i < argc; i++)
192 if (strncmp(argv[i], "-I", 2) == 0)
194 if (strlen(argv[i]) > 2)
201 directories = (char**)malloc(sizeof(char*)*nDirectories);
203 /* build list of -I directories and add -i ignores */
205 for (i = 1; i < argc; i++)
207 if (strncmp(argv[i], "-I", 2) == 0)
209 if (strlen(argv[i]) > 2)
211 directories[nDirectories++] = strdup(argv[i] + 2);
214 else if (strncmp(argv[i], "-i", 2) == 0)
216 if (strlen(argv[i]) > 2)
218 lookUp(visitedFiles, (argv[i] + 2));
224 * initialise depFile to zero and use strncat rather than strncpy
225 * because there is a bug in the SGI strncat that if 0 preceeds the '.'
228 depFile = (char*)malloc(strlen(sourceFile) + 3);
230 strncat(depFile, sourceFile, (dotPos - sourceFile)/sizeof(char));
231 strcat(depFile, ".dep");
233 if (strcmp(dotPos, ".java") == 0)
235 char *classFile = strdup(sourceFile);
236 classFile[(dotPos - sourceFile)/sizeof(char)] = 0;
238 printf("$(CLASSES_DIR)/%s.class: %s\n", classFile, depFile);
243 char *objectFile = strdup(basePos);
244 objectFile[(dotPos - basePos)/sizeof(char)] = 0;
246 printf("$(OBJECTS_DIR)/%s.o: %s\n", objectFile, depFile);
250 nextFile(sourceFile);
254 for (i = 0; i < nDirectories; i++)
256 free(directories[i]);
267 int currentBuffer = 0; /* Buffer pointer stack counter */
268 YY_BUFFER_STATE buffers[FILE_STACK_SIZE]; /* Buffer pointer stack */
272 * Add a directory name to the file name
274 char* addDirectoryName(const char* dirName, const char* fileName)
276 char* pathName = (char*)malloc(strlen(dirName) + strlen(fileName) + 2);
277 strcpy(pathName, dirName);
279 if (dirName[strlen(dirName)-1] != '/')
281 strcat(pathName, "/");
284 strcat(pathName, fileName);
291 * open a file and create buffer and put on stack
293 void nextFile(const char* fileName)
295 if (lookUp(visitedFiles, fileName))
297 return; /* already existed (did not insert) */
300 if (currentBuffer >= FILE_STACK_SIZE)
305 "depth of file search exceeds stack size %d "
306 "while opening %s for file %s\n",
307 FILE_STACK_SIZE, fileName, sourceFile
312 /* Pointer to new file which is set if the file is successfully opened */
313 FILE* newyyin = NULL;
315 if (!(newyyin = fopen(fileName, "r")))
318 for (d=0; d<nDirectories; d++)
320 char* pathName = addDirectoryName(directories[d], fileName);
322 if ((newyyin = fopen(pathName, "r")))
324 printf("%s: %s\n", depFile, pathName);
325 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
326 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
339 "could not open file %s for source file %s\n",
346 /* only report the first occurance */
347 lookUp(visitedFiles, fileName);
351 printf("%s: %s\n", depFile, fileName);
354 buffers[currentBuffer++] = YY_CURRENT_BUFFER;
355 yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
361 * Replace all '.' with '/'
363 void dotToSlash(char* fileName)
366 len = strlen(fileName);
368 for (i=0; i<len; i++)
370 if (fileName[i] == '.') fileName[i] = '/';
378 void importFile(const char* fileName)
383 fileNameLen = strlen(fileName);
384 javaFileName = (char*)malloc(fileNameLen + 6);
386 strncat(javaFileName, fileName, fileNameLen - 1);
387 dotToSlash(javaFileName);
388 strcat(javaFileName, ".java");
390 nextFile(javaFileName);
397 * Import (java) directories
399 void importDir(const char* dirName)
404 if (lookUp(visitedDirs, dirName))
406 return; /* already existed (did not insert) */
409 uDirName = strdup(dirName);
410 dotToSlash(uDirName);
412 uDirName[strlen(dirName)-2] = 0;
414 if ((source = opendir(uDirName)) == NULL)
419 "could not open directory %s\n",
425 /* Read and parse all the entries in the directory */
428 while ((list = readdir(source)) != NULL)
430 char* dotPos = strrchr(list->d_name, '.');
432 if (dotPos != NULL && strcmp(dotPos, ".java") == 0)
434 char* pathName = addDirectoryName(uDirName, list->d_name);
447 * The lexer calls yywrap to handle EOF conditions
451 /* Close the file for the buffer which has just reached EOF */
452 /* This causes strange problems on some systems
457 /* Delete the buffer */
458 yy_delete_buffer(YY_CURRENT_BUFFER);
460 /* Set buffer counter to previous buffer */
463 if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
465 /* reset input buffer to the previous buffer on the stack */
466 yy_switch_to_buffer(buffers[currentBuffer]);
468 /* Return to the normal state for the previous buffer on the stack */
471 /* return 0 to inform lex to continue reading */
474 else /* else there are no more buffers on the stack */
476 /* return 1 to inform lex finish now that all buffers have been read */
482 /*****************************************************************************/