2008-12-26 23:36:45 -05:00
|
|
|
#include "picoc.h"
|
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
struct OutputStream CStdOut;
|
|
|
|
|
2009-04-19 07:49:01 -04:00
|
|
|
static int TRUEValue = 1;
|
|
|
|
static int ZeroValue = 0;
|
|
|
|
|
2009-02-24 05:29:14 -05:00
|
|
|
/* initialise a library */
|
2009-02-24 06:16:37 -05:00
|
|
|
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[])
|
2009-02-24 05:29:14 -05:00
|
|
|
{
|
|
|
|
struct ParseState Parser;
|
|
|
|
int Count;
|
|
|
|
char *Identifier;
|
|
|
|
struct ValueType *ReturnType;
|
|
|
|
struct Value *NewValue;
|
|
|
|
void *Tokens;
|
|
|
|
const char *IntrinsicName = TableStrRegister("c library");
|
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
CStdOut.Putch = &PlatformPutc;
|
|
|
|
|
2009-02-24 06:16:37 -05:00
|
|
|
for (Count = 0; (*FuncList)[Count].Prototype != NULL; Count++)
|
2009-02-24 05:29:14 -05:00
|
|
|
{
|
2009-04-03 23:11:12 -04:00
|
|
|
Tokens = LexAnalyse(IntrinsicName, (*FuncList)[Count].Prototype, strlen((char *)(*FuncList)[Count].Prototype), NULL);
|
2009-06-04 03:41:06 -04:00
|
|
|
LexInitParser(&Parser, (*FuncList)[Count].Prototype, Tokens, IntrinsicName, TRUE);
|
2009-02-24 05:29:14 -05:00
|
|
|
TypeParse(&Parser, &ReturnType, &Identifier);
|
|
|
|
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier, TRUE);
|
2009-02-24 06:16:37 -05:00
|
|
|
NewValue->Val->FuncDef.Intrinsic = (*FuncList)[Count].Func;
|
2009-06-02 04:00:02 -04:00
|
|
|
HeapFreeMem(Tokens);
|
2009-02-24 05:29:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 07:49:01 -04:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
/* stream for writing into strings */
|
|
|
|
void SPutc(unsigned char Ch, union OutputStreamInfo *Stream)
|
|
|
|
{
|
|
|
|
struct StringOutputStream *Out = &Stream->Str;
|
|
|
|
*Out->WritePos++ = Ch;
|
2009-10-23 15:01:32 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
2009-04-27 00:56:58 -04:00
|
|
|
if (Out->WritePos == Out->MaxPos)
|
|
|
|
Out->WritePos--;
|
2009-10-23 15:01:32 -04:00
|
|
|
#endif
|
2009-04-27 00:56:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* print a character to a stream without using printf/sprintf */
|
|
|
|
void PrintCh(char OutCh, struct OutputStream *Stream)
|
|
|
|
{
|
|
|
|
(*Stream->Putch)(OutCh, &Stream->i);
|
|
|
|
}
|
|
|
|
|
2009-02-24 06:16:37 -05:00
|
|
|
/* print a string to a stream without using printf/sprintf */
|
2009-04-27 00:56:58 -04:00
|
|
|
void PrintStr(const char *Str, struct OutputStream *Stream)
|
2009-02-24 06:16:37 -05:00
|
|
|
{
|
|
|
|
while (*Str != 0)
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintCh(*Str++, Stream);
|
2009-02-24 06:16:37 -05:00
|
|
|
}
|
|
|
|
|
2009-10-23 15:01:32 -04:00
|
|
|
/* print a single character a given number of times */
|
|
|
|
void PrintRepeatedChar(char ShowChar, int Length, struct OutputStream *Stream)
|
|
|
|
{
|
|
|
|
while (Length-- > 0)
|
|
|
|
PrintCh(ShowChar, Stream);
|
|
|
|
}
|
|
|
|
|
2009-06-15 11:08:05 -04:00
|
|
|
/* print an unsigned integer to a stream without using printf/sprintf */
|
2009-10-23 15:01:32 -04:00
|
|
|
void PrintUnsigned(unsigned int Num, unsigned int Base, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream)
|
2009-06-15 11:08:05 -04:00
|
|
|
{
|
|
|
|
char Result[33];
|
|
|
|
int ResPos = sizeof(Result);
|
|
|
|
|
|
|
|
if (Num == 0)
|
|
|
|
PrintCh('0', Stream);
|
|
|
|
|
|
|
|
Result[--ResPos] = '\0';
|
|
|
|
while (Num > 0)
|
|
|
|
{
|
|
|
|
unsigned int NextNum = Num / Base;
|
|
|
|
unsigned int Digit = Num - NextNum * Base;
|
|
|
|
if (Digit < 10)
|
|
|
|
Result[--ResPos] = '0' + Digit;
|
|
|
|
else
|
|
|
|
Result[--ResPos] = 'a' + Digit - 10;
|
|
|
|
|
|
|
|
Num = NextNum;
|
|
|
|
}
|
|
|
|
|
2009-10-23 15:01:32 -04:00
|
|
|
if (FieldWidth > 0 && !LeftJustify)
|
|
|
|
PrintRepeatedChar(ZeroPad ? '0' : ' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream);
|
|
|
|
|
2009-06-15 11:08:05 -04:00
|
|
|
PrintStr(&Result[ResPos], Stream);
|
2009-10-23 15:01:32 -04:00
|
|
|
|
|
|
|
if (FieldWidth > 0 && LeftJustify)
|
|
|
|
PrintRepeatedChar(' ', FieldWidth - (sizeof(Result) - 1 - ResPos), Stream);
|
2009-06-15 11:08:05 -04:00
|
|
|
}
|
|
|
|
|
2009-02-20 21:35:52 -05:00
|
|
|
/* print an integer to a stream without using printf/sprintf */
|
2009-10-23 15:01:32 -04:00
|
|
|
void PrintInt(int Num, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream)
|
2009-02-20 21:35:52 -05:00
|
|
|
{
|
|
|
|
if (Num < 0)
|
|
|
|
{
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintCh('-', Stream);
|
2009-10-23 15:01:32 -04:00
|
|
|
Num = -Num;
|
|
|
|
if (FieldWidth != 0)
|
|
|
|
FieldWidth--;
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
|
|
|
|
2009-10-23 15:01:32 -04:00
|
|
|
PrintUnsigned((unsigned int)Num, 10, FieldWidth, ZeroPad, LeftJustify, Stream);
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
|
|
|
|
2009-02-23 23:52:35 -05:00
|
|
|
#ifndef NO_FP
|
2009-02-20 21:35:52 -05:00
|
|
|
/* print a double to a stream without using printf/sprintf */
|
2009-04-27 00:56:58 -04:00
|
|
|
void PrintFP(double Num, struct OutputStream *Stream)
|
2009-02-20 21:35:52 -05:00
|
|
|
{
|
|
|
|
int Exponent = 0;
|
2009-05-28 20:12:12 -04:00
|
|
|
int MaxDecimal;
|
2009-02-20 21:35:52 -05:00
|
|
|
|
2009-05-26 23:43:37 -04:00
|
|
|
if (Num < 0)
|
|
|
|
{
|
|
|
|
PrintCh('-', Stream);
|
|
|
|
Num = -Num;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Num >= 1e7)
|
2009-05-28 20:21:58 -04:00
|
|
|
Exponent = math_log(Num) / LOG10E;
|
2009-05-27 00:55:44 -04:00
|
|
|
else if (Num <= 1e-7 && Num != 0.0)
|
2009-05-28 20:21:58 -04:00
|
|
|
Exponent = math_log(Num) / LOG10E - 0.999999999;
|
2009-02-20 21:35:52 -05:00
|
|
|
|
2009-05-28 20:21:58 -04:00
|
|
|
Num /= math_pow(10.0, Exponent);
|
2009-10-23 15:01:32 -04:00
|
|
|
PrintInt((int)Num, 0, FALSE, FALSE, Stream);
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintCh('.', Stream);
|
2009-05-26 19:23:39 -04:00
|
|
|
Num = (Num - (int)Num) * 10;
|
|
|
|
if (abs(Num) >= 1e-7)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
for (MaxDecimal = 6; MaxDecimal > 0 && abs(Num) >= 1e-7; Num = (Num - (int)(Num + 1e-7)) * 10, MaxDecimal--)
|
2009-05-26 19:23:39 -04:00
|
|
|
PrintCh('0' + (int)(Num + 1e-7), Stream);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
PrintCh('0', Stream);
|
|
|
|
|
2009-05-26 18:31:42 -04:00
|
|
|
if (Exponent != 0)
|
2009-02-20 21:35:52 -05:00
|
|
|
{
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintCh('e', Stream);
|
2009-10-23 15:01:32 -04:00
|
|
|
PrintInt(Exponent, 0, FALSE, FALSE, Stream);
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
|
|
|
}
|
2009-02-23 23:52:35 -05:00
|
|
|
#endif
|
2009-02-20 21:35:52 -05:00
|
|
|
|
2009-04-23 21:02:25 -04:00
|
|
|
/* print a type to a stream without using printf/sprintf */
|
2009-04-27 00:56:58 -04:00
|
|
|
void PrintType(struct ValueType *Typ, struct OutputStream *Stream)
|
2009-04-23 21:02:25 -04:00
|
|
|
{
|
|
|
|
switch (Typ->Base)
|
|
|
|
{
|
2009-10-25 07:54:34 -04:00
|
|
|
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 TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
|
|
|
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
|
|
|
case TypeUnsignedChar: PrintStr("unsigned char", Stream); break;
|
2009-04-23 21:02:25 -04:00
|
|
|
#ifndef NO_FP
|
2009-10-25 07:54:34 -04:00
|
|
|
case TypeFP: PrintStr("double", Stream); break;
|
2009-04-23 21:02:25 -04:00
|
|
|
#endif
|
2009-10-25 07:54:34 -04:00
|
|
|
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) PrintInt(Typ->ArraySize, 0, FALSE, FALSE, 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 Type_Type: PrintStr("type ", Stream); break;
|
2009-04-23 21:02:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-20 21:35:52 -05:00
|
|
|
/* intrinsic functions made available to the language */
|
2009-04-27 00:56:58 -04:00
|
|
|
void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream)
|
2008-12-26 23:36:45 -05:00
|
|
|
{
|
2009-02-20 21:35:52 -05:00
|
|
|
char *FPos;
|
|
|
|
struct Value *NextArg = Param[0];
|
|
|
|
struct ValueType *FormatType;
|
|
|
|
int ArgCount = 1;
|
2009-10-23 15:01:32 -04:00
|
|
|
int LeftJustify = FALSE;
|
|
|
|
int ZeroPad = FALSE;
|
|
|
|
int FieldWidth = 0;
|
2009-05-05 20:25:09 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
|
|
|
char *Format;
|
|
|
|
struct Value *CharArray = Param[0]->Val->Pointer.Segment;
|
|
|
|
|
2009-03-15 03:07:21 -04:00
|
|
|
if (Param[0]->Val->Pointer.Offset < 0 || Param[0]->Val->Pointer.Offset >= CharArray->Val->Array.Size)
|
2009-02-20 21:35:52 -05:00
|
|
|
Format = StrEmpty;
|
|
|
|
else
|
2009-06-02 03:50:46 -04:00
|
|
|
Format = (char *)CharArray->Val->Array.Data + Param[0]->Val->Pointer.Offset;
|
2009-05-05 20:25:09 -04:00
|
|
|
#else
|
|
|
|
char *Format = Param[0]->Val->NativePointer;
|
2009-06-02 03:50:46 -04:00
|
|
|
/* XXX - dereference this properly */
|
2009-05-05 20:25:09 -04:00
|
|
|
#endif
|
2009-02-20 21:35:52 -05:00
|
|
|
|
|
|
|
for (FPos = Format; *FPos != '\0'; FPos++)
|
|
|
|
{
|
|
|
|
if (*FPos == '%')
|
|
|
|
{
|
|
|
|
FPos++;
|
2009-10-23 15:01:32 -04:00
|
|
|
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(*FPos))
|
|
|
|
FieldWidth = FieldWidth * 10 + (*FPos++ - '0');
|
|
|
|
|
|
|
|
/* now check the format type */
|
2009-02-20 21:35:52 -05:00
|
|
|
switch (*FPos)
|
|
|
|
{
|
|
|
|
case 's': FormatType = CharPtrType; break;
|
2009-06-15 11:08:05 -04:00
|
|
|
case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break;
|
2009-02-23 19:21:17 -05:00
|
|
|
#ifndef NO_FP
|
2009-02-20 21:35:52 -05:00
|
|
|
case 'f': FormatType = &FPType; break;
|
2009-02-23 19:21:17 -05:00
|
|
|
#endif
|
2009-04-27 00:56:58 -04:00
|
|
|
case '%': PrintCh('%', Stream); FormatType = NULL; break;
|
2009-02-20 21:35:52 -05:00
|
|
|
case '\0': FPos--; FormatType = NULL; break;
|
2009-04-27 00:56:58 -04:00
|
|
|
default: PrintCh(*FPos, Stream); FormatType = NULL; break;
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FormatType != NULL)
|
|
|
|
{ /* we have to format something */
|
|
|
|
if (ArgCount >= NumArgs)
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintStr("XXX", Stream); /* not enough parameters for format */
|
2009-02-20 21:35:52 -05:00
|
|
|
else
|
|
|
|
{
|
2009-06-02 03:50:46 -04:00
|
|
|
NextArg = (struct Value *)((char *)NextArg + sizeof(struct Value) + TypeStackSizeValue(NextArg));
|
2009-06-03 04:40:30 -04:00
|
|
|
if (NextArg->Typ != FormatType &&
|
|
|
|
!((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) &&
|
|
|
|
!(FormatType == CharPtrType && ( (NextArg->Typ->Base == TypePointer && NextArg->Typ->FromType->Base == TypeArray && NextArg->Typ->FromType->FromType->Base == TypeChar) ||
|
|
|
|
(NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) )
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintStr("XXX", Stream); /* bad type for format */
|
2009-02-20 21:35:52 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (*FPos)
|
|
|
|
{
|
|
|
|
case 's':
|
|
|
|
{
|
|
|
|
char *Str;
|
|
|
|
|
2009-06-03 20:18:28 -04:00
|
|
|
if (NextArg->Typ == CharPtrType || (NextArg->Typ->Base == TypePointer && NextArg->Typ->FromType->Base == TypeArray && NextArg->Typ->FromType->FromType->Base == TypeChar) )
|
2009-06-03 04:40:30 -04:00
|
|
|
{
|
2009-06-04 20:55:54 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
|
|
|
struct Value *CharArray = NextArg->Val->Pointer.Segment;
|
2009-06-03 04:40:30 -04:00
|
|
|
|
|
|
|
if (NextArg->Val->Pointer.Offset < 0 || NextArg->Val->Pointer.Offset >= CharArray->Val->Array.Size)
|
|
|
|
Str = StrEmpty;
|
|
|
|
else
|
|
|
|
Str = (char *)CharArray->Val->Array.Data + NextArg->Val->Pointer.Offset;
|
2009-06-04 20:55:54 -04:00
|
|
|
#else
|
|
|
|
Str = NextArg->Val->NativePointer;
|
|
|
|
#endif
|
2009-06-03 04:40:30 -04:00
|
|
|
}
|
2009-02-20 21:35:52 -05:00
|
|
|
else
|
2009-06-03 04:40:30 -04:00
|
|
|
Str = NextArg->Val->Array.Data;
|
2009-02-20 21:35:52 -05:00
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintStr(Str, Stream);
|
2009-02-20 21:35:52 -05:00
|
|
|
break;
|
|
|
|
}
|
2009-10-25 07:54:34 -04:00
|
|
|
case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
|
|
|
case 'u': PrintUnsigned((unsigned int)ExpressionCoerceInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
|
|
|
case 'x': PrintUnsigned((unsigned int)ExpressionCoerceInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
|
|
|
case 'b': PrintUnsigned((unsigned int)ExpressionCoerceInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break;
|
|
|
|
case 'c': PrintCh(ExpressionCoerceInteger(NextArg), Stream); break;
|
2009-02-23 19:21:17 -05:00
|
|
|
#ifndef NO_FP
|
2009-10-25 07:54:34 -04:00
|
|
|
case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break;
|
2009-02-23 19:21:17 -05:00
|
|
|
#endif
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ArgCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2009-04-27 00:56:58 -04:00
|
|
|
PrintCh(*FPos, Stream);
|
2009-02-20 21:35:52 -05:00
|
|
|
}
|
2008-12-26 23:36:45 -05:00
|
|
|
}
|
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
/* 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;
|
|
|
|
struct Value *DerefVal;
|
|
|
|
int DerefOffset;
|
2009-06-04 20:55:54 -04:00
|
|
|
StrStream.i.Str.WritePos = VariableDereferencePointer(StrStream.i.Str.Parser, Param[0], &DerefVal, &DerefOffset, NULL, NULL);
|
2009-04-27 00:56:58 -04:00
|
|
|
|
|
|
|
if (DerefVal->Typ->Base != TypeArray)
|
|
|
|
ProgramFail(Parser, "can only print to arrays of char");
|
|
|
|
|
|
|
|
StrStream.Putch = &SPutc;
|
|
|
|
StrStream.i.Str.Parser = Parser;
|
2009-10-23 15:01:32 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
2009-06-04 20:55:54 -04:00
|
|
|
StrStream.i.Str.MaxPos = StrStream.i.Str.WritePos - DerefOffset + DerefVal->Val->Array.Size;
|
2009-10-23 15:01:32 -04:00
|
|
|
#endif
|
2009-04-27 00:56:58 -04:00
|
|
|
GenericPrintf(Parser, ReturnValue, Param+1, NumArgs-1, &StrStream);
|
|
|
|
PrintCh(0, &StrStream);
|
2009-05-05 20:25:09 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
2009-04-27 00:56:58 -04:00
|
|
|
ReturnValue->Val->Pointer.Segment = *Param;
|
|
|
|
ReturnValue->Val->Pointer.Offset = 0;
|
2009-05-05 20:25:09 -04:00
|
|
|
#else
|
|
|
|
ReturnValue->Val->NativePointer = *Param;
|
|
|
|
#endif
|
2009-04-27 00:56:58 -04:00
|
|
|
}
|
|
|
|
|
2009-03-15 05:57:19 -04:00
|
|
|
/* get a line of input. protected from buffer overrun */
|
2009-03-15 03:07:21 -04:00
|
|
|
void LibGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-05 20:25:09 -04:00
|
|
|
#ifndef NATIVE_POINTERS
|
2009-03-15 05:57:19 -04:00
|
|
|
struct Value *CharArray = Param[0]->Val->Pointer.Segment;
|
2009-06-02 03:50:46 -04:00
|
|
|
char *ReadBuffer = (char *)CharArray->Val->Array.Data + Param[0]->Val->Pointer.Offset;
|
2009-03-15 05:57:19 -04:00
|
|
|
int MaxLength = CharArray->Val->Array.Size - Param[0]->Val->Pointer.Offset;
|
|
|
|
char *Result;
|
|
|
|
|
2009-04-27 00:56:58 -04:00
|
|
|
ReturnValue->Val->Pointer.Segment = NULL;
|
2009-03-15 05:57:19 -04:00
|
|
|
ReturnValue->Val->Pointer.Offset = 0;
|
|
|
|
|
|
|
|
if (Param[0]->Val->Pointer.Offset < 0 || MaxLength < 0)
|
|
|
|
return; /* no room for data */
|
|
|
|
|
|
|
|
Result = PlatformGetLine(ReadBuffer, MaxLength);
|
|
|
|
if (Result == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ReturnValue->Val->Pointer = Param[0]->Val->Pointer;
|
2009-05-05 20:25:09 -04:00
|
|
|
#else
|
|
|
|
struct Value *CharArray = (struct Value *)(Param[0]->Val->NativePointer);
|
|
|
|
char *ReadBuffer = CharArray->Val->Array.Data;
|
|
|
|
char *Result;
|
|
|
|
|
|
|
|
ReturnValue->Val->NativePointer = NULL;
|
2009-10-23 15:01:32 -04:00
|
|
|
Result = PlatformGetLine(ReadBuffer, GETS_BUF_MAX);
|
2009-05-05 20:25:09 -04:00
|
|
|
if (Result == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ReturnValue->Val->NativePointer = Param[0]->Val->NativePointer;
|
|
|
|
#endif
|
2009-03-15 03:07:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibGetc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-03-15 05:57:19 -04:00
|
|
|
ReturnValue->Val->Integer = PlatformGetCharacter();
|
2009-03-15 03:07:21 -04:00
|
|
|
}
|
|
|
|
|
2009-06-15 10:33:21 -04:00
|
|
|
void LibExit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
|
|
|
PlatformExit();
|
|
|
|
}
|
|
|
|
|
2009-05-28 20:12:12 -04:00
|
|
|
#ifdef PICOC_MATH_LIBRARY
|
2009-05-27 00:55:44 -04:00
|
|
|
void LibSin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_sin(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibCos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_cos(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibTan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_tan(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibAsin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_asin(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibAcos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_acos(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibAtan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_atan(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibSinh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_sinh(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibCosh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_cosh(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibTanh(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_tanh(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibExp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_exp(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
2009-05-28 20:12:12 -04:00
|
|
|
void LibFabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
2009-05-27 00:55:44 -04:00
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_fabs(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibLog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_log(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibLog10(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_log10(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibPow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_pow(Param[0]->Val->FP, Param[1]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibSqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_sqrt(Param[0]->Val->FP);
|
2009-05-27 00:55:44 -04:00
|
|
|
}
|
2009-05-28 04:22:24 -04:00
|
|
|
|
|
|
|
void LibRound(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-06-02 03:50:46 -04:00
|
|
|
ReturnValue->Val->FP = math_floor(Param[0]->Val->FP + 0.5); /* XXX - fix for soft float */
|
2009-05-28 04:22:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibCeil(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_ceil(Param[0]->Val->FP);
|
2009-05-28 04:22:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibFloor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
2009-05-28 20:12:12 -04:00
|
|
|
ReturnValue->Val->FP = math_floor(Param[0]->Val->FP);
|
2009-05-28 04:22:24 -04:00
|
|
|
}
|
2009-05-27 00:55:44 -04:00
|
|
|
#endif
|
|
|
|
|
2009-10-25 16:50:56 -04:00
|
|
|
#ifdef NATIVE_POINTERS
|
|
|
|
void LibMalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
|
|
|
ReturnValue->Val->NativePointer = malloc(Param[0]->Val->Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibCalloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
|
|
|
ReturnValue->Val->NativePointer = calloc(Param[0]->Val->Integer, Param[1]->Val->Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibRealloc(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
|
|
|
ReturnValue->Val->NativePointer = realloc(Param[0]->Val->NativePointer, Param[1]->Val->Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LibFree(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
|
|
{
|
|
|
|
free(Param[0]->Val->NativePointer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-02-24 06:16:37 -05:00
|
|
|
/* list of all library functions and their prototypes */
|
|
|
|
struct LibraryFunction CLibrary[] =
|
2008-12-26 23:36:45 -05:00
|
|
|
{
|
2009-02-24 06:16:37 -05:00
|
|
|
{ LibPrintf, "void printf(char *, ...)" },
|
2009-04-27 00:56:58 -04:00
|
|
|
{ LibSPrintf, "char *sprintf(char *, char *, ...)" },
|
2009-03-15 03:07:21 -04:00
|
|
|
{ LibGets, "void gets(char *, int)" },
|
2009-03-15 05:57:19 -04:00
|
|
|
{ LibGetc, "int getchar()" },
|
2009-06-15 10:33:21 -04:00
|
|
|
{ LibExit, "void exit()" },
|
2009-05-28 20:12:12 -04:00
|
|
|
#ifdef PICOC_MATH_LIBRARY
|
2009-05-27 00:55:44 -04:00
|
|
|
{ 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)" },
|
2009-05-28 20:12:12 -04:00
|
|
|
{ LibFabs, "float fabs(float)" },
|
2009-05-27 00:55:44 -04:00
|
|
|
{ LibLog, "float log(float)" },
|
|
|
|
{ LibLog10, "float log10(float)" },
|
|
|
|
{ LibPow, "float pow(float,float)" },
|
|
|
|
{ LibSqrt, "float sqrt(float)" },
|
2009-05-28 04:22:24 -04:00
|
|
|
{ LibRound, "float round(float)" },
|
|
|
|
{ LibCeil, "float ceil(float)" },
|
|
|
|
{ LibFloor, "float floor(float)" },
|
2009-10-25 16:50:56 -04:00
|
|
|
#endif
|
|
|
|
#ifdef NATIVE_POINTERS
|
|
|
|
{ LibMalloc, "void *malloc(int)" },
|
|
|
|
{ LibCalloc, "void *calloc(int,int)" },
|
|
|
|
{ LibCalloc, "void *realloc(void *,int)" },
|
|
|
|
{ LibFree, "void free(void *)" },
|
2009-05-27 00:55:44 -04:00
|
|
|
#endif
|
2009-02-24 06:16:37 -05:00
|
|
|
{ NULL, NULL }
|
2008-12-26 23:36:45 -05:00
|
|
|
};
|