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:
parent
88d904ada8
commit
096def8f55
4
TODO
4
TODO
|
@ -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
|
||||||
|
|
12
clibrary.c
12
clibrary.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
70
expression.c
70
expression.c
|
@ -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 */
|
||||||
|
|
1
picoc.c
1
picoc.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
2
picoc.h
2
picoc.h
|
@ -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);
|
||||||
|
|
20
tests/19_pointer_arithmetic.c
Normal file
20
tests/19_pointer_arithmetic.c
Normal 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");
|
||||||
|
|
3
tests/19_pointer_arithmetic.expect
Normal file
3
tests/19_pointer_arithmetic.expect
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
42
|
||||||
|
b is not NULL
|
||||||
|
c is NULL
|
|
@ -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: $*...
|
||||||
|
|
Loading…
Reference in a new issue