Пример #1
0
static void FreeLiteralPool (LiteralPool* LP)
/* Free a LiteralPool structure */
{
    /* Free the collections contained within the struct */
    DoneCollection (&LP->WritableLiterals);
    DoneCollection (&LP->ReadOnlyLiterals);

    /* Free the struct itself */
    xfree (LP);
}
Пример #2
0
static void FreeLineInfo (LineInfo* LI)
/* Free a LineInfo structure */
{
    /* Free the Spans collection. It is supposed to be empty */
    CHECK (CollCount (&LI->Spans) == 0);
    DoneCollection (&LI->Spans);
    DoneCollection (&LI->OpenSpans);

    /* Free the structure itself */
    xfree (LI);
}
Пример #3
0
void FreeObjData (ObjData* O)
/* Free a complete struct */
{
    unsigned I;

    xfree (O->Name);
    for (I = 0; I < CollCount (&O->Strings); ++I) {
        xfree (CollAt (&O->Strings, I));
    }
    DoneCollection (&O->Strings);
    DoneCollection (&O->Exports);
    xfree (O);
}
Пример #4
0
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted)
/* Determine register usage information for the instructions starting at the
** given index.
*/
{
    CodeEntry*      E;
    Collection      Visited;    /* Visited entries */
    unsigned        R;

    /* Get the code entry for the given index */
    if (Index >= CS_GetEntryCount (S)) {
        /* There is no such code entry */
        return REG_NONE;
    }
    E = CS_GetEntry (S, Index);

    /* Initialize the data structure used to collection information */
    InitCollection (&Visited);

    /* Call the recursive subfunction */
    R = GetRegInfo1 (S, E, Index, &Visited, REG_NONE, REG_NONE, Wanted);

    /* Delete the line collection */
    DoneCollection (&Visited);

    /* Return the registers used */
    return R;
}
Пример #5
0
void FreeImport (Import* I)
/* Free an import. NOTE: This won't remove the import from the exports table,
** so it may only be called for unused imports (imports from modules that
** aren't referenced).
*/
{
    /* Safety */
    PRECONDITION ((I->Flags & IMP_INLIST) == 0);

    /* Free the line info collections */
    DoneCollection (&I->DefLines);
    DoneCollection (&I->RefLines);

    /* Free the struct */
    xfree (I);
}
Пример #6
0
void FreeCollection (Collection* C)
/* Free a collection */
{
    /* Free the data */
    DoneCollection (C);

    /* Free the structure itself */
    xfree (C);
}
Пример #7
0
void FreeExport (Export* E)
/* Free an export. NOTE: This won't remove the export from the exports table,
** so it may only be called for unused exports (exports from modules that
** aren't referenced).
*/
{
    /* Safety */
    PRECONDITION ((E->Flags & EXP_INLIST) == 0);

    /* Free the line infos */
    DoneCollection (&E->DefLines);
    DoneCollection (&E->RefLines);

    /* Free the export expression */
    FreeExpr (E->Expr);

    /* Free the struct */
    xfree (E);
}
Пример #8
0
static void DestroyStrPool (Collection* C)
/* Free all strings in the given pool plus the item pointers. Note: The
 * collection may not be reused later.
 */
{
    unsigned I;
    for (I = 0; I < CollCount (C); ++I) {
        xfree (CollAtUnchecked (C, I));
    }
    DoneCollection (C);
}
Пример #9
0
static void DoneMacroExp (MacroExp* E)
/* Cleanup after use of a MacroExp structure */
{
    unsigned I;

    /* Delete the list with actual arguments */
    for (I = 0; I < CollCount (&E->ActualArgs); ++I) {
        FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I));
    }
    DoneCollection (&E->ActualArgs);
    SB_Done (&E->Replacement);
}
Пример #10
0
void FreeObjData (ObjData* O)
/* Free an ObjData object. NOTE: This function works only for unused object
 * data, that is, ObjData objects that aren't used because they aren't
 * referenced.
 */
{
    unsigned I;

    for (I = 0; I < CollCount (&O->Files); ++I) {
        CollDeleteItem (&((FileInfo*) CollAtUnchecked (&O->Files, I))->Modules, O);
    }
    DoneCollection (&O->Files);
    DoneCollection (&O->Sections);
    for (I = 0; I < CollCount (&O->Exports); ++I) {
        FreeExport (CollAtUnchecked (&O->Exports, I));
    }
    DoneCollection (&O->Exports);
    for (I = 0; I < CollCount (&O->Imports); ++I) {
        FreeImport (CollAtUnchecked (&O->Imports, I));
    }
    DoneCollection (&O->Imports);
    DoneCollection (&O->DbgSyms);
    DoneCollection (&O->HLLDbgSyms);

    for (I = 0; I < CollCount (&O->LineInfos); ++I) {
        FreeLineInfo (CollAtUnchecked (&O->LineInfos, I));
    }
    DoneCollection (&O->LineInfos);
    xfree (O->Strings);
    DoneCollection (&O->Assertions);
    DoneCollection (&O->Scopes);
    for (I = 0; I < CollCount (&O->Spans); ++I) {
        FreeSpan (CollAtUnchecked (&O->Spans, I));
    }
    DoneCollection (&O->Spans);

    xfree (O);
}
Пример #11
0
static void FreeIf (void)
/* Free all .IF descriptors until we reach one with the NeedTerm bit set */
{
    int Done;
    do {
        IfDesc* ID = GetCurrentIf();
        if (ID == 0) {
            Error (" Unexpected .ENDIF");
            Done = 1;
        } else {
            Done = (ID->Flags & ifNeedTerm) != 0;
            ReleaseFullLineInfo (&ID->LineInfos);
            DoneCollection (&ID->LineInfos);
            --IfCount;
        }
    } while (!Done);
}
Пример #12
0
void Error (const char* Format, ...)
/* Print an error message */
{
    va_list ap;
    Collection LineInfos = STATIC_COLLECTION_INITIALIZER;

    /* Get line infos for the current position */
    GetFullLineInfo (&LineInfos);

    /* Output the message */
    va_start (ap, Format);
    ErrorMsg (&LineInfos, Format, ap);
    va_end (ap);

    /* Free the line info list */
    ReleaseFullLineInfo (&LineInfos);
    DoneCollection (&LineInfos);
}
Пример #13
0
void FreeCodeEntry (CodeEntry* E)
/* Free the given code entry */
{
    /* Free the string argument if we have one */
    FreeArg (E->Arg);

    /* Cleanup the collection */
    DoneCollection (&E->Labels);

    /* Release the line info */
    ReleaseLineInfo (E->LI);

    /* Delete the register info */
    CE_FreeRegInfo (E);

    /* Free the entry */
    xfree (E);
}
Пример #14
0
void ErrorSkip (const char* Format, ...)
/* Print an error message and skip the rest of the line */
{
    va_list ap;
    Collection LineInfos = STATIC_COLLECTION_INITIALIZER;

    /* Get line infos for the current position */
    GetFullLineInfo (&LineInfos);

    /* Output the message */
    va_start (ap, Format);
    ErrorMsg (&LineInfos, Format, ap);
    va_end (ap);

    /* Free the line info list */
    ReleaseFullLineInfo (&LineInfos);
    DoneCollection (&LineInfos);

    /* Skip tokens until we reach the end of the line */
    SkipUntilSep ();
}
Пример #15
0
void Warning (unsigned Level, const char* Format, ...)
/* Print warning message. */
{
    if (Level <= WarnLevel) {

        va_list ap;
        Collection LineInfos = STATIC_COLLECTION_INITIALIZER;

        /* Get line infos for the current position */
        GetFullLineInfo (&LineInfos);

        /* Output the message */
        va_start (ap, Format);
        WarningMsg (&LineInfos, Format, ap);
        va_end (ap);

        /* Free the line info list */
        ReleaseFullLineInfo (&LineInfos);
        DoneCollection (&LineInfos);
    }
}
Пример #16
0
void NextRawTok (void)
/* Read the next raw token from the input stream */
{
    Macro* M;

    /* If we've a forced end of assembly, don't read further */
    if (ForcedEnd) {
        CurTok.Tok = TOK_EOF;
        return;
    }

Restart:
    /* Check if we have tokens from another input source */
    if (InputFromStack ()) {
        if (CurTok.Tok == TOK_IDENT && (M = FindDefine (&CurTok.SVal)) != 0) {
            /* This is a define style macro - expand it */
            MacExpandStart (M);
            goto Restart;
        }
        return;
    }

Again:
    /* Skip whitespace, remember if we had some */
    if ((CurTok.WS = IsBlank (C)) != 0) {
        do {
            NextChar ();
        } while (IsBlank (C));
    }

    /* Mark the file position of the next token */
    Source->Func->MarkStart (Source);

    /* Clear the string attribute */
    SB_Clear (&CurTok.SVal);

    /* Generate line info for the current token */
    NewAsmLine ();

    /* Hex number or PC symbol? */
    if (C == '$') {
        NextChar ();

        /* Hex digit must follow or DollarIsPC must be enabled */
        if (!IsXDigit (C)) {
            if (DollarIsPC) {
                CurTok.Tok = TOK_PC;
                return;
            } else {
                Error ("Hexadecimal digit expected");
            }
        }

        /* Read the number */
        CurTok.IVal = 0;
        while (1) {
            if (UnderlineInNumbers && C == '_') {
                while (C == '_') {
                    NextChar ();
                }
                if (!IsXDigit (C)) {
                    Error ("Number may not end with underline");
                }
            }
            if (IsXDigit (C)) {
                if (CurTok.IVal & 0xF0000000) {
                    Error ("Overflow in hexadecimal number");
                    CurTok.IVal = 0;
                }
                CurTok.IVal = (CurTok.IVal << 4) + DigitVal (C);
                NextChar ();
            } else {
                break;
            }
        }

        /* This is an integer constant */
        CurTok.Tok = TOK_INTCON;
        return;
    }

    /* Binary number? */
    if (C == '%') {
        NextChar ();

        /* 0 or 1 must follow */
        if (!IsBDigit (C)) {
            Error ("Binary digit expected");
        }

        /* Read the number */
        CurTok.IVal = 0;
        while (1) {
            if (UnderlineInNumbers && C == '_') {
                while (C == '_') {
                    NextChar ();
                }
                if (!IsBDigit (C)) {
                    Error ("Number may not end with underline");
                }
            }
            if (IsBDigit (C)) {
                if (CurTok.IVal & 0x80000000) {
                    Error ("Overflow in binary number");
                    CurTok.IVal = 0;
                }
                CurTok.IVal = (CurTok.IVal << 1) + DigitVal (C);
                NextChar ();
            } else {
                break;
            }
        }

        /* This is an integer constant */
        CurTok.Tok = TOK_INTCON;
        return;
    }

    /* Number? */
    if (IsDigit (C)) {

        char Buf[16];
        unsigned Digits;
        unsigned Base;
        unsigned I;
        long     Max;
        unsigned DVal;

        /* Ignore leading zeros */
        while (C == '0') {
            NextChar ();
        }

        /* Read the number into Buf counting the digits */
        Digits = 0;
        while (1) {
            if (UnderlineInNumbers && C == '_') {
                while (C == '_') {
                    NextChar ();
                }
                if (!IsXDigit (C)) {
                    Error ("Number may not end with underline");
                }
            }
            if (IsXDigit (C)) {
                /* Buf is big enough to allow any decimal and hex number to
                ** overflow, so ignore excess digits here, they will be detected
                ** when we convert the value.
                */
                if (Digits < sizeof (Buf)) {
                    Buf[Digits++] = C;
                }
                NextChar ();
            } else {
                break;
            }
        }

        /* Allow zilog/intel style hex numbers with a 'h' suffix */
        if (C == 'h' || C == 'H') {
            NextChar ();
            Base = 16;
            Max  = 0xFFFFFFFFUL / 16;
        } else {
            Base = 10;
            Max  = 0xFFFFFFFFUL / 10;
        }

        /* Convert the number using the given base */
        CurTok.IVal = 0;
        for (I = 0; I < Digits; ++I) {
            if (CurTok.IVal > Max) {
                Error ("Number out of range");
                CurTok.IVal = 0;
                break;
            }
            DVal = DigitVal (Buf[I]);
            if (DVal >= Base) {
                Error ("Invalid digits in number");
                CurTok.IVal = 0;
                break;
            }
            CurTok.IVal = (CurTok.IVal * Base) + DVal;
        }

        /* This is an integer constant */
        CurTok.Tok = TOK_INTCON;
        return;
    }

    /* Control command? */
    if (C == '.') {

        /* Remember and skip the dot */
        NextChar ();

        /* Check if it's just a dot */
        if (!IsIdStart (C)) {

            /* Just a dot */
            CurTok.Tok = TOK_DOT;

        } else {

            /* Read the remainder of the identifier */
            SB_AppendChar (&CurTok.SVal, '.');
            ReadIdent ();

            /* Dot keyword, search for it */
            CurTok.Tok = FindDotKeyword ();
            if (CurTok.Tok == TOK_NONE) {

                /* Not found */
                if (!LeadingDotInIdents) {
                    /* Invalid pseudo instruction */
                    Error ("'%m%p' is not a recognized control command", &CurTok.SVal);
                    goto Again;
                }

                /* An identifier with a dot. Check if it's a define style
                ** macro.
                */
                if ((M = FindDefine (&CurTok.SVal)) != 0) {
                    /* This is a define style macro - expand it */
                    MacExpandStart (M);
                    goto Restart;
                }

                /* Just an identifier with a dot */
                CurTok.Tok = TOK_IDENT;
            }

        }
        return;
    }

    /* Indirect op for sweet16 cpu. Must check this before checking for local
    ** symbols, because these may also use the '@' symbol.
    */
    if (CPU == CPU_SWEET16 && C == '@') {
        NextChar ();
        CurTok.Tok = TOK_AT;
        return;
    }

    /* Local symbol? */
    if (C == LocalStart) {

        /* Read the identifier. */
        ReadIdent ();

        /* Start character alone is not enough */
        if (SB_GetLen (&CurTok.SVal) == 1) {
            Error ("Invalid cheap local symbol");
            goto Again;
        }

        /* A local identifier */
        CurTok.Tok = TOK_LOCAL_IDENT;
        return;
    }


    /* Identifier or keyword? */
    if (IsIdStart (C)) {

        /* Read the identifier */
        ReadIdent ();

        /* Check for special names. Bail out if we have identified the type of
        ** the token. Go on if the token is an identifier.
        */
        switch (SB_GetLen (&CurTok.SVal)) {
            case 1:
                switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {

                    case 'A':
                        if (C == ':') {
                            NextChar ();
                            CurTok.Tok = TOK_OVERRIDE_ABS;
                        } else {
                            CurTok.Tok = TOK_A;
                        }
                        return;

                    case 'F':
                        if (C == ':') {
                            NextChar ();
                            CurTok.Tok = TOK_OVERRIDE_FAR;
                            return;
                        }
                        break;

                    case 'S':
                        if ((CPU == CPU_4510) || (CPU == CPU_65816)) {
                            CurTok.Tok = TOK_S;
                            return;
                        }
                        break;

                    case 'X':
                        CurTok.Tok = TOK_X;
                        return;

                    case 'Y':
                        CurTok.Tok = TOK_Y;
                        return;

                    case 'Z':
                        if (C == ':') {
                            NextChar ();
                            CurTok.Tok = TOK_OVERRIDE_ZP;
                           return;
                        } else {
                            if (CPU == CPU_4510) {
                                CurTok.Tok = TOK_Z;
                                return;
                            }
                        }
                        break;

                    default:
                        break;
                }
                break;
            case 2:
                if ((CPU == CPU_4510) &&
                    (toupper (SB_AtUnchecked (&CurTok.SVal, 0)) == 'S') &&
                    (toupper (SB_AtUnchecked (&CurTok.SVal, 1)) == 'P')) {

                    CurTok.Tok = TOK_S;
                    return;
                }
                /* FALL THROUGH */
            default:
                if (CPU == CPU_SWEET16 &&
                   (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) {

                    /* A sweet16 register number in sweet16 mode */
                    CurTok.Tok = TOK_REG;
                    return;
                }
        }

        /* Check for define style macro */
        if ((M = FindDefine (&CurTok.SVal)) != 0) {
            /* Macro - expand it */
            MacExpandStart (M);
            goto Restart;
        } else {
            /* An identifier */
            CurTok.Tok = TOK_IDENT;
        }
        return;
    }

    /* Ok, let's do the switch */
CharAgain:
    switch (C) {

        case '+':
            NextChar ();
            CurTok.Tok = TOK_PLUS;
            return;

        case '-':
            NextChar ();
            CurTok.Tok = TOK_MINUS;
            return;

        case '/':
            NextChar ();
            if (C != '*') {
                CurTok.Tok = TOK_DIV;
            } else if (CComments) {
                /* Remember the position, then skip the '*' */
                Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
                GetFullLineInfo (&LineInfos);
                NextChar ();
                do {
                    while (C !=  '*') {
                        if (C == EOF) {
                            LIError (&LineInfos, "Unterminated comment");
                            ReleaseFullLineInfo (&LineInfos);
                            DoneCollection (&LineInfos);
                            goto CharAgain;
                        }
                        NextChar ();
                    }
                    NextChar ();
                } while (C != '/');
                NextChar ();
                ReleaseFullLineInfo (&LineInfos);
                DoneCollection (&LineInfos);
                goto Again;
            }
            return;

        case '*':
            NextChar ();
            CurTok.Tok = TOK_MUL;
            return;

        case '^':
            NextChar ();
            CurTok.Tok = TOK_XOR;
            return;

        case '&':
            NextChar ();
            if (C == '&') {
                NextChar ();
                CurTok.Tok = TOK_BOOLAND;
            } else {
                CurTok.Tok = TOK_AND;
            }
            return;

        case '|':
            NextChar ();
            if (C == '|') {
                NextChar ();
                CurTok.Tok = TOK_BOOLOR;
            } else {
                CurTok.Tok = TOK_OR;
            }
            return;

        case ':':
            NextChar ();
            switch (C) {

                case ':':
                    NextChar ();
                    CurTok.Tok = TOK_NAMESPACE;
                    break;

                case '-':
                    CurTok.IVal = 0;
                    do {
                        --CurTok.IVal;
                        NextChar ();
                    } while (C == '-');
                    CurTok.Tok = TOK_ULABEL;
                    break;

                case '+':
                    CurTok.IVal = 0;
                    do {
                        ++CurTok.IVal;
                        NextChar ();
                    } while (C == '+');
                    CurTok.Tok = TOK_ULABEL;
                    break;

                case '=':
                    NextChar ();
                    CurTok.Tok = TOK_ASSIGN;
                    break;

                default:
                    CurTok.Tok = TOK_COLON;
                    break;
            }
            return;

        case ',':
            NextChar ();
            CurTok.Tok = TOK_COMMA;
            return;

        case ';':
            NextChar ();
            while (C != '\n' && C != EOF) {
                NextChar ();
            }
            goto CharAgain;

        case '#':
            NextChar ();
            CurTok.Tok = TOK_HASH;
            return;

        case '(':
            NextChar ();
            CurTok.Tok = TOK_LPAREN;
            return;

        case ')':
            NextChar ();
            CurTok.Tok = TOK_RPAREN;
            return;

        case '[':
            NextChar ();
            CurTok.Tok = TOK_LBRACK;
            return;

        case ']':
            NextChar ();
            CurTok.Tok = TOK_RBRACK;
            return;

        case '{':
            NextChar ();
            CurTok.Tok = TOK_LCURLY;
            return;

        case '}':
            NextChar ();
            CurTok.Tok = TOK_RCURLY;
            return;

        case '<':
            NextChar ();
            if (C == '=') {
                NextChar ();
                CurTok.Tok = TOK_LE;
            } else if (C == '<') {
                NextChar ();
                CurTok.Tok = TOK_SHL;
            } else if (C == '>') {
                NextChar ();
                CurTok.Tok = TOK_NE;
            } else {
                CurTok.Tok = TOK_LT;
            }
            return;

        case '=':
            NextChar ();
            CurTok.Tok = TOK_EQ;
            return;

        case '!':
            NextChar ();
            CurTok.Tok = TOK_BOOLNOT;
            return;

        case '>':
            NextChar ();
            if (C == '=') {
                NextChar ();
                CurTok.Tok = TOK_GE;
            } else if (C == '>') {
                NextChar ();
                CurTok.Tok = TOK_SHR;
            } else {
                CurTok.Tok = TOK_GT;
            }
            return;

        case '~':
            NextChar ();
            CurTok.Tok = TOK_NOT;
            return;

        case '\'':
            /* Hack: If we allow ' as terminating character for strings, read
            ** the following stuff as a string, and check for a one character
            ** string later.
            */
            if (LooseStringTerm) {
                ReadStringConst ('\'');
                if (SB_GetLen (&CurTok.SVal) == 1) {
                    CurTok.IVal = SB_AtUnchecked (&CurTok.SVal, 0);
                    CurTok.Tok = TOK_CHARCON;
                } else {
                    CurTok.Tok = TOK_STRCON;
                }
            } else {
                /* Always a character constant */
                NextChar ();
                if (C == EOF || IsControl (C)) {
                    Error ("Illegal character constant");
                    goto CharAgain;
                }
                CurTok.IVal = C;
                CurTok.Tok = TOK_CHARCON;
                NextChar ();
                if (C != '\'') {
                    if (!MissingCharTerm) {
                        Error ("Illegal character constant");
                    }
                } else {
                    NextChar ();
                }
            }
            return;

        case '\"':
            ReadStringConst ('\"');
            CurTok.Tok = TOK_STRCON;
            return;

        case '\\':
            /* Line continuation? */
            if (LineCont) {
                NextChar ();
                /* Next char should be a LF, if not, will result in an error later */
                if (C == '\n') {
                    /* Ignore the '\n' */
                    NextChar ();
                    goto Again;
                } else {
                    /* Make it clear what the problem is: */
                    Error ("EOL expected.");
                }
            }
            break;

        case '\n':
            NextChar ();
            CurTok.Tok = TOK_SEP;
            return;

        case EOF:
            CheckInputStack ();
            /* In case of the main file, do not close it, but return EOF. */
            if (Source && Source->Next) {
                DoneCharSource ();
                goto Again;
            } else {
                CurTok.Tok = TOK_EOF;
            }
            return;
    }

    /* If we go here, we could not identify the current character. Skip it
    ** and try again.
    */
    Error ("Invalid input character: 0x%02X", C & 0xFF);
    NextChar ();
    goto Again;
}
Пример #17
0
int CE_UseLoadFlags (CodeEntry* E)
/* Return true if the instruction uses any flags that are set by a load of
** a register (N and Z).
*/
{
    /* Follow unconditional branches, but beware of endless loops. After this,
    ** E will point to the first entry that is not a branch.
    */
    if (E->Info & OF_UBRA) {
        Collection C = AUTO_COLLECTION_INITIALIZER;

        /* Follow the chain */
        while (E->Info & OF_UBRA) {

            /* Remember the entry so we can detect loops */
            CollAppend (&C, E);

            /* Check the target */
            if (E->JumpTo == 0 || CollIndex (&C, E->JumpTo->Owner) >= 0) {
                /* Unconditional jump to external symbol, or endless loop. */
                DoneCollection (&C);
                return 0;       /* Flags not used */
            }

            /* Follow the chain */
            E = E->JumpTo->Owner;
        }

        /* Delete the collection */
        DoneCollection (&C);
    }

    /* A branch will use the flags */
    if (E->Info & OF_FBRA) {
        return 1;
    }

    /* Call of a boolean transformer routine will also use the flags */
    if (E->OPC == OP65_JSR) {
        /* Get the condition that is evaluated and check it */
        switch (FindBoolCmpCond (E->Arg)) {
            case CMP_EQ:
            case CMP_NE:
            case CMP_GT:
            case CMP_GE:
            case CMP_LT:
            case CMP_LE:
            case CMP_UGT:
            case CMP_ULE:
                /* Will use the N or Z flags */
                return 1;


            case CMP_UGE:       /* Uses only carry */
            case CMP_ULT:       /* Dito */
            default:            /* No bool transformer subroutine */
                return 0;
        }
    }

    /* Anything else */
    return 0;
}