Skip to content

Commit

Permalink
Added some more comments.
Browse files Browse the repository at this point in the history
Added the beginnings of a debugger. It's not useful yet.
  • Loading branch information
zik.saleeba committed May 1, 2011
1 parent 9cf3727 commit 5667fc1
Show file tree
Hide file tree
Showing 16 changed files with 250 additions and 31 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LIBS=-lm -lreadline

TARGET = picoc
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 \
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.c \
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
Expand All @@ -24,7 +24,7 @@ clean:

count:
@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 "Everything:"
@cat $(SRCS) *.h */*.h | wc
Expand All @@ -42,6 +42,7 @@ variable.o: variable.c interpreter.h platform.h
clibrary.o: clibrary.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
debug.o: debug.c 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
cstdlib/stdio.o: cstdlib/stdio.c interpreter.h platform.h
Expand Down
7 changes: 5 additions & 2 deletions clibrary.c
Original file line number Diff line number Diff line change
@@ -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 "interpreter.h"

Expand Down Expand Up @@ -35,13 +38,13 @@ void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct Libra
struct ValueType *ReturnType;
struct Value *NewValue;
void *Tokens;
const char *IntrinsicName = TableStrRegister("c library");
char *IntrinsicName = TableStrRegister("c library");

/* read all the library definitions */
for (Count = 0; FuncList[Count].Prototype != NULL; Count++)
{
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);
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
Expand Down
127 changes: 127 additions & 0 deletions debug.c
Original file line number Diff line number Diff line change
@@ -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 */
4 changes: 3 additions & 1 deletion expression.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* 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 */
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
#define BRACKET_PRECEDENCE 20
Expand Down
4 changes: 4 additions & 0 deletions heap.c
Original file line number Diff line number Diff line change
@@ -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 */
#include "interpreter.h"

Expand Down
5 changes: 4 additions & 1 deletion include.c
Original file line number Diff line number Diff line change
@@ -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 "interpreter.h"

Expand Down Expand Up @@ -92,7 +95,7 @@ void IncludeFile(char *FileName)

/* parse the setup C source code - may define types etc. */
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 */
if (LInclude->FuncList != NULL)
Expand Down
38 changes: 30 additions & 8 deletions interpreter.h
Original file line number Diff line number Diff line change
@@ -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
#define INTERPRETER_H

Expand Down Expand Up @@ -104,16 +108,17 @@ enum RunMode
/* parser state - has all this detail so we can parse nested files */
struct ParseState
{
const unsigned char *Pos;
const char *FileName;
short int Line;
short int CharacterPos;
const unsigned char *Pos; /* the character position in the source text */
char *FileName; /* what file we're executing (registered string) */
short int Line; /* line number we're executing */
short int CharacterPos; /* character/column in the line we're executing */
enum RunMode Mode; /* whether to skip or run code */
int SearchLabel; /* what case label we're searching for */
const char *SearchGotoLabel;/* what goto label we're searching for */
short int HashIfLevel;
short int HashIfEvaluateToLevel;
const char *SourceText;
const char *SourceText; /* the entire source text */
short int HashIfLevel; /* how many "if"s we're nested down */
short int HashIfEvaluateToLevel; /* if we're not evaluating an if branch, what the last evaluated level was */
char DebugMode; /* debugging mode */
};

/* values */
Expand Down Expand Up @@ -225,6 +230,14 @@ struct TableEntry
} v; /* used for tables of values */

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;
};

Expand Down Expand Up @@ -340,7 +353,7 @@ void TableStrFree();
void LexInit();
void LexCleanup();
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 LexRawPeekToken(struct ParseState *Parser);
void LexToEndOfLine(struct ParseState *Parser);
Expand All @@ -353,6 +366,7 @@ void LexInteractiveStatementPrompt();
/* the following are defined in picoc.h:
* void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
* void PicocParseInteractive(); */
void PicocParseInteractiveNoStartPrompt(int EnableDebugger);
enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon);
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier);
void ParseCleanup();
Expand Down Expand Up @@ -440,6 +454,7 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
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 LexFail(struct LexState *Lexer, const char *Message, ...);
void PlatformInit();
void PlatformCleanup();
char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt);
int PlatformGetCharacter();
Expand All @@ -458,6 +473,13 @@ void IncludeRegister(const char *IncludeName, void (*SetupFunction)(void), struc
void IncludeFile(char *Filename);
/* the following is defined in picoc.h:
* void PicocIncludeAllSystemHeaders(); */

/* debug.c */
extern int DebugManualBreak;
void DebugInit();
void DebugCleanup();
void DebugCheckStatement(struct ParseState *Parser);


/* stdio.c */
extern const char StdioDefs[];
Expand Down
5 changes: 4 additions & 1 deletion lex.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* picoc lexer - converts source text into a tokenised form */

#include "interpreter.h"

#ifdef NO_CTYPE
Expand Down Expand Up @@ -583,7 +585,7 @@ void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *T
}

/* 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->Line = 1;
Expand All @@ -594,6 +596,7 @@ void LexInitParser(struct ParseState *Parser, const char *SourceText, void *Toke
Parser->HashIfEvaluateToLevel = 0;
Parser->CharacterPos = 0;
Parser->SourceText = SourceText;
Parser->DebugMode = EnableDebugger;
}

/* get the next token, without pre-processing */
Expand Down
26 changes: 20 additions & 6 deletions parse.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* picoc parser - parses source and executes statements */

#include "picoc.h"
#include "interpreter.h"

Expand Down Expand Up @@ -484,6 +486,11 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
struct ParseState PreState;
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);
Token = LexGetToken(Parser, &LexerValue, TRUE);

Expand Down Expand Up @@ -806,13 +813,14 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
}

/* 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;
enum ParseResult Ok;
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 */
if (!CleanupNow)
Expand All @@ -832,7 +840,7 @@ void PicocParse(const char *FileName, const char *Source, int SourceLen, int Run
}

/* do the parsing */
LexInitParser(&Parser, Source, Tokens, FileName, RunIt);
LexInitParser(&Parser, Source, Tokens, RegFileName, RunIt, EnableDebugger);

do {
Ok = ParseStatement(&Parser, TRUE);
Expand All @@ -847,13 +855,12 @@ void PicocParse(const char *FileName, const char *Source, int SourceLen, int Run
}

/* parse interactively */
void PicocParseInteractive()
void PicocParseInteractiveNoStartPrompt(int EnableDebugger)
{
struct ParseState Parser;
enum ParseResult Ok;

PlatformPrintf(INTERACTIVE_PROMPT_START);
LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE);
LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE, EnableDebugger);
PicocPlatformSetExitPoint();
LexInteractiveClear(&Parser);

Expand All @@ -870,3 +877,10 @@ void PicocParseInteractive()

PlatformPrintf("\n");
}

/* parse interactively, showing a startup message */
void PicocParseInteractive()
{
PlatformPrintf(INTERACTIVE_PROMPT_START);
PicocParseInteractiveNoStartPrompt(TRUE);
}
Loading

0 comments on commit 5667fc1

Please sign in to comment.