asllisting.c revision 245582
1/****************************************************************************** 2 * 3 * Module Name: asllisting - Listing file generation 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2013, 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 45#include <contrib/dev/acpica/compiler/aslcompiler.h> 46#include "aslcompiler.y.h" 47#include <contrib/dev/acpica/include/amlcode.h> 48#include <contrib/dev/acpica/include/acparser.h> 49#include <contrib/dev/acpica/include/acnamesp.h> 50 51#define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("aslisting") 53 54/* Local prototypes */ 55 56static void 57LsDumpAscii ( 58 UINT32 FileId, 59 UINT32 Count, 60 UINT8 *Buffer); 61 62static ACPI_STATUS 63LsAmlListingWalk ( 64 ACPI_PARSE_OBJECT *Op, 65 UINT32 Level, 66 void *Context); 67 68static void 69LsGenerateListing ( 70 UINT32 FileId); 71 72static void 73LsPushNode ( 74 char *Filename); 75 76static ASL_LISTING_NODE * 77LsPopNode ( 78 void); 79 80static void 81LsCheckException ( 82 UINT32 LineNumber, 83 UINT32 FileId); 84 85static void 86LsFlushListingBuffer ( 87 UINT32 FileId); 88 89static void 90LsWriteListingHexBytes ( 91 UINT8 *Buffer, 92 UINT32 Length, 93 UINT32 FileId); 94 95static UINT32 96LsWriteOneSourceLine ( 97 UINT32 FileId); 98 99static void 100LsFinishSourceListing ( 101 UINT32 FileId); 102 103static void 104LsWriteSourceLines ( 105 UINT32 ToLineNumber, 106 UINT32 ToLogicalLineNumber, 107 UINT32 FileId); 108 109static void 110LsWriteNodeToListing ( 111 ACPI_PARSE_OBJECT *Op, 112 UINT32 FileId); 113 114static ACPI_STATUS 115LsTreeWriteWalk ( 116 ACPI_PARSE_OBJECT *Op, 117 UINT32 Level, 118 void *Context); 119 120#define ASL_LISTING_LINE_PREFIX ": " 121 122 123/******************************************************************************* 124 * 125 * FUNCTION: LsDoListings 126 * 127 * PARAMETERS: None 128 * 129 * RETURN: None 130 * 131 * DESCRIPTION: Generate all requested listing files. 132 * 133 ******************************************************************************/ 134 135void 136LsDoListings ( 137 void) 138{ 139 140 if (Gbl_C_OutputFlag) 141 { 142 LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT); 143 } 144 145 if (Gbl_ListingFlag) 146 { 147 LsGenerateListing (ASL_FILE_LISTING_OUTPUT); 148 } 149 150 if (Gbl_AsmOutputFlag) 151 { 152 LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT); 153 } 154 155 if (Gbl_C_IncludeOutputFlag) 156 { 157 LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT); 158 } 159 160 if (Gbl_AsmIncludeOutputFlag) 161 { 162 LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT); 163 } 164} 165 166 167/******************************************************************************* 168 * 169 * FUNCTION: LsTreeWriteWalk 170 * 171 * PARAMETERS: ASL_WALK_CALLBACK 172 * 173 * 174 * RETURN: None 175 * 176 * DESCRIPTION: Dump entire parse tree, for compiler debug only 177 * 178 ******************************************************************************/ 179 180static ACPI_STATUS 181LsTreeWriteWalk ( 182 ACPI_PARSE_OBJECT *Op, 183 UINT32 Level, 184 void *Context) 185{ 186 187 /* Debug output */ 188 189 DbgPrint (ASL_TREE_OUTPUT, 190 "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level); 191 UtPrintFormattedName (Op->Asl.ParseOpcode, Level); 192 193 194 DbgPrint (ASL_TREE_OUTPUT, "\n"); 195 return (AE_OK); 196} 197 198 199void 200LsDumpParseTree ( 201 void) 202{ 203 204 if (!Gbl_DebugFlag) 205 { 206 return; 207 } 208 209 DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); 210 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, 211 LsTreeWriteWalk, NULL, NULL); 212} 213 214 215/******************************************************************************* 216 * 217 * FUNCTION: LsDumpAscii 218 * 219 * PARAMETERS: FileId - ID of current listing file 220 * Count - Number of bytes to convert 221 * Buffer - Buffer of bytes to convert 222 * 223 * RETURN: None 224 * 225 * DESCRIPTION: Convert hex bytes to ascii 226 * 227 ******************************************************************************/ 228 229static void 230LsDumpAscii ( 231 UINT32 FileId, 232 UINT32 Count, 233 UINT8 *Buffer) 234{ 235 UINT8 BufChar; 236 UINT32 i; 237 238 239 FlPrintFile (FileId, " \""); 240 for (i = 0; i < Count; i++) 241 { 242 BufChar = Buffer[i]; 243 if (isprint (BufChar)) 244 { 245 FlPrintFile (FileId, "%c", BufChar); 246 } 247 else 248 { 249 /* Not a printable character, just put out a dot */ 250 251 FlPrintFile (FileId, "."); 252 } 253 } 254 FlPrintFile (FileId, "\""); 255} 256 257 258/******************************************************************************* 259 * 260 * FUNCTION: LsDumpAsciiInComment 261 * 262 * PARAMETERS: FileId - ID of current listing file 263 * Count - Number of bytes to convert 264 * Buffer - Buffer of bytes to convert 265 * 266 * RETURN: None 267 * 268 * DESCRIPTION: Convert hex bytes to ascii 269 * 270 ******************************************************************************/ 271 272void 273LsDumpAsciiInComment ( 274 UINT32 FileId, 275 UINT32 Count, 276 UINT8 *Buffer) 277{ 278 UINT8 BufChar = 0; 279 UINT8 LastChar; 280 UINT32 i; 281 282 283 FlPrintFile (FileId, " \""); 284 for (i = 0; i < Count; i++) 285 { 286 LastChar = BufChar; 287 BufChar = Buffer[i]; 288 289 if (isprint (BufChar)) 290 { 291 /* Handle embedded C comment sequences */ 292 293 if (((LastChar == '*') && (BufChar == '/')) || 294 ((LastChar == '/') && (BufChar == '*'))) 295 { 296 /* Insert a space to break the sequence */ 297 298 FlPrintFile (FileId, ".", BufChar); 299 } 300 301 FlPrintFile (FileId, "%c", BufChar); 302 } 303 else 304 { 305 /* Not a printable character, just put out a dot */ 306 307 FlPrintFile (FileId, "."); 308 } 309 } 310 FlPrintFile (FileId, "\""); 311} 312 313 314/******************************************************************************* 315 * 316 * FUNCTION: LsAmlListingWalk 317 * 318 * PARAMETERS: ASL_WALK_CALLBACK 319 * 320 * RETURN: Status 321 * 322 * DESCRIPTION: Process one node during a listing file generation. 323 * 324 ******************************************************************************/ 325 326static ACPI_STATUS 327LsAmlListingWalk ( 328 ACPI_PARSE_OBJECT *Op, 329 UINT32 Level, 330 void *Context) 331{ 332 UINT8 FileByte; 333 UINT32 i; 334 UINT32 FileId = (UINT32) ACPI_TO_INTEGER (Context); 335 336 337 LsWriteNodeToListing (Op, FileId); 338 339 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA) 340 { 341 /* Buffer is a resource template, don't dump the data all at once */ 342 343 return (AE_OK); 344 } 345 346 /* Write the hex bytes to the listing file(s) (if requested) */ 347 348 for (i = 0; i < Op->Asl.FinalAmlLength; i++) 349 { 350 if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1))) 351 { 352 FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ); 353 AslAbort (); 354 } 355 LsWriteListingHexBytes (&FileByte, 1, FileId); 356 } 357 358 return (AE_OK); 359} 360 361 362/******************************************************************************* 363 * 364 * FUNCTION: LsGenerateListing 365 * 366 * PARAMETERS: FileId - ID of listing file 367 * 368 * RETURN: None 369 * 370 * DESCRIPTION: Generate a listing file. This can be one of the several types 371 * of "listings" supported. 372 * 373 ******************************************************************************/ 374 375static void 376LsGenerateListing ( 377 UINT32 FileId) 378{ 379 380 /* Start at the beginning of both the source and AML files */ 381 382 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); 383 FlSeekFile (ASL_FILE_AML_OUTPUT, 0); 384 Gbl_SourceLine = 0; 385 Gbl_CurrentHexColumn = 0; 386 LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename); 387 388 /* Process all parse nodes */ 389 390 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk, 391 NULL, (void *) ACPI_TO_POINTER (FileId)); 392 393 /* Final processing */ 394 395 LsFinishSourceListing (FileId); 396} 397 398 399/******************************************************************************* 400 * 401 * FUNCTION: LsPushNode 402 * 403 * PARAMETERS: Filename - Pointer to the include filename 404 * 405 * RETURN: None 406 * 407 * DESCRIPTION: Push a listing node on the listing/include file stack. This 408 * stack enables tracking of include files (infinitely nested) 409 * and resumption of the listing of the parent file when the 410 * include file is finished. 411 * 412 ******************************************************************************/ 413 414static void 415LsPushNode ( 416 char *Filename) 417{ 418 ASL_LISTING_NODE *Lnode; 419 420 421 /* Create a new node */ 422 423 Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE)); 424 425 /* Initialize */ 426 427 Lnode->Filename = Filename; 428 Lnode->LineNumber = 0; 429 430 /* Link (push) */ 431 432 Lnode->Next = Gbl_ListingNode; 433 Gbl_ListingNode = Lnode; 434} 435 436 437/******************************************************************************* 438 * 439 * FUNCTION: LsPopNode 440 * 441 * PARAMETERS: None 442 * 443 * RETURN: List head after current head is popped off 444 * 445 * DESCRIPTION: Pop the current head of the list, free it, and return the 446 * next node on the stack (the new current node). 447 * 448 ******************************************************************************/ 449 450static ASL_LISTING_NODE * 451LsPopNode ( 452 void) 453{ 454 ASL_LISTING_NODE *Lnode; 455 456 457 /* Just grab the node at the head of the list */ 458 459 Lnode = Gbl_ListingNode; 460 if ((!Lnode) || 461 (!Lnode->Next)) 462 { 463 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL, 464 "Could not pop empty listing stack"); 465 return (Gbl_ListingNode); 466 } 467 468 Gbl_ListingNode = Lnode->Next; 469 ACPI_FREE (Lnode); 470 471 /* New "Current" node is the new head */ 472 473 return (Gbl_ListingNode); 474} 475 476 477/******************************************************************************* 478 * 479 * FUNCTION: LsCheckException 480 * 481 * PARAMETERS: LineNumber - Current logical (cumulative) line # 482 * FileId - ID of output listing file 483 * 484 * RETURN: None 485 * 486 * DESCRIPTION: Check if there is an exception for this line, and if there is, 487 * put it in the listing immediately. Handles multiple errors 488 * per line. Gbl_NextError points to the next error in the 489 * sorted (by line #) list of compile errors/warnings. 490 * 491 ******************************************************************************/ 492 493static void 494LsCheckException ( 495 UINT32 LineNumber, 496 UINT32 FileId) 497{ 498 499 if ((!Gbl_NextError) || 500 (LineNumber < Gbl_NextError->LogicalLineNumber )) 501 { 502 return; 503 } 504 505 /* Handle multiple errors per line */ 506 507 if (FileId == ASL_FILE_LISTING_OUTPUT) 508 { 509 while (Gbl_NextError && 510 (LineNumber >= Gbl_NextError->LogicalLineNumber)) 511 { 512 AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n"); 513 514 Gbl_NextError = Gbl_NextError->Next; 515 } 516 517 FlPrintFile (FileId, "\n"); 518 } 519} 520 521 522/******************************************************************************* 523 * 524 * FUNCTION: LsFlushListingBuffer 525 * 526 * PARAMETERS: FileId - ID of the listing file 527 * 528 * RETURN: None 529 * 530 * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code 531 * buffer. Usually called at the termination of a single line 532 * of source code or when the buffer is full. 533 * 534 ******************************************************************************/ 535 536static void 537LsFlushListingBuffer ( 538 UINT32 FileId) 539{ 540 UINT32 i; 541 542 543 if (Gbl_CurrentHexColumn == 0) 544 { 545 return; 546 } 547 548 /* Write the hex bytes */ 549 550 switch (FileId) 551 { 552 case ASL_FILE_LISTING_OUTPUT: 553 554 for (i = 0; i < Gbl_CurrentHexColumn; i++) 555 { 556 FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]); 557 } 558 559 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++) 560 { 561 FlWriteFile (FileId, ".", 1); 562 } 563 564 /* Write the ASCII character associated with each of the bytes */ 565 566 LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 567 break; 568 569 570 case ASL_FILE_ASM_SOURCE_OUTPUT: 571 572 for (i = 0; i < Gbl_CurrentHexColumn; i++) 573 { 574 if (i > 0) 575 { 576 FlPrintFile (FileId, ","); 577 } 578 FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]); 579 } 580 581 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) 582 { 583 FlWriteFile (FileId, " ", 1); 584 } 585 586 FlPrintFile (FileId, " ;%8.8X", 587 Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); 588 589 /* Write the ASCII character associated with each of the bytes */ 590 591 LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 592 break; 593 594 595 case ASL_FILE_C_SOURCE_OUTPUT: 596 597 for (i = 0; i < Gbl_CurrentHexColumn; i++) 598 { 599 FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]); 600 } 601 602 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) 603 { 604 FlWriteFile (FileId, " ", 1); 605 } 606 607 FlPrintFile (FileId, " /* %8.8X", 608 Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); 609 610 /* Write the ASCII character associated with each of the bytes */ 611 612 LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 613 FlPrintFile (FileId, " */"); 614 break; 615 616 default: 617 /* No other types supported */ 618 return; 619 } 620 621 FlPrintFile (FileId, "\n"); 622 623 Gbl_CurrentHexColumn = 0; 624 Gbl_HexBytesWereWritten = TRUE; 625} 626 627 628/******************************************************************************* 629 * 630 * FUNCTION: LsWriteListingHexBytes 631 * 632 * PARAMETERS: Buffer - AML code buffer 633 * Length - Number of AML bytes to write 634 * FileId - ID of current listing file. 635 * 636 * RETURN: None 637 * 638 * DESCRIPTION: Write the contents of the AML buffer to the listing file via 639 * the listing buffer. The listing buffer is flushed every 16 640 * AML bytes. 641 * 642 ******************************************************************************/ 643 644static void 645LsWriteListingHexBytes ( 646 UINT8 *Buffer, 647 UINT32 Length, 648 UINT32 FileId) 649{ 650 UINT32 i; 651 652 653 /* Transfer all requested bytes */ 654 655 for (i = 0; i < Length; i++) 656 { 657 /* Print line header when buffer is empty */ 658 659 if (Gbl_CurrentHexColumn == 0) 660 { 661 if (Gbl_HasIncludeFiles) 662 { 663 FlPrintFile (FileId, "%*s", 10, " "); 664 } 665 666 switch (FileId) 667 { 668 case ASL_FILE_LISTING_OUTPUT: 669 670 FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset, 671 ASL_LISTING_LINE_PREFIX); 672 break; 673 674 case ASL_FILE_ASM_SOURCE_OUTPUT: 675 676 FlPrintFile (FileId, " db "); 677 break; 678 679 case ASL_FILE_C_SOURCE_OUTPUT: 680 681 FlPrintFile (FileId, " "); 682 break; 683 684 default: 685 /* No other types supported */ 686 return; 687 } 688 } 689 690 /* Transfer AML byte and update counts */ 691 692 Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i]; 693 694 Gbl_CurrentHexColumn++; 695 Gbl_CurrentAmlOffset++; 696 697 /* Flush buffer when it is full */ 698 699 if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE) 700 { 701 LsFlushListingBuffer (FileId); 702 } 703 } 704} 705 706 707/******************************************************************************* 708 * 709 * FUNCTION: LsWriteOneSourceLine 710 * 711 * PARAMETERS: FileID - ID of current listing file 712 * 713 * RETURN: FALSE on EOF (input source file), TRUE otherwise 714 * 715 * DESCRIPTION: Read one line from the input source file and echo it to the 716 * listing file, prefixed with the line number, and if the source 717 * file contains include files, prefixed with the current filename 718 * 719 ******************************************************************************/ 720 721static UINT32 722LsWriteOneSourceLine ( 723 UINT32 FileId) 724{ 725 UINT8 FileByte; 726 727 728 Gbl_SourceLine++; 729 Gbl_ListingNode->LineNumber++; 730 731 /* Ignore lines that are completely blank (but count the line above) */ 732 733 if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK) 734 { 735 return (0); 736 } 737 if (FileByte == '\n') 738 { 739 return (1); 740 } 741 742 /* 743 * This is a non-empty line, we will print the entire line with 744 * the line number and possibly other prefixes and transforms. 745 */ 746 747 /* Line prefixes for special files, C and ASM output */ 748 749 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 750 { 751 FlPrintFile (FileId, " *"); 752 } 753 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 754 { 755 FlPrintFile (FileId, "; "); 756 } 757 758 if (Gbl_HasIncludeFiles) 759 { 760 /* 761 * This file contains "include" statements, print the current 762 * filename and line number within the current file 763 */ 764 FlPrintFile (FileId, "%12s %5d%s", 765 Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber, 766 ASL_LISTING_LINE_PREFIX); 767 } 768 else 769 { 770 /* No include files, just print the line number */ 771 772 FlPrintFile (FileId, "%8u%s", Gbl_SourceLine, 773 ASL_LISTING_LINE_PREFIX); 774 } 775 776 /* Read the rest of this line (up to a newline or EOF) */ 777 778 do 779 { 780 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 781 { 782 if (FileByte == '/') 783 { 784 FileByte = '*'; 785 } 786 } 787 788 FlWriteFile (FileId, &FileByte, 1); 789 if (FileByte == '\n') 790 { 791 /* 792 * This line has been completed. 793 * Check if an error occurred on this source line during the compile. 794 * If so, we print the error message after the source line. 795 */ 796 LsCheckException (Gbl_SourceLine, FileId); 797 return (1); 798 } 799 800 } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK); 801 802 /* EOF on the input file was reached */ 803 804 return (0); 805} 806 807 808/******************************************************************************* 809 * 810 * FUNCTION: LsFinishSourceListing 811 * 812 * PARAMETERS: FileId - ID of current listing file. 813 * 814 * RETURN: None 815 * 816 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML 817 * listing buffer, and flush out any remaining lines in the 818 * source input file. 819 * 820 ******************************************************************************/ 821 822static void 823LsFinishSourceListing ( 824 UINT32 FileId) 825{ 826 827 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 828 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 829 { 830 return; 831 } 832 833 LsFlushListingBuffer (FileId); 834 Gbl_CurrentAmlOffset = 0; 835 836 /* Flush any remaining text in the source file */ 837 838 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 839 { 840 FlPrintFile (FileId, " /*\n"); 841 } 842 843 while (LsWriteOneSourceLine (FileId)) 844 { ; } 845 846 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 847 { 848 FlPrintFile (FileId, "\n */\n };\n"); 849 } 850 851 FlPrintFile (FileId, "\n"); 852 853 if (FileId == ASL_FILE_LISTING_OUTPUT) 854 { 855 /* Print a summary of the compile exceptions */ 856 857 FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n"); 858 AePrintErrorLog (FileId); 859 FlPrintFile (FileId, "\n"); 860 UtDisplaySummary (FileId); 861 FlPrintFile (FileId, "\n"); 862 } 863} 864 865 866/******************************************************************************* 867 * 868 * FUNCTION: LsWriteSourceLines 869 * 870 * PARAMETERS: ToLineNumber - 871 * ToLogicalLineNumber - Write up to this source line number 872 * FileId - ID of current listing file 873 * 874 * RETURN: None 875 * 876 * DESCRIPTION: Read then write source lines to the listing file until we have 877 * reached the specified logical (cumulative) line number. This 878 * automatically echos out comment blocks and other non-AML 879 * generating text until we get to the actual AML-generating line 880 * of ASL code specified by the logical line number. 881 * 882 ******************************************************************************/ 883 884static void 885LsWriteSourceLines ( 886 UINT32 ToLineNumber, 887 UINT32 ToLogicalLineNumber, 888 UINT32 FileId) 889{ 890 891 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 892 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 893 { 894 return; 895 } 896 897 Gbl_CurrentLine = ToLogicalLineNumber; 898 899 /* Flush any hex bytes remaining from the last opcode */ 900 901 LsFlushListingBuffer (FileId); 902 903 /* Read lines and write them as long as we are not caught up */ 904 905 if (Gbl_SourceLine < Gbl_CurrentLine) 906 { 907 /* 908 * If we just completed writing some AML hex bytes, output a linefeed 909 * to add some whitespace for readability. 910 */ 911 if (Gbl_HexBytesWereWritten) 912 { 913 FlPrintFile (FileId, "\n"); 914 Gbl_HexBytesWereWritten = FALSE; 915 } 916 917 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 918 { 919 FlPrintFile (FileId, " /*\n"); 920 } 921 922 /* Write one line at a time until we have reached the target line # */ 923 924 while ((Gbl_SourceLine < Gbl_CurrentLine) && 925 LsWriteOneSourceLine (FileId)) 926 { ; } 927 928 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 929 { 930 FlPrintFile (FileId, " */"); 931 } 932 FlPrintFile (FileId, "\n"); 933 } 934} 935 936 937/******************************************************************************* 938 * 939 * FUNCTION: LsWriteNodeToListing 940 * 941 * PARAMETERS: Op - Parse node to write to the listing file. 942 * FileId - ID of current listing file 943 * 944 * RETURN: None. 945 * 946 * DESCRIPTION: Write "a node" to the listing file. This means to 947 * 1) Write out all of the source text associated with the node 948 * 2) Write out all of the AML bytes associated with the node 949 * 3) Write any compiler exceptions associated with the node 950 * 951 ******************************************************************************/ 952 953static void 954LsWriteNodeToListing ( 955 ACPI_PARSE_OBJECT *Op, 956 UINT32 FileId) 957{ 958 const ACPI_OPCODE_INFO *OpInfo; 959 UINT32 OpClass; 960 char *Pathname; 961 UINT32 Length; 962 UINT32 i; 963 964 965 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 966 OpClass = OpInfo->Class; 967 968 /* TBD: clean this up with a single flag that says: 969 * I start a named output block 970 */ 971 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 972 { 973 switch (Op->Asl.ParseOpcode) 974 { 975 case PARSEOP_DEFINITIONBLOCK: 976 case PARSEOP_METHODCALL: 977 case PARSEOP_INCLUDE: 978 case PARSEOP_INCLUDE_END: 979 case PARSEOP_DEFAULT_ARG: 980 981 break; 982 983 default: 984 switch (OpClass) 985 { 986 case AML_CLASS_NAMED_OBJECT: 987 switch (Op->Asl.AmlOpcode) 988 { 989 case AML_SCOPE_OP: 990 case AML_ALIAS_OP: 991 break; 992 993 default: 994 if (Op->Asl.ExternalName) 995 { 996 LsFlushListingBuffer (FileId); 997 FlPrintFile (FileId, " };\n"); 998 } 999 break; 1000 } 1001 break; 1002 1003 default: 1004 /* Don't care about other objects */ 1005 break; 1006 } 1007 break; 1008 } 1009 } 1010 1011 /* These cases do not have a corresponding AML opcode */ 1012 1013 switch (Op->Asl.ParseOpcode) 1014 { 1015 case PARSEOP_DEFINITIONBLOCK: 1016 1017 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId); 1018 1019 /* Use the table Signature and TableId to build a unique name */ 1020 1021 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 1022 { 1023 FlPrintFile (FileId, 1024 "%s_%s_Header \\\n", 1025 Gbl_TableSignature, Gbl_TableId); 1026 } 1027 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 1028 { 1029 FlPrintFile (FileId, 1030 " unsigned char %s_%s_Header [] =\n {\n", 1031 Gbl_TableSignature, Gbl_TableId); 1032 } 1033 if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) 1034 { 1035 FlPrintFile (FileId, 1036 "extrn %s_%s_Header : byte\n", 1037 Gbl_TableSignature, Gbl_TableId); 1038 } 1039 if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) 1040 { 1041 FlPrintFile (FileId, 1042 "extern unsigned char %s_%s_Header [];\n", 1043 Gbl_TableSignature, Gbl_TableId); 1044 } 1045 return; 1046 1047 1048 case PARSEOP_METHODCALL: 1049 1050 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1051 FileId); 1052 return; 1053 1054 1055 case PARSEOP_INCLUDE: 1056 1057 /* Flush everything up to and including the include source line */ 1058 1059 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1060 FileId); 1061 1062 /* Create a new listing node and push it */ 1063 1064 LsPushNode (Op->Asl.Child->Asl.Value.String); 1065 return; 1066 1067 1068 case PARSEOP_INCLUDE_END: 1069 1070 /* Flush out the rest of the include file */ 1071 1072 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1073 FileId); 1074 1075 /* Pop off this listing node and go back to the parent file */ 1076 1077 (void) LsPopNode (); 1078 return; 1079 1080 1081 case PARSEOP_DEFAULT_ARG: 1082 1083 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 1084 { 1085 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine, 1086 FileId); 1087 } 1088 return; 1089 1090 1091 default: 1092 /* All other opcodes have an AML opcode */ 1093 break; 1094 } 1095 1096 /* 1097 * Otherwise, we look at the AML opcode because we can 1098 * switch on the opcode type, getting an entire class 1099 * at once 1100 */ 1101 switch (OpClass) 1102 { 1103 case AML_CLASS_ARGUMENT: /* argument type only */ 1104 case AML_CLASS_INTERNAL: 1105 1106 break; 1107 1108 1109 case AML_CLASS_NAMED_OBJECT: 1110 1111 switch (Op->Asl.AmlOpcode) 1112 { 1113 case AML_FIELD_OP: 1114 case AML_INDEX_FIELD_OP: 1115 case AML_BANK_FIELD_OP: 1116 1117 /* 1118 * For fields, we want to dump all the AML after the 1119 * entire definition 1120 */ 1121 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 1122 FileId); 1123 break; 1124 1125 case AML_NAME_OP: 1126 1127 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 1128 { 1129 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1130 FileId); 1131 } 1132 else 1133 { 1134 /* 1135 * For fields, we want to dump all the AML after the 1136 * entire definition 1137 */ 1138 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 1139 FileId); 1140 } 1141 break; 1142 1143 default: 1144 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1145 FileId); 1146 break; 1147 } 1148 1149 switch (Op->Asl.AmlOpcode) 1150 { 1151 case AML_SCOPE_OP: 1152 case AML_ALIAS_OP: 1153 1154 /* These opcodes do not declare a new object, ignore them */ 1155 1156 break; 1157 1158 default: 1159 1160 /* All other named object opcodes come here */ 1161 1162 switch (FileId) 1163 { 1164 case ASL_FILE_ASM_SOURCE_OUTPUT: 1165 case ASL_FILE_C_SOURCE_OUTPUT: 1166 case ASL_FILE_ASM_INCLUDE_OUTPUT: 1167 case ASL_FILE_C_INCLUDE_OUTPUT: 1168 1169 /* 1170 * For named objects, we will create a valid symbol so that the 1171 * AML code can be referenced from C or ASM 1172 */ 1173 if (Op->Asl.ExternalName) 1174 { 1175 /* Get the full pathname associated with this node */ 1176 1177 Pathname = AcpiNsGetExternalPathname (Op->Asl.Node); 1178 Length = strlen (Pathname); 1179 if (Length >= 4) 1180 { 1181 /* Convert all dots in the path to underscores */ 1182 1183 for (i = 0; i < Length; i++) 1184 { 1185 if (Pathname[i] == '.') 1186 { 1187 Pathname[i] = '_'; 1188 } 1189 } 1190 1191 /* Create the appropriate symbol in the output file */ 1192 1193 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 1194 { 1195 FlPrintFile (FileId, 1196 "%s_%s_%s \\\n", 1197 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1198 } 1199 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 1200 { 1201 FlPrintFile (FileId, 1202 " unsigned char %s_%s_%s [] =\n {\n", 1203 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1204 } 1205 if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) 1206 { 1207 FlPrintFile (FileId, 1208 "extrn %s_%s_%s : byte\n", 1209 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1210 } 1211 if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) 1212 { 1213 FlPrintFile (FileId, 1214 "extern unsigned char %s_%s_%s [];\n", 1215 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1216 } 1217 } 1218 ACPI_FREE (Pathname); 1219 } 1220 break; 1221 1222 default: 1223 /* Nothing to do for listing file */ 1224 break; 1225 } 1226 } 1227 break; 1228 1229 case AML_CLASS_EXECUTE: 1230 case AML_CLASS_CREATE: 1231 default: 1232 1233 if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) && 1234 (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)) 1235 { 1236 return; 1237 } 1238 1239 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1240 FileId); 1241 break; 1242 1243 case AML_CLASS_UNKNOWN: 1244 break; 1245 } 1246} 1247