Beispiel #1
0
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");
}
Beispiel #2
0
static void FuncString (void)
/* Handle the .STRING function */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Accept identifiers or numeric expressions */
    if (CurTok.Tok == TOK_LOCAL_IDENT) {
        /* Save the identifier, then skip it */
        SB_Copy (&Buf, &CurTok.SVal);
        NextTok ();
    } else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) {

        /* Parse a fully qualified symbol name. We cannot use
         * ParseScopedSymName here since the name may be invalid.
         */
        int NameSpace;
        do {
            NameSpace = (CurTok.Tok == TOK_NAMESPACE);
            if (NameSpace) {
                SB_AppendStr (&Buf, "::");
            } else {
                SB_Append (&Buf, &CurTok.SVal);
            }
            NextTok ();
        } while ((NameSpace != 0 && CurTok.Tok == TOK_IDENT) ||
                 (NameSpace == 0 && CurTok.Tok == TOK_NAMESPACE));

    } else {
        /* Numeric expression */
        long Val = ConstExpression ();
        SB_Printf (&Buf, "%ld", Val);
    }

    /* We expect a closing parenthesis, but will not skip it but replace it
     * by the string token just created.
     */
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = TOK_STRCON;
        SB_Copy (&CurTok.SVal, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free string memory */
    SB_Done (&Buf);
}
Beispiel #3
0
static void FuncRight (void)
/* Handle the .RIGHT function */
{
    long        Count;
    TokList*    List;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Count argument. Correct negative counts to zero. */
    Count = ConstExpression ();
    if (Count < 0) {
        Count = 0;
    }
    ConsumeComma ();

    /* Read the complete token list */
    List = CollectTokens (0, 9999);

    /* Delete tokens from the list until Count tokens are remaining */
    while (List->Count > (unsigned) Count) {
        /* Get the first node */
        TokNode* T = List->Root;

        /* Remove it from the list */
        List->Root = List->Root->Next;

        /* Free the node */
        FreeTokNode (T);

        /* Corrent the token counter */
        List->Count--;
    }

    /* Since we want to insert the list before the now current token, we have
     * to save the current token in some way and then skip it. To do this, we
     * will add the current token at the end of the token list (so the list
     * will never be empty), push the token list, and then skip the current
     * token. This will replace the current token by the first token from the
     * list (which will be the old current token in case the list was empty).
     */
    AddCurTok (List);

    /* Insert it into the scanner feed */
    PushTokList (List, ".RIGHT");

    /* Skip the current token */
    NextTok ();
}
Beispiel #4
0
static void FuncConcat (void)
/* Handle the .CONCAT function */
{
    StrBuf      Buf = STATIC_STRBUF_INITIALIZER;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Concatenate any number of strings */
    while (1) {

        /* Next token must be a string */
        if (!LookAtStrCon ()) {
            SB_Done (&Buf);
            return;
        }

        /* Append the string */
        SB_Append (&Buf, &CurTok.SVal);

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

        /* Comma means another argument */
        if (CurTok.Tok == TOK_COMMA) {
            NextTok ();
        } else {
            /* Done */
            break;
        }
    }

    /* We expect a closing parenthesis, but will not skip it but replace it
     * by the string token just created.
     */
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = TOK_STRCON;
        SB_Copy (&CurTok.SVal, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free the string buffer */
    SB_Done (&Buf);
}
Beispiel #5
0
static void FuncMid (void)
/* Handle the .MID function */
{
    long        Start;
    long        Count;
    TokList*    List;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Start argument. Since the start argument can get negative with
     * expressions like ".tcount(arg)-2", we correct it to zero silently.
     */
    Start = ConstExpression ();
    if (Start < 0 || Start > 100) {
        Start = 0;
    }
    ConsumeComma ();

    /* Count argument. Similar as above, we will accept negative counts and
     * correct them to zero silently.
     */
    Count = ConstExpression ();
    if (Count < 0) {
        Count = 0;
    }
    ConsumeComma ();

    /* Read the token list */
    List = CollectTokens ((unsigned) Start, (unsigned) Count);

    /* Since we want to insert the list before the now current token, we have
     * to save the current token in some way and then skip it. To do this, we
     * will add the current token at the end of the token list (so the list
     * will never be empty), push the token list, and then skip the current
     * token. This will replace the current token by the first token from the
     * list (which will be the old current token in case the list was empty).
     */
    AddCurTok (List);

    /* Insert it into the scanner feed */
    PushTokList (List, ".MID");

    /* Skip the current token */
    NextTok ();
}
Beispiel #6
0
static TokList* CollectRepeatTokens (void)
/* Collect all tokens inside the .REPEAT body in a token list and return
 * this list. In case of errors, NULL is returned.
 */
{
    /* Create the token list */
    TokList* List = NewTokList ();

    /* Read the token list */
    unsigned Repeats = 0;
    while (Repeats != 0 || Tok != TOK_ENDREP) {

     	/* Check for end of input */
       	if (Tok == TOK_EOF) {
     	    Error ("Unexpected end of file");
	    FreeTokList (List);
     	    return 0;
     	}

	/* If we find a token that is equal to the repeat counter name,
	 * replace it by a REPCOUNTER token. This way we have to do strcmps
	 * only once for each identifier, and not for each expansion.
	 * Note: This will fail for nested repeats using the same repeat
	 * counter name, but
	 */



       	/* Collect all tokens in the list */
	AddCurTok (List);

     	/* Check for and count nested .REPEATs */
     	if (Tok == TOK_REPEAT) {
     	    ++Repeats;
     	} else if (Tok == TOK_ENDREP) {
     	    --Repeats;
     	}

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

    /* Eat the closing .ENDREP */
    NextTok ();

    /* Return the list of collected tokens */
    return List;
}
Beispiel #7
0
int DSNLEXER::NeedSYMBOLorNUMBER() throw( IO_ERROR )
{
    int  tok = NextTok();
    if( !IsSymbol( tok ) && tok!=DSN_NUMBER )
        Expecting( "symbol|number" );
    return tok;
}
Beispiel #8
0
int DSNLEXER::NeedSYMBOL() throw( IO_ERROR )
{
    int tok = NextTok();
    if( !IsSymbol( tok ) )
        Expecting( DSN_SYMBOL );
    return tok;
}
Beispiel #9
0
void SkipUntilSep (void)
/* Skip tokens until we reach a line separator or end of file */
{
    while (!TokIsSep (CurTok.Tok)) {
        NextTok ();
    }
}
Beispiel #10
0
static TokList* CollectTokens (unsigned Start, unsigned Count)
/* Read a list of tokens that is optionally enclosed in curly braces and
 * terminated by a right paren. For all tokens starting at the one with index
 * Start, and ending at (Start+Count-1), place them into a token list, and
 * return this token list.
 */
{

    /* Create the token list */
    TokList* List = NewTokList ();

    /* Determine if the list is enclosed in curly braces. */
    token_t Term = GetTokListTerm (TOK_RPAREN);

    /* Read the token list */
    unsigned Current = 0;
    while (CurTok.Tok != Term) {

        /* Check for end of line or end of input */
        if (TokIsSep (CurTok.Tok)) {
            Error ("Unexpected end of line");
            return List;
        }

        /* Collect tokens in the given range */
        if (Current >= Start && Current < Start+Count) {
            /* Add the current token to the list */
            AddCurTok (List);
        }

        /* Get the next token */
        ++Current;
        NextTok ();
    }

    /* Eat the terminator token */
    NextTok ();

    /* If the list was enclosed in curly braces, we do expect now a right paren */
    if (Term == TOK_RCURLY) {
        ConsumeRParen ();
    }

    /* Return the list of collected tokens */
    return List;
}
Beispiel #11
0
void Consume (token_t Expected, const char* ErrMsg)
/* Consume Expected, print an error if we don't find it */
{
    if (CurTok.Tok == Expected) {
        NextTok ();
    } else {
        Error ("%s", ErrMsg);
    }
}
Beispiel #12
0
void ConsumeSep (void)
/* Consume a separator token */
{
    /* We expect a separator token */
    ExpectSep ();

    /* If we are at end of line, skip it */
    if (CurTok.Tok == TOK_SEP) {
        NextTok ();
    }
}
Beispiel #13
0
int DSNLEXER::NeedNUMBER( const char* aExpectation ) throw( IO_ERROR )
{
    int tok = NextTok();
    if( tok != DSN_NUMBER )
    {
        wxString    errText;

        errText.Printf( _("need a NUMBER for '%s'"), wxString::FromUTF8( aExpectation ).GetData() );
        THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
    }
    return tok;
}
Beispiel #14
0
enum Token GetTokListTerm (enum Token Term)
/* Determine if the following token list is enclosed in curly braces. This is
 * the case if the next token is the opening brace. If so, skip it and return
 * a closing brace, otherwise return Term.
 */
{
    if (Tok == TOK_LCURLY) {
        NextTok ();
        return TOK_RCURLY;
    } else {
        return Term;
    }
}
Beispiel #15
0
static TokList* CollectRepeatTokens (void)
/* Collect all tokens inside the .REPEAT body in a token list and return
 * this list. In case of errors, NULL is returned.
 */
{
    /* Create the token list */
    TokList* List = NewTokList ();

    /* Read the token list */
    unsigned Repeats = 0;
    while (Repeats != 0 || CurTok.Tok != TOK_ENDREP) {

        /* Check for end of input */
        if (CurTok.Tok == TOK_EOF) {
            Error ("Unexpected end of file");
            FreeTokList (List);
            return 0;
        }

        /* Collect all tokens in the list */
        AddCurTok (List);

        /* Check for and count nested .REPEATs */
        if (CurTok.Tok == TOK_REPEAT) {
            ++Repeats;
        } else if (CurTok.Tok == TOK_ENDREP) {
            --Repeats;
        }

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

    /* Eat the closing .ENDREP */
    NextTok ();

    /* Return the list of collected tokens */
    return List;
}
Beispiel #16
0
static void FuncLeft (void)
/* Handle the .LEFT function */
{
    long        Count;
    TokList*    List;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Count argument. Correct negative counts to zero. */
    Count = ConstExpression ();
    if (Count < 0) {
        Count = 0;
    }
    ConsumeComma ();

    /* Read the token list */
    List = CollectTokens (0, (unsigned) Count);

    /* Since we want to insert the list before the now current token, we have
     * to save the current token in some way and then skip it. To do this, we
     * will add the current token at the end of the token list (so the list
     * will never be empty), push the token list, and then skip the current
     * token. This will replace the current token by the first token from the
     * list (which will be the old current token in case the list was empty).
     */
    AddCurTok (List);

    /* Insert it into the scanner feed */
    PushTokList (List, ".LEFT");

    /* Skip the current token */
    NextTok ();
}
Beispiel #17
0
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);
}
Beispiel #18
0
static void MacSkipDef (unsigned Style)
/* Skip a macro definition */
{
    if (Style == MAC_STYLE_CLASSIC) {
        /* Skip tokens until we reach the final .endmacro */
        while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
            NextTok ();
        }
        if (CurTok.Tok != TOK_EOF) {
            SkipUntilSep ();
        } else {
            Error ("`.ENDMACRO' expected");
        }
    } else {
        /* Skip until end of line */
        SkipUntilSep ();
    }
}
Beispiel #19
0
SymEntry* ParseAnySymName (SymFindAction Action)
/* Parse a cheap local symbol or a a (possibly scoped) symbol name, search
 * for it in the symbol table and return the symbol table entry.
 */
{
    SymEntry* Sym;

    /* Distinguish cheap locals and other symbols */
    if (CurTok.Tok == TOK_LOCAL_IDENT) {
        Sym = SymFindLocal (SymLast, &CurTok.SVal, Action);
        NextTok ();
    } else {
        Sym = ParseScopedSymName (Action);
    }

    /* Return the symbol found */
    return Sym;
}
Beispiel #20
0
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);
}
Beispiel #21
0
static void FuncIdent (void)
/* Handle the .IDENT function */
{
    StrBuf    Buf = STATIC_STRBUF_INITIALIZER;
    token_t   Id;
    unsigned  I;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* The function expects a string argument */
    if (!LookAtStrCon ()) {
        return;
    }

    /* Check that the string contains a valid identifier. While doing so,
     * determine if it is a cheap local, or global one.
     */
    SB_Reset (&CurTok.SVal);

    /* Check for a cheap local symbol */
    if (SB_Peek (&CurTok.SVal) == LocalStart) {
        SB_Skip (&CurTok.SVal);
        Id = TOK_LOCAL_IDENT;
    } else {
        Id = TOK_IDENT;
    }

    /* Next character must be a valid identifier start */
    if (!IsIdStart (SB_Get (&CurTok.SVal))) {
        NoIdent ();
        return;
    }
    for (I = SB_GetIndex (&CurTok.SVal); I < SB_GetLen (&CurTok.SVal); ++I) {
        if (!IsIdChar (SB_AtUnchecked (&CurTok.SVal, I))) {
            NoIdent ();
            return;
        }
    }
    if (IgnoreCase) {
        UpcaseSVal ();
    }

    /* If anything is ok, save and skip the string. Check that the next token
     * is a right paren, then replace the token by an identifier token.
     */
    SB_Copy (&Buf, &CurTok.SVal);
    NextTok ();
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = Id;
        SB_Copy (&CurTok.SVal, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free buffer memory */
    SB_Done (&Buf);
}
Beispiel #22
0
void GetEA (EffAddr* A)
/* Parse an effective address, return the result in A */
{
    unsigned long Restrictions;
    token_t IndirectEnter;
    token_t IndirectLeave;
    const char* IndirectExpect;

    /* Choose syntax for indirection */
    if (BracketAsIndirect) {
        IndirectEnter = TOK_LBRACK;
        IndirectLeave = TOK_RBRACK;
        IndirectExpect = "']' expected";
    } else {
        IndirectEnter = TOK_LPAREN;
        IndirectLeave = TOK_RPAREN;
        IndirectExpect = "')' expected";
    }

    /* Clear the output struct */
    A->AddrModeSet = 0;
    A->Expr = 0;

    /* Handle an addressing size override */
    switch (CurTok.Tok) {
        case TOK_OVERRIDE_ZP:
            Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y;
            NextTok ();
            break;

        case TOK_OVERRIDE_ABS:
            Restrictions = AM65_ABS | AM65_ABS_X | AM65_ABS_Y;
            NextTok ();
            break;

        case TOK_OVERRIDE_FAR:
            Restrictions = AM65_ABS_LONG | AM65_ABS_LONG_X;
            NextTok ();
            break;

        default:
            Restrictions = ~0UL;        /* None */
            break;
    }

    /* Parse the effective address */
    if (TokIsSep (CurTok.Tok)) {

        A->AddrModeSet = AM65_IMPLICIT;

    } else if (CurTok.Tok == TOK_HASH) {

        /* #val */
        NextTok ();
        A->Expr  = Expression ();
        A->AddrModeSet = AM65_ALL_IMM;

    } else if (CurTok.Tok == TOK_A) {

        NextTok ();
        A->AddrModeSet = AM65_ACCU;

    } else if (CurTok.Tok == IndirectEnter) {

        /* One of the indirect modes */
        NextTok ();
        A->Expr = Expression ();

        if (CurTok.Tok == TOK_COMMA) {

            /* (expr,X) or (rel,S),y */
            NextTok ();
            if (CurTok.Tok == TOK_X) {
                /* (adr,x) */
                NextTok ();
                A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
                Consume (IndirectLeave, IndirectExpect);
            } else if (CurTok.Tok == TOK_S) {
                /* (rel,s),y */
                NextTok ();
                A->AddrModeSet = AM65_STACK_REL_IND_Y;
                Consume (IndirectLeave, IndirectExpect);
                ConsumeComma ();
                Consume (TOK_Y, "`Y' expected");
            } else {
                Error ("Syntax error");
            }

        } else {

            /* (adr), (adr),y or (adr),z */
            Consume (IndirectLeave, IndirectExpect);
            if (CurTok.Tok == TOK_COMMA) {
                /* (adr),y */
                NextTok ();
                switch (CurTok.Tok) {
                case TOK_Z:
                    /* only set by scanner.c if in 4510-mode */
                    NextTok ();
                    A->AddrModeSet = AM65_DIR_IND;
                    break;
                default:
                    Consume (TOK_Y, "`Y' expected");
                    A->AddrModeSet = AM65_DIR_IND_Y;
                    break;
                }
            } else {
                /* (adr) */
                A->AddrModeSet = (CPU == CPU_4510) ? AM65_ABS_IND
                                                   : AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
            }
        }

    } else if (CurTok.Tok == TOK_LBRACK) {

        /* Never executed if BracketAsIndirect feature is enabled. */
        /* [dir] or [dir],y */
        NextTok ();
        A->Expr = Expression ();
        Consume (TOK_RBRACK, "']' expected");
        if (CurTok.Tok == TOK_COMMA) {
            /* [dir],y */
            NextTok ();
            Consume (TOK_Y, "`Y' expected");
            A->AddrModeSet = AM65_DIR_IND_LONG_Y;
        } else {
            /* [dir] */
            A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG;
        }

    } else {

        /* Remaining stuff:
        **
        ** adr
        ** adr,x
        ** adr,y
        ** adr,s
        */
        A->Expr = Expression ();

        if (CurTok.Tok == TOK_COMMA) {

            NextTok ();
            switch (CurTok.Tok) {

                case TOK_X:
                    A->AddrModeSet = AM65_ABS_LONG_X | AM65_ABS_X | AM65_DIR_X;
                    NextTok ();
                    break;

                case TOK_Y:
                    A->AddrModeSet = AM65_ABS_Y | AM65_DIR_Y;
                    NextTok ();
                    break;

                case TOK_S:
                    A->AddrModeSet = AM65_STACK_REL;
                    NextTok ();
                    break;

                default:
                    Error ("Syntax error");

            }

        } else {

            A->AddrModeSet = AM65_ABS_LONG | AM65_ABS | AM65_DIR;

        }
    }

    /* Apply addressing mode overrides */
    A->AddrModeSet &= Restrictions;
}
Beispiel #23
0
SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
/* Parse a (possibly scoped) identifer. The scope of the name must exist and
 * is returned as function result, while the last part (the identifier) which
 * may be either a symbol or a scope depending on the context is returned in
 * Name. FullName is a string buffer that is used to store the full name of
 * the identifier including the scope. It is used internally and may be used
 * by the caller for error messages or similar.
 */
{
    SymTable* Scope;

    /* Clear both passed string buffers */
    SB_Clear (Name);
    SB_Clear (FullName);

    /* Get the starting table */
    if (CurTok.Tok == TOK_NAMESPACE) {

        /* Start from the root scope */
        Scope = RootScope;

    } else if (CurTok.Tok == TOK_IDENT) {

        /* Remember the name and skip it */
        SB_Copy (Name, &CurTok.SVal);
        NextTok ();

        /* If no namespace symbol follows, we're already done */
        if (CurTok.Tok != TOK_NAMESPACE) {
            SB_Terminate (FullName);
            return CurrentScope;
        }

        /* Pass the scope back to the caller */
        SB_Append (FullName, Name);

        /* The scope must exist, so search for it starting with the current
         * scope.
         */
        Scope = SymFindAnyScope (CurrentScope, Name);
        if (Scope == 0) {
            /* Scope not found */
            SB_Terminate (FullName);
            Error ("No such scope: `%m%p'", FullName);
            return 0;
        }

    } else {

        /* Invalid token */
        Error ("Identifier expected");
        return 0;

    }

    /* Skip the namespace token that follows */
    SB_AppendStr (FullName, "::");
    NextTok ();

    /* Resolve scopes. */
    while (1) {

        /* Next token must be an identifier. */
        if (CurTok.Tok != TOK_IDENT) {
            Error ("Identifier expected");
            return 0;
        }

        /* Remember and skip the identifier */
        SB_Copy (Name, &CurTok.SVal);
        NextTok ();

        /* If a namespace token follows, we search for another scope, otherwise
         * the name is a symbol and we're done.
         */
        if (CurTok.Tok != TOK_NAMESPACE) {
            /* Symbol */
            return Scope;
        }

        /* Pass the scope back to the caller */
        SB_Append (FullName, Name);

        /* Search for the child scope */
        Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
        if (Scope == 0) {
            /* Scope not found */
            Error ("No such scope: `%m%p'", FullName);
            return 0;
        }

        /* Skip the namespace token that follows */
        SB_AppendStr (FullName, "::");
        NextTok ();
    }
}
Beispiel #24
0
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);
}
Beispiel #25
0
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);
}
Beispiel #26
0
void GetEA (EffAddr* A)
/* Parse an effective address, return the result in A */
{
    unsigned long Restrictions;

    /* Clear the output struct */
    A->AddrModeSet = 0;
    A->Expr = 0;

    /* Handle an addressing size override */
    switch (CurTok.Tok) {
        case TOK_OVERRIDE_ZP:
            Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y;
            NextTok ();
            break;

        case TOK_OVERRIDE_ABS:
            Restrictions = AM65_ABS | AM65_ABS_X | AM65_ABS_Y;
            NextTok ();
            break;

        case TOK_OVERRIDE_FAR:
            Restrictions = AM65_ABS_LONG | AM65_ABS_LONG_X;
            NextTok ();
            break;

        default:
            Restrictions = ~0UL;        /* None */
            break;
    }

    /* Parse the effective address */
    if (TokIsSep (CurTok.Tok)) {

	A->AddrModeSet = AM65_IMPLICIT;

    } else if (CurTok.Tok == TOK_HASH) {

	/* #val */
	NextTok ();
	A->Expr  = Expression ();
	A->AddrModeSet = AM65_ALL_IMM;

    } else if (CurTok.Tok == TOK_A) {

	NextTok ();
	A->AddrModeSet = AM65_ACCU;

    } else if (CurTok.Tok == TOK_LBRACK) {

	/* [dir] or [dir],y */
	NextTok ();
	A->Expr = Expression ();
	Consume (TOK_RBRACK, "']' expected");
	if (CurTok.Tok == TOK_COMMA) {
	    /* [dir],y */
	    NextTok ();
	    Consume (TOK_Y, "`Y' expected");
	    A->AddrModeSet = AM65_DIR_IND_LONG_Y;
	} else {
	    /* [dir] */
	    A->AddrModeSet = AM65_DIR_IND_LONG;
	}

    } else if (CurTok.Tok == TOK_LPAREN) {

    	/* One of the indirect modes */
    	NextTok ();
    	A->Expr = Expression ();

    	if (CurTok.Tok == TOK_COMMA) {

    	    /* (expr,X) or (rel,S),y */
    	    NextTok ();
    	    if (CurTok.Tok == TOK_X) {
	   	/* (adr,x) */
    	   	NextTok ();
       	       	A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
    	       	ConsumeRParen ();
    	    } else if (CurTok.Tok == TOK_S) {
	   	/* (rel,s),y */
    	 	NextTok ();
    	 	A->AddrModeSet = AM65_STACK_REL_IND_Y;
    	 	ConsumeRParen ();
    	 	ConsumeComma ();
    	 	Consume (TOK_Y, "`Y' expected");
    	    } else {
    	 	Error ("Syntax error");
    	    }

       	} else {

	    /* (adr) or (adr),y */
    	    ConsumeRParen ();
    	    if (CurTok.Tok == TOK_COMMA) {
		/* (adr),y */
    	 	NextTok ();
    	 	Consume (TOK_Y, "`Y' expected");
    	 	A->AddrModeSet = AM65_DIR_IND_Y;
    	    } else {
		/* (adr) */
    	 	A->AddrModeSet = AM65_ABS_IND | AM65_DIR_IND;
    	    }
    	}

    } else {

	/* Remaining stuff:
	 *
	 * adr
	 * adr,x
	 * adr,y
	 * adr,s
	 */
       	A->Expr = Expression ();

        if (CurTok.Tok == TOK_COMMA) {

            NextTok ();
            switch (CurTok.Tok) {

                case TOK_X:
                    A->AddrModeSet = AM65_ABS_LONG_X | AM65_ABS_X | AM65_DIR_X;
                    NextTok ();
                    break;

                case TOK_Y:
                    A->AddrModeSet = AM65_ABS_Y | AM65_DIR_Y;
                    NextTok ();
                    break;

                case TOK_S:
                    A->AddrModeSet = AM65_STACK_REL;
                    NextTok ();
                    break;

                default:
                    Error ("Syntax error");

            }

        } else {

            A->AddrModeSet = AM65_ABS_LONG | AM65_ABS | AM65_DIR;

        }
    }

    /* Apply addressing mode overrides */
    A->AddrModeSet &= Restrictions;
}
Beispiel #27
0
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;
}
Beispiel #28
0
void DSNLEXER::NeedRIGHT() throw( IO_ERROR )
{
    int tok = NextTok();
    if( tok != DSN_RIGHT )
        Expecting( DSN_RIGHT );
}
Beispiel #29
0
static void FuncSPrintF (void)
/* Handle the .SPRINTF function */
{
    StrBuf      Format = STATIC_STRBUF_INITIALIZER; /* User supplied format */
    StrBuf      R = STATIC_STRBUF_INITIALIZER;      /* Result string */
    StrBuf      F1 = STATIC_STRBUF_INITIALIZER;     /* One format spec from F */
    StrBuf      R1 = STATIC_STRBUF_INITIALIZER;     /* One result */
    char        C;
    int         Done;
    long        IVal;                               /* Integer value */



    /* Skip the .SPRINTF token */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* First argument is a format string. Remember and skip it */
    if (!LookAtStrCon ()) {
        return;
    }
    SB_Copy (&Format, &CurTok.SVal);
    NextTok ();

    /* Walk over the format string, generating the function result in R */
    while (1) {

        /* Get the next char from the format string and check for EOS */
        if (SB_Peek (&Format) == '\0') {
            break;
        }

        /* Check for a format specifier */
        if (SB_Peek (&Format) != '%') {
            /* No format specifier, just copy */
            SB_AppendChar (&R, SB_Get (&Format));
            continue;
        }
        SB_Skip (&Format);
        if (SB_Peek (&Format) == '%') {
            /* %% */
            SB_AppendChar (&R, '%');
            SB_Skip (&Format);
            continue;
        }
        if (SB_Peek (&Format) == '\0') {
            InvalidFormatString ();
            break;
        }

        /* Since a format specifier follows, we do expect anotehr argument for
         * the .sprintf function.
         */
        ConsumeComma ();

        /* We will copy the format spec into F1 checking for the things we
         * support, and later use xsprintf to do the actual formatting. This
         * is easier than adding another printf implementation...
         */
        SB_Clear (&F1);
        SB_AppendChar (&F1, '%');

        /* Check for flags */
        Done = 0;
        while ((C = SB_Peek (&Format)) != '\0' && !Done) {
            switch (C) {
                case '-': /* FALLTHROUGH */
                case '+': /* FALLTHROUGH */
                case ' ': /* FALLTHROUGH */
                case '#': /* FALLTHROUGH */
                case '0': SB_AppendChar (&F1, SB_Get (&Format));  break;
                default:  Done = 1;                               break;
            }
        }

        /* We do only support a numerical width field */
        while (IsDigit (SB_Peek (&Format))) {
            SB_AppendChar (&F1, SB_Get (&Format));
        }

        /* Precision - only positive numerical fields supported */
        if (SB_Peek (&Format) == '.') {
            SB_AppendChar (&F1, SB_Get (&Format));
            while (IsDigit (SB_Peek (&Format))) {
                SB_AppendChar (&F1, SB_Get (&Format));
            }
        }

        /* Length modifiers aren't supported, so read the conversion specs */
        switch (SB_Peek (&Format)) {

            case 'd':
            case 'i':
            case 'o':
            case 'u':
            case 'X':
            case 'x':
                /* Our ints are actually longs, so we use the 'l' modifier when
                 * calling xsprintf later. Terminate the format string.
                 */
                SB_AppendChar (&F1, 'l');
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a constant expression */
                IVal = ConstExpression ();

                /* Format this argument according to the spec */
                SB_Printf (&R1, SB_GetConstBuf (&F1), IVal);

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            case 's':
                /* Add the format spec and terminate the format */
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a string constant */
                if (!LookAtStrCon ()) {
                    /* Make it one */
                    SB_CopyStr (&CurTok.SVal, "**undefined**");
                }

                /* Format this argument according to the spec */
                SB_Printf (&R1, SB_GetConstBuf (&F1), SB_GetConstBuf (&CurTok.SVal));

                /* Skip the string constant */
                NextTok ();

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            case 'c':
                /* Add the format spec and terminate the format */
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a constant expression */
                IVal = ConstExpression ();

                /* Check for a valid character range */
                if (IVal <= 0 || IVal > 255) {
                    Error ("Char argument out of range");
                    IVal = ' ';
                }

                /* Format this argument according to the spec. Be sure to pass
                 * an int as the char value.
                 */
                SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal);

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            default:
                Error ("Invalid format string");
                SB_Skip (&Format);
                break;
        }

    }

    /* Terminate the result string */
    SB_Terminate (&R);

    /* We expect a closing parenthesis, but will not skip it but replace it
     * by the string token just created.
     */
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = TOK_STRCON;
        SB_Copy (&CurTok.SVal, &R);
        SB_Terminate (&CurTok.SVal);
    }


    /* Delete the string buffers */
    SB_Done (&Format);
    SB_Done (&R);
    SB_Done (&F1);
    SB_Done (&R1);
}
Beispiel #30
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);
}