More renaming. Remove the case label limit by using a collection to store
the switch entries. git-svn-id: svn://svn.cc65.org/cc65/trunk@807 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -231,7 +231,7 @@ static void ParseEnumDecl (void)
|
|||||||
ExprDesc lval;
|
ExprDesc lval;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
EnumVal = lval.e_const;
|
EnumVal = lval.ConstVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an entry to the symbol table */
|
/* Add an entry to the symbol table */
|
||||||
@@ -859,7 +859,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
if (CurTok.Tok != TOK_RBRACK) {
|
if (CurTok.Tok != TOK_RBRACK) {
|
||||||
ExprDesc lval;
|
ExprDesc lval;
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
Size = lval.e_const;
|
Size = lval.ConstVal;
|
||||||
}
|
}
|
||||||
ConsumeRBrack ();
|
ConsumeRBrack ();
|
||||||
*D->T++ = T_ARRAY;
|
*D->T++ = T_ARRAY;
|
||||||
@@ -965,9 +965,9 @@ static void ParseVoidInit (void)
|
|||||||
|
|
||||||
case T_SCHAR:
|
case T_SCHAR:
|
||||||
case T_UCHAR:
|
case T_UCHAR:
|
||||||
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
|
if ((lval.Flags & E_MCTYPE) == E_TCONST) {
|
||||||
/* Make it byte sized */
|
/* Make it byte sized */
|
||||||
lval.e_const &= 0xFF;
|
lval.ConstVal &= 0xFF;
|
||||||
}
|
}
|
||||||
DefineData (&lval);
|
DefineData (&lval);
|
||||||
break;
|
break;
|
||||||
@@ -978,9 +978,9 @@ static void ParseVoidInit (void)
|
|||||||
case T_UINT:
|
case T_UINT:
|
||||||
case T_PTR:
|
case T_PTR:
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
|
if ((lval.Flags & E_MCTYPE) == E_TCONST) {
|
||||||
/* Make it word sized */
|
/* Make it word sized */
|
||||||
lval.e_const &= 0xFFFF;
|
lval.ConstVal &= 0xFFFF;
|
||||||
}
|
}
|
||||||
DefineData (&lval);
|
DefineData (&lval);
|
||||||
break;
|
break;
|
||||||
@@ -1070,9 +1070,9 @@ void ParseInit (type* T)
|
|||||||
case T_SCHAR:
|
case T_SCHAR:
|
||||||
case T_UCHAR:
|
case T_UCHAR:
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
|
if ((lval.Flags & E_MCTYPE) == E_TCONST) {
|
||||||
/* Make it byte sized */
|
/* Make it byte sized */
|
||||||
lval.e_const &= 0xFF;
|
lval.ConstVal &= 0xFF;
|
||||||
}
|
}
|
||||||
assignadjust (T, &lval);
|
assignadjust (T, &lval);
|
||||||
DefineData (&lval);
|
DefineData (&lval);
|
||||||
@@ -1084,9 +1084,9 @@ void ParseInit (type* T)
|
|||||||
case T_UINT:
|
case T_UINT:
|
||||||
case T_PTR:
|
case T_PTR:
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
|
if ((lval.Flags & E_MCTYPE) == E_TCONST) {
|
||||||
/* Make it word sized */
|
/* Make it word sized */
|
||||||
lval.e_const &= 0xFFFF;
|
lval.ConstVal &= 0xFFFF;
|
||||||
}
|
}
|
||||||
assignadjust (T, &lval);
|
assignadjust (T, &lval);
|
||||||
DefineData (&lval);
|
DefineData (&lval);
|
||||||
@@ -1095,9 +1095,9 @@ void ParseInit (type* T)
|
|||||||
case T_LONG:
|
case T_LONG:
|
||||||
case T_ULONG:
|
case T_ULONG:
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
|
if ((lval.Flags & E_MCTYPE) == E_TCONST) {
|
||||||
/* Make it long sized */
|
/* Make it long sized */
|
||||||
lval.e_const &= 0xFFFFFFFF;
|
lval.ConstVal &= 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
assignadjust (T, &lval);
|
assignadjust (T, &lval);
|
||||||
DefineData (&lval);
|
DefineData (&lval);
|
||||||
|
|||||||
486
src/cc65/expr.c
486
src/cc65/expr.c
File diff suppressed because it is too large
Load Diff
@@ -46,10 +46,10 @@ typedef struct ExprDesc ExprDesc;
|
|||||||
struct ExprDesc {
|
struct ExprDesc {
|
||||||
struct SymEntry* Sym; /* Symbol table entry if known */
|
struct SymEntry* Sym; /* Symbol table entry if known */
|
||||||
type* Type; /* Type array of expression */
|
type* Type; /* Type array of expression */
|
||||||
long e_const; /* Value if expression constant */
|
long ConstVal;/* Value if expression constant */
|
||||||
unsigned short e_flags;
|
unsigned short Flags;
|
||||||
unsigned short e_test; /* */
|
unsigned short Test; /* */
|
||||||
unsigned long e_name; /* Name or label number */
|
unsigned long Name; /* Name or label number */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Push the value */
|
/* Push the value */
|
||||||
g_push (flags | TypeOf (Decl.Type), lval.e_const);
|
g_push (flags | TypeOf (Decl.Type), lval.ConstVal);
|
||||||
|
|
||||||
/* Mark the variable as referenced */
|
/* Mark the variable as referenced */
|
||||||
SC |= SC_REF;
|
SC |= SC_REF;
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ static void FlagPragma (unsigned char* Flag)
|
|||||||
constexpr (&val);
|
constexpr (&val);
|
||||||
|
|
||||||
/* Store the value into the flag parameter */
|
/* Store the value into the flag parameter */
|
||||||
*Flag = (val.e_const != 0);
|
*Flag = (val.ConstVal != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -670,7 +670,7 @@ static int doiff (int skip)
|
|||||||
NextTok = sv2;
|
NextTok = sv2;
|
||||||
|
|
||||||
/* Set the #if condition according to the expression result */
|
/* Set the #if condition according to the expression result */
|
||||||
return (setmflag (skip, 1, lval.e_const != 0));
|
return (setmflag (skip, 1, lval.ConstVal != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -119,14 +119,14 @@ static void StdFunc_strlen (ExprDesc* lval)
|
|||||||
|
|
||||||
/* Check if the parameter is a const address */
|
/* Check if the parameter is a const address */
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
unsigned pflags = pval.e_flags & ~E_MCTYPE;
|
unsigned pflags = pval.Flags & ~E_MCTYPE;
|
||||||
if (pflags == E_MCONST) {
|
if (pflags == E_MCONST) {
|
||||||
/* Constant numeric address */
|
/* Constant numeric address */
|
||||||
flags |= CF_CONST | CF_ABSOLUTE;
|
flags |= CF_CONST | CF_ABSOLUTE;
|
||||||
} else if (k == 0 && ((pflags & E_MGLOBAL) != 0 || pval.e_flags == E_MEOFFS)) {
|
} else if (k == 0 && ((pflags & E_MGLOBAL) != 0 || pval.Flags == E_MEOFFS)) {
|
||||||
/* Global array with or without offset */
|
/* Global array with or without offset */
|
||||||
flags |= CF_CONST;
|
flags |= CF_CONST;
|
||||||
if (pval.e_flags & E_TGLAB) {
|
if (pval.Flags & E_TGLAB) {
|
||||||
/* External linkage */
|
/* External linkage */
|
||||||
flags |= CF_EXTERNAL;
|
flags |= CF_EXTERNAL;
|
||||||
} else {
|
} else {
|
||||||
@@ -144,7 +144,7 @@ static void StdFunc_strlen (ExprDesc* lval)
|
|||||||
assignadjust (ArgType, &pval);
|
assignadjust (ArgType, &pval);
|
||||||
|
|
||||||
/* Generate the strlen code */
|
/* Generate the strlen code */
|
||||||
g_strlen (flags, pval.e_name, pval.e_const);
|
g_strlen (flags, pval.Name, pval.ConstVal);
|
||||||
|
|
||||||
/* We expect the closing brace */
|
/* We expect the closing brace */
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
@@ -173,7 +173,7 @@ void HandleStdFunc (ExprDesc* lval)
|
|||||||
/* Generate code for a known standard function. */
|
/* Generate code for a known standard function. */
|
||||||
{
|
{
|
||||||
/* Get a pointer to the table entry */
|
/* Get a pointer to the table entry */
|
||||||
struct StdFuncDesc* F = FindFunc ((const char*) lval->e_name);
|
struct StdFuncDesc* F = FindFunc ((const char*) lval->Name);
|
||||||
CHECK (F != 0);
|
CHECK (F != 0);
|
||||||
|
|
||||||
/* Call the handler function */
|
/* Call the handler function */
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "coll.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
@@ -379,7 +380,7 @@ static void CascadeSwitch (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check the range of the expression */
|
/* Check the range of the expression */
|
||||||
Val = lval.e_const;
|
Val = lval.ConstVal;
|
||||||
switch (*Expr->Type) {
|
switch (*Expr->Type) {
|
||||||
|
|
||||||
case T_SCHAR:
|
case T_SCHAR:
|
||||||
@@ -496,43 +497,34 @@ static void TableSwitch (ExprDesc* Expr)
|
|||||||
/* Handle a switch statement via table based selector */
|
/* Handle a switch statement via table based selector */
|
||||||
{
|
{
|
||||||
/* Entry for one case in a switch statement */
|
/* Entry for one case in a switch statement */
|
||||||
struct swent {
|
typedef struct {
|
||||||
long sw_const; /* selector value */
|
long Value; /* selector value */
|
||||||
unsigned sw_lab; /* label for this selector */
|
unsigned Label; /* label for this selector */
|
||||||
};
|
} SwitchEntry;
|
||||||
|
|
||||||
int dlabel; /* for default */
|
unsigned DefaultLabel; /* Label for default case */
|
||||||
int lab; /* exit label */
|
unsigned ExitLabel; /* exit label */
|
||||||
int label; /* label for case */
|
|
||||||
int lcase; /* label for compares */
|
int lcase; /* label for compares */
|
||||||
int lcount; /* Label count */
|
|
||||||
int HaveBreak; /* Last statement has a break */
|
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 */
|
||||||
ExprDesc lval; /* Case label expression */
|
ExprDesc lval; /* Case label expression */
|
||||||
struct swent *p;
|
unsigned I;
|
||||||
struct swent *swtab;
|
SwitchEntry* P;
|
||||||
|
Collection SwitchTab;
|
||||||
|
|
||||||
/* Allocate memory for the switch table */
|
/* Initialize the collection for the switch entries */
|
||||||
swtab = xmalloc (CASE_MAX * sizeof (struct swent));
|
InitCollection (&SwitchTab);
|
||||||
|
|
||||||
/* Create a look so we may break out, init labels */
|
/* Create a look so we may break out, init labels */
|
||||||
HaveBreak = 0; /* Keep gcc silent */
|
HaveBreak = 0; /* Keep gcc silent */
|
||||||
HaveDefault = 0; /* No default case until now */
|
DefaultLabel = 0; /* No default case until now */
|
||||||
dlabel = 0; /* init */
|
ExitLabel = GetLocalLabel (); /* get exit */
|
||||||
lab = GetLocalLabel (); /* get exit */
|
AddLoop (oursp, 0, ExitLabel, 0, 0);
|
||||||
p = swtab;
|
|
||||||
AddLoop (oursp, 0, lab, 0, 0);
|
|
||||||
|
|
||||||
/* Jump behind the code for the CASE labels */
|
/* Jump behind the code for the CASE labels */
|
||||||
g_jump (lcase = GetLocalLabel ());
|
g_jump (lcase = GetLocalLabel ());
|
||||||
lcount = 0;
|
|
||||||
while (CurTok.Tok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
if (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
|
if (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
|
||||||
if (lcount >= CASE_MAX) {
|
|
||||||
Fatal ("Too many case labels");
|
|
||||||
}
|
|
||||||
label = GetLocalLabel ();
|
|
||||||
do {
|
do {
|
||||||
if (CurTok.Tok == TOK_CASE) {
|
if (CurTok.Tok == TOK_CASE) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -540,18 +532,23 @@ static void TableSwitch (ExprDesc* Expr)
|
|||||||
if (!IsClassInt (lval.Type)) {
|
if (!IsClassInt (lval.Type)) {
|
||||||
Error ("Switch quantity not an integer");
|
Error ("Switch quantity not an integer");
|
||||||
}
|
}
|
||||||
p->sw_const = lval.e_const;
|
P = xmalloc (sizeof (SwitchEntry));
|
||||||
p->sw_lab = label;
|
P->Value = lval.ConstVal;
|
||||||
++p;
|
P->Label = GetLocalLabel ();
|
||||||
++lcount;
|
CollAppend (&SwitchTab, P);
|
||||||
} else {
|
g_defcodelabel (P->Label);
|
||||||
|
} else if (DefaultLabel == 0) {
|
||||||
|
NextToken ();
|
||||||
|
DefaultLabel = GetLocalLabel ();
|
||||||
|
g_defcodelabel (DefaultLabel);
|
||||||
|
} else {
|
||||||
|
/* We already had a default label */
|
||||||
|
Error ("Multiple default labels in one switch");
|
||||||
|
/* Try to recover */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
dlabel = label;
|
|
||||||
HaveDefault = 1;
|
|
||||||
}
|
}
|
||||||
ConsumeColon ();
|
ConsumeColon ();
|
||||||
} while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT);
|
} while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT);
|
||||||
g_defcodelabel (label);
|
|
||||||
HaveBreak = 0;
|
HaveBreak = 0;
|
||||||
}
|
}
|
||||||
if (CurTok.Tok != TOK_RCURLY) {
|
if (CurTok.Tok != TOK_RCURLY) {
|
||||||
@@ -560,7 +557,7 @@ static void TableSwitch (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have any labels */
|
/* Check if we have any labels */
|
||||||
if (lcount == 0 && !HaveDefault) {
|
if (CollCount(&SwitchTab) == 0 && DefaultLabel == 0) {
|
||||||
Warning ("No case labels");
|
Warning ("No case labels");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +566,7 @@ static void TableSwitch (ExprDesc* Expr)
|
|||||||
|
|
||||||
/* If the last statement doesn't have a break or return, add one */
|
/* If the last statement doesn't have a break or return, add one */
|
||||||
if (!HaveBreak) {
|
if (!HaveBreak) {
|
||||||
g_jump (lab);
|
g_jump (ExitLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actual selector code goes here */
|
/* Actual selector code goes here */
|
||||||
@@ -580,24 +577,27 @@ static void TableSwitch (ExprDesc* Expr)
|
|||||||
g_switch (Flags);
|
g_switch (Flags);
|
||||||
|
|
||||||
/* First entry is negative of label count */
|
/* First entry is negative of label count */
|
||||||
g_defdata (CF_INT | CF_CONST, -((int)lcount)-1, 0);
|
g_defdata (CF_INT | CF_CONST, -((int)CollCount(&SwitchTab))-1, 0);
|
||||||
|
|
||||||
/* Create the case selector table */
|
/* Create the case selector table */
|
||||||
p = swtab;
|
for (I = 0; I < CollCount (&SwitchTab); ++I) {
|
||||||
while (lcount) {
|
P = CollAt (&SwitchTab, I);
|
||||||
g_case (Flags, p->sw_lab, p->sw_const); /* Create one label */
|
g_case (Flags, P->Label, P->Value); /* Create one label */
|
||||||
--lcount;
|
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dlabel) {
|
if (DefaultLabel != 0) {
|
||||||
g_jump (dlabel);
|
g_jump (DefaultLabel);
|
||||||
}
|
}
|
||||||
g_defcodelabel (lab);
|
g_defcodelabel (ExitLabel);
|
||||||
DelLoop ();
|
DelLoop ();
|
||||||
|
|
||||||
/* Free the allocated space for the labels */
|
/* Free the allocated space for the labels */
|
||||||
xfree (swtab);
|
for (I = 0; I < CollCount (&SwitchTab); ++I) {
|
||||||
|
xfree (CollAt (&SwitchTab, I));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the collection itself */
|
||||||
|
DoneCollection (&SwitchTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user