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