1/****************************************************************************** 2 * 3 * Module Name: pstree - Parser op tree manipulation/traversal/search 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44#include <acpi/acpi.h> 45#include <acpi/acparser.h> 46#include <acpi/amlcode.h> 47 48#define _COMPONENT ACPI_PARSER 49ACPI_MODULE_NAME("pstree") 50 51/* Local prototypes */ 52#ifdef ACPI_OBSOLETE_FUNCTIONS 53union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op); 54#endif 55 56/******************************************************************************* 57 * 58 * FUNCTION: acpi_ps_get_arg 59 * 60 * PARAMETERS: Op - Get an argument for this op 61 * Argn - Nth argument to get 62 * 63 * RETURN: The argument (as an Op object). NULL if argument does not exist 64 * 65 * DESCRIPTION: Get the specified op's argument. 66 * 67 ******************************************************************************/ 68 69union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) 70{ 71 union acpi_parse_object *arg = NULL; 72 const struct acpi_opcode_info *op_info; 73 74 ACPI_FUNCTION_ENTRY(); 75 76 /* Get the info structure for this opcode */ 77 78 op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); 79 if (op_info->class == AML_CLASS_UNKNOWN) { 80 81 /* Invalid opcode or ASCII character */ 82 83 return (NULL); 84 } 85 86 /* Check if this opcode requires argument sub-objects */ 87 88 if (!(op_info->flags & AML_HAS_ARGS)) { 89 90 /* Has no linked argument objects */ 91 92 return (NULL); 93 } 94 95 /* Get the requested argument object */ 96 97 arg = op->common.value.arg; 98 while (arg && argn) { 99 argn--; 100 arg = arg->common.next; 101 } 102 103 return (arg); 104} 105 106/******************************************************************************* 107 * 108 * FUNCTION: acpi_ps_append_arg 109 * 110 * PARAMETERS: Op - Append an argument to this Op. 111 * Arg - Argument Op to append 112 * 113 * RETURN: None. 114 * 115 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) 116 * 117 ******************************************************************************/ 118 119void 120acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) 121{ 122 union acpi_parse_object *prev_arg; 123 const struct acpi_opcode_info *op_info; 124 125 ACPI_FUNCTION_ENTRY(); 126 127 if (!op) { 128 return; 129 } 130 131 /* Get the info structure for this opcode */ 132 133 op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); 134 if (op_info->class == AML_CLASS_UNKNOWN) { 135 136 /* Invalid opcode */ 137 138 ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", 139 op->common.aml_opcode)); 140 return; 141 } 142 143 /* Check if this opcode requires argument sub-objects */ 144 145 if (!(op_info->flags & AML_HAS_ARGS)) { 146 147 /* Has no linked argument objects */ 148 149 return; 150 } 151 152 /* Append the argument to the linked argument list */ 153 154 if (op->common.value.arg) { 155 156 /* Append to existing argument list */ 157 158 prev_arg = op->common.value.arg; 159 while (prev_arg->common.next) { 160 prev_arg = prev_arg->common.next; 161 } 162 prev_arg->common.next = arg; 163 } else { 164 /* No argument list, this will be the first argument */ 165 166 op->common.value.arg = arg; 167 } 168 169 /* Set the parent in this arg and any args linked after it */ 170 171 while (arg) { 172 arg->common.parent = op; 173 arg = arg->common.next; 174 } 175} 176 177#ifdef ACPI_FUTURE_USAGE 178/******************************************************************************* 179 * 180 * FUNCTION: acpi_ps_get_depth_next 181 * 182 * PARAMETERS: Origin - Root of subtree to search 183 * Op - Last (previous) Op that was found 184 * 185 * RETURN: Next Op found in the search. 186 * 187 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) 188 * Return NULL when reaching "origin" or when walking up from root 189 * 190 ******************************************************************************/ 191 192union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, 193 union acpi_parse_object *op) 194{ 195 union acpi_parse_object *next = NULL; 196 union acpi_parse_object *parent; 197 union acpi_parse_object *arg; 198 199 ACPI_FUNCTION_ENTRY(); 200 201 if (!op) { 202 return (NULL); 203 } 204 205 /* Look for an argument or child */ 206 207 next = acpi_ps_get_arg(op, 0); 208 if (next) { 209 return (next); 210 } 211 212 /* Look for a sibling */ 213 214 next = op->common.next; 215 if (next) { 216 return (next); 217 } 218 219 /* Look for a sibling of parent */ 220 221 parent = op->common.parent; 222 223 while (parent) { 224 arg = acpi_ps_get_arg(parent, 0); 225 while (arg && (arg != origin) && (arg != op)) { 226 arg = arg->common.next; 227 } 228 229 if (arg == origin) { 230 231 /* Reached parent of origin, end search */ 232 233 return (NULL); 234 } 235 236 if (parent->common.next) { 237 238 /* Found sibling of parent */ 239 240 return (parent->common.next); 241 } 242 243 op = parent; 244 parent = parent->common.parent; 245 } 246 247 return (next); 248} 249 250#ifdef ACPI_OBSOLETE_FUNCTIONS 251/******************************************************************************* 252 * 253 * FUNCTION: acpi_ps_get_child 254 * 255 * PARAMETERS: Op - Get the child of this Op 256 * 257 * RETURN: Child Op, Null if none is found. 258 * 259 * DESCRIPTION: Get op's children or NULL if none 260 * 261 ******************************************************************************/ 262 263union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) 264{ 265 union acpi_parse_object *child = NULL; 266 267 ACPI_FUNCTION_ENTRY(); 268 269 switch (op->common.aml_opcode) { 270 case AML_SCOPE_OP: 271 case AML_ELSE_OP: 272 case AML_DEVICE_OP: 273 case AML_THERMAL_ZONE_OP: 274 case AML_INT_METHODCALL_OP: 275 276 child = acpi_ps_get_arg(op, 0); 277 break; 278 279 case AML_BUFFER_OP: 280 case AML_PACKAGE_OP: 281 case AML_METHOD_OP: 282 case AML_IF_OP: 283 case AML_WHILE_OP: 284 case AML_FIELD_OP: 285 286 child = acpi_ps_get_arg(op, 1); 287 break; 288 289 case AML_POWER_RES_OP: 290 case AML_INDEX_FIELD_OP: 291 292 child = acpi_ps_get_arg(op, 2); 293 break; 294 295 case AML_PROCESSOR_OP: 296 case AML_BANK_FIELD_OP: 297 298 child = acpi_ps_get_arg(op, 3); 299 break; 300 301 default: 302 /* All others have no children */ 303 break; 304 } 305 306 return (child); 307} 308#endif 309#endif /* ACPI_FUTURE_USAGE */ 310