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