xref: /freebsd/sys/contrib/dev/acpica/compiler/asltree.c (revision 4657548d18877f64bd02be888406aa5b02bf9b06)
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 <contrib/dev/acpica/compiler/aslcompiler.h>
153 #include "aslcompiler.y.h"
154 #include <contrib/dev/acpica/include/acapps.h>
155 #include <contrib/dev/acpica/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         CvDbgPrint ("trallocatenode=Set latest parse node to this node.\n");
299         CvDbgPrint ("           Op->Asl.ParseOpName = %s\n",
300             Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName);
301         CvDbgPrint ("           Op->Asl.ParseOpcode = 0x%x\n", ParseOpcode);
302 
303         if (Op->Asl.FileChanged)
304         {
305             CvDbgPrint("    file has been changed!\n");
306         }
307 
308         /*
309          * if this parse op's syntax uses () and {} (i.e. Package(1){0x00}) then
310          * set a flag in the comment state. This facilitates paring comments for
311          * these types of opcodes.
312          */
313         if ((CvParseOpBlockType(Op) == (BLOCK_PAREN | BLOCK_BRACE)) &&
314             (ParseOpcode != PARSEOP_DEFINITION_BLOCK))
315         {
316             CvDbgPrint ("Parsing paren/Brace node now!\n");
317             Gbl_CommentState.ParsingParenBraceNode = Op;
318         }
319 
320         if (Gbl_Comment_List_Head)
321         {
322             CvDbgPrint ("Transferring...\n");
323             Op->Asl.CommentList = Gbl_Comment_List_Head;
324             Gbl_Comment_List_Head = NULL;
325             Gbl_Comment_List_Tail = NULL;
326             CvDbgPrint ("    Transferred current comment list to this node.\n");
327             CvDbgPrint ("    %s\n", Op->Asl.CommentList->Comment);
328         }
329         if (Gbl_Inline_Comment_Buffer)
330         {
331             Op->Asl.InlineComment = Gbl_Inline_Comment_Buffer;
332             Gbl_Inline_Comment_Buffer = NULL;
333             CvDbgPrint ("Transferred current inline comment list to this node.\n");
334         }
335 
336     }
337 
338     return (Op);
339 }
340 
341 
342 /*******************************************************************************
343  *
344  * FUNCTION:    TrReleaseNode
345  *
346  * PARAMETERS:  Op            - Op to be released
347  *
348  * RETURN:      None
349  *
350  * DESCRIPTION: "release" a node. In truth, nothing is done since the node
351  *              is part of a larger buffer
352  *
353  ******************************************************************************/
354 
355 void
356 TrReleaseNode (
357     ACPI_PARSE_OBJECT       *Op)
358 {
359 
360     return;
361 }
362 
363 
364 /*******************************************************************************
365  *
366  * FUNCTION:    TrSetCurrentFilename
367  *
368  * PARAMETERS:  Op                  - An existing parse node
369  *
370  * RETURN:      None
371  *
372  * DESCRIPTION: Save the include file filename. Used for debug output only.
373  *
374  ******************************************************************************/
375 
376 void
377 TrSetCurrentFilename (
378     ACPI_PARSE_OBJECT       *Op)
379 {
380     Op->Asl.Filename = Gbl_PreviousIncludeFilename;
381 }
382 
383 
384 /*******************************************************************************
385  *
386  * FUNCTION:    TrUpdateNode
387  *
388  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
389  *              Op                  - An existing parse node
390  *
391  * RETURN:      The updated node
392  *
393  * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
394  *              change an opcode to DEFAULT_ARG so that the node is ignored
395  *              during the code generation. Also used to set generic integers
396  *              to a specific size (8, 16, 32, or 64 bits)
397  *
398  ******************************************************************************/
399 
400 ACPI_PARSE_OBJECT *
401 TrUpdateNode (
402     UINT32                  ParseOpcode,
403     ACPI_PARSE_OBJECT       *Op)
404 {
405 
406     if (!Op)
407     {
408         return (NULL);
409     }
410 
411     DbgPrint (ASL_PARSE_OUTPUT,
412         "\nUpdateNode: Old - %s, New - %s\n",
413         UtGetOpName (Op->Asl.ParseOpcode),
414         UtGetOpName (ParseOpcode));
415 
416     /* Assign new opcode and name */
417 
418     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
419     {
420         switch (ParseOpcode)
421         {
422         case PARSEOP_BYTECONST:
423 
424             Op->Asl.Value.Integer = ACPI_UINT8_MAX;
425             break;
426 
427         case PARSEOP_WORDCONST:
428 
429             Op->Asl.Value.Integer = ACPI_UINT16_MAX;
430             break;
431 
432         case PARSEOP_DWORDCONST:
433 
434             Op->Asl.Value.Integer = ACPI_UINT32_MAX;
435             break;
436 
437         /* Don't need to do the QWORD case */
438 
439         default:
440 
441             /* Don't care about others */
442             break;
443         }
444     }
445 
446     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
447     UtSetParseOpName (Op);
448 
449     /*
450      * For the BYTE, WORD, and DWORD constants, make sure that the integer
451      * that was passed in will actually fit into the data type
452      */
453     switch (ParseOpcode)
454     {
455     case PARSEOP_BYTECONST:
456 
457         UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
458         Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
459         break;
460 
461     case PARSEOP_WORDCONST:
462 
463         UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
464         Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
465         break;
466 
467     case PARSEOP_DWORDCONST:
468 
469         UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
470         Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
471         break;
472 
473     default:
474 
475         /* Don't care about others, don't need to check QWORD */
476 
477         break;
478     }
479 
480     /* Converter: if this is a method invocation, turn off capture comments. */
481     if (Gbl_CaptureComments &&
482         (ParseOpcode == PARSEOP_METHODCALL))
483     {
484         Gbl_CommentState.CaptureComments = FALSE;
485     }
486 
487     return (Op);
488 }
489 
490 
491 /*******************************************************************************
492  *
493  * FUNCTION:    TrPrintNodeCompileFlags
494  *
495  * PARAMETERS:  Flags               - Flags word to be decoded
496  *
497  * RETURN:      None
498  *
499  * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
500  *
501  ******************************************************************************/
502 
503 void
504 TrPrintNodeCompileFlags (
505     UINT32                  Flags)
506 {
507     UINT32                  i;
508     UINT32                  FlagBit = 1;
509     char                    *FlagName = NULL;
510 
511 
512     for (i = 0; i < 32; i++)
513     {
514         switch (Flags & FlagBit)
515         {
516         case NODE_VISITED:
517 
518             FlagName = "NODE_VISITED";
519             break;
520 
521         case NODE_AML_PACKAGE:
522 
523             FlagName = "NODE_AML_PACKAGE";
524             break;
525 
526         case NODE_IS_TARGET:
527 
528             FlagName = "NODE_IS_TARGET";
529             break;
530 
531         case NODE_IS_RESOURCE_DESC:
532 
533             FlagName = "NODE_IS_RESOURCE_DESC";
534             break;
535 
536         case NODE_IS_RESOURCE_FIELD:
537 
538             FlagName = "NODE_IS_RESOURCE_FIELD";
539             break;
540 
541         case NODE_HAS_NO_EXIT:
542 
543             FlagName = "NODE_HAS_NO_EXIT";
544             break;
545 
546         case NODE_IF_HAS_NO_EXIT:
547 
548             FlagName = "NODE_IF_HAS_NO_EXIT";
549             break;
550 
551         case NODE_NAME_INTERNALIZED:
552 
553             FlagName = "NODE_NAME_INTERNALIZED";
554             break;
555 
556         case NODE_METHOD_NO_RETVAL:
557 
558             FlagName = "NODE_METHOD_NO_RETVAL";
559             break;
560 
561         case NODE_METHOD_SOME_NO_RETVAL:
562 
563             FlagName = "NODE_METHOD_SOME_NO_RETVAL";
564             break;
565 
566         case NODE_RESULT_NOT_USED:
567 
568             FlagName = "NODE_RESULT_NOT_USED";
569             break;
570 
571         case NODE_METHOD_TYPED:
572 
573             FlagName = "NODE_METHOD_TYPED";
574             break;
575 
576         case NODE_COULD_NOT_REDUCE:
577 
578             FlagName = "NODE_COULD_NOT_REDUCE";
579             break;
580 
581         case NODE_COMPILE_TIME_CONST:
582 
583             FlagName = "NODE_COMPILE_TIME_CONST";
584             break;
585 
586         case NODE_IS_TERM_ARG:
587 
588             FlagName = "NODE_IS_TERM_ARG";
589             break;
590 
591         case NODE_WAS_ONES_OP:
592 
593             FlagName = "NODE_WAS_ONES_OP";
594             break;
595 
596         case NODE_IS_NAME_DECLARATION:
597 
598             FlagName = "NODE_IS_NAME_DECLARATION";
599             break;
600 
601         case NODE_COMPILER_EMITTED:
602 
603             FlagName = "NODE_COMPILER_EMITTED";
604             break;
605 
606         case NODE_IS_DUPLICATE:
607 
608             FlagName = "NODE_IS_DUPLICATE";
609             break;
610 
611         case NODE_IS_RESOURCE_DATA:
612 
613             FlagName = "NODE_IS_RESOURCE_DATA";
614             break;
615 
616         case NODE_IS_NULL_RETURN:
617 
618             FlagName = "NODE_IS_NULL_RETURN";
619             break;
620 
621         default:
622             break;
623         }
624 
625         if (FlagName)
626         {
627             DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
628             FlagName = NULL;
629         }
630 
631         FlagBit <<= 1;
632     }
633 }
634 
635 
636 /*******************************************************************************
637  *
638  * FUNCTION:    TrSetNodeFlags
639  *
640  * PARAMETERS:  Op                  - An existing parse node
641  *              Flags               - New flags word
642  *
643  * RETURN:      The updated parser op
644  *
645  * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
646  *
647  ******************************************************************************/
648 
649 ACPI_PARSE_OBJECT *
650 TrSetNodeFlags (
651     ACPI_PARSE_OBJECT       *Op,
652     UINT32                  Flags)
653 {
654 
655     if (!Op)
656     {
657         return (NULL);
658     }
659 
660     DbgPrint (ASL_PARSE_OUTPUT,
661         "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
662 
663     TrPrintNodeCompileFlags (Flags);
664     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
665 
666     Op->Asl.CompileFlags |= Flags;
667     return (Op);
668 }
669 
670 
671 /*******************************************************************************
672  *
673  * FUNCTION:    TrSetNodeAmlLength
674  *
675  * PARAMETERS:  Op                  - An existing parse node
676  *              Length              - AML Length
677  *
678  * RETURN:      The updated parser op
679  *
680  * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
681  *              the presence of a node that must be reduced to a fixed length
682  *              constant.
683  *
684  ******************************************************************************/
685 
686 ACPI_PARSE_OBJECT *
687 TrSetNodeAmlLength (
688     ACPI_PARSE_OBJECT       *Op,
689     UINT32                  Length)
690 {
691 
692     DbgPrint (ASL_PARSE_OUTPUT,
693         "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
694 
695     if (!Op)
696     {
697         return (NULL);
698     }
699 
700     Op->Asl.AmlLength = Length;
701     return (Op);
702 }
703 
704 
705 /*******************************************************************************
706  *
707  * FUNCTION:    TrSetEndLineNumber
708  *
709  * PARAMETERS:  Op                - An existing parse node
710  *
711  * RETURN:      None.
712  *
713  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
714  *              parse node to the current line numbers.
715  *
716  ******************************************************************************/
717 
718 void
719 TrSetEndLineNumber (
720     ACPI_PARSE_OBJECT       *Op)
721 {
722 
723     /* If the end line # is already set, just return */
724 
725     if (Op->Asl.EndLine)
726     {
727         return;
728     }
729 
730     Op->Asl.EndLine = Gbl_CurrentLineNumber;
731     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
732 }
733 
734 
735 /*******************************************************************************
736  *
737  * FUNCTION:    TrCreateAssignmentNode
738  *
739  * PARAMETERS:  Target              - Assignment target
740  *              Source              - Assignment source
741  *
742  * RETURN:      Pointer to the new node. Aborts on allocation failure
743  *
744  * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
745  *              tree if possible to utilize the last argument of the math
746  *              operators which is a target operand -- thus saving invocation
747  *              of and additional Store() operator. An optimization.
748  *
749  ******************************************************************************/
750 
751 ACPI_PARSE_OBJECT *
752 TrCreateAssignmentNode (
753     ACPI_PARSE_OBJECT       *Target,
754     ACPI_PARSE_OBJECT       *Source)
755 {
756     ACPI_PARSE_OBJECT       *TargetOp;
757     ACPI_PARSE_OBJECT       *SourceOp1;
758     ACPI_PARSE_OBJECT       *SourceOp2;
759     ACPI_PARSE_OBJECT       *Operator;
760 
761 
762     DbgPrint (ASL_PARSE_OUTPUT,
763         "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
764         Source->Asl.LineNumber, Source->Asl.EndLine,
765         UtGetOpName (Source->Asl.ParseOpcode),
766         UtGetOpName (Target->Asl.ParseOpcode));
767 
768     TrSetNodeFlags (Target, NODE_IS_TARGET);
769 
770     switch (Source->Asl.ParseOpcode)
771     {
772     /*
773      * Only these operators can be optimized because they have
774      * a target operand
775      */
776     case PARSEOP_ADD:
777     case PARSEOP_AND:
778     case PARSEOP_DIVIDE:
779     case PARSEOP_INDEX:
780     case PARSEOP_MOD:
781     case PARSEOP_MULTIPLY:
782     case PARSEOP_NOT:
783     case PARSEOP_OR:
784     case PARSEOP_SHIFTLEFT:
785     case PARSEOP_SHIFTRIGHT:
786     case PARSEOP_SUBTRACT:
787     case PARSEOP_XOR:
788 
789         break;
790 
791     /* Otherwise, just create a normal Store operator */
792 
793     default:
794 
795         goto CannotOptimize;
796     }
797 
798     /*
799      * Transform the parse tree such that the target is moved to the
800      * last operand of the operator
801      */
802     SourceOp1 = Source->Asl.Child;
803     SourceOp2 = SourceOp1->Asl.Next;
804 
805     /* NOT only has one operand, but has a target */
806 
807     if (Source->Asl.ParseOpcode == PARSEOP_NOT)
808     {
809         SourceOp2 = SourceOp1;
810     }
811 
812     /* DIVIDE has an extra target operand (remainder) */
813 
814     if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
815     {
816         SourceOp2 = SourceOp2->Asl.Next;
817     }
818 
819     TargetOp = SourceOp2->Asl.Next;
820 
821     /*
822      * Can't perform this optimization if there already is a target
823      * for the operator (ZERO is a "no target" placeholder).
824      */
825     if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
826     {
827         goto CannotOptimize;
828     }
829 
830     /* Link in the target as the final operand */
831 
832     SourceOp2->Asl.Next = Target;
833     Target->Asl.Parent = Source;
834 
835     return (Source);
836 
837 
838 CannotOptimize:
839 
840     Operator = TrAllocateNode (PARSEOP_STORE);
841     TrLinkChildren (Operator, 2, Source, Target);
842 
843     /* Set the appropriate line numbers for the new node */
844 
845     Operator->Asl.LineNumber        = Target->Asl.LineNumber;
846     Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
847     Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
848     Operator->Asl.Column            = Target->Asl.Column;
849 
850     return (Operator);
851 }
852 
853 
854 /*******************************************************************************
855  *
856  * FUNCTION:    TrCreateLeafNode
857  *
858  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
859  *
860  * RETURN:      Pointer to the new node. Aborts on allocation failure
861  *
862  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
863  *              assigned to the node)
864  *
865  ******************************************************************************/
866 
867 ACPI_PARSE_OBJECT *
868 TrCreateLeafNode (
869     UINT32                  ParseOpcode)
870 {
871     ACPI_PARSE_OBJECT       *Op;
872 
873 
874     Op = TrAllocateNode (ParseOpcode);
875 
876     DbgPrint (ASL_PARSE_OUTPUT,
877         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
878         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
879 
880     return (Op);
881 }
882 
883 
884 /*******************************************************************************
885  *
886  * FUNCTION:    TrCreateNullTarget
887  *
888  * PARAMETERS:  None
889  *
890  * RETURN:      Pointer to the new node. Aborts on allocation failure
891  *
892  * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
893  *              specification to be a zero AML opcode, and indicates that
894  *              no target has been specified for the parent operation
895  *
896  ******************************************************************************/
897 
898 ACPI_PARSE_OBJECT *
899 TrCreateNullTarget (
900     void)
901 {
902     ACPI_PARSE_OBJECT       *Op;
903 
904 
905     Op = TrAllocateNode (PARSEOP_ZERO);
906     Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
907 
908     DbgPrint (ASL_PARSE_OUTPUT,
909         "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
910         Op->Asl.LineNumber, Op->Asl.Column, Op,
911         UtGetOpName (Op->Asl.ParseOpcode));
912 
913     return (Op);
914 }
915 
916 
917 /*******************************************************************************
918  *
919  * FUNCTION:    TrCreateConstantLeafNode
920  *
921  * PARAMETERS:  ParseOpcode         - The constant opcode
922  *
923  * RETURN:      Pointer to the new node. Aborts on allocation failure
924  *
925  * DESCRIPTION: Create a leaf node (no children or peers) for one of the
926  *              special constants - __LINE__, __FILE__, and __DATE__.
927  *
928  * Note: An implemenation of __FUNC__ cannot happen here because we don't
929  * have a full parse tree at this time and cannot find the parent control
930  * method. If it is ever needed, __FUNC__ must be implemented later, after
931  * the parse tree has been fully constructed.
932  *
933  ******************************************************************************/
934 
935 ACPI_PARSE_OBJECT *
936 TrCreateConstantLeafNode (
937     UINT32                  ParseOpcode)
938 {
939     ACPI_PARSE_OBJECT       *Op = NULL;
940     time_t                  CurrentTime;
941     char                    *StaticTimeString;
942     char                    *TimeString;
943     char                    *Filename;
944 
945 
946     switch (ParseOpcode)
947     {
948     case PARSEOP___LINE__:
949 
950         Op = TrAllocateNode (PARSEOP_INTEGER);
951         Op->Asl.Value.Integer = Op->Asl.LineNumber;
952         break;
953 
954     case PARSEOP___PATH__:
955 
956         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
957 
958         /* Op.Asl.Filename contains the full pathname to the file */
959 
960         Op->Asl.Value.String = Op->Asl.Filename;
961         break;
962 
963     case PARSEOP___FILE__:
964 
965         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
966 
967         /* Get the simple filename from the full path */
968 
969         FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
970         Op->Asl.Value.String = Filename;
971         break;
972 
973     case PARSEOP___DATE__:
974 
975         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
976 
977         /* Get a copy of the current time */
978 
979         CurrentTime = time (NULL);
980         StaticTimeString = ctime (&CurrentTime);
981         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
982         strcpy (TimeString, StaticTimeString);
983 
984         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
985         Op->Asl.Value.String = TimeString;
986         break;
987 
988     default: /* This would be an internal error */
989 
990         return (NULL);
991     }
992 
993     DbgPrint (ASL_PARSE_OUTPUT,
994         "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  "
995         "Op %s  Value %8.8X%8.8X  \n",
996         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
997         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
998     return (Op);
999 }
1000 
1001 
1002 /*******************************************************************************
1003  *
1004  * FUNCTION:    TrCreateTargetOperand
1005  *
1006  * PARAMETERS:  OriginalOp          - Op to be copied
1007  *
1008  * RETURN:      Pointer to the new node. Aborts on allocation failure
1009  *
1010  * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
1011  *              expressions where the target is the same as one of the
1012  *              operands. A new node and subtree must be created from the
1013  *              original so that the parse tree can be linked properly.
1014  *
1015  * NOTE:        This code is specific to target operands that are the last
1016  *              operand in an ASL/AML operator. Meaning that the top-level
1017  *              parse Op in a possible subtree has a NULL Next pointer.
1018  *              This simplifies the recursion.
1019  *
1020  *              Subtree example:
1021  *                  DeRefOf (Local1) += 32
1022  *
1023  *              This gets converted to:
1024  *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
1025  *
1026  *              Each DeRefOf has a single child, Local1. Even more complex
1027  *              subtrees can be created via the Index and DeRefOf operators.
1028  *
1029  ******************************************************************************/
1030 
1031 ACPI_PARSE_OBJECT *
1032 TrCreateTargetOperand (
1033     ACPI_PARSE_OBJECT       *OriginalOp,
1034     ACPI_PARSE_OBJECT       *ParentOp)
1035 {
1036     ACPI_PARSE_OBJECT       *Op;
1037 
1038 
1039     if (!OriginalOp)
1040     {
1041         return (NULL);
1042     }
1043 
1044     Op = TrGetNextNode ();
1045 
1046     /* Copy the pertinent values (omit link pointer fields) */
1047 
1048     Op->Asl.Value               = OriginalOp->Asl.Value;
1049     Op->Asl.Filename            = OriginalOp->Asl.Filename;
1050     Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
1051     Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
1052     Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
1053     Op->Asl.Column              = OriginalOp->Asl.Column;
1054     Op->Asl.Flags               = OriginalOp->Asl.Flags;
1055     Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
1056     Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
1057     Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
1058     Op->Asl.Parent              = ParentOp;
1059     UtSetParseOpName (Op);
1060 
1061     /* Copy a possible subtree below this node */
1062 
1063     if (OriginalOp->Asl.Child)
1064     {
1065         Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
1066     }
1067 
1068     if (OriginalOp->Asl.Next) /* Null for top-level node */
1069     {
1070         Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
1071     }
1072 
1073     return (Op);
1074 }
1075 
1076 
1077 /*******************************************************************************
1078  *
1079  * FUNCTION:    TrCreateValuedLeafNode
1080  *
1081  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
1082  *              Value               - Value to be assigned to the node
1083  *
1084  * RETURN:      Pointer to the new node. Aborts on allocation failure
1085  *
1086  * DESCRIPTION: Create a leaf node (no children or peers) with a value
1087  *              assigned to it
1088  *
1089  ******************************************************************************/
1090 
1091 ACPI_PARSE_OBJECT *
1092 TrCreateValuedLeafNode (
1093     UINT32                  ParseOpcode,
1094     UINT64                  Value)
1095 {
1096     ACPI_PARSE_OBJECT       *Op;
1097 
1098 
1099     Op = TrAllocateNode (ParseOpcode);
1100 
1101     DbgPrint (ASL_PARSE_OUTPUT,
1102         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  "
1103         "Op %s  Value %8.8X%8.8X  ",
1104         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
1105         ACPI_FORMAT_UINT64 (Value));
1106     Op->Asl.Value.Integer = Value;
1107 
1108     switch (ParseOpcode)
1109     {
1110     case PARSEOP_STRING_LITERAL:
1111 
1112         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
1113         break;
1114 
1115     case PARSEOP_NAMESEG:
1116 
1117         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
1118         break;
1119 
1120     case PARSEOP_NAMESTRING:
1121 
1122         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
1123         break;
1124 
1125     case PARSEOP_EISAID:
1126 
1127         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
1128         break;
1129 
1130     case PARSEOP_METHOD:
1131 
1132         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
1133         break;
1134 
1135     case PARSEOP_INTEGER:
1136 
1137         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
1138             ACPI_FORMAT_UINT64 (Value));
1139         break;
1140 
1141     default:
1142 
1143         break;
1144     }
1145 
1146     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1147     return (Op);
1148 }
1149 
1150 
1151 /*******************************************************************************
1152  *
1153  * FUNCTION:    TrCreateNode
1154  *
1155  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
1156  *              NumChildren         - Number of children to follow
1157  *              ...                 - A list of child nodes to link to the new
1158  *                                    node. NumChildren long.
1159  *
1160  * RETURN:      Pointer to the new node. Aborts on allocation failure
1161  *
1162  * DESCRIPTION: Create a new parse node and link together a list of child
1163  *              nodes underneath the new node.
1164  *
1165  ******************************************************************************/
1166 
1167 ACPI_PARSE_OBJECT *
1168 TrCreateNode (
1169     UINT32                  ParseOpcode,
1170     UINT32                  NumChildren,
1171     ...)
1172 {
1173     ACPI_PARSE_OBJECT       *Op;
1174     ACPI_PARSE_OBJECT       *Child;
1175     ACPI_PARSE_OBJECT       *PrevChild;
1176     va_list                 ap;
1177     UINT32                  i;
1178     BOOLEAN                 FirstChild;
1179 
1180 
1181     va_start (ap, NumChildren);
1182 
1183     /* Allocate one new node */
1184 
1185     Op = TrAllocateNode (ParseOpcode);
1186 
1187     DbgPrint (ASL_PARSE_OUTPUT,
1188         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
1189         Op->Asl.LineNumber, Op->Asl.Column, Op,
1190         NumChildren, UtGetOpName(ParseOpcode));
1191 
1192     /* Some extra debug output based on the parse opcode */
1193 
1194     switch (ParseOpcode)
1195     {
1196     case PARSEOP_ASL_CODE:
1197 
1198         Gbl_ParseTreeRoot = Op;
1199         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1200         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1201         break;
1202 
1203     case PARSEOP_DEFINITION_BLOCK:
1204 
1205         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1206         break;
1207 
1208     case PARSEOP_OPERATIONREGION:
1209 
1210         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1211         break;
1212 
1213     case PARSEOP_OR:
1214 
1215         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1216         break;
1217 
1218     default:
1219 
1220         /* Nothing to do for other opcodes */
1221 
1222         break;
1223     }
1224 
1225     /* Link the new node to its children */
1226 
1227     PrevChild = NULL;
1228     FirstChild = TRUE;
1229     for (i = 0; i < NumChildren; i++)
1230     {
1231         /* Get the next child */
1232 
1233         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1234         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1235 
1236         /*
1237          * If child is NULL, this means that an optional argument
1238          * was omitted. We must create a placeholder with a special
1239          * opcode (DEFAULT_ARG) so that the code generator will know
1240          * that it must emit the correct default for this argument
1241          */
1242         if (!Child)
1243         {
1244             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1245         }
1246 
1247         /* Link first child to parent */
1248 
1249         if (FirstChild)
1250         {
1251             FirstChild = FALSE;
1252             Op->Asl.Child = Child;
1253 
1254             /*
1255              * For the ASL-/ASL+ converter: if the ParseOp is a connection,
1256              * external, offset or accessAs, it means that the comments in the
1257              * FirstChild belongs to their parent due to the parsing order in
1258              * the .y files. To correct this, take the comments in the
1259              * FirstChild place it in the parent. This also means that
1260              * legitimate comments for the child gets put to the parent.
1261              */
1262             if (Gbl_CaptureComments &&
1263                 ((ParseOpcode == PARSEOP_CONNECTION) ||
1264                  (ParseOpcode == PARSEOP_EXTERNAL) ||
1265                  (ParseOpcode == PARSEOP_OFFSET) ||
1266                  (ParseOpcode == PARSEOP_ACCESSAS)))
1267             {
1268                 Op->Asl.CommentList      = Child->Asl.CommentList;
1269                 Op->Asl.EndBlkComment    = Child->Asl.EndBlkComment;
1270                 Op->Asl.InlineComment    = Child->Asl.InlineComment;
1271                 Op->Asl.FileChanged      = Child->Asl.FileChanged;
1272 
1273                 Child->Asl.CommentList   = NULL;
1274                 Child->Asl.EndBlkComment = NULL;
1275                 Child->Asl.InlineComment = NULL;
1276                 Child->Asl.FileChanged   = FALSE;
1277 
1278                 /*
1279                  * These do not need to be "passed off". They can be copied
1280                  * because the code for these opcodes should be printed in the
1281                  * same file.
1282                  */
1283                 Op->Asl.Filename         = Child->Asl.Filename;
1284                 Op->Asl.ParentFilename   = Child->Asl.ParentFilename;
1285             }
1286         }
1287 
1288         /* Point all children to parent */
1289 
1290         Child->Asl.Parent = Op;
1291 
1292         /* Link children in a peer list */
1293 
1294         if (PrevChild)
1295         {
1296             PrevChild->Asl.Next = Child;
1297         };
1298 
1299         /* Get the comment from last child in the resource template call */
1300 
1301         if (Gbl_CaptureComments &&
1302             (Op->Asl.ParseOpcode == PARSEOP_RESOURCETEMPLATE))
1303         {
1304             CvDbgPrint ("Transferred current comment list to this node.\n");
1305             Op->Asl.CommentList = Child->Asl.CommentList;
1306             Child->Asl.CommentList = NULL;
1307             Op->Asl.InlineComment = Child->Asl.InlineComment;
1308             Child->Asl.InlineComment = NULL;
1309         }
1310 
1311         /*
1312          * This child might be a list, point all nodes in the list
1313          * to the same parent
1314          */
1315         while (Child->Asl.Next)
1316         {
1317             Child = Child->Asl.Next;
1318             Child->Asl.Parent = Op;
1319         }
1320 
1321         PrevChild = Child;
1322     }
1323     va_end(ap);
1324 
1325     DbgPrint (ASL_PARSE_OUTPUT, "\n");
1326     return (Op);
1327 }
1328 
1329 
1330 /*******************************************************************************
1331  *
1332  * FUNCTION:    TrLinkChildren
1333  *
1334  * PARAMETERS:  Op                - An existing parse node
1335  *              NumChildren        - Number of children to follow
1336  *              ...                - A list of child nodes to link to the new
1337  *                                   node. NumChildren long.
1338  *
1339  * RETURN:      The updated (linked) node
1340  *
1341  * DESCRIPTION: Link a group of nodes to an existing parse node
1342  *
1343  ******************************************************************************/
1344 
1345 ACPI_PARSE_OBJECT *
1346 TrLinkChildren (
1347     ACPI_PARSE_OBJECT       *Op,
1348     UINT32                  NumChildren,
1349     ...)
1350 {
1351     ACPI_PARSE_OBJECT       *Child;
1352     ACPI_PARSE_OBJECT       *PrevChild;
1353     va_list                 ap;
1354     UINT32                  i;
1355     BOOLEAN                 FirstChild;
1356 
1357 
1358     va_start (ap, NumChildren);
1359 
1360 
1361     TrSetEndLineNumber (Op);
1362 
1363     DbgPrint (ASL_PARSE_OUTPUT,
1364         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
1365         Op->Asl.LineNumber, Op->Asl.EndLine,
1366         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1367 
1368     switch (Op->Asl.ParseOpcode)
1369     {
1370     case PARSEOP_ASL_CODE:
1371 
1372         Gbl_ParseTreeRoot = Op;
1373         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1374         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1375         break;
1376 
1377     case PARSEOP_DEFINITION_BLOCK:
1378 
1379         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1380         break;
1381 
1382     case PARSEOP_OPERATIONREGION:
1383 
1384         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1385         break;
1386 
1387     case PARSEOP_OR:
1388 
1389         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1390         break;
1391 
1392     default:
1393 
1394         /* Nothing to do for other opcodes */
1395 
1396         break;
1397     }
1398 
1399     /* The following is for capturing comments */
1400 
1401     if(Gbl_CaptureComments)
1402     {
1403         /*
1404          * If there are "regular comments" detected at this point,
1405          * then is an endBlk comment. Categorize it as so and distribute
1406          * all regular comments to this parse node.
1407          */
1408         if (Gbl_Comment_List_Head)
1409         {
1410             Op->Asl.EndBlkComment = Gbl_Comment_List_Head;
1411             CvDbgPrint ("EndBlk Comment for %s: %s",
1412                 Op->Asl.ParseOpName, Gbl_Comment_List_Head->Comment);
1413             Gbl_Comment_List_Head = NULL;
1414             Gbl_Comment_List_Tail = NULL;
1415         }
1416     }
1417 
1418     /* Link the new node to it's children */
1419 
1420     PrevChild = NULL;
1421     FirstChild = TRUE;
1422     for (i = 0; i < NumChildren; i++)
1423     {
1424         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1425 
1426         if ((Child == PrevChild) && (Child != NULL))
1427         {
1428             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1429                 "Child node list invalid");
1430             va_end(ap);
1431             return (Op);
1432         }
1433 
1434         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1435 
1436         /*
1437          * If child is NULL, this means that an optional argument
1438          * was omitted. We must create a placeholder with a special
1439          * opcode (DEFAULT_ARG) so that the code generator will know
1440          * that it must emit the correct default for this argument
1441          */
1442         if (!Child)
1443         {
1444             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1445         }
1446 
1447         /* Link first child to parent */
1448 
1449         if (FirstChild)
1450         {
1451             FirstChild = FALSE;
1452             Op->Asl.Child = Child;
1453         }
1454 
1455         /* Point all children to parent */
1456 
1457         Child->Asl.Parent = Op;
1458 
1459         /* Link children in a peer list */
1460 
1461         if (PrevChild)
1462         {
1463             PrevChild->Asl.Next = Child;
1464         };
1465 
1466         /*
1467          * This child might be a list, point all nodes in the list
1468          * to the same parent
1469          */
1470         while (Child->Asl.Next)
1471         {
1472             Child = Child->Asl.Next;
1473             Child->Asl.Parent = Op;
1474         }
1475 
1476         PrevChild = Child;
1477     }
1478 
1479     va_end(ap);
1480     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1481 
1482 
1483     if(Gbl_CaptureComments)
1484     {
1485         Gbl_CommentState.Latest_Parse_Node = Op;
1486         CvDbgPrint ("trlinkchildren=====Set latest parse node to this node.\n");
1487     }
1488     return (Op);
1489 }
1490 
1491 
1492 /*******************************************************************************
1493  *
1494  * FUNCTION:    TrLinkPeerNode
1495  *
1496  * PARAMETERS:  Op1           - First peer
1497  *              Op2           - Second peer
1498  *
1499  * RETURN:      Op1 or the non-null node.
1500  *
1501  * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1502  *
1503  ******************************************************************************/
1504 
1505 ACPI_PARSE_OBJECT *
1506 TrLinkPeerNode (
1507     ACPI_PARSE_OBJECT       *Op1,
1508     ACPI_PARSE_OBJECT       *Op2)
1509 {
1510     ACPI_PARSE_OBJECT       *Next;
1511 
1512 
1513     DbgPrint (ASL_PARSE_OUTPUT,
1514         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1515         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1516         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1517 
1518 
1519     if ((!Op1) && (!Op2))
1520     {
1521         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1522         return (Op1);
1523     }
1524 
1525     /* If one of the nodes is null, just return the non-null node */
1526 
1527     if (!Op2)
1528     {
1529         return (Op1);
1530     }
1531 
1532     if (!Op1)
1533     {
1534         return (Op2);
1535     }
1536 
1537     if (Op1 == Op2)
1538     {
1539         DbgPrint (ASL_DEBUG_OUTPUT,
1540             "\n************* Internal error, linking node to itself %p\n",
1541             Op1);
1542         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1543             "Linking node to itself");
1544         return (Op1);
1545     }
1546 
1547     Op1->Asl.Parent = Op2->Asl.Parent;
1548 
1549     /*
1550      * Op 1 may already have a peer list (such as an IF/ELSE pair),
1551      * so we must walk to the end of the list and attach the new
1552      * peer at the end
1553      */
1554     Next = Op1;
1555     while (Next->Asl.Next)
1556     {
1557         Next = Next->Asl.Next;
1558     }
1559 
1560     Next->Asl.Next = Op2;
1561     return (Op1);
1562 }
1563 
1564 
1565 /*******************************************************************************
1566  *
1567  * FUNCTION:    TrLinkPeerNodes
1568  *
1569  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
1570  *              ...                 - A list of nodes to link together as peers
1571  *
1572  * RETURN:      The first node in the list (head of the peer list)
1573  *
1574  * DESCRIPTION: Link together an arbitrary number of peer nodes.
1575  *
1576  ******************************************************************************/
1577 
1578 ACPI_PARSE_OBJECT *
1579 TrLinkPeerNodes (
1580     UINT32                  NumPeers,
1581     ...)
1582 {
1583     ACPI_PARSE_OBJECT       *This;
1584     ACPI_PARSE_OBJECT       *Next;
1585     va_list                 ap;
1586     UINT32                  i;
1587     ACPI_PARSE_OBJECT       *Start;
1588 
1589 
1590     DbgPrint (ASL_PARSE_OUTPUT,
1591         "\nLinkPeerNodes: (%u) ", NumPeers);
1592 
1593     va_start (ap, NumPeers);
1594     This = va_arg (ap, ACPI_PARSE_OBJECT *);
1595     Start = This;
1596 
1597     /*
1598      * Link all peers
1599      */
1600     for (i = 0; i < (NumPeers -1); i++)
1601     {
1602         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1603 
1604         while (This->Asl.Next)
1605         {
1606             This = This->Asl.Next;
1607         }
1608 
1609         /* Get another peer node */
1610 
1611         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1612         if (!Next)
1613         {
1614             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1615         }
1616 
1617         /* link new node to the current node */
1618 
1619         This->Asl.Next = Next;
1620         This = Next;
1621     }
1622     va_end (ap);
1623 
1624     DbgPrint (ASL_PARSE_OUTPUT,"\n");
1625     return (Start);
1626 }
1627 
1628 
1629 /*******************************************************************************
1630  *
1631  * FUNCTION:    TrLinkChildNode
1632  *
1633  * PARAMETERS:  Op1           - Parent node
1634  *              Op2           - Op to become a child
1635  *
1636  * RETURN:      The parent node
1637  *
1638  * DESCRIPTION: Link two nodes together as a parent and child
1639  *
1640  ******************************************************************************/
1641 
1642 ACPI_PARSE_OBJECT *
1643 TrLinkChildNode (
1644     ACPI_PARSE_OBJECT       *Op1,
1645     ACPI_PARSE_OBJECT       *Op2)
1646 {
1647     ACPI_PARSE_OBJECT       *Next;
1648 
1649 
1650     DbgPrint (ASL_PARSE_OUTPUT,
1651         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1652         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1653         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1654 
1655     /*
1656      * Converter: if TrLinkChildNode is called to link a method call,
1657      * turn on capture comments as it signifies that we are done parsing
1658      * a method call.
1659      */
1660     if (Gbl_CaptureComments)
1661     {
1662         if (Op1->Asl.ParseOpcode == PARSEOP_METHODCALL)
1663         {
1664             Gbl_CommentState.CaptureComments = TRUE;
1665         }
1666         Gbl_CommentState.Latest_Parse_Node = Op1;
1667     }
1668     if (!Op1 || !Op2)
1669     {
1670         return (Op1);
1671     }
1672 
1673     Op1->Asl.Child = Op2;
1674 
1675     /* Set the child and all peers of the child to point to the parent */
1676 
1677     Next = Op2;
1678     while (Next)
1679     {
1680         Next->Asl.Parent = Op1;
1681         Next = Next->Asl.Next;
1682     }
1683 
1684     return (Op1);
1685 }
1686 
1687 
1688 /*******************************************************************************
1689  *
1690  * FUNCTION:    TrWalkParseTree
1691  *
1692  * PARAMETERS:  Visitation              - Type of walk
1693  *              DescendingCallback      - Called during tree descent
1694  *              AscendingCallback       - Called during tree ascent
1695  *              Context                 - To be passed to the callbacks
1696  *
1697  * RETURN:      Status from callback(s)
1698  *
1699  * DESCRIPTION: Walk the entire parse tree.
1700  *
1701  ******************************************************************************/
1702 
1703 ACPI_STATUS
1704 TrWalkParseTree (
1705     ACPI_PARSE_OBJECT       *Op,
1706     UINT32                  Visitation,
1707     ASL_WALK_CALLBACK       DescendingCallback,
1708     ASL_WALK_CALLBACK       AscendingCallback,
1709     void                    *Context)
1710 {
1711     UINT32                  Level;
1712     BOOLEAN                 NodePreviouslyVisited;
1713     ACPI_PARSE_OBJECT       *StartOp = Op;
1714     ACPI_STATUS             Status;
1715 
1716 
1717     if (!Gbl_ParseTreeRoot)
1718     {
1719         return (AE_OK);
1720     }
1721 
1722     Level = 0;
1723     NodePreviouslyVisited = FALSE;
1724 
1725     switch (Visitation)
1726     {
1727     case ASL_WALK_VISIT_DOWNWARD:
1728 
1729         while (Op)
1730         {
1731             if (!NodePreviouslyVisited)
1732             {
1733                 /* Let the callback process the node. */
1734 
1735                 Status = DescendingCallback (Op, Level, Context);
1736                 if (ACPI_SUCCESS (Status))
1737                 {
1738                     /* Visit children first, once */
1739 
1740                     if (Op->Asl.Child)
1741                     {
1742                         Level++;
1743                         Op = Op->Asl.Child;
1744                         continue;
1745                     }
1746                 }
1747                 else if (Status != AE_CTRL_DEPTH)
1748                 {
1749                     /* Exit immediately on any error */
1750 
1751                     return (Status);
1752                 }
1753             }
1754 
1755             /* Terminate walk at start op */
1756 
1757             if (Op == StartOp)
1758             {
1759                 break;
1760             }
1761 
1762             /* No more children, visit peers */
1763 
1764             if (Op->Asl.Next)
1765             {
1766                 Op = Op->Asl.Next;
1767                 NodePreviouslyVisited = FALSE;
1768             }
1769             else
1770             {
1771                 /* No children or peers, re-visit parent */
1772 
1773                 if (Level != 0 )
1774                 {
1775                     Level--;
1776                 }
1777                 Op = Op->Asl.Parent;
1778                 NodePreviouslyVisited = TRUE;
1779             }
1780         }
1781         break;
1782 
1783     case ASL_WALK_VISIT_UPWARD:
1784 
1785         while (Op)
1786         {
1787             /* Visit leaf node (no children) or parent node on return trip */
1788 
1789             if ((!Op->Asl.Child) ||
1790                 (NodePreviouslyVisited))
1791             {
1792                 /* Let the callback process the node. */
1793 
1794                 Status = AscendingCallback (Op, Level, Context);
1795                 if (ACPI_FAILURE (Status))
1796                 {
1797                     return (Status);
1798                 }
1799             }
1800             else
1801             {
1802                 /* Visit children first, once */
1803 
1804                 Level++;
1805                 Op = Op->Asl.Child;
1806                 continue;
1807             }
1808 
1809             /* Terminate walk at start op */
1810 
1811             if (Op == StartOp)
1812             {
1813                 break;
1814             }
1815 
1816             /* No more children, visit peers */
1817 
1818             if (Op->Asl.Next)
1819             {
1820                 Op = Op->Asl.Next;
1821                 NodePreviouslyVisited = FALSE;
1822             }
1823             else
1824             {
1825                 /* No children or peers, re-visit parent */
1826 
1827                 if (Level != 0 )
1828                 {
1829                     Level--;
1830                 }
1831                 Op = Op->Asl.Parent;
1832                 NodePreviouslyVisited = TRUE;
1833             }
1834         }
1835         break;
1836 
1837      case ASL_WALK_VISIT_TWICE:
1838 
1839         while (Op)
1840         {
1841             if (NodePreviouslyVisited)
1842             {
1843                 Status = AscendingCallback (Op, Level, Context);
1844                 if (ACPI_FAILURE (Status))
1845                 {
1846                     return (Status);
1847                 }
1848             }
1849             else
1850             {
1851                 /* Let the callback process the node. */
1852 
1853                 Status = DescendingCallback (Op, Level, Context);
1854                 if (ACPI_SUCCESS (Status))
1855                 {
1856                     /* Visit children first, once */
1857 
1858                     if (Op->Asl.Child)
1859                     {
1860                         Level++;
1861                         Op = Op->Asl.Child;
1862                         continue;
1863                     }
1864                 }
1865                 else if (Status != AE_CTRL_DEPTH)
1866                 {
1867                     /* Exit immediately on any error */
1868 
1869                     return (Status);
1870                 }
1871             }
1872 
1873             /* Terminate walk at start op */
1874 
1875             if (Op == StartOp)
1876             {
1877                 break;
1878             }
1879 
1880             /* No more children, visit peers */
1881 
1882             if (Op->Asl.Next)
1883             {
1884                 Op = Op->Asl.Next;
1885                 NodePreviouslyVisited = FALSE;
1886             }
1887             else
1888             {
1889                 /* No children or peers, re-visit parent */
1890 
1891                 if (Level != 0 )
1892                 {
1893                     Level--;
1894                 }
1895                 Op = Op->Asl.Parent;
1896                 NodePreviouslyVisited = TRUE;
1897             }
1898         }
1899         break;
1900 
1901     default:
1902         /* No other types supported */
1903         break;
1904     }
1905 
1906     /* If we get here, the walk completed with no errors */
1907 
1908     return (AE_OK);
1909 }
1910