:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / utils / cmclib.c
1 /******************************************************************************
2  *
3  * Module Name: cmclib - Local implementation of C library functions
4  * $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acevents.h"
29 #include "achware.h"
30 #include "acnamesp.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33
34 /*
35  * These implementations of standard C Library routines can optionally be
36  * used if a C library is not available.  In general, they are less efficient
37  * than an inline or assembly implementation
38  */
39
40 #define _COMPONENT          MISCELLANEOUS
41          MODULE_NAME         ("cmclib")
42
43
44 #ifndef ACPI_USE_SYSTEM_CLIBRARY
45
46 /*******************************************************************************
47  *
48  * FUNCTION:    strlen
49  *
50  * PARAMETERS:  String              - Null terminated string
51  *
52  * RETURN:      Length
53  *
54  * DESCRIPTION: Returns the length of the input string
55  *
56  ******************************************************************************/
57
58
59 u32
60 acpi_cm_strlen (
61         const NATIVE_CHAR       *string)
62 {
63         u32                     length = 0;
64
65
66         /* Count the string until a null is encountered */
67
68         while (*string) {
69                 length++;
70                 string++;
71         }
72
73         return (length);
74 }
75
76
77 /*******************************************************************************
78  *
79  * FUNCTION:    strcpy
80  *
81  * PARAMETERS:  Dst_string      - Target of the copy
82  *              Src_string      - The source string to copy
83  *
84  * RETURN:      Dst_string
85  *
86  * DESCRIPTION: Copy a null terminated string
87  *
88  ******************************************************************************/
89
90 NATIVE_CHAR *
91 acpi_cm_strcpy (
92         NATIVE_CHAR             *dst_string,
93         const NATIVE_CHAR       *src_string)
94 {
95         NATIVE_CHAR             *string = dst_string;
96
97
98         /* Move bytes brute force */
99
100         while (*src_string) {
101                 *string = *src_string;
102
103                 string++;
104                 src_string++;
105         }
106
107         /* Null terminate */
108
109         *string = 0;
110
111         return (dst_string);
112 }
113
114
115 /*******************************************************************************
116  *
117  * FUNCTION:    strncpy
118  *
119  * PARAMETERS:  Dst_string      - Target of the copy
120  *              Src_string      - The source string to copy
121  *              Count           - Maximum # of bytes to copy
122  *
123  * RETURN:      Dst_string
124  *
125  * DESCRIPTION: Copy a null terminated string, with a maximum length
126  *
127  ******************************************************************************/
128
129 NATIVE_CHAR *
130 acpi_cm_strncpy (
131         NATIVE_CHAR             *dst_string,
132         const NATIVE_CHAR       *src_string,
133         NATIVE_UINT             count)
134 {
135         NATIVE_CHAR             *string = dst_string;
136
137
138         /* Copy the string */
139
140         for (string = dst_string;
141                 count && (count--, (*string++ = *src_string++)); ) {;}
142
143         /* Pad with nulls if necessary */
144
145         while (count--) {
146                 *string = 0;
147                 string++;
148         }
149
150         /* Return original pointer */
151
152         return (dst_string);
153 }
154
155
156 /*******************************************************************************
157  *
158  * FUNCTION:    strcmp
159  *
160  * PARAMETERS:  String1         - First string
161  *              String2         - Second string
162  *
163  * RETURN:      Index where strings mismatched, or 0 if strings matched
164  *
165  * DESCRIPTION: Compare two null terminated strings
166  *
167  ******************************************************************************/
168
169 u32
170 acpi_cm_strcmp (
171         const NATIVE_CHAR       *string1,
172         const NATIVE_CHAR       *string2)
173 {
174
175
176         for ( ; (*string1 == *string2); string2++) {
177                 if (!*string1++) {
178                         return (0);
179                 }
180         }
181
182
183         return ((unsigned char) *string1 - (unsigned char) *string2);
184 }
185
186
187 /*******************************************************************************
188  *
189  * FUNCTION:    strncmp
190  *
191  * PARAMETERS:  String1         - First string
192  *              String2         - Second string
193  *              Count           - Maximum # of bytes to compare
194  *
195  * RETURN:      Index where strings mismatched, or 0 if strings matched
196  *
197  * DESCRIPTION: Compare two null terminated strings, with a maximum length
198  *
199  ******************************************************************************/
200
201 u32
202 acpi_cm_strncmp (
203         const NATIVE_CHAR       *string1,
204         const NATIVE_CHAR       *string2,
205         NATIVE_UINT             count)
206 {
207
208
209         for ( ; count-- && (*string1 == *string2); string2++) {
210                 if (!*string1++) {
211                         return (0);
212                 }
213         }
214
215         return ((count == -1) ? 0 : ((unsigned char) *string1 -
216                 (unsigned char) *string2));
217 }
218
219
220 /*******************************************************************************
221  *
222  * FUNCTION:    Strcat
223  *
224  * PARAMETERS:  Dst_string      - Target of the copy
225  *              Src_string      - The source string to copy
226  *
227  * RETURN:      Dst_string
228  *
229  * DESCRIPTION: Append a null terminated string to a null terminated string
230  *
231  ******************************************************************************/
232
233 NATIVE_CHAR *
234 acpi_cm_strcat (
235         NATIVE_CHAR             *dst_string,
236         const NATIVE_CHAR       *src_string)
237 {
238         NATIVE_CHAR             *string;
239
240
241         /* Find end of the destination string */
242
243         for (string = dst_string; *string++; ) { ; }
244
245         /* Concatinate the string */
246
247         for (--string; (*string++ = *src_string++); ) { ; }
248
249         return (dst_string);
250 }
251
252
253 /*******************************************************************************
254  *
255  * FUNCTION:    strncat
256  *
257  * PARAMETERS:  Dst_string      - Target of the copy
258  *              Src_string      - The source string to copy
259  *              Count           - Maximum # of bytes to copy
260  *
261  * RETURN:      Dst_string
262  *
263  * DESCRIPTION: Append a null terminated string to a null terminated string,
264  *              with a maximum count.
265  *
266  ******************************************************************************/
267
268 NATIVE_CHAR *
269 acpi_cm_strncat (
270         NATIVE_CHAR             *dst_string,
271         const NATIVE_CHAR       *src_string,
272         NATIVE_UINT             count)
273 {
274         NATIVE_CHAR             *string;
275
276
277         if (count) {
278                 /* Find end of the destination string */
279
280                 for (string = dst_string; *string++; ) { ; }
281
282                 /* Concatinate the string */
283
284                 for (--string; (*string++ = *src_string++) && --count; ) { ; }
285
286                 /* Null terminate if necessary */
287
288                 if (!count) {
289                         *string = 0;
290                 }
291         }
292
293         return (dst_string);
294 }
295
296
297 /*******************************************************************************
298  *
299  * FUNCTION:    memcpy
300  *
301  * PARAMETERS:  Dest        - Target of the copy
302  *              Src         - Source buffer to copy
303  *              Count       - Number of bytes to copy
304  *
305  * RETURN:      Dest
306  *
307  * DESCRIPTION: Copy arbitrary bytes of memory
308  *
309  ******************************************************************************/
310
311 void *
312 acpi_cm_memcpy (
313         void                    *dest,
314         const void              *src,
315         NATIVE_UINT             count)
316 {
317         NATIVE_CHAR             *new = (NATIVE_CHAR *) dest;
318         NATIVE_CHAR             *old = (NATIVE_CHAR *) src;
319
320
321         while (count) {
322                 *new = *old;
323                 new++;
324                 old++;
325                 count--;
326         }
327
328         return (dest);
329 }
330
331
332 /*******************************************************************************
333  *
334  * FUNCTION:    memset
335  *
336  * PARAMETERS:  Dest        - Buffer to set
337  *              Value       - Value to set each byte of memory
338  *              Count       - Number of bytes to set
339  *
340  * RETURN:      Dest
341  *
342  * DESCRIPTION: Initialize a buffer to a known value.
343  *
344  ******************************************************************************/
345
346 void *
347 acpi_cm_memset (
348         void                    *dest,
349         NATIVE_UINT             value,
350         NATIVE_UINT             count)
351 {
352         NATIVE_CHAR             *new = (NATIVE_CHAR *) dest;
353
354
355         while (count) {
356                 *new = (char) value;
357                 new++;
358                 count--;
359         }
360
361         return (dest);
362 }
363
364
365 #define NEGATIVE    1
366 #define POSITIVE    0
367
368
369 #define _ACPI_XA     0x00    /* extra alphabetic - not supported */
370 #define _ACPI_XS     0x40    /* extra space */
371 #define _ACPI_BB     0x00    /* BEL, BS, etc. - not supported */
372 #define _ACPI_CN     0x20    /* CR, FF, HT, NL, VT */
373 #define _ACPI_DI     0x04    /* '0'-'9' */
374 #define _ACPI_LO     0x02    /* 'a'-'z' */
375 #define _ACPI_PU     0x10    /* punctuation */
376 #define _ACPI_SP     0x08    /* space */
377 #define _ACPI_UP     0x01    /* 'A'-'Z' */
378 #define _ACPI_XD     0x80    /* '0'-'9', 'A'-'F', 'a'-'f' */
379
380 static const u8 _acpi_ctype[257] = {
381         _ACPI_CN,            /* 0x0      0.     */
382         _ACPI_CN,            /* 0x1      1.     */
383         _ACPI_CN,            /* 0x2      2.     */
384         _ACPI_CN,            /* 0x3      3.     */
385         _ACPI_CN,            /* 0x4      4.     */
386         _ACPI_CN,            /* 0x5      5.     */
387         _ACPI_CN,            /* 0x6      6.     */
388         _ACPI_CN,            /* 0x7      7.     */
389         _ACPI_CN,            /* 0x8      8.     */
390         _ACPI_CN|_ACPI_SP,   /* 0x9      9.     */
391         _ACPI_CN|_ACPI_SP,   /* 0xA     10.     */
392         _ACPI_CN|_ACPI_SP,   /* 0xB     11.     */
393         _ACPI_CN|_ACPI_SP,   /* 0xC     12.     */
394         _ACPI_CN|_ACPI_SP,   /* 0xD     13.     */
395         _ACPI_CN,            /* 0xE     14.     */
396         _ACPI_CN,            /* 0xF     15.     */
397         _ACPI_CN,            /* 0x10    16.     */
398         _ACPI_CN,            /* 0x11    17.     */
399         _ACPI_CN,            /* 0x12    18.     */
400         _ACPI_CN,            /* 0x13    19.     */
401         _ACPI_CN,            /* 0x14    20.     */
402         _ACPI_CN,            /* 0x15    21.     */
403         _ACPI_CN,            /* 0x16    22.     */
404         _ACPI_CN,            /* 0x17    23.     */
405         _ACPI_CN,            /* 0x18    24.     */
406         _ACPI_CN,            /* 0x19    25.     */
407         _ACPI_CN,            /* 0x1A    26.     */
408         _ACPI_CN,            /* 0x1B    27.     */
409         _ACPI_CN,            /* 0x1C    28.     */
410         _ACPI_CN,            /* 0x1D    29.     */
411         _ACPI_CN,            /* 0x1E    30.     */
412         _ACPI_CN,            /* 0x1F    31.     */
413         _ACPI_XS|_ACPI_SP,   /* 0x20    32. ' ' */
414         _ACPI_PU,            /* 0x21    33. '!' */
415         _ACPI_PU,            /* 0x22    34. '"' */
416         _ACPI_PU,            /* 0x23    35. '#' */
417         _ACPI_PU,            /* 0x24    36. '$' */
418         _ACPI_PU,            /* 0x25    37. '%' */
419         _ACPI_PU,            /* 0x26    38. '&' */
420         _ACPI_PU,            /* 0x27    39. ''' */
421         _ACPI_PU,            /* 0x28    40. '(' */
422         _ACPI_PU,            /* 0x29    41. ')' */
423         _ACPI_PU,            /* 0x2A    42. '*' */
424         _ACPI_PU,            /* 0x2B    43. '+' */
425         _ACPI_PU,            /* 0x2C    44. ',' */
426         _ACPI_PU,            /* 0x2D    45. '-' */
427         _ACPI_PU,            /* 0x2E    46. '.' */
428         _ACPI_PU,            /* 0x2F    47. '/' */
429         _ACPI_XD|_ACPI_DI,   /* 0x30    48. '0' */
430         _ACPI_XD|_ACPI_DI,   /* 0x31    49. '1' */
431         _ACPI_XD|_ACPI_DI,   /* 0x32    50. '2' */
432         _ACPI_XD|_ACPI_DI,   /* 0x33    51. '3' */
433         _ACPI_XD|_ACPI_DI,   /* 0x34    52. '4' */
434         _ACPI_XD|_ACPI_DI,   /* 0x35    53. '5' */
435         _ACPI_XD|_ACPI_DI,   /* 0x36    54. '6' */
436         _ACPI_XD|_ACPI_DI,   /* 0x37    55. '7' */
437         _ACPI_XD|_ACPI_DI,   /* 0x38    56. '8' */
438         _ACPI_XD|_ACPI_DI,   /* 0x39    57. '9' */
439         _ACPI_PU,            /* 0x3A    58. ':' */
440         _ACPI_PU,            /* 0x3B    59. ';' */
441         _ACPI_PU,            /* 0x3C    60. '<' */
442         _ACPI_PU,            /* 0x3D    61. '=' */
443         _ACPI_PU,            /* 0x3E    62. '>' */
444         _ACPI_PU,            /* 0x3F    63. '?' */
445         _ACPI_PU,            /* 0x40    64. '@' */
446         _ACPI_XD|_ACPI_UP,   /* 0x41    65. 'A' */
447         _ACPI_XD|_ACPI_UP,   /* 0x42    66. 'B' */
448         _ACPI_XD|_ACPI_UP,   /* 0x43    67. 'C' */
449         _ACPI_XD|_ACPI_UP,   /* 0x44    68. 'D' */
450         _ACPI_XD|_ACPI_UP,   /* 0x45    69. 'E' */
451         _ACPI_XD|_ACPI_UP,   /* 0x46    70. 'F' */
452         _ACPI_UP,            /* 0x47    71. 'G' */
453         _ACPI_UP,            /* 0x48    72. 'H' */
454         _ACPI_UP,            /* 0x49    73. 'I' */
455         _ACPI_UP,            /* 0x4A    74. 'J' */
456         _ACPI_UP,            /* 0x4B    75. 'K' */
457         _ACPI_UP,            /* 0x4C    76. 'L' */
458         _ACPI_UP,            /* 0x4D    77. 'M' */
459         _ACPI_UP,            /* 0x4E    78. 'N' */
460         _ACPI_UP,            /* 0x4F    79. 'O' */
461         _ACPI_UP,            /* 0x50    80. 'P' */
462         _ACPI_UP,            /* 0x51    81. 'Q' */
463         _ACPI_UP,            /* 0x52    82. 'R' */
464         _ACPI_UP,            /* 0x53    83. 'S' */
465         _ACPI_UP,            /* 0x54    84. 'T' */
466         _ACPI_UP,            /* 0x55    85. 'U' */
467         _ACPI_UP,            /* 0x56    86. 'V' */
468         _ACPI_UP,            /* 0x57    87. 'W' */
469         _ACPI_UP,            /* 0x58    88. 'X' */
470         _ACPI_UP,            /* 0x59    89. 'Y' */
471         _ACPI_UP,            /* 0x5A    90. 'Z' */
472         _ACPI_PU,            /* 0x5B    91. '[' */
473         _ACPI_PU,            /* 0x5C    92. '\' */
474         _ACPI_PU,            /* 0x5D    93. ']' */
475         _ACPI_PU,            /* 0x5E    94. '^' */
476         _ACPI_PU,            /* 0x5F    95. '_' */
477         _ACPI_PU,            /* 0x60    96. '`' */
478         _ACPI_XD|_ACPI_LO,   /* 0x61    97. 'a' */
479         _ACPI_XD|_ACPI_LO,   /* 0x62    98. 'b' */
480         _ACPI_XD|_ACPI_LO,   /* 0x63    99. 'c' */
481         _ACPI_XD|_ACPI_LO,   /* 0x64   100. 'd' */
482         _ACPI_XD|_ACPI_LO,   /* 0x65   101. 'e' */
483         _ACPI_XD|_ACPI_LO,   /* 0x66   102. 'f' */
484         _ACPI_LO,            /* 0x67   103. 'g' */
485         _ACPI_LO,            /* 0x68   104. 'h' */
486         _ACPI_LO,            /* 0x69   105. 'i' */
487         _ACPI_LO,            /* 0x6A   106. 'j' */
488         _ACPI_LO,            /* 0x6B   107. 'k' */
489         _ACPI_LO,            /* 0x6C   108. 'l' */
490         _ACPI_LO,            /* 0x6D   109. 'm' */
491         _ACPI_LO,            /* 0x6E   110. 'n' */
492         _ACPI_LO,            /* 0x6F   111. 'o' */
493         _ACPI_LO,            /* 0x70   112. 'p' */
494         _ACPI_LO,            /* 0x71   113. 'q' */
495         _ACPI_LO,            /* 0x72   114. 'r' */
496         _ACPI_LO,            /* 0x73   115. 's' */
497         _ACPI_LO,            /* 0x74   116. 't' */
498         _ACPI_LO,            /* 0x75   117. 'u' */
499         _ACPI_LO,            /* 0x76   118. 'v' */
500         _ACPI_LO,            /* 0x77   119. 'w' */
501         _ACPI_LO,            /* 0x78   120. 'x' */
502         _ACPI_LO,            /* 0x79   121. 'y' */
503         _ACPI_LO,            /* 0x7A   122. 'z' */
504         _ACPI_PU,            /* 0x7B   123. '{' */
505         _ACPI_PU,            /* 0x7C   124. '|' */
506         _ACPI_PU,            /* 0x7D   125. '}' */
507         _ACPI_PU,            /* 0x7E   126. '~' */
508         _ACPI_CN,            /* 0x7F   127.     */
509
510         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0x80 to 0x8F    */
511         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0x90 to 0x9F    */
512         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xA0 to 0xAF    */
513         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xB0 to 0xBF    */
514         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xC0 to 0xCF    */
515         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xD0 to 0xDF    */
516         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xE0 to 0xEF    */
517         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100   */
518 };
519
520 #define IS_UPPER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP))
521 #define IS_LOWER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
522 #define IS_DIGIT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI))
523 #define IS_SPACE(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP))
524 #define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
525
526
527 /*******************************************************************************
528  *
529  * FUNCTION:    Acpi_cm_to_upper
530  *
531  * PARAMETERS:
532  *
533  * RETURN:
534  *
535  * DESCRIPTION: Convert character to uppercase
536  *
537  ******************************************************************************/
538
539 u32
540 acpi_cm_to_upper (
541         u32                     c)
542 {
543
544         return (IS_LOWER(c) ? ((c)-0x20) : (c));
545 }
546
547
548 /*******************************************************************************
549  *
550  * FUNCTION:    Acpi_cm_to_lower
551  *
552  * PARAMETERS:
553  *
554  * RETURN:
555  *
556  * DESCRIPTION: Convert character to lowercase
557  *
558  ******************************************************************************/
559
560 u32
561 acpi_cm_to_lower (
562         u32                     c)
563 {
564
565         return (IS_UPPER(c) ? ((c)+0x20) : (c));
566 }
567
568
569 /*******************************************************************************
570  *
571  * FUNCTION:    strupr
572  *
573  * PARAMETERS:  Src_string      - The source string to convert to
574  *
575  * RETURN:      Src_string
576  *
577  * DESCRIPTION: Convert string to uppercase
578  *
579  ******************************************************************************/
580
581 NATIVE_CHAR *
582 acpi_cm_strupr (
583         NATIVE_CHAR             *src_string)
584 {
585         NATIVE_CHAR             *string;
586
587
588         /* Walk entire string, uppercasing the letters */
589
590         for (string = src_string; *string; ) {
591                 *string = (char) acpi_cm_to_upper (*string);
592                 string++;
593         }
594
595
596         return (src_string);
597 }
598
599
600 /*******************************************************************************
601  *
602  * FUNCTION:    strstr
603  *
604  * PARAMETERS:  String1       -
605  *              String2
606  *
607  * RETURN:
608  *
609  * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
610  *              full implementation of strstr, only sufficient for command
611  *              matching
612  *
613  ******************************************************************************/
614
615 NATIVE_CHAR *
616 acpi_cm_strstr (
617         NATIVE_CHAR             *string1,
618         NATIVE_CHAR             *string2)
619 {
620         NATIVE_CHAR             *string;
621
622
623         if (acpi_cm_strlen (string2) > acpi_cm_strlen (string1)) {
624                 return (NULL);
625         }
626
627         /* Walk entire string, comparing the letters */
628
629         for (string = string1; *string2; ) {
630                 if (*string2 != *string) {
631                         return (NULL);
632                 }
633
634                 string2++;
635                 string++;
636         }
637
638
639         return (string1);
640 }
641
642
643 /*******************************************************************************
644  *
645  * FUNCTION:    strtoul
646  *
647  * PARAMETERS:  String          - Null terminated string
648  *              Terminater      - Where a pointer to the terminating byte is returned
649  *              Base            - Radix of the string
650  *
651  * RETURN:      Converted value
652  *
653  * DESCRIPTION: Convert a string into an unsigned value.
654  *
655  ******************************************************************************/
656
657 NATIVE_UINT
658 acpi_cm_strtoul (
659         const NATIVE_CHAR       *string,
660         NATIVE_CHAR             **terminator,
661         NATIVE_UINT             base)
662 {
663         u32                     converted = 0;
664         u32                     index;
665         u32                     sign;
666         const NATIVE_CHAR       *string_start;
667         NATIVE_UINT             return_value = 0;
668         ACPI_STATUS             status = AE_OK;
669
670
671         /*
672          * Save the value of the pointer to the buffer's first
673          * character, save the current errno value, and then
674          * skip over any white space in the buffer:
675          */
676         string_start = string;
677         while (IS_SPACE (*string) || *string == '\t') {
678                 ++string;
679         }
680
681         /*
682          * The buffer may contain an optional plus or minus sign.
683          * If it does, then skip over it but remember what is was:
684          */
685         if (*string == '-') {
686                 sign = NEGATIVE;
687                 ++string;
688         }
689
690         else if (*string == '+') {
691                 ++string;
692                 sign = POSITIVE;
693         }
694
695         else {
696                 sign = POSITIVE;
697         }
698
699         /*
700          * If the input parameter Base is zero, then we need to
701          * determine if it is octal, decimal, or hexadecimal:
702          */
703         if (base == 0) {
704                 if (*string == '0') {
705                         if (acpi_cm_to_lower (*(++string)) == 'x') {
706                                 base = 16;
707                                 ++string;
708                         }
709
710                         else {
711                                 base = 8;
712                         }
713                 }
714
715                 else {
716                         base = 10;
717                 }
718         }
719
720         else if (base < 2 || base > 36) {
721                 /*
722                  * The specified Base parameter is not in the domain of
723                  * this function:
724                  */
725                 goto done;
726         }
727
728         /*
729          * For octal and hexadecimal bases, skip over the leading
730          * 0 or 0x, if they are present.
731          */
732         if (base == 8 && *string == '0') {
733                 string++;
734         }
735
736         if (base == 16 &&
737                 *string == '0' &&
738                 acpi_cm_to_lower (*(++string)) == 'x') {
739                 string++;
740         }
741
742
743         /*
744          * Main loop: convert the string to an unsigned long:
745          */
746         while (*string) {
747                 if (IS_DIGIT (*string)) {
748                         index = *string - '0';
749                 }
750
751                 else {
752                         index = acpi_cm_to_upper (*string);
753                         if (IS_UPPER (index)) {
754                                 index = index - 'A' + 10;
755                         }
756
757                         else {
758                                 goto done;
759                         }
760                 }
761
762                 if (index >= base) {
763                         goto done;
764                 }
765
766                 /*
767                  * Check to see if value is out of range:
768                  */
769
770                 if (return_value > ((ACPI_UINT32_MAX - (u32) index) /
771                                    (u32) base)) {
772                         status = AE_ERROR;
773                         return_value = 0L;          /* reset */
774                 }
775
776                 else {
777                         return_value *= base;
778                         return_value += index;
779                         converted = 1;
780                 }
781
782                 ++string;
783         }
784
785 done:
786         /*
787          * If appropriate, update the caller's pointer to the next
788          * unconverted character in the buffer.
789          */
790         if (terminator) {
791                 if (converted == 0 && return_value == 0L && string != NULL) {
792                         *terminator = (NATIVE_CHAR *) string_start;
793                 }
794
795                 else {
796                         *terminator = (NATIVE_CHAR *) string;
797                 }
798         }
799
800         if (status == AE_ERROR) {
801                 return_value = ACPI_UINT32_MAX;
802         }
803
804         /*
805          * If a minus sign was present, then "the conversion is negated":
806          */
807         if (sign == NEGATIVE) {
808                 return_value = (ACPI_UINT32_MAX - return_value) + 1;
809         }
810
811         return (return_value);
812 }
813
814 #endif /* ACPI_USE_SYSTEM_CLIBRARY */
815