minor corrections by M.Taguchi
[reactos.git] / reactos / drivers / bus / acpi / parser / pstree.c
1 /******************************************************************************
2 *
3 * Module Name: pstree - Parser op tree manipulation/traversal/search
4 * $Revision: 1.1 $
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