Import acpica-20050211 from Intel.
[dragonfly.git] / sys / contrib / dev / acpica-unix-20050211 / interpreter / parser / pswalk.c
1 /******************************************************************************
2  *
3  * Module Name: pswalk - Parser routines to walk parsed op tree(s)
4  *              $Revision: 71 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117
118 #include "acpi.h"
119 #include "acparser.h"
120 #include "acdispat.h"
121
122 #define _COMPONENT          ACPI_PARSER
123         ACPI_MODULE_NAME    ("pswalk")
124
125
126 /*******************************************************************************
127  *
128  * FUNCTION:    AcpiPsGetNextWalkOp
129  *
130  * PARAMETERS:  WalkState           - Current state of the walk
131  *              Op                  - Current Op to be walked
132  *              AscendingCallback   - Procedure called when Op is complete
133  *
134  * RETURN:      Status
135  *
136  * DESCRIPTION: Get the next Op in a walk of the parse tree.
137  *
138  ******************************************************************************/
139
140 ACPI_STATUS
141 AcpiPsGetNextWalkOp (
142     ACPI_WALK_STATE         *WalkState,
143     ACPI_PARSE_OBJECT       *Op,
144     ACPI_PARSE_UPWARDS      AscendingCallback)
145 {
146     ACPI_PARSE_OBJECT       *Next;
147     ACPI_PARSE_OBJECT       *Parent;
148     ACPI_PARSE_OBJECT       *GrandParent;
149     ACPI_STATUS             Status;
150
151
152     ACPI_FUNCTION_TRACE_PTR ("PsGetNextWalkOp", Op);
153
154
155     /* Check for a argument only if we are descending in the tree */
156
157     if (WalkState->NextOpInfo != ACPI_NEXT_OP_UPWARD)
158     {
159         /* Look for an argument or child of the current op */
160
161         Next = AcpiPsGetArg (Op, 0);
162         if (Next)
163         {
164             /* Still going downward in tree (Op is not completed yet) */
165
166             WalkState->PrevOp       = Op;
167             WalkState->NextOp       = Next;
168             WalkState->NextOpInfo   = ACPI_NEXT_OP_DOWNWARD;
169
170             return_ACPI_STATUS (AE_OK);
171         }
172
173         /*
174          * No more children, this Op is complete.  Save Next and Parent
175          * in case the Op object gets deleted by the callback routine
176          */
177         Next    = Op->Common.Next;
178         Parent  = Op->Common.Parent;
179
180         WalkState->Op     = Op;
181         WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
182         WalkState->Opcode = Op->Common.AmlOpcode;
183
184         Status = AscendingCallback (WalkState);
185
186         /*
187          * If we are back to the starting point, the walk is complete.
188          */
189         if (Op == WalkState->Origin)
190         {
191             /* Reached the point of origin, the walk is complete */
192
193             WalkState->PrevOp       = Op;
194             WalkState->NextOp       = NULL;
195
196             return_ACPI_STATUS (Status);
197         }
198
199         /*
200          * Check for a sibling to the current op.  A sibling means
201          * we are still going "downward" in the tree.
202          */
203         if (Next)
204         {
205             /* There is a sibling, it will be next */
206
207             WalkState->PrevOp       = Op;
208             WalkState->NextOp       = Next;
209             WalkState->NextOpInfo   = ACPI_NEXT_OP_DOWNWARD;
210
211             /* Continue downward */
212
213             return_ACPI_STATUS (Status);
214         }
215
216         /*
217          * Drop into the loop below because we are moving upwards in
218          * the tree
219          */
220     }
221     else
222     {
223         /*
224          * We are resuming a walk, and we were (are) going upward in the tree.
225          * So, we want to drop into the parent loop below.
226          */
227         Parent = Op;
228     }
229
230     /*
231      * Look for a sibling of the current Op's parent
232      * Continue moving up the tree until we find a node that has not been
233      * visited, or we get back to where we started.
234      */
235     while (Parent)
236     {
237         /* We are moving up the tree, therefore this parent Op is complete */
238
239         GrandParent = Parent->Common.Parent;
240         Next        = Parent->Common.Next;
241
242         WalkState->Op     = Parent;
243         WalkState->OpInfo = AcpiPsGetOpcodeInfo (Parent->Common.AmlOpcode);
244         WalkState->Opcode = Parent->Common.AmlOpcode;
245
246         Status = AscendingCallback (WalkState);
247
248         /*
249          * If we are back to the starting point, the walk is complete.
250          */
251         if (Parent == WalkState->Origin)
252         {
253             /* Reached the point of origin, the walk is complete */
254
255             WalkState->PrevOp       = Parent;
256             WalkState->NextOp       = NULL;
257
258             return_ACPI_STATUS (Status);
259         }
260
261         /*
262          * If there is a sibling to this parent (it is not the starting point
263          * Op), then we will visit it.
264          */
265         if (Next)
266         {
267             /* found sibling of parent */
268
269             WalkState->PrevOp       = Parent;
270             WalkState->NextOp       = Next;
271             WalkState->NextOpInfo   = ACPI_NEXT_OP_DOWNWARD;
272
273             return_ACPI_STATUS (Status);
274         }
275
276         /* No siblings, no errors, just move up one more level in the tree */
277
278         Op                  = Parent;
279         Parent              = GrandParent;
280         WalkState->PrevOp   = Op;
281     }
282
283
284     /*
285      * Got all the way to the top of the tree, we must be done!
286      * However, the code should have terminated in the loop above
287      */
288     WalkState->NextOp       = NULL;
289
290     return_ACPI_STATUS (AE_OK);
291 }
292
293
294 /*******************************************************************************
295  *
296  * FUNCTION:    AcpiPsDeleteCompletedOp
297  *
298  * PARAMETERS:  State           - Walk state
299  *              Op              - Completed op
300  *
301  * RETURN:      AE_OK
302  *
303  * DESCRIPTION: Callback function for AcpiPsGetNextWalkOp().  Used during
304  *              AcpiPsDeleteParse tree to delete Op objects when all sub-objects
305  *              have been visited (and deleted.)
306  *
307  ******************************************************************************/
308
309 ACPI_STATUS
310 AcpiPsDeleteCompletedOp (
311     ACPI_WALK_STATE         *WalkState)
312 {
313
314     AcpiPsFreeOp (WalkState->Op);
315     return (AE_OK);
316 }
317
318
319 /*******************************************************************************
320  *
321  * FUNCTION:    AcpiPsDeleteParseTree
322  *
323  * PARAMETERS:  SubtreeRoot         - Root of tree (or subtree) to delete
324  *
325  * RETURN:      None
326  *
327  * DESCRIPTION: Delete a portion of or an entire parse tree.
328  *
329  ******************************************************************************/
330
331 void
332 AcpiPsDeleteParseTree (
333     ACPI_PARSE_OBJECT       *SubtreeRoot)
334 {
335     ACPI_WALK_STATE         *WalkState;
336     ACPI_THREAD_STATE       *Thread;
337     ACPI_STATUS             Status;
338
339
340     ACPI_FUNCTION_TRACE_PTR ("PsDeleteParseTree", SubtreeRoot);
341
342
343     if (!SubtreeRoot)
344     {
345         return_VOID;
346     }
347
348     /* Create and initialize a new walk list */
349
350     Thread = AcpiUtCreateThreadState ();
351     if (!Thread)
352     {
353         return_VOID;
354     }
355
356     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, Thread);
357     if (!WalkState)
358     {
359         return_VOID;
360     }
361
362     WalkState->ParseFlags           = 0;
363     WalkState->DescendingCallback   = NULL;
364     WalkState->AscendingCallback    = NULL;
365
366     WalkState->Origin = SubtreeRoot;
367     WalkState->NextOp = SubtreeRoot;
368
369     /* Head downward in the tree */
370
371     WalkState->NextOpInfo = ACPI_NEXT_OP_DOWNWARD;
372
373     /* Visit all nodes in the subtree */
374
375     while (WalkState->NextOp)
376     {
377         Status = AcpiPsGetNextWalkOp (WalkState, WalkState->NextOp,
378                                 AcpiPsDeleteCompletedOp);
379         if (ACPI_FAILURE (Status))
380         {
381             break;
382         }
383     }
384
385     /* We are done with this walk */
386
387     AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
388     AcpiDsDeleteWalkState (WalkState);
389
390     return_VOID;
391 }
392
393