xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utstring.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*******************************************************************************
2  *
3  * Module Name: utstring - Common functions for strings and characters
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 
45 #define __UTSTRING_C__
46 
47 #include <contrib/dev/acpica/include/acpi.h>
48 #include <contrib/dev/acpica/include/accommon.h>
49 #include <contrib/dev/acpica/include/acnamesp.h>
50 
51 
52 #define _COMPONENT          ACPI_UTILITIES
53         ACPI_MODULE_NAME    ("utstring")
54 
55 
56 /*
57  * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit
58  * version of strtoul.
59  */
60 
61 #ifdef ACPI_ASL_COMPILER
62 /*******************************************************************************
63  *
64  * FUNCTION:    AcpiUtStrlwr (strlwr)
65  *
66  * PARAMETERS:  SrcString       - The source string to convert
67  *
68  * RETURN:      None
69  *
70  * DESCRIPTION: Convert string to lowercase
71  *
72  * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
73  *
74  ******************************************************************************/
75 
76 void
77 AcpiUtStrlwr (
78     char                    *SrcString)
79 {
80     char                    *String;
81 
82 
83     ACPI_FUNCTION_ENTRY ();
84 
85 
86     if (!SrcString)
87     {
88         return;
89     }
90 
91     /* Walk entire string, lowercasing the letters */
92 
93     for (String = SrcString; *String; String++)
94     {
95         *String = (char) ACPI_TOLOWER (*String);
96     }
97 
98     return;
99 }
100 
101 
102 /******************************************************************************
103  *
104  * FUNCTION:    AcpiUtStricmp (stricmp)
105  *
106  * PARAMETERS:  String1             - first string to compare
107  *              String2             - second string to compare
108  *
109  * RETURN:      int that signifies string relationship. Zero means strings
110  *              are equal.
111  *
112  * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
113  *              strings with no case sensitivity)
114  *
115  ******************************************************************************/
116 
117 int
118 AcpiUtStricmp (
119     char                    *String1,
120     char                    *String2)
121 {
122     int                     c1;
123     int                     c2;
124 
125 
126     do
127     {
128         c1 = tolower ((int) *String1);
129         c2 = tolower ((int) *String2);
130 
131         String1++;
132         String2++;
133     }
134     while ((c1 == c2) && (c1));
135 
136     return (c1 - c2);
137 }
138 #endif
139 
140 
141 /*******************************************************************************
142  *
143  * FUNCTION:    AcpiUtStrupr (strupr)
144  *
145  * PARAMETERS:  SrcString       - The source string to convert
146  *
147  * RETURN:      None
148  *
149  * DESCRIPTION: Convert string to uppercase
150  *
151  * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
152  *
153  ******************************************************************************/
154 
155 void
156 AcpiUtStrupr (
157     char                    *SrcString)
158 {
159     char                    *String;
160 
161 
162     ACPI_FUNCTION_ENTRY ();
163 
164 
165     if (!SrcString)
166     {
167         return;
168     }
169 
170     /* Walk entire string, uppercasing the letters */
171 
172     for (String = SrcString; *String; String++)
173     {
174         *String = (char) ACPI_TOUPPER (*String);
175     }
176 
177     return;
178 }
179 
180 
181 /*******************************************************************************
182  *
183  * FUNCTION:    AcpiUtStrtoul64
184  *
185  * PARAMETERS:  String          - Null terminated string
186  *              Base            - Radix of the string: 16 or ACPI_ANY_BASE;
187  *                                ACPI_ANY_BASE means 'in behalf of ToInteger'
188  *              RetInteger      - Where the converted integer is returned
189  *
190  * RETURN:      Status and Converted value
191  *
192  * DESCRIPTION: Convert a string into an unsigned value. Performs either a
193  *              32-bit or 64-bit conversion, depending on the current mode
194  *              of the interpreter.
195  *              NOTE: Does not support Octal strings, not needed.
196  *
197  ******************************************************************************/
198 
199 ACPI_STATUS
200 AcpiUtStrtoul64 (
201     char                    *String,
202     UINT32                  Base,
203     UINT64                  *RetInteger)
204 {
205     UINT32                  ThisDigit = 0;
206     UINT64                  ReturnValue = 0;
207     UINT64                  Quotient;
208     UINT64                  Dividend;
209     UINT32                  ToIntegerOp = (Base == ACPI_ANY_BASE);
210     UINT32                  Mode32 = (AcpiGbl_IntegerByteWidth == 4);
211     UINT8                   ValidDigits = 0;
212     UINT8                   SignOf0x = 0;
213     UINT8                   Term = 0;
214 
215 
216     ACPI_FUNCTION_TRACE_STR (UtStroul64, String);
217 
218 
219     switch (Base)
220     {
221     case ACPI_ANY_BASE:
222     case 16:
223 
224         break;
225 
226     default:
227 
228         /* Invalid Base */
229 
230         return_ACPI_STATUS (AE_BAD_PARAMETER);
231     }
232 
233     if (!String)
234     {
235         goto ErrorExit;
236     }
237 
238     /* Skip over any white space in the buffer */
239 
240     while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t'))
241     {
242         String++;
243     }
244 
245     if (ToIntegerOp)
246     {
247         /*
248          * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
249          * We need to determine if it is decimal or hexadecimal.
250          */
251         if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x'))
252         {
253             SignOf0x = 1;
254             Base = 16;
255 
256             /* Skip over the leading '0x' */
257             String += 2;
258         }
259         else
260         {
261             Base = 10;
262         }
263     }
264 
265     /* Any string left? Check that '0x' is not followed by white space. */
266 
267     if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t')
268     {
269         if (ToIntegerOp)
270         {
271             goto ErrorExit;
272         }
273         else
274         {
275             goto AllDone;
276         }
277     }
278 
279     /*
280      * Perform a 32-bit or 64-bit conversion, depending upon the current
281      * execution mode of the interpreter
282      */
283     Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
284 
285     /* Main loop: convert the string to a 32- or 64-bit integer */
286 
287     while (*String)
288     {
289         if (ACPI_IS_DIGIT (*String))
290         {
291             /* Convert ASCII 0-9 to Decimal value */
292 
293             ThisDigit = ((UINT8) *String) - '0';
294         }
295         else if (Base == 10)
296         {
297             /* Digit is out of range; possible in ToInteger case only */
298 
299             Term = 1;
300         }
301         else
302         {
303             ThisDigit = (UINT8) ACPI_TOUPPER (*String);
304             if (ACPI_IS_XDIGIT ((char) ThisDigit))
305             {
306                 /* Convert ASCII Hex char to value */
307 
308                 ThisDigit = ThisDigit - 'A' + 10;
309             }
310             else
311             {
312                 Term = 1;
313             }
314         }
315 
316         if (Term)
317         {
318             if (ToIntegerOp)
319             {
320                 goto ErrorExit;
321             }
322             else
323             {
324                 break;
325             }
326         }
327         else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x)
328         {
329             /* Skip zeros */
330             String++;
331             continue;
332         }
333 
334         ValidDigits++;
335 
336         if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32)))
337         {
338             /*
339              * This is ToInteger operation case.
340              * No any restrictions for string-to-integer conversion,
341              * see ACPI spec.
342              */
343             goto ErrorExit;
344         }
345 
346         /* Divide the digit into the correct position */
347 
348         (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit),
349                     Base, &Quotient, NULL);
350 
351         if (ReturnValue > Quotient)
352         {
353             if (ToIntegerOp)
354             {
355                 goto ErrorExit;
356             }
357             else
358             {
359                 break;
360             }
361         }
362 
363         ReturnValue *= Base;
364         ReturnValue += ThisDigit;
365         String++;
366     }
367 
368     /* All done, normal exit */
369 
370 AllDone:
371 
372     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
373         ACPI_FORMAT_UINT64 (ReturnValue)));
374 
375     *RetInteger = ReturnValue;
376     return_ACPI_STATUS (AE_OK);
377 
378 
379 ErrorExit:
380     /* Base was set/validated above */
381 
382     if (Base == 10)
383     {
384         return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
385     }
386     else
387     {
388         return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
389     }
390 }
391 
392 
393 /*******************************************************************************
394  *
395  * FUNCTION:    AcpiUtPrintString
396  *
397  * PARAMETERS:  String          - Null terminated ASCII string
398  *              MaxLength       - Maximum output length. Used to constrain the
399  *                                length of strings during debug output only.
400  *
401  * RETURN:      None
402  *
403  * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
404  *              sequences.
405  *
406  ******************************************************************************/
407 
408 void
409 AcpiUtPrintString (
410     char                    *String,
411     UINT16                  MaxLength)
412 {
413     UINT32                  i;
414 
415 
416     if (!String)
417     {
418         AcpiOsPrintf ("<\"NULL STRING PTR\">");
419         return;
420     }
421 
422     AcpiOsPrintf ("\"");
423     for (i = 0; String[i] && (i < MaxLength); i++)
424     {
425         /* Escape sequences */
426 
427         switch (String[i])
428         {
429         case 0x07:
430 
431             AcpiOsPrintf ("\\a");       /* BELL */
432             break;
433 
434         case 0x08:
435 
436             AcpiOsPrintf ("\\b");       /* BACKSPACE */
437             break;
438 
439         case 0x0C:
440 
441             AcpiOsPrintf ("\\f");       /* FORMFEED */
442             break;
443 
444         case 0x0A:
445 
446             AcpiOsPrintf ("\\n");       /* LINEFEED */
447             break;
448 
449         case 0x0D:
450 
451             AcpiOsPrintf ("\\r");       /* CARRIAGE RETURN*/
452             break;
453 
454         case 0x09:
455 
456             AcpiOsPrintf ("\\t");       /* HORIZONTAL TAB */
457             break;
458 
459         case 0x0B:
460 
461             AcpiOsPrintf ("\\v");       /* VERTICAL TAB */
462             break;
463 
464         case '\'':                      /* Single Quote */
465         case '\"':                      /* Double Quote */
466         case '\\':                      /* Backslash */
467 
468             AcpiOsPrintf ("\\%c", (int) String[i]);
469             break;
470 
471         default:
472 
473             /* Check for printable character or hex escape */
474 
475             if (ACPI_IS_PRINT (String[i]))
476             {
477                 /* This is a normal character */
478 
479                 AcpiOsPrintf ("%c", (int) String[i]);
480             }
481             else
482             {
483                 /* All others will be Hex escapes */
484 
485                 AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]);
486             }
487             break;
488         }
489     }
490     AcpiOsPrintf ("\"");
491 
492     if (i == MaxLength && String[i])
493     {
494         AcpiOsPrintf ("...");
495     }
496 }
497 
498 
499 /*******************************************************************************
500  *
501  * FUNCTION:    AcpiUtValidAcpiChar
502  *
503  * PARAMETERS:  Char            - The character to be examined
504  *              Position        - Byte position (0-3)
505  *
506  * RETURN:      TRUE if the character is valid, FALSE otherwise
507  *
508  * DESCRIPTION: Check for a valid ACPI character. Must be one of:
509  *              1) Upper case alpha
510  *              2) numeric
511  *              3) underscore
512  *
513  *              We allow a '!' as the last character because of the ASF! table
514  *
515  ******************************************************************************/
516 
517 BOOLEAN
518 AcpiUtValidAcpiChar (
519     char                    Character,
520     UINT32                  Position)
521 {
522 
523     if (!((Character >= 'A' && Character <= 'Z') ||
524           (Character >= '0' && Character <= '9') ||
525           (Character == '_')))
526     {
527         /* Allow a '!' in the last position */
528 
529         if (Character == '!' && Position == 3)
530         {
531             return (TRUE);
532         }
533 
534         return (FALSE);
535     }
536 
537     return (TRUE);
538 }
539 
540 
541 /*******************************************************************************
542  *
543  * FUNCTION:    AcpiUtValidAcpiName
544  *
545  * PARAMETERS:  Name            - The name to be examined. Does not have to
546  *                                be NULL terminated string.
547  *
548  * RETURN:      TRUE if the name is valid, FALSE otherwise
549  *
550  * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
551  *              1) Upper case alpha
552  *              2) numeric
553  *              3) underscore
554  *
555  ******************************************************************************/
556 
557 BOOLEAN
558 AcpiUtValidAcpiName (
559     char                    *Name)
560 {
561     UINT32                  i;
562 
563 
564     ACPI_FUNCTION_ENTRY ();
565 
566 
567     for (i = 0; i < ACPI_NAME_SIZE; i++)
568     {
569         if (!AcpiUtValidAcpiChar (Name[i], i))
570         {
571             return (FALSE);
572         }
573     }
574 
575     return (TRUE);
576 }
577 
578 
579 /*******************************************************************************
580  *
581  * FUNCTION:    AcpiUtRepairName
582  *
583  * PARAMETERS:  Name            - The ACPI name to be repaired
584  *
585  * RETURN:      Repaired version of the name
586  *
587  * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
588  *              return the new name. NOTE: the Name parameter must reside in
589  *              read/write memory, cannot be a const.
590  *
591  * An ACPI Name must consist of valid ACPI characters. We will repair the name
592  * if necessary because we don't want to abort because of this, but we want
593  * all namespace names to be printable. A warning message is appropriate.
594  *
595  * This issue came up because there are in fact machines that exhibit
596  * this problem, and we want to be able to enable ACPI support for them,
597  * even though there are a few bad names.
598  *
599  ******************************************************************************/
600 
601 void
602 AcpiUtRepairName (
603     char                    *Name)
604 {
605     UINT32                  i;
606     BOOLEAN                 FoundBadChar = FALSE;
607     UINT32                  OriginalName;
608 
609 
610     ACPI_FUNCTION_NAME (UtRepairName);
611 
612 
613     ACPI_MOVE_NAME (&OriginalName, Name);
614 
615     /* Check each character in the name */
616 
617     for (i = 0; i < ACPI_NAME_SIZE; i++)
618     {
619         if (AcpiUtValidAcpiChar (Name[i], i))
620         {
621             continue;
622         }
623 
624         /*
625          * Replace a bad character with something printable, yet technically
626          * still invalid. This prevents any collisions with existing "good"
627          * names in the namespace.
628          */
629         Name[i] = '*';
630         FoundBadChar = TRUE;
631     }
632 
633     if (FoundBadChar)
634     {
635         /* Report warning only if in strict mode or debug mode */
636 
637         if (!AcpiGbl_EnableInterpreterSlack)
638         {
639             ACPI_WARNING ((AE_INFO,
640                 "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
641                 OriginalName, Name));
642         }
643         else
644         {
645             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
646                 "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
647                 OriginalName, Name));
648         }
649     }
650 }
651 
652 
653 #if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
654 /*******************************************************************************
655  *
656  * FUNCTION:    UtConvertBackslashes
657  *
658  * PARAMETERS:  Pathname        - File pathname string to be converted
659  *
660  * RETURN:      Modifies the input Pathname
661  *
662  * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
663  *              the entire input file pathname string.
664  *
665  ******************************************************************************/
666 
667 void
668 UtConvertBackslashes (
669     char                    *Pathname)
670 {
671 
672     if (!Pathname)
673     {
674         return;
675     }
676 
677     while (*Pathname)
678     {
679         if (*Pathname == '\\')
680         {
681             *Pathname = '/';
682         }
683 
684         Pathname++;
685     }
686 }
687 #endif
688