source: trunk/src/kmk/kbuild.c@ 1922

Last change on this file since 1922 was 1922, checked in by bird, 17 years ago

kbuild.c: got rid of the va_list fun.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 71.0 KB
Line 
1/* $Id: kbuild.c 1922 2008-10-24 02:10:58Z bird $ */
2/** @file
3 *
4 * kBuild specific make functionality.
5 *
6 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
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/* No GNU coding style here! */
28
29
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include "make.h"
34#include "filedef.h"
35#include "variable.h"
36#include "dep.h"
37#include "debug.h"
38#ifdef WINDOWS32
39# include "pathstuff.h"
40# include <Windows.h>
41#endif
42#if defined(__APPLE__)
43# include <mach-o/dyld.h>
44#endif
45
46#include "kbuild.h"
47
48#include <assert.h>
49#include <stdarg.h>
50
51
52/*******************************************************************************
53* Defined Constants And Macros *
54*******************************************************************************/
55#ifndef va_copy
56# define va_copy(dst, src) do {(dst) = (src);} while (0)
57#endif
58
59/** Helper for passing a string constant to kbuild_get_variable_n. */
60#define ST(strconst) strconst, sizeof(strconst) - 1
61
62#if 1
63# define my_memcpy(dst, src, len) \
64 do { \
65 if (len > 8) \
66 memcpy(dst, src, len); \
67 else \
68 switch (len) \
69 { \
70 case 8: dst[7] = src[7]; \
71 case 7: dst[6] = src[6]; \
72 case 6: dst[5] = src[5]; \
73 case 5: dst[4] = src[4]; \
74 case 4: dst[3] = src[3]; \
75 case 3: dst[2] = src[2]; \
76 case 2: dst[1] = src[1]; \
77 case 1: dst[0] = src[0]; \
78 case 0: break; \
79 } \
80 } while (0)
81#elif defined(__GNUC__)
82# define my_memcpy __builtin_memcpy
83#elif defined(_MSC_VER)
84# pragma instrinic(memcpy)
85# define my_memcpy memcpy
86#endif
87
88
89/*******************************************************************************
90* Global Variables *
91*******************************************************************************/
92/** The argv[0] passed to main. */
93static const char *g_pszExeName;
94/** The initial working directory. */
95static char *g_pszInitialCwd;
96
97
98/**
99 * Initialize kBuild stuff.
100 *
101 * @param argc Number of arguments to main().
102 * @param argv The main() argument vector.
103 */
104void init_kbuild(int argc, char **argv)
105{
106 int rc;
107 PATH_VAR(szTmp);
108
109 /*
110 * Get the initial cwd for use in my_abspath.
111 */
112#ifdef WINDOWS32
113 if (getcwd_fs(szTmp, GET_PATH_MAX) != 0)
114#else
115 if (getcwd(szTmp, GET_PATH_MAX) != 0)
116#endif
117 g_pszInitialCwd = xstrdup(szTmp);
118 else
119 fatal(NILF, _("getcwd failed"));
120
121 /*
122 * Determin the executable name.
123 */
124 rc = -1;
125#if defined(__APPLE__)
126 {
127 const char *pszImageName = _dyld_get_image_name(0);
128 if (pszImageName)
129 {
130 size_t cchImageName = strlen(pszImageName);
131 if (cchImageName < GET_PATH_MAX)
132 {
133 memcpy(szTmp, pszImageName, cchImageName + 1);
134 rc = 0;
135 }
136 }
137 }
138
139#elif defined(__FreeBSD__)
140 rc = readlink("/proc/curproc/file", szTmp, GET_PATH_MAX - 1);
141 if (rc < 0 || rc == GET_PATH_MAX - 1)
142 rc = -1;
143 else
144 szTmp[rc] = '\0';
145
146#elif defined(__gnu_linux__) /** @todo find proper define... */
147 rc = readlink("/proc/self/exe", szTmp, GET_PATH_MAX - 1);
148 if (rc < 0 || rc == GET_PATH_MAX - 1)
149 rc = -1;
150 else
151 szTmp[rc] = '\0';
152
153#elif defined(__OS2__)
154 _execname(szTmp, GET_PATH_MAX);
155 rc = 0;
156
157#elif defined(__sun__)
158 {
159 char szTmp2[64];
160 snprintf(szTmp2, sizeof(szTmp2), "/proc/%d/path/a.out", getpid());
161 rc = readlink(szTmp2, szTmp, GET_PATH_MAX - 1);
162 if (rc < 0 || rc == GET_PATH_MAX - 1)
163 rc = -1;
164 else
165 szTmp[rc] = '\0';
166 }
167
168#elif defined(WINDOWS32)
169 if (GetModuleFileName(GetModuleHandle(NULL), szTmp, GET_PATH_MAX))
170 rc = 0;
171
172#endif
173
174#if !defined(__OS2__) && !defined(WINDOWS32)
175 /* fallback, try use the path to locate the binary. */
176 if ( rc < 0
177 && access(argv[0], X_OK))
178 {
179 size_t cchArgv0 = strlen(argv[0]);
180 const char *pszPath = getenv("PATH");
181 char *pszCopy = xstrdup(pszPath ? pszPath : ".");
182 char *psz = pszCopy;
183 while (*psz)
184 {
185 size_t cch;
186 char *pszEnd = strchr(psz, PATH_SEPARATOR_CHAR);
187 if (!pszEnd)
188 pszEnd = strchr(psz, '\0');
189 cch = pszEnd - psz;
190 if (cch + cchArgv0 + 2 <= GET_PATH_MAX)
191 {
192 memcpy(szTmp, psz, cch);
193 szTmp[cch] = '/';
194 memcpy(&szTmp[cch + 1], argv[0], cchArgv0 + 1);
195 if (!access(szTmp, X_OK))
196 {
197 rc = 0;
198 break;
199 }
200 }
201
202 /* next */
203 psz = pszEnd;
204 while (*psz == PATH_SEPARATOR_CHAR)
205 psz++;
206 }
207 free(pszCopy);
208 }
209#endif
210
211 if (rc < 0)
212 g_pszExeName = argv[0];
213 else
214 g_pszExeName = xstrdup(szTmp);
215
216 (void)argc;
217}
218
219
220/**
221 * Wrapper that ensures correct starting_directory.
222 */
223static char *my_abspath(const char *pszIn, char *pszOut)
224{
225 char *pszSaved, *pszRet;
226
227 pszSaved = starting_directory;
228 starting_directory = g_pszInitialCwd;
229 pszRet = abspath(pszIn, pszOut);
230 starting_directory = pszSaved;
231
232 return pszRet;
233}
234
235
236/**
237 * Determin the KBUILD_PATH value.
238 *
239 * @returns Pointer to static a buffer containing the value (consider it read-only).
240 */
241const char *get_kbuild_path(void)
242{
243 static const char *s_pszPath = NULL;
244 if (!s_pszPath)
245 {
246 PATH_VAR(szTmpPath);
247 const char *pszEnvVar = getenv("KBUILD_PATH");
248 if ( !pszEnvVar
249 || !my_abspath(pszEnvVar, szTmpPath))
250 {
251 const char *pszEnvVar = getenv("PATH_KBUILD");
252 if ( !pszEnvVar
253 || !my_abspath(pszEnvVar, szTmpPath))
254 {
255#ifdef KBUILD_PATH
256 return s_pszPath = KBUILD_PATH;
257#else
258 /* $(abspath $(KBUILD_BIN_PATH)/../..)*/
259 size_t cch = strlen(get_kbuild_bin_path());
260 char *pszTmp2 = alloca(cch + sizeof("/../.."));
261 strcat(strcpy(pszTmp2, get_kbuild_bin_path()), "/../..");
262 if (!my_abspath(pszTmp2, szTmpPath))
263 fatal(NILF, _("failed to determin KBUILD_PATH"));
264#endif
265 }
266 }
267 s_pszPath = xstrdup(szTmpPath);
268 }
269 return s_pszPath;
270}
271
272
273/**
274 * Determin the KBUILD_BIN_PATH value.
275 *
276 * @returns Pointer to static a buffer containing the value (consider it read-only).
277 */
278const char *get_kbuild_bin_path(void)
279{
280 static const char *s_pszPath = NULL;
281 if (!s_pszPath)
282 {
283 PATH_VAR(szTmpPath);
284
285 const char *pszEnvVar = getenv("KBUILD_BIN_PATH");
286 if ( !pszEnvVar
287 || !my_abspath(pszEnvVar, szTmpPath))
288 {
289 const char *pszEnvVar = getenv("PATH_KBUILD_BIN");
290 if ( !pszEnvVar
291 || !my_abspath(pszEnvVar, szTmpPath))
292 {
293#ifdef KBUILD_PATH
294 return s_pszPath = KBUILD_BIN_PATH;
295#else
296 /* $(abspath $(dir $(ARGV0)).) */
297 size_t cch = strlen(g_pszExeName);
298 char *pszTmp2 = alloca(cch + sizeof("."));
299 char *pszSep = pszTmp2 + cch - 1;
300 memcpy(pszTmp2, g_pszExeName, cch);
301# ifdef HAVE_DOS_PATHS
302 while (pszSep >= pszTmp2 && *pszSep != '/' && *pszSep != '\\' && *pszSep != ':')
303# else
304 while (pszSep >= pszTmp2 && *pszSep != '/')
305# endif
306 pszSep--;
307 if (pszSep >= pszTmp2)
308 strcpy(pszSep + 1, ".");
309 else
310 strcpy(pszTmp2, ".");
311
312 if (!my_abspath(pszTmp2, szTmpPath))
313 fatal(NILF, _("failed to determin KBUILD_BIN_PATH (pszTmp2=%s szTmpPath=%s)"), pszTmp2, szTmpPath);
314#endif /* !KBUILD_PATH */
315 }
316 }
317 s_pszPath = xstrdup(szTmpPath);
318 }
319 return s_pszPath;
320}
321
322
323/**
324 * Determin the location of default kBuild shell.
325 *
326 * @returns Pointer to static a buffer containing the location (consider it read-only).
327 */
328const char *get_default_kbuild_shell(void)
329{
330 static char *s_pszDefaultShell = NULL;
331 if (!s_pszDefaultShell)
332 {
333#if defined(__OS2__) || defined(_WIN32) || defined(WINDOWS32)
334 static const char s_szShellName[] = "/kmk_ash.exe";
335#else
336 static const char s_szShellName[] = "/kmk_ash";
337#endif
338 const char *pszBin = get_kbuild_bin_path();
339 size_t cchBin = strlen(pszBin);
340 s_pszDefaultShell = xmalloc(cchBin + sizeof(s_szShellName));
341 memcpy(s_pszDefaultShell, pszBin, cchBin);
342 memcpy(&s_pszDefaultShell[cchBin], s_szShellName, sizeof(s_szShellName));
343 }
344 return s_pszDefaultShell;
345}
346
347#ifdef KMK_HELPERS
348
349/**
350 * Applies the specified default path to any relative paths in *ppsz.
351 *
352 * @param pDefPath The default path.
353 * @param ppsz Pointer to the string pointer. If we expand anything, *ppsz
354 * will be replaced and the caller is responsible for calling free() on it.
355 * @param pcch IN: *pcch contains the current string length.
356 * OUT: *pcch contains the new string length.
357 * @param pcchAlloc *pcchAlloc contains the length allocated for the string. Can be NULL.
358 * @param fCanFree Whether *ppsz should be freed when we replace it.
359 */
360static void
361kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, int *pcch, int *pcchAlloc, int fCanFree)
362{
363 const char *pszIterator;
364 const char *pszInCur;
365 unsigned int cchInCur;
366 unsigned int cRelativePaths;
367
368 /*
369 * The first pass, count the relative paths.
370 */
371 cRelativePaths = 0;
372 pszIterator = *ppsz;
373 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
374 {
375 /* is relative? */
376#ifdef HAVE_DOS_PATHS
377 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
378#else
379 if (pszInCur[0] != '/')
380#endif
381 cRelativePaths++;
382 }
383
384 /*
385 * The second pass construct the new string.
386 */
387 if (cRelativePaths)
388 {
389 const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1;
390 char *pszOut = xmalloc(cchOut);
391 char *pszOutCur = pszOut;
392 const char *pszInNextCopy = *ppsz;
393
394 cRelativePaths = 0;
395 pszIterator = *ppsz;
396 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
397 {
398 /* is relative? */
399#ifdef HAVE_DOS_PATHS
400 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
401#else
402 if (pszInCur[0] != '/')
403#endif
404 {
405 PATH_VAR(szAbsPathIn);
406 PATH_VAR(szAbsPathOut);
407
408 if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX)
409 continue;
410
411 /* Create the abspath input. */
412 memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length);
413 szAbsPathIn[pDefPath->value_length] = '/';
414 memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur);
415 szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0';
416
417 if (abspath(szAbsPathIn, szAbsPathOut) != NULL)
418 {
419 const size_t cchAbsPathOut = strlen(szAbsPathOut);
420 assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur);
421
422 /* copy leading input */
423 if (pszInCur != pszInNextCopy)
424 {
425 const size_t cchCopy = pszInCur - pszInNextCopy;
426 memcpy(pszOutCur, pszInNextCopy, cchCopy);
427 pszOutCur += cchCopy;
428 }
429 pszInNextCopy = pszInCur + cchInCur;
430
431 /* copy out the abspath. */
432 memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut);
433 pszOutCur += cchAbsPathOut;
434 }
435 }
436 }
437 /* the final copy (includes the nil). */
438 cchInCur = *ppsz + *pcch - pszInNextCopy;
439 memcpy(pszOutCur, pszInNextCopy, cchInCur);
440 pszOutCur += cchInCur;
441 *pszOutCur = '\0';
442 assert((size_t)(pszOutCur - pszOut) < cchOut);
443
444 /* set return values */
445 if (fCanFree)
446 free(*ppsz);
447 *ppsz = pszOut;
448 *pcch = pszOutCur - pszOut;
449 if (pcchAlloc)
450 *pcchAlloc = cchOut;
451 }
452}
453
454/**
455 * Gets a variable that must exist.
456 * Will cause a fatal failure if the variable doesn't exist.
457 *
458 * @returns Pointer to the variable.
459 * @param pszName The variable name.
460 * @param cchName The name length.
461 */
462MY_INLINE struct variable *
463kbuild_get_variable_n(const char *pszName, size_t cchName)
464{
465#ifndef NDEBUG
466 int i;
467#endif
468 struct variable *pVar = lookup_variable(pszName, cchName);
469 if (!pVar)
470 fatal(NILF, _("variable `%.*s' isn't defined!"), (int)cchName, pszName);
471 if (pVar->recursive)
472 fatal(NILF, _("variable `%.*s' is defined as `recursive' instead of `simple'!"), (int)cchName, pszName);
473#ifndef NDEBUG
474 i = strlen(pVar->value);
475 if (i != pVar->value_length)
476 {
477 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
478# ifdef _MSC_VER
479 __debugbreak();
480# endif
481 assert(0);
482 }
483#endif
484 return pVar;
485}
486
487
488#if 0 /* unused */
489/**
490 * Gets a variable that must exist.
491 * Will cause a fatal failure if the variable doesn't exist.
492 *
493 * @returns Pointer to the variable.
494 * @param pszName The variable name.
495 */
496static struct variable *
497kbuild_get_variable(const char *pszName)
498{
499 return kbuild_get_variable_n(pszName, strlen(pszName));
500}
501#endif
502
503
504/**
505 * Gets a variable that must exist and can be recursive.
506 * Will cause a fatal failure if the variable doesn't exist.
507 *
508 * @returns Pointer to the variable.
509 * @param pszName The variable name.
510 */
511static struct variable *
512kbuild_get_recursive_variable(const char *pszName)
513{
514#ifndef NDEBUG
515 int i;
516#endif
517 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
518 if (!pVar)
519 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
520#ifndef NDEBUG
521 i = strlen(pVar->value);
522 if (i != pVar->value_length)
523 {
524 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
525# ifdef _MSC_VER
526 __debugbreak();
527# endif
528 assert(0);
529 }
530#endif
531 return pVar;
532}
533
534
535/**
536 * Gets a variable that doesn't have to exit, but if it does can be recursive.
537 *
538 * @returns Pointer to the variable.
539 * NULL if not found.
540 * @param pszName The variable name.
541 */
542static struct variable *
543kbuild_query_recursive_variable(const char *pszName)
544{
545#ifndef NDEBUG
546 int i;
547#endif
548 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
549 if (pVar)
550 {
551#ifndef NDEBUG
552 i = strlen(pVar->value);
553 if (i != pVar->value_length)
554 {
555 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
556# ifdef _MSC_VER
557 __debugbreak();
558# endif
559 assert(0);
560 }
561#endif
562 }
563 return pVar;
564}
565
566
567/**
568 * Converts the specified variable into a 'simple' one.
569 * @returns pVar.
570 * @param pVar The variable.
571 */
572static struct variable *
573kbuild_simplify_variable(struct variable *pVar)
574{
575 if (memchr(pVar->value, '$', pVar->value_length))
576 {
577 unsigned int value_len;
578 char *pszExpanded = allocated_variable_expand_2(pVar->value, pVar->value_length, &value_len);
579 free(pVar->value);
580 pVar->value = pszExpanded;
581 pVar->value_length = value_len;
582 pVar->value_alloc_len = value_len + 1;
583 }
584 pVar->recursive = 0;
585 return pVar;
586}
587
588
589/**
590 * Looks up a variable.
591 * The value_length field is valid upon successful return.
592 *
593 * @returns Pointer to the variable. NULL if not found.
594 * @param pszName The variable name.
595 * @param cchName The name length.
596 */
597MY_INLINE struct variable *
598kbuild_lookup_variable_n(const char *pszName, size_t cchName)
599{
600 struct variable *pVar = lookup_variable(pszName, cchName);
601 if (pVar)
602 {
603#ifndef NDEBUG
604 int i = strlen(pVar->value);
605 if (i != pVar->value_length)
606 {
607 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
608# ifdef _MSC_VER
609 __debugbreak();
610# endif
611 assert(0);
612 }
613#endif
614 /* Make sure the variable is simple, convert it if necessary. */
615 if (pVar->recursive)
616 kbuild_simplify_variable(pVar);
617 }
618 return pVar;
619}
620
621
622/**
623 * Looks up a variable.
624 * The value_length field is valid upon successful return.
625 *
626 * @returns Pointer to the variable. NULL if not found.
627 * @param pszName The variable name.
628 */
629MY_INLINE struct variable *
630kbuild_lookup_variable(const char *pszName)
631{
632 return kbuild_lookup_variable_n(pszName, strlen(pszName));
633}
634
635
636/**
637 * Looks up a variable and applies default a path to all relative paths.
638 * The value_length field is valid upon successful return.
639 *
640 * @returns Pointer to the variable. NULL if not found.
641 * @param pDefPath The default path.
642 * @param pszName The variable name.
643 * @param cchName The name length.
644 */
645MY_INLINE struct variable *
646kbuild_lookup_variable_defpath_n(struct variable *pDefPath, const char *pszName, size_t cchName)
647{
648 struct variable *pVar = kbuild_lookup_variable_n(pszName, cchName);
649 if (pVar && pDefPath)
650 kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
651 return pVar;
652}
653
654
655/**
656 * Looks up a variable and applies default a path to all relative paths.
657 * The value_length field is valid upon successful return.
658 *
659 * @returns Pointer to the variable. NULL if not found.
660 * @param pDefPath The default path.
661 * @param pszName The variable name.
662 */
663MY_INLINE struct variable *
664kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
665{
666 struct variable *pVar = kbuild_lookup_variable(pszName);
667 if (pVar && pDefPath)
668 kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
669 return pVar;
670}
671
672
673/**
674 * Gets the first defined property variable.
675 */
676static struct variable *
677kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
678 struct variable *pTool, struct variable *pType,
679 struct variable *pBldTrg, struct variable *pBldTrgArch,
680 const char *pszPropF1, char cchPropF1,
681 const char *pszPropF2, char cchPropF2,
682 const char *pszVarName)
683{
684 struct variable *pVar;
685 size_t cchBuf;
686 char *pszBuf;
687 char *psz, *psz1, *psz2, *psz3, *psz4;
688
689 /* calc and allocate a too big name buffer. */
690 cchBuf = cchPropF2 + 1
691 + cchPropF1 + 1
692 + pTarget->value_length + 1
693 + pSource->value_length + 1
694 + (pTool ? pTool->value_length + 1 : 0)
695 + pType->value_length + 1
696 + pBldTrg->value_length + 1
697 + pBldTrgArch->value_length + 1;
698 pszBuf = xmalloc(cchBuf);
699
700#define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
701#define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
702#define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
703#define ADD_CH(ch) do { *psz++ = (ch); } while (0)
704
705 /*
706 * $(target)_$(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
707 */
708 psz = pszBuf;
709 ADD_VAR(pTarget);
710 ADD_CH('_');
711 ADD_VAR(pSource);
712 ADD_CH('_');
713 psz2 = psz;
714 ADD_VAR(pType);
715 ADD_STR(pszPropF2, cchPropF2);
716 psz3 = psz;
717 ADD_CH('.');
718 ADD_VAR(pBldTrg);
719 psz4 = psz;
720 ADD_CH('.');
721 ADD_VAR(pBldTrgArch);
722 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
723
724 /* $(target)_$(source)_$(type)$(propf2).$(bld_trg) */
725 if (!pVar)
726 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
727
728 /* $(target)_$(source)_$(type)$(propf2) */
729 if (!pVar)
730 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
731
732 /*
733 * $(target)_$(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
734 */
735 if (!pVar)
736 {
737 psz = psz2;
738 ADD_STR(pszPropF2, cchPropF2);
739 psz3 = psz;
740 ADD_CH('.');
741 ADD_VAR(pBldTrg);
742 psz4 = psz;
743 ADD_CH('.');
744 ADD_VAR(pBldTrgArch);
745 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
746
747 /* $(target)_$(source)_$(propf2).$(bld_trg) */
748 if (!pVar)
749 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
750
751 /* $(target)_$(source)_$(propf2) */
752 if (!pVar)
753 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
754 }
755
756
757 /*
758 * $(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
759 */
760 if (!pVar)
761 {
762 psz = pszBuf;
763 ADD_VAR(pSource);
764 ADD_CH('_');
765 psz2 = psz;
766 ADD_VAR(pType);
767 ADD_STR(pszPropF2, cchPropF2);
768 psz3 = psz;
769 ADD_CH('.');
770 ADD_VAR(pBldTrg);
771 psz4 = psz;
772 ADD_CH('.');
773 ADD_VAR(pBldTrgArch);
774 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
775
776 /* $(source)_$(type)$(propf2).$(bld_trg) */
777 if (!pVar)
778 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
779
780 /* $(source)_$(type)$(propf2) */
781 if (!pVar)
782 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
783
784 /*
785 * $(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
786 */
787 if (!pVar)
788 {
789 psz = psz2;
790 ADD_STR(pszPropF2, cchPropF2);
791 psz3 = psz;
792 ADD_CH('.');
793 ADD_VAR(pBldTrg);
794 psz4 = psz;
795 ADD_CH('.');
796 ADD_VAR(pBldTrgArch);
797 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
798
799 /* $(source)_$(propf2).$(bld_trg) */
800 if (!pVar)
801 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
802
803 /* $(source)_$(propf2) */
804 if (!pVar)
805 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
806 }
807 }
808
809 /*
810 * $(target)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
811 */
812 if (!pVar)
813 {
814 psz = pszBuf;
815 ADD_VAR(pTarget);
816 ADD_CH('_');
817 psz2 = psz;
818 ADD_VAR(pType);
819 ADD_STR(pszPropF2, cchPropF2);
820 psz3 = psz;
821 ADD_CH('.');
822 ADD_VAR(pBldTrg);
823 psz4 = psz;
824 ADD_CH('.');
825 ADD_VAR(pBldTrgArch);
826 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
827
828 /* $(target)_$(type)$(propf2).$(bld_trg) */
829 if (!pVar)
830 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
831
832 /* $(target)_$(type)$(propf2) */
833 if (!pVar)
834 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
835
836 /* $(target)_$(propf2).$(bld_trg).$(bld_trg_arch) */
837 if (!pVar)
838 {
839 psz = psz2;
840 ADD_STR(pszPropF2, cchPropF2);
841 psz3 = psz;
842 ADD_CH('.');
843 ADD_VAR(pBldTrg);
844 psz4 = psz;
845 ADD_CH('.');
846 ADD_VAR(pBldTrgArch);
847 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
848 }
849
850 /* $(target)_$(propf2).$(bld_trg) */
851 if (!pVar)
852 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
853
854 /* $(target)_$(propf2) */
855 if (!pVar)
856 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
857 }
858
859 /*
860 * TOOL_$(tool)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
861 */
862 if (!pVar && pTool)
863 {
864 psz = pszBuf;
865 ADD_CSTR("TOOL_");
866 ADD_VAR(pTool);
867 ADD_CH('_');
868 psz2 = psz;
869 ADD_VAR(pType);
870 ADD_STR(pszPropF2, cchPropF2);
871 psz3 = psz;
872 ADD_CH('.');
873 ADD_VAR(pBldTrg);
874 psz4 = psz;
875 ADD_CH('.');
876 ADD_VAR(pBldTrgArch);
877 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
878
879 /* TOOL_$(tool)_$(type)$(propf2).$(bld_trg) */
880 if (!pVar)
881 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
882
883 /* TOOL_$(tool)_$(type)$(propf2) */
884 if (!pVar)
885 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
886
887 /* TOOL_$(tool)_$(propf2).$(bld_trg).$(bld_trg_arch) */
888 if (!pVar)
889 {
890 psz = psz2;
891 ADD_STR(pszPropF2, cchPropF2);
892 psz3 = psz;
893 ADD_CH('.');
894 ADD_VAR(pBldTrg);
895 psz4 = psz;
896 ADD_CH('.');
897 ADD_VAR(pBldTrgArch);
898 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
899
900 /* TOOL_$(tool)_$(propf2).$(bld_trg) */
901 if (!pVar)
902 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
903
904 /* TOOL_$(tool)_$(propf2) */
905 if (!pVar)
906 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
907 }
908 }
909
910 /*
911 * $(type)$(propf1).$(bld_trg).$(bld_trg_arch)
912 */
913 if (!pVar)
914 {
915 psz = pszBuf;
916 ADD_VAR(pType);
917 ADD_STR(pszPropF1, cchPropF1);
918 psz3 = psz;
919 ADD_CH('.');
920 ADD_VAR(pBldTrg);
921 psz4 = psz;
922 ADD_CH('.');
923 ADD_VAR(pBldTrgArch);
924 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
925
926 /* $(type)$(propf1).$(bld_trg) */
927 if (!pVar)
928 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
929
930 /* $(type)$(propf1) */
931 if (!pVar)
932 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
933
934 /*
935 * $(propf1).$(bld_trg).$(bld_trg_arch)
936 */
937 if (!pVar)
938 {
939 psz1 = pszBuf + pType->value_length;
940 pVar = kbuild_lookup_variable_n(psz1, psz - psz1);
941
942 /* $(propf1).$(bld_trg) */
943 if (!pVar)
944 pVar = kbuild_lookup_variable_n(psz1, psz4 - psz1);
945
946 /* $(propf1) */
947 if (!pVar)
948 pVar = kbuild_lookup_variable_n(pszPropF1, cchPropF1);
949 }
950 }
951 free(pszBuf);
952#undef ADD_VAR
953#undef ADD_STR
954#undef ADD_CSTR
955#undef ADD_CH
956
957 if (pVar)
958 {
959 /* strip it */
960 char *psz = pVar->value;
961 char *pszEnd = psz + pVar->value_length;
962 while (isblank((unsigned char)*psz))
963 psz++;
964 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
965 pszEnd--;
966 if (pszEnd > psz)
967 {
968 char chSaved = *pszEnd;
969 *pszEnd = '\0';
970 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
971 1 /* duplicate */, o_local, 0 /* !recursive */);
972 *pszEnd = chSaved;
973 if (pVar)
974 return pVar;
975 }
976 }
977 return NULL;
978}
979
980
981/*
982_SOURCE_TOOL = $(strip $(firstword \
983 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
984 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
985 $($(target)_$(source)_$(type)TOOL) \
986 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
987 $($(target)_$(source)_TOOL.$(bld_trg)) \
988 $($(target)_$(source)_TOOL) \
989 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
990 $($(source)_$(type)TOOL.$(bld_trg)) \
991 $($(source)_$(type)TOOL) \
992 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
993 $($(source)_TOOL.$(bld_trg)) \
994 $($(source)_TOOL) \
995 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
996 $($(target)_$(type)TOOL.$(bld_trg)) \
997 $($(target)_$(type)TOOL) \
998 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
999 $($(target)_TOOL.$(bld_trg)) \
1000 $($(target)_TOOL) \
1001 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
1002 $($(type)TOOL.$(bld_trg)) \
1003 $($(type)TOOL) \
1004 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
1005 $(TOOL.$(bld_trg)) \
1006 $(TOOL) ))
1007*/
1008static struct variable *
1009kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
1010 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
1011{
1012 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
1013 "TOOL", sizeof("TOOL") - 1,
1014 "TOOL", sizeof("TOOL") - 1,
1015 pszVarName);
1016 if (!pVar)
1017 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
1018 return pVar;
1019}
1020
1021
1022/* Implements _SOURCE_TOOL. */
1023char *
1024func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
1025{
1026 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable_n(ST("target")),
1027 kbuild_get_variable_n(ST("source")),
1028 kbuild_get_variable_n(ST("type")),
1029 kbuild_get_variable_n(ST("bld_trg")),
1030 kbuild_get_variable_n(ST("bld_trg_arch")),
1031 argv[0]);
1032 if (pVar)
1033 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1034 (void)pszFuncName;
1035 return o;
1036
1037}
1038
1039
1040/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
1041$(firstword \
1042 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1043 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
1044 $($(target)_$(source)_OBJSUFF)\
1045 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1046 $($(source)_OBJSUFF.$(bld_trg))\
1047 $($(source)_OBJSUFF)\
1048 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1049 $($(target)_OBJSUFF.$(bld_trg))\
1050 $($(target)_OBJSUFF)\
1051 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1052 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
1053 $(TOOL_$(tool)_$(type)OBJSUFF)\
1054 $(SUFF_OBJ))
1055*/
1056static struct variable *
1057kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
1058 struct variable *pTool, struct variable *pType,
1059 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
1060{
1061 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
1062 "SUFF_OBJ", sizeof("SUFF_OBJ") - 1,
1063 "OBJSUFF", sizeof("OBJSUFF") - 1,
1064 pszVarName);
1065 if (!pVar)
1066 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
1067 return pVar;
1068}
1069
1070
1071/* */
1072char *
1073func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
1074{
1075 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable_n(ST("target")),
1076 kbuild_get_variable_n(ST("source")),
1077 kbuild_get_variable_n(ST("tool")),
1078 kbuild_get_variable_n(ST("type")),
1079 kbuild_get_variable_n(ST("bld_trg")),
1080 kbuild_get_variable_n(ST("bld_trg_arch")),
1081 argv[0]);
1082 if (pVar)
1083 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1084 (void)pszFuncName;
1085 return o;
1086
1087}
1088
1089
1090/*
1091## Figure out where to put object files.
1092# @param $1 source file
1093# @param $2 normalized main target
1094# @remark There are two major hacks here:
1095# 1. Source files in the output directory are translated into a gen/ subdir.
1096# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
1097_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
1098 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
1099*/
1100static struct variable *
1101kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
1102{
1103 struct variable *pPathTarget = kbuild_get_variable_n(ST("PATH_TARGET"));
1104 struct variable *pPathRoot = kbuild_get_variable_n(ST("PATH_ROOT"));
1105 struct variable *pPathSubCur = kbuild_get_variable_n(ST("PATH_SUB_CURRENT"));
1106 const char *pszSrcPrefix = NULL;
1107 size_t cchSrcPrefix = 0;
1108 size_t cchSrc = 0;
1109 const char *pszSrcEnd;
1110 char *pszSrc;
1111 char *pszResult;
1112 char *psz;
1113 char *pszDot;
1114 size_t cch;
1115
1116 /*
1117 * Strip the source filename of any uncessary leading path and root specs.
1118 */
1119 /* */
1120 if ( pSource->value_length > pPathTarget->value_length
1121 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
1122 {
1123 pszSrc = pSource->value + pPathTarget->value_length;
1124 pszSrcPrefix = "gen/";
1125 cchSrcPrefix = sizeof("gen/") - 1;
1126 if ( *pszSrc == '/'
1127 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
1128 && ( pszSrc[pTarget->value_length + 1] == '/'
1129 || pszSrc[pTarget->value_length + 1] == '\0'))
1130 pszSrc += 1 + pTarget->value_length;
1131 }
1132 else if ( pSource->value_length > pPathRoot->value_length
1133 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
1134 {
1135 pszSrc = pSource->value + pPathRoot->value_length;
1136 if ( *pszSrc == '/'
1137 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
1138 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
1139 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
1140 pszSrc += 1 + pPathSubCur->value_length;
1141 }
1142 else
1143 pszSrc = pSource->value;
1144
1145 /* skip root specification */
1146#ifdef HAVE_DOS_PATHS
1147 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
1148 pszSrc += 2;
1149#endif
1150 while (*pszSrc == '/'
1151#ifdef HAVE_DOS_PATHS
1152 || *pszSrc == '\\'
1153#endif
1154 )
1155 pszSrc++;
1156
1157 /* drop the source extension. */
1158 pszSrcEnd = pSource->value + pSource->value_length;
1159 for (;;)
1160 {
1161 pszSrcEnd--;
1162 if ( pszSrcEnd <= pszSrc
1163 || *pszSrcEnd == '/'
1164#ifdef HAVE_DOS_PATHS
1165 || *pszSrcEnd == '\\'
1166 || *pszSrcEnd == ':'
1167#endif
1168 )
1169 {
1170 pszSrcEnd = pSource->value + pSource->value_length;
1171 break;
1172 }
1173 if (*pszSrcEnd == '.')
1174 break;
1175 }
1176
1177 /*
1178 * Assemble the string on the heap and define the objbase variable
1179 * which we then return.
1180 */
1181 cchSrc = pszSrcEnd - pszSrc;
1182 cch = pPathTarget->value_length
1183 + 1 /* slash */
1184 + pTarget->value_length
1185 + 1 /* slash */
1186 + cchSrcPrefix
1187 + cchSrc
1188 + 1;
1189 psz = pszResult = xmalloc(cch);
1190
1191 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
1192 *psz++ = '/';
1193 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1194 *psz++ = '/';
1195 if (pszSrcPrefix)
1196 {
1197 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
1198 psz += cchSrcPrefix;
1199 }
1200 pszDot = psz;
1201 memcpy(psz, pszSrc, cchSrc); psz += cchSrc;
1202 *psz = '\0';
1203
1204 /* convert '..' path elements in the source to 'dt'. */
1205 while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL)
1206 {
1207 if ( pszDot[1] == '.'
1208 && ( pszDot == psz
1209 || pszDot[-1] == '/'
1210#ifdef HAVE_DOS_PATHS
1211 || pszDot[-1] == '\\'
1212 || pszDot[-1] == ':'
1213#endif
1214 )
1215 && ( !pszDot[2]
1216 || pszDot[2] == '/'
1217#ifdef HAVE_DOS_PATHS
1218 || pszDot[2] == '\\'
1219 || pszDot[2] == ':'
1220#endif
1221 )
1222 )
1223 {
1224 *pszDot++ = 'd';
1225 *pszDot++ = 't';
1226 }
1227 else
1228 pszDot++;
1229 }
1230
1231 /*
1232 * Define the variable in the current set and return it.
1233 */
1234 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
1235 0 /* use pszResult */, o_local, 0 /* !recursive */);
1236}
1237
1238
1239/* Implements _OBJECT_BASE. */
1240char *
1241func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
1242{
1243 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
1244 kbuild_lookup_variable("source"),
1245 argv[0]);
1246 if (pVar)
1247 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1248 (void)pszFuncName;
1249 return o;
1250
1251}
1252
1253
1254struct kbuild_sdks
1255{
1256 char *apsz[4];
1257 struct variable *pa;
1258 unsigned c;
1259 unsigned iGlobal;
1260 unsigned cGlobal;
1261 unsigned iTarget;
1262 unsigned cTarget;
1263 unsigned iSource;
1264 unsigned cSource;
1265 unsigned iTargetSource;
1266 unsigned cTargetSource;
1267 unsigned int cchMax;
1268};
1269
1270
1271/* Fills in the SDK struct (remember to free it). */
1272static void
1273kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
1274 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
1275{
1276 unsigned i;
1277 unsigned j;
1278 size_t cchTmp, cch;
1279 char *pszTmp;
1280 unsigned cchCur;
1281 char *pszCur;
1282 const char *pszIterator;
1283
1284 /** @todo rewrite this to avoid sprintf and allocated_varaible_expand_2. */
1285
1286 /* basic init. */
1287 pSdks->cchMax = 0;
1288 pSdks->pa = NULL;
1289 pSdks->c = 0;
1290 i = 0;
1291
1292 /* determin required tmp variable name space. */
1293 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
1294 + (pTarget->value_length + pSource->value_length) * 5
1295 + pBldType->value_length
1296 + pBldTrg->value_length
1297 + pBldTrgArch->value_length
1298 + pBldTrg->value_length + pBldTrgArch->value_length;
1299 pszTmp = alloca(cchTmp);
1300
1301 /* the global sdks. */
1302 pSdks->iGlobal = i;
1303 pSdks->cGlobal = 0;
1304 cch = sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
1305 pBldType->value,
1306 pBldTrg->value,
1307 pBldTrgArch->value,
1308 pBldTrg->value, pBldTrgArch->value);
1309 pszIterator = pSdks->apsz[0] = allocated_variable_expand_2(pszTmp, cch, NULL);
1310 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1311 pSdks->cGlobal++;
1312 i += pSdks->cGlobal;
1313
1314 /* the target sdks.*/
1315 pSdks->iTarget = i;
1316 pSdks->cTarget = 0;
1317 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1318 pTarget->value,
1319 pTarget->value, pBldType->value,
1320 pTarget->value, pBldTrg->value,
1321 pTarget->value, pBldTrgArch->value,
1322 pTarget->value, pBldTrg->value, pBldTrgArch->value);
1323 pszIterator = pSdks->apsz[1] = allocated_variable_expand_2(pszTmp, cch, NULL);
1324 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1325 pSdks->cTarget++;
1326 i += pSdks->cTarget;
1327
1328 /* the source sdks.*/
1329 pSdks->iSource = i;
1330 pSdks->cSource = 0;
1331 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1332 pSource->value,
1333 pSource->value, pBldType->value,
1334 pSource->value, pBldTrg->value,
1335 pSource->value, pBldTrgArch->value,
1336 pSource->value, pBldTrg->value, pBldTrgArch->value);
1337 pszIterator = pSdks->apsz[2] = allocated_variable_expand_2(pszTmp, cch, NULL);
1338 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1339 pSdks->cSource++;
1340 i += pSdks->cSource;
1341
1342 /* the target + source sdks. */
1343 pSdks->iTargetSource = i;
1344 pSdks->cTargetSource = 0;
1345 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
1346 pTarget->value, pSource->value,
1347 pTarget->value, pSource->value, pBldType->value,
1348 pTarget->value, pSource->value, pBldTrg->value,
1349 pTarget->value, pSource->value, pBldTrgArch->value,
1350 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
1351 assert(cch < cchTmp); (void)cch;
1352 pszIterator = pSdks->apsz[3] = allocated_variable_expand_2(pszTmp, cch, NULL);
1353 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1354 pSdks->cTargetSource++;
1355 i += pSdks->cTargetSource;
1356
1357 pSdks->c = i;
1358 if (!i)
1359 return;
1360
1361 /*
1362 * Allocate the variable array and create the variables.
1363 */
1364 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
1365 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
1366 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1367 {
1368 pszIterator = pSdks->apsz[j];
1369 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1370 {
1371 pSdks->pa[i].value = pszCur;
1372 pSdks->pa[i].value_length = cchCur;
1373 i++;
1374 }
1375 }
1376 assert(i == pSdks->c);
1377
1378 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
1379 while (i-- > 0)
1380 {
1381 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
1382
1383 /* calc the max variable length too. */
1384 if (pSdks->cchMax < (unsigned int)pSdks->pa[i].value_length)
1385 pSdks->cchMax = pSdks->pa[i].value_length;
1386 }
1387}
1388
1389
1390/* releases resources allocated in the kbuild_get_sdks. */
1391static void
1392kbuild_put_sdks(struct kbuild_sdks *pSdks)
1393{
1394 unsigned j;
1395 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1396 free(pSdks->apsz[j]);
1397 free(pSdks->pa);
1398}
1399
1400
1401/* this kind of stuff:
1402
1403defs := $(kb-src-exp defs)
1404 $(TOOL_$(tool)_DEFS)\
1405 $(TOOL_$(tool)_DEFS.$(bld_type))\
1406 $(TOOL_$(tool)_DEFS.$(bld_trg))\
1407 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
1408 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
1409 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
1410 $(TOOL_$(tool)_$(type)DEFS)\
1411 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
1412 $(foreach sdk, $(SDKS.$(bld_trg)) \
1413 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
1414 $(SDKS.$(bld_type)) \
1415 $(SDKS),\
1416 $(SDK_$(sdk)_DEFS)\
1417 $(SDK_$(sdk)_DEFS.$(bld_type))\
1418 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1419 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1420 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1421 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1422 $(SDK_$(sdk)_$(type)DEFS)\
1423 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1424 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1425 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1426 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1427 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1428 $(DEFS)\
1429 $(DEFS.$(bld_type))\
1430 $(DEFS.$(bld_trg))\
1431 $(DEFS.$(bld_trg_arch))\
1432 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1433 $(DEFS.$(bld_trg_cpu))\
1434 $($(type)DEFS)\
1435 $($(type)DEFS.$(bld_type))\
1436 $($(type)DEFS.$(bld_trg))\
1437 $($(type)DEFS.$(bld_trg_arch))\
1438 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1439 $($(type)DEFS.$(bld_trg_cpu))\
1440 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1441 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1442 $($(target)_SDKS.$(bld_type)) \
1443 $($(target)_SDKS),\
1444 $(SDK_$(sdk)_DEFS)\
1445 $(SDK_$(sdk)_DEFS.$(bld_type))\
1446 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1447 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1448 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1449 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1450 $(SDK_$(sdk)_$(type)DEFS)\
1451 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1452 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1453 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1454 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1455 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1456 $($(target)_DEFS)\
1457 $($(target)_DEFS.$(bld_type))\
1458 $($(target)_DEFS.$(bld_trg))\
1459 $($(target)_DEFS.$(bld_trg_arch))\
1460 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1461 $($(target)_DEFS.$(bld_trg_cpu))\
1462 $($(target)_$(type)DEFS)\
1463 $($(target)_$(type)DEFS.$(bld_type))\
1464 $($(target)_$(type)DEFS.$(bld_trg))\
1465 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1466 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1467 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1468 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1469 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1470 $($(source)_SDKS.$(bld_type)) \
1471 $($(source)_SDKS),\
1472 $(SDK_$(sdk)_DEFS)\
1473 $(SDK_$(sdk)_DEFS.$(bld_type))\
1474 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1475 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1476 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1477 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1478 $(SDK_$(sdk)_$(type)DEFS)\
1479 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1480 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1481 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1482 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1483 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1484 $($(source)_DEFS)\
1485 $($(source)_DEFS.$(bld_type))\
1486 $($(source)_DEFS.$(bld_trg))\
1487 $($(source)_DEFS.$(bld_trg_arch))\
1488 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1489 $($(source)_DEFS.$(bld_trg_cpu))\
1490 $($(source)_$(type)DEFS)\
1491 $($(source)_$(type)DEFS.$(bld_type))\
1492 $($(source)_$(type)DEFS.$(bld_trg))\
1493 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1494 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1495 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1496 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1497 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1498 $($(target)_$(source)_SDKS.$(bld_type)) \
1499 $($(target)_$(source)_SDKS),\
1500 $(SDK_$(sdk)_DEFS)\
1501 $(SDK_$(sdk)_DEFS.$(bld_type))\
1502 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1503 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1504 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1505 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1506 $(SDK_$(sdk)_$(type)DEFS)\
1507 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1508 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1509 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1510 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1511 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1512 $($(target)_$(source)_DEFS)\
1513 $($(target)_$(source)_DEFS.$(bld_type))\
1514 $($(target)_$(source)_DEFS.$(bld_trg))\
1515 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1516 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1517 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1518 $($(target)_$(source)_$(type)DEFS)\
1519 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1520 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1521 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1522 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1523 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1524*/
1525static struct variable *
1526kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
1527 struct variable *pTool, struct kbuild_sdks *pSdks,
1528 struct variable *pType, struct variable *pBldType,
1529 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
1530 struct variable *pDefPath,
1531 const char *pszProp, size_t cchProp,
1532 const char *pszVarName, size_t cchVarName,
1533 int iDirection)
1534{
1535 struct variable *pVar;
1536 unsigned iSdk, iSdkEnd;
1537 int cVars, iVar, iVarEnd;
1538 size_t cchTotal, cchBuf;
1539 char *pszResult, *pszBuf, *psz, *psz2, *psz3;
1540 struct
1541 {
1542 struct variable *pVar;
1543 int cchExp;
1544 char *pszExp;
1545 } *paVars;
1546
1547 assert(iDirection == 1 || iDirection == -1);
1548
1549 /*
1550 * Calc and allocate a too big name buffer.
1551 */
1552 cchBuf = cchProp + 1
1553 + pTarget->value_length + 1
1554 + pSource->value_length + 1
1555 + pSdks->cchMax + 1
1556 + (pTool ? pTool->value_length + 1 : 0)
1557 + pType->value_length + 1
1558 + pBldTrg->value_length + 1
1559 + pBldTrgArch->value_length + 1
1560 + pBldTrgCpu->value_length + 1
1561 + pBldType->value_length + 1;
1562 pszBuf = xmalloc(cchBuf);
1563
1564 /*
1565 * Get the variables.
1566 */
1567 cVars = 12 * (pSdks->c + 5);
1568 paVars = alloca(cVars * sizeof(paVars[0]));
1569
1570 iVar = 0;
1571
1572#define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
1573#define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
1574#define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
1575#define ADD_CH(ch) do { *psz++ = (ch); } while (0)
1576# define DO_VAR_LOOKUP() \
1577 do { \
1578 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); \
1579 /*if (pVar)*/ \
1580 paVars[iVar++].pVar = pVar; \
1581 } while (0)
1582#define DO_SINGLE_PSZ3_VARIATION() \
1583 do { \
1584 DO_VAR_LOOKUP(); \
1585 \
1586 ADD_CH('.'); \
1587 psz3 = psz; \
1588 ADD_VAR(pBldType); \
1589 DO_VAR_LOOKUP(); \
1590 \
1591 psz = psz3; \
1592 ADD_VAR(pBldTrg); \
1593 DO_VAR_LOOKUP(); \
1594 \
1595 psz = psz3; \
1596 ADD_VAR(pBldTrgArch); \
1597 DO_VAR_LOOKUP(); \
1598 \
1599 psz = psz3; \
1600 ADD_VAR(pBldTrg); \
1601 ADD_CH('.'); \
1602 ADD_VAR(pBldTrgArch); \
1603 DO_VAR_LOOKUP(); \
1604 \
1605 psz = psz3; \
1606 ADD_VAR(pBldTrgCpu); \
1607 DO_VAR_LOOKUP(); \
1608 } while (0)
1609
1610#define DO_DOUBLE_PSZ2_VARIATION() \
1611 do { \
1612 psz2 = psz; \
1613 ADD_STR(pszProp, cchProp); \
1614 DO_SINGLE_PSZ3_VARIATION(); \
1615 \
1616 /* add prop before type */ \
1617 psz = psz2; \
1618 ADD_VAR(pType); \
1619 ADD_STR(pszProp, cchProp); \
1620 DO_SINGLE_PSZ3_VARIATION(); \
1621 } while (0)
1622
1623 /* the tool (lowest priority). */
1624 psz = pszBuf;
1625 ADD_CSTR("TOOL_");
1626 ADD_VAR(pTool);
1627 ADD_CH('_');
1628 DO_DOUBLE_PSZ2_VARIATION();
1629
1630
1631 /* the global sdks. */
1632 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
1633 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
1634 iSdk != iSdkEnd;
1635 iSdk += iDirection)
1636 {
1637 struct variable *pSdk = &pSdks->pa[iSdk];
1638 psz = pszBuf;
1639 ADD_CSTR("SDK_");
1640 ADD_VAR(pSdk);
1641 ADD_CH('_');
1642 DO_DOUBLE_PSZ2_VARIATION();
1643 }
1644
1645 /* the globals. */
1646 psz = pszBuf;
1647 DO_DOUBLE_PSZ2_VARIATION();
1648
1649
1650 /* the target sdks. */
1651 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
1652 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
1653 iSdk != iSdkEnd;
1654 iSdk += iDirection)
1655 {
1656 struct variable *pSdk = &pSdks->pa[iSdk];
1657 psz = pszBuf;
1658 ADD_CSTR("SDK_");
1659 ADD_VAR(pSdk);
1660 ADD_CH('_');
1661 DO_DOUBLE_PSZ2_VARIATION();
1662 }
1663
1664 /* the target. */
1665 psz = pszBuf;
1666 ADD_VAR(pTarget);
1667 ADD_CH('_');
1668 DO_DOUBLE_PSZ2_VARIATION();
1669
1670 /* the source sdks. */
1671 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
1672 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
1673 iSdk != iSdkEnd;
1674 iSdk += iDirection)
1675 {
1676 struct variable *pSdk = &pSdks->pa[iSdk];
1677 psz = pszBuf;
1678 ADD_CSTR("SDK_");
1679 ADD_VAR(pSdk);
1680 ADD_CH('_');
1681 DO_DOUBLE_PSZ2_VARIATION();
1682 }
1683
1684 /* the source. */
1685 psz = pszBuf;
1686 ADD_VAR(pSource);
1687 ADD_CH('_');
1688 DO_DOUBLE_PSZ2_VARIATION();
1689
1690 /* the target + source sdks. */
1691 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
1692 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
1693 iSdk != iSdkEnd;
1694 iSdk += iDirection)
1695 {
1696 struct variable *pSdk = &pSdks->pa[iSdk];
1697 psz = pszBuf;
1698 ADD_CSTR("SDK_");
1699 ADD_VAR(pSdk);
1700 ADD_CH('_');
1701 DO_DOUBLE_PSZ2_VARIATION();
1702 }
1703
1704 /* the target + source. */
1705 psz = pszBuf;
1706 ADD_VAR(pTarget);
1707 ADD_CH('_');
1708 ADD_VAR(pSource);
1709 ADD_CH('_');
1710 DO_DOUBLE_PSZ2_VARIATION();
1711
1712 free(pszBuf);
1713
1714 /*assert(iVar <= cVars);
1715 cVars = iVar;*/
1716 assert(iVar == cVars);
1717
1718 if (!cVars)
1719 pVar = define_variable_vl(pszVarName, cchVarName, "", 0,
1720 1 /* duplicate value */ , o_local, 0 /* !recursive */);
1721 else
1722 {
1723 /*
1724 * Expand the variables and calculate the total length.
1725 */
1726 cchTotal = 0;
1727 iVarEnd = iDirection == 1 ? cVars : 0;
1728 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1729 {
1730 if (!paVars[iVar].pVar)
1731 {
1732 paVars[iVar].cchExp = 0;
1733 continue;
1734 }
1735 if ( !paVars[iVar].pVar->recursive
1736 || !memchr(paVars[iVar].pVar->value, '$', paVars[iVar].pVar->value_length))
1737 {
1738 paVars[iVar].pszExp = paVars[iVar].pVar->value;
1739 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
1740 }
1741 else
1742 {
1743 unsigned int cchExp;
1744 paVars[iVar].pszExp = allocated_variable_expand_2(paVars[iVar].pVar->value, paVars[iVar].pVar->value_length, &cchExp);
1745 paVars[iVar].cchExp = cchExp;
1746 }
1747 if (pDefPath)
1748 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL,
1749 paVars[iVar].pszExp != paVars[iVar].pVar->value);
1750 cchTotal += paVars[iVar].cchExp + 1;
1751 }
1752
1753 /*
1754 * Construct the result value.
1755 */
1756 psz = pszResult = xmalloc(cchTotal + 1);
1757 iVarEnd = iDirection == 1 ? cVars : 0;
1758 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1759 {
1760 if (!paVars[iVar].cchExp)
1761 continue;
1762 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1763 psz += paVars[iVar].cchExp;
1764 *psz++ = ' ';
1765 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1766 free(paVars[iVar].pszExp);
1767 }
1768 if (psz != pszResult)
1769 psz--;
1770 *psz = '\0';
1771 cchTotal = psz - pszResult;
1772 pVar = define_variable_vl(pszVarName, cchVarName, pszResult, cchTotal,
1773 0 /* take pszResult */ , o_local, 0 /* !recursive */);
1774 }
1775
1776 return pVar;
1777
1778#undef ADD_VAR
1779#undef ADD_STR
1780#undef ADD_CSTR
1781#undef ADD_CH
1782#undef DO_VAR_LOOKUP
1783#undef DO_DOUBLE_PSZ2_VARIATION
1784#undef DO_SINGLE_PSZ3_VARIATION
1785}
1786
1787
1788/* get a source property. */
1789char *
1790func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1791{
1792 struct variable *pTarget = kbuild_get_variable_n(ST("target"));
1793 struct variable *pSource = kbuild_get_variable_n(ST("source"));
1794 struct variable *pDefPath = NULL;
1795 struct variable *pType = kbuild_get_variable_n(ST("type"));
1796 struct variable *pTool = kbuild_get_variable_n(ST("tool"));
1797 struct variable *pBldType = kbuild_get_variable_n(ST("bld_type"));
1798 struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg"));
1799 struct variable *pBldTrgArch = kbuild_get_variable_n(ST("bld_trg_arch"));
1800 struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
1801 struct variable *pVar;
1802 struct kbuild_sdks Sdks;
1803 int iDirection;
1804 if (!strcmp(argv[2], "left-to-right"))
1805 iDirection = 1;
1806 else if (!strcmp(argv[2], "right-to-left"))
1807 iDirection = -1;
1808 else
1809 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1810 if (argv[3])
1811 {
1812 const char *psz = argv[3];
1813 while (isspace(*psz))
1814 psz++;
1815 if (*psz)
1816 pDefPath = kbuild_get_variable_n(ST("defpath"));
1817 }
1818
1819 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1820
1821 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1822 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1823 pDefPath,
1824 argv[0], strlen(argv[0]),
1825 argv[1], strlen(argv[1]),
1826 iDirection);
1827 if (pVar)
1828 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1829
1830 kbuild_put_sdks(&Sdks);
1831 (void)pszFuncName;
1832 return o;
1833}
1834
1835
1836/*
1837dep := $(obj)$(SUFF_DEP)
1838obj := $(outbase)$(objsuff)
1839dirdep := $(call DIRDEP,$(dir $(outbase)))
1840PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1841*/
1842static struct variable *
1843kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1844 struct variable *pOutBase, struct variable *pObjSuff,
1845 const char *pszVarName, struct variable **ppDep,
1846 struct variable **ppDirDep)
1847{
1848 struct variable *pDepSuff = kbuild_get_variable_n(ST("SUFF_DEP"));
1849 struct variable *pObj;
1850 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1851 char *pszResult = alloca(cch);
1852 char *pszName, *psz;
1853
1854 /*
1855 * dep.
1856 */
1857 psz = pszResult;
1858 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1859 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1860 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1861 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */);
1862
1863 /*
1864 * obj
1865 */
1866 *psz = '\0';
1867 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1868 1/* dup */, o_local, 0 /* !recursive */);
1869
1870 /*
1871 * PATH_$(target)_$(source) - this is global!
1872 */
1873 /* calc variable name. */
1874 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1875 psz = pszName = alloca(cch + 1);
1876 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1877 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1878 *psz++ = '_';
1879 memcpy(psz, pSource->value, pSource->value_length + 1);
1880
1881 /* strip off the filename. */
1882 psz = pszResult + pOutBase->value_length;
1883 for (;;)
1884 {
1885 psz--;
1886 if (psz <= pszResult)
1887 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1888#ifdef HAVE_DOS_PATHS
1889 if (*psz == ':')
1890 {
1891 psz++;
1892 break;
1893 }
1894#endif
1895 if ( *psz == '/'
1896#ifdef HAVE_DOS_PATHS
1897 || *psz == '\\'
1898#endif
1899 )
1900 {
1901 while ( psz - 1 > pszResult
1902 && psz[-1] == '/'
1903#ifdef HAVE_DOS_PATHS
1904 || psz[-1] == '\\'
1905#endif
1906 )
1907 psz--;
1908#ifdef HAVE_DOS_PATHS
1909 if (psz == pszResult + 2 && pszResult[1] == ':')
1910 psz++;
1911#endif
1912 break;
1913 }
1914 }
1915 *psz = '\0';
1916
1917 /* set global variable */
1918 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1919
1920 /*
1921 * dirdep
1922 */
1923 if ( psz[-1] != '/'
1924#ifdef HAVE_DOS_PATHS
1925 && psz[-1] != '\\'
1926 && psz[-1] != ':'
1927#endif
1928 )
1929 {
1930 *psz++ = '/';
1931 *psz = '\0';
1932 }
1933 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */);
1934
1935 return pObj;
1936}
1937
1938
1939/* setup the base variables for def_target_source_c_cpp_asm_new:
1940
1941X := $(kb-src-tool tool)
1942x := $(kb-obj-base outbase)
1943x := $(kb-obj-suff objsuff)
1944obj := $(outbase)$(objsuff)
1945PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1946
1947x := $(kb-src-prop DEFS,defs,left-to-right)
1948x := $(kb-src-prop INCS,incs,right-to-left)
1949x := $(kb-src-prop FLAGS,flags,right-to-left)
1950
1951x := $(kb-src-prop DEPS,deps,left-to-right)
1952dirdep := $(call DIRDEP,$(dir $(outbase)))
1953dep := $(obj)$(SUFF_DEP)
1954*/
1955char *
1956func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1957{
1958 static int s_fNoCompileCmdsDepsDefined = -1;
1959 struct variable *pTarget = kbuild_get_variable_n(ST("target"));
1960 struct variable *pSource = kbuild_get_variable_n(ST("source"));
1961 struct variable *pDefPath = kbuild_get_variable_n(ST("defpath"));
1962 struct variable *pType = kbuild_get_variable_n(ST("type"));
1963 struct variable *pBldType = kbuild_get_variable_n(ST("bld_type"));
1964 struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg"));
1965 struct variable *pBldTrgArch= kbuild_get_variable_n(ST("bld_trg_arch"));
1966 struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
1967 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1968 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1969 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1970 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
1971 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1972 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1973 char *pszSavedVarBuf;
1974 unsigned cchSavedVarBuf;
1975 size_t cch;
1976 struct kbuild_sdks Sdks;
1977 int iVer;
1978
1979 /*
1980 * argv[0] is the function version. Prior to r1792 (early 0.1.5) this
1981 * was undefined and footer.kmk always passed an empty string.
1982 *
1983 * Version 2, as implemented in r1797, will make use of the async
1984 * includedep queue feature. This means the files will be read by one or
1985 * more background threads, leaving the eval'ing to be done later on by
1986 * the main thread (in snap_deps).
1987 */
1988 if (!argv[0][0])
1989 iVer = 0;
1990 else
1991 switch (argv[0][0] | (argv[0][1] << 8))
1992 {
1993 case '2': iVer = 2; break;
1994 case '3': iVer = 3; break;
1995 case '4': iVer = 4; break;
1996 case '5': iVer = 5; break;
1997 case '6': iVer = 6; break;
1998 case '7': iVer = 7; break;
1999 case '8': iVer = 8; break;
2000 case '9': iVer = 9; break;
2001 case '0': iVer = 0; break;
2002 case '1': iVer = 1; break;
2003 default:
2004 iVer = 0;
2005 psz = argv[0];
2006 while (isblank((unsigned char)*psz))
2007 psz++;
2008 if (*psz)
2009 iVer = atoi(psz);
2010 break;
2011 }
2012
2013 /*
2014 * Gather properties.
2015 */
2016 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
2017
2018 if (pDefPath && !pDefPath->value_length)
2019 pDefPath = NULL;
2020 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
2021 ST("DEFS"), ST("defs"), 1/* left-to-right */);
2022 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2023 ST("INCS"), ST("incs"), -1/* right-to-left */);
2024 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
2025 ST("FLAGS"), ST("flags"), 1/* left-to-right */);
2026 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2027 ST("DEPS"), ST("deps"), 1/* left-to-right */);
2028 pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2029 ST("ORDERDEPS"), ST("orderdeps"), 1/* left-to-right */);
2030
2031 /*
2032 * If we've got a default path, we must expand the source now.
2033 * If we do this too early, "<source>_property = stuff" won't work becuase
2034 * our 'source' value isn't what the user expects.
2035 */
2036 if (pDefPath)
2037 kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
2038
2039 /*
2040 # dependencies
2041 ifndef NO_COMPILE_CMDS_DEPS
2042 _DEPFILES_INCLUDED += $(dep)
2043 $(if $(wildcard $(dep)),$(eval include $(dep)))
2044 endif
2045 */
2046 if (s_fNoCompileCmdsDepsDefined == -1)
2047 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL;
2048 if (!s_fNoCompileCmdsDepsDefined)
2049 {
2050 do_variable_definition_2(NILF, "_DEPFILES_INCLUDED", pDep->value, pDep->value_length,
2051 !pDep->recursive, 0, o_file, f_append, 0 /* !target_var */);
2052 eval_include_dep(pDep->value, NILF, iVer >= 2 ? incdep_queue : incdep_read_it);
2053 }
2054
2055 /*
2056 # call the tool
2057 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
2058 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
2059 $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
2060 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
2061 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
2062 */
2063 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE");
2064 psz = pszSrcVar = alloca(cch);
2065 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
2066 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
2067 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
2068 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
2069 pszSrc = psz;
2070
2071 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_");
2072 psz = pszDstVar = alloca(cch);
2073 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
2074 *psz++ = '_';
2075 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
2076 pszDst = psz;
2077
2078 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
2079 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
2080 pVar = kbuild_get_recursive_variable(pszSrcVar);
2081 do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2082 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2083
2084 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
2085 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
2086 pVar = kbuild_get_recursive_variable(pszSrcVar);
2087 pOutput = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2088 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2089
2090 memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
2091 memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
2092 pVar = kbuild_query_recursive_variable(pszSrcVar);
2093 if (pVar)
2094 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2095 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2096 else
2097 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_file, f_simple, 0 /* !target_var */);
2098
2099 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
2100 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
2101 pVar = kbuild_get_recursive_variable(pszSrcVar);
2102 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
2103 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2104 *psz++ = ' ';
2105 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
2106 *psz++ = ' ';
2107 memcpy(psz, pSource->value, pSource->value_length + 1);
2108 do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length,
2109 !pVar->recursive && !pDeps->recursive && !pSource->recursive,
2110 pszVal, o_file, f_simple, 0 /* !target_var */);
2111
2112 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
2113 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
2114 pVar = kbuild_get_recursive_variable(pszSrcVar);
2115 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
2116 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2117 *psz++ = ' ';
2118 memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
2119 *psz++ = ' ';
2120 memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
2121 do_variable_definition_2(NILF, pszDstVar, pszVal,
2122 pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length,
2123 !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive,
2124 pszVal, o_file, f_simple, 0 /* !target_var */);
2125
2126 /*
2127 _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
2128 */
2129 /** @todo use append? */
2130 pVar = kbuild_get_variable_n(ST("_OUT_FILES"));
2131 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
2132 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2133 *psz++ = ' ';
2134 memcpy(psz, pOutput->value, pOutput->value_length); psz += pOutput->value_length;
2135 *psz++ = ' ';
2136 memcpy(psz, pOutputMaybe->value, pOutputMaybe->value_length + 1);
2137 do_variable_definition_2(NILF, "_OUT_FILES", pszVal,
2138 pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length,
2139 !pVar->recursive && !pOutput->recursive && !pOutputMaybe->recursive,
2140 pszVal, o_file, f_simple, 0 /* !target_var */);
2141
2142 /*
2143 $(target)_OBJS_ += $(obj)
2144 */
2145 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
2146 do_variable_definition_2(NILF, pszDstVar, pObj->value, pObj->value_length,
2147 !pObj->recursive, 0, o_file, f_append, 0 /* !target_var */);
2148
2149 /*
2150 $(eval $(def_target_source_rule))
2151 */
2152 pVar = kbuild_get_recursive_variable("def_target_source_rule");
2153 pszVal = variable_expand_string_2 (o, pVar->value, pVar->value_length, &psz);
2154 assert (!((size_t)pszVal & 3));
2155
2156 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
2157 eval_buffer(pszVal, psz);
2158 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
2159
2160 kbuild_put_sdks(&Sdks);
2161 (void)pszFuncName;
2162
2163 *pszVal = '\0';
2164 return pszVal;
2165}
2166
2167
2168#endif /* KMK_HELPERS */
2169
Note: See TracBrowser for help on using the repository browser.