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 - 2020, 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
156#define _COMPONENT          ACPI_COMPILER
157        ACPI_MODULE_NAME    ("asltree")
158
159
160/*******************************************************************************
161 *
162 * FUNCTION:    TrSetOpIntegerValue
163 *
164 * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the op
165 *              Op                  - An existing parse op
166 *
167 * RETURN:      The updated op
168 *
169 * DESCRIPTION: Used to set the integer value of a op,
170 *              usually to a specific size (8, 16, 32, or 64 bits)
171 *
172 ******************************************************************************/
173
174ACPI_PARSE_OBJECT *
175TrSetOpIntegerValue (
176    UINT32                  ParseOpcode,
177    ACPI_PARSE_OBJECT       *Op)
178{
179
180    if (!Op)
181    {
182        return (NULL);
183    }
184
185    DbgPrint (ASL_PARSE_OUTPUT,
186        "\nUpdateOp: Old - %s, New - %s\n",
187        UtGetOpName (Op->Asl.ParseOpcode),
188        UtGetOpName (ParseOpcode));
189
190    /* Assign new opcode and name */
191
192    if (Op->Asl.ParseOpcode == PARSEOP_ONES)
193    {
194        switch (ParseOpcode)
195        {
196        case PARSEOP_BYTECONST:
197
198            Op->Asl.Value.Integer = ACPI_UINT8_MAX;
199            break;
200
201        case PARSEOP_WORDCONST:
202
203            Op->Asl.Value.Integer = ACPI_UINT16_MAX;
204            break;
205
206        case PARSEOP_DWORDCONST:
207
208            Op->Asl.Value.Integer = ACPI_UINT32_MAX;
209            break;
210
211        /* Don't need to do the QWORD case */
212
213        default:
214
215            /* Don't care about others */
216            break;
217        }
218    }
219
220    Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
221    UtSetParseOpName (Op);
222
223    /*
224     * For the BYTE, WORD, and DWORD constants, make sure that the integer
225     * that was passed in will actually fit into the data type
226     */
227    switch (ParseOpcode)
228    {
229    case PARSEOP_BYTECONST:
230
231        UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
232        Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
233        break;
234
235    case PARSEOP_WORDCONST:
236
237        UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
238        Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
239        break;
240
241    case PARSEOP_DWORDCONST:
242
243        UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
244        Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
245        break;
246
247    default:
248
249        /* Don't care about others, don't need to check QWORD */
250
251        break;
252    }
253
254    /* Converter: if this is a method invocation, turn off capture comments */
255
256    if (AcpiGbl_CaptureComments &&
257        (ParseOpcode == PARSEOP_METHODCALL))
258    {
259        AslGbl_CommentState.CaptureComments = FALSE;
260    }
261
262    return (Op);
263}
264
265
266/*******************************************************************************
267 *
268 * FUNCTION:    TrSetOpFlags
269 *
270 * PARAMETERS:  Op                  - An existing parse op
271 *              Flags               - New flags word
272 *
273 * RETURN:      The updated parser op
274 *
275 * DESCRIPTION: Set bits in the op flags word. Will not clear bits, only set
276 *
277 ******************************************************************************/
278
279ACPI_PARSE_OBJECT *
280TrSetOpFlags (
281    ACPI_PARSE_OBJECT       *Op,
282    UINT32                  Flags)
283{
284
285    if (!Op)
286    {
287        return (NULL);
288    }
289
290    DbgPrint (ASL_PARSE_OUTPUT,
291        "\nSetOpFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
292
293    TrPrintOpFlags (Flags, ASL_PARSE_OUTPUT);
294    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
295
296    Op->Asl.CompileFlags |= Flags;
297    return (Op);
298}
299
300
301/*******************************************************************************
302 *
303 * FUNCTION:    TrSetOpAmlLength
304 *
305 * PARAMETERS:  Op                  - An existing parse op
306 *              Length              - AML Length
307 *
308 * RETURN:      The updated parser op
309 *
310 * DESCRIPTION: Set the AML Length in a op. Used by the parser to indicate
311 *              the presence of a op that must be reduced to a fixed length
312 *              constant.
313 *
314 ******************************************************************************/
315
316ACPI_PARSE_OBJECT *
317TrSetOpAmlLength (
318    ACPI_PARSE_OBJECT       *Op,
319    UINT32                  Length)
320{
321
322    DbgPrint (ASL_PARSE_OUTPUT,
323        "\nSetOpAmlLength: Op %p, %8.8X\n", Op, Length);
324
325    if (!Op)
326    {
327        return (NULL);
328    }
329
330    Op->Asl.AmlLength = Length;
331    return (Op);
332}
333
334
335/*******************************************************************************
336 *
337 * FUNCTION:    TrSetOpParent
338 *
339 * PARAMETERS:  Op                  - To be set to new parent
340 *              ParentOp            - The parent
341 *
342 * RETURN:      None, sets Op parent directly
343 *
344 * DESCRIPTION: Change the parent of a parse op.
345 *
346 ******************************************************************************/
347
348void
349TrSetOpParent (
350    ACPI_PARSE_OBJECT       *Op,
351    ACPI_PARSE_OBJECT       *ParentOp)
352{
353
354    Op->Asl.Parent = ParentOp;
355}
356
357
358/*******************************************************************************
359 *
360 * FUNCTION:    TrSetOpCurrentFilename
361 *
362 * PARAMETERS:  Op                  - An existing parse op
363 *
364 * RETURN:      None
365 *
366 * DESCRIPTION: Save the include file filename. Used for debug output only.
367 *
368 ******************************************************************************/
369
370void
371TrSetOpCurrentFilename (
372    ACPI_PARSE_OBJECT       *Op)
373{
374
375    Op->Asl.Filename = AslGbl_PreviousIncludeFilename;
376}
377
378
379/*******************************************************************************
380 *
381 * FUNCTION:    TrSetOpIntegerWidth
382 *
383 * PARAMETERS:  Op                  - An existing parse op
384 *
385 * RETURN:      None
386 *
387 * DESCRIPTION:
388 *
389 ******************************************************************************/
390
391void
392TrSetOpIntegerWidth (
393    ACPI_PARSE_OBJECT       *TableSignatureOp,
394    ACPI_PARSE_OBJECT       *RevisionOp)
395{
396
397    /* TBD: Check table sig? (DSDT vs. SSDT) */
398
399    /* Handle command-line version override */
400
401    if (AslGbl_RevisionOverride)
402    {
403        AcpiUtSetIntegerWidth (AslGbl_RevisionOverride);
404    }
405    else
406    {
407        AcpiUtSetIntegerWidth ((UINT8) RevisionOp->Asl.Value.Integer);
408    }
409}
410
411
412/*******************************************************************************
413 *
414 * FUNCTION:    TrSetOpEndLineNumber
415 *
416 * PARAMETERS:  Op                - An existing parse op
417 *
418 * RETURN:      None.
419 *
420 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
421 *              parse op to the current line numbers.
422 *
423 ******************************************************************************/
424
425void
426TrSetOpEndLineNumber (
427    ACPI_PARSE_OBJECT       *Op)
428{
429
430    /* If the end line # is already set, just return */
431
432    if (Op->Asl.EndLine)
433    {
434        return;
435    }
436
437    Op->Asl.EndLine = AslGbl_CurrentLineNumber;
438    Op->Asl.EndLogicalLine = AslGbl_LogicalLineNumber;
439}
440
441
442/*******************************************************************************
443 *
444 * FUNCTION:    TrLinkOpChildren
445 *
446 * PARAMETERS:  Op                - An existing parse op
447 *              NumChildren        - Number of children to follow
448 *              ...                - A list of child ops to link to the new
449 *                                   op. NumChildren long.
450 *
451 * RETURN:      The updated (linked) op
452 *
453 * DESCRIPTION: Link a group of ops to an existing parse op
454 *
455 ******************************************************************************/
456
457ACPI_PARSE_OBJECT *
458TrLinkOpChildren (
459    ACPI_PARSE_OBJECT       *Op,
460    UINT32                  NumChildren,
461    ...)
462{
463    ACPI_PARSE_OBJECT       *Child;
464    ACPI_PARSE_OBJECT       *PrevChild;
465    ACPI_PARSE_OBJECT       *LastSibling;
466    va_list                 ap;
467    UINT32                  i;
468    BOOLEAN                 FirstChild;
469
470
471    va_start (ap, NumChildren);
472
473    TrSetOpEndLineNumber (Op);
474
475    DbgPrint (ASL_PARSE_OUTPUT,
476        "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
477        Op->Asl.LineNumber, Op->Asl.EndLine,
478        Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
479
480    switch (Op->Asl.ParseOpcode)
481    {
482    case PARSEOP_ASL_CODE:
483
484        if (!AslGbl_ParseTreeRoot)
485        {
486            DbgPrint (ASL_PARSE_OUTPUT, "Creating first Definition Block\n");
487            AslGbl_ParseTreeRoot = Op;
488            Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
489        }
490        else
491        {
492            DbgPrint (ASL_PARSE_OUTPUT, "Creating subsequent Definition Block\n");
493            Op = AslGbl_ParseTreeRoot;
494        }
495
496        DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
497        break;
498
499    case PARSEOP_DEFINITION_BLOCK:
500
501        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
502        break;
503
504    case PARSEOP_OPERATIONREGION:
505
506        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
507        break;
508
509    case PARSEOP_OR:
510
511        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
512        break;
513
514    default:
515
516        /* Nothing to do for other opcodes */
517
518        break;
519    }
520
521    /* The following is for capturing comments */
522
523    if (AcpiGbl_CaptureComments)
524    {
525        /*
526         * If there are "regular comments" detected at this point,
527         * then is an endBlk comment. Categorize it as so and distribute
528         * all regular comments to this parse op.
529         */
530        if (AslGbl_CommentListHead)
531        {
532            Op->Asl.EndBlkComment = AslGbl_CommentListHead;
533            CvDbgPrint ("EndBlk Comment for %s: %s",
534                Op->Asl.ParseOpName, AslGbl_CommentListHead->Comment);
535            AslGbl_CommentListHead = NULL;
536            AslGbl_CommentListTail = NULL;
537        }
538    }
539
540    /* Link the new op to it's children */
541
542    PrevChild = NULL;
543    FirstChild = TRUE;
544    for (i = 0; i < NumChildren; i++)
545    {
546        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
547
548        if ((Child == PrevChild) && (Child != NULL))
549        {
550            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
551                "Child op list invalid");
552            va_end(ap);
553            return (Op);
554        }
555
556        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
557
558        /*
559         * If child is NULL, this means that an optional argument
560         * was omitted. We must create a placeholder with a special
561         * opcode (DEFAULT_ARG) so that the code generator will know
562         * that it must emit the correct default for this argument
563         */
564        if (!Child)
565        {
566            Child = TrAllocateOp (PARSEOP_DEFAULT_ARG);
567        }
568
569        /* Link first child to parent */
570
571        if (FirstChild)
572        {
573            FirstChild = FALSE;
574
575            /*
576             * In the case that multiple definition blocks are being compiled,
577             * append the definition block to the end of the child list as the
578             * last sibling. This is done to facilitate namespace cross-
579             * reference between multiple definition blocks.
580             */
581            if (Op->Asl.Child &&
582                (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
583            {
584                LastSibling = Op->Asl.Child;
585                while (LastSibling->Asl.Next)
586                {
587                    LastSibling = LastSibling->Asl.Next;
588                }
589                LastSibling->Asl.Next = Child;
590            }
591            else
592            {
593                Op->Asl.Child = Child;
594            }
595        }
596
597        /* Point all children to parent */
598
599        Child->Asl.Parent = Op;
600
601        /* Link children in a peer list */
602
603        if (PrevChild)
604        {
605            PrevChild->Asl.Next = Child;
606        }
607
608        /*
609         * This child might be a list, point all ops in the list
610         * to the same parent
611         */
612        while (Child->Asl.Next)
613        {
614            Child = Child->Asl.Next;
615            Child->Asl.Parent = Op;
616        }
617
618        PrevChild = Child;
619    }
620
621    va_end(ap);
622    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
623
624    if (AcpiGbl_CaptureComments)
625    {
626        AslGbl_CommentState.LatestParseOp = Op;
627        CvDbgPrint ("TrLinkOpChildren=====Set latest parse op to this op.\n");
628    }
629
630    return (Op);
631}
632
633
634/*******************************************************************************
635 *
636 * FUNCTION:    TrLinkPeerOp
637 *
638 * PARAMETERS:  Op1           - First peer
639 *              Op2           - Second peer
640 *
641 * RETURN:      Op1 or the non-null op.
642 *
643 * DESCRIPTION: Link two ops as peers. Handles cases where one peer is null.
644 *
645 ******************************************************************************/
646
647ACPI_PARSE_OBJECT *
648TrLinkPeerOp (
649    ACPI_PARSE_OBJECT       *Op1,
650    ACPI_PARSE_OBJECT       *Op2)
651{
652    ACPI_PARSE_OBJECT       *Next;
653
654
655    DbgPrint (ASL_PARSE_OUTPUT,
656        "\nLinkPeerOp: 1=%p (%s), 2=%p (%s)\n",
657        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
658        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
659
660
661    if ((!Op1) && (!Op2))
662    {
663        DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null ops!\n");
664        return (Op1);
665    }
666
667    /* If one of the ops is null, just return the non-null op */
668
669    if (!Op2)
670    {
671        return (Op1);
672    }
673
674    if (!Op1)
675    {
676        return (Op2);
677    }
678
679    if (Op1 == Op2)
680    {
681        DbgPrint (ASL_DEBUG_OUTPUT,
682            "\n************* Internal error, linking op to itself %p\n",
683            Op1);
684        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
685            "Linking op to itself");
686        return (Op1);
687    }
688
689    Op1->Asl.Parent = Op2->Asl.Parent;
690
691    /*
692     * Op 1 may already have a peer list (such as an IF/ELSE pair),
693     * so we must walk to the end of the list and attach the new
694     * peer at the end
695     */
696    Next = Op1;
697    while (Next->Asl.Next)
698    {
699        Next = Next->Asl.Next;
700    }
701
702    Next->Asl.Next = Op2;
703    return (Op1);
704}
705
706
707/*******************************************************************************
708 *
709 * FUNCTION:    TrLinkPeerOps
710 *
711 * PARAMETERS:  NumPeers            - The number of ops in the list to follow
712 *              ...                 - A list of ops to link together as peers
713 *
714 * RETURN:      The first op in the list (head of the peer list)
715 *
716 * DESCRIPTION: Link together an arbitrary number of peer ops.
717 *
718 ******************************************************************************/
719
720ACPI_PARSE_OBJECT *
721TrLinkPeerOps (
722    UINT32                  NumPeers,
723    ...)
724{
725    ACPI_PARSE_OBJECT       *This;
726    ACPI_PARSE_OBJECT       *Next;
727    va_list                 ap;
728    UINT32                  i;
729    ACPI_PARSE_OBJECT       *Start;
730
731
732    DbgPrint (ASL_PARSE_OUTPUT,
733        "\nLinkPeerOps: (%u) ", NumPeers);
734
735    va_start (ap, NumPeers);
736    This = va_arg (ap, ACPI_PARSE_OBJECT *);
737    Start = This;
738
739    /*
740     * Link all peers
741     */
742    for (i = 0; i < (NumPeers -1); i++)
743    {
744        DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
745
746        while (This->Asl.Next)
747        {
748            This = This->Asl.Next;
749        }
750
751        /* Get another peer op */
752
753        Next = va_arg (ap, ACPI_PARSE_OBJECT *);
754        if (!Next)
755        {
756            Next = TrAllocateOp (PARSEOP_DEFAULT_ARG);
757        }
758
759        /* link new op to the current op */
760
761        This->Asl.Next = Next;
762        This = Next;
763    }
764
765    va_end (ap);
766    DbgPrint (ASL_PARSE_OUTPUT,"\n");
767    return (Start);
768}
769
770
771/*******************************************************************************
772 *
773 * FUNCTION:    TrLinkChildOp
774 *
775 * PARAMETERS:  Op1           - Parent op
776 *              Op2           - Op to become a child
777 *
778 * RETURN:      The parent op
779 *
780 * DESCRIPTION: Link two ops together as a parent and child
781 *
782 ******************************************************************************/
783
784ACPI_PARSE_OBJECT *
785TrLinkChildOp (
786    ACPI_PARSE_OBJECT       *Op1,
787    ACPI_PARSE_OBJECT       *Op2)
788{
789    ACPI_PARSE_OBJECT       *Next;
790
791
792    DbgPrint (ASL_PARSE_OUTPUT,
793        "\nLinkChildOp: Parent=%p (%s), Child=%p (%s)\n",
794        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
795        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
796
797    /*
798     * Converter: if TrLinkChildOp is called to link a method call,
799     * turn on capture comments as it signifies that we are done parsing
800     * a method call.
801     */
802    if (AcpiGbl_CaptureComments && Op1)
803    {
804        if (Op1->Asl.ParseOpcode == PARSEOP_METHODCALL)
805        {
806            AslGbl_CommentState.CaptureComments = TRUE;
807        }
808        AslGbl_CommentState.LatestParseOp = Op1;
809    }
810
811    if (!Op1 || !Op2)
812    {
813        return (Op1);
814    }
815
816    Op1->Asl.Child = Op2;
817
818    /* Set the child and all peers of the child to point to the parent */
819
820    Next = Op2;
821    while (Next)
822    {
823        Next->Asl.Parent = Op1;
824        Next = Next->Asl.Next;
825    }
826
827    return (Op1);
828}
829
830
831/*******************************************************************************
832 *
833 * FUNCTION:    TrWalkParseTree
834 *
835 * PARAMETERS:  Op                      - Walk starting point
836 *              Visitation              - Type of walk
837 *              DescendingCallback      - Called during tree descent
838 *              AscendingCallback       - Called during tree ascent
839 *              Context                 - To be passed to the callbacks
840 *
841 * RETURN:      Status from callback(s)
842 *
843 * DESCRIPTION: Walk the entire parse tree.
844 *
845 ******************************************************************************/
846
847ACPI_STATUS
848TrWalkParseTree (
849    ACPI_PARSE_OBJECT       *Op,
850    UINT32                  Visitation,
851    ASL_WALK_CALLBACK       DescendingCallback,
852    ASL_WALK_CALLBACK       AscendingCallback,
853    void                    *Context)
854{
855    UINT32                  Level;
856    BOOLEAN                 OpPreviouslyVisited;
857    ACPI_PARSE_OBJECT       *StartOp = Op;
858    ACPI_STATUS             Status;
859    ACPI_PARSE_OBJECT       *Restore = NULL;
860    BOOLEAN                 WalkOneDefinitionBlock = Visitation & ASL_WALK_VISIT_DB_SEPARATELY;
861
862
863    if (!AslGbl_ParseTreeRoot)
864    {
865        return (AE_OK);
866    }
867
868    Level = 0;
869    OpPreviouslyVisited = FALSE;
870
871    if (Op->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK &&
872        WalkOneDefinitionBlock)
873    {
874        Restore = Op->Asl.Next;
875        Op->Asl.Next = NULL;
876    }
877    switch (Visitation & ~ASL_WALK_VISIT_DB_SEPARATELY)
878    {
879    case ASL_WALK_VISIT_DOWNWARD:
880
881        while (Op)
882        {
883            if (!OpPreviouslyVisited)
884            {
885                /* Let the callback process the op. */
886
887                Status = DescendingCallback (Op, Level, Context);
888                if (ACPI_SUCCESS (Status))
889                {
890                    /* Visit children first, once */
891
892                    if (Op->Asl.Child)
893                    {
894                        Level++;
895                        Op = Op->Asl.Child;
896                        continue;
897                    }
898                }
899                else if (Status != AE_CTRL_DEPTH)
900                {
901                    /* Exit immediately on any error */
902
903                    goto ErrorExit;
904                }
905            }
906
907            /* Terminate walk at start op */
908
909            if (Op == StartOp)
910            {
911                break;
912            }
913
914            /* No more children, visit peers */
915
916            if (Op->Asl.Next)
917            {
918                Op = Op->Asl.Next;
919                OpPreviouslyVisited = FALSE;
920            }
921            else
922            {
923                /* No children or peers, re-visit parent */
924
925                if (Level != 0 )
926                {
927                    Level--;
928                }
929                Op = Op->Asl.Parent;
930                OpPreviouslyVisited = TRUE;
931            }
932        }
933        break;
934
935    case ASL_WALK_VISIT_UPWARD:
936
937        while (Op)
938        {
939            /* Visit leaf op (no children) or parent op on return trip */
940
941            if ((!Op->Asl.Child) ||
942                (OpPreviouslyVisited))
943            {
944                /* Let the callback process the op. */
945
946                Status = AscendingCallback (Op, Level, Context);
947                if (ACPI_FAILURE (Status))
948                {
949                    goto ErrorExit;
950                }
951            }
952            else
953            {
954                /* Visit children first, once */
955
956                Level++;
957                Op = Op->Asl.Child;
958                continue;
959            }
960
961            /* Terminate walk at start op */
962
963            if (Op == StartOp)
964            {
965                break;
966            }
967
968            /* No more children, visit peers */
969
970            if (Op->Asl.Next)
971            {
972                Op = Op->Asl.Next;
973                OpPreviouslyVisited = FALSE;
974            }
975            else
976            {
977                /* No children or peers, re-visit parent */
978
979                if (Level != 0 )
980                {
981                    Level--;
982                }
983                Op = Op->Asl.Parent;
984                OpPreviouslyVisited = TRUE;
985            }
986        }
987        break;
988
989     case ASL_WALK_VISIT_TWICE:
990
991        while (Op)
992        {
993            if (OpPreviouslyVisited)
994            {
995                Status = AscendingCallback (Op, Level, Context);
996                if (ACPI_FAILURE (Status))
997                {
998                    goto ErrorExit;
999                }
1000            }
1001            else
1002            {
1003                /* Let the callback process the op. */
1004
1005                Status = DescendingCallback (Op, Level, Context);
1006                if (ACPI_SUCCESS (Status))
1007                {
1008                    /* Visit children first, once */
1009
1010                    if (Op->Asl.Child)
1011                    {
1012                        Level++;
1013                        Op = Op->Asl.Child;
1014                        continue;
1015                    }
1016                }
1017                else if (Status != AE_CTRL_DEPTH)
1018                {
1019                    /* Exit immediately on any error */
1020
1021                    goto ErrorExit;
1022                }
1023            }
1024
1025            /* Terminate walk at start op */
1026
1027            if (Op == StartOp)
1028            {
1029                break;
1030            }
1031
1032            /* No more children, visit peers */
1033
1034            if (Op->Asl.Next)
1035            {
1036                Op = Op->Asl.Next;
1037                OpPreviouslyVisited = FALSE;
1038            }
1039            else
1040            {
1041                /* No children or peers, re-visit parent */
1042
1043                if (Level != 0 )
1044                {
1045                    Level--;
1046                }
1047                Op = Op->Asl.Parent;
1048                OpPreviouslyVisited = TRUE;
1049            }
1050        }
1051        break;
1052
1053    default:
1054        /* No other types supported */
1055        break;
1056    }
1057
1058    /* If we get here, the walk completed with no errors */
1059
1060    if (Op->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK &&
1061        WalkOneDefinitionBlock)
1062    {
1063        Op->Asl.Next = Restore;
1064    }
1065
1066    return (AE_OK);
1067
1068ErrorExit:
1069
1070    if (Op->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK &&
1071        WalkOneDefinitionBlock)
1072    {
1073        Op->Asl.Next = Restore;
1074    }
1075    return (Status);
1076}
1077