ongoing dev: remove unused platform specific code
This commit is contained in:
parent
820a026d90
commit
1a4b9a92c4
574
clibrary.c
574
clibrary.c
|
@ -1,5 +1,4 @@
|
||||||
/* picoc mini standard C library - provides an optional tiny C standard library
|
/* */
|
||||||
* if BUILTIN_MINI_STDLIB is defined */
|
|
||||||
|
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
@ -77,574 +76,3 @@ void PrintType(struct ValueType *Typ, IOFILE *Stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int TRUEValue = 1;
|
|
||||||
static int ZeroValue = 0;
|
|
||||||
|
|
||||||
void BasicIOInit(Picoc *pc)
|
|
||||||
{
|
|
||||||
pc->CStdOutBase.Putch = &PlatformPutc;
|
|
||||||
pc->CStdOut = &CStdOutBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialise the C library */
|
|
||||||
void CLibraryInit(Picoc *pc)
|
|
||||||
{
|
|
||||||
/* define some constants */
|
|
||||||
VariableDefinePlatformVar(pc, NULL, "NULL", &IntType, (union AnyValue*)&ZeroValue, FALSE);
|
|
||||||
VariableDefinePlatformVar(pc, NULL, "TRUE", &IntType, (union AnyValue*)&TRUEValue, FALSE);
|
|
||||||
VariableDefinePlatformVar(pc, 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(Picoc *pc, 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++;
|
|
||||||
FieldWidth = 0;
|
|
||||||
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 */
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
void StdIsalnum(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
void StdIsalnum(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
|
@ -107,4 +106,3 @@ struct LibraryFunction StdCtypeFunctions[] =
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
#ifdef EACCES
|
#ifdef EACCES
|
||||||
static int EACCESValue = EACCES;
|
static int EACCESValue = EACCES;
|
||||||
|
@ -652,4 +651,3 @@ void StdErrnoSetupFunc(Picoc *pc)
|
||||||
VariableDefinePlatformVar(pc, NULL, "errno", &pc->IntType, (union AnyValue *)&errno, TRUE);
|
VariableDefinePlatformVar(pc, NULL, "errno", &pc->IntType, (union AnyValue *)&errno, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
|
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
|
|
||||||
static double M_EValue = 2.7182818284590452354; /* e */
|
static double M_EValue = 2.7182818284590452354; /* e */
|
||||||
|
@ -184,4 +183,3 @@ void MathSetupFunc(Picoc *pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !NO_FP */
|
#endif /* !NO_FP */
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
static int trueValue = 1;
|
static int trueValue = 1;
|
||||||
static int falseValue = 0;
|
static int falseValue = 0;
|
||||||
|
@ -18,5 +17,3 @@ void StdboolSetupFunc(Picoc *pc)
|
||||||
VariableDefinePlatformVar(pc, NULL, "false", &pc->IntType, (union AnyValue *)&falseValue, FALSE);
|
VariableDefinePlatformVar(pc, NULL, "false", &pc->IntType, (union AnyValue *)&falseValue, FALSE);
|
||||||
VariableDefinePlatformVar(pc, NULL, "__bool_true_false_are_defined", &pc->IntType, (union AnyValue *)&trueValue, FALSE);
|
VariableDefinePlatformVar(pc, NULL, "__bool_true_false_are_defined", &pc->IntType, (union AnyValue *)&trueValue, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
|
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
@ -693,4 +692,3 @@ void PrintFP(double Num, FILE *Stream)
|
||||||
fprintf(Stream, "%f", Num);
|
fprintf(Stream, "%f", Num);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */
|
/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
static int Stdlib_ZeroValue = 0;
|
static int Stdlib_ZeroValue = 0;
|
||||||
|
|
||||||
|
@ -171,4 +170,3 @@ void StdlibSetupFunc(Picoc *pc)
|
||||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdlib_ZeroValue, FALSE);
|
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdlib_ZeroValue, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
static int String_ZeroValue = 0;
|
static int String_ZeroValue = 0;
|
||||||
|
|
||||||
|
@ -183,4 +182,3 @@ void StringSetupFunc(Picoc *pc)
|
||||||
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&String_ZeroValue, FALSE);
|
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&String_ZeroValue, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
static int CLOCKS_PER_SECValue = CLOCKS_PER_SEC;
|
static int CLOCKS_PER_SECValue = CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
@ -125,4 +124,3 @@ void StdTimeSetupFunc(Picoc *pc)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "../interpreter.h"
|
#include "../interpreter.h"
|
||||||
|
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
|
|
||||||
static int ZeroValue = 0;
|
static int ZeroValue = 0;
|
||||||
|
|
||||||
|
@ -501,5 +500,3 @@ void UnistdSetupFunc(Picoc *pc)
|
||||||
VariableDefinePlatformVar(pc, NULL, "optopt", &pc->IntType, (union AnyValue *)&optopt, TRUE);
|
VariableDefinePlatformVar(pc, NULL, "optopt", &pc->IntType, (union AnyValue *)&optopt, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !BUILTIN_MINI_STDLIB */
|
|
||||||
|
|
||||||
|
|
140
heap.c
140
heap.c
|
@ -1,6 +1,4 @@
|
||||||
/* picoc heap memory allocation. This is a complete (but small) memory
|
/* picoc heap memory allocation. */
|
||||||
* allocator for embedded systems which have no memory allocator. Alternatively
|
|
||||||
* you can define USE_MALLOC_HEAP to use your system's own malloc() allocator */
|
|
||||||
|
|
||||||
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
@ -25,24 +23,10 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
|
||||||
int Count;
|
int Count;
|
||||||
int AlignOffset = 0;
|
int AlignOffset = 0;
|
||||||
|
|
||||||
#ifdef USE_MALLOC_STACK
|
|
||||||
pc->HeapMemory = malloc(StackOrHeapSize);
|
pc->HeapMemory = malloc(StackOrHeapSize);
|
||||||
pc->HeapBottom = NULL; /* the bottom of the (downward-growing) heap */
|
pc->HeapBottom = NULL; /* the bottom of the (downward-growing) heap */
|
||||||
pc->StackFrame = NULL; /* the current stack frame */
|
pc->StackFrame = NULL; /* the current stack frame */
|
||||||
pc->HeapStackTop = NULL; /* the top of the stack */
|
pc->HeapStackTop = NULL; /* the top of the stack */
|
||||||
#else
|
|
||||||
# ifdef SURVEYOR_HOST
|
|
||||||
pc->HeapMemory = (unsigned char *)C_HEAPSTART; /* all memory - stack and heap */
|
|
||||||
pc->HeapBottom = (void *)C_HEAPSTART + HEAP_SIZE; /* the bottom of the (downward-growing) heap */
|
|
||||||
pc->StackFrame = (void *)C_HEAPSTART; /* the current stack frame */
|
|
||||||
pc->HeapStackTop = (void *)C_HEAPSTART; /* the top of the stack */
|
|
||||||
pc->HeapMemStart = (void *)C_HEAPSTART;
|
|
||||||
# else
|
|
||||||
pc->HeapBottom = &HeapMemory[HEAP_SIZE]; /* the bottom of the (downward-growing) heap */
|
|
||||||
pc->StackFrame = &HeapMemory[0]; /* the current stack frame */
|
|
||||||
pc->HeapStackTop = &HeapMemory[0]; /* the top of the stack */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (((unsigned long)&pc->HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0)
|
while (((unsigned long)&pc->HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0)
|
||||||
AlignOffset++;
|
AlignOffset++;
|
||||||
|
@ -58,9 +42,7 @@ void HeapInit(Picoc *pc, int StackOrHeapSize)
|
||||||
|
|
||||||
void HeapCleanup(Picoc *pc)
|
void HeapCleanup(Picoc *pc)
|
||||||
{
|
{
|
||||||
#ifdef USE_MALLOC_STACK
|
|
||||||
free(pc->HeapMemory);
|
free(pc->HeapMemory);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate some space on the stack, in the current stack frame
|
/* allocate some space on the stack, in the current stack frame
|
||||||
|
@ -134,132 +116,12 @@ int HeapPopStackFrame(Picoc *pc)
|
||||||
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
||||||
void *HeapAllocMem(Picoc *pc, int Size)
|
void *HeapAllocMem(Picoc *pc, int Size)
|
||||||
{
|
{
|
||||||
#ifdef USE_MALLOC_HEAP
|
|
||||||
return calloc(Size, 1);
|
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 && pc->FreeListBucket[Bucket] != NULL) {
|
|
||||||
/* try to allocate from a freelist bucket first */
|
|
||||||
#ifdef DEBUG_HEAP
|
|
||||||
printf("allocating %d(%d) from bucket", Size, AllocSize);
|
|
||||||
#endif
|
|
||||||
NewMem = pc->FreeListBucket[Bucket];
|
|
||||||
assert((unsigned long)NewMem >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char*)NewMem - &(pc->HeapMemory)[0] < HEAP_SIZE);
|
|
||||||
pc->FreeListBucket[Bucket] = *(struct AllocNode **)NewMem;
|
|
||||||
assert(pc->FreeListBucket[Bucket] == NULL || ((unsigned long)pc->FreeListBucket[Bucket] >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)pc->FreeListBucket[Bucket] - &(pc->HeapMemory)[0] < HEAP_SIZE));
|
|
||||||
NewMem->Size = AllocSize;
|
|
||||||
} else if (pc->FreeListBig != NULL) {
|
|
||||||
/* grab the first item from the "big" freelist we can fit in */
|
|
||||||
for (FreeNode = &pc->FreeListBig; *FreeNode != NULL && (*FreeNode)->Size < AllocSize; FreeNode = &(*FreeNode)->NextFree) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*FreeNode != NULL) {
|
|
||||||
assert((unsigned long)*FreeNode >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char*)*FreeNode - &(pc->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)&(pc->HeapMemory)[0] && (unsigned char*)NewMem - &(pc->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)&(pc->HeapMemory)[0] && (unsigned char*)NewMem - &(pc->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*)pc->HeapBottom - AllocSize), (long)HeapBottom);
|
|
||||||
#endif
|
|
||||||
if ((char*)pc->HeapBottom - AllocSize < (char*)pc->HeapStackTop)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
pc->HeapBottom = (void*)((char*)pc->HeapBottom - AllocSize);
|
|
||||||
NewMem = pc->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 */
|
/* free some dynamically allocated memory */
|
||||||
void HeapFreeMem(Picoc *pc, void *Mem)
|
void HeapFreeMem(Picoc *pc, void *Mem)
|
||||||
{
|
{
|
||||||
#ifdef USE_MALLOC_HEAP
|
|
||||||
free(Mem);
|
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)&(pc->HeapMemory)[0] && (unsigned char*)Mem - &(pc->HeapMemory)[0] < HEAP_SIZE);
|
|
||||||
assert(MemNode->Size < HEAP_SIZE && MemNode->Size > 0);
|
|
||||||
if (Mem == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((void *)MemNode == pc->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
|
|
||||||
pc->HeapBottom = (void *)((char *)pc->HeapBottom + MemNode->Size);
|
|
||||||
#ifdef DEBUG_HEAP
|
|
||||||
ShowBigList(pc);
|
|
||||||
#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(pc->FreeListBucket[Bucket] == NULL || ((unsigned long)pc->FreeListBucket[Bucket] >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)FreeListBucket[Bucket] - &HeapMemory[0] < HEAP_SIZE));
|
|
||||||
*(struct AllocNode **)MemNode = pc->FreeListBucket[Bucket];
|
|
||||||
pc->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(pc->FreeListBig == NULL || ((unsigned long)pc->FreeListBig >= (unsigned long)&(pc->HeapMemory)[0] && (unsigned char *)pc->FreeListBig - &(pc->HeapMemory)[0] < HEAP_SIZE));
|
|
||||||
MemNode->NextFree = pc->FreeListBig;
|
|
||||||
FreeListBig = MemNode;
|
|
||||||
#ifdef DEBUG_HEAP
|
|
||||||
ShowBigList(pc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,10 @@
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
#ifndef NO_HASH_INCLUDE
|
|
||||||
|
|
||||||
|
|
||||||
/* initialise the built-in include libraries */
|
/* initialise the built-in include libraries */
|
||||||
void IncludeInit(Picoc *pc)
|
void IncludeInit(Picoc *pc)
|
||||||
{
|
{
|
||||||
#ifndef BUILTIN_MINI_STDLIB
|
|
||||||
IncludeRegister(pc, "ctype.h", NULL, &StdCtypeFunctions[0], NULL);
|
IncludeRegister(pc, "ctype.h", NULL, &StdCtypeFunctions[0], NULL);
|
||||||
IncludeRegister(pc, "errno.h", &StdErrnoSetupFunc, NULL, NULL);
|
IncludeRegister(pc, "errno.h", &StdErrnoSetupFunc, NULL, NULL);
|
||||||
# ifndef NO_FP
|
# ifndef NO_FP
|
||||||
|
@ -24,7 +21,6 @@ void IncludeInit(Picoc *pc)
|
||||||
# ifndef WIN32
|
# ifndef WIN32
|
||||||
IncludeRegister(pc, "unistd.h", &UnistdSetupFunc, &UnistdFunctions[0], UnistdDefs);
|
IncludeRegister(pc, "unistd.h", &UnistdSetupFunc, &UnistdFunctions[0], UnistdDefs);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up space used by the include system */
|
/* clean up space used by the include system */
|
||||||
|
@ -96,4 +92,3 @@ void IncludeFile(Picoc *pc, char *FileName)
|
||||||
PicocPlatformScanFile(pc, FileName);
|
PicocPlatformScanFile(pc, FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NO_HASH_INCLUDE */
|
|
||||||
|
|
|
@ -30,12 +30,7 @@
|
||||||
#define PRINT_SOURCE_POS ({ PrintSourceTextErrorLine(Parser->pc->CStdOut, Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); PlatformPrintf(Parser->pc->CStdOut, "\n"); })
|
#define PRINT_SOURCE_POS ({ PrintSourceTextErrorLine(Parser->pc->CStdOut, Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); PlatformPrintf(Parser->pc->CStdOut, "\n"); })
|
||||||
#define PRINT_TYPE(typ) PlatformPrintf(Parser->pc->CStdOut, "%t\n", typ);
|
#define PRINT_TYPE(typ) PlatformPrintf(Parser->pc->CStdOut, "%t\n", typ);
|
||||||
|
|
||||||
/* small processors use a simplified FILE * for stdio, otherwise use the system FILE * */
|
|
||||||
#ifdef BUILTIN_MINI_STDLIB
|
|
||||||
typedef struct OutputStream IOFILE;
|
|
||||||
#else
|
|
||||||
typedef FILE IOFILE;
|
typedef FILE IOFILE;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* coercion of numeric types to other numeric types */
|
/* coercion of numeric types to other numeric types */
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
|
@ -391,25 +386,10 @@ struct Picoc_Struct
|
||||||
struct IncludeLibrary *IncludeLibList;
|
struct IncludeLibrary *IncludeLibList;
|
||||||
|
|
||||||
/* heap memory */
|
/* heap memory */
|
||||||
#ifdef USE_MALLOC_STACK
|
|
||||||
unsigned char *HeapMemory; /* stack memory since our heap is malloc()ed */
|
unsigned char *HeapMemory; /* stack memory since our heap is malloc()ed */
|
||||||
void *HeapBottom; /* the bottom of the (downward-growing) heap */
|
void *HeapBottom; /* the bottom of the (downward-growing) heap */
|
||||||
void *StackFrame; /* the current stack frame */
|
void *StackFrame; /* the current stack frame */
|
||||||
void *HeapStackTop; /* the top of the stack */
|
void *HeapStackTop; /* the top of the stack */
|
||||||
#else
|
|
||||||
# ifdef SURVEYOR_HOST
|
|
||||||
unsigned char *HeapMemory; /* all memory - stack and heap */
|
|
||||||
void *HeapBottom; /* the bottom of the (downward-growing) heap */
|
|
||||||
void *StackFrame; /* the current stack frame */
|
|
||||||
void *HeapStackTop; /* the top of the stack */
|
|
||||||
void *HeapMemStart;
|
|
||||||
# else
|
|
||||||
unsigned char HeapMemory[HEAP_SIZE]; /* all memory - stack and heap */
|
|
||||||
void *HeapBottom; /* the bottom of the (downward-growing) heap */
|
|
||||||
void *StackFrame; /* the current stack frame */
|
|
||||||
void *HeapStackTop; /* the top of the stack */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */
|
struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */
|
||||||
struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */
|
struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */
|
||||||
|
@ -458,9 +438,6 @@ struct Picoc_Struct
|
||||||
#if defined(UNIX_HOST) || defined(WIN32)
|
#if defined(UNIX_HOST) || defined(WIN32)
|
||||||
jmp_buf PicocExitBuf;
|
jmp_buf PicocExitBuf;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SURVEYOR_HOST
|
|
||||||
int PicocExitBuf[41];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* string table */
|
/* string table */
|
||||||
struct Table StringTable;
|
struct Table StringTable;
|
||||||
|
|
2
parse.c
2
parse.c
|
@ -690,14 +690,12 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
|
||||||
ParseMacroDefinition(Parser);
|
ParseMacroDefinition(Parser);
|
||||||
CheckTrailingSemicolon = FALSE;
|
CheckTrailingSemicolon = FALSE;
|
||||||
break;
|
break;
|
||||||
#ifndef NO_HASH_INCLUDE
|
|
||||||
case TokenHashInclude:
|
case TokenHashInclude:
|
||||||
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
|
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
|
||||||
ProgramFail(Parser, "\"filename.h\" expected");
|
ProgramFail(Parser, "\"filename.h\" expected");
|
||||||
IncludeFile(Parser->pc, (char *)LexerValue->Val->Pointer);
|
IncludeFile(Parser->pc, (char *)LexerValue->Val->Pointer);
|
||||||
CheckTrailingSemicolon = FALSE;
|
CheckTrailingSemicolon = FALSE;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case TokenSwitch:
|
case TokenSwitch:
|
||||||
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
||||||
ProgramFail(Parser, "'(' expected");
|
ProgramFail(Parser, "'(' expected");
|
||||||
|
|
37
picoc.c
37
picoc.c
|
@ -55,41 +55,4 @@ int main(int argc, char **argv)
|
||||||
PicocCleanup(&pc);
|
PicocCleanup(&pc);
|
||||||
return pc.PicocExitValue;
|
return pc.PicocExitValue;
|
||||||
}
|
}
|
||||||
#elif defined(SURVEYOR_HOST)
|
|
||||||
#define HEAP_SIZE C_HEAPSIZE
|
|
||||||
#include <setjmp.h>
|
|
||||||
#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;
|
|
||||||
PicocPlatformSetExitPoint();
|
|
||||||
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
|
||||||
|
|
7
picoc.h
7
picoc.h
|
@ -26,13 +26,6 @@
|
||||||
#define PicocPlatformSetExitPoint(pc) setjmp((pc)->PicocExitBuf)
|
#define PicocPlatformSetExitPoint(pc) setjmp((pc)->PicocExitBuf)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SURVEYOR_HOST
|
|
||||||
/* mark where to end the program for platforms which require this */
|
|
||||||
extern int PicocExitBuf[];
|
|
||||||
|
|
||||||
#define PicocPlatformSetExitPoint(pc) setjmp((pc)->PicocExitBuf)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* parse.c */
|
/* parse.c */
|
||||||
extern void PicocParse(Picoc *pc, const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource, int EnableDebugger);
|
extern void PicocParse(Picoc *pc, const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource, int EnableDebugger);
|
||||||
extern void PicocParseInteractive(Picoc *pc);
|
extern void PicocParseInteractive(Picoc *pc);
|
||||||
|
|
|
@ -22,14 +22,8 @@ void PicocInitialise(Picoc *pc, int StackSize)
|
||||||
VariableInit(pc);
|
VariableInit(pc);
|
||||||
LexInit(pc);
|
LexInit(pc);
|
||||||
TypeInit(pc);
|
TypeInit(pc);
|
||||||
#ifndef NO_HASH_INCLUDE
|
|
||||||
IncludeInit(pc);
|
IncludeInit(pc);
|
||||||
#endif
|
|
||||||
LibraryInit(pc);
|
LibraryInit(pc);
|
||||||
#ifdef BUILTIN_MINI_STDLIB
|
|
||||||
LibraryAdd(pc, &GlobalTable, "c library", &CLibrary[0]);
|
|
||||||
CLibraryInit(pc);
|
|
||||||
#endif
|
|
||||||
PlatformLibraryInit(pc);
|
PlatformLibraryInit(pc);
|
||||||
#ifndef NO_DEBUGGER
|
#ifndef NO_DEBUGGER
|
||||||
DebugInit(pc);
|
DebugInit(pc);
|
||||||
|
@ -42,9 +36,7 @@ void PicocCleanup(Picoc *pc)
|
||||||
#ifndef NO_DEBUGGER
|
#ifndef NO_DEBUGGER
|
||||||
DebugCleanup(pc);
|
DebugCleanup(pc);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NO_HASH_INCLUDE
|
|
||||||
IncludeCleanup(pc);
|
IncludeCleanup(pc);
|
||||||
#endif
|
|
||||||
ParseCleanup(pc);
|
ParseCleanup(pc);
|
||||||
LexCleanup(pc);
|
LexCleanup(pc);
|
||||||
VariableCleanup(pc);
|
VariableCleanup(pc);
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
|
|
||||||
/* host platform includes */
|
/* host platform includes */
|
||||||
#ifdef UNIX_HOST
|
#ifdef UNIX_HOST
|
||||||
# define USE_MALLOC_STACK /* stack is allocated using malloc() */
|
|
||||||
# define USE_MALLOC_HEAP /* heap is allocated using malloc() */
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
@ -52,8 +50,6 @@
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
# define USE_MALLOC_STACK /* stack is allocated using malloc() */
|
|
||||||
# define USE_MALLOC_HEAP /* heap is allocated using malloc() */
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
|
Loading…
Reference in a new issue