VirtualBox

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


Ignore:
Timestamp:
Sep 14, 2015 12:41:11 AM (10 years ago)
Author:
bird
Message:

kmk_cc_exec.c: Some more code, lots of hacking left to do.

File:
1 edited

Legend:

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

    r2789 r2790  
    151151 * @{ */
    152152/** Normal character, nothing special. */
    153 #define KMK_CC_EVAL_CH_NORMAL                       UINT8_C(0)
     153#define KMK_CC_EVAL_CH_NORMAL                       UINT16_C(0)
    154154/** Blank character. */
    155 #define KMK_CC_EVAL_CH_BLANK                        UINT8_C(1)
     155#define KMK_CC_EVAL_CH_BLANK                        UINT16_C(1)
    156156#define KMK_CC_EVAL_IS_BLANK(a_ch)                  (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_BLANK)
    157157/** Space character. */
    158 #define KMK_CC_EVAL_CH_SPACE                        UINT8_C(2)
     158#define KMK_CC_EVAL_CH_SPACE                        UINT16_C(2)
    159159#define KMK_CC_EVAL_IS_SPACE(a_ch)                  (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE)
    160160/** Space character or potential EOL escape backslash. */
    161 #define KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH           UINT8_C(4)
     161#define KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH           UINT16_C(4)
    162162#define KMK_CC_EVAL_IS_SPACE_OR_BACKSLASH(a_ch)     (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH)
     163/** Anything we need to take notice of when parsing something could be a
     164 * variable name or a recipe.
     165 * All space characters, backslash (EOL escape), variable expansion dollar,
     166 * variable assignment operator chars, recipe colon and recipe percent. */
     167#define KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE       UINT16_C(8)
     168#define KMK_CC_EVAL_IS_SPACE_OR_VAR_OR_RECIPE(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE)
    163169/** Possible EOL character. */
    164 #define KMK_CC_EVAL_CH_EOL_CANDIDATE                UINT8_C(8)
     170#define KMK_CC_EVAL_CH_EOL_CANDIDATE                UINT16_C(16)
    165171#define KMK_CC_EVAL_IS_EOL_CANDIDATE(a_ch)          (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_EOL_CANDIDATE)
    166172/** First character in a keyword. */
    167 #define KMK_CC_EVAL_CH_1ST_IN_KEYWORD               UINT8_C(16)
     173#define KMK_CC_EVAL_CH_1ST_IN_KEYWORD               UINT16_C(32)
    168174#define KMK_CC_EVAL_IS_1ST_IN_KEYWORD(a_ch)         (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_1ST_IN_KEYWORD)
    169175/** Second character in a keyword. */
    170 #define KMK_CC_EVAL_CH_2ND_IN_KEYWORD               UINT8_C(32)
     176#define KMK_CC_EVAL_CH_2ND_IN_KEYWORD               UINT16_C(64)
    171177#define KMK_CC_EVAL_IS_2ND_IN_KEYWORD(a_ch)         (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_2ND_IN_KEYWORD)
    172178/** First character in a variable qualifier keyword or 'define'. */
    173 #define KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD      UINT8_C(64)
     179#define KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD      UINT16_C(128)
    174180#define KMK_CC_EVAL_IS_1ST_IN_VARIABLE_KEYWORD(a_ch) (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD)
    175 /** Assignment punctuation character. */
    176 #define KMK_CC_EVAL_CH_ASSIGNMENT                   UINT8_C(128)
    177 #define KMK_CC_EVAL_IS_ASSIGNMENT(a_ch)             (KMK_CC_EVAL_BM_GET(g_abEvalCcChars, a_ch) & KMK_CC_EVAL_CH_ASSIGNMENT)
     181/** Used when parsing variable names, looking for the end of a nested
     182 *  variable reference.  Matches parentheses and backslash (escaped eol). */
     183#define KMK_CC_EVAL_CH_PAREN_OR_SLASH               UINT16_C(256)
     184#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)
    178185/** @} */
    179186
     
    708715    KMKCCEVALIFCORE         IfCore;
    709716    /** The subprogram that will give us the variable name. */
    710     KMKCCEXPSUBPROG         NameSubProg;
     717    KMKCCEXPSUBPROG         NameSubprog;
    711718} KMKCCEVALIFDEFDYNAMIC;
    712719typedef KMKCCEVALIFDEFDYNAMIC *PKMKCCEVALIFDEFDYNAMIC;
     
    945952#endif
    946953
    947 /** Bitmap taking 'unsigned char' index.
     954/** Generic character classification, taking an 'unsigned char' index.
    948955 * ASSUMES unsigned char is 8-bits. */
    949 static uint8_t  g_abEvalCcChars[256];
     956static uint16_t g_abEvalCcChars[256];
     957
    950958
    951959/**
     
    984992*   Internal Functions                                                                                                           *
    985993*********************************************************************************************************************************/
    986 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg);
    987 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcch);
     994static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubprog);
     995static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubprog, uint32_t *pcch);
    988996
    989997
     
    10051013
    10061014    /* space chars and zero terminator. */
    1007     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ' ',  KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH);
    1008     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\t', KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH);
    1009     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\n', KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_EOL_CANDIDATE);
    1010     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\v', KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH);
    1011     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\f', KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH);
    1012     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\r', KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_EOL_CANDIDATE);
    1013     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH);
     1015#define MY_SPACE_BITS KMK_CC_EVAL_CH_SPACE | KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE
     1016    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ' ',  MY_SPACE_BITS);
     1017    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\t', MY_SPACE_BITS);
     1018    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\n', MY_SPACE_BITS | KMK_CC_EVAL_CH_EOL_CANDIDATE);
     1019    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\v', MY_SPACE_BITS);
     1020    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\f', MY_SPACE_BITS);
     1021    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\r', MY_SPACE_BITS | KMK_CC_EVAL_CH_EOL_CANDIDATE);
     1022    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_SPACE_OR_BACKSLASH | KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1023#undef MY_SPACE_BITS
    10141024
    10151025    /* keywords  */
     
    10301040    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, 'u', KMK_CC_EVAL_CH_1ST_IN_VARIABLE_KEYWORD); /* undefine */
    10311041
    1032     /* Assignment punctuation. */
    1033     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '=', KMK_CC_EVAL_CH_ASSIGNMENT);
    1034     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ':', KMK_CC_EVAL_CH_ASSIGNMENT);
    1035     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '<', KMK_CC_EVAL_CH_ASSIGNMENT);
    1036     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '?', KMK_CC_EVAL_CH_ASSIGNMENT);
    1037     KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '+', KMK_CC_EVAL_CH_ASSIGNMENT);
     1042    /* Assignment punctuation and recipe stuff. */
     1043    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '=', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1044    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ':', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1045    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '<', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1046    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '?', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1047    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '+', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE);
     1048    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '%', KMK_CC_EVAL_CH_SPACE_OR_VAR_OR_RECIPE); /* uncertain... */
     1049
     1050    /* For locating the end of variable expansion.  */
     1051    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '(', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
     1052    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, ')', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
     1053    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '{', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
     1054    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '}', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
     1055    KMK_CC_EVAL_BM_OR(g_abEvalCcChars, '\\', KMK_CC_EVAL_CH_PAREN_OR_SLASH);
    10381056}
    10391057
     
    14971515    }
    14981516    return kmk_cc_block_alloc_eval_grow(ppBlockTail, cb);
     1517}
     1518
     1519
     1520/**
     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 */
     1527static 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);
    14991542}
    15001543
     
    22032246 * @param   cchStr              The length of the string to compile. Expected to
    22042247 *                              be at least on char long.
    2205  * @param   pSubProg            The subprogram structure to initialize.
    2206  */
    2207 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg)
     2248 * @param   pSubprog            The subprogram structure to initialize.
     2249 */
     2250static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubprog)
    22082251{
    22092252    KMK_CC_ASSERT(cchStr > 0);
    2210     pSubProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
    2211     kmk_cc_exp_stats_init(&pSubProg->Stats);
     2253    pSubprog->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
     2254    kmk_cc_exp_stats_init(&pSubprog->Stats);
    22122255    return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr);
    22132256}
     
    26352678 *
    26362679 * @returns Pointer to the output buffer (hand to free when done).
    2637  * @param   pSubProg          The subprogram to execute.
     2680 * @param   pSubprog          The subprogram to execute.
    26382681 * @param   pcchResult        Where to return the size of the result. Optional.
    26392682 */
    2640 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcchResult)
     2683static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubprog, uint32_t *pcchResult)
    26412684{
    26422685    char           *pchOldVarBuf;
     
    26512694     */
    26522695    pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf,
    2653                                                pSubProg->Stats.cchAvg ? pSubProg->Stats.cchAvg + 32 : 256);
    2654 
    2655     pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubProg->pFirstInstr, pchDst);
     2696                                               pSubprog->Stats.cchAvg ? pSubprog->Stats.cchAvg + 32 : 256);
     2697
     2698    pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubprog->pFirstInstr, pchDst);
    26562699
    26572700    /* Ensure that it's terminated. */
     
    26632706    if (pcchResult)
    26642707        *pcchResult = cchResult;
    2665     kmk_cc_exp_stats_update(&pSubProg->Stats, cchResult);
     2708    kmk_cc_exp_stats_update(&pSubprog->Stats, cchResult);
    26662709
    26672710    variable_buffer = pchOldVarBuf;
     
    28742917/**
    28752918 * Escaped end-of-line sequence in the current line.
    2876  *
    2877  * This is initially noting down the start of the escape sequence and the EOL
    2878  * marker.  But after kmk_cc_eval_prep_command_line or
    2879  * kmk_cc_eval_prep_normal_line it will change into copy instructions.  The
    2880  * offEsc is the end position of the current line, while offEol is the start of
    2881  * the next line.  If the next line doesn't contain anything to copy, offEsc
    2882  * will contain the same value as offEol on the previous.
    28832919 */
    28842920typedef struct KMKCCEVALESCEOL
    28852921{
    2886     /** Offset at which the EOL escape sequence starts for a non-command line.
    2887      * After prepping the line, this will be moved back to indicate the end of
    2888      * the copy sequence for that line. */
     2922    /** Offset at which the EOL escape sequence starts for a non-command line. */
    28892923    size_t              offEsc;
    2890     /** Offset of the newline sequence.
    2891      * After prepping the line, this will indicate where to start copying on the
    2892      * following line.  This may be the same as the offEsc in the next entry. */
     2924    /** Offset of the newline sequence. */
    28932925    size_t              offEol;
    28942926} KMKCCEVALESCEOL;
    28952927typedef KMKCCEVALESCEOL *PKMKCCEVALESCEOL;
     2928
     2929
     2930/**
     2931 * String copy segment.
     2932 */
     2933typedef struct KMKCCEVALSTRCPYSEG
     2934{
     2935    /** The start. */
     2936    const char         *pchSrc;
     2937    /** The number of chars to copy and whether to prepend space.
     2938     * Negative values indicates that we should prepend a space. */
     2939    ssize_t             cchSrcAndPrependSpace;
     2940} KMKCCEVALSTRCPYSEG;
     2941typedef KMKCCEVALSTRCPYSEG *PKMKCCEVALSTRCPYSEG;
     2942typedef KMKCCEVALSTRCPYSEG const *PCKMKCCEVALSTRCPYSEG;
    28962943
    28972944
     
    29202967    /** Length of the current line, sans the final EOL and comments. */
    29212968    size_t              cchLine;
     2969    /** Length of the current line, sans the final EOL but with comments. */
     2970    size_t              cchLineWithComments;
    29222971
    29232972    /** The first char in an EOL sequence.
     
    29322981    /** The minimum length of an esacped EOL sequence (cchEolSeq + 1). */
    29332982    size_t              cchEscEolSeq;
     2983
     2984    /** String copy segments. */
     2985    PKMKCCEVALSTRCPYSEG paStrCopySegs;
     2986    /** The number of segments that has been prepared. */
     2987    unsigned            cStrCopySegs;
     2988    /** The number of segments we've allocated. */
     2989    unsigned            cStrCopySegsAllocated;
    29342990    /** @} */
    29352991
     
    30683124}
    30693125
     3126
     3127/**
     3128 * Compiles a string expansion subprogram.
     3129 *
     3130 * @param   pCompiler   The compiler state.
     3131 * @param   pszExpr     The expression to compile.
     3132 * @param   cchExpr     The length of the expression.
     3133 * @param   pSubprog    The subprogram to compile.
     3134 */
     3135static void kmk_cc_eval_compile_string_exp_subprog(PKMKCCEVALCOMPILER pCompiler, const char *pszExpr, size_t cchExpr,
     3136                                                   PKMKCCEXPSUBPROG pSubprog)
     3137{
     3138    int rc = kmk_cc_exp_compile_subprog(pCompiler->ppBlockTail, pszExpr, cchExpr, pSubprog);
     3139    if (rc == 0)
     3140        return;
     3141    kmk_cc_eval_fatal(pCompiler, NULL, "String expansion compile error");
     3142}
    30703143
    30713144
     
    35003573
    35013574/**
     3575 * Skips to the end of a variable name.
     3576 *
     3577 * This may advance pCompiler->iEscEol.
     3578 *
     3579 * @returns Pointer to the first char after the variable name.
     3580 * @param   pCompiler   The compiler state.
     3581 * @param   pchWord     The current position. Must be at the start of the
     3582 *                      variable name.
     3583 * @param   cchLeft     The number of chars left to parse in the current line.
     3584 * @param   pcchLeft    The to store the updated count of characters left to
     3585 *                      parse.
     3586 * @param   pfPlain     Where to store the plain variable name indicator.
     3587 *                      Returns 0 if plain, and 1 if there are variable
     3588 *                      references in it.
     3589 */
     3590static const char *kmk_cc_eval_skip_var_name(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft,
     3591                                             size_t *pcchLeft, int *pfPlain)
     3592{
     3593    const char * const  pszContent = pCompiler->pszContent;
     3594    size_t              off        = pchWord - pszContent;
     3595    size_t const        offLineEnd = off + cchLeft;
     3596    int                 fPlain     = 1;
     3597    unsigned            iEscEol    = pCompiler->iEscEol;
     3598
     3599    /* Check our expectations. */
     3600    KMK_CC_ASSERT(cchLeft);
     3601    KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord));
     3602    KMK_CC_ASSERT(iEscEol <= pCompiler->cEscEols);
     3603    KMK_CC_ASSERT(   iEscEol >= pCompiler->cEscEols
     3604                  || off < pCompiler->paEscEols[iEscEol].offEol);
     3605    KMK_CC_ASSERT(off >= (iEscEol == 0 ? pCompiler->offLine : pCompiler->paEscEols[iEscEol - 1].offEol + pCompiler->cchEolSeq));
     3606
     3607    /*
     3608     * The outer loop parses plain text.  Variable expansion ($) is handled
     3609     * by an inner loop.
     3610     */
     3611    while (off < offLineEnd)
     3612    {
     3613        char ch = pszContent[off];
     3614        if (!KMK_CC_EVAL_IS_SPACE_OR_VAR_OR_RECIPE(ch))
     3615            off++;
     3616        else
     3617        {
     3618            if (KMK_CC_EVAL_IS_SPACE(ch))
     3619                break;
     3620
     3621            if (ch == '$')
     3622            {
     3623                off++;
     3624                if (off < offLineEnd)
     3625                {
     3626                    char const chOpen = pszContent[off];
     3627                    if (chOpen == '(' || chOpen == '{')
     3628                    {
     3629                        /*
     3630                         * Got a $(VAR) or ${VAR} to deal with here.  This may
     3631                         * include nested variable references and span multiple
     3632                         * lines (at least for function calls).
     3633                         *
     3634                         * We scan forward till we've found the corresponding
     3635                         * closing parenthesis, considering any open parentheses
     3636                         * of the same kind as worth counting, even if there are
     3637                         * no dollar preceeding them, just like GNU make does.
     3638                         */
     3639                        size_t const offStart = off - 1;
     3640                        char const   chClose  = chOpen == '(' ? ')' : '}';
     3641                        unsigned     cOpen    = 1;
     3642                        for (;;)
     3643                        {
     3644                            if (off < offLineEnd)
     3645                            {
     3646                                ch = pszContent[off];
     3647                                if (!(KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch)))
     3648                                    off++;
     3649                                else
     3650                                {
     3651                                    off++;
     3652                                    if (ch == chClose)
     3653                                    {
     3654                                        if (--cOpen == 0)
     3655                                            break;
     3656                                    }
     3657                                    else if (ch == chOpen)
     3658                                        cOpen++;
     3659                                    else if (   ch == '\\'
     3660                                             && iEscEol < pCompiler->cEscEols
     3661                                             && off == pCompiler->paEscEols[iEscEol].offEsc)
     3662                                    {
     3663                                        off = pCompiler->paEscEols[iEscEol].offEsc + pCompiler->cchEolSeq;
     3664                                        iEscEol++;
     3665                                        pCompiler->iEscEol = iEscEol;
     3666                                    }
     3667                                }
     3668                            }
     3669                            else if (cOpen == 1)
     3670                                kmk_cc_eval_fatal(pCompiler, &pszContent[offStart],
     3671                                                  "Variable reference is missing '%c'", chClose);
     3672                            else
     3673                                kmk_cc_eval_fatal(pCompiler, &pszContent[offStart],
     3674                                                  "%u variable references are missing '%c'", cOpen, chClose);
     3675                        }
     3676                    }
     3677                    /* Single char variable name. */
     3678                    else if (!KMK_CC_EVAL_IS_SPACE(chOpen))
     3679                    {  /* likely */ }
     3680                    else
     3681                        kmk_cc_eval_fatal(pCompiler, &pszContent[off], "Expected variable name after '$', not end of line");
     3682                }
     3683                else
     3684                    kmk_cc_eval_fatal(pCompiler, &pszContent[off], "Expected variable name after '$', not end of line");
     3685                fPlain = 0;
     3686            }
     3687            /* Deal with potential escaped EOL. */
     3688            else if (   ch != '\\'
     3689                     || iEscEol >= pCompiler->cEscEols
     3690                     || off != pCompiler->paEscEols[iEscEol].offEsc )
     3691                off++;
     3692            else
     3693                break;
     3694        }
     3695    }
     3696
     3697    *pcchLeft = offLineEnd - off;
     3698    *pfPlain  = fPlain;
     3699    return &pszContent[off];
     3700}
     3701
     3702
     3703/**
    35023704 * Prepares for copying a command line.
    35033705 *
     
    36223824
    36233825/**
    3624  * Prepares for copying a normal line.
    3625  *
    3626  * This will modify the members of paEscEols to store copy instructions for the
    3627  * following kmk_cc_eval_copy_prepped_normal_line() call.
    3628  *
    3629  * @returns The number of chars that will be copied by
    3630  *          kmk_cc_eval_copy_prepped_normal_line().
     3826 * Gather string from segments and optional space insertion trick.
     3827 *
     3828 * @param   pszDst          The destination buffer.
     3829 * @param   paSegs          The source segments.
     3830 * @param   cSegs           The number of segments.
     3831 * @param   cchDstPrepped   The size of pszDst, excluding the terminator.
     3832 */
     3833static void kmk_cc_eval_strcpyv(char *pszDst, PCKMKCCEVALSTRCPYSEG paSegs, unsigned cSegs, size_t cchDstPrepped)
     3834{
     3835    const char *pszDstStart = pszDst;
     3836    unsigned    iSeg = 0;
     3837    while (iSeg < cSegs)
     3838    {
     3839        size_t cchToCopy;
     3840        if (paSegs[iSeg].cchSrcAndPrependSpace >= 0)
     3841            cchToCopy = paSegs[iSeg].cchSrcAndPrependSpace;
     3842        else
     3843        {
     3844            cchToCopy = -paSegs[iSeg].cchSrcAndPrependSpace;
     3845            *pszDst++ = ' ';
     3846        }
     3847
     3848        memcpy(pszDst, paSegs[iSeg].pchSrc, cchToCopy);
     3849        pszDst += cchToCopy;
     3850
     3851        iSeg++;
     3852    }
     3853    *pszDst = '\0';
     3854    KMK_CC_ASSERT(pszDst == &pszDstStart[cchDstPrepped]); K_NOREF(pszDstStart); K_NOREF(cchDstPrepped);
     3855}
     3856
     3857/**
     3858 * Helper for ensuring that we've got sufficient number of string copy segments.
     3859 */
     3860#define KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(a_pCompiler, a_cRequiredSegs) \
     3861    do { \
     3862        if ((a_cRequiredSegs) < (a_pCompiler)->cStrCopySegsAllocated) \
     3863        { /* likely */ } \
     3864        else \
     3865        { \
     3866            unsigned cSegs = ((a_cRequiredSegs) + 3 /*15*/) & ~(unsigned)3/*15*/; \
     3867            KMK_CC_ASSERT((a_cRequiredSegs) < 0x8000); \
     3868            (a_pCompiler)->paStrCopySegs = (PKMKCCEVALSTRCPYSEG)xmalloc(cSegs * sizeof((a_pCompiler)->paStrCopySegs)[0]); \
     3869        } \
     3870    } while (0)
     3871
     3872
     3873/**
     3874 * Prepares for copying a normal line, extended version.
     3875 *
     3876 * This does not assume that we start on a word, it can handle any starting
     3877 * character.  It can also prepare partial copies.
     3878 *
     3879 * In addition to the returned information, this will store instruction in
     3880 * paEscEols for the following kmk_cc_eval_strcpyv() call.
     3881 *
     3882 * This will advance pCompiler->iEscEol, so that it's possible to use the common
     3883 * macros and helpers for parsing what comes afterwards.
     3884 *
     3885 * @returns The number of chars that will be copied by kmk_cc_eval_strcpyv().
     3886 * @param   pCompiler               The compiler instance data.
     3887 * @param   pchWord                 Pointer to the first char to copy from the
     3888 *                                  current line. This must be the start of a
     3889 *                                  word.
     3890 * @param   cchLeft                 The number of chars left on the current line
     3891 *                                  starting at @a pchWord.
     3892 */
     3893static size_t kmk_cc_eval_prep_normal_line_ex(PKMKCCEVALCOMPILER pCompiler, const char * const pchWord, size_t cchLeft)
     3894{
     3895    size_t          cchRet;
     3896    unsigned        iEscEol  = pCompiler->iEscEol;
     3897    unsigned const  cEscEols = pCompiler->cEscEols;
     3898
     3899    KMK_CC_ASSERT(cchLeft >= 0);
     3900    KMK_CC_ASSERT(iEscEol <= cEscEols);
     3901
     3902    if (cchLeft > 0)
     3903    {
     3904        /*
     3905         * If there are no escaped EOLs left, just copy exactly
     3906         * what was passed in.
     3907         */
     3908        if (iEscEol >= cEscEols)
     3909        {
     3910            KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, 1);
     3911            pCompiler->cStrCopySegs = 1;
     3912            pCompiler->paStrCopySegs[0].pchSrc = pchWord;
     3913            pCompiler->paStrCopySegs[0].cchSrcAndPrependSpace = cchRet = cchLeft;
     3914        }
     3915        /*
     3916         * Ok, we have to deal with escaped EOLs and do the proper
     3917         * replacement of escaped newlines with space.  The deal is that we
     3918         * collaps all whitespace before and after one or more newlines into a
     3919         * single space.  (FreeBSD make does this differently, by the by.)
     3920         */
     3921        else
     3922        {
     3923            const char * const  pszContent    = pCompiler->pszContent;
     3924            size_t              offWord       = pchWord - pCompiler->pszContent;
     3925            size_t const        offLineEnd    = offWord + cchLeft;             /* Note! Not necessarily end of line.*/
     3926            size_t              offEsc;
     3927            size_t              fPendingSpace = 0;
     3928            unsigned            cSegs         = 0;
     3929            size_t              cchSeg;
     3930
     3931            /* Go nuts checking our preconditions here. */
     3932            KMK_CC_ASSERT(offWord >= pCompiler->offLine);
     3933            KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->offLine + pCompiler->cchLine);
     3934            KMK_CC_ASSERT(offWord + cchLeft <= pCompiler->cchContent);
     3935            KMK_CC_ASSERT(offWord <= pCompiler->paEscEols[iEscEol].offEsc);
     3936            KMK_CC_ASSERT(offWord >= (iEscEol ? pCompiler->paEscEols[cEscEols - 1].offEol + pCompiler->cchEolSeq
     3937                                              : pCompiler->offLine));
     3938            KMK_CC_ASSERT(offWord <  offLineEnd);
     3939
     3940            /* Make sure we've got more than enough segments to fill in. */
     3941            KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cEscEols - iEscEol + 2);
     3942
     3943            /*
     3944             * All but the last line.
     3945             */
     3946            cchRet = 0;
     3947            do
     3948            {
     3949                KMK_CC_ASSERT(offWord < offLineEnd);
     3950                offEsc = pCompiler->paEscEols[iEscEol].offEsc;
     3951                if (offWord < offEsc)
     3952                {
     3953                    /* Strip trailing spaces. */
     3954                    while (offEsc > offWord && KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1]))
     3955                        offEsc--;
     3956                    cchSeg = offEsc - offWord;
     3957                    if (cchSeg)
     3958                    {
     3959                        /* Add segment. */
     3960                        pCompiler->paStrCopySegs[cSegs].pchSrc = &pszContent[offWord];
     3961                        if (offEsc < offLineEnd)
     3962                        {
     3963                            pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace
     3964                                                                                  ? -(ssize_t)cchSeg : (ssize_t)cchSeg;
     3965                            cchRet       += cchSeg + fPendingSpace;
     3966                            cSegs        += 1;
     3967                            fPendingSpace = 1;
     3968                        }
     3969                        else
     3970                        {
     3971                            cchSeg = offLineEnd - offWord;
     3972                            pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace
     3973                                                                                  ? -(ssize_t)cchSeg : (ssize_t)cchSeg;
     3974                            pCompiler->cStrCopySegs = cSegs + 1;
     3975                            pCompiler->iEscEol      = iEscEol;
     3976                            return cchRet + cchSeg + fPendingSpace;
     3977                        }
     3978                    }
     3979                }
     3980                else
     3981                    KMK_CC_ASSERT(offWord == offEsc);
     3982
     3983                /* Next line. */
     3984                offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq;
     3985                iEscEol++;
     3986
     3987                /* Strip leading spaces. */
     3988                while (offWord < offLineEnd && KMK_CC_EVAL_IS_SPACE(pszContent[offWord]))
     3989                    offWord++;
     3990                if (offWord >= offLineEnd)
     3991                {
     3992                    pCompiler->cStrCopySegs = cSegs;
     3993                    pCompiler->iEscEol      = iEscEol;
     3994                    return cchRet;
     3995                }
     3996            } while (iEscEol < cEscEols);
     3997
     3998            /*
     3999             * The last line.
     4000             */
     4001            cchSeg      = offLineEnd - offWord;
     4002            cchRet     += cchSeg;
     4003            pCompiler->paStrCopySegs[cSegs].pchSrc                = &pszContent[offWord];
     4004            pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace
     4005                                                                  ? -(ssize_t)cchSeg : (ssize_t)cchSeg;
     4006            pCompiler->cStrCopySegs = cSegs + 1;
     4007            pCompiler->iEscEol      = iEscEol;
     4008        }
     4009    }
     4010    /*
     4011     * Odd case: Nothing to copy.
     4012     */
     4013    else
     4014    {
     4015        cchRet = 0;
     4016        pCompiler->cStrCopySegs = 0;
     4017    }
     4018    return cchRet;
     4019}
     4020
     4021
     4022/**
     4023 * Prepares for copying a normal line, from the given position all the way to
     4024 * the end.
     4025 *
     4026 * In addition to the returned information, this will store instruction in
     4027 * paStrCopySegs and cSTrCopySeg for the following kmk_cc_eval_strcpyv() call.
     4028 *
     4029 * @returns The number of chars that will be copied by kmk_cc_eval_strcpyv().
    36314030 * @param   pCompiler               The compiler instance data.
    36324031 * @param   pchWord                 Pointer to the first char to copy from the
     
    36484047    KMK_CC_ASSERT(iEscEol <= cEscEols);
    36494048
     4049    /*
     4050     * If there are no escaped EOLs left, just copy what was specified,
     4051     * optionally sans any trailing spaces.
     4052     */
    36504053    if (iEscEol >= cEscEols)
    36514054    {
    3652         /*
    3653          * No escaped EOLs left, simple.  Just need to strip trailing spaces
    3654          * when desired by the caller.
    3655          */
    36564055        cchRet = cchLeft;
    36574056        if (fStripTrailingSpaces)
    36584057            while (cchRet > 0 && KMK_CC_IS_SPACE_CH(pchWord[cchRet - 1]))
    36594058                cchRet--;
    3660     }
     4059
     4060        KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, 1);
     4061        pCompiler->cStrCopySegs = 1;
     4062        pCompiler->paStrCopySegs[0].pchSrc = pchWord;
     4063        pCompiler->paStrCopySegs[0].cchSrcAndPrependSpace = cchRet;
     4064    }
     4065    /*
     4066     * Ok, we have to deal with escaped EOLs and do the proper
     4067     * replacement of escaped newlines with space.  The deal is that we
     4068     * collaps all whitespace before and after one or more newlines into a
     4069     * single space.  (FreeBSD make does this differently, by the by.)
     4070     */
    36614071    else
    36624072    {
    3663         /*
    3664          * This is a tad complicated.  Working with offsets here is simpler.
    3665          */
    36664073        const char *pszContent = pCompiler->pszContent;
    36674074        size_t      offWord    = pchWord - pCompiler->pszContent;
    36684075        size_t      offEsc;
    36694076        size_t      fPendingSpace;
     4077        size_t      cchSeg;
     4078        unsigned    cSegs      = 0;
    36704079
    36714080        /* Go nuts checking our preconditions here. */
     
    36764085        KMK_CC_ASSERT(offWord >= (iEscEol ? pCompiler->paEscEols[cEscEols - 1].offEol + pCompiler->cchEolSeq : pCompiler->offLine));
    36774086
    3678         /* First line - We're at the start of a word, so no left stripping needed.  */
     4087        /* Make sure we've got more than enough segments to fill in. */
     4088        KMK_CC_EVAL_ENSURE_STRCOPY_SEGS(pCompiler, cEscEols - iEscEol + 2);
     4089
     4090        /*
     4091         * First line - We're at the start of a word, so no left stripping needed.
     4092         */
    36794093        offEsc = pCompiler->paEscEols[iEscEol].offEsc;
    36804094        KMK_CC_ASSERT(offEsc > offWord);
     
    36854099        fPendingSpace = 1;
    36864100        cchRet        = offEsc - offWord;
    3687         pCompiler->paEscEols[iEscEol].offEsc = offEsc;
     4101        pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = cchRet;
     4102        pCompiler->paStrCopySegs[cSegs].pchSrc                = pchWord;
    36884103
    36894104        offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq;
    36904105        iEscEol++;
    36914106
    3692         /* All but the last line. */
     4107        /*
     4108         * All but the last line.
     4109         */
    36934110        while (iEscEol < cEscEols)
    36944111        {
    36954112            offEsc = pCompiler->paEscEols[iEscEol].offEsc;
     4113
     4114            /* Strip leading spaces. */
    36964115            while (offWord < offEsc && KMK_CC_EVAL_IS_SPACE(pszContent[offWord]))
    36974116                offWord++;
     
    36994118            if (offWord < offEsc)
    37004119            {
     4120                /* Strip trailing spaces. */
    37014121                while (KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1]))
    37024122                    offEsc--;
    3703                 cchRet += offEsc - offWord + fPendingSpace;
     4123                cchSeg = offEsc - offWord;
     4124                pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg;
     4125                cchRet += cchSeg + fPendingSpace;
     4126                pCompiler->paStrCopySegs[cSegs].pchSrc                = &pszContent[offWord];
     4127                cSegs  += 1;
    37044128                fPendingSpace = 1;
    37054129            }
    37064130
    3707             pCompiler->paEscEols[iEscEol - 1].offEol = offWord;
    3708             pCompiler->paEscEols[iEscEol].offEsc     = offEsc;
    3709 
     4131            /* Next. */
    37104132            offWord = pCompiler->paEscEols[iEscEol].offEol + pCompiler->cchEolSeq;
    37114133            iEscEol++;
    37124134        }
    37134135
    3714         /* Final line. We must calculate the end of line offset our selves here. */
     4136        /*
     4137         * Final line. We must calculate the end of line offset our selves here.
     4138         */
    37154139        offEsc = &pchWord[cchLeft] - pszContent;
    37164140        while (offWord < offEsc && KMK_CC_EVAL_IS_SPACE(pszContent[offWord]))
     
    37224146                while (KMK_CC_EVAL_IS_SPACE(pszContent[offEsc - 1]))
    37234147                    offEsc--;
    3724             cchRet += offEsc - offWord + fPendingSpace;
     4148            cchSeg = offEsc - offWord;
     4149            pCompiler->paStrCopySegs[cSegs].cchSrcAndPrependSpace = fPendingSpace ? -(ssize_t)cchSeg : (ssize_t)cchSeg;
     4150            cchRet += cchSeg + fPendingSpace;
     4151            pCompiler->paStrCopySegs[cSegs].pchSrc                = &pszContent[offWord];
     4152            cSegs  += 1;
    37254153        }
    3726         pCompiler->paEscEols[iEscEol - 1].offEol = offWord;
     4154
     4155        pCompiler->cStrCopySegs = cSegs;
    37274156    }
    37284157    return cchRet;
    3729 }
    3730 
    3731 
    3732 /**
    3733  * Copies a normal line to the buffer @a pszDst points to.
    3734  *
    3735  * Must only be used immediately after kmk_cc_eval_prep_normal_line().
    3736  *
    3737  * @param   pCompiler   The compiler instance data.
    3738  * @param   pchLeft     Pointer to the first char to copy from the current line.
    3739  *                      This does not have to the start of a word.
    3740  * @param   cchPrepped  The return value of kmk_cc_eval_prep_normal_line().
    3741  * @param   pszDst      The destination buffer, must be at least @a cchPrepped
    3742  *                      plus one (terminator) char big.
    3743  */
    3744 static void kmk_cc_eval_copy_prepped_normal_line(PKMKCCEVALCOMPILER pCompiler, const char *pchWord,
    3745                                                  size_t cchPrepped, char *pszDst)
    3746 {
    3747     unsigned        iEscEol  = pCompiler->iEscEol;
    3748     unsigned const  cEscEols = pCompiler->cEscEols;
    3749     if (iEscEol >= cEscEols)
    3750     {
    3751         /* Single line. */
    3752         memcpy(pszDst, pchWord, cchPrepped);
    3753         pszDst[cchPrepped] = '\0';
    3754     }
    3755     else
    3756     {
    3757         /* offEsc = end of copy on a line, offWord/offEol is where to start on the next. */
    3758         size_t          offWord       = pchWord - pCompiler->pszContent;
    3759         int             fPendingSpace = 0;
    3760         char * const    pszDstStart   = pszDst;
    3761         size_t          cchCopy;
    3762         do
    3763         {
    3764             cchCopy = pCompiler->paEscEols[iEscEol].offEsc - offWord;
    3765             KMK_CC_ASSERT(pCompiler->paEscEols[iEscEol].offEsc >= offWord);
    3766             if (cchCopy)
    3767             {
    3768                 if (fPendingSpace)
    3769                     *pszDst++ = ' ';
    3770                 memcpy(pszDst, &pCompiler->pszContent[offWord], cchCopy);
    3771                 pszDst += cchCopy;
    3772                 fPendingSpace = 1;
    3773             }
    3774             offWord = pCompiler->paEscEols[iEscEol].offEol;
    3775             iEscEol++;
    3776         } while (iEscEol < cEscEols);
    3777 
    3778         /* The final line is delimited by cchPrepped. */
    3779         cchCopy = cchPrepped - (pszDst - pszDstStart);
    3780         KMK_CC_ASSERT(cchCopy <= cchPrepped);
    3781         if (cchCopy > 0)
    3782         {
    3783             if (fPendingSpace)
    3784                 *pszDst++ = ' ';
    3785             memcpy(pszDst, &pCompiler->pszContent[offWord], cchCopy);
    3786             pszDst += cchCopy;
    3787         }
    3788         *pszDst = '\0';
    3789         KMK_CC_ASSERT(pszDst == &pszDstStart[cchPrepped]);
    3790     }
    37914158}
    37924159
     
    38474214        PKMKCCEVALIFEXPR pInstr  = (PKMKCCEVALIFEXPR)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail,
    38484215                                                                             KMKCCEVALIFEXPR_SIZE(cchExpr));
    3849         kmk_cc_eval_copy_prepped_normal_line(pCompiler, pchWord, cchExpr, pInstr->szExpr);
     4216        kmk_cc_eval_strcpyv(pInstr->szExpr, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchExpr);
    38504217        pInstr->cchExpr = cchExpr;
    38514218        pInstr->IfCore.Core.enmOpCode = kKmkCcEvalInstr_if;
     
    38594226
    38604227
     4228/**
     4229 * Deals with 'ifdef var', 'ifndef var', 'else ifdef var' and 'else ifndef var'
     4230 * statements.
     4231 *
     4232 * @returns 1 to indicate we've handled a keyword (see
     4233 *          kmk_cc_eval_try_handle_keyword).
     4234 * @param   pCompiler       The compiler state.
     4235 * @param   pchWord         First char after 'define'.
     4236 * @param   cchLeft         The number of chars left to parse on this line.
     4237 * @param   fInElse         Set if this is an 'else if' (rather than just 'if').
     4238 * @param   fPositiveStmt   Set if 'ifdef', clear if 'ifndef'.
     4239 */
    38614240static int kmk_cc_eval_do_ifdef(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt)
    38624241{
     4242    KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4243    if (cchLeft)
     4244    {
     4245        /*
     4246         * Skip to the end of the variable name.
     4247         */
     4248        unsigned const      iSavedEscEol = pCompiler->iEscEol;
     4249        const char * const  pchVarNm     = pchWord;
     4250        int                 fPlain;
     4251        pchWord = kmk_cc_eval_skip_var_name(pCompiler, pchWord, cchLeft, &cchLeft, &fPlain);
     4252        KMK_CC_ASSERT(pCompiler->iEscEol == iSavedEscEol || !fPlain);
     4253        if (fPlain)
     4254        {
     4255            size_t const            cchVarNm = pchWord - pchVarNm;
     4256            PKMKCCEVALIFDEFPLAIN    pInstr;
     4257            pInstr = (PKMKCCEVALIFDEFPLAIN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     4258            pInstr->IfCore.Core.enmOpCode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_plain : kKmkCcEvalInstr_ifndef_plain;
     4259            pInstr->IfCore.Core.iLine     = pCompiler->iLine;
     4260            pInstr->pszName = strcache2_add(&variable_strcache, pchVarNm, cchVarNm);
     4261            kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse);
     4262        }
     4263        else
     4264        {
     4265            PKMKCCEVALIFDEFDYNAMIC  pInstr;
     4266            size_t const            cchVarNm = pchWord - pchVarNm;
     4267            size_t                  cchCopy;
     4268            char                   *pszCopy;
     4269            pCompiler->iEscEol = iSavedEscEol;
     4270            cchCopy = kmk_cc_eval_prep_normal_line(pCompiler, pchVarNm, cchVarNm, 0 /*fStripTrailingSpaces*/);
     4271
     4272            pInstr = (PKMKCCEVALIFDEFDYNAMIC)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     4273
     4274            /** @todo Make the subprogram embed necessary strings. */
     4275            pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, cchCopy + 1);
     4276            kmk_cc_eval_strcpyv(pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, cchCopy);
     4277
     4278            pInstr->IfCore.Core.enmOpCode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_dynamic : kKmkCcEvalInstr_ifndef_dynamic;
     4279            pInstr->IfCore.Core.iLine     = pCompiler->iLine;
     4280            kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->NameSubprog);
     4281
     4282            kmk_cc_eval_do_if_core(pCompiler, &pInstr->IfCore, fInElse);
     4283        }
     4284
     4285        /*
     4286         * Make sure there is nothing following the variable name.
     4287         */
     4288        KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4289        if (cchLeft)
     4290            kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'if%sdef' variable name", fPositiveStmt ? "" : "n");
     4291    }
     4292    else
     4293        kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive");
    38634294    return 1;
    38644295}
     
    38674298static int kmk_cc_eval_do_ifeq(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, int fInElse, int fPositiveStmt)
    38684299{
     4300    KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4301    if (cchLeft)
     4302    {
     4303        /*
     4304         * There are two forms:
     4305         *
     4306         *   ifeq (string1, string2)
     4307         *   ifeq "string1" 'string2'
     4308         *
     4309         */
     4310        const char * const  pchEnd = &pchWord[cchLeft];
     4311        PKMKCCEVALIFEQ      pInstr;
     4312
     4313        struct
     4314        {
     4315            char           *pszCopy;
     4316            size_t          cchCopy;
     4317            int             fPlain;
     4318        } Left, Right;
     4319
     4320        char ch = *pchWord;
     4321        if (ch == '(')
     4322        {
     4323//            unsigned cCounts;
     4324
     4325            /* Skip the parenthesis. */
     4326            pchWord++;
     4327            cchLeft--;
     4328
     4329/** @todo continue here.   */
     4330        }
     4331        else if (ch == '"' || ch == '\'')
     4332        {
     4333            const char *pchTmp;
     4334
     4335            /*
     4336             * Quoted left side.
     4337             */
     4338            /* Skip leading quote. */
     4339            pchWord++;
     4340            cchLeft--;
     4341
     4342            /* Locate the end quote. */
     4343            pchTmp = (const char *)memchr(pchWord, ch, cchLeft);
     4344            if (pchTmp) { /* likely */ }
     4345            else kmk_cc_eval_fatal(pCompiler, pchWord - 1, "Unbalanced quote in first if%seq string", fPositiveStmt ? "" : "n");
     4346
     4347            Left.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord);
     4348            Left.pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, Left.cchCopy + 1);
     4349            kmk_cc_eval_strcpyv(Left.pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, Left.cchCopy);
     4350            Left.fPlain  = memchr(Left.pszCopy, '$', Left.cchCopy) == NULL;
     4351
     4352            /* skip end quote */
     4353            pchWord  = pchTmp + 1;
     4354            cchLeft  = pchEnd - pchWord;
     4355
     4356            /* Skip anything inbetween the left and right hand side (not mandatory). */
     4357            if (   cchLeft /** @todo replace with straight 'isspace' that takes escaped EOLs into account. */
     4358                && KMK_CC_EVAL_IS_SPACE_AFTER_WORD(pCompiler, pchWord[0], pchWord[1], cchLeft))
     4359                KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4360
     4361            /*
     4362             * Quoted right side.
     4363             */
     4364            if (   cchLeft > 0
     4365                && ( (ch = *pchWord) != '"' || ch == '\'') )
     4366            {
     4367                /* Skip leading quote. */
     4368                pchWord++;
     4369                cchLeft--;
     4370
     4371                /* Locate the end quote. */
     4372                pchTmp = (const char *)memchr(pchWord, ch, cchLeft);
     4373                if (pchTmp) { /* likely */ }
     4374                else kmk_cc_eval_fatal(pCompiler, pchWord - 1, "Unbalanced quote in second if%seq string", fPositiveStmt ? "" : "n");
     4375
     4376                Right.cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchWord, pchTmp - pchWord);
     4377                Right.pszCopy = kmk_cc_block_alloc_eval_string(pCompiler->ppBlockTail, Right.cchCopy + 1);
     4378                kmk_cc_eval_strcpyv(Left.pszCopy, pCompiler->paStrCopySegs, pCompiler->cStrCopySegs, Right.cchCopy);
     4379                Right.fPlain  = memchr(Right.pszCopy, '$', Right.cchCopy) == NULL;
     4380
     4381                /* skip end quote */
     4382                pchWord  = pchTmp + 1;
     4383                cchLeft  = pchEnd - pchWord;
     4384            }
     4385            else
     4386                kmk_cc_eval_fatal(pCompiler, pchWord, "Expected a second quoted string for 'if%seq'",
     4387                                  fPositiveStmt ? "" : "n");
     4388        }
     4389        else
     4390            kmk_cc_eval_fatal(pCompiler, pchWord, "Expected parentheses or quoted string after 'if%seq'",
     4391                              fPositiveStmt ? "" : "n");
     4392
     4393        /*
     4394         *
     4395         */
     4396        pInstr = (PKMKCCEVALIFEQ)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     4397
     4398
     4399        /*
     4400         * Make sure there is nothing following the variable name.
     4401         */
     4402        KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4403        if (cchLeft)
     4404            kmk_cc_eval_fatal(pCompiler, pchWord, "Bogus stuff after 'if%sdef' variable name", fPositiveStmt ? "" : "n");
     4405    }
     4406    else
     4407        kmk_cc_eval_fatal(pCompiler, pchWord, "Expected expression after 'if' directive");
    38694408    return 1;
    38704409}
     
    39334472
    39344473            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "eq", 2))
    3935                 return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft + 2, 1 /* in else */, 1 /* positive */);
     4474                return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft - 2, 1 /* in else */, 1 /* positive */);
    39364475
    39374476            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "def", 3))
    3938                 return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft + 3, 1 /* in else */, 1 /* positive */);
     4477                return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 1 /* positive */);
    39394478
    39404479            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "neq", 3))
    3941                 return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft + 3, 1 /* in else */, 0 /* positive */);
     4480                return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 0 /* positive */);
    39424481
    39434482            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "1of", 3))
    3944                 return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft + 3, 1 /* in else */, 1 /* positive */);
     4483                return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft - 3, 1 /* in else */, 1 /* positive */);
    39454484
    39464485            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "ndef", 4))
    3947                 return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft + 4, 1 /* in else */, 0 /* positive */);
     4486                return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft - 4, 1 /* in else */, 0 /* positive */);
    39484487
    39494488            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "n1of", 4))
    3950                 return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft + 4, 1 /* in else */, 0 /* positive */);
     4489                return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft - 4, 1 /* in else */, 0 /* positive */);
    39514490
    39524491            pchWord -= 2;
     
    41234662 * @param   fQualifiers The qualifiers.
    41244663 */
    4125 static int kmk_cc_eval_handle_var_export(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft,
    4126                                                   unsigned fQualifiers)
     4664static int kmk_cc_eval_handle_var_export(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers)
    41274665{
    41284666
     
    41424680 */
    41434681static int kmk_cc_eval_try_handle_var_with_keywords(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft,
    4144                                                              unsigned fQualifiers)
     4682                                                    unsigned fQualifiers)
    41454683{
    41464684    for (;;)
     
    41944732        else
    41954733            kmk_cc_eval_fatal(pCompiler, NULL,
    4196                                        "Expected assignment operator or variable directive after variable qualifier(s)\n");
     4734                              "Expected assignment operator or variable directive after variable qualifier(s)\n");
    41974735    }
    41984736}
     
    42624800
    42634801            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "eq", 2))
    4264                 return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft + 2, 0 /* in else */, 1 /* positive */);
     4802                return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 2, cchLeft - 2, 0 /* in else */, 1 /* positive */);
    42654803
    42664804            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "def", 3))
    4267                 return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft + 3, 0 /* in else */, 1 /* positive */);
     4805                return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 1 /* positive */);
    42684806
    42694807            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "neq", 3))
    4270                 return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft + 3, 0 /* in else */, 0 /* positive */);
     4808                return kmk_cc_eval_do_ifeq( pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 0 /* positive */);
    42714809
    42724810            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "1of", 3))
    4273                 return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft + 3, 0 /* in else */, 1 /* positive */);
     4811                return kmk_cc_eval_do_if1of(pCompiler, pchWord + 3, cchLeft - 3, 0 /* in else */, 1 /* positive */);
    42744812
    42754813            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "ndef", 4))
    4276                 return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft + 4, 0 /* in else */, 0 /* positive */);
     4814                return kmk_cc_eval_do_ifdef(pCompiler, pchWord + 4, cchLeft - 4, 0 /* in else */, 0 /* positive */);
    42774815
    42784816            if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "n1of", 4))
    4279                 return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft + 4, 0 /* in else */, 0 /* positive */);
     4817                return kmk_cc_eval_do_if1of(pCompiler, pchWord + 4, cchLeft - 4, 0 /* in else */, 0 /* positive */);
    42804818        }
    42814819        /* include... */
     
    42934831                    return kmk_cc_eval_do_include(pCompiler, pchWord, cchLeft, kKmkCcEvalInstr_includedep);
    42944832                if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-queue", 6))
    4295                     return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft + 6, kKmkCcEvalInstr_includedep_queue);
     4833                    return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft - 6, kKmkCcEvalInstr_includedep_queue);
    42964834                if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-flush", 6))
    4297                     return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft + 6, kKmkCcEvalInstr_includedep_flush);
     4835                    return kmk_cc_eval_do_include(pCompiler, pchWord + 6, cchLeft - 6, kKmkCcEvalInstr_includedep_flush);
    42984836            }
    42994837        }
     
    43024840    {
    43034841        if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "else", 4))
    4304             return kmk_cc_eval_do_else(pCompiler, pchWord + 4, cchLeft + 4);
     4842            return kmk_cc_eval_do_else(pCompiler, pchWord + 4, cchLeft - 4);
    43054843        if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "endif", 5))
    4306             return kmk_cc_eval_do_endif(pCompiler, pchWord + 5, cchLeft + 5);
     4844            return kmk_cc_eval_do_endif(pCompiler, pchWord + 5, cchLeft - 5);
    43074845        /* export and endef are handled elsewhere, though stray endef's may end up here... */
    43084846        KMK_CC_ASSERT(!KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "export", 6));
     
    43134851        if (   KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "sinclude", 8)
    43144852            || KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "-include", 8))
    4315             return kmk_cc_eval_do_include(pCompiler, pchWord + 8, cchLeft + 8, kKmkCcEvalInstr_include_silent);
     4853            return kmk_cc_eval_do_include(pCompiler, pchWord + 8, cchLeft - 8, kKmkCcEvalInstr_include_silent);
    43164854        if (KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "vpath", 5))
    4317             return kmk_cc_eval_do_vpath(pCompiler, pchWord + 5, cchLeft + 5);
     4855            return kmk_cc_eval_do_vpath(pCompiler, pchWord + 5, cchLeft - 5);
    43184856
    43194857        KMK_CC_ASSERT(!KMK_CC_WORD_COMP_CONST(pCompiler, pchWord, cchLeft, "local", 5));
     
    43724910            /* Simple case: No escaped EOL, nor the end of the input. */
    43734911            pchTmp = (const char *)memchr(&pszContent[offNext], chFirstEol, cchContent - offNext);
    4374             if (pchTmp && (&pszContent[offNext] == pchTmp || pchTmp[-1] != '\\') )
     4912            if (   pchTmp
     4913                && (   &pszContent[offNext] == pchTmp
     4914                    || pchTmp[-1] != '\\') )
    43754915            {
    43764916                if (   cchEolSeq == 1
    43774917                    || pchTmp[1] == Compiler.chSecondEol)
    43784918                {
    4379                     /* Frequent: Blank line or comment line. Skip. */
    4380                     if (   &pszContent[offNext] == pchTmp
    4381                         || pszContent[offNext] == '#')
     4919                    /* Frequent: Blank line. */
     4920                    if (&pszContent[offNext] == pchTmp)
    43824921                    {
    4383                         iLine++;
     4922fprintf(stderr, "#%03u: <empty>\n", Compiler.iLine, &pszContent[off]);
     4923                        Compiler.iLine++;
    43844924                        off = offNext += cchEolSeq;
    43854925                        continue;
    43864926                    }
    4387 
    4388                     cchLine = pchTmp - pszContent;
    4389                     offNext = cchLine + cchEolSeq;
     4927                    if (pszContent[offNext] == '#')
     4928                    {
     4929fprintf(stderr, "#%03u: <comment>\n", Compiler.iLine, &pszContent[off]);
     4930                        Compiler.iLine++;
     4931                        offNext = pchTmp - pszContent;
     4932                        off = offNext += cchEolSeq;
     4933                        continue;
     4934                    }
     4935
     4936                    offNext  = pchTmp - pszContent;
     4937                    cchLine  = offNext - off;
     4938
     4939                    offFirstWord = off;
     4940                    while (offFirstWord < offNext && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
     4941                        offFirstWord++;
     4942
     4943                    offNext += cchEolSeq;
    43904944                    Compiler.cEscEols = 0;
    43914945                    Compiler.iEscEol  = 0;
    4392 
    4393                     offFirstWord = off;
    4394                     while (offFirstWord < cchLine && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
    4395                         offFirstWord++;
    43964946                }
    43974947                else
    4398                     kmk_cc_eval_fatal_eol(&Compiler, pchTmp, iLine, off);
     4948                    kmk_cc_eval_fatal_eol(&Compiler, pchTmp, Compiler.iLine, off);
    43994949            }
    44004950            /* The complicated, less common cases. */
     
    44074957                {
    44084958                    if (offFirstWord == offNext)
    4409                         while (offFirstWord < cchLine && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
     4959                    {
     4960                        size_t offEol = off + cchLine;
     4961                        while (offFirstWord < off + cchLine && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
    44104962                            offFirstWord++;
     4963                    }
    44114964
    44124965                    if (pchTmp)
     
    44164969                        {
    44174970                            size_t offEsc;
    4418                             offNext = pchTmp - pszContent;
     4971                            if (offFirstWord != offNext)
     4972                                offNext = pchTmp - pszContent;
     4973                            else
     4974                            {
     4975                                offNext = pchTmp - pszContent;
     4976                                while (offFirstWord < offNext && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
     4977                                    offFirstWord++;
     4978                            }
     4979
    44194980
    44204981                            /* Is it an escape sequence? */
     
    44685029                        }
    44695030                        else
    4470                             kmk_cc_eval_fatal_eol(&Compiler, pchTmp, iLine, off);
     5031                            kmk_cc_eval_fatal_eol(&Compiler, pchTmp, Compiler.iLine, off);
    44715032                    }
    44725033                    else
    44735034                    {
    44745035                        /* End of input. Happens only once per compilation, nothing to optimize for. */
     5036                        if (offFirstWord == offNext)
     5037                            while (offFirstWord < cchContent && KMK_CC_EVAL_IS_SPACE(pszContent[offFirstWord]))
     5038                                offFirstWord++;
    44755039                        offNext = cchContent;
    44765040                        cchLine = cchContent - off;
     
    44815045            }
    44825046            KMK_CC_ASSERT(offNext       <= cchContent);
     5047            KMK_CC_ASSERT(offNext       >= off + cchLine);
    44835048            KMK_CC_ASSERT(off + cchLine <= cchContent && cchLine <= cchContent);
    4484             KMK_CC_ASSERT(offFirstWord  <= cchLine);
     5049            KMK_CC_ASSERT(offFirstWord  <= off + cchLine);
    44855050            KMK_CC_ASSERT(offFirstWord  >= off);
    44865051            KMK_CC_ASSERT(pszContent[offFirstWord] != ' ' && pszContent[offFirstWord] != '\t');
     5052{
     5053char chSaved = ((char *)pszContent)[off+cchLine] = '\0';
     5054fprintf(stderr, "#%03u: %s\n", Compiler.iLine, &pszContent[off]);
     5055((char *)pszContent)[off+cchLine] = chSaved;
     5056}
    44875057
    44885058            /*
    4489              * Check for comments and skip blank lines.
     5059             * Skip blank lines.
    44905060             */
    4491             if (   offFirstWord < cchLine
    4492                 && pszContent[offFirstWord] != '#')
     5061            if (offFirstWord < off + cchLine)
    44935062            {
    4494                 const char *pchWord = &pszContent[offFirstWord];
    4495                 size_t      cchLeft = cchLine - offFirstWord;
    4496                 pchTmp = (const char *)memchr(pchWord, '#', cchLeft); /** @todo not correct for command lines! */
    4497                 if (pchTmp)
    4498                 {
    4499                     cchLeft = pchTmp - pchWord;
    4500                     cchLine = pchTmp - &pszContent[off];
    4501                 }
    4502 
    4503                 /*
    4504                  * Update the compiler state that we pass around.
    4505                  */
    4506                 Compiler.iLine   = iLine;
    4507                 Compiler.offLine = off;
    4508                 Compiler.cchLine = cchLine;
    4509 
    45105063                /*
    45115064                 * Command? Ignore command prefix if no open recipe (SunOS 4 behavior).
     
    45175070                        kmk_cc_eval_handle_command(&Compiler, &pszContent[off], cchLine);
    45185071                }
    4519                 else
     5072                /*
     5073                 * Since it's not a command line, we can now skip comment lines
     5074                 * even with a tab indentation.  If it's not a comment line, we
     5075                 * tentatively strip any trailing comment.
     5076                 */
     5077                else if (pszContent[offFirstWord] != '#')
    45205078                {
     5079                    const char *pchWord = &pszContent[offFirstWord];
     5080                    size_t      cchLeft = off + cchLine - offFirstWord;
     5081                    char        ch;
     5082
     5083                    Compiler.cchLineWithComments =  cchLine;
     5084                    pchTmp = (const char *)memchr(pchWord, '#', cchLeft);
     5085                    if (pchTmp)
     5086                    {
     5087                        cchLeft = pchTmp - pchWord;
     5088                        cchLine = pchTmp - &pszContent[off];
     5089                    }
     5090                    Compiler.cchLine = cchLine;
     5091                    Compiler.offLine = off;
     5092
    45215093                    /*
    45225094                     * If not a directive or variable qualifier, it's either a variable
    45235095                     * assignment or a recipe.
    45245096                     */
    4525                     char ch = *pchWord;
     5097                    ch = *pchWord;
    45265098                    if (   !KMK_CC_EVAL_IS_1ST_IN_KEYWORD(ch)
    45275099                        || !KMK_CC_EVAL_IS_2ND_IN_KEYWORD(pchWord[1])
     
    45405112             * Advance to the next line.
    45415113             */
    4542             off    = offNext;
    4543             iLine += Compiler.cEscEols + 1;
     5114            off             = offNext;
     5115            Compiler.iLine += Compiler.cEscEols + 1;
    45445116        }
    45455117    }
     
    47345306    KMK_CC_ASSERT(pVar->evalprog || pProg);
    47355307
    4736 #if 0
    47375308    if (pVar->evalprog)
    47385309    {
     
    47405311        pVar->evalprog = NULL;
    47415312    }
    4742 #endif
    47435313
    47445314    if (pProg)
     
    47645334    KMK_CC_ASSERT(pVar->evalprog || pProg);
    47655335
    4766 #if 0
    47675336    if (pVar->evalprog)
    47685337    {
     
    47705339        pVar->evalprog = NULL;
    47715340    }
    4772 #endif
    47735341
    47745342    if (pProg)
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