1 /******************************************************************************
3 * Module Name: aslprintf - ASL Printf/Fprintf macro support
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
48 #define _COMPONENT ACPI_COMPILER
49 ACPI_MODULE_NAME ("aslprintf")
52 /* Local prototypes */
55 OpcCreateConcatenateNode (
56 ACPI_PARSE_OBJECT *Op,
57 ACPI_PARSE_OBJECT *Node);
61 ACPI_PARSE_OBJECT *Op,
62 ACPI_PARSE_OBJECT *DestOp);
65 /*******************************************************************************
67 * FUNCTION: OpcDoPrintf
69 * PARAMETERS: Op - printf parse node
73 * DESCRIPTION: Convert printf macro to a Store(..., Debug) AML operation.
75 ******************************************************************************/
79 ACPI_PARSE_OBJECT *Op)
81 ACPI_PARSE_OBJECT *DestOp;
84 /* Store destination is the Debug op */
86 DestOp = TrAllocateNode (PARSEOP_DEBUG);
87 DestOp->Asl.AmlOpcode = AML_DEBUG_OP;
88 DestOp->Asl.Parent = Op;
89 DestOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
91 OpcParsePrintf (Op, DestOp);
95 /*******************************************************************************
97 * FUNCTION: OpcDoFprintf
99 * PARAMETERS: Op - fprintf parse node
103 * DESCRIPTION: Convert fprintf macro to a Store AML operation.
105 ******************************************************************************/
109 ACPI_PARSE_OBJECT *Op)
111 ACPI_PARSE_OBJECT *DestOp;
114 /* Store destination is the first argument of fprintf */
116 DestOp = Op->Asl.Child;
117 Op->Asl.Child = DestOp->Asl.Next;
118 DestOp->Asl.Next = NULL;
120 OpcParsePrintf (Op, DestOp);
124 /*******************************************************************************
126 * FUNCTION: OpcParsePrintf
128 * PARAMETERS: Op - Printf parse node
129 * DestOp - Destination of Store operation
133 * DESCRIPTION: Convert printf macro to a Store AML operation. The printf
134 * macro parse tree is layed out as follows:
136 * Op - printf parse op
137 * Op->Child - Format string
138 * Op->Next - Format string arguments
140 ******************************************************************************/
144 ACPI_PARSE_OBJECT *Op,
145 ACPI_PARSE_OBJECT *DestOp)
148 char *StartPosition = NULL;
149 ACPI_PARSE_OBJECT *ArgNode;
150 ACPI_PARSE_OBJECT *NextNode;
151 UINT32 StringLength = 0;
153 BOOLEAN StringToProcess = FALSE;
154 ACPI_PARSE_OBJECT *NewOp;
157 /* Get format string */
159 Format = ACPI_CAST_PTR (char, Op->Asl.Child->Asl.Value.String);
160 ArgNode = Op->Asl.Child->Asl.Next;
163 * Detach argument list so that we can use a NULL check to distinguish
164 * the first concatenation operation we need to make
166 Op->Asl.Child = NULL;
168 for (; *Format; ++Format)
172 if (!StringToProcess)
174 /* Mark the beginning of a string */
176 StartPosition = Format;
177 StringToProcess = TRUE;
184 /* Save string, if any, to new string object and concat it */
188 NewString = UtStringCacheCalloc (StringLength + 1);
189 ACPI_STRNCPY (NewString, StartPosition, StringLength);
191 NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
192 NewOp->Asl.Value.String = NewString;
193 NewOp->Asl.AmlOpcode = AML_STRING_OP;
194 NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
195 NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
197 OpcCreateConcatenateNode(Op, NewOp);
200 StringToProcess = FALSE;
206 * We have a format parameter and will need an argument to go
210 ArgNode->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
212 AslError(ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, NULL);
217 * We do not support sub-specifiers of printf (flags, width,
218 * precision, length). For specifiers we only support %x/%X for
219 * hex or %s for strings. Also, %o for generic "acpi object".
225 if (ArgNode->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
227 AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgNode,
232 NextNode = ArgNode->Asl.Next;
233 ArgNode->Asl.Next = NULL;
234 OpcCreateConcatenateNode(Op, ArgNode);
242 NextNode = ArgNode->Asl.Next;
243 ArgNode->Asl.Next = NULL;
246 * Append an empty string if the first argument is
247 * not a string. This will implicitly conver the 2nd
248 * concat source to a string per the ACPI specification.
252 NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
253 NewOp->Asl.Value.String = "";
254 NewOp->Asl.AmlOpcode = AML_STRING_OP;
255 NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
256 NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
258 OpcCreateConcatenateNode(Op, NewOp);
261 OpcCreateConcatenateNode(Op, ArgNode);
267 AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Op,
268 "Unrecognized format specifier");
273 /* Process any remaining string */
277 NewString = UtStringCacheCalloc (StringLength + 1);
278 ACPI_STRNCPY (NewString, StartPosition, StringLength);
280 NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
281 NewOp->Asl.Value.String = NewString;
282 NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
283 NewOp->Asl.AmlOpcode = AML_STRING_OP;
284 NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
286 OpcCreateConcatenateNode(Op, NewOp);
290 * If we get here and there's no child node then Format
291 * was an empty string. Just make a no op.
295 Op->Asl.ParseOpcode = PARSEOP_NOOP;
296 AslError(ASL_WARNING, ASL_MSG_NULL_STRING, Op,
297 "Converted to NOOP");
301 /* Check for erroneous extra arguments */
304 ArgNode->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
306 AslError(ASL_WARNING, ASL_MSG_ARG_COUNT_HI, ArgNode,
307 "Extra arguments ignored");
310 /* Change Op to a Store */
312 Op->Asl.ParseOpcode = PARSEOP_STORE;
313 Op->Common.AmlOpcode = AML_STORE_OP;
314 Op->Asl.CompileFlags = 0;
316 /* Disable further optimization */
318 Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
319 UtSetParseOpName (Op);
321 /* Set Store destination */
323 Op->Asl.Child->Asl.Next = DestOp;
327 /*******************************************************************************
329 * FUNCTION: OpcCreateConcatenateNode
331 * PARAMETERS: Op - Parse node
332 * Node - Parse node to be concatenated
336 * DESCRIPTION: Make Node the child of Op. If child node already exists, then
337 * concat child with Node and makes concat node the child of Op.
339 ******************************************************************************/
342 OpcCreateConcatenateNode (
343 ACPI_PARSE_OBJECT *Op,
344 ACPI_PARSE_OBJECT *Node)
346 ACPI_PARSE_OBJECT *NewConcatOp;
351 Op->Asl.Child = Node;
352 Node->Asl.Parent = Op;
356 NewConcatOp = TrAllocateNode (PARSEOP_CONCATENATE);
357 NewConcatOp->Asl.AmlOpcode = AML_CONCAT_OP;
358 NewConcatOp->Asl.AcpiBtype = 0x7;
359 NewConcatOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;
361 /* First arg is child of Op*/
363 NewConcatOp->Asl.Child = Op->Asl.Child;
364 Op->Asl.Child->Asl.Parent = NewConcatOp;
366 /* Second arg is Node */
368 NewConcatOp->Asl.Child->Asl.Next = Node;
369 Node->Asl.Parent = NewConcatOp;
371 /* Third arg is Zero (not used) */
373 NewConcatOp->Asl.Child->Asl.Next->Asl.Next =
374 TrAllocateNode (PARSEOP_ZERO);
375 NewConcatOp->Asl.Child->Asl.Next->Asl.Next->Asl.Parent =
378 Op->Asl.Child = NewConcatOp;
379 NewConcatOp->Asl.Parent = Op;