psparse.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 1,190 行 · 第 1/3 页
C
1,190 行
/****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines * $Revision: 121 $ * *****************************************************************************//* * Copyright (C) 2000 - 2002, R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * Parse the AML and build an operation tree as most interpreters, * like Perl, do. Parsing is done by hand rather than with a YACC * generated parser to tightly constrain stack and dynamic memory * usage. At the same time, parsing is kept flexible and the code * fairly compact by parsing based on a list of AML opcode * templates in Aml_op_info[] */#include "acpi.h"#include "acparser.h"#include "acdispat.h"#include "amlcode.h"#include "acnamesp.h"#include "acdebug.h"#include "acinterp.h"#define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("psparse")u32 acpi_gbl_depth = 0;extern u32 acpi_gbl_scope_depth;/******************************************************************************* * * FUNCTION: Acpi_ps_get_opcode_size * * PARAMETERS: Opcode - An AML opcode * * RETURN: Size of the opcode, in bytes (1 or 2) * * DESCRIPTION: Get the size of the current opcode. * ******************************************************************************/u32acpi_ps_get_opcode_size ( u32 opcode){ /* Extended (2-byte) opcode if > 255 */ if (opcode > 0x00FF) { return (2); } /* Otherwise, just a single byte opcode */ return (1);}/******************************************************************************* * * FUNCTION: Acpi_ps_peek_opcode * * PARAMETERS: Parser_state - A parser state object * * RETURN: Status * * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) * ******************************************************************************/u16acpi_ps_peek_opcode ( acpi_parse_state *parser_state){ u8 *aml; u16 opcode; aml = parser_state->aml; opcode = (u16) ACPI_GET8 (aml); if (opcode == AML_EXTOP) { /* Extended opcode */ aml++; opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml)); } return (opcode);}/******************************************************************************* * * FUNCTION: Acpi_ps_find_object * * PARAMETERS: Opcode - Current opcode * Parser_state - Current state * Walk_state - Current state * *Op - Where found/new op is returned * * RETURN: Status * * DESCRIPTION: Find a named object. Two versions - one to search the parse * tree (for parser-only applications such as acpidump), another * to search the ACPI internal namespace (the parse tree may no * longer exist) * ******************************************************************************/#ifdef PARSER_ONLYacpi_statusacpi_ps_find_object ( acpi_walk_state *walk_state, acpi_parse_object **out_op){ NATIVE_CHAR *path; /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & AML_NAMED)) { *out_op = walk_state->op; return (AE_OK); } /* Find the name in the parse tree */ path = acpi_ps_get_next_namestring (&walk_state->parser_state); *out_op = acpi_ps_find (acpi_ps_get_parent_scope (&walk_state->parser_state), path, walk_state->opcode, 1); if (!(*out_op)) { return (AE_NOT_FOUND); } return (AE_OK);}#endif/******************************************************************************* * * FUNCTION: Acpi_ps_complete_this_op * * PARAMETERS: Walk_state - Current State * Op - Op to complete * * RETURN: TRUE if Op and subtree was deleted * * DESCRIPTION: Perform any cleanup at the completion of an Op. * ******************************************************************************/u8acpi_ps_complete_this_op ( acpi_walk_state *walk_state, acpi_parse_object *op){#ifndef PARSER_ONLY acpi_parse_object *prev; acpi_parse_object *next; const acpi_opcode_info *parent_info; acpi_parse_object *replacement_op = NULL; ACPI_FUNCTION_TRACE_PTR ("Ps_complete_this_op", op); /* Check for null Op, can happen if AML code is corrupt */ if (!op) { return_VALUE (TRUE); } /* Delete this op and the subtree below it if asked to */ if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) && (walk_state->op_info->class != AML_CLASS_ARGUMENT)) { /* Make sure that we only delete this subtree */ if (op->parent) { /* * Check if we need to replace the operator and its subtree * with a return value op (placeholder op) */ parent_info = acpi_ps_get_opcode_info (op->parent->opcode); switch (parent_info->class) { case AML_CLASS_CONTROL: break; case AML_CLASS_CREATE: /* * These opcodes contain Term_arg operands. The current * op must be replaced by a placeholder return op */ replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { return_VALUE (FALSE); } break; case AML_CLASS_NAMED_OBJECT: /* * These opcodes contain Term_arg operands. The current * op must be replaced by a placeholder return op */ if ((op->parent->opcode == AML_REGION_OP) || (op->parent->opcode == AML_DATA_REGION_OP) || (op->parent->opcode == AML_BUFFER_OP) || (op->parent->opcode == AML_PACKAGE_OP) || (op->parent->opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { return_VALUE (FALSE); } } if ((op->parent->opcode == AML_NAME_OP) && (walk_state->descending_callback != acpi_ds_exec_begin_op)) { if ((op->opcode == AML_BUFFER_OP) || (op->opcode == AML_PACKAGE_OP) || (op->opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (op->opcode); if (!replacement_op) { return_VALUE (FALSE); } ((acpi_parse2_object *) replacement_op)->data = ((acpi_parse2_object *) op)->data; ((acpi_parse2_object *) replacement_op)->length = ((acpi_parse2_object *) op)->length; } } break; default: replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { return_VALUE (FALSE); } } /* We must unlink this op from the parent tree */ prev = op->parent->value.arg; if (prev == op) { /* This op is the first in the list */ if (replacement_op) { replacement_op->parent = op->parent; replacement_op->value.arg = NULL; replacement_op->node = op->node; op->parent->value.arg = replacement_op; replacement_op->next = op->next; } else { op->parent->value.arg = op->next; } } /* Search the parent list */ else while (prev) { /* Traverse all siblings in the parent's argument list */ next = prev->next; if (next == op) { if (replacement_op) { replacement_op->parent = op->parent; replacement_op->value.arg = NULL; replacement_op->node = op->node; prev->next = replacement_op; replacement_op->next = op->next; next = NULL; } else { prev->next = op->next; next = NULL; } } prev = next; } } /* Now we can actually delete the subtree rooted at op */ acpi_ps_delete_parse_tree (op); return_VALUE (TRUE); } return_VALUE (FALSE);#else return (FALSE);#endif}/******************************************************************************* * * FUNCTION: Acpi_ps_next_parse_state * * PARAMETERS: Parser_state - Current parser state object * * RETURN: Status * * DESCRIPTION: Update the parser state based upon the return exception from * the parser callback. * ******************************************************************************/acpi_statusacpi_ps_next_parse_state ( acpi_walk_state *walk_state, acpi_parse_object *op, acpi_status callback_status){ acpi_parse_state *parser_state = &walk_state->parser_state; acpi_status status = AE_CTRL_PENDING; ACPI_FUNCTION_TRACE_PTR ("Ps_next_parse_state", op); switch (callback_status) { case AE_CTRL_TERMINATE: /* * A control method was terminated via a RETURN statement. * The walk of this method is complete. */ parser_state->aml = parser_state->aml_end; status = AE_CTRL_TERMINATE; break; case AE_CTRL_BREAK: parser_state->aml = walk_state->aml_last_while; walk_state->control_state->common.value = FALSE; status = AE_CTRL_BREAK; break; case AE_CTRL_CONTINUE: parser_state->aml = walk_state->aml_last_while; status = AE_CTRL_CONTINUE; break; case AE_CTRL_PENDING: parser_state->aml = walk_state->aml_last_while; break; case AE_CTRL_TRUE: /* * Predicate of an IF was true, and we are at the matching ELSE. * Just close out this package */ parser_state->aml = acpi_ps_get_next_package_end (parser_state); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?