diff --git a/expression.c b/expression.c index 952750e..fa50d35 100644 --- a/expression.c +++ b/expression.c @@ -341,7 +341,7 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack else if (TopValue->Typ->Base == TypePointer) { /* pointer prefix arithmetic */ - int Size = TypeSize(TopValue->Typ->FromType, 0); + int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); int OrigOffset = TopValue->Val->Pointer.Offset; struct Value *StackValue; @@ -400,8 +400,8 @@ void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack else if (TopValue->Typ->Base == TypePointer) { /* pointer postfix arithmetic */ - int Size = TypeSize(TopValue->Typ->FromType, 0); - int OrigOffset = TopValue->Val->Pointer.Offset; + int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); + struct PointerValue OrigPointer = TopValue->Val->Pointer; struct Value *StackValue; if (TopValue->Val->Pointer.Segment == NULL) @@ -410,9 +410,6 @@ void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack if (!TopValue->IsLValue) ProgramFail(Parser, "can't assign to this"); - StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ); - StackValue->Val->Pointer = TopValue->Val->Pointer; - switch (Op) { case TokenIncrement: TopValue->Val->Pointer.Offset += Size; break; @@ -421,8 +418,13 @@ void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack } /* check pointer bounds */ - if (TopValue->Val->Pointer.Offset < 0 || TopValue->Val->Pointer.Offset > TypeLastAccessibleOffset(TopValue->Val->Pointer.Segment)) - TopValue->Val->Pointer.Offset = OrigOffset; + if (TopValue->Val->Pointer.Offset < 0) + TopValue->Val->Pointer.Offset = 0; + else if (TopValue->Val->Pointer.Offset > TypeLastAccessibleOffset(TopValue->Val->Pointer.Segment)) + TopValue->Val->Pointer.Offset = TypeLastAccessibleOffset(TopValue->Val->Pointer.Segment); + + StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ); + StackValue->Val->Pointer = OrigPointer; } else ProgramFail(Parser, "invalid operation"); @@ -461,7 +463,7 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack * /* make the array element result */ // XXX - need to handle char array access - Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)(BottomValue->Val->Array.Data + TypeSize(BottomValue->Typ->FromType, 0) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom); + Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)(BottomValue->Val->Array.Data + TypeSize(BottomValue->Typ->FromType, 0, FALSE) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom); ExpressionStackPushValueNode(Parser, StackTop, Result); } else if (IS_INTEGER_COERCIBLE(TopValue) && IS_INTEGER_COERCIBLE(BottomValue)) @@ -567,7 +569,7 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack * else if (Op == TokenPlus || Op == TokenMinus) { /* pointer arithmetic */ - int Size = TypeSize(BottomValue->Typ->FromType, 0); + int Size = TypeSize(BottomValue->Typ->FromType, 0, TRUE); Pointer = BottomValue->Val->Pointer; if (Pointer.Segment == NULL) diff --git a/picoc.h b/picoc.h index d3d91db..b9e5463 100644 --- a/picoc.h +++ b/picoc.h @@ -311,7 +311,7 @@ int ExpressionParseInt(struct ParseState *Parser); /* type.c */ void TypeInit(); void TypeCleanup(); -int TypeSize(struct ValueType *Typ, int ArraySize); +int TypeSize(struct ValueType *Typ, int ArraySize, int Compact); int TypeSizeValue(struct Value *Val); int TypeStackSizeValue(struct Value *Val); int TypeLastAccessibleOffset(struct Value *Val); diff --git a/type.c b/type.c index 945ae69..763120b 100644 --- a/type.c +++ b/type.c @@ -86,9 +86,9 @@ int TypeLastAccessibleOffset(struct Value *Val) } /* memory used by a variable given its type and array size */ -int TypeSize(struct ValueType *Typ, int ArraySize) +int TypeSize(struct ValueType *Typ, int ArraySize, int Compact) { - if (Typ->Base == TypeChar) + if (Typ->Base == TypeChar && !Compact) return sizeof(int); /* allow some extra room for type extension to int */ else if (Typ->Base != TypeArray) return Typ->Sizeof; diff --git a/variable.c b/variable.c index de7a2f7..d3cafde 100644 --- a/variable.c +++ b/variable.c @@ -101,7 +101,7 @@ struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, /* allocate a value given its type */ struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom) { - int Size = TypeSize(Typ, Typ->ArraySize); + int Size = TypeSize(Typ, Typ->ArraySize, FALSE); struct Value *NewValue = VariableAllocValueAndData(Parser, Size, IsLValue, LValueFrom, FALSE); assert(Size > 0 || Typ == &VoidType); NewValue->Typ = Typ;