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