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