VirtualBox

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

Last change on this file since 2788 was 2788, checked in by bird, 9 years ago

kmk_cc_exec.c: Sketched the basic makefile evaluation 'instructions'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 93.3 KB
Line 
1#ifdef CONFIG_WITH_COMPILER
2/* $Id: kmk_cc_exec.c 2788 2015-09-06 15:43:10Z 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* Defined Constants And Macros *
48*********************************************************************************************************************************/
49/** @def KMK_CC_WITH_STATS
50 * Enables the collection of extra statistics. */
51#ifndef KMK_CC_WITH_STATS
52# ifdef CONFIG_WITH_MAKE_STATS
53# define KMK_CC_WITH_STATS
54# endif
55#endif
56
57/** @def KMK_CC_STRICT
58 * Indicates whether assertions and other checks are enabled. */
59#ifndef KMK_CC_STRICT
60# ifndef NDEBUG
61# define KMK_CC_STRICT
62# endif
63#endif
64
65#ifdef KMK_CC_STRICT
66# ifdef _MSC_VER
67# define KMK_CC_ASSERT(a_TrueExpr) do { if (!(a_TrueExpr)) __debugbreak(); } while (0)
68# else
69# define KMK_CC_ASSERT(a_TrueExpr) assert(a_TrueExpr)
70# endif
71#else
72# define KMK_CC_ASSERT(a_TrueExpr) do {} while (0)
73#endif
74#define KMK_CC_ASSERT_ALIGNED(a_uValue, a_uAlignment) \
75 KMK_CC_ASSERT( ((a_uValue) & ((a_uAlignment) - 1)) == 0 )
76
77
78/** @def KMK_CC_OFFSETOF
79 * Offsetof for simple stuff. */
80#if defined(__GNUC__)
81# define KMK_CC_OFFSETOF(a_Struct, a_Member) __builtin_offsetof(a_Struct, a_Member)
82#else
83# define KMK_CC_OFFSETOF(a_Struct, a_Member) ( (uintptr_t)&( ((a_Struct *)(void *)0)->a_Member) )
84#endif
85
86/** def KMK_CC_SIZEOF_MEMBER */
87#define KMK_CC_SIZEOF_MEMBER(a_Struct, a_Member) ( sizeof( ((a_Struct *)(void *)0x1000)->a_Member) )
88
89/** @def KMK_CC_SIZEOF_VAR_STRUCT
90 * Size of a struct with a variable sized array as the final member. */
91#define KMK_CC_SIZEOF_VAR_STRUCT(a_Struct, a_FinalArrayMember, a_cArray) \
92 ( KMK_CC_OFFSETOF(a_Struct, a_FinalArrayMember) + KMK_CC_SIZEOF_MEMBER(a_Struct, a_FinalArrayMember) * (a_cArray) )
93
94
95
96/** @def KMK_CC_STATIC_ASSERT_EX
97 * Compile time assertion with text.
98 */
99#ifdef _MSC_VER_
100# if _MSC_VER >= 1600
101# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) static_assert(a_Expr, a_szExpl)
102# else
103# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) typedef int RTASSERTVAR[(a_Expr) ? 1 : 0]
104# endif
105#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
106# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) static_assert(a_Expr, a_szExpl)
107#elif !defined(__GNUC__) && !defined(__IBMC__) && !defined(__IBMCPP__)
108# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) typedef int KMK_CC_STATIC_ASSERT_EX_TYPE[(a_Expr) ? 1 : 0]
109#else
110# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) extern int KMK_CC_STATIC_ASSERT_EX_VAR[(aExpr) ? 1 : 0]
111extern int KMK_CC_STATIC_ASSERT_EX_VAR[1];
112#endif
113/** @def KMK_CC_STATIC_ASSERT
114 * Compile time assertion, simple variant.
115 */
116#define KMK_CC_STATIC_ASSERT(a_Expr) KMK_CC_STATIC_ASSERT_EX(a_Expr, #a_Expr)
117
118
119/*********************************************************************************************************************************
120* Structures and Typedefs *
121*********************************************************************************************************************************/
122/**
123 * Block of expand instructions.
124 *
125 * To avoid wasting space on "next" pointers, as well as a lot of time walking
126 * these chains when destroying programs, we work with blocks of instructions.
127 */
128typedef struct kmk_cc_block
129{
130 /** The pointer to the next block (LIFO). */
131 struct kmk_cc_block *pNext;
132 /** The size of this block. */
133 uint32_t cbBlock;
134 /** The offset of the next free byte in the block. When set to cbBlock the
135 * block is 100% full. */
136 uint32_t offNext;
137} KMKCCBLOCK;
138typedef KMKCCBLOCK *PKMKCCBLOCK;
139
140
141/** @name String Expansion
142 * @{*/
143
144/**
145 * String expansion statistics.
146 */
147typedef struct KMKCCEXPSTATS
148{
149 /** Recent average size. */
150 uint32_t cchAvg;
151} KMKCCEXPSTATS;
152typedef KMKCCEXPSTATS *PKMKCCEXPSTATS;
153
154/**
155 * Expansion instructions.
156 */
157typedef enum KMKCCEXPINSTR
158{
159 /** Copy a plain string. */
160 kKmkCcExpInstr_CopyString = 0,
161 /** Insert an expanded variable value, which name we already know. */
162 kKmkCcExpInstr_PlainVariable,
163 /** Insert an expanded variable value, the name is dynamic (sub prog). */
164 kKmkCcExpInstr_DynamicVariable,
165 /** Insert an expanded variable value, which name we already know, doing
166 * search an replace on a string. */
167 kKmkCcExpInstr_SearchAndReplacePlainVariable,
168 /** Insert the output of function that requires no argument expansion. */
169 kKmkCcExpInstr_PlainFunction,
170 /** Insert the output of function that requires dynamic expansion of one ore
171 * more arguments. (Dynamic is perhaps not such a great name, but whatever.) */
172 kKmkCcExpInstr_DynamicFunction,
173 /** Jump to a new instruction block. */
174 kKmkCcExpInstr_Jump,
175 /** We're done, return. Has no specific structure. */
176 kKmkCcExpInstr_Return,
177 /** The end of valid instructions (exclusive). */
178 kKmkCcExpInstr_End
179} KMKCCEXPINSTR;
180
181/** Instruction core. */
182typedef struct kmk_cc_exp_core
183{
184 /** The instruction opcode number (KMKCCEXPINSTR). */
185 KMKCCEXPINSTR enmOpCode;
186} KMKCCEXPCORE;
187typedef KMKCCEXPCORE *PKMKCCEXPCORE;
188
189/**
190 * String expansion subprogram.
191 */
192#pragma pack(1) /* save some precious bytes */
193typedef struct kmk_cc_exp_subprog
194{
195 /** Pointer to the first instruction. */
196 PKMKCCEXPCORE pFirstInstr;
197 /** Statistics. */
198 KMKCCEXPSTATS Stats;
199} KMKCCEXPSUBPROG;
200#pragma pack()
201typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG;
202KMK_CC_STATIC_ASSERT(sizeof(KMKCCEXPSUBPROG) == 12 || sizeof(void *) != 8);
203
204
205/**
206 * String expansion subprogram or plain string.
207 */
208#pragma pack(1) /* save some precious bytes */
209typedef struct kmk_cc_exp_subprog_or_string
210{
211 /** Either a plain string pointer or a subprogram. */
212 union
213 {
214 /** Subprogram for expanding this argument. */
215 KMKCCEXPSUBPROG Subprog;
216 /** Pointer to the plain string. */
217 struct
218 {
219 /** Pointer to the string. */
220 const char *psz;
221 /** String length. */
222 uint32_t cch;
223 } Plain;
224 } u;
225 /** Set if subprogram (u.Subprog), clear if plain string (u.Plain). */
226 uint8_t fSubprog;
227 /** Set if the plain string is kept in the variable_strcache.
228 * @remarks Here rather than in u.Plain to make use of alignment padding. */
229 uint8_t fPlainIsInVarStrCache;
230 /** Context/user specific. */
231 uint8_t bUser;
232 /** Context/user specific #2. */
233 uint8_t bUser2;
234} KMKCCEXPSUBPROGORPLAIN;
235#pragma pack()
236typedef KMKCCEXPSUBPROGORPLAIN *PKMKCCEXPSUBPROGORPLAIN;
237KMK_CC_STATIC_ASSERT( sizeof(void *) == 8
238 ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 16
239 : sizeof(void *) == 4
240 ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 12
241 : 1);
242
243/**
244 * kKmkCcExpInstr_CopyString instruction format.
245 */
246typedef struct kmk_cc_exp_copy_string
247{
248 /** The core instruction. */
249 KMKCCEXPCORE Core;
250 /** The number of bytes to copy. */
251 uint32_t cchCopy;
252 /** Pointer to the source string (not terminated at cchCopy). */
253 const char *pachSrc;
254} KMKCCEXPCOPYSTRING;
255typedef KMKCCEXPCOPYSTRING *PKMKCCEXPCOPYSTRING;
256
257/**
258 * kKmkCcExpInstr_PlainVariable instruction format.
259 */
260typedef struct kmk_cc_exp_plain_variable
261{
262 /** The core instruction. */
263 KMKCCEXPCORE Core;
264 /** The name of the variable (points into variable_strcache). */
265 const char *pszName;
266} KMKCCEXPPLAINVAR;
267typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR;
268
269/**
270 * kKmkCcExpInstr_DynamicVariable instruction format.
271 */
272typedef struct kmk_cc_exp_dynamic_variable
273{
274 /** The core instruction. */
275 KMKCCEXPCORE Core;
276 /** The subprogram that will give us the variable name. */
277 KMKCCEXPSUBPROG Subprog;
278 /** Where to continue after this instruction. (This is necessary since the
279 * instructions of the subprogram are emitted after this instruction.) */
280 PKMKCCEXPCORE pNext;
281} KMKCCEXPDYNVAR;
282typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR;
283
284/**
285 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction format.
286 */
287typedef struct kmk_cc_exp_sr_plain_variable
288{
289 /** The core instruction. */
290 KMKCCEXPCORE Core;
291 /** Where to continue after this instruction. (This is necessary since the
292 * instruction contains string data of variable size.) */
293 PKMKCCEXPCORE pNext;
294 /** The name of the variable (points into variable_strcache). */
295 const char *pszName;
296 /** Search pattern. */
297 const char *pszSearchPattern;
298 /** Replacement pattern. */
299 const char *pszReplacePattern;
300 /** Offset into pszSearchPattern of the significant '%' char. */
301 uint32_t offPctSearchPattern;
302 /** Offset into pszReplacePattern of the significant '%' char. */
303 uint32_t offPctReplacePattern;
304} KMKCCEXPSRPLAINVAR;
305typedef KMKCCEXPSRPLAINVAR *PKMKCCEXPSRPLAINVAR;
306
307/**
308 * Instruction format parts common to both kKmkCcExpInstr_PlainFunction and
309 * kKmkCcExpInstr_DynamicFunction.
310 */
311typedef struct kmk_cc_exp_function_core
312{
313 /** The core instruction. */
314 KMKCCEXPCORE Core;
315 /** Number of arguments. */
316 uint32_t cArgs; /**< @todo uint16_t to save 7 bytes of unecessary alignment padding on 64-bit systems, or merge fDirty into this member. */
317 /** Set if the function could be modifying the input arguments. */
318 uint8_t fDirty;
319 /** Where to continue after this instruction. (This is necessary since the
320 * instructions are of variable size and may be followed by string data.) */
321 PKMKCCEXPCORE pNext;
322 /**
323 * Pointer to the function table entry.
324 *
325 * @returns New variable buffer position.
326 * @param pchDst Current variable buffer position.
327 * @param papszArgs Pointer to a NULL terminated array of argument strings.
328 * @param pszFuncName The name of the function being called.
329 */
330 char * (*pfnFunction)(char *pchDst, char **papszArgs, const char *pszFuncName);
331 /** Pointer to the function name in the variable string cache. */
332 const char *pszFuncName;
333} KMKCCEXPFUNCCORE;
334typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE;
335
336/**
337 * Instruction format for kKmkCcExpInstr_PlainFunction.
338 */
339typedef struct kmk_cc_exp_plain_function
340{
341 /** The bits comment to both plain and dynamic functions. */
342 KMKCCEXPFUNCCORE FnCore;
343 /** Variable sized argument list (cArgs + 1 in length, last entry is NULL).
344 * The string pointers are to memory following this instruction, to memory in
345 * the next block or to memory in the variable / makefile we're working on
346 * (if zero terminated appropriately). */
347 const char *apszArgs[1];
348} KMKCCEXPPLAINFUNC;
349typedef KMKCCEXPPLAINFUNC *PKMKCCEXPPLAINFUNC;
350/** Calculates the size of an KMKCCEXPPLAINFUNC structure with the apszArgs
351 * member holding a_cArgs entries plus a NULL terminator. */
352#define KMKCCEXPPLAINFUNC_SIZE(a_cArgs) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, (a_cArgs) + 1)
353
354/**
355 * Instruction format for kKmkCcExpInstr_DynamicFunction.
356 */
357typedef struct kmk_cc_exp_dyn_function
358{
359 /** The bits comment to both plain and dynamic functions. */
360 KMKCCEXPFUNCCORE FnCore;
361 /** Variable sized argument list (FnCore.cArgs in length).
362 * The subprograms / strings are allocated after this array (or in the next
363 * block). */
364 KMKCCEXPSUBPROGORPLAIN aArgs[1];
365} KMKCCEXPDYNFUNC;
366typedef KMKCCEXPDYNFUNC *PKMKCCEXPDYNFUNC;
367/** Calculates the size of an KMKCCEXPDYNFUNC structure with the apszArgs
368 * member holding a_cArgs entries (no zero terminator). */
369#define KMKCCEXPDYNFUNC_SIZE(a_cArgs) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, a_cArgs)
370
371/**
372 * Instruction format for kKmkCcExpInstr_Jump.
373 */
374typedef struct kmk_cc_exp_jump
375{
376 /** The core instruction. */
377 KMKCCEXPCORE Core;
378 /** Where to jump to (new instruction block, typically). */
379 PKMKCCEXPCORE pNext;
380} KMKCCEXPJUMP;
381typedef KMKCCEXPJUMP *PKMKCCEXPJUMP;
382
383/**
384 * String expansion program.
385 */
386typedef struct kmk_cc_expandprog
387{
388 /** Pointer to the first instruction for this program. */
389 PKMKCCEXPCORE pFirstInstr;
390 /** List of blocks for this program (LIFO). */
391 PKMKCCBLOCK pBlockTail;
392 /** Statistics. */
393 KMKCCEXPSTATS Stats;
394#ifdef KMK_CC_STRICT
395 /** The hash of the input string. Used to check that we get all the change
396 * notifications we require. */
397 uint32_t uInputHash;
398#endif
399 /** Reference count. */
400 uint32_t volatile cRefs;
401} KMKCCEXPPROG;
402/** Pointer to a string expansion program. */
403typedef KMKCCEXPPROG *PKMKCCEXPPROG;
404
405/** @} */
406
407
408/** @name Makefile Evaluation
409 * @{ */
410
411/** Pointer to a makefile evaluation program. */
412typedef struct kmk_cc_evalprog *PKMKCCEVALPROG;
413
414/**
415 * Makefile evaluation instructions.
416 */
417typedef enum KMKCCEVALINSTR
418{
419 /** Jump instruction - KMKCCEVALJUMP. */
420 kKmkCcEvalInstr_jump = 0,
421
422 /** [local|override|export] variable = value - KMKCCEVALASSIGN.
423 * @note Can be used for target-specific variables. */
424 kKmkCcEvalInstr_assign_recursive,
425 /** [local|override|export] variable := value - KMKCCEVALASSIGN.
426 * @note Can be used for target-specific variables. */
427 kKmkCcEvalInstr_assign_simple,
428 /** [local|override|export] variable += value - KMKCCEVALASSIGN.
429 * @note Can be used for target-specific variables. */
430 kKmkCcEvalInstr_assign_append,
431 /** [local|override|export] variable -= value - KMKCCEVALASSIGN.
432 * @note Can be used for target-specific variables. */
433 kKmkCcEvalInstr_assign_prepend,
434 /** [local|override|export] variable ?= value - KMKCCEVALASSIGN.
435 * @note Can be used for target-specific variables. */
436 kKmkCcEvalInstr_assign_if_new,
437 /** [local|override|export] define variable ... endef - KMKCCEVALASSIGNDEF. */
438 kKmkCcEvalInstr_assign_define,
439
440 /** export variable1 [variable2...] - KMKCCEVALEXPORT. */
441 kKmkCcEvalInstr_export,
442 /** unexport variable1 [variable2...] - KMKCCEVALEXPORT. */
443 kKmkCcEvalInstr_unexport,
444 /** export - KMKCCEVALCORE. */
445 kKmkCcEvalInstr_export_all,
446 /** unexport - KMKCCEVALCORE. */
447 kKmkCcEvalInstr_unexport_all,
448
449 /** [else] ifdef variable - KMKCCEVALIFDEFPLAIN. */
450 kKmkCcEvalInstr_ifdef_plain,
451 /** [else] ifndef variable - KMKCCEVALIFDEFPLAIN. */
452 kKmkCcEvalInstr_ifndef_plain,
453 /** [else] ifdef variable - KMKCCEVALIFDEFDYNAMIC. */
454 kKmkCcEvalInstr_ifdef_dynamic,
455 /** [else] ifndef variable - KMKCCEVALIFDEFDYNAMIC. */
456 kKmkCcEvalInstr_ifndef_dynamic,
457 /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */
458 kKmkCcEvalInstr_ifeq,
459 /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */
460 kKmkCcEvalInstr_ifneq,
461 /** [else] if1of (set-a,set-b) - KMKCCEVALIF1OF. */
462 kKmkCcEvalInstr_if1of,
463 /** [else] ifn1of (set-a,set-b) - KMKCCEVALIF1OF. */
464 kKmkCcEvalInstr_ifn1of,
465 /** [else] if expr - KMKCCEVALIFEXPR. */
466 kKmkCcEvalInstr_if,
467
468 /** include file1 [file2...] - KMKCCEVALINCLUDE. */
469 kKmkCcEvalInstr_include,
470 /** [sinclude|-include] file1 [file2...] - KMKCCEVALINCLUDE. */
471 kKmkCcEvalInstr_include_silent,
472 /** includedep file1 [file2...] - KMKCCEVALINCLUDE. */
473 kKmkCcEvalInstr_includedep,
474 /** includedep-queue file1 [file2...] - KMKCCEVALINCLUDE. */
475 kKmkCcEvalInstr_includedep_queue,
476 /** includedep-flush file1 [file2...] - KMKCCEVALINCLUDE. */
477 kKmkCcEvalInstr_includedep_flush,
478
479 /** Recipe without commands (defines dependencies) - KMKCCEVALRECIPE. */
480 kKmkCcEvalInstr_recipe_no_commands,
481 /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
482 kKmkCcEvalInstr_recipe_start_normal,
483 /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
484 kKmkCcEvalInstr_recipe_start_double_colon,
485 /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
486 kKmkCcEvalInstr_recipe_start_pattern,
487 /** Adds more commands to the current recipe - KMKCCEVALRECIPECOMMANDS. */
488 kKmkCcEvalInstr_recipe_commands,
489 /** Adds more commands to the current recipe - KMKCCEVALRECIPECOMMANDS. */
490 kKmkCcEvalInstr_recipe_vari,
491 /** Special instruction for indicating the end of the recipe commands - KMKCCEVALCORE. */
492 kKmkCcEvalInstr_recipe_end,
493 /** Cancel previously defined pattern rule - KMKCCEVALRECIPE. */
494 kKmkCcEvalInstr_recipe_cancel_pattern,
495
496 /** vpath pattern directories - KMKCCEVALVPATH. */
497 kKmkCcEvalInstr_vpath,
498 /** vpath pattern directories - KMKCCEVALVPATH. */
499 kKmkCcEvalInstr_vpath_clear_pattern,
500 /** vpath - KMKCCEVALCORE. */
501 kKmkCcEvalInstr_vpath_clear_all,
502
503 /** The end of valid instructions (exclusive). */
504 kKmkCcEvalInstr_End
505} KMKCCEVALINSTR;
506
507/**
508 * Instruction core common to all instructions.
509 */
510typedef struct kmk_cc_eval_core
511{
512 /** The instruction opcode number (KMKCCEVALINSTR). */
513 KMKCCEVALINSTR enmOpCode;
514 /** The line number in the source this statement is associated with. */
515 unsigned iLine;
516} KMKCCEVALCORE;
517/** Pointer to an instruction core structure. */
518typedef KMKCCEVALCORE *PKMKCCEVALCORE;
519
520/**
521 * Instruction format for kKmkCcEvalInstr_jump.
522 */
523typedef struct kmk_cc_eval_jump
524{
525 /** The core instruction. */
526 KMKCCEVALCORE Core;
527 /** Where to jump to (new instruction block or endif, typically). */
528 PKMKCCEVALCORE pNext;
529} KMKCCEVALJUMP;
530typedef KMKCCEVALJUMP *PKMKCCEVALJUMP;
531
532/**
533 * Instruction format for kKmkCcEvalInstr_assign_recursive,
534 * kKmkCcEvalInstr_assign_simple, kKmkCcEvalInstr_assign_append,
535 * kKmkCcEvalInstr_assign_prepend and kKmkCcEvalInstr_assign_if_new.
536 */
537typedef struct kmk_cc_eval_assign
538{
539 /** The core instruction. */
540 KMKCCEVALCORE Core;
541 /** Whether the 'export' directive was used. */
542 uint8_t fExport;
543 /** Whether the 'override' directive was used. */
544 uint8_t fOverride;
545 /** Whether the 'local' directive was used. */
546 uint8_t fLocal;
547 /** The variable name.
548 * @remarks Plain text names are in variable_strcache. */
549 KMKCCEXPSUBPROGORPLAIN Variable;
550 /** The value or value expression. */
551 KMKCCEXPSUBPROGORPLAIN Value;
552 /** Pointer to the next instruction. */
553 PKMKCCEVALCORE pNext;
554} KMKCCEVALASSIGN;
555typedef KMKCCEVALASSIGN *PKMKCCEVALASSIGN;
556
557/**
558 * Instruction format for kKmkCcEvalInstr_assign_define.
559 */
560typedef struct kmk_cc_eval_assign_define
561{
562 /** The assignment core structure. */
563 KMKCCEVALASSIGN AssignCore;
564 /** Makefile evaluation program compiled from the define.
565 * NULL if it does not compile.
566 * @todo Let's see if this is actually doable... */
567 PKMKCCEVALPROG pEvalProg;
568} KMKCCEVALASSIGNDEF;
569typedef KMKCCEVALASSIGNDEF *PKMKCCEVALASSIGNDEF;
570
571/**
572 * Instruction format for kKmkCcEvalInstr_export and kKmkCcEvalInstr_unexport.
573 */
574typedef struct kmk_cc_eval_export
575{
576 /** The core instruction. */
577 KMKCCEVALCORE Core;
578 /** The number of variables named in aVars. */
579 uint32_t cVars;
580 /** Pointer to the next instruction. */
581 PKMKCCEVALCORE pNext;
582 /** The variable names.
583 * Expressions will be expanded and split on space.
584 * @remarks Plain text names are in variable_strcache. */
585 KMKCCEXPSUBPROGORPLAIN aVars[1];
586} KMKCCEVALEXPORT;
587typedef KMKCCEVALEXPORT *PKMKCCEVALEXPORT;
588/** Calculates the size of an KMKCCEVALEXPORT structure for @a a_cVars. */
589#define KMKCCEVALEXPORT_SIZE(a_cVars) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aVars, a_cVars)
590
591/**
592 * Core structure for all conditionals (kKmkCcEvalInstr_if*).
593 */
594typedef struct kmk_cc_eval_if_core
595{
596 /** The core instruction. */
597 KMKCCEVALCORE Core;
598 /** Condition true: Pointer to the next instruction. */
599 PKMKCCEVALCORE pNextTrue;
600 /** Condition false: Pointer to the next instruction (i.e. 'else if*'
601 * or whatever follows 'else' / 'endif'. */
602 PKMKCCEVALCORE pNextFalse;
603 /** Pointer to the previous conditional for 'else if*' directives.
604 * This is to assist the compilation process. */
605 PKMKCCEVALCORE pPrevCond;
606} KMKCCEVALIFCORE;
607typedef KMKCCEVALIFCORE *PKMKCCEVALIFCORE;
608
609/**
610 * Instruction format for kKmkCcEvalInstr_ifdef_plain and
611 * kKmkCcEvalInstr_ifndef_plain.
612 * The variable name is known at compilation time.
613 */
614typedef struct kmk_cc_eval_ifdef_plain
615{
616 /** The 'if' core structure. */
617 KMKCCEVALIFCORE IfCore;
618 /** The name of the variable (points into variable_strcache). */
619 const char *pszName;
620} KMKCCEVALIFDEFPLAIN;
621typedef KMKCCEVALIFDEFPLAIN *PKMKCCEVALIFDEFPLAIN;
622
623/**
624 * Instruction format for kKmkCcEvalInstr_ifdef_dynamic and
625 * kKmkCcEvalInstr_ifndef_dynamic.
626 * The variable name is dynamically expanded at run time.
627 */
628typedef struct kmk_cc_eval_ifdef_dynamic
629{
630 /** The 'if' core structure. */
631 KMKCCEVALIFCORE IfCore;
632 /** The subprogram that will give us the variable name. */
633 KMKCCEXPSUBPROG NameSubProg;
634} KMKCCEVALIFDEFDYNAMIC;
635KMK_CC_STATIC_ASSERT(sizeof(KMKCCEVALIFDEFDYNAMIC) == 48 || sizeof(void *) != 8);
636typedef KMKCCEVALIFDEFDYNAMIC *PKMKCCEVALIFDEFDYNAMIC;
637
638/**
639 * Instruction format for kKmkCcEvalInstr_ifeq and kKmkCcEvalInstr_ifneq.
640 */
641typedef struct kmk_cc_eval_ifeq
642{
643 /** The 'if' core structure. */
644 KMKCCEVALIFCORE IfCore;
645 /** The left hand side string expression (dynamic or plain). */
646 KMKCCEXPSUBPROGORPLAIN Left;
647 /** The rigth hand side string expression (dynamic or plain). */
648 KMKCCEXPSUBPROGORPLAIN Right;
649} KMKCCEVALIFEQ;
650typedef KMKCCEVALIFEQ *PKMKCCEVALIFEQ;
651
652/**
653 * Instruction format for kKmkCcEvalInstr_if1of and kKmkCcEvalInstr_ifn1of.
654 *
655 * @todo This can be optimized further by pre-hashing plain text items. One of
656 * the sides are usually plain text.
657 */
658typedef struct kmk_cc_eval_if1of
659{
660 /** The 'if' core structure. */
661 KMKCCEVALIFCORE IfCore;
662 /** The left hand side string expression (dynamic or plain). */
663 KMKCCEXPSUBPROGORPLAIN Left;
664 /** The rigth hand side string expression (dynamic or plain). */
665 KMKCCEXPSUBPROGORPLAIN Right;
666} KMKCCEVALIF1OF;
667typedef KMKCCEVALIF1OF *PKMKCCEVALIF1OF;
668
669/**
670 * Instruction format for kKmkCcEvalInstr_if.
671 *
672 * @todo Parse and compile the expression. At least strip whitespace in it.
673 */
674typedef struct kmk_cc_eval_if_expr
675{
676 /** The 'if' core structure. */
677 KMKCCEVALIFCORE IfCore;
678 /** The expression string length. */
679 uint16_t cchExpr;
680 /** The expression string. */
681 char szExpr[1];
682} KMKCCEVALIFEXPR;
683typedef KMKCCEVALIFEXPR *PKMKCCEVALIFEXPR;
684/** Calculates the size of an KMKCCEVALIFEXPR structure for @a a_cchExpr long
685 * expression string (terminator is automatically added). */
686#define KMKCCEVALIFEXPR_SIZE(a_cchExpr) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALIFEXPR, szExpr, (a_cchExpr) + 1)
687
688/**
689 * Instruction format for kKmkCcEvalInstr_include,
690 * kKmkCcEvalInstr_include_silent, kKmkCcEvalInstr_includedep,
691 * kKmkCcEvalInstr_includedep_queue, kKmkCcEvalInstr_includedep_flush.
692 */
693typedef struct kmk_cc_eval_include
694{
695 /** The core instruction. */
696 KMKCCEVALCORE Core;
697 /** The number of files. */
698 uint32_t cFiles;
699 /** Pointer to the next instruction (subprogs and strings after this one). */
700 PKMKCCEVALCORE pNext;
701 /** The files to be included.
702 * Expressions will be expanded and split on space.
703 * @todo Plain text file name could be replaced by file string cache entries. */
704 KMKCCEXPSUBPROGORPLAIN aFiles[1];
705} KMKCCEVALINCLUDE;
706typedef KMKCCEVALINCLUDE *PKMKCCEVALINCLUDE;
707/** Calculates the size of an KMKCCEVALINCLUDE structure for @a a_cFiles files. */
708#define KMKCCEVALINCLUDE_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALINCLUDE, aFiles, a_cFiles)
709
710/**
711 * Instruction format for kKmkCcEvalInstr_recipe_no_commands,
712 * kKmkCcEvalInstr_recipe_start_normal,
713 * kKmkCcEvalInstr_recipe_start_double_colon, kKmkCcEvalInstr_includedep_queue,
714 * kKmkCcEvalInstr_recipe_start_pattern.
715 */
716typedef struct kmk_cc_eval_recipe
717{
718 /** The core instruction. */
719 KMKCCEVALCORE Core;
720 /** The total number of files and dependencies in aFilesAndDeps. */
721 uint16_t cFilesAndDeps;
722
723 /** Number of targets (from index 0).
724 * This is always 1 if this is an explicit multitarget or pattern recipe,
725 * indicating the main target. */
726 uint16_t cTargets;
727 /** Explicit multitarget & patterns: First always made target. */
728 uint16_t iFirstAlwaysMadeTargets;
729 /** Explicit multitarget & patterns: Number of always targets. */
730 uint16_t cAlwaysMadeTargets;
731 /** Explicit multitarget: First maybe made target. */
732 uint16_t iFirstMaybeTarget;
733 /** Explicit multitarget: Number of maybe made targets. */
734 uint16_t cMaybeTargets;
735
736 /** First dependency. */
737 uint16_t iFirstDep;
738 /** Number of ordinary dependnecies. */
739 uint16_t cDeps;
740 /** First order only dependency. */
741 uint16_t iFirstOrderOnlyDep;
742 /** Number of ordinary dependnecies. */
743 uint16_t cOrderOnlyDeps;
744
745 /** Pointer to the next instruction (subprogs and strings after this one). */
746 PKMKCCEVALCORE pNext;
747 /** The .MUST_MAKE variable value, if present.
748 * If not present, this is a zero length plain string. */
749 KMKCCEXPSUBPROGORPLAIN MustMake;
750 /** The target files and dependencies.
751 * This is sorted into several sections, as defined by the above indexes and
752 * counts. Expressions will be expanded and split on space.
753 *
754 * The KMKCCEXPSUBPROGORPLAIN::bUser member is used to indicate secondary
755 * expansion for a plain text entry.
756 *
757 * @todo Plain text file name could be replaced by file string cache entries. */
758 KMKCCEXPSUBPROGORPLAIN aFilesAndDeps[1];
759} KMKCCEVALRECIPE;
760typedef KMKCCEVALRECIPE *PKMKCCEVALRECIPE;
761/** Calculates the size of an KMKCCEVALRECIPE structure for @a a_cFiles
762 * files. */
763#define KMKCCEVALRECIPE_SIZE(a_cFilesAndDeps) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPE, aFilesAndDeps, a_cFilesAndDeps)
764
765/**
766 * Instruction format for kKmkCcEvalInstr_recipe_commands.
767 */
768typedef struct kmk_cc_eval_recipe_commands
769{
770 /** The core instruction. */
771 KMKCCEVALCORE Core;
772 /** The number of search directories. */
773 uint32_t cCommands;
774 /** Pointer to the next instruction (subprogs and strings after this one). */
775 PKMKCCEVALCORE pNext;
776 /** Commands to add to the current recipe.
777 * Expressions will be expanded and split on space. */
778 KMKCCEXPSUBPROGORPLAIN aCommands[1];
779} KMKCCEVALRECIPECOMMANDS;
780typedef KMKCCEVALRECIPECOMMANDS *PKMKCCEVALRECIPECOMMANDS;
781/** Calculates the size of an KMKCCEVALRECIPECOMMANDS structure for
782 * @a a_cCommands commands. */
783#define KMKCCEVALRECIPECOMMANDS_SIZE(a_cCommands) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPECOMMANDS, aCommands, a_cCommands)
784
785/**
786 * Instruction format for kKmkCcEvalInstr_vpath and
787 * kKmkCcEvalInstr_vpath_clear_pattern.
788 */
789typedef struct kmk_cc_eval_vpath
790{
791 /** The core instruction. */
792 KMKCCEVALCORE Core;
793 /** The number of search directories.
794 * This will be zero for kKmkCcEvalInstr_vpath_clear_pattern. */
795 uint32_t cDirs;
796 /** Pointer to the next instruction (subprogs and strings after this one). */
797 PKMKCCEVALCORE pNext;
798 /** The pattern. */
799 KMKCCEXPSUBPROGORPLAIN Pattern;
800 /** The directory. Expressions will be expanded and split on space. */
801 KMKCCEXPSUBPROGORPLAIN aDirs[1];
802} KMKCCEVALVPATH;
803typedef KMKCCEVALVPATH *PKMKCCEVALVPATH;
804/** Calculates the size of an KMKCCEVALVPATH structure for @a a_cFiles files. */
805#define KMKCCEVALVPATH_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aDirs, a_cDirs)
806
807
808/**
809 * Makefile evaluation program.
810 */
811typedef struct kmk_cc_evalprog
812{
813 /** Pointer to the first instruction for this program. */
814 PKMKCCEVALCORE pFirstInstr;
815 /** List of blocks for this program (LIFO). */
816 PKMKCCBLOCK pBlockTail;
817
818} KMKCCEVALPROG;
819
820/** @} */
821
822
823/*********************************************************************************************************************************
824* Global Variables *
825*********************************************************************************************************************************/
826static uint32_t g_cVarForExpandCompilations = 0;
827static uint32_t g_cVarForExpandExecs = 0;
828#ifdef KMK_CC_WITH_STATS
829static uint32_t g_cBlockAllocated = 0;
830static uint32_t g_cbAllocated = 0;
831static uint32_t g_cBlocksAllocatedExpProgs = 0;
832static uint32_t g_cbAllocatedExpProgs = 0;
833static uint32_t g_cSingleBlockExpProgs = 0;
834static uint32_t g_cTwoBlockExpProgs = 0;
835static uint32_t g_cMultiBlockExpProgs = 0;
836static uint32_t g_cbUnusedMemExpProgs = 0;
837#endif
838
839
840/*********************************************************************************************************************************
841* Internal Functions *
842*********************************************************************************************************************************/
843static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg);
844static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcch);
845
846
847/**
848 * Initializes global variables for the 'compiler'.
849 */
850void kmk_cc_init(void)
851{
852}
853
854
855/**
856 * Prints stats (for kmk -p).
857 */
858void kmk_cc_print_stats(void)
859{
860 puts(_("\n# The kmk 'compiler' and kmk 'program executor':\n"));
861
862 printf(_("# Variables compiled for string expansion: %6u\n"), g_cVarForExpandCompilations);
863 printf(_("# Variables string expansion runs: %6u\n"), g_cVarForExpandExecs);
864 printf(_("# String expansion runs per compile: %6u\n"), g_cVarForExpandExecs / g_cVarForExpandCompilations);
865#ifdef KMK_CC_WITH_STATS
866 printf(_("# Single alloc block exp progs: %6u (%u%%)\n"
867 "# Two alloc block exp progs: %6u (%u%%)\n"
868 "# Three or more alloc block exp progs: %6u (%u%%)\n"
869 ),
870 g_cSingleBlockExpProgs, (uint32_t)((uint64_t)g_cSingleBlockExpProgs * 100 / g_cVarForExpandCompilations),
871 g_cTwoBlockExpProgs, (uint32_t)((uint64_t)g_cTwoBlockExpProgs * 100 / g_cVarForExpandCompilations),
872 g_cMultiBlockExpProgs, (uint32_t)((uint64_t)g_cMultiBlockExpProgs * 100 / g_cVarForExpandCompilations));
873 printf(_("# Total amount of memory for exp progs: %8u bytes\n"
874 "# in: %6u blocks\n"
875 "# avg block size: %6u bytes\n"
876 "# unused memory: %8u bytes (%u%%)\n"
877 "# avg unused memory per block: %6u bytes\n"
878 "\n"),
879 g_cbAllocatedExpProgs, g_cBlocksAllocatedExpProgs, g_cbAllocatedExpProgs / g_cBlocksAllocatedExpProgs,
880 g_cbUnusedMemExpProgs, (uint32_t)((uint64_t)g_cbUnusedMemExpProgs * 100 / g_cbAllocatedExpProgs),
881 g_cbUnusedMemExpProgs / g_cBlocksAllocatedExpProgs);
882
883 printf(_("# Total amount of block mem allocated: %8u bytes\n"), g_cbAllocated);
884 printf(_("# Total number of block allocated: %8u\n"), g_cBlockAllocated);
885 printf(_("# Average block size: %8u byte\n"), g_cbAllocated / g_cBlockAllocated);
886#endif
887
888 puts("");
889}
890
891
892/*
893 *
894 * Various utility functions.
895 * Various utility functions.
896 * Various utility functions.
897 *
898 */
899
900/**
901 * Counts the number of dollar chars in the string.
902 *
903 * @returns Number of dollar chars.
904 * @param pchStr The string to search (does not need to be zero
905 * terminated).
906 * @param cchStr The length of the string.
907 */
908static uint32_t kmk_cc_count_dollars(const char *pchStr, uint32_t cchStr)
909{
910 uint32_t cDollars = 0;
911 const char *pch;
912 while ((pch = memchr(pchStr, '$', cchStr)) != NULL)
913 {
914 cDollars++;
915 cchStr -= pch - pchStr + 1;
916 pchStr = pch + 1;
917 }
918 return cDollars;
919}
920
921#ifdef KMK_CC_STRICT
922/**
923 * Used to check that function arguments are left alone.
924 * @returns Updated hash.
925 * @param uHash The current hash value.
926 * @param psz The string to hash.
927 */
928static uint32_t kmk_cc_debug_string_hash(uint32_t uHash, const char *psz)
929{
930 unsigned char ch;
931 while ((ch = *(unsigned char const *)psz++) != '\0')
932 uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch;
933 return uHash;
934}
935
936/**
937 * Used to check that function arguments are left alone.
938 * @returns Updated hash.
939 * @param uHash The current hash value.
940 * @param pch The string to hash, not terminated.
941 * @param cch The number of chars to hash.
942 */
943static uint32_t kmk_cc_debug_string_hash_n(uint32_t uHash, const char *pch, uint32_t cch)
944{
945 while (cch-- > 0)
946 {
947 unsigned char ch = *(unsigned char const *)pch++;
948 uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch;
949 }
950 return uHash;
951}
952
953#endif
954
955
956
957/*
958 *
959 * The allocator.
960 * The allocator.
961 * The allocator.
962 *
963 */
964
965
966/**
967 * For the first allocation using the block allocator.
968 *
969 * @returns Pointer to the first allocation (@a cbFirst in size).
970 * @param ppBlockTail Where to return the pointer to the first block.
971 * @param cbFirst The size of the first allocation.
972 * @param cbHint Hint about how much memory we might be needing.
973 */
974static void *kmk_cc_block_alloc_first(PKMKCCBLOCK *ppBlockTail, size_t cbFirst, size_t cbHint)
975{
976 uint32_t cbBlock;
977 PKMKCCBLOCK pNewBlock;
978
979 KMK_CC_ASSERT_ALIGNED(cbFirst, sizeof(void *));
980
981 /*
982 * Turn the hint into a block size.
983 */
984 if (cbHint <= 512)
985 {
986 if (cbHint <= 256)
987 cbBlock = 128;
988 else
989 cbBlock = 256;
990 }
991 else if (cbHint < 2048)
992 cbBlock = 1024;
993 else if (cbHint < 3072)
994 cbBlock = 2048;
995 else
996 cbBlock = 4096;
997
998 /*
999 * Allocate and initialize the first block.
1000 */
1001 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock);
1002 pNewBlock->cbBlock = cbBlock;
1003 pNewBlock->offNext = sizeof(*pNewBlock) + cbFirst;
1004 pNewBlock->pNext = NULL;
1005 *ppBlockTail = pNewBlock;
1006
1007#ifdef KMK_CC_WITH_STATS
1008 g_cBlockAllocated++;
1009 g_cbAllocated += cbBlock;
1010#endif
1011
1012 return pNewBlock + 1;
1013}
1014
1015
1016/**
1017 * Used for getting the address of the next instruction.
1018 *
1019 * @returns Pointer to the next allocation.
1020 * @param pBlockTail The allocator tail pointer.
1021 */
1022static void *kmk_cc_block_get_next_ptr(PKMKCCBLOCK pBlockTail)
1023{
1024 return (char *)pBlockTail + pBlockTail->offNext;
1025}
1026
1027
1028/**
1029 * Realigns the allocator after doing byte or string allocations.
1030 *
1031 * @param ppBlockTail Pointer to the allocator tail pointer.
1032 */
1033static void kmk_cc_block_realign(PKMKCCBLOCK *ppBlockTail)
1034{
1035 PKMKCCBLOCK pBlockTail = *ppBlockTail;
1036 if (pBlockTail->offNext & (sizeof(void *) - 1))
1037 {
1038 pBlockTail->offNext = (pBlockTail->offNext + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
1039 KMK_CC_ASSERT(pBlockTail->cbBlock - pBlockTail->offNext >= sizeof(KMKCCEXPJUMP));
1040 }
1041}
1042
1043
1044/**
1045 * Grows the allocation with another block, byte allocator case.
1046 *
1047 * @returns Pointer to the byte allocation.
1048 * @param ppBlockTail Pointer to the allocator tail pointer.
1049 * @param cb The number of bytes to allocate.
1050 */
1051static void *kmk_cc_block_byte_alloc_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb)
1052{
1053 PKMKCCBLOCK pOldBlock = *ppBlockTail;
1054 PKMKCCBLOCK pPrevBlock = pOldBlock->pNext;
1055 PKMKCCBLOCK pNewBlock;
1056 uint32_t cbBlock;
1057
1058 /*
1059 * Check if there accidentally is some space left in the previous block first.
1060 */
1061 if ( pPrevBlock
1062 && pPrevBlock->cbBlock - pPrevBlock->offNext >= cb)
1063 {
1064 void *pvRet = (char *)pPrevBlock + pPrevBlock->offNext;
1065 pPrevBlock->offNext += cb;
1066 return pvRet;
1067 }
1068
1069 /*
1070 * Allocate a new block.
1071 */
1072
1073 /* Figure the block size. */
1074 cbBlock = pOldBlock->cbBlock;
1075 while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb)
1076 cbBlock *= 2;
1077
1078 /* Allocate and initialize the block it with the new instruction already accounted for. */
1079 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock);
1080 pNewBlock->cbBlock = cbBlock;
1081 pNewBlock->offNext = sizeof(*pNewBlock) + cb;
1082 pNewBlock->pNext = pOldBlock;
1083 *ppBlockTail = pNewBlock;
1084
1085#ifdef KMK_CC_WITH_STATS
1086 g_cBlockAllocated++;
1087 g_cbAllocated += cbBlock;
1088#endif
1089
1090 return pNewBlock + 1;
1091}
1092
1093
1094/**
1095 * Make a byte allocation.
1096 *
1097 * Must call kmk_cc_block_realign() when done doing byte and string allocations.
1098 *
1099 * @returns Pointer to the byte allocation (byte aligned).
1100 * @param ppBlockTail Pointer to the allocator tail pointer.
1101 * @param cb The number of bytes to allocate.
1102 */
1103static void *kmk_cc_block_byte_alloc(PKMKCCBLOCK *ppBlockTail, uint32_t cb)
1104{
1105 PKMKCCBLOCK pBlockTail = *ppBlockTail;
1106 uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext;
1107
1108 KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP));
1109 if (cbLeft >= cb + sizeof(KMKCCEXPJUMP))
1110 {
1111 void *pvRet = (char *)pBlockTail + pBlockTail->offNext;
1112 pBlockTail->offNext += cb;
1113 return pvRet;
1114 }
1115 return kmk_cc_block_byte_alloc_grow(ppBlockTail, cb);
1116}
1117
1118
1119/**
1120 * Duplicates the given string in a byte allocation.
1121 *
1122 * Must call kmk_cc_block_realign() when done doing byte and string allocations.
1123 *
1124 * @returns Pointer to the byte allocation (byte aligned).
1125 * @param ppBlockTail Pointer to the allocator tail pointer.
1126 * @param cb The number of bytes to allocate.
1127 */
1128static const char *kmk_cc_block_strdup(PKMKCCBLOCK *ppBlockTail, const char *pachStr, uint32_t cchStr)
1129{
1130 char *pszCopy;
1131 if (cchStr)
1132 {
1133 pszCopy = kmk_cc_block_byte_alloc(ppBlockTail, cchStr + 1);
1134 memcpy(pszCopy, pachStr, cchStr);
1135 pszCopy[cchStr] = '\0';
1136 return pszCopy;
1137 }
1138 return "";
1139}
1140
1141
1142/**
1143 * Grows the allocation with another block, string expansion program case.
1144 *
1145 * @returns Pointer to a string expansion instruction core.
1146 * @param ppBlockTail Pointer to the allocator tail pointer.
1147 * @param cb The number of bytes to allocate.
1148 */
1149static PKMKCCEXPCORE kmk_cc_block_alloc_exp_grow(PKMKCCBLOCK *ppBlockTail, uint32_t cb)
1150{
1151 PKMKCCBLOCK pOldBlock = *ppBlockTail;
1152 PKMKCCBLOCK pNewBlock;
1153 PKMKCCEXPCORE pRet;
1154 PKMKCCEXPJUMP pJump;
1155
1156 /* Figure the block size. */
1157 uint32_t cbBlock = !pOldBlock->pNext ? 128 : pOldBlock->cbBlock;
1158 while (cbBlock - sizeof(KMKCCEXPJUMP) - sizeof(*pNewBlock) < cb)
1159 cbBlock *= 2;
1160
1161 /* Allocate and initialize the block it with the new instruction already accounted for. */
1162 pNewBlock = (PKMKCCBLOCK)xmalloc(cbBlock);
1163 pNewBlock->cbBlock = cbBlock;
1164 pNewBlock->offNext = sizeof(*pNewBlock) + cb;
1165 pNewBlock->pNext = pOldBlock;
1166 *ppBlockTail = pNewBlock;
1167
1168#ifdef KMK_CC_WITH_STATS
1169 g_cBlockAllocated++;
1170 g_cbAllocated += cbBlock;
1171#endif
1172
1173 pRet = (PKMKCCEXPCORE)(pNewBlock + 1);
1174
1175 /* Emit jump. */
1176 pJump = (PKMKCCEXPJUMP)((char *)pOldBlock + pOldBlock->offNext);
1177 pJump->Core.enmOpCode = kKmkCcExpInstr_Jump;
1178 pJump->pNext = pRet;
1179 pOldBlock->offNext += sizeof(*pJump);
1180 KMK_CC_ASSERT(pOldBlock->offNext <= pOldBlock->cbBlock);
1181
1182 return pRet;
1183}
1184
1185
1186/**
1187 * Allocates a string expansion instruction of size @a cb.
1188 *
1189 * @returns Pointer to a string expansion instruction core.
1190 * @param ppBlockTail Pointer to the allocator tail pointer.
1191 * @param cb The number of bytes to allocate.
1192 */
1193static PKMKCCEXPCORE kmk_cc_block_alloc_exp(PKMKCCBLOCK *ppBlockTail, uint32_t cb)
1194{
1195 PKMKCCBLOCK pBlockTail = *ppBlockTail;
1196 uint32_t cbLeft = pBlockTail->cbBlock - pBlockTail->offNext;
1197
1198 KMK_CC_ASSERT(cbLeft >= sizeof(KMKCCEXPJUMP));
1199 KMK_CC_ASSERT( (cb & (sizeof(void *) - 1)) == 0 || cb == sizeof(KMKCCEXPCORE) /* final */ );
1200
1201 if (cbLeft >= cb + sizeof(KMKCCEXPJUMP))
1202 {
1203 PKMKCCEXPCORE pRet = (PKMKCCEXPCORE)((char *)pBlockTail + pBlockTail->offNext);
1204 pBlockTail->offNext += cb;
1205 return pRet;
1206 }
1207 return kmk_cc_block_alloc_exp_grow(ppBlockTail, cb);
1208}
1209
1210
1211/**
1212 * Frees all memory used by an allocator.
1213 *
1214 * @param ppBlockTail The allocator tail pointer.
1215 */
1216static void kmk_cc_block_free_list(PKMKCCBLOCK pBlockTail)
1217{
1218 while (pBlockTail)
1219 {
1220 PKMKCCBLOCK pThis = pBlockTail;
1221 pBlockTail = pBlockTail->pNext;
1222 free(pThis);
1223 }
1224}
1225
1226 /*
1227 *
1228 * The string expansion compiler.
1229 * The string expansion compiler.
1230 * The string expansion compiler.
1231 *
1232 */
1233
1234
1235/**
1236 * Emits a kKmkCcExpInstr_Return.
1237 *
1238 * @param ppBlockTail Pointer to the allocator tail pointer.
1239 */
1240static void kmk_cc_exp_emit_return(PKMKCCBLOCK *ppBlockTail)
1241{
1242 PKMKCCEXPCORE pCore = kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pCore));
1243 pCore->enmOpCode = kKmkCcExpInstr_Return;
1244}
1245
1246
1247/**
1248 * Checks if a function is known to mess up the arguments its given.
1249 *
1250 * When executing calls to "dirty" functions, all arguments must be duplicated
1251 * on the heap.
1252 *
1253 * @returns 1 if dirty, 0 if clean.
1254 * @param pszFunction The function name.
1255 */
1256static uint8_t kmk_cc_is_dirty_function(const char *pszFunction)
1257{
1258 switch (pszFunction[0])
1259 {
1260 default:
1261 return 0;
1262
1263 case 'e':
1264 if (!strcmp(pszFunction, "eval"))
1265 return 1;
1266 if (!strcmp(pszFunction, "evalctx"))
1267 return 1;
1268 return 0;
1269
1270 case 'f':
1271 if (!strcmp(pszFunction, "filter"))
1272 return 1;
1273 if (!strcmp(pszFunction, "filter-out"))
1274 return 1;
1275 if (!strcmp(pszFunction, "for"))
1276 return 1;
1277 return 0;
1278
1279 case 's':
1280 if (!strcmp(pszFunction, "sort"))
1281 return 1;
1282 return 0;
1283 }
1284}
1285
1286
1287/**
1288 * Emits a function call instruction taking arguments that needs expanding.
1289 *
1290 * @returns 0 on success, non-zero on failure.
1291 * @param ppBlockTail Pointer to the allocator tail pointer.
1292 * @param pszFunction The function name (const string from function.c).
1293 * @param pchArgs Pointer to the arguments expression string, leading
1294 * any blanks has been stripped.
1295 * @param cchArgs The length of the arguments expression string.
1296 * @param cArgs Number of arguments found.
1297 * @param chOpen The char used to open the function call.
1298 * @param chClose The char used to close the function call.
1299 * @param pfnFunction The function implementation.
1300 * @param cMaxArgs Maximum number of arguments the function takes.
1301 */
1302static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction,
1303 const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose,
1304 make_function_ptr_t pfnFunction, unsigned char cMaxArgs)
1305{
1306 uint32_t iArg;
1307
1308 /*
1309 * The function instruction has variable size. The maximum argument count
1310 * isn't quite like the minium one. Zero means no limit. While a non-zero
1311 * value means that any commas beyond the max will be taken to be part of
1312 * the final argument.
1313 */
1314 uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs;
1315 PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPDYNFUNC_SIZE(cActualArgs));
1316 pInstr->FnCore.Core.enmOpCode = kKmkCcExpInstr_DynamicFunction;
1317 pInstr->FnCore.cArgs = cActualArgs;
1318 pInstr->FnCore.pfnFunction = pfnFunction;
1319 pInstr->FnCore.pszFuncName = pszFunction;
1320 pInstr->FnCore.fDirty = kmk_cc_is_dirty_function(pszFunction);
1321
1322 /*
1323 * Parse the arguments. Plain arguments gets duplicated in the program
1324 * memory so that they are terminated and no extra processing is necessary
1325 * later on. ASSUMES that the function implementations do NOT change
1326 * argument memory. Other arguments the compiled into their own expansion
1327 * sub programs.
1328 */
1329 iArg = 0;
1330 for (;;)
1331 {
1332 /* Find the end of the argument. Check for $. */
1333 char ch = '\0';
1334 uint8_t fDollar = 0;
1335 int32_t cDepth = 0;
1336 uint32_t cchThisArg = 0;
1337 while (cchThisArg < cchArgs)
1338 {
1339 ch = pchArgs[cchThisArg];
1340 if (ch == chClose)
1341 {
1342 KMK_CC_ASSERT(cDepth > 0);
1343 if (cDepth > 0)
1344 cDepth--;
1345 }
1346 else if (ch == chOpen)
1347 cDepth++;
1348 else if (ch == ',' && cDepth == 0 && iArg + 1 < cActualArgs)
1349 break;
1350 else if (ch == '$')
1351 fDollar = 1;
1352 cchThisArg++;
1353 }
1354
1355 pInstr->aArgs[iArg].fSubprog = fDollar;
1356 if (fDollar)
1357 {
1358 /* Compile it. */
1359 int rc;
1360 kmk_cc_block_realign(ppBlockTail);
1361 rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchArgs, cchThisArg, &pInstr->aArgs[iArg].u.Subprog);
1362 if (rc != 0)
1363 return rc;
1364 }
1365 else
1366 {
1367 /* Duplicate it. */
1368 pInstr->aArgs[iArg].u.Plain.psz = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg);
1369 pInstr->aArgs[iArg].u.Plain.cch = cchThisArg;
1370 }
1371 iArg++;
1372 if (ch != ',')
1373 break;
1374 pchArgs += cchThisArg + 1;
1375 cchArgs -= cchThisArg + 1;
1376 }
1377 KMK_CC_ASSERT(iArg == cActualArgs);
1378
1379 /*
1380 * Realign the allocator and take down the address of the next instruction.
1381 */
1382 kmk_cc_block_realign(ppBlockTail);
1383 pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
1384 return 0;
1385}
1386
1387
1388/**
1389 * Emits a function call instruction taking plain arguments.
1390 *
1391 * @returns 0 on success, non-zero on failure.
1392 * @param ppBlockTail Pointer to the allocator tail pointer.
1393 * @param pszFunction The function name (const string from function.c).
1394 * @param pchArgs Pointer to the arguments string, leading any blanks
1395 * has been stripped.
1396 * @param cchArgs The length of the arguments string.
1397 * @param cArgs Number of arguments found.
1398 * @param chOpen The char used to open the function call.
1399 * @param chClose The char used to close the function call.
1400 * @param pfnFunction The function implementation.
1401 * @param cMaxArgs Maximum number of arguments the function takes.
1402 */
1403static void kmk_cc_exp_emit_plain_function(PKMKCCBLOCK *ppBlockTail, const char *pszFunction,
1404 const char *pchArgs, uint32_t cchArgs, uint32_t cArgs, char chOpen, char chClose,
1405 make_function_ptr_t pfnFunction, unsigned char cMaxArgs)
1406{
1407 uint32_t iArg;
1408
1409 /*
1410 * The function instruction has variable size. The maximum argument count
1411 * isn't quite like the minium one. Zero means no limit. While a non-zero
1412 * value means that any commas beyond the max will be taken to be part of
1413 * the final argument.
1414 */
1415 uint32_t cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs;
1416 PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPPLAINFUNC_SIZE(cActualArgs));
1417 pInstr->FnCore.Core.enmOpCode = kKmkCcExpInstr_PlainFunction;
1418 pInstr->FnCore.cArgs = cActualArgs;
1419 pInstr->FnCore.pfnFunction = pfnFunction;
1420 pInstr->FnCore.pszFuncName = pszFunction;
1421 pInstr->FnCore.fDirty = kmk_cc_is_dirty_function(pszFunction);
1422
1423 /*
1424 * Parse the arguments. Plain arguments gets duplicated in the program
1425 * memory so that they are terminated and no extra processing is necessary
1426 * later on. ASSUMES that the function implementations do NOT change
1427 * argument memory.
1428 */
1429 iArg = 0;
1430 for (;;)
1431 {
1432 /* Find the end of the argument. */
1433 char ch = '\0';
1434 int32_t cDepth = 0;
1435 uint32_t cchThisArg = 0;
1436 while (cchThisArg < cchArgs)
1437 {
1438 ch = pchArgs[cchThisArg];
1439 if (ch == chClose)
1440 {
1441 KMK_CC_ASSERT(cDepth > 0);
1442 if (cDepth > 0)
1443 cDepth--;
1444 }
1445 else if (ch == chOpen)
1446 cDepth++;
1447 else if (ch == ',' && cDepth == 0 && iArg + 1 < cActualArgs)
1448 break;
1449 cchThisArg++;
1450 }
1451
1452 /* Duplicate it. */
1453 pInstr->apszArgs[iArg++] = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg);
1454 if (ch != ',')
1455 break;
1456 pchArgs += cchThisArg + 1;
1457 cchArgs -= cchThisArg + 1;
1458 }
1459
1460 KMK_CC_ASSERT(iArg == cActualArgs);
1461 pInstr->apszArgs[iArg] = NULL;
1462
1463 /*
1464 * Realign the allocator and take down the address of the next instruction.
1465 */
1466 kmk_cc_block_realign(ppBlockTail);
1467 pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
1468}
1469
1470
1471/**
1472 * Emits a kKmkCcExpInstr_DynamicVariable.
1473 *
1474 * @returns 0 on success, non-zero on failure.
1475 * @param ppBlockTail Pointer to the allocator tail pointer.
1476 * @param pchNameExpr The name of the variable (ASSUMED presistent
1477 * thru-out the program life time).
1478 * @param cchNameExpr The length of the variable name. If zero,
1479 * nothing will be emitted.
1480 */
1481static int kmk_cc_exp_emit_dyn_variable(PKMKCCBLOCK *ppBlockTail, const char *pchNameExpr, uint32_t cchNameExpr)
1482{
1483 PKMKCCEXPDYNVAR pInstr;
1484 int rc;
1485 KMK_CC_ASSERT(cchNameExpr > 0);
1486
1487 pInstr = (PKMKCCEXPDYNVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
1488 pInstr->Core.enmOpCode = kKmkCcExpInstr_DynamicVariable;
1489
1490 rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchNameExpr, cchNameExpr, &pInstr->Subprog);
1491
1492 pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
1493 return rc;
1494}
1495
1496
1497/**
1498 * Emits either a kKmkCcExpInstr_PlainVariable or
1499 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction.
1500 *
1501 * @param ppBlockTail Pointer to the allocator tail pointer.
1502 * @param pchName The name of the variable. (Does not need to be
1503 * valid beyond the call.)
1504 * @param cchName The length of the variable name. If zero,
1505 * nothing will be emitted.
1506 */
1507static void kmk_cc_exp_emit_plain_variable_maybe_sr(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName)
1508{
1509 if (cchName > 0)
1510 {
1511 /*
1512 * Hopefully, we're not expected to do any search and replace on the
1513 * expanded variable string later... Requires both ':' and '='.
1514 */
1515 const char *pchEqual;
1516 const char *pchColon = (const char *)memchr(pchName, ':', cchName);
1517 if ( pchColon == NULL
1518 || (pchEqual = (const char *)memchr(pchColon + 1, ':', cchName - (pchColon - pchName - 1))) == NULL
1519 || pchEqual == pchEqual + 1)
1520 {
1521 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
1522 pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable;
1523 pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName);
1524 }
1525 else if (pchColon != pchName)
1526 {
1527 /*
1528 * Okay, we need to do search and replace the variable value.
1529 * This is performed by patsubst_expand_pat using '%' patterns.
1530 */
1531 uint32_t cchName2 = (uint32_t)(pchColon - pchName);
1532 uint32_t cchSearch = (uint32_t)(pchEqual - pchColon - 1);
1533 uint32_t cchReplace = cchName - cchName2 - cchSearch - 2;
1534 const char *pchPct;
1535 char *psz;
1536 PKMKCCEXPSRPLAINVAR pInstr;
1537
1538 pInstr = (PKMKCCEXPSRPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
1539 pInstr->Core.enmOpCode = kKmkCcExpInstr_SearchAndReplacePlainVariable;
1540 pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName2);
1541
1542 /* Figure out the search pattern, unquoting percent chars.. */
1543 psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchSearch + 2);
1544 psz[0] = '%';
1545 memcpy(psz + 1, pchColon + 1, cchSearch);
1546 psz[1 + cchSearch] = '\0';
1547 pchPct = find_percent(psz + 1); /* also performs unquoting */
1548 if (pchPct)
1549 {
1550 pInstr->pszSearchPattern = psz + 1;
1551 pInstr->offPctSearchPattern = (uint32_t)(pchPct - psz - 1);
1552 }
1553 else
1554 {
1555 pInstr->pszSearchPattern = psz;
1556 pInstr->offPctSearchPattern = 0;
1557 }
1558
1559 /* Figure out the replacement pattern, unquoting percent chars.. */
1560 if (cchReplace == 0)
1561 {
1562 pInstr->pszReplacePattern = "%";
1563 pInstr->offPctReplacePattern = 0;
1564 }
1565 else
1566 {
1567 psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchReplace + 2);
1568 psz[0] = '%';
1569 memcpy(psz + 1, pchEqual + 1, cchReplace);
1570 psz[1 + cchReplace] = '\0';
1571 pchPct = find_percent(psz + 1); /* also performs unquoting */
1572 if (pchPct)
1573 {
1574 pInstr->pszReplacePattern = psz + 1;
1575 pInstr->offPctReplacePattern = (uint32_t)(pchPct - psz - 1);
1576 }
1577 else
1578 {
1579 pInstr->pszReplacePattern = psz;
1580 pInstr->offPctReplacePattern = 0;
1581 }
1582 }
1583
1584 /* Note down where the next instruction is after realigning the allocator. */
1585 kmk_cc_block_realign(ppBlockTail);
1586 pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
1587 }
1588 }
1589}
1590
1591
1592/**
1593 * Emits a kKmkCcExpInstr_CopyString.
1594 *
1595 * @param ppBlockTail Pointer to the allocator tail pointer.
1596 * @param pchStr The string to emit (ASSUMED presistent thru-out
1597 * the program life time).
1598 * @param cchStr The number of chars to copy. If zero, nothing
1599 * will be emitted.
1600 */
1601static void kmk_cc_exp_emit_copy_string(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr)
1602{
1603 if (cchStr > 0)
1604 {
1605 PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
1606 pInstr->Core.enmOpCode = kKmkCcExpInstr_CopyString;
1607 pInstr->cchCopy = cchStr;
1608 pInstr->pachSrc = pchStr;
1609 }
1610}
1611
1612
1613/**
1614 * String expansion compilation function common to both normal and sub programs.
1615 *
1616 * @returns 0 on success, non-zero on failure.
1617 * @param ppBlockTail Pointer to the allocator tail pointer.
1618 * @param pchStr The expression to compile.
1619 * @param cchStr The length of the expression to compile.
1620 */
1621static int kmk_cc_exp_compile_common(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr)
1622{
1623 /*
1624 * Process the string.
1625 */
1626 while (cchStr > 0)
1627 {
1628 /* Look for dollar sign, marks variable expansion or dollar-escape. */
1629 int rc;
1630 const char *pchDollar = memchr(pchStr, '$', cchStr);
1631 if (pchDollar)
1632 {
1633 /*
1634 * Check for multiple dollar chars.
1635 */
1636 uint32_t offDollar = (uint32_t)(pchDollar - pchStr);
1637 uint32_t cDollars = 1;
1638 while ( offDollar + cDollars < cchStr
1639 && pchStr[offDollar + cDollars] == '$')
1640 cDollars++;
1641
1642 /*
1643 * Emit a string copy for any preceeding stuff, including half of
1644 * the dollars we found (dollar escape: $$ -> $).
1645 * (kmk_cc_exp_emit_copy_string ignore zero length strings).
1646 */
1647 kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, offDollar + cDollars / 2);
1648 pchStr += offDollar + cDollars;
1649 cchStr -= offDollar + cDollars;
1650
1651 /*
1652 * Odd number of dollar chars means there is a variable to expand
1653 * or function to call.
1654 */
1655 if (cDollars & 1)
1656 {
1657 if (cchStr > 0)
1658 {
1659 char const chOpen = *pchStr;
1660 if (chOpen == '(' || chOpen == '{')
1661 {
1662 /* There are several alternative ways of finding the ending
1663 parenthesis / braces.
1664
1665 GNU make does one thing for functions and variable containing
1666 any '$' chars before the first closing char. While for
1667 variables where a closing char comes before any '$' char, a
1668 simplified approach is taken. This means that for example:
1669
1670 Given VAR=var, the expressions "$(var())" and
1671 "$($(VAR)())" would be expanded differently.
1672 In the first case the variable "var(" would be
1673 used and in the second "var()".
1674
1675 This code will not duplicate this weird behavior, but work
1676 the same regardless of whether there is a '$' char before
1677 the first closing char. */
1678 make_function_ptr_t pfnFunction;
1679 const char *pszFunction;
1680 unsigned char cMaxArgs;
1681 unsigned char cMinArgs;
1682 char fExpandArgs;
1683 char const chClose = chOpen == '(' ? ')' : '}';
1684 char ch = 0;
1685 uint32_t cchName = 0;
1686 uint32_t cDepth = 1;
1687 uint32_t cMaxDepth = 1;
1688 cDollars = 0;
1689
1690 pchStr++;
1691 cchStr--;
1692
1693 /* First loop: Identify potential function calls and dynamic expansion. */
1694 KMK_CC_ASSERT(!func_char_map[chOpen]);
1695 KMK_CC_ASSERT(!func_char_map[chClose]);
1696 KMK_CC_ASSERT(!func_char_map['$']);
1697 while (cchName < cchStr)
1698 {
1699 ch = pchStr[cchName];
1700 if (!func_char_map[(int)ch])
1701 break;
1702 cchName++;
1703 }
1704
1705 if ( cchName >= MIN_FUNCTION_LENGTH
1706 && cchName <= MAX_FUNCTION_LENGTH
1707 && (isblank(ch) || ch == chClose || cchName == cchStr)
1708 && (pfnFunction = lookup_function_for_compiler(pchStr, cchName, &cMinArgs, &cMaxArgs,
1709 &fExpandArgs, &pszFunction)) != NULL)
1710 {
1711 /*
1712 * It's a function invocation, we should count parameters while
1713 * looking for the end.
1714 * Note! We use cchName for the length of the argument list.
1715 */
1716 uint32_t cArgs = 1;
1717 if (ch != chClose)
1718 {
1719 /* Skip leading spaces before the first arg. */
1720 cchName++;
1721 while (cchName < cchStr && isblank((unsigned char)pchStr[cchName]))
1722 cchName++;
1723
1724 pchStr += cchName;
1725 cchStr -= cchName;
1726 cchName = 0;
1727
1728 while (cchName < cchStr)
1729 {
1730 ch = pchStr[cchName];
1731 if (ch == ',')
1732 {
1733 if (cDepth == 1)
1734 cArgs++;
1735 }
1736 else if (ch == chClose)
1737 {
1738 if (!--cDepth)
1739 break;
1740 }
1741 else if (ch == chOpen)
1742 {
1743 if (++cDepth > cMaxDepth)
1744 cMaxDepth = cDepth;
1745 }
1746 else if (ch == '$')
1747 cDollars++;
1748 cchName++;
1749 }
1750 }
1751 else
1752 {
1753 pchStr += cchName;
1754 cchStr -= cchName;
1755 cchName = 0;
1756 }
1757 if (cArgs < cMinArgs)
1758 {
1759 fatal(NULL, _("Function '%.*s' takes a minimum of %d arguments: %d given"),
1760 pszFunction, (int)cMinArgs, (int)cArgs);
1761 return -1; /* not reached */
1762 }
1763 if (cDepth != 0)
1764 {
1765 fatal(NULL, chOpen == '('
1766 ? _("Missing closing parenthesis calling '%s'") : _("Missing closing braces calling '%s'"),
1767 pszFunction);
1768 return -1; /* not reached */
1769 }
1770 if (cMaxDepth > 16 && fExpandArgs)
1771 {
1772 fatal(NULL, _("Too many levels of nested function arguments expansions: %s"), pszFunction);
1773 return -1; /* not reached */
1774 }
1775 if (!fExpandArgs || cDollars == 0)
1776 kmk_cc_exp_emit_plain_function(ppBlockTail, pszFunction, pchStr, cchName,
1777 cArgs, chOpen, chClose, pfnFunction, cMaxArgs);
1778 else
1779 {
1780 rc = kmk_cc_exp_emit_dyn_function(ppBlockTail, pszFunction, pchStr, cchName,
1781 cArgs, chOpen, chClose, pfnFunction, cMaxArgs);
1782 if (rc != 0)
1783 return rc;
1784 }
1785 }
1786 else
1787 {
1788 /*
1789 * Variable, find the end while checking whether anything needs expanding.
1790 */
1791 if (ch == chClose)
1792 cDepth = 0;
1793 else if (cchName < cchStr)
1794 {
1795 if (ch != '$')
1796 {
1797 /* Second loop: Look for things that needs expanding. */
1798 while (cchName < cchStr)
1799 {
1800 ch = pchStr[cchName];
1801 if (ch == chClose)
1802 {
1803 if (!--cDepth)
1804 break;
1805 }
1806 else if (ch == chOpen)
1807 {
1808 if (++cDepth > cMaxDepth)
1809 cMaxDepth = cDepth;
1810 }
1811 else if (ch == '$')
1812 break;
1813 cchName++;
1814 }
1815 }
1816 if (ch == '$')
1817 {
1818 /* Third loop: Something needs expanding, just find the end. */
1819 cDollars = 1;
1820 cchName++;
1821 while (cchName < cchStr)
1822 {
1823 ch = pchStr[cchName];
1824 if (ch == chClose)
1825 {
1826 if (!--cDepth)
1827 break;
1828 }
1829 else if (ch == chOpen)
1830 {
1831 if (++cDepth > cMaxDepth)
1832 cMaxDepth = cDepth;
1833 }
1834 cchName++;
1835 }
1836 }
1837 }
1838 if (cDepth > 0) /* After warning, we just assume they're all there. */
1839 error(NULL, chOpen == '(' ? _("Missing closing parenthesis ") : _("Missing closing braces"));
1840 if (cMaxDepth >= 16)
1841 {
1842 fatal(NULL, _("Too many levels of nested variable expansions: '%.*s'"), (int)cchName + 2, pchStr - 1);
1843 return -1; /* not reached */
1844 }
1845 if (cDollars == 0)
1846 kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, cchName);
1847 else
1848 {
1849 rc = kmk_cc_exp_emit_dyn_variable(ppBlockTail, pchStr, cchName);
1850 if (rc != 0)
1851 return rc;
1852 }
1853 }
1854 pchStr += cchName + 1;
1855 cchStr -= cchName + (cDepth == 0);
1856 }
1857 else
1858 {
1859 /* Single character variable name. */
1860 kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, 1);
1861 pchStr++;
1862 cchStr--;
1863 }
1864 }
1865 else
1866 {
1867 error(NULL, _("Unexpected end of string after $"));
1868 break;
1869 }
1870 }
1871 }
1872 else
1873 {
1874 /*
1875 * Nothing more to expand, the remainder is a simple string copy.
1876 */
1877 kmk_cc_exp_emit_copy_string(ppBlockTail, pchStr, cchStr);
1878 break;
1879 }
1880 }
1881
1882 /*
1883 * Emit final instruction.
1884 */
1885 kmk_cc_exp_emit_return(ppBlockTail);
1886 return 0;
1887}
1888
1889
1890/**
1891 * Initializes string expansion program statistics.
1892 * @param pStats Pointer to the statistics structure to init.
1893 */
1894static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats)
1895{
1896 pStats->cchAvg = 0;
1897}
1898
1899
1900/**
1901 * Compiles a string expansion subprogram.
1902 *
1903 * The caller typically make a call to kmk_cc_block_get_next_ptr after this
1904 * function returns to figure out where to continue executing.
1905 *
1906 * @returns 0 on success, non-zero on failure.
1907 * @param ppBlockTail Pointer to the allocator tail pointer.
1908 * @param pchStr Pointer to the string to compile an expansion
1909 * program for (ASSUMED to be valid for the
1910 * lifetime of the program).
1911 * @param cchStr The length of the string to compile. Expected to
1912 * be at least on char long.
1913 * @param pSubProg The subprogram structure to initialize.
1914 */
1915static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg)
1916{
1917 KMK_CC_ASSERT(cchStr > 0);
1918 pSubProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
1919 kmk_cc_exp_stats_init(&pSubProg->Stats);
1920 return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr);
1921}
1922
1923
1924/**
1925 * Compiles a string expansion program.
1926 *
1927 * @returns Pointer to the program on success, NULL on failure.
1928 * @param pchStr Pointer to the string to compile an expansion
1929 * program for (ASSUMED to be valid for the
1930 * lifetime of the program).
1931 * @param cchStr The length of the string to compile. Expected to
1932 * be at least on char long.
1933 */
1934static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr)
1935{
1936 /*
1937 * Estimate block size, allocate one and initialize it.
1938 */
1939 PKMKCCEXPPROG pProg;
1940 PKMKCCBLOCK pBlock;
1941 pProg = kmk_cc_block_alloc_first(&pBlock, sizeof(*pProg),
1942 (kmk_cc_count_dollars(pchStr, cchStr) + 4) * 8);
1943 if (pProg)
1944 {
1945 int rc = 0;
1946
1947 pProg->pBlockTail = pBlock;
1948 pProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(pBlock);
1949 kmk_cc_exp_stats_init(&pProg->Stats);
1950 pProg->cRefs = 1;
1951#ifdef KMK_CC_STRICT
1952 pProg->uInputHash = kmk_cc_debug_string_hash_n(0, pchStr, cchStr);
1953#endif
1954
1955 /*
1956 * Join forces with the subprogram compilation code.
1957 */
1958 if (kmk_cc_exp_compile_common(&pProg->pBlockTail, pchStr, cchStr) == 0)
1959 {
1960#ifdef KMK_CC_WITH_STATS
1961 pBlock = pProg->pBlockTail;
1962 if (!pBlock->pNext)
1963 g_cSingleBlockExpProgs++;
1964 else if (!pBlock->pNext->pNext)
1965 g_cTwoBlockExpProgs++;
1966 else
1967 g_cMultiBlockExpProgs++;
1968 for (; pBlock; pBlock = pBlock->pNext)
1969 {
1970 g_cBlocksAllocatedExpProgs++;
1971 g_cbAllocatedExpProgs += pBlock->cbBlock;
1972 g_cbUnusedMemExpProgs += pBlock->cbBlock - pBlock->offNext;
1973 }
1974#endif
1975 return pProg;
1976 }
1977 kmk_cc_block_free_list(pProg->pBlockTail);
1978 }
1979 return NULL;
1980}
1981
1982
1983/**
1984 * Updates the recursive_without_dollar member of a variable structure.
1985 *
1986 * This avoid compiling string expansion programs without only a CopyString
1987 * instruction. By setting recursive_without_dollar to 1, code calling
1988 * kmk_cc_compile_variable_for_expand and kmk_exec_expand_to_var_buf will
1989 * instead treat start treating it as a simple variable, which is faster.
1990 *
1991 * @returns The updated recursive_without_dollar value.
1992 * @param pVar Pointer to the variable.
1993 */
1994static int kmk_cc_update_variable_recursive_without_dollar(struct variable *pVar)
1995{
1996 int fValue;
1997 KMK_CC_ASSERT(pVar->recursive_without_dollar == 0);
1998
1999 if (memchr(pVar->value, '$', pVar->value_length))
2000 fValue = -1;
2001 else
2002 fValue = 1;
2003 pVar->recursive_without_dollar = fValue;
2004
2005 return fValue;
2006}
2007
2008
2009/**
2010 * Compiles a variable for string expansion.
2011 *
2012 * @returns Pointer to the string expansion program on success, NULL if no
2013 * program was created.
2014 * @param pVar Pointer to the variable.
2015 */
2016struct kmk_cc_expandprog *kmk_cc_compile_variable_for_expand(struct variable *pVar)
2017{
2018 KMK_CC_ASSERT(strlen(pVar->value) == pVar->value_length);
2019 KMK_CC_ASSERT(!pVar->expandprog);
2020 KMK_CC_ASSERT(pVar->recursive_without_dollar <= 0);
2021
2022 if ( !pVar->expandprog
2023 && pVar->recursive)
2024 {
2025 if ( pVar->recursive_without_dollar < 0
2026 || ( pVar->recursive_without_dollar == 0
2027 && kmk_cc_update_variable_recursive_without_dollar(pVar) < 0) )
2028 {
2029 pVar->expandprog = kmk_cc_exp_compile(pVar->value, pVar->value_length);
2030 g_cVarForExpandCompilations++;
2031 }
2032 }
2033 return pVar->expandprog;
2034}
2035
2036
2037/**
2038 * String expansion execution worker for outputting a variable.
2039 *
2040 * @returns The new variable buffer position.
2041 * @param pVar The variable to reference.
2042 * @param pchDst The current variable buffer position.
2043 */
2044static char *kmk_exec_expand_worker_reference_variable(struct variable *pVar, char *pchDst)
2045{
2046 if (pVar->value_length > 0)
2047 {
2048 if (!pVar->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar))
2049 pchDst = variable_buffer_output(pchDst, pVar->value, pVar->value_length);
2050 else
2051 pchDst = reference_recursive_variable(pchDst, pVar);
2052 }
2053 else if (pVar->append)
2054 pchDst = reference_recursive_variable(pchDst, pVar);
2055 return pchDst;
2056}
2057
2058
2059/**
2060 * Executes a stream string expansion instructions, outputting to the current
2061 * varaible buffer.
2062 *
2063 * @returns The new variable buffer position.
2064 * @param pInstrCore The instruction to start executing at.
2065 * @param pchDst The current variable buffer position.
2066 */
2067static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrCore, char *pchDst)
2068{
2069 for (;;)
2070 {
2071 switch (pInstrCore->enmOpCode)
2072 {
2073 case kKmkCcExpInstr_CopyString:
2074 {
2075 PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)pInstrCore;
2076 pchDst = variable_buffer_output(pchDst, pInstr->pachSrc, pInstr->cchCopy);
2077
2078 pInstrCore = &(pInstr + 1)->Core;
2079 break;
2080 }
2081
2082 case kKmkCcExpInstr_PlainVariable:
2083 {
2084 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)pInstrCore;
2085 struct variable *pVar = lookup_variable_strcached(pInstr->pszName);
2086 if (pVar)
2087 pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst);
2088 else
2089 warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName));
2090
2091 pInstrCore = &(pInstr + 1)->Core;
2092 break;
2093 }
2094
2095 case kKmkCcExpInstr_DynamicVariable:
2096 {
2097 PKMKCCEXPDYNVAR pInstr = (PKMKCCEXPDYNVAR)pInstrCore;
2098 struct variable *pVar;
2099 uint32_t cchName;
2100 char *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->Subprog, &cchName);
2101 char *pszColon = (char *)memchr(pszName, ':', cchName);
2102 char *pszEqual;
2103 if ( pszColon == NULL
2104 || (pszEqual = (char *)memchr(pszColon + 1, '=', &pszName[cchName] - pszColon - 1)) == NULL
2105 || pszEqual == pszColon + 1)
2106 {
2107 pVar = lookup_variable(pszName, cchName);
2108 if (pVar)
2109 pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst);
2110 else
2111 warn_undefined(pszName, cchName);
2112 }
2113 else if (pszColon != pszName)
2114 {
2115 /*
2116 * Oh, we have to do search and replace. How tedious.
2117 * Since the variable name is a temporary buffer, we can transform
2118 * the strings into proper search and replacement patterns directly.
2119 */
2120 pVar = lookup_variable(pszName, pszColon - pszName);
2121 if (pVar)
2122 {
2123 char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value;
2124 char *pszSearchPat = pszColon + 1;
2125 char *pszReplacePat = pszEqual + 1;
2126 const char *pchPctSearchPat;
2127 const char *pchPctReplacePat;
2128
2129 *pszEqual = '\0';
2130 pchPctSearchPat = find_percent(pszSearchPat);
2131 pchPctReplacePat = find_percent(pszReplacePat);
2132
2133 if (!pchPctReplacePat)
2134 {
2135 if (pszReplacePat[-2] != '\0') /* On the offchance that a pct was unquoted by find_percent. */
2136 {
2137 memmove(pszName + 1, pszSearchPat, pszReplacePat - pszSearchPat);
2138 if (pchPctSearchPat)
2139 pchPctSearchPat -= pszSearchPat - &pszName[1];
2140 pszSearchPat = &pszName[1];
2141 }
2142 pchPctReplacePat = --pszReplacePat;
2143 *pszReplacePat = '%';
2144 }
2145
2146 if (!pchPctSearchPat)
2147 {
2148 pchPctSearchPat = --pszSearchPat;
2149 *pszSearchPat = '%';
2150 }
2151
2152 pchDst = patsubst_expand_pat(pchDst, pszExpandedVarValue,
2153 pszSearchPat, pszReplacePat,
2154 pchPctSearchPat, pchPctReplacePat);
2155
2156 if (pVar->recursive)
2157 free((void *)pszExpandedVarValue);
2158 }
2159 else
2160 warn_undefined(pszName, pszColon - pszName);
2161 }
2162 free(pszName);
2163
2164 pInstrCore = pInstr->pNext;
2165 break;
2166 }
2167
2168
2169 case kKmkCcExpInstr_SearchAndReplacePlainVariable:
2170 {
2171 PKMKCCEXPSRPLAINVAR pInstr = (PKMKCCEXPSRPLAINVAR)pInstrCore;
2172 struct variable *pVar = lookup_variable_strcached(pInstr->pszName);
2173 if (pVar)
2174 {
2175 char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value;
2176 pchDst = patsubst_expand_pat(pchDst,
2177 pszExpandedVarValue,
2178 pInstr->pszSearchPattern,
2179 pInstr->pszReplacePattern,
2180 &pInstr->pszSearchPattern[pInstr->offPctSearchPattern],
2181 &pInstr->pszReplacePattern[pInstr->offPctReplacePattern]);
2182 if (pVar->recursive)
2183 free((void *)pszExpandedVarValue);
2184 }
2185 else
2186 warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName));
2187
2188 pInstrCore = pInstr->pNext;
2189 break;
2190 }
2191
2192 case kKmkCcExpInstr_PlainFunction:
2193 {
2194 PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)pInstrCore;
2195 uint32_t iArg;
2196 if (!pInstr->FnCore.fDirty)
2197 {
2198#ifdef KMK_CC_STRICT
2199 uint32_t uCrcBefore = 0;
2200 uint32_t uCrcAfter = 0;
2201 iArg = pInstr->FnCore.cArgs;
2202 while (iArg-- > 0)
2203 uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pInstr->apszArgs[iArg]);
2204#endif
2205
2206 pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName);
2207
2208#ifdef KMK_CC_STRICT
2209 iArg = pInstr->FnCore.cArgs;
2210 while (iArg-- > 0)
2211 uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, pInstr->apszArgs[iArg]);
2212 KMK_CC_ASSERT(uCrcBefore == uCrcAfter);
2213#endif
2214 }
2215 else
2216 {
2217 char **papszShadowArgs = xmalloc((pInstr->FnCore.cArgs * 2 + 1) * sizeof(papszShadowArgs[0]));
2218 char **papszArgs = &papszShadowArgs[pInstr->FnCore.cArgs];
2219
2220 iArg = pInstr->FnCore.cArgs;
2221 papszArgs[iArg] = NULL;
2222 while (iArg-- > 0)
2223 papszArgs[iArg] = papszShadowArgs[iArg] = xstrdup(pInstr->apszArgs[iArg]);
2224
2225 pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName);
2226
2227 iArg = pInstr->FnCore.cArgs;
2228 while (iArg-- > 0)
2229 free(papszShadowArgs[iArg]);
2230 free(papszShadowArgs);
2231 }
2232
2233 pInstrCore = pInstr->FnCore.pNext;
2234 break;
2235 }
2236
2237 case kKmkCcExpInstr_DynamicFunction:
2238 {
2239 PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)pInstrCore;
2240 char **papszArgsShadow = xmalloc( (pInstr->FnCore.cArgs * 2 + 1) * sizeof(char *));
2241 char **papszArgs = &papszArgsShadow[pInstr->FnCore.cArgs];
2242 uint32_t iArg;
2243
2244 if (!pInstr->FnCore.fDirty)
2245 {
2246#ifdef KMK_CC_STRICT
2247 uint32_t uCrcBefore = 0;
2248 uint32_t uCrcAfter = 0;
2249#endif
2250 iArg = pInstr->FnCore.cArgs;
2251 papszArgs[iArg] = NULL;
2252 while (iArg-- > 0)
2253 {
2254 char *pszArg;
2255 if (pInstr->aArgs[iArg].fSubprog)
2256 pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL);
2257 else
2258 pszArg = (char *)pInstr->aArgs[iArg].u.Plain.psz;
2259 papszArgsShadow[iArg] = pszArg;
2260 papszArgs[iArg] = pszArg;
2261#ifdef KMK_CC_STRICT
2262 uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pszArg);
2263#endif
2264 }
2265 pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
2266
2267 iArg = pInstr->FnCore.cArgs;
2268 while (iArg-- > 0)
2269 {
2270#ifdef KMK_CC_STRICT
2271 KMK_CC_ASSERT(papszArgsShadow[iArg] == papszArgs[iArg]);
2272 uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]);
2273#endif
2274 if (pInstr->aArgs[iArg].fSubprog)
2275 free(papszArgsShadow[iArg]);
2276 }
2277 KMK_CC_ASSERT(uCrcBefore == uCrcAfter);
2278 }
2279 else
2280 {
2281 iArg = pInstr->FnCore.cArgs;
2282 papszArgs[iArg] = NULL;
2283 while (iArg-- > 0)
2284 {
2285 char *pszArg;
2286 if (pInstr->aArgs[iArg].fSubprog)
2287 pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL);
2288 else
2289 pszArg = xstrdup(pInstr->aArgs[iArg].u.Plain.psz);
2290 papszArgsShadow[iArg] = pszArg;
2291 papszArgs[iArg] = pszArg;
2292 }
2293
2294 pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
2295
2296 iArg = pInstr->FnCore.cArgs;
2297 while (iArg-- > 0)
2298 free(papszArgsShadow[iArg]);
2299 }
2300 free(papszArgsShadow);
2301
2302 pInstrCore = pInstr->FnCore.pNext;
2303 break;
2304 }
2305
2306 case kKmkCcExpInstr_Jump:
2307 {
2308 PKMKCCEXPJUMP pInstr = (PKMKCCEXPJUMP)pInstrCore;
2309 pInstrCore = pInstr->pNext;
2310 break;
2311 }
2312
2313 case kKmkCcExpInstr_Return:
2314 return pchDst;
2315
2316 default:
2317 fatal(NULL, _("Unknown string expansion opcode: %d (%#x)"),
2318 (int)pInstrCore->enmOpCode, (int)pInstrCore->enmOpCode);
2319 return NULL;
2320 }
2321 }
2322}
2323
2324
2325/**
2326 * Updates the string expansion statistics.
2327 *
2328 * @param pStats The statistics structure to update.
2329 * @param cchResult The result lenght.
2330 */
2331void kmk_cc_exp_stats_update(PKMKCCEXPSTATS pStats, uint32_t cchResult)
2332{
2333 /*
2334 * The average is simplified and not an exact average for every
2335 * expansion that has taken place.
2336 */
2337 pStats->cchAvg = (pStats->cchAvg * 7 + cchResult) / 8;
2338}
2339
2340
2341/**
2342 * Execute a string expansion subprogram, outputting to a new heap buffer.
2343 *
2344 * @returns Pointer to the output buffer (hand to free when done).
2345 * @param pSubProg The subprogram to execute.
2346 * @param pcchResult Where to return the size of the result. Optional.
2347 */
2348static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcchResult)
2349{
2350 char *pchOldVarBuf;
2351 unsigned int cbOldVarBuf;
2352 char *pchDst;
2353 char *pszResult;
2354 uint32_t cchResult;
2355
2356 /*
2357 * Temporarily replace the variable buffer while executing the instruction
2358 * stream for this subprogram.
2359 */
2360 pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf,
2361 pSubProg->Stats.cchAvg ? pSubProg->Stats.cchAvg + 32 : 256);
2362
2363 pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubProg->pFirstInstr, pchDst);
2364
2365 /* Ensure that it's terminated. */
2366 pchDst = variable_buffer_output(pchDst, "\0", 1) - 1;
2367
2368 /* Grab the result buffer before restoring the previous one. */
2369 pszResult = variable_buffer;
2370 cchResult = (uint32_t)(pchDst - pszResult);
2371 if (pcchResult)
2372 *pcchResult = cchResult;
2373 kmk_cc_exp_stats_update(&pSubProg->Stats, cchResult);
2374
2375 variable_buffer = pchOldVarBuf;
2376 variable_buffer_length = cbOldVarBuf;
2377
2378 return pszResult;
2379}
2380
2381
2382/**
2383 * Execute a string expansion program, outputting to the current variable
2384 * buffer.
2385 *
2386 * @returns New variable buffer position.
2387 * @param pProg The program to execute.
2388 * @param pchDst The current varaible buffer position.
2389 */
2390static char *kmk_exec_expand_prog_to_var_buf(PKMKCCEXPPROG pProg, char *pchDst)
2391{
2392 uint32_t cchResult;
2393 uint32_t offStart = (uint32_t)(pchDst - variable_buffer);
2394
2395 if (pProg->Stats.cchAvg >= variable_buffer_length - offStart)
2396 pchDst = ensure_variable_buffer_space(pchDst, offStart + pProg->Stats.cchAvg + 32);
2397
2398 KMK_CC_ASSERT(pProg->cRefs > 0);
2399 pProg->cRefs++;
2400
2401 pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pProg->pFirstInstr, pchDst);
2402
2403 pProg->cRefs--;
2404 KMK_CC_ASSERT(pProg->cRefs > 0);
2405
2406 cchResult = (uint32_t)(pchDst - variable_buffer);
2407 KMK_CC_ASSERT(cchResult >= offStart);
2408 cchResult -= offStart;
2409 kmk_cc_exp_stats_update(&pProg->Stats, cchResult);
2410 g_cVarForExpandExecs++;
2411
2412 return pchDst;
2413}
2414
2415
2416/**
2417 * Expands a variable into a variable buffer using its expandprog.
2418 *
2419 * @returns The new variable buffer position.
2420 * @param pVar Pointer to the variable. Must have a program.
2421 * @param pchDst Pointer to the current variable buffer position.
2422 */
2423char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst)
2424{
2425 KMK_CC_ASSERT(pVar->expandprog);
2426 KMK_CC_ASSERT(pVar->expandprog->uInputHash == kmk_cc_debug_string_hash(0, pVar->value));
2427 return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst);
2428}
2429
2430
2431
2432
2433
2434/*
2435 *
2436 * Makefile evaluation programs.
2437 * Makefile evaluation programs.
2438 * Makefile evaluation programs.
2439 *
2440 */
2441/*#define KMK_CC_EVAL_ENABLE*/
2442
2443
2444/**
2445 * Compiles a variable direct evaluation as is, setting v->evalprog on success.
2446 *
2447 * @returns Pointer to the program on success, NULL if no program was created.
2448 * @param pVar Pointer to the variable.
2449 */
2450struct kmk_cc_evalprog *kmk_cc_compile_variable_for_eval(struct variable *pVar)
2451{
2452 return NULL;
2453}
2454
2455
2456/**
2457 * Compiles a makefile for
2458 *
2459 * @returns Pointer to the program on success, NULL if no program was created.
2460 * @param pVar Pointer to the variable.
2461 */
2462struct kmk_cc_evalprog *kmk_cc_compile_file_for_eval(FILE *pFile, const char *pszFilename)
2463{
2464#ifdef KMK_CC_EVAL_ENABLE
2465 /*
2466 * Read the entire file into a zero terminate memory buffer.
2467 */
2468 size_t cchContent = 0;
2469 char *pszContent = NULL;
2470 struct stat st;
2471 if (!fstat(fileno(pFile), &st))
2472 {
2473 if ( st.st_size > (off_t)16*1024*1024
2474 && st.st_size < 0)
2475 fatal(NULL, _("Makefile too large to compile: %ld bytes (%#lx) - max 16MB"), (long)st.st_size, (long)st.st_size);
2476 cchContent = (size_t)st.st_size;
2477 pszContent = (char *)xmalloc(cchContent + 1);
2478
2479 cchContent = fread(pszContent, 1, cchContent, pFile);
2480 if (ferror(pFile))
2481 fatal(NULL, _("Read error: %s"), strerror(errno));
2482 }
2483 else
2484 {
2485 size_t cbAllocated = 2048;
2486 do
2487 {
2488 cbAllocated *= 2;
2489 if (cbAllocated > 16*1024*1024)
2490 fatal(NULL, _("Makefile too large to compile: max 16MB"));
2491 pszContent = (char *)xrealloc(pszContent, cbAllocated);
2492 cchContent += fread(&pszContent[cchContent], 1, cbAllocated - 1 - cchContent, pFile);
2493 if (ferror(pFile))
2494 fatal(NULL, _("Read error: %s"), strerror(errno));
2495 } while (!feof(pFile));
2496 }
2497 pszContent[cchContent] = '\0';
2498
2499 /*
2500 * Call common function to do the compilation.
2501 */
2502 //kmk_cc_eval_compile_common()
2503
2504 free(pszContent);
2505 return NULL;
2506#else
2507 return NULL;
2508#endif
2509}
2510
2511
2512/**
2513 * Equivalent of eval_buffer, only it's using the evalprog of the variable.
2514 *
2515 * @param pVar Pointer to the variable. Must have a program.
2516 */
2517void kmk_exec_eval_variable(struct variable *pVar)
2518{
2519 KMK_CC_ASSERT(pVar->evalprog);
2520 assert(0);
2521}
2522
2523
2524/**
2525 * Worker for eval_makefile.
2526 *
2527 * @param pEvalProg The program pointer.
2528 */
2529void kmk_exec_eval_file(struct kmk_cc_evalprog *pEvalProg)
2530{
2531 KMK_CC_ASSERT(pEvalProg);
2532 assert(0);
2533}
2534
2535
2536
2537/*
2538 *
2539 * Program destruction hooks.
2540 * Program destruction hooks.
2541 * Program destruction hooks.
2542 *
2543 */
2544
2545
2546/**
2547 * Called when a variable with expandprog or/and evalprog changes.
2548 *
2549 * @param pVar Pointer to the variable.
2550 */
2551void kmk_cc_variable_changed(struct variable *pVar)
2552{
2553 PKMKCCEXPPROG pProg = pVar->expandprog;
2554
2555 KMK_CC_ASSERT(pVar->evalprog || pProg);
2556
2557#if 0
2558 if (pVar->evalprog)
2559 {
2560 kmk_cc_block_free_list(pVar->evalprog->pBlockTail);
2561 pVar->evalprog = NULL;
2562 }
2563#endif
2564
2565 if (pProg)
2566 {
2567 if (pProg->cRefs == 1)
2568 kmk_cc_block_free_list(pProg->pBlockTail);
2569 else
2570 fatal(NULL, _("Modifying a variable (%s) while its expansion program is running is not supported"), pVar->name);
2571 pVar->expandprog = NULL;
2572 }
2573}
2574
2575
2576/**
2577 * Called when a variable with expandprog or/and evalprog is deleted.
2578 *
2579 * @param pVar Pointer to the variable.
2580 */
2581void kmk_cc_variable_deleted(struct variable *pVar)
2582{
2583 PKMKCCEXPPROG pProg = pVar->expandprog;
2584
2585 KMK_CC_ASSERT(pVar->evalprog || pProg);
2586
2587#if 0
2588 if (pVar->evalprog)
2589 {
2590 kmk_cc_block_free_list(pVar->evalprog->pBlockTail);
2591 pVar->evalprog = NULL;
2592 }
2593#endif
2594
2595 if (pProg)
2596 {
2597 if (pProg->cRefs == 1)
2598 kmk_cc_block_free_list(pProg->pBlockTail);
2599 else
2600 fatal(NULL, _("Deleting a variable (%s) while its expansion program is running is not supported"), pVar->name);
2601 pVar->expandprog = NULL;
2602 }
2603}
2604
2605
2606
2607
2608
2609
2610
2611#endif /* CONFIG_WITH_COMPILER */
2612
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