VirtualBox

Changeset 2769 in kBuild for trunk/src


Ignore:
Timestamp:
Feb 1, 2015 12:44:30 AM (10 years ago)
Author:
bird
Message:

String expansion 'compilation' and 'execution' code is mostly done.

Location:
trunk/src/kmk
Files:
4 edited

Legend:

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

    r2765 r2769  
    212212
    213213#ifdef CONFIG_WITH_VALUE_LENGTH
    214 /* Static worker for reference_variable() that expands the recursive
     214/* Worker for reference_variable() and kmk_exec_* that expands the recursive
    215215   variable V. The main difference between this and
    216216   recursively_expand[_for_file] is that this worker avoids the temporary
    217217   buffer and outputs directly into the current variable buffer (O).  */
    218 static char *
     218char *
    219219reference_recursive_variable (char *o, struct variable *v)
    220220{
     
    12181218}
    12191219
    1220 /* Restore a previously-saved variable_buffer setting (free the current one).
    1221  */
     1220#ifdef CONFIG_WITH_COMPILER
     1221/* Same as install_variable_buffer, except we supply a size hint.  */
     1222
     1223char *
     1224install_variable_buffer_with_hint (char **bufp, unsigned int *lenp, unsigned int size_hint)
     1225{
     1226  struct recycled_buffer *recycled;
     1227  char *buf;
     1228
     1229  *bufp = variable_buffer;
     1230  *lenp = variable_buffer_length;
     1231
     1232  recycled = recycled_head;
     1233  if (recycled)
     1234    {
     1235      recycled_head = recycled->next;
     1236      variable_buffer_length = recycled->length;
     1237      variable_buffer = buf = (char *)recycled;
     1238    }
     1239  else
     1240    {
     1241      if (size_hint < 512)
     1242        variable_buffer_length = (size_hint + 1 + 63) & ~(unsigned int)63;
     1243      else if (size_hint < 4096)
     1244        variable_buffer_length = (size_hint + 1 + 1023) & ~(unsigned int)1023;
     1245      else
     1246        variable_buffer_length = (size_hint + 1 + 4095) & ~(unsigned int)4095;
     1247      variable_buffer = buf = xmalloc (variable_buffer_length);
     1248    }
     1249  buf[0] = '\0';
     1250  return buf;
     1251}
     1252#endif /* CONFIG_WITH_COMPILER */
     1253
     1254/* Restore a previously-saved variable_buffer setting (free the
     1255   current one). */
    12221256
    12231257void
     
    12341268  variable_buffer_length = len;
    12351269}
     1270
     1271
     1272/* Used to make sure there is at least SIZE bytes of buffer space
     1273   available starting at PTR.  */
     1274char *
     1275ensure_variable_buffer_space(char *ptr, unsigned int size)
     1276{
     1277  unsigned int offset = (unsigned int)(ptr - variable_buffer);
     1278  assert(offset <= variable_buffer_length);
     1279  if (variable_buffer_length - offset < size)
     1280    {
     1281      unsigned minlen = size + offset;
     1282      variable_buffer_length *= 2;
     1283      if (variable_buffer_length < minlen + 100)
     1284        variable_buffer_length = (minlen + 100 + 63) & ~(unsigned int)63;
     1285      variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
     1286      ptr = variable_buffer + offset;
     1287    }
     1288  return ptr;
     1289}
     1290
  • trunk/src/kmk/kmk_cc_exec.c

    r2768 r2769  
    6565typedef KMKCCBLOCK *PKMKCCBLOCK;
    6666
    67 /** Expansion instructions. */
     67/**
     68 * String expansion statistics.
     69 */
     70typedef struct KMKCCEXPSTATS
     71{
     72    /** Max expanded size. */
     73    uint32_t                    cchMax;
     74    /** Recent average size. */
     75    uint32_t                    cchAvg;
     76} KMKCCEXPSTATS;
     77typedef KMKCCEXPSTATS *PKMKCCEXPSTATS;
     78
     79/**
     80 * Expansion instructions.
     81 */
    6882typedef enum KMKCCEXPINSTR
    6983{
     
    7488    /** Insert an expanded variable value, the name is dynamic (sub prog). */
    7589    kKmkCcExpInstr_DynamicVariable,
     90    /** Insert an expanded variable value, which name we already know, doing
     91     * search an replace on a string. */
     92    kKmkCcExpInstr_SearchAndReplacePlainVariable,
    7693    /** Insert the output of function that requires no argument expansion. */
    7794    kKmkCcExpInstr_PlainFunction,
    7895    /** Insert the output of function that requires dynamic expansion of one ore
    79      * more arguments. */
     96     * more arguments.  (Dynamic is perhaps not such a great name, but whatever.) */
    8097    kKmkCcExpInstr_DynamicFunction,
    8198    /** Jump to a new instruction block. */
     
    95112typedef KMKCCEXPCORE *PKMKCCEXPCORE;
    96113
     114/**
     115 * String expansion sub program.
     116 */
    97117typedef struct kmk_cc_exp_subprog
    98118{
    99119    /** Pointer to the first instruction. */
    100120    PKMKCCEXPCORE           pFirstInstr;
    101     /** Max expanded size. */
    102     uint32_t                cbMax;
    103     /** Recent average size. */
    104     uint32_t                cbAvg;
     121    /** Statistics. */
     122    KMKCCEXPSTATS           Stats;
    105123} KMKCCEXPSUBPROG;
    106124typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG;
    107125
     126/**
     127 * kKmkCcExpInstr_CopyString instruction format.
     128 */
    108129typedef struct kmk_cc_exp_copy_string
    109130{
     
    117138typedef KMKCCEXPCOPYSTRING *PKMKCCEXPCOPYSTRING;
    118139
     140/**
     141 * kKmkCcExpInstr_PlainVariable instruction format.
     142 */
    119143typedef struct kmk_cc_exp_plain_variable
    120144{
    121145    /** The core instruction. */
    122146    KMKCCEXPCORE            Core;
    123     /** The variable strcache entry for this variable. */
    124     struct strcache2_entry const *pNameEntry;
     147    /** The name of the variable (points into variable_strcache). */
     148    const char             *pszName;
    125149} KMKCCEXPPLAINVAR;
    126150typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR;
    127151
     152/**
     153 * kKmkCcExpInstr_DynamicVariable instruction format.
     154 */
    128155typedef struct kmk_cc_exp_dynamic_variable
    129156{
    130157    /** The core instruction. */
    131158    KMKCCEXPCORE            Core;
    132     /** Where to continue after this instruction.  This is necessary since the
    133      * subprogram is allocated after us in the instruction block.  Since the sub
    134      * program is of variable size, we don't even know if we're still in the same
    135      * instruction block.  So, we include a jump here. */
     159    /** Where to continue after this instruction.  (This is necessary since the
     160     * instructions of the subprogram are emitted after this instruction.) */
    136161    PKMKCCEXPCORE           pNext;
    137162    /** The subprogram that will give us the variable name. */
     
    140165typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR;
    141166
     167/**
     168 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction format.
     169 */
     170typedef struct kmk_cc_exp_sr_plain_variable
     171{
     172    /** The core instruction. */
     173    KMKCCEXPCORE            Core;
     174    /** Where to continue after this instruction.  (This is necessary since the
     175     * instruction contains string data of variable size.) */
     176    PKMKCCEXPCORE           pNext;
     177    /** The name of the variable (points into variable_strcache). */
     178    const char             *pszName;
     179    /** Search pattern.  */
     180    const char             *pszSearchPattern;
     181    /** Replacement pattern. */
     182    const char             *pszReplacePattern;
     183    /** Offset into pszSearchPattern of the significant '%' char. */
     184    uint32_t                offPctSearchPattern;
     185    /** Offset into pszReplacePattern of the significant '%' char. */
     186    uint32_t                offPctReplacePattern;
     187} KMKCCEXPSRPLAINVAR;
     188typedef KMKCCEXPSRPLAINVAR *PKMKCCEXPSRPLAINVAR;
     189
     190/**
     191 * Instruction format parts common to both kKmkCcExpInstr_PlainFunction and
     192 * kKmkCcExpInstr_DynamicFunction.
     193 */
    142194typedef struct kmk_cc_exp_function_core
    143195{
     
    146198    /** Number of arguments. */
    147199    uint32_t                cArgs;
    148     /** Where to continue after this instruction.  This is necessary since the
    149      * instruction is of variable size and we don't even know if we're still in the
    150      * same instruction block.  So, we include a jump here. */
     200    /** Where to continue after this instruction.  (This is necessary since the
     201     * instructions are of variable size and may be followed by string data.) */
    151202    PKMKCCEXPCORE           pNext;
    152203    /**
     
    164215typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE;
    165216
     217/**
     218 * Instruction format for kKmkCcExpInstr_PlainFunction.
     219 */
    166220typedef struct kmk_cc_exp_plain_function
    167221{
     
    178232#define KMKCCEXPPLAINFUNC_SIZE(a_cArgs)  (sizeof(KMKCCEXPFUNCCORE) + (a_cArgs + 1) * sizeof(const char *))
    179233
     234/**
     235 * Instruction format for kKmkCcExpInstr_DynamicFunction.
     236 */
    180237typedef struct kmk_cc_exp_dyn_function
    181238{
     
    209266                                          + (a_cArgs) * sizeof(((PKMKCCEXPDYNFUNC)(uintptr_t)42)->aArgs[0]) )
    210267
     268/**
     269 * Instruction format for kKmkCcExpInstr_Jump.
     270 */
    211271typedef struct kmk_cc_exp_jump
    212272{
     
    227287    /** List of blocks for this program (LIFO). */
    228288    PKMKCCBLOCK             pBlockTail;
    229     /** Max expanded size. */
    230     uint32_t                cbMax;
    231     /** Recent average size. */
    232     uint32_t                cbAvg;
     289    /** Statistics. */
     290    KMKCCEXPSTATS           Stats;
    233291} KMKCCEXPPROG;
    234292/** Pointer to a string expansion program. */
     
    245303*******************************************************************************/
    246304static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg);
     305static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcch);
    247306
    248307
     
    741800
    742801/**
    743  * Emits a kKmkCcExpInstr_PlainVariable.
     802 * Emits either a kKmkCcExpInstr_PlainVariable or
     803 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction.
    744804 *
    745805 * @returns 0 on success, non-zero on failure.
     
    750810 *                              nothing will be emitted.
    751811 */
    752 static int kmk_cc_exp_emit_plain_variable(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName)
     812static int kmk_cc_exp_emit_plain_variable_maybe_sr(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName)
    753813{
    754814    if (cchName > 0)
    755815    {
    756         PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
    757         pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable;
    758         pInstr->pNameEntry = strcache2_get_entry(&variable_strcache, strcache2_add(&variable_strcache, pchName, cchName));
     816        /*
     817         * Hopefully, we're not expected to do any search and replace on the
     818         * expanded variable string later...  Requires both ':' and '='.
     819         */
     820        const char *pchEqual;
     821        const char *pchColon = (const char *)memchr(pchName, ':', cchName);
     822        if (   pchColon == NULL
     823            || (pchEqual = (const char *)memchr(pchColon + 1, ':', cchName - (pchColon - pchName - 1))) == NULL
     824            || pchEqual == pchEqual + 1)
     825        {
     826            PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
     827            pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable;
     828            pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName);
     829        }
     830        else if (pchColon != pchName)
     831        {
     832            /*
     833             * Okay, we need to do search and replace the variable value.
     834             * This is performed by patsubst_expand_pat using '%' patterns.
     835             */
     836            uint32_t            cchName2   = (uint32_t)(pchColon - pchName);
     837            uint32_t            cchSearch  = (uint32_t)(pchEqual - pchColon - 1);
     838            uint32_t            cchReplace = cchName - cchName2 - cchSearch - 2;
     839            const char         *pchPct;
     840            char               *psz;
     841            PKMKCCEXPSRPLAINVAR pInstr;
     842
     843            pInstr = (PKMKCCEXPSRPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
     844            pInstr->Core.enmOpCode = kKmkCcExpInstr_SearchAndReplacePlainVariable;
     845            pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName2);
     846
     847            /* Figure out the search pattern, unquoting percent chars.. */
     848            psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchSearch + 2);
     849            psz[0] = '%';
     850            memcpy(psz + 1, pchColon + 1, cchSearch);
     851            psz[1 + cchSearch] = '\0';
     852            pchPct = find_percent(psz + 1); /* also performs unquoting */
     853            if (pchPct)
     854            {
     855                pInstr->pszSearchPattern    = psz + 1;
     856                pInstr->offPctSearchPattern = (uint32_t)(pchPct - psz - 1);
     857            }
     858            else
     859            {
     860                pInstr->pszSearchPattern    = psz;
     861                pInstr->offPctSearchPattern = 0;
     862            }
     863
     864            /* Figure out the replacement pattern, unquoting percent chars.. */
     865            if (cchReplace == 0)
     866            {
     867                pInstr->pszReplacePattern    = "%";
     868                pInstr->offPctReplacePattern = 0;
     869            }
     870            else
     871            {
     872                psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchReplace + 2);
     873                psz[0] = '%';
     874                memcpy(psz + 1, pchEqual + 1, cchReplace);
     875                psz[1 + cchReplace] = '\0';
     876                pchPct = find_percent(psz + 1); /* also performs unquoting */
     877                if (pchPct)
     878                {
     879                    pInstr->pszReplacePattern    = psz + 1;
     880                    pInstr->offPctReplacePattern = (uint32_t)(pchPct - psz - 1);
     881                }
     882                else
     883                {
     884                    pInstr->pszReplacePattern    = psz;
     885                    pInstr->offPctReplacePattern = 0;
     886                }
     887            }
     888
     889            /* Note down where the next instruction is after realigning the allocator. */
     890            kmk_cc_block_realign(ppBlockTail);
     891            pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
     892        }
    759893    }
    760894    return 0;
     
    837971                    {
    838972                        /* There are several alternative ways of finding the ending
    839                            parenthesis / braces.  GNU make only consideres open &
    840                            close chars of the one we're processing, and it does not
    841                            matter whether the opening paren / braces are preceeded by
    842                            any dollar char.  Simple and efficient.  */
     973                           parenthesis / braces.
     974
     975                           GNU make does one thing for functions and variable containing
     976                           any '$' chars before the first closing char.  While for
     977                           variables where a closing char comes before any '$' char, a
     978                           simplified approach is taken.  This means that for example:
     979
     980                                Given VAR=var, the expressions "$(var())" and
     981                                "$($(VAR)())" would be expanded differently.
     982                                In the first case the variable "var(" would be
     983                                used and in the second "var()".
     984
     985                           This code will not duplicate this weird behavior, but work
     986                           the same regardless of whether there is a '$' char before
     987                           the first closing char. */
    843988                        make_function_ptr_t pfnFunction;
    844989                        const char         *pszFunction;
     
    8651010                            cchName++;
    8661011                        }
     1012
    8671013                        if (   cchName >= MIN_FUNCTION_LENGTH
    8681014                            && cchName <= MAX_FUNCTION_LENGTH
     
    10021148                            }
    10031149                            if (cDollars == 0)
    1004                                 rc = kmk_cc_exp_emit_plain_variable(ppBlockTail, pchStr, cchName);
     1150                                rc = kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, cchName);
    10051151                            else
    10061152                                rc = kmk_cc_exp_emit_dyn_variable(ppBlockTail, pchStr, cchName);
     
    10121158                    {
    10131159                        /* Single character variable name. */
    1014                         rc = kmk_cc_exp_emit_plain_variable(ppBlockTail, pchStr, 1);
     1160                        rc = kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, 1);
    10151161                        pchStr++;
    10161162                        cchStr--;
     
    10461192
    10471193/**
     1194 * Initializes string expansion program statistics.
     1195 * @param   pStats              Pointer to the statistics structure to init.
     1196 */
     1197static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats)
     1198{
     1199    pStats->cchAvg = 0;
     1200    pStats->cchMax = 0;
     1201}
     1202
     1203
     1204/**
    10481205 * Compiles a string expansion sub program.
    10491206 *
     
    10641221    assert(cchStr);
    10651222    pSubProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
    1066     pSubProg->cbMax = 0;
    1067     pSubProg->cbAvg = 0;
     1223    kmk_cc_exp_stats_init(&pSubProg->Stats);
    10681224    return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr);
    10691225}
     
    10951251        pProg->pBlockTail   = pBlock;
    10961252        pProg->pFirstInstr  = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(pBlock);
    1097         pProg->cbMax        = 0;
    1098         pProg->cbAvg        = 0;
     1253        kmk_cc_exp_stats_init(&pProg->Stats);
    10991254
    11001255        /*
     
    11451300
    11461301
     1302#ifndef NDEBUG
     1303/**
     1304 * Used to check that function arguments are left alone.
     1305 * @returns Updated hash.
     1306 * @param   uHash       The current hash value.
     1307 * @param   psz         The string to hash.
     1308 */
     1309static uint32_t kmk_exec_debug_string_hash(uint32_t uHash, const char *psz)
     1310{
     1311    unsigned char ch;
     1312    while ((ch = *(unsigned char const *)psz++) != '\0')
     1313        uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch;
     1314    return uHash;
     1315}
     1316#endif
     1317
     1318
     1319/**
     1320 * String expansion execution worker for outputting a variable.
     1321 *
     1322 * @returns The new variable buffer position.
     1323 * @param   pVar        The variable to reference.
     1324 * @param   pchDst      The current variable buffer position.
     1325 */
     1326static char *kmk_exec_expand_worker_reference_variable(struct variable *pVar, char *pchDst)
     1327{
     1328    if (pVar->value_length > 0)
     1329    {
     1330        if (!pVar->recursive)
     1331            pchDst = variable_buffer_output(pchDst, pVar->value, pVar->value_length);
     1332        else
     1333            pchDst = reference_recursive_variable(pchDst, pVar);
     1334    }
     1335    else if (pVar->append)
     1336        pchDst = reference_recursive_variable(pchDst, pVar);
     1337    return pchDst;
     1338}
     1339
     1340
     1341/**
     1342 * Executes a stream string expansion instructions, outputting to the current
     1343 * varaible buffer.
     1344 *
     1345 * @returns The new variable buffer position.
     1346 * @param   pInstrCore      The instruction to start executing at.
     1347 * @param   pchDst          The current variable buffer position.
     1348 */
     1349static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrCore, char *pchDst)
     1350{
     1351    for (;;)
     1352    {
     1353        switch (pInstrCore->enmOpCode)
     1354        {
     1355            case kKmkCcExpInstr_CopyString:
     1356            {
     1357                PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)pInstrCore;
     1358                pchDst = variable_buffer_output(pchDst, pInstr->pachSrc, pInstr->cchCopy);
     1359
     1360                pInstrCore = &(pInstr + 1)->Core;
     1361                break;
     1362            }
     1363
     1364            case kKmkCcExpInstr_PlainVariable:
     1365            {
     1366                PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)pInstrCore;
     1367                struct variable  *pVar = lookup_variable_strcached(pInstr->pszName);
     1368                if (pVar)
     1369                    pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst);
     1370                else
     1371                    warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName));
     1372
     1373                pInstrCore = &(pInstr + 1)->Core;
     1374                break;
     1375            }
     1376
     1377            case kKmkCcExpInstr_DynamicVariable:
     1378            {
     1379                PKMKCCEXPDYNVAR  pInstr = (PKMKCCEXPDYNVAR)pInstrCore;
     1380                struct variable *pVar;
     1381                uint32_t         cchName;
     1382                char            *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->SubProg, &cchName);
     1383                char            *pszColon = (char *)memchr(pszName, ':', cchName);
     1384                char            *pszEqual;
     1385                if (   pszColon == NULL
     1386                    || (pszEqual = (char *)memchr(pszColon + 1, '=', &pszName[cchName] - pszColon - 1)) == NULL
     1387                    || pszEqual == pszColon + 1)
     1388                {
     1389                    pVar = lookup_variable(pszName, cchName);
     1390                    if (pVar)
     1391                        pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst);
     1392                    else
     1393                        warn_undefined(pszName, cchName);
     1394                }
     1395                else if (pszColon != pszName)
     1396                {
     1397                    /*
     1398                     * Oh, we have to do search and replace. How tedious.
     1399                     * Since the variable name is a temporary buffer, we can transform
     1400                     * the strings into proper search and replacement patterns directly.
     1401                     */
     1402                    pVar = lookup_variable(pszName, pszColon - pszName);
     1403                    if (pVar)
     1404                    {
     1405                        char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value;
     1406                        char       *pszSearchPat  = pszColon + 1;
     1407                        char       *pszReplacePat = pszEqual + 1;
     1408                        const char *pchPctSearchPat;
     1409                        const char *pchPctReplacePat;
     1410
     1411                        *pszEqual = '\0';
     1412                        pchPctSearchPat = find_percent(pszSearchPat);
     1413                        pchPctReplacePat = find_percent(pszReplacePat);
     1414
     1415                        if (!pchPctReplacePat)
     1416                        {
     1417                            if (pszReplacePat[-2] != '\0') /* On the offchance that a pct was unquoted by find_percent. */
     1418                            {
     1419                                memmove(pszName + 1, pszSearchPat, pszReplacePat - pszSearchPat);
     1420                                if (pchPctSearchPat)
     1421                                    pchPctSearchPat -= pszSearchPat - &pszName[1];
     1422                                pszSearchPat = &pszName[1];
     1423                            }
     1424                            pchPctReplacePat = --pszReplacePat;
     1425                            *pszReplacePat = '%';
     1426                        }
     1427
     1428                        if (!pchPctSearchPat)
     1429                        {
     1430                            pchPctSearchPat = --pszSearchPat;
     1431                            *pszSearchPat = '%';
     1432                        }
     1433
     1434                        pchDst = patsubst_expand_pat(pchDst, pszExpandedVarValue,
     1435                                                     pszSearchPat, pszReplacePat,
     1436                                                     pchPctSearchPat, pchPctReplacePat);
     1437
     1438                        if (pVar->recursive)
     1439                            free((void *)pszExpandedVarValue);
     1440                    }
     1441                    else
     1442                        warn_undefined(pszName, pszColon - pszName);
     1443                }
     1444                free(pszName);
     1445
     1446                pInstrCore = pInstr->pNext;
     1447                break;
     1448            }
     1449
     1450
     1451            case kKmkCcExpInstr_SearchAndReplacePlainVariable:
     1452            {
     1453                PKMKCCEXPSRPLAINVAR pInstr = (PKMKCCEXPSRPLAINVAR)pInstrCore;
     1454                struct variable    *pVar = lookup_variable_strcached(pInstr->pszName);
     1455                if (pVar)
     1456                {
     1457                    char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value;
     1458                    pchDst = patsubst_expand_pat(pchDst,
     1459                                                 pszExpandedVarValue,
     1460                                                 pInstr->pszSearchPattern,
     1461                                                 pInstr->pszReplacePattern,
     1462                                                 &pInstr->pszSearchPattern[pInstr->offPctSearchPattern],
     1463                                                 &pInstr->pszReplacePattern[pInstr->offPctReplacePattern]);
     1464                    if (pVar->recursive)
     1465                        free((void *)pszExpandedVarValue);
     1466                }
     1467                else
     1468                    warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName));
     1469
     1470                pInstrCore = pInstr->pNext;
     1471                break;
     1472            }
     1473
     1474            case kKmkCcExpInstr_PlainFunction:
     1475            {
     1476                PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)pInstrCore;
     1477#ifndef NDEBUG
     1478                uint32_t uCrcBefore = 0;
     1479                uint32_t uCrcAfter = 0;
     1480                uint32_t iArg = pInstr->Core.cArgs;
     1481                while (iArg-- > 0)
     1482                    uCrcBefore = kmk_exec_debug_string_hash(uCrcBefore, pInstr->apszArgs[iArg]);
     1483#endif
     1484
     1485                pchDst = pInstr->Core.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->Core.pszFuncName);
     1486
     1487#ifndef NDEBUG
     1488                iArg = pInstr->Core.cArgs;
     1489                while (iArg-- > 0)
     1490                    uCrcAfter = kmk_exec_debug_string_hash(uCrcAfter, pInstr->apszArgs[iArg]);
     1491                assert(uCrcBefore == uCrcAfter);
     1492#endif
     1493
     1494                pInstrCore = pInstr->Core.pNext;
     1495                break;
     1496            }
     1497
     1498            case kKmkCcExpInstr_DynamicFunction:
     1499            {
     1500                PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)pInstrCore;
     1501                char           **papszArgsShadow = xmalloc( (pInstr->Core.cArgs * 2 + 1) * sizeof(char *));
     1502                char           **papszArgs = &papszArgsShadow[pInstr->Core.cArgs];
     1503                uint32_t         iArg;
     1504#ifndef NDEBUG
     1505                uint32_t         uCrcBefore = 0;
     1506                uint32_t         uCrcAfter = 0;
     1507#endif
     1508                iArg = pInstr->Core.cArgs;
     1509                papszArgs[iArg] = NULL;
     1510                while (iArg-- > 0)
     1511                {
     1512                    char *pszArg;
     1513                    if (pInstr->aArgs[iArg].fPlain)
     1514                        pszArg = (char *)pInstr->aArgs[iArg].u.Plain.pszArg;
     1515                    else
     1516                        pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.SubProg, NULL);
     1517                    papszArgsShadow[iArg] = pszArg;
     1518                    papszArgs[iArg]       = pszArg;
     1519#ifndef NDEBUG
     1520                    uCrcBefore = kmk_exec_debug_string_hash(uCrcBefore, pszArg);
     1521#endif
     1522                }
     1523
     1524                pchDst = pInstr->Core.pfnFunction(pchDst, papszArgs, pInstr->Core.pszFuncName);
     1525
     1526                iArg = pInstr->Core.cArgs;
     1527                while (iArg-- > 0)
     1528                {
     1529#ifndef NDEBUG
     1530                    assert(papszArgsShadow[iArg] == papszArgs[iArg]);
     1531                    uCrcAfter = kmk_exec_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]);
     1532#endif
     1533                    if (!pInstr->aArgs[iArg].fPlain)
     1534                        free(papszArgsShadow);
     1535                }
     1536                assert(uCrcBefore == uCrcAfter);
     1537                free(papszArgsShadow);
     1538
     1539                pInstrCore = pInstr->Core.pNext;
     1540                break;
     1541            }
     1542
     1543            case kKmkCcExpInstr_Jump:
     1544            {
     1545                PKMKCCEXPJUMP pInstr = (PKMKCCEXPJUMP)pInstrCore;
     1546                pInstrCore = pInstr->pNext;
     1547                break;
     1548            }
     1549
     1550            case kKmkCcExpInstr_Return:
     1551                return pchDst;
     1552
     1553            default:
     1554                fatal(NULL, _("Unknown string expansion opcode: %d (%#x)"),
     1555                      (int)pInstrCore->enmOpCode, (int)pInstrCore->enmOpCode);
     1556                return NULL;
     1557        }
     1558    }
     1559}
     1560
     1561
     1562/**
     1563 * Updates the string expansion statistics.
     1564 *
     1565 * @param   pStats              The statistics structure to update.
     1566 * @param   cchResult           The result lenght.
     1567 */
     1568void kmk_cc_exp_stats_update(PKMKCCEXPSTATS pStats, uint32_t cchResult)
     1569{
     1570    /*
     1571     * Keep statistics on output size.  The average is simplified and not an
     1572     * exact average for every expansion that has taken place.
     1573     */
     1574    if (cchResult > pStats->cchMax)
     1575    {
     1576        if (pStats->cchMax)
     1577            pStats->cchAvg = cchResult;
     1578        pStats->cchMax = cchResult;
     1579    }
     1580    pStats->cchAvg = (pStats->cchAvg * 7 + cchResult) / 8;
     1581}
     1582
     1583
     1584/**
     1585 * Execute a string expansion sub-program, outputting to a new heap buffer.
     1586 *
     1587 * @returns Pointer to the output buffer (hand to free when done).
     1588 * @param   pSubProg          The sub-program to execute.
     1589 * @param   pcchResult        Where to return the size of the result. Optional.
     1590 */
     1591static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcchResult)
     1592{
     1593    char           *pchOldVarBuf;
     1594    unsigned int    cbOldVarBuf;
     1595    char           *pchDst;
     1596    char           *pszResult;
     1597    uint32_t        cchResult;
     1598
     1599    /*
     1600     * Temporarily replace the variable buffer while executing the instruction
     1601     * stream for this sub program.
     1602     */
     1603    pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf,
     1604                                               pSubProg->Stats.cchAvg ? pSubProg->Stats.cchAvg + 32 : 256);
     1605
     1606    pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubProg->pFirstInstr, pchDst);
     1607
     1608    /* Ensure that it's terminated. */
     1609    pchDst = variable_buffer_output(pchDst, "\0", 1) - 1;
     1610
     1611    /* Grab the result buffer before restoring the previous one. */
     1612    pszResult = variable_buffer;
     1613    cchResult = (uint32_t)(pchDst - pszResult);
     1614    if (pcchResult)
     1615        *pcchResult = cchResult;
     1616    kmk_cc_exp_stats_update(&pSubProg->Stats, cchResult);
     1617
     1618    restore_variable_buffer(pchOldVarBuf, cbOldVarBuf);
     1619
     1620    return pszResult;
     1621}
     1622
     1623
     1624/**
     1625 * Execute a string expansion program, outputting to the current variable
     1626 * buffer.
     1627 *
     1628 * @returns New variable buffer position.
     1629 * @param   pProg               The program to execute.
     1630 * @param   pchDst              The current varaible buffer position.
     1631 */
     1632static char *kmk_exec_expand_prog_to_var_buf(PKMKCCEXPPROG pProg, char *pchDst)
     1633{
     1634    uint32_t cchResult;
     1635    uint32_t offStart = (uint32_t)(pchDst - variable_buffer);
     1636
     1637    if (pProg->Stats.cchAvg >= variable_buffer_length - offStart)
     1638        pchDst = ensure_variable_buffer_space(pchDst, offStart + pProg->Stats.cchAvg + 32);
     1639
     1640    pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pProg->pFirstInstr, pchDst);
     1641
     1642    cchResult = (uint32_t)(pchDst - variable_buffer);
     1643    assert(cchResult >= offStart);
     1644    cchResult -= offStart;
     1645    kmk_cc_exp_stats_update(&pProg->Stats, cchResult);
     1646
     1647    return pchDst;
     1648}
     1649
     1650
    11471651/**
    11481652 * Equivalent of eval_buffer, only it's using the evalprog of the variable.
     
    11671671{
    11681672    assert(pVar->expandprog);
    1169     assert(0);
    1170     return pchDst;
     1673    return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst);
    11711674}
    11721675
     
    11801683{
    11811684    assert(pVar->evalprog || pVar->expandprog);
     1685#if 0
     1686    if (pVar->evalprog)
     1687    {
     1688        kmk_cc_block_free_list(pVar->evalprog->pBlockTail);
     1689        pVar->evalprog = NULL;
     1690    }
     1691#endif
     1692    if (pVar->expandprog)
     1693    {
     1694        kmk_cc_block_free_list(pVar->expandprog->pBlockTail);
     1695        pVar->expandprog = NULL;
     1696    }
    11821697}
    11831698
     
    11911706{
    11921707    assert(pVar->evalprog || pVar->expandprog);
     1708#if 0
     1709    if (pVar->evalprog)
     1710    {
     1711        kmk_cc_block_free_list(pVar->evalprog->pBlockTail);
     1712        pVar->evalprog = NULL;
     1713    }
     1714#endif
     1715    if (pVar->expandprog)
     1716    {
     1717        kmk_cc_block_free_list(pVar->expandprog->pBlockTail);
     1718        pVar->expandprog = NULL;
     1719    }
    11931720}
    11941721
  • trunk/src/kmk/variable.c

    r2765 r2769  
    10351035  return 0;
    10361036}
     1037
     1038#ifdef CONFIG_WITH_STRCACHE2
     1039/* Alternative version of lookup_variable that takes a name that's already in
     1040   the variable string cache. */
     1041struct variable *
     1042lookup_variable_strcached (const char *name)
     1043{
     1044  struct variable *v;
     1045#if 1 /*FIX THIS - ndef KMK*/
     1046  const struct variable_set_list *setlist;
     1047  struct variable var_key;
     1048#endif /* KMK */
     1049  int is_parent = 0;
     1050
     1051#ifndef NDEBUG
     1052  strcache2_verify_entry (&variable_strcache, name);
     1053#endif
     1054
     1055#ifdef KMK
     1056  /* Check for kBuild-define- local variable accesses and handle these first. */
     1057  if (strcache2_get_len(&variable_strcache, name) > 3 && name[0] == '[')
     1058    {
     1059      v = lookup_kbuild_object_variable_accessor(name, strcache2_get_len(&variable_strcache, name));
     1060      if (v != VAR_NOT_KBUILD_ACCESSOR)
     1061        {
     1062          MAKE_STATS_2 (v->references++);
     1063          return v;
     1064        }
     1065    }
     1066#endif
     1067
     1068#if 1  /*FIX THIS - ndef KMK */
     1069
     1070  var_key.name = (char *) name;
     1071  var_key.length = strcache2_get_len(&variable_strcache, name);
     1072
     1073  for (setlist = current_variable_set_list;
     1074       setlist != 0; setlist = setlist->next)
     1075    {
     1076      const struct variable_set *set = setlist->set;
     1077
     1078      v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key);
     1079      if (v && (!is_parent || !v->private_var))
     1080        {
     1081# ifdef KMK
     1082          RESOLVE_ALIAS_VARIABLE(v);
     1083# endif
     1084          MAKE_STATS_2 (v->references++);
     1085           return v->special ? lookup_special_var (v) : v;
     1086        }
     1087
     1088      is_parent |= setlist->next_is_parent;
     1089    }
     1090
     1091#else  /* KMK - need for speed */
     1092
     1093  v = lookup_cached_variable (name);
     1094  assert (lookup_variable_for_assert(name, length) == v);
     1095#ifdef VMS
     1096  if (v)
     1097#endif
     1098    return v;
     1099#endif /* KMK - need for speed */
     1100#ifdef VMS
     1101# error "Port me (split out the relevant code from lookup_varaible and call it)"
     1102#endif
     1103  return 0;
     1104}
     1105#endif
     1106
    10371107
    10381108
  • trunk/src/kmk/variable.h

    r2768 r2769  
    244244#endif /* CONFIG_WITH_VALUE_LENGTH */
    245245void install_variable_buffer (char **bufp, unsigned int *lenp);
     246char *install_variable_buffer_with_hint (char **bufp, unsigned int *lenp, unsigned int size_hint);
    246247void restore_variable_buffer (char *buf, unsigned int len);
     248char *ensure_variable_buffer_space(char *ptr, unsigned int size);
    247249#ifdef CONFIG_WITH_VALUE_LENGTH
    248250void append_expanded_string_to_variable (struct variable *v, const char *value,
     
    325327                                   unsigned int *value_lenp);
    326328#define recursively_expand(v)   recursively_expand_for_file (v, NULL, NULL)
     329#endif
     330#ifdef CONFIG_WITH_COMPILER
     331char *reference_recursive_variable (char *o, struct variable *v);
    327332#endif
    328333
     
    369374struct variable *lookup_variable_in_set (const char *name, unsigned int length,
    370375                                         const struct variable_set *set);
     376#ifdef CONFIG_WITH_STRCACHE2
     377struct variable *lookup_variable_strcached (const char *name);
     378#endif
    371379
    372380#ifdef CONFIG_WITH_VALUE_LENGTH
Note: See TracChangeset for help on using the changeset viewer.

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