From 3a272d93afc234f80ad34beece7d6d80dfc35b81 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 22 May 2001 16:54:47 +0000 Subject: [PATCH] More polishing to get the line info right git-svn-id: svn://svn.cc65.org/cc65/trunk@742 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 28 ++--- src/cc65/codeseg.c | 9 +- src/cc65/expr.c | 6 +- src/cc65/goto.c | 2 +- src/cc65/goto.h | 2 +- src/cc65/lineinfo.c | 34 +++++- src/cc65/stmt.c | 257 ++++++++++++++++++++++++-------------------- 7 files changed, 194 insertions(+), 144 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index ead59afaf..7b2e7dbbc 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -357,19 +357,21 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F) } /* Print usage info if requested by the debugging flag */ -// if (Debug) { - Chars += fprintf (F, - "%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u\n", - 30-Chars, "", - (E->Use & REG_A)? 'A' : '_', - (E->Use & REG_X)? 'X' : '_', - (E->Use & REG_Y)? 'Y' : '_', - (E->Chg & REG_A)? 'A' : '_', - (E->Chg & REG_X)? 'X' : '_', - (E->Chg & REG_Y)? 'Y' : '_', - E->Size); -// } - + if (Debug) { + fprintf (F, + "%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u\n", + 30-Chars, "", + (E->Use & REG_A)? 'A' : '_', + (E->Use & REG_X)? 'X' : '_', + (E->Use & REG_Y)? 'Y' : '_', + (E->Chg & REG_A)? 'A' : '_', + (E->Chg & REG_X)? 'X' : '_', + (E->Chg & REG_Y)? 'Y' : '_', + E->Size); + } else { + /* Terminate the line */ + fprintf (F, "\n"); + } } diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index 57bf95cec..9371593d7 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -436,7 +436,7 @@ void AddCodeEntry (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) break; default: - E = ParseInsn (S, LI, L); + E = ParseInsn (S, LI, L); break; } @@ -949,12 +949,7 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F) if (E->LI != LI) { LI = E->LI; if (AddSource) { - /* Skip spaces to make the output somewhat more readable */ - const char* Line = LI->Line; - while (IsBlank (*Line)) { - ++Line; - } - fprintf (F, ";\n; %s\n;\n", Line); + fprintf (F, ";\n; %s\n;\n", LI->Line); } } /* Output the code */ diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 1c51d0139..995cf39e2 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3128,9 +3128,6 @@ void test (unsigned label, int cond) /* Load the value into the primary register */ exprhs (CF_FORCECHAR, k, &lval); - /* Check for the closing brace */ - ConsumeRParen (); - /* Generate the jump */ if (cond) { g_truejump (CF_NONE, label); @@ -3143,6 +3140,9 @@ void test (unsigned label, int cond) g_falsejump (CF_NONE, label); } } + + /* Check for the closing brace */ + ConsumeRParen (); } diff --git a/src/cc65/goto.c b/src/cc65/goto.c index fe3e1b8bd..33d056f9a 100644 --- a/src/cc65/goto.c +++ b/src/cc65/goto.c @@ -47,7 +47,7 @@ -void DoGoto (void) +void GotoStatement (void) /* Process a goto statement. */ { /* Eat the "goto" */ diff --git a/src/cc65/goto.h b/src/cc65/goto.h index 4492b1e89..3ec95e542 100644 --- a/src/cc65/goto.h +++ b/src/cc65/goto.h @@ -44,7 +44,7 @@ -void DoGoto (void); +void GotoStatement (void); /* Process a goto statement. */ void DoLabel (void); diff --git a/src/cc65/lineinfo.c b/src/cc65/lineinfo.c index fbf954134..60ba962ef 100644 --- a/src/cc65/lineinfo.c +++ b/src/cc65/lineinfo.c @@ -36,10 +36,12 @@ #include /* common */ +#include "chartype.h" #include "check.h" #include "xmalloc.h" /* cc65 */ +#include "global.h" #include "input.h" #include "lineinfo.h" @@ -65,11 +67,20 @@ static LineInfo* CurLineInfo = 0; static LineInfo* NewLineInfo (struct IFile* F, unsigned LineNum, const char* Line) /* Create and return a new line info. Ref count will be 1. */ { + unsigned Len; + LineInfo* LI; + char* S; + + /* Skip leading spaces in Line */ + while (IsBlank (*Line)) { + ++Line; + } + /* Calculate the length of the line */ - unsigned Len = strlen (Line); + Len = strlen (Line); /* Allocate memory */ - LineInfo* LI = xmalloc (sizeof (LineInfo) + Len); + LI = xmalloc (sizeof (LineInfo) + Len); /* Initialize the fields */ LI->RefCount = 1; @@ -77,6 +88,18 @@ static LineInfo* NewLineInfo (struct IFile* F, unsigned LineNum, const char* Lin LI->LineNum = LineNum; memcpy (LI->Line, Line, Len+1); + /* Replace tabs by spaces in the given line since tabs will give rather + * arbitrary results when used in the output later, and if we do it here, + * we won't need another copy. + */ + S = LI->Line; + while (*S) { + if (*S == '\t') { + *S = ' '; + } + ++S; + } + /* Return the new struct */ return LI; } @@ -133,6 +156,13 @@ void UpdateLineInfo (struct IFile* F, unsigned LineNum, const char* Line) ReleaseLineInfo (CurLineInfo); } + /* If we have intermixed assembly switched off, use an empty line instead + * of the supplied one to save some memory. + */ + if (!AddSource) { + Line = ""; + } + /* Create a new line info */ CurLineInfo = NewLineInfo (F, LineNum, Line); } diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 866c859d9..54934cd19 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -45,33 +45,38 @@ +/*****************************************************************************/ +/* Forwards */ +/*****************************************************************************/ + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ -static int DoIf (void) +static int IfStatement (void) /* Handle an 'if' statement */ { - int flab1; - int flab2; - int gotbreak; + unsigned Label1; + int GotBreak; /* Skip the if */ NextToken (); /* Generate a jump label and parse the condition */ - flab1 = GetLocalLabel (); - test (flab1, 0); + Label1 = GetLocalLabel (); + test (Label1, 0); /* Parse the if body */ - gotbreak = Statement (); + GotBreak = Statement (); /* Else clause present? */ if (CurTok.Tok != TOK_ELSE) { - g_defcodelabel (flab1); + g_defcodelabel (Label1); /* Since there's no else clause, we're not sure, if the a break * statement is really executed. */ @@ -79,36 +84,30 @@ static int DoIf (void) } else { - /* Skip the else */ + /* Generate a jump around the else branch */ + unsigned Label2 = GetLocalLabel (); + g_jump (Label2); + + /* Skip the else */ NextToken (); - /* If we had some sort of break statement at the end of the if clause, - * there's no need to generate an additional jump around the else - * clause, since the jump is never reached. - */ - if (!gotbreak) { - flab2 = GetLocalLabel (); - g_jump (flab2); - } else { - /* Mark the label as unused */ - flab2 = 0; - } - g_defcodelabel (flab1); - gotbreak &= Statement (); + /* Define the target for the first test */ + g_defcodelabel (Label1); + + /* Total break only if both branches had a break. */ + GotBreak &= Statement (); /* Generate the label for the else clause */ - if (flab2) { - g_defcodelabel (flab2); - } + g_defcodelabel (Label2); /* Done */ - return gotbreak; + return GotBreak; } } -static void DoDo (void) +static void DoStatement (void) /* Handle the 'do' statement */ { /* Get the loop control labels */ @@ -141,7 +140,7 @@ static void DoDo (void) -static void DoWhile (void) +static void WhileStatement (void) /* Handle the 'while' statement */ { /* Get the loop control labels */ @@ -184,7 +183,7 @@ static void DoWhile (void) -static void DoReturn (void) +static void ReturnStatement (void) /* Handle the 'return' statement */ { struct expent lval; @@ -215,7 +214,7 @@ static void DoReturn (void) -static void DoBreak (void) +static void BreakStatement (void) /* Handle the 'break' statement */ { LoopDesc* L; @@ -242,7 +241,7 @@ static void DoBreak (void) -static void DoContinue (void) +static void ContinueStatement (void) /* Handle the 'continue' statement */ { LoopDesc* L; @@ -284,8 +283,8 @@ static void DoContinue (void) static void CascadeSwitch (struct expent* eval) /* Handle a switch statement for chars with a cmp cascade for the selector */ { - unsigned ExitLab; /* Exit label */ - unsigned NextLab; /* Next case label */ + unsigned ExitLab; /* Exit label */ + unsigned NextLab; /* Next case label */ unsigned CodeLab; /* Label that starts the actual selector code */ int HaveBreak; /* Remember if we exited with break */ int HaveDefault; /* Remember if we had a default label */ @@ -352,29 +351,29 @@ static void CascadeSwitch (struct expent* eval) case T_SCHAR: /* Signed char */ if (Val < -128 || Val > 127) { - Error ("Range error"); - } - break; - - case T_UCHAR: - if (Val < 0 || Val > 255) { - Error ("Range error"); - } - break; - - case T_INT: - if (Val < -32768 || Val > 32767) { - Error ("Range error"); - } - break; - - case T_UINT: - if (Val < 0 || Val > 65535) { - Error ("Range error"); - } - break; - - default: + Error ("Range error"); + } + break; + + case T_UCHAR: + if (Val < 0 || Val > 255) { + Error ("Range error"); + } + break; + + case T_INT: + if (Val < -32768 || Val > 32767) { + Error ("Range error"); + } + break; + + case T_UINT: + if (Val < 0 || Val > 65535) { + Error ("Range error"); + } + break; + + default: Internal ("Invalid type: %02X", *eval->e_tptr & 0xFF); } @@ -385,17 +384,17 @@ static void CascadeSwitch (struct expent* eval) * the condition is true. */ if (CurTok.Tok == TOK_CASE) { - /* Create a code label if needed */ - if (CodeLab == 0) { - CodeLab = GetLocalLabel (); - } - g_falsejump (CF_NONE, CodeLab); + /* Create a code label if needed */ + if (CodeLab == 0) { + CodeLab = GetLocalLabel (); + } + g_falsejump (CF_NONE, CodeLab); } else if (CurTok.Tok != TOK_DEFAULT) { /* No case follows, jump to next selector */ if (NextLab == 0) { NextLab = GetLocalLabel (); } - g_truejump (CF_NONE, NextLab); + g_truejump (CF_NONE, NextLab); } /* Skip the colon */ @@ -475,7 +474,7 @@ static void TableSwitch (struct expent* eval) int lcount; /* Label count */ int HaveBreak; /* Last statement has a break */ int HaveDefault; /* Remember if we had a default label */ - unsigned Flags; /* Code generator flags */ + unsigned Flags; /* Code generator flags */ struct expent lval; /* Case label expression */ struct swent *p; struct swent *swtab; @@ -569,7 +568,7 @@ static void TableSwitch (struct expent* eval) -static void DoSwitch (void) +static void SwitchStatement (void) /* Handle a 'switch' statement */ { struct expent eval; /* Switch statement expression */ @@ -595,98 +594,122 @@ static void DoSwitch (void) -static void DoFor (void) +static void ForStatement (void) /* Handle a 'for' statement */ { - int loop; - int lab; - int linc; - int lstat; struct expent lval1; struct expent lval2; struct expent lval3; + /* Get several local labels needed later */ + unsigned TestLabel = GetLocalLabel (); + unsigned lab = GetLocalLabel (); + unsigned IncLabel = GetLocalLabel (); + unsigned lstat = GetLocalLabel (); + + /* Skip the FOR token */ NextToken (); - loop = GetLocalLabel (); - lab = GetLocalLabel (); - linc = GetLocalLabel (); - lstat = GetLocalLabel (); - AddLoop (oursp, loop, lab, linc, lstat); + + /* Add the loop to the loop stack */ + AddLoop (oursp, TestLabel, lab, IncLabel, lstat); + + /* Skip the opening paren */ ConsumeLParen (); - if (CurTok.Tok != TOK_SEMI) { /* exp1 */ + + /* Parse the initializer expression */ + if (CurTok.Tok != TOK_SEMI) { expression (&lval1); } ConsumeSemi (); - g_defcodelabel (loop); - if (CurTok.Tok != TOK_SEMI) { /* exp2 */ - boolexpr (&lval2); - g_truejump (CF_NONE, lstat); - g_jump (lab); + + /* Label for the test expressions */ + g_defcodelabel (TestLabel); + + /* Parse the text expression */ + if (CurTok.Tok != TOK_SEMI) { + boolexpr (&lval2); + g_truejump (CF_NONE, lstat); + g_jump (lab); } else { - g_jump (lstat); + g_jump (lstat); } ConsumeSemi (); - g_defcodelabel (linc); - if (CurTok.Tok != TOK_RPAREN) { /* exp3 */ + + /* Label for the increment expression */ + g_defcodelabel (IncLabel); + + /* Parse the increment expression */ + if (CurTok.Tok != TOK_RPAREN) { expression (&lval3); } + + /* Jump to the test */ + g_jump (TestLabel); + + /* Skip the closing paren */ ConsumeRParen (); - g_jump (loop); + + /* Loop body */ g_defcodelabel (lstat); Statement (); - g_jump (linc); + + /* Jump back to the increment expression */ + g_jump (IncLabel); + + /* Declare the break label */ g_defcodelabel (lab); + + /* Remove the loop from the loop stack */ DelLoop (); } static int CompoundStatement (void) -/* Compound statement. Allow any number of statements inside braces. */ +/* Compound statement. Allow any number of statements inside braces. The + * function returns true if the last statement was a break or return. + */ { - int isbrk; - int oldsp; - - /* eat LCURLY */ - NextToken (); + int GotBreak; /* Remember the stack at block entry */ - oldsp = oursp; + int OldStack = oursp; /* Enter a new lexical level */ EnterBlockLevel (); + /* Skip the rcurly */ + NextToken (); + /* Parse local variable declarations if any */ DeclareLocals (); /* Now process statements in this block */ - isbrk = 0; + GotBreak = 0; while (CurTok.Tok != TOK_RCURLY) { if (CurTok.Tok != TOK_CEOF) { - isbrk = Statement (); + GotBreak = Statement (); } else { break; } } - /* Emit references to imports/exports for this block */ - EmitExternals (); - /* Clean up the stack. */ - if (isbrk) { - oursp = oldsp; - } else { - g_space (oursp - oldsp); - oursp = oldsp; + if (!GotBreak) { + g_space (oursp - OldStack); } + oursp = OldStack; + + /* Skip the closing brace */ + ConsumeRCurly (); + + /* Emit references to imports/exports for this block */ + EmitExternals (); /* Leave the lexical level */ LeaveBlockLevel (); - /* Eat closing brace */ - ConsumeRCurly (); - - return isbrk; + return GotBreak; } @@ -698,7 +721,7 @@ int Statement (void) { struct expent lval; - /* */ + /* Check for a label */ if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { /* Special handling for a label */ @@ -709,44 +732,44 @@ int Statement (void) switch (CurTok.Tok) { case TOK_LCURLY: - return CompoundStatement (); + return CompoundStatement (); case TOK_IF: - return DoIf (); + return IfStatement (); case TOK_WHILE: - DoWhile (); + WhileStatement (); break; case TOK_DO: - DoDo (); + DoStatement (); break; case TOK_SWITCH: - DoSwitch (); + SwitchStatement (); break; case TOK_RETURN: - DoReturn (); + ReturnStatement (); ConsumeSemi (); return 1; case TOK_BREAK: - DoBreak (); + BreakStatement (); ConsumeSemi (); return 1; case TOK_CONTINUE: - DoContinue (); + ContinueStatement (); ConsumeSemi (); return 1; case TOK_FOR: - DoFor (); + ForStatement (); break; case TOK_GOTO: - DoGoto (); + GotoStatement (); ConsumeSemi (); return 1; -- 2.39.5