1ff4a156dSchristos /****************************************************************************** 2ff4a156dSchristos * 3ff4a156dSchristos * Module Name: prmacros - Preprocessor #define macro support 4ff4a156dSchristos * 5ff4a156dSchristos *****************************************************************************/ 6ff4a156dSchristos 7ff4a156dSchristos /* 8*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp. 9ff4a156dSchristos * All rights reserved. 10ff4a156dSchristos * 11ff4a156dSchristos * Redistribution and use in source and binary forms, with or without 12ff4a156dSchristos * modification, are permitted provided that the following conditions 13ff4a156dSchristos * are met: 14ff4a156dSchristos * 1. Redistributions of source code must retain the above copyright 15ff4a156dSchristos * notice, this list of conditions, and the following disclaimer, 16ff4a156dSchristos * without modification. 17ff4a156dSchristos * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18ff4a156dSchristos * substantially similar to the "NO WARRANTY" disclaimer below 19ff4a156dSchristos * ("Disclaimer") and any redistribution must be conditioned upon 20ff4a156dSchristos * including a substantially similar Disclaimer requirement for further 21ff4a156dSchristos * binary redistribution. 22ff4a156dSchristos * 3. Neither the names of the above-listed copyright holders nor the names 23ff4a156dSchristos * of any contributors may be used to endorse or promote products derived 24ff4a156dSchristos * from this software without specific prior written permission. 25ff4a156dSchristos * 26ff4a156dSchristos * Alternatively, this software may be distributed under the terms of the 27ff4a156dSchristos * GNU General Public License ("GPL") version 2 as published by the Free 28ff4a156dSchristos * Software Foundation. 29ff4a156dSchristos * 30ff4a156dSchristos * NO WARRANTY 31ff4a156dSchristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32ff4a156dSchristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34ff4a156dSchristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35ff4a156dSchristos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36ff4a156dSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37ff4a156dSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38ff4a156dSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39ff4a156dSchristos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40ff4a156dSchristos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41ff4a156dSchristos * POSSIBILITY OF SUCH DAMAGES. 42ff4a156dSchristos */ 43ff4a156dSchristos 44ff4a156dSchristos #include "aslcompiler.h" 45ff4a156dSchristos 46ff4a156dSchristos #define _COMPONENT ASL_PREPROCESSOR 47ff4a156dSchristos ACPI_MODULE_NAME ("prmacros") 48ff4a156dSchristos 49ff4a156dSchristos 50ff4a156dSchristos /******************************************************************************* 51ff4a156dSchristos * 52ff4a156dSchristos * FUNCTION: PrDumpPredefinedNames 53ff4a156dSchristos * 54ff4a156dSchristos * PARAMETERS: None 55ff4a156dSchristos * 56ff4a156dSchristos * RETURN: None 57ff4a156dSchristos * 58ff4a156dSchristos * DESCRIPTION: Dump the list of #defines. Used as the preprocessor starts, to 59ff4a156dSchristos * display the names that were defined on the command line. 60ff4a156dSchristos * Debug information only. 61ff4a156dSchristos * 62ff4a156dSchristos ******************************************************************************/ 63ff4a156dSchristos 64ff4a156dSchristos void 65ff4a156dSchristos PrDumpPredefinedNames ( 66ff4a156dSchristos void) 67ff4a156dSchristos { 68ff4a156dSchristos PR_DEFINE_INFO *DefineInfo; 69ff4a156dSchristos 70ff4a156dSchristos 714c4e8184Schristos DefineInfo = AslGbl_DefineList; 72ff4a156dSchristos while (DefineInfo) 73ff4a156dSchristos { 74ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 75ff4a156dSchristos "Predefined #define: %s->%s\n", 76ff4a156dSchristos 0, DefineInfo->Identifier, DefineInfo->Replacement); 77ff4a156dSchristos 78ff4a156dSchristos DefineInfo = DefineInfo->Next; 79ff4a156dSchristos } 80ff4a156dSchristos } 81ff4a156dSchristos 82ff4a156dSchristos 83ff4a156dSchristos /******************************************************************************* 84ff4a156dSchristos * 85ff4a156dSchristos * FUNCTION: PrAddDefine 86ff4a156dSchristos * 87ff4a156dSchristos * PARAMETERS: Identifier - Name to be replaced 88ff4a156dSchristos * Replacement - Replacement for Identifier 89ff4a156dSchristos * Persist - Keep define across multiple compiles? 90ff4a156dSchristos * 91ff4a156dSchristos * RETURN: A new define_info struct. NULL on error. 92ff4a156dSchristos * 93ff4a156dSchristos * DESCRIPTION: Add a new #define to the global list 94ff4a156dSchristos * 95ff4a156dSchristos ******************************************************************************/ 96ff4a156dSchristos 97ff4a156dSchristos PR_DEFINE_INFO * 98ff4a156dSchristos PrAddDefine ( 99ff4a156dSchristos char *Identifier, 100ff4a156dSchristos char *Replacement, 101ff4a156dSchristos BOOLEAN Persist) 102ff4a156dSchristos { 103ff4a156dSchristos char *IdentifierString; 104ff4a156dSchristos char *ReplacementString; 105ff4a156dSchristos PR_DEFINE_INFO *DefineInfo; 106ff4a156dSchristos 107ff4a156dSchristos 108ff4a156dSchristos if (!Replacement) 109ff4a156dSchristos { 110ff4a156dSchristos Replacement = ""; 111ff4a156dSchristos } 112ff4a156dSchristos 113ff4a156dSchristos /* Check for already-defined first */ 114ff4a156dSchristos 115ff4a156dSchristos DefineInfo = PrMatchDefine (Identifier); 116ff4a156dSchristos if (DefineInfo) 117ff4a156dSchristos { 118783af925Schristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 119ff4a156dSchristos "#define: name already exists: %s\n", 1204c4e8184Schristos AslGbl_CurrentLineNumber, Identifier); 121ff4a156dSchristos 122ff4a156dSchristos /* 123ff4a156dSchristos * Name already exists. This is only an error if the target name 124ff4a156dSchristos * is different. 125ff4a156dSchristos */ 126ff4a156dSchristos if (strcmp (Replacement, DefineInfo->Replacement)) 127ff4a156dSchristos { 128ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME, 129ff4a156dSchristos THIS_TOKEN_OFFSET (Identifier)); 130ff4a156dSchristos 131ff4a156dSchristos return (NULL); 132ff4a156dSchristos } 133ff4a156dSchristos 134ff4a156dSchristos return (DefineInfo); 135ff4a156dSchristos } 136ff4a156dSchristos 137ff4a156dSchristos /* Copy input strings */ 138ff4a156dSchristos 139ff4a156dSchristos IdentifierString = UtLocalCalloc (strlen (Identifier) + 1); 140ff4a156dSchristos strcpy (IdentifierString, Identifier); 141ff4a156dSchristos 142ff4a156dSchristos ReplacementString = UtLocalCalloc (strlen (Replacement) + 1); 143ff4a156dSchristos strcpy (ReplacementString, Replacement); 144ff4a156dSchristos 145ff4a156dSchristos /* Init and link new define info struct */ 146ff4a156dSchristos 147ff4a156dSchristos DefineInfo = UtLocalCalloc (sizeof (PR_DEFINE_INFO)); 148ff4a156dSchristos DefineInfo->Replacement = ReplacementString; 149ff4a156dSchristos DefineInfo->Identifier = IdentifierString; 150ff4a156dSchristos DefineInfo->Persist = Persist; 151ff4a156dSchristos 1524c4e8184Schristos if (AslGbl_DefineList) 153ff4a156dSchristos { 1544c4e8184Schristos AslGbl_DefineList->Previous = DefineInfo; 155ff4a156dSchristos } 156ff4a156dSchristos 1574c4e8184Schristos DefineInfo->Next = AslGbl_DefineList; 1584c4e8184Schristos AslGbl_DefineList = DefineInfo; 159ff4a156dSchristos return (DefineInfo); 160ff4a156dSchristos } 161ff4a156dSchristos 162ff4a156dSchristos 163ff4a156dSchristos /******************************************************************************* 164ff4a156dSchristos * 165ff4a156dSchristos * FUNCTION: PrRemoveDefine 166ff4a156dSchristos * 167ff4a156dSchristos * PARAMETERS: DefineName - Name of define to be removed 168ff4a156dSchristos * 169ff4a156dSchristos * RETURN: None 170ff4a156dSchristos * 171ff4a156dSchristos * DESCRIPTION: Implements #undef. Remove a #define if found in the global 172ff4a156dSchristos * list. No error if the target of the #undef does not exist, 173ff4a156dSchristos * as per the C #undef definition. 174ff4a156dSchristos * 175ff4a156dSchristos ******************************************************************************/ 176ff4a156dSchristos 177ff4a156dSchristos void 178ff4a156dSchristos PrRemoveDefine ( 179ff4a156dSchristos char *DefineName) 180ff4a156dSchristos { 181ff4a156dSchristos PR_DEFINE_INFO *DefineInfo; 182ff4a156dSchristos 183ff4a156dSchristos 184ff4a156dSchristos /* Match name and delete the node */ 185ff4a156dSchristos 1864c4e8184Schristos DefineInfo = AslGbl_DefineList; 187ff4a156dSchristos while (DefineInfo) 188ff4a156dSchristos { 189ff4a156dSchristos if (!strcmp (DefineName, DefineInfo->Identifier)) 190ff4a156dSchristos { 191ff4a156dSchristos /* Remove from linked list */ 192ff4a156dSchristos 193ff4a156dSchristos if (DefineInfo->Previous) 194ff4a156dSchristos { 195ff4a156dSchristos (DefineInfo->Previous)->Next = DefineInfo->Next; 196ff4a156dSchristos } 197ff4a156dSchristos else 198ff4a156dSchristos { 1994c4e8184Schristos AslGbl_DefineList = DefineInfo->Next; 200ff4a156dSchristos } 201ff4a156dSchristos 202ff4a156dSchristos if (DefineInfo->Next) 203ff4a156dSchristos { 204ff4a156dSchristos (DefineInfo->Next)->Previous = DefineInfo->Previous; 205ff4a156dSchristos } 206ff4a156dSchristos 207ff4a156dSchristos free (DefineInfo); 208ff4a156dSchristos return; 209ff4a156dSchristos } 210ff4a156dSchristos 211ff4a156dSchristos DefineInfo = DefineInfo->Next; 212ff4a156dSchristos } 213ff4a156dSchristos 214ff4a156dSchristos /* 215ff4a156dSchristos * Name was not found. By definition of #undef, this is not 216ff4a156dSchristos * an error, however. 217ff4a156dSchristos */ 218ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 219ff4a156dSchristos "#undef: could not find %s\n", 2204c4e8184Schristos AslGbl_CurrentLineNumber, DefineName); 221ff4a156dSchristos } 222ff4a156dSchristos 223ff4a156dSchristos 224ff4a156dSchristos /******************************************************************************* 225ff4a156dSchristos * 226ff4a156dSchristos * FUNCTION: PrMatchDefine 227ff4a156dSchristos * 228ff4a156dSchristos * PARAMETERS: MatchString - Name associated with the #define 229ff4a156dSchristos * 230ff4a156dSchristos * RETURN: Matched string if found. NULL otherwise. 231ff4a156dSchristos * 232ff4a156dSchristos * DESCRIPTION: Find a name in global #define list 233ff4a156dSchristos * 234ff4a156dSchristos ******************************************************************************/ 235ff4a156dSchristos 236ff4a156dSchristos PR_DEFINE_INFO * 237ff4a156dSchristos PrMatchDefine ( 238ff4a156dSchristos char *MatchString) 239ff4a156dSchristos { 240ff4a156dSchristos PR_DEFINE_INFO *DefineInfo; 241ff4a156dSchristos 242ff4a156dSchristos 2434c4e8184Schristos DefineInfo = AslGbl_DefineList; 244ff4a156dSchristos while (DefineInfo) 245ff4a156dSchristos { 246ff4a156dSchristos if (!strcmp (MatchString, DefineInfo->Identifier)) 247ff4a156dSchristos { 248ff4a156dSchristos return (DefineInfo); 249ff4a156dSchristos } 250ff4a156dSchristos 251ff4a156dSchristos DefineInfo = DefineInfo->Next; 252ff4a156dSchristos } 253ff4a156dSchristos 254ff4a156dSchristos return (NULL); 255ff4a156dSchristos } 256ff4a156dSchristos 257ff4a156dSchristos 258ff4a156dSchristos /******************************************************************************* 259ff4a156dSchristos * 260ff4a156dSchristos * FUNCTION: PrAddMacro 261ff4a156dSchristos * 262ff4a156dSchristos * PARAMETERS: Name - Start of the macro definition 263ff4a156dSchristos * Next - "Next" buffer from GetNextToken 264ff4a156dSchristos * 265ff4a156dSchristos * RETURN: None 266ff4a156dSchristos * 267ff4a156dSchristos * DESCRIPTION: Add a new macro to the list of #defines. Handles argument 268ff4a156dSchristos * processing. 269ff4a156dSchristos * 270ff4a156dSchristos ******************************************************************************/ 271ff4a156dSchristos 272ff4a156dSchristos void 273ff4a156dSchristos PrAddMacro ( 274ff4a156dSchristos char *Name, 275ff4a156dSchristos char **Next) 276ff4a156dSchristos { 277ff4a156dSchristos char *Token = NULL; 278ff4a156dSchristos ACPI_SIZE TokenOffset; 279ff4a156dSchristos ACPI_SIZE MacroBodyOffset; 280ff4a156dSchristos PR_DEFINE_INFO *DefineInfo; 281ff4a156dSchristos PR_MACRO_ARG *Args; 282ff4a156dSchristos char *Body; 283ff4a156dSchristos char *BodyInSource; 284ff4a156dSchristos UINT32 i; 285ff4a156dSchristos UINT16 UseCount = 0; 286ff4a156dSchristos UINT16 ArgCount = 0; 287ff4a156dSchristos UINT32 Depth = 1; 288*046a2985Schristos /*UINT32 Depth = 1;*/ 289ff4a156dSchristos UINT32 EndOfArgList; 290ff4a156dSchristos char BufferChar; 291ff4a156dSchristos 292ff4a156dSchristos /* Find the end of the arguments list */ 293ff4a156dSchristos 2944c4e8184Schristos TokenOffset = Name - AslGbl_MainTokenBuffer + strlen (Name) + 1; 295ff4a156dSchristos while (1) 296ff4a156dSchristos { 2974c4e8184Schristos BufferChar = AslGbl_CurrentLineBuffer[TokenOffset]; 298ff4a156dSchristos if (BufferChar == '(') 299ff4a156dSchristos { 300ff4a156dSchristos Depth++; 301ff4a156dSchristos } 302ff4a156dSchristos else if (BufferChar == ')') 303ff4a156dSchristos { 304ff4a156dSchristos Depth--; 305ff4a156dSchristos } 306ff4a156dSchristos else if (BufferChar == 0) 307ff4a156dSchristos { 308ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_MACRO_SYNTAX, TokenOffset); 309ff4a156dSchristos return; 310ff4a156dSchristos } 311ff4a156dSchristos 312ff4a156dSchristos if (Depth == 0) 313ff4a156dSchristos { 314ff4a156dSchristos /* Found arg list end */ 315ff4a156dSchristos 316ff4a156dSchristos EndOfArgList = TokenOffset; 317ff4a156dSchristos break; 318ff4a156dSchristos } 319ff4a156dSchristos 320ff4a156dSchristos TokenOffset++; 321ff4a156dSchristos } 322ff4a156dSchristos 323ff4a156dSchristos /* At this point, we know that we have a reasonable argument list */ 324ff4a156dSchristos 325ff4a156dSchristos Args = UtLocalCalloc (sizeof (PR_MACRO_ARG) * PR_MAX_MACRO_ARGS); 326ff4a156dSchristos 327ff4a156dSchristos /* Get the macro argument names */ 328ff4a156dSchristos 329ff4a156dSchristos for (i = 0; i < PR_MAX_MACRO_ARGS; i++) 330ff4a156dSchristos { 331ff4a156dSchristos Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next); 332*046a2985Schristos 333ff4a156dSchristos if (!Token) 334ff4a156dSchristos { 335ff4a156dSchristos /* This is the case for a NULL macro body */ 336ff4a156dSchristos 337ff4a156dSchristos BodyInSource = ""; 338ff4a156dSchristos goto AddMacroToList; 339ff4a156dSchristos } 340ff4a156dSchristos 341ff4a156dSchristos /* Don't go beyond the argument list */ 342ff4a156dSchristos 3434c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer + strlen (Token); 344ff4a156dSchristos if (TokenOffset > EndOfArgList) 345ff4a156dSchristos { 346ff4a156dSchristos break; 347ff4a156dSchristos } 348ff4a156dSchristos 349ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 350*046a2985Schristos "Macro param: %s\n", 3514c4e8184Schristos AslGbl_CurrentLineNumber, Token); 352ff4a156dSchristos 353ff4a156dSchristos Args[i].Name = UtLocalCalloc (strlen (Token) + 1); 354ff4a156dSchristos strcpy (Args[i].Name, Token); 355ff4a156dSchristos 356ff4a156dSchristos Args[i].UseCount = 0; 357ff4a156dSchristos ArgCount++; 358ff4a156dSchristos if (ArgCount >= PR_MAX_MACRO_ARGS) 359ff4a156dSchristos { 360ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS, TokenOffset); 361460301d4Schristos goto ErrorExit; 362ff4a156dSchristos } 363ff4a156dSchristos } 364ff4a156dSchristos 365ff4a156dSchristos /* Get the macro body. Token now points to start of body */ 366ff4a156dSchristos 3674c4e8184Schristos MacroBodyOffset = Token - AslGbl_MainTokenBuffer; 368ff4a156dSchristos 369ff4a156dSchristos /* Match each method arg in the macro body for later use */ 370ff4a156dSchristos 371ff4a156dSchristos while (Token) 372ff4a156dSchristos { 373ff4a156dSchristos /* Search the macro arg list for matching arg */ 374ff4a156dSchristos 37589b8eb6cSchristos for (i = 0; ((i < PR_MAX_MACRO_ARGS) && Args[i].Name); i++) 376ff4a156dSchristos { 377ff4a156dSchristos /* 378ff4a156dSchristos * Save argument offset within macro body. This is the mechanism 379ff4a156dSchristos * used to expand the macro upon invocation. 380ff4a156dSchristos * 381ff4a156dSchristos * Handles multiple instances of the same argument 382ff4a156dSchristos */ 383ff4a156dSchristos if (!strcmp (Token, Args[i].Name)) 384ff4a156dSchristos { 385ff4a156dSchristos UseCount = Args[i].UseCount; 386ff4a156dSchristos 38771e38f1dSchristos Args[i].Offset[UseCount] = 3884c4e8184Schristos (Token - AslGbl_MainTokenBuffer) - MacroBodyOffset; 389ff4a156dSchristos 390*046a2985Schristos 391ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 392ff4a156dSchristos "Macro Arg #%u: %s UseCount %u Offset %u\n", 3934c4e8184Schristos AslGbl_CurrentLineNumber, i, Token, 394ff4a156dSchristos UseCount+1, Args[i].Offset[UseCount]); 395ff4a156dSchristos 396ff4a156dSchristos Args[i].UseCount++; 397*046a2985Schristos 398ff4a156dSchristos if (Args[i].UseCount >= PR_MAX_ARG_INSTANCES) 399ff4a156dSchristos { 400ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS, 401ff4a156dSchristos THIS_TOKEN_OFFSET (Token)); 402ff4a156dSchristos 403460301d4Schristos goto ErrorExit; 404ff4a156dSchristos } 405ff4a156dSchristos break; 406ff4a156dSchristos } 407ff4a156dSchristos } 408ff4a156dSchristos 409ff4a156dSchristos Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next); 410ff4a156dSchristos } 411ff4a156dSchristos 4124c4e8184Schristos BodyInSource = &AslGbl_CurrentLineBuffer[MacroBodyOffset]; 413ff4a156dSchristos 414ff4a156dSchristos 415ff4a156dSchristos AddMacroToList: 416ff4a156dSchristos 417ff4a156dSchristos /* Check if name is already defined first */ 418ff4a156dSchristos 419ff4a156dSchristos DefineInfo = PrMatchDefine (Name); 420ff4a156dSchristos if (DefineInfo) 421ff4a156dSchristos { 422ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 423ff4a156dSchristos "#define: macro name already exists: %s\n", 4244c4e8184Schristos AslGbl_CurrentLineNumber, Name); 425ff4a156dSchristos 426ff4a156dSchristos /* Error only if not exactly the same macro */ 427ff4a156dSchristos 428ff4a156dSchristos if (strcmp (DefineInfo->Body, BodyInSource) || 429ff4a156dSchristos (DefineInfo->ArgCount != ArgCount)) 430ff4a156dSchristos { 431ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME, 432ff4a156dSchristos THIS_TOKEN_OFFSET (Name)); 433ff4a156dSchristos } 434ff4a156dSchristos 435460301d4Schristos goto ErrorExit; 436ff4a156dSchristos } 437ff4a156dSchristos 438ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 439ff4a156dSchristos "Macro body: %s\n", 4404c4e8184Schristos AslGbl_CurrentLineNumber, BodyInSource); 441ff4a156dSchristos 442ff4a156dSchristos /* Add macro to the #define list */ 443ff4a156dSchristos 444ff4a156dSchristos DefineInfo = PrAddDefine (Name, BodyInSource, FALSE); 445ff4a156dSchristos if (DefineInfo) 446ff4a156dSchristos { 447ff4a156dSchristos Body = UtLocalCalloc (strlen (BodyInSource) + 1); 448ff4a156dSchristos strcpy (Body, BodyInSource); 449ff4a156dSchristos 450ff4a156dSchristos DefineInfo->Body = Body; 451ff4a156dSchristos DefineInfo->Args = Args; 452ff4a156dSchristos DefineInfo->ArgCount = ArgCount; 453ff4a156dSchristos } 454460301d4Schristos 455460301d4Schristos return; 456460301d4Schristos 457460301d4Schristos 458460301d4Schristos ErrorExit: 459460301d4Schristos ACPI_FREE (Args); 460460301d4Schristos return; 461ff4a156dSchristos } 462ff4a156dSchristos 463ff4a156dSchristos 464ff4a156dSchristos /******************************************************************************* 465ff4a156dSchristos * 466ff4a156dSchristos * FUNCTION: PrDoMacroInvocation 467ff4a156dSchristos * 468ff4a156dSchristos * PARAMETERS: TokenBuffer - Current line buffer 469ff4a156dSchristos * MacroStart - Start of the macro invocation within 470ff4a156dSchristos * the token buffer 471ff4a156dSchristos * DefineInfo - Info for this macro 472ff4a156dSchristos * Next - "Next" buffer from GetNextToken 473ff4a156dSchristos * 474ff4a156dSchristos * RETURN: None 475ff4a156dSchristos * 476ff4a156dSchristos * DESCRIPTION: Expand a macro invocation 477ff4a156dSchristos * 478ff4a156dSchristos ******************************************************************************/ 479ff4a156dSchristos 480ff4a156dSchristos void 481ff4a156dSchristos PrDoMacroInvocation ( 482ff4a156dSchristos char *TokenBuffer, 483ff4a156dSchristos char *MacroStart, 484ff4a156dSchristos PR_DEFINE_INFO *DefineInfo, 485ff4a156dSchristos char **Next) 486ff4a156dSchristos { 487ff4a156dSchristos PR_MACRO_ARG *Args; 488ff4a156dSchristos char *Token = NULL; 489ff4a156dSchristos UINT32 TokenOffset; 490ff4a156dSchristos UINT32 Length; 491ff4a156dSchristos UINT32 i; 492*046a2985Schristos UINT32 Diff1; 493*046a2985Schristos UINT32 Diff2; 494ff4a156dSchristos 495ff4a156dSchristos /* Take a copy of the macro body for expansion */ 496ff4a156dSchristos 4974c4e8184Schristos strcpy (AslGbl_MacroTokenBuffer, DefineInfo->Body); 498ff4a156dSchristos 499ff4a156dSchristos /* Replace each argument within the prototype body */ 500ff4a156dSchristos 501ff4a156dSchristos Args = DefineInfo->Args; 502ff4a156dSchristos if (!Args->Name) 503ff4a156dSchristos { 504ff4a156dSchristos /* This macro has no arguments */ 505ff4a156dSchristos 506ff4a156dSchristos Token = PrGetNextToken (NULL, PR_MACRO_ARGUMENTS, Next); 507*046a2985Schristos 508ff4a156dSchristos if (!Token) 509ff4a156dSchristos { 510ff4a156dSchristos goto BadInvocation; 511ff4a156dSchristos } 512ff4a156dSchristos 513ff4a156dSchristos TokenOffset = (MacroStart - TokenBuffer); 514ff4a156dSchristos Length = Token - MacroStart + strlen (Token) + 1; 515ff4a156dSchristos 516ff4a156dSchristos PrReplaceData ( 5174c4e8184Schristos &AslGbl_CurrentLineBuffer[TokenOffset], Length, 5184c4e8184Schristos AslGbl_MacroTokenBuffer, strlen (AslGbl_MacroTokenBuffer)); 519ff4a156dSchristos return; 520ff4a156dSchristos } 521ff4a156dSchristos 522ff4a156dSchristos while (Args->Name) 523ff4a156dSchristos { 524ff4a156dSchristos /* Get the next argument from macro invocation */ 525ff4a156dSchristos 526ff4a156dSchristos Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next); 527ff4a156dSchristos if (!Token) 528ff4a156dSchristos { 529ff4a156dSchristos goto BadInvocation; 530ff4a156dSchristos } 531ff4a156dSchristos 532*046a2985Schristos /* 533*046a2985Schristos * Avoid optimizing using just 1 signed int due to specific 534*046a2985Schristos * non-portable implementations of signed ints 535*046a2985Schristos */ 536*046a2985Schristos Diff1 = strlen (Args->Name) > strlen (Token) ? strlen (Args->Name) - 537*046a2985Schristos strlen (Token) : 0; 538*046a2985Schristos 539*046a2985Schristos Diff2 = strlen (Args->Name) < strlen (Token) ? strlen (Token) - 540*046a2985Schristos strlen (Args->Name) : 0; 541*046a2985Schristos 542ff4a156dSchristos /* Replace all instances of this argument */ 543ff4a156dSchristos 544ff4a156dSchristos for (i = 0; i < Args->UseCount; i++) 545ff4a156dSchristos { 546*046a2985Schristos /* 547*046a2985Schristos * To test the output of the preprocessed macro function that 548*046a2985Schristos * is passed to the compiler 549*046a2985Schristos */ 550ff4a156dSchristos 551*046a2985Schristos /* 552*046a2985Schristos * fprintf (stderr, "Current token = %s \t Current arg_name = %s \ 553*046a2985Schristos * \t strlen (Token) = %u \t strlen (Args->Name) = %u \t Offset = %u \ 554*046a2985Schristos * \t UseCount = %u \t", Token, Args->Name, strlen (Token), \ 555*046a2985Schristos * strlen (Args->Name), Args->Offset[i], Args->UseCount); 556*046a2985Schristos */ 557ff4a156dSchristos 558*046a2985Schristos AslGbl_MacroTokenReplaceBuffer = (char *) calloc ((strlen (AslGbl_MacroTokenBuffer)), sizeof (char)); 559*046a2985Schristos 560*046a2985Schristos PrReplaceResizeSubstring (Args, Diff1, Diff2, i, Token); 561ff4a156dSchristos 562ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 563ff4a156dSchristos "ExpandArg: %s\n", 5644c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_MacroTokenBuffer); 565ff4a156dSchristos } 566ff4a156dSchristos 567ff4a156dSchristos Args++; 568ff4a156dSchristos } 569ff4a156dSchristos 570ff4a156dSchristos if (!Token) 571ff4a156dSchristos { 572ff4a156dSchristos return; 573ff4a156dSchristos } 574ff4a156dSchristos 575ff4a156dSchristos /* Replace the entire macro invocation with the expanded macro */ 576ff4a156dSchristos 577ff4a156dSchristos TokenOffset = (MacroStart - TokenBuffer); 578ff4a156dSchristos Length = Token - MacroStart + strlen (Token) + 1; 579ff4a156dSchristos 580ff4a156dSchristos PrReplaceData ( 5814c4e8184Schristos &AslGbl_CurrentLineBuffer[TokenOffset], Length, 5824c4e8184Schristos AslGbl_MacroTokenBuffer, strlen (AslGbl_MacroTokenBuffer)); 583ff4a156dSchristos 584ff4a156dSchristos return; 585ff4a156dSchristos 586ff4a156dSchristos BadInvocation: 587ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_INVALID_INVOCATION, 588ff4a156dSchristos THIS_TOKEN_OFFSET (MacroStart)); 589ff4a156dSchristos 590ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 591ff4a156dSchristos "Bad macro invocation: %s\n", 5924c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_MacroTokenBuffer); 593ff4a156dSchristos return; 594ff4a156dSchristos } 595