Changeset 3154 in kBuild
- Timestamp:
- Mar 15, 2018 11:35:33 PM (7 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/Makefile.kmk
r3151 r3154 228 228 kmk_DEFS += CONFIG_WITH_COMPILE_EVERYTHING 229 229 endif 230 #ifeq ($(KBUILD_TYPE).$(USERNAME),debug.bird) 231 # kmk_DEFS += CONFIG_WITH_COMPILER CONFIG_WITH_EVAL_COMPILER CONFIG_WITH_COMPILE_EVERYTHING 232 #endif 230 233 231 234 kmk_SOURCES = \ -
trunk/src/kmk/kmk_cc_exec.c
r3140 r3154 6 6 7 7 /* 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> 9 9 * 10 10 * This file is part of kBuild. … … 132 132 #endif 133 133 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 134 143 135 144 /** @defgroup grp_kmk_cc_evalprog Makefile Evaluation 136 145 * @{ 137 146 */ 138 #if 1 147 #define KMK_CC_EVAL_LOGGING_ENABLED 148 #ifdef KMK_CC_EVAL_LOGGING_ENABLED 139 149 # define KMK_CC_EVAL_DPRINTF_UNPACK(...) __VA_ARGS__ 140 150 # define KMK_CC_EVAL_DPRINTF(a) fprintf(stderr, KMK_CC_EVAL_DPRINTF_UNPACK a) … … 150 160 #define KMK_CC_EVAL_QUALIFIER_PRIVATE 8 151 161 /** @} */ 162 163 /** Eval: Max makefile size we accept as input (in bytes). */ 164 #define KMK_CC_EVAL_MAX_COMPILE_SIZE (16*1024*1024) 152 165 153 166 /** Eval: Max nesting depth of makefile conditionals. … … 239 252 *********************************************************************************************************************************/ 240 253 /** 241 * Block of expandinstructions.254 * Block of instructions. 242 255 * 243 256 * To avoid wasting space on "next" pointers, as well as a lot of time walking … … 567 580 kKmkCcEvalInstr_undefine, 568 581 569 570 582 /** [else] ifdef variable - KMKCCEVALIFDEFPLAIN. */ 571 583 kKmkCcEvalInstr_ifdef_plain, … … 613 625 kKmkCcEvalInstr_recipe_cancel_pattern, 614 626 627 /** @todo target variables. */ 628 615 629 /** vpath pattern directories - KMKCCEVALVPATH. */ 616 630 kKmkCcEvalInstr_vpath, … … 619 633 /** vpath - KMKCCEVALCORE. */ 620 634 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, 621 642 622 643 /** The end of valid instructions (exclusive). */ … … 757 778 /** The 'if' core structure. */ 758 779 KMKCCEVALIFCORE IfCore; 780 /** Alignment padding, MBZ. */ 781 KU32 uPadding; 759 782 /** The subprogram that will give us the variable name. */ 760 783 KMKCCEXPSUBPROG NameSubprog; … … 862 885 /** First dependency. */ 863 886 uint16_t iFirstDep; 864 /** Number of ordinary depend necies. */887 /** Number of ordinary dependencies. */ 865 888 uint16_t cDeps; 866 889 /** First order only dependency. */ 867 890 uint16_t iFirstOrderOnlyDep; 868 /** Number of ordinary depend necies. */891 /** Number of ordinary dependencies. */ 869 892 uint16_t cOrderOnlyDeps; 870 893 … … 904 927 /** The core instruction. */ 905 928 KMKCCEVALCORE Core; 906 /** The number of search directories. */929 /** The number of commands. */ 907 930 uint32_t cCommands; 908 931 /** Pointer to the next instruction (subprogs and strings after this one). */ 909 932 PKMKCCEVALCORE pNext; 910 933 /** 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? */ 912 935 KMKCCEXPSUBPROGORPLAIN aCommands[1]; 913 936 } KMKCCEVALRECIPECOMMANDS; … … 938 961 /** Calculates the size of an KMKCCEVALVPATH structure for @a a_cFiles files. */ 939 962 #define KMKCCEVALVPATH_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aDirs, a_cDirs) 963 964 965 /** 966 * Instruction format for kKmkCcEvalInstr_expand. 967 */ 968 typedef 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; 977 typedef KMKCCEVALEXPAND *PKMKCCEVALEXPAND; 940 978 941 979 … … 1110 1148 for (i = 0; i < K_ELEMENTS(g_apszEvalKeywords); i++) 1111 1149 { 1150 #ifdef KMK_CC_STRICT 1112 1151 size_t cch = strlen(g_apszEvalKeywords[i]); 1113 1152 KMK_CC_ASSERT(cch >= KMK_CC_EVAL_KEYWORD_MIN); 1114 1153 KMK_CC_ASSERT(cch <= KMK_CC_EVAL_KEYWORD_MAX); 1154 #endif 1115 1155 1116 1156 KMK_CC_EVAL_BM_OR(g_abEvalCcChars, g_apszEvalKeywords[i][0], KMK_CC_EVAL_CH_1ST_IN_KEYWORD); … … 1370 1410 { 1371 1411 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)); 1375 1417 KMK_CC_ASSERT(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP)); 1376 1418 } … … 1400 1442 void *pvRet = (char *)pPrevBlock + pPrevBlock->offNext; 1401 1443 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)); 1402 1445 return pvRet; 1403 1446 } … … 1424 1467 #endif 1425 1468 1469 KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc_grow: %p LB %#x offNext=%#x\n", pNewBlock + 1, cb, pNewBlock->offNext)); 1426 1470 return pNewBlock + 1; 1427 1471 } … … 1447 1491 void *pvRet = (char *)pBlockTail + pBlockTail->offNext; 1448 1492 pBlockTail->offNext += cb; 1493 KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_byte_alloc: %p LB %#x offNext=%#x\n", pvRet, cb, pBlockTail->offNext)); 1449 1494 return pvRet; 1450 1495 } … … 1517 1562 KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock); 1518 1563 1564 KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_exp_grow: %p LB %#x offNext=%#x\n", pRet, cb, pNewBlock->offNext)); 1519 1565 return pRet; 1520 1566 } … … 1535 1581 KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP)); 1536 1582 KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 || cb == sizeof(KMKCCEXPCORE) /* final */ ); 1583 KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0); 1537 1584 1538 1585 if (cbLeft >= cb + sizeof(KMKCCEXPJUMP)) … … 1541 1588 pBlockTail->offNext += cb; 1542 1589 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)); 1543 1591 return pRet; 1544 1592 } … … 1586 1634 pOldBlock->offNext += sizeof(*pJump); 1587 1635 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)); 1589 1640 return pRet; 1590 1641 } … … 1605 1656 KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEVALJUMP)); 1606 1657 KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 ); 1658 KMK_CC_ASSERT((pBlockTail->offNext & (sizeof(void *) - 1)) == 0); 1607 1659 1608 1660 if (cbLeft >= cb + sizeof(KMKCCEVALJUMP)) … … 1610 1662 PKMKCCEVALCORE pRet = (PKMKCCEVALCORE)((char *)pBlockTail + pBlockTail->offNext); 1611 1663 pBlockTail->offNext += cb; 1664 KMK_CC_BLOCK_DPRINTF(("kmk_cc_block_alloc_eval: %p LB %#x offNext=%#x\n", pRet, cb, pBlockTail->offNext)); 1612 1665 return pRet; 1613 1666 } … … 2912 2965 2913 2966 2967 /** 2968 * Tokens (for KMKCCEVALWORD). 2969 */ 2914 2970 typedef enum kmk_cc_eval_token 2915 2971 { 2916 /** Invalid token . */2972 /** Invalid token value 0. */ 2917 2973 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,2967 2974 2968 2975 /** Plain word. */ … … 2971 2978 kKmkCcEvalToken_WordWithDollar, 2972 2979 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). */ 2973 2992 kKmkCcEvalToken_End 2974 2993 } KMKCCEVALTOKEN; … … 3036 3055 unsigned iEscEol; 3037 3056 3038 /** The current line number (for error handling / debugging). */3057 /** The current line number for error handling / debugging (1-based). */ 3039 3058 unsigned iLine; 3040 /** The start offset of the current line. */3059 /** The start offset (into pchContent) of the current line. */ 3041 3060 size_t offLine; 3042 3061 /** Length of the current line, sans the final EOL and comments. */ … … 3070 3089 /** Set if we're working on a recipe. */ 3071 3090 PKMKCCEVALRECIPE pRecipe; 3072 /** Set for ignoring recipes without targets (Sun 3091 /** Set for ignoring recipes without targets (SunOS 4 Make). */ 3073 3092 uint8_t fNoTargetRecipe; 3074 3093 /** The command prefix character. */ … … 3141 3160 } 3142 3161 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 */ 3171 static 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 3143 3191 static void KMK_CC_FN_NO_RETURN kmk_cc_eval_fatal(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...) 3144 3192 { 3145 3193 va_list va; 3146 unsigned iLine = pCompiler->iLine;3147 3148 3194 log_working_directory(1); 3149 3195 … … 3153 3199 if (pchWhere) 3154 3200 { 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); 3166 3203 3167 3204 if (pCompiler->pEvalProg->pszVarName) 3168 3205 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); 3170 3207 else 3171 3208 fprintf(stderr, "%s:%u:%u: *** fatal parsing error: ", 3172 pCompiler->pEvalProg->pszFilename, iLine, (unsigned)(off - offLine));3209 pCompiler->pEvalProg->pszFilename, iLine, iColumn); 3173 3210 } 3174 3211 else if (pCompiler->pEvalProg->pszVarName) 3175 3212 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); 3177 3214 else 3178 3215 fprintf(stderr, "%s:%u: *** fatal parsing error: ", 3179 pCompiler->pEvalProg->pszFilename, iLine);3216 pCompiler->pEvalProg->pszFilename, pCompiler->iLine); 3180 3217 3181 3218 /* … … 3206 3243 static void kmk_cc_eval_warn(PKMKCCEVALCOMPILER pCompiler, const char *pchWhere, const char *pszMsg, ...) 3207 3244 { 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); 3212 3278 } 3213 3279 … … 3282 3348 { 3283 3349 paDst[i].fSubprog = 1; 3350 kmk_cc_block_realign(pCompiler->ppBlockTail); 3284 3351 kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, paSrc[i].cchWord, &paDst[i].u.Subprog); 3285 3352 } … … 3313 3380 # define KMK_CC_WORD_COMP_CONST_6(a_pchLine, a_pszWord) \ 3314 3381 ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) \ 3315 && ((uint16_t const *)(a_pchLine))[2] == ((uint 32_t const *)(a_pszWord))[2] )3382 && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] ) 3316 3383 # define KMK_CC_WORD_COMP_CONST_7(a_pchLine, a_pszWord) \ 3317 3384 ( *(uint32_t const *)(a_pchLine) == *(uint32_t const *)(a_pszWord) \ 3318 && ((uint16_t const *)(a_pchLine))[2] == ((uint 32_t const *)(a_pszWord))[2] \3385 && ((uint16_t const *)(a_pchLine))[2] == ((uint16_t const *)(a_pszWord))[2] \ 3319 3386 && (a_pchLine)[6] == (a_pszWord)[6] ) 3320 3387 # define KMK_CC_WORD_COMP_CONST_8(a_pchLine, a_pszWord) \ … … 4131 4198 unsigned cEnsureWords = ((a_cRequiredWords) + 3 /*15*/) & ~(unsigned)3/*15*/; \ 4132 4199 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]); \ 4134 4202 } \ 4135 4203 } 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 */ 4216 K_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 */ 4304 static 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 4136 4405 4137 4406 /** … … 4168 4437 { 4169 4438 size_t cchSkipAfter = 0; 4170 size_t cchWord = 1;4439 size_t cchWord = 0; 4171 4440 KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; 4172 4441 … … 4176 4445 char ch = pchWord[cchWord]; 4177 4446 if (!KMK_CC_EVAL_IS_SPACE_OR_DOLLAR(ch)) 4178 { /* likely */ }4447 cchWord++; 4179 4448 else if (ch == '$') 4449 { 4180 4450 enmToken = kKmkCcEvalToken_WordWithDollar; 4451 cchWord = kmk_cc_eval_parse_along_dollar_simple(pCompiler, cchWord, pchWord, cchLeft); 4452 } 4181 4453 else 4182 4454 break; 4183 cchWord++;4184 4455 } 4185 4456 … … 4207 4478 { 4208 4479 size_t cchSkipAfter = 0; 4209 size_t cchWord = 1;4480 size_t cchWord = 0; 4210 4481 KMKCCEVALTOKEN enmToken = kKmkCcEvalToken_WordPlain; 4211 4482 … … 4215 4486 char ch = pchWord[cchWord]; 4216 4487 if (!KMK_CC_EVAL_IS_SPACE_DOLLAR_OR_SLASH(ch)) 4217 { /* likely */ }4488 cchWord++; 4218 4489 else if (ch == '$') 4490 { 4219 4491 enmToken = kKmkCcEvalToken_WordWithDollar; 4492 cchWord = kmk_cc_eval_parse_along_dollar_esc_eol(pCompiler, cchWord, pchWord, cchLeft); 4493 } 4220 4494 else if (ch != '\\') 4221 4495 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 4223 4499 { 4224 4500 cchSkipAfter = pCompiler->paEscEols[iEscEol].offEol - pCompiler->paEscEols[iEscEol].offEsc … … 4227 4503 break; 4228 4504 } 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 */ 4538 static 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 } 4230 4625 } 4231 4626 … … 4788 5183 pInstr->IfCore.Core.enmOpcode = fPositiveStmt ? kKmkCcEvalInstr_ifdef_dynamic : kKmkCcEvalInstr_ifndef_dynamic; 4789 5184 pInstr->IfCore.Core.iLine = pCompiler->iLine; 5185 pInstr->uPadding = 0; 4790 5186 kmk_cc_eval_compile_string_exp_subprog(pCompiler, pszCopy, cchCopy, &pInstr->NameSubprog); 4791 5187 … … 5334 5730 5335 5731 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 */ 5740 static 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 5336 5750 static void kmk_cc_eval_handle_command(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft) 5337 5751 { … … 5340 5754 5341 5755 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 */ 5342 5768 static 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) 5344 5770 { 5345 5771 kmk_cc_eval_fatal(pCompiler, pchWord0, "recipe handling not implemented yet (#1)"); … … 5348 5774 5349 5775 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 */ 5350 5788 static 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 5353 5793 kmk_cc_eval_fatal(pCompiler, pchWord, "recipe handling not implemented yet (#2)"); 5354 5794 return 1; … … 5356 5796 5357 5797 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 } 5798 static 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 5370 5817 5371 5818 … … 5392 5839 */ 5393 5840 unsigned cWords = kmk_cc_eval_parse_words(pCompiler, pchWord, cchLeft); 5841 #ifdef KMK_CC_EVAL_LOGGING_ENABLED 5842 unsigned iWord; 5394 5843 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 5395 5849 if (cWords) 5396 5850 { … … 5399 5853 pInstr->Core.enmOpcode = enmOpcode; 5400 5854 pInstr->Core.iLine = pCompiler->iLine; 5401 pInstr->cVars = cWords;5855 pInstr->cVars = cWords; 5402 5856 kmk_cc_eval_init_spp_array_from_duplicated_words(pCompiler, cWords, pCompiler->paWords, pInstr->aVars); 5403 5857 kmk_cc_block_realign(pCompiler->ppBlockTail); … … 5487 5941 static int kmk_cc_eval_do_var_define(PKMKCCEVALCOMPILER pCompiler, const char *pchWord, size_t cchLeft, unsigned fQualifiers) 5488 5942 { 5489 5490 5943 KMK_CC_EVAL_SKIP_SPACES_AFTER_WORD(pCompiler, pchWord, cchLeft); 5491 5944 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 */ 5959 static 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 5492 5980 return 1; 5493 5981 } … … 5508 5996 size_t cchVarNm; 5509 5997 size_t cch = 0; 5998 size_t cchSubprog = 0; 5510 5999 char ch; 5511 6000 … … 5520 6009 { /*likely*/ } 5521 6010 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 } 5523 6019 5524 6020 ch = pchWord[cch]; … … 5537 6033 else if (ch == '$') 5538 6034 { 6035 size_t const offStart = cch; 5539 6036 cch++; 5540 6037 if (cch < cchLeft) … … 5602 6099 kmk_cc_eval_fatal(pCompiler, &pchWord[cch], "Neither recipe nor variable assignment"); 5603 6100 fPlainVarNm = 0; 6101 cchSubprog += cch - offStart; 5604 6102 } 5605 /* Check out potential recipe . */6103 /* Check out potential recipe, simple assignment or DOS drive letter separator. */ 5606 6104 else if (ch == ':') 5607 6105 { … … 5618 6116 C:/Windows/System32/Kernel32.dll: C:/Windows/System32/NtDll.dll 5619 6117 for a recipe, it is only the second one which counts. */ 5620 elseif ( cch == 15621 6118 if ( cch == 1 6119 && isalpha((unsigned char)pchWord[0])) 5622 6120 cch++; 6121 else 5623 6122 #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 */ 5626 6130 } 5627 6131 /* Check out assignment operator. */ 5628 6132 else if (ch == '=') 5629 6133 { 5630 if (cch )6134 if (cch > 0) 5631 6135 { 5632 6136 char chPrev = pchWord[cch - 1]; … … 5638 6142 break; 5639 6143 } 5640 else 5641 kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name."); 6144 kmk_cc_eval_fatal(pCompiler, pchWord, "Empty variable name."); 5642 6145 } 5643 6146 /* Check out potential escaped EOL sequence. */ … … 5697 6200 else if (ch == '?') 5698 6201 enmOpCode = kKmkCcEvalInstr_assign_if_new; 6202 else if (!fQualifiers) 6203 return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft); 5699 6204 else 5700 return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft, fQualifiers);6205 return 0; /* retry without preceding keywords */ 5701 6206 pchWord += 2; 5702 6207 cchLeft -= 2; 5703 6208 } 6209 else if (!fQualifiers) 6210 return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft); 5704 6211 else 5705 return kmk_cc_eval_handle_recipe_cont_2nd_word(pCompiler, pchVarNm, cchVarNm, pchWord, cchLeft, fQualifiers);6212 return 0; /* retry without preceding keywords */ 5706 6213 5707 6214 /* … … 5712 6219 fPlainValue = memchr(pchWord, '$', cchLeft) == NULL; 5713 6220 5714 5715 6221 /* 5716 6222 * Emit the instruction. 5717 6223 */ 5718 kmk_cc_eval_end_of_recipe(pCompiler );6224 kmk_cc_eval_end_of_recipe(pCompiler, pchWord); 5719 6225 5720 6226 pInstr = (PKMKCCEVALASSIGN)kmk_cc_block_alloc_eval(pCompiler->ppBlockTail, sizeof(*pInstr)); … … 5745 6251 pInstr->pNext = (PKMKCCEVALCORE)kmk_cc_block_get_next_ptr(*pCompiler->ppBlockTail); 5746 6252 } 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."); 5747 6261 else 5748 6262 kmk_cc_eval_fatal(pCompiler, pchWord, "Neither recipe nor variable assignment"); … … 6181 6695 if (pszContent[offNext] == '#') 6182 6696 { 6183 KMK_CC_EVAL_DPRINTF(("#%03u: <comment >\n", Compiler.iLine));6697 KMK_CC_EVAL_DPRINTF(("#%03u: <comment-col-0>\n", Compiler.iLine)); 6184 6698 Compiler.iLine++; 6185 6699 offNext = pchTmp - pszContent; … … 6332 6846 char ch; 6333 6847 6334 Compiler.cchLineWithComments = 6848 Compiler.cchLineWithComments = cchLine; 6335 6849 pchTmp = (const char *)memchr(pchWord, '#', cchLeft); 6336 6850 if (pchTmp) … … 6341 6855 Compiler.cchLine = cchLine; 6342 6856 Compiler.offLine = off; 6857 6858 #ifdef KMK_CC_STRICT 6859 Compiler.cWords = 0x424242; 6860 #endif 6343 6861 6344 6862 /* … … 6355 6873 kmk_cc_eval_handle_assignment_or_recipe(&Compiler, pchWord, cchLeft, 0 /*fQualifiers*/); 6356 6874 else 6357 kmk_cc_eval_handle_recipe(&Compiler, pch Tmp, pchWord, cchLeft);6875 kmk_cc_eval_handle_recipe(&Compiler, pchWord, cchLeft); 6358 6876 } 6359 6877 /* else: handled a keyword expression */ … … 6472 6990 if (!fstat(fileno(pFile), &st)) 6473 6991 { 6474 if ( st.st_size > (off_t) 16*1024*10246992 if ( st.st_size > (off_t)KMK_CC_EVAL_MAX_COMPILE_SIZE 6475 6993 && 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); 6477 6996 cchContent = (size_t)st.st_size; 6478 6997 pszContent = (char *)xmalloc(cchContent + 1); … … 6488 7007 { 6489 7008 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); 6492 7011 pszContent = (char *)xrealloc(pszContent, cbAllocated); 6493 7012 cchContent += fread(&pszContent[cchContent], 1, cbAllocated - 1 - cchContent, pFile); … … 6532 7051 KMK_CC_ASSERT(pEvalProg); 6533 7052 assert(0); 7053 6534 7054 } 6535 7055 -
trunk/src/kmk/kmk_cc_exec.h
r2788 r3154 5 5 6 6 /* 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> 8 8 * 9 9 * This file is part of kBuild. … … 24 24 */ 25 25 26 #ifndef ___kmk_cc_and_exec h27 #define ___kmk_cc_and_exec h26 #ifndef ___kmk_cc_and_exec_h 27 #define ___kmk_cc_and_exec_h 28 28 #ifdef CONFIG_WITH_COMPILER 29 29
Note:
See TracChangeset
for help on using the changeset viewer.