Changeset 2717 in kBuild for trunk/src/kmk
- Timestamp:
- Dec 30, 2013 12:58:43 AM (11 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kbuild-read.c
r2549 r2717 5 5 6 6 /* 7 * Copyright (c) 2011 knut st. osmundsen <[email protected]>7 * Copyright (c) 2011-2013 knut st. osmundsen <[email protected]> 8 8 * 9 9 * This file is part of kBuild. … … 37 37 38 38 #include <assert.h> 39 #include <stdarg.h> 39 40 40 41 … … 49 50 * Structures and Typedefs * 50 51 *******************************************************************************/ 51 /** Indicate which kind of kBuild define we're working on. */52 enum kBuild Def53 { 54 kBuild Def_Invalid,55 kBuild Def_Target,56 kBuild Def_Template,57 kBuild Def_Tool,58 kBuild Def_Sdk,59 kBuild Def_Unit52 /** kBuild object type. */ 53 enum kBuildType 54 { 55 kBuildType_Invalid, 56 kBuildType_Target, 57 kBuildType_Template, 58 kBuildType_Tool, 59 kBuildType_Sdk, 60 kBuildType_Unit 60 61 }; 61 62 62 enum kBuildExtendBy 63 { 64 kBuildExtendBy_NoParent, 65 kBuildExtendBy_Overriding, 66 kBuildExtendBy_Appending, 67 kBuildExtendBy_Prepending 63 enum kBuildSeverity 64 { 65 kBuildSeverity_Warning, 66 kBuildSeverity_Error, 67 kBuildSeverity_Fatal 68 68 }; 69 69 70 70 71 71 /** 72 * The data we stack during eval. 73 */ 74 struct kbuild_eval_data 75 { 76 /** The kind of define. */ 77 enum kBuildDef enmKind; 72 * kBuild object data. 73 */ 74 struct kbuild_object 75 { 76 /** The object type. */ 77 enum kBuildType enmType; 78 /** Object name length. */ 79 size_t cchName; 78 80 /** The bare name of the define. */ 79 81 char *pszName; … … 82 84 83 85 /** Pointer to the next element in the global list. */ 84 struct kbuild_eval_data *pGlobalNext; 85 /** Pointer to the element below us on the stack. */ 86 struct kbuild_eval_data *pStackDown; 86 struct kbuild_object *pGlobalNext; 87 87 88 88 /** The variable set associated with this define. */ 89 89 struct variable_set_list *pVariables; 90 /** The saved current variable set, for restoring in kBuild-endef. */91 struct variable_set_list *pVariablesSaved;92 90 93 91 /** The parent name, NULL if none. */ 94 92 char *pszParent; 95 /** The inheritance method. */ 96 enum kBuildExtendBy enmExtendBy; 97 /** Pointer to the parent. Resolved lazily, so it can be NULL even if we have 98 * a parent. */ 99 struct kbuild_eval_data *pParent; 100 101 /** The template, NULL if none. Only applicable to targets. */ 102 char *pszTemplate; 103 /** Pointer to the template. Resolved lazily, so it can be NULL even if we have 104 * a parent. */ 105 struct kbuild_eval_data *pTemplate; 106 107 /** The variable prefix. */ 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. */ 108 105 char *pszVarPrefix; 109 106 /** The length of the variable prefix. */ 110 107 size_t cchVarPrefix; 111 108 }; 109 110 111 /** 112 * The data we stack during eval. 113 */ 114 struct 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 112 124 113 125 … … 117 129 /** Linked list (LIFO) of kBuild defines. 118 130 * @todo use a hash! */ 119 struct kbuild_eval_data *g_pHeadKbDefs = NULL; 120 /** Stack of kBuild defines. */ 121 struct kbuild_eval_data *g_pTopKbDef = NULL; 122 123 124 struct variable_set * 125 get_top_kbuild_variable_set(void) 126 { 127 struct kbuild_eval_data *pTop = g_pTopKbDef; 128 assert(pTop != NULL); 129 return pTop->pVariables->set; 130 } 131 132 133 char * 134 kbuild_prefix_variable(const char *pszName, unsigned int *pcchName) 135 { 136 struct kbuild_eval_data *pTop = g_pTopKbDef; 137 char *pszPrefixed; 138 unsigned int cchPrefixed; 139 140 assert(pTop != NULL); 141 142 cchPrefixed = pTop->cchVarPrefix + *pcchName; 143 pszPrefixed = xmalloc(cchPrefixed + 1); 144 memcpy(pszPrefixed, pTop->pszVarPrefix, pTop->cchVarPrefix); 145 memcpy(&pszPrefixed[pTop->cchVarPrefix], pszName, *pcchName); 146 pszPrefixed[cchPrefixed] = '\0'; 147 *pcchName = cchPrefixed; 148 return pszPrefixed; 149 } 150 151 131 static 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. */ 135 struct kbuild_eval_data *g_pTopKbEvalData = NULL; 136 137 /** Cached variable name '_TEMPLATE'. */ 138 static 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. */ 142 int g_fKbObjCompMode = 1; 143 144 145 /******************************************************************************* 146 * Internal Functions * 147 *******************************************************************************/ 148 static struct kbuild_object * 149 eval_kbuild_resolve_parent(struct kbuild_object *pObj, int fQuiet); 150 151 static struct kbuild_object * 152 parse_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 */ 162 void 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 */ 176 static 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 */ 152 214 static const char * 153 eval_kbuild_kind_to_string(enum kBuildDef enmKind) 154 { 155 switch (enmKind) 156 { 157 case kBuildDef_Target: return "target"; 158 case kBuildDef_Template: return "template"; 159 case kBuildDef_Tool: return "tool"; 160 case kBuildDef_Sdk: return "sdk"; 161 case kBuildDef_Unit: return "unit"; 215 kbuild_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 223 static struct kbuild_object * 224 lookup_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 */ 251 static int 252 is_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 265 static struct variable * 266 define_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 304 struct variable * 305 define_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 */ 338 struct variable * 339 try_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 */ 384 struct variable * 385 define_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 */ 418 struct variable * 419 kbuild_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 569 static const char * 570 eval_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"; 162 579 default: 163 case kBuildDef_Invalid: return "invalid"; 164 } 165 } 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 */ 591 static enum kBuildType 592 eval_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 166 617 167 618 static char * 168 allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, unsigned int *pcchToken, int fStrip)619 allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, size_t *pcchToken, int fStrip) 169 620 { 170 621 unsigned int cchToken; … … 193 644 if (pcchToken) 194 645 *pcchToken = cchToken; 195 } 196 } 197 return pszToken; 198 } 199 200 static struct kbuild_eval_data * 201 eval_kbuild_resolve_parent(struct kbuild_eval_data *pData) 202 { 203 if ( !pData->pParent 204 && pData->pszParent) 205 { 206 struct kbuild_eval_data *pCur = g_pHeadKbDefs; 646 return pszToken; 647 } 648 } 649 650 if (pcchToken) 651 *pcchToken = 0; 652 return NULL; 653 } 654 655 static struct kbuild_object * 656 eval_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; 207 662 while (pCur) 208 663 { 209 if ( pCur->enm Kind == pData->enmKind210 && !strcmp(pCur->pszName, p Data->pszParent))664 if ( pCur->enmType == pObj->enmType 665 && !strcmp(pCur->pszName, pObj->pszParent)) 211 666 { 212 667 if ( pCur->pszParent 213 && ( pCur->pParent == p Data214 || !strcmp(pCur->pszParent, p Data->pszName)) )215 fatal(&p Data->FileLoc, _("'%s' and '%s' are both trying to be each other children..."),216 p Data->pszName, pCur->pszName);217 218 p Data->pParent = pCur;219 p Data->pVariables->next = pData->pVariables;220 break;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; 221 676 } 677 222 678 pCur = pCur->pGlobalNext; 223 679 } 224 } 225 return pData->pParent; 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; 226 686 } 227 687 228 688 static int 229 689 eval_kbuild_define_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc, 230 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuild Def enmKind)690 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType) 231 691 { 232 692 unsigned int cch; 233 unsigned int cchName;234 693 char ch; 235 694 char *psz; 236 695 const char *pszPrefix; 696 struct kbuild_object *pObj; 237 697 struct kbuild_eval_data *pData; 238 698 … … 241 701 242 702 /* 243 * Create a new kBuild eval data item. 244 */ 245 pData = xmalloc(sizeof(*pData)); 246 pData->enmKind = enmKind; 247 pData->pszName = NULL; 248 pData->FileLoc = *pFileLoc; 249 250 pData->pGlobalNext = g_pHeadKbDefs; 251 g_pHeadKbDefs = pData; 252 253 pData->pStackDown = *ppData; 254 *ppData = g_pTopKbDef = pData; 255 pData->pVariables = create_new_variable_set(); 256 pData->pVariablesSaved = NULL; 257 258 pData->pszParent = NULL; 259 pData->enmExtendBy = kBuildExtendBy_NoParent; 260 pData->pParent = NULL; 261 262 pData->pszTemplate = NULL; 263 pData->pTemplate = NULL; 264 265 pData->pszVarPrefix = NULL; 266 pData->cchVarPrefix = 0; 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; 267 724 268 725 /* 269 726 * The first word is the name. 270 727 */ 271 p Data->pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*strip*/);272 if (!p Data->pszName || !*pData->pszName)728 pObj->pszName = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchName, 1 /*strip*/); 729 if (!pObj->pszName || !*pObj->pszName) 273 730 fatal(pFileLoc, _("The kBuild define requires a name")); 274 731 275 psz = p Data->pszName;732 psz = pObj->pszName; 276 733 while ((ch = *psz++) != '\0') 277 734 if (!isgraph(ch)) 278 735 { 279 736 error(pFileLoc, _("The 'kBuild-define-%s' name '%s' contains one or more invalid characters"), 280 eval_kbuild_ kind_to_string(enmKind), pData->pszName);737 eval_kbuild_type_to_string(enmType), pObj->pszName); 281 738 break; 282 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); 283 760 284 761 /* … … 291 768 { 292 769 /* Inheritance directive. */ 293 if (p Data->pszParent != NULL)770 if (pObj->pszParent != NULL) 294 771 fatal(pFileLoc, _("'extending' can only occure once")); 295 p Data->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &cch, 1 /*strip*/);296 if (!p Data->pszParent || !*pData->pszParent)772 pObj->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &pObj->cchParent, 1 /*strip*/); 773 if (!pObj->pszParent || !*pObj->pszParent) 297 774 fatal(pFileLoc, _("'extending' requires a parent name")); 298 299 pData->enmExtendBy = kBuildExtendBy_Overriding;300 301 /* optionally 'by overriding|prepending|appending' */302 psz = find_next_token_eos(&pszLine, pszEos, &cch);303 if (psz && WORD_IS(psz, cch, "by"))304 {305 cch = 0;306 psz = find_next_token_eos(&pszLine, pszEos, &cch);307 if (WORD_IS(psz, cch, "overriding"))308 pData->enmExtendBy = kBuildExtendBy_Overriding;309 else if (WORD_IS(psz, cch, "appending"))310 pData->enmExtendBy = kBuildExtendBy_Appending;311 else if (WORD_IS(psz, cch, "prepending"))312 pData->enmExtendBy = kBuildExtendBy_Prepending;313 else314 fatal(pFileLoc, _("Unknown 'extending by' method '%.*s'"), (int)cch, psz);315 316 /* next token */317 psz = find_next_token_eos(&pszLine, pszEos, &cch);318 }319 775 } 320 776 else if (WORD_IS(psz, cch, "using")) 321 777 { 778 char *pszTemplate; 779 size_t cchTemplate; 780 322 781 /* Template directive. */ 323 if (enm Kind != kBuildDef_Tool)782 if (enmType != kBuildType_Target) 324 783 fatal(pFileLoc, _("'using <template>' can only be used with 'kBuild-define-target'")); 325 if (p Data->pszTemplate != NULL)784 if (pObj->pszTemplate != NULL) 326 785 fatal(pFileLoc, _("'using' can only occure once")); 327 786 328 p Data->pszTemplate = allocate_expanded_next_token(&pszLine, pszEos, &cch, 1 /*fStrip*/);329 if (!p Data->pszTemplate || !*pData->pszTemplate)787 pszTemplate = allocate_expanded_next_token(&pszLine, pszEos, &cchTemplate, 1 /*fStrip*/); 788 if (!pszTemplate || !*pszTemplate) 330 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), 331 793 332 794 /* next token */ … … 338 800 339 801 /* 340 * Calc the variable prefix. 341 */ 342 switch (enmKind) 343 { 344 case kBuildDef_Target: pszPrefix = ""; break; 345 case kBuildDef_Template: pszPrefix = "TEMPLATE_"; break; 346 case kBuildDef_Tool: pszPrefix = "TOOL_"; break; 347 case kBuildDef_Sdk: pszPrefix = "SDK_"; break; 348 case kBuildDef_Unit: pszPrefix = "UNIT_"; break; 349 default: 350 fatal(pFileLoc, _("enmKind=%d"), enmKind); 351 return -1; 352 } 353 cch = strlen(pszPrefix); 354 pData->cchVarPrefix = cch + cchName; 355 pData->pszVarPrefix = xmalloc(pData->cchVarPrefix + 1); 356 memcpy(pData->pszVarPrefix, pszPrefix, cch); 357 memcpy(&pData->pszVarPrefix[cch], pData->pszName, cchName); 358 359 /* 360 * Try resolve the parent and change the current variable set. 361 */ 362 eval_kbuild_resolve_parent(pData); 363 pData->pVariablesSaved = current_variable_set_list; 364 current_variable_set_list = pData->pVariables; 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; 365 817 366 818 return 0; … … 369 821 static int 370 822 eval_kbuild_endef_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc, 371 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuild Def enmKind)823 const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildType enmType) 372 824 { 373 825 struct kbuild_eval_data *pData; 374 unsigned int cchName; 826 struct kbuild_object *pObj; 827 size_t cchName; 375 828 char *pszName; 376 829 … … 385 838 { 386 839 error(pFileLoc, _("kBuild-endef-%s is missing kBuild-define-%s"), 387 eval_kbuild_ kind_to_string(enmKind), eval_kbuild_kind_to_string(enmKind));840 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(enmType)); 388 841 return 0; 389 842 } … … 392 845 * ... and does it have a matching kind? 393 846 */ 394 if (pData->enmKind != enmKind) 847 pObj = pData->pObj; 848 if (pObj->enmType != enmType) 395 849 error(pFileLoc, _("'kBuild-endef-%s' does not match 'kBuild-define-%s %s'"), 396 eval_kbuild_ kind_to_string(enmKind), eval_kbuild_kind_to_string(pData->enmKind), pData->pszName);850 eval_kbuild_type_to_string(enmType), eval_kbuild_type_to_string(pObj->enmType), pObj->pszName); 397 851 398 852 /* … … 403 857 if (pszName) 404 858 { 405 if (strcmp(pszName, pData->pszName)) 859 if ( cchName != pObj->cchName 860 || strcmp(pszName, pObj->pszName)) 406 861 error(pFileLoc, _("'kBuild-endef-%s %s' does not match 'kBuild-define-%s %s'"), 407 eval_kbuild_ kind_to_string(enmKind), pszName,408 eval_kbuild_ kind_to_string(pData->enmKind), pData->pszName);862 eval_kbuild_type_to_string(enmType), pszName, 863 eval_kbuild_type_to_string(pObj->enmType), pObj->pszName); 409 864 free(pszName); 410 865 } … … 413 868 * Pop a define off the stack. 414 869 */ 415 assert(pData == g_pTopKb Def);416 *ppData = g_pTopKb Def= pData->pStackDown;870 assert(pData == g_pTopKbEvalData); 871 *ppData = g_pTopKbEvalData = pData->pStackDown; 417 872 pData->pStackDown = NULL; 418 873 current_variable_set_list = pData->pVariablesSaved; 419 874 pData->pVariablesSaved = NULL; 875 free(pData); 420 876 421 877 return 0; 422 878 } 423 879 424 int eval_kbuild_define(struct kbuild_eval_data **kdata, const struct floc *flocp, 425 const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring) 426 { 427 assert(memcmp(word, "kBuild-define", sizeof("kBuild-define") - 1) == 0); 428 word += sizeof("kBuild-define") - 1; 429 wlen -= sizeof("kBuild-define") - 1; 430 if ( wlen > 1 431 && word[0] == '-') 432 { 433 if (WORD_IS(word, wlen, "-target")) 434 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Target); 435 if (WORD_IS(word, wlen, "-template")) 436 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Template); 437 if (WORD_IS(word, wlen, "-tool")) 438 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Tool); 439 if (WORD_IS(word, wlen, "-sdk")) 440 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Sdk); 441 if (WORD_IS(word, wlen, "-unit")) 442 return eval_kbuild_define_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Unit); 443 } 444 445 error(flocp, _("Unknown syntax 'kBuild-define%.*s'"), (int)wlen, word); 880 int 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); 446 920 return 0; 447 921 } 448 922 449 int eval_kbuild_endef(struct kbuild_eval_data **kdata, const struct floc *flocp, 450 const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring) 451 { 452 assert(memcmp(word, "kBuild-endef", sizeof("kBuild-endef") - 1) == 0); 453 word += sizeof("kBuild-endef") - 1; 454 wlen -= sizeof("kBuild-endef") - 1; 455 if ( wlen > 1 456 && word[0] == '-') 457 { 458 if (WORD_IS(word, wlen, "-target")) 459 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Target); 460 if (WORD_IS(word, wlen, "-template")) 461 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Template); 462 if (WORD_IS(word, wlen, "-tool")) 463 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Tool); 464 if (WORD_IS(word, wlen, "-sdk")) 465 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Sdk); 466 if (WORD_IS(word, wlen, "-unit")) 467 return eval_kbuild_endef_xxxx(kdata, flocp, line, eos, ignoring, kBuildDef_Unit); 468 } 469 470 error(flocp, _("Unknown syntax 'kBuild-endef%.*s'"), (int)wlen, word); 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 */ 936 int 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 } 471 960 return 0; 472 961 } 473 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 */ 982 static struct kbuild_object * 983 parse_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 */ 1073 struct variable * 1074 lookup_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 474 1131 void print_kbuild_data_base(void) 475 1132 { 476 struct kbuild_ eval_data*pCur;1133 struct kbuild_object *pCur; 477 1134 478 1135 puts(_("\n# kBuild defines")); 479 1136 480 for (pCur = g_pHeadKb Defs; pCur; pCur = pCur->pGlobalNext)1137 for (pCur = g_pHeadKbObjs; pCur; pCur = pCur->pGlobalNext) 481 1138 { 482 1139 printf("\nkBuild-define-%s %s", 483 eval_kbuild_ kind_to_string(pCur->enmKind), pCur->pszName);1140 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName); 484 1141 if (pCur->pszParent) 485 {486 1142 printf(" extending %s", pCur->pszParent); 487 switch (pCur->enmExtendBy)488 {489 case kBuildExtendBy_Overriding: break;490 case kBuildExtendBy_Appending: printf(" by appending"); break;491 case kBuildExtendBy_Prepending: printf(" by prepending"); break;492 default: printf(" by ?!?");493 }494 }495 1143 if (pCur->pszTemplate) 496 1144 printf(" using %s", pCur->pszTemplate); … … 500 1148 501 1149 printf("kBuild-endef-%s %s\n", 502 eval_kbuild_ kind_to_string(pCur->enmKind), pCur->pszName);1150 eval_kbuild_type_to_string(pCur->enmType), pCur->pszName); 503 1151 } 504 1152 /** @todo hash stats. */ -
trunk/src/kmk/kbuild.h
r2549 r2717 39 39 const char *get_default_kbuild_shell(void); 40 40 41 /** @name kBuild objects 42 * @{ */ 41 43 struct kbuild_eval_data; 42 extern struct kbuild_eval_data *g_pTopKbDef; 43 struct variable_set *get_top_kbuild_variable_set(void); 44 char *kbuild_prefix_variable(const char *pszName, unsigned int *pcchName); 44 struct kbuild_object; 45 45 46 int eval_kbuild_define(struct kbuild_eval_data **kdata, const struct floc *flocp, 47 const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring); 48 int eval_kbuild_endef(struct kbuild_eval_data **kdata, const struct floc *flocp, 49 const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring); 46 extern struct kbuild_eval_data *g_pTopKbEvalData; 50 47 51 void print_kbuild_data_base(void); 52 void print_kbuild_define_stats(void); 48 49 /** Special return value indicating variable name isn't an accessor. */ 50 #define KOBJ_NOT_KBUILD_ACCESSOR ( (struct kbuild_object *)~(size_t)0 ) 51 52 /** Special lookup_kbuild_object_variable return value. */ 53 #define VAR_NOT_KBUILD_ACCESSOR ( (struct variable *)~(size_t)0 ) 54 55 struct variable *lookup_kbuild_object_variable_accessor(const char *pchName, size_t cchName); 56 int is_kbuild_object_variable_accessor(const char *pchName, size_t cchName); 57 struct variable *try_define_kbuild_object_variable_via_accessor(const char *pszName, size_t cchName, 58 const char *pszValue, size_t cchValue, int fDuplicateValue, 59 enum variable_origin enmOrigin, int fRecursive, 60 struct floc const *pFileLoc); 61 struct variable *define_kbuild_object_variable_in_top_obj(const char *pszName, size_t cchName, 62 const char *pszValue, size_t cchValue, int fDuplicateValue, 63 enum variable_origin enmOrigin, int fRecursive, 64 struct floc const *pFileLoc); 65 struct variable *kbuild_object_variable_pre_append(const char *pchName, size_t cchName, 66 const char *pchValue, size_t cchValue, int fSimpleValue, 67 enum variable_origin enmOrigin, int fAppend, 68 const struct floc *pFileLoc); 69 int eval_kbuild_read_hook(struct kbuild_eval_data **kdata, const struct floc *flocp, 70 const char *word, size_t wlen, const char *line, const char *eos, int ignoring); 71 void print_kbuild_data_base(void); 72 void print_kbuild_define_stats(void); 73 void init_kbuild_object(void); 74 /** @} */ 53 75 54 76 #endif -
trunk/src/kmk/main.c
r2705 r2717 1584 1584 #endif 1585 1585 initialize_global_hash_tables (); 1586 #ifdef KMK 1587 init_kbuild_object (); 1588 #endif 1586 1589 1587 1590 /* Figure out where we are. */ -
trunk/src/kmk/read.c
r2591 r2717 961 961 #ifdef KMK 962 962 /* Check for the kBuild language extensions. */ 963 if ( wlen >= sizeof("kBuild-define") - 1 964 && strneq (p, "kBuild-define", sizeof("kBuild-define") - 1)) 965 krc = eval_kbuild_define (&kdata, fstart, p, wlen, p2, eol, ignoring); 966 else if ( wlen >= sizeof("kBuild-endef") - 1 967 && strneq (p, "kBuild-endef", sizeof("kBuild-endef") - 1)) 968 krc = eval_kbuild_endef (&kdata, fstart, p, wlen, p2, eol, ignoring); 969 else 970 krc = 42; 971 if (krc != 42) 963 if ( wlen > sizeof("kBuild-") 964 && strneq (p, "kBuild-", sizeof("kBuild-") - 1)) 972 965 { 973 if (krc != 0) 974 error (fstart, _("krc=%d"), krc); 975 continue; 966 krc = eval_kbuild_read_hook (&kdata, fstart, p, wlen, p2, eol, ignoring); 967 if (krc != 42) 968 { 969 if (krc != 0) 970 error (fstart, _("krc=%d"), krc); 971 continue; 972 } 976 973 } 977 978 974 #endif /* KMK */ 979 975 … … 1852 1848 definition[idx - 1] = '\0'; 1853 1849 1850 #ifndef CONFIG_WITH_VALUE_LENGTH 1854 1851 v = do_variable_definition (&defstart, name, definition, origin, flavor, 0); 1852 #else 1853 v = do_variable_definition_2 (&defstart, name, definition, 1854 idx ? idx - 1 : idx, flavor == f_simple, 1855 0 /* free_value */, origin, flavor, 1856 0 /*target_var*/); 1857 #endif 1855 1858 free (definition); 1856 1859 free (var); -
trunk/src/kmk/testcase-kBuild-define.kmk
r2658 r2717 5 5 6 6 # 7 # Copyright (c) 2011-201 2knut st. osmundsen <[email protected]>7 # Copyright (c) 2011-2013 knut st. osmundsen <[email protected]> 8 8 # 9 9 # This file is part of kBuild. … … 24 24 # 25 25 26 DEPTH = ../..26 #DEPTH = ../.. 27 27 #include $(PATH_KBUILD)/header.kmk 28 28 29 if 0 29 30 # object definition syntax: 30 # kobject <type> <name> [extends <object> ] [object specific args...]31 # endkobj [<type> [name]]31 # kobject <type> <name> [extends <object> [by <||>]] [object specific args...] 32 # kendobj [<type> [name]] 32 33 kobject kb-target MyTarget 33 34 .TOOL = GCC 34 35 .SOURCES = file.c 35 endobj 36 kendobj 37 else 38 # Target definition. 39 # kBuild-define-target <name> [extends <target> [by <||>]] [using <template>] 40 # kBuild-endef-target [name] 41 kBuild-define-target MyTarget 42 _TOOL = GCC 43 _SOURCES = file.c 44 kBuild-endef-target 45 endif 36 46 47 if 0 37 48 # accesses an already defined object. 38 49 # syntax: 39 50 # kaccess <type> <name> 40 # endkacc [<type> [name]]51 # kendacc [<type> [name]] 41 52 kaccess kb-target MyTarget 42 53 .SOURCES += file2.c 43 endkacc 54 kendacc 55 else 56 #kBuild-access-target MyTarget 57 #_SOURCES += file2.c 58 #kBuild-endacc-target 59 endif 44 60 45 61 46 62 # Referencing an object variable, the object must exist. 47 63 # syntax: [<type>@<name>].<property> 48 [ kb-target@MyTarget].SOURCES += file3.c49 $(info [ kb-target@MyTarget].SOURCES is $([kb-target@MyTarget].SOURCES))64 [target@MyTarget]_SOURCES += file3.c 65 $(info [target@MyTarget]_SOURCES is $([target@MyTarget]_SOURCES)) 50 66 51 67 52 68 # Test #1 53 k object target BaseTarget with DUMMY as template54 .SOURCES = BaseTargetSource.c55 k endobj56 $(if "$([target@BaseTarget].SOURCES)" == "BaseTargetSource.c",,$(error [target@BaseTarget].SOURCES is '$([target@BaseTarget].SOURCES)' not 'BaseTargetSource.c'))57 $(if "$(BaseTarget_SOURCES)" == "BaseTargetSource.c",,$(error BaseTarget's _SOURCES wasn't set correctly in the global space))69 kBuild-define-target BaseTarget using DUMMY 70 _SOURCES = BaseTargetSource.c 71 kBuild-endef-target BaseTarget 72 $(if-expr "$([target@BaseTarget]_SOURCES)" == "BaseTargetSource.c",,$(error [target@BaseTarget]_SOURCES is '$([target@BaseTarget]_SOURCES)' not 'BaseTargetSource.c')) 73 $(if-expr "$(BaseTarget_SOURCES)" == "BaseTargetSource.c",,$(error BaseTarget's _SOURCES wasn't set correctly in the global space)) 58 74 59 $(if "$([target@BaseTarget].TEMPLATE)" == "DUMMY",,$(error [target@BaseTarget].TEMPLATE is '$([target@BaseTarget].TEMPLATE)' not 'DUMMY'))60 $(if "$(BaseTarget_TEMPLATE)" == "DUMMY",,$(error BaseTarget's _TEMPLATE wasn't set correctly in the global space))75 $(if-expr "$([target@BaseTarget]_TEMPLATE)" == "DUMMY",,$(error [target@BaseTarget]_TEMPLATE is '$([target@BaseTarget]_TEMPLATE)' not 'DUMMY')) 76 $(if-expr "$(BaseTarget_TEMPLATE)" == "DUMMY",,$(error BaseTarget's _TEMPLATE wasn't set correctly in the global space)) 61 77 62 78 # Test #2 63 k objecttarget TargetWithLocals64 local .LOCAL_PROP = no global alias65 k endobj66 $(if "$([target@TargetWithLocals].LOCAL_PROP)" == "no global alias",,$(error [target@TargetWithLocals].LOCAL_PROP is '$([target@TargetWithLocals].LOCAL_PROP)' not 'no global alias'))67 $(if "$(TargetWithLocals_LOCAL_PROP)" == "",,$(error TargetWithLocals_LOCAL_PROP's local property 'LOCAL_PROP' was exposed globally.))79 kBuild-define-target TargetWithLocals 80 local _LOCAL_PROP = no global alias 81 kBuild-endef-target 82 $(if-expr "$([target@TargetWithLocals]_LOCAL_PROP)" == "no global alias",,$(error [target@TargetWithLocals]_LOCAL_PROP is '$([target@TargetWithLocals]_LOCAL_PROP)' not 'no global alias')) 83 $(if-expr "$(TargetWithLocals_LOCAL_PROP)" == "",,$(error TargetWithLocals_LOCAL_PROP's local property 'LOCAL_PROP' was exposed globally.)) 68 84 85 # Test #3 86 kBuild-define-target OutsideMod 87 _SOURCES = file3.c 88 _OTHER = inside-value 89 kBuild-endef-target 90 [target@OutsideMod]_SOURCES += file4.c 91 [target@OutsideMod]_SOURCES <= file2.c 92 [target@OutsideMod]_OTHER = outside-value 93 $(if-expr "$([target@OutsideMod]_SOURCES)" == "file2.c file3.c file4.c",,$(error [target@OutsideMod]_SOURCES is '$([target@OutsideMod]_SOURCES)' not 'file2.c file3.c file4.c')) 94 $(if-expr "OutsideMod_SOURCES" == "file2.c file3.c file4.c",,$(error OutsideMod_SOURCES is '$(OutsideMod_SOURCES)' not 'file2.c file3.c file4.c')) 95 96 $(if-expr "$([target@OutsideMod]_OTHER)" == "outside-value",,$(error [target@OutsideMod]_OTHER is '$([target@OutsideMod]_OTHER)' not 'outside-value')) 97 $(if-expr "$(OutsideMod_OTHER)" == "outside-value",,$(error OutsideMod_OTHER is '$(OutsideMod_OTHER)' not 'outside-value')) 69 98 70 99 all_recursive: 71 #$(ECHO)"kBuild-define-xxxx works fine"100 @kmk_echo "kBuild-define-xxxx works fine" 72 101 -
trunk/src/kmk/variable.c
r2591 r2717 202 202 #endif 203 203 204 205 #ifdef KMK /* Drop the 'static' */ 206 struct variable_set global_variable_set; 207 struct variable_set_list global_setlist 208 #else 204 209 static struct variable_set global_variable_set; 205 210 static struct variable_set_list global_setlist 211 #endif 206 212 = { 0, &global_variable_set, 0 }; 207 213 struct variable_set_list *current_variable_set_list = &global_setlist; … … 249 255 struct variable var_key; 250 256 257 if (env_overrides && origin == o_env) 258 origin = o_env_override; 259 251 260 #ifndef KMK 252 261 if (set == NULL) 253 262 set = &global_variable_set; 254 #else 263 #else /* KMK */ 264 /* Intercept kBuild object variable definitions. */ 265 if (name[0] == '[' && length > 3) 266 { 267 v = try_define_kbuild_object_variable_via_accessor (name, length, 268 value, value_len, duplicate_value, 269 origin, recursive, flocp); 270 if (v != VAR_NOT_KBUILD_ACCESSOR) 271 return v; 272 } 255 273 if (set == NULL) 256 274 { 257 /* underscore prefixed variables are automatically local in 258 kBuild-define-* scopes. They also get a global definition with 259 the current scope prefix. */ 260 if (g_pTopKbDef && length > 0 && name[0] == '_') 261 { 262 char *prefixed_nm; 263 unsigned int prefixed_nm_len; 264 265 set = get_top_kbuild_variable_set(); 266 v = define_variable_in_set(name, length, value, value_len, 267 1 /* duplicate_value */, 268 origin, recursive, set, flocp); 269 270 prefixed_nm_len = length; 271 prefixed_nm = kbuild_prefix_variable(name, &prefixed_nm_len); 272 define_variable_in_set(prefixed_nm, prefixed_nm_len, 273 value, value_len, duplicate_value, 274 origin, recursive, &global_variable_set, 275 flocp); 276 free(prefixed_nm); 277 return v; 278 } 275 if (g_pTopKbEvalData) 276 return define_kbuild_object_variable_in_top_obj (name, length, 277 value, value_len, duplicate_value, 278 origin, recursive, flocp); 279 279 set = &global_variable_set; 280 280 } 281 #endif 281 #endif /* KMK */ 282 282 283 283 #ifndef CONFIG_WITH_STRCACHE2 … … 286 286 var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); 287 287 288 if (env_overrides && origin == o_env)289 origin = o_env_override; 288 /* if (env_overrides && origin == o_env) 289 origin = o_env_override; - bird moved this up */ 290 290 291 291 v = *var_slot; 292 292 #else /* CONFIG_WITH_STRCACHE2 */ 293 var_key.name = name = strcache2_add (&variable_strcache, name, length); 294 var_key.length = length; 293 name = strcache2_add (&variable_strcache, name, length); 295 294 if ( set != &global_variable_set 296 || !(v = strcache2_get_user_val (&variable_strcache, var_key.name))) 297 { 295 || !(v = strcache2_get_user_val (&variable_strcache, name))) 296 { 297 var_key.name = name; 298 var_key.length = length; 298 299 var_slot = (struct variable **) hash_find_slot_strcached (&set->table, &var_key); 299 300 v = *var_slot; … … 470 471 set = &global_variable_set; 471 472 473 #ifndef CONFIG_WITH_STRCACHE2 472 474 var_key.name = (char *) name; 473 475 var_key.length = length; 474 476 var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); 477 #else 478 var_key.name = strcache2_lookup(&variable_strcache, name, length); 479 if (!var_key.name) 480 return; 481 var_key.length = length; 482 var_slot = (struct variable **) hash_find_slot_strcached (&set->table, &var_key); 483 #endif 475 484 476 485 if (env_overrides && origin == o_env) … … 490 499 { 491 500 hash_delete_at (&set->table, var_slot); 501 #ifdef CONFIG_WITH_STRCACHE2 502 if (set == &global_variable_set) 503 strcache2_set_user_val (&variable_strcache, v->name, NULL); 504 #endif 492 505 free_variable_name_and_value (v); 493 506 } … … 735 748 #ifdef CONFIG_WITH_STRCACHE2 736 749 const char *cached_name; 737 750 #endif 751 752 # ifdef KMK 753 /* Check for kBuild-define- local variable accesses and handle these first. */ 754 if (length > 3 && name[0] == '[') 755 { 756 struct variable *v = lookup_kbuild_object_variable_accessor(name, length); 757 if (v != VAR_NOT_KBUILD_ACCESSOR) 758 return v; 759 } 760 # endif 761 762 #ifdef CONFIG_WITH_STRCACHE2 738 763 /* lookup the name in the string case, if it's not there it won't 739 764 be in any of the sets either. */ … … 851 876 #else /* CONFIG_WITH_STRCACHE2 */ 852 877 const char *cached_name; 878 879 # ifdef KMK 880 /* Check for kBuild-define- local variable accesses and handle these first. */ 881 if (length > 3 && name[0] == '[' && set == &global_variable_set) 882 { 883 struct variable *v = lookup_kbuild_object_variable_accessor(name, length); 884 if (v != VAR_NOT_KBUILD_ACCESSOR) 885 return v; 886 } 887 # endif 853 888 854 889 /* lookup the name in the string case, if it's not there it won't … … 1914 1949 } 1915 1950 1916 st atic struct variable *1951 struct variable * 1917 1952 do_variable_definition_append (const struct floc *flocp, struct variable *v, 1918 1953 const char *value, unsigned int value_len, … … 1996 2031 int conditional = 0; 1997 2032 const size_t varname_len = strlen (varname); /* bird */ 2033 1998 2034 #ifdef CONFIG_WITH_VALUE_LENGTH 1999 assert (value_len == ~0U || value_len == strlen (value)); 2035 if (value_len == ~0U) 2036 value_len = strlen (value); 2037 else 2038 assert (value_len == strlen (value)); 2000 2039 #endif 2001 2040 … … 2066 2105 #endif 2067 2106 2068 #ifdef CONFIG_WITH_LOCAL_VARIABLES2069 /* If we have += but we're in a target or local variable context,2070 we want to append only with other variables in the context of2071 this target. */2072 if (target_var || origin == o_local)2073 #else2074 2107 /* If we have += but we're in a target variable context, we want to 2075 2108 append only with other variables in the context of this target. */ 2076 2109 if (target_var) 2077 #endif2078 2110 { 2079 2111 append = 1; … … 2086 2118 append = 0; 2087 2119 } 2120 #ifdef KMK 2121 else if ( g_pTopKbEvalData 2122 || ( varname_len > 3 2123 && varname[0] == '[' 2124 && is_kbuild_object_variable_accessor (varname, varname_len)) ) 2125 { 2126 v = kbuild_object_variable_pre_append (varname, varname_len, 2127 value, value_len, simple_value, 2128 origin, org_flavor == f_append, flocp); 2129 if (free_value) 2130 free (free_value); 2131 return v; 2132 } 2133 #endif 2134 #ifdef CONFIG_WITH_LOCAL_VARIABLES 2135 /* If 'local', restrict it to the current variable context. */ 2136 else if (origin == o_local) 2137 v = lookup_variable_in_set (varname, varname_len, 2138 current_variable_set_list->set); 2139 #endif 2088 2140 else 2089 2141 v = lookup_variable (varname, varname_len); -
trunk/src/kmk/variable.h
r2591 r2717 143 143 144 144 #ifdef KMK 145 extern struct variable_set global_variable_set; 146 extern struct variable_set_list global_setlist; 145 147 extern unsigned int variable_buffer_length; 146 148 # define VARIABLE_BUFFER_ZONE 5 … … 351 353 void append_string_to_variable (struct variable *v, const char *value, 352 354 unsigned int value_len, int append); 355 struct variable * do_variable_definition_append (const struct floc *flocp, struct variable *v, 356 const char *value, unsigned int value_len, 357 int simple_value, enum variable_origin origin, 358 int append); 353 359 354 360 struct variable *define_variable_in_set (const char *name, unsigned int length,
Note:
See TracChangeset
for help on using the changeset viewer.