1 /****************************************************************************** 2 * 3 * Module Name: aslutils -- compiler utilities 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "acdisasm.h" 47 #include "acnamesp.h" 48 #include "amlcode.h" 49 #include <acapps.h> 50 51 #define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("aslutils") 53 54 55 /* Local prototypes */ 56 57 static void 58 UtPadNameWithUnderscores ( 59 char *NameSeg, 60 char *PaddedNameSeg); 61 62 static void 63 UtAttachNameseg ( 64 ACPI_PARSE_OBJECT *Op, 65 char *Name); 66 67 68 /******************************************************************************* 69 * 70 * FUNCTION: UtDisplaySupportedTables 71 * 72 * PARAMETERS: None 73 * 74 * RETURN: None 75 * 76 * DESCRIPTION: Print all supported ACPI table names. 77 * 78 ******************************************************************************/ 79 80 void 81 UtDisplaySupportedTables ( 82 void) 83 { 84 const AH_TABLE *TableData; 85 UINT32 i; 86 87 88 printf ("\nACPI tables supported by iASL version %8.8X:\n" 89 " (Compiler, Disassembler, Template Generator)\n\n", 90 ACPI_CA_VERSION); 91 92 /* All ACPI tables with the common table header */ 93 94 printf ("\n Supported ACPI tables:\n"); 95 for (TableData = AcpiSupportedTables, i = 1; 96 TableData->Signature; TableData++, i++) 97 { 98 printf ("%8u) %s %s\n", i, 99 TableData->Signature, TableData->Description); 100 } 101 } 102 103 104 /******************************************************************************* 105 * 106 * FUNCTION: UtDisplayConstantOpcodes 107 * 108 * PARAMETERS: None 109 * 110 * RETURN: None 111 * 112 * DESCRIPTION: Print AML opcodes that can be used in constant expressions. 113 * 114 ******************************************************************************/ 115 116 void 117 UtDisplayConstantOpcodes ( 118 void) 119 { 120 UINT32 i; 121 122 123 printf ("Constant expression opcode information\n\n"); 124 125 for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++) 126 { 127 if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT) 128 { 129 printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name); 130 } 131 } 132 } 133 134 135 /******************************************************************************* 136 * 137 * FUNCTION: UtLocalCalloc 138 * 139 * PARAMETERS: Size - Bytes to be allocated 140 * 141 * RETURN: Pointer to the allocated memory. Guaranteed to be valid. 142 * 143 * DESCRIPTION: Allocate zero-initialized memory. Aborts the compile on an 144 * allocation failure, on the assumption that nothing more can be 145 * accomplished. 146 * 147 ******************************************************************************/ 148 149 void * 150 UtLocalCalloc ( 151 UINT32 Size) 152 { 153 void *Allocated; 154 155 156 Allocated = ACPI_ALLOCATE_ZEROED (Size); 157 if (!Allocated) 158 { 159 AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, 160 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 161 Gbl_InputByteCount, Gbl_CurrentColumn, 162 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 163 164 CmCleanupAndExit (); 165 exit (1); 166 } 167 168 TotalAllocations++; 169 TotalAllocated += Size; 170 return (Allocated); 171 } 172 173 /******************************************************************************* 174 * 175 * FUNCTION: UtLocalFree 176 * 177 * PARAMETERS: Allocated - Pointer to be released 178 * PARAMETERS: Size - Bytes to be released 179 * 180 * RETURN: None 181 * 182 * DESCRIPTION: Free memory previously allocated 183 * 184 ******************************************************************************/ 185 void 186 UtLocalFree ( 187 void *Allocated, UINT32 Size) 188 { 189 ACPI_FREE (Allocated); 190 TotalAllocations--; 191 TotalAllocated -= Size; 192 } 193 194 /******************************************************************************* 195 * 196 * FUNCTION: UtBeginEvent 197 * 198 * PARAMETERS: Name - Ascii name of this event 199 * 200 * RETURN: Event number (integer index) 201 * 202 * DESCRIPTION: Saves the current time with this event 203 * 204 ******************************************************************************/ 205 206 UINT8 207 UtBeginEvent ( 208 char *Name) 209 { 210 211 if (AslGbl_NextEvent >= ASL_NUM_EVENTS) 212 { 213 AcpiOsPrintf ("Ran out of compiler event structs!\n"); 214 return (AslGbl_NextEvent); 215 } 216 217 /* Init event with current (start) time */ 218 219 AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer (); 220 AslGbl_Events[AslGbl_NextEvent].EventName = Name; 221 AslGbl_Events[AslGbl_NextEvent].Valid = TRUE; 222 223 return (AslGbl_NextEvent++); 224 } 225 226 227 /******************************************************************************* 228 * 229 * FUNCTION: UtEndEvent 230 * 231 * PARAMETERS: Event - Event number (integer index) 232 * 233 * RETURN: None 234 * 235 * DESCRIPTION: Saves the current time (end time) with this event 236 * 237 ******************************************************************************/ 238 239 void 240 UtEndEvent ( 241 UINT8 Event) 242 { 243 244 if (Event >= ASL_NUM_EVENTS) 245 { 246 return; 247 } 248 249 /* Insert end time for event */ 250 251 AslGbl_Events[Event].EndTime = AcpiOsGetTimer (); 252 } 253 254 255 /******************************************************************************* 256 * 257 * FUNCTION: UtConvertByteToHex 258 * 259 * PARAMETERS: RawByte - Binary data 260 * Buffer - Pointer to where the hex bytes will be 261 * stored 262 * 263 * RETURN: Ascii hex byte is stored in Buffer. 264 * 265 * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed 266 * with "0x" 267 * 268 ******************************************************************************/ 269 270 void 271 UtConvertByteToHex ( 272 UINT8 RawByte, 273 UINT8 *Buffer) 274 { 275 276 Buffer[0] = '0'; 277 Buffer[1] = 'x'; 278 279 Buffer[2] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 4); 280 Buffer[3] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 0); 281 } 282 283 284 /******************************************************************************* 285 * 286 * FUNCTION: UtConvertByteToAsmHex 287 * 288 * PARAMETERS: RawByte - Binary data 289 * Buffer - Pointer to where the hex bytes will be 290 * stored 291 * 292 * RETURN: Ascii hex byte is stored in Buffer. 293 * 294 * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed 295 * with '0', and a trailing 'h' is added. 296 * 297 ******************************************************************************/ 298 299 void 300 UtConvertByteToAsmHex ( 301 UINT8 RawByte, 302 UINT8 *Buffer) 303 { 304 305 Buffer[0] = '0'; 306 Buffer[1] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 4); 307 Buffer[2] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 0); 308 Buffer[3] = 'h'; 309 } 310 311 312 /******************************************************************************* 313 * 314 * FUNCTION: DbgPrint 315 * 316 * PARAMETERS: Type - Type of output 317 * Fmt - Printf format string 318 * ... - variable printf list 319 * 320 * RETURN: None 321 * 322 * DESCRIPTION: Conditional print statement. Prints to stderr only if the 323 * debug flag is set. 324 * 325 ******************************************************************************/ 326 327 void 328 DbgPrint ( 329 UINT32 Type, 330 char *Fmt, 331 ...) 332 { 333 va_list Args; 334 335 336 if (!Gbl_DebugFlag) 337 { 338 return; 339 } 340 341 if ((Type == ASL_PARSE_OUTPUT) && 342 (!(AslCompilerdebug))) 343 { 344 return; 345 } 346 347 va_start (Args, Fmt); 348 (void) vfprintf (stderr, Fmt, Args); 349 va_end (Args); 350 return; 351 } 352 353 354 /******************************************************************************* 355 * 356 * FUNCTION: UtPrintFormattedName 357 * 358 * PARAMETERS: ParseOpcode - Parser keyword ID 359 * Level - Indentation level 360 * 361 * RETURN: None 362 * 363 * DESCRIPTION: Print the ascii name of the parse opcode. 364 * 365 ******************************************************************************/ 366 367 #define TEXT_OFFSET 10 368 369 void 370 UtPrintFormattedName ( 371 UINT16 ParseOpcode, 372 UINT32 Level) 373 { 374 375 if (Level) 376 { 377 DbgPrint (ASL_TREE_OUTPUT, 378 "%*s", (3 * Level), " "); 379 } 380 DbgPrint (ASL_TREE_OUTPUT, 381 " %-20.20s", UtGetOpName (ParseOpcode)); 382 383 if (Level < TEXT_OFFSET) 384 { 385 DbgPrint (ASL_TREE_OUTPUT, 386 "%*s", (TEXT_OFFSET - Level) * 3, " "); 387 } 388 } 389 390 391 /******************************************************************************* 392 * 393 * FUNCTION: UtSetParseOpName 394 * 395 * PARAMETERS: Op - Parse op to be named. 396 * 397 * RETURN: None 398 * 399 * DESCRIPTION: Insert the ascii name of the parse opcode 400 * 401 ******************************************************************************/ 402 403 void 404 UtSetParseOpName ( 405 ACPI_PARSE_OBJECT *Op) 406 { 407 408 strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode), 409 ACPI_MAX_PARSEOP_NAME); 410 } 411 412 413 /******************************************************************************* 414 * 415 * FUNCTION: UtDisplaySummary 416 * 417 * PARAMETERS: FileID - ID of outpout file 418 * 419 * RETURN: None 420 * 421 * DESCRIPTION: Display compilation statistics 422 * 423 ******************************************************************************/ 424 425 void 426 UtDisplaySummary ( 427 UINT32 FileId) 428 { 429 UINT32 i; 430 431 432 if (FileId != ASL_FILE_STDOUT) 433 { 434 /* Compiler name and version number */ 435 436 FlPrintFile (FileId, "%s version %X%s [%s]\n\n", 437 ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH, ACPI_DATE); 438 } 439 440 /* Summary of main input and output files */ 441 442 if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) 443 { 444 FlPrintFile (FileId, 445 "%-14s %s - %u lines, %u bytes, %u fields\n", 446 "Table Input:", 447 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 448 Gbl_InputByteCount, Gbl_InputFieldCount); 449 450 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 451 { 452 FlPrintFile (FileId, 453 "%-14s %s - %u bytes\n", 454 "Binary Output:", 455 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength); 456 } 457 } 458 else 459 { 460 FlPrintFile (FileId, 461 "%-14s %s - %u lines, %u bytes, %u keywords\n", 462 "ASL Input:", 463 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 464 Gbl_OriginalInputFileSize, TotalKeywords); 465 466 /* AML summary */ 467 468 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 469 { 470 if (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle) 471 { 472 FlPrintFile (FileId, 473 "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n", 474 "AML Output:", 475 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength, 476 TotalNamedObjects, TotalExecutableOpcodes); 477 } 478 } 479 } 480 481 /* Display summary of any optional files */ 482 483 for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++) 484 { 485 if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle) 486 { 487 continue; 488 } 489 490 /* .SRC is a temp file unless specifically requested */ 491 492 if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag)) 493 { 494 continue; 495 } 496 497 /* .PRE is the preprocessor intermediate file */ 498 499 if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_KeepPreprocessorTempFile)) 500 { 501 continue; 502 } 503 504 FlPrintFile (FileId, "%14s %s - %u bytes\n", 505 Gbl_Files[i].ShortDescription, 506 Gbl_Files[i].Filename, FlGetFileSize (i)); 507 } 508 509 /* Error summary */ 510 511 FlPrintFile (FileId, 512 "\nCompilation complete. %u Errors, %u Warnings, %u Remarks", 513 Gbl_ExceptionCount[ASL_ERROR], 514 Gbl_ExceptionCount[ASL_WARNING] + 515 Gbl_ExceptionCount[ASL_WARNING2] + 516 Gbl_ExceptionCount[ASL_WARNING3], 517 Gbl_ExceptionCount[ASL_REMARK]); 518 519 if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA) 520 { 521 FlPrintFile (FileId, ", %u Optimizations", 522 Gbl_ExceptionCount[ASL_OPTIMIZATION]); 523 524 if (TotalFolds) 525 { 526 FlPrintFile (FileId, ", %u Constants Folded", TotalFolds); 527 } 528 } 529 530 FlPrintFile (FileId, "\n"); 531 } 532 533 534 /******************************************************************************* 535 * 536 * FUNCTION: UtCheckIntegerRange 537 * 538 * PARAMETERS: Op - Integer parse node 539 * LowValue - Smallest allowed value 540 * HighValue - Largest allowed value 541 * 542 * RETURN: Op if OK, otherwise NULL 543 * 544 * DESCRIPTION: Check integer for an allowable range 545 * 546 ******************************************************************************/ 547 548 ACPI_PARSE_OBJECT * 549 UtCheckIntegerRange ( 550 ACPI_PARSE_OBJECT *Op, 551 UINT32 LowValue, 552 UINT32 HighValue) 553 { 554 555 if (!Op) 556 { 557 return (NULL); 558 } 559 560 if ((Op->Asl.Value.Integer < LowValue) || 561 (Op->Asl.Value.Integer > HighValue)) 562 { 563 snprintf (MsgBuffer, sizeof(MsgBuffer), "0x%X, allowable: 0x%X-0x%X", 564 (UINT32) Op->Asl.Value.Integer, LowValue, HighValue); 565 566 AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer); 567 return (NULL); 568 } 569 570 return (Op); 571 } 572 573 574 /******************************************************************************* 575 * 576 * FUNCTION: UtStringCacheCalloc 577 * 578 * PARAMETERS: Length - Size of buffer requested 579 * 580 * RETURN: Pointer to the buffer. Aborts on allocation failure 581 * 582 * DESCRIPTION: Allocate a string buffer. Bypass the local 583 * dynamic memory manager for performance reasons (This has a 584 * major impact on the speed of the compiler.) 585 * 586 ******************************************************************************/ 587 588 char * 589 UtStringCacheCalloc ( 590 UINT32 Length) 591 { 592 char *Buffer; 593 ASL_CACHE_INFO *Cache; 594 UINT32 CacheSize = ASL_STRING_CACHE_SIZE; 595 596 597 if (Length > CacheSize) 598 { 599 CacheSize = Length; 600 601 if (Gbl_StringCacheList) 602 { 603 Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize); 604 605 /* Link new cache buffer just following head of list */ 606 607 Cache->Next = Gbl_StringCacheList->Next; 608 Gbl_StringCacheList->Next = Cache; 609 610 /* Leave cache management pointers alone as they pertain to head */ 611 612 Gbl_StringCount++; 613 Gbl_StringSize += Length; 614 615 return (Cache->Buffer); 616 } 617 } 618 619 if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast) 620 { 621 /* Allocate a new buffer */ 622 623 Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize); 624 625 /* Link new cache buffer to head of list */ 626 627 Cache->Next = Gbl_StringCacheList; 628 Gbl_StringCacheList = Cache; 629 630 /* Setup cache management pointers */ 631 632 Gbl_StringCacheNext = Cache->Buffer; 633 Gbl_StringCacheLast = Gbl_StringCacheNext + CacheSize; 634 } 635 636 Gbl_StringCount++; 637 Gbl_StringSize += Length; 638 639 Buffer = Gbl_StringCacheNext; 640 Gbl_StringCacheNext += Length; 641 return (Buffer); 642 } 643 644 645 /****************************************************************************** 646 * 647 * FUNCTION: UtExpandLineBuffers 648 * 649 * PARAMETERS: None. Updates global line buffer pointers. 650 * 651 * RETURN: None. Reallocates the global line buffers 652 * 653 * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates 654 * all global line buffers and updates Gbl_LineBufferSize. NOTE: 655 * Also used for the initial allocation of the buffers, when 656 * all of the buffer pointers are NULL. Initial allocations are 657 * of size ASL_DEFAULT_LINE_BUFFER_SIZE 658 * 659 *****************************************************************************/ 660 661 void 662 UtExpandLineBuffers ( 663 void) 664 { 665 UINT32 NewSize; 666 667 668 /* Attempt to double the size of all line buffers */ 669 670 NewSize = Gbl_LineBufferSize * 2; 671 if (Gbl_CurrentLineBuffer) 672 { 673 DbgPrint (ASL_DEBUG_OUTPUT, 674 "Increasing line buffer size from %u to %u\n", 675 Gbl_LineBufferSize, NewSize); 676 } 677 678 Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize); 679 Gbl_LineBufPtr = Gbl_CurrentLineBuffer; 680 if (!Gbl_CurrentLineBuffer) 681 { 682 goto ErrorExit; 683 } 684 685 Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize); 686 if (!Gbl_MainTokenBuffer) 687 { 688 goto ErrorExit; 689 } 690 691 Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize); 692 if (!Gbl_MacroTokenBuffer) 693 { 694 goto ErrorExit; 695 } 696 697 Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize); 698 if (!Gbl_ExpressionTokenBuffer) 699 { 700 goto ErrorExit; 701 } 702 703 Gbl_LineBufferSize = NewSize; 704 return; 705 706 707 /* On error above, simply issue error messages and abort, cannot continue */ 708 709 ErrorExit: 710 printf ("Could not increase line buffer size from %u to %u\n", 711 Gbl_LineBufferSize, Gbl_LineBufferSize * 2); 712 713 AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION, 714 NULL, NULL); 715 AslAbort (); 716 } 717 718 719 /****************************************************************************** 720 * 721 * FUNCTION: UtFreeLineBuffers 722 * 723 * PARAMETERS: None 724 * 725 * RETURN: None 726 * 727 * DESCRIPTION: Free all line buffers 728 * 729 *****************************************************************************/ 730 731 void 732 UtFreeLineBuffers ( 733 void) 734 { 735 736 free (Gbl_CurrentLineBuffer); 737 free (Gbl_MainTokenBuffer); 738 free (Gbl_MacroTokenBuffer); 739 free (Gbl_ExpressionTokenBuffer); 740 } 741 742 743 /******************************************************************************* 744 * 745 * FUNCTION: UtInternalizeName 746 * 747 * PARAMETERS: ExternalName - Name to convert 748 * ConvertedName - Where the converted name is returned 749 * 750 * RETURN: Status 751 * 752 * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name 753 * 754 ******************************************************************************/ 755 756 ACPI_STATUS 757 UtInternalizeName ( 758 char *ExternalName, 759 char **ConvertedName) 760 { 761 ACPI_NAMESTRING_INFO Info; 762 ACPI_STATUS Status; 763 764 765 if (!ExternalName) 766 { 767 return (AE_OK); 768 } 769 770 /* Get the length of the new internal name */ 771 772 Info.ExternalName = ExternalName; 773 AcpiNsGetInternalNameLength (&Info); 774 775 /* We need a segment to store the internal name */ 776 777 Info.InternalName = UtStringCacheCalloc (Info.Length); 778 if (!Info.InternalName) 779 { 780 return (AE_NO_MEMORY); 781 } 782 783 /* Build the name */ 784 785 Status = AcpiNsBuildInternalName (&Info); 786 if (ACPI_FAILURE (Status)) 787 { 788 return (Status); 789 } 790 791 *ConvertedName = Info.InternalName; 792 return (AE_OK); 793 } 794 795 796 /******************************************************************************* 797 * 798 * FUNCTION: UtPadNameWithUnderscores 799 * 800 * PARAMETERS: NameSeg - Input nameseg 801 * PaddedNameSeg - Output padded nameseg 802 * 803 * RETURN: Padded nameseg. 804 * 805 * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full 806 * ACPI_NAME. 807 * 808 ******************************************************************************/ 809 810 static void 811 UtPadNameWithUnderscores ( 812 char *NameSeg, 813 char *PaddedNameSeg) 814 { 815 UINT32 i; 816 817 818 for (i = 0; (i < ACPI_NAME_SIZE); i++) 819 { 820 if (*NameSeg) 821 { 822 *PaddedNameSeg = *NameSeg; 823 NameSeg++; 824 } 825 else 826 { 827 *PaddedNameSeg = '_'; 828 } 829 PaddedNameSeg++; 830 } 831 } 832 833 834 /******************************************************************************* 835 * 836 * FUNCTION: UtAttachNameseg 837 * 838 * PARAMETERS: Op - Parent parse node 839 * Name - Full ExternalName 840 * 841 * RETURN: None; Sets the NameSeg field in parent node 842 * 843 * DESCRIPTION: Extract the last nameseg of the ExternalName and store it 844 * in the NameSeg field of the Op. 845 * 846 ******************************************************************************/ 847 848 static void 849 UtAttachNameseg ( 850 ACPI_PARSE_OBJECT *Op, 851 char *Name) 852 { 853 char *NameSeg; 854 char PaddedNameSeg[4]; 855 856 857 if (!Name) 858 { 859 return; 860 } 861 862 /* Look for the last dot in the namepath */ 863 864 NameSeg = strrchr (Name, '.'); 865 if (NameSeg) 866 { 867 /* Found last dot, we have also found the final nameseg */ 868 869 NameSeg++; 870 UtPadNameWithUnderscores (NameSeg, PaddedNameSeg); 871 } 872 else 873 { 874 /* No dots in the namepath, there is only a single nameseg. */ 875 /* Handle prefixes */ 876 877 while (ACPI_IS_ROOT_PREFIX (*Name) || 878 ACPI_IS_PARENT_PREFIX (*Name)) 879 { 880 Name++; 881 } 882 883 /* Remaining string should be one single nameseg */ 884 885 UtPadNameWithUnderscores (Name, PaddedNameSeg); 886 } 887 888 ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg); 889 } 890 891 892 /******************************************************************************* 893 * 894 * FUNCTION: UtAttachNamepathToOwner 895 * 896 * PARAMETERS: Op - Parent parse node 897 * NameOp - Node that contains the name 898 * 899 * RETURN: Sets the ExternalName and Namepath in the parent node 900 * 901 * DESCRIPTION: Store the name in two forms in the parent node: The original 902 * (external) name, and the internalized name that is used within 903 * the ACPI namespace manager. 904 * 905 ******************************************************************************/ 906 907 void 908 UtAttachNamepathToOwner ( 909 ACPI_PARSE_OBJECT *Op, 910 ACPI_PARSE_OBJECT *NameOp) 911 { 912 ACPI_STATUS Status; 913 914 915 /* Full external path */ 916 917 Op->Asl.ExternalName = NameOp->Asl.Value.String; 918 919 /* Save the NameOp for possible error reporting later */ 920 921 Op->Asl.ParentMethod = (void *) NameOp; 922 923 /* Last nameseg of the path */ 924 925 UtAttachNameseg (Op, Op->Asl.ExternalName); 926 927 /* Create internalized path */ 928 929 Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath); 930 if (ACPI_FAILURE (Status)) 931 { 932 /* TBD: abort on no memory */ 933 } 934 } 935 936 937 /******************************************************************************* 938 * 939 * FUNCTION: UtDoConstant 940 * 941 * PARAMETERS: String - Hex, Octal, or Decimal string 942 * 943 * RETURN: Converted Integer 944 * 945 * DESCRIPTION: Convert a string to an integer, with error checking. 946 * 947 ******************************************************************************/ 948 949 UINT64 950 UtDoConstant ( 951 char *String) 952 { 953 ACPI_STATUS Status; 954 UINT64 Converted; 955 char ErrBuf[64]; 956 957 958 Status = stroul64 (String, 0, &Converted); 959 if (ACPI_FAILURE (Status)) 960 { 961 snprintf (ErrBuf, sizeof(ErrBuf), "%s %s\n", "Conversion error:", 962 AcpiFormatException (Status)); 963 AslCompilererror (ErrBuf); 964 } 965 966 return (Converted); 967 } 968 969 970 /* TBD: use version in ACPICA main code base? */ 971 972 /******************************************************************************* 973 * 974 * FUNCTION: stroul64 975 * 976 * PARAMETERS: String - Null terminated string 977 * Terminater - Where a pointer to the terminating byte 978 * is returned 979 * Base - Radix of the string 980 * 981 * RETURN: Converted value 982 * 983 * DESCRIPTION: Convert a string into an unsigned value. 984 * 985 ******************************************************************************/ 986 987 ACPI_STATUS 988 stroul64 ( 989 char *String, 990 UINT32 Base, 991 UINT64 *RetInteger) 992 { 993 UINT32 Index; 994 UINT32 Sign; 995 UINT64 ReturnValue = 0; 996 ACPI_STATUS Status = AE_OK; 997 998 999 *RetInteger = 0; 1000 1001 switch (Base) 1002 { 1003 case 0: 1004 case 8: 1005 case 10: 1006 case 16: 1007 1008 break; 1009 1010 default: 1011 /* 1012 * The specified Base parameter is not in the domain of 1013 * this function: 1014 */ 1015 return (AE_BAD_PARAMETER); 1016 } 1017 1018 /* Skip over any white space in the buffer: */ 1019 1020 while (isspace ((int) *String) || *String == '\t') 1021 { 1022 ++String; 1023 } 1024 1025 /* 1026 * The buffer may contain an optional plus or minus sign. 1027 * If it does, then skip over it but remember what is was: 1028 */ 1029 if (*String == '-') 1030 { 1031 Sign = ACPI_SIGN_NEGATIVE; 1032 ++String; 1033 } 1034 else if (*String == '+') 1035 { 1036 ++String; 1037 Sign = ACPI_SIGN_POSITIVE; 1038 } 1039 else 1040 { 1041 Sign = ACPI_SIGN_POSITIVE; 1042 } 1043 1044 /* 1045 * If the input parameter Base is zero, then we need to 1046 * determine if it is octal, decimal, or hexadecimal: 1047 */ 1048 if (Base == 0) 1049 { 1050 if (*String == '0') 1051 { 1052 if (tolower ((int) *(++String)) == 'x') 1053 { 1054 Base = 16; 1055 ++String; 1056 } 1057 else 1058 { 1059 Base = 8; 1060 } 1061 } 1062 else 1063 { 1064 Base = 10; 1065 } 1066 } 1067 1068 /* 1069 * For octal and hexadecimal bases, skip over the leading 1070 * 0 or 0x, if they are present. 1071 */ 1072 if (Base == 8 && *String == '0') 1073 { 1074 String++; 1075 } 1076 1077 if (Base == 16 && 1078 *String == '0' && 1079 tolower ((int) *(++String)) == 'x') 1080 { 1081 String++; 1082 } 1083 1084 /* Main loop: convert the string to an unsigned long */ 1085 1086 while (*String) 1087 { 1088 if (isdigit ((int) *String)) 1089 { 1090 Index = ((UINT8) *String) - '0'; 1091 } 1092 else 1093 { 1094 Index = (UINT8) toupper ((int) *String); 1095 if (isupper ((int) Index)) 1096 { 1097 Index = Index - 'A' + 10; 1098 } 1099 else 1100 { 1101 goto ErrorExit; 1102 } 1103 } 1104 1105 if (Index >= Base) 1106 { 1107 goto ErrorExit; 1108 } 1109 1110 /* Check to see if value is out of range: */ 1111 1112 if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) / 1113 (UINT64) Base)) 1114 { 1115 goto ErrorExit; 1116 } 1117 else 1118 { 1119 ReturnValue *= Base; 1120 ReturnValue += Index; 1121 } 1122 1123 ++String; 1124 } 1125 1126 1127 /* If a minus sign was present, then "the conversion is negated": */ 1128 1129 if (Sign == ACPI_SIGN_NEGATIVE) 1130 { 1131 ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; 1132 } 1133 1134 *RetInteger = ReturnValue; 1135 return (Status); 1136 1137 1138 ErrorExit: 1139 switch (Base) 1140 { 1141 case 8: 1142 1143 Status = AE_BAD_OCTAL_CONSTANT; 1144 break; 1145 1146 case 10: 1147 1148 Status = AE_BAD_DECIMAL_CONSTANT; 1149 break; 1150 1151 case 16: 1152 1153 Status = AE_BAD_HEX_CONSTANT; 1154 break; 1155 1156 default: 1157 1158 /* Base validated above */ 1159 1160 break; 1161 } 1162 1163 return (Status); 1164 } 1165