1118611Snjl/******************************************************************************
2118611Snjl *
3118611Snjl * Module Name: asltree - parse tree management
4118611Snjl *
5118611Snjl *****************************************************************************/
6118611Snjl
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9118611Snjl * All rights reserved.
10118611Snjl *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25118611Snjl *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29118611Snjl *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43118611Snjl
44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45118611Snjl#include "aslcompiler.y.h"
46228110Sjkim#include <contrib/dev/acpica/include/acapps.h>
47218590Sjkim#include <time.h>
48118611Snjl
49118611Snjl#define _COMPONENT          ACPI_COMPILER
50118611Snjl        ACPI_MODULE_NAME    ("asltree")
51118611Snjl
52151937Sjkim/* Local prototypes */
53118611Snjl
54151937Sjkimstatic ACPI_PARSE_OBJECT *
55151937SjkimTrGetNextNode (
56151937Sjkim    void);
57151937Sjkim
58151937Sjkim
59118611Snjl/*******************************************************************************
60118611Snjl *
61306536Sjkim * FUNCTION:    TrSetParent
62306536Sjkim *
63306536Sjkim * PARAMETERS:  Op                  - To be set to new parent
64306536Sjkim *              ParentOp            - The parent
65306536Sjkim *
66306536Sjkim * RETURN:      None, sets Op parent directly
67306536Sjkim *
68306536Sjkim * DESCRIPTION: Change the parent of a parse op.
69306536Sjkim *
70306536Sjkim ******************************************************************************/
71306536Sjkim
72306536Sjkimvoid
73306536SjkimTrSetParent (
74306536Sjkim    ACPI_PARSE_OBJECT       *Op,
75306536Sjkim    ACPI_PARSE_OBJECT       *ParentOp)
76306536Sjkim{
77306536Sjkim
78306536Sjkim    Op->Asl.Parent = ParentOp;
79306536Sjkim}
80306536Sjkim
81306536Sjkim
82306536Sjkim/*******************************************************************************
83306536Sjkim *
84118611Snjl * FUNCTION:    TrGetNextNode
85118611Snjl *
86118611Snjl * PARAMETERS:  None
87118611Snjl *
88239340Sjkim * RETURN:      New parse node. Aborts on allocation failure
89118611Snjl *
90239340Sjkim * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
91118611Snjl *              dynamic memory manager for performance reasons (This has a
92118611Snjl *              major impact on the speed of the compiler.)
93118611Snjl *
94118611Snjl ******************************************************************************/
95118611Snjl
96151937Sjkimstatic ACPI_PARSE_OBJECT *
97151937SjkimTrGetNextNode (
98151937Sjkim    void)
99118611Snjl{
100281075Sdim    ASL_CACHE_INFO          *Cache;
101118611Snjl
102281075Sdim
103281075Sdim    if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
104118611Snjl    {
105281075Sdim        /* Allocate a new buffer */
106281075Sdim
107281075Sdim        Cache = UtLocalCalloc (sizeof (Cache->Next) +
108281075Sdim            (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
109281075Sdim
110281075Sdim        /* Link new cache buffer to head of list */
111281075Sdim
112281075Sdim        Cache->Next = Gbl_ParseOpCacheList;
113281075Sdim        Gbl_ParseOpCacheList = Cache;
114281075Sdim
115281075Sdim        /* Setup cache management pointers */
116281075Sdim
117281075Sdim        Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
118281075Sdim        Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
119118611Snjl    }
120118611Snjl
121281075Sdim    Gbl_ParseOpCount++;
122281075Sdim    return (Gbl_ParseOpCacheNext++);
123118611Snjl}
124118611Snjl
125118611Snjl
126118611Snjl/*******************************************************************************
127118611Snjl *
128118611Snjl * FUNCTION:    TrAllocateNode
129118611Snjl *
130118611Snjl * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
131118611Snjl *
132239340Sjkim * RETURN:      New parse node. Aborts on allocation failure
133118611Snjl *
134118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
135118611Snjl *
136118611Snjl ******************************************************************************/
137118611Snjl
138118611SnjlACPI_PARSE_OBJECT *
139118611SnjlTrAllocateNode (
140118611Snjl    UINT32                  ParseOpcode)
141118611Snjl{
142118611Snjl    ACPI_PARSE_OBJECT       *Op;
143118611Snjl
144118611Snjl
145118611Snjl    Op = TrGetNextNode ();
146118611Snjl
147118611Snjl    Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
148118611Snjl    Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
149118611Snjl    Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
150118611Snjl    Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
151118611Snjl    Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
152118611Snjl    Op->Asl.Column            = Gbl_CurrentColumn;
153118611Snjl
154118611Snjl    UtSetParseOpName (Op);
155241973Sjkim    return (Op);
156118611Snjl}
157118611Snjl
158118611Snjl
159118611Snjl/*******************************************************************************
160118611Snjl *
161118611Snjl * FUNCTION:    TrReleaseNode
162118611Snjl *
163118611Snjl * PARAMETERS:  Op            - Op to be released
164118611Snjl *
165118611Snjl * RETURN:      None
166118611Snjl *
167239340Sjkim * DESCRIPTION: "release" a node. In truth, nothing is done since the node
168118611Snjl *              is part of a larger buffer
169118611Snjl *
170118611Snjl ******************************************************************************/
171118611Snjl
172118611Snjlvoid
173118611SnjlTrReleaseNode (
174118611Snjl    ACPI_PARSE_OBJECT       *Op)
175118611Snjl{
176118611Snjl
177118611Snjl    return;
178118611Snjl}
179118611Snjl
180118611Snjl
181118611Snjl/*******************************************************************************
182118611Snjl *
183306536Sjkim * FUNCTION:    TrSetCurrentFilename
184306536Sjkim *
185306536Sjkim * PARAMETERS:  Op                  - An existing parse node
186306536Sjkim *
187306536Sjkim * RETURN:      None
188306536Sjkim *
189306536Sjkim * DESCRIPTION: Save the include file filename. Used for debug output only.
190306536Sjkim *
191306536Sjkim ******************************************************************************/
192306536Sjkim
193306536Sjkimvoid
194306536SjkimTrSetCurrentFilename (
195306536Sjkim    ACPI_PARSE_OBJECT       *Op)
196306536Sjkim{
197306536Sjkim    Op->Asl.Filename = Gbl_PreviousIncludeFilename;
198306536Sjkim}
199306536Sjkim
200306536Sjkim
201306536Sjkim/*******************************************************************************
202306536Sjkim *
203118611Snjl * FUNCTION:    TrUpdateNode
204118611Snjl *
205118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
206306536Sjkim *              Op                  - An existing parse node
207118611Snjl *
208118611Snjl * RETURN:      The updated node
209118611Snjl *
210239340Sjkim * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
211118611Snjl *              change an opcode to DEFAULT_ARG so that the node is ignored
212239340Sjkim *              during the code generation. Also used to set generic integers
213118611Snjl *              to a specific size (8, 16, 32, or 64 bits)
214118611Snjl *
215118611Snjl ******************************************************************************/
216118611Snjl
217118611SnjlACPI_PARSE_OBJECT *
218118611SnjlTrUpdateNode (
219118611Snjl    UINT32                  ParseOpcode,
220118611Snjl    ACPI_PARSE_OBJECT       *Op)
221118611Snjl{
222118611Snjl
223118611Snjl    if (!Op)
224118611Snjl    {
225241973Sjkim        return (NULL);
226118611Snjl    }
227118611Snjl
228118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
229281687Sjkim        "\nUpdateNode: Old - %s, New - %s\n",
230118611Snjl        UtGetOpName (Op->Asl.ParseOpcode),
231118611Snjl        UtGetOpName (ParseOpcode));
232118611Snjl
233118611Snjl    /* Assign new opcode and name */
234118611Snjl
235118611Snjl    if (Op->Asl.ParseOpcode == PARSEOP_ONES)
236118611Snjl    {
237118611Snjl        switch (ParseOpcode)
238118611Snjl        {
239118611Snjl        case PARSEOP_BYTECONST:
240250838Sjkim
241239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT8_MAX;
242118611Snjl            break;
243118611Snjl
244118611Snjl        case PARSEOP_WORDCONST:
245250838Sjkim
246239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT16_MAX;
247118611Snjl            break;
248118611Snjl
249118611Snjl        case PARSEOP_DWORDCONST:
250250838Sjkim
251239340Sjkim            Op->Asl.Value.Integer = ACPI_UINT32_MAX;
252118611Snjl            break;
253118611Snjl
254239340Sjkim        /* Don't need to do the QWORD case */
255239340Sjkim
256118611Snjl        default:
257250838Sjkim
258239340Sjkim            /* Don't care about others */
259118611Snjl            break;
260118611Snjl        }
261118611Snjl    }
262118611Snjl
263118611Snjl    Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
264118611Snjl    UtSetParseOpName (Op);
265118611Snjl
266118611Snjl    /*
267118611Snjl     * For the BYTE, WORD, and DWORD constants, make sure that the integer
268118611Snjl     * that was passed in will actually fit into the data type
269118611Snjl     */
270118611Snjl    switch (ParseOpcode)
271118611Snjl    {
272118611Snjl    case PARSEOP_BYTECONST:
273250838Sjkim
274239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
275239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
276118611Snjl        break;
277118611Snjl
278118611Snjl    case PARSEOP_WORDCONST:
279250838Sjkim
280239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
281239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
282118611Snjl        break;
283118611Snjl
284118611Snjl    case PARSEOP_DWORDCONST:
285250838Sjkim
286239340Sjkim        UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
287239340Sjkim        Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
288118611Snjl        break;
289118611Snjl
290118611Snjl    default:
291250838Sjkim
292118611Snjl        /* Don't care about others, don't need to check QWORD */
293250838Sjkim
294118611Snjl        break;
295118611Snjl    }
296118611Snjl
297241973Sjkim    return (Op);
298118611Snjl}
299118611Snjl
300118611Snjl
301118611Snjl/*******************************************************************************
302118611Snjl *
303281687Sjkim * FUNCTION:    TrPrintNodeCompileFlags
304118611Snjl *
305118611Snjl * PARAMETERS:  Flags               - Flags word to be decoded
306118611Snjl *
307281687Sjkim * RETURN:      None
308118611Snjl *
309281687Sjkim * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
310118611Snjl *
311118611Snjl ******************************************************************************/
312118611Snjl
313281687Sjkimvoid
314281687SjkimTrPrintNodeCompileFlags (
315118611Snjl    UINT32                  Flags)
316118611Snjl{
317281687Sjkim    UINT32                  i;
318281687Sjkim    UINT32                  FlagBit = 1;
319281687Sjkim    char                    *FlagName = NULL;
320118611Snjl
321281687Sjkim
322281687Sjkim    for (i = 0; i < 32; i++)
323118611Snjl    {
324281687Sjkim        switch (Flags & FlagBit)
325281687Sjkim        {
326281687Sjkim        case NODE_VISITED:
327250838Sjkim
328281687Sjkim            FlagName = "NODE_VISITED";
329281687Sjkim            break;
330118611Snjl
331281687Sjkim        case NODE_AML_PACKAGE:
332250838Sjkim
333281687Sjkim            FlagName = "NODE_AML_PACKAGE";
334281687Sjkim            break;
335118611Snjl
336281687Sjkim        case NODE_IS_TARGET:
337250838Sjkim
338281687Sjkim            FlagName = "NODE_IS_TARGET";
339281687Sjkim            break;
340118611Snjl
341281687Sjkim        case NODE_IS_RESOURCE_DESC:
342250838Sjkim
343281687Sjkim            FlagName = "NODE_IS_RESOURCE_DESC";
344281687Sjkim            break;
345118611Snjl
346281687Sjkim        case NODE_IS_RESOURCE_FIELD:
347250838Sjkim
348281687Sjkim            FlagName = "NODE_IS_RESOURCE_FIELD";
349281687Sjkim            break;
350118611Snjl
351281687Sjkim        case NODE_HAS_NO_EXIT:
352250838Sjkim
353281687Sjkim            FlagName = "NODE_HAS_NO_EXIT";
354281687Sjkim            break;
355118611Snjl
356281687Sjkim        case NODE_IF_HAS_NO_EXIT:
357250838Sjkim
358281687Sjkim            FlagName = "NODE_IF_HAS_NO_EXIT";
359281687Sjkim            break;
360118611Snjl
361281687Sjkim        case NODE_NAME_INTERNALIZED:
362250838Sjkim
363281687Sjkim            FlagName = "NODE_NAME_INTERNALIZED";
364281687Sjkim            break;
365118611Snjl
366281687Sjkim        case NODE_METHOD_NO_RETVAL:
367250838Sjkim
368281687Sjkim            FlagName = "NODE_METHOD_NO_RETVAL";
369281687Sjkim            break;
370118611Snjl
371281687Sjkim        case NODE_METHOD_SOME_NO_RETVAL:
372250838Sjkim
373281687Sjkim            FlagName = "NODE_METHOD_SOME_NO_RETVAL";
374281687Sjkim            break;
375118611Snjl
376281687Sjkim        case NODE_RESULT_NOT_USED:
377250838Sjkim
378281687Sjkim            FlagName = "NODE_RESULT_NOT_USED";
379281687Sjkim            break;
380118611Snjl
381281687Sjkim        case NODE_METHOD_TYPED:
382250838Sjkim
383281687Sjkim            FlagName = "NODE_METHOD_TYPED";
384281687Sjkim            break;
385118611Snjl
386306536Sjkim        case NODE_COULD_NOT_REDUCE:
387306536Sjkim
388306536Sjkim            FlagName = "NODE_COULD_NOT_REDUCE";
389306536Sjkim            break;
390306536Sjkim
391281687Sjkim        case NODE_COMPILE_TIME_CONST:
392250838Sjkim
393281687Sjkim            FlagName = "NODE_COMPILE_TIME_CONST";
394281687Sjkim            break;
395118611Snjl
396281687Sjkim        case NODE_IS_TERM_ARG:
397250838Sjkim
398281687Sjkim            FlagName = "NODE_IS_TERM_ARG";
399281687Sjkim            break;
400118611Snjl
401281687Sjkim        case NODE_WAS_ONES_OP:
402250838Sjkim
403281687Sjkim            FlagName = "NODE_WAS_ONES_OP";
404281687Sjkim            break;
405118611Snjl
406281687Sjkim        case NODE_IS_NAME_DECLARATION:
407250838Sjkim
408281687Sjkim            FlagName = "NODE_IS_NAME_DECLARATION";
409281687Sjkim            break;
410118611Snjl
411281687Sjkim        case NODE_COMPILER_EMITTED:
412250838Sjkim
413281687Sjkim            FlagName = "NODE_COMPILER_EMITTED";
414281687Sjkim            break;
415281687Sjkim
416281687Sjkim        case NODE_IS_DUPLICATE:
417281687Sjkim
418281687Sjkim            FlagName = "NODE_IS_DUPLICATE";
419281687Sjkim            break;
420281687Sjkim
421281687Sjkim        case NODE_IS_RESOURCE_DATA:
422281687Sjkim
423281687Sjkim            FlagName = "NODE_IS_RESOURCE_DATA";
424281687Sjkim            break;
425281687Sjkim
426281687Sjkim        case NODE_IS_NULL_RETURN:
427281687Sjkim
428281687Sjkim            FlagName = "NODE_IS_NULL_RETURN";
429281687Sjkim            break;
430281687Sjkim
431281687Sjkim        default:
432281687Sjkim            break;
433281687Sjkim        }
434281687Sjkim
435281687Sjkim        if (FlagName)
436281687Sjkim        {
437281687Sjkim            DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
438281687Sjkim            FlagName = NULL;
439281687Sjkim        }
440281687Sjkim
441281687Sjkim        FlagBit <<= 1;
442118611Snjl    }
443118611Snjl}
444118611Snjl
445118611Snjl
446118611Snjl/*******************************************************************************
447118611Snjl *
448118611Snjl * FUNCTION:    TrSetNodeFlags
449118611Snjl *
450151937Sjkim * PARAMETERS:  Op                  - An existing parse node
451118611Snjl *              Flags               - New flags word
452118611Snjl *
453151937Sjkim * RETURN:      The updated parser op
454118611Snjl *
455239340Sjkim * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
456118611Snjl *
457118611Snjl ******************************************************************************/
458118611Snjl
459118611SnjlACPI_PARSE_OBJECT *
460118611SnjlTrSetNodeFlags (
461118611Snjl    ACPI_PARSE_OBJECT       *Op,
462118611Snjl    UINT32                  Flags)
463118611Snjl{
464118611Snjl
465118611Snjl    if (!Op)
466118611Snjl    {
467241973Sjkim        return (NULL);
468118611Snjl    }
469118611Snjl
470281687Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
471281687Sjkim        "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
472281687Sjkim
473281687Sjkim    TrPrintNodeCompileFlags (Flags);
474281687Sjkim    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
475281687Sjkim
476118611Snjl    Op->Asl.CompileFlags |= Flags;
477239340Sjkim    return (Op);
478239340Sjkim}
479118611Snjl
480239340Sjkim
481239340Sjkim/*******************************************************************************
482239340Sjkim *
483239340Sjkim * FUNCTION:    TrSetNodeAmlLength
484239340Sjkim *
485239340Sjkim * PARAMETERS:  Op                  - An existing parse node
486239340Sjkim *              Length              - AML Length
487239340Sjkim *
488239340Sjkim * RETURN:      The updated parser op
489239340Sjkim *
490239340Sjkim * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
491239340Sjkim *              the presence of a node that must be reduced to a fixed length
492239340Sjkim *              constant.
493239340Sjkim *
494239340Sjkim ******************************************************************************/
495239340Sjkim
496239340SjkimACPI_PARSE_OBJECT *
497239340SjkimTrSetNodeAmlLength (
498239340Sjkim    ACPI_PARSE_OBJECT       *Op,
499239340Sjkim    UINT32                  Length)
500239340Sjkim{
501239340Sjkim
502239340Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
503239340Sjkim        "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
504239340Sjkim
505239340Sjkim    if (!Op)
506239340Sjkim    {
507241973Sjkim        return (NULL);
508239340Sjkim    }
509239340Sjkim
510239340Sjkim    Op->Asl.AmlLength = Length;
511239340Sjkim    return (Op);
512118611Snjl}
513118611Snjl
514118611Snjl
515118611Snjl/*******************************************************************************
516118611Snjl *
517118611Snjl * FUNCTION:    TrSetEndLineNumber
518118611Snjl *
519118611Snjl * PARAMETERS:  Op                - An existing parse node
520118611Snjl *
521118611Snjl * RETURN:      None.
522118611Snjl *
523118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
524118611Snjl *              parse node to the current line numbers.
525118611Snjl *
526118611Snjl ******************************************************************************/
527118611Snjl
528118611Snjlvoid
529118611SnjlTrSetEndLineNumber (
530118611Snjl    ACPI_PARSE_OBJECT       *Op)
531118611Snjl{
532118611Snjl
533118611Snjl    /* If the end line # is already set, just return */
534118611Snjl
535118611Snjl    if (Op->Asl.EndLine)
536118611Snjl    {
537118611Snjl        return;
538118611Snjl    }
539118611Snjl
540306536Sjkim    Op->Asl.EndLine = Gbl_CurrentLineNumber;
541118611Snjl    Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
542118611Snjl}
543118611Snjl
544118611Snjl
545118611Snjl/*******************************************************************************
546118611Snjl *
547281075Sdim * FUNCTION:    TrCreateAssignmentNode
548281075Sdim *
549281075Sdim * PARAMETERS:  Target              - Assignment target
550281075Sdim *              Source              - Assignment source
551281075Sdim *
552281075Sdim * RETURN:      Pointer to the new node. Aborts on allocation failure
553281075Sdim *
554281075Sdim * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
555281075Sdim *              tree if possible to utilize the last argument of the math
556281075Sdim *              operators which is a target operand -- thus saving invocation
557281075Sdim *              of and additional Store() operator. An optimization.
558281075Sdim *
559281075Sdim ******************************************************************************/
560281075Sdim
561281075SdimACPI_PARSE_OBJECT *
562281075SdimTrCreateAssignmentNode (
563281075Sdim    ACPI_PARSE_OBJECT       *Target,
564281075Sdim    ACPI_PARSE_OBJECT       *Source)
565281075Sdim{
566281075Sdim    ACPI_PARSE_OBJECT       *TargetOp;
567281075Sdim    ACPI_PARSE_OBJECT       *SourceOp1;
568281075Sdim    ACPI_PARSE_OBJECT       *SourceOp2;
569281075Sdim    ACPI_PARSE_OBJECT       *Operator;
570281075Sdim
571281075Sdim
572281075Sdim    DbgPrint (ASL_PARSE_OUTPUT,
573281075Sdim        "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
574281075Sdim        Source->Asl.LineNumber, Source->Asl.EndLine,
575281075Sdim        UtGetOpName (Source->Asl.ParseOpcode),
576281075Sdim        UtGetOpName (Target->Asl.ParseOpcode));
577281075Sdim
578281075Sdim    TrSetNodeFlags (Target, NODE_IS_TARGET);
579281075Sdim
580281075Sdim    switch (Source->Asl.ParseOpcode)
581281075Sdim    {
582281075Sdim    /*
583281075Sdim     * Only these operators can be optimized because they have
584281075Sdim     * a target operand
585281075Sdim     */
586281075Sdim    case PARSEOP_ADD:
587281075Sdim    case PARSEOP_AND:
588281075Sdim    case PARSEOP_DIVIDE:
589306536Sjkim    case PARSEOP_INDEX:
590281075Sdim    case PARSEOP_MOD:
591281075Sdim    case PARSEOP_MULTIPLY:
592281075Sdim    case PARSEOP_NOT:
593281075Sdim    case PARSEOP_OR:
594281075Sdim    case PARSEOP_SHIFTLEFT:
595281075Sdim    case PARSEOP_SHIFTRIGHT:
596281075Sdim    case PARSEOP_SUBTRACT:
597281075Sdim    case PARSEOP_XOR:
598281075Sdim
599281075Sdim        break;
600281075Sdim
601281075Sdim    /* Otherwise, just create a normal Store operator */
602281075Sdim
603281075Sdim    default:
604281075Sdim
605281075Sdim        goto CannotOptimize;
606281075Sdim    }
607281075Sdim
608281075Sdim    /*
609281075Sdim     * Transform the parse tree such that the target is moved to the
610281075Sdim     * last operand of the operator
611281075Sdim     */
612281075Sdim    SourceOp1 = Source->Asl.Child;
613281075Sdim    SourceOp2 = SourceOp1->Asl.Next;
614281075Sdim
615281075Sdim    /* NOT only has one operand, but has a target */
616281075Sdim
617281075Sdim    if (Source->Asl.ParseOpcode == PARSEOP_NOT)
618281075Sdim    {
619281075Sdim        SourceOp2 = SourceOp1;
620281075Sdim    }
621281075Sdim
622281075Sdim    /* DIVIDE has an extra target operand (remainder) */
623281075Sdim
624281075Sdim    if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
625281075Sdim    {
626281075Sdim        SourceOp2 = SourceOp2->Asl.Next;
627281075Sdim    }
628281075Sdim
629281075Sdim    TargetOp = SourceOp2->Asl.Next;
630281075Sdim
631281075Sdim    /*
632281075Sdim     * Can't perform this optimization if there already is a target
633281075Sdim     * for the operator (ZERO is a "no target" placeholder).
634281075Sdim     */
635281075Sdim    if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
636281075Sdim    {
637281075Sdim        goto CannotOptimize;
638281075Sdim    }
639281075Sdim
640281075Sdim    /* Link in the target as the final operand */
641281075Sdim
642281075Sdim    SourceOp2->Asl.Next = Target;
643281075Sdim    Target->Asl.Parent = Source;
644281075Sdim
645281075Sdim    return (Source);
646281075Sdim
647281075Sdim
648281075SdimCannotOptimize:
649281075Sdim
650281075Sdim    Operator = TrAllocateNode (PARSEOP_STORE);
651281075Sdim    TrLinkChildren (Operator, 2, Source, Target);
652281075Sdim
653281075Sdim    /* Set the appropriate line numbers for the new node */
654281075Sdim
655281075Sdim    Operator->Asl.LineNumber        = Target->Asl.LineNumber;
656281075Sdim    Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
657281075Sdim    Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
658281075Sdim    Operator->Asl.Column            = Target->Asl.Column;
659281075Sdim
660281075Sdim    return (Operator);
661281075Sdim}
662281075Sdim
663281075Sdim
664281075Sdim/*******************************************************************************
665281075Sdim *
666118611Snjl * FUNCTION:    TrCreateLeafNode
667118611Snjl *
668118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
669118611Snjl *
670239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
671118611Snjl *
672118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
673118611Snjl *              assigned to the node)
674118611Snjl *
675118611Snjl ******************************************************************************/
676118611Snjl
677118611SnjlACPI_PARSE_OBJECT *
678118611SnjlTrCreateLeafNode (
679118611Snjl    UINT32                  ParseOpcode)
680118611Snjl{
681118611Snjl    ACPI_PARSE_OBJECT       *Op;
682118611Snjl
683118611Snjl
684118611Snjl    Op = TrAllocateNode (ParseOpcode);
685118611Snjl
686118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
687209746Sjkim        "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
688281687Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
689118611Snjl
690241973Sjkim    return (Op);
691118611Snjl}
692118611Snjl
693118611Snjl
694118611Snjl/*******************************************************************************
695118611Snjl *
696281687Sjkim * FUNCTION:    TrCreateNullTarget
697281687Sjkim *
698281687Sjkim * PARAMETERS:  None
699281687Sjkim *
700281687Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
701281687Sjkim *
702281687Sjkim * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
703281687Sjkim *              specification to be a zero AML opcode, and indicates that
704281687Sjkim *              no target has been specified for the parent operation
705281687Sjkim *
706281687Sjkim ******************************************************************************/
707281687Sjkim
708281687SjkimACPI_PARSE_OBJECT *
709281687SjkimTrCreateNullTarget (
710281687Sjkim    void)
711281687Sjkim{
712281687Sjkim    ACPI_PARSE_OBJECT       *Op;
713281687Sjkim
714281687Sjkim
715281687Sjkim    Op = TrAllocateNode (PARSEOP_ZERO);
716281687Sjkim    Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
717281687Sjkim
718281687Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
719281687Sjkim        "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
720281687Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op,
721281687Sjkim        UtGetOpName (Op->Asl.ParseOpcode));
722281687Sjkim
723281687Sjkim    return (Op);
724281687Sjkim}
725281687Sjkim
726281687Sjkim
727281687Sjkim/*******************************************************************************
728281687Sjkim *
729218590Sjkim * FUNCTION:    TrCreateConstantLeafNode
730218590Sjkim *
731218590Sjkim * PARAMETERS:  ParseOpcode         - The constant opcode
732218590Sjkim *
733239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
734218590Sjkim *
735218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the
736218590Sjkim *              special constants - __LINE__, __FILE__, and __DATE__.
737218590Sjkim *
738218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't
739218590Sjkim * have a full parse tree at this time and cannot find the parent control
740218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after
741218590Sjkim * the parse tree has been fully constructed.
742218590Sjkim *
743218590Sjkim ******************************************************************************/
744218590Sjkim
745218590SjkimACPI_PARSE_OBJECT *
746218590SjkimTrCreateConstantLeafNode (
747218590Sjkim    UINT32                  ParseOpcode)
748218590Sjkim{
749218590Sjkim    ACPI_PARSE_OBJECT       *Op = NULL;
750218590Sjkim    time_t                  CurrentTime;
751218590Sjkim    char                    *StaticTimeString;
752218590Sjkim    char                    *TimeString;
753228110Sjkim    char                    *Filename;
754218590Sjkim
755218590Sjkim
756218590Sjkim    switch (ParseOpcode)
757218590Sjkim    {
758218590Sjkim    case PARSEOP___LINE__:
759250838Sjkim
760218590Sjkim        Op = TrAllocateNode (PARSEOP_INTEGER);
761218590Sjkim        Op->Asl.Value.Integer = Op->Asl.LineNumber;
762218590Sjkim        break;
763218590Sjkim
764228110Sjkim    case PARSEOP___PATH__:
765250838Sjkim
766218590Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
767218590Sjkim
768218590Sjkim        /* Op.Asl.Filename contains the full pathname to the file */
769218590Sjkim
770218590Sjkim        Op->Asl.Value.String = Op->Asl.Filename;
771218590Sjkim        break;
772218590Sjkim
773228110Sjkim    case PARSEOP___FILE__:
774250838Sjkim
775218590Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
776218590Sjkim
777228110Sjkim        /* Get the simple filename from the full path */
778228110Sjkim
779281687Sjkim        FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
780228110Sjkim        Op->Asl.Value.String = Filename;
781228110Sjkim        break;
782228110Sjkim
783228110Sjkim    case PARSEOP___DATE__:
784250838Sjkim
785228110Sjkim        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
786228110Sjkim
787218590Sjkim        /* Get a copy of the current time */
788218590Sjkim
789218590Sjkim        CurrentTime = time (NULL);
790218590Sjkim        StaticTimeString = ctime (&CurrentTime);
791218590Sjkim        TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
792218590Sjkim        strcpy (TimeString, StaticTimeString);
793218590Sjkim
794218590Sjkim        TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
795218590Sjkim        Op->Asl.Value.String = TimeString;
796218590Sjkim        break;
797218590Sjkim
798218590Sjkim    default: /* This would be an internal error */
799250838Sjkim
800218590Sjkim        return (NULL);
801218590Sjkim    }
802218590Sjkim
803218590Sjkim    DbgPrint (ASL_PARSE_OUTPUT,
804306536Sjkim        "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  "
805306536Sjkim        "Op %s  Value %8.8X%8.8X  \n",
806218590Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
807218590Sjkim        ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
808218590Sjkim    return (Op);
809218590Sjkim}
810218590Sjkim
811218590Sjkim
812218590Sjkim/*******************************************************************************
813218590Sjkim *
814281075Sdim * FUNCTION:    TrCreateTargetOperand
815281075Sdim *
816281075Sdim * PARAMETERS:  OriginalOp          - Op to be copied
817281075Sdim *
818281075Sdim * RETURN:      Pointer to the new node. Aborts on allocation failure
819281075Sdim *
820281075Sdim * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
821281075Sdim *              expressions where the target is the same as one of the
822281075Sdim *              operands. A new node and subtree must be created from the
823281075Sdim *              original so that the parse tree can be linked properly.
824281075Sdim *
825281075Sdim * NOTE:        This code is specific to target operands that are the last
826281075Sdim *              operand in an ASL/AML operator. Meaning that the top-level
827281075Sdim *              parse Op in a possible subtree has a NULL Next pointer.
828281075Sdim *              This simplifies the recursion.
829281075Sdim *
830281075Sdim *              Subtree example:
831281075Sdim *                  DeRefOf (Local1) += 32
832281075Sdim *
833281075Sdim *              This gets converted to:
834281075Sdim *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
835281075Sdim *
836281075Sdim *              Each DeRefOf has a single child, Local1. Even more complex
837281075Sdim *              subtrees can be created via the Index and DeRefOf operators.
838281075Sdim *
839281075Sdim ******************************************************************************/
840281075Sdim
841281075SdimACPI_PARSE_OBJECT *
842281075SdimTrCreateTargetOperand (
843281075Sdim    ACPI_PARSE_OBJECT       *OriginalOp,
844281075Sdim    ACPI_PARSE_OBJECT       *ParentOp)
845281075Sdim{
846281075Sdim    ACPI_PARSE_OBJECT       *Op;
847281075Sdim
848281075Sdim
849281075Sdim    if (!OriginalOp)
850281075Sdim    {
851281075Sdim        return (NULL);
852281075Sdim    }
853281075Sdim
854281075Sdim    Op = TrGetNextNode ();
855281075Sdim
856281075Sdim    /* Copy the pertinent values (omit link pointer fields) */
857281075Sdim
858281075Sdim    Op->Asl.Value               = OriginalOp->Asl.Value;
859281075Sdim    Op->Asl.Filename            = OriginalOp->Asl.Filename;
860281075Sdim    Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
861281075Sdim    Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
862281075Sdim    Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
863281075Sdim    Op->Asl.Column              = OriginalOp->Asl.Column;
864281075Sdim    Op->Asl.Flags               = OriginalOp->Asl.Flags;
865281075Sdim    Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
866281075Sdim    Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
867281075Sdim    Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
868281075Sdim    Op->Asl.Parent              = ParentOp;
869281075Sdim    UtSetParseOpName (Op);
870281075Sdim
871281075Sdim    /* Copy a possible subtree below this node */
872281075Sdim
873281075Sdim    if (OriginalOp->Asl.Child)
874281075Sdim    {
875281075Sdim        Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
876281075Sdim    }
877281075Sdim
878281075Sdim    if (OriginalOp->Asl.Next) /* Null for top-level node */
879281075Sdim    {
880281075Sdim        Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
881281075Sdim    }
882281075Sdim
883281075Sdim    return (Op);
884281075Sdim}
885281075Sdim
886281075Sdim
887281075Sdim/*******************************************************************************
888281075Sdim *
889118611Snjl * FUNCTION:    TrCreateValuedLeafNode
890118611Snjl *
891118611Snjl * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
892118611Snjl *              Value               - Value to be assigned to the node
893118611Snjl *
894239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
895118611Snjl *
896118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value
897118611Snjl *              assigned to it
898118611Snjl *
899118611Snjl ******************************************************************************/
900118611Snjl
901118611SnjlACPI_PARSE_OBJECT *
902118611SnjlTrCreateValuedLeafNode (
903118611Snjl    UINT32                  ParseOpcode,
904202771Sjkim    UINT64                  Value)
905118611Snjl{
906118611Snjl    ACPI_PARSE_OBJECT       *Op;
907118611Snjl
908118611Snjl
909118611Snjl    Op = TrAllocateNode (ParseOpcode);
910118611Snjl
911118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
912306536Sjkim        "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  "
913306536Sjkim        "Op %s  Value %8.8X%8.8X  ",
914167802Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
915123315Snjl        ACPI_FORMAT_UINT64 (Value));
916118611Snjl    Op->Asl.Value.Integer = Value;
917118611Snjl
918118611Snjl    switch (ParseOpcode)
919118611Snjl    {
920118611Snjl    case PARSEOP_STRING_LITERAL:
921250838Sjkim
922118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
923118611Snjl        break;
924118611Snjl
925118611Snjl    case PARSEOP_NAMESEG:
926250838Sjkim
927118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
928118611Snjl        break;
929118611Snjl
930118611Snjl    case PARSEOP_NAMESTRING:
931250838Sjkim
932118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
933118611Snjl        break;
934118611Snjl
935118611Snjl    case PARSEOP_EISAID:
936250838Sjkim
937118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
938118611Snjl        break;
939118611Snjl
940118611Snjl    case PARSEOP_METHOD:
941250838Sjkim
942118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
943118611Snjl        break;
944118611Snjl
945118611Snjl    case PARSEOP_INTEGER:
946250838Sjkim
947281687Sjkim        DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
948281687Sjkim            ACPI_FORMAT_UINT64 (Value));
949118611Snjl        break;
950118611Snjl
951118611Snjl    default:
952250838Sjkim
953118611Snjl        break;
954118611Snjl    }
955118611Snjl
956118611Snjl    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
957241973Sjkim    return (Op);
958118611Snjl}
959118611Snjl
960118611Snjl
961118611Snjl/*******************************************************************************
962118611Snjl *
963118611Snjl * FUNCTION:    TrCreateNode
964118611Snjl *
965118611Snjl * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
966118611Snjl *              NumChildren         - Number of children to follow
967118611Snjl *              ...                 - A list of child nodes to link to the new
968239340Sjkim *                                    node. NumChildren long.
969118611Snjl *
970239340Sjkim * RETURN:      Pointer to the new node. Aborts on allocation failure
971118611Snjl *
972118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child
973118611Snjl *              nodes underneath the new node.
974118611Snjl *
975118611Snjl ******************************************************************************/
976118611Snjl
977118611SnjlACPI_PARSE_OBJECT *
978118611SnjlTrCreateNode (
979118611Snjl    UINT32                  ParseOpcode,
980118611Snjl    UINT32                  NumChildren,
981118611Snjl    ...)
982118611Snjl{
983118611Snjl    ACPI_PARSE_OBJECT       *Op;
984118611Snjl    ACPI_PARSE_OBJECT       *Child;
985118611Snjl    ACPI_PARSE_OBJECT       *PrevChild;
986118611Snjl    va_list                 ap;
987118611Snjl    UINT32                  i;
988118611Snjl    BOOLEAN                 FirstChild;
989118611Snjl
990118611Snjl
991118611Snjl    va_start (ap, NumChildren);
992118611Snjl
993118611Snjl    /* Allocate one new node */
994118611Snjl
995118611Snjl    Op = TrAllocateNode (ParseOpcode);
996118611Snjl
997118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
998209746Sjkim        "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
999306536Sjkim        Op->Asl.LineNumber, Op->Asl.Column, Op,
1000306536Sjkim        NumChildren, UtGetOpName(ParseOpcode));
1001118611Snjl
1002118611Snjl    /* Some extra debug output based on the parse opcode */
1003118611Snjl
1004118611Snjl    switch (ParseOpcode)
1005118611Snjl    {
1006306536Sjkim    case PARSEOP_ASL_CODE:
1007250838Sjkim
1008306536Sjkim        Gbl_ParseTreeRoot = Op;
1009306536Sjkim        Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1010306536Sjkim        DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1011306536Sjkim        break;
1012306536Sjkim
1013306536Sjkim    case PARSEOP_DEFINITION_BLOCK:
1014306536Sjkim
1015118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1016118611Snjl        break;
1017118611Snjl
1018118611Snjl    case PARSEOP_OPERATIONREGION:
1019250838Sjkim
1020118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1021118611Snjl        break;
1022118611Snjl
1023118611Snjl    case PARSEOP_OR:
1024250838Sjkim
1025118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1026118611Snjl        break;
1027118611Snjl
1028118611Snjl    default:
1029250838Sjkim
1030118611Snjl        /* Nothing to do for other opcodes */
1031250838Sjkim
1032118611Snjl        break;
1033118611Snjl    }
1034118611Snjl
1035118611Snjl    /* Link the new node to its children */
1036118611Snjl
1037118611Snjl    PrevChild = NULL;
1038118611Snjl    FirstChild = TRUE;
1039118611Snjl    for (i = 0; i < NumChildren; i++)
1040118611Snjl    {
1041118611Snjl        /* Get the next child */
1042118611Snjl
1043118611Snjl        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1044118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1045118611Snjl
1046118611Snjl        /*
1047118611Snjl         * If child is NULL, this means that an optional argument
1048239340Sjkim         * was omitted. We must create a placeholder with a special
1049118611Snjl         * opcode (DEFAULT_ARG) so that the code generator will know
1050118611Snjl         * that it must emit the correct default for this argument
1051118611Snjl         */
1052118611Snjl        if (!Child)
1053118611Snjl        {
1054118611Snjl            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1055118611Snjl        }
1056118611Snjl
1057118611Snjl        /* Link first child to parent */
1058118611Snjl
1059118611Snjl        if (FirstChild)
1060118611Snjl        {
1061118611Snjl            FirstChild = FALSE;
1062118611Snjl            Op->Asl.Child = Child;
1063118611Snjl        }
1064118611Snjl
1065118611Snjl        /* Point all children to parent */
1066118611Snjl
1067118611Snjl        Child->Asl.Parent = Op;
1068118611Snjl
1069118611Snjl        /* Link children in a peer list */
1070118611Snjl
1071118611Snjl        if (PrevChild)
1072118611Snjl        {
1073118611Snjl            PrevChild->Asl.Next = Child;
1074118611Snjl        };
1075118611Snjl
1076118611Snjl        /*
1077118611Snjl         * This child might be a list, point all nodes in the list
1078118611Snjl         * to the same parent
1079118611Snjl         */
1080118611Snjl        while (Child->Asl.Next)
1081118611Snjl        {
1082118611Snjl            Child = Child->Asl.Next;
1083118611Snjl            Child->Asl.Parent = Op;
1084118611Snjl        }
1085118611Snjl
1086118611Snjl        PrevChild = Child;
1087118611Snjl    }
1088118611Snjl    va_end(ap);
1089118611Snjl
1090281687Sjkim    DbgPrint (ASL_PARSE_OUTPUT, "\n");
1091241973Sjkim    return (Op);
1092118611Snjl}
1093118611Snjl
1094118611Snjl
1095118611Snjl/*******************************************************************************
1096118611Snjl *
1097118611Snjl * FUNCTION:    TrLinkChildren
1098118611Snjl *
1099118611Snjl * PARAMETERS:  Op                - An existing parse node
1100118611Snjl *              NumChildren         - Number of children to follow
1101118611Snjl *              ...                 - A list of child nodes to link to the new
1102239340Sjkim *                                    node. NumChildren long.
1103118611Snjl *
1104118611Snjl * RETURN:      The updated (linked) node
1105118611Snjl *
1106118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node
1107118611Snjl *
1108118611Snjl ******************************************************************************/
1109118611Snjl
1110118611SnjlACPI_PARSE_OBJECT *
1111118611SnjlTrLinkChildren (
1112118611Snjl    ACPI_PARSE_OBJECT       *Op,
1113118611Snjl    UINT32                  NumChildren,
1114118611Snjl    ...)
1115118611Snjl{
1116118611Snjl    ACPI_PARSE_OBJECT       *Child;
1117118611Snjl    ACPI_PARSE_OBJECT       *PrevChild;
1118118611Snjl    va_list                 ap;
1119118611Snjl    UINT32                  i;
1120118611Snjl    BOOLEAN                 FirstChild;
1121118611Snjl
1122118611Snjl
1123118611Snjl    va_start (ap, NumChildren);
1124118611Snjl
1125118611Snjl
1126118611Snjl    TrSetEndLineNumber (Op);
1127118611Snjl
1128118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
1129209746Sjkim        "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
1130118611Snjl        Op->Asl.LineNumber, Op->Asl.EndLine,
1131118611Snjl        Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1132118611Snjl
1133118611Snjl    switch (Op->Asl.ParseOpcode)
1134118611Snjl    {
1135306536Sjkim    case PARSEOP_ASL_CODE:
1136250838Sjkim
1137306536Sjkim        Gbl_ParseTreeRoot = Op;
1138306536Sjkim        Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1139306536Sjkim        DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1140306536Sjkim        break;
1141306536Sjkim
1142306536Sjkim    case PARSEOP_DEFINITION_BLOCK:
1143306536Sjkim
1144118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1145118611Snjl        break;
1146118611Snjl
1147118611Snjl    case PARSEOP_OPERATIONREGION:
1148250838Sjkim
1149118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1150118611Snjl        break;
1151118611Snjl
1152118611Snjl    case PARSEOP_OR:
1153250838Sjkim
1154118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1155118611Snjl        break;
1156118611Snjl
1157118611Snjl    default:
1158250838Sjkim
1159118611Snjl        /* Nothing to do for other opcodes */
1160250838Sjkim
1161118611Snjl        break;
1162118611Snjl    }
1163118611Snjl
1164118611Snjl    /* Link the new node to it's children */
1165118611Snjl
1166118611Snjl    PrevChild = NULL;
1167118611Snjl    FirstChild = TRUE;
1168118611Snjl    for (i = 0; i < NumChildren; i++)
1169118611Snjl    {
1170118611Snjl        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1171118611Snjl
1172118611Snjl        if ((Child == PrevChild) && (Child != NULL))
1173118611Snjl        {
1174151937Sjkim            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1175151937Sjkim                "Child node list invalid");
1176252279Sjkim            va_end(ap);
1177241973Sjkim            return (Op);
1178118611Snjl        }
1179118611Snjl
1180118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1181118611Snjl
1182118611Snjl        /*
1183118611Snjl         * If child is NULL, this means that an optional argument
1184239340Sjkim         * was omitted. We must create a placeholder with a special
1185118611Snjl         * opcode (DEFAULT_ARG) so that the code generator will know
1186118611Snjl         * that it must emit the correct default for this argument
1187118611Snjl         */
1188118611Snjl        if (!Child)
1189118611Snjl        {
1190118611Snjl            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1191118611Snjl        }
1192118611Snjl
1193118611Snjl        /* Link first child to parent */
1194118611Snjl
1195118611Snjl        if (FirstChild)
1196118611Snjl        {
1197118611Snjl            FirstChild = FALSE;
1198118611Snjl            Op->Asl.Child = Child;
1199118611Snjl        }
1200118611Snjl
1201118611Snjl        /* Point all children to parent */
1202118611Snjl
1203118611Snjl        Child->Asl.Parent = Op;
1204118611Snjl
1205118611Snjl        /* Link children in a peer list */
1206118611Snjl
1207118611Snjl        if (PrevChild)
1208118611Snjl        {
1209118611Snjl            PrevChild->Asl.Next = Child;
1210118611Snjl        };
1211118611Snjl
1212118611Snjl        /*
1213118611Snjl         * This child might be a list, point all nodes in the list
1214118611Snjl         * to the same parent
1215118611Snjl         */
1216118611Snjl        while (Child->Asl.Next)
1217118611Snjl        {
1218118611Snjl            Child = Child->Asl.Next;
1219118611Snjl            Child->Asl.Parent = Op;
1220118611Snjl        }
1221306536Sjkim
1222118611Snjl        PrevChild = Child;
1223118611Snjl    }
1224252279Sjkim
1225118611Snjl    va_end(ap);
1226118611Snjl    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1227241973Sjkim    return (Op);
1228118611Snjl}
1229118611Snjl
1230118611Snjl
1231118611Snjl/*******************************************************************************
1232118611Snjl *
1233118611Snjl * FUNCTION:    TrLinkPeerNode
1234118611Snjl *
1235118611Snjl * PARAMETERS:  Op1           - First peer
1236118611Snjl *              Op2           - Second peer
1237118611Snjl *
1238118611Snjl * RETURN:      Op1 or the non-null node.
1239118611Snjl *
1240239340Sjkim * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1241118611Snjl *
1242118611Snjl ******************************************************************************/
1243118611Snjl
1244118611SnjlACPI_PARSE_OBJECT *
1245118611SnjlTrLinkPeerNode (
1246118611Snjl    ACPI_PARSE_OBJECT       *Op1,
1247118611Snjl    ACPI_PARSE_OBJECT       *Op2)
1248118611Snjl{
1249118611Snjl    ACPI_PARSE_OBJECT       *Next;
1250118611Snjl
1251118611Snjl
1252118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
1253281687Sjkim        "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1254118611Snjl        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1255118611Snjl        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1256118611Snjl
1257118611Snjl
1258118611Snjl    if ((!Op1) && (!Op2))
1259118611Snjl    {
1260118611Snjl        DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1261241973Sjkim        return (Op1);
1262118611Snjl    }
1263118611Snjl
1264118611Snjl    /* If one of the nodes is null, just return the non-null node */
1265118611Snjl
1266118611Snjl    if (!Op2)
1267118611Snjl    {
1268241973Sjkim        return (Op1);
1269118611Snjl    }
1270118611Snjl
1271118611Snjl    if (!Op1)
1272118611Snjl    {
1273241973Sjkim        return (Op2);
1274118611Snjl    }
1275118611Snjl
1276118611Snjl    if (Op1 == Op2)
1277118611Snjl    {
1278118611Snjl        DbgPrint (ASL_DEBUG_OUTPUT,
1279281687Sjkim            "\n************* Internal error, linking node to itself %p\n",
1280151937Sjkim            Op1);
1281151937Sjkim        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1282151937Sjkim            "Linking node to itself");
1283241973Sjkim        return (Op1);
1284118611Snjl    }
1285118611Snjl
1286118611Snjl    Op1->Asl.Parent = Op2->Asl.Parent;
1287118611Snjl
1288118611Snjl    /*
1289118611Snjl     * Op 1 may already have a peer list (such as an IF/ELSE pair),
1290118611Snjl     * so we must walk to the end of the list and attach the new
1291118611Snjl     * peer at the end
1292118611Snjl     */
1293118611Snjl    Next = Op1;
1294118611Snjl    while (Next->Asl.Next)
1295118611Snjl    {
1296118611Snjl        Next = Next->Asl.Next;
1297118611Snjl    }
1298118611Snjl
1299118611Snjl    Next->Asl.Next = Op2;
1300241973Sjkim    return (Op1);
1301118611Snjl}
1302118611Snjl
1303118611Snjl
1304118611Snjl/*******************************************************************************
1305118611Snjl *
1306118611Snjl * FUNCTION:    TrLinkPeerNodes
1307118611Snjl *
1308118611Snjl * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
1309118611Snjl *              ...                 - A list of nodes to link together as peers
1310118611Snjl *
1311118611Snjl * RETURN:      The first node in the list (head of the peer list)
1312118611Snjl *
1313118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes.
1314118611Snjl *
1315118611Snjl ******************************************************************************/
1316118611Snjl
1317118611SnjlACPI_PARSE_OBJECT *
1318118611SnjlTrLinkPeerNodes (
1319118611Snjl    UINT32                  NumPeers,
1320118611Snjl    ...)
1321118611Snjl{
1322118611Snjl    ACPI_PARSE_OBJECT       *This;
1323118611Snjl    ACPI_PARSE_OBJECT       *Next;
1324118611Snjl    va_list                 ap;
1325118611Snjl    UINT32                  i;
1326118611Snjl    ACPI_PARSE_OBJECT       *Start;
1327118611Snjl
1328118611Snjl
1329118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
1330209746Sjkim        "\nLinkPeerNodes: (%u) ", NumPeers);
1331118611Snjl
1332118611Snjl    va_start (ap, NumPeers);
1333118611Snjl    This = va_arg (ap, ACPI_PARSE_OBJECT *);
1334118611Snjl    Start = This;
1335118611Snjl
1336118611Snjl    /*
1337118611Snjl     * Link all peers
1338118611Snjl     */
1339118611Snjl    for (i = 0; i < (NumPeers -1); i++)
1340118611Snjl    {
1341209746Sjkim        DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1342118611Snjl
1343118611Snjl        while (This->Asl.Next)
1344118611Snjl        {
1345118611Snjl            This = This->Asl.Next;
1346118611Snjl        }
1347118611Snjl
1348118611Snjl        /* Get another peer node */
1349118611Snjl
1350118611Snjl        Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1351118611Snjl        if (!Next)
1352118611Snjl        {
1353118611Snjl            Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1354118611Snjl        }
1355118611Snjl
1356118611Snjl        /* link new node to the current node */
1357118611Snjl
1358118611Snjl        This->Asl.Next = Next;
1359118611Snjl        This = Next;
1360118611Snjl    }
1361193529Sjkim    va_end (ap);
1362118611Snjl
1363281687Sjkim    DbgPrint (ASL_PARSE_OUTPUT,"\n");
1364118611Snjl    return (Start);
1365118611Snjl}
1366118611Snjl
1367118611Snjl
1368118611Snjl/*******************************************************************************
1369118611Snjl *
1370118611Snjl * FUNCTION:    TrLinkChildNode
1371118611Snjl *
1372118611Snjl * PARAMETERS:  Op1           - Parent node
1373118611Snjl *              Op2           - Op to become a child
1374118611Snjl *
1375118611Snjl * RETURN:      The parent node
1376118611Snjl *
1377118611Snjl * DESCRIPTION: Link two nodes together as a parent and child
1378118611Snjl *
1379118611Snjl ******************************************************************************/
1380118611Snjl
1381118611SnjlACPI_PARSE_OBJECT *
1382118611SnjlTrLinkChildNode (
1383118611Snjl    ACPI_PARSE_OBJECT       *Op1,
1384118611Snjl    ACPI_PARSE_OBJECT       *Op2)
1385118611Snjl{
1386118611Snjl    ACPI_PARSE_OBJECT       *Next;
1387118611Snjl
1388118611Snjl
1389118611Snjl    DbgPrint (ASL_PARSE_OUTPUT,
1390281687Sjkim        "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1391118611Snjl        Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1392118611Snjl        Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1393118611Snjl
1394118611Snjl    if (!Op1 || !Op2)
1395118611Snjl    {
1396241973Sjkim        return (Op1);
1397118611Snjl    }
1398118611Snjl
1399118611Snjl    Op1->Asl.Child = Op2;
1400118611Snjl
1401118611Snjl    /* Set the child and all peers of the child to point to the parent */
1402118611Snjl
1403118611Snjl    Next = Op2;
1404118611Snjl    while (Next)
1405118611Snjl    {
1406118611Snjl        Next->Asl.Parent = Op1;
1407118611Snjl        Next = Next->Asl.Next;
1408118611Snjl    }
1409118611Snjl
1410241973Sjkim    return (Op1);
1411118611Snjl}
1412118611Snjl
1413118611Snjl
1414118611Snjl/*******************************************************************************
1415118611Snjl *
1416118611Snjl * FUNCTION:    TrWalkParseTree
1417118611Snjl *
1418118611Snjl * PARAMETERS:  Visitation              - Type of walk
1419118611Snjl *              DescendingCallback      - Called during tree descent
1420118611Snjl *              AscendingCallback       - Called during tree ascent
1421118611Snjl *              Context                 - To be passed to the callbacks
1422118611Snjl *
1423118611Snjl * RETURN:      Status from callback(s)
1424118611Snjl *
1425118611Snjl * DESCRIPTION: Walk the entire parse tree.
1426118611Snjl *
1427118611Snjl ******************************************************************************/
1428118611Snjl
1429118611SnjlACPI_STATUS
1430118611SnjlTrWalkParseTree (
1431118611Snjl    ACPI_PARSE_OBJECT       *Op,
1432118611Snjl    UINT32                  Visitation,
1433118611Snjl    ASL_WALK_CALLBACK       DescendingCallback,
1434118611Snjl    ASL_WALK_CALLBACK       AscendingCallback,
1435118611Snjl    void                    *Context)
1436118611Snjl{
1437118611Snjl    UINT32                  Level;
1438118611Snjl    BOOLEAN                 NodePreviouslyVisited;
1439118611Snjl    ACPI_PARSE_OBJECT       *StartOp = Op;
1440118611Snjl    ACPI_STATUS             Status;
1441118611Snjl
1442118611Snjl
1443306536Sjkim    if (!Gbl_ParseTreeRoot)
1444118611Snjl    {
1445118611Snjl        return (AE_OK);
1446118611Snjl    }
1447118611Snjl
1448118611Snjl    Level = 0;
1449118611Snjl    NodePreviouslyVisited = FALSE;
1450118611Snjl
1451118611Snjl    switch (Visitation)
1452118611Snjl    {
1453118611Snjl    case ASL_WALK_VISIT_DOWNWARD:
1454118611Snjl
1455118611Snjl        while (Op)
1456118611Snjl        {
1457118611Snjl            if (!NodePreviouslyVisited)
1458118611Snjl            {
1459151937Sjkim                /* Let the callback process the node. */
1460151937Sjkim
1461118611Snjl                Status = DescendingCallback (Op, Level, Context);
1462118611Snjl                if (ACPI_SUCCESS (Status))
1463118611Snjl                {
1464118611Snjl                    /* Visit children first, once */
1465118611Snjl
1466118611Snjl                    if (Op->Asl.Child)
1467118611Snjl                    {
1468118611Snjl                        Level++;
1469118611Snjl                        Op = Op->Asl.Child;
1470118611Snjl                        continue;
1471118611Snjl                    }
1472118611Snjl                }
1473118611Snjl                else if (Status != AE_CTRL_DEPTH)
1474118611Snjl                {
1475118611Snjl                    /* Exit immediately on any error */
1476118611Snjl
1477118611Snjl                    return (Status);
1478118611Snjl                }
1479118611Snjl            }
1480118611Snjl
1481118611Snjl            /* Terminate walk at start op */
1482118611Snjl
1483118611Snjl            if (Op == StartOp)
1484118611Snjl            {
1485118611Snjl                break;
1486118611Snjl            }
1487118611Snjl
1488118611Snjl            /* No more children, visit peers */
1489118611Snjl
1490118611Snjl            if (Op->Asl.Next)
1491118611Snjl            {
1492118611Snjl                Op = Op->Asl.Next;
1493118611Snjl                NodePreviouslyVisited = FALSE;
1494118611Snjl            }
1495118611Snjl            else
1496118611Snjl            {
1497118611Snjl                /* No children or peers, re-visit parent */
1498118611Snjl
1499118611Snjl                if (Level != 0 )
1500118611Snjl                {
1501118611Snjl                    Level--;
1502118611Snjl                }
1503118611Snjl                Op = Op->Asl.Parent;
1504118611Snjl                NodePreviouslyVisited = TRUE;
1505118611Snjl            }
1506118611Snjl        }
1507118611Snjl        break;
1508118611Snjl
1509118611Snjl    case ASL_WALK_VISIT_UPWARD:
1510118611Snjl
1511118611Snjl        while (Op)
1512118611Snjl        {
1513118611Snjl            /* Visit leaf node (no children) or parent node on return trip */
1514118611Snjl
1515118611Snjl            if ((!Op->Asl.Child) ||
1516118611Snjl                (NodePreviouslyVisited))
1517118611Snjl            {
1518151937Sjkim                /* Let the callback process the node. */
1519151937Sjkim
1520118611Snjl                Status = AscendingCallback (Op, Level, Context);
1521118611Snjl                if (ACPI_FAILURE (Status))
1522118611Snjl                {
1523118611Snjl                    return (Status);
1524118611Snjl                }
1525118611Snjl            }
1526118611Snjl            else
1527118611Snjl            {
1528118611Snjl                /* Visit children first, once */
1529118611Snjl
1530118611Snjl                Level++;
1531118611Snjl                Op = Op->Asl.Child;
1532118611Snjl                continue;
1533118611Snjl            }
1534118611Snjl
1535118611Snjl            /* Terminate walk at start op */
1536118611Snjl
1537118611Snjl            if (Op == StartOp)
1538118611Snjl            {
1539118611Snjl                break;
1540118611Snjl            }
1541118611Snjl
1542118611Snjl            /* No more children, visit peers */
1543118611Snjl
1544118611Snjl            if (Op->Asl.Next)
1545118611Snjl            {
1546118611Snjl                Op = Op->Asl.Next;
1547118611Snjl                NodePreviouslyVisited = FALSE;
1548118611Snjl            }
1549118611Snjl            else
1550118611Snjl            {
1551118611Snjl                /* No children or peers, re-visit parent */
1552118611Snjl
1553118611Snjl                if (Level != 0 )
1554118611Snjl                {
1555118611Snjl                    Level--;
1556118611Snjl                }
1557118611Snjl                Op = Op->Asl.Parent;
1558118611Snjl                NodePreviouslyVisited = TRUE;
1559118611Snjl            }
1560118611Snjl        }
1561118611Snjl        break;
1562118611Snjl
1563118611Snjl     case ASL_WALK_VISIT_TWICE:
1564118611Snjl
1565118611Snjl        while (Op)
1566118611Snjl        {
1567118611Snjl            if (NodePreviouslyVisited)
1568118611Snjl            {
1569118611Snjl                Status = AscendingCallback (Op, Level, Context);
1570118611Snjl                if (ACPI_FAILURE (Status))
1571118611Snjl                {
1572118611Snjl                    return (Status);
1573118611Snjl                }
1574118611Snjl            }
1575118611Snjl            else
1576118611Snjl            {
1577151937Sjkim                /* Let the callback process the node. */
1578151937Sjkim
1579118611Snjl                Status = DescendingCallback (Op, Level, Context);
1580118611Snjl                if (ACPI_SUCCESS (Status))
1581118611Snjl                {
1582118611Snjl                    /* Visit children first, once */
1583118611Snjl
1584118611Snjl                    if (Op->Asl.Child)
1585118611Snjl                    {
1586118611Snjl                        Level++;
1587118611Snjl                        Op = Op->Asl.Child;
1588118611Snjl                        continue;
1589118611Snjl                    }
1590118611Snjl                }
1591118611Snjl                else if (Status != AE_CTRL_DEPTH)
1592118611Snjl                {
1593118611Snjl                    /* Exit immediately on any error */
1594118611Snjl
1595118611Snjl                    return (Status);
1596118611Snjl                }
1597118611Snjl            }
1598118611Snjl
1599118611Snjl            /* Terminate walk at start op */
1600118611Snjl
1601118611Snjl            if (Op == StartOp)
1602118611Snjl            {
1603118611Snjl                break;
1604118611Snjl            }
1605118611Snjl
1606118611Snjl            /* No more children, visit peers */
1607118611Snjl
1608118611Snjl            if (Op->Asl.Next)
1609118611Snjl            {
1610118611Snjl                Op = Op->Asl.Next;
1611118611Snjl                NodePreviouslyVisited = FALSE;
1612118611Snjl            }
1613118611Snjl            else
1614118611Snjl            {
1615118611Snjl                /* No children or peers, re-visit parent */
1616118611Snjl
1617118611Snjl                if (Level != 0 )
1618118611Snjl                {
1619118611Snjl                    Level--;
1620118611Snjl                }
1621118611Snjl                Op = Op->Asl.Parent;
1622118611Snjl                NodePreviouslyVisited = TRUE;
1623118611Snjl            }
1624118611Snjl        }
1625118611Snjl        break;
1626118611Snjl
1627118611Snjl    default:
1628118611Snjl        /* No other types supported */
1629118611Snjl        break;
1630118611Snjl    }
1631118611Snjl
1632118611Snjl    /* If we get here, the walk completed with no errors */
1633118611Snjl
1634118611Snjl    return (AE_OK);
1635118611Snjl}
1636