1 /******************************************************************************
   2  *
   3  * Module Name: prexpress - Preprocessor #if expression support
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 "dtcompiler.h"
  46 
  47 
  48 #define _COMPONENT          ASL_PREPROCESSOR
  49         ACPI_MODULE_NAME    ("prexpress")
  50 
  51 /* Local prototypes */
  52 
  53 static char *
  54 PrExpandMacros (
  55     char                    *Line);
  56 
  57 
  58 #ifdef _UNDER_DEVELOPMENT
  59 /******************************************************************************
  60  *
  61  * FUNCTION:    PrUnTokenize
  62  *
  63  * PARAMETERS:  Buffer              - Token Buffer
  64  *              Next                - "Next" buffer from GetNextToken
  65  *
  66  * RETURN:      None
  67  *
  68  * DESCRIPTION: Un-tokenized the current token buffer. The implementation is
  69  *              to simply set the null inserted by GetNextToken to a blank.
  70  *              If Next is NULL, there were no tokens found in the Buffer,
  71  *              so there is nothing to do.
  72  *
  73  *****************************************************************************/
  74 
  75 static void
  76 PrUnTokenize (
  77     char                    *Buffer,
  78     char                    *Next)
  79 {
  80     UINT32                  Length = strlen (Buffer);
  81 
  82 
  83     if (!Next)
  84     {
  85         return;
  86     }
  87     if (Buffer[Length] != '\n')
  88     {
  89         Buffer[strlen(Buffer)] = ' ';
  90     }
  91 }
  92 #endif
  93 
  94 
  95 /******************************************************************************
  96  *
  97  * FUNCTION:    PrExpandMacros
  98  *
  99  * PARAMETERS:  Line                - Pointer into the current line
 100  *
 101  * RETURN:      Updated pointer into the current line
 102  *
 103  * DESCRIPTION: Expand any macros found in the current line buffer.
 104  *
 105  *****************************************************************************/
 106 
 107 static char *
 108 PrExpandMacros (
 109     char                    *Line)
 110 {
 111     char                    *Token;
 112     char                    *ReplaceString;
 113     PR_DEFINE_INFO          *DefineInfo;
 114     ACPI_SIZE               TokenOffset;
 115     char                    *Next;
 116     int                     OffsetAdjust;
 117 
 118 
 119     strcpy (Gbl_ExpressionTokenBuffer, Gbl_CurrentLineBuffer);
 120     Token = PrGetNextToken (Gbl_ExpressionTokenBuffer, PR_EXPR_SEPARATORS, &Next);
 121     OffsetAdjust = 0;
 122 
 123     while (Token)
 124     {
 125         DefineInfo = PrMatchDefine (Token);
 126         if (DefineInfo)
 127         {
 128             if (DefineInfo->Body)
 129             {
 130                 /* This is a macro. TBD: Is this allowed? */
 131 
 132                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 133                     "Matched Macro: %s->%s\n",
 134                     Gbl_CurrentLineNumber, DefineInfo->Identifier,
 135                     DefineInfo->Replacement);
 136 
 137                 PrDoMacroInvocation (Gbl_ExpressionTokenBuffer, Token,
 138                     DefineInfo, &Next);
 139             }
 140             else
 141             {
 142                 ReplaceString = DefineInfo->Replacement;
 143 
 144                 /* Replace the name in the original line buffer */
 145 
 146                 TokenOffset = Token - Gbl_ExpressionTokenBuffer + OffsetAdjust;
 147                 PrReplaceData (
 148                     &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
 149                     ReplaceString, strlen (ReplaceString));
 150 
 151                 /* Adjust for length difference between old and new name length */
 152 
 153                 OffsetAdjust += strlen (ReplaceString) - strlen (Token);
 154 
 155                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 156                     "Matched #define within expression: %s->%s\n",
 157                     Gbl_CurrentLineNumber, Token,
 158                     *ReplaceString ? ReplaceString : "(NULL STRING)");
 159             }
 160         }
 161 
 162         Token = PrGetNextToken (NULL, PR_EXPR_SEPARATORS, &Next);
 163     }
 164 
 165     return (Line);
 166 }
 167 
 168 
 169 /******************************************************************************
 170  *
 171  * FUNCTION:    PrIsDefined
 172  *
 173  * PARAMETERS:  Identifier          - Name to be resolved
 174  *
 175  * RETURN:      64-bit boolean integer value
 176  *
 177  * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
 178  *
 179  *****************************************************************************/
 180 
 181 UINT64
 182 PrIsDefined (
 183     char                    *Identifier)
 184 {
 185     UINT64                  Value;
 186     PR_DEFINE_INFO          *DefineInfo;
 187 
 188 
 189     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 190         "**** Is defined?:  %s\n", Gbl_CurrentLineNumber, Identifier);
 191 
 192     Value = 0; /* Default is "Not defined" -- FALSE */
 193 
 194     DefineInfo = PrMatchDefine (Identifier);
 195     if (DefineInfo)
 196     {
 197         Value = ACPI_UINT64_MAX; /* TRUE */
 198     }
 199 
 200     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 201         "[#if defined %s] resolved to: %8.8X%8.8X\n",
 202         Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
 203 
 204     return (Value);
 205 }
 206 
 207 
 208 /******************************************************************************
 209  *
 210  * FUNCTION:    PrResolveDefine
 211  *
 212  * PARAMETERS:  Identifier          - Name to be resolved
 213  *
 214  * RETURN:      A 64-bit boolean integer value
 215  *
 216  * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
 217  *
 218  *****************************************************************************/
 219 
 220 UINT64
 221 PrResolveDefine (
 222     char                    *Identifier)
 223 {
 224     UINT64                  Value;
 225     PR_DEFINE_INFO          *DefineInfo;
 226 
 227 
 228     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 229         "**** Resolve #define:  %s\n", Gbl_CurrentLineNumber, Identifier);
 230 
 231     Value = 0; /* Default is "Not defined" -- FALSE */
 232 
 233     DefineInfo = PrMatchDefine (Identifier);
 234     if (DefineInfo)
 235     {
 236         Value = ACPI_UINT64_MAX; /* TRUE */
 237     }
 238 
 239     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 240         "[#if defined %s] resolved to: %8.8X%8.8X\n",
 241         Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
 242 
 243     return (Value);
 244 }
 245 
 246 
 247 /******************************************************************************
 248  *
 249  * FUNCTION:    PrResolveIntegerExpression
 250  *
 251  * PARAMETERS:  Line                - Pointer to integer expression
 252  *              ReturnValue         - Where the resolved 64-bit integer is
 253  *                                    returned.
 254  *
 255  * RETURN:      Status
 256  *
 257  * DESCRIPTION: Resolve an integer expression to a single value. Supports
 258  *              both integer constants and labels.
 259  *
 260  *****************************************************************************/
 261 
 262 ACPI_STATUS
 263 PrResolveIntegerExpression (
 264     char                    *Line,
 265     UINT64                  *ReturnValue)
 266 {
 267     UINT64                  Result;
 268     char                    *ExpandedLine;
 269 
 270 
 271     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 272         "**** Resolve #if:  %s\n", Gbl_CurrentLineNumber, Line);
 273 
 274     /* Expand all macros within the expression first */
 275 
 276     ExpandedLine = PrExpandMacros (Line);
 277 
 278     /* Now we can evaluate the expression */
 279 
 280     Result = PrEvaluateExpression (ExpandedLine);
 281     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 282         "**** Expression Resolved to: %8.8X%8.8X\n",
 283         Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Result));
 284 
 285     *ReturnValue = Result;
 286     return (AE_OK);
 287 
 288 #if 0
 289 InvalidExpression:
 290 
 291     ACPI_FREE (EvalBuffer);
 292     PrError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, 0);
 293     return (AE_ERROR);
 294 
 295 
 296 NormalExit:
 297 
 298     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
 299         "**** Expression Resolved to: %8.8X%8.8X\n",
 300         Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value1));
 301 
 302     *ReturnValue = Value1;
 303     return (AE_OK);
 304 #endif
 305 }