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