VirtualBox

Changeset 2799 in kBuild for trunk/src/kmk/kmk_cc_exec.c


Ignore:
Timestamp:
Sep 19, 2015 8:36:31 PM (10 years ago)
Author:
bird
Message:

Fixed glob.h inclusion issue causing stack corruption. Fixed alignment issue in the string expansion compiler. More makefile eval 'compiler' work.

File:
1 edited

Legend:

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

    r2797 r2799  
    6868# ifdef _MSC_VER
    6969#  define KMK_CC_ASSERT(a_TrueExpr)         do { if (!(a_TrueExpr)) __debugbreak(); } while (0)
     70# elif defined(__GNUC__) && (defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64))
     71#  define KMK_CC_ASSERT(a_TrueExpr)         do { if (!(a_TrueExpr)) __asm__ __volatile__("int3;nop"); } while (0)
    7072# else
    7173#  define KMK_CC_ASSERT(a_TrueExpr)         assert(a_TrueExpr)
     
    123125#define KMK_CC_IS_SPACE_CH(a_ch)                    isspace((unsigned char)(a_ch))
    124126
     127/** Aligns a size for the block allocator. */
     128#define KMK_CC_BLOCK_ALIGN_SIZE(a_cb)               ( ((a_cb) + (sizeof(void *) - 1U)) & ~(uint32_t)(sizeof(void *) - 1U) )
     129
    125130
    126131/** @defgroup grp_kmk_cc_evalprog Makefile Evaluation
    127132 * @{
    128133 */
     134#if 1
     135# define KMK_CC_EVAL_DPRINTF_UNPACK(...)            __VA_ARGS__
     136# define KMK_CC_EVAL_DPRINTF(a)                     fprintf(stderr, KMK_CC_EVAL_DPRINTF_UNPACK a)
     137#else
     138# define KMK_CC_EVAL_DPRINTF(a)                     do { } while (0)
     139#endif
     140
    129141/** @name KMK_CC_EVAL_QUALIFIER_XXX - Variable qualifiers.
    130142 * @{ */
     
    183195#define KMK_CC_EVAL_CH_PAREN_OR_SLASH               UINT16_C(256)
    184196#define KMK_CC_EVAL_IS_PAREN_OR_SLASH(a_ch)         (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_PAREN_OR_SLASH)
     197/** Used when parsing ifeq/ifneq (,) sequences.
     198 * Matches parentheses, comma and dollar (for non-plain string detection). */
     199#define KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR        UINT16_C(512)
     200#define KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(a_ch)  (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR)
    185201/** @} */
    186202
     
    767783/** Calculates the size of an KMKCCEVALIFEXPR structure for @a a_cchExpr long
    768784 * expression string (terminator is automatically added).  */
    769 #define KMKCCEVALIFEXPR_SIZE(a_cchExpr) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALIFEXPR, szExpr, (a_cchExpr) + 1)
     785#define KMKCCEVALIFEXPR_SIZE(a_cchExpr) KMK_CC_BLOCK_ALIGN_SIZE(KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALIFEXPR, szExpr, (a_cchExpr) + 1))
    770786
    771787/**
     
    10541070    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '}', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
    10551071    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
     1072
     1073    /* For parsing ifeq and if1of expressions. (GNU weirdly does not respect {} style function references.)  */
     1074    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '(', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR);
     1075    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ')', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR);
     1076    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ',', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR);
     1077    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '$', KMK_CC_EVAL_CH_PAREN_COMMA_OR_DOLLAR);
    10561078}
    10571079
     
    12741296{
    12751297    PKMKCCBLOCK pBlockTail = *ppBlockTail;
    1276     if (pBlockTail->offNext & (sizeof(void *) - 1))
    1277     {
    1278         pBlockTail->offNext = (pBlockTail->offNext + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
     1298    if (pBlockTail->offNext & (sizeof(void *) - 1U))
     1299    {
     1300        pBlockTail->offNext = KMK_CC_BLOCK_ALIGN_SIZE(pBlockTail->offNext);
    12791301        KMK_CC_ASSERT(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP));
    12801302    }
     
    13441366{
    13451367    PKMKCCBLOCK pBlockTail = *ppBlockTail;
    1346     uint32_t    cbLeft = pBlockTail->cbBlock - pBlockTail->offNext;
     1368    uint32_t    cbLeft     = pBlockTail->cbBlock - pBlockTail->offNext;
    13471369
    13481370    KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP));
     
    14121434
    14131435    pRet = (PKMKCCEXPCORE)(pNewBlock + 1);
     1436    KMK_CC_ASSERT(((size_t)pRet & (sizeof(void *) - 1)) == 0);
    14141437
    14151438    /* Emit jump. */
     
    14431466        PKMKCCEXPCORE pRet = (PKMKCCEXPCORE)((char *)pBlockTail + pBlockTail->offNext);
    14441467        pBlockTail->offNext += cb;
     1468        KMK_CC_ASSERT(((size_t)pRet & (sizeof(void *) - 1)) == 0);
    14451469        return pRet;
    14461470    }
     
    15191543
    15201544/**
    1521  * Allocate a string buffer for a makefile evaluation program.
    1522  *
    1523  * @returns Pointer to a makefile evaluation instruction core.
    1524  * @param   ppBlockTail         Pointer to the allocator tail pointer.
    1525  * @param   cb                  The number of bytes to allocate.
    1526  */
    1527 static char *kmk_cc_block_alloc_eval_string(PKMKCCBLOCK *ppBlockTail, uint32_t cb)
    1528 {
    1529     PKMKCCBLOCK pBlockTail = *ppBlockTail;
    1530     uint32_t    cbLeft = pBlockTail->cbBlock - pBlockTail->offNext;
    1531 
    1532     KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEVALJUMP));
    1533 
    1534     cb = (cb + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
    1535     if (cbLeft >= cb + sizeof(KMKCCEVALJUMP))
    1536     {
    1537         char *pszRet = (char *)pBlockTail + pBlockTail->offNext;
    1538         pBlockTail->offNext += cb;
    1539         return pszRet;
    1540     }
    1541     return (char *)kmk_cc_block_alloc_eval_grow(ppBlockTail, cb);
    1542 }
    1543 
    1544 
    1545 /**
    15461545 * Frees all memory used by an allocator.
    15471546 *
     
    15771576    PKMKCCEXPCORE pCore = kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pCore));
    15781577    pCore->enmOpCode = kKmkCcExpInstr_Return;
     1578    kmk_cc_block_realign(ppBlockTail);
    15791579}
    15801580
     
    30423042    pCompiler->iLine            = iLine;
    30433043
     3044    pCompiler->cStrCopySegsAllocated = 0;
     3045    pCompiler->paStrCopySegs    = NULL;
     3046
    30443047    pCompiler->cIfs             = 0;
    30453048
     
    31433146
    31443147
     3148/**
     3149 * Initializes a subprogam or plain operand structure.
     3150 *
     3151 * @param   pCompiler   The compiler state.
     3152 * @param   pOperand    The subprogram or plain structure to init.
     3153 * @param   pszString   The string.
     3154 * @param   cchString   The length of the string.
     3155 * @param   fPlain      Whether it's plain or not.  If not, we'll compile it.
     3156 */
     3157static void kmk_cc_eval_do_subprogram_or_plain(PKMKCCEVALCOMPILER pCompiler, PKMKCCEXPSUBPROGORPLAIN pOperand,
     3158                                               const char *pszString, size_t cchString, int fPlain)
     3159{
     3160    pOperand->fPlainIsInVarStrCache  = 0;
     3161    pOperand->bUser                  = 0;
     3162    pOperand->bUser2                 = 0;
     3163    pOperand->fSubprog               = fPlain;
     3164    if (fPlain)
     3165    {
     3166        pOperand->u.Plain.cch = cchString;
     3167        pOperand->u.Plain.psz = pszString;
     3168    }
     3169    else
     3170        kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszString, cchString, &pOperand->u.Subprog);
     3171}
     3172
     3173
     3174
    31453175/** @name KMK_CC_WORD_COMP_CONST_XXX - Optimal(/insane) constant work matching.
    31463176 * @{
    31473177 */
    3148 #if defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64) /* Unaligned access is reasonably cheap. */
     3178#if (defined(KBUILD_ARCH_X86) || defined(KBUILD_ARCH_AMD64)) /* Unaligned access is reasonably cheap. */ \
     3179 && !defined(GCC_ADDRESS_SANITIZER)
    31493180# define KMK_CC_WORD_COMP_CONST_2(a_pchLine, a_pszWord) \
    31503181        (   *(uint16_t const *)(a_pchLine)     == *(uint16_t const *)(a_pszWord) )
     
    38613892}
    38623893
     3894
     3895/**
     3896 * Allocate a byte buffer and ocpy the prepared string segments into it.
     3897 *
     3898 * The caller must call kmk_cc_block_realign!
     3899 *
     3900 * @returns Pointer to the duplicated string.
     3901 * @param   pCompiler       The compiler instance data.
     3902 * @param   cchPrepped      The length of the prepped string segments.
     3903 */
     3904static char *kmk_cc_eval_strdup_prepped(PKMKCCEVALCOMPILER pCompiler, size_t cchPrepped)
     3905{
     3906    char *pszCopy = kmk_cc_block_byte_alloc(pCompiler->ppBlockTail, cchPrepped + 1);
     3907    kmk_cc_eval_strcpyv(pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchPrepped);
     3908    return pszCopy;
     3909}
     3910
     3911
     3912/**
     3913 * Strip trailing spaces from prepped copy
     3914 *
     3915 * @param   paSegs          The segments to strip trailing chars from.
     3916 * @param   pcSegs          The number of segments (in/out).
     3917 * @param   pcchDstPrepped  The total number of chars prepped (in/out).
     3918 */
     3919static void kmk_cc_eval_strip_right_v(PKMKCCEVALSTRCPYSEG paSegs, unsigned *pcSegs, size_t *pcchDstPrepped)
     3920{
     3921    /*
     3922     * Work our way thru the segments, from the end obviously.
     3923     */
     3924    size_t   cchDstPrepped = *pcchDstPrepped;
     3925    unsigned cSegs         = *pcSegs;
     3926    while (cSegs > 0)
     3927    {
     3928        unsigned    iSeg   = cSegs - 1;
     3929        const char *pszSrc = paSegs[iSeg].pchSrc;
     3930        size_t      cchSrc = paSegs[iSeg].cchSrcAndPrependSpace >= 0
     3931                           ? paSegs[iSeg].cchSrcAndPrependSpace : -paSegs[iSeg].cchSrcAndPrependSpace;
     3932        if (cchSrc)
     3933        {
     3934            /*
     3935             * Check for trailing spaces.
     3936             */
     3937            size_t cchSrcOrg;
     3938            if (!KMK_CC_EVAL_IS_SPACE(pszSrc[cchSrc - 1]))
     3939            {
     3940                /* Special case: No trailing spaces at all. No need to update
     3941                                 input/output variables. */
     3942                if (cSegs == *pcSegs)
     3943                    return;
     3944                break;
     3945            }
     3946
     3947            /* Skip the rest of the trailing spaces. */
     3948            cchSrcOrg = cchSrc;
     3949            do
     3950                cchSrc--;
     3951            while (cchSrc > 0 && KMK_CC_EVAL_IS_SPACE(pszSrc[cchSrc - 1]));
     3952
     3953            if (cchSrc > 0)
     3954            {
     3955                /*
     3956                 * There are non-space chars in this segment. So, update the
     3957                 * segment and total char count and we're done.
     3958                 */
     3959                cchDstPrepped -= cchSrcOrg - cchSrc;
     3960                if (paSegs[iSeg].cchSrcAndPrependSpace < 0)
     3961                    paSegs[iSeg].cchSrcAndPrependSpace = -(ssize_t)cchSrc;
     3962                else
     3963                    paSegs[iSeg].cchSrcAndPrependSpace = cchSrc;
     3964                break;
     3965            }
     3966
     3967            /*
     3968             * Skip the whole segment.
     3969             */
     3970            cchDstPrepped -= cchSrcOrg + (paSegs[iSeg].cchSrcAndPrependSpace < 0);
     3971        }
     3972        cSegs--;
     3973    }
     3974    *pcchDstPrepped = cchDstPrepped;
     3975    *pcSegs         = cSegs;
     3976}
     3977
    38633978/**
    38643979 * Helper for ensuring that we've got sufficient number of string copy segments.
     
    38703985        else \
    38713986        { \
    3872             unsigned cSegs = ((a_cRequiredSegs) + 3 /*15*/) & ~(unsigned)3/*15*/; \
     3987            unsigned cEnsureSegs = ((a_cRequiredSegs) + 3 /*15*/) & ~(unsigned)3/*15*/; \
    38733988            KMK_CC_ASSERT((a_cRequiredSegs) < 0x8000); \
    3874             (a_pCompiler)->paStrCopySegs = (PKMKCCEVALSTRCPYSEG)xmalloc(cSegs * sizeof((a_pCompiler)->paStrCopySegs)[0]); \
     3989            (a_pCompiler)->paStrCopySegs = (PKMKCCEVALSTRCPYSEG)xmalloc(cEnsureSegs * sizeof((a_pCompiler)->paStrCopySegs)[0]); \
    38753990        } \
    38763991    } while (0)
     
    42074322 *          kmk_cc_eval_try_handle_keyword).
    42084323 * @param   pCompiler   The compiler state.
    4209  * @param   pchWord     First char after 'define'.
     4324 * @param   pchWord     First char after 'if'.
    42104325 * @param   cchLeft     The number of chars left to parse on this line.
    42114326 * @param   fInElse     Set if this is an 'else if' (rather than just 'if').
     
    42384353 *          kmk_cc_eval_try_handle_keyword).
    42394354 * @param   pCompiler       The compiler state.
    4240  * @param   pchWord         First char after 'define'.
     4355 * @param   pchWord         First char after 'if[n]def'.
    42414356 * @param   cchLeft         The number of chars left to parse on this line.
    42424357 * @param   fInElse         Set if this is an 'else if' (rather than just 'if').
     
    42784393
    42794394            /** @todo Make the subprogram embed necessary strings. */
    4280             pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, cchCopy + 1);
    4281             kmk_cc_eval_strcpyv(pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchCopy);
     4395            pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, cchCopy);
     4396            kmk_cc_block_realign(pCompiler->ppBlockTail);
    42824397
    42834398            pInstr->IfCore.Core.enmOpCode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_dynamic : kKmkCcEvalInstr_ifndef_dynamic;
     
    43014416
    43024417
     4418/**
     4419 * Deals with 'ifeq (a,b)', 'ifeq "a" "b"', 'ifneq (a,b)', 'ifneq "a" "b"',
     4420 * 'else ifeq (a,b)', 'else ifeq "a" "b"', 'else ifneq (a,b)' and
     4421 * 'else ifneq "a" "b"' statements.
     4422 *
     4423 * @returns 1 to indicate we've handled a keyword (see
     4424 *          kmk_cc_eval_try_handle_keyword).
     4425 * @param   pCompiler       The compiler state.
     4426 * @param   pchWord         First char after 'if[n]eq'.
     4427 * @param   cchLeft         The number of chars left to parse on this line.
     4428 * @param   fInElse         Set if this is an 'else if' (rather than just 'if').
     4429 * @param   fPositiveStmt   Set if 'ifeq', clear if 'ifneq'.
     4430 */
    43034431static int kmk_cc_eval_do_ifeq(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt)
    43044432{
     
    43144442         */
    43154443        const char * const  pchEnd = &pchWord[cchLeft];
    4316         PKMKCCEVALIFEQ      pInstr;
     4444        PKMKCCEVALIFEQ      pInstr = (PKMKCCEVALIFEQ)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
    43174445
    43184446        struct
     
    43264454        if (ch == '(')
    43274455        {
    4328 //            unsigned cCounts;
    4329 
    4330 
     4456            int      cCounts;
     4457            size_t   off;
     4458
     4459            /*
     4460             * The left side ends with a comma.  We respect parentheses, but
     4461             * not curly brackets.
     4462             */
    43314463
    43324464            /* Skip the parenthesis. */
     
    43344466            cchLeft--;
    43354467
    4336 /** @todo continue here.   */
     4468            /* Find the comma, checking for non-plainness. */
     4469            cCounts = 0;
     4470            Left.fPlain = 1;
     4471            for (off = 0; off < cchLeft; off++)
     4472            {
     4473                ch = pchWord[off];
     4474                if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch))
     4475                { /* likely */ }
     4476                else if (ch == '$')
     4477                    Left.fPlain = 0;
     4478                else if (ch == '(')
     4479                    cCounts++;
     4480                else if (ch == ')')
     4481                    cCounts--; /** @todo warn if it goes negative. */
     4482                else if (ch == ',' && cCounts == 0)
     4483                    break;
     4484                else
     4485                    KMK_CC_ASSERT(cCounts > 0);
     4486            }
     4487            if (ch == ',' && cCounts == 0) { /* likely */ }
     4488            else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ',' before end of line");
     4489
     4490            /* Copy out the string. */
     4491            Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off);
     4492            kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Left.cchCopy);
     4493            Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy);
     4494
     4495            /* Skip past the comma and any following spaces. */
     4496            pchWord += off + 1;
     4497            cchLeft -= off + 1;
     4498            if (   cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */
     4499                && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft))
     4500                KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4501
     4502            /*
     4503             * Ditto for the right side, only it ends with a closing parenthesis.
     4504             */
     4505            cCounts = 1;
     4506            Right.fPlain = 1;
     4507            for (off = 0; off < cchLeft; off++)
     4508            {
     4509                ch = pchWord[off];
     4510                if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch))
     4511                { /* likely */ }
     4512                else if (ch == '$')
     4513                    Right.fPlain = 0;
     4514                else if (ch == '(')
     4515                    cCounts++;
     4516                else if (ch == ')')
     4517                {
     4518                    if (--cCounts == 0)
     4519                        break;
     4520                }
     4521                else
     4522                    KMK_CC_ASSERT(cCounts > 0 || ch == ',');
     4523            }
     4524            if (ch == ')' && cCounts == 0) { /* likely */ }
     4525            else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ')' before end of line");
     4526
     4527            /* Copy out the string. */
     4528            Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off);
     4529            kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Right.cchCopy);
     4530            Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy);
     4531
     4532            /* Skip past the parenthesis. */
     4533            pchWord += off + 1;
     4534            cchLeft -= off + 1;
    43374535        }
    43384536        else if (ch == '"' || ch == '\'')
     
    43534551
    43544552            Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord);
    4355             Left.pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, Left.cchCopy + 1);
    4356             kmk_cc_eval_strcpyv(Left.pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, Left.cchCopy);
     4553            Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy);
    43574554            Left.fPlain  = memchr(Left.pszCopy, '$', Left.cchCopy) == NULL;
    43584555
     
    43824579
    43834580                Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord);
    4384                 Right.pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, Right.cchCopy + 1);
    4385                 kmk_cc_eval_strcpyv(Left.pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, Right.cchCopy);
     4581                Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy);
    43864582                Right.fPlain  = memchr(Right.pszCopy, '$', Right.cchCopy) == NULL;
    43874583
     
    43974593            kmk_cc_eval_fatal(pCompiler, pchWord, "Expected parentheses or quoted string after 'if%seq'",
    43984594                              fPositiveStmt ? "" : "n");
     4595        kmk_cc_block_realign(pCompiler->ppBlockTail);
    43994596
    44004597        /*
    4401          *
     4598         * Initialize the instruction.
    44024599         */
    4403         pInstr = (PKMKCCEVALIFEQ)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
    4404 
     4600        pInstr->IfCore.Core.enmOpCode = fPositiveStmt ? kKmkCcEvalInstr_ifeq : kKmkCcEvalInstr_ifneq;
     4601        pInstr->IfCore.Core.iLine     = pCompiler->iLine;
     4602        kmk_cc_eval_do_subprogram_or_plain(pCompiler, &pInstr->Left, Left.pszCopy, Left.cchCopy, Left.fPlain);
     4603        kmk_cc_eval_do_subprogram_or_plain(pCompiler, &pInstr->Right, Right.pszCopy, Right.cchCopy, Right.fPlain);
     4604        kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse);
    44054605
    44064606        /*
     
    44174617
    44184618
     4619/**
     4620 * Deals with 'if1of (set-a,set-b)', 'ifn1of (set-a,set-b)',
     4621 * 'else if1of (set-a,set-b)' and 'else ifn1of (set-a,set-b)' statements.
     4622 *
     4623 * @returns 1 to indicate we've handled a keyword (see
     4624 *          kmk_cc_eval_try_handle_keyword).
     4625 * @param   pCompiler       The compiler state.
     4626 * @param   pchWord         First char after 'if[n]1of'.
     4627 * @param   cchLeft         The number of chars left to parse on this line.
     4628 * @param   fInElse         Set if this is an 'else if' (rather than just 'if').
     4629 * @param   fPositiveStmt   Set if 'if1of', clear if 'ifn1of'.
     4630 */
    44194631static int kmk_cc_eval_do_if1of(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt)
    44204632{
     4633    KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4634    if (cchLeft)
     4635    {
     4636        /*
     4637         * This code is (currently) very similar to kmk_cc_eval_do_ifeq.
     4638         * However, we may want to add hashing optimizations of plain text,
     4639         * and we don't want to support the quoted form as it is not necessary
     4640         * and may interfere with support for quoted words later on.
     4641         */
     4642        PKMKCCEVALIF1OF     pInstr = (PKMKCCEVALIF1OF)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     4643
     4644        struct
     4645        {
     4646            char           *pszCopy;
     4647            size_t          cchCopy;
     4648            int             fPlain;
     4649        } Left, Right;
     4650
     4651        char ch = *pchWord;
     4652        if (ch == '(')
     4653        {
     4654            int      cCounts;
     4655            size_t   off;
     4656
     4657            /*
     4658             * The left side ends with a comma.  We respect parentheses, but
     4659             * not curly brackets.
     4660             */
     4661
     4662            /* Skip the parenthesis. */
     4663            pchWord++;
     4664            cchLeft--;
     4665
     4666            /* Find the comma, checking for non-plainness. */
     4667            cCounts = 0;
     4668            Left.fPlain = 1;
     4669            for (off = 0; off < cchLeft; off++)
     4670            {
     4671                ch = pchWord[off];
     4672                if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch))
     4673                { /* likely */ }
     4674                else if (ch == '$')
     4675                    Left.fPlain = 0;
     4676                else if (ch == '(')
     4677                    cCounts++;
     4678                else if (ch == ')')
     4679                    cCounts--; /** @todo warn if it goes negative. */
     4680                else if (ch == ',' && cCounts == 0)
     4681                    break;
     4682                else
     4683                    KMK_CC_ASSERT(cCounts > 0);
     4684            }
     4685            if (ch == ',' && cCounts == 0) { /* likely */ }
     4686            else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ',' before end of line");
     4687
     4688            /* Copy out the string. */
     4689            Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off);
     4690            kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Left.cchCopy);
     4691            Left.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Left.cchCopy);
     4692
     4693            /* Skip past the comma and any following spaces. */
     4694            pchWord += off + 1;
     4695            cchLeft -= off + 1;
     4696            if (   cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */
     4697                && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft))
     4698                KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4699
     4700            /*
     4701             * Ditto for the right side, only it ends with a closing parenthesis.
     4702             */
     4703            cCounts = 1;
     4704            Right.fPlain = 1;
     4705            for (off = 0; off < cchLeft; off++)
     4706            {
     4707                ch = pchWord[off];
     4708                if (!KMK_CC_EVAL_IS_PAREN_COMMA_OR_DOLLAR(ch))
     4709                { /* likely */ }
     4710                else if (ch == '$')
     4711                    Right.fPlain = 0;
     4712                else if (ch == '(')
     4713                    cCounts++;
     4714                else if (ch == ')')
     4715                {
     4716                    if (--cCounts == 0)
     4717                        break;
     4718                }
     4719                else
     4720                    KMK_CC_ASSERT(cCounts > 0 || ch == ',');
     4721            }
     4722            if (ch == ')' && cCounts == 0) { /* likely */ }
     4723            else kmk_cc_eval_fatal(pCompiler, &pchWord[off], "Expected ')' before end of line");
     4724
     4725            /* Copy out the string. */
     4726            Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, off);
     4727            kmk_cc_eval_strip_right_v(pCompiler->paStrCopySegs, &pCompiler->cStrCopySegs, &Right.cchCopy);
     4728            Right.pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, Right.cchCopy);
     4729
     4730            /* Skip past the parenthesis. */
     4731            pchWord += off + 1;
     4732            cchLeft -= off + 1;
     4733        }
     4734        else
     4735            kmk_cc_eval_fatal(pCompiler, pchWord, "Expected parentheses after 'if%s1of'", fPositiveStmt ? "" : "n");
     4736        kmk_cc_block_realign(pCompiler->ppBlockTail);
     4737
     4738        /*
     4739         * Initialize the instruction.
     4740         */
     4741        pInstr->IfCore.Core.enmOpCode = fPositiveStmt ? kKmkCcEvalInstr_if1of : kKmkCcEvalInstr_ifn1of;
     4742        pInstr->IfCore.Core.iLine     = pCompiler->iLine;
     4743        kmk_cc_eval_do_subprogram_or_plain(pCompiler, &pInstr->Left, Left.pszCopy, Left.cchCopy, Left.fPlain);
     4744        kmk_cc_eval_do_subprogram_or_plain(pCompiler, &pInstr->Right, Right.pszCopy, Right.cchCopy, Right.fPlain);
     4745        kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse);
     4746
     4747        /*
     4748         * Make sure there is nothing following the variable name.
     4749         */
     4750        KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4751        if (cchLeft)
     4752            kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'if%s1of' variable name", fPositiveStmt ? "" : "n");
     4753    }
     4754    else
     4755        kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive");
    44214756    return 1;
    44224757}
     
    46204955 * @param   fQualifiers The qualifiers.
    46214956 */
    4622 static int kmk_cc_eval_do_var_define(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft,
    4623                                               unsigned fQualifiers)
     4957static int kmk_cc_eval_do_var_define(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers)
    46244958{
    46254959
     
    46294963
    46304964static int kmk_cc_eval_try_handle_assignment(PKMKCCEVALCOMPILER pCompiler, const char *pchTmp,
    4631                                                       const char *pchWord, size_t cchLeft, unsigned fQualifiers)
     4965                                             const char *pchWord, size_t cchLeft, unsigned fQualifiers)
    46324966{
    46334967    return 0;
     
    48865220    KMKCCEVALCOMPILER   Compiler;
    48875221    kmk_cc_eval_init_compiler(&Compiler, pEvalProg, iLine, pszContent, cchContent);
     5222    KMK_CC_EVAL_DPRINTF(("\nkmk_cc_eval_compile_worker - begin (%s/%s/%d)\n", pEvalProg->pszFilename, pEvalProg->pszVarName, iLine));
    48885223
    48895224    {
     
    49275262                    if (&pszContent[offNext] == pchTmp)
    49285263                    {
    4929 fprintf(stderr, "#%03u: <empty>\n", Compiler.iLine);
     5264                        KMK_CC_EVAL_DPRINTF(("#%03u: <empty>\n", Compiler.iLine));
    49305265                        Compiler.iLine++;
    49315266                        off = offNext += cchEolSeq;
     
    49345269                    if (pszContent[offNext] == '#')
    49355270                    {
    4936 fprintf(stderr, "#%03u: <comment>\n", Compiler.iLine);
     5271                        KMK_CC_EVAL_DPRINTF(("#%03u: <comment>\n", Compiler.iLine));
    49375272                        Compiler.iLine++;
    49385273                        offNext = pchTmp - pszContent;
     
    50575392            KMK_CC_ASSERT(offFirstWord  >= off);
    50585393            KMK_CC_ASSERT(pszContent[offFirstWord] != ' ' && pszContent[offFirstWord] != '\t');
    5059 {
    5060 char chSaved = ((char *)pszContent)[off+cchLine] = '\0';
    5061 fprintf(stderr, "#%03u: %s\n", Compiler.iLine, &pszContent[off]);
    5062 ((char *)pszContent)[off+cchLine] = chSaved;
    5063 }
     5394
     5395            KMK_CC_EVAL_DPRINTF(("#%03u: %*.*s\n", Compiler.iLine, (int)cchLine, (int)cchLine, &pszContent[off]));
    50645396
    50655397            /*
     
    51295461
    51305462    kmk_cc_eval_delete_compiler(&Compiler);
     5463    KMK_CC_EVAL_DPRINTF(("kmk_cc_eval_compile_worker - done (%s/%s)\n\n", pEvalProg->pszFilename, pEvalProg->pszVarName));
    51315464    return 0;
    51325465}
    51335466
    51345467
    5135 /*#define KMK_CC_EVAL_ENABLE*/
    51365468
    51375469static PKMKCCEVALPROG kmk_cc_eval_compile(const char *pszContent, size_t cchContent,
     
    51585490         * Do the actual compiling.
    51595491         */
    5160 #ifdef KMK_CC_EVAL_ENABLE
     5492#ifdef CONFIG_WITH_EVAL_COMPILER
    51615493        if (kmk_cc_eval_compile_worker(pEvalProg, pszContent, cchContent, iLine) == 0)
    51625494#else
     
    51985530    if (!pEvalProg)
    51995531    {
    5200 #ifdef KMK_CC_EVAL_ENABLE
     5532#ifdef CONFIG_WITH_EVAL_COMPILER
    52015533        pEvalProg = kmk_cc_eval_compile(pVar->value, pVar->value_length,
    52025534                                        pVar->fileinfo.filenm, pVar->fileinfo.lineno, pVar->name);
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