1/****************************************************************************** 2 * 3 * Module Name: pstree - Parser op tree manipulation/traversal/search 4 * $Revision: 1.1.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 48acpi_parse_object * 49acpi_ps_get_arg ( 50 acpi_parse_object *op, 51 u32 argn) 52{ 53 acpi_parse_object *arg = NULL; 54 const acpi_opcode_info *op_info; 55 56 57 FUNCTION_ENTRY (); 58 59 60 /* Get the info structure for this opcode */ 61 62 op_info = acpi_ps_get_opcode_info (op->opcode); 63 if (op_info->class == AML_CLASS_UNKNOWN) { 64 /* Invalid opcode or ASCII character */ 65 66 return (NULL); 67 } 68 69 /* Check if this opcode requires argument sub-objects */ 70 71 if (!(op_info->flags & AML_HAS_ARGS)) { 72 /* Has no linked argument objects */ 73 74 return (NULL); 75 } 76 77 /* Get the requested argument object */ 78 79 arg = op->value.arg; 80 while (arg && argn) { 81 argn--; 82 arg = arg->next; 83 } 84 85 return (arg); 86} 87 88 89/******************************************************************************* 90 * 91 * FUNCTION: Acpi_ps_append_arg 92 * 93 * PARAMETERS: Op - Append an argument to this Op. 94 * Arg - Argument Op to append 95 * 96 * RETURN: None. 97 * 98 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) 99 * 100 ******************************************************************************/ 101 102void 103acpi_ps_append_arg ( 104 acpi_parse_object *op, 105 acpi_parse_object *arg) 106{ 107 acpi_parse_object *prev_arg; 108 const acpi_opcode_info *op_info; 109 110 111 FUNCTION_ENTRY (); 112 113 114 if (!op) { 115 return; 116 } 117 118 /* Get the info structure for this opcode */ 119 120 op_info = acpi_ps_get_opcode_info (op->opcode); 121 if (op_info->class == AML_CLASS_UNKNOWN) { 122 /* Invalid opcode */ 123 124 REPORT_ERROR (("Ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->opcode)); 125 return; 126 } 127 128 /* Check if this opcode requires argument sub-objects */ 129 130 if (!(op_info->flags & AML_HAS_ARGS)) { 131 /* Has no linked argument objects */ 132 133 return; 134 } 135 136 137 /* Append the argument to the linked argument list */ 138 139 if (op->value.arg) { 140 /* Append to existing argument list */ 141 142 prev_arg = op->value.arg; 143 while (prev_arg->next) { 144 prev_arg = prev_arg->next; 145 } 146 prev_arg->next = arg; 147 } 148 149 else { 150 /* No argument list, this will be the first argument */ 151 152 op->value.arg = arg; 153 } 154 155 156 /* Set the parent in this arg and any args linked after it */ 157 158 while (arg) { 159 arg->parent = op; 160 arg = arg->next; 161 } 162} 163 164 165/******************************************************************************* 166 * 167 * FUNCTION: Acpi_ps_get_child 168 * 169 * PARAMETERS: Op - Get the child of this Op 170 * 171 * RETURN: Child Op, Null if none is found. 172 * 173 * DESCRIPTION: Get op's children or NULL if none 174 * 175 ******************************************************************************/ 176 177acpi_parse_object * 178acpi_ps_get_child ( 179 acpi_parse_object *op) 180{ 181 acpi_parse_object *child = NULL; 182 183 184 FUNCTION_ENTRY (); 185 186 187 switch (op->opcode) { 188 case AML_SCOPE_OP: 189 case AML_ELSE_OP: 190 case AML_DEVICE_OP: 191 case AML_THERMAL_ZONE_OP: 192 case AML_INT_METHODCALL_OP: 193 194 child = acpi_ps_get_arg (op, 0); 195 break; 196 197 198 case AML_BUFFER_OP: 199 case AML_PACKAGE_OP: 200 case AML_METHOD_OP: 201 case AML_IF_OP: 202 case AML_WHILE_OP: 203 case AML_FIELD_OP: 204 205 child = acpi_ps_get_arg (op, 1); 206 break; 207 208 209 case AML_POWER_RES_OP: 210 case AML_INDEX_FIELD_OP: 211 212 child = acpi_ps_get_arg (op, 2); 213 break; 214 215 216 case AML_PROCESSOR_OP: 217 case AML_BANK_FIELD_OP: 218 219 child = acpi_ps_get_arg (op, 3); 220 break; 221 222 } 223 224 return (child); 225} 226 227 228/******************************************************************************* 229 * 230 * FUNCTION: Acpi_ps_get_depth_next 231 * 232 * PARAMETERS: Origin - Root of subtree to search 233 * Op - Last (previous) Op that was found 234 * 235 * RETURN: Next Op found in the search. 236 * 237 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) 238 * Return NULL when reaching "origin" or when walking up from root 239 * 240 ******************************************************************************/ 241 242acpi_parse_object * 243acpi_ps_get_depth_next ( 244 acpi_parse_object *origin, 245 acpi_parse_object *op) 246{ 247 acpi_parse_object *next = NULL; 248 acpi_parse_object *parent; 249 acpi_parse_object *arg; 250 251 252 FUNCTION_ENTRY (); 253 254 255 if (!op) { 256 return (NULL); 257 } 258 259 /* look for an argument or child */ 260 261 next = acpi_ps_get_arg (op, 0); 262 if (next) { 263 return (next); 264 } 265 266 /* look for a sibling */ 267 268 next = op->next; 269 if (next) { 270 return (next); 271 } 272 273 /* look for a sibling of parent */ 274 275 parent = op->parent; 276 277 while (parent) { 278 arg = acpi_ps_get_arg (parent, 0); 279 while (arg && (arg != origin) && (arg != op)) { 280 arg = arg->next; 281 } 282 283 if (arg == origin) { 284 /* reached parent of origin, end search */ 285 286 return (NULL); 287 } 288 289 if (parent->next) { 290 /* found sibling of parent */ 291 return (parent->next); 292 } 293 294 op = parent; 295 parent = parent->parent; 296 } 297 298 return (next); 299} 300 301 302