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