formatting
This commit is contained in:
parent
c8c01cd1f5
commit
a61bd97d9b
235
clibrary.c
235
clibrary.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc mini standard C library - provides an optional tiny C standard library
|
||||
* if BUILTIN_MINI_STDLIB is defined */
|
||||
|
||||
/* picoc mini standard C library - provides an optional tiny C standard library
|
||||
* if BUILTIN_MINI_STDLIB is defined */
|
||||
|
||||
#include "picoc.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -14,7 +14,7 @@ static int LittleEndian;
|
|||
/* global initialisation for libraries */
|
||||
void LibraryInit(Picoc *pc)
|
||||
{
|
||||
|
||||
|
||||
/* define the version number macro */
|
||||
pc->VersionString = TableStrRegister(pc, PICOC_VERSION);
|
||||
VariableDefinePlatformVar(pc, NULL, "PICOC_VERSION", pc->CharPtrType, (union AnyValue *)&pc->VersionString, FALSE);
|
||||
|
@ -37,10 +37,9 @@ void LibraryAdd(Picoc *pc, struct Table *GlobalTable, const char *LibraryName, s
|
|||
struct Value *NewValue;
|
||||
void *Tokens;
|
||||
char *IntrinsicName = TableStrRegister(pc, "c library");
|
||||
|
||||
|
||||
/* read all the library definitions */
|
||||
for (Count = 0; FuncList[Count].Prototype != NULL; Count++)
|
||||
{
|
||||
for (Count = 0; FuncList[Count].Prototype != NULL; Count++) {
|
||||
Tokens = LexAnalyse(pc, IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL);
|
||||
LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE, FALSE);
|
||||
TypeParse(&Parser, &ReturnType, &Identifier, NULL);
|
||||
|
@ -53,42 +52,41 @@ void LibraryAdd(Picoc *pc, struct Table *GlobalTable, const char *LibraryName, s
|
|||
/* print a type to a stream without using printf/sprintf */
|
||||
void PrintType(struct ValueType *Typ, IOFILE *Stream)
|
||||
{
|
||||
switch (Typ->Base)
|
||||
{
|
||||
case TypeVoid: PrintStr("void", Stream); break;
|
||||
case TypeInt: PrintStr("int", Stream); break;
|
||||
case TypeShort: PrintStr("short", Stream); break;
|
||||
case TypeChar: PrintStr("char", Stream); break;
|
||||
case TypeLong: PrintStr("long", Stream); break;
|
||||
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
||||
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
||||
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
|
||||
case TypeUnsignedChar: PrintStr("unsigned char", Stream); break;
|
||||
switch (Typ->Base) {
|
||||
case TypeVoid: PrintStr("void", Stream); break;
|
||||
case TypeInt: PrintStr("int", Stream); break;
|
||||
case TypeShort: PrintStr("short", Stream); break;
|
||||
case TypeChar: PrintStr("char", Stream); break;
|
||||
case TypeLong: PrintStr("long", Stream); break;
|
||||
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
||||
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
||||
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
|
||||
case TypeUnsignedChar: PrintStr("unsigned char", Stream); break;
|
||||
#ifndef NO_FP
|
||||
case TypeFP: PrintStr("double", Stream); break;
|
||||
case TypeFP: PrintStr("double", Stream); break;
|
||||
#endif
|
||||
case TypeFunction: PrintStr("function", Stream); break;
|
||||
case TypeMacro: PrintStr("macro", Stream); break;
|
||||
case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break;
|
||||
case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintSimpleInt(Typ->ArraySize, Stream); PrintCh(']', Stream); break;
|
||||
case TypeStruct: PrintStr("struct ", Stream); PrintStr( Typ->Identifier, Stream); break;
|
||||
case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||
case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||
case TypeGotoLabel: PrintStr("goto label ", Stream); break;
|
||||
case Type_Type: PrintStr("type ", Stream); break;
|
||||
case TypeFunction: PrintStr("function", Stream); break;
|
||||
case TypeMacro: PrintStr("macro", Stream); break;
|
||||
case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break;
|
||||
case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintSimpleInt(Typ->ArraySize, Stream); PrintCh(']', Stream); break;
|
||||
case TypeStruct: PrintStr("struct ", Stream); PrintStr( Typ->Identifier, Stream); break;
|
||||
case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||
case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||
case TypeGotoLabel: PrintStr("goto label ", Stream); break;
|
||||
case Type_Type: PrintStr("type ", Stream); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef BUILTIN_MINI_STDLIB
|
||||
|
||||
/*
|
||||
/*
|
||||
* This is a simplified standard library for small embedded systems. It doesn't require
|
||||
* a system stdio library to operate.
|
||||
*
|
||||
* A more complete standard library for larger computers is in the library_XXX.c files.
|
||||
*/
|
||||
|
||||
|
||||
static int TRUEValue = 1;
|
||||
static int ZeroValue = 0;
|
||||
|
||||
|
@ -143,22 +141,21 @@ void PrintUnsigned(unsigned long Num, unsigned int Base, int FieldWidth, int Zer
|
|||
Result[--ResPos] = '\0';
|
||||
if (Num == 0)
|
||||
Result[--ResPos] = '0';
|
||||
|
||||
while (Num > 0)
|
||||
{
|
||||
|
||||
while (Num > 0) {
|
||||
unsigned long NextNum = Num / Base;
|
||||
unsigned long Digit = Num - NextNum * Base;
|
||||
if (Digit < 10)
|
||||
Result[--ResPos] = '0' + Digit;
|
||||
else
|
||||
Result[--ResPos] = 'a' + Digit - 10;
|
||||
|
||||
|
||||
Num = NextNum;
|
||||
}
|
||||
|
||||
|
||||
if (FieldWidth > 0 && !LeftJustify)
|
||||
PrintRepeatedChar(ZeroPad ? '0' : ' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream);
|
||||
|
||||
|
||||
PrintStr(&Result[ResPos], Stream);
|
||||
|
||||
if (FieldWidth > 0 && LeftJustify)
|
||||
|
@ -174,14 +171,13 @@ void PrintSimpleInt(long Num, struct OutputStream *Stream)
|
|||
/* print an integer to a stream without using printf/sprintf */
|
||||
void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream)
|
||||
{
|
||||
if (Num < 0)
|
||||
{
|
||||
if (Num < 0) {
|
||||
PrintCh('-', Stream);
|
||||
Num = -Num;
|
||||
if (FieldWidth != 0)
|
||||
FieldWidth--;
|
||||
}
|
||||
|
||||
|
||||
PrintUnsigned((unsigned long)Num, 10, FieldWidth, ZeroPad, LeftJustify, Stream);
|
||||
}
|
||||
|
||||
|
@ -191,32 +187,29 @@ void PrintFP(double Num, struct OutputStream *Stream)
|
|||
{
|
||||
int Exponent = 0;
|
||||
int MaxDecimal;
|
||||
|
||||
if (Num < 0)
|
||||
{
|
||||
|
||||
if (Num < 0) {
|
||||
PrintCh('-', Stream);
|
||||
Num = -Num;
|
||||
Num = -Num;
|
||||
}
|
||||
|
||||
|
||||
if (Num >= 1e7)
|
||||
Exponent = log10(Num);
|
||||
else if (Num <= 1e-7 && Num != 0.0)
|
||||
Exponent = log10(Num) - 0.999999999;
|
||||
|
||||
Num /= pow(10.0, Exponent);
|
||||
|
||||
Num /= pow(10.0, Exponent);
|
||||
PrintInt((long)Num, 0, FALSE, FALSE, Stream);
|
||||
PrintCh('.', Stream);
|
||||
Num = (Num - (long)Num) * 10;
|
||||
if (abs(Num) >= 1e-7)
|
||||
{
|
||||
if (abs(Num) >= 1e-7) {
|
||||
for (MaxDecimal = 6; MaxDecimal > 0 && abs(Num) >= 1e-7; Num = (Num - (long)(Num + 1e-7)) * 10, MaxDecimal--)
|
||||
PrintCh('0' + (long)(Num + 1e-7), Stream);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
PrintCh('0', Stream);
|
||||
|
||||
if (Exponent != 0)
|
||||
{
|
||||
}
|
||||
|
||||
if (Exponent != 0) {
|
||||
PrintCh('e', Stream);
|
||||
PrintInt(Exponent, 0, FALSE, FALSE, Stream);
|
||||
}
|
||||
|
@ -234,88 +227,79 @@ void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct
|
|||
int ZeroPad = FALSE;
|
||||
int FieldWidth = 0;
|
||||
char *Format = Param[0]->Val->Pointer;
|
||||
|
||||
for (FPos = Format; *FPos != '\0'; FPos++)
|
||||
{
|
||||
if (*FPos == '%')
|
||||
{
|
||||
|
||||
for (FPos = Format; *FPos != '\0'; FPos++) {
|
||||
if (*FPos == '%') {
|
||||
FPos++;
|
||||
FieldWidth = 0;
|
||||
if (*FPos == '-')
|
||||
{
|
||||
FieldWidth = 0;
|
||||
if (*FPos == '-') {
|
||||
/* a leading '-' means left justify */
|
||||
LeftJustify = TRUE;
|
||||
FPos++;
|
||||
}
|
||||
|
||||
if (*FPos == '0')
|
||||
{
|
||||
|
||||
if (*FPos == '0') {
|
||||
/* a leading zero means zero pad a decimal number */
|
||||
ZeroPad = TRUE;
|
||||
FPos++;
|
||||
}
|
||||
|
||||
|
||||
/* get any field width in the format */
|
||||
while (isdigit((int)*FPos))
|
||||
FieldWidth = FieldWidth * 10 + (*FPos++ - '0');
|
||||
|
||||
|
||||
/* now check the format type */
|
||||
switch (*FPos)
|
||||
{
|
||||
case 's': FormatType = CharPtrType; break;
|
||||
case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break;
|
||||
switch (*FPos) {
|
||||
case 's': FormatType = CharPtrType; break;
|
||||
case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break;
|
||||
#ifndef NO_FP
|
||||
case 'f': FormatType = &FPType; break;
|
||||
case 'f': FormatType = &FPType; break;
|
||||
#endif
|
||||
case '%': PrintCh('%', Stream); FormatType = NULL; break;
|
||||
case '\0': FPos--; FormatType = NULL; break;
|
||||
default: PrintCh(*FPos, Stream); FormatType = NULL; break;
|
||||
case '%': PrintCh('%', Stream); FormatType = NULL; break;
|
||||
case '\0': FPos--; FormatType = NULL; break;
|
||||
default: PrintCh(*FPos, Stream); FormatType = NULL; break;
|
||||
}
|
||||
|
||||
if (FormatType != NULL)
|
||||
{
|
||||
|
||||
if (FormatType != NULL) {
|
||||
/* we have to format something */
|
||||
if (ArgCount >= NumArgs)
|
||||
PrintStr("XXX", Stream); /* not enough parameters for format */
|
||||
else
|
||||
{
|
||||
else {
|
||||
NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg)));
|
||||
if (NextArg->Typ != FormatType &&
|
||||
if (NextArg->Typ != FormatType &&
|
||||
!((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) &&
|
||||
!(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer ||
|
||||
!(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer ||
|
||||
(NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) )
|
||||
PrintStr("XXX", Stream); /* bad type for format */
|
||||
else
|
||||
{
|
||||
switch (*FPos)
|
||||
{
|
||||
case 's':
|
||||
else {
|
||||
switch (*FPos) {
|
||||
case 's':
|
||||
{
|
||||
char *Str;
|
||||
|
||||
|
||||
if (NextArg->Typ->Base == TypePointer)
|
||||
Str = NextArg->Val->Pointer;
|
||||
else
|
||||
Str = &NextArg->Val->ArrayMem[0];
|
||||
|
||||
|
||||
if (Str == NULL)
|
||||
PrintStr("NULL", Stream);
|
||||
PrintStr("NULL", Stream);
|
||||
else
|
||||
PrintStr(Str, Stream);
|
||||
PrintStr(Str, Stream);
|
||||
break;
|
||||
}
|
||||
case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break;
|
||||
case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
||||
case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break;
|
||||
#ifndef NO_FP
|
||||
case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break;
|
||||
case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ArgCount++;
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +312,7 @@ void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct
|
|||
void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||
{
|
||||
struct OutputStream ConsoleStream;
|
||||
|
||||
|
||||
ConsoleStream.Putch = &PlatformPutc;
|
||||
GenericPrintf(Parser, ReturnValue, Param, NumArgs, &ConsoleStream);
|
||||
}
|
||||
|
@ -337,7 +321,7 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
void LibSPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||
{
|
||||
struct OutputStream StrStream;
|
||||
|
||||
|
||||
StrStream.Putch = &SPutc;
|
||||
StrStream.i.Str.Parser = Parser;
|
||||
StrStream.i.Str.WritePos = Param[0]->Val->Pointer;
|
||||
|
@ -351,8 +335,7 @@ void LibSPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Val
|
|||
void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||
{
|
||||
ReturnValue->Val->Pointer = PlatformGetLine(Param[0]->Val->Pointer, GETS_BUF_MAX, NULL);
|
||||
if (ReturnValue->Val->Pointer != NULL)
|
||||
{
|
||||
if (ReturnValue->Val->Pointer != NULL) {
|
||||
char *EOLPos = strchr(Param[0]->Val->Pointer, '\n');
|
||||
if (EOLPos != NULL)
|
||||
*EOLPos = '\0';
|
||||
|
@ -490,10 +473,10 @@ void LibStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
{
|
||||
char *To = (char *)Param[0]->Val->Pointer;
|
||||
char *From = (char *)Param[1]->Val->Pointer;
|
||||
|
||||
|
||||
while (*From != '\0')
|
||||
*To++ = *From++;
|
||||
|
||||
|
||||
*To = '\0';
|
||||
}
|
||||
|
||||
|
@ -502,10 +485,10 @@ void LibStrncpy(struct ParseState *Parser, struct Value *ReturnValue, struct Val
|
|||
char *To = (char *)Param[0]->Val->Pointer;
|
||||
char *From = (char *)Param[1]->Val->Pointer;
|
||||
int Len = Param[2]->Val->Integer;
|
||||
|
||||
|
||||
for (; *From != '\0' && Len > 0; Len--)
|
||||
*To++ = *From++;
|
||||
|
||||
|
||||
if (Len > 0)
|
||||
*To = '\0';
|
||||
}
|
||||
|
@ -515,13 +498,12 @@ void LibStrcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
char *Str1 = (char *)Param[0]->Val->Pointer;
|
||||
char *Str2 = (char *)Param[1]->Val->Pointer;
|
||||
int StrEnded;
|
||||
|
||||
for (StrEnded = FALSE; !StrEnded; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++)
|
||||
{
|
||||
if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; }
|
||||
|
||||
for (StrEnded = FALSE; !StrEnded; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++) {
|
||||
if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; }
|
||||
else if (*Str1 > *Str2) { ReturnValue->Val->Integer = 1; return; }
|
||||
}
|
||||
|
||||
|
||||
ReturnValue->Val->Integer = 0;
|
||||
}
|
||||
|
||||
|
@ -531,13 +513,12 @@ void LibStrncmp(struct ParseState *Parser, struct Value *ReturnValue, struct Val
|
|||
char *Str2 = (char *)Param[1]->Val->Pointer;
|
||||
int Len = Param[2]->Val->Integer;
|
||||
int StrEnded;
|
||||
|
||||
for (StrEnded = FALSE; !StrEnded && Len > 0; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++, Len--)
|
||||
{
|
||||
if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; }
|
||||
|
||||
for (StrEnded = FALSE; !StrEnded && Len > 0; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++, Len--) {
|
||||
if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; }
|
||||
else if (*Str1 > *Str2) { ReturnValue->Val->Integer = 1; return; }
|
||||
}
|
||||
|
||||
|
||||
ReturnValue->Val->Integer = 0;
|
||||
}
|
||||
|
||||
|
@ -545,13 +526,13 @@ void LibStrcat(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
{
|
||||
char *To = (char *)Param[0]->Val->Pointer;
|
||||
char *From = (char *)Param[1]->Val->Pointer;
|
||||
|
||||
|
||||
while (*To != '\0')
|
||||
To++;
|
||||
|
||||
|
||||
while (*From != '\0')
|
||||
*To++ = *From++;
|
||||
|
||||
|
||||
*To = '\0';
|
||||
}
|
||||
|
||||
|
@ -562,7 +543,7 @@ void LibIndex(struct ParseState *Parser, struct Value *ReturnValue, struct Value
|
|||
|
||||
while (*Pos != '\0' && *Pos != SearchChar)
|
||||
Pos++;
|
||||
|
||||
|
||||
if (*Pos != SearchChar)
|
||||
ReturnValue->Val->Pointer = NULL;
|
||||
else
|
||||
|
@ -575,8 +556,7 @@ void LibRindex(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
int SearchChar = Param[1]->Val->Integer;
|
||||
|
||||
ReturnValue->Val->Pointer = NULL;
|
||||
for (; *Pos != '\0'; Pos++)
|
||||
{
|
||||
for (; *Pos != '\0'; Pos++) {
|
||||
if (*Pos == SearchChar)
|
||||
ReturnValue->Val->Pointer = Pos;
|
||||
}
|
||||
|
@ -586,10 +566,10 @@ void LibStrlen(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
{
|
||||
char *Pos = (char *)Param[0]->Val->Pointer;
|
||||
int Len;
|
||||
|
||||
|
||||
for (Len = 0; *Pos != '\0'; Pos++)
|
||||
Len++;
|
||||
|
||||
|
||||
ReturnValue->Val->Integer = Len;
|
||||
}
|
||||
|
||||
|
@ -610,13 +590,12 @@ void LibMemcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
|||
unsigned char *Mem1 = (unsigned char *)Param[0]->Val->Pointer;
|
||||
unsigned char *Mem2 = (unsigned char *)Param[1]->Val->Pointer;
|
||||
int Len = Param[2]->Val->Integer;
|
||||
|
||||
for (; Len > 0; Mem1++, Mem2++, Len--)
|
||||
{
|
||||
if (*Mem1 < *Mem2) { ReturnValue->Val->Integer = -1; return; }
|
||||
|
||||
for (; Len > 0; Mem1++, Mem2++, Len--) {
|
||||
if (*Mem1 < *Mem2) { ReturnValue->Val->Integer = -1; return; }
|
||||
else if (*Mem1 > *Mem2) { ReturnValue->Val->Integer = 1; return; }
|
||||
}
|
||||
|
||||
|
||||
ReturnValue->Val->Integer = 0;
|
||||
}
|
||||
#endif
|
||||
|
|
42
debug.c
42
debug.c
|
@ -19,11 +19,9 @@ void DebugCleanup(Picoc *pc)
|
|||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
int Count;
|
||||
|
||||
for (Count = 0; Count < pc->BreakpointTable.Size; Count++)
|
||||
{
|
||||
for (Entry = pc->BreakpointHashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
|
||||
for (Count = 0; Count < pc->BreakpointTable.Size; Count++) {
|
||||
for (Entry = pc->BreakpointHashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
HeapFreeMem(pc, Entry);
|
||||
}
|
||||
|
@ -36,13 +34,12 @@ static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser,
|
|||
struct TableEntry *Entry;
|
||||
Picoc *pc = Parser->pc;
|
||||
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
|
||||
|
||||
for (Entry = pc->BreakpointHashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
|
||||
{
|
||||
|
||||
for (Entry = pc->BreakpointHashTable[HashValue]; 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 */
|
||||
}
|
||||
|
||||
|
||||
*AddAt = HashValue; /* didn't find it in the chain */
|
||||
return NULL;
|
||||
}
|
||||
|
@ -53,14 +50,13 @@ void DebugSetBreakpoint(struct ParseState *Parser)
|
|||
int AddAt;
|
||||
struct TableEntry *FoundEntry = DebugTableSearchBreakpoint(Parser, &AddAt);
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
if (FoundEntry == NULL)
|
||||
{
|
||||
|
||||
if (FoundEntry == NULL) {
|
||||
/* add it to the table */
|
||||
struct TableEntry *NewEntry = HeapAllocMem(pc, sizeof(struct TableEntry));
|
||||
if (NewEntry == NULL)
|
||||
ProgramFailNoParser(pc, "out of memory");
|
||||
|
||||
|
||||
NewEntry->p.b.FileName = Parser->FileName;
|
||||
NewEntry->p.b.Line = Parser->Line;
|
||||
NewEntry->p.b.CharacterPos = Parser->CharacterPos;
|
||||
|
@ -76,12 +72,10 @@ int DebugClearBreakpoint(struct ParseState *Parser)
|
|||
struct TableEntry **EntryPtr;
|
||||
Picoc *pc = Parser->pc;
|
||||
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;
|
||||
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;
|
||||
HeapFreeMem(pc, DeleteEntry);
|
||||
pc->BreakpointCount--;
|
||||
|
@ -99,22 +93,20 @@ void DebugCheckStatement(struct ParseState *Parser)
|
|||
int DoBreak = FALSE;
|
||||
int AddAt;
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
|
||||
/* has the user manually pressed break? */
|
||||
if (pc->DebugManualBreak)
|
||||
{
|
||||
if (pc->DebugManualBreak) {
|
||||
PlatformPrintf(pc->CStdOut, "break\n");
|
||||
DoBreak = TRUE;
|
||||
pc->DebugManualBreak = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* is this a breakpoint location? */
|
||||
if (Parser->pc->BreakpointCount != 0 && DebugTableSearchBreakpoint(Parser, &AddAt) != NULL)
|
||||
DoBreak = TRUE;
|
||||
|
||||
|
||||
/* handle a break */
|
||||
if (DoBreak)
|
||||
{
|
||||
if (DoBreak) {
|
||||
PlatformPrintf(pc->CStdOut, "Handling a break\n");
|
||||
PicocParseInteractiveNoStartPrompt(pc, FALSE);
|
||||
}
|
||||
|
|
1273
expression.c
1273
expression.c
File diff suppressed because it is too large
Load diff
77
heap.c
77
heap.c
|
@ -1,7 +1,7 @@
|
|||
/* picoc heap memory allocation. This is a complete (but small) memory
|
||||
* allocator for embedded systems which have no memory allocator. Alternatively
|
||||
* you can define USE_MALLOC_HEAP to use your system's own malloc() allocator */
|
||||
|
||||
|
||||
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -9,11 +9,11 @@
|
|||
void ShowBigList(Picoc *pc)
|
||||
{
|
||||
struct AllocNode *LPos;
|
||||
|
||||
|
||||
printf("Heap: bottom=0x%lx 0x%lx-0x%lx, big freelist=", (long)pc->HeapBottom, (long)&(pc->HeapMemory)[0], (long)&(pc->HeapMemory)[HEAP_SIZE]);
|
||||
for (LPos = pc->FreeListBig; LPos != NULL; LPos = LPos->NextFree)
|
||||
printf("0x%lx:%d ", (long)LPos, LPos->Size);
|
||||
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -23,7 +23,7 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
|
|||
{
|
||||
int Count;
|
||||
int AlignOffset = 0;
|
||||
|
||||
|
||||
#ifdef USE_MALLOC_STACK
|
||||
pc->HeapMemory = malloc(StackOrHeapSize);
|
||||
pc->HeapBottom = NULL; /* the bottom of the (downward-growing) heap */
|
||||
|
@ -45,7 +45,7 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
|
|||
|
||||
while (((unsigned long)&pc->HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0)
|
||||
AlignOffset++;
|
||||
|
||||
|
||||
pc->StackFrame = &(pc->HeapMemory)[AlignOffset];
|
||||
pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset];
|
||||
*(void **)(pc->StackFrame) = NULL;
|
||||
|
@ -73,7 +73,7 @@ void *HeapAllocStack(Picoc *pc, int Size)
|
|||
#endif
|
||||
if (NewTop > (char *)pc->HeapBottom)
|
||||
return NULL;
|
||||
|
||||
|
||||
pc->HeapStackTop = (void *)NewTop;
|
||||
memset((void *)NewMem, '\0', Size);
|
||||
return NewMem;
|
||||
|
@ -94,13 +94,13 @@ int HeapPopStack(Picoc *pc, void *Addr, int Size)
|
|||
int ToLose = MEM_ALIGN(Size);
|
||||
if (ToLose > ((char *)pc->HeapStackTop - (char *)&(pc->HeapMemory)[0]))
|
||||
return FALSE;
|
||||
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("HeapPopStack(0x%lx, %ld) back to 0x%lx\n", (unsigned long)Addr, (unsigned long)MEM_ALIGN(Size), (unsigned long)pc->HeapStackTop - ToLose);
|
||||
#endif
|
||||
pc->HeapStackTop = (void *)((char *)pc->HeapStackTop - ToLose);
|
||||
assert(Addr == NULL || pc->HeapStackTop == Addr);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -118,16 +118,14 @@ void HeapPushStackFrame(Picoc *pc)
|
|||
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
||||
int HeapPopStackFrame(Picoc *pc)
|
||||
{
|
||||
if (*(void **)pc->StackFrame != NULL)
|
||||
{
|
||||
if (*(void **)pc->StackFrame != NULL) {
|
||||
pc->HeapStackTop = pc->StackFrame;
|
||||
pc->StackFrame = *(void **)pc->StackFrame;
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("Popping stack frame back to 0x%lx\n", (unsigned long)pc->HeapStackTop);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -142,19 +140,18 @@ void *HeapAllocMem(Picoc *pc, int Size)
|
|||
int AllocSize = MEM_ALIGN(Size) + MEM_ALIGN(sizeof(NewMem->Size));
|
||||
int Bucket;
|
||||
void *ReturnMem;
|
||||
|
||||
|
||||
if (Size == 0)
|
||||
return NULL;
|
||||
|
||||
|
||||
assert(Size > 0);
|
||||
|
||||
|
||||
/* make sure we have enough space for an AllocNode */
|
||||
if (AllocSize < sizeof(struct AllocNode))
|
||||
AllocSize = sizeof(struct AllocNode);
|
||||
|
||||
|
||||
Bucket = AllocSize >> 2;
|
||||
if (Bucket < FREELIST_BUCKETS && pc->FreeListBucket[Bucket] != NULL)
|
||||
{
|
||||
if (Bucket < FREELIST_BUCKETS && pc->FreeListBucket[Bucket] != NULL) {
|
||||
/* try to allocate from a freelist bucket first */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("allocating %d(%d) from bucket", Size, AllocSize);
|
||||
|
@ -164,19 +161,15 @@ void *HeapAllocMem(Picoc *pc, int Size)
|
|||
pc->FreeListBucket[Bucket] = *(struct AllocNode **)NewMem;
|
||||
assert(pc->FreeListBucket[Bucket] == NULL || ((unsigned long)pc->FreeListBucket[Bucket] >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)pc->FreeListBucket[Bucket] - &(pc->HeapMemory)[0] < HEAP_SIZE));
|
||||
NewMem->Size = AllocSize;
|
||||
}
|
||||
else if (pc->FreeListBig != NULL)
|
||||
{
|
||||
} else if (pc->FreeListBig != NULL) {
|
||||
/* grab the first item from the "big" freelist we can fit in */
|
||||
for (FreeNode = &pc->FreeListBig; *FreeNode != NULL && (*FreeNode)->Size < AllocSize; FreeNode = &(*FreeNode)->NextFree)
|
||||
{}
|
||||
|
||||
if (*FreeNode != NULL)
|
||||
{
|
||||
for (FreeNode = &pc->FreeListBig; *FreeNode != NULL && (*FreeNode)->Size < AllocSize; FreeNode = &(*FreeNode)->NextFree) {
|
||||
}
|
||||
|
||||
if (*FreeNode != NULL) {
|
||||
assert((unsigned long)*FreeNode >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)*FreeNode - &(pc->HeapMemory)[0] < HEAP_SIZE);
|
||||
assert((*FreeNode)->Size < HEAP_SIZE && (*FreeNode)->Size > 0);
|
||||
if ((*FreeNode)->Size < AllocSize + SPLIT_MEM_THRESHOLD)
|
||||
{
|
||||
if ((*FreeNode)->Size < AllocSize + SPLIT_MEM_THRESHOLD) {
|
||||
/* close in size - reduce fragmentation by not splitting */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("allocating %d(%d) from freelist, no split (%d)", Size, AllocSize, (*FreeNode)->Size);
|
||||
|
@ -184,9 +177,7 @@ void *HeapAllocMem(Picoc *pc, int Size)
|
|||
NewMem = *FreeNode;
|
||||
assert((unsigned long)NewMem >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)NewMem - &(pc->HeapMemory)[0] < HEAP_SIZE);
|
||||
*FreeNode = NewMem->NextFree;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* split this big memory chunk */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("allocating %d(%d) from freelist, split chunk (%d)", Size, AllocSize, (*FreeNode)->Size);
|
||||
|
@ -198,21 +189,20 @@ void *HeapAllocMem(Picoc *pc, int Size)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NewMem == NULL)
|
||||
{
|
||||
|
||||
if (NewMem == NULL) {
|
||||
/* couldn't allocate from a freelist - try to increase the size of the heap area */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("allocating %d(%d) at bottom of heap (0x%lx-0x%lx)", Size, AllocSize, (long)((char *)pc->HeapBottom - AllocSize), (long)HeapBottom);
|
||||
#endif
|
||||
if ((char *)pc->HeapBottom - AllocSize < (char *)pc->HeapStackTop)
|
||||
return NULL;
|
||||
|
||||
|
||||
pc->HeapBottom = (void *)((char *)pc->HeapBottom - AllocSize);
|
||||
NewMem = pc->HeapBottom;
|
||||
NewMem->Size = AllocSize;
|
||||
}
|
||||
|
||||
|
||||
ReturnMem = (void *)((char *)NewMem + MEM_ALIGN(sizeof(NewMem->Size)));
|
||||
memset(ReturnMem, '\0', AllocSize - MEM_ALIGN(sizeof(NewMem->Size)));
|
||||
#ifdef DEBUG_HEAP
|
||||
|
@ -230,7 +220,7 @@ void HeapFreeMem(Picoc *pc, void *Mem)
|
|||
#else
|
||||
struct AllocNode *MemNode = (struct AllocNode *)((char *)Mem - MEM_ALIGN(sizeof(MemNode->Size)));
|
||||
int Bucket = MemNode->Size >> 2;
|
||||
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("HeapFreeMem(0x%lx)\n", (unsigned long)Mem);
|
||||
#endif
|
||||
|
@ -238,9 +228,8 @@ void HeapFreeMem(Picoc *pc, void *Mem)
|
|||
assert(MemNode->Size < HEAP_SIZE && MemNode->Size > 0);
|
||||
if (Mem == NULL)
|
||||
return;
|
||||
|
||||
if ((void *)MemNode == pc->HeapBottom)
|
||||
{
|
||||
|
||||
if ((void *)MemNode == pc->HeapBottom) {
|
||||
/* pop it off the bottom of the heap, reducing the heap size */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("freeing %d from bottom of heap\n", MemNode->Size);
|
||||
|
@ -249,9 +238,7 @@ void HeapFreeMem(Picoc *pc, void *Mem)
|
|||
#ifdef DEBUG_HEAP
|
||||
ShowBigList(pc);
|
||||
#endif
|
||||
}
|
||||
else if (Bucket < FREELIST_BUCKETS)
|
||||
{
|
||||
} else if (Bucket < FREELIST_BUCKETS) {
|
||||
/* we can fit it in a bucket */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("freeing %d to bucket\n", MemNode->Size);
|
||||
|
@ -259,9 +246,7 @@ void HeapFreeMem(Picoc *pc, void *Mem)
|
|||
assert(pc->FreeListBucket[Bucket] == NULL || ((unsigned long)pc->FreeListBucket[Bucket] >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)FreeListBucket[Bucket] - &HeapMemory[0] < HEAP_SIZE));
|
||||
*(struct AllocNode **)MemNode = pc->FreeListBucket[Bucket];
|
||||
pc->FreeListBucket[Bucket] = (struct AllocNode *)MemNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* put it in the big memory freelist */
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("freeing %lx:%d to freelist\n", (unsigned long)Mem, MemNode->Size);
|
||||
|
|
30
include.c
30
include.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc include system - can emulate system includes from built-in libraries
|
||||
* or it can include and parse files if the system has files */
|
||||
|
||||
|
||||
#include "picoc.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -32,9 +32,8 @@ void IncludeCleanup(Picoc *pc)
|
|||
{
|
||||
struct IncludeLibrary *ThisInclude = pc->IncludeLibList;
|
||||
struct IncludeLibrary *NextInclude;
|
||||
|
||||
while (ThisInclude != NULL)
|
||||
{
|
||||
|
||||
while (ThisInclude != NULL) {
|
||||
NextInclude = ThisInclude->NextLib;
|
||||
HeapFreeMem(pc, ThisInclude);
|
||||
ThisInclude = NextInclude;
|
||||
|
@ -59,7 +58,7 @@ void IncludeRegister(Picoc *pc, const char *IncludeName, void (*SetupFunction)(P
|
|||
void PicocIncludeAllSystemHeaders(Picoc *pc)
|
||||
{
|
||||
struct IncludeLibrary *ThisInclude = pc->IncludeLibList;
|
||||
|
||||
|
||||
for (; ThisInclude != NULL; ThisInclude = ThisInclude->NextLib)
|
||||
IncludeFile(pc, ThisInclude->IncludeName);
|
||||
}
|
||||
|
@ -68,34 +67,31 @@ void PicocIncludeAllSystemHeaders(Picoc *pc)
|
|||
void IncludeFile(Picoc *pc, char *FileName)
|
||||
{
|
||||
struct IncludeLibrary *LInclude;
|
||||
|
||||
|
||||
/* scan for the include file name to see if it's in our list of predefined includes */
|
||||
for (LInclude = pc->IncludeLibList; LInclude != NULL; LInclude = LInclude->NextLib)
|
||||
{
|
||||
if (strcmp(LInclude->IncludeName, FileName) == 0)
|
||||
{
|
||||
for (LInclude = pc->IncludeLibList; LInclude != NULL; LInclude = LInclude->NextLib) {
|
||||
if (strcmp(LInclude->IncludeName, FileName) == 0) {
|
||||
/* found it - protect against multiple inclusion */
|
||||
if (!VariableDefined(pc, FileName))
|
||||
{
|
||||
if (!VariableDefined(pc, FileName)) {
|
||||
VariableDefine(pc, NULL, FileName, NULL, &pc->VoidType, FALSE);
|
||||
|
||||
|
||||
/* run an extra startup function if there is one */
|
||||
if (LInclude->SetupFunction != NULL)
|
||||
(*LInclude->SetupFunction)(pc);
|
||||
|
||||
|
||||
/* parse the setup C source code - may define types etc. */
|
||||
if (LInclude->SetupCSource != NULL)
|
||||
PicocParse(pc, FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE, FALSE);
|
||||
|
||||
|
||||
/* set up the library functions */
|
||||
if (LInclude->FuncList != NULL)
|
||||
LibraryAdd(pc, &pc->GlobalTable, FileName, LInclude->FuncList);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* not a predefined file, read a real file */
|
||||
PicocPlatformScanFile(pc, FileName);
|
||||
}
|
||||
|
|
525
lex.c
525
lex.c
|
@ -1,4 +1,4 @@
|
|||
/* picoc lexer - converts source text into a tokenised form */
|
||||
/* picoc lexer - converts source text into a tokenised form */
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -87,14 +87,13 @@ static struct ReservedWord ReservedWords[] =
|
|||
void LexInit(Picoc *pc)
|
||||
{
|
||||
int Count;
|
||||
|
||||
|
||||
TableInitTable(&pc->ReservedWordTable, &pc->ReservedWordHashTable[0], sizeof(ReservedWords) / sizeof(struct ReservedWord) * 2, TRUE);
|
||||
|
||||
for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++)
|
||||
{
|
||||
for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) {
|
||||
TableSet(pc, &pc->ReservedWordTable, TableStrRegister(pc, ReservedWords[Count].Word), (struct Value *)&ReservedWords[Count], NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
pc->LexValue.Typ = NULL;
|
||||
pc->LexValue.Val = &pc->LexAnyValue;
|
||||
pc->LexValue.LValueFrom = FALSE;
|
||||
|
@ -119,7 +118,7 @@ void LexCleanup(Picoc *pc)
|
|||
enum LexToken LexCheckReservedWord(Picoc *pc, const char *Word)
|
||||
{
|
||||
struct Value *val;
|
||||
|
||||
|
||||
if (TableGet(&pc->ReservedWordTable, Word, &val, NULL, NULL, NULL))
|
||||
return ((struct ReservedWord *)val)->Token;
|
||||
else
|
||||
|
@ -141,18 +140,16 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
|
|||
char IsLong = 0;
|
||||
char IsUnsigned = 0;
|
||||
#endif
|
||||
|
||||
if (*Lexer->Pos == '0')
|
||||
{
|
||||
|
||||
if (*Lexer->Pos == '0') {
|
||||
/* a binary, octal or hex literal */
|
||||
LEXER_INC(Lexer);
|
||||
if (Lexer->Pos != Lexer->End)
|
||||
{
|
||||
if (*Lexer->Pos == 'x' || *Lexer->Pos == 'X')
|
||||
{ Base = 16; LEXER_INC(Lexer); }
|
||||
else if (*Lexer->Pos == 'b' || *Lexer->Pos == 'B')
|
||||
{ Base = 2; LEXER_INC(Lexer); }
|
||||
else if (*Lexer->Pos != '.')
|
||||
if (Lexer->Pos != Lexer->End) {
|
||||
if (*Lexer->Pos == 'x' || *Lexer->Pos == 'X') {
|
||||
Base = 16; LEXER_INC(Lexer);
|
||||
} else if (*Lexer->Pos == 'b' || *Lexer->Pos == 'B') {
|
||||
Base = 2; LEXER_INC(Lexer);
|
||||
} else if (*Lexer->Pos != '.')
|
||||
Base = 8;
|
||||
}
|
||||
}
|
||||
|
@ -161,69 +158,60 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
|
|||
for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer))
|
||||
Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos);
|
||||
|
||||
if (*Lexer->Pos == 'u' || *Lexer->Pos == 'U')
|
||||
{
|
||||
if (*Lexer->Pos == 'u' || *Lexer->Pos == 'U') {
|
||||
LEXER_INC(Lexer);
|
||||
/* IsUnsigned = 1; */
|
||||
}
|
||||
if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L')
|
||||
{
|
||||
if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L') {
|
||||
LEXER_INC(Lexer);
|
||||
/* IsLong = 1; */
|
||||
}
|
||||
|
||||
|
||||
Value->Typ = &pc->LongType; /* ignored? */
|
||||
Value->Val->LongInteger = Result;
|
||||
|
||||
ResultToken = TokenIntegerConstant;
|
||||
|
||||
|
||||
if (Lexer->Pos == Lexer->End)
|
||||
return ResultToken;
|
||||
|
||||
|
||||
#ifndef NO_FP
|
||||
if (Lexer->Pos == Lexer->End)
|
||||
{
|
||||
if (Lexer->Pos == Lexer->End) {
|
||||
return ResultToken;
|
||||
}
|
||||
|
||||
if (*Lexer->Pos != '.' && *Lexer->Pos != 'e' && *Lexer->Pos != 'E')
|
||||
{
|
||||
|
||||
if (*Lexer->Pos != '.' && *Lexer->Pos != 'e' && *Lexer->Pos != 'E') {
|
||||
return ResultToken;
|
||||
}
|
||||
|
||||
|
||||
Value->Typ = &pc->FPType;
|
||||
FPResult = (double)Result;
|
||||
|
||||
if (*Lexer->Pos == '.')
|
||||
{
|
||||
|
||||
if (*Lexer->Pos == '.') {
|
||||
LEXER_INC(Lexer);
|
||||
for (FPDiv = 1.0/Base; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base)
|
||||
{
|
||||
for (FPDiv = 1.0/Base; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base) {
|
||||
FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv;
|
||||
}
|
||||
}
|
||||
|
||||
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E'))
|
||||
{
|
||||
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E')) {
|
||||
int ExponentSign = 1;
|
||||
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-')
|
||||
{
|
||||
if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-') {
|
||||
ExponentSign = -1;
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
|
||||
Result = 0;
|
||||
while (Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base))
|
||||
{
|
||||
while (Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base)) {
|
||||
Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos);
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
FPResult *= pow((double)Base, (double)Result * ExponentSign);
|
||||
}
|
||||
|
||||
|
||||
Value->Val->FP = FPResult;
|
||||
|
||||
if (*Lexer->Pos == 'f' || *Lexer->Pos == 'F')
|
||||
|
@ -240,28 +228,27 @@ enum LexToken LexGetWord(Picoc *pc, struct LexState *Lexer, struct Value *Value)
|
|||
{
|
||||
const char *StartPos = Lexer->Pos;
|
||||
enum LexToken Token;
|
||||
|
||||
|
||||
do {
|
||||
LEXER_INC(Lexer);
|
||||
} while (Lexer->Pos != Lexer->End && isCident((int)*Lexer->Pos));
|
||||
|
||||
|
||||
Value->Typ = NULL;
|
||||
Value->Val->Identifier = TableStrRegister2(pc, StartPos, Lexer->Pos - StartPos);
|
||||
|
||||
|
||||
Token = LexCheckReservedWord(pc, Value->Val->Identifier);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break;
|
||||
case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break;
|
||||
default: break;
|
||||
switch (Token) {
|
||||
case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break;
|
||||
case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
if (Token != TokenNone)
|
||||
return Token;
|
||||
|
||||
|
||||
if (Lexer->Mode == LexModeHashDefineSpace)
|
||||
Lexer->Mode = LexModeHashDefineSpaceIdent;
|
||||
|
||||
|
||||
return TokenIdentifier;
|
||||
}
|
||||
|
||||
|
@ -272,7 +259,7 @@ unsigned char LexUnEscapeCharacterConstant(const char **From, const char *End, u
|
|||
int CCount;
|
||||
for (CCount = 0; IS_BASE_DIGIT(**From, Base) && CCount < 2; CCount++, (*From)++)
|
||||
Total = Total * Base + GET_BASE_DIGIT(**From);
|
||||
|
||||
|
||||
return Total;
|
||||
}
|
||||
|
||||
|
@ -280,41 +267,39 @@ unsigned char LexUnEscapeCharacterConstant(const char **From, const char *End, u
|
|||
unsigned char LexUnEscapeCharacter(const char **From, const char *End)
|
||||
{
|
||||
unsigned char ThisChar;
|
||||
|
||||
while ( *From != End && **From == '\\' &&
|
||||
|
||||
while ( *From != End && **From == '\\' &&
|
||||
&(*From)[1] != End && (*From)[1] == '\n' )
|
||||
(*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) += 3; /* skip escaped end of lines with CR/LF line termination */
|
||||
|
||||
|
||||
if (*From == End)
|
||||
return '\\';
|
||||
|
||||
if (**From == '\\')
|
||||
{
|
||||
|
||||
if (**From == '\\') {
|
||||
/* it's escaped */
|
||||
(*From)++;
|
||||
if (*From == End)
|
||||
return '\\';
|
||||
|
||||
|
||||
ThisChar = *(*From)++;
|
||||
switch (ThisChar)
|
||||
{
|
||||
case '\\': return '\\';
|
||||
case '\'': return '\'';
|
||||
case '"': return '"';
|
||||
case 'a': return '\a';
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
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;
|
||||
switch (ThisChar) {
|
||||
case '\\': return '\\';
|
||||
case '\'': return '\'';
|
||||
case '"': return '"';
|
||||
case 'a': return '\a';
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
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
|
||||
|
@ -331,45 +316,40 @@ enum LexToken LexGetStringConstant(Picoc *pc, struct LexState *Lexer, struct Val
|
|||
char *EscBufPos;
|
||||
char *RegString;
|
||||
struct Value *ArrayValue;
|
||||
|
||||
while (Lexer->Pos != Lexer->End && (*Lexer->Pos != EndChar || Escape))
|
||||
{
|
||||
|
||||
while (Lexer->Pos != Lexer->End && (*Lexer->Pos != EndChar || Escape)) {
|
||||
/* find the end */
|
||||
if (Escape)
|
||||
{
|
||||
if (Escape) {
|
||||
if (*Lexer->Pos == '\r' && Lexer->Pos+1 != Lexer->End)
|
||||
Lexer->Pos++;
|
||||
|
||||
if (*Lexer->Pos == '\n' && Lexer->Pos+1 != Lexer->End)
|
||||
{
|
||||
|
||||
if (*Lexer->Pos == '\n' && Lexer->Pos+1 != Lexer->End) {
|
||||
Lexer->Line++;
|
||||
Lexer->Pos++;
|
||||
Lexer->CharacterPos = 0;
|
||||
Lexer->EmitExtraNewlines++;
|
||||
}
|
||||
|
||||
|
||||
Escape = FALSE;
|
||||
}
|
||||
else if (*Lexer->Pos == '\\')
|
||||
} else if (*Lexer->Pos == '\\')
|
||||
Escape = TRUE;
|
||||
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
EndPos = Lexer->Pos;
|
||||
|
||||
|
||||
EscBuf = HeapAllocStack(pc, EndPos - StartPos);
|
||||
if (EscBuf == NULL)
|
||||
LexFail(pc, Lexer, "out of memory");
|
||||
|
||||
|
||||
for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;)
|
||||
*EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos);
|
||||
|
||||
|
||||
/* try to find an existing copy of this string literal */
|
||||
RegString = TableStrRegister2(pc, EscBuf, EscBufPos - EscBuf);
|
||||
HeapPopStack(pc, EscBuf, EndPos - StartPos);
|
||||
ArrayValue = VariableStringLiteralGet(pc, RegString);
|
||||
if (ArrayValue == NULL)
|
||||
{
|
||||
if (ArrayValue == NULL) {
|
||||
/* create and store this string literal */
|
||||
ArrayValue = VariableAllocValueAndData(pc, NULL, 0, FALSE, NULL, TRUE);
|
||||
ArrayValue->Typ = pc->CharArrayType;
|
||||
|
@ -382,7 +362,7 @@ enum LexToken LexGetStringConstant(Picoc *pc, struct LexState *Lexer, struct Val
|
|||
Value->Val->Pointer = RegString;
|
||||
if (*Lexer->Pos == EndChar)
|
||||
LEXER_INC(Lexer);
|
||||
|
||||
|
||||
return TokenStringConstant;
|
||||
}
|
||||
|
||||
|
@ -393,7 +373,7 @@ enum LexToken LexGetCharacterConstant(Picoc *pc, struct LexState *Lexer, struct
|
|||
Value->Val->Character = LexUnEscapeCharacter(&Lexer->Pos, Lexer->End);
|
||||
if (Lexer->Pos != Lexer->End && *Lexer->Pos != '\'')
|
||||
LexFail(pc, Lexer, "expected \"'\"");
|
||||
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
return TokenCharacterConstant;
|
||||
}
|
||||
|
@ -401,8 +381,7 @@ enum LexToken LexGetCharacterConstant(Picoc *pc, struct LexState *Lexer, struct
|
|||
/* skip a comment - used while scanning */
|
||||
void LexSkipComment(struct LexState *Lexer, char NextChar, enum LexToken *ReturnToken)
|
||||
{
|
||||
if (NextChar == '*')
|
||||
{
|
||||
if (NextChar == '*') {
|
||||
/* conventional C comment */
|
||||
while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/'))
|
||||
{
|
||||
|
@ -411,14 +390,12 @@ void LexSkipComment(struct LexState *Lexer, char NextChar, enum LexToken *Return
|
|||
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
|
||||
if (Lexer->Pos != Lexer->End)
|
||||
LEXER_INC(Lexer);
|
||||
|
||||
|
||||
Lexer->Mode = LexModeNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* C++ style comment */
|
||||
while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n')
|
||||
LEXER_INC(Lexer);
|
||||
|
@ -431,94 +408,86 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer, struct Value **
|
|||
char ThisChar;
|
||||
char NextChar;
|
||||
enum LexToken GotToken = TokenNone;
|
||||
|
||||
|
||||
/* 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--;
|
||||
return TokenEndOfLine;
|
||||
}
|
||||
|
||||
|
||||
/* scan for a token */
|
||||
do
|
||||
{
|
||||
do {
|
||||
*Value = &pc->LexValue;
|
||||
while (Lexer->Pos != Lexer->End && isspace((int)*Lexer->Pos))
|
||||
{
|
||||
if (*Lexer->Pos == '\n')
|
||||
{
|
||||
while (Lexer->Pos != Lexer->End && isspace((int)*Lexer->Pos)) {
|
||||
if (*Lexer->Pos == '\n') {
|
||||
Lexer->Line++;
|
||||
Lexer->Pos++;
|
||||
Lexer->Mode = LexModeNormal;
|
||||
Lexer->CharacterPos = 0;
|
||||
return TokenEndOfLine;
|
||||
}
|
||||
else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace)
|
||||
} else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace)
|
||||
Lexer->Mode = LexModeHashDefineSpace;
|
||||
|
||||
else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
|
||||
Lexer->Mode = LexModeNormal;
|
||||
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
||||
|
||||
if (Lexer->Pos == Lexer->End || *Lexer->Pos == '\0')
|
||||
return TokenEOF;
|
||||
|
||||
|
||||
ThisChar = *Lexer->Pos;
|
||||
if (isCidstart((int)ThisChar))
|
||||
return LexGetWord(pc, Lexer, *Value);
|
||||
|
||||
|
||||
if (isdigit((int)ThisChar))
|
||||
return LexGetNumber(pc, Lexer, *Value);
|
||||
|
||||
|
||||
NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0;
|
||||
LEXER_INC(Lexer);
|
||||
switch (ThisChar)
|
||||
{
|
||||
case '"': GotToken = LexGetStringConstant(pc, Lexer, *Value, '"'); break;
|
||||
case '\'': GotToken = LexGetCharacterConstant(pc, Lexer, *Value); break;
|
||||
case '(': if (Lexer->Mode == LexModeHashDefineSpaceIdent) GotToken = TokenOpenMacroBracket; else GotToken = TokenOpenBracket; Lexer->Mode = LexModeNormal; break;
|
||||
case ')': GotToken = TokenCloseBracket; break;
|
||||
case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
|
||||
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break;
|
||||
case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); break;
|
||||
case '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break;
|
||||
case '/': if (NextChar == '/' || NextChar == '*') { LEXER_INC(Lexer); LexSkipComment(Lexer, NextChar, &GotToken); } else NEXTIS('=', TokenDivideAssign, TokenSlash); break;
|
||||
case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); break;
|
||||
case '<': if (Lexer->Mode == LexModeHashInclude) GotToken = LexGetStringConstant(pc, Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break;
|
||||
case '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break;
|
||||
case ';': GotToken = TokenSemicolon; break;
|
||||
case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); break;
|
||||
case '|': NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr); break;
|
||||
case '{': GotToken = TokenLeftBrace; break;
|
||||
case '}': GotToken = TokenRightBrace; break;
|
||||
case '[': GotToken = TokenLeftSquareBracket; break;
|
||||
case ']': GotToken = TokenRightSquareBracket; break;
|
||||
case '!': NEXTIS('=', TokenNotEqual, TokenUnaryNot); break;
|
||||
case '^': NEXTIS('=', TokenArithmeticExorAssign, TokenArithmeticExor); break;
|
||||
case '~': GotToken = TokenUnaryExor; break;
|
||||
case ',': GotToken = TokenComma; break;
|
||||
case '.': NEXTISEXACTLY3('.', '.', TokenEllipsis, TokenDot); break;
|
||||
case '?': GotToken = TokenQuestionMark; break;
|
||||
case ':': GotToken = TokenColon; break;
|
||||
default: LexFail(pc, Lexer, "illegal character '%c'", ThisChar); break;
|
||||
switch (ThisChar) {
|
||||
case '"': GotToken = LexGetStringConstant(pc, Lexer, *Value, '"'); break;
|
||||
case '\'': GotToken = LexGetCharacterConstant(pc, Lexer, *Value); break;
|
||||
case '(': if (Lexer->Mode == LexModeHashDefineSpaceIdent) GotToken = TokenOpenMacroBracket; else GotToken = TokenOpenBracket; Lexer->Mode = LexModeNormal; break;
|
||||
case ')': GotToken = TokenCloseBracket; break;
|
||||
case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
|
||||
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break;
|
||||
case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); break;
|
||||
case '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break;
|
||||
case '/': if (NextChar == '/' || NextChar == '*') { LEXER_INC(Lexer); LexSkipComment(Lexer, NextChar, &GotToken); } else NEXTIS('=', TokenDivideAssign, TokenSlash); break;
|
||||
case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); break;
|
||||
case '<': if (Lexer->Mode == LexModeHashInclude) GotToken = LexGetStringConstant(pc, Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break;
|
||||
case '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break;
|
||||
case ';': GotToken = TokenSemicolon; break;
|
||||
case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); break;
|
||||
case '|': NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr); break;
|
||||
case '{': GotToken = TokenLeftBrace; break;
|
||||
case '}': GotToken = TokenRightBrace; break;
|
||||
case '[': GotToken = TokenLeftSquareBracket; break;
|
||||
case ']': GotToken = TokenRightSquareBracket; break;
|
||||
case '!': NEXTIS('=', TokenNotEqual, TokenUnaryNot); break;
|
||||
case '^': NEXTIS('=', TokenArithmeticExorAssign, TokenArithmeticExor); break;
|
||||
case '~': GotToken = TokenUnaryExor; break;
|
||||
case ',': GotToken = TokenComma; break;
|
||||
case '.': NEXTISEXACTLY3('.', '.', TokenEllipsis, TokenDot); break;
|
||||
case '?': GotToken = TokenQuestionMark; break;
|
||||
case ':': GotToken = TokenColon; break;
|
||||
default: LexFail(pc, Lexer, "illegal character '%c'", ThisChar); break;
|
||||
}
|
||||
} while (GotToken == TokenNone);
|
||||
|
||||
|
||||
return GotToken;
|
||||
}
|
||||
|
||||
/* what size value goes with each token */
|
||||
int LexTokenSize(enum LexToken Token)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIdentifier: case TokenStringConstant: return sizeof(char *);
|
||||
case TokenIntegerConstant: return sizeof(long);
|
||||
case TokenCharacterConstant: return sizeof(unsigned char);
|
||||
case TokenFPConstant: return sizeof(double);
|
||||
default: return 0;
|
||||
switch (Token) {
|
||||
case TokenIdentifier: case TokenStringConstant: return sizeof(char *);
|
||||
case TokenIntegerConstant: return sizeof(long);
|
||||
case TokenCharacterConstant: return sizeof(unsigned char);
|
||||
case TokenFPConstant: return sizeof(double);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,16 +499,15 @@ void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
|||
struct Value *GotValue;
|
||||
int MemUsed = 0;
|
||||
int ValueSize;
|
||||
int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 16;
|
||||
int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 16;
|
||||
void *TokenSpace = HeapAllocStack(pc, ReserveSpace);
|
||||
char *TokenPos = (char *)TokenSpace;
|
||||
int LastCharacterPos = 0;
|
||||
|
||||
if (TokenSpace == NULL)
|
||||
LexFail(pc, Lexer, "out of memory");
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
do {
|
||||
/* store the token at the end of the stack area */
|
||||
Token = LexScanGetToken(pc, Lexer, &GotValue);
|
||||
|
||||
|
@ -555,22 +523,21 @@ void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
|||
MemUsed++;
|
||||
|
||||
ValueSize = LexTokenSize(Token);
|
||||
if (ValueSize > 0)
|
||||
{
|
||||
if (ValueSize > 0) {
|
||||
/* store a value as well */
|
||||
memcpy((void *)TokenPos, (void *)GotValue->Val, ValueSize);
|
||||
TokenPos += ValueSize;
|
||||
MemUsed += ValueSize;
|
||||
}
|
||||
|
||||
|
||||
LastCharacterPos = Lexer->CharacterPos;
|
||||
|
||||
|
||||
} while (Token != TokenEOF);
|
||||
|
||||
|
||||
HeapMem = HeapAllocMem(pc, MemUsed);
|
||||
if (HeapMem == NULL)
|
||||
LexFail(pc, Lexer, "out of memory");
|
||||
|
||||
|
||||
assert(ReserveSpace >= MemUsed);
|
||||
memcpy(HeapMem, TokenSpace, MemUsed);
|
||||
HeapPopStack(pc, TokenSpace, ReserveSpace);
|
||||
|
@ -585,7 +552,7 @@ void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
|||
#endif
|
||||
if (TokenLen)
|
||||
*TokenLen = MemUsed;
|
||||
|
||||
|
||||
return HeapMem;
|
||||
}
|
||||
|
||||
|
@ -593,7 +560,7 @@ void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
|
|||
void *LexAnalyse(Picoc *pc, const char *FileName, const char *Source, int SourceLen, int *TokenLen)
|
||||
{
|
||||
struct LexState Lexer;
|
||||
|
||||
|
||||
Lexer.Pos = Source;
|
||||
Lexer.End = Source + SourceLen;
|
||||
Lexer.Line = 1;
|
||||
|
@ -602,7 +569,7 @@ void *LexAnalyse(Picoc *pc, const char *FileName, const char *Source, int Source
|
|||
Lexer.EmitExtraNewlines = 0;
|
||||
Lexer.CharacterPos = 1;
|
||||
Lexer.SourceText = Source;
|
||||
|
||||
|
||||
return LexTokenise(pc, &Lexer, TokenLen);
|
||||
}
|
||||
|
||||
|
@ -629,72 +596,61 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, in
|
|||
int ValueSize;
|
||||
char *Prompt = NULL;
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
do {
|
||||
/* get the next token */
|
||||
if (Parser->Pos == NULL && pc->InteractiveHead != NULL)
|
||||
Parser->Pos = pc->InteractiveHead->Tokens;
|
||||
|
||||
if (Parser->FileName != pc->StrEmpty || pc->InteractiveHead != NULL)
|
||||
{
|
||||
|
||||
if (Parser->FileName != pc->StrEmpty || pc->InteractiveHead != NULL) {
|
||||
/* skip leading newlines */
|
||||
while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine)
|
||||
{
|
||||
while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine) {
|
||||
Parser->Line++;
|
||||
Parser->Pos += TOKEN_DATA_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
char LineBuffer[LINEBUFFER_MAX];
|
||||
void *LineTokens;
|
||||
int LineBytes;
|
||||
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 */
|
||||
if (pc->LexUseStatementPrompt)
|
||||
{
|
||||
if (pc->LexUseStatementPrompt) {
|
||||
Prompt = INTERACTIVE_PROMPT_STATEMENT;
|
||||
pc->LexUseStatementPrompt = FALSE;
|
||||
}
|
||||
else
|
||||
} else
|
||||
Prompt = INTERACTIVE_PROMPT_LINE;
|
||||
|
||||
|
||||
if (PlatformGetLine(&LineBuffer[0], LINEBUFFER_MAX, Prompt) == NULL)
|
||||
return TokenEOF;
|
||||
|
||||
/* put the new line at the end of the linked list of interactive lines */
|
||||
/* put the new line at the end of the linked list of interactive lines */
|
||||
LineTokens = LexAnalyse(pc, pc->StrEmpty, &LineBuffer[0], strlen(LineBuffer), &LineBytes);
|
||||
LineNode = VariableAlloc(pc, Parser, sizeof(struct TokenLine), TRUE);
|
||||
LineNode->Tokens = LineTokens;
|
||||
LineNode->NumBytes = LineBytes;
|
||||
if (pc->InteractiveHead == NULL)
|
||||
{
|
||||
if (pc->InteractiveHead == NULL) {
|
||||
/* start a new list */
|
||||
pc->InteractiveHead = LineNode;
|
||||
Parser->Line = 1;
|
||||
Parser->CharacterPos = 0;
|
||||
}
|
||||
else
|
||||
} else
|
||||
pc->InteractiveTail->Next = LineNode;
|
||||
|
||||
pc->InteractiveTail = LineNode;
|
||||
pc->InteractiveCurrentLine = LineNode;
|
||||
Parser->Pos = LineTokens;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* 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 */
|
||||
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); }
|
||||
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 != NULL);
|
||||
|
@ -709,23 +665,20 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, in
|
|||
|
||||
Parser->CharacterPos = *((unsigned char *)Parser->Pos + 1);
|
||||
ValueSize = LexTokenSize(Token);
|
||||
if (ValueSize > 0)
|
||||
{
|
||||
if (ValueSize > 0) {
|
||||
/* this token requires a value - unpack it */
|
||||
if (Value != NULL)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenStringConstant: pc->LexValue.Typ = pc->CharPtrType; break;
|
||||
case TokenIdentifier: pc->LexValue.Typ = NULL; break;
|
||||
case TokenIntegerConstant: pc->LexValue.Typ = &pc->LongType; break;
|
||||
case TokenCharacterConstant: pc->LexValue.Typ = &pc->CharType; break;
|
||||
if (Value != NULL) {
|
||||
switch (Token) {
|
||||
case TokenStringConstant: pc->LexValue.Typ = pc->CharPtrType; break;
|
||||
case TokenIdentifier: pc->LexValue.Typ = NULL; break;
|
||||
case TokenIntegerConstant: pc->LexValue.Typ = &pc->LongType; break;
|
||||
case TokenCharacterConstant: pc->LexValue.Typ = &pc->CharType; break;
|
||||
#ifndef NO_FP
|
||||
case TokenFPConstant: pc->LexValue.Typ = &pc->FPType; break;
|
||||
case TokenFPConstant: pc->LexValue.Typ = &pc->FPType; break;
|
||||
#endif
|
||||
default: break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
memcpy((void *)pc->LexValue.Val, (void *)((char *)Parser->Pos + TOKEN_DATA_OFFSET), ValueSize);
|
||||
pc->LexValue.ValOnHeap = FALSE;
|
||||
pc->LexValue.ValOnStack = FALSE;
|
||||
|
@ -733,16 +686,14 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, in
|
|||
pc->LexValue.LValueFrom = NULL;
|
||||
*Value = &pc->LexValue;
|
||||
}
|
||||
|
||||
|
||||
if (IncPos)
|
||||
Parser->Pos += ValueSize + TOKEN_DATA_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (IncPos && Token != TokenEOF)
|
||||
Parser->Pos += TOKEN_DATA_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_LEXER
|
||||
printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos);
|
||||
#endif
|
||||
|
@ -765,18 +716,17 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot)
|
|||
struct Value *SavedValue;
|
||||
int IsDefined;
|
||||
enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE);
|
||||
|
||||
|
||||
if (Token != TokenIdentifier)
|
||||
ProgramFail(Parser, "identifier expected");
|
||||
|
||||
|
||||
/* is the identifier defined? */
|
||||
IsDefined = TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier, &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 */
|
||||
Parser->HashIfEvaluateToLevel++;
|
||||
}
|
||||
|
||||
|
||||
Parser->HashIfLevel++;
|
||||
}
|
||||
|
||||
|
@ -789,29 +739,27 @@ void LexHashIf(struct ParseState *Parser)
|
|||
struct ParseState MacroParser;
|
||||
enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE);
|
||||
|
||||
if (Token == TokenIdentifier)
|
||||
{
|
||||
if (Token == TokenIdentifier) {
|
||||
/* look up a value from a macro definition */
|
||||
if (!TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL))
|
||||
ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier);
|
||||
|
||||
|
||||
if (SavedValue->Typ->Base != TypeMacro)
|
||||
ProgramFail(Parser, "value expected");
|
||||
|
||||
|
||||
ParserCopy(&MacroParser, &SavedValue->Val->MacroDef.Body);
|
||||
Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE);
|
||||
}
|
||||
|
||||
|
||||
if (Token != TokenCharacterConstant && Token != TokenIntegerConstant)
|
||||
ProgramFail(Parser, "value expected");
|
||||
|
||||
|
||||
/* 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 */
|
||||
Parser->HashIfEvaluateToLevel++;
|
||||
}
|
||||
|
||||
|
||||
Parser->HashIfLevel++;
|
||||
}
|
||||
|
||||
|
@ -820,13 +768,11 @@ void LexHashElse(struct ParseState *Parser)
|
|||
{
|
||||
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel - 1)
|
||||
Parser->HashIfEvaluateToLevel++; /* #if was not active, make this next section active */
|
||||
|
||||
else if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel)
|
||||
{
|
||||
else if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel) {
|
||||
/* #if was active, now go inactive */
|
||||
if (Parser->HashIfLevel == 0)
|
||||
ProgramFail(Parser, "#else without #if");
|
||||
|
||||
|
||||
Parser->HashIfEvaluateToLevel--;
|
||||
}
|
||||
}
|
||||
|
@ -846,23 +792,23 @@ void LexHashEndif(struct ParseState *Parser)
|
|||
void LexPrintToken(enum LexToken Token)
|
||||
{
|
||||
char* TokenNames[] = {
|
||||
/* 0x00 */ "None",
|
||||
/* 0x00 */ "None",
|
||||
/* 0x01 */ "Comma",
|
||||
/* 0x02 */ "Assign", "AddAssign", "SubtractAssign", "MultiplyAssign", "DivideAssign", "ModulusAssign",
|
||||
/* 0x08 */ "ShiftLeftAssign", "ShiftRightAssign", "ArithmeticAndAssign", "ArithmeticOrAssign", "ArithmeticExorAssign",
|
||||
/* 0x0d */ "QuestionMark", "Colon",
|
||||
/* 0x0f */ "LogicalOr",
|
||||
/* 0x10 */ "LogicalAnd",
|
||||
/* 0x11 */ "ArithmeticOr",
|
||||
/* 0x12 */ "ArithmeticExor",
|
||||
/* 0x13 */ "Ampersand",
|
||||
/* 0x14 */ "Equal", "NotEqual",
|
||||
/* 0x0d */ "QuestionMark", "Colon",
|
||||
/* 0x0f */ "LogicalOr",
|
||||
/* 0x10 */ "LogicalAnd",
|
||||
/* 0x11 */ "ArithmeticOr",
|
||||
/* 0x12 */ "ArithmeticExor",
|
||||
/* 0x13 */ "Ampersand",
|
||||
/* 0x14 */ "Equal", "NotEqual",
|
||||
/* 0x16 */ "LessThan", "GreaterThan", "LessEqual", "GreaterEqual",
|
||||
/* 0x1a */ "ShiftLeft", "ShiftRight",
|
||||
/* 0x1c */ "Plus", "Minus",
|
||||
/* 0x1a */ "ShiftLeft", "ShiftRight",
|
||||
/* 0x1c */ "Plus", "Minus",
|
||||
/* 0x1e */ "Asterisk", "Slash", "Modulus",
|
||||
/* 0x21 */ "Increment", "Decrement", "UnaryNot", "UnaryExor", "Sizeof", "Cast",
|
||||
/* 0x27 */ "LeftSquareBracket", "RightSquareBracket", "Dot", "Arrow",
|
||||
/* 0x27 */ "LeftSquareBracket", "RightSquareBracket", "Dot", "Arrow",
|
||||
/* 0x2b */ "OpenBracket", "CloseBracket",
|
||||
/* 0x2d */ "Identifier", "IntegerConstant", "FPConstant", "StringConstant", "CharacterConstant",
|
||||
/* 0x32 */ "Semicolon", "Ellipsis",
|
||||
|
@ -884,30 +830,28 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
|
|||
{
|
||||
enum LexToken Token;
|
||||
int TryNextToken;
|
||||
|
||||
|
||||
/* implements the pre-processor #if commands */
|
||||
do
|
||||
{
|
||||
do {
|
||||
int WasPreProcToken = TRUE;
|
||||
|
||||
Token = LexGetRawToken(Parser, Value, IncPos);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenHashIfdef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, FALSE); break;
|
||||
case TokenHashIfndef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, TRUE); break;
|
||||
case TokenHashIf: LexHashIncPos(Parser, IncPos); LexHashIf(Parser); break;
|
||||
case TokenHashElse: LexHashIncPos(Parser, IncPos); LexHashElse(Parser); break;
|
||||
case TokenHashEndif: LexHashIncPos(Parser, IncPos); LexHashEndif(Parser); break;
|
||||
default: WasPreProcToken = FALSE; break;
|
||||
switch (Token) {
|
||||
case TokenHashIfdef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, FALSE); break;
|
||||
case TokenHashIfndef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, TRUE); break;
|
||||
case TokenHashIf: LexHashIncPos(Parser, IncPos); LexHashIf(Parser); break;
|
||||
case TokenHashElse: LexHashIncPos(Parser, IncPos); LexHashElse(Parser); break;
|
||||
case TokenHashEndif: LexHashIncPos(Parser, IncPos); LexHashEndif(Parser); break;
|
||||
default: WasPreProcToken = FALSE; break;
|
||||
}
|
||||
|
||||
/* if we're going to reject this token, increment the token pointer to the next one */
|
||||
TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel && Token != TokenEOF) || WasPreProcToken;
|
||||
if (!IncPos && TryNextToken)
|
||||
LexGetRawToken(Parser, NULL, TRUE);
|
||||
|
||||
|
||||
} while (TryNextToken);
|
||||
|
||||
|
||||
return Token;
|
||||
}
|
||||
|
||||
|
@ -920,8 +864,7 @@ enum LexToken LexRawPeekToken(struct ParseState *Parser)
|
|||
/* find the end of the line */
|
||||
void LexToEndOfLine(struct ParseState *Parser)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
while (TRUE) {
|
||||
enum LexToken Token = (enum LexToken)*(unsigned char *)Parser->Pos;
|
||||
if (Token == TokenEndOfLine || Token == TokenEOF)
|
||||
return;
|
||||
|
@ -940,44 +883,37 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
|
|||
unsigned char *NewTokenPos;
|
||||
struct TokenLine *ILine;
|
||||
Picoc *pc = StartParser->pc;
|
||||
|
||||
if (pc->InteractiveHead == NULL)
|
||||
{
|
||||
|
||||
if (pc->InteractiveHead == NULL) {
|
||||
/* non-interactive mode - copy the tokens */
|
||||
MemSize = EndParser->Pos - StartParser->Pos;
|
||||
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE);
|
||||
memcpy(NewTokens, (void *)StartParser->Pos, MemSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* 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)
|
||||
{} /* find the line we just counted */
|
||||
|
||||
if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes])
|
||||
{
|
||||
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 */
|
||||
|
||||
if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]) {
|
||||
/* all on a single line */
|
||||
MemSize = EndParser->Pos - StartParser->Pos;
|
||||
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE);
|
||||
memcpy(NewTokens, (void *)StartParser->Pos, MemSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* it's spread across multiple lines */
|
||||
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)
|
||||
MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET;
|
||||
|
||||
|
||||
assert(ILine != NULL);
|
||||
MemSize += EndParser->Pos - &ILine->Tokens[0];
|
||||
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE);
|
||||
|
||||
|
||||
CopySize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
|
||||
memcpy(NewTokens, Pos, 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);
|
||||
NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET;
|
||||
}
|
||||
|
@ -985,19 +921,18 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
|
|||
memcpy(NewTokenPos, &ILine->Tokens[0], EndParser->Pos - &ILine->Tokens[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NewTokens[MemSize] = (unsigned char)TokenEndOfFunction;
|
||||
|
||||
|
||||
return NewTokens;
|
||||
}
|
||||
|
||||
/* indicate that we've completed up to this point in the interactive input and free expired tokens */
|
||||
void LexInteractiveClear(Picoc *pc, struct ParseState *Parser)
|
||||
{
|
||||
while (pc->InteractiveHead != NULL)
|
||||
{
|
||||
while (pc->InteractiveHead != NULL) {
|
||||
struct TokenLine *NextLine = pc->InteractiveHead->Next;
|
||||
|
||||
|
||||
HeapFreeMem(pc, pc->InteractiveHead->Tokens);
|
||||
HeapFreeMem(pc, pc->InteractiveHead);
|
||||
pc->InteractiveHead = NextLine;
|
||||
|
@ -1005,24 +940,22 @@ void LexInteractiveClear(Picoc *pc, struct ParseState *Parser)
|
|||
|
||||
if (Parser != NULL)
|
||||
Parser->Pos = NULL;
|
||||
|
||||
|
||||
pc->InteractiveTail = NULL;
|
||||
}
|
||||
|
||||
/* indicate that we've completed up to this point in the interactive input and free expired tokens */
|
||||
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 */
|
||||
struct TokenLine *NextLine = pc->InteractiveHead->Next;
|
||||
|
||||
|
||||
HeapFreeMem(pc, pc->InteractiveHead->Tokens);
|
||||
HeapFreeMem(pc, pc->InteractiveHead);
|
||||
pc->InteractiveHead = NextLine;
|
||||
|
||||
if (pc->InteractiveHead == NULL)
|
||||
{
|
||||
|
||||
if (pc->InteractiveHead == NULL) {
|
||||
/* we've emptied the list */
|
||||
Parser->Pos = NULL;
|
||||
pc->InteractiveTail = NULL;
|
||||
|
|
36
picoc.c
36
picoc.c
|
@ -20,8 +20,7 @@ int main(int argc, char **argv)
|
|||
int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE;
|
||||
Picoc pc;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf(PICOC_VERSION " \n"
|
||||
"Format: picoc <file1.c>... [- <arg1>...] : run a program (calls main() to start it)\n"
|
||||
" picoc -s <file1.c>... [- <arg1>...] : script mode - runs the program without calling main()\n"
|
||||
|
@ -31,22 +30,17 @@ int main(int argc, char **argv)
|
|||
|
||||
PicocInitialise(&pc, StackSize);
|
||||
|
||||
if (strcmp(argv[ParamCount], "-s") == 0 || strcmp(argv[ParamCount], "-m") == 0)
|
||||
{
|
||||
if (strcmp(argv[ParamCount], "-s") == 0 || strcmp(argv[ParamCount], "-m") == 0) {
|
||||
DontRunMain = TRUE;
|
||||
PicocIncludeAllSystemHeaders(&pc);
|
||||
ParamCount++;
|
||||
}
|
||||
|
||||
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0)
|
||||
{
|
||||
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0) {
|
||||
PicocIncludeAllSystemHeaders(&pc);
|
||||
PicocParseInteractive(&pc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PicocPlatformSetExitPoint(&pc))
|
||||
{
|
||||
} else {
|
||||
if (PicocPlatformSetExitPoint(&pc)) {
|
||||
PicocCleanup(&pc);
|
||||
return pc.PicocExitValue;
|
||||
}
|
||||
|
@ -62,11 +56,12 @@ int main(int argc, char **argv)
|
|||
return pc.PicocExitValue;
|
||||
}
|
||||
#elif defined(SURVEYOR_HOST)
|
||||
# define HEAP_SIZE C_HEAPSIZE
|
||||
# include <setjmp.h>
|
||||
# include "../srv.h"
|
||||
# include "../print.h"
|
||||
# include "../string.h"
|
||||
|
||||
#define HEAP_SIZE C_HEAPSIZE
|
||||
#include <setjmp.h>
|
||||
#include "../srv.h"
|
||||
#include "../print.h"
|
||||
#include "../string.h"
|
||||
|
||||
int picoc(char *SourceStr)
|
||||
{
|
||||
|
@ -74,12 +69,9 @@ int picoc(char *SourceStr)
|
|||
|
||||
PicocInitialise(HEAP_SIZE);
|
||||
|
||||
if (SourceStr)
|
||||
{
|
||||
for (pos = SourceStr; *pos != 0; pos++)
|
||||
{
|
||||
if (*pos == 0x1a)
|
||||
{
|
||||
if (SourceStr) {
|
||||
for (pos = SourceStr; *pos != 0; pos++) {
|
||||
if (*pos == 0x1a) {
|
||||
*pos = 0x20;
|
||||
}
|
||||
}
|
||||
|
|
72
platform.c
72
platform.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc's interface to the underlying platform. most platform-specific code
|
||||
* is in platform/platform_XX.c and platform/library_XX.c */
|
||||
|
||||
|
||||
#include "picoc.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
@ -59,29 +59,25 @@ void PicocCallMain(Picoc *pc, int argc, char **argv)
|
|||
|
||||
if (!VariableDefined(pc, TableStrRegister(pc, "main")))
|
||||
ProgramFailNoParser(pc, "main() is not defined");
|
||||
|
||||
|
||||
VariableGet(pc, NULL, TableStrRegister(pc, "main"), &FuncValue);
|
||||
if (FuncValue->Typ->Base != TypeFunction)
|
||||
ProgramFailNoParser(pc, "main is not a function - can't call it");
|
||||
|
||||
if (FuncValue->Val->FuncDef.NumParams != 0)
|
||||
{
|
||||
if (FuncValue->Val->FuncDef.NumParams != 0) {
|
||||
/* define the arguments */
|
||||
VariableDefinePlatformVar(pc, NULL, "__argc", &pc->IntType, (union AnyValue *)&argc, FALSE);
|
||||
VariableDefinePlatformVar(pc, NULL, "__argv", pc->CharPtrPtrType, (union AnyValue *)&argv, FALSE);
|
||||
}
|
||||
|
||||
if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType)
|
||||
{
|
||||
if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) {
|
||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE);
|
||||
else
|
||||
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType, (union AnyValue *)&pc->PicocExitValue, TRUE);
|
||||
|
||||
|
||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE, TRUE);
|
||||
else
|
||||
|
@ -96,38 +92,33 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName, const char *
|
|||
const char *LinePos;
|
||||
const char *CPos;
|
||||
int CCount;
|
||||
|
||||
if (SourceText != NULL)
|
||||
{
|
||||
|
||||
if (SourceText != NULL) {
|
||||
/* 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')
|
||||
LineCount++;
|
||||
}
|
||||
|
||||
|
||||
/* display the line */
|
||||
for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++)
|
||||
PrintCh(*CPos, Stream);
|
||||
PrintCh('\n', Stream);
|
||||
|
||||
|
||||
/* 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')
|
||||
PrintCh('\t', Stream);
|
||||
else
|
||||
PrintCh(' ', Stream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* 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++)
|
||||
PrintCh(' ', Stream);
|
||||
}
|
||||
PlatformPrintf(Stream, "^\n%s:%d:%d ", FileName, Line, CharacterPos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* exit with a message */
|
||||
|
@ -159,18 +150,18 @@ void ProgramFailNoParser(Picoc *pc, const char *Message, ...)
|
|||
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo)
|
||||
{
|
||||
IOFILE *Stream = Parser->pc->CStdOut;
|
||||
|
||||
|
||||
PrintSourceTextErrorLine(Parser->pc->CStdOut, Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos);
|
||||
PlatformPrintf(Stream, "can't %s ", (FuncName == NULL) ? "assign" : "set");
|
||||
|
||||
PlatformPrintf(Stream, "can't %s ", (FuncName == NULL) ? "assign" : "set");
|
||||
|
||||
if (Type1 != NULL)
|
||||
PlatformPrintf(Stream, Format, Type1, Type2);
|
||||
else
|
||||
PlatformPrintf(Stream, Format, Num1, Num2);
|
||||
|
||||
|
||||
if (FuncName != NULL)
|
||||
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName);
|
||||
|
||||
|
||||
PlatformPrintf(Stream, "\n");
|
||||
PlatformExit(Parser->pc, 1);
|
||||
}
|
||||
|
@ -192,7 +183,7 @@ void LexFail(Picoc *pc, struct LexState *Lexer, const char *Message, ...)
|
|||
void PlatformPrintf(IOFILE *Stream, const char *Format, ...)
|
||||
{
|
||||
va_list Args;
|
||||
|
||||
|
||||
va_start(Args, Format);
|
||||
PlatformVPrintf(Stream, Format, Args);
|
||||
va_end(Args);
|
||||
|
@ -201,14 +192,11 @@ void PlatformPrintf(IOFILE *Stream, const char *Format, ...)
|
|||
void PlatformVPrintf(IOFILE *Stream, const char *Format, va_list Args)
|
||||
{
|
||||
const char *FPos;
|
||||
|
||||
for (FPos = Format; *FPos != '\0'; FPos++)
|
||||
{
|
||||
if (*FPos == '%')
|
||||
{
|
||||
|
||||
for (FPos = Format; *FPos != '\0'; FPos++) {
|
||||
if (*FPos == '%') {
|
||||
FPos++;
|
||||
switch (*FPos)
|
||||
{
|
||||
switch (*FPos) {
|
||||
case 's': PrintStr(va_arg(Args, char *), Stream); break;
|
||||
case 'd': PrintSimpleInt(va_arg(Args, int), Stream); break;
|
||||
case 'c': PrintCh(va_arg(Args, int), Stream); break;
|
||||
|
@ -230,16 +218,12 @@ void PlatformVPrintf(IOFILE *Stream, const char *Format, va_list Args)
|
|||
char *PlatformMakeTempName(Picoc *pc, char *TempNameBuffer)
|
||||
{
|
||||
int CPos = 5;
|
||||
|
||||
while (CPos > 1)
|
||||
{
|
||||
if (TempNameBuffer[CPos] < '9')
|
||||
{
|
||||
|
||||
while (CPos > 1) {
|
||||
if (TempNameBuffer[CPos] < '9') {
|
||||
TempNameBuffer[CPos]++;
|
||||
return TableStrRegister(pc, TempNameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
TempNameBuffer[CPos] = '0';
|
||||
CPos--;
|
||||
}
|
||||
|
|
66
table.c
66
table.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc hash table module. This hash table code is used for both symbol tables
|
||||
* and the shared string table. */
|
||||
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
/* initialise the shared string system */
|
||||
|
@ -16,15 +16,14 @@ static unsigned int TableHash(const char *Key, int Len)
|
|||
unsigned int Hash = Len;
|
||||
int Offset;
|
||||
int Count;
|
||||
|
||||
for (Count = 0, Offset = 8; Count < Len; Count++, Offset+=7)
|
||||
{
|
||||
|
||||
for (Count = 0, Offset = 8; Count < Len; Count++, Offset+=7) {
|
||||
if (Offset > sizeof(unsigned int) * 8 - 7)
|
||||
Offset -= sizeof(unsigned int) * 8 - 6;
|
||||
|
||||
|
||||
Hash ^= *Key++ << Offset;
|
||||
}
|
||||
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
|
@ -42,26 +41,24 @@ static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *A
|
|||
{
|
||||
struct TableEntry *Entry;
|
||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
|
||||
{
|
||||
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) {
|
||||
if (Entry->p.v.Key == Key)
|
||||
return Entry; /* found */
|
||||
}
|
||||
|
||||
|
||||
*AddAt = HashValue; /* didn't find it in the chain */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set an identifier to a value. returns FALSE if it already exists.
|
||||
/* set an identifier to a value. returns FALSE if it already exists.
|
||||
* Key must be a shared string from TableStrRegister() */
|
||||
int TableSet(Picoc *pc, struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn)
|
||||
{
|
||||
int 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);
|
||||
NewEntry->DeclFileName = DeclFileName;
|
||||
NewEntry->DeclLine = DeclLine;
|
||||
|
@ -76,7 +73,7 @@ int TableSet(Picoc *pc, struct Table *Tbl, char *Key, struct Value *Val, const c
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* find a value in a table. returns FALSE if not found.
|
||||
/* find a value in a table. returns FALSE if not found.
|
||||
* Key must be a shared string from TableStrRegister() */
|
||||
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn)
|
||||
{
|
||||
|
@ -84,16 +81,15 @@ int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char
|
|||
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
|
||||
if (FoundEntry == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
||||
*Val = FoundEntry->p.v.Val;
|
||||
|
||||
if (DeclFileName != NULL)
|
||||
{
|
||||
|
||||
if (DeclFileName != NULL) {
|
||||
*DeclFileName = FoundEntry->DeclFileName;
|
||||
*DeclLine = FoundEntry->DeclLine;
|
||||
*DeclColumn = FoundEntry->DeclColumn;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -102,11 +98,9 @@ struct Value *TableDelete(Picoc *pc, struct Table *Tbl, const char *Key)
|
|||
{
|
||||
struct TableEntry **EntryPtr;
|
||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||
|
||||
for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next)
|
||||
{
|
||||
if ((*EntryPtr)->p.v.Key == Key)
|
||||
{
|
||||
|
||||
for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
||||
if ((*EntryPtr)->p.v.Key == Key) {
|
||||
struct TableEntry *DeleteEntry = *EntryPtr;
|
||||
struct Value *Val = DeleteEntry->p.v.Val;
|
||||
*EntryPtr = DeleteEntry->Next;
|
||||
|
@ -124,13 +118,12 @@ static struct TableEntry *TableSearchIdentifier(struct Table *Tbl, const char *K
|
|||
{
|
||||
struct TableEntry *Entry;
|
||||
int HashValue = TableHash(Key, Len) % Tbl->Size;
|
||||
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
|
||||
{
|
||||
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) {
|
||||
if (strncmp(&Entry->p.Key[0], (char *)Key, Len) == 0 && Entry->p.Key[Len] == '\0')
|
||||
return Entry; /* found */
|
||||
}
|
||||
|
||||
|
||||
*AddAt = HashValue; /* didn't find it in the chain */
|
||||
return NULL;
|
||||
}
|
||||
|
@ -140,15 +133,14 @@ char *TableSetIdentifier(Picoc *pc, struct Table *Tbl, const char *Ident, int Id
|
|||
{
|
||||
int AddAt;
|
||||
struct TableEntry *FoundEntry = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt);
|
||||
|
||||
|
||||
if (FoundEntry != NULL)
|
||||
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);
|
||||
if (NewEntry == NULL)
|
||||
ProgramFailNoParser(pc, "out of memory");
|
||||
|
||||
|
||||
strncpy((char *)&NewEntry->p.Key[0], (char *)Ident, IdentLen);
|
||||
NewEntry->p.Key[IdentLen] = '\0';
|
||||
NewEntry->Next = Tbl->HashTable[AddAt];
|
||||
|
@ -174,11 +166,9 @@ void TableStrFree(Picoc *pc)
|
|||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
int Count;
|
||||
|
||||
for (Count = 0; Count < pc->StringTable.Size; Count++)
|
||||
{
|
||||
for (Entry = pc->StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
|
||||
for (Count = 0; Count < pc->StringTable.Size; Count++) {
|
||||
for (Entry = pc->StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
HeapFreeMem(pc, Entry);
|
||||
}
|
||||
|
|
280
type.c
280
type.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc data type module. This manages a tree of data types and has facilities
|
||||
* for parsing data types. */
|
||||
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
/* some basic types */
|
||||
|
@ -23,7 +23,7 @@ struct ValueType *TypeAdd(Picoc *pc, struct ParseState *Parser, struct ValueType
|
|||
NewType->OnHeap = TRUE;
|
||||
NewType->Next = ParentType->DerivedTypeList;
|
||||
ParentType->DerivedTypeList = NewType;
|
||||
|
||||
|
||||
return NewType;
|
||||
}
|
||||
|
||||
|
@ -36,21 +36,19 @@ struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser, struct V
|
|||
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
||||
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
|
||||
ThisType = ThisType->Next;
|
||||
|
||||
if (ThisType != NULL)
|
||||
{
|
||||
|
||||
if (ThisType != NULL) {
|
||||
if (AllowDuplicates)
|
||||
return ThisType;
|
||||
else
|
||||
ProgramFail(Parser, "data type '%s' is already defined", Identifier);
|
||||
}
|
||||
|
||||
switch (Base)
|
||||
{
|
||||
case TypePointer: Sizeof = sizeof(void *); AlignBytes = PointerAlignBytes; break;
|
||||
case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break;
|
||||
case TypeEnum: Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break;
|
||||
default: Sizeof = 0; AlignBytes = 0; break; /* structs and unions will get bigger when we add members to them */
|
||||
|
||||
switch (Base) {
|
||||
case TypePointer: Sizeof = sizeof(void *); AlignBytes = PointerAlignBytes; break;
|
||||
case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break;
|
||||
case TypeEnum: Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break;
|
||||
default: 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);
|
||||
|
@ -114,10 +112,10 @@ void TypeInit(Picoc *pc)
|
|||
struct DoubleAlign { char x; double y; } da;
|
||||
#endif
|
||||
struct PointerAlign { char x; void *y; } pa;
|
||||
|
||||
|
||||
IntAlignBytes = (char *)&ia.y - &ia.x;
|
||||
PointerAlignBytes = (char *)&pa.y - &pa.x;
|
||||
|
||||
|
||||
pc->UberType.DerivedTypeList = NULL;
|
||||
TypeAddBaseType(pc, &pc->IntType, TypeInt, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(pc, &pc->ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x);
|
||||
|
@ -148,17 +146,14 @@ void TypeCleanupNode(Picoc *pc, struct ValueType *Typ)
|
|||
{
|
||||
struct ValueType *SubType;
|
||||
struct ValueType *NextSubType;
|
||||
|
||||
|
||||
/* clean up and free all the sub-nodes */
|
||||
for (SubType = Typ->DerivedTypeList; SubType != NULL; SubType = NextSubType)
|
||||
{
|
||||
for (SubType = Typ->DerivedTypeList; SubType != NULL; SubType = NextSubType) {
|
||||
NextSubType = SubType->Next;
|
||||
TypeCleanupNode(pc, SubType);
|
||||
if (SubType->OnHeap)
|
||||
{
|
||||
if (SubType->OnHeap) {
|
||||
/* if it's a struct or union deallocate all the member values */
|
||||
if (SubType->Members != NULL)
|
||||
{
|
||||
if (SubType->Members != NULL) {
|
||||
VariableTableCleanup(pc, SubType->Members);
|
||||
HeapFreeMem(pc, SubType->Members);
|
||||
}
|
||||
|
@ -185,16 +180,13 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
|||
enum LexToken Token;
|
||||
int AlignBoundary;
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
|
||||
Token = LexGetToken(Parser, &LexValue, FALSE);
|
||||
if (Token == TokenIdentifier)
|
||||
{
|
||||
if (Token == TokenIdentifier) {
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
StructIdentifier = LexValue->Val->Identifier;
|
||||
Token = LexGetToken(Parser, NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
static char TempNameBuf[7] = "^s0000";
|
||||
StructIdentifier = PlatformMakeTempName(pc, TempNameBuf);
|
||||
}
|
||||
|
@ -204,43 +196,39 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
|||
ProgramFail(Parser, "data type '%t' is already defined", *Typ);
|
||||
|
||||
Token = LexGetToken(Parser, NULL, FALSE);
|
||||
if (Token != TokenLeftBrace)
|
||||
{
|
||||
if (Token != TokenLeftBrace) {
|
||||
/* use the already defined structure */
|
||||
#if 0
|
||||
if ((*Typ)->Members == NULL)
|
||||
ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier);
|
||||
#endif
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (pc->TopStackFrame != NULL)
|
||||
ProgramFail(Parser, "struct/union definitions can only be globals");
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
(*Typ)->Members = VariableAlloc(pc, Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
|
||||
(*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table));
|
||||
TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
|
||||
|
||||
|
||||
do {
|
||||
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL);
|
||||
if (MemberType == NULL || MemberIdentifier == NULL)
|
||||
ProgramFail(Parser, "invalid type in struct");
|
||||
|
||||
|
||||
MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), FALSE, NULL, TRUE);
|
||||
MemberValue->Typ = MemberType;
|
||||
if (IsStruct)
|
||||
{
|
||||
if (IsStruct) {
|
||||
/* allocate this member's location in the struct */
|
||||
AlignBoundary = MemberValue->Typ->AlignBytes;
|
||||
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0)
|
||||
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||
|
||||
|
||||
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
||||
(*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* union members always start at 0, make sure it's big enough to hold the largest member */
|
||||
MemberValue->Val->Integer = 0;
|
||||
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
||||
|
@ -250,21 +238,21 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
|||
/* make sure to align to the size of the largest member's alignment */
|
||||
if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes)
|
||||
(*Typ)->AlignBytes = MemberValue->Typ->AlignBytes;
|
||||
|
||||
|
||||
/* define it */
|
||||
if (!TableSet(pc, (*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos))
|
||||
ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier);
|
||||
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon)
|
||||
ProgramFail(Parser, "semicolon expected");
|
||||
|
||||
|
||||
} while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace);
|
||||
|
||||
|
||||
/* now align the structure to the size of its largest member's alignment */
|
||||
AlignBoundary = (*Typ)->AlignBytes;
|
||||
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0)
|
||||
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
}
|
||||
|
||||
|
@ -272,13 +260,13 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
|
|||
struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser, const char *StructName, int Size)
|
||||
{
|
||||
struct ValueType *Typ = TypeGetMatching(pc, Parser, &pc->UberType, TypeStruct, 0, StructName, FALSE);
|
||||
|
||||
|
||||
/* create the (empty) table */
|
||||
Typ->Members = VariableAlloc(pc, Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
|
||||
Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table));
|
||||
TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
|
||||
Typ->Sizeof = Size;
|
||||
|
||||
|
||||
return Typ;
|
||||
}
|
||||
|
||||
|
@ -291,35 +279,31 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
|
|||
int EnumValue = 0;
|
||||
char *EnumIdentifier;
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
|
||||
Token = LexGetToken(Parser, &LexValue, FALSE);
|
||||
if (Token == TokenIdentifier)
|
||||
{
|
||||
if (Token == TokenIdentifier) {
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
EnumIdentifier = LexValue->Val->Identifier;
|
||||
Token = LexGetToken(Parser, NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
static char TempNameBuf[7] = "^e0000";
|
||||
EnumIdentifier = PlatformMakeTempName(pc, TempNameBuf);
|
||||
}
|
||||
|
||||
TypeGetMatching(pc, Parser, &pc->UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace);
|
||||
*Typ = &pc->IntType;
|
||||
if (Token != TokenLeftBrace)
|
||||
{
|
||||
if (Token != TokenLeftBrace) {
|
||||
/* use the already defined enum */
|
||||
if ((*Typ)->Members == NULL)
|
||||
ProgramFail(Parser, "enum '%s' isn't defined", EnumIdentifier);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (pc->TopStackFrame != NULL)
|
||||
ProgramFail(Parser, "enum definitions can only be globals");
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
(*Typ)->Members = &pc->GlobalTable;
|
||||
memset((void *)&InitValue, '\0', sizeof(struct Value));
|
||||
InitValue.Typ = &pc->IntType;
|
||||
|
@ -327,22 +311,20 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
|
|||
do {
|
||||
if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier)
|
||||
ProgramFail(Parser, "identifier expected");
|
||||
|
||||
|
||||
EnumIdentifier = LexValue->Val->Identifier;
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenAssign)
|
||||
{
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) {
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
EnumValue = ExpressionParseInt(Parser);
|
||||
}
|
||||
|
||||
|
||||
VariableDefine(pc, Parser, EnumIdentifier, &InitValue, NULL, FALSE);
|
||||
|
||||
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token != TokenComma && Token != TokenRightBrace)
|
||||
ProgramFail(Parser, "comma expected");
|
||||
|
||||
|
||||
EnumValue++;
|
||||
|
||||
} while (Token == TokenComma);
|
||||
}
|
||||
|
||||
|
@ -361,70 +343,65 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
|
|||
/* ignore leading type qualifiers */
|
||||
ParserCopy(&Before, Parser);
|
||||
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)
|
||||
StaticQualifier = TRUE;
|
||||
|
||||
|
||||
Token = LexGetToken(Parser, &LexerValue, TRUE);
|
||||
}
|
||||
|
||||
|
||||
if (IsStatic != NULL)
|
||||
*IsStatic = StaticQualifier;
|
||||
|
||||
|
||||
/* handle signed/unsigned with no trailing type */
|
||||
if (Token == TokenSignedType || Token == TokenUnsignedType)
|
||||
{
|
||||
if (Token == TokenSignedType || Token == TokenUnsignedType) {
|
||||
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, FALSE);
|
||||
Unsigned = (Token == TokenUnsignedType);
|
||||
|
||||
if (FollowToken != TokenIntType && FollowToken != TokenLongType && FollowToken != TokenShortType && FollowToken != TokenCharType)
|
||||
{
|
||||
|
||||
if (FollowToken != TokenIntType && FollowToken != TokenLongType && FollowToken != TokenShortType && FollowToken != TokenCharType) {
|
||||
if (Token == TokenUnsignedType)
|
||||
*Typ = &pc->UnsignedIntType;
|
||||
else
|
||||
*Typ = &pc->IntType;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Token = LexGetToken(Parser, &LexerValue, TRUE);
|
||||
}
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIntType: *Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType; break;
|
||||
case TokenShortType: *Typ = Unsigned ? &pc->UnsignedShortType : &pc->ShortType; break;
|
||||
case TokenCharType: *Typ = Unsigned ? &pc->UnsignedCharType : &pc->CharType; break;
|
||||
case TokenLongType: *Typ = Unsigned ? &pc->UnsignedLongType : &pc->LongType; break;
|
||||
|
||||
switch (Token) {
|
||||
case TokenIntType: *Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType; break;
|
||||
case TokenShortType: *Typ = Unsigned ? &pc->UnsignedShortType : &pc->ShortType; break;
|
||||
case TokenCharType: *Typ = Unsigned ? &pc->UnsignedCharType : &pc->CharType; break;
|
||||
case TokenLongType: *Typ = Unsigned ? &pc->UnsignedLongType : &pc->LongType; break;
|
||||
#ifndef NO_FP
|
||||
case TokenFloatType: case TokenDoubleType: *Typ = &pc->FPType; break;
|
||||
case TokenFloatType: case TokenDoubleType: *Typ = &pc->FPType; break;
|
||||
#endif
|
||||
case TokenVoidType: *Typ = &pc->VoidType; break;
|
||||
|
||||
case TokenStructType: case TokenUnionType:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
TypeParseStruct(Parser, Typ, Token == TokenStructType);
|
||||
break;
|
||||
case TokenVoidType: *Typ = &pc->VoidType; break;
|
||||
case TokenStructType: case TokenUnionType:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
case TokenEnumType:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
TypeParseEnum(Parser, Typ);
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
/* we already know it's a typedef-defined type because we got here */
|
||||
VariableGet(pc, Parser, LexerValue->Val->Identifier, &VarValue);
|
||||
*Typ = VarValue->Val->Typ;
|
||||
break;
|
||||
TypeParseStruct(Parser, Typ, Token == TokenStructType);
|
||||
break;
|
||||
|
||||
default: ParserCopy(Parser, &Before); return FALSE;
|
||||
case TokenEnumType:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
TypeParseEnum(Parser, Typ);
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
/* we already know it's a typedef-defined type because we got here */
|
||||
VariableGet(pc, Parser, LexerValue->Val->Identifier, &VarValue);
|
||||
*Typ = VarValue->Val->Typ;
|
||||
break;
|
||||
|
||||
default: ParserCopy(Parser, &Before); return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -436,32 +413,26 @@ struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *Fro
|
|||
|
||||
ParserCopy(&Before, Parser);
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token == TokenLeftSquareBracket)
|
||||
{
|
||||
if (Token == TokenLeftSquareBracket) {
|
||||
/* add another array bound */
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenRightSquareBracket)
|
||||
{
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenRightSquareBracket) {
|
||||
/* an unsized array */
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
return TypeGetMatching(Parser->pc, Parser, TypeParseBack(Parser, FromType), TypeArray, 0, Parser->pc->StrEmpty, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* get a numeric array size */
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
int ArraySize;
|
||||
Parser->Mode = RunModeRun;
|
||||
ArraySize = ExpressionParseInt(Parser);
|
||||
Parser->Mode = OldMode;
|
||||
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenRightSquareBracket)
|
||||
ProgramFail(Parser, "']' expected");
|
||||
|
||||
|
||||
return TypeGetMatching(Parser->pc, Parser, TypeParseBack(Parser, FromType), TypeArray, ArraySize, Parser->pc->StrEmpty, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* the type specification has finished */
|
||||
ParserCopy(Parser, &Before);
|
||||
return FromType;
|
||||
|
@ -477,46 +448,43 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s
|
|||
int Done = FALSE;
|
||||
*Typ = BasicTyp;
|
||||
*Identifier = Parser->pc->StrEmpty;
|
||||
|
||||
while (!Done)
|
||||
{
|
||||
|
||||
while (!Done) {
|
||||
ParserCopy(&Before, Parser);
|
||||
Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenOpenBracket:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
TypeParse(Parser, Typ, Identifier, NULL);
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
break;
|
||||
|
||||
case TokenAsterisk:
|
||||
if (*Typ == NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
switch (Token) {
|
||||
case TokenOpenBracket:
|
||||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
*Typ = TypeGetMatching(Parser->pc, Parser, *Typ, TypePointer, 0, Parser->pc->StrEmpty, TRUE);
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
if (*Typ == NULL || *Identifier != Parser->pc->StrEmpty)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
*Identifier = LexValue->Val->Identifier;
|
||||
Done = TRUE;
|
||||
break;
|
||||
|
||||
default: ParserCopy(Parser, &Before); Done = TRUE; break;
|
||||
TypeParse(Parser, Typ, Identifier, NULL);
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
break;
|
||||
|
||||
case TokenAsterisk:
|
||||
if (*Typ == NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
*Typ = TypeGetMatching(Parser->pc, Parser, *Typ, TypePointer, 0, Parser->pc->StrEmpty, TRUE);
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
if (*Typ == NULL || *Identifier != Parser->pc->StrEmpty)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
*Identifier = LexValue->Val->Identifier;
|
||||
Done = TRUE;
|
||||
break;
|
||||
|
||||
default: ParserCopy(Parser, &Before); Done = TRUE; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (*Typ == NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
if (*Identifier != Parser->pc->StrEmpty)
|
||||
{
|
||||
if (*Identifier != Parser->pc->StrEmpty) {
|
||||
/* parse stuff after the identifier */
|
||||
*Typ = TypeParseBack(Parser, *Typ);
|
||||
}
|
||||
|
@ -526,7 +494,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s
|
|||
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic)
|
||||
{
|
||||
struct ValueType *BasicType;
|
||||
|
||||
|
||||
TypeParseFront(Parser, &BasicType, IsStatic);
|
||||
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
||||
}
|
||||
|
@ -536,9 +504,9 @@ int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ)
|
|||
{
|
||||
if (Typ->Base == TypeArray)
|
||||
return TypeIsForwardDeclared(Parser, Typ->FromType);
|
||||
|
||||
|
||||
if ( (Typ->Base == TypeStruct || Typ->Base == TypeUnion) && Typ->Members == NULL)
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
153
variable.c
153
variable.c
|
@ -1,6 +1,6 @@
|
|||
/* picoc variable storage. This provides ways of defining and accessing
|
||||
* variables */
|
||||
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
/* maximum size of a value to temporarily copy while we create a variable */
|
||||
|
@ -18,8 +18,7 @@ void VariableInit(Picoc *pc)
|
|||
/* deallocate the contents of a variable */
|
||||
void VariableFree(Picoc *pc, struct Value *Val)
|
||||
{
|
||||
if (Val->ValOnHeap || Val->AnyValOnHeap)
|
||||
{
|
||||
if (Val->ValOnHeap || Val->AnyValOnHeap) {
|
||||
/* free function bodies */
|
||||
if (Val->Typ == &pc->FunctionType && Val->Val->FuncDef.Intrinsic == NULL && Val->Val->FuncDef.Body.Pos != NULL)
|
||||
HeapFreeMem(pc, (void *)Val->Val->FuncDef.Body.Pos);
|
||||
|
@ -44,14 +43,12 @@ void VariableTableCleanup(Picoc *pc, struct Table *HashTable)
|
|||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
int Count;
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
VariableFree(pc, Entry->p.v.Val);
|
||||
|
||||
|
||||
/* free the hash table entry */
|
||||
HeapFreeMem(pc, Entry);
|
||||
}
|
||||
|
@ -68,20 +65,20 @@ void VariableCleanup(Picoc *pc)
|
|||
void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
|
||||
{
|
||||
void *NewValue;
|
||||
|
||||
|
||||
if (OnHeap)
|
||||
NewValue = HeapAllocMem(pc, Size);
|
||||
else
|
||||
NewValue = HeapAllocStack(pc, Size);
|
||||
|
||||
|
||||
if (NewValue == NULL)
|
||||
ProgramFail(Parser, "out of memory");
|
||||
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
if (!OnHeap)
|
||||
printf("pushing %d at 0x%lx\n", Size, (unsigned long)NewValue);
|
||||
#endif
|
||||
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
|
@ -95,11 +92,11 @@ struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser, in
|
|||
NewValue->ValOnStack = !OnHeap;
|
||||
NewValue->IsLValue = IsLValue;
|
||||
NewValue->LValueFrom = LValueFrom;
|
||||
if (Parser)
|
||||
if (Parser)
|
||||
NewValue->ScopeID = Parser->ScopeID;
|
||||
|
||||
NewValue->OutOfScope = 0;
|
||||
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
|
@ -110,7 +107,7 @@ struct Value *VariableAllocValueFromType(Picoc *pc, struct ParseState *Parser, s
|
|||
struct Value *NewValue = VariableAllocValueAndData(pc, Parser, Size, IsLValue, LValueFrom, OnHeap);
|
||||
assert(Size >= 0 || Typ == &pc->VoidType);
|
||||
NewValue->Typ = Typ;
|
||||
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
|
@ -127,7 +124,7 @@ struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser, st
|
|||
NewValue = VariableAllocValueAndData(pc, Parser, CopySize, FromValue->IsLValue, FromValue->LValueFrom, OnHeap);
|
||||
NewValue->Typ = DType;
|
||||
memcpy((void *)NewValue->Val, (void *)&TmpBuf[0], CopySize);
|
||||
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
|
@ -142,7 +139,7 @@ struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, stru
|
|||
NewValue->ValOnStack = FALSE;
|
||||
NewValue->IsLValue = IsLValue;
|
||||
NewValue->LValueFrom = LValueFrom;
|
||||
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
|
@ -157,7 +154,7 @@ void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int New
|
|||
{
|
||||
if (FromValue->AnyValOnHeap)
|
||||
HeapFreeMem(Parser->pc, FromValue->Val);
|
||||
|
||||
|
||||
FromValue->Val = VariableAlloc(Parser->pc, Parser, NewSize, TRUE);
|
||||
FromValue->AnyValOnHeap = TRUE;
|
||||
}
|
||||
|
@ -168,10 +165,10 @@ int VariableScopeBegin(struct ParseState * Parser, int* OldScopeID)
|
|||
struct TableEntry *NextEntry;
|
||||
Picoc * pc = Parser->pc;
|
||||
int Count;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
int FirstPrint = 0;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
if (Parser->ScopeID == -1) return -1;
|
||||
|
@ -181,21 +178,18 @@ int VariableScopeBegin(struct ParseState * Parser, int* OldScopeID)
|
|||
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*));
|
||||
/* or maybe a more human-readable hash for debugging? */
|
||||
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope)
|
||||
{
|
||||
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope) {
|
||||
Entry->p.v.Val->OutOfScope = FALSE;
|
||||
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (!FirstPrint) { PRINT_SOURCE_POS; }
|
||||
FirstPrint = 1;
|
||||
printf(">>> back into scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,26 +203,25 @@ void VariableScopeEnd(struct ParseState * Parser, int ScopeID, int PrevScopeID)
|
|||
struct TableEntry *NextEntry;
|
||||
Picoc * pc = Parser->pc;
|
||||
int Count;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
int FirstPrint = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
if (ScopeID == -1) return;
|
||||
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||
{
|
||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
if (Entry->p.v.Val->ScopeID == ScopeID && !Entry->p.v.Val->OutOfScope)
|
||||
{
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (!FirstPrint) { PRINT_SOURCE_POS; }
|
||||
if (Entry->p.v.Val->ScopeID == ScopeID && !Entry->p.v.Val->OutOfScope) {
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (!FirstPrint) {
|
||||
PRINT_SOURCE_POS;
|
||||
}
|
||||
FirstPrint = 1;
|
||||
printf(">>> out of scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
|
||||
#endif
|
||||
#endif
|
||||
Entry->p.v.Val->OutOfScope = TRUE;
|
||||
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key | 1); /* alter the key so it won't be found by normal searches */
|
||||
}
|
||||
|
@ -244,10 +237,8 @@ int VariableDefinedAndOutOfScope(Picoc * pc, const char* Ident)
|
|||
int Count;
|
||||
|
||||
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
for (Count = 0; Count < HashTable->Size; Count++)
|
||||
{
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next)
|
||||
{
|
||||
for (Count = 0; Count < HashTable->Size; Count++) {
|
||||
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next) {
|
||||
if (Entry->p.v.Val->OutOfScope && (char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -260,24 +251,24 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
|
|||
{
|
||||
struct Value * AssignValue;
|
||||
struct Table * currentTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
|
||||
|
||||
|
||||
int ScopeID = Parser ? Parser->ScopeID : -1;
|
||||
#ifdef VAR_SCOPE_DEBUG
|
||||
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID, Parser->FileName, Parser->Line, Parser->CharacterPos);
|
||||
#endif
|
||||
|
||||
|
||||
if (InitValue != NULL)
|
||||
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL);
|
||||
else
|
||||
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable, NULL, pc->TopStackFrame == NULL);
|
||||
|
||||
|
||||
AssignValue->IsLValue = MakeWritable;
|
||||
AssignValue->ScopeID = ScopeID;
|
||||
AssignValue->OutOfScope = FALSE;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
return AssignValue;
|
||||
}
|
||||
|
||||
|
@ -289,39 +280,36 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *
|
|||
const char *DeclFileName;
|
||||
int DeclLine;
|
||||
int DeclColumn;
|
||||
|
||||
|
||||
/* is the type a forward declaration? */
|
||||
if (TypeIsForwardDeclared(Parser, Typ))
|
||||
ProgramFail(Parser, "type '%t' isn't defined", Typ);
|
||||
|
||||
if (IsStatic)
|
||||
{
|
||||
if (IsStatic) {
|
||||
char MangledName[LINEBUFFER_MAX];
|
||||
char *MNPos = &MangledName[0];
|
||||
char *MNEnd = &MangledName[LINEBUFFER_MAX-1];
|
||||
const char *RegisteredMangledName;
|
||||
|
||||
|
||||
/* make the mangled static name (avoiding using sprintf() to minimise library impact) */
|
||||
memset((void *)&MangledName, '\0', sizeof(MangledName));
|
||||
*MNPos++ = '/';
|
||||
strncpy(MNPos, (char *)Parser->FileName, MNEnd - MNPos);
|
||||
MNPos += strlen(MNPos);
|
||||
|
||||
if (pc->TopStackFrame != NULL)
|
||||
{
|
||||
|
||||
if (pc->TopStackFrame != NULL) {
|
||||
/* we're inside a function */
|
||||
if (MNEnd - MNPos > 0) *MNPos++ = '/';
|
||||
strncpy(MNPos, (char *)pc->TopStackFrame->FuncName, MNEnd - MNPos);
|
||||
MNPos += strlen(MNPos);
|
||||
}
|
||||
|
||||
|
||||
if (MNEnd - MNPos > 0) *MNPos++ = '/';
|
||||
strncpy(MNPos, Ident, MNEnd - MNPos);
|
||||
RegisteredMangledName = TableStrRegister(pc, MangledName);
|
||||
|
||||
|
||||
/* 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 */
|
||||
ExistingValue = VariableAllocValueFromType(Parser->pc, Parser, Typ, TRUE, NULL, TRUE);
|
||||
TableSet(pc, &pc->GlobalTable, (char *)RegisteredMangledName, ExistingValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos);
|
||||
|
@ -331,9 +319,7 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *
|
|||
/* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */
|
||||
VariableDefinePlatformVar(Parser->pc, Parser, Ident, ExistingValue->Typ, ExistingValue->Val, TRUE);
|
||||
return ExistingValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
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)
|
||||
return ExistingValue;
|
||||
|
@ -346,9 +332,8 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *
|
|||
int VariableDefined(Picoc *pc, const char *Ident)
|
||||
{
|
||||
struct Value *FoundValue;
|
||||
|
||||
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL, NULL))
|
||||
{
|
||||
|
||||
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL, NULL)) {
|
||||
if (!TableGet(&pc->GlobalTable, Ident, &FoundValue, NULL, NULL, NULL))
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -359,10 +344,8 @@ int VariableDefined(Picoc *pc, const char *Ident)
|
|||
/* get the value of a variable. must be defined. Ident must be registered */
|
||||
void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct Value **LVal)
|
||||
{
|
||||
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL))
|
||||
{
|
||||
if (!TableGet(&pc->GlobalTable, Ident, LVal, NULL, NULL, NULL))
|
||||
{
|
||||
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL)) {
|
||||
if (!TableGet(&pc->GlobalTable, Ident, LVal, NULL, NULL, NULL)) {
|
||||
if (VariableDefinedAndOutOfScope(pc, Ident))
|
||||
ProgramFail(Parser, "'%s' is out of scope", Ident);
|
||||
else
|
||||
|
@ -377,7 +360,7 @@ void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident
|
|||
struct Value *SomeValue = VariableAllocValueAndData(pc, NULL, 0, IsWritable, NULL, TRUE);
|
||||
SomeValue->Typ = Typ;
|
||||
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))
|
||||
ProgramFail(Parser, "'%s' is already defined", Ident);
|
||||
}
|
||||
|
@ -386,24 +369,22 @@ void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident
|
|||
void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
||||
{
|
||||
int Success;
|
||||
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
if (Var->ValOnStack)
|
||||
printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(Var, FALSE)), (unsigned long)Var);
|
||||
#endif
|
||||
|
||||
if (Var->ValOnHeap)
|
||||
{
|
||||
|
||||
if (Var->ValOnHeap) {
|
||||
if (Var->Val != NULL)
|
||||
HeapFreeMem(Parser->pc, Var->Val);
|
||||
|
||||
|
||||
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value)); /* free from heap */
|
||||
}
|
||||
else if (Var->ValOnStack)
|
||||
} else if (Var->ValOnStack)
|
||||
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value) + TypeSizeValue(Var, FALSE)); /* free from stack */
|
||||
else
|
||||
Success = HeapPopStack(Parser->pc, Var, sizeof(struct Value)); /* value isn't our problem */
|
||||
|
||||
|
||||
if (!Success)
|
||||
ProgramFail(Parser, "stack underrun");
|
||||
}
|
||||
|
@ -412,12 +393,12 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var)
|
|||
void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams)
|
||||
{
|
||||
struct StackFrame *NewFrame;
|
||||
|
||||
|
||||
HeapPushStackFrame(Parser->pc);
|
||||
NewFrame = HeapAllocStack(Parser->pc, sizeof(struct StackFrame) + sizeof(struct Value *) * NumParams);
|
||||
if (NewFrame == NULL)
|
||||
ProgramFail(Parser, "out of memory");
|
||||
|
||||
|
||||
ParserCopy(&NewFrame->ReturnParser, Parser);
|
||||
NewFrame->FuncName = FuncName;
|
||||
NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL;
|
||||
|
@ -431,7 +412,7 @@ void VariableStackFramePop(struct ParseState *Parser)
|
|||
{
|
||||
if (Parser->pc->TopStackFrame == NULL)
|
||||
ProgramFail(Parser, "stack is empty - can't go back");
|
||||
|
||||
|
||||
ParserCopy(Parser, &Parser->pc->TopStackFrame->ReturnParser);
|
||||
Parser->pc->TopStackFrame = Parser->pc->TopStackFrame->PreviousStackFrame;
|
||||
HeapPopStackFrame(Parser->pc);
|
||||
|
@ -459,13 +440,13 @@ void *VariableDereferencePointer(struct ParseState *Parser, struct Value *Pointe
|
|||
{
|
||||
if (DerefVal != NULL)
|
||||
*DerefVal = NULL;
|
||||
|
||||
|
||||
if (DerefType != NULL)
|
||||
*DerefType = PointerValue->Typ->FromType;
|
||||
|
||||
|
||||
if (DerefOffset != NULL)
|
||||
*DerefOffset = 0;
|
||||
|
||||
|
||||
if (DerefIsLValue != NULL)
|
||||
*DerefIsLValue = TRUE;
|
||||
|
||||
|
|
Loading…
Reference in a new issue