Пример #1
0
static void CheckSymTable (SymTable* Tab)
/* Check a symbol table for open references, unused symbols ... */
{
    SymEntry* Entry = Tab->SymHead;
    while (Entry) {

        /* Get the storage flags for tne entry */
        unsigned Flags = Entry->Flags;

        /* Ignore typedef entries */
        if (!SymIsTypeDef (Entry)) {

            /* Check if the symbol is one with storage, and it if it was
            ** defined but not used.
            */
            if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
                if (SymIsDef (Entry) && !SymIsRef (Entry) &&
                    !SymHasAttr (Entry, atUnused)) {
                    if (Flags & SC_PARAM) {
                        if (IS_Get (&WarnUnusedParam)) {
                            Warning ("Parameter `%s' is never used", Entry->Name);
                        }
                    } else {
                        if (IS_Get (&WarnUnusedVar)) {
                            Warning ("`%s' is defined but never used", Entry->Name);
                        }
                    }
                }
            }

            /* If the entry is a label, check if it was defined in the function */
            if (Flags & SC_LABEL) {
                if (!SymIsDef (Entry)) {
                    /* Undefined label */
                    Error ("Undefined label: `%s'", Entry->Name);
                } else if (!SymIsRef (Entry)) {
                    /* Defined but not used */
                    if (IS_Get (&WarnUnusedLabel)) {
                        Warning ("`%s' is defined but never used", Entry->Name);
                    }
                }
            }

        }

        /* Next entry */
        Entry = Entry->NextSym;
    }
}
Пример #2
0
static void NewSymbol (const char* SymName, long Val)
/* Define a symbol with a fixed numeric value in the current scope */
{
    ExprNode* Expr;
    SymEntry* Sym;

    /* Convert the name to a string buffer */
    StrBuf SymBuf = STATIC_STRBUF_INITIALIZER;
    SB_CopyStr (&SymBuf, SymName);

    /* Search for the symbol, allocate a new one if it doesn't exist */
    Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW);

    /* Check if have already a symbol with this name */
    if (SymIsDef (Sym)) {
        AbEnd ("`%s' is already defined", SymName);
    }

    /* Generate an expression for the symbol */
    Expr = GenLiteralExpr (Val);

    /* Mark the symbol as defined */
    SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);

    /* Free string buffer memory */
    SB_Done (&SymBuf);
}
Пример #3
0
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
/* Add a goto label to the label table */
{
    /* Do we have an entry with this name already? */
    SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
    if (Entry) {

        if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) {
            /* Trying to define the label more than once */
            Error ("Label `%s' is defined more than once", Name);
        }
        Entry->Flags |= Flags;

    } else {

        /* Create a new entry */
        Entry = NewSymEntry (Name, SC_LABEL | Flags);

        /* Set a new label number */
        Entry->V.Label = GetLocalLabel ();

        /* Generate the assembler name of the label */
        Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));

        /* Add the entry to the label table */
        AddSymEntry (LabelTab, Entry);

    }

    /* Return the entry */
    return Entry;
}
Пример #4
0
void EmitExternals (void)
/* Write import/export statements for external symbols */
{
    SymEntry* Entry;

    Entry = SymTab->SymHead;
    while (Entry) {
        unsigned Flags = Entry->Flags;
        if (Flags & SC_EXTERN) {
            /* Only defined or referenced externs */
            if (SymIsRef (Entry) && !SymIsDef (Entry)) {
                /* An import */
                g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
            } else if (SymIsDef (Entry)) {
                /* An export */
                g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
            }
        }
        Entry = Entry->NextSym;
    }
}
Пример #5
0
void EmitDebugInfo (void)
/* Emit debug infos for the locals of the current scope */
{
    const char* Head;
    const SymEntry* Sym;

    /* Output info for locals if enabled */
    if (DebugInfo) {
        /* For cosmetic reasons in the output file, we will insert two tabs
        ** on global level and just one on local level.
        */
        if (LexicalLevel == LEX_LEVEL_GLOBAL) {
            Head = "\t.dbg\t\tsym";
        } else {
            Head = "\t.dbg\tsym";
        }
        Sym = SymTab->SymHead;
        while (Sym) {
            if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
                if (Sym->Flags & SC_AUTO) {
                    AddTextLine ("%s, \"%s\", \"00\", auto, %d",
                                 Head, Sym->Name, Sym->V.Offs);
                } else if (Sym->Flags & SC_REGISTER) {
                    AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
                                 Head, Sym->Name, Sym->V.R.RegOffs);

                } else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
                    AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
                                 Head, Sym->Name,
                                 (Sym->Flags & SC_EXTERN)? "extern" : "static",
                                 Sym->AsmName);
                }
            }
            Sym = Sym->NextSym;
        }
    }
}
Пример #6
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);
}
Пример #7
0
Файл: struct.c Проект: cc65/cc65
static long DoStructInternal (long Offs, unsigned Type)
/* Handle the .STRUCT command */
{
    long Size = 0;

    /* Outside of other structs, we need a name. Inside another struct or
    ** union, the struct may be anonymous, in which case no new lexical level
    ** is started.
    */
    int Anon = (CurTok.Tok != TOK_IDENT);
    if (!Anon) {
        /* Enter a new scope, then skip the name */
        SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
        NextTok ();
        /* Start at zero offset in the new scope */
        Offs = 0;
    }

    /* Test for end of line */
    ConsumeSep ();

    /* Read until end of struct */
    while (CurTok.Tok != TOK_ENDSTRUCT &&
           CurTok.Tok != TOK_ENDUNION  &&
           CurTok.Tok != TOK_EOF) {

        long      MemberSize;
        SymTable* Struct;
        SymEntry* Sym;

        /* Allow empty and comment lines */
        if (CurTok.Tok == TOK_SEP) {
            NextTok ();
            continue;
        }

        /* The format is "[identifier] storage-allocator [, multiplicator]" */
        Sym = 0;
        if (CurTok.Tok == TOK_IDENT) {

            /* Beware: An identifier may also be a macro, in which case we have
            ** to start over.
            */
            Macro* M = FindMacro (&CurTok.SVal);
            if (M) {
                MacExpandStart (M);
                continue;
            }

            /* We have an identifier, generate a symbol */
            Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW);

            /* Assign the symbol the offset of the current member */
            SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE);

            /* Skip the member name */
            NextTok ();
        }

        /* Read storage allocators */
        MemberSize = 0;                 /* In case of errors, use zero */
        switch (CurTok.Tok) {

            case TOK_BYTE:
                NextTok ();
                MemberSize = Member (1);
                break;

            case TOK_DBYT:
            case TOK_WORD:
            case TOK_ADDR:
                NextTok ();
                MemberSize = Member (2);
                break;

            case TOK_FARADDR:
                NextTok ();
                MemberSize = Member (3);
                break;

            case TOK_DWORD:
                NextTok ();
                MemberSize = Member (4);
                break;

            case TOK_RES:
                NextTok ();
                if (CurTok.Tok == TOK_SEP) {
                    ErrorSkip ("Size is missing");
                } else {
                    MemberSize = Member (1);
                }
                break;

            case TOK_TAG:
                NextTok ();
                Struct = ParseScopedSymTable ();
                if (Struct == 0) {
                    ErrorSkip ("Unknown struct/union");
                } else if (GetSymTabType (Struct) != SCOPE_STRUCT) {
                    ErrorSkip ("Not a struct/union");
                } else {
                    SymEntry* SizeSym = GetSizeOfScope (Struct);
                    if (!SymIsDef (SizeSym) || !SymIsConst (SizeSym, &MemberSize)) {
                        ErrorSkip ("Size of struct/union is unknown");
                    }
                }
                MemberSize = Member (MemberSize);
                break;

            case TOK_STRUCT:
                NextTok ();
                MemberSize = DoStructInternal (Offs, STRUCT);
                break;

            case TOK_UNION:
                NextTok ();
                MemberSize = DoStructInternal (Offs, UNION);
                break;

            default:
                if (!CheckConditionals ()) {
                    /* Not a conditional directive */
                    ErrorSkip ("Invalid storage allocator in struct/union");
                }
        }

        /* Assign the size to the member if it has a name */
        if (Sym) {
            DefSizeOfSymbol (Sym, MemberSize);
        }

        /* Next member */
        if (Type == STRUCT) {
            /* Struct */
            Offs += MemberSize;
            Size += MemberSize;
        } else {
            /* Union */
            if (MemberSize > Size) {
                Size = MemberSize;
            }
        }

        /* Expect end of line */
        ConsumeSep ();
    }

    /* If this is not a anon struct, enter a special symbol named ".size"
    ** into the symbol table of the struct that holds the size of the
    ** struct. Since the symbol starts with a dot, it cannot be accessed
    ** by user code.
    ** Leave the struct scope level.
    */
    if (!Anon) {
        /* Add a symbol */
        SymEntry* SizeSym = GetSizeOfScope (CurrentScope);
        SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE);

        /* Close the struct scope */
        SymLeaveLevel ();
    }

    /* End of struct/union definition */
    if (Type == STRUCT) {
        Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected");
    } else {
        Consume (TOK_ENDUNION, "'.ENDUNION' expected");
    }

    /* Return the size of the struct */
    return Size;
}