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