1 /******************************************************************************
2  *
3  * Module Name: asltree - parse tree management
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "aslcompiler.h"
153 #include "aslcompiler.y.h"
154 #include "acapps.h"
155 #include "acconvert.h"
156 #include <time.h>
157 
158 #define _COMPONENT          ACPI_COMPILER
159         ACPI_MODULE_NAME    ("asltree")
160 
161 /* Local prototypes */
162 
163 static ACPI_PARSE_OBJECT *
164 TrGetNextNode (
165     void);
166 
167 
168 /*******************************************************************************
169  *
170  * FUNCTION:    TrSetParent
171  *
172  * PARAMETERS:  Op                  - To be set to new parent
173  *              ParentOp            - The parent
174  *
175  * RETURN:      None, sets Op parent directly
176  *
177  * DESCRIPTION: Change the parent of a parse op.
178  *
179  ******************************************************************************/
180 
181 void
182 TrSetParent (
183     ACPI_PARSE_OBJECT       *Op,
184     ACPI_PARSE_OBJECT       *ParentOp)
185 {
186 
187     Op->Asl.Parent = ParentOp;
188 }
189 
190 
191 /*******************************************************************************
192  *
193  * FUNCTION:    TrGetNextNode
194  *
195  * PARAMETERS:  None
196  *
197  * RETURN:      New parse node. Aborts on allocation failure
198  *
199  * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
200  *              dynamic memory manager for performance reasons (This has a
201  *              major impact on the speed of the compiler.)
202  *
203  ******************************************************************************/
204 
205 static ACPI_PARSE_OBJECT *
206 TrGetNextNode (
207     void)
208 {
209     ASL_CACHE_INFO          *Cache;
210 
211 
212     if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
213     {
214         /* Allocate a new buffer */
215 
216         Cache = UtLocalCalloc (sizeof (Cache->Next) +
217             (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
218 
219         /* Link new cache buffer to head of list */
220 
221         Cache->Next = Gbl_ParseOpCacheList;
222         Gbl_ParseOpCacheList = Cache;
223 
224         /* Setup cache management pointers */
225 
226         Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
227         Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
228     }
229 
230     Gbl_ParseOpCount++;
231     return (Gbl_ParseOpCacheNext++);
232 }
233 
234 
235 /*******************************************************************************
236  *
237  * FUNCTION:    TrAllocateNode
238  *
239  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
240  *
241  * RETURN:      New parse node. Aborts on allocation failure
242  *
243  * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
244  *
245  ******************************************************************************/
246 
247 ACPI_PARSE_OBJECT *
248 TrAllocateNode (
249     UINT32                  ParseOpcode)
250 {
251     ACPI_PARSE_OBJECT       *Op;
252     ACPI_PARSE_OBJECT       *LatestNode;
253 
254 
255     Op = TrGetNextNode ();
256 
257     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
258     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
259     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
260     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
261     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
262     Op->Asl.Column            = Gbl_CurrentColumn;
263 
264     UtSetParseOpName (Op);
265 
266     /* The following is for capturing comments */
267 
268     if(Gbl_CaptureComments)
269     {
270         LatestNode = Gbl_CommentState.Latest_Parse_Node;
271         Op->Asl.InlineComment     = NULL;
272         Op->Asl.EndNodeComment    = NULL;
273         Op->Asl.CommentList       = NULL;
274         Op->Asl.FileChanged       = FALSE;
275 
276         /*
277          * Check to see if the file name has changed before resetting the
278          * latest parse node.
279          */
280         if (LatestNode &&
281             (ParseOpcode != PARSEOP_INCLUDE) &&
282             (ParseOpcode != PARSEOP_INCLUDE_END) &&
283             strcmp (LatestNode->Asl.Filename, Op->Asl.Filename))
284         {
285             CvDbgPrint ("latest node: %s\n", LatestNode->Asl.ParseOpName);
286             Op->Asl.FileChanged = TRUE;
287             if (Gbl_IncludeFileStack)
288             {
289                 Op->Asl.ParentFilename = Gbl_IncludeFileStack->Filename;
290             }
291             else
292             {
293                 Op->Asl.ParentFilename = NULL;
294             }
295         }
296 
297         Gbl_CommentState.Latest_Parse_Node = Op;
298         if (Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName)
299         {
300             CvDbgPrint ("trallocatenode=Set latest parse node to this node.\n");
301             CvDbgPrint ("           Op->Asl.ParseOpName = %s\n",
302                 Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName);
303             CvDbgPrint ("           Op->Asl.ParseOpcode = 0x%x\n", ParseOpcode);
304 
305             if (Op->Asl.FileChanged)
306             {
307                 CvDbgPrint("    file has been changed!\n");
308             }
309         }
310 
311         /*
312          * if this parse op's syntax uses () and {} (i.e. Package(1){0x00}) then
313          * set a flag in the comment state. This facilitates paring comments for
314          * these types of opcodes.
315          */
316         if ((CvParseOpBlockType(Op) == (BLOCK_PAREN | BLOCK_BRACE)) &&
317             (ParseOpcode != PARSEOP_DEFINITION_BLOCK))
318         {
319             CvDbgPrint ("Parsing paren/Brace node now!\n");
320             Gbl_CommentState.ParsingParenBraceNode = Op;
321         }
322 
323         if (Gbl_Comment_List_Head)
324         {
325             CvDbgPrint ("Transferring...\n");
326             Op->Asl.CommentList = Gbl_Comment_List_Head;
327             Gbl_Comment_List_Head = NULL;
328             Gbl_Comment_List_Tail = NULL;
329             CvDbgPrint ("    Transferred current comment list to this node.\n");
330             CvDbgPrint ("    %s\n", Op->Asl.CommentList->Comment);
331         }
332         if (Gbl_Inline_Comment_Buffer)
333         {
334             Op->Asl.InlineComment = Gbl_Inline_Comment_Buffer;
335             Gbl_Inline_Comment_Buffer = NULL;
336             CvDbgPrint ("Transferred current inline comment list to this node.\n");
337         }
338 
339     }
340 
341     return (Op);
342 }
343 
344 
345 /*******************************************************************************
346  *
347  * FUNCTION:    TrReleaseNode
348  *
349  * PARAMETERS:  Op            - Op to be released
350  *
351  * RETURN:      None
352  *
353  * DESCRIPTION: "release" a node. In truth, nothing is done since the node
354  *              is part of a larger buffer
355  *
356  ******************************************************************************/
357 
358 void
359 TrReleaseNode (
360     ACPI_PARSE_OBJECT       *Op)
361 {
362 
363     return;
364 }
365 
366 
367 /*******************************************************************************
368  *
369  * FUNCTION:    TrSetCurrentFilename
370  *
371  * PARAMETERS:  Op                  - An existing parse node
372  *
373  * RETURN:      None
374  *
375  * DESCRIPTION: Save the include file filename. Used for debug output only.
376  *
377  ******************************************************************************/
378 
379 void
380 TrSetCurrentFilename (
381     ACPI_PARSE_OBJECT       *Op)
382 {
383     Op->Asl.Filename = Gbl_PreviousIncludeFilename;
384 }
385 
386 
387 /*******************************************************************************
388  *
389  * FUNCTION:    TrUpdateNode
390  *
391  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
392  *              Op                  - An existing parse node
393  *
394  * RETURN:      The updated node
395  *
396  * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
397  *              change an opcode to DEFAULT_ARG so that the node is ignored
398  *              during the code generation. Also used to set generic integers
399  *              to a specific size (8, 16, 32, or 64 bits)
400  *
401  ******************************************************************************/
402 
403 ACPI_PARSE_OBJECT *
404 TrUpdateNode (
405     UINT32                  ParseOpcode,
406     ACPI_PARSE_OBJECT       *Op)
407 {
408 
409     if (!Op)
410     {
411         return (NULL);
412     }
413 
414     DbgPrint (ASL_PARSE_OUTPUT,
415         "\nUpdateNode: Old - %s, New - %s\n",
416         UtGetOpName (Op->Asl.ParseOpcode),
417         UtGetOpName (ParseOpcode));
418 
419     /* Assign new opcode and name */
420 
421     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
422     {
423         switch (ParseOpcode)
424         {
425         case PARSEOP_BYTECONST:
426 
427             Op->Asl.Value.Integer = ACPI_UINT8_MAX;
428             break;
429 
430         case PARSEOP_WORDCONST:
431 
432             Op->Asl.Value.Integer = ACPI_UINT16_MAX;
433             break;
434 
435         case PARSEOP_DWORDCONST:
436 
437             Op->Asl.Value.Integer = ACPI_UINT32_MAX;
438             break;
439 
440         /* Don't need to do the QWORD case */
441 
442         default:
443 
444             /* Don't care about others */
445             break;
446         }
447     }
448 
449     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
450     UtSetParseOpName (Op);
451 
452     /*
453      * For the BYTE, WORD, and DWORD constants, make sure that the integer
454      * that was passed in will actually fit into the data type
455      */
456     switch (ParseOpcode)
457     {
458     case PARSEOP_BYTECONST:
459 
460         UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
461         Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
462         break;
463 
464     case PARSEOP_WORDCONST:
465 
466         UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
467         Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
468         break;
469 
470     case PARSEOP_DWORDCONST:
471 
472         UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
473         Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
474         break;
475 
476     default:
477 
478         /* Don't care about others, don't need to check QWORD */
479 
480         break;
481     }
482 
483     /* Converter: if this is a method invocation, turn off capture comments. */
484     if (Gbl_CaptureComments &&
485         (ParseOpcode == PARSEOP_METHODCALL))
486     {
487         Gbl_CommentState.CaptureComments = FALSE;
488     }
489 
490     return (Op);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION:    TrPrintNodeCompileFlags
497  *
498  * PARAMETERS:  Flags               - Flags word to be decoded
499  *
500  * RETURN:      None
501  *
502  * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
503  *
504  ******************************************************************************/
505 
506 void
507 TrPrintNodeCompileFlags (
508     UINT32                  Flags)
509 {
510     UINT32                  i;
511     UINT32                  FlagBit = 1;
512     char                    *FlagName = NULL;
513 
514 
515     for (i = 0; i < 32; i++)
516     {
517         switch (Flags & FlagBit)
518         {
519         case NODE_VISITED:
520 
521             FlagName = "NODE_VISITED";
522             break;
523 
524         case NODE_AML_PACKAGE:
525 
526             FlagName = "NODE_AML_PACKAGE";
527             break;
528 
529         case NODE_IS_TARGET:
530 
531             FlagName = "NODE_IS_TARGET";
532             break;
533 
534         case NODE_IS_RESOURCE_DESC:
535 
536             FlagName = "NODE_IS_RESOURCE_DESC";
537             break;
538 
539         case NODE_IS_RESOURCE_FIELD:
540 
541             FlagName = "NODE_IS_RESOURCE_FIELD";
542             break;
543 
544         case NODE_HAS_NO_EXIT:
545 
546             FlagName = "NODE_HAS_NO_EXIT";
547             break;
548 
549         case NODE_IF_HAS_NO_EXIT:
550 
551             FlagName = "NODE_IF_HAS_NO_EXIT";
552             break;
553 
554         case NODE_NAME_INTERNALIZED:
555 
556             FlagName = "NODE_NAME_INTERNALIZED";
557             break;
558 
559         case NODE_METHOD_NO_RETVAL:
560 
561             FlagName = "NODE_METHOD_NO_RETVAL";
562             break;
563 
564         case NODE_METHOD_SOME_NO_RETVAL:
565 
566             FlagName = "NODE_METHOD_SOME_NO_RETVAL";
567             break;
568 
569         case NODE_RESULT_NOT_USED:
570 
571             FlagName = "NODE_RESULT_NOT_USED";
572             break;
573 
574         case NODE_METHOD_TYPED:
575 
576             FlagName = "NODE_METHOD_TYPED";
577             break;
578 
579         case NODE_COULD_NOT_REDUCE:
580 
581             FlagName = "NODE_COULD_NOT_REDUCE";
582             break;
583 
584         case NODE_COMPILE_TIME_CONST:
585 
586             FlagName = "NODE_COMPILE_TIME_CONST";
587             break;
588 
589         case NODE_IS_TERM_ARG:
590 
591             FlagName = "NODE_IS_TERM_ARG";
592             break;
593 
594         case NODE_WAS_ONES_OP:
595 
596             FlagName = "NODE_WAS_ONES_OP";
597             break;
598 
599         case NODE_IS_NAME_DECLARATION:
600 
601             FlagName = "NODE_IS_NAME_DECLARATION";
602             break;
603 
604         case NODE_COMPILER_EMITTED:
605 
606             FlagName = "NODE_COMPILER_EMITTED";
607             break;
608 
609         case NODE_IS_DUPLICATE:
610 
611             FlagName = "NODE_IS_DUPLICATE";
612             break;
613 
614         case NODE_IS_RESOURCE_DATA:
615 
616             FlagName = "NODE_IS_RESOURCE_DATA";
617             break;
618 
619         case NODE_IS_NULL_RETURN:
620 
621             FlagName = "NODE_IS_NULL_RETURN";
622             break;
623 
624         default:
625             break;
626         }
627 
628         if (FlagName)
629         {
630             DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
631             FlagName = NULL;
632         }
633 
634         FlagBit <<= 1;
635     }
636 }
637 
638 
639 /*******************************************************************************
640  *
641  * FUNCTION:    TrSetNodeFlags
642  *
643  * PARAMETERS:  Op                  - An existing parse node
644  *              Flags               - New flags word
645  *
646  * RETURN:      The updated parser op
647  *
648  * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
649  *
650  ******************************************************************************/
651 
652 ACPI_PARSE_OBJECT *
653 TrSetNodeFlags (
654     ACPI_PARSE_OBJECT       *Op,
655     UINT32                  Flags)
656 {
657 
658     if (!Op)
659     {
660         return (NULL);
661     }
662 
663     DbgPrint (ASL_PARSE_OUTPUT,
664         "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
665 
666     TrPrintNodeCompileFlags (Flags);
667     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
668 
669     Op->Asl.CompileFlags |= Flags;
670     return (Op);
671 }
672 
673 
674 /*******************************************************************************
675  *
676  * FUNCTION:    TrSetNodeAmlLength
677  *
678  * PARAMETERS:  Op                  - An existing parse node
679  *              Length              - AML Length
680  *
681  * RETURN:      The updated parser op
682  *
683  * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
684  *              the presence of a node that must be reduced to a fixed length
685  *              constant.
686  *
687  ******************************************************************************/
688 
689 ACPI_PARSE_OBJECT *
690 TrSetNodeAmlLength (
691     ACPI_PARSE_OBJECT       *Op,
692     UINT32                  Length)
693 {
694 
695     DbgPrint (ASL_PARSE_OUTPUT,
696         "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
697 
698     if (!Op)
699     {
700         return (NULL);
701     }
702 
703     Op->Asl.AmlLength = Length;
704     return (Op);
705 }
706 
707 
708 /*******************************************************************************
709  *
710  * FUNCTION:    TrSetEndLineNumber
711  *
712  * PARAMETERS:  Op                - An existing parse node
713  *
714  * RETURN:      None.
715  *
716  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
717  *              parse node to the current line numbers.
718  *
719  ******************************************************************************/
720 
721 void
722 TrSetEndLineNumber (
723     ACPI_PARSE_OBJECT       *Op)
724 {
725 
726     /* If the end line # is already set, just return */
727 
728     if (Op->Asl.EndLine)
729     {
730         return;
731     }
732 
733     Op->Asl.EndLine = Gbl_CurrentLineNumber;
734     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
735 }
736 
737 
738 /*******************************************************************************
739  *
740  * FUNCTION:    TrCreateAssignmentNode
741  *
742  * PARAMETERS:  Target              - Assignment target
743  *              Source              - Assignment source
744  *
745  * RETURN:      Pointer to the new node. Aborts on allocation failure
746  *
747  * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
748  *              tree if possible to utilize the last argument of the math
749  *              operators which is a target operand -- thus saving invocation
750  *              of and additional Store() operator. An optimization.
751  *
752  ******************************************************************************/
753 
754 ACPI_PARSE_OBJECT *
755 TrCreateAssignmentNode (
756     ACPI_PARSE_OBJECT       *Target,
757     ACPI_PARSE_OBJECT       *Source)
758 {
759     ACPI_PARSE_OBJECT       *TargetOp;
760     ACPI_PARSE_OBJECT       *SourceOp1;
761     ACPI_PARSE_OBJECT       *SourceOp2;
762     ACPI_PARSE_OBJECT       *Operator;
763 
764 
765     DbgPrint (ASL_PARSE_OUTPUT,
766         "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
767         Source->Asl.LineNumber, Source->Asl.EndLine,
768         UtGetOpName (Source->Asl.ParseOpcode),
769         UtGetOpName (Target->Asl.ParseOpcode));
770 
771     TrSetNodeFlags (Target, NODE_IS_TARGET);
772 
773     switch (Source->Asl.ParseOpcode)
774     {
775     /*
776      * Only these operators can be optimized because they have
777      * a target operand
778      */
779     case PARSEOP_ADD:
780     case PARSEOP_AND:
781     case PARSEOP_DIVIDE:
782     case PARSEOP_INDEX:
783     case PARSEOP_MOD:
784     case PARSEOP_MULTIPLY:
785     case PARSEOP_NOT:
786     case PARSEOP_OR:
787     case PARSEOP_SHIFTLEFT:
788     case PARSEOP_SHIFTRIGHT:
789     case PARSEOP_SUBTRACT:
790     case PARSEOP_XOR:
791 
792         break;
793 
794     /* Otherwise, just create a normal Store operator */
795 
796     default:
797 
798         goto CannotOptimize;
799     }
800 
801     /*
802      * Transform the parse tree such that the target is moved to the
803      * last operand of the operator
804      */
805     SourceOp1 = Source->Asl.Child;
806     SourceOp2 = SourceOp1->Asl.Next;
807 
808     /* NOT only has one operand, but has a target */
809 
810     if (Source->Asl.ParseOpcode == PARSEOP_NOT)
811     {
812         SourceOp2 = SourceOp1;
813     }
814 
815     /* DIVIDE has an extra target operand (remainder) */
816 
817     if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
818     {
819         SourceOp2 = SourceOp2->Asl.Next;
820     }
821 
822     TargetOp = SourceOp2->Asl.Next;
823 
824     /*
825      * Can't perform this optimization if there already is a target
826      * for the operator (ZERO is a "no target" placeholder).
827      */
828     if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
829     {
830         goto CannotOptimize;
831     }
832 
833     /* Link in the target as the final operand */
834 
835     SourceOp2->Asl.Next = Target;
836     Target->Asl.Parent = Source;
837 
838     return (Source);
839 
840 
841 CannotOptimize:
842 
843     Operator = TrAllocateNode (PARSEOP_STORE);
844     TrLinkChildren (Operator, 2, Source, Target);
845 
846     /* Set the appropriate line numbers for the new node */
847 
848     Operator->Asl.LineNumber        = Target->Asl.LineNumber;
849     Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
850     Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
851     Operator->Asl.Column            = Target->Asl.Column;
852 
853     return (Operator);
854 }
855 
856 
857 /*******************************************************************************
858  *
859  * FUNCTION:    TrCreateLeafNode
860  *
861  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
862  *
863  * RETURN:      Pointer to the new node. Aborts on allocation failure
864  *
865  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
866  *              assigned to the node)
867  *
868  ******************************************************************************/
869 
870 ACPI_PARSE_OBJECT *
871 TrCreateLeafNode (
872     UINT32                  ParseOpcode)
873 {
874     ACPI_PARSE_OBJECT       *Op;
875 
876 
877     Op = TrAllocateNode (ParseOpcode);
878 
879     DbgPrint (ASL_PARSE_OUTPUT,
880         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
881         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
882 
883     return (Op);
884 }
885 
886 
887 /*******************************************************************************
888  *
889  * FUNCTION:    TrCreateNullTarget
890  *
891  * PARAMETERS:  None
892  *
893  * RETURN:      Pointer to the new node. Aborts on allocation failure
894  *
895  * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
896  *              specification to be a zero AML opcode, and indicates that
897  *              no target has been specified for the parent operation
898  *
899  ******************************************************************************/
900 
901 ACPI_PARSE_OBJECT *
902 TrCreateNullTarget (
903     void)
904 {
905     ACPI_PARSE_OBJECT       *Op;
906 
907 
908     Op = TrAllocateNode (PARSEOP_ZERO);
909     Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
910 
911     DbgPrint (ASL_PARSE_OUTPUT,
912         "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
913         Op->Asl.LineNumber, Op->Asl.Column, Op,
914         UtGetOpName (Op->Asl.ParseOpcode));
915 
916     return (Op);
917 }
918 
919 
920 /*******************************************************************************
921  *
922  * FUNCTION:    TrCreateConstantLeafNode
923  *
924  * PARAMETERS:  ParseOpcode         - The constant opcode
925  *
926  * RETURN:      Pointer to the new node. Aborts on allocation failure
927  *
928  * DESCRIPTION: Create a leaf node (no children or peers) for one of the
929  *              special constants - __LINE__, __FILE__, and __DATE__.
930  *
931  * Note: An implemenation of __FUNC__ cannot happen here because we don't
932  * have a full parse tree at this time and cannot find the parent control
933  * method. If it is ever needed, __FUNC__ must be implemented later, after
934  * the parse tree has been fully constructed.
935  *
936  ******************************************************************************/
937 
938 ACPI_PARSE_OBJECT *
939 TrCreateConstantLeafNode (
940     UINT32                  ParseOpcode)
941 {
942     ACPI_PARSE_OBJECT       *Op = NULL;
943     time_t                  CurrentTime;
944     char                    *StaticTimeString;
945     char                    *TimeString;
946     char                    *Filename;
947 
948 
949     switch (ParseOpcode)
950     {
951     case PARSEOP___LINE__:
952 
953         Op = TrAllocateNode (PARSEOP_INTEGER);
954         Op->Asl.Value.Integer = Op->Asl.LineNumber;
955         break;
956 
957     case PARSEOP___PATH__:
958 
959         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
960 
961         /* Op.Asl.Filename contains the full pathname to the file */
962 
963         Op->Asl.Value.String = Op->Asl.Filename;
964         break;
965 
966     case PARSEOP___FILE__:
967 
968         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
969 
970         /* Get the simple filename from the full path */
971 
972         FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
973         Op->Asl.Value.String = Filename;
974         break;
975 
976     case PARSEOP___DATE__:
977 
978         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
979 
980         /* Get a copy of the current time */
981 
982         CurrentTime = time (NULL);
983         StaticTimeString = ctime (&CurrentTime);
984         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
985         strcpy (TimeString, StaticTimeString);
986 
987         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
988         Op->Asl.Value.String = TimeString;
989         break;
990 
991     default: /* This would be an internal error */
992 
993         return (NULL);
994     }
995 
996     DbgPrint (ASL_PARSE_OUTPUT,
997         "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  "
998         "Op %s  Value %8.8X%8.8X  \n",
999         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
1000         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
1001     return (Op);
1002 }
1003 
1004 
1005 /*******************************************************************************
1006  *
1007  * FUNCTION:    TrCreateTargetOperand
1008  *
1009  * PARAMETERS:  OriginalOp          - Op to be copied
1010  *
1011  * RETURN:      Pointer to the new node. Aborts on allocation failure
1012  *
1013  * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
1014  *              expressions where the target is the same as one of the
1015  *              operands. A new node and subtree must be created from the
1016  *              original so that the parse tree can be linked properly.
1017  *
1018  * NOTE:        This code is specific to target operands that are the last
1019  *              operand in an ASL/AML operator. Meaning that the top-level
1020  *              parse Op in a possible subtree has a NULL Next pointer.
1021  *              This simplifies the recursion.
1022  *
1023  *              Subtree example:
1024  *                  DeRefOf (Local1) += 32
1025  *
1026  *              This gets converted to:
1027  *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
1028  *
1029  *              Each DeRefOf has a single child, Local1. Even more complex
1030  *              subtrees can be created via the Index and DeRefOf operators.
1031  *
1032  ******************************************************************************/
1033 
1034 ACPI_PARSE_OBJECT *
1035 TrCreateTargetOperand (
1036     ACPI_PARSE_OBJECT       *OriginalOp,
1037     ACPI_PARSE_OBJECT       *ParentOp)
1038 {
1039     ACPI_PARSE_OBJECT       *Op;
1040 
1041 
1042     if (!OriginalOp)
1043     {
1044         return (NULL);
1045     }
1046 
1047     Op = TrGetNextNode ();
1048 
1049     /* Copy the pertinent values (omit link pointer fields) */
1050 
1051     Op->Asl.Value               = OriginalOp->Asl.Value;
1052     Op->Asl.Filename            = OriginalOp->Asl.Filename;
1053     Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
1054     Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
1055     Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
1056     Op->Asl.Column              = OriginalOp->Asl.Column;
1057     Op->Asl.Flags               = OriginalOp->Asl.Flags;
1058     Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
1059     Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
1060     Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
1061     Op->Asl.Parent              = ParentOp;
1062     UtSetParseOpName (Op);
1063 
1064     /* Copy a possible subtree below this node */
1065 
1066     if (OriginalOp->Asl.Child)
1067     {
1068         Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
1069     }
1070 
1071     if (OriginalOp->Asl.Next) /* Null for top-level node */
1072     {
1073         Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
1074     }
1075 
1076     return (Op);
1077 }
1078 
1079 
1080 /*******************************************************************************
1081  *
1082  * FUNCTION:    TrCreateValuedLeafNode
1083  *
1084  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
1085  *              Value               - Value to be assigned to the node
1086  *
1087  * RETURN:      Pointer to the new node. Aborts on allocation failure
1088  *
1089  * DESCRIPTION: Create a leaf node (no children or peers) with a value
1090  *              assigned to it
1091  *
1092  ******************************************************************************/
1093 
1094 ACPI_PARSE_OBJECT *
1095 TrCreateValuedLeafNode (
1096     UINT32                  ParseOpcode,
1097     UINT64                  Value)
1098 {
1099     ACPI_PARSE_OBJECT       *Op;
1100 
1101 
1102     Op = TrAllocateNode (ParseOpcode);
1103 
1104     DbgPrint (ASL_PARSE_OUTPUT,
1105         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  "
1106         "Op %s  Value %8.8X%8.8X  ",
1107         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
1108         ACPI_FORMAT_UINT64 (Value));
1109     Op->Asl.Value.Integer = Value;
1110 
1111     switch (ParseOpcode)
1112     {
1113     case PARSEOP_STRING_LITERAL:
1114 
1115         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
1116         break;
1117 
1118     case PARSEOP_NAMESEG:
1119 
1120         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
1121         break;
1122 
1123     case PARSEOP_NAMESTRING:
1124 
1125         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
1126         break;
1127 
1128     case PARSEOP_EISAID:
1129 
1130         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
1131         break;
1132 
1133     case PARSEOP_METHOD:
1134 
1135         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
1136         break;
1137 
1138     case PARSEOP_INTEGER:
1139 
1140         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
1141             ACPI_FORMAT_UINT64 (Value));
1142         break;
1143 
1144     default:
1145 
1146         break;
1147     }
1148 
1149     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1150     return (Op);
1151 }
1152 
1153 
1154 /*******************************************************************************
1155  *
1156  * FUNCTION:    TrCreateNode
1157  *
1158  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
1159  *              NumChildren         - Number of children to follow
1160  *              ...                 - A list of child nodes to link to the new
1161  *                                    node. NumChildren long.
1162  *
1163  * RETURN:      Pointer to the new node. Aborts on allocation failure
1164  *
1165  * DESCRIPTION: Create a new parse node and link together a list of child
1166  *              nodes underneath the new node.
1167  *
1168  ******************************************************************************/
1169 
1170 ACPI_PARSE_OBJECT *
1171 TrCreateNode (
1172     UINT32                  ParseOpcode,
1173     UINT32                  NumChildren,
1174     ...)
1175 {
1176     ACPI_PARSE_OBJECT       *Op;
1177     ACPI_PARSE_OBJECT       *Child;
1178     ACPI_PARSE_OBJECT       *PrevChild;
1179     va_list                 ap;
1180     UINT32                  i;
1181     BOOLEAN                 FirstChild;
1182 
1183 
1184     va_start (ap, NumChildren);
1185 
1186     /* Allocate one new node */
1187 
1188     Op = TrAllocateNode (ParseOpcode);
1189 
1190     DbgPrint (ASL_PARSE_OUTPUT,
1191         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
1192         Op->Asl.LineNumber, Op->Asl.Column, Op,
1193         NumChildren, UtGetOpName(ParseOpcode));
1194 
1195     /* Some extra debug output based on the parse opcode */
1196 
1197     switch (ParseOpcode)
1198     {
1199     case PARSEOP_ASL_CODE:
1200 
1201         Gbl_ParseTreeRoot = Op;
1202         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1203         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1204         break;
1205 
1206     case PARSEOP_DEFINITION_BLOCK:
1207 
1208         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1209         break;
1210 
1211     case PARSEOP_OPERATIONREGION:
1212 
1213         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1214         break;
1215 
1216     case PARSEOP_OR:
1217 
1218         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1219         break;
1220 
1221     default:
1222 
1223         /* Nothing to do for other opcodes */
1224 
1225         break;
1226     }
1227 
1228     /* Link the new node to its children */
1229 
1230     PrevChild = NULL;
1231     FirstChild = TRUE;
1232     for (i = 0; i < NumChildren; i++)
1233     {
1234         /* Get the next child */
1235 
1236         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1237         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1238 
1239         /*
1240          * If child is NULL, this means that an optional argument
1241          * was omitted. We must create a placeholder with a special
1242          * opcode (DEFAULT_ARG) so that the code generator will know
1243          * that it must emit the correct default for this argument
1244          */
1245         if (!Child)
1246         {
1247             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1248         }
1249 
1250         /* Link first child to parent */
1251 
1252         if (FirstChild)
1253         {
1254             FirstChild = FALSE;
1255             Op->Asl.Child = Child;
1256 
1257             /*
1258              * For the ASL-/ASL+ converter: if the ParseOp is a connection,
1259              * external, offset or accessAs, it means that the comments in the
1260              * FirstChild belongs to their parent due to the parsing order in
1261              * the .y files. To correct this, take the comments in the
1262              * FirstChild place it in the parent. This also means that
1263              * legitimate comments for the child gets put to the parent.
1264              */
1265             if (Gbl_CaptureComments &&
1266                 ((ParseOpcode == PARSEOP_CONNECTION) ||
1267                  (ParseOpcode == PARSEOP_EXTERNAL) ||
1268                  (ParseOpcode == PARSEOP_OFFSET) ||
1269                  (ParseOpcode == PARSEOP_ACCESSAS)))
1270             {
1271                 Op->Asl.CommentList      = Child->Asl.CommentList;
1272                 Op->Asl.EndBlkComment    = Child->Asl.EndBlkComment;
1273                 Op->Asl.InlineComment    = Child->Asl.InlineComment;
1274                 Op->Asl.FileChanged      = Child->Asl.FileChanged;
1275 
1276                 Child->Asl.CommentList   = NULL;
1277                 Child->Asl.EndBlkComment = NULL;
1278                 Child->Asl.InlineComment = NULL;
1279                 Child->Asl.FileChanged   = FALSE;
1280 
1281                 /*
1282                  * These do not need to be "passed off". They can be copied
1283                  * because the code for these opcodes should be printed in the
1284                  * same file.
1285                  */
1286                 Op->Asl.Filename         = Child->Asl.Filename;
1287                 Op->Asl.ParentFilename   = Child->Asl.ParentFilename;
1288             }
1289         }
1290 
1291         /* Point all children to parent */
1292 
1293         Child->Asl.Parent = Op;
1294 
1295         /* Link children in a peer list */
1296 
1297         if (PrevChild)
1298         {
1299             PrevChild->Asl.Next = Child;
1300         };
1301 
1302         /* Get the comment from last child in the resource template call */
1303 
1304         if (Gbl_CaptureComments &&
1305             (Op->Asl.ParseOpcode == PARSEOP_RESOURCETEMPLATE))
1306         {
1307             CvDbgPrint ("Transferred current comment list to this node.\n");
1308             Op->Asl.CommentList = Child->Asl.CommentList;
1309             Child->Asl.CommentList = NULL;
1310             Op->Asl.InlineComment = Child->Asl.InlineComment;
1311             Child->Asl.InlineComment = NULL;
1312         }
1313 
1314         /*
1315          * This child might be a list, point all nodes in the list
1316          * to the same parent
1317          */
1318         while (Child->Asl.Next)
1319         {
1320             Child = Child->Asl.Next;
1321             Child->Asl.Parent = Op;
1322         }
1323 
1324         PrevChild = Child;
1325     }
1326     va_end(ap);
1327 
1328     DbgPrint (ASL_PARSE_OUTPUT, "\n");
1329     return (Op);
1330 }
1331 
1332 
1333 /*******************************************************************************
1334  *
1335  * FUNCTION:    TrLinkChildren
1336  *
1337  * PARAMETERS:  Op                - An existing parse node
1338  *              NumChildren        - Number of children to follow
1339  *              ...                - A list of child nodes to link to the new
1340  *                                   node. NumChildren long.
1341  *
1342  * RETURN:      The updated (linked) node
1343  *
1344  * DESCRIPTION: Link a group of nodes to an existing parse node
1345  *
1346  ******************************************************************************/
1347 
1348 ACPI_PARSE_OBJECT *
1349 TrLinkChildren (
1350     ACPI_PARSE_OBJECT       *Op,
1351     UINT32                  NumChildren,
1352     ...)
1353 {
1354     ACPI_PARSE_OBJECT       *Child;
1355     ACPI_PARSE_OBJECT       *PrevChild;
1356     va_list                 ap;
1357     UINT32                  i;
1358     BOOLEAN                 FirstChild;
1359 
1360 
1361     va_start (ap, NumChildren);
1362 
1363 
1364     TrSetEndLineNumber (Op);
1365 
1366     DbgPrint (ASL_PARSE_OUTPUT,
1367         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
1368         Op->Asl.LineNumber, Op->Asl.EndLine,
1369         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1370 
1371     switch (Op->Asl.ParseOpcode)
1372     {
1373     case PARSEOP_ASL_CODE:
1374 
1375         Gbl_ParseTreeRoot = Op;
1376         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1377         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1378         break;
1379 
1380     case PARSEOP_DEFINITION_BLOCK:
1381 
1382         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1383         break;
1384 
1385     case PARSEOP_OPERATIONREGION:
1386 
1387         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1388         break;
1389 
1390     case PARSEOP_OR:
1391 
1392         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1393         break;
1394 
1395     default:
1396 
1397         /* Nothing to do for other opcodes */
1398 
1399         break;
1400     }
1401 
1402     /* The following is for capturing comments */
1403 
1404     if(Gbl_CaptureComments)
1405     {
1406         /*
1407          * If there are "regular comments" detected at this point,
1408          * then is an endBlk comment. Categorize it as so and distribute
1409          * all regular comments to this parse node.
1410          */
1411         if (Gbl_Comment_List_Head)
1412         {
1413             Op->Asl.EndBlkComment = Gbl_Comment_List_Head;
1414             CvDbgPrint ("EndBlk Comment for %s: %s",
1415                 Op->Asl.ParseOpName, Gbl_Comment_List_Head->Comment);
1416             Gbl_Comment_List_Head = NULL;
1417             Gbl_Comment_List_Tail = NULL;
1418         }
1419     }
1420 
1421     /* Link the new node to it's children */
1422 
1423     PrevChild = NULL;
1424     FirstChild = TRUE;
1425     for (i = 0; i < NumChildren; i++)
1426     {
1427         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1428 
1429         if ((Child == PrevChild) && (Child != NULL))
1430         {
1431             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1432                 "Child node list invalid");
1433             va_end(ap);
1434             return (Op);
1435         }
1436 
1437         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1438 
1439         /*
1440          * If child is NULL, this means that an optional argument
1441          * was omitted. We must create a placeholder with a special
1442          * opcode (DEFAULT_ARG) so that the code generator will know
1443          * that it must emit the correct default for this argument
1444          */
1445         if (!Child)
1446         {
1447             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1448         }
1449 
1450         /* Link first child to parent */
1451 
1452         if (FirstChild)
1453         {
1454             FirstChild = FALSE;
1455             Op->Asl.Child = Child;
1456         }
1457 
1458         /* Point all children to parent */
1459 
1460         Child->Asl.Parent = Op;
1461 
1462         /* Link children in a peer list */
1463 
1464         if (PrevChild)
1465         {
1466             PrevChild->Asl.Next = Child;
1467         };
1468 
1469         /*
1470          * This child might be a list, point all nodes in the list
1471          * to the same parent
1472          */
1473         while (Child->Asl.Next)
1474         {
1475             Child = Child->Asl.Next;
1476             Child->Asl.Parent = Op;
1477         }
1478 
1479         PrevChild = Child;
1480     }
1481 
1482     va_end(ap);
1483     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1484 
1485 
1486     if(Gbl_CaptureComments)
1487     {
1488         Gbl_CommentState.Latest_Parse_Node = Op;
1489         CvDbgPrint ("trlinkchildren=====Set latest parse node to this node.\n");
1490     }
1491     return (Op);
1492 }
1493 
1494 
1495 /*******************************************************************************
1496  *
1497  * FUNCTION:    TrLinkPeerNode
1498  *
1499  * PARAMETERS:  Op1           - First peer
1500  *              Op2           - Second peer
1501  *
1502  * RETURN:      Op1 or the non-null node.
1503  *
1504  * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1505  *
1506  ******************************************************************************/
1507 
1508 ACPI_PARSE_OBJECT *
1509 TrLinkPeerNode (
1510     ACPI_PARSE_OBJECT       *Op1,
1511     ACPI_PARSE_OBJECT       *Op2)
1512 {
1513     ACPI_PARSE_OBJECT       *Next;
1514 
1515 
1516     DbgPrint (ASL_PARSE_OUTPUT,
1517         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1518         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1519         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1520 
1521 
1522     if ((!Op1) && (!Op2))
1523     {
1524         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1525         return (Op1);
1526     }
1527 
1528     /* If one of the nodes is null, just return the non-null node */
1529 
1530     if (!Op2)
1531     {
1532         return (Op1);
1533     }
1534 
1535     if (!Op1)
1536     {
1537         return (Op2);
1538     }
1539 
1540     if (Op1 == Op2)
1541     {
1542         DbgPrint (ASL_DEBUG_OUTPUT,
1543             "\n************* Internal error, linking node to itself %p\n",
1544             Op1);
1545         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1546             "Linking node to itself");
1547         return (Op1);
1548     }
1549 
1550     Op1->Asl.Parent = Op2->Asl.Parent;
1551 
1552     /*
1553      * Op 1 may already have a peer list (such as an IF/ELSE pair),
1554      * so we must walk to the end of the list and attach the new
1555      * peer at the end
1556      */
1557     Next = Op1;
1558     while (Next->Asl.Next)
1559     {
1560         Next = Next->Asl.Next;
1561     }
1562 
1563     Next->Asl.Next = Op2;
1564     return (Op1);
1565 }
1566 
1567 
1568 /*******************************************************************************
1569  *
1570  * FUNCTION:    TrLinkPeerNodes
1571  *
1572  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
1573  *              ...                 - A list of nodes to link together as peers
1574  *
1575  * RETURN:      The first node in the list (head of the peer list)
1576  *
1577  * DESCRIPTION: Link together an arbitrary number of peer nodes.
1578  *
1579  ******************************************************************************/
1580 
1581 ACPI_PARSE_OBJECT *
1582 TrLinkPeerNodes (
1583     UINT32                  NumPeers,
1584     ...)
1585 {
1586     ACPI_PARSE_OBJECT       *This;
1587     ACPI_PARSE_OBJECT       *Next;
1588     va_list                 ap;
1589     UINT32                  i;
1590     ACPI_PARSE_OBJECT       *Start;
1591 
1592 
1593     DbgPrint (ASL_PARSE_OUTPUT,
1594         "\nLinkPeerNodes: (%u) ", NumPeers);
1595 
1596     va_start (ap, NumPeers);
1597     This = va_arg (ap, ACPI_PARSE_OBJECT *);
1598     Start = This;
1599 
1600     /*
1601      * Link all peers
1602      */
1603     for (i = 0; i < (NumPeers -1); i++)
1604     {
1605         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1606 
1607         while (This->Asl.Next)
1608         {
1609             This = This->Asl.Next;
1610         }
1611 
1612         /* Get another peer node */
1613 
1614         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1615         if (!Next)
1616         {
1617             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1618         }
1619 
1620         /* link new node to the current node */
1621 
1622         This->Asl.Next = Next;
1623         This = Next;
1624     }
1625     va_end (ap);
1626 
1627     DbgPrint (ASL_PARSE_OUTPUT,"\n");
1628     return (Start);
1629 }
1630 
1631 
1632 /*******************************************************************************
1633  *
1634  * FUNCTION:    TrLinkChildNode
1635  *
1636  * PARAMETERS:  Op1           - Parent node
1637  *              Op2           - Op to become a child
1638  *
1639  * RETURN:      The parent node
1640  *
1641  * DESCRIPTION: Link two nodes together as a parent and child
1642  *
1643  ******************************************************************************/
1644 
1645 ACPI_PARSE_OBJECT *
1646 TrLinkChildNode (
1647     ACPI_PARSE_OBJECT       *Op1,
1648     ACPI_PARSE_OBJECT       *Op2)
1649 {
1650     ACPI_PARSE_OBJECT       *Next;
1651 
1652 
1653     DbgPrint (ASL_PARSE_OUTPUT,
1654         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1655         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1656         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1657 
1658     /*
1659      * Converter: if TrLinkChildNode is called to link a method call,
1660      * turn on capture comments as it signifies that we are done parsing
1661      * a method call.
1662      */
1663     if (Gbl_CaptureComments)
1664     {
1665         if (Op1->Asl.ParseOpcode == PARSEOP_METHODCALL)
1666         {
1667             Gbl_CommentState.CaptureComments = TRUE;
1668         }
1669         Gbl_CommentState.Latest_Parse_Node = Op1;
1670     }
1671     if (!Op1 || !Op2)
1672     {
1673         return (Op1);
1674     }
1675 
1676     Op1->Asl.Child = Op2;
1677 
1678     /* Set the child and all peers of the child to point to the parent */
1679 
1680     Next = Op2;
1681     while (Next)
1682     {
1683         Next->Asl.Parent = Op1;
1684         Next = Next->Asl.Next;
1685     }
1686 
1687     return (Op1);
1688 }
1689 
1690 
1691 /*******************************************************************************
1692  *
1693  * FUNCTION:    TrWalkParseTree
1694  *
1695  * PARAMETERS:  Visitation              - Type of walk
1696  *              DescendingCallback      - Called during tree descent
1697  *              AscendingCallback       - Called during tree ascent
1698  *              Context                 - To be passed to the callbacks
1699  *
1700  * RETURN:      Status from callback(s)
1701  *
1702  * DESCRIPTION: Walk the entire parse tree.
1703  *
1704  ******************************************************************************/
1705 
1706 ACPI_STATUS
1707 TrWalkParseTree (
1708     ACPI_PARSE_OBJECT       *Op,
1709     UINT32                  Visitation,
1710     ASL_WALK_CALLBACK       DescendingCallback,
1711     ASL_WALK_CALLBACK       AscendingCallback,
1712     void                    *Context)
1713 {
1714     UINT32                  Level;
1715     BOOLEAN                 NodePreviouslyVisited;
1716     ACPI_PARSE_OBJECT       *StartOp = Op;
1717     ACPI_STATUS             Status;
1718 
1719 
1720     if (!Gbl_ParseTreeRoot)
1721     {
1722         return (AE_OK);
1723     }
1724 
1725     Level = 0;
1726     NodePreviouslyVisited = FALSE;
1727 
1728     switch (Visitation)
1729     {
1730     case ASL_WALK_VISIT_DOWNWARD:
1731 
1732         while (Op)
1733         {
1734             if (!NodePreviouslyVisited)
1735             {
1736                 /* Let the callback process the node. */
1737 
1738                 Status = DescendingCallback (Op, Level, Context);
1739                 if (ACPI_SUCCESS (Status))
1740                 {
1741                     /* Visit children first, once */
1742 
1743                     if (Op->Asl.Child)
1744                     {
1745                         Level++;
1746                         Op = Op->Asl.Child;
1747                         continue;
1748                     }
1749                 }
1750                 else if (Status != AE_CTRL_DEPTH)
1751                 {
1752                     /* Exit immediately on any error */
1753 
1754                     return (Status);
1755                 }
1756             }
1757 
1758             /* Terminate walk at start op */
1759 
1760             if (Op == StartOp)
1761             {
1762                 break;
1763             }
1764 
1765             /* No more children, visit peers */
1766 
1767             if (Op->Asl.Next)
1768             {
1769                 Op = Op->Asl.Next;
1770                 NodePreviouslyVisited = FALSE;
1771             }
1772             else
1773             {
1774                 /* No children or peers, re-visit parent */
1775 
1776                 if (Level != 0 )
1777                 {
1778                     Level--;
1779                 }
1780                 Op = Op->Asl.Parent;
1781                 NodePreviouslyVisited = TRUE;
1782             }
1783         }
1784         break;
1785 
1786     case ASL_WALK_VISIT_UPWARD:
1787 
1788         while (Op)
1789         {
1790             /* Visit leaf node (no children) or parent node on return trip */
1791 
1792             if ((!Op->Asl.Child) ||
1793                 (NodePreviouslyVisited))
1794             {
1795                 /* Let the callback process the node. */
1796 
1797                 Status = AscendingCallback (Op, Level, Context);
1798                 if (ACPI_FAILURE (Status))
1799                 {
1800                     return (Status);
1801                 }
1802             }
1803             else
1804             {
1805                 /* Visit children first, once */
1806 
1807                 Level++;
1808                 Op = Op->Asl.Child;
1809                 continue;
1810             }
1811 
1812             /* Terminate walk at start op */
1813 
1814             if (Op == StartOp)
1815             {
1816                 break;
1817             }
1818 
1819             /* No more children, visit peers */
1820 
1821             if (Op->Asl.Next)
1822             {
1823                 Op = Op->Asl.Next;
1824                 NodePreviouslyVisited = FALSE;
1825             }
1826             else
1827             {
1828                 /* No children or peers, re-visit parent */
1829 
1830                 if (Level != 0 )
1831                 {
1832                     Level--;
1833                 }
1834                 Op = Op->Asl.Parent;
1835                 NodePreviouslyVisited = TRUE;
1836             }
1837         }
1838         break;
1839 
1840      case ASL_WALK_VISIT_TWICE:
1841 
1842         while (Op)
1843         {
1844             if (NodePreviouslyVisited)
1845             {
1846                 Status = AscendingCallback (Op, Level, Context);
1847                 if (ACPI_FAILURE (Status))
1848                 {
1849                     return (Status);
1850                 }
1851             }
1852             else
1853             {
1854                 /* Let the callback process the node. */
1855 
1856                 Status = DescendingCallback (Op, Level, Context);
1857                 if (ACPI_SUCCESS (Status))
1858                 {
1859                     /* Visit children first, once */
1860 
1861                     if (Op->Asl.Child)
1862                     {
1863                         Level++;
1864                         Op = Op->Asl.Child;
1865                         continue;
1866                     }
1867                 }
1868                 else if (Status != AE_CTRL_DEPTH)
1869                 {
1870                     /* Exit immediately on any error */
1871 
1872                     return (Status);
1873                 }
1874             }
1875 
1876             /* Terminate walk at start op */
1877 
1878             if (Op == StartOp)
1879             {
1880                 break;
1881             }
1882 
1883             /* No more children, visit peers */
1884 
1885             if (Op->Asl.Next)
1886             {
1887                 Op = Op->Asl.Next;
1888                 NodePreviouslyVisited = FALSE;
1889             }
1890             else
1891             {
1892                 /* No children or peers, re-visit parent */
1893 
1894                 if (Level != 0 )
1895                 {
1896                     Level--;
1897                 }
1898                 Op = Op->Asl.Parent;
1899                 NodePreviouslyVisited = TRUE;
1900             }
1901         }
1902         break;
1903 
1904     default:
1905         /* No other types supported */
1906         break;
1907     }
1908 
1909     /* If we get here, the walk completed with no errors */
1910 
1911     return (AE_OK);
1912 }
1913