Beispiel #1
0
int IsSizeOfSymbol (const SymEntry* Sym)
/* Return true if the given symbol is the one that encodes the size of some
 * entity. Sym may also be a NULL pointer in which case false is returned.
 */
{
    return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0);
}
Beispiel #2
0
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
/* Search in the given tree for a name. If we find the symbol, the function
** will return 0 and put the entry pointer into E. If we did not find the
** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
** E will be set to the last entry, and the result of the function is <0 if
** the entry should be inserted on the left side, and >0 if it should get
** inserted on the right side.
*/
{
    /* Is there a tree? */
    if (T == 0) {
        *E = 0;
        return 1;
    }

    /* We have a table, search it */
    while (1) {

        /* Get the symbol name */
        const StrBuf* SymName = GetStrBuf (T->Name);

        /* Choose next entry */
        int Cmp = SB_Compare (Name, SymName);
        if (Cmp < 0 && T->Left) {
            T = T->Left;
        } else if (Cmp > 0 && T->Right) {
            T = T->Right;
        } else {
            /* Found or end of search, return the result */
            *E = T;
            return Cmp;
        }
    }
}
Beispiel #3
0
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
 * Key1 is smaller than Key2, zero if both are equal, and a value greater
 * than zero if Key1 is greater then Key2.
 */
{
    return SB_Compare (Key1, Key2);
}
Beispiel #4
0
enum TC TokCmp (const TokNode* T)
/* Compare the token given as parameter against the current token */
{
    if (T->Tok != Tok) {
	/* Different token */
	return tcDifferent;
    }

    /* If the token has string attribute, check it */
    if (TokHasSVal (T->Tok)) {
       	if (SB_Compare (&SVal, &T->SVal) != 0) {
     	    return tcSameToken;
	}
    } else if (TokHasIVal (T->Tok)) {
	if (T->IVal != IVal) {
     	    return tcSameToken;
	}
    }

    /* Tokens are identical */
    return tcIdentical;
}
Beispiel #5
0
SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Action)
/* Find a scope in the given enclosing scope */
{
    SymTable** T = &Parent->Childs;
    while (*T) {
        int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
        if (Cmp < 0) {
            T = &(*T)->Left;
        } else if (Cmp > 0) {
            T = &(*T)->Right;
        } else {
            /* Found the scope */
            return *T;
        }
    }

    /* Create a new scope if requested and we didn't find one */
    if (*T == 0 && (Action & SYM_ALLOC_NEW) != 0) {
        *T = NewSymTable (Parent, Name);
    }

    /* Return the scope */
    return *T;
}
Beispiel #6
0
static int CmpExpName (const void* K1, const void* K2)
/* Compare function for qsort */
{
    return SB_Compare (GetStrBuf ((*(Export**)K1)->Name),
                       GetStrBuf ((*(Export**)K2)->Name));
}
Beispiel #7
0
static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
/* Allocate a symbol table on the heap and return it */
{
    /* Determine the lexical level and the number of table slots */
    unsigned Level = Parent? Parent->Level + 1 : 0;
    unsigned Slots = ScopeTableSize (Level);

    /* Allocate memory */
    SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));

    /* Set variables and clear hash table entries */
    S->Next         = 0;
    S->Left         = 0;
    S->Right        = 0;
    S->Childs       = 0;
    S->Label        = 0;
    S->Spans        = AUTO_COLLECTION_INITIALIZER;
    S->Id           = ScopeCount++;
    S->Flags        = ST_NONE;
    S->AddrSize     = ADDR_SIZE_DEFAULT;
    S->Type         = SCOPE_UNDEF;
    S->Level        = Level;
    S->TableSlots   = Slots;
    S->TableEntries = 0;
    S->Parent       = Parent;
    S->Name         = GetStrBufId (Name);
    while (Slots--) {
        S->Table[Slots] = 0;
    }

    /* Insert the symbol table into the list of all symbol tables */
    if (RootScope == 0) {
        RootScope = S;
    } else {
        LastScope->Next = S;
    }
    LastScope = S;

    /* Insert the symbol table into the child tree of the parent */
    if (Parent) {
        SymTable* T = Parent->Childs;
        if (T == 0) {
            /* First entry */
            Parent->Childs = S;
        } else {
            while (1) {
                /* Choose next entry */
                int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
                if (Cmp < 0) {
                    if (T->Left) {
                        T = T->Left;
                    } else {
                        T->Left = S;
                        break;
                    }
                } else if (Cmp > 0) {
                    if (T->Right) {
                        T = T->Right;
                    } else {
                        T->Right = S;
                        break;
                    }
                } else {
                    /* Duplicate scope name */
                    Internal ("Duplicate scope name: `%m%p'", Name);
                }
            }
        }
    }

    /* Return the prepared struct */
    return S;
}
Beispiel #8
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.
     */
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;
}
Beispiel #9
0
void MacDef (unsigned Style)
/* Parse a macro definition */
{
    Macro* M;
    TokNode* N;
    int HaveParams;

    /* We expect a macro name here */
    if (CurTok.Tok != TOK_IDENT) {
        Error ("Identifier expected");
        MacSkipDef (Style);
        return;
    } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
        /* The identifier is a name of a 6502 instruction, which is not
         * allowed if not explicitly enabled.
         */
        Error ("Cannot use an instruction as macro name");
        MacSkipDef (Style);
        return;
    }

    /* Did we already define that macro? */
    if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
        /* Macro is already defined */
        Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
        /* Skip tokens until we reach the final .endmacro */
        MacSkipDef (Style);
        return;
    }

    /* Define the macro */
    M = NewMacro (&CurTok.SVal, Style);

    /* Switch to raw token mode and skip the macro name */
    EnterRawTokenMode ();
    NextTok ();

    /* If we have a DEFINE style macro, we may have parameters in braces,
     * otherwise we may have parameters without braces.
     */
    if (Style == MAC_STYLE_CLASSIC) {
        HaveParams = 1;
    } else {
        if (CurTok.Tok == TOK_LPAREN) {
            HaveParams = 1;
            NextTok ();
        } else {
            HaveParams = 0;
        }
    }

    /* Parse the parameter list */
    if (HaveParams) {

        while (CurTok.Tok == TOK_IDENT) {

            /* Create a struct holding the identifier */
            IdDesc* I = NewIdDesc (&CurTok.SVal);

            /* Insert the struct into the list, checking for duplicate idents */
            if (M->ParamCount == 0) {
                M->Params = I;
            } else {
                IdDesc* List = M->Params;
                while (1) {
                    if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
                        Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
                    }
                    if (List->Next == 0) {
                        break;
                    } else {
                        List = List->Next;
                    }
                }
                List->Next = I;
            }
            ++M->ParamCount;

            /* Skip the name */
            NextTok ();

            /* Maybe there are more params... */
            if (CurTok.Tok == TOK_COMMA) {
                NextTok ();
            } else {
                break;
            }
        }
    }

    /* For class macros, we expect a separator token, for define style macros,
     * we expect the closing paren.
     */
    if (Style == MAC_STYLE_CLASSIC) {
        ConsumeSep ();
    } else if (HaveParams) {
        ConsumeRParen ();
    }

    /* Preparse the macro body. We will read the tokens until we reach end of
     * file, or a .endmacro (or end of line for DEFINE style macros) and store
     * them into an token list internal to the macro. For classic macros, there
     * the .LOCAL command is detected and removed at this time.
     */
    while (1) {

        /* Check for end of macro */
        if (Style == MAC_STYLE_CLASSIC) {
            /* In classic macros, only .endmacro is allowed */
            if (CurTok.Tok == TOK_ENDMACRO) {
                /* Done */
                break;
            }
            /* May not have end of file in a macro definition */
            if (CurTok.Tok == TOK_EOF) {
                Error ("`.ENDMACRO' expected");
                goto Done;
            }
        } else {
            /* Accept a newline or end of file for new style macros */
            if (TokIsSep (CurTok.Tok)) {
                break;
            }
        }

        /* Check for a .LOCAL declaration */
        if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {

            while (1) {

                IdDesc* I;

                /* Skip .local or comma */
                NextTok ();

                /* Need an identifer */
                if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
                    Error ("Identifier expected");
                    SkipUntilSep ();
                    break;
                }

                /* Put the identifier into the locals list and skip it */
                I = NewIdDesc (&CurTok.SVal);
                I->Next = M->Locals;
                M->Locals = I;
                ++M->LocalCount;
                NextTok ();

                /* Check for end of list */
                if (CurTok.Tok != TOK_COMMA) {
                    break;
                }

            }

            /* We need end of line after the locals */
            ConsumeSep ();
            continue;
        }

        /* Create a token node for the current token */
        N = NewTokNode ();

        /* If the token is an identifier, check if it is a local parameter */
        if (CurTok.Tok == TOK_IDENT) {
            unsigned Count = 0;
            IdDesc* I = M->Params;
            while (I) {
                if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
                    /* Local param name, replace it */
                    N->T.Tok  = TOK_MACPARAM;
                    N->T.IVal = Count;
                    break;
                }
                ++Count;
                I = I->Next;
            }
        }

        /* Insert the new token in the list */
        if (M->TokCount == 0) {
            /* First token */
            M->TokRoot = M->TokLast = N;
        } else {
            /* We have already tokens */
            M->TokLast->Next = N;
            M->TokLast = N;
        }
        ++M->TokCount;

        /* Read the next token */
        NextTok ();
    }

    /* Skip the .endmacro for a classic macro */
    if (Style == MAC_STYLE_CLASSIC) {
        NextTok ();
    }

    /* Reset the Incomplete flag now that parsing is done */
    M->Incomplete = 0;

Done:
    /* Switch out of raw token mode */
    LeaveRawTokenMode ();
}
Beispiel #10
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;
}