Exemple #1
0
static IfDesc* AllocIf (const char* Directive, int NeedTerm)
/* Alloc a new element from the .IF stack */
{
    IfDesc* ID;

    /* Check for stack overflow */
    if (IfCount >= MAX_IFS) {
        Fatal ("Too many nested .IFs");
    }

    /* Get the next element */
    ID = &IfStack[IfCount];

    /* Initialize elements */
    ID->Flags = NeedTerm? ifNeedTerm : ifNone;
    if (GetOverallIfCond ()) {
        /* The parents .IF condition is true */
        ID->Flags |= ifParentCond;
    }
    ID->LineInfos = EmptyCollection;
    GetFullLineInfo (&ID->LineInfos);
    ID->Name = Directive;

    /* One more slot allocated */
    ++IfCount;

    /* Return the result */
    return ID;
}
Exemple #2
0
void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
    if (S->Flags & SF_DEFINED) {
        Error ("Symbol `%m%p' is already defined", GetSymName (S));
        S->Flags |= SF_MULTDEF;
        return;
    }
    if (S->Flags & SF_EXPORT) {
        /* The symbol is already marked as exported symbol */
        Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
        return;
    }

    /* If no address size is given, use the address size of the enclosing
    ** segment.
    */
    if (AddrSize == ADDR_SIZE_DEFAULT) {
        AddrSize = GetCurrentSegAddrSize ();
    }

    /* If the symbol is marked as import or global, check the address size,
    ** then do silently remove the global flag.
    */
    if (S->Flags & SF_IMPORT) {
        if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
            Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
        }
        if (AddrSize != S->AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
    }
    if (S->Flags & SF_GLOBAL) {
        S->Flags &= ~SF_GLOBAL;
        if (AddrSize != S->AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
    }

    /* Set the symbol data */
    S->Flags |= (SF_IMPORT | Flags);
    S->AddrSize = AddrSize;

    /* Mark the position of the import as the position of the definition.
    ** Please note: In case of multiple .global or .import statements, the line
    ** infos add up.
    */
    GetFullLineInfo (&S->DefLines);
}
Exemple #3
0
static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Msg)
/* Create a new Assertion struct and return it */
{
    /* Allocate memory */
    Assertion* A = xmalloc (sizeof (Assertion));

    /* Initialize the fields */
    A->Expr     = Expr;
    A->Action   = Action;
    A->Msg      = Msg;
    A->LI       = EmptyCollection;
    GetFullLineInfo (&A->LI);

    /* Return the new struct */
    return A;
}
Exemple #4
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);
}
Exemple #5
0
Fragment* NewFragment (unsigned char Type, unsigned short Len)
/* Create, initialize and return a new fragment. The fragment will be inserted
 * into the current segment.
 */
{
    /* Create a new fragment */
    Fragment* F = xmalloc (sizeof (*F));

    /* Initialize it */
    F->Next     = 0;
    F->LineList = 0;
    F->LI       = EmptyCollection;
    GetFullLineInfo (&F->LI);
    F->Len      = Len;
    F->Type     = Type;

    /* And return it */
    return F;
}
Exemple #6
0
static ULabel* NewULabel (ExprNode* Val)
/* Create a new ULabel and insert it into the collection. The created label
 * structure is returned.
 */
{
    /* Allocate memory for the ULabel structure */
    ULabel* L = xmalloc (sizeof (ULabel));

    /* Initialize the fields */
    L->LineInfos = EmptyCollection;
    GetFullLineInfo (&L->LineInfos);
    L->Val       = Val;
    L->Ref       = 0;

    /* Insert the label into the collection */
    CollAppend (&ULabList, L);

    /* Return the created label */
    return L;
}
Exemple #7
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 ();
}
Exemple #8
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);
    }
}
Exemple #9
0
void ULabDef (void)
/* Define an unnamed label at the current PC */
{
    if (ULabDefCount < CollCount (&ULabList)) {
        /* We did already have a forward reference to this label, so has
         * already been generated, but doesn't have a value. Use the current
         * PC for the label value.
         */
        ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
        CHECK (L->Val == 0);
        L->Val = GenCurrentPC ();     
        ReleaseFullLineInfo (&L->LineInfos);
        GetFullLineInfo (&L->LineInfos);
    } else {
        /* There is no such label, create it */
        NewULabel (GenCurrentPC ());
    }

    /* We have one more defined label */
    ++ULabDefCount;
}
Exemple #10
0
void DoConditionals (void)
/* Catch all for conditional directives */
{
    IfDesc* D;

    do {

        switch (CurTok.Tok) {

            case TOK_ELSE:
                D = GetCurrentIf ();

                /* Allow an .ELSE */
                ElseClause (D, ".ELSE");

                /* Remember the data for the .ELSE */
                if (D) {
                    ReleaseFullLineInfo (&D->LineInfos);
                    GetFullLineInfo (&D->LineInfos);
                    D->Name = ".ELSE";
                }

                /* Calculate the new overall condition */
                CalcOverallIfCond ();

                /* Skip .ELSE */
                NextTok ();
                ExpectSep ();
                break;

            case TOK_ELSEIF:
                D = GetCurrentIf ();
                /* Handle as if there was an .ELSE first */
                ElseClause (D, ".ELSEIF");

                /* Calculate the new overall if condition */
                CalcOverallIfCond ();

                /* Allocate and prepare a new descriptor */
                D = AllocIf (".ELSEIF", 0);
                NextTok ();

                /* Ignore the new condition if we are inside a false .ELSE
                ** branch. This way we won't get any errors about undefined
                ** symbols or similar...
                */
                if (IfCond) {
                    SetIfCond (D, ConstExpression ());
                    ExpectSep ();
                }

                /* Get the new overall condition */
                CalcOverallIfCond ();
                break;

            case TOK_ENDIF:
                /* We're done with this .IF.. - remove the descriptor(s) */
                FreeIf ();

                /* Be sure not to read the next token until the .IF stack
                ** has been cleanup up, since we may be at end of file.
                */
                NextTok ();
                ExpectSep ();

                /* Get the new overall condition */
                CalcOverallIfCond ();
                break;

            case TOK_IF:
                D = AllocIf (".IF", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, ConstExpression ());
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFBLANK:
                D = AllocIf (".IFBLANK", 1);
                NextTok ();
                if (IfCond) {
                    if (TokIsSep (CurTok.Tok)) {
                        SetIfCond (D, 1);
                    } else {
                        SetIfCond (D, 0);
                        SkipUntilSep ();
                    }
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFCONST:
                D = AllocIf (".IFCONST", 1);
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
                    SetIfCond (D, IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFDEF:
                D = AllocIf (".IFDEF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym != 0 && SymIsDef (Sym));
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNBLANK:
                D = AllocIf (".IFNBLANK", 1);
                NextTok ();
                if (IfCond) {
                    if (TokIsSep (CurTok.Tok)) {
                        SetIfCond (D, 0);
                    } else {
                        SetIfCond (D, 1);
                        SkipUntilSep ();
                    }
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNCONST:
                D = AllocIf (".IFNCONST", 1);
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
                    SetIfCond (D, !IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNDEF:
                D = AllocIf (".IFNDEF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNREF:
                D = AllocIf (".IFNREF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFP02:
                D = AllocIf (".IFP02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_6502);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFP4510:
                D = AllocIf (".IFP4510", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_4510);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFP816:
                D = AllocIf (".IFP816", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65816);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFPC02:
                D = AllocIf (".IFPC02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65C02);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFPSC02:
                D = AllocIf (".IFPSC02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65SC02);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFREF:
                D = AllocIf (".IFREF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym != 0 && SymIsRef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            default:
                /* Skip tokens */
                NextTok ();

        }

    } while (IfCond == 0 && CurTok.Tok != TOK_EOF);
}
Exemple #11
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;
}
Exemple #12
0
static void SymCheckUndefined (SymEntry* S)
/* Handle an undefined symbol */
{
    /* Undefined symbol. It may be...
    **
    **   - An undefined symbol in a nested lexical level. If the symbol is not
    **     fixed to this level, search for the symbol in the higher levels and
    **     make the entry a trampoline entry if we find one.
    **
    **   - If the symbol is not found, it is a real undefined symbol. If the
    **     AutoImport flag is set, make it an import. If the AutoImport flag is
    **     not set, it's an error.
    */
    SymEntry* Sym = 0;
    if ((S->Flags & SF_FIXED) == 0) {
        SymTable* Tab = GetSymParentScope (S);
        while (Tab) {
            Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY);
            if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
                /* We've found a symbol in a higher level that is
                ** either defined in the source, or an import.
                */
                 break;
            }
            /* No matching symbol found in this level. Look further */
            Tab = Tab->Parent;
        }
    }

    if (Sym) {

        /* We found the symbol in a higher level. Transfer the flags and
        ** address size from the local symbol to that in the higher level
        ** and check for problems.
        */
        if (S->Flags & SF_EXPORT) {
            if (Sym->Flags & SF_IMPORT) {
                /* The symbol is already marked as import */
                LIError (&S->RefLines,
                         "Symbol `%s' is already an import",
                         GetString (Sym->Name));
            }
            if ((Sym->Flags & SF_EXPORT) == 0) {
                /* Mark the symbol as an export */
                Sym->Flags |= SF_EXPORT;
                Sym->ExportSize = S->ExportSize;
                if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
                    /* Use the actual size of the symbol */
                    Sym->ExportSize = Sym->AddrSize;
                }
                if (Sym->AddrSize > Sym->ExportSize) {
                    /* We're exporting a symbol smaller than it actually is */
                    LIWarning (&Sym->DefLines, 1,
                               "Symbol `%m%p' is %s but exported %s",
                               GetSymName (Sym),
                               AddrSizeToStr (Sym->AddrSize),
                               AddrSizeToStr (Sym->ExportSize));
                }
            }
        }
        if (S->Flags & SF_REFERENCED) {
            /* Mark as referenced and move the line info */
            Sym->Flags |= SF_REFERENCED;
            CollTransfer (&Sym->RefLines, &S->RefLines);
            CollDeleteAll (&S->RefLines);
        }

        /* Transfer all expression references */
        SymTransferExprRefs (S, Sym);

        /* Mark the symbol as unused removing all other flags */
        S->Flags = SF_UNUSED;

    } else {
        /* The symbol is definitely undefined */
        if (S->Flags & SF_EXPORT) {
            /* We will not auto-import an export */
            LIError (&S->RefLines,
                     "Exported symbol `%m%p' was never defined",
                     GetSymName (S));
        } else {
            if (AutoImport) {
                /* Mark as import, will be indexed later */
                S->Flags |= SF_IMPORT;
                /* Use the address size for code */
                S->AddrSize = CodeAddrSize;
                /* Mark point of import */
                GetFullLineInfo (&S->DefLines);
            } else {
                /* Error */
                LIError (&S->RefLines,
                         "Symbol `%m%p' is undefined",
                         GetSymName (S));
            }
        }
    }
}
Exemple #13
0
void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as a global symbol, that is, as a symbol that is
** either imported or exported.
*/
{
    if (S->Flags & SF_VAR) {
        /* Variable symbols cannot be exported or imported */
        Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
        return;
    }

    /* If the symbol is already marked as import, the address size must match.
    ** Apart from that, ignore the global declaration.
    */
    if (S->Flags & SF_IMPORT) {
        if (AddrSize == ADDR_SIZE_DEFAULT) {
            /* Use the size of the current segment */
            AddrSize = GetCurrentSegAddrSize ();
        }
        if (AddrSize != S->AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        return;
    }

    /* If the symbol is already an export: If it is not defined, the address
    ** sizes must match.
    */
    if (S->Flags & SF_EXPORT) {
        if ((S->Flags & SF_DEFINED) == 0) {
            /* Symbol is undefined */
            if (AddrSize != S->ExportSize) {
                Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
            }
        } else if (AddrSize != ADDR_SIZE_DEFAULT) {
            /* Symbol is defined and address size given */
            if (AddrSize != S->ExportSize) {
                Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
            }
        }
        return;
    }

    /* If the symbol is already marked as global, the address size must match.
    ** Use the ExportSize here, since it contains the actual address size
    ** passed to this function.
    */
    if (S->Flags & SF_GLOBAL) {
        if (AddrSize != S->ExportSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        return;
    }

    /* If we come here, the symbol was neither declared as export, import or
    ** global before. Check if it is already defined, in which case it will
    ** become an export. If it is not defined, mark it as global and remember
    ** the given address sizes.
    */
    if (S->Flags & SF_DEFINED) {
        /* The symbol is defined, export it */
        S->ExportSize = AddrSize;
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* No export size given, use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize > S->ExportSize) {
            /* We're exporting a symbol smaller than it actually is */
            Warning (1, "Symbol `%m%p' is %s but exported %s",
                     GetSymName (S), AddrSizeToStr (S->AddrSize),
                     AddrSizeToStr (S->ExportSize));
        }
        S->Flags |= (SF_EXPORT | Flags);
    } else {
        /* Since we don't know if the symbol will get exported or imported,
        ** remember two different address sizes: One for an import in AddrSize,
        ** and the other one for an export in ExportSize.
        */
        S->AddrSize = AddrSize;
        if (S->AddrSize == ADDR_SIZE_DEFAULT) {
            /* Use the size of the current segment */
            S->AddrSize = GetCurrentSegAddrSize ();
        }
        S->ExportSize = AddrSize;
        S->Flags |= (SF_GLOBAL | Flags);

        /* Remember the current location as location of definition in case
        ** an .IMPORT follows later.
        */
        GetFullLineInfo (&S->DefLines);
    }
}
Exemple #14
0
void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
/* Define a new symbol */
{
    if (S->Flags & SF_IMPORT) {
        /* Defined symbol is marked as imported external symbol */
        Error ("Symbol `%m%p' is already an import", GetSymName (S));
        return;
    }
    if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
        /* Variable symbols cannot be exports or globals */
        Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
        return;
    }
    if (S->Flags & SF_DEFINED) {
        /* Multiple definition. In case of a variable, this is legal. */
        if ((S->Flags & SF_VAR) == 0) {
            Error ("Symbol `%m%p' is already defined", GetSymName (S));
            S->Flags |= SF_MULTDEF;
            return;
        } else {
            /* Redefinition must also be a variable symbol */
            if ((Flags & SF_VAR) == 0) {
                Error ("Symbol `%m%p' is already different kind", GetSymName (S));
                return;
            }
            /* Delete the current symbol expression, since it will get
            ** replaced
            */
            FreeExpr (S->Expr);
            S->Expr = 0;
        }
    }

    /* Map a default address size to a real value */
    if (AddrSize == ADDR_SIZE_DEFAULT) {
        /* ### Must go! Delay address size calculation until end of assembly! */
        ExprDesc ED;
        ED_Init (&ED);
        StudyExpr (Expr, &ED);
        AddrSize = ED.AddrSize;
        ED_Done (&ED);
    }

    /* Set the symbol value */
    S->Expr = Expr;

    /* In case of a variable symbol, walk over all expressions containing
    ** this symbol and replace the (sub-)expression by the literal value of
    ** the tree. Be sure to replace the expression node in place, since there
    ** may be pointers to it.
    */
    if (Flags & SF_VAR) {
        SymReplaceExprRefs (S);
    }

    /* If the symbol is marked as global, export it. Address size is checked
    ** below.
    */
    if (S->Flags & SF_GLOBAL) {
        S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
        ReleaseFullLineInfo (&S->DefLines);
    }

    /* Mark the symbol as defined and use the given address size */
    S->Flags |= (SF_DEFINED | Flags);
    S->AddrSize = AddrSize;

    /* Remember the line info of the symbol definition */
    GetFullLineInfo (&S->DefLines);

    /* If the symbol is exported, check the address sizes */
    if (S->Flags & SF_EXPORT) {
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* Use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize > S->ExportSize) {
            /* We're exporting a symbol smaller than it actually is */
            Warning (1, "Symbol `%m%p' is %s but exported %s",
                     GetSymName (S), AddrSizeToStr (S->AddrSize),
                     AddrSizeToStr (S->ExportSize));
        }
    }

    /* If this is not a local symbol, remember it as the last global one */
    if ((S->Flags & SF_LOCAL) == 0) {
        SymLast = S;
    }
}
Exemple #15
0
void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
/* Mark the given symbol as a module constructor/destructor. This will also
 * mark the symbol as an export. Initializers may never be zero page symbols.
 */
{
    /* Check the parameters */
#if (CD_TYPE_MIN != 0)
    CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
#else
    CHECK (Type <= CD_TYPE_MAX);
#endif
    CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);

    /* Check for errors */
    if (S->Flags & SF_IMPORT) {
       	/* The symbol is already marked as imported external symbol */
       	Error ("Symbol `%m%p' is already an import", GetSymName (S));
       	return;
    }
    if (S->Flags & SF_VAR) {
        /* Variable symbols cannot be exported or imported */
        Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
        return;
    }

    /* If the symbol was already marked as an export or global, check if
     * this was done specifiying the same address size. In case of a global
     * declaration, silently remove the global flag.
     */
    if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
        if (S->ExportSize != AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        S->Flags &= ~SF_GLOBAL;
    }
    S->ExportSize = AddrSize;

    /* If the symbol is already defined, check symbol size against the
     * exported size.
     */
    if (S->Flags & SF_DEFINED) {
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* Use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize != S->ExportSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
    }

    /* If the symbol was already declared as a condes, check if the new
     * priority value is the same as the old one.
     */
    if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
 	if (S->ConDesPrio[Type] != Prio) {
 	    Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
 	}
    }
    S->ConDesPrio[Type] = Prio;

    /* Set the symbol data */
    S->Flags |= (SF_EXPORT | SF_REFERENCED);

    /* In case we have no line info for the definition, record it now */
    if (CollCount (&S->DefLines) == 0) {
        GetFullLineInfo (&S->DefLines);
    }
}