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 TODO
Bugs:
* assignment in declarators: int *b = &a;
* #define NORTH 1 ... startnode(NORTH,1,2);
Implement: Implement:
* pointer arithmetic * pointer arithmetic
* NULL pointers and pointer comparison * NULL pointers and pointer comparison

View file

@ -1,5 +1,8 @@
#include "picoc.h" #include "picoc.h"
static int TRUEValue = 1;
static int ZeroValue = 0;
/* initialise a library */ /* initialise a library */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]) 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 */ /* print a string to a stream without using printf/sprintf */
void PrintStr(const char *Str, CharWriter *PutCh) 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 */ /* 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"); debugf("ExpressionStackPushValueByType()\n");
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL); struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL);
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
return ValueLoc;
} }
/* push a value on to the expression stack */ /* push a value on to the expression stack */
@ -427,32 +429,56 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
ExpressionPushFP(Parser, StackTop, ResultFP); ExpressionPushFP(Parser, StackTop, ResultFP);
} }
#endif #endif
#if 0 else if (BottomValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(TopValue))
XXX - finish this
else if ( (TopValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(BottomValue)) ||
(IS_INTEGER_COERCIBLE(TopValue) && BottomValue->Typ->Base == TypePointer) )
{ {
/* pointer infix arithmetic */ /* pointer/integer infix arithmetic */
int TopInt = COERCE_INTEGER(TopValue);
switch (TopOperatorNode->Op) struct PointerValue Pointer;
struct Value *StackValue;
if (Op == TokenEqual || Op == TokenNotEqual)
{ {
case TokenEqual: ResultInt = BottomInt == TopInt; ResultIsInt = TRUE; break; /* comparison to a NULL pointer */
case TokenNotEqual: ResultInt = BottomInt != TopInt; ResultIsInt = TRUE; break; if (TopInt != 0)
case TokenLessThan: ResultInt = BottomInt < TopInt; ResultIsInt = TRUE; break; ProgramFail(Parser, "invalid operation");
case TokenGreaterThan: ResultInt = BottomInt > TopInt; ResultIsInt = TRUE; break;
case TokenLessEqual: ResultInt = BottomInt <= TopInt; ResultIsInt = TRUE; break; if (Op == TokenEqual)
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; ResultIsInt = TRUE; break; ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment == NULL);
case TokenPlus: Result = BottomInt + TopInt; break; else
case TokenMinus: Result = BottomInt - TopInt; break; ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment != NULL);
default: ProgramFail(Parser, "invalid operation"); break; }
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);
} }
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
else else
ExpressionPushPointer(Parser, StackTop, ResultInt); ProgramFail(Parser, "invalid operation");
} }
#endif
else if (Op == TokenAssign) else if (Op == TokenAssign)
{ {
/* assign a non-numeric type */ /* assign a non-numeric type */

View file

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

View file

@ -241,6 +241,7 @@ extern struct ValueType MacroType;
extern struct ValueType *CharPtrType; extern struct ValueType *CharPtrType;
extern struct ValueType *CharArrayType; extern struct ValueType *CharArrayType;
extern char *StrEmpty; extern char *StrEmpty;
extern struct PointerValue NULLPointer;
extern struct LibraryFunction CLibrary[]; extern struct LibraryFunction CLibrary[];
extern struct LibraryFunction PlatformLibrary[]; extern struct LibraryFunction PlatformLibrary[];
@ -322,6 +323,7 @@ void VariableStringLiteralDefine(char *Ident, struct Value *Val);
/* library.c */ /* library.c */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]); void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);
void CLibraryInit();
void PrintInt(int Num, CharWriter *PutCh); void PrintInt(int Num, CharWriter *PutCh);
void PrintStr(const char *Str, CharWriter *PutCh); void PrintStr(const char *Str, CharWriter *PutCh);
void PrintFP(double Num, 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 \ 15_recursion.test \
16_nesting.test \ 16_nesting.test \
17_enum.test \ 17_enum.test \
18_include.test 18_include.test \
19_pointer_arithmetic.test
%.test: %.expect %.c %.test: %.expect %.c
@echo Test: $*... @echo Test: $*...