Changeset 2768 in kBuild for trunk/src/kmk/kmk_cc_exec.c
- Timestamp:
- Jan 31, 2015 4:49:17 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmk_cc_exec.c
r2767 r2768 53 53 * these chains when destroying programs, we work with blocks of instructions. 54 54 */ 55 typedef struct kmk_cc_ exp_block55 typedef struct kmk_cc_block 56 56 { 57 57 /** The pointer to the next block (LIFO). */ 58 struct kmk_cc_ exp_block*pNext;58 struct kmk_cc_block *pNext; 59 59 /** The size of this block. */ 60 uint32_t cbBlock; 61 } KMKCCEXPBLOCK; 62 typedef KMKCCEXPBLOCK *PKMKCCEXPBLOCK; 60 uint32_t cbBlock; 61 /** The offset of the next free byte in the block. When set to cbBlock the 62 * block is 100% full. */ 63 uint32_t offNext; 64 } KMKCCBLOCK; 65 typedef KMKCCBLOCK *PKMKCCBLOCK; 63 66 64 67 /** Expansion instructions. */ … … 79 82 kKmkCcExpInstr_Jump, 80 83 /** We're done, return. Has no specific structure. */ 81 kKmkCcExpInstr_ Done,84 kKmkCcExpInstr_Return, 82 85 /** The end of valid instructions (exclusive). */ 83 86 kKmkCcExpInstr_End … … 98 101 /** Max expanded size. */ 99 102 uint32_t cbMax; 103 /** Recent average size. */ 104 uint32_t cbAvg; 100 105 } KMKCCEXPSUBPROG; 101 106 typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG; … … 117 122 KMKCCEXPCORE Core; 118 123 /** The variable strcache entry for this variable. */ 119 struct strcache2_entry *pNameEntry;124 struct strcache2_entry const *pNameEntry; 120 125 } KMKCCEXPPLAINVAR; 121 126 typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR; … … 140 145 KMKCCEXPCORE Core; 141 146 /** Number of arguments. */ 142 uint 8_tcArgs;147 uint32_t cArgs; 143 148 /** Where to continue after this instruction. This is necessary since the 144 149 * instruction is of variable size and we don't even know if we're still in the … … 170 175 } KMKCCEXPPLAINFUNC; 171 176 typedef KMKCCEXPPLAINFUNC *PKMKCCEXPPLAINFUNC; 177 /** Calculates the size of an KMKCCEXPPLAINFUNC with a_cArgs. */ 178 #define KMKCCEXPPLAINFUNC_SIZE(a_cArgs) (sizeof(KMKCCEXPFUNCCORE) + (a_cArgs + 1) * sizeof(const char *)) 172 179 173 180 typedef struct kmk_cc_exp_dyn_function … … 198 205 } KMKCCEXPDYNFUNC; 199 206 typedef KMKCCEXPDYNFUNC *PKMKCCEXPDYNFUNC; 207 /** Calculates the size of an KMKCCEXPPLAINFUNC with a_cArgs. */ 208 #define KMKCCEXPDYNFUNC_SIZE(a_cArgs) ( sizeof(KMKCCEXPFUNCCORE) \ 209 + (a_cArgs) * sizeof(((PKMKCCEXPDYNFUNC)(uintptr_t)42)->aArgs[0]) ) 200 210 201 211 typedef struct kmk_cc_exp_jump … … 214 224 { 215 225 /** Pointer to the first instruction for this program. */ 216 PKMKCCEXPCORE pFirstInstr;226 PKMKCCEXPCORE pFirstInstr; 217 227 /** List of blocks for this program (LIFO). */ 218 PKMKCC EXPBLOCKpBlockTail;228 PKMKCCBLOCK pBlockTail; 219 229 /** Max expanded size. */ 220 uint32_t cbMax; 221 } KMKCCEXPANDPROG; 230 uint32_t cbMax; 231 /** Recent average size. */ 232 uint32_t cbAvg; 233 } KMKCCEXPPROG; 222 234 /** Pointer to a string expansion program. */ 223 typedef KMKCCEXP ANDPROG *PKMKCCEXPANDPROG;235 typedef KMKCCEXPPROG *PKMKCCEXPPROG; 224 236 225 237 … … 229 241 230 242 243 /******************************************************************************* 244 * Internal Functions * 245 *******************************************************************************/ 246 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg); 247 248 231 249 /** 232 250 * Initializes global variables for the 'compiler'. … … 235 253 { 236 254 } 255 256 257 /** 258 * For the first allocation using the block allocator. 259 * 260 * @returns Pointer to the first allocation (@a cbFirst in size). 261 * @param ppBlockTail Where to return the pointer to the first block. 262 * @param cbFirst The size of the first allocation. 263 * @param cbHint Hint about how much memory we might be needing. 264 */ 265 static void *kmk_cc_block_alloc_first(PKMKCCBLOCK *ppBlockTail, size_t cbFirst, size_t cbHint) 266 { 267 uint32_t cbBlock; 268 PKMKCCBLOCK pNewBlock; 269 270 assert(((cbFirst + sizeof(void *) - 1) & (sizeof(void *) - 1)) == 0); 271 272 /* 273 * Turn the hint into a block size. 274 */ 275 if (cbHint <= 512) 276 cbBlock = 512; 277 else if (cbHint < 2048) 278 cbBlock = 1024; 279 else if (cbHint < 3072) 280 cbBlock = 2048; 281 else 282 cbBlock = 4096; 283 284 /* 285 * Allocate and initialize the first block. 286 */ 287 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); 288 pNewBlock->cbBlock = cbBlock; 289 pNewBlock->offNext = sizeof(*pNewBlock) + cbFirst; 290 pNewBlock->pNext = NULL; 291 *ppBlockTail = pNewBlock; 292 293 return pNewBlock + 1; 294 } 295 296 297 /** 298 * Used for getting the address of the next instruction. 299 * 300 * @returns Pointer to the next allocation. 301 * @param pBlockTail The allocator tail pointer. 302 */ 303 static void *kmk_cc_block_get_next_ptr(PKMKCCBLOCK pBlockTail) 304 { 305 return (char *)pBlockTail + pBlockTail->offNext; 306 } 307 308 309 /** 310 * Realigns the allocator after doing byte or string allocations. 311 * 312 * @param ppBlockTail Pointer to the allocator tail pointer. 313 */ 314 static void kmk_cc_block_realign(PKMKCCBLOCK *ppBlockTail) 315 { 316 PKMKCCBLOCK pBlockTail = *ppBlockTail; 317 if (pBlockTail->offNext & (sizeof(void *) - 1)) 318 { 319 pBlockTail->offNext = (pBlockTail->offNext + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 320 assert(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP)); 321 } 322 } 323 324 325 /** 326 * Grows the allocation with another block, byte allocator case. 327 * 328 * @returns Pointer to the byte allocation. 329 * @param ppBlockTail Pointer to the allocator tail pointer. 330 * @param cb The number of bytes to allocate. 331 */ 332 static void *kmk_cc_block_byte_alloc_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb) 333 { 334 PKMKCCBLOCK pOldBlock = *ppBlockTail; 335 PKMKCCBLOCK pPrevBlock = pOldBlock->pNext; 336 PKMKCCBLOCK pNewBlock; 337 uint32_t cbBlock; 338 339 /* 340 * Check if there accidentally is some space left in the previous block first. 341 */ 342 if ( pPrevBlock 343 && pPrevBlock->cbBlock - pPrevBlock->offNext >= cb) 344 { 345 void *pvRet = (char *)pPrevBlock + pPrevBlock->offNext; 346 pPrevBlock->offNext += cb; 347 return pvRet; 348 } 349 350 /* 351 * Allocate a new block. 352 */ 353 354 /* Figure the block size. */ 355 cbBlock = pOldBlock->cbBlock; 356 while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb) 357 cbBlock *= 2; 358 359 /* Allocate and initialize the block it with the new instruction already accounted for. */ 360 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); 361 pNewBlock->cbBlock = cbBlock; 362 pNewBlock->offNext = sizeof(*pNewBlock) + cb; 363 pNewBlock->pNext = pOldBlock; 364 *ppBlockTail = pNewBlock; 365 366 return pNewBlock + 1; 367 } 368 369 370 /** 371 * Make a byte allocation. 372 * 373 * Must call kmk_cc_block_realign() when done doing byte and string allocations. 374 * 375 * @returns Pointer to the byte allocation (byte aligned). 376 * @param ppBlockTail Pointer to the allocator tail pointer. 377 * @param cb The number of bytes to allocate. 378 */ 379 static void *kmk_cc_block_byte_alloc(PKMKCCBLOCK *ppBlockTail, uint32_t cb) 380 { 381 PKMKCCBLOCK pBlockTail = *ppBlockTail; 382 uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext; 383 384 assert(cbLeft >= sizeof(KMKCCEXPJUMP)); 385 if (cbLeft >= cb + sizeof(KMKCCEXPJUMP)) 386 { 387 void *pvRet = (char *)pBlockTail + pBlockTail->offNext; 388 pBlockTail->offNext += cb; 389 return pvRet; 390 } 391 return kmk_cc_block_byte_alloc_grow(ppBlockTail, cb); 392 } 393 394 395 /** 396 * Duplicates the given string in a byte allocation. 397 * 398 * Must call kmk_cc_block_realign() when done doing byte and string allocations. 399 * 400 * @returns Pointer to the byte allocation (byte aligned). 401 * @param ppBlockTail Pointer to the allocator tail pointer. 402 * @param cb The number of bytes to allocate. 403 */ 404 static const char *kmk_cc_block_strdup(PKMKCCBLOCK *ppBlockTail, const char *pachStr, uint32_t cchStr) 405 { 406 char *pszCopy; 407 if (cchStr) 408 { 409 pszCopy = kmk_cc_block_byte_alloc(ppBlockTail, cchStr + 1); 410 memcpy(pszCopy, pachStr, cchStr); 411 pszCopy[cchStr] = '\0'; 412 return pszCopy; 413 } 414 return ""; 415 } 416 417 418 /** 419 * Grows the allocation with another block, string expansion program case. 420 * 421 * @returns Pointer to a string expansion instruction core. 422 * @param ppBlockTail Pointer to the allocator tail pointer. 423 * @param cb The number of bytes to allocate. 424 */ 425 static PKMKCCEXPCORE kmk_cc_block_alloc_exp_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb) 426 { 427 PKMKCCBLOCK pOldBlock = *ppBlockTail; 428 PKMKCCBLOCK pNewBlock; 429 PKMKCCEXPCORE pRet; 430 PKMKCCEXPJUMP pJump; 431 432 /* Figure the block size. */ 433 uint32_t cbBlock = pOldBlock->cbBlock; 434 while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb) 435 cbBlock *= 2; 436 437 /* Allocate and initialize the block it with the new instruction already accounted for. */ 438 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock); 439 pNewBlock->cbBlock = cbBlock; 440 pNewBlock->offNext = sizeof(*pNewBlock) + cb; 441 pNewBlock->pNext = pOldBlock; 442 *ppBlockTail = pNewBlock; 443 444 pRet = (PKMKCCEXPCORE)(pNewBlock + 1); 445 446 /* Emit jump. */ 447 pJump = (PKMKCCEXPJUMP)((char *)pOldBlock + pOldBlock->offNext); 448 pJump->Core.enmOpCode = kKmkCcExpInstr_Jump; 449 pJump->pNext = pRet; 450 pOldBlock->offNext += sizeof(*pJump); 451 assert(pOldBlock->offNext <= pOldBlock->cbBlock); 452 453 return pRet; 454 } 455 456 457 /** 458 * Allocates a string expansion instruction of size @a cb. 459 * 460 * @returns Pointer to a string expansion instruction core. 461 * @param ppBlockTail Pointer to the allocator tail pointer. 462 * @param cb The number of bytes to allocate. 463 */ 464 static PKMKCCEXPCORE kmk_cc_block_alloc_exp(PKMKCCBLOCK *ppBlockTail, uint32_t cb) 465 { 466 PKMKCCBLOCK pBlockTail = *ppBlockTail; 467 uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext; 468 469 assert(cbLeft >= sizeof(KMKCCEXPJUMP)); 470 assert(((cb + sizeof(void *) - 1) & (sizeof(void *) - 1)) == 0 || cb == sizeof(KMKCCEXPCORE)); 471 472 if (cbLeft >= cb + sizeof(KMKCCEXPJUMP)) 473 { 474 PKMKCCEXPCORE pRet = (PKMKCCEXPCORE)((char *)pBlockTail + pBlockTail->offNext); 475 pBlockTail->offNext += cb; 476 return pRet; 477 } 478 return kmk_cc_block_alloc_exp_grow(ppBlockTail, cb); 479 } 480 481 482 /** 483 * Frees all memory used by an allocator. 484 * 485 * @param ppBlockTail The allocator tail pointer. 486 */ 487 static void kmk_cc_block_free_list(PKMKCCBLOCK pBlockTail) 488 { 489 while (pBlockTail) 490 { 491 PKMKCCBLOCK pThis = pBlockTail; 492 pBlockTail = pBlockTail->pNext; 493 free(pThis); 494 } 495 } 496 497 498 /** 499 * Counts the number of dollar chars in the string. 500 * 501 * @returns Number of dollar chars. 502 * @param pchStr The string to search (does not need to be zero 503 * terminated). 504 * @param cchStr The length of the string. 505 */ 506 static uint32_t kmk_cc_count_dollars(const char *pchStr, uint32_t cchStr) 507 { 508 uint32_t cDollars = 0; 509 const char *pch; 510 while ((pch = memchr(pchStr, '$', cchStr)) != NULL) 511 { 512 cDollars++; 513 cchStr -= pch - pchStr + 1; 514 pchStr = pch + 1; 515 } 516 return cDollars; 517 } 518 519 520 /** 521 * Emits a kKmkCcExpInstr_Return. 522 * 523 * @returns 0 on success, non-zero on failure. 524 * @param ppBlockTail Pointer to the allocator tail pointer. 525 */ 526 static int kmk_cc_exp_emit_return(PKMKCCBLOCK *ppBlockTail) 527 { 528 PKMKCCEXPCORE pCore = kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pCore)); 529 pCore->enmOpCode = kKmkCcExpInstr_Return; 530 return 0; 531 } 532 533 534 /** 535 * Emits a function call instruction taking arguments that needs expanding. 536 * 537 * @returns 0 on success, non-zero on failure. 538 * @param ppBlockTail Pointer to the allocator tail pointer. 539 * @param pszFunction The function name (const string from function.c). 540 * @param pchArgs Pointer to the arguments expression string, leading 541 * any blanks has been stripped. 542 * @param cchArgs The length of the arguments expression string. 543 * @param cArgs Number of arguments found. 544 * @param chOpen The char used to open the function call. 545 * @param chClose The char used to close the function call. 546 * @param pfnFunction The function implementation. 547 * @param cMaxArgs Maximum number of arguments the function takes. 548 */ 549 static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction, 550 const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose, 551 make_function_ptr_t pfnFunction, unsigned char cMaxArgs) 552 { 553 uint32_t iArg; 554 555 /* 556 * The function instruction has variable size. The maximum argument count 557 * isn't quite like the minium one. Zero means no limit. While a non-zero 558 * value means that any commas beyond the max will be taken to be part of 559 * the final argument. 560 */ 561 uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs; 562 PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPDYNFUNC_SIZE(cActualArgs)); 563 pInstr->Core.Core.enmOpCode = kKmkCcExpInstr_DynamicFunction; 564 pInstr->Core.cArgs = cActualArgs; 565 pInstr->Core.pfnFunction = pfnFunction; 566 pInstr->Core.pszFuncName = pszFunction; 567 568 /* 569 * Parse the arguments. Plain arguments gets duplicated in the program 570 * memory so that they are terminated and no extra processing is necessary 571 * later on. ASSUMES that the function implementations do NOT change 572 * argument memory. Other arguments the compiled into their own expansion 573 * sub programs. 574 */ 575 iArg = 0; 576 for (;;) 577 { 578 /* Find the end of the argument. Check for $. */ 579 char ch = '\0'; 580 uint8_t fDollar = 0; 581 int32_t cDepth = 0; 582 uint32_t cchThisArg = 0; 583 while (cchThisArg < cchArgs) 584 { 585 ch = pchArgs[cchThisArg]; 586 if (ch == chClose) 587 { 588 assert(cDepth > 0); 589 if (cDepth > 0) 590 cDepth--; 591 } 592 else if (ch == chOpen) 593 cDepth++; 594 else if (ch == ',' && cDepth == 0) 595 break; 596 else if (ch == '$') 597 fDollar = 1; 598 cchThisArg++; 599 } 600 601 pInstr->aArgs[iArg].fPlain = fDollar; 602 if (fDollar) 603 { 604 /* Compile it. */ 605 int rc; 606 kmk_cc_block_realign(ppBlockTail); 607 rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchArgs, cchThisArg, &pInstr->aArgs[iArg].u.SubProg); 608 if (rc != 0) 609 return rc; 610 } 611 else 612 { 613 /* Duplicate it. */ 614 pInstr->aArgs[iArg].u.Plain.pszArg = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg); 615 } 616 iArg++; 617 if (ch != ',') 618 break; 619 pchArgs += cchThisArg + 1; 620 cchArgs -= cchThisArg + 1; 621 } 622 assert(iArg == cActualArgs); 623 624 /* 625 * Realign the allocator and take down the address of the next instruction. 626 */ 627 kmk_cc_block_realign(ppBlockTail); 628 pInstr->Core.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 629 return 0; 630 } 631 632 633 /** 634 * Emits a function call instruction taking plain arguments. 635 * 636 * @returns 0 on success, non-zero on failure. 637 * @param ppBlockTail Pointer to the allocator tail pointer. 638 * @param pszFunction The function name (const string from function.c). 639 * @param pchArgs Pointer to the arguments string, leading any blanks 640 * has been stripped. 641 * @param cchArgs The length of the arguments string. 642 * @param cArgs Number of arguments found. 643 * @param chOpen The char used to open the function call. 644 * @param chClose The char used to close the function call. 645 * @param pfnFunction The function implementation. 646 * @param cMaxArgs Maximum number of arguments the function takes. 647 */ 648 static int kmk_cc_exp_emit_plain_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction, 649 const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose, 650 make_function_ptr_t pfnFunction, unsigned char cMaxArgs) 651 { 652 uint32_t iArg; 653 654 /* 655 * The function instruction has variable size. The maximum argument count 656 * isn't quite like the minium one. Zero means no limit. While a non-zero 657 * value means that any commas beyond the max will be taken to be part of 658 * the final argument. 659 */ 660 uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs; 661 PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPPLAINFUNC_SIZE(cActualArgs)); 662 pInstr->Core.Core.enmOpCode = kKmkCcExpInstr_PlainFunction; 663 pInstr->Core.cArgs = cActualArgs; 664 pInstr->Core.pfnFunction = pfnFunction; 665 pInstr->Core.pszFuncName = pszFunction; 666 667 /* 668 * Parse the arguments. Plain arguments gets duplicated in the program 669 * memory so that they are terminated and no extra processing is necessary 670 * later on. ASSUMES that the function implementations do NOT change 671 * argument memory. 672 */ 673 iArg = 0; 674 for (;;) 675 { 676 /* Find the end of the argument. */ 677 char ch = '\0'; 678 int32_t cDepth = 0; 679 uint32_t cchThisArg = 0; 680 while (cchThisArg < cchArgs) 681 { 682 ch = pchArgs[cchThisArg]; 683 if (ch == chClose) 684 { 685 assert(cDepth > 0); 686 if (cDepth > 0) 687 cDepth--; 688 } 689 else if (ch == chOpen) 690 cDepth++; 691 else if (ch == ',' && cDepth == 0) 692 break; 693 cchThisArg++; 694 } 695 696 /* Duplicate it. */ 697 pInstr->apszArgs[iArg++] = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg); 698 if (ch != ',') 699 break; 700 pchArgs += cchThisArg + 1; 701 cchArgs -= cchThisArg + 1; 702 } 703 704 assert(iArg == cActualArgs); 705 pInstr->apszArgs[iArg] = NULL; 706 707 /* 708 * Realign the allocator and take down the address of the next instruction. 709 */ 710 kmk_cc_block_realign(ppBlockTail); 711 pInstr->Core.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 712 return 0; 713 } 714 715 716 /** 717 * Emits a kKmkCcExpInstr_DynamicVariable. 718 * 719 * @returns 0 on success, non-zero on failure. 720 * @param ppBlockTail Pointer to the allocator tail pointer. 721 * @param pchNameExpr The name of the variable (ASSUMED presistent 722 * thru-out the program life time). 723 * @param cchNameExpr The length of the variable name. If zero, 724 * nothing will be emitted. 725 */ 726 static int kmk_cc_exp_emit_dyn_variable(PKMKCCBLOCK *ppBlockTail, const char *pchNameExpr, uint32_t cchNameExpr) 727 { 728 PKMKCCEXPDYNVAR pInstr; 729 int rc; 730 assert(cchNameExpr > 0); 731 732 pInstr = (PKMKCCEXPDYNVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 733 pInstr->Core.enmOpCode = kKmkCcExpInstr_DynamicVariable; 734 735 rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchNameExpr, cchNameExpr, &pInstr->SubProg); 736 737 pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 738 return rc; 739 } 740 741 742 /** 743 * Emits a kKmkCcExpInstr_PlainVariable. 744 * 745 * @returns 0 on success, non-zero on failure. 746 * @param ppBlockTail Pointer to the allocator tail pointer. 747 * @param pchName The name of the variable. (Does not need to be 748 * valid beyond the call.) 749 * @param cchName The length of the variable name. If zero, 750 * nothing will be emitted. 751 */ 752 static int kmk_cc_exp_emit_plain_variable(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName) 753 { 754 if (cchName > 0) 755 { 756 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 757 pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable; 758 pInstr->pNameEntry = strcache2_get_entry(&variable_strcache, strcache2_add(&variable_strcache, pchName, cchName)); 759 } 760 return 0; 761 } 762 763 764 /** 765 * Emits a kKmkCcExpInstr_CopyString. 766 * 767 * @returns 0 on success, non-zero on failure. 768 * @param ppBlockTail Pointer to the allocator tail pointer. 769 * @param pchStr The string to emit (ASSUMED presistent thru-out 770 * the program life time). 771 * @param cchStr The number of chars to copy. If zero, nothing 772 * will be emitted. 773 */ 774 static int kmk_cc_exp_emit_copy_string(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr) 775 { 776 if (cchStr > 0) 777 { 778 PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 779 pInstr->Core.enmOpCode = kKmkCcExpInstr_CopyString; 780 pInstr->cchCopy = cchStr; 781 pInstr->pachSrc = pchStr; 782 } 783 return 0; 784 } 785 786 787 /** 788 * String expansion compilation function common to both normal and sub programs. 789 * 790 * @returns 0 on success, non-zero on failure. 791 * @param ppBlockTail Pointer to the allocator tail pointer. 792 * @param pchStr The expression to compile. 793 * @param cchStr The length of the expression to compile. 794 */ 795 static int kmk_cc_exp_compile_common(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr) 796 { 797 /* 798 * Process the string. 799 */ 800 while (cchStr > 0) 801 { 802 /* Look for dollar sign, marks variable expansion or dollar-escape. */ 803 int rc; 804 const char *pchDollar = memchr(pchStr, '$', cchStr); 805 if (pchDollar) 806 { 807 /* 808 * Check for multiple dollar chars. 809 */ 810 uint32_t offDollar = (uint32_t)(pchDollar - pchStr); 811 uint32_t cDollars = 1; 812 while ( offDollar + cDollars < cchStr 813 && pchStr[offDollar + cDollars] == '$') 814 cDollars++; 815 816 /* 817 * Emit a string copy for any preceeding stuff, including half of 818 * the dollars we found (dollar escape: $$ -> $). 819 * (kmk_cc_exp_emit_copy_string ignore zero length strings). 820 */ 821 rc = kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, offDollar + cDollars / 2); 822 if (rc != 0) 823 return rc; 824 pchStr += offDollar + cDollars; 825 cchStr -= offDollar + cDollars; 826 827 /* 828 * Odd number of dollar chars means there is a variable to expand 829 * or function to call. 830 */ 831 if (cDollars & 1) 832 { 833 if (cchStr > 0) 834 { 835 char const chOpen = *pchStr; 836 if (chOpen == '(' || chOpen == '{') 837 { 838 /* There are several alternative ways of finding the ending 839 parenthesis / braces. GNU make only consideres open & 840 close chars of the one we're processing, and it does not 841 matter whether the opening paren / braces are preceeded by 842 any dollar char. Simple and efficient. */ 843 make_function_ptr_t pfnFunction; 844 const char *pszFunction; 845 unsigned char cMaxArgs; 846 unsigned char cMinArgs; 847 char fExpandArgs; 848 char const chClose = chOpen == '(' ? ')' : '}'; 849 char ch = 0; 850 uint32_t cchName = 0; 851 uint32_t cDepth = 1; 852 uint32_t cMaxDepth = 1; 853 cDollars = 0; 854 855 pchStr++; 856 cchStr--; 857 858 /* First loop: Identify potential function calls and dynamic expansion. */ 859 assert(!func_char_map[chOpen]); assert(!func_char_map[chClose]); assert(!func_char_map['$']); 860 while (cchName < cchStr) 861 { 862 ch = pchStr[cchName]; 863 if (!func_char_map[(int)ch]) 864 break; 865 cchName++; 866 } 867 if ( cchName >= MIN_FUNCTION_LENGTH 868 && cchName <= MAX_FUNCTION_LENGTH 869 && (isblank(ch) || ch == chClose || cchName == cchStr) 870 && (pfnFunction = lookup_function_for_compiler(pchStr, cchName, &cMinArgs, &cMaxArgs, 871 &fExpandArgs, &pszFunction)) != NULL) 872 { 873 /* 874 * It's a function invocation, we should count parameters while 875 * looking for the end. 876 * Note! We use cchName for the length of the argument list. 877 */ 878 uint32_t cArgs = 1; 879 if (ch != chClose) 880 { 881 /* Skip leading spaces before the first arg. */ 882 cchName++; 883 while (cchName < cchStr && isblank((unsigned char)pchStr[cchName])) 884 cchName++; 885 886 pchStr += cchName; 887 cchStr -= cchName; 888 cchName = 0; 889 890 while (cchName < cchStr) 891 { 892 ch = pchStr[cchName]; 893 if (ch == ',') 894 { 895 if (cDepth == 1) 896 cArgs++; 897 } 898 else if (ch == chClose) 899 { 900 if (!--cDepth) 901 break; 902 } 903 else if (ch == chOpen) 904 { 905 if (++cDepth > cMaxDepth) 906 cMaxDepth = cDepth; 907 } 908 else if (ch == '$') 909 cDollars++; 910 cchName++; 911 } 912 } 913 else 914 { 915 pchStr += cchName; 916 cchStr -= cchName; 917 cchName = 0; 918 } 919 if (cArgs < cMinArgs) 920 { 921 fatal(NULL, _("Function '%.*s' takes a minimum of %d arguments: %d given"), 922 pszFunction, (int)cMinArgs, (int)cArgs); 923 return -1; /* not reached */ 924 } 925 if (cDepth != 0) 926 { 927 fatal(NULL, chOpen == '(' 928 ? _("Missing closing parenthesis calling '%s'") : _("Missing closing braces calling '%s'"), 929 pszFunction); 930 return -1; /* not reached */ 931 } 932 if (cMaxDepth > 16 && fExpandArgs) 933 { 934 fatal(NULL, _("Too many levels of nested function arguments expansions: %s"), pszFunction); 935 return -1; /* not reached */ 936 } 937 if (!fExpandArgs || cDollars == 0) 938 rc = kmk_cc_exp_emit_plain_function(ppBlockTail, pszFunction, pchStr, cchName, 939 cArgs, chOpen, chClose, pfnFunction, cMaxArgs); 940 else 941 rc = kmk_cc_exp_emit_dyn_function(ppBlockTail, pszFunction, pchStr, cchName, 942 cArgs, chOpen, chClose, pfnFunction, cMaxArgs); 943 } 944 else 945 { 946 /* 947 * Variable, find the end while checking whether anything needs expanding. 948 */ 949 if (ch == chClose) 950 cDepth = 0; 951 else if (cchName < cchStr) 952 { 953 if (ch != '$') 954 { 955 /* Second loop: Look for things that needs expanding. */ 956 while (cchName < cchStr) 957 { 958 ch = pchStr[cchName]; 959 if (ch == chClose) 960 { 961 if (!--cDepth) 962 break; 963 } 964 else if (ch == chOpen) 965 { 966 if (++cDepth > cMaxDepth) 967 cMaxDepth = cDepth; 968 } 969 else if (ch == '$') 970 break; 971 cchName++; 972 } 973 } 974 if (ch == '$') 975 { 976 /* Third loop: Something needs expanding, just find the end. */ 977 cDollars = 1; 978 cchName++; 979 while (cchName < cchStr) 980 { 981 ch = pchStr[cchName]; 982 if (ch == chClose) 983 { 984 if (!--cDepth) 985 break; 986 } 987 else if (ch == chOpen) 988 { 989 if (++cDepth > cMaxDepth) 990 cMaxDepth = cDepth; 991 } 992 cchName++; 993 } 994 } 995 } 996 if (cDepth > 0) /* After warning, we just assume they're all there. */ 997 error(NULL, chOpen == '(' ? _("Missing closing parenthesis ") : _("Missing closing braces")); 998 if (cMaxDepth >= 16) 999 { 1000 fatal(NULL, _("Too many levels of nested variable expansions: '%.*s'"), (int)cchName + 2, pchStr - 1); 1001 return -1; /* not reached */ 1002 } 1003 if (cDollars == 0) 1004 rc = kmk_cc_exp_emit_plain_variable(ppBlockTail, pchStr, cchName); 1005 else 1006 rc = kmk_cc_exp_emit_dyn_variable(ppBlockTail, pchStr, cchName); 1007 } 1008 pchStr += cchName + 1; 1009 cchStr -= cchName + (cDepth == 0); 1010 } 1011 else 1012 { 1013 /* Single character variable name. */ 1014 rc = kmk_cc_exp_emit_plain_variable(ppBlockTail, pchStr, 1); 1015 pchStr++; 1016 cchStr--; 1017 } 1018 if (rc != 0) 1019 return rc; 1020 } 1021 else 1022 { 1023 error(NULL, _("Unexpected end of string after $")); 1024 break; 1025 } 1026 } 1027 } 1028 else 1029 { 1030 /* 1031 * Nothing more to expand, the remainder is a simple string copy. 1032 */ 1033 rc = kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, cchStr); 1034 if (rc != 0) 1035 return rc; 1036 break; 1037 } 1038 } 1039 1040 /* 1041 * Emit final instruction. 1042 */ 1043 return kmk_cc_exp_emit_return(ppBlockTail); 1044 } 1045 1046 1047 /** 1048 * Compiles a string expansion sub program. 1049 * 1050 * The caller typically make a call to kmk_cc_block_get_next_ptr after this 1051 * function returns to figure out where to continue executing. 1052 * 1053 * @returns 0 on success, non-zero on failure. 1054 * @param ppBlockTail Pointer to the allocator tail pointer. 1055 * @param pchStr Pointer to the string to compile an expansion 1056 * program for (ASSUMED to be valid for the 1057 * lifetime of the program). 1058 * @param cchStr The length of the string to compile. Expected to 1059 * be at least on char long. 1060 * @param pSubProg The sub program structure to initialize. 1061 */ 1062 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg) 1063 { 1064 assert(cchStr); 1065 pSubProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 1066 pSubProg->cbMax = 0; 1067 pSubProg->cbAvg = 0; 1068 return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr); 1069 } 1070 1071 1072 /** 1073 * Compiles a string expansion program. 1074 * 1075 * @returns Pointer to the program on success, NULL on failure. 1076 * @param pchStr Pointer to the string to compile an expansion 1077 * program for (ASSUMED to be valid for the 1078 * lifetime of the program). 1079 * @param cchStr The length of the string to compile. Expected to 1080 * be at least on char long. 1081 */ 1082 static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr) 1083 { 1084 /* 1085 * Estimate block size, allocate one and initialize it. 1086 */ 1087 PKMKCCEXPPROG pProg; 1088 PKMKCCBLOCK pBlock; 1089 pProg = kmk_cc_block_alloc_first(&pBlock, sizeof(*pProg), 1090 (kmk_cc_count_dollars(pchStr, cchStr) + 8) * 16); 1091 if (pProg) 1092 { 1093 int rc = 0; 1094 1095 pProg->pBlockTail = pBlock; 1096 pProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(pBlock); 1097 pProg->cbMax = 0; 1098 pProg->cbAvg = 0; 1099 1100 /* 1101 * Join forces with the sub program compilation code. 1102 */ 1103 if (kmk_cc_exp_compile_common(&pProg->pBlockTail, pchStr, cchStr) == 0) 1104 return pProg; 1105 kmk_cc_block_free_list(pProg->pBlockTail); 1106 } 1107 return NULL; 1108 } 1109 237 1110 238 1111 … … 258 1131 struct kmk_cc_expandprog *kmk_cc_compile_variable_for_expand(struct variable *pVar) 259 1132 { 260 assert(!pVar->evalprog); 261 262 //memchr() 263 264 265 266 267 return NULL; 1133 assert(!pVar->expandprog); 1134 if ( !pVar->expandprog 1135 && pVar->value_length > 0 1136 && pVar->recursive) 1137 { 1138 assert(strlen(pVar->value) == pVar->value_length); 1139 #if 0 /** @todo test & debug this code. Write interpreters! */ 1140 pVar->expandprog = kmk_cc_exp_compile(pVar->value, pVar->value_length); 1141 #endif 1142 } 1143 return pVar->expandprog; 268 1144 } 269 1145
Note:
See TracChangeset
for help on using the changeset viewer.