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