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