Fixed the inlined strlen function
git-svn-id: svn://svn.cc65.org/cc65/trunk@1738 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
@@ -87,6 +86,9 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int hie0 (ExprDesc *lval);
|
||||||
|
/* Parse comma operator. */
|
||||||
|
|
||||||
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
|
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
|
||||||
/* Expression parser; func is either hie0 or hie1. */
|
/* Expression parser; func is either hie0 or hie1. */
|
||||||
|
|
||||||
@@ -465,7 +467,7 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr)
|
|||||||
* from this input error.
|
* from this input error.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
memset (Expr, 0, sizeof (*Expr));
|
InitExprDesc (Expr);
|
||||||
if (F (Expr) != 0 || Expr->Flags != E_MCONST) {
|
if (F (Expr) != 0 || Expr->Flags != E_MCONST) {
|
||||||
Error ("Constant expression expected");
|
Error ("Constant expression expected");
|
||||||
/* To avoid any compiler errors, make the expression a valid const */
|
/* To avoid any compiler errors, make the expression a valid const */
|
||||||
@@ -858,7 +860,7 @@ static int primary (ExprDesc* lval)
|
|||||||
*/
|
*/
|
||||||
if (CurTok.Tok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
|
InitExprDesc (lval); /* Remove any attributes */
|
||||||
k = hie0 (lval);
|
k = hie0 (lval);
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
return k;
|
return k;
|
||||||
@@ -915,7 +917,7 @@ static int primary (ExprDesc* lval)
|
|||||||
/* Check for legal symbol types */
|
/* Check for legal symbol types */
|
||||||
if ((Sym->Flags & SC_CONST) == SC_CONST) {
|
if ((Sym->Flags & SC_CONST) == SC_CONST) {
|
||||||
/* Enum or some other numeric constant */
|
/* Enum or some other numeric constant */
|
||||||
lval->Flags = E_MCONST;
|
lval->Flags = E_MCONST | E_TCONST;
|
||||||
lval->ConstVal = Sym->V.ConstVal;
|
lval->ConstVal = Sym->V.ConstVal;
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
||||||
@@ -3003,7 +3005,7 @@ int hie1 (ExprDesc* lval)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int hie0 (ExprDesc *lval)
|
static int hie0 (ExprDesc *lval)
|
||||||
/* Parse comma operator. */
|
/* Parse comma operator. */
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
@@ -3069,7 +3071,7 @@ void expression1 (ExprDesc* lval)
|
|||||||
* the primary register
|
* the primary register
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
memset (lval, 0, sizeof (*lval));
|
InitExprDesc (lval);
|
||||||
exprhs (CF_NONE, expr (hie1, lval), lval);
|
exprhs (CF_NONE, expr (hie1, lval), lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3078,7 +3080,7 @@ void expression1 (ExprDesc* lval)
|
|||||||
void expression (ExprDesc* lval)
|
void expression (ExprDesc* lval)
|
||||||
/* Evaluate an expression and put it into the primary register */
|
/* Evaluate an expression and put it into the primary register */
|
||||||
{
|
{
|
||||||
memset (lval, 0, sizeof (*lval));
|
InitExprDesc (lval);
|
||||||
exprhs (CF_NONE, expr (hie0, lval), lval);
|
exprhs (CF_NONE, expr (hie0, lval), lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3087,7 +3089,7 @@ void expression (ExprDesc* lval)
|
|||||||
void ConstExpr (ExprDesc* lval)
|
void ConstExpr (ExprDesc* lval)
|
||||||
/* Get a constant value */
|
/* Get a constant value */
|
||||||
{
|
{
|
||||||
memset (lval, 0, sizeof (*lval));
|
InitExprDesc (lval);
|
||||||
if (expr (hie1, lval) != 0 || (lval->Flags & E_MCONST) == 0) {
|
if (expr (hie1, lval) != 0 || (lval->Flags & E_MCONST) == 0) {
|
||||||
Error ("Constant expression expected");
|
Error ("Constant expression expected");
|
||||||
/* To avoid any compiler errors, make the expression a valid const */
|
/* To avoid any compiler errors, make the expression a valid const */
|
||||||
@@ -3100,7 +3102,7 @@ void ConstExpr (ExprDesc* lval)
|
|||||||
void ConstIntExpr (ExprDesc* Val)
|
void ConstIntExpr (ExprDesc* Val)
|
||||||
/* Get a constant int value */
|
/* Get a constant int value */
|
||||||
{
|
{
|
||||||
memset (Val, 0, sizeof (*Val));
|
InitExprDesc (Val);
|
||||||
if (expr (hie1, Val) != 0 ||
|
if (expr (hie1, Val) != 0 ||
|
||||||
(Val->Flags & E_MCONST) == 0 ||
|
(Val->Flags & E_MCONST) == 0 ||
|
||||||
!IsClassInt (Val->Type)) {
|
!IsClassInt (Val->Type)) {
|
||||||
@@ -3134,8 +3136,7 @@ void Test (unsigned Label, int Invert)
|
|||||||
ExprDesc lval;
|
ExprDesc lval;
|
||||||
|
|
||||||
/* Evaluate the expression */
|
/* Evaluate the expression */
|
||||||
memset (&lval, 0, sizeof (lval));
|
k = expr (hie0, InitExprDesc (&lval));
|
||||||
k = expr (hie0, &lval);
|
|
||||||
|
|
||||||
/* Check for a boolean expression */
|
/* Check for a boolean expression */
|
||||||
CheckBoolExpr (&lval);
|
CheckBoolExpr (&lval);
|
||||||
|
|||||||
@@ -88,9 +88,6 @@ int hie10 (ExprDesc* lval);
|
|||||||
int hie1 (ExprDesc* lval);
|
int hie1 (ExprDesc* lval);
|
||||||
/* Parse first level of expression hierarchy. */
|
/* Parse first level of expression hierarchy. */
|
||||||
|
|
||||||
int hie0 (ExprDesc* lval);
|
|
||||||
/* Parse comma operator (highest level of expression hierarchy) */
|
|
||||||
|
|
||||||
void DefineData (ExprDesc* lval);
|
void DefineData (ExprDesc* lval);
|
||||||
/* Output a data definition for the given expression */
|
/* Output a data definition for the given expression */
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "inline.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
|
|
||||||
@@ -88,6 +93,16 @@ struct ExprDesc {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE ExprDesc* InitExprDesc (ExprDesc* Expr)
|
||||||
|
/* Initialize an ExprDesc */
|
||||||
|
{
|
||||||
|
return memset (Expr, 0, sizeof (*Expr));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define InitExprDesc(E) memset ((E), 0, sizeof (*(E)))
|
||||||
|
#endif
|
||||||
|
|
||||||
void MakeConstIntExpr (ExprDesc* Expr, long Value);
|
void MakeConstIntExpr (ExprDesc* Expr, long Value);
|
||||||
/* Make Expr a constant integer expression with the given value */
|
/* Make Expr a constant integer expression with the given value */
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "funcdesc.h"
|
#include "funcdesc.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "litpool.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "stdfunc.h"
|
#include "stdfunc.h"
|
||||||
|
|
||||||
@@ -207,42 +208,86 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)),
|
|||||||
ExprDesc* lval attribute ((unused)))
|
ExprDesc* lval attribute ((unused)))
|
||||||
/* Handle the strlen function */
|
/* Handle the strlen function */
|
||||||
{
|
{
|
||||||
ExprDesc pval;
|
static type ParamType[] = { T_PTR, T_SCHAR, T_END };
|
||||||
static type ArgType[] = { T_PTR, T_SCHAR, T_END };
|
|
||||||
|
|
||||||
|
ExprDesc Param;
|
||||||
|
unsigned CodeFlags;
|
||||||
|
unsigned long ParamName;
|
||||||
|
|
||||||
/* Fetch the parameter */
|
/* Fetch the parameter */
|
||||||
int k = hie1 (&pval);
|
int k = hie1 (InitExprDesc (&Param));
|
||||||
|
|
||||||
/* Check if the parameter is a const address */
|
|
||||||
unsigned flags = 0;
|
|
||||||
unsigned pflags = pval.Flags & ~E_MCTYPE;
|
|
||||||
if (pflags == E_MCONST) {
|
|
||||||
/* Constant numeric address */
|
|
||||||
flags |= CF_CONST | CF_ABSOLUTE;
|
|
||||||
} else if (k == 0 && ((pflags & E_MGLOBAL) != 0 || pval.Flags == E_MEOFFS)) {
|
|
||||||
/* Global array with or without offset */
|
|
||||||
flags |= CF_CONST;
|
|
||||||
if (pval.Flags & E_TGLAB) {
|
|
||||||
/* External linkage */
|
|
||||||
flags |= CF_EXTERNAL;
|
|
||||||
} else {
|
|
||||||
flags |= CF_STATIC;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Not const, load parameter into primary */
|
|
||||||
exprhs (CF_NONE, k, &pval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup the argument type string */
|
/* Setup the argument type string */
|
||||||
ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
|
ParamType[1] = GetDefaultChar () | T_QUAL_CONST;
|
||||||
|
|
||||||
/* Convert the parameter type to the type needed, check for mismatches */
|
/* Convert the parameter type to the type needed, check for mismatches */
|
||||||
assignadjust (ArgType, &pval);
|
assignadjust (ParamType, &Param);
|
||||||
|
|
||||||
|
/* Check if the parameter is a constant array of some type, or a numeric
|
||||||
|
* address cast to a pointer.
|
||||||
|
*/
|
||||||
|
CodeFlags = 0;
|
||||||
|
ParamName = Param.Name;
|
||||||
|
if ((IsTypeArray (Param.Type) && (Param.Flags & E_MCONST) != 0) ||
|
||||||
|
(IsTypePtr (Param.Type) && Param.Flags == (E_MCONST | E_TCONST))) {
|
||||||
|
|
||||||
|
/* Check which type of constant it is */
|
||||||
|
switch (Param.Flags & E_MCTYPE) {
|
||||||
|
|
||||||
|
case E_TCONST:
|
||||||
|
/* Numerical address */
|
||||||
|
CodeFlags |= CF_CONST | CF_ABSOLUTE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_TREGISTER:
|
||||||
|
/* Register variable */
|
||||||
|
CodeFlags |= CF_CONST | CF_REGVAR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_TGLAB:
|
||||||
|
/* Global label */
|
||||||
|
CodeFlags |= CF_CONST | CF_EXTERNAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_TLLAB:
|
||||||
|
/* Local symbol */
|
||||||
|
CodeFlags |= CF_CONST | CF_STATIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_TLIT:
|
||||||
|
/* A literal of some kind. If string literals are read only,
|
||||||
|
* we can calculate the length of the string and remove it
|
||||||
|
* from the literal pool. Otherwise we have to calculate the
|
||||||
|
* length at runtime.
|
||||||
|
*/
|
||||||
|
if (!WriteableStrings) {
|
||||||
|
/* String literals are const */
|
||||||
|
ExprDesc Length;
|
||||||
|
MakeConstIntExpr (&Length, strlen (GetLiteral (Param.ConstVal)));
|
||||||
|
ResetLiteralPoolOffs (Param.ConstVal);
|
||||||
|
exprhs (CF_NONE, 0, &Length);
|
||||||
|
goto ExitPoint;
|
||||||
|
} else {
|
||||||
|
CodeFlags |= CF_CONST | CF_STATIC;
|
||||||
|
ParamName = LiteralPoolLabel;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Internal ("Unknown constant type: %04X", Param.Flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Not an array with a constant address. Load parameter into primary */
|
||||||
|
exprhs (CF_NONE, k, &Param);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate the strlen code */
|
/* Generate the strlen code */
|
||||||
g_strlen (flags, pval.Name, pval.ConstVal);
|
g_strlen (CodeFlags, ParamName, Param.ConstVal);
|
||||||
|
|
||||||
|
ExitPoint:
|
||||||
/* We expect the closing brace */
|
/* We expect the closing brace */
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user