aslutils.c revision 1.1.1.7 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 = ACPI_SIGN_NEGATIVE;
1012 ++String;
1013 }
1014 else if (*String == '+')
1015 {
1016 ++String;
1017 Sign = ACPI_SIGN_POSITIVE;
1018 }
1019 else
1020 {
1021 Sign = ACPI_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 == ACPI_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 }
1145