(file) Return to mkdep.cpp CVS log (file) (dir) Up to [OMI] / omi / tools / mkdep

  1 mike  1.1 /*
  2           **==============================================================================
  3           **
  4           ** Open Management Infrastructure (OMI)
  5           **
  6           ** Copyright (c) Microsoft Corporation
  7           ** 
  8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9           ** use this file except in compliance with the License. You may obtain a copy 
 10           ** of the License at 
 11           **
 12           **     http://www.apache.org/licenses/LICENSE-2.0 
 13           **
 14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18           **
 19           ** See the Apache 2 License for the specific language governing permissions 
 20           ** and limitations under the License.
 21           **
 22 mike  1.1 **==============================================================================
 23           */
 24           
 25           #include <string>
 26           #include <vector>
 27           #include <set>
 28           #include <cstdio>
 29           #include <cstdlib>
 30           #include <cstring>
 31           #include <cctype>
 32           #include <unistd.h>
 33           
 34           using namespace std;
 35           
 36           const char* arg0;
 37           
 38           struct Options
 39           {
 40               vector<string> paths;
 41               string objdir;
 42           };
 43 mike  1.1 
 44           static Options opts;
 45           
 46           static void _GetOptions( 
 47               int& argc, 
 48               char**& argv,
 49               Options& opts)
 50           {
 51               /* For each argument */
 52               for (int i = 0; i < argc; )
 53               {
 54                   /* Number of argv[] elements to remove at end of loop */
 55                   int r = 0;
 56           
 57                   /* Check for -I option */
 58                   if (strncmp(argv[i], "-I", 2) == 0)
 59                   {
 60                       const char* fn = argv[i] + 2;
 61           
 62                       /* Check for mandatory option argument */
 63                       if (*fn)
 64 mike  1.1             {
 65                           r = 1;
 66                       }
 67                       else
 68                       {
 69                           if (i + 1 == argc)
 70                           {
 71                               fprintf(stderr, "%s: missing option argument for -I", arg0);
 72                               exit(1);
 73                           }
 74           
 75                           fn = argv[i+1];
 76                           r = 2;
 77                       }
 78           
 79                       opts.paths.push_back(fn);
 80                   }
 81                   else if (strcmp(argv[i], "--objdir") == 0)
 82                   {
 83                       if (i + 1 == argc)
 84                       {
 85 mike  1.1                 fprintf(stderr, "%s: missing option argument for --objdir", 
 86                               arg0);
 87                           exit(1);
 88                       }
 89           
 90                       opts.objdir = argv[i+1];
 91                       r = 2;
 92                   }
 93                   else if (argv[i][0] == '-')
 94                   {
 95                       fprintf(stderr, "%s: unknown option: %s", arg0, argv[i]);
 96                       exit(1);
 97                   }
 98                   else
 99                       i++;
100           
101                   if (r)
102                   {
103                       memmove(&argv[i], &argv[i+r], sizeof(char*) * (argc-i-r));
104                       argc -= r;
105                   }
106 mike  1.1     }
107           }
108           
109           void PrintDependencies(
110               const char* path, 
111               set<string>& found,
112               size_t level = 0)
113           {
114               vector<string> includes;
115           
116               // Recurse no deeper than this!
117               if (level > 10)
118                   return;
119           
120               // Open file:
121               FILE* is = fopen(path, "rb");
122               {
123                   if (!is)
124                   {
125                       if (level == 0)
126                       {
127 mike  1.1                 fprintf(stderr, "%s: failed to open: %s\n", arg0, path);
128                           return;
129                       }
130           
131                       return;
132                   }
133               }
134           
135               // Find #include directives.
136               char buf[1024];
137               while (fgets(buf, sizeof(buf), is) != NULL)
138               {
139                   char* p = buf;
140           
141                   // Skip leading whitespace:
142                   while (*p && isspace(*p))
143                       p++;
144           
145                   // Skip lines that do not begin with preprocessor directives.
146                   if (*p != '#')
147                       continue;
148 mike  1.1         p++;
149           
150                   // Skip whitespace:
151                   while (*p && isspace(*p))
152                       p++;
153           
154                   // Skip line if not 'include' directive.
155                   if (strncmp(p, "include", 7) != 0)
156                       continue;
157                   p += 7;
158           
159                   // Skip whitespace:
160                   while (*p && isspace(*p))
161                       p++;
162           
163                   // Skip if not '"' or '<':
164                   if (*p != '"' && *p != '<')
165                       continue;
166                   p++;
167           
168                   // Extract file name (between "..." or <...>).
169 mike  1.1         {
170                       const char* start = p;
171                       while (*p && *p != '"' && *p != '>')
172                           p++;
173           
174                       if (p == start)
175                           continue;
176           
177                       includes.push_back(string(start, p - start));
178                   }
179               }
180           
181               // Close file:
182               fclose(is);
183           
184               // Search for each include file on the paths.
185               for (size_t i = 0; i < includes.size(); i++)
186               {
187                   for (size_t j = 0; j < opts.paths.size(); j++)
188                   {
189                       string path = includes[i];
190 mike  1.1 
191                       // Check relative first:
192                       if (access(path.c_str(), R_OK) == 0)
193                       {
194                           if (found.find(path) == found.end())
195                           {
196                               printf(" \\\n    %s", path.c_str());
197                               found.insert(path);
198                               PrintDependencies(path.c_str(), found, level+1);
199                           }
200                       }
201           
202                       // Find absolute path:
203                       path = opts.paths[j] + "/" + includes[i];
204                       if (path[0] != '/')
205                       {
206                           char cwd[1024];
207                           if (getcwd(cwd, sizeof(cwd)) == NULL)
208                           {
209                               fprintf(stdout, "%s: failed to stat current dir\n", arg0);
210                               exit(1);
211 mike  1.1                 }
212           
213                           path = string(cwd) + string("/") + path;
214                       }
215           
216                       if (access(path.c_str(), R_OK) == 0)
217                       {
218                           if (found.find(path) == found.end())
219                           {
220                               printf(" \\\n    %s", path.c_str());
221                               found.insert(path);
222                               PrintDependencies(path.c_str(), found, level+1);
223                           }
224                       }
225                   }
226               }
227           }
228           
229           int main(int argc, char** argv)
230           {
231               arg0 = argv[0];
232 mike  1.1 
233               // Get command line options.
234               _GetOptions(argc, argv, opts);
235           
236               // Check arguments:
237               if (argc < 2)
238               {
239                   fprintf(stderr, "Usage: %s [OPTIONS-AND-ARGUMENTS]\n", argv[0]);
240                   exit(1);
241               }
242           
243               // Make dependencies for each file.
244               for (int i = 1; i < argc; i++)
245               {
246                   string srcfile = argv[i];
247                   string objfile;
248           
249                   // Replace '.cpp' with '.o'
250                   if (srcfile.size() >= 4 && srcfile.substr(srcfile.size()-4) == ".cpp")
251                   {
252                       objfile = srcfile.substr(0, srcfile.size()-4) + ".o";
253 mike  1.1         }
254           
255                   // Replace '.c' with '.o'
256                   if (srcfile.size() >= 2 && srcfile.substr(srcfile.size()-2) == ".c")
257                   {
258                       objfile = srcfile.substr(0, srcfile.size()-2) + ".o";
259                   }
260           
261                   set<string> found;
262           
263                   if (opts.objdir.size())
264                       printf("%s/%s:", opts.objdir.c_str(), objfile.c_str());
265                   else
266                       printf("%s:", objfile.c_str());
267           
268                   PrintDependencies(srcfile.c_str(), found);
269                   printf("\n\n");
270               }
271           
272               return 0;
273           }

ViewCVS 0.9.2