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