- Make ACPI use PCH. Cuts down compile time to 9 seconds on gcc.
[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
29 #define _COMPONENT ACPI_PARSER
30 MODULE_NAME ("pstree")
31
32
33 /*******************************************************************************
34 *
35 * FUNCTION: Acpi_ps_get_arg
36 *
37 * PARAMETERS: Op - Get an argument for this op
38 * Argn - Nth argument to get
39 *
40 * RETURN: The argument (as an Op object). NULL if argument does not exist
41 *
42 * DESCRIPTION: Get the specified op's argument.
43 *
44 ******************************************************************************/
45
46 ACPI_PARSE_OBJECT *
47 acpi_ps_get_arg (
48 ACPI_PARSE_OBJECT *op,
49 u32 argn)
50 {
51 ACPI_PARSE_OBJECT *arg = NULL;
52 ACPI_OPCODE_INFO *op_info;
53
54
55 /* Get the info structure for this opcode */
56
57 op_info = acpi_ps_get_opcode_info (op->opcode);
58 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
59 /* Invalid opcode or ASCII character */
60
61 return (NULL);
62 }
63
64 /* Check if this opcode requires argument sub-objects */
65
66 if (!(ACPI_GET_OP_ARGS (op_info))) {
67 /* Has no linked argument objects */
68
69 return (NULL);
70 }
71
72 /* Get the requested argument object */
73
74 arg = op->value.arg;
75 while (arg && argn) {
76 argn--;
77 arg = arg->next;
78 }
79
80 return (arg);
81 }
82
83
84 /*******************************************************************************
85 *
86 * FUNCTION: Acpi_ps_append_arg
87 *
88 * PARAMETERS: Op - Append an argument to this Op.
89 * Arg - Argument Op to append
90 *
91 * RETURN: None.
92 *
93 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
94 *
95 ******************************************************************************/
96
97 void
98 acpi_ps_append_arg (
99 ACPI_PARSE_OBJECT *op,
100 ACPI_PARSE_OBJECT *arg)
101 {
102 ACPI_PARSE_OBJECT *prev_arg;
103 ACPI_OPCODE_INFO *op_info;
104
105
106 if (!op) {
107 return;
108 }
109
110 /* Get the info structure for this opcode */
111
112 op_info = acpi_ps_get_opcode_info (op->opcode);
113 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
114 /* Invalid opcode */
115
116 return;
117 }
118
119 /* Check if this opcode requires argument sub-objects */
120
121 if (!(ACPI_GET_OP_ARGS (op_info))) {
122 /* Has no linked argument objects */
123
124 return;
125 }
126
127
128 /* Append the argument to the linked argument list */
129
130 if (op->value.arg) {
131 /* Append to existing argument list */
132
133 prev_arg = op->value.arg;
134 while (prev_arg->next) {
135 prev_arg = prev_arg->next;
136 }
137 prev_arg->next = arg;
138 }
139
140 else {
141 /* No argument list, this will be the first argument */
142
143 op->value.arg = arg;
144 }
145
146
147 /* Set the parent in this arg and any args linked after it */
148
149 while (arg) {
150 arg->parent = op;
151 arg = arg->next;
152 }
153 }
154
155
156 /*******************************************************************************
157 *
158 * FUNCTION: Acpi_ps_get_child
159 *
160 * PARAMETERS: Op - Get the child of this Op
161 *
162 * RETURN: Child Op, Null if none is found.
163 *
164 * DESCRIPTION: Get op's children or NULL if none
165 *
166 ******************************************************************************/
167
168 ACPI_PARSE_OBJECT *
169 acpi_ps_get_child (
170 ACPI_PARSE_OBJECT *op)
171 {
172 ACPI_PARSE_OBJECT *child = NULL;
173
174
175 switch (op->opcode) {
176 case AML_SCOPE_OP:
177 case AML_ELSE_OP:
178 case AML_DEVICE_OP:
179 case AML_THERMAL_ZONE_OP:
180 case AML_METHODCALL_OP:
181
182 child = acpi_ps_get_arg (op, 0);
183 break;
184
185
186 case AML_BUFFER_OP:
187 case AML_PACKAGE_OP:
188 case AML_METHOD_OP:
189 case AML_IF_OP:
190 case AML_WHILE_OP:
191 case AML_DEF_FIELD_OP:
192
193 child = acpi_ps_get_arg (op, 1);
194 break;
195
196
197 case AML_POWER_RES_OP:
198 case AML_INDEX_FIELD_OP:
199
200 child = acpi_ps_get_arg (op, 2);
201 break;
202
203
204 case AML_PROCESSOR_OP:
205 case AML_BANK_FIELD_OP:
206
207 child = acpi_ps_get_arg (op, 3);
208 break;
209
210 }
211
212 return (child);
213 }
214
215
216 /*******************************************************************************
217 *
218 * FUNCTION: Acpi_ps_get_depth_next
219 *
220 * PARAMETERS: Origin - Root of subtree to search
221 * Op - Last (previous) Op that was found
222 *
223 * RETURN: Next Op found in the search.
224 *
225 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
226 * Return NULL when reaching "origin" or when walking up from root
227 *
228 ******************************************************************************/
229
230 ACPI_PARSE_OBJECT *
231 acpi_ps_get_depth_next (
232 ACPI_PARSE_OBJECT *origin,
233 ACPI_PARSE_OBJECT *op)
234 {
235 ACPI_PARSE_OBJECT *next = NULL;
236 ACPI_PARSE_OBJECT *parent;
237 ACPI_PARSE_OBJECT *arg;
238
239
240 if (!op) {
241 return (NULL);
242 }
243
244 /* look for an argument or child */
245
246 next = acpi_ps_get_arg (op, 0);
247 if (next) {
248 return (next);
249 }
250
251 /* look for a sibling */
252
253 next = op->next;
254 if (next) {
255 return (next);
256 }
257
258 /* look for a sibling of parent */
259
260 parent = op->parent;
261
262 while (parent) {
263 arg = acpi_ps_get_arg (parent, 0);
264 while (arg && (arg != origin) && (arg != op)) {
265 arg = arg->next;
266 }
267
268 if (arg == origin) {
269 /* reached parent of origin, end search */
270
271 return (NULL);
272 }
273
274 if (parent->next) {
275 /* found sibling of parent */
276 return (parent->next);
277 }
278
279 op = parent;
280 parent = parent->parent;
281 }
282
283 return (next);
284 }
285
286