Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / wmake / src / wmkdep.l
blob95fcd6999c8dabf8413457b5be960673f9f9f270
1 %{
2 /*---------------------------------------------------------------------------*\
3   =========                   |
4   \\      /   F ield          | foam-extend: Open Source CFD
5    \\    /    O peration      |
6     \\  /     A nd            | For copyright notice see file Copyright
7      \\/      M anipulation   |
8 ------------------------------------------------------------------------------
9 License
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/>.
25 Application
26     wmkdep
28 Description
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.
37 Usage
38     wmkdep [ -Idirectory ... -Idirectory ] 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 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 */
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); importDirectory(yytext); } /*"*/
80 "      "include[ \t]+\'   BEGIN(FFNAME);  /* FORTRAN-file name */
81 <FFNAME>[^']*           { BEGIN(INITIAL); nextFile(yytext); } /*'*/
83 .|\t|\n                   ;
88 int nDirectories;
89 char** directories;
90 char* sourceFile = NULL;
91 char* sourceExt = NULL;
92 char* objectFile = NULL;
93 char* classFile = NULL;
94 char* depFile = NULL;
96 int main(int argc, char* argv[])
98     char *dotPtr, *slashPtr;
99     int i;
101     if (argc == 1)
102     {
103         fprintf(stderr,"input file not supplied\n");
104         exit(1);
105     }
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. */
113     nDirectories = 0;
115     for (i = 1; i < argc; i++)
116     {
117         if (strncmp(argv[i], "-I", 2) == 0)
118         {
119             nDirectories++;
120         }
121     }
123     directories = (char**)malloc(sizeof(char*)*nDirectories);
125     nDirectories = 0;
127     for (i = 1; i < argc; i++)
128     {
129         if (strncmp(argv[i], "-I", 2) == 0)
130         {
131             directories[nDirectories++] = strdup(argv[i] + 2);
132         }
133     }
137     if ((dotPtr = strrchr(sourceFile, '.')) == NULL)
138     {
139         fprintf
140         (
141             stderr,
142             "Cannot find extension in source file name %s\n",
143             sourceFile
144         );
145         exit(1);
146     }
148     if ((slashPtr = strrchr(sourceFile, '/')) == NULL)
149     {
150         slashPtr = sourceFile;
151     }
152     else
153     {
154         slashPtr++;
155     }
157     sourceExt = (char*)malloc(strlen(sourceFile));
158     sourceExt[0] = 0;
159     strncat
160     (
161         sourceExt,
162         dotPtr+1,
163         (&sourceFile[strlen(sourceFile) - 1] - dotPtr)/sizeof(char)
164     );
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);
170     depFile[0] = 0;
171     strncat(depFile, sourceFile, (dotPtr - sourceFile)/sizeof(char));
172     strcat(depFile, ".dep");
174     if (strcmp(sourceExt, "java") == 0)
175     {
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);
182     }
183     else
184     {
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);
191     }
193     nextFile(sourceFile);
194     yylex();
197     for (i = 0; i < nDirectories; i++)
198     {
199         free(directories[i]);
200     }
201     free(directories);
203     free(sourceFile);
204     free(sourceExt);
205     free(objectFile);
206     free(classFile);
207     free(depFile);
209     return 0;
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 */
218 struct FileName
220     char* name;
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)
232     int ii = 0;
233     struct FileName* n;
234     struct FileName* nn;
236     /* hash */
237     const char* pp = p;
238     while (*pp) ii = ii<<1 ^ *pp++;
239     if (ii < 0) ii = -ii;
240     ii %= HASH_TABLE_SIZE;
242     /* search */
243     for (n=hashTable[ii]; n; n=n->next)
244     {
245         if (strcmp(p, n->name) == 0)
246         {
247             /* entry found so return true */
248             return 1;
249         }
250     }
252     /* insert */
253     nn = (struct FileName*)malloc(sizeof(struct FileName));
254     nn->name = (char*)malloc(strlen(p)+1);
255     strcpy(nn->name, p);
256     nn->next = hashTable[ii];
257     hashTable[ii] = nn;
259     /* entry not found, and therefore added. return false */
260     return 0;
265 /* Add a directory name to the file name */
267 char* addDirectoryName(const char* directoryName, const char* fileName)
269     char* pathName;
270     pathName = (char*)malloc(strlen(directoryName) + strlen(fileName) + 2);
272     strcpy(pathName, directoryName);
274     if (directoryName[strlen(directoryName)-1] != '/')
275     {
276         strcat(pathName, "/");
277     }
279     strcat(pathName, fileName);
281     return pathName;
285 /* open a file and create buffer and put on stack stack */
287 void nextFile(const char* fileName)
289     int d;
290     char* pathName;
292     if (lookUp(fileHashTable, fileName)) return;
294     if (currentBuffer >= FILE_STACK_SIZE)
295     {
296         fprintf
297         (
298             stderr,
299             "depth of file search exceeds stack size %d "
300             "while opening %s for file %s\n",
301             FILE_STACK_SIZE, fileName, sourceFile
302         );
303         exit(1);
304     }
306     /* Pointer to new file which is set if the file is successfully opened */
307     FILE* newyyin = NULL;
309     if (!(newyyin = fopen(fileName, "r")))
310     {
311         for (d=0; d<nDirectories; d++)
312         {
313             pathName = addDirectoryName(directories[d], fileName);
315             if ((newyyin = fopen(pathName, "r")))
316             {
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));
321                 free(pathName);
323                 return;
324             }
326             free(pathName);
327         }
329         fprintf
330         (
331             stderr,
332             "could not open file %s for source file %s\n",
333             fileName, sourceFile
334         );
336         fflush(stdout);
337     }
338     else
339     {
340         printf("%s: %s\n", depFile, fileName);
341         fflush(stdout);
343         buffers[currentBuffer++] = YY_CURRENT_BUFFER;
344         yy_switch_to_buffer(yy_create_buffer(newyyin, YY_BUF_SIZE));
345     }
349 void dotToSlash(char* fileName)
351     int i, len;
353     len = strlen(fileName);
355     for (i=0; i<len; i++)
356     {
357         if (fileName[i] == '.') fileName[i] = '/';
358     }
362 void importFile(const char* fileName)
364     char* javaFileName;
365     int fileNameLen;
367     fileNameLen = strlen(fileName);
368     javaFileName = (char*)malloc(fileNameLen + 6);
369     javaFileName[0] = 0;
370     strncat(javaFileName, fileName, fileNameLen - 1);
371     dotToSlash(javaFileName);
372     strcat(javaFileName, ".java");
374     nextFile(javaFileName);
376     free(javaFileName);
380 void importDirectory(const char* dirName)
382     int dirNameLen;
383     char *uDirName, *path;
384     DIR *source;
385     struct dirent *list;
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)
395     {
396         fprintf
397         (
398             stderr,
399             "could not open directory %s\n",
400             uDirName
401         );
402         free(uDirName);
404         return;
405     }
406     else
407     {
408         /* Read and parse all the entries in the directory */
409         while ((list = readdir(source)) != NULL)
410         {
411             if
412             (
413                 strstr(list->d_name, ".java")
414              && !strstr(list->d_name, ".java~")
415             )
416             {
417                 path = addDirectoryName(uDirName, list->d_name);
418                 nextFile(path);
419                 free(path);
420             }
421         }
423         closedir(source);
424         free(uDirName);
425     }
429 /* The lexer calls yywrap to handle EOF conditions */
431 int yywrap()
433     /* Close the file for the buffer which has just reached EOF */
434     /* This causes strange problems
435     fclose(yyin);
436     yyin = 0;
437     */
439     /* Delete the buffer */
440     yy_delete_buffer(YY_CURRENT_BUFFER);
442     /* Set buffer counter to previous buffer */
443     currentBuffer--;
445     if (currentBuffer >= 0) /* if buffer counter refers to a valid file */
446     {
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 */
451         BEGIN(INITIAL);
453         /* return 0 to inform lex to continue reading */
454         return 0;
455     }
456     else                 /* else there are no more buffers on the stack */
457     {
458         /* return 1 to inform lex finish now that all buffers have been read */
459         return 1;
460     }
464 /*****************************************************************************/