VirtualBox

source: kBuild/trunk/src/lib/kDep.c@ 1733

Last change on this file since 1733 was 1733, checked in by bird, 16 years ago

kDep: shut up pedantic gcc warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/* $Id: kDep.c 1733 2008-09-05 04:35:25Z bird $ */
2/** @file
3 *
4 * kDep - Common Dependency Managemnt Code.
5 *
6 * Copyright (c) 2004-2007 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <errno.h>
35#include <ctype.h>
36#include <limits.h>
37#include <sys/stat.h>
38#include "k/kDefs.h"
39#if K_OS == K_OS_WINDOWS
40# include <windows.h>
41 extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); /* nt_fullpath.c */
42#else
43# include <dirent.h>
44# include <unistd.h>
45# include <stdint.h>
46#endif
47
48#include "kDep.h"
49
50
51/*******************************************************************************
52* Global Variables *
53*******************************************************************************/
54/** List of dependencies. */
55static PDEP g_pDeps = NULL;
56
57
58/**
59 * Corrects all slashes to unix slashes.
60 *
61 * @returns pszFilename.
62 * @param pszFilename The filename to correct.
63 */
64static char *fixslash(char *pszFilename)
65{
66 char *psz = pszFilename;
67 while ((psz = strchr(psz, '\\')) != NULL)
68 *psz++ = '/';
69 return pszFilename;
70}
71
72
73#if K_OS == K_OS_OS2
74
75/**
76 * Corrects the case of a path.
77 *
78 * @param pszPath Pointer to the path, both input and output.
79 * The buffer must be able to hold one more byte than the string length.
80 */
81static void fixcase(char *pszFilename)
82{
83 return;
84}
85
86#elif K_OS != K_OS_WINDOWS
87
88/**
89 * Corrects the case of a path.
90 *
91 * @param pszPath Pointer to the path, both input and output.
92 */
93static void fixcase(char *pszFilename)
94{
95 char *psz;
96
97 /*
98 * Skip the root.
99 */
100 psz = pszFilename;
101 while (*psz == '/')
102 psz++;
103
104 /*
105 * Iterate all the components.
106 */
107 while (*psz)
108 {
109 char chSlash;
110 struct stat s;
111 char *pszStart = psz;
112
113 /*
114 * Find the next slash (or end of string) and terminate the string there.
115 */
116 while (*psz != '/' && *psz)
117 *psz++;
118 chSlash = *psz;
119 *psz = '\0';
120
121 /*
122 * Does this part exist?
123 * If not we'll enumerate the directory and search for an case-insensitive match.
124 */
125 if (stat(pszFilename, &s))
126 {
127 struct dirent *pEntry;
128 DIR *pDir;
129 if (pszStart == pszFilename)
130 pDir = opendir(*pszFilename ? pszFilename : ".");
131 else
132 {
133 pszStart[-1] = '\0';
134 pDir = opendir(pszFilename);
135 pszStart[-1] = '/';
136 }
137 if (!pDir)
138 {
139 *psz = chSlash;
140 break; /* giving up, if we fail to open the directory. */
141 }
142
143 while ((pEntry = readdir(pDir)) != NULL)
144 {
145 if (!strcasecmp(pEntry->d_name, pszStart))
146 {
147 strcpy(pszStart, pEntry->d_name);
148 break;
149 }
150 }
151 closedir(pDir);
152 if (!pEntry)
153 {
154 *psz = chSlash;
155 break; /* giving up if not found. */
156 }
157 }
158
159 /* restore the slash and press on. */
160 *psz = chSlash;
161 while (*psz == '/')
162 psz++;
163 }
164
165 return;
166}
167
168#endif /* !OS/2 && !Windows */
169
170
171/**
172 * 'Optimizes' and corrects the dependencies.
173 */
174void depOptimize(int fFixCase)
175{
176 /*
177 * Walk the list correct the names and re-insert them.
178 */
179 PDEP pDepOrg = g_pDeps;
180 PDEP pDep = g_pDeps;
181 g_pDeps = NULL;
182 for (; pDep; pDep = pDep->pNext)
183 {
184#ifndef PATH_MAX
185 char szFilename[_MAX_PATH + 1];
186#else
187 char szFilename[PATH_MAX + 1];
188#endif
189 char *pszFilename;
190 struct stat s;
191
192 /*
193 * Skip some fictive names like <built-in> and <command line>.
194 */
195 if ( pDep->szFilename[0] == '<'
196 && pDep->szFilename[pDep->cchFilename - 1] == '>')
197 continue;
198 pszFilename = pDep->szFilename;
199
200#if K_OS != K_OS_OS2 && K_OS != K_OS_WINDOWS
201 /*
202 * Skip any drive letters from compilers running in wine.
203 */
204 if (pszFilename[1] == ':')
205 pszFilename += 2;
206#endif
207
208 /*
209 * The microsoft compilers are notoriously screwing up the casing.
210 * This will screw up kmk (/ GNU Make).
211 */
212 if (fFixCase)
213 {
214#if K_OS == K_OS_WINDOWS
215 nt_fullpath(pszFilename, szFilename, sizeof(szFilename));
216 fixslash(szFilename);
217#else
218 strcpy(szFilename, pszFilename);
219 fixslash(szFilename);
220 fixcase(szFilename);
221#endif
222 pszFilename = szFilename;
223 }
224
225 /*
226 * Check that the file exists before we start depending on it.
227 */
228 if (stat(pszFilename, &s))
229 {
230 fprintf(stderr, "kDep: Skipping '%s' - %s!\n", pszFilename, strerror(errno));
231 continue;
232 }
233
234 /*
235 * Insert the corrected dependency.
236 */
237 depAdd(pszFilename, strlen(pszFilename));
238 }
239
240 /*
241 * Free the old ones.
242 */
243 while (pDepOrg)
244 {
245 pDep = pDepOrg;
246 pDepOrg = pDepOrg->pNext;
247 free(pDep);
248 }
249}
250
251
252/**
253 * Prints the dependency chain.
254 *
255 * @returns Pointer to the allocated dependency.
256 * @param pOutput Output stream.
257 */
258void depPrint(FILE *pOutput)
259{
260 PDEP pDep;
261 for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
262 fprintf(pOutput, " \\\n\t%s", pDep->szFilename);
263 fprintf(pOutput, "\n\n");
264}
265
266
267/**
268 * Prints empty dependency stubs for all dependencies.
269 */
270void depPrintStubs(FILE *pOutput)
271{
272 PDEP pDep;
273 for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
274 fprintf(pOutput, "%s:\n\n", pDep->szFilename);
275}
276
277
278/* sdbm:
279 This algorithm was created for sdbm (a public-domain reimplementation of
280 ndbm) database library. it was found to do well in scrambling bits,
281 causing better distribution of the keys and fewer splits. it also happens
282 to be a good general hashing function with good distribution. the actual
283 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
284 is the faster version used in gawk. [there is even a faster, duff-device
285 version] the magic constant 65599 was picked out of thin air while
286 experimenting with different constants, and turns out to be a prime.
287 this is one of the algorithms used in berkeley db (see sleepycat) and
288 elsewhere. */
289static unsigned sdbm(const char *str)
290{
291 unsigned hash = 0;
292 int c;
293
294 while ((c = *(unsigned const char *)str++))
295 hash = c + (hash << 6) + (hash << 16) - hash;
296
297 return hash;
298}
299
300
301/**
302 * Adds a dependency.
303 *
304 * @returns Pointer to the allocated dependency.
305 * @param pszFilename The filename.
306 * @param cchFilename The length of the filename.
307 */
308PDEP depAdd(const char *pszFilename, size_t cchFilename)
309{
310 unsigned uHash = sdbm(pszFilename);
311 PDEP pDep;
312 PDEP pDepPrev;
313
314 /*
315 * Check if we've already got this one.
316 */
317 pDepPrev = NULL;
318 for (pDep = g_pDeps; pDep; pDepPrev = pDep, pDep = pDep->pNext)
319 if ( pDep->uHash == uHash
320 && pDep->cchFilename == cchFilename
321 && !memcmp(pDep->szFilename, pszFilename, cchFilename))
322 return pDep;
323
324 /*
325 * Add it.
326 */
327 pDep = (PDEP)malloc(sizeof(*pDep) + cchFilename);
328 if (!pDep)
329 {
330 fprintf(stderr, "\nOut of memory! (requested %lx bytes)\n\n",
331 (unsigned long)(sizeof(*pDep) + cchFilename));
332 exit(1);
333 }
334
335 pDep->cchFilename = cchFilename;
336 memcpy(pDep->szFilename, pszFilename, cchFilename + 1);
337 pDep->uHash = uHash;
338
339 if (pDepPrev)
340 {
341 pDep->pNext = pDepPrev->pNext;
342 pDepPrev->pNext = pDep;
343 }
344 else
345 {
346 pDep->pNext = g_pDeps;
347 g_pDeps = pDep;
348 }
349 return pDep;
350}
351
352
353/**
354 * Frees the current dependency chain.
355 */
356void depCleanup(void)
357{
358 PDEP pDep = g_pDeps;
359 g_pDeps = NULL;
360 while (pDep)
361 {
362 PDEP pFree = pDep;
363 pDep = pDep->pNext;
364 free(pFree);
365 }
366}
367
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette