FreeBSD/sys/contrib/dev/acpica/compiler/aslopt.c
/*******************************************************************************
 *
 * FUNCTION:    OptBuildShortestPath
 *
 * PARAMETERS:  Op                  - Current parser op
 *              WalkState           - Current state
 *              CurrentNode         - Where we are in the namespace
 *              TargetNode          - Node to which we are referring
 *              CurrentPath         - External full path to the current node
 *              TargetPath          - External full path to the target node
 *              AmlNameStringLength - Length of the original namepath
 *              IsDeclaration       - TRUE for declaration, FALSE for reference
 *              ReturnNewPath       - Where the optimized path is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Build an optimal NamePath using carats
 *
 ******************************************************************************/


Status

Build an optimal NamePath using carats
Status Build an optimal NamePath using carats
static ACPI_STATUS
OptBuildShortestPath (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *CurrentNode,
    ACPI_NAMESPACE_NODE     *TargetNode,
    ACPI_BUFFER             *CurrentPath,
    ACPI_BUFFER             *TargetPath,
    ACPI_SIZE               AmlNameStringLength,
    UINT8                   IsDeclaration,
    char                    **ReturnNewPath)
{
    UINT32                  NumCommonSegments;
    UINT32                  MaxCommonSegments;
    UINT32                  Index;
    UINT32                  NumCarats;
    UINT32                  i;
    char                    *NewPathInternal;
    char                    *NewPathExternal;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_STATUS             Status;
    BOOLEAN                 SubPath = FALSE;
    ACPI_FUNCTION_NAME (OptBuildShortestPath);
    ScopeInfo.Scope.Node = CurrentNode;
    MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    if (CurrentPath->Length < TargetPath->Length)
    {
        MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    }
    for (NumCommonSegments = 0;
         NumCommonSegments < MaxCommonSegments;
         NumCommonSegments++)
    {
        Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
        if (!ACPI_COMPARE_NAME (
            &(ACPI_CAST_PTR (char, TargetPath->Pointer)) [Index],
            &(ACPI_CAST_PTR (char, CurrentPath->Pointer)) [Index]))
        {
            break;
        }
    }
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
        NumCommonSegments));
    if (NumCommonSegments == 0)
    {
        return (AE_NOT_FOUND);
    }
    if (NumCommonSegments == MaxCommonSegments)
    {
        if (CurrentPath->Length == TargetPath->Length)
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
            return (AE_NOT_FOUND);
        }
        else
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
            SubPath = TRUE;
        }
    }
    NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
        NumCommonSegments;
    NewPathExternal =
        ACPI_ALLOCATE_ZEROED (TargetPath->Length + NumCarats + 1);
    for (i = 0; i < NumCarats; i++)
    {
        NewPathExternal[i] = AML_PARENT_PREFIX;
    }
    Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
    if (IsDeclaration && SubPath &&
        (CurrentPath->Length > TargetPath->Length))
    {
        Index -= ACPI_PATH_SEGMENT_LENGTH;
        if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
        {
            NewPathExternal[i] = AML_PARENT_PREFIX;
            i++;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
        }
    }
    if (Index > TargetPath->Length)
    {
        Index = TargetPath->Length;
    }
    strcpy (&NewPathExternal[i],
        &(ACPI_CAST_PTR (char, TargetPath->Pointer))[Index]);
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
    Status = AcpiNsInternalizeName (NewPathExternal, &NewPathInternal);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
            ASL_NO_ABORT);
        goto Cleanup;
    }
    if (strlen (NewPathInternal) >= AmlNameStringLength)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            " NOT SHORTER (New %u old %u)",
            (UINT32) strlen (NewPathInternal),
            (UINT32) AmlNameStringLength));
        ACPI_FREE (NewPathInternal);
        Status = AE_NOT_FOUND;
        goto Cleanup;
    }
    Status = AcpiNsLookup (&ScopeInfo, NewPathInternal,
        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
        ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
    if (ACPI_SUCCESS (Status))
    {
        if (Node == TargetNode)
        {
            AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
                Op, NewPathExternal);
            *ReturnNewPath = NewPathInternal;
        }
        else
        {
            Status = AE_NOT_FOUND;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
                "Not using optimized name - found wrong node");
        }
    }
    else
    {
        ACPI_FREE (NewPathInternal);
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
            "Not using optimized name - did not find node");
    }
Cleanup:
    ACPI_FREE (NewPathExternal);
    return (Status);
}
static ACPI_STATUS OptBuildShortestPath ( ACPI_PARSE_OBJECT * Op , ACPI_WALK_STATE * WalkState , ACPI_NAMESPACE_NODE * CurrentNode , ACPI_NAMESPACE_NODE * TargetNode , ACPI_BUFFER * CurrentPath , ACPI_BUFFER * TargetPath , ACPI_SIZE AmlNameStringLength , UINT8 IsDeclaration , char * * ReturnNewPath ) { UINT32 NumCommonSegments ; UINT32 MaxCommonSegments ; UINT32 Index ; UINT32 NumCarats ; UINT32 i ; char * NewPathInternal ; char * NewPathExternal ; ACPI_NAMESPACE_NODE * Node ; ACPI_GENERIC_STATE ScopeInfo ; ACPI_STATUS Status ; BOOLEAN SubPath = FALSE ; ACPI_FUNCTION_NAME ( OptBuildShortestPath ) ; ScopeInfo . Scope . Node = CurrentNode ; MaxCommonSegments = TargetPath -> Length / ACPI_PATH_SEGMENT_LENGTH ; if ( CurrentPath -> Length < TargetPath -> Length ) { MaxCommonSegments = CurrentPath -> Length / ACPI_PATH_SEGMENT_LENGTH ; } for ( NumCommonSegments = 0 ; NumCommonSegments < MaxCommonSegments ; NumCommonSegments ++ ) { Index = ( NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH ) + 1 ; if ( ! ACPI_COMPARE_NAME ( & ( ACPI_CAST_PTR ( char , TargetPath -> Pointer ) ) [ Index ] , & ( ACPI_CAST_PTR ( char , CurrentPath -> Pointer ) ) [ Index ] ) ) { break ; } } ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " , NumCommonSegments ) ) ; if ( NumCommonSegments == 0 ) { return ( AE_NOT_FOUND ) ; } if ( NumCommonSegments == MaxCommonSegments ) { if ( CurrentPath -> Length == TargetPath -> Length ) { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; return ( AE_NOT_FOUND ) ; } else { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; SubPath = TRUE ; } } NumCarats = ( CurrentPath -> Length / ACPI_PATH_SEGMENT_LENGTH ) - NumCommonSegments ; NewPathExternal = ACPI_ALLOCATE_ZEROED ( TargetPath -> Length + NumCarats + 1 ) ; for ( i = 0 ; i < NumCarats ; i ++ ) { NewPathExternal [ i ] = AML_PARENT_PREFIX ; } Index = ( NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH ) + 1 ; if ( IsDeclaration && SubPath && ( CurrentPath -> Length > TargetPath -> Length ) ) { Index -= ACPI_PATH_SEGMENT_LENGTH ; if ( Op -> Asl . AmlOpcode == AML_SCOPE_OP ) { NewPathExternal [ i ] = AML_PARENT_PREFIX ; i ++ ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; } } if ( Index > TargetPath -> Length ) { Index = TargetPath -> Length ; } strcpy ( & NewPathExternal [ i ] , & ( ACPI_CAST_PTR ( char , TargetPath -> Pointer ) ) [ Index ] ) ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " , NewPathExternal ) ) ; Status = AcpiNsInternalizeName ( NewPathExternal , & NewPathInternal ) ; if ( ACPI_FAILURE ( Status ) ) { AslCoreSubsystemError ( Op , Status , " " , ASL_NO_ABORT ) ; goto Cleanup ; } if ( strlen ( NewPathInternal ) >= AmlNameStringLength ) { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " , ( UINT32 ) strlen ( NewPathInternal ) , ( UINT32 ) AmlNameStringLength ) ) ; ACPI_FREE ( NewPathInternal ) ; Status = AE_NOT_FOUND ; goto Cleanup ; } Status = AcpiNsLookup ( & ScopeInfo , NewPathInternal , ACPI_TYPE_ANY , ACPI_IMODE_EXECUTE , ACPI_NS_DONT_OPEN_SCOPE , WalkState , & ( Node ) ) ; if ( ACPI_SUCCESS ( Status ) ) { if ( Node == TargetNode ) { AslError ( ASL_OPTIMIZATION , ASL_MSG_NAME_OPTIMIZATION , Op , NewPathExternal ) ; * ReturnNewPath = NewPathInternal ; } else { Status = AE_NOT_FOUND ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; AslError ( ASL_WARNING , ASL_MSG_COMPILER_INTERNAL , Op , " " ) ; } } else { ACPI_FREE ( NewPathInternal ) ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; AslError ( ASL_WARNING , ASL_MSG_COMPILER_INTERNAL , Op , " " ) ; } Cleanup : ACPI_FREE ( NewPathExternal ) ; return ( Status ) ; }
FUNCTION:    OptBuildShortestPath
 PARAMETERS:  Op                  - Current parser op
              WalkState           - Current state
              CurrentNode         - Where we are in the namespace
              TargetNode          - Node to which we are referring
              CurrentPath         - External full path to the current node
              TargetPath          - External full path to the target node
              AmlNameStringLength - Length of the original namepath
              IsDeclaration       - TRUE for declaration, FALSE for reference
              ReturnNewPath       - Where the optimized path is returned
FUNCTION : OptBuildShortestPath PARAMETERS : Op - Current parser op WalkState - Current state CurrentNode - Where we are in the namespace TargetNode - Node to which we are referring CurrentPath - External full path to the current node TargetPath - External full path to the target node AmlNameStringLength - Length of the original namepath IsDeclaration - TRUE for declaration FALSE for reference ReturnNewPath - Where the optimized path is returned
/*
     * Determine the maximum number of NameSegs that the Target and Current paths
     * can possibly have in common. (To optimize, we have to have at least 1)
     *
     * Note: The external NamePath string lengths are always a multiple of 5
     * (ACPI_NAME_SIZE + separator)
     */ /*
     * Determine how many NameSegs the two paths have in common.
     * (Starting from the root)
     */ /* Compare two single NameSegs */ /* Mismatch */ /* There must be at least 1 common NameSeg in order to optimize */ /* Determine how many prefix Carats are required */ /*
     * Construct a new target string
     */ /* Insert the Carats into the Target string */ /*
     * Copy only the necessary (optimal) segments from the original
     * target string
     */ /* Special handling for exact subpath in a name declaration */ /*
         * The current path is longer than the target, and the target is a
         * subpath of the current path. We must include one more NameSeg of
         * the target path
         */ /* Special handling for Scope() operator */ /* Make sure we haven't gone off the end of the target path */ /*
     * Internalize the new target string and check it against the original
     * string to make sure that this is in fact an optimization. If the
     * original string is already optimal, there is no point in continuing.
     */ /*
     * Check to make sure that the optimization finds the node we are
     * looking for. This is simply a sanity check on the new
     * path that has been created.
     */ /* Found the namepath, but make sure the node is correct */ /* The lookup matched the node, accept this optimization */ /* Node is not correct, do not use this optimization */ /* The lookup failed, we obviously cannot use this optimization */