Pointer arithmetic and NULL pointer support added

git-svn-id: http://picoc.googlecode.com/svn/trunk@255 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-04-19 11:49:01 +00:00
parent 88d904ada8
commit 096def8f55
8 changed files with 92 additions and 23 deletions

4
TODO
View file

@ -1,5 +1,9 @@
TODO
Bugs:
* assignment in declarators: int *b = &a;
* #define NORTH 1 ... startnode(NORTH,1,2);
Implement:
* pointer arithmetic
* NULL pointers and pointer comparison

View file

@ -1,5 +1,8 @@
#include "picoc.h"
static int TRUEValue = 1;
static int ZeroValue = 0;
/* initialise a library */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[])
{
@ -22,6 +25,15 @@ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct Libr
}
}
/* initialise the C library */
void CLibraryInit()
{
/* define some constants */
VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE);
VariableDefinePlatformVar(NULL, "TRUE", &IntType, (union AnyValue *)&TRUEValue, FALSE);
VariableDefinePlatformVar(NULL, "FALSE", &IntType, (union AnyValue *)&ZeroValue, FALSE);
}
/* print a string to a stream without using printf/sprintf */
void PrintStr(const char *Str, CharWriter *PutCh)
{

View file

@ -150,11 +150,13 @@ void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionSt
}
/* push a blank value on to the expression stack by type */
void ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType)
struct Value *ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType)
{
debugf("ExpressionStackPushValueByType()\n");
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL);
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
return ValueLoc;
}
/* push a value on to the expression stack */
@ -427,32 +429,56 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
ExpressionPushFP(Parser, StackTop, ResultFP);
}
#endif
#if 0
XXX - finish this
else if ( (TopValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(BottomValue)) ||
(IS_INTEGER_COERCIBLE(TopValue) && BottomValue->Typ->Base == TypePointer) )
else if (BottomValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(TopValue))
{
/* pointer infix arithmetic */
/* pointer/integer infix arithmetic */
int TopInt = COERCE_INTEGER(TopValue);
struct PointerValue Pointer;
struct Value *StackValue;
switch (TopOperatorNode->Op)
if (Op == TokenEqual || Op == TokenNotEqual)
{
case TokenEqual: ResultInt = BottomInt == TopInt; ResultIsInt = TRUE; break;
case TokenNotEqual: ResultInt = BottomInt != TopInt; ResultIsInt = TRUE; break;
case TokenLessThan: ResultInt = BottomInt < TopInt; ResultIsInt = TRUE; break;
case TokenGreaterThan: ResultInt = BottomInt > TopInt; ResultIsInt = TRUE; break;
case TokenLessEqual: ResultInt = BottomInt <= TopInt; ResultIsInt = TRUE; break;
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; ResultIsInt = TRUE; break;
case TokenPlus: Result = BottomInt + TopInt; break;
case TokenMinus: Result = BottomInt - TopInt; break;
default: ProgramFail(Parser, "invalid operation"); break;
}
/* comparison to a NULL pointer */
if (TopInt != 0)
ProgramFail(Parser, "invalid operation");
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
if (Op == TokenEqual)
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment == NULL);
else
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment != NULL);
}
else if (Op == TokenPlus || Op == TokenMinus)
{
/* pointer arithmetic */
int Size = TypeSize(BottomValue->Typ->FromType, 0);
Pointer = BottomValue->Val->Pointer;
if (Pointer.Segment == NULL)
ProgramFail(Parser, "invalid use of a NULL pointer");
if (Op == TokenPlus)
Pointer.Offset += TopInt * Size;
else
Pointer.Offset -= TopInt * Size;
/* check pointer bounds */
if (Pointer.Offset < 0 || Pointer.Offset > TypeSizeValue(BottomValue->Val->Pointer.Segment) - Size)
Pointer.Offset = BottomValue->Val->Pointer.Offset;
StackValue = ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ);
StackValue->Val->Pointer = Pointer;
}
else if (Op == TokenAssign && TopInt == 0)
{
/* assign a NULL pointer */
if (!BottomValue->IsLValue)
ProgramFail(Parser, "can't assign to this");
ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ);
}
else
ExpressionPushPointer(Parser, StackTop, ResultInt);
ProgramFail(Parser, "invalid operation");
}
#endif
else if (Op == TokenAssign)
{
/* assign a non-numeric type */

View file

@ -9,6 +9,7 @@ void Initialise()
LexInit();
TypeInit();
LibraryInit(&GlobalTable, "c library", &CLibrary);
CLibraryInit();
PlatformLibraryInit();
LibraryInit(&GlobalTable, "platform library", &PlatformLibrary);
}

View file

@ -241,6 +241,7 @@ extern struct ValueType MacroType;
extern struct ValueType *CharPtrType;
extern struct ValueType *CharArrayType;
extern char *StrEmpty;
extern struct PointerValue NULLPointer;
extern struct LibraryFunction CLibrary[];
extern struct LibraryFunction PlatformLibrary[];
@ -322,6 +323,7 @@ void VariableStringLiteralDefine(char *Ident, struct Value *Val);
/* library.c */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);
void CLibraryInit();
void PrintInt(int Num, CharWriter *PutCh);
void PrintStr(const char *Str, CharWriter *PutCh);
void PrintFP(double Num, CharWriter *PutCh);

View file

@ -0,0 +1,20 @@
int a;
int *b;
int *c;
a = 42;
b = &a;
c = NULL;
printf("%d\n", *b);
if (b == NULL)
printf("b is NULL\n");
else
printf("b is not NULL\n");
if (c == NULL)
printf("c is NULL\n");
else
printf("c is not NULL\n");

View file

@ -0,0 +1,3 @@
42
b is not NULL
c is NULL

View file

@ -16,7 +16,8 @@ TESTS= 00_assignment.test \
15_recursion.test \
16_nesting.test \
17_enum.test \
18_include.test
18_include.test \
19_pointer_arithmetic.test
%.test: %.expect %.c
@echo Test: $*...