respect 80 col mark when it makes sense
This commit is contained in:
parent
e52188dcda
commit
8c18e1d061
|
@ -29,7 +29,8 @@ void LibraryInit(Picoc *pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a library */
|
/* add a library */
|
||||||
void LibraryAdd(Picoc *pc, struct Table *GlobalTable, struct LibraryFunction *FuncList)
|
void LibraryAdd(Picoc *pc, struct Table *GlobalTable,
|
||||||
|
struct LibraryFunction *FuncList)
|
||||||
{
|
{
|
||||||
struct ParseState Parser;
|
struct ParseState Parser;
|
||||||
int Count;
|
int Count;
|
||||||
|
|
|
@ -163,7 +163,8 @@ void StdioFprintfPointer(StdOutStream *Stream, const char *Format, void *Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal do-anything v[s][n]printf() formatting system with output to strings or FILE * */
|
/* internal do-anything v[s][n]printf() formatting system with output
|
||||||
|
to strings or FILE * */
|
||||||
int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
||||||
int StrOutLen, char *Format, struct StdVararg *Args)
|
int StrOutLen, char *Format, struct StdVararg *Args)
|
||||||
{
|
{
|
||||||
|
@ -262,8 +263,10 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
||||||
StdioOutPutc(*FPos, &SOStream);
|
StdioOutPutc(*FPos, &SOStream);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
ThisArg = (struct Value*)((char*)ThisArg +
|
||||||
if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeInt)
|
MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
||||||
|
if (ThisArg->Typ->Base == TypeArray &&
|
||||||
|
ThisArg->Typ->FromType->Base == TypeInt)
|
||||||
*(int *)ThisArg->Val->Pointer = SOStream.CharCount;
|
*(int *)ThisArg->Val->Pointer = SOStream.CharCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -281,7 +284,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
||||||
OneFormatBuf[OneFormatCount] = '\0';
|
OneFormatBuf[OneFormatCount] = '\0';
|
||||||
|
|
||||||
/* print this argument */
|
/* print this argument */
|
||||||
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
ThisArg = (struct Value*)((char*)ThisArg +
|
||||||
|
MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
||||||
if (ShowType == &pc->IntType) {
|
if (ShowType == &pc->IntType) {
|
||||||
/* show a signed integer */
|
/* show a signed integer */
|
||||||
if (IS_NUMERIC_COERCIBLE(ThisArg))
|
if (IS_NUMERIC_COERCIBLE(ThisArg))
|
||||||
|
@ -300,7 +304,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
||||||
if (ThisArg->Typ->Base == TypePointer)
|
if (ThisArg->Typ->Base == TypePointer)
|
||||||
StdioFprintfPointer(&SOStream, OneFormatBuf,
|
StdioFprintfPointer(&SOStream, OneFormatBuf,
|
||||||
ThisArg->Val->Pointer);
|
ThisArg->Val->Pointer);
|
||||||
else if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeChar)
|
else if (ThisArg->Typ->Base == TypeArray &&
|
||||||
|
ThisArg->Typ->FromType->Base == TypeChar)
|
||||||
StdioFprintfPointer(&SOStream, OneFormatBuf,
|
StdioFprintfPointer(&SOStream, OneFormatBuf,
|
||||||
&ThisArg->Val->ArrayMem[0]);
|
&ThisArg->Val->ArrayMem[0]);
|
||||||
else
|
else
|
||||||
|
@ -333,7 +338,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
|
||||||
return SOStream.CharCount;
|
return SOStream.CharCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal do-anything v[s][n]scanf() formatting system with input from strings or FILE * */
|
/* internal do-anything v[s][n]scanf() formatting system with input
|
||||||
|
from strings or FILE * */
|
||||||
int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn,
|
int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn,
|
||||||
char *Format, struct StdVararg *Args)
|
char *Format, struct StdVararg *Args)
|
||||||
{
|
{
|
||||||
|
@ -346,7 +352,8 @@ int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn,
|
||||||
MAX_SCANF_ARGS);
|
MAX_SCANF_ARGS);
|
||||||
|
|
||||||
for (ArgCount = 0; ArgCount < Args->NumArgs; ArgCount++) {
|
for (ArgCount = 0; ArgCount < Args->NumArgs; ArgCount++) {
|
||||||
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
ThisArg = (struct Value*)((char*)ThisArg +
|
||||||
|
MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
|
||||||
|
|
||||||
if (ThisArg->Typ->Base == TypePointer)
|
if (ThisArg->Typ->Base == TypePointer)
|
||||||
ScanfArg[ArgCount] = ThisArg->Val->Pointer;
|
ScanfArg[ArgCount] = ThisArg->Val->Pointer;
|
||||||
|
@ -478,25 +485,29 @@ void StdioFflush(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
|
ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
|
ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer, Param[1]->Val->Pointer);
|
ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer,
|
||||||
|
Param[1]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
|
ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -630,7 +641,8 @@ void StdioSnprintf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
PrintfArgs.Param = Param+2;
|
PrintfArgs.Param = Param+2;
|
||||||
PrintfArgs.NumArgs = NumArgs-3;
|
PrintfArgs.NumArgs = NumArgs-3;
|
||||||
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
||||||
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, &PrintfArgs);
|
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer,
|
||||||
|
&PrintfArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -670,14 +682,16 @@ void StdioVsprintf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
||||||
Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, Param[2]->Val->Pointer);
|
Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer,
|
||||||
|
Param[2]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
|
||||||
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer);
|
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer,
|
||||||
|
Param[3]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue,
|
void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -766,7 +780,8 @@ void StdioSetupFunc(Picoc *pc)
|
||||||
struct ValueType *StructFileType;
|
struct ValueType *StructFileType;
|
||||||
struct ValueType *FilePtrType;
|
struct ValueType *FilePtrType;
|
||||||
|
|
||||||
/* make a "struct __FILEStruct" which is the same size as a native FILE structure */
|
/* make a "struct __FILEStruct" which is the same size as a
|
||||||
|
native FILE structure */
|
||||||
StructFileType = TypeCreateOpaqueStruct(pc, NULL,
|
StructFileType = TypeCreateOpaqueStruct(pc, NULL,
|
||||||
TableStrRegister(pc, "__FILEStruct"), sizeof(FILE));
|
TableStrRegister(pc, "__FILEStruct"), sizeof(FILE));
|
||||||
|
|
||||||
|
@ -774,7 +789,8 @@ void StdioSetupFunc(Picoc *pc)
|
||||||
FilePtrType = TypeGetMatching(pc, NULL, StructFileType, TypePointer, 0,
|
FilePtrType = TypeGetMatching(pc, NULL, StructFileType, TypePointer, 0,
|
||||||
pc->StrEmpty, true);
|
pc->StrEmpty, true);
|
||||||
|
|
||||||
/* make a "struct __va_listStruct" which is the same size as our struct StdVararg */
|
/* make a "struct __va_listStruct" which is the same size as
|
||||||
|
our struct StdVararg */
|
||||||
TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__va_listStruct"),
|
TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__va_listStruct"),
|
||||||
sizeof(FILE));
|
sizeof(FILE));
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,8 @@ void StdlibBsearch(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Pointer = bsearch(Param[0]->Val->Pointer,
|
ReturnValue->Val->Pointer = bsearch(Param[0]->Val->Pointer,
|
||||||
Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer, (int (*)())Param[4]->Val->Pointer);
|
Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer,
|
||||||
|
(int (*)())Param[4]->Val->Pointer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ static int ZeroValue = 0;
|
||||||
void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = access(Param[0]->Val->Pointer, Param[1]->Val->Integer);
|
ReturnValue->Val->Integer = access(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -33,7 +34,8 @@ void UnistdChroot(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer);
|
ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Integer, Param[2]->Val->Integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -134,7 +136,8 @@ void UnistdFtruncate(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, Param[1]->Val->Integer);
|
ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
@ -254,7 +257,8 @@ void UnistdLchown(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Integer = link(Param[0]->Val->Pointer, Param[1]->Val->Pointer);
|
ReturnValue->Val->Integer = link(Param[0]->Val->Pointer,
|
||||||
|
Param[1]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
|
|
23
debug.c
23
debug.c
|
@ -29,14 +29,18 @@ void DebugCleanup(Picoc *pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search the table for a breakpoint */
|
/* search the table for a breakpoint */
|
||||||
static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser, int *AddAt)
|
static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser,
|
||||||
|
int *AddAt)
|
||||||
{
|
{
|
||||||
struct TableEntry *Entry;
|
struct TableEntry *Entry;
|
||||||
Picoc *pc = Parser->pc;
|
Picoc *pc = Parser->pc;
|
||||||
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
|
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
|
||||||
|
|
||||||
for (Entry = pc->BreakpointHashTable[HashValue]; Entry != NULL; Entry = Entry->Next) {
|
for (Entry = pc->BreakpointHashTable[HashValue];
|
||||||
if (Entry->p.b.FileName == Parser->FileName && Entry->p.b.Line == Parser->Line && Entry->p.b.CharacterPos == Parser->CharacterPos)
|
Entry != NULL; Entry = Entry->Next) {
|
||||||
|
if (Entry->p.b.FileName == Parser->FileName &&
|
||||||
|
Entry->p.b.Line == Parser->Line &&
|
||||||
|
Entry->p.b.CharacterPos == Parser->CharacterPos)
|
||||||
return Entry; /* found */
|
return Entry; /* found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +77,12 @@ int DebugClearBreakpoint(struct ParseState *Parser)
|
||||||
Picoc *pc = Parser->pc;
|
Picoc *pc = Parser->pc;
|
||||||
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
|
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
|
||||||
|
|
||||||
for (EntryPtr = &pc->BreakpointHashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
for (EntryPtr = &pc->BreakpointHashTable[HashValue];
|
||||||
|
*EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
||||||
struct TableEntry *DeleteEntry = *EntryPtr;
|
struct TableEntry *DeleteEntry = *EntryPtr;
|
||||||
if (DeleteEntry->p.b.FileName == Parser->FileName && DeleteEntry->p.b.Line == Parser->Line && DeleteEntry->p.b.CharacterPos == Parser->CharacterPos) {
|
if (DeleteEntry->p.b.FileName == Parser->FileName &&
|
||||||
|
DeleteEntry->p.b.Line == Parser->Line &&
|
||||||
|
DeleteEntry->p.b.CharacterPos == Parser->CharacterPos) {
|
||||||
*EntryPtr = DeleteEntry->Next;
|
*EntryPtr = DeleteEntry->Next;
|
||||||
HeapFreeMem(pc, DeleteEntry);
|
HeapFreeMem(pc, DeleteEntry);
|
||||||
pc->BreakpointCount--;
|
pc->BreakpointCount--;
|
||||||
|
@ -87,7 +94,8 @@ int DebugClearBreakpoint(struct ParseState *Parser)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* before we run a statement, check if there's anything we have to do with the debugger here */
|
/* before we run a statement, check if there's anything we have to
|
||||||
|
do with the debugger here */
|
||||||
void DebugCheckStatement(struct ParseState *Parser)
|
void DebugCheckStatement(struct ParseState *Parser)
|
||||||
{
|
{
|
||||||
int DoBreak = false;
|
int DoBreak = false;
|
||||||
|
@ -102,7 +110,8 @@ void DebugCheckStatement(struct ParseState *Parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is this a breakpoint location? */
|
/* is this a breakpoint location? */
|
||||||
if (Parser->pc->BreakpointCount != 0 && DebugTableSearchBreakpoint(Parser, &AddAt) != NULL)
|
if (Parser->pc->BreakpointCount != 0 &&
|
||||||
|
DebugTableSearchBreakpoint(Parser, &AddAt) != NULL)
|
||||||
DoBreak = true;
|
DoBreak = true;
|
||||||
|
|
||||||
/* handle a break */
|
/* handle a break */
|
||||||
|
|
674
expression.c
674
expression.c
|
@ -7,10 +7,14 @@
|
||||||
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
||||||
#define BRACKET_PRECEDENCE (20)
|
#define BRACKET_PRECEDENCE (20)
|
||||||
|
|
||||||
/* If the destination is not float, we can't assign a floating value to it, we need to convert it to integer instead */
|
/* If the destination is not float, we can't assign a floating value to it,
|
||||||
|
we need to convert it to integer instead */
|
||||||
#define ASSIGN_FP_OR_INT(value) \
|
#define ASSIGN_FP_OR_INT(value) \
|
||||||
if (IS_FP(BottomValue)) { ResultFP = ExpressionAssignFP(Parser, BottomValue, value); } \
|
if (IS_FP(BottomValue)) { \
|
||||||
else { ResultInt = ExpressionAssignInt(Parser, BottomValue, (long)(value), false); ResultIsInt = true; } \
|
ResultFP = ExpressionAssignFP(Parser, BottomValue, value); \
|
||||||
|
} else { \
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, BottomValue, (long)(value), false); \
|
||||||
|
ResultIsInt = true; }
|
||||||
|
|
||||||
#define DEEP_PRECEDENCE (BRACKET_PRECEDENCE*1000)
|
#define DEEP_PRECEDENCE (BRACKET_PRECEDENCE*1000)
|
||||||
|
|
||||||
|
@ -42,7 +46,8 @@ struct OpPrecedence
|
||||||
char *Name;
|
char *Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NOTE: the order of this array must correspond exactly to the order of these tokens in enum LexToken */
|
/* NOTE: the order of this array must correspond exactly to the order of
|
||||||
|
these tokens in enum LexToken */
|
||||||
static struct OpPrecedence OperatorPrecedence[] =
|
static struct OpPrecedence OperatorPrecedence[] =
|
||||||
{
|
{
|
||||||
/* TokenNone, */ {0, 0, 0, "none"},
|
/* TokenNone, */ {0, 0, 0, "none"},
|
||||||
|
@ -110,17 +115,39 @@ void ExpressionStackShow(Picoc *pc, struct ExpressionStack *StackTop)
|
||||||
printf("value=");
|
printf("value=");
|
||||||
|
|
||||||
switch (StackTop->Val->Typ->Base) {
|
switch (StackTop->Val->Typ->Base) {
|
||||||
case TypeVoid: printf("void"); break;
|
case TypeVoid:
|
||||||
case TypeInt: printf("%d:int", StackTop->Val->Val->Integer); break;
|
printf("void");
|
||||||
case TypeShort: printf("%d:short", StackTop->Val->Val->ShortInteger); break;
|
break;
|
||||||
case TypeChar: printf("%d:char", StackTop->Val->Val->Character); break;
|
case TypeInt:
|
||||||
case TypeLong: printf("%ld:long", StackTop->Val->Val->LongInteger); break;
|
printf("%d:int", StackTop->Val->Val->Integer);
|
||||||
case TypeUnsignedShort: printf("%d:unsigned short", StackTop->Val->Val->UnsignedShortInteger); break;
|
break;
|
||||||
case TypeUnsignedInt: printf("%d:unsigned int", StackTop->Val->Val->UnsignedInteger); break;
|
case TypeShort:
|
||||||
case TypeUnsignedLong: printf("%ld:unsigned long", StackTop->Val->Val->UnsignedLongInteger); break;
|
printf("%d:short", StackTop->Val->Val->ShortInteger);
|
||||||
case TypeFP: printf("%f:fp", StackTop->Val->Val->FP); break;
|
break;
|
||||||
case TypeFunction: printf("%s:function", StackTop->Val->Val->Identifier); break;
|
case TypeChar:
|
||||||
case TypeMacro: printf("%s:macro", StackTop->Val->Val->Identifier); break;
|
printf("%d:char", StackTop->Val->Val->Character);
|
||||||
|
break;
|
||||||
|
case TypeLong:
|
||||||
|
printf("%ld:long", StackTop->Val->Val->LongInteger);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedShort:
|
||||||
|
printf("%d:unsigned short", StackTop->Val->Val->UnsignedShortInteger);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedInt:
|
||||||
|
printf("%d:unsigned int", StackTop->Val->Val->UnsignedInteger);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedLong:
|
||||||
|
printf("%ld:unsigned long", StackTop->Val->Val->UnsignedLongInteger);
|
||||||
|
break;
|
||||||
|
case TypeFP:
|
||||||
|
printf("%f:fp", StackTop->Val->Val->FP);
|
||||||
|
break;
|
||||||
|
case TypeFunction:
|
||||||
|
printf("%s:function", StackTop->Val->Val->Identifier);
|
||||||
|
break;
|
||||||
|
case TypeMacro:
|
||||||
|
printf("%s:macro", StackTop->Val->Val->Identifier);
|
||||||
|
break;
|
||||||
case TypePointer:
|
case TypePointer:
|
||||||
if (StackTop->Val->Val->Pointer == NULL)
|
if (StackTop->Val->Val->Pointer == NULL)
|
||||||
printf("ptr(NULL)");
|
printf("ptr(NULL)");
|
||||||
|
@ -129,18 +156,32 @@ void ExpressionStackShow(Picoc *pc, struct ExpressionStack *StackTop)
|
||||||
else
|
else
|
||||||
printf("ptr(0x%lx)", (long)StackTop->Val->Val->Pointer);
|
printf("ptr(0x%lx)", (long)StackTop->Val->Val->Pointer);
|
||||||
break;
|
break;
|
||||||
case TypeArray: printf("array"); break;
|
case TypeArray:
|
||||||
case TypeStruct: printf("%s:struct", StackTop->Val->Val->Identifier); break;
|
printf("array");
|
||||||
case TypeUnion: printf("%s:union", StackTop->Val->Val->Identifier); break;
|
break;
|
||||||
case TypeEnum: printf("%s:enum", StackTop->Val->Val->Identifier); break;
|
case TypeStruct:
|
||||||
case Type_Type: PrintType(StackTop->Val->Val->Typ, pc->CStdOut); printf(":type"); break;
|
printf("%s:struct", StackTop->Val->Val->Identifier);
|
||||||
default: printf("unknown"); break;
|
break;
|
||||||
|
case TypeUnion:
|
||||||
|
printf("%s:union", StackTop->Val->Val->Identifier);
|
||||||
|
break;
|
||||||
|
case TypeEnum:
|
||||||
|
printf("%s:enum", StackTop->Val->Val->Identifier);
|
||||||
|
break;
|
||||||
|
case Type_Type:
|
||||||
|
PrintType(StackTop->Val->Val->Typ, pc->CStdOut);
|
||||||
|
printf(":type");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unknown");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
printf("[0x%lx,0x%lx]", (long)StackTop, (long)StackTop->Val);
|
printf("[0x%lx,0x%lx]", (long)StackTop, (long)StackTop->Val);
|
||||||
} else {
|
} else {
|
||||||
/* it's an operator */
|
/* it's an operator */
|
||||||
printf("op='%s' %s %d", OperatorPrecedence[(int)StackTop->Op].Name,
|
printf("op='%s' %s %d", OperatorPrecedence[(int)StackTop->Op].Name,
|
||||||
(StackTop->Order == OrderPrefix) ? "prefix" : ((StackTop->Order == OrderPostfix) ? "postfix" : "infix"),
|
(StackTop->Order == OrderPrefix) ?
|
||||||
|
"prefix" : ((StackTop->Order == OrderPostfix) ? "postfix" : "infix"),
|
||||||
StackTop->Precedence);
|
StackTop->Precedence);
|
||||||
printf("[0x%lx]", (long)StackTop);
|
printf("[0x%lx]", (long)StackTop);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +202,8 @@ int IsTypeToken(struct ParseState * Parser, enum LexToken t,
|
||||||
return 1; /* base type */
|
return 1; /* base type */
|
||||||
|
|
||||||
/* typedef'ed type? */
|
/* typedef'ed type? */
|
||||||
if (t == TokenIdentifier) {/* see TypeParseFront, case TokenIdentifier and ParseTypedef */
|
if (t == TokenIdentifier) {
|
||||||
|
/* see TypeParseFront, case TokenIdentifier and ParseTypedef */
|
||||||
struct Value * VarValue;
|
struct Value * VarValue;
|
||||||
if (VariableDefined(Parser->pc, LexValue->Val->Pointer)) {
|
if (VariableDefined(Parser->pc, LexValue->Val->Pointer)) {
|
||||||
VariableGet(Parser->pc, Parser, LexValue->Val->Pointer, &VarValue);
|
VariableGet(Parser->pc, Parser, LexValue->Val->Pointer, &VarValue);
|
||||||
|
@ -213,16 +255,34 @@ double ExpressionCoerceFP(struct Value *Val)
|
||||||
unsigned UnsignedVal;
|
unsigned UnsignedVal;
|
||||||
|
|
||||||
switch (Val->Typ->Base) {
|
switch (Val->Typ->Base) {
|
||||||
case TypeInt: IntVal = Val->Val->Integer; return (double)IntVal;
|
case TypeInt:
|
||||||
case TypeChar: IntVal = Val->Val->Character; return (double)IntVal;
|
IntVal = Val->Val->Integer;
|
||||||
case TypeShort: IntVal = Val->Val->ShortInteger; return (double)IntVal;
|
return (double)IntVal;
|
||||||
case TypeLong: IntVal = Val->Val->LongInteger; return (double)IntVal;
|
case TypeChar:
|
||||||
case TypeUnsignedInt: UnsignedVal = Val->Val->UnsignedInteger; return (double)UnsignedVal;
|
IntVal = Val->Val->Character;
|
||||||
case TypeUnsignedShort: UnsignedVal = Val->Val->UnsignedShortInteger; return (double)UnsignedVal;
|
return (double)IntVal;
|
||||||
case TypeUnsignedLong: UnsignedVal = Val->Val->UnsignedLongInteger; return (double)UnsignedVal;
|
case TypeShort:
|
||||||
case TypeUnsignedChar: UnsignedVal = Val->Val->UnsignedCharacter; return (double)UnsignedVal;
|
IntVal = Val->Val->ShortInteger;
|
||||||
case TypeFP: return Val->Val->FP;
|
return (double)IntVal;
|
||||||
default: return 0.0;
|
case TypeLong:
|
||||||
|
IntVal = Val->Val->LongInteger;
|
||||||
|
return (double)IntVal;
|
||||||
|
case TypeUnsignedInt:
|
||||||
|
UnsignedVal = Val->Val->UnsignedInteger;
|
||||||
|
return (double)UnsignedVal;
|
||||||
|
case TypeUnsignedShort:
|
||||||
|
UnsignedVal = Val->Val->UnsignedShortInteger;
|
||||||
|
return (double)UnsignedVal;
|
||||||
|
case TypeUnsignedLong:
|
||||||
|
UnsignedVal = Val->Val->UnsignedLongInteger;
|
||||||
|
return (double)UnsignedVal;
|
||||||
|
case TypeUnsignedChar:
|
||||||
|
UnsignedVal = Val->Val->UnsignedCharacter;
|
||||||
|
return (double)UnsignedVal;
|
||||||
|
case TypeFP:
|
||||||
|
return Val->Val->FP;
|
||||||
|
default:
|
||||||
|
return 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,30 +409,42 @@ void ExpressionPushFP(struct ParseState *Parser,
|
||||||
|
|
||||||
/* assign to a pointer */
|
/* assign to a pointer */
|
||||||
void ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue,
|
void ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue,
|
||||||
struct Value *FromValue, const char *FuncName, int ParamNo, int AllowPointerCoercion)
|
struct Value *FromValue, const char *FuncName, int ParamNo,
|
||||||
|
int AllowPointerCoercion)
|
||||||
{
|
{
|
||||||
struct ValueType *PointedToType = ToValue->Typ->FromType;
|
struct ValueType *PointedToType = ToValue->Typ->FromType;
|
||||||
|
|
||||||
if (FromValue->Typ == ToValue->Typ || FromValue->Typ == Parser->pc->VoidPtrType || (ToValue->Typ == Parser->pc->VoidPtrType && FromValue->Typ->Base == TypePointer))
|
if (FromValue->Typ == ToValue->Typ ||
|
||||||
|
FromValue->Typ == Parser->pc->VoidPtrType ||
|
||||||
|
(ToValue->Typ == Parser->pc->VoidPtrType &&
|
||||||
|
FromValue->Typ->Base == TypePointer))
|
||||||
ToValue->Val->Pointer = FromValue->Val->Pointer; /* plain old pointer assignment */
|
ToValue->Val->Pointer = FromValue->Val->Pointer; /* plain old pointer assignment */
|
||||||
else if (FromValue->Typ->Base == TypeArray && (PointedToType == FromValue->Typ->FromType || ToValue->Typ == Parser->pc->VoidPtrType)) {
|
else if (FromValue->Typ->Base == TypeArray &&
|
||||||
|
(PointedToType == FromValue->Typ->FromType ||
|
||||||
|
ToValue->Typ == Parser->pc->VoidPtrType)) {
|
||||||
/* the form is: blah *x = array of blah */
|
/* the form is: blah *x = array of blah */
|
||||||
ToValue->Val->Pointer = (void *)&FromValue->Val->ArrayMem[0];
|
ToValue->Val->Pointer = (void *)&FromValue->Val->ArrayMem[0];
|
||||||
} else if (FromValue->Typ->Base == TypePointer && FromValue->Typ->FromType->Base == TypeArray &&
|
} else if (FromValue->Typ->Base == TypePointer &&
|
||||||
(PointedToType == FromValue->Typ->FromType->FromType || ToValue->Typ == Parser->pc->VoidPtrType) ) {
|
FromValue->Typ->FromType->Base == TypeArray &&
|
||||||
|
(PointedToType == FromValue->Typ->FromType->FromType ||
|
||||||
|
ToValue->Typ == Parser->pc->VoidPtrType) ) {
|
||||||
/* the form is: blah *x = pointer to array of blah */
|
/* the form is: blah *x = pointer to array of blah */
|
||||||
ToValue->Val->Pointer = VariableDereferencePointer(Parser, FromValue, NULL, NULL, NULL, NULL);
|
ToValue->Val->Pointer = VariableDereferencePointer(Parser, FromValue,
|
||||||
} else if (IS_NUMERIC_COERCIBLE(FromValue) && ExpressionCoerceInteger(FromValue) == 0) {
|
NULL, NULL, NULL, NULL);
|
||||||
|
} else if (IS_NUMERIC_COERCIBLE(FromValue) &&
|
||||||
|
ExpressionCoerceInteger(FromValue) == 0) {
|
||||||
/* null pointer assignment */
|
/* null pointer assignment */
|
||||||
ToValue->Val->Pointer = NULL;
|
ToValue->Val->Pointer = NULL;
|
||||||
} else if (AllowPointerCoercion && IS_NUMERIC_COERCIBLE(FromValue)) {
|
} else if (AllowPointerCoercion && IS_NUMERIC_COERCIBLE(FromValue)) {
|
||||||
/* assign integer to native pointer */
|
/* assign integer to native pointer */
|
||||||
ToValue->Val->Pointer = (void *)(unsigned long)ExpressionCoerceUnsignedInteger(FromValue);
|
ToValue->Val->Pointer =
|
||||||
|
(void*)(unsigned long)ExpressionCoerceUnsignedInteger(FromValue);
|
||||||
} else if (AllowPointerCoercion && FromValue->Typ->Base == TypePointer) {
|
} else if (AllowPointerCoercion && FromValue->Typ->Base == TypePointer) {
|
||||||
/* assign a pointer to a pointer to a different type */
|
/* assign a pointer to a pointer to a different type */
|
||||||
ToValue->Val->Pointer = FromValue->Val->Pointer;
|
ToValue->Val->Pointer = FromValue->Val->Pointer;
|
||||||
} else
|
} else
|
||||||
AssignFail(Parser, "%t from %t", ToValue->Typ, FromValue->Typ, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "%t from %t", ToValue->Typ, FromValue->Typ, 0, 0,
|
||||||
|
FuncName, ParamNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign any kind of value */
|
/* assign any kind of value */
|
||||||
|
@ -383,31 +455,56 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue,
|
||||||
if (!DestValue->IsLValue && !Force)
|
if (!DestValue->IsLValue && !Force)
|
||||||
AssignFail(Parser, "not an lvalue", NULL, NULL, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "not an lvalue", NULL, NULL, 0, 0, FuncName, ParamNo);
|
||||||
|
|
||||||
if (IS_NUMERIC_COERCIBLE(DestValue) && !IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion))
|
if (IS_NUMERIC_COERCIBLE(DestValue) &&
|
||||||
|
!IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion))
|
||||||
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
||||||
|
|
||||||
switch (DestValue->Typ->Base) {
|
switch (DestValue->Typ->Base) {
|
||||||
case TypeInt: DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); break;
|
case TypeInt:
|
||||||
case TypeShort: DestValue->Val->ShortInteger = (short)ExpressionCoerceInteger(SourceValue); break;
|
DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue);
|
||||||
case TypeChar: DestValue->Val->Character = (char)ExpressionCoerceInteger(SourceValue); break;
|
break;
|
||||||
case TypeLong: DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); break;
|
case TypeShort:
|
||||||
case TypeUnsignedInt: DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
|
DestValue->Val->ShortInteger = (short)ExpressionCoerceInteger(SourceValue);
|
||||||
case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)ExpressionCoerceUnsignedInteger(SourceValue); break;
|
break;
|
||||||
case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
|
case TypeChar:
|
||||||
case TypeUnsignedChar: DestValue->Val->UnsignedCharacter = (unsigned char)ExpressionCoerceUnsignedInteger(SourceValue); break;
|
DestValue->Val->Character = (char)ExpressionCoerceInteger(SourceValue);
|
||||||
|
break;
|
||||||
|
case TypeLong:
|
||||||
|
DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedInt:
|
||||||
|
DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedShort:
|
||||||
|
DestValue->Val->UnsignedShortInteger =
|
||||||
|
(unsigned short)ExpressionCoerceUnsignedInteger(SourceValue);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedLong:
|
||||||
|
DestValue->Val->UnsignedLongInteger =
|
||||||
|
ExpressionCoerceUnsignedInteger(SourceValue);
|
||||||
|
break;
|
||||||
|
case TypeUnsignedChar:
|
||||||
|
DestValue->Val->UnsignedCharacter =
|
||||||
|
(unsigned char)ExpressionCoerceUnsignedInteger(SourceValue);
|
||||||
|
break;
|
||||||
case TypeFP:
|
case TypeFP:
|
||||||
if (!IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion))
|
if (!IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion))
|
||||||
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ,
|
||||||
|
0, 0, FuncName, ParamNo);
|
||||||
|
|
||||||
DestValue->Val->FP = ExpressionCoerceFP(SourceValue);
|
DestValue->Val->FP = ExpressionCoerceFP(SourceValue);
|
||||||
break;
|
break;
|
||||||
case TypePointer:
|
case TypePointer:
|
||||||
ExpressionAssignToPointer(Parser, DestValue, SourceValue, FuncName, ParamNo, AllowPointerCoercion);
|
ExpressionAssignToPointer(Parser, DestValue, SourceValue, FuncName,
|
||||||
|
ParamNo, AllowPointerCoercion);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeArray:
|
case TypeArray:
|
||||||
if (SourceValue->Typ->Base == TypeArray && DestValue->Typ->FromType == DestValue->Typ->FromType && DestValue->Typ->ArraySize == 0) {
|
if (SourceValue->Typ->Base == TypeArray &&
|
||||||
/* destination array is unsized - need to resize the destination array to the same size as the source array */
|
DestValue->Typ->FromType == DestValue->Typ->FromType &&
|
||||||
|
DestValue->Typ->ArraySize == 0) {
|
||||||
|
/* destination array is unsized - need to resize the destination
|
||||||
|
array to the same size as the source array */
|
||||||
DestValue->Typ = SourceValue->Typ;
|
DestValue->Typ = SourceValue->Typ;
|
||||||
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue, false));
|
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue, false));
|
||||||
|
|
||||||
|
@ -419,7 +516,9 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* char array = "abcd" */
|
/* char array = "abcd" */
|
||||||
if (DestValue->Typ->FromType->Base == TypeChar && SourceValue->Typ->Base == TypePointer && SourceValue->Typ->FromType->Base == TypeChar) {
|
if (DestValue->Typ->FromType->Base == TypeChar &&
|
||||||
|
SourceValue->Typ->Base == TypePointer &&
|
||||||
|
SourceValue->Typ->FromType->Base == TypeChar) {
|
||||||
if (DestValue->Typ->ArraySize == 0) { /* char x[] = "abcd", x is unsized */
|
if (DestValue->Typ->ArraySize == 0) { /* char x[] = "abcd", x is unsized */
|
||||||
int Size = strlen(SourceValue->Val->Pointer) + 1;
|
int Size = strlen(SourceValue->Val->Pointer) + 1;
|
||||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||||
|
@ -429,21 +528,25 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue,
|
||||||
DestValue->Typ = TypeGetMatching(Parser->pc, Parser,
|
DestValue->Typ = TypeGetMatching(Parser->pc, Parser,
|
||||||
DestValue->Typ->FromType, DestValue->Typ->Base,
|
DestValue->Typ->FromType, DestValue->Typ->Base,
|
||||||
Size, DestValue->Typ->Identifier, true);
|
Size, DestValue->Typ->Identifier, true);
|
||||||
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue, false));
|
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue,
|
||||||
|
false));
|
||||||
}
|
}
|
||||||
/* else, it's char x[10] = "abcd" */
|
/* else, it's char x[10] = "abcd" */
|
||||||
|
|
||||||
#ifdef DEBUG_ARRAY_INITIALIZER
|
#ifdef DEBUG_ARRAY_INITIALIZER
|
||||||
PRINT_SOURCE_POS();
|
PRINT_SOURCE_POS();
|
||||||
fprintf(stderr, "char[%d] from char* (len=%d)\n",
|
fprintf(stderr, "char[%d] from char* (len=%d)\n",
|
||||||
DestValue->Typ->ArraySize, strlen(SourceValue->Val->Pointer));
|
DestValue->Typ->ArraySize,
|
||||||
|
strlen(SourceValue->Val->Pointer));
|
||||||
#endif
|
#endif
|
||||||
memcpy((void *)DestValue->Val, SourceValue->Val->Pointer, TypeSizeValue(DestValue, false));
|
memcpy((void *)DestValue->Val, SourceValue->Val->Pointer,
|
||||||
|
TypeSizeValue(DestValue, false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DestValue->Typ != SourceValue->Typ)
|
if (DestValue->Typ != SourceValue->Typ)
|
||||||
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
|
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ,
|
||||||
|
0, 0, FuncName, ParamNo);
|
||||||
|
|
||||||
if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize)
|
if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize)
|
||||||
AssignFail(Parser, "from an array of size %d to one of size %d",
|
AssignFail(Parser, "from an array of size %d to one of size %d",
|
||||||
|
@ -547,12 +650,24 @@ void ExpressionPrefixOperator(struct ParseState *Parser,
|
||||||
double ResultFP = 0.0;
|
double ResultFP = 0.0;
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenPlus: ResultFP = TopValue->Val->FP; break;
|
case TokenPlus:
|
||||||
case TokenMinus: ResultFP = -TopValue->Val->FP; break;
|
ResultFP = TopValue->Val->FP;
|
||||||
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
|
break;
|
||||||
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
|
case TokenMinus:
|
||||||
case TokenUnaryNot: ResultFP = !TopValue->Val->FP; break;
|
ResultFP = -TopValue->Val->FP;
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
break;
|
||||||
|
case TokenIncrement:
|
||||||
|
ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1);
|
||||||
|
break;
|
||||||
|
case TokenDecrement:
|
||||||
|
ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1);
|
||||||
|
break;
|
||||||
|
case TokenUnaryNot:
|
||||||
|
ResultFP = !TopValue->Val->FP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionPushFP(Parser, StackTop, ResultFP);
|
ExpressionPushFP(Parser, StackTop, ResultFP);
|
||||||
|
@ -561,13 +676,29 @@ void ExpressionPrefixOperator(struct ParseState *Parser,
|
||||||
long ResultInt = 0;
|
long ResultInt = 0;
|
||||||
long TopInt = ExpressionCoerceInteger(TopValue);
|
long TopInt = ExpressionCoerceInteger(TopValue);
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenPlus: ResultInt = TopInt; break;
|
case TokenPlus:
|
||||||
case TokenMinus: ResultInt = -TopInt; break;
|
ResultInt = TopInt;
|
||||||
case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, false); break;
|
break;
|
||||||
case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, false); break;
|
case TokenMinus:
|
||||||
case TokenUnaryNot: ResultInt = !TopInt; break;
|
ResultInt = -TopInt;
|
||||||
case TokenUnaryExor: ResultInt = ~TopInt; break;
|
break;
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
case TokenIncrement:
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, TopValue,
|
||||||
|
TopInt+1, false);
|
||||||
|
break;
|
||||||
|
case TokenDecrement:
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, TopValue,
|
||||||
|
TopInt-1, false);
|
||||||
|
break;
|
||||||
|
case TokenUnaryNot:
|
||||||
|
ResultInt = !TopInt;
|
||||||
|
break;
|
||||||
|
case TokenUnaryExor:
|
||||||
|
ResultInt = ~TopInt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionPushInt(Parser, StackTop, ResultInt);
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
||||||
|
@ -584,13 +715,22 @@ void ExpressionPrefixOperator(struct ParseState *Parser,
|
||||||
ProgramFail(Parser, "can't assign to this");
|
ProgramFail(Parser, "can't assign to this");
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenIncrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); break;
|
case TokenIncrement:
|
||||||
case TokenDecrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); break;
|
TopValue->Val->Pointer =
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
(void*)((char*)TopValue->Val->Pointer+Size);
|
||||||
|
break;
|
||||||
|
case TokenDecrement:
|
||||||
|
TopValue->Val->Pointer =
|
||||||
|
(void*)((char*)TopValue->Val->Pointer-Size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultPtr = TopValue->Val->Pointer;
|
ResultPtr = TopValue->Val->Pointer;
|
||||||
StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ);
|
StackValue = ExpressionStackPushValueByType(Parser, StackTop,
|
||||||
|
TopValue->Typ);
|
||||||
StackValue->Val->Pointer = ResultPtr;
|
StackValue->Val->Pointer = ResultPtr;
|
||||||
} else
|
} else
|
||||||
ProgramFail(Parser, "invalid operation");
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
@ -611,9 +751,15 @@ void ExpressionPostfixOperator(struct ParseState *Parser,
|
||||||
double ResultFP = 0.0;
|
double ResultFP = 0.0;
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
|
case TokenIncrement:
|
||||||
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
|
ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1);
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
break;
|
||||||
|
case TokenDecrement:
|
||||||
|
ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionPushFP(Parser, StackTop, ResultFP);
|
ExpressionPushFP(Parser, StackTop, ResultFP);
|
||||||
|
@ -622,11 +768,21 @@ void ExpressionPostfixOperator(struct ParseState *Parser,
|
||||||
long ResultInt = 0;
|
long ResultInt = 0;
|
||||||
long TopInt = ExpressionCoerceInteger(TopValue);
|
long TopInt = ExpressionCoerceInteger(TopValue);
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, true); break;
|
case TokenIncrement:
|
||||||
case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, true); break;
|
ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, true);
|
||||||
case TokenRightSquareBracket: ProgramFail(Parser, "not supported"); break; /* XXX */
|
break;
|
||||||
case TokenCloseBracket: ProgramFail(Parser, "not supported"); break; /* XXX */
|
case TokenDecrement:
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, true);
|
||||||
|
break;
|
||||||
|
case TokenRightSquareBracket:
|
||||||
|
ProgramFail(Parser, "not supported");
|
||||||
|
break; /* XXX */
|
||||||
|
case TokenCloseBracket:
|
||||||
|
ProgramFail(Parser, "not supported");
|
||||||
|
break; /* XXX */
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionPushInt(Parser, StackTop, ResultInt);
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
||||||
|
@ -643,12 +799,19 @@ void ExpressionPostfixOperator(struct ParseState *Parser,
|
||||||
ProgramFail(Parser, "can't assign to this");
|
ProgramFail(Parser, "can't assign to this");
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenIncrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); break;
|
case TokenIncrement:
|
||||||
case TokenDecrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); break;
|
TopValue->Val->Pointer = (void*)((char*)TopValue->Val->Pointer+Size);
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
break;
|
||||||
|
case TokenDecrement:
|
||||||
|
TopValue->Val->Pointer = (void*)((char*)TopValue->Val->Pointer-Size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ);
|
StackValue = ExpressionStackPushValueByType(Parser, StackTop,
|
||||||
|
TopValue->Typ);
|
||||||
StackValue->Val->Pointer = OrigPointer;
|
StackValue->Val->Pointer = OrigPointer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -696,7 +859,9 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
0, true) * ArrayIndex),
|
0, true) * ArrayIndex),
|
||||||
BottomValue->IsLValue, BottomValue->LValueFrom);
|
BottomValue->IsLValue, BottomValue->LValueFrom);
|
||||||
break;
|
break;
|
||||||
default: ProgramFail(Parser, "this %t is not an array", BottomValue->Typ);
|
default:
|
||||||
|
ProgramFail(Parser, "this %t is not an array", BottomValue->Typ);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
||||||
|
@ -704,32 +869,69 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
ExpressionQuestionMarkOperator(Parser, StackTop, TopValue, BottomValue);
|
ExpressionQuestionMarkOperator(Parser, StackTop, TopValue, BottomValue);
|
||||||
else if (Op == TokenColon)
|
else if (Op == TokenColon)
|
||||||
ExpressionColonOperator(Parser, StackTop, TopValue, BottomValue);
|
ExpressionColonOperator(Parser, StackTop, TopValue, BottomValue);
|
||||||
else if ( (TopValue->Typ == &Parser->pc->FPType && BottomValue->Typ == &Parser->pc->FPType) ||
|
else if ((TopValue->Typ == &Parser->pc->FPType &&
|
||||||
(TopValue->Typ == &Parser->pc->FPType && IS_NUMERIC_COERCIBLE(BottomValue)) ||
|
BottomValue->Typ == &Parser->pc->FPType) ||
|
||||||
(IS_NUMERIC_COERCIBLE(TopValue) && BottomValue->Typ == &Parser->pc->FPType) ) {
|
(TopValue->Typ == &Parser->pc->FPType
|
||||||
|
&& IS_NUMERIC_COERCIBLE(BottomValue)) ||
|
||||||
|
(IS_NUMERIC_COERCIBLE(TopValue)
|
||||||
|
&& BottomValue->Typ == &Parser->pc->FPType) ) {
|
||||||
/* floating point infix arithmetic */
|
/* floating point infix arithmetic */
|
||||||
int ResultIsInt = false;
|
int ResultIsInt = false;
|
||||||
double ResultFP = 0.0;
|
double ResultFP = 0.0;
|
||||||
double TopFP = (TopValue->Typ == &Parser->pc->FPType) ? TopValue->Val->FP : (double)ExpressionCoerceInteger(TopValue);
|
double TopFP = (TopValue->Typ == &Parser->pc->FPType) ?
|
||||||
double BottomFP = (BottomValue->Typ == &Parser->pc->FPType) ? BottomValue->Val->FP : (double)ExpressionCoerceInteger(BottomValue);
|
TopValue->Val->FP : (double)ExpressionCoerceInteger(TopValue);
|
||||||
|
double BottomFP = (BottomValue->Typ == &Parser->pc->FPType) ?
|
||||||
|
BottomValue->Val->FP : (double)ExpressionCoerceInteger(BottomValue);
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenAssign: ASSIGN_FP_OR_INT(TopFP); break;
|
case TokenAssign:
|
||||||
case TokenAddAssign: ASSIGN_FP_OR_INT(BottomFP + TopFP); break;
|
ASSIGN_FP_OR_INT(TopFP);
|
||||||
case TokenSubtractAssign: ASSIGN_FP_OR_INT(BottomFP - TopFP); break;
|
break;
|
||||||
case TokenMultiplyAssign: ASSIGN_FP_OR_INT(BottomFP * TopFP); break;
|
case TokenAddAssign:
|
||||||
case TokenDivideAssign: ASSIGN_FP_OR_INT(BottomFP / TopFP); break;
|
ASSIGN_FP_OR_INT(BottomFP + TopFP);
|
||||||
case TokenEqual: ResultInt = BottomFP == TopFP; ResultIsInt = true; break;
|
break;
|
||||||
case TokenNotEqual: ResultInt = BottomFP != TopFP; ResultIsInt = true; break;
|
case TokenSubtractAssign:
|
||||||
case TokenLessThan: ResultInt = BottomFP < TopFP; ResultIsInt = true; break;
|
ASSIGN_FP_OR_INT(BottomFP - TopFP);
|
||||||
case TokenGreaterThan: ResultInt = BottomFP > TopFP; ResultIsInt = true; break;
|
break;
|
||||||
case TokenLessEqual: ResultInt = BottomFP <= TopFP; ResultIsInt = true; break;
|
case TokenMultiplyAssign:
|
||||||
case TokenGreaterEqual: ResultInt = BottomFP >= TopFP; ResultIsInt = true; break;
|
ASSIGN_FP_OR_INT(BottomFP * TopFP);
|
||||||
case TokenPlus: ResultFP = BottomFP + TopFP; break;
|
break;
|
||||||
case TokenMinus: ResultFP = BottomFP - TopFP; break;
|
case TokenDivideAssign:
|
||||||
case TokenAsterisk: ResultFP = BottomFP * TopFP; break;
|
ASSIGN_FP_OR_INT(BottomFP / TopFP);
|
||||||
case TokenSlash: ResultFP = BottomFP / TopFP; break;
|
break;
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
case TokenEqual:
|
||||||
|
ResultInt = BottomFP == TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenNotEqual:
|
||||||
|
ResultInt = BottomFP != TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenLessThan:
|
||||||
|
ResultInt = BottomFP < TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenGreaterThan:
|
||||||
|
ResultInt = BottomFP > TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenLessEqual:
|
||||||
|
ResultInt = BottomFP <= TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenGreaterEqual:
|
||||||
|
ResultInt = BottomFP >= TopFP; ResultIsInt = true;
|
||||||
|
break;
|
||||||
|
case TokenPlus:
|
||||||
|
ResultFP = BottomFP + TopFP;
|
||||||
|
break;
|
||||||
|
case TokenMinus:
|
||||||
|
ResultFP = BottomFP - TopFP;
|
||||||
|
break;
|
||||||
|
case TokenAsterisk:
|
||||||
|
ResultFP = BottomFP * TopFP;
|
||||||
|
break;
|
||||||
|
case TokenSlash:
|
||||||
|
ResultFP = BottomFP / TopFP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ResultIsInt)
|
if (ResultIsInt)
|
||||||
|
@ -741,40 +943,110 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
long TopInt = ExpressionCoerceInteger(TopValue);
|
long TopInt = ExpressionCoerceInteger(TopValue);
|
||||||
long BottomInt = ExpressionCoerceInteger(BottomValue);
|
long BottomInt = ExpressionCoerceInteger(BottomValue);
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, TopInt, false); break;
|
case TokenAssign:
|
||||||
case TokenAddAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt + TopInt, false); break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue, TopInt, false);
|
||||||
case TokenSubtractAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt - TopInt, false); break;
|
break;
|
||||||
case TokenMultiplyAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt * TopInt, false); break;
|
case TokenAddAssign:
|
||||||
case TokenDivideAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt / TopInt, false); break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt + TopInt, false);
|
||||||
case TokenModulusAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt % TopInt, false); break;
|
break;
|
||||||
case TokenShiftLeftAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt << TopInt, false); break;
|
case TokenSubtractAssign:
|
||||||
case TokenShiftRightAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt >> TopInt, false); break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenArithmeticAndAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt & TopInt, false); break;
|
BottomInt-TopInt, false);
|
||||||
case TokenArithmeticOrAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt | TopInt, false); break;
|
break;
|
||||||
case TokenArithmeticExorAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt ^ TopInt, false); break;
|
case TokenMultiplyAssign:
|
||||||
case TokenLogicalOr: ResultInt = BottomInt || TopInt; break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenLogicalAnd: ResultInt = BottomInt && TopInt; break;
|
BottomInt*TopInt, false);
|
||||||
case TokenArithmeticOr: ResultInt = BottomInt | TopInt; break;
|
break;
|
||||||
case TokenArithmeticExor: ResultInt = BottomInt ^ TopInt; break;
|
case TokenDivideAssign:
|
||||||
case TokenAmpersand: ResultInt = BottomInt & TopInt; break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenEqual: ResultInt = BottomInt == TopInt; break;
|
BottomInt/TopInt, false);
|
||||||
case TokenNotEqual: ResultInt = BottomInt != TopInt; break;
|
break;
|
||||||
case TokenLessThan: ResultInt = BottomInt < TopInt; break;
|
case TokenModulusAssign:
|
||||||
case TokenGreaterThan: ResultInt = BottomInt > TopInt; break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenLessEqual: ResultInt = BottomInt <= TopInt; break;
|
BottomInt%TopInt, false);
|
||||||
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; break;
|
break;
|
||||||
case TokenShiftLeft: ResultInt = BottomInt << TopInt; break;
|
case TokenShiftLeftAssign:
|
||||||
case TokenShiftRight: ResultInt = BottomInt >> TopInt; break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenPlus: ResultInt = BottomInt + TopInt; break;
|
BottomInt<<TopInt, false);
|
||||||
case TokenMinus: ResultInt = BottomInt - TopInt; break;
|
break;
|
||||||
case TokenAsterisk: ResultInt = BottomInt * TopInt; break;
|
case TokenShiftRightAssign:
|
||||||
case TokenSlash: ResultInt = BottomInt / TopInt; break;
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
case TokenModulus: ResultInt = BottomInt % TopInt; break;
|
BottomInt>>TopInt, false);
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
break;
|
||||||
|
case TokenArithmeticAndAssign:
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
|
BottomInt&TopInt, false);
|
||||||
|
break;
|
||||||
|
case TokenArithmeticOrAssign:
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
|
BottomInt|TopInt, false);
|
||||||
|
break;
|
||||||
|
case TokenArithmeticExorAssign:
|
||||||
|
ResultInt = ExpressionAssignInt(Parser, BottomValue,
|
||||||
|
BottomInt^TopInt, false);
|
||||||
|
break;
|
||||||
|
case TokenLogicalOr:
|
||||||
|
ResultInt = BottomInt || TopInt;
|
||||||
|
break;
|
||||||
|
case TokenLogicalAnd:
|
||||||
|
ResultInt = BottomInt && TopInt;
|
||||||
|
break;
|
||||||
|
case TokenArithmeticOr:
|
||||||
|
ResultInt = BottomInt | TopInt;
|
||||||
|
break;
|
||||||
|
case TokenArithmeticExor:
|
||||||
|
ResultInt = BottomInt ^ TopInt;
|
||||||
|
break;
|
||||||
|
case TokenAmpersand:
|
||||||
|
ResultInt = BottomInt & TopInt;
|
||||||
|
break;
|
||||||
|
case TokenEqual:
|
||||||
|
ResultInt = BottomInt == TopInt;
|
||||||
|
break;
|
||||||
|
case TokenNotEqual:
|
||||||
|
ResultInt = BottomInt != TopInt;
|
||||||
|
break;
|
||||||
|
case TokenLessThan:
|
||||||
|
ResultInt = BottomInt < TopInt;
|
||||||
|
break;
|
||||||
|
case TokenGreaterThan:
|
||||||
|
ResultInt = BottomInt > TopInt;
|
||||||
|
break;
|
||||||
|
case TokenLessEqual:
|
||||||
|
ResultInt = BottomInt <= TopInt;
|
||||||
|
break;
|
||||||
|
case TokenGreaterEqual:
|
||||||
|
ResultInt = BottomInt >= TopInt;
|
||||||
|
break;
|
||||||
|
case TokenShiftLeft:
|
||||||
|
ResultInt = BottomInt << TopInt;
|
||||||
|
break;
|
||||||
|
case TokenShiftRight:
|
||||||
|
ResultInt = BottomInt >> TopInt;
|
||||||
|
break;
|
||||||
|
case TokenPlus:
|
||||||
|
ResultInt = BottomInt + TopInt;
|
||||||
|
break;
|
||||||
|
case TokenMinus:
|
||||||
|
ResultInt = BottomInt - TopInt;
|
||||||
|
break;
|
||||||
|
case TokenAsterisk:
|
||||||
|
ResultInt = BottomInt * TopInt;
|
||||||
|
break;
|
||||||
|
case TokenSlash:
|
||||||
|
ResultInt = BottomInt / TopInt;
|
||||||
|
break;
|
||||||
|
case TokenModulus:
|
||||||
|
ResultInt = BottomInt % TopInt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionPushInt(Parser, StackTop, ResultInt);
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
||||||
} else if (BottomValue->Typ->Base == TypePointer && IS_NUMERIC_COERCIBLE(TopValue)) {
|
} else if (BottomValue->Typ->Base == TypePointer &&
|
||||||
|
IS_NUMERIC_COERCIBLE(TopValue)) {
|
||||||
/* pointer/integer infix arithmetic */
|
/* pointer/integer infix arithmetic */
|
||||||
long TopInt = ExpressionCoerceInteger(TopValue);
|
long TopInt = ExpressionCoerceInteger(TopValue);
|
||||||
|
|
||||||
|
@ -784,9 +1056,11 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
ProgramFail(Parser, "invalid operation");
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
|
||||||
if (Op == TokenEqual)
|
if (Op == TokenEqual)
|
||||||
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer == NULL);
|
ExpressionPushInt(Parser, StackTop,
|
||||||
|
BottomValue->Val->Pointer == NULL);
|
||||||
else
|
else
|
||||||
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer != NULL);
|
ExpressionPushInt(Parser, StackTop,
|
||||||
|
BottomValue->Val->Pointer != NULL);
|
||||||
} else if (Op == TokenPlus || Op == TokenMinus) {
|
} else if (Op == TokenPlus || Op == TokenMinus) {
|
||||||
/* pointer arithmetic */
|
/* pointer arithmetic */
|
||||||
int Size = TypeSize(BottomValue->Typ->FromType, 0, true);
|
int Size = TypeSize(BottomValue->Typ->FromType, 0, true);
|
||||||
|
@ -800,7 +1074,8 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
else
|
else
|
||||||
Pointer = (void *)((char *)Pointer - TopInt * Size);
|
Pointer = (void *)((char *)Pointer - TopInt * Size);
|
||||||
|
|
||||||
StackValue = ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ);
|
StackValue = ExpressionStackPushValueByType(Parser, StackTop,
|
||||||
|
BottomValue->Typ);
|
||||||
StackValue->Val->Pointer = Pointer;
|
StackValue->Val->Pointer = Pointer;
|
||||||
} else if (Op == TokenAssign && TopInt == 0) {
|
} else if (Op == TokenAssign && TopInt == 0) {
|
||||||
/* assign a NULL pointer */
|
/* assign a NULL pointer */
|
||||||
|
@ -825,24 +1100,35 @@ void ExpressionInfixOperator(struct ParseState *Parser,
|
||||||
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
|
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
|
||||||
} else
|
} else
|
||||||
ProgramFail(Parser, "invalid operation");
|
ProgramFail(Parser, "invalid operation");
|
||||||
} else if (BottomValue->Typ->Base == TypePointer && TopValue->Typ->Base == TypePointer && Op != TokenAssign) {
|
} else if (BottomValue->Typ->Base == TypePointer &&
|
||||||
|
TopValue->Typ->Base == TypePointer && Op != TokenAssign) {
|
||||||
/* pointer/pointer operations */
|
/* pointer/pointer operations */
|
||||||
char *TopLoc = (char *)TopValue->Val->Pointer;
|
char *TopLoc = (char *)TopValue->Val->Pointer;
|
||||||
char *BottomLoc = (char *)BottomValue->Val->Pointer;
|
char *BottomLoc = (char *)BottomValue->Val->Pointer;
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
case TokenEqual: ExpressionPushInt(Parser, StackTop, BottomLoc == TopLoc); break;
|
case TokenEqual:
|
||||||
case TokenNotEqual: ExpressionPushInt(Parser, StackTop, BottomLoc != TopLoc); break;
|
ExpressionPushInt(Parser, StackTop, BottomLoc == TopLoc);
|
||||||
case TokenMinus: ExpressionPushInt(Parser, StackTop, BottomLoc - TopLoc); break;
|
break;
|
||||||
default: ProgramFail(Parser, "invalid operation"); break;
|
case TokenNotEqual:
|
||||||
|
ExpressionPushInt(Parser, StackTop, BottomLoc != TopLoc);
|
||||||
|
break;
|
||||||
|
case TokenMinus:
|
||||||
|
ExpressionPushInt(Parser, StackTop, BottomLoc - TopLoc);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ProgramFail(Parser, "invalid operation");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (Op == TokenAssign) {
|
} else if (Op == TokenAssign) {
|
||||||
/* assign a non-numeric type */
|
/* assign a non-numeric type */
|
||||||
HeapUnpopStack(Parser->pc, sizeof(struct Value)); /* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */
|
HeapUnpopStack(Parser->pc, sizeof(struct Value));
|
||||||
|
/* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */
|
||||||
ExpressionAssign(Parser, BottomValue, TopValue, false, NULL, 0, false);
|
ExpressionAssign(Parser, BottomValue, TopValue, false, NULL, 0, false);
|
||||||
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
|
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
|
||||||
} else if (Op == TokenCast) {
|
} else if (Op == TokenCast) {
|
||||||
/* cast a value to a different type */ /* XXX - possible bug if the destination type takes more than sizeof(struct Value) + sizeof(struct ValueType *) */
|
/* cast a value to a different type */
|
||||||
|
/* XXX - possible bug if the destination type takes more than sizeof(struct Value) + sizeof(struct ValueType *) */
|
||||||
struct Value *ValueLoc = ExpressionStackPushValueByType(Parser, StackTop,
|
struct Value *ValueLoc = ExpressionStackPushValueByType(Parser, StackTop,
|
||||||
BottomValue->Val->Typ);
|
BottomValue->Val->Typ);
|
||||||
ExpressionAssign(Parser, ValueLoc, TopValue, true, NULL, 0, true);
|
ExpressionAssign(Parser, ValueLoc, TopValue, true, NULL, 0, true);
|
||||||
|
@ -864,7 +1150,8 @@ void ExpressionStackCollapse(struct ParseState *Parser,
|
||||||
printf("ExpressionStackCollapse(%d):\n", Precedence);
|
printf("ExpressionStackCollapse(%d):\n", Precedence);
|
||||||
ExpressionStackShow(Parser->pc, *StackTop);
|
ExpressionStackShow(Parser->pc, *StackTop);
|
||||||
#endif
|
#endif
|
||||||
while (TopStackNode != NULL && TopStackNode->Next != NULL && FoundPrecedence >= Precedence) {
|
while (TopStackNode != NULL && TopStackNode->Next != NULL &&
|
||||||
|
FoundPrecedence >= Precedence) {
|
||||||
/* find the top operator on the stack */
|
/* find the top operator on the stack */
|
||||||
if (TopStackNode->Order == OrderNone)
|
if (TopStackNode->Order == OrderNone)
|
||||||
TopOperatorNode = TopStackNode->Next;
|
TopOperatorNode = TopStackNode->Next;
|
||||||
|
@ -885,14 +1172,17 @@ void ExpressionStackCollapse(struct ParseState *Parser,
|
||||||
TopValue = TopStackNode->Val;
|
TopValue = TopStackNode->Val;
|
||||||
|
|
||||||
/* pop the value and then the prefix operator - assume they'll still be there until we're done */
|
/* pop the value and then the prefix operator - assume they'll still be there until we're done */
|
||||||
HeapPopStack(Parser->pc, NULL, sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
HeapPopStack(Parser->pc, NULL,
|
||||||
HeapPopStack(Parser->pc, TopOperatorNode, sizeof(struct ExpressionStack));
|
sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
||||||
|
HeapPopStack(Parser->pc, TopOperatorNode,
|
||||||
|
sizeof(struct ExpressionStack));
|
||||||
*StackTop = TopOperatorNode->Next;
|
*StackTop = TopOperatorNode->Next;
|
||||||
|
|
||||||
/* do the prefix operation */
|
/* do the prefix operation */
|
||||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */) {
|
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */) {
|
||||||
/* run the operator */
|
/* run the operator */
|
||||||
ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
|
ExpressionPrefixOperator(Parser, StackTop,
|
||||||
|
TopOperatorNode->Op, TopValue);
|
||||||
} else {
|
} else {
|
||||||
/* we're not running it so just return 0 */
|
/* we're not running it so just return 0 */
|
||||||
ExpressionPushInt(Parser, StackTop, 0);
|
ExpressionPushInt(Parser, StackTop, 0);
|
||||||
|
@ -908,13 +1198,15 @@ void ExpressionStackCollapse(struct ParseState *Parser,
|
||||||
|
|
||||||
/* pop the postfix operator and then the value - assume they'll still be there until we're done */
|
/* pop the postfix operator and then the value - assume they'll still be there until we're done */
|
||||||
HeapPopStack(Parser->pc, NULL, sizeof(struct ExpressionStack));
|
HeapPopStack(Parser->pc, NULL, sizeof(struct ExpressionStack));
|
||||||
HeapPopStack(Parser->pc, TopValue, sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
HeapPopStack(Parser->pc, TopValue,
|
||||||
|
sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
||||||
*StackTop = TopStackNode->Next->Next;
|
*StackTop = TopStackNode->Next->Next;
|
||||||
|
|
||||||
/* do the postfix operation */
|
/* do the postfix operation */
|
||||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */) {
|
if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */) {
|
||||||
/* run the operator */
|
/* run the operator */
|
||||||
ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
|
ExpressionPostfixOperator(Parser, StackTop,
|
||||||
|
TopOperatorNode->Op, TopValue);
|
||||||
} else {
|
} else {
|
||||||
/* we're not running it so just return 0 */
|
/* we're not running it so just return 0 */
|
||||||
ExpressionPushInt(Parser, StackTop, 0);
|
ExpressionPushInt(Parser, StackTop, 0);
|
||||||
|
@ -931,15 +1223,19 @@ void ExpressionStackCollapse(struct ParseState *Parser,
|
||||||
BottomValue = TopOperatorNode->Next->Val;
|
BottomValue = TopOperatorNode->Next->Val;
|
||||||
|
|
||||||
/* pop a value, the operator and another value - assume they'll still be there until we're done */
|
/* pop a value, the operator and another value - assume they'll still be there until we're done */
|
||||||
HeapPopStack(Parser->pc, NULL, sizeof(struct ExpressionStack) + sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
HeapPopStack(Parser->pc, NULL,
|
||||||
HeapPopStack(Parser->pc, NULL, sizeof(struct ExpressionStack));
|
sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(TopValue));
|
||||||
HeapPopStack(Parser->pc, BottomValue, sizeof(struct ExpressionStack) + sizeof(struct Value)+TypeStackSizeValue(BottomValue));
|
HeapPopStack(Parser->pc, NULL,
|
||||||
|
sizeof(struct ExpressionStack));
|
||||||
|
HeapPopStack(Parser->pc, BottomValue,
|
||||||
|
sizeof(struct ExpressionStack)+sizeof(struct Value)+TypeStackSizeValue(BottomValue));
|
||||||
*StackTop = TopOperatorNode->Next->Next;
|
*StackTop = TopOperatorNode->Next->Next;
|
||||||
|
|
||||||
/* do the infix operation */
|
/* do the infix operation */
|
||||||
if (Parser->Mode == RunModeRun /* && FoundPrecedence <= *IgnorePrecedence */) {
|
if (Parser->Mode == RunModeRun /* && FoundPrecedence <= *IgnorePrecedence */) {
|
||||||
/* run the operator */
|
/* run the operator */
|
||||||
ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue);
|
ExpressionInfixOperator(Parser, StackTop,
|
||||||
|
TopOperatorNode->Op, BottomValue, TopValue);
|
||||||
} else {
|
} else {
|
||||||
/* we're not running it so just return 0 */
|
/* we're not running it so just return 0 */
|
||||||
ExpressionPushInt(Parser, StackTop, 0);
|
ExpressionPushInt(Parser, StackTop, 0);
|
||||||
|
@ -1024,8 +1320,10 @@ void ExpressionGetStructElement(struct ParseState *Parser,
|
||||||
(Token == TokenDot) ? "." : "->",
|
(Token == TokenDot) ? "." : "->",
|
||||||
(Token == TokenArrow) ? "pointer" : "", ParamVal->Typ);
|
(Token == TokenArrow) ? "pointer" : "", ParamVal->Typ);
|
||||||
|
|
||||||
if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL, NULL))
|
if (!TableGet(StructType->Members, Ident->Val->Identifier,
|
||||||
ProgramFail(Parser, "doesn't have a member called '%s'", Ident->Val->Identifier);
|
&MemberValue, NULL, NULL, NULL))
|
||||||
|
ProgramFail(Parser, "doesn't have a member called '%s'",
|
||||||
|
Ident->Val->Identifier);
|
||||||
|
|
||||||
/* pop the value - assume it'll still be there until we're done */
|
/* pop the value - assume it'll still be there until we're done */
|
||||||
HeapPopStack(Parser->pc, ParamVal,
|
HeapPopStack(Parser->pc, ParamVal,
|
||||||
|
@ -1078,7 +1376,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
if (Token == TokenOpenBracket) {
|
if (Token == TokenOpenBracket) {
|
||||||
/* it's either a new bracket level or a cast */
|
/* it's either a new bracket level or a cast */
|
||||||
enum LexToken BracketToken = LexGetToken(Parser, &LexValue, false);
|
enum LexToken BracketToken = LexGetToken(Parser, &LexValue, false);
|
||||||
if (IsTypeToken(Parser, BracketToken, LexValue) && (StackTop == NULL || StackTop->Op != TokenSizeof)) {
|
if (IsTypeToken(Parser, BracketToken, LexValue) &&
|
||||||
|
(StackTop == NULL || StackTop->Op != TokenSizeof)) {
|
||||||
/* it's a cast - get the new type */
|
/* it's a cast - get the new type */
|
||||||
struct ValueType *CastType;
|
struct ValueType *CastType;
|
||||||
char *CastIdentifier;
|
char *CastIdentifier;
|
||||||
|
@ -1089,9 +1388,11 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
ProgramFail(Parser, "brackets not closed");
|
ProgramFail(Parser, "brackets not closed");
|
||||||
|
|
||||||
/* scan and collapse the stack to the precedence of this infix cast operator, then push */
|
/* scan and collapse the stack to the precedence of this infix cast operator, then push */
|
||||||
Precedence = BracketPrecedence + OperatorPrecedence[(int)TokenCast].PrefixPrecedence;
|
Precedence = BracketPrecedence +
|
||||||
|
OperatorPrecedence[(int)TokenCast].PrefixPrecedence;
|
||||||
|
|
||||||
ExpressionStackCollapse(Parser, &StackTop, Precedence+1, &IgnorePrecedence);
|
ExpressionStackCollapse(Parser, &StackTop, Precedence+1,
|
||||||
|
&IgnorePrecedence);
|
||||||
CastTypeValue = VariableAllocValueFromType(Parser->pc,
|
CastTypeValue = VariableAllocValueFromType(Parser->pc,
|
||||||
Parser, &Parser->pc->TypeType, false, NULL, false);
|
Parser, &Parser->pc->TypeType, false, NULL, false);
|
||||||
CastTypeValue->Val->Typ = CastType;
|
CastTypeValue->Val->Typ = CastType;
|
||||||
|
@ -1109,10 +1410,13 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
int NextToken = LexGetToken(Parser, NULL, false);
|
int NextToken = LexGetToken(Parser, NULL, false);
|
||||||
int TempPrecedenceBoost = 0;
|
int TempPrecedenceBoost = 0;
|
||||||
if (NextToken > TokenComma && NextToken < TokenOpenBracket) {
|
if (NextToken > TokenComma && NextToken < TokenOpenBracket) {
|
||||||
int NextPrecedence = OperatorPrecedence[(int)NextToken].PrefixPrecedence;
|
int NextPrecedence =
|
||||||
|
OperatorPrecedence[(int)NextToken].PrefixPrecedence;
|
||||||
|
|
||||||
/* two prefix operators with equal precedence? make sure the innermost one runs first */
|
/* two prefix operators with equal precedence? make
|
||||||
/* XXX - probably not correct, but can't find a test that fails at this */
|
sure the innermost one runs first */
|
||||||
|
/* XXX - probably not correct, but can't find a
|
||||||
|
test that fails at this */
|
||||||
if (LocalPrecedence == NextPrecedence)
|
if (LocalPrecedence == NextPrecedence)
|
||||||
TempPrecedenceBoost = -1;
|
TempPrecedenceBoost = -1;
|
||||||
}
|
}
|
||||||
|
@ -1141,7 +1445,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* scan and collapse the stack to the precedence of this operator, then push */
|
/* scan and collapse the stack to the precedence of this operator, then push */
|
||||||
Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].PostfixPrecedence;
|
Precedence = BracketPrecedence +
|
||||||
|
OperatorPrecedence[(int)Token].PostfixPrecedence;
|
||||||
ExpressionStackCollapse(Parser, &StackTop, Precedence,
|
ExpressionStackCollapse(Parser, &StackTop, Precedence,
|
||||||
&IgnorePrecedence);
|
&IgnorePrecedence);
|
||||||
ExpressionStackPushOperator(Parser, &StackTop,
|
ExpressionStackPushOperator(Parser, &StackTop,
|
||||||
|
@ -1150,7 +1455,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
}
|
}
|
||||||
} else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0) {
|
} else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0) {
|
||||||
/* scan and collapse the stack, then push */
|
/* scan and collapse the stack, then push */
|
||||||
Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].InfixPrecedence;
|
Precedence = BracketPrecedence +
|
||||||
|
OperatorPrecedence[(int)Token].InfixPrecedence;
|
||||||
|
|
||||||
/* for right to left order, only go down to the next higher precedence so we evaluate it in reverse order */
|
/* for right to left order, only go down to the next higher precedence so we evaluate it in reverse order */
|
||||||
/* for left to right order, collapse down to this precedence so we evaluate it in forward order */
|
/* for left to right order, collapse down to this precedence so we evaluate it in forward order */
|
||||||
|
@ -1166,9 +1472,11 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
ExpressionGetStructElement(Parser, &StackTop, Token);
|
ExpressionGetStructElement(Parser, &StackTop, Token);
|
||||||
} else {
|
} else {
|
||||||
/* if it's a && or || operator we may not need to evaluate the right hand side of the expression */
|
/* if it's a && or || operator we may not need to evaluate the right hand side of the expression */
|
||||||
if ( (Token == TokenLogicalOr || Token == TokenLogicalAnd) && IS_NUMERIC_COERCIBLE(StackTop->Val)) {
|
if ((Token == TokenLogicalOr || Token == TokenLogicalAnd) &&
|
||||||
|
IS_NUMERIC_COERCIBLE(StackTop->Val)) {
|
||||||
long LHSInt = ExpressionCoerceInteger(StackTop->Val);
|
long LHSInt = ExpressionCoerceInteger(StackTop->Val);
|
||||||
if ( ( (Token == TokenLogicalOr && LHSInt) || (Token == TokenLogicalAnd && !LHSInt) ) &&
|
if (((Token == TokenLogicalOr && LHSInt) ||
|
||||||
|
(Token == TokenLogicalAnd && !LHSInt)) &&
|
||||||
(IgnorePrecedence > Precedence) )
|
(IgnorePrecedence > Precedence) )
|
||||||
IgnorePrecedence = Precedence;
|
IgnorePrecedence = Precedence;
|
||||||
}
|
}
|
||||||
|
@ -1185,7 +1493,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* treat an open square bracket as an infix array index operator followed by an open bracket */
|
/* treat an open square bracket as an infix array index
|
||||||
|
operator followed by an open bracket */
|
||||||
if (Token == TokenLeftSquareBracket) {
|
if (Token == TokenLeftSquareBracket) {
|
||||||
/* boost the bracket operator precedence, then push */
|
/* boost the bracket operator precedence, then push */
|
||||||
BracketPrecedence += BRACKET_PRECEDENCE;
|
BracketPrecedence += BRACKET_PRECEDENCE;
|
||||||
|
@ -1218,7 +1527,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
if (VariableValue->Val->MacroDef.NumParams != 0)
|
if (VariableValue->Val->MacroDef.NumParams != 0)
|
||||||
ProgramFail(&MacroParser, "macro arguments missing");
|
ProgramFail(&MacroParser, "macro arguments missing");
|
||||||
|
|
||||||
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, false) != TokenEndOfFunction)
|
if (!ExpressionParse(&MacroParser, &MacroResult) ||
|
||||||
|
LexGetToken(&MacroParser, NULL, false) != TokenEndOfFunction)
|
||||||
ProgramFail(&MacroParser, "expression expected");
|
ProgramFail(&MacroParser, "expression expected");
|
||||||
|
|
||||||
ExpressionStackPushValueNode(Parser, &StackTop, MacroResult);
|
ExpressionStackPushValueNode(Parser, &StackTop, MacroResult);
|
||||||
|
@ -1394,12 +1704,15 @@ void ExpressionParseFunctionCall(struct ParseState *Parser,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FuncValue->Typ->Base != TypeFunction)
|
if (FuncValue->Typ->Base != TypeFunction)
|
||||||
ProgramFail(Parser, "%t is not a function - can't call", FuncValue->Typ);
|
ProgramFail(Parser, "%t is not a function - can't call",
|
||||||
|
FuncValue->Typ);
|
||||||
|
|
||||||
ExpressionStackPushValueByType(Parser, StackTop, FuncValue->Val->FuncDef.ReturnType);
|
ExpressionStackPushValueByType(Parser, StackTop,
|
||||||
|
FuncValue->Val->FuncDef.ReturnType);
|
||||||
ReturnValue = (*StackTop)->Val;
|
ReturnValue = (*StackTop)->Val;
|
||||||
HeapPushStackFrame(Parser->pc);
|
HeapPushStackFrame(Parser->pc);
|
||||||
ParamArray = HeapAllocStack(Parser->pc, sizeof(struct Value*)*FuncValue->Val->FuncDef.NumParams);
|
ParamArray = HeapAllocStack(Parser->pc,
|
||||||
|
sizeof(struct Value*)*FuncValue->Val->FuncDef.NumParams);
|
||||||
if (ParamArray == NULL)
|
if (ParamArray == NULL)
|
||||||
ProgramFail(Parser, "(ExpressionParseFunctionCall) out of memory");
|
ProgramFail(Parser, "(ExpressionParseFunctionCall) out of memory");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1473,7 +1786,8 @@ void ExpressionParseFunctionCall(struct ParseState *Parser,
|
||||||
ProgramFail(&FuncParser, "function body expected");
|
ProgramFail(&FuncParser, "function body expected");
|
||||||
|
|
||||||
if (RunIt) {
|
if (RunIt) {
|
||||||
if (FuncParser.Mode == RunModeRun && FuncValue->Val->FuncDef.ReturnType != &Parser->pc->VoidType)
|
if (FuncParser.Mode == RunModeRun &&
|
||||||
|
FuncValue->Val->FuncDef.ReturnType != &Parser->pc->VoidType)
|
||||||
ProgramFail(&FuncParser,
|
ProgramFail(&FuncParser,
|
||||||
"no value returned from a function returning %t",
|
"no value returned from a function returning %t",
|
||||||
FuncValue->Val->FuncDef.ReturnType);
|
FuncValue->Val->FuncDef.ReturnType);
|
||||||
|
|
12
heap.c
12
heap.c
|
@ -34,7 +34,8 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
|
||||||
pc->StackFrame = &(pc->HeapMemory)[AlignOffset];
|
pc->StackFrame = &(pc->HeapMemory)[AlignOffset];
|
||||||
pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset];
|
pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset];
|
||||||
*(void **)(pc->StackFrame) = NULL;
|
*(void **)(pc->StackFrame) = NULL;
|
||||||
pc->HeapBottom = &(pc->HeapMemory)[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset];
|
pc->HeapBottom =
|
||||||
|
&(pc->HeapMemory)[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset];
|
||||||
pc->FreeListBig = NULL;
|
pc->FreeListBig = NULL;
|
||||||
for (Count = 0; Count < FREELIST_BUCKETS; Count++)
|
for (Count = 0; Count < FREELIST_BUCKETS; Count++)
|
||||||
pc->FreeListBucket[Count] = NULL;
|
pc->FreeListBucket[Count] = NULL;
|
||||||
|
@ -98,7 +99,8 @@ void HeapPushStackFrame(Picoc *pc)
|
||||||
#endif
|
#endif
|
||||||
*(void **)pc->HeapStackTop = pc->StackFrame;
|
*(void **)pc->HeapStackTop = pc->StackFrame;
|
||||||
pc->StackFrame = pc->HeapStackTop;
|
pc->StackFrame = pc->HeapStackTop;
|
||||||
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE)));
|
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop +
|
||||||
|
MEM_ALIGN(sizeof(ALIGN_TYPE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
||||||
|
@ -108,14 +110,16 @@ int HeapPopStackFrame(Picoc *pc)
|
||||||
pc->HeapStackTop = pc->StackFrame;
|
pc->HeapStackTop = pc->StackFrame;
|
||||||
pc->StackFrame = *(void**)pc->StackFrame;
|
pc->StackFrame = *(void**)pc->StackFrame;
|
||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
printf("Popping stack frame back to 0x%lx\n", (unsigned long)pc->HeapStackTop);
|
printf("Popping stack frame back to 0x%lx\n",
|
||||||
|
(unsigned long)pc->HeapStackTop);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
/* allocate some dynamically allocated memory. memory is cleared.
|
||||||
|
can return NULL if out of memory */
|
||||||
void *HeapAllocMem(Picoc *pc, int Size)
|
void *HeapAllocMem(Picoc *pc, int Size)
|
||||||
{
|
{
|
||||||
return calloc(Size, 1);
|
return calloc(Size, 1);
|
||||||
|
|
113
lex.c
113
lex.c
|
@ -265,7 +265,8 @@ unsigned char LexUnEscapeCharacter(const char **From, const char *End)
|
||||||
(*From) += 2; /* skip escaped end of lines with LF line termination */
|
(*From) += 2; /* skip escaped end of lines with LF line termination */
|
||||||
|
|
||||||
while ( *From != End && **From == '\\' &&
|
while ( *From != End && **From == '\\' &&
|
||||||
&(*From)[1] != End && &(*From)[2] != End && (*From)[1] == '\r' && (*From)[2] == '\n')
|
&(*From)[1] != End &&
|
||||||
|
&(*From)[2] != End && (*From)[1] == '\r' && (*From)[2] == '\n')
|
||||||
(*From) += 3; /* skip escaped end of lines with CR/LF line termination */
|
(*From) += 3; /* skip escaped end of lines with CR/LF line termination */
|
||||||
|
|
||||||
if (*From == End)
|
if (*From == End)
|
||||||
|
@ -279,19 +280,35 @@ unsigned char LexUnEscapeCharacter(const char **From, const char *End)
|
||||||
|
|
||||||
ThisChar = *(*From)++;
|
ThisChar = *(*From)++;
|
||||||
switch (ThisChar) {
|
switch (ThisChar) {
|
||||||
case '\\': return '\\';
|
case '\\':
|
||||||
case '\'': return '\'';
|
return '\\';
|
||||||
case '"': return '"';
|
case '\'':
|
||||||
case 'a': return '\a';
|
return '\'';
|
||||||
case 'b': return '\b';
|
case '"':
|
||||||
case 'f': return '\f';
|
return '"';
|
||||||
case 'n': return '\n';
|
case 'a':
|
||||||
case 'r': return '\r';
|
return '\a';
|
||||||
case 't': return '\t';
|
case 'b':
|
||||||
case 'v': return '\v';
|
return '\b';
|
||||||
case '0': case '1': case '2': case '3': return LexUnEscapeCharacterConstant(From, End, ThisChar, 8);
|
case 'f':
|
||||||
case 'x': return LexUnEscapeCharacterConstant(From, End, '0', 16);
|
return '\f';
|
||||||
default: return ThisChar;
|
case 'n':
|
||||||
|
return '\n';
|
||||||
|
case 'r':
|
||||||
|
return '\r';
|
||||||
|
case 't':
|
||||||
|
return '\t';
|
||||||
|
case 'v':
|
||||||
|
return '\v';
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
return LexUnEscapeCharacterConstant(From, End, ThisChar, 8);
|
||||||
|
case 'x':
|
||||||
|
return LexUnEscapeCharacterConstant(From, End, '0', 16);
|
||||||
|
default:
|
||||||
|
return ThisChar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -378,7 +395,8 @@ void LexSkipComment(struct LexState *Lexer, char NextChar,
|
||||||
{
|
{
|
||||||
if (NextChar == '*') {
|
if (NextChar == '*') {
|
||||||
/* conventional C comment */
|
/* conventional C comment */
|
||||||
while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) {
|
while (Lexer->Pos != Lexer->End &&
|
||||||
|
(*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) {
|
||||||
if (*Lexer->Pos == '\n')
|
if (*Lexer->Pos == '\n')
|
||||||
Lexer->EmitExtraNewlines++;
|
Lexer->EmitExtraNewlines++;
|
||||||
|
|
||||||
|
@ -404,7 +422,8 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
|
||||||
char NextChar;
|
char NextChar;
|
||||||
enum LexToken GotToken = TokenNone;
|
enum LexToken GotToken = TokenNone;
|
||||||
|
|
||||||
/* handle cases line multi-line comments or string constants which mess up the line count */
|
/* handle cases line multi-line comments or string constants
|
||||||
|
which mess up the line count */
|
||||||
if (Lexer->EmitExtraNewlines > 0) {
|
if (Lexer->EmitExtraNewlines > 0) {
|
||||||
Lexer->EmitExtraNewlines--;
|
Lexer->EmitExtraNewlines--;
|
||||||
return TokenEndOfLine;
|
return TokenEndOfLine;
|
||||||
|
@ -420,7 +439,8 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
|
||||||
Lexer->Mode = LexModeNormal;
|
Lexer->Mode = LexModeNormal;
|
||||||
Lexer->CharacterPos = 0;
|
Lexer->CharacterPos = 0;
|
||||||
return TokenEndOfLine;
|
return TokenEndOfLine;
|
||||||
} else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace)
|
} else if (Lexer->Mode == LexModeHashDefine ||
|
||||||
|
Lexer->Mode == LexModeHashDefineSpace)
|
||||||
Lexer->Mode = LexModeHashDefineSpace;
|
Lexer->Mode = LexModeHashDefineSpace;
|
||||||
else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
|
else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
|
||||||
Lexer->Mode = LexModeNormal;
|
Lexer->Mode = LexModeNormal;
|
||||||
|
@ -487,16 +507,19 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan);
|
NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=',
|
||||||
|
TokenShiftRightAssign, TokenGreaterThan);
|
||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
GotToken = TokenSemicolon;
|
GotToken = TokenSemicolon;
|
||||||
break;
|
break;
|
||||||
case '&':
|
case '&':
|
||||||
NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand);
|
NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd,
|
||||||
|
TokenAmpersand);
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr);
|
NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr,
|
||||||
|
TokenArithmeticOr);
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
GotToken = TokenLeftBrace;
|
GotToken = TokenLeftBrace;
|
||||||
|
@ -552,7 +575,8 @@ int LexTokenSize(enum LexToken Token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* produce tokens from the lexer and return a heap buffer with the result - used for scanning */
|
/* produce tokens from the lexer and return a heap buffer with
|
||||||
|
the result - used for scanning */
|
||||||
void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
||||||
{
|
{
|
||||||
int MemUsed = 0;
|
int MemUsed = 0;
|
||||||
|
@ -674,14 +698,16 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Parser->FileName == pc->StrEmpty && (pc->InteractiveHead == NULL || Token == TokenEOF)) {
|
if (Parser->FileName == pc->StrEmpty &&
|
||||||
|
(pc->InteractiveHead == NULL || Token == TokenEOF)) {
|
||||||
/* we're at the end of an interactive input token list */
|
/* we're at the end of an interactive input token list */
|
||||||
char LineBuffer[LINEBUFFER_MAX];
|
char LineBuffer[LINEBUFFER_MAX];
|
||||||
void *LineTokens;
|
void *LineTokens;
|
||||||
int LineBytes;
|
int LineBytes;
|
||||||
struct TokenLine *LineNode;
|
struct TokenLine *LineNode;
|
||||||
|
|
||||||
if (pc->InteractiveHead == NULL || (unsigned char*)Parser->Pos == &pc->InteractiveTail->Tokens[pc->InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) {
|
if (pc->InteractiveHead == NULL ||
|
||||||
|
(unsigned char*)Parser->Pos == &pc->InteractiveTail->Tokens[pc->InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) {
|
||||||
/* get interactive input */
|
/* get interactive input */
|
||||||
if (pc->LexUseStatementPrompt) {
|
if (pc->LexUseStatementPrompt) {
|
||||||
Prompt = INTERACTIVE_PROMPT_STATEMENT;
|
Prompt = INTERACTIVE_PROMPT_STATEMENT;
|
||||||
|
@ -714,7 +740,9 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value,
|
||||||
/* go to the next token line */
|
/* go to the next token line */
|
||||||
if (Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) {
|
if (Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) {
|
||||||
/* scan for the line */
|
/* scan for the line */
|
||||||
for (pc->InteractiveCurrentLine = pc->InteractiveHead; Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
|
for (pc->InteractiveCurrentLine = pc->InteractiveHead;
|
||||||
|
Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET];
|
||||||
|
pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
|
||||||
assert(pc->InteractiveCurrentLine->Next != NULL);
|
assert(pc->InteractiveCurrentLine->Next != NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,7 +827,8 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot)
|
||||||
/* is the identifier defined? */
|
/* is the identifier defined? */
|
||||||
IsDefined = TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier,
|
IsDefined = TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier,
|
||||||
&SavedValue, NULL, NULL, NULL);
|
&SavedValue, NULL, NULL, NULL);
|
||||||
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ((IsDefined && !IfNot) || (!IsDefined && IfNot))) {
|
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel &&
|
||||||
|
((IsDefined && !IfNot) || (!IsDefined && IfNot))) {
|
||||||
/* #if is active, evaluate to this new level */
|
/* #if is active, evaluate to this new level */
|
||||||
Parser->HashIfEvaluateToLevel++;
|
Parser->HashIfEvaluateToLevel++;
|
||||||
}
|
}
|
||||||
|
@ -833,7 +862,8 @@ void LexHashIf(struct ParseState *Parser)
|
||||||
ProgramFail(Parser, "value expected");
|
ProgramFail(Parser, "value expected");
|
||||||
|
|
||||||
/* is the identifier defined? */
|
/* is the identifier defined? */
|
||||||
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && IdentValue->Val->Character) {
|
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel &&
|
||||||
|
IdentValue->Val->Character) {
|
||||||
/* #if is active, evaluate to this new level */
|
/* #if is active, evaluate to this new level */
|
||||||
Parser->HashIfEvaluateToLevel++;
|
Parser->HashIfEvaluateToLevel++;
|
||||||
}
|
}
|
||||||
|
@ -904,7 +934,8 @@ void LexPrintToken(enum LexToken Token)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* get the next token given a parser state, pre-processing as we go */
|
/* get the next token given a parser state, pre-processing as we go */
|
||||||
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos)
|
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value,
|
||||||
|
int IncPos)
|
||||||
{
|
{
|
||||||
int TryNextToken;
|
int TryNextToken;
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
|
@ -936,7 +967,8 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're going to reject this token, increment the token pointer to the next one */
|
/* if we're going to reject this token, increment the token pointer to the next one */
|
||||||
TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel && Token != TokenEOF) || WasPreProcToken;
|
TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel &&
|
||||||
|
Token != TokenEOF) || WasPreProcToken;
|
||||||
if (!IncPos && TryNextToken)
|
if (!IncPos && TryNextToken)
|
||||||
LexGetRawToken(Parser, NULL, true);
|
LexGetRawToken(Parser, NULL, true);
|
||||||
|
|
||||||
|
@ -963,7 +995,8 @@ void LexToEndOfLine(struct ParseState *Parser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the tokens from StartParser to EndParser into new memory, removing TokenEOFs and terminate with a TokenEndOfFunction */
|
/* copy the tokens from StartParser to EndParser into new memory, removing
|
||||||
|
TokenEOFs and terminate with a TokenEndOfFunction */
|
||||||
void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser)
|
void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser)
|
||||||
{
|
{
|
||||||
int MemSize = 0;
|
int MemSize = 0;
|
||||||
|
@ -981,10 +1014,15 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
|
||||||
memcpy(NewTokens, (void *)StartParser->Pos, MemSize);
|
memcpy(NewTokens, (void *)StartParser->Pos, MemSize);
|
||||||
} else {
|
} else {
|
||||||
/* we're in interactive mode - add up line by line */
|
/* we're in interactive mode - add up line by line */
|
||||||
for (pc->InteractiveCurrentLine = pc->InteractiveHead; pc->InteractiveCurrentLine != NULL && (Pos < &pc->InteractiveCurrentLine->Tokens[0] || Pos >= &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]); pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
|
for (pc->InteractiveCurrentLine = pc->InteractiveHead;
|
||||||
|
pc->InteractiveCurrentLine != NULL &&
|
||||||
|
(Pos < &pc->InteractiveCurrentLine->Tokens[0] ||
|
||||||
|
Pos >= &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]);
|
||||||
|
pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
|
||||||
} /* find the line we just counted */
|
} /* find the line we just counted */
|
||||||
|
|
||||||
if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]) {
|
if (EndParser->Pos >= StartParser->Pos &&
|
||||||
|
EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]) {
|
||||||
/* all on a single line */
|
/* all on a single line */
|
||||||
MemSize = EndParser->Pos - StartParser->Pos;
|
MemSize = EndParser->Pos - StartParser->Pos;
|
||||||
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, true);
|
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, true);
|
||||||
|
@ -993,7 +1031,10 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
|
||||||
/* it's spread across multiple lines */
|
/* it's spread across multiple lines */
|
||||||
MemSize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
|
MemSize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
|
||||||
|
|
||||||
for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next)
|
for (ILine = pc->InteractiveCurrentLine->Next;
|
||||||
|
ILine != NULL &&
|
||||||
|
(EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]);
|
||||||
|
ILine = ILine->Next)
|
||||||
MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET;
|
MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET;
|
||||||
|
|
||||||
assert(ILine != NULL);
|
assert(ILine != NULL);
|
||||||
|
@ -1003,7 +1044,9 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
|
||||||
CopySize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
|
CopySize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
|
||||||
memcpy(NewTokens, Pos, CopySize);
|
memcpy(NewTokens, Pos, CopySize);
|
||||||
NewTokenPos = NewTokens + CopySize;
|
NewTokenPos = NewTokens + CopySize;
|
||||||
for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) {
|
for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL &&
|
||||||
|
(EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]);
|
||||||
|
ILine = ILine->Next) {
|
||||||
memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET);
|
memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET);
|
||||||
NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET;
|
NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET;
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1080,9 @@ void LexInteractiveClear(Picoc *pc, struct ParseState *Parser)
|
||||||
/* indicate that we've completed up to this point in the interactive input and free expired tokens */
|
/* indicate that we've completed up to this point in the interactive input and free expired tokens */
|
||||||
void LexInteractiveCompleted(Picoc *pc, struct ParseState *Parser)
|
void LexInteractiveCompleted(Picoc *pc, struct ParseState *Parser)
|
||||||
{
|
{
|
||||||
while (pc->InteractiveHead != NULL && !(Parser->Pos >= &pc->InteractiveHead->Tokens[0] && Parser->Pos < &pc->InteractiveHead->Tokens[pc->InteractiveHead->NumBytes])) {
|
while (pc->InteractiveHead != NULL &&
|
||||||
|
!(Parser->Pos >= &pc->InteractiveHead->Tokens[0] &&
|
||||||
|
Parser->Pos < &pc->InteractiveHead->Tokens[pc->InteractiveHead->NumBytes])) {
|
||||||
/* this token line is no longer needed - free it */
|
/* this token line is no longer needed - free it */
|
||||||
struct TokenLine *NextLine = pc->InteractiveHead->Next;
|
struct TokenLine *NextLine = pc->InteractiveHead->Next;
|
||||||
|
|
||||||
|
|
34
parse.c
34
parse.c
|
@ -49,7 +49,8 @@ int ParseCountParams(struct ParseState *Parser)
|
||||||
if (Token != TokenCloseBracket && Token != TokenEOF) {
|
if (Token != TokenCloseBracket && Token != TokenEOF) {
|
||||||
/* count the number of parameters */
|
/* count the number of parameters */
|
||||||
ParamCount++;
|
ParamCount++;
|
||||||
while ((Token = LexGetToken(Parser, NULL, true)) != TokenCloseBracket && Token != TokenEOF) {
|
while ((Token = LexGetToken(Parser, NULL, true)) !=
|
||||||
|
TokenCloseBracket && Token != TokenEOF) {
|
||||||
if (Token == TokenComma)
|
if (Token == TokenComma)
|
||||||
ParamCount++;
|
ParamCount++;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +96,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||||
|
|
||||||
for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) {
|
for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) {
|
||||||
/* harvest the parameters into the function definition */
|
/* harvest the parameters into the function definition */
|
||||||
if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, false) == TokenEllipsis) {
|
if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 &&
|
||||||
|
LexGetToken(&ParamParser, NULL, false) == TokenEllipsis) {
|
||||||
/* ellipsis at end */
|
/* ellipsis at end */
|
||||||
FuncValue->Val->FuncDef.NumParams--;
|
FuncValue->Val->FuncDef.NumParams--;
|
||||||
FuncValue->Val->FuncDef.VarArgs = true;
|
FuncValue->Val->FuncDef.VarArgs = true;
|
||||||
|
@ -118,7 +120,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||||
ProgramFail(&ParamParser, "comma expected");
|
ProgramFail(&ParamParser, "comma expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FuncValue->Val->FuncDef.NumParams != 0 && Token != TokenCloseBracket && Token != TokenComma && Token != TokenEllipsis)
|
if (FuncValue->Val->FuncDef.NumParams != 0 && Token != TokenCloseBracket &&
|
||||||
|
Token != TokenComma && Token != TokenEllipsis)
|
||||||
ProgramFail(&ParamParser, "bad parameter");
|
ProgramFail(&ParamParser, "bad parameter");
|
||||||
|
|
||||||
if (strcmp(Identifier, "main") == 0) {
|
if (strcmp(Identifier, "main") == 0) {
|
||||||
|
@ -128,7 +131,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||||
ProgramFail(Parser, "main() should return an int or void");
|
ProgramFail(Parser, "main() should return an int or void");
|
||||||
|
|
||||||
if (FuncValue->Val->FuncDef.NumParams != 0 &&
|
if (FuncValue->Val->FuncDef.NumParams != 0 &&
|
||||||
(FuncValue->Val->FuncDef.NumParams != 2 || FuncValue->Val->FuncDef.ParamType[0] != &pc->IntType) )
|
(FuncValue->Val->FuncDef.NumParams != 2 ||
|
||||||
|
FuncValue->Val->FuncDef.ParamType[0] != &pc->IntType) )
|
||||||
ProgramFail(Parser, "bad parameters to main()");
|
ProgramFail(Parser, "bad parameters to main()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +242,8 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
|
||||||
ElementType = ElementType->FromType;
|
ElementType = ElementType->FromType;
|
||||||
|
|
||||||
/* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */
|
/* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */
|
||||||
if (LexGetToken(Parser, NULL, false) == TokenStringConstant && ElementType->FromType->Base == TypeChar)
|
if (LexGetToken(Parser, NULL, false) == TokenStringConstant &&
|
||||||
|
ElementType->FromType->Base == TypeChar)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ElementSize = TypeSize(ElementType, ElementType->ArraySize, true);
|
ElementSize = TypeSize(ElementType, ElementType->ArraySize, true);
|
||||||
|
@ -320,7 +325,9 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
||||||
TypeParseFront(Parser, &BasicType, &IsStatic);
|
TypeParseFront(Parser, &BasicType, &IsStatic);
|
||||||
do {
|
do {
|
||||||
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
||||||
if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType && Token != TokenEnumType) && Identifier == pc->StrEmpty)
|
if ((Token != TokenVoidType && Token != TokenStructType &&
|
||||||
|
Token != TokenUnionType && Token != TokenEnumType) &&
|
||||||
|
Identifier == pc->StrEmpty)
|
||||||
ProgramFail(Parser, "identifier expected");
|
ProgramFail(Parser, "identifier expected");
|
||||||
|
|
||||||
if (Identifier != pc->StrEmpty) {
|
if (Identifier != pc->StrEmpty) {
|
||||||
|
@ -387,7 +394,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
||||||
|
|
||||||
while (Token == TokenIdentifier) {
|
while (Token == TokenIdentifier) {
|
||||||
/* store a parameter name */
|
/* store a parameter name */
|
||||||
MacroValue->Val->MacroDef.ParamName[ParamCount++] = ParamName->Val->Identifier;
|
MacroValue->Val->MacroDef.ParamName[ParamCount++] =
|
||||||
|
ParamName->Val->Identifier;
|
||||||
|
|
||||||
/* get the trailing comma */
|
/* get the trailing comma */
|
||||||
Token = LexGetToken(Parser, NULL, true);
|
Token = LexGetToken(Parser, NULL, true);
|
||||||
|
@ -411,7 +419,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
||||||
ParserCopy(&MacroValue->Val->MacroDef.Body, Parser);
|
ParserCopy(&MacroValue->Val->MacroDef.Body, Parser);
|
||||||
MacroValue->Typ = &Parser->pc->MacroType;
|
MacroValue->Typ = &Parser->pc->MacroType;
|
||||||
LexToEndOfLine(Parser);
|
LexToEndOfLine(Parser);
|
||||||
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
|
MacroValue->Val->MacroDef.Body.Pos =
|
||||||
|
LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
|
||||||
|
|
||||||
if (!TableSet(Parser->pc, &Parser->pc->GlobalTable, MacroNameStr, MacroValue,
|
if (!TableSet(Parser->pc, &Parser->pc->GlobalTable, MacroNameStr, MacroValue,
|
||||||
(char *)Parser->FileName, Parser->Line, Parser->CharacterPos))
|
(char *)Parser->FileName, Parser->Line, Parser->CharacterPos))
|
||||||
|
@ -595,7 +604,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
if (NextToken == TokenColon) {
|
if (NextToken == TokenColon) {
|
||||||
/* declare the identifier as a goto label */
|
/* declare the identifier as a goto label */
|
||||||
LexGetToken(Parser, NULL, true);
|
LexGetToken(Parser, NULL, true);
|
||||||
if (Parser->Mode == RunModeGoto && LexerValue->Val->Identifier == Parser->SearchGotoLabel)
|
if (Parser->Mode == RunModeGoto &&
|
||||||
|
LexerValue->Val->Identifier == Parser->SearchGotoLabel)
|
||||||
Parser->Mode = RunModeRun;
|
Parser->Mode = RunModeRun;
|
||||||
CheckTrailingSemicolon = false;
|
CheckTrailingSemicolon = false;
|
||||||
break;
|
break;
|
||||||
|
@ -727,7 +737,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
int OldSearchLabel = Parser->SearchLabel;
|
int OldSearchLabel = Parser->SearchLabel;
|
||||||
Parser->Mode = RunModeCaseSearch;
|
Parser->Mode = RunModeCaseSearch;
|
||||||
Parser->SearchLabel = Condition;
|
Parser->SearchLabel = Condition;
|
||||||
ParseBlock(Parser, true, (OldMode != RunModeSkip) && (OldMode != RunModeReturn));
|
ParseBlock(Parser, true, (OldMode != RunModeSkip) &&
|
||||||
|
(OldMode != RunModeReturn));
|
||||||
if (Parser->Mode != RunModeReturn)
|
if (Parser->Mode != RunModeReturn)
|
||||||
Parser->Mode = OldMode;
|
Parser->Mode = OldMode;
|
||||||
Parser->SearchLabel = OldSearchLabel;
|
Parser->SearchLabel = OldSearchLabel;
|
||||||
|
@ -764,7 +775,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
break;
|
break;
|
||||||
case TokenReturn:
|
case TokenReturn:
|
||||||
if (Parser->Mode == RunModeRun) {
|
if (Parser->Mode == RunModeRun) {
|
||||||
if (!Parser->pc->TopStackFrame || Parser->pc->TopStackFrame->ReturnValue->Typ->Base != TypeVoid) {
|
if (!Parser->pc->TopStackFrame ||
|
||||||
|
Parser->pc->TopStackFrame->ReturnValue->Typ->Base != TypeVoid) {
|
||||||
if (!ExpressionParse(Parser, &CValue))
|
if (!ExpressionParse(Parser, &CValue))
|
||||||
ProgramFail(Parser, "value required in return");
|
ProgramFail(Parser, "value required in return");
|
||||||
if (!Parser->pc->TopStackFrame) /* return from top-level program? */
|
if (!Parser->pc->TopStackFrame) /* return from top-level program? */
|
||||||
|
|
25
platform.c
25
platform.c
|
@ -77,20 +77,24 @@ void PicocCallMain(Picoc *pc, int argc, char **argv)
|
||||||
if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) {
|
if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) {
|
||||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||||
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID,
|
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID,
|
||||||
strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), true, true, false, gEnableDebugger);
|
strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), true, true, false,
|
||||||
|
gEnableDebugger);
|
||||||
else
|
else
|
||||||
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID,
|
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID,
|
||||||
strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), true, true, false, gEnableDebugger);
|
strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), true, true, false,
|
||||||
|
gEnableDebugger);
|
||||||
} else {
|
} else {
|
||||||
VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType,
|
VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType,
|
||||||
(union AnyValue *)&pc->PicocExitValue, true);
|
(union AnyValue *)&pc->PicocExitValue, true);
|
||||||
|
|
||||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||||
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT,
|
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT,
|
||||||
strlen(CALL_MAIN_NO_ARGS_RETURN_INT), true, true, false, gEnableDebugger);
|
strlen(CALL_MAIN_NO_ARGS_RETURN_INT), true, true, false,
|
||||||
|
gEnableDebugger);
|
||||||
else
|
else
|
||||||
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_INT,
|
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_INT,
|
||||||
strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), true, true, false, gEnableDebugger);
|
strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), true, true, false,
|
||||||
|
gEnableDebugger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,7 +109,8 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
|
||||||
|
|
||||||
if (SourceText != NULL) {
|
if (SourceText != NULL) {
|
||||||
/* find the source line */
|
/* find the source line */
|
||||||
for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++) {
|
for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' &&
|
||||||
|
LineCount < Line; LinePos++) {
|
||||||
if (*LinePos == '\n')
|
if (*LinePos == '\n')
|
||||||
LineCount++;
|
LineCount++;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +121,8 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
|
||||||
PrintCh('\n', Stream);
|
PrintCh('\n', Stream);
|
||||||
|
|
||||||
/* display the error position */
|
/* display the error position */
|
||||||
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) {
|
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' &&
|
||||||
|
(CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) {
|
||||||
if (*CPos == '\t')
|
if (*CPos == '\t')
|
||||||
PrintCh('\t', Stream);
|
PrintCh('\t', Stream);
|
||||||
else
|
else
|
||||||
|
@ -124,7 +130,9 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* assume we're in interactive mode - try to make the arrow match up with the input text */
|
/* assume we're in interactive mode - try to make the arrow match up with the input text */
|
||||||
for (CCount = 0; CCount < CharacterPos+(int)strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++)
|
for (CCount = 0;
|
||||||
|
CCount < CharacterPos+(int)strlen(INTERACTIVE_PROMPT_STATEMENT);
|
||||||
|
CCount++)
|
||||||
PrintCh(' ', Stream);
|
PrintCh(' ', Stream);
|
||||||
}
|
}
|
||||||
PlatformPrintf(Stream, "^\n%s:%d:%d ", FileName, Line, CharacterPos);
|
PlatformPrintf(Stream, "^\n%s:%d:%d ", FileName, Line, CharacterPos);
|
||||||
|
@ -173,7 +181,8 @@ void AssignFail(struct ParseState *Parser, const char *Format,
|
||||||
PlatformPrintf(Stream, Format, Num1, Num2);
|
PlatformPrintf(Stream, Format, Num1, Num2);
|
||||||
|
|
||||||
if (FuncName != NULL)
|
if (FuncName != NULL)
|
||||||
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName);
|
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo,
|
||||||
|
FuncName);
|
||||||
|
|
||||||
PlatformPrintf(Stream, "\n");
|
PlatformPrintf(Stream, "\n");
|
||||||
PlatformExit(Parser->pc, 1);
|
PlatformExit(Parser->pc, 1);
|
||||||
|
|
15
table.c
15
table.c
|
@ -39,7 +39,8 @@ void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check a hash table entry for a key */
|
/* check a hash table entry for a key */
|
||||||
static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *AddAt)
|
static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key,
|
||||||
|
int *AddAt)
|
||||||
{
|
{
|
||||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||||
struct TableEntry *Entry;
|
struct TableEntry *Entry;
|
||||||
|
@ -62,7 +63,8 @@ int TableSet(Picoc *pc, struct Table *Tbl, char *Key, struct Value *Val,
|
||||||
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
|
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
|
||||||
|
|
||||||
if (FoundEntry == NULL) { /* add it to the table */
|
if (FoundEntry == NULL) { /* add it to the table */
|
||||||
struct TableEntry *NewEntry = VariableAlloc(pc, NULL, sizeof(struct TableEntry), Tbl->OnHeap);
|
struct TableEntry *NewEntry = VariableAlloc(pc, NULL,
|
||||||
|
sizeof(struct TableEntry), Tbl->OnHeap);
|
||||||
NewEntry->DeclFileName = DeclFileName;
|
NewEntry->DeclFileName = DeclFileName;
|
||||||
NewEntry->DeclLine = DeclLine;
|
NewEntry->DeclLine = DeclLine;
|
||||||
NewEntry->DeclColumn = DeclColumn;
|
NewEntry->DeclColumn = DeclColumn;
|
||||||
|
@ -103,7 +105,8 @@ struct Value *TableDelete(Picoc *pc, struct Table *Tbl, const char *Key)
|
||||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||||
struct TableEntry **EntryPtr;
|
struct TableEntry **EntryPtr;
|
||||||
|
|
||||||
for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
for (EntryPtr = &Tbl->HashTable[HashValue];
|
||||||
|
*EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
||||||
if ((*EntryPtr)->p.v.Key == Key) {
|
if ((*EntryPtr)->p.v.Key == Key) {
|
||||||
struct TableEntry *DeleteEntry = *EntryPtr;
|
struct TableEntry *DeleteEntry = *EntryPtr;
|
||||||
struct Value *Val = DeleteEntry->p.v.Val;
|
struct Value *Val = DeleteEntry->p.v.Val;
|
||||||
|
@ -142,7 +145,8 @@ char *TableSetIdentifier(Picoc *pc, struct Table *Tbl, const char *Ident, int Id
|
||||||
if (FoundEntry != NULL)
|
if (FoundEntry != NULL)
|
||||||
return &FoundEntry->p.Key[0];
|
return &FoundEntry->p.Key[0];
|
||||||
else { /* add it to the table - we economise by not allocating the whole structure here */
|
else { /* add it to the table - we economise by not allocating the whole structure here */
|
||||||
struct TableEntry *NewEntry = HeapAllocMem(pc, sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1);
|
struct TableEntry *NewEntry = HeapAllocMem(pc,
|
||||||
|
sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1);
|
||||||
if (NewEntry == NULL)
|
if (NewEntry == NULL)
|
||||||
ProgramFailNoParser(pc, "(TableSetIdentifier) out of memory");
|
ProgramFailNoParser(pc, "(TableSetIdentifier) out of memory");
|
||||||
|
|
||||||
|
@ -173,7 +177,8 @@ void TableStrFree(Picoc *pc)
|
||||||
struct TableEntry *NextEntry;
|
struct TableEntry *NextEntry;
|
||||||
|
|
||||||
for (Count = 0; Count < pc->StringTable.Size; Count++) {
|
for (Count = 0; Count < pc->StringTable.Size; Count++) {
|
||||||
for (Entry = pc->StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
for (Entry = pc->StringTable.HashTable[Count];
|
||||||
|
Entry != NULL; Entry = NextEntry) {
|
||||||
NextEntry = Entry->Next;
|
NextEntry = Entry->Next;
|
||||||
HeapFreeMem(pc, Entry);
|
HeapFreeMem(pc, Entry);
|
||||||
}
|
}
|
||||||
|
|
60
type.c
60
type.c
|
@ -13,7 +13,8 @@ struct ValueType *TypeAdd(Picoc *pc, struct ParseState *Parser,
|
||||||
struct ValueType *ParentType, enum BaseType Base, int ArraySize,
|
struct ValueType *ParentType, enum BaseType Base, int ArraySize,
|
||||||
const char *Identifier, int Sizeof, int AlignBytes)
|
const char *Identifier, int Sizeof, int AlignBytes)
|
||||||
{
|
{
|
||||||
struct ValueType *NewType = VariableAlloc(pc, Parser, sizeof(struct ValueType), true);
|
struct ValueType *NewType = VariableAlloc(pc, Parser,
|
||||||
|
sizeof(struct ValueType), true);
|
||||||
NewType->Base = Base;
|
NewType->Base = Base;
|
||||||
NewType->ArraySize = ArraySize;
|
NewType->ArraySize = ArraySize;
|
||||||
NewType->Sizeof = Sizeof;
|
NewType->Sizeof = Sizeof;
|
||||||
|
@ -38,7 +39,8 @@ struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
|
||||||
int Sizeof;
|
int Sizeof;
|
||||||
int AlignBytes;
|
int AlignBytes;
|
||||||
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
||||||
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
|
while (ThisType != NULL && (ThisType->Base != Base ||
|
||||||
|
ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
|
||||||
ThisType = ThisType->Next;
|
ThisType = ThisType->Next;
|
||||||
|
|
||||||
if (ThisType != NULL) {
|
if (ThisType != NULL) {
|
||||||
|
@ -50,16 +52,24 @@ struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
|
||||||
|
|
||||||
switch (Base) {
|
switch (Base) {
|
||||||
case TypePointer:
|
case TypePointer:
|
||||||
Sizeof = sizeof(void*); AlignBytes = PointerAlignBytes; break;
|
Sizeof = sizeof(void*);
|
||||||
|
AlignBytes = PointerAlignBytes;
|
||||||
|
break;
|
||||||
case TypeArray:
|
case TypeArray:
|
||||||
Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break;
|
Sizeof = ArraySize * ParentType->Sizeof;
|
||||||
|
AlignBytes = ParentType->AlignBytes;
|
||||||
|
break;
|
||||||
case TypeEnum:
|
case TypeEnum:
|
||||||
Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break;
|
Sizeof = sizeof(int);
|
||||||
|
AlignBytes = IntAlignBytes;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Sizeof = 0; AlignBytes = 0; break; /* structs and unions will get bigger when we add members to them */
|
Sizeof = 0; AlignBytes = 0;
|
||||||
|
break; /* structs and unions will get bigger when we add members to them */
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeAdd(pc, Parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes);
|
return TypeAdd(pc, Parser, ParentType, Base, ArraySize, Identifier, Sizeof,
|
||||||
|
AlignBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stack space used by a value */
|
/* stack space used by a value */
|
||||||
|
@ -185,7 +195,8 @@ void TypeCleanup(Picoc *pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a struct or union declaration */
|
/* parse a struct or union declaration */
|
||||||
void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct)
|
void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
|
int IsStruct)
|
||||||
{
|
{
|
||||||
char *MemberIdentifier;
|
char *MemberIdentifier;
|
||||||
char *StructIdentifier;
|
char *StructIdentifier;
|
||||||
|
@ -216,7 +227,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
||||||
/* use the already defined structure */
|
/* use the already defined structure */
|
||||||
#if 0
|
#if 0
|
||||||
if ((*Typ)->Members == NULL)
|
if ((*Typ)->Members == NULL)
|
||||||
ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier);
|
ProgramFail(Parser, "structure '%s' isn't defined",
|
||||||
|
LexValue->Val->Identifier);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +250,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
||||||
if (MemberType == NULL || MemberIdentifier == NULL)
|
if (MemberType == NULL || MemberIdentifier == NULL)
|
||||||
ProgramFail(Parser, "invalid type in struct");
|
ProgramFail(Parser, "invalid type in struct");
|
||||||
|
|
||||||
MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), false, NULL, true);
|
MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), false,
|
||||||
|
NULL, true);
|
||||||
MemberValue->Typ = MemberType;
|
MemberValue->Typ = MemberType;
|
||||||
if (IsStruct) {
|
if (IsStruct) {
|
||||||
/* allocate this member's location in the struct */
|
/* allocate this member's location in the struct */
|
||||||
|
@ -249,7 +262,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
||||||
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
||||||
(*Typ)->Sizeof += TypeSizeValue(MemberValue, true);
|
(*Typ)->Sizeof += TypeSizeValue(MemberValue, true);
|
||||||
} else {
|
} else {
|
||||||
/* union members always start at 0, make sure it's big enough to hold the largest member */
|
/* union members always start at 0, make sure it's big enough
|
||||||
|
to hold the largest member */
|
||||||
MemberValue->Val->Integer = 0;
|
MemberValue->Val->Integer = 0;
|
||||||
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
||||||
(*Typ)->Sizeof = TypeSizeValue(MemberValue, true);
|
(*Typ)->Sizeof = TypeSizeValue(MemberValue, true);
|
||||||
|
@ -317,7 +331,8 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
|
||||||
EnumIdentifier = PlatformMakeTempName(pc, TempNameBuf);
|
EnumIdentifier = PlatformMakeTempName(pc, TempNameBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeGetMatching(pc, Parser, &pc->UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace);
|
TypeGetMatching(pc, Parser, &pc->UberType, TypeEnum, 0, EnumIdentifier,
|
||||||
|
Token != TokenLeftBrace);
|
||||||
*Typ = &pc->IntType;
|
*Typ = &pc->IntType;
|
||||||
if (Token != TokenLeftBrace) {
|
if (Token != TokenLeftBrace) {
|
||||||
/* use the already defined enum */
|
/* use the already defined enum */
|
||||||
|
@ -356,7 +371,8 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a type - just the basic type */
|
/* parse a type - just the basic type */
|
||||||
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic)
|
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
|
int *IsStatic)
|
||||||
{
|
{
|
||||||
int Unsigned = false;
|
int Unsigned = false;
|
||||||
int StaticQualifier = false;
|
int StaticQualifier = false;
|
||||||
|
@ -370,7 +386,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
|
||||||
/* ignore leading type qualifiers */
|
/* ignore leading type qualifiers */
|
||||||
ParserCopy(&Before, Parser);
|
ParserCopy(&Before, Parser);
|
||||||
Token = LexGetToken(Parser, &LexerValue, true);
|
Token = LexGetToken(Parser, &LexerValue, true);
|
||||||
while (Token == TokenStaticType || Token == TokenAutoType || Token == TokenRegisterType || Token == TokenExternType) {
|
while (Token == TokenStaticType || Token == TokenAutoType ||
|
||||||
|
Token == TokenRegisterType || Token == TokenExternType) {
|
||||||
if (Token == TokenStaticType)
|
if (Token == TokenStaticType)
|
||||||
StaticQualifier = true;
|
StaticQualifier = true;
|
||||||
|
|
||||||
|
@ -385,7 +402,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
|
||||||
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
|
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
|
||||||
Unsigned = (Token == TokenUnsignedType);
|
Unsigned = (Token == TokenUnsignedType);
|
||||||
|
|
||||||
if (FollowToken != TokenIntType && FollowToken != TokenLongType && FollowToken != TokenShortType && FollowToken != TokenCharType) {
|
if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
|
||||||
|
FollowToken != TokenShortType && FollowToken != TokenCharType) {
|
||||||
if (Token == TokenUnsignedType)
|
if (Token == TokenUnsignedType)
|
||||||
*Typ = &pc->UnsignedIntType;
|
*Typ = &pc->UnsignedIntType;
|
||||||
else
|
else
|
||||||
|
@ -443,7 +461,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a type - the part at the end after the identifier. eg. array specifications etc. */
|
/* parse a type - the part at the end after the identifier. eg. array specifications etc. */
|
||||||
struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *FromType)
|
struct ValueType *TypeParseBack(struct ParseState *Parser,
|
||||||
|
struct ValueType *FromType)
|
||||||
{
|
{
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
struct ParseState Before;
|
struct ParseState Before;
|
||||||
|
@ -480,7 +499,8 @@ struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *Fro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a type - the part which is repeated with each identifier in a declaration list */
|
/* parse a type - the part which is repeated with each
|
||||||
|
identifier in a declaration list */
|
||||||
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
||||||
struct ValueType **Typ, char **Identifier)
|
struct ValueType **Typ, char **Identifier)
|
||||||
{
|
{
|
||||||
|
@ -543,13 +563,15 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if a type has been fully defined - otherwise it's just a forward declaration */
|
/* check if a type has been fully defined - otherwise it's
|
||||||
|
just a forward declaration */
|
||||||
int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ)
|
int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ)
|
||||||
{
|
{
|
||||||
if (Typ->Base == TypeArray)
|
if (Typ->Base == TypeArray)
|
||||||
return TypeIsForwardDeclared(Parser, Typ->FromType);
|
return TypeIsForwardDeclared(Parser, Typ->FromType);
|
||||||
|
|
||||||
if ( (Typ->Base == TypeStruct || Typ->Base == TypeUnion) && Typ->Members == NULL)
|
if ((Typ->Base == TypeStruct || Typ->Base == TypeUnion) &&
|
||||||
|
Typ->Members == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
114
variable.c
114
variable.c
|
@ -22,7 +22,9 @@ void VariableFree(Picoc *pc, struct Value *Val)
|
||||||
{
|
{
|
||||||
if (Val->ValOnHeap || Val->AnyValOnHeap) {
|
if (Val->ValOnHeap || Val->AnyValOnHeap) {
|
||||||
/* free function bodies */
|
/* free function bodies */
|
||||||
if (Val->Typ == &pc->FunctionType && Val->Val->FuncDef.Intrinsic == NULL && Val->Val->FuncDef.Body.Pos != NULL)
|
if (Val->Typ == &pc->FunctionType &&
|
||||||
|
Val->Val->FuncDef.Intrinsic == NULL &&
|
||||||
|
Val->Val->FuncDef.Body.Pos != NULL)
|
||||||
HeapFreeMem(pc, (void *)Val->Val->FuncDef.Body.Pos);
|
HeapFreeMem(pc, (void *)Val->Val->FuncDef.Body.Pos);
|
||||||
|
|
||||||
/* free macro bodies */
|
/* free macro bodies */
|
||||||
|
@ -47,7 +49,9 @@ void VariableTableCleanup(Picoc *pc, struct Table *HashTable)
|
||||||
struct TableEntry *NextEntry;
|
struct TableEntry *NextEntry;
|
||||||
|
|
||||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
for (Entry = HashTable->HashTable[Count];
|
||||||
|
Entry != NULL;
|
||||||
|
Entry = NextEntry) {
|
||||||
NextEntry = Entry->Next;
|
NextEntry = Entry->Next;
|
||||||
VariableFree(pc, Entry->p.v.Val);
|
VariableFree(pc, Entry->p.v.Val);
|
||||||
|
|
||||||
|
@ -63,7 +67,8 @@ void VariableCleanup(Picoc *pc)
|
||||||
VariableTableCleanup(pc, &pc->StringLiteralTable);
|
VariableTableCleanup(pc, &pc->StringLiteralTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate some memory, either on the heap or the stack and check if we've run out */
|
/* allocate some memory, either on the heap or the stack
|
||||||
|
and check if we've run out */
|
||||||
void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
|
void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
|
||||||
{
|
{
|
||||||
void *NewValue;
|
void *NewValue;
|
||||||
|
@ -84,7 +89,8 @@ void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
|
||||||
return NewValue;
|
return NewValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a value either on the heap or the stack using space dependent on what type we want */
|
/* allocate a value either on the heap or the stack using space
|
||||||
|
dependent on what type we want */
|
||||||
struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser,
|
struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser,
|
||||||
int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap)
|
int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap)
|
||||||
{
|
{
|
||||||
|
@ -110,14 +116,16 @@ struct Value *VariableAllocValueFromType(Picoc *pc, struct ParseState *Parser,
|
||||||
struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap)
|
struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap)
|
||||||
{
|
{
|
||||||
int Size = TypeSize(Typ, Typ->ArraySize, false);
|
int Size = TypeSize(Typ, Typ->ArraySize, false);
|
||||||
struct Value *NewValue = VariableAllocValueAndData(pc, Parser, Size, IsLValue, LValueFrom, OnHeap);
|
struct Value *NewValue = VariableAllocValueAndData(pc, Parser, Size,
|
||||||
|
IsLValue, LValueFrom, OnHeap);
|
||||||
assert(Size >= 0 || Typ == &pc->VoidType);
|
assert(Size >= 0 || Typ == &pc->VoidType);
|
||||||
NewValue->Typ = Typ;
|
NewValue->Typ = Typ;
|
||||||
|
|
||||||
return NewValue;
|
return NewValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */
|
/* allocate a value either on the heap or the stack and copy
|
||||||
|
its value. handles overlapping data */
|
||||||
struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser,
|
struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser,
|
||||||
struct Value *FromValue, int OnHeap)
|
struct Value *FromValue, int OnHeap)
|
||||||
{
|
{
|
||||||
|
@ -136,12 +144,14 @@ struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser,
|
||||||
return NewValue;
|
return NewValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a value either on the heap or the stack from an existing AnyValue and type */
|
/* allocate a value either on the heap or the stack from an
|
||||||
|
existing AnyValue and type */
|
||||||
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser,
|
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser,
|
||||||
struct ValueType *Typ, union AnyValue *FromValue, int IsLValue,
|
struct ValueType *Typ, union AnyValue *FromValue, int IsLValue,
|
||||||
struct Value *LValueFrom)
|
struct Value *LValueFrom)
|
||||||
{
|
{
|
||||||
struct Value *NewValue = VariableAlloc(Parser->pc, Parser, sizeof(struct Value), false);
|
struct Value *NewValue = VariableAlloc(Parser->pc, Parser,
|
||||||
|
sizeof(struct Value), false);
|
||||||
NewValue->Typ = Typ;
|
NewValue->Typ = Typ;
|
||||||
NewValue->Val = FromValue;
|
NewValue->Val = FromValue;
|
||||||
NewValue->ValOnHeap = false;
|
NewValue->ValOnHeap = false;
|
||||||
|
@ -153,7 +163,8 @@ struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser,
|
||||||
return NewValue;
|
return NewValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a value either on the heap or the stack from an existing Value, sharing the value */
|
/* allocate a value either on the heap or the stack from an
|
||||||
|
existing Value, sharing the value */
|
||||||
struct Value *VariableAllocValueShared(struct ParseState *Parser,
|
struct Value *VariableAllocValueShared(struct ParseState *Parser,
|
||||||
struct Value *FromValue)
|
struct Value *FromValue)
|
||||||
{
|
{
|
||||||
|
@ -183,18 +194,22 @@ int VariableScopeBegin(struct ParseState *Parser, int* OldScopeID)
|
||||||
if (Parser->ScopeID == -1)
|
if (Parser->ScopeID == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ? &(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
|
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ?
|
||||||
|
&(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
|
||||||
|
|
||||||
/* XXX dumb hash, let's hope for no collisions... */
|
/* XXX dumb hash, let's hope for no collisions... */
|
||||||
*OldScopeID = Parser->ScopeID;
|
*OldScopeID = Parser->ScopeID;
|
||||||
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*));
|
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) *
|
||||||
|
((int)(intptr_t)(Parser->Pos) / sizeof(char*));
|
||||||
/* or maybe a more human-readable hash for debugging? */
|
/* or maybe a more human-readable hash for debugging? */
|
||||||
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
|
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
|
||||||
|
|
||||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
for (Entry = HashTable->HashTable[Count];
|
||||||
|
Entry != NULL; Entry = NextEntry) {
|
||||||
NextEntry = Entry->Next;
|
NextEntry = Entry->Next;
|
||||||
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope == true) {
|
if (Entry->p.v.Val->ScopeID == Parser->ScopeID &&
|
||||||
|
Entry->p.v.Val->OutOfScope == true) {
|
||||||
Entry->p.v.Val->OutOfScope = false;
|
Entry->p.v.Val->OutOfScope = false;
|
||||||
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
|
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
|
||||||
#ifdef DEBUG_VAR_SCOPE
|
#ifdef DEBUG_VAR_SCOPE
|
||||||
|
@ -222,12 +237,15 @@ void VariableScopeEnd(struct ParseState *Parser, int ScopeID, int PrevScopeID)
|
||||||
if (ScopeID == -1)
|
if (ScopeID == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ? &(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
|
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ?
|
||||||
|
&(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
|
||||||
|
|
||||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
for (Entry = HashTable->HashTable[Count];
|
||||||
|
Entry != NULL; Entry = NextEntry) {
|
||||||
NextEntry = Entry->Next;
|
NextEntry = Entry->Next;
|
||||||
if ((Entry->p.v.Val->ScopeID == ScopeID) && (Entry->p.v.Val->OutOfScope == false)) {
|
if ((Entry->p.v.Val->ScopeID == ScopeID) &&
|
||||||
|
(Entry->p.v.Val->OutOfScope == false)) {
|
||||||
#ifdef DEBUG_VAR_SCOPE
|
#ifdef DEBUG_VAR_SCOPE
|
||||||
if (!FirstPrint) PRINT_SOURCE_POS();
|
if (!FirstPrint) PRINT_SOURCE_POS();
|
||||||
FirstPrint = 1;
|
FirstPrint = 1;
|
||||||
|
@ -248,10 +266,14 @@ int VariableDefinedAndOutOfScope(Picoc * pc, const char* Ident)
|
||||||
int Count;
|
int Count;
|
||||||
struct TableEntry *Entry;
|
struct TableEntry *Entry;
|
||||||
|
|
||||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
struct Table * HashTable = (pc->TopStackFrame == NULL) ?
|
||||||
|
&(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||||
|
|
||||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next) {
|
for (Entry = HashTable->HashTable[Count];
|
||||||
if (Entry->p.v.Val->OutOfScope == true && (char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
|
Entry != NULL; Entry = Entry->Next) {
|
||||||
|
if (Entry->p.v.Val->OutOfScope == true &&
|
||||||
|
(char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +286,8 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
|
||||||
{
|
{
|
||||||
int ScopeID = Parser ? Parser->ScopeID : -1;
|
int ScopeID = Parser ? Parser->ScopeID : -1;
|
||||||
struct Value * AssignValue;
|
struct Value * AssignValue;
|
||||||
struct Table * currentTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
struct Table * currentTable = (pc->TopStackFrame == NULL) ?
|
||||||
|
&(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||||
|
|
||||||
#ifdef DEBUG_VAR_SCOPE
|
#ifdef DEBUG_VAR_SCOPE
|
||||||
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID,
|
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID,
|
||||||
|
@ -272,7 +295,8 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (InitValue != NULL)
|
if (InitValue != NULL)
|
||||||
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL);
|
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue,
|
||||||
|
pc->TopStackFrame == NULL);
|
||||||
else
|
else
|
||||||
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable,
|
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable,
|
||||||
NULL, pc->TopStackFrame == NULL);
|
NULL, pc->TopStackFrame == NULL);
|
||||||
|
@ -281,13 +305,16 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
|
||||||
AssignValue->ScopeID = ScopeID;
|
AssignValue->ScopeID = ScopeID;
|
||||||
AssignValue->OutOfScope = false;
|
AssignValue->OutOfScope = false;
|
||||||
|
|
||||||
if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ? ((char*)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
|
if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ?
|
||||||
|
((char*)Parser->FileName) : NULL, Parser ? Parser->Line : 0,
|
||||||
|
Parser ? Parser->CharacterPos : 0))
|
||||||
ProgramFail(Parser, "'%s' is already defined", Ident);
|
ProgramFail(Parser, "'%s' is already defined", Ident);
|
||||||
|
|
||||||
return AssignValue;
|
return AssignValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */
|
/* define a variable. Ident must be registered. If it's a redefinition
|
||||||
|
from the same declaration don't throw an error */
|
||||||
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
|
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
|
||||||
char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit)
|
char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit)
|
||||||
{
|
{
|
||||||
|
@ -307,7 +334,8 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
|
||||||
char *MNEnd = &MangledName[LINEBUFFER_MAX-1];
|
char *MNEnd = &MangledName[LINEBUFFER_MAX-1];
|
||||||
const char *RegisteredMangledName;
|
const char *RegisteredMangledName;
|
||||||
|
|
||||||
/* make the mangled static name (avoiding using sprintf() to minimise library impact) */
|
/* make the mangled static name (avoiding using sprintf()
|
||||||
|
to minimise library impact) */
|
||||||
memset((void *)&MangledName, '\0', sizeof(MangledName));
|
memset((void *)&MangledName, '\0', sizeof(MangledName));
|
||||||
*MNPos++ = '/';
|
*MNPos++ = '/';
|
||||||
strncpy(MNPos, (char*)Parser->FileName, MNEnd - MNPos);
|
strncpy(MNPos, (char*)Parser->FileName, MNEnd - MNPos);
|
||||||
|
@ -325,18 +353,26 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
|
||||||
RegisteredMangledName = TableStrRegister(pc, MangledName);
|
RegisteredMangledName = TableStrRegister(pc, MangledName);
|
||||||
|
|
||||||
/* is this static already defined? */
|
/* is this static already defined? */
|
||||||
if (!TableGet(&pc->GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) {
|
if (!TableGet(&pc->GlobalTable, RegisteredMangledName, &ExistingValue,
|
||||||
|
&DeclFileName, &DeclLine, &DeclColumn)) {
|
||||||
/* define the mangled-named static variable store in the global scope */
|
/* define the mangled-named static variable store in the global scope */
|
||||||
ExistingValue = VariableAllocValueFromType(Parser->pc, Parser, Typ, true, NULL, true);
|
ExistingValue = VariableAllocValueFromType(Parser->pc, Parser, Typ,
|
||||||
TableSet(pc, &pc->GlobalTable, (char*)RegisteredMangledName, ExistingValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos);
|
true, NULL, true);
|
||||||
|
TableSet(pc, &pc->GlobalTable, (char*)RegisteredMangledName,
|
||||||
|
ExistingValue, (char *)Parser->FileName, Parser->Line,
|
||||||
|
Parser->CharacterPos);
|
||||||
*FirstVisit = true;
|
*FirstVisit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */
|
/* static variable exists in the global scope - now make a
|
||||||
VariableDefinePlatformVar(Parser->pc, Parser, Ident, ExistingValue->Typ, ExistingValue->Val, true);
|
mirroring variable in our own scope with the short name */
|
||||||
|
VariableDefinePlatformVar(Parser->pc, Parser, Ident, ExistingValue->Typ,
|
||||||
|
ExistingValue->Val, true);
|
||||||
return ExistingValue;
|
return ExistingValue;
|
||||||
} else {
|
} else {
|
||||||
if (Parser->Line != 0 && TableGet((pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)
|
if (Parser->Line != 0 && TableGet((pc->TopStackFrame == NULL) ?
|
||||||
|
&pc->GlobalTable : &pc->TopStackFrame->LocalTable, Ident,
|
||||||
|
&ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)
|
||||||
&& DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos)
|
&& DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos)
|
||||||
return ExistingValue;
|
return ExistingValue;
|
||||||
else
|
else
|
||||||
|
@ -377,15 +413,21 @@ void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident,
|
||||||
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident,
|
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident,
|
||||||
struct ValueType *Typ, union AnyValue *FromValue, int IsWritable)
|
struct ValueType *Typ, union AnyValue *FromValue, int IsWritable)
|
||||||
{
|
{
|
||||||
struct Value *SomeValue = VariableAllocValueAndData(pc, NULL, 0, IsWritable, NULL, true);
|
struct Value *SomeValue = VariableAllocValueAndData(pc, NULL, 0, IsWritable,
|
||||||
|
NULL, true);
|
||||||
SomeValue->Typ = Typ;
|
SomeValue->Typ = Typ;
|
||||||
SomeValue->Val = FromValue;
|
SomeValue->Val = FromValue;
|
||||||
|
|
||||||
if (!TableSet(pc, (pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable, TableStrRegister(pc, Ident), SomeValue, Parser ? Parser->FileName : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
|
if (!TableSet(pc,
|
||||||
|
(pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable,
|
||||||
|
TableStrRegister(pc, Ident), SomeValue,
|
||||||
|
Parser ? Parser->FileName : NULL,
|
||||||
|
Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
|
||||||
ProgramFail(Parser, "'%s' is already defined", Ident);
|
ProgramFail(Parser, "'%s' is already defined", Ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free and/or pop the top value off the stack. Var must be the top value on the stack! */
|
/* free and/or pop the top value off the stack. Var must be
|
||||||
|
the top value on the stack! */
|
||||||
void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
||||||
{
|
{
|
||||||
int Success;
|
int Success;
|
||||||
|
@ -426,7 +468,8 @@ void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName,
|
||||||
|
|
||||||
ParserCopy(&NewFrame->ReturnParser, Parser);
|
ParserCopy(&NewFrame->ReturnParser, Parser);
|
||||||
NewFrame->FuncName = FuncName;
|
NewFrame->FuncName = FuncName;
|
||||||
NewFrame->Parameter = (NumParams > 0) ? ((void*)((char *)NewFrame+sizeof(struct StackFrame))) : NULL;
|
NewFrame->Parameter = (NumParams > 0) ?
|
||||||
|
((void*)((char*)NewFrame+sizeof(struct StackFrame))) : NULL;
|
||||||
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0],
|
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0],
|
||||||
LOCAL_TABLE_SIZE, false);
|
LOCAL_TABLE_SIZE, false);
|
||||||
NewFrame->PreviousStackFrame = Parser->pc->TopStackFrame;
|
NewFrame->PreviousStackFrame = Parser->pc->TopStackFrame;
|
||||||
|
@ -444,7 +487,8 @@ void VariableStackFramePop(struct ParseState *Parser)
|
||||||
HeapPopStackFrame(Parser->pc);
|
HeapPopStackFrame(Parser->pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a string literal. assumes that Ident is already registered. NULL if not found */
|
/* get a string literal. assumes that Ident is already
|
||||||
|
registered. NULL if not found */
|
||||||
struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident)
|
struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident)
|
||||||
{
|
{
|
||||||
struct Value *LVal = NULL;
|
struct Value *LVal = NULL;
|
||||||
|
|
Loading…
Reference in a new issue