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
|
||||
|
||||
Bugs:
|
||||
* assignment in declarators: int *b = &a;
|
||||
* #define NORTH 1 ... startnode(NORTH,1,2);
|
||||
|
||||
Implement:
|
||||
* pointer arithmetic
|
||||
* NULL pointers and pointer comparison
|
||||
|
|
12
clibrary.c
12
clibrary.c
|
@ -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)
|
||||
{
|
||||
|
|
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 */
|
||||
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 */
|
||||
|
||||
switch (TopOperatorNode->Op)
|
||||
/* pointer/integer infix arithmetic */
|
||||
int TopInt = COERCE_INTEGER(TopValue);
|
||||
struct PointerValue Pointer;
|
||||
struct Value *StackValue;
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
if (ResultIsInt)
|
||||
ExpressionPushInt(Parser, StackTop, ResultInt);
|
||||
else
|
||||
ExpressionPushPointer(Parser, StackTop, ResultInt);
|
||||
ProgramFail(Parser, "invalid operation");
|
||||
}
|
||||
#endif
|
||||
else if (Op == TokenAssign)
|
||||
{
|
||||
/* assign a non-numeric type */
|
||||
|
|
1
picoc.c
1
picoc.c
|
@ -9,6 +9,7 @@ void Initialise()
|
|||
LexInit();
|
||||
TypeInit();
|
||||
LibraryInit(&GlobalTable, "c library", &CLibrary);
|
||||
CLibraryInit();
|
||||
PlatformLibraryInit();
|
||||
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 *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);
|
||||
|
|
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 \
|
||||
16_nesting.test \
|
||||
17_enum.test \
|
||||
18_include.test
|
||||
18_include.test \
|
||||
19_pointer_arithmetic.test
|
||||
|
||||
%.test: %.expect %.c
|
||||
@echo Test: $*...
|
||||
|
|
Loading…
Reference in a new issue