mirror of https://github.com/cc65/cc65.git
Merge eb2acfc3e4
into b1e1c13d4b
This commit is contained in:
commit
1b93598de9
|
@ -94,6 +94,8 @@ Short options:
|
|||
-W n Set warning level n
|
||||
-d Debug mode
|
||||
-g Add debug info to object file
|
||||
-x Expand macros in the listing
|
||||
repeat -x for full expansion
|
||||
-h Help (this text)
|
||||
-i Ignore case of symbols
|
||||
-l name Create a listing file if assembly was ok
|
||||
|
@ -111,6 +113,8 @@ Long options:
|
|||
--create-full-dep name Create a full make dependency file
|
||||
--debug Debug mode
|
||||
--debug-info Add debug info to object file
|
||||
--expand-macros Expand macros in listing
|
||||
Repeat to get full expansion
|
||||
--feature name Set an emulation feature
|
||||
--help Help (this text)
|
||||
--ignore-case Ignore case of symbols
|
||||
|
|
|
@ -69,6 +69,7 @@ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */
|
|||
unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */
|
||||
unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
|
||||
unsigned char WarningsAsErrors = 0; /* Error if any warnings */
|
||||
unsigned char ExpandMacros = 0; /* Expand macros in listing */
|
||||
|
||||
/* Emulation features */
|
||||
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */
|
||||
|
|
|
@ -71,6 +71,7 @@ extern unsigned char RelaxChecks; /* Relax a few assembler checks */
|
|||
extern unsigned char StringEscapes; /* Allow C-style escapes in strings */
|
||||
extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
|
||||
extern unsigned char WarningsAsErrors; /* Error if any warnings */
|
||||
extern unsigned char ExpandMacros; /* Expand macros in listing */
|
||||
|
||||
/* Emulation features */
|
||||
extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */
|
||||
|
|
|
@ -93,6 +93,7 @@ void PushInput (int (*Func) (void*), void* Data, const char* Desc)
|
|||
|
||||
/* Push it */
|
||||
E->Next = IStack;
|
||||
ICount++;
|
||||
IStack = E;
|
||||
}
|
||||
|
||||
|
@ -111,7 +112,7 @@ void PopInput (void)
|
|||
|
||||
/* Pop it */
|
||||
IStack = IStack->Next;
|
||||
|
||||
ICount--;
|
||||
/* And delete it */
|
||||
xfree (E);
|
||||
}
|
||||
|
@ -156,3 +157,8 @@ void CheckInputStack (void)
|
|||
Error ("Open %s", IStack->Desc);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned GetStackDepth (void)
|
||||
{
|
||||
return ICount;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ void CheckInputStack (void);
|
|||
** stuff on the input stack.
|
||||
*/
|
||||
|
||||
|
||||
unsigned GetStackDepth (void);
|
||||
|
||||
/* End of istack.h */
|
||||
|
||||
|
|
127
src/ca65/macro.c
127
src/ca65/macro.c
|
@ -53,6 +53,7 @@
|
|||
#include "pseudo.h"
|
||||
#include "toklist.h"
|
||||
#include "macro.h"
|
||||
#include "listing.h"
|
||||
|
||||
|
||||
|
||||
|
@ -74,7 +75,8 @@ static int HT_Compare (const void* Key1, const void* Key2);
|
|||
** than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
|
||||
|
||||
static char* GetTokenString (Token* T);
|
||||
/* decompile a token back to a string */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
|
@ -133,6 +135,7 @@ struct MacExp {
|
|||
TokNode* ParamExp; /* Node for expanding parameters */
|
||||
LineInfo* LI; /* Line info for the expansion */
|
||||
LineInfo* ParamLI; /* Line info for parameter expansion */
|
||||
unsigned ExpandStart; /* First pass through expansion ?*/
|
||||
};
|
||||
|
||||
/* Maximum number of nested macro expansions */
|
||||
|
@ -312,6 +315,7 @@ static MacExp* NewMacExp (Macro* M)
|
|||
E->ParamExp = 0;
|
||||
E->LI = 0;
|
||||
E->ParamLI = 0;
|
||||
E->ExpandStart = 1; /* set up detection of first call */
|
||||
|
||||
/* Mark the macro as expanding */
|
||||
++M->Expansions;
|
||||
|
@ -689,6 +693,8 @@ ExpandParam:
|
|||
Mac->ParamLI = 0;
|
||||
|
||||
}
|
||||
/* boolean to indicate that we need to start a new macro expansion line*/
|
||||
static int new_expand_line = 1;
|
||||
|
||||
/* We're not expanding macro parameters. Check if we have tokens left from
|
||||
** the macro itself.
|
||||
|
@ -697,7 +703,33 @@ ExpandParam:
|
|||
|
||||
/* Use next macro token */
|
||||
TokSet (Mac->Exp);
|
||||
|
||||
if (ExpandMacros) {
|
||||
if (new_expand_line) {
|
||||
/* Suppress unneeded lines if short expansion
|
||||
** the ExpandStart is used to ensure that
|
||||
** the invokation line itself isnt suppress
|
||||
** This is becuase we are always working a line behind
|
||||
** Lines we want to keep are upvoted so that this downvote
|
||||
** will not suppress them
|
||||
*/
|
||||
if (LineLast->FragList == 0 && ExpandMacros == 1 && !Mac->ExpandStart) {
|
||||
LineCur->Output--;
|
||||
}
|
||||
Mac->ExpandStart = 0;
|
||||
StrBuf mac_line = MakeLineFromTokens (Mac->Exp);
|
||||
NewListingLine (&mac_line, 0, 0);
|
||||
InitListingLine ();
|
||||
if (CurTok.Tok == TOK_SEGMENT) {
|
||||
/* upvote the lines to keep*/
|
||||
LineCur->Output = 2;
|
||||
}
|
||||
SB_Done (&mac_line);
|
||||
new_expand_line = 0;
|
||||
}
|
||||
if (CurTok.Tok == TOK_SEP) {
|
||||
new_expand_line = 1;
|
||||
}
|
||||
}
|
||||
/* Create new line info for this token */
|
||||
if (Mac->LI) {
|
||||
EndLine (Mac->LI);
|
||||
|
@ -794,6 +826,7 @@ MacEnd:
|
|||
PopInput ();
|
||||
|
||||
/* No token available */
|
||||
new_expand_line = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1065,3 +1098,93 @@ void EnableDefineStyleMacros (void)
|
|||
PRECONDITION (DisableDefines > 0);
|
||||
--DisableDefines;
|
||||
}
|
||||
StrBuf MakeLineFromTokens (TokNode* first)
|
||||
{
|
||||
/* This code reconstitutes a Macro line from the 'compiled' tokens*/
|
||||
unsigned I;
|
||||
/* string to be returned */
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
|
||||
/* prepend depth indicator */
|
||||
for (I = 0; I < GetStackDepth (); I++) {
|
||||
SB_AppendStr (&S, ">");
|
||||
}
|
||||
SB_AppendStr (&S, " ");
|
||||
|
||||
TokNode* tn = first;
|
||||
while (tn) {
|
||||
/* per token string */
|
||||
StrBuf T = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
Token* token = &tn->T;
|
||||
tn = tn->Next;
|
||||
char* token_string;
|
||||
/* leading white space?*/
|
||||
if (token->WS) SB_AppendChar (&T, ' ');
|
||||
/* is it a string of some sort?*/
|
||||
unsigned len = SB_GetLen (&token->SVal);
|
||||
if (len > 0) {
|
||||
SB_Append (&T, &token->SVal);
|
||||
} else if (token->Tok == TOK_INTCON) {
|
||||
char ival[12]; // max size a long can be
|
||||
snprintf (ival, sizeof(ival), "%ld", token->IVal);
|
||||
SB_AppendStr (&T, ival);
|
||||
} else if ((token_string = GetTokenString (token)) != NULL) {
|
||||
SB_AppendStr (&T, token_string);
|
||||
}
|
||||
SB_Append (&S, &T);
|
||||
if (token->Tok == TOK_SEP) {
|
||||
return S;
|
||||
}
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
static char* GetTokenString (Token* T)
|
||||
{
|
||||
switch (T->Tok) {
|
||||
|
||||
case TOK_ASSIGN: return ":="; /* := */
|
||||
case TOK_ULABEL: return ":++"; /* :++ or :-- */
|
||||
|
||||
case TOK_EQ:return "="; /* = */
|
||||
case TOK_NE: return "<>"; /* <> */
|
||||
case TOK_LT: return "<"; /* < */
|
||||
case TOK_GT:return ">"; /* > */
|
||||
case TOK_LE: return "<="; /* <= */
|
||||
case TOK_GE:return ">="; /* >= */
|
||||
|
||||
|
||||
case TOK_PLUS: return "+"; /* + */
|
||||
case TOK_MINUS:return "-"; /* - */
|
||||
case TOK_MUL: return "*"; /* * */
|
||||
case TOK_DIV: return "/"; /* / */
|
||||
case TOK_MOD:return "!"; /* ! */
|
||||
case TOK_OR: return "|"; /* | */
|
||||
case TOK_XOR: return "^"; /* ^ */
|
||||
case TOK_AND:return "&"; /* & */
|
||||
case TOK_SHL: return "<<"; /* << */
|
||||
case TOK_SHR: return ">>"; /* >> */
|
||||
case TOK_NOT:return "~"; /* ~ */
|
||||
|
||||
case TOK_PC: return "$"; /* $ if enabled */
|
||||
case TOK_NAMESPACE:return "::"; /* :: */
|
||||
case TOK_DOT:return "."; /* . */
|
||||
case TOK_COMMA:return ","; /* , */
|
||||
case TOK_HASH: return "#"; /* # */
|
||||
case TOK_COLON:return ":"; /* : */
|
||||
case TOK_LPAREN:return "("; /* ( */
|
||||
case TOK_RPAREN:return ")"; /* ) */
|
||||
case TOK_LBRACK:return "["; /* [ */
|
||||
case TOK_RBRACK:return "]"; /* ] */
|
||||
case TOK_LCURLY:return "{"; /* { */
|
||||
case TOK_RCURLY:return "}"; /* } */
|
||||
case TOK_AT:return "@"; /* @ - in Sweet16 mode */
|
||||
|
||||
case TOK_OVERRIDE_ZP:return "z:"; /* z: */
|
||||
case TOK_OVERRIDE_ABS:return "a:"; /* a: */
|
||||
case TOK_OVERRIDE_FAR:return "f:"; /* f: */
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#ifndef MACRO_H
|
||||
#define MACRO_H
|
||||
|
||||
|
||||
#include "toklist.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
|
@ -105,7 +105,7 @@ void EnableDefineStyleMacros (void);
|
|||
** DisableDefineStyleMacros.
|
||||
*/
|
||||
|
||||
|
||||
StrBuf MakeLineFromTokens (TokNode* first);
|
||||
|
||||
/* End of macro.h */
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ static void Usage (void)
|
|||
" -s\t\t\t\tEnable smart mode\n"
|
||||
" -t sys\t\t\tSet the target system\n"
|
||||
" -v\t\t\t\tIncrease verbosity\n"
|
||||
" -x\t\t\t\tExpand macros\n"
|
||||
"\n"
|
||||
"Long options:\n"
|
||||
" --auto-import\t\t\tMark unresolved symbols as import\n"
|
||||
|
@ -116,6 +117,7 @@ static void Usage (void)
|
|||
" --create-full-dep name\tCreate a full make dependency file\n"
|
||||
" --debug\t\t\tDebug mode\n"
|
||||
" --debug-info\t\t\tAdd debug info to object file\n"
|
||||
" --expand-macros\t\tExpand macros in the listing\n"
|
||||
" --feature name\t\tSet an emulation feature\n"
|
||||
" --help\t\t\tHelp (this text)\n"
|
||||
" --ignore-case\t\t\tIgnore case of symbols\n"
|
||||
|
@ -670,7 +672,16 @@ static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
|
|||
WarningsAsErrors = 1;
|
||||
}
|
||||
|
||||
static void OptExpandMacros (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Expand macros in listing
|
||||
** one -x means short listing
|
||||
** two means full listing
|
||||
*/
|
||||
{
|
||||
|
||||
ExpandMacros++;
|
||||
}
|
||||
|
||||
static void DoPCAssign (void)
|
||||
/* Start absolute code */
|
||||
|
@ -695,9 +706,10 @@ 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 ()) {
|
||||
|
||||
if (!HavePushedInput () ) {
|
||||
InitListingLine ();
|
||||
}
|
||||
|
||||
|
@ -886,6 +898,7 @@ static void Assemble (void)
|
|||
while (CurTok.Tok != TOK_EOF) {
|
||||
OneLine ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -947,6 +960,7 @@ int main (int argc, char* argv [])
|
|||
{ "--create-full-dep", 1, OptCreateFullDep },
|
||||
{ "--debug", 0, OptDebug },
|
||||
{ "--debug-info", 0, OptDebugInfo },
|
||||
{ "--expand-macros", 0, OptExpandMacros },
|
||||
{ "--feature", 1, OptFeature },
|
||||
{ "--help", 0, OptHelp },
|
||||
{ "--ignore-case", 0, OptIgnoreCase },
|
||||
|
@ -1069,6 +1083,10 @@ int main (int argc, char* argv [])
|
|||
case 'W':
|
||||
WarnLevel = atoi (GetArg (&I, 2));
|
||||
break;
|
||||
case 'x':
|
||||
ExpandMacros++;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
UnknownOption (Arg);
|
||||
|
|
|
@ -378,6 +378,16 @@ static void IFMarkStart (CharSource* S)
|
|||
static void IFNextChar (CharSource* S)
|
||||
/* Read the next character from the input file */
|
||||
{
|
||||
/* if expanding macros the next input line gets pushed too early
|
||||
** to the output. So defer the push.
|
||||
** Its harmless to do it regardless of expansion or not
|
||||
*/
|
||||
static int pending_line = 0;
|
||||
if (pending_line) {
|
||||
NewListingLine (&S->V.File.Line, S->V.File.Pos.Name, FCount);
|
||||
pending_line = 0;
|
||||
};
|
||||
|
||||
/* Check for end of line, read the next line if needed */
|
||||
while (SB_GetIndex (&S->V.File.Line) >= SB_GetLen (&S->V.File.Line)) {
|
||||
|
||||
|
@ -443,7 +453,8 @@ static void IFNextChar (CharSource* S)
|
|||
S->V.File.Pos.Line++;
|
||||
|
||||
/* Remember the new line for the listing */
|
||||
NewListingLine (&S->V.File.Line, S->V.File.Pos.Name, FCount);
|
||||
|
||||
pending_line = 1;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
#include "nexttok.h"
|
||||
#include "scanner.h"
|
||||
#include "toklist.h"
|
||||
|
||||
#include "macro.h"
|
||||
#include "listing.h"
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -248,6 +250,26 @@ static int ReplayTokList (void* List)
|
|||
}
|
||||
L->LI = StartLine (&CurTok.Pos, LI_TYPE_ASM, PushCounter);
|
||||
|
||||
/* see description in macro.c */
|
||||
static int new_expand_line = 1;
|
||||
if (ExpandMacros) {
|
||||
if (new_expand_line) {
|
||||
if (LineLast->FragList == 0 && ExpandMacros==1) {
|
||||
LineCur->Output--;
|
||||
}
|
||||
StrBuf mac_line = MakeLineFromTokens (L->Last);
|
||||
if (L->Last->T.Tok == TOK_SEGMENT) {
|
||||
LineCur->Output = 2;
|
||||
}
|
||||
NewListingLine (&mac_line, 0, 0);
|
||||
InitListingLine ();
|
||||
SB_Done (&mac_line);
|
||||
new_expand_line = 0;
|
||||
}
|
||||
if (L->Last->T.Tok == TOK_SEP) {
|
||||
new_expand_line = 1;
|
||||
}
|
||||
}
|
||||
/* If a check function is defined, call it, so it may look at the token
|
||||
** just set and changed it as apropriate.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue