1 /******************************************************************************
2  *
3  * Module Name: aslutils -- compiler utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
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 "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acdisasm.h"
47 #include "acnamesp.h"
48 #include "amlcode.h"
49 #include <acapps.h>
50 
51 #define _COMPONENT          ACPI_COMPILER
52         ACPI_MODULE_NAME    ("aslutils")
53 
54 
55 /* Local prototypes */
56 
57 static void
58 UtPadNameWithUnderscores (
59     char                    *NameSeg,
60     char                    *PaddedNameSeg);
61 
62 static void
63 UtAttachNameseg (
64     ACPI_PARSE_OBJECT       *Op,
65     char                    *Name);
66 
67 
68 /*******************************************************************************
69  *
70  * FUNCTION:    UtDisplaySupportedTables
71  *
72  * PARAMETERS:  None
73  *
74  * RETURN:      None
75  *
76  * DESCRIPTION: Print all supported ACPI table names.
77  *
78  ******************************************************************************/
79 
80 #define ACPI_TABLE_HELP_FORMAT  "%8u) %s    %s\n"
81 
82 void
83 UtDisplaySupportedTables (
84     void)
85 {
86     ACPI_DMTABLE_DATA       *TableData;
87     UINT32                  i;
88 
89 
90     printf ("\nACPI tables supported by iASL version %8.8X:\n"
91         "  (Compiler, Disassembler, Template Generator)\n\n",
92         ACPI_CA_VERSION);
93 
94     /* Special tables */
95 
96     printf ("  Special tables and AML tables:\n");
97     printf (ACPI_TABLE_HELP_FORMAT, 1, ACPI_RSDP_NAME, "Root System Description Pointer");
98     printf (ACPI_TABLE_HELP_FORMAT, 2, ACPI_SIG_FACS, "Firmware ACPI Control Structure");
99     printf (ACPI_TABLE_HELP_FORMAT, 3, ACPI_SIG_DSDT, "Differentiated System Description Table");
100     printf (ACPI_TABLE_HELP_FORMAT, 4, ACPI_SIG_SSDT, "Secondary System Description Table");
101 
102     /* All data tables with common table header */
103 
104     printf ("\n  Standard ACPI data tables:\n");
105     for (TableData = AcpiDmTableData, i = 5; TableData->Signature; TableData++, i++)
106     {
107         printf (ACPI_TABLE_HELP_FORMAT, i, TableData->Signature, TableData->Name);
108     }
109 }
110 
111 
112 /*******************************************************************************
113  *
114  * FUNCTION:    UtDisplayConstantOpcodes
115  *
116  * PARAMETERS:  None
117  *
118  * RETURN:      None
119  *
120  * DESCRIPTION: Print AML opcodes that can be used in constant expressions.
121  *
122  ******************************************************************************/
123 
124 void
125 UtDisplayConstantOpcodes (
126     void)
127 {
128     UINT32                  i;
129 
130 
131     printf ("Constant expression opcode information\n\n");
132 
133     for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++)
134     {
135         if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT)
136         {
137             printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name);
138         }
139     }
140 }
141 
142 
143 /*******************************************************************************
144  *
145  * FUNCTION:    UtLocalCalloc
146  *
147  * PARAMETERS:  Size                - Bytes to be allocated
148  *
149  * RETURN:      Pointer to the allocated memory. Guaranteed to be valid.
150  *
151  * DESCRIPTION: Allocate zero-initialized memory. Aborts the compile on an
152  *              allocation failure, on the assumption that nothing more can be
153  *              accomplished.
154  *
155  ******************************************************************************/
156 
157 void *
158 UtLocalCalloc (
159     UINT32                  Size)
160 {
161     void                    *Allocated;
162 
163 
164     Allocated = ACPI_ALLOCATE_ZEROED (Size);
165     if (!Allocated)
166     {
167         AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION,
168             Gbl_CurrentLineNumber, Gbl_LogicalLineNumber,
169             Gbl_InputByteCount, Gbl_CurrentColumn,
170             Gbl_Files[ASL_FILE_INPUT].Filename, NULL);
171 
172         CmCleanupAndExit ();
173         exit (1);
174     }
175 
176     TotalAllocations++;
177     TotalAllocated += Size;
178     return (Allocated);
179 }
180 
181 
182 /*******************************************************************************
183  *
184  * FUNCTION:    UtBeginEvent
185  *
186  * PARAMETERS:  Name                - Ascii name of this event
187  *
188  * RETURN:      Event number (integer index)
189  *
190  * DESCRIPTION: Saves the current time with this event
191  *
192  ******************************************************************************/
193 
194 UINT8
195 UtBeginEvent (
196     char                    *Name)
197 {
198 
199     if (AslGbl_NextEvent >= ASL_NUM_EVENTS)
200     {
201         AcpiOsPrintf ("Ran out of compiler event structs!\n");
202         return (AslGbl_NextEvent);
203     }
204 
205     /* Init event with current (start) time */
206 
207     AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer ();
208     AslGbl_Events[AslGbl_NextEvent].EventName = Name;
209     AslGbl_Events[AslGbl_NextEvent].Valid = TRUE;
210 
211     return (AslGbl_NextEvent++);
212 }
213 
214 
215 /*******************************************************************************
216  *
217  * FUNCTION:    UtEndEvent
218  *
219  * PARAMETERS:  Event               - Event number (integer index)
220  *
221  * RETURN:      None
222  *
223  * DESCRIPTION: Saves the current time (end time) with this event
224  *
225  ******************************************************************************/
226 
227 void
228 UtEndEvent (
229     UINT8                   Event)
230 {
231 
232     if (Event >= ASL_NUM_EVENTS)
233     {
234         return;
235     }
236 
237     /* Insert end time for event */
238 
239     AslGbl_Events[Event].EndTime = AcpiOsGetTimer ();
240 }
241 
242 
243 /*******************************************************************************
244  *
245  * FUNCTION:    UtConvertByteToHex
246  *
247  * PARAMETERS:  RawByte             - Binary data
248  *              Buffer              - Pointer to where the hex bytes will be
249  *                                    stored
250  *
251  * RETURN:      Ascii hex byte is stored in Buffer.
252  *
253  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
254  *              with "0x"
255  *
256  ******************************************************************************/
257 
258 void
259 UtConvertByteToHex (
260     UINT8                   RawByte,
261     UINT8                   *Buffer)
262 {
263 
264     Buffer[0] = '0';
265     Buffer[1] = 'x';
266 
267     Buffer[2] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 4);
268     Buffer[3] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 0);
269 }
270 
271 
272 /*******************************************************************************
273  *
274  * FUNCTION:    UtConvertByteToAsmHex
275  *
276  * PARAMETERS:  RawByte             - Binary data
277  *              Buffer              - Pointer to where the hex bytes will be
278  *                                    stored
279  *
280  * RETURN:      Ascii hex byte is stored in Buffer.
281  *
282  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
283  *              with '0', and a trailing 'h' is added.
284  *
285  ******************************************************************************/
286 
287 void
288 UtConvertByteToAsmHex (
289     UINT8                   RawByte,
290     UINT8                   *Buffer)
291 {
292 
293     Buffer[0] = '0';
294     Buffer[1] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 4);
295     Buffer[2] = (UINT8) AcpiUtHexToAsciiChar (RawByte, 0);
296     Buffer[3] = 'h';
297 }
298 
299 
300 /*******************************************************************************
301  *
302  * FUNCTION:    DbgPrint
303  *
304  * PARAMETERS:  Type                - Type of output
305  *              Fmt                 - Printf format string
306  *              ...                 - variable printf list
307  *
308  * RETURN:      None
309  *
310  * DESCRIPTION: Conditional print statement. Prints to stderr only if the
311  *              debug flag is set.
312  *
313  ******************************************************************************/
314 
315 void
316 DbgPrint (
317     UINT32                  Type,
318     char                    *Fmt,
319     ...)
320 {
321     va_list                 Args;
322 
323 
324     if (!Gbl_DebugFlag)
325     {
326         return;
327     }
328 
329     if ((Type == ASL_PARSE_OUTPUT) &&
330         (!(AslCompilerdebug)))
331     {
332         return;
333     }
334 
335     va_start (Args, Fmt);
336     (void) vfprintf (stderr, Fmt, Args);
337     va_end (Args);
338     return;
339 }
340 
341 
342 /*******************************************************************************
343  *
344  * FUNCTION:    UtPrintFormattedName
345  *
346  * PARAMETERS:  ParseOpcode         - Parser keyword ID
347  *              Level               - Indentation level
348  *
349  * RETURN:      None
350  *
351  * DESCRIPTION: Print the ascii name of the parse opcode.
352  *
353  ******************************************************************************/
354 
355 #define TEXT_OFFSET 10
356 
357 void
358 UtPrintFormattedName (
359     UINT16                  ParseOpcode,
360     UINT32                  Level)
361 {
362 
363     if (Level)
364     {
365         DbgPrint (ASL_TREE_OUTPUT,
366             "%*s", (3 * Level), " ");
367     }
368     DbgPrint (ASL_TREE_OUTPUT,
369         " %-20.20s", UtGetOpName (ParseOpcode));
370 
371     if (Level < TEXT_OFFSET)
372     {
373         DbgPrint (ASL_TREE_OUTPUT,
374             "%*s", (TEXT_OFFSET - Level) * 3, " ");
375     }
376 }
377 
378 
379 /*******************************************************************************
380  *
381  * FUNCTION:    UtSetParseOpName
382  *
383  * PARAMETERS:  Op                  - Parse op to be named.
384  *
385  * RETURN:      None
386  *
387  * DESCRIPTION: Insert the ascii name of the parse opcode
388  *
389  ******************************************************************************/
390 
391 void
392 UtSetParseOpName (
393     ACPI_PARSE_OBJECT       *Op)
394 {
395 
396     strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode),
397         ACPI_MAX_PARSEOP_NAME);
398 }
399 
400 
401 /*******************************************************************************
402  *
403  * FUNCTION:    UtDisplaySummary
404  *
405  * PARAMETERS:  FileID              - ID of outpout file
406  *
407  * RETURN:      None
408  *
409  * DESCRIPTION: Display compilation statistics
410  *
411  ******************************************************************************/
412 
413 void
414 UtDisplaySummary (
415     UINT32                  FileId)
416 {
417     UINT32                  i;
418 
419 
420     if (FileId != ASL_FILE_STDOUT)
421     {
422         /* Compiler name and version number */
423 
424         FlPrintFile (FileId, "%s version %X%s [%s]\n\n",
425             ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH, __DATE__);
426     }
427 
428     /* Summary of main input and output files */
429 
430     if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA)
431     {
432         FlPrintFile (FileId,
433             "%-14s %s - %u lines, %u bytes, %u fields\n",
434             "Table Input:",
435             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
436             Gbl_InputByteCount, Gbl_InputFieldCount);
437 
438         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
439         {
440             FlPrintFile (FileId,
441                 "%-14s %s - %u bytes\n",
442                 "Binary Output:",
443                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength);
444         }
445     }
446     else
447     {
448         FlPrintFile (FileId,
449             "%-14s %s - %u lines, %u bytes, %u keywords\n",
450             "ASL Input:",
451             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
452             Gbl_InputByteCount, TotalKeywords);
453 
454         /* AML summary */
455 
456         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
457         {
458             FlPrintFile (FileId,
459                 "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n",
460                 "AML Output:",
461                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength,
462                 TotalNamedObjects, TotalExecutableOpcodes);
463         }
464     }
465 
466     /* Display summary of any optional files */
467 
468     for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
469     {
470         if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle)
471         {
472             continue;
473         }
474 
475         /* .SRC is a temp file unless specifically requested */
476 
477         if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag))
478         {
479             continue;
480         }
481 
482         /* .I is a temp file unless specifically requested */
483 
484         if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_PreprocessorOutputFlag))
485         {
486             continue;
487         }
488 
489         FlPrintFile (FileId, "%14s %s - %u bytes\n",
490             Gbl_Files[i].ShortDescription,
491             Gbl_Files[i].Filename, FlGetFileSize (i));
492     }
493 
494     /* Error summary */
495 
496     FlPrintFile (FileId,
497         "\nCompilation complete. %u Errors, %u Warnings, %u Remarks",
498         Gbl_ExceptionCount[ASL_ERROR],
499         Gbl_ExceptionCount[ASL_WARNING] +
500             Gbl_ExceptionCount[ASL_WARNING2] +
501             Gbl_ExceptionCount[ASL_WARNING3],
502         Gbl_ExceptionCount[ASL_REMARK]);
503 
504     if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
505     {
506         FlPrintFile (FileId, ", %u Optimizations",
507             Gbl_ExceptionCount[ASL_OPTIMIZATION]);
508 
509         if (TotalFolds)
510         {
511             FlPrintFile (FileId, ", %u Constants Folded", TotalFolds);
512         }
513     }
514 
515     FlPrintFile (FileId, "\n");
516 }
517 
518 
519 /*******************************************************************************
520  *
521  * FUNCTION:    UtCheckIntegerRange
522  *
523  * PARAMETERS:  Op                  - Integer parse node
524  *              LowValue            - Smallest allowed value
525  *              HighValue           - Largest allowed value
526  *
527  * RETURN:      Op if OK, otherwise NULL
528  *
529  * DESCRIPTION: Check integer for an allowable range
530  *
531  ******************************************************************************/
532 
533 ACPI_PARSE_OBJECT *
534 UtCheckIntegerRange (
535     ACPI_PARSE_OBJECT       *Op,
536     UINT32                  LowValue,
537     UINT32                  HighValue)
538 {
539 
540     if (!Op)
541     {
542         return (NULL);
543     }
544 
545     if ((Op->Asl.Value.Integer < LowValue) ||
546         (Op->Asl.Value.Integer > HighValue))
547     {
548         sprintf (MsgBuffer, "0x%X, allowable: 0x%X-0x%X",
549             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
550 
551         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
552         return (NULL);
553     }
554 
555     return (Op);
556 }
557 
558 
559 /*******************************************************************************
560  *
561  * FUNCTION:    UtStringCacheCalloc
562  *
563  * PARAMETERS:  Length              - Size of buffer requested
564  *
565  * RETURN:      Pointer to the buffer. Aborts on allocation failure
566  *
567  * DESCRIPTION: Allocate a string buffer. Bypass the local
568  *              dynamic memory manager for performance reasons (This has a
569  *              major impact on the speed of the compiler.)
570  *
571  ******************************************************************************/
572 
573 char *
574 UtStringCacheCalloc (
575     UINT32                  Length)
576 {
577     char                    *Buffer;
578     ASL_CACHE_INFO          *Cache;
579     UINT32                  CacheSize = ASL_STRING_CACHE_SIZE;
580 
581 
582     if (Length > CacheSize)
583     {
584         CacheSize = Length;
585 
586         if (Gbl_StringCacheList)
587         {
588             Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
589 
590             /* Link new cache buffer just following head of list */
591 
592             Cache->Next = Gbl_StringCacheList->Next;
593             Gbl_StringCacheList->Next = Cache;
594 
595             /* Leave cache management pointers alone as they pertain to head */
596 
597             Gbl_StringCount++;
598             Gbl_StringSize += Length;
599 
600             return (Cache->Buffer);
601         }
602     }
603 
604     if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast)
605     {
606         /* Allocate a new buffer */
607 
608         Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
609 
610         /* Link new cache buffer to head of list */
611 
612         Cache->Next = Gbl_StringCacheList;
613         Gbl_StringCacheList = Cache;
614 
615         /* Setup cache management pointers */
616 
617         Gbl_StringCacheNext = Cache->Buffer;
618         Gbl_StringCacheLast = Gbl_StringCacheNext + CacheSize;
619     }
620 
621     Gbl_StringCount++;
622     Gbl_StringSize += Length;
623 
624     Buffer = Gbl_StringCacheNext;
625     Gbl_StringCacheNext += Length;
626     return (Buffer);
627 }
628 
629 
630 /******************************************************************************
631  *
632  * FUNCTION:    UtExpandLineBuffers
633  *
634  * PARAMETERS:  None. Updates global line buffer pointers.
635  *
636  * RETURN:      None. Reallocates the global line buffers
637  *
638  * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates
639  *              all global line buffers and updates Gbl_LineBufferSize. NOTE:
640  *              Also used for the initial allocation of the buffers, when
641  *              all of the buffer pointers are NULL. Initial allocations are
642  *              of size ASL_DEFAULT_LINE_BUFFER_SIZE
643  *
644  *****************************************************************************/
645 
646 void
647 UtExpandLineBuffers (
648     void)
649 {
650     UINT32                  NewSize;
651 
652 
653     /* Attempt to double the size of all line buffers */
654 
655     NewSize = Gbl_LineBufferSize * 2;
656     if (Gbl_CurrentLineBuffer)
657     {
658         DbgPrint (ASL_DEBUG_OUTPUT,
659             "Increasing line buffer size from %u to %u\n",
660             Gbl_LineBufferSize, NewSize);
661     }
662 
663     Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize);
664     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
665     if (!Gbl_CurrentLineBuffer)
666     {
667         goto ErrorExit;
668     }
669 
670     Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize);
671     if (!Gbl_MainTokenBuffer)
672     {
673         goto ErrorExit;
674     }
675 
676     Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize);
677     if (!Gbl_MacroTokenBuffer)
678     {
679         goto ErrorExit;
680     }
681 
682     Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize);
683     if (!Gbl_ExpressionTokenBuffer)
684     {
685         goto ErrorExit;
686     }
687 
688     Gbl_LineBufferSize = NewSize;
689     return;
690 
691 
692     /* On error above, simply issue error messages and abort, cannot continue */
693 
694 ErrorExit:
695     printf ("Could not increase line buffer size from %u to %u\n",
696         Gbl_LineBufferSize, Gbl_LineBufferSize * 2);
697 
698     AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION,
699         NULL, NULL);
700     AslAbort ();
701 }
702 
703 
704 /******************************************************************************
705  *
706  * FUNCTION:    UtFreeLineBuffers
707  *
708  * PARAMETERS:  None
709  *
710  * RETURN:      None
711  *
712  * DESCRIPTION: Free all line buffers
713  *
714  *****************************************************************************/
715 
716 void
717 UtFreeLineBuffers (
718     void)
719 {
720 
721     free (Gbl_CurrentLineBuffer);
722     free (Gbl_MainTokenBuffer);
723     free (Gbl_MacroTokenBuffer);
724     free (Gbl_ExpressionTokenBuffer);
725 }
726 
727 
728 /*******************************************************************************
729  *
730  * FUNCTION:    UtInternalizeName
731  *
732  * PARAMETERS:  ExternalName        - Name to convert
733  *              ConvertedName       - Where the converted name is returned
734  *
735  * RETURN:      Status
736  *
737  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
738  *
739  ******************************************************************************/
740 
741 ACPI_STATUS
742 UtInternalizeName (
743     char                    *ExternalName,
744     char                    **ConvertedName)
745 {
746     ACPI_NAMESTRING_INFO    Info;
747     ACPI_STATUS             Status;
748 
749 
750     if (!ExternalName)
751     {
752         return (AE_OK);
753     }
754 
755     /* Get the length of the new internal name */
756 
757     Info.ExternalName = ExternalName;
758     AcpiNsGetInternalNameLength (&Info);
759 
760     /* We need a segment to store the internal name */
761 
762     Info.InternalName = UtStringCacheCalloc (Info.Length);
763     if (!Info.InternalName)
764     {
765         return (AE_NO_MEMORY);
766     }
767 
768     /* Build the name */
769 
770     Status = AcpiNsBuildInternalName (&Info);
771     if (ACPI_FAILURE (Status))
772     {
773         return (Status);
774     }
775 
776     *ConvertedName = Info.InternalName;
777     return (AE_OK);
778 }
779 
780 
781 /*******************************************************************************
782  *
783  * FUNCTION:    UtPadNameWithUnderscores
784  *
785  * PARAMETERS:  NameSeg             - Input nameseg
786  *              PaddedNameSeg       - Output padded nameseg
787  *
788  * RETURN:      Padded nameseg.
789  *
790  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
791  *              ACPI_NAME.
792  *
793  ******************************************************************************/
794 
795 static void
796 UtPadNameWithUnderscores (
797     char                    *NameSeg,
798     char                    *PaddedNameSeg)
799 {
800     UINT32                  i;
801 
802 
803     for (i = 0; (i < ACPI_NAME_SIZE); i++)
804     {
805         if (*NameSeg)
806         {
807             *PaddedNameSeg = *NameSeg;
808             NameSeg++;
809         }
810         else
811         {
812             *PaddedNameSeg = '_';
813         }
814         PaddedNameSeg++;
815     }
816 }
817 
818 
819 /*******************************************************************************
820  *
821  * FUNCTION:    UtAttachNameseg
822  *
823  * PARAMETERS:  Op                  - Parent parse node
824  *              Name                - Full ExternalName
825  *
826  * RETURN:      None; Sets the NameSeg field in parent node
827  *
828  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
829  *              in the NameSeg field of the Op.
830  *
831  ******************************************************************************/
832 
833 static void
834 UtAttachNameseg (
835     ACPI_PARSE_OBJECT       *Op,
836     char                    *Name)
837 {
838     char                    *NameSeg;
839     char                    PaddedNameSeg[4];
840 
841 
842     if (!Name)
843     {
844         return;
845     }
846 
847     /* Look for the last dot in the namepath */
848 
849     NameSeg = strrchr (Name, '.');
850     if (NameSeg)
851     {
852         /* Found last dot, we have also found the final nameseg */
853 
854         NameSeg++;
855         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
856     }
857     else
858     {
859         /* No dots in the namepath, there is only a single nameseg. */
860         /* Handle prefixes */
861 
862         while (ACPI_IS_ROOT_PREFIX (*Name) ||
863                ACPI_IS_PARENT_PREFIX (*Name))
864         {
865             Name++;
866         }
867 
868         /* Remaining string should be one single nameseg */
869 
870         UtPadNameWithUnderscores (Name, PaddedNameSeg);
871     }
872 
873     ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
874 }
875 
876 
877 /*******************************************************************************
878  *
879  * FUNCTION:    UtAttachNamepathToOwner
880  *
881  * PARAMETERS:  Op                  - Parent parse node
882  *              NameOp              - Node that contains the name
883  *
884  * RETURN:      Sets the ExternalName and Namepath in the parent node
885  *
886  * DESCRIPTION: Store the name in two forms in the parent node: The original
887  *              (external) name, and the internalized name that is used within
888  *              the ACPI namespace manager.
889  *
890  ******************************************************************************/
891 
892 void
893 UtAttachNamepathToOwner (
894     ACPI_PARSE_OBJECT       *Op,
895     ACPI_PARSE_OBJECT       *NameOp)
896 {
897     ACPI_STATUS             Status;
898 
899 
900     /* Full external path */
901 
902     Op->Asl.ExternalName = NameOp->Asl.Value.String;
903 
904     /* Save the NameOp for possible error reporting later */
905 
906     Op->Asl.ParentMethod = (void *) NameOp;
907 
908     /* Last nameseg of the path */
909 
910     UtAttachNameseg (Op, Op->Asl.ExternalName);
911 
912     /* Create internalized path */
913 
914     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
915     if (ACPI_FAILURE (Status))
916     {
917         /* TBD: abort on no memory */
918     }
919 }
920 
921 
922 /*******************************************************************************
923  *
924  * FUNCTION:    UtDoConstant
925  *
926  * PARAMETERS:  String              - Hex, Octal, or Decimal string
927  *
928  * RETURN:      Converted Integer
929  *
930  * DESCRIPTION: Convert a string to an integer, with error checking.
931  *
932  ******************************************************************************/
933 
934 UINT64
935 UtDoConstant (
936     char                    *String)
937 {
938     ACPI_STATUS             Status;
939     UINT64                  Converted;
940     char                    ErrBuf[64];
941 
942 
943     Status = UtStrtoul64 (String, 0, &Converted);
944     if (ACPI_FAILURE (Status))
945     {
946         sprintf (ErrBuf, "%s %s\n", "Conversion error:",
947             AcpiFormatException (Status));
948         AslCompilererror (ErrBuf);
949     }
950 
951     return (Converted);
952 }
953 
954 
955 /* TBD: use version in ACPICA main code base? */
956 
957 /*******************************************************************************
958  *
959  * FUNCTION:    UtStrtoul64
960  *
961  * PARAMETERS:  String              - Null terminated string
962  *              Terminater          - Where a pointer to the terminating byte
963  *                                    is returned
964  *              Base                - Radix of the string
965  *
966  * RETURN:      Converted value
967  *
968  * DESCRIPTION: Convert a string into an unsigned value.
969  *
970  ******************************************************************************/
971 
972 ACPI_STATUS
973 UtStrtoul64 (
974     char                    *String,
975     UINT32                  Base,
976     UINT64                  *RetInteger)
977 {
978     UINT32                  Index;
979     UINT32                  Sign;
980     UINT64                  ReturnValue = 0;
981     ACPI_STATUS             Status = AE_OK;
982 
983 
984     *RetInteger = 0;
985 
986     switch (Base)
987     {
988     case 0:
989     case 8:
990     case 10:
991     case 16:
992 
993         break;
994 
995     default:
996         /*
997          * The specified Base parameter is not in the domain of
998          * this function:
999          */
1000         return (AE_BAD_PARAMETER);
1001     }
1002 
1003     /* Skip over any white space in the buffer: */
1004 
1005     while (isspace ((int) *String) || *String == '\t')
1006     {
1007         ++String;
1008     }
1009 
1010     /*
1011      * The buffer may contain an optional plus or minus sign.
1012      * If it does, then skip over it but remember what is was:
1013      */
1014     if (*String == '-')
1015     {
1016         Sign = NEGATIVE;
1017         ++String;
1018     }
1019     else if (*String == '+')
1020     {
1021         ++String;
1022         Sign = POSITIVE;
1023     }
1024     else
1025     {
1026         Sign = POSITIVE;
1027     }
1028 
1029     /*
1030      * If the input parameter Base is zero, then we need to
1031      * determine if it is octal, decimal, or hexadecimal:
1032      */
1033     if (Base == 0)
1034     {
1035         if (*String == '0')
1036         {
1037             if (tolower ((int) *(++String)) == 'x')
1038             {
1039                 Base = 16;
1040                 ++String;
1041             }
1042             else
1043             {
1044                 Base = 8;
1045             }
1046         }
1047         else
1048         {
1049             Base = 10;
1050         }
1051     }
1052 
1053     /*
1054      * For octal and hexadecimal bases, skip over the leading
1055      * 0 or 0x, if they are present.
1056      */
1057     if (Base == 8 && *String == '0')
1058     {
1059         String++;
1060     }
1061 
1062     if (Base == 16 &&
1063         *String == '0' &&
1064         tolower ((int) *(++String)) == 'x')
1065     {
1066         String++;
1067     }
1068 
1069     /* Main loop: convert the string to an unsigned long */
1070 
1071     while (*String)
1072     {
1073         if (isdigit ((int) *String))
1074         {
1075             Index = ((UINT8) *String) - '0';
1076         }
1077         else
1078         {
1079             Index = (UINT8) toupper ((int) *String);
1080             if (isupper ((int) Index))
1081             {
1082                 Index = Index - 'A' + 10;
1083             }
1084             else
1085             {
1086                 goto ErrorExit;
1087             }
1088         }
1089 
1090         if (Index >= Base)
1091         {
1092             goto ErrorExit;
1093         }
1094 
1095         /* Check to see if value is out of range: */
1096 
1097         if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) /
1098                             (UINT64) Base))
1099         {
1100             goto ErrorExit;
1101         }
1102         else
1103         {
1104             ReturnValue *= Base;
1105             ReturnValue += Index;
1106         }
1107 
1108         ++String;
1109     }
1110 
1111 
1112     /* If a minus sign was present, then "the conversion is negated": */
1113 
1114     if (Sign == NEGATIVE)
1115     {
1116         ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1;
1117     }
1118 
1119     *RetInteger = ReturnValue;
1120     return (Status);
1121 
1122 
1123 ErrorExit:
1124     switch (Base)
1125     {
1126     case 8:
1127 
1128         Status = AE_BAD_OCTAL_CONSTANT;
1129         break;
1130 
1131     case 10:
1132 
1133         Status = AE_BAD_DECIMAL_CONSTANT;
1134         break;
1135 
1136     case 16:
1137 
1138         Status = AE_BAD_HEX_CONSTANT;
1139         break;
1140 
1141     default:
1142 
1143         /* Base validated above */
1144 
1145         break;
1146     }
1147 
1148     return (Status);
1149 }
1150