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