FreeBSD/sys/contrib/dev/acpica/compiler/aslprintf.c
/*******************************************************************************
 *
 * FUNCTION:    OpcParsePrintf
 *
 * PARAMETERS:  Op                  - Printf parse node
 *              DestOp              - Destination of Store operation
 *
 * RETURN:      None
 *
 * DESCRIPTION: Convert printf macro to a Store AML operation. The printf
 *              macro parse tree is layed out as follows:
 *
 *              Op        - printf parse op
 *              Op->Child - Format string
 *              Op->Next  - Format string arguments
 *
 ******************************************************************************/
OpcParsePrintf
PARAMETERS:  Op                  - Printf parse node
DestOp              - Destination of Store operation

None

Convert printf macro to a Store AML operation. The printf
macro parse tree is layed out as follows.


OpcParsePrintf PARAMETERS : Op - Printf parse node DestOp - Destination of Store operation None Convert printf macro to a Store AML operation . The printf macro parse tree is layed out as follows .
static void
OpcParsePrintf (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_PARSE_OBJECT       *DestOp)
{
    char                    *Format;
    char                    *StartPosition = NULL;
    ACPI_PARSE_OBJECT       *ArgNode;
    ACPI_PARSE_OBJECT       *NextNode;
    UINT32                  StringLength = 0;
    char                    *NewString;
    BOOLEAN                 StringToProcess = FALSE;
    ACPI_PARSE_OBJECT       *NewOp;
    Format = ACPI_CAST_PTR (char, Op->Asl.Child->Asl.Value.String);
    ArgNode = Op->Asl.Child->Asl.Next;
    Op->Asl.Child = NULL;
    for (; *Format; ++Format)
    {
        if (*Format != '%')
        {
            if (!StringToProcess)
            {
                StartPosition = Format;
                StringToProcess = TRUE;
            }
            ++StringLength;
            continue;
        }
        if (StringToProcess)
        {
            NewString = UtStringCacheCalloc (StringLength + 1);
            strncpy (NewString, StartPosition, StringLength);
            NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
            NewOp->Asl.Value.String = NewString;
            NewOp->Asl.AmlOpcode = AML_STRING_OP;
            NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
            NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
            OpcCreateConcatenateNode(Op, NewOp);
            StringLength = 0;
            StringToProcess = FALSE;
        }
        ++Format;
        if (!ArgNode ||
            ArgNode->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
        {
            AslError(ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, NULL);
            return;
        }
        switch (*Format)
        {
        case 's':
            if (ArgNode->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgNode,
                    "String required");
                return;
            }
            NextNode = ArgNode->Asl.Next;
            ArgNode->Asl.Next = NULL;
            OpcCreateConcatenateNode(Op, ArgNode);
            ArgNode = NextNode;
            continue;
        case 'X':
        case 'x':
        case 'o':
            NextNode = ArgNode->Asl.Next;
            ArgNode->Asl.Next = NULL;
            if (!Op->Asl.Child)
            {
                NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
                NewOp->Asl.Value.String = "";
                NewOp->Asl.AmlOpcode = AML_STRING_OP;
                NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
                NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
                OpcCreateConcatenateNode(Op, NewOp);
            }
            OpcCreateConcatenateNode(Op, ArgNode);
            ArgNode = NextNode;
            break;
        default:
            AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Op,
                "Unrecognized format specifier");
            continue;
        }
    }
    if (StringToProcess)
    {
        NewString = UtStringCacheCalloc (StringLength + 1);
        strncpy (NewString, StartPosition, StringLength);
        NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
        NewOp->Asl.Value.String = NewString;
        NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
        NewOp->Asl.AmlOpcode = AML_STRING_OP;
        NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
        OpcCreateConcatenateNode(Op, NewOp);
    }
    if (!Op->Asl.Child)
    {
        Op->Asl.ParseOpcode = PARSEOP_NOOP;
        AslError(ASL_WARNING, ASL_MSG_NULL_STRING, Op,
            "Converted to NOOP");
        return;
    }
    if (ArgNode &&
        ArgNode->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    {
        AslError(ASL_WARNING, ASL_MSG_ARG_COUNT_HI, ArgNode,
            "Extra arguments ignored");
    }
    Op->Asl.ParseOpcode = PARSEOP_STORE;
    Op->Common.AmlOpcode = AML_STORE_OP;
    Op->Asl.CompileFlags  = 0;
    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    UtSetParseOpName (Op);
    Op->Asl.Child->Asl.Next = DestOp;
}
static void OpcParsePrintf ( ACPI_PARSE_OBJECT * Op , ACPI_PARSE_OBJECT * DestOp ) { char * Format ; char * StartPosition = NULL ; ACPI_PARSE_OBJECT * ArgNode ; ACPI_PARSE_OBJECT * NextNode ; UINT32 StringLength = 0 ; char * NewString ; BOOLEAN StringToProcess = FALSE ; ACPI_PARSE_OBJECT * NewOp ; Format = ACPI_CAST_PTR ( char , Op -> Asl . Child -> Asl . Value . String ) ; ArgNode = Op -> Asl . Child -> Asl . Next ; Op -> Asl . Child = NULL ; for ( ; * Format ; ++ Format ) { if ( * Format != ' ' ) { if ( ! StringToProcess ) { StartPosition = Format ; StringToProcess = TRUE ; } ++ StringLength ; continue ; } if ( StringToProcess ) { NewString = UtStringCacheCalloc ( StringLength + 1 ) ; strncpy ( NewString , StartPosition , StringLength ) ; NewOp = TrAllocateNode ( PARSEOP_STRING_LITERAL ) ; NewOp -> Asl . Value . String = NewString ; NewOp -> Asl . AmlOpcode = AML_STRING_OP ; NewOp -> Asl . AcpiBtype = ACPI_BTYPE_STRING ; NewOp -> Asl . LogicalLineNumber = Op -> Asl . LogicalLineNumber ; OpcCreateConcatenateNode ( Op , NewOp ) ; StringLength = 0 ; StringToProcess = FALSE ; } ++ Format ; if ( ! ArgNode || ArgNode -> Asl . ParseOpcode == PARSEOP_DEFAULT_ARG ) { AslError ( ASL_ERROR , ASL_MSG_ARG_COUNT_LO , Op , NULL ) ; return ; } switch ( * Format ) { case ' ' : if ( ArgNode -> Asl . ParseOpcode != PARSEOP_STRING_LITERAL ) { AslError ( ASL_ERROR , ASL_MSG_INVALID_TYPE , ArgNode , " " ) ; return ; } NextNode = ArgNode -> Asl . Next ; ArgNode -> Asl . Next = NULL ; OpcCreateConcatenateNode ( Op , ArgNode ) ; ArgNode = NextNode ; continue ; case ' ' : case ' ' : case ' ' : NextNode = ArgNode -> Asl . Next ; ArgNode -> Asl . Next = NULL ; if ( ! Op -> Asl . Child ) { NewOp = TrAllocateNode ( PARSEOP_STRING_LITERAL ) ; NewOp -> Asl . Value . String = " " ; NewOp -> Asl . AmlOpcode = AML_STRING_OP ; NewOp -> Asl . AcpiBtype = ACPI_BTYPE_STRING ; NewOp -> Asl . LogicalLineNumber = Op -> Asl . LogicalLineNumber ; OpcCreateConcatenateNode ( Op , NewOp ) ; } OpcCreateConcatenateNode ( Op , ArgNode ) ; ArgNode = NextNode ; break ; default : AslError ( ASL_ERROR , ASL_MSG_INVALID_OPERAND , Op , " " ) ; continue ; } } if ( StringToProcess ) { NewString = UtStringCacheCalloc ( StringLength + 1 ) ; strncpy ( NewString , StartPosition , StringLength ) ; NewOp = TrAllocateNode ( PARSEOP_STRING_LITERAL ) ; NewOp -> Asl . Value . String = NewString ; NewOp -> Asl . AcpiBtype = ACPI_BTYPE_STRING ; NewOp -> Asl . AmlOpcode = AML_STRING_OP ; NewOp -> Asl . LogicalLineNumber = Op -> Asl . LogicalLineNumber ; OpcCreateConcatenateNode ( Op , NewOp ) ; } if ( ! Op -> Asl . Child ) { Op -> Asl . ParseOpcode = PARSEOP_NOOP ; AslError ( ASL_WARNING , ASL_MSG_NULL_STRING , Op , " " ) ; return ; } if ( ArgNode && ArgNode -> Asl . ParseOpcode != PARSEOP_DEFAULT_ARG ) { AslError ( ASL_WARNING , ASL_MSG_ARG_COUNT_HI , ArgNode , " " ) ; } Op -> Asl . ParseOpcode = PARSEOP_STORE ; Op -> Common . AmlOpcode = AML_STORE_OP ; Op -> Asl . CompileFlags = 0 ; Op -> Asl . CompileFlags &= ~ NODE_COMPILE_TIME_CONST ; UtSetParseOpName ( Op ) ; Op -> Asl . Child -> Asl . Next = DestOp ; }
FUNCTION:    OpcParsePrintf
 PARAMETERS:  Op                  - Printf parse node
              DestOp              - Destination of Store operation
FUNCTION : OpcParsePrintf PARAMETERS : Op - Printf parse node DestOp - Destination of Store operation
/* Get format string */ /*
     * Detach argument list so that we can use a NULL check to distinguish
     * the first concatenation operation we need to make
     */ /* Mark the beginning of a string */ /* Save string, if any, to new string object and concat it */ /*
         * We have a format parameter and will need an argument to go
         * with it
         */ /*
         * We do not support sub-specifiers of printf (flags, width,
         * precision, length). For specifiers we only support %x/%X for
         * hex or %s for strings. Also, %o for generic "acpi object".
         */ /*
             * Append an empty string if the first argument is
             * not a string. This will implicitly conver the 2nd
             * concat source to a string per the ACPI specification.
             */ /* Process any remaining string */ /*
     * If we get here and there's no child node then Format
     * was an empty string. Just make a no op.
     */ /* Check for erroneous extra arguments */ /* Change Op to a Store */ /* Disable further optimization */ /* Set Store destination */