diff --git a/expression.c b/expression.c index 78cb586..c287229 100644 --- a/expression.c +++ b/expression.c @@ -191,6 +191,16 @@ void ExpressionStackPushLValue(struct ParseState *Parser, struct ExpressionStack ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); } +void ExpressionStackPushDereference(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *DereferenceValue) +{ + struct Value *DerefVal; + int Offset; + struct ValueType *DerefType; + void *DerefDataLoc = VariableDereferencePointer(Parser, DereferenceValue, &DerefVal, &Offset, &DerefType); + struct Value *ValueLoc = VariableAllocValueFromExistingData(Parser, DerefType, (union AnyValue *)DerefDataLoc, DerefVal->IsLValue, DerefVal); + ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); +} + void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **StackTop, int IntValue) { debugf("ExpressionPushInt()\n"); @@ -239,8 +249,7 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack break; case TokenAsterisk: - VariableCheckPointer(Parser, TopValue); - ExpressionStackPushLValue(Parser, StackTop, TopValue->Val->Pointer.Segment, TopValue->Val->Pointer.Offset); + ExpressionStackPushDereference(Parser, StackTop, TopValue); break; case TokenSizeof: @@ -640,21 +649,19 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac struct Value *ParamVal = (*StackTop)->p.Val; struct Value *StructVal = ParamVal; int StructOffset = 0; + struct ValueType *StructType = ParamVal->Typ; + void *DerefDataLoc = (void *)ParamVal->Val; struct Value *MemberValue; struct Value *Result; + /* if we're doing '->' dereference the struct pointer first */ if (Token == TokenArrow) - { - /* dereference the struct pointer first */ - VariableCheckPointer(Parser, ParamVal); - StructVal = ParamVal->Val->Pointer.Segment; - StructOffset = ParamVal->Val->Pointer.Offset; - } + DerefDataLoc = VariableDereferencePointer(Parser, ParamVal, &StructVal, &StructOffset, &StructType); - if (StructVal->Typ->Base != TypeStruct && StructVal->Typ->Base != TypeUnion) + if (StructType->Base != TypeStruct && StructType->Base != TypeUnion) ProgramFail(Parser, "can't use '%s' on something that's not a struct or union %s : it's a %t", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "", ParamVal->Typ); - if (!TableGet(StructVal->Typ->Members, Ident->Val->Identifier, &MemberValue)) + if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue)) ProgramFail(Parser, "doesn't have a member called '%s'", Ident->Val->Identifier); /* pop the value - assume it'll still be there until we're done */ @@ -662,7 +669,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac *StackTop = (*StackTop)->Next; /* make the result value for this member only */ - Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)StructVal->Val + StructOffset + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom); + Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, DerefDataLoc + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom); ExpressionStackPushValueNode(Parser, StackTop, Result); } } diff --git a/lex.c b/lex.c index 2c44610..6a71331 100644 --- a/lex.c +++ b/lex.c @@ -56,7 +56,6 @@ static struct ReservedWord ReservedWords[] = { "long", TokenLongType, NULL }, { "new", TokenNew, NULL }, { "return", TokenReturn, NULL }, -// { "short", TokenShortType, NULL }, { "signed", TokenSignedType, NULL }, { "sizeof", TokenSizeof, NULL }, { "struct", TokenStructType, NULL }, diff --git a/picoc.h b/picoc.h index 15a07b4..2a4e57c 100644 --- a/picoc.h +++ b/picoc.h @@ -330,7 +330,7 @@ void VariableStackFrameAdd(struct ParseState *Parser, int NumParams); void VariableStackFramePop(struct ParseState *Parser); struct Value *VariableStringLiteralGet(char *Ident); void VariableStringLiteralDefine(char *Ident, struct Value *Val); -void VariableCheckPointer(struct ParseState *Parser, struct Value *PointerValue); +void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType); /* clibrary.c */ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]); diff --git a/tests/21_char_array.c b/tests/21_char_array.c index 4d1d284..c2ff2f2 100644 --- a/tests/21_char_array.c +++ b/tests/21_char_array.c @@ -1,3 +1,6 @@ +int x = 'a'; +char y = x; + char *a = "hello"; printf("%s\n", a); diff --git a/variable.c b/variable.c index a9adf1a..de7a2f7 100644 --- a/variable.c +++ b/variable.c @@ -261,8 +261,8 @@ void VariableStringLiteralDefine(char *Ident, struct Value *Val) TableSet(&StringLiteralTable, Ident, Val); } -/* check a pointer for validity */ -void VariableCheckPointer(struct ParseState *Parser, struct Value *PointerValue) +/* check a pointer for validity and dereference it for use */ +void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType) { struct Value *PointedToValue = PointerValue->Val->Pointer.Segment; @@ -274,5 +274,18 @@ void VariableCheckPointer(struct ParseState *Parser, struct Value *PointerValue) if (PointerValue->Val->Pointer.Offset < 0 || PointerValue->Val->Pointer.Offset > TypeLastAccessibleOffset(PointedToValue)) ProgramFail(Parser, "attempt to access invalid pointer"); + + /* pass back the optional dereferenced pointer, offset and type */ + if (DerefVal != NULL) + { + *DerefVal = PointedToValue; + *DerefOffset = PointerValue->Val->Pointer.Offset; + *DerefType = PointerValue->Typ->FromType; + } + + /* return a pointer to the data */ + if (PointedToValue->Typ->Base == TypeArray) + return PointedToValue->Val->Array.Data + PointerValue->Val->Pointer.Offset; + else + return (void *)PointedToValue->Val + PointerValue->Val->Pointer.Offset; } -