VirtualBox

Changeset 2011 in kBuild for trunk/src/kmk/kbuild.c


Ignore:
Timestamp:
Nov 1, 2008 2:15:50 PM (17 years ago)
Author:
bird
Message:

kmk,footer.kmk: New helper function 'kb-exp-tmpl', 10x faster than the gnu make script.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kbuild.c

    r1999 r2011  
    458458kbuild_get_variable_n(const char *pszName, size_t cchName)
    459459{
    460 #ifndef NDEBUG
    461     int i;
    462 #endif
    463460    struct variable *pVar = lookup_variable(pszName, cchName);
    464461    if (!pVar)
     
    466463    if (pVar->recursive)
    467464        fatal(NILF, _("variable `%.*s' is defined as `recursive' instead of `simple'!"), (int)cchName, pszName);
    468 #ifndef NDEBUG
    469     i = strlen(pVar->value);
    470     if (i != pVar->value_length)
    471     {
    472         printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
    473 # ifdef _MSC_VER
    474         __debugbreak();
    475 # endif
    476         assert(0);
    477     }
    478 #endif
     465
     466    MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length,
     467                  ("%u != %u %.*s\n", pVar->value_length, strlen(pVar->value), (int)cchName, pVar->name));
    479468    return pVar;
    480469}
    481 
    482 
    483 #if 0 /* unused */
    484 /**
    485  * Gets a variable that must exist.
    486  * Will cause a fatal failure if the variable doesn't exist.
    487  *
    488  * @returns Pointer to the variable.
    489  * @param   pszName     The variable name.
    490  */
    491 static struct variable *
    492 kbuild_get_variable(const char *pszName)
    493 {
    494     return kbuild_get_variable_n(pszName, strlen(pszName));
    495 }
    496 #endif
    497470
    498471
     
    507480kbuild_get_recursive_variable(const char *pszName)
    508481{
    509 #ifndef NDEBUG
    510     int i;
    511 #endif
    512482    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
    513483    if (!pVar)
    514484        fatal(NILF, _("variable `%s' isn't defined!"), pszName);
    515 #ifndef NDEBUG
    516     i = strlen(pVar->value);
    517     if (i != pVar->value_length)
    518     {
    519         printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
    520 # ifdef _MSC_VER
    521         __debugbreak();
    522 # endif
    523         assert(0);
    524     }
    525 #endif
     485
     486    MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length,
     487                  ("%u != %u %s\n", pVar->value_length, strlen(pVar->value), pVar->name));
     488    return pVar;
     489}
     490
     491
     492/**
     493 * Gets a variable that doesn't have to exit, but if it does can be recursive.
     494 *
     495 * @returns Pointer to the variable.
     496 *          NULL if not found.
     497 * @param   pszName     The variable name. Doesn't need to be terminated.
     498 * @param   cchName     The name length.
     499 */
     500static struct variable *
     501kbuild_query_recursive_variable_n(const char *pszName, size_t cchName)
     502{
     503    struct variable *pVar = lookup_variable(pszName, cchName);
     504    MY_ASSERT_MSG(!pVar || strlen(pVar->value) == pVar->value_length,
     505                  ("%u != %u %.*s\n", pVar->value_length, strlen(pVar->value), (int)cchName, pVar->name));
    526506    return pVar;
    527507}
     
    538518kbuild_query_recursive_variable(const char *pszName)
    539519{
    540 #ifndef NDEBUG
    541     int i;
    542 #endif
    543     struct variable *pVar = lookup_variable(pszName, strlen(pszName));
    544     if (pVar)
    545     {
    546 #ifndef NDEBUG
    547         i = strlen(pVar->value);
    548         if (i != pVar->value_length)
    549         {
    550             printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
    551 # ifdef _MSC_VER
    552             __debugbreak();
    553 # endif
    554             assert(0);
    555         }
    556 #endif
    557     }
    558     return pVar;
     520    return kbuild_query_recursive_variable_n(pszName, strlen(pszName));
    559521}
    560522
     
    602564    if (pVar)
    603565    {
    604 #ifndef NDEBUG
    605         int i = strlen(pVar->value);
    606         if (i != pVar->value_length)
    607         {
    608             printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
    609 # ifdef _MSC_VER
    610             __debugbreak();
    611 # endif
    612             assert(0);
    613         }
    614 #endif
     566        MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length,
     567                      ("%u != %u %.*s\n", pVar->value_length, strlen(pVar->value), (int)cchName, pVar->name));
     568
    615569        /* Make sure the variable is simple, convert it if necessary. */
    616570        if (pVar->recursive)
     
    21992153}
    22002154
     2155/*
     2156
     2157## Inherit one template property in a non-accumulative manner.
     2158# @param    $(prop)     Property name
     2159# @param    $(target)   Target name
     2160# @todo fix the precedence order for some properties.
     2161define def_inherit_template_one
     2162ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
     2163ifndef $(target)_$(prop)
     2164$(target)_$(prop) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
     2165endif
     2166endif
     2167ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
     2168ifndef $(target)_$(prop).$(bld_trg)
     2169$(target)_$(prop).$(bld_trg) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
     2170endif
     2171endif
     2172ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
     2173ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
     2174$(target)_$(prop).$(bld_trg).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
     2175endif
     2176endif
     2177ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
     2178ifndef $(target)_$(prop).$(bld_trg_arch)
     2179$(target)_$(prop).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
     2180endif
     2181endif
     2182ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
     2183ifndef $(target)_$(prop).$(bld_trg_cpu)
     2184$(target)_$(prop).$(bld_trg_cpu) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
     2185endif
     2186endif
     2187endef
     2188
     2189## Inherit one template property in a non-accumulative manner, deferred expansion.
     2190# @param    1: $(prop)     Property name
     2191# @param    2: $(target)        Target name
     2192# @todo fix the precedence order for some properties.
     2193# @remark this define relies on double evaluation
     2194define def_inherit_template_one_deferred
     2195ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
     2196ifndef $(target)_$(prop)
     2197$(target)_$(prop) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
     2198endif
     2199endif
     2200ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
     2201ifndef $(target)_$(prop).$(bld_trg)
     2202$(target)_$(prop).$(bld_trg) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
     2203endif
     2204endif
     2205ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
     2206ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
     2207$(target)_$(prop).$(bld_trg).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
     2208endif
     2209endif
     2210ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
     2211ifndef $(target)_$(prop).$(bld_trg_arch)
     2212$(target)_$(prop).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
     2213endif
     2214endif
     2215ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
     2216ifndef $(target)_$(prop).$(bld_trg_cpu)
     2217$(target)_$(prop).$(bld_trg_cpu) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
     2218endif
     2219endif
     2220endef
     2221
     2222## Inherit one acculumlative template property where the 'most significant' items are at the left end.
     2223# @param    $(prop)     Property name
     2224# @param    $(target)   Target name
     2225define def_inherit_template_one_accumulate_l
     2226ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
     2227 ifeq ($$(flavor $(target)_$(prop)),simple)
     2228 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop))
     2229 endif
     2230$(target)_$(prop) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
     2231endif
     2232ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
     2233 ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple)
     2234 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE))
     2235 endif
     2236$(target)_$(prop).$(KBUILD_TYPE) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
     2237endif
     2238ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
     2239 ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple)
     2240 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg))
     2241 endif
     2242$(target)_$(prop).$(bld_trg) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
     2243endif
     2244ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
     2245 ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple)
     2246 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch))
     2247 endif
     2248$(target)_$(prop).$(bld_trg).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
     2249endif
     2250ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
     2251 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple)
     2252 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu))
     2253 endif
     2254$(target)_$(prop).$(bld_trg_cpu) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
     2255endif
     2256ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
     2257 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple)
     2258 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch))
     2259 endif
     2260$(target)_$(prop).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
     2261endif
     2262endef
     2263
     2264## Inherit one acculumlative template property where the 'most significant' items are at the right end.
     2265# @param    $(prop)     Property name
     2266# @param    $(target)   Target name
     2267define def_inherit_template_one_accumulate_r
     2268ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
     2269 ifeq ($$(flavor $(target)_$(prop)),simple)
     2270 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop))
     2271 endif
     2272$(target)_$(prop) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
     2273endif
     2274ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
     2275 ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple)
     2276 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE))
     2277 endif
     2278$(target)_$(prop).$(KBUILD_TYPE) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
     2279endif
     2280ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
     2281 ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple)
     2282 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg))
     2283 endif
     2284$(target)_$(prop).$(bld_trg) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
     2285endif
     2286ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
     2287 ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple)
     2288 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch))
     2289 endif
     2290$(target)_$(prop).$(bld_trg).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
     2291endif
     2292ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
     2293 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple)
     2294 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu))
     2295 endif
     2296$(target)_$(prop).$(bld_trg_cpu) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
     2297endif
     2298ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
     2299 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple)
     2300 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch))
     2301 endif
     2302$(target)_$(prop).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
     2303endif
     2304endef
     2305
     2306
     2307## Inherit template properties for on target.
     2308# @param    $(target)    Target name.
     2309define def_inherit_template
     2310# sanity check.
     2311ifdef _$(target)_ALREADY_PROCESSED
     2312 $(error kBuild: The target $(target) appears more than once in the target lists! Please correct the makefile(s))
     2313endif
     2314_$(target)_ALREADY_PROCESSED := 1
     2315
     2316# Inherit any default template.
     2317ifdef TEMPLATE
     2318ifeq ($($(target)_TEMPLATE),)
     2319$(eval $(target)_TEMPLATE:=$(TEMPLATE))
     2320endif
     2321endif
     2322# Expand the template if specified.
     2323ifneq ($($(target)_TEMPLATE),)
     2324$(foreach prop,$(PROPS_SINGLE),$(evalval def_inherit_template_one))
     2325$(foreach prop,$(PROPS_DEFERRED),$(eval $(def_inherit_template_one_deferred))) # exploits the 2 evaluation, so no value!
     2326$(foreach prop,$(PROPS_ACCUMULATE_L),$(eval $(def_inherit_template_one_accumulate_l))) # += works fine without value
     2327$(foreach prop,$(PROPS_ACCUMULATE_R),$(eval $(def_inherit_template_one_accumulate_r))) # use <= (kmk addition)
     2328endif
     2329endef
     2330
     2331
     2332Invoked like this:
     2333 $(kb-exp-tmpl 1,$(_ALL_TARGET_TARGETS),$(KBUILD_TARGET),$(KBUILD_TARGET_ARCH),$(KBUILD_TARGET_CPU),$(KBUILD_TYPE))
     2334*/
     2335char *
     2336func_kbuild_expand_template(char *o, char **argv, const char *pszFuncName)
     2337{
     2338    const char         *pszVersion    = argv[0];
     2339    const char         *pszBldTrg     = argv[2];
     2340    const char         *pszBldTrgArch = argv[3];
     2341    const char         *pszBldTrgCpu  = argv[4];
     2342    const char         *pszBldType    = argv[5];
     2343    size_t              cchBldTrg     = strlen(pszBldTrg);
     2344    size_t              cchBldTrgArch = strlen(pszBldTrgArch);
     2345    size_t              cchBldTrgCpu  = strlen(pszBldTrgCpu);
     2346    size_t              cchBldType    = strlen(pszBldType);
     2347    size_t              cchMaxBld     = cchBldTrg + cchBldTrgArch + cchBldTrgCpu + cchBldType; /* too big, but so what. */
     2348    struct kbet_key
     2349    {
     2350        unsigned int        cch;
     2351        char               *psz;
     2352    }                   aKeys[6];
     2353    unsigned int const  cKeys = 6;
     2354    unsigned int        iKey;
     2355    struct variable    *pDefTemplate;
     2356    struct variable    *pProps;
     2357    struct kbet_prop
     2358    {
     2359        unsigned int        cch;
     2360        const char         *pch;
     2361    }                  *paProps;
     2362    unsigned int        cProps;
     2363    unsigned int        iProp;
     2364    unsigned int        iPropsSingle;
     2365    unsigned int        iPropsSingleEnd;
     2366    unsigned int        iPropsDeferred;
     2367    unsigned int        iPropsDeferredEnd;
     2368    unsigned int        iPropsAccumulateL;
     2369    unsigned int        iPropsAccumulateLEnd;
     2370    unsigned int        iPropsAccumulateR;
     2371    unsigned int        iPropsAccumulateREnd;
     2372    size_t              cchMaxProp;
     2373    struct variable    *pVarTrg;
     2374    struct variable    *pVarSrc;
     2375    const char         *pszIter;
     2376    const char         *pszTarget;
     2377    unsigned int        cchTarget;
     2378    char               *pszSrc    = 0;
     2379    char               *pszSrcRef = 0;
     2380    char               *pszSrcBuf = 0;
     2381    size_t              cchSrcBuf = 0;
     2382    char               *pszTrg    = 0;
     2383    size_t              cchTrg    = 0;
     2384
     2385    /*
     2386     * Validate input.
     2387     */
     2388    if (pszVersion[0] != '1' || pszVersion[1])
     2389      fatal(NULL, "%s: Unsupported version `%s'", pszFuncName, pszVersion);
     2390
     2391    if (!cchBldTrg)
     2392      fatal(NULL, "%s: missing bldtrg", pszFuncName);
     2393
     2394    if (!cchBldTrgArch)
     2395      fatal(NULL, "%s: missing bld_trg_arch", pszFuncName);
     2396
     2397    if (!cchBldTrgCpu)
     2398      fatal(NULL, "%s: missing bld_trg_cpu", pszFuncName);
     2399
     2400    if (!cchBldType)
     2401      fatal(NULL, "%s: missing bld_type", pszFuncName);
     2402
     2403    /*
     2404     * Prepare the keywords, prepending dots for quicker copying.
     2405     * This allows for an inner loop when processing properties, saving code
     2406     * at the expense of a few xmallocs.
     2407     */
     2408    /* the first entry is empty. */
     2409    aKeys[0].cch = 0;
     2410    aKeys[0].psz = NULL;
     2411
     2412    aKeys[1].cch = cchBldType + 1;
     2413    aKeys[1].psz = xmalloc (aKeys[1].cch + 1);
     2414    aKeys[1].psz[0] = '.';
     2415    memcpy(aKeys[1].psz + 1, pszBldType, cchBldType + 1);
     2416
     2417    aKeys[2].cch = cchBldTrg + 1;
     2418    aKeys[2].psz = xmalloc (aKeys[2].cch + 1);
     2419    aKeys[2].psz[0] = '.';
     2420    memcpy(aKeys[2].psz + 1, pszBldTrg, cchBldTrg + 1);
     2421
     2422    aKeys[3].cch = cchBldTrg + 1 + cchBldTrgArch + 1;
     2423    aKeys[3].psz = xmalloc (aKeys[3].cch + 1);
     2424    aKeys[3].psz[0] = '.';
     2425    memcpy(aKeys[3].psz + 1, pszBldTrg, cchBldTrg);
     2426    aKeys[3].psz[1 + cchBldTrg] = '.';
     2427    memcpy(aKeys[3].psz + 1 + cchBldTrg + 1, pszBldTrgArch, cchBldTrgArch + 1);
     2428
     2429    aKeys[4].cch = cchBldTrgCpu + 1;
     2430    aKeys[4].psz = xmalloc (aKeys[4].cch + 1);
     2431    aKeys[4].psz[0] = '.';
     2432    memcpy(aKeys[4].psz + 1, pszBldTrgCpu, cchBldTrgCpu + 1);
     2433
     2434    aKeys[5].cch = cchBldTrgArch + 1;
     2435    aKeys[5].psz = xmalloc (aKeys[5].cch + 1);
     2436    aKeys[5].psz[0] = '.';
     2437    memcpy(aKeys[5].psz + 1, pszBldTrgArch, cchBldTrgArch + 1);
     2438
     2439
     2440    /*
     2441     * Prepare the properties, folding them into an array.
     2442     * This way we won't have to reparse them for each an every target, though
     2443     * it comes at the expense of one or more heap calls.
     2444     */
     2445#define PROP_ALLOC_INC  128
     2446    iProp = 0;
     2447    cProps = PROP_ALLOC_INC;
     2448    paProps = xmalloc(sizeof(*pProps) * cProps);
     2449
     2450    pProps = kbuild_get_variable_n(ST("PROPS_SINGLE"));
     2451    iPropsSingle = iProp;
     2452    pszIter = pProps->value;
     2453    while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch)))
     2454       if (++iProp >= cProps)
     2455       {
     2456           cProps += PROP_ALLOC_INC;
     2457           paProps = xrealloc(paProps, sizeof(*paProps) * cProps);
     2458       }
     2459    iPropsSingleEnd = iProp;
     2460
     2461    pProps = kbuild_get_variable_n(ST("PROPS_DEFERRED"));
     2462    iPropsDeferred = iProp;
     2463    pszIter = pProps->value;
     2464    while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch)))
     2465        if (++iProp >= cProps)
     2466        {
     2467            cProps += PROP_ALLOC_INC;
     2468            paProps = xrealloc(paProps, sizeof(*paProps) * cProps);
     2469        }
     2470    iPropsDeferredEnd = iProp;
     2471
     2472    pProps = kbuild_get_variable_n(ST("PROPS_ACCUMULATE_L"));
     2473    iPropsAccumulateL = iProp;
     2474    pszIter = pProps->value;
     2475    while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch)))
     2476        if (++iProp >= cProps)
     2477        {
     2478            cProps += PROP_ALLOC_INC;
     2479            paProps = xrealloc(paProps, sizeof(*paProps) * cProps);
     2480        }
     2481    iPropsAccumulateLEnd = iProp;
     2482
     2483    pProps = kbuild_get_variable_n(ST("PROPS_ACCUMULATE_R"));
     2484    iPropsAccumulateR = iProp;
     2485    pszIter = pProps->value;
     2486    while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch)))
     2487        if (++iProp >= cProps)
     2488        {
     2489            cProps += PROP_ALLOC_INC;
     2490            paProps = xrealloc(paProps, sizeof(*paProps) * cProps);
     2491        }
     2492    iPropsAccumulateREnd = iProp;
     2493#undef PROP_ALLOC_INC
     2494    cProps = iProp;
     2495
     2496    /* find the max prop length. */
     2497    cchMaxProp = paProps[0].cch;
     2498    while (--iProp > 0)
     2499        if (paProps[iProp].cch > cchMaxProp)
     2500            cchMaxProp = paProps[iProp].cch;
     2501
     2502    /*
     2503     * Query and prepare (strip) the default template
     2504     * (given by the TEMPLATE variable).
     2505     */
     2506    pDefTemplate = kbuild_lookup_variable_n(ST("TEMPLATE"));
     2507    if (pDefTemplate)
     2508    {
     2509        if (   pDefTemplate->value_length
     2510            && (   isspace(pDefTemplate->value[0])
     2511                || isspace(pDefTemplate->value[pDefTemplate->value_length - 1])))
     2512        {
     2513            unsigned int off;
     2514            if (pDefTemplate->rdonly_val)
     2515                fatal(NULL, "%s: TEMPLATE is read-only", pszFuncName);
     2516
     2517            /* head */
     2518            for (off = 0; isspace(pDefTemplate->value[off]); off++)
     2519                /* nothing */;
     2520            if (off)
     2521            {
     2522                pDefTemplate->value_length -= off;
     2523                memmove(pDefTemplate->value, pDefTemplate->value + off, pDefTemplate->value_length + 1);
     2524            }
     2525
     2526            /* tail */
     2527            off = pDefTemplate->value_length;
     2528            while (off > 0 && isspace(pDefTemplate->value[off - 1]))
     2529                off--;
     2530            pDefTemplate->value_length = off;
     2531            pDefTemplate->value[off] = '\0';
     2532        }
     2533
     2534        if (!pDefTemplate->value_length)
     2535            pDefTemplate = NULL;
     2536    }
     2537
     2538    /*
     2539     * Iterate the target list.
     2540     */
     2541    pszIter = argv[1];
     2542    while ((pszTarget = find_next_token(&pszIter, &cchTarget)))
     2543    {
     2544        char *pszTrgProp, *pszSrcProp;
     2545        char *pszTrgKey, *pszSrcKey;
     2546        struct variable *pTmpl;
     2547        const char *pszTmpl;
     2548        size_t cchTmpl, cchMax;
     2549
     2550        /* resize the target buffer. */
     2551        cchMax = cchTarget + cchMaxProp + cchMaxBld + 10;
     2552        if (cchTrg < cchMax)
     2553        {
     2554            cchTrg = (cchMax + 31U) & ~(size_t)31;
     2555            pszTrg = xrealloc(pszTrg, cchTrg);
     2556        }
     2557
     2558        /*
     2559         * Query the TEMPLATE property, if not found or zero-length fall back on the default.
     2560         */
     2561        memcpy(pszTrg, pszTarget, cchTarget);
     2562        pszTrgProp = pszTrg + cchTarget;
     2563        memcpy(pszTrgProp, "_TEMPLATE", sizeof("_TEMPLATE"));
     2564        pszTrgProp++; /* after '_'. */
     2565
     2566        /** @todo Change this to a recursive lookup with simplification below. That
     2567         *        will allow target_TEMPLATE = $(NO_SUCH_TEMPLATE) instead of having
     2568         *        to use target_TEMPLATE = DUMMY */
     2569        pTmpl = kbuild_lookup_variable_n(pszTrg, cchTarget + sizeof("_TEMPLATE") - 1);
     2570        if (!pTmpl || !pTmpl->value_length)
     2571        {
     2572            if (!pDefTemplate)
     2573                continue; /* no template */
     2574            pszTmpl = pDefTemplate->value;
     2575            cchTmpl = pDefTemplate->value_length;
     2576        }
     2577        else
     2578        {
     2579            pszTmpl = pTmpl->value;
     2580            cchTmpl = pTmpl->value_length;
     2581            while (isspace(*pszTmpl))
     2582                cchTmpl--, pszTmpl++;
     2583            if (!cchTmpl)
     2584                continue; /* no template */
     2585        }
     2586
     2587        /* resize the source buffer. */
     2588        cchMax = sizeof("TEMPLATE_") + cchTmpl + cchMaxProp + cchMaxBld + 10 + sizeof(void *);
     2589        if (cchSrcBuf < cchMax)
     2590        {
     2591            cchSrcBuf = (cchMax + 31U) & ~(size_t)31;
     2592            pszSrcBuf = xrealloc(pszSrcBuf, cchSrcBuf);
     2593            pszSrc = pszSrcBuf + sizeof(void *);  assert(sizeof(void *) >= 2);
     2594            pszSrcRef = pszSrc - 2;
     2595            pszSrcRef[0] = '$';
     2596            pszSrcRef[1] = '(';
     2597        }
     2598
     2599        /* prepare the source buffer */
     2600        memcpy(pszSrc, "TEMPLATE_", sizeof("TEMPLATE_") - 1);
     2601        pszSrcProp = pszSrc + sizeof("TEMPLATE_") - 1;
     2602        memcpy(pszSrcProp, pszTmpl, cchTmpl);
     2603        pszSrcProp += cchTmpl;
     2604        *pszSrcProp++ = '_';
     2605
     2606        /*
     2607         * Process properties.
     2608         * Note! The single and deferred are handled in the same way now.
     2609         */
     2610#define BY_REF_LIMIT   64 /*(cchSrcVar * 4 > 64 ? cchSrcVar * 4 : 64)*/
     2611
     2612        /* single: copy template prop if target doesn't define it. */
     2613        for (iProp = iPropsSingle; iProp < iPropsSingleEnd; iProp++)
     2614        {
     2615            memcpy(pszTrgProp, paProps[iProp].pch, paProps[iProp].cch);
     2616            pszTrgKey = pszTrgProp + paProps[iProp].cch;
     2617
     2618            memcpy(pszSrcProp, paProps[iProp].pch, paProps[iProp].cch);
     2619            pszSrcKey = pszSrcProp + paProps[iProp].cch;
     2620
     2621            for (iKey = 0; iKey < cKeys; iKey++)
     2622            {
     2623                char *pszTrgEnd;
     2624                size_t cchSrcVar;
     2625
     2626                /* lookup source, skip ahead if it doesn't exist. */
     2627                memcpy(pszSrcKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2628                cchSrcVar = pszSrcKey - pszSrc + aKeys[iKey].cch;
     2629                pszSrc[cchSrcVar] = '\0';
     2630                pVarSrc = kbuild_query_recursive_variable_n(pszSrc, cchSrcVar);
     2631                if (!pVarSrc)
     2632                    continue;
     2633
     2634                /* lookup target, skip ahead if it exists. */
     2635                memcpy(pszTrgKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2636                pszTrgEnd = pszTrgKey + aKeys[iKey].cch;
     2637                *pszTrgEnd = '\0';
     2638                pVarTrg = kbuild_query_recursive_variable_n(pszTrg, pszTrgEnd - pszTrg);
     2639                if (pVarTrg)
     2640                    continue;
     2641
     2642                /* copy the variable if its short, otherwise reference it. */
     2643                if (pVarSrc->value_length < BY_REF_LIMIT)
     2644                    define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2645                                              pVarSrc->value, pVarSrc->value_length,
     2646                                              1 /* duplicate_value */,
     2647                                              o_file,
     2648                                              pVarSrc->recursive,
     2649                                              NULL /* flocp */);
     2650                else
     2651                {
     2652                    pszSrc[cchSrcVar] = ')';
     2653                    pszSrc[cchSrcVar + 1] = '\0';
     2654                    define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2655                                              pszSrcRef, 2 + cchSrcVar + 1,
     2656                                              1 /* duplicate_value */,
     2657                                              o_file,
     2658                                              1 /* recursive */,
     2659                                              NULL /* flocp */);
     2660                }
     2661            } /* foreach key */
     2662        } /* foreach single prop */
     2663
     2664        /* deferred: copy template prop if target doesn't define it. */
     2665        for (iProp = iPropsDeferred; iProp < iPropsDeferredEnd; iProp++)
     2666        {
     2667            memcpy(pszTrgProp, paProps[iProp].pch, paProps[iProp].cch);
     2668            pszTrgKey = pszTrgProp + paProps[iProp].cch;
     2669
     2670            memcpy(pszSrcProp, paProps[iProp].pch, paProps[iProp].cch);
     2671            pszSrcKey = pszSrcProp + paProps[iProp].cch;
     2672
     2673            for (iKey = 0; iKey < cKeys; iKey++)
     2674            {
     2675                char *pszTrgEnd;
     2676                size_t cchSrcVar;
     2677
     2678                /* lookup source, skip ahead if it doesn't exist. */
     2679                memcpy(pszSrcKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2680                cchSrcVar = pszSrcKey - pszSrc + aKeys[iKey].cch;
     2681                pszSrc[cchSrcVar] = '\0';
     2682                pVarSrc = kbuild_query_recursive_variable_n(pszSrc, cchSrcVar);
     2683                if (!pVarSrc)
     2684                    continue;
     2685
     2686                /* lookup target, skip ahead if it exists. */
     2687                memcpy(pszTrgKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2688                pszTrgEnd = pszTrgKey + aKeys[iKey].cch;
     2689                *pszTrgEnd = '\0';
     2690                pVarTrg = kbuild_query_recursive_variable_n(pszTrg, pszTrgEnd - pszTrg);
     2691                if (pVarTrg)
     2692                    continue;
     2693
     2694                /* copy the variable if its short, otherwise reference it. */
     2695                if (pVarSrc->value_length < BY_REF_LIMIT)
     2696                    define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2697                                              pVarSrc->value, pVarSrc->value_length,
     2698                                              1 /* duplicate_value */,
     2699                                              o_file,
     2700                                              pVarSrc->recursive,
     2701                                              NULL /* flocp */);
     2702                else
     2703                {
     2704                    pszSrc[cchSrcVar] = ')';
     2705                    pszSrc[cchSrcVar + 1] = '\0';
     2706                    define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2707                                              pszSrcRef, 2 + cchSrcVar + 1,
     2708                                              1 /* duplicate_value */,
     2709                                              o_file,
     2710                                              1 /* recursive */,
     2711                                              NULL /* flocp */);
     2712                }
     2713            }  /* foreach key */
     2714        } /* foreach deferred prop */
     2715
     2716        /* accumulate_l: append the unexpanded template variable to the . */
     2717        for (iProp = iPropsAccumulateL; iProp < iPropsAccumulateLEnd; iProp++)
     2718        {
     2719            memcpy(pszTrgProp, paProps[iProp].pch, paProps[iProp].cch);
     2720            pszTrgKey = pszTrgProp + paProps[iProp].cch;
     2721
     2722            memcpy(pszSrcProp, paProps[iProp].pch, paProps[iProp].cch);
     2723            pszSrcKey = pszSrcProp + paProps[iProp].cch;
     2724
     2725            for (iKey = 0; iKey < cKeys; iKey++)
     2726            {
     2727                char *pszTrgEnd;
     2728                size_t cchSrcVar;
     2729
     2730                /* lookup source, skip ahead if it doesn't exist. */
     2731                memcpy(pszSrcKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2732                cchSrcVar = pszSrcKey - pszSrc + aKeys[iKey].cch;
     2733                pszSrc[cchSrcVar] = '\0';
     2734                pVarSrc = kbuild_query_recursive_variable_n(pszSrc, cchSrcVar);
     2735                if (!pVarSrc)
     2736                    continue;
     2737
     2738                /* lookup target, skip ahead if it exists. */
     2739                memcpy(pszTrgKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2740                pszTrgEnd = pszTrgKey + aKeys[iKey].cch;
     2741                *pszTrgEnd = '\0';
     2742                pVarTrg = kbuild_query_recursive_variable_n(pszTrg, pszTrgEnd - pszTrg);
     2743                if (!pVarTrg)
     2744                {
     2745                    /* The target doesn't exist, copy the source if it's short,
     2746                       otherwise just reference it. */
     2747                    if (pVarSrc->value_length < BY_REF_LIMIT)
     2748                        define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2749                                                  pVarSrc->value, pVarSrc->value_length,
     2750                                                  1 /* duplicate_value */,
     2751                                                  o_file,
     2752                                                  pVarSrc->recursive,
     2753                                                  NULL /* flocp */);
     2754                    else
     2755                    {
     2756                        pszSrc[cchSrcVar] = ')';
     2757                        pszSrc[cchSrcVar + 1] = '\0';
     2758                        define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2759                                                  pszSrcRef, 2 + cchSrcVar + 1,
     2760                                                  1 /* duplicate_value */,
     2761                                                  o_file,
     2762                                                  1 /* recursive */,
     2763                                                  NULL /* flocp */);
     2764                    }
     2765                }
     2766                else
     2767                {
     2768                    /* Append to existing variable. If the source is recursive,
     2769                       or we append by reference, we'll have to make sure the
     2770                       target is recusive as well. */
     2771                    if (    !pVarTrg->recursive
     2772                        &&  (   pVarSrc->value_length >= BY_REF_LIMIT
     2773                             || pVarSrc->recursive))
     2774                        pVarTrg->recursive = 1;
     2775
     2776                    if (pVarSrc->value_length < BY_REF_LIMIT)
     2777                        append_string_to_variable(pVarTrg, pVarSrc->value, pVarSrc->value_length, 1 /* append */);
     2778                    else
     2779                    {
     2780                        pszSrc[cchSrcVar] = ')';
     2781                        pszSrc[cchSrcVar + 1] = '\0';
     2782                        append_string_to_variable(pVarTrg, pszSrcRef, 2 + cchSrcVar + 1, 1 /* append */);
     2783                    }
     2784                }
     2785            } /* foreach key */
     2786        } /* foreach accumulate_l prop */
     2787
     2788        /* accumulate_r: prepend the unexpanded template variable to the . */
     2789        for (iProp = iPropsAccumulateR; iProp < iPropsAccumulateREnd; iProp++)
     2790        {
     2791            memcpy(pszTrgProp, paProps[iProp].pch, paProps[iProp].cch);
     2792            pszTrgKey = pszTrgProp + paProps[iProp].cch;
     2793
     2794            memcpy(pszSrcProp, paProps[iProp].pch, paProps[iProp].cch);
     2795            pszSrcKey = pszSrcProp + paProps[iProp].cch;
     2796
     2797            for (iKey = 0; iKey < cKeys; iKey++)
     2798            {
     2799                char *pszTrgEnd;
     2800                size_t cchSrcVar;
     2801
     2802                /* lookup source, skip ahead if it doesn't exist. */
     2803                memcpy(pszSrcKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2804                cchSrcVar = pszSrcKey - pszSrc + aKeys[iKey].cch;
     2805                pszSrc[cchSrcVar] = '\0';
     2806                pVarSrc = kbuild_query_recursive_variable_n(pszSrc, cchSrcVar);
     2807                if (!pVarSrc)
     2808                    continue;
     2809
     2810                /* lookup target, skip ahead if it exists. */
     2811                memcpy(pszTrgKey, aKeys[iKey].psz, aKeys[iKey].cch);
     2812                pszTrgEnd = pszTrgKey + aKeys[iKey].cch;
     2813                *pszTrgEnd = '\0';
     2814                pVarTrg = kbuild_query_recursive_variable_n(pszTrg, pszTrgEnd - pszTrg);
     2815                if (!pVarTrg)
     2816                {
     2817                    /* The target doesn't exist, copy the source if it's short,
     2818                       otherwise just reference it. */
     2819                    if (pVarSrc->value_length < BY_REF_LIMIT)
     2820                        define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2821                                                  pVarSrc->value, pVarSrc->value_length,
     2822                                                  1 /* duplicate_value */,
     2823                                                  o_file,
     2824                                                  pVarSrc->recursive,
     2825                                                  NULL /* flocp */);
     2826                    else
     2827                    {
     2828                        pszSrc[cchSrcVar] = ')';
     2829                        pszSrc[cchSrcVar + 1] = '\0';
     2830                        define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg,
     2831                                                  pszSrcRef, 2 + cchSrcVar + 1,
     2832                                                  1 /* duplicate_value */,
     2833                                                  o_file,
     2834                                                  1 /* recursive */,
     2835                                                  NULL /* flocp */);
     2836                    }
     2837                }
     2838                else
     2839                {
     2840                    /* Append to existing variable. If the source is recursive,
     2841                       or we append by reference, we'll have to make sure the
     2842                       target is recusive as well. */
     2843                    if (    !pVarTrg->recursive
     2844                        &&  (   pVarSrc->value_length >= BY_REF_LIMIT
     2845                             || pVarSrc->recursive))
     2846                        pVarTrg->recursive = 1;
     2847
     2848                    if (pVarSrc->value_length < BY_REF_LIMIT)
     2849                        append_string_to_variable(pVarTrg, pVarSrc->value, pVarSrc->value_length, 0 /* prepend */);
     2850                    else
     2851                    {
     2852                        pszSrc[cchSrcVar] = ')';
     2853                        pszSrc[cchSrcVar + 1] = '\0';
     2854                        append_string_to_variable(pVarTrg, pszSrcRef, 2 + cchSrcVar + 1, 0 /* append */);
     2855                    }
     2856                }
     2857            } /* foreach key */
     2858        } /* foreach accumulate_r prop */
     2859
     2860#undef BY_REF_LIMIT
     2861    } /* foreach target */
     2862
     2863    /*
     2864     * Cleanup.
     2865     */
     2866    free(pszSrcBuf);
     2867    free(pszTrg);
     2868    free(paProps);
     2869    for (iKey = 1; iKey < cKeys; iKey++)
     2870        free(aKeys[iKey].psz);
     2871
     2872    return o;
     2873}
    22012874
    22022875#endif /* KMK_HELPERS */
Note: See TracChangeset for help on using the changeset viewer.

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