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,
507             ", %u Optimizations", Gbl_ExceptionCount[ASL_OPTIMIZATION]);
508     }
509 
510     FlPrintFile (FileId, "\n");
511 }
512 
513 
514 /*******************************************************************************
515  *
516  * FUNCTION:    UtCheckIntegerRange
517  *
518  * PARAMETERS:  Op                  - Integer parse node
519  *              LowValue            - Smallest allowed value
520  *              HighValue           - Largest allowed value
521  *
522  * RETURN:      Op if OK, otherwise NULL
523  *
524  * DESCRIPTION: Check integer for an allowable range
525  *
526  ******************************************************************************/
527 
528 ACPI_PARSE_OBJECT *
529 UtCheckIntegerRange (
530     ACPI_PARSE_OBJECT       *Op,
531     UINT32                  LowValue,
532     UINT32                  HighValue)
533 {
534 
535     if (!Op)
536     {
537         return (NULL);
538     }
539 
540     if ((Op->Asl.Value.Integer < LowValue) ||
541         (Op->Asl.Value.Integer > HighValue))
542     {
543         sprintf (MsgBuffer, "0x%X, allowable: 0x%X-0x%X",
544             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
545 
546         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
547         return (NULL);
548     }
549 
550     return (Op);
551 }
552 
553 
554 /*******************************************************************************
555  *
556  * FUNCTION:    UtStringCacheCalloc
557  *
558  * PARAMETERS:  Length              - Size of buffer requested
559  *
560  * RETURN:      Pointer to the buffer. Aborts on allocation failure
561  *
562  * DESCRIPTION: Allocate a string buffer. Bypass the local
563  *              dynamic memory manager for performance reasons (This has a
564  *              major impact on the speed of the compiler.)
565  *
566  ******************************************************************************/
567 
568 char *
569 UtStringCacheCalloc (
570     UINT32                  Length)
571 {
572     char                    *Buffer;
573     ASL_CACHE_INFO          *Cache;
574     UINT32                  CacheSize = ASL_STRING_CACHE_SIZE;
575 
576 
577     if (Length > CacheSize)
578     {
579         CacheSize = Length;
580 
581         if (Gbl_StringCacheList)
582         {
583             Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
584 
585             /* Link new cache buffer just following head of list */
586 
587             Cache->Next = Gbl_StringCacheList->Next;
588             Gbl_StringCacheList->Next = Cache;
589 
590             /* Leave cache management pointers alone as they pertain to head */
591 
592             Gbl_StringCount++;
593             Gbl_StringSize += Length;
594 
595             return (Cache->Buffer);
596         }
597     }
598 
599     if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast)
600     {
601         /* Allocate a new buffer */
602 
603         Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
604 
605         /* Link new cache buffer to head of list */
606 
607         Cache->Next = Gbl_StringCacheList;
608         Gbl_StringCacheList = Cache;
609 
610         /* Setup cache management pointers */
611 
612         Gbl_StringCacheNext = Cache->Buffer;
613         Gbl_StringCacheLast = Gbl_StringCacheNext + CacheSize;
614     }
615 
616     Gbl_StringCount++;
617     Gbl_StringSize += Length;
618 
619     Buffer = Gbl_StringCacheNext;
620     Gbl_StringCacheNext += Length;
621     return (Buffer);
622 }
623 
624 
625 /******************************************************************************
626  *
627  * FUNCTION:    UtExpandLineBuffers
628  *
629  * PARAMETERS:  None. Updates global line buffer pointers.
630  *
631  * RETURN:      None. Reallocates the global line buffers
632  *
633  * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates
634  *              all global line buffers and updates Gbl_LineBufferSize. NOTE:
635  *              Also used for the initial allocation of the buffers, when
636  *              all of the buffer pointers are NULL. Initial allocations are
637  *              of size ASL_DEFAULT_LINE_BUFFER_SIZE
638  *
639  *****************************************************************************/
640 
641 void
642 UtExpandLineBuffers (
643     void)
644 {
645     UINT32                  NewSize;
646 
647 
648     /* Attempt to double the size of all line buffers */
649 
650     NewSize = Gbl_LineBufferSize * 2;
651     if (Gbl_CurrentLineBuffer)
652     {
653         DbgPrint (ASL_DEBUG_OUTPUT,
654             "Increasing line buffer size from %u to %u\n",
655             Gbl_LineBufferSize, NewSize);
656     }
657 
658     Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize);
659     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
660     if (!Gbl_CurrentLineBuffer)
661     {
662         goto ErrorExit;
663     }
664 
665     Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize);
666     if (!Gbl_MainTokenBuffer)
667     {
668         goto ErrorExit;
669     }
670 
671     Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize);
672     if (!Gbl_MacroTokenBuffer)
673     {
674         goto ErrorExit;
675     }
676 
677     Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize);
678     if (!Gbl_ExpressionTokenBuffer)
679     {
680         goto ErrorExit;
681     }
682 
683     Gbl_LineBufferSize = NewSize;
684     return;
685 
686 
687     /* On error above, simply issue error messages and abort, cannot continue */
688 
689 ErrorExit:
690     printf ("Could not increase line buffer size from %u to %u\n",
691         Gbl_LineBufferSize, Gbl_LineBufferSize * 2);
692 
693     AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION,
694         NULL, NULL);
695     AslAbort ();
696 }
697 
698 
699 /******************************************************************************
700  *
701  * FUNCTION:    UtFreeLineBuffers
702  *
703  * PARAMETERS:  None
704  *
705  * RETURN:      None
706  *
707  * DESCRIPTION: Free all line buffers
708  *
709  *****************************************************************************/
710 
711 void
712 UtFreeLineBuffers (
713     void)
714 {
715 
716     free (Gbl_CurrentLineBuffer);
717     free (Gbl_MainTokenBuffer);
718     free (Gbl_MacroTokenBuffer);
719     free (Gbl_ExpressionTokenBuffer);
720 }
721 
722 
723 /*******************************************************************************
724  *
725  * FUNCTION:    UtInternalizeName
726  *
727  * PARAMETERS:  ExternalName        - Name to convert
728  *              ConvertedName       - Where the converted name is returned
729  *
730  * RETURN:      Status
731  *
732  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
733  *
734  ******************************************************************************/
735 
736 ACPI_STATUS
737 UtInternalizeName (
738     char                    *ExternalName,
739     char                    **ConvertedName)
740 {
741     ACPI_NAMESTRING_INFO    Info;
742     ACPI_STATUS             Status;
743 
744 
745     if (!ExternalName)
746     {
747         return (AE_OK);
748     }
749 
750     /* Get the length of the new internal name */
751 
752     Info.ExternalName = ExternalName;
753     AcpiNsGetInternalNameLength (&Info);
754 
755     /* We need a segment to store the internal name */
756 
757     Info.InternalName = UtStringCacheCalloc (Info.Length);
758     if (!Info.InternalName)
759     {
760         return (AE_NO_MEMORY);
761     }
762 
763     /* Build the name */
764 
765     Status = AcpiNsBuildInternalName (&Info);
766     if (ACPI_FAILURE (Status))
767     {
768         return (Status);
769     }
770 
771     *ConvertedName = Info.InternalName;
772     return (AE_OK);
773 }
774 
775 
776 /*******************************************************************************
777  *
778  * FUNCTION:    UtPadNameWithUnderscores
779  *
780  * PARAMETERS:  NameSeg             - Input nameseg
781  *              PaddedNameSeg       - Output padded nameseg
782  *
783  * RETURN:      Padded nameseg.
784  *
785  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
786  *              ACPI_NAME.
787  *
788  ******************************************************************************/
789 
790 static void
791 UtPadNameWithUnderscores (
792     char                    *NameSeg,
793     char                    *PaddedNameSeg)
794 {
795     UINT32                  i;
796 
797 
798     for (i = 0; (i < ACPI_NAME_SIZE); i++)
799     {
800         if (*NameSeg)
801         {
802             *PaddedNameSeg = *NameSeg;
803             NameSeg++;
804         }
805         else
806         {
807             *PaddedNameSeg = '_';
808         }
809         PaddedNameSeg++;
810     }
811 }
812 
813 
814 /*******************************************************************************
815  *
816  * FUNCTION:    UtAttachNameseg
817  *
818  * PARAMETERS:  Op                  - Parent parse node
819  *              Name                - Full ExternalName
820  *
821  * RETURN:      None; Sets the NameSeg field in parent node
822  *
823  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
824  *              in the NameSeg field of the Op.
825  *
826  ******************************************************************************/
827 
828 static void
829 UtAttachNameseg (
830     ACPI_PARSE_OBJECT       *Op,
831     char                    *Name)
832 {
833     char                    *NameSeg;
834     char                    PaddedNameSeg[4];
835 
836 
837     if (!Name)
838     {
839         return;
840     }
841 
842     /* Look for the last dot in the namepath */
843 
844     NameSeg = strrchr (Name, '.');
845     if (NameSeg)
846     {
847         /* Found last dot, we have also found the final nameseg */
848 
849         NameSeg++;
850         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
851     }
852     else
853     {
854         /* No dots in the namepath, there is only a single nameseg. */
855         /* Handle prefixes */
856 
857         while (ACPI_IS_ROOT_PREFIX (*Name) ||
858                ACPI_IS_PARENT_PREFIX (*Name))
859         {
860             Name++;
861         }
862 
863         /* Remaining string should be one single nameseg */
864 
865         UtPadNameWithUnderscores (Name, PaddedNameSeg);
866     }
867 
868     ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
869 }
870 
871 
872 /*******************************************************************************
873  *
874  * FUNCTION:    UtAttachNamepathToOwner
875  *
876  * PARAMETERS:  Op                  - Parent parse node
877  *              NameOp              - Node that contains the name
878  *
879  * RETURN:      Sets the ExternalName and Namepath in the parent node
880  *
881  * DESCRIPTION: Store the name in two forms in the parent node: The original
882  *              (external) name, and the internalized name that is used within
883  *              the ACPI namespace manager.
884  *
885  ******************************************************************************/
886 
887 void
888 UtAttachNamepathToOwner (
889     ACPI_PARSE_OBJECT       *Op,
890     ACPI_PARSE_OBJECT       *NameOp)
891 {
892     ACPI_STATUS             Status;
893 
894 
895     /* Full external path */
896 
897     Op->Asl.ExternalName = NameOp->Asl.Value.String;
898 
899     /* Save the NameOp for possible error reporting later */
900 
901     Op->Asl.ParentMethod = (void *) NameOp;
902 
903     /* Last nameseg of the path */
904 
905     UtAttachNameseg (Op, Op->Asl.ExternalName);
906 
907     /* Create internalized path */
908 
909     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
910     if (ACPI_FAILURE (Status))
911     {
912         /* TBD: abort on no memory */
913     }
914 }
915 
916 
917 /*******************************************************************************
918  *
919  * FUNCTION:    UtDoConstant
920  *
921  * PARAMETERS:  String              - Hex, Octal, or Decimal string
922  *
923  * RETURN:      Converted Integer
924  *
925  * DESCRIPTION: Convert a string to an integer, with error checking.
926  *
927  ******************************************************************************/
928 
929 UINT64
930 UtDoConstant (
931     char                    *String)
932 {
933     ACPI_STATUS             Status;
934     UINT64                  Converted;
935     char                    ErrBuf[64];
936 
937 
938     Status = UtStrtoul64 (String, 0, &Converted);
939     if (ACPI_FAILURE (Status))
940     {
941         sprintf (ErrBuf, "%s %s\n", "Conversion error:",
942             AcpiFormatException (Status));
943         AslCompilererror (ErrBuf);
944     }
945 
946     return (Converted);
947 }
948 
949 
950 /* TBD: use version in ACPICA main code base? */
951 
952 /*******************************************************************************
953  *
954  * FUNCTION:    UtStrtoul64
955  *
956  * PARAMETERS:  String              - Null terminated string
957  *              Terminater          - Where a pointer to the terminating byte
958  *                                    is returned
959  *              Base                - Radix of the string
960  *
961  * RETURN:      Converted value
962  *
963  * DESCRIPTION: Convert a string into an unsigned value.
964  *
965  ******************************************************************************/
966 
967 ACPI_STATUS
968 UtStrtoul64 (
969     char                    *String,
970     UINT32                  Base,
971     UINT64                  *RetInteger)
972 {
973     UINT32                  Index;
974     UINT32                  Sign;
975     UINT64                  ReturnValue = 0;
976     ACPI_STATUS             Status = AE_OK;
977 
978 
979     *RetInteger = 0;
980 
981     switch (Base)
982     {
983     case 0:
984     case 8:
985     case 10:
986     case 16:
987 
988         break;
989 
990     default:
991         /*
992          * The specified Base parameter is not in the domain of
993          * this function:
994          */
995         return (AE_BAD_PARAMETER);
996     }
997 
998     /* Skip over any white space in the buffer: */
999 
1000     while (isspace ((int) *String) || *String == '\t')
1001     {
1002         ++String;
1003     }
1004 
1005     /*
1006      * The buffer may contain an optional plus or minus sign.
1007      * If it does, then skip over it but remember what is was:
1008      */
1009     if (*String == '-')
1010     {
1011         Sign = NEGATIVE;
1012         ++String;
1013     }
1014     else if (*String == '+')
1015     {
1016         ++String;
1017         Sign = POSITIVE;
1018     }
1019     else
1020     {
1021         Sign = POSITIVE;
1022     }
1023 
1024     /*
1025      * If the input parameter Base is zero, then we need to
1026      * determine if it is octal, decimal, or hexadecimal:
1027      */
1028     if (Base == 0)
1029     {
1030         if (*String == '0')
1031         {
1032             if (tolower ((int) *(++String)) == 'x')
1033             {
1034                 Base = 16;
1035                 ++String;
1036             }
1037             else
1038             {
1039                 Base = 8;
1040             }
1041         }
1042         else
1043         {
1044             Base = 10;
1045         }
1046     }
1047 
1048     /*
1049      * For octal and hexadecimal bases, skip over the leading
1050      * 0 or 0x, if they are present.
1051      */
1052     if (Base == 8 && *String == '0')
1053     {
1054         String++;
1055     }
1056 
1057     if (Base == 16 &&
1058         *String == '0' &&
1059         tolower ((int) *(++String)) == 'x')
1060     {
1061         String++;
1062     }
1063 
1064     /* Main loop: convert the string to an unsigned long */
1065 
1066     while (*String)
1067     {
1068         if (isdigit ((int) *String))
1069         {
1070             Index = ((UINT8) *String) - '0';
1071         }
1072         else
1073         {
1074             Index = (UINT8) toupper ((int) *String);
1075             if (isupper ((int) Index))
1076             {
1077                 Index = Index - 'A' + 10;
1078             }
1079             else
1080             {
1081                 goto ErrorExit;
1082             }
1083         }
1084 
1085         if (Index >= Base)
1086         {
1087             goto ErrorExit;
1088         }
1089 
1090         /* Check to see if value is out of range: */
1091 
1092         if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) /
1093                             (UINT64) Base))
1094         {
1095             goto ErrorExit;
1096         }
1097         else
1098         {
1099             ReturnValue *= Base;
1100             ReturnValue += Index;
1101         }
1102 
1103         ++String;
1104     }
1105 
1106 
1107     /* If a minus sign was present, then "the conversion is negated": */
1108 
1109     if (Sign == NEGATIVE)
1110     {
1111         ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1;
1112     }
1113 
1114     *RetInteger = ReturnValue;
1115     return (Status);
1116 
1117 
1118 ErrorExit:
1119     switch (Base)
1120     {
1121     case 8:
1122 
1123         Status = AE_BAD_OCTAL_CONSTANT;
1124         break;
1125 
1126     case 10:
1127 
1128         Status = AE_BAD_DECIMAL_CONSTANT;
1129         break;
1130 
1131     case 16:
1132 
1133         Status = AE_BAD_HEX_CONSTANT;
1134         break;
1135 
1136     default:
1137 
1138         /* Base validated above */
1139 
1140         break;
1141     }
1142 
1143     return (Status);
1144 }
1145