asltree.c revision 239340
1118611Snjl
2118611Snjl/******************************************************************************
3118611Snjl *
4118611Snjl * Module Name: asltree - parse tree management
5118611Snjl *
6118611Snjl *****************************************************************************/
7118611Snjl
8217365Sjkim/*
9229989Sjkim * Copyright (C) 2000 - 2012, Intel Corp.
10118611Snjl * All rights reserved.
11118611Snjl *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
26118611Snjl *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
30118611Snjl *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
44118611Snjl
45118611Snjl
46151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
47118611Snjl#include "aslcompiler.y.h"
48228110Sjkim#include <contrib/dev/acpica/include/acapps.h>
49218590Sjkim#include <time.h>
50118611Snjl
51118611Snjl#define _COMPONENT          ACPI_COMPILER
52118611Snjl        ACPI_MODULE_NAME    ("asltree")
53118611Snjl
54151937Sjkim/* Local prototypes */
55118611Snjl
56151937Sjkimstatic ACPI_PARSE_OBJECT *
57151937SjkimTrGetNextNode (
58151937Sjkim    void);
59151937Sjkim
60151937Sjkimstatic char *
61151937SjkimTrGetNodeFlagName (
62151937Sjkim    UINT32                  Flags);
63151937Sjkim
64151937Sjkim
65118611Snjl/*******************************************************************************
66118611Snjl *
67118611Snjl * FUNCTION:    TrGetNextNode
68118611Snjl *
69118611Snjl * PARAMETERS:  None
70118611Snjl *
71239340Sjkim * RETURN:      New parse node. Aborts on allocation failure
72118611Snjl *
73239340Sjkim * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
74118611Snjl *              dynamic memory manager for performance reasons (This has a
75118611Snjl *              major impact on the speed of the compiler.)
76118611Snjl *
77118611Snjl ******************************************************************************/
78118611Snjl
79151937Sjkimstatic ACPI_PARSE_OBJECT *
80151937SjkimTrGetNextNode (
81151937Sjkim    void)
82118611Snjl{
83118611Snjl
84118611Snjl    if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast)
85118611Snjl    {
86151937Sjkim        Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) *
87151937Sjkim                                ASL_NODE_CACHE_SIZE);
88118611Snjl        Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE;
89118611Snjl    }
90118611Snjl
91118611Snjl    return (Gbl_NodeCacheNext++);
92118611Snjl}
93118611Snjl
94118611Snjl
95118611Snjl/*******************************************************************************
96118611Snjl *
97118611Snjl * FUNCTION:    TrAllocateNode
98118611Snjl *
99118611Snjl * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
100118611Snjl *
101239340Sjkim * RETURN:      New parse node. Aborts on allocation failure
102118611Snjl *
103118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
104118611Snjl *
105118611Snjl ******************************************************************************/
106118611Snjl
107118611SnjlACPI_PARSE_OBJECT *
108118611SnjlTrAllocateNode (
109118611Snjl    UINT32                  ParseOpcode)
110118611Snjl{
111118611Snjl    ACPI_PARSE_OBJECT       *Op;
112118611Snjl
113118611Snjl
114118611Snjl    Op = TrGetNextNode ();
115118611Snjl
116118611Snjl    Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
117118611Snjl    Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
118118611Snjl    Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
119118611Snjl    Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
120118611Snjl    Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
121118611Snjl    Op->Asl.Column            = Gbl_CurrentColumn;
122118611Snjl
123118611Snjl    UtSetParseOpName (Op);
124118611Snjl    return Op;
125118611Snjl}
126118611Snjl
127118611Snjl
128118611Snjl/*******************************************************************************
129118611Snjl *
130118611Snjl * FUNCTION:    TrReleaseNode
131118611Snjl *
132118611Snjl * PARAMETERS:  Op            - Op to be released
133118611Snjl *
134118611Snjl * RETURN:      None
135118611Snjl *
136239340Sjkim * DESCRIPTION: "release" a node. In truth, nothing is done since the node
137118611Snjl *              is part of a larger buffer
138118611Snjl *
139118611Snjl ******************************************************************************/
140118611Snjl
141118611Snjlvoid
142118611SnjlTrReleaseNode (
143118611Snjl    ACPI_PARSE_OBJECT       *Op)
144118611Snjl{
145118611Snjl
146118611Snjl    return;
147118611Snjl}
148118611Snjl
149118611Snjl
150118611Snjl/*******************************************************************************
151118611Snjl *
152118611Snjl * FUNCTION:    TrUpdateNode
153118611Snjl *
154118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
155118611Snjl *              Op                - An existing parse node
156118611Snjl *
157118611Snjl * RETURN:      The updated node
158118611Snjl *
159239340Sjkim * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
160118611Snjl *              change an opcode to DEFAULT_ARG so that the node is ignored
161239340Sjkim *              during the code generation. Also used to set generic integers
162118611Snjl *              to a specific size (8, 16, 32, or 64 bits)
163118611Snjl *
164118611Snjl ******************************************************************************/
165118611Snjl
166118611SnjlACPI_PARSE_OBJECT *
167118611SnjlTrUpdateNode (
168118611Snjl    UINT32                  ParseOpcode,
169118611Snjl    ACPI_PARSE_OBJECT       *Op)
170118611Snjl{
171118611Snjl
172118611Snjl    if (!Op)
173118611Snjl    {
174118611Snjl        return NULL;
175118611Snjl    }
176118611Snjl
177118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
178118611Snjl        "\nUpdateNode: Old - %s, New - %s\n\n",
179118611Snjl        UtGetOpName (Op->Asl.ParseOpcode),
180118611Snjl        UtGetOpName (ParseOpcode));
181118611Snjl
182118611Snjl    /* Assign new opcode and name */
183118611Snjl
184118611Snjl    if (Op->Asl.ParseOpcode == PARSEOP_ONES)
185118611Snjl    {
186118611Snjl        switch (ParseOpcode)
187118611Snjl        {
188118611Snjl        case PARSEOP_BYTECONST:
189239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT8_MAX;
190118611Snjl            break;
191118611Snjl
192118611Snjl        case PARSEOP_WORDCONST:
193239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT16_MAX;
194118611Snjl            break;
195118611Snjl
196118611Snjl        case PARSEOP_DWORDCONST:
197239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT32_MAX;
198118611Snjl            break;
199118611Snjl
200239340Sjkim        /* Don't need to do the QWORD case */
201239340Sjkim
202118611Snjl        default:
203239340Sjkim            /* Don't care about others */
204118611Snjl            break;
205118611Snjl        }
206118611Snjl    }
207118611Snjl
208118611Snjl    Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
209118611Snjl    UtSetParseOpName (Op);
210118611Snjl
211118611Snjl    /*
212118611Snjl     * For the BYTE, WORD, and DWORD constants, make sure that the integer
213118611Snjl     * that was passed in will actually fit into the data type
214118611Snjl     */
215118611Snjl    switch (ParseOpcode)
216118611Snjl    {
217118611Snjl    case PARSEOP_BYTECONST:
218239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
219239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
220118611Snjl        break;
221118611Snjl
222118611Snjl    case PARSEOP_WORDCONST:
223239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
224239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
225118611Snjl        break;
226118611Snjl
227118611Snjl    case PARSEOP_DWORDCONST:
228239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
229239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
230118611Snjl        break;
231118611Snjl
232118611Snjl    default:
233118611Snjl        /* Don't care about others, don't need to check QWORD */
234118611Snjl        break;
235118611Snjl    }
236118611Snjl
237118611Snjl    return Op;
238118611Snjl}
239118611Snjl
240118611Snjl
241118611Snjl/*******************************************************************************
242118611Snjl *
243118611Snjl * FUNCTION:    TrGetNodeFlagName
244118611Snjl *
245118611Snjl * PARAMETERS:  Flags               - Flags word to be decoded
246118611Snjl *
247151937Sjkim * RETURN:      Name string. Always returns a valid string pointer.
248118611Snjl *
249118611Snjl * DESCRIPTION: Decode a flags word
250118611Snjl *
251118611Snjl ******************************************************************************/
252118611Snjl
253151937Sjkimstatic char *
254118611SnjlTrGetNodeFlagName (
255118611Snjl    UINT32                  Flags)
256118611Snjl{
257118611Snjl
258118611Snjl    switch (Flags)
259118611Snjl    {
260118611Snjl    case NODE_VISITED:
261118611Snjl        return ("NODE_VISITED");
262118611Snjl
263118611Snjl    case NODE_AML_PACKAGE:
264118611Snjl        return ("NODE_AML_PACKAGE");
265118611Snjl
266118611Snjl    case NODE_IS_TARGET:
267118611Snjl        return ("NODE_IS_TARGET");
268118611Snjl
269118611Snjl    case NODE_IS_RESOURCE_DESC:
270118611Snjl        return ("NODE_IS_RESOURCE_DESC");
271118611Snjl
272118611Snjl    case NODE_IS_RESOURCE_FIELD:
273118611Snjl        return ("NODE_IS_RESOURCE_FIELD");
274118611Snjl
275118611Snjl    case NODE_HAS_NO_EXIT:
276118611Snjl        return ("NODE_HAS_NO_EXIT");
277118611Snjl
278118611Snjl    case NODE_IF_HAS_NO_EXIT:
279118611Snjl        return ("NODE_IF_HAS_NO_EXIT");
280118611Snjl
281118611Snjl    case NODE_NAME_INTERNALIZED:
282118611Snjl        return ("NODE_NAME_INTERNALIZED");
283118611Snjl
284118611Snjl    case NODE_METHOD_NO_RETVAL:
285118611Snjl        return ("NODE_METHOD_NO_RETVAL");
286118611Snjl
287118611Snjl    case NODE_METHOD_SOME_NO_RETVAL:
288118611Snjl        return ("NODE_METHOD_SOME_NO_RETVAL");
289118611Snjl
290118611Snjl    case NODE_RESULT_NOT_USED:
291118611Snjl        return ("NODE_RESULT_NOT_USED");
292118611Snjl
293118611Snjl    case NODE_METHOD_TYPED:
294118611Snjl        return ("NODE_METHOD_TYPED");
295118611Snjl
296118611Snjl    case NODE_COMPILE_TIME_CONST:
297118611Snjl        return ("NODE_COMPILE_TIME_CONST");
298118611Snjl
299118611Snjl    case NODE_IS_TERM_ARG:
300118611Snjl        return ("NODE_IS_TERM_ARG");
301118611Snjl
302118611Snjl    case NODE_WAS_ONES_OP:
303118611Snjl        return ("NODE_WAS_ONES_OP");
304118611Snjl
305118611Snjl    case NODE_IS_NAME_DECLARATION:
306118611Snjl        return ("NODE_IS_NAME_DECLARATION");
307118611Snjl
308118611Snjl    default:
309118611Snjl        return ("Multiple Flags (or unknown flag) set");
310118611Snjl    }
311118611Snjl}
312118611Snjl
313118611Snjl
314118611Snjl/*******************************************************************************
315118611Snjl *
316118611Snjl * FUNCTION:    TrSetNodeFlags
317118611Snjl *
318151937Sjkim * PARAMETERS:  Op                  - An existing parse node
319118611Snjl *              Flags               - New flags word
320118611Snjl *
321151937Sjkim * RETURN:      The updated parser op
322118611Snjl *
323239340Sjkim * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
324118611Snjl *
325118611Snjl ******************************************************************************/
326118611Snjl
327118611SnjlACPI_PARSE_OBJECT *
328118611SnjlTrSetNodeFlags (
329118611Snjl    ACPI_PARSE_OBJECT       *Op,
330118611Snjl    UINT32                  Flags)
331118611Snjl{
332118611Snjl
333118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
334151937Sjkim        "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags,
335151937Sjkim        TrGetNodeFlagName (Flags));
336118611Snjl
337118611Snjl    if (!Op)
338118611Snjl    {
339118611Snjl        return NULL;
340118611Snjl    }
341118611Snjl
342118611Snjl    Op->Asl.CompileFlags |= Flags;
343239340Sjkim    return (Op);
344239340Sjkim}
345118611Snjl
346239340Sjkim
347239340Sjkim/*******************************************************************************
348239340Sjkim *
349239340Sjkim * FUNCTION:    TrSetNodeAmlLength
350239340Sjkim *
351239340Sjkim * PARAMETERS:  Op                  - An existing parse node
352239340Sjkim *              Length              - AML Length
353239340Sjkim *
354239340Sjkim * RETURN:      The updated parser op
355239340Sjkim *
356239340Sjkim * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
357239340Sjkim *              the presence of a node that must be reduced to a fixed length
358239340Sjkim *              constant.
359239340Sjkim *
360239340Sjkim ******************************************************************************/
361239340Sjkim
362239340SjkimACPI_PARSE_OBJECT *
363239340SjkimTrSetNodeAmlLength (
364239340Sjkim    ACPI_PARSE_OBJECT       *Op,
365239340Sjkim    UINT32                  Length)
366239340Sjkim{
367239340Sjkim
368239340Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
369239340Sjkim        "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
370239340Sjkim
371239340Sjkim    if (!Op)
372239340Sjkim    {
373239340Sjkim        return NULL;
374239340Sjkim    }
375239340Sjkim
376239340Sjkim    Op->Asl.AmlLength = Length;
377239340Sjkim    return (Op);
378118611Snjl}
379118611Snjl
380118611Snjl
381118611Snjl/*******************************************************************************
382118611Snjl *
383118611Snjl * FUNCTION:    TrSetEndLineNumber
384118611Snjl *
385118611Snjl * PARAMETERS:  Op                - An existing parse node
386118611Snjl *
387118611Snjl * RETURN:      None.
388118611Snjl *
389118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
390118611Snjl *              parse node to the current line numbers.
391118611Snjl *
392118611Snjl ******************************************************************************/
393118611Snjl
394118611Snjlvoid
395118611SnjlTrSetEndLineNumber (
396118611Snjl    ACPI_PARSE_OBJECT       *Op)
397118611Snjl{
398118611Snjl
399118611Snjl    /* If the end line # is already set, just return */
400118611Snjl
401118611Snjl    if (Op->Asl.EndLine)
402118611Snjl    {
403118611Snjl        return;
404118611Snjl    }
405118611Snjl
406118611Snjl    Op->Asl.EndLine        = Gbl_CurrentLineNumber;
407118611Snjl    Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
408118611Snjl}
409118611Snjl
410118611Snjl
411118611Snjl/*******************************************************************************
412118611Snjl *
413118611Snjl * FUNCTION:    TrCreateLeafNode
414118611Snjl *
415118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
416118611Snjl *
417239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
418118611Snjl *
419118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
420118611Snjl *              assigned to the node)
421118611Snjl *
422118611Snjl ******************************************************************************/
423118611Snjl
424118611SnjlACPI_PARSE_OBJECT *
425118611SnjlTrCreateLeafNode (
426118611Snjl    UINT32                  ParseOpcode)
427118611Snjl{
428118611Snjl    ACPI_PARSE_OBJECT       *Op;
429118611Snjl
430118611Snjl
431118611Snjl    Op = TrAllocateNode (ParseOpcode);
432118611Snjl
433118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
434209746Sjkim        "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
435167802Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode));
436118611Snjl
437118611Snjl    return Op;
438118611Snjl}
439118611Snjl
440118611Snjl
441118611Snjl/*******************************************************************************
442118611Snjl *
443218590Sjkim * FUNCTION:    TrCreateConstantLeafNode
444218590Sjkim *
445218590Sjkim * PARAMETERS:  ParseOpcode         - The constant opcode
446218590Sjkim *
447239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
448218590Sjkim *
449218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the
450218590Sjkim *              special constants - __LINE__, __FILE__, and __DATE__.
451218590Sjkim *
452218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't
453218590Sjkim * have a full parse tree at this time and cannot find the parent control
454218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after
455218590Sjkim * the parse tree has been fully constructed.
456218590Sjkim *
457218590Sjkim ******************************************************************************/
458218590Sjkim
459218590SjkimACPI_PARSE_OBJECT *
460218590SjkimTrCreateConstantLeafNode (
461218590Sjkim    UINT32                  ParseOpcode)
462218590Sjkim{
463218590Sjkim    ACPI_PARSE_OBJECT       *Op = NULL;
464218590Sjkim    time_t                  CurrentTime;
465218590Sjkim    char                    *StaticTimeString;
466218590Sjkim    char                    *TimeString;
467228110Sjkim    char                    *Path;
468228110Sjkim    char                    *Filename;
469218590Sjkim
470218590Sjkim
471218590Sjkim    switch (ParseOpcode)
472218590Sjkim    {
473218590Sjkim    case PARSEOP___LINE__:
474218590Sjkim        Op = TrAllocateNode (PARSEOP_INTEGER);
475218590Sjkim        Op->Asl.Value.Integer = Op->Asl.LineNumber;
476218590Sjkim        break;
477218590Sjkim
478228110Sjkim    case PARSEOP___PATH__:
479218590Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
480218590Sjkim
481218590Sjkim        /* Op.Asl.Filename contains the full pathname to the file */
482218590Sjkim
483218590Sjkim        Op->Asl.Value.String = Op->Asl.Filename;
484218590Sjkim        break;
485218590Sjkim
486228110Sjkim    case PARSEOP___FILE__:
487218590Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
488218590Sjkim
489228110Sjkim        /* Get the simple filename from the full path */
490228110Sjkim
491228110Sjkim        FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename);
492228110Sjkim        ACPI_FREE (Path);
493228110Sjkim        Op->Asl.Value.String = Filename;
494228110Sjkim        break;
495228110Sjkim
496228110Sjkim    case PARSEOP___DATE__:
497228110Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
498228110Sjkim
499218590Sjkim        /* Get a copy of the current time */
500218590Sjkim
501218590Sjkim        CurrentTime = time (NULL);
502218590Sjkim        StaticTimeString = ctime (&CurrentTime);
503218590Sjkim        TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
504218590Sjkim        strcpy (TimeString, StaticTimeString);
505218590Sjkim
506218590Sjkim        TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
507218590Sjkim        Op->Asl.Value.String = TimeString;
508218590Sjkim        break;
509218590Sjkim
510218590Sjkim    default: /* This would be an internal error */
511218590Sjkim        return (NULL);
512218590Sjkim    }
513218590Sjkim
514218590Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
515218590Sjkim        "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
516218590Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
517218590Sjkim        ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
518218590Sjkim    return (Op);
519218590Sjkim}
520218590Sjkim
521218590Sjkim
522218590Sjkim/*******************************************************************************
523218590Sjkim *
524118611Snjl * FUNCTION:    TrCreateValuedLeafNode
525118611Snjl *
526118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
527118611Snjl *              Value               - Value to be assigned to the node
528118611Snjl *
529239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
530118611Snjl *
531118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value
532118611Snjl *              assigned to it
533118611Snjl *
534118611Snjl ******************************************************************************/
535118611Snjl
536118611SnjlACPI_PARSE_OBJECT *
537118611SnjlTrCreateValuedLeafNode (
538118611Snjl    UINT32                  ParseOpcode,
539202771Sjkim    UINT64                  Value)
540118611Snjl{
541118611Snjl    ACPI_PARSE_OBJECT       *Op;
542118611Snjl
543118611Snjl
544118611Snjl    Op = TrAllocateNode (ParseOpcode);
545118611Snjl
546118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
547209746Sjkim        "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
548167802Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
549123315Snjl        ACPI_FORMAT_UINT64 (Value));
550118611Snjl    Op->Asl.Value.Integer = Value;
551118611Snjl
552118611Snjl    switch (ParseOpcode)
553118611Snjl    {
554118611Snjl    case PARSEOP_STRING_LITERAL:
555118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
556118611Snjl        break;
557118611Snjl
558118611Snjl    case PARSEOP_NAMESEG:
559118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
560118611Snjl        break;
561118611Snjl
562118611Snjl    case PARSEOP_NAMESTRING:
563118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
564118611Snjl        break;
565118611Snjl
566118611Snjl    case PARSEOP_EISAID:
567118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
568118611Snjl        break;
569118611Snjl
570118611Snjl    case PARSEOP_METHOD:
571118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
572118611Snjl        break;
573118611Snjl
574118611Snjl    case PARSEOP_INTEGER:
575118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "INTEGER");
576118611Snjl        break;
577118611Snjl
578118611Snjl    default:
579118611Snjl        break;
580118611Snjl    }
581118611Snjl
582118611Snjl    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
583118611Snjl    return Op;
584118611Snjl}
585118611Snjl
586118611Snjl
587118611Snjl/*******************************************************************************
588118611Snjl *
589118611Snjl * FUNCTION:    TrCreateNode
590118611Snjl *
591118611Snjl * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
592118611Snjl *              NumChildren         - Number of children to follow
593118611Snjl *              ...                 - A list of child nodes to link to the new
594239340Sjkim *                                    node. NumChildren long.
595118611Snjl *
596239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
597118611Snjl *
598118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child
599118611Snjl *              nodes underneath the new node.
600118611Snjl *
601118611Snjl ******************************************************************************/
602118611Snjl
603118611SnjlACPI_PARSE_OBJECT *
604118611SnjlTrCreateNode (
605118611Snjl    UINT32                  ParseOpcode,
606118611Snjl    UINT32                  NumChildren,
607118611Snjl    ...)
608118611Snjl{
609118611Snjl    ACPI_PARSE_OBJECT       *Op;
610118611Snjl    ACPI_PARSE_OBJECT       *Child;
611118611Snjl    ACPI_PARSE_OBJECT       *PrevChild;
612118611Snjl    va_list                 ap;
613118611Snjl    UINT32                  i;
614118611Snjl    BOOLEAN                 FirstChild;
615118611Snjl
616118611Snjl
617118611Snjl    va_start (ap, NumChildren);
618118611Snjl
619118611Snjl    /* Allocate one new node */
620118611Snjl
621118611Snjl    Op = TrAllocateNode (ParseOpcode);
622118611Snjl
623118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
624209746Sjkim        "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
625167802Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode));
626118611Snjl
627118611Snjl    /* Some extra debug output based on the parse opcode */
628118611Snjl
629118611Snjl    switch (ParseOpcode)
630118611Snjl    {
631118611Snjl    case PARSEOP_DEFINITIONBLOCK:
632118611Snjl        RootNode = Op;
633118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
634118611Snjl        break;
635118611Snjl
636118611Snjl    case PARSEOP_OPERATIONREGION:
637118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
638118611Snjl        break;
639118611Snjl
640118611Snjl    case PARSEOP_OR:
641118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
642118611Snjl        break;
643118611Snjl
644118611Snjl    default:
645118611Snjl        /* Nothing to do for other opcodes */
646118611Snjl        break;
647118611Snjl    }
648118611Snjl
649118611Snjl    /* Link the new node to its children */
650118611Snjl
651118611Snjl    PrevChild = NULL;
652118611Snjl    FirstChild = TRUE;
653118611Snjl    for (i = 0; i < NumChildren; i++)
654118611Snjl    {
655118611Snjl        /* Get the next child */
656118611Snjl
657118611Snjl        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
658118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
659118611Snjl
660118611Snjl        /*
661118611Snjl         * If child is NULL, this means that an optional argument
662239340Sjkim         * was omitted. We must create a placeholder with a special
663118611Snjl         * opcode (DEFAULT_ARG) so that the code generator will know
664118611Snjl         * that it must emit the correct default for this argument
665118611Snjl         */
666118611Snjl        if (!Child)
667118611Snjl        {
668118611Snjl            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
669118611Snjl        }
670118611Snjl
671118611Snjl        /* Link first child to parent */
672118611Snjl
673118611Snjl        if (FirstChild)
674118611Snjl        {
675118611Snjl            FirstChild = FALSE;
676118611Snjl            Op->Asl.Child = Child;
677118611Snjl        }
678118611Snjl
679118611Snjl        /* Point all children to parent */
680118611Snjl
681118611Snjl        Child->Asl.Parent = Op;
682118611Snjl
683118611Snjl        /* Link children in a peer list */
684118611Snjl
685118611Snjl        if (PrevChild)
686118611Snjl        {
687118611Snjl            PrevChild->Asl.Next = Child;
688118611Snjl        };
689118611Snjl
690118611Snjl        /*
691118611Snjl         * This child might be a list, point all nodes in the list
692118611Snjl         * to the same parent
693118611Snjl         */
694118611Snjl        while (Child->Asl.Next)
695118611Snjl        {
696118611Snjl            Child = Child->Asl.Next;
697118611Snjl            Child->Asl.Parent = Op;
698118611Snjl        }
699118611Snjl
700118611Snjl        PrevChild = Child;
701118611Snjl    }
702118611Snjl    va_end(ap);
703118611Snjl
704118611Snjl    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
705118611Snjl    return Op;
706118611Snjl}
707118611Snjl
708118611Snjl
709118611Snjl/*******************************************************************************
710118611Snjl *
711118611Snjl * FUNCTION:    TrLinkChildren
712118611Snjl *
713118611Snjl * PARAMETERS:  Op                - An existing parse node
714118611Snjl *              NumChildren         - Number of children to follow
715118611Snjl *              ...                 - A list of child nodes to link to the new
716239340Sjkim *                                    node. NumChildren long.
717118611Snjl *
718118611Snjl * RETURN:      The updated (linked) node
719118611Snjl *
720118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node
721118611Snjl *
722118611Snjl ******************************************************************************/
723118611Snjl
724118611SnjlACPI_PARSE_OBJECT *
725118611SnjlTrLinkChildren (
726118611Snjl    ACPI_PARSE_OBJECT       *Op,
727118611Snjl    UINT32                  NumChildren,
728118611Snjl    ...)
729118611Snjl{
730118611Snjl    ACPI_PARSE_OBJECT       *Child;
731118611Snjl    ACPI_PARSE_OBJECT       *PrevChild;
732118611Snjl    va_list                 ap;
733118611Snjl    UINT32                  i;
734118611Snjl    BOOLEAN                 FirstChild;
735118611Snjl
736118611Snjl
737118611Snjl    va_start (ap, NumChildren);
738118611Snjl
739118611Snjl
740118611Snjl    TrSetEndLineNumber (Op);
741118611Snjl
742118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
743209746Sjkim        "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
744118611Snjl        Op->Asl.LineNumber, Op->Asl.EndLine,
745118611Snjl        Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
746118611Snjl
747118611Snjl    switch (Op->Asl.ParseOpcode)
748118611Snjl    {
749118611Snjl    case PARSEOP_DEFINITIONBLOCK:
750118611Snjl        RootNode = Op;
751118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
752118611Snjl        break;
753118611Snjl
754118611Snjl    case PARSEOP_OPERATIONREGION:
755118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
756118611Snjl        break;
757118611Snjl
758118611Snjl    case PARSEOP_OR:
759118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
760118611Snjl        break;
761118611Snjl
762118611Snjl    default:
763118611Snjl        /* Nothing to do for other opcodes */
764118611Snjl        break;
765118611Snjl    }
766118611Snjl
767118611Snjl    /* Link the new node to it's children */
768118611Snjl
769118611Snjl    PrevChild = NULL;
770118611Snjl    FirstChild = TRUE;
771118611Snjl    for (i = 0; i < NumChildren; i++)
772118611Snjl    {
773118611Snjl        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
774118611Snjl
775118611Snjl        if ((Child == PrevChild) && (Child != NULL))
776118611Snjl        {
777151937Sjkim            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
778151937Sjkim                "Child node list invalid");
779118611Snjl            return Op;
780118611Snjl        }
781118611Snjl
782118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
783118611Snjl
784118611Snjl        /*
785118611Snjl         * If child is NULL, this means that an optional argument
786239340Sjkim         * was omitted. We must create a placeholder with a special
787118611Snjl         * opcode (DEFAULT_ARG) so that the code generator will know
788118611Snjl         * that it must emit the correct default for this argument
789118611Snjl         */
790118611Snjl        if (!Child)
791118611Snjl        {
792118611Snjl            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
793118611Snjl        }
794118611Snjl
795118611Snjl        /* Link first child to parent */
796118611Snjl
797118611Snjl        if (FirstChild)
798118611Snjl        {
799118611Snjl            FirstChild = FALSE;
800118611Snjl            Op->Asl.Child = Child;
801118611Snjl        }
802118611Snjl
803118611Snjl        /* Point all children to parent */
804118611Snjl
805118611Snjl        Child->Asl.Parent = Op;
806118611Snjl
807118611Snjl        /* Link children in a peer list */
808118611Snjl
809118611Snjl        if (PrevChild)
810118611Snjl        {
811118611Snjl            PrevChild->Asl.Next = Child;
812118611Snjl        };
813118611Snjl
814118611Snjl        /*
815118611Snjl         * This child might be a list, point all nodes in the list
816118611Snjl         * to the same parent
817118611Snjl         */
818118611Snjl        while (Child->Asl.Next)
819118611Snjl        {
820118611Snjl            Child = Child->Asl.Next;
821118611Snjl            Child->Asl.Parent = Op;
822118611Snjl        }
823118611Snjl        PrevChild = Child;
824118611Snjl    }
825118611Snjl    va_end(ap);
826118611Snjl
827118611Snjl    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
828118611Snjl    return Op;
829118611Snjl}
830118611Snjl
831118611Snjl
832118611Snjl/*******************************************************************************
833118611Snjl *
834118611Snjl * FUNCTION:    TrLinkPeerNode
835118611Snjl *
836118611Snjl * PARAMETERS:  Op1           - First peer
837118611Snjl *              Op2           - Second peer
838118611Snjl *
839118611Snjl * RETURN:      Op1 or the non-null node.
840118611Snjl *
841239340Sjkim * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
842118611Snjl *
843118611Snjl ******************************************************************************/
844118611Snjl
845118611SnjlACPI_PARSE_OBJECT *
846118611SnjlTrLinkPeerNode (
847118611Snjl    ACPI_PARSE_OBJECT       *Op1,
848118611Snjl    ACPI_PARSE_OBJECT       *Op2)
849118611Snjl{
850118611Snjl    ACPI_PARSE_OBJECT       *Next;
851118611Snjl
852118611Snjl
853118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
854118611Snjl        "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n",
855118611Snjl        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
856118611Snjl        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
857118611Snjl
858118611Snjl
859118611Snjl    if ((!Op1) && (!Op2))
860118611Snjl    {
861118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
862118611Snjl        return Op1;
863118611Snjl    }
864118611Snjl
865118611Snjl    /* If one of the nodes is null, just return the non-null node */
866118611Snjl
867118611Snjl    if (!Op2)
868118611Snjl    {
869118611Snjl        return Op1;
870118611Snjl    }
871118611Snjl
872118611Snjl    if (!Op1)
873118611Snjl    {
874118611Snjl        return Op2;
875118611Snjl    }
876118611Snjl
877118611Snjl    if (Op1 == Op2)
878118611Snjl    {
879118611Snjl        DbgPrint (ASL_DEBUG_OUTPUT,
880151937Sjkim            "\n\n************* Internal error, linking node to itself %p\n\n\n",
881151937Sjkim            Op1);
882151937Sjkim        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
883151937Sjkim            "Linking node to itself");
884118611Snjl        return Op1;
885118611Snjl    }
886118611Snjl
887118611Snjl    Op1->Asl.Parent = Op2->Asl.Parent;
888118611Snjl
889118611Snjl    /*
890118611Snjl     * Op 1 may already have a peer list (such as an IF/ELSE pair),
891118611Snjl     * so we must walk to the end of the list and attach the new
892118611Snjl     * peer at the end
893118611Snjl     */
894118611Snjl    Next = Op1;
895118611Snjl    while (Next->Asl.Next)
896118611Snjl    {
897118611Snjl        Next = Next->Asl.Next;
898118611Snjl    }
899118611Snjl
900118611Snjl    Next->Asl.Next = Op2;
901118611Snjl    return Op1;
902118611Snjl}
903118611Snjl
904118611Snjl
905118611Snjl/*******************************************************************************
906118611Snjl *
907118611Snjl * FUNCTION:    TrLinkPeerNodes
908118611Snjl *
909118611Snjl * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
910118611Snjl *              ...                 - A list of nodes to link together as peers
911118611Snjl *
912118611Snjl * RETURN:      The first node in the list (head of the peer list)
913118611Snjl *
914118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes.
915118611Snjl *
916118611Snjl ******************************************************************************/
917118611Snjl
918118611SnjlACPI_PARSE_OBJECT *
919118611SnjlTrLinkPeerNodes (
920118611Snjl    UINT32                  NumPeers,
921118611Snjl    ...)
922118611Snjl{
923118611Snjl    ACPI_PARSE_OBJECT       *This;
924118611Snjl    ACPI_PARSE_OBJECT       *Next;
925118611Snjl    va_list                 ap;
926118611Snjl    UINT32                  i;
927118611Snjl    ACPI_PARSE_OBJECT       *Start;
928118611Snjl
929118611Snjl
930118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
931209746Sjkim        "\nLinkPeerNodes: (%u) ", NumPeers);
932118611Snjl
933118611Snjl    va_start (ap, NumPeers);
934118611Snjl    This = va_arg (ap, ACPI_PARSE_OBJECT *);
935118611Snjl    Start = This;
936118611Snjl
937118611Snjl    /*
938118611Snjl     * Link all peers
939118611Snjl     */
940118611Snjl    for (i = 0; i < (NumPeers -1); i++)
941118611Snjl    {
942209746Sjkim        DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
943118611Snjl
944118611Snjl        while (This->Asl.Next)
945118611Snjl        {
946118611Snjl            This = This->Asl.Next;
947118611Snjl        }
948118611Snjl
949118611Snjl        /* Get another peer node */
950118611Snjl
951118611Snjl        Next = va_arg (ap, ACPI_PARSE_OBJECT *);
952118611Snjl        if (!Next)
953118611Snjl        {
954118611Snjl            Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
955118611Snjl        }
956118611Snjl
957118611Snjl        /* link new node to the current node */
958118611Snjl
959118611Snjl        This->Asl.Next = Next;
960118611Snjl        This = Next;
961118611Snjl    }
962193529Sjkim    va_end (ap);
963118611Snjl
964118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,"\n\n");
965118611Snjl    return (Start);
966118611Snjl}
967118611Snjl
968118611Snjl
969118611Snjl/*******************************************************************************
970118611Snjl *
971118611Snjl * FUNCTION:    TrLinkChildNode
972118611Snjl *
973118611Snjl * PARAMETERS:  Op1           - Parent node
974118611Snjl *              Op2           - Op to become a child
975118611Snjl *
976118611Snjl * RETURN:      The parent node
977118611Snjl *
978118611Snjl * DESCRIPTION: Link two nodes together as a parent and child
979118611Snjl *
980118611Snjl ******************************************************************************/
981118611Snjl
982118611SnjlACPI_PARSE_OBJECT *
983118611SnjlTrLinkChildNode (
984118611Snjl    ACPI_PARSE_OBJECT       *Op1,
985118611Snjl    ACPI_PARSE_OBJECT       *Op2)
986118611Snjl{
987118611Snjl    ACPI_PARSE_OBJECT       *Next;
988118611Snjl
989118611Snjl
990118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
991118611Snjl        "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n",
992118611Snjl        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
993118611Snjl        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
994118611Snjl
995118611Snjl    if (!Op1 || !Op2)
996118611Snjl    {
997118611Snjl        return Op1;
998118611Snjl    }
999118611Snjl
1000118611Snjl    Op1->Asl.Child = Op2;
1001118611Snjl
1002118611Snjl    /* Set the child and all peers of the child to point to the parent */
1003118611Snjl
1004118611Snjl    Next = Op2;
1005118611Snjl    while (Next)
1006118611Snjl    {
1007118611Snjl        Next->Asl.Parent = Op1;
1008118611Snjl        Next = Next->Asl.Next;
1009118611Snjl    }
1010118611Snjl
1011118611Snjl    return Op1;
1012118611Snjl}
1013118611Snjl
1014118611Snjl
1015118611Snjl/*******************************************************************************
1016118611Snjl *
1017118611Snjl * FUNCTION:    TrWalkParseTree
1018118611Snjl *
1019118611Snjl * PARAMETERS:  Visitation              - Type of walk
1020118611Snjl *              DescendingCallback      - Called during tree descent
1021118611Snjl *              AscendingCallback       - Called during tree ascent
1022118611Snjl *              Context                 - To be passed to the callbacks
1023118611Snjl *
1024118611Snjl * RETURN:      Status from callback(s)
1025118611Snjl *
1026118611Snjl * DESCRIPTION: Walk the entire parse tree.
1027118611Snjl *
1028118611Snjl ******************************************************************************/
1029118611Snjl
1030118611SnjlACPI_STATUS
1031118611SnjlTrWalkParseTree (
1032118611Snjl    ACPI_PARSE_OBJECT       *Op,
1033118611Snjl    UINT32                  Visitation,
1034118611Snjl    ASL_WALK_CALLBACK       DescendingCallback,
1035118611Snjl    ASL_WALK_CALLBACK       AscendingCallback,
1036118611Snjl    void                    *Context)
1037118611Snjl{
1038118611Snjl    UINT32                  Level;
1039118611Snjl    BOOLEAN                 NodePreviouslyVisited;
1040118611Snjl    ACPI_PARSE_OBJECT       *StartOp = Op;
1041118611Snjl    ACPI_STATUS             Status;
1042118611Snjl
1043118611Snjl
1044118611Snjl    if (!RootNode)
1045118611Snjl    {
1046118611Snjl        return (AE_OK);
1047118611Snjl    }
1048118611Snjl
1049118611Snjl    Level = 0;
1050118611Snjl    NodePreviouslyVisited = FALSE;
1051118611Snjl
1052118611Snjl    switch (Visitation)
1053118611Snjl    {
1054118611Snjl    case ASL_WALK_VISIT_DOWNWARD:
1055118611Snjl
1056118611Snjl        while (Op)
1057118611Snjl        {
1058118611Snjl            if (!NodePreviouslyVisited)
1059118611Snjl            {
1060151937Sjkim                /* Let the callback process the node. */
1061151937Sjkim
1062118611Snjl                Status = DescendingCallback (Op, Level, Context);
1063118611Snjl                if (ACPI_SUCCESS (Status))
1064118611Snjl                {
1065118611Snjl                    /* Visit children first, once */
1066118611Snjl
1067118611Snjl                    if (Op->Asl.Child)
1068118611Snjl                    {
1069118611Snjl                        Level++;
1070118611Snjl                        Op = Op->Asl.Child;
1071118611Snjl                        continue;
1072118611Snjl                    }
1073118611Snjl                }
1074118611Snjl                else if (Status != AE_CTRL_DEPTH)
1075118611Snjl                {
1076118611Snjl                    /* Exit immediately on any error */
1077118611Snjl
1078118611Snjl                    return (Status);
1079118611Snjl                }
1080118611Snjl            }
1081118611Snjl
1082118611Snjl            /* Terminate walk at start op */
1083118611Snjl
1084118611Snjl            if (Op == StartOp)
1085118611Snjl            {
1086118611Snjl                break;
1087118611Snjl            }
1088118611Snjl
1089118611Snjl            /* No more children, visit peers */
1090118611Snjl
1091118611Snjl            if (Op->Asl.Next)
1092118611Snjl            {
1093118611Snjl                Op = Op->Asl.Next;
1094118611Snjl                NodePreviouslyVisited = FALSE;
1095118611Snjl            }
1096118611Snjl            else
1097118611Snjl            {
1098118611Snjl                /* No children or peers, re-visit parent */
1099118611Snjl
1100118611Snjl                if (Level != 0 )
1101118611Snjl                {
1102118611Snjl                    Level--;
1103118611Snjl                }
1104118611Snjl                Op = Op->Asl.Parent;
1105118611Snjl                NodePreviouslyVisited = TRUE;
1106118611Snjl            }
1107118611Snjl        }
1108118611Snjl        break;
1109118611Snjl
1110118611Snjl
1111118611Snjl    case ASL_WALK_VISIT_UPWARD:
1112118611Snjl
1113118611Snjl        while (Op)
1114118611Snjl        {
1115118611Snjl            /* Visit leaf node (no children) or parent node on return trip */
1116118611Snjl
1117118611Snjl            if ((!Op->Asl.Child) ||
1118118611Snjl                (NodePreviouslyVisited))
1119118611Snjl            {
1120151937Sjkim                /* Let the callback process the node. */
1121151937Sjkim
1122118611Snjl                Status = AscendingCallback (Op, Level, Context);
1123118611Snjl                if (ACPI_FAILURE (Status))
1124118611Snjl                {
1125118611Snjl                    return (Status);
1126118611Snjl                }
1127118611Snjl            }
1128118611Snjl            else
1129118611Snjl            {
1130118611Snjl                /* Visit children first, once */
1131118611Snjl
1132118611Snjl                Level++;
1133118611Snjl                Op = Op->Asl.Child;
1134118611Snjl                continue;
1135118611Snjl            }
1136118611Snjl
1137118611Snjl            /* Terminate walk at start op */
1138118611Snjl
1139118611Snjl            if (Op == StartOp)
1140118611Snjl            {
1141118611Snjl                break;
1142118611Snjl            }
1143118611Snjl
1144118611Snjl            /* No more children, visit peers */
1145118611Snjl
1146118611Snjl            if (Op->Asl.Next)
1147118611Snjl            {
1148118611Snjl                Op = Op->Asl.Next;
1149118611Snjl                NodePreviouslyVisited = FALSE;
1150118611Snjl            }
1151118611Snjl            else
1152118611Snjl            {
1153118611Snjl                /* No children or peers, re-visit parent */
1154118611Snjl
1155118611Snjl                if (Level != 0 )
1156118611Snjl                {
1157118611Snjl                    Level--;
1158118611Snjl                }
1159118611Snjl                Op = Op->Asl.Parent;
1160118611Snjl                NodePreviouslyVisited = TRUE;
1161118611Snjl            }
1162118611Snjl        }
1163118611Snjl        break;
1164118611Snjl
1165118611Snjl
1166118611Snjl     case ASL_WALK_VISIT_TWICE:
1167118611Snjl
1168118611Snjl        while (Op)
1169118611Snjl        {
1170118611Snjl            if (NodePreviouslyVisited)
1171118611Snjl            {
1172118611Snjl                Status = AscendingCallback (Op, Level, Context);
1173118611Snjl                if (ACPI_FAILURE (Status))
1174118611Snjl                {
1175118611Snjl                    return (Status);
1176118611Snjl                }
1177118611Snjl            }
1178118611Snjl            else
1179118611Snjl            {
1180151937Sjkim                /* Let the callback process the node. */
1181151937Sjkim
1182118611Snjl                Status = DescendingCallback (Op, Level, Context);
1183118611Snjl                if (ACPI_SUCCESS (Status))
1184118611Snjl                {
1185118611Snjl                    /* Visit children first, once */
1186118611Snjl
1187118611Snjl                    if (Op->Asl.Child)
1188118611Snjl                    {
1189118611Snjl                        Level++;
1190118611Snjl                        Op = Op->Asl.Child;
1191118611Snjl                        continue;
1192118611Snjl                    }
1193118611Snjl                }
1194118611Snjl                else if (Status != AE_CTRL_DEPTH)
1195118611Snjl                {
1196118611Snjl                    /* Exit immediately on any error */
1197118611Snjl
1198118611Snjl                    return (Status);
1199118611Snjl                }
1200118611Snjl            }
1201118611Snjl
1202118611Snjl            /* Terminate walk at start op */
1203118611Snjl
1204118611Snjl            if (Op == StartOp)
1205118611Snjl            {
1206118611Snjl                break;
1207118611Snjl            }
1208118611Snjl
1209118611Snjl            /* No more children, visit peers */
1210118611Snjl
1211118611Snjl            if (Op->Asl.Next)
1212118611Snjl            {
1213118611Snjl                Op = Op->Asl.Next;
1214118611Snjl                NodePreviouslyVisited = FALSE;
1215118611Snjl            }
1216118611Snjl            else
1217118611Snjl            {
1218118611Snjl                /* No children or peers, re-visit parent */
1219118611Snjl
1220118611Snjl                if (Level != 0 )
1221118611Snjl                {
1222118611Snjl                    Level--;
1223118611Snjl                }
1224118611Snjl                Op = Op->Asl.Parent;
1225118611Snjl                NodePreviouslyVisited = TRUE;
1226118611Snjl            }
1227118611Snjl        }
1228118611Snjl        break;
1229118611Snjl
1230118611Snjl    default:
1231118611Snjl        /* No other types supported */
1232118611Snjl        break;
1233118611Snjl    }
1234118611Snjl
1235118611Snjl    /* If we get here, the walk completed with no errors */
1236118611Snjl
1237118611Snjl    return (AE_OK);
1238118611Snjl}
1239118611Snjl
1240118611Snjl
1241