xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslutils.c (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1 /******************************************************************************
2  *
3  * Module Name: aslutils -- compiler utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acdisasm.h"
47 #include "acnamesp.h"
48 #include "amlcode.h"
49 #include "acapps.h"
50 #include <sys/stat.h>
51 
52 
53 #define _COMPONENT          ACPI_COMPILER
54         ACPI_MODULE_NAME    ("aslutils")
55 
56 
57 /* Local prototypes */
58 
59 static void
60 UtPadNameWithUnderscores (
61     char                    *NameSeg,
62     char                    *PaddedNameSeg);
63 
64 static void
65 UtAttachNameseg (
66     ACPI_PARSE_OBJECT       *Op,
67     char                    *Name);
68 
69 static void
70 UtDisplayErrorSummary (
71     UINT32                  FileId);
72 
73 
74 /*******************************************************************************
75  *
76  * FUNCTION:    UtIsBigEndianMachine
77  *
78  * PARAMETERS:  None
79  *
80  * RETURN:      TRUE if machine is big endian
81  *              FALSE if machine is little endian
82  *
83  * DESCRIPTION: Detect whether machine is little endian or big endian.
84  *
85  ******************************************************************************/
86 
87 UINT8
88 UtIsBigEndianMachine (
89     void)
90 {
91     union {
92         UINT32              Integer;
93         UINT8               Bytes[4];
94     } Overlay =                 {0xFF000000};
95 
96 
97     return (Overlay.Bytes[0]); /* Returns 0xFF (TRUE) for big endian */
98 }
99 
100 
101 /*******************************************************************************
102  *
103  * FUNCTION:    UtIsIdInteger
104  *
105  * PARAMETERS:  Pointer to an ACPI ID (HID, CID) string
106  *
107  * RETURN:      TRUE if string is an integer
108  *              FALSE if string is not an integer
109  *
110  * DESCRIPTION: Determine whether the input ACPI ID string can be converted to
111  *              an integer value.
112  *
113  ******************************************************************************/
114 
115 BOOLEAN
116 UtIsIdInteger (
117     UINT8                   *Target)
118 {
119     UINT32                  i;
120 
121 
122     /* The first three characters of the string must be alphabetic */
123 
124     for (i = 0; i < 3; i++)
125     {
126         if (!isalpha ((int) Target[i]))
127         {
128             break;
129         }
130     }
131 
132     if (i < 3)
133     {
134         return (TRUE);
135     }
136 
137     return (FALSE);
138 }
139 
140 
141 /******************************************************************************
142  *
143  * FUNCTION:    UtQueryForOverwrite
144  *
145  * PARAMETERS:  Pathname            - Output filename
146  *
147  * RETURN:      TRUE if file does not exist or overwrite is authorized
148  *
149  * DESCRIPTION: Query for file overwrite if it already exists.
150  *
151  ******************************************************************************/
152 
153 BOOLEAN
154 UtQueryForOverwrite (
155     char                    *Pathname)
156 {
157     struct stat             StatInfo;
158     int                     InChar;
159 
160 
161     if (!stat (Pathname, &StatInfo))
162     {
163         fprintf (stderr, "Target file \"%s\" already exists, overwrite? [y|n] ",
164             Pathname);
165 
166         InChar = fgetc (stdin);
167         if (InChar == '\n')
168         {
169             InChar = fgetc (stdin);
170         }
171 
172         if ((InChar != 'y') && (InChar != 'Y'))
173         {
174             return (FALSE);
175         }
176     }
177 
178     return (TRUE);
179 }
180 
181 
182 /*******************************************************************************
183  *
184  * FUNCTION:    UtNodeIsDescendantOf
185  *
186  * PARAMETERS:  Node1                   - Child node
187  *              Node2                   - Possible parent node
188  *
189  * RETURN:      Boolean
190  *
191  * DESCRIPTION: Returns TRUE if Node1 is a descendant of Node2. Otherwise,
192  *              return FALSE. Note, we assume a NULL Node2 element to be the
193  *              topmost (root) scope. All nodes are descendants of the root.
194  *              Note: Nodes at the same level (siblings) are not considered
195  *              descendants.
196  *
197  ******************************************************************************/
198 
199 BOOLEAN
200 UtNodeIsDescendantOf (
201     ACPI_NAMESPACE_NODE     *Node1,
202     ACPI_NAMESPACE_NODE     *Node2)
203 {
204 
205     if (Node1 == Node2)
206     {
207         return (FALSE);
208     }
209 
210     if (!Node2)
211     {
212         return (TRUE); /* All nodes descend from the root */
213     }
214 
215     /* Walk upward until the root is reached or parent is found */
216 
217     while (Node1)
218     {
219         if (Node1 == Node2)
220         {
221             return (TRUE);
222         }
223 
224         Node1 = Node1->Parent;
225     }
226 
227     return (FALSE);
228 }
229 
230 
231 /*******************************************************************************
232  *
233  * FUNCTION:    UtGetParentMethodNode
234  *
235  * PARAMETERS:  Node                    - Namespace node for any object
236  *
237  * RETURN:      Namespace node for the parent method
238  *              NULL - object is not within a method
239  *
240  * DESCRIPTION: Find the parent (owning) method node for a namespace object
241  *
242  ******************************************************************************/
243 
244 ACPI_NAMESPACE_NODE *
245 UtGetParentMethodNode (
246     ACPI_NAMESPACE_NODE     *Node)
247 {
248     ACPI_NAMESPACE_NODE     *ParentNode;
249 
250 
251     if (!Node)
252     {
253         return (NULL);
254     }
255 
256     /* Walk upward until a method is found, or the root is reached */
257 
258     ParentNode = Node->Parent;
259     while (ParentNode)
260     {
261         if (ParentNode->Type == ACPI_TYPE_METHOD)
262         {
263             return (ParentNode);
264         }
265 
266         ParentNode = ParentNode->Parent;
267     }
268 
269     return (NULL); /* Object is not within a control method */
270 }
271 
272 
273 /*******************************************************************************
274  *
275  * FUNCTION:    UtGetParentMethodOp
276  *
277  * PARAMETERS:  Op                      - Parse Op to be checked
278  *
279  * RETURN:      Control method Op if found. NULL otherwise
280  *
281  * DESCRIPTION: Find the control method parent of a parse op. Returns NULL if
282  *              the input Op is not within a control method.
283  *
284  ******************************************************************************/
285 
286 ACPI_PARSE_OBJECT *
287 UtGetParentMethodOp (
288     ACPI_PARSE_OBJECT       *Op)
289 {
290     ACPI_PARSE_OBJECT       *NextOp;
291 
292 
293     NextOp = Op->Asl.Parent;
294     while (NextOp)
295     {
296         if (NextOp->Asl.AmlOpcode == AML_METHOD_OP)
297         {
298             return (NextOp);
299         }
300 
301         NextOp = NextOp->Asl.Parent;
302     }
303 
304     return (NULL); /* No parent method found */
305 }
306 
307 
308 /*******************************************************************************
309  *
310  * FUNCTION:    UtDisplaySupportedTables
311  *
312  * PARAMETERS:  None
313  *
314  * RETURN:      None
315  *
316  * DESCRIPTION: Print all supported ACPI table names.
317  *
318  ******************************************************************************/
319 
320 void
321 UtDisplaySupportedTables (
322     void)
323 {
324     const AH_TABLE          *TableData;
325     UINT32                  i;
326 
327 
328     printf ("\nACPI tables supported by iASL version %8.8X:\n"
329         "  (Compiler, Disassembler, Template Generator)\n\n",
330         ACPI_CA_VERSION);
331 
332     /* All ACPI tables with the common table header */
333 
334     printf ("\n  Supported ACPI tables:\n");
335     for (TableData = AcpiGbl_SupportedTables, i = 1;
336          TableData->Signature; TableData++, i++)
337     {
338         printf ("%8u) %s    %s\n", i,
339             TableData->Signature, TableData->Description);
340     }
341 }
342 
343 
344 /*******************************************************************************
345  *
346  * FUNCTION:    UtDisplayConstantOpcodes
347  *
348  * PARAMETERS:  None
349  *
350  * RETURN:      None
351  *
352  * DESCRIPTION: Print AML opcodes that can be used in constant expressions.
353  *
354  ******************************************************************************/
355 
356 void
357 UtDisplayConstantOpcodes (
358     void)
359 {
360     UINT32                  i;
361 
362 
363     printf ("Constant expression opcode information\n\n");
364 
365     for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++)
366     {
367         if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT)
368         {
369             printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name);
370         }
371     }
372 }
373 
374 
375 /*******************************************************************************
376  *
377  * FUNCTION:    UtBeginEvent
378  *
379  * PARAMETERS:  Name                - Ascii name of this event
380  *
381  * RETURN:      Event number (integer index)
382  *
383  * DESCRIPTION: Saves the current time with this event
384  *
385  ******************************************************************************/
386 
387 UINT8
388 UtBeginEvent (
389     char                    *Name)
390 {
391 
392     if (AslGbl_NextEvent >= ASL_NUM_EVENTS)
393     {
394         AcpiOsPrintf ("Ran out of compiler event structs!\n");
395         return (AslGbl_NextEvent);
396     }
397 
398     /* Init event with current (start) time */
399 
400     AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer ();
401     AslGbl_Events[AslGbl_NextEvent].EventName = Name;
402     AslGbl_Events[AslGbl_NextEvent].Valid = TRUE;
403     return (AslGbl_NextEvent++);
404 }
405 
406 
407 /*******************************************************************************
408  *
409  * FUNCTION:    UtEndEvent
410  *
411  * PARAMETERS:  Event               - Event number (integer index)
412  *
413  * RETURN:      None
414  *
415  * DESCRIPTION: Saves the current time (end time) with this event
416  *
417  ******************************************************************************/
418 
419 void
420 UtEndEvent (
421     UINT8                   Event)
422 {
423 
424     if (Event >= ASL_NUM_EVENTS)
425     {
426         return;
427     }
428 
429     /* Insert end time for event */
430 
431     AslGbl_Events[Event].EndTime = AcpiOsGetTimer ();
432 }
433 
434 
435 /*******************************************************************************
436  *
437  * FUNCTION:    DbgPrint
438  *
439  * PARAMETERS:  Type                - Type of output
440  *              Fmt                 - Printf format string
441  *              ...                 - variable printf list
442  *
443  * RETURN:      None
444  *
445  * DESCRIPTION: Conditional print statement. Prints to stderr only if the
446  *              debug flag is set.
447  *
448  ******************************************************************************/
449 
450 void
451 DbgPrint (
452     UINT32                  Type,
453     char                    *Fmt,
454     ...)
455 {
456     va_list                 Args;
457 
458 
459     if (!AslGbl_DebugFlag)
460     {
461         return;
462     }
463 
464     if ((Type == ASL_PARSE_OUTPUT) &&
465         (!(AslCompilerdebug)))
466     {
467         return;
468     }
469 
470     va_start (Args, Fmt);
471     (void) vfprintf (stderr, Fmt, Args);
472     va_end (Args);
473     return;
474 }
475 
476 
477 /*******************************************************************************
478  *
479  * FUNCTION:    UtSetParseOpName
480  *
481  * PARAMETERS:  Op                  - Parse op to be named.
482  *
483  * RETURN:      None
484  *
485  * DESCRIPTION: Insert the ascii name of the parse opcode
486  *
487  ******************************************************************************/
488 
489 void
490 UtSetParseOpName (
491     ACPI_PARSE_OBJECT       *Op)
492 {
493 
494     AcpiUtSafeStrncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode),
495         ACPI_MAX_PARSEOP_NAME);
496 }
497 
498 
499 /*******************************************************************************
500  *
501  * FUNCTION:    UtDisplayOneSummary
502  *
503  * PARAMETERS:  FileID              - ID of outpout file
504  *
505  * RETURN:      None
506  *
507  * DESCRIPTION: Display compilation statistics for one input file
508  *
509  ******************************************************************************/
510 
511 void
512 UtDisplayOneSummary (
513     UINT32                  FileId,
514     BOOLEAN                 DisplayErrorSummary)
515 {
516     UINT32                  i;
517     ASL_GLOBAL_FILE_NODE    *FileNode;
518     BOOLEAN                 DisplayAMLSummary;
519 
520 
521     DisplayAMLSummary =
522         !AslGbl_PreprocessOnly && !AslGbl_ParserErrorDetected &&
523         ((AslGbl_ExceptionCount[ASL_ERROR] == 0) || AslGbl_IgnoreErrors) &&
524         AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle;
525 
526     if (FileId != ASL_FILE_STDOUT)
527     {
528         /* Compiler name and version number */
529 
530         FlPrintFile (FileId, "%s version %X [%s]\n\n",
531             ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, "2017-01-19");
532     }
533 
534     /* Summary of main input and output files */
535 
536     FileNode = FlGetCurrentFileNode ();
537 
538     if (FileNode->ParserErrorDetected)
539     {
540         FlPrintFile (FileId,
541             "%-14s %s - Compilation aborted due to parser-detected syntax error(s)\n",
542             "Input file:", AslGbl_Files[ASL_FILE_INPUT].Filename);
543     }
544     else if (FileNode->FileType == ASL_INPUT_TYPE_ASCII_DATA)
545     {
546         FlPrintFile (FileId,
547             "%-14s %s - %7u bytes %6u fields %8u source lines\n",
548             "Table Input:",
549             AslGbl_Files[ASL_FILE_INPUT].Filename,
550             FileNode->OriginalInputFileSize, FileNode->TotalFields,
551             FileNode->TotalLineCount);
552 
553         FlPrintFile (FileId,
554             "%-14s %s - %7u bytes\n",
555             "Binary Output:",
556             AslGbl_Files[ASL_FILE_AML_OUTPUT].Filename, FileNode->OutputByteLength);
557     }
558     else if (FileNode->FileType == ASL_INPUT_TYPE_ASCII_ASL)
559     {
560         FlPrintFile (FileId,
561             "%-14s %s - %7u bytes %6u keywords %6u source lines\n",
562             "ASL Input:",
563             AslGbl_Files[ASL_FILE_INPUT].Filename,
564             FileNode->OriginalInputFileSize,
565             FileNode->TotalKeywords,
566             FileNode->TotalLineCount);
567 
568         /* AML summary */
569 
570         if (DisplayAMLSummary)
571         {
572             FlPrintFile (FileId,
573                 "%-14s %s - %7u bytes %6u opcodes  %6u named objects\n",
574                 "AML Output:",
575                 AslGbl_Files[ASL_FILE_AML_OUTPUT].Filename,
576                 FlGetFileSize (ASL_FILE_AML_OUTPUT),
577                 FileNode->TotalExecutableOpcodes,
578                 FileNode->TotalNamedObjects);
579         }
580     }
581 
582     /* Display summary of any optional files */
583 
584     for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++)
585     {
586         if (!AslGbl_Files[i].Filename || !AslGbl_Files[i].Handle)
587         {
588             continue;
589         }
590 
591         /* .SRC is a temp file unless specifically requested */
592 
593         if ((i == ASL_FILE_SOURCE_OUTPUT) && (!AslGbl_SourceOutputFlag))
594         {
595             continue;
596         }
597 
598         /* .PRE is the preprocessor intermediate file */
599 
600         if ((i == ASL_FILE_PREPROCESSOR)  && (!AslGbl_KeepPreprocessorTempFile))
601         {
602             continue;
603         }
604 
605         FlPrintFile (FileId, "%-14s %s - %7u bytes\n",
606             AslGbl_FileDescs[i].ShortDescription,
607             AslGbl_Files[i].Filename, FlGetFileSize (i));
608     }
609 
610 
611     /*
612      * Optionally emit an error summary for a file. This is used to enhance the
613      * appearance of listing files.
614      */
615     if (DisplayErrorSummary)
616     {
617         UtDisplayErrorSummary (FileId);
618     }
619 }
620 
621 
622 /*******************************************************************************
623  *
624  * FUNCTION:    UtDisplayErrorSummary
625  *
626  * PARAMETERS:  FileID              - ID of outpout file
627  *
628  * RETURN:      None
629  *
630  * DESCRIPTION: Display compilation statistics for all input files
631  *
632  ******************************************************************************/
633 
634 static void
635 UtDisplayErrorSummary (
636     UINT32                  FileId)
637 {
638     BOOLEAN                 ErrorDetected;
639 
640 
641     ErrorDetected = AslGbl_ParserErrorDetected ||
642         ((AslGbl_ExceptionCount[ASL_ERROR] > 0) && !AslGbl_IgnoreErrors);
643 
644     if (ErrorDetected)
645     {
646         FlPrintFile (FileId, "\nCompilation failed. ");
647     }
648     else
649     {
650         FlPrintFile (FileId, "\nCompilation successful. ");
651     }
652 
653     FlPrintFile (FileId,
654         "%u Errors, %u Warnings, %u Remarks",
655         AslGbl_ExceptionCount[ASL_ERROR],
656         AslGbl_ExceptionCount[ASL_WARNING] +
657             AslGbl_ExceptionCount[ASL_WARNING2] +
658             AslGbl_ExceptionCount[ASL_WARNING3],
659         AslGbl_ExceptionCount[ASL_REMARK]);
660 
661     if (AslGbl_FileType != ASL_INPUT_TYPE_ASCII_DATA)
662     {
663         if (AslGbl_ParserErrorDetected)
664         {
665             FlPrintFile (FileId,
666                 "\nNo AML files were generated due to syntax error(s)\n");
667             return;
668         }
669         else if (ErrorDetected)
670         {
671             FlPrintFile (FileId,
672                 "\nNo AML files were generated due to compiler error(s)\n");
673             return;
674         }
675 
676         FlPrintFile (FileId, ", %u Optimizations",
677             AslGbl_ExceptionCount[ASL_OPTIMIZATION]);
678 
679         if (AslGbl_TotalFolds)
680         {
681             FlPrintFile (FileId, ", %u Constants Folded", AslGbl_TotalFolds);
682         }
683     }
684 
685     FlPrintFile (FileId, "\n");
686 }
687 
688 
689 /*******************************************************************************
690  *
691  * FUNCTION:    UtDisplaySummary
692  *
693  * PARAMETERS:  FileID              - ID of outpout file
694  *
695  * RETURN:      None
696  *
697  * DESCRIPTION: Display compilation statistics for all input files
698  *
699  ******************************************************************************/
700 
701 void
702 UtDisplaySummary (
703     UINT32                  FileId)
704 {
705     ASL_GLOBAL_FILE_NODE    *Current = AslGbl_FilesList;
706 
707 
708     while (Current)
709     {
710         switch  (FlSwitchFileSet(Current->Files[ASL_FILE_INPUT].Filename))
711         {
712             case SWITCH_TO_SAME_FILE:
713             case SWITCH_TO_DIFFERENT_FILE:
714 
715                 UtDisplayOneSummary (FileId, FALSE);
716                 Current = Current->Next;
717                 break;
718 
719             case FILE_NOT_FOUND:
720             default:
721 
722                 Current = NULL;
723                 break;
724         }
725     }
726     UtDisplayErrorSummary (FileId);
727 }
728 
729 /*******************************************************************************
730  *
731  * FUNCTION:    UtCheckIntegerRange
732  *
733  * PARAMETERS:  Op                  - Integer parse node
734  *              LowValue            - Smallest allowed value
735  *              HighValue           - Largest allowed value
736  *
737  * RETURN:      Op if OK, otherwise NULL
738  *
739  * DESCRIPTION: Check integer for an allowable range
740  *
741  ******************************************************************************/
742 
743 ACPI_PARSE_OBJECT *
744 UtCheckIntegerRange (
745     ACPI_PARSE_OBJECT       *Op,
746     UINT32                  LowValue,
747     UINT32                  HighValue)
748 {
749 
750     if (!Op)
751     {
752         return (NULL);
753     }
754 
755     if ((Op->Asl.Value.Integer < LowValue) ||
756         (Op->Asl.Value.Integer > HighValue))
757     {
758         snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "0x%X, allowable: 0x%X-0x%X",
759             (UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
760 
761         AslError (ASL_ERROR, ASL_MSG_RANGE, Op, AslGbl_MsgBuffer);
762         return (NULL);
763     }
764 
765     return (Op);
766 }
767 
768 
769 /*******************************************************************************
770  *
771  * FUNCTION:    UtInternalizeName
772  *
773  * PARAMETERS:  ExternalName        - Name to convert
774  *              ConvertedName       - Where the converted name is returned
775  *
776  * RETURN:      Status
777  *
778  * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name
779  *
780  ******************************************************************************/
781 
782 ACPI_STATUS
783 UtInternalizeName (
784     char                    *ExternalName,
785     char                    **ConvertedName)
786 {
787     ACPI_NAMESTRING_INFO    Info;
788     ACPI_STATUS             Status;
789 
790 
791     if (!ExternalName)
792     {
793         return (AE_OK);
794     }
795 
796     /* Get the length of the new internal name */
797 
798     Info.ExternalName = ExternalName;
799     AcpiNsGetInternalNameLength (&Info);
800 
801     /* We need a segment to store the internal name */
802 
803     Info.InternalName = UtLocalCacheCalloc (Info.Length);
804 
805     /* Build the name */
806 
807     Status = AcpiNsBuildInternalName (&Info);
808     if (ACPI_FAILURE (Status))
809     {
810         return (Status);
811     }
812 
813     *ConvertedName = Info.InternalName;
814     return (AE_OK);
815 }
816 
817 
818 /*******************************************************************************
819  *
820  * FUNCTION:    UtPadNameWithUnderscores
821  *
822  * PARAMETERS:  NameSeg             - Input nameseg
823  *              PaddedNameSeg       - Output padded nameseg
824  *
825  * RETURN:      Padded nameseg.
826  *
827  * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full
828  *              ACPI_NAME.
829  *
830  ******************************************************************************/
831 
832 static void
833 UtPadNameWithUnderscores (
834     char                    *NameSeg,
835     char                    *PaddedNameSeg)
836 {
837     UINT32                  i;
838 
839 
840     for (i = 0; (i < ACPI_NAMESEG_SIZE); i++)
841     {
842         if (*NameSeg)
843         {
844             *PaddedNameSeg = *NameSeg;
845             NameSeg++;
846         }
847         else
848         {
849             *PaddedNameSeg = '_';
850         }
851 
852         PaddedNameSeg++;
853     }
854 }
855 
856 
857 /*******************************************************************************
858  *
859  * FUNCTION:    UtAttachNameseg
860  *
861  * PARAMETERS:  Op                  - Parent parse node
862  *              Name                - Full ExternalName
863  *
864  * RETURN:      None; Sets the NameSeg field in parent node
865  *
866  * DESCRIPTION: Extract the last nameseg of the ExternalName and store it
867  *              in the NameSeg field of the Op.
868  *
869  ******************************************************************************/
870 
871 static void
872 UtAttachNameseg (
873     ACPI_PARSE_OBJECT       *Op,
874     char                    *Name)
875 {
876     char                    *NameSeg;
877     char                    PaddedNameSeg[4];
878 
879 
880     if (!Name)
881     {
882         return;
883     }
884 
885     /* Look for the last dot in the namepath */
886 
887     NameSeg = strrchr (Name, '.');
888     if (NameSeg)
889     {
890         /* Found last dot, we have also found the final nameseg */
891 
892         NameSeg++;
893         UtPadNameWithUnderscores (NameSeg, PaddedNameSeg);
894     }
895     else
896     {
897         /* No dots in the namepath, there is only a single nameseg. */
898         /* Handle prefixes */
899 
900         while (ACPI_IS_ROOT_PREFIX (*Name) ||
901                ACPI_IS_PARENT_PREFIX (*Name))
902         {
903             Name++;
904         }
905 
906         /* Remaining string should be one single nameseg */
907 
908         UtPadNameWithUnderscores (Name, PaddedNameSeg);
909     }
910 
911     ACPI_COPY_NAMESEG (Op->Asl.NameSeg, PaddedNameSeg);
912 }
913 
914 
915 /*******************************************************************************
916  *
917  * FUNCTION:    UtAttachNamepathToOwner
918  *
919  * PARAMETERS:  Op                  - Parent parse node
920  *              NameOp              - Node that contains the name
921  *
922  * RETURN:      Sets the ExternalName and Namepath in the parent node
923  *
924  * DESCRIPTION: Store the name in two forms in the parent node: The original
925  *              (external) name, and the internalized name that is used within
926  *              the ACPI namespace manager.
927  *
928  ******************************************************************************/
929 
930 void
931 UtAttachNamepathToOwner (
932     ACPI_PARSE_OBJECT       *Op,
933     ACPI_PARSE_OBJECT       *NameOp)
934 {
935     ACPI_STATUS             Status;
936 
937 
938     /* Full external path */
939 
940     Op->Asl.ExternalName = NameOp->Asl.Value.String;
941 
942     /* Save the NameOp for possible error reporting later */
943 
944     Op->Asl.ParentMethod = (void *) NameOp;
945 
946     /* Last nameseg of the path */
947 
948     UtAttachNameseg (Op, Op->Asl.ExternalName);
949 
950     /* Create internalized path */
951 
952     Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath);
953     if (ACPI_FAILURE (Status))
954     {
955         /* TBD: abort on no memory */
956     }
957 }
958 
959 
960 /*******************************************************************************
961  *
962  * FUNCTION:    UtNameContainsAllPrefix
963  *
964  * PARAMETERS:  Op                  - Op containing NameString
965  *
966  * RETURN:      NameString consists of all ^ characters
967  *
968  * DESCRIPTION: Determine if this Op contains a name segment that consists of
969  *              all '^' characters.
970  *
971  ******************************************************************************/
972 
973 BOOLEAN
974 UtNameContainsAllPrefix (
975     ACPI_PARSE_OBJECT       *Op)
976 {
977     UINT32                  Length = Op->Asl.AmlLength;
978     UINT32                  i;
979 
980     for (i = 0; i < Length; i++)
981     {
982         if (Op->Asl.Value.String[i] != '^')
983         {
984             return (FALSE);
985         }
986     }
987 
988     return (TRUE);
989 }
990 
991 /*******************************************************************************
992  *
993  * FUNCTION:    UtDoConstant
994  *
995  * PARAMETERS:  String              - Hex/Decimal/Octal
996  *
997  * RETURN:      Converted Integer
998  *
999  * DESCRIPTION: Convert a string to an integer, with overflow/error checking.
1000  *
1001  ******************************************************************************/
1002 
1003 UINT64
1004 UtDoConstant (
1005     char                    *String)
1006 {
1007     ACPI_STATUS             Status;
1008     UINT64                  ConvertedInteger;
1009     char                    ErrBuf[128];
1010     const ACPI_EXCEPTION_INFO *ExceptionInfo;
1011 
1012 
1013     Status = AcpiUtStrtoul64 (String, &ConvertedInteger);
1014     if (ACPI_FAILURE (Status))
1015     {
1016         ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status);
1017         snprintf (ErrBuf, sizeof(ErrBuf), " %s while converting to 64-bit integer",
1018             ExceptionInfo->Description);
1019 
1020         AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, AslGbl_CurrentLineNumber,
1021             AslGbl_LogicalLineNumber, AslGbl_CurrentLineOffset,
1022             AslGbl_CurrentColumn, AslGbl_Files[ASL_FILE_INPUT].Filename, ErrBuf);
1023     }
1024 
1025     return (ConvertedInteger);
1026 }
1027 
1028 
1029 /******************************************************************************
1030  *
1031  * FUNCTION:    AcpiUtStrdup
1032  *
1033  * PARAMETERS:  String1             - string to duplicate
1034  *
1035  * RETURN:      int that signifies string relationship. Zero means strings
1036  *              are equal.
1037  *
1038  * DESCRIPTION: Duplicate the string using UtCacheAlloc to avoid manual memory
1039  *              reclamation.
1040  *
1041  ******************************************************************************/
1042 
1043 char *
1044 AcpiUtStrdup (
1045     char                    *String)
1046 {
1047     char                    *NewString = (char *) UtLocalCalloc (strlen (String) + 1);
1048 
1049 
1050     strcpy (NewString, String);
1051     return (NewString);
1052 }
1053 
1054 
1055 /******************************************************************************
1056  *
1057  * FUNCTION:    AcpiUtStrcat
1058  *
1059  * PARAMETERS:  String1
1060  *              String2
1061  *
1062  * RETURN:      New string with String1 concatenated with String2
1063  *
1064  * DESCRIPTION: Concatenate string1 and string2
1065  *
1066  ******************************************************************************/
1067 
1068 char *
1069 AcpiUtStrcat (
1070     char                    *String1,
1071     char                    *String2)
1072 {
1073     UINT32                  String1Length = strlen (String1);
1074     char                    *NewString = (char *) UtLocalCalloc (strlen (String1) + strlen (String2) + 1);
1075 
1076     strcpy (NewString, String1);
1077     strcpy (NewString + String1Length, String2);
1078     return (NewString);
1079 }
1080