From 20fb2407efb64124caac45a7730fe9e3b47f896e Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Tue, 24 Feb 2009 11:16:37 +0000 Subject: [PATCH] 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 --- Makefile | 4 +- TODO | 1 + intrinsic.c => clibrary.c | 59 ++++++++++------- heap.c | 3 - lex.c | 15 ++--- parse.c | 6 -- picoc.c | 105 +++++++++-------------------- picoc.h | 51 +++++++------- platform_library.c | 20 ++++++ platform_support.c | 135 ++++++++++++++++++++++++++++++++++++++ table.c | 1 - variable.c | 6 -- 12 files changed, 256 insertions(+), 150 deletions(-) rename intrinsic.c => clibrary.c (72%) create mode 100644 platform_library.c create mode 100644 platform_support.c diff --git a/Makefile b/Makefile index 8a0b30b..3a077a8 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/TODO b/TODO index d68f6f6..1ae8e68 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/intrinsic.c b/clibrary.c similarity index 72% rename from intrinsic.c rename to clibrary.c index cdaf1bc..c653675 100644 --- a/intrinsic.c +++ b/clibrary.c @@ -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 } }; diff --git a/heap.c b/heap.c index d8502d7..3f3d5fc 100644 --- a/heap.c +++ b/heap.c @@ -1,7 +1,4 @@ /* stack grows up from the bottom and heap grows down from the top of heap space */ -#include -#include -#include #include "picoc.h" #define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */ diff --git a/lex.c b/lex.c index 26a10f3..d83c874 100644 --- a/lex.c +++ b/lex.c @@ -1,15 +1,10 @@ -#include -#include -#include -#include -#include -#include - #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 diff --git a/parse.c b/parse.c index 5c0fea7..6f76868 100644 --- a/parse.c +++ b/parse.c @@ -1,6 +1,3 @@ -#include -#include - #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 */ diff --git a/picoc.c b/picoc.c index 8076d40..4b0fe06 100644 --- a/picoc.c +++ b/picoc.c @@ -1,87 +1,44 @@ -#include -#include -#include -#include -#include -#include -#include - #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 ...\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 diff --git a/picoc.h b/picoc.h index cba8e60..d23396b 100644 --- a/picoc.h +++ b/picoc.h @@ -1,19 +1,7 @@ #ifndef PICOC_H #define PICOC_H -#include - -/* 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 */ diff --git a/platform_library.c b/platform_library.c new file mode 100644 index 0000000..72b30f8 --- /dev/null +++ b/platform_library.c @@ -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 } +}; + diff --git a/platform_support.c b/platform_support.c new file mode 100644 index 0000000..0e7bac8 --- /dev/null +++ b/platform_support.c @@ -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); + } +} diff --git a/table.c b/table.c index 9995f13..c30eb88 100644 --- a/table.c +++ b/table.c @@ -1,4 +1,3 @@ -#include #include "picoc.h" struct Table StringTable; diff --git a/variable.c b/variable.c index 3eede8f..e519932 100644 --- a/variable.c +++ b/variable.c @@ -1,9 +1,3 @@ -#ifdef DEBUG_HEAP -#include -#endif -#include -#include - #include "picoc.h" /* the table of global definitions */