VirtualBox

source: kBuild/trunk/src/kmk/kbuild-read.c@ 2717

Last change on this file since 2717 was 2717, checked in by bird, 11 years ago

kmk: Hacking kBuild-define-*.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 40.4 KB
Line 
1/* $Id: kbuild-read.c 2717 2013-12-30 00:58:43Z bird $ */
2/** @file
3 * kBuild specific make functionality related to read.c.
4 */
5
6/*
7 * Copyright (c) 2011-2013 knut st. osmundsen <[email protected]>
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
23 *
24 */
25
26/* No GNU coding style here! */
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "make.h"
32#include "filedef.h"
33#include "variable.h"
34#include "dep.h"
35#include "debug.h"
36#include "kbuild.h"
37
38#include <assert.h>
39#include <stdarg.h>
40
41
42/*******************************************************************************
43* Defined Constants And Macros *
44*******************************************************************************/
45#define WORD_IS(a_pszWord, a_cchWord, a_szWord2) \
46 ( (a_cchWord) == sizeof(a_szWord2) - 1 && memcmp((a_pszWord), a_szWord2, sizeof(a_szWord2) - 1) == 0)
47
48
49/*******************************************************************************
50* Structures and Typedefs *
51*******************************************************************************/
52/** kBuild object type. */
53enum kBuildType
54{
55 kBuildType_Invalid,
56 kBuildType_Target,
57 kBuildType_Template,
58 kBuildType_Tool,
59 kBuildType_Sdk,
60 kBuildType_Unit
61};
62
63enum kBuildSeverity
64{
65 kBuildSeverity_Warning,
66 kBuildSeverity_Error,
67 kBuildSeverity_Fatal
68};
69
70
71/**
72 * kBuild object data.
73 */
74struct kbuild_object
75{
76 /** The object type. */
77 enum kBuildType enmType;
78 /** Object name length. */
79 size_t cchName;
80 /** The bare name of the define. */
81 char *pszName;
82 /** The file location where this define was declared. */
83 struct floc FileLoc;
84
85 /** Pointer to the next element in the global list. */
86 struct kbuild_object *pGlobalNext;
87
88 /** The variable set associated with this define. */
89 struct variable_set_list *pVariables;
90
91 /** The parent name, NULL if none. */
92 char *pszParent;
93 /** The length of the parent name. */
94 size_t cchParent;
95 /** Pointer to the parent. Resolved lazily, so it can be NULL even if we
96 * have a parent. */
97 struct kbuild_object *pParent;
98
99 /** The template, NULL if none. Only applicable to targets. Only covers the
100 * primary template, not target or type specific templates.
101 * @todo not sure if this is really necessary. */
102 char const *pszTemplate;
103
104 /** The variable prefix. */
105 char *pszVarPrefix;
106 /** The length of the variable prefix. */
107 size_t cchVarPrefix;
108};
109
110
111/**
112 * The data we stack during eval.
113 */
114struct kbuild_eval_data
115{
116 /** Pointer to the element below us on the stack. */
117 struct kbuild_eval_data *pStackDown;
118 /** Pointer to the object. */
119 struct kbuild_object *pObj;
120 /** The saved current variable set, for restoring in kBuild-endef. */
121 struct variable_set_list *pVariablesSaved;
122};
123
124
125
126/*******************************************************************************
127* Header Files *
128*******************************************************************************/
129/** Linked list (LIFO) of kBuild defines.
130 * @todo use a hash! */
131static struct kbuild_object *g_pHeadKbObjs = NULL;
132/** Stack of kBuild evalutation contexts.
133 * This is for dealing with potential recursive kBuild object definition,
134 * generally believed to only happen via $(eval ) or include similar. */
135struct kbuild_eval_data *g_pTopKbEvalData = NULL;
136
137/** Cached variable name '_TEMPLATE'. */
138static const char *g_pszVarNmTemplate = NULL;
139
140/** Zero if compatibility mode is disabled, non-zero if enabled.
141 * If explicitily enabled, the value will be greater than 1. */
142int g_fKbObjCompMode = 1;
143
144
145/*******************************************************************************
146* Internal Functions *
147*******************************************************************************/
148static struct kbuild_object *
149eval_kbuild_resolve_parent(struct kbuild_object *pObj, int fQuiet);
150
151static struct kbuild_object *
152parse_kbuild_object_variable_accessor(const char *pchExpr, size_t cchExpr,
153 enum kBuildSeverity enmSeverity, const struct floc *pFileLoc,
154 const char **ppchVarNm, size_t *pcchVarNm, enum kBuildType *penmType);
155
156
157/**
158 * Initializes the kBuild object stuff.
159 *
160 * Requires the variable_cache to be initialized.
161 */
162void init_kbuild_object(void)
163{
164 g_pszVarNmTemplate = strcache2_add(&variable_strcache, STRING_SIZE_TUPLE("_TEMPLATE"));
165}
166
167
168/**
169 * Reports a problem with dynamic severity level.
170 *
171 * @param enmSeverity The severity level.
172 * @param pFileLoc The file location.
173 * @param pszFormat The format string.
174 * @param ... Arguments for the format string.
175 */
176static void kbuild_report_problem(enum kBuildSeverity enmSeverity, const struct floc *pFileLoc,
177 const char *pszFormat, ...)
178{
179 char szBuf[8192];
180 va_list va;
181
182 va_start(va, pszFormat);
183#ifdef _MSC_VER
184 _vsnprintf(szBuf, sizeof(szBuf), pszFormat, va);
185#else
186 vsnprintf(szBuf, sizeof(szBuf), pszFormat, va);
187#endif
188 va_end(va);
189
190 switch (enmSeverity)
191 {
192 case kBuildSeverity_Warning:
193 message(0, "%s", szBuf);
194 break;
195 case kBuildSeverity_Error:
196 error(pFileLoc, "%s", szBuf);
197 break;
198 default:
199 case kBuildSeverity_Fatal:
200 fatal(pFileLoc, "%s", szBuf);
201 break;
202 }
203}
204
205
206/**
207 * Helper function for caching variable name strings.
208 *
209 * @returns The string cache variable name.
210 * @param pszName The variable name.
211 * @param ppszCache Cache variable, static or global. Initialize to
212 * NULL.
213 */
214static const char *
215kbuild_variable_name(const char *pszName, const char **ppszCache)
216{
217 const char *pszRet = *ppszCache;
218 if (!pszRet)
219 *ppszCache = pszRet = strcache2_add(&variable_strcache, pszName, strlen(pszName));
220 return pszRet;
221}
222
223static struct kbuild_object *
224lookup_kbuild_object(enum kBuildType enmType, const char *pchName, size_t cchName)
225{
226 /* Linear lookup for now. */
227 struct kbuild_object *pCur = g_pHeadKbObjs;
228 while (pCur)
229 {
230 if ( pCur->enmType == enmType
231 && pCur->cchName == cchName
232 && !memcmp(pCur->pszName, pchName, cchName))
233 return pCur;
234 pCur = pCur->pGlobalNext;
235 }
236 return NULL;
237}
238
239
240/** @name Defining and modifying variables
241 * @{
242 */
243
244/**
245 * Checks if the variable name is valid.
246 *
247 * @returns 1 if valid, 0 if not.
248 * @param pchName The variable name.
249 * @param cchName The length of the variable name.
250 */
251static int
252is_valid_kbuild_object_variable_name(const char *pchName, size_t cchName)
253{
254 if (cchName > 0)
255 {
256 if (!memchr(pchName, '[', cchName))
257 {
258 /** @todo more? */
259 return 1;
260 }
261 }
262 return 0;
263}
264
265static struct variable *
266define_kbuild_object_variable_cached(struct kbuild_object *pObj, const char *pszName,
267 const char *pchValue, size_t cchValue,
268 int fDuplicateValue, enum variable_origin enmOrigin,
269 int fRecursive, const struct floc *pFileLoc)
270{
271 struct variable *pVar;
272 size_t cchName = strcache2_get_len(&variable_strcache, pszName);
273
274
275 pVar = define_variable_in_set(pszName, cchName,
276 pchValue, cchValue, fDuplicateValue,
277 enmOrigin, fRecursive,
278 pObj->pVariables->set,
279 pFileLoc);
280
281 /* Single underscore prefixed variables gets a global alias. */
282 if ( pszName[0] == '_'
283 && pszName[1] != '_'
284 && g_fKbObjCompMode)
285 {
286 size_t cchPrefixed = pObj->cchVarPrefix + cchName;
287 char *pszPrefixed = xmalloc(cchPrefixed + 1);
288 memcpy(pszPrefixed, pObj->pszVarPrefix, pObj->cchVarPrefix);
289 memcpy(&pszPrefixed[pObj->cchVarPrefix], pszName, cchName);
290 pszPrefixed[cchPrefixed] = '\0';
291
292 /** @todo implement variable aliases or something. */
293 define_variable_in_set(pszPrefixed, cchPrefixed,
294 pchValue, cchValue, 1 /*duplicate_value*/,
295 enmOrigin, fRecursive,
296 &global_variable_set,
297 pFileLoc);
298 }
299
300 return pVar;
301}
302
303#if 0
304struct variable *
305define_kbuild_object_variable(struct kbuild_object *pObj, const char *pchName, size_t cchName,
306 const char *pchValue, size_t cchValue,
307 int fDuplicateValue, enum variable_origin enmOrigin,
308 int fRecursive, const struct floc *pFileLoc)
309{
310 return define_kbuild_object_variable_cached(pObj, strcache2_add(&variable_strcache, pchName, cchName),
311 pchValue, cchValue,
312 fDuplicateValue, enmOrigin,
313 fRecursive, pFileLoc);
314}
315#endif
316
317/**
318 * Try define a kBuild object variable via a possible accessor
319 * ([type@object]var).
320 *
321 * @returns Pointer to the defined variable on success.
322 * @retval VAR_NOT_KBUILD_ACCESSOR if it isn't an accessor.
323 *
324 * @param pchName The variable name, not cached.
325 * @param cchName The variable name length. This will not be ~0U.
326 * @param pszValue The variable value. If @a fDuplicateValue is clear,
327 * this should be assigned as the actual variable
328 * value, otherwise it will be duplicated. In the
329 * latter case it might not be properly null
330 * terminated.
331 * @param cchValue The value length.
332 * @param fDuplicateValue Whether @a pszValue need to be duplicated on the
333 * heap or is already there.
334 * @param enmOrigin The variable origin.
335 * @param fRecursive Whether it's a recursive variable.
336 * @param pFileLoc The location of the variable definition.
337 */
338struct variable *
339try_define_kbuild_object_variable_via_accessor(const char *pchName, size_t cchName,
340 const char *pszValue, size_t cchValue, int fDuplicateValue,
341 enum variable_origin enmOrigin, int fRecursive,
342 struct floc const *pFileLoc)
343{
344 struct kbuild_object *pObj;
345 const char *pchVarNm;
346 size_t cchVarNm;
347
348 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Fatal, pFileLoc,
349 &pchVarNm, &cchVarNm, NULL);
350 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
351 {
352 assert(pObj != NULL);
353 if (!is_valid_kbuild_object_variable_name(pchVarNm, cchVarNm))
354 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s' ('%s')"),
355 (int)cchVarNm, pchVarNm, (int)cchName, pchName);
356 return define_kbuild_object_variable_cached(pObj, strcache2_add(&variable_strcache, pchVarNm, cchVarNm),
357 pszValue, cchValue, fDuplicateValue, enmOrigin, fRecursive, pFileLoc);
358 }
359
360 return VAR_NOT_KBUILD_ACCESSOR;
361}
362
363/**
364 * Define a kBuild object variable in the topmost kBuild object.
365 *
366 * This won't be an variable accessor.
367 *
368 * @returns Pointer to the defined variable on success.
369 *
370 * @param pchName The variable name, not cached.
371 * @param cchName The variable name length. This will not be ~0U.
372 * @param pszValue The variable value. If @a fDuplicateValue is clear,
373 * this should be assigned as the actual variable
374 * value, otherwise it will be duplicated. In the
375 * latter case it might not be properly null
376 * terminated.
377 * @param cchValue The value length.
378 * @param fDuplicateValue Whether @a pszValue need to be duplicated on the
379 * heap or is already there.
380 * @param enmOrigin The variable origin.
381 * @param fRecursive Whether it's a recursive variable.
382 * @param pFileLoc The location of the variable definition.
383 */
384struct variable *
385define_kbuild_object_variable_in_top_obj(const char *pchName, size_t cchName,
386 const char *pszValue, size_t cchValue, int fDuplicateValue,
387 enum variable_origin enmOrigin, int fRecursive,
388 struct floc const *pFileLoc)
389{
390 assert(g_pTopKbEvalData != NULL);
391
392 if (!is_valid_kbuild_object_variable_name(pchName, cchName))
393 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s'"), (int)cchName, pchName);
394
395 return define_kbuild_object_variable_cached(g_pTopKbEvalData->pObj, strcache2_add(&variable_strcache, pchName, cchName),
396 pszValue, cchValue, fDuplicateValue, enmOrigin, fRecursive, pFileLoc);
397}
398
399/**
400 * Implements appending and prepending to a kBuild object variable.
401 *
402 * The variable is either accessed thru an accessor or by the topmost kBuild
403 * object.
404 *
405 * @returns Pointer to the defined variable on success.
406 *
407 * @param pchName The variable name, not cached.
408 * @param cchName The variable name length. This will not be ~0U.
409 * @param pszValue The variable value. Must be duplicated.
410 * @param cchValue The value length.
411 * @param fSimpleValue Whether we've already figured that it's a simple
412 * value. This is for optimizing appending/prepending
413 * to an existing simple value variable.
414 * @param enmOrigin The variable origin.
415 * @param fAppend Append if set, prepend if clear.
416 * @param pFileLoc The location of the variable definition.
417 */
418struct variable *
419kbuild_object_variable_pre_append(const char *pchName, size_t cchName,
420 const char *pchValue, size_t cchValue, int fSimpleValue,
421 enum variable_origin enmOrigin, int fAppend,
422 const struct floc *pFileLoc)
423{
424 struct kbuild_object *pObj;
425 struct variable VarKey;
426
427 /*
428 * Resolve the relevant kBuild object first.
429 */
430 if (cchName > 3 && pchName[0] == '[')
431 {
432 const char *pchVarNm;
433 size_t cchVarNm;
434 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Fatal, pFileLoc,
435 &pchVarNm, &cchVarNm, NULL);
436 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
437 {
438 pchName = pchVarNm;
439 cchName = cchVarNm;
440 }
441 else
442 pObj = g_pTopKbEvalData->pObj;
443 }
444 else
445 pObj = g_pTopKbEvalData->pObj;
446
447 /*
448 * Make sure the variable name is valid. Raise fatal error if not.
449 */
450 if (!is_valid_kbuild_object_variable_name(pchName, cchName))
451 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s'"), (int)cchName, pchName);
452
453 /*
454 * Get the cached name and look it up in the object's variables.
455 */
456 VarKey.name = strcache2_lookup(&variable_strcache, pchName, cchName);
457 if (VarKey.name)
458 {
459 struct variable *pVar;
460
461 VarKey.length = cchName;
462 pVar = (struct variable *)hash_find_item_strcached(&pObj->pVariables->set->table, &VarKey);
463 if (pVar)
464 {
465 /* Append/prepend to existing variable. */
466 return do_variable_definition_append(pFileLoc, pVar, pchValue, cchValue, fSimpleValue, enmOrigin, fAppend);
467 }
468
469 /*
470 * Not found. Check ancestors if the 'override' directive isn't applied.
471 */
472 if (pObj->pszParent && enmOrigin != o_override)
473 {
474 struct kbuild_object *pParent = pObj;
475 for (;;)
476 {
477 pParent = eval_kbuild_resolve_parent(pParent, 0 /*fQuiet*/);
478 if (!pParent)
479 break;
480
481 pVar = (struct variable *)hash_find_item_strcached(&pParent->pVariables->set->table, &VarKey);
482 if (pVar)
483 {
484 if (pVar->value_length != ~0U)
485 assert(pVar->value_length == strlen(pVar->value));
486 else
487 pVar->value_length = strlen(pVar->value);
488
489 /*
490 * Combine the two values and define the variable in the
491 * specified child object. We must disregard 'origin' a
492 * little here, so we must do the gritty stuff our selves.
493 */
494 if ( pVar->recursive
495 || fSimpleValue
496 || !cchValue
497 || memchr(pchValue, '$', cchValue) == NULL )
498 {
499 size_t cchNewValue;
500 char *pszNewValue;
501 char *pszTmp;
502
503 /* Just join up the two values. */
504 if (pVar->value_length == 0)
505 {
506 cchNewValue = cchValue;
507 pszNewValue = xstrndup(pchValue, cchValue);
508 }
509 else if (!cchValue)
510 {
511 cchNewValue = pVar->value_length;
512 pszNewValue = xmalloc(cchNewValue + 1);
513 memcpy(pszNewValue, pVar->value, cchNewValue + 1);
514 }
515 else
516 {
517 cchNewValue = pVar->value_length + 1 + cchValue;
518 pszNewValue = xmalloc(cchNewValue + 1);
519 if (fAppend)
520 {
521 memcpy(pszNewValue, pVar->value, pVar->value_length);
522 pszTmp = pszNewValue + pVar->value_length;
523 *pszTmp++ = ' ';
524 memcpy(pszTmp, pchValue, cchValue);
525 pszTmp[cchValue] = '\0';
526 }
527 else
528 {
529 memcpy(pszNewValue, pchValue, cchValue);
530 pszTmp = pszNewValue + cchValue;
531 *pszTmp++ = ' ';
532 memcpy(pszNewValue, pVar->value, pVar->value_length);
533 pszTmp[pVar->value_length] = '\0';
534 }
535 }
536
537 /* Define the new variable in the child. */
538 return define_kbuild_object_variable_cached(pObj, VarKey.name,
539 pszNewValue, cchNewValue, 0 /*fDuplicateValue*/,
540 enmOrigin, pVar->recursive, pFileLoc);
541
542 }
543 else
544 {
545 /* Lazy bird: Copy the variable from the ancestor and
546 then do a normal append/prepend on it. */
547 pVar = define_kbuild_object_variable_cached(pObj, VarKey.name,
548 pVar->value, pVar->value_length, 1 /*fDuplicateValue*/,
549 enmOrigin, pVar->recursive, pFileLoc);
550 append_expanded_string_to_variable(pVar, pchValue, cchValue, fAppend);
551 return pVar;
552 }
553 }
554 }
555 }
556 }
557 else
558 VarKey.name = strcache2_add(&variable_strcache, pchName, cchName);
559
560 /* Variable not found. */
561 return define_kbuild_object_variable_cached(pObj, VarKey.name,
562 pchValue, cchValue, 1 /*fDuplicateValue*/, enmOrigin,
563 1 /*fRecursive */, pFileLoc);
564}
565
566/** @} */
567
568
569static const char *
570eval_kbuild_type_to_string(enum kBuildType enmType)
571{
572 switch (enmType)
573 {
574 case kBuildType_Target: return "target";
575 case kBuildType_Template: return "template";
576 case kBuildType_Tool: return "tool";
577 case kBuildType_Sdk: return "sdk";
578 case kBuildType_Unit: return "unit";
579 default:
580 case kBuildType_Invalid: return "invalid";
581 }
582}
583
584/**
585 * Converts a string into an kBuild object type.
586 *
587 * @returns The type on success, kBuildType_Invalid on failure.
588 * @param pchWord The pchWord. Not necessarily zero terminated.
589 * @param cchWord The length of the word.
590 */
591static enum kBuildType
592eval_kbuild_type_from_string(const char *pchWord, size_t cchWord)
593{
594 if (cchWord >= 3)
595 {
596 if (*pchWord == 't')
597 {
598 if (WORD_IS(pchWord, cchWord, "target"))
599 return kBuildType_Target;
600 if (WORD_IS(pchWord, cchWord, "template"))
601 return kBuildType_Template;
602 if (WORD_IS(pchWord, cchWord, "tool"))
603 return kBuildType_Tool;
604 }
605 else
606 {
607 if (WORD_IS(pchWord, cchWord, "sdk"))
608 return kBuildType_Sdk;
609 if (WORD_IS(pchWord, cchWord, "unit"))
610 return kBuildType_Unit;
611 }
612 }
613
614 return kBuildType_Invalid;
615}
616
617
618static char *
619allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, size_t *pcchToken, int fStrip)
620{
621 unsigned int cchToken;
622 char *pszToken = find_next_token_eos(ppszCursor, pszEos, &cchToken);
623 if (pszToken)
624 {
625 pszToken = allocated_variable_expand_2(pszToken, cchToken, &cchToken);
626 if (pszToken)
627 {
628 if (fStrip)
629 {
630 unsigned int off = 0;
631 while (MY_IS_BLANK(pszToken[off]))
632 off++;
633 if (off)
634 {
635 cchToken -= off;
636 memmove(pszToken, &pszToken[off], cchToken + 1);
637 }
638
639 while (cchToken > 0 && MY_IS_BLANK(pszToken[cchToken - 1]))
640 pszToken[--cchToken] = '\0';
641 }
642
643 assert(cchToken == strlen(pszToken));
644 if (pcchToken)
645 *pcchToken = cchToken;
646 return pszToken;
647 }
648 }
649
650 if (pcchToken)
651 *pcchToken = 0;
652 return NULL;
653}
654
655static struct kbuild_object *
656eval_kbuild_resolve_parent(struct kbuild_object *pObj, int fQuiet)
657{
658 if ( !pObj->pParent
659 && pObj->pszParent)
660 {
661 struct kbuild_object *pCur = g_pHeadKbObjs;
662 while (pCur)
663 {
664 if ( pCur->enmType == pObj->enmType
665 && !strcmp(pCur->pszName, pObj->pszParent))
666 {
667 if ( pCur->pszParent
668 && ( pCur->pParent == pObj
669 || !strcmp(pCur->pszParent, pObj->pszName)) )
670 fatal(&pObj->FileLoc, _("'%s' and '%s' are both trying to be each other children..."),
671 pObj->pszName, pCur->pszName);
672
673 pObj->pParent = pCur;
674 pObj->pVariables->next = pObj->pVariables;
675 return pCur;
676 }
677
678 pCur = pCur->pGlobalNext;
679 }
680
681 /* Not found. */
682 if (!fQuiet)
683 error(&pObj->FileLoc, _("Could not locate parent '%s' of '%s'"), pObj->pszParent, pObj->pszName);
684 }
685 return pObj->pParent;
686}
687
688static int
689eval_kbuild_define_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc,
690 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType)
691{
692 unsigned int cch;
693 char ch;
694 char *psz;
695 const char *pszPrefix;
696 struct kbuild_object *pObj;
697 struct kbuild_eval_data *pData;
698
699 if (fIgnoring)
700 return 0;
701
702 /*
703 * Create a new kBuild object.
704 */
705 pObj = xmalloc(sizeof(*pObj));
706 pObj->enmType = enmType;
707 pObj->pszName = NULL;
708 pObj->cchName = 0;
709 pObj->FileLoc = *pFileLoc;
710
711 pObj->pGlobalNext = g_pHeadKbObjs;
712 g_pHeadKbObjs = pObj;
713
714 pObj->pVariables = create_new_variable_set();
715
716 pObj->pszParent = NULL;
717 pObj->cchParent = 0;
718 pObj->pParent = NULL;
719
720 pObj->pszTemplate = NULL;
721
722 pObj->pszVarPrefix = NULL;
723 pObj->cchVarPrefix = 0;
724
725 /*
726 * The first word is the name.
727 */
728 pObj->pszName = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchName, 1 /*strip*/);
729 if (!pObj->pszName || !*pObj->pszName)
730 fatal(pFileLoc, _("The kBuild define requires a name"));
731
732 psz = pObj->pszName;
733 while ((ch = *psz++) != '\0')
734 if (!isgraph(ch))
735 {
736 error(pFileLoc, _("The 'kBuild-define-%s' name '%s' contains one or more invalid characters"),
737 eval_kbuild_type_to_string(enmType), pObj->pszName);
738 break;
739 }
740
741 /*
742 * Calc the variable prefix.
743 */
744 switch (enmType)
745 {
746 case kBuildType_Target: pszPrefix = ""; break;
747 case kBuildType_Template: pszPrefix = "TEMPLATE_"; break;
748 case kBuildType_Tool: pszPrefix = "TOOL_"; break;
749 case kBuildType_Sdk: pszPrefix = "SDK_"; break;
750 case kBuildType_Unit: pszPrefix = "UNIT_"; break;
751 default:
752 fatal(pFileLoc, _("enmType=%d"), enmType);
753 return -1;
754 }
755 cch = strlen(pszPrefix);
756 pObj->cchVarPrefix = cch + pObj->cchName;
757 pObj->pszVarPrefix = xmalloc(pObj->cchVarPrefix + 1);
758 memcpy(pObj->pszVarPrefix, pszPrefix, cch);
759 memcpy(&pObj->pszVarPrefix[cch], pObj->pszName, pObj->cchName);
760
761 /*
762 * Parse subsequent words.
763 */
764 psz = find_next_token_eos(&pszLine, pszEos, &cch);
765 while (psz)
766 {
767 if (WORD_IS(psz, cch, "extending"))
768 {
769 /* Inheritance directive. */
770 if (pObj->pszParent != NULL)
771 fatal(pFileLoc, _("'extending' can only occure once"));
772 pObj->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchParent, 1 /*strip*/);
773 if (!pObj->pszParent || !*pObj->pszParent)
774 fatal(pFileLoc, _("'extending' requires a parent name"));
775 }
776 else if (WORD_IS(psz, cch, "using"))
777 {
778 char *pszTemplate;
779 size_t cchTemplate;
780
781 /* Template directive. */
782 if (enmType != kBuildType_Target)
783 fatal(pFileLoc, _("'using <template>' can only be used with 'kBuild-define-target'"));
784 if (pObj->pszTemplate != NULL)
785 fatal(pFileLoc, _("'using' can only occure once"));
786
787 pszTemplate = allocate_expanded_next_token(&pszLine, pszEos, &cchTemplate, 1 /*fStrip*/);
788 if (!pszTemplate || !*pszTemplate)
789 fatal(pFileLoc, _("'using' requires a template name"));
790
791 define_kbuild_object_variable_cached(pObj, g_pszVarNmTemplate, pszTemplate, cchTemplate,
792 0 /*fDuplicateValue*/, o_default, 0 /*fRecursive*/, pFileLoc),
793
794 /* next token */
795 psz = find_next_token_eos(&pszLine, pszEos, &cch);
796 }
797 else
798 fatal(pFileLoc, _("Don't know what '%.*s' means"), (int)cch, psz);
799 }
800
801 /*
802 * Try resolve the parent.
803 */
804 eval_kbuild_resolve_parent(pObj, 1 /*fQuiet*/);
805
806 /*
807 * Create an eval stack entry and change the current variable set.
808 */
809 pData = xmalloc(sizeof(*pData));
810 pData->pObj = pObj;
811 pData->pVariablesSaved = current_variable_set_list;
812 current_variable_set_list = pObj->pVariables;
813
814 pData->pStackDown = *ppData;
815 *ppData = pData;
816 g_pTopKbEvalData = pData;
817
818 return 0;
819}
820
821static int
822eval_kbuild_endef_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc,
823 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType)
824{
825 struct kbuild_eval_data *pData;
826 struct kbuild_object *pObj;
827 size_t cchName;
828 char *pszName;
829
830 if (fIgnoring)
831 return 0;
832
833 /*
834 * Is there something to pop?
835 */
836 pData = *ppData;
837 if (!pData)
838 {
839 error(pFileLoc, _("kBuild-endef-%s is missing kBuild-define-%s"),
840 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(enmType));
841 return 0;
842 }
843
844 /*
845 * ... and does it have a matching kind?
846 */
847 pObj = pData->pObj;
848 if (pObj->enmType != enmType)
849 error(pFileLoc, _("'kBuild-endef-%s' does not match 'kBuild-define-%s %s'"),
850 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(pObj->enmType), pObj->pszName);
851
852 /*
853 * The endef-kbuild may optionally be followed by the target name.
854 * It should match the name given to the kBuild-define.
855 */
856 pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*fStrip*/);
857 if (pszName)
858 {
859 if ( cchName != pObj->cchName
860 || strcmp(pszName, pObj->pszName))
861 error(pFileLoc, _("'kBuild-endef-%s %s' does not match 'kBuild-define-%s %s'"),
862 eval_kbuild_type_to_string(enmType), pszName,
863 eval_kbuild_type_to_string(pObj->enmType), pObj->pszName);
864 free(pszName);
865 }
866
867 /*
868 * Pop a define off the stack.
869 */
870 assert(pData == g_pTopKbEvalData);
871 *ppData = g_pTopKbEvalData = pData->pStackDown;
872 pData->pStackDown = NULL;
873 current_variable_set_list = pData->pVariablesSaved;
874 pData->pVariablesSaved = NULL;
875 free(pData);
876
877 return 0;
878}
879
880int eval_kbuild_read_hook(struct kbuild_eval_data **kdata, const struct floc *flocp,
881 const char *pchWord, size_t cchWord, const char *line, const char *eos, int ignoring)
882{
883 enum kBuildType enmType;
884
885 /*
886 * Skip the 'kBuild-' prefix that the caller already matched.
887 */
888 assert(memcmp(pchWord, "kBuild-", sizeof("kBuild-") - 1) == 0);
889 pchWord += sizeof("kBuild-") - 1;
890 cchWord -= sizeof("kBuild-") - 1;
891
892 /*
893 * String switch.
894 */
895 if ( cchWord >= sizeof("define-") - 1
896 && strneq(pchWord, "define-", sizeof("define-") - 1))
897 {
898 enmType = eval_kbuild_type_from_string(pchWord + sizeof("define-") - 1, cchWord - sizeof("define-") + 1);
899 if (enmType != kBuildType_Invalid)
900 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, enmType);
901 }
902 else if ( cchWord >= sizeof("endef-") - 1
903 && strneq(pchWord, "endef-", sizeof("endef-") - 1))
904 {
905 enmType = eval_kbuild_type_from_string(pchWord + sizeof("endif-") - 1, cchWord - sizeof("endif-") + 1);
906 if (enmType != kBuildType_Invalid)
907 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, enmType);
908 }
909 else if (WORD_IS(pchWord, cchWord, "endef"))
910 {
911 /* Terminate whatever definition is on top. */
912
913 }
914
915 /*
916 * Everything that is prefixed with 'kBuild-' is reserved for language
917 * extensions, at least until legacy assignments/whatever turns up.
918 */
919 error(flocp, _("Unknown syntax 'kBuild-%.*s'"), (int)cchWord, pchWord);
920 return 0;
921}
922
923
924/** @name kBuild object variable accessor related functions
925 * @{
926 */
927
928/**
929 * Checks if the given name is an object variable accessor.
930 *
931 * @returns 1 if it is, 0 if it isn't.
932 * @param pchName The potential kBuild variable accessor
933 * expression.
934 * @param cchName Length of the expression.
935 */
936int is_kbuild_object_variable_accessor(const char *pchName, size_t cchName)
937{
938 char const *pchTmp;
939
940 /* See lookup_kbuild_object_variable for the rules. */
941 if (cchName >= 1+1+1+1 && *pchName == '[')
942 {
943 pchName++;
944 cchName--;
945
946 pchTmp = memchr(pchName, '@', cchName);
947 if (pchTmp)
948 {
949 cchName -= pchTmp + 1 - pchName;
950 pchName = pchTmp + 1;
951 pchTmp = memchr(pchName, ']', cchName);
952 if (pchTmp)
953 {
954 cchName -= pchTmp + 1 - pchName;
955 if (cchName > 0)
956 return 1;
957 }
958 }
959 }
960 return 0;
961}
962
963/**
964 * Parses a kBuild object variable accessor, resolving the object.
965 *
966 * @returns Pointer to the variable if found.
967 * @retval NULL if the object (or type) couldn't be resolved.
968 * @retval KOBJ_NOT_KBUILD_ACCESSOR if no a kBuild variable accessor.
969 *
970 * @param pchExpr The kBuild variable accessor expression.
971 * @param cchExpr Length of the expression.
972 * @param enmSeverity The minimum severity level for errors.
973 * @param pFileLoc The file location any errors should be reported
974 * at. Optional.
975 * @param ppchVarNm Where to return the pointer to the start of the
976 * variable name within the string @a pchExpr
977 * points to. Mandatory.
978 * @param pcchVarNm Where to return the length of the variable name.
979 * Mandatory.
980 * @param penmType Where to return the object type. Optional.
981 */
982static struct kbuild_object *
983parse_kbuild_object_variable_accessor(const char *pchExpr, size_t cchExpr,
984 enum kBuildSeverity enmSeverity, const struct floc *pFileLoc,
985 const char **ppchVarNm, size_t *pcchVarNm, enum kBuildType *penmType)
986{
987 const char * const pchOrgExpr = pchExpr;
988 size_t const cchOrgExpr = cchExpr;
989 char const *pchTmp;
990
991 /*
992 * To accept this as an kBuild accessor, we require:
993 * 1. Open bracket.
994 * 2. At sign separating the type from the name.
995 * 3. Closing bracket.
996 * 4. At least one character following it.
997 */
998 if (cchExpr >= 1+1+1+1 && *pchExpr == '[')
999 {
1000 pchExpr++;
1001 cchExpr--;
1002
1003 pchTmp = memchr(pchExpr, '@', cchExpr);
1004 if (pchTmp)
1005 {
1006 const char * const pchType = pchExpr;
1007 size_t const cchType = pchTmp - pchExpr;
1008
1009 cchExpr -= cchType + 1;
1010 pchExpr = pchTmp + 1;
1011 pchTmp = memchr(pchExpr, ']', cchExpr);
1012 if (pchTmp)
1013 {
1014 const char * const pchObjName = pchExpr;
1015 size_t const cchObjName = pchTmp - pchExpr;
1016
1017 cchExpr -= cchObjName + 1;
1018 pchExpr = pchTmp + 1;
1019 if (cchExpr > 0)
1020 {
1021 enum kBuildType enmType;
1022
1023 *pcchVarNm = cchExpr;
1024 *ppchVarNm = pchExpr;
1025
1026 /*
1027 * It's an kBuild define variable accessor, alright.
1028 */
1029 enmType = eval_kbuild_type_from_string(pchType, cchType);
1030 if (penmType)
1031 *penmType = enmType;
1032 if (enmType != kBuildType_Invalid)
1033 {
1034 struct kbuild_object *pObj = lookup_kbuild_object(enmType, pchObjName, cchObjName);
1035 if (pObj)
1036 return pObj;
1037
1038 /* failed. */
1039 kbuild_report_problem(enmSeverity, pFileLoc,
1040 _("kBuild object '%s' not found in kBuild variable accessor '%.*s'"),
1041 (int)cchObjName, pchObjName, (int)cchOrgExpr, pchOrgExpr);
1042 }
1043 else
1044 kbuild_report_problem(MAX(enmSeverity, kBuildSeverity_Error), pFileLoc,
1045 _("Invalid type '%.*s' specified in kBuild variable accessor '%.*s'"),
1046 (int)cchType, pchType, (int)cchOrgExpr, pchOrgExpr);
1047 return NULL;
1048 }
1049 }
1050 }
1051 }
1052
1053 *ppchVarNm = NULL;
1054 *pcchVarNm = 0;
1055 if (penmType)
1056 *penmType = kBuildType_Invalid;
1057 return KOBJ_NOT_KBUILD_ACCESSOR;
1058}
1059
1060/**
1061 * Looks up a variable in a kBuild object.
1062 *
1063 * The caller has done minimal matching, i.e. starting square brackets and
1064 * minimum length. We do the rest here.
1065 *
1066 * @returns Pointer to the variable if found.
1067 * @retval NULL if not found.
1068 * @retval VAR_NOT_KBUILD_ACCESSOR if no a kBuild variable accessor.
1069 *
1070 * @param pchName The kBuild variable accessor expression.
1071 * @param cchName Length of the expression.
1072 */
1073struct variable *
1074lookup_kbuild_object_variable_accessor(const char *pchName, size_t cchName)
1075{
1076 const char * const pchOrgName = pchName;
1077 size_t const cchOrgName = cchName;
1078 const char * pchVarNm;
1079 size_t cchVarNm;
1080 struct kbuild_object *pObj;
1081
1082 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Warning, NULL, &pchVarNm, &cchVarNm, NULL);
1083 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
1084 {
1085 if (pObj)
1086 {
1087 /*
1088 * Do the variable lookup.
1089 */
1090 const char *pszCachedName = strcache2_lookup(&variable_strcache, pchVarNm, cchVarNm);
1091 if (pszCachedName)
1092 {
1093 struct variable VarKey;
1094 struct variable *pVar;
1095 VarKey.name = pszCachedName;
1096 VarKey.length = cchName;
1097
1098 pVar = (struct variable *)hash_find_item_strcached(&pObj->pVariables->set->table, &VarKey);
1099 if (pVar)
1100 return pVar;
1101
1102 /*
1103 * Not found, check ancestors if any.
1104 */
1105 if (pObj->pszParent || pObj->pszTemplate)
1106 {
1107 struct kbuild_object *pParent = pObj;
1108 for (;;)
1109 {
1110 pParent = eval_kbuild_resolve_parent(pParent, 0 /*fQuiet*/);
1111 if (!pParent)
1112 break;
1113 pVar = (struct variable *)hash_find_item_strcached(&pParent->pVariables->set->table, &VarKey);
1114 if (pVar)
1115 return pVar;
1116 }
1117 }
1118 }
1119 }
1120
1121 /* Not found one way or the other. */
1122 return NULL;
1123 }
1124
1125 /* Not a kBuild object variable accessor. */
1126 return VAR_NOT_KBUILD_ACCESSOR;
1127}
1128
1129/** @} */
1130
1131void print_kbuild_data_base(void)
1132{
1133 struct kbuild_object *pCur;
1134
1135 puts(_("\n# kBuild defines"));
1136
1137 for (pCur = g_pHeadKbObjs; pCur; pCur = pCur->pGlobalNext)
1138 {
1139 printf("\nkBuild-define-%s %s",
1140 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName);
1141 if (pCur->pszParent)
1142 printf(" extending %s", pCur->pszParent);
1143 if (pCur->pszTemplate)
1144 printf(" using %s", pCur->pszTemplate);
1145 putchar('\n');
1146
1147 print_variable_set(pCur->pVariables->set, "");
1148
1149 printf("kBuild-endef-%s %s\n",
1150 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName);
1151 }
1152 /** @todo hash stats. */
1153}
1154
1155void print_kbuild_define_stats(void)
1156{
1157 /* later when hashing stuff */
1158}
1159
Note: See TracBrowser for help on using the repository browser.

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