static void FreeMacExp (MacExp* E) /* Remove and free the current macro expansion */ { unsigned I; /* One macro expansion less */ --MacExpansions; /* Free the parameter lists */ for (I = 0; I < E->ParamCount; ++I) { /* Free one parameter list */ TokNode* N = E->Params[I]; while (N) { TokNode* P = N->Next; FreeTokNode (N); N = P; } } xfree (E->Params); /* Free the final token if we have one */ if (E->Final) { FreeTokNode (E->Final); } /* Free the structure itself */ xfree (E); }
static void FuncRight (void) /* Handle the .RIGHT function */ { long Count; TokList* List; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Count argument. Correct negative counts to zero. */ Count = ConstExpression (); if (Count < 0) { Count = 0; } ConsumeComma (); /* Read the complete token list */ List = CollectTokens (0, 9999); /* Delete tokens from the list until Count tokens are remaining */ while (List->Count > (unsigned) Count) { /* Get the first node */ TokNode* T = List->Root; /* Remove it from the list */ List->Root = List->Root->Next; /* Free the node */ FreeTokNode (T); /* Corrent the token counter */ List->Count--; } /* Since we want to insert the list before the now current token, we have * to save the current token in some way and then skip it. To do this, we * will add the current token at the end of the token list (so the list * will never be empty), push the token list, and then skip the current * token. This will replace the current token by the first token from the * list (which will be the old current token in case the list was empty). */ AddCurTok (List); /* Insert it into the scanner feed */ PushTokList (List, ".RIGHT"); /* Skip the current token */ NextTok (); }
void FreeTokList (TokList* List) /* Delete the token list including all token nodes */ { /* Free the token list */ TokNode* T = List->Root; while (T) { TokNode* Tmp = T; T = T->Next; FreeTokNode (Tmp); } /* If we have associated data, free it */ if (List->Data) { xfree (List->Data); } /* Free the list structure itself */ xfree (List); }
static void FreeMacro (Macro* M) /* Free a macro entry which has already been removed from the macro table. */ { TokNode* T; /* Free locals */ FreeIdDescList (M->Locals); /* Free identifiers of parameters */ FreeIdDescList (M->Params); /* Free the token list for the macro */ while ((T = M->TokRoot) != 0) { M->TokRoot = T->Next; FreeTokNode (T); } /* Free the macro name */ SB_Done (&M->Name); /* Free the macro structure itself */ xfree (M); }
static int MacExpand (void* Data) /* If we're currently expanding a macro, set the the scanner token and * attribute to the next value and return true. If we are not expanding * a macro, return false. */ { /* Cast the Data pointer to the actual data structure */ MacExp* Mac = (MacExp*) Data; /* Check if we should abort this macro */ if (DoMacAbort) { /* Reset the flag */ DoMacAbort = 0; /* Abort any open .IF statements in this macro expansion */ CleanupIfStack (Mac->IfSP); /* Terminate macro expansion */ goto MacEnd; } /* We're expanding a macro. Check if we are expanding one of the * macro parameters. */ ExpandParam: if (Mac->ParamExp) { /* Ok, use token from parameter list */ TokSet (Mac->ParamExp); /* Create new line info for this parameter token */ if (Mac->ParamLI) { EndLine (Mac->ParamLI); } Mac->ParamLI = StartLine (&CurTok.Pos, LI_TYPE_MACPARAM, Mac->MacExpansions); /* Set pointer to next token */ Mac->ParamExp = Mac->ParamExp->Next; /* Done */ return 1; } else if (Mac->ParamLI) { /* There's still line info open from the parameter expansion - end it */ EndLine (Mac->ParamLI); Mac->ParamLI = 0; } /* We're not expanding macro parameters. Check if we have tokens left from * the macro itself. */ if (Mac->Exp) { /* Use next macro token */ TokSet (Mac->Exp); /* Create new line info for this token */ if (Mac->LI) { EndLine (Mac->LI); } Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, Mac->MacExpansions); /* Set pointer to next token */ Mac->Exp = Mac->Exp->Next; /* Is it a request for actual parameter count? */ if (CurTok.Tok == TOK_PARAMCOUNT) { CurTok.Tok = TOK_INTCON; CurTok.IVal = Mac->ParamCount; return 1; } /* Is it the name of a macro parameter? */ if (CurTok.Tok == TOK_MACPARAM) { /* Start to expand the parameter token list */ Mac->ParamExp = Mac->Params[CurTok.IVal]; /* Go back and expand the parameter */ goto ExpandParam; } /* If it's an identifier, it may in fact be a local symbol */ if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) && Mac->M->LocalCount) { /* Search for the local symbol in the list */ unsigned Index = 0; IdDesc* I = Mac->M->Locals; while (I) { if (SB_Compare (&CurTok.SVal, &I->Id) == 0) { /* This is in fact a local symbol, change the name. Be sure * to generate a local label name if the original name was * a local label, and also generate a name that cannot be * generated by a user. */ if (SB_At (&I->Id, 0) == LocalStart) { /* Must generate a local symbol */ SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X", LocalStart, Mac->LocalStart + Index); } else { /* Global symbol */ SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X", Mac->LocalStart + Index); } break; } /* Next symbol */ ++Index; I = I->Next; } /* Done */ return 1; } /* The token was successfully set */ return 1; } /* No more macro tokens. Do we have a final token? */ if (Mac->Final) { /* Set the final token and remove it */ TokSet (Mac->Final); FreeTokNode (Mac->Final); Mac->Final = 0; /* Problem: When a .define style macro is expanded within the call * of a classic one, the latter may be terminated and removed while * the expansion of the .define style macro is still active. Because * line info slots are "stacked", this runs into a CHECK FAILED. For * now, we will fix that by removing the .define style macro expansion * immediately, once the final token is placed. The better solution * would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot * to be called in FIFO order, but this is a bigger change. */ /* End of macro expansion and pop the input function */ FreeMacExp (Mac); PopInput (); /* The token was successfully set */ return 1; } MacEnd: /* End of macro expansion */ FreeMacExp (Mac); /* Pop the input function */ PopInput (); /* No token available */ return 0; }
static int MacExpand (void* Data) /* If we're currently expanding a macro, set the the scanner token and * attribute to the next value and return true. If we are not expanding * a macro, return false. */ { /* Cast the Data pointer to the actual data structure */ MacExp* Mac = (MacExp*) Data; /* Check if we should abort this macro */ if (DoMacAbort) { /* Reset the flag */ DoMacAbort = 0; /* Abort any open .IF statements in this macro expansion */ CleanupIfStack (Mac->IfSP); /* Terminate macro expansion */ goto MacEnd; } /* We're expanding a macro. Check if we are expanding one of the * macro parameters. */ if (Mac->ParamExp) { /* Ok, use token from parameter list */ TokSet (Mac->ParamExp); /* Set pointer to next token */ Mac->ParamExp = Mac->ParamExp->Next; /* Done */ return 1; } /* We're not expanding macro parameters. Check if we have tokens left from * the macro itself. */ if (Mac->Exp) { /* Use next macro token */ TokSet (Mac->Exp); /* Set pointer to next token */ Mac->Exp = Mac->Exp->Next; /* Is it a request for actual parameter count? */ if (Tok == TOK_PARAMCOUNT) { Tok = TOK_INTCON; IVal = Mac->ParamCount; return 1; } /* Is it the name of a macro parameter? */ if (Tok == TOK_MACPARAM) { /* Start to expand the parameter token list */ Mac->ParamExp = Mac->Params [IVal]; /* Recursive call to expand the parameter */ return MacExpand (Mac); } /* If it's an identifier, it may in fact be a local symbol */ if ((Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) && Mac->M->LocalCount) { /* Search for the local symbol in the list */ unsigned Index = 0; IdDesc* I = Mac->M->Locals; while (I) { if (SB_Compare (&SVal, &I->Id) == 0) { /* This is in fact a local symbol, change the name. Be sure * to generate a local label name if the original name was * a local label, and also generate a name that cannot be * generated by a user. */ if (SB_At (&I->Id, 0) == LocalStart) { /* Must generate a local symbol */ SB_Printf (&SVal, "%cLOCAL-MACRO_SYMBOL-%04X", LocalStart, Mac->LocalStart + Index); } else { /* Global symbol */ SB_Printf (&SVal, "LOCAL-MACRO_SYMBOL-%04X", Mac->LocalStart + Index); } break; } /* Next symbol */ ++Index; I = I->Next; } /* Done */ return 1; } /* The token was successfully set */ return 1; } /* No more macro tokens. Do we have a final token? */ if (Mac->Final) { /* Set the final token and remove it */ TokSet (Mac->Final); FreeTokNode (Mac->Final); Mac->Final = 0; /* The token was successfully set */ return 1; } MacEnd: /* End of macro expansion */ FreeMacExp (Mac); /* Pop the input function */ PopInput (); /* No token available */ return 0; }