Added some more comments.
Added the beginnings of a debugger. It's not useful yet. git-svn-id: http://picoc.googlecode.com/svn/trunk@570 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
0bb912af5d
commit
853b6f6259
5
Makefile
5
Makefile
|
@ -4,7 +4,7 @@ LIBS=-lm -lreadline
|
||||||
|
|
||||||
TARGET = picoc
|
TARGET = picoc
|
||||||
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
|
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
|
||||||
variable.c clibrary.c platform.c include.c \
|
variable.c clibrary.c platform.c include.c debug.c \
|
||||||
platform/platform_unix.c platform/library_unix.c \
|
platform/platform_unix.c platform/library_unix.c \
|
||||||
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.c \
|
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.c \
|
||||||
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
|
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
|
||||||
|
@ -24,7 +24,7 @@ clean:
|
||||||
|
|
||||||
count:
|
count:
|
||||||
@echo "Core:"
|
@echo "Core:"
|
||||||
@cat picoc.h interpreter.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c include.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
|
@cat picoc.h interpreter.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c include.c debug.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Everything:"
|
@echo "Everything:"
|
||||||
@cat $(SRCS) *.h */*.h | wc
|
@cat $(SRCS) *.h */*.h | wc
|
||||||
|
@ -42,6 +42,7 @@ variable.o: variable.c interpreter.h platform.h
|
||||||
clibrary.o: clibrary.c picoc.h interpreter.h platform.h
|
clibrary.o: clibrary.c picoc.h interpreter.h platform.h
|
||||||
platform.o: platform.c picoc.h interpreter.h platform.h
|
platform.o: platform.c picoc.h interpreter.h platform.h
|
||||||
include.o: include.c picoc.h interpreter.h platform.h
|
include.o: include.c picoc.h interpreter.h platform.h
|
||||||
|
debug.o: debug.c interpreter.h platform.h
|
||||||
platform/platform_unix.o: platform/platform_unix.c picoc.h interpreter.h platform.h
|
platform/platform_unix.o: platform/platform_unix.c picoc.h interpreter.h platform.h
|
||||||
platform/library_unix.o: platform/library_unix.c interpreter.h platform.h
|
platform/library_unix.o: platform/library_unix.c interpreter.h platform.h
|
||||||
cstdlib/stdio.o: cstdlib/stdio.c interpreter.h platform.h
|
cstdlib/stdio.o: cstdlib/stdio.c interpreter.h platform.h
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* picoc mini standard C library - provides an optional tiny C standard library
|
||||||
|
* if BUILTIN_MINI_STDLIB is defined */
|
||||||
|
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
@ -35,13 +38,13 @@ void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct Libra
|
||||||
struct ValueType *ReturnType;
|
struct ValueType *ReturnType;
|
||||||
struct Value *NewValue;
|
struct Value *NewValue;
|
||||||
void *Tokens;
|
void *Tokens;
|
||||||
const char *IntrinsicName = TableStrRegister("c library");
|
char *IntrinsicName = TableStrRegister("c library");
|
||||||
|
|
||||||
/* read all the library definitions */
|
/* read all the library definitions */
|
||||||
for (Count = 0; FuncList[Count].Prototype != NULL; Count++)
|
for (Count = 0; FuncList[Count].Prototype != NULL; Count++)
|
||||||
{
|
{
|
||||||
Tokens = LexAnalyse(IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL);
|
Tokens = LexAnalyse(IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL);
|
||||||
LexInitParser(&Parser, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE);
|
LexInitParser(&Parser, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE, FALSE);
|
||||||
TypeParse(&Parser, &ReturnType, &Identifier, NULL);
|
TypeParse(&Parser, &ReturnType, &Identifier, NULL);
|
||||||
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
|
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
|
||||||
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
|
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
|
||||||
|
|
127
debug.c
Normal file
127
debug.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/* picoc interactive debugger */
|
||||||
|
|
||||||
|
#ifndef NO_DEBUGGER
|
||||||
|
|
||||||
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
#define BREAKPOINT_TABLE_SIZE 21
|
||||||
|
#define BREAKPOINT_HASH(p) ( ((unsigned long)(p)->FileName) ^ (((p)->Line << 16) | ((p)->CharacterPos << 16)) )
|
||||||
|
|
||||||
|
struct Table BreakpointTable;
|
||||||
|
struct TableEntry *BreakpointHashTable[BREAKPOINT_TABLE_SIZE];
|
||||||
|
int BreakpointCount = 0;
|
||||||
|
int DebugManualBreak = FALSE;
|
||||||
|
|
||||||
|
/* initialise the debugger by clearing the breakpoint table */
|
||||||
|
void DebugInit()
|
||||||
|
{
|
||||||
|
TableInitTable(&BreakpointTable, &BreakpointHashTable[0], BREAKPOINT_TABLE_SIZE, TRUE);
|
||||||
|
BreakpointCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the contents of the breakpoint table */
|
||||||
|
void DebugCleanup()
|
||||||
|
{
|
||||||
|
struct TableEntry *Entry;
|
||||||
|
struct TableEntry *NextEntry;
|
||||||
|
int Count;
|
||||||
|
|
||||||
|
for (Count = 0; Count < BreakpointTable.Size; Count++)
|
||||||
|
{
|
||||||
|
for (Entry = BreakpointHashTable[Count]; Entry != NULL; Entry = NextEntry)
|
||||||
|
{
|
||||||
|
NextEntry = Entry->Next;
|
||||||
|
HeapFreeMem(Entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the table for a breakpoint */
|
||||||
|
static struct TableEntry *DebugTableSearchBreakpoint(struct ParseState *Parser, int *AddAt)
|
||||||
|
{
|
||||||
|
struct TableEntry *Entry;
|
||||||
|
int HashValue = BREAKPOINT_HASH(Parser) % BreakpointTable.Size;
|
||||||
|
|
||||||
|
for (Entry = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a breakpoint in the table */
|
||||||
|
void DebugSetBreakpoint(struct ParseState *Parser)
|
||||||
|
{
|
||||||
|
int AddAt;
|
||||||
|
struct TableEntry *FoundEntry = DebugTableSearchBreakpoint(Parser, &AddAt);
|
||||||
|
|
||||||
|
if (FoundEntry == NULL)
|
||||||
|
{
|
||||||
|
/* add it to the table */
|
||||||
|
struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry));
|
||||||
|
if (NewEntry == NULL)
|
||||||
|
ProgramFail(NULL, "out of memory");
|
||||||
|
|
||||||
|
NewEntry->p.b.FileName = Parser->FileName;
|
||||||
|
NewEntry->p.b.Line = Parser->Line;
|
||||||
|
NewEntry->p.b.CharacterPos = Parser->CharacterPos;
|
||||||
|
NewEntry->Next = BreakpointHashTable[AddAt];
|
||||||
|
BreakpointHashTable[AddAt] = NewEntry;
|
||||||
|
BreakpointCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete a breakpoint from the hash table */
|
||||||
|
int DebugClearBreakpoint(struct ParseState *Parser)
|
||||||
|
{
|
||||||
|
struct TableEntry **EntryPtr;
|
||||||
|
int HashValue = BREAKPOINT_HASH(Parser) % BreakpointTable.Size;
|
||||||
|
|
||||||
|
for (EntryPtr = &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)
|
||||||
|
{
|
||||||
|
*EntryPtr = DeleteEntry->Next;
|
||||||
|
HeapFreeMem(DeleteEntry);
|
||||||
|
BreakpointCount--;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* before we run a statement, check if there's anything we have to do with the debugger here */
|
||||||
|
void DebugCheckStatement(struct ParseState *Parser)
|
||||||
|
{
|
||||||
|
int DoBreak = FALSE;
|
||||||
|
int AddAt;
|
||||||
|
|
||||||
|
/* has the user manually pressed break? */
|
||||||
|
if (DebugManualBreak)
|
||||||
|
{
|
||||||
|
DoBreak = TRUE;
|
||||||
|
DebugManualBreak = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is this a breakpoint location? */
|
||||||
|
if (BreakpointCount != 0 && DebugTableSearchBreakpoint(Parser, &AddAt) != NULL)
|
||||||
|
DoBreak = TRUE;
|
||||||
|
|
||||||
|
/* handle a break */
|
||||||
|
if (DoBreak)
|
||||||
|
{
|
||||||
|
PlatformPrintf("Handling a break\n");
|
||||||
|
PicocParseInteractiveNoStartPrompt(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugStep()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* !NO_DEBUGGER */
|
|
@ -1,5 +1,7 @@
|
||||||
#include "interpreter.h"
|
/* picoc expression evaluator - a stack-based expression evaluation system
|
||||||
|
* which handles operator precedence */
|
||||||
|
|
||||||
|
#include "interpreter.h"
|
||||||
|
|
||||||
/* whether evaluation is left to right for a given precedence level */
|
/* whether evaluation is left to right for a given precedence level */
|
||||||
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
||||||
|
|
4
heap.c
4
heap.c
|
@ -1,3 +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 */
|
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +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 "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
@ -92,7 +95,7 @@ void IncludeFile(char *FileName)
|
||||||
|
|
||||||
/* parse the setup C source code - may define types etc. */
|
/* parse the setup C source code - may define types etc. */
|
||||||
if (LInclude->SetupCSource != NULL)
|
if (LInclude->SetupCSource != NULL)
|
||||||
PicocParse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE);
|
PicocParse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE, FALSE);
|
||||||
|
|
||||||
/* set up the library functions */
|
/* set up the library functions */
|
||||||
if (LInclude->FuncList != NULL)
|
if (LInclude->FuncList != NULL)
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/* picoc main header file - this has all the main data structures and
|
||||||
|
* function prototypes. If you're just calling picoc you should look at the
|
||||||
|
* external interface instead, in picoc.h */
|
||||||
|
|
||||||
#ifndef INTERPRETER_H
|
#ifndef INTERPRETER_H
|
||||||
#define INTERPRETER_H
|
#define INTERPRETER_H
|
||||||
|
|
||||||
|
@ -104,16 +108,17 @@ enum RunMode
|
||||||
/* parser state - has all this detail so we can parse nested files */
|
/* parser state - has all this detail so we can parse nested files */
|
||||||
struct ParseState
|
struct ParseState
|
||||||
{
|
{
|
||||||
const unsigned char *Pos;
|
const unsigned char *Pos; /* the character position in the source text */
|
||||||
const char *FileName;
|
char *FileName; /* what file we're executing (registered string) */
|
||||||
short int Line;
|
short int Line; /* line number we're executing */
|
||||||
short int CharacterPos;
|
short int CharacterPos; /* character/column in the line we're executing */
|
||||||
enum RunMode Mode; /* whether to skip or run code */
|
enum RunMode Mode; /* whether to skip or run code */
|
||||||
int SearchLabel; /* what case label we're searching for */
|
int SearchLabel; /* what case label we're searching for */
|
||||||
const char *SearchGotoLabel;/* what goto label we're searching for */
|
const char *SearchGotoLabel;/* what goto label we're searching for */
|
||||||
short int HashIfLevel;
|
const char *SourceText; /* the entire source text */
|
||||||
short int HashIfEvaluateToLevel;
|
short int HashIfLevel; /* how many "if"s we're nested down */
|
||||||
const char *SourceText;
|
short int HashIfEvaluateToLevel; /* if we're not evaluating an if branch, what the last evaluated level was */
|
||||||
|
char DebugMode; /* debugging mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* values */
|
/* values */
|
||||||
|
@ -225,6 +230,14 @@ struct TableEntry
|
||||||
} v; /* used for tables of values */
|
} v; /* used for tables of values */
|
||||||
|
|
||||||
char Key[1]; /* dummy size - used for the shared string table */
|
char Key[1]; /* dummy size - used for the shared string table */
|
||||||
|
|
||||||
|
struct BreakpointEntry /* defines a breakpoint */
|
||||||
|
{
|
||||||
|
const char *FileName;
|
||||||
|
short int Line;
|
||||||
|
short int CharacterPos;
|
||||||
|
} b;
|
||||||
|
|
||||||
} p;
|
} p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -340,7 +353,7 @@ void TableStrFree();
|
||||||
void LexInit();
|
void LexInit();
|
||||||
void LexCleanup();
|
void LexCleanup();
|
||||||
void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen);
|
void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen);
|
||||||
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt);
|
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, char *FileName, int RunIt, int SetDebugMode);
|
||||||
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos);
|
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos);
|
||||||
enum LexToken LexRawPeekToken(struct ParseState *Parser);
|
enum LexToken LexRawPeekToken(struct ParseState *Parser);
|
||||||
void LexToEndOfLine(struct ParseState *Parser);
|
void LexToEndOfLine(struct ParseState *Parser);
|
||||||
|
@ -353,6 +366,7 @@ void LexInteractiveStatementPrompt();
|
||||||
/* the following are defined in picoc.h:
|
/* the following are defined in picoc.h:
|
||||||
* void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
|
* void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
|
||||||
* void PicocParseInteractive(); */
|
* void PicocParseInteractive(); */
|
||||||
|
void PicocParseInteractiveNoStartPrompt(int EnableDebugger);
|
||||||
enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon);
|
enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon);
|
||||||
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier);
|
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier);
|
||||||
void ParseCleanup();
|
void ParseCleanup();
|
||||||
|
@ -440,6 +454,7 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
||||||
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
|
void ProgramFail(struct ParseState *Parser, 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);
|
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo);
|
||||||
void LexFail(struct LexState *Lexer, const char *Message, ...);
|
void LexFail(struct LexState *Lexer, const char *Message, ...);
|
||||||
|
void PlatformInit();
|
||||||
void PlatformCleanup();
|
void PlatformCleanup();
|
||||||
char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt);
|
char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt);
|
||||||
int PlatformGetCharacter();
|
int PlatformGetCharacter();
|
||||||
|
@ -459,6 +474,13 @@ void IncludeFile(char *Filename);
|
||||||
/* the following is defined in picoc.h:
|
/* the following is defined in picoc.h:
|
||||||
* void PicocIncludeAllSystemHeaders(); */
|
* void PicocIncludeAllSystemHeaders(); */
|
||||||
|
|
||||||
|
/* debug.c */
|
||||||
|
extern int DebugManualBreak;
|
||||||
|
void DebugInit();
|
||||||
|
void DebugCleanup();
|
||||||
|
void DebugCheckStatement(struct ParseState *Parser);
|
||||||
|
|
||||||
|
|
||||||
/* stdio.c */
|
/* stdio.c */
|
||||||
extern const char StdioDefs[];
|
extern const char StdioDefs[];
|
||||||
extern struct LibraryFunction StdioFunctions[];
|
extern struct LibraryFunction StdioFunctions[];
|
||||||
|
|
5
lex.c
5
lex.c
|
@ -1,3 +1,5 @@
|
||||||
|
/* picoc lexer - converts source text into a tokenised form */
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
#ifdef NO_CTYPE
|
#ifdef NO_CTYPE
|
||||||
|
@ -583,7 +585,7 @@ void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *T
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prepare to parse a pre-tokenised buffer */
|
/* prepare to parse a pre-tokenised buffer */
|
||||||
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt)
|
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, char *FileName, int RunIt, int EnableDebugger)
|
||||||
{
|
{
|
||||||
Parser->Pos = TokenSource;
|
Parser->Pos = TokenSource;
|
||||||
Parser->Line = 1;
|
Parser->Line = 1;
|
||||||
|
@ -594,6 +596,7 @@ void LexInitParser(struct ParseState *Parser, const char *SourceText, void *Toke
|
||||||
Parser->HashIfEvaluateToLevel = 0;
|
Parser->HashIfEvaluateToLevel = 0;
|
||||||
Parser->CharacterPos = 0;
|
Parser->CharacterPos = 0;
|
||||||
Parser->SourceText = SourceText;
|
Parser->SourceText = SourceText;
|
||||||
|
Parser->DebugMode = EnableDebugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the next token, without pre-processing */
|
/* get the next token, without pre-processing */
|
||||||
|
|
26
parse.c
26
parse.c
|
@ -1,3 +1,5 @@
|
||||||
|
/* picoc parser - parses source and executes statements */
|
||||||
|
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
@ -484,6 +486,11 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
|
||||||
struct ParseState PreState;
|
struct ParseState PreState;
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
|
|
||||||
|
/* if we're debugging, check for a breakpoint */
|
||||||
|
if (Parser->DebugMode && Parser->Mode == RunModeRun)
|
||||||
|
DebugCheckStatement(Parser);
|
||||||
|
|
||||||
|
/* take note of where we are and then grab a token to see what statement we have */
|
||||||
ParserCopy(&PreState, Parser);
|
ParserCopy(&PreState, Parser);
|
||||||
Token = LexGetToken(Parser, &LexerValue, TRUE);
|
Token = LexGetToken(Parser, &LexerValue, TRUE);
|
||||||
|
|
||||||
|
@ -806,13 +813,14 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
|
||||||
}
|
}
|
||||||
|
|
||||||
/* quick scan a source file for definitions */
|
/* quick scan a source file for definitions */
|
||||||
void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource)
|
void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource, int EnableDebugger)
|
||||||
{
|
{
|
||||||
struct ParseState Parser;
|
struct ParseState Parser;
|
||||||
enum ParseResult Ok;
|
enum ParseResult Ok;
|
||||||
struct CleanupTokenNode *NewCleanupNode;
|
struct CleanupTokenNode *NewCleanupNode;
|
||||||
|
char *RegFileName = TableStrRegister(FileName);
|
||||||
|
|
||||||
void *Tokens = LexAnalyse(FileName, Source, SourceLen, NULL);
|
void *Tokens = LexAnalyse(RegFileName, Source, SourceLen, NULL);
|
||||||
|
|
||||||
/* allocate a cleanup node so we can clean up the tokens later */
|
/* allocate a cleanup node so we can clean up the tokens later */
|
||||||
if (!CleanupNow)
|
if (!CleanupNow)
|
||||||
|
@ -832,7 +840,7 @@ void PicocParse(const char *FileName, const char *Source, int SourceLen, int Run
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do the parsing */
|
/* do the parsing */
|
||||||
LexInitParser(&Parser, Source, Tokens, FileName, RunIt);
|
LexInitParser(&Parser, Source, Tokens, RegFileName, RunIt, EnableDebugger);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Ok = ParseStatement(&Parser, TRUE);
|
Ok = ParseStatement(&Parser, TRUE);
|
||||||
|
@ -847,13 +855,12 @@ void PicocParse(const char *FileName, const char *Source, int SourceLen, int Run
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse interactively */
|
/* parse interactively */
|
||||||
void PicocParseInteractive()
|
void PicocParseInteractiveNoStartPrompt(int EnableDebugger)
|
||||||
{
|
{
|
||||||
struct ParseState Parser;
|
struct ParseState Parser;
|
||||||
enum ParseResult Ok;
|
enum ParseResult Ok;
|
||||||
|
|
||||||
PlatformPrintf(INTERACTIVE_PROMPT_START);
|
LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE, EnableDebugger);
|
||||||
LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE);
|
|
||||||
PicocPlatformSetExitPoint();
|
PicocPlatformSetExitPoint();
|
||||||
LexInteractiveClear(&Parser);
|
LexInteractiveClear(&Parser);
|
||||||
|
|
||||||
|
@ -870,3 +877,10 @@ void PicocParseInteractive()
|
||||||
|
|
||||||
PlatformPrintf("\n");
|
PlatformPrintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse interactively, showing a startup message */
|
||||||
|
void PicocParseInteractive()
|
||||||
|
{
|
||||||
|
PlatformPrintf(INTERACTIVE_PROMPT_START);
|
||||||
|
PicocParseInteractiveNoStartPrompt(TRUE);
|
||||||
|
}
|
||||||
|
|
5
picoc.c
5
picoc.c
|
@ -1,3 +1,6 @@
|
||||||
|
/* picoc main program - this varies depending on your operating system and
|
||||||
|
* how you're using picoc */
|
||||||
|
|
||||||
/* include only picoc.h here - should be able to use it with only the external interfaces, no internals from interpreter.h */
|
/* include only picoc.h here - should be able to use it with only the external interfaces, no internals from interpreter.h */
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
|
|
||||||
|
@ -36,7 +39,7 @@ int main(int argc, char **argv)
|
||||||
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0)
|
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0)
|
||||||
{
|
{
|
||||||
PicocIncludeAllSystemHeaders();
|
PicocIncludeAllSystemHeaders();
|
||||||
PicocParseInteractive();
|
PicocParseInteractive(TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
8
picoc.h
8
picoc.h
|
@ -1,11 +1,13 @@
|
||||||
|
/* picoc external interface. This should be the only header you need to use if
|
||||||
|
* you're using picoc as a library. Internal details are in interpreter.h */
|
||||||
#ifndef PICOC_H
|
#ifndef PICOC_H
|
||||||
#define PICOC_H
|
#define PICOC_H
|
||||||
|
|
||||||
/* picoc version number */
|
/* picoc version number */
|
||||||
#ifdef VER
|
#ifdef VER
|
||||||
#define PICOC_VERSION "v2.1 beta r" VER /* VER is the subversion version number, obtained via the Makefile */
|
#define PICOC_VERSION "v2.2 beta r" VER /* VER is the subversion version number, obtained via the Makefile */
|
||||||
#else
|
#else
|
||||||
#define PICOC_VERSION "v2.1 beta"
|
#define PICOC_VERSION "v2.2"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* handy definitions */
|
/* handy definitions */
|
||||||
|
@ -33,7 +35,7 @@ extern int PicocExitBuf[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* parse.c */
|
/* parse.c */
|
||||||
void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
|
void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource, int EnableDebugger);
|
||||||
void PicocParseInteractive();
|
void PicocParseInteractive();
|
||||||
|
|
||||||
/* platform.c */
|
/* platform.c */
|
||||||
|
|
16
platform.c
16
platform.c
|
@ -1,3 +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 "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
@ -7,6 +10,7 @@ int PicocExitValue = 0;
|
||||||
/* initialise everything */
|
/* initialise everything */
|
||||||
void PicocInitialise(int StackSize)
|
void PicocInitialise(int StackSize)
|
||||||
{
|
{
|
||||||
|
PlatformInit();
|
||||||
BasicIOInit();
|
BasicIOInit();
|
||||||
HeapInit(StackSize);
|
HeapInit(StackSize);
|
||||||
TableInit();
|
TableInit();
|
||||||
|
@ -22,12 +26,13 @@ void PicocInitialise(int StackSize)
|
||||||
CLibraryInit();
|
CLibraryInit();
|
||||||
#endif
|
#endif
|
||||||
PlatformLibraryInit();
|
PlatformLibraryInit();
|
||||||
|
DebugInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free memory */
|
/* free memory */
|
||||||
void PicocCleanup()
|
void PicocCleanup()
|
||||||
{
|
{
|
||||||
PlatformCleanup();
|
DebugCleanup();
|
||||||
#ifndef NO_HASH_INCLUDE
|
#ifndef NO_HASH_INCLUDE
|
||||||
IncludeCleanup();
|
IncludeCleanup();
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +42,7 @@ void PicocCleanup()
|
||||||
TypeCleanup();
|
TypeCleanup();
|
||||||
TableStrFree();
|
TableStrFree();
|
||||||
HeapCleanup();
|
HeapCleanup();
|
||||||
|
PlatformCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* platform-dependent code for running programs */
|
/* platform-dependent code for running programs */
|
||||||
|
@ -69,18 +75,18 @@ void PicocCallMain(int argc, char **argv)
|
||||||
if (FuncValue->Val->FuncDef.ReturnType == &VoidType)
|
if (FuncValue->Val->FuncDef.ReturnType == &VoidType)
|
||||||
{
|
{
|
||||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||||
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE);
|
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE);
|
||||||
else
|
else
|
||||||
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE);
|
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE);
|
VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE);
|
||||||
|
|
||||||
if (FuncValue->Val->FuncDef.NumParams == 0)
|
if (FuncValue->Val->FuncDef.NumParams == 0)
|
||||||
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE);
|
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE, TRUE);
|
||||||
else
|
else
|
||||||
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE);
|
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,26 @@
|
||||||
/* mark where to end the program for platforms which require this */
|
/* mark where to end the program for platforms which require this */
|
||||||
jmp_buf PicocExitBuf;
|
jmp_buf PicocExitBuf;
|
||||||
|
|
||||||
|
#ifndef NO_DEBUGGER
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
static void BreakHandler(int Signal)
|
||||||
|
{
|
||||||
|
PlatformPrintf("break\n");
|
||||||
|
DebugManualBreak = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformInit()
|
||||||
|
{
|
||||||
|
/* capture the break signal and pass it to the debugger */
|
||||||
|
signal(SIGINT, BreakHandler);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void PlatformInit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void PlatformCleanup()
|
void PlatformCleanup()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -90,7 +110,7 @@ void PicocPlatformScanFile(const char *FileName)
|
||||||
{
|
{
|
||||||
char *SourceStr = PlatformReadFile(FileName);
|
char *SourceStr = PlatformReadFile(FileName);
|
||||||
|
|
||||||
PicocParse(FileName, SourceStr, strlen(SourceStr), TRUE, FALSE, TRUE);
|
PicocParse(FileName, SourceStr, strlen(SourceStr), TRUE, FALSE, TRUE, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exit the program */
|
/* exit the program */
|
||||||
|
|
3
table.c
3
table.c
|
@ -1,3 +1,6 @@
|
||||||
|
/* picoc hash table module. This hash table code is used for both symbol tables
|
||||||
|
* and the shared string table. */
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
struct Table StringTable;
|
struct Table StringTable;
|
||||||
|
|
3
type.c
3
type.c
|
@ -1,3 +1,6 @@
|
||||||
|
/* picoc data type module. This manages a tree of data types and has facilities
|
||||||
|
* for parsing data types. */
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
/* some basic types */
|
/* some basic types */
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* picoc variable storage. This provides ways of defining and accessing
|
||||||
|
* variables */
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
/* maximum size of a value to temporarily copy while we create a variable */
|
/* maximum size of a value to temporarily copy while we create a variable */
|
||||||
|
|
Loading…
Reference in a new issue