ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / wmake / src / wmkdep.l
blob86c6f64e939511e99cbd53bd5cf7b4cadf966548
1 %{
2 /*---------------------------------*- C -*-----------------------------------*\
3  =========                   |
4  \\      /   F ield          | OpenFOAM: The Open Source CFD Toolbox
5   \\    /    O peration      |
6    \\  /     A nd            | Copyright (C) 2011 OpenFOAM Foundation
7     \\/      M anipulation   |
8 ------------------------------------------------------------------------------
9 License
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
20     for more details.
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/>.
25 Application
26     wmkdep
28 Description
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.
37 Usage
38     wmkdep [ -Idir ... -Idir ] [ -iheader .. -iheader ] filename
40 \*---------------------------------------------------------------------------*/
42 #define FILE_STACK_SIZE 300
43 #define HASH_TABLE_SIZE 500
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sys/types.h>
48 #include <dirent.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 */
64 <CMNT>.|\n                ;
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); } /*'*/
83 .|\t|\n                   ;
88 /* char* entry in hash table */
89 struct HashEntry
91     char* name;
92     struct HashEntry* next;
97  * lookup name in hash table.
98  * if found - return 1
99  * if not found - insert in table and return 0
100  */
101 int lookUp(struct HashEntry** hashTable, const char* p)
103     int ii = 0;
104     struct HashEntry* n;
105     struct HashEntry* nn;
107     /* hash */
108     const char* pp = p;
109     while (*pp) ii = ii<<1 ^ *pp++;
110     if (ii < 0) ii = -ii;
111     ii %= HASH_TABLE_SIZE;
113     /* search */
114     for (n=hashTable[ii]; n; n=n->next)
115     {
116         if (strcmp(p, n->name) == 0)
117         {
118             /* entry found so return true */
119             return 1;
120         }
121     }
123     /* insert */
124     nn = (struct HashEntry*)malloc(sizeof(struct HashEntry));
125     nn->name = strdup(p);
126     nn->next = hashTable[ii];
127     hashTable[ii] = nn;
129     /* entry not found, and therefore added. return false */
130     return 0;
134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 int nDirectories = 0;
138 char** directories;
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;
152     int i;
154     if (argc == 1)
155     {
156         fprintf(stderr, "input file not supplied\n");
157         exit(1);
158     }
160     sourceFile = strdup(argv[argc-1]);
161     fprintf(stderr, "Making dependency list for source file %s\n", sourceFile);
164     if ((basePos = strrchr(sourceFile, '/')) == NULL)
165     {
166         basePos = sourceFile;
167     }
168     else
169     {
170         basePos++;
171     }
173     if
174     (
175         (dotPos = strrchr(sourceFile, '.')) == NULL
176      || (dotPos < basePos)
177     )
178     {
179         fprintf
180         (
181             stderr,
182             "cannot find extension in source file name %s\n",
183             sourceFile
184         );
185         exit(1);
186     }
188     /* count number of -I directories */
189     nDirectories = 0;
190     for (i = 1; i < argc; i++)
191     {
192         if (strncmp(argv[i], "-I", 2) == 0)
193         {
194             if (strlen(argv[i]) > 2)
195             {
196                 nDirectories++;
197             }
198         }
199     }
201     directories = (char**)malloc(sizeof(char*)*nDirectories);
203     /* build list of -I directories and add -i ignores */
204     nDirectories = 0;
205     for (i = 1; i < argc; i++)
206     {
207         if (strncmp(argv[i], "-I", 2) == 0)
208         {
209             if (strlen(argv[i]) > 2)
210             {
211                 directories[nDirectories++] = strdup(argv[i] + 2);
212             }
213         }
214         else if (strncmp(argv[i], "-i", 2) == 0)
215         {
216             if (strlen(argv[i]) > 2)
217             {
218                 lookUp(visitedFiles, (argv[i] + 2));
219             }
220         }
221     }
223     /*
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 '.'
226      * it inserts a space
227      */
228     depFile = (char*)malloc(strlen(sourceFile) + 3);
229     depFile[0] = 0;
230     strncat(depFile, sourceFile, (dotPos - sourceFile)/sizeof(char));
231     strcat(depFile, ".dep");
233     if (strcmp(dotPos, ".java") == 0)
234     {
235         char *classFile = strdup(sourceFile);
236         classFile[(dotPos - sourceFile)/sizeof(char)] = 0;
238         printf("$(CLASSES_DIR)/%s.class: %s\n", classFile, depFile);
239         free(classFile);
240     }
241     else
242     {
243         char *objectFile = strdup(basePos);
244         objectFile[(dotPos - basePos)/sizeof(char)] = 0;
246         printf("$(OBJECTS_DIR)/%s.o: %s\n", objectFile, depFile);
247         free(objectFile);
248     }
250     nextFile(sourceFile);
251     yylex();
254     for (i = 0; i < nDirectories; i++)
255     {
256         free(directories[i]);
257     }
258     free(directories);
260     free(sourceFile);
261     free(depFile);
263     return 0;
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
273  */
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] != '/')
280     {
281         strcat(pathName, "/");
282     }
284     strcat(pathName, fileName);
286     return pathName;
291  * open a file and create buffer and put on stack
292  */
293 void nextFile(const char* fileName)
295     if (lookUp(visitedFiles, fileName))
296     {
297         return;   /* already existed (did not insert) */
298     }
300     if (currentBuffer >= FILE_STACK_SIZE)
301     {
302         fprintf
303         (
304             stderr,
305             "depth of file search exceeds stack size %d "
306             "while opening %s for file %s\n",
307             FILE_STACK_SIZE, fileName, sourceFile
308         );
309         exit(1);
310     }
312     /* Pointer to new file which is set if the file is successfully opened */
313     FILE* newyyin = NULL;
315     if (!(newyyin = fopen(fileName, "r")))
316     {
317         int d;
318         for (d=0; d<nDirectories; d++)
319         {
320             char* pathName = addDirectoryName(directories[d], fileName);
322             if ((newyyin = fopen(pathName, "r")))
323             {
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));
328                 free(pathName);
330                 return;
331             }
333             free(pathName);
334         }
336         fprintf
337         (
338             stderr,
339             "could not open file %s for source file %s\n",
340             fileName, sourceFile
341         );
343         fflush(stdout);
344         fflush(stderr);
346         /* only report the first occurance */
347         lookUp(visitedFiles, fileName);
348     }
349     else
350     {
351         printf("%s: %s\n", depFile, fileName);
352         fflush(stdout);
354         buffers[currentBuffer++] = YY_CURRENT_BUFFER;
355         yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
356     }
361  * Replace all '.' with '/'
362  */
363 void dotToSlash(char* fileName)
365     int i, len;
366     len = strlen(fileName);
368     for (i=0; i<len; i++)
369     {
370         if (fileName[i] == '.') fileName[i] = '/';
371     }
376  * Import (java) file
377  */
378 void importFile(const char* fileName)
380     char* javaFileName;
381     int fileNameLen;
383     fileNameLen = strlen(fileName);
384     javaFileName = (char*)malloc(fileNameLen + 6);
385     javaFileName[0] = 0;
386     strncat(javaFileName, fileName, fileNameLen - 1);
387     dotToSlash(javaFileName);
388     strcat(javaFileName, ".java");
390     nextFile(javaFileName);
392     free(javaFileName);
397  * Import (java) directories
398  */
399 void importDir(const char* dirName)
401     char *uDirName;
402     DIR *source;
404     if (lookUp(visitedDirs, dirName))
405     {
406         return;   /* already existed (did not insert) */
407     }
409     uDirName = strdup(dirName);
410     dotToSlash(uDirName);
412     uDirName[strlen(dirName)-2] = 0;
414     if ((source = opendir(uDirName)) == NULL)
415     {
416         fprintf
417         (
418             stderr,
419             "could not open directory %s\n",
420             uDirName
421         );
422     }
423     else
424     {
425         /* Read and parse all the entries in the directory */
426         struct dirent *list;
428         while ((list = readdir(source)) != NULL)
429         {
430             char* dotPos = strrchr(list->d_name, '.');
432             if (dotPos != NULL && strcmp(dotPos, ".java") == 0)
433             {
434                 char* pathName = addDirectoryName(uDirName, list->d_name);
435                 nextFile(pathName);
436                 free(pathName);
437             }
438         }
440         closedir(source);
441     }
442     free(uDirName);
447  * The lexer calls yywrap to handle EOF conditions
448  */
449 int yywrap()
451     /* Close the file for the buffer which has just reached EOF */
452     /* This causes strange problems on some systems
453     fclose(yyin);
454     yyin = 0;
455     */
457     /* Delete the buffer */
458     yy_delete_buffer(YY_CURRENT_BUFFER);
460     /* Set buffer counter to previous buffer */
461     currentBuffer--;
463     if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
464     {
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 */
469         BEGIN(INITIAL);
471         /* return 0 to inform lex to continue reading */
472         return 0;
473     }
474     else                 /* else there are no more buffers on the stack */
475     {
476         /* return 1 to inform lex finish now that all buffers have been read */
477         return 1;
478     }
482 /*****************************************************************************/