From 3f5c4725f90133402a4fd8dbd3c20a34dca10777 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 15 Jul 2014 22:41:09 +0200 Subject: [PATCH] [DEV] start rework of the eci lib ==> base seams to be interecting but not really extensive --- README | 86 +- eci/clibrary.c | 610 +++++++ eci/cstdlib/ctype.c | 93 ++ eci/cstdlib/errno.c | 574 +++++++ eci/cstdlib/math.c | 162 ++ eci/cstdlib/stdbool.c | 21 + eci/cstdlib/stdio.c | 657 ++++++++ eci/cstdlib/stdlib.c | 118 ++ eci/cstdlib/string.c | 151 ++ eci/cstdlib/time.c | 108 ++ eci/cstdlib/unistd.c | 373 +++++ eci/expression.c | 1533 ++++++++++++++++++ eci/heap.c | 119 ++ eci/include.c | 94 ++ {ecilib => eci}/interpreter.h | 368 ++--- eci/lex.c | 980 +++++++++++ eci/parse.c | 758 +++++++++ eci/picoc.c | 45 + {ecilib => eci}/picoc.h | 9 - eci/platform.c | 215 +++ eci/platform.h | 43 + {ecilib => eci}/platform/library_ffox.c | 0 {ecilib => eci}/platform/library_srv1.c | 0 {ecilib => eci}/platform/library_surveyor.c | 0 eci/platform/library_unix.c | 25 + {ecilib => eci}/platform/platform_ffox.c | 0 {ecilib => eci}/platform/platform_surveyor.c | 0 eci/platform/platform_unix.c | 89 + eci/table.c | 156 ++ eci/type.c | 521 ++++++ eci/variable.c | 353 ++++ ecilib/clibrary.c | 676 -------- ecilib/cstdlib/ctype.c | 110 -- ecilib/cstdlib/errno.c | 655 -------- ecilib/cstdlib/math.c | 187 --- ecilib/cstdlib/stdbool.c | 22 - ecilib/cstdlib/stdio.c | 722 --------- ecilib/cstdlib/stdlib.c | 174 -- ecilib/cstdlib/string.c | 178 -- ecilib/cstdlib/time.c | 124 -- ecilib/cstdlib/unistd.c | 499 ------ ecilib/expression.c | 1501 ----------------- ecilib/heap.c | 285 ---- ecilib/include.c | 110 -- ecilib/lex.c | 971 ----------- ecilib/parse.c | 872 ---------- ecilib/picoc.c | 101 -- ecilib/platform.c | 236 --- ecilib/platform.h | 125 -- ecilib/platform/library_unix.c | 29 - ecilib/platform/platform_unix.c | 102 -- ecilib/table.c | 187 --- ecilib/type.c | 536 ------ ecilib/variable.c | 350 ---- lutin_eci.py | 43 + tests/Makefile | 4 +- 56 files changed, 8021 insertions(+), 9039 deletions(-) create mode 100644 eci/clibrary.c create mode 100644 eci/cstdlib/ctype.c create mode 100644 eci/cstdlib/errno.c create mode 100644 eci/cstdlib/math.c create mode 100644 eci/cstdlib/stdbool.c create mode 100644 eci/cstdlib/stdio.c create mode 100644 eci/cstdlib/stdlib.c create mode 100644 eci/cstdlib/string.c create mode 100644 eci/cstdlib/time.c create mode 100644 eci/cstdlib/unistd.c create mode 100644 eci/expression.c create mode 100644 eci/heap.c create mode 100644 eci/include.c rename {ecilib => eci}/interpreter.h (54%) create mode 100644 eci/lex.c create mode 100644 eci/parse.c create mode 100644 eci/picoc.c rename {ecilib => eci}/picoc.h (80%) create mode 100644 eci/platform.c create mode 100644 eci/platform.h rename {ecilib => eci}/platform/library_ffox.c (100%) rename {ecilib => eci}/platform/library_srv1.c (100%) rename {ecilib => eci}/platform/library_surveyor.c (100%) create mode 100644 eci/platform/library_unix.c rename {ecilib => eci}/platform/platform_ffox.c (100%) rename {ecilib => eci}/platform/platform_surveyor.c (100%) create mode 100644 eci/platform/platform_unix.c create mode 100644 eci/table.c create mode 100644 eci/type.c create mode 100644 eci/variable.c delete mode 100644 ecilib/clibrary.c delete mode 100644 ecilib/cstdlib/ctype.c delete mode 100644 ecilib/cstdlib/errno.c delete mode 100644 ecilib/cstdlib/math.c delete mode 100644 ecilib/cstdlib/stdbool.c delete mode 100644 ecilib/cstdlib/stdio.c delete mode 100644 ecilib/cstdlib/stdlib.c delete mode 100644 ecilib/cstdlib/string.c delete mode 100644 ecilib/cstdlib/time.c delete mode 100644 ecilib/cstdlib/unistd.c delete mode 100644 ecilib/expression.c delete mode 100644 ecilib/heap.c delete mode 100644 ecilib/include.c delete mode 100644 ecilib/lex.c delete mode 100644 ecilib/parse.c delete mode 100644 ecilib/picoc.c delete mode 100644 ecilib/platform.c delete mode 100644 ecilib/platform.h delete mode 100644 ecilib/platform/library_unix.c delete mode 100644 ecilib/platform/platform_unix.c delete mode 100644 ecilib/table.c delete mode 100644 ecilib/type.c delete mode 100644 ecilib/variable.c create mode 100644 lutin_eci.py diff --git a/README b/README index 18779d3..99859fc 100644 --- a/README +++ b/README @@ -1,91 +1,11 @@ -picoc +ECI : Ewol C Interpreter ----- -PicoC is a very small C interpreter for scripting. It was originally written -as a script language for a UAV's on-board flight system. It's also very -suitable for other robotic, embedded and non-embedded applications. +Eci is a fork of PicoC... -The core C source code is around 3500 lines of code. It's not intended to be -a complete implementation of ISO C but it has all the essentials. When -compiled it only takes a few k of code space and is also very sparing of -data space. This means it can work well in small embedded devices. It's also -a fun example of how to create a very small language implementation while -still keeping the code readable. - -picoc is now feature frozen. Since it's important that it remain small it's -intended that no more major features will be added from now on. It's been -tested on x86-32, x86-64, powerpc, arm, ultrasparc, HP-PA and blackfin -processors and is easy to port to new targets. - - -Compiling picoc ---------------- - -picoc can be compiled for a UNIX/Linux/POSIX host by typing "make". - -The test suite can be run by typing "make test". - - -Porting picoc -------------- - -platform.h is where you select your platform type and specify the includes -etc. for your platform. - -platform_XXX.c contains support functions so the compiler can work on -your platform, such as how to write characters to the console etc.. - -platform_library.c contains your library of functions you want to make -available to user programs. - -There's also a clibrary.c which contains user library functions like -printf() which are platform-independent. - -Porting the system will involve setting up suitable includes and defines -in platform.h, writing some I/O routines in platform_XXX.c, putting -whatever user functions you want in platform_library.c and then changing -the main program in picoc.c to whatever you need to do to get programs -into the system. - -platform.h is set to UNIX_HOST by default so tests can be easily run on -a UNIX system. You'll need to specify your own host setup dependent on -your target platform. Copyright --------- -picoc is published under the "New BSD License". -http://www.opensource.org/licenses/bsd-license.php - - -Copyright (c) 2009-2011, Zik Saleeba -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of the Zik Saleeba nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +BSD 3 clauses \ No newline at end of file diff --git a/eci/clibrary.c b/eci/clibrary.c new file mode 100644 index 0000000..b3a5fcf --- /dev/null +++ b/eci/clibrary.c @@ -0,0 +1,610 @@ +#include "picoc.h" +#include "interpreter.h" + +/* the picoc version string */ +static const char *VersionString = NULL; + +/* endian-ness checking */ +static const int __ENDIAN_CHECK__ = 1; + +static int BigEndian = 0; +static int LittleEndian = 0; + + +/* global initialisation for libraries */ +void LibraryInit() { + /* define the version number macro */ + VersionString = TableStrRegister(PICOC_VERSION); + VariableDefinePlatformVar(NULL, "PICOC_VERSION", CharPtrType, (union AnyValue *)&VersionString, FALSE); + /* define endian-ness macros */ + BigEndian = ((*(char*)&__ENDIAN_CHECK__) == 0); + LittleEndian = ((*(char*)&__ENDIAN_CHECK__) == 1); + VariableDefinePlatformVar(NULL, "BIG_ENDIAN", &IntType, (union AnyValue *)&BigEndian, FALSE); + VariableDefinePlatformVar(NULL, "LITTLE_ENDIAN", &IntType, (union AnyValue *)&LittleEndian, FALSE); +} + +/* add a library */ +void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction *FuncList) { + struct ParseState Parser; + int Count; + char *Identifier; + struct ValueType *ReturnType; + struct Value *NewValue; + void *Tokens; + const 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); + TypeParse(&Parser, &ReturnType, &Identifier, NULL); + NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); + NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; + HeapFreeMem(Tokens); + } +} + +/* print a type to a stream without using printf/sprintf */ +void PrintType(struct ValueType *Typ, IOFILE *Stream) { + switch (Typ->Base) { + case TypeVoid: PrintStr("void", Stream); break; + case TypeInt: PrintStr("int", Stream); break; + case TypeShort: PrintStr("short", Stream); break; + case TypeChar: PrintStr("char", Stream); break; + case TypeLong: PrintStr("long", Stream); break; + case TypeUnsignedInt: PrintStr("unsigned int", Stream); break; + case TypeUnsignedShort: PrintStr("unsigned short", Stream); break; + case TypeUnsignedLong: PrintStr("unsigned long", Stream); break; +#ifndef NO_FP + case TypeFP: PrintStr("double", Stream); break; +#endif + case TypeFunction: PrintStr("function", Stream); break; + case TypeMacro: PrintStr("macro", Stream); break; + case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break; + case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintSimpleInt(Typ->ArraySize, Stream); PrintCh(']', Stream); break; + case TypeStruct: PrintStr("struct ", Stream); PrintStr(Typ->Identifier, Stream); break; + case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break; + case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break; + case TypeGotoLabel: PrintStr("goto label ", Stream); break; + case Type_Type: PrintStr("type ", Stream); break; + } +} + + +#ifdef BUILTIN_MINI_STDLIB + +/* + * This is a simplified standard library for small embedded systems. It doesn't require + * a system stdio library to operate. + * + * A more complete standard library for larger computers is in the library_XXX.c files. + */ +IOFILE *CStdOut; +IOFILE CStdOutBase; + +static int TRUEValue = 1; +static int ZeroValue = 0; + +void BasicIOInit() { + CStdOutBase.Putch = &PlatformPutc; + CStdOut = &CStdOutBase; +} + +/* initialise the C library */ +void CLibraryInit() { + /* define some constants */ + VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); + VariableDefinePlatformVar(NULL, "TRUE", &IntType, (union AnyValue *)&TRUEValue, FALSE); + VariableDefinePlatformVar(NULL, "FALSE", &IntType, (union AnyValue *)&ZeroValue, FALSE); +} + +/* stream for writing into strings */ +void SPutc(unsigned char Ch, union OutputStreamInfo *Stream) { + struct StringOutputStream *Out = &Stream->Str; + *Out->WritePos++ = Ch; +} + +/* print a character to a stream without using printf/sprintf */ +void PrintCh(char OutCh, struct OutputStream *Stream) { + (*Stream->Putch)(OutCh, &Stream->i); +} + +/* print a string to a stream without using printf/sprintf */ +void PrintStr(const char *Str, struct OutputStream *Stream) { + while (*Str != 0) { + PrintCh(*Str++, Stream); + } +} + +/* print a single character a given number of times */ +void PrintRepeatedChar(char ShowChar, int Length, struct OutputStream *Stream) { + while (Length-- > 0) { + PrintCh(ShowChar, Stream); + } +} + +/* print an unsigned integer to a stream without using printf/sprintf */ +void PrintUnsigned(unsigned long Num, unsigned int Base, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream) { + char Result[33]; + int ResPos = sizeof(Result); + + Result[--ResPos] = '\0'; + if (Num == 0) { + Result[--ResPos] = '0'; + } + + while (Num > 0) { + unsigned long NextNum = Num / Base; + unsigned long Digit = Num - NextNum * Base; + if (Digit < 10) { + Result[--ResPos] = '0' + Digit; + } else { + Result[--ResPos] = 'a' + Digit - 10; + } + Num = NextNum; + } + + if (FieldWidth > 0 && !LeftJustify) { + PrintRepeatedChar(ZeroPad ? '0' : ' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream); + } + PrintStr(&Result[ResPos], Stream); + if (FieldWidth > 0 && LeftJustify) { + PrintRepeatedChar(' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream); + } +} + +/* print an integer to a stream without using printf/sprintf */ +void PrintSimpleInt(long Num, struct OutputStream *Stream) { + PrintInt(Num, -1, FALSE, FALSE, Stream); +} + +/* print an integer to a stream without using printf/sprintf */ +void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream) { + if (Num < 0) { + PrintCh('-', Stream); + Num = -Num; + if (FieldWidth != 0) { + FieldWidth--; + } + } + PrintUnsigned((unsigned long)Num, 10, FieldWidth, ZeroPad, LeftJustify, Stream); +} + +#ifndef NO_FP +/* print a double to a stream without using printf/sprintf */ +void PrintFP(double Num, struct OutputStream *Stream) { + int Exponent = 0; + int MaxDecimal; + if (Num < 0) { + PrintCh('-', Stream); + Num = -Num; + } + + if (Num >= 1e7) { + Exponent = log10(Num); + } else if (Num <= 1e-7 && Num != 0.0) { + Exponent = log10(Num) - 0.999999999; + } + Num /= pow(10.0, Exponent); + PrintInt((long)Num, 0, FALSE, FALSE, Stream); + PrintCh('.', Stream); + Num = (Num - (long)Num) * 10; + if (abs(Num) >= 1e-7) { + for (MaxDecimal = 6; MaxDecimal > 0 && abs(Num) >= 1e-7; Num = (Num - (long)(Num + 1e-7)) * 10, MaxDecimal--) { + PrintCh('0' + (long)(Num + 1e-7), Stream); + } + } else { + PrintCh('0', Stream); + } + if (Exponent != 0) { + PrintCh('e', Stream); + PrintInt(Exponent, 0, FALSE, FALSE, Stream); + } +} +#endif + +/* intrinsic functions made available to the language */ +void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream) { + char *FPos; + struct Value *NextArg = Param[0]; + struct ValueType *FormatType; + int ArgCount = 1; + int LeftJustify = FALSE; + int ZeroPad = FALSE; + int FieldWidth = 0; + char *Format = Param[0]->Val->Pointer; + + for (FPos = Format; *FPos != '\0'; FPos++) { + if (*FPos == '%') { + FPos++; + if (*FPos == '-') { + /* a leading '-' means left justify */ + LeftJustify = TRUE; + FPos++; + } + + if (*FPos == '0') { + /* a leading zero means zero pad a decimal number */ + ZeroPad = TRUE; + FPos++; + } + + /* get any field width in the format */ + while (isdigit((int)*FPos)) { + FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); + } + /* now check the format type */ + switch (*FPos) { + case 's': FormatType = CharPtrType; break; + case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; +#ifndef NO_FP + case 'f': FormatType = &FPType; break; +#endif + case '%': PrintCh('%', Stream); FormatType = NULL; break; + case '\0': FPos--; FormatType = NULL; break; + default: PrintCh(*FPos, Stream); FormatType = NULL; break; + } + + if (FormatType != NULL) { + /* we have to format something */ + if (ArgCount >= NumArgs) { + PrintStr("XXX", Stream); /* not enough parameters for format */ + } else { + NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); + if (NextArg->Typ != FormatType && + !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && + !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || + (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) { + PrintStr("XXX", Stream); /* bad type for format */ + } else { + switch (*FPos) { + case 's': + { + char *Str; + + if (NextArg->Typ->Base == TypePointer) { + Str = NextArg->Val->Pointer; + }else { + Str = &NextArg->Val->ArrayMem[0]; + } + if (Str == NULL) { + PrintStr("NULL", Stream); + } else { + PrintStr(Str, Stream); + } + break; + } + case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break; + case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break; + case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break; + case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break; + case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break; +#ifndef NO_FP + case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break; +#endif + } + } + } + ArgCount++; + } + } else { + PrintCh(*FPos, Stream); + } + } +} + +/* printf(): print to console output */ +void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct OutputStream ConsoleStream; + ConsoleStream.Putch = &PlatformPutc; + GenericPrintf(Parser, ReturnValue, Param, NumArgs, &ConsoleStream); +} + +/* sprintf(): print to a string */ +void LibSPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct OutputStream StrStream; + StrStream.Putch = &SPutc; + StrStream.i.Str.Parser = Parser; + StrStream.i.Str.WritePos = Param[0]->Val->Pointer; + GenericPrintf(Parser, ReturnValue, Param+1, NumArgs-1, &StrStream); + PrintCh(0, &StrStream); + ReturnValue->Val->Pointer = *Param; +} + +/* get a line of input. protected from buffer overrun */ +void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = PlatformGetLine(Param[0]->Val->Pointer, GETS_BUF_MAX, NULL); + if (ReturnValue->Val->Pointer != NULL) { + char *EOLPos = strchr(Param[0]->Val->Pointer, '\n'); + if (EOLPos != NULL) { + *EOLPos = '\0'; + } + } +} + +void LibGetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = PlatformGetCharacter(); +} + +void LibExit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + PlatformExit(Param[0]->Val->Integer); +} + +#ifdef PICOC_LIBRARY +void LibSin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sin(Param[0]->Val->FP); +} + +void LibCos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = cos(Param[0]->Val->FP); +} + +void LibTan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = tan(Param[0]->Val->FP); +} + +void LibAsin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = asin(Param[0]->Val->FP); +} + +void LibAcos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = acos(Param[0]->Val->FP); +} + +void LibAtan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = atan(Param[0]->Val->FP); +} + +void LibSinh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sinh(Param[0]->Val->FP); +} + +void LibCosh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = cosh(Param[0]->Val->FP); +} + +void LibTanh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = tanh(Param[0]->Val->FP); +} + +void LibExp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = exp(Param[0]->Val->FP); +} + +void LibFabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = fabs(Param[0]->Val->FP); +} + +void LibLog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = log(Param[0]->Val->FP); +} + +void LibLog10(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = log10(Param[0]->Val->FP); +} + +void LibPow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = pow(Param[0]->Val->FP, Param[1]->Val->FP); +} + +void LibSqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sqrt(Param[0]->Val->FP); +} + +void LibRound(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = floor(Param[0]->Val->FP + 0.5); /* XXX - fix for soft float */ +} + +void LibCeil(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = ceil(Param[0]->Val->FP); +} + +void LibFloor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = floor(Param[0]->Val->FP); +} +#endif + +#ifndef NO_STRING_FUNCTIONS +void LibMalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = malloc(Param[0]->Val->Integer); +} + +#ifndef NO_CALLOC +void LibCalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = calloc(Param[0]->Val->Integer, Param[1]->Val->Integer); +} +#endif + +#ifndef NO_REALLOC +void LibRealloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = realloc(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} +#endif + +void LibFree(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + free(Param[0]->Val->Pointer); +} + +void LibStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *To = (char *)Param[0]->Val->Pointer; + char *From = (char *)Param[1]->Val->Pointer; + + while (*From != '\0') { + *To++ = *From++; + } + + *To = '\0'; +} + +void LibStrncpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *To = (char *)Param[0]->Val->Pointer; + char *From = (char *)Param[1]->Val->Pointer; + int Len = Param[2]->Val->Integer; + + for (; *From != '\0' && Len > 0; Len--) { + *To++ = *From++; + } + if (Len > 0) { + *To = '\0'; + } +} + +void LibStrcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *Str1 = (char *)Param[0]->Val->Pointer; + char *Str2 = (char *)Param[1]->Val->Pointer; + int StrEnded; + + for (StrEnded = FALSE; !StrEnded; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++) { + if (*Str1 < *Str2) { + ReturnValue->Val->Integer = -1; + return; + } else if (*Str1 > *Str2) { + ReturnValue->Val->Integer = 1; + return; + } + } + ReturnValue->Val->Integer = 0; +} + +void LibStrncmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *Str1 = (char *)Param[0]->Val->Pointer; + char *Str2 = (char *)Param[1]->Val->Pointer; + int Len = Param[2]->Val->Integer; + int StrEnded; + + for (StrEnded = FALSE; !StrEnded && Len > 0; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++, Len--) { + if (*Str1 < *Str2) { + ReturnValue->Val->Integer = -1; + return; + } else if (*Str1 > *Str2) { + ReturnValue->Val->Integer = 1; + return; + } + } + ReturnValue->Val->Integer = 0; +} + +void LibStrcat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *To = (char *)Param[0]->Val->Pointer; + char *From = (char *)Param[1]->Val->Pointer; + while (*To != '\0') { + To++; + } + while (*From != '\0') { + *To++ = *From++; + } + *To = '\0'; +} + +void LibIndex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *Pos = (char *)Param[0]->Val->Pointer; + int SearchChar = Param[1]->Val->Integer; + while (*Pos != '\0' && *Pos != SearchChar) { + Pos++; + } + if (*Pos != SearchChar) { + ReturnValue->Val->Pointer = NULL; + } else { + ReturnValue->Val->Pointer = Pos; + } +} + +void LibRindex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *Pos = (char *)Param[0]->Val->Pointer; + int SearchChar = Param[1]->Val->Integer; + ReturnValue->Val->Pointer = NULL; + for (; *Pos != '\0'; Pos++) { + if (*Pos == SearchChar) { + ReturnValue->Val->Pointer = Pos; + } + } +} + +void LibStrlen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + char *Pos = (char *)Param[0]->Val->Pointer; + int Len; + for (Len = 0; *Pos != '\0'; Pos++) { + Len++; + } + ReturnValue->Val->Integer = Len; +} + +void LibMemset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + /* we can use the system memset() */ + memset(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void LibMemcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + /* we can use the system memcpy() */ + memcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void LibMemcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + unsigned char *Mem1 = (unsigned char *)Param[0]->Val->Pointer; + unsigned char *Mem2 = (unsigned char *)Param[1]->Val->Pointer; + int Len = Param[2]->Val->Integer; + + for (; Len > 0; Mem1++, Mem2++, Len--) { + if (*Mem1 < *Mem2) { + ReturnValue->Val->Integer = -1; + return; + } else if (*Mem1 > *Mem2) { + ReturnValue->Val->Integer = 1; + return; + } + } + ReturnValue->Val->Integer = 0; +} +#endif + +/* list of all library functions and their prototypes */ +struct LibraryFunction CLibrary[] = { + { LibPrintf, "void printf(char *, ...);" }, + { LibSPrintf, "char *sprintf(char *, char *, ...);" }, + { LibGets, "char *gets(char *);" }, + { LibGetc, "int getchar();" }, + { LibExit, "void exit(int);" }, +#ifdef PICOC_LIBRARY + { LibSin, "float sin(float);" }, + { LibCos, "float cos(float);" }, + { LibTan, "float tan(float);" }, + { LibAsin, "float asin(float);" }, + { LibAcos, "float acos(float);" }, + { LibAtan, "float atan(float);" }, + { LibSinh, "float sinh(float);" }, + { LibCosh, "float cosh(float);" }, + { LibTanh, "float tanh(float);" }, + { LibExp, "float exp(float);" }, + { LibFabs, "float fabs(float);" }, + { LibLog, "float log(float);" }, + { LibLog10, "float log10(float);" }, + { LibPow, "float pow(float,float);" }, + { LibSqrt, "float sqrt(float);" }, + { LibRound, "float round(float);" }, + { LibCeil, "float ceil(float);" }, + { LibFloor, "float floor(float);" }, +#endif + { LibMalloc, "void *malloc(int);" }, +#ifndef NO_CALLOC + { LibCalloc, "void *calloc(int,int);" }, +#endif +#ifndef NO_REALLOC + { LibRealloc, "void *realloc(void *,int);" }, +#endif + { LibFree, "void free(void *);" }, +#ifndef NO_STRING_FUNCTIONS + { LibStrcpy, "void strcpy(char *,char *);" }, + { LibStrncpy, "void strncpy(char *,char *,int);" }, + { LibStrcmp, "int strcmp(char *,char *);" }, + { LibStrncmp, "int strncmp(char *,char *,int);" }, + { LibStrcat, "void strcat(char *,char *);" }, + { LibIndex, "char *index(char *,int);" }, + { LibRindex, "char *rindex(char *,int);" }, + { LibStrlen, "int strlen(char *);" }, + { LibMemset, "void memset(void *,int,int);" }, + { LibMemcpy, "void memcpy(void *,void *,int);" }, + { LibMemcmp, "int memcmp(void *,void *,int);" }, +#endif + { NULL, NULL } +}; + +#endif /* BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/ctype.c b/eci/cstdlib/ctype.c new file mode 100644 index 0000000..e4254ae --- /dev/null +++ b/eci/cstdlib/ctype.c @@ -0,0 +1,93 @@ +/* string.h library for large systems - small embedded systems use clibrary.c instead */ +#include +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +void StdIsalnum(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isalnum(Param[0]->Val->Integer); +} + +void StdIsalpha(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isalpha(Param[0]->Val->Integer); +} + +void StdIsblank(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + int ch = Param[0]->Val->Integer; + ReturnValue->Val->Integer = (ch == ' ') | (ch == '\t'); +} + +void StdIscntrl(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = iscntrl(Param[0]->Val->Integer); +} + +void StdIsdigit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isdigit(Param[0]->Val->Integer); +} + +void StdIsgraph(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isgraph(Param[0]->Val->Integer); +} + +void StdIslower(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = islower(Param[0]->Val->Integer); +} + +void StdIsprint(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isprint(Param[0]->Val->Integer); +} + +void StdIspunct(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ispunct(Param[0]->Val->Integer); +} + +void StdIsspace(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isspace(Param[0]->Val->Integer); +} + +void StdIsupper(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isupper(Param[0]->Val->Integer); +} + +void StdIsxdigit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isxdigit(Param[0]->Val->Integer); +} + +void StdTolower(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = tolower(Param[0]->Val->Integer); +} + +void StdToupper(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = toupper(Param[0]->Val->Integer); +} + +void StdIsascii(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isascii(Param[0]->Val->Integer); +} + +void StdToascii(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = toascii(Param[0]->Val->Integer); +} + +/* all string.h functions */ +struct LibraryFunction StdCtypeFunctions[] = { + { StdIsalnum, "int isalnum(int);" }, + { StdIsalpha, "int isalpha(int);" }, + { StdIsblank, "int isblank(int);" }, + { StdIscntrl, "int iscntrl(int);" }, + { StdIsdigit, "int isdigit(int);" }, + { StdIsgraph, "int isgraph(int);" }, + { StdIslower, "int islower(int);" }, + { StdIsprint, "int isprint(int);" }, + { StdIspunct, "int ispunct(int);" }, + { StdIsspace, "int isspace(int);" }, + { StdIsupper, "int isupper(int);" }, + { StdIsxdigit, "int isxdigit(int);" }, + { StdTolower, "int tolower(int);" }, + { StdToupper, "int toupper(int);" }, + { StdIsascii, "int isascii(int);" }, + { StdToascii, "int toascii(int);" }, + { NULL, NULL } +}; + +#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/errno.c b/eci/cstdlib/errno.c new file mode 100644 index 0000000..0fdb86b --- /dev/null +++ b/eci/cstdlib/errno.c @@ -0,0 +1,574 @@ +/* string.h library for large systems - small embedded systems use clibrary.c instead */ +#include +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +#ifdef EACCES +static int EACCESValue = EACCES; +#endif + +#ifdef EADDRINUSE +static int EADDRINUSEValue = EADDRINUSE; +#endif + +#ifdef EADDRNOTAVAIL +static int EADDRNOTAVAILValue = EADDRNOTAVAIL; +#endif + +#ifdef EAFNOSUPPORT +static int EAFNOSUPPORTValue = EAFNOSUPPORT; +#endif + +#ifdef EAGAIN +static int EAGAINValue = EAGAIN; +#endif + +#ifdef EALREADY +static int EALREADYValue = EALREADY; +#endif + +#ifdef EBADF +static int EBADFValue = EBADF; +#endif + +#ifdef EBADMSG +static int EBADMSGValue = EBADMSG; +#endif + +#ifdef EBUSY +static int EBUSYValue = EBUSY; +#endif + +#ifdef ECANCELED +static int ECANCELEDValue = ECANCELED; +#endif + +#ifdef ECHILD +static int ECHILDValue = ECHILD; +#endif + +#ifdef ECONNABORTED +static int ECONNABORTEDValue = ECONNABORTED; +#endif + +#ifdef ECONNREFUSED +static int ECONNREFUSEDValue = ECONNREFUSED; +#endif + +#ifdef ECONNRESET +static int ECONNRESETValue = ECONNRESET; +#endif + +#ifdef EDEADLK +static int EDEADLKValue = EDEADLK; +#endif + +#ifdef EDESTADDRREQ +static int EDESTADDRREQValue = EDESTADDRREQ; +#endif + +#ifdef EDOM +static int EDOMValue = EDOM; +#endif + +#ifdef EDQUOT +static int EDQUOTValue = EDQUOT; +#endif + +#ifdef EEXIST +static int EEXISTValue = EEXIST; +#endif + +#ifdef EFAULT +static int EFAULTValue = EFAULT; +#endif + +#ifdef EFBIG +static int EFBIGValue = EFBIG; +#endif + +#ifdef EHOSTUNREACH +static int EHOSTUNREACHValue = EHOSTUNREACH; +#endif + +#ifdef EIDRM +static int EIDRMValue = EIDRM; +#endif + +#ifdef EILSEQ +static int EILSEQValue = EILSEQ; +#endif + +#ifdef EINPROGRESS +static int EINPROGRESSValue = EINPROGRESS; +#endif + +#ifdef EINTR +static int EINTRValue = EINTR; +#endif + +#ifdef EINVAL +static int EINVALValue = EINVAL; +#endif + +#ifdef EIO +static int EIOValue = EIO; +#endif + +#ifdef EISCONN +static int EISCONNValue = EISCONN; +#endif + +#ifdef EISDIR +static int EISDIRValue = EISDIR; +#endif + +#ifdef ELOOP +static int ELOOPValue = ELOOP; +#endif + +#ifdef EMFILE +static int EMFILEValue = EMFILE; +#endif + +#ifdef EMLINK +static int EMLINKValue = EMLINK; +#endif + +#ifdef EMSGSIZE +static int EMSGSIZEValue = EMSGSIZE; +#endif + +#ifdef EMULTIHOP +static int EMULTIHOPValue = EMULTIHOP; +#endif + +#ifdef ENAMETOOLONG +static int ENAMETOOLONGValue = ENAMETOOLONG; +#endif + +#ifdef ENETDOWN +static int ENETDOWNValue = ENETDOWN; +#endif + +#ifdef ENETRESET +static int ENETRESETValue = ENETRESET; +#endif + +#ifdef ENETUNREACH +static int ENETUNREACHValue = ENETUNREACH; +#endif + +#ifdef ENFILE +static int ENFILEValue = ENFILE; +#endif + +#ifdef ENOBUFS +static int ENOBUFSValue = ENOBUFS; +#endif + +#ifdef ENODATA +static int ENODATAValue = ENODATA; +#endif + +#ifdef ENODEV +static int ENODEVValue = ENODEV; +#endif + +#ifdef ENOENT +static int ENOENTValue = ENOENT; +#endif + +#ifdef ENOEXEC +static int ENOEXECValue = ENOEXEC; +#endif + +#ifdef ENOLCK +static int ENOLCKValue = ENOLCK; +#endif + +#ifdef ENOLINK +static int ENOLINKValue = ENOLINK; +#endif + +#ifdef ENOMEM +static int ENOMEMValue = ENOMEM; +#endif + +#ifdef ENOMSG +static int ENOMSGValue = ENOMSG; +#endif + +#ifdef ENOPROTOOPT +static int ENOPROTOOPTValue = ENOPROTOOPT; +#endif + +#ifdef ENOSPC +static int ENOSPCValue = ENOSPC; +#endif + +#ifdef ENOSR +static int ENOSRValue = ENOSR; +#endif + +#ifdef ENOSTR +static int ENOSTRValue = ENOSTR; +#endif + +#ifdef ENOSYS +static int ENOSYSValue = ENOSYS; +#endif + +#ifdef ENOTCONN +static int ENOTCONNValue = ENOTCONN; +#endif + +#ifdef ENOTDIR +static int ENOTDIRValue = ENOTDIR; +#endif + +#ifdef ENOTEMPTY +static int ENOTEMPTYValue = ENOTEMPTY; +#endif + +#ifdef ENOTRECOVERABLE +static int ENOTRECOVERABLEValue = ENOTRECOVERABLE; +#endif + +#ifdef ENOTSOCK +static int ENOTSOCKValue = ENOTSOCK; +#endif + +#ifdef ENOTSUP +static int ENOTSUPValue = ENOTSUP; +#endif + +#ifdef ENOTTY +static int ENOTTYValue = ENOTTY; +#endif + +#ifdef ENXIO +static int ENXIOValue = ENXIO; +#endif + +#ifdef EOPNOTSUPP +static int EOPNOTSUPPValue = EOPNOTSUPP; +#endif + +#ifdef EOVERFLOW +static int EOVERFLOWValue = EOVERFLOW; +#endif + +#ifdef EOWNERDEAD +static int EOWNERDEADValue = EOWNERDEAD; +#endif + +#ifdef EPERM +static int EPERMValue = EPERM; +#endif + +#ifdef EPIPE +static int EPIPEValue = EPIPE; +#endif + +#ifdef EPROTO +static int EPROTOValue = EPROTO; +#endif + +#ifdef EPROTONOSUPPORT +static int EPROTONOSUPPORTValue = EPROTONOSUPPORT; +#endif + +#ifdef EPROTOTYPE +static int EPROTOTYPEValue = EPROTOTYPE; +#endif + +#ifdef ERANGE +static int ERANGEValue = ERANGE; +#endif + +#ifdef EROFS +static int EROFSValue = EROFS; +#endif + +#ifdef ESPIPE +static int ESPIPEValue = ESPIPE; +#endif + +#ifdef ESRCH +static int ESRCHValue = ESRCH; +#endif + +#ifdef ESTALE +static int ESTALEValue = ESTALE; +#endif + +#ifdef ETIME +static int ETIMEValue = ETIME; +#endif + +#ifdef ETIMEDOUT +static int ETIMEDOUTValue = ETIMEDOUT; +#endif + +#ifdef ETXTBSY +static int ETXTBSYValue = ETXTBSY; +#endif + +#ifdef EWOULDBLOCK +static int EWOULDBLOCKValue = EWOULDBLOCK; +#endif + +#ifdef EXDEV +static int EXDEVValue = EXDEV; +#endif + + +/* creates various system-dependent definitions */ +void StdErrnoSetupFunc(void) { + /* defines */ + #ifdef EACCES + VariableDefinePlatformVar(NULL, "EACCES", &IntType, (union AnyValue *)&EACCESValue, FALSE); + #endif + #ifdef EADDRINUSE + VariableDefinePlatformVar(NULL, "EADDRINUSE", &IntType, (union AnyValue *)&EADDRINUSEValue, FALSE); + #endif + #ifdef EADDRNOTAVAIL + VariableDefinePlatformVar(NULL, "EADDRNOTAVAIL", &IntType, (union AnyValue *)&EADDRNOTAVAILValue, FALSE); + #endif + #ifdef EAFNOSUPPORT + VariableDefinePlatformVar(NULL, "EAFNOSUPPORT", &IntType, (union AnyValue *)&EAFNOSUPPORTValue, FALSE); + #endif + #ifdef EAGAIN + VariableDefinePlatformVar(NULL, "EAGAIN", &IntType, (union AnyValue *)&EAGAINValue, FALSE); + #endif + #ifdef EALREADY + VariableDefinePlatformVar(NULL, "EALREADY", &IntType, (union AnyValue *)&EALREADYValue, FALSE); + #endif + #ifdef EBADF + VariableDefinePlatformVar(NULL, "EBADF", &IntType, (union AnyValue *)&EBADFValue, FALSE); + #endif + #ifdef EBADMSG + VariableDefinePlatformVar(NULL, "EBADMSG", &IntType, (union AnyValue *)&EBADMSGValue, FALSE); + #endif + #ifdef EBUSY + VariableDefinePlatformVar(NULL, "EBUSY", &IntType, (union AnyValue *)&EBUSYValue, FALSE); + #endif + #ifdef ECANCELED + VariableDefinePlatformVar(NULL, "ECANCELED", &IntType, (union AnyValue *)&ECANCELEDValue, FALSE); + #endif + #ifdef ECHILD + VariableDefinePlatformVar(NULL, "ECHILD", &IntType, (union AnyValue *)&ECHILDValue, FALSE); + #endif + #ifdef ECONNABORTED + VariableDefinePlatformVar(NULL, "ECONNABORTED", &IntType, (union AnyValue *)&ECONNABORTEDValue, FALSE); + #endif + #ifdef ECONNREFUSED + VariableDefinePlatformVar(NULL, "ECONNREFUSED", &IntType, (union AnyValue *)&ECONNREFUSEDValue, FALSE); + #endif + #ifdef ECONNRESET + VariableDefinePlatformVar(NULL, "ECONNRESET", &IntType, (union AnyValue *)&ECONNRESETValue, FALSE); + #endif + #ifdef EDEADLK + VariableDefinePlatformVar(NULL, "EDEADLK", &IntType, (union AnyValue *)&EDEADLKValue, FALSE); + #endif + #ifdef EDESTADDRREQ + VariableDefinePlatformVar(NULL, "EDESTADDRREQ", &IntType, (union AnyValue *)&EDESTADDRREQValue, FALSE); + #endif + #ifdef EDOM + VariableDefinePlatformVar(NULL, "EDOM", &IntType, (union AnyValue *)&EDOMValue, FALSE); + #endif + #ifdef EDQUOT + VariableDefinePlatformVar(NULL, "EDQUOT", &IntType, (union AnyValue *)&EDQUOTValue, FALSE); + #endif + #ifdef EEXIST + VariableDefinePlatformVar(NULL, "EEXIST", &IntType, (union AnyValue *)&EEXISTValue, FALSE); + #endif + #ifdef EFAULT + VariableDefinePlatformVar(NULL, "EFAULT", &IntType, (union AnyValue *)&EFAULTValue, FALSE); + #endif + #ifdef EFBIG + VariableDefinePlatformVar(NULL, "EFBIG", &IntType, (union AnyValue *)&EFBIGValue, FALSE); + #endif + #ifdef EHOSTUNREACH + VariableDefinePlatformVar(NULL, "EHOSTUNREACH", &IntType, (union AnyValue *)&EHOSTUNREACHValue, FALSE); + #endif + #ifdef EIDRM + VariableDefinePlatformVar(NULL, "EIDRM", &IntType, (union AnyValue *)&EIDRMValue, FALSE); + #endif + #ifdef EILSEQ + VariableDefinePlatformVar(NULL, "EILSEQ", &IntType, (union AnyValue *)&EILSEQValue, FALSE); + #endif + #ifdef EINPROGRESS + VariableDefinePlatformVar(NULL, "EINPROGRESS", &IntType, (union AnyValue *)&EINPROGRESSValue, FALSE); + #endif + #ifdef EINTR + VariableDefinePlatformVar(NULL, "EINTR", &IntType, (union AnyValue *)&EINTRValue, FALSE); + #endif + #ifdef EINVAL + VariableDefinePlatformVar(NULL, "EINVAL", &IntType, (union AnyValue *)&EINVALValue, FALSE); + #endif + #ifdef EIO + VariableDefinePlatformVar(NULL, "EIO", &IntType, (union AnyValue *)&EIOValue, FALSE); + #endif + #ifdef EISCONN + VariableDefinePlatformVar(NULL, "EISCONN", &IntType, (union AnyValue *)&EISCONNValue, FALSE); + #endif + #ifdef EISDIR + VariableDefinePlatformVar(NULL, "EISDIR", &IntType, (union AnyValue *)&EISDIRValue, FALSE); + #endif + #ifdef ELOOP + VariableDefinePlatformVar(NULL, "ELOOP", &IntType, (union AnyValue *)&ELOOPValue, FALSE); + #endif + #ifdef EMFILE + VariableDefinePlatformVar(NULL, "EMFILE", &IntType, (union AnyValue *)&EMFILEValue, FALSE); + #endif + #ifdef EMLINK + VariableDefinePlatformVar(NULL, "EMLINK", &IntType, (union AnyValue *)&EMLINKValue, FALSE); + #endif + #ifdef EMSGSIZE + VariableDefinePlatformVar(NULL, "EMSGSIZE", &IntType, (union AnyValue *)&EMSGSIZEValue, FALSE); + #endif + #ifdef EMULTIHOP + VariableDefinePlatformVar(NULL, "EMULTIHOP", &IntType, (union AnyValue *)&EMULTIHOPValue, FALSE); + #endif + #ifdef ENAMETOOLONG + VariableDefinePlatformVar(NULL, "ENAMETOOLONG", &IntType, (union AnyValue *)&ENAMETOOLONGValue, FALSE); + #endif + #ifdef ENETDOWN + VariableDefinePlatformVar(NULL, "ENETDOWN", &IntType, (union AnyValue *)&ENETDOWNValue, FALSE); + #endif + #ifdef ENETRESET + VariableDefinePlatformVar(NULL, "ENETRESET", &IntType, (union AnyValue *)&ENETRESETValue, FALSE); + #endif + #ifdef ENETUNREACH + VariableDefinePlatformVar(NULL, "ENETUNREACH", &IntType, (union AnyValue *)&ENETUNREACHValue, FALSE); + #endif + #ifdef ENFILE + VariableDefinePlatformVar(NULL, "ENFILE", &IntType, (union AnyValue *)&ENFILEValue, FALSE); + #endif + #ifdef ENOBUFS + VariableDefinePlatformVar(NULL, "ENOBUFS", &IntType, (union AnyValue *)&ENOBUFSValue, FALSE); + #endif + #ifdef ENODATA + VariableDefinePlatformVar(NULL, "ENODATA", &IntType, (union AnyValue *)&ENODATAValue, FALSE); + #endif + #ifdef ENODEV + VariableDefinePlatformVar(NULL, "ENODEV", &IntType, (union AnyValue *)&ENODEVValue, FALSE); + #endif + #ifdef ENOENT + VariableDefinePlatformVar(NULL, "ENOENT", &IntType, (union AnyValue *)&ENOENTValue, FALSE); + #endif + #ifdef ENOEXEC + VariableDefinePlatformVar(NULL, "ENOEXEC", &IntType, (union AnyValue *)&ENOEXECValue, FALSE); + #endif + #ifdef ENOLCK + VariableDefinePlatformVar(NULL, "ENOLCK", &IntType, (union AnyValue *)&ENOLCKValue, FALSE); + #endif + #ifdef ENOLINK + VariableDefinePlatformVar(NULL, "ENOLINK", &IntType, (union AnyValue *)&ENOLINKValue, FALSE); + #endif + #ifdef ENOMEM + VariableDefinePlatformVar(NULL, "ENOMEM", &IntType, (union AnyValue *)&ENOMEMValue, FALSE); + #endif + #ifdef ENOMSG + VariableDefinePlatformVar(NULL, "ENOMSG", &IntType, (union AnyValue *)&ENOMSGValue, FALSE); + #endif + #ifdef ENOPROTOOPT + VariableDefinePlatformVar(NULL, "ENOPROTOOPT", &IntType, (union AnyValue *)&ENOPROTOOPTValue, FALSE); + #endif + #ifdef ENOSPC + VariableDefinePlatformVar(NULL, "ENOSPC", &IntType, (union AnyValue *)&ENOSPCValue, FALSE); + #endif + #ifdef ENOSR + VariableDefinePlatformVar(NULL, "ENOSR", &IntType, (union AnyValue *)&ENOSRValue, FALSE); + #endif + #ifdef ENOSTR + VariableDefinePlatformVar(NULL, "ENOSTR", &IntType, (union AnyValue *)&ENOSTRValue, FALSE); + #endif + #ifdef ENOSYS + VariableDefinePlatformVar(NULL, "ENOSYS", &IntType, (union AnyValue *)&ENOSYSValue, FALSE); + #endif + #ifdef ENOTCONN + VariableDefinePlatformVar(NULL, "ENOTCONN", &IntType, (union AnyValue *)&ENOTCONNValue, FALSE); + #endif + #ifdef ENOTDIR + VariableDefinePlatformVar(NULL, "ENOTDIR", &IntType, (union AnyValue *)&ENOTDIRValue, FALSE); + #endif + #ifdef ENOTEMPTY + VariableDefinePlatformVar(NULL, "ENOTEMPTY", &IntType, (union AnyValue *)&ENOTEMPTYValue, FALSE); + #endif + #ifdef ENOTRECOVERABLE + VariableDefinePlatformVar(NULL, "ENOTRECOVERABLE", &IntType, (union AnyValue *)&ENOTRECOVERABLEValue, FALSE); + #endif + #ifdef ENOTSOCK + VariableDefinePlatformVar(NULL, "ENOTSOCK", &IntType, (union AnyValue *)&ENOTSOCKValue, FALSE); + #endif + #ifdef ENOTSUP + VariableDefinePlatformVar(NULL, "ENOTSUP", &IntType, (union AnyValue *)&ENOTSUPValue, FALSE); + #endif + #ifdef ENOTTY + VariableDefinePlatformVar(NULL, "ENOTTY", &IntType, (union AnyValue *)&ENOTTYValue, FALSE); + #endif + #ifdef ENXIO + VariableDefinePlatformVar(NULL, "ENXIO", &IntType, (union AnyValue *)&ENXIOValue, FALSE); + #endif + #ifdef EOPNOTSUPP + VariableDefinePlatformVar(NULL, "EOPNOTSUPP", &IntType, (union AnyValue *)&EOPNOTSUPPValue, FALSE); + #endif + #ifdef EOVERFLOW + VariableDefinePlatformVar(NULL, "EOVERFLOW", &IntType, (union AnyValue *)&EOVERFLOWValue, FALSE); + #endif + #ifdef EOWNERDEAD + VariableDefinePlatformVar(NULL, "EOWNERDEAD", &IntType, (union AnyValue *)&EOWNERDEADValue, FALSE); + #endif + #ifdef EPERM + VariableDefinePlatformVar(NULL, "EPERM", &IntType, (union AnyValue *)&EPERMValue, FALSE); + #endif + #ifdef EPIPE + VariableDefinePlatformVar(NULL, "EPIPE", &IntType, (union AnyValue *)&EPIPEValue, FALSE); + #endif + #ifdef EPROTO + VariableDefinePlatformVar(NULL, "EPROTO", &IntType, (union AnyValue *)&EPROTOValue, FALSE); + #endif + #ifdef EPROTONOSUPPORT + VariableDefinePlatformVar(NULL, "EPROTONOSUPPORT", &IntType, (union AnyValue *)&EPROTONOSUPPORTValue, FALSE); + #endif + #ifdef EPROTOTYPE + VariableDefinePlatformVar(NULL, "EPROTOTYPE", &IntType, (union AnyValue *)&EPROTOTYPEValue, FALSE); + #endif + #ifdef ERANGE + VariableDefinePlatformVar(NULL, "ERANGE", &IntType, (union AnyValue *)&ERANGEValue, FALSE); + #endif + #ifdef EROFS + VariableDefinePlatformVar(NULL, "EROFS", &IntType, (union AnyValue *)&EROFSValue, FALSE); + #endif + #ifdef ESPIPE + VariableDefinePlatformVar(NULL, "ESPIPE", &IntType, (union AnyValue *)&ESPIPEValue, FALSE); + #endif + #ifdef ESRCH + VariableDefinePlatformVar(NULL, "ESRCH", &IntType, (union AnyValue *)&ESRCHValue, FALSE); + #endif + #ifdef ESTALE + VariableDefinePlatformVar(NULL, "ESTALE", &IntType, (union AnyValue *)&ESTALEValue, FALSE); + #endif + #ifdef ETIME + VariableDefinePlatformVar(NULL, "ETIME", &IntType, (union AnyValue *)&ETIMEValue, FALSE); + #endif + #ifdef ETIMEDOUT + VariableDefinePlatformVar(NULL, "ETIMEDOUT", &IntType, (union AnyValue *)&ETIMEDOUTValue, FALSE); + #endif + #ifdef ETXTBSY + VariableDefinePlatformVar(NULL, "ETXTBSY", &IntType, (union AnyValue *)&ETXTBSYValue, FALSE); + #endif + #ifdef EWOULDBLOCK + VariableDefinePlatformVar(NULL, "EWOULDBLOCK", &IntType, (union AnyValue *)&EWOULDBLOCKValue, FALSE); + #endif + #ifdef EXDEV + VariableDefinePlatformVar(NULL, "EXDEV", &IntType, (union AnyValue *)&EXDEVValue, FALSE); + #endif + VariableDefinePlatformVar(NULL, "errno", &IntType, (union AnyValue *)&errno, TRUE); +} + +#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/math.c b/eci/cstdlib/math.c new file mode 100644 index 0000000..8f630cc --- /dev/null +++ b/eci/cstdlib/math.c @@ -0,0 +1,162 @@ +/* stdio.h library for large systems - small embedded systems use clibrary.c instead */ +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB +#ifndef NO_FP + +static double M_EValue = 2.7182818284590452354; /* e */ +static double M_LOG2EValue = 1.4426950408889634074; /* log_2 e */ +static double M_LOG10EValue = 0.43429448190325182765; /* log_10 e */ +static double M_LN2Value = 0.69314718055994530942; /* log_e 2 */ +static double M_LN10Value = 2.30258509299404568402; /* log_e 10 */ +static double M_PIValue = 3.14159265358979323846; /* pi */ +static double M_PI_2Value = 1.57079632679489661923; /* pi/2 */ +static double M_PI_4Value = 0.78539816339744830962; /* pi/4 */ +static double M_1_PIValue = 0.31830988618379067154; /* 1/pi */ +static double M_2_PIValue = 0.63661977236758134308; /* 2/pi */ +static double M_2_SQRTPIValue = 1.12837916709551257390; /* 2/sqrt(pi) */ +static double M_SQRT2Value = 1.41421356237309504880; /* sqrt(2) */ +static double M_SQRT1_2Value = 0.70710678118654752440; /* 1/sqrt(2) */ + + +void MathSin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sin(Param[0]->Val->FP); +} + +void MathCos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs){ + ReturnValue->Val->FP = cos(Param[0]->Val->FP); +} + +void MathTan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = tan(Param[0]->Val->FP); +} + +void MathAsin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = asin(Param[0]->Val->FP); +} + +void MathAcos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = acos(Param[0]->Val->FP); +} + +void MathAtan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = atan(Param[0]->Val->FP); +} + +void MathAtan2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = atan2(Param[0]->Val->FP, Param[1]->Val->FP); +} + +void MathSinh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sinh(Param[0]->Val->FP); +} + +void MathCosh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = cosh(Param[0]->Val->FP); +} + +void MathTanh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = tanh(Param[0]->Val->FP); +} + +void MathExp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = exp(Param[0]->Val->FP); +} + +void MathFabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = fabs(Param[0]->Val->FP); +} + +void MathFmod(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = fmod(Param[0]->Val->FP, Param[1]->Val->FP); +} + +void MathFrexp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = frexp(Param[0]->Val->FP, Param[1]->Val->Pointer); +} + +void MathLdexp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = ldexp(Param[0]->Val->FP, Param[1]->Val->Integer); +} + +void MathLog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = log(Param[0]->Val->FP); +} + +void MathLog10(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = log10(Param[0]->Val->FP); +} + +void MathModf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = modf(Param[0]->Val->FP, Param[0]->Val->Pointer); +} + +void MathPow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = pow(Param[0]->Val->FP, Param[1]->Val->FP); +} + +void MathSqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = sqrt(Param[0]->Val->FP); +} + +void MathRound(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + /* this awkward definition of "round()" due to it being inconsistently + * declared in math.h */ + ReturnValue->Val->FP = ceil(Param[0]->Val->FP - 0.5); +} + +void MathCeil(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = ceil(Param[0]->Val->FP); +} + +void MathFloor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = floor(Param[0]->Val->FP); +} + +/* all math.h functions */ +struct LibraryFunction MathFunctions[] = { + { MathAcos, "float acos(float);" }, + { MathAsin, "float asin(float);" }, + { MathAtan, "float atan(float);" }, + { MathAtan2, "float atan2(float, float);" }, + { MathCeil, "float ceil(float);" }, + { MathCos, "float cos(float);" }, + { MathCosh, "float cosh(float);" }, + { MathExp, "float exp(float);" }, + { MathFabs, "float fabs(float);" }, + { MathFloor, "float floor(float);" }, + { MathFmod, "float fmod(float, float);" }, + { MathFrexp, "float frexp(float, int *);" }, + { MathLdexp, "float ldexp(float, int);" }, + { MathLog, "float log(float);" }, + { MathLog10, "float log10(float);" }, + { MathModf, "float modf(float, float *);" }, + { MathPow, "float pow(float,float);" }, + { MathRound, "float round(float);" }, + { MathSin, "float sin(float);" }, + { MathSinh, "float sinh(float);" }, + { MathSqrt, "float sqrt(float);" }, + { MathTan, "float tan(float);" }, + { MathTanh, "float tanh(float);" }, + { NULL, NULL } +}; + +/* creates various system-dependent definitions */ +void MathSetupFunc() { + VariableDefinePlatformVar(NULL, "M_E", &FPType, (union AnyValue *)&M_EValue, FALSE); + VariableDefinePlatformVar(NULL, "M_LOG2E", &FPType, (union AnyValue *)&M_LOG2EValue, FALSE); + VariableDefinePlatformVar(NULL, "M_LOG10E", &FPType, (union AnyValue *)&M_LOG10EValue, FALSE); + VariableDefinePlatformVar(NULL, "M_LN2", &FPType, (union AnyValue *)&M_LN2Value, FALSE); + VariableDefinePlatformVar(NULL, "M_LN10", &FPType, (union AnyValue *)&M_LN10Value, FALSE); + VariableDefinePlatformVar(NULL, "M_PI", &FPType, (union AnyValue *)&M_PIValue, FALSE); + VariableDefinePlatformVar(NULL, "M_PI_2", &FPType, (union AnyValue *)&M_PI_2Value, FALSE); + VariableDefinePlatformVar(NULL, "M_PI_4", &FPType, (union AnyValue *)&M_PI_4Value, FALSE); + VariableDefinePlatformVar(NULL, "M_1_PI", &FPType, (union AnyValue *)&M_1_PIValue, FALSE); + VariableDefinePlatformVar(NULL, "M_2_PI", &FPType, (union AnyValue *)&M_2_PIValue, FALSE); + VariableDefinePlatformVar(NULL, "M_2_SQRTPI", &FPType, (union AnyValue *)&M_2_SQRTPIValue, FALSE); + VariableDefinePlatformVar(NULL, "M_SQRT2", &FPType, (union AnyValue *)&M_SQRT2Value, FALSE); + VariableDefinePlatformVar(NULL, "M_SQRT1_2", &FPType, (union AnyValue *)&M_SQRT1_2Value, FALSE); +} + +#endif /* !NO_FP */ +#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/stdbool.c b/eci/cstdlib/stdbool.c new file mode 100644 index 0000000..50957ac --- /dev/null +++ b/eci/cstdlib/stdbool.c @@ -0,0 +1,21 @@ +/* string.h library for large systems - small embedded systems use clibrary.c instead */ +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +static int trueValue = 1; +static int falseValue = 0; + + +/* structure definitions */ +const char StdboolDefs[] = "typedef int bool;"; + +/* creates various system-dependent definitions */ +void StdboolSetupFunc() { + /* defines */ + VariableDefinePlatformVar(NULL, "true", &IntType, (union AnyValue *)&trueValue, FALSE); + VariableDefinePlatformVar(NULL, "false", &IntType, (union AnyValue *)&falseValue, FALSE); + VariableDefinePlatformVar(NULL, "__bool_true_false_are_defined", &IntType, (union AnyValue *)&trueValue, FALSE); +} + +#endif diff --git a/eci/cstdlib/stdio.c b/eci/cstdlib/stdio.c new file mode 100644 index 0000000..164e467 --- /dev/null +++ b/eci/cstdlib/stdio.c @@ -0,0 +1,657 @@ +/* stdio.h library for large systems - small embedded systems use clibrary.c instead */ +#include +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +#define MAX_FORMAT 80 +#define MAX_SCANF_ARGS 10 + +FILE *CStdOut; + +static int ZeroValue = 0; +static int EOFValue = EOF; +static int SEEK_SETValue = SEEK_SET; +static int SEEK_CURValue = SEEK_CUR; +static int SEEK_ENDValue = SEEK_END; +static int BUFSIZValue = BUFSIZ; +static int FILENAME_MAXValue = FILENAME_MAX; +static int _IOFBFValue = _IOFBF; +static int _IOLBFValue = _IOLBF; +static int _IONBFValue = _IONBF; +static int L_tmpnamValue = L_tmpnam; +static int GETS_MAXValue = 255; /* arbitrary maximum size of a gets() file */ + +static FILE *stdinValue; +static FILE *stdoutValue; +static FILE *stderrValue; + +struct ValueType *FilePtrType = NULL; + + +/* our own internal output stream which can output to FILE * or strings */ +typedef struct StdOutStreamStruct { + FILE *FilePtr; + char *StrOutPtr; + int StrOutLen; + int CharCount; +} StdOutStream; + +/* our representation of varargs within picoc */ +struct StdVararg { + struct Value **Param; + int NumArgs; +}; + +/* initialises the I/O system so error reporting works */ +void BasicIOInit() { + CStdOut = stdout; + stdinValue = stdin; + stdoutValue = stdout; + stderrValue = stderr; +} + +/* output a single character to either a FILE * or a string */ +void StdioOutPutc(int OutCh, StdOutStream *Stream) { + if (Stream->FilePtr != NULL) { + /* output to stdio stream */ + putc(OutCh, Stream->FilePtr); + Stream->CharCount++; + } else if ( Stream->StrOutLen < 0 + || Stream->StrOutLen > 1) { + /* output to a string */ + *Stream->StrOutPtr = OutCh; + Stream->StrOutPtr++; + if (Stream->StrOutLen > 1) { + Stream->StrOutLen--; + } + Stream->CharCount++; + } +} + +/* output a string to either a FILE * or a string */ +void StdioOutPuts(const char *Str, StdOutStream *Stream) { + if (Stream->FilePtr != NULL) { + /* output to stdio stream */ + fputs(Str, Stream->FilePtr); + } else { + /* output to a string */ + while (*Str != '\0') { + if ( Stream->StrOutLen < 0 + || Stream->StrOutLen > 1) { + /* output to a string */ + *Stream->StrOutPtr = *Str; + Str++; + Stream->StrOutPtr++; + if (Stream->StrOutLen > 1) { + Stream->StrOutLen--; + } + Stream->CharCount++; + } + } + } +} + +/* printf-style format of an int or other word-sized object */ +void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned int Value) { + if (Stream->FilePtr != NULL) { + Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); + } else if (Stream->StrOutLen >= 0) { + int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); + Stream->StrOutPtr += CCount; + Stream->StrOutLen -= CCount; + Stream->CharCount += CCount; + } else { + int CCount = sprintf(Stream->StrOutPtr, Format, Value); + Stream->CharCount += CCount; + Stream->StrOutPtr += CCount; + } +} + +/* printf-style format of a floating point number */ +void StdioFprintfFP(StdOutStream *Stream, const char *Format, double Value) { + if (Stream->FilePtr != NULL) { + Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); + } else if (Stream->StrOutLen >= 0) { + int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); + Stream->StrOutPtr += CCount; + Stream->StrOutLen -= CCount; + Stream->CharCount += CCount; + } else { + int CCount = sprintf(Stream->StrOutPtr, Format, Value); + Stream->CharCount += CCount; + Stream->StrOutPtr += CCount; + } +} + +/* printf-style format of a pointer */ +void StdioFprintfPointer(StdOutStream *Stream, const char *Format, void *Value) { + if (Stream->FilePtr != NULL) { + Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); + } else if (Stream->StrOutLen >= 0) { + int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); + Stream->StrOutPtr += CCount; + Stream->StrOutLen -= CCount; + Stream->CharCount += CCount; + } else { + int CCount = sprintf(Stream->StrOutPtr, Format, Value); + Stream->CharCount += CCount; + Stream->StrOutPtr += CCount; + } +} + +/* internal do-anything v[s][n]printf() formatting system with output to strings or FILE * */ +int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int StrOutLen, char *Format, struct StdVararg *Args) { + struct Value *ThisArg = Args->Param[0]; + int ArgCount = 0; + char *FPos = Format; + char OneFormatBuf[MAX_FORMAT+1]; + int OneFormatCount; + struct ValueType *ShowType; + StdOutStream SOStream; + SOStream.FilePtr = Stream; + SOStream.StrOutPtr = StrOut; + SOStream.StrOutLen = StrOutLen; + SOStream.CharCount = 0; + while (*FPos != '\0') { + if (*FPos == '%') { + /* work out what type we're printing */ + FPos++; + ShowType = NULL; + OneFormatBuf[0] = '%'; + OneFormatCount = 1; + do { + switch (*FPos) { + case 'd': + case 'i': + ShowType = &IntType; + break; + /* integer decimal */ + case 'o': + case 'u': + case 'x': + case 'X': + ShowType = &IntType; + break; + /* integer base conversions */ +#ifndef NO_FP + case 'e': + case 'E': + ShowType = &FPType; + break; + /* double, exponent form */ + case 'f': + case 'F': + ShowType = &FPType; + break; + /* double, fixed-point */ + case 'g': + case 'G': + ShowType = &FPType; + break; + /* double, flexible format */ +#endif + case 'a': + case 'A': + ShowType = &IntType; + break; + /* hexadecimal, 0x- format */ + case 'c': + ShowType = &IntType; + break; + /* character */ + case 's': + ShowType = CharPtrType; + break; + /* string */ + case 'p': + ShowType = VoidPtrType; + break; + /* pointer */ + case 'n': + ShowType = &VoidType; + break; + /* number of characters written */ + case 'm': + ShowType = &VoidType; + break; + /* strerror(errno) */ + case '%': + ShowType = &VoidType; + break; + /* just a '%' character */ + case '\0': + ShowType = &VoidType; + break; + /* end of format string */ + } + /* copy one character of format across to the OneFormatBuf */ + OneFormatBuf[OneFormatCount] = *FPos; + OneFormatCount++; + /* do special actions depending on the conversion type */ + if (ShowType == &VoidType) { + switch (*FPos) { + case 'm': + StdioOutPuts(strerror(errno), &SOStream); + break; + case '%': + StdioOutPutc(*FPos, &SOStream); + break; + case '\0': + OneFormatBuf[OneFormatCount] = '\0'; + StdioOutPutc(*FPos, &SOStream); + break; + case 'n': + ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); + if ( ThisArg->Typ->Base == TypeArray + && ThisArg->Typ->FromType->Base == TypeInt) { + *(int *)ThisArg->Val->Pointer = SOStream.CharCount; + } + break; + } + } + FPos++; + } while ( ShowType == NULL + && OneFormatCount < MAX_FORMAT); + if (ShowType != &VoidType) { + if (ArgCount >= Args->NumArgs) { + StdioOutPuts("XXX", &SOStream); + } else { + /* null-terminate the buffer */ + OneFormatBuf[OneFormatCount] = '\0'; + /* print this argument */ + ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); + if (ShowType == &IntType) { + /* show a signed integer */ + if (IS_NUMERIC_COERCIBLE(ThisArg)) { + StdioFprintfWord(&SOStream, OneFormatBuf, ExpressionCoerceUnsignedInteger(ThisArg)); + } else { + StdioOutPuts("XXX", &SOStream); + } + } +#ifndef NO_FP + else if (ShowType == &FPType) { + /* show a floating point number */ + if (IS_NUMERIC_COERCIBLE(ThisArg)) { + StdioFprintfFP(&SOStream, OneFormatBuf, ExpressionCoerceFP(ThisArg)); + } else { + StdioOutPuts("XXX", &SOStream); + } + } +#endif + else if (ShowType == CharPtrType) { + if (ThisArg->Typ->Base == TypePointer) { + StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); + } else if ( ThisArg->Typ->Base == TypeArray + && ThisArg->Typ->FromType->Base == TypeChar) { + StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); + } else { + StdioOutPuts("XXX", &SOStream); + } + } else if (ShowType == VoidPtrType) { + if (ThisArg->Typ->Base == TypePointer) { + StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); + } else if (ThisArg->Typ->Base == TypeArray) { + StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); + } else { + StdioOutPuts("XXX", &SOStream); + } + } + ArgCount++; + } + } + } else { + /* just output a normal character */ + StdioOutPutc(*FPos, &SOStream); + FPos++; + } + } + /* null-terminate */ + if ( SOStream.StrOutPtr != NULL + && SOStream.StrOutLen > 0) { + *SOStream.StrOutPtr = '\0'; + } + return SOStream.CharCount; +} + +/* internal do-anything v[s][n]scanf() formatting system with input from strings or FILE * */ +int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn, char *Format, struct StdVararg *Args) { + struct Value *ThisArg = Args->Param[0]; + int ArgCount = 0; + void *ScanfArg[MAX_SCANF_ARGS]; + if (Args->NumArgs > MAX_SCANF_ARGS) { + ProgramFail(Parser, "too many arguments to scanf() - %d max", MAX_SCANF_ARGS); + } + for (ArgCount = 0; ArgCount < Args->NumArgs; ++ArgCount) { + ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); + if (ThisArg->Typ->Base == TypePointer) { + ScanfArg[ArgCount] = ThisArg->Val->Pointer; + } else if (ThisArg->Typ->Base == TypeArray) { + ScanfArg[ArgCount] = &ThisArg->Val->ArrayMem[0]; + } else { + ProgramFail(Parser, "non-pointer argument to scanf() - argument %d after format", ArgCount+1); + } + } + if (Stream != NULL) { + return fscanf(Stream, Format, ScanfArg[0], ScanfArg[1], ScanfArg[2], ScanfArg[3], ScanfArg[4], ScanfArg[5], ScanfArg[6], ScanfArg[7], ScanfArg[8], ScanfArg[9]); + } else { + return sscanf(StrIn, Format, ScanfArg[0], ScanfArg[1], ScanfArg[2], ScanfArg[3], ScanfArg[4], ScanfArg[5], ScanfArg[6], ScanfArg[7], ScanfArg[8], ScanfArg[9]); + } +} + +/* stdio calls */ +void StdioFopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = fopen(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioFreopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = freopen(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +void StdioFclose(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fclose(Param[0]->Val->Pointer); +} + +void StdioFread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fread(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->Pointer); +} + +void StdioFwrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fwrite(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->Pointer); +} + +void StdioFgetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fgetc(Param[0]->Val->Pointer); +} + +void StdioFgets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = fgets(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer); +} + +void StdioRemove(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = remove(Param[0]->Val->Pointer); +} + +void StdioRename(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = rename(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioRewind(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + rewind(Param[0]->Val->Pointer); +} + +void StdioTmpfile(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = tmpfile(); +} + +void StdioClearerr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + clearerr((FILE *)Param[0]->Val->Pointer); +} + +void StdioFeof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = feof((FILE *)Param[0]->Val->Pointer); +} + +void StdioFerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ferror((FILE *)Param[0]->Val->Pointer); +} + +void StdioFileno(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fileno(Param[0]->Val->Pointer); +} + +void StdioFflush(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fflush(Param[0]->Val->Pointer); +} + +void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer, Param[1]->Val->Pointer); +} + +void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ftell(Param[0]->Val->Pointer); +} + +void StdioFseek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fseek(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void StdioPerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + perror(Param[0]->Val->Pointer); +} + +void StdioPutc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = putc(Param[0]->Val->Integer, Param[1]->Val->Pointer); +} + +void StdioPutchar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = putchar(Param[0]->Val->Integer); +} + +void StdioSetbuf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + setbuf(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioSetvbuf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + setvbuf(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer); +} + +void StdioUngetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ungetc(Param[0]->Val->Integer, Param[1]->Val->Pointer); +} + +void StdioPuts(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = puts(Param[0]->Val->Pointer); +} + +void StdioGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = fgets(Param[0]->Val->Pointer, GETS_MAXValue, stdin); + if (ReturnValue->Val->Pointer != NULL) { + char *EOLPos = strchr(Param[0]->Val->Pointer, '\n'); + if (EOLPos != NULL) { + *EOLPos = '\0'; + } + } +} + +void StdioGetchar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getchar(); +} + +void StdioPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg PrintfArgs; + PrintfArgs.Param = Param; + PrintfArgs.NumArgs = NumArgs-1; + ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, NULL, 0, Param[0]->Val->Pointer, &PrintfArgs); +} + +void StdioVprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, NULL, 0, Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioFprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg PrintfArgs; + PrintfArgs.Param = Param + 1; + PrintfArgs.NumArgs = NumArgs-2; + ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->Pointer, NULL, 0, Param[1]->Val->Pointer, &PrintfArgs); +} + +void StdioVfprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->Pointer, NULL, 0, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +void StdioSprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg PrintfArgs; + PrintfArgs.Param = Param + 1; + PrintfArgs.NumArgs = NumArgs-2; + ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, &PrintfArgs); +} + +void StdioSnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg PrintfArgs; + PrintfArgs.Param = Param+2; + PrintfArgs.NumArgs = NumArgs-3; + ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, &PrintfArgs); +} + +void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg ScanfArgs; + ScanfArgs.Param = Param; + ScanfArgs.NumArgs = NumArgs-1; + ReturnValue->Val->Integer = StdioBaseScanf(Parser, stdin, NULL, Param[0]->Val->Pointer, &ScanfArgs); +} + +void StdioFscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg ScanfArgs; + ScanfArgs.Param = Param+1; + ScanfArgs.NumArgs = NumArgs-2; + ReturnValue->Val->Integer = StdioBaseScanf(Parser, Param[0]->Val->Pointer, NULL, Param[1]->Val->Pointer, &ScanfArgs); +} + +void StdioSscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + struct StdVararg ScanfArgs; + ScanfArgs.Param = Param+1; + ScanfArgs.NumArgs = NumArgs-2; + ReturnValue->Val->Integer = StdioBaseScanf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer, &ScanfArgs); +} + +void StdioVsprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer); +} + +void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBaseScanf(Parser, stdin, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdioVfscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBaseScanf(Parser, Param[0]->Val->Pointer, NULL, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +void StdioVsscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = StdioBaseScanf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +/* handy structure definitions */ +const char StdioDefs[] = "\ +typedef struct __va_listStruct va_list; \ +typedef struct __FILEStruct FILE;\ +"; + +/* all stdio functions */ +struct LibraryFunction StdioFunctions[] = { + { StdioFopen, "FILE *fopen(char *, char *);" }, + { StdioFreopen, "FILE *freopen(char *, char *, FILE *);" }, + { StdioFclose, "int fclose(FILE *);" }, + { StdioFread, "int fread(void *, int, int, FILE *);" }, + { StdioFwrite, "int fwrite(void *, int, int, FILE *);" }, + { StdioFgetc, "int fgetc(FILE *);" }, + { StdioFgetc, "int getc(FILE *);" }, + { StdioFgets, "char *fgets(char *, int, FILE *);" }, + { StdioFputc, "int fputc(int, FILE *);" }, + { StdioFputs, "int fputs(char *, FILE *);" }, + { StdioRemove, "int remove(char *);" }, + { StdioRename, "int rename(char *, char *);" }, + { StdioRewind, "void rewind(FILE *);" }, + { StdioTmpfile, "FILE *tmpfile();" }, + { StdioClearerr,"void clearerr(FILE *);" }, + { StdioFeof, "int feof(FILE *);" }, + { StdioFerror, "int ferror(FILE *);" }, + { StdioFileno, "int fileno(FILE *);" }, + { StdioFflush, "int fflush(FILE *);" }, + { StdioFgetpos, "int fgetpos(FILE *, int *);" }, + { StdioFsetpos, "int fsetpos(FILE *, int *);" }, + { StdioFtell, "int ftell(FILE *);" }, + { StdioFseek, "int fseek(FILE *, int, int);" }, + { StdioPerror, "void perror(char *);" }, + { StdioPutc, "int putc(char *, FILE *);" }, + { StdioPutchar, "int putchar(int);" }, + { StdioPutchar, "int fputchar(int);" }, + { StdioSetbuf, "void setbuf(FILE *, char *);" }, + { StdioSetvbuf, "void setvbuf(FILE *, char *, int, int);" }, + { StdioUngetc, "int ungetc(int, FILE *);" }, + { StdioPuts, "int puts(char *);" }, + { StdioGets, "char *gets(char *);" }, + { StdioGetchar, "int getchar();" }, + { StdioPrintf, "int printf(char *, ...);" }, + { StdioFprintf, "int fprintf(FILE *, char *, ...);" }, + { StdioSprintf, "int sprintf(char *, char *, ...);" }, + { StdioSnprintf,"int snprintf(char *, int, char *, ...);" }, + { StdioScanf, "int scanf(char *, ...);" }, + { StdioFscanf, "int fscanf(FILE *, char *, ...);" }, + { StdioSscanf, "int sscanf(char *, char *, ...);" }, + { StdioVprintf, "int vprintf(char *, va_list);" }, + { StdioVfprintf,"int vfprintf(FILE *, char *, va_list);" }, + { StdioVsprintf,"int vsprintf(char *, char *, va_list);" }, + { StdioVsnprintf,"int vsnprintf(char *, int, char *, va_list);" }, + { StdioVscanf, "int vscanf(char *, va_list);" }, + { StdioVfscanf, "int vfscanf(FILE *, char *, va_list);" }, + { StdioVsscanf, "int vsscanf(char *, char *, va_list);" }, + { NULL, NULL } +}; + +/* creates various system-dependent definitions */ +void StdioSetupFunc(void) { + struct ValueType *StructFileType; + struct ValueType *FilePtrType; + /* make a "struct __FILEStruct" which is the same size as a native FILE structure */ + StructFileType = TypeCreateOpaqueStruct(NULL, TableStrRegister("__FILEStruct"), sizeof(FILE)); + /* get a FILE * type */ + FilePtrType = TypeGetMatching(NULL, StructFileType, TypePointer, 0, StrEmpty, TRUE); + /* make a "struct __va_listStruct" which is the same size as our struct StdVararg */ + TypeCreateOpaqueStruct(NULL, TableStrRegister("__va_listStruct"), sizeof(FILE)); + /* define EOF equal to the system EOF */ + VariableDefinePlatformVar(NULL, "EOF", &IntType, (union AnyValue *)&EOFValue, FALSE); + VariableDefinePlatformVar(NULL, "SEEK_SET", &IntType, (union AnyValue *)&SEEK_SETValue, FALSE); + VariableDefinePlatformVar(NULL, "SEEK_CUR", &IntType, (union AnyValue *)&SEEK_CURValue, FALSE); + VariableDefinePlatformVar(NULL, "SEEK_END", &IntType, (union AnyValue *)&SEEK_ENDValue, FALSE); + VariableDefinePlatformVar(NULL, "BUFSIZ", &IntType, (union AnyValue *)&BUFSIZValue, FALSE); + VariableDefinePlatformVar(NULL, "FILENAME_MAX", &IntType, (union AnyValue *)&FILENAME_MAXValue, FALSE); + VariableDefinePlatformVar(NULL, "_IOFBF", &IntType, (union AnyValue *)&_IOFBFValue, FALSE); + VariableDefinePlatformVar(NULL, "_IOLBF", &IntType, (union AnyValue *)&_IOLBFValue, FALSE); + VariableDefinePlatformVar(NULL, "_IONBF", &IntType, (union AnyValue *)&_IONBFValue, FALSE); + VariableDefinePlatformVar(NULL, "L_tmpnam", &IntType, (union AnyValue *)&L_tmpnamValue, FALSE); + VariableDefinePlatformVar(NULL, "GETS_MAX", &IntType, (union AnyValue *)&GETS_MAXValue, FALSE); + /* define stdin, stdout and stderr */ + VariableDefinePlatformVar(NULL, "stdin", FilePtrType, (union AnyValue *)&stdinValue, FALSE); + VariableDefinePlatformVar(NULL, "stdout", FilePtrType, (union AnyValue *)&stdoutValue, FALSE); + VariableDefinePlatformVar(NULL, "stderr", FilePtrType, (union AnyValue *)&stderrValue, FALSE); + /* define NULL, TRUE and FALSE */ + if (!VariableDefined(TableStrRegister("NULL"))) { + VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); + } +} + +/* portability-related I/O calls */ +void PrintCh(char OutCh, FILE *Stream) { + putc(OutCh, Stream); +} + +void PrintSimpleInt(long Num, FILE *Stream) { + fprintf(Stream, "%ld", Num); +} + +void PrintStr(const char *Str, FILE *Stream) { + fputs(Str, Stream); +} + +void PrintFP(double Num, FILE *Stream) { + fprintf(Stream, "%f", Num); +} + +#endif diff --git a/eci/cstdlib/stdlib.c b/eci/cstdlib/stdlib.c new file mode 100644 index 0000000..06698bb --- /dev/null +++ b/eci/cstdlib/stdlib.c @@ -0,0 +1,118 @@ +/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */ +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +static int ZeroValue = 0; + +#ifndef NO_FP +void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = atof(Param[0]->Val->Pointer); +} +#endif + +void StdlibAtoi(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = atoi(Param[0]->Val->Pointer); +} + +void StdlibAtol(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = atol(Param[0]->Val->Pointer); +} + +#ifndef NO_FP +void StdlibStrtod(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = strtod(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} +#endif + +void StdlibStrtol(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strtol(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StdlibStrtoul(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strtoul(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StdlibMalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = malloc(Param[0]->Val->Integer); +} + +void StdlibCalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = calloc(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void StdlibRealloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = realloc(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void StdlibFree(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + free(Param[0]->Val->Pointer); +} + +void StdlibRand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = rand(); +} + +void StdlibSrand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + srand(Param[0]->Val->Integer); +} + +void StdlibAbort(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ProgramFail(Parser, "abort"); +} + +void StdlibExit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + PlatformExit(Param[0]->Val->Integer); +} + +void StdlibGetenv(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = getenv(Param[0]->Val->Pointer); +} + +void StdlibSystem(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = system(Param[0]->Val->Pointer); +} + +void StdlibAbs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = abs(Param[0]->Val->Integer); +} + +void StdlibLabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = labs(Param[0]->Val->Integer); +} + +/* all stdlib.h functions */ +struct LibraryFunction StdlibFunctions[] = +{ +#ifndef NO_FP + { StdlibAtof, "float atof(char *);" }, + { StdlibStrtod, "float strtod(char *,char **);" }, +#endif + { StdlibAtoi, "int atoi(char *);" }, + { StdlibAtol, "int atol(char *);" }, + { StdlibStrtol, "int strtol(char *,char **,int);" }, + { StdlibStrtoul, "int strtoul(char *,char **,int);" }, + { StdlibMalloc, "void *malloc(int);" }, + { StdlibCalloc, "void *calloc(int,int);" }, + { StdlibRealloc, "void *realloc(void *,int);" }, + { StdlibFree, "void free(void *);" }, + { StdlibRand, "int rand();" }, + { StdlibSrand, "void srand(int);" }, + { StdlibAbort, "void abort();" }, + { StdlibExit, "void exit(int);" }, + { StdlibGetenv, "char *getenv(char *);" }, + { StdlibSystem, "int system(char *);" }, + { StdlibAbs, "int abs(int);" }, + { StdlibLabs, "int labs(int);" }, + { NULL, NULL } +}; + +/* creates various system-dependent definitions */ +void StdlibSetupFunc() { + /* define NULL, TRUE and FALSE */ + if (!VariableDefined(TableStrRegister("NULL"))) { + VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); + } +} + +#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/string.c b/eci/cstdlib/string.c new file mode 100644 index 0000000..2382a58 --- /dev/null +++ b/eci/cstdlib/string.c @@ -0,0 +1,151 @@ +/* string.h library for large systems - small embedded systems use clibrary.c instead */ +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +static int ZeroValue = 0; + +void StringStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrncpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strncpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringStrcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strcmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrncmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strncmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringStrcat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strcat(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrncat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strncat(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringIndex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = index(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void StringRindex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = rindex(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void StringStrlen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strlen(Param[0]->Val->Pointer); +} + +void StringMemset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = memset(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void StringMemcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = memcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringMemcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = memcmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringMemmove(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = memmove(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringMemchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = memchr(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void StringStrchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strchr(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void StringStrrchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strrchr(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void StringStrcoll(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strcoll(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strerror(Param[0]->Val->Integer); +} + +void StringStrspn(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strspn(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrcspn(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strcspn(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrpbrk(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strpbrk(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrstr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strstr(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrtok(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strtok(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StringStrxfrm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strxfrm(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void StringStrdup(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strdup(Param[0]->Val->Pointer); +} + +void StringStrtok_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = strtok_r(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +/* all string.h functions */ +struct LibraryFunction StringFunctions[] = { + { StringIndex, "char *index(char *,int);" }, + { StringRindex, "char *rindex(char *,int);" }, + { StringMemcpy, "void *memcpy(void *,void *,int);" }, + { StringMemmove, "void *memmove(void *,void *,int);" }, + { StringMemchr, "void *memchr(char *,int,int);" }, + { StringMemcmp, "int memcmp(void *,void *,int);" }, + { StringMemset, "void *memset(void *,int,int);" }, + { StringStrcat, "char *strcat(char *,char *);" }, + { StringStrncat, "char *strncat(char *,char *,int);" }, + { StringStrchr, "char *strchr(char *,int);" }, + { StringStrrchr, "char *strrchr(char *,int);" }, + { StringStrcmp, "int strcmp(char *,char *);" }, + { StringStrncmp, "int strncmp(char *,char *,int);" }, + { StringStrcoll, "int strcoll(char *,char *);" }, + { StringStrcpy, "char *strcpy(char *,char *);" }, + { StringStrncpy, "char *strncpy(char *,char *,int);" }, + { StringStrerror, "char *strerror(int);" }, + { StringStrlen, "int strlen(char *);" }, + { StringStrspn, "int strspn(char *,char *);" }, + { StringStrcspn, "int strcspn(char *,char *);" }, + { StringStrpbrk, "char *strpbrk(char *,char *);" }, + { StringStrstr, "char *strstr(char *,char *);" }, + { StringStrtok, "char *strtok(char *,char *);" }, + { StringStrxfrm, "int strxfrm(char *,char *,int);" }, + { StringStrdup, "char *strdup(char *);" }, + { StringStrtok_r, "char *strtok_r(char *,char *,char **);" }, + { NULL, NULL } +}; + +/* creates various system-dependent definitions */ +void StringSetupFunc() { + /* define NULL */ + if (!VariableDefined(TableStrRegister("NULL"))) { + VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); + } +} + +#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/eci/cstdlib/time.c b/eci/cstdlib/time.c new file mode 100644 index 0000000..4e25022 --- /dev/null +++ b/eci/cstdlib/time.c @@ -0,0 +1,108 @@ +/* string.h library for large systems - small embedded systems use clibrary.c instead */ +#include +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +static int CLOCKS_PER_SECValue = CLOCKS_PER_SEC; + +#ifdef CLK_PER_SEC +static int CLK_PER_SECValue = CLK_PER_SEC; +#endif + +#ifdef CLK_TCK +static int CLK_TCKValue = CLK_TCK; +#endif + +void StdAsctime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = asctime(Param[0]->Val->Pointer); +} + +void StdClock(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = clock(); +} + +void StdCtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = ctime(Param[0]->Val->Pointer); +} + +#ifndef NO_FP +void StdDifftime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->FP = difftime((time_t)Param[0]->Val->Integer, Param[1]->Val->Integer); +} +#endif + +void StdGmtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = gmtime(Param[0]->Val->Pointer); +} + +void StdGmtime_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = gmtime_r(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void StdLocaltime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = localtime(Param[0]->Val->Pointer); +} + +void StdMktime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = mktime(Param[0]->Val->Pointer); +} + +void StdTime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = time(Param[0]->Val->Pointer); +} + +void StdStrftime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = strftime(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer); +} + +void StdStrptime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + extern char *strptime(const char *s, const char *format, struct tm *tm); + ReturnValue->Val->Pointer = strptime(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); +} + +void StdTimegm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = timegm(Param[0]->Val->Pointer); +} + +/* handy structure definitions */ +const char StdTimeDefs[] = "\ +typedef int time_t; \ +typedef int clock_t;\ +"; + +/* all string.h functions */ +struct LibraryFunction StdTimeFunctions[] = { + { StdAsctime, "char *asctime(struct tm *);" }, + { StdClock, "time_t clock();" }, + { StdCtime, "char *ctime(int *);" }, +#ifndef NO_FP + { StdDifftime, "double difftime(int, int);" }, +#endif + { StdGmtime, "struct tm *gmtime(int *);" }, + { StdGmtime_r, "struct tm *gmtime_r(int *, struct tm *);" }, + { StdLocaltime, "struct tm *localtime(int *);" }, + { StdMktime, "int mktime(struct tm *ptm);" }, + { StdTime, "int time(int *);" }, + { StdStrftime, "int strftime(char *, int, char *, struct tm *);" }, + { StdStrptime, "char *strptime(char *, char *, struct tm *);" }, + { StdTimegm, "int timegm(struct tm *);" }, + { NULL, NULL } +}; + + +/* creates various system-dependent definitions */ +void StdTimeSetupFunc() { + /* make a "struct tm" which is the same size as a native tm structure */ + TypeCreateOpaqueStruct(NULL, TableStrRegister("tm"), sizeof(struct tm)); + /* define CLK_PER_SEC etc. */ + VariableDefinePlatformVar(NULL, "CLOCKS_PER_SEC", &IntType, (union AnyValue *)&CLOCKS_PER_SECValue, FALSE); +#ifdef CLK_PER_SEC + VariableDefinePlatformVar(NULL, "CLK_PER_SEC", &IntType, (union AnyValue *)&CLK_PER_SECValue, FALSE); +#endif +#ifdef CLK_TCK + VariableDefinePlatformVar(NULL, "CLK_TCK", &IntType, (union AnyValue *)&CLK_TCKValue, FALSE); +#endif +} + +#endif diff --git a/eci/cstdlib/unistd.c b/eci/cstdlib/unistd.c new file mode 100644 index 0000000..c8789ce --- /dev/null +++ b/eci/cstdlib/unistd.c @@ -0,0 +1,373 @@ +/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */ +#include +#include +#include +#include "../interpreter.h" + +#ifndef BUILTIN_MINI_STDLIB + +static int ZeroValue = 0; + +void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = access(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = alarm(Param[0]->Val->Integer); +} + +void UnistdChdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = chdir(Param[0]->Val->Pointer); +} + +void UnistdChroot(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = chroot(Param[0]->Val->Pointer); +} + +void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = close(Param[0]->Val->Integer); +} + +void UnistdConfstr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = confstr(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void UnistdCtermid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = ctermid(Param[0]->Val->Pointer); +} + +void UnistdDup(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = dup(Param[0]->Val->Integer); +} + +void UnistdDup2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = dup2(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void Unistd_Exit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + _exit(Param[0]->Val->Integer); +} + +void UnistdFchown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fchown(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void UnistdFchdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fchdir(Param[0]->Val->Integer); +} + +void UnistdFdatasync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fdatasync(Param[0]->Val->Integer); +} + +void UnistdFork(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fork(); +} + +void UnistdFpathconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fpathconf(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdFsync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = fsync(Param[0]->Val->Integer); +} + +void UnistdFtruncate(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ftruncate(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getdtablesize(); +} + +void UnistdGetegid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getegid(); +} + +void UnistdGeteuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = geteuid(); +} + +void UnistdGetgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getgid(); +} + +void UnistdGethostid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = gethostid(); +} + +void UnistdGetlogin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = getlogin(); +} + +void UnistdGetlogin_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getlogin_r(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void UnistdGetpagesize(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getpagesize(); +} + +void UnistdGetpass(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = getpass(Param[0]->Val->Pointer); +} + +void UnistdGetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getpgrp(); +} + +void UnistdGetpid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getpid(); +} + +void UnistdGetppid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getppid(); +} + +void UnistdGetuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = getuid(); +} + +void UnistdGetwd(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, PATH_MAX); +} + +void UnistdIsatty(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = isatty(Param[0]->Val->Integer); +} + +void UnistdLchown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = lchown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = link(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = lockf(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void UnistdLseek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = lseek(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); +} + +void UnistdNice(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = nice(Param[0]->Val->Integer); +} + +void UnistdPathconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = pathconf(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void UnistdPause(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = pause(); +} + +void UnistdRead(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = read(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void UnistdReadlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = readlink(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void UnistdRmdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = rmdir(Param[0]->Val->Pointer); +} + +void UnistdSbrk(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = sbrk(Param[0]->Val->Integer); +} + +void UnistdSetgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setgid(Param[0]->Val->Integer); +} + +void UnistdSetpgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setpgid(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdSetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setpgrp(); +} + +void UnistdSetregid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setregid(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdSetreuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setreuid(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdSetsid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setsid(); +} + +void UnistdSetuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = setuid(Param[0]->Val->Integer); +} + +void UnistdSleep(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = sleep(Param[0]->Val->Integer); +} + +void UnistdSymlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = symlink(Param[0]->Val->Pointer, Param[1]->Val->Pointer); +} + +void UnistdSync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + sync(); +} + +void UnistdSysconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = sysconf(Param[0]->Val->Integer); +} + +void UnistdTcgetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = tcgetpgrp(Param[0]->Val->Integer); +} + +void UnistdTcsetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = tcsetpgrp(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdTruncate(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = truncate(Param[0]->Val->Pointer, Param[1]->Val->Integer); +} + +void UnistdTtyname(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Pointer = ttyname(Param[0]->Val->Integer); +} + +void UnistdTtyname_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ttyname_r(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + +void UnistdUalarm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = ualarm(Param[0]->Val->Integer, Param[1]->Val->Integer); +} + +void UnistdUnlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = unlink(Param[0]->Val->Pointer); +} + +void UnistdUsleep(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = usleep(Param[0]->Val->Integer); +} + +void UnistdVfork(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = vfork(); +} + +void UnistdWrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = write(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); +} + + +/* handy structure definitions */ +const char UnistdDefs[] = "\ +typedef int uid_t; \ +typedef int gid_t; \ +typedef int pid_t; \ +typedef int off_t; \ +typedef int size_t; \ +typedef int ssize_t; \ +typedef int useconds_t;\ +typedef int intptr_t;\ +"; + +/* all unistd.h functions */ +struct LibraryFunction UnistdFunctions[] = { + { UnistdAccess, "int access(char *, int);" }, + { UnistdAlarm, "unsigned int alarm(unsigned int);" }, + { UnistdChdir, "int chdir(char *);" }, + { UnistdChroot, "int chroot(char *);" }, + { UnistdChown, "int chown(char *, uid_t, gid_t);" }, + { UnistdClose, "int close(int);" }, + { UnistdConfstr, "size_t confstr(int, char *, size_t);" }, + { UnistdCtermid, "char *ctermid(char *);" }, + { UnistdDup, "int dup(int);" }, + { UnistdDup2, "int dup2(int, int);" }, + { Unistd_Exit, "void _exit(int);" }, + { UnistdFchown, "int fchown(int, uid_t, gid_t);" }, + { UnistdFchdir, "int fchdir(int);" }, + { UnistdFdatasync, "int fdatasync(int);" }, + { UnistdFork, "pid_t fork(void);" }, + { UnistdFpathconf, "long fpathconf(int, int);" }, + { UnistdFsync, "int fsync(int);" }, + { UnistdFtruncate, "int ftruncate(int, off_t);" }, + { UnistdGetcwd, "char *getcwd(char *, size_t);" }, + { UnistdGetdtablesize, "int getdtablesize(void);" }, + { UnistdGetegid, "gid_t getegid(void);" }, + { UnistdGeteuid, "uid_t geteuid(void);" }, + { UnistdGetgid, "gid_t getgid(void);" }, + { UnistdGethostid, "long gethostid(void);" }, + { UnistdGetlogin, "char *getlogin(void);" }, + { UnistdGetlogin_r, "int getlogin_r(char *, size_t);" }, + { UnistdGetpagesize, "int getpagesize(void);" }, + { UnistdGetpass, "char *getpass(char *);" }, + { UnistdGetpgrp, "pid_t getpgrp(void);" }, + { UnistdGetpid, "pid_t getpid(void);" }, + { UnistdGetppid, "pid_t getppid(void);" }, + { UnistdGetuid, "uid_t getuid(void);" }, + { UnistdGetwd, "char *getwd(char *);" }, + { UnistdIsatty, "int isatty(int);" }, + { UnistdLchown, "int lchown(char *, uid_t, gid_t);" }, + { UnistdLink, "int link(char *, char *);" }, + { UnistdLockf, "int lockf(int, int, off_t);" }, + { UnistdLseek, "off_t lseek(int, off_t, int);" }, + { UnistdNice, "int nice(int);" }, + { UnistdPathconf, "long pathconf(char *, int);" }, + { UnistdPause, "int pause(void);" }, + { UnistdRead, "ssize_t read(int, void *, size_t);" }, + { UnistdReadlink, "int readlink(char *, char *, size_t);" }, + { UnistdRmdir, "int rmdir(char *);" }, + { UnistdSbrk, "void *sbrk(intptr_t);" }, + { UnistdSetgid, "int setgid(gid_t);" }, + { UnistdSetpgid, "int setpgid(pid_t, pid_t);" }, + { UnistdSetpgrp, "pid_t setpgrp(void);" }, + { UnistdSetregid, "int setregid(gid_t, gid_t);" }, + { UnistdSetreuid, "int setreuid(uid_t, uid_t);" }, + { UnistdSetsid, "pid_t setsid(void);" }, + { UnistdSetuid, "int setuid(uid_t);" }, + { UnistdSleep, "unsigned int sleep(unsigned int);" }, + { UnistdSymlink, "int symlink(char *, char *);" }, + { UnistdSync, "void sync(void);" }, + { UnistdSysconf, "long sysconf(int);" }, + { UnistdTcgetpgrp, "pid_t tcgetpgrp(int);" }, + { UnistdTcsetpgrp, "int tcsetpgrp(int, pid_t);" }, + { UnistdTruncate, "int truncate(char *, off_t);" }, + { UnistdTtyname, "char *ttyname(int);" }, + { UnistdTtyname_r, "int ttyname_r(int, char *, size_t);" }, + { UnistdUalarm, "useconds_t ualarm(useconds_t, useconds_t);" }, + { UnistdUnlink, "int unlink(char *);" }, + { UnistdUsleep, "int usleep(useconds_t);" }, + { UnistdVfork, "pid_t vfork(void);" }, + { UnistdWrite, "ssize_t write(int, void *, size_t);" }, + { NULL, NULL } +}; + +/* creates various system-dependent definitions */ +void UnistdSetupFunc() { + /* define NULL */ + if (!VariableDefined(TableStrRegister("NULL"))) { + VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); + } + /* define optarg and friends */ + VariableDefinePlatformVar(NULL, "optarg", CharPtrType, (union AnyValue *)&optarg, TRUE); + VariableDefinePlatformVar(NULL, "optind", &IntType, (union AnyValue *)&optind, TRUE); + VariableDefinePlatformVar(NULL, "opterr", &IntType, (union AnyValue *)&opterr, TRUE); + VariableDefinePlatformVar(NULL, "optopt", &IntType, (union AnyValue *)&optopt, TRUE); +} + +#endif /* !BUILTIN_MINI_STDLIB */ + diff --git a/eci/expression.c b/eci/expression.c new file mode 100644 index 0000000..c7be241 --- /dev/null +++ b/eci/expression.c @@ -0,0 +1,1533 @@ +#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 +#define IS_TYPE_TOKEN(t) ((t) >= TokenIntType && (t) <= TokenUnsignedType) + +#define DEEP_PRECEDENCE (BRACKET_PRECEDENCE*1000) + +#ifdef DEBUG_EXPRESSIONS +#define debugf printf +#else +void debugf(char *Format, ...) { +} +#endif + +/* local prototypes */ +enum OperatorOrder { + OrderNone, + OrderPrefix, + OrderInfix, + OrderPostfix +}; + +/* a stack of expressions we use in evaluation */ +struct ExpressionStack +{ + struct ExpressionStack *Next; /* the next lower item on the stack */ + struct Value *Val; /* the value for this stack node */ + enum LexToken Op; /* the operator */ + short unsigned int Precedence; /* the operator precedence of this node */ + unsigned char Order; /* the evaluation order of this operator */ +}; + +/* operator precedence definitions */ +struct OpPrecedence { + unsigned int PrefixPrecedence:4; + unsigned int PostfixPrecedence:4; + unsigned int InfixPrecedence:4; + char *Name; +}; + +/* NOTE: the order of this array must correspond exactly to the order of these tokens in enum LexToken */ +static struct OpPrecedence OperatorPrecedence[] = +{ + /* TokenNone, */ { 0, 0, 0, "none" }, + /* TokenComma, */ { 0, 0, 0, "," }, + /* TokenAssign, */ { 0, 0, 2, "=" }, + /* TokenAddAssign, */ { 0, 0, 2, "+=" }, + /* TokenSubtractAssign, */ { 0, 0, 2, "-=" }, + /* TokenMultiplyAssign, */ { 0, 0, 2, "*=" }, + /* TokenDivideAssign, */ { 0, 0, 2, "/=" }, + /* TokenModulusAssign, */ { 0, 0, 2, "%=" }, + /* TokenShiftLeftAssign, */ { 0, 0, 2, "<<=" }, + /* TokenShiftRightAssign, */ { 0, 0, 2, ">>=" }, + /* TokenArithmeticAndAssign, */ { 0, 0, 2, "&=" }, + /* TokenArithmeticOrAssign, */ { 0, 0, 2, "|=" }, + /* TokenArithmeticExorAssign, */ { 0, 0, 2, "^=" }, + /* TokenQuestionMark, */ { 0, 0, 3, "?" }, + /* TokenColon, */ { 0, 0, 3, ":" }, + /* TokenLogicalOr, */ { 0, 0, 4, "||" }, + /* TokenLogicalAnd, */ { 0, 0, 5, "&&" }, + /* TokenArithmeticOr, */ { 0, 0, 6, "|" }, + /* TokenArithmeticExor, */ { 0, 0, 7, "^" }, + /* TokenAmpersand, */ { 14, 0, 8, "&" }, + /* TokenEqual, */ { 0, 0, 9, "==" }, + /* TokenNotEqual, */ { 0, 0, 9, "!=" }, + /* TokenLessThan, */ { 0, 0, 10, "<" }, + /* TokenGreaterThan, */ { 0, 0, 10, ">" }, + /* TokenLessEqual, */ { 0, 0, 10, "<=" }, + /* TokenGreaterEqual, */ { 0, 0, 10, ">=" }, + /* TokenShiftLeft, */ { 0, 0, 11, "<<" }, + /* TokenShiftRight, */ { 0, 0, 11, ">>" }, + /* TokenPlus, */ { 14, 0, 12, "+" }, + /* TokenMinus, */ { 14, 0, 12, "-" }, + /* TokenAsterisk, */ { 14, 0, 13, "*" }, + /* TokenSlash, */ { 0, 0, 13, "/" }, + /* TokenModulus, */ { 0, 0, 13, "%" }, + /* TokenIncrement, */ { 14, 15, 0, "++" }, + /* TokenDecrement, */ { 14, 15, 0, "--" }, + /* TokenUnaryNot, */ { 14, 0, 0, "!" }, + /* TokenUnaryExor, */ { 14, 0, 0, "~" }, + /* TokenSizeof, */ { 14, 0, 0, "sizeof" }, + /* TokenCast, */ { 14, 0, 0, "cast" }, + /* TokenLeftSquareBracket, */ { 0, 0, 15, "[" }, + /* TokenRightSquareBracket, */ { 0, 15, 0, "]" }, + /* TokenDot, */ { 0, 0, 15, "." }, + /* TokenArrow, */ { 0, 0, 15, "->" }, + /* TokenOpenBracket, */ { 15, 0, 0, "(" }, + /* TokenCloseBracket, */ { 0, 15, 0, ")" } +}; + +void ExpressionParseFunctionCall(struct ParseState *_parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt); + +#ifdef DEBUG_EXPRESSIONS +/* show the contents of the expression stack */ +void ExpressionStackShow(struct ExpressionStack *StackTop) { + printf("Expression stack [0x%lx,0x%lx]: ", (long)HeapStackTop, (long)StackTop); + + while (StackTop != NULL) { + if (StackTop->Order == OrderNone) { + /* it's a value */ + if (StackTop->Val->IsLValue) { + printf("lvalue="); + }else { + printf("value="); + } + switch (StackTop->Val->Typ->Base) { + case TypeVoid: printf("void"); break; + case TypeInt: printf("%d:int", StackTop->Val->Val->Integer); break; + case TypeShort: printf("%d:short", StackTop->Val->Val->ShortInteger); break; + case TypeChar: printf("%d:char", StackTop->Val->Val->Character); break; + case TypeLong: printf("%d:long", StackTop->Val->Val->LongInteger); break; + case TypeUnsignedShort: printf("%d:unsigned short", StackTop->Val->Val->UnsignedShortInteger); break; + case TypeUnsignedInt: printf("%d:unsigned int", StackTop->Val->Val->UnsignedInteger); break; + case TypeUnsignedLong: printf("%d:unsigned long", StackTop->Val->Val->UnsignedLongInteger); break; + case TypeFP: printf("%f:fp", StackTop->Val->Val->FP); break; + case TypeFunction: printf("%s:function", StackTop->Val->Val->Identifier); break; + case TypeMacro: printf("%s:macro", StackTop->Val->Val->Identifier); break; + case TypePointer: + if (StackTop->Val->Val->Pointer == NULL) + printf("ptr(NULL)"); + else if (StackTop->Val->Typ->FromType->Base == TypeChar) + printf("\"%s\":string", (char *)StackTop->Val->Val->Pointer); + else + printf("ptr(0x%lx)", (long)StackTop->Val->Val->Pointer); + break; + case TypeArray: printf("array"); break; + case TypeStruct: printf("%s:struct", StackTop->Val->Val->Identifier); break; + case TypeUnion: printf("%s:union", StackTop->Val->Val->Identifier); break; + case TypeEnum: printf("%s:enum", StackTop->Val->Val->Identifier); break; + case Type_Type: PrintType(StackTop->Val->Val->Typ, CStdOut); printf(":type"); break; + default: printf("unknown"); break; + } + printf("[0x%lx,0x%lx]", (long)StackTop, (long)StackTop->Val); + } else { + /* it's an operator */ + printf("op='%s' %s %d", OperatorPrecedence[(int)StackTop->Op].Name, + (StackTop->Order == OrderPrefix) ? "prefix" : ((StackTop->Order == OrderPostfix) ? "postfix" : "infix"), + StackTop->Precedence); + printf("[0x%lx]", (long)StackTop); + } + StackTop = StackTop->Next; + if (StackTop != NULL) { + printf(", "); + } + } + printf("\n"); +} +#endif + +long ExpressionCoerceInteger(struct Value *Val) { + switch (Val->Typ->Base) { + case TypeInt: + return (long)Val->Val->Integer; + case TypeChar: + return (long)Val->Val->Character; + case TypeShort: + return (long)Val->Val->ShortInteger; + case TypeLong: + return (long)Val->Val->LongInteger; + case TypeUnsignedInt: + return (long)Val->Val->UnsignedInteger; + case TypeUnsignedShort: + return (long)Val->Val->UnsignedShortInteger; + case TypeUnsignedLong: + return (long)Val->Val->UnsignedLongInteger; + case TypePointer: + return (long)Val->Val->Pointer; +#ifndef NO_FP + case TypeFP: + return (long)Val->Val->FP; +#endif + default: + return 0; + } +} + +unsigned long ExpressionCoerceUnsignedInteger(struct Value *Val) { + switch (Val->Typ->Base) { + case TypeInt: + return (unsigned long)Val->Val->Integer; + case TypeChar: + return (unsigned long)Val->Val->Character; + case TypeShort: + return (unsigned long)Val->Val->ShortInteger; + case TypeLong: + return (unsigned long)Val->Val->LongInteger; + case TypeUnsignedInt: + return (unsigned long)Val->Val->UnsignedInteger; + case TypeUnsignedShort: + return (unsigned long)Val->Val->UnsignedShortInteger; + case TypeUnsignedLong: + return (unsigned long)Val->Val->UnsignedLongInteger; + case TypePointer: + return (unsigned long)Val->Val->Pointer; +#ifndef NO_FP + case TypeFP: + return (unsigned long)Val->Val->FP; +#endif + default: + return 0; + } +} + +#ifndef NO_FP +double ExpressionCoerceFP(struct Value *Val) { +#ifndef BROKEN_FLOAT_CASTS + int IntVal; + unsigned UnsignedVal; + switch (Val->Typ->Base) { + case TypeInt: + IntVal = Val->Val->Integer; + return (double)IntVal; + case TypeChar: + IntVal = Val->Val->Character; + return (double)IntVal; + case TypeShort: + IntVal = Val->Val->ShortInteger; + return (double)IntVal; + case TypeLong: + IntVal = Val->Val->LongInteger; + return (double)IntVal; + case TypeUnsignedInt: + UnsignedVal = Val->Val->UnsignedInteger; + return (double)UnsignedVal; + case TypeUnsignedShort: + UnsignedVal = Val->Val->UnsignedShortInteger; + return (double)UnsignedVal; + case TypeUnsignedLong: + UnsignedVal = Val->Val->UnsignedLongInteger; + return (double)UnsignedVal; + case TypeFP: + return Val->Val->FP; + default: + return 0.0; + } +#else + switch (Val->Typ->Base) { + case TypeInt: + return (double)Val->Val->Integer; + case TypeChar: + return (double)Val->Val->Character; + case TypeShort: + return (double)Val->Val->ShortInteger; + case TypeLong: + return (double)Val->Val->LongInteger; + case TypeUnsignedInt: + return (double)Val->Val->UnsignedInteger; + case TypeUnsignedShort: + return (double)Val->Val->UnsignedShortInteger; + case TypeUnsignedLong: + return (double)Val->Val->UnsignedLongInteger; + case TypeFP: + return (double)Val->Val->FP; + default: + return 0.0; + } +#endif +} +#endif + +/* assign an integer value */ +long ExpressionAssignInt(struct ParseState *_parser, struct Value *DestValue, long FromInt, int After) { + long Result; + if (!DestValue->IsLValue) { + ProgramFail(_parser, "can't assign to this"); + } + if (After) { + Result = ExpressionCoerceInteger(DestValue); + } else { + Result = FromInt; + } + switch (DestValue->Typ->Base) { + case TypeInt: + DestValue->Val->Integer = FromInt; + break; + case TypeShort: + DestValue->Val->ShortInteger = (short)FromInt; + break; + case TypeChar: + DestValue->Val->Character = (unsigned char)FromInt; + break; + case TypeLong: + DestValue->Val->LongInteger = (long)FromInt; + break; + case TypeUnsignedInt: + DestValue->Val->UnsignedInteger = (unsigned int)FromInt; + break; + case TypeUnsignedShort: + DestValue->Val->UnsignedShortInteger = (unsigned short)FromInt; + break; + case TypeUnsignedLong: + DestValue->Val->UnsignedLongInteger = (unsigned long)FromInt; + break; + default: + break; + } + return Result; +} + +#ifndef NO_FP +/* assign a floating point value */ +double ExpressionAssignFP(struct ParseState *_parser, struct Value *DestValue, double FromFP) { + if (!DestValue->IsLValue) { + ProgramFail(_parser, "can't assign to this"); + } + DestValue->Val->FP = FromFP; + return FromFP; +} +#endif + +/* push a node on to the expression stack */ +void ExpressionStackPushValueNode(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *ValueLoc) { + struct ExpressionStack *StackNode = VariableAlloc(_parser, sizeof(struct ExpressionStack), FALSE); + StackNode->Next = *StackTop; + StackNode->Val = ValueLoc; + *StackTop = StackNode; +#ifdef FANCY_ERROR_MESSAGES + StackNode->Line = _parser->Line; + StackNode->CharacterPos = _parser->CharacterPos; +#endif +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(*StackTop); +#endif +} + +/* push a blank value on to the expression stack by type */ +struct Value *ExpressionStackPushValueByType(struct ParseState *_parser, struct ExpressionStack **StackTop, struct ValueType *PushType) { + struct Value *ValueLoc = VariableAllocValueFromType(_parser, PushType, FALSE, NULL, FALSE); + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); + return ValueLoc; +} + +/* push a value on to the expression stack */ +void ExpressionStackPushValue(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *PushValue) { + struct Value *ValueLoc = VariableAllocValueAndCopy(_parser, PushValue, FALSE); + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); +} + +void ExpressionStackPushLValue(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *PushValue, int Offset) { + struct Value *ValueLoc = VariableAllocValueShared(_parser, PushValue); + ValueLoc->Val = (void *)((char *)ValueLoc->Val + Offset); + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); +} + +void ExpressionStackPushDereference(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *DereferenceValue) { + struct Value *DerefVal; + struct Value *ValueLoc; + int Offset; + struct ValueType *DerefType; + int DerefIsLValue; + void *DerefDataLoc = VariableDereferencePointer(_parser, DereferenceValue, &DerefVal, &Offset, &DerefType, &DerefIsLValue); + if (DerefDataLoc == NULL) { + ProgramFail(_parser, "NULL pointer dereference"); + } + ValueLoc = VariableAllocValueFromExistingData(_parser, DerefType, (union AnyValue *)DerefDataLoc, DerefIsLValue, DerefVal); + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); +} + +void ExpressionPushInt(struct ParseState *_parser, struct ExpressionStack **StackTop, long IntValue) { + struct Value *ValueLoc = VariableAllocValueFromType(_parser, &IntType, FALSE, NULL, FALSE); + ValueLoc->Val->Integer = IntValue; + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); +} + +#ifndef NO_FP +void ExpressionPushFP(struct ParseState *_parser, struct ExpressionStack **StackTop, double FPValue) { + struct Value *ValueLoc = VariableAllocValueFromType(_parser, &FPType, FALSE, NULL, FALSE); + ValueLoc->Val->FP = FPValue; + ExpressionStackPushValueNode(_parser, StackTop, ValueLoc); +} +#endif + +/* assign to a pointer */ +void ExpressionAssignToPointer(struct ParseState *_parser, struct Value *ToValue, struct Value *FromValue, const char *FuncName, int ParamNo, int AllowPointerCoercion) { + struct ValueType *PointedToType = ToValue->Typ->FromType; + if ( FromValue->Typ == ToValue->Typ + || FromValue->Typ == VoidPtrType + || ( ToValue->Typ == VoidPtrType + && FromValue->Typ->Base == TypePointer) ) { + // plain old pointer assignment + ToValue->Val->Pointer = FromValue->Val->Pointer; + } else if ( FromValue->Typ->Base == TypeArray + && ( PointedToType == FromValue->Typ->FromType + || ToValue->Typ == VoidPtrType) ) { + // the form is: blah *x = array of blah + ToValue->Val->Pointer = (void *)&FromValue->Val->ArrayMem[0]; + } else if ( FromValue->Typ->Base == TypePointer + && FromValue->Typ->FromType->Base == TypeArray + && ( PointedToType == FromValue->Typ->FromType->FromType + || ToValue->Typ == VoidPtrType) ) { + // the form is: blah *x = pointer to array of blah + ToValue->Val->Pointer = VariableDereferencePointer(_parser, FromValue, NULL, NULL, NULL, NULL); + } else if ( IS_NUMERIC_COERCIBLE(FromValue) + && ExpressionCoerceInteger(FromValue) == 0){ + // null pointer assignment + ToValue->Val->Pointer = NULL; + } else if (AllowPointerCoercion && IS_NUMERIC_COERCIBLE(FromValue)) { + // assign integer to native pointer + ToValue->Val->Pointer = (void *)(unsigned long)ExpressionCoerceUnsignedInteger(FromValue); + } else if ( AllowPointerCoercion + && FromValue->Typ->Base == TypePointer) { + /* assign a pointer to a pointer to a different type */ + ToValue->Val->Pointer = FromValue->Val->Pointer; + } else { + AssignFail(_parser, "%t from %t", ToValue->Typ, FromValue->Typ, 0, 0, FuncName, ParamNo); + } +} + +/* assign any kind of value */ +void ExpressionAssign(struct ParseState *_parser, struct Value *DestValue, struct Value *SourceValue, int Force, const char *FuncName, int ParamNo, int AllowPointerCoercion) { + if ( !DestValue->IsLValue + && !Force) { + AssignFail(_parser, "not an lvalue", NULL, NULL, 0, 0, FuncName, ParamNo); + } + if ( IS_NUMERIC_COERCIBLE(DestValue) + && !IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion)) { + AssignFail(_parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); + } + switch (DestValue->Typ->Base) { + case TypeInt: + DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); + break; + case TypeShort: + DestValue->Val->ShortInteger = ExpressionCoerceInteger(SourceValue); + break; + case TypeChar: + DestValue->Val->Character = ExpressionCoerceUnsignedInteger(SourceValue); + break; + case TypeLong: + DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); + break; + case TypeUnsignedInt: + DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); + break; + case TypeUnsignedShort: + DestValue->Val->UnsignedShortInteger = ExpressionCoerceUnsignedInteger(SourceValue); + break; + case TypeUnsignedLong: + DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); + break; +#ifndef NO_FP + case TypeFP: + if (!IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion)) { + AssignFail(_parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); + } + DestValue->Val->FP = ExpressionCoerceFP(SourceValue); + break; +#endif + case TypePointer: + ExpressionAssignToPointer(_parser, DestValue, SourceValue, FuncName, ParamNo, AllowPointerCoercion); + break; + case TypeArray: + if (DestValue->Typ != SourceValue->Typ) { + AssignFail(_parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); + } + if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize) { + AssignFail(_parser, "from an array of size %d to one of size %d", NULL, NULL, DestValue->Typ->ArraySize, SourceValue->Typ->ArraySize, FuncName, ParamNo); + } + memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(DestValue, FALSE)); + break; + case TypeStruct: + case TypeUnion: + if (DestValue->Typ != SourceValue->Typ) { + AssignFail(_parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); + } + memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(SourceValue, FALSE)); + break; + default: + AssignFail(_parser, "%t", DestValue->Typ, NULL, 0, 0, FuncName, ParamNo); + break; + } +} + +/* evaluate the first half of a ternary operator x ? y : z */ +void ExpressionQuestionMarkOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue) { + if (!IS_NUMERIC_COERCIBLE(TopValue)) { + ProgramFail(_parser, "first argument to '?' should be a number"); + } + if (ExpressionCoerceInteger(TopValue)) { + /* the condition's true, return the BottomValue */ + ExpressionStackPushValue(_parser, StackTop, BottomValue); + } else { + /* the condition's false, return void */ + ExpressionStackPushValueByType(_parser, StackTop, &VoidType); + } +} + +/* evaluate the second half of a ternary operator x ? y : z */ +void ExpressionColonOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue) { + if (TopValue->Typ->Base == TypeVoid) { + /* invoke the "else" part - return the BottomValue */ + ExpressionStackPushValue(_parser, StackTop, BottomValue); + } else { + /* it was a "then" - return the TopValue */ + ExpressionStackPushValue(_parser, StackTop, TopValue); + } +} + +/* evaluate a prefix operator */ +void ExpressionPrefixOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue) { + struct Value *Result; + union AnyValue *ValPtr; + debugf("ExpressionPrefixOperator()\n"); + switch (Op) { + case TokenAmpersand: + if (!TopValue->IsLValue) { + ProgramFail(_parser, "can't get the address of this"); + } + ValPtr = TopValue->Val; + Result = VariableAllocValueFromType(_parser, TypeGetMatching(_parser, TopValue->Typ, TypePointer, 0, StrEmpty, TRUE), FALSE, NULL, FALSE); + Result->Val->Pointer = (void *)ValPtr; + ExpressionStackPushValueNode(_parser, StackTop, Result); + break; + case TokenAsterisk: + ExpressionStackPushDereference(_parser, StackTop, TopValue); + break; + case TokenSizeof: + /* return the size of the argument */ + if (TopValue->Typ == &TypeType) { + ExpressionPushInt(_parser, StackTop, TypeSize(TopValue->Val->Typ, TopValue->Val->Typ->ArraySize, TRUE)); + } else { + ExpressionPushInt(_parser, StackTop, TypeSize(TopValue->Typ, TopValue->Typ->ArraySize, TRUE)); + } + break; + default: + /* an arithmetic operator */ +#ifndef NO_FP + if (TopValue->Typ == &FPType) { + /* floating point prefix arithmetic */ + double ResultFP = 0.0; + switch (Op) { + case TokenPlus: + ResultFP = TopValue->Val->FP; + break; + case TokenMinus: + ResultFP = -TopValue->Val->FP; + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + ExpressionPushFP(_parser, StackTop, ResultFP); + } else +#endif + if (IS_NUMERIC_COERCIBLE(TopValue)) { + /* integer prefix arithmetic */ + long ResultInt = 0; + long TopInt = ExpressionCoerceInteger(TopValue); + switch (Op) { + case TokenPlus: + ResultInt = TopInt; + break; + case TokenMinus: + ResultInt = -TopInt; + break; + case TokenIncrement: + ResultInt = ExpressionAssignInt(_parser, TopValue, TopInt+1, FALSE); + break; + case TokenDecrement: + ResultInt = ExpressionAssignInt(_parser, TopValue, TopInt-1, FALSE); + break; + case TokenUnaryNot: + ResultInt = !TopInt; + break; + case TokenUnaryExor: + ResultInt = ~TopInt; + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + ExpressionPushInt(_parser, StackTop, ResultInt); + } else if (TopValue->Typ->Base == TypePointer) { + /* pointer prefix arithmetic */ + int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); + struct Value *StackValue; + void *ResultPtr; + if (TopValue->Val->Pointer == NULL) { + ProgramFail(_parser, "invalid use of a NULL pointer"); + } + if (!TopValue->IsLValue) { + ProgramFail(_parser, "can't assign to this"); + } + switch (Op) { + case TokenIncrement: + TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); + break; + case TokenDecrement: + TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + ResultPtr = TopValue->Val->Pointer; + StackValue = ExpressionStackPushValueByType(_parser, StackTop, TopValue->Typ); + StackValue->Val->Pointer = ResultPtr; + } else { + ProgramFail(_parser, "invalid operation"); + } + break; + } +} + +/* evaluate a postfix operator */ +void ExpressionPostfixOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue) { + debugf("ExpressionPostfixOperator()\n"); + if (IS_NUMERIC_COERCIBLE(TopValue)) { + long ResultInt = 0; + long TopInt = ExpressionCoerceInteger(TopValue); + switch (Op) { + case TokenIncrement: + ResultInt = ExpressionAssignInt(_parser, TopValue, TopInt+1, TRUE); + break; + case TokenDecrement: + ResultInt = ExpressionAssignInt(_parser, TopValue, TopInt-1, TRUE); + break; + case TokenRightSquareBracket: + ProgramFail(_parser, "not supported"); + // TODO : ... + break; + case TokenCloseBracket: + ProgramFail(_parser, "not supported"); + // TODO : ... + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + ExpressionPushInt(_parser, StackTop, ResultInt); + } else if (TopValue->Typ->Base == TypePointer) { + /* pointer postfix arithmetic */ + int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); + struct Value *StackValue; + void *OrigPointer = TopValue->Val->Pointer; + if (TopValue->Val->Pointer == NULL) { + ProgramFail(_parser, "invalid use of a NULL pointer"); + } + if (!TopValue->IsLValue) { + ProgramFail(_parser, "can't assign to this"); + } + switch (Op) { + case TokenIncrement: + TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); + break; + case TokenDecrement: + TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + StackValue = ExpressionStackPushValueByType(_parser, StackTop, TopValue->Typ); + StackValue->Val->Pointer = OrigPointer; + } else { + ProgramFail(_parser, "invalid operation"); + } +} + +/* evaluate an infix operator */ +void ExpressionInfixOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *BottomValue, struct Value *TopValue) { + long ResultInt = 0; + struct Value *StackValue; + void *Pointer; + debugf("ExpressionInfixOperator()\n"); + if ( BottomValue == NULL + || TopValue == NULL) { + ProgramFail(_parser, "invalid expression"); + } + if (Op == TokenLeftSquareBracket) { + /* array index */ + int ArrayIndex; + struct Value *Result = NULL; + if (!IS_NUMERIC_COERCIBLE(TopValue)) { + ProgramFail(_parser, "array index must be an integer"); + } + ArrayIndex = ExpressionCoerceInteger(TopValue); + /* make the array element result */ + switch (BottomValue->Typ->Base) { + case TypeArray: + Result = VariableAllocValueFromExistingData(_parser, BottomValue->Typ->FromType, (union AnyValue *)(&BottomValue->Val->ArrayMem[0] + TypeSize(BottomValue->Typ, ArrayIndex, TRUE)), BottomValue->IsLValue, BottomValue->LValueFrom); + break; + case TypePointer: + Result = VariableAllocValueFromExistingData(_parser, BottomValue->Typ->FromType, (union AnyValue *)((char *)BottomValue->Val->Pointer + TypeSize(BottomValue->Typ->FromType, 0, TRUE) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom); + break; + default: + ProgramFail(_parser, "this %t is not an array", BottomValue->Typ); + } + ExpressionStackPushValueNode(_parser, StackTop, Result); + } else if (Op == TokenQuestionMark) { + ExpressionQuestionMarkOperator(_parser, StackTop, TopValue, BottomValue); + } else if (Op == TokenColon) { + ExpressionColonOperator(_parser, StackTop, TopValue, BottomValue); + } +#ifndef NO_FP + else if ( (TopValue->Typ == &FPType && BottomValue->Typ == &FPType) + || (TopValue->Typ == &FPType && IS_NUMERIC_COERCIBLE(BottomValue)) + || (IS_NUMERIC_COERCIBLE(TopValue) && BottomValue->Typ == &FPType) ) { + /* floating point infix arithmetic */ + int ResultIsInt = FALSE; + double ResultFP = 0.0; + double TopFP = (TopValue->Typ == &FPType) ? TopValue->Val->FP : (double)ExpressionCoerceInteger(TopValue); + double BottomFP = (BottomValue->Typ == &FPType) ? BottomValue->Val->FP : (double)ExpressionCoerceInteger(BottomValue); + switch (Op) { + case TokenAssign: + ResultFP = ExpressionAssignFP(_parser, BottomValue, TopFP); + break; + case TokenAddAssign: + ResultFP = ExpressionAssignFP(_parser, BottomValue, BottomFP + TopFP); + break; + case TokenSubtractAssign: + ResultFP = ExpressionAssignFP(_parser, BottomValue, BottomFP - TopFP); + break; + case TokenMultiplyAssign: + ResultFP = ExpressionAssignFP(_parser, BottomValue, BottomFP * TopFP); + break; + case TokenDivideAssign: + ResultFP = ExpressionAssignFP(_parser, BottomValue, BottomFP / TopFP); + break; + case TokenEqual: + ResultInt = BottomFP == TopFP; + ResultIsInt = TRUE; + break; + case TokenNotEqual: + ResultInt = BottomFP != TopFP; + ResultIsInt = TRUE; + break; + case TokenLessThan: + ResultInt = BottomFP < TopFP; + ResultIsInt = TRUE; + break; + case TokenGreaterThan: + ResultInt = BottomFP > TopFP; + ResultIsInt = TRUE; + break; + case TokenLessEqual: + ResultInt = BottomFP <= TopFP; + ResultIsInt = TRUE; + break; + case TokenGreaterEqual: + ResultInt = BottomFP >= TopFP; + ResultIsInt = TRUE; + break; + case TokenPlus: + ResultFP = BottomFP + TopFP; + break; + case TokenMinus: + ResultFP = BottomFP - TopFP; + break; + case TokenAsterisk: + ResultFP = BottomFP * TopFP; + break; + case TokenSlash: + ResultFP = BottomFP / TopFP; + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + if (ResultIsInt) { + ExpressionPushInt(_parser, StackTop, ResultInt); + } else { + ExpressionPushFP(_parser, StackTop, ResultFP); + } + } +#endif + else if (IS_NUMERIC_COERCIBLE(TopValue) && IS_NUMERIC_COERCIBLE(BottomValue)) { + /* integer operation */ + long TopInt = ExpressionCoerceInteger(TopValue); + long BottomInt = ExpressionCoerceInteger(BottomValue); + switch (Op) { + case TokenAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, TopInt, FALSE); + break; + case TokenAddAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt + TopInt, FALSE); + break; + case TokenSubtractAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt - TopInt, FALSE); + break; + case TokenMultiplyAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt * TopInt, FALSE); + break; + case TokenDivideAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt / TopInt, FALSE); + break; +#ifndef NO_MODULUS + case TokenModulusAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt % TopInt, FALSE); + break; +#endif + case TokenShiftLeftAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt << TopInt, FALSE); + break; + case TokenShiftRightAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt >> TopInt, FALSE); + break; + case TokenArithmeticAndAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt & TopInt, FALSE); + break; + case TokenArithmeticOrAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt | TopInt, FALSE); + break; + case TokenArithmeticExorAssign: + ResultInt = ExpressionAssignInt(_parser, BottomValue, BottomInt ^ TopInt, FALSE); + break; + case TokenLogicalOr: + ResultInt = BottomInt || TopInt; + break; + case TokenLogicalAnd: + ResultInt = BottomInt && TopInt; + break; + case TokenArithmeticOr: + ResultInt = BottomInt | TopInt; + break; + case TokenArithmeticExor: + ResultInt = BottomInt ^ TopInt; + break; + case TokenAmpersand: + ResultInt = BottomInt & TopInt; + break; + case TokenEqual: + ResultInt = BottomInt == TopInt; + break; + case TokenNotEqual: + ResultInt = BottomInt != TopInt; + break; + case TokenLessThan: + ResultInt = BottomInt < TopInt; + break; + case TokenGreaterThan: + ResultInt = BottomInt > TopInt; + break; + case TokenLessEqual: + ResultInt = BottomInt <= TopInt; + break; + case TokenGreaterEqual: + ResultInt = BottomInt >= TopInt; + break; + case TokenShiftLeft: + ResultInt = BottomInt << TopInt; + break; + case TokenShiftRight: + ResultInt = BottomInt >> TopInt; + break; + case TokenPlus: + ResultInt = BottomInt + TopInt; + break; + case TokenMinus: + ResultInt = BottomInt - TopInt; + break; + case TokenAsterisk: + ResultInt = BottomInt * TopInt; + break; + case TokenSlash: + ResultInt = BottomInt / TopInt; + break; +#ifndef NO_MODULUS + case TokenModulus: + ResultInt = BottomInt % TopInt; + break; +#endif + default: + ProgramFail(_parser, "invalid operation"); + break; + } + ExpressionPushInt(_parser, StackTop, ResultInt); + } else if (BottomValue->Typ->Base == TypePointer && IS_NUMERIC_COERCIBLE(TopValue)) { + /* pointer/integer infix arithmetic */ + long TopInt = ExpressionCoerceInteger(TopValue); + if ( Op == TokenEqual + || Op == TokenNotEqual) { + /* comparison to a NULL pointer */ + if (TopInt != 0) { + ProgramFail(_parser, "invalid operation"); + } + if (Op == TokenEqual) { + ExpressionPushInt(_parser, StackTop, BottomValue->Val->Pointer == NULL); + } else { + ExpressionPushInt(_parser, StackTop, BottomValue->Val->Pointer != NULL); + } + } else if ( Op == TokenPlus + || Op == TokenMinus) { + /* pointer arithmetic */ + int Size = TypeSize(BottomValue->Typ->FromType, 0, TRUE); + Pointer = BottomValue->Val->Pointer; + if (Pointer == NULL) { + ProgramFail(_parser, "invalid use of a NULL pointer"); + } + if (Op == TokenPlus) { + Pointer = (void *)((char *)Pointer + TopInt * Size); + } else { + Pointer = (void *)((char *)Pointer - TopInt * Size); + } + StackValue = ExpressionStackPushValueByType(_parser, StackTop, BottomValue->Typ); + StackValue->Val->Pointer = Pointer; + } else if ( Op == TokenAssign + && TopInt == 0) { + /* assign a NULL pointer */ + HeapUnpopStack(sizeof(struct Value)); + ExpressionAssign(_parser, BottomValue, TopValue, FALSE, NULL, 0, FALSE); + ExpressionStackPushValueNode(_parser, StackTop, BottomValue); + } else if ( Op == TokenAddAssign + || Op == TokenSubtractAssign) { + /* pointer arithmetic */ + int Size = TypeSize(BottomValue->Typ->FromType, 0, TRUE); + Pointer = BottomValue->Val->Pointer; + if (Pointer == NULL) { + ProgramFail(_parser, "invalid use of a NULL pointer"); + } + if (Op == TokenAddAssign) { + Pointer = (void *)((char *)Pointer + TopInt * Size); + } else { + Pointer = (void *)((char *)Pointer - TopInt * Size); + } + HeapUnpopStack(sizeof(struct Value)); + BottomValue->Val->Pointer = Pointer; + ExpressionStackPushValueNode(_parser, StackTop, BottomValue); + } else { + ProgramFail(_parser, "invalid operation"); + } + } else if ( BottomValue->Typ->Base == TypePointer + && TopValue->Typ->Base == TypePointer + && Op != TokenAssign) { + /* pointer/pointer operations */ + char *TopLoc = (char *)TopValue->Val->Pointer; + char *BottomLoc = (char *)BottomValue->Val->Pointer; + switch (Op) { + case TokenEqual: + ExpressionPushInt(_parser, StackTop, BottomLoc == TopLoc); + break; + case TokenNotEqual: + ExpressionPushInt(_parser, StackTop, BottomLoc != TopLoc); + break; + case TokenMinus: + ExpressionPushInt(_parser, StackTop, BottomLoc - TopLoc); + break; + default: + ProgramFail(_parser, "invalid operation"); + break; + } + } else if (Op == TokenAssign) { + /* assign a non-numeric type */ + HeapUnpopStack(sizeof(struct Value)); /* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */ + ExpressionAssign(_parser, BottomValue, TopValue, FALSE, NULL, 0, FALSE); + ExpressionStackPushValueNode(_parser, StackTop, BottomValue); + } else if (Op == TokenCast) { + /* cast a value to a different type */ /* XXX - possible bug if the destination type takes more than sizeof(struct Value) + sizeof(struct ValueType *) */ + struct Value *ValueLoc = ExpressionStackPushValueByType(_parser, StackTop, BottomValue->Val->Typ); + ExpressionAssign(_parser, ValueLoc, TopValue, TRUE, NULL, 0, TRUE); + } else { + ProgramFail(_parser, "invalid operation"); + } +} + +/* take the contents of the expression stack and compute the top until there's nothing greater than the given precedence */ +void ExpressionStackCollapse(struct ParseState *_parser, struct ExpressionStack **StackTop, int Precedence, int *IgnorePrecedence) { + int FoundPrecedence = Precedence; + struct Value *TopValue; + struct Value *BottomValue; + struct ExpressionStack *TopStackNode = *StackTop; + struct ExpressionStack *TopOperatorNode; + debugf("ExpressionStackCollapse(%d):\n", Precedence); +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(*StackTop); +#endif + while (TopStackNode != NULL && TopStackNode->Next != NULL && FoundPrecedence >= Precedence) { + /* find the top operator on the stack */ + if (TopStackNode->Order == OrderNone) { + TopOperatorNode = TopStackNode->Next; + } else { + TopOperatorNode = TopStackNode; + } + FoundPrecedence = TopOperatorNode->Precedence; + /* does it have a high enough precedence? */ + if (FoundPrecedence >= Precedence && TopOperatorNode != NULL) { + /* execute this operator */ + switch (TopOperatorNode->Order) { + case OrderPrefix: + /* prefix evaluation */ + debugf("prefix evaluation\n"); + TopValue = TopStackNode->Val; + /* pop the value and then the prefix operator - assume they'll still be there until we're done */ + HeapPopStack(NULL, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); + HeapPopStack(TopOperatorNode, sizeof(struct ExpressionStack)); + *StackTop = TopOperatorNode->Next; + /* do the prefix operation */ + if ( _parser->Mode == RunModeRun + && FoundPrecedence < *IgnorePrecedence) { + /* run the operator */ + ExpressionPrefixOperator(_parser, StackTop, TopOperatorNode->Op, TopValue); + } else { + /* we're not running it so just return 0 */ + ExpressionPushInt(_parser, StackTop, 0); + } + break; + case OrderPostfix: + /* postfix evaluation */ + debugf("postfix evaluation\n"); + TopValue = TopStackNode->Next->Val; + /* pop the postfix operator and then the value - assume they'll still be there until we're done */ + HeapPopStack(NULL, sizeof(struct ExpressionStack)); + HeapPopStack(TopValue, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); + *StackTop = TopStackNode->Next->Next; + /* do the postfix operation */ + if ( _parser->Mode == RunModeRun + && FoundPrecedence < *IgnorePrecedence) { + /* run the operator */ + ExpressionPostfixOperator(_parser, StackTop, TopOperatorNode->Op, TopValue); + } else { + /* we're not running it so just return 0 */ + ExpressionPushInt(_parser, StackTop, 0); + } + break; + case OrderInfix: + /* infix evaluation */ + debugf("infix evaluation\n"); + TopValue = TopStackNode->Val; + if (TopValue != NULL) { + BottomValue = TopOperatorNode->Next->Val; + /* pop a value, the operator and another value - assume they'll still be there until we're done */ + HeapPopStack(NULL, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); + HeapPopStack(NULL, sizeof(struct ExpressionStack)); + HeapPopStack(BottomValue, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(BottomValue)); + *StackTop = TopOperatorNode->Next->Next; + /* do the infix operation */ + if (_parser->Mode == RunModeRun && FoundPrecedence <= *IgnorePrecedence) { + /* run the operator */ + ExpressionInfixOperator(_parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue); + } else { + /* we're not running it so just return 0 */ + ExpressionPushInt(_parser, StackTop, 0); + } + } else { + FoundPrecedence = -1; + } + break; + case OrderNone: + /* this should never happen */ + assert(TopOperatorNode->Order != OrderNone); + break; + } + /* if we've returned above the ignored precedence level turn ignoring off */ + if (FoundPrecedence <= *IgnorePrecedence) { + *IgnorePrecedence = DEEP_PRECEDENCE; + } + } +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(*StackTop); +#endif + TopStackNode = *StackTop; + } + debugf("ExpressionStackCollapse() finished\n"); +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(*StackTop); +#endif +} + +/* push an operator on to the expression stack */ +void ExpressionStackPushOperator(struct ParseState *_parser, struct ExpressionStack **StackTop, enum OperatorOrder Order, enum LexToken Token, int Precedence) { + struct ExpressionStack *StackNode = VariableAlloc(_parser, sizeof(struct ExpressionStack), FALSE); + StackNode->Next = *StackTop; + StackNode->Order = Order; + StackNode->Op = Token; + StackNode->Precedence = Precedence; + *StackTop = StackNode; + debugf("ExpressionStackPushOperator()\n"); +#ifdef FANCY_ERROR_MESSAGES + StackNode->Line = _parser->Line; + StackNode->CharacterPos = _parser->CharacterPos; +#endif +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(*StackTop); +#endif +} + +/* do the '.' and '->' operators */ +void ExpressionGetStructElement(struct ParseState *_parser, struct ExpressionStack **StackTop, enum LexToken Token) { + struct Value *Ident; + /* get the identifier following the '.' or '->' */ + if (LexGetToken(_parser, &Ident, TRUE) != TokenIdentifier) { + ProgramFail(_parser, "need an structure or union member after '%s'", (Token == TokenDot) ? "." : "->"); + } + if (_parser->Mode == RunModeRun) { + /* look up the struct element */ + struct Value *ParamVal = (*StackTop)->Val; + struct Value *StructVal = ParamVal; + struct ValueType *StructType = ParamVal->Typ; + char *DerefDataLoc = (char *)ParamVal->Val; + struct Value *MemberValue; + struct Value *Result; + /* if we're doing '->' dereference the struct pointer first */ + if (Token == TokenArrow) { + DerefDataLoc = VariableDereferencePointer(_parser, ParamVal, &StructVal, NULL, &StructType, NULL); + } + if (StructType->Base != TypeStruct && StructType->Base != TypeUnion) { + ProgramFail(_parser, "can't use '%s' on something that's not a struct or union %s : it's a %t", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "", ParamVal->Typ); + } + if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL, NULL)) { + ProgramFail(_parser, "doesn't have a member called '%s'", Ident->Val->Identifier); + } + /* pop the value - assume it'll still be there until we're done */ + HeapPopStack(ParamVal, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StructVal)); + *StackTop = (*StackTop)->Next; + /* make the result value for this member only */ + Result = VariableAllocValueFromExistingData(_parser, MemberValue->Typ, (void *)(DerefDataLoc + MemberValue->Val->Integer), TRUE, (StructVal != NULL) ? StructVal->LValueFrom : NULL); + ExpressionStackPushValueNode(_parser, StackTop, Result); + } +} + +/* parse an expression with operator precedence */ +int ExpressionParse(struct ParseState *_parser, struct Value **Result) { + struct Value *LexValue; + int PrefixState = TRUE; + int Done = FALSE; + int BracketPrecedence = 0; + int LocalPrecedence; + int Precedence = 0; + int IgnorePrecedence = DEEP_PRECEDENCE; + struct ExpressionStack *StackTop = NULL; + int TernaryDepth = 0; + debugf("ExpressionParse():\n"); + do { + struct ParseState PreState; + enum LexToken Token; + ParserCopy(&PreState, _parser); + Token = LexGetToken(_parser, &LexValue, TRUE); + if ( ( ( (int)Token > TokenComma + && (int)Token <= (int)TokenOpenBracket) + || ( Token == TokenCloseBracket + && BracketPrecedence != 0) ) + && ( Token != TokenColon + || TernaryDepth > 0) ) { + /* it's an operator with precedence */ + if (PrefixState) { + /* expect a prefix operator */ + if (OperatorPrecedence[(int)Token].PrefixPrecedence == 0) { + ProgramFail(_parser, "operator not expected here"); + } + LocalPrecedence = OperatorPrecedence[(int)Token].PrefixPrecedence; + Precedence = BracketPrecedence + LocalPrecedence; + if (Token == TokenOpenBracket) { + /* it's either a new bracket level or a cast */ + enum LexToken BracketToken = LexGetToken(_parser, &LexValue, FALSE); + if ( IS_TYPE_TOKEN(BracketToken) + && ( StackTop == NULL + || StackTop->Op != TokenSizeof) ) { + /* it's a cast - get the new type */ + struct ValueType *CastType; + char *CastIdentifier; + struct Value *CastTypeValue; + TypeParse(_parser, &CastType, &CastIdentifier, NULL); + if (LexGetToken(_parser, &LexValue, TRUE) != TokenCloseBracket) { + ProgramFail(_parser, "brackets not closed"); + } + // scan and collapse the stack to the precedence of this infix cast operator, then push + Precedence = BracketPrecedence + OperatorPrecedence[(int)TokenCast].PrefixPrecedence; + ExpressionStackCollapse(_parser, &StackTop, Precedence+1, &IgnorePrecedence); + CastTypeValue = VariableAllocValueFromType(_parser, &TypeType, FALSE, NULL, FALSE); + CastTypeValue->Val->Typ = CastType; + ExpressionStackPushValueNode(_parser, &StackTop, CastTypeValue); + ExpressionStackPushOperator(_parser, &StackTop, OrderInfix, TokenCast, Precedence); + } else { + /* boost the bracket operator precedence */ + BracketPrecedence += BRACKET_PRECEDENCE; + } + } else { + //scan and collapse the stack to the precedence of this operator, then push + ExpressionStackCollapse(_parser, &StackTop, Precedence, &IgnorePrecedence); + ExpressionStackPushOperator(_parser, &StackTop, OrderPrefix, Token, Precedence); + } + } else { + // expect an infix or postfix operator + if (OperatorPrecedence[(int)Token].PostfixPrecedence != 0) { + switch (Token) { + case TokenCloseBracket: + case TokenRightSquareBracket: + if (BracketPrecedence == 0) { + // assume this bracket is after the end of the expression + ParserCopy(_parser, &PreState); + Done = TRUE; + } else { + // collapse to the bracket precedence + ExpressionStackCollapse(_parser, &StackTop, BracketPrecedence, &IgnorePrecedence); + BracketPrecedence -= BRACKET_PRECEDENCE; + } + break; + default: + // scan and collapse the stack to the precedence of this operator, then push + Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].PostfixPrecedence; + ExpressionStackCollapse(_parser, &StackTop, Precedence, &IgnorePrecedence); + ExpressionStackPushOperator(_parser, &StackTop, OrderPostfix, Token, Precedence); + break; + } + } else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0) { + // scan and collapse the stack, then push + Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].InfixPrecedence; + // for right to left order, only go down to the next higher precedence so we evaluate it in reverse order + // for left to right order, collapse down to this precedence so we evaluate it in forward order + if (IS_LEFT_TO_RIGHT(OperatorPrecedence[(int)Token].InfixPrecedence)) { + ExpressionStackCollapse(_parser, &StackTop, Precedence, &IgnorePrecedence); + } else { + ExpressionStackCollapse(_parser, &StackTop, Precedence+1, &IgnorePrecedence); + } + if ( Token == TokenDot + || Token == TokenArrow) { + ExpressionGetStructElement(_parser, &StackTop, Token); /* this operator is followed by a struct element so handle it as a special case */ + } else { + /* if it's a && or || operator we may not need to evaluate the right hand side of the expression */ + if ( ( Token == TokenLogicalOr + || Token == TokenLogicalAnd) + && IS_NUMERIC_COERCIBLE(StackTop->Val)) { + long LHSInt = ExpressionCoerceInteger(StackTop->Val); + if ( ( ( Token == TokenLogicalOr + && LHSInt) + || ( Token == TokenLogicalAnd + && !LHSInt) ) + && (IgnorePrecedence > Precedence) ) + IgnorePrecedence = Precedence; + } + // push the operator on the stack + ExpressionStackPushOperator(_parser, &StackTop, OrderInfix, Token, Precedence); + PrefixState = TRUE; + switch (Token) { + case TokenQuestionMark: + TernaryDepth++; + break; + case TokenColon: + TernaryDepth--; + break; + default: + break; + } + } + /* treat an open square bracket as an infix array index operator followed by an open bracket */ + if (Token == TokenLeftSquareBracket) { + /* boost the bracket operator precedence, then push */ + BracketPrecedence += BRACKET_PRECEDENCE; + } + } else { + ProgramFail(_parser, "operator not expected here"); + } + } + } else if (Token == TokenIdentifier) { + /* it's a variable, function or a macro */ + if (!PrefixState) { + ProgramFail(_parser, "identifier not expected here"); + } + if (LexGetToken(_parser, NULL, FALSE) == TokenOpenBracket) { + ExpressionParseFunctionCall(_parser, &StackTop, LexValue->Val->Identifier, _parser->Mode == RunModeRun && Precedence < IgnorePrecedence); + } else { + if (_parser->Mode == RunModeRun && Precedence < IgnorePrecedence) { + struct Value *VariableValue = NULL; + VariableGet(_parser, LexValue->Val->Identifier, &VariableValue); + if (VariableValue->Typ->Base == TypeMacro) { + /* evaluate a macro as a kind of simple subroutine */ + struct ParseState Macro_parser; + struct Value *MacroResult; + ParserCopy(&Macro_parser, &VariableValue->Val->MacroDef.Body); + if (VariableValue->Val->MacroDef.NumParams != 0) { + ProgramFail(&Macro_parser, "macro arguments missing"); + } + if ( !ExpressionParse(&Macro_parser, &MacroResult) + || LexGetToken(&Macro_parser, NULL, FALSE) != TokenEndOfFunction) { + ProgramFail(&Macro_parser, "expression expected"); + } + ExpressionStackPushValueNode(_parser, &StackTop, MacroResult); + } else if (VariableValue->Typ == TypeVoid) { + ProgramFail(_parser, "a void value isn't much use here"); + } else { + ExpressionStackPushLValue(_parser, &StackTop, VariableValue, 0); /* it's a value variable */ + } + } else { + // push a dummy value + ExpressionPushInt(_parser, &StackTop, 0); + } + } + // if we've successfully ignored the RHS turn ignoring off + if (Precedence <= IgnorePrecedence) { + IgnorePrecedence = DEEP_PRECEDENCE; + } + PrefixState = FALSE; + } else if ( (int)Token > TokenCloseBracket + && (int)Token <= TokenCharacterConstant) { + /* it's a value of some sort, push it */ + if (!PrefixState) { + ProgramFail(_parser, "value not expected here"); + } + PrefixState = FALSE; + ExpressionStackPushValue(_parser, &StackTop, LexValue); + } else if (IS_TYPE_TOKEN(Token)) { + /* it's a type. push it on the stack like a value. this is used in sizeof() */ + struct ValueType *Typ; + char *Identifier; + struct Value *TypeValue; + if (!PrefixState) { + ProgramFail(_parser, "type not expected here"); + } + PrefixState = FALSE; + ParserCopy(_parser, &PreState); + TypeParse(_parser, &Typ, &Identifier, NULL); + TypeValue = VariableAllocValueFromType(_parser, &TypeType, FALSE, NULL, FALSE); + TypeValue->Val->Typ = Typ; + ExpressionStackPushValueNode(_parser, &StackTop, TypeValue); + } else { + // it isn't a token from an expression + ParserCopy(_parser, &PreState); + Done = TRUE; + } + } while (!Done); + // check that brackets have been closed + if (BracketPrecedence > 0) { + ProgramFail(_parser, "brackets not closed"); + } + // scan and collapse the stack to precedence 0 + ExpressionStackCollapse(_parser, &StackTop, 0, &IgnorePrecedence); + // fix up the stack and return the result if we're in run mode + if (StackTop != NULL) { + // all that should be left is a single value on the stack + if (_parser->Mode == RunModeRun) { + if ( StackTop->Order != OrderNone + || StackTop->Next != NULL) { + ProgramFail(_parser, "invalid expression"); + } + *Result = StackTop->Val; + HeapPopStack(StackTop, sizeof(struct ExpressionStack)); + } else { + HeapPopStack(StackTop->Val, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StackTop->Val)); + } + } + debugf("ExpressionParse() done\n\n"); +#ifdef DEBUG_EXPRESSIONS + ExpressionStackShow(StackTop); +#endif + return StackTop != NULL; +} + + +/* do a parameterised macro call */ +void ExpressionParseMacroCall(struct ParseState *_parser, struct ExpressionStack **StackTop, const char *MacroName, struct MacroDef *MDef) { + struct Value *ReturnValue = NULL; + struct Value *Param; + struct Value **ParamArray = NULL; + int ArgCount; + enum LexToken Token; + if (_parser->Mode == RunModeRun) { + /* create a stack frame for this macro */ +#ifndef NO_FP + ExpressionStackPushValueByType(_parser, StackTop, &FPType); /* largest return type there is */ +#else + ExpressionStackPushValueByType(_parser, StackTop, &IntType); /* largest return type there is */ +#endif + ReturnValue = (*StackTop)->Val; + HeapPushStackFrame(); + ParamArray = HeapAllocStack(sizeof(struct Value *) * MDef->NumParams); + if (ParamArray == NULL) { + ProgramFail(_parser, "out of memory"); + } + } else { + ExpressionPushInt(_parser, StackTop, 0); + } + // parse arguments + ArgCount = 0; + do { + if (ExpressionParse(_parser, &Param)) { + if (_parser->Mode == RunModeRun) { + if (ArgCount < MDef->NumParams) { + ParamArray[ArgCount] = Param; + } else { + ProgramFail(_parser, "too many arguments to %s()", MacroName); + } + } + ArgCount++; + Token = LexGetToken(_parser, NULL, TRUE); + if ( Token != TokenComma + && Token != TokenCloseBracket) { + ProgramFail(_parser, "comma expected"); + } + } else { + /* end of argument list? */ + Token = LexGetToken(_parser, NULL, TRUE); + if (!TokenCloseBracket) { + ProgramFail(_parser, "bad argument"); + } + } + } while (Token != TokenCloseBracket); + + if (_parser->Mode == RunModeRun) { + /* evaluate the macro */ + struct ParseState Macro_parser; + int Count; + struct Value *EvalValue; + if (ArgCount < MDef->NumParams) { + ProgramFail(_parser, "not enough arguments to '%s'", MacroName); + } + if (MDef->Body.Pos == NULL) { + ProgramFail(_parser, "'%s' is undefined", MacroName); + } + ParserCopy(&Macro_parser, &MDef->Body); + VariableStackFrameAdd(_parser, MacroName, 0); + TopStackFrame->NumParams = ArgCount; + TopStackFrame->ReturnValue = ReturnValue; + for (Count = 0; Count < MDef->NumParams; Count++) { + VariableDefine(_parser, MDef->ParamName[Count], ParamArray[Count], NULL, TRUE); + } + ExpressionParse(&Macro_parser, &EvalValue); + ExpressionAssign(_parser, ReturnValue, EvalValue, TRUE, MacroName, 0, FALSE); + VariableStackFramePop(_parser); + HeapPopStackFrame(); + } +} + +/* do a function call */ +void ExpressionParseFunctionCall(struct ParseState *_parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt) { + struct Value *ReturnValue = NULL; + struct Value *FuncValue; + struct Value *Param; + struct Value **ParamArray = NULL; + int ArgCount; + enum LexToken Token = LexGetToken(_parser, NULL, TRUE); /* open bracket */ + enum RunMode OldMode = _parser->Mode; + if (RunIt) { + /* get the function definition */ + VariableGet(_parser, FuncName, &FuncValue); + if (FuncValue->Typ->Base == TypeMacro) { + /* this is actually a macro, not a function */ + ExpressionParseMacroCall(_parser, StackTop, FuncName, &FuncValue->Val->MacroDef); + return; + } + if (FuncValue->Typ->Base != TypeFunction) { + ProgramFail(_parser, "%t is not a function - can't call", FuncValue->Typ); + } + ExpressionStackPushValueByType(_parser, StackTop, FuncValue->Val->FuncDef.ReturnType); + ReturnValue = (*StackTop)->Val; + HeapPushStackFrame(); + ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams); + if (ParamArray == NULL) { + ProgramFail(_parser, "out of memory"); + } + } else { + ExpressionPushInt(_parser, StackTop, 0); + _parser->Mode = RunModeSkip; + } + // parse arguments + ArgCount = 0; + do { + if ( RunIt + && ArgCount < FuncValue->Val->FuncDef.NumParams) { + ParamArray[ArgCount] = VariableAllocValueFromType(_parser, FuncValue->Val->FuncDef.ParamType[ArgCount], FALSE, NULL, FALSE); + } + if (ExpressionParse(_parser, &Param)) { + if (RunIt) { + if (ArgCount < FuncValue->Val->FuncDef.NumParams) { + ExpressionAssign(_parser, ParamArray[ArgCount], Param, TRUE, FuncName, ArgCount+1, FALSE); + VariableStackPop(_parser, Param); + } else { + if (!FuncValue->Val->FuncDef.VarArgs) { + ProgramFail(_parser, "too many arguments to %s()", FuncName); + } + } + } + ArgCount++; + Token = LexGetToken(_parser, NULL, TRUE); + if (Token != TokenComma && Token != TokenCloseBracket) { + ProgramFail(_parser, "comma expected"); + } + } else { + /* end of argument list? */ + Token = LexGetToken(_parser, NULL, TRUE); + if (!TokenCloseBracket) { + ProgramFail(_parser, "bad argument"); + } + } + } while (Token != TokenCloseBracket); + if (RunIt) { + /* run the function */ + if (ArgCount < FuncValue->Val->FuncDef.NumParams) { + ProgramFail(_parser, "not enough arguments to '%s'", FuncName); + } + if (FuncValue->Val->FuncDef.Intrinsic == NULL) { + /* run a user-defined function */ + struct ParseState FuncParser; + int Count; + if (FuncValue->Val->FuncDef.Body.Pos == NULL) { + ProgramFail(_parser, "'%s' is undefined", FuncName); + } + ParserCopy(&FuncParser, &FuncValue->Val->FuncDef.Body); + VariableStackFrameAdd(_parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); + TopStackFrame->NumParams = ArgCount; + TopStackFrame->ReturnValue = ReturnValue; + for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; ++Count) { + VariableDefine(_parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE); + } + if (ParseStatement(&FuncParser, TRUE) != ParseResultOk) { + ProgramFail(&FuncParser, "function body expected"); + } + if (RunIt) { + if ( FuncParser.Mode == RunModeRun + && FuncValue->Val->FuncDef.ReturnType != &VoidType) { + ProgramFail(&FuncParser, "no value returned from a function returning %t", FuncValue->Val->FuncDef.ReturnType); + } else if (FuncParser.Mode == RunModeGoto) { + ProgramFail(&FuncParser, "couldn't find goto label '%s'", FuncParser.SearchGotoLabel); + } + } + VariableStackFramePop(_parser); + } else { + FuncValue->Val->FuncDef.Intrinsic(_parser, ReturnValue, ParamArray, ArgCount); + } + HeapPopStackFrame(); + } + _parser->Mode = OldMode; +} + +/* parse an expression */ +long ExpressionParseInt(struct ParseState *_parser) { + struct Value *Val; + long Result = 0; + if (!ExpressionParse(_parser, &Val)) { + ProgramFail(_parser, "expression expected"); + } + if (_parser->Mode == RunModeRun) { + if (!IS_NUMERIC_COERCIBLE(Val)) { + ProgramFail(_parser, "integer value expected instead of %t", Val->Typ); + } + Result = ExpressionCoerceInteger(Val); + VariableStackPop(_parser, Val); + } + return Result; +} + diff --git a/eci/heap.c b/eci/heap.c new file mode 100644 index 0000000..a21d579 --- /dev/null +++ b/eci/heap.c @@ -0,0 +1,119 @@ +/* stack grows up from the bottom and heap grows down from the top of heap space */ +#include "interpreter.h" + +#define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */ +#define SPLIT_MEM_THRESHOLD 16 /* don't split memory which is close in size */ + +static unsigned char *HeapMemory = NULL; /* stack memory since our heap is malloc()ed */ +static void *HeapBottom = NULL; /* the bottom of the (downward-growing) heap */ +static void *StackFrame = NULL; /* the current stack frame */ +void *HeapStackTop = NULL; /* the top of the stack */ + +static struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */ +static struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */ + +#ifdef DEBUG_HEAP +void ShowBigList() { + struct AllocNode *LPos; + printf("Heap: bottom=0x%lx 0x%lx-0x%lx, big freelist=", (long)HeapBottom, (long)&HeapMemory[0], (long)&HeapMemory[HEAP_SIZE]); + for (LPos = FreeListBig; LPos != NULL; LPos = LPos->NextFree) { + printf("0x%lx:%d ", (long)LPos, LPos->Size); + } + printf("\n"); +} +#endif + +/* initialise the stack and heap storage */ +void HeapInit(int StackOrHeapSize) { + int Count; + int AlignOffset = 0; + HeapMemory = malloc(StackOrHeapSize); + while (((unsigned long)&HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0) { + AlignOffset++; + } + StackFrame = &HeapMemory[AlignOffset]; + HeapStackTop = &HeapMemory[AlignOffset]; + *(void **)StackFrame = NULL; + HeapBottom = &HeapMemory[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset]; + FreeListBig = NULL; + for (Count = 0; Count < FREELIST_BUCKETS; Count++) { + FreeListBucket[Count] = NULL; + } +} + +void HeapCleanup() { + free(HeapMemory); +} + +/* allocate some space on the stack, in the current stack frame + * clears memory. can return NULL if out of stack space */ +void *HeapAllocStack(int Size) { + char *NewMem = HeapStackTop; + char *NewTop = (char *)HeapStackTop + MEM_ALIGN(Size); +#ifdef DEBUG_HEAP + printf("HeapAllocStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop); +#endif + if (NewTop > (char *)HeapBottom) { + return NULL; + } + HeapStackTop = (void *)NewTop; + memset((void *)NewMem, '\0', Size); + return NewMem; +} + +/* allocate some space on the stack, in the current stack frame */ +void HeapUnpopStack(int Size) { +#ifdef DEBUG_HEAP + printf("HeapUnpopStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop); +#endif + HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(Size)); +} + +/* free some space at the top of the stack */ +int HeapPopStack(void *Addr, int Size) { + int ToLose = MEM_ALIGN(Size); + if (ToLose > ((char *)HeapStackTop - (char *)&HeapMemory[0])) { + return FALSE; + } +#ifdef DEBUG_HEAP + printf("HeapPopStack(0x%lx, %ld) back to 0x%lx\n", (unsigned long)Addr, (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop - ToLose); +#endif + HeapStackTop = (void *)((char *)HeapStackTop - ToLose); + assert(Addr == NULL || HeapStackTop == Addr); + return TRUE; +} + +/* push a new stack frame on to the stack */ +void HeapPushStackFrame() { +#ifdef DEBUG_HEAP + printf("Adding stack frame at 0x%lx\n", (unsigned long)HeapStackTop); +#endif + *(void **)HeapStackTop = StackFrame; + StackFrame = HeapStackTop; + HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE))); +} + +/* pop the current stack frame, freeing all memory in the frame. can return NULL */ +int HeapPopStackFrame() { + if (*(void **)StackFrame != NULL) { + HeapStackTop = StackFrame; + StackFrame = *(void **)StackFrame; +#ifdef DEBUG_HEAP + printf("Popping stack frame back to 0x%lx\n", (unsigned long)HeapStackTop); +#endif + return TRUE; + } else { + return FALSE; + } +} + +/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */ +void *HeapAllocMem(int Size) { + return calloc(Size, 1); +} + +/* free some dynamically allocated memory */ +void HeapFreeMem(void *Mem) { + free(Mem); +} + diff --git a/eci/include.c b/eci/include.c new file mode 100644 index 0000000..bb88e0e --- /dev/null +++ b/eci/include.c @@ -0,0 +1,94 @@ +#include "picoc.h" +#include "interpreter.h" + +#ifndef NO_HASH_INCLUDE + +/* a list of libraries we can include */ +struct IncludeLibrary { + char *IncludeName; + void (*SetupFunction)(void); + struct LibraryFunction *FuncList; + const char *SetupCSource; + struct IncludeLibrary *NextLib; +}; + +struct IncludeLibrary *IncludeLibList = NULL; + +/* initialise the built-in include libraries */ +void IncludeInit() { +#ifndef BUILTIN_MINI_STDLIB + IncludeRegister("ctype.h", NULL, &StdCtypeFunctions[0], NULL); + IncludeRegister("errno.h", &StdErrnoSetupFunc, NULL, NULL); +#ifndef NO_FP + IncludeRegister("math.h", &MathSetupFunc, &MathFunctions[0], NULL); +#endif + IncludeRegister("stdbool.h", &StdboolSetupFunc, NULL, StdboolDefs); + IncludeRegister("stdio.h", &StdioSetupFunc, &StdioFunctions[0], StdioDefs); + IncludeRegister("stdlib.h", &StdlibSetupFunc, &StdlibFunctions[0], NULL); + IncludeRegister("string.h", &StringSetupFunc, &StringFunctions[0], NULL); + IncludeRegister("time.h", &StdTimeSetupFunc, &StdTimeFunctions[0], StdTimeDefs); + IncludeRegister("unistd.h", &UnistdSetupFunc, &UnistdFunctions[0], UnistdDefs); +#endif +} + +/* clean up space used by the include system */ +void IncludeCleanup() { + struct IncludeLibrary *ThisInclude = IncludeLibList; + struct IncludeLibrary *NextInclude; + while (ThisInclude != NULL) { + NextInclude = ThisInclude->NextLib; + HeapFreeMem(ThisInclude); + ThisInclude = NextInclude; + } + IncludeLibList = NULL; +} + +/* register a new build-in include file */ +void IncludeRegister(const char *IncludeName, void (*SetupFunction)(void), struct LibraryFunction *FuncList, const char *SetupCSource) { + struct IncludeLibrary *NewLib = HeapAllocMem(sizeof(struct IncludeLibrary)); + NewLib->IncludeName = TableStrRegister(IncludeName); + NewLib->SetupFunction = SetupFunction; + NewLib->FuncList = FuncList; + NewLib->SetupCSource = SetupCSource; + NewLib->NextLib = IncludeLibList; + IncludeLibList = NewLib; +} + +/* include all of the system headers */ +void PicocIncludeAllSystemHeaders() { + struct IncludeLibrary *ThisInclude = IncludeLibList; + for (; ThisInclude != NULL; ThisInclude = ThisInclude->NextLib) { + IncludeFile(ThisInclude->IncludeName); + } +} + +/* include one of a number of predefined libraries, or perhaps an actual file */ +void IncludeFile(char *FileName) { + struct IncludeLibrary *LInclude; + // scan for the include file name to see if it's in our list of predefined includes + for (LInclude = IncludeLibList; LInclude != NULL; LInclude = LInclude->NextLib) { + if (strcmp(LInclude->IncludeName, FileName) == 0) { + // found it - protect against multiple inclusion + if (!VariableDefined(FileName)) { + VariableDefine(NULL, FileName, NULL, &VoidType, FALSE); + // run an extra startup function if there is one + if (LInclude->SetupFunction != NULL) { + (*LInclude->SetupFunction)(); + } + // parse the setup C source code - may define types etc. + if (LInclude->SetupCSource != NULL) { + PicocParse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE); + } + // set up the library functions + if (LInclude->FuncList != NULL) { + LibraryAdd(&GlobalTable, FileName, LInclude->FuncList); + } + } + return; + } + } + // not a predefined file, read a real file + PicocPlatformScanFile(FileName); +} + +#endif /* NO_HASH_INCLUDE */ diff --git a/ecilib/interpreter.h b/eci/interpreter.h similarity index 54% rename from ecilib/interpreter.h rename to eci/interpreter.h index 2dcdb95..b05c627 100644 --- a/ecilib/interpreter.h +++ b/eci/interpreter.h @@ -50,255 +50,237 @@ typedef FILE IOFILE; struct Table; /* lexical tokens */ -enum LexToken -{ - /* 0x00 */ TokenNone, - /* 0x01 */ TokenComma, - /* 0x02 */ TokenAssign, TokenAddAssign, TokenSubtractAssign, TokenMultiplyAssign, TokenDivideAssign, TokenModulusAssign, - /* 0x08 */ TokenShiftLeftAssign, TokenShiftRightAssign, TokenArithmeticAndAssign, TokenArithmeticOrAssign, TokenArithmeticExorAssign, - /* 0x0d */ TokenQuestionMark, TokenColon, - /* 0x0f */ TokenLogicalOr, - /* 0x10 */ TokenLogicalAnd, - /* 0x11 */ TokenArithmeticOr, - /* 0x12 */ TokenArithmeticExor, - /* 0x13 */ TokenAmpersand, - /* 0x14 */ TokenEqual, TokenNotEqual, - /* 0x16 */ TokenLessThan, TokenGreaterThan, TokenLessEqual, TokenGreaterEqual, - /* 0x1a */ TokenShiftLeft, TokenShiftRight, - /* 0x1c */ TokenPlus, TokenMinus, - /* 0x1e */ TokenAsterisk, TokenSlash, TokenModulus, - /* 0x21 */ TokenIncrement, TokenDecrement, TokenUnaryNot, TokenUnaryExor, TokenSizeof, TokenCast, - /* 0x27 */ TokenLeftSquareBracket, TokenRightSquareBracket, TokenDot, TokenArrow, - /* 0x2b */ TokenOpenBracket, TokenCloseBracket, - /* 0x2d */ TokenIdentifier, TokenIntegerConstant, TokenFPConstant, TokenStringConstant, TokenCharacterConstant, - /* 0x32 */ TokenSemicolon, TokenEllipsis, - /* 0x34 */ TokenLeftBrace, TokenRightBrace, - /* 0x36 */ TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType, - /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenAutoType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, - /* 0x46 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenGoto, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, - /* 0x52 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif, - /* 0x59 */ TokenNew, TokenDelete, - /* 0x5b */ TokenOpenMacroBracket, - /* 0x5c */ TokenEOF, TokenEndOfLine, TokenEndOfFunction +enum LexToken { + /* 0x00 */ TokenNone, + /* 0x01 */ TokenComma, + /* 0x02 */ TokenAssign, TokenAddAssign, TokenSubtractAssign, TokenMultiplyAssign, TokenDivideAssign, TokenModulusAssign, + /* 0x08 */ TokenShiftLeftAssign, TokenShiftRightAssign, TokenArithmeticAndAssign, TokenArithmeticOrAssign, TokenArithmeticExorAssign, + /* 0x0d */ TokenQuestionMark, TokenColon, + /* 0x0f */ TokenLogicalOr, + /* 0x10 */ TokenLogicalAnd, + /* 0x11 */ TokenArithmeticOr, + /* 0x12 */ TokenArithmeticExor, + /* 0x13 */ TokenAmpersand, + /* 0x14 */ TokenEqual, TokenNotEqual, + /* 0x16 */ TokenLessThan, TokenGreaterThan, TokenLessEqual, TokenGreaterEqual, + /* 0x1a */ TokenShiftLeft, TokenShiftRight, + /* 0x1c */ TokenPlus, TokenMinus, + /* 0x1e */ TokenAsterisk, TokenSlash, TokenModulus, + /* 0x21 */ TokenIncrement, TokenDecrement, TokenUnaryNot, TokenUnaryExor, TokenSizeof, TokenCast, + /* 0x27 */ TokenLeftSquareBracket, TokenRightSquareBracket, TokenDot, TokenArrow, + /* 0x2b */ TokenOpenBracket, TokenCloseBracket, + /* 0x2d */ TokenIdentifier, TokenIntegerConstant, TokenFPConstant, TokenStringConstant, TokenCharacterConstant, + /* 0x32 */ TokenSemicolon, TokenEllipsis, + /* 0x34 */ TokenLeftBrace, TokenRightBrace, + /* 0x36 */ TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType, + /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStaticType, TokenAutoType, TokenRegisterType, TokenExternType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, + /* 0x46 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenGoto, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, + /* 0x52 */ TokenHashDefine, TokenHashInclude, TokenHashIf, TokenHashIfdef, TokenHashIfndef, TokenHashElse, TokenHashEndif, + /* 0x59 */ TokenNew, TokenDelete, + /* 0x5b */ TokenOpenMacroBracket, + /* 0x5c */ TokenEOF, TokenEndOfLine, TokenEndOfFunction }; /* used in dynamic memory allocation */ -struct AllocNode -{ - unsigned int Size; - struct AllocNode *NextFree; +struct AllocNode { + unsigned int Size; + struct AllocNode *NextFree; }; /* whether we're running or skipping code */ -enum RunMode -{ - RunModeRun, /* we're running code as we parse it */ - RunModeSkip, /* skipping code, not running */ - RunModeReturn, /* returning from a function */ - RunModeCaseSearch, /* searching for a case label */ - RunModeBreak, /* breaking out of a switch/while/do */ - RunModeContinue, /* as above but repeat the loop */ - RunModeGoto /* searching for a goto label */ +enum RunMode { + RunModeRun, //!< we're running code as we parse it + RunModeSkip, //!< skipping code, not running + RunModeReturn, //!< returning from a function + RunModeCaseSearch, //!< searching for a case label + RunModeBreak, //!< breaking out of a switch/while/do + RunModeContinue, //!< as above but repeat the loop + RunModeGoto //!< searching for a goto label }; /* 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; - 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; +struct ParseState { + const unsigned char *Pos; + const char *FileName; + short int Line; + short int CharacterPos; + 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; }; /* values */ -enum BaseType -{ - TypeVoid, /* no type */ - TypeInt, /* integer */ - TypeShort, /* short integer */ - TypeChar, /* a single character (unsigned) */ - TypeLong, /* long integer */ - TypeUnsignedInt, /* unsigned integer */ - TypeUnsignedShort, /* unsigned short integer */ - TypeUnsignedLong, /* unsigned long integer */ +enum BaseType { + TypeVoid, //!< no type + TypeInt, //!< integer + TypeShort, //!< short integer + TypeChar, //!< a single character (unsigned) + TypeLong, //!< long integer + TypeUnsignedInt, //!< unsigned integer + TypeUnsignedShort, //!< unsigned short integer + TypeUnsignedLong, //!< unsigned long integer #ifndef NO_FP - TypeFP, /* floating point */ + TypeFP, //!< floating point #endif - TypeFunction, /* a function */ - TypeMacro, /* a macro */ - TypePointer, /* a pointer */ - TypeArray, /* an array of a sub-type */ - TypeStruct, /* aggregate type */ - TypeUnion, /* merged type */ - TypeEnum, /* enumerated integer type */ - TypeGotoLabel, /* a label we can "goto" */ - Type_Type /* a type for storing types */ + TypeFunction, //!< a function + TypeMacro, //!< a macro + TypePointer, //!< a pointer + TypeArray, //!< an array of a sub-type + TypeStruct, //!< aggregate type + TypeUnion, //!< merged type + TypeEnum, //!< enumerated integer type + TypeGotoLabel, //!< a label we can "goto" + Type_Type //!< a type for storing types }; /* 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 */ - int AlignBytes; /* the alignment boundary of this type */ - 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 */ - int StaticQualifier; /* true if it's a static */ +struct ValueType { + enum BaseType Base; //!< what kind of type this is + int ArraySize; //!< the size of an array type + int Sizeof; //!< the storage required + int AlignBytes; //!< the alignment boundary of this type + 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 + int StaticQualifier; //!< true if it's a static }; /* function definition */ -struct FuncDef -{ - struct ValueType *ReturnType; /* the return value type */ - int NumParams; /* the number of parameters */ - int VarArgs; /* has a variable number of arguments after the explicitly specified ones */ - struct ValueType **ParamType; /* array of parameter types */ - char **ParamName; /* array of parameter names */ - void (*Intrinsic)(); /* intrinsic call address or NULL */ - struct ParseState Body; /* lexical tokens of the function body if not intrinsic */ +struct FuncDef { + struct ValueType *ReturnType; //!< the return value type + int NumParams; //!< the number of parameters + int VarArgs; //!< has a variable number of arguments after the explicitly specified ones + struct ValueType **ParamType; //!< array of parameter types + char **ParamName; //!< array of parameter names + void (*Intrinsic)(); //!< intrinsic call address or NULL + struct ParseState Body; //!< lexical tokens of the function body if not intrinsic }; /* macro definition */ -struct MacroDef -{ - int NumParams; /* the number of parameters */ - char **ParamName; /* array of parameter names */ - struct ParseState Body; /* lexical tokens of the function body if not intrinsic */ +struct MacroDef { + int NumParams; //!< the number of parameters + char **ParamName; //!< array of parameter names + struct ParseState Body; //!< lexical tokens of the function body if not intrinsic }; /* values */ -union AnyValue -{ - unsigned char Character; - short ShortInteger; - int Integer; - long LongInteger; - unsigned short UnsignedShortInteger; - unsigned int UnsignedInteger; - unsigned long UnsignedLongInteger; - char *Identifier; - char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */ - struct ValueType *Typ; - struct FuncDef FuncDef; - struct MacroDef MacroDef; +union AnyValue { + unsigned char Character; + short ShortInteger; + int Integer; + long LongInteger; + unsigned short UnsignedShortInteger; + unsigned int UnsignedInteger; + unsigned long UnsignedLongInteger; + char *Identifier; + char ArrayMem[2]; //!< placeholder for where the data starts, doesn't point to it + struct ValueType *Typ; + struct FuncDef FuncDef; + struct MacroDef MacroDef; #ifndef NO_FP - double FP; + double FP; #endif - void *Pointer; /* unsafe native pointers */ + void *Pointer; //!< unsafe native pointers }; 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 */ - const char *DeclFileName; /* where the variable was declared */ - unsigned short DeclLine; - unsigned short DeclColumn; - - 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[1]; /* dummy size - used for the shared string table */ - } p; +struct TableEntry { + struct TableEntry *Next; //!< next item in this hash chain + const char *DeclFileName; //!< where the variable was declared + unsigned short DeclLine; + unsigned short DeclColumn; + 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[1]; //!< dummy size - used for the shared string table + } p; }; - -struct Table -{ - short Size; - short OnHeap; - struct TableEntry **HashTable; + +struct Table { + short Size; + short OnHeap; + struct TableEntry **HashTable; }; /* stack frame for function calls */ -struct StackFrame -{ - struct ParseState ReturnParser; /* how we got here */ - const char *FuncName; /* the name of the function we're in */ - struct Value *ReturnValue; /* copy the return value here */ - struct Value **Parameter; /* array of parameter values */ - int NumParams; /* the number of parameters */ - struct Table LocalTable; /* the local variables and parameters */ - struct TableEntry *LocalHashTable[LOCAL_TABLE_SIZE]; - struct StackFrame *PreviousStackFrame; /* the next lower stack frame */ +struct StackFrame { + struct ParseState ReturnParser; //!< how we got here + const char *FuncName; //!< the name of the function we're in + struct Value *ReturnValue; //!< copy the return value here + struct Value **Parameter; //!< array of parameter values + int NumParams; //!< the number of parameters + struct Table LocalTable; //!< the local variables and parameters + struct TableEntry *LocalHashTable[LOCAL_TABLE_SIZE]; + struct StackFrame *PreviousStackFrame; //!< the next lower stack frame }; /* lexer state */ -enum LexMode -{ - LexModeNormal, - LexModeHashInclude, - LexModeHashDefine, - LexModeHashDefineSpace, - LexModeHashDefineSpaceIdent +enum LexMode { + LexModeNormal, + LexModeHashInclude, + LexModeHashDefine, + LexModeHashDefineSpace, + LexModeHashDefineSpaceIdent }; -struct LexState -{ - const char *Pos; - const char *End; - const char *FileName; - int Line; - int CharacterPos; - const char *SourceText; - enum LexMode Mode; - int EmitExtraNewlines; +struct LexState { + const char *Pos; + const char *End; + const char *FileName; + int Line; + int CharacterPos; + const char *SourceText; + enum LexMode Mode; + int EmitExtraNewlines; }; /* library function definition */ -struct LibraryFunction -{ - void (*Func)(struct ParseState *Parser, struct Value *, struct Value **, int); - const char *Prototype; +struct LibraryFunction { + void (*Func)(struct ParseState *Parser, struct Value *, struct Value **, int); + const char *Prototype; }; /* output stream-type specific state information */ -union OutputStreamInfo -{ - struct StringOutputStream - { - struct ParseState *Parser; - char *WritePos; - } Str; +union OutputStreamInfo { + struct StringOutputStream { + struct ParseState *Parser; + char *WritePos; + } Str; }; /* stream-specific method for writing characters to the console */ typedef void CharWriter(unsigned char, union OutputStreamInfo *); /* used when writing output to a string - eg. sprintf() */ -struct OutputStream -{ - CharWriter *Putch; - union OutputStreamInfo i; +struct OutputStream { + CharWriter *Putch; + union OutputStreamInfo i; }; /* possible results of parsing a statement */ -enum ParseResult { ParseResultEOF, ParseResultError, ParseResultOk }; +enum ParseResult { + ParseResultEOF, + ParseResultError, + ParseResultOk +}; /* globals */ extern void *HeapStackTop; @@ -327,9 +309,9 @@ extern IOFILE *CStdOut; /* table.c */ void TableInit(); -char *TableStrRegister(const char *Str); -char *TableStrRegister2(const char *Str, int Len); -void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap); +char *TableStrRegister(const char *_str); +char *TableStrRegister2(const char *_str, int Len); +void TableInitTable(struct Table *_table, struct TableEntry **_hashTable, int _size, int _onHeap); int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn); int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn); struct Value *TableDelete(struct Table *Tbl, const char *Key); diff --git a/eci/lex.c b/eci/lex.c new file mode 100644 index 0000000..96429e9 --- /dev/null +++ b/eci/lex.c @@ -0,0 +1,980 @@ +#include "interpreter.h" + +#ifdef NO_CTYPE +#define isalpha(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) +#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)=='_') + +#define IS_HEX_ALPHA_DIGIT(c) (((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define IS_BASE_DIGIT(c,b) (((c) >= '0' && (c) < '0' + (((b)<10)?(b):10)) || (((b) > 10) ? IS_HEX_ALPHA_DIGIT(c) : FALSE)) +#define GET_BASE_DIGIT(c) (((c) <= '9') ? ((c) - '0') : (((c) <= 'F') ? ((c) - 'A' + 10) : ((c) - 'a' + 10))) + +#define NEXTIS(c,x,y) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else GotToken = (y); } +#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS(d,y,z) } +#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS3(d,y,e,z,a) } +#define NEXTIS3PLUS(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else if (NextChar == (d)) { if (Lexer->Pos[1] == (e)) { LEXER_INCN(Lexer, 2); GotToken = (z); } else { LEXER_INC(Lexer); GotToken = (y); } } else GotToken = (a); } +#define NEXTISEXACTLY3(c,d,y,z) { if (NextChar == (c) && Lexer->Pos[1] == (d)) { LEXER_INCN(Lexer, 2); GotToken = (y); } else GotToken = (z); } + +#define LEXER_INC(l) ( (l)->Pos++, (l)->CharacterPos++ ) +#define LEXER_INCN(l, n) ( (l)->Pos+=(n), (l)->CharacterPos+=(n) ) +#define TOKEN_DATA_OFFSET 2 + +#define MAX_CHAR_VALUE 255 /* maximum value which can be represented by a "char" data type */ + +static union AnyValue LexAnyValue; +static struct Value LexValue = { TypeVoid, &LexAnyValue, FALSE, FALSE }; + +struct ReservedWord { + const char *Word; + enum LexToken Token; + const char *SharedWord; /* word stored in shared string space */ +}; + +static struct ReservedWord ReservedWords[] = { + { "#define", TokenHashDefine, NULL }, + { "#else", TokenHashElse, NULL }, + { "#endif", TokenHashEndif, NULL }, + { "#if", TokenHashIf, NULL }, + { "#ifdef", TokenHashIfdef, NULL }, + { "#ifndef", TokenHashIfndef, NULL }, + { "#include", TokenHashInclude, NULL }, + { "auto", TokenAutoType, NULL }, + { "break", TokenBreak, NULL }, + { "case", TokenCase, NULL }, + { "char", TokenCharType, NULL }, + { "continue", TokenContinue, NULL }, + { "default", TokenDefault, NULL }, + { "delete", TokenDelete, NULL }, + { "do", TokenDo, NULL }, +#ifndef NO_FP + { "double", TokenDoubleType, NULL }, +#endif + { "else", TokenElse, NULL }, + { "enum", TokenEnumType, NULL }, + { "extern", TokenExternType, NULL }, +#ifndef NO_FP + { "float", TokenFloatType, NULL }, +#endif + { "for", TokenFor, NULL }, + { "goto", TokenGoto, NULL }, + { "if", TokenIf, NULL }, + { "int", TokenIntType, NULL }, + { "long", TokenLongType, NULL }, + { "new", TokenNew, NULL }, + { "register", TokenRegisterType, NULL }, + { "return", TokenReturn, NULL }, + { "short", TokenShortType, NULL }, + { "signed", TokenSignedType, NULL }, + { "sizeof", TokenSizeof, NULL }, + { "static", TokenStaticType, NULL }, + { "struct", TokenStructType, NULL }, + { "switch", TokenSwitch, NULL }, + { "typedef", TokenTypedef, NULL }, + { "union", TokenUnionType, NULL }, + { "unsigned", TokenUnsignedType, NULL }, + { "void", TokenVoidType, NULL }, + { "while", TokenWhile, NULL } +}; + +/* linked list of tokens used in interactive mode */ +struct TokenLine { + struct TokenLine *Next; + unsigned char *Tokens; + int NumBytes; +}; + +static struct TokenLine *InteractiveHead = NULL; +static struct TokenLine *InteractiveTail = NULL; +static struct TokenLine *InteractiveCurrentLine = NULL; +static int LexUseStatementPrompt = FALSE; + + +/* initialise the lexer */ +void LexInit() { + int Count; + for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) { + ReservedWords[Count].SharedWord = TableStrRegister(ReservedWords[Count].Word); + } +} + +/* deallocate */ +void LexCleanup() { + LexInteractiveClear(NULL); +} + +/* check if a word is a reserved word - used while scanning */ +enum LexToken LexCheckReservedWord(const char *Word) { + int Count; + for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) { + if (Word == ReservedWords[Count].SharedWord) { + return ReservedWords[Count].Token; + } + } + return TokenNone; +} + +/* get a numeric literal - used while scanning */ +enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value) { + int Result = 0; + int Base = 10; + enum LexToken ResultToken; +#ifndef NO_FP + double FPResult; + double FPDiv; +#endif + if (*Lexer->Pos == '0') { + /* a binary, octal or hex literal */ + LEXER_INC(Lexer); + if (Lexer->Pos != Lexer->End) { + if ( *Lexer->Pos == 'x' + || *Lexer->Pos == 'X') { + Base = 16; + LEXER_INC(Lexer); + } else if (*Lexer->Pos == 'b' || *Lexer->Pos == 'B') { + Base = 2; + LEXER_INC(Lexer); + } else if (*Lexer->Pos != '.') { + Base = 8; + } + } + } + /* get the value */ + for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer)) { + Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos); + } + if (Result >= 0 && Result <= MAX_CHAR_VALUE) { + Value->Typ = &CharType; + Value->Val->Character = Result; + ResultToken = TokenCharacterConstant; + } else { + Value->Typ = &IntType; + Value->Val->Integer = Result; + ResultToken = TokenIntegerConstant; + } + if (Lexer->Pos == Lexer->End) { + return ResultToken; + } + if ( *Lexer->Pos == 'l' + || *Lexer->Pos == 'L') { + LEXER_INC(Lexer); + return ResultToken; + } +#ifndef NO_FP + if ( Lexer->Pos == Lexer->End + || *Lexer->Pos != '.') { + return ResultToken; + } + Value->Typ = &FPType; + LEXER_INC(Lexer); + for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base) { + FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv; + } + + if ( Lexer->Pos != Lexer->End + && ( *Lexer->Pos == 'e' + || *Lexer->Pos == 'E') ) { + double ExponentMultiplier = 1.0; + LEXER_INC(Lexer); + if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-') { + ExponentMultiplier = -1.0; + LEXER_INC(Lexer); + } + for (Result = 0; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer)) { + Result = Result * (double)Base + GET_BASE_DIGIT(*Lexer->Pos); + } + FPResult *= pow((double)Base, (double)Result * ExponentMultiplier); + } + Value->Val->FP = FPResult; + return TokenFPConstant; +#else + return ResultToken; +#endif +} + +/* get a reserved word or identifier - used while scanning */ +enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value) { + const char *StartPos = Lexer->Pos; + enum LexToken Token; + do { + LEXER_INC(Lexer); + } while ( Lexer->Pos != Lexer->End + && isCident((int)*Lexer->Pos)); + Value->Typ = NULL; + Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos); + Token = LexCheckReservedWord(Value->Val->Identifier); + switch (Token) { + case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break; + case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break; + default: break; + } + if (Token != TokenNone) { + return Token; + } + if (Lexer->Mode == LexModeHashDefineSpace) { + Lexer->Mode = LexModeHashDefineSpaceIdent; + } + return TokenIdentifier; +} + +/* unescape a character from an octal character constant */ +unsigned char LexUnEscapeCharacterConstant(const char **From, const char *End, unsigned char FirstChar, int Base) { + unsigned char Total = GET_BASE_DIGIT(FirstChar); + int CCount; + for (CCount = 0; IS_BASE_DIGIT(**From, Base) && CCount < 2; CCount++, (*From)++) { + Total = Total * Base + GET_BASE_DIGIT(**From); + } + return Total; +} + +/* unescape a character from a string or character constant */ +unsigned char LexUnEscapeCharacter(const char **From, const char *End) { + unsigned char ThisChar; + while ( *From != End + && **From == '\\' + && &(*From)[1] != End + && (*From)[1] == '\n' ) { + (*From) += 2; /* skip escaped end of lines with LF line termination */ + } + while ( *From != End + && **From == '\\' + && &(*From)[1] != End + && &(*From)[2] != End + && (*From)[1] == '\r' + && (*From)[2] == '\n') { + (*From) += 3; /* skip escaped end of lines with CR/LF line termination */ + } + if (*From == End) { + return '\\'; + } + if (**From == '\\') { + /* it's escaped */ + (*From)++; + if (*From == End) { + return '\\'; + } + ThisChar = *(*From)++; + switch (ThisChar) { + case '\\': + return '\\'; + case '\'': + return '\''; + case '"': + return '"'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case '0': + case '1': + case '2': + case '3': + return LexUnEscapeCharacterConstant(From, End, ThisChar, 8); + case 'x': + return LexUnEscapeCharacterConstant(From, End, '0', 16); + default: + return ThisChar; + } + } else { + return *(*From)++; + } +} + +/* get a string constant - used while scanning */ +enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value, char EndChar) { + int Escape = FALSE; + const char *StartPos = Lexer->Pos; + const char *EndPos; + char *EscBuf; + char *EscBufPos; + char *RegString; + struct Value *ArrayValue; + + while ( Lexer->Pos != Lexer->End + && ( *Lexer->Pos != EndChar + || Escape)) { + /* find the end */ + if (Escape) { + if ( *Lexer->Pos == '\r' + && Lexer->Pos+1 != Lexer->End) { + Lexer->Pos++; + } + if ( *Lexer->Pos == '\n' + && Lexer->Pos+1 != Lexer->End) { + Lexer->Line++; + Lexer->Pos++; + Lexer->CharacterPos = 0; + Lexer->EmitExtraNewlines++; + } + Escape = FALSE; + } else if (*Lexer->Pos == '\\') { + Escape = TRUE; + } + LEXER_INC(Lexer); + } + EndPos = Lexer->Pos; + EscBuf = HeapAllocStack(EndPos - StartPos); + if (EscBuf == NULL) { + LexFail(Lexer, "out of memory"); + } + for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;) { + *EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos); + } + /* try to find an existing copy of this string literal */ + RegString = TableStrRegister2(EscBuf, EscBufPos - EscBuf); + HeapPopStack(EscBuf, EndPos - StartPos); + ArrayValue = VariableStringLiteralGet(RegString); + if (ArrayValue == NULL) { + /* create and store this string literal */ + ArrayValue = VariableAllocValueAndData(NULL, 0, FALSE, NULL, TRUE); + ArrayValue->Typ = CharArrayType; + ArrayValue->Val = (union AnyValue *)RegString; + VariableStringLiteralDefine(RegString, ArrayValue); + } + /* create the the pointer for this char* */ + Value->Typ = CharPtrType; + Value->Val->Pointer = RegString; + if (*Lexer->Pos == EndChar) { + LEXER_INC(Lexer); + } + return TokenStringConstant; +} + +/* get a character constant - used while scanning */ +enum LexToken LexGetCharacterConstant(struct LexState *Lexer, struct Value *Value) { + Value->Typ = &CharType; + Value->Val->Character = LexUnEscapeCharacter(&Lexer->Pos, Lexer->End); + if (Lexer->Pos != Lexer->End && *Lexer->Pos != '\'') { + LexFail(Lexer, "expected \"'\""); // " + } + LEXER_INC(Lexer); + return TokenCharacterConstant; +} + +/* skip a comment - used while scanning */ +void LexSkipComment(struct LexState *Lexer, char NextChar, enum LexToken *ReturnToken) { + if (NextChar == '*') { + /* conventional C comment */ + while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) { + if (*Lexer->Pos == '\n') { + Lexer->EmitExtraNewlines++; + } + LEXER_INC(Lexer); + } + if (Lexer->Pos != Lexer->End) { + LEXER_INC(Lexer); + } + Lexer->Mode = LexModeNormal; + } else { + /* C++ style comment */ + while ( Lexer->Pos != Lexer->End + && *Lexer->Pos != '\n') { + LEXER_INC(Lexer); + } + } +} + +/* get a single token from the source - used while scanning */ +enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value) { + char ThisChar; + char NextChar; + enum LexToken GotToken = TokenNone; + /* handle cases line multi-line comments or string constants which mess up the line count */ + if (Lexer->EmitExtraNewlines > 0) { + Lexer->EmitExtraNewlines--; + return TokenEndOfLine; + } + /* scan for a token */ + do { + *Value = &LexValue; + while ( Lexer->Pos != Lexer->End + && isspace((int)*Lexer->Pos)) { + if (*Lexer->Pos == '\n') { + Lexer->Line++; + Lexer->Pos++; + Lexer->Mode = LexModeNormal; + Lexer->CharacterPos = 0; + return TokenEndOfLine; + } else if ( Lexer->Mode == LexModeHashDefine + || Lexer->Mode == LexModeHashDefineSpace) { + Lexer->Mode = LexModeHashDefineSpace; + } else if (Lexer->Mode == LexModeHashDefineSpaceIdent) { + Lexer->Mode = LexModeNormal; + } + LEXER_INC(Lexer); + } + if ( Lexer->Pos == Lexer->End + || *Lexer->Pos == '\0') { + return TokenEOF; + } + ThisChar = *Lexer->Pos; + if (isCidstart((int)ThisChar)) { + return LexGetWord(Lexer, *Value); + } + if (isdigit((int)ThisChar)) { + return LexGetNumber(Lexer, *Value); + } + NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0; + LEXER_INC(Lexer); + switch (ThisChar) { + case '"': + GotToken = LexGetStringConstant(Lexer, *Value, '"'); + break; + case '\'': //' + GotToken = LexGetCharacterConstant(Lexer, *Value); + break; + case '(': + if (Lexer->Mode == LexModeHashDefineSpaceIdent) { + GotToken = TokenOpenMacroBracket; + } else { + GotToken = TokenOpenBracket; + } + Lexer->Mode = LexModeNormal; + break; + case ')': + GotToken = TokenCloseBracket; + break; + case '=': + NEXTIS('=', TokenEqual, TokenAssign); + break; + case '+': + NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); + break; + case '-': + NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); + break; + case '*': + NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); + break; + case '/': + if ( NextChar == '/' + || NextChar == '*') { + LEXER_INC(Lexer); + LexSkipComment(Lexer, NextChar, &GotToken); + } else { + NEXTIS('=', TokenDivideAssign, TokenSlash); + } + break; + case '%': + NEXTIS('=', TokenModulusAssign, TokenModulus); + break; + case '<': + if (Lexer->Mode == LexModeHashInclude) { + GotToken = LexGetStringConstant(Lexer, *Value, '>'); + } else { + NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); + } + break; + case '>': + NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); + break; + case ';': + GotToken = TokenSemicolon; + break; + case '&': + NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); + break; + case '|': + NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr); + break; + case '{': + GotToken = TokenLeftBrace; + break; + case '}': + GotToken = TokenRightBrace; + break; + case '[': + GotToken = TokenLeftSquareBracket; + break; + case ']': + GotToken = TokenRightSquareBracket; + break; + case '!': + NEXTIS('=', TokenNotEqual, TokenUnaryNot); + break; + case '^': + NEXTIS('=', TokenArithmeticExorAssign, TokenArithmeticExor); + break; + case '~': + GotToken = TokenUnaryExor; + break; + case ',': + GotToken = TokenComma; + break; + case '.': + NEXTISEXACTLY3('.', '.', TokenEllipsis, TokenDot); + break; + case '?': + GotToken = TokenQuestionMark; + break; + case ':': + GotToken = TokenColon; + break; + default: + LexFail(Lexer, "illegal character '%c'", ThisChar); + break; + } + } while (GotToken == TokenNone); + return GotToken; +} + +/* what size value goes with each token */ +int LexTokenSize(enum LexToken Token) { + switch (Token) { + case TokenIdentifier: + case TokenStringConstant: + return sizeof(char *); + case TokenIntegerConstant: + return sizeof(int); + case TokenCharacterConstant: + return sizeof(unsigned char); + case TokenFPConstant: + return sizeof(double); + default: + return 0; + } +} + +/* produce tokens from the lexer and return a heap buffer with the result - used for scanning */ +void *LexTokenise(struct LexState *Lexer, int *TokenLen) { + enum LexToken Token; + void *HeapMem; + struct Value *GotValue; + int MemUsed = 0; + int ValueSize; + int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 16; + void *TokenSpace = HeapAllocStack(ReserveSpace); + char *TokenPos = (char *)TokenSpace; + int LastCharacterPos = 0; + if (TokenSpace == NULL) { + LexFail(Lexer, "out of memory"); + } + do { + /* store the token at the end of the stack area */ + Token = LexScanGetToken(Lexer, &GotValue); +#ifdef DEBUG_LEXER + printf("Token: %02x\n", Token); +#endif + *(unsigned char *)TokenPos = Token; + TokenPos++; + MemUsed++; + *(unsigned char *)TokenPos = (unsigned char)LastCharacterPos; + TokenPos++; + MemUsed++; + ValueSize = LexTokenSize(Token); + if (ValueSize > 0) { + /* store a value as well */ + memcpy((void *)TokenPos, (void *)GotValue->Val, ValueSize); + TokenPos += ValueSize; + MemUsed += ValueSize; + } + LastCharacterPos = Lexer->CharacterPos; + } while (Token != TokenEOF); + HeapMem = HeapAllocMem(MemUsed); + if (HeapMem == NULL) { + LexFail(Lexer, "out of memory"); + } + assert(ReserveSpace >= MemUsed); + memcpy(HeapMem, TokenSpace, MemUsed); + HeapPopStack(TokenSpace, ReserveSpace); +#ifdef DEBUG_LEXER + { + int Count; + printf("Tokens: "); + for (Count = 0; Count < MemUsed; Count++) { + printf("%02x ", *((unsigned char *)HeapMem+Count)); + } + printf("\n"); + } +#endif + if (TokenLen) { + *TokenLen = MemUsed; + } + return HeapMem; +} + +/* lexically analyse some source text */ +void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen) { + struct LexState Lexer; + Lexer.Pos = Source; + Lexer.End = Source + SourceLen; + Lexer.Line = 1; + Lexer.FileName = FileName; + Lexer.Mode = LexModeNormal; + Lexer.EmitExtraNewlines = 0; + Lexer.CharacterPos = 1; + Lexer.SourceText = Source; + return LexTokenise(&Lexer, TokenLen); +} + +/* prepare to parse a pre-tokenised buffer */ +void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt){ + Parser->Pos = TokenSource; + Parser->Line = 1; + Parser->FileName = FileName; + Parser->Mode = RunIt ? RunModeRun : RunModeSkip; + Parser->SearchLabel = 0; + Parser->HashIfLevel = 0; + Parser->HashIfEvaluateToLevel = 0; + Parser->CharacterPos = 0; + Parser->SourceText = SourceText; +} + +/* get the next token, without pre-processing */ +enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, int IncPos) { + enum LexToken Token = TokenNone; + int ValueSize; + char *Prompt = NULL; + do { + /* get the next token */ + if ( Parser->Pos == NULL + && InteractiveHead != NULL) { + Parser->Pos = InteractiveHead->Tokens; + } + if ( Parser->FileName != StrEmpty + || InteractiveHead != NULL) { + /* skip leading newlines */ + while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine) { + Parser->Line++; + Parser->Pos += TOKEN_DATA_OFFSET; + } + } + if ( Parser->FileName == StrEmpty + && ( InteractiveHead == NULL + || Token == TokenEOF) ) { + /* we're at the end of an interactive input token list */ + char LineBuffer[LINEBUFFER_MAX]; + void *LineTokens; + int LineBytes; + struct TokenLine *LineNode; + if ( InteractiveHead == NULL + || (unsigned char *)Parser->Pos == &InteractiveTail->Tokens[InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) { + /* get interactive input */ + if (LexUseStatementPrompt) { + Prompt = INTERACTIVE_PROMPT_STATEMENT; + LexUseStatementPrompt = FALSE; + } else { + Prompt = INTERACTIVE_PROMPT_LINE; + } + if (PlatformGetLine(&LineBuffer[0], LINEBUFFER_MAX, Prompt) == NULL) { + return TokenEOF; + } + /* put the new line at the end of the linked list of interactive lines */ + LineTokens = LexAnalyse(StrEmpty, &LineBuffer[0], strlen(LineBuffer), &LineBytes); + LineNode = VariableAlloc(Parser, sizeof(struct TokenLine), TRUE); + LineNode->Tokens = LineTokens; + LineNode->NumBytes = LineBytes; + if (InteractiveHead == NULL) { + /* start a new list */ + InteractiveHead = LineNode; + Parser->Line = 1; + Parser->CharacterPos = 0; + } else { + InteractiveTail->Next = LineNode; + } + InteractiveTail = LineNode; + InteractiveCurrentLine = LineNode; + Parser->Pos = LineTokens; + } else { + /* go to the next token line */ + if (Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) { + /* scan for the line */ + for (InteractiveCurrentLine = InteractiveHead; Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; InteractiveCurrentLine = InteractiveCurrentLine->Next) { + assert(InteractiveCurrentLine->Next != NULL); + } + } + assert(InteractiveCurrentLine != NULL); + InteractiveCurrentLine = InteractiveCurrentLine->Next; + assert(InteractiveCurrentLine != NULL); + Parser->Pos = InteractiveCurrentLine->Tokens; + } + Token = (enum LexToken)*(unsigned char *)Parser->Pos; + } + } while ( ( Parser->FileName == StrEmpty + && Token == TokenEOF) + || Token == TokenEndOfLine); + Parser->CharacterPos = *((unsigned char *)Parser->Pos + 1); + ValueSize = LexTokenSize(Token); + if (ValueSize > 0) { + /* this token requires a value - unpack it */ + if (Value != NULL) { + switch (Token) { + case TokenStringConstant: + LexValue.Typ = CharPtrType; + break; + case TokenIdentifier: + LexValue.Typ = NULL; + break; + case TokenIntegerConstant: + LexValue.Typ = &IntType; + break; + case TokenCharacterConstant: + LexValue.Typ = &CharType; + break; +#ifndef NO_FP + case TokenFPConstant: + LexValue.Typ = &FPType; + break; +#endif + default: + break; + } + memcpy((void *)LexValue.Val, (void *)((char *)Parser->Pos + TOKEN_DATA_OFFSET), ValueSize); + LexValue.ValOnHeap = FALSE; + LexValue.ValOnStack = FALSE; + LexValue.IsLValue = FALSE; + LexValue.LValueFrom = NULL; + *Value = &LexValue; + } + if (IncPos) { + Parser->Pos += ValueSize + TOKEN_DATA_OFFSET; + } + } else { + if (IncPos && Token != TokenEOF) { + Parser->Pos += TOKEN_DATA_OFFSET; + } + } +#ifdef DEBUG_LEXER + printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos); +#endif + assert(Token >= TokenNone && Token <= TokenEndOfFunction); + return Token; +} + +/* correct the token position depending if we already incremented the position */ +void LexHashIncPos(struct ParseState *Parser, int IncPos) { + if (!IncPos) { + LexGetRawToken(Parser, NULL, TRUE); + } +} + +/* handle a #ifdef directive */ +void LexHashIfdef(struct ParseState *Parser, int IfNot) { + /* get symbol to check */ + struct Value *IdentValue; + struct Value *SavedValue; + int IsDefined; + enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE); + if (Token != TokenIdentifier) { + ProgramFail(Parser, "identifier expected"); + } + /* is the identifier defined? */ + IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL); + if ( Parser->HashIfEvaluateToLevel == Parser->HashIfLevel + && ( ( IsDefined + && !IfNot) + || ( !IsDefined + && IfNot) ) ) { + /* #if is active, evaluate to this new level */ + Parser->HashIfEvaluateToLevel++; + } + Parser->HashIfLevel++; +} + +/* handle a #if directive */ +void LexHashIf(struct ParseState *Parser) { + /* get symbol to check */ + struct Value *IdentValue; + struct Value *SavedValue; + struct ParseState MacroParser; + enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE); + if (Token == TokenIdentifier) { + /* look up a value from a macro definition */ + if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL)) { + ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier); + } + if (SavedValue->Typ->Base != TypeMacro) { + ProgramFail(Parser, "value expected"); + } + ParserCopy(&MacroParser, &SavedValue->Val->MacroDef.Body); + Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE); + } + if (Token != TokenCharacterConstant) { + ProgramFail(Parser, "value expected"); + } + /* is the identifier defined? */ + if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && IdentValue->Val->Character) { + /* #if is active, evaluate to this new level */ + Parser->HashIfEvaluateToLevel++; + } + Parser->HashIfLevel++; +} + +/* handle a #else directive */ +void LexHashElse(struct ParseState *Parser) { + if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel - 1) { + Parser->HashIfEvaluateToLevel++; /* #if was not active, make this next section active */ + } else if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel) { + /* #if was active, now go inactive */ + if (Parser->HashIfLevel == 0) { + ProgramFail(Parser, "#else without #if"); + } + Parser->HashIfEvaluateToLevel--; + } +} + +/* handle a #endif directive */ +void LexHashEndif(struct ParseState *Parser) { + if (Parser->HashIfLevel == 0) { + ProgramFail(Parser, "#endif without #if"); + } + Parser->HashIfLevel--; + if (Parser->HashIfEvaluateToLevel > Parser->HashIfLevel) { + Parser->HashIfEvaluateToLevel = Parser->HashIfLevel; + } +} + +/* get the next token given a parser state, pre-processing as we go */ +enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos) { + enum LexToken Token; + int TryNextToken; + /* implements the pre-processor #if commands */ + do { + int WasPreProcToken = TRUE; + Token = LexGetRawToken(Parser, Value, IncPos); + switch (Token) { + case TokenHashIfdef: + LexHashIncPos(Parser, IncPos); + LexHashIfdef(Parser, FALSE); + break; + case TokenHashIfndef: + LexHashIncPos(Parser, IncPos); + LexHashIfdef(Parser, TRUE); + break; + case TokenHashIf: + LexHashIncPos(Parser, IncPos); + LexHashIf(Parser); + break; + case TokenHashElse: + LexHashIncPos(Parser, IncPos); + LexHashElse(Parser); + break; + case TokenHashEndif: + LexHashIncPos(Parser, IncPos); + LexHashEndif(Parser); + break; + default: + WasPreProcToken = FALSE; + break; + } + /* if we're going to reject this token, increment the token pointer to the next one */ + TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel && Token != TokenEOF) || WasPreProcToken; + if (!IncPos && TryNextToken) { + LexGetRawToken(Parser, NULL, TRUE); + } + } while (TryNextToken); + return Token; +} + +/* take a quick peek at the next token, skipping any pre-processing */ +enum LexToken LexRawPeekToken(struct ParseState *Parser) { + return (enum LexToken)*(unsigned char *)Parser->Pos; +} + +/* find the end of the line */ +void LexToEndOfLine(struct ParseState *Parser) { + while (TRUE) { + enum LexToken Token = (enum LexToken)*(unsigned char *)Parser->Pos; + if ( Token == TokenEndOfLine + || Token == TokenEOF) { + return; + } else { + LexGetRawToken(Parser, NULL, TRUE); + } + } +} + +/* copy the tokens from StartParser to EndParser into new memory, removing TokenEOFs and terminate with a TokenEndOfFunction */ +void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser) { + int MemSize = 0; + int CopySize; + unsigned char *Pos = (unsigned char *)StartParser->Pos; + unsigned char *NewTokens; + unsigned char *NewTokenPos; + struct TokenLine *ILine; + if (InteractiveHead == NULL) { + /* non-interactive mode - copy the tokens */ + MemSize = EndParser->Pos - StartParser->Pos; + NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); + memcpy(NewTokens, (void *)StartParser->Pos, MemSize); + } else { + /* we're in interactive mode - add up line by line */ + for (InteractiveCurrentLine = InteractiveHead; InteractiveCurrentLine != NULL && (Pos < &InteractiveCurrentLine->Tokens[0] || Pos >= &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes]); InteractiveCurrentLine = InteractiveCurrentLine->Next) + {} /* find the line we just counted */ + + if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes]) { + /* all on a single line */ + MemSize = EndParser->Pos - StartParser->Pos; + NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); + memcpy(NewTokens, (void *)StartParser->Pos, MemSize); + } else { + /* it's spread across multiple lines */ + MemSize = &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; + for (ILine = InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) { + MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET; + } + assert(ILine != NULL); + MemSize += EndParser->Pos - &ILine->Tokens[0]; + NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); + CopySize = &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; + memcpy(NewTokens, Pos, CopySize); + NewTokenPos = NewTokens + CopySize; + for (ILine = InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) { + memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET); + NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET; + } + assert(ILine != NULL); + memcpy(NewTokenPos, &ILine->Tokens[0], EndParser->Pos - &ILine->Tokens[0]); + } + } + NewTokens[MemSize] = (unsigned char)TokenEndOfFunction; + return NewTokens; +} + +/* indicate that we've completed up to this point in the interactive input and free expired tokens */ +void LexInteractiveClear(struct ParseState *Parser) { + while (InteractiveHead != NULL) { + struct TokenLine *NextLine = InteractiveHead->Next; + HeapFreeMem(InteractiveHead->Tokens); + HeapFreeMem(InteractiveHead); + InteractiveHead = NextLine; + } + if (Parser != NULL) { + Parser->Pos = NULL; + } + InteractiveTail = NULL; +} + +/* indicate that we've completed up to this point in the interactive input and free expired tokens */ +void LexInteractiveCompleted(struct ParseState *Parser) { + while (InteractiveHead != NULL && !(Parser->Pos >= &InteractiveHead->Tokens[0] && Parser->Pos < &InteractiveHead->Tokens[InteractiveHead->NumBytes])) { + /* this token line is no longer needed - free it */ + struct TokenLine *NextLine = InteractiveHead->Next; + HeapFreeMem(InteractiveHead->Tokens); + HeapFreeMem(InteractiveHead); + InteractiveHead = NextLine; + if (InteractiveHead == NULL) { + // we've emptied the list + Parser->Pos = NULL; + InteractiveTail = NULL; + } + } +} + +/* the next time we prompt, make it the full statement prompt */ +void LexInteractiveStatementPrompt() { + LexUseStatementPrompt = TRUE; +} diff --git a/eci/parse.c b/eci/parse.c new file mode 100644 index 0000000..2cec544 --- /dev/null +++ b/eci/parse.c @@ -0,0 +1,758 @@ +#include "picoc.h" +#include "interpreter.h" + +/* a chunk of heap-allocated tokens we'll cleanup when we're done */ +struct CleanupTokenNode { + void *Tokens; + const char *SourceText; + struct CleanupTokenNode *Next; +}; + +static struct CleanupTokenNode *CleanupTokenList = NULL; + +/* deallocate any memory */ +void ParseCleanup() { + while (CleanupTokenList != NULL) { + struct CleanupTokenNode *Next = CleanupTokenList->Next; + HeapFreeMem(CleanupTokenList->Tokens); + if (CleanupTokenList->SourceText != NULL) { + HeapFreeMem((void *)CleanupTokenList->SourceText); + } + HeapFreeMem(CleanupTokenList); + CleanupTokenList = Next; + } +} + +/* parse a statement, but only run it if Condition is TRUE */ +enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser, int Condition, int CheckTrailingSemicolon) { + if (Parser->Mode != RunModeSkip && !Condition) { + enum RunMode OldMode = Parser->Mode; + int Result; + Parser->Mode = RunModeSkip; + Result = ParseStatement(Parser, CheckTrailingSemicolon); + Parser->Mode = OldMode; + return Result; + } else { + return ParseStatement(Parser, CheckTrailingSemicolon); + } +} + +/* count the number of parameters to a function or macro */ +int ParseCountParams(struct ParseState *Parser) { + int ParamCount = 0; + enum LexToken Token = LexGetToken(Parser, NULL, TRUE); + if ( Token != TokenCloseBracket + && Token != TokenEOF) { + /* count the number of parameters */ + ParamCount++; + while ((Token = LexGetToken(Parser, NULL, TRUE)) != TokenCloseBracket && Token != TokenEOF) { + if (Token == TokenComma) { + ParamCount++; + } + } + } + return ParamCount; +} + +/* parse a function definition and store it for later */ +struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier) { + struct ValueType *ParamType; + char *ParamIdentifier; + enum LexToken Token = TokenNone; + struct ParseState ParamParser; + struct Value *FuncValue; + struct Value *OldFuncValue; + struct ParseState FuncBody; + int ParamCount = 0; + + if (TopStackFrame != NULL) { + ProgramFail(Parser, "nested function definitions are not allowed"); + } + LexGetToken(Parser, NULL, TRUE); /* open bracket */ + ParserCopy(&ParamParser, Parser); + ParamCount = ParseCountParams(Parser); + if (ParamCount > PARAMETER_MAX) { + ProgramFail(Parser, "too many parameters"); + } + FuncValue = VariableAllocValueAndData(Parser, sizeof(struct FuncDef) + sizeof(struct ValueType *) * ParamCount + sizeof(const char *) * ParamCount, FALSE, NULL, TRUE); + FuncValue->Typ = &FunctionType; + FuncValue->Val->FuncDef.ReturnType = ReturnType; + FuncValue->Val->FuncDef.NumParams = ParamCount; + FuncValue->Val->FuncDef.VarArgs = FALSE; + FuncValue->Val->FuncDef.ParamType = (struct ValueType **)((char *)FuncValue->Val + sizeof(struct FuncDef)); + FuncValue->Val->FuncDef.ParamName = (char **)((char *)FuncValue->Val->FuncDef.ParamType + sizeof(struct ValueType *) * ParamCount); + for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ++ParamCount) { + /* harvest the parameters into the function definition */ + if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, FALSE) == TokenEllipsis) { + /* ellipsis at end */ + FuncValue->Val->FuncDef.NumParams--; + FuncValue->Val->FuncDef.VarArgs = TRUE; + break; + } else { + /* add a parameter */ + TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL); + if (ParamType->Base == TypeVoid) { + /* this isn't a real parameter at all - delete it */ + ParamCount--; + FuncValue->Val->FuncDef.NumParams--; + } else { + FuncValue->Val->FuncDef.ParamType[ParamCount] = ParamType; + FuncValue->Val->FuncDef.ParamName[ParamCount] = ParamIdentifier; + } + } + Token = LexGetToken(&ParamParser, NULL, TRUE); + if ( Token != TokenComma + && ParamCount < FuncValue->Val->FuncDef.NumParams-1) { + ProgramFail(&ParamParser, "comma expected"); + } + } + if ( FuncValue->Val->FuncDef.NumParams != 0 + && Token != TokenCloseBracket + && Token != TokenComma + && Token != TokenEllipsis) { + ProgramFail(&ParamParser, "bad parameter"); + } + + if (strcmp(Identifier, "main") == 0) { + /* make sure it's int main() */ + if ( FuncValue->Val->FuncDef.ReturnType != &IntType + && FuncValue->Val->FuncDef.ReturnType != &VoidType ) { + ProgramFail(Parser, "main() should return an int or void"); + } + if ( FuncValue->Val->FuncDef.NumParams != 0 + && ( FuncValue->Val->FuncDef.NumParams != 2 + || FuncValue->Val->FuncDef.ParamType[0] != &IntType) ) { + ProgramFail(Parser, "bad parameters to main()"); + } + } + /* look for a function body */ + Token = LexGetToken(Parser, NULL, FALSE); + if (Token == TokenSemicolon) { + LexGetToken(Parser, NULL, TRUE); /* it's a prototype, absorb the trailing semicolon */ + } else { + /* it's a full function definition with a body */ + if (Token != TokenLeftBrace) { + ProgramFail(Parser, "bad function definition"); + } + ParserCopy(&FuncBody, Parser); + if (ParseStatementMaybeRun(Parser, FALSE, TRUE) != ParseResultOk) { + ProgramFail(Parser, "function definition expected"); + } + FuncValue->Val->FuncDef.Body = FuncBody; + FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser); + /* is this function already in the global table? */ + if (TableGet(&GlobalTable, Identifier, &OldFuncValue, NULL, NULL, NULL)) { + if (OldFuncValue->Val->FuncDef.Body.Pos == NULL) { + /* override an old function prototype */ + VariableFree(TableDelete(&GlobalTable, Identifier)); + } else { + ProgramFail(Parser, "'%s' is already defined", Identifier); + } + } + } + if (!TableSet(&GlobalTable, Identifier, FuncValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) { + ProgramFail(Parser, "'%s' is already defined", Identifier); + } + return FuncValue; +} + +/* assign an initial value to a variable */ +void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVariable, int DoAssignment) { + struct Value *CValue; + int ArrayIndex; + enum LexToken Token = TokenComma; + if (LexGetToken(Parser, NULL, FALSE) == TokenLeftBrace) { + /* this is an array initialiser */ + LexGetToken(Parser, NULL, TRUE); + for (ArrayIndex = 0; (Parser->Mode != RunModeRun && Token == TokenComma) || (Parser->Mode == RunModeRun && ArrayIndex < NewVariable->Typ->ArraySize); ArrayIndex++) { + struct Value *ArrayElement = NULL; + if (Token != TokenComma) { + ProgramFail(Parser, "comma expected"); + } + if (Parser->Mode == RunModeRun) { + ArrayElement = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + TypeSize(NewVariable->Typ->FromType, 0, TRUE) * ArrayIndex), TRUE, NewVariable); + } + if (!ExpressionParse(Parser, &CValue)) { + ProgramFail(Parser, "expression expected"); + } + if (Parser->Mode == RunModeRun && DoAssignment) { + ExpressionAssign(Parser, ArrayElement, CValue, FALSE, NULL, 0, FALSE); + VariableStackPop(Parser, CValue); + VariableStackPop(Parser, ArrayElement); + } + Token = LexGetToken(Parser, NULL, TRUE); + } + if (Token == TokenComma) { + Token = LexGetToken(Parser, NULL, TRUE); + } + if (Token != TokenRightBrace) { + ProgramFail(Parser, "'}' expected"); + } + } else { + /* this is a normal expression initialiser */ + if (!ExpressionParse(Parser, &CValue)) { + ProgramFail(Parser, "expression expected"); + } + if ( Parser->Mode == RunModeRun + && DoAssignment) { + ExpressionAssign(Parser, NewVariable, CValue, FALSE, NULL, 0, FALSE); + VariableStackPop(Parser, CValue); + } + } +} + +/* declare a variable or function */ +int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) { + char *Identifier; + struct ValueType *BasicType; + struct ValueType *Typ; + struct Value *NewVariable = NULL; + int IsStatic = FALSE; + int FirstVisit = FALSE; + TypeParseFront(Parser, &BasicType, &IsStatic); + do { + TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); + if ( ( Token != TokenVoidType + && Token != TokenStructType + && Token != TokenUnionType + && Token != TokenEnumType) + && Identifier == StrEmpty) { + ProgramFail(Parser, "identifier expected"); + } + if (Identifier != StrEmpty) { + /* handle function definitions */ + if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) { + ParseFunctionDefinition(Parser, Typ, Identifier); + return FALSE; + } else { + if ( Typ == &VoidType + && Identifier != StrEmpty) { + ProgramFail(Parser, "can't define a void variable"); + } + if ( Parser->Mode == RunModeRun + || Parser->Mode == RunModeGoto) { + NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ, IsStatic, &FirstVisit); + } + if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) { + /* we're assigning an initial value */ + LexGetToken(Parser, NULL, TRUE); + ParseDeclarationAssignment(Parser, NewVariable, !IsStatic || FirstVisit); + } + } + } + Token = LexGetToken(Parser, NULL, FALSE); + if (Token == TokenComma) { + LexGetToken(Parser, NULL, TRUE); + } + } while (Token == TokenComma); + return TRUE; +} + +/* parse a #define macro definition and store it for later */ +void ParseMacroDefinition(struct ParseState *Parser) { + struct Value *MacroName; + char *MacroNameStr; + struct Value *ParamName; + struct Value *MacroValue; + if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier) { + ProgramFail(Parser, "identifier expected"); + } + MacroNameStr = MacroName->Val->Identifier; + if (LexRawPeekToken(Parser) == TokenOpenMacroBracket) { + /* it's a parameterised macro, read the parameters */ + enum LexToken Token = LexGetToken(Parser, NULL, TRUE); + struct ParseState ParamParser; + int NumParams; + int ParamCount = 0; + ParserCopy(&ParamParser, Parser); + NumParams = ParseCountParams(&ParamParser); + MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE); + MacroValue->Val->MacroDef.NumParams = NumParams; + MacroValue->Val->MacroDef.ParamName = (char **)((char *)MacroValue->Val + sizeof(struct MacroDef)); + Token = LexGetToken(Parser, &ParamName, TRUE); + while (Token == TokenIdentifier) { + /* store a parameter name */ + MacroValue->Val->MacroDef.ParamName[ParamCount++] = ParamName->Val->Identifier; + /* get the trailing comma */ + Token = LexGetToken(Parser, NULL, TRUE); + if (Token == TokenComma) { + Token = LexGetToken(Parser, &ParamName, TRUE); + } else if (Token != TokenCloseBracket) { + ProgramFail(Parser, "comma expected"); + } + } + if (Token != TokenCloseBracket) { + ProgramFail(Parser, "close bracket expected"); + } + } else { + /* allocate a simple unparameterised macro */ + MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef), FALSE, NULL, TRUE); + MacroValue->Val->MacroDef.NumParams = 0; + } + + /* copy the body of the macro to execute later */ + ParserCopy(&MacroValue->Val->MacroDef.Body, Parser); + MacroValue->Typ = &MacroType; + LexToEndOfLine(Parser); + MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser); + if (!TableSet(&GlobalTable, MacroNameStr, MacroValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) { + ProgramFail(Parser, "'%s' is already defined", MacroNameStr); + } +} + +/* copy the entire parser state */ +void ParserCopy(struct ParseState *To, struct ParseState *From) { + memcpy((void *)To, (void *)From, sizeof(*To)); +} + +/* copy where we're at in the parsing */ +void ParserCopyPos(struct ParseState *To, struct ParseState *From) { + To->Pos = From->Pos; + To->Line = From->Line; + To->HashIfLevel = From->HashIfLevel; + To->HashIfEvaluateToLevel = From->HashIfEvaluateToLevel; + To->CharacterPos = From->CharacterPos; +} + +/* parse a "for" statement */ +void ParseFor(struct ParseState *Parser) { + int Condition; + struct ParseState PreConditional; + struct ParseState PreIncrement; + struct ParseState PreStatement; + struct ParseState After; + if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) { + ProgramFail(Parser, "'(' expected"); + } + if (ParseStatement(Parser, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + ParserCopyPos(&PreConditional, Parser); + if (LexGetToken(Parser, NULL, FALSE) == TokenSemicolon) { + Condition = TRUE; + } else { + Condition = ExpressionParseInt(Parser); + } + if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) { + ProgramFail(Parser, "';' expected"); + } + ParserCopyPos(&PreIncrement, Parser); + ParseStatementMaybeRun(Parser, FALSE, FALSE); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + ParserCopyPos(&PreStatement, Parser); + if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + if (Parser->Mode == RunModeContinue) { + Parser->Mode = RunModeRun; + } + ParserCopyPos(&After, Parser); + while (Condition && Parser->Mode == RunModeRun) { + ParserCopyPos(Parser, &PreIncrement); + ParseStatement(Parser, FALSE); + + ParserCopyPos(Parser, &PreConditional); + if (LexGetToken(Parser, NULL, FALSE) == TokenSemicolon) { + Condition = TRUE; + } else { + Condition = ExpressionParseInt(Parser); + } + if (Condition) { + ParserCopyPos(Parser, &PreStatement); + ParseStatement(Parser, TRUE); + if (Parser->Mode == RunModeContinue) { + Parser->Mode = RunModeRun; + } + } + } + if (Parser->Mode == RunModeBreak) { + Parser->Mode = RunModeRun; + } + ParserCopyPos(Parser, &After); +} + +/* parse a block of code and return what mode it returned in */ +enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition) { + if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace) { + ProgramFail(Parser, "'{' expected"); + } + if (Parser->Mode == RunModeSkip || !Condition) { + /* condition failed - skip this block instead */ + enum RunMode OldMode = Parser->Mode; + Parser->Mode = RunModeSkip; + while (ParseStatement(Parser, TRUE) == ParseResultOk) { + + } + Parser->Mode = OldMode; + } else { + /* just run it in its current mode */ + while (ParseStatement(Parser, TRUE) == ParseResultOk) { + + } + } + if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace) { + ProgramFail(Parser, "'}' expected"); + } + return Parser->Mode; +} + +/* parse a typedef declaration */ +void ParseTypedef(struct ParseState *Parser) { + struct ValueType *Typ; + struct ValueType **TypPtr; + char *TypeName; + struct Value InitValue; + TypeParse(Parser, &Typ, &TypeName, NULL); + if (Parser->Mode == RunModeRun) { + TypPtr = &Typ; + InitValue.Typ = &TypeType; + InitValue.Val = (union AnyValue *)TypPtr; + VariableDefine(Parser, TypeName, &InitValue, NULL, FALSE); + } +} + +/* parse a statement */ +enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon) { + struct Value *CValue; + struct Value *LexerValue; + struct Value *VarValue; + int Condition; + struct ParseState PreState; + enum LexToken Token; + ParserCopy(&PreState, Parser); + Token = LexGetToken(Parser, &LexerValue, TRUE); + switch (Token) { + case TokenEOF: + return ParseResultEOF; + case TokenIdentifier: + /* might be a typedef-typed variable declaration or it might be an expression */ + if (VariableDefined(LexerValue->Val->Identifier)) { + VariableGet(Parser, LexerValue->Val->Identifier, &VarValue); + if (VarValue->Typ->Base == Type_Type) { + *Parser = PreState; + ParseDeclaration(Parser, Token); + break; + } + } else { + /* it might be a goto label */ + enum LexToken NextToken = LexGetToken(Parser, NULL, FALSE); + if (NextToken == TokenColon) { + /* declare the identifier as a goto label */ + LexGetToken(Parser, NULL, TRUE); + if ( Parser->Mode == RunModeGoto + && LexerValue->Val->Identifier == Parser->SearchGotoLabel) { + Parser->Mode = RunModeRun; + } + CheckTrailingSemicolon = FALSE; + break; + } + } + /* else fallthrough to expression */ + + case TokenAsterisk: + case TokenAmpersand: + case TokenIncrement: + case TokenDecrement: + case TokenOpenBracket: + *Parser = PreState; + ExpressionParse(Parser, &CValue); + if (Parser->Mode == RunModeRun) { + VariableStackPop(Parser, CValue); + } + break; + + case TokenLeftBrace: + ParseBlock(Parser, FALSE, TRUE); + CheckTrailingSemicolon = FALSE; + break; + + case TokenIf: + if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) { + ProgramFail(Parser, "'(' expected"); + } + Condition = ExpressionParseInt(Parser); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + if (LexGetToken(Parser, NULL, FALSE) == TokenElse) { + LexGetToken(Parser, NULL, TRUE); + if (ParseStatementMaybeRun(Parser, !Condition, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + } + CheckTrailingSemicolon = FALSE; + break; + case TokenWhile: + { + struct ParseState PreConditional; + enum RunMode PreMode = Parser->Mode; + if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) { + ProgramFail(Parser, "'(' expected"); + } + ParserCopyPos(&PreConditional, Parser); + do { + ParserCopyPos(Parser, &PreConditional); + Condition = ExpressionParseInt(Parser); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + if (Parser->Mode == RunModeContinue) { + Parser->Mode = PreMode; + } + } while (Parser->Mode == RunModeRun && Condition); + + if (Parser->Mode == RunModeBreak) { + Parser->Mode = PreMode; + } + CheckTrailingSemicolon = FALSE; + } + break; + case TokenDo: + { + struct ParseState PreStatement; + enum RunMode PreMode = Parser->Mode; + ParserCopyPos(&PreStatement, Parser); + do { + ParserCopyPos(Parser, &PreStatement); + if (ParseStatement(Parser, TRUE) != ParseResultOk) { + ProgramFail(Parser, "statement expected"); + } + if (Parser->Mode == RunModeContinue) { + Parser->Mode = PreMode; + } + if (LexGetToken(Parser, NULL, TRUE) != TokenWhile) { + ProgramFail(Parser, "'while' expected"); + } + if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) { + ProgramFail(Parser, "'(' expected"); + } + Condition = ExpressionParseInt(Parser); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + } while ( Condition + && Parser->Mode == RunModeRun); + if (Parser->Mode == RunModeBreak) { + Parser->Mode = PreMode; + } + } + break; + case TokenFor: + ParseFor(Parser); + CheckTrailingSemicolon = FALSE; + break; + case TokenSemicolon: + CheckTrailingSemicolon = FALSE; + break; + case TokenIntType: + case TokenShortType: + case TokenCharType: + case TokenLongType: + case TokenFloatType: + case TokenDoubleType: + case TokenVoidType: + case TokenStructType: + case TokenUnionType: + case TokenEnumType: + case TokenSignedType: + case TokenUnsignedType: + case TokenStaticType: + case TokenAutoType: + case TokenRegisterType: + case TokenExternType: + *Parser = PreState; + CheckTrailingSemicolon = ParseDeclaration(Parser, Token); + break; + case TokenHashDefine: + ParseMacroDefinition(Parser); + CheckTrailingSemicolon = FALSE; + break; +#ifndef NO_HASH_INCLUDE + case TokenHashInclude: + if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant) { + ProgramFail(Parser, "\"filename.h\" expected"); + } + IncludeFile((char *)LexerValue->Val->Pointer); + CheckTrailingSemicolon = FALSE; + break; +#endif + case TokenSwitch: + if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) { + ProgramFail(Parser, "'(' expected"); + } + Condition = ExpressionParseInt(Parser); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace) { + ProgramFail(Parser, "'{' expected"); + } + { + /* new block so we can store parser state */ + enum RunMode OldMode = Parser->Mode; + int OldSearchLabel = Parser->SearchLabel; + Parser->Mode = RunModeCaseSearch; + Parser->SearchLabel = Condition; + ParseBlock(Parser, TRUE, OldMode != RunModeSkip); + if (Parser->Mode != RunModeReturn) { + Parser->Mode = OldMode; + } + Parser->SearchLabel = OldSearchLabel; + } + CheckTrailingSemicolon = FALSE; + break; + case TokenCase: + if (Parser->Mode == RunModeCaseSearch) { + Parser->Mode = RunModeRun; + Condition = ExpressionParseInt(Parser); + Parser->Mode = RunModeCaseSearch; + } else { + Condition = ExpressionParseInt(Parser); + } + if (LexGetToken(Parser, NULL, TRUE) != TokenColon) { + ProgramFail(Parser, "':' expected"); + } + if (Parser->Mode == RunModeCaseSearch && Condition == Parser->SearchLabel) { + Parser->Mode = RunModeRun; + } + CheckTrailingSemicolon = FALSE; + break; + case TokenDefault: + if (LexGetToken(Parser, NULL, TRUE) != TokenColon) { + ProgramFail(Parser, "':' expected"); + } + if (Parser->Mode == RunModeCaseSearch) { + Parser->Mode = RunModeRun; + } + CheckTrailingSemicolon = FALSE; + break; + case TokenBreak: + if (Parser->Mode == RunModeRun) { + Parser->Mode = RunModeBreak; + } + break; + case TokenContinue: + if (Parser->Mode == RunModeRun) { + Parser->Mode = RunModeContinue; + } + break; + case TokenReturn: + if (Parser->Mode == RunModeRun) { + if (TopStackFrame->ReturnValue->Typ->Base != TypeVoid) { + if (!ExpressionParse(Parser, &CValue)) { + ProgramFail(Parser, "value required in return"); + } + ExpressionAssign(Parser, TopStackFrame->ReturnValue, CValue, TRUE, NULL, 0, FALSE); + VariableStackPop(Parser, CValue); + } else { + if (ExpressionParse(Parser, &CValue)) { + ProgramFail(Parser, "value in return from a void function"); + } + } + Parser->Mode = RunModeReturn; + } else { + ExpressionParse(Parser, &CValue); + } + break; + case TokenTypedef: + ParseTypedef(Parser); + break; + case TokenGoto: + if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) { + ProgramFail(Parser, "identifier expected"); + } + if (Parser->Mode == RunModeRun) { + /* start scanning for the goto label */ + Parser->SearchGotoLabel = LexerValue->Val->Identifier; + Parser->Mode = RunModeGoto; + } + break; + case TokenDelete: + { + /* try it as a function or variable name to delete */ + if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) { + ProgramFail(Parser, "identifier expected"); + } + if (Parser->Mode == RunModeRun) { + /* delete this variable or function */ + CValue = TableDelete(&GlobalTable, LexerValue->Val->Identifier); + if (CValue == NULL) { + ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier); + } + VariableFree(CValue); + } + break; + } + default: + *Parser = PreState; + return ParseResultError; + } + if (CheckTrailingSemicolon) { + if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) { + ProgramFail(Parser, "';' expected"); + } + } + return ParseResultOk; +} + +/* quick scan a source file for definitions */ +void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource) { + struct ParseState Parser; + enum ParseResult Ok; + struct CleanupTokenNode *NewCleanupNode; + void *Tokens = LexAnalyse(FileName, Source, SourceLen, NULL); + /* allocate a cleanup node so we can clean up the tokens later */ + if (!CleanupNow) { + NewCleanupNode = HeapAllocMem(sizeof(struct CleanupTokenNode)); + if (NewCleanupNode == NULL) { + ProgramFail(NULL, "out of memory"); + } + NewCleanupNode->Tokens = Tokens; + if (CleanupSource) { + NewCleanupNode->SourceText = Source; + } else { + NewCleanupNode->SourceText = NULL; + } + NewCleanupNode->Next = CleanupTokenList; + CleanupTokenList = NewCleanupNode; + } + /* do the parsing */ + LexInitParser(&Parser, Source, Tokens, FileName, RunIt); + do { + Ok = ParseStatement(&Parser, TRUE); + } while (Ok == ParseResultOk); + if (Ok == ParseResultError) { + ProgramFail(&Parser, "parse error"); + } + /* clean up */ + if (CleanupNow) { + HeapFreeMem(Tokens); + } +} + +/* parse interactively */ +void PicocParseInteractive() { + struct ParseState Parser; + enum ParseResult Ok; + PlatformPrintf(INTERACTIVE_PROMPT_START); + LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE); + PicocPlatformSetExitPoint(); + LexInteractiveClear(&Parser); + do { + LexInteractiveStatementPrompt(); + Ok = ParseStatement(&Parser, TRUE); + LexInteractiveCompleted(&Parser); + } while (Ok == ParseResultOk); + if (Ok == ParseResultError) { + ProgramFail(&Parser, "parse error"); + } + PlatformPrintf("\n"); +} diff --git a/eci/picoc.c b/eci/picoc.c new file mode 100644 index 0000000..39f2372 --- /dev/null +++ b/eci/picoc.c @@ -0,0 +1,45 @@ +/* include only picoc.h here - should be able to use it with only the external interfaces, no internals from interpreter.h */ +#include "picoc.h" + +/* platform-dependent code for running programs is in this file */ + +#include +#include +#include + +#define PICOC_STACK_SIZE (128*1024) /* space for the the stack */ + +int main(int argc, char **argv) { + int ParamCount = 1; + int DontRunMain = FALSE; + int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE; + if (argc < 2) { + printf("Format: picoc ... [- ...] : run a program (calls main() to start it)\n" + " picoc -s ... [- ...] : script mode - runs the program without calling main()\n" + " picoc -i : interactive mode\n"); + exit(1); + } + PicocInitialise(StackSize); + if (strcmp(argv[ParamCount], "-s") == 0 || strcmp(argv[ParamCount], "-m") == 0) { + DontRunMain = TRUE; + PicocIncludeAllSystemHeaders(); + ParamCount++; + } + if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0) { + PicocIncludeAllSystemHeaders(); + PicocParseInteractive(); + } else { + if (PicocPlatformSetExitPoint()) { + PicocCleanup(); + return PicocExitValue; + } + for (; ParamCount < argc && strcmp(argv[ParamCount], "-") != 0; ParamCount++) { + PicocPlatformScanFile(argv[ParamCount]); + } + if (!DontRunMain) { + PicocCallMain(argc - ParamCount, &argv[ParamCount]); + } + } + PicocCleanup(); + return PicocExitValue; +} diff --git a/ecilib/picoc.h b/eci/picoc.h similarity index 80% rename from ecilib/picoc.h rename to eci/picoc.h index f5cd852..c9423ca 100644 --- a/ecilib/picoc.h +++ b/eci/picoc.h @@ -11,7 +11,6 @@ #endif -#ifdef UNIX_HOST #include /* mark where to end the program for platforms which require this */ @@ -19,14 +18,6 @@ extern jmp_buf PicocExitBuf; /* this has to be a macro, otherwise errors will occur due to the stack being corrupt */ #define PicocPlatformSetExitPoint() setjmp(PicocExitBuf) -#endif - -#ifdef SURVEYOR_HOST -/* mark where to end the program for platforms which require this */ -extern int PicocExitBuf[]; - -#define PicocPlatformSetExitPoint() setjmp(PicocExitBuf) -#endif /* parse.c */ void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource); diff --git a/eci/platform.c b/eci/platform.c new file mode 100644 index 0000000..d6439e9 --- /dev/null +++ b/eci/platform.c @@ -0,0 +1,215 @@ +#include "picoc.h" +#include "interpreter.h" + +/* the value passed to exit() */ +int PicocExitValue = 0; + +/* initialise everything */ +void PicocInitialise(int StackSize) { + BasicIOInit(); + HeapInit(StackSize); + TableInit(); + VariableInit(); + LexInit(); + TypeInit(); +#ifndef NO_HASH_INCLUDE + IncludeInit(); +#endif + LibraryInit(); +#ifdef BUILTIN_MINI_STDLIB + LibraryAdd(&GlobalTable, "c library", &CLibrary[0]); + CLibraryInit(); +#endif + PlatformLibraryInit(); +} + +/* free memory */ +void PicocCleanup() +{ + PlatformCleanup(); +#ifndef NO_HASH_INCLUDE + IncludeCleanup(); +#endif + ParseCleanup(); + LexCleanup(); + VariableCleanup(); + TypeCleanup(); + TableStrFree(); + HeapCleanup(); +} + +/* platform-dependent code for running programs */ + +#define CALL_MAIN_NO_ARGS_RETURN_VOID "main();" +#define CALL_MAIN_WITH_ARGS_RETURN_VOID "main(__argc,__argv);" +#define CALL_MAIN_NO_ARGS_RETURN_INT "__exit_value = main();" +#define CALL_MAIN_WITH_ARGS_RETURN_INT "__exit_value = main(__argc,__argv);" + +void PicocCallMain(int argc, char **argv) { + /* check if the program wants arguments */ + struct Value *FuncValue = NULL; + if (!VariableDefined(TableStrRegister("main"))) { + ProgramFail(NULL, "main() is not defined"); + } + VariableGet(NULL, TableStrRegister("main"), &FuncValue); + if (FuncValue->Typ->Base != TypeFunction) { + ProgramFail(NULL, "main is not a function - can't call it"); + } + if (FuncValue->Val->FuncDef.NumParams != 0) { + /* define the arguments */ + VariableDefinePlatformVar(NULL, "__argc", &IntType, (union AnyValue *)&argc, FALSE); + VariableDefinePlatformVar(NULL, "__argv", CharPtrPtrType, (union AnyValue *)&argv, FALSE); + } + if (FuncValue->Val->FuncDef.ReturnType == &VoidType) { + if (FuncValue->Val->FuncDef.NumParams == 0) { + PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); + } else { + PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); + } + } else { + VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE); + if (FuncValue->Val->FuncDef.NumParams == 0) { + PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE); + } else { + PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE); + } + } +} + +void PrintSourceTextErrorLine(const char *FileName, const char *SourceText, int Line, int CharacterPos) { + int LineCount; + const char *LinePos; + const char *CPos; + int CCount; + if (SourceText != NULL) { + /* find the source line */ + for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++) { + if (*LinePos == '\n') { + LineCount++; + } + } + /* display the line */ + for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++) { + PrintCh(*CPos, CStdOut); + } + PrintCh('\n', CStdOut); + /* display the error position */ + for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) { + if (*CPos == '\t') { + PrintCh('\t', CStdOut); + } else { + PrintCh(' ', CStdOut); + } + } + } else { + /* assume we're in interactive mode - try to make the arrow match up with the input text */ + for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++) { + PrintCh(' ', CStdOut); + } + } + PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos); +} + +/* display the source line and line number to identify an error */ +void PlatformErrorPrefix(struct ParseState *Parser) { + if (Parser != NULL) { + PrintSourceTextErrorLine(Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); + } +} + +/* exit with a message */ +void ProgramFail(struct ParseState *Parser, const char *Message, ...) { + va_list Args; + PlatformErrorPrefix(Parser); + va_start(Args, Message); + PlatformVPrintf(Message, Args); + va_end(Args); + PlatformPrintf("\n"); + PlatformExit(1); +} + +/* like ProgramFail() but gives descriptive error messages for assignment */ +void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo) { + PlatformErrorPrefix(Parser); + PlatformPrintf("can't %s ", (FuncName == NULL) ? "assign" : "set"); + if (Type1 != NULL) { + PlatformPrintf(Format, Type1, Type2); + } else { + PlatformPrintf(Format, Num1, Num2); + } + if (FuncName != NULL) { + PlatformPrintf(" in argument %d of call to %s()", ParamNo, FuncName); + } + ProgramFail(NULL, ""); +} + +/* exit lexing with a message */ +void LexFail(struct LexState *Lexer, const char *Message, ...) { + va_list Args; + PrintSourceTextErrorLine(Lexer->FileName, Lexer->SourceText, Lexer->Line, Lexer->CharacterPos); + va_start(Args, Message); + PlatformVPrintf(Message, Args); + va_end(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 *), CStdOut); + break; + case 'd': + PrintSimpleInt(va_arg(Args, int), CStdOut); + break; + case 'c': + PrintCh(va_arg(Args, int), CStdOut); + break; + case 't': + PrintType(va_arg(Args, struct ValueType *), CStdOut); + break; +#ifndef NO_FP + case 'f': + PrintFP(va_arg(Args, double), CStdOut); + break; +#endif + case '%': + PrintCh('%', CStdOut); + break; + case '\0': + FPos--; + break; + } + } else { + PrintCh(*FPos, CStdOut); + } + } +} + +/* make a new temporary name. takes a static buffer of char [7] as a parameter. should be initialised to "XX0000" + * where XX can be any characters */ +char *PlatformMakeTempName(char *TempNameBuffer) { + int CPos = 5; + while (CPos > 1) { + if (TempNameBuffer[CPos] < '9') { + TempNameBuffer[CPos]++; + return TableStrRegister(TempNameBuffer); + } else { + TempNameBuffer[CPos] = '0'; + CPos--; + } + } + return TableStrRegister(TempNameBuffer); +} diff --git a/eci/platform.h b/eci/platform.h new file mode 100644 index 0000000..aca8bcc --- /dev/null +++ b/eci/platform.h @@ -0,0 +1,43 @@ +/* all platform-specific includes and defines go in this file */ +#ifndef PLATFORM_H +#define PLATFORM_H + +#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */ +#define ALIGN_TYPE void * /* the default data type to use for alignment */ + +#define GLOBAL_TABLE_SIZE 97 /* global variable table */ +#define STRING_TABLE_SIZE 97 /* shared string table size */ +#define STRING_LITERAL_TABLE_SIZE 97 /* string literal 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) */ + +#define INTERACTIVE_PROMPT_START "starting picoc " PICOC_VERSION "\n" +#define INTERACTIVE_PROMPT_STATEMENT "picoc> " +#define INTERACTIVE_PROMPT_LINE " > " + +/* host platform includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef NO_FP +# include +# define PICOC_MATH_LIBRARY +/*# define USE_READLINE*/ +# undef BIG_ENDIAN +# if defined(__powerpc__) || defined(__hppa__) || defined(__sparc__) +# define BIG_ENDIAN +# endif +#endif + +extern jmp_buf ExitBuf; + +#endif /* PLATFORM_H */ diff --git a/ecilib/platform/library_ffox.c b/eci/platform/library_ffox.c similarity index 100% rename from ecilib/platform/library_ffox.c rename to eci/platform/library_ffox.c diff --git a/ecilib/platform/library_srv1.c b/eci/platform/library_srv1.c similarity index 100% rename from ecilib/platform/library_srv1.c rename to eci/platform/library_srv1.c diff --git a/ecilib/platform/library_surveyor.c b/eci/platform/library_surveyor.c similarity index 100% rename from ecilib/platform/library_surveyor.c rename to eci/platform/library_surveyor.c diff --git a/eci/platform/library_unix.c b/eci/platform/library_unix.c new file mode 100644 index 0000000..8726580 --- /dev/null +++ b/eci/platform/library_unix.c @@ -0,0 +1,25 @@ +#include "../interpreter.h" + +void UnixSetupFunc() { + +} + +void Ctest (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + printf("test(%d)\n", Param[0]->Val->Integer); + Param[0]->Val->Integer = 1234; +} + +void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { + ReturnValue->Val->Integer = Parser->Line; +} + +/* list of all library functions and their prototypes */ +struct LibraryFunction UnixFunctions[] = { + { Ctest, "void test(int);" }, + { Clineno, "int lineno();" }, + { NULL, NULL } +}; + +void PlatformLibraryInit() { + IncludeRegister("picoc_unix.h", &UnixSetupFunc, &UnixFunctions[0], NULL); +} diff --git a/ecilib/platform/platform_ffox.c b/eci/platform/platform_ffox.c similarity index 100% rename from ecilib/platform/platform_ffox.c rename to eci/platform/platform_ffox.c diff --git a/ecilib/platform/platform_surveyor.c b/eci/platform/platform_surveyor.c similarity index 100% rename from ecilib/platform/platform_surveyor.c rename to eci/platform/platform_surveyor.c diff --git a/eci/platform/platform_unix.c b/eci/platform/platform_unix.c new file mode 100644 index 0000000..e677a8e --- /dev/null +++ b/eci/platform/platform_unix.c @@ -0,0 +1,89 @@ +#include "../picoc.h" +#include "../interpreter.h" + +#ifdef USE_READLINE +#include +#include +#endif + +/* mark where to end the program for platforms which require this */ +jmp_buf PicocExitBuf; + +void PlatformCleanup() { + +} + +/* get a line of interactive input */ +char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt) { +#ifdef USE_READLINE + if (Prompt != NULL) { + /* use GNU readline to read the line */ + char *InLine = readline(Prompt); + if (InLine == NULL) { + return NULL; + } + Buf[MaxLen] = '\0'; + strncpy(Buf, InLine, MaxLen-1); + strncat(Buf, "\n", MaxLen-1); + if (InLine[0] != '\0') { + add_history(InLine); + } + free(InLine); + return Buf; + } +#endif + if (Prompt != NULL) { + printf("%s", Prompt); + } + fflush(stdout); + return fgets(Buf, MaxLen, stdin); +} + +/* get a character of interactive input */ +int PlatformGetCharacter() { + fflush(stdout); + return getchar(); +} + +/* write a character to the console */ +void PlatformPutc(unsigned char OutCh, union OutputStreamInfo *Stream) { + 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 PicocPlatformScanFile(const char *FileName) { + char *SourceStr = PlatformReadFile(FileName); + PicocParse(FileName, SourceStr, strlen(SourceStr), TRUE, FALSE, TRUE); +} + +/* exit the program */ +void PlatformExit(int RetVal) { + PicocExitValue = RetVal; + longjmp(PicocExitBuf, 1); +} diff --git a/eci/table.c b/eci/table.c new file mode 100644 index 0000000..0db4969 --- /dev/null +++ b/eci/table.c @@ -0,0 +1,156 @@ +#include "interpreter.h" + +struct Table StringTable; +struct TableEntry *StringHashTable[STRING_TABLE_SIZE]; +char *StrEmpty = NULL; + +/* initialise the shared string system */ +void TableInit() { + TableInitTable(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE); + StrEmpty = TableStrRegister(""); +} + +/* hash function for strings */ +static unsigned int TableHash(const char *Key, int Len) { + unsigned int Hash = Len; + int Offset; + int Count; + for (Count = 0, Offset = 8; Count < Len; Count++, Offset+=7) { + if (Offset > sizeof(unsigned int) * 8 - 7) { + Offset -= sizeof(unsigned int) * 8 - 6; + } + Hash ^= *Key++ << Offset; + } + return Hash; +} + +/* initialise a table */ +void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap) { + Tbl->Size = Size; + Tbl->OnHeap = OnHeap; + Tbl->HashTable = HashTable; + memset((void *)HashTable, '\0', sizeof(struct TableEntry *) * Size); +} + +/* check a hash table entry for a key */ +static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *AddAt) { + struct TableEntry *Entry; + int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ + for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) { + if (Entry->p.v.Key == Key) { + return Entry; /* found */ + } + } + *AddAt = HashValue; /* didn't find it in the chain */ + return NULL; +} + +/* set an identifier to a value. returns FALSE if it already exists. + * Key must be a shared string from TableStrRegister() */ +int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn) { + int AddAt; + struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); + if (FoundEntry == NULL) { + /* add it to the table */ + struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap); + NewEntry->DeclFileName = DeclFileName; + NewEntry->DeclLine = DeclLine; + NewEntry->DeclColumn = DeclColumn; + NewEntry->p.v.Key = Key; + NewEntry->p.v.Val = Val; + NewEntry->Next = Tbl->HashTable[AddAt]; + Tbl->HashTable[AddAt] = NewEntry; + return TRUE; + } + return FALSE; +} + +/* find a value in a table. returns FALSE if not found. + * Key must be a shared string from TableStrRegister() */ +int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn) { + int AddAt; + struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); + if (FoundEntry == NULL) { + return FALSE; + } + *Val = FoundEntry->p.v.Val; + if (DeclFileName != NULL) { + *DeclFileName = FoundEntry->DeclFileName; + *DeclLine = FoundEntry->DeclLine; + *DeclColumn = FoundEntry->DeclColumn; + } + return TRUE; +} + +/* remove an entry from the table */ +struct Value *TableDelete(struct Table *Tbl, const char *Key) { + struct TableEntry **EntryPtr; + int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ + for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) { + if ((*EntryPtr)->p.v.Key == Key) { + struct TableEntry *DeleteEntry = *EntryPtr; + struct Value *Val = DeleteEntry->p.v.Val; + *EntryPtr = DeleteEntry->Next; + HeapFreeMem(DeleteEntry); + return Val; + } + } + return NULL; +} + +/* check a hash table entry for an identifier */ +static struct TableEntry *TableSearchIdentifier(struct Table *Tbl, const char *Key, int Len, int *AddAt) { + struct TableEntry *Entry; + int HashValue = TableHash(Key, Len) % Tbl->Size; + for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) { + if (strncmp(&Entry->p.Key[0], (char *)Key, Len) == 0 && Entry->p.Key[Len] == '\0') { + // found + return Entry; + } + } + *AddAt = HashValue; /* didn't find it in the chain */ + return NULL; +} + +/* set an identifier and return the identifier. share if possible */ +char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen) { + int AddAt; + struct TableEntry *FoundEntry = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt); + if (FoundEntry != NULL) { + return &FoundEntry->p.Key[0]; + } else { + //add it to the table - we economise by not allocating the whole structure here + struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1); + if (NewEntry == NULL) { + ProgramFail(NULL, "out of memory"); + } + strncpy((char *)&NewEntry->p.Key[0], (char *)Ident, IdentLen); + NewEntry->p.Key[IdentLen] = '\0'; + NewEntry->Next = Tbl->HashTable[AddAt]; + Tbl->HashTable[AddAt] = NewEntry; + return &NewEntry->p.Key[0]; + } + return NULL; +} + +/* register a string in the shared string store */ +char *TableStrRegister2(const char *Str, int Len) { + return TableSetIdentifier(&StringTable, Str, Len); +} + +char *TableStrRegister(const char *Str) { + return TableStrRegister2(Str, strlen((char *)Str)); +} + +/* free all the strings */ +void TableStrFree() { + struct TableEntry *Entry; + struct TableEntry *NextEntry; + int Count; + for (Count = 0; Count < StringTable.Size; Count++) { + for (Entry = StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) { + NextEntry = Entry->Next; + HeapFreeMem(Entry); + } + } +} diff --git a/eci/type.c b/eci/type.c new file mode 100644 index 0000000..402ab7b --- /dev/null +++ b/eci/type.c @@ -0,0 +1,521 @@ +#include "interpreter.h" + +/* some basic types */ +struct ValueType UberType; +struct ValueType IntType; +struct ValueType ShortType; +struct ValueType CharType; +struct ValueType LongType; +struct ValueType UnsignedIntType; +struct ValueType UnsignedShortType; +struct ValueType UnsignedLongType; +#ifndef NO_FP +struct ValueType FPType; +#endif +struct ValueType VoidType; +struct ValueType TypeType; +struct ValueType FunctionType; +struct ValueType MacroType; +struct ValueType EnumType; +struct ValueType GotoLabelType; +struct ValueType *CharPtrType; +struct ValueType *CharPtrPtrType; +struct ValueType *CharArrayType; +struct ValueType *VoidPtrType; + +static int PointerAlignBytes; +static int IntAlignBytes; + +/* add a new type to the set of types we know about */ +struct ValueType *TypeAdd(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int Sizeof, int AlignBytes) { + struct ValueType *NewType = VariableAlloc(Parser, sizeof(struct ValueType), TRUE); + NewType->Base = Base; + NewType->ArraySize = ArraySize; + NewType->Sizeof = Sizeof; + NewType->AlignBytes = AlignBytes; + NewType->Identifier = Identifier; + NewType->Members = NULL; + NewType->FromType = ParentType; + NewType->DerivedTypeList = NULL; + NewType->OnHeap = TRUE; + NewType->Next = ParentType->DerivedTypeList; + ParentType->DerivedTypeList = NewType; + return NewType; +} + +/* given a parent type, get a matching derived type and make one if necessary. + * Identifier should be registered with the shared string table. */ +struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates) { + int Sizeof; + int AlignBytes; + struct ValueType *ThisType = ParentType->DerivedTypeList; + while ( ThisType != NULL + && ( ThisType->Base != Base + || ThisType->ArraySize != ArraySize + || ThisType->Identifier != Identifier) ) { + ThisType = ThisType->Next; + } + if (ThisType != NULL) { + if (AllowDuplicates) { + return ThisType; + } else { + ProgramFail(Parser, "data type '%s' is already defined", Identifier); + } + } + switch (Base) { + case TypePointer: + Sizeof = sizeof(void *); + AlignBytes = PointerAlignBytes; + break; + case TypeArray: + Sizeof = ArraySize * ParentType->Sizeof; + AlignBytes = ParentType->AlignBytes; + break; + case TypeEnum: + Sizeof = sizeof(int); + AlignBytes = IntAlignBytes; + break; + default: + Sizeof = 0; + AlignBytes = 0; + break; + /* structs and unions will get bigger when we add members to them */ + } + return TypeAdd(Parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes); +} + +/* stack space used by a value */ +int TypeStackSizeValue(struct Value *Val) { + if (Val != NULL && Val->ValOnStack) { + return TypeSizeValue(Val, FALSE); + } else { + return 0; + } +} + +/* memory used by a value */ +int TypeSizeValue(struct Value *Val, int Compact) { + if (IS_INTEGER_NUMERIC(Val) && !Compact) { + return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */ + } else if (Val->Typ->Base != TypeArray) { + return Val->Typ->Sizeof; + } else { + return Val->Typ->FromType->Sizeof * Val->Typ->ArraySize; + } +} + +/* memory used by a variable given its type and array size */ +int TypeSize(struct ValueType *Typ, int ArraySize, int Compact) { + if (IS_INTEGER_NUMERIC_TYPE(Typ) && !Compact) { + return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */ + } else if (Typ->Base != TypeArray) { + return Typ->Sizeof; + } else { + return Typ->FromType->Sizeof * ArraySize; + } +} + +/* add a base type */ +void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof, int AlignBytes) { + TypeNode->Base = Base; + TypeNode->ArraySize = 0; + TypeNode->Sizeof = Sizeof; + TypeNode->AlignBytes = AlignBytes; + TypeNode->Identifier = StrEmpty; + TypeNode->Members = NULL; + TypeNode->FromType = NULL; + TypeNode->DerivedTypeList = NULL; + TypeNode->OnHeap = FALSE; + TypeNode->Next = UberType.DerivedTypeList; + UberType.DerivedTypeList = TypeNode; +} + +/* initialise the type system */ +void TypeInit() { + struct IntAlign { + char x; + int y; + } ia; + struct ShortAlign { + char x; + short y; + } sa; + struct CharAlign { + char x; + char y; + } ca; + struct LongAlign { + char x; + long y; + } la; +#ifndef NO_FP + struct DoubleAlign { + char x; + double y; + } da; +#endif + struct PointerAlign { + char x; + void *y; + } pa; + + IntAlignBytes = (char *)&ia.y - &ia.x; + PointerAlignBytes = (char *)&pa.y - &pa.x; + + UberType.DerivedTypeList = NULL; + TypeAddBaseType(&IntType, TypeInt, sizeof(int), IntAlignBytes); + TypeAddBaseType(&ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x); + TypeAddBaseType(&CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x); + TypeAddBaseType(&LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x); + TypeAddBaseType(&UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes); + TypeAddBaseType(&UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x); + TypeAddBaseType(&UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x); + TypeAddBaseType(&VoidType, TypeVoid, 0, 1); + TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int), IntAlignBytes); + TypeAddBaseType(&MacroType, TypeMacro, sizeof(int), IntAlignBytes); + TypeAddBaseType(&GotoLabelType, TypeGotoLabel, 0, 1); +#ifndef NO_FP + TypeAddBaseType(&FPType, TypeFP, sizeof(double), (char *)&da.y - &da.x); + TypeAddBaseType(&TypeType, Type_Type, sizeof(double), (char *)&da.y - &da.x); /* must be large enough to cast to a double */ +#else + TypeAddBaseType(&TypeType, Type_Type, sizeof(struct ValueType *), PointerAlignBytes); +#endif + CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char), (char *)&ca.y - &ca.x); + CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); + CharPtrPtrType = TypeAdd(NULL, CharPtrType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); + VoidPtrType = TypeAdd(NULL, &VoidType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); +} + +/* deallocate heap-allocated types */ +void TypeCleanupNode(struct ValueType *Typ) { + struct ValueType *SubType; + struct ValueType *NextSubType; + /* clean up and free all the sub-nodes */ + for (SubType = Typ->DerivedTypeList; SubType != NULL; SubType = NextSubType) { + NextSubType = SubType->Next; + TypeCleanupNode(SubType); + if (SubType->OnHeap) { + /* if it's a struct or union deallocate all the member values */ + if (SubType->Members != NULL) { + VariableTableCleanup(SubType->Members); + HeapFreeMem(SubType->Members); + } + /* free this node */ + HeapFreeMem(SubType); + } + } +} + +void TypeCleanup() { + TypeCleanupNode(&UberType); +} + +/* parse a struct or union declaration */ +void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct) { + struct Value *LexValue; + struct ValueType *MemberType; + char *MemberIdentifier; + char *StructIdentifier; + struct Value *MemberValue; + enum LexToken Token; + int AlignBoundary; + Token = LexGetToken(Parser, &LexValue, FALSE); + if (Token == TokenIdentifier) { + LexGetToken(Parser, &LexValue, TRUE); + StructIdentifier = LexValue->Val->Identifier; + Token = LexGetToken(Parser, NULL, FALSE); + } else { + static char TempNameBuf[7] = "^s0000"; + StructIdentifier = PlatformMakeTempName(TempNameBuf); + } + *Typ = TypeGetMatching(Parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, Token != TokenLeftBrace); + Token = LexGetToken(Parser, NULL, FALSE); + if (Token != TokenLeftBrace) { + /* use the already defined structure */ + if ((*Typ)->Members == NULL) { + ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier); + } + return; + } + if (TopStackFrame != NULL) { + ProgramFail(Parser, "struct/union definitions can only be globals"); + } + LexGetToken(Parser, NULL, TRUE); + (*Typ)->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); + (*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)); + TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); + do { + TypeParse(Parser, &MemberType, &MemberIdentifier, NULL); + if (MemberType == NULL || MemberIdentifier == NULL) { + ProgramFail(Parser, "invalid type in struct"); + } + MemberValue = VariableAllocValueAndData(Parser, sizeof(int), FALSE, NULL, TRUE); + MemberValue->Typ = MemberType; + if (IsStruct) { + /* allocate this member's location in the struct */ + AlignBoundary = MemberValue->Typ->AlignBytes; + if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) { + (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); + } + MemberValue->Val->Integer = (*Typ)->Sizeof; + (*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE); + } else { + /* union members always start at 0, make sure it's big enough to hold the largest member */ + MemberValue->Val->Integer = 0; + if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof) { + (*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE); + } + } + /* make sure to align to the size of the largest member's alignment */ + if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes) { + (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes; + } + /* define it */ + if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos)) { + ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier); + } + if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) { + ProgramFail(Parser, "semicolon expected"); + } + } while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace); + /* now align the structure to the size of its largest member's alignment */ + AlignBoundary = (*Typ)->AlignBytes; + if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) { + (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); + } + LexGetToken(Parser, NULL, TRUE); +} + +/* create a system struct which has no user-visible members */ +struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size) { + struct ValueType *Typ = TypeGetMatching(Parser, &UberType, TypeStruct, 0, StructName, FALSE); + /* create the (empty) table */ + Typ->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); + Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)); + TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); + Typ->Sizeof = Size; + return Typ; +} + +/* parse an enum declaration */ +void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ) { + struct Value *LexValue; + struct Value InitValue; + enum LexToken Token; + struct ValueType *EnumType; + int EnumValue = 0; + char *EnumIdentifier; + Token = LexGetToken(Parser, &LexValue, FALSE); + if (Token == TokenIdentifier) { + LexGetToken(Parser, &LexValue, TRUE); + EnumIdentifier = LexValue->Val->Identifier; + Token = LexGetToken(Parser, NULL, FALSE); + } else { + static char TempNameBuf[7] = "^e0000"; + EnumIdentifier = PlatformMakeTempName(TempNameBuf); + } + EnumType = TypeGetMatching(Parser, &UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace); + *Typ = &IntType; + if (Token != TokenLeftBrace) { + /* use the already defined enum */ + if ((*Typ)->Members == NULL) { + ProgramFail(Parser, "enum '%s' isn't defined", EnumIdentifier); + } + return; + } + if (TopStackFrame != NULL) { + ProgramFail(Parser, "enum definitions can only be globals"); + } + LexGetToken(Parser, NULL, TRUE); + (*Typ)->Members = &GlobalTable; + memset((void *)&InitValue, '\0', sizeof(struct Value)); + InitValue.Typ = &IntType; + InitValue.Val = (union AnyValue *)&EnumValue; + do { + if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier) { + ProgramFail(Parser, "identifier expected"); + } + EnumIdentifier = LexValue->Val->Identifier; + if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) { + LexGetToken(Parser, NULL, TRUE); + EnumValue = ExpressionParseInt(Parser); + } + VariableDefine(Parser, EnumIdentifier, &InitValue, NULL, FALSE); + + Token = LexGetToken(Parser, NULL, TRUE); + if (Token != TokenComma && Token != TokenRightBrace) { + ProgramFail(Parser, "comma expected"); + } + EnumValue++; + } while (Token == TokenComma); +} + +/* parse a type - just the basic type */ +int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic) { + struct ParseState Before; + struct Value *LexerValue; + enum LexToken Token; + int Unsigned = FALSE; + struct Value *VarValue; + int StaticQualifier = FALSE; + *Typ = NULL; + /* ignore leading type qualifiers */ + ParserCopy(&Before, Parser); + Token = LexGetToken(Parser, &LexerValue, TRUE); + while ( Token == TokenStaticType + || Token == TokenAutoType + || Token == TokenRegisterType + || Token == TokenExternType) { + if (Token == TokenStaticType) { + StaticQualifier = TRUE; + } + Token = LexGetToken(Parser, &LexerValue, TRUE); + } + if (IsStatic != NULL) { + *IsStatic = StaticQualifier; + } + /* handle signed/unsigned with no trailing type */ + if (Token == TokenSignedType || Token == TokenUnsignedType) { + enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, FALSE); + Unsigned = (Token == TokenUnsignedType); + if ( FollowToken != TokenIntType + && FollowToken != TokenLongType + && FollowToken != TokenShortType + && FollowToken != TokenCharType) { + if (Token == TokenUnsignedType) { + *Typ = &UnsignedIntType; + } else { + *Typ = &IntType; + } + return TRUE; + } + Token = LexGetToken(Parser, &LexerValue, TRUE); + } + switch (Token) { + case TokenIntType: + *Typ = Unsigned ? &UnsignedIntType : &IntType; + break; + case TokenShortType: + *Typ = Unsigned ? &UnsignedShortType : &ShortType; + break; + case TokenCharType: + *Typ = &CharType; + break; + case TokenLongType: + *Typ = Unsigned ? &UnsignedLongType : &LongType; + break; +#ifndef NO_FP + case TokenFloatType: + case TokenDoubleType: + *Typ = &FPType; + break; +#endif + case TokenVoidType: + *Typ = &VoidType; + break; + case TokenStructType: + case TokenUnionType: + if (*Typ != NULL) { + ProgramFail(Parser, "bad type declaration"); + } + TypeParseStruct(Parser, Typ, Token == TokenStructType); + break; + case TokenEnumType: + if (*Typ != NULL) { + ProgramFail(Parser, "bad type declaration"); + } + TypeParseEnum(Parser, Typ); + break; + case TokenIdentifier: + /* we already know it's a typedef-defined type because we got here */ + VariableGet(Parser, LexerValue->Val->Identifier, &VarValue); + *Typ = VarValue->Val->Typ; + break; + default: + ParserCopy(Parser, &Before); + return FALSE; + } + return TRUE; +} + +/* parse a type - the part at the end after the identifier. eg. array specifications etc. */ +struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *FromType) { + enum LexToken Token; + struct ParseState Before; + ParserCopy(&Before, Parser); + Token = LexGetToken(Parser, NULL, TRUE); + if (Token == TokenLeftSquareBracket) { + /* add another array bound */ + enum RunMode OldMode = Parser->Mode; + int ArraySize; + Parser->Mode = RunModeRun; + ArraySize = ExpressionParseInt(Parser); + Parser->Mode = OldMode; + if (LexGetToken(Parser, NULL, TRUE) != TokenRightSquareBracket) { + ProgramFail(Parser, "']' expected"); + } + return TypeGetMatching(Parser, TypeParseBack(Parser, FromType), TypeArray, ArraySize, StrEmpty, TRUE); + } else { + /* the type specification has finished */ + ParserCopy(Parser, &Before); + return FromType; + } +} + +/* parse a type - the part which is repeated with each identifier in a declaration list */ +void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier) { + struct ParseState Before; + enum LexToken Token; + struct Value *LexValue; + int Done = FALSE; + *Typ = BasicTyp; + *Identifier = StrEmpty; + while (!Done) { + ParserCopy(&Before, Parser); + Token = LexGetToken(Parser, &LexValue, TRUE); + switch (Token) { + case TokenOpenBracket: + if (*Typ != NULL) { + ProgramFail(Parser, "bad type declaration"); + } + TypeParse(Parser, Typ, Identifier, NULL); + if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) { + ProgramFail(Parser, "')' expected"); + } + break; + case TokenAsterisk: + if (*Typ == NULL) { + ProgramFail(Parser, "bad type declaration"); + } + *Typ = TypeGetMatching(Parser, *Typ, TypePointer, 0, StrEmpty, TRUE); + break; + case TokenIdentifier: + if ( *Typ == NULL + || *Identifier != StrEmpty) { + ProgramFail(Parser, "bad type declaration"); + } + *Identifier = LexValue->Val->Identifier; + Done = TRUE; + break; + default: + ParserCopy(Parser, &Before); + Done = TRUE; + break; + } + } + if (*Typ == NULL) { + ProgramFail(Parser, "bad type declaration"); + } + if (*Identifier != StrEmpty) { + /* parse stuff after the identifier */ + *Typ = TypeParseBack(Parser, *Typ); + } +} + +/* parse a type - a complete declaration including identifier */ +void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic) { + struct ValueType *BasicType; + TypeParseFront(Parser, &BasicType, IsStatic); + TypeParseIdentPart(Parser, BasicType, Typ, Identifier); +} + diff --git a/eci/variable.c b/eci/variable.c new file mode 100644 index 0000000..fe8ac9a --- /dev/null +++ b/eci/variable.c @@ -0,0 +1,353 @@ +#include "interpreter.h" + +/* maximum size of a value to temporarily copy while we create a variable */ +#define MAX_TMP_COPY_BUF 256 + +/* the table of global definitions */ +struct Table GlobalTable; +struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE]; + +/* the table of string literal values */ +struct Table StringLiteralTable; +struct TableEntry *StringLiteralHashTable[STRING_LITERAL_TABLE_SIZE]; + +/* the stack */ +struct StackFrame *TopStackFrame = NULL; + + +/* initialise the variable system */ +void VariableInit() { + TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE); + TableInitTable(&StringLiteralTable, &StringLiteralHashTable[0], STRING_LITERAL_TABLE_SIZE, TRUE); + TopStackFrame = NULL; +} + +/* deallocate the contents of a variable */ +void VariableFree(struct Value *_value) { + if (_value->ValOnHeap) { + /* free function bodies */ + if ( _value->Typ == &FunctionType + && _value->Val->FuncDef.Intrinsic == NULL + && _value->Val->FuncDef.Body.Pos != NULL) { + HeapFreeMem((void *)_value->Val->FuncDef.Body.Pos); + } + /* free macro bodies */ + if (_value->Typ == &MacroType) { + HeapFreeMem((void *)_value->Val->MacroDef.Body.Pos); + } + /* free the value */ + HeapFreeMem(_value); + } +} + +/* deallocate the global table and the string literal table */ +void VariableTableCleanup(struct Table *_hashTable) { + struct TableEntry *Entry; + struct TableEntry *NextEntry; + int Count; + for (Count = 0; Count < _hashTable->Size; ++Count) { + for (Entry = _hashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) { + NextEntry = Entry->Next; + VariableFree(Entry->p.v.Val); + /* free the hash table entry */ + HeapFreeMem(Entry); + } + } +} + +void VariableCleanup() { + VariableTableCleanup(&GlobalTable); + VariableTableCleanup(&StringLiteralTable); +} + +/* allocate some memory, either on the heap or the stack and check if we've run out */ +void *VariableAlloc(struct ParseState *_parser, + int _size, + int _onHeap) { + void *NewValue; + if (_onHeap) { + NewValue = HeapAllocMem(_size); + } else { + NewValue = HeapAllocStack(_size); + } + if (NewValue == NULL) { + ProgramFail(_parser, "out of memory"); + } +#ifdef DEBUG_HEAP + if (!_onHeap) { + printf("pushing %d at 0x%lx\n", _size, (unsigned long)NewValue); + } +#endif + return NewValue; +} + +/* allocate a value either on the heap or the stack using space dependent on what type we want */ +struct Value *VariableAllocValueAndData(struct ParseState *_parser, + int _dataSize, + int _isLValue, + struct Value *_lValueFrom, + int _onHeap) { + struct Value *NewValue = VariableAlloc(_parser, MEM_ALIGN(sizeof(struct Value)) + _dataSize, _onHeap); + NewValue->Val = (union AnyValue *)((char *)NewValue + MEM_ALIGN(sizeof(struct Value))); + NewValue->ValOnHeap = _onHeap; + NewValue->ValOnStack = !_onHeap; + NewValue->IsLValue = _isLValue; + NewValue->LValueFrom = _lValueFrom; + return NewValue; +} + +/* allocate a value given its type */ +struct Value *VariableAllocValueFromType(struct ParseState *_parser, + struct ValueType *_type, + int _isLValue, + struct Value *_lValueFrom, + int _onHeap) { + int Size = TypeSize(_type, _type->ArraySize, FALSE); + struct Value *NewValue = VariableAllocValueAndData(_parser, Size, _isLValue, _lValueFrom, _onHeap); + assert(Size > 0 || _type == &VoidType); + NewValue->Typ = _type; + return NewValue; +} + +/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */ +struct Value *VariableAllocValueAndCopy(struct ParseState *_parser, + struct Value *_fromValue, + int _onHeap) { + struct ValueType *DType = _fromValue->Typ; + struct Value *NewValue; + char TmpBuf[MAX_TMP_COPY_BUF]; + int CopySize = TypeSizeValue(_fromValue, TRUE); + assert(CopySize <= MAX_TMP_COPY_BUF); + memcpy((void *)&TmpBuf[0], (void *)_fromValue->Val, CopySize); + NewValue = VariableAllocValueAndData(_parser, CopySize, _fromValue->IsLValue, _fromValue->LValueFrom, _onHeap); + NewValue->Typ = DType; + memcpy((void *)NewValue->Val, (void *)&TmpBuf[0], CopySize); + return NewValue; +} + +/* allocate a value either on the heap or the stack from an existing AnyValue and type */ +struct Value *VariableAllocValueFromExistingData(struct ParseState *_parser, + struct ValueType *_type, + union AnyValue *_fromValue, + int _isLValue, + struct Value *_lValueFrom) { + struct Value *NewValue = VariableAlloc(_parser, sizeof(struct Value), FALSE); + NewValue->Typ = _type; + NewValue->Val = _fromValue; + NewValue->ValOnHeap = FALSE; + NewValue->ValOnStack = FALSE; + NewValue->IsLValue = _isLValue; + NewValue->LValueFrom = _lValueFrom; + return NewValue; +} + +/* allocate a value either on the heap or the stack from an existing Value, sharing the value */ +struct Value *VariableAllocValueShared(struct ParseState *_parser, + struct Value *_fromValue) { + return VariableAllocValueFromExistingData(_parser, _fromValue->Typ, _fromValue->Val, _fromValue->IsLValue, _fromValue->IsLValue ? _fromValue : NULL); +} + +/* define a variable. Ident must be registered */ +struct Value *VariableDefine(struct ParseState *_parser, + char *_ident, + struct Value *_initValue, + struct ValueType *_type, + int _makeWritable) { + struct Value *AssignValue; + if (_initValue != NULL) { + AssignValue = VariableAllocValueAndCopy(_parser, _initValue, TopStackFrame == NULL); + } else { + AssignValue = VariableAllocValueFromType(_parser, _type, _makeWritable, NULL, TopStackFrame == NULL); + } + AssignValue->IsLValue = _makeWritable; + if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, _ident, AssignValue, _parser ? ((char *)_parser->FileName) : NULL, _parser ? _parser->Line : 0, _parser ? _parser->CharacterPos : 0)) { + ProgramFail(_parser, "'%s' is already defined", _ident); + } + return AssignValue; +} + +/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ +struct Value *VariableDefineButIgnoreIdentical(struct ParseState *_parser, + char *_ident, + struct ValueType *_type, + int _isStatic, + int *_firstVisit) { + struct Value *ExistingValue; + const char *DeclFileName; + int DeclLine; + int DeclColumn; + if (_isStatic) { + char MangledName[LINEBUFFER_MAX]; + char *MNPos = &MangledName[0]; + char *MNEnd = &MangledName[LINEBUFFER_MAX-1]; + const char *RegisteredMangledName; + /* make the mangled static name (avoiding using sprintf() to minimise library impact) */ + memset((void *)&MangledName, '\0', sizeof(MangledName)); + *MNPos++ = '/'; + strncpy(MNPos, (char *)_parser->FileName, MNEnd - MNPos); + MNPos += strlen(MNPos); + if (TopStackFrame != NULL) { + /* we're inside a function */ + if (MNEnd - MNPos > 0) { + *MNPos++ = '/'; + } + strncpy(MNPos, (char *)TopStackFrame->FuncName, MNEnd - MNPos); + MNPos += strlen(MNPos); + } + if (MNEnd - MNPos > 0) { + *MNPos++ = '/'; + } + strncpy(MNPos, _ident, MNEnd - MNPos); + RegisteredMangledName = TableStrRegister(MangledName); + /* is this static already defined? */ + if (!TableGet(&GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) { + /* define the mangled-named static variable store in the global scope */ + ExistingValue = VariableAllocValueFromType(_parser, _type, TRUE, NULL, TRUE); + TableSet(&GlobalTable, (char *)RegisteredMangledName, ExistingValue, (char *)_parser->FileName, _parser->Line, _parser->CharacterPos); + *_firstVisit = TRUE; + } + /* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */ + VariableDefinePlatformVar(_parser, _ident, ExistingValue->Typ, ExistingValue->Val, TRUE); + return ExistingValue; + } else { + if ( _parser->Line != 0 + && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, _ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn) + && DeclFileName == _parser->FileName + && DeclLine == _parser->Line + && DeclColumn == _parser->CharacterPos) { + return ExistingValue; + } else { + return VariableDefine(_parser, _ident, NULL, _type, TRUE); + } + } +} + +/* check if a variable with a given name is defined. Ident must be registered */ +int VariableDefined(const char *_ident) { + struct Value *FoundValue; + if ( TopStackFrame == NULL + || !TableGet(&TopStackFrame->LocalTable, _ident, &FoundValue, NULL, NULL, NULL)) { + if (!TableGet(&GlobalTable, _ident, &FoundValue, NULL, NULL, NULL)) { + return FALSE; + } + } + return TRUE; +} + +/* get the value of a variable. must be defined. Ident must be registered */ +void VariableGet(struct ParseState *_parser, + const char *_ident, + struct Value **_lValue) { + if ( TopStackFrame == NULL + || !TableGet(&TopStackFrame->LocalTable, _ident, _lValue, NULL, NULL, NULL)) { + if (!TableGet(&GlobalTable, _ident, _lValue, NULL, NULL, NULL)) { + ProgramFail(_parser, "'%s' is undefined", _ident); + } + } +} + +/* define a global variable shared with a platform global. Ident will be registered */ +void VariableDefinePlatformVar(struct ParseState *_parser, + char *_ident, + struct ValueType *_type, + union AnyValue *_fromValue, + int _isWritable) { + struct Value *SomeValue = VariableAllocValueAndData(NULL, 0, _isWritable, NULL, TRUE); + SomeValue->Typ = _type; + SomeValue->Val = _fromValue; + if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(_ident), SomeValue, _parser ? _parser->FileName : NULL, _parser ? _parser->Line : 0, _parser ? _parser->CharacterPos : 0)) { + ProgramFail(_parser, "'%s' is already defined", _ident); + } +} + +/* free and/or pop the top value off the stack. Var must be the top value on the stack! */ +void VariableStackPop(struct ParseState *_parser, + struct Value *_variable) { + int Success; +#ifdef DEBUG_HEAP + if (_variable->ValOnStack) { + printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(_variable, FALSE)), (unsigned long)_variable); + } +#endif + if (_variable->ValOnHeap) { + if (_variable->Val != NULL) { + HeapFreeMem(_variable->Val); + } + Success = HeapPopStack(_variable, sizeof(struct Value)); + /* free from heap */ + } else if (_variable->ValOnStack) { + Success = HeapPopStack(_variable, sizeof(struct Value) + TypeSizeValue(_variable, FALSE)); /* free from stack */ + } else { + Success = HeapPopStack(_variable, sizeof(struct Value)); /* value isn't our problem */ + } + if (!Success) { + ProgramFail(_parser, "stack underrun"); + } +} + +/* add a stack frame when doing a function call */ +void VariableStackFrameAdd(struct ParseState *_parser, + const char *_functionName, + int _numberParameters) { + struct StackFrame *NewFrame; + HeapPushStackFrame(); + NewFrame = HeapAllocStack(sizeof(struct StackFrame) + sizeof(struct Value *) * _numberParameters); + if (NewFrame == NULL) { + ProgramFail(_parser, "out of memory"); + } + ParserCopy(&NewFrame->ReturnParser, _parser); + NewFrame->FuncName = _functionName; + NewFrame->Parameter = (_numberParameters > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL; + TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); + NewFrame->PreviousStackFrame = TopStackFrame; + TopStackFrame = NewFrame; +} + +/* remove a stack frame */ +void VariableStackFramePop(struct ParseState *_parser) { + if (TopStackFrame == NULL) { + ProgramFail(_parser, "stack is empty - can't go back"); + } + ParserCopy(_parser, &TopStackFrame->ReturnParser); + TopStackFrame = TopStackFrame->PreviousStackFrame; + HeapPopStackFrame(); +} + +/* get a string literal. assumes that Ident is already registered. NULL if not found */ +struct Value *VariableStringLiteralGet(char *_ident) { + struct Value *LVal = NULL; + if (TableGet(&StringLiteralTable, _ident, &LVal, NULL, NULL, NULL)) { + return LVal; + } else { + return NULL; + } +} + +/* define a string literal. assumes that Ident is already registered */ +void VariableStringLiteralDefine(char *_ident, + struct Value *_value) { + TableSet(&StringLiteralTable, _ident, _value, NULL, 0, 0); +} + +/* check a pointer for validity and dereference it for use */ +void *VariableDereferencePointer(struct ParseState *_parser, + struct Value *_pointerValue, + struct Value **_dereferenceValue, + int *_dereferenceOffset, + struct ValueType **_dereferenceType, + int *_dereferenceIsLValue) { + if (_dereferenceValue != NULL) { + *_dereferenceValue = NULL; + } + if (_dereferenceType != NULL) { + *_dereferenceType = _pointerValue->Typ->FromType; + } + if (_dereferenceOffset != NULL) { + *_dereferenceOffset = 0; + } + if (_dereferenceIsLValue != NULL) { + *_dereferenceIsLValue = TRUE; + } + return _pointerValue->Val->Pointer; +} + diff --git a/ecilib/clibrary.c b/ecilib/clibrary.c deleted file mode 100644 index 8069dd3..0000000 --- a/ecilib/clibrary.c +++ /dev/null @@ -1,676 +0,0 @@ -#include "picoc.h" -#include "interpreter.h" - -/* the picoc version string */ -static const char *VersionString = NULL; - -/* endian-ness checking */ -static const int __ENDIAN_CHECK__ = 1; - -static int BigEndian = 0; -static int LittleEndian = 0; - - -/* global initialisation for libraries */ -void LibraryInit() -{ - /* define the version number macro */ - VersionString = TableStrRegister(PICOC_VERSION); - VariableDefinePlatformVar(NULL, "PICOC_VERSION", CharPtrType, (union AnyValue *)&VersionString, FALSE); - - /* define endian-ness macros */ - BigEndian = ((*(char*)&__ENDIAN_CHECK__) == 0); - LittleEndian = ((*(char*)&__ENDIAN_CHECK__) == 1); - - VariableDefinePlatformVar(NULL, "BIG_ENDIAN", &IntType, (union AnyValue *)&BigEndian, FALSE); - VariableDefinePlatformVar(NULL, "LITTLE_ENDIAN", &IntType, (union AnyValue *)&LittleEndian, FALSE); -} - -/* add a library */ -void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction *FuncList) -{ - struct ParseState Parser; - int Count; - char *Identifier; - struct ValueType *ReturnType; - struct Value *NewValue; - void *Tokens; - const 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); - TypeParse(&Parser, &ReturnType, &Identifier, NULL); - NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); - NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; - HeapFreeMem(Tokens); - } -} - -/* print a type to a stream without using printf/sprintf */ -void PrintType(struct ValueType *Typ, IOFILE *Stream) -{ - switch (Typ->Base) - { - case TypeVoid: PrintStr("void", Stream); break; - case TypeInt: PrintStr("int", Stream); break; - case TypeShort: PrintStr("short", Stream); break; - case TypeChar: PrintStr("char", Stream); break; - case TypeLong: PrintStr("long", Stream); break; - case TypeUnsignedInt: PrintStr("unsigned int", Stream); break; - case TypeUnsignedShort: PrintStr("unsigned short", Stream); break; - case TypeUnsignedLong: PrintStr("unsigned long", Stream); break; -#ifndef NO_FP - case TypeFP: PrintStr("double", Stream); break; -#endif - case TypeFunction: PrintStr("function", Stream); break; - case TypeMacro: PrintStr("macro", Stream); break; - case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break; - case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintSimpleInt(Typ->ArraySize, Stream); PrintCh(']', Stream); break; - case TypeStruct: PrintStr("struct ", Stream); PrintStr(Typ->Identifier, Stream); break; - case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break; - case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break; - case TypeGotoLabel: PrintStr("goto label ", Stream); break; - case Type_Type: PrintStr("type ", Stream); break; - } -} - - -#ifdef BUILTIN_MINI_STDLIB - -/* - * This is a simplified standard library for small embedded systems. It doesn't require - * a system stdio library to operate. - * - * A more complete standard library for larger computers is in the library_XXX.c files. - */ - -IOFILE *CStdOut; -IOFILE CStdOutBase; - -static int TRUEValue = 1; -static int ZeroValue = 0; - -void BasicIOInit() -{ - CStdOutBase.Putch = &PlatformPutc; - CStdOut = &CStdOutBase; -} - -/* initialise the C library */ -void CLibraryInit() -{ - /* define some constants */ - VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); - VariableDefinePlatformVar(NULL, "TRUE", &IntType, (union AnyValue *)&TRUEValue, FALSE); - VariableDefinePlatformVar(NULL, "FALSE", &IntType, (union AnyValue *)&ZeroValue, FALSE); -} - -/* stream for writing into strings */ -void SPutc(unsigned char Ch, union OutputStreamInfo *Stream) -{ - struct StringOutputStream *Out = &Stream->Str; - *Out->WritePos++ = Ch; -} - -/* print a character to a stream without using printf/sprintf */ -void PrintCh(char OutCh, struct OutputStream *Stream) -{ - (*Stream->Putch)(OutCh, &Stream->i); -} - -/* print a string to a stream without using printf/sprintf */ -void PrintStr(const char *Str, struct OutputStream *Stream) -{ - while (*Str != 0) - PrintCh(*Str++, Stream); -} - -/* print a single character a given number of times */ -void PrintRepeatedChar(char ShowChar, int Length, struct OutputStream *Stream) -{ - while (Length-- > 0) - PrintCh(ShowChar, Stream); -} - -/* print an unsigned integer to a stream without using printf/sprintf */ -void PrintUnsigned(unsigned long Num, unsigned int Base, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream) -{ - char Result[33]; - int ResPos = sizeof(Result); - - Result[--ResPos] = '\0'; - if (Num == 0) - Result[--ResPos] = '0'; - - while (Num > 0) - { - unsigned long NextNum = Num / Base; - unsigned long Digit = Num - NextNum * Base; - if (Digit < 10) - Result[--ResPos] = '0' + Digit; - else - Result[--ResPos] = 'a' + Digit - 10; - - Num = NextNum; - } - - if (FieldWidth > 0 && !LeftJustify) - PrintRepeatedChar(ZeroPad ? '0' : ' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream); - - PrintStr(&Result[ResPos], Stream); - - if (FieldWidth > 0 && LeftJustify) - PrintRepeatedChar(' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream); -} - -/* print an integer to a stream without using printf/sprintf */ -void PrintSimpleInt(long Num, struct OutputStream *Stream) -{ - PrintInt(Num, -1, FALSE, FALSE, Stream); -} - -/* print an integer to a stream without using printf/sprintf */ -void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream) -{ - if (Num < 0) - { - PrintCh('-', Stream); - Num = -Num; - if (FieldWidth != 0) - FieldWidth--; - } - - PrintUnsigned((unsigned long)Num, 10, FieldWidth, ZeroPad, LeftJustify, Stream); -} - -#ifndef NO_FP -/* print a double to a stream without using printf/sprintf */ -void PrintFP(double Num, struct OutputStream *Stream) -{ - int Exponent = 0; - int MaxDecimal; - - if (Num < 0) - { - PrintCh('-', Stream); - Num = -Num; - } - - if (Num >= 1e7) - Exponent = log10(Num); - else if (Num <= 1e-7 && Num != 0.0) - Exponent = log10(Num) - 0.999999999; - - Num /= pow(10.0, Exponent); - PrintInt((long)Num, 0, FALSE, FALSE, Stream); - PrintCh('.', Stream); - Num = (Num - (long)Num) * 10; - if (abs(Num) >= 1e-7) - { - for (MaxDecimal = 6; MaxDecimal > 0 && abs(Num) >= 1e-7; Num = (Num - (long)(Num + 1e-7)) * 10, MaxDecimal--) - PrintCh('0' + (long)(Num + 1e-7), Stream); - } - else - PrintCh('0', Stream); - - if (Exponent != 0) - { - PrintCh('e', Stream); - PrintInt(Exponent, 0, FALSE, FALSE, Stream); - } -} -#endif - -/* intrinsic functions made available to the language */ -void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream) -{ - char *FPos; - struct Value *NextArg = Param[0]; - struct ValueType *FormatType; - int ArgCount = 1; - int LeftJustify = FALSE; - int ZeroPad = FALSE; - int FieldWidth = 0; - char *Format = Param[0]->Val->Pointer; - - for (FPos = Format; *FPos != '\0'; FPos++) - { - if (*FPos == '%') - { - FPos++; - if (*FPos == '-') - { - /* a leading '-' means left justify */ - LeftJustify = TRUE; - FPos++; - } - - if (*FPos == '0') - { - /* a leading zero means zero pad a decimal number */ - ZeroPad = TRUE; - FPos++; - } - - /* get any field width in the format */ - while (isdigit((int)*FPos)) - FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); - - /* now check the format type */ - switch (*FPos) - { - case 's': FormatType = CharPtrType; break; - case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; -#ifndef NO_FP - case 'f': FormatType = &FPType; break; -#endif - case '%': PrintCh('%', Stream); FormatType = NULL; break; - case '\0': FPos--; FormatType = NULL; break; - default: PrintCh(*FPos, Stream); FormatType = NULL; break; - } - - if (FormatType != NULL) - { - /* we have to format something */ - if (ArgCount >= NumArgs) - PrintStr("XXX", Stream); /* not enough parameters for format */ - else - { - NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); - if (NextArg->Typ != FormatType && - !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && - !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || - (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) - PrintStr("XXX", Stream); /* bad type for format */ - else - { - switch (*FPos) - { - case 's': - { - char *Str; - - if (NextArg->Typ->Base == TypePointer) - Str = NextArg->Val->Pointer; - else - Str = &NextArg->Val->ArrayMem[0]; - - if (Str == NULL) - PrintStr("NULL", Stream); - else - PrintStr(Str, Stream); - break; - } - case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break; - case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break; - case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break; - case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break; - case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break; -#ifndef NO_FP - case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break; -#endif - } - } - } - - ArgCount++; - } - } - else - PrintCh(*FPos, Stream); - } -} - -/* printf(): print to console output */ -void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct OutputStream ConsoleStream; - - ConsoleStream.Putch = &PlatformPutc; - GenericPrintf(Parser, ReturnValue, Param, NumArgs, &ConsoleStream); -} - -/* sprintf(): print to a string */ -void LibSPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct OutputStream StrStream; - - StrStream.Putch = &SPutc; - StrStream.i.Str.Parser = Parser; - StrStream.i.Str.WritePos = Param[0]->Val->Pointer; - - GenericPrintf(Parser, ReturnValue, Param+1, NumArgs-1, &StrStream); - PrintCh(0, &StrStream); - ReturnValue->Val->Pointer = *Param; -} - -/* get a line of input. protected from buffer overrun */ -void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = PlatformGetLine(Param[0]->Val->Pointer, GETS_BUF_MAX, NULL); - if (ReturnValue->Val->Pointer != NULL) - { - char *EOLPos = strchr(Param[0]->Val->Pointer, '\n'); - if (EOLPos != NULL) - *EOLPos = '\0'; - } -} - -void LibGetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = PlatformGetCharacter(); -} - -void LibExit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - PlatformExit(Param[0]->Val->Integer); -} - -#ifdef PICOC_LIBRARY -void LibSin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sin(Param[0]->Val->FP); -} - -void LibCos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = cos(Param[0]->Val->FP); -} - -void LibTan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = tan(Param[0]->Val->FP); -} - -void LibAsin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = asin(Param[0]->Val->FP); -} - -void LibAcos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = acos(Param[0]->Val->FP); -} - -void LibAtan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = atan(Param[0]->Val->FP); -} - -void LibSinh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sinh(Param[0]->Val->FP); -} - -void LibCosh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = cosh(Param[0]->Val->FP); -} - -void LibTanh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = tanh(Param[0]->Val->FP); -} - -void LibExp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = exp(Param[0]->Val->FP); -} - -void LibFabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = fabs(Param[0]->Val->FP); -} - -void LibLog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = log(Param[0]->Val->FP); -} - -void LibLog10(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = log10(Param[0]->Val->FP); -} - -void LibPow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = pow(Param[0]->Val->FP, Param[1]->Val->FP); -} - -void LibSqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sqrt(Param[0]->Val->FP); -} - -void LibRound(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = floor(Param[0]->Val->FP + 0.5); /* XXX - fix for soft float */ -} - -void LibCeil(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = ceil(Param[0]->Val->FP); -} - -void LibFloor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = floor(Param[0]->Val->FP); -} -#endif - -#ifndef NO_STRING_FUNCTIONS -void LibMalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = malloc(Param[0]->Val->Integer); -} - -#ifndef NO_CALLOC -void LibCalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = calloc(Param[0]->Val->Integer, Param[1]->Val->Integer); -} -#endif - -#ifndef NO_REALLOC -void LibRealloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = realloc(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} -#endif - -void LibFree(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - free(Param[0]->Val->Pointer); -} - -void LibStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *To = (char *)Param[0]->Val->Pointer; - char *From = (char *)Param[1]->Val->Pointer; - - while (*From != '\0') - *To++ = *From++; - - *To = '\0'; -} - -void LibStrncpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *To = (char *)Param[0]->Val->Pointer; - char *From = (char *)Param[1]->Val->Pointer; - int Len = Param[2]->Val->Integer; - - for (; *From != '\0' && Len > 0; Len--) - *To++ = *From++; - - if (Len > 0) - *To = '\0'; -} - -void LibStrcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *Str1 = (char *)Param[0]->Val->Pointer; - char *Str2 = (char *)Param[1]->Val->Pointer; - int StrEnded; - - for (StrEnded = FALSE; !StrEnded; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++) - { - if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; } - else if (*Str1 > *Str2) { ReturnValue->Val->Integer = 1; return; } - } - - ReturnValue->Val->Integer = 0; -} - -void LibStrncmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *Str1 = (char *)Param[0]->Val->Pointer; - char *Str2 = (char *)Param[1]->Val->Pointer; - int Len = Param[2]->Val->Integer; - int StrEnded; - - for (StrEnded = FALSE; !StrEnded && Len > 0; StrEnded = (*Str1 == '\0' || *Str2 == '\0'), Str1++, Str2++, Len--) - { - if (*Str1 < *Str2) { ReturnValue->Val->Integer = -1; return; } - else if (*Str1 > *Str2) { ReturnValue->Val->Integer = 1; return; } - } - - ReturnValue->Val->Integer = 0; -} - -void LibStrcat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *To = (char *)Param[0]->Val->Pointer; - char *From = (char *)Param[1]->Val->Pointer; - - while (*To != '\0') - To++; - - while (*From != '\0') - *To++ = *From++; - - *To = '\0'; -} - -void LibIndex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *Pos = (char *)Param[0]->Val->Pointer; - int SearchChar = Param[1]->Val->Integer; - - while (*Pos != '\0' && *Pos != SearchChar) - Pos++; - - if (*Pos != SearchChar) - ReturnValue->Val->Pointer = NULL; - else - ReturnValue->Val->Pointer = Pos; -} - -void LibRindex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *Pos = (char *)Param[0]->Val->Pointer; - int SearchChar = Param[1]->Val->Integer; - - ReturnValue->Val->Pointer = NULL; - for (; *Pos != '\0'; Pos++) - { - if (*Pos == SearchChar) - ReturnValue->Val->Pointer = Pos; - } -} - -void LibStrlen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - char *Pos = (char *)Param[0]->Val->Pointer; - int Len; - - for (Len = 0; *Pos != '\0'; Pos++) - Len++; - - ReturnValue->Val->Integer = Len; -} - -void LibMemset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - /* we can use the system memset() */ - memset(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void LibMemcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - /* we can use the system memcpy() */ - memcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void LibMemcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - unsigned char *Mem1 = (unsigned char *)Param[0]->Val->Pointer; - unsigned char *Mem2 = (unsigned char *)Param[1]->Val->Pointer; - int Len = Param[2]->Val->Integer; - - for (; Len > 0; Mem1++, Mem2++, Len--) - { - if (*Mem1 < *Mem2) { ReturnValue->Val->Integer = -1; return; } - else if (*Mem1 > *Mem2) { ReturnValue->Val->Integer = 1; return; } - } - - ReturnValue->Val->Integer = 0; -} -#endif - -/* list of all library functions and their prototypes */ -struct LibraryFunction CLibrary[] = -{ - { LibPrintf, "void printf(char *, ...);" }, - { LibSPrintf, "char *sprintf(char *, char *, ...);" }, - { LibGets, "char *gets(char *);" }, - { LibGetc, "int getchar();" }, - { LibExit, "void exit(int);" }, -#ifdef PICOC_LIBRARY - { LibSin, "float sin(float);" }, - { LibCos, "float cos(float);" }, - { LibTan, "float tan(float);" }, - { LibAsin, "float asin(float);" }, - { LibAcos, "float acos(float);" }, - { LibAtan, "float atan(float);" }, - { LibSinh, "float sinh(float);" }, - { LibCosh, "float cosh(float);" }, - { LibTanh, "float tanh(float);" }, - { LibExp, "float exp(float);" }, - { LibFabs, "float fabs(float);" }, - { LibLog, "float log(float);" }, - { LibLog10, "float log10(float);" }, - { LibPow, "float pow(float,float);" }, - { LibSqrt, "float sqrt(float);" }, - { LibRound, "float round(float);" }, - { LibCeil, "float ceil(float);" }, - { LibFloor, "float floor(float);" }, -#endif - { LibMalloc, "void *malloc(int);" }, -#ifndef NO_CALLOC - { LibCalloc, "void *calloc(int,int);" }, -#endif -#ifndef NO_REALLOC - { LibRealloc, "void *realloc(void *,int);" }, -#endif - { LibFree, "void free(void *);" }, -#ifndef NO_STRING_FUNCTIONS - { LibStrcpy, "void strcpy(char *,char *);" }, - { LibStrncpy, "void strncpy(char *,char *,int);" }, - { LibStrcmp, "int strcmp(char *,char *);" }, - { LibStrncmp, "int strncmp(char *,char *,int);" }, - { LibStrcat, "void strcat(char *,char *);" }, - { LibIndex, "char *index(char *,int);" }, - { LibRindex, "char *rindex(char *,int);" }, - { LibStrlen, "int strlen(char *);" }, - { LibMemset, "void memset(void *,int,int);" }, - { LibMemcpy, "void memcpy(void *,void *,int);" }, - { LibMemcmp, "int memcmp(void *,void *,int);" }, -#endif - { NULL, NULL } -}; - -#endif /* BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/ctype.c b/ecilib/cstdlib/ctype.c deleted file mode 100644 index d1e8140..0000000 --- a/ecilib/cstdlib/ctype.c +++ /dev/null @@ -1,110 +0,0 @@ -/* string.h library for large systems - small embedded systems use clibrary.c instead */ -#include -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -void StdIsalnum(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isalnum(Param[0]->Val->Integer); -} - -void StdIsalpha(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isalpha(Param[0]->Val->Integer); -} - -void StdIsblank(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - int ch = Param[0]->Val->Integer; - ReturnValue->Val->Integer = (ch == ' ') | (ch == '\t'); -} - -void StdIscntrl(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = iscntrl(Param[0]->Val->Integer); -} - -void StdIsdigit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isdigit(Param[0]->Val->Integer); -} - -void StdIsgraph(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isgraph(Param[0]->Val->Integer); -} - -void StdIslower(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = islower(Param[0]->Val->Integer); -} - -void StdIsprint(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isprint(Param[0]->Val->Integer); -} - -void StdIspunct(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ispunct(Param[0]->Val->Integer); -} - -void StdIsspace(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isspace(Param[0]->Val->Integer); -} - -void StdIsupper(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isupper(Param[0]->Val->Integer); -} - -void StdIsxdigit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isxdigit(Param[0]->Val->Integer); -} - -void StdTolower(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = tolower(Param[0]->Val->Integer); -} - -void StdToupper(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = toupper(Param[0]->Val->Integer); -} - -void StdIsascii(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isascii(Param[0]->Val->Integer); -} - -void StdToascii(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = toascii(Param[0]->Val->Integer); -} - -/* all string.h functions */ -struct LibraryFunction StdCtypeFunctions[] = -{ - { StdIsalnum, "int isalnum(int);" }, - { StdIsalpha, "int isalpha(int);" }, - { StdIsblank, "int isblank(int);" }, - { StdIscntrl, "int iscntrl(int);" }, - { StdIsdigit, "int isdigit(int);" }, - { StdIsgraph, "int isgraph(int);" }, - { StdIslower, "int islower(int);" }, - { StdIsprint, "int isprint(int);" }, - { StdIspunct, "int ispunct(int);" }, - { StdIsspace, "int isspace(int);" }, - { StdIsupper, "int isupper(int);" }, - { StdIsxdigit, "int isxdigit(int);" }, - { StdTolower, "int tolower(int);" }, - { StdToupper, "int toupper(int);" }, - { StdIsascii, "int isascii(int);" }, - { StdToascii, "int toascii(int);" }, - { NULL, NULL } -}; - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/errno.c b/ecilib/cstdlib/errno.c deleted file mode 100644 index e5becbf..0000000 --- a/ecilib/cstdlib/errno.c +++ /dev/null @@ -1,655 +0,0 @@ -/* string.h library for large systems - small embedded systems use clibrary.c instead */ -#include -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -#ifdef EACCES -static int EACCESValue = EACCES; -#endif - -#ifdef EADDRINUSE -static int EADDRINUSEValue = EADDRINUSE; -#endif - -#ifdef EADDRNOTAVAIL -static int EADDRNOTAVAILValue = EADDRNOTAVAIL; -#endif - -#ifdef EAFNOSUPPORT -static int EAFNOSUPPORTValue = EAFNOSUPPORT; -#endif - -#ifdef EAGAIN -static int EAGAINValue = EAGAIN; -#endif - -#ifdef EALREADY -static int EALREADYValue = EALREADY; -#endif - -#ifdef EBADF -static int EBADFValue = EBADF; -#endif - -#ifdef EBADMSG -static int EBADMSGValue = EBADMSG; -#endif - -#ifdef EBUSY -static int EBUSYValue = EBUSY; -#endif - -#ifdef ECANCELED -static int ECANCELEDValue = ECANCELED; -#endif - -#ifdef ECHILD -static int ECHILDValue = ECHILD; -#endif - -#ifdef ECONNABORTED -static int ECONNABORTEDValue = ECONNABORTED; -#endif - -#ifdef ECONNREFUSED -static int ECONNREFUSEDValue = ECONNREFUSED; -#endif - -#ifdef ECONNRESET -static int ECONNRESETValue = ECONNRESET; -#endif - -#ifdef EDEADLK -static int EDEADLKValue = EDEADLK; -#endif - -#ifdef EDESTADDRREQ -static int EDESTADDRREQValue = EDESTADDRREQ; -#endif - -#ifdef EDOM -static int EDOMValue = EDOM; -#endif - -#ifdef EDQUOT -static int EDQUOTValue = EDQUOT; -#endif - -#ifdef EEXIST -static int EEXISTValue = EEXIST; -#endif - -#ifdef EFAULT -static int EFAULTValue = EFAULT; -#endif - -#ifdef EFBIG -static int EFBIGValue = EFBIG; -#endif - -#ifdef EHOSTUNREACH -static int EHOSTUNREACHValue = EHOSTUNREACH; -#endif - -#ifdef EIDRM -static int EIDRMValue = EIDRM; -#endif - -#ifdef EILSEQ -static int EILSEQValue = EILSEQ; -#endif - -#ifdef EINPROGRESS -static int EINPROGRESSValue = EINPROGRESS; -#endif - -#ifdef EINTR -static int EINTRValue = EINTR; -#endif - -#ifdef EINVAL -static int EINVALValue = EINVAL; -#endif - -#ifdef EIO -static int EIOValue = EIO; -#endif - -#ifdef EISCONN -static int EISCONNValue = EISCONN; -#endif - -#ifdef EISDIR -static int EISDIRValue = EISDIR; -#endif - -#ifdef ELOOP -static int ELOOPValue = ELOOP; -#endif - -#ifdef EMFILE -static int EMFILEValue = EMFILE; -#endif - -#ifdef EMLINK -static int EMLINKValue = EMLINK; -#endif - -#ifdef EMSGSIZE -static int EMSGSIZEValue = EMSGSIZE; -#endif - -#ifdef EMULTIHOP -static int EMULTIHOPValue = EMULTIHOP; -#endif - -#ifdef ENAMETOOLONG -static int ENAMETOOLONGValue = ENAMETOOLONG; -#endif - -#ifdef ENETDOWN -static int ENETDOWNValue = ENETDOWN; -#endif - -#ifdef ENETRESET -static int ENETRESETValue = ENETRESET; -#endif - -#ifdef ENETUNREACH -static int ENETUNREACHValue = ENETUNREACH; -#endif - -#ifdef ENFILE -static int ENFILEValue = ENFILE; -#endif - -#ifdef ENOBUFS -static int ENOBUFSValue = ENOBUFS; -#endif - -#ifdef ENODATA -static int ENODATAValue = ENODATA; -#endif - -#ifdef ENODEV -static int ENODEVValue = ENODEV; -#endif - -#ifdef ENOENT -static int ENOENTValue = ENOENT; -#endif - -#ifdef ENOEXEC -static int ENOEXECValue = ENOEXEC; -#endif - -#ifdef ENOLCK -static int ENOLCKValue = ENOLCK; -#endif - -#ifdef ENOLINK -static int ENOLINKValue = ENOLINK; -#endif - -#ifdef ENOMEM -static int ENOMEMValue = ENOMEM; -#endif - -#ifdef ENOMSG -static int ENOMSGValue = ENOMSG; -#endif - -#ifdef ENOPROTOOPT -static int ENOPROTOOPTValue = ENOPROTOOPT; -#endif - -#ifdef ENOSPC -static int ENOSPCValue = ENOSPC; -#endif - -#ifdef ENOSR -static int ENOSRValue = ENOSR; -#endif - -#ifdef ENOSTR -static int ENOSTRValue = ENOSTR; -#endif - -#ifdef ENOSYS -static int ENOSYSValue = ENOSYS; -#endif - -#ifdef ENOTCONN -static int ENOTCONNValue = ENOTCONN; -#endif - -#ifdef ENOTDIR -static int ENOTDIRValue = ENOTDIR; -#endif - -#ifdef ENOTEMPTY -static int ENOTEMPTYValue = ENOTEMPTY; -#endif - -#ifdef ENOTRECOVERABLE -static int ENOTRECOVERABLEValue = ENOTRECOVERABLE; -#endif - -#ifdef ENOTSOCK -static int ENOTSOCKValue = ENOTSOCK; -#endif - -#ifdef ENOTSUP -static int ENOTSUPValue = ENOTSUP; -#endif - -#ifdef ENOTTY -static int ENOTTYValue = ENOTTY; -#endif - -#ifdef ENXIO -static int ENXIOValue = ENXIO; -#endif - -#ifdef EOPNOTSUPP -static int EOPNOTSUPPValue = EOPNOTSUPP; -#endif - -#ifdef EOVERFLOW -static int EOVERFLOWValue = EOVERFLOW; -#endif - -#ifdef EOWNERDEAD -static int EOWNERDEADValue = EOWNERDEAD; -#endif - -#ifdef EPERM -static int EPERMValue = EPERM; -#endif - -#ifdef EPIPE -static int EPIPEValue = EPIPE; -#endif - -#ifdef EPROTO -static int EPROTOValue = EPROTO; -#endif - -#ifdef EPROTONOSUPPORT -static int EPROTONOSUPPORTValue = EPROTONOSUPPORT; -#endif - -#ifdef EPROTOTYPE -static int EPROTOTYPEValue = EPROTOTYPE; -#endif - -#ifdef ERANGE -static int ERANGEValue = ERANGE; -#endif - -#ifdef EROFS -static int EROFSValue = EROFS; -#endif - -#ifdef ESPIPE -static int ESPIPEValue = ESPIPE; -#endif - -#ifdef ESRCH -static int ESRCHValue = ESRCH; -#endif - -#ifdef ESTALE -static int ESTALEValue = ESTALE; -#endif - -#ifdef ETIME -static int ETIMEValue = ETIME; -#endif - -#ifdef ETIMEDOUT -static int ETIMEDOUTValue = ETIMEDOUT; -#endif - -#ifdef ETXTBSY -static int ETXTBSYValue = ETXTBSY; -#endif - -#ifdef EWOULDBLOCK -static int EWOULDBLOCKValue = EWOULDBLOCK; -#endif - -#ifdef EXDEV -static int EXDEVValue = EXDEV; -#endif - - -/* creates various system-dependent definitions */ -void StdErrnoSetupFunc(void) -{ - /* defines */ -#ifdef EACCES - VariableDefinePlatformVar(NULL, "EACCES", &IntType, (union AnyValue *)&EACCESValue, FALSE); -#endif - -#ifdef EADDRINUSE - VariableDefinePlatformVar(NULL, "EADDRINUSE", &IntType, (union AnyValue *)&EADDRINUSEValue, FALSE); -#endif - -#ifdef EADDRNOTAVAIL - VariableDefinePlatformVar(NULL, "EADDRNOTAVAIL", &IntType, (union AnyValue *)&EADDRNOTAVAILValue, FALSE); -#endif - -#ifdef EAFNOSUPPORT - VariableDefinePlatformVar(NULL, "EAFNOSUPPORT", &IntType, (union AnyValue *)&EAFNOSUPPORTValue, FALSE); -#endif - -#ifdef EAGAIN - VariableDefinePlatformVar(NULL, "EAGAIN", &IntType, (union AnyValue *)&EAGAINValue, FALSE); -#endif - -#ifdef EALREADY - VariableDefinePlatformVar(NULL, "EALREADY", &IntType, (union AnyValue *)&EALREADYValue, FALSE); -#endif - -#ifdef EBADF - VariableDefinePlatformVar(NULL, "EBADF", &IntType, (union AnyValue *)&EBADFValue, FALSE); -#endif - -#ifdef EBADMSG - VariableDefinePlatformVar(NULL, "EBADMSG", &IntType, (union AnyValue *)&EBADMSGValue, FALSE); -#endif - -#ifdef EBUSY - VariableDefinePlatformVar(NULL, "EBUSY", &IntType, (union AnyValue *)&EBUSYValue, FALSE); -#endif - -#ifdef ECANCELED - VariableDefinePlatformVar(NULL, "ECANCELED", &IntType, (union AnyValue *)&ECANCELEDValue, FALSE); -#endif - -#ifdef ECHILD - VariableDefinePlatformVar(NULL, "ECHILD", &IntType, (union AnyValue *)&ECHILDValue, FALSE); -#endif - -#ifdef ECONNABORTED - VariableDefinePlatformVar(NULL, "ECONNABORTED", &IntType, (union AnyValue *)&ECONNABORTEDValue, FALSE); -#endif - -#ifdef ECONNREFUSED - VariableDefinePlatformVar(NULL, "ECONNREFUSED", &IntType, (union AnyValue *)&ECONNREFUSEDValue, FALSE); -#endif - -#ifdef ECONNRESET - VariableDefinePlatformVar(NULL, "ECONNRESET", &IntType, (union AnyValue *)&ECONNRESETValue, FALSE); -#endif - -#ifdef EDEADLK - VariableDefinePlatformVar(NULL, "EDEADLK", &IntType, (union AnyValue *)&EDEADLKValue, FALSE); -#endif - -#ifdef EDESTADDRREQ - VariableDefinePlatformVar(NULL, "EDESTADDRREQ", &IntType, (union AnyValue *)&EDESTADDRREQValue, FALSE); -#endif - -#ifdef EDOM - VariableDefinePlatformVar(NULL, "EDOM", &IntType, (union AnyValue *)&EDOMValue, FALSE); -#endif - -#ifdef EDQUOT - VariableDefinePlatformVar(NULL, "EDQUOT", &IntType, (union AnyValue *)&EDQUOTValue, FALSE); -#endif - -#ifdef EEXIST - VariableDefinePlatformVar(NULL, "EEXIST", &IntType, (union AnyValue *)&EEXISTValue, FALSE); -#endif - -#ifdef EFAULT - VariableDefinePlatformVar(NULL, "EFAULT", &IntType, (union AnyValue *)&EFAULTValue, FALSE); -#endif - -#ifdef EFBIG - VariableDefinePlatformVar(NULL, "EFBIG", &IntType, (union AnyValue *)&EFBIGValue, FALSE); -#endif - -#ifdef EHOSTUNREACH - VariableDefinePlatformVar(NULL, "EHOSTUNREACH", &IntType, (union AnyValue *)&EHOSTUNREACHValue, FALSE); -#endif - -#ifdef EIDRM - VariableDefinePlatformVar(NULL, "EIDRM", &IntType, (union AnyValue *)&EIDRMValue, FALSE); -#endif - -#ifdef EILSEQ - VariableDefinePlatformVar(NULL, "EILSEQ", &IntType, (union AnyValue *)&EILSEQValue, FALSE); -#endif - -#ifdef EINPROGRESS - VariableDefinePlatformVar(NULL, "EINPROGRESS", &IntType, (union AnyValue *)&EINPROGRESSValue, FALSE); -#endif - -#ifdef EINTR - VariableDefinePlatformVar(NULL, "EINTR", &IntType, (union AnyValue *)&EINTRValue, FALSE); -#endif - -#ifdef EINVAL - VariableDefinePlatformVar(NULL, "EINVAL", &IntType, (union AnyValue *)&EINVALValue, FALSE); -#endif - -#ifdef EIO - VariableDefinePlatformVar(NULL, "EIO", &IntType, (union AnyValue *)&EIOValue, FALSE); -#endif - -#ifdef EISCONN - VariableDefinePlatformVar(NULL, "EISCONN", &IntType, (union AnyValue *)&EISCONNValue, FALSE); -#endif - -#ifdef EISDIR - VariableDefinePlatformVar(NULL, "EISDIR", &IntType, (union AnyValue *)&EISDIRValue, FALSE); -#endif - -#ifdef ELOOP - VariableDefinePlatformVar(NULL, "ELOOP", &IntType, (union AnyValue *)&ELOOPValue, FALSE); -#endif - -#ifdef EMFILE - VariableDefinePlatformVar(NULL, "EMFILE", &IntType, (union AnyValue *)&EMFILEValue, FALSE); -#endif - -#ifdef EMLINK - VariableDefinePlatformVar(NULL, "EMLINK", &IntType, (union AnyValue *)&EMLINKValue, FALSE); -#endif - -#ifdef EMSGSIZE - VariableDefinePlatformVar(NULL, "EMSGSIZE", &IntType, (union AnyValue *)&EMSGSIZEValue, FALSE); -#endif - -#ifdef EMULTIHOP - VariableDefinePlatformVar(NULL, "EMULTIHOP", &IntType, (union AnyValue *)&EMULTIHOPValue, FALSE); -#endif - -#ifdef ENAMETOOLONG - VariableDefinePlatformVar(NULL, "ENAMETOOLONG", &IntType, (union AnyValue *)&ENAMETOOLONGValue, FALSE); -#endif - -#ifdef ENETDOWN - VariableDefinePlatformVar(NULL, "ENETDOWN", &IntType, (union AnyValue *)&ENETDOWNValue, FALSE); -#endif - -#ifdef ENETRESET - VariableDefinePlatformVar(NULL, "ENETRESET", &IntType, (union AnyValue *)&ENETRESETValue, FALSE); -#endif - -#ifdef ENETUNREACH - VariableDefinePlatformVar(NULL, "ENETUNREACH", &IntType, (union AnyValue *)&ENETUNREACHValue, FALSE); -#endif - -#ifdef ENFILE - VariableDefinePlatformVar(NULL, "ENFILE", &IntType, (union AnyValue *)&ENFILEValue, FALSE); -#endif - -#ifdef ENOBUFS - VariableDefinePlatformVar(NULL, "ENOBUFS", &IntType, (union AnyValue *)&ENOBUFSValue, FALSE); -#endif - -#ifdef ENODATA - VariableDefinePlatformVar(NULL, "ENODATA", &IntType, (union AnyValue *)&ENODATAValue, FALSE); -#endif - -#ifdef ENODEV - VariableDefinePlatformVar(NULL, "ENODEV", &IntType, (union AnyValue *)&ENODEVValue, FALSE); -#endif - -#ifdef ENOENT - VariableDefinePlatformVar(NULL, "ENOENT", &IntType, (union AnyValue *)&ENOENTValue, FALSE); -#endif - -#ifdef ENOEXEC - VariableDefinePlatformVar(NULL, "ENOEXEC", &IntType, (union AnyValue *)&ENOEXECValue, FALSE); -#endif - -#ifdef ENOLCK - VariableDefinePlatformVar(NULL, "ENOLCK", &IntType, (union AnyValue *)&ENOLCKValue, FALSE); -#endif - -#ifdef ENOLINK - VariableDefinePlatformVar(NULL, "ENOLINK", &IntType, (union AnyValue *)&ENOLINKValue, FALSE); -#endif - -#ifdef ENOMEM - VariableDefinePlatformVar(NULL, "ENOMEM", &IntType, (union AnyValue *)&ENOMEMValue, FALSE); -#endif - -#ifdef ENOMSG - VariableDefinePlatformVar(NULL, "ENOMSG", &IntType, (union AnyValue *)&ENOMSGValue, FALSE); -#endif - -#ifdef ENOPROTOOPT - VariableDefinePlatformVar(NULL, "ENOPROTOOPT", &IntType, (union AnyValue *)&ENOPROTOOPTValue, FALSE); -#endif - -#ifdef ENOSPC - VariableDefinePlatformVar(NULL, "ENOSPC", &IntType, (union AnyValue *)&ENOSPCValue, FALSE); -#endif - -#ifdef ENOSR - VariableDefinePlatformVar(NULL, "ENOSR", &IntType, (union AnyValue *)&ENOSRValue, FALSE); -#endif - -#ifdef ENOSTR - VariableDefinePlatformVar(NULL, "ENOSTR", &IntType, (union AnyValue *)&ENOSTRValue, FALSE); -#endif - -#ifdef ENOSYS - VariableDefinePlatformVar(NULL, "ENOSYS", &IntType, (union AnyValue *)&ENOSYSValue, FALSE); -#endif - -#ifdef ENOTCONN - VariableDefinePlatformVar(NULL, "ENOTCONN", &IntType, (union AnyValue *)&ENOTCONNValue, FALSE); -#endif - -#ifdef ENOTDIR - VariableDefinePlatformVar(NULL, "ENOTDIR", &IntType, (union AnyValue *)&ENOTDIRValue, FALSE); -#endif - -#ifdef ENOTEMPTY - VariableDefinePlatformVar(NULL, "ENOTEMPTY", &IntType, (union AnyValue *)&ENOTEMPTYValue, FALSE); -#endif - -#ifdef ENOTRECOVERABLE - VariableDefinePlatformVar(NULL, "ENOTRECOVERABLE", &IntType, (union AnyValue *)&ENOTRECOVERABLEValue, FALSE); -#endif - -#ifdef ENOTSOCK - VariableDefinePlatformVar(NULL, "ENOTSOCK", &IntType, (union AnyValue *)&ENOTSOCKValue, FALSE); -#endif - -#ifdef ENOTSUP - VariableDefinePlatformVar(NULL, "ENOTSUP", &IntType, (union AnyValue *)&ENOTSUPValue, FALSE); -#endif - -#ifdef ENOTTY - VariableDefinePlatformVar(NULL, "ENOTTY", &IntType, (union AnyValue *)&ENOTTYValue, FALSE); -#endif - -#ifdef ENXIO - VariableDefinePlatformVar(NULL, "ENXIO", &IntType, (union AnyValue *)&ENXIOValue, FALSE); -#endif - -#ifdef EOPNOTSUPP - VariableDefinePlatformVar(NULL, "EOPNOTSUPP", &IntType, (union AnyValue *)&EOPNOTSUPPValue, FALSE); -#endif - -#ifdef EOVERFLOW - VariableDefinePlatformVar(NULL, "EOVERFLOW", &IntType, (union AnyValue *)&EOVERFLOWValue, FALSE); -#endif - -#ifdef EOWNERDEAD - VariableDefinePlatformVar(NULL, "EOWNERDEAD", &IntType, (union AnyValue *)&EOWNERDEADValue, FALSE); -#endif - -#ifdef EPERM - VariableDefinePlatformVar(NULL, "EPERM", &IntType, (union AnyValue *)&EPERMValue, FALSE); -#endif - -#ifdef EPIPE - VariableDefinePlatformVar(NULL, "EPIPE", &IntType, (union AnyValue *)&EPIPEValue, FALSE); -#endif - -#ifdef EPROTO - VariableDefinePlatformVar(NULL, "EPROTO", &IntType, (union AnyValue *)&EPROTOValue, FALSE); -#endif - -#ifdef EPROTONOSUPPORT - VariableDefinePlatformVar(NULL, "EPROTONOSUPPORT", &IntType, (union AnyValue *)&EPROTONOSUPPORTValue, FALSE); -#endif - -#ifdef EPROTOTYPE - VariableDefinePlatformVar(NULL, "EPROTOTYPE", &IntType, (union AnyValue *)&EPROTOTYPEValue, FALSE); -#endif - -#ifdef ERANGE - VariableDefinePlatformVar(NULL, "ERANGE", &IntType, (union AnyValue *)&ERANGEValue, FALSE); -#endif - -#ifdef EROFS - VariableDefinePlatformVar(NULL, "EROFS", &IntType, (union AnyValue *)&EROFSValue, FALSE); -#endif - -#ifdef ESPIPE - VariableDefinePlatformVar(NULL, "ESPIPE", &IntType, (union AnyValue *)&ESPIPEValue, FALSE); -#endif - -#ifdef ESRCH - VariableDefinePlatformVar(NULL, "ESRCH", &IntType, (union AnyValue *)&ESRCHValue, FALSE); -#endif - -#ifdef ESTALE - VariableDefinePlatformVar(NULL, "ESTALE", &IntType, (union AnyValue *)&ESTALEValue, FALSE); -#endif - -#ifdef ETIME - VariableDefinePlatformVar(NULL, "ETIME", &IntType, (union AnyValue *)&ETIMEValue, FALSE); -#endif - -#ifdef ETIMEDOUT - VariableDefinePlatformVar(NULL, "ETIMEDOUT", &IntType, (union AnyValue *)&ETIMEDOUTValue, FALSE); -#endif - -#ifdef ETXTBSY - VariableDefinePlatformVar(NULL, "ETXTBSY", &IntType, (union AnyValue *)&ETXTBSYValue, FALSE); -#endif - -#ifdef EWOULDBLOCK - VariableDefinePlatformVar(NULL, "EWOULDBLOCK", &IntType, (union AnyValue *)&EWOULDBLOCKValue, FALSE); -#endif - -#ifdef EXDEV - VariableDefinePlatformVar(NULL, "EXDEV", &IntType, (union AnyValue *)&EXDEVValue, FALSE); -#endif - - VariableDefinePlatformVar(NULL, "errno", &IntType, (union AnyValue *)&errno, TRUE); -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/math.c b/ecilib/cstdlib/math.c deleted file mode 100644 index 0ba29a4..0000000 --- a/ecilib/cstdlib/math.c +++ /dev/null @@ -1,187 +0,0 @@ -/* stdio.h library for large systems - small embedded systems use clibrary.c instead */ -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB -#ifndef NO_FP - -static double M_EValue = 2.7182818284590452354; /* e */ -static double M_LOG2EValue = 1.4426950408889634074; /* log_2 e */ -static double M_LOG10EValue = 0.43429448190325182765; /* log_10 e */ -static double M_LN2Value = 0.69314718055994530942; /* log_e 2 */ -static double M_LN10Value = 2.30258509299404568402; /* log_e 10 */ -static double M_PIValue = 3.14159265358979323846; /* pi */ -static double M_PI_2Value = 1.57079632679489661923; /* pi/2 */ -static double M_PI_4Value = 0.78539816339744830962; /* pi/4 */ -static double M_1_PIValue = 0.31830988618379067154; /* 1/pi */ -static double M_2_PIValue = 0.63661977236758134308; /* 2/pi */ -static double M_2_SQRTPIValue = 1.12837916709551257390; /* 2/sqrt(pi) */ -static double M_SQRT2Value = 1.41421356237309504880; /* sqrt(2) */ -static double M_SQRT1_2Value = 0.70710678118654752440; /* 1/sqrt(2) */ - - -void MathSin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sin(Param[0]->Val->FP); -} - -void MathCos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = cos(Param[0]->Val->FP); -} - -void MathTan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = tan(Param[0]->Val->FP); -} - -void MathAsin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = asin(Param[0]->Val->FP); -} - -void MathAcos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = acos(Param[0]->Val->FP); -} - -void MathAtan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = atan(Param[0]->Val->FP); -} - -void MathAtan2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = atan2(Param[0]->Val->FP, Param[1]->Val->FP); -} - -void MathSinh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sinh(Param[0]->Val->FP); -} - -void MathCosh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = cosh(Param[0]->Val->FP); -} - -void MathTanh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = tanh(Param[0]->Val->FP); -} - -void MathExp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = exp(Param[0]->Val->FP); -} - -void MathFabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = fabs(Param[0]->Val->FP); -} - -void MathFmod(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = fmod(Param[0]->Val->FP, Param[1]->Val->FP); -} - -void MathFrexp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = frexp(Param[0]->Val->FP, Param[1]->Val->Pointer); -} - -void MathLdexp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = ldexp(Param[0]->Val->FP, Param[1]->Val->Integer); -} - -void MathLog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = log(Param[0]->Val->FP); -} - -void MathLog10(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = log10(Param[0]->Val->FP); -} - -void MathModf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = modf(Param[0]->Val->FP, Param[0]->Val->Pointer); -} - -void MathPow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = pow(Param[0]->Val->FP, Param[1]->Val->FP); -} - -void MathSqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = sqrt(Param[0]->Val->FP); -} - -void MathRound(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - /* this awkward definition of "round()" due to it being inconsistently - * declared in math.h */ - ReturnValue->Val->FP = ceil(Param[0]->Val->FP - 0.5); -} - -void MathCeil(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = ceil(Param[0]->Val->FP); -} - -void MathFloor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = floor(Param[0]->Val->FP); -} - -/* all math.h functions */ -struct LibraryFunction MathFunctions[] = -{ - { MathAcos, "float acos(float);" }, - { MathAsin, "float asin(float);" }, - { MathAtan, "float atan(float);" }, - { MathAtan2, "float atan2(float, float);" }, - { MathCeil, "float ceil(float);" }, - { MathCos, "float cos(float);" }, - { MathCosh, "float cosh(float);" }, - { MathExp, "float exp(float);" }, - { MathFabs, "float fabs(float);" }, - { MathFloor, "float floor(float);" }, - { MathFmod, "float fmod(float, float);" }, - { MathFrexp, "float frexp(float, int *);" }, - { MathLdexp, "float ldexp(float, int);" }, - { MathLog, "float log(float);" }, - { MathLog10, "float log10(float);" }, - { MathModf, "float modf(float, float *);" }, - { MathPow, "float pow(float,float);" }, - { MathRound, "float round(float);" }, - { MathSin, "float sin(float);" }, - { MathSinh, "float sinh(float);" }, - { MathSqrt, "float sqrt(float);" }, - { MathTan, "float tan(float);" }, - { MathTanh, "float tanh(float);" }, - { NULL, NULL } -}; - -/* creates various system-dependent definitions */ -void MathSetupFunc(void) -{ - VariableDefinePlatformVar(NULL, "M_E", &FPType, (union AnyValue *)&M_EValue, FALSE); - VariableDefinePlatformVar(NULL, "M_LOG2E", &FPType, (union AnyValue *)&M_LOG2EValue, FALSE); - VariableDefinePlatformVar(NULL, "M_LOG10E", &FPType, (union AnyValue *)&M_LOG10EValue, FALSE); - VariableDefinePlatformVar(NULL, "M_LN2", &FPType, (union AnyValue *)&M_LN2Value, FALSE); - VariableDefinePlatformVar(NULL, "M_LN10", &FPType, (union AnyValue *)&M_LN10Value, FALSE); - VariableDefinePlatformVar(NULL, "M_PI", &FPType, (union AnyValue *)&M_PIValue, FALSE); - VariableDefinePlatformVar(NULL, "M_PI_2", &FPType, (union AnyValue *)&M_PI_2Value, FALSE); - VariableDefinePlatformVar(NULL, "M_PI_4", &FPType, (union AnyValue *)&M_PI_4Value, FALSE); - VariableDefinePlatformVar(NULL, "M_1_PI", &FPType, (union AnyValue *)&M_1_PIValue, FALSE); - VariableDefinePlatformVar(NULL, "M_2_PI", &FPType, (union AnyValue *)&M_2_PIValue, FALSE); - VariableDefinePlatformVar(NULL, "M_2_SQRTPI", &FPType, (union AnyValue *)&M_2_SQRTPIValue, FALSE); - VariableDefinePlatformVar(NULL, "M_SQRT2", &FPType, (union AnyValue *)&M_SQRT2Value, FALSE); - VariableDefinePlatformVar(NULL, "M_SQRT1_2", &FPType, (union AnyValue *)&M_SQRT1_2Value, FALSE); -} - -#endif /* !NO_FP */ -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/stdbool.c b/ecilib/cstdlib/stdbool.c deleted file mode 100644 index 30b2528..0000000 --- a/ecilib/cstdlib/stdbool.c +++ /dev/null @@ -1,22 +0,0 @@ -/* string.h library for large systems - small embedded systems use clibrary.c instead */ -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -static int trueValue = 1; -static int falseValue = 0; - - -/* structure definitions */ -const char StdboolDefs[] = "typedef int bool;"; - -/* creates various system-dependent definitions */ -void StdboolSetupFunc(void) -{ - /* defines */ - VariableDefinePlatformVar(NULL, "true", &IntType, (union AnyValue *)&trueValue, FALSE); - VariableDefinePlatformVar(NULL, "false", &IntType, (union AnyValue *)&falseValue, FALSE); - VariableDefinePlatformVar(NULL, "__bool_true_false_are_defined", &IntType, (union AnyValue *)&trueValue, FALSE); -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/stdio.c b/ecilib/cstdlib/stdio.c deleted file mode 100644 index 4a79a8d..0000000 --- a/ecilib/cstdlib/stdio.c +++ /dev/null @@ -1,722 +0,0 @@ -/* stdio.h library for large systems - small embedded systems use clibrary.c instead */ -#include -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -#define MAX_FORMAT 80 -#define MAX_SCANF_ARGS 10 - -FILE *CStdOut; - -static int ZeroValue = 0; -static int EOFValue = EOF; -static int SEEK_SETValue = SEEK_SET; -static int SEEK_CURValue = SEEK_CUR; -static int SEEK_ENDValue = SEEK_END; -static int BUFSIZValue = BUFSIZ; -static int FILENAME_MAXValue = FILENAME_MAX; -static int _IOFBFValue = _IOFBF; -static int _IOLBFValue = _IOLBF; -static int _IONBFValue = _IONBF; -static int L_tmpnamValue = L_tmpnam; -static int GETS_MAXValue = 255; /* arbitrary maximum size of a gets() file */ - -static FILE *stdinValue; -static FILE *stdoutValue; -static FILE *stderrValue; - -struct ValueType *FilePtrType = NULL; - - -/* our own internal output stream which can output to FILE * or strings */ -typedef struct StdOutStreamStruct -{ - FILE *FilePtr; - char *StrOutPtr; - int StrOutLen; - int CharCount; - -} StdOutStream; - -/* our representation of varargs within picoc */ -struct StdVararg -{ - struct Value **Param; - int NumArgs; -}; - -/* initialises the I/O system so error reporting works */ -void BasicIOInit() -{ - CStdOut = stdout; - stdinValue = stdin; - stdoutValue = stdout; - stderrValue = stderr; -} - -/* output a single character to either a FILE * or a string */ -void StdioOutPutc(int OutCh, StdOutStream *Stream) -{ - if (Stream->FilePtr != NULL) - { - /* output to stdio stream */ - putc(OutCh, Stream->FilePtr); - Stream->CharCount++; - } - else if (Stream->StrOutLen < 0 || Stream->StrOutLen > 1) - { - /* output to a string */ - *Stream->StrOutPtr = OutCh; - Stream->StrOutPtr++; - - if (Stream->StrOutLen > 1) - Stream->StrOutLen--; - - Stream->CharCount++; - } -} - -/* output a string to either a FILE * or a string */ -void StdioOutPuts(const char *Str, StdOutStream *Stream) -{ - if (Stream->FilePtr != NULL) - { - /* output to stdio stream */ - fputs(Str, Stream->FilePtr); - } - else - { - /* output to a string */ - while (*Str != '\0') - { - if (Stream->StrOutLen < 0 || Stream->StrOutLen > 1) - { - /* output to a string */ - *Stream->StrOutPtr = *Str; - Str++; - Stream->StrOutPtr++; - - if (Stream->StrOutLen > 1) - Stream->StrOutLen--; - - Stream->CharCount++; - } - } - } -} - -/* printf-style format of an int or other word-sized object */ -void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned int Value) -{ - if (Stream->FilePtr != NULL) - Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); - - else if (Stream->StrOutLen >= 0) - { - int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); - Stream->StrOutPtr += CCount; - Stream->StrOutLen -= CCount; - Stream->CharCount += CCount; - } - else - { - int CCount = sprintf(Stream->StrOutPtr, Format, Value); - Stream->CharCount += CCount; - Stream->StrOutPtr += CCount; - } -} - -/* printf-style format of a floating point number */ -void StdioFprintfFP(StdOutStream *Stream, const char *Format, double Value) -{ - if (Stream->FilePtr != NULL) - Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); - - else if (Stream->StrOutLen >= 0) - { - int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); - Stream->StrOutPtr += CCount; - Stream->StrOutLen -= CCount; - Stream->CharCount += CCount; - } - else - { - int CCount = sprintf(Stream->StrOutPtr, Format, Value); - Stream->CharCount += CCount; - Stream->StrOutPtr += CCount; - } -} - -/* printf-style format of a pointer */ -void StdioFprintfPointer(StdOutStream *Stream, const char *Format, void *Value) -{ - if (Stream->FilePtr != NULL) - Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); - - else if (Stream->StrOutLen >= 0) - { - int CCount = snprintf(Stream->StrOutPtr, Stream->StrOutLen, Format, Value); - Stream->StrOutPtr += CCount; - Stream->StrOutLen -= CCount; - Stream->CharCount += CCount; - } - else - { - int CCount = sprintf(Stream->StrOutPtr, Format, Value); - Stream->CharCount += CCount; - Stream->StrOutPtr += CCount; - } -} - -/* internal do-anything v[s][n]printf() formatting system with output to strings or FILE * */ -int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int StrOutLen, char *Format, struct StdVararg *Args) -{ - struct Value *ThisArg = Args->Param[0]; - int ArgCount = 0; - char *FPos = Format; - char OneFormatBuf[MAX_FORMAT+1]; - int OneFormatCount; - struct ValueType *ShowType; - StdOutStream SOStream; - - SOStream.FilePtr = Stream; - SOStream.StrOutPtr = StrOut; - SOStream.StrOutLen = StrOutLen; - SOStream.CharCount = 0; - - while (*FPos != '\0') - { - if (*FPos == '%') - { - /* work out what type we're printing */ - FPos++; - ShowType = NULL; - OneFormatBuf[0] = '%'; - OneFormatCount = 1; - - do - { - switch (*FPos) - { - case 'd': case 'i': ShowType = &IntType; break; /* integer decimal */ - case 'o': case 'u': case 'x': case 'X': ShowType = &IntType; break; /* integer base conversions */ -#ifndef NO_FP - case 'e': case 'E': ShowType = &FPType; break; /* double, exponent form */ - case 'f': case 'F': ShowType = &FPType; break; /* double, fixed-point */ - case 'g': case 'G': ShowType = &FPType; break; /* double, flexible format */ -#endif - case 'a': case 'A': ShowType = &IntType; break; /* hexadecimal, 0x- format */ - case 'c': ShowType = &IntType; break; /* character */ - case 's': ShowType = CharPtrType; break; /* string */ - case 'p': ShowType = VoidPtrType; break; /* pointer */ - case 'n': ShowType = &VoidType; break; /* number of characters written */ - case 'm': ShowType = &VoidType; break; /* strerror(errno) */ - case '%': ShowType = &VoidType; break; /* just a '%' character */ - case '\0': ShowType = &VoidType; break; /* end of format string */ - } - - /* copy one character of format across to the OneFormatBuf */ - OneFormatBuf[OneFormatCount] = *FPos; - OneFormatCount++; - - /* do special actions depending on the conversion type */ - if (ShowType == &VoidType) - { - switch (*FPos) - { - case 'm': StdioOutPuts(strerror(errno), &SOStream); break; - case '%': StdioOutPutc(*FPos, &SOStream); break; - case '\0': OneFormatBuf[OneFormatCount] = '\0'; StdioOutPutc(*FPos, &SOStream); break; - case 'n': - ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); - if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeInt) - *(int *)ThisArg->Val->Pointer = SOStream.CharCount; - break; - } - } - - FPos++; - - } while (ShowType == NULL && OneFormatCount < MAX_FORMAT); - - if (ShowType != &VoidType) - { - if (ArgCount >= Args->NumArgs) - StdioOutPuts("XXX", &SOStream); - else - { - /* null-terminate the buffer */ - OneFormatBuf[OneFormatCount] = '\0'; - - /* print this argument */ - ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); - if (ShowType == &IntType) - { - /* show a signed integer */ - if (IS_NUMERIC_COERCIBLE(ThisArg)) - StdioFprintfWord(&SOStream, OneFormatBuf, ExpressionCoerceUnsignedInteger(ThisArg)); - else - StdioOutPuts("XXX", &SOStream); - } -#ifndef NO_FP - else if (ShowType == &FPType) - { - /* show a floating point number */ - if (IS_NUMERIC_COERCIBLE(ThisArg)) - StdioFprintfFP(&SOStream, OneFormatBuf, ExpressionCoerceFP(ThisArg)); - else - StdioOutPuts("XXX", &SOStream); - } -#endif - else if (ShowType == CharPtrType) - { - if (ThisArg->Typ->Base == TypePointer) - StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); - - else if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeChar) - StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); - - else - StdioOutPuts("XXX", &SOStream); - } - else if (ShowType == VoidPtrType) - { - if (ThisArg->Typ->Base == TypePointer) - StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); - - else if (ThisArg->Typ->Base == TypeArray) - StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); - - else - StdioOutPuts("XXX", &SOStream); - } - - ArgCount++; - } - } - } - else - { - /* just output a normal character */ - StdioOutPutc(*FPos, &SOStream); - FPos++; - } - } - - /* null-terminate */ - if (SOStream.StrOutPtr != NULL && SOStream.StrOutLen > 0) - *SOStream.StrOutPtr = '\0'; - - return SOStream.CharCount; -} - -/* internal do-anything v[s][n]scanf() formatting system with input from strings or FILE * */ -int StdioBaseScanf(struct ParseState *Parser, FILE *Stream, char *StrIn, char *Format, struct StdVararg *Args) -{ - struct Value *ThisArg = Args->Param[0]; - int ArgCount = 0; - void *ScanfArg[MAX_SCANF_ARGS]; - - if (Args->NumArgs > MAX_SCANF_ARGS) - ProgramFail(Parser, "too many arguments to scanf() - %d max", MAX_SCANF_ARGS); - - for (ArgCount = 0; ArgCount < Args->NumArgs; ArgCount++) - { - ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); - - if (ThisArg->Typ->Base == TypePointer) - ScanfArg[ArgCount] = ThisArg->Val->Pointer; - - else if (ThisArg->Typ->Base == TypeArray) - ScanfArg[ArgCount] = &ThisArg->Val->ArrayMem[0]; - - else - ProgramFail(Parser, "non-pointer argument to scanf() - argument %d after format", ArgCount+1); - } - - if (Stream != NULL) - return fscanf(Stream, Format, ScanfArg[0], ScanfArg[1], ScanfArg[2], ScanfArg[3], ScanfArg[4], ScanfArg[5], ScanfArg[6], ScanfArg[7], ScanfArg[8], ScanfArg[9]); - else - return sscanf(StrIn, Format, ScanfArg[0], ScanfArg[1], ScanfArg[2], ScanfArg[3], ScanfArg[4], ScanfArg[5], ScanfArg[6], ScanfArg[7], ScanfArg[8], ScanfArg[9]); -} - -/* stdio calls */ -void StdioFopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = fopen(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioFreopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = freopen(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -void StdioFclose(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fclose(Param[0]->Val->Pointer); -} - -void StdioFread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fread(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->Pointer); -} - -void StdioFwrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fwrite(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer, Param[3]->Val->Pointer); -} - -void StdioFgetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fgetc(Param[0]->Val->Pointer); -} - -void StdioFgets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = fgets(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer); -} - -void StdioRemove(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = remove(Param[0]->Val->Pointer); -} - -void StdioRename(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = rename(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioRewind(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - rewind(Param[0]->Val->Pointer); -} - -void StdioTmpfile(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = tmpfile(); -} - -void StdioClearerr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - clearerr((FILE *)Param[0]->Val->Pointer); -} - -void StdioFeof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = feof((FILE *)Param[0]->Val->Pointer); -} - -void StdioFerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ferror((FILE *)Param[0]->Val->Pointer); -} - -void StdioFileno(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fileno(Param[0]->Val->Pointer); -} - -void StdioFflush(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fflush(Param[0]->Val->Pointer); -} - -void StdioFgetpos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fgetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioFsetpos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fsetpos(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioFputc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fputc(Param[0]->Val->Integer, Param[1]->Val->Pointer); -} - -void StdioFputs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fputs(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioFtell(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ftell(Param[0]->Val->Pointer); -} - -void StdioFseek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fseek(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void StdioPerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - perror(Param[0]->Val->Pointer); -} - -void StdioPutc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = putc(Param[0]->Val->Integer, Param[1]->Val->Pointer); -} - -void StdioPutchar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = putchar(Param[0]->Val->Integer); -} - -void StdioSetbuf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - setbuf(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioSetvbuf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - setvbuf(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer); -} - -void StdioUngetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ungetc(Param[0]->Val->Integer, Param[1]->Val->Pointer); -} - -void StdioPuts(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = puts(Param[0]->Val->Pointer); -} - -void StdioGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = fgets(Param[0]->Val->Pointer, GETS_MAXValue, stdin); - if (ReturnValue->Val->Pointer != NULL) - { - char *EOLPos = strchr(Param[0]->Val->Pointer, '\n'); - if (EOLPos != NULL) - *EOLPos = '\0'; - } -} - -void StdioGetchar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getchar(); -} - -void StdioPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg PrintfArgs; - - PrintfArgs.Param = Param; - PrintfArgs.NumArgs = NumArgs-1; - ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, NULL, 0, Param[0]->Val->Pointer, &PrintfArgs); -} - -void StdioVprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, NULL, 0, Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioFprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg PrintfArgs; - - PrintfArgs.Param = Param + 1; - PrintfArgs.NumArgs = NumArgs-2; - ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->Pointer, NULL, 0, Param[1]->Val->Pointer, &PrintfArgs); -} - -void StdioVfprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->Pointer, NULL, 0, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -void StdioSprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg PrintfArgs; - - PrintfArgs.Param = Param + 1; - PrintfArgs.NumArgs = NumArgs-2; - ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, &PrintfArgs); -} - -void StdioSnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg PrintfArgs; - - PrintfArgs.Param = Param+2; - PrintfArgs.NumArgs = NumArgs-3; - ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, &PrintfArgs); -} - -void StdioScanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg ScanfArgs; - - ScanfArgs.Param = Param; - ScanfArgs.NumArgs = NumArgs-1; - ReturnValue->Val->Integer = StdioBaseScanf(Parser, stdin, NULL, Param[0]->Val->Pointer, &ScanfArgs); -} - -void StdioFscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg ScanfArgs; - - ScanfArgs.Param = Param+1; - ScanfArgs.NumArgs = NumArgs-2; - ReturnValue->Val->Integer = StdioBaseScanf(Parser, Param[0]->Val->Pointer, NULL, Param[1]->Val->Pointer, &ScanfArgs); -} - -void StdioSscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - struct StdVararg ScanfArgs; - - ScanfArgs.Param = Param+1; - ScanfArgs.NumArgs = NumArgs-2; - ReturnValue->Val->Integer = StdioBaseScanf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer, &ScanfArgs); -} - -void StdioVsprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, -1, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBasePrintf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer); -} - -void StdioVscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBaseScanf(Parser, stdin, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdioVfscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBaseScanf(Parser, Param[0]->Val->Pointer, NULL, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -void StdioVsscanf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = StdioBaseScanf(Parser, NULL, Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -/* handy structure definitions */ -const char StdioDefs[] = "\ -typedef struct __va_listStruct va_list; \ -typedef struct __FILEStruct FILE;\ -"; - -/* all stdio functions */ -struct LibraryFunction StdioFunctions[] = -{ - { StdioFopen, "FILE *fopen(char *, char *);" }, - { StdioFreopen, "FILE *freopen(char *, char *, FILE *);" }, - { StdioFclose, "int fclose(FILE *);" }, - { StdioFread, "int fread(void *, int, int, FILE *);" }, - { StdioFwrite, "int fwrite(void *, int, int, FILE *);" }, - { StdioFgetc, "int fgetc(FILE *);" }, - { StdioFgetc, "int getc(FILE *);" }, - { StdioFgets, "char *fgets(char *, int, FILE *);" }, - { StdioFputc, "int fputc(int, FILE *);" }, - { StdioFputs, "int fputs(char *, FILE *);" }, - { StdioRemove, "int remove(char *);" }, - { StdioRename, "int rename(char *, char *);" }, - { StdioRewind, "void rewind(FILE *);" }, - { StdioTmpfile, "FILE *tmpfile();" }, - { StdioClearerr,"void clearerr(FILE *);" }, - { StdioFeof, "int feof(FILE *);" }, - { StdioFerror, "int ferror(FILE *);" }, - { StdioFileno, "int fileno(FILE *);" }, - { StdioFflush, "int fflush(FILE *);" }, - { StdioFgetpos, "int fgetpos(FILE *, int *);" }, - { StdioFsetpos, "int fsetpos(FILE *, int *);" }, - { StdioFtell, "int ftell(FILE *);" }, - { StdioFseek, "int fseek(FILE *, int, int);" }, - { StdioPerror, "void perror(char *);" }, - { StdioPutc, "int putc(char *, FILE *);" }, - { StdioPutchar, "int putchar(int);" }, - { StdioPutchar, "int fputchar(int);" }, - { StdioSetbuf, "void setbuf(FILE *, char *);" }, - { StdioSetvbuf, "void setvbuf(FILE *, char *, int, int);" }, - { StdioUngetc, "int ungetc(int, FILE *);" }, - { StdioPuts, "int puts(char *);" }, - { StdioGets, "char *gets(char *);" }, - { StdioGetchar, "int getchar();" }, - { StdioPrintf, "int printf(char *, ...);" }, - { StdioFprintf, "int fprintf(FILE *, char *, ...);" }, - { StdioSprintf, "int sprintf(char *, char *, ...);" }, - { StdioSnprintf,"int snprintf(char *, int, char *, ...);" }, - { StdioScanf, "int scanf(char *, ...);" }, - { StdioFscanf, "int fscanf(FILE *, char *, ...);" }, - { StdioSscanf, "int sscanf(char *, char *, ...);" }, - { StdioVprintf, "int vprintf(char *, va_list);" }, - { StdioVfprintf,"int vfprintf(FILE *, char *, va_list);" }, - { StdioVsprintf,"int vsprintf(char *, char *, va_list);" }, - { StdioVsnprintf,"int vsnprintf(char *, int, char *, va_list);" }, - { StdioVscanf, "int vscanf(char *, va_list);" }, - { StdioVfscanf, "int vfscanf(FILE *, char *, va_list);" }, - { StdioVsscanf, "int vsscanf(char *, char *, va_list);" }, - { NULL, NULL } -}; - -/* creates various system-dependent definitions */ -void StdioSetupFunc(void) -{ - struct ValueType *StructFileType; - struct ValueType *FilePtrType; - - /* make a "struct __FILEStruct" which is the same size as a native FILE structure */ - StructFileType = TypeCreateOpaqueStruct(NULL, TableStrRegister("__FILEStruct"), sizeof(FILE)); - - /* get a FILE * type */ - FilePtrType = TypeGetMatching(NULL, StructFileType, TypePointer, 0, StrEmpty, TRUE); - - /* make a "struct __va_listStruct" which is the same size as our struct StdVararg */ - TypeCreateOpaqueStruct(NULL, TableStrRegister("__va_listStruct"), sizeof(FILE)); - - /* define EOF equal to the system EOF */ - VariableDefinePlatformVar(NULL, "EOF", &IntType, (union AnyValue *)&EOFValue, FALSE); - VariableDefinePlatformVar(NULL, "SEEK_SET", &IntType, (union AnyValue *)&SEEK_SETValue, FALSE); - VariableDefinePlatformVar(NULL, "SEEK_CUR", &IntType, (union AnyValue *)&SEEK_CURValue, FALSE); - VariableDefinePlatformVar(NULL, "SEEK_END", &IntType, (union AnyValue *)&SEEK_ENDValue, FALSE); - VariableDefinePlatformVar(NULL, "BUFSIZ", &IntType, (union AnyValue *)&BUFSIZValue, FALSE); - VariableDefinePlatformVar(NULL, "FILENAME_MAX", &IntType, (union AnyValue *)&FILENAME_MAXValue, FALSE); - VariableDefinePlatformVar(NULL, "_IOFBF", &IntType, (union AnyValue *)&_IOFBFValue, FALSE); - VariableDefinePlatformVar(NULL, "_IOLBF", &IntType, (union AnyValue *)&_IOLBFValue, FALSE); - VariableDefinePlatformVar(NULL, "_IONBF", &IntType, (union AnyValue *)&_IONBFValue, FALSE); - VariableDefinePlatformVar(NULL, "L_tmpnam", &IntType, (union AnyValue *)&L_tmpnamValue, FALSE); - VariableDefinePlatformVar(NULL, "GETS_MAX", &IntType, (union AnyValue *)&GETS_MAXValue, FALSE); - - /* define stdin, stdout and stderr */ - VariableDefinePlatformVar(NULL, "stdin", FilePtrType, (union AnyValue *)&stdinValue, FALSE); - VariableDefinePlatformVar(NULL, "stdout", FilePtrType, (union AnyValue *)&stdoutValue, FALSE); - VariableDefinePlatformVar(NULL, "stderr", FilePtrType, (union AnyValue *)&stderrValue, FALSE); - - /* define NULL, TRUE and FALSE */ - if (!VariableDefined(TableStrRegister("NULL"))) - VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); -} - -/* portability-related I/O calls */ -void PrintCh(char OutCh, FILE *Stream) -{ - putc(OutCh, Stream); -} - -void PrintSimpleInt(long Num, FILE *Stream) -{ - fprintf(Stream, "%ld", Num); -} - -void PrintStr(const char *Str, FILE *Stream) -{ - fputs(Str, Stream); -} - -void PrintFP(double Num, FILE *Stream) -{ - fprintf(Stream, "%f", Num); -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/stdlib.c b/ecilib/cstdlib/stdlib.c deleted file mode 100644 index 8eebb1c..0000000 --- a/ecilib/cstdlib/stdlib.c +++ /dev/null @@ -1,174 +0,0 @@ -/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */ -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -static int ZeroValue = 0; - -#ifndef NO_FP -void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = atof(Param[0]->Val->Pointer); -} -#endif - -void StdlibAtoi(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = atoi(Param[0]->Val->Pointer); -} - -void StdlibAtol(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = atol(Param[0]->Val->Pointer); -} - -#ifndef NO_FP -void StdlibStrtod(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = strtod(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} -#endif - -void StdlibStrtol(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strtol(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StdlibStrtoul(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strtoul(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StdlibMalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = malloc(Param[0]->Val->Integer); -} - -void StdlibCalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = calloc(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void StdlibRealloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = realloc(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void StdlibFree(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - free(Param[0]->Val->Pointer); -} - -void StdlibRand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = rand(); -} - -void StdlibSrand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - srand(Param[0]->Val->Integer); -} - -void StdlibAbort(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ProgramFail(Parser, "abort"); -} - -void StdlibExit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - PlatformExit(Param[0]->Val->Integer); -} - -void StdlibGetenv(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = getenv(Param[0]->Val->Pointer); -} - -void StdlibSystem(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = system(Param[0]->Val->Pointer); -} - -#if 0 -void StdlibBsearch(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = bsearch(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer, (int (*)())Param[4]->Val->Pointer); -} -#endif - -void StdlibAbs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = abs(Param[0]->Val->Integer); -} - -void StdlibLabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = labs(Param[0]->Val->Integer); -} - -#if 0 -void StdlibDiv(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = div(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void StdlibLdiv(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ldiv(Param[0]->Val->Integer, Param[1]->Val->Integer); -} -#endif - -#if 0 -/* handy structure definitions */ -const char StdlibDefs[] = "\ -typedef struct { \ - int quot, rem; \ -} div_t; \ -\ -typedef struct { \ - int quot, rem; \ -} ldiv_t; \ -"; -#endif - -/* all stdlib.h functions */ -struct LibraryFunction StdlibFunctions[] = -{ -#ifndef NO_FP - { StdlibAtof, "float atof(char *);" }, - { StdlibStrtod, "float strtod(char *,char **);" }, -#endif - { StdlibAtoi, "int atoi(char *);" }, - { StdlibAtol, "int atol(char *);" }, - { StdlibStrtol, "int strtol(char *,char **,int);" }, - { StdlibStrtoul, "int strtoul(char *,char **,int);" }, - { StdlibMalloc, "void *malloc(int);" }, - { StdlibCalloc, "void *calloc(int,int);" }, - { StdlibRealloc, "void *realloc(void *,int);" }, - { StdlibFree, "void free(void *);" }, - { StdlibRand, "int rand();" }, - { StdlibSrand, "void srand(int);" }, - { StdlibAbort, "void abort();" }, - { StdlibExit, "void exit(int);" }, - { StdlibGetenv, "char *getenv(char *);" }, - { StdlibSystem, "int system(char *);" }, -/* { StdlibBsearch, "void *bsearch(void *,void *,int,int,int (*)());" }, */ -/* { StdlibQsort, "void *qsort(void *,int,int,int (*)());" }, */ - { StdlibAbs, "int abs(int);" }, - { StdlibLabs, "int labs(int);" }, -#if 0 - { StdlibDiv, "div_t div(int);" }, - { StdlibLdiv, "ldiv_t ldiv(int);" }, -#endif - { NULL, NULL } -}; - -/* creates various system-dependent definitions */ -void StdlibSetupFunc(void) -{ - /* define NULL, TRUE and FALSE */ - if (!VariableDefined(TableStrRegister("NULL"))) - VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/string.c b/ecilib/cstdlib/string.c deleted file mode 100644 index 88f349f..0000000 --- a/ecilib/cstdlib/string.c +++ /dev/null @@ -1,178 +0,0 @@ -/* string.h library for large systems - small embedded systems use clibrary.c instead */ -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -static int ZeroValue = 0; - -void StringStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrncpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strncpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringStrcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strcmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrncmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strncmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringStrcat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strcat(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrncat(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strncat(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringIndex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = index(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void StringRindex(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = rindex(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void StringStrlen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strlen(Param[0]->Val->Pointer); -} - -void StringMemset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = memset(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void StringMemcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = memcpy(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringMemcmp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = memcmp(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringMemmove(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = memmove(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringMemchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = memchr(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void StringStrchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strchr(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void StringStrrchr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strrchr(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void StringStrcoll(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strcoll(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrerror(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strerror(Param[0]->Val->Integer); -} - -void StringStrspn(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strspn(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrcspn(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strcspn(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrpbrk(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strpbrk(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrstr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strstr(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrtok(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strtok(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StringStrxfrm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strxfrm(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void StringStrdup(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strdup(Param[0]->Val->Pointer); -} - -void StringStrtok_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = strtok_r(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -/* all string.h functions */ -struct LibraryFunction StringFunctions[] = -{ - { StringIndex, "char *index(char *,int);" }, - { StringRindex, "char *rindex(char *,int);" }, - { StringMemcpy, "void *memcpy(void *,void *,int);" }, - { StringMemmove, "void *memmove(void *,void *,int);" }, - { StringMemchr, "void *memchr(char *,int,int);" }, - { StringMemcmp, "int memcmp(void *,void *,int);" }, - { StringMemset, "void *memset(void *,int,int);" }, - { StringStrcat, "char *strcat(char *,char *);" }, - { StringStrncat, "char *strncat(char *,char *,int);" }, - { StringStrchr, "char *strchr(char *,int);" }, - { StringStrrchr, "char *strrchr(char *,int);" }, - { StringStrcmp, "int strcmp(char *,char *);" }, - { StringStrncmp, "int strncmp(char *,char *,int);" }, - { StringStrcoll, "int strcoll(char *,char *);" }, - { StringStrcpy, "char *strcpy(char *,char *);" }, - { StringStrncpy, "char *strncpy(char *,char *,int);" }, - { StringStrerror, "char *strerror(int);" }, - { StringStrlen, "int strlen(char *);" }, - { StringStrspn, "int strspn(char *,char *);" }, - { StringStrcspn, "int strcspn(char *,char *);" }, - { StringStrpbrk, "char *strpbrk(char *,char *);" }, - { StringStrstr, "char *strstr(char *,char *);" }, - { StringStrtok, "char *strtok(char *,char *);" }, - { StringStrxfrm, "int strxfrm(char *,char *,int);" }, - { StringStrdup, "char *strdup(char *);" }, - { StringStrtok_r, "char *strtok_r(char *,char *,char **);" }, - { NULL, NULL } -}; - -/* creates various system-dependent definitions */ -void StringSetupFunc(void) -{ - /* define NULL */ - if (!VariableDefined(TableStrRegister("NULL"))) - VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/time.c b/ecilib/cstdlib/time.c deleted file mode 100644 index 0406679..0000000 --- a/ecilib/cstdlib/time.c +++ /dev/null @@ -1,124 +0,0 @@ -/* string.h library for large systems - small embedded systems use clibrary.c instead */ -#include -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -static int CLOCKS_PER_SECValue = CLOCKS_PER_SEC; - -#ifdef CLK_PER_SEC -static int CLK_PER_SECValue = CLK_PER_SEC; -#endif - -#ifdef CLK_TCK -static int CLK_TCKValue = CLK_TCK; -#endif - -void StdAsctime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = asctime(Param[0]->Val->Pointer); -} - -void StdClock(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = clock(); -} - -void StdCtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = ctime(Param[0]->Val->Pointer); -} - -#ifndef NO_FP -void StdDifftime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->FP = difftime((time_t)Param[0]->Val->Integer, Param[1]->Val->Integer); -} -#endif - -void StdGmtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = gmtime(Param[0]->Val->Pointer); -} - -void StdGmtime_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = gmtime_r(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void StdLocaltime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = localtime(Param[0]->Val->Pointer); -} - -void StdMktime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = mktime(Param[0]->Val->Pointer); -} - -void StdTime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = time(Param[0]->Val->Pointer); -} - -void StdStrftime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = strftime(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Pointer, Param[3]->Val->Pointer); -} - -void StdStrptime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - extern char *strptime(const char *s, const char *format, struct tm *tm); - - ReturnValue->Val->Pointer = strptime(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Pointer); -} - -void StdTimegm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = timegm(Param[0]->Val->Pointer); -} - -/* handy structure definitions */ -const char StdTimeDefs[] = "\ -typedef int time_t; \ -typedef int clock_t;\ -"; - -/* all string.h functions */ -struct LibraryFunction StdTimeFunctions[] = -{ - { StdAsctime, "char *asctime(struct tm *);" }, - { StdClock, "time_t clock();" }, - { StdCtime, "char *ctime(int *);" }, -#ifndef NO_FP - { StdDifftime, "double difftime(int, int);" }, -#endif - { StdGmtime, "struct tm *gmtime(int *);" }, - { StdGmtime_r, "struct tm *gmtime_r(int *, struct tm *);" }, - { StdLocaltime, "struct tm *localtime(int *);" }, - { StdMktime, "int mktime(struct tm *ptm);" }, - { StdTime, "int time(int *);" }, - { StdStrftime, "int strftime(char *, int, char *, struct tm *);" }, - { StdStrptime, "char *strptime(char *, char *, struct tm *);" }, - { StdTimegm, "int timegm(struct tm *);" }, - { NULL, NULL } -}; - - -/* creates various system-dependent definitions */ -void StdTimeSetupFunc(void) -{ - /* make a "struct tm" which is the same size as a native tm structure */ - TypeCreateOpaqueStruct(NULL, TableStrRegister("tm"), sizeof(struct tm)); - - /* define CLK_PER_SEC etc. */ - VariableDefinePlatformVar(NULL, "CLOCKS_PER_SEC", &IntType, (union AnyValue *)&CLOCKS_PER_SECValue, FALSE); -#ifdef CLK_PER_SEC - VariableDefinePlatformVar(NULL, "CLK_PER_SEC", &IntType, (union AnyValue *)&CLK_PER_SECValue, FALSE); -#endif -#ifdef CLK_TCK - VariableDefinePlatformVar(NULL, "CLK_TCK", &IntType, (union AnyValue *)&CLK_TCKValue, FALSE); -#endif -} - -#endif /* !BUILTIN_MINI_STDLIB */ diff --git a/ecilib/cstdlib/unistd.c b/ecilib/cstdlib/unistd.c deleted file mode 100644 index a8dfa37..0000000 --- a/ecilib/cstdlib/unistd.c +++ /dev/null @@ -1,499 +0,0 @@ -/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */ -#include -#include -#include -#include "../interpreter.h" - -#ifndef BUILTIN_MINI_STDLIB - -static int ZeroValue = 0; - -void UnistdAccess(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = access(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void UnistdAlarm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = alarm(Param[0]->Val->Integer); -} - -void UnistdChdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = chdir(Param[0]->Val->Pointer); -} - -void UnistdChroot(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = chroot(Param[0]->Val->Pointer); -} - -void UnistdChown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = chown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void UnistdClose(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = close(Param[0]->Val->Integer); -} - -void UnistdConfstr(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = confstr(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void UnistdCtermid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = ctermid(Param[0]->Val->Pointer); -} - -#if 0 -void UnistdCuserid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = cuserid(Param[0]->Val->Pointer); -} -#endif - -void UnistdDup(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = dup(Param[0]->Val->Integer); -} - -void UnistdDup2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = dup2(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void Unistd_Exit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - _exit(Param[0]->Val->Integer); -} - -void UnistdFchown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fchown(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void UnistdFchdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fchdir(Param[0]->Val->Integer); -} - -void UnistdFdatasync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fdatasync(Param[0]->Val->Integer); -} - -void UnistdFork(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fork(); -} - -void UnistdFpathconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fpathconf(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdFsync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = fsync(Param[0]->Val->Integer); -} - -void UnistdFtruncate(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ftruncate(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdGetcwd(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void UnistdGetdtablesize(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getdtablesize(); -} - -void UnistdGetegid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getegid(); -} - -void UnistdGeteuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = geteuid(); -} - -void UnistdGetgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getgid(); -} - -void UnistdGethostid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = gethostid(); -} - -void UnistdGetlogin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = getlogin(); -} - -void UnistdGetlogin_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getlogin_r(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void UnistdGetpagesize(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getpagesize(); -} - -void UnistdGetpass(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = getpass(Param[0]->Val->Pointer); -} - -#if 0 -void UnistdGetpgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getpgid(Param[0]->Val->Integer); -} -#endif - -void UnistdGetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getpgrp(); -} - -void UnistdGetpid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getpid(); -} - -void UnistdGetppid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getppid(); -} - -#if 0 -void UnistdGetsid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getsid(Param[0]->Val->Integer); -} -#endif - -void UnistdGetuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = getuid(); -} - -void UnistdGetwd(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = getcwd(Param[0]->Val->Pointer, PATH_MAX); -} - -void UnistdIsatty(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = isatty(Param[0]->Val->Integer); -} - -void UnistdLchown(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = lchown(Param[0]->Val->Pointer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void UnistdLink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = link(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void UnistdLockf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = lockf(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void UnistdLseek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = lseek(Param[0]->Val->Integer, Param[1]->Val->Integer, Param[2]->Val->Integer); -} - -void UnistdNice(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = nice(Param[0]->Val->Integer); -} - -void UnistdPathconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = pathconf(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void UnistdPause(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = pause(); -} - -#if 0 -void UnistdPread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = pread(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer); -} - -void UnistdPwrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = pwrite(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer, Param[3]->Val->Integer); -} -#endif - -void UnistdRead(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = read(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void UnistdReadlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = readlink(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void UnistdRmdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = rmdir(Param[0]->Val->Pointer); -} - -void UnistdSbrk(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = sbrk(Param[0]->Val->Integer); -} - -void UnistdSetgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setgid(Param[0]->Val->Integer); -} - -void UnistdSetpgid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setpgid(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdSetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setpgrp(); -} - -void UnistdSetregid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setregid(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdSetreuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setreuid(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdSetsid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setsid(); -} - -void UnistdSetuid(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = setuid(Param[0]->Val->Integer); -} - -void UnistdSleep(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = sleep(Param[0]->Val->Integer); -} - -#if 0 -void UnistdSwab(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = swab(Param[0]->Val->Pointer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} -#endif - -void UnistdSymlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = symlink(Param[0]->Val->Pointer, Param[1]->Val->Pointer); -} - -void UnistdSync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - sync(); -} - -void UnistdSysconf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = sysconf(Param[0]->Val->Integer); -} - -void UnistdTcgetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = tcgetpgrp(Param[0]->Val->Integer); -} - -void UnistdTcsetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = tcsetpgrp(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdTruncate(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = truncate(Param[0]->Val->Pointer, Param[1]->Val->Integer); -} - -void UnistdTtyname(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Pointer = ttyname(Param[0]->Val->Integer); -} - -void UnistdTtyname_r(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ttyname_r(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - -void UnistdUalarm(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = ualarm(Param[0]->Val->Integer, Param[1]->Val->Integer); -} - -void UnistdUnlink(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = unlink(Param[0]->Val->Pointer); -} - -void UnistdUsleep(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = usleep(Param[0]->Val->Integer); -} - -void UnistdVfork(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = vfork(); -} - -void UnistdWrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = write(Param[0]->Val->Integer, Param[1]->Val->Pointer, Param[2]->Val->Integer); -} - - -/* handy structure definitions */ -const char UnistdDefs[] = "\ -typedef int uid_t; \ -typedef int gid_t; \ -typedef int pid_t; \ -typedef int off_t; \ -typedef int size_t; \ -typedef int ssize_t; \ -typedef int useconds_t;\ -typedef int intptr_t;\ -"; - -/* all unistd.h functions */ -struct LibraryFunction UnistdFunctions[] = -{ - { UnistdAccess, "int access(char *, int);" }, - { UnistdAlarm, "unsigned int alarm(unsigned int);" }, -/* { UnistdBrk, "int brk(void *);" }, */ - { UnistdChdir, "int chdir(char *);" }, - { UnistdChroot, "int chroot(char *);" }, - { UnistdChown, "int chown(char *, uid_t, gid_t);" }, - { UnistdClose, "int close(int);" }, - { UnistdConfstr, "size_t confstr(int, char *, size_t);" }, - { UnistdCtermid, "char *ctermid(char *);" }, -/* { UnistdCuserid, "char *cuserid(char *);" }, */ - { UnistdDup, "int dup(int);" }, - { UnistdDup2, "int dup2(int, int);" }, -/* { UnistdEncrypt, "void encrypt(char[64], int);" }, */ -/* { UnistdExecl, "int execl(char *, char *, ...);" }, */ -/* { UnistdExecle, "int execle(char *, char *, ...);" }, */ -/* { UnistdExeclp, "int execlp(char *, char *, ...);" }, */ -/* { UnistdExecv, "int execv(char *, char *[]);" }, */ -/* { UnistdExecve, "int execve(char *, char *[], char *[]);" }, */ -/* { UnistdExecvp, "int execvp(char *, char *[]);" }, */ - { Unistd_Exit, "void _exit(int);" }, - { UnistdFchown, "int fchown(int, uid_t, gid_t);" }, - { UnistdFchdir, "int fchdir(int);" }, - { UnistdFdatasync, "int fdatasync(int);" }, - { UnistdFork, "pid_t fork(void);" }, - { UnistdFpathconf, "long fpathconf(int, int);" }, - { UnistdFsync, "int fsync(int);" }, - { UnistdFtruncate, "int ftruncate(int, off_t);" }, - { UnistdGetcwd, "char *getcwd(char *, size_t);" }, - { UnistdGetdtablesize, "int getdtablesize(void);" }, - { UnistdGetegid, "gid_t getegid(void);" }, - { UnistdGeteuid, "uid_t geteuid(void);" }, - { UnistdGetgid, "gid_t getgid(void);" }, -/* { UnistdGetgroups, "int getgroups(int, gid_t []);" }, */ - { UnistdGethostid, "long gethostid(void);" }, - { UnistdGetlogin, "char *getlogin(void);" }, - { UnistdGetlogin_r, "int getlogin_r(char *, size_t);" }, -/* { UnistdGetopt, "int getopt(int, char * [], char *);" }, */ - { UnistdGetpagesize, "int getpagesize(void);" }, - { UnistdGetpass, "char *getpass(char *);" }, -/* { UnistdGetpgid, "pid_t getpgid(pid_t);" }, */ - { UnistdGetpgrp, "pid_t getpgrp(void);" }, - { UnistdGetpid, "pid_t getpid(void);" }, - { UnistdGetppid, "pid_t getppid(void);" }, -/* { UnistdGetsid, "pid_t getsid(pid_t);" }, */ - { UnistdGetuid, "uid_t getuid(void);" }, - { UnistdGetwd, "char *getwd(char *);" }, - { UnistdIsatty, "int isatty(int);" }, - { UnistdLchown, "int lchown(char *, uid_t, gid_t);" }, - { UnistdLink, "int link(char *, char *);" }, - { UnistdLockf, "int lockf(int, int, off_t);" }, - { UnistdLseek, "off_t lseek(int, off_t, int);" }, - { UnistdNice, "int nice(int);" }, - { UnistdPathconf, "long pathconf(char *, int);" }, - { UnistdPause, "int pause(void);" }, -/* { UnistdPipe, "int pipe(int [2]);" }, */ -/* { UnistdPread, "ssize_t pread(int, void *, size_t, off_t);" }, */ -/* { UnistdPthread_atfork,"int pthread_atfork(void (*)(void), void (*)(void), void(*)(void));" }, */ -/* { UnistdPwrite, "ssize_t pwrite(int, void *, size_t, off_t);" }, */ - { UnistdRead, "ssize_t read(int, void *, size_t);" }, - { UnistdReadlink, "int readlink(char *, char *, size_t);" }, - { UnistdRmdir, "int rmdir(char *);" }, - { UnistdSbrk, "void *sbrk(intptr_t);" }, - { UnistdSetgid, "int setgid(gid_t);" }, - { UnistdSetpgid, "int setpgid(pid_t, pid_t);" }, - { UnistdSetpgrp, "pid_t setpgrp(void);" }, - { UnistdSetregid, "int setregid(gid_t, gid_t);" }, - { UnistdSetreuid, "int setreuid(uid_t, uid_t);" }, - { UnistdSetsid, "pid_t setsid(void);" }, - { UnistdSetuid, "int setuid(uid_t);" }, - { UnistdSleep, "unsigned int sleep(unsigned int);" }, -/* { UnistdSwab, "void swab(void *, void *, ssize_t);" }, */ - { UnistdSymlink, "int symlink(char *, char *);" }, - { UnistdSync, "void sync(void);" }, - { UnistdSysconf, "long sysconf(int);" }, - { UnistdTcgetpgrp, "pid_t tcgetpgrp(int);" }, - { UnistdTcsetpgrp, "int tcsetpgrp(int, pid_t);" }, - { UnistdTruncate, "int truncate(char *, off_t);" }, - { UnistdTtyname, "char *ttyname(int);" }, - { UnistdTtyname_r, "int ttyname_r(int, char *, size_t);" }, - { UnistdUalarm, "useconds_t ualarm(useconds_t, useconds_t);" }, - { UnistdUnlink, "int unlink(char *);" }, - { UnistdUsleep, "int usleep(useconds_t);" }, - { UnistdVfork, "pid_t vfork(void);" }, - { UnistdWrite, "ssize_t write(int, void *, size_t);" }, - { NULL, NULL } -}; - -/* creates various system-dependent definitions */ -void UnistdSetupFunc(void) -{ - /* define NULL */ - if (!VariableDefined(TableStrRegister("NULL"))) - VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); - - /* define optarg and friends */ - VariableDefinePlatformVar(NULL, "optarg", CharPtrType, (union AnyValue *)&optarg, TRUE); - VariableDefinePlatformVar(NULL, "optind", &IntType, (union AnyValue *)&optind, TRUE); - VariableDefinePlatformVar(NULL, "opterr", &IntType, (union AnyValue *)&opterr, TRUE); - VariableDefinePlatformVar(NULL, "optopt", &IntType, (union AnyValue *)&optopt, TRUE); -} - -#endif /* !BUILTIN_MINI_STDLIB */ - diff --git a/ecilib/expression.c b/ecilib/expression.c deleted file mode 100644 index 69f6f74..0000000 --- a/ecilib/expression.c +++ /dev/null @@ -1,1501 +0,0 @@ -#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 -#define IS_TYPE_TOKEN(t) ((t) >= TokenIntType && (t) <= TokenUnsignedType) - -#define DEEP_PRECEDENCE (BRACKET_PRECEDENCE*1000) - -#ifdef DEBUG_EXPRESSIONS -#define debugf printf -#else -void debugf(char *Format, ...) -{ -} -#endif - -/* local prototypes */ -enum OperatorOrder -{ - OrderNone, - OrderPrefix, - OrderInfix, - OrderPostfix -}; - -/* a stack of expressions we use in evaluation */ -struct ExpressionStack -{ - struct ExpressionStack *Next; /* the next lower item on the stack */ - struct Value *Val; /* the value for this stack node */ - enum LexToken Op; /* the operator */ - short unsigned int Precedence; /* the operator precedence of this node */ - unsigned char Order; /* the evaluation order of this operator */ -}; - -/* operator precedence definitions */ -struct OpPrecedence -{ - unsigned int PrefixPrecedence:4; - unsigned int PostfixPrecedence:4; - unsigned int InfixPrecedence:4; - char *Name; -}; - -/* NOTE: the order of this array must correspond exactly to the order of these tokens in enum LexToken */ -static struct OpPrecedence OperatorPrecedence[] = -{ - /* TokenNone, */ { 0, 0, 0, "none" }, - /* TokenComma, */ { 0, 0, 0, "," }, - /* TokenAssign, */ { 0, 0, 2, "=" }, - /* TokenAddAssign, */ { 0, 0, 2, "+=" }, - /* TokenSubtractAssign, */ { 0, 0, 2, "-=" }, - /* TokenMultiplyAssign, */ { 0, 0, 2, "*=" }, - /* TokenDivideAssign, */ { 0, 0, 2, "/=" }, - /* TokenModulusAssign, */ { 0, 0, 2, "%=" }, - /* TokenShiftLeftAssign, */ { 0, 0, 2, "<<=" }, - /* TokenShiftRightAssign, */ { 0, 0, 2, ">>=" }, - /* TokenArithmeticAndAssign, */ { 0, 0, 2, "&=" }, - /* TokenArithmeticOrAssign, */ { 0, 0, 2, "|=" }, - /* TokenArithmeticExorAssign, */ { 0, 0, 2, "^=" }, - /* TokenQuestionMark, */ { 0, 0, 3, "?" }, - /* TokenColon, */ { 0, 0, 3, ":" }, - /* TokenLogicalOr, */ { 0, 0, 4, "||" }, - /* TokenLogicalAnd, */ { 0, 0, 5, "&&" }, - /* TokenArithmeticOr, */ { 0, 0, 6, "|" }, - /* TokenArithmeticExor, */ { 0, 0, 7, "^" }, - /* TokenAmpersand, */ { 14, 0, 8, "&" }, - /* TokenEqual, */ { 0, 0, 9, "==" }, - /* TokenNotEqual, */ { 0, 0, 9, "!=" }, - /* TokenLessThan, */ { 0, 0, 10, "<" }, - /* TokenGreaterThan, */ { 0, 0, 10, ">" }, - /* TokenLessEqual, */ { 0, 0, 10, "<=" }, - /* TokenGreaterEqual, */ { 0, 0, 10, ">=" }, - /* TokenShiftLeft, */ { 0, 0, 11, "<<" }, - /* TokenShiftRight, */ { 0, 0, 11, ">>" }, - /* TokenPlus, */ { 14, 0, 12, "+" }, - /* TokenMinus, */ { 14, 0, 12, "-" }, - /* TokenAsterisk, */ { 14, 0, 13, "*" }, - /* TokenSlash, */ { 0, 0, 13, "/" }, - /* TokenModulus, */ { 0, 0, 13, "%" }, - /* TokenIncrement, */ { 14, 15, 0, "++" }, - /* TokenDecrement, */ { 14, 15, 0, "--" }, - /* TokenUnaryNot, */ { 14, 0, 0, "!" }, - /* TokenUnaryExor, */ { 14, 0, 0, "~" }, - /* TokenSizeof, */ { 14, 0, 0, "sizeof" }, - /* TokenCast, */ { 14, 0, 0, "cast" }, - /* TokenLeftSquareBracket, */ { 0, 0, 15, "[" }, - /* TokenRightSquareBracket, */ { 0, 15, 0, "]" }, - /* TokenDot, */ { 0, 0, 15, "." }, - /* TokenArrow, */ { 0, 0, 15, "->" }, - /* TokenOpenBracket, */ { 15, 0, 0, "(" }, - /* TokenCloseBracket, */ { 0, 15, 0, ")" } -}; - -void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt); - -#ifdef DEBUG_EXPRESSIONS -/* show the contents of the expression stack */ -void ExpressionStackShow(struct ExpressionStack *StackTop) -{ - printf("Expression stack [0x%lx,0x%lx]: ", (long)HeapStackTop, (long)StackTop); - - while (StackTop != NULL) - { - if (StackTop->Order == OrderNone) - { - /* it's a value */ - if (StackTop->Val->IsLValue) - printf("lvalue="); - else - printf("value="); - - switch (StackTop->Val->Typ->Base) - { - case TypeVoid: printf("void"); break; - case TypeInt: printf("%d:int", StackTop->Val->Val->Integer); break; - case TypeShort: printf("%d:short", StackTop->Val->Val->ShortInteger); break; - case TypeChar: printf("%d:char", StackTop->Val->Val->Character); break; - case TypeLong: printf("%d:long", StackTop->Val->Val->LongInteger); break; - case TypeUnsignedShort: printf("%d:unsigned short", StackTop->Val->Val->UnsignedShortInteger); break; - case TypeUnsignedInt: printf("%d:unsigned int", StackTop->Val->Val->UnsignedInteger); break; - case TypeUnsignedLong: printf("%d:unsigned long", StackTop->Val->Val->UnsignedLongInteger); break; - case TypeFP: printf("%f:fp", StackTop->Val->Val->FP); break; - case TypeFunction: printf("%s:function", StackTop->Val->Val->Identifier); break; - case TypeMacro: printf("%s:macro", StackTop->Val->Val->Identifier); break; - case TypePointer: - if (StackTop->Val->Val->Pointer == NULL) - printf("ptr(NULL)"); - else if (StackTop->Val->Typ->FromType->Base == TypeChar) - printf("\"%s\":string", (char *)StackTop->Val->Val->Pointer); - else - printf("ptr(0x%lx)", (long)StackTop->Val->Val->Pointer); - break; - case TypeArray: printf("array"); break; - case TypeStruct: printf("%s:struct", StackTop->Val->Val->Identifier); break; - case TypeUnion: printf("%s:union", StackTop->Val->Val->Identifier); break; - case TypeEnum: printf("%s:enum", StackTop->Val->Val->Identifier); break; - case Type_Type: PrintType(StackTop->Val->Val->Typ, CStdOut); printf(":type"); break; - default: printf("unknown"); break; - } - printf("[0x%lx,0x%lx]", (long)StackTop, (long)StackTop->Val); - } - else - { - /* it's an operator */ - printf("op='%s' %s %d", OperatorPrecedence[(int)StackTop->Op].Name, - (StackTop->Order == OrderPrefix) ? "prefix" : ((StackTop->Order == OrderPostfix) ? "postfix" : "infix"), - StackTop->Precedence); - printf("[0x%lx]", (long)StackTop); - } - - StackTop = StackTop->Next; - if (StackTop != NULL) - printf(", "); - } - - printf("\n"); -} -#endif - -long ExpressionCoerceInteger(struct Value *Val) -{ - switch (Val->Typ->Base) - { - case TypeInt: return (long)Val->Val->Integer; - case TypeChar: return (long)Val->Val->Character; - case TypeShort: return (long)Val->Val->ShortInteger; - case TypeLong: return (long)Val->Val->LongInteger; - case TypeUnsignedInt: return (long)Val->Val->UnsignedInteger; - case TypeUnsignedShort: return (long)Val->Val->UnsignedShortInteger; - case TypeUnsignedLong: return (long)Val->Val->UnsignedLongInteger; - case TypePointer: return (long)Val->Val->Pointer; -#ifndef NO_FP - case TypeFP: return (long)Val->Val->FP; -#endif - default: return 0; - } -} - -unsigned long ExpressionCoerceUnsignedInteger(struct Value *Val) -{ - switch (Val->Typ->Base) - { - case TypeInt: return (unsigned long)Val->Val->Integer; - case TypeChar: return (unsigned long)Val->Val->Character; - case TypeShort: return (unsigned long)Val->Val->ShortInteger; - case TypeLong: return (unsigned long)Val->Val->LongInteger; - case TypeUnsignedInt: return (unsigned long)Val->Val->UnsignedInteger; - case TypeUnsignedShort: return (unsigned long)Val->Val->UnsignedShortInteger; - case TypeUnsignedLong: return (unsigned long)Val->Val->UnsignedLongInteger; - case TypePointer: return (unsigned long)Val->Val->Pointer; -#ifndef NO_FP - case TypeFP: return (unsigned long)Val->Val->FP; -#endif - default: return 0; - } -} - -#ifndef NO_FP -double ExpressionCoerceFP(struct Value *Val) -{ -#ifndef BROKEN_FLOAT_CASTS - int IntVal; - unsigned UnsignedVal; - - switch (Val->Typ->Base) - { - case TypeInt: IntVal = Val->Val->Integer; return (double)IntVal; - case TypeChar: IntVal = Val->Val->Character; return (double)IntVal; - case TypeShort: IntVal = Val->Val->ShortInteger; return (double)IntVal; - case TypeLong: IntVal = Val->Val->LongInteger; return (double)IntVal; - case TypeUnsignedInt: UnsignedVal = Val->Val->UnsignedInteger; return (double)UnsignedVal; - case TypeUnsignedShort: UnsignedVal = Val->Val->UnsignedShortInteger; return (double)UnsignedVal; - case TypeUnsignedLong: UnsignedVal = Val->Val->UnsignedLongInteger; return (double)UnsignedVal; - case TypeFP: return Val->Val->FP; - default: return 0.0; - } -#else - switch (Val->Typ->Base) - { - case TypeInt: return (double)Val->Val->Integer; - case TypeChar: return (double)Val->Val->Character; - case TypeShort: return (double)Val->Val->ShortInteger; - case TypeLong: return (double)Val->Val->LongInteger; - case TypeUnsignedInt: return (double)Val->Val->UnsignedInteger; - case TypeUnsignedShort: return (double)Val->Val->UnsignedShortInteger; - case TypeUnsignedLong: return (double)Val->Val->UnsignedLongInteger; - case TypeFP: return (double)Val->Val->FP; - default: return 0.0; - } -#endif -} -#endif - -/* assign an integer value */ -long ExpressionAssignInt(struct ParseState *Parser, struct Value *DestValue, long FromInt, int After) -{ - long Result; - - if (!DestValue->IsLValue) - ProgramFail(Parser, "can't assign to this"); - - if (After) - Result = ExpressionCoerceInteger(DestValue); - else - Result = FromInt; - - switch (DestValue->Typ->Base) - { - case TypeInt: DestValue->Val->Integer = FromInt; break; - case TypeShort: DestValue->Val->ShortInteger = (short)FromInt; break; - case TypeChar: DestValue->Val->Character = (unsigned char)FromInt; break; - case TypeLong: DestValue->Val->LongInteger = (long)FromInt; break; - case TypeUnsignedInt: DestValue->Val->UnsignedInteger = (unsigned int)FromInt; break; - case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)FromInt; break; - case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = (unsigned long)FromInt; break; - default: break; - } - return Result; -} - -#ifndef NO_FP -/* assign a floating point value */ -double ExpressionAssignFP(struct ParseState *Parser, struct Value *DestValue, double FromFP) -{ - if (!DestValue->IsLValue) - ProgramFail(Parser, "can't assign to this"); - - DestValue->Val->FP = FromFP; - return FromFP; -} -#endif - -/* push a node on to the expression stack */ -void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *ValueLoc) -{ - struct ExpressionStack *StackNode = VariableAlloc(Parser, sizeof(struct ExpressionStack), FALSE); - StackNode->Next = *StackTop; - StackNode->Val = ValueLoc; - *StackTop = StackNode; -#ifdef FANCY_ERROR_MESSAGES - StackNode->Line = Parser->Line; - StackNode->CharacterPos = Parser->CharacterPos; -#endif -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(*StackTop); -#endif -} - -/* push a blank value on to the expression stack by type */ -struct Value *ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType) -{ - struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL, FALSE); - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); - - return ValueLoc; -} - -/* push a value on to the expression stack */ -void ExpressionStackPushValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue) -{ - struct Value *ValueLoc = VariableAllocValueAndCopy(Parser, PushValue, FALSE); - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); -} - -void ExpressionStackPushLValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue, int Offset) -{ - struct Value *ValueLoc = VariableAllocValueShared(Parser, PushValue); - ValueLoc->Val = (void *)((char *)ValueLoc->Val + Offset); - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); -} - -void ExpressionStackPushDereference(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *DereferenceValue) -{ - struct Value *DerefVal; - struct Value *ValueLoc; - int Offset; - struct ValueType *DerefType; - int DerefIsLValue; - void *DerefDataLoc = VariableDereferencePointer(Parser, DereferenceValue, &DerefVal, &Offset, &DerefType, &DerefIsLValue); - if (DerefDataLoc == NULL) - ProgramFail(Parser, "NULL pointer dereference"); - - ValueLoc = VariableAllocValueFromExistingData(Parser, DerefType, (union AnyValue *)DerefDataLoc, DerefIsLValue, DerefVal); - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); -} - -void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **StackTop, long IntValue) -{ - struct Value *ValueLoc = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL, FALSE); - ValueLoc->Val->Integer = IntValue; - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); -} - -#ifndef NO_FP -void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackTop, double FPValue) -{ - struct Value *ValueLoc = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL, FALSE); - ValueLoc->Val->FP = FPValue; - ExpressionStackPushValueNode(Parser, StackTop, ValueLoc); -} -#endif - -/* assign to a pointer */ -void ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue, struct Value *FromValue, const char *FuncName, int ParamNo, int AllowPointerCoercion) -{ - struct ValueType *PointedToType = ToValue->Typ->FromType; - - if (FromValue->Typ == ToValue->Typ || FromValue->Typ == VoidPtrType || (ToValue->Typ == VoidPtrType && FromValue->Typ->Base == TypePointer)) - ToValue->Val->Pointer = FromValue->Val->Pointer; /* plain old pointer assignment */ - - else if (FromValue->Typ->Base == TypeArray && (PointedToType == FromValue->Typ->FromType || ToValue->Typ == VoidPtrType)) - { - /* the form is: blah *x = array of blah */ - ToValue->Val->Pointer = (void *)&FromValue->Val->ArrayMem[0]; - } - else if (FromValue->Typ->Base == TypePointer && FromValue->Typ->FromType->Base == TypeArray && - (PointedToType == FromValue->Typ->FromType->FromType || ToValue->Typ == VoidPtrType) ) - { - /* the form is: blah *x = pointer to array of blah */ - ToValue->Val->Pointer = VariableDereferencePointer(Parser, FromValue, NULL, NULL, NULL, NULL); - } - else if (IS_NUMERIC_COERCIBLE(FromValue) && ExpressionCoerceInteger(FromValue) == 0) - { - /* null pointer assignment */ - ToValue->Val->Pointer = NULL; - } - else if (AllowPointerCoercion && IS_NUMERIC_COERCIBLE(FromValue)) - { - /* assign integer to native pointer */ - ToValue->Val->Pointer = (void *)(unsigned long)ExpressionCoerceUnsignedInteger(FromValue); - } - else if (AllowPointerCoercion && FromValue->Typ->Base == TypePointer) - { - /* assign a pointer to a pointer to a different type */ - ToValue->Val->Pointer = FromValue->Val->Pointer; - } - else - AssignFail(Parser, "%t from %t", ToValue->Typ, FromValue->Typ, 0, 0, FuncName, ParamNo); -} - -/* assign any kind of value */ -void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct Value *SourceValue, int Force, const char *FuncName, int ParamNo, int AllowPointerCoercion) -{ - if (!DestValue->IsLValue && !Force) - AssignFail(Parser, "not an lvalue", NULL, NULL, 0, 0, FuncName, ParamNo); - - if (IS_NUMERIC_COERCIBLE(DestValue) && !IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion)) - AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); - - switch (DestValue->Typ->Base) - { - case TypeInt: DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); break; - case TypeShort: DestValue->Val->ShortInteger = ExpressionCoerceInteger(SourceValue); break; - case TypeChar: DestValue->Val->Character = ExpressionCoerceUnsignedInteger(SourceValue); break; - case TypeLong: DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); break; - case TypeUnsignedInt: DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); break; - case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = ExpressionCoerceUnsignedInteger(SourceValue); break; - case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); break; - -#ifndef NO_FP - case TypeFP: - if (!IS_NUMERIC_COERCIBLE_PLUS_POINTERS(SourceValue, AllowPointerCoercion)) - AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); - - DestValue->Val->FP = ExpressionCoerceFP(SourceValue); - break; -#endif - case TypePointer: - ExpressionAssignToPointer(Parser, DestValue, SourceValue, FuncName, ParamNo, AllowPointerCoercion); - break; - - case TypeArray: - if (DestValue->Typ != SourceValue->Typ) - AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); - - if (DestValue->Typ->ArraySize != SourceValue->Typ->ArraySize) - AssignFail(Parser, "from an array of size %d to one of size %d", NULL, NULL, DestValue->Typ->ArraySize, SourceValue->Typ->ArraySize, FuncName, ParamNo); - - memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(DestValue, FALSE)); - break; - - case TypeStruct: - case TypeUnion: - if (DestValue->Typ != SourceValue->Typ) - AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); - - memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(SourceValue, FALSE)); - break; - - default: - AssignFail(Parser, "%t", DestValue->Typ, NULL, 0, 0, FuncName, ParamNo); - break; - } -} - -/* evaluate the first half of a ternary operator x ? y : z */ -void ExpressionQuestionMarkOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue) -{ - if (!IS_NUMERIC_COERCIBLE(TopValue)) - ProgramFail(Parser, "first argument to '?' should be a number"); - - if (ExpressionCoerceInteger(TopValue)) - { - /* the condition's true, return the BottomValue */ - ExpressionStackPushValue(Parser, StackTop, BottomValue); - } - else - { - /* the condition's false, return void */ - ExpressionStackPushValueByType(Parser, StackTop, &VoidType); - } -} - -/* evaluate the second half of a ternary operator x ? y : z */ -void ExpressionColonOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue) -{ - if (TopValue->Typ->Base == TypeVoid) - { - /* invoke the "else" part - return the BottomValue */ - ExpressionStackPushValue(Parser, StackTop, BottomValue); - } - else - { - /* it was a "then" - return the TopValue */ - ExpressionStackPushValue(Parser, StackTop, TopValue); - } -} - -/* evaluate a prefix operator */ -void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue) -{ - struct Value *Result; - union AnyValue *ValPtr; - - debugf("ExpressionPrefixOperator()\n"); - switch (Op) - { - case TokenAmpersand: - if (!TopValue->IsLValue) - ProgramFail(Parser, "can't get the address of this"); - - ValPtr = TopValue->Val; - Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, TopValue->Typ, TypePointer, 0, StrEmpty, TRUE), FALSE, NULL, FALSE); - Result->Val->Pointer = (void *)ValPtr; - ExpressionStackPushValueNode(Parser, StackTop, Result); - break; - - case TokenAsterisk: - ExpressionStackPushDereference(Parser, StackTop, TopValue); - break; - - case TokenSizeof: - /* return the size of the argument */ - if (TopValue->Typ == &TypeType) - ExpressionPushInt(Parser, StackTop, TypeSize(TopValue->Val->Typ, TopValue->Val->Typ->ArraySize, TRUE)); - else - ExpressionPushInt(Parser, StackTop, TypeSize(TopValue->Typ, TopValue->Typ->ArraySize, TRUE)); - break; - - default: - /* an arithmetic operator */ -#ifndef NO_FP - if (TopValue->Typ == &FPType) - { - /* floating point prefix arithmetic */ - double ResultFP = 0.0; - - switch (Op) - { - case TokenPlus: ResultFP = TopValue->Val->FP; break; - case TokenMinus: ResultFP = -TopValue->Val->FP; break; - default: ProgramFail(Parser, "invalid operation"); break; - } - - ExpressionPushFP(Parser, StackTop, ResultFP); - } - else -#endif - if (IS_NUMERIC_COERCIBLE(TopValue)) - { - /* integer prefix arithmetic */ - long ResultInt = 0; - long TopInt = ExpressionCoerceInteger(TopValue); - switch (Op) - { - case TokenPlus: ResultInt = TopInt; break; - case TokenMinus: ResultInt = -TopInt; break; - case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, FALSE); break; - case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, FALSE); break; - case TokenUnaryNot: ResultInt = !TopInt; break; - case TokenUnaryExor: ResultInt = ~TopInt; break; - default: ProgramFail(Parser, "invalid operation"); break; - } - - ExpressionPushInt(Parser, StackTop, ResultInt); - } - else if (TopValue->Typ->Base == TypePointer) - { - /* pointer prefix arithmetic */ - int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); - struct Value *StackValue; - void *ResultPtr; - - if (TopValue->Val->Pointer == NULL) - ProgramFail(Parser, "invalid use of a NULL pointer"); - - if (!TopValue->IsLValue) - ProgramFail(Parser, "can't assign to this"); - - switch (Op) - { - case TokenIncrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); break; - case TokenDecrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); break; - default: ProgramFail(Parser, "invalid operation"); break; - } - - ResultPtr = TopValue->Val->Pointer; - StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ); - StackValue->Val->Pointer = ResultPtr; - } - else - ProgramFail(Parser, "invalid operation"); - break; - } -} - -/* evaluate a postfix operator */ -void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue) -{ - debugf("ExpressionPostfixOperator()\n"); - if (IS_NUMERIC_COERCIBLE(TopValue)) - { - long ResultInt = 0; - long TopInt = ExpressionCoerceInteger(TopValue); - switch (Op) - { - case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, TRUE); break; - case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, TRUE); break; - case TokenRightSquareBracket: ProgramFail(Parser, "not supported"); break; /* XXX */ - case TokenCloseBracket: ProgramFail(Parser, "not supported"); break; /* XXX */ - default: ProgramFail(Parser, "invalid operation"); break; - } - - ExpressionPushInt(Parser, StackTop, ResultInt); - } - else if (TopValue->Typ->Base == TypePointer) - { - /* pointer postfix arithmetic */ - int Size = TypeSize(TopValue->Typ->FromType, 0, TRUE); - struct Value *StackValue; - void *OrigPointer = TopValue->Val->Pointer; - - if (TopValue->Val->Pointer == NULL) - ProgramFail(Parser, "invalid use of a NULL pointer"); - - if (!TopValue->IsLValue) - ProgramFail(Parser, "can't assign to this"); - - switch (Op) - { - case TokenIncrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer + Size); break; - case TokenDecrement: TopValue->Val->Pointer = (void *)((char *)TopValue->Val->Pointer - Size); break; - default: ProgramFail(Parser, "invalid operation"); break; - } - - StackValue = ExpressionStackPushValueByType(Parser, StackTop, TopValue->Typ); - StackValue->Val->Pointer = OrigPointer; - } - else - ProgramFail(Parser, "invalid operation"); -} - -/* evaluate an infix operator */ -void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *BottomValue, struct Value *TopValue) -{ - long ResultInt = 0; - struct Value *StackValue; - void *Pointer; - - debugf("ExpressionInfixOperator()\n"); - if (BottomValue == NULL || TopValue == NULL) - ProgramFail(Parser, "invalid expression"); - - if (Op == TokenLeftSquareBracket) - { - /* array index */ - int ArrayIndex; - struct Value *Result = NULL; - - if (!IS_NUMERIC_COERCIBLE(TopValue)) - ProgramFail(Parser, "array index must be an integer"); - - ArrayIndex = ExpressionCoerceInteger(TopValue); - - /* make the array element result */ - switch (BottomValue->Typ->Base) - { - case TypeArray: Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)(&BottomValue->Val->ArrayMem[0] + TypeSize(BottomValue->Typ, ArrayIndex, TRUE)), BottomValue->IsLValue, BottomValue->LValueFrom); break; - case TypePointer: Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)((char *)BottomValue->Val->Pointer + TypeSize(BottomValue->Typ->FromType, 0, TRUE) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom); break; - default: ProgramFail(Parser, "this %t is not an array", BottomValue->Typ); - } - - ExpressionStackPushValueNode(Parser, StackTop, Result); - } - else if (Op == TokenQuestionMark) - ExpressionQuestionMarkOperator(Parser, StackTop, TopValue, BottomValue); - - else if (Op == TokenColon) - ExpressionColonOperator(Parser, StackTop, TopValue, BottomValue); - -#ifndef NO_FP - else if ( (TopValue->Typ == &FPType && BottomValue->Typ == &FPType) || - (TopValue->Typ == &FPType && IS_NUMERIC_COERCIBLE(BottomValue)) || - (IS_NUMERIC_COERCIBLE(TopValue) && BottomValue->Typ == &FPType) ) - { - /* floating point infix arithmetic */ - int ResultIsInt = FALSE; - double ResultFP = 0.0; - double TopFP = (TopValue->Typ == &FPType) ? TopValue->Val->FP : (double)ExpressionCoerceInteger(TopValue); - double BottomFP = (BottomValue->Typ == &FPType) ? BottomValue->Val->FP : (double)ExpressionCoerceInteger(BottomValue); - - switch (Op) - { - case TokenAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, TopFP); break; - case TokenAddAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP + TopFP); break; - case TokenSubtractAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP - TopFP); break; - case TokenMultiplyAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP * TopFP); break; - case TokenDivideAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP / TopFP); break; - case TokenEqual: ResultInt = BottomFP == TopFP; ResultIsInt = TRUE; break; - case TokenNotEqual: ResultInt = BottomFP != TopFP; ResultIsInt = TRUE; break; - case TokenLessThan: ResultInt = BottomFP < TopFP; ResultIsInt = TRUE; break; - case TokenGreaterThan: ResultInt = BottomFP > TopFP; ResultIsInt = TRUE; break; - case TokenLessEqual: ResultInt = BottomFP <= TopFP; ResultIsInt = TRUE; break; - case TokenGreaterEqual: ResultInt = BottomFP >= TopFP; ResultIsInt = TRUE; break; - case TokenPlus: ResultFP = BottomFP + TopFP; break; - case TokenMinus: ResultFP = BottomFP - TopFP; break; - case TokenAsterisk: ResultFP = BottomFP * TopFP; break; - case TokenSlash: ResultFP = BottomFP / TopFP; break; - default: ProgramFail(Parser, "invalid operation"); break; - } - - if (ResultIsInt) - ExpressionPushInt(Parser, StackTop, ResultInt); - else - ExpressionPushFP(Parser, StackTop, ResultFP); - } -#endif - else if (IS_NUMERIC_COERCIBLE(TopValue) && IS_NUMERIC_COERCIBLE(BottomValue)) - { - /* integer operation */ - long TopInt = ExpressionCoerceInteger(TopValue); - long BottomInt = ExpressionCoerceInteger(BottomValue); - switch (Op) - { - case TokenAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, TopInt, FALSE); break; - case TokenAddAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt + TopInt, FALSE); break; - case TokenSubtractAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt - TopInt, FALSE); break; - case TokenMultiplyAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt * TopInt, FALSE); break; - case TokenDivideAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt / TopInt, FALSE); break; -#ifndef NO_MODULUS - case TokenModulusAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt % TopInt, FALSE); break; -#endif - case TokenShiftLeftAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt << TopInt, FALSE); break; - case TokenShiftRightAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt >> TopInt, FALSE); break; - case TokenArithmeticAndAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt & TopInt, FALSE); break; - case TokenArithmeticOrAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt | TopInt, FALSE); break; - case TokenArithmeticExorAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt ^ TopInt, FALSE); break; - case TokenLogicalOr: ResultInt = BottomInt || TopInt; break; - case TokenLogicalAnd: ResultInt = BottomInt && TopInt; break; - case TokenArithmeticOr: ResultInt = BottomInt | TopInt; break; - case TokenArithmeticExor: ResultInt = BottomInt ^ TopInt; break; - case TokenAmpersand: ResultInt = BottomInt & TopInt; break; - case TokenEqual: ResultInt = BottomInt == TopInt; break; - case TokenNotEqual: ResultInt = BottomInt != TopInt; break; - case TokenLessThan: ResultInt = BottomInt < TopInt; break; - case TokenGreaterThan: ResultInt = BottomInt > TopInt; break; - case TokenLessEqual: ResultInt = BottomInt <= TopInt; break; - case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; break; - case TokenShiftLeft: ResultInt = BottomInt << TopInt; break; - case TokenShiftRight: ResultInt = BottomInt >> TopInt; break; - case TokenPlus: ResultInt = BottomInt + TopInt; break; - case TokenMinus: ResultInt = BottomInt - TopInt; break; - case TokenAsterisk: ResultInt = BottomInt * TopInt; break; - case TokenSlash: ResultInt = BottomInt / TopInt; break; -#ifndef NO_MODULUS - case TokenModulus: ResultInt = BottomInt % TopInt; break; -#endif - default: ProgramFail(Parser, "invalid operation"); break; - } - - ExpressionPushInt(Parser, StackTop, ResultInt); - } - else if (BottomValue->Typ->Base == TypePointer && IS_NUMERIC_COERCIBLE(TopValue)) - { - /* pointer/integer infix arithmetic */ - long TopInt = ExpressionCoerceInteger(TopValue); - - if (Op == TokenEqual || Op == TokenNotEqual) - { - /* comparison to a NULL pointer */ - if (TopInt != 0) - ProgramFail(Parser, "invalid operation"); - - if (Op == TokenEqual) - ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer == NULL); - else - ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer != NULL); - } - else if (Op == TokenPlus || Op == TokenMinus) - { - /* pointer arithmetic */ - int Size = TypeSize(BottomValue->Typ->FromType, 0, TRUE); - - Pointer = BottomValue->Val->Pointer; - if (Pointer == NULL) - ProgramFail(Parser, "invalid use of a NULL pointer"); - - if (Op == TokenPlus) - Pointer = (void *)((char *)Pointer + TopInt * Size); - else - Pointer = (void *)((char *)Pointer - TopInt * Size); - - StackValue = ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ); - StackValue->Val->Pointer = Pointer; - } - else if (Op == TokenAssign && TopInt == 0) - { - /* assign a NULL pointer */ - HeapUnpopStack(sizeof(struct Value)); - ExpressionAssign(Parser, BottomValue, TopValue, FALSE, NULL, 0, FALSE); - ExpressionStackPushValueNode(Parser, StackTop, BottomValue); - } - else if (Op == TokenAddAssign || Op == TokenSubtractAssign) - { - /* pointer arithmetic */ - int Size = TypeSize(BottomValue->Typ->FromType, 0, TRUE); - - Pointer = BottomValue->Val->Pointer; - if (Pointer == NULL) - ProgramFail(Parser, "invalid use of a NULL pointer"); - - if (Op == TokenAddAssign) - Pointer = (void *)((char *)Pointer + TopInt * Size); - else - Pointer = (void *)((char *)Pointer - TopInt * Size); - - HeapUnpopStack(sizeof(struct Value)); - BottomValue->Val->Pointer = Pointer; - ExpressionStackPushValueNode(Parser, StackTop, BottomValue); - } - else - ProgramFail(Parser, "invalid operation"); - } - else if (BottomValue->Typ->Base == TypePointer && TopValue->Typ->Base == TypePointer && Op != TokenAssign) - { - /* pointer/pointer operations */ - char *TopLoc = (char *)TopValue->Val->Pointer; - char *BottomLoc = (char *)BottomValue->Val->Pointer; - - switch (Op) - { - case TokenEqual: ExpressionPushInt(Parser, StackTop, BottomLoc == TopLoc); break; - case TokenNotEqual: ExpressionPushInt(Parser, StackTop, BottomLoc != TopLoc); break; - case TokenMinus: ExpressionPushInt(Parser, StackTop, BottomLoc - TopLoc); break; - default: ProgramFail(Parser, "invalid operation"); break; - } - } - else if (Op == TokenAssign) - { - /* assign a non-numeric type */ - HeapUnpopStack(sizeof(struct Value)); /* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */ - ExpressionAssign(Parser, BottomValue, TopValue, FALSE, NULL, 0, FALSE); - ExpressionStackPushValueNode(Parser, StackTop, BottomValue); - } - else if (Op == TokenCast) - { - /* cast a value to a different type */ /* XXX - possible bug if the destination type takes more than sizeof(struct Value) + sizeof(struct ValueType *) */ - struct Value *ValueLoc = ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Val->Typ); - ExpressionAssign(Parser, ValueLoc, TopValue, TRUE, NULL, 0, TRUE); - } - else - ProgramFail(Parser, "invalid operation"); -} - -/* take the contents of the expression stack and compute the top until there's nothing greater than the given precedence */ -void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack **StackTop, int Precedence, int *IgnorePrecedence) -{ - int FoundPrecedence = Precedence; - struct Value *TopValue; - struct Value *BottomValue; - struct ExpressionStack *TopStackNode = *StackTop; - struct ExpressionStack *TopOperatorNode; - - debugf("ExpressionStackCollapse(%d):\n", Precedence); -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(*StackTop); -#endif - while (TopStackNode != NULL && TopStackNode->Next != NULL && FoundPrecedence >= Precedence) - { - /* find the top operator on the stack */ - if (TopStackNode->Order == OrderNone) - TopOperatorNode = TopStackNode->Next; - else - TopOperatorNode = TopStackNode; - - FoundPrecedence = TopOperatorNode->Precedence; - - /* does it have a high enough precedence? */ - if (FoundPrecedence >= Precedence && TopOperatorNode != NULL) - { - /* execute this operator */ - switch (TopOperatorNode->Order) - { - case OrderPrefix: - /* prefix evaluation */ - debugf("prefix evaluation\n"); - TopValue = TopStackNode->Val; - - /* pop the value and then the prefix operator - assume they'll still be there until we're done */ - HeapPopStack(NULL, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); - HeapPopStack(TopOperatorNode, sizeof(struct ExpressionStack)); - *StackTop = TopOperatorNode->Next; - - /* do the prefix operation */ - if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence) - { - /* run the operator */ - ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue); - } - else - { - /* we're not running it so just return 0 */ - ExpressionPushInt(Parser, StackTop, 0); - } - break; - - case OrderPostfix: - /* postfix evaluation */ - debugf("postfix evaluation\n"); - TopValue = TopStackNode->Next->Val; - - /* pop the postfix operator and then the value - assume they'll still be there until we're done */ - HeapPopStack(NULL, sizeof(struct ExpressionStack)); - HeapPopStack(TopValue, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); - *StackTop = TopStackNode->Next->Next; - - /* do the postfix operation */ - if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence) - { - /* run the operator */ - ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue); - } - else - { - /* we're not running it so just return 0 */ - ExpressionPushInt(Parser, StackTop, 0); - } - break; - - case OrderInfix: - /* infix evaluation */ - debugf("infix evaluation\n"); - TopValue = TopStackNode->Val; - if (TopValue != NULL) - { - BottomValue = TopOperatorNode->Next->Val; - - /* pop a value, the operator and another value - assume they'll still be there until we're done */ - HeapPopStack(NULL, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(TopValue)); - HeapPopStack(NULL, sizeof(struct ExpressionStack)); - HeapPopStack(BottomValue, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(BottomValue)); - *StackTop = TopOperatorNode->Next->Next; - - /* do the infix operation */ - if (Parser->Mode == RunModeRun && FoundPrecedence <= *IgnorePrecedence) - { - /* run the operator */ - ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue); - } - else - { - /* we're not running it so just return 0 */ - ExpressionPushInt(Parser, StackTop, 0); - } - } - else - FoundPrecedence = -1; - break; - - case OrderNone: - /* this should never happen */ - assert(TopOperatorNode->Order != OrderNone); - break; - } - - /* if we've returned above the ignored precedence level turn ignoring off */ - if (FoundPrecedence <= *IgnorePrecedence) - *IgnorePrecedence = DEEP_PRECEDENCE; - } -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(*StackTop); -#endif - TopStackNode = *StackTop; - } - debugf("ExpressionStackCollapse() finished\n"); -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(*StackTop); -#endif -} - -/* push an operator on to the expression stack */ -void ExpressionStackPushOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum OperatorOrder Order, enum LexToken Token, int Precedence) -{ - struct ExpressionStack *StackNode = VariableAlloc(Parser, sizeof(struct ExpressionStack), FALSE); - StackNode->Next = *StackTop; - StackNode->Order = Order; - StackNode->Op = Token; - StackNode->Precedence = Precedence; - *StackTop = StackNode; - debugf("ExpressionStackPushOperator()\n"); -#ifdef FANCY_ERROR_MESSAGES - StackNode->Line = Parser->Line; - StackNode->CharacterPos = Parser->CharacterPos; -#endif -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(*StackTop); -#endif -} - -/* do the '.' and '->' operators */ -void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Token) -{ - struct Value *Ident; - - /* get the identifier following the '.' or '->' */ - if (LexGetToken(Parser, &Ident, TRUE) != TokenIdentifier) - ProgramFail(Parser, "need an structure or union member after '%s'", (Token == TokenDot) ? "." : "->"); - - if (Parser->Mode == RunModeRun) - { - /* look up the struct element */ - struct Value *ParamVal = (*StackTop)->Val; - struct Value *StructVal = ParamVal; - struct ValueType *StructType = ParamVal->Typ; - char *DerefDataLoc = (char *)ParamVal->Val; - struct Value *MemberValue; - struct Value *Result; - - /* if we're doing '->' dereference the struct pointer first */ - if (Token == TokenArrow) - DerefDataLoc = VariableDereferencePointer(Parser, ParamVal, &StructVal, NULL, &StructType, NULL); - - if (StructType->Base != TypeStruct && StructType->Base != TypeUnion) - ProgramFail(Parser, "can't use '%s' on something that's not a struct or union %s : it's a %t", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "", ParamVal->Typ); - - if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL, NULL)) - ProgramFail(Parser, "doesn't have a member called '%s'", Ident->Val->Identifier); - - /* pop the value - assume it'll still be there until we're done */ - HeapPopStack(ParamVal, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StructVal)); - *StackTop = (*StackTop)->Next; - - /* make the result value for this member only */ - Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)(DerefDataLoc + MemberValue->Val->Integer), TRUE, (StructVal != NULL) ? StructVal->LValueFrom : NULL); - ExpressionStackPushValueNode(Parser, StackTop, Result); - } -} - -/* parse an expression with operator precedence */ -int ExpressionParse(struct ParseState *Parser, struct Value **Result) -{ - struct Value *LexValue; - int PrefixState = TRUE; - int Done = FALSE; - int BracketPrecedence = 0; - int LocalPrecedence; - int Precedence = 0; - int IgnorePrecedence = DEEP_PRECEDENCE; - struct ExpressionStack *StackTop = NULL; - int TernaryDepth = 0; - - debugf("ExpressionParse():\n"); - do - { - struct ParseState PreState; - enum LexToken Token; - - ParserCopy(&PreState, Parser); - Token = LexGetToken(Parser, &LexValue, TRUE); - if ( ( ( (int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) || - (Token == TokenCloseBracket && BracketPrecedence != 0)) && - (Token != TokenColon || TernaryDepth > 0) ) - { - /* it's an operator with precedence */ - if (PrefixState) - { - /* expect a prefix operator */ - if (OperatorPrecedence[(int)Token].PrefixPrecedence == 0) - ProgramFail(Parser, "operator not expected here"); - - LocalPrecedence = OperatorPrecedence[(int)Token].PrefixPrecedence; - Precedence = BracketPrecedence + LocalPrecedence; - - if (Token == TokenOpenBracket) - { - /* it's either a new bracket level or a cast */ - enum LexToken BracketToken = LexGetToken(Parser, &LexValue, FALSE); - if (IS_TYPE_TOKEN(BracketToken) && (StackTop == NULL || StackTop->Op != TokenSizeof) ) - { - /* it's a cast - get the new type */ - struct ValueType *CastType; - char *CastIdentifier; - struct Value *CastTypeValue; - - TypeParse(Parser, &CastType, &CastIdentifier, NULL); - if (LexGetToken(Parser, &LexValue, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "brackets not closed"); - - /* scan and collapse the stack to the precedence of this infix cast operator, then push */ - Precedence = BracketPrecedence + OperatorPrecedence[(int)TokenCast].PrefixPrecedence; - - ExpressionStackCollapse(Parser, &StackTop, Precedence+1, &IgnorePrecedence); - CastTypeValue = VariableAllocValueFromType(Parser, &TypeType, FALSE, NULL, FALSE); - CastTypeValue->Val->Typ = CastType; - ExpressionStackPushValueNode(Parser, &StackTop, CastTypeValue); - ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, TokenCast, Precedence); - } - else - { - /* boost the bracket operator precedence */ - BracketPrecedence += BRACKET_PRECEDENCE; - } - } - else - { - /* scan and collapse the stack to the precedence of this operator, then push */ - ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence); - ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence); - } - } - else - { - /* expect an infix or postfix operator */ - if (OperatorPrecedence[(int)Token].PostfixPrecedence != 0) - { - switch (Token) - { - case TokenCloseBracket: - case TokenRightSquareBracket: - if (BracketPrecedence == 0) - { - /* assume this bracket is after the end of the expression */ - ParserCopy(Parser, &PreState); - Done = TRUE; - } - else - { - /* collapse to the bracket precedence */ - ExpressionStackCollapse(Parser, &StackTop, BracketPrecedence, &IgnorePrecedence); - BracketPrecedence -= BRACKET_PRECEDENCE; - } - break; - - default: - /* scan and collapse the stack to the precedence of this operator, then push */ - Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].PostfixPrecedence; - ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence); - ExpressionStackPushOperator(Parser, &StackTop, OrderPostfix, Token, Precedence); - break; - } - } - else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0) - { - /* scan and collapse the stack, then push */ - Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].InfixPrecedence; - - /* for right to left order, only go down to the next higher precedence so we evaluate it in reverse order */ - /* for left to right order, collapse down to this precedence so we evaluate it in forward order */ - if (IS_LEFT_TO_RIGHT(OperatorPrecedence[(int)Token].InfixPrecedence)) - ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence); - else - ExpressionStackCollapse(Parser, &StackTop, Precedence+1, &IgnorePrecedence); - - if (Token == TokenDot || Token == TokenArrow) - { - ExpressionGetStructElement(Parser, &StackTop, Token); /* this operator is followed by a struct element so handle it as a special case */ - } - else - { - /* if it's a && or || operator we may not need to evaluate the right hand side of the expression */ - if ( (Token == TokenLogicalOr || Token == TokenLogicalAnd) && IS_NUMERIC_COERCIBLE(StackTop->Val)) - { - long LHSInt = ExpressionCoerceInteger(StackTop->Val); - if ( ( (Token == TokenLogicalOr && LHSInt) || (Token == TokenLogicalAnd && !LHSInt) ) && - (IgnorePrecedence > Precedence) ) - IgnorePrecedence = Precedence; - } - - /* push the operator on the stack */ - ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, Token, Precedence); - PrefixState = TRUE; - - switch (Token) - { - case TokenQuestionMark: TernaryDepth++; break; - case TokenColon: TernaryDepth--; break; - default: break; - } - } - - /* treat an open square bracket as an infix array index operator followed by an open bracket */ - if (Token == TokenLeftSquareBracket) - { - /* boost the bracket operator precedence, then push */ - BracketPrecedence += BRACKET_PRECEDENCE; - } - } - else - ProgramFail(Parser, "operator not expected here"); - } - } - else if (Token == TokenIdentifier) - { - /* it's a variable, function or a macro */ - if (!PrefixState) - ProgramFail(Parser, "identifier not expected here"); - - if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) - { - ExpressionParseFunctionCall(Parser, &StackTop, LexValue->Val->Identifier, Parser->Mode == RunModeRun && Precedence < IgnorePrecedence); - } - else - { - if (Parser->Mode == RunModeRun && Precedence < IgnorePrecedence) - { - struct Value *VariableValue = NULL; - - VariableGet(Parser, LexValue->Val->Identifier, &VariableValue); - if (VariableValue->Typ->Base == TypeMacro) - { - /* evaluate a macro as a kind of simple subroutine */ - struct ParseState MacroParser; - struct Value *MacroResult; - - ParserCopy(&MacroParser, &VariableValue->Val->MacroDef.Body); - if (VariableValue->Val->MacroDef.NumParams != 0) - ProgramFail(&MacroParser, "macro arguments missing"); - - if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction) - ProgramFail(&MacroParser, "expression expected"); - - ExpressionStackPushValueNode(Parser, &StackTop, MacroResult); - } - else if (VariableValue->Typ == TypeVoid) - ProgramFail(Parser, "a void value isn't much use here"); - else - ExpressionStackPushLValue(Parser, &StackTop, VariableValue, 0); /* it's a value variable */ - } - else /* push a dummy value */ - ExpressionPushInt(Parser, &StackTop, 0); - - } - - /* if we've successfully ignored the RHS turn ignoring off */ - if (Precedence <= IgnorePrecedence) - IgnorePrecedence = DEEP_PRECEDENCE; - - PrefixState = FALSE; - } - else if ((int)Token > TokenCloseBracket && (int)Token <= TokenCharacterConstant) - { - /* it's a value of some sort, push it */ - if (!PrefixState) - ProgramFail(Parser, "value not expected here"); - - PrefixState = FALSE; - ExpressionStackPushValue(Parser, &StackTop, LexValue); - } - else if (IS_TYPE_TOKEN(Token)) - { - /* it's a type. push it on the stack like a value. this is used in sizeof() */ - struct ValueType *Typ; - char *Identifier; - struct Value *TypeValue; - - if (!PrefixState) - ProgramFail(Parser, "type not expected here"); - - PrefixState = FALSE; - ParserCopy(Parser, &PreState); - TypeParse(Parser, &Typ, &Identifier, NULL); - TypeValue = VariableAllocValueFromType(Parser, &TypeType, FALSE, NULL, FALSE); - TypeValue->Val->Typ = Typ; - ExpressionStackPushValueNode(Parser, &StackTop, TypeValue); - } - else - { - /* it isn't a token from an expression */ - ParserCopy(Parser, &PreState); - Done = TRUE; - } - - } while (!Done); - - /* check that brackets have been closed */ - if (BracketPrecedence > 0) - ProgramFail(Parser, "brackets not closed"); - - /* scan and collapse the stack to precedence 0 */ - ExpressionStackCollapse(Parser, &StackTop, 0, &IgnorePrecedence); - - /* fix up the stack and return the result if we're in run mode */ - if (StackTop != NULL) - { - /* all that should be left is a single value on the stack */ - if (Parser->Mode == RunModeRun) - { - if (StackTop->Order != OrderNone || StackTop->Next != NULL) - ProgramFail(Parser, "invalid expression"); - - *Result = StackTop->Val; - HeapPopStack(StackTop, sizeof(struct ExpressionStack)); - } - else - HeapPopStack(StackTop->Val, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StackTop->Val)); - } - - debugf("ExpressionParse() done\n\n"); -#ifdef DEBUG_EXPRESSIONS - ExpressionStackShow(StackTop); -#endif - return StackTop != NULL; -} - - -/* do a parameterised macro call */ -void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *MacroName, struct MacroDef *MDef) -{ - struct Value *ReturnValue = NULL; - struct Value *Param; - struct Value **ParamArray = NULL; - int ArgCount; - enum LexToken Token; - - if (Parser->Mode == RunModeRun) - { - /* create a stack frame for this macro */ -#ifndef NO_FP - ExpressionStackPushValueByType(Parser, StackTop, &FPType); /* largest return type there is */ -#else - ExpressionStackPushValueByType(Parser, StackTop, &IntType); /* largest return type there is */ -#endif - ReturnValue = (*StackTop)->Val; - HeapPushStackFrame(); - ParamArray = HeapAllocStack(sizeof(struct Value *) * MDef->NumParams); - if (ParamArray == NULL) - ProgramFail(Parser, "out of memory"); - } - else - ExpressionPushInt(Parser, StackTop, 0); - - /* parse arguments */ - ArgCount = 0; - do { - if (ExpressionParse(Parser, &Param)) - { - if (Parser->Mode == RunModeRun) - { - if (ArgCount < MDef->NumParams) - ParamArray[ArgCount] = Param; - else - ProgramFail(Parser, "too many arguments to %s()", MacroName); - } - - ArgCount++; - Token = LexGetToken(Parser, NULL, TRUE); - if (Token != TokenComma && Token != TokenCloseBracket) - ProgramFail(Parser, "comma expected"); - } - else - { - /* end of argument list? */ - Token = LexGetToken(Parser, NULL, TRUE); - if (!TokenCloseBracket) - ProgramFail(Parser, "bad argument"); - } - - } while (Token != TokenCloseBracket); - - if (Parser->Mode == RunModeRun) - { - /* evaluate the macro */ - struct ParseState MacroParser; - int Count; - struct Value *EvalValue; - - if (ArgCount < MDef->NumParams) - ProgramFail(Parser, "not enough arguments to '%s'", MacroName); - - if (MDef->Body.Pos == NULL) - ProgramFail(Parser, "'%s' is undefined", MacroName); - - ParserCopy(&MacroParser, &MDef->Body); - VariableStackFrameAdd(Parser, MacroName, 0); - TopStackFrame->NumParams = ArgCount; - TopStackFrame->ReturnValue = ReturnValue; - for (Count = 0; Count < MDef->NumParams; Count++) - VariableDefine(Parser, MDef->ParamName[Count], ParamArray[Count], NULL, TRUE); - - ExpressionParse(&MacroParser, &EvalValue); - ExpressionAssign(Parser, ReturnValue, EvalValue, TRUE, MacroName, 0, FALSE); - VariableStackFramePop(Parser); - HeapPopStackFrame(); - } -} - -/* do a function call */ -void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt) -{ - struct Value *ReturnValue = NULL; - struct Value *FuncValue; - struct Value *Param; - struct Value **ParamArray = NULL; - int ArgCount; - enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */ - enum RunMode OldMode = Parser->Mode; - - if (RunIt) - { - /* get the function definition */ - VariableGet(Parser, FuncName, &FuncValue); - - if (FuncValue->Typ->Base == TypeMacro) - { - /* this is actually a macro, not a function */ - ExpressionParseMacroCall(Parser, StackTop, FuncName, &FuncValue->Val->MacroDef); - return; - } - - if (FuncValue->Typ->Base != TypeFunction) - ProgramFail(Parser, "%t is not a function - can't call", FuncValue->Typ); - - ExpressionStackPushValueByType(Parser, StackTop, FuncValue->Val->FuncDef.ReturnType); - ReturnValue = (*StackTop)->Val; - HeapPushStackFrame(); - ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams); - if (ParamArray == NULL) - ProgramFail(Parser, "out of memory"); - } - else - { - ExpressionPushInt(Parser, StackTop, 0); - Parser->Mode = RunModeSkip; - } - - /* parse arguments */ - ArgCount = 0; - do { - if (RunIt && ArgCount < FuncValue->Val->FuncDef.NumParams) - ParamArray[ArgCount] = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ParamType[ArgCount], FALSE, NULL, FALSE); - - if (ExpressionParse(Parser, &Param)) - { - if (RunIt) - { - if (ArgCount < FuncValue->Val->FuncDef.NumParams) - { - ExpressionAssign(Parser, ParamArray[ArgCount], Param, TRUE, FuncName, ArgCount+1, FALSE); - VariableStackPop(Parser, Param); - } - else - { - if (!FuncValue->Val->FuncDef.VarArgs) - ProgramFail(Parser, "too many arguments to %s()", FuncName); - } - } - - ArgCount++; - Token = LexGetToken(Parser, NULL, TRUE); - if (Token != TokenComma && Token != TokenCloseBracket) - ProgramFail(Parser, "comma expected"); - } - else - { - /* end of argument list? */ - Token = LexGetToken(Parser, NULL, TRUE); - if (!TokenCloseBracket) - ProgramFail(Parser, "bad argument"); - } - - } while (Token != TokenCloseBracket); - - if (RunIt) - { - /* run the function */ - if (ArgCount < FuncValue->Val->FuncDef.NumParams) - ProgramFail(Parser, "not enough arguments to '%s'", FuncName); - - if (FuncValue->Val->FuncDef.Intrinsic == NULL) - { - /* run a user-defined function */ - struct ParseState FuncParser; - int Count; - - if (FuncValue->Val->FuncDef.Body.Pos == NULL) - ProgramFail(Parser, "'%s' is undefined", FuncName); - - ParserCopy(&FuncParser, &FuncValue->Val->FuncDef.Body); - VariableStackFrameAdd(Parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); - TopStackFrame->NumParams = ArgCount; - TopStackFrame->ReturnValue = ReturnValue; - for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++) - VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE); - - if (ParseStatement(&FuncParser, TRUE) != ParseResultOk) - ProgramFail(&FuncParser, "function body expected"); - - if (RunIt) - { - if (FuncParser.Mode == RunModeRun && FuncValue->Val->FuncDef.ReturnType != &VoidType) - ProgramFail(&FuncParser, "no value returned from a function returning %t", FuncValue->Val->FuncDef.ReturnType); - - else if (FuncParser.Mode == RunModeGoto) - ProgramFail(&FuncParser, "couldn't find goto label '%s'", FuncParser.SearchGotoLabel); - } - - VariableStackFramePop(Parser); - } - else - FuncValue->Val->FuncDef.Intrinsic(Parser, ReturnValue, ParamArray, ArgCount); - - HeapPopStackFrame(); - } - - Parser->Mode = OldMode; -} - -/* parse an expression */ -long ExpressionParseInt(struct ParseState *Parser) -{ - struct Value *Val; - long Result = 0; - - if (!ExpressionParse(Parser, &Val)) - ProgramFail(Parser, "expression expected"); - - if (Parser->Mode == RunModeRun) - { - if (!IS_NUMERIC_COERCIBLE(Val)) - ProgramFail(Parser, "integer value expected instead of %t", Val->Typ); - - Result = ExpressionCoerceInteger(Val); - VariableStackPop(Parser, Val); - } - - return Result; -} - diff --git a/ecilib/heap.c b/ecilib/heap.c deleted file mode 100644 index 926edad..0000000 --- a/ecilib/heap.c +++ /dev/null @@ -1,285 +0,0 @@ -/* stack grows up from the bottom and heap grows down from the top of heap space */ -#include "interpreter.h" - -#define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */ -#define SPLIT_MEM_THRESHOLD 16 /* don't split memory which is close in size */ - -#ifdef USE_MALLOC_STACK -static unsigned char *HeapMemory = NULL; /* stack memory since our heap is malloc()ed */ -static void *HeapBottom = NULL; /* the bottom of the (downward-growing) heap */ -static void *StackFrame = NULL; /* the current stack frame */ -void *HeapStackTop = NULL; /* the top of the stack */ -#else -# ifdef SURVEYOR_HOST -static unsigned char *HeapMemory = (unsigned char *)C_HEAPSTART; /* all memory - stack and heap */ -static void *HeapBottom = (void *)C_HEAPSTART + HEAP_SIZE; /* the bottom of the (downward-growing) heap */ -static void *StackFrame = (void *)C_HEAPSTART; /* the current stack frame */ -void *HeapStackTop = (void *)C_HEAPSTART; /* the top of the stack */ -void *HeapMemStart = (void *)C_HEAPSTART; -# else -static unsigned char HeapMemory[HEAP_SIZE]; /* all memory - stack and heap */ -static void *HeapBottom = &HeapMemory[HEAP_SIZE]; /* the bottom of the (downward-growing) heap */ -static void *StackFrame = &HeapMemory[0]; /* the current stack frame */ -void *HeapStackTop = &HeapMemory[0]; /* the top of the stack */ -# endif -#endif - -static struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */ -static struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */ - -#ifdef DEBUG_HEAP -void ShowBigList() -{ - struct AllocNode *LPos; - - printf("Heap: bottom=0x%lx 0x%lx-0x%lx, big freelist=", (long)HeapBottom, (long)&HeapMemory[0], (long)&HeapMemory[HEAP_SIZE]); - for (LPos = FreeListBig; LPos != NULL; LPos = LPos->NextFree) - printf("0x%lx:%d ", (long)LPos, LPos->Size); - - printf("\n"); -} -#endif - -/* initialise the stack and heap storage */ -void HeapInit(int StackOrHeapSize) -{ - int Count; - int AlignOffset = 0; - -#ifdef USE_MALLOC_STACK - HeapMemory = malloc(StackOrHeapSize); -#endif - - while (((unsigned long)&HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0) - AlignOffset++; - - StackFrame = &HeapMemory[AlignOffset]; - HeapStackTop = &HeapMemory[AlignOffset]; - *(void **)StackFrame = NULL; - HeapBottom = &HeapMemory[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset]; - FreeListBig = NULL; - for (Count = 0; Count < FREELIST_BUCKETS; Count++) - FreeListBucket[Count] = NULL; -} - -void HeapCleanup() -{ -#ifdef USE_MALLOC_STACK - free(HeapMemory); -#endif -} - -/* allocate some space on the stack, in the current stack frame - * clears memory. can return NULL if out of stack space */ -void *HeapAllocStack(int Size) -{ - char *NewMem = HeapStackTop; - char *NewTop = (char *)HeapStackTop + MEM_ALIGN(Size); -#ifdef DEBUG_HEAP - printf("HeapAllocStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop); -#endif - if (NewTop > (char *)HeapBottom) - return NULL; - - HeapStackTop = (void *)NewTop; - memset((void *)NewMem, '\0', Size); - return NewMem; -} - -/* allocate some space on the stack, in the current stack frame */ -void HeapUnpopStack(int Size) -{ -#ifdef DEBUG_HEAP - printf("HeapUnpopStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop); -#endif - HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(Size)); -} - -/* free some space at the top of the stack */ -int HeapPopStack(void *Addr, int Size) -{ - int ToLose = MEM_ALIGN(Size); - if (ToLose > ((char *)HeapStackTop - (char *)&HeapMemory[0])) - return FALSE; - -#ifdef DEBUG_HEAP - printf("HeapPopStack(0x%lx, %ld) back to 0x%lx\n", (unsigned long)Addr, (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop - ToLose); -#endif - HeapStackTop = (void *)((char *)HeapStackTop - ToLose); - assert(Addr == NULL || HeapStackTop == Addr); - - return TRUE; -} - -/* push a new stack frame on to the stack */ -void HeapPushStackFrame() -{ -#ifdef DEBUG_HEAP - printf("Adding stack frame at 0x%lx\n", (unsigned long)HeapStackTop); -#endif - *(void **)HeapStackTop = StackFrame; - StackFrame = HeapStackTop; - HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE))); -} - -/* pop the current stack frame, freeing all memory in the frame. can return NULL */ -int HeapPopStackFrame() -{ - if (*(void **)StackFrame != NULL) - { - HeapStackTop = StackFrame; - StackFrame = *(void **)StackFrame; -#ifdef DEBUG_HEAP - printf("Popping stack frame back to 0x%lx\n", (unsigned long)HeapStackTop); -#endif - return TRUE; - } - else - return FALSE; -} - -/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */ -void *HeapAllocMem(int Size) -{ -#ifdef USE_MALLOC_HEAP - return calloc(Size, 1); -#else - struct AllocNode *NewMem = NULL; - struct AllocNode **FreeNode; - int AllocSize = MEM_ALIGN(Size) + MEM_ALIGN(sizeof(NewMem->Size)); - int Bucket; - void *ReturnMem; - - if (Size == 0) - return NULL; - - assert(Size > 0); - - /* make sure we have enough space for an AllocNode */ - if (AllocSize < sizeof(struct AllocNode)) - AllocSize = sizeof(struct AllocNode); - - Bucket = AllocSize >> 2; - if (Bucket < FREELIST_BUCKETS && FreeListBucket[Bucket] != NULL) - { - /* try to allocate from a freelist bucket first */ -#ifdef DEBUG_HEAP - printf("allocating %d(%d) from bucket", Size, AllocSize); -#endif - NewMem = FreeListBucket[Bucket]; - assert((unsigned long)NewMem >= (unsigned long)&HeapMemory[0] && (unsigned char *)NewMem - &HeapMemory[0] < HEAP_SIZE); - FreeListBucket[Bucket] = *(struct AllocNode **)NewMem; - assert(FreeListBucket[Bucket] == NULL || ((unsigned long)FreeListBucket[Bucket] >= (unsigned long)&HeapMemory[0] && (unsigned char *)FreeListBucket[Bucket] - &HeapMemory[0] < HEAP_SIZE)); - NewMem->Size = AllocSize; - } - else if (FreeListBig != NULL) - { - /* grab the first item from the "big" freelist we can fit in */ - for (FreeNode = &FreeListBig; *FreeNode != NULL && (*FreeNode)->Size < AllocSize; FreeNode = &(*FreeNode)->NextFree) - {} - - if (*FreeNode != NULL) - { - assert((unsigned long)*FreeNode >= (unsigned long)&HeapMemory[0] && (unsigned char *)*FreeNode - &HeapMemory[0] < HEAP_SIZE); - assert((*FreeNode)->Size < HEAP_SIZE && (*FreeNode)->Size > 0); - if ((*FreeNode)->Size < AllocSize + SPLIT_MEM_THRESHOLD) - { - /* close in size - reduce fragmentation by not splitting */ -#ifdef DEBUG_HEAP - printf("allocating %d(%d) from freelist, no split (%d)", Size, AllocSize, (*FreeNode)->Size); -#endif - NewMem = *FreeNode; - assert((unsigned long)NewMem >= (unsigned long)&HeapMemory[0] && (unsigned char *)NewMem - &HeapMemory[0] < HEAP_SIZE); - *FreeNode = NewMem->NextFree; - } - else - { - /* split this big memory chunk */ -#ifdef DEBUG_HEAP - printf("allocating %d(%d) from freelist, split chunk (%d)", Size, AllocSize, (*FreeNode)->Size); -#endif - NewMem = (void *)((char *)*FreeNode + (*FreeNode)->Size - AllocSize); - assert((unsigned long)NewMem >= (unsigned long)&HeapMemory[0] && (unsigned char *)NewMem - &HeapMemory[0] < HEAP_SIZE); - (*FreeNode)->Size -= AllocSize; - NewMem->Size = AllocSize; - } - } - } - - if (NewMem == NULL) - { - /* couldn't allocate from a freelist - try to increase the size of the heap area */ -#ifdef DEBUG_HEAP - printf("allocating %d(%d) at bottom of heap (0x%lx-0x%lx)", Size, AllocSize, (long)((char *)HeapBottom - AllocSize), (long)HeapBottom); -#endif - if ((char *)HeapBottom - AllocSize < (char *)HeapStackTop) - return NULL; - - HeapBottom = (void *)((char *)HeapBottom - AllocSize); - NewMem = HeapBottom; - NewMem->Size = AllocSize; - } - - ReturnMem = (void *)((char *)NewMem + MEM_ALIGN(sizeof(NewMem->Size))); - memset(ReturnMem, '\0', AllocSize - MEM_ALIGN(sizeof(NewMem->Size))); -#ifdef DEBUG_HEAP - printf(" = %lx\n", (unsigned long)ReturnMem); -#endif - return ReturnMem; -#endif -} - -/* free some dynamically allocated memory */ -void HeapFreeMem(void *Mem) -{ -#ifdef USE_MALLOC_HEAP - free(Mem); -#else - struct AllocNode *MemNode = (struct AllocNode *)((char *)Mem - MEM_ALIGN(sizeof(MemNode->Size))); - int Bucket = MemNode->Size >> 2; - -#ifdef DEBUG_HEAP - printf("HeapFreeMem(0x%lx)\n", (unsigned long)Mem); -#endif - assert((unsigned long)Mem >= (unsigned long)&HeapMemory[0] && (unsigned char *)Mem - &HeapMemory[0] < HEAP_SIZE); - assert(MemNode->Size < HEAP_SIZE && MemNode->Size > 0); - if (Mem == NULL) - return; - - if ((void *)MemNode == HeapBottom) - { - /* pop it off the bottom of the heap, reducing the heap size */ -#ifdef DEBUG_HEAP - printf("freeing %d from bottom of heap\n", MemNode->Size); -#endif - HeapBottom = (void *)((char *)HeapBottom + MemNode->Size); -#ifdef DEBUG_HEAP - ShowBigList(); -#endif - } - else if (Bucket < FREELIST_BUCKETS) - { - /* we can fit it in a bucket */ -#ifdef DEBUG_HEAP - printf("freeing %d to bucket\n", MemNode->Size); -#endif - assert(FreeListBucket[Bucket] == NULL || ((unsigned long)FreeListBucket[Bucket] >= (unsigned long)&HeapMemory[0] && (unsigned char *)FreeListBucket[Bucket] - &HeapMemory[0] < HEAP_SIZE)); - *(struct AllocNode **)MemNode = FreeListBucket[Bucket]; - FreeListBucket[Bucket] = (struct AllocNode *)MemNode; - } - else - { - /* put it in the big memory freelist */ -#ifdef DEBUG_HEAP - printf("freeing %lx:%d to freelist\n", (unsigned long)Mem, MemNode->Size); -#endif - assert(FreeListBig == NULL || ((unsigned long)FreeListBig >= (unsigned long)&HeapMemory[0] && (unsigned char *)FreeListBig - &HeapMemory[0] < HEAP_SIZE)); - MemNode->NextFree = FreeListBig; - FreeListBig = MemNode; -#ifdef DEBUG_HEAP - ShowBigList(); -#endif - } -#endif -} - diff --git a/ecilib/include.c b/ecilib/include.c deleted file mode 100644 index 360fe93..0000000 --- a/ecilib/include.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "picoc.h" -#include "interpreter.h" - -#ifndef NO_HASH_INCLUDE - -/* a list of libraries we can include */ -struct IncludeLibrary -{ - char *IncludeName; - void (*SetupFunction)(void); - struct LibraryFunction *FuncList; - const char *SetupCSource; - struct IncludeLibrary *NextLib; -}; - -struct IncludeLibrary *IncludeLibList = NULL; - - -/* initialise the built-in include libraries */ -void IncludeInit() -{ -#ifndef BUILTIN_MINI_STDLIB - IncludeRegister("ctype.h", NULL, &StdCtypeFunctions[0], NULL); - IncludeRegister("errno.h", &StdErrnoSetupFunc, NULL, NULL); -#ifndef NO_FP - IncludeRegister("math.h", &MathSetupFunc, &MathFunctions[0], NULL); -#endif - IncludeRegister("stdbool.h", &StdboolSetupFunc, NULL, StdboolDefs); - IncludeRegister("stdio.h", &StdioSetupFunc, &StdioFunctions[0], StdioDefs); - IncludeRegister("stdlib.h", &StdlibSetupFunc, &StdlibFunctions[0], NULL); - IncludeRegister("string.h", &StringSetupFunc, &StringFunctions[0], NULL); - IncludeRegister("time.h", &StdTimeSetupFunc, &StdTimeFunctions[0], StdTimeDefs); - IncludeRegister("unistd.h", &UnistdSetupFunc, &UnistdFunctions[0], UnistdDefs); -#endif -} - -/* clean up space used by the include system */ -void IncludeCleanup() -{ - struct IncludeLibrary *ThisInclude = IncludeLibList; - struct IncludeLibrary *NextInclude; - - while (ThisInclude != NULL) - { - NextInclude = ThisInclude->NextLib; - HeapFreeMem(ThisInclude); - ThisInclude = NextInclude; - } - - IncludeLibList = NULL; -} - -/* register a new build-in include file */ -void IncludeRegister(const char *IncludeName, void (*SetupFunction)(void), struct LibraryFunction *FuncList, const char *SetupCSource) -{ - struct IncludeLibrary *NewLib = HeapAllocMem(sizeof(struct IncludeLibrary)); - NewLib->IncludeName = TableStrRegister(IncludeName); - NewLib->SetupFunction = SetupFunction; - NewLib->FuncList = FuncList; - NewLib->SetupCSource = SetupCSource; - NewLib->NextLib = IncludeLibList; - IncludeLibList = NewLib; -} - -/* include all of the system headers */ -void PicocIncludeAllSystemHeaders() -{ - struct IncludeLibrary *ThisInclude = IncludeLibList; - - for (; ThisInclude != NULL; ThisInclude = ThisInclude->NextLib) - IncludeFile(ThisInclude->IncludeName); -} - -/* include one of a number of predefined libraries, or perhaps an actual file */ -void IncludeFile(char *FileName) -{ - struct IncludeLibrary *LInclude; - - /* scan for the include file name to see if it's in our list of predefined includes */ - for (LInclude = IncludeLibList; LInclude != NULL; LInclude = LInclude->NextLib) - { - if (strcmp(LInclude->IncludeName, FileName) == 0) - { - /* found it - protect against multiple inclusion */ - if (!VariableDefined(FileName)) - { - VariableDefine(NULL, FileName, NULL, &VoidType, FALSE); - - /* run an extra startup function if there is one */ - if (LInclude->SetupFunction != NULL) - (*LInclude->SetupFunction)(); - - /* parse the setup C source code - may define types etc. */ - if (LInclude->SetupCSource != NULL) - PicocParse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE); - - /* set up the library functions */ - if (LInclude->FuncList != NULL) - LibraryAdd(&GlobalTable, FileName, LInclude->FuncList); - } - - return; - } - } - - /* not a predefined file, read a real file */ - PicocPlatformScanFile(FileName); -} - -#endif /* NO_HASH_INCLUDE */ diff --git a/ecilib/lex.c b/ecilib/lex.c deleted file mode 100644 index f8bd28e..0000000 --- a/ecilib/lex.c +++ /dev/null @@ -1,971 +0,0 @@ -#include "interpreter.h" - -#ifdef NO_CTYPE -#define isalpha(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) -#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)=='_') - -#define IS_HEX_ALPHA_DIGIT(c) (((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#define IS_BASE_DIGIT(c,b) (((c) >= '0' && (c) < '0' + (((b)<10)?(b):10)) || (((b) > 10) ? IS_HEX_ALPHA_DIGIT(c) : FALSE)) -#define GET_BASE_DIGIT(c) (((c) <= '9') ? ((c) - '0') : (((c) <= 'F') ? ((c) - 'A' + 10) : ((c) - 'a' + 10))) - -#define NEXTIS(c,x,y) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else GotToken = (y); } -#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS(d,y,z) } -#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS3(d,y,e,z,a) } -#define NEXTIS3PLUS(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else if (NextChar == (d)) { if (Lexer->Pos[1] == (e)) { LEXER_INCN(Lexer, 2); GotToken = (z); } else { LEXER_INC(Lexer); GotToken = (y); } } else GotToken = (a); } -#define NEXTISEXACTLY3(c,d,y,z) { if (NextChar == (c) && Lexer->Pos[1] == (d)) { LEXER_INCN(Lexer, 2); GotToken = (y); } else GotToken = (z); } - -#define LEXER_INC(l) ( (l)->Pos++, (l)->CharacterPos++ ) -#define LEXER_INCN(l, n) ( (l)->Pos+=(n), (l)->CharacterPos+=(n) ) -#define TOKEN_DATA_OFFSET 2 - -#define MAX_CHAR_VALUE 255 /* maximum value which can be represented by a "char" data type */ - -static union AnyValue LexAnyValue; -static struct Value LexValue = { TypeVoid, &LexAnyValue, FALSE, FALSE }; - -struct ReservedWord -{ - const char *Word; - enum LexToken Token; - const char *SharedWord; /* word stored in shared string space */ -}; - -static struct ReservedWord ReservedWords[] = -{ - { "#define", TokenHashDefine, NULL }, - { "#else", TokenHashElse, NULL }, - { "#endif", TokenHashEndif, NULL }, - { "#if", TokenHashIf, NULL }, - { "#ifdef", TokenHashIfdef, NULL }, - { "#ifndef", TokenHashIfndef, NULL }, - { "#include", TokenHashInclude, NULL }, - { "auto", TokenAutoType, NULL }, - { "break", TokenBreak, NULL }, - { "case", TokenCase, NULL }, - { "char", TokenCharType, NULL }, - { "continue", TokenContinue, NULL }, - { "default", TokenDefault, NULL }, - { "delete", TokenDelete, NULL }, - { "do", TokenDo, NULL }, -#ifndef NO_FP - { "double", TokenDoubleType, NULL }, -#endif - { "else", TokenElse, NULL }, - { "enum", TokenEnumType, NULL }, - { "extern", TokenExternType, NULL }, -#ifndef NO_FP - { "float", TokenFloatType, NULL }, -#endif - { "for", TokenFor, NULL }, - { "goto", TokenGoto, NULL }, - { "if", TokenIf, NULL }, - { "int", TokenIntType, NULL }, - { "long", TokenLongType, NULL }, - { "new", TokenNew, NULL }, - { "register", TokenRegisterType, NULL }, - { "return", TokenReturn, NULL }, - { "short", TokenShortType, NULL }, - { "signed", TokenSignedType, NULL }, - { "sizeof", TokenSizeof, NULL }, - { "static", TokenStaticType, NULL }, - { "struct", TokenStructType, NULL }, - { "switch", TokenSwitch, NULL }, - { "typedef", TokenTypedef, NULL }, - { "union", TokenUnionType, NULL }, - { "unsigned", TokenUnsignedType, NULL }, - { "void", TokenVoidType, NULL }, - { "while", TokenWhile, NULL } -}; - -/* linked list of tokens used in interactive mode */ -struct TokenLine -{ - struct TokenLine *Next; - unsigned char *Tokens; - int NumBytes; -}; - -static struct TokenLine *InteractiveHead = NULL; -static struct TokenLine *InteractiveTail = NULL; -static struct TokenLine *InteractiveCurrentLine = NULL; -static int LexUseStatementPrompt = FALSE; - - -/* initialise the lexer */ -void LexInit() -{ - int Count; - - for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) - ReservedWords[Count].SharedWord = TableStrRegister(ReservedWords[Count].Word); -} - -/* deallocate */ -void LexCleanup() -{ - LexInteractiveClear(NULL); -} - -/* check if a word is a reserved word - used while scanning */ -enum LexToken LexCheckReservedWord(const char *Word) -{ - int Count; - - for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) - { - if (Word == ReservedWords[Count].SharedWord) - return ReservedWords[Count].Token; - } - - return TokenNone; -} - -/* get a numeric literal - used while scanning */ -enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value) -{ - int Result = 0; - int Base = 10; - enum LexToken ResultToken; -#ifndef NO_FP - double FPResult; - double FPDiv; -#endif - - if (*Lexer->Pos == '0') - { - /* a binary, octal or hex literal */ - LEXER_INC(Lexer); - if (Lexer->Pos != Lexer->End) - { - if (*Lexer->Pos == 'x' || *Lexer->Pos == 'X') - { Base = 16; LEXER_INC(Lexer); } - else if (*Lexer->Pos == 'b' || *Lexer->Pos == 'B') - { Base = 2; LEXER_INC(Lexer); } - else if (*Lexer->Pos != '.') - Base = 8; - } - } - - /* get the value */ - for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer)) - Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos); - - if (Result >= 0 && Result <= MAX_CHAR_VALUE) - { - Value->Typ = &CharType; - Value->Val->Character = Result; - ResultToken = TokenCharacterConstant; - } - else - { - Value->Typ = &IntType; - Value->Val->Integer = Result; - ResultToken = TokenIntegerConstant; - } - - if (Lexer->Pos == Lexer->End) - return ResultToken; - - if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L') - { - LEXER_INC(Lexer); - return ResultToken; - } - -#ifndef NO_FP - if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.') - return ResultToken; - - Value->Typ = &FPType; - LEXER_INC(Lexer); - for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base) - FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv; - - if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E')) - { - double ExponentMultiplier = 1.0; - - LEXER_INC(Lexer); - if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-') - { - ExponentMultiplier = -1.0; - LEXER_INC(Lexer); - } - - for (Result = 0; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer)) - Result = Result * (double)Base + GET_BASE_DIGIT(*Lexer->Pos); - - FPResult *= pow((double)Base, (double)Result * ExponentMultiplier); - } - - Value->Val->FP = FPResult; - - return TokenFPConstant; -#else - return ResultToken; -#endif -} - -/* get a reserved word or identifier - used while scanning */ -enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value) -{ - const char *StartPos = Lexer->Pos; - enum LexToken Token; - - do { - LEXER_INC(Lexer); - } while (Lexer->Pos != Lexer->End && isCident((int)*Lexer->Pos)); - - Value->Typ = NULL; - Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos); - - Token = LexCheckReservedWord(Value->Val->Identifier); - switch (Token) - { - case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break; - case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break; - default: break; - } - - if (Token != TokenNone) - return Token; - - if (Lexer->Mode == LexModeHashDefineSpace) - Lexer->Mode = LexModeHashDefineSpaceIdent; - - return TokenIdentifier; -} - -/* unescape a character from an octal character constant */ -unsigned char LexUnEscapeCharacterConstant(const char **From, const char *End, unsigned char FirstChar, int Base) -{ - unsigned char Total = GET_BASE_DIGIT(FirstChar); - int CCount; - for (CCount = 0; IS_BASE_DIGIT(**From, Base) && CCount < 2; CCount++, (*From)++) - Total = Total * Base + GET_BASE_DIGIT(**From); - - return Total; -} - -/* unescape a character from a string or character constant */ -unsigned char LexUnEscapeCharacter(const char **From, const char *End) -{ - unsigned char ThisChar; - - while ( *From != End && **From == '\\' && - &(*From)[1] != End && (*From)[1] == '\n' ) - (*From) += 2; /* skip escaped end of lines with LF line termination */ - - while ( *From != End && **From == '\\' && - &(*From)[1] != End && &(*From)[2] != End && (*From)[1] == '\r' && (*From)[2] == '\n') - (*From) += 3; /* skip escaped end of lines with CR/LF line termination */ - - if (*From == End) - return '\\'; - - if (**From == '\\') - { - /* it's escaped */ - (*From)++; - if (*From == End) - return '\\'; - - ThisChar = *(*From)++; - switch (ThisChar) - { - case '\\': return '\\'; - case '\'': return '\''; - case '"': return '"'; - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'v': return '\v'; - case '0': case '1': case '2': case '3': return LexUnEscapeCharacterConstant(From, End, ThisChar, 8); - case 'x': return LexUnEscapeCharacterConstant(From, End, '0', 16); - default: return ThisChar; - } - } - else - return *(*From)++; -} - -/* get a string constant - used while scanning */ -enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value, char EndChar) -{ - int Escape = FALSE; - const char *StartPos = Lexer->Pos; - const char *EndPos; - char *EscBuf; - char *EscBufPos; - char *RegString; - struct Value *ArrayValue; - - while (Lexer->Pos != Lexer->End && (*Lexer->Pos != EndChar || Escape)) - { - /* find the end */ - if (Escape) - { - if (*Lexer->Pos == '\r' && Lexer->Pos+1 != Lexer->End) - Lexer->Pos++; - - if (*Lexer->Pos == '\n' && Lexer->Pos+1 != Lexer->End) - { - Lexer->Line++; - Lexer->Pos++; - Lexer->CharacterPos = 0; - Lexer->EmitExtraNewlines++; - } - - Escape = FALSE; - } - else if (*Lexer->Pos == '\\') - Escape = TRUE; - - LEXER_INC(Lexer); - } - EndPos = Lexer->Pos; - - EscBuf = HeapAllocStack(EndPos - StartPos); - if (EscBuf == NULL) - LexFail(Lexer, "out of memory"); - - for (EscBufPos = EscBuf, Lexer->Pos = StartPos; Lexer->Pos != EndPos;) - *EscBufPos++ = LexUnEscapeCharacter(&Lexer->Pos, EndPos); - - /* try to find an existing copy of this string literal */ - RegString = TableStrRegister2(EscBuf, EscBufPos - EscBuf); - HeapPopStack(EscBuf, EndPos - StartPos); - ArrayValue = VariableStringLiteralGet(RegString); - if (ArrayValue == NULL) - { - /* create and store this string literal */ - ArrayValue = VariableAllocValueAndData(NULL, 0, FALSE, NULL, TRUE); - ArrayValue->Typ = CharArrayType; - ArrayValue->Val = (union AnyValue *)RegString; - VariableStringLiteralDefine(RegString, ArrayValue); - } - - /* create the the pointer for this char* */ - Value->Typ = CharPtrType; - Value->Val->Pointer = RegString; - if (*Lexer->Pos == EndChar) - LEXER_INC(Lexer); - - return TokenStringConstant; -} - -/* get a character constant - used while scanning */ -enum LexToken LexGetCharacterConstant(struct LexState *Lexer, struct Value *Value) -{ - Value->Typ = &CharType; - Value->Val->Character = LexUnEscapeCharacter(&Lexer->Pos, Lexer->End); - if (Lexer->Pos != Lexer->End && *Lexer->Pos != '\'') - LexFail(Lexer, "expected \"'\""); - - LEXER_INC(Lexer); - return TokenCharacterConstant; -} - -/* skip a comment - used while scanning */ -void LexSkipComment(struct LexState *Lexer, char NextChar, enum LexToken *ReturnToken) -{ - if (NextChar == '*') - { - /* conventional C comment */ - while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/')) - { - if (*Lexer->Pos == '\n') - Lexer->EmitExtraNewlines++; - - LEXER_INC(Lexer); - } - - if (Lexer->Pos != Lexer->End) - LEXER_INC(Lexer); - - Lexer->Mode = LexModeNormal; - } - else - { - /* C++ style comment */ - while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n') - LEXER_INC(Lexer); - } -} - -/* get a single token from the source - used while scanning */ -enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value) -{ - char ThisChar; - char NextChar; - enum LexToken GotToken = TokenNone; - - /* handle cases line multi-line comments or string constants which mess up the line count */ - if (Lexer->EmitExtraNewlines > 0) - { - Lexer->EmitExtraNewlines--; - return TokenEndOfLine; - } - - /* scan for a token */ - do - { - *Value = &LexValue; - while (Lexer->Pos != Lexer->End && isspace((int)*Lexer->Pos)) - { - if (*Lexer->Pos == '\n') - { - Lexer->Line++; - Lexer->Pos++; - Lexer->Mode = LexModeNormal; - Lexer->CharacterPos = 0; - return TokenEndOfLine; - } - else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace) - Lexer->Mode = LexModeHashDefineSpace; - - else if (Lexer->Mode == LexModeHashDefineSpaceIdent) - Lexer->Mode = LexModeNormal; - - LEXER_INC(Lexer); - } - - if (Lexer->Pos == Lexer->End || *Lexer->Pos == '\0') - return TokenEOF; - - ThisChar = *Lexer->Pos; - if (isCidstart((int)ThisChar)) - return LexGetWord(Lexer, *Value); - - if (isdigit((int)ThisChar)) - return LexGetNumber(Lexer, *Value); - - NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0; - LEXER_INC(Lexer); - switch (ThisChar) - { - case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break; - case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break; - case '(': if (Lexer->Mode == LexModeHashDefineSpaceIdent) GotToken = TokenOpenMacroBracket; else GotToken = TokenOpenBracket; Lexer->Mode = LexModeNormal; break; - case ')': GotToken = TokenCloseBracket; break; - case '=': NEXTIS('=', TokenEqual, TokenAssign); break; - case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break; - case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); break; - case '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break; - case '/': if (NextChar == '/' || NextChar == '*') { LEXER_INC(Lexer); LexSkipComment(Lexer, NextChar, &GotToken); } else NEXTIS('=', TokenDivideAssign, TokenSlash); break; - case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); break; - case '<': if (Lexer->Mode == LexModeHashInclude) GotToken = LexGetStringConstant(Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break; - case '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break; - case ';': GotToken = TokenSemicolon; break; - case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); break; - case '|': NEXTIS3('=', TokenArithmeticOrAssign, '|', TokenLogicalOr, TokenArithmeticOr); break; - case '{': GotToken = TokenLeftBrace; break; - case '}': GotToken = TokenRightBrace; break; - case '[': GotToken = TokenLeftSquareBracket; break; - case ']': GotToken = TokenRightSquareBracket; break; - case '!': NEXTIS('=', TokenNotEqual, TokenUnaryNot); break; - case '^': NEXTIS('=', TokenArithmeticExorAssign, TokenArithmeticExor); break; - case '~': GotToken = TokenUnaryExor; break; - case ',': GotToken = TokenComma; break; - case '.': NEXTISEXACTLY3('.', '.', TokenEllipsis, TokenDot); break; - case '?': GotToken = TokenQuestionMark; break; - case ':': GotToken = TokenColon; break; - default: LexFail(Lexer, "illegal character '%c'", ThisChar); break; - } - } while (GotToken == TokenNone); - - return GotToken; -} - -/* what size value goes with each token */ -int LexTokenSize(enum LexToken Token) -{ - switch (Token) - { - case TokenIdentifier: case TokenStringConstant: return sizeof(char *); - case TokenIntegerConstant: return sizeof(int); - case TokenCharacterConstant: return sizeof(unsigned char); - case TokenFPConstant: return sizeof(double); - default: return 0; - } -} - -/* produce tokens from the lexer and return a heap buffer with the result - used for scanning */ -void *LexTokenise(struct LexState *Lexer, int *TokenLen) -{ - enum LexToken Token; - void *HeapMem; - struct Value *GotValue; - int MemUsed = 0; - int ValueSize; - int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 16; - void *TokenSpace = HeapAllocStack(ReserveSpace); - char *TokenPos = (char *)TokenSpace; - int LastCharacterPos = 0; - - if (TokenSpace == NULL) - LexFail(Lexer, "out of memory"); - - do - { - /* store the token at the end of the stack area */ - Token = LexScanGetToken(Lexer, &GotValue); - -#ifdef DEBUG_LEXER - printf("Token: %02x\n", Token); -#endif - *(unsigned char *)TokenPos = Token; - TokenPos++; - MemUsed++; - - *(unsigned char *)TokenPos = (unsigned char)LastCharacterPos; - TokenPos++; - MemUsed++; - - ValueSize = LexTokenSize(Token); - if (ValueSize > 0) - { - /* store a value as well */ - memcpy((void *)TokenPos, (void *)GotValue->Val, ValueSize); - TokenPos += ValueSize; - MemUsed += ValueSize; - } - - LastCharacterPos = Lexer->CharacterPos; - - } while (Token != TokenEOF); - - HeapMem = HeapAllocMem(MemUsed); - if (HeapMem == NULL) - LexFail(Lexer, "out of memory"); - - assert(ReserveSpace >= MemUsed); - memcpy(HeapMem, TokenSpace, MemUsed); - HeapPopStack(TokenSpace, ReserveSpace); -#ifdef DEBUG_LEXER - { - int Count; - printf("Tokens: "); - for (Count = 0; Count < MemUsed; Count++) - printf("%02x ", *((unsigned char *)HeapMem+Count)); - printf("\n"); - } -#endif - if (TokenLen) - *TokenLen = MemUsed; - - return HeapMem; -} - -/* lexically analyse some source text */ -void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen) -{ - struct LexState Lexer; - - Lexer.Pos = Source; - Lexer.End = Source + SourceLen; - Lexer.Line = 1; - Lexer.FileName = FileName; - Lexer.Mode = LexModeNormal; - Lexer.EmitExtraNewlines = 0; - Lexer.CharacterPos = 1; - Lexer.SourceText = Source; - - return LexTokenise(&Lexer, TokenLen); -} - -/* prepare to parse a pre-tokenised buffer */ -void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt) -{ - Parser->Pos = TokenSource; - Parser->Line = 1; - Parser->FileName = FileName; - Parser->Mode = RunIt ? RunModeRun : RunModeSkip; - Parser->SearchLabel = 0; - Parser->HashIfLevel = 0; - Parser->HashIfEvaluateToLevel = 0; - Parser->CharacterPos = 0; - Parser->SourceText = SourceText; -} - -/* get the next token, without pre-processing */ -enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, int IncPos) -{ - enum LexToken Token = TokenNone; - int ValueSize; - char *Prompt = NULL; - - do - { - /* get the next token */ - if (Parser->Pos == NULL && InteractiveHead != NULL) - Parser->Pos = InteractiveHead->Tokens; - - if (Parser->FileName != StrEmpty || InteractiveHead != NULL) - { - /* skip leading newlines */ - while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine) - { - Parser->Line++; - Parser->Pos += TOKEN_DATA_OFFSET; - } - } - - if (Parser->FileName == StrEmpty && (InteractiveHead == NULL || Token == TokenEOF)) - { - /* we're at the end of an interactive input token list */ - char LineBuffer[LINEBUFFER_MAX]; - void *LineTokens; - int LineBytes; - struct TokenLine *LineNode; - - if (InteractiveHead == NULL || (unsigned char *)Parser->Pos == &InteractiveTail->Tokens[InteractiveTail->NumBytes-TOKEN_DATA_OFFSET]) - { - /* get interactive input */ - if (LexUseStatementPrompt) - { - Prompt = INTERACTIVE_PROMPT_STATEMENT; - LexUseStatementPrompt = FALSE; - } - else - Prompt = INTERACTIVE_PROMPT_LINE; - - if (PlatformGetLine(&LineBuffer[0], LINEBUFFER_MAX, Prompt) == NULL) - return TokenEOF; - - /* put the new line at the end of the linked list of interactive lines */ - LineTokens = LexAnalyse(StrEmpty, &LineBuffer[0], strlen(LineBuffer), &LineBytes); - LineNode = VariableAlloc(Parser, sizeof(struct TokenLine), TRUE); - LineNode->Tokens = LineTokens; - LineNode->NumBytes = LineBytes; - if (InteractiveHead == NULL) - { - /* start a new list */ - InteractiveHead = LineNode; - Parser->Line = 1; - Parser->CharacterPos = 0; - } - else - InteractiveTail->Next = LineNode; - - InteractiveTail = LineNode; - InteractiveCurrentLine = LineNode; - Parser->Pos = LineTokens; - } - else - { - /* go to the next token line */ - if (Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]) - { - /* scan for the line */ - for (InteractiveCurrentLine = InteractiveHead; Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; InteractiveCurrentLine = InteractiveCurrentLine->Next) - { assert(InteractiveCurrentLine->Next != NULL); } - } - - assert(InteractiveCurrentLine != NULL); - InteractiveCurrentLine = InteractiveCurrentLine->Next; - assert(InteractiveCurrentLine != NULL); - Parser->Pos = InteractiveCurrentLine->Tokens; - } - - Token = (enum LexToken)*(unsigned char *)Parser->Pos; - } - } while ((Parser->FileName == StrEmpty && Token == TokenEOF) || Token == TokenEndOfLine); - - Parser->CharacterPos = *((unsigned char *)Parser->Pos + 1); - ValueSize = LexTokenSize(Token); - if (ValueSize > 0) - { - /* this token requires a value - unpack it */ - if (Value != NULL) - { - switch (Token) - { - case TokenStringConstant: LexValue.Typ = CharPtrType; break; - case TokenIdentifier: LexValue.Typ = NULL; break; - case TokenIntegerConstant: LexValue.Typ = &IntType; break; - case TokenCharacterConstant: LexValue.Typ = &CharType; break; -#ifndef NO_FP - case TokenFPConstant: LexValue.Typ = &FPType; break; -#endif - default: break; - } - - memcpy((void *)LexValue.Val, (void *)((char *)Parser->Pos + TOKEN_DATA_OFFSET), ValueSize); - LexValue.ValOnHeap = FALSE; - LexValue.ValOnStack = FALSE; - LexValue.IsLValue = FALSE; - LexValue.LValueFrom = NULL; - *Value = &LexValue; - } - - if (IncPos) - Parser->Pos += ValueSize + TOKEN_DATA_OFFSET; - } - else - { - if (IncPos && Token != TokenEOF) - Parser->Pos += TOKEN_DATA_OFFSET; - } - -#ifdef DEBUG_LEXER - printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos); -#endif - assert(Token >= TokenNone && Token <= TokenEndOfFunction); - return Token; -} - -/* correct the token position depending if we already incremented the position */ -void LexHashIncPos(struct ParseState *Parser, int IncPos) -{ - if (!IncPos) - LexGetRawToken(Parser, NULL, TRUE); -} - -/* handle a #ifdef directive */ -void LexHashIfdef(struct ParseState *Parser, int IfNot) -{ - /* get symbol to check */ - struct Value *IdentValue; - struct Value *SavedValue; - int IsDefined; - enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE); - - if (Token != TokenIdentifier) - ProgramFail(Parser, "identifier expected"); - - /* is the identifier defined? */ - IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL); - if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ( (IsDefined && !IfNot) || (!IsDefined && IfNot)) ) - { - /* #if is active, evaluate to this new level */ - Parser->HashIfEvaluateToLevel++; - } - - Parser->HashIfLevel++; -} - -/* handle a #if directive */ -void LexHashIf(struct ParseState *Parser) -{ - /* get symbol to check */ - struct Value *IdentValue; - struct Value *SavedValue; - struct ParseState MacroParser; - enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE); - - if (Token == TokenIdentifier) - { - /* look up a value from a macro definition */ - if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL, NULL)) - ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier); - - if (SavedValue->Typ->Base != TypeMacro) - ProgramFail(Parser, "value expected"); - - ParserCopy(&MacroParser, &SavedValue->Val->MacroDef.Body); - Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE); - } - - if (Token != TokenCharacterConstant) - ProgramFail(Parser, "value expected"); - - /* is the identifier defined? */ - if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && IdentValue->Val->Character) - { - /* #if is active, evaluate to this new level */ - Parser->HashIfEvaluateToLevel++; - } - - Parser->HashIfLevel++; -} - -/* handle a #else directive */ -void LexHashElse(struct ParseState *Parser) -{ - if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel - 1) - Parser->HashIfEvaluateToLevel++; /* #if was not active, make this next section active */ - - else if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel) - { - /* #if was active, now go inactive */ - if (Parser->HashIfLevel == 0) - ProgramFail(Parser, "#else without #if"); - - Parser->HashIfEvaluateToLevel--; - } -} - -/* handle a #endif directive */ -void LexHashEndif(struct ParseState *Parser) -{ - if (Parser->HashIfLevel == 0) - ProgramFail(Parser, "#endif without #if"); - - Parser->HashIfLevel--; - if (Parser->HashIfEvaluateToLevel > Parser->HashIfLevel) - Parser->HashIfEvaluateToLevel = Parser->HashIfLevel; -} - -/* get the next token given a parser state, pre-processing as we go */ -enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos) -{ - enum LexToken Token; - int TryNextToken; - - /* implements the pre-processor #if commands */ - do - { - int WasPreProcToken = TRUE; - - Token = LexGetRawToken(Parser, Value, IncPos); - switch (Token) - { - case TokenHashIfdef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, FALSE); break; - case TokenHashIfndef: LexHashIncPos(Parser, IncPos); LexHashIfdef(Parser, TRUE); break; - case TokenHashIf: LexHashIncPos(Parser, IncPos); LexHashIf(Parser); break; - case TokenHashElse: LexHashIncPos(Parser, IncPos); LexHashElse(Parser); break; - case TokenHashEndif: LexHashIncPos(Parser, IncPos); LexHashEndif(Parser); break; - default: WasPreProcToken = FALSE; break; - } - - /* if we're going to reject this token, increment the token pointer to the next one */ - TryNextToken = (Parser->HashIfEvaluateToLevel < Parser->HashIfLevel && Token != TokenEOF) || WasPreProcToken; - if (!IncPos && TryNextToken) - LexGetRawToken(Parser, NULL, TRUE); - - } while (TryNextToken); - - return Token; -} - -/* take a quick peek at the next token, skipping any pre-processing */ -enum LexToken LexRawPeekToken(struct ParseState *Parser) -{ - return (enum LexToken)*(unsigned char *)Parser->Pos; -} - -/* find the end of the line */ -void LexToEndOfLine(struct ParseState *Parser) -{ - while (TRUE) - { - enum LexToken Token = (enum LexToken)*(unsigned char *)Parser->Pos; - if (Token == TokenEndOfLine || Token == TokenEOF) - return; - else - LexGetRawToken(Parser, NULL, TRUE); - } -} - -/* copy the tokens from StartParser to EndParser into new memory, removing TokenEOFs and terminate with a TokenEndOfFunction */ -void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser) -{ - int MemSize = 0; - int CopySize; - unsigned char *Pos = (unsigned char *)StartParser->Pos; - unsigned char *NewTokens; - unsigned char *NewTokenPos; - struct TokenLine *ILine; - - if (InteractiveHead == NULL) - { - /* non-interactive mode - copy the tokens */ - MemSize = EndParser->Pos - StartParser->Pos; - NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); - memcpy(NewTokens, (void *)StartParser->Pos, MemSize); - } - else - { - /* we're in interactive mode - add up line by line */ - for (InteractiveCurrentLine = InteractiveHead; InteractiveCurrentLine != NULL && (Pos < &InteractiveCurrentLine->Tokens[0] || Pos >= &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes]); InteractiveCurrentLine = InteractiveCurrentLine->Next) - {} /* find the line we just counted */ - - if (EndParser->Pos >= StartParser->Pos && EndParser->Pos < &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes]) - { - /* all on a single line */ - MemSize = EndParser->Pos - StartParser->Pos; - NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); - memcpy(NewTokens, (void *)StartParser->Pos, MemSize); - } - else - { - /* it's spread across multiple lines */ - MemSize = &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; - - for (ILine = InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) - MemSize += ILine->NumBytes - TOKEN_DATA_OFFSET; - - assert(ILine != NULL); - MemSize += EndParser->Pos - &ILine->Tokens[0]; - NewTokens = VariableAlloc(StartParser, MemSize + TOKEN_DATA_OFFSET, TRUE); - - CopySize = &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET] - Pos; - memcpy(NewTokens, Pos, CopySize); - NewTokenPos = NewTokens + CopySize; - for (ILine = InteractiveCurrentLine->Next; ILine != NULL && (EndParser->Pos < &ILine->Tokens[0] || EndParser->Pos >= &ILine->Tokens[ILine->NumBytes]); ILine = ILine->Next) - { - memcpy(NewTokenPos, &ILine->Tokens[0], ILine->NumBytes - TOKEN_DATA_OFFSET); - NewTokenPos += ILine->NumBytes-TOKEN_DATA_OFFSET; - } - assert(ILine != NULL); - memcpy(NewTokenPos, &ILine->Tokens[0], EndParser->Pos - &ILine->Tokens[0]); - } - } - - NewTokens[MemSize] = (unsigned char)TokenEndOfFunction; - - return NewTokens; -} - -/* indicate that we've completed up to this point in the interactive input and free expired tokens */ -void LexInteractiveClear(struct ParseState *Parser) -{ - while (InteractiveHead != NULL) - { - struct TokenLine *NextLine = InteractiveHead->Next; - - HeapFreeMem(InteractiveHead->Tokens); - HeapFreeMem(InteractiveHead); - InteractiveHead = NextLine; - } - - if (Parser != NULL) - Parser->Pos = NULL; - InteractiveTail = NULL; -} - -/* indicate that we've completed up to this point in the interactive input and free expired tokens */ -void LexInteractiveCompleted(struct ParseState *Parser) -{ - while (InteractiveHead != NULL && !(Parser->Pos >= &InteractiveHead->Tokens[0] && Parser->Pos < &InteractiveHead->Tokens[InteractiveHead->NumBytes])) - { - /* this token line is no longer needed - free it */ - struct TokenLine *NextLine = InteractiveHead->Next; - - HeapFreeMem(InteractiveHead->Tokens); - HeapFreeMem(InteractiveHead); - InteractiveHead = NextLine; - - if (InteractiveHead == NULL) - { - /* we've emptied the list */ - Parser->Pos = NULL; - InteractiveTail = NULL; - } - } -} - -/* the next time we prompt, make it the full statement prompt */ -void LexInteractiveStatementPrompt() -{ - LexUseStatementPrompt = TRUE; -} diff --git a/ecilib/parse.c b/ecilib/parse.c deleted file mode 100644 index f18b62d..0000000 --- a/ecilib/parse.c +++ /dev/null @@ -1,872 +0,0 @@ -#include "picoc.h" -#include "interpreter.h" - -/* a chunk of heap-allocated tokens we'll cleanup when we're done */ -struct CleanupTokenNode -{ - void *Tokens; - const char *SourceText; - struct CleanupTokenNode *Next; -}; - -static struct CleanupTokenNode *CleanupTokenList = NULL; - - -/* deallocate any memory */ -void ParseCleanup() -{ - while (CleanupTokenList != NULL) - { - struct CleanupTokenNode *Next = CleanupTokenList->Next; - - HeapFreeMem(CleanupTokenList->Tokens); - if (CleanupTokenList->SourceText != NULL) - HeapFreeMem((void *)CleanupTokenList->SourceText); - - HeapFreeMem(CleanupTokenList); - CleanupTokenList = Next; - } -} - -/* parse a statement, but only run it if Condition is TRUE */ -enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser, int Condition, int CheckTrailingSemicolon) -{ - if (Parser->Mode != RunModeSkip && !Condition) - { - enum RunMode OldMode = Parser->Mode; - int Result; - Parser->Mode = RunModeSkip; - Result = ParseStatement(Parser, CheckTrailingSemicolon); - Parser->Mode = OldMode; - return Result; - } - else - return ParseStatement(Parser, CheckTrailingSemicolon); -} - -/* count the number of parameters to a function or macro */ -int ParseCountParams(struct ParseState *Parser) -{ - int ParamCount = 0; - - enum LexToken Token = LexGetToken(Parser, NULL, TRUE); - if (Token != TokenCloseBracket && Token != TokenEOF) - { - /* count the number of parameters */ - ParamCount++; - while ((Token = LexGetToken(Parser, NULL, TRUE)) != TokenCloseBracket && Token != TokenEOF) - { - if (Token == TokenComma) - ParamCount++; - } - } - - return ParamCount; -} - -/* parse a function definition and store it for later */ -struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier) -{ - struct ValueType *ParamType; - char *ParamIdentifier; - enum LexToken Token = TokenNone; - struct ParseState ParamParser; - struct Value *FuncValue; - struct Value *OldFuncValue; - struct ParseState FuncBody; - int ParamCount = 0; - - if (TopStackFrame != NULL) - ProgramFail(Parser, "nested function definitions are not allowed"); - - LexGetToken(Parser, NULL, TRUE); /* open bracket */ - ParserCopy(&ParamParser, Parser); - ParamCount = ParseCountParams(Parser); - if (ParamCount > PARAMETER_MAX) - ProgramFail(Parser, "too many parameters"); - - FuncValue = VariableAllocValueAndData(Parser, sizeof(struct FuncDef) + sizeof(struct ValueType *) * ParamCount + sizeof(const char *) * ParamCount, FALSE, NULL, TRUE); - FuncValue->Typ = &FunctionType; - FuncValue->Val->FuncDef.ReturnType = ReturnType; - FuncValue->Val->FuncDef.NumParams = ParamCount; - FuncValue->Val->FuncDef.VarArgs = FALSE; - FuncValue->Val->FuncDef.ParamType = (struct ValueType **)((char *)FuncValue->Val + sizeof(struct FuncDef)); - FuncValue->Val->FuncDef.ParamName = (char **)((char *)FuncValue->Val->FuncDef.ParamType + sizeof(struct ValueType *) * ParamCount); - - for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) - { - /* harvest the parameters into the function definition */ - if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, FALSE) == TokenEllipsis) - { - /* ellipsis at end */ - FuncValue->Val->FuncDef.NumParams--; - FuncValue->Val->FuncDef.VarArgs = TRUE; - break; - } - else - { - /* add a parameter */ - TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL); - if (ParamType->Base == TypeVoid) - { - /* this isn't a real parameter at all - delete it */ - ParamCount--; - FuncValue->Val->FuncDef.NumParams--; - } - else - { - FuncValue->Val->FuncDef.ParamType[ParamCount] = ParamType; - FuncValue->Val->FuncDef.ParamName[ParamCount] = ParamIdentifier; - } - } - - Token = LexGetToken(&ParamParser, NULL, TRUE); - if (Token != TokenComma && ParamCount < FuncValue->Val->FuncDef.NumParams-1) - ProgramFail(&ParamParser, "comma expected"); - } - - if (FuncValue->Val->FuncDef.NumParams != 0 && Token != TokenCloseBracket && Token != TokenComma && Token != TokenEllipsis) - ProgramFail(&ParamParser, "bad parameter"); - - if (strcmp(Identifier, "main") == 0) - { - /* make sure it's int main() */ - if ( FuncValue->Val->FuncDef.ReturnType != &IntType && - FuncValue->Val->FuncDef.ReturnType != &VoidType ) - ProgramFail(Parser, "main() should return an int or void"); - - if (FuncValue->Val->FuncDef.NumParams != 0 && - (FuncValue->Val->FuncDef.NumParams != 2 || FuncValue->Val->FuncDef.ParamType[0] != &IntType) ) - ProgramFail(Parser, "bad parameters to main()"); - } - - /* look for a function body */ - Token = LexGetToken(Parser, NULL, FALSE); - if (Token == TokenSemicolon) - LexGetToken(Parser, NULL, TRUE); /* it's a prototype, absorb the trailing semicolon */ - else - { - /* it's a full function definition with a body */ - if (Token != TokenLeftBrace) - ProgramFail(Parser, "bad function definition"); - - ParserCopy(&FuncBody, Parser); - if (ParseStatementMaybeRun(Parser, FALSE, TRUE) != ParseResultOk) - ProgramFail(Parser, "function definition expected"); - - FuncValue->Val->FuncDef.Body = FuncBody; - FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser); - - /* is this function already in the global table? */ - if (TableGet(&GlobalTable, Identifier, &OldFuncValue, NULL, NULL, NULL)) - { - if (OldFuncValue->Val->FuncDef.Body.Pos == NULL) - { - /* override an old function prototype */ - VariableFree(TableDelete(&GlobalTable, Identifier)); - } - else - ProgramFail(Parser, "'%s' is already defined", Identifier); - } - } - - if (!TableSet(&GlobalTable, Identifier, FuncValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) - ProgramFail(Parser, "'%s' is already defined", Identifier); - - return FuncValue; -} - -/* assign an initial value to a variable */ -void ParseDeclarationAssignment(struct ParseState *Parser, struct Value *NewVariable, int DoAssignment) -{ - struct Value *CValue; - int ArrayIndex; - enum LexToken Token = TokenComma; - - if (LexGetToken(Parser, NULL, FALSE) == TokenLeftBrace) - { - /* this is an array initialiser */ - LexGetToken(Parser, NULL, TRUE); - - for (ArrayIndex = 0; (Parser->Mode != RunModeRun && Token == TokenComma) || (Parser->Mode == RunModeRun && ArrayIndex < NewVariable->Typ->ArraySize); ArrayIndex++) - { - struct Value *ArrayElement = NULL; - - if (Token != TokenComma) - ProgramFail(Parser, "comma expected"); - - if (Parser->Mode == RunModeRun) - ArrayElement = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + TypeSize(NewVariable->Typ->FromType, 0, TRUE) * ArrayIndex), TRUE, NewVariable); - - if (!ExpressionParse(Parser, &CValue)) - ProgramFail(Parser, "expression expected"); - - if (Parser->Mode == RunModeRun && DoAssignment) - { - ExpressionAssign(Parser, ArrayElement, CValue, FALSE, NULL, 0, FALSE); - VariableStackPop(Parser, CValue); - VariableStackPop(Parser, ArrayElement); - } - - Token = LexGetToken(Parser, NULL, TRUE); - } - - if (Token == TokenComma) - Token = LexGetToken(Parser, NULL, TRUE); - - if (Token != TokenRightBrace) - ProgramFail(Parser, "'}' expected"); - } - else - { - /* this is a normal expression initialiser */ - if (!ExpressionParse(Parser, &CValue)) - ProgramFail(Parser, "expression expected"); - - if (Parser->Mode == RunModeRun && DoAssignment) - { - ExpressionAssign(Parser, NewVariable, CValue, FALSE, NULL, 0, FALSE); - VariableStackPop(Parser, CValue); - } - } -} - -/* declare a variable or function */ -int ParseDeclaration(struct ParseState *Parser, enum LexToken Token) -{ - char *Identifier; - struct ValueType *BasicType; - struct ValueType *Typ; - struct Value *NewVariable = NULL; - int IsStatic = FALSE; - int FirstVisit = FALSE; - - TypeParseFront(Parser, &BasicType, &IsStatic); - do - { - TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); - if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType && Token != TokenEnumType) && Identifier == StrEmpty) - ProgramFail(Parser, "identifier expected"); - - if (Identifier != StrEmpty) - { - /* handle function definitions */ - if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) - { - ParseFunctionDefinition(Parser, Typ, Identifier); - return FALSE; - } - else - { - if (Typ == &VoidType && Identifier != StrEmpty) - ProgramFail(Parser, "can't define a void variable"); - - if (Parser->Mode == RunModeRun || Parser->Mode == RunModeGoto) - NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ, IsStatic, &FirstVisit); - - if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) - { - /* we're assigning an initial value */ - LexGetToken(Parser, NULL, TRUE); - ParseDeclarationAssignment(Parser, NewVariable, !IsStatic || FirstVisit); - } - } - } - - Token = LexGetToken(Parser, NULL, FALSE); - if (Token == TokenComma) - LexGetToken(Parser, NULL, TRUE); - - } while (Token == TokenComma); - - return TRUE; -} - -/* parse a #define macro definition and store it for later */ -void ParseMacroDefinition(struct ParseState *Parser) -{ - struct Value *MacroName; - char *MacroNameStr; - struct Value *ParamName; - struct Value *MacroValue; - - if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier) - ProgramFail(Parser, "identifier expected"); - - MacroNameStr = MacroName->Val->Identifier; - - if (LexRawPeekToken(Parser) == TokenOpenMacroBracket) - { - /* it's a parameterised macro, read the parameters */ - enum LexToken Token = LexGetToken(Parser, NULL, TRUE); - struct ParseState ParamParser; - int NumParams; - int ParamCount = 0; - - ParserCopy(&ParamParser, Parser); - NumParams = ParseCountParams(&ParamParser); - MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE); - MacroValue->Val->MacroDef.NumParams = NumParams; - MacroValue->Val->MacroDef.ParamName = (char **)((char *)MacroValue->Val + sizeof(struct MacroDef)); - - Token = LexGetToken(Parser, &ParamName, TRUE); - - while (Token == TokenIdentifier) - { - /* store a parameter name */ - MacroValue->Val->MacroDef.ParamName[ParamCount++] = ParamName->Val->Identifier; - - /* get the trailing comma */ - Token = LexGetToken(Parser, NULL, TRUE); - if (Token == TokenComma) - Token = LexGetToken(Parser, &ParamName, TRUE); - - else if (Token != TokenCloseBracket) - ProgramFail(Parser, "comma expected"); - } - - if (Token != TokenCloseBracket) - ProgramFail(Parser, "close bracket expected"); - } - else - { - /* allocate a simple unparameterised macro */ - MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef), FALSE, NULL, TRUE); - MacroValue->Val->MacroDef.NumParams = 0; - } - - /* copy the body of the macro to execute later */ - ParserCopy(&MacroValue->Val->MacroDef.Body, Parser); - MacroValue->Typ = &MacroType; - LexToEndOfLine(Parser); - MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser); - - if (!TableSet(&GlobalTable, MacroNameStr, MacroValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos)) - ProgramFail(Parser, "'%s' is already defined", MacroNameStr); -} - -/* copy the entire parser state */ -void ParserCopy(struct ParseState *To, struct ParseState *From) -{ - memcpy((void *)To, (void *)From, sizeof(*To)); -} - -/* copy where we're at in the parsing */ -void ParserCopyPos(struct ParseState *To, struct ParseState *From) -{ - To->Pos = From->Pos; - To->Line = From->Line; - To->HashIfLevel = From->HashIfLevel; - To->HashIfEvaluateToLevel = From->HashIfEvaluateToLevel; - To->CharacterPos = From->CharacterPos; -} - -/* parse a "for" statement */ -void ParseFor(struct ParseState *Parser) -{ - int Condition; - struct ParseState PreConditional; - struct ParseState PreIncrement; - struct ParseState PreStatement; - struct ParseState After; - - if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) - ProgramFail(Parser, "'(' expected"); - - if (ParseStatement(Parser, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - - ParserCopyPos(&PreConditional, Parser); - if (LexGetToken(Parser, NULL, FALSE) == TokenSemicolon) - Condition = TRUE; - else - Condition = ExpressionParseInt(Parser); - - if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) - ProgramFail(Parser, "';' expected"); - - ParserCopyPos(&PreIncrement, Parser); - ParseStatementMaybeRun(Parser, FALSE, FALSE); - - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - - ParserCopyPos(&PreStatement, Parser); - if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - - if (Parser->Mode == RunModeContinue) - Parser->Mode = RunModeRun; - - ParserCopyPos(&After, Parser); - - while (Condition && Parser->Mode == RunModeRun) - { - ParserCopyPos(Parser, &PreIncrement); - ParseStatement(Parser, FALSE); - - ParserCopyPos(Parser, &PreConditional); - if (LexGetToken(Parser, NULL, FALSE) == TokenSemicolon) - Condition = TRUE; - else - Condition = ExpressionParseInt(Parser); - - if (Condition) - { - ParserCopyPos(Parser, &PreStatement); - ParseStatement(Parser, TRUE); - - if (Parser->Mode == RunModeContinue) - Parser->Mode = RunModeRun; - } - } - - if (Parser->Mode == RunModeBreak) - Parser->Mode = RunModeRun; - - ParserCopyPos(Parser, &After); -} - -/* parse a block of code and return what mode it returned in */ -enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition) -{ - if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace) - ProgramFail(Parser, "'{' expected"); - - if (Parser->Mode == RunModeSkip || !Condition) - { - /* condition failed - skip this block instead */ - enum RunMode OldMode = Parser->Mode; - Parser->Mode = RunModeSkip; - while (ParseStatement(Parser, TRUE) == ParseResultOk) - {} - Parser->Mode = OldMode; - } - else - { - /* just run it in its current mode */ - while (ParseStatement(Parser, TRUE) == ParseResultOk) - {} - } - - if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace) - ProgramFail(Parser, "'}' expected"); - - return Parser->Mode; -} - -/* parse a typedef declaration */ -void ParseTypedef(struct ParseState *Parser) -{ - struct ValueType *Typ; - struct ValueType **TypPtr; - char *TypeName; - struct Value InitValue; - - TypeParse(Parser, &Typ, &TypeName, NULL); - - if (Parser->Mode == RunModeRun) - { - TypPtr = &Typ; - InitValue.Typ = &TypeType; - InitValue.Val = (union AnyValue *)TypPtr; - VariableDefine(Parser, TypeName, &InitValue, NULL, FALSE); - } -} - -/* parse a statement */ -enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon) -{ - struct Value *CValue; - struct Value *LexerValue; - struct Value *VarValue; - int Condition; - struct ParseState PreState; - enum LexToken Token; - - ParserCopy(&PreState, Parser); - Token = LexGetToken(Parser, &LexerValue, TRUE); - - switch (Token) - { - case TokenEOF: - return ParseResultEOF; - - case TokenIdentifier: - /* might be a typedef-typed variable declaration or it might be an expression */ - if (VariableDefined(LexerValue->Val->Identifier)) - { - VariableGet(Parser, LexerValue->Val->Identifier, &VarValue); - if (VarValue->Typ->Base == Type_Type) - { - *Parser = PreState; - ParseDeclaration(Parser, Token); - break; - } - } - else - { - /* it might be a goto label */ - enum LexToken NextToken = LexGetToken(Parser, NULL, FALSE); - if (NextToken == TokenColon) - { - /* declare the identifier as a goto label */ - LexGetToken(Parser, NULL, TRUE); - if (Parser->Mode == RunModeGoto && LexerValue->Val->Identifier == Parser->SearchGotoLabel) - Parser->Mode = RunModeRun; - - CheckTrailingSemicolon = FALSE; - break; - } - } - /* else fallthrough to expression */ - - case TokenAsterisk: - case TokenAmpersand: - case TokenIncrement: - case TokenDecrement: - case TokenOpenBracket: - *Parser = PreState; - ExpressionParse(Parser, &CValue); - if (Parser->Mode == RunModeRun) - VariableStackPop(Parser, CValue); - break; - - case TokenLeftBrace: - ParseBlock(Parser, FALSE, TRUE); - CheckTrailingSemicolon = FALSE; - break; - - case TokenIf: - if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) - ProgramFail(Parser, "'(' expected"); - - Condition = ExpressionParseInt(Parser); - - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - - if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - - if (LexGetToken(Parser, NULL, FALSE) == TokenElse) - { - LexGetToken(Parser, NULL, TRUE); - if (ParseStatementMaybeRun(Parser, !Condition, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - } - CheckTrailingSemicolon = FALSE; - break; - - case TokenWhile: - { - struct ParseState PreConditional; - enum RunMode PreMode = Parser->Mode; - - if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) - ProgramFail(Parser, "'(' expected"); - - ParserCopyPos(&PreConditional, Parser); - do - { - ParserCopyPos(Parser, &PreConditional); - Condition = ExpressionParseInt(Parser); - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - - if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - - if (Parser->Mode == RunModeContinue) - Parser->Mode = PreMode; - - } while (Parser->Mode == RunModeRun && Condition); - - if (Parser->Mode == RunModeBreak) - Parser->Mode = PreMode; - - CheckTrailingSemicolon = FALSE; - } - break; - - case TokenDo: - { - struct ParseState PreStatement; - enum RunMode PreMode = Parser->Mode; - ParserCopyPos(&PreStatement, Parser); - do - { - ParserCopyPos(Parser, &PreStatement); - if (ParseStatement(Parser, TRUE) != ParseResultOk) - ProgramFail(Parser, "statement expected"); - - if (Parser->Mode == RunModeContinue) - Parser->Mode = PreMode; - - if (LexGetToken(Parser, NULL, TRUE) != TokenWhile) - ProgramFail(Parser, "'while' expected"); - - if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) - ProgramFail(Parser, "'(' expected"); - - Condition = ExpressionParseInt(Parser); - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - - } while (Condition && Parser->Mode == RunModeRun); - - if (Parser->Mode == RunModeBreak) - Parser->Mode = PreMode; - } - break; - - case TokenFor: - ParseFor(Parser); - CheckTrailingSemicolon = FALSE; - break; - - case TokenSemicolon: - CheckTrailingSemicolon = FALSE; - break; - - case TokenIntType: - case TokenShortType: - case TokenCharType: - case TokenLongType: - case TokenFloatType: - case TokenDoubleType: - case TokenVoidType: - case TokenStructType: - case TokenUnionType: - case TokenEnumType: - case TokenSignedType: - case TokenUnsignedType: - case TokenStaticType: - case TokenAutoType: - case TokenRegisterType: - case TokenExternType: - *Parser = PreState; - CheckTrailingSemicolon = ParseDeclaration(Parser, Token); - break; - - case TokenHashDefine: - ParseMacroDefinition(Parser); - CheckTrailingSemicolon = FALSE; - break; - -#ifndef NO_HASH_INCLUDE - case TokenHashInclude: - if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant) - ProgramFail(Parser, "\"filename.h\" expected"); - - IncludeFile((char *)LexerValue->Val->Pointer); - CheckTrailingSemicolon = FALSE; - break; -#endif - - case TokenSwitch: - if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) - ProgramFail(Parser, "'(' expected"); - - Condition = ExpressionParseInt(Parser); - - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - - if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace) - ProgramFail(Parser, "'{' expected"); - - { - /* new block so we can store parser state */ - enum RunMode OldMode = Parser->Mode; - int OldSearchLabel = Parser->SearchLabel; - Parser->Mode = RunModeCaseSearch; - Parser->SearchLabel = Condition; - - ParseBlock(Parser, TRUE, OldMode != RunModeSkip); - - if (Parser->Mode != RunModeReturn) - Parser->Mode = OldMode; - - Parser->SearchLabel = OldSearchLabel; - } - - CheckTrailingSemicolon = FALSE; - break; - - case TokenCase: - if (Parser->Mode == RunModeCaseSearch) - { - Parser->Mode = RunModeRun; - Condition = ExpressionParseInt(Parser); - Parser->Mode = RunModeCaseSearch; - } - else - Condition = ExpressionParseInt(Parser); - - if (LexGetToken(Parser, NULL, TRUE) != TokenColon) - ProgramFail(Parser, "':' expected"); - - if (Parser->Mode == RunModeCaseSearch && Condition == Parser->SearchLabel) - Parser->Mode = RunModeRun; - - CheckTrailingSemicolon = FALSE; - break; - - case TokenDefault: - if (LexGetToken(Parser, NULL, TRUE) != TokenColon) - ProgramFail(Parser, "':' expected"); - - if (Parser->Mode == RunModeCaseSearch) - Parser->Mode = RunModeRun; - - CheckTrailingSemicolon = FALSE; - break; - - case TokenBreak: - if (Parser->Mode == RunModeRun) - Parser->Mode = RunModeBreak; - break; - - case TokenContinue: - if (Parser->Mode == RunModeRun) - Parser->Mode = RunModeContinue; - break; - - case TokenReturn: - if (Parser->Mode == RunModeRun) - { - if (TopStackFrame->ReturnValue->Typ->Base != TypeVoid) - { - if (!ExpressionParse(Parser, &CValue)) - ProgramFail(Parser, "value required in return"); - - ExpressionAssign(Parser, TopStackFrame->ReturnValue, CValue, TRUE, NULL, 0, FALSE); - VariableStackPop(Parser, CValue); - } - else - { - if (ExpressionParse(Parser, &CValue)) - ProgramFail(Parser, "value in return from a void function"); - } - - Parser->Mode = RunModeReturn; - } - else - ExpressionParse(Parser, &CValue); - break; - - case TokenTypedef: - ParseTypedef(Parser); - break; - - case TokenGoto: - if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) - ProgramFail(Parser, "identifier expected"); - - if (Parser->Mode == RunModeRun) - { - /* start scanning for the goto label */ - Parser->SearchGotoLabel = LexerValue->Val->Identifier; - Parser->Mode = RunModeGoto; - } - break; - - case TokenDelete: - { - /* try it as a function or variable name to delete */ - if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier) - ProgramFail(Parser, "identifier expected"); - - if (Parser->Mode == RunModeRun) - { - /* delete this variable or function */ - CValue = TableDelete(&GlobalTable, LexerValue->Val->Identifier); - - if (CValue == NULL) - ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier); - - VariableFree(CValue); - } - break; - } - - default: - *Parser = PreState; - return ParseResultError; - } - - if (CheckTrailingSemicolon) - { - if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) - ProgramFail(Parser, "';' expected"); - } - - return ParseResultOk; -} - -/* quick scan a source file for definitions */ -void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource) -{ - struct ParseState Parser; - enum ParseResult Ok; - struct CleanupTokenNode *NewCleanupNode; - - void *Tokens = LexAnalyse(FileName, Source, SourceLen, NULL); - - /* allocate a cleanup node so we can clean up the tokens later */ - if (!CleanupNow) - { - NewCleanupNode = HeapAllocMem(sizeof(struct CleanupTokenNode)); - if (NewCleanupNode == NULL) - ProgramFail(NULL, "out of memory"); - - NewCleanupNode->Tokens = Tokens; - if (CleanupSource) - NewCleanupNode->SourceText = Source; - else - NewCleanupNode->SourceText = NULL; - - NewCleanupNode->Next = CleanupTokenList; - CleanupTokenList = NewCleanupNode; - } - - /* do the parsing */ - LexInitParser(&Parser, Source, Tokens, FileName, RunIt); - - do { - Ok = ParseStatement(&Parser, TRUE); - } while (Ok == ParseResultOk); - - if (Ok == ParseResultError) - ProgramFail(&Parser, "parse error"); - - /* clean up */ - if (CleanupNow) - HeapFreeMem(Tokens); -} - -/* parse interactively */ -void PicocParseInteractive() -{ - struct ParseState Parser; - enum ParseResult Ok; - - PlatformPrintf(INTERACTIVE_PROMPT_START); - LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE); - PicocPlatformSetExitPoint(); - LexInteractiveClear(&Parser); - - do - { - LexInteractiveStatementPrompt(); - Ok = ParseStatement(&Parser, TRUE); - LexInteractiveCompleted(&Parser); - - } while (Ok == ParseResultOk); - - if (Ok == ParseResultError) - ProgramFail(&Parser, "parse error"); - - PlatformPrintf("\n"); -} diff --git a/ecilib/picoc.c b/ecilib/picoc.c deleted file mode 100644 index ac21130..0000000 --- a/ecilib/picoc.c +++ /dev/null @@ -1,101 +0,0 @@ -/* include only picoc.h here - should be able to use it with only the external interfaces, no internals from interpreter.h */ -#include "picoc.h" - -/* platform-dependent code for running programs is in this file */ - -#ifdef UNIX_HOST -#include -#include -#include - -#define PICOC_STACK_SIZE (128*1024) /* space for the the stack */ - -int main(int argc, char **argv) -{ - int ParamCount = 1; - int DontRunMain = FALSE; - int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE; - - if (argc < 2) - { - printf("Format: picoc ... [- ...] : run a program (calls main() to start it)\n" - " picoc -s ... [- ...] : script mode - runs the program without calling main()\n" - " picoc -i : interactive mode\n"); - exit(1); - } - - PicocInitialise(StackSize); - - if (strcmp(argv[ParamCount], "-s") == 0 || strcmp(argv[ParamCount], "-m") == 0) - { - DontRunMain = TRUE; - PicocIncludeAllSystemHeaders(); - ParamCount++; - } - - if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0) - { - PicocIncludeAllSystemHeaders(); - PicocParseInteractive(); - } - else - { - if (PicocPlatformSetExitPoint()) - { - PicocCleanup(); - return PicocExitValue; - } - - for (; ParamCount < argc && strcmp(argv[ParamCount], "-") != 0; ParamCount++) - PicocPlatformScanFile(argv[ParamCount]); - - if (!DontRunMain) - PicocCallMain(argc - ParamCount, &argv[ParamCount]); - } - - PicocCleanup(); - return PicocExitValue; -} -#else -# ifdef SURVEYOR_HOST -# define HEAP_SIZE C_HEAPSIZE -# include -# include "../srv.h" -# include "../print.h" -# include "../string.h" - -int picoc(char *SourceStr) -{ - char *pos; - - PicocInitialise(HEAP_SIZE); - - if (SourceStr) - { - for (pos = SourceStr; *pos != 0; pos++) - { - if (*pos == 0x1a) - { - *pos = 0x20; - } - } - } - - PicocExitBuf[40] = 0; - setjmp(PicocExitBuf); - if (PicocExitBuf[40]) { - printf("Leaving PicoC\n\r"); - PicocCleanup(); - return PicocExitValue; - } - - if (SourceStr) - PicocParse("nofile", SourceStr, strlen(SourceStr), TRUE, TRUE, FALSE); - - PicocParseInteractive(); - PicocCleanup(); - - return PicocExitValue; -} -# endif -#endif diff --git a/ecilib/platform.c b/ecilib/platform.c deleted file mode 100644 index 2ca0ed6..0000000 --- a/ecilib/platform.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "picoc.h" -#include "interpreter.h" - -/* the value passed to exit() */ -int PicocExitValue = 0; - -/* initialise everything */ -void PicocInitialise(int StackSize) -{ - BasicIOInit(); - HeapInit(StackSize); - TableInit(); - VariableInit(); - LexInit(); - TypeInit(); -#ifndef NO_HASH_INCLUDE - IncludeInit(); -#endif - LibraryInit(); -#ifdef BUILTIN_MINI_STDLIB - LibraryAdd(&GlobalTable, "c library", &CLibrary[0]); - CLibraryInit(); -#endif - PlatformLibraryInit(); -} - -/* free memory */ -void PicocCleanup() -{ - PlatformCleanup(); -#ifndef NO_HASH_INCLUDE - IncludeCleanup(); -#endif - ParseCleanup(); - LexCleanup(); - VariableCleanup(); - TypeCleanup(); - TableStrFree(); - HeapCleanup(); -} - -/* platform-dependent code for running programs */ -#ifdef UNIX_HOST - -#define CALL_MAIN_NO_ARGS_RETURN_VOID "main();" -#define CALL_MAIN_WITH_ARGS_RETURN_VOID "main(__argc,__argv);" -#define CALL_MAIN_NO_ARGS_RETURN_INT "__exit_value = main();" -#define CALL_MAIN_WITH_ARGS_RETURN_INT "__exit_value = main(__argc,__argv);" - -void PicocCallMain(int argc, char **argv) -{ - /* check if the program wants arguments */ - struct Value *FuncValue = NULL; - - if (!VariableDefined(TableStrRegister("main"))) - ProgramFail(NULL, "main() is not defined"); - - VariableGet(NULL, TableStrRegister("main"), &FuncValue); - if (FuncValue->Typ->Base != TypeFunction) - ProgramFail(NULL, "main is not a function - can't call it"); - - if (FuncValue->Val->FuncDef.NumParams != 0) - { - /* define the arguments */ - VariableDefinePlatformVar(NULL, "__argc", &IntType, (union AnyValue *)&argc, FALSE); - VariableDefinePlatformVar(NULL, "__argv", CharPtrPtrType, (union AnyValue *)&argv, FALSE); - } - - if (FuncValue->Val->FuncDef.ReturnType == &VoidType) - { - if (FuncValue->Val->FuncDef.NumParams == 0) - PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); - else - PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); - } - else - { - VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE); - - if (FuncValue->Val->FuncDef.NumParams == 0) - PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE); - else - PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE); - } -} -#endif - -void PrintSourceTextErrorLine(const char *FileName, const char *SourceText, int Line, int CharacterPos) -{ - int LineCount; - const char *LinePos; - const char *CPos; - int CCount; - - if (SourceText != NULL) - { - /* find the source line */ - for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++) - { - if (*LinePos == '\n') - LineCount++; - } - - /* display the line */ - for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++) - PrintCh(*CPos, CStdOut); - PrintCh('\n', CStdOut); - - /* display the error position */ - for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) - { - if (*CPos == '\t') - PrintCh('\t', CStdOut); - else - PrintCh(' ', CStdOut); - } - } - else - { - /* assume we're in interactive mode - try to make the arrow match up with the input text */ - for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++) - PrintCh(' ', CStdOut); - } - PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos); - -} - -/* display the source line and line number to identify an error */ -void PlatformErrorPrefix(struct ParseState *Parser) -{ - if (Parser != NULL) - PrintSourceTextErrorLine(Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); -} - -/* exit with a message */ -void ProgramFail(struct ParseState *Parser, const char *Message, ...) -{ - va_list Args; - - PlatformErrorPrefix(Parser); - va_start(Args, Message); - PlatformVPrintf(Message, Args); - va_end(Args); - PlatformPrintf("\n"); - PlatformExit(1); -} - -/* like ProgramFail() but gives descriptive error messages for assignment */ -void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo) -{ - PlatformErrorPrefix(Parser); - PlatformPrintf("can't %s ", (FuncName == NULL) ? "assign" : "set"); - - if (Type1 != NULL) - PlatformPrintf(Format, Type1, Type2); - else - PlatformPrintf(Format, Num1, Num2); - - if (FuncName != NULL) - PlatformPrintf(" in argument %d of call to %s()", ParamNo, FuncName); - - ProgramFail(NULL, ""); -} - -/* exit lexing with a message */ -void LexFail(struct LexState *Lexer, const char *Message, ...) -{ - va_list Args; - - PrintSourceTextErrorLine(Lexer->FileName, Lexer->SourceText, Lexer->Line, Lexer->CharacterPos); - va_start(Args, Message); - PlatformVPrintf(Message, Args); - va_end(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 *), CStdOut); break; - case 'd': PrintSimpleInt(va_arg(Args, int), CStdOut); break; - case 'c': PrintCh(va_arg(Args, int), CStdOut); break; - case 't': PrintType(va_arg(Args, struct ValueType *), CStdOut); break; -#ifndef NO_FP - case 'f': PrintFP(va_arg(Args, double), CStdOut); break; -#endif - case '%': PrintCh('%', CStdOut); break; - case '\0': FPos--; break; - } - } - else - PrintCh(*FPos, CStdOut); - } -} - -/* make a new temporary name. takes a static buffer of char [7] as a parameter. should be initialised to "XX0000" - * where XX can be any characters */ -char *PlatformMakeTempName(char *TempNameBuffer) -{ - int CPos = 5; - - while (CPos > 1) - { - if (TempNameBuffer[CPos] < '9') - { - TempNameBuffer[CPos]++; - return TableStrRegister(TempNameBuffer); - } - else - { - TempNameBuffer[CPos] = '0'; - CPos--; - } - } - - return TableStrRegister(TempNameBuffer); -} diff --git a/ecilib/platform.h b/ecilib/platform.h deleted file mode 100644 index d4150d0..0000000 --- a/ecilib/platform.h +++ /dev/null @@ -1,125 +0,0 @@ -/* all platform-specific includes and defines go in this file */ -#ifndef PLATFORM_H -#define PLATFORM_H - -/* configurable options */ -/* select your host type (or do it in the Makefile): - * #define UNIX_HOST - * #define FLYINGFOX_HOST - * #define SURVEYOR_HOST - * #define SRV1_UNIX_HOST - * #define UMON_HOST - */ - -#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */ -#if defined(__hppa__) || defined(__sparc__) -#define ALIGN_TYPE double /* the default data type to use for alignment */ -#else -#define ALIGN_TYPE void * /* the default data type to use for alignment */ -#endif - -#define GLOBAL_TABLE_SIZE 97 /* global variable table */ -#define STRING_TABLE_SIZE 97 /* shared string table size */ -#define STRING_LITERAL_TABLE_SIZE 97 /* string literal 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) */ - -#define INTERACTIVE_PROMPT_START "starting picoc " PICOC_VERSION "\n" -#define INTERACTIVE_PROMPT_STATEMENT "picoc> " -#define INTERACTIVE_PROMPT_LINE " > " - -/* host platform includes */ -#ifdef UNIX_HOST -# define USE_MALLOC_STACK /* stack is allocated using malloc() */ -# define USE_MALLOC_HEAP /* heap is allocated using malloc() */ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# ifndef NO_FP -# include -# define PICOC_MATH_LIBRARY -/*# define USE_READLINE*/ -# undef BIG_ENDIAN -# if defined(__powerpc__) || defined(__hppa__) || defined(__sparc__) -# define BIG_ENDIAN -# endif -# endif - -extern jmp_buf ExitBuf; - -#else -# ifdef FLYINGFOX_HOST -# define HEAP_SIZE (16*1024) /* space for the heap and the stack */ -# define NO_HASH_INCLUDE -# include -# include -# include -# include -# include -# include -# include -# define assert(x) -# define BUILTIN_MINI_STDLIB -# undef BIG_ENDIAN - -# else -# ifdef SURVEYOR_HOST -# define HEAP_SIZE C_HEAPSIZE -# define NO_FP -# define NO_CTYPE -# define NO_HASH_INCLUDE -# define NO_MODULUS -# include -# include "../string.h" -# include "../print.h" -# include "../srv.h" -# include "../setjmp.h" -# include "../stdarg.h" -# include "../colors.h" -# include "../neural.h" -# include "../gps.h" -# include "../i2c.h" -# include "../jpeg.h" -# include "../malloc.h" -# include "../xmodem.h" -# define assert(x) -# undef BIG_ENDIAN -# define NO_CALLOC -# define NO_REALLOC -# define BROKEN_FLOAT_CASTS -# define BUILTIN_MINI_STDLIB -# else -# ifdef UMON_HOST -# define HEAP_SIZE (128*1024) /* space for the heap and the stack */ -# define NO_FP -# define BUILTIN_MINI_STDLIB -# include -# include -# include -# include -# include -# include -# include "monlib.h" -# define assert(x) -# define malloc mon_malloc -# define calloc(a,b) mon_malloc(a*b) -# define realloc mon_realloc -# define free mon_free -# endif -# endif - -extern int ExitBuf[]; - -# endif -#endif - -#endif /* PLATFORM_H */ diff --git a/ecilib/platform/library_unix.c b/ecilib/platform/library_unix.c deleted file mode 100644 index 0308702..0000000 --- a/ecilib/platform/library_unix.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "../interpreter.h" - -void UnixSetupFunc() -{ -} - -void Ctest (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - printf("test(%d)\n", Param[0]->Val->Integer); - Param[0]->Val->Integer = 1234; -} - -void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) -{ - ReturnValue->Val->Integer = Parser->Line; -} - -/* list of all library functions and their prototypes */ -struct LibraryFunction UnixFunctions[] = -{ - { Ctest, "void test(int);" }, - { Clineno, "int lineno();" }, - { NULL, NULL } -}; - -void PlatformLibraryInit() -{ - IncludeRegister("picoc_unix.h", &UnixSetupFunc, &UnixFunctions[0], NULL); -} diff --git a/ecilib/platform/platform_unix.c b/ecilib/platform/platform_unix.c deleted file mode 100644 index b0f4614..0000000 --- a/ecilib/platform/platform_unix.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "../picoc.h" -#include "../interpreter.h" - -#ifdef USE_READLINE -#include -#include -#endif - -/* mark where to end the program for platforms which require this */ -jmp_buf PicocExitBuf; - -void PlatformCleanup() -{ -} - -/* get a line of interactive input */ -char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt) -{ -#ifdef USE_READLINE - if (Prompt != NULL) - { - /* use GNU readline to read the line */ - char *InLine = readline(Prompt); - if (InLine == NULL) - return NULL; - - Buf[MaxLen] = '\0'; - strncpy(Buf, InLine, MaxLen-1); - strncat(Buf, "\n", MaxLen-1); - - if (InLine[0] != '\0') - add_history(InLine); - - free(InLine); - return Buf; - } -#endif - - if (Prompt != NULL) - printf("%s", Prompt); - - fflush(stdout); - return fgets(Buf, MaxLen, stdin); -} - -/* get a character of interactive input */ -int PlatformGetCharacter() -{ - fflush(stdout); - return getchar(); -} - -/* write a character to the console */ -void PlatformPutc(unsigned char OutCh, union OutputStreamInfo *Stream) -{ - 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 PicocPlatformScanFile(const char *FileName) -{ - char *SourceStr = PlatformReadFile(FileName); - - PicocParse(FileName, SourceStr, strlen(SourceStr), TRUE, FALSE, TRUE); -} - -/* exit the program */ -void PlatformExit(int RetVal) -{ - PicocExitValue = RetVal; - longjmp(PicocExitBuf, 1); -} - diff --git a/ecilib/table.c b/ecilib/table.c deleted file mode 100644 index 0554ffa..0000000 --- a/ecilib/table.c +++ /dev/null @@ -1,187 +0,0 @@ -#include "interpreter.h" - -struct Table StringTable; -struct TableEntry *StringHashTable[STRING_TABLE_SIZE]; -char *StrEmpty = NULL; - -/* initialise the shared string system */ -void TableInit() -{ - TableInitTable(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE); - StrEmpty = TableStrRegister(""); -} - -/* hash function for strings */ -static unsigned int TableHash(const char *Key, int Len) -{ - unsigned int Hash = Len; - int Offset; - int Count; - - for (Count = 0, Offset = 8; Count < Len; Count++, Offset+=7) - { - if (Offset > sizeof(unsigned int) * 8 - 7) - Offset -= sizeof(unsigned int) * 8 - 6; - - Hash ^= *Key++ << Offset; - } - - return Hash; -} - -/* initialise a table */ -void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap) -{ - Tbl->Size = Size; - Tbl->OnHeap = OnHeap; - Tbl->HashTable = HashTable; - memset((void *)HashTable, '\0', sizeof(struct TableEntry *) * Size); -} - -/* check a hash table entry for a key */ -static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *AddAt) -{ - struct TableEntry *Entry; - int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ - - for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) - { - if (Entry->p.v.Key == Key) - return Entry; /* found */ - } - - *AddAt = HashValue; /* didn't find it in the chain */ - return NULL; -} - -/* set an identifier to a value. returns FALSE if it already exists. - * Key must be a shared string from TableStrRegister() */ -int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn) -{ - int AddAt; - struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); - - if (FoundEntry == NULL) - { /* add it to the table */ - struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap); - NewEntry->DeclFileName = DeclFileName; - NewEntry->DeclLine = DeclLine; - NewEntry->DeclColumn = DeclColumn; - NewEntry->p.v.Key = Key; - NewEntry->p.v.Val = Val; - NewEntry->Next = Tbl->HashTable[AddAt]; - Tbl->HashTable[AddAt] = NewEntry; - return TRUE; - } - - return FALSE; -} - -/* find a value in a table. returns FALSE if not found. - * Key must be a shared string from TableStrRegister() */ -int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn) -{ - int AddAt; - struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt); - if (FoundEntry == NULL) - return FALSE; - - *Val = FoundEntry->p.v.Val; - - if (DeclFileName != NULL) - { - *DeclFileName = FoundEntry->DeclFileName; - *DeclLine = FoundEntry->DeclLine; - *DeclColumn = FoundEntry->DeclColumn; - } - - return TRUE; -} - -/* remove an entry from the table */ -struct Value *TableDelete(struct Table *Tbl, const char *Key) -{ - struct TableEntry **EntryPtr; - int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ - - for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) - { - if ((*EntryPtr)->p.v.Key == Key) - { - struct TableEntry *DeleteEntry = *EntryPtr; - struct Value *Val = DeleteEntry->p.v.Val; - *EntryPtr = DeleteEntry->Next; - HeapFreeMem(DeleteEntry); - - return Val; - } - } - - return NULL; -} - -/* check a hash table entry for an identifier */ -static struct TableEntry *TableSearchIdentifier(struct Table *Tbl, const char *Key, int Len, int *AddAt) -{ - struct TableEntry *Entry; - int HashValue = TableHash(Key, Len) % Tbl->Size; - - for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) - { - if (strncmp(&Entry->p.Key[0], (char *)Key, Len) == 0 && Entry->p.Key[Len] == '\0') - return Entry; /* found */ - } - - *AddAt = HashValue; /* didn't find it in the chain */ - return NULL; -} - -/* set an identifier and return the identifier. share if possible */ -char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen) -{ - int AddAt; - struct TableEntry *FoundEntry = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt); - - if (FoundEntry != NULL) - return &FoundEntry->p.Key[0]; - else - { /* add it to the table - we economise by not allocating the whole structure here */ - struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1); - if (NewEntry == NULL) - ProgramFail(NULL, "out of memory"); - - strncpy((char *)&NewEntry->p.Key[0], (char *)Ident, IdentLen); - NewEntry->p.Key[IdentLen] = '\0'; - NewEntry->Next = Tbl->HashTable[AddAt]; - Tbl->HashTable[AddAt] = NewEntry; - return &NewEntry->p.Key[0]; - } -} - -/* register a string in the shared string store */ -char *TableStrRegister2(const char *Str, int Len) -{ - return TableSetIdentifier(&StringTable, Str, Len); -} - -char *TableStrRegister(const char *Str) -{ - return TableStrRegister2(Str, strlen((char *)Str)); -} - -/* free all the strings */ -void TableStrFree() -{ - struct TableEntry *Entry; - struct TableEntry *NextEntry; - int Count; - - for (Count = 0; Count < StringTable.Size; Count++) - { - for (Entry = StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) - { - NextEntry = Entry->Next; - HeapFreeMem(Entry); - } - } -} diff --git a/ecilib/type.c b/ecilib/type.c deleted file mode 100644 index 33464c5..0000000 --- a/ecilib/type.c +++ /dev/null @@ -1,536 +0,0 @@ -#include "interpreter.h" - -/* some basic types */ -struct ValueType UberType; -struct ValueType IntType; -struct ValueType ShortType; -struct ValueType CharType; -struct ValueType LongType; -struct ValueType UnsignedIntType; -struct ValueType UnsignedShortType; -struct ValueType UnsignedLongType; -#ifndef NO_FP -struct ValueType FPType; -#endif -struct ValueType VoidType; -struct ValueType TypeType; -struct ValueType FunctionType; -struct ValueType MacroType; -struct ValueType EnumType; -struct ValueType GotoLabelType; -struct ValueType *CharPtrType; -struct ValueType *CharPtrPtrType; -struct ValueType *CharArrayType; -struct ValueType *VoidPtrType; - -static int PointerAlignBytes; -static int IntAlignBytes; - - -/* add a new type to the set of types we know about */ -struct ValueType *TypeAdd(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int Sizeof, int AlignBytes) -{ - struct ValueType *NewType = VariableAlloc(Parser, sizeof(struct ValueType), TRUE); - NewType->Base = Base; - NewType->ArraySize = ArraySize; - NewType->Sizeof = Sizeof; - NewType->AlignBytes = AlignBytes; - NewType->Identifier = Identifier; - NewType->Members = NULL; - NewType->FromType = ParentType; - NewType->DerivedTypeList = NULL; - NewType->OnHeap = TRUE; - NewType->Next = ParentType->DerivedTypeList; - ParentType->DerivedTypeList = NewType; - - return NewType; -} - -/* given a parent type, get a matching derived type and make one if necessary. - * Identifier should be registered with the shared string table. */ -struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates) -{ - int Sizeof; - int AlignBytes; - struct ValueType *ThisType = ParentType->DerivedTypeList; - while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || ThisType->Identifier != Identifier)) - ThisType = ThisType->Next; - - if (ThisType != NULL) - { - if (AllowDuplicates) - return ThisType; - else - ProgramFail(Parser, "data type '%s' is already defined", Identifier); - } - - switch (Base) - { - case TypePointer: Sizeof = sizeof(void *); AlignBytes = PointerAlignBytes; break; - case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; AlignBytes = ParentType->AlignBytes; break; - case TypeEnum: Sizeof = sizeof(int); AlignBytes = IntAlignBytes; break; - default: Sizeof = 0; AlignBytes = 0; break; /* structs and unions will get bigger when we add members to them */ - } - - return TypeAdd(Parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes); -} - -/* stack space used by a value */ -int TypeStackSizeValue(struct Value *Val) -{ - if (Val != NULL && Val->ValOnStack) - return TypeSizeValue(Val, FALSE); - else - return 0; -} - -/* memory used by a value */ -int TypeSizeValue(struct Value *Val, int Compact) -{ - if (IS_INTEGER_NUMERIC(Val) && !Compact) - return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */ - else if (Val->Typ->Base != TypeArray) - return Val->Typ->Sizeof; - else - return Val->Typ->FromType->Sizeof * Val->Typ->ArraySize; -} - -/* memory used by a variable given its type and array size */ -int TypeSize(struct ValueType *Typ, int ArraySize, int Compact) -{ - if (IS_INTEGER_NUMERIC_TYPE(Typ) && !Compact) - return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */ - else if (Typ->Base != TypeArray) - return Typ->Sizeof; - else - return Typ->FromType->Sizeof * ArraySize; -} - -/* add a base type */ -void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof, int AlignBytes) -{ - TypeNode->Base = Base; - TypeNode->ArraySize = 0; - TypeNode->Sizeof = Sizeof; - TypeNode->AlignBytes = AlignBytes; - TypeNode->Identifier = StrEmpty; - TypeNode->Members = NULL; - TypeNode->FromType = NULL; - TypeNode->DerivedTypeList = NULL; - TypeNode->OnHeap = FALSE; - TypeNode->Next = UberType.DerivedTypeList; - UberType.DerivedTypeList = TypeNode; -} - -/* initialise the type system */ -void TypeInit() -{ - struct IntAlign { char x; int y; } ia; - struct ShortAlign { char x; short y; } sa; - struct CharAlign { char x; char y; } ca; - struct LongAlign { char x; long y; } la; -#ifndef NO_FP - struct DoubleAlign { char x; double y; } da; -#endif - struct PointerAlign { char x; void *y; } pa; - - IntAlignBytes = (char *)&ia.y - &ia.x; - PointerAlignBytes = (char *)&pa.y - &pa.x; - - UberType.DerivedTypeList = NULL; - TypeAddBaseType(&IntType, TypeInt, sizeof(int), IntAlignBytes); - TypeAddBaseType(&ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x); - TypeAddBaseType(&CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x); - TypeAddBaseType(&LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x); - TypeAddBaseType(&UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes); - TypeAddBaseType(&UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x); - TypeAddBaseType(&UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x); - TypeAddBaseType(&VoidType, TypeVoid, 0, 1); - TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int), IntAlignBytes); - TypeAddBaseType(&MacroType, TypeMacro, sizeof(int), IntAlignBytes); - TypeAddBaseType(&GotoLabelType, TypeGotoLabel, 0, 1); -#ifndef NO_FP - TypeAddBaseType(&FPType, TypeFP, sizeof(double), (char *)&da.y - &da.x); - TypeAddBaseType(&TypeType, Type_Type, sizeof(double), (char *)&da.y - &da.x); /* must be large enough to cast to a double */ -#else - TypeAddBaseType(&TypeType, Type_Type, sizeof(struct ValueType *), PointerAlignBytes); -#endif - CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char), (char *)&ca.y - &ca.x); - CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); - CharPtrPtrType = TypeAdd(NULL, CharPtrType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); - VoidPtrType = TypeAdd(NULL, &VoidType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes); -} - -/* deallocate heap-allocated types */ -void TypeCleanupNode(struct ValueType *Typ) -{ - struct ValueType *SubType; - struct ValueType *NextSubType; - - /* clean up and free all the sub-nodes */ - for (SubType = Typ->DerivedTypeList; SubType != NULL; SubType = NextSubType) - { - NextSubType = SubType->Next; - TypeCleanupNode(SubType); - if (SubType->OnHeap) - { - /* if it's a struct or union deallocate all the member values */ - if (SubType->Members != NULL) - { - VariableTableCleanup(SubType->Members); - HeapFreeMem(SubType->Members); - } - - /* free this node */ - HeapFreeMem(SubType); - } - } -} - -void TypeCleanup() -{ - TypeCleanupNode(&UberType); -} - -/* parse a struct or union declaration */ -void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct) -{ - struct Value *LexValue; - struct ValueType *MemberType; - char *MemberIdentifier; - char *StructIdentifier; - struct Value *MemberValue; - enum LexToken Token; - int AlignBoundary; - - Token = LexGetToken(Parser, &LexValue, FALSE); - if (Token == TokenIdentifier) - { - LexGetToken(Parser, &LexValue, TRUE); - StructIdentifier = LexValue->Val->Identifier; - Token = LexGetToken(Parser, NULL, FALSE); - } - else - { - static char TempNameBuf[7] = "^s0000"; - StructIdentifier = PlatformMakeTempName(TempNameBuf); - } - - *Typ = TypeGetMatching(Parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, Token != TokenLeftBrace); - - Token = LexGetToken(Parser, NULL, FALSE); - if (Token != TokenLeftBrace) - { - /* use the already defined structure */ - if ((*Typ)->Members == NULL) - ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier); - - return; - } - - if (TopStackFrame != NULL) - ProgramFail(Parser, "struct/union definitions can only be globals"); - - LexGetToken(Parser, NULL, TRUE); - (*Typ)->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); - (*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)); - TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); - - do { - TypeParse(Parser, &MemberType, &MemberIdentifier, NULL); - if (MemberType == NULL || MemberIdentifier == NULL) - ProgramFail(Parser, "invalid type in struct"); - - MemberValue = VariableAllocValueAndData(Parser, sizeof(int), FALSE, NULL, TRUE); - MemberValue->Typ = MemberType; - if (IsStruct) - { - /* allocate this member's location in the struct */ - AlignBoundary = MemberValue->Typ->AlignBytes; - if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) - (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); - - MemberValue->Val->Integer = (*Typ)->Sizeof; - (*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE); - } - else - { - /* union members always start at 0, make sure it's big enough to hold the largest member */ - MemberValue->Val->Integer = 0; - if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof) - (*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE); - } - - /* make sure to align to the size of the largest member's alignment */ - if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes) - (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes; - - /* define it */ - if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos)) - ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier); - - if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) - ProgramFail(Parser, "semicolon expected"); - - } while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace); - - /* now align the structure to the size of its largest member's alignment */ - AlignBoundary = (*Typ)->AlignBytes; - if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) - (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); - - LexGetToken(Parser, NULL, TRUE); -} - -/* create a system struct which has no user-visible members */ -struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size) -{ - struct ValueType *Typ = TypeGetMatching(Parser, &UberType, TypeStruct, 0, StructName, FALSE); - - /* create the (empty) table */ - Typ->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); - Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)); - TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); - Typ->Sizeof = Size; - - return Typ; -} - -/* parse an enum declaration */ -void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ) -{ - struct Value *LexValue; - struct Value InitValue; - enum LexToken Token; - struct ValueType *EnumType; - int EnumValue = 0; - char *EnumIdentifier; - - Token = LexGetToken(Parser, &LexValue, FALSE); - if (Token == TokenIdentifier) - { - LexGetToken(Parser, &LexValue, TRUE); - EnumIdentifier = LexValue->Val->Identifier; - Token = LexGetToken(Parser, NULL, FALSE); - } - else - { - static char TempNameBuf[7] = "^e0000"; - EnumIdentifier = PlatformMakeTempName(TempNameBuf); - } - - EnumType = TypeGetMatching(Parser, &UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace); - *Typ = &IntType; - if (Token != TokenLeftBrace) - { - /* use the already defined enum */ - if ((*Typ)->Members == NULL) - ProgramFail(Parser, "enum '%s' isn't defined", EnumIdentifier); - - return; - } - - if (TopStackFrame != NULL) - ProgramFail(Parser, "enum definitions can only be globals"); - - LexGetToken(Parser, NULL, TRUE); - (*Typ)->Members = &GlobalTable; - memset((void *)&InitValue, '\0', sizeof(struct Value)); - InitValue.Typ = &IntType; - InitValue.Val = (union AnyValue *)&EnumValue; - do { - if (LexGetToken(Parser, &LexValue, TRUE) != TokenIdentifier) - ProgramFail(Parser, "identifier expected"); - - EnumIdentifier = LexValue->Val->Identifier; - if (LexGetToken(Parser, NULL, FALSE) == TokenAssign) - { - LexGetToken(Parser, NULL, TRUE); - EnumValue = ExpressionParseInt(Parser); - } - - VariableDefine(Parser, EnumIdentifier, &InitValue, NULL, FALSE); - - Token = LexGetToken(Parser, NULL, TRUE); - if (Token != TokenComma && Token != TokenRightBrace) - ProgramFail(Parser, "comma expected"); - - EnumValue++; - - } while (Token == TokenComma); -} - -/* parse a type - just the basic type */ -int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic) -{ - struct ParseState Before; - struct Value *LexerValue; - enum LexToken Token; - int Unsigned = FALSE; - struct Value *VarValue; - int StaticQualifier = FALSE; - *Typ = NULL; - - /* ignore leading type qualifiers */ - ParserCopy(&Before, Parser); - Token = LexGetToken(Parser, &LexerValue, TRUE); - while (Token == TokenStaticType || Token == TokenAutoType || Token == TokenRegisterType || Token == TokenExternType) - { - if (Token == TokenStaticType) - StaticQualifier = TRUE; - - Token = LexGetToken(Parser, &LexerValue, TRUE); - } - - if (IsStatic != NULL) - *IsStatic = StaticQualifier; - - /* handle signed/unsigned with no trailing type */ - if (Token == TokenSignedType || Token == TokenUnsignedType) - { - enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, FALSE); - Unsigned = (Token == TokenUnsignedType); - - if (FollowToken != TokenIntType && FollowToken != TokenLongType && FollowToken != TokenShortType && FollowToken != TokenCharType) - { - if (Token == TokenUnsignedType) - *Typ = &UnsignedIntType; - else - *Typ = &IntType; - - return TRUE; - } - - Token = LexGetToken(Parser, &LexerValue, TRUE); - } - - switch (Token) - { - case TokenIntType: *Typ = Unsigned ? &UnsignedIntType : &IntType; break; - case TokenShortType: *Typ = Unsigned ? &UnsignedShortType : &ShortType; break; - case TokenCharType: *Typ = &CharType; break; - case TokenLongType: *Typ = Unsigned ? &UnsignedLongType : &LongType; break; -#ifndef NO_FP - case TokenFloatType: case TokenDoubleType: *Typ = &FPType; break; -#endif - case TokenVoidType: *Typ = &VoidType; break; - - case TokenStructType: case TokenUnionType: - if (*Typ != NULL) - ProgramFail(Parser, "bad type declaration"); - - TypeParseStruct(Parser, Typ, Token == TokenStructType); - break; - - case TokenEnumType: - if (*Typ != NULL) - ProgramFail(Parser, "bad type declaration"); - - TypeParseEnum(Parser, Typ); - break; - - case TokenIdentifier: - /* we already know it's a typedef-defined type because we got here */ - VariableGet(Parser, LexerValue->Val->Identifier, &VarValue); - *Typ = VarValue->Val->Typ; - break; - - default: ParserCopy(Parser, &Before); return FALSE; - } - - return TRUE; -} - -/* parse a type - the part at the end after the identifier. eg. array specifications etc. */ -struct ValueType *TypeParseBack(struct ParseState *Parser, struct ValueType *FromType) -{ - enum LexToken Token; - struct ParseState Before; - - ParserCopy(&Before, Parser); - Token = LexGetToken(Parser, NULL, TRUE); - if (Token == TokenLeftSquareBracket) - { - /* add another array bound */ - enum RunMode OldMode = Parser->Mode; - int ArraySize; - Parser->Mode = RunModeRun; - ArraySize = ExpressionParseInt(Parser); - Parser->Mode = OldMode; - - if (LexGetToken(Parser, NULL, TRUE) != TokenRightSquareBracket) - ProgramFail(Parser, "']' expected"); - - return TypeGetMatching(Parser, TypeParseBack(Parser, FromType), TypeArray, ArraySize, StrEmpty, TRUE); - } - else - { - /* the type specification has finished */ - ParserCopy(Parser, &Before); - return FromType; - } -} - -/* parse a type - the part which is repeated with each identifier in a declaration list */ -void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier) -{ - struct ParseState Before; - enum LexToken Token; - struct Value *LexValue; - int Done = FALSE; - *Typ = BasicTyp; - *Identifier = StrEmpty; - - while (!Done) - { - ParserCopy(&Before, Parser); - Token = LexGetToken(Parser, &LexValue, TRUE); - switch (Token) - { - case TokenOpenBracket: - if (*Typ != NULL) - ProgramFail(Parser, "bad type declaration"); - - TypeParse(Parser, Typ, Identifier, NULL); - if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) - ProgramFail(Parser, "')' expected"); - break; - - case TokenAsterisk: - if (*Typ == NULL) - ProgramFail(Parser, "bad type declaration"); - - *Typ = TypeGetMatching(Parser, *Typ, TypePointer, 0, StrEmpty, TRUE); - break; - - case TokenIdentifier: - if (*Typ == NULL || *Identifier != StrEmpty) - ProgramFail(Parser, "bad type declaration"); - - *Identifier = LexValue->Val->Identifier; - Done = TRUE; - break; - - default: ParserCopy(Parser, &Before); Done = TRUE; break; - } - } - - if (*Typ == NULL) - ProgramFail(Parser, "bad type declaration"); - - if (*Identifier != StrEmpty) - { - /* parse stuff after the identifier */ - *Typ = TypeParseBack(Parser, *Typ); - } -} - -/* parse a type - a complete declaration including identifier */ -void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic) -{ - struct ValueType *BasicType; - - TypeParseFront(Parser, &BasicType, IsStatic); - TypeParseIdentPart(Parser, BasicType, Typ, Identifier); -} - diff --git a/ecilib/variable.c b/ecilib/variable.c deleted file mode 100644 index ad81128..0000000 --- a/ecilib/variable.c +++ /dev/null @@ -1,350 +0,0 @@ -#include "interpreter.h" - -/* maximum size of a value to temporarily copy while we create a variable */ -#define MAX_TMP_COPY_BUF 256 - -/* the table of global definitions */ -struct Table GlobalTable; -struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE]; - -/* the table of string literal values */ -struct Table StringLiteralTable; -struct TableEntry *StringLiteralHashTable[STRING_LITERAL_TABLE_SIZE]; - -/* the stack */ -struct StackFrame *TopStackFrame = NULL; - - -/* initialise the variable system */ -void VariableInit() -{ - TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE); - TableInitTable(&StringLiteralTable, &StringLiteralHashTable[0], STRING_LITERAL_TABLE_SIZE, TRUE); - TopStackFrame = NULL; -} - -/* deallocate the contents of a variable */ -void VariableFree(struct Value *Val) -{ - if (Val->ValOnHeap) - { - /* free function bodies */ - if (Val->Typ == &FunctionType && Val->Val->FuncDef.Intrinsic == NULL && Val->Val->FuncDef.Body.Pos != NULL) - HeapFreeMem((void *)Val->Val->FuncDef.Body.Pos); - - /* free macro bodies */ - if (Val->Typ == &MacroType) - HeapFreeMem((void *)Val->Val->MacroDef.Body.Pos); - - /* free the value */ - HeapFreeMem(Val); - } -} - -/* deallocate the global table and the string literal table */ -void VariableTableCleanup(struct Table *HashTable) -{ - struct TableEntry *Entry; - struct TableEntry *NextEntry; - int Count; - - for (Count = 0; Count < HashTable->Size; Count++) - { - for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) - { - NextEntry = Entry->Next; - VariableFree(Entry->p.v.Val); - - /* free the hash table entry */ - HeapFreeMem(Entry); - } - } -} - -void VariableCleanup() -{ - VariableTableCleanup(&GlobalTable); - VariableTableCleanup(&StringLiteralTable); -} - -/* allocate some memory, either on the heap or the stack and check if we've run out */ -void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap) -{ - void *NewValue; - - if (OnHeap) - NewValue = HeapAllocMem(Size); - else - NewValue = HeapAllocStack(Size); - - if (NewValue == NULL) - ProgramFail(Parser, "out of memory"); - -#ifdef DEBUG_HEAP - if (!OnHeap) - printf("pushing %d at 0x%lx\n", Size, (unsigned long)NewValue); -#endif - - return NewValue; -} - -/* allocate a value either on the heap or the stack using space dependent on what type we want */ -struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap) -{ - struct Value *NewValue = VariableAlloc(Parser, MEM_ALIGN(sizeof(struct Value)) + DataSize, OnHeap); - NewValue->Val = (union AnyValue *)((char *)NewValue + MEM_ALIGN(sizeof(struct Value))); - NewValue->ValOnHeap = OnHeap; - NewValue->ValOnStack = !OnHeap; - NewValue->IsLValue = IsLValue; - NewValue->LValueFrom = LValueFrom; - - return NewValue; -} - -/* allocate a value given its type */ -struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap) -{ - int Size = TypeSize(Typ, Typ->ArraySize, FALSE); - struct Value *NewValue = VariableAllocValueAndData(Parser, Size, IsLValue, LValueFrom, OnHeap); - assert(Size > 0 || Typ == &VoidType); - NewValue->Typ = Typ; - - return NewValue; -} - -/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */ -struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap) -{ - struct ValueType *DType = FromValue->Typ; - struct Value *NewValue; - char TmpBuf[MAX_TMP_COPY_BUF]; - int CopySize = TypeSizeValue(FromValue, TRUE); - - assert(CopySize <= MAX_TMP_COPY_BUF); - memcpy((void *)&TmpBuf[0], (void *)FromValue->Val, CopySize); - NewValue = VariableAllocValueAndData(Parser, CopySize, FromValue->IsLValue, FromValue->LValueFrom, OnHeap); - NewValue->Typ = DType; - memcpy((void *)NewValue->Val, (void *)&TmpBuf[0], CopySize); - - return NewValue; -} - -/* allocate a value either on the heap or the stack from an existing AnyValue and type */ -struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue, struct Value *LValueFrom) -{ - struct Value *NewValue = VariableAlloc(Parser, sizeof(struct Value), FALSE); - NewValue->Typ = Typ; - NewValue->Val = FromValue; - NewValue->ValOnHeap = FALSE; - NewValue->ValOnStack = FALSE; - NewValue->IsLValue = IsLValue; - NewValue->LValueFrom = LValueFrom; - - return NewValue; -} - -/* allocate a value either on the heap or the stack from an existing Value, sharing the value */ -struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *FromValue) -{ - return VariableAllocValueFromExistingData(Parser, FromValue->Typ, FromValue->Val, FromValue->IsLValue, FromValue->IsLValue ? FromValue : NULL); -} - -/* define a variable. Ident must be registered */ -struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable) -{ - struct Value *AssignValue; - - if (InitValue != NULL) - AssignValue = VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL); - else - AssignValue = VariableAllocValueFromType(Parser, Typ, MakeWritable, NULL, TopStackFrame == NULL); - - AssignValue->IsLValue = MakeWritable; - - if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) - ProgramFail(Parser, "'%s' is already defined", Ident); - - return AssignValue; -} - -/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ -struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit) -{ - struct Value *ExistingValue; - const char *DeclFileName; - int DeclLine; - int DeclColumn; - - if (IsStatic) - { - char MangledName[LINEBUFFER_MAX]; - char *MNPos = &MangledName[0]; - char *MNEnd = &MangledName[LINEBUFFER_MAX-1]; - const char *RegisteredMangledName; - - /* make the mangled static name (avoiding using sprintf() to minimise library impact) */ - memset((void *)&MangledName, '\0', sizeof(MangledName)); - *MNPos++ = '/'; - strncpy(MNPos, (char *)Parser->FileName, MNEnd - MNPos); - MNPos += strlen(MNPos); - - if (TopStackFrame != NULL) - { - /* we're inside a function */ - if (MNEnd - MNPos > 0) *MNPos++ = '/'; - strncpy(MNPos, (char *)TopStackFrame->FuncName, MNEnd - MNPos); - MNPos += strlen(MNPos); - } - - if (MNEnd - MNPos > 0) *MNPos++ = '/'; - strncpy(MNPos, Ident, MNEnd - MNPos); - RegisteredMangledName = TableStrRegister(MangledName); - - /* is this static already defined? */ - if (!TableGet(&GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) - { - /* define the mangled-named static variable store in the global scope */ - ExistingValue = VariableAllocValueFromType(Parser, Typ, TRUE, NULL, TRUE); - TableSet(&GlobalTable, (char *)RegisteredMangledName, ExistingValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos); - *FirstVisit = TRUE; - } - - /* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */ - VariableDefinePlatformVar(Parser, Ident, ExistingValue->Typ, ExistingValue->Val, TRUE); - return ExistingValue; - } - else - { - if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn) - && DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) - return ExistingValue; - else - return VariableDefine(Parser, Ident, NULL, Typ, TRUE); - } -} - -/* check if a variable with a given name is defined. Ident must be registered */ -int VariableDefined(const char *Ident) -{ - struct Value *FoundValue; - - if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL, NULL)) - { - if (!TableGet(&GlobalTable, Ident, &FoundValue, NULL, NULL, NULL)) - return FALSE; - } - - return TRUE; -} - -/* get the value of a variable. must be defined. Ident must be registered */ -void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal) -{ - if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL)) - { - if (!TableGet(&GlobalTable, Ident, LVal, NULL, NULL, NULL)) - ProgramFail(Parser, "'%s' is undefined", Ident); - } -} - -/* define a global variable shared with a platform global. Ident will be registered */ -void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable) -{ - struct Value *SomeValue = VariableAllocValueAndData(NULL, 0, IsWritable, NULL, TRUE); - SomeValue->Typ = Typ; - SomeValue->Val = FromValue; - - if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue, Parser ? Parser->FileName : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) - ProgramFail(Parser, "'%s' is already defined", Ident); -} - -/* free and/or pop the top value off the stack. Var must be the top value on the stack! */ -void VariableStackPop(struct ParseState *Parser, struct Value *Var) -{ - int Success; - -#ifdef DEBUG_HEAP - if (Var->ValOnStack) - printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(Var, FALSE)), (unsigned long)Var); -#endif - - if (Var->ValOnHeap) - { - if (Var->Val != NULL) - HeapFreeMem(Var->Val); - - Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */ - } - else if (Var->ValOnStack) - Success = HeapPopStack(Var, sizeof(struct Value) + TypeSizeValue(Var, FALSE)); /* free from stack */ - else - Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */ - - if (!Success) - ProgramFail(Parser, "stack underrun"); -} - -/* add a stack frame when doing a function call */ -void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams) -{ - struct StackFrame *NewFrame; - - HeapPushStackFrame(); - NewFrame = HeapAllocStack(sizeof(struct StackFrame) + sizeof(struct Value *) * NumParams); - if (NewFrame == NULL) - ProgramFail(Parser, "out of memory"); - - ParserCopy(&NewFrame->ReturnParser, Parser); - NewFrame->FuncName = FuncName; - NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL; - TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); - NewFrame->PreviousStackFrame = TopStackFrame; - TopStackFrame = NewFrame; -} - -/* remove a stack frame */ -void VariableStackFramePop(struct ParseState *Parser) -{ - if (TopStackFrame == NULL) - ProgramFail(Parser, "stack is empty - can't go back"); - - ParserCopy(Parser, &TopStackFrame->ReturnParser); - TopStackFrame = TopStackFrame->PreviousStackFrame; - HeapPopStackFrame(); -} - -/* get a string literal. assumes that Ident is already registered. NULL if not found */ -struct Value *VariableStringLiteralGet(char *Ident) -{ - struct Value *LVal = NULL; - - if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL, NULL)) - return LVal; - else - return NULL; -} - -/* define a string literal. assumes that Ident is already registered */ -void VariableStringLiteralDefine(char *Ident, struct Value *Val) -{ - TableSet(&StringLiteralTable, Ident, Val, NULL, 0, 0); -} - -/* check a pointer for validity and dereference it for use */ -void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue) -{ - if (DerefVal != NULL) - *DerefVal = NULL; - - if (DerefType != NULL) - *DerefType = PointerValue->Typ->FromType; - - if (DerefOffset != NULL) - *DerefOffset = 0; - - if (DerefIsLValue != NULL) - *DerefIsLValue = TRUE; - - return PointerValue->Val->Pointer; -} - diff --git a/lutin_eci.py b/lutin_eci.py new file mode 100644 index 0000000..0a78e84 --- /dev/null +++ b/lutin_eci.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +import lutinModule as module +import lutinTools as tools +import os +import lutinMultiprocess + +def get_desc(): + return "Ewol C Interpreter" + +def create(target): + # module name is 'edn' and type binary. + myModule = module.Module(__file__, 'eci', 'BINARY') + # add extra compilation flags : + myModule.add_extra_compile_flags() + # add the file to compile: + myModule.add_src_file([ + 'eci/clibrary.c', + 'eci/expression.c', + 'eci/heap.c', + 'eci/include.c', + 'eci/lex.c', + 'eci/parse.c', + 'eci/picoc.c', + 'eci/platform.c', + 'eci/table.c', + 'eci/type.c', + 'eci/variable.c', + 'eci/platform/platform_unix.c', + 'eci/platform/library_unix.c', + 'eci/cstdlib/ctype.c', + 'eci/cstdlib/errno.c', + 'eci/cstdlib/math.c', + 'eci/cstdlib/stdbool.c', + 'eci/cstdlib/stdio.c', + 'eci/cstdlib/stdlib.c', + 'eci/cstdlib/string.c', + 'eci/cstdlib/time.c', + 'eci/cstdlib/unistd.c' + ]) + myModule.add_export_path(tools.get_current_path(__file__)) + # add the currrent module at the + return myModule + diff --git a/tests/Makefile b/tests/Makefile index 7b42f6f..e7dd4e3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -54,9 +54,9 @@ TESTS= 00_assignment.test \ @echo Test: $*... @if [ "x`echo $* | grep args`" != "x" ]; \ then \ - ../picoc $*.c - arg1 arg2 arg3 arg4 2>&1 >$*.output; \ + ../eci $*.c - arg1 arg2 arg3 arg4 2>&1 >$*.output; \ else \ - ../picoc $*.c 2>&1 >$*.output; \ + ../eci $*.c 2>&1 >$*.output; \ fi @if [ "x`diff -qbu $*.expect $*.output`" != "x" ]; \ then \