ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / wmake / src / wmkdependParser.atg
blobbf2df41f57f350d42a0b45d3d61754fb5572639c
1 /*---------------------------------------------------------------------------*\
2     Attributed Grammar for Coco/R  (-*- C++ -*- version)
3     compile with:
4         coco-cpp wmkdependParser.atg
5 \*---------------------------------------------------------------------------*/
6 [copy]
7 /*---------------------------------*- C++ -*---------------------------------*\
8   =========                 |
9   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
10    \\    /   O peration     |
11     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
12      \\/     M anipulation  |
13 -------------------------------------------------------------------------------
14 License
15     This file is part of OpenFOAM.
17     OpenFOAM is free software: you can redistribute it and/or modify it
18     under the terms of the GNU General Public License as published by
19     the Free Software Foundation, either version 3 of the License, or
20     (at your option) any later version.
22     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
23     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25     for more details.
27     You should have received a copy of the GNU General Public License
28     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
30 @file wmkdependParser.atg
32 Description
33     An attributed Coco/R grammar to parse C/C++, Fortran and Java files
34     for include and import statements.
36 SourceFiles
37     generated
39 \*---------------------------------------------------------------------------*/
40 [/copy]
41 #include <iostream>
42 #include <string>
43 #include <list>
44 #include <set>
46 /*---------------------------------------------------------------------------*/
48 COMPILER wmkdepend
49     // grammar pragmas:
50     $namespace=wmake
51     $prefix=wmkdepend
52     $define=FORCE_UTF8
54 /*---------------------------------------------------------------------------*/
55 private:
57     //! Set of (java) directories already visited
58     static std::set<std::string> visitedDirs_;
60     //! Replace all '.' with '/'
61     static void dotToSlash(std::string& name);
63     //! Import (java) directories
64     static void importDir(const std::string& dirName);
66     //! Import (java) file
67     static void importFile(const std::string& name);
69 public:
70     //! Set of files already visited
71     static std::set<std::string> visitedFiles;
73     //! Include directories to search
74     static std::list<std::string> includeDirs;
76     //! The name of the top-level source file
77     static std::string sourceFile;
79     //! The name of the top-level dep file
80     static std::string depFile;
82     //! Add directory to list of visited dirs, thus effectively ignoring it
83     static void ignoreDir(const std::string& name);
85     //! Include file
86     static void includeFile(const std::string& name);
88 /*---------------------------------------------------------------------------*/
89 [code]
90 #include <sys/types.h>
91 #include <dirent.h>
93 std::set<std::string> Parser::visitedDirs_;
95 std::set<std::string> Parser::visitedFiles;
96 std::list<std::string> Parser::includeDirs;
97 std::string Parser::sourceFile;
98 std::string Parser::depFile;
101 void Parser::dotToSlash(std::string& name)
103     std::string::size_type start = 0;
105     while ((start = name.find('.', start)) != std::string::npos)
106     {
107         name.replace(start, 1, 1, '/');
108         start++;
109     }
113 void Parser::ignoreDir(const std::string& name)
115     visitedDirs_.insert(name);
119 void Parser::includeFile(const std::string& name)
121     if (!visitedFiles.insert(name).second)
122     {
123         return;   // already existed (did not insert)
124     }
126     // use stdio and buffering within Coco/R -- (faster)
127     FILE *fh = fopen(name.c_str(), "r");
128     if (fh)
129     {
130         std::cout << depFile << ": " << name << "\n";
131     }
132     else
133     {
134         for
135         (
136             std::list<std::string>::const_iterator iter = includeDirs.begin();
137             iter != includeDirs.end();
138             ++iter
139         )
140         {
141             const std::string pathName = *iter + name;
143             fh = fopen(pathName.c_str(), "r");
144             if (fh)
145             {
146                 std::cout << depFile << ": " << pathName << "\n";
147                 break;
148             }
149         }
150     }
152     if (fh)
153     {
154         Scanner scanner(fh);
155         Parser  parser(&scanner);
157         parser.Parse();
158         fclose(fh);
159     }
160     else
161     {
162         fwprintf
163         (
164             stderr,
165             L"could not open file %s for source file %s\n",
166             name.c_str(), sourceFile.c_str()
167         );
169         // only report the first occurance
170         visitedFiles.insert(name);
171     }
175 void Parser::importFile(const std::string& name)
177     // check if a globbed form was already visited
178     std::string::size_type dotPos = name.find('.');
179     if (dotPos != std::string::npos)
180     {
181         std::string dirGlob = name.substr(0, dotPos);
182         dirGlob += ".*";
184         if (visitedDirs_.find(dirGlob) != visitedDirs_.end())
185         {
186             return;
187         }
188     }
190     std::string javaFileName = name;
192     dotToSlash(javaFileName);
193     javaFileName += ".java";
195     includeFile(javaFileName);
199 void Parser::importDir(const std::string& name)
201     if (!visitedDirs_.insert(name).second)
202     {
203         return;   // already existed (did not insert)
204     }
206     std::string dirName = name;
207     dotToSlash(dirName);
209     DIR *source = opendir(dirName.c_str());
211     if (source)
212     {
213         struct dirent *list;
215         // Read and parse all the entries in the directory
216         while ((list = readdir(source)) != NULL)
217         {
218             const char* ext = strstr(list->d_name, ".java");
220             // avoid matching on something like '.java~'
221             if (ext && strlen(ext) == 5)
222             {
223                 std::string pathName = dirName + list->d_name;
224                 includeFile(pathName);
225             }
226         }
228         closedir(source);
229     }
230     else
231     {
232         fwprintf
233         (
234             stderr,
235             L"could not open directory %s\n",
236             dirName.c_str()
237         );
238         return;
239     }
242 [/code]
245 /*---------------------------------------------------------------------------*/
247 CHARACTERS
248     letter    = 'A'..'Z' + 'a'..'z' + '_'.
249     digit     = "0123456789".
250     cr        = '\r'.
251     lf        = '\n'.
252     tab       = '\t'.
253     stringCh  = ANY - '"' - '\\' - cr - lf.
254     printable = '\u0020' .. '\u007e'.
255     java_letter = letter + '$'.
257 // * * * * * * * * * * * * * * * *  TOKENS * * * * * * * * * * * * * * * * * //
259 TOKENS
261 // string
262 string =
263     '"' { stringCh | '\\' printable } '"'.
265 // single-quoted string (eg, Fortran)
266 sqstring =
267     '\'' { stringCh | '\\' printable } '\''.
269 // for java import
270 package_name =
271     java_letter { java_letter | digit }
272     { '.' java_letter { java_letter | digit } } .
274 // for java import
275 package_dir =
276     java_letter { java_letter | digit }
277     { '.' java_letter { java_letter | digit } } ".*" .
280 // * * * * * * * * * * *  PRAGMAS / COMMENTS / IGNORE  * * * * * * * * * * * //
282 COMMENTS FROM "/*" TO "*/" NESTED
283 COMMENTS FROM "//" TO lf
285 IGNORE tab
287 // * * * * * * * * * * * * * * *  PRODUCTIONS  * * * * * * * * * * * * * * * //
289 PRODUCTIONS
291 wmkdepend
294     // C/C++-style includes
295     '#'
296     [
297         "include"
298         [
299             string      (.
300                            if (isUTF8())
301                            {
302                                includeFile(t->toStringUTF8(1, t->length()-2));
303                            }
304                            else
305                            {
306                                includeFile(t->toString(1, t->length()-2));
307                            }
308                          .)
309         ]
310     ]
311     [ ANY { ANY } ] '\n'    // skip trailing junk
313     // Fortran-style includes
314   | "include"
315     [
316         sqstring        (.
317                            if (isUTF8())
318                            {
319                                includeFile(t->toStringUTF8(1, t->length()-2));
320                            }
321                            else
322                            {
323                                includeFile(t->toString(1, t->length()-2));
324                            }
325                          .)
326     ]
327     [ ANY { ANY } ] '\n'    // skip trailing junk
329         // Java imports
330   | "import"
331     (
332         package_dir     (.
333                            if (isUTF8())
334                            {
335                                importDir(t->toStringUTF8());
336                            }
337                            else
338                            {
339                                importDir(t->toString());
340                            }
341                          .)
342       | package_name    (.
343                            if (isUTF8())
344                            {
345                                importFile(t->toStringUTF8());
346                            }
347                            else
348                            {
349                                importFile(t->toString());
350                            }
351                          .)
352     )
353     ';'
354     [ ANY { ANY } ] '\n'    // skip trailing junk
356   | [ ANY { ANY } ] '\n'    // skip any other lines
362 /*---------------------------------------------------------------------------*/
364 END wmkdepend.
366 // ************************************************************************* //