diff --git a/Makefile b/Makefile index 58062fb..1bbf515 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall -g LIBS=-lm TARGET = picoc -SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c clibrary.c platform_library.c platform_support.c +SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c clibrary.c library_unix.c platform.c platform_unix.c OBJS := $(SRCS:%.c=%.o) all: depend $(TARGET) diff --git a/TODO b/TODO index 002d66c..35a1739 100644 --- a/TODO +++ b/TODO @@ -9,6 +9,8 @@ Implement: * pointer arithmetic * casts * char access/char array access/char * access +* getc()/gets()/malloc()/free() +* "delete" for interactive mode to remove old functions Improvements: * #define with arguments diff --git a/clibrary.c b/clibrary.c index 386af19..a238f2c 100644 --- a/clibrary.c +++ b/clibrary.c @@ -96,10 +96,10 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu struct ValueType *FormatType; int ArgCount = 1; - if (Param[0]->Val->Pointer.Data.Offset < 0 || Param[0]->Val->Pointer.Data.Offset >= CharArray->Val->Array.Size) + if (Param[0]->Val->Pointer.Offset < 0 || Param[0]->Val->Pointer.Offset >= CharArray->Val->Array.Size) Format = StrEmpty; else - Format = CharArray->Val->Array.Data + Param[0]->Val->Pointer.Data.Offset; + Format = CharArray->Val->Array.Data + Param[0]->Val->Pointer.Offset; for (FPos = Format; *FPos != '\0'; FPos++) { @@ -136,10 +136,10 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu struct Value *CharArray = NextArg->Val->Pointer.Segment; char *Str; - if (NextArg->Val->Pointer.Data.Offset < 0 || NextArg->Val->Pointer.Data.Offset >= CharArray->Val->Array.Size) + if (NextArg->Val->Pointer.Offset < 0 || NextArg->Val->Pointer.Offset >= CharArray->Val->Array.Size) Str = StrEmpty; else - Str = CharArray->Val->Array.Data + NextArg->Val->Pointer.Data.Offset; + Str = CharArray->Val->Array.Data + NextArg->Val->Pointer.Offset; PrintStr(Str, PlatformPutc); break; @@ -161,9 +161,19 @@ void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Valu } } +void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) +{ +} + +void LibGetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) +{ +} + /* list of all library functions and their prototypes */ struct LibraryFunction CLibrary[] = { { LibPrintf, "void printf(char *, ...)" }, + { LibGets, "void gets(char *, int)" }, + { LibGetc, "int getc()" }, { NULL, NULL } }; diff --git a/expression.c b/expression.c index 0883bb1..4dd681e 100644 --- a/expression.c +++ b/expression.c @@ -70,7 +70,7 @@ int ExpressionParseValue(struct ParseState *Parser, struct Value **Result) VariableStackPop(Parser, *Result); *Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, VType, TypePointer, 0, StrEmpty), FALSE, NULL); (*Result)->Val->Pointer.Segment = LocalLValue; - (*Result)->Val->Pointer.Data.Offset = (void *)(*Result)->Val - (void *)(*Result)->LValueFrom; + (*Result)->Val->Pointer.Offset = (void *)(*Result)->Val - (void *)(*Result)->LValueFrom; break; case TokenIdentifier: diff --git a/lex.c b/lex.c index 4f5b61a..1a5c21b 100644 --- a/lex.c +++ b/lex.c @@ -280,7 +280,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value) /* create the the pointer for this char* */ Value->Typ = CharPtrType; Value->Val->Pointer.Segment = ArrayValue; - Value->Val->Pointer.Data.Offset = 0; + Value->Val->Pointer.Offset = 0; if (*Lexer->Pos == '"') Lexer->Pos++; diff --git a/platform_library.c b/library_surveyor.c similarity index 93% rename from platform_library.c rename to library_surveyor.c index 005a620..c165fe1 100644 --- a/platform_library.c +++ b/library_surveyor.c @@ -1,31 +1,8 @@ #include "picoc.h" -void SayHello(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - PlatformPrintf("Hello\n"); -} - -void PrintInteger(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - PlatformPrintf("%d\n", Param[0]->Val->Integer); -} - -#ifdef UNIX_HOST -void Random(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = rand(); -} -#endif - -static int SomeVar = 42; -static int SomeArray[4]; static int Blobcnt, Blobx1, Blobx2, Bloby1, Bloby2, Iy1, Iy2, Iu1, Iu2, Iv1, Iv2; void PlatformLibraryInit() { - struct ValueType *IntArrayType; - - VariableDefinePlatformVar(NULL, "somevar", &IntType, (union AnyValue *)&SomeVar, TRUE); - VariableDefinePlatformVar(NULL, "blobcnt", &IntType, (union AnyValue *)&Blobcnt, FALSE); VariableDefinePlatformVar(NULL, "blobx1", &IntType, (union AnyValue *)&Blobx1, FALSE); VariableDefinePlatformVar(NULL, "blobx2", &IntType, (union AnyValue *)&Blobx2, FALSE); @@ -37,17 +14,8 @@ void PlatformLibraryInit() VariableDefinePlatformVar(NULL, "u2", &IntType, (union AnyValue *)&Iu2, FALSE); VariableDefinePlatformVar(NULL, "v1", &IntType, (union AnyValue *)&Iv1, FALSE); VariableDefinePlatformVar(NULL, "v2", &IntType, (union AnyValue *)&Iv2, FALSE); - - IntArrayType = TypeGetMatching(NULL, &IntType, TypeArray, 4, NULL); - SomeArray[0] = 12; - SomeArray[1] = 34; - SomeArray[2] = 56; - SomeArray[3] = 78; - VariableDefinePlatformVar(NULL, "somearray", IntArrayType, (union AnyValue *)&SomeArray, FALSE); } -#ifdef SURVEYOR_HOST - void Csignal(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // check for kbhit, return t or nil { unsigned char ch; @@ -567,16 +535,4 @@ struct LibraryFunction PlatformLibrary[] = { Cnnlearnblob, "void nnlearnblob(int)" }, { NULL, NULL } }; -#endif - -#ifdef UNIX_HOST -/* list of all library functions and their prototypes */ -struct LibraryFunction PlatformLibrary[] = -{ - { SayHello, "void sayhello()" }, - { PrintInteger, "void printint(int)" }, - { Random, "int random()" }, - { NULL, NULL } -}; -#endif diff --git a/library_unix.c b/library_unix.c new file mode 100644 index 0000000..403fef6 --- /dev/null +++ b/library_unix.c @@ -0,0 +1,12 @@ +#include "picoc.h" + +void PlatformLibraryInit() +{ +} + +/* list of all library functions and their prototypes */ +struct LibraryFunction PlatformLibrary[] = +{ + { NULL, NULL } +}; + diff --git a/picoc.h b/picoc.h index 44d18d8..9003061 100644 --- a/picoc.h +++ b/picoc.h @@ -108,15 +108,15 @@ enum BaseType /* data type */ struct ValueType { - enum BaseType Base; /* what kind of type this is */ - int ArraySize; /* the size of an array type */ - int Sizeof; /* the storage required */ - const char *Identifier; /* the name of a struct or union */ - struct ValueType *FromType; /* the type we're derived from (or NULL) */ + enum BaseType Base; /* what kind of type this is */ + int ArraySize; /* the size of an array type */ + int Sizeof; /* the storage required */ + const char *Identifier; /* the name of a struct or union */ + struct ValueType *FromType; /* the type we're derived from (or NULL) */ struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */ - struct ValueType *Next; /* next item in the derived type list */ - struct Table *Members; /* members of a struct or union */ - int OnHeap; /* true if allocated on the heap */ + struct ValueType *Next; /* next item in the derived type list */ + struct Table *Members; /* members of a struct or union */ + int OnHeap; /* true if allocated on the heap */ }; /* function definition */ @@ -134,17 +134,14 @@ struct FuncDef /* values */ struct ArrayValue { - unsigned int Size; /* the number of elements in the array */ - void *Data; /* pointer to the array data */ + unsigned int Size; /* the number of elements in the array */ + void *Data; /* pointer to the array data */ }; struct PointerValue { - struct Value *Segment; /* array or basic value which this points to, NULL for machine memory access */ - union s { - unsigned int Offset; /* index into an array */ - void *Memory; /* machine memory pointer for raw memory access */ - } Data; + struct Value *Segment; /* array or basic value which this points to, NULL for machine memory access */ + unsigned int Offset; /* index into an array */ }; union AnyValue @@ -165,27 +162,27 @@ union AnyValue struct Value { - struct ValueType *Typ; /* the type of this value */ - union AnyValue *Val; /* pointer to the AnyValue which holds the actual content */ - struct Value *LValueFrom; /* if an LValue, this is a Value our LValue is contained within (or NULL) */ - char ValOnHeap; /* the AnyValue is on the heap (but this Value is on the stack) */ - char ValOnStack; /* the AnyValue is on the stack along with this Value */ - char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */ + struct ValueType *Typ; /* the type of this value */ + union AnyValue *Val; /* pointer to the AnyValue which holds the actual content */ + struct Value *LValueFrom; /* if an LValue, this is a Value our LValue is contained within (or NULL) */ + char ValOnHeap; /* the AnyValue is on the heap (but this Value is on the stack) */ + char ValOnStack; /* the AnyValue is on the stack along with this Value */ + char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */ }; /* hash table data structure */ struct TableEntry { - struct TableEntry *Next; /* next item in this hash chain */ + struct TableEntry *Next; /* next item in this hash chain */ union TableEntryPayload { struct ValueEntry { - char *Key; /* points to the shared string table */ - struct Value *Val; /* the value we're storing */ - } v; /* used for tables of values */ + char *Key; /* points to the shared string table */ + struct Value *Val; /* the value we're storing */ + } 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 */ } p; }; diff --git a/platform.c b/platform.c new file mode 100644 index 0000000..cc120d8 --- /dev/null +++ b/platform.c @@ -0,0 +1,64 @@ +#include "picoc.h" + + +/* 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"); + PlatformExit(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"); + PlatformExit(1); +} + +/* 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/platform_support.c b/platform_support.c deleted file mode 100644 index 4aa37b0..0000000 --- a/platform_support.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "picoc.h" - -#ifdef UNIX_HOST -/* a source file we need to clean up */ -static char *CleanupText = NULL; - -/* deallocate any storage */ -void PlatformCleanup() -{ - if (CleanupText != NULL) - HeapFree(CleanupText); -} - -/* get a line of interactive input */ -char *PlatformGetLine(char *Buf, int MaxLen) -{ - fflush(stdout); - 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; - int BytesRead; - - 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); - - BytesRead = fread(ReadText, 1, FileInfo.st_size, InFile); - if (BytesRead == 0) - ProgramFail(NULL, "can't read file %s\n", FileName); - - ReadText[BytesRead] = '\0'; - fclose(InFile); - - return ReadText; -} - -/* read and scan a file for definitions */ -void PlatformScanFile(const char *FileName) -{ - char *SourceStr = PlatformReadFile(FileName); - char *OrigCleanupText = CleanupText; - if (CleanupText == NULL) - CleanupText = SourceStr; - - Parse(FileName, SourceStr, strlen(SourceStr), TRUE); - free(SourceStr); - - if (OrigCleanupText == NULL) - CleanupText = NULL; -} - -/* mark where to end the program for platforms which require this */ -static jmp_buf ExitBuf; -int PlatformSetExitPoint() -{ - return setjmp(ExitBuf); -} - -/* exit the program */ -void PlatformExit() -{ - longjmp(ExitBuf, 1); -} -#endif - -#ifdef SURVEYOR_HOST - -/* deallocate any storage */ -void PlatformCleanup() -{ -} - -/* get a line of interactive input */ -char *PlatformGetLine(char *Buf, int MaxLen) -{ - int ix; - char ch, *cp; - - ix = 0; - cp = Buf; - while (ix++ < MaxLen) { - ch = getch(); - if (ch == 0x1B) { // ESC character - exit - printf("leaving picoC\n\r"); - return NULL; - } - if (ch == '\n') { - *cp++ = '\n'; // if newline, send newline character followed by null - *cp = 0; - return Buf; - } - *cp++ = ch; - ix++; - } - return NULL; -} - -/* write a character to the console */ -void PlatformPutc(unsigned char OutCh) -{ - putchar(OutCh); -} - -/* mark where to end the program for platforms which require this */ -int PlatformSetExitPoint() -{ - return 0; -} - -/* exit the program */ -extern int errjmp[]; - -void PlatformExit() -{ - errjmp[40] = 1; - longjmp(errjmp, 1); -} -#endif - -/* 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"); - PlatformExit(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"); - PlatformExit(1); -} - -/* 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/platform_surveyor.c b/platform_surveyor.c new file mode 100644 index 0000000..ad4bdda --- /dev/null +++ b/platform_surveyor.c @@ -0,0 +1,60 @@ +#include "picoc.h" + + +/* deallocate any storage */ +void PlatformCleanup() +{ +} + +/* get a line of interactive input */ +char *PlatformGetLine(char *Buf, int MaxLen) +{ + int ix; + char ch, *cp; + + ix = 0; + cp = Buf; + while (ix++ < MaxLen) { + ch = getch(); + if (ch == 0x1B) { // ESC character - exit + printf("leaving picoC\n\r"); + return NULL; + } + if (ch == '\n') { + *cp++ = '\n'; // if newline, send newline character followed by null + *cp = 0; + return Buf; + } + *cp++ = ch; + ix++; + } + return NULL; +} + +/* write a character to the console */ +void PlatformPutc(unsigned char OutCh) +{ + putchar(OutCh); +} + +/* write a character to the console */ +int PlatformGetc() +{ + return getch(); +} + +/* mark where to end the program for platforms which require this */ +int PlatformSetExitPoint() +{ + return 0; +} + +/* exit the program */ +extern int errjmp[]; + +void PlatformExit() +{ + errjmp[40] = 1; + longjmp(errjmp, 1); +} + diff --git a/platform_unix.c b/platform_unix.c new file mode 100644 index 0000000..7859f3f --- /dev/null +++ b/platform_unix.c @@ -0,0 +1,82 @@ +#include "picoc.h" + +/* a source file we need to clean up */ +static char *CleanupText = NULL; + +/* deallocate any storage */ +void PlatformCleanup() +{ + if (CleanupText != NULL) + HeapFree(CleanupText); +} + +/* get a line of interactive input */ +char *PlatformGetLine(char *Buf, int MaxLen) +{ + fflush(stdout); + 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; + int BytesRead; + + 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); + + BytesRead = fread(ReadText, 1, FileInfo.st_size, InFile); + if (BytesRead == 0) + ProgramFail(NULL, "can't read file %s\n", FileName); + + ReadText[BytesRead] = '\0'; + fclose(InFile); + + return ReadText; +} + +/* read and scan a file for definitions */ +void PlatformScanFile(const char *FileName) +{ + char *SourceStr = PlatformReadFile(FileName); + char *OrigCleanupText = CleanupText; + if (CleanupText == NULL) + CleanupText = SourceStr; + + Parse(FileName, SourceStr, strlen(SourceStr), TRUE); + free(SourceStr); + + if (OrigCleanupText == NULL) + CleanupText = NULL; +} + +/* mark where to end the program for platforms which require this */ +static jmp_buf ExitBuf; +int PlatformSetExitPoint() +{ + return setjmp(ExitBuf); +} + +/* exit the program */ +void PlatformExit() +{ + longjmp(ExitBuf, 1); +} +