예제 #1
0
파일: dbginfo.c 프로젝트: cc65/cc65
void DbgInfoLine (void)
/* Parse and handle LINE subcommand of the .dbg pseudo instruction */
{
    long Line;
    FilePos Pos = STATIC_FILEPOS_INITIALIZER;

    /* Any new line info terminates the last one */
    if (CurLineInfo) {
        EndLine (CurLineInfo);
        CurLineInfo = 0;
    }

    /* If a parameters follow, this is actual line info. If no parameters
    ** follow, the last line info is terminated.
    */
    if (CurTok.Tok == TOK_SEP) {
        return;
    }

    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* The name of the file follows */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }

    /* Get the index in the file table for the name */
    Pos.Name = GetFileIndex (&CurTok.SVal);

    /* Skip the name */
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Line number */
    Line = ConstExpression ();
    if (Line < 0) {
        ErrorSkip ("Line number is out of valid range");
        return;
    }
    Pos.Line = Line;

    /* Generate a new external line info */
    CurLineInfo = StartLine (&Pos, LI_TYPE_EXT, 0);
}
예제 #2
0
파일: repeat.c 프로젝트: Aliandrana/snesdev
void ParseRepeat (void)
/* Parse and handle the .REPEAT statement */
{
    char* Name;
    TokList* List;

    /* Repeat count follows */
    long RepCount = ConstExpression ();
    if (RepCount < 0) {
	Error ("Range error");
	RepCount = 0;
    }

    /* Optional there is a comma and a counter variable */
    Name = 0;
    if (Tok == TOK_COMMA) {

       	/* Skip the comma */
       	NextTok ();

       	/* Check for an identifier */
       	if (Tok != TOK_IDENT) {
       	    ErrorSkip ("Identifier expected");
       	} else {
       	    /* Remember the name and skip it */
            SB_Terminate (&SVal);
       	    Name = xstrdup (SB_GetConstBuf (&SVal));
       	    NextTok ();
       	}
    }

    /* Separator */
    ConsumeSep ();

    /* Read the token list */
    List = CollectRepeatTokens ();

    /* If we had an error, bail out */
    if (List == 0) {
	xfree (Name);
       	return;
    }

    /* Update the token list for replay */
    List->RepMax = (unsigned) RepCount;
    List->Data   = Name;
    List->Check  = RepeatTokenCheck;

    /* If the list is empty, or repeat count zero, there is nothing
     * to repeat.
     */
    if (List->Count == 0 || RepCount == 0) {
     	FreeTokList (List);
	return;
    }

    /* Read input from the repeat descriptor */
    PushTokList (List, ".REPEAT");
}
예제 #3
0
void ExpectSep (void)
/* Check if we've reached a line separator, and output an error if not. Do
 * not skip the line separator.
 */
{
    if (!TokIsSep (CurTok.Tok)) {
        ErrorSkip ("Unexpected trailing garbage characters");
    }
}
예제 #4
0
파일: dbginfo.c 프로젝트: cc65/cc65
static int ValidateType (StrBuf* Type)
/* Check if the given type is valid and if so, return a string id for it. If
** the type isn't valid, return -1. Type is overwritten when checking.
*/
{
    unsigned        I;
    const char*     A;
    char*           B;


    /* The length must not be zero and divideable by two */
    unsigned Length = SB_GetLen (Type);
    if (Length < 2 || (Length & 0x01) != 0) {
        ErrorSkip ("Type value has invalid length");
        return -1;
    }

    /* The string must consist completely of hex digit chars */
    A = SB_GetConstBuf (Type);
    for (I = 0; I < Length; ++I) {
        if (!IsXDigit (A[I])) {
            ErrorSkip ("Type value contains invalid characters");
            return -1;
        }
    }

    /* Convert the type to binary */
    B = SB_GetBuf (Type);
    while (A < SB_GetConstBuf (Type) + Length) {
        /* Since we know, there are only hex digits, there can't be any errors */
        *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]);
        A += 2;
    }
    Type->Len = (Length /= 2);

    /* Allocate the type and return it */
    return GetStrBufId (Type);
}
예제 #5
0
파일: struct.c 프로젝트: cc65/cc65
static long Member (long AllocSize)
/* Read one struct member and return its size */
{
    long Multiplicator;

    /* A multiplicator may follow */
    if (CurTok.Tok != TOK_SEP) {
        Multiplicator = ConstExpression ();
        if (Multiplicator <= 0) {
            ErrorSkip ("Range error");
            Multiplicator = 1;
        }
        AllocSize *= Multiplicator;
    }

    /* Check the size for a reasonable value */
    if (AllocSize >= 0x10000) {
        ErrorSkip ("Range error");
    }

    /* Return the size */
    return AllocSize;
}
예제 #6
0
파일: dbginfo.c 프로젝트: cc65/cc65
void DbgInfoFile (void)
/* Parse and handle FILE subcommand of the .dbg pseudo instruction */
{
    StrBuf Name = STATIC_STRBUF_INITIALIZER;
    unsigned long Size;
    unsigned long MTime;

    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* Name */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    SB_Copy (&Name, &CurTok.SVal);
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Size */
    Size = ConstExpression ();

    /* Comma expected */
    ConsumeComma ();

    /* MTime */
    MTime = ConstExpression ();

    /* Insert the file into the table */
    AddFile (&Name, FT_DBGINFO, Size, MTime);

    /* Free memory used for Name */
    SB_Done (&Name);
}
예제 #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;
}
예제 #8
0
파일: declattr.c 프로젝트: Aliandrana/cc65
void ParseAttribute (Declaration* D)
/* Parse an additional __attribute__ modifier */
{
    /* Do we have an attribute? */
    if (CurTok.Tok != TOK_ATTRIBUTE) {
        /* No attribute, bail out */
        return;
    }

    /* Skip the attribute token */
    NextToken ();

    /* Expect two(!) open braces */
    ConsumeLParen ();
    ConsumeLParen ();

    /* Read a list of attributes */
    while (1) {

        ident           AttrName;
        const AttrDesc* Attr = 0;

        /* Identifier follows */
        if (CurTok.Tok != TOK_IDENT) {

            /* No attribute name */
            Error ("Attribute name expected");

            /* Skip until end of attribute */
            ErrorSkip ();

            /* Bail out */
            return;
        }

        /* Map the attribute name to its id, then skip the identifier */
        strcpy (AttrName, CurTok.Ident);
        Attr = FindAttribute (AttrName);
        NextToken ();

        /* Did we find a valid attribute? */
        if (Attr) {

            /* Call the handler */
            Attr->Handler (D);

        } else {
            /* Attribute not known, maybe typo */
            Error ("Illegal attribute: `%s'", AttrName);

            /* Skip until end of attribute */
            ErrorSkip ();

            /* Bail out */
            return;
        }

        /* If a comma follows, there's a next attribute. Otherwise this is the
        ** end of the attribute list.
        */
        if (CurTok.Tok != TOK_COMMA) {
            break;
        }
        NextToken ();
    }

    /* The declaration is terminated with two closing braces */
    ConsumeRParen ();
    ConsumeRParen ();
}
예제 #9
0
파일: dbginfo.c 프로젝트: cc65/cc65
void DbgInfoSym (void)
/* Parse and handle SYM subcommand of the .dbg pseudo instruction */
{
    static const char* const StorageKeys[] = {
        "AUTO",
        "EXTERN",
        "REGISTER",
        "STATIC",
    };

    unsigned    Name;
    int         Type;
    unsigned    AsmName = EMPTY_STRING_ID;
    unsigned    Flags;
    int         Offs = 0;
    HLLDbgSym*  S;


    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* Name */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Name = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Type */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Type = ValidateType (&CurTok.SVal);
    if (Type < 0) {
        return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* The storage class follows */
    if (CurTok.Tok != TOK_IDENT) {
        ErrorSkip ("Storage class specifier expected");
        return;
    }
    switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) {
        case 0:   Flags = HLL_SC_AUTO;                              break;
        case 1:   Flags = HLL_SC_EXTERN;                            break;
        case 2:   Flags = HLL_SC_REG;                               break;
        case 3:   Flags = HLL_SC_STATIC;                            break;
        default:  ErrorSkip ("Storage class specifier expected");   return;
    }

    /* Skip the storage class token and the following comma */
    NextTok ();
    ConsumeComma ();

    /* The next tokens depend on the storage class */
    if (Flags == HLL_SC_AUTO) {
        /* Auto: Stack offset follows */
        Offs = ConstExpression ();
    } else {
        /* Register, extern or static: Assembler name follows */
        if (CurTok.Tok != TOK_STRCON) {
            ErrorSkip ("String constant expected");
            return;
        }
        AsmName = GetStrBufId (&CurTok.SVal);
        NextTok ();

        /* For register, an offset follows */
        if (Flags == HLL_SC_REG) {
            ConsumeComma ();
            Offs = ConstExpression ();
        }
    }

    /* Add the function */
    S = NewHLLDbgSym (Flags | HLL_TYPE_SYM, Name, Type);
    S->AsmName = AsmName;
    S->Offs    = Offs;
    CollAppend (&HLLDbgSyms, S);
}
예제 #10
0
파일: dbginfo.c 프로젝트: cc65/cc65
void DbgInfoFunc (void)
/* Parse and handle func subcommand of the .dbg pseudo instruction */
{
    static const char* const StorageKeys[] = {
        "EXTERN",
        "STATIC",
    };

    unsigned    Name;
    int         Type;
    unsigned    AsmName;
    unsigned    Flags;
    HLLDbgSym*  S;


    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* Name */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Name = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Type */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Type = ValidateType (&CurTok.SVal);
    if (Type < 0) {
        return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* The storage class follows */
    if (CurTok.Tok != TOK_IDENT) {
        ErrorSkip ("Storage class specifier expected");
        return;
    }
    switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) {
        case 0:   Flags = HLL_TYPE_FUNC | HLL_SC_EXTERN;            break;
        case 1:   Flags = HLL_TYPE_FUNC | HLL_SC_STATIC;            break;
        default:  ErrorSkip ("Storage class specifier expected");   return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Assembler name follows */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    AsmName = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* There may only be one function per scope */
    if (CurrentScope == RootScope) {
        ErrorSkip ("Functions may not be used in the root scope");
        return;
    } else if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) {
        ErrorSkip ("Functions can only be tagged to .PROC scopes");
        return;
    } else if (CurrentScope->Label->HLLSym != 0) {
        ErrorSkip ("Only one HLL symbol per asm symbol is allowed");
        return;
    } else if (CurrentScope->Label->Name != AsmName) {
        ErrorSkip ("Scope label and asm name for function must match");
        return;
    }

    /* Add the function */
    S = NewHLLDbgSym (Flags, Name, Type);
    S->Sym = CurrentScope->Label;
    CurrentScope->Label->HLLSym = S;
    CollAppend (&HLLDbgSyms, S);
}
예제 #11
0
static void StartExpDefine (MacExp* E)
/* Start expanding a DEFINE style macro */
{
    /* A define style macro must be called with as many actual parameters
     * as there are formal ones. Get the parameter count.
     */
    unsigned Count = E->M->ParamCount;

    /* Skip the current token */
    NextTok ();

    /* Read the actual parameters */
    while (Count--) {

        TokNode*   Last;

        /* The macro may optionally be enclosed in curly braces */
        token_t Term = GetTokListTerm (TOK_COMMA);

        /* Check if there is really a parameter */
        if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
            ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
            FreeMacExp (E);
            return;
        }

        /* Read tokens for one parameter */
        Last = 0;
        do {

            TokNode* T;

            /* Get the next token in a node */
            T = NewTokNode ();

            /* Insert it into the list */
            if (Last == 0) {
                E->Params [E->ParamCount] = T;
            } else {
                Last->Next = T;
            }
            Last = T;

            /* And skip it... */
            NextTok ();

        } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));

        /* One parameter more */
        ++E->ParamCount;

        /* If the macro argument was enclosed in curly braces, end-of-line
         * is an error. Skip the closing curly brace.
         */
        if (Term == TOK_RCURLY) {
            if (TokIsSep (CurTok.Tok)) {
                Error ("End of line encountered within macro argument");
                break;
            }
            NextTok ();
        }

        /* Check for a comma */
        if (Count > 0) {
            if (CurTok.Tok == TOK_COMMA) {
                NextTok ();
            } else {
                Error ("`,' expected");
            }
        }
    }

    /* Macro expansion will overwrite the current token. This is a problem
     * for define style macros since these are called from the scanner level.
     * To avoid it, remember the current token and re-insert it, once macro
     * expansion is done.
     */
    E->Final = NewTokNode ();

    /* Insert a new token input function */
    PushInput (MacExpand, E, ".DEFINE");
}
예제 #12
0
static void StartExpClassic (MacExp* E)
/* Start expanding a classic macro */
{
    token_t     Term;

    /* Skip the macro name */
    NextTok ();

    /* Read the actual parameters */
    while (!TokIsSep (CurTok.Tok)) {

        TokNode* Last;

        /* Check for maximum parameter count */
        if (E->ParamCount >= E->M->ParamCount) {
            ErrorSkip ("Too many macro parameters");
            break;
        }

        /* The macro may optionally be enclosed in curly braces */
        Term = GetTokListTerm (TOK_COMMA);

        /* Read tokens for one parameter, accept empty params */
        Last = 0;
        while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {

            TokNode* T;

            /* Check for end of file */
            if (CurTok.Tok == TOK_EOF) {
                Error ("Unexpected end of file");
                FreeMacExp (E);
                return;
            }

            /* Get the next token in a node */
            T = NewTokNode ();

            /* Insert it into the list */
            if (Last == 0) {
                E->Params [E->ParamCount] = T;
            } else {
                Last->Next = T;
            }
            Last = T;

            /* And skip it... */
            NextTok ();
        }

        /* One parameter more */
        ++E->ParamCount;

        /* If the macro argument was enclosed in curly braces, end-of-line
         * is an error. Skip the closing curly brace.
         */
        if (Term == TOK_RCURLY) {
            if (CurTok.Tok == TOK_SEP) {
                Error ("End of line encountered within macro argument");
                break;
            }
            NextTok ();
        }

        /* Check for a comma */
        if (CurTok.Tok == TOK_COMMA) {
            NextTok ();
        } else {
            break;
        }
    }

    /* We must be at end of line now, otherwise something is wrong */
    ExpectSep ();

    /* Insert a new token input function */
    PushInput (MacExpand, E, ".MACRO");
}