VirtualBox

source: kBuild/trunk/src/kmk/kbuild-object.c@ 2719

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

kbuild-read.c -> kbuild-object.c

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 40.4 KB
Line 
1/* $Id: kbuild-object.c 2719 2014-01-01 17:40:56Z 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 struct variable *pAlias;
287 size_t cchPrefixed = pObj->cchVarPrefix + cchName;
288 char *pszPrefixed = xmalloc(cchPrefixed + 1);
289 memcpy(pszPrefixed, pObj->pszVarPrefix, pObj->cchVarPrefix);
290 memcpy(&pszPrefixed[pObj->cchVarPrefix], pszName, cchName);
291 pszPrefixed[cchPrefixed] = '\0';
292
293 pAlias = define_variable_alias_in_set(pszPrefixed, cchPrefixed, pVar, enmOrigin,
294 &global_variable_set, pFileLoc);
295 if (!pAlias->alias)
296 error(pFileLoc, _("Error defining alias '%s'"), pszPrefixed);
297 }
298
299 return pVar;
300}
301
302#if 0
303struct variable *
304define_kbuild_object_variable(struct kbuild_object *pObj, const char *pchName, size_t cchName,
305 const char *pchValue, size_t cchValue,
306 int fDuplicateValue, enum variable_origin enmOrigin,
307 int fRecursive, const struct floc *pFileLoc)
308{
309 return define_kbuild_object_variable_cached(pObj, strcache2_add(&variable_strcache, pchName, cchName),
310 pchValue, cchValue,
311 fDuplicateValue, enmOrigin,
312 fRecursive, pFileLoc);
313}
314#endif
315
316/**
317 * Try define a kBuild object variable via a possible accessor
318 * ([type@object]var).
319 *
320 * @returns Pointer to the defined variable on success.
321 * @retval VAR_NOT_KBUILD_ACCESSOR if it isn't an accessor.
322 *
323 * @param pchName The variable name, not cached.
324 * @param cchName The variable name length. This will not be ~0U.
325 * @param pszValue The variable value. If @a fDuplicateValue is clear,
326 * this should be assigned as the actual variable
327 * value, otherwise it will be duplicated. In the
328 * latter case it might not be properly null
329 * terminated.
330 * @param cchValue The value length.
331 * @param fDuplicateValue Whether @a pszValue need to be duplicated on the
332 * heap or is already there.
333 * @param enmOrigin The variable origin.
334 * @param fRecursive Whether it's a recursive variable.
335 * @param pFileLoc The location of the variable definition.
336 */
337struct variable *
338try_define_kbuild_object_variable_via_accessor(const char *pchName, size_t cchName,
339 const char *pszValue, size_t cchValue, int fDuplicateValue,
340 enum variable_origin enmOrigin, int fRecursive,
341 struct floc const *pFileLoc)
342{
343 struct kbuild_object *pObj;
344 const char *pchVarNm;
345 size_t cchVarNm;
346
347 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Fatal, pFileLoc,
348 &pchVarNm, &cchVarNm, NULL);
349 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
350 {
351 assert(pObj != NULL);
352 if (!is_valid_kbuild_object_variable_name(pchVarNm, cchVarNm))
353 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s' ('%s')"),
354 (int)cchVarNm, pchVarNm, (int)cchName, pchName);
355 return define_kbuild_object_variable_cached(pObj, strcache2_add(&variable_strcache, pchVarNm, cchVarNm),
356 pszValue, cchValue, fDuplicateValue, enmOrigin, fRecursive, pFileLoc);
357 }
358
359 return VAR_NOT_KBUILD_ACCESSOR;
360}
361
362/**
363 * Define a kBuild object variable in the topmost kBuild object.
364 *
365 * This won't be an variable accessor.
366 *
367 * @returns Pointer to the defined variable on success.
368 *
369 * @param pchName The variable name, not cached.
370 * @param cchName The variable name length. This will not be ~0U.
371 * @param pszValue The variable value. If @a fDuplicateValue is clear,
372 * this should be assigned as the actual variable
373 * value, otherwise it will be duplicated. In the
374 * latter case it might not be properly null
375 * terminated.
376 * @param cchValue The value length.
377 * @param fDuplicateValue Whether @a pszValue need to be duplicated on the
378 * heap or is already there.
379 * @param enmOrigin The variable origin.
380 * @param fRecursive Whether it's a recursive variable.
381 * @param pFileLoc The location of the variable definition.
382 */
383struct variable *
384define_kbuild_object_variable_in_top_obj(const char *pchName, size_t cchName,
385 const char *pszValue, size_t cchValue, int fDuplicateValue,
386 enum variable_origin enmOrigin, int fRecursive,
387 struct floc const *pFileLoc)
388{
389 assert(g_pTopKbEvalData != NULL);
390
391 if (!is_valid_kbuild_object_variable_name(pchName, cchName))
392 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s'"), (int)cchName, pchName);
393
394 return define_kbuild_object_variable_cached(g_pTopKbEvalData->pObj, strcache2_add(&variable_strcache, pchName, cchName),
395 pszValue, cchValue, fDuplicateValue, enmOrigin, fRecursive, pFileLoc);
396}
397
398/**
399 * Implements appending and prepending to a kBuild object variable.
400 *
401 * The variable is either accessed thru an accessor or by the topmost kBuild
402 * object.
403 *
404 * @returns Pointer to the defined variable on success.
405 *
406 * @param pchName The variable name, not cached.
407 * @param cchName The variable name length. This will not be ~0U.
408 * @param pszValue The variable value. Must be duplicated.
409 * @param cchValue The value length.
410 * @param fSimpleValue Whether we've already figured that it's a simple
411 * value. This is for optimizing appending/prepending
412 * to an existing simple value variable.
413 * @param enmOrigin The variable origin.
414 * @param fAppend Append if set, prepend if clear.
415 * @param pFileLoc The location of the variable definition.
416 */
417struct variable *
418kbuild_object_variable_pre_append(const char *pchName, size_t cchName,
419 const char *pchValue, size_t cchValue, int fSimpleValue,
420 enum variable_origin enmOrigin, int fAppend,
421 const struct floc *pFileLoc)
422{
423 struct kbuild_object *pObj;
424 struct variable VarKey;
425
426 /*
427 * Resolve the relevant kBuild object first.
428 */
429 if (cchName > 3 && pchName[0] == '[')
430 {
431 const char *pchVarNm;
432 size_t cchVarNm;
433 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Fatal, pFileLoc,
434 &pchVarNm, &cchVarNm, NULL);
435 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
436 {
437 pchName = pchVarNm;
438 cchName = cchVarNm;
439 }
440 else
441 pObj = g_pTopKbEvalData->pObj;
442 }
443 else
444 pObj = g_pTopKbEvalData->pObj;
445
446 /*
447 * Make sure the variable name is valid. Raise fatal error if not.
448 */
449 if (!is_valid_kbuild_object_variable_name(pchName, cchName))
450 fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s'"), (int)cchName, pchName);
451
452 /*
453 * Get the cached name and look it up in the object's variables.
454 */
455 VarKey.name = strcache2_lookup(&variable_strcache, pchName, cchName);
456 if (VarKey.name)
457 {
458 struct variable *pVar;
459
460 VarKey.length = cchName;
461 pVar = (struct variable *)hash_find_item_strcached(&pObj->pVariables->set->table, &VarKey);
462 if (pVar)
463 {
464 /* Append/prepend to existing variable. */
465 return do_variable_definition_append(pFileLoc, pVar, pchValue, cchValue, fSimpleValue, enmOrigin, fAppend);
466 }
467
468 /*
469 * Not found. Check ancestors if the 'override' directive isn't applied.
470 */
471 if (pObj->pszParent && enmOrigin != o_override)
472 {
473 struct kbuild_object *pParent = pObj;
474 for (;;)
475 {
476 pParent = eval_kbuild_resolve_parent(pParent, 0 /*fQuiet*/);
477 if (!pParent)
478 break;
479
480 pVar = (struct variable *)hash_find_item_strcached(&pParent->pVariables->set->table, &VarKey);
481 if (pVar)
482 {
483 if (pVar->value_length != ~0U)
484 assert(pVar->value_length == strlen(pVar->value));
485 else
486 pVar->value_length = strlen(pVar->value);
487
488 /*
489 * Combine the two values and define the variable in the
490 * specified child object. We must disregard 'origin' a
491 * little here, so we must do the gritty stuff our selves.
492 */
493 if ( pVar->recursive
494 || fSimpleValue
495 || !cchValue
496 || memchr(pchValue, '$', cchValue) == NULL )
497 {
498 size_t cchNewValue;
499 char *pszNewValue;
500 char *pszTmp;
501
502 /* Just join up the two values. */
503 if (pVar->value_length == 0)
504 {
505 cchNewValue = cchValue;
506 pszNewValue = xstrndup(pchValue, cchValue);
507 }
508 else if (!cchValue)
509 {
510 cchNewValue = pVar->value_length;
511 pszNewValue = xmalloc(cchNewValue + 1);
512 memcpy(pszNewValue, pVar->value, cchNewValue + 1);
513 }
514 else
515 {
516 cchNewValue = pVar->value_length + 1 + cchValue;
517 pszNewValue = xmalloc(cchNewValue + 1);
518 if (fAppend)
519 {
520 memcpy(pszNewValue, pVar->value, pVar->value_length);
521 pszTmp = pszNewValue + pVar->value_length;
522 *pszTmp++ = ' ';
523 memcpy(pszTmp, pchValue, cchValue);
524 pszTmp[cchValue] = '\0';
525 }
526 else
527 {
528 memcpy(pszNewValue, pchValue, cchValue);
529 pszTmp = pszNewValue + cchValue;
530 *pszTmp++ = ' ';
531 memcpy(pszNewValue, pVar->value, pVar->value_length);
532 pszTmp[pVar->value_length] = '\0';
533 }
534 }
535
536 /* Define the new variable in the child. */
537 return define_kbuild_object_variable_cached(pObj, VarKey.name,
538 pszNewValue, cchNewValue, 0 /*fDuplicateValue*/,
539 enmOrigin, pVar->recursive, pFileLoc);
540
541 }
542 else
543 {
544 /* Lazy bird: Copy the variable from the ancestor and
545 then do a normal append/prepend on it. */
546 pVar = define_kbuild_object_variable_cached(pObj, VarKey.name,
547 pVar->value, pVar->value_length, 1 /*fDuplicateValue*/,
548 enmOrigin, pVar->recursive, pFileLoc);
549 append_expanded_string_to_variable(pVar, pchValue, cchValue, fAppend);
550 return pVar;
551 }
552 }
553 }
554 }
555 }
556 else
557 VarKey.name = strcache2_add(&variable_strcache, pchName, cchName);
558
559 /* Variable not found. */
560 return define_kbuild_object_variable_cached(pObj, VarKey.name,
561 pchValue, cchValue, 1 /*fDuplicateValue*/, enmOrigin,
562 1 /*fRecursive */, pFileLoc);
563}
564
565/** @} */
566
567
568static const char *
569eval_kbuild_type_to_string(enum kBuildType enmType)
570{
571 switch (enmType)
572 {
573 case kBuildType_Target: return "target";
574 case kBuildType_Template: return "template";
575 case kBuildType_Tool: return "tool";
576 case kBuildType_Sdk: return "sdk";
577 case kBuildType_Unit: return "unit";
578 default:
579 case kBuildType_Invalid: return "invalid";
580 }
581}
582
583/**
584 * Converts a string into an kBuild object type.
585 *
586 * @returns The type on success, kBuildType_Invalid on failure.
587 * @param pchWord The pchWord. Not necessarily zero terminated.
588 * @param cchWord The length of the word.
589 */
590static enum kBuildType
591eval_kbuild_type_from_string(const char *pchWord, size_t cchWord)
592{
593 if (cchWord >= 3)
594 {
595 if (*pchWord == 't')
596 {
597 if (WORD_IS(pchWord, cchWord, "target"))
598 return kBuildType_Target;
599 if (WORD_IS(pchWord, cchWord, "template"))
600 return kBuildType_Template;
601 if (WORD_IS(pchWord, cchWord, "tool"))
602 return kBuildType_Tool;
603 }
604 else
605 {
606 if (WORD_IS(pchWord, cchWord, "sdk"))
607 return kBuildType_Sdk;
608 if (WORD_IS(pchWord, cchWord, "unit"))
609 return kBuildType_Unit;
610 }
611 }
612
613 return kBuildType_Invalid;
614}
615
616
617static char *
618allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, size_t *pcchToken, int fStrip)
619{
620 unsigned int cchToken;
621 char *pszToken = find_next_token_eos(ppszCursor, pszEos, &cchToken);
622 if (pszToken)
623 {
624 pszToken = allocated_variable_expand_2(pszToken, cchToken, &cchToken);
625 if (pszToken)
626 {
627 if (fStrip)
628 {
629 unsigned int off = 0;
630 while (MY_IS_BLANK(pszToken[off]))
631 off++;
632 if (off)
633 {
634 cchToken -= off;
635 memmove(pszToken, &pszToken[off], cchToken + 1);
636 }
637
638 while (cchToken > 0 && MY_IS_BLANK(pszToken[cchToken - 1]))
639 pszToken[--cchToken] = '\0';
640 }
641
642 assert(cchToken == strlen(pszToken));
643 if (pcchToken)
644 *pcchToken = cchToken;
645 return pszToken;
646 }
647 }
648
649 if (pcchToken)
650 *pcchToken = 0;
651 return NULL;
652}
653
654static struct kbuild_object *
655eval_kbuild_resolve_parent(struct kbuild_object *pObj, int fQuiet)
656{
657 if ( !pObj->pParent
658 && pObj->pszParent)
659 {
660 struct kbuild_object *pCur = g_pHeadKbObjs;
661 while (pCur)
662 {
663 if ( pCur->enmType == pObj->enmType
664 && !strcmp(pCur->pszName, pObj->pszParent))
665 {
666 if ( pCur->pszParent
667 && ( pCur->pParent == pObj
668 || !strcmp(pCur->pszParent, pObj->pszName)) )
669 fatal(&pObj->FileLoc, _("'%s' and '%s' are both trying to be each other children..."),
670 pObj->pszName, pCur->pszName);
671
672 pObj->pParent = pCur;
673 pObj->pVariables->next = pObj->pVariables;
674 return pCur;
675 }
676
677 pCur = pCur->pGlobalNext;
678 }
679
680 /* Not found. */
681 if (!fQuiet)
682 error(&pObj->FileLoc, _("Could not locate parent '%s' of '%s'"), pObj->pszParent, pObj->pszName);
683 }
684 return pObj->pParent;
685}
686
687static int
688eval_kbuild_define_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc,
689 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType)
690{
691 unsigned int cch;
692 char ch;
693 char *psz;
694 const char *pszPrefix;
695 struct kbuild_object *pObj;
696 struct kbuild_eval_data *pData;
697
698 if (fIgnoring)
699 return 0;
700
701 /*
702 * Create a new kBuild object.
703 */
704 pObj = xmalloc(sizeof(*pObj));
705 pObj->enmType = enmType;
706 pObj->pszName = NULL;
707 pObj->cchName = 0;
708 pObj->FileLoc = *pFileLoc;
709
710 pObj->pGlobalNext = g_pHeadKbObjs;
711 g_pHeadKbObjs = pObj;
712
713 pObj->pVariables = create_new_variable_set();
714
715 pObj->pszParent = NULL;
716 pObj->cchParent = 0;
717 pObj->pParent = NULL;
718
719 pObj->pszTemplate = NULL;
720
721 pObj->pszVarPrefix = NULL;
722 pObj->cchVarPrefix = 0;
723
724 /*
725 * The first word is the name.
726 */
727 pObj->pszName = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchName, 1 /*strip*/);
728 if (!pObj->pszName || !*pObj->pszName)
729 fatal(pFileLoc, _("The kBuild define requires a name"));
730
731 psz = pObj->pszName;
732 while ((ch = *psz++) != '\0')
733 if (!isgraph(ch))
734 {
735 error(pFileLoc, _("The 'kBuild-define-%s' name '%s' contains one or more invalid characters"),
736 eval_kbuild_type_to_string(enmType), pObj->pszName);
737 break;
738 }
739
740 /*
741 * Calc the variable prefix.
742 */
743 switch (enmType)
744 {
745 case kBuildType_Target: pszPrefix = ""; break;
746 case kBuildType_Template: pszPrefix = "TEMPLATE_"; break;
747 case kBuildType_Tool: pszPrefix = "TOOL_"; break;
748 case kBuildType_Sdk: pszPrefix = "SDK_"; break;
749 case kBuildType_Unit: pszPrefix = "UNIT_"; break;
750 default:
751 fatal(pFileLoc, _("enmType=%d"), enmType);
752 return -1;
753 }
754 cch = strlen(pszPrefix);
755 pObj->cchVarPrefix = cch + pObj->cchName;
756 pObj->pszVarPrefix = xmalloc(pObj->cchVarPrefix + 1);
757 memcpy(pObj->pszVarPrefix, pszPrefix, cch);
758 memcpy(&pObj->pszVarPrefix[cch], pObj->pszName, pObj->cchName);
759
760 /*
761 * Parse subsequent words.
762 */
763 psz = find_next_token_eos(&pszLine, pszEos, &cch);
764 while (psz)
765 {
766 if (WORD_IS(psz, cch, "extending"))
767 {
768 /* Inheritance directive. */
769 if (pObj->pszParent != NULL)
770 fatal(pFileLoc, _("'extending' can only occure once"));
771 pObj->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchParent, 1 /*strip*/);
772 if (!pObj->pszParent || !*pObj->pszParent)
773 fatal(pFileLoc, _("'extending' requires a parent name"));
774 }
775 else if (WORD_IS(psz, cch, "using"))
776 {
777 char *pszTemplate;
778 size_t cchTemplate;
779
780 /* Template directive. */
781 if (enmType != kBuildType_Target)
782 fatal(pFileLoc, _("'using <template>' can only be used with 'kBuild-define-target'"));
783 if (pObj->pszTemplate != NULL)
784 fatal(pFileLoc, _("'using' can only occure once"));
785
786 pszTemplate = allocate_expanded_next_token(&pszLine, pszEos, &cchTemplate, 1 /*fStrip*/);
787 if (!pszTemplate || !*pszTemplate)
788 fatal(pFileLoc, _("'using' requires a template name"));
789
790 define_kbuild_object_variable_cached(pObj, g_pszVarNmTemplate, pszTemplate, cchTemplate,
791 0 /*fDuplicateValue*/, o_default, 0 /*fRecursive*/, pFileLoc),
792
793 /* next token */
794 psz = find_next_token_eos(&pszLine, pszEos, &cch);
795 }
796 else
797 fatal(pFileLoc, _("Don't know what '%.*s' means"), (int)cch, psz);
798 }
799
800 /*
801 * Try resolve the parent.
802 */
803 eval_kbuild_resolve_parent(pObj, 1 /*fQuiet*/);
804
805 /*
806 * Create an eval stack entry and change the current variable set.
807 */
808 pData = xmalloc(sizeof(*pData));
809 pData->pObj = pObj;
810 pData->pVariablesSaved = current_variable_set_list;
811 current_variable_set_list = pObj->pVariables;
812
813 pData->pStackDown = *ppData;
814 *ppData = pData;
815 g_pTopKbEvalData = pData;
816
817 return 0;
818}
819
820static int
821eval_kbuild_endef_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc,
822 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType)
823{
824 struct kbuild_eval_data *pData;
825 struct kbuild_object *pObj;
826 size_t cchName;
827 char *pszName;
828
829 if (fIgnoring)
830 return 0;
831
832 /*
833 * Is there something to pop?
834 */
835 pData = *ppData;
836 if (!pData)
837 {
838 error(pFileLoc, _("kBuild-endef-%s is missing kBuild-define-%s"),
839 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(enmType));
840 return 0;
841 }
842
843 /*
844 * ... and does it have a matching kind?
845 */
846 pObj = pData->pObj;
847 if (pObj->enmType != enmType)
848 error(pFileLoc, _("'kBuild-endef-%s' does not match 'kBuild-define-%s %s'"),
849 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(pObj->enmType), pObj->pszName);
850
851 /*
852 * The endef-kbuild may optionally be followed by the target name.
853 * It should match the name given to the kBuild-define.
854 */
855 pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*fStrip*/);
856 if (pszName)
857 {
858 if ( cchName != pObj->cchName
859 || strcmp(pszName, pObj->pszName))
860 error(pFileLoc, _("'kBuild-endef-%s %s' does not match 'kBuild-define-%s %s'"),
861 eval_kbuild_type_to_string(enmType), pszName,
862 eval_kbuild_type_to_string(pObj->enmType), pObj->pszName);
863 free(pszName);
864 }
865
866 /*
867 * Pop a define off the stack.
868 */
869 assert(pData == g_pTopKbEvalData);
870 *ppData = g_pTopKbEvalData = pData->pStackDown;
871 pData->pStackDown = NULL;
872 current_variable_set_list = pData->pVariablesSaved;
873 pData->pVariablesSaved = NULL;
874 free(pData);
875
876 return 0;
877}
878
879int eval_kbuild_read_hook(struct kbuild_eval_data **kdata, const struct floc *flocp,
880 const char *pchWord, size_t cchWord, const char *line, const char *eos, int ignoring)
881{
882 enum kBuildType enmType;
883
884 /*
885 * Skip the 'kBuild-' prefix that the caller already matched.
886 */
887 assert(memcmp(pchWord, "kBuild-", sizeof("kBuild-") - 1) == 0);
888 pchWord += sizeof("kBuild-") - 1;
889 cchWord -= sizeof("kBuild-") - 1;
890
891 /*
892 * String switch.
893 */
894 if ( cchWord >= sizeof("define-") - 1
895 && strneq(pchWord, "define-", sizeof("define-") - 1))
896 {
897 enmType = eval_kbuild_type_from_string(pchWord + sizeof("define-") - 1, cchWord - sizeof("define-") + 1);
898 if (enmType != kBuildType_Invalid)
899 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, enmType);
900 }
901 else if ( cchWord >= sizeof("endef-") - 1
902 && strneq(pchWord, "endef-", sizeof("endef-") - 1))
903 {
904 enmType = eval_kbuild_type_from_string(pchWord + sizeof("endif-") - 1, cchWord - sizeof("endif-") + 1);
905 if (enmType != kBuildType_Invalid)
906 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, enmType);
907 }
908 else if (WORD_IS(pchWord, cchWord, "endef"))
909 {
910 /* Terminate whatever definition is on top. */
911
912 }
913
914 /*
915 * Everything that is prefixed with 'kBuild-' is reserved for language
916 * extensions, at least until legacy assignments/whatever turns up.
917 */
918 error(flocp, _("Unknown syntax 'kBuild-%.*s'"), (int)cchWord, pchWord);
919 return 0;
920}
921
922
923/** @name kBuild object variable accessor related functions
924 * @{
925 */
926
927/**
928 * Checks if the given name is an object variable accessor.
929 *
930 * @returns 1 if it is, 0 if it isn't.
931 * @param pchName The potential kBuild variable accessor
932 * expression.
933 * @param cchName Length of the expression.
934 */
935int is_kbuild_object_variable_accessor(const char *pchName, size_t cchName)
936{
937 char const *pchTmp;
938
939 /* See lookup_kbuild_object_variable for the rules. */
940 if (cchName >= 1+1+1+1 && *pchName == '[')
941 {
942 pchName++;
943 cchName--;
944
945 pchTmp = memchr(pchName, '@', cchName);
946 if (pchTmp)
947 {
948 cchName -= pchTmp + 1 - pchName;
949 pchName = pchTmp + 1;
950 pchTmp = memchr(pchName, ']', cchName);
951 if (pchTmp)
952 {
953 cchName -= pchTmp + 1 - pchName;
954 if (cchName > 0)
955 return 1;
956 }
957 }
958 }
959 return 0;
960}
961
962/**
963 * Parses a kBuild object variable accessor, resolving the object.
964 *
965 * @returns Pointer to the variable if found.
966 * @retval NULL if the object (or type) couldn't be resolved.
967 * @retval KOBJ_NOT_KBUILD_ACCESSOR if no a kBuild variable accessor.
968 *
969 * @param pchExpr The kBuild variable accessor expression.
970 * @param cchExpr Length of the expression.
971 * @param enmSeverity The minimum severity level for errors.
972 * @param pFileLoc The file location any errors should be reported
973 * at. Optional.
974 * @param ppchVarNm Where to return the pointer to the start of the
975 * variable name within the string @a pchExpr
976 * points to. Mandatory.
977 * @param pcchVarNm Where to return the length of the variable name.
978 * Mandatory.
979 * @param penmType Where to return the object type. Optional.
980 */
981static struct kbuild_object *
982parse_kbuild_object_variable_accessor(const char *pchExpr, size_t cchExpr,
983 enum kBuildSeverity enmSeverity, const struct floc *pFileLoc,
984 const char **ppchVarNm, size_t *pcchVarNm, enum kBuildType *penmType)
985{
986 const char * const pchOrgExpr = pchExpr;
987 size_t const cchOrgExpr = cchExpr;
988 char const *pchTmp;
989
990 /*
991 * To accept this as an kBuild accessor, we require:
992 * 1. Open bracket.
993 * 2. At sign separating the type from the name.
994 * 3. Closing bracket.
995 * 4. At least one character following it.
996 */
997 if (cchExpr >= 1+1+1+1 && *pchExpr == '[')
998 {
999 pchExpr++;
1000 cchExpr--;
1001
1002 pchTmp = memchr(pchExpr, '@', cchExpr);
1003 if (pchTmp)
1004 {
1005 const char * const pchType = pchExpr;
1006 size_t const cchType = pchTmp - pchExpr;
1007
1008 cchExpr -= cchType + 1;
1009 pchExpr = pchTmp + 1;
1010 pchTmp = memchr(pchExpr, ']', cchExpr);
1011 if (pchTmp)
1012 {
1013 const char * const pchObjName = pchExpr;
1014 size_t const cchObjName = pchTmp - pchExpr;
1015
1016 cchExpr -= cchObjName + 1;
1017 pchExpr = pchTmp + 1;
1018 if (cchExpr > 0)
1019 {
1020 enum kBuildType enmType;
1021
1022 *pcchVarNm = cchExpr;
1023 *ppchVarNm = pchExpr;
1024
1025 /*
1026 * It's an kBuild define variable accessor, alright.
1027 */
1028 enmType = eval_kbuild_type_from_string(pchType, cchType);
1029 if (penmType)
1030 *penmType = enmType;
1031 if (enmType != kBuildType_Invalid)
1032 {
1033 struct kbuild_object *pObj = lookup_kbuild_object(enmType, pchObjName, cchObjName);
1034 if (pObj)
1035 return pObj;
1036
1037 /* failed. */
1038 kbuild_report_problem(enmSeverity, pFileLoc,
1039 _("kBuild object '%s' not found in kBuild variable accessor '%.*s'"),
1040 (int)cchObjName, pchObjName, (int)cchOrgExpr, pchOrgExpr);
1041 }
1042 else
1043 kbuild_report_problem(MAX(enmSeverity, kBuildSeverity_Error), pFileLoc,
1044 _("Invalid type '%.*s' specified in kBuild variable accessor '%.*s'"),
1045 (int)cchType, pchType, (int)cchOrgExpr, pchOrgExpr);
1046 return NULL;
1047 }
1048 }
1049 }
1050 }
1051
1052 *ppchVarNm = NULL;
1053 *pcchVarNm = 0;
1054 if (penmType)
1055 *penmType = kBuildType_Invalid;
1056 return KOBJ_NOT_KBUILD_ACCESSOR;
1057}
1058
1059/**
1060 * Looks up a variable in a kBuild object.
1061 *
1062 * The caller has done minimal matching, i.e. starting square brackets and
1063 * minimum length. We do the rest here.
1064 *
1065 * @returns Pointer to the variable if found.
1066 * @retval NULL if not found.
1067 * @retval VAR_NOT_KBUILD_ACCESSOR if no a kBuild variable accessor.
1068 *
1069 * @param pchName The kBuild variable accessor expression.
1070 * @param cchName Length of the expression.
1071 */
1072struct variable *
1073lookup_kbuild_object_variable_accessor(const char *pchName, size_t cchName)
1074{
1075 const char * const pchOrgName = pchName;
1076 size_t const cchOrgName = cchName;
1077 const char * pchVarNm;
1078 size_t cchVarNm;
1079 struct kbuild_object *pObj;
1080
1081 pObj = parse_kbuild_object_variable_accessor(pchName, cchName, kBuildSeverity_Warning, NULL, &pchVarNm, &cchVarNm, NULL);
1082 if (pObj != KOBJ_NOT_KBUILD_ACCESSOR)
1083 {
1084 if (pObj)
1085 {
1086 /*
1087 * Do the variable lookup.
1088 */
1089 const char *pszCachedName = strcache2_lookup(&variable_strcache, pchVarNm, cchVarNm);
1090 if (pszCachedName)
1091 {
1092 struct variable VarKey;
1093 struct variable *pVar;
1094 VarKey.name = pszCachedName;
1095 VarKey.length = cchName;
1096
1097 pVar = (struct variable *)hash_find_item_strcached(&pObj->pVariables->set->table, &VarKey);
1098 if (pVar)
1099 return pVar;
1100
1101 /*
1102 * Not found, check ancestors if any.
1103 */
1104 if (pObj->pszParent || pObj->pszTemplate)
1105 {
1106 struct kbuild_object *pParent = pObj;
1107 for (;;)
1108 {
1109 pParent = eval_kbuild_resolve_parent(pParent, 0 /*fQuiet*/);
1110 if (!pParent)
1111 break;
1112 pVar = (struct variable *)hash_find_item_strcached(&pParent->pVariables->set->table, &VarKey);
1113 if (pVar)
1114 return pVar;
1115 }
1116 }
1117 }
1118 }
1119
1120 /* Not found one way or the other. */
1121 return NULL;
1122 }
1123
1124 /* Not a kBuild object variable accessor. */
1125 return VAR_NOT_KBUILD_ACCESSOR;
1126}
1127
1128/** @} */
1129
1130void print_kbuild_data_base(void)
1131{
1132 struct kbuild_object *pCur;
1133
1134 puts(_("\n# kBuild defines"));
1135
1136 for (pCur = g_pHeadKbObjs; pCur; pCur = pCur->pGlobalNext)
1137 {
1138 printf("\nkBuild-define-%s %s",
1139 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName);
1140 if (pCur->pszParent)
1141 printf(" extending %s", pCur->pszParent);
1142 if (pCur->pszTemplate)
1143 printf(" using %s", pCur->pszTemplate);
1144 putchar('\n');
1145
1146 print_variable_set(pCur->pVariables->set, "");
1147
1148 printf("kBuild-endef-%s %s\n",
1149 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName);
1150 }
1151 /** @todo hash stats. */
1152}
1153
1154void print_kbuild_define_stats(void)
1155{
1156 /* later when hashing stuff */
1157}
1158
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