7dc0697236b8933ff887586a45820c60f73265c9
[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:    UtHexCharToValue
247  *
248  * PARAMETERS:  HexChar             - Hex character in Ascii
249  *
250  * RETURN:      The binary value of the hex character
251  *
252  * DESCRIPTION: Perform ascii-to-hex translation
253  *
254  ******************************************************************************/
255
256 UINT8
257 UtHexCharToValue (
258     int                     HexChar)
259 {
260
261     if (HexChar <= 0x39)
262     {
263         return ((UINT8) (HexChar - 0x30));
264     }
265
266     if (HexChar <= 0x46)
267     {
268         return ((UINT8) (HexChar - 0x37));
269     }
270
271     return ((UINT8) (HexChar - 0x57));
272 }
273
274
275 /*******************************************************************************
276  *
277  * FUNCTION:    UtConvertByteToHex
278  *
279  * PARAMETERS:  RawByte             - Binary data
280  *              Buffer              - Pointer to where the hex bytes will be
281  *                                    stored
282  *
283  * RETURN:      Ascii hex byte is stored in Buffer.
284  *
285  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
286  *              with "0x"
287  *
288  ******************************************************************************/
289
290 void
291 UtConvertByteToHex (
292     UINT8                   RawByte,
293     UINT8                   *Buffer)
294 {
295
296     Buffer[0] = '0';
297     Buffer[1] = 'x';
298
299     Buffer[2] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF];
300     Buffer[3] = (UINT8) AslHexLookup[RawByte & 0xF];
301 }
302
303
304 /*******************************************************************************
305  *
306  * FUNCTION:    UtConvertByteToAsmHex
307  *
308  * PARAMETERS:  RawByte             - Binary data
309  *              Buffer              - Pointer to where the hex bytes will be
310  *                                    stored
311  *
312  * RETURN:      Ascii hex byte is stored in Buffer.
313  *
314  * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed
315  *              with "0x"
316  *
317  ******************************************************************************/
318
319 void
320 UtConvertByteToAsmHex (
321     UINT8                   RawByte,
322     UINT8                   *Buffer)
323 {
324
325     Buffer[0] = '0';
326     Buffer[1] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF];
327     Buffer[2] = (UINT8) AslHexLookup[RawByte & 0xF];
328     Buffer[3] = 'h';
329 }
330
331
332 /*******************************************************************************
333  *
334  * FUNCTION:    DbgPrint
335  *
336  * PARAMETERS:  Type                - Type of output
337  *              Fmt                 - Printf format string
338  *              ...                 - variable printf list
339  *
340  * RETURN:      None
341  *
342  * DESCRIPTION: Conditional print statement. Prints to stderr only if the
343  *              debug flag is set.
344  *
345  ******************************************************************************/
346
347 void
348 DbgPrint (
349     UINT32                  Type,
350     char                    *Fmt,
351     ...)
352 {
353     va_list                 Args;
354
355
356     if (!Gbl_DebugFlag)
357     {
358         return;
359     }
360
361     if ((Type == ASL_PARSE_OUTPUT) &&
362         (!(AslCompilerdebug)))
363     {
364         return;
365     }
366
367     va_start (Args, Fmt);
368     (void) vfprintf (stderr, Fmt, Args);
369     va_end (Args);
370     return;
371 }
372
373
374 /*******************************************************************************
375  *
376  * FUNCTION:    UtPrintFormattedName
377  *
378  * PARAMETERS:  ParseOpcode         - Parser keyword ID
379  *              Level               - Indentation level
380  *
381  * RETURN:      None
382  *
383  * DESCRIPTION: Print the ascii name of the parse opcode.
384  *
385  ******************************************************************************/
386
387 #define TEXT_OFFSET 10
388
389 void
390 UtPrintFormattedName (
391     UINT16                  ParseOpcode,
392     UINT32                  Level)
393 {
394
395     if (Level)
396     {
397         DbgPrint (ASL_TREE_OUTPUT,
398             "%*s", (3 * Level), " ");
399     }
400     DbgPrint (ASL_TREE_OUTPUT,
401         " %-20.20s", UtGetOpName (ParseOpcode));
402
403     if (Level < TEXT_OFFSET)
404     {
405         DbgPrint (ASL_TREE_OUTPUT,
406             "%*s", (TEXT_OFFSET - Level) * 3, " ");
407     }
408 }
409
410
411 /*******************************************************************************
412  *
413  * FUNCTION:    UtSetParseOpName
414  *
415  * PARAMETERS:  Op                  - Parse op to be named.
416  *
417  * RETURN:      None
418  *
419  * DESCRIPTION: Insert the ascii name of the parse opcode
420  *
421  ******************************************************************************/
422
423 void
424 UtSetParseOpName (
425     ACPI_PARSE_OBJECT       *Op)
426 {
427
428     strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode),
429         ACPI_MAX_PARSEOP_NAME);
430 }
431
432
433 /*******************************************************************************
434  *
435  * FUNCTION:    UtDisplaySummary
436  *
437  * PARAMETERS:  FileID              - ID of outpout file
438  *
439  * RETURN:      None
440  *
441  * DESCRIPTION: Display compilation statistics
442  *
443  ******************************************************************************/
444
445 void
446 UtDisplaySummary (
447     UINT32                  FileId)
448 {
449     UINT32                  i;
450
451
452     if (FileId != ASL_FILE_STDOUT)
453     {
454         /* Compiler name and version number */
455
456         FlPrintFile (FileId, "%s version %X%s [%s]\n\n",
457             ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH, __DATE__);
458     }
459
460     /* Summary of main input and output files */
461
462     if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA)
463     {
464         FlPrintFile (FileId,
465             "%-14s %s - %u lines, %u bytes, %u fields\n",
466             "Table Input:",
467             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
468             Gbl_InputByteCount, Gbl_InputFieldCount);
469
470         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
471         {
472             FlPrintFile (FileId,
473                 "%-14s %s - %u bytes\n",
474                 "Binary Output:",
475                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength);
476         }
477     }
478     else
479     {
480         FlPrintFile (FileId,
481             "%-14s %s - %u lines, %u bytes, %u keywords\n",
482             "ASL Input:",
483             Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber,
484             Gbl_InputByteCount, TotalKeywords);
485
486         /* AML summary */
487
488         if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
489         {
490             FlPrintFile (FileId,
491                 "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n",
492                 "AML Output:",
493                 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength,
494                 TotalNamedObjects, TotalExecutableOpcodes);
495         }
496     }
497
498     /* Display summary of any optional files */
499
500     for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
501     {
502         if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle)
503         {
504             continue;
505         }
506
507         /* .SRC is a temp file unless specifically requested */
508
509         if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag))
510         {
511             continue;
512         }
513
514         /* .I is a temp file unless specifically requested */
515
516         if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_PreprocessorOutputFlag))
517         {
518             continue;
519         }
520
521         FlPrintFile (FileId, "%14s %s - %u bytes\n",
522             Gbl_Files[i].ShortDescription,
523             Gbl_Files[i].Filename, FlGetFileSize (i));
524     }
525
526     /* Error summary */
527
528     FlPrintFile (FileId,
529         "\nCompilation complete. %u Errors, %u Warnings, %u Remarks",
530         Gbl_ExceptionCount[ASL_ERROR],
531         Gbl_ExceptionCount[ASL_WARNING] +
532             Gbl_ExceptionCount[ASL_WARNING2] +
533             Gbl_ExceptionCount[ASL_WARNING3],
534         Gbl_ExceptionCount[ASL_REMARK]);
535
536     if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
537     {
538         FlPrintFile (FileId,
539             ", %u Optimizations", Gbl_ExceptionCount[ASL_OPTIMIZATION]);
540     }
541
542     FlPrintFile (FileId, "\n");
543 }
544
545
546 /*******************************************************************************
547  *
548  * FUNCTION:    UtCheckIntegerRange
549  *
550  * PARAMETERS:  Op                  - Integer parse node
551  *              LowValue            - Smallest allowed value
552  *              HighValue           - Largest allowed value
553  *
554  * RETURN:      Op if OK, otherwise NULL
555  *
556  * DESCRIPTION: Check integer for an allowable range
557  *
558  ******************************************************************************/
559
560 ACPI_PARSE_OBJECT *
561 UtCheckIntegerRange (
562     ACPI_PARSE_OBJECT       *Op,
563     UINT32                  LowValue,
564     UINT32                  HighValue)
565 {
566
567     if (!Op)
568     {
569         return (NULL);
570     }
571
572     if ((Op->Asl.Value.Integer < LowValue) ||
573         (Op->Asl.Value.Integer > HighValue))
574     {
575         sprintf (MsgBuffer, "0x%X, allowable: 0x%X-0x%X",
576             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
577
578         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
579         return (NULL);
580     }
581
582     return (Op);
583 }
584
585
586 /*******************************************************************************
587  *
588  * FUNCTION:    UtGetStringBuffer
589  *
590  * PARAMETERS:  Length              - Size of buffer requested
591  *
592  * RETURN:      Pointer to the buffer. Aborts on allocation failure
593  *
594  * DESCRIPTION: Allocate a string buffer. Bypass the local
595  *              dynamic memory manager for performance reasons (This has a
596  *              major impact on the speed of the compiler.)
597  *
598  ******************************************************************************/
599
600 char *
601 UtGetStringBuffer (
602     UINT32                  Length)
603 {
604     char                    *Buffer;
605
606
607     if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast)
608     {
609         Gbl_StringCacheNext = UtLocalCalloc (ASL_STRING_CACHE_SIZE + Length);
610         Gbl_StringCacheLast = Gbl_StringCacheNext + ASL_STRING_CACHE_SIZE +
611                                 Length;
612     }
613
614     Buffer = Gbl_StringCacheNext;
615     Gbl_StringCacheNext += Length;
616
617     return (Buffer);
618 }
619
620
621 /******************************************************************************
622  *
623  * FUNCTION:    UtExpandLineBuffers
624  *
625  * PARAMETERS:  None. Updates global line buffer pointers.
626  *
627  * RETURN:      None. Reallocates the global line buffers
628  *
629  * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates
630  *              all global line buffers and updates Gbl_LineBufferSize. NOTE:
631  *              Also used for the initial allocation of the buffers, when
632  *              all of the buffer pointers are NULL. Initial allocations are
633  *              of size ASL_DEFAULT_LINE_BUFFER_SIZE
634  *
635  *****************************************************************************/
636
637 void
638 UtExpandLineBuffers (
639     void)
640 {
641     UINT32                  NewSize;
642
643
644     /* Attempt to double the size of all line buffers */
645
646     NewSize = Gbl_LineBufferSize * 2;
647     if (Gbl_CurrentLineBuffer)
648     {
649         DbgPrint (ASL_DEBUG_OUTPUT,"Increasing line buffer size from %u to %u\n",
650             Gbl_LineBufferSize, NewSize);
651     }
652
653     Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize);
654     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
655     if (!Gbl_CurrentLineBuffer)
656     {
657         goto ErrorExit;
658     }
659
660     Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize);
661     if (!Gbl_MainTokenBuffer)
662     {
663         goto ErrorExit;
664     }
665
666     Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize);
667     if (!Gbl_MacroTokenBuffer)
668     {
669         goto ErrorExit;
670     }
671
672     Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize);
673     if (!Gbl_ExpressionTokenBuffer)
674     {
675         goto ErrorExit;
676     }
677
678     Gbl_LineBufferSize = NewSize;
679     return;
680
681
682     /* On error above, simply issue error messages and abort, cannot continue */
683
684 ErrorExit:
685     printf ("Could not increase line buffer size from %u to %u\n",
686         Gbl_LineBufferSize, Gbl_LineBufferSize * 2);
687
688     AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION,
689         NULL, NULL);
690     AslAbort ();
691 }
692
693
694 /*******************************************************************************
695  *
696  * FUNCTION:    UtInternalizeName
697  *
698  * PARAMETERS:  ExternalName        - Name to convert
699  *              ConvertedName       - Where the converted name is returned
700  *
701  * RETURN:      Status
702  *
703  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
704  *
705  ******************************************************************************/
706
707 ACPI_STATUS
708 UtInternalizeName (
709     char                    *ExternalName,
710     char                    **ConvertedName)
711 {
712     ACPI_NAMESTRING_INFO    Info;
713     ACPI_STATUS             Status;
714
715
716     if (!ExternalName)
717     {
718         return (AE_OK);
719     }
720
721     /* Get the length of the new internal name */
722
723     Info.ExternalName = ExternalName;
724     AcpiNsGetInternalNameLength (&Info);
725
726     /* We need a segment to store the internal  name */
727
728     Info.InternalName = UtGetStringBuffer (Info.Length);
729     if (!Info.InternalName)
730     {
731         return (AE_NO_MEMORY);
732     }
733
734     /* Build the name */
735
736     Status = AcpiNsBuildInternalName (&Info);
737     if (ACPI_FAILURE (Status))
738     {
739         return (Status);
740     }
741
742     *ConvertedName = Info.InternalName;
743     return (AE_OK);
744 }
745
746
747 /*******************************************************************************
748  *
749  * FUNCTION:    UtPadNameWithUnderscores
750  *
751  * PARAMETERS:  NameSeg             - Input nameseg
752  *              PaddedNameSeg       - Output padded nameseg
753  *
754  * RETURN:      Padded nameseg.
755  *
756  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
757  *              ACPI_NAME.
758  *
759  ******************************************************************************/
760
761 static void
762 UtPadNameWithUnderscores (
763     char                    *NameSeg,
764     char                    *PaddedNameSeg)
765 {
766     UINT32                  i;
767
768
769     for (i = 0; (i < ACPI_NAME_SIZE); i++)
770     {
771         if (*NameSeg)
772         {
773             *PaddedNameSeg = *NameSeg;
774             NameSeg++;
775         }
776         else
777         {
778             *PaddedNameSeg = '_';
779         }
780         PaddedNameSeg++;
781     }
782 }
783
784
785 /*******************************************************************************
786  *
787  * FUNCTION:    UtAttachNameseg
788  *
789  * PARAMETERS:  Op                  - Parent parse node
790  *              Name                - Full ExternalName
791  *
792  * RETURN:      None; Sets the NameSeg field in parent node
793  *
794  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
795  *              in the NameSeg field of the Op.
796  *
797  ******************************************************************************/
798
799 static void
800 UtAttachNameseg (
801     ACPI_PARSE_OBJECT       *Op,
802     char                    *Name)
803 {
804     char                    *NameSeg;
805     char                    PaddedNameSeg[4];
806
807
808     if (!Name)
809     {
810         return;
811     }
812
813     /* Look for the last dot in the namepath */
814
815     NameSeg = strrchr (Name, '.');
816     if (NameSeg)
817     {
818         /* Found last dot, we have also found the final nameseg */
819
820         NameSeg++;
821         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
822     }
823     else
824     {
825         /* No dots in the namepath, there is only a single nameseg. */
826         /* Handle prefixes */
827
828         while (ACPI_IS_ROOT_PREFIX (*Name) ||
829                ACPI_IS_PARENT_PREFIX (*Name))
830         {
831             Name++;
832         }
833
834         /* Remaining string should be one single nameseg */
835
836         UtPadNameWithUnderscores (Name, PaddedNameSeg);
837     }
838
839     ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
840 }
841
842
843 /*******************************************************************************
844  *
845  * FUNCTION:    UtAttachNamepathToOwner
846  *
847  * PARAMETERS:  Op                  - Parent parse node
848  *              NameOp              - Node that contains the name
849  *
850  * RETURN:      Sets the ExternalName and Namepath in the parent node
851  *
852  * DESCRIPTION: Store the name in two forms in the parent node: The original
853  *              (external) name, and the internalized name that is used within
854  *              the ACPI namespace manager.
855  *
856  ******************************************************************************/
857
858 void
859 UtAttachNamepathToOwner (
860     ACPI_PARSE_OBJECT       *Op,
861     ACPI_PARSE_OBJECT       *NameOp)
862 {
863     ACPI_STATUS             Status;
864
865
866     /* Full external path */
867
868     Op->Asl.ExternalName = NameOp->Asl.Value.String;
869
870     /* Save the NameOp for possible error reporting later */
871
872     Op->Asl.ParentMethod = (void *) NameOp;
873
874     /* Last nameseg of the path */
875
876     UtAttachNameseg (Op, Op->Asl.ExternalName);
877
878     /* Create internalized path */
879
880     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
881     if (ACPI_FAILURE (Status))
882     {
883         /* TBD: abort on no memory */
884     }
885 }
886
887
888 /*******************************************************************************
889  *
890  * FUNCTION:    UtDoConstant
891  *
892  * PARAMETERS:  String              - Hex, Octal, or Decimal string
893  *
894  * RETURN:      Converted Integer
895  *
896  * DESCRIPTION: Convert a string to an integer, with error checking.
897  *
898  ******************************************************************************/
899
900 UINT64
901 UtDoConstant (
902     char                    *String)
903 {
904     ACPI_STATUS             Status;
905     UINT64                  Converted;
906     char                    ErrBuf[64];
907
908
909     Status = UtStrtoul64 (String, 0, &Converted);
910     if (ACPI_FAILURE (Status))
911     {
912         sprintf (ErrBuf, "%s %s\n", "Conversion error:",
913             AcpiFormatException (Status));
914         AslCompilererror (ErrBuf);
915     }
916
917     return (Converted);
918 }
919
920
921 /* TBD: use version in ACPICA main code base? */
922
923 /*******************************************************************************
924  *
925  * FUNCTION:    UtStrtoul64
926  *
927  * PARAMETERS:  String              - Null terminated string
928  *              Terminater          - Where a pointer to the terminating byte
929  *                                    is returned
930  *              Base                - Radix of the string
931  *
932  * RETURN:      Converted value
933  *
934  * DESCRIPTION: Convert a string into an unsigned value.
935  *
936  ******************************************************************************/
937
938 ACPI_STATUS
939 UtStrtoul64 (
940     char                    *String,
941     UINT32                  Base,
942     UINT64                  *RetInteger)
943 {
944     UINT32                  Index;
945     UINT32                  Sign;
946     UINT64                  ReturnValue = 0;
947     ACPI_STATUS             Status = AE_OK;
948
949
950     *RetInteger = 0;
951
952     switch (Base)
953     {
954     case 0:
955     case 8:
956     case 10:
957     case 16:
958
959         break;
960
961     default:
962         /*
963          * The specified Base parameter is not in the domain of
964          * this function:
965          */
966         return (AE_BAD_PARAMETER);
967     }
968
969     /* Skip over any white space in the buffer: */
970
971     while (isspace ((int) *String) || *String == '\t')
972     {
973         ++String;
974     }
975
976     /*
977      * The buffer may contain an optional plus or minus sign.
978      * If it does, then skip over it but remember what is was:
979      */
980     if (*String == '-')
981     {
982         Sign = NEGATIVE;
983         ++String;
984     }
985     else if (*String == '+')
986     {
987         ++String;
988         Sign = POSITIVE;
989     }
990     else
991     {
992         Sign = POSITIVE;
993     }
994
995     /*
996      * If the input parameter Base is zero, then we need to
997      * determine if it is octal, decimal, or hexadecimal:
998      */
999     if (Base == 0)
1000     {
1001         if (*String == '0')
1002         {
1003             if (tolower ((int) *(++String)) == 'x')
1004             {
1005                 Base = 16;
1006                 ++String;
1007             }
1008             else
1009             {
1010                 Base = 8;
1011             }
1012         }
1013         else
1014         {
1015             Base = 10;
1016         }
1017     }
1018
1019     /*
1020      * For octal and hexadecimal bases, skip over the leading
1021      * 0 or 0x, if they are present.
1022      */
1023     if (Base == 8 && *String == '0')
1024     {
1025         String++;
1026     }
1027
1028     if (Base == 16 &&
1029         *String == '0' &&
1030         tolower ((int) *(++String)) == 'x')
1031     {
1032         String++;
1033     }
1034
1035     /* Main loop: convert the string to an unsigned long */
1036
1037     while (*String)
1038     {
1039         if (isdigit ((int) *String))
1040         {
1041             Index = ((UINT8) *String) - '0';
1042         }
1043         else
1044         {
1045             Index = (UINT8) toupper ((int) *String);
1046             if (isupper ((int) Index))
1047             {
1048                 Index = Index - 'A' + 10;
1049             }
1050             else
1051             {
1052                 goto ErrorExit;
1053             }
1054         }
1055
1056         if (Index >= Base)
1057         {
1058             goto ErrorExit;
1059         }
1060
1061         /* Check to see if value is out of range: */
1062
1063         if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) /
1064                             (UINT64) Base))
1065         {
1066             goto ErrorExit;
1067         }
1068         else
1069         {
1070             ReturnValue *= Base;
1071             ReturnValue += Index;
1072         }
1073
1074         ++String;
1075     }
1076
1077
1078     /* If a minus sign was present, then "the conversion is negated": */
1079
1080     if (Sign == NEGATIVE)
1081     {
1082         ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1;
1083     }
1084
1085     *RetInteger = ReturnValue;
1086     return (Status);
1087
1088
1089 ErrorExit:
1090     switch (Base)
1091     {
1092     case 8:
1093
1094         Status = AE_BAD_OCTAL_CONSTANT;
1095         break;
1096
1097     case 10:
1098
1099         Status = AE_BAD_DECIMAL_CONSTANT;
1100         break;
1101
1102     case 16:
1103
1104         Status = AE_BAD_HEX_CONSTANT;
1105         break;
1106
1107     default:
1108
1109         /* Base validated above */
1110
1111         break;
1112     }
1113
1114     return (Status);
1115 }