VirtualBox

Changeset 3154 in kBuild


Ignore:
Timestamp:
Mar 15, 2018 11:35:33 PM (7 years ago)
Author:
bird
Message:

kmk_cc_exec: Some more work.

Location:
trunk/src/kmk
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/Makefile.kmk

    r3151 r3154  
    228228 kmk_DEFS += CONFIG_WITH_COMPILE_EVERYTHING
    229229endif
     230#ifeq ($(KBUILD_TYPE).$(USERNAME),debug.bird)
     231# kmk_DEFS += CONFIG_WITH_COMPILER CONFIG_WITH_EVAL_COMPILER CONFIG_WITH_COMPILE_EVERYTHING
     232#endif
    230233
    231234kmk_SOURCES = \
  • trunk/src/kmk/kmk_cc_exec.c

    r3140 r3154  
    66
    77/*
    8  * Copyright (c) 2015 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
     8 * Copyright (c) 2015-2017 knut st. osmundsen <bird-kBuild-spam-xiiv@anduin.net>
    99 *
    1010 * This file is part of kBuild.
     
    132132#endif
    133133
     134/** Block allocator logging.   */
     135//#define KMK_CC_BLOCK_LOGGING_ENABLED
     136#ifdef KMK_CC_BLOCK_LOGGING_ENABLED
     137# define KMK_CC_BLOCK_DPRINTF_UNPACK(...)           __VA_ARGS__
     138# define KMK_CC_BLOCK_DPRINTF(a)                    fprintf(stderr, KMK_CC_BLOCK_DPRINTF_UNPACK a)
     139#else
     140# define KMK_CC_BLOCK_DPRINTF(a)                    do { } while (0)
     141#endif
     142
    134143
    135144/** @defgroup grp_kmk_cc_evalprog Makefile Evaluation
    136145 * @{
    137146 */
    138 #if 1
     147#define KMK_CC_EVAL_LOGGING_ENABLED
     148#ifdef KMK_CC_EVAL_LOGGING_ENABLED
    139149# define KMK_CC_EVAL_DPRINTF_UNPACK(...)            __VA_ARGS__
    140150# define KMK_CC_EVAL_DPRINTF(a)                     fprintf(stderr, KMK_CC_EVAL_DPRINTF_UNPACK a)
     
    150160#define KMK_CC_EVAL_QUALIFIER_PRIVATE       8
    151161/** @} */
     162
     163/** Eval: Max makefile size we accept as input (in bytes). */
     164#define KMK_CC_EVAL_MAX_COMPILE_SIZE        (16*1024*1024)
    152165
    153166/** Eval: Max nesting depth of makefile conditionals.
     
    239252*********************************************************************************************************************************/
    240253/**
    241  * Block of expand instructions.
     254 * Block of instructions.
    242255 *
    243256 * To avoid wasting space on "next" pointers, as well as a lot of time walking
     
    567580    kKmkCcEvalInstr_undefine,
    568581
    569 
    570582    /** [else] ifdef variable - KMKCCEVALIFDEFPLAIN. */
    571583    kKmkCcEvalInstr_ifdef_plain,
     
    613625    kKmkCcEvalInstr_recipe_cancel_pattern,
    614626
     627/** @todo target variables. */
     628
    615629    /** vpath pattern directories - KMKCCEVALVPATH. */
    616630    kKmkCcEvalInstr_vpath,
     
    619633    /** vpath - KMKCCEVALCORE. */
    620634    kKmkCcEvalInstr_vpath_clear_all,
     635
     636    /** Make 'code' needing expanding and evaluation - KMKCCEVALEXPAND.
     637     * @note That this could in theory be used to start a recipe.  This will be
     638     *       detected by the interpreter and loading will for now fail.  A
     639     *       strategy for implement support for it would require picking up
     640     *       potential commands following the statements too. */
     641    kKmkCcEvalInstr_expand,
    621642
    622643    /** The end of valid instructions (exclusive). */
     
    757778    /** The 'if' core structure. */
    758779    KMKCCEVALIFCORE         IfCore;
     780    /** Alignment padding, MBZ. */
     781    KU32                    uPadding;
    759782    /** The subprogram that will give us the variable name. */
    760783    KMKCCEXPSUBPROG         NameSubprog;
     
    862885    /** First dependency. */
    863886    uint16_t                iFirstDep;
    864     /** Number of ordinary dependnecies. */
     887    /** Number of ordinary dependencies. */
    865888    uint16_t                cDeps;
    866889    /** First order only dependency. */
    867890    uint16_t                iFirstOrderOnlyDep;
    868     /** Number of ordinary dependnecies. */
     891    /** Number of ordinary dependencies. */
    869892    uint16_t                cOrderOnlyDeps;
    870893
     
    904927    /** The core instruction. */
    905928    KMKCCEVALCORE           Core;
    906     /** The number of search directories. */
     929    /** The number of commands. */
    907930    uint32_t                cCommands;
    908931    /** Pointer to the next instruction (subprogs and strings after this one). */
    909932    PKMKCCEVALCORE          pNext;
    910933    /** Commands to add to the current recipe.
    911      * Expressions will be expanded and split on space. */
     934     * Expressions will be expanded and split on newline? */
    912935    KMKCCEXPSUBPROGORPLAIN  aCommands[1];
    913936} KMKCCEVALRECIPECOMMANDS;
     
    938961/** Calculates the size of an KMKCCEVALVPATH structure for @a a_cFiles files. */
    939962#define KMKCCEVALVPATH_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aDirs, a_cDirs)
     963
     964
     965/**
     966 * Instruction format for kKmkCcEvalInstr_expand.
     967 */
     968typedef struct kmk_cc_eval_expand
     969{
     970    /** The core instruction. */
     971    KMKCCEVALCORE           Core;
     972    /** Alignment padding, MBZ. */
     973    KU32                    uPadding;
     974    /** The expansion subprogram that to execute and evaluate the output of. */
     975    KMKCCEXPSUBPROG         Subprog;
     976} KMKCCEVALEXPAND;
     977typedef KMKCCEVALEXPAND *PKMKCCEVALEXPAND;
    940978
    941979
     
    11101148    for (i = 0; i < K_ELEMENTS(g_apszEvalKeywords); i++)
    11111149    {
     1150#ifdef KMK_CC_STRICT
    11121151        size_t cch = strlen(g_apszEvalKeywords[i]);
    11131152        KMK_CC_ASSERT(cch >= KMK_CC_EVAL_KEYWORD_MIN);
    11141153        KMK_CC_ASSERT(cch <= KMK_CC_EVAL_KEYWORD_MAX);
     1154#endif
    11151155
    11161156        KMK_CC_EVAL_BM_OR(g_abEvalCcChars, g_apszEvalKeywords[i][0], KMK_CC_EVAL_CH_1ST_IN_KEYWORD);
     
    13701410{
    13711411    PKMKCCBLOCK pBlockTail = *ppBlockTail;
    1372     if (pBlockTail->offNext & (sizeof(void *) - 1U))
    1373     {
    1374         pBlockTail->offNext = KMK_CC_BLOCK_ALIGN_SIZE(pBlockTail->offNext);
     1412    uint32_t    offNext    = pBlockTail->offNext;
     1413    if (offNext & (sizeof(void *) - 1U))
     1414    {
     1415        pBlockTail->offNext = KMK_CC_BLOCK_ALIGN_SIZE(offNext);
     1416        KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_realign: offNext=%#x -> %#x\n", offNext, pBlockTail->offNext));
    13751417        KMK_CC_ASSERT(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP));
    13761418    }
     
    14001442        void *pvRet = (char *)pPrevBlock + pPrevBlock->offNext;
    14011443        pPrevBlock->offNext += cb;
     1444        KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc_grow: %p LB %#x offNext=%#x [prev]\n", pvRet, cb, pPrevBlock->offNext));
    14021445        return pvRet;
    14031446    }
     
    14241467#endif
    14251468
     1469    KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc_grow: %p LB %#x offNext=%#x\n", pNewBlock + 1, cb, pNewBlock->offNext));
    14261470    return pNewBlock + 1;
    14271471}
     
    14471491        void *pvRet = (char *)pBlockTail + pBlockTail->offNext;
    14481492        pBlockTail->offNext += cb;
     1493        KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc: %p LB %#x offNext=%#x\n", pvRet, cb, pBlockTail->offNext));
    14491494        return pvRet;
    14501495    }
     
    15171562    KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock);
    15181563
     1564    KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_exp_grow: %p LB %#x offNext=%#x\n", pRet, cb, pNewBlock->offNext));
    15191565    return pRet;
    15201566}
     
    15351581    KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP));
    15361582    KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 || cb == sizeof(KMKCCEXPCORE) /* final */ );
     1583    KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0);
    15371584
    15381585    if (cbLeft >= cb + sizeof(KMKCCEXPJUMP))
     
    15411588        pBlockTail->offNext += cb;
    15421589        KMK_CC_ASSERT(((size_t)pRet & (sizeof(void *) - 1)) == 0);
     1590        KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_exp: %p LB %#x offNext=%#x\n", pRet, cb, pBlockTail->offNext));
    15431591        return pRet;
    15441592    }
     
    15861634    pOldBlock->offNext += sizeof(*pJump);
    15871635    KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock);
    1588 
     1636    KMK_CC_ASSERT((pNewBlock->offNext & (sizeof(void *) - 1)) == 0);
     1637
     1638    KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_eval_grow: %p LB %#x offNext=%#x (*ppBlockTail=%p, was %p)\n",
     1639                          pRet, cb, pNewBlock->offNext, *ppBlockTail, pOldBlock));
    15891640    return pRet;
    15901641}
     
    16051656    KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEVALJUMP));
    16061657    KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 );
     1658    KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0);
    16071659
    16081660    if (cbLeft >= cb + sizeof(KMKCCEVALJUMP))
     
    16101662        PKMKCCEVALCORE pRet = (PKMKCCEVALCORE)((char *)pBlockTail + pBlockTail->offNext);
    16111663        pBlockTail->offNext += cb;
     1664        KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_eval: %p LB %#x offNext=%#x\n", pRet, cb, pBlockTail->offNext));
    16121665        return pRet;
    16131666    }
     
    29122965
    29132966
     2967/**
     2968 * Tokens (for KMKCCEVALWORD).
     2969 */
    29142970typedef enum kmk_cc_eval_token
    29152971{
    2916     /** Invalid token . */
     2972    /** Invalid token value 0. */
    29172973    kKmkCcEvalToken_Invalid = 0,
    2918 
    2919     /** Assignment: '=' */
    2920     kKmkCcEvalToken_AssignRecursive,
    2921     /** Assignment: ':=' */
    2922     kKmkCcEvalToken_AssignSimple,
    2923     /** Assignment: '+=' */
    2924     kKmkCcEvalToken_AssignAppend,
    2925     /** Assignment: '<=' */
    2926     kKmkCcEvalToken_AssignPrepend,
    2927     /** Assignment: '?=' */
    2928     kKmkCcEvalToken_AssignIfNew,
    2929     /** Assignment: 'define' */
    2930     kKmkCcEvalToken_define,
    2931     /** Unassignment: 'undefine' */
    2932     kKmkCcEvalToken_undefine,
    2933 
    2934     /* Assignment modifier: 'local'  */
    2935     kKmkCcEvalToken_local,
    2936     /* Assignment modifier: 'override' */
    2937     kKmkCcEvalToken_override,
    2938     /* Assignment modifier: 'private' (target variable not inh by deps) */
    2939     kKmkCcEvalToken_private,
    2940     /* Assignment modifier / other variable thing: 'export' */
    2941     kKmkCcEvalToken_export,
    2942     /* Other variable thing: 'unexport' */
    2943     kKmkCcEvalToken_unexport,
    2944 
    2945     kKmkCcEvalToken_ifdef,
    2946     kKmkCcEvalToken_ifndef,
    2947     kKmkCcEvalToken_ifeq,
    2948     kKmkCcEvalToken_ifneq,
    2949     kKmkCcEvalToken_if1of,
    2950     kKmkCcEvalToken_ifn1of,
    2951     kKmkCcEvalToken_if,
    2952     kKmkCcEvalToken_else,
    2953     kKmkCcEvalToken_endif,
    2954 
    2955     kKmkCcEvalToken_include,
    2956     kKmkCcEvalToken_include_silent,
    2957     kKmkCcEvalToken_includedep,
    2958     kKmkCcEvalToken_includedep_queue,
    2959     kKmkCcEvalToken_includedep_flush,
    2960 
    2961     kKmkCcEvalToken_colon,
    2962     kKmkCcEvalToken_double_colon,
    2963     kKmkCcEvalToken_plus,
    2964     kKmkCcEvalToken_plus_maybe,
    2965 
    2966     kKmkCcEvalToken_vpath,
    29672974
    29682975    /** Plain word. */
     
    29712978    kKmkCcEvalToken_WordWithDollar,
    29722979
     2980    /** Recipe colon. */
     2981    kKmkCcEvalToken_colon,
     2982    /** Recipe double colon.   */
     2983    kKmkCcEvalToken_double_colon,
     2984    /** Recipe multi target plus. */
     2985    kKmkCcEvalToken_plus,
     2986    /** Recipe multi target plus-maybe (+|). */
     2987    kKmkCcEvalToken_plus_maybe,
     2988    /** Recipe semicolon. */
     2989    kKmkCcEvalToken_semicolon,
     2990
     2991    /** End of valid token values (not included). */
    29732992    kKmkCcEvalToken_End
    29742993} KMKCCEVALTOKEN;
     
    30363055    unsigned            iEscEol;
    30373056
    3038     /** The current line number (for error handling / debugging). */
     3057    /** The current line number for error handling / debugging (1-based). */
    30393058    unsigned            iLine;
    3040     /** The start offset of the current line. */
     3059    /** The start offset (into pchContent) of the current line. */
    30413060    size_t              offLine;
    30423061    /** Length of the current line, sans the final EOL and comments. */
     
    30703089    /** Set if we're working on a recipe. */
    30713090    PKMKCCEVALRECIPE    pRecipe;
    3072     /** Set for ignoring recipes without targets (Sun OS 4 Make). */
     3091    /** Set for ignoring recipes without targets (SunOS 4 Make). */
    30733092    uint8_t             fNoTargetRecipe;
    30743093    /** The command prefix character. */
     
    31413160}
    31423161
     3162
     3163/**
     3164 * Translates a makefile source pointer to a line number and offset.
     3165 *
     3166 * @returns Line number (1-based)
     3167 * @param   pCompiler   The compiler state.
     3168 * @param   pszWhere    There location to translate.
     3169 * @param   piColumn    Where to return the line offset (1-based).
     3170 */
     3171static unsigned kmk_cc_eval_translate_location(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, unsigned *piColumn)
     3172{
     3173    unsigned iLine   = pCompiler->iLine;
     3174    size_t   offLine = pCompiler->offLine;
     3175    size_t   off     = pchWhere - pCompiler->pszContent;
     3176    unsigned i       = 0;
     3177    while (   i   < pCompiler->cEscEols
     3178           && off > pCompiler->paEscEols[i].offEol)
     3179    {
     3180        offLine = pCompiler->paEscEols[i].offEol + 1 + pCompiler->cchEolSeq;
     3181        iLine++;
     3182        i++;
     3183    }
     3184    KMK_CC_ASSERT(off <= pCompiler->cchContent);
     3185    if (piColumn)
     3186        *piColumn = (unsigned)(off - offLine) + 1;
     3187    return iLine;
     3188}
     3189
     3190
    31433191static void KMK_CC_FN_NO_RETURN kmk_cc_eval_fatal(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...)
    31443192{
    31453193    va_list  va;
    3146     unsigned iLine = pCompiler->iLine;
    3147 
    31483194    log_working_directory(1);
    31493195
     
    31533199    if (pchWhere)
    31543200    {
    3155         size_t   offLine = pCompiler->offLine;
    3156         size_t   off     = pchWhere - pCompiler->pszContent;
    3157         unsigned i       = 0;
    3158         while (   i   < pCompiler->cEscEols
    3159                && off > pCompiler->paEscEols[i].offEol)
    3160         {
    3161             offLine = pCompiler->paEscEols[i].offEol + 1 + pCompiler->cchEolSeq;
    3162             iLine++;
    3163             i++;
    3164         }
    3165         KMK_CC_ASSERT(off <= pCompiler->cchContent);
     3201        unsigned iColumn;
     3202        unsigned iLine = kmk_cc_eval_translate_location(pCompiler, pchWhere, &iColumn);
    31663203
    31673204        if (pCompiler->pEvalProg->pszVarName)
    31683205            fprintf(stderr, "%s:%u:%u: *** fatal parsing error in %s: ",
    3169                     pCompiler->pEvalProg->pszFilename, iLine, (unsigned)(off - offLine), pCompiler->pEvalProg->pszVarName);
     3206                    pCompiler->pEvalProg->pszFilename, iLine, iColumn, pCompiler->pEvalProg->pszVarName);
    31703207        else
    31713208            fprintf(stderr, "%s:%u:%u: *** fatal parsing error: ",
    3172                     pCompiler->pEvalProg->pszFilename, iLine, (unsigned)(off - offLine));
     3209                    pCompiler->pEvalProg->pszFilename, iLine, iColumn);
    31733210    }
    31743211    else if (pCompiler->pEvalProg->pszVarName)
    31753212        fprintf(stderr, "%s:%u: *** fatal parsing error in %s: ",
    3176                 pCompiler->pEvalProg->pszFilename, iLine, pCompiler->pEvalProg->pszVarName);
     3213                pCompiler->pEvalProg->pszFilename, pCompiler->iLine, pCompiler->pEvalProg->pszVarName);
    31773214    else
    31783215        fprintf(stderr, "%s:%u: *** fatal parsing error: ",
    3179                 pCompiler->pEvalProg->pszFilename, iLine);
     3216                pCompiler->pEvalProg->pszFilename, pCompiler->iLine);
    31803217
    31813218    /*
     
    32063243static void kmk_cc_eval_warn(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...)
    32073244{
    3208     /** @todo warnings.   */
    3209     (void)pchWhere;
    3210     (void)pCompiler;
    3211     (void)pszMsg;
     3245    va_list  va;
     3246
     3247    log_working_directory(1);
     3248
     3249    /*
     3250     * If we have a pointer location, use it to figure out the exact line and column.
     3251     */
     3252    if (pchWhere)
     3253    {
     3254        unsigned iColumn;
     3255        unsigned iLine = kmk_cc_eval_translate_location(pCompiler, pchWhere, &iColumn);
     3256
     3257        if (pCompiler->pEvalProg->pszVarName)
     3258            fprintf(stderr, "%s:%u:%u: *** warning in %s: ",
     3259                    pCompiler->pEvalProg->pszFilename, iLine, iColumn, pCompiler->pEvalProg->pszVarName);
     3260        else
     3261            fprintf(stderr, "%s:%u:%u: *** warning: ",
     3262                    pCompiler->pEvalProg->pszFilename, iLine, iColumn);
     3263    }
     3264    else if (pCompiler->pEvalProg->pszVarName)
     3265        fprintf(stderr, "%s:%u: *** warning in %s: ",
     3266                pCompiler->pEvalProg->pszFilename, pCompiler->iLine, pCompiler->pEvalProg->pszVarName);
     3267    else
     3268        fprintf(stderr, "%s:%u: *** warning: ",
     3269                pCompiler->pEvalProg->pszFilename, pCompiler->iLine);
     3270
     3271    /*
     3272     * Print the message.
     3273     */
     3274    va_start(va, pszMsg);
     3275    vfprintf(stderr, pszMsg, va);
     3276    va_end(va);
     3277    fputs(".\n", stderr);
    32123278}
    32133279
     
    32823348        {
    32833349            paDst[i].fSubprog    = 1;
     3350            kmk_cc_block_realign(pCompiler->ppBlockTail);
    32843351            kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, paSrc[i].cchWord, &paDst[i].u.Subprog);
    32853352        }
     
    33133380# define KMK_CC_WORD_COMP_CONST_6(a_pchLine, a_pszWord) \
    33143381        (   *(uint32_t const *)(a_pchLine)     == *(uint32_t const *)(a_pszWord) \
    3315          && ((uint16_t const *)(a_pchLine))[2] == ((uint32_t const *)(a_pszWord))[2] )
     3382         && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] )
    33163383# define KMK_CC_WORD_COMP_CONST_7(a_pchLine, a_pszWord) \
    33173384        (   *(uint32_t const *)(a_pchLine)     == *(uint32_t const *)(a_pszWord) \
    3318          && ((uint16_t const *)(a_pchLine))[2] == ((uint32_t const *)(a_pszWord))[2] \
     3385         && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] \
    33193386         && (a_pchLine)[6]                     == (a_pszWord)[6] )
    33203387# define KMK_CC_WORD_COMP_CONST_8(a_pchLine, a_pszWord) \
     
    41314198            unsigned cEnsureWords = ((a_cRequiredWords) + 3 /*15*/) & ~(unsigned)3/*15*/; \
    41324199            KMK_CC_ASSERT((a_cRequiredWords) < 0x8000); \
    4133             (a_pCompiler)->paWords = (PKMKCCEVALWORD)xmalloc(cEnsureWords * sizeof((a_pCompiler)->paWords)[0]); \
     4200            (a_pCompiler)->paWords = (PKMKCCEVALWORD)xrealloc((a_pCompiler)->paWords, \
     4201                                                              cEnsureWords * sizeof((a_pCompiler)->paWords)[0]); \
    41344202        } \
    41354203    } while (0)
     4204
     4205
     4206/**
     4207 * Word parser helper function for dealing with dollars, simple variant that
     4208 * doesn't need to take multiple lines into account.
     4209 *
     4210 * @returns New word length placing us after the
     4211 * @param   pCompiler   The compiler state.
     4212 * @param   cchWord     Offset of the dollar into pchWord.
     4213 * @param   pchWord     The word we're currently parsing.
     4214 * @param   cchLeft     How much we've got left to parse.
     4215 */
     4216K_INLINE size_t kmk_cc_eval_parse_along_dollar_simple(PKMKCCEVALCOMPILER pCompiler, size_t cchWord,
     4217                                                      const char *pchWord, size_t cchLeft)
     4218{
     4219    const size_t cchStart = cchWord;
     4220    cchWord++;
     4221    if (cchWord < cchLeft)
     4222    {
     4223        /*
     4224         * Got a $(VAR) or ${VAR} to deal with here.  This may include nested variable
     4225         * references and span multiple lines (at least for function calls).
     4226         *
     4227         * We scan forward till we've found the corresponding closing parenthesis,
     4228         * considering any open parentheses of the same kind as worth counting, even
     4229         * if there are no dollar preceeding them, just like GNU make does.
     4230         *
     4231         * We leave the other parenthesis type to the expansion compiler to deal with.
     4232         */
     4233        unsigned   cOpens = 1;
     4234        char const chOpen = pchWord[cchWord++];
     4235        if (chOpen == '(')
     4236        {
     4237            for (;;)
     4238            {
     4239                if (cchWord < cchLeft)
     4240                {
     4241                    char const ch = pchWord[cchWord++];
     4242                    if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))
     4243                    { /* likely */ }
     4244                    else if (ch == ')')
     4245                    {
     4246                        if (--cOpens == 0)
     4247                            return cchWord;
     4248                    }
     4249                    else if (ch == '(')
     4250                       cOpens++;
     4251                }
     4252                else
     4253                    break;
     4254            }
     4255        }
     4256        else if (chOpen == '{')
     4257        {
     4258            for (;;)
     4259            {
     4260                if (cchWord < cchLeft)
     4261                {
     4262                    char const ch = pchWord[cchWord++];
     4263                    if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))
     4264                    { /* likely */ }
     4265                    else if (ch == '}')
     4266                    {
     4267                        if (--cOpens == 0)
     4268                            return cchWord;
     4269                    }
     4270                    else if (ch == '{')
     4271                       cOpens++;
     4272                }
     4273                else
     4274                    break;
     4275            }
     4276        }
     4277        else
     4278            return cchWord;
     4279
     4280        /* Unterminated. */
     4281        if (cOpens == 1)
     4282            kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart],
     4283                              "Variable reference is missing '%c'", chOpen == '(' ? ')' : '}');
     4284        else
     4285            kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart],
     4286                              "%u variable references are missing '%c'", cOpens, chOpen == '(' ? ')' : '}');
     4287    }
     4288    else
     4289        kmk_cc_eval_warn(pCompiler, &pchWord[cchWord - 1], "found '$' at end of line");
     4290    return cchWord;
     4291}
     4292
     4293
     4294/**
     4295 * Word parser helper function for dealing with dollars, complicated variant
     4296 * that takes escaped EOLs into account.
     4297 *
     4298 * @returns New word length placing us after the
     4299 * @param   pCompiler   The compiler state.
     4300 * @param   cchWord     Offset of the dollar into pchWord.
     4301 * @param   pchWord     The word we're currently parsing.
     4302 * @param   cchLeft     How much we've got left to parse.
     4303 */
     4304static size_t kmk_cc_eval_parse_along_dollar_esc_eol(PKMKCCEVALCOMPILER pCompiler, size_t cchWord,
     4305                                                     const char *pchWord, size_t cchLeft)
     4306{
     4307    const size_t cchStart = cchWord;
     4308    cchWord++;
     4309    if (cchWord < cchLeft)
     4310    {
     4311        /*
     4312         * Got a $(VAR) or ${VAR} to deal with here.  This may include nested variable
     4313         * references and span multiple lines (at least for function calls).
     4314         *
     4315         * We scan forward till we've found the corresponding closing parenthesis,
     4316         * considering any open parentheses of the same kind as worth counting, even
     4317         * if there are no dollar preceeding them, just like GNU make does.
     4318         *
     4319         * We leave the other parenthesis type to the expansion compiler to deal with.
     4320         */
     4321        unsigned   cOpens = 1;
     4322        char const chOpen = pchWord[cchWord++];
     4323        if (chOpen == '(')
     4324        {
     4325            for (;;)
     4326            {
     4327                if (cchWord < cchLeft)
     4328                {
     4329                    char const ch = pchWord[cchWord++];
     4330                    if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))
     4331                    { /* likely */ }
     4332                    else if (ch == ')')
     4333                    {
     4334                        if (--cOpens == 0)
     4335                            return cchWord;
     4336                    }
     4337                    else if (ch == '(')
     4338                       cOpens++;
     4339                    else if (ch == '\\')
     4340                    {
     4341                        unsigned const iEscEol = pCompiler->iEscEol;
     4342                        if (   iEscEol < pCompiler->cEscEols
     4343                            && (size_t)(&pchWord[cchWord] - pCompiler->pszContent) == pCompiler->paEscEols[iEscEol].offEsc)
     4344                        {
     4345                            cchWord += pCompiler->paEscEols[iEscEol].offEol
     4346                                     - pCompiler->paEscEols[iEscEol].offEsc
     4347                                     + pCompiler->cchEolSeq;
     4348                            pCompiler->iEscEol = iEscEol + 1;
     4349                        }
     4350                    }
     4351                }
     4352                else
     4353                    break;
     4354            }
     4355        }
     4356        else if (chOpen == '{')
     4357        {
     4358            for (;;)
     4359            {
     4360                if (cchWord < cchLeft)
     4361                {
     4362                    char const ch = pchWord[cchWord++];
     4363                    if (!KMK_CC_EVAL_IS_PAREN_OR_SLASH(ch))
     4364                    { /* likely */ }
     4365                    else if (ch == '}')
     4366                    {
     4367                        if (--cOpens == 0)
     4368                            return cchWord;
     4369                    }
     4370                    else if (ch == '{')
     4371                       cOpens++;
     4372                    else if (ch == '\\')
     4373                    {
     4374                        unsigned const iEscEol = pCompiler->iEscEol;
     4375                        if (   iEscEol < pCompiler->cEscEols
     4376                            && (size_t)(&pchWord[cchWord] - pCompiler->pszContent) == pCompiler->paEscEols[iEscEol].offEsc)
     4377                        {
     4378                            cchWord += pCompiler->paEscEols[iEscEol].offEol
     4379                                     - pCompiler->paEscEols[iEscEol].offEsc
     4380                                     + pCompiler->cchEolSeq;
     4381                            pCompiler->iEscEol = iEscEol + 1;
     4382                        }
     4383                    }
     4384                }
     4385                else
     4386                    break;
     4387            }
     4388        }
     4389        else
     4390            return cchWord;
     4391
     4392        /* Unterminated. */
     4393        if (cOpens == 1)
     4394            kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart],
     4395                              "Variable reference is missing '%c'", chOpen == '(' ? ')' : '}');
     4396        else
     4397            kmk_cc_eval_fatal(pCompiler, &pchWord[cchStart],
     4398                              "%u variable references are missing '%c'", cOpens, chOpen == '(' ? ')' : '}');
     4399    }
     4400    else
     4401        kmk_cc_eval_warn(pCompiler, &pchWord[cchWord - 1], "found '$' at end of line");
     4402    return cchWord;
     4403}
     4404
    41364405
    41374406/**
     
    41684437        {
    41694438            size_t          cchSkipAfter = 0;
    4170             size_t          cchWord      = 1;
     4439            size_t          cchWord      = 0;
    41714440            KMKCCEVALTOKEN  enmToken     = kKmkCcEvalToken_WordPlain;
    41724441
     
    41764445                char ch = pchWord[cchWord];
    41774446                if (!KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(ch))
    4178                 { /* likely */ }
     4447                    cchWord++;
    41794448                else if (ch == '$')
     4449                {
    41804450                    enmToken = kKmkCcEvalToken_WordWithDollar;
     4451                    cchWord = kmk_cc_eval_parse_along_dollar_simple(pCompiler, cchWord, pchWord, cchLeft);
     4452                }
    41814453                else
    41824454                    break;
    4183                 cchWord++;
    41844455            }
    41854456
     
    42074478        {
    42084479            size_t          cchSkipAfter = 0;
    4209             size_t          cchWord      = 1;
     4480            size_t          cchWord      = 0;
    42104481            KMKCCEVALTOKEN  enmToken     = kKmkCcEvalToken_WordPlain;
    42114482
     
    42154486                char ch = pchWord[cchWord];
    42164487                if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch))
    4217                 { /* likely */ }
     4488                    cchWord++;
    42184489                else if (ch == '$')
     4490                {
    42194491                    enmToken = kKmkCcEvalToken_WordWithDollar;
     4492                    cchWord = kmk_cc_eval_parse_along_dollar_esc_eol(pCompiler, cchWord, pchWord, cchLeft);
     4493                }
    42204494                else if (ch != '\\')
    42214495                    break;
    4222                 else if ((size_t)(&pchWord[cchWord] - pszContent) == pCompiler->paEscEols[iEscEol].offEsc)
     4496                else if ((size_t)(&pchWord[cchWord] - pszContent) != pCompiler->paEscEols[iEscEol].offEsc)
     4497                    cchWord++;
     4498                else
    42234499                {
    42244500                    cchSkipAfter = pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc
     
    42274503                    break;
    42284504                }
    4229                 cchWord++;
     4505            }
     4506
     4507            /* Add the word. */
     4508            KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1);
     4509            pCompiler->paWords[cWords].pchWord  = pchWord;
     4510            pCompiler->paWords[cWords].cchWord  = cchWord;
     4511            pCompiler->paWords[cWords].enmToken = enmToken;
     4512            cWords++;
     4513
     4514            /* Skip the work and any trailing blanks. */
     4515            cchWord += cchSkipAfter;
     4516            pchWord += cchWord;
     4517            cchLeft -= cchWord;
     4518            KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4519        } while (cchLeft > 0);
     4520    }
     4521    pCompiler->cWords = cWords;
     4522    return cWords;
     4523}
     4524
     4525
     4526/**
     4527 * Parses the remainder of the line into target words.
     4528 *
     4529 * The resulting words are classified as either kKmkCcEvalToken_WordPlain or
     4530 * kKmkCcEvalToken_WordWithDollar.
     4531 *
     4532 * @returns Number of words.
     4533 * @param   pCompiler   The compiler state.
     4534 * @param   pchWord     Where to start, we expect this to be at a word.
     4535 * @param   cchLeft     The number of chars left to parse on this line.
     4536 *                      This is expected to be non-zero.
     4537 */
     4538static unsigned kmk_cc_eval_parse_recipe_words(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft)
     4539{
     4540    unsigned iEscEol  = pCompiler->iEscEol;
     4541    unsigned cEscEols = pCompiler->cEscEols;
     4542    unsigned cWords   = 0;
     4543
     4544    /* Precoditions. */
     4545    KMK_CC_ASSERT(cchLeft > 0);
     4546    KMK_CC_ASSERT(!KMK_CC_EVAL_IS_SPACE(*pchWord));
     4547
     4548    /*
     4549     * If we don't have to deal with escaped EOLs, the find-end-of word search
     4550     * becomes a little bit simpler.  Since this function will be used a lot
     4551     * for simple lines with single words, this could maybe save a nano second
     4552     * or two.
     4553     */
     4554    if (iEscEol >= cEscEols)
     4555    {
     4556        do
     4557        {
     4558            size_t          cchSkipAfter = 0;
     4559            size_t          cchWord      = 0;
     4560            KMKCCEVALTOKEN  enmToken     = kKmkCcEvalToken_WordPlain;
     4561
     4562            /* Find the end of the current word. */
     4563            while (cchWord < cchLeft)
     4564            {
     4565                char ch = pchWord[cchWord];
     4566                if (!KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(ch))
     4567                    cchWord++;
     4568                else if (ch == '$')
     4569                {
     4570                    enmToken = kKmkCcEvalToken_WordWithDollar;
     4571                    cchWord = kmk_cc_eval_parse_along_dollar_simple(pCompiler, cchWord, pchWord, cchLeft);
     4572                }
     4573                else
     4574                    break;
     4575            }
     4576
     4577            /* Add the word. */
     4578            KMK_CC_EVAL_ENSURE_WORDS(pCompiler, cWords + 1);
     4579            pCompiler->paWords[cWords].pchWord  = pchWord;
     4580            pCompiler->paWords[cWords].cchWord  = cchWord;
     4581            pCompiler->paWords[cWords].enmToken = enmToken;
     4582            cWords++;
     4583
     4584            /* Skip the work and any trailing blanks. */
     4585            cchWord += cchSkipAfter;
     4586            pchWord += cchWord;
     4587            cchLeft -= cchWord;
     4588            KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
     4589        } while (cchLeft > 0);
     4590    }
     4591    /*
     4592     * Have to deal with escaped EOLs.
     4593     */
     4594    else
     4595    {
     4596        const char *pszContent = pCompiler->pszContent;
     4597        do
     4598        {
     4599            size_t          cchSkipAfter = 0;
     4600            size_t          cchWord      = 0;
     4601            KMKCCEVALTOKEN  enmToken     = kKmkCcEvalToken_WordPlain;
     4602
     4603            /* Find the end of the current word. */
     4604            while (cchWord < cchLeft)
     4605            {
     4606                char ch = pchWord[cchWord];
     4607                if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch))
     4608                    cchWord++;
     4609                else if (ch == '$')
     4610                {
     4611                    enmToken = kKmkCcEvalToken_WordWithDollar;
     4612                    cchWord = kmk_cc_eval_parse_along_dollar_esc_eol(pCompiler, cchWord, pchWord, cchLeft);
     4613                }
     4614                else if (ch != '\\')
     4615                    break;
     4616                else if ((size_t)(&pchWord[cchWord] - pszContent) != pCompiler->paEscEols[iEscEol].offEsc)
     4617                    cchWord++;
     4618                else
     4619                {
     4620                    cchSkipAfter = pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc
     4621                                 + pCompiler->cchEolSeq;
     4622                    iEscEol++;
     4623                    break;
     4624                }
    42304625            }
    42314626
     
    47885183            pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_dynamic : kKmkCcEvalInstr_ifndef_dynamic;
    47895184            pInstr->IfCore.Core.iLine     = pCompiler->iLine;
     5185            pInstr->uPadding              = 0;
    47905186            kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->NameSubprog);
    47915187
     
    53345730
    53355731
     5732/**
     5733 * Called when any previous recipe must have ended and can be finalized.
     5734 *
     5735 * This occurs when encountering an assignement, a new recipe or the end of the
     5736 * complication unit.
     5737 *
     5738 * @param   pCompiler   The compiler state.
     5739 */
     5740static void kmk_cc_eval_end_of_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pchWord)
     5741{
     5742    if (pCompiler->pRecipe)
     5743    {
     5744        /** @todo do stuff here. */
     5745        kmk_cc_eval_fatal(pCompiler, pchWord, "end-of-recipe handling not implemented yet");
     5746    }
     5747}
     5748
     5749
    53365750static void kmk_cc_eval_handle_command(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft)
    53375751{
     
    53405754
    53415755
     5756/**
     5757 * Pick up the recipe parsing at the colon.
     5758 *
     5759 * @returns 1 to indicate we've handled a keyword (see
     5760 *          kmk_cc_eval_try_handle_keyword).
     5761 * @param   pCompiler   The compiler state.
     5762 * @param   pchWord0    The first word.
     5763 * @param   cchWord0    The length of the first word.
     5764 * @param   enmToken0   The classification of the first word.
     5765 * @param   pchColon    The colon.
     5766 * @param   cchLeft     How much is left, starting at the colon.
     5767 */
    53425768static int kmk_cc_eval_handle_recipe_cont_colon(PKMKCCEVALCOMPILER pCompiler, const char *pchWord0, size_t cchWord0,
    5343                                                 const char *pchColon, size_t cchLeft, unsigned fQualifiers)
     5769                                                KMKCCEVALTOKEN enmToken0, const char *pchColon, size_t cchLeft)
    53445770{
    53455771    kmk_cc_eval_fatal(pCompiler, pchWord0, "recipe handling not implemented yet (#1)");
     
    53485774
    53495775
     5776/**
     5777 * Pick up the recipe parsing at the 2nd word (after it was determined not to be
     5778 * an assignment operator after all).
     5779 *
     5780 * @returns 1 to indicate we've handled a keyword (see
     5781 *          kmk_cc_eval_try_handle_keyword).
     5782 * @param   pCompiler   The compiler state.
     5783 * @param   pchWord0    The first word.
     5784 * @param   cchWord0    The length of the first word.
     5785 * @param   pchWord     Where to continue parsing.
     5786 * @param   cchLeft     How much is left to parse.
     5787 */
    53505788static int kmk_cc_eval_handle_recipe_cont_2nd_word(PKMKCCEVALCOMPILER pCompiler, const char *pchWord0, size_t cchWord0,
    5351                                                    const char *pchWord, size_t cchLeft, unsigned fQualifiers)
    5352 {
     5789                                                   const char *pchWord, size_t cchLeft)
     5790{
     5791//    const char *pchColon = memchr()
     5792
    53535793    kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#2)");
    53545794    return 1;
     
    53565796
    53575797
    5358 static void kmk_cc_eval_handle_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pszEqual, const char *pchWord, size_t cchLeft)
    5359 {
    5360     kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#3)");
    5361 }
    5362 
    5363 static void kmk_cc_eval_end_of_recipe(PKMKCCEVALCOMPILER pCompiler)
    5364 {
    5365     if (pCompiler->pRecipe)
    5366     {
    5367         /** @todo do stuff here. */
    5368     }
    5369 }
     5798static void kmk_cc_eval_handle_recipe(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft)
     5799{
     5800    const char *pszColon = NULL;//memchr(pchWord, cchLeft);
     5801    if (pszColon)
     5802    {
     5803
     5804
     5805        kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#3)");
     5806    }
     5807    else if (pchWord[0] == '$')
     5808    {
     5809
     5810    }
     5811    else
     5812        kmk_cc_eval_fatal(pCompiler, pchWord,
     5813                          "Not variable assignment. Could be a complicated indirect recipe definition, however that's currently not supported.");
     5814
     5815}
     5816
    53705817
    53715818
     
    53925839         */
    53935840        unsigned cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft);
     5841#ifdef KMK_CC_EVAL_LOGGING_ENABLED
     5842        unsigned iWord;
    53945843        KMK_CC_EVAL_DPRINTF(("%s: cWords=%d\n", g_apszEvalInstrNms[enmOpcode], cWords));
     5844        for (iWord = 0; iWord < cWords; iWord++)
     5845            KMK_CC_EVAL_DPRINTF(("  word[%u]: len=%#05x t=%d '%*.*s'\n", iWord, (int)pCompiler->paWords[iWord].cchWord,
     5846                                 (int)pCompiler->paWords[iWord].enmToken, (int)pCompiler->paWords[iWord].cchWord,
     5847                                 (int)pCompiler->paWords[iWord].cchWord, pCompiler->paWords[iWord].pchWord));
     5848#endif
    53955849        if (cWords)
    53965850        {
     
    53995853            pInstr->Core.enmOpcode = enmOpcode;
    54005854            pInstr->Core.iLine     = pCompiler->iLine;
    5401             pInstr->cVars         = cWords;
     5855            pInstr->cVars          = cWords;
    54025856            kmk_cc_eval_init_spp_array_from_duplicated_words(pCompiler, cWords, pCompiler->paWords, pInstr->aVars);
    54035857            kmk_cc_block_realign(pCompiler->ppBlockTail);
     
    54875941static int kmk_cc_eval_do_var_define(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers)
    54885942{
    5489 
    54905943    KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft);
    54915944    kmk_cc_eval_fatal(pCompiler, pchWord, "define handling not implemented yet");
     5945    return 1;
     5946}
     5947
     5948
     5949/**
     5950 * Emits a 'expand(-and-eval)' instruction.
     5951 *
     5952 * @returns 1 to indicate we've handled a keyword (see
     5953 *          kmk_cc_eval_try_handle_keyword).
     5954 * @param   pCompiler   The compiler state.
     5955 * @param   pchSubprog  The subprogram that needs expanding.
     5956 * @param   cchSubprog  The length of the subprogram.
     5957 * @param   iEscEol     The escaped EOL index corresponding to pchSubprog.
     5958 */
     5959static int kmk_cc_eval_emit_expand(PKMKCCEVALCOMPILER pCompiler, const char *pchSubprog, size_t cchSubprog, unsigned iEscEolVarNm)
     5960{
     5961    /*
     5962     * We're unexporting all variables.
     5963     */
     5964    size_t           cchCopy;
     5965    char            *pszCopy;
     5966    PKMKCCEVALEXPAND pInstr;
     5967
     5968    pCompiler->iEscEol = iEscEolVarNm;
     5969    cchCopy = kmk_cc_eval_prep_normal_line_ex(pCompiler, pchSubprog, cchSubprog);
     5970    pszCopy = kmk_cc_eval_strdup_prepped(pCompiler, cchCopy);
     5971    kmk_cc_block_realign(pCompiler->ppBlockTail);
     5972
     5973    pInstr = (PKMKCCEVALEXPAND)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     5974    pInstr->Core.enmOpcode = kKmkCcEvalInstr_expand;
     5975    pInstr->Core.iLine     = pCompiler->iLine;
     5976    pInstr->uPadding       = 0;
     5977    /** @todo Make the subprogram embed necessary strings. */
     5978    kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->Subprog);
     5979
    54925980    return 1;
    54935981}
     
    55085996    size_t          cchVarNm;
    55095997    size_t          cch = 0;
     5998    size_t          cchSubprog = 0;
    55105999    char            ch;
    55116000
     
    55206009        { /*likely*/ }
    55216010        else
    5522             kmk_cc_eval_fatal(pCompiler, &pchWord[cch], "Neither recipe nor variable assignment");
     6011        {
     6012            /* Single word, join paths with word + whitespace. */
     6013            KMK_CC_ASSERT(cch == cchLeft);
     6014            cchVarNm = cch;
     6015            pchWord += cch;
     6016            cchLeft -= cch;
     6017            break;
     6018        }
    55236019
    55246020        ch = pchWord[cch];
     
    55376033        else if (ch == '$')
    55386034        {
     6035            size_t const offStart = cch;
    55396036            cch++;
    55406037            if (cch < cchLeft)
     
    56026099                kmk_cc_eval_fatal(pCompiler, &pchWord[cch], "Neither recipe nor variable assignment");
    56036100            fPlainVarNm = 0;
     6101            cchSubprog += cch - offStart;
    56046102        }
    5605         /* Check out potential recipe. */
     6103        /* Check out potential recipe, simple assignment or DOS drive letter separator. */
    56066104        else if (ch == ':')
    56076105        {
     
    56186116                    C:/Windows/System32/Kernel32.dll: C:/Windows/System32/NtDll.dll
    56196117               for a recipe, it is only the second one which counts. */
    5620             else if (   cch == 1
    5621                      && isalpha((unsigned char)pchWord[0]))
     6118            if (   cch == 1
     6119                && isalpha((unsigned char)pchWord[0]))
    56226120                cch++;
     6121            else
    56236122#endif
    5624             else
    5625                 return kmk_cc_eval_handle_recipe_cont_colon(pCompiler, pchWord, cch, pchWord + cch, cchLeft - cch, fQualifiers);
     6123            if (!fQualifiers)
     6124                return kmk_cc_eval_handle_recipe_cont_colon(pCompiler, pchWord, cch,
     6125                                                            fPlainVarNm
     6126                                                            ? kKmkCcEvalToken_WordPlain : kKmkCcEvalToken_WordWithDollar,
     6127                                                            pchWord + cch, cchLeft - cch);
     6128            /** @todo we may have words already preparsed here so restarting is easy...  */
     6129            return 0; /* retry with preceeding keywords */
    56266130        }
    56276131        /* Check out assignment operator. */
    56286132        else if (ch == '=')
    56296133        {
    5630             if (cch)
     6134            if (cch > 0)
    56316135            {
    56326136                char chPrev = pchWord[cch - 1];
     
    56386142                break;
    56396143            }
    5640             else
    5641                 kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name.");
     6144            kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name.");
    56426145        }
    56436146        /* Check out potential escaped EOL sequence. */
     
    56976200            else if (ch == '?')
    56986201                enmOpCode = kKmkCcEvalInstr_assign_if_new;
     6202            else if (!fQualifiers)
     6203                return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft);
    56996204            else
    5700                 return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft, fQualifiers);
     6205                return 0; /* retry without preceding keywords */
    57016206            pchWord += 2;
    57026207            cchLeft -= 2;
    57036208        }
     6209        else if (!fQualifiers)
     6210            return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft);
    57046211        else
    5705             return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft, fQualifiers);
     6212            return 0; /* retry without preceding keywords */
    57066213
    57076214        /*
     
    57126219        fPlainValue = memchr(pchWord, '$', cchLeft) == NULL;
    57136220
    5714 
    57156221        /*
    57166222         * Emit the instruction.
    57176223         */
    5718         kmk_cc_eval_end_of_recipe(pCompiler);
     6224        kmk_cc_eval_end_of_recipe(pCompiler, pchWord);
    57196225
    57206226        pInstr = (PKMKCCEVALASSIGN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr));
     
    57456251        pInstr->pNext = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail);
    57466252    }
     6253    /*
     6254     * This could be one or more function calls.
     6255     */
     6256    else if (!fPlainVarNm && cchVarNm == cchSubprog && fQualifiers == 0)
     6257        return kmk_cc_eval_emit_expand(pCompiler, pchVarNm, cchVarNm, iEscEolVarNm);
     6258    else if (!fPlainVarNm)
     6259        kmk_cc_eval_fatal(pCompiler, pchWord,
     6260                          "Not variable assignment. Could be a complicated indirect recipe definition, however that's currently not supported.");
    57476261    else
    57486262        kmk_cc_eval_fatal(pCompiler, pchWord, "Neither recipe nor variable assignment");
     
    61816695                    if (pszContent[offNext] == '#')
    61826696                    {
    6183                         KMK_CC_EVAL_DPRINTF(("#%03u: <comment>\n", Compiler.iLine));
     6697                        KMK_CC_EVAL_DPRINTF(("#%03u: <comment-col-0>\n", Compiler.iLine));
    61846698                        Compiler.iLine++;
    61856699                        offNext = pchTmp - pszContent;
     
    63326846                    char        ch;
    63336847
    6334                     Compiler.cchLineWithComments =  cchLine;
     6848                    Compiler.cchLineWithComments = cchLine;
    63356849                    pchTmp = (const char *)memchr(pchWord, '#', cchLeft);
    63366850                    if (pchTmp)
     
    63416855                    Compiler.cchLine = cchLine;
    63426856                    Compiler.offLine = off;
     6857
     6858#ifdef KMK_CC_STRICT
     6859                    Compiler.cWords = 0x424242;
     6860#endif
    63436861
    63446862                    /*
     
    63556873                            kmk_cc_eval_handle_assignment_or_recipe(&Compiler, pchWord, cchLeft, 0 /*fQualifiers*/);
    63566874                        else
    6357                             kmk_cc_eval_handle_recipe(&Compiler, pchTmp, pchWord, cchLeft);
     6875                            kmk_cc_eval_handle_recipe(&Compiler, pchWord, cchLeft);
    63586876                    }
    63596877                    /* else: handled a keyword expression */
     
    64726990    if (!fstat(fileno(pFile), &st))
    64736991    {
    6474         if (   st.st_size > (off_t)16*1024*1024
     6992        if (   st.st_size > (off_t)KMK_CC_EVAL_MAX_COMPILE_SIZE
    64756993            && st.st_size < 0)
    6476             fatal(NULL, _("Makefile too large to compile: %ld bytes (%#lx) - max 16MB"), (long)st.st_size, (long)st.st_size);
     6994            fatal(NULL, _("Makefile too large to compile: %ld bytes (%#lx) - max %uMB"),
     6995                  (long)st.st_size, (long)st.st_size, KMK_CC_EVAL_MAX_COMPILE_SIZE / 1024 / 1024);
    64776996        cchContent = (size_t)st.st_size;
    64786997        pszContent = (char *)xmalloc(cchContent + 1);
     
    64887007        {
    64897008            cbAllocated *= 2;
    6490             if (cbAllocated > 16*1024*1024)
    6491                 fatal(NULL, _("Makefile too large to compile: max 16MB"));
     7009            if (cbAllocated > KMK_CC_EVAL_MAX_COMPILE_SIZE)
     7010                fatal(NULL, _("Makefile too large to compile: max %uMB"), KMK_CC_EVAL_MAX_COMPILE_SIZE / 1024 / 1024);
    64927011            pszContent = (char *)xrealloc(pszContent, cbAllocated);
    64937012            cchContent += fread(&pszContent[cchContent], 1, cbAllocated - 1 - cchContent, pFile);
     
    65327051    KMK_CC_ASSERT(pEvalProg);
    65337052    assert(0);
     7053
    65347054}
    65357055
  • trunk/src/kmk/kmk_cc_exec.h

    r2788 r3154  
    55
    66/*
    7  * Copyright (c) 2015 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
     7 * Copyright (c) 2015-2017 knut st. osmundsen <bird-kBuild-spam-xviiv@anduin.net>
    88 *
    99 * This file is part of kBuild.
     
    2424 */
    2525
    26 #ifndef ___kmk_cc_and_exech
    27 #define ___kmk_cc_and_exech
     26#ifndef ___kmk_cc_and_exec_h
     27#define ___kmk_cc_and_exec_h
    2828#ifdef CONFIG_WITH_COMPILER
    2929
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