VirtualBox

source: kBuild/trunk/src/kmk/kmk_cc_exec.c@ 2768

Last change on this file since 2768 was 2768, checked in by bird, 10 years ago

Initial code for the string expansion 'compiler'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 43.0 KB
Line 
1#ifdef CONFIG_WITH_COMPILER
2/* $Id: kmk_cc_exec.c 2768 2015-01-31 04:49:17Z bird $ */
3/** @file
4 * kmk_cc - Make "Compiler".
5 */
6
7/*
8 * Copyright (c) 2015 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
9 *
10 * This file is part of kBuild.
11 *
12 * kBuild is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * kBuild is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "make.h"
32
33#include "dep.h"
34#include "variable.h"
35#include "rule.h"
36#include "debug.h"
37#include "hash.h"
38#include <ctype.h>
39#ifdef HAVE_STDINT_H
40# include <stdint.h>
41#endif
42#include <stdarg.h>
43#include <assert.h>
44
45
46/*******************************************************************************
47* Structures and Typedefs *
48*******************************************************************************/
49/**
50 * Block of expand instructions.
51 *
52 * To avoid wasting space on "next" pointers, as well as a lot of time walking
53 * these chains when destroying programs, we work with blocks of instructions.
54 */
55typedef struct kmk_cc_block
56{
57 /** The pointer to the next block (LIFO). */
58 struct kmk_cc_block *pNext;
59 /** The size of this block. */
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;
65typedef KMKCCBLOCK *PKMKCCBLOCK;
66
67/** Expansion instructions. */
68typedef enum KMKCCEXPINSTR
69{
70 /** Copy a plain string. */
71 kKmkCcExpInstr_CopyString = 0,
72 /** Insert an expanded variable value, which name we already know. */
73 kKmkCcExpInstr_PlainVariable,
74 /** Insert an expanded variable value, the name is dynamic (sub prog). */
75 kKmkCcExpInstr_DynamicVariable,
76 /** Insert the output of function that requires no argument expansion. */
77 kKmkCcExpInstr_PlainFunction,
78 /** Insert the output of function that requires dynamic expansion of one ore
79 * more arguments. */
80 kKmkCcExpInstr_DynamicFunction,
81 /** Jump to a new instruction block. */
82 kKmkCcExpInstr_Jump,
83 /** We're done, return. Has no specific structure. */
84 kKmkCcExpInstr_Return,
85 /** The end of valid instructions (exclusive). */
86 kKmkCcExpInstr_End
87} KMKCCEXPANDINSTR;
88
89/** Instruction core. */
90typedef struct kmk_cc_exp_core
91{
92 /** The instruction opcode number (KMKCCEXPANDINSTR). */
93 KMKCCEXPANDINSTR enmOpCode;
94} KMKCCEXPCORE;
95typedef KMKCCEXPCORE *PKMKCCEXPCORE;
96
97typedef struct kmk_cc_exp_subprog
98{
99 /** Pointer to the first instruction. */
100 PKMKCCEXPCORE pFirstInstr;
101 /** Max expanded size. */
102 uint32_t cbMax;
103 /** Recent average size. */
104 uint32_t cbAvg;
105} KMKCCEXPSUBPROG;
106typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG;
107
108typedef struct kmk_cc_exp_copy_string
109{
110 /** The core instruction. */
111 KMKCCEXPCORE Core;
112 /** The number of bytes to copy. */
113 uint32_t cchCopy;
114 /** Pointer to the source string (not terminated at cchCopy). */
115 const char *pachSrc;
116} KMKCCEXPCOPYSTRING;
117typedef KMKCCEXPCOPYSTRING *PKMKCCEXPCOPYSTRING;
118
119typedef struct kmk_cc_exp_plain_variable
120{
121 /** The core instruction. */
122 KMKCCEXPCORE Core;
123 /** The variable strcache entry for this variable. */
124 struct strcache2_entry const *pNameEntry;
125} KMKCCEXPPLAINVAR;
126typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR;
127
128typedef struct kmk_cc_exp_dynamic_variable
129{
130 /** The core instruction. */
131 KMKCCEXPCORE Core;
132 /** Where to continue after this instruction. This is necessary since the
133 * subprogram is allocated after us in the instruction block. Since the sub
134 * program is of variable size, we don't even know if we're still in the same
135 * instruction block. So, we include a jump here. */
136 PKMKCCEXPCORE pNext;
137 /** The subprogram that will give us the variable name. */
138 KMKCCEXPSUBPROG SubProg;
139} KMKCCEXPDYNVAR;
140typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR;
141
142typedef struct kmk_cc_exp_function_core
143{
144 /** The core instruction. */
145 KMKCCEXPCORE Core;
146 /** Number of arguments. */
147 uint32_t cArgs;
148 /** Where to continue after this instruction. This is necessary since the
149 * instruction is of variable size and we don't even know if we're still in the
150 * same instruction block. So, we include a jump here. */
151 PKMKCCEXPCORE pNext;
152 /**
153 * Pointer to the function table entry.
154 *
155 * @returns New variable buffer position.
156 * @param pchDst Current variable buffer position.
157 * @param papszArgs Pointer to a NULL terminated array of argument strings.
158 * @param pszFuncName The name of the function being called.
159 */
160 char * (*pfnFunction)(char *pchDst, char **papszArgs, const char *pszFuncName);
161 /** Pointer to the function name in the variable string cache. */
162 const char *pszFuncName;
163} KMKCCEXPFUNCCORE;
164typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE;
165
166typedef struct kmk_cc_exp_plain_function
167{
168 /** The bits comment to both plain and dynamic functions. */
169 KMKCCEXPFUNCCORE Core;
170 /** Variable sized argument list (cArgs + 1 in length, last entry is NULL).
171 * The string pointers are to memory following this instruction, to memory in
172 * the next block or to memory in the variable / makefile we're working on
173 * (if zero terminated appropriately). */
174 const char *apszArgs[1];
175} KMKCCEXPPLAINFUNC;
176typedef 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 *))
179
180typedef struct kmk_cc_exp_dyn_function
181{
182 /** The bits comment to both plain and dynamic functions. */
183 KMKCCEXPFUNCCORE Core;
184 /** Variable sized argument list (cArgs + 1 in length, last entry is NULL).
185 * The string pointers are to memory following this instruction, to memory in
186 * the next block or to memory in the variable / makefile we're working on
187 * (if zero terminated appropriately). */
188 struct
189 {
190 /** Set if plain string argument, clear if sub program. */
191 uint8_t fPlain;
192 union
193 {
194 /** Sub program for expanding this argument. */
195 KMKCCEXPSUBPROG SubProg;
196 struct
197 {
198 /** Pointer to the plain argument string.
199 * This is allocated in the same manner as the
200 * string pointed to by KMKCCEXPPLAINFUNC::apszArgs. */
201 const char *pszArg;
202 } Plain;
203 } u;
204 } aArgs[1];
205} KMKCCEXPDYNFUNC;
206typedef 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]) )
210
211typedef struct kmk_cc_exp_jump
212{
213 /** The core instruction. */
214 KMKCCEXPCORE Core;
215 /** Where to jump to (new instruction block, typically). */
216 PKMKCCEXPCORE pNext;
217} KMKCCEXPJUMP;
218typedef KMKCCEXPJUMP *PKMKCCEXPJUMP;
219
220/**
221 * String expansion program.
222 */
223typedef struct kmk_cc_expandprog
224{
225 /** Pointer to the first instruction for this program. */
226 PKMKCCEXPCORE pFirstInstr;
227 /** List of blocks for this program (LIFO). */
228 PKMKCCBLOCK pBlockTail;
229 /** Max expanded size. */
230 uint32_t cbMax;
231 /** Recent average size. */
232 uint32_t cbAvg;
233} KMKCCEXPPROG;
234/** Pointer to a string expansion program. */
235typedef KMKCCEXPPROG *PKMKCCEXPPROG;
236
237
238/*******************************************************************************
239* Global Variables *
240*******************************************************************************/
241
242
243/*******************************************************************************
244* Internal Functions *
245*******************************************************************************/
246static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg);
247
248
249/**
250 * Initializes global variables for the 'compiler'.
251 */
252void kmk_cc_init(void)
253{
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 */
265static 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 */
303static 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 */
314static 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 */
332static 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 */
379static 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 */
404static 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 */
425static 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 */
464static 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 */
487static 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 */
506static 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 */
526static 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 */
549static 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 */
648static 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 */
726static 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 */
752static 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 */
774static 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 */
795static 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 */
1062static 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 */
1082static 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
1110
1111
1112/**
1113 * Compiles a variable direct evaluation as is, setting v->evalprog on success.
1114 *
1115 * @returns Pointer to the program on success, NULL if no program was created.
1116 * @param pVar Pointer to the variable.
1117 */
1118struct kmk_cc_evalprog *kmk_cc_compile_variable_for_eval(struct variable *pVar)
1119{
1120 return NULL;
1121}
1122
1123
1124/**
1125 * Compiles a variable for string expansion.
1126 *
1127 * @returns Pointer to the string expansion program on success, NULL if no
1128 * program was created.
1129 * @param pVar Pointer to the variable.
1130 */
1131struct kmk_cc_expandprog *kmk_cc_compile_variable_for_expand(struct variable *pVar)
1132{
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;
1144}
1145
1146
1147/**
1148 * Equivalent of eval_buffer, only it's using the evalprog of the variable.
1149 *
1150 * @param pVar Pointer to the variable. Must have a program.
1151 */
1152void kmk_exec_evalval(struct variable *pVar)
1153{
1154 assert(pVar->evalprog);
1155 assert(0);
1156}
1157
1158
1159/**
1160 * Expands a variable into a variable buffer using its expandprog.
1161 *
1162 * @returns The new variable buffer position.
1163 * @param pVar Pointer to the variable. Must have a program.
1164 * @param pchDst Pointer to the current variable buffer position.
1165 */
1166char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst)
1167{
1168 assert(pVar->expandprog);
1169 assert(0);
1170 return pchDst;
1171}
1172
1173
1174/**
1175 * Called when a variable with expandprog or/and evalprog changes.
1176 *
1177 * @param pVar Pointer to the variable.
1178 */
1179void kmk_cc_variable_changed(struct variable *pVar)
1180{
1181 assert(pVar->evalprog || pVar->expandprog);
1182}
1183
1184
1185/**
1186 * Called when a variable with expandprog or/and evalprog is deleted.
1187 *
1188 * @param pVar Pointer to the variable.
1189 */
1190void kmk_cc_variable_deleted(struct variable *pVar)
1191{
1192 assert(pVar->evalprog || pVar->expandprog);
1193}
1194
1195
1196#endif /* CONFIG_WITH_COMPILER */
1197
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette