Big reorganisation to make it easier to port to different targets

git-svn-id: http://picoc.googlecode.com/svn/trunk@110 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-02-24 11:16:37 +00:00
parent 54efa99a65
commit 20fb2407ef
12 changed files with 256 additions and 150 deletions

View file

@ -1,9 +1,9 @@
CC=gcc
CFLAGS=-Wall -g #-DNO_FP #-DDEBUG_LEXER #-DDEBUG_HEAP
CFLAGS=-Wall -g
LIBS=-lm
TARGET = picoc
SRCS = picoc.c table.c lex.c parse.c intrinsic.c heap.c type.c variable.c
SRCS = picoc.c table.c lex.c parse.c heap.c type.c variable.c clibrary.c platform_library.c platform_support.c
OBJS := $(SRCS:%.c=%.o)
all: $(TARGET)

1
TODO
View file

@ -11,6 +11,7 @@ TODO
* change heap to use a single consistent freelist node struct
* periodic heap cleanup
* fix type comparison to take into account array size
* fix return of array types
* expression and auto-cast support for all types
* octal/hex character constants
* fix #include

View file

@ -1,7 +1,7 @@
#include "picoc.h"
/* initialise a library */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct IntrinsicFunction *FuncList[])
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[])
{
struct ParseState Parser;
int Count;
@ -11,19 +11,26 @@ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct Intr
void *Tokens;
const char *IntrinsicName = TableStrRegister("c library");
for (Count = 0; Count < sizeof(Intrinsics) / sizeof(struct IntrinsicFunction); Count++)
for (Count = 0; (*FuncList)[Count].Prototype != NULL; Count++)
{
Tokens = LexAnalyse(IntrinsicName, Intrinsics[Count].Prototype, strlen(Intrinsics[Count].Prototype));
Tokens = LexAnalyse(IntrinsicName, (*FuncList)[Count].Prototype, strlen((*FuncList)[Count].Prototype));
LexInitParser(&Parser, Tokens, IntrinsicName, Count+1, TRUE);
TypeParse(&Parser, &ReturnType, &Identifier);
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier, TRUE);
NewValue->Val->FuncDef.Intrinsic = Intrinsics[Count].Func;
NewValue->Val->FuncDef.Intrinsic = (*FuncList)[Count].Func;
HeapFree(Tokens);
}
}
/* print a string to a stream without using printf/sprintf */
void PrintStr(const char *Str, CharWriter *PutCh)
{
while (*Str != 0)
PutCh(*Str++);
}
/* print an integer to a stream without using printf/sprintf */
void PrintInt(int Num, FILE *Stream)
void PrintInt(int Num, CharWriter *PutCh)
{
int Div;
int Remainder = 0;
@ -31,12 +38,12 @@ void PrintInt(int Num, FILE *Stream)
if (Num < 0)
{
fputc('-', Stream);
PutCh('-');
Num = -Num;
}
if (Num == 0)
fputc('0', Stream);
PutCh('0');
else
{
Div = LARGE_INT_POWER_OF_TEN;
@ -45,7 +52,7 @@ void PrintInt(int Num, FILE *Stream)
Remainder = Num / Div;
if (Printing || Remainder > 0)
{
fputc('0' + Remainder, Stream);
PutCh('0' + Remainder);
Printing = TRUE;
}
Num -= Remainder * Div;
@ -56,7 +63,7 @@ void PrintInt(int Num, FILE *Stream)
#ifndef NO_FP
/* print a double to a stream without using printf/sprintf */
void PrintFP(double Num, FILE *Stream)
void PrintFP(double Num, CharWriter *PutCh)
{
int Exponent = 0;
@ -66,15 +73,15 @@ void PrintFP(double Num, FILE *Stream)
Exponent = log(Num) / LOG10E - 0.999999999;
Num /= pow(10.0, Exponent);
PrintInt((int)Num, Stream);
fputc('.', Stream);
PrintInt((int)Num, PutCh);
PutCh('.');
for (Num -= (int)Num; Num != 0.0; Num *= 10.0)
fputc('0' + (int)Num, Stream);
PutCh('0' + (int)Num);
if (Exponent)
{
fputc('e', Stream);
PrintInt(Exponent, Stream);
PutCh('e');
PrintInt(Exponent, PutCh);
}
}
#endif
@ -106,20 +113,20 @@ void LibPrintf(struct Value *ReturnValue, struct Value **Param, int NumArgs)
#ifndef NO_FP
case 'f': FormatType = &FPType; break;
#endif
case '%': fputc('%', stdout); FormatType = NULL; break;
case '%': PlatformPutc('%'); FormatType = NULL; break;
case '\0': FPos--; FormatType = NULL; break;
default: putchar(*FPos); FormatType = NULL; break;
default: PlatformPutc(*FPos); FormatType = NULL; break;
}
if (FormatType != NULL)
{ /* we have to format something */
if (ArgCount >= NumArgs)
fputs("XXX", stdout); /* not enough parameters for format */
PrintStr("XXX", PlatformPutc); /* not enough parameters for format */
else
{
NextArg = (struct Value *)((void *)NextArg + sizeof(struct Value) + TypeSizeValue(NextArg));
if (NextArg->Typ != FormatType)
fputs("XXX", stdout); /* bad type for format */
PrintStr("XXX", PlatformPutc); /* bad type for format */
else
{
switch (*FPos)
@ -134,13 +141,13 @@ void LibPrintf(struct Value *ReturnValue, struct Value **Param, int NumArgs)
else
Str = CharArray->Val->Array.Data + NextArg->Val->Pointer.Data.Offset;
fputs(Str, stdout);
PrintStr(Str, PlatformPutc);
break;
}
case 'd': PrintInt(NextArg->Val->Integer, stdout); break;
case 'c': fputc(NextArg->Val->Integer, stdout); break;
case 'd': PrintInt(NextArg->Val->Integer, PlatformPutc); break;
case 'c': PlatformPutc(NextArg->Val->Integer); break;
#ifndef NO_FP
case 'f': PrintFP(NextArg->Val->FP, stdout); break;
case 'f': PrintFP(NextArg->Val->FP, PlatformPutc); break;
#endif
}
}
@ -150,11 +157,13 @@ void LibPrintf(struct Value *ReturnValue, struct Value **Param, int NumArgs)
}
}
else
putchar(*FPos);
PlatformPutc(*FPos);
}
}
struct IntrinsicFunction CLibrary[] =
/* list of all library functions and their prototypes */
struct LibraryFunction CLibrary[] =
{
{ LibPrintf, "void printf(char *, ...)" },
{ LibPrintf, "void printf(char *, ...)" },
{ NULL, NULL }
};

3
heap.c
View file

@ -1,7 +1,4 @@
/* stack grows up from the bottom and heap grows down from the top of heap space */
#include <stdio.h>
#include <memory.h>
#include <assert.h>
#include "picoc.h"
#define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */

15
lex.c
View file

@ -1,15 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include "picoc.h"
#ifndef isalpha
#ifdef NO_CTYPE
#define isalpha(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
#define isalnum(c) (isalpha(c) || ((c) >= '0' && (c) <= '9'))
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define isalnum(c) (isalpha(c) || isdigit(c))
#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
#endif
#define isCidstart(c) (isalpha(c) || (c)=='_' || (c)=='#')
#define isCident(c) (isalnum(c) || (c)=='_')
@ -286,7 +281,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
if (Lexer->FileName == StrEmpty)
{ /* get interactive input */
char LineBuffer[LINEBUFFER_MAX];
if (fgets(&LineBuffer[0], LINEBUFFER_MAX, stdin) == NULL)
if (PlatformGetLine(&LineBuffer[0], LINEBUFFER_MAX) == NULL)
return TokenEOF;
// XXX - finish this

View file

@ -1,6 +1,3 @@
#include <stdio.h>
#include <string.h>
#include "picoc.h"
/* local prototypes */
@ -11,9 +8,6 @@ int ParseStatementMaybeRun(struct ParseState *Parser, int Condition);
/* initialise the parser */
void ParseInit()
{
VariableInit();
TypeInit();
IntrinsicInit(&GlobalTable);
}
/* do a function call */

105
picoc.c
View file

@ -1,87 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "picoc.h"
/* all platform-dependent code is in this file */
void ProgramFail(struct ParseState *Parser, const char *Message, ...)
/* initialise everything */
void Initialise()
{
va_list Args;
if (Parser != NULL)
IntrinsicHostPrintf("%s:%d: ", Parser->FileName, Parser->Line);
va_start(Args, Message);
IntrinsicHostVPrintf(Message, Args);
IntrinsicHostPrintf("\n");
exit(1);
}
/* exit with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
IntrinsicHostPrintf("%s:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
IntrinsicHostVPrintf(Message, Args);
IntrinsicHostPrintf("\n");
exit(1);
}
/* read a file into memory */
char *ReadFile(const char *FileName)
{
struct stat FileInfo;
char *ReadText;
FILE *InFile;
if (stat(FileName, &FileInfo))
ProgramFail(NULL, "can't read file %s\n", FileName);
ReadText = malloc(FileInfo.st_size + 1);
if (ReadText == NULL)
ProgramFail(NULL, "out of memory\n");
InFile = fopen(FileName, "r");
if (InFile == NULL)
ProgramFail(NULL, "can't read file %s\n", FileName);
if (fread(ReadText, 1, FileInfo.st_size, InFile) != FileInfo.st_size)
ProgramFail(NULL, "can't read file %s\n", FileName);
ReadText[FileInfo.st_size] = '\0';
fclose(InFile);
return ReadText;
}
/* read and scan a file for definitions */
void ScanFile(const char *FileName)
{
char *SourceStr = ReadFile(FileName);
Parse(FileName, SourceStr, strlen(SourceStr), TRUE);
free(SourceStr);
HeapInit();
TableInit();
VariableInit();
LexInit();
VariableInit();
TypeInit();
LibraryInit(&GlobalTable, "c library", &CLibrary);
LibraryInit(&GlobalTable, "platform library", &PlatformLibrary);
ParseInit();
}
/* platform-dependent code for running programs is in this file */
#ifdef UNIX_HOST
int main(int argc, char **argv)
{
if (argc < 2)
ProgramFail(NULL, "Format: picoc <program.c> <args>...\n");
HeapInit();
TableInit();
VariableInit();
LexInit();
ParseInit();
ScanFile(argv[1]);
Initialise();
PlatformScanFile(argv[1]);
return 0;
}
#else
# ifdef SURVEYOR_HOST
static char *SourceStr = "\
printf(\"This is a test program\n\");\
for (Count = 1; Count <= 10; Count++)\
printf(\"%d\n\");\
";
int main(int argc, char **argv)
{
Initialise();
Parse("test.c", SourceStr, strlen(SourceStr), TRUE);
return 0;
}
# endif
#endif

51
picoc.h
View file

@ -1,19 +1,7 @@
#ifndef PICOC_H
#define PICOC_H
#include <stdarg.h>
/* configurable options */
#define HEAP_SIZE 16384 /* space for the heap and the stack */
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
#define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */
#define GLOBAL_TABLE_SIZE 397 /* global variable table */
#define STRING_TABLE_SIZE 97 /* shared string table size */
#define PARAMETER_MAX 16 /* maximum number of parameters to a function */
#define LINEBUFFER_MAX 256 /* maximum number of characters on a line */
#define LOCAL_TABLE_SIZE 11 /* size of local variable table (can expand) */
#define STRUCT_TABLE_SIZE 11 /* size of struct/union member table (can expand) */
#include "platform.h"
/* handy definitions */
#ifndef TRUE
@ -216,6 +204,16 @@ struct LexState
const char *FileName;
};
/* library function definition */
struct LibraryFunction
{
void (*Func)(struct Value *, struct Value **, int);
const char *Prototype;
};
/* platform-specific method for writing characters to the console */
typedef void CharWriter(unsigned char);
/* globals */
extern struct Table GlobalTable;
extern struct StackFrame *TopStackFrame;
@ -230,11 +228,8 @@ extern struct ValueType MacroType;
extern struct ValueType *CharPtrType;
extern struct ValueType *CharArrayType;
extern char *StrEmpty;
/* picoc.c */
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void LexFail(struct LexState *Lexer, const char *Message, ...);
void ScanFile(const char *FileName);
extern struct LibraryFunction CLibrary[];
extern struct LibraryFunction PlatformLibrary[];
/* table.c */
void TableInit();
@ -266,11 +261,6 @@ int TypeSizeValue(struct Value *Val);
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier);
struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier);
/* intrinsic.c */
void IntrinsicInit(struct Table *GlobalTable);
void IntrinsicHostPrintf(const char *Format, ...);
void IntrinsicHostVPrintf(const char *Format, va_list Args);
/* heap.c */
void HeapInit();
void *HeapAllocStack(int Size);
@ -295,4 +285,19 @@ void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LV
void VariableStackFrameAdd(struct ParseState *Parser, int NumParams);
void VariableStackFramePop(struct ParseState *Parser);
/* library.c */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);
void PrintInt(int Num, CharWriter *PutCh);
void PrintStr(const char *Str, CharWriter *PutCh);
void PrintFP(double Num, CharWriter *PutCh);
/* platform_support.c */
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void LexFail(struct LexState *Lexer, const char *Message, ...);
void PlatformScanFile(const char *FileName);
char *PlatformGetLine(char *Buf, int MaxLen);
void PlatformPutc(unsigned char OutCh);
void PlatformPrintf(const char *Format, ...);
void PlatformVPrintf(const char *Format, va_list Args);
#endif /* PICOC_H */

20
platform_library.c Normal file
View file

@ -0,0 +1,20 @@
#include "picoc.h"
void SayHello(struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
PlatformPrintf("Hello\n");
}
void PrintInteger(struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
PlatformPrintf("%d\n", Param[0]->Val->Integer);
}
/* list of all library functions and their prototypes */
struct LibraryFunction PlatformLibrary[] =
{
{ SayHello, "void sayhello()" },
{ PrintInteger, "void printint(int)" },
{ NULL, NULL }
};

135
platform_support.c Normal file
View file

@ -0,0 +1,135 @@
#include "picoc.h"
#ifdef UNIX_HOST
/* exit with a message */
void ProgramFail(struct ParseState *Parser, const char *Message, ...)
{
va_list Args;
if (Parser != NULL)
PlatformPrintf("%s:%d: ", Parser->FileName, Parser->Line);
va_start(Args, Message);
PlatformVPrintf(Message, Args);
PlatformPrintf("\n");
exit(1);
}
/* exit lexing with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
PlatformPrintf("%s:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
PlatformVPrintf(Message, Args);
PlatformPrintf("\n");
exit(1);
}
/* get a line of interactive input */
char *PlatformGetLine(char *Buf, int MaxLen)
{
return fgets(Buf, MaxLen, stdin);
}
/* write a character to the console */
void PlatformPutc(unsigned char OutCh)
{
putchar(OutCh);
}
/* read a file into memory */
char *PlatformReadFile(const char *FileName)
{
struct stat FileInfo;
char *ReadText;
FILE *InFile;
if (stat(FileName, &FileInfo))
ProgramFail(NULL, "can't read file %s\n", FileName);
ReadText = malloc(FileInfo.st_size + 1);
if (ReadText == NULL)
ProgramFail(NULL, "out of memory\n");
InFile = fopen(FileName, "r");
if (InFile == NULL)
ProgramFail(NULL, "can't read file %s\n", FileName);
if (fread(ReadText, 1, FileInfo.st_size, InFile) != FileInfo.st_size)
ProgramFail(NULL, "can't read file %s\n", FileName);
ReadText[FileInfo.st_size] = '\0';
fclose(InFile);
return ReadText;
}
/* read and scan a file for definitions */
void PlatformScanFile(const char *FileName)
{
char *SourceStr = PlatformReadFile(FileName);
Parse(FileName, SourceStr, strlen(SourceStr), TRUE);
free(SourceStr);
}
#endif
#ifdef SURVEYOR_HOST
/* exit with a message */
void ProgramFail(struct ParseState *Parser, const char *Message, ...)
{
}
/* exit lexing with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
}
/* get a line of interactive input */
char *PlatformGetLine(char *Buf, int MaxLen)
{
return NULL;
}
/* write a character to the console */
void PlatformPutc(unsigned char OutCh)
{
}
#endif
/* printf for compiler error reporting */
void PlatformPrintf(const char *Format, ...)
{
va_list Args;
va_start(Args, Format);
PlatformVPrintf(Format, Args);
va_end(Args);
}
void PlatformVPrintf(const char *Format, va_list Args)
{
const char *FPos;
for (FPos = Format; *FPos != '\0'; FPos++)
{
if (*FPos == '%')
{
FPos++;
switch (*FPos)
{
case 's': PrintStr(va_arg(Args, char *), PlatformPutc); break;
case 'd': PrintInt(va_arg(Args, int), PlatformPutc); break;
case 'c': PlatformPutc(va_arg(Args, int)); break;
#ifndef NO_FP
case 'f': PrintFP(va_arg(Args, double), PlatformPutc); break;
#endif
case '%': PlatformPutc('%'); break;
case '\0': FPos--; break;
}
}
else
PlatformPutc(*FPos);
}
}

View file

@ -1,4 +1,3 @@
#include <string.h>
#include "picoc.h"
struct Table StringTable;

View file

@ -1,9 +1,3 @@
#ifdef DEBUG_HEAP
#include <stdio.h>
#endif
#include <string.h>
#include <assert.h>
#include "picoc.h"
/* the table of global definitions */