respect 80 col mark when it makes sense

This commit is contained in:
Joseph Poirier 2015-06-10 19:27:30 -05:00
parent e52188dcda
commit 8c18e1d061
13 changed files with 819 additions and 333 deletions

View file

@ -29,7 +29,8 @@ void LibraryInit(Picoc *pc)
} }
/* add a library */ /* add a library */
void LibraryAdd(Picoc *pc, struct Table *GlobalTable, struct LibraryFunction *FuncList) void LibraryAdd(Picoc *pc, struct Table *GlobalTable,
struct LibraryFunction *FuncList)
{ {
struct ParseState Parser; struct ParseState Parser;
int Count; int Count;

View file

@ -17,7 +17,7 @@ static int _IOFBFValue = _IOFBF;
static int _IOLBFValue = _IOLBF; static int _IOLBFValue = _IOLBF;
static int _IONBFValue = _IONBF; static int _IONBFValue = _IONBF;
static int L_tmpnamValue = L_tmpnam; static int L_tmpnamValue = L_tmpnam;
static int GETS_MAXValue = 255; /* arbitrary maximum size of a gets() file */ static int GETS_MAXValue = 255; /* arbitrary maximum size of a gets() file */
static FILE *stdinValue; static FILE *stdinValue;
static FILE *stdoutValue; static FILE *stdoutValue;
@ -163,7 +163,8 @@ void StdioFprintfPointer(StdOutStream *Stream, const char *Format, void *Value)
} }
} }
/* internal do-anything v[s][n]printf() formatting system with output to strings or FILE * */ /* internal do-anything v[s][n]printf() formatting system with output
to strings or FILE * */
int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
int StrOutLen, char *Format, struct StdVararg *Args) int StrOutLen, char *Format, struct StdVararg *Args)
{ {
@ -262,8 +263,10 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
StdioOutPutc(*FPos, &SOStream); StdioOutPutc(*FPos, &SOStream);
break; break;
case 'n': case 'n':
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg))); ThisArg = (struct Value*)((char*)ThisArg +
if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeInt) MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
if (ThisArg->Typ->Base == TypeArray &&
ThisArg->Typ->FromType->Base == TypeInt)
*(int *)ThisArg->Val->Pointer = SOStream.CharCount; *(int *)ThisArg->Val->Pointer = SOStream.CharCount;
break; break;
} }
@ -281,7 +284,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
OneFormatBuf[OneFormatCount] = '\0'; OneFormatBuf[OneFormatCount] = '\0';
/* print this argument */ /* print this argument */
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg))); ThisArg = (struct Value*)((char*)ThisArg +
MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
if (ShowType == &pc->IntType) { if (ShowType == &pc->IntType) {
/* show a signed integer */ /* show a signed integer */
if (IS_NUMERIC_COERCIBLE(ThisArg)) if (IS_NUMERIC_COERCIBLE(ThisArg))
@ -300,7 +304,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
if (ThisArg->Typ->Base == TypePointer) if (ThisArg->Typ->Base == TypePointer)
StdioFprintfPointer(&SOStream, OneFormatBuf, StdioFprintfPointer(&SOStream, OneFormatBuf,
ThisArg->Val->Pointer); ThisArg->Val->Pointer);
else if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeChar) else if (ThisArg->Typ->Base == TypeArray &&
ThisArg->Typ->FromType->Base == TypeChar)
StdioFprintfPointer(&SOStream, OneFormatBuf, StdioFprintfPointer(&SOStream, OneFormatBuf,
&ThisArg->Val->ArrayMem[0]); &ThisArg->Val->ArrayMem[0]);
else else
@ -333,7 +338,8 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut,
return SOStream.CharCount; return SOStream.CharCount;
} }
/* internal do-anything v[s][n]scanf() formatting system with input from strings or FILE * */ /* internal do-anything v[s][n]scanf() formatting system with input
from strings or FILE * */
int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn, int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn,
char *Format, struct StdVararg *Args) char *Format, struct StdVararg *Args)
{ {
@ -346,7 +352,8 @@ int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn,
MAX_SCANF_ARGS); MAX_SCANF_ARGS);
for (ArgCount = 0; ArgCount < Args->NumArgs; ArgCount++) { for (ArgCount = 0; ArgCount < Args->NumArgs; ArgCount++) {
ThisArg = (struct Value*)((char*)ThisArg+MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg))); ThisArg = (struct Value*)((char*)ThisArg +
MEM_ALIGN(sizeof(struct Value)+TypeStackSizeValue(ThisArg)));
if (ThisArg->Typ->Base == TypePointer) if (ThisArg->Typ->Base == TypePointer)
ScanfArg[ArgCount] = ThisArg->Val->Pointer; ScanfArg[ArgCount] = ThisArg->Val->Pointer;
@ -478,25 +485,29 @@ void StdioFflush(struct ParseState *Parser, struct Value *ReturnValue,
void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue, void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer,
Param[1]->Val->Pointer);
} }
void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue, void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer,
Param[1]->Val->Pointer);
} }
void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue, void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer, Param[1]->Val->Pointer); ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer,
Param[1]->Val->Pointer);
} }
void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue, void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer, Param[1]->Val->Pointer); ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer,
Param[1]->Val->Pointer);
} }
void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue, void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue,
@ -630,7 +641,8 @@ void StdioSnprintf(struct ParseState *Parser, struct Value *ReturnValue,
PrintfArgs.Param = Param+2; PrintfArgs.Param = Param+2;
PrintfArgs.NumArgs = NumArgs-3; PrintfArgs.NumArgs = NumArgs-3;
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, &PrintfArgs); Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer,
&PrintfArgs);
} }
void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue, void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue,
@ -670,14 +682,16 @@ void StdioVsprintf(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, Param[2]->Val->Pointer); Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer,
Param[2]->Val->Pointer);
} }
void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue, void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL,
Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer); Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer,
Param[3]->Val->Pointer);
} }
void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue, void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue,
@ -766,7 +780,8 @@ void StdioSetupFunc(Picoc *pc)
struct ValueType *StructFileType; struct ValueType *StructFileType;
struct ValueType *FilePtrType; struct ValueType *FilePtrType;
/* make a "struct __FILEStruct" which is the same size as a native FILE structure */ /* make a "struct __FILEStruct" which is the same size as a
native FILE structure */
StructFileType = TypeCreateOpaqueStruct(pc, NULL, StructFileType = TypeCreateOpaqueStruct(pc, NULL,
TableStrRegister(pc, "__FILEStruct"), sizeof(FILE)); TableStrRegister(pc, "__FILEStruct"), sizeof(FILE));
@ -774,7 +789,8 @@ void StdioSetupFunc(Picoc *pc)
FilePtrType = TypeGetMatching(pc, NULL, StructFileType, TypePointer, 0, FilePtrType = TypeGetMatching(pc, NULL, StructFileType, TypePointer, 0,
pc->StrEmpty, true); pc->StrEmpty, true);
/* make a "struct __va_listStruct" which is the same size as our struct StdVararg */ /* make a "struct __va_listStruct" which is the same size as
our struct StdVararg */
TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__va_listStruct"), TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__va_listStruct"),
sizeof(FILE)); sizeof(FILE));

View file

@ -110,7 +110,8 @@ void StdlibBsearch(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Pointer = bsearch(Param[0]->Val->Pointer, ReturnValue->Val->Pointer = bsearch(Param[0]->Val->Pointer,
Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer, (int (*)())Param[4]->Val->Pointer); Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer,
(int (*)())Param[4]->Val->Pointer);
} }
#endif #endif

View file

@ -9,7 +9,8 @@ static int ZeroValue = 0;
void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue, void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = access(Param[0]->Val->Pointer, Param[1]->Val->Integer); ReturnValue->Val->Integer = access(Param[0]->Val->Pointer,
Param[1]->Val->Integer);
} }
void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue, void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue,
@ -33,7 +34,8 @@ void UnistdChroot(struct ParseState *Parser, struct Value *ReturnValue,
void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue, void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer,
Param[1]->Val->Integer, Param[2]->Val->Integer);
} }
void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue, void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue,
@ -134,7 +136,8 @@ void UnistdFtruncate(struct ParseState *Parser, struct Value *ReturnValue,
void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue, void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, Param[1]->Val->Integer); ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer,
Param[1]->Val->Integer);
} }
void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue, void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue,
@ -254,7 +257,8 @@ void UnistdLchown(struct ParseState *Parser, struct Value *ReturnValue,
void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue, void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue,
struct Value **Param, int NumArgs) struct Value **Param, int NumArgs)
{ {
ReturnValue->Val->Integer = link(Param[0]->Val->Pointer, Param[1]->Val->Pointer); ReturnValue->Val->Integer = link(Param[0]->Val->Pointer,
Param[1]->Val->Pointer);
} }
void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue, void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue,

23
debug.c
View file

@ -29,14 +29,18 @@ void DebugCleanup(Picoc *pc)
} }
/* search the table for a breakpoint */ /* search the table for a breakpoint */
static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser, int *AddAt) static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser,
int *AddAt)
{ {
struct TableEntry *Entry; struct TableEntry *Entry;
Picoc *pc = Parser->pc; Picoc *pc = Parser->pc;
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size; int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
for (Entry = pc->BreakpointHashTable[HashValue]; Entry != NULL; Entry = Entry->Next) { for (Entry = pc->BreakpointHashTable[HashValue];
if (Entry->p.b.FileName == Parser->FileName && Entry->p.b.Line == Parser->Line && Entry->p.b.CharacterPos == Parser->CharacterPos) Entry != NULL; Entry = Entry->Next) {
if (Entry->p.b.FileName == Parser->FileName &&
Entry->p.b.Line == Parser->Line &&
Entry->p.b.CharacterPos == Parser->CharacterPos)
return Entry; /* found */ return Entry; /* found */
} }
@ -73,9 +77,12 @@ int DebugClearBreakpoint(struct ParseState *Parser)
Picoc *pc = Parser->pc; Picoc *pc = Parser->pc;
int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size; int HashValue = BREAKPOINT_HASH(Parser) % pc->BreakpointTable.Size;
for (EntryPtr = &pc->BreakpointHashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) { for (EntryPtr = &pc->BreakpointHashTable[HashValue];
*EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
struct TableEntry *DeleteEntry = *EntryPtr; struct TableEntry *DeleteEntry = *EntryPtr;
if (DeleteEntry->p.b.FileName == Parser->FileName && DeleteEntry->p.b.Line == Parser->Line && DeleteEntry->p.b.CharacterPos == Parser->CharacterPos) { if (DeleteEntry->p.b.FileName == Parser->FileName &&
DeleteEntry->p.b.Line == Parser->Line &&
DeleteEntry->p.b.CharacterPos == Parser->CharacterPos) {
*EntryPtr = DeleteEntry->Next; *EntryPtr = DeleteEntry->Next;
HeapFreeMem(pc, DeleteEntry); HeapFreeMem(pc, DeleteEntry);
pc->BreakpointCount--; pc->BreakpointCount--;
@ -87,7 +94,8 @@ int DebugClearBreakpoint(struct ParseState *Parser)
return false; return false;
} }
/* before we run a statement, check if there's anything we have to do with the debugger here */ /* before we run a statement, check if there's anything we have to
do with the debugger here */
void DebugCheckStatement(struct ParseState *Parser) void DebugCheckStatement(struct ParseState *Parser)
{ {
int DoBreak = false; int DoBreak = false;
@ -102,7 +110,8 @@ void DebugCheckStatement(struct ParseState *Parser)
} }
/* is this a breakpoint location? */ /* is this a breakpoint location? */
if (Parser->pc->BreakpointCount != 0 && DebugTableSearchBreakpoint(Parser, &AddAt) != NULL) if (Parser->pc->BreakpointCount != 0 &&
DebugTableSearchBreakpoint(Parser, &AddAt) != NULL)
DoBreak = true; DoBreak = true;
/* handle a break */ /* handle a break */

File diff suppressed because it is too large Load diff

12
heap.c
View file

@ -34,7 +34,8 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
pc->StackFrame = &(pc->HeapMemory)[AlignOffset]; pc->StackFrame = &(pc->HeapMemory)[AlignOffset];
pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset]; pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset];
*(void **)(pc->StackFrame) = NULL; *(void **)(pc->StackFrame) = NULL;
pc->HeapBottom = &(pc->HeapMemory)[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset]; pc->HeapBottom =
&(pc->HeapMemory)[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset];
pc->FreeListBig = NULL; pc->FreeListBig = NULL;
for (Count = 0; Count < FREELIST_BUCKETS; Count++) for (Count = 0; Count < FREELIST_BUCKETS; Count++)
pc->FreeListBucket[Count] = NULL; pc->FreeListBucket[Count] = NULL;
@ -98,7 +99,8 @@ void HeapPushStackFrame(Picoc *pc)
#endif #endif
*(void **)pc->HeapStackTop = pc->StackFrame; *(void **)pc->HeapStackTop = pc->StackFrame;
pc->StackFrame = pc->HeapStackTop; pc->StackFrame = pc->HeapStackTop;
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE))); pc->HeapStackTop = (void*)((char*)pc->HeapStackTop +
MEM_ALIGN(sizeof(ALIGN_TYPE)));
} }
/* pop the current stack frame, freeing all memory in the frame. can return NULL */ /* pop the current stack frame, freeing all memory in the frame. can return NULL */
@ -108,14 +110,16 @@ int HeapPopStackFrame(Picoc *pc)
pc->HeapStackTop = pc->StackFrame; pc->HeapStackTop = pc->StackFrame;
pc->StackFrame = *(void**)pc->StackFrame; pc->StackFrame = *(void**)pc->StackFrame;
#ifdef DEBUG_HEAP #ifdef DEBUG_HEAP
printf("Popping stack frame back to 0x%lx\n", (unsigned long)pc->HeapStackTop); printf("Popping stack frame back to 0x%lx\n",
(unsigned long)pc->HeapStackTop);
#endif #endif
return true; return true;
} else } else
return false; return false;
} }
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */ /* allocate some dynamically allocated memory. memory is cleared.
can return NULL if out of memory */
void *HeapAllocMem(Picoc *pc, int Size) void *HeapAllocMem(Picoc *pc, int Size)
{ {
return calloc(Size, 1); return calloc(Size, 1);

115
lex.c
View file

@ -265,7 +265,8 @@ unsigned char LexUnEscapeCharacter(const char **From, const char *End)
(*From) += 2; /* skip escaped end of lines with LF line termination */ (*From) += 2; /* skip escaped end of lines with LF line termination */
while ( *From != End && **From == '\\' && while ( *From != End && **From == '\\' &&
&(*From)[1] != End && &(*From)[2] != End && (*From)[1] == '\r' && (*From)[2] == '\n') &(*From)[1] != End &&
&(*From)[2] != End && (*From)[1] == '\r' && (*From)[2] == '\n')
(*From) += 3; /* skip escaped end of lines with CR/LF line termination */ (*From) += 3; /* skip escaped end of lines with CR/LF line termination */
if (*From == End) if (*From == End)
@ -279,19 +280,35 @@ unsigned char LexUnEscapeCharacter(const char **From, const char *End)
ThisChar = *(*From)++; ThisChar = *(*From)++;
switch (ThisChar) { switch (ThisChar) {
case '\\': return '\\'; case '\\':
case '\'': return '\''; return '\\';
case '"': return '"'; case '\'':
case 'a': return '\a'; return '\'';
case 'b': return '\b'; case '"':
case 'f': return '\f'; return '"';
case 'n': return '\n'; case 'a':
case 'r': return '\r'; return '\a';
case 't': return '\t'; case 'b':
case 'v': return '\v'; return '\b';
case '0': case '1': case '2': case '3': return LexUnEscapeCharacterConstant(From, End, ThisChar, 8); case 'f':
case 'x': return LexUnEscapeCharacterConstant(From, End, '0', 16); return '\f';
default: return ThisChar; case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '0':
case '1':
case '2':
case '3':
return LexUnEscapeCharacterConstant(From, End, ThisChar, 8);
case 'x':
return LexUnEscapeCharacterConstant(From, End, '0', 16);
default:
return ThisChar;
} }
} }
else else
@ -378,7 +395,8 @@ void LexSkipComment(struct LexState *Lexer, char NextChar,
{ {
if (NextChar == '*') { if (NextChar == '*') {
/* conventional C comment */ /* conventional C comment */
while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) { while (Lexer->Pos != Lexer->End &&
(*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) {
if (*Lexer->Pos == '\n') if (*Lexer->Pos == '\n')
Lexer->EmitExtraNewlines++; Lexer->EmitExtraNewlines++;
@ -404,7 +422,8 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
char NextChar; char NextChar;
enum LexToken GotToken = TokenNone; enum LexToken GotToken = TokenNone;
/* handle cases line multi-line comments or string constants which mess up the line count */ /* handle cases line multi-line comments or string constants
which mess up the line count */
if (Lexer->EmitExtraNewlines > 0) { if (Lexer->EmitExtraNewlines > 0) {
Lexer->EmitExtraNewlines--; Lexer->EmitExtraNewlines--;
return TokenEndOfLine; return TokenEndOfLine;
@ -420,7 +439,8 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
Lexer->Mode = LexModeNormal; Lexer->Mode = LexModeNormal;
Lexer->CharacterPos = 0; Lexer->CharacterPos = 0;
return TokenEndOfLine; return TokenEndOfLine;
} else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace) } else if (Lexer->Mode == LexModeHashDefine ||
Lexer->Mode == LexModeHashDefineSpace)
Lexer->Mode = LexModeHashDefineSpace; Lexer->Mode = LexModeHashDefineSpace;
else if (Lexer->Mode == LexModeHashDefineSpaceIdent) else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
Lexer->Mode = LexModeNormal; Lexer->Mode = LexModeNormal;
@ -487,16 +507,19 @@ enum LexToken LexScanGetToken(Picoc *pc, struct LexState *Lexer,
} }
break; break;
case '>': case '>':
NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=',
TokenShiftRightAssign, TokenGreaterThan);
break; break;
case ';': case ';':
GotToken = TokenSemicolon; GotToken = TokenSemicolon;
break; break;
case '&': case '&':
NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd,
TokenAmpersand);
break; break;
case '|': case '|':
NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr); NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr,
TokenArithmeticOr);
break; break;
case '{': case '{':
GotToken = TokenLeftBrace; GotToken = TokenLeftBrace;
@ -552,7 +575,8 @@ int LexTokenSize(enum LexToken Token)
} }
} }
/* produce tokens from the lexer and return a heap buffer with the result - used for scanning */ /* produce tokens from the lexer and return a heap buffer with
the result - used for scanning */
void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen) void *LexTokenise(Picoc *pc, struct LexState *Lexer, int *TokenLen)
{ {
int MemUsed = 0; int MemUsed = 0;
@ -674,14 +698,16 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value,
} }
} }
if (Parser->FileName == pc->StrEmpty && (pc->InteractiveHead == NULL || Token == TokenEOF)) { if (Parser->FileName == pc->StrEmpty &&
(pc->InteractiveHead == NULL || Token == TokenEOF)) {
/* we're at the end of an interactive input token list */ /* we're at the end of an interactive input token list */
char LineBuffer[LINEBUFFER_MAX]; char LineBuffer[LINEBUFFER_MAX];
void *LineTokens; void *LineTokens;
int LineBytes; int LineBytes;
struct TokenLine *LineNode; struct TokenLine *LineNode;
if (pc->InteractiveHead == NULL || (unsigned char*)Parser->Pos == &pc->InteractiveTail->Tokens[pc->InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) { if (pc->InteractiveHead == NULL ||
(unsigned char*)Parser->Pos == &pc->InteractiveTail->Tokens[pc->InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) {
/* get interactive input */ /* get interactive input */
if (pc->LexUseStatementPrompt) { if (pc->LexUseStatementPrompt) {
Prompt = INTERACTIVE_PROMPT_STATEMENT; Prompt = INTERACTIVE_PROMPT_STATEMENT;
@ -714,7 +740,9 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value,
/* go to the next token line */ /* go to the next token line */
if (Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) { if (Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) {
/* scan for the line */ /* scan for the line */
for (pc->InteractiveCurrentLine = pc->InteractiveHead; Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) { for (pc->InteractiveCurrentLine = pc->InteractiveHead;
Parser->Pos != &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET];
pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
assert(pc->InteractiveCurrentLine->Next != NULL); assert(pc->InteractiveCurrentLine->Next != NULL);
} }
} }
@ -799,7 +827,8 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot)
/* is the identifier defined? */ /* is the identifier defined? */
IsDefined = TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier, IsDefined = TableGet(&Parser->pc->GlobalTable, IdentValue->Val->Identifier,
&SavedValue, NULL, NULL, NULL); &SavedValue, NULL, NULL, NULL);
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ((IsDefined && !IfNot) || (!IsDefined && IfNot))) { if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel &&
((IsDefined && !IfNot) || (!IsDefined && IfNot))) {
/* #if is active, evaluate to this new level */ /* #if is active, evaluate to this new level */
Parser->HashIfEvaluateToLevel++; Parser->HashIfEvaluateToLevel++;
} }
@ -833,7 +862,8 @@ void LexHashIf(struct ParseState *Parser)
ProgramFail(Parser, "value expected"); ProgramFail(Parser, "value expected");
/* is the identifier defined? */ /* is the identifier defined? */
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && IdentValue->Val->Character) { if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel &&
IdentValue->Val->Character) {
/* #if is active, evaluate to this new level */ /* #if is active, evaluate to this new level */
Parser->HashIfEvaluateToLevel++; Parser->HashIfEvaluateToLevel++;
} }
@ -845,7 +875,7 @@ void LexHashIf(struct ParseState *Parser)
void LexHashElse(struct ParseState *Parser) void LexHashElse(struct ParseState *Parser)
{ {
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel - 1) if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel - 1)
Parser->HashIfEvaluateToLevel++; /* #if was not active, make this next section active */ 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 was active, now go inactive */
if (Parser->HashIfLevel == 0) if (Parser->HashIfLevel == 0)
@ -904,7 +934,8 @@ void LexPrintToken(enum LexToken Token)
#endif #endif
/* get the next token given a parser state, pre-processing as we go */ /* get the next token given a parser state, pre-processing as we go */
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos) enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value,
int IncPos)
{ {
int TryNextToken; int TryNextToken;
enum LexToken Token; enum LexToken Token;
@ -936,7 +967,8 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
} }
/* if we're going to reject this token, increment the token pointer to the next one */ /* if we're going to reject this token, increment the token pointer to the next one */
TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel && Token != TokenEOF) || WasPreProcToken; TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel &&
Token != TokenEOF) || WasPreProcToken;
if (!IncPos && TryNextToken) if (!IncPos && TryNextToken)
LexGetRawToken(Parser, NULL, true); LexGetRawToken(Parser, NULL, true);
@ -963,7 +995,8 @@ void LexToEndOfLine(struct ParseState *Parser)
} }
} }
/* copy the tokens from StartParser to EndParser into new memory, removing TokenEOFs and terminate with a TokenEndOfFunction */ /* copy the tokens from StartParser to EndParser into new memory, removing
TokenEOFs and terminate with a TokenEndOfFunction */
void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser) void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser)
{ {
int MemSize = 0; int MemSize = 0;
@ -981,10 +1014,15 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
memcpy(NewTokens, (void *)StartParser->Pos, MemSize); memcpy(NewTokens, (void *)StartParser->Pos, MemSize);
} else { } else {
/* we're in interactive mode - add up line by line */ /* we're in interactive mode - add up line by line */
for (pc->InteractiveCurrentLine = pc->InteractiveHead; pc->InteractiveCurrentLine != NULL && (Pos < &pc->InteractiveCurrentLine->Tokens[0] || Pos >= &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]); pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) { for (pc->InteractiveCurrentLine = pc->InteractiveHead;
pc->InteractiveCurrentLine != NULL &&
(Pos < &pc->InteractiveCurrentLine->Tokens[0] ||
Pos >= &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]);
pc->InteractiveCurrentLine = pc->InteractiveCurrentLine->Next) {
} /* find the line we just counted */ } /* find the line we just counted */
if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]) { if (EndParser->Pos >= StartParser->Pos &&
EndParser->Pos < &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes]) {
/* all on a single line */ /* all on a single line */
MemSize = EndParser->Pos - StartParser->Pos; MemSize = EndParser->Pos - StartParser->Pos;
NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, true); NewTokens = VariableAlloc(pc, StartParser, MemSize + TOKEN_DATA_OFFSET, true);
@ -993,7 +1031,10 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
/* it's spread across multiple lines */ /* it's spread across multiple lines */
MemSize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; MemSize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) for (ILine = pc->InteractiveCurrentLine->Next;
ILine != NULL &&
(EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]);
ILine = ILine->Next)
MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET; MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET;
assert(ILine != NULL); assert(ILine != NULL);
@ -1003,7 +1044,9 @@ void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser
CopySize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; CopySize = &pc->InteractiveCurrentLine->Tokens[pc->InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos;
memcpy(NewTokens, Pos, CopySize); memcpy(NewTokens, Pos, CopySize);
NewTokenPos = NewTokens + CopySize; NewTokenPos = NewTokens + CopySize;
for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) { for (ILine = pc->InteractiveCurrentLine->Next; ILine != NULL &&
(EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]);
ILine = ILine->Next) {
memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET); memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET);
NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET; NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET;
} }
@ -1037,7 +1080,9 @@ void LexInteractiveClear(Picoc *pc, struct ParseState *Parser)
/* indicate that we've completed up to this point in the interactive input and free expired tokens */ /* indicate that we've completed up to this point in the interactive input and free expired tokens */
void LexInteractiveCompleted(Picoc *pc, struct ParseState *Parser) void LexInteractiveCompleted(Picoc *pc, struct ParseState *Parser)
{ {
while (pc->InteractiveHead != NULL && !(Parser->Pos >= &pc->InteractiveHead->Tokens[0] && Parser->Pos < &pc->InteractiveHead->Tokens[pc->InteractiveHead->NumBytes])) { while (pc->InteractiveHead != NULL &&
!(Parser->Pos >= &pc->InteractiveHead->Tokens[0] &&
Parser->Pos < &pc->InteractiveHead->Tokens[pc->InteractiveHead->NumBytes])) {
/* this token line is no longer needed - free it */ /* this token line is no longer needed - free it */
struct TokenLine *NextLine = pc->InteractiveHead->Next; struct TokenLine *NextLine = pc->InteractiveHead->Next;

36
parse.c
View file

@ -49,7 +49,8 @@ int ParseCountParams(struct ParseState *Parser)
if (Token != TokenCloseBracket && Token != TokenEOF) { if (Token != TokenCloseBracket && Token != TokenEOF) {
/* count the number of parameters */ /* count the number of parameters */
ParamCount++; ParamCount++;
while ((Token = LexGetToken(Parser, NULL, true)) != TokenCloseBracket && Token != TokenEOF) { while ((Token = LexGetToken(Parser, NULL, true)) !=
TokenCloseBracket && Token != TokenEOF) {
if (Token == TokenComma) if (Token == TokenComma)
ParamCount++; ParamCount++;
} }
@ -95,7 +96,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) { for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) {
/* harvest the parameters into the function definition */ /* harvest the parameters into the function definition */
if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, false) == TokenEllipsis) { if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 &&
LexGetToken(&ParamParser, NULL, false) == TokenEllipsis) {
/* ellipsis at end */ /* ellipsis at end */
FuncValue->Val->FuncDef.NumParams--; FuncValue->Val->FuncDef.NumParams--;
FuncValue->Val->FuncDef.VarArgs = true; FuncValue->Val->FuncDef.VarArgs = true;
@ -118,7 +120,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
ProgramFail(&ParamParser, "comma expected"); ProgramFail(&ParamParser, "comma expected");
} }
if (FuncValue->Val->FuncDef.NumParams != 0 && Token != TokenCloseBracket && Token != TokenComma && Token != TokenEllipsis) if (FuncValue->Val->FuncDef.NumParams != 0 && Token != TokenCloseBracket &&
Token != TokenComma && Token != TokenEllipsis)
ProgramFail(&ParamParser, "bad parameter"); ProgramFail(&ParamParser, "bad parameter");
if (strcmp(Identifier, "main") == 0) { if (strcmp(Identifier, "main") == 0) {
@ -128,7 +131,8 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
ProgramFail(Parser, "main() should return an int or void"); ProgramFail(Parser, "main() should return an int or void");
if (FuncValue->Val->FuncDef.NumParams != 0 && if (FuncValue->Val->FuncDef.NumParams != 0 &&
(FuncValue->Val->FuncDef.NumParams != 2 || FuncValue->Val->FuncDef.ParamType[0] != &pc->IntType) ) (FuncValue->Val->FuncDef.NumParams != 2 ||
FuncValue->Val->FuncDef.ParamType[0] != &pc->IntType) )
ProgramFail(Parser, "bad parameters to main()"); ProgramFail(Parser, "bad parameters to main()");
} }
@ -238,7 +242,8 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
ElementType = ElementType->FromType; ElementType = ElementType->FromType;
/* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */ /* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */
if (LexGetToken(Parser, NULL, false) == TokenStringConstant && ElementType->FromType->Base == TypeChar) if (LexGetToken(Parser, NULL, false) == TokenStringConstant &&
ElementType->FromType->Base == TypeChar)
break; break;
} }
ElementSize = TypeSize(ElementType, ElementType->ArraySize, true); ElementSize = TypeSize(ElementType, ElementType->ArraySize, true);
@ -320,7 +325,9 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
TypeParseFront(Parser, &BasicType, &IsStatic); TypeParseFront(Parser, &BasicType, &IsStatic);
do { do {
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType && Token != TokenEnumType) && Identifier == pc->StrEmpty) if ((Token != TokenVoidType && Token != TokenStructType &&
Token != TokenUnionType && Token != TokenEnumType) &&
Identifier == pc->StrEmpty)
ProgramFail(Parser, "identifier expected"); ProgramFail(Parser, "identifier expected");
if (Identifier != pc->StrEmpty) { if (Identifier != pc->StrEmpty) {
@ -381,13 +388,14 @@ void ParseMacroDefinition(struct ParseState *Parser)
sizeof(struct MacroDef) + sizeof(const char *) * NumParams, sizeof(struct MacroDef) + sizeof(const char *) * NumParams,
false, NULL, true); false, NULL, true);
MacroValue->Val->MacroDef.NumParams = NumParams; MacroValue->Val->MacroDef.NumParams = NumParams;
MacroValue->Val->MacroDef.ParamName = (char **)((char *)MacroValue->Val + sizeof(struct MacroDef)); MacroValue->Val->MacroDef.ParamName = (char**)((char*)MacroValue->Val+sizeof(struct MacroDef));
Token = LexGetToken(Parser, &ParamName, true); Token = LexGetToken(Parser, &ParamName, true);
while (Token == TokenIdentifier) { while (Token == TokenIdentifier) {
/* store a parameter name */ /* store a parameter name */
MacroValue->Val->MacroDef.ParamName[ParamCount++] = ParamName->Val->Identifier; MacroValue->Val->MacroDef.ParamName[ParamCount++] =
ParamName->Val->Identifier;
/* get the trailing comma */ /* get the trailing comma */
Token = LexGetToken(Parser, NULL, true); Token = LexGetToken(Parser, NULL, true);
@ -411,7 +419,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
ParserCopy(&MacroValue->Val->MacroDef.Body, Parser); ParserCopy(&MacroValue->Val->MacroDef.Body, Parser);
MacroValue->Typ = &Parser->pc->MacroType; MacroValue->Typ = &Parser->pc->MacroType;
LexToEndOfLine(Parser); LexToEndOfLine(Parser);
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser); MacroValue->Val->MacroDef.Body.Pos =
LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
if (!TableSet(Parser->pc, &Parser->pc->GlobalTable, MacroNameStr, MacroValue, if (!TableSet(Parser->pc, &Parser->pc->GlobalTable, MacroNameStr, MacroValue,
(char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) (char *)Parser->FileName, Parser->Line, Parser->CharacterPos))
@ -595,7 +604,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
if (NextToken == TokenColon) { if (NextToken == TokenColon) {
/* declare the identifier as a goto label */ /* declare the identifier as a goto label */
LexGetToken(Parser, NULL, true); LexGetToken(Parser, NULL, true);
if (Parser->Mode == RunModeGoto && LexerValue->Val->Identifier == Parser->SearchGotoLabel) if (Parser->Mode == RunModeGoto &&
LexerValue->Val->Identifier == Parser->SearchGotoLabel)
Parser->Mode = RunModeRun; Parser->Mode = RunModeRun;
CheckTrailingSemicolon = false; CheckTrailingSemicolon = false;
break; break;
@ -727,7 +737,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
int OldSearchLabel = Parser->SearchLabel; int OldSearchLabel = Parser->SearchLabel;
Parser->Mode = RunModeCaseSearch; Parser->Mode = RunModeCaseSearch;
Parser->SearchLabel = Condition; Parser->SearchLabel = Condition;
ParseBlock(Parser, true, (OldMode != RunModeSkip) && (OldMode != RunModeReturn)); ParseBlock(Parser, true, (OldMode != RunModeSkip) &&
(OldMode != RunModeReturn));
if (Parser->Mode != RunModeReturn) if (Parser->Mode != RunModeReturn)
Parser->Mode = OldMode; Parser->Mode = OldMode;
Parser->SearchLabel = OldSearchLabel; Parser->SearchLabel = OldSearchLabel;
@ -764,7 +775,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
break; break;
case TokenReturn: case TokenReturn:
if (Parser->Mode == RunModeRun) { if (Parser->Mode == RunModeRun) {
if (!Parser->pc->TopStackFrame || Parser->pc->TopStackFrame->ReturnValue->Typ->Base != TypeVoid) { if (!Parser->pc->TopStackFrame ||
Parser->pc->TopStackFrame->ReturnValue->Typ->Base != TypeVoid) {
if (!ExpressionParse(Parser, &CValue)) if (!ExpressionParse(Parser, &CValue))
ProgramFail(Parser, "value required in return"); ProgramFail(Parser, "value required in return");
if (!Parser->pc->TopStackFrame) /* return from top-level program? */ if (!Parser->pc->TopStackFrame) /* return from top-level program? */

View file

@ -77,20 +77,24 @@ void PicocCallMain(Picoc *pc, int argc, char **argv)
if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) { if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) {
if (FuncValue->Val->FuncDef.NumParams == 0) if (FuncValue->Val->FuncDef.NumParams == 0)
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID, PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID,
strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), true, true, false, gEnableDebugger); strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), true, true, false,
gEnableDebugger);
else else
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID,
strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), true, true, false, gEnableDebugger); strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), true, true, false,
gEnableDebugger);
} else { } else {
VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType, VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType,
(union AnyValue *)&pc->PicocExitValue, true); (union AnyValue *)&pc->PicocExitValue, true);
if (FuncValue->Val->FuncDef.NumParams == 0) if (FuncValue->Val->FuncDef.NumParams == 0)
PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT, PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT,
strlen(CALL_MAIN_NO_ARGS_RETURN_INT), true, true, false, gEnableDebugger); strlen(CALL_MAIN_NO_ARGS_RETURN_INT), true, true, false,
gEnableDebugger);
else else
PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_INT, PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_INT,
strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), true, true, false, gEnableDebugger); strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), true, true, false,
gEnableDebugger);
} }
} }
#endif #endif
@ -105,7 +109,8 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
if (SourceText != NULL) { if (SourceText != NULL) {
/* find the source line */ /* find the source line */
for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++) { for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' &&
LineCount < Line; LinePos++) {
if (*LinePos == '\n') if (*LinePos == '\n')
LineCount++; LineCount++;
} }
@ -116,7 +121,8 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
PrintCh('\n', Stream); PrintCh('\n', Stream);
/* display the error position */ /* display the error position */
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) { for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' &&
(CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) {
if (*CPos == '\t') if (*CPos == '\t')
PrintCh('\t', Stream); PrintCh('\t', Stream);
else else
@ -124,7 +130,9 @@ void PrintSourceTextErrorLine(IOFILE *Stream, const char *FileName,
} }
} else { } else {
/* assume we're in interactive mode - try to make the arrow match up with the input text */ /* assume we're in interactive mode - try to make the arrow match up with the input text */
for (CCount = 0; CCount < CharacterPos+(int)strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++) for (CCount = 0;
CCount < CharacterPos+(int)strlen(INTERACTIVE_PROMPT_STATEMENT);
CCount++)
PrintCh(' ', Stream); PrintCh(' ', Stream);
} }
PlatformPrintf(Stream, "^\n%s:%d:%d ", FileName, Line, CharacterPos); PlatformPrintf(Stream, "^\n%s:%d:%d ", FileName, Line, CharacterPos);
@ -173,7 +181,8 @@ void AssignFail(struct ParseState *Parser, const char *Format,
PlatformPrintf(Stream, Format, Num1, Num2); PlatformPrintf(Stream, Format, Num1, Num2);
if (FuncName != NULL) if (FuncName != NULL)
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName); PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo,
FuncName);
PlatformPrintf(Stream, "\n"); PlatformPrintf(Stream, "\n");
PlatformExit(Parser->pc, 1); PlatformExit(Parser->pc, 1);

15
table.c
View file

@ -39,7 +39,8 @@ void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size,
} }
/* check a hash table entry for a key */ /* check a hash table entry for a key */
static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *AddAt) static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key,
int *AddAt)
{ {
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
struct TableEntry *Entry; struct TableEntry *Entry;
@ -62,7 +63,8 @@ int TableSet(Picoc *pc, struct Table *Tbl, char *Key, struct Value *Val,
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
if (FoundEntry == NULL) { /* add it to the table */ if (FoundEntry == NULL) { /* add it to the table */
struct TableEntry *NewEntry = VariableAlloc(pc, NULL, sizeof(struct TableEntry), Tbl->OnHeap); struct TableEntry *NewEntry = VariableAlloc(pc, NULL,
sizeof(struct TableEntry), Tbl->OnHeap);
NewEntry->DeclFileName = DeclFileName; NewEntry->DeclFileName = DeclFileName;
NewEntry->DeclLine = DeclLine; NewEntry->DeclLine = DeclLine;
NewEntry->DeclColumn = DeclColumn; NewEntry->DeclColumn = DeclColumn;
@ -103,7 +105,8 @@ struct Value *TableDelete(Picoc *pc, struct Table *Tbl, const char *Key)
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
struct TableEntry **EntryPtr; struct TableEntry **EntryPtr;
for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) { for (EntryPtr = &Tbl->HashTable[HashValue];
*EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
if ((*EntryPtr)->p.v.Key == Key) { if ((*EntryPtr)->p.v.Key == Key) {
struct TableEntry *DeleteEntry = *EntryPtr; struct TableEntry *DeleteEntry = *EntryPtr;
struct Value *Val = DeleteEntry->p.v.Val; struct Value *Val = DeleteEntry->p.v.Val;
@ -142,7 +145,8 @@ char *TableSetIdentifier(Picoc *pc, struct Table *Tbl, const char *Ident, int Id
if (FoundEntry != NULL) if (FoundEntry != NULL)
return &FoundEntry->p.Key[0]; return &FoundEntry->p.Key[0];
else { /* add it to the table - we economise by not allocating the whole structure here */ else { /* add it to the table - we economise by not allocating the whole structure here */
struct TableEntry *NewEntry = HeapAllocMem(pc, sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1); struct TableEntry *NewEntry = HeapAllocMem(pc,
sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1);
if (NewEntry == NULL) if (NewEntry == NULL)
ProgramFailNoParser(pc, "(TableSetIdentifier) out of memory"); ProgramFailNoParser(pc, "(TableSetIdentifier) out of memory");
@ -173,7 +177,8 @@ void TableStrFree(Picoc *pc)
struct TableEntry *NextEntry; struct TableEntry *NextEntry;
for (Count = 0; Count < pc->StringTable.Size; Count++) { for (Count = 0; Count < pc->StringTable.Size; Count++) {
for (Entry = pc->StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) { for (Entry = pc->StringTable.HashTable[Count];
Entry != NULL; Entry = NextEntry) {
NextEntry = Entry->Next; NextEntry = Entry->Next;
HeapFreeMem(pc, Entry); HeapFreeMem(pc, Entry);
} }

60
type.c
View file

@ -13,7 +13,8 @@ struct ValueType *TypeAdd(Picoc *pc, struct ParseState *Parser,
struct ValueType *ParentType, enum BaseType Base, int ArraySize, struct ValueType *ParentType, enum BaseType Base, int ArraySize,
const char *Identifier, int Sizeof, int AlignBytes) const char *Identifier, int Sizeof, int AlignBytes)
{ {
struct ValueType *NewType = VariableAlloc(pc, Parser, sizeof(struct ValueType), true); struct ValueType *NewType = VariableAlloc(pc, Parser,
sizeof(struct ValueType), true);
NewType->Base = Base; NewType->Base = Base;
NewType->ArraySize = ArraySize; NewType->ArraySize = ArraySize;
NewType->Sizeof = Sizeof; NewType->Sizeof = Sizeof;
@ -38,7 +39,8 @@ struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
int Sizeof; int Sizeof;
int AlignBytes; int AlignBytes;
struct ValueType *ThisType = ParentType->DerivedTypeList; struct ValueType *ThisType = ParentType->DerivedTypeList;
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier)) while (ThisType != NULL && (ThisType->Base != Base ||
ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier))
ThisType = ThisType->Next; ThisType = ThisType->Next;
if (ThisType != NULL) { if (ThisType != NULL) {
@ -50,16 +52,24 @@ struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
switch (Base) { switch (Base) {
case TypePointer: case TypePointer:
Sizeof = sizeof(void*); AlignBytes = PointerAlignBytes; break; Sizeof = sizeof(void*);
AlignBytes = PointerAlignBytes;
break;
case TypeArray: case TypeArray:
Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break; Sizeof = ArraySize * ParentType->Sizeof;
AlignBytes = ParentType->AlignBytes;
break;
case TypeEnum: case TypeEnum:
Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break; Sizeof = sizeof(int);
AlignBytes = IntAlignBytes;
break;
default: default:
Sizeof = 0; AlignBytes = 0; break; /* structs and unions will get bigger when we add members to them */ Sizeof = 0; AlignBytes = 0;
break; /* structs and unions will get bigger when we add members to them */
} }
return TypeAdd(pc, Parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes); return TypeAdd(pc, Parser, ParentType, Base, ArraySize, Identifier, Sizeof,
AlignBytes);
} }
/* stack space used by a value */ /* stack space used by a value */
@ -185,7 +195,8 @@ void TypeCleanup(Picoc *pc)
} }
/* parse a struct or union declaration */ /* parse a struct or union declaration */
void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct) void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ,
int IsStruct)
{ {
char *MemberIdentifier; char *MemberIdentifier;
char *StructIdentifier; char *StructIdentifier;
@ -216,7 +227,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
/* use the already defined structure */ /* use the already defined structure */
#if 0 #if 0
if ((*Typ)->Members == NULL) if ((*Typ)->Members == NULL)
ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier); ProgramFail(Parser, "structure '%s' isn't defined",
LexValue->Val->Identifier);
#endif #endif
return; return;
} }
@ -238,7 +250,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
if (MemberType == NULL || MemberIdentifier == NULL) if (MemberType == NULL || MemberIdentifier == NULL)
ProgramFail(Parser, "invalid type in struct"); ProgramFail(Parser, "invalid type in struct");
MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), false, NULL, true); MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), false,
NULL, true);
MemberValue->Typ = MemberType; MemberValue->Typ = MemberType;
if (IsStruct) { if (IsStruct) {
/* allocate this member's location in the struct */ /* allocate this member's location in the struct */
@ -249,7 +262,8 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
MemberValue->Val->Integer = (*Typ)->Sizeof; MemberValue->Val->Integer = (*Typ)->Sizeof;
(*Typ)->Sizeof += TypeSizeValue(MemberValue, true); (*Typ)->Sizeof += TypeSizeValue(MemberValue, true);
} else { } else {
/* union members always start at 0, make sure it's big enough to hold the largest member */ /* union members always start at 0, make sure it's big enough
to hold the largest member */
MemberValue->Val->Integer = 0; MemberValue->Val->Integer = 0;
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof) if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
(*Typ)->Sizeof = TypeSizeValue(MemberValue, true); (*Typ)->Sizeof = TypeSizeValue(MemberValue, true);
@ -317,7 +331,8 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
EnumIdentifier = PlatformMakeTempName(pc, TempNameBuf); EnumIdentifier = PlatformMakeTempName(pc, TempNameBuf);
} }
TypeGetMatching(pc, Parser, &pc->UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace); TypeGetMatching(pc, Parser, &pc->UberType, TypeEnum, 0, EnumIdentifier,
Token != TokenLeftBrace);
*Typ = &pc->IntType; *Typ = &pc->IntType;
if (Token != TokenLeftBrace) { if (Token != TokenLeftBrace) {
/* use the already defined enum */ /* use the already defined enum */
@ -356,7 +371,8 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
} }
/* parse a type - just the basic type */ /* parse a type - just the basic type */
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic) int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
int *IsStatic)
{ {
int Unsigned = false; int Unsigned = false;
int StaticQualifier = false; int StaticQualifier = false;
@ -370,7 +386,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
/* ignore leading type qualifiers */ /* ignore leading type qualifiers */
ParserCopy(&Before, Parser); ParserCopy(&Before, Parser);
Token = LexGetToken(Parser, &LexerValue, true); Token = LexGetToken(Parser, &LexerValue, true);
while (Token == TokenStaticType || Token == TokenAutoType || Token == TokenRegisterType || Token == TokenExternType) { while (Token == TokenStaticType || Token == TokenAutoType ||
Token == TokenRegisterType || Token == TokenExternType) {
if (Token == TokenStaticType) if (Token == TokenStaticType)
StaticQualifier = true; StaticQualifier = true;
@ -385,7 +402,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false); enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
Unsigned = (Token == TokenUnsignedType); Unsigned = (Token == TokenUnsignedType);
if (FollowToken != TokenIntType && FollowToken != TokenLongType && FollowToken != TokenShortType && FollowToken != TokenCharType) { if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
FollowToken != TokenShortType && FollowToken != TokenCharType) {
if (Token == TokenUnsignedType) if (Token == TokenUnsignedType)
*Typ = &pc->UnsignedIntType; *Typ = &pc->UnsignedIntType;
else else
@ -443,7 +461,8 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
} }
/* parse a type - the part at the end after the identifier. eg. array specifications etc. */ /* parse a type - the part at the end after the identifier. eg. array specifications etc. */
struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *FromType) struct ValueType *TypeParseBack(struct ParseState *Parser,
struct ValueType *FromType)
{ {
enum LexToken Token; enum LexToken Token;
struct ParseState Before; struct ParseState Before;
@ -480,7 +499,8 @@ struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *Fro
} }
} }
/* parse a type - the part which is repeated with each identifier in a declaration list */ /* parse a type - the part which is repeated with each
identifier in a declaration list */
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
struct ValueType **Typ, char **Identifier) struct ValueType **Typ, char **Identifier)
{ {
@ -543,13 +563,15 @@ void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
TypeParseIdentPart(Parser, BasicType, Typ, Identifier); TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
} }
/* check if a type has been fully defined - otherwise it's just a forward declaration */ /* check if a type has been fully defined - otherwise it's
just a forward declaration */
int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ) int TypeIsForwardDeclared(struct ParseState *Parser, struct ValueType *Typ)
{ {
if (Typ->Base == TypeArray) if (Typ->Base == TypeArray)
return TypeIsForwardDeclared(Parser, Typ->FromType); return TypeIsForwardDeclared(Parser, Typ->FromType);
if ( (Typ->Base == TypeStruct || Typ->Base == TypeUnion) && Typ->Members == NULL) if ((Typ->Base == TypeStruct || Typ->Base == TypeUnion) &&
Typ->Members == NULL)
return true; return true;
return false; return false;

View file

@ -22,7 +22,9 @@ void VariableFree(Picoc *pc, struct Value *Val)
{ {
if (Val->ValOnHeap || Val->AnyValOnHeap) { if (Val->ValOnHeap || Val->AnyValOnHeap) {
/* free function bodies */ /* free function bodies */
if (Val->Typ == &pc->FunctionType && Val->Val->FuncDef.Intrinsic == NULL && Val->Val->FuncDef.Body.Pos != NULL) if (Val->Typ == &pc->FunctionType &&
Val->Val->FuncDef.Intrinsic == NULL &&
Val->Val->FuncDef.Body.Pos != NULL)
HeapFreeMem(pc, (void *)Val->Val->FuncDef.Body.Pos); HeapFreeMem(pc, (void *)Val->Val->FuncDef.Body.Pos);
/* free macro bodies */ /* free macro bodies */
@ -47,7 +49,9 @@ void VariableTableCleanup(Picoc *pc, struct Table *HashTable)
struct TableEntry *NextEntry; struct TableEntry *NextEntry;
for (Count = 0; Count < HashTable->Size; Count++) { for (Count = 0; Count < HashTable->Size; Count++) {
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) { for (Entry = HashTable->HashTable[Count];
Entry != NULL;
Entry = NextEntry) {
NextEntry = Entry->Next; NextEntry = Entry->Next;
VariableFree(pc, Entry->p.v.Val); VariableFree(pc, Entry->p.v.Val);
@ -63,7 +67,8 @@ void VariableCleanup(Picoc *pc)
VariableTableCleanup(pc, &pc->StringLiteralTable); VariableTableCleanup(pc, &pc->StringLiteralTable);
} }
/* allocate some memory, either on the heap or the stack and check if we've run out */ /* allocate some memory, either on the heap or the stack
and check if we've run out */
void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap) void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
{ {
void *NewValue; void *NewValue;
@ -84,7 +89,8 @@ void *VariableAlloc(Picoc *pc, struct ParseState *Parser, int Size, int OnHeap)
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack using space dependent on what type we want */ /* allocate a value either on the heap or the stack using space
dependent on what type we want */
struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser, struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser,
int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap) int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap)
{ {
@ -110,14 +116,16 @@ struct Value *VariableAllocValueFromType(Picoc *pc, struct ParseState *Parser,
struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap) struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap)
{ {
int Size = TypeSize(Typ, Typ->ArraySize, false); int Size = TypeSize(Typ, Typ->ArraySize, false);
struct Value *NewValue = VariableAllocValueAndData(pc, Parser, Size, IsLValue, LValueFrom, OnHeap); struct Value *NewValue = VariableAllocValueAndData(pc, Parser, Size,
IsLValue, LValueFrom, OnHeap);
assert(Size >= 0 || Typ == &pc->VoidType); assert(Size >= 0 || Typ == &pc->VoidType);
NewValue->Typ = Typ; NewValue->Typ = Typ;
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */ /* allocate a value either on the heap or the stack and copy
its value. handles overlapping data */
struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser, struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser,
struct Value *FromValue, int OnHeap) struct Value *FromValue, int OnHeap)
{ {
@ -136,12 +144,14 @@ struct Value *VariableAllocValueAndCopy(Picoc *pc, struct ParseState *Parser,
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack from an existing AnyValue and type */ /* allocate a value either on the heap or the stack from an
existing AnyValue and type */
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser,
struct ValueType *Typ, union AnyValue *FromValue, int IsLValue, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue,
struct Value *LValueFrom) struct Value *LValueFrom)
{ {
struct Value *NewValue = VariableAlloc(Parser->pc, Parser, sizeof(struct Value), false); struct Value *NewValue = VariableAlloc(Parser->pc, Parser,
sizeof(struct Value), false);
NewValue->Typ = Typ; NewValue->Typ = Typ;
NewValue->Val = FromValue; NewValue->Val = FromValue;
NewValue->ValOnHeap = false; NewValue->ValOnHeap = false;
@ -153,7 +163,8 @@ struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser,
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack from an existing Value, sharing the value */ /* allocate a value either on the heap or the stack from an
existing Value, sharing the value */
struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *VariableAllocValueShared(struct ParseState *Parser,
struct Value *FromValue) struct Value *FromValue)
{ {
@ -183,18 +194,22 @@ int VariableScopeBegin(struct ParseState *Parser, int* OldScopeID)
if (Parser->ScopeID == -1) if (Parser->ScopeID == -1)
return -1; return -1;
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ? &(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable; struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ?
&(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
/* XXX dumb hash, let's hope for no collisions... */ /* XXX dumb hash, let's hope for no collisions... */
*OldScopeID = Parser->ScopeID; *OldScopeID = Parser->ScopeID;
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*)); Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) *
((int)(intptr_t)(Parser->Pos) / sizeof(char*));
/* or maybe a more human-readable hash for debugging? */ /* or maybe a more human-readable hash for debugging? */
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */ /* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
for (Count = 0; Count < HashTable->Size; Count++) { for (Count = 0; Count < HashTable->Size; Count++) {
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) { for (Entry = HashTable->HashTable[Count];
Entry != NULL; Entry = NextEntry) {
NextEntry = Entry->Next; NextEntry = Entry->Next;
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope == true) { if (Entry->p.v.Val->ScopeID == Parser->ScopeID &&
Entry->p.v.Val->OutOfScope == true) {
Entry->p.v.Val->OutOfScope = false; Entry->p.v.Val->OutOfScope = false;
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1); Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
#ifdef DEBUG_VAR_SCOPE #ifdef DEBUG_VAR_SCOPE
@ -222,12 +237,15 @@ void VariableScopeEnd(struct ParseState *Parser, int ScopeID, int PrevScopeID)
if (ScopeID == -1) if (ScopeID == -1)
return; return;
struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ? &(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable; struct Table *HashTable = (Parser->pc->TopStackFrame == NULL) ?
&(Parser->pc->GlobalTable) : &(Parser->pc->TopStackFrame)->LocalTable;
for (Count = 0; Count < HashTable->Size; Count++) { for (Count = 0; Count < HashTable->Size; Count++) {
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) { for (Entry = HashTable->HashTable[Count];
Entry != NULL; Entry = NextEntry) {
NextEntry = Entry->Next; NextEntry = Entry->Next;
if ((Entry->p.v.Val->ScopeID == ScopeID) && (Entry->p.v.Val->OutOfScope == false)) { if ((Entry->p.v.Val->ScopeID == ScopeID) &&
(Entry->p.v.Val->OutOfScope == false)) {
#ifdef DEBUG_VAR_SCOPE #ifdef DEBUG_VAR_SCOPE
if (!FirstPrint) PRINT_SOURCE_POS(); if (!FirstPrint) PRINT_SOURCE_POS();
FirstPrint = 1; FirstPrint = 1;
@ -248,10 +266,14 @@ int VariableDefinedAndOutOfScope(Picoc * pc, const char* Ident)
int Count; int Count;
struct TableEntry *Entry; struct TableEntry *Entry;
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable; struct Table * HashTable = (pc->TopStackFrame == NULL) ?
&(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
for (Count = 0; Count < HashTable->Size; Count++) { for (Count = 0; Count < HashTable->Size; Count++) {
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next) { for (Entry = HashTable->HashTable[Count];
if (Entry->p.v.Val->OutOfScope == true && (char*)((intptr_t)Entry->p.v.Key & ~1) == Ident) Entry != NULL; Entry = Entry->Next) {
if (Entry->p.v.Val->OutOfScope == true &&
(char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
return true; return true;
} }
} }
@ -264,7 +286,8 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
{ {
int ScopeID = Parser ? Parser->ScopeID : -1; int ScopeID = Parser ? Parser->ScopeID : -1;
struct Value * AssignValue; struct Value * AssignValue;
struct Table * currentTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable; struct Table * currentTable = (pc->TopStackFrame == NULL) ?
&(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
#ifdef DEBUG_VAR_SCOPE #ifdef DEBUG_VAR_SCOPE
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID, if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID,
@ -272,7 +295,8 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
#endif #endif
if (InitValue != NULL) if (InitValue != NULL)
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL); AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue,
pc->TopStackFrame == NULL);
else else
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable, AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable,
NULL, pc->TopStackFrame == NULL); NULL, pc->TopStackFrame == NULL);
@ -281,13 +305,16 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
AssignValue->ScopeID = ScopeID; AssignValue->ScopeID = ScopeID;
AssignValue->OutOfScope = false; AssignValue->OutOfScope = false;
if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ? ((char*)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ?
((char*)Parser->FileName) : NULL, Parser ? Parser->Line : 0,
Parser ? Parser->CharacterPos : 0))
ProgramFail(Parser, "'%s' is already defined", Ident); ProgramFail(Parser, "'%s' is already defined", Ident);
return AssignValue; return AssignValue;
} }
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ /* define a variable. Ident must be registered. If it's a redefinition
from the same declaration don't throw an error */
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit) char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit)
{ {
@ -307,7 +334,8 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
char *MNEnd = &MangledName[LINEBUFFER_MAX-1]; char *MNEnd = &MangledName[LINEBUFFER_MAX-1];
const char *RegisteredMangledName; const char *RegisteredMangledName;
/* make the mangled static name (avoiding using sprintf() to minimise library impact) */ /* make the mangled static name (avoiding using sprintf()
to minimise library impact) */
memset((void *)&MangledName, '\0', sizeof(MangledName)); memset((void *)&MangledName, '\0', sizeof(MangledName));
*MNPos++ = '/'; *MNPos++ = '/';
strncpy(MNPos, (char*)Parser->FileName, MNEnd - MNPos); strncpy(MNPos, (char*)Parser->FileName, MNEnd - MNPos);
@ -325,18 +353,26 @@ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser,
RegisteredMangledName = TableStrRegister(pc, MangledName); RegisteredMangledName = TableStrRegister(pc, MangledName);
/* is this static already defined? */ /* is this static already defined? */
if (!TableGet(&pc->GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) { if (!TableGet(&pc->GlobalTable, RegisteredMangledName, &ExistingValue,
&DeclFileName, &DeclLine, &DeclColumn)) {
/* define the mangled-named static variable store in the global scope */ /* define the mangled-named static variable store in the global scope */
ExistingValue = VariableAllocValueFromType(Parser->pc, Parser, Typ, true, NULL, true); ExistingValue = VariableAllocValueFromType(Parser->pc, Parser, Typ,
TableSet(pc, &pc->GlobalTable, (char*)RegisteredMangledName, ExistingValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos); true, NULL, true);
TableSet(pc, &pc->GlobalTable, (char*)RegisteredMangledName,
ExistingValue, (char *)Parser->FileName, Parser->Line,
Parser->CharacterPos);
*FirstVisit = true; *FirstVisit = true;
} }
/* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */ /* static variable exists in the global scope - now make a
VariableDefinePlatformVar(Parser->pc, Parser, Ident, ExistingValue->Typ, ExistingValue->Val, true); mirroring variable in our own scope with the short name */
VariableDefinePlatformVar(Parser->pc, Parser, Ident, ExistingValue->Typ,
ExistingValue->Val, true);
return ExistingValue; return ExistingValue;
} else { } else {
if (Parser->Line != 0 && TableGet((pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn) if (Parser->Line != 0 && TableGet((pc->TopStackFrame == NULL) ?
&pc->GlobalTable : &pc->TopStackFrame->LocalTable, Ident,
&ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)
&& DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) && DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos)
return ExistingValue; return ExistingValue;
else else
@ -377,15 +413,21 @@ void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident,
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident, void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident,
struct ValueType *Typ, union AnyValue *FromValue, int IsWritable) struct ValueType *Typ, union AnyValue *FromValue, int IsWritable)
{ {
struct Value *SomeValue = VariableAllocValueAndData(pc, NULL, 0, IsWritable, NULL, true); struct Value *SomeValue = VariableAllocValueAndData(pc, NULL, 0, IsWritable,
NULL, true);
SomeValue->Typ = Typ; SomeValue->Typ = Typ;
SomeValue->Val = FromValue; SomeValue->Val = FromValue;
if (!TableSet(pc, (pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable, TableStrRegister(pc, Ident), SomeValue, Parser ? Parser->FileName : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) if (!TableSet(pc,
(pc->TopStackFrame == NULL) ? &pc->GlobalTable : &pc->TopStackFrame->LocalTable,
TableStrRegister(pc, Ident), SomeValue,
Parser ? Parser->FileName : NULL,
Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
ProgramFail(Parser, "'%s' is already defined", Ident); ProgramFail(Parser, "'%s' is already defined", Ident);
} }
/* free and/or pop the top value off the stack. Var must be the top value on the stack! */ /* free and/or pop the top value off the stack. Var must be
the top value on the stack! */
void VariableStackPop(struct ParseState *Parser, struct Value *Var) void VariableStackPop(struct ParseState *Parser, struct Value *Var)
{ {
int Success; int Success;
@ -426,7 +468,8 @@ void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName,
ParserCopy(&NewFrame->ReturnParser, Parser); ParserCopy(&NewFrame->ReturnParser, Parser);
NewFrame->FuncName = FuncName; NewFrame->FuncName = FuncName;
NewFrame->Parameter = (NumParams > 0) ? ((void*)((char *)NewFrame+sizeof(struct StackFrame))) : NULL; NewFrame->Parameter = (NumParams > 0) ?
((void*)((char*)NewFrame+sizeof(struct StackFrame))) : NULL;
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0],
LOCAL_TABLE_SIZE, false); LOCAL_TABLE_SIZE, false);
NewFrame->PreviousStackFrame = Parser->pc->TopStackFrame; NewFrame->PreviousStackFrame = Parser->pc->TopStackFrame;
@ -444,7 +487,8 @@ void VariableStackFramePop(struct ParseState *Parser)
HeapPopStackFrame(Parser->pc); HeapPopStackFrame(Parser->pc);
} }
/* get a string literal. assumes that Ident is already registered. NULL if not found */ /* get a string literal. assumes that Ident is already
registered. NULL if not found */
struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident) struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident)
{ {
struct Value *LVal = NULL; struct Value *LVal = NULL;