aslutils.c revision 284460
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 <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/acdisasm.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48#include <contrib/dev/acpica/include/amlcode.h>
49#include <contrib/dev/acpica/include/acapps.h>
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("aslutils")
53
54
55/* Local prototypes */
56
57static void
58UtPadNameWithUnderscores (
59    char                    *NameSeg,
60    char                    *PaddedNameSeg);
61
62static void
63UtAttachNameseg (
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
80void
81UtDisplaySupportedTables (
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
116void
117UtDisplayConstantOpcodes (
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
149void *
150UtLocalCalloc (
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
186UINT8
187UtBeginEvent (
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
219void
220UtEndEvent (
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
250void
251UtConvertByteToHex (
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
279void
280UtConvertByteToAsmHex (
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
307void
308DbgPrint (
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
349void
350UtPrintFormattedName (
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
383void
384UtSetParseOpName (
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
405void
406UtDisplaySummary (
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\n\n",
417            ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH);
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_InputByteCount, TotalKeywords);
445
446        /* AML summary */
447
448        if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors))
449        {
450            FlPrintFile (FileId,
451                "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n",
452                "AML Output:",
453                Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength,
454                TotalNamedObjects, TotalExecutableOpcodes);
455        }
456    }
457
458    /* Display summary of any optional files */
459
460    for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
461    {
462        if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle)
463        {
464            continue;
465        }
466
467        /* .SRC is a temp file unless specifically requested */
468
469        if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag))
470        {
471            continue;
472        }
473
474        /* .I is a temp file unless specifically requested */
475
476        if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_PreprocessorOutputFlag))
477        {
478            continue;
479        }
480
481        FlPrintFile (FileId, "%14s %s - %u bytes\n",
482            Gbl_Files[i].ShortDescription,
483            Gbl_Files[i].Filename, FlGetFileSize (i));
484    }
485
486    /* Error summary */
487
488    FlPrintFile (FileId,
489        "\nCompilation complete. %u Errors, %u Warnings, %u Remarks",
490        Gbl_ExceptionCount[ASL_ERROR],
491        Gbl_ExceptionCount[ASL_WARNING] +
492            Gbl_ExceptionCount[ASL_WARNING2] +
493            Gbl_ExceptionCount[ASL_WARNING3],
494        Gbl_ExceptionCount[ASL_REMARK]);
495
496    if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
497    {
498        FlPrintFile (FileId, ", %u Optimizations",
499            Gbl_ExceptionCount[ASL_OPTIMIZATION]);
500
501        if (TotalFolds)
502        {
503            FlPrintFile (FileId, ", %u Constants Folded", TotalFolds);
504        }
505    }
506
507    FlPrintFile (FileId, "\n");
508}
509
510
511/*******************************************************************************
512 *
513 * FUNCTION:    UtCheckIntegerRange
514 *
515 * PARAMETERS:  Op                  - Integer parse node
516 *              LowValue            - Smallest allowed value
517 *              HighValue           - Largest allowed value
518 *
519 * RETURN:      Op if OK, otherwise NULL
520 *
521 * DESCRIPTION: Check integer for an allowable range
522 *
523 ******************************************************************************/
524
525ACPI_PARSE_OBJECT *
526UtCheckIntegerRange (
527    ACPI_PARSE_OBJECT       *Op,
528    UINT32                  LowValue,
529    UINT32                  HighValue)
530{
531
532    if (!Op)
533    {
534        return (NULL);
535    }
536
537    if ((Op->Asl.Value.Integer < LowValue) ||
538        (Op->Asl.Value.Integer > HighValue))
539    {
540        sprintf (MsgBuffer, "0x%X, allowable: 0x%X-0x%X",
541            (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
542
543        AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
544        return (NULL);
545    }
546
547    return (Op);
548}
549
550
551/*******************************************************************************
552 *
553 * FUNCTION:    UtStringCacheCalloc
554 *
555 * PARAMETERS:  Length              - Size of buffer requested
556 *
557 * RETURN:      Pointer to the buffer. Aborts on allocation failure
558 *
559 * DESCRIPTION: Allocate a string buffer. Bypass the local
560 *              dynamic memory manager for performance reasons (This has a
561 *              major impact on the speed of the compiler.)
562 *
563 ******************************************************************************/
564
565char *
566UtStringCacheCalloc (
567    UINT32                  Length)
568{
569    char                    *Buffer;
570    ASL_CACHE_INFO          *Cache;
571    UINT32                  CacheSize = ASL_STRING_CACHE_SIZE;
572
573
574    if (Length > CacheSize)
575    {
576        CacheSize = Length;
577
578        if (Gbl_StringCacheList)
579        {
580            Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
581
582            /* Link new cache buffer just following head of list */
583
584            Cache->Next = Gbl_StringCacheList->Next;
585            Gbl_StringCacheList->Next = Cache;
586
587            /* Leave cache management pointers alone as they pertain to head */
588
589            Gbl_StringCount++;
590            Gbl_StringSize += Length;
591
592            return (Cache->Buffer);
593        }
594    }
595
596    if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast)
597    {
598        /* Allocate a new buffer */
599
600        Cache = UtLocalCalloc (sizeof (Cache->Next) + CacheSize);
601
602        /* Link new cache buffer to head of list */
603
604        Cache->Next = Gbl_StringCacheList;
605        Gbl_StringCacheList = Cache;
606
607        /* Setup cache management pointers */
608
609        Gbl_StringCacheNext = Cache->Buffer;
610        Gbl_StringCacheLast = Gbl_StringCacheNext + CacheSize;
611    }
612
613    Gbl_StringCount++;
614    Gbl_StringSize += Length;
615
616    Buffer = Gbl_StringCacheNext;
617    Gbl_StringCacheNext += Length;
618    return (Buffer);
619}
620
621
622/******************************************************************************
623 *
624 * FUNCTION:    UtExpandLineBuffers
625 *
626 * PARAMETERS:  None. Updates global line buffer pointers.
627 *
628 * RETURN:      None. Reallocates the global line buffers
629 *
630 * DESCRIPTION: Called if the current line buffer becomes filled. Reallocates
631 *              all global line buffers and updates Gbl_LineBufferSize. NOTE:
632 *              Also used for the initial allocation of the buffers, when
633 *              all of the buffer pointers are NULL. Initial allocations are
634 *              of size ASL_DEFAULT_LINE_BUFFER_SIZE
635 *
636 *****************************************************************************/
637
638void
639UtExpandLineBuffers (
640    void)
641{
642    UINT32                  NewSize;
643
644
645    /* Attempt to double the size of all line buffers */
646
647    NewSize = Gbl_LineBufferSize * 2;
648    if (Gbl_CurrentLineBuffer)
649    {
650        DbgPrint (ASL_DEBUG_OUTPUT,
651            "Increasing line buffer size from %u to %u\n",
652            Gbl_LineBufferSize, NewSize);
653    }
654
655    Gbl_CurrentLineBuffer = realloc (Gbl_CurrentLineBuffer, NewSize);
656    Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
657    if (!Gbl_CurrentLineBuffer)
658    {
659        goto ErrorExit;
660    }
661
662    Gbl_MainTokenBuffer = realloc (Gbl_MainTokenBuffer, NewSize);
663    if (!Gbl_MainTokenBuffer)
664    {
665        goto ErrorExit;
666    }
667
668    Gbl_MacroTokenBuffer = realloc (Gbl_MacroTokenBuffer, NewSize);
669    if (!Gbl_MacroTokenBuffer)
670    {
671        goto ErrorExit;
672    }
673
674    Gbl_ExpressionTokenBuffer = realloc (Gbl_ExpressionTokenBuffer, NewSize);
675    if (!Gbl_ExpressionTokenBuffer)
676    {
677        goto ErrorExit;
678    }
679
680    Gbl_LineBufferSize = NewSize;
681    return;
682
683
684    /* On error above, simply issue error messages and abort, cannot continue */
685
686ErrorExit:
687    printf ("Could not increase line buffer size from %u to %u\n",
688        Gbl_LineBufferSize, Gbl_LineBufferSize * 2);
689
690    AslError (ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION,
691        NULL, NULL);
692    AslAbort ();
693}
694
695
696/******************************************************************************
697 *
698 * FUNCTION:    UtFreeLineBuffers
699 *
700 * PARAMETERS:  None
701 *
702 * RETURN:      None
703 *
704 * DESCRIPTION: Free all line buffers
705 *
706 *****************************************************************************/
707
708void
709UtFreeLineBuffers (
710    void)
711{
712
713    free (Gbl_CurrentLineBuffer);
714    free (Gbl_MainTokenBuffer);
715    free (Gbl_MacroTokenBuffer);
716    free (Gbl_ExpressionTokenBuffer);
717}
718
719
720/*******************************************************************************
721 *
722 * FUNCTION:    UtInternalizeName
723 *
724 * PARAMETERS:  ExternalName        - Name to convert
725 *              ConvertedName       - Where the converted name is returned
726 *
727 * RETURN:      Status
728 *
729 * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
730 *
731 ******************************************************************************/
732
733ACPI_STATUS
734UtInternalizeName (
735    char                    *ExternalName,
736    char                    **ConvertedName)
737{
738    ACPI_NAMESTRING_INFO    Info;
739    ACPI_STATUS             Status;
740
741
742    if (!ExternalName)
743    {
744        return (AE_OK);
745    }
746
747    /* Get the length of the new internal name */
748
749    Info.ExternalName = ExternalName;
750    AcpiNsGetInternalNameLength (&Info);
751
752    /* We need a segment to store the internal name */
753
754    Info.InternalName = UtStringCacheCalloc (Info.Length);
755    if (!Info.InternalName)
756    {
757        return (AE_NO_MEMORY);
758    }
759
760    /* Build the name */
761
762    Status = AcpiNsBuildInternalName (&Info);
763    if (ACPI_FAILURE (Status))
764    {
765        return (Status);
766    }
767
768    *ConvertedName = Info.InternalName;
769    return (AE_OK);
770}
771
772
773/*******************************************************************************
774 *
775 * FUNCTION:    UtPadNameWithUnderscores
776 *
777 * PARAMETERS:  NameSeg             - Input nameseg
778 *              PaddedNameSeg       - Output padded nameseg
779 *
780 * RETURN:      Padded nameseg.
781 *
782 * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
783 *              ACPI_NAME.
784 *
785 ******************************************************************************/
786
787static void
788UtPadNameWithUnderscores (
789    char                    *NameSeg,
790    char                    *PaddedNameSeg)
791{
792    UINT32                  i;
793
794
795    for (i = 0; (i < ACPI_NAME_SIZE); i++)
796    {
797        if (*NameSeg)
798        {
799            *PaddedNameSeg = *NameSeg;
800            NameSeg++;
801        }
802        else
803        {
804            *PaddedNameSeg = '_';
805        }
806        PaddedNameSeg++;
807    }
808}
809
810
811/*******************************************************************************
812 *
813 * FUNCTION:    UtAttachNameseg
814 *
815 * PARAMETERS:  Op                  - Parent parse node
816 *              Name                - Full ExternalName
817 *
818 * RETURN:      None; Sets the NameSeg field in parent node
819 *
820 * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
821 *              in the NameSeg field of the Op.
822 *
823 ******************************************************************************/
824
825static void
826UtAttachNameseg (
827    ACPI_PARSE_OBJECT       *Op,
828    char                    *Name)
829{
830    char                    *NameSeg;
831    char                    PaddedNameSeg[4];
832
833
834    if (!Name)
835    {
836        return;
837    }
838
839    /* Look for the last dot in the namepath */
840
841    NameSeg = strrchr (Name, '.');
842    if (NameSeg)
843    {
844        /* Found last dot, we have also found the final nameseg */
845
846        NameSeg++;
847        UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
848    }
849    else
850    {
851        /* No dots in the namepath, there is only a single nameseg. */
852        /* Handle prefixes */
853
854        while (ACPI_IS_ROOT_PREFIX (*Name) ||
855               ACPI_IS_PARENT_PREFIX (*Name))
856        {
857            Name++;
858        }
859
860        /* Remaining string should be one single nameseg */
861
862        UtPadNameWithUnderscores (Name, PaddedNameSeg);
863    }
864
865    ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg);
866}
867
868
869/*******************************************************************************
870 *
871 * FUNCTION:    UtAttachNamepathToOwner
872 *
873 * PARAMETERS:  Op                  - Parent parse node
874 *              NameOp              - Node that contains the name
875 *
876 * RETURN:      Sets the ExternalName and Namepath in the parent node
877 *
878 * DESCRIPTION: Store the name in two forms in the parent node: The original
879 *              (external) name, and the internalized name that is used within
880 *              the ACPI namespace manager.
881 *
882 ******************************************************************************/
883
884void
885UtAttachNamepathToOwner (
886    ACPI_PARSE_OBJECT       *Op,
887    ACPI_PARSE_OBJECT       *NameOp)
888{
889    ACPI_STATUS             Status;
890
891
892    /* Full external path */
893
894    Op->Asl.ExternalName = NameOp->Asl.Value.String;
895
896    /* Save the NameOp for possible error reporting later */
897
898    Op->Asl.ParentMethod = (void *) NameOp;
899
900    /* Last nameseg of the path */
901
902    UtAttachNameseg (Op, Op->Asl.ExternalName);
903
904    /* Create internalized path */
905
906    Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
907    if (ACPI_FAILURE (Status))
908    {
909        /* TBD: abort on no memory */
910    }
911}
912
913
914/*******************************************************************************
915 *
916 * FUNCTION:    UtDoConstant
917 *
918 * PARAMETERS:  String              - Hex, Octal, or Decimal string
919 *
920 * RETURN:      Converted Integer
921 *
922 * DESCRIPTION: Convert a string to an integer, with error checking.
923 *
924 ******************************************************************************/
925
926UINT64
927UtDoConstant (
928    char                    *String)
929{
930    ACPI_STATUS             Status;
931    UINT64                  Converted;
932    char                    ErrBuf[64];
933
934
935    Status = UtStrtoul64 (String, 0, &Converted);
936    if (ACPI_FAILURE (Status))
937    {
938        sprintf (ErrBuf, "%s %s\n", "Conversion error:",
939            AcpiFormatException (Status));
940        AslCompilererror (ErrBuf);
941    }
942
943    return (Converted);
944}
945
946
947/* TBD: use version in ACPICA main code base? */
948
949/*******************************************************************************
950 *
951 * FUNCTION:    UtStrtoul64
952 *
953 * PARAMETERS:  String              - Null terminated string
954 *              Terminater          - Where a pointer to the terminating byte
955 *                                    is returned
956 *              Base                - Radix of the string
957 *
958 * RETURN:      Converted value
959 *
960 * DESCRIPTION: Convert a string into an unsigned value.
961 *
962 ******************************************************************************/
963
964ACPI_STATUS
965UtStrtoul64 (
966    char                    *String,
967    UINT32                  Base,
968    UINT64                  *RetInteger)
969{
970    UINT32                  Index;
971    UINT32                  Sign;
972    UINT64                  ReturnValue = 0;
973    ACPI_STATUS             Status = AE_OK;
974
975
976    *RetInteger = 0;
977
978    switch (Base)
979    {
980    case 0:
981    case 8:
982    case 10:
983    case 16:
984
985        break;
986
987    default:
988        /*
989         * The specified Base parameter is not in the domain of
990         * this function:
991         */
992        return (AE_BAD_PARAMETER);
993    }
994
995    /* Skip over any white space in the buffer: */
996
997    while (isspace ((int) *String) || *String == '\t')
998    {
999        ++String;
1000    }
1001
1002    /*
1003     * The buffer may contain an optional plus or minus sign.
1004     * If it does, then skip over it but remember what is was:
1005     */
1006    if (*String == '-')
1007    {
1008        Sign = NEGATIVE;
1009        ++String;
1010    }
1011    else if (*String == '+')
1012    {
1013        ++String;
1014        Sign = POSITIVE;
1015    }
1016    else
1017    {
1018        Sign = POSITIVE;
1019    }
1020
1021    /*
1022     * If the input parameter Base is zero, then we need to
1023     * determine if it is octal, decimal, or hexadecimal:
1024     */
1025    if (Base == 0)
1026    {
1027        if (*String == '0')
1028        {
1029            if (tolower ((int) *(++String)) == 'x')
1030            {
1031                Base = 16;
1032                ++String;
1033            }
1034            else
1035            {
1036                Base = 8;
1037            }
1038        }
1039        else
1040        {
1041            Base = 10;
1042        }
1043    }
1044
1045    /*
1046     * For octal and hexadecimal bases, skip over the leading
1047     * 0 or 0x, if they are present.
1048     */
1049    if (Base == 8 && *String == '0')
1050    {
1051        String++;
1052    }
1053
1054    if (Base == 16 &&
1055        *String == '0' &&
1056        tolower ((int) *(++String)) == 'x')
1057    {
1058        String++;
1059    }
1060
1061    /* Main loop: convert the string to an unsigned long */
1062
1063    while (*String)
1064    {
1065        if (isdigit ((int) *String))
1066        {
1067            Index = ((UINT8) *String) - '0';
1068        }
1069        else
1070        {
1071            Index = (UINT8) toupper ((int) *String);
1072            if (isupper ((int) Index))
1073            {
1074                Index = Index - 'A' + 10;
1075            }
1076            else
1077            {
1078                goto ErrorExit;
1079            }
1080        }
1081
1082        if (Index >= Base)
1083        {
1084            goto ErrorExit;
1085        }
1086
1087        /* Check to see if value is out of range: */
1088
1089        if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) /
1090                            (UINT64) Base))
1091        {
1092            goto ErrorExit;
1093        }
1094        else
1095        {
1096            ReturnValue *= Base;
1097            ReturnValue += Index;
1098        }
1099
1100        ++String;
1101    }
1102
1103
1104    /* If a minus sign was present, then "the conversion is negated": */
1105
1106    if (Sign == NEGATIVE)
1107    {
1108        ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1;
1109    }
1110
1111    *RetInteger = ReturnValue;
1112    return (Status);
1113
1114
1115ErrorExit:
1116    switch (Base)
1117    {
1118    case 8:
1119
1120        Status = AE_BAD_OCTAL_CONSTANT;
1121        break;
1122
1123    case 10:
1124
1125        Status = AE_BAD_DECIMAL_CONSTANT;
1126        break;
1127
1128    case 16:
1129
1130        Status = AE_BAD_HEX_CONSTANT;
1131        break;
1132
1133    default:
1134
1135        /* Base validated above */
1136
1137        break;
1138    }
1139
1140    return (Status);
1141}
1142