Merge https://github.com/cc65/cc65 into c1p
This commit is contained in:
@@ -59,9 +59,9 @@ static const char AnonTag[] = "$anon";
|
||||
|
||||
StrBuf* AnonName (StrBuf* Buf, const char* Spec)
|
||||
/* Get a name for an anonymous scope, variable or type. Size is the size of
|
||||
* the buffer passed to the function, Spec will be used as part of the
|
||||
* identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
** the buffer passed to the function, Spec will be used as part of the
|
||||
** identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
{
|
||||
static unsigned ACount = 0;
|
||||
SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount);
|
||||
@@ -79,6 +79,3 @@ int IsAnonName (const StrBuf* Name)
|
||||
}
|
||||
return (strncmp (SB_GetConstBuf (Name), AnonTag, sizeof (AnonTag) - 1) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,9 +51,9 @@
|
||||
|
||||
StrBuf* AnonName (StrBuf* Buf, const char* Spec);
|
||||
/* Get a name for an anonymous scope, variable or type. Size is the size of
|
||||
* the buffer passed to the function, Spec will be used as part of the
|
||||
* identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
** the buffer passed to the function, Spec will be used as part of the
|
||||
** identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
|
||||
int IsAnonName (const StrBuf* Name);
|
||||
/* Check if the given symbol name is that of an anonymous symbol */
|
||||
@@ -61,7 +61,5 @@ int IsAnonName (const StrBuf* Name);
|
||||
|
||||
|
||||
/* End of anonname.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -176,8 +176,3 @@ void WriteAssertions (void)
|
||||
/* Done writing the assertions */
|
||||
ObjEndAssertions ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -74,6 +74,3 @@ void WriteAssertions (void);
|
||||
/* End of asserts.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ static int GetOverallIfCond (void)
|
||||
/* Get the overall condition based on all conditions on the stack. */
|
||||
{
|
||||
/* Since the last entry contains the overall condition of the parent, we
|
||||
* must check it in combination of the current condition. If there is no
|
||||
* last entry, the overall condition is true.
|
||||
*/
|
||||
** must check it in combination of the current condition. If there is no
|
||||
** last entry, the overall condition is true.
|
||||
*/
|
||||
return (IfCount == 0) ||
|
||||
((IfStack[IfCount-1].Flags & (ifCond | ifParentCond)) == (ifCond | ifParentCond));
|
||||
}
|
||||
@@ -114,7 +114,7 @@ static int GetOverallIfCond (void)
|
||||
|
||||
|
||||
static void CalcOverallIfCond (void)
|
||||
/* Caclulate the overall condition based on all conditions on the stack. */
|
||||
/* Calculate the overall condition, based on all conditions on the stack. */
|
||||
{
|
||||
IfCond = GetOverallIfCond ();
|
||||
}
|
||||
@@ -256,9 +256,9 @@ void DoConditionals (void)
|
||||
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...
|
||||
*/
|
||||
** branch. This way we won't get any errors about undefined
|
||||
** symbols or similar...
|
||||
*/
|
||||
if (IfCond) {
|
||||
SetIfCond (D, ConstExpression ());
|
||||
ExpectSep ();
|
||||
@@ -273,8 +273,8 @@ void DoConditionals (void)
|
||||
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.
|
||||
*/
|
||||
** has been cleanup up, since we may be at end of file.
|
||||
*/
|
||||
NextTok ();
|
||||
ExpectSep ();
|
||||
|
||||
@@ -440,9 +440,9 @@ void DoConditionals (void)
|
||||
|
||||
int CheckConditionals (void)
|
||||
/* Check if the current token is one that starts a conditional directive, and
|
||||
* call DoConditionals if so. Return true if a conditional directive was found,
|
||||
* return false otherwise.
|
||||
*/
|
||||
** call DoConditionals if so. Return true if a conditional directive was found,
|
||||
** return false otherwise.
|
||||
*/
|
||||
{
|
||||
switch (CurTok.Tok) {
|
||||
case TOK_ELSE:
|
||||
@@ -473,15 +473,15 @@ int CheckConditionals (void)
|
||||
|
||||
void CheckOpenIfs (void)
|
||||
/* Called from the scanner before closing an input file. Will check for any
|
||||
* open .ifs in this file.
|
||||
*/
|
||||
** open .ifs in this file.
|
||||
*/
|
||||
{
|
||||
const LineInfo* LI;
|
||||
|
||||
while (1) {
|
||||
/* Get the current file number and check if the topmost entry on the
|
||||
* .IF stack was inserted with this file number
|
||||
*/
|
||||
** .IF stack was inserted with this file number
|
||||
*/
|
||||
IfDesc* D = GetCurrentIf ();
|
||||
if (D == 0) {
|
||||
/* There are no open .IFs */
|
||||
@@ -523,7 +523,3 @@ void CleanupIfStack (unsigned SP)
|
||||
/* Calculate the new overall .IF condition */
|
||||
CalcOverallIfCond ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -60,14 +60,14 @@ void DoConditionals (void);
|
||||
|
||||
int CheckConditionals (void);
|
||||
/* Check if the current token is one that starts a conditional directive, and
|
||||
* call DoConditionals if so. Return true if a conditional directive was found,
|
||||
* return false otherwise.
|
||||
*/
|
||||
** call DoConditionals if so. Return true if a conditional directive was found,
|
||||
** return false otherwise.
|
||||
*/
|
||||
|
||||
void CheckOpenIfs (void);
|
||||
/* Called from the scanner before closing an input file. Will check for any
|
||||
* open .ifs in this file.
|
||||
*/
|
||||
** open .ifs in this file.
|
||||
*/
|
||||
|
||||
unsigned GetIfStack (void);
|
||||
/* Get the current .IF stack pointer */
|
||||
@@ -80,6 +80,3 @@ void CleanupIfStack (unsigned SP);
|
||||
/* End of condasm.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -130,8 +130,8 @@ static unsigned HexValue (char C)
|
||||
|
||||
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.
|
||||
*/
|
||||
** the type isn't valid, return -1. Type is overwritten when checking.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
const char* A;
|
||||
@@ -311,8 +311,8 @@ void DbgInfoLine (void)
|
||||
}
|
||||
|
||||
/* If a parameters follow, this is actual line info. If no parameters
|
||||
* follow, the last line info is terminated.
|
||||
*/
|
||||
** follow, the last line info is terminated.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_SEP) {
|
||||
return;
|
||||
}
|
||||
@@ -445,10 +445,10 @@ void DbgInfoCheck (void)
|
||||
/* Do checks on all hll debug info symbols when assembly is complete */
|
||||
{
|
||||
/* When parsing the debug statements for HLL symbols, we have already
|
||||
* tagged the functions to their asm counterparts. This wasn't done for
|
||||
* C symbols, since we will allow forward declarations. So we have to
|
||||
* resolve the normal C symbols now.
|
||||
*/
|
||||
** tagged the functions to their asm counterparts. This wasn't done for
|
||||
** C symbols, since we will allow forward declarations. So we have to
|
||||
** resolve the normal C symbols now.
|
||||
*/
|
||||
unsigned I;
|
||||
for (I = 0; I < CollCount (&HLLDbgSyms); ++I) {
|
||||
|
||||
@@ -456,8 +456,8 @@ void DbgInfoCheck (void)
|
||||
HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I);
|
||||
|
||||
/* Ignore functions and auto symbols, because the later live on the
|
||||
* stack and don't have corresponding asm symbols.
|
||||
*/
|
||||
** stack and don't have corresponding asm symbols.
|
||||
*/
|
||||
if (HLL_IS_FUNC (S->Flags) || HLL_GET_SC (S->Flags) == HLL_SC_AUTO) {
|
||||
continue;
|
||||
}
|
||||
@@ -501,8 +501,8 @@ void WriteHLLDbgSyms (void)
|
||||
unsigned SC = HLL_GET_SC (S->Flags);
|
||||
|
||||
/* Remember if the symbol has debug info attached
|
||||
* ### This should go into DbgInfoCheck
|
||||
*/
|
||||
** ### This should go into DbgInfoCheck
|
||||
*/
|
||||
if (S->Sym && S->Sym->DebugSymId != ~0U) {
|
||||
S->Flags |= HLL_DATA_SYM;
|
||||
}
|
||||
@@ -527,6 +527,3 @@ void WriteHLLDbgSyms (void)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,8 +67,3 @@ void WriteHLLDbgSyms (void);
|
||||
/* End of dbginfo.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,3 @@ struct EffAddr {
|
||||
/* End of ea.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ void GetEA (EffAddr* A)
|
||||
A->AddrModeSet = AM65_DIR_IND_LONG_Y;
|
||||
} else {
|
||||
/* [dir] */
|
||||
A->AddrModeSet = AM65_DIR_IND_LONG;
|
||||
A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG;
|
||||
}
|
||||
|
||||
} else if (CurTok.Tok == TOK_LPAREN) {
|
||||
@@ -150,19 +150,19 @@ void GetEA (EffAddr* A)
|
||||
A->AddrModeSet = AM65_DIR_IND_Y;
|
||||
} else {
|
||||
/* (adr) */
|
||||
A->AddrModeSet = AM65_ABS_IND | AM65_DIR_IND;
|
||||
A->AddrModeSet = AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Remaining stuff:
|
||||
*
|
||||
* adr
|
||||
* adr,x
|
||||
* adr,y
|
||||
* adr,s
|
||||
*/
|
||||
**
|
||||
** adr
|
||||
** adr,x
|
||||
** adr,y
|
||||
** adr,s
|
||||
*/
|
||||
A->Expr = Expression ();
|
||||
|
||||
if (CurTok.Tok == TOK_COMMA) {
|
||||
@@ -200,7 +200,3 @@ void GetEA (EffAddr* A)
|
||||
/* Apply addressing mode overrides */
|
||||
A->AddrModeSet &= Restrictions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,6 +62,3 @@ void GetEA (EffAddr* A);
|
||||
/* End of ea65.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,9 +51,9 @@
|
||||
|
||||
static long RegNum ()
|
||||
/* Try to read a register number specified not as a register (Rx) but as a
|
||||
* numeric value between 0 and 15. Return the register number or -1 on
|
||||
* failure.
|
||||
*/
|
||||
** numeric value between 0 and 15. Return the register number or -1 on
|
||||
** failure.
|
||||
*/
|
||||
{
|
||||
long Val;
|
||||
ExprNode* Expr = Expression ();
|
||||
@@ -126,8 +126,8 @@ void GetSweet16EA (EffAddr* A)
|
||||
A->AddrModeSet = AMSW16_BRA;
|
||||
|
||||
/* If the value is a constant between 0 and 15, it may also be a
|
||||
* register number.
|
||||
*/
|
||||
** register number.
|
||||
*/
|
||||
if (IsConstExpr (A->Expr, &Reg) && Reg >= 0 && Reg <= 15) {
|
||||
FreeExpr (A->Expr);
|
||||
A->Reg = (unsigned) Reg;
|
||||
|
||||
@@ -151,7 +151,3 @@ void DoEnum (void)
|
||||
/* Free the base expression */
|
||||
FreeExpr (BaseExpr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,3 @@ void DoEnum (void);
|
||||
/* End of enum.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -128,10 +128,10 @@ static void AddNotifications (const Collection* LineInfos)
|
||||
unsigned Skipped;
|
||||
|
||||
/* The basic line info is always in slot zero. It has been used to
|
||||
* output the actual error or warning. The following slots may contain
|
||||
* more information. Check them and print additional notifications if
|
||||
* they're present, but limit the number to a reasonable value.
|
||||
*/
|
||||
** output the actual error or warning. The following slots may contain
|
||||
** more information. Check them and print additional notifications if
|
||||
** they're present, but limit the number to a reasonable value.
|
||||
*/
|
||||
for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) {
|
||||
/* Get next line info */
|
||||
const LineInfo* LI = CollConstAt (LineInfos, I);
|
||||
@@ -400,6 +400,3 @@ void Internal (const char* Format, ...)
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@
|
||||
|
||||
|
||||
|
||||
#if defined( __MINGW32__)
|
||||
# pragma GCC diagnostic ignored "-Wformat"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "coll.h"
|
||||
@@ -98,7 +104,3 @@ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))
|
||||
/* End of error.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
147
src/ca65/expr.c
147
src/ca65/expr.c
@@ -72,11 +72,11 @@
|
||||
|
||||
|
||||
/* Since all expressions are first packed into expression trees, and each
|
||||
* expression tree node is allocated on the heap, we add some type of special
|
||||
* purpose memory allocation here: Instead of freeing the nodes, we save some
|
||||
* number of freed nodes for later and remember them in a single linked list
|
||||
* using the Left link.
|
||||
*/
|
||||
** expression tree node is allocated on the heap, we add some type of special
|
||||
** purpose memory allocation here: Instead of freeing the nodes, we save some
|
||||
** number of freed nodes for later and remember them in a single linked list
|
||||
** using the Left link.
|
||||
*/
|
||||
#define MAX_FREE_NODES 64
|
||||
static ExprNode* FreeExprNodes = 0;
|
||||
static unsigned FreeNodeCount = 0;
|
||||
@@ -172,9 +172,9 @@ int IsFarRange (long Val)
|
||||
|
||||
int IsEasyConst (const ExprNode* E, long* Val)
|
||||
/* Do some light checking if the given node is a constant. Don't care if E is
|
||||
* a complex expression. If E is a constant, return true and place its value
|
||||
* into Val, provided that Val is not NULL.
|
||||
*/
|
||||
** a complex expression. If E is a constant, return true and place its value
|
||||
** into Val, provided that Val is not NULL.
|
||||
*/
|
||||
{
|
||||
/* Resolve symbols, follow symbol chains */
|
||||
while (E->Op == EXPR_SYMBOL) {
|
||||
@@ -322,8 +322,8 @@ static ExprNode* Symbol (SymEntry* S)
|
||||
/* Mark the symbol as referenced */
|
||||
SymRef (S);
|
||||
/* If the symbol is a variable, return just its value, otherwise
|
||||
* return a reference to the symbol.
|
||||
*/
|
||||
** return a reference to the symbol.
|
||||
*/
|
||||
if (SymIsVar (S)) {
|
||||
return CloneExpr (GetSymExpr (S));
|
||||
} else {
|
||||
@@ -355,16 +355,16 @@ static ExprNode* FuncBlank (void)
|
||||
/* Handle the .BLANK builtin function */
|
||||
{
|
||||
/* We have a list of tokens that ends with the closing paren. Skip
|
||||
* the tokens, and count them. Allow optionally curly braces.
|
||||
*/
|
||||
** the tokens, and count them. Allow optionally curly braces.
|
||||
*/
|
||||
token_t Term = GetTokListTerm (TOK_RPAREN);
|
||||
unsigned Count = 0;
|
||||
while (CurTok.Tok != Term) {
|
||||
|
||||
/* Check for end of line or end of input. Since the calling function
|
||||
* will check for the closing paren, we don't need to print an error
|
||||
* here, just bail out.
|
||||
*/
|
||||
** will check for the closing paren, we don't need to print an error
|
||||
** here, just bail out.
|
||||
*/
|
||||
if (TokIsSep (CurTok.Tok)) {
|
||||
break;
|
||||
}
|
||||
@@ -458,9 +458,9 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
|
||||
TokNode* Node;
|
||||
|
||||
/* A list of tokens follows. Read this list and remember it building a
|
||||
* single linked list of tokens including attributes. The list is
|
||||
* either enclosed in curly braces, or terminated by a comma.
|
||||
*/
|
||||
** single linked list of tokens including attributes. The list is
|
||||
** either enclosed in curly braces, or terminated by a comma.
|
||||
*/
|
||||
token_t Term = GetTokListTerm (TOK_COMMA);
|
||||
while (CurTok.Tok != Term) {
|
||||
|
||||
@@ -494,9 +494,9 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
|
||||
}
|
||||
|
||||
/* Read the second list which is optionally enclosed in curly braces and
|
||||
* terminated by the right parenthesis. Compare each token against the
|
||||
* one in the first list.
|
||||
*/
|
||||
** terminated by the right parenthesis. Compare each token against the
|
||||
** one in the first list.
|
||||
*/
|
||||
Term = GetTokListTerm (TOK_RPAREN);
|
||||
Result = 1;
|
||||
Node = Root;
|
||||
@@ -674,8 +674,8 @@ static ExprNode* FuncSizeOf (void)
|
||||
}
|
||||
|
||||
/* If ScopeName is empty, no explicit scope was specified. We have to
|
||||
* search upper scope levels in this case.
|
||||
*/
|
||||
** search upper scope levels in this case.
|
||||
*/
|
||||
NoScope = SB_IsEmpty (&ScopeName);
|
||||
|
||||
/* First search for a scope with the given name */
|
||||
@@ -686,8 +686,8 @@ static ExprNode* FuncSizeOf (void)
|
||||
}
|
||||
|
||||
/* If we did find a scope with the name, read the symbol defining the
|
||||
* size, otherwise search for a symbol entry with the name and scope.
|
||||
*/
|
||||
** size, otherwise search for a symbol entry with the name and scope.
|
||||
*/
|
||||
if (Scope) {
|
||||
/* Yep, it's a scope */
|
||||
SizeSym = GetSizeOfScope (Scope);
|
||||
@@ -755,8 +755,8 @@ static ExprNode* FuncStrAt (void)
|
||||
}
|
||||
|
||||
/* Get the char, handle as unsigned. Be sure to translate it into
|
||||
* the target character set.
|
||||
*/
|
||||
** the target character set.
|
||||
*/
|
||||
C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
|
||||
|
||||
ExitPoint:
|
||||
@@ -803,16 +803,16 @@ static ExprNode* FuncTCount (void)
|
||||
/* Handle the .TCOUNT function */
|
||||
{
|
||||
/* We have a list of tokens that ends with the closing paren. Skip
|
||||
* the tokens, and count them. Allow optionally curly braces.
|
||||
*/
|
||||
** the tokens, and count them. Allow optionally curly braces.
|
||||
*/
|
||||
token_t Term = GetTokListTerm (TOK_RPAREN);
|
||||
int Count = 0;
|
||||
while (CurTok.Tok != Term) {
|
||||
|
||||
/* Check for end of line or end of input. Since the calling function
|
||||
* will check for the closing paren, we don't need to print an error
|
||||
* here, just bail out.
|
||||
*/
|
||||
** will check for the closing paren, we don't need to print an error
|
||||
** here, just bail out.
|
||||
*/
|
||||
if (TokIsSep (CurTok.Tok)) {
|
||||
break;
|
||||
}
|
||||
@@ -1131,8 +1131,8 @@ static ExprNode* Term (void)
|
||||
}
|
||||
|
||||
/* Generate a literal expression and delete the old left and
|
||||
* right sides.
|
||||
*/
|
||||
** right sides.
|
||||
*/
|
||||
FreeExpr (Left);
|
||||
FreeExpr (Right);
|
||||
Root = GenLiteralExpr (Val);
|
||||
@@ -1198,8 +1198,8 @@ static ExprNode* SimpleExpr (void)
|
||||
}
|
||||
|
||||
/* Generate a literal expression and delete the old left and
|
||||
* right sides.
|
||||
*/
|
||||
** right sides.
|
||||
*/
|
||||
FreeExpr (Left);
|
||||
FreeExpr (Right);
|
||||
Root = GenLiteralExpr (Val);
|
||||
@@ -1264,8 +1264,8 @@ static ExprNode* BoolExpr (void)
|
||||
}
|
||||
|
||||
/* Generate a literal expression and delete the old left and
|
||||
* right sides.
|
||||
*/
|
||||
** right sides.
|
||||
*/
|
||||
FreeExpr (Left);
|
||||
FreeExpr (Right);
|
||||
Root = GenLiteralExpr (Val);
|
||||
@@ -1327,8 +1327,8 @@ static ExprNode* Expr2 (void)
|
||||
}
|
||||
|
||||
/* Generate a literal expression and delete the old left and
|
||||
* right sides.
|
||||
*/
|
||||
** right sides.
|
||||
*/
|
||||
FreeExpr (Left);
|
||||
FreeExpr (Right);
|
||||
Root = GenLiteralExpr (Val);
|
||||
@@ -1385,8 +1385,8 @@ static ExprNode* Expr1 (void)
|
||||
}
|
||||
|
||||
/* Generate a literal expression and delete the old left and
|
||||
* right sides.
|
||||
*/
|
||||
** right sides.
|
||||
*/
|
||||
FreeExpr (Left);
|
||||
FreeExpr (Right);
|
||||
Root = GenLiteralExpr (Val);
|
||||
@@ -1453,8 +1453,8 @@ static ExprNode* Expr0 (void)
|
||||
|
||||
ExprNode* Expression (void)
|
||||
/* Evaluate an expression, build the expression tree on the heap and return
|
||||
* a pointer to the root of the tree.
|
||||
*/
|
||||
** a pointer to the root of the tree.
|
||||
*/
|
||||
{
|
||||
return Expr0 ();
|
||||
}
|
||||
@@ -1463,9 +1463,9 @@ ExprNode* Expression (void)
|
||||
|
||||
long ConstExpression (void)
|
||||
/* Parse an expression. Check if the expression is const, and print an error
|
||||
* message if not. Return the value of the expression, or a dummy, if it is
|
||||
* not constant.
|
||||
*/
|
||||
** message if not. Return the value of the expression, or a dummy, if it is
|
||||
** not constant.
|
||||
*/
|
||||
{
|
||||
long Val;
|
||||
|
||||
@@ -1620,8 +1620,8 @@ ExprNode* GenSwapExpr (ExprNode* Expr)
|
||||
|
||||
ExprNode* GenBranchExpr (unsigned Offs)
|
||||
/* Return an expression that encodes the difference between current PC plus
|
||||
* offset and the target expression (that is, Expression() - (*+Offs) ).
|
||||
*/
|
||||
** offset and the target expression (that is, Expression() - (*+Offs) ).
|
||||
*/
|
||||
{
|
||||
ExprNode* N;
|
||||
ExprNode* Root;
|
||||
@@ -1637,11 +1637,11 @@ ExprNode* GenBranchExpr (unsigned Offs)
|
||||
FreeExpr (N);
|
||||
|
||||
/* Generate the final expression:
|
||||
* Val - (* + Offs)
|
||||
* Val - ((Seg + PC) + Offs)
|
||||
* Val - Seg - PC - Offs
|
||||
* (Val - PC - Offs) - Seg
|
||||
*/
|
||||
** Val - (* + Offs)
|
||||
** Val - ((Seg + PC) + Offs)
|
||||
** Val - Seg - PC - Offs
|
||||
** (Val - PC - Offs) - Seg
|
||||
*/
|
||||
Root = GenLiteralExpr (Val - GetPC () - Offs);
|
||||
if (GetRelocMode ()) {
|
||||
N = Root;
|
||||
@@ -1653,11 +1653,11 @@ ExprNode* GenBranchExpr (unsigned Offs)
|
||||
} else {
|
||||
|
||||
/* Generate the expression:
|
||||
* N - (* + Offs)
|
||||
* N - ((Seg + PC) + Offs)
|
||||
* N - Seg - PC - Offs
|
||||
* N - (PC + Offs) - Seg
|
||||
*/
|
||||
** N - (* + Offs)
|
||||
** N - ((Seg + PC) + Offs)
|
||||
** N - Seg - PC - Offs
|
||||
** N - (PC + Offs) - Seg
|
||||
*/
|
||||
Root = NewExprNode (EXPR_MINUS);
|
||||
Root->Left = N;
|
||||
Root->Right = GenLiteralExpr (GetPC () + Offs);
|
||||
@@ -1759,9 +1759,9 @@ ExprNode* GenNE (ExprNode* Expr, long Val)
|
||||
|
||||
int IsConstExpr (ExprNode* Expr, long* Val)
|
||||
/* Return true if the given expression is a constant expression, that is, one
|
||||
* with no references to external symbols. If Val is not NULL and the
|
||||
* expression is constant, the constant value is stored here.
|
||||
*/
|
||||
** with no references to external symbols. If Val is not NULL and the
|
||||
** expression is constant, the constant value is stored here.
|
||||
*/
|
||||
{
|
||||
int IsConst;
|
||||
|
||||
@@ -1785,8 +1785,8 @@ int IsConstExpr (ExprNode* Expr, long* Val)
|
||||
|
||||
ExprNode* CloneExpr (ExprNode* Expr)
|
||||
/* Clone the given expression tree. The function will simply clone symbol
|
||||
* nodes, it will not resolve them.
|
||||
*/
|
||||
** nodes, it will not resolve them.
|
||||
*/
|
||||
{
|
||||
ExprNode* Clone;
|
||||
|
||||
@@ -1843,8 +1843,8 @@ void WriteExpr (ExprNode* Expr)
|
||||
}
|
||||
|
||||
/* If the is a leafnode, write the expression attribute, otherwise
|
||||
* write the expression operands.
|
||||
*/
|
||||
** write the expression operands.
|
||||
*/
|
||||
switch (Expr->Op) {
|
||||
|
||||
case EXPR_LITERAL:
|
||||
@@ -1884,12 +1884,12 @@ void WriteExpr (ExprNode* Expr)
|
||||
|
||||
void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
|
||||
/* Mark the address size of the given expression tree as guessed. The address
|
||||
* size passed as argument is the one NOT used, because the actual address
|
||||
* size wasn't known. Example: Zero page addressing was not used because symbol
|
||||
* is undefined, and absolute addressing was available.
|
||||
* This function will actually parse the expression tree for undefined symbols,
|
||||
* and mark these symbols accordingly.
|
||||
*/
|
||||
** size passed as argument is the one NOT used, because the actual address
|
||||
** size wasn't known. Example: Zero page addressing was not used because symbol
|
||||
** is undefined, and absolute addressing was available.
|
||||
** This function will actually parse the expression tree for undefined symbols,
|
||||
** and mark these symbols accordingly.
|
||||
*/
|
||||
{
|
||||
/* Accept NULL expressions */
|
||||
if (Expr == 0) {
|
||||
@@ -1942,6 +1942,3 @@ ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
|
||||
{
|
||||
return MakeBoundedExpr (ExprFunc (), Size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,14 +62,14 @@ struct ExprDesc;
|
||||
|
||||
ExprNode* Expression (void);
|
||||
/* Evaluate an expression, build the expression tree on the heap and return
|
||||
* a pointer to the root of the tree.
|
||||
*/
|
||||
** a pointer to the root of the tree.
|
||||
*/
|
||||
|
||||
long ConstExpression (void);
|
||||
/* Parse an expression. Check if the expression is const, and print an error
|
||||
* message if not. Return the value of the expression, or a dummy, if it is
|
||||
* not constant.
|
||||
*/
|
||||
** message if not. Return the value of the expression, or a dummy, if it is
|
||||
** not constant.
|
||||
*/
|
||||
|
||||
void FreeExpr (ExprNode* Root);
|
||||
/* Free the expression tree, Root is pointing to. */
|
||||
@@ -97,8 +97,8 @@ ExprNode* GenSwapExpr (ExprNode* Expr);
|
||||
|
||||
ExprNode* GenBranchExpr (unsigned Offs);
|
||||
/* Return an expression that encodes the difference between current PC plus
|
||||
* offset and the target expression (that is, Expression() - (*+Offs) ).
|
||||
*/
|
||||
** offset and the target expression (that is, Expression() - (*+Offs) ).
|
||||
*/
|
||||
|
||||
ExprNode* GenULabelExpr (unsigned Num);
|
||||
/* Return an expression for an unnamed label with the given index */
|
||||
@@ -120,9 +120,9 @@ ExprNode* GenNE (ExprNode* Expr, long Val);
|
||||
|
||||
int IsConstExpr (ExprNode* Expr, long* Val);
|
||||
/* Return true if the given expression is a constant expression, that is, one
|
||||
* with no references to external symbols. If Val is not NULL and the
|
||||
* expression is constant, the constant value is stored here.
|
||||
*/
|
||||
** with no references to external symbols. If Val is not NULL and the
|
||||
** expression is constant, the constant value is stored here.
|
||||
*/
|
||||
|
||||
int IsByteExpr (ExprNode* Root);
|
||||
/* Return true if this is a byte expression */
|
||||
@@ -138,26 +138,26 @@ int IsFarRange (long Val);
|
||||
|
||||
int IsEasyConst (const ExprNode* E, long* Val);
|
||||
/* Do some light checking if the given node is a constant. Don't care if E is
|
||||
* a complex expression. If E is a constant, return true and place its value
|
||||
* into Val, provided that Val is not NULL.
|
||||
*/
|
||||
** a complex expression. If E is a constant, return true and place its value
|
||||
** into Val, provided that Val is not NULL.
|
||||
*/
|
||||
|
||||
ExprNode* CloneExpr (ExprNode* Expr);
|
||||
/* Clone the given expression tree. The function will simply clone symbol
|
||||
* nodes, it will not resolve them.
|
||||
*/
|
||||
** nodes, it will not resolve them.
|
||||
*/
|
||||
|
||||
void WriteExpr (ExprNode* Expr);
|
||||
/* Write the given expression to the object file */
|
||||
|
||||
void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize);
|
||||
/* Mark the address size of the given expression tree as guessed. The address
|
||||
* size passed as argument is the one NOT used, because the actual address
|
||||
* size wasn't known. Example: Zero page addressing was not used because symbol
|
||||
* is undefined, and absolute addressing was available.
|
||||
* This function will actually parse the expression tree for undefined symbols,
|
||||
* and mark these symbols accordingly.
|
||||
*/
|
||||
** size passed as argument is the one NOT used, because the actual address
|
||||
** size wasn't known. Example: Zero page addressing was not used because symbol
|
||||
** is undefined, and absolute addressing was available.
|
||||
** This function will actually parse the expression tree for undefined symbols,
|
||||
** and mark these symbols accordingly.
|
||||
*/
|
||||
|
||||
ExprNode* FuncBankByte (void);
|
||||
/* Handle the .BANKBYTE builtin function */
|
||||
@@ -179,6 +179,3 @@ ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size);
|
||||
/* End of expr.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ static const char* FeatureKeys[FEAT_COUNT] = {
|
||||
|
||||
feature_t FindFeature (const StrBuf* Key)
|
||||
/* Find the feature in a table and return the corresponding enum value. If the
|
||||
* feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
** feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
{
|
||||
feature_t F;
|
||||
|
||||
@@ -96,9 +96,9 @@ feature_t FindFeature (const StrBuf* Key)
|
||||
|
||||
feature_t SetFeature (const StrBuf* Key)
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
* In any case, return the feature found. An invalid Key will return
|
||||
* FEAT_UNKNOWN.
|
||||
*/
|
||||
** In any case, return the feature found. An invalid Key will return
|
||||
** FEAT_UNKNOWN.
|
||||
*/
|
||||
{
|
||||
/* Map the string to an enum value */
|
||||
feature_t Feature = FindFeature (Key);
|
||||
@@ -125,6 +125,3 @@ feature_t SetFeature (const StrBuf* Key)
|
||||
/* Return the value found */
|
||||
return Feature;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -80,20 +80,17 @@ typedef enum {
|
||||
|
||||
feature_t FindFeature (const StrBuf* Key);
|
||||
/* Find the feature in a table and return the corresponding enum value. If the
|
||||
* feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
** feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
|
||||
feature_t SetFeature (const StrBuf* Key);
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
* In any case, return the feature found. An invalid Key will return
|
||||
* FEAT_UNKNOWN.
|
||||
*/
|
||||
** In any case, return the feature found. An invalid Key will return
|
||||
** FEAT_UNKNOWN.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of feature.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,9 +66,9 @@ static const void* HT_GetKey (const void* Entry);
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2);
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -132,9 +132,9 @@ static const void* HT_GetKey (const void* Entry)
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2)
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
{
|
||||
return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
|
||||
}
|
||||
@@ -183,9 +183,9 @@ const StrBuf* GetFileName (unsigned Name)
|
||||
|
||||
if (Name == 0) {
|
||||
/* Name was defined outside any file scope, use the name of the first
|
||||
* file instead. Errors are then reported with a file position of
|
||||
* line zero in the first file.
|
||||
*/
|
||||
** file instead. Errors are then reported with a file position of
|
||||
** line zero in the first file.
|
||||
*/
|
||||
if (CollCount (&FileTab) == 0) {
|
||||
/* No files defined until now */
|
||||
return &ErrorMsg;
|
||||
@@ -223,8 +223,8 @@ unsigned GetFileIndex (const StrBuf* Name)
|
||||
unsigned AddFile (const StrBuf* Name, FileType Type,
|
||||
unsigned long Size, unsigned long MTime)
|
||||
/* Add a new file to the list of input files. Return the index of the file in
|
||||
* the table.
|
||||
*/
|
||||
** the table.
|
||||
*/
|
||||
{
|
||||
/* Create a new file entry and insert it into the tables */
|
||||
FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
|
||||
@@ -295,8 +295,8 @@ static void WriteDep (FILE* F, FileType Types)
|
||||
|
||||
static void CreateDepFile (const char* Name, FileType Types)
|
||||
/* Create a dependency file with the given name and place dependencies for
|
||||
* all files with the given types there.
|
||||
*/
|
||||
** all files with the given types there.
|
||||
*/
|
||||
{
|
||||
/* Open the file */
|
||||
FILE* F = fopen (Name, "w");
|
||||
@@ -336,5 +336,3 @@ void CreateDependencies (void)
|
||||
FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
|
||||
|
||||
/* An enum that describes different types of input files. The members are
|
||||
* choosen so that it is possible to combine them to bitsets
|
||||
*/
|
||||
** choosen so that it is possible to combine them to bitsets
|
||||
*/
|
||||
typedef enum {
|
||||
FT_MAIN = 0x01, /* Main input file */
|
||||
FT_INCLUDE = 0x02, /* Normal include file */
|
||||
@@ -76,8 +76,8 @@ unsigned GetFileIndex (const StrBuf* Name);
|
||||
unsigned AddFile (const StrBuf* Name, FileType Type,
|
||||
unsigned long Size, unsigned long MTime);
|
||||
/* Add a new file to the list of input files. Return the index of the file in
|
||||
* the table.
|
||||
*/
|
||||
** the table.
|
||||
*/
|
||||
|
||||
void WriteFiles (void);
|
||||
/* Write the list of input files to the object file */
|
||||
@@ -90,8 +90,3 @@ void CreateDependencies (void);
|
||||
/* End of filetab.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
Fragment* NewFragment (unsigned char Type, unsigned short Len)
|
||||
/* Create, initialize and return a new fragment. The fragment will be inserted
|
||||
* into the current segment.
|
||||
*/
|
||||
** into the current segment.
|
||||
*/
|
||||
{
|
||||
/* Create a new fragment */
|
||||
Fragment* F = xmalloc (sizeof (*F));
|
||||
@@ -66,6 +66,3 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
|
||||
/* And return it */
|
||||
return F;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -76,14 +76,11 @@ struct Fragment {
|
||||
|
||||
Fragment* NewFragment (unsigned char Type, unsigned short Len);
|
||||
/* Create, initialize and return a new fragment. The fragment will be inserted
|
||||
* into the current segment.
|
||||
*/
|
||||
** into the current segment.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of fragment.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +90,3 @@ extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
|
||||
/* End of global.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
|
||||
|
||||
|
||||
SearchPath* IncSearchPath; /* Standard include path */
|
||||
SearchPath* BinSearchPath; /* Binary include path */
|
||||
SearchPaths* IncSearchPath; /* Standard include path */
|
||||
SearchPaths* BinSearchPath; /* Binary include path */
|
||||
|
||||
|
||||
|
||||
@@ -75,13 +75,10 @@ void FinishIncludePaths (void)
|
||||
AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc");
|
||||
|
||||
/* Add some compiled-in search paths if defined at compile time. */
|
||||
#ifdef CA65_INC
|
||||
#if defined(CA65_INC) && !defined(_WIN32)
|
||||
AddSearchPath (IncSearchPath, STRINGIZE (CA65_INC));
|
||||
#endif
|
||||
|
||||
/* Add paths relative to the parent directory of the Windows binary. */
|
||||
AddSubSearchPathFromWinBin (IncSearchPath, "asminc");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
|
||||
|
||||
extern SearchPath* IncSearchPath; /* Standard include path */
|
||||
extern SearchPath* BinSearchPath; /* Binary include path */
|
||||
extern SearchPaths* IncSearchPath; /* Standard include path */
|
||||
extern SearchPaths* BinSearchPath; /* Binary include path */
|
||||
|
||||
|
||||
|
||||
@@ -71,6 +71,3 @@ void FinishIncludePaths (void);
|
||||
/* End of incpath.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
190
src/ca65/instr.c
190
src/ca65/instr.c
@@ -90,37 +90,37 @@ static void PutSEP (const InsDesc* Ins);
|
||||
|
||||
static void PutTAMn (const InsDesc* Ins);
|
||||
/* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
|
||||
* implicit addressing mode, the opcode byte in the table is actually the
|
||||
* second operand byte. The TAM instruction is the more generic form, it takes
|
||||
* an immediate argument.
|
||||
*/
|
||||
** implicit addressing mode, the opcode byte in the table is actually the
|
||||
** second operand byte. The TAM instruction is the more generic form, it takes
|
||||
** an immediate argument.
|
||||
*/
|
||||
|
||||
static void PutTMA (const InsDesc* Ins);
|
||||
/* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
|
||||
* in the argument byte may be set.
|
||||
*/
|
||||
** in the argument byte may be set.
|
||||
*/
|
||||
|
||||
static void PutTMAn (const InsDesc* Ins);
|
||||
/* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
|
||||
* implicit addressing mode, the opcode byte in the table is actually the
|
||||
* second operand byte. The TAM instruction is the more generic form, it takes
|
||||
* an immediate argument.
|
||||
*/
|
||||
** implicit addressing mode, the opcode byte in the table is actually the
|
||||
** second operand byte. The TAM instruction is the more generic form, it takes
|
||||
** an immediate argument.
|
||||
*/
|
||||
|
||||
static void PutTST (const InsDesc* Ins);
|
||||
/* Emit a TST instruction (HuC6280). */
|
||||
|
||||
static void PutJMP (const InsDesc* Ins);
|
||||
/* Handle the jump instruction for the 6502. Problem is that these chips have
|
||||
* a bug: If the address crosses a page, the upper byte gets not corrected and
|
||||
* the instruction will fail. The PutJmp function will add a linker assertion
|
||||
* to check for this case and is otherwise identical to PutAll.
|
||||
*/
|
||||
** a bug: If the address crosses a page, the upper byte gets not corrected and
|
||||
** the instruction will fail. The PutJmp function will add a linker assertion
|
||||
** to check for this case and is otherwise identical to PutAll.
|
||||
*/
|
||||
|
||||
static void PutRTS (const InsDesc* Ins attribute ((unused)));
|
||||
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
|
||||
* the enclosing scope is FAR.
|
||||
*/
|
||||
** the enclosing scope is FAR.
|
||||
*/
|
||||
|
||||
static void PutAll (const InsDesc* Ins);
|
||||
/* Handle all other instructions */
|
||||
@@ -516,8 +516,8 @@ static const struct {
|
||||
{ "INC", 0x000006F, 0x00, 4, PutAll },
|
||||
{ "INX", 0x0000001, 0xe8, 0, PutAll },
|
||||
{ "INY", 0x0000001, 0xc8, 0, PutAll },
|
||||
{ "JML", 0x0000810, 0x5c, 1, PutAll },
|
||||
{ "JMP", 0x0010818, 0x4c, 6, PutAll },
|
||||
{ "JML", 0x4000010, 0x5c, 1, PutAll },
|
||||
{ "JMP", 0x4010818, 0x4c, 6, PutAll },
|
||||
{ "JSL", 0x0000010, 0x20, 7, PutAll },
|
||||
{ "JSR", 0x0010018, 0x20, 7, PutAll },
|
||||
{ "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
|
||||
@@ -585,11 +585,6 @@ static const struct {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SUNPLUS
|
||||
/* Table for the SUNPLUS CPU */
|
||||
#include "sunplus.inc"
|
||||
#endif
|
||||
|
||||
/* Instruction table for the SWEET16 pseudo CPU */
|
||||
static const struct {
|
||||
unsigned Count;
|
||||
@@ -781,11 +776,6 @@ static const InsTable* InsTabs[CPU_COUNT] = {
|
||||
(const InsTable*) &InsTab65SC02,
|
||||
(const InsTable*) &InsTab65C02,
|
||||
(const InsTable*) &InsTab65816,
|
||||
#ifdef SUNPLUS
|
||||
(const InsTable*) &InsTabSunPlus,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
(const InsTable*) &InsTabSweet16,
|
||||
(const InsTable*) &InsTabHuC6280,
|
||||
0, /* Mitsubishi 740 */
|
||||
@@ -793,74 +783,74 @@ static const InsTable* InsTabs[CPU_COUNT] = {
|
||||
const InsTable* InsTab = (const InsTable*) &InsTab6502;
|
||||
|
||||
/* Table to build the effective 65xx opcode from a base opcode and an
|
||||
* addressing mode.
|
||||
*/
|
||||
** addressing mode.
|
||||
*/
|
||||
static unsigned char EATab[10][AM65I_COUNT] = {
|
||||
{ /* Table 0 */
|
||||
0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
|
||||
0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
|
||||
0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 1 */
|
||||
0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
|
||||
0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x80
|
||||
},
|
||||
{ /* Table 2 */
|
||||
0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 3 */
|
||||
0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 4 */
|
||||
0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 5 */
|
||||
0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 6 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x90
|
||||
},
|
||||
{ /* Table 7 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 8 */
|
||||
0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
|
||||
0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
{ /* Table 9 */
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x00, 0x00, 0x00
|
||||
},
|
||||
};
|
||||
|
||||
/* Table to build the effective SWEET16 opcode from a base opcode and an
|
||||
* addressing mode.
|
||||
*/
|
||||
** addressing mode.
|
||||
*/
|
||||
static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
|
||||
{ /* Table 0 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -898,6 +888,7 @@ unsigned char ExtBytes[AM65I_COUNT] = {
|
||||
1, /* Immidiate byte */
|
||||
2, /* Blockmove (65816) */
|
||||
7, /* Block transfer (HuC6280) */
|
||||
2, /* Absolute Indirect long */
|
||||
};
|
||||
|
||||
/* Table that encodes the additional bytes for each SWEET16 instruction */
|
||||
@@ -919,21 +910,21 @@ static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
|
||||
|
||||
static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
||||
/* Evaluate the effective address. All fields in A will be valid after calling
|
||||
* this function. The function returns true on success and false on errors.
|
||||
*/
|
||||
** this function. The function returns true on success and false on errors.
|
||||
*/
|
||||
{
|
||||
/* Get the set of possible addressing modes */
|
||||
GetEA (A);
|
||||
|
||||
/* From the possible addressing modes, remove the ones that are invalid
|
||||
* for this instruction or CPU.
|
||||
*/
|
||||
** for this instruction or CPU.
|
||||
*/
|
||||
A->AddrModeSet &= Ins->AddrMode;
|
||||
|
||||
/* If we have an expression, check it and remove any addressing modes that
|
||||
* are too small for the expression size. Since we have to study the
|
||||
* expression anyway, do also replace it by a simpler one if possible.
|
||||
*/
|
||||
** are too small for the expression size. Since we have to study the
|
||||
** expression anyway, do also replace it by a simpler one if possible.
|
||||
*/
|
||||
if (A->Expr) {
|
||||
ExprDesc ED;
|
||||
ED_Init (&ED);
|
||||
@@ -946,10 +937,10 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
||||
|
||||
if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
/* We don't know how big the expression is. If the instruction
|
||||
* allows just one addressing mode, assume this as address size
|
||||
* for the expression. Otherwise assume the default address size
|
||||
* for data.
|
||||
*/
|
||||
** allows just one addressing mode, assume this as address size
|
||||
** for the expression. Otherwise assume the default address size
|
||||
** for data.
|
||||
*/
|
||||
if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
|
||||
ED.AddrSize = ADDR_SIZE_ZP;
|
||||
} else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
|
||||
@@ -959,12 +950,12 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
||||
} else {
|
||||
ED.AddrSize = DataAddrSize;
|
||||
/* If the default address size of the data segment is unequal
|
||||
* to zero page addressing, but zero page addressing is
|
||||
* allowed by the instruction, mark all symbols in the
|
||||
* expression tree. This mark will be checked at end of
|
||||
* assembly, and a warning is issued, if a zero page symbol
|
||||
* was guessed wrong here.
|
||||
*/
|
||||
** to zero page addressing, but zero page addressing is
|
||||
** allowed by the instruction, mark all symbols in the
|
||||
** expression tree. This mark will be checked at end of
|
||||
** assembly, and a warning is issued, if a zero page symbol
|
||||
** was guessed wrong here.
|
||||
*/
|
||||
if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
|
||||
ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
|
||||
}
|
||||
@@ -996,11 +987,11 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
||||
A->AddrModeBit = (0x01UL << A->AddrMode);
|
||||
|
||||
/* If the instruction has a one byte operand and immediate addressing is
|
||||
* allowed but not used, check for an operand expression in the form
|
||||
* <label or >label, where label is a far or absolute label. If found,
|
||||
* emit a warning. This warning protects against a typo, where the '#'
|
||||
* for the immediate operand is omitted.
|
||||
*/
|
||||
** allowed but not used, check for an operand expression in the form
|
||||
** <label or >label, where label is a far or absolute label. If found,
|
||||
** emit a warning. This warning protects against a typo, where the '#'
|
||||
** for the immediate operand is omitted.
|
||||
*/
|
||||
if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) &&
|
||||
(A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
|
||||
ExtBytes[A->AddrMode] == 1) {
|
||||
@@ -1020,8 +1011,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
||||
A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
|
||||
|
||||
/* If feature force_range is active, and we have immediate addressing mode,
|
||||
* limit the expression to the maximum possible value.
|
||||
*/
|
||||
** limit the expression to the maximum possible value.
|
||||
*/
|
||||
if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
|
||||
A->AddrMode == AM65I_IMM_IMPLICIT) {
|
||||
if (ForceRange && A->Expr) {
|
||||
@@ -1052,9 +1043,9 @@ static void EmitCode (EffAddr* A)
|
||||
case 2:
|
||||
if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
|
||||
/* This is a 16 bit mode that uses an address. If in 65816,
|
||||
* mode, force this address into 16 bit range to allow
|
||||
* addressing inside a 64K segment.
|
||||
*/
|
||||
** mode, force this address into 16 bit range to allow
|
||||
** addressing inside a 64K segment.
|
||||
*/
|
||||
Emit2 (A->Opcode, GenWordExpr (A->Expr));
|
||||
} else {
|
||||
Emit2 (A->Opcode, A->Expr);
|
||||
@@ -1076,8 +1067,8 @@ static void EmitCode (EffAddr* A)
|
||||
|
||||
static long PutImmed8 (const InsDesc* Ins)
|
||||
/* Parse and emit an immediate 8 bit instruction. Return the value of the
|
||||
* operand if it's available and const.
|
||||
*/
|
||||
** operand if it's available and const.
|
||||
*/
|
||||
{
|
||||
EffAddr A;
|
||||
long Val = -1;
|
||||
@@ -1219,10 +1210,10 @@ static void PutSEP (const InsDesc* Ins)
|
||||
|
||||
static void PutTAMn (const InsDesc* Ins)
|
||||
/* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
|
||||
* implicit addressing mode, the opcode byte in the table is actually the
|
||||
* second operand byte. The TAM instruction is the more generic form, it takes
|
||||
* an immediate argument.
|
||||
*/
|
||||
** implicit addressing mode, the opcode byte in the table is actually the
|
||||
** second operand byte. The TAM instruction is the more generic form, it takes
|
||||
** an immediate argument.
|
||||
*/
|
||||
{
|
||||
/* Emit the TAM opcode itself */
|
||||
Emit0 (0x53);
|
||||
@@ -1235,8 +1226,8 @@ static void PutTAMn (const InsDesc* Ins)
|
||||
|
||||
static void PutTMA (const InsDesc* Ins)
|
||||
/* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
|
||||
* in the argument byte may be set.
|
||||
*/
|
||||
** in the argument byte may be set.
|
||||
*/
|
||||
{
|
||||
/* Use the generic handler */
|
||||
long Val = PutImmed8 (Ins);
|
||||
@@ -1257,10 +1248,10 @@ static void PutTMA (const InsDesc* Ins)
|
||||
|
||||
static void PutTMAn (const InsDesc* Ins)
|
||||
/* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
|
||||
* implicit addressing mode, the opcode byte in the table is actually the
|
||||
* second operand byte. The TAM instruction is the more generic form, it takes
|
||||
* an immediate argument.
|
||||
*/
|
||||
** implicit addressing mode, the opcode byte in the table is actually the
|
||||
** second operand byte. The TAM instruction is the more generic form, it takes
|
||||
** an immediate argument.
|
||||
*/
|
||||
{
|
||||
/* Emit the TMA opcode itself */
|
||||
Emit0 (0x43);
|
||||
@@ -1312,10 +1303,10 @@ static void PutTST (const InsDesc* Ins)
|
||||
|
||||
static void PutJMP (const InsDesc* Ins)
|
||||
/* Handle the jump instruction for the 6502. Problem is that these chips have
|
||||
* a bug: If the address crosses a page, the upper byte gets not corrected and
|
||||
* the instruction will fail. The PutJmp function will add a linker assertion
|
||||
* to check for this case and is otherwise identical to PutAll.
|
||||
*/
|
||||
** a bug: If the address crosses a page, the upper byte gets not corrected and
|
||||
** the instruction will fail. The PutJmp function will add a linker assertion
|
||||
** to check for this case and is otherwise identical to PutAll.
|
||||
*/
|
||||
{
|
||||
EffAddr A;
|
||||
|
||||
@@ -1326,9 +1317,9 @@ static void PutJMP (const InsDesc* Ins)
|
||||
if (A.AddrModeBit & AM65_ABS_IND) {
|
||||
|
||||
/* Compare the low byte of the expression to 0xFF to check for
|
||||
* a page cross. Be sure to use a copy of the expression otherwise
|
||||
* things will go weird later.
|
||||
*/
|
||||
** a page cross. Be sure to use a copy of the expression otherwise
|
||||
** things will go weird later.
|
||||
*/
|
||||
ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
|
||||
|
||||
/* Generate the message */
|
||||
@@ -1347,8 +1338,8 @@ static void PutJMP (const InsDesc* Ins)
|
||||
|
||||
static void PutRTS (const InsDesc* Ins attribute ((unused)))
|
||||
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
|
||||
* the enclosing scope is FAR.
|
||||
*/
|
||||
** the enclosing scope is FAR.
|
||||
*/
|
||||
{
|
||||
if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
|
||||
Emit0 (0x6B); /* RTL */
|
||||
@@ -1388,8 +1379,8 @@ static void PutSweet16 (const InsDesc* Ins)
|
||||
GetSweet16EA (&A);
|
||||
|
||||
/* From the possible addressing modes, remove the ones that are invalid
|
||||
* for this instruction or CPU.
|
||||
*/
|
||||
** for this instruction or CPU.
|
||||
*/
|
||||
A.AddrModeSet &= Ins->AddrMode;
|
||||
|
||||
/* Check if we have any adressing modes left */
|
||||
@@ -1475,16 +1466,16 @@ cpu_t GetCPU (void)
|
||||
|
||||
int FindInstruction (const StrBuf* Ident)
|
||||
/* Check if Ident is a valid mnemonic. If so, return the index in the
|
||||
* instruction table. If not, return -1.
|
||||
*/
|
||||
** instruction table. If not, return -1.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
const InsDesc* ID;
|
||||
char Key[sizeof (ID->Mnemonic)];
|
||||
|
||||
/* Shortcut for the "none" CPU: If there are no instructions to search
|
||||
* for, bail out early.
|
||||
*/
|
||||
** for, bail out early.
|
||||
*/
|
||||
if (InsTab->Count == 0) {
|
||||
/* Not found */
|
||||
return -1;
|
||||
@@ -1494,8 +1485,8 @@ int FindInstruction (const StrBuf* Ident)
|
||||
I = 0;
|
||||
while (I < SB_GetLen (Ident)) {
|
||||
/* If the identifier is longer than the longest mnemonic, it cannot
|
||||
* be one.
|
||||
*/
|
||||
** be one.
|
||||
*/
|
||||
if (I >= sizeof (Key) - 1) {
|
||||
/* Not found, no need for further action */
|
||||
return -1;
|
||||
@@ -1530,6 +1521,3 @@ void HandleInstruction (unsigned Index)
|
||||
/* Call the handler */
|
||||
InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
|
||||
|
||||
/* Constants for the addressing mode. If an opcode is available in zero page
|
||||
* and absolut adressing mode, both bits are set. When checking for valid
|
||||
* modes, the zeropage bit is checked first. Similar, the implicit bit is set
|
||||
* on accu adressing modes, so the 'A' for accu adressing is not needed (but
|
||||
* may be specified).
|
||||
* When assembling for the 6502 or 65C02, all addressing modes that are not
|
||||
* available on these CPUs are removed before doing any checks.
|
||||
*/
|
||||
** and absolut adressing mode, both bits are set. When checking for valid
|
||||
** modes, the zeropage bit is checked first. Similar, the implicit bit is set
|
||||
** on accu adressing modes, so the 'A' for accu adressing is not needed (but
|
||||
** may be specified).
|
||||
** When assembling for the 6502 or 65C02, all addressing modes that are not
|
||||
** available on these CPUs are removed before doing any checks.
|
||||
*/
|
||||
#define AM65_IMPLICIT 0x00000003UL
|
||||
#define AM65_ACCU 0x00000002UL
|
||||
#define AM65_DIR 0x00000004UL
|
||||
@@ -84,6 +84,7 @@
|
||||
#define AM65_IMM_IMPLICIT 0x00800000UL
|
||||
#define AM65_BLOCKMOVE 0x01000000UL
|
||||
#define AM65_BLOCKXFER 0x02000000UL
|
||||
#define AM65_ABS_IND_LONG 0x04000000UL
|
||||
|
||||
/* Bitmask for all ZP operations that have correspondent ABS ops */
|
||||
#define AM65_SET_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND)
|
||||
@@ -107,7 +108,7 @@
|
||||
#define AM65I_IMM_ACCU 21
|
||||
#define AM65I_IMM_INDEX 22
|
||||
#define AM65I_IMM_IMPLICIT 23
|
||||
#define AM65I_COUNT 26
|
||||
#define AM65I_COUNT 27
|
||||
|
||||
|
||||
|
||||
@@ -167,8 +168,8 @@ cpu_t GetCPU (void);
|
||||
|
||||
int FindInstruction (const StrBuf* Ident);
|
||||
/* Check if Ident is a valid mnemonic. If so, return the index in the
|
||||
* instruction table. If not, return -1.
|
||||
*/
|
||||
** instruction table. If not, return -1.
|
||||
*/
|
||||
|
||||
void HandleInstruction (unsigned Index);
|
||||
/* Handle the mnemonic with the given index */
|
||||
@@ -178,8 +179,3 @@ void HandleInstruction (unsigned Index);
|
||||
/* End of instr.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* R<EFBFBD>merstra<EFBFBD>e 52 */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@@ -120,12 +120,12 @@ void PopInput (void)
|
||||
|
||||
int InputFromStack (void)
|
||||
/* Try to get input from the input stack. Return true if we had such input,
|
||||
* return false otherwise.
|
||||
*/
|
||||
** return false otherwise.
|
||||
*/
|
||||
{
|
||||
/* Repeatedly call the TOS routine until we have a token or if run out of
|
||||
* routines.
|
||||
*/
|
||||
** routines.
|
||||
*/
|
||||
while (IStack) {
|
||||
if (IStack->Func (IStack->Data) != 0) {
|
||||
/* We have a token */
|
||||
@@ -149,13 +149,10 @@ int HavePushedInput (void)
|
||||
|
||||
void CheckInputStack (void)
|
||||
/* Called from the scanner before closing an input file. Will check for any
|
||||
* stuff on the input stack.
|
||||
*/
|
||||
** stuff on the input stack.
|
||||
*/
|
||||
{
|
||||
if (IStack) {
|
||||
Error ("Open %s", IStack->Desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,23 +52,19 @@ void PopInput (void);
|
||||
|
||||
int InputFromStack (void);
|
||||
/* Try to get input from the input stack. Return true if we had such input,
|
||||
* return false otherwise.
|
||||
*/
|
||||
** return false otherwise.
|
||||
*/
|
||||
|
||||
int HavePushedInput (void);
|
||||
/* Return true if we have stacked input available, return false if not */
|
||||
|
||||
void CheckInputStack (void);
|
||||
/* Called from the scanner before closing an input file. Will check for any
|
||||
* stuff on the input stack.
|
||||
*/
|
||||
** stuff on the input stack.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of istack.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ static const void* HT_GetKey (const void* Entry);
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2);
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -145,9 +145,9 @@ static const void* HT_GetKey (const void* Entry)
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2)
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
{
|
||||
/* Convert both parameters to FileInfoKey pointers */
|
||||
const LineInfoKey* K1 = Key1;
|
||||
@@ -272,8 +272,8 @@ void InitLineInfo (void)
|
||||
CollGrow (&LineInfoList, 200);
|
||||
|
||||
/* Create a LineInfo for the default source. This is necessary to allow
|
||||
* error message to be generated without any input file open.
|
||||
*/
|
||||
** error message to be generated without any input file open.
|
||||
*/
|
||||
AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0);
|
||||
}
|
||||
|
||||
@@ -289,9 +289,9 @@ void DoneLineInfo (void)
|
||||
}
|
||||
|
||||
/* Walk over the entries in the hash table and sort them into used and
|
||||
* unused ones. Add the used ones to the line info list and assign them
|
||||
* an id.
|
||||
*/
|
||||
** unused ones. Add the used ones to the line info list and assign them
|
||||
** an id.
|
||||
*/
|
||||
HT_Walk (&LineInfoTab, CheckLineInfo, 0);
|
||||
}
|
||||
|
||||
@@ -304,14 +304,14 @@ void EndLine (LineInfo* LI)
|
||||
CloseSpanList (&LI->OpenSpans);
|
||||
|
||||
/* Move the spans to the list of all spans for this line, then clear the
|
||||
* list of open spans.
|
||||
*/
|
||||
** list of open spans.
|
||||
*/
|
||||
CollTransfer (&LI->Spans, &LI->OpenSpans);
|
||||
CollDeleteAll (&LI->OpenSpans);
|
||||
|
||||
/* Line info is no longer active - remove it from the list of current
|
||||
* line infos.
|
||||
*/
|
||||
** line infos.
|
||||
*/
|
||||
CollDeleteItem (&CurLineInfo, LI);
|
||||
}
|
||||
|
||||
@@ -328,8 +328,8 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
|
||||
Key.Type = LI_MAKE_TYPE (Type, Count);
|
||||
|
||||
/* Try to find a line info with this position and type in the hash table.
|
||||
* If so, reuse it. Otherwise create a new one.
|
||||
*/
|
||||
** If so, reuse it. Otherwise create a new one.
|
||||
*/
|
||||
LI = HT_Find (&LineInfoTab, &Key);
|
||||
if (LI == 0) {
|
||||
/* Allocate a new LineInfo */
|
||||
@@ -350,9 +350,9 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
|
||||
|
||||
void NewAsmLine (void)
|
||||
/* Start a new assembler input line. Use this function when generating new
|
||||
* line of LI_TYPE_ASM. It will check if line and/or file have actually
|
||||
* changed, end the old and start the new line as necessary.
|
||||
*/
|
||||
** line of LI_TYPE_ASM. It will check if line and/or file have actually
|
||||
** changed, end the old and start the new line as necessary.
|
||||
*/
|
||||
{
|
||||
/* Check if we can reuse the old line */
|
||||
if (AsmLineInfo) {
|
||||
@@ -374,8 +374,8 @@ void NewAsmLine (void)
|
||||
|
||||
LineInfo* GetAsmLineInfo (void)
|
||||
/* Return the line info for the current assembler file. The function will
|
||||
* bump the reference counter before returning the line info.
|
||||
*/
|
||||
** bump the reference counter before returning the line info.
|
||||
*/
|
||||
{
|
||||
++AsmLineInfo->RefCount;
|
||||
return AsmLineInfo;
|
||||
@@ -395,9 +395,9 @@ void ReleaseLineInfo (LineInfo* LI)
|
||||
|
||||
void GetFullLineInfo (Collection* LineInfos)
|
||||
/* Return full line infos, that is line infos for currently active Slots. The
|
||||
* infos will be added to the given collection, existing entries will be left
|
||||
* intact. The reference count of all added entries will be increased.
|
||||
*/
|
||||
** infos will be added to the given collection, existing entries will be left
|
||||
** intact. The reference count of all added entries will be increased.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
@@ -414,8 +414,8 @@ void GetFullLineInfo (Collection* LineInfos)
|
||||
|
||||
void ReleaseFullLineInfo (Collection* LineInfos)
|
||||
/* Decrease the reference count for a collection full of LineInfos, then clear
|
||||
* the collection.
|
||||
*/
|
||||
** the collection.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
@@ -501,6 +501,3 @@ void WriteLineInfos (void)
|
||||
/* End of line infos */
|
||||
ObjEndLineInfos ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -77,28 +77,28 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count);
|
||||
|
||||
void NewAsmLine (void);
|
||||
/* Start a new assembler input line. Use this function when generating new
|
||||
* line of LI_TYPE_ASM. It will check if line and/or file have actually
|
||||
* changed, end the old and start the new line as necessary.
|
||||
*/
|
||||
** line of LI_TYPE_ASM. It will check if line and/or file have actually
|
||||
** changed, end the old and start the new line as necessary.
|
||||
*/
|
||||
|
||||
LineInfo* GetAsmLineInfo (void);
|
||||
/* Return the line info for the current assembler file. The function will
|
||||
* bump the reference counter before returning the line info.
|
||||
*/
|
||||
** bump the reference counter before returning the line info.
|
||||
*/
|
||||
|
||||
void ReleaseLineInfo (LineInfo* LI);
|
||||
/* Decrease the reference count for a line info */
|
||||
|
||||
void GetFullLineInfo (Collection* LineInfos);
|
||||
/* Return full line infos, that is line infos for currently active Slots. The
|
||||
* infos will be added to the given collection, existing entries will be left
|
||||
* intact. The reference count of all added entries will be increased.
|
||||
*/
|
||||
** infos will be added to the given collection, existing entries will be left
|
||||
** intact. The reference count of all added entries will be increased.
|
||||
*/
|
||||
|
||||
void ReleaseFullLineInfo (Collection* LineInfos);
|
||||
/* Decrease the reference count for a collection full of LineInfos, then clear
|
||||
* the collection.
|
||||
*/
|
||||
** the collection.
|
||||
*/
|
||||
|
||||
const FilePos* GetSourcePos (const LineInfo* LI);
|
||||
/* Return the source file position from the given line info */
|
||||
@@ -115,8 +115,5 @@ void WriteLineInfos (void);
|
||||
|
||||
|
||||
/* End of lineinfo.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -131,8 +131,8 @@ void EnableListing (void)
|
||||
{
|
||||
if (SB_GetLen (&ListingName) > 0) {
|
||||
/* If we're about to enable the listing, do this for the current line
|
||||
* also, so we will see the source line that did this.
|
||||
*/
|
||||
** also, so we will see the source line that did this.
|
||||
*/
|
||||
if (ListingEnabled++ == 0) {
|
||||
LineCur->Output = 1;
|
||||
}
|
||||
@@ -172,9 +172,9 @@ void InitListingLine (void)
|
||||
{
|
||||
if (SB_GetLen (&ListingName) > 0) {
|
||||
/* Make the last loaded line the current line */
|
||||
/* ###### This code is a hack! We really need to do it right
|
||||
* as soon as we know, how:-(
|
||||
*/
|
||||
/* ###### This code is a hack! We really need to do it right --
|
||||
** as soon as we know how. :-(
|
||||
*/
|
||||
if (LineCur && LineCur->Next && LineCur->Next != LineLast) {
|
||||
ListLine* L = LineCur;
|
||||
do {
|
||||
@@ -217,8 +217,8 @@ static char* AddHex (char* S, unsigned Val)
|
||||
|
||||
static void PrintPageHeader (FILE* F, const ListLine* L)
|
||||
/* Print the header for a new page. It is assumed that the given line is the
|
||||
* last line of the previous page.
|
||||
*/
|
||||
** last line of the previous page.
|
||||
*/
|
||||
{
|
||||
/* Gte a pointer to the current input file */
|
||||
const StrBuf* CurFile = GetFileName (L->File);
|
||||
@@ -250,8 +250,8 @@ static void PrintLine (FILE* F, const char* Header, const char* Line, const List
|
||||
++PageLines;
|
||||
|
||||
/* Switch to a new page if needed. Do not switch, if the current line is
|
||||
* the last one, to avoid pages that consist of just the header.
|
||||
*/
|
||||
** the last one, to avoid pages that consist of just the header.
|
||||
*/
|
||||
if (PageLength > 0 && PageLines >= PageLength && L->Next != 0) {
|
||||
/* Do a formfeed */
|
||||
putc ('\f', F);
|
||||
@@ -392,16 +392,16 @@ void CreateListing (void)
|
||||
}
|
||||
|
||||
/* Output the data. The format of a listing line is:
|
||||
*
|
||||
* PPPPPPm I 11 22 33 44
|
||||
*
|
||||
* where
|
||||
*
|
||||
* PPPPPP is the PC
|
||||
* m is the mode ('r' or empty)
|
||||
* I is the include level
|
||||
* 11 .. are code or data bytes
|
||||
*/
|
||||
**
|
||||
** PPPPPPm I 11 22 33 44
|
||||
**
|
||||
** where
|
||||
**
|
||||
** PPPPPP is the PC
|
||||
** m is the mode ('r' or empty)
|
||||
** I is the include level
|
||||
** 11 .. are code or data bytes
|
||||
*/
|
||||
Line = L->Line;
|
||||
B = Buf;
|
||||
while (Count) {
|
||||
@@ -420,9 +420,9 @@ void CreateListing (void)
|
||||
Count -= Chunk;
|
||||
|
||||
/* Increment the program counter. Since we don't need the PC stored
|
||||
* in the LineList object for anything else, just increment this
|
||||
* variable.
|
||||
*/
|
||||
** in the LineList object for anything else, just increment this
|
||||
** variable.
|
||||
*/
|
||||
L->PC += Chunk;
|
||||
|
||||
/* Copy the bytes into the line */
|
||||
@@ -452,6 +452,3 @@ void CreateListing (void)
|
||||
/* Close the listing file */
|
||||
(void) fclose (F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -123,6 +123,3 @@ void CreateListing (void);
|
||||
/* End of listing.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
113
src/ca65/macro.c
113
src/ca65/macro.c
@@ -70,9 +70,9 @@ static const void* HT_GetKey (const void* Entry);
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2);
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -176,9 +176,9 @@ static const void* HT_GetKey (const void* Entry)
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2)
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
{
|
||||
return SB_Compare (Key1, Key2);
|
||||
}
|
||||
@@ -399,8 +399,8 @@ void MacDef (unsigned Style)
|
||||
return;
|
||||
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
|
||||
/* The identifier is a name of a 6502 instruction, which is not
|
||||
* allowed if not explicitly enabled.
|
||||
*/
|
||||
** allowed if not explicitly enabled.
|
||||
*/
|
||||
Error ("Cannot use an instruction as macro name");
|
||||
MacSkipDef (Style);
|
||||
return;
|
||||
@@ -423,8 +423,8 @@ void MacDef (unsigned Style)
|
||||
NextTok ();
|
||||
|
||||
/* If we have a DEFINE style macro, we may have parameters in braces,
|
||||
* otherwise we may have parameters without braces.
|
||||
*/
|
||||
** otherwise we may have parameters without braces.
|
||||
*/
|
||||
if (Style == MAC_STYLE_CLASSIC) {
|
||||
HaveParams = 1;
|
||||
} else {
|
||||
@@ -476,8 +476,8 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* For class macros, we expect a separator token, for define style macros,
|
||||
* we expect the closing paren.
|
||||
*/
|
||||
** we expect the closing paren.
|
||||
*/
|
||||
if (Style == MAC_STYLE_CLASSIC) {
|
||||
ConsumeSep ();
|
||||
} else if (HaveParams) {
|
||||
@@ -485,10 +485,10 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* Preparse the macro body. We will read the tokens until we reach end of
|
||||
* file, or a .endmacro (or end of line for DEFINE style macros) and store
|
||||
* them into an token list internal to the macro. For classic macros, there
|
||||
* the .LOCAL command is detected and removed at this time.
|
||||
*/
|
||||
** file, or a .endmacro (or end of line for DEFINE style macros) and store
|
||||
** them into an token list internal to the macro. For classic macros, there
|
||||
** the .LOCAL command is detected and removed at this time.
|
||||
*/
|
||||
while (1) {
|
||||
|
||||
/* Check for end of macro */
|
||||
@@ -597,8 +597,8 @@ Done:
|
||||
|
||||
void MacUndef (const StrBuf* Name, unsigned char Style)
|
||||
/* Undefine the macro with the given name and style. A style mismatch is
|
||||
* treated as if the macro didn't exist.
|
||||
*/
|
||||
** treated as if the macro didn't exist.
|
||||
*/
|
||||
{
|
||||
/* Search for the macro */
|
||||
Macro* M = HT_Find (&MacroTab, Name);
|
||||
@@ -624,9 +624,9 @@ void MacUndef (const StrBuf* Name, unsigned char Style)
|
||||
|
||||
static int MacExpand (void* Data)
|
||||
/* If we're currently expanding a macro, set the the scanner token and
|
||||
* attribute to the next value and return true. If we are not expanding
|
||||
* a macro, return false.
|
||||
*/
|
||||
** attribute to the next value and return true. If we are not expanding
|
||||
** a macro, return false.
|
||||
*/
|
||||
{
|
||||
/* Cast the Data pointer to the actual data structure */
|
||||
MacExp* Mac = (MacExp*) Data;
|
||||
@@ -645,8 +645,8 @@ static int MacExpand (void* Data)
|
||||
}
|
||||
|
||||
/* We're expanding a macro. Check if we are expanding one of the
|
||||
* macro parameters.
|
||||
*/
|
||||
** macro parameters.
|
||||
*/
|
||||
ExpandParam:
|
||||
if (Mac->ParamExp) {
|
||||
|
||||
@@ -674,8 +674,8 @@ ExpandParam:
|
||||
}
|
||||
|
||||
/* We're not expanding macro parameters. Check if we have tokens left from
|
||||
* the macro itself.
|
||||
*/
|
||||
** the macro itself.
|
||||
*/
|
||||
if (Mac->Exp) {
|
||||
|
||||
/* Use next macro token */
|
||||
@@ -716,10 +716,10 @@ ExpandParam:
|
||||
while (I) {
|
||||
if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
|
||||
/* This is in fact a local symbol, change the name. Be sure
|
||||
* to generate a local label name if the original name was
|
||||
* a local label, and also generate a name that cannot be
|
||||
* generated by a user.
|
||||
*/
|
||||
** to generate a local label name if the original name was
|
||||
** a local label, and also generate a name that cannot be
|
||||
** generated by a user.
|
||||
*/
|
||||
if (SB_At (&I->Id, 0) == LocalStart) {
|
||||
/* Must generate a local symbol */
|
||||
SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
|
||||
@@ -753,14 +753,14 @@ ExpandParam:
|
||||
Mac->Final = 0;
|
||||
|
||||
/* Problem: When a .define style macro is expanded within the call
|
||||
* of a classic one, the latter may be terminated and removed while
|
||||
* the expansion of the .define style macro is still active. Because
|
||||
* line info slots are "stacked", this runs into a CHECK FAILED. For
|
||||
* now, we will fix that by removing the .define style macro expansion
|
||||
* immediately, once the final token is placed. The better solution
|
||||
* would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
|
||||
* to be called in FIFO order, but this is a bigger change.
|
||||
*/
|
||||
** of a classic one, the latter may be terminated and removed while
|
||||
** the expansion of the .define style macro is still active. Because
|
||||
** line info slots are "stacked", this runs into a CHECK FAILED. For
|
||||
** now, we will fix that by removing the .define style macro expansion
|
||||
** immediately, once the final token is placed. The better solution
|
||||
** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
|
||||
** to be called in FIFO order, but this is a bigger change.
|
||||
*/
|
||||
/* End of macro expansion and pop the input function */
|
||||
FreeMacExp (Mac);
|
||||
PopInput ();
|
||||
@@ -836,8 +836,8 @@ static void StartExpClassic (MacExp* E)
|
||||
++E->ParamCount;
|
||||
|
||||
/* If the macro argument was enclosed in curly braces, end-of-line
|
||||
* is an error. Skip the closing curly brace.
|
||||
*/
|
||||
** 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");
|
||||
@@ -867,8 +867,8 @@ 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.
|
||||
*/
|
||||
** as there are formal ones. Get the parameter count.
|
||||
*/
|
||||
unsigned Count = E->M->ParamCount;
|
||||
|
||||
/* Skip the current token */
|
||||
@@ -915,8 +915,8 @@ static void StartExpDefine (MacExp* E)
|
||||
++E->ParamCount;
|
||||
|
||||
/* If the macro argument was enclosed in curly braces, end-of-line
|
||||
* is an error. Skip the closing curly brace.
|
||||
*/
|
||||
** is an error. Skip the closing curly brace.
|
||||
*/
|
||||
if (Term == TOK_RCURLY) {
|
||||
if (TokIsSep (CurTok.Tok)) {
|
||||
Error ("End of line encountered within macro argument");
|
||||
@@ -936,10 +936,10 @@ static void StartExpDefine (MacExp* E)
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** 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 */
|
||||
@@ -963,8 +963,8 @@ void MacExpandStart (Macro* M)
|
||||
}
|
||||
|
||||
/* Don't allow too many nested macro expansions - otherwise it is possible
|
||||
* to force an endless loop and assembler crash.
|
||||
*/
|
||||
** to force an endless loop and assembler crash.
|
||||
*/
|
||||
if (MacExpansions >= MAX_MACEXPANSIONS) {
|
||||
Error ("Too many nested macro expansions");
|
||||
return;
|
||||
@@ -997,8 +997,8 @@ void MacAbort (void)
|
||||
|
||||
Macro* FindMacro (const StrBuf* Name)
|
||||
/* Try to find the macro with the given name and return it. If no macro with
|
||||
* this name was found, return NULL.
|
||||
*/
|
||||
** this name was found, return NULL.
|
||||
*/
|
||||
{
|
||||
Macro* M = HT_Find (&MacroTab, Name);
|
||||
return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0;
|
||||
@@ -1008,8 +1008,8 @@ Macro* FindMacro (const StrBuf* Name)
|
||||
|
||||
Macro* FindDefine (const StrBuf* Name)
|
||||
/* Try to find the define style macro with the given name and return it. If no
|
||||
* such macro was found, return NULL.
|
||||
*/
|
||||
** such macro was found, return NULL.
|
||||
*/
|
||||
{
|
||||
Macro* M;
|
||||
|
||||
@@ -1043,12 +1043,9 @@ void DisableDefineStyleMacros (void)
|
||||
|
||||
void EnableDefineStyleMacros (void)
|
||||
/* Re-enable define style macros previously disabled with
|
||||
* DisableDefineStyleMacros.
|
||||
*/
|
||||
** DisableDefineStyleMacros.
|
||||
*/
|
||||
{
|
||||
PRECONDITION (DisableDefines > 0);
|
||||
--DisableDefines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ void MacDef (unsigned Style);
|
||||
|
||||
void MacUndef (const struct StrBuf* Name, unsigned char Style);
|
||||
/* Undefine the macro with the given name and style. A style mismatch is
|
||||
* treated as if the macro didn't exist.
|
||||
*/
|
||||
** treated as if the macro didn't exist.
|
||||
*/
|
||||
|
||||
void MacExpandStart (Macro* M);
|
||||
/* Start expanding a macro */
|
||||
@@ -86,13 +86,13 @@ void MacAbort (void);
|
||||
|
||||
Macro* FindMacro (const struct StrBuf* Name);
|
||||
/* Try to find the macro with the given name and return it. If no macro with
|
||||
* this name was found, return NULL.
|
||||
*/
|
||||
** this name was found, return NULL.
|
||||
*/
|
||||
|
||||
Macro* FindDefine (const struct StrBuf* Name);
|
||||
/* Try to find the define style macro with the given name and return it. If no
|
||||
* such macro was found, return NULL.
|
||||
*/
|
||||
** such macro was found, return NULL.
|
||||
*/
|
||||
|
||||
int InMacExpansion (void);
|
||||
/* Return true if we're currently expanding a macro */
|
||||
@@ -102,14 +102,11 @@ void DisableDefineStyleMacros (void);
|
||||
|
||||
void EnableDefineStyleMacros (void);
|
||||
/* Re-enable define style macros previously disabled with
|
||||
* DisableDefineStyleMacros.
|
||||
*/
|
||||
** DisableDefineStyleMacros.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of macro.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* main.c */
|
||||
/* */
|
||||
@@ -204,6 +205,10 @@ static void SetSys (const char* Sys)
|
||||
AbEnd ("Cannot use `module' as a target for the assembler");
|
||||
break;
|
||||
|
||||
case TGT_ATARI5200:
|
||||
NewSymbol ("__ATARI5200__", 1);
|
||||
break;
|
||||
|
||||
case TGT_ATARI:
|
||||
NewSymbol ("__ATARI__", 1);
|
||||
break;
|
||||
@@ -518,8 +523,8 @@ static void OptListing (const char* Opt, const char* Arg)
|
||||
/* Create a listing file */
|
||||
{
|
||||
/* Since the meaning of -l and --listing has changed, print an error if
|
||||
* the filename is empty or begins with the option char.
|
||||
*/
|
||||
** the filename is empty or begins with the option char.
|
||||
*/
|
||||
if (Arg == 0 || *Arg == '\0' || *Arg == '-') {
|
||||
Fatal ("The meaning of `%s' has changed. It does now "
|
||||
"expect a file name as argument.", Opt);
|
||||
@@ -634,8 +639,8 @@ static void OneLine (void)
|
||||
int Instr = -1;
|
||||
|
||||
/* Initialize the new listing line if we are actually reading from file
|
||||
* and not from internally pushed input.
|
||||
*/
|
||||
** and not from internally pushed input.
|
||||
*/
|
||||
if (!HavePushedInput ()) {
|
||||
InitListingLine ();
|
||||
}
|
||||
@@ -647,25 +652,28 @@ static void OneLine (void)
|
||||
}
|
||||
|
||||
/* If the first token on the line is an identifier, check for a macro or
|
||||
* an instruction.
|
||||
*/
|
||||
** an instruction.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_IDENT) {
|
||||
if (!UbiquitousIdents) {
|
||||
/* Macros and symbols cannot use instruction names */
|
||||
if (UbiquitousIdents) {
|
||||
/* Macros CAN be instructions, so check for them first */
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
if (Mac == 0) {
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may NOT use the names of instructions */
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
if (Instr < 0) {
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may use the names of instructions */
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle an identifier. This may be a cheap local symbol, or a fully
|
||||
* scoped identifier which may start with a namespace token (for global
|
||||
* namespace)
|
||||
*/
|
||||
** scoped identifier which may start with a namespace token (for global
|
||||
** namespace)
|
||||
*/
|
||||
if (CurTok.Tok == TOK_LOCAL_IDENT ||
|
||||
CurTok.Tok == TOK_NAMESPACE ||
|
||||
(CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) {
|
||||
@@ -677,8 +685,8 @@ static void OneLine (void)
|
||||
Sym = ParseAnySymName (SYM_ALLOC_NEW);
|
||||
|
||||
/* If a colon follows, this is a label definition. If there
|
||||
* is no colon, it's an assignment.
|
||||
*/
|
||||
** is no colon, it's an assignment.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) {
|
||||
|
||||
/* Determine the symbol flags from the assignment token */
|
||||
@@ -705,8 +713,8 @@ static void OneLine (void)
|
||||
Expr = GenLiteralExpr (ConstExpression ());
|
||||
|
||||
/* Define the symbol with the constant expression following
|
||||
* the '='
|
||||
*/
|
||||
** the '='
|
||||
*/
|
||||
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
|
||||
|
||||
/* Don't allow anything after a symbol definition */
|
||||
@@ -716,8 +724,8 @@ static void OneLine (void)
|
||||
} else {
|
||||
|
||||
/* A label. Remember the current segment, so we can later
|
||||
* determine the size of the data stored under the label.
|
||||
*/
|
||||
** determine the size of the data stored under the label.
|
||||
*/
|
||||
Seg = ActiveSeg;
|
||||
PC = GetPC ();
|
||||
|
||||
@@ -725,9 +733,9 @@ static void OneLine (void)
|
||||
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
|
||||
|
||||
/* Skip the colon. If NoColonLabels is enabled, allow labels
|
||||
* without a colon if there is no whitespace before the
|
||||
* identifier.
|
||||
*/
|
||||
** without a colon if there is no whitespace before the
|
||||
** identifier.
|
||||
*/
|
||||
if (CurTok.Tok != TOK_COLON) {
|
||||
if (HadWS || !NoColonLabels) {
|
||||
Error ("`:' expected");
|
||||
@@ -742,18 +750,21 @@ static void OneLine (void)
|
||||
}
|
||||
|
||||
/* If we come here, a new identifier may be waiting, which may
|
||||
* be a macro or instruction.
|
||||
*/
|
||||
** be a macro or instruction.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_IDENT) {
|
||||
if (!UbiquitousIdents) {
|
||||
/* Macros and symbols cannot use instruction names */
|
||||
if (UbiquitousIdents) {
|
||||
/* Macros CAN be instructions, so check for them first */
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
if (Mac == 0) {
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may NOT use the names of instructions */
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
if (Instr < 0) {
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may use the names of instructions */
|
||||
Mac = FindMacro (&CurTok.SVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -766,8 +777,7 @@ static void OneLine (void)
|
||||
} else if (Mac != 0) {
|
||||
/* A macro expansion */
|
||||
MacExpandStart (Mac);
|
||||
} else if (Instr >= 0 ||
|
||||
(UbiquitousIdents && ((Instr = FindInstruction (&CurTok.SVal)) >= 0))) {
|
||||
} else if (Instr >= 0) {
|
||||
/* A mnemonic - assemble one instruction */
|
||||
HandleInstruction (Instr);
|
||||
} else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
|
||||
@@ -784,9 +794,9 @@ static void OneLine (void)
|
||||
}
|
||||
|
||||
/* If we have defined a label, remember its size. Sym is also set by
|
||||
* a symbol assignment, but in this case Done is false, so we don't
|
||||
* come here.
|
||||
*/
|
||||
** a symbol assignment, but in this case Done is false, so we don't
|
||||
** come here.
|
||||
*/
|
||||
if (Sym) {
|
||||
unsigned long Size;
|
||||
if (Seg == ActiveSeg) {
|
||||
@@ -910,13 +920,13 @@ int main (int argc, char* argv [])
|
||||
SegInit ();
|
||||
|
||||
/* Enter the base lexical level. We must do that here, since we may
|
||||
* define symbols using -D.
|
||||
*/
|
||||
** define symbols using -D.
|
||||
*/
|
||||
SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0);
|
||||
|
||||
/* Initialize the line infos. Must be done here, since we need line infos
|
||||
* for symbol definitions.
|
||||
*/
|
||||
** for symbol definitions.
|
||||
*/
|
||||
InitLineInfo ();
|
||||
|
||||
/* Check the parameters */
|
||||
@@ -1098,8 +1108,8 @@ int main (int argc, char* argv [])
|
||||
DoneLineInfo ();
|
||||
|
||||
/* If we didn't have any errors, create the object, listing and
|
||||
* dependency files
|
||||
*/
|
||||
** dependency files
|
||||
*/
|
||||
if (ErrorCount == 0) {
|
||||
CreateObjFile ();
|
||||
if (SB_GetLen (&ListingName) > 0) {
|
||||
@@ -1114,6 +1124,3 @@ int main (int argc, char* argv [])
|
||||
/* Return an apropriate exit code */
|
||||
return (ErrorCount == 0)? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ static unsigned RawMode = 0; /* Raw token mode flag/counter */
|
||||
|
||||
static int LookAtStrCon (void)
|
||||
/* Make sure the next token is a string constant. If not, print an error
|
||||
* messages skip the remainder of the line and return false. Otherwise return
|
||||
* true.
|
||||
*/
|
||||
** messages skip the remainder of the line and return false. Otherwise return
|
||||
** true.
|
||||
*/
|
||||
{
|
||||
if (CurTok.Tok != TOK_STRCON) {
|
||||
Error ("String constant expected");
|
||||
@@ -93,10 +93,10 @@ static int LookAtStrCon (void)
|
||||
|
||||
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.
|
||||
*/
|
||||
** 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 */
|
||||
@@ -176,8 +176,8 @@ static void FuncConcat (void)
|
||||
}
|
||||
|
||||
/* We expect a closing parenthesis, but will not skip it but replace it
|
||||
* by the string token just created.
|
||||
*/
|
||||
** by the string token just created.
|
||||
*/
|
||||
if (CurTok.Tok != TOK_RPAREN) {
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
@@ -220,8 +220,8 @@ static void FuncIdent (void)
|
||||
}
|
||||
|
||||
/* Check that the string contains a valid identifier. While doing so,
|
||||
* determine if it is a cheap local, or global one.
|
||||
*/
|
||||
** determine if it is a cheap local, or global one.
|
||||
*/
|
||||
SB_Reset (&CurTok.SVal);
|
||||
|
||||
/* Check for a cheap local symbol */
|
||||
@@ -248,8 +248,8 @@ static void FuncIdent (void)
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** is a right paren, then replace the token by an identifier token.
|
||||
*/
|
||||
SB_Copy (&Buf, &CurTok.SVal);
|
||||
NextTok ();
|
||||
if (CurTok.Tok != TOK_RPAREN) {
|
||||
@@ -289,12 +289,12 @@ static void FuncLeft (void)
|
||||
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).
|
||||
*/
|
||||
** 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 */
|
||||
@@ -320,8 +320,8 @@ static void FuncMid (void)
|
||||
ConsumeLParen ();
|
||||
|
||||
/* Start argument. Since the start argument can get negative with
|
||||
* expressions like ".tcount(arg)-2", we correct it to zero silently.
|
||||
*/
|
||||
** expressions like ".tcount(arg)-2", we correct it to zero silently.
|
||||
*/
|
||||
Start = ConstExpression ();
|
||||
if (Start < 0 || Start > 100) {
|
||||
Start = 0;
|
||||
@@ -329,8 +329,8 @@ static void FuncMid (void)
|
||||
ConsumeComma ();
|
||||
|
||||
/* Count argument. Similar as above, we will accept negative counts and
|
||||
* correct them to zero silently.
|
||||
*/
|
||||
** correct them to zero silently.
|
||||
*/
|
||||
Count = ConstExpression ();
|
||||
if (Count < 0) {
|
||||
Count = 0;
|
||||
@@ -341,12 +341,12 @@ static void FuncMid (void)
|
||||
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).
|
||||
*/
|
||||
** 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 */
|
||||
@@ -396,12 +396,12 @@ static void FuncRight (void)
|
||||
}
|
||||
|
||||
/* 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).
|
||||
*/
|
||||
** 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 */
|
||||
@@ -474,15 +474,15 @@ static void FuncSPrintF (void)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Since a format specifier follows, we do expect anotehr argument for
|
||||
* the .sprintf function.
|
||||
*/
|
||||
/* Since a format specifier follows, we do expect another 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...
|
||||
*/
|
||||
** support, and later use xsprintf to do the actual formatting. This
|
||||
** is easier than adding another printf implementation...
|
||||
*/
|
||||
SB_Clear (&F1);
|
||||
SB_AppendChar (&F1, '%');
|
||||
|
||||
@@ -522,8 +522,8 @@ static void FuncSPrintF (void)
|
||||
case 'X':
|
||||
case 'x':
|
||||
/* Our ints are actually longs, so we use the 'l' modifier when
|
||||
* calling xsprintf later. Terminate the format string.
|
||||
*/
|
||||
** calling xsprintf later. Terminate the format string.
|
||||
*/
|
||||
SB_AppendChar (&F1, 'l');
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
SB_Terminate (&F1);
|
||||
@@ -576,8 +576,8 @@ static void FuncSPrintF (void)
|
||||
}
|
||||
|
||||
/* Format this argument according to the spec. Be sure to pass
|
||||
* an int as the char value.
|
||||
*/
|
||||
** an int as the char value.
|
||||
*/
|
||||
SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal);
|
||||
|
||||
/* Append the formatted argument to the result */
|
||||
@@ -597,8 +597,8 @@ static void FuncSPrintF (void)
|
||||
SB_Terminate (&R);
|
||||
|
||||
/* We expect a closing parenthesis, but will not skip it but replace it
|
||||
* by the string token just created.
|
||||
*/
|
||||
** by the string token just created.
|
||||
*/
|
||||
if (CurTok.Tok != TOK_RPAREN) {
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
@@ -636,8 +636,8 @@ static void FuncString (void)
|
||||
} 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.
|
||||
*/
|
||||
** ParseScopedSymName here since the name may be invalid.
|
||||
*/
|
||||
int NameSpace;
|
||||
do {
|
||||
NameSpace = (CurTok.Tok == TOK_NAMESPACE);
|
||||
@@ -657,8 +657,8 @@ static void FuncString (void)
|
||||
}
|
||||
|
||||
/* We expect a closing parenthesis, but will not skip it but replace it
|
||||
* by the string token just created.
|
||||
*/
|
||||
** by the string token just created.
|
||||
*/
|
||||
if (CurTok.Tok != TOK_RPAREN) {
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
@@ -680,8 +680,8 @@ void NextTok (void)
|
||||
NextRawTok ();
|
||||
|
||||
/* In raw mode, or when output is suppressed via conditional assembly,
|
||||
* pass the token unchanged.
|
||||
*/
|
||||
** pass the token unchanged.
|
||||
*/
|
||||
if (RawMode == 0 && IfCond) {
|
||||
|
||||
/* Execute token handling functions */
|
||||
@@ -787,8 +787,8 @@ void SkipUntilSep (void)
|
||||
|
||||
void ExpectSep (void)
|
||||
/* Check if we've reached a line separator, and output an error if not. Do
|
||||
* not skip the line separator.
|
||||
*/
|
||||
** not skip the line separator.
|
||||
*/
|
||||
{
|
||||
if (!TokIsSep (CurTok.Tok)) {
|
||||
ErrorSkip ("Unexpected trailing garbage characters");
|
||||
@@ -799,11 +799,11 @@ void ExpectSep (void)
|
||||
|
||||
void EnterRawTokenMode (void)
|
||||
/* Enter raw token mode. In raw mode, token handling functions are not
|
||||
* executed, but the function tokens are passed untouched to the upper
|
||||
* layer. Raw token mode is used when storing macro tokens for later
|
||||
* use.
|
||||
* Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
|
||||
*/
|
||||
** executed, but the function tokens are passed untouched to the upper
|
||||
** layer. Raw token mode is used when storing macro tokens for later
|
||||
** use.
|
||||
** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
|
||||
*/
|
||||
{
|
||||
++RawMode;
|
||||
}
|
||||
@@ -816,6 +816,3 @@ void LeaveRawTokenMode (void)
|
||||
PRECONDITION (RawMode > 0);
|
||||
--RawMode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -71,16 +71,16 @@ void SkipUntilSep (void);
|
||||
|
||||
void ExpectSep (void);
|
||||
/* Check if we've reached a line separator, and output an error if not. Do
|
||||
* not skip the line separator.
|
||||
*/
|
||||
** not skip the line separator.
|
||||
*/
|
||||
|
||||
void EnterRawTokenMode (void);
|
||||
/* Enter raw token mode. In raw mode, token handling functions are not
|
||||
* executed, but the function tokens are passed untouched to the upper
|
||||
* layer. Raw token mode is used when storing macro tokens for later
|
||||
* use.
|
||||
* Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
|
||||
*/
|
||||
** executed, but the function tokens are passed untouched to the upper
|
||||
** layer. Raw token mode is used when storing macro tokens for later
|
||||
** use.
|
||||
** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
|
||||
*/
|
||||
|
||||
void LeaveRawTokenMode (void);
|
||||
/* Leave raw token mode. */
|
||||
@@ -90,7 +90,3 @@ void LeaveRawTokenMode (void);
|
||||
/* End of nexttok.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -278,6 +278,3 @@ void EmitFill (unsigned long Count)
|
||||
GenFragment (FRAG_FILL, Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -94,6 +94,3 @@ void EmitFill (unsigned long Count);
|
||||
/* End of objcode.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -100,8 +100,8 @@ static ObjHeader Header = {
|
||||
|
||||
static void ObjWriteError (void)
|
||||
/* Called on a write error. Will try to close and remove the file, then
|
||||
* print a fatal error.
|
||||
*/
|
||||
** print a fatal error.
|
||||
*/
|
||||
{
|
||||
/* Remember the error */
|
||||
int Error = errno;
|
||||
@@ -162,8 +162,8 @@ void ObjOpen (void)
|
||||
/* Do we have a name for the output file? */
|
||||
if (OutFile == 0) {
|
||||
/* We don't have an output name explicitly given, construct one from
|
||||
* the name of the input file.
|
||||
*/
|
||||
** the name of the input file.
|
||||
*/
|
||||
OutFile = MakeFilename (InFile, OBJ_EXT);
|
||||
}
|
||||
|
||||
@@ -269,10 +269,10 @@ void ObjWriteVar (unsigned long V)
|
||||
/* Write a variable sized value to the file in special encoding */
|
||||
{
|
||||
/* We will write the value to the file in 7 bit chunks. If the 8th bit
|
||||
* is clear, we're done, if it is set, another chunk follows. This will
|
||||
* allow us to encode smaller values with less bytes, at the expense of
|
||||
* needing 5 bytes if a 32 bit value is written to file.
|
||||
*/
|
||||
** is clear, we're done, if it is set, another chunk follows. This will
|
||||
** allow us to encode smaller values with less bytes, at the expense of
|
||||
** needing 5 bytes if a 32 bit value is written to file.
|
||||
*/
|
||||
do {
|
||||
unsigned char C = (V & 0x7F);
|
||||
V >>= 7;
|
||||
@@ -291,9 +291,9 @@ void ObjWriteStr (const char* S)
|
||||
unsigned Len = strlen (S);
|
||||
|
||||
/* Write the string with the length preceeded (this is easier for
|
||||
* the reading routine than the C format since the length is known in
|
||||
* advance).
|
||||
*/
|
||||
** the reading routine than the C format since the length is known in
|
||||
** advance).
|
||||
*/
|
||||
ObjWriteVar (Len);
|
||||
ObjWriteData (S, Len);
|
||||
}
|
||||
@@ -304,9 +304,9 @@ void ObjWriteBuf (const StrBuf* S)
|
||||
/* Write a string to the object file */
|
||||
{
|
||||
/* Write the string with the length preceeded (this is easier for
|
||||
* the reading routine than the C format since the length is known in
|
||||
* advance).
|
||||
*/
|
||||
** the reading routine than the C format since the length is known in
|
||||
** advance).
|
||||
*/
|
||||
ObjWriteVar (SB_GetLen (S));
|
||||
ObjWriteData (SB_GetConstBuf (S), SB_GetLen (S));
|
||||
}
|
||||
@@ -512,6 +512,3 @@ void ObjEndSpans (void)
|
||||
{
|
||||
Header.SpanSize = ftell (F) - Header.SpanOffs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -160,6 +160,3 @@ void ObjEndSpans (void);
|
||||
/* End of objfile.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,3 @@ void WriteOptions (void);
|
||||
/* End of options.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -112,12 +112,12 @@ static void DoUnexpected (void);
|
||||
|
||||
static void DoInvalid (void);
|
||||
/* Handle a token that is invalid here, since it should have been handled on
|
||||
* a much lower level of the expression hierarchy. Getting this sort of token
|
||||
* means that the lower level code has bugs.
|
||||
* This function differs to DoUnexpected in that the latter may be triggered
|
||||
* by the user by using keywords in the wrong location. DoUnexpected is not
|
||||
* an error in the assembler itself, while DoInvalid is.
|
||||
*/
|
||||
** a much lower level of the expression hierarchy. Getting this sort of token
|
||||
** means that the lower level code has bugs.
|
||||
** This function differs to DoUnexpected in that the latter may be triggered
|
||||
** by the user by using keywords in the wrong location. DoUnexpected is not
|
||||
** an error in the assembler itself, while DoInvalid is.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -129,8 +129,8 @@ static void DoInvalid (void);
|
||||
|
||||
static unsigned char OptionalAddrSize (void)
|
||||
/* If a colon follows, parse an optional address size spec and return it.
|
||||
* Otherwise return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
** Otherwise return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
{
|
||||
unsigned AddrSize = ADDR_SIZE_DEFAULT;
|
||||
if (CurTok.Tok == TOK_COLON) {
|
||||
@@ -183,8 +183,8 @@ static void ExportWithAssign (SymEntry* Sym, unsigned char AddrSize, unsigned Fl
|
||||
/* Allow to assign the value of an export in an .export statement */
|
||||
{
|
||||
/* The name and optional address size spec may be followed by an assignment
|
||||
* or equal token.
|
||||
*/
|
||||
** or equal token.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_ASSIGN || CurTok.Tok == TOK_EQ) {
|
||||
|
||||
/* Assignment means the symbol is a label */
|
||||
@@ -249,8 +249,8 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
|
||||
|
||||
static long IntArg (long Min, long Max)
|
||||
/* Read an integer argument and check a range. Accept the token "unlimited"
|
||||
* and return -1 in this case.
|
||||
*/
|
||||
** and return -1 in this case.
|
||||
*/
|
||||
{
|
||||
if (CurTok.Tok == TOK_IDENT && SB_CompareStr (&CurTok.SVal, "unlimited") == 0) {
|
||||
NextTok ();
|
||||
@@ -301,9 +301,9 @@ static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize,
|
||||
const char* ElementType,
|
||||
unsigned ElementTypeLen)
|
||||
/* Create an array (or single data) of the given type. SpanSize is the size
|
||||
* of the span, ElementType is a string that encodes the element data type.
|
||||
* The function returns Type.
|
||||
*/
|
||||
** of the span, ElementType is a string that encodes the element data type.
|
||||
** The function returns Type.
|
||||
*/
|
||||
{
|
||||
/* Get the size of the element type */
|
||||
unsigned ElementSize = GT_GET_SIZE (ElementType[0]);
|
||||
@@ -504,8 +504,8 @@ static void DoAssert (void)
|
||||
NextTok ();
|
||||
|
||||
/* We can have an optional message. If no message is present, use
|
||||
* "Assertion failed".
|
||||
*/
|
||||
** "Assertion failed".
|
||||
*/
|
||||
if (CurTok.Tok == TOK_COMMA) {
|
||||
|
||||
/* Skip the comma */
|
||||
@@ -518,8 +518,8 @@ static void DoAssert (void)
|
||||
}
|
||||
|
||||
/* Translate the message into a string id. We can then skip the input
|
||||
* string.
|
||||
*/
|
||||
** string.
|
||||
*/
|
||||
Msg = GetStrBufId (&CurTok.SVal);
|
||||
NextTok ();
|
||||
|
||||
@@ -1253,14 +1253,14 @@ static void DoIncBin (void)
|
||||
fseek (F, 0, SEEK_END);
|
||||
Size = ftell (F);
|
||||
|
||||
/* Stat the file and remember the values. There a race condition here,
|
||||
* since we cannot use fileno() (non standard identifier in standard
|
||||
* header file), and therefore not fstat. When using stat with the
|
||||
* file name, there's a risk that the file was deleted and recreated
|
||||
* while it was open. Since mtime and size are only used to check
|
||||
* if a file has changed in the debugger, we will ignore this problem
|
||||
* here.
|
||||
*/
|
||||
/* Stat the file and remember the values. There's a race condition here,
|
||||
** since we cannot use fileno() (non-standard identifier in standard
|
||||
** header file), and therefore not fstat. When using stat with the
|
||||
** file name, there's a risk that the file was deleted and recreated
|
||||
** while it was open. Since mtime and size are only used to check
|
||||
** if a file has changed in the debugger, we will ignore this problem
|
||||
** here.
|
||||
*/
|
||||
SB_Terminate (&Name);
|
||||
if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) {
|
||||
Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno));
|
||||
@@ -1364,12 +1364,12 @@ static void DoInterruptor (void)
|
||||
|
||||
static void DoInvalid (void)
|
||||
/* Handle a token that is invalid here, since it should have been handled on
|
||||
* a much lower level of the expression hierarchy. Getting this sort of token
|
||||
* means that the lower level code has bugs.
|
||||
* This function differs to DoUnexpected in that the latter may be triggered
|
||||
* by the user by using keywords in the wrong location. DoUnexpected is not
|
||||
* an error in the assembler itself, while DoInvalid is.
|
||||
*/
|
||||
** a much lower level of the expression hierarchy. Getting this sort of token
|
||||
** means that the lower level code has bugs.
|
||||
** This function differs to DoUnexpected in that the latter may be triggered
|
||||
** by the user by using keywords in the wrong location. DoUnexpected is not
|
||||
** an error in the assembler itself, while DoInvalid is.
|
||||
*/
|
||||
{
|
||||
Internal ("Unexpected token: %m%p", &Keyword);
|
||||
}
|
||||
@@ -1494,8 +1494,8 @@ static void DoOut (void)
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
/* Output the string and be sure to flush the output to keep it in
|
||||
* sync with any error messages if the output is redirected to a file.
|
||||
*/
|
||||
** sync with any error messages if the output is redirected to a file.
|
||||
*/
|
||||
printf ("%.*s\n",
|
||||
(int) SB_GetLen (&CurTok.SVal),
|
||||
SB_GetConstBuf (&CurTok.SVal));
|
||||
@@ -1794,8 +1794,8 @@ static void DoSetCPU (void)
|
||||
SetCPU (CPU);
|
||||
|
||||
/* Skip the identifier. If the CPU switch was successful, the scanner
|
||||
* will treat the input now correctly for the new CPU.
|
||||
*/
|
||||
** will treat the input now correctly for the new CPU.
|
||||
*/
|
||||
NextTok ();
|
||||
}
|
||||
}
|
||||
@@ -1810,14 +1810,6 @@ static void DoSmart (void)
|
||||
|
||||
|
||||
|
||||
static void DoSunPlus (void)
|
||||
/* Switch to the SUNPLUS CPU */
|
||||
{
|
||||
SetCPU (CPU_SUNPLUS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoTag (void)
|
||||
/* Allocate space for a struct */
|
||||
{
|
||||
@@ -1869,10 +1861,10 @@ static void DoUnDef (void)
|
||||
/* Undefine a define style macro */
|
||||
{
|
||||
/* The function is called with the .UNDEF token in place, because we need
|
||||
* to disable .define macro expansions before reading the next token.
|
||||
* Otherwise the name of the macro would be expanded, so we would never
|
||||
* see it.
|
||||
*/
|
||||
** to disable .define macro expansions before reading the next token.
|
||||
** Otherwise the name of the macro would be expanded, so we would never
|
||||
** see it.
|
||||
*/
|
||||
DisableDefineStyleMacros ();
|
||||
NextTok ();
|
||||
EnableDefineStyleMacros ();
|
||||
@@ -2093,7 +2085,6 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoUnexpected }, /* .STRING */
|
||||
{ ccNone, DoUnexpected }, /* .STRLEN */
|
||||
{ ccNone, DoStruct },
|
||||
{ ccNone, DoSunPlus },
|
||||
{ ccNone, DoTag },
|
||||
{ ccNone, DoUnexpected }, /* .TCOUNT */
|
||||
{ ccNone, DoUnexpected }, /* .TIME */
|
||||
@@ -2154,6 +2145,3 @@ void CheckPseudo (void)
|
||||
Warning (1, "CPU stack is not empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,3 @@ void CheckPseudo (void);
|
||||
/* End of pseudo.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
|
||||
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.
|
||||
*/
|
||||
** this list. In case of errors, NULL is returned.
|
||||
*/
|
||||
{
|
||||
/* Create the token list */
|
||||
TokList* List = NewTokList ();
|
||||
@@ -97,8 +97,8 @@ static TokList* CollectRepeatTokens (void)
|
||||
|
||||
static void RepeatTokenCheck (TokList* L)
|
||||
/* Called each time a token from a repeat token list is set. Is used to check
|
||||
* for and replace identifiers that are the repeat counter.
|
||||
*/
|
||||
** for and replace identifiers that are the repeat counter.
|
||||
*/
|
||||
{
|
||||
if (CurTok.Tok == TOK_IDENT &&
|
||||
L->Data != 0 &&
|
||||
@@ -161,8 +161,8 @@ void ParseRepeat (void)
|
||||
List->Check = RepeatTokenCheck;
|
||||
|
||||
/* If the list is empty, or repeat count zero, there is nothing
|
||||
* to repeat.
|
||||
*/
|
||||
** to repeat.
|
||||
*/
|
||||
if (List->Count == 0 || RepCount == 0) {
|
||||
FreeTokList (List);
|
||||
goto Done;
|
||||
@@ -175,6 +175,3 @@ Done:
|
||||
/* Switch out of raw token mode */
|
||||
LeaveRawTokenMode ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,3 @@ void ParseRepeat (void);
|
||||
/* End of repeat.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -276,7 +276,6 @@ struct DotKeyword {
|
||||
{ ".STRING", TOK_STRING },
|
||||
{ ".STRLEN", TOK_STRLEN },
|
||||
{ ".STRUCT", TOK_STRUCT },
|
||||
{ ".SUNPLUS", TOK_SUNPLUS },
|
||||
{ ".TAG", TOK_TAG },
|
||||
{ ".TCOUNT", TOK_TCOUNT },
|
||||
{ ".TIME", TOK_TIME },
|
||||
@@ -314,8 +313,8 @@ static void UseCharSource (CharSource* S)
|
||||
S->Func->NextChar (S);
|
||||
|
||||
/* Setup the next token so it will be skipped on the next call to
|
||||
* NextRawTok().
|
||||
*/
|
||||
** NextRawTok().
|
||||
*/
|
||||
CurTok.Tok = TOK_SEP;
|
||||
}
|
||||
|
||||
@@ -379,8 +378,8 @@ static void IFNextChar (CharSource* S)
|
||||
}
|
||||
|
||||
/* No more data - add an empty line to the listing. This
|
||||
* is a small hack needed to keep the PC output in sync.
|
||||
*/
|
||||
** is a small hack needed to keep the PC output in sync.
|
||||
*/
|
||||
NewListingLine (&EmptyStrBuf, S->V.File.Pos.Name, FCount);
|
||||
C = EOF;
|
||||
return;
|
||||
@@ -402,9 +401,9 @@ static void IFNextChar (CharSource* S)
|
||||
|
||||
|
||||
/* If we come here, we have a new input line. To avoid problems
|
||||
* with strange line terminators, remove all whitespace from the
|
||||
* end of the line, the add a single newline.
|
||||
*/
|
||||
** with strange line terminators, remove all whitespace from the
|
||||
** end of the line, the add a single newline.
|
||||
*/
|
||||
Len = SB_GetLen (&S->V.File.Line);
|
||||
while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) {
|
||||
--Len;
|
||||
@@ -436,11 +435,11 @@ void IFDone (CharSource* S)
|
||||
/* Close the current input file */
|
||||
{
|
||||
/* We're at the end of an include file. Check if we have any
|
||||
* open .IFs, or any open token lists in this file. This
|
||||
* enforcement is artificial, using conditionals that start
|
||||
* in one file and end in another are uncommon, and don't
|
||||
* allowing these things will help finding errors.
|
||||
*/
|
||||
** open .IFs, or any open token lists in this file. This
|
||||
** enforcement is artificial, using conditionals that start
|
||||
** in one file and end in another are uncommon, and don't
|
||||
** allowing these things will help finding errors.
|
||||
*/
|
||||
CheckOpenIfs ();
|
||||
|
||||
/* If we've added search paths for this file, remove them */
|
||||
@@ -455,8 +454,8 @@ void IFDone (CharSource* S)
|
||||
SB_Done (&S->V.File.Line);
|
||||
|
||||
/* Close the input file and decrement the file count. We will ignore
|
||||
* errors here, since we were just reading from the file.
|
||||
*/
|
||||
** errors here, since we were just reading from the file.
|
||||
*/
|
||||
(void) fclose (S->V.File.F);
|
||||
--FCount;
|
||||
}
|
||||
@@ -474,8 +473,8 @@ static const CharSourceFunctions IFFunc = {
|
||||
|
||||
int NewInputFile (const char* Name)
|
||||
/* Open a new input file. Returns true if the file could be successfully opened
|
||||
* and false otherwise.
|
||||
*/
|
||||
** and false otherwise.
|
||||
*/
|
||||
{
|
||||
int RetCode = 0; /* Return code. Assume an error. */
|
||||
char* PathName = 0;
|
||||
@@ -488,8 +487,8 @@ int NewInputFile (const char* Name)
|
||||
|
||||
|
||||
/* If this is the main file, just try to open it. If it's an include file,
|
||||
* search for it using the include path list.
|
||||
*/
|
||||
** search for it using the include path list.
|
||||
*/
|
||||
if (FCount == 0) {
|
||||
/* Main file */
|
||||
F = fopen (Name, "r");
|
||||
@@ -498,8 +497,8 @@ int NewInputFile (const char* Name)
|
||||
}
|
||||
} else {
|
||||
/* We are on include level. Search for the file in the include
|
||||
* directories.
|
||||
*/
|
||||
** directories.
|
||||
*/
|
||||
PathName = SearchFile (IncSearchPath, Name);
|
||||
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
|
||||
/* Not found or cannot open, print an error and bail out */
|
||||
@@ -511,14 +510,14 @@ int NewInputFile (const char* Name)
|
||||
Name = PathName;
|
||||
}
|
||||
|
||||
/* Stat the file and remember the values. There a race condition here,
|
||||
* since we cannot use fileno() (non standard identifier in standard
|
||||
* header file), and therefore not fstat. When using stat with the
|
||||
* file name, there's a risk that the file was deleted and recreated
|
||||
* while it was open. Since mtime and size are only used to check
|
||||
* if a file has changed in the debugger, we will ignore this problem
|
||||
* here.
|
||||
*/
|
||||
/* Stat the file and remember the values. There's a race condition here,
|
||||
** since we cannot use fileno() (non-standard identifier in standard
|
||||
** header file), and therefore not fstat. When using stat with the
|
||||
** file name, there's a risk that the file was deleted and recreated
|
||||
** while it was open. Since mtime and size are only used to check
|
||||
** if a file has changed in the debugger, we will ignore this problem
|
||||
** here.
|
||||
*/
|
||||
if (FileStat (Name, &Buf) != 0) {
|
||||
Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno));
|
||||
}
|
||||
@@ -705,8 +704,8 @@ static int CmpDotKeyword (const void* K1, const void* K2)
|
||||
|
||||
static token_t FindDotKeyword (void)
|
||||
/* Find the dot keyword in SVal. Return the corresponding token if found,
|
||||
* return TOK_NONE if not found.
|
||||
*/
|
||||
** return TOK_NONE if not found.
|
||||
*/
|
||||
{
|
||||
struct DotKeyword K;
|
||||
struct DotKeyword* R;
|
||||
@@ -734,10 +733,10 @@ static token_t FindDotKeyword (void)
|
||||
|
||||
static void ReadIdent (void)
|
||||
/* Read an identifier from the current input position into Ident. Filling SVal
|
||||
* starts at the current position with the next character in C. It is assumed
|
||||
* that any characters already filled in are ok, and the character in C is
|
||||
* checked.
|
||||
*/
|
||||
** starts at the current position with the next character in C. It is assumed
|
||||
** that any characters already filled in are ok, and the character in C is
|
||||
** checked.
|
||||
*/
|
||||
{
|
||||
/* Read the identifier */
|
||||
do {
|
||||
@@ -788,8 +787,8 @@ static void ReadStringConst (int StringTerm)
|
||||
|
||||
static int Sweet16Reg (const StrBuf* Id)
|
||||
/* Check if the given identifier is a sweet16 register. Return -1 if this is
|
||||
* not the case, return the register number otherwise.
|
||||
*/
|
||||
** not the case, return the register number otherwise.
|
||||
*/
|
||||
{
|
||||
unsigned RegNum;
|
||||
char Check;
|
||||
@@ -961,9 +960,9 @@ Again:
|
||||
}
|
||||
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.
|
||||
*/
|
||||
** overflow, so ignore excess digits here, they will be detected
|
||||
** when we convert the value.
|
||||
*/
|
||||
if (Digits < sizeof (Buf)) {
|
||||
Buf[Digits++] = C;
|
||||
}
|
||||
@@ -1035,8 +1034,8 @@ Again:
|
||||
}
|
||||
|
||||
/* An identifier with a dot. Check if it's a define style
|
||||
* macro.
|
||||
*/
|
||||
** macro.
|
||||
*/
|
||||
if ((M = FindDefine (&CurTok.SVal)) != 0) {
|
||||
/* This is a define style macro - expand it */
|
||||
MacExpandStart (M);
|
||||
@@ -1052,8 +1051,8 @@ Again:
|
||||
}
|
||||
|
||||
/* Indirect op for sweet16 cpu. Must check this before checking for local
|
||||
* symbols, because these may also use the '@' symbol.
|
||||
*/
|
||||
** symbols, because these may also use the '@' symbol.
|
||||
*/
|
||||
if (CPU == CPU_SWEET16 && C == '@') {
|
||||
NextChar ();
|
||||
CurTok.Tok = TOK_AT;
|
||||
@@ -1085,8 +1084,8 @@ Again:
|
||||
ReadIdent ();
|
||||
|
||||
/* Check for special names. Bail out if we have identified the type of
|
||||
* the token. Go on if the token is an identifier.
|
||||
*/
|
||||
** the token. Go on if the token is an identifier.
|
||||
*/
|
||||
if (SB_GetLen (&CurTok.SVal) == 1) {
|
||||
switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
|
||||
|
||||
@@ -1358,9 +1357,9 @@ CharAgain:
|
||||
|
||||
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.
|
||||
*/
|
||||
** the following stuff as a string, and check for a one character
|
||||
** string later.
|
||||
*/
|
||||
if (LooseStringTerm) {
|
||||
ReadStringConst ('\'');
|
||||
if (SB_GetLen (&CurTok.SVal) == 1) {
|
||||
@@ -1425,8 +1424,8 @@ CharAgain:
|
||||
}
|
||||
|
||||
/* If we go here, we could not identify the current character. Skip it
|
||||
* and try again.
|
||||
*/
|
||||
** and try again.
|
||||
*/
|
||||
Error ("Invalid input character: 0x%02X", C & 0xFF);
|
||||
NextChar ();
|
||||
goto Again;
|
||||
@@ -1436,10 +1435,10 @@ CharAgain:
|
||||
|
||||
int GetSubKey (const char** Keys, unsigned Count)
|
||||
/* Search for a subkey in a table of keywords. The current token must be an
|
||||
* identifier and all keys must be in upper case. The identifier will be
|
||||
* uppercased in the process. The function returns the index of the keyword,
|
||||
* or -1 if the keyword was not found.
|
||||
*/
|
||||
** identifier and all keys must be in upper case. The identifier will be
|
||||
** uppercased in the process. The function returns the index of the keyword,
|
||||
** or -1 if the keyword was not found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
@@ -1467,9 +1466,9 @@ int GetSubKey (const char** Keys, unsigned Count)
|
||||
|
||||
unsigned char ParseAddrSize (void)
|
||||
/* Check if the next token is a keyword that denotes an address size specifier.
|
||||
* If so, return the corresponding address size constant, otherwise output an
|
||||
* error message and return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
** If so, return the corresponding address size constant, otherwise output an
|
||||
** error message and return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
{
|
||||
unsigned char AddrSize;
|
||||
|
||||
@@ -1506,7 +1505,3 @@ void DoneScanner (void)
|
||||
{
|
||||
DoneCharSource ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,8 +69,8 @@ int IsIdStart (int C);
|
||||
|
||||
int NewInputFile (const char* Name);
|
||||
/* Open a new input file. Returns true if the file could be successfully opened
|
||||
* and false otherwise.
|
||||
*/
|
||||
** and false otherwise.
|
||||
*/
|
||||
|
||||
void NewInputData (char* Text, int Malloced);
|
||||
/* Add a chunk of input data to the input stream */
|
||||
@@ -86,16 +86,16 @@ void NextRawTok (void);
|
||||
|
||||
int GetSubKey (const char** Keys, unsigned Count);
|
||||
/* Search for a subkey in a table of keywords. The current token must be an
|
||||
* identifier and all keys must be in upper case. The identifier will be
|
||||
* uppercased in the process. The function returns the index of the keyword,
|
||||
* or -1 if the keyword was not found.
|
||||
*/
|
||||
** identifier and all keys must be in upper case. The identifier will be
|
||||
** uppercased in the process. The function returns the index of the keyword,
|
||||
** or -1 if the keyword was not found.
|
||||
*/
|
||||
|
||||
unsigned char ParseAddrSize (void);
|
||||
/* Check if the next token is a keyword that denotes an address size specifier.
|
||||
* If so, return the corresponding address size constant, otherwise output an
|
||||
* error message and return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
** If so, return the corresponding address size constant, otherwise output an
|
||||
** error message and return ADDR_SIZE_DEFAULT.
|
||||
*/
|
||||
|
||||
void InitScanner (const char* InFile);
|
||||
/* Initialize the scanner, open the given input file */
|
||||
@@ -108,7 +108,3 @@ void DoneScanner (void);
|
||||
/* End of scanner.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,3 @@ SegDef* DupSegDef (const SegDef* Def)
|
||||
{
|
||||
return NewSegDef (Def->Name, Def->AddrSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,3 @@ SegDef* DupSegDef (const SegDef* D);
|
||||
/* End of segdef.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@
|
||||
|
||||
|
||||
/* If OrgPerSeg is false, all segments share the RelocMode flag and a PC
|
||||
* used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg
|
||||
*/
|
||||
** used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg
|
||||
*/
|
||||
static int RelocMode = 1;
|
||||
static unsigned long AbsPC = 0; /* PC if in absolute mode */
|
||||
|
||||
@@ -97,8 +97,8 @@ Segment* ActiveSeg;
|
||||
|
||||
static Segment* NewSegFromDef (SegDef* Def)
|
||||
/* Create a new segment from a segment definition. Used only internally, no
|
||||
* checks.
|
||||
*/
|
||||
** checks.
|
||||
*/
|
||||
{
|
||||
/* Create a new segment */
|
||||
Segment* S = xmalloc (sizeof (*S));
|
||||
@@ -233,8 +233,8 @@ unsigned long GetPC (void)
|
||||
|
||||
void EnterAbsoluteMode (unsigned long PC)
|
||||
/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
|
||||
* this will either switch the mode globally or for the current segment.
|
||||
*/
|
||||
** this will either switch the mode globally or for the current segment.
|
||||
*/
|
||||
{
|
||||
if (OrgPerSeg) {
|
||||
/* Relocatable mode is switched per segment */
|
||||
@@ -265,8 +265,8 @@ int GetRelocMode (void)
|
||||
|
||||
void EnterRelocMode (void)
|
||||
/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
|
||||
* switch the mode globally or for the current segment.
|
||||
*/
|
||||
** switch the mode globally or for the current segment.
|
||||
*/
|
||||
{
|
||||
if (OrgPerSeg) {
|
||||
/* Relocatable mode is switched per segment */
|
||||
@@ -281,25 +281,25 @@ void EnterRelocMode (void)
|
||||
|
||||
void SegAlign (unsigned long Alignment, int FillVal)
|
||||
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
|
||||
* (the actual fill value will be determined by the linker), otherwise use
|
||||
* the given value.
|
||||
*/
|
||||
** (the actual fill value will be determined by the linker), otherwise use
|
||||
** the given value.
|
||||
*/
|
||||
{
|
||||
unsigned char Data [4];
|
||||
unsigned long CombinedAlignment;
|
||||
unsigned long Count;
|
||||
|
||||
/* The segment must have the combined alignment of all separate alignments
|
||||
* in the source. Calculate this alignment and check it for sanity.
|
||||
*/
|
||||
** in the source. Calculate this alignment and check it for sanity.
|
||||
*/
|
||||
CombinedAlignment = LeastCommonMultiple (ActiveSeg->Align, Alignment);
|
||||
if (CombinedAlignment > MAX_ALIGNMENT) {
|
||||
Error ("Combined alignment for active segment is %lu which exceeds %lu",
|
||||
CombinedAlignment, MAX_ALIGNMENT);
|
||||
|
||||
/* Avoid creating large fills for an object file that is thrown away
|
||||
* later.
|
||||
*/
|
||||
** later.
|
||||
*/
|
||||
Count = 1;
|
||||
|
||||
} else {
|
||||
@@ -410,10 +410,10 @@ void SegDone (void)
|
||||
} else if (RelaxChecks == 0) {
|
||||
|
||||
/* We cannot evaluate the expression now, leave the job for
|
||||
* the linker. However, we can check if the address size
|
||||
* matches the fragment size. Mismatches are errors in
|
||||
* most situations.
|
||||
*/
|
||||
** the linker. However, we can check if the address size
|
||||
** matches the fragment size. Mismatches are errors in
|
||||
** most situations.
|
||||
*/
|
||||
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
|
||||
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
|
||||
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
|
||||
@@ -496,9 +496,9 @@ void SetSegmentSizes (void)
|
||||
/* Set the default segment sizes according to the memory model */
|
||||
{
|
||||
/* Initialize segment sizes. The segment definitions do already contain
|
||||
* the correct values for the default case (near), so we must only change
|
||||
* things that should be different.
|
||||
*/
|
||||
** the correct values for the default case (near), so we must only change
|
||||
** things that should be different.
|
||||
*/
|
||||
switch (MemoryModel) {
|
||||
|
||||
case MMODEL_NEAR:
|
||||
@@ -530,8 +530,8 @@ static void WriteOneSeg (Segment* Seg)
|
||||
unsigned long EndPos;
|
||||
|
||||
/* Remember the file position, then write a dummy for the size of the
|
||||
* following data
|
||||
*/
|
||||
** following data
|
||||
*/
|
||||
unsigned long SizePos = ObjGetFilePos ();
|
||||
ObjWrite32 (0);
|
||||
|
||||
@@ -544,8 +544,8 @@ static void WriteOneSeg (Segment* Seg)
|
||||
ObjWriteVar (Seg->FragCount); /* Number of fragments */
|
||||
|
||||
/* Now walk through the fragment list for this segment and write the
|
||||
* fragments.
|
||||
*/
|
||||
** fragments.
|
||||
*/
|
||||
Frag = Seg->Root;
|
||||
while (Frag) {
|
||||
|
||||
@@ -627,7 +627,3 @@ void WriteSegments (void)
|
||||
/* Done writing segments */
|
||||
ObjEndSegments ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -131,9 +131,9 @@ INLINE unsigned char GetCurrentSegAddrSize (void)
|
||||
|
||||
void SegAlign (unsigned long Alignment, int FillVal);
|
||||
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
|
||||
* (the actual fill value will be determined by the linker), otherwise use
|
||||
* the given value.
|
||||
*/
|
||||
** (the actual fill value will be determined by the linker), otherwise use
|
||||
** the given value.
|
||||
*/
|
||||
|
||||
unsigned char GetSegAddrSize (unsigned SegNum);
|
||||
/* Return the address size of the segment with the given number */
|
||||
@@ -146,13 +146,13 @@ int GetRelocMode (void);
|
||||
|
||||
void EnterAbsoluteMode (unsigned long AbsPC);
|
||||
/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
|
||||
* this will either switch the mode globally or for the current segment.
|
||||
*/
|
||||
** this will either switch the mode globally or for the current segment.
|
||||
*/
|
||||
|
||||
void EnterRelocMode (void);
|
||||
/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
|
||||
* switch the mode globally or for the current segment.
|
||||
*/
|
||||
** switch the mode globally or for the current segment.
|
||||
*/
|
||||
|
||||
void SegDone (void);
|
||||
/* Check the segments for range and other errors. Do cleanup. */
|
||||
@@ -174,6 +174,3 @@ void WriteSegments (void);
|
||||
/* End of segment.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
|
||||
|
||||
/* The name of the symbol used to encode the size. The name of this entry is
|
||||
* choosen so that it cannot be accessed by the user.
|
||||
*/
|
||||
** choosen so that it cannot be accessed by the user.
|
||||
*/
|
||||
static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
|
||||
|
||||
int IsSizeOfSymbol (const SymEntry* Sym)
|
||||
/* Return true if the given symbol is the one that encodes the size of some
|
||||
* entity. Sym may also be a NULL pointer in which case false is returned.
|
||||
*/
|
||||
** entity. Sym may also be a NULL pointer in which case false is returned.
|
||||
*/
|
||||
{
|
||||
return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0);
|
||||
}
|
||||
@@ -74,8 +74,8 @@ int IsSizeOfSymbol (const SymEntry* Sym)
|
||||
|
||||
SymEntry* FindSizeOfScope (SymTable* Scope)
|
||||
/* Get the size of a scope. The function returns the symbol table entry that
|
||||
* encodes the size or NULL if there is no such entry.
|
||||
*/
|
||||
** encodes the size or NULL if there is no such entry.
|
||||
*/
|
||||
{
|
||||
return SymFind (Scope, &SizeEntryName, SYM_FIND_EXISTING);
|
||||
}
|
||||
@@ -84,8 +84,8 @@ SymEntry* FindSizeOfScope (SymTable* Scope)
|
||||
|
||||
SymEntry* FindSizeOfSymbol (SymEntry* Sym)
|
||||
/* Get the size of a symbol table entry. The function returns the symbol table
|
||||
* entry that encodes the size of the symbol or NULL if there is no such entry.
|
||||
*/
|
||||
** entry that encodes the size of the symbol or NULL if there is no such entry.
|
||||
*/
|
||||
{
|
||||
return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING);
|
||||
}
|
||||
@@ -94,8 +94,8 @@ SymEntry* FindSizeOfSymbol (SymEntry* Sym)
|
||||
|
||||
SymEntry* GetSizeOfScope (SymTable* Scope)
|
||||
/* Get the size of a scope. The function returns the symbol table entry that
|
||||
* encodes the size, and will create a new entry if it does not exist.
|
||||
*/
|
||||
** encodes the size, and will create a new entry if it does not exist.
|
||||
*/
|
||||
{
|
||||
return SymFind (Scope, &SizeEntryName, SYM_ALLOC_NEW);
|
||||
}
|
||||
@@ -104,9 +104,9 @@ SymEntry* GetSizeOfScope (SymTable* Scope)
|
||||
|
||||
SymEntry* GetSizeOfSymbol (SymEntry* Sym)
|
||||
/* Get the size of a symbol table entry. The function returns the symbol table
|
||||
* entry that encodes the size of the symbol and will create a new one if it
|
||||
* does not exist.
|
||||
*/
|
||||
** entry that encodes the size of the symbol and will create a new one if it
|
||||
** does not exist.
|
||||
*/
|
||||
{
|
||||
return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW);
|
||||
}
|
||||
@@ -130,6 +130,3 @@ SymEntry* DefSizeOfSymbol (SymEntry* Sym, long Size)
|
||||
SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE);
|
||||
return SizeSym;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,29 +62,29 @@ struct SymTable;
|
||||
|
||||
int IsSizeOfSymbol (const struct SymEntry* Sym);
|
||||
/* Return true if the given symbol is the one that encodes the size of some
|
||||
* entity. Sym may also be a NULL pointer in which case false is returned.
|
||||
*/
|
||||
** entity. Sym may also be a NULL pointer in which case false is returned.
|
||||
*/
|
||||
|
||||
struct SymEntry* FindSizeOfScope (struct SymTable* Scope);
|
||||
/* Get the size of a scope. The function returns the symbol table entry that
|
||||
* encodes the size or NULL if there is no such entry.
|
||||
*/
|
||||
** encodes the size or NULL if there is no such entry.
|
||||
*/
|
||||
|
||||
struct SymEntry* FindSizeOfSymbol (struct SymEntry* Sym);
|
||||
/* Get the size of a symbol table entry. The function returns the symbol table
|
||||
* entry that encodes the size of the symbol or NULL if there is no such entry.
|
||||
*/
|
||||
** entry that encodes the size of the symbol or NULL if there is no such entry.
|
||||
*/
|
||||
|
||||
struct SymEntry* GetSizeOfScope (struct SymTable* Scope);
|
||||
/* Get the size of a scope. The function returns the symbol table entry that
|
||||
* encodes the size, and will create a new entry if it does not exist.
|
||||
*/
|
||||
** encodes the size, and will create a new entry if it does not exist.
|
||||
*/
|
||||
|
||||
struct SymEntry* GetSizeOfSymbol (struct SymEntry* Sym);
|
||||
/* Get the size of a symbol table entry. The function returns the symbol table
|
||||
* entry that encodes the size of the symbol and will create a new one if it
|
||||
* does not exist.
|
||||
*/
|
||||
** entry that encodes the size of the symbol and will create a new one if it
|
||||
** does not exist.
|
||||
*/
|
||||
|
||||
struct SymEntry* DefSizeOfScope (struct SymTable* Scope, long Size);
|
||||
/* Define the size of a scope and return the size symbol */
|
||||
@@ -95,7 +95,5 @@ struct SymEntry* DefSizeOfSymbol (struct SymEntry* Sym, long Size);
|
||||
|
||||
|
||||
/* End of sizeof.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ static const void* HT_GetKey (const void* Entry);
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2);
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -113,9 +113,9 @@ static const void* HT_GetKey (const void* Entry)
|
||||
|
||||
static int HT_Compare (const void* Key1, const void* Key2)
|
||||
/* Compare two keys. The function must return a value less than zero if
|
||||
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
** Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
{
|
||||
/* Convert both parameters to Span pointers */
|
||||
const Span* S1 = Key1;
|
||||
@@ -144,8 +144,8 @@ static int HT_Compare (const void* Key1, const void* Key2)
|
||||
|
||||
static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End)
|
||||
/* Create a new span. The segment is set to Seg, Start and End are set to the
|
||||
* current PC of the segment.
|
||||
*/
|
||||
** current PC of the segment.
|
||||
*/
|
||||
{
|
||||
/* Allocate memory */
|
||||
Span* S = xmalloc (sizeof (Span));
|
||||
@@ -174,13 +174,13 @@ static void FreeSpan (Span* S)
|
||||
|
||||
static Span* MergeSpan (Span* S)
|
||||
/* Check if we have a span with the same data as S already. If so, free S and
|
||||
* return the already existing one. If not, remember S and return it.
|
||||
*/
|
||||
** return the already existing one. If not, remember S and return it.
|
||||
*/
|
||||
{
|
||||
/* Check if we have such a span already. If so use the existing
|
||||
* one and free the one from the collection. If not, add the one to
|
||||
* the hash table and return it.
|
||||
*/
|
||||
** one and free the one from the collection. If not, add the one to
|
||||
** the hash table and return it.
|
||||
*/
|
||||
Span* E = HT_Find (&SpanTab, S);
|
||||
if (E) {
|
||||
/* If S has a type and E not, move the type */
|
||||
@@ -223,9 +223,9 @@ Span* OpenSpan (void)
|
||||
|
||||
Span* CloseSpan (Span* S)
|
||||
/* Close the given span. Be sure to replace the passed span by the one
|
||||
* returned, since the span will get deleted if it is empty or may be
|
||||
* replaced if a duplicate exists.
|
||||
*/
|
||||
** returned, since the span will get deleted if it is empty or may be
|
||||
** replaced if a duplicate exists.
|
||||
*/
|
||||
{
|
||||
/* Set the end offset */
|
||||
if (S->Start == S->Seg->PC) {
|
||||
@@ -237,9 +237,9 @@ Span* CloseSpan (Span* S)
|
||||
S->End = S->Seg->PC;
|
||||
|
||||
/* Check if we have such a span already. If so use the existing
|
||||
* one and free the one from the collection. If not, add the one to
|
||||
* the hash table and return it.
|
||||
*/
|
||||
** one and free the one from the collection. If not, add the one to
|
||||
** the hash table and return it.
|
||||
*/
|
||||
return MergeSpan (S);
|
||||
}
|
||||
}
|
||||
@@ -248,9 +248,9 @@ Span* CloseSpan (Span* S)
|
||||
|
||||
void OpenSpanList (Collection* Spans)
|
||||
/* Open a list of spans for all existing segments to the given collection of
|
||||
* spans. The currently active segment will be inserted first with all others
|
||||
* following.
|
||||
*/
|
||||
** spans. The currently active segment will be inserted first with all others
|
||||
** following.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
@@ -275,8 +275,8 @@ void OpenSpanList (Collection* Spans)
|
||||
|
||||
void CloseSpanList (Collection* Spans)
|
||||
/* Close a list of spans. This will add new segments to the list, mark the end
|
||||
* of existing ones, and remove empty spans from the list.
|
||||
*/
|
||||
** of existing ones, and remove empty spans from the list.
|
||||
*/
|
||||
{
|
||||
unsigned I, J;
|
||||
|
||||
@@ -385,9 +385,9 @@ void WriteSpans (void)
|
||||
CHECK (S->End > S->Start);
|
||||
|
||||
/* Write data for the span We will write the size instead of the
|
||||
* end offset to save some bytes, since most spans are expected
|
||||
* to be rather small.
|
||||
*/
|
||||
** end offset to save some bytes, since most spans are expected
|
||||
** to be rather small.
|
||||
*/
|
||||
ObjWriteVar (S->Seg->Num);
|
||||
ObjWriteVar (S->Start);
|
||||
ObjWriteVar (S->End - S->Start);
|
||||
@@ -407,7 +407,3 @@ void WriteSpans (void)
|
||||
/* Done writing the spans */
|
||||
ObjEndSpans ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -93,15 +93,15 @@ Span* OpenSpan (void);
|
||||
|
||||
Span* CloseSpan (Span* S);
|
||||
/* Close the given span. Be sure to replace the passed span by the one
|
||||
* returned, since the span will get deleted if it is empty or may be
|
||||
* replaced if a duplicate exists.
|
||||
*/
|
||||
** returned, since the span will get deleted if it is empty or may be
|
||||
** replaced if a duplicate exists.
|
||||
*/
|
||||
|
||||
void OpenSpanList (Collection* Spans);
|
||||
/* Open a list of spans for all existing segments to the given collection of
|
||||
* spans. The currently active segment will be inserted first with all others
|
||||
* following.
|
||||
*/
|
||||
** spans. The currently active segment will be inserted first with all others
|
||||
** following.
|
||||
*/
|
||||
|
||||
void CloseSpanList (Collection* Spans);
|
||||
/* Close all open spans by setting PC to the current PC for the segment. */
|
||||
@@ -117,6 +117,3 @@ void WriteSpans (void);
|
||||
/* End of span.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -89,6 +89,3 @@ void InitStrPool (void)
|
||||
/* Insert an empty string. It will have string id 0 */
|
||||
SP_AddStr (StrPool, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -114,7 +114,3 @@ void InitStrPool (void);
|
||||
/* End of spool.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -102,9 +102,9 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
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.
|
||||
*/
|
||||
** 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 */
|
||||
@@ -137,8 +137,8 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
if (CurTok.Tok == TOK_IDENT) {
|
||||
|
||||
/* Beware: An identifier may also be a macro, in which case we have
|
||||
* to start over.
|
||||
*/
|
||||
** to start over.
|
||||
*/
|
||||
Macro* M = FindMacro (&CurTok.SVal);
|
||||
if (M) {
|
||||
MacExpandStart (M);
|
||||
@@ -245,11 +245,11 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** 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);
|
||||
@@ -299,6 +299,3 @@ void DoUnion (void)
|
||||
{
|
||||
DoStructInternal (0, UNION);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -68,6 +68,3 @@ void DoUnion (void);
|
||||
/* End of struct.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@ int ED_IsConst (const ExprDesc* D)
|
||||
|
||||
static int ED_IsValid (const ExprDesc* D)
|
||||
/* Return true if the expression is valid, that is, neither the ERROR nor the
|
||||
* TOO_COMPLEX flags are set.
|
||||
*/
|
||||
** TOO_COMPLEX flags are set.
|
||||
*/
|
||||
{
|
||||
return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
|
||||
}
|
||||
@@ -164,22 +164,22 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
|
||||
{
|
||||
if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
/* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
|
||||
* it takes precedence over anything else.
|
||||
*/
|
||||
** it takes precedence over anything else.
|
||||
*/
|
||||
if (ED_IsValid (ED)) {
|
||||
ED->AddrSize = Right->AddrSize;
|
||||
}
|
||||
} else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
/* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
|
||||
* otherwise it takes precedence over anything else.
|
||||
*/
|
||||
** otherwise it takes precedence over anything else.
|
||||
*/
|
||||
if (!ED_IsValid (Right)) {
|
||||
ED->AddrSize = Right->AddrSize;
|
||||
}
|
||||
} else {
|
||||
/* Neither ED nor Right has a default address size, use the larger of
|
||||
* the two.
|
||||
*/
|
||||
** the two.
|
||||
*/
|
||||
if (Right->AddrSize > ED->AddrSize) {
|
||||
ED->AddrSize = Right->AddrSize;
|
||||
}
|
||||
@@ -190,8 +190,8 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
|
||||
|
||||
static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
/* Find a symbol reference and return it. Return NULL if the reference does
|
||||
* not exist.
|
||||
*/
|
||||
** not exist.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
ED_SymRef* SymRef;
|
||||
@@ -207,8 +207,8 @@ static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
|
||||
static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
|
||||
/* Find a section reference and return it. Return NULL if the reference does
|
||||
* not exist.
|
||||
*/
|
||||
** not exist.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
ED_SecRef* SecRef;
|
||||
@@ -224,8 +224,8 @@ static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
|
||||
|
||||
static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
/* Allocate a new symbol reference and return it. The count of the new
|
||||
* reference will be set to zero, and the reference itself to Sym.
|
||||
*/
|
||||
** reference will be set to zero, and the reference itself to Sym.
|
||||
*/
|
||||
{
|
||||
ED_SymRef* SymRef;
|
||||
|
||||
@@ -251,8 +251,8 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
|
||||
static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
|
||||
/* Allocate a new section reference and return it. The count of the new
|
||||
* reference will be set to zero, and the reference itself to Sec.
|
||||
*/
|
||||
** reference will be set to zero, and the reference itself to Sec.
|
||||
*/
|
||||
{
|
||||
ED_SecRef* SecRef;
|
||||
|
||||
@@ -278,8 +278,8 @@ static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
|
||||
|
||||
static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
/* Get a symbol reference and return it. If the symbol reference does not
|
||||
* exist, a new one is created and returned.
|
||||
*/
|
||||
** exist, a new one is created and returned.
|
||||
*/
|
||||
{
|
||||
ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
|
||||
if (SymRef == 0) {
|
||||
@@ -292,8 +292,8 @@ static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||
|
||||
static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
|
||||
/* Get a section reference and return it. If the section reference does not
|
||||
* exist, a new one is created and returned.
|
||||
*/
|
||||
** exist, a new one is created and returned.
|
||||
*/
|
||||
{
|
||||
ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
|
||||
if (SecRef == 0) {
|
||||
@@ -416,8 +416,8 @@ static void ED_Neg (ExprDesc* D)
|
||||
|
||||
static void ED_Move (ExprDesc* From, ExprDesc* To)
|
||||
/* Move the data from one ExprDesc to another. Old data is freed, and From
|
||||
* is prepared to that ED_Done may be called safely.
|
||||
*/
|
||||
** is prepared to that ED_Done may be called safely.
|
||||
*/
|
||||
{
|
||||
/* Delete old data */
|
||||
ED_Done (To);
|
||||
@@ -460,12 +460,12 @@ static unsigned char GetConstAddrSize (long Val)
|
||||
|
||||
static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
||||
/* Study a binary expression subtree. This is a helper function for StudyExpr
|
||||
* used for operations that succeed when both operands are known and constant.
|
||||
* It evaluates the two subtrees and checks if they are constant. If they
|
||||
* aren't constant, it will set the TOO_COMPLEX flag, and merge references.
|
||||
* Otherwise the first value is returned in D->Val, the second one in D->Right,
|
||||
* so the actual operation can be done by the caller.
|
||||
*/
|
||||
** used for operations that succeed when both operands are known and constant.
|
||||
** It evaluates the two subtrees and checks if they are constant. If they
|
||||
** aren't constant, it will set the TOO_COMPLEX flag, and merge references.
|
||||
** Otherwise the first value is returned in D->Val, the second one in D->Right,
|
||||
** so the actual operation can be done by the caller.
|
||||
*/
|
||||
{
|
||||
ExprDesc Right;
|
||||
|
||||
@@ -516,10 +516,10 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
||||
SymEntry* Sym = Expr->V.Sym;
|
||||
|
||||
/* If the symbol is defined somewhere, it has an expression associated.
|
||||
* In this case, just study the expression associated with the symbol,
|
||||
* but mark the symbol so if we encounter it twice, we know that we have
|
||||
* a circular reference.
|
||||
*/
|
||||
** In this case, just study the expression associated with the symbol,
|
||||
** but mark the symbol so if we encounter it twice, we know that we have
|
||||
** a circular reference.
|
||||
*/
|
||||
if (SymHasExpr (Sym)) {
|
||||
|
||||
if (SymHasUserMark (Sym)) {
|
||||
@@ -542,9 +542,9 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
||||
}
|
||||
|
||||
/* If the symbol has an explicit address size, use it. This may
|
||||
* lead to range errors later (maybe even in the linker stage), if
|
||||
* the user lied about the address size, but for now we trust him.
|
||||
*/
|
||||
** lead to range errors later (maybe even in the linker stage), if
|
||||
** the user lied about the address size, but for now we trust him.
|
||||
*/
|
||||
AddrSize = GetSymAddrSize (Sym);
|
||||
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||
D->AddrSize = AddrSize;
|
||||
@@ -554,8 +554,8 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
||||
} else if (SymIsImport (Sym)) {
|
||||
|
||||
/* The symbol is an import. Track the symbols used and update the
|
||||
* address size.
|
||||
*/
|
||||
** address size.
|
||||
*/
|
||||
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
|
||||
++SymRef->Count;
|
||||
ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
|
||||
@@ -566,17 +566,17 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
||||
SymTable* Parent;
|
||||
|
||||
/* The symbol is undefined. Track symbol usage but set the "too
|
||||
* complex" flag, since we cannot evaluate the final result.
|
||||
*/
|
||||
** complex" flag, since we cannot evaluate the final result.
|
||||
*/
|
||||
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
|
||||
++SymRef->Count;
|
||||
ED_Invalidate (D);
|
||||
|
||||
/* Since the symbol may be a forward, and we may need a statement
|
||||
* about the address size, check higher lexical levels for a symbol
|
||||
* with the same name and use its address size if we find such a
|
||||
* symbol which is defined.
|
||||
*/
|
||||
** about the address size, check higher lexical levels for a symbol
|
||||
** with the same name and use its address size if we find such a
|
||||
** symbol which is defined.
|
||||
*/
|
||||
AddrSize = GetSymAddrSize (Sym);
|
||||
Parent = GetSymParentScope (Sym);
|
||||
if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
|
||||
@@ -612,8 +612,8 @@ static void StudyULabel (ExprNode* Expr, ExprDesc* D)
|
||||
/* Study an unnamed label expression node */
|
||||
{
|
||||
/* If we can resolve the label, study the expression associated with it,
|
||||
* otherwise mark the expression as too complex to evaluate.
|
||||
*/
|
||||
** otherwise mark the expression as too complex to evaluate.
|
||||
*/
|
||||
if (ULabCanResolve ()) {
|
||||
/* We can resolve the label */
|
||||
StudyExprInternal (ULabResolve (Expr->V.IVal), D);
|
||||
@@ -707,8 +707,8 @@ static void StudyMul (ExprNode* Expr, ExprDesc* D)
|
||||
StudyExprInternal (Expr->Right, &Right);
|
||||
|
||||
/* We can handle the operation if at least one of both operands is const
|
||||
* and the other one is valid.
|
||||
*/
|
||||
** and the other one is valid.
|
||||
*/
|
||||
if (ED_IsConst (D) && ED_IsValid (&Right)) {
|
||||
|
||||
/* Multiplicate both, result goes into Right */
|
||||
@@ -1480,24 +1480,24 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
|
||||
}
|
||||
|
||||
/* If we don't have an address size, assign one if the expression is a
|
||||
* constant.
|
||||
*/
|
||||
** constant.
|
||||
*/
|
||||
if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
|
||||
D->AddrSize = GetConstAddrSize (D->Val);
|
||||
}
|
||||
|
||||
/* If the expression is valid, throw away the address size and recalculate
|
||||
* it using the data we have. This is more exact than the on-the-fly
|
||||
* calculation done when evaluating the tree, because symbols may have
|
||||
* been removed from the expression, and the final numeric value is now
|
||||
* known.
|
||||
*/
|
||||
** it using the data we have. This is more exact than the on-the-fly
|
||||
** calculation done when evaluating the tree, because symbols may have
|
||||
** been removed from the expression, and the final numeric value is now
|
||||
** known.
|
||||
*/
|
||||
if (ED_IsValid (D)) {
|
||||
unsigned char AddrSize;
|
||||
|
||||
/* If there are symbols or sections, use the largest one. If the
|
||||
* expression resolves to a const, use the address size of the value.
|
||||
*/
|
||||
** expression resolves to a const, use the address size of the value.
|
||||
*/
|
||||
if (D->SymCount > 0 || D->SecCount > 0) {
|
||||
|
||||
D->AddrSize = ADDR_SIZE_DEFAULT;
|
||||
@@ -1539,6 +1539,3 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
|
||||
printf ("%u sections:\n", D->SecCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -118,7 +118,5 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D);
|
||||
|
||||
|
||||
/* End of studyexpr.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,12 +54,12 @@
|
||||
|
||||
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.
|
||||
*/
|
||||
** 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;
|
||||
|
||||
@@ -89,8 +89,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
||||
SB_Append (FullName, Name);
|
||||
|
||||
/* The scope must exist, so search for it starting with the current
|
||||
* scope.
|
||||
*/
|
||||
** scope.
|
||||
*/
|
||||
Scope = SymFindAnyScope (CurrentScope, Name);
|
||||
if (Scope == 0) {
|
||||
/* Scope not found */
|
||||
@@ -125,8 +125,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
||||
NextTok ();
|
||||
|
||||
/* If a namespace token follows, we search for another scope, otherwise
|
||||
* the name is a symbol and we're done.
|
||||
*/
|
||||
** the name is a symbol and we're done.
|
||||
*/
|
||||
if (CurTok.Tok != TOK_NAMESPACE) {
|
||||
/* Symbol */
|
||||
return Scope;
|
||||
@@ -153,8 +153,8 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
||||
|
||||
SymEntry* ParseScopedSymName (SymFindAction Action)
|
||||
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
|
||||
* and return the symbol table entry.
|
||||
*/
|
||||
** and return the symbol table entry.
|
||||
*/
|
||||
{
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Ident = STATIC_STRBUF_INITIALIZER;
|
||||
@@ -171,12 +171,12 @@ SymEntry* ParseScopedSymName (SymFindAction Action)
|
||||
SB_Done (&ScopeName);
|
||||
|
||||
/* Check if the scope is valid. Errors have already been diagnosed by
|
||||
* the routine, so just exit.
|
||||
*/
|
||||
** the routine, so just exit.
|
||||
*/
|
||||
if (Scope) {
|
||||
/* Search for the symbol and return it. If no scope was specified,
|
||||
* search also in the upper levels.
|
||||
*/
|
||||
** search also in the upper levels.
|
||||
*/
|
||||
if (NoScope && (Action & SYM_ALLOC_NEW) == 0) {
|
||||
Sym = SymFindAny (Scope, &Ident);
|
||||
} else {
|
||||
@@ -184,9 +184,9 @@ SymEntry* ParseScopedSymName (SymFindAction Action)
|
||||
}
|
||||
} else {
|
||||
/* No scope ==> no symbol. To avoid errors in the calling routine that
|
||||
* may not expect NULL to be returned if Action contains SYM_ALLOC_NEW,
|
||||
* create a new symbol.
|
||||
*/
|
||||
** may not expect NULL to be returned if Action contains SYM_ALLOC_NEW,
|
||||
** create a new symbol.
|
||||
*/
|
||||
if (Action & SYM_ALLOC_NEW) {
|
||||
Sym = NewSymEntry (&Ident, SF_NONE);
|
||||
} else {
|
||||
@@ -205,8 +205,8 @@ SymEntry* ParseScopedSymName (SymFindAction Action)
|
||||
|
||||
SymTable* ParseScopedSymTable (void)
|
||||
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
|
||||
* symbol space and return the symbol table struct.
|
||||
*/
|
||||
** symbol space and return the symbol table struct.
|
||||
*/
|
||||
{
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
@@ -223,9 +223,9 @@ SymTable* ParseScopedSymTable (void)
|
||||
SB_Done (&ScopeName);
|
||||
|
||||
/* If we got no error, search for the child scope withint the enclosing one.
|
||||
* Beware: If no explicit parent scope was specified, search in all upper
|
||||
* levels.
|
||||
*/
|
||||
** Beware: If no explicit parent scope was specified, search in all upper
|
||||
** levels.
|
||||
*/
|
||||
if (Scope) {
|
||||
/* Search for the last scope */
|
||||
if (NoScope) {
|
||||
@@ -246,8 +246,8 @@ SymTable* ParseScopedSymTable (void)
|
||||
|
||||
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.
|
||||
*/
|
||||
** for it in the symbol table and return the symbol table entry.
|
||||
*/
|
||||
{
|
||||
SymEntry* Sym;
|
||||
|
||||
@@ -262,6 +262,3 @@ SymEntry* ParseAnySymName (SymFindAction Action)
|
||||
/* Return the symbol found */
|
||||
return Sym;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -61,33 +61,30 @@ struct StrBuf;
|
||||
|
||||
struct SymTable* ParseScopedIdent (struct StrBuf* Name, struct 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.
|
||||
*/
|
||||
** 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.
|
||||
*/
|
||||
|
||||
struct SymEntry* ParseScopedSymName (SymFindAction Action);
|
||||
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
|
||||
* and return the symbol table entry.
|
||||
*/
|
||||
** and return the symbol table entry.
|
||||
*/
|
||||
|
||||
struct SymTable* ParseScopedSymTable (void);
|
||||
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
|
||||
* symbol space and return the symbol table struct.
|
||||
*/
|
||||
** symbol space and return the symbol table struct.
|
||||
*/
|
||||
|
||||
struct 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.
|
||||
*/
|
||||
** for it in the symbol table and return the symbol table entry.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of symbol.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -115,12 +115,12 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
|
||||
|
||||
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
|
||||
/* Search in the given tree for a name. If we find the symbol, the function
|
||||
* will return 0 and put the entry pointer into E. If we did not find the
|
||||
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
* E will be set to the last entry, and the result of the function is <0 if
|
||||
* the entry should be inserted on the left side, and >0 if it should get
|
||||
* inserted on the right side.
|
||||
*/
|
||||
** will return 0 and put the entry pointer into E. If we did not find the
|
||||
** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
** E will be set to the last entry, and the result of the function is <0 if
|
||||
** the entry should be inserted on the left side, and >0 if it should get
|
||||
** inserted on the right side.
|
||||
*/
|
||||
{
|
||||
/* Is there a tree? */
|
||||
if (T == 0) {
|
||||
@@ -196,8 +196,8 @@ static void SymReplaceExprRefs (SymEntry* S)
|
||||
CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);
|
||||
|
||||
/* We cannot touch the root node, since there are pointers to it.
|
||||
* Replace it by a literal node.
|
||||
*/
|
||||
** Replace it by a literal node.
|
||||
*/
|
||||
E->Op = EXPR_LITERAL;
|
||||
E->V.IVal = Val;
|
||||
}
|
||||
@@ -234,8 +234,8 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
|
||||
return;
|
||||
}
|
||||
/* Delete the current symbol expression, since it will get
|
||||
* replaced
|
||||
*/
|
||||
** replaced
|
||||
*/
|
||||
FreeExpr (S->Expr);
|
||||
S->Expr = 0;
|
||||
}
|
||||
@@ -255,17 +255,17 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
|
||||
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.
|
||||
*/
|
||||
** 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.
|
||||
*/
|
||||
** below.
|
||||
*/
|
||||
if (S->Flags & SF_GLOBAL) {
|
||||
S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
|
||||
ReleaseFullLineInfo (&S->DefLines);
|
||||
@@ -326,15 +326,15 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* If no address size is given, use the address size of the enclosing
|
||||
* segment.
|
||||
*/
|
||||
** 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.
|
||||
*/
|
||||
** 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));
|
||||
@@ -355,9 +355,9 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned 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.
|
||||
*/
|
||||
** Please note: In case of multiple .global or .import statements, the line
|
||||
** infos add up.
|
||||
*/
|
||||
GetFullLineInfo (&S->DefLines);
|
||||
}
|
||||
|
||||
@@ -379,8 +379,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* If the symbol was marked as global before, remove the global flag and
|
||||
* proceed, but check the address size.
|
||||
*/
|
||||
** proceed, but check the address size.
|
||||
*/
|
||||
if (S->Flags & SF_GLOBAL) {
|
||||
if (AddrSize != S->ExportSize) {
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
@@ -388,14 +388,14 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
S->Flags &= ~SF_GLOBAL;
|
||||
|
||||
/* .GLOBAL remembers line infos in case an .IMPORT follows. We have
|
||||
* to remove these here.
|
||||
*/
|
||||
** to remove these here.
|
||||
*/
|
||||
ReleaseFullLineInfo (&S->DefLines);
|
||||
}
|
||||
|
||||
/* If the symbol was already marked as an export, but wasn't defined
|
||||
* before, the address sizes in both definitions must match.
|
||||
*/
|
||||
** before, the address sizes in both definitions must match.
|
||||
*/
|
||||
if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
|
||||
if (S->ExportSize != AddrSize) {
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
@@ -404,8 +404,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
S->ExportSize = AddrSize;
|
||||
|
||||
/* If the symbol is already defined, check symbol size against the
|
||||
* exported size.
|
||||
*/
|
||||
** exported size.
|
||||
*/
|
||||
if (S->Flags & SF_DEFINED) {
|
||||
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
|
||||
/* No export size given, use the real size of the symbol */
|
||||
@@ -429,8 +429,8 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
|
||||
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.
|
||||
*/
|
||||
** either imported or exported.
|
||||
*/
|
||||
{
|
||||
if (S->Flags & SF_VAR) {
|
||||
/* Variable symbols cannot be exported or imported */
|
||||
@@ -439,8 +439,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* If the symbol is already marked as import, the address size must match.
|
||||
* Apart from that, ignore the global declaration.
|
||||
*/
|
||||
** Apart from that, ignore the global declaration.
|
||||
*/
|
||||
if (S->Flags & SF_IMPORT) {
|
||||
if (AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
/* Use the size of the current segment */
|
||||
@@ -453,8 +453,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* If the symbol is already an export: If it is not defined, the address
|
||||
* sizes must match.
|
||||
*/
|
||||
** sizes must match.
|
||||
*/
|
||||
if (S->Flags & SF_EXPORT) {
|
||||
if ((S->Flags & SF_DEFINED) == 0) {
|
||||
/* Symbol is undefined */
|
||||
@@ -471,9 +471,9 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** 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));
|
||||
@@ -482,10 +482,10 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** 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;
|
||||
@@ -501,9 +501,9 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
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.
|
||||
*/
|
||||
** 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 */
|
||||
@@ -513,8 +513,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
S->Flags |= (SF_GLOBAL | Flags);
|
||||
|
||||
/* Remember the current location as location of definition in case
|
||||
* an .IMPORT follows later.
|
||||
*/
|
||||
** an .IMPORT follows later.
|
||||
*/
|
||||
GetFullLineInfo (&S->DefLines);
|
||||
}
|
||||
}
|
||||
@@ -523,8 +523,8 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
|
||||
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.
|
||||
*/
|
||||
** mark the symbol as an export. Initializers may never be zero page symbols.
|
||||
*/
|
||||
{
|
||||
/* Check the parameters */
|
||||
#if (CD_TYPE_MIN != 0)
|
||||
@@ -547,9 +547,9 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
** 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));
|
||||
@@ -559,8 +559,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
||||
S->ExportSize = AddrSize;
|
||||
|
||||
/* If the symbol is already defined, check symbol size against the
|
||||
* exported size.
|
||||
*/
|
||||
** exported size.
|
||||
*/
|
||||
if (S->Flags & SF_DEFINED) {
|
||||
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
|
||||
/* Use the real size of the symbol */
|
||||
@@ -571,8 +571,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
||||
}
|
||||
|
||||
/* If the symbol was already declared as a condes, check if the new
|
||||
* priority value is the same as the old one.
|
||||
*/
|
||||
** 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));
|
||||
@@ -593,10 +593,10 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
||||
|
||||
void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
|
||||
/* Mark the address size of the given symbol as guessed. The address size
|
||||
* passed as argument is the one NOT used, because the actual address size
|
||||
* wasn't known. Example: Zero page addressing was not used because symbol
|
||||
* is undefined, and absolute addressing was available.
|
||||
*/
|
||||
** passed as argument is the one NOT used, because the actual address size
|
||||
** wasn't known. Example: Zero page addressing was not used because symbol
|
||||
** is undefined, and absolute addressing was available.
|
||||
*/
|
||||
{
|
||||
/* We must have a valid address size passed */
|
||||
PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT);
|
||||
@@ -619,8 +619,8 @@ void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
|
||||
|
||||
void SymExportFromGlobal (SymEntry* S)
|
||||
/* Called at the end of assembly. Converts a global symbol that is defined
|
||||
* into an export.
|
||||
*/
|
||||
** into an export.
|
||||
*/
|
||||
{
|
||||
/* Remove the global flag and make the symbol an export */
|
||||
S->Flags &= ~SF_GLOBAL;
|
||||
@@ -631,8 +631,8 @@ void SymExportFromGlobal (SymEntry* S)
|
||||
|
||||
void SymImportFromGlobal (SymEntry* S)
|
||||
/* Called at the end of assembly. Converts a global symbol that is undefined
|
||||
* into an import.
|
||||
*/
|
||||
** into an import.
|
||||
*/
|
||||
{
|
||||
/* Remove the global flag and make it an import */
|
||||
S->Flags &= ~SF_GLOBAL;
|
||||
@@ -643,8 +643,8 @@ void SymImportFromGlobal (SymEntry* S)
|
||||
|
||||
int SymIsConst (const SymEntry* S, long* Val)
|
||||
/* Return true if the given symbol has a constant value. If Val is not NULL
|
||||
* and the symbol has a constant value, store it's value there.
|
||||
*/
|
||||
** and the symbol has a constant value, store it's value there.
|
||||
*/
|
||||
{
|
||||
/* Check for constness */
|
||||
return (SymHasExpr (S) && IsConstExpr (S->Expr, Val));
|
||||
@@ -654,16 +654,16 @@ int SymIsConst (const SymEntry* S, long* Val)
|
||||
|
||||
SymTable* GetSymParentScope (SymEntry* S)
|
||||
/* Get the parent scope of the symbol (not the one it is defined in). Return
|
||||
* NULL if the symbol is a cheap local, or defined on global level.
|
||||
*/
|
||||
** NULL if the symbol is a cheap local, or defined on global level.
|
||||
*/
|
||||
{
|
||||
if ((S->Flags & SF_LOCAL) != 0) {
|
||||
/* This is a cheap local symbol */
|
||||
return 0;
|
||||
} else if (S->Sym.Tab == 0) {
|
||||
/* Symbol not in a table. This may happen if there have been errors
|
||||
* before. Return NULL in this case to avoid further errors.
|
||||
*/
|
||||
** before. Return NULL in this case to avoid further errors.
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* This is a global symbol */
|
||||
@@ -684,8 +684,8 @@ struct ExprNode* GetSymExpr (SymEntry* S)
|
||||
|
||||
const struct ExprNode* SymResolve (const SymEntry* S)
|
||||
/* Helper function for DumpExpr. Resolves a symbol into an expression or return
|
||||
* NULL. Do not call in other contexts!
|
||||
*/
|
||||
** NULL. Do not call in other contexts!
|
||||
*/
|
||||
{
|
||||
return SymHasExpr (S)? S->Expr : 0;
|
||||
}
|
||||
@@ -694,8 +694,8 @@ const struct ExprNode* SymResolve (const SymEntry* S)
|
||||
|
||||
long GetSymVal (SymEntry* S)
|
||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
||||
* in case the symbol is undefined or not constant.
|
||||
*/
|
||||
** in case the symbol is undefined or not constant.
|
||||
*/
|
||||
{
|
||||
long Val;
|
||||
CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
|
||||
@@ -724,10 +724,10 @@ unsigned GetSymExportId (const SymEntry* S)
|
||||
|
||||
unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
|
||||
/* Return a set of flags used when writing symbol information into a file.
|
||||
* If the SYM_CONST bit is set, ConstVal will contain the constant value
|
||||
* of the symbol. The result does not include the condes count.
|
||||
* See common/symdefs.h for more information.
|
||||
*/
|
||||
** If the SYM_CONST bit is set, ConstVal will contain the constant value
|
||||
** of the symbol. The result does not include the condes count.
|
||||
** See common/symdefs.h for more information.
|
||||
*/
|
||||
{
|
||||
/* Setup info flags */
|
||||
unsigned Flags = 0;
|
||||
@@ -744,6 +744,3 @@ unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
|
||||
/* Return the result */
|
||||
return Flags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -92,11 +92,11 @@ struct SymEntry {
|
||||
Collection DefLines; /* Line infos for definition */
|
||||
Collection RefLines; /* Line infos for references */
|
||||
FilePos* GuessedUse[1]; /* File position where symbol
|
||||
* address size was guessed, and the
|
||||
* smallest possible addressing was NOT
|
||||
* used. Currently only for zero page
|
||||
* addressing
|
||||
*/
|
||||
** address size was guessed, and the
|
||||
** smallest possible addressing was NOT
|
||||
** used. Currently only for zero page
|
||||
** addressing
|
||||
*/
|
||||
struct HLLDbgSym* HLLSym; /* Symbol from high level language */
|
||||
unsigned Flags; /* Symbol flags */
|
||||
unsigned DebugSymId; /* Debug symbol id */
|
||||
@@ -130,12 +130,12 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags);
|
||||
|
||||
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
|
||||
/* Search in the given tree for a name. If we find the symbol, the function
|
||||
* will return 0 and put the entry pointer into E. If we did not find the
|
||||
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
* E will be set to the last entry, and the result of the function is <0 if
|
||||
* the entry should be inserted on the left side, and >0 if it should get
|
||||
* inserted on the right side.
|
||||
*/
|
||||
** will return 0 and put the entry pointer into E. If we did not find the
|
||||
** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
** E will be set to the last entry, and the result of the function is <0 if
|
||||
** the entry should be inserted on the left side, and >0 if it should get
|
||||
** inserted on the right side.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
|
||||
@@ -174,30 +174,30 @@ void SymExport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
|
||||
|
||||
void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
|
||||
/* Mark the given symbol as a global symbol, that is, as a symbol that is
|
||||
* either imported or exported.
|
||||
*/
|
||||
** either imported or exported.
|
||||
*/
|
||||
|
||||
void SymConDes (SymEntry* Sym, 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.
|
||||
*/
|
||||
** mark the symbol as an export. Initializers may never be zero page symbols.
|
||||
*/
|
||||
|
||||
void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize);
|
||||
/* Mark the address size of the given symbol as guessed. The address size
|
||||
* passed as argument is the one NOT used, because the actual address size
|
||||
* wasn't known. Example: Zero page addressing was not used because symbol
|
||||
* is undefined, and absolute addressing was available.
|
||||
*/
|
||||
** passed as argument is the one NOT used, because the actual address size
|
||||
** wasn't known. Example: Zero page addressing was not used because symbol
|
||||
** is undefined, and absolute addressing was available.
|
||||
*/
|
||||
|
||||
void SymExportFromGlobal (SymEntry* S);
|
||||
/* Called at the end of assembly. Converts a global symbol that is defined
|
||||
* into an export.
|
||||
*/
|
||||
** into an export.
|
||||
*/
|
||||
|
||||
void SymImportFromGlobal (SymEntry* S);
|
||||
/* Called at the end of assembly. Converts a global symbol that is undefined
|
||||
* into an import.
|
||||
*/
|
||||
** into an import.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsDef (const SymEntry* S)
|
||||
@@ -254,8 +254,8 @@ INLINE int SymIsVar (const SymEntry* S)
|
||||
|
||||
int SymIsConst (const SymEntry* Sym, long* Val);
|
||||
/* Return true if the given symbol has a constant value. If Val is not NULL
|
||||
* and the symbol has a constant value, store it's value there.
|
||||
*/
|
||||
** and the symbol has a constant value, store it's value there.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymHasExpr (const SymEntry* S)
|
||||
@@ -303,16 +303,16 @@ INLINE int SymHasUserMark (SymEntry* S)
|
||||
|
||||
struct SymTable* GetSymParentScope (SymEntry* S);
|
||||
/* Get the parent scope of the symbol (not the one it is defined in). Return
|
||||
* NULL if the symbol is a cheap local, or defined on global level.
|
||||
*/
|
||||
** NULL if the symbol is a cheap local, or defined on global level.
|
||||
*/
|
||||
|
||||
struct ExprNode* GetSymExpr (SymEntry* Sym);
|
||||
/* Get the expression for a non-const symbol */
|
||||
|
||||
const struct ExprNode* SymResolve (const SymEntry* Sym);
|
||||
/* Helper function for DumpExpr. Resolves a symbol into an expression or return
|
||||
* NULL. Do not call in other contexts!
|
||||
*/
|
||||
** NULL. Do not call in other contexts!
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const StrBuf* GetSymName (const SymEntry* S)
|
||||
@@ -327,8 +327,8 @@ INLINE const StrBuf* GetSymName (const SymEntry* S)
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned char GetSymAddrSize (const SymEntry* S)
|
||||
/* Return the address size of the symbol. Beware: This function will just
|
||||
* return the AddrSize member, it will not look at the expression!
|
||||
*/
|
||||
** return the AddrSize member, it will not look at the expression!
|
||||
*/
|
||||
{
|
||||
return S->AddrSize;
|
||||
}
|
||||
@@ -338,8 +338,8 @@ INLINE unsigned char GetSymAddrSize (const SymEntry* S)
|
||||
|
||||
long GetSymVal (SymEntry* Sym);
|
||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
||||
* in case the symbol is undefined or not constant.
|
||||
*/
|
||||
** in case the symbol is undefined or not constant.
|
||||
*/
|
||||
|
||||
unsigned GetSymImportId (const SymEntry* Sym);
|
||||
/* Return the import id for the given symbol */
|
||||
@@ -349,17 +349,13 @@ unsigned GetSymExportId (const SymEntry* Sym);
|
||||
|
||||
unsigned GetSymInfoFlags (const SymEntry* Sym, long* ConstVal);
|
||||
/* Return a set of flags used when writing symbol information into a file.
|
||||
* If the SYM_CONST bit is set, ConstVal will contain the constant value
|
||||
* of the symbol. The result does not include the condes count.
|
||||
* See common/symdefs.h for more information.
|
||||
*/
|
||||
** If the SYM_CONST bit is set, ConstVal will contain the constant value
|
||||
** of the symbol. The result does not include the condes count.
|
||||
** See common/symdefs.h for more information.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of symentry.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@@ -207,8 +207,8 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
|
||||
}
|
||||
|
||||
/* If we have a current scope, search for the given name and create a
|
||||
* new one if it doesn't exist. If this is the root scope, just create it.
|
||||
*/
|
||||
** new one if it doesn't exist. If this is the root scope, just create it.
|
||||
*/
|
||||
if (CurrentScope) {
|
||||
|
||||
/* Search for the scope, create a new one */
|
||||
@@ -230,11 +230,11 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
|
||||
CurrentScope->Label = ScopeLabel;
|
||||
|
||||
/* If this is a scope that allows to emit data into segments, add spans
|
||||
* for all currently existing segments. Doing this for just a few scope
|
||||
* types is not really necessary but an optimization, because it does not
|
||||
* allocate memory for useless data (unhandled types here don't occupy
|
||||
* space in any segment).
|
||||
*/
|
||||
** for all currently existing segments. Doing this for just a few scope
|
||||
** types is not really necessary but an optimization, because it does not
|
||||
** allocate memory for useless data (unhandled types here don't occupy
|
||||
** space in any segment).
|
||||
*/
|
||||
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
||||
OpenSpanList (&CurrentScope->Spans);
|
||||
}
|
||||
@@ -246,17 +246,17 @@ void SymLeaveLevel (void)
|
||||
/* Leave the current lexical level */
|
||||
{
|
||||
/* If this is a scope that allows to emit data into segments, close the
|
||||
* open the spans.
|
||||
*/
|
||||
** open the spans.
|
||||
*/
|
||||
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
||||
CloseSpanList (&CurrentScope->Spans);
|
||||
}
|
||||
|
||||
/* If we have spans, the first one is the segment that was active, when the
|
||||
* scope was opened. Set the size of the scope to the number of data bytes
|
||||
* emitted into this segment. If we have an owner symbol set the size of
|
||||
* this symbol, too.
|
||||
*/
|
||||
** scope was opened. Set the size of the scope to the number of data bytes
|
||||
** emitted into this segment. If we have an owner symbol set the size of
|
||||
** this symbol, too.
|
||||
*/
|
||||
if (CollCount (&CurrentScope->Spans) > 0) {
|
||||
const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0);
|
||||
unsigned long Size = GetSpanSize (S);
|
||||
@@ -304,9 +304,9 @@ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Acti
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
|
||||
/* Find a scope in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
*/
|
||||
** never create a new symbol, since this can only be done in one specific
|
||||
** scope.
|
||||
*/
|
||||
{
|
||||
SymTable* Scope;
|
||||
do {
|
||||
@@ -325,9 +325,9 @@ SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
|
||||
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action)
|
||||
/* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is
|
||||
* not found, create a new one. Return the entry found, or the new entry
|
||||
* created, or - in case Action is SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
** not found, create a new one. Return the entry found, or the new entry
|
||||
** created, or - in case Action is SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
|
||||
{
|
||||
SymEntry* S;
|
||||
@@ -375,10 +375,10 @@ SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Acti
|
||||
|
||||
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action)
|
||||
/* Find a new symbol table entry in the given table. If Action contains
|
||||
* SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
|
||||
* entry found, or the new entry created, or - in case Action is
|
||||
* SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
|
||||
** entry found, or the new entry created, or - in case Action is
|
||||
** SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
{
|
||||
SymEntry* S;
|
||||
|
||||
@@ -399,9 +399,9 @@ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action)
|
||||
if (Action & SYM_ALLOC_NEW) {
|
||||
|
||||
/* Otherwise create a new entry, insert and return it. If the scope is
|
||||
* already closed, mark the symbol as fixed so it won't be resolved
|
||||
* by a symbol in the enclosing scopes later.
|
||||
*/
|
||||
** already closed, mark the symbol as fixed so it won't be resolved
|
||||
** by a symbol in the enclosing scopes later.
|
||||
*/
|
||||
SymEntry* N = NewSymEntry (Name, SF_NONE);
|
||||
if (SymTabIsClosed (Scope)) {
|
||||
N->Flags |= SF_FIXED;
|
||||
@@ -427,9 +427,9 @@ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action)
|
||||
|
||||
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
|
||||
/* Find a symbol in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
*/
|
||||
** never create a new symbol, since this can only be done in one specific
|
||||
** scope.
|
||||
*/
|
||||
{
|
||||
/* Generate the name hash */
|
||||
unsigned Hash = HashBuf (Name);
|
||||
@@ -438,9 +438,9 @@ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
|
||||
SymEntry* Sym;
|
||||
do {
|
||||
/* Search in the current table. Ignore entries flagged with SF_UNUSED,
|
||||
* because for such symbols there is a real entry in one of the parent
|
||||
* scopes.
|
||||
*/
|
||||
** because for such symbols there is a real entry in one of the parent
|
||||
** scopes.
|
||||
*/
|
||||
if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) {
|
||||
if (Sym->Flags & SF_UNUSED) {
|
||||
Sym = 0;
|
||||
@@ -467,15 +467,15 @@ 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.
|
||||
*/
|
||||
**
|
||||
** - 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);
|
||||
@@ -483,8 +483,8 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
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.
|
||||
*/
|
||||
** either defined in the source, or an import.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/* No matching symbol found in this level. Look further */
|
||||
@@ -495,9 +495,9 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
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.
|
||||
*/
|
||||
** 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 */
|
||||
@@ -505,17 +505,7 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
"Symbol `%s' is already an import",
|
||||
GetString (Sym->Name));
|
||||
}
|
||||
if (Sym->Flags & SF_EXPORT) {
|
||||
/* The symbol is already marked as an export. */
|
||||
if (Sym->AddrSize > S->ExportSize) {
|
||||
/* We're exporting a symbol smaller than it actually is */
|
||||
LIWarning (&S->DefLines, 1,
|
||||
"Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (Sym),
|
||||
AddrSizeToStr (Sym->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
} else {
|
||||
if ((Sym->Flags & SF_EXPORT) == 0) {
|
||||
/* Mark the symbol as an export */
|
||||
Sym->Flags |= SF_EXPORT;
|
||||
Sym->ExportSize = S->ExportSize;
|
||||
@@ -525,7 +515,7 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
}
|
||||
if (Sym->AddrSize > Sym->ExportSize) {
|
||||
/* We're exporting a symbol smaller than it actually is */
|
||||
LIWarning (&S->DefLines, 1,
|
||||
LIWarning (&Sym->DefLines, 1,
|
||||
"Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (Sym),
|
||||
AddrSizeToStr (Sym->AddrSize),
|
||||
@@ -584,13 +574,13 @@ void SymCheck (void)
|
||||
}
|
||||
|
||||
/* First pass: Walk through all symbols, checking for undefined's and
|
||||
* changing them to trampoline symbols or make them imports.
|
||||
*/
|
||||
** changing them to trampoline symbols or make them imports.
|
||||
*/
|
||||
S = SymList;
|
||||
while (S) {
|
||||
/* If the symbol is marked as global, mark it as export, if it is
|
||||
* already defined, otherwise mark it as import.
|
||||
*/
|
||||
** already defined, otherwise mark it as import.
|
||||
*/
|
||||
if (S->Flags & SF_GLOBAL) {
|
||||
if (S->Flags & SF_DEFINED) {
|
||||
SymExportFromGlobal (S);
|
||||
@@ -610,10 +600,10 @@ void SymCheck (void)
|
||||
}
|
||||
|
||||
/* Second pass: Walk again through the symbols. Count exports and imports
|
||||
* and set address sizes where this has not happened before. Ignore
|
||||
* undefined's, since we handled them in the last pass, and ignore unused
|
||||
* symbols, since we handled them in the last pass, too.
|
||||
*/
|
||||
** and set address sizes where this has not happened before. Ignore
|
||||
** undefined's, since we handled them in the last pass, and ignore unused
|
||||
** symbols, since we handled them in the last pass, too.
|
||||
*/
|
||||
S = SymList;
|
||||
while (S) {
|
||||
if ((S->Flags & SF_UNUSED) == 0 &&
|
||||
@@ -649,8 +639,8 @@ void SymCheck (void)
|
||||
}
|
||||
|
||||
/* If the symbol is defined but has an unknown address size,
|
||||
* recalculate it.
|
||||
*/
|
||||
** recalculate it.
|
||||
*/
|
||||
if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
ExprDesc ED;
|
||||
ED_Init (&ED);
|
||||
@@ -673,9 +663,9 @@ void SymCheck (void)
|
||||
}
|
||||
|
||||
/* If the address size of the symbol was guessed, check the guess
|
||||
* against the actual address size and print a warning if the two
|
||||
* differ.
|
||||
*/
|
||||
** against the actual address size and print a warning if the two
|
||||
** differ.
|
||||
*/
|
||||
if (S->AddrSize != ADDR_SIZE_DEFAULT) {
|
||||
/* Do we have data for this address size? */
|
||||
if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
|
||||
@@ -735,10 +725,10 @@ void WriteImports (void)
|
||||
ObjWriteVar (ImportCount);
|
||||
|
||||
/* Walk throught list and write all valid imports to the file. An import
|
||||
* is considered valid, if it is either referenced, or the forced bit is
|
||||
* set. Otherwise, the import is ignored (no need to link in something
|
||||
* that isn't used).
|
||||
*/
|
||||
** is considered valid, if it is either referenced, or the forced bit is
|
||||
** set. Otherwise, the import is ignored (no need to link in something
|
||||
** that isn't used).
|
||||
*/
|
||||
S = SymList;
|
||||
while (S) {
|
||||
if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
|
||||
@@ -780,8 +770,8 @@ void WriteExports (void)
|
||||
unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
|
||||
|
||||
/* Check if this symbol has a size. If so, remember it in the
|
||||
* flags.
|
||||
*/
|
||||
** flags.
|
||||
*/
|
||||
long Size;
|
||||
SymEntry* SizeSym = FindSizeOfSymbol (S);
|
||||
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
|
||||
@@ -865,8 +855,8 @@ void WriteDbgSyms (void)
|
||||
ObjWriteVar (Count);
|
||||
|
||||
/* Walk through list and write all symbols to the file. Ignore size
|
||||
* symbols.
|
||||
*/
|
||||
** symbols.
|
||||
*/
|
||||
S = SymList;
|
||||
while (S) {
|
||||
if (IsDbgSym (S)) {
|
||||
@@ -876,8 +866,8 @@ void WriteDbgSyms (void)
|
||||
unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
|
||||
|
||||
/* Check if this symbol has a size. If so, remember it in the
|
||||
* flags.
|
||||
*/
|
||||
** flags.
|
||||
*/
|
||||
long Size;
|
||||
SymEntry* SizeSym = FindSizeOfSymbol (S);
|
||||
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
|
||||
@@ -891,8 +881,8 @@ void WriteDbgSyms (void)
|
||||
ObjWrite8 (S->AddrSize);
|
||||
|
||||
/* Write the id of the parent. For normal symbols, this is a
|
||||
* scope (symbol table), for cheap locals, it's a symbol.
|
||||
*/
|
||||
** scope (symbol table), for cheap locals, it's a symbol.
|
||||
*/
|
||||
if (SYM_IS_STD (SymFlags)) {
|
||||
ObjWriteVar (S->Sym.Tab->Id);
|
||||
} else {
|
||||
@@ -969,8 +959,8 @@ void WriteScopes (void)
|
||||
unsigned Flags = 0;
|
||||
|
||||
/* Check if this scope has a size. If so, remember it in the
|
||||
* flags.
|
||||
*/
|
||||
** flags.
|
||||
*/
|
||||
long Size;
|
||||
SymEntry* SizeSym = FindSizeOfScope (S);
|
||||
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
|
||||
@@ -1031,6 +1021,3 @@ void WriteScopes (void)
|
||||
/* Done writing the scopes */
|
||||
ObjEndScopes ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -112,28 +112,28 @@ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Acti
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name);
|
||||
/* Find a scope in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
*/
|
||||
** never create a new symbol, since this can only be done in one specific
|
||||
** scope.
|
||||
*/
|
||||
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action);
|
||||
/* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is
|
||||
* not found, create a new one. Return the entry found, or the new entry
|
||||
* created, or - in case Action is SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
** not found, create a new one. Return the entry found, or the new entry
|
||||
** created, or - in case Action is SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
|
||||
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action);
|
||||
/* Find a new symbol table entry in the given table. If Action contains
|
||||
* SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
|
||||
* entry found, or the new entry created, or - in case Action is
|
||||
* SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
|
||||
** entry found, or the new entry created, or - in case Action is
|
||||
** SYM_FIND_EXISTING - return 0.
|
||||
*/
|
||||
|
||||
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name);
|
||||
/* Find a symbol in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
*/
|
||||
** never create a new symbol, since this can only be done in one specific
|
||||
** scope.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned char GetSymTabType (const SymTable* S)
|
||||
@@ -178,6 +178,3 @@ void WriteScopes (void);
|
||||
/* End of symtab.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ int TokHasIVal (token_t Tok)
|
||||
|
||||
void CopyToken (Token* Dst, const Token* Src)
|
||||
/* Copy a token from Src to Dst. The current value of Dst.SVal is free'd,
|
||||
* so Dst must be initialized.
|
||||
*/
|
||||
** so Dst must be initialized.
|
||||
*/
|
||||
{
|
||||
/* Copy the fields */
|
||||
Dst->Tok = Src->Tok;
|
||||
@@ -72,6 +72,3 @@ void CopyToken (Token* Dst, const Token* Src)
|
||||
SB_Copy (&Dst->SVal, &Src->SVal);
|
||||
Dst->Pos = Src->Pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -244,7 +244,6 @@ typedef enum token_t {
|
||||
TOK_STRING,
|
||||
TOK_STRLEN,
|
||||
TOK_STRUCT,
|
||||
TOK_SUNPLUS,
|
||||
TOK_TAG,
|
||||
TOK_TCOUNT,
|
||||
TOK_TIME,
|
||||
@@ -307,14 +306,11 @@ INLINE int TokIsSep (enum token_t T)
|
||||
|
||||
void CopyToken (Token* Dst, const Token* Src);
|
||||
/* Copy a token. The current value of Dst.SVal is free'd, so Dst must be
|
||||
* initialized.
|
||||
*/
|
||||
** initialized.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of token.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -180,9 +180,9 @@ void FreeTokList (TokList* List)
|
||||
|
||||
enum token_t GetTokListTerm (enum token_t 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.
|
||||
*/
|
||||
** the case if the next token is the opening brace. If so, skip it and return
|
||||
** a closing brace, otherwise return Term.
|
||||
*/
|
||||
{
|
||||
if (CurTok.Tok == TOK_LCURLY) {
|
||||
NextTok ();
|
||||
@@ -216,16 +216,16 @@ void AddCurTok (TokList* List)
|
||||
|
||||
static int ReplayTokList (void* List)
|
||||
/* Function that gets the next token from a token list and sets it. This
|
||||
* function may be used together with the PushInput function from the istack
|
||||
* module.
|
||||
*/
|
||||
** function may be used together with the PushInput function from the istack
|
||||
** module.
|
||||
*/
|
||||
{
|
||||
/* Cast the generic pointer to an actual list */
|
||||
TokList* L = List;
|
||||
|
||||
/* If there are no more tokens, decrement the repeat counter. If it goes
|
||||
* zero, delete the list and remove the function from the stack.
|
||||
*/
|
||||
** zero, delete the list and remove the function from the stack.
|
||||
*/
|
||||
if (L->Last == 0) {
|
||||
if (++L->RepCount >= L->RepMax) {
|
||||
/* Done with this list */
|
||||
@@ -249,8 +249,8 @@ static int ReplayTokList (void* List)
|
||||
L->LI = StartLine (&CurTok.Pos, LI_TYPE_ASM, PushCounter);
|
||||
|
||||
/* If a check function is defined, call it, so it may look at the token
|
||||
* just set and changed it as apropriate.
|
||||
*/
|
||||
** just set and changed it as apropriate.
|
||||
*/
|
||||
if (L->Check) {
|
||||
L->Check (L);
|
||||
}
|
||||
@@ -266,9 +266,9 @@ static int ReplayTokList (void* List)
|
||||
|
||||
void PushTokList (TokList* List, const char* Desc)
|
||||
/* Push a token list to be used as input for InputFromStack. This includes
|
||||
* several initializations needed in the token list structure, so don't use
|
||||
* PushInput directly.
|
||||
*/
|
||||
** several initializations needed in the token list structure, so don't use
|
||||
** PushInput directly.
|
||||
*/
|
||||
{
|
||||
/* If the list is empty, just delete it and bail out */
|
||||
if (List->Count == 0) {
|
||||
@@ -283,6 +283,3 @@ void PushTokList (TokList* List, const char* Desc)
|
||||
++PushCounter;
|
||||
PushInput (ReplayTokList, List, Desc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -111,25 +111,21 @@ void FreeTokList (TokList* T);
|
||||
|
||||
token_t GetTokListTerm (token_t 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.
|
||||
*/
|
||||
** the case if the next token is the opening brace. If so, skip it and return
|
||||
** a closing brace, otherwise return Term.
|
||||
*/
|
||||
|
||||
void AddCurTok (TokList* T);
|
||||
/* Add the current token to the token list */
|
||||
|
||||
void PushTokList (TokList* List, const char* Desc);
|
||||
/* Push a token list to be used as input for InputFromStack. This includes
|
||||
* several initializations needed in the token list structure, so don't use
|
||||
* PushInput directly.
|
||||
*/
|
||||
** several initializations needed in the token list structure, so don't use
|
||||
** PushInput directly.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of toklist.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ static unsigned ULabDefCount = 0; /* Number of defined labels */
|
||||
|
||||
static ULabel* NewULabel (ExprNode* Val)
|
||||
/* Create a new ULabel and insert it into the collection. The created label
|
||||
* structure is returned.
|
||||
*/
|
||||
** structure is returned.
|
||||
*/
|
||||
{
|
||||
/* Allocate memory for the ULabel structure */
|
||||
ULabel* L = xmalloc (sizeof (ULabel));
|
||||
@@ -98,11 +98,11 @@ static ULabel* NewULabel (ExprNode* Val)
|
||||
|
||||
ExprNode* ULabRef (int Which)
|
||||
/* Get an unnamed label. If Which is negative, it is a backreference (a
|
||||
* reference to an already defined label), and the function will return a
|
||||
* segment relative expression. If Which is positive, it is a forward ref,
|
||||
* and the function will return a expression node for an unnamed label that
|
||||
* must be resolved later.
|
||||
*/
|
||||
** reference to an already defined label), and the function will return a
|
||||
** segment relative expression. If Which is positive, it is a forward ref,
|
||||
** and the function will return a expression node for an unnamed label that
|
||||
** must be resolved later.
|
||||
*/
|
||||
{
|
||||
int Index;
|
||||
ULabel* L;
|
||||
@@ -139,8 +139,8 @@ ExprNode* ULabRef (int Which)
|
||||
++L->Ref;
|
||||
|
||||
/* If the label is already defined, return its value, otherwise return
|
||||
* just a reference.
|
||||
*/
|
||||
** just a reference.
|
||||
*/
|
||||
if (L->Val) {
|
||||
return CloneExpr (L->Val);
|
||||
} else {
|
||||
@@ -155,9 +155,9 @@ void ULabDef (void)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
** 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 ();
|
||||
@@ -185,9 +185,9 @@ int ULabCanResolve (void)
|
||||
|
||||
ExprNode* ULabResolve (unsigned Index)
|
||||
/* Return a valid expression for the unnamed label with the given index. This
|
||||
* is used to resolve unnamed labels when assembly is done, so it is an error
|
||||
* if a label is still undefined in this phase.
|
||||
*/
|
||||
** is used to resolve unnamed labels when assembly is done, so it is an error
|
||||
** if a label is still undefined in this phase.
|
||||
*/
|
||||
{
|
||||
/* Get the label and check that it is defined */
|
||||
ULabel* L = CollAt (&ULabList, Index);
|
||||
@@ -201,8 +201,8 @@ ExprNode* ULabResolve (unsigned Index)
|
||||
|
||||
void ULabDone (void)
|
||||
/* Run through all unnamed labels, check for anomalies and errors and do
|
||||
* necessary cleanups.
|
||||
*/
|
||||
** necessary cleanups.
|
||||
*/
|
||||
{
|
||||
/* Check if there are undefined labels */
|
||||
unsigned I = ULabDefCount;
|
||||
@@ -213,8 +213,8 @@ void ULabDone (void)
|
||||
}
|
||||
|
||||
/* Walk over all labels and emit a warning if any unreferenced ones
|
||||
* are found. Remove line infos because they're no longer needed.
|
||||
*/
|
||||
** are found. Remove line infos because they're no longer needed.
|
||||
*/
|
||||
for (I = 0; I < CollCount (&ULabList); ++I) {
|
||||
ULabel* L = CollAtUnchecked (&ULabList, I);
|
||||
if (L->Ref == 0) {
|
||||
@@ -223,7 +223,3 @@ void ULabDone (void)
|
||||
ReleaseFullLineInfo (&L->LineInfos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
|
||||
ExprNode* ULabRef (int Which);
|
||||
/* Get an unnamed label. If Which is negative, it is a backreference (a
|
||||
* reference to an already defined label), and the function will return a
|
||||
* segment relative expression. If Which is positive, it is a forward ref,
|
||||
* and the function will return a expression node for an unnamed label that
|
||||
* must be resolved later.
|
||||
*/
|
||||
** reference to an already defined label), and the function will return a
|
||||
** segment relative expression. If Which is positive, it is a forward ref,
|
||||
** and the function will return a expression node for an unnamed label that
|
||||
** must be resolved later.
|
||||
*/
|
||||
|
||||
void ULabDef (void);
|
||||
/* Define an unnamed label at the current PC */
|
||||
@@ -60,20 +60,17 @@ int ULabCanResolve (void);
|
||||
|
||||
ExprNode* ULabResolve (unsigned Index);
|
||||
/* Return a valid expression for the unnamed label with the given index. This
|
||||
* is used to resolve unnamed labels when assembly is done, so it is an error
|
||||
* if a label is still undefined in this phase.
|
||||
*/
|
||||
** is used to resolve unnamed labels when assembly is done, so it is an error
|
||||
** if a label is still undefined in this phase.
|
||||
*/
|
||||
|
||||
void ULabDone (void);
|
||||
/* Run through all unnamed labels, check for anomalies and errors and do
|
||||
* necessary cleanups.
|
||||
*/
|
||||
** necessary cleanups.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of ulabel.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user