:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / parser / pstree.c
1 /******************************************************************************
2  *
3  * Module Name: pstree - Parser op tree manipulation/traversal/search
4  *              $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acparser.h"
29 #include "amlcode.h"
30
31 #define _COMPONENT          ACPI_PARSER
32          MODULE_NAME         ("pstree")
33
34
35 /*******************************************************************************
36  *
37  * FUNCTION:    Acpi_ps_get_arg
38  *
39  * PARAMETERS:  Op              - Get an argument for this op
40  *              Argn            - Nth argument to get
41  *
42  * RETURN:      The argument (as an Op object).  NULL if argument does not exist
43  *
44  * DESCRIPTION: Get the specified op's argument.
45  *
46  ******************************************************************************/
47
48 ACPI_PARSE_OBJECT *
49 acpi_ps_get_arg (
50         ACPI_PARSE_OBJECT       *op,
51         u32                     argn)
52 {
53         ACPI_PARSE_OBJECT       *arg = NULL;
54         ACPI_OPCODE_INFO        *op_info;
55
56
57         /* Get the info structure for this opcode */
58
59         op_info = acpi_ps_get_opcode_info (op->opcode);
60         if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
61                 /* Invalid opcode or ASCII character */
62
63                 return (NULL);
64         }
65
66         /* Check if this opcode requires argument sub-objects */
67
68         if (!(ACPI_GET_OP_ARGS (op_info))) {
69                 /* Has no linked argument objects */
70
71                 return (NULL);
72         }
73
74         /* Get the requested argument object */
75
76         arg = op->value.arg;
77         while (arg && argn) {
78                 argn--;
79                 arg = arg->next;
80         }
81
82         return (arg);
83 }
84
85
86 /*******************************************************************************
87  *
88  * FUNCTION:    Acpi_ps_append_arg
89  *
90  * PARAMETERS:  Op              - Append an argument to this Op.
91  *              Arg             - Argument Op to append
92  *
93  * RETURN:      None.
94  *
95  * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
96  *
97  ******************************************************************************/
98
99 void
100 acpi_ps_append_arg (
101         ACPI_PARSE_OBJECT       *op,
102         ACPI_PARSE_OBJECT       *arg)
103 {
104         ACPI_PARSE_OBJECT       *prev_arg;
105         ACPI_OPCODE_INFO        *op_info;
106
107
108         if (!op) {
109                 return;
110         }
111
112         /* Get the info structure for this opcode */
113
114         op_info = acpi_ps_get_opcode_info (op->opcode);
115         if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
116                 /* Invalid opcode */
117
118                 return;
119         }
120
121         /* Check if this opcode requires argument sub-objects */
122
123         if (!(ACPI_GET_OP_ARGS (op_info))) {
124                 /* Has no linked argument objects */
125
126                 return;
127         }
128
129
130         /* Append the argument to the linked argument list */
131
132         if (op->value.arg) {
133                 /* Append to existing argument list */
134
135                 prev_arg = op->value.arg;
136                 while (prev_arg->next) {
137                         prev_arg = prev_arg->next;
138                 }
139                 prev_arg->next = arg;
140         }
141
142         else {
143                 /* No argument list, this will be the first argument */
144
145                 op->value.arg = arg;
146         }
147
148
149         /* Set the parent in this arg and any args linked after it */
150
151         while (arg) {
152                 arg->parent = op;
153                 arg = arg->next;
154         }
155 }
156
157
158 /*******************************************************************************
159  *
160  * FUNCTION:    Acpi_ps_get_child
161  *
162  * PARAMETERS:  Op              - Get the child of this Op
163  *
164  * RETURN:      Child Op, Null if none is found.
165  *
166  * DESCRIPTION: Get op's children or NULL if none
167  *
168  ******************************************************************************/
169
170 ACPI_PARSE_OBJECT *
171 acpi_ps_get_child (
172         ACPI_PARSE_OBJECT       *op)
173 {
174         ACPI_PARSE_OBJECT       *child = NULL;
175
176
177         switch (op->opcode) {
178         case AML_SCOPE_OP:
179         case AML_ELSE_OP:
180         case AML_DEVICE_OP:
181         case AML_THERMAL_ZONE_OP:
182         case AML_METHODCALL_OP:
183
184                 child = acpi_ps_get_arg (op, 0);
185                 break;
186
187
188         case AML_BUFFER_OP:
189         case AML_PACKAGE_OP:
190         case AML_METHOD_OP:
191         case AML_IF_OP:
192         case AML_WHILE_OP:
193         case AML_DEF_FIELD_OP:
194
195                 child = acpi_ps_get_arg (op, 1);
196                 break;
197
198
199         case AML_POWER_RES_OP:
200         case AML_INDEX_FIELD_OP:
201
202                 child = acpi_ps_get_arg (op, 2);
203                 break;
204
205
206         case AML_PROCESSOR_OP:
207         case AML_BANK_FIELD_OP:
208
209                 child = acpi_ps_get_arg (op, 3);
210                 break;
211
212         }
213
214         return (child);
215 }
216
217
218 /*******************************************************************************
219  *
220  * FUNCTION:    Acpi_ps_get_depth_next
221  *
222  * PARAMETERS:  Origin          - Root of subtree to search
223  *              Op              - Last (previous) Op that was found
224  *
225  * RETURN:      Next Op found in the search.
226  *
227  * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
228  *              Return NULL when reaching "origin" or when walking up from root
229  *
230  ******************************************************************************/
231
232 ACPI_PARSE_OBJECT *
233 acpi_ps_get_depth_next (
234         ACPI_PARSE_OBJECT       *origin,
235         ACPI_PARSE_OBJECT       *op)
236 {
237         ACPI_PARSE_OBJECT       *next = NULL;
238         ACPI_PARSE_OBJECT       *parent;
239         ACPI_PARSE_OBJECT       *arg;
240
241
242         if (!op) {
243                 return (NULL);
244         }
245
246         /* look for an argument or child */
247
248         next = acpi_ps_get_arg (op, 0);
249         if (next) {
250                 return (next);
251         }
252
253         /* look for a sibling */
254
255         next = op->next;
256         if (next) {
257                 return (next);
258         }
259
260         /* look for a sibling of parent */
261
262         parent = op->parent;
263
264         while (parent) {
265                 arg = acpi_ps_get_arg (parent, 0);
266                 while (arg && (arg != origin) && (arg != op)) {
267                         arg = arg->next;
268                 }
269
270                 if (arg == origin) {
271                         /* reached parent of origin, end search */
272
273                         return (NULL);
274                 }
275
276                 if (parent->next) {
277                         /* found sibling of parent */
278                         return (parent->next);
279                 }
280
281                 op = parent;
282                 parent = parent->parent;
283         }
284
285         return (next);
286 }
287
288