3 * kDep - Common Dependency Managemnt Code.
7 * Copyright (c) 2004-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
9 * This file is part of kBuild.
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 3 of the License, or
14 * (at your option) any later version.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
26 /*******************************************************************************
28 *******************************************************************************/
37 #if K_OS == K_OS_WINDOWS
39 extern void nt_fullpath(const char *pszPath
, char *pszFull
, size_t cchFull
); /* nt_fullpath.c */
49 /*******************************************************************************
51 *******************************************************************************/
52 /** List of dependencies. */
53 static PDEP g_pDeps
= NULL
;
57 * Corrects all slashes to unix slashes.
59 * @returns pszFilename.
60 * @param pszFilename The filename to correct.
62 static char *fixslash(char *pszFilename
)
64 char *psz
= pszFilename
;
65 while ((psz
= strchr(psz
, '\\')) != NULL
)
74 * Corrects the case of a path.
76 * @param pszPath Pointer to the path, both input and output.
77 * The buffer must be able to hold one more byte than the string length.
79 static void fixcase(char *pszFilename
)
84 #elif K_OS != K_OS_WINDOWS
87 * Corrects the case of a path.
89 * @param pszPath Pointer to the path, both input and output.
91 static void fixcase(char *pszFilename
)
103 * Iterate all the components.
109 char *pszStart
= psz
;
112 * Find the next slash (or end of string) and terminate the string there.
114 while (*psz
!= '/' && *psz
)
120 * Does this part exist?
121 * If not we'll enumerate the directory and search for an case-insensitive match.
123 if (stat(pszFilename
, &s
))
125 struct dirent
*pEntry
;
127 if (pszStart
== pszFilename
)
128 pDir
= opendir(*pszFilename
? pszFilename
: ".");
132 pDir
= opendir(pszFilename
);
138 break; /* giving up, if we fail to open the directory. */
141 while ((pEntry
= readdir(pDir
)) != NULL
)
143 if (!strcasecmp(pEntry
->d_name
, pszStart
))
145 strcpy(pszStart
, pEntry
->d_name
);
153 break; /* giving up if not found. */
157 /* restore the slash and press on. */
166 #endif /* !OS/2 && !Windows */
170 * 'Optimizes' and corrects the dependencies.
172 void depOptimize(int fFixCase
, int fQuiet
)
175 * Walk the list correct the names and re-insert them.
177 PDEP pDepOrg
= g_pDeps
;
180 for (; pDep
; pDep
= pDep
->pNext
)
183 char szFilename
[_MAX_PATH
+ 1];
185 char szFilename
[PATH_MAX
+ 1];
191 * Skip some fictive names like <built-in> and <command line>.
193 if ( pDep
->szFilename
[0] == '<'
194 && pDep
->szFilename
[pDep
->cchFilename
- 1] == '>')
196 pszFilename
= pDep
->szFilename
;
198 #if K_OS != K_OS_OS2 && K_OS != K_OS_WINDOWS
200 * Skip any drive letters from compilers running in wine.
202 if (pszFilename
[1] == ':')
207 * The microsoft compilers are notoriously screwing up the casing.
208 * This will screw up kmk (/ GNU Make).
212 #if K_OS == K_OS_WINDOWS
213 nt_fullpath(pszFilename
, szFilename
, sizeof(szFilename
));
214 fixslash(szFilename
);
216 strcpy(szFilename
, pszFilename
);
217 fixslash(szFilename
);
220 pszFilename
= szFilename
;
224 * Check that the file exists before we start depending on it.
226 if (stat(pszFilename
, &s
))
230 || ( pszFilename
[0] != '/'
231 && pszFilename
[0] != '\\'
232 && ( !isalpha(pszFilename
[0])
233 || pszFilename
[1] != ':'
234 || ( pszFilename
[2] != '/'
235 && pszFilename
[2] != '\\')))
237 fprintf(stderr
, "kDep: Skipping '%s' - %s!\n", pszFilename
, strerror(errno
));
242 * Insert the corrected dependency.
244 depAdd(pszFilename
, strlen(pszFilename
));
253 pDepOrg
= pDepOrg
->pNext
;
260 * Prints the dependency chain.
262 * @returns Pointer to the allocated dependency.
263 * @param pOutput Output stream.
265 void depPrint(FILE *pOutput
)
268 for (pDep
= g_pDeps
; pDep
; pDep
= pDep
->pNext
)
269 fprintf(pOutput
, " \\\n\t%s", pDep
->szFilename
);
270 fprintf(pOutput
, "\n\n");
275 * Prints empty dependency stubs for all dependencies.
277 void depPrintStubs(FILE *pOutput
)
280 for (pDep
= g_pDeps
; pDep
; pDep
= pDep
->pNext
)
281 fprintf(pOutput
, "%s:\n\n", pDep
->szFilename
);
286 This algorithm was created for sdbm (a public-domain reimplementation of
287 ndbm) database library. it was found to do well in scrambling bits,
288 causing better distribution of the keys and fewer splits. it also happens
289 to be a good general hashing function with good distribution. the actual
290 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
291 is the faster version used in gawk. [there is even a faster, duff-device
292 version] the magic constant 65599 was picked out of thin air while
293 experimenting with different constants, and turns out to be a prime.
294 this is one of the algorithms used in berkeley db (see sleepycat) and
296 static unsigned sdbm(const char *str
)
301 while ((c
= *(unsigned const char *)str
++))
302 hash
= c
+ (hash
<< 6) + (hash
<< 16) - hash
;
311 * @returns Pointer to the allocated dependency.
312 * @param pszFilename The filename.
313 * @param cchFilename The length of the filename.
315 PDEP
depAdd(const char *pszFilename
, size_t cchFilename
)
317 unsigned uHash
= sdbm(pszFilename
);
322 * Check if we've already got this one.
325 for (pDep
= g_pDeps
; pDep
; pDepPrev
= pDep
, pDep
= pDep
->pNext
)
326 if ( pDep
->uHash
== uHash
327 && pDep
->cchFilename
== cchFilename
328 && !memcmp(pDep
->szFilename
, pszFilename
, cchFilename
))
334 pDep
= (PDEP
)malloc(sizeof(*pDep
) + cchFilename
);
337 fprintf(stderr
, "\nOut of memory! (requested %lx bytes)\n\n",
338 (unsigned long)(sizeof(*pDep
) + cchFilename
));
342 pDep
->cchFilename
= cchFilename
;
343 memcpy(pDep
->szFilename
, pszFilename
, cchFilename
+ 1);
348 pDep
->pNext
= pDepPrev
->pNext
;
349 pDepPrev
->pNext
= pDep
;
353 pDep
->pNext
= g_pDeps
;
361 * Frees the current dependency chain.
363 void depCleanup(void)