[DEV] basic repo

This commit is contained in:
Edouard DUPIN 2014-01-16 21:52:25 +01:00
commit dd444af28f
140 changed files with 14043 additions and 0 deletions

55
Makefile Normal file
View File

@ -0,0 +1,55 @@
CC=gcc
CFLAGS=-Wall -pedantic -g -DUNIX_HOST
LIBS=-lm -lreadline
TARGET = picoc
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
variable.c clibrary.c platform.c include.c \
platform/platform_unix.c platform/library_unix.c \
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.c \
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
cstdlib/unistd.c
OBJS := $(SRCS:%.c=%.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
test: all
(cd tests; make test)
clean:
rm -f $(TARGET) $(OBJS) *~
count:
@echo "Core:"
@cat picoc.h interpreter.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c include.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
@echo ""
@echo "Everything:"
@cat $(SRCS) *.h */*.h | wc
.PHONY: clibrary.c
picoc.o: picoc.c picoc.h
table.o: table.c interpreter.h platform.h
lex.o: lex.c interpreter.h platform.h
parse.o: parse.c picoc.h interpreter.h platform.h
expression.o: expression.c interpreter.h platform.h
heap.o: heap.c interpreter.h platform.h
type.o: type.c interpreter.h platform.h
variable.o: variable.c interpreter.h platform.h
clibrary.o: clibrary.c picoc.h interpreter.h platform.h
platform.o: platform.c picoc.h interpreter.h platform.h
include.o: include.c picoc.h interpreter.h platform.h
platform/platform_unix.o: platform/platform_unix.c picoc.h interpreter.h platform.h
platform/library_unix.o: platform/library_unix.c interpreter.h platform.h
cstdlib/stdio.o: cstdlib/stdio.c interpreter.h platform.h
cstdlib/math.o: cstdlib/math.c interpreter.h platform.h
cstdlib/string.o: cstdlib/string.c interpreter.h platform.h
cstdlib/stdlib.o: cstdlib/stdlib.c interpreter.h platform.h
cstdlib/time.o: cstdlib/time.c interpreter.h platform.h
cstdlib/errno.o: cstdlib/errno.c interpreter.h platform.h
cstdlib/ctype.o: cstdlib/ctype.c interpreter.h platform.h
cstdlib/stdbool.o: cstdlib/stdbool.c interpreter.h platform.h
cstdlib/unistd.o: cstdlib/unistd.c interpreter.h platform.h

91
README Normal file
View File

@ -0,0 +1,91 @@
picoc
-----
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.
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.

676
clibrary.c Normal file
View File

@ -0,0 +1,676 @@
#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 */

110
cstdlib/ctype.c Normal file
View File

@ -0,0 +1,110 @@
/* string.h library for large systems - small embedded systems use clibrary.c instead */
#include <ctype.h>
#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 */

655
cstdlib/errno.c Normal file
View File

@ -0,0 +1,655 @@
/* string.h library for large systems - small embedded systems use clibrary.c instead */
#include <errno.h>
#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 */

187
cstdlib/math.c Normal file
View File

@ -0,0 +1,187 @@
/* 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 */

22
cstdlib/stdbool.c Normal file
View File

@ -0,0 +1,22 @@
/* 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 */

722
cstdlib/stdio.c Normal file
View File

@ -0,0 +1,722 @@
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
#include <errno.h>
#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 */

174
cstdlib/stdlib.c Normal file
View File

@ -0,0 +1,174 @@
/* 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 */

178
cstdlib/string.c Normal file
View File

@ -0,0 +1,178 @@
/* 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 */

124
cstdlib/time.c Normal file
View File

@ -0,0 +1,124 @@
/* string.h library for large systems - small embedded systems use clibrary.c instead */
#include <time.h>
#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 */

499
cstdlib/unistd.c Normal file
View File

@ -0,0 +1,499 @@
/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#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 */

1501
expression.c Normal file

File diff suppressed because it is too large Load Diff

285
heap.c Normal file
View File

@ -0,0 +1,285 @@
/* 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
}

110
include.c Normal file
View File

@ -0,0 +1,110 @@
#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 */

499
interpreter.h Normal file
View File

@ -0,0 +1,499 @@
#ifndef INTERPRETER_H
#define INTERPRETER_H
#include "platform.h"
/* handy definitions */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
#define MEM_ALIGN(x) (((x) + sizeof(ALIGN_TYPE) - 1) & ~(sizeof(ALIGN_TYPE)-1))
#define GETS_BUF_MAX 256
/* 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;
#endif
/* coercion of numeric types to other numeric types */
#ifndef NO_FP
#define IS_FP(v) ((v)->Typ->Base == TypeFP)
#define FP_VAL(v) ((v)->Val->FP)
#else
#define IS_FP(v) 0
#define FP_VAL(v) 0
#endif
#define IS_POINTER_COERCIBLE(v, ap) ((ap) ? ((v)->Typ->Base == TypePointer) : 0)
#define POINTER_COERCE(v) ((int)(v)->Val->Pointer)
#define IS_INTEGER_NUMERIC_TYPE(t) ((t)->Base >= TypeInt && (t)->Base <= TypeUnsignedLong)
#define IS_INTEGER_NUMERIC(v) IS_INTEGER_NUMERIC_TYPE((v)->Typ)
#define IS_NUMERIC_COERCIBLE(v) (IS_INTEGER_NUMERIC(v) || IS_FP(v))
#define IS_NUMERIC_COERCIBLE_PLUS_POINTERS(v,ap) (IS_NUMERIC_COERCIBLE(v) || IS_POINTER_COERCIBLE(v,ap))
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
};
/* used in dynamic memory allocation */
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 */
};
/* 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;
};
/* 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 */
#ifndef NO_FP
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 */
};
/* 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 */
};
/* 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 */
};
/* 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 */
};
/* 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;
#ifndef NO_FP
double FP;
#endif
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 */
};
/* 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 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 */
};
/* lexer state */
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;
};
/* library function definition */
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;
};
/* 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;
};
/* possible results of parsing a statement */
enum ParseResult { ParseResultEOF, ParseResultError, ParseResultOk };
/* globals */
extern void *HeapStackTop;
extern struct Table GlobalTable;
extern struct StackFrame *TopStackFrame;
extern struct ValueType UberType;
extern struct ValueType IntType;
extern struct ValueType CharType;
#ifndef NO_FP
extern struct ValueType FPType;
#endif
extern struct ValueType VoidType;
extern struct ValueType TypeType;
extern struct ValueType FunctionType;
extern struct ValueType MacroType;
extern struct ValueType GotoLabelType;
extern struct ValueType *CharPtrType;
extern struct ValueType *CharPtrPtrType;
extern struct ValueType *CharArrayType;
extern struct ValueType *VoidPtrType;
extern char *StrEmpty;
extern struct PointerValue NULLPointer;
extern struct LibraryFunction CLibrary[];
extern struct LibraryFunction PlatformLibrary[];
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);
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);
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen);
void TableStrFree();
/* lex.c */
void LexInit();
void LexCleanup();
void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen);
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt);
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos);
enum LexToken LexRawPeekToken(struct ParseState *Parser);
void LexToEndOfLine(struct ParseState *Parser);
void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser);
void LexInteractiveClear(struct ParseState *Parser);
void LexInteractiveCompleted(struct ParseState *Parser);
void LexInteractiveStatementPrompt();
/* parse.c */
/* the following are defined in picoc.h:
* void PicocParse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource);
* void PicocParseInteractive(); */
enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon);
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier);
void ParseCleanup();
void ParserCopyPos(struct ParseState *To, struct ParseState *From);
void ParserCopy(struct ParseState *To, struct ParseState *From);
/* expression.c */
int ExpressionParse(struct ParseState *Parser, struct Value **Result);
long ExpressionParseInt(struct ParseState *Parser);
void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct Value *SourceValue, int Force, const char *FuncName, int ParamNo, int AllowPointerCoercion);
long ExpressionCoerceInteger(struct Value *Val);
unsigned long ExpressionCoerceUnsignedInteger(struct Value *Val);
#ifndef NO_FP
double ExpressionCoerceFP(struct Value *Val);
#endif
/* type.c */
void TypeInit();
void TypeCleanup();
int TypeSize(struct ValueType *Typ, int ArraySize, int Compact);
int TypeSizeValue(struct Value *Val, int Compact);
int TypeStackSizeValue(struct Value *Val);
int TypeLastAccessibleOffset(struct Value *Val);
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsStatic);
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier, int *IsStatic);
struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates);
struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size);
/* heap.c */
void HeapInit(int StackSize);
void HeapCleanup();
void *HeapAllocStack(int Size);
int HeapPopStack(void *Addr, int Size);
void HeapUnpopStack(int Size);
void HeapPushStackFrame();
int HeapPopStackFrame();
void *HeapAllocMem(int Size);
void HeapFreeMem(void *Mem);
/* variable.c */
void VariableInit();
void VariableCleanup();
void VariableFree(struct Value *Val);
void VariableTableCleanup(struct Table *HashTable);
void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap);
void VariableStackPop(struct ParseState *Parser, struct Value *Var);
struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap);
struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap);
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap);
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue, struct Value *LValueFrom);
struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *FromValue);
struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable);
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit);
int VariableDefined(const char *Ident);
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal);
void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable);
void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams);
void VariableStackFramePop(struct ParseState *Parser);
struct Value *VariableStringLiteralGet(char *Ident);
void VariableStringLiteralDefine(char *Ident, struct Value *Val);
void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue);
/* clibrary.c */
void BasicIOInit();
void LibraryInit();
void LibraryAdd(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction *FuncList);
void CLibraryInit();
void PrintCh(char OutCh, IOFILE *Stream);
void PrintSimpleInt(long Num, IOFILE *Stream);
void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, IOFILE *Stream);
void PrintStr(const char *Str, IOFILE *Stream);
void PrintFP(double Num, IOFILE *Stream);
void PrintType(struct ValueType *Typ, IOFILE *Stream);
void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs);
/* platform.c */
/* the following are defined in picoc.h:
* void PicocCallMain(int argc, char **argv);
* int PicocPlatformSetExitPoint();
* void PicocInitialise(int StackSize);
* void PicocCleanup();
* void PicocPlatformScanFile(const char *FileName);
* extern int PicocExitValue; */
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo);
void LexFail(struct LexState *Lexer, const char *Message, ...);
void PlatformCleanup();
char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt);
int PlatformGetCharacter();
void PlatformPutc(unsigned char OutCh, union OutputStreamInfo *);
void PlatformErrorPrefix(struct ParseState *Parser);
void PlatformPrintf(const char *Format, ...);
void PlatformVPrintf(const char *Format, va_list Args);
void PlatformExit(int ExitVal);
char *PlatformMakeTempName(char *TempNameBuffer);
void PlatformLibraryInit();
/* include.c */
void IncludeInit();
void IncludeCleanup();
void IncludeRegister(const char *IncludeName, void (*SetupFunction)(void), struct LibraryFunction *FuncList, const char *SetupCSource);
void IncludeFile(char *Filename);
/* the following is defined in picoc.h:
* void PicocIncludeAllSystemHeaders(); */
/* stdio.c */
extern const char StdioDefs[];
extern struct LibraryFunction StdioFunctions[];
void StdioSetupFunc(void);
/* math.c */
extern struct LibraryFunction MathFunctions[];
void MathSetupFunc(void);
/* string.c */
extern struct LibraryFunction StringFunctions[];
void StringSetupFunc(void);
/* stdlib.c */
extern struct LibraryFunction StdlibFunctions[];
void StdlibSetupFunc(void);
/* time.c */
extern const char StdTimeDefs[];
extern struct LibraryFunction StdTimeFunctions[];
void StdTimeSetupFunc(void);
/* errno.c */
void StdErrnoSetupFunc(void);
/* ctype.c */
extern struct LibraryFunction StdCtypeFunctions[];
/* stdbool.c */
extern const char StdboolDefs[];
void StdboolSetupFunc(void);
/* unistd.c */
extern const char UnistdDefs[];
extern struct LibraryFunction UnistdFunctions[];
void UnistdSetupFunc(void);
#endif /* INTERPRETER_H */

971
lex.c Normal file
View File

@ -0,0 +1,971 @@
#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;
}

872
parse.c Normal file
View File

@ -0,0 +1,872 @@
#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");
}

101
picoc.c Normal file
View File

@ -0,0 +1,101 @@
/* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 <csource1.c>... [- <arg1>...] : run a program (calls main() to start it)\n"
" picoc -s <csource1.c>... [- <arg1>...] : 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 <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;
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

46
picoc.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef PICOC_H
#define PICOC_H
/* picoc version number */
#define PICOC_VERSION "v2.1"
/* handy definitions */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifdef UNIX_HOST
#include <setjmp.h>
/* mark where to end the program for platforms which require this */
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);
void PicocParseInteractive();
/* platform.c */
void PicocCallMain(int argc, char **argv);
void PicocInitialise(int StackSize);
void PicocCleanup();
void PicocPlatformScanFile(const char *FileName);
extern int PicocExitValue;
/* include.c */
void PicocIncludeAllSystemHeaders();
#endif /* PICOC_H */

236
platform.c Normal file
View File

@ -0,0 +1,236 @@
#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);
}

125
platform.h Normal file
View File

@ -0,0 +1,125 @@
/* 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 <stdio.h>
# include <stdlib.h>
# include <ctype.h>
# include <string.h>
# include <assert.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <stdarg.h>
# include <setjmp.h>
# ifndef NO_FP
# include <math.h>
# 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 <stdlib.h>
# include <ctype.h>
# include <string.h>
# include <sys/types.h>
# include <stdarg.h>
# include <setjmp.h>
# include <math.h>
# 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 <cdefBF537.h>
# 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 <stdlib.h>
# include <string.h>
# include <ctype.h>
# include <sys/types.h>
# include <stdarg.h>
# include <math.h>
# 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 */

13
platform/library_ffox.c Normal file
View File

@ -0,0 +1,13 @@
#include "../interpreter.h"
/* list of all library functions and their prototypes */
struct LibraryFunction PlatformLibrary[] =
{
{ NULL, NULL }
};
void PlatformLibraryInit()
{
LibraryAdd(&GlobalTable, "platform library", &PlatformLibrary);
}

809
platform/library_srv1.c Normal file
View File

@ -0,0 +1,809 @@
#include "../interpreter.h"
static int Blobcnt, Blobx1, Blobx2, Bloby1, Bloby2, Iy1, Iy2, Iu1, Iu2, Iv1, Iv2;
static int GPSlat, GPSlon, GPSalt, GPSfix, GPSsat, GPSutc, Elcount, Ercount;
static int ScanVect[16], NNVect[NUM_OUTPUT];
struct ValueType *IntArrayType;
void SRV1SetupFunc()
{
IntArrayType = TypeGetMatching(NULL, &IntType, TypeArray, 16, StrEmpty, TRUE);
VariableDefinePlatformVar(NULL, "scanvect", IntArrayType, (union AnyValue *)&ScanVect, FALSE);
VariableDefinePlatformVar(NULL, "neuron", IntArrayType, (union AnyValue *)&NNVect, FALSE);
VariableDefinePlatformVar(NULL, "blobcnt", &IntType, (union AnyValue *)&Blobcnt, FALSE);
VariableDefinePlatformVar(NULL, "blobx1", &IntType, (union AnyValue *)&Blobx1, FALSE);
VariableDefinePlatformVar(NULL, "blobx2", &IntType, (union AnyValue *)&Blobx2, FALSE);
VariableDefinePlatformVar(NULL, "bloby1", &IntType, (union AnyValue *)&Bloby1, FALSE);
VariableDefinePlatformVar(NULL, "bloby2", &IntType, (union AnyValue *)&Bloby2, FALSE);
VariableDefinePlatformVar(NULL, "lcount", &IntType, (union AnyValue *)&Elcount, FALSE);
VariableDefinePlatformVar(NULL, "rcount", &IntType, (union AnyValue *)&Ercount, FALSE);
VariableDefinePlatformVar(NULL, "y1", &IntType, (union AnyValue *)&Iy1, FALSE);
VariableDefinePlatformVar(NULL, "y2", &IntType, (union AnyValue *)&Iy2, FALSE);
VariableDefinePlatformVar(NULL, "u1", &IntType, (union AnyValue *)&Iu1, FALSE);
VariableDefinePlatformVar(NULL, "u2", &IntType, (union AnyValue *)&Iu2, FALSE);
VariableDefinePlatformVar(NULL, "v1", &IntType, (union AnyValue *)&Iv1, FALSE);
VariableDefinePlatformVar(NULL, "v2", &IntType, (union AnyValue *)&Iv2, FALSE);
VariableDefinePlatformVar(NULL, "gpslat", &IntType, (union AnyValue *)&GPSlat, FALSE);
VariableDefinePlatformVar(NULL, "gpslon", &IntType, (union AnyValue *)&GPSlon, FALSE);
VariableDefinePlatformVar(NULL, "gpsalt", &IntType, (union AnyValue *)&GPSalt, FALSE);
VariableDefinePlatformVar(NULL, "gpsfix", &IntType, (union AnyValue *)&GPSfix, FALSE);
VariableDefinePlatformVar(NULL, "gpssat", &IntType, (union AnyValue *)&GPSsat, FALSE);
VariableDefinePlatformVar(NULL, "gpsutc", &IntType, (union AnyValue *)&GPSutc, FALSE);
}
void Csignal(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // check for kbhit, return t or nil
{
if (getsignal())
ReturnValue->Val->Integer = 1;
else
ReturnValue->Val->Integer = 0;
}
void Cinput(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
ReturnValue->Val->Integer = getch();
}
void Cdelay(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int del;
del = Param[0]->Val->Integer;
if ((del < 0) || (del > 1000000))
return;
delayMS(del);
}
void Crand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (int)rand() % (unsigned int)(Param[0]->Val->Integer + 1);
}
void Ctime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (int)readRTC();
}
void Ciodir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int dir;
dir = Param[0]->Val->Integer;
*pPORTHIO_DIR = ((dir << 10) & 0xFC00) + (*pPORTHIO_DIR & 0x03FF); // H15/14/13/12/11/10 - 1=output, 0=input
*pPORTHIO_INEN = (((~dir) << 10) & 0xFC00) + (*pPORTHIO_INEN & 0x03FF); // invert dir bits to enable inputs
}
void Cioread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (*pPORTHIO >> 10) & 0x003F;
}
void Ciowrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
*pPORTHIO = ((Param[0]->Val->Integer << 10) & 0xFC00) + (*pPORTHIO & 0x03FF);
}
void Cpeek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int size, ptr;
unsigned char *cp;
unsigned short *sp;
unsigned int *ip;
/* x = peek(addr, size);
mask ptr to align with word size */
ptr = Param[0]->Val->Integer;
size = Param[1]->Val->Integer;
switch (size) {
case 1: // char *
cp = (unsigned char *)ptr;
ReturnValue->Val->Integer = (int)((unsigned int)*cp);
break;
case 2: // short *
sp = (unsigned short *)(ptr & 0xFFFFFFFE); // align with even boundary
ReturnValue->Val->Integer = (int)((unsigned short)*sp);
break;
case 4: // int *
ip = (unsigned int *)(ptr & 0xFFFFFFFC); // aling with quad boundary
ReturnValue->Val->Integer = (int)*ip;
break;
default:
ReturnValue->Val->Integer = 0;
break;
}
}
void Cpoke(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int size, ptr, val;
unsigned char *cp;
unsigned short *sp;
unsigned int *ip;
/* x = poke(addr, size, val);
mask ptr to align with word size */
ptr = Param[0]->Val->Integer;
size = Param[1]->Val->Integer;
val = Param[2]->Val->Integer;
switch (size) {
case 1: // char *
cp = (unsigned char *)ptr;
*cp = (unsigned char)(val & 0x000000FF);
break;
case 2: // short *
sp = (unsigned short *)(ptr & 0xFFFFFFFE);
*sp = (unsigned short)(val & 0x0000FFFF);
break;
case 4: // int *
ip = (unsigned int *)(ptr & 0xFFFFFFFC);
*ip = val;
break;
default: // don't bother with bad value
break;
}
}
void Cencoders(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
unsigned int ix;
ix = encoders(); // read left and right encoders; save data to C globals lcount, rcount
Elcount = (ix >> 16) & 0x0000FFFF;
Ercount = ix & 0x0000FFFF;
}
void Cmotors(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
lspeed = Param[0]->Val->Integer;
if ((lspeed < -100) || (lspeed > 100))
ProgramFail(NULL, "motors(): left motor value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < -100) || (rspeed > 100))
ProgramFail(NULL, "motors(): right motor value out of range");
if (!pwm1_init) {
initPWM();
pwm1_init = 1;
pwm1_mode = PWM_PWM;
base_speed = 50;
}
setPWM(lspeed, rspeed);
}
void Cmotors2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
lspeed2 = Param[0]->Val->Integer;
if ((lspeed2 < -100) || (lspeed2 > 100))
ProgramFail(NULL, "motors2(): left motor value out of range");
rspeed2 = Param[1]->Val->Integer;
if ((rspeed2 < -100) || (rspeed2 > 100))
ProgramFail(NULL, "motors2(): right motor value out of range");
if (!pwm2_init) {
initPWM2();
pwm2_init = 1;
pwm2_mode = PWM_PWM;
base_speed2 = 50;
}
setPWM2(lspeed2, rspeed2);
}
void Cservos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int lspeed, rspeed;
lspeed = Param[0]->Val->Integer;
if ((lspeed < 0) || (lspeed > 100))
ProgramFail(NULL, "servos(): TMR2 value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < 0) || (rspeed > 100))
ProgramFail(NULL, "servos()(): TMR3 value out of range");
if (!pwm1_init) {
initPPM1();
pwm1_init = 1;
pwm1_mode = PWM_PPM;
}
setPPM1(lspeed, rspeed);
}
void Cservos2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int lspeed, rspeed;
lspeed = Param[0]->Val->Integer;
if ((lspeed < 0) || (lspeed > 100))
ProgramFail(NULL, "servos2(): TMR6 value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < 0) || (rspeed > 100))
ProgramFail(NULL, "servos2(): TMR7 value out of range");
if (!pwm2_init) {
initPPM2();
pwm2_init = 1;
pwm2_mode = PWM_PPM;
}
setPPM2(lspeed, rspeed);
}
void Claser(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // laser(1) turns them on, laser(0) turns them off
{
*pPORTHIO &= 0xFD7F; // turn off both lasers
switch (Param[0]->Val->Integer) {
case 1:
*pPORTHIO |= 0x0080; // turn on left laser
break;
case 2:
*pPORTHIO |= 0x0200; // turn on right laser
break;
case 3:
*pPORTHIO |= 0x0280; // turn on both lasers
break;
}
}
void Csonar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // read sonar module
{
unsigned int i;
i = Param[0]->Val->Integer;
if ((i<1) || (i>4)) {
ProgramFail(NULL, "sonar(): 1, 2, 3, 4 are only valid selections");
}
sonar();
ReturnValue->Val->Integer = sonar_data[i] / 100;
}
void Crange(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = laser_range(0);
}
void Cbattery(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
if (*pPORTHIO & 0x0004)
ReturnValue->Val->Integer = 0; // low battery voltage detected
else
ReturnValue->Val->Integer = 1; // battery voltage okay
}
void Cvcolor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set color bin -
// vcolor (color, ymin, ymax, umin, umax, vmin, vmax);
{
int ix;
ix = Param[0]->Val->Integer;
ymin[ix] = Param[1]->Val->Integer;
ymax[ix] = Param[2]->Val->Integer;
umin[ix] = Param[3]->Val->Integer;
umax[ix] = Param[4]->Val->Integer;
vmin[ix] = Param[5]->Val->Integer;
vmax[ix] = Param[6]->Val->Integer;
}
void Cvcam(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set camera functions -
// enable/disable AGC(4) / AWB(2) / AEC(1) camera controls
// vcam(7) = AGC+AWB+AEC on vcam(0) = AGC+AWB+AEC off
{
unsigned char cx, i2c_data[2];
cx = (unsigned char)Param[0]->Val->Integer & 0x07;
i2c_data[0] = 0x13;
i2c_data[1] = 0xC0 + cx;
i2cwrite(0x30, (unsigned char *)i2c_data, 1, SCCB_ON); // OV9655
i2cwrite(0x21, (unsigned char *)i2c_data, 1, SCCB_ON); // OV7725
}
void Cvfind(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set color bin -
// vfind (color, x1, x2, y1, y2);
{
int ix, x1, x2, y1, y2;
ix = Param[0]->Val->Integer;
x1 = Param[1]->Val->Integer;
x2 = Param[2]->Val->Integer;
y1 = Param[3]->Val->Integer;
y2 = Param[4]->Val->Integer;
ReturnValue->Val->Integer = vfind((unsigned char *)FRAME_BUF, ix, x1, x2, y1, y2);
}
void Cvcap(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
grab_frame(); // capture frame for processing
}
void Cvrcap(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
grab_reference_frame(); // capture reference frame for differencing
}
void Cvdiff(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
frame_diff_flag = Param[0]->Val->Integer; // set/clear frame_diff_flag
}
void Cvpix(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int x, y, ix;
x = Param[0]->Val->Integer;
y = Param[1]->Val->Integer;
ix = vpix((unsigned char *)FRAME_BUF, x, y);
Iy1 = ((ix>>16) & 0x000000FF); // Y1
Iu1 = ((ix>>24) & 0x000000FF); // U
Iv1 = ((ix>>8) & 0x000000FF); // V
}
void Cvscan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int col, thresh, ix;
col = Param[0]->Val->Integer;
if ((col < 1) || (col > 9))
ProgramFail(NULL, "vscan(): number of columns must be between 1 and 9");
thresh = Param[1]->Val->Integer;
if ((thresh < 0) || (thresh > 9999))
ProgramFail(NULL, "vscan(): threshold must be between 0 and 9999");
ix = vscan((unsigned char *)SPI_BUFFER1, (unsigned char *)FRAME_BUF, thresh, (unsigned int)col, (unsigned int *)&ScanVect[0]);
ReturnValue->Val->Integer = ix;
}
void Cvmean(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
vmean((unsigned char *)FRAME_BUF);
Iy1 = mean[0];
Iu1 = mean[1];
Iv1 = mean[2];
}
// search for blob by color, index; return center point X,Y and width Z
void Cvblob(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, iblob, numblob;
ix = Param[0]->Val->Integer;
if (ix > MAX_COLORS)
ProgramFail(NULL, "blob(): invalid color index");
iblob = Param[1]->Val->Integer;
if (iblob > MAX_BLOBS)
ProgramFail(NULL, "blob(): invalid blob index");
numblob = vblob((unsigned char *)FRAME_BUF, (unsigned char *)FRAME_BUF3, ix);
if ((blobcnt[iblob] == 0) || (numblob == -1)) {
Blobcnt = 0;
} else {
Blobcnt = blobcnt[iblob];
Blobx1 = blobx1[iblob];
Blobx2 = blobx2[iblob];
Bloby1 = bloby1[iblob];
Bloby2 = bloby2[iblob];
}
ReturnValue->Val->Integer = numblob;
}
void Cvjpeg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
unsigned int image_size, qual;
unsigned char *output_start, *output_end;
qual = Param[0]->Val->Integer;
if ((qual < 1) || (qual > 8))
ProgramFail(NULL, "vjpeg(): quality parameter out of range");
output_start = (unsigned char *)JPEG_BUF;
output_end = encode_image((unsigned char *)FRAME_BUF, output_start, qual,
FOUR_TWO_TWO, imgWidth, imgHeight);
image_size = (unsigned int)(output_end - output_start);
ReturnValue->Val->Integer = image_size;
}
void Cvsend (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
unsigned int ix, image_size;
unsigned char *cp;
image_size = Param[0]->Val->Integer;
if ((image_size < 0) || (image_size > 200000))
ProgramFail(NULL, "vsend(): image size out of range");
led1_on();
cp = (unsigned char *)JPEG_BUF;
for (ix=0; ix<image_size; ix++)
putchar(*cp++);
led0_on();
}
void Ccompass(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned char i2c_data[2];
unsigned int ix;
i2c_data[0] = 0x41; // read compass twice to clear last reading
i2cread(0x22, (unsigned char *)i2c_data, 2, SCCB_ON);
delayMS(20);
i2c_data[0] = 0x41;
i2cread(0x22, (unsigned char *)i2c_data, 2, SCCB_ON);
ix = ((unsigned int)(i2c_data[0] << 8) + i2c_data[1]) / 10;
ReturnValue->Val->Integer = ix;
}
void Ctilt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned int ix;
ix = (unsigned int)Param[0]->Val->Integer;
if ((ix<1) || (ix>3))
ProgramFail(NULL, "tilt(): invalid channel");
ReturnValue->Val->Integer = tilt(ix);
}
void Canalog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned char i2c_data[3], device_id;
unsigned int ix, channel;
unsigned char mask1[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08 };
unsigned char mask2[] = { 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00 };
// decide which i2c device based on channel range
ix = (unsigned char)Param[0]->Val->Integer;
if ((ix<1) || (ix>28))
ProgramFail(NULL, "analog(): invalid channel");
device_id = 0;
switch (ix / 10) {
case 0:
device_id = 0x20; // channels 1-8
break;
case 1:
device_id = 0x23; // channels 11-18
break;
case 2:
device_id = 0x24; // channels 21-28
break;
}
channel = ix % 10;
if ((channel<1) || (channel>8))
ProgramFail(NULL, "analog(): invalid channel");
// set timer register 3
i2c_data[0] = 0x03;
i2c_data[1] = 0x01;
i2cwrite(device_id, (unsigned char *)i2c_data, 1, SCCB_ON);
// set analog channel
i2c_data[0] = 0x02;
i2c_data[1] = mask1[channel-1];
i2c_data[2] = mask2[channel-1];
i2cwritex(device_id, (unsigned char *)i2c_data, 3, SCCB_ON);
// small delay
delayUS(1000);
// read data
i2c_data[0] = 0x00;
i2cread(device_id, (unsigned char *)i2c_data, 2, SCCB_ON);
ix = (((i2c_data[0] & 0x0F) << 8) + i2c_data[1]);
ReturnValue->Val->Integer = ix;
}
void Cgps(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
gps_parse();
GPSlat = gps_gga.lat;
GPSlon = gps_gga.lon;
GPSalt = gps_gga.alt;
GPSfix = gps_gga.fix;
GPSsat = gps_gga.sat;
GPSutc = gps_gga.utc;
}
void Creadi2c(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax val = readi2c(device, register);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2cread(i2c_device, (unsigned char *)i2c_data, 1, SCCB_OFF);
ReturnValue->Val->Integer = ((int)i2c_data[0] & 0x000000FF);
}
void Creadi2c2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax two_byte_val = readi2c(device, register);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2cread(i2c_device, (unsigned char *)i2c_data, 2, SCCB_OFF);
ReturnValue->Val->Integer = (((unsigned int)i2c_data[0] << 8) + i2c_data[1]);
}
void Cwritei2c(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax writei2c(device, register, value);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2c_data[1] = (unsigned char)Param[2]->Val->Integer;
i2cwrite(i2c_device, (unsigned char *)i2c_data, 1, SCCB_OFF);
}
void Csin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // sin(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = sin(ix);
}
void Ccos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // cos(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = cos(ix);
}
void Ctan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // tan(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = tan(ix);
}
void Casin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // asin(y,hyp)
{
int y, hyp;
y = Param[0]->Val->Integer;
hyp = Param[1]->Val->Integer;
if (y > hyp)
ProgramFail(NULL, "asin(): opposite greater than hypotenuse");
ReturnValue->Val->Integer = asin(y, hyp);
}
void Cacos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // acos(x,hyp)
{
int x, hyp;
x = Param[0]->Val->Integer;
hyp = Param[1]->Val->Integer;
if (x > hyp)
ProgramFail(NULL, "acos(): adjacent greater than hypotenuse");
ReturnValue->Val->Integer = acos(x, hyp);
}
void Catan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // atan(y,x)
{
int x ,y;
y = Param[0]->Val->Integer;
x = Param[1]->Val->Integer;
ReturnValue->Val->Integer = atan(y, x);
}
void Cgps_head(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // gps_head(lat1, lon1, lat2, lon2)
{
int lat1, lon1, lat2, lon2;
lat1 = Param[0]->Val->Integer;
lon1 = Param[1]->Val->Integer;
lat2 = Param[2]->Val->Integer;
lon2 = Param[3]->Val->Integer;
ReturnValue->Val->Integer = gps_head(lat1, lon1, lat2, lon2);
}
void Cgps_dist(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // gps_dist(lat1, lon1, lat2, lon2)
{
int lat1, lon1, lat2, lon2;
lat1 = Param[0]->Val->Integer;
lon1 = Param[1]->Val->Integer;
lat2 = Param[2]->Val->Integer;
lon2 = Param[3]->Val->Integer;
ReturnValue->Val->Integer = gps_dist(lat1, lon1, lat2, lon2);
}
void Csqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // sqrt(x)
{
int x;
x = Param[0]->Val->Integer;
ReturnValue->Val->Integer = isqrt(x);
}
void Cnnset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnset(): invalid index");
for (i1=0; i1<8; i1++)
npattern[ix*8 + i1] = (unsigned char)Param[i1+1]->Val->Integer;
}
void Cnnshow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnshow(): invalid index");
nndisplay(ix);
}
void Cnninit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
nninit_network();
}
void Cnntrain(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1;
nntrain_network(10000);
for (ix=0; ix<NUM_NPATTERNS; ix++) {
nnset_pattern(ix);
nncalculate_network();
for (i1=0; i1<NUM_OUTPUT; i1++)
printf(" %3d", N_OUT(i1)/10);
printf("\r\n");
}
}
void Cnntest(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1, i2, max;
unsigned char ch;
ix = 0;
for (i1=0; i1<8; i1++) {
ch = (unsigned char)Param[i1]->Val->Integer;
for (i2=0; i2<8; i2++) {
if (ch & nmask[i2])
N_IN(ix++) = 1024;
else
N_IN(ix++) = 0;
}
}
nncalculate_network();
ix = 0;
max = 0;
for (i1=0; i1<NUM_OUTPUT; i1++) {
NNVect[i1] = N_OUT(i1)/10;
if (max < NNVect[i1]) {
ix = i1;
max = NNVect[i1];
}
}
ReturnValue->Val->Integer = ix;
}
void Cnnmatchblob(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1, max;
ix = Param[0]->Val->Integer;
if (ix > MAX_BLOBS)
ProgramFail(NULL, "nnmatchblob(): invalid blob index");
if (!blobcnt[ix])
ProgramFail(NULL, "nnmatchblob(): not a valid blob");
/* use data still in blob_buf[] (FRAME_BUF3)
square the aspect ratio of x1, x2, y1, y2
then subsample blob pixels to populate N_IN(0:63) with 0:1024 values
then nncalculate_network() and display the N_OUT() results */
nnscale8x8((unsigned char *)FRAME_BUF3, blobix[ix], blobx1[ix], blobx2[ix],
bloby1[ix], bloby2[ix], imgWidth, imgHeight);
nncalculate_network();
ix = 0;
max = 0;
for (i1=0; i1<NUM_OUTPUT; i1++) {
NNVect[i1] = N_OUT(i1)/10;
if (max < NNVect[i1]) {
ix = i1;
max = NNVect[i1];
}
}
ReturnValue->Val->Integer = ix;
}
void Cnnlearnblob (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnlearnblob(): invalid index");
if (!blobcnt[0])
ProgramFail(NULL, "nnlearnblob(): no blob to grab");
nnscale8x8((unsigned char *)FRAME_BUF3, blobix[0], blobx1[0], blobx2[0],
bloby1[0], bloby2[0], imgWidth, imgHeight);
nnpack8x8(ix);
nndisplay(ix);
}
void Cautorun (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, t0;
unsigned char ch;
ix = Param[0]->Val->Integer;
t0 = readRTC();
while (readRTC() < (t0 + ix*1000)) { // watch for ESC in 'ix' seconds
if (getchar(&ch)) {
if (ch == 0x1B) { // if ESC found, exit picoC
printf("found ESC\r\n");
ExitBuf[40] = 1;
longjmp(ExitBuf, 1);
}
}
}
}
void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
ReturnValue->Val->Integer = Parser->Line;
}
void Cerrormsg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
PlatformErrorPrefix(Parser);
LibPrintf(Parser, ReturnValue, Param, NumArgs);
}
/* nothing here because we don't add any functions until srv1.h is #included */
struct LibraryFunction PlatformLibrary[] =
{
{ NULL, NULL }
};
/* list of all library functions included with srv1.h */
struct LibraryFunction SRV1Functions[] =
{
{ Csignal, "int signal();" },
{ Cinput, "int input();" },
{ Cdelay, "void delay(int);" },
{ Crand, "int rand(int);" },
{ Ctime, "int time();" },
{ Ciodir, "void iodir(int);" },
{ Cioread, "int ioread();" },
{ Ciowrite, "void iowrite(int);" },
{ Cpeek, "int peek(int, int);" },
{ Cpoke, "void poke(int, int, int);" },
{ Cmotors, "void motors(int, int);" },
{ Cmotors2, "void motors2(int, int);" },
{ Cservos, "void servos(int, int);" },
{ Cservos2, "void servos2(int, int);" },
{ Cencoders, "void encoders();" },
{ Claser, "void laser(int);" },
{ Csonar, "int sonar(int);" },
{ Crange, "int range();" },
{ Cbattery, "int battery();" },
{ Cvcolor, "void vcolor(int, int, int, int, int, int, int);" },
{ Cvfind, "int vfind(int, int, int, int, int);" },
{ Cvcam, "void vcam(int);" },
{ Cvcap, "void vcap();" },
{ Cvrcap, "void vrcap();" },
{ Cvdiff, "void vdiff(int);" },
{ Cvpix, "void vpix(int, int);" },
{ Cvscan, "int vscan(int, int);" },
{ Cvmean, "void vmean();" },
{ Cvblob, "int vblob(int, int);" },
{ Cvjpeg, "int vjpeg(int);" },
{ Cvsend, "void vsend(int);" },
{ Ccompass, "int compass();" },
{ Canalog, "int analog(int);" },
{ Ctilt, "int tilt(int);" },
{ Cgps, "void gps();" },
{ Creadi2c, "int readi2c(int, int);" },
{ Creadi2c2, "int readi2c2(int, int);" },
{ Cwritei2c, "void writei2c(int, int, int);" },
{ Csin, "int sin(int);" },
{ Ccos, "int cos(int);" },
{ Ctan, "int tan(int);" },
{ Casin, "int asin(int, int);" },
{ Cacos, "int acos(int, int);" },
{ Catan, "int atan(int, int);" },
{ Cgps_head, "int gps_head(int, int, int, int);" },
{ Cgps_dist, "int gps_dist(int, int, int, int);" },
{ Csqrt, "int sqrt(int);" },
{ Cnnshow, "void nnshow(int);" },
{ Cnnset, "void nnset(int, int, int, int, int, int, int, int, int);" },
{ Cnninit, "void nninit();" },
{ Cnntrain, "void nntrain();" },
{ Cnntest, "int nntest(int, int, int, int, int, int, int, int);" },
{ Cnnmatchblob, "int nnmatchblob(int);" },
{ Cnnlearnblob, "void nnlearnblob(int);" },
{ Cautorun, "void autorun(int);" },
{ Clineno, "int lineno();" },
{ Cerrormsg, "void errormsg(char *);" },
{ NULL, NULL }
};
void PlatformLibraryInit()
{
IncludeRegister("srv1.h", &SRV1SetupFunc, &SRV1Functions[0], NULL);
}

945
platform/library_surveyor.c Normal file
View File

@ -0,0 +1,945 @@
#include "../interpreter.h"
#include "../picoc.h"
static int Blobcnt, Blobx1, Blobx2, Bloby1, Bloby2, Iy1, Iy2, Iu1, Iu2, Iv1, Iv2;
static int Cxmin, Cxmax, Cymin, Cymax;
static int GPSlat, GPSlon, GPSalt, GPSfix, GPSsat, GPSutc, Elcount, Ercount;
static int ScanVect[16], NNVect[NUM_OUTPUT];
void PlatformLibraryInit()
{
struct ValueType *IntArrayType;
IntArrayType = TypeGetMatching(NULL, &IntType, TypeArray, 16, StrEmpty, TRUE);
VariableDefinePlatformVar(NULL, "scanvect", IntArrayType, (union AnyValue *)&ScanVect, FALSE);
VariableDefinePlatformVar(NULL, "neuron", IntArrayType, (union AnyValue *)&NNVect, FALSE);
VariableDefinePlatformVar(NULL, "xbuf", CharArrayType, (union AnyValue *)&xbuff, FALSE);
VariableDefinePlatformVar(NULL, "blobcnt", &IntType, (union AnyValue *)&Blobcnt, FALSE);
VariableDefinePlatformVar(NULL, "blobx1", &IntType, (union AnyValue *)&Blobx1, FALSE);
VariableDefinePlatformVar(NULL, "blobx2", &IntType, (union AnyValue *)&Blobx2, FALSE);
VariableDefinePlatformVar(NULL, "bloby1", &IntType, (union AnyValue *)&Bloby1, FALSE);
VariableDefinePlatformVar(NULL, "bloby2", &IntType, (union AnyValue *)&Bloby2, FALSE);
VariableDefinePlatformVar(NULL, "lcount", &IntType, (union AnyValue *)&Elcount, FALSE);
VariableDefinePlatformVar(NULL, "rcount", &IntType, (union AnyValue *)&Ercount, FALSE);
VariableDefinePlatformVar(NULL, "y1", &IntType, (union AnyValue *)&Iy1, FALSE);
VariableDefinePlatformVar(NULL, "y2", &IntType, (union AnyValue *)&Iy2, FALSE);
VariableDefinePlatformVar(NULL, "u1", &IntType, (union AnyValue *)&Iu1, FALSE);
VariableDefinePlatformVar(NULL, "u2", &IntType, (union AnyValue *)&Iu2, FALSE);
VariableDefinePlatformVar(NULL, "v1", &IntType, (union AnyValue *)&Iv1, FALSE);
VariableDefinePlatformVar(NULL, "v2", &IntType, (union AnyValue *)&Iv2, FALSE);
VariableDefinePlatformVar(NULL, "gpslat", &IntType, (union AnyValue *)&GPSlat, FALSE);
VariableDefinePlatformVar(NULL, "gpslon", &IntType, (union AnyValue *)&GPSlon, FALSE);
VariableDefinePlatformVar(NULL, "gpsalt", &IntType, (union AnyValue *)&GPSalt, FALSE);
VariableDefinePlatformVar(NULL, "gpsfix", &IntType, (union AnyValue *)&GPSfix, FALSE);
VariableDefinePlatformVar(NULL, "gpssat", &IntType, (union AnyValue *)&GPSsat, FALSE);
VariableDefinePlatformVar(NULL, "gpsutc", &IntType, (union AnyValue *)&GPSutc, FALSE);
VariableDefinePlatformVar(NULL, "cxmin", &IntType, (union AnyValue *)&Cxmin, FALSE);
VariableDefinePlatformVar(NULL, "cxmax", &IntType, (union AnyValue *)&Cxmax, FALSE);
VariableDefinePlatformVar(NULL, "cymin", &IntType, (union AnyValue *)&Cymin, FALSE);
VariableDefinePlatformVar(NULL, "cymax", &IntType, (union AnyValue *)&Cymax, FALSE);
LibraryAdd(&GlobalTable, "platform library", &PlatformLibrary[0]);
}
void Csignal(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // check for kbhit, return t or nil
{
ReturnValue->Val->Integer = getsignal();
}
void Csignal1(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // check for kbhit, return t or nil
{
ReturnValue->Val->Integer = uart1Signal();
}
void Cinput(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
ReturnValue->Val->Integer = getch();
}
void Cinput1(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
ReturnValue->Val->Integer = uart1GetCh();
}
void Cread_int(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
int ix, sign;
unsigned char ch;
ix = 0;
sign = 1;
while (1) {
ch = getch();
if (ch == '-') {
sign = -1;
continue;
}
if ((ch < '0') || (ch > '9')) { // if not '-' or 0-9, we're done
ReturnValue->Val->Integer = ix * sign;
return;
}
ix = (ix * 10) + (ch & 0x0F);
}
}
void Cread_str(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // read string from console
{
int ix;
unsigned char ch;
ix = 0;
char *cp = (char *)Param[0]->Val->Pointer;
while (1) {
ch = getch();
cp[ix++] = ch;
if ((ch == 0) || (ch == 0x01)) { // null or ctrl-A
ix--;
cp[ix] = 0;
break;
}
if (ix > 1023) {
cp[ix] = 0;
ix--;
break;
}
}
ReturnValue->Val->Integer = ix;
}
void Cinit_uart1(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
int ii;
ii = Param[0]->Val->Integer; // ii = baudrate for uart1
init_uart1(ii);
}
void Coutput(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
int ch;
ch = Param[0]->Val->Integer;
putchar((unsigned char)ch);
}
void Coutput1(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return 0-9 from console input
{
int ch;
ch = Param[0]->Val->Integer;
uart1SendChar((unsigned char)ch);
}
void Cdelay(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int del;
del = Param[0]->Val->Integer;
if ((del < 0) || (del > 1000000))
return;
delayMS(del);
}
void Crand(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (int)rand() % (unsigned int)(Param[0]->Val->Integer + 1);
}
void Ctime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (int)readRTC();
}
void Ciodir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int dir;
dir = Param[0]->Val->Integer;
*pPORTHIO_DIR = ((dir << 10) & 0xFC00) + (*pPORTHIO_DIR & 0x03FF); // H15/14/13/12/11/10 - 1=output, 0=input
*pPORTHIO_INEN = (((~dir) << 10) & 0xFC00) + (*pPORTHIO_INEN & 0x03FF); // invert dir bits to enable inputs
}
void Cioread(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = (*pPORTHIO >> 10) & 0x003F;
}
void Ciowrite(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
*pPORTHIO = ((Param[0]->Val->Integer << 10) & 0xFC00) + (*pPORTHIO & 0x03FF);
}
void Cpeek(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int size, ptr;
unsigned char *cp;
unsigned short *sp;
unsigned int *ip;
/* x = peek(addr, size);
mask ptr to align with word size */
ptr = Param[0]->Val->Integer;
size = Param[1]->Val->Integer;
switch (size) {
case 1: // char *
cp = (unsigned char *)ptr;
ReturnValue->Val->Integer = (int)((unsigned int)*cp);
break;
case 2: // short *
sp = (unsigned short *)(ptr & 0xFFFFFFFE); // align with even boundary
ReturnValue->Val->Integer = (int)((unsigned short)*sp);
break;
case 4: // int *
ip = (unsigned int *)(ptr & 0xFFFFFFFC); // aling with quad boundary
ReturnValue->Val->Integer = (int)*ip;
break;
default:
ReturnValue->Val->Integer = 0;
break;
}
}
void Cpoke(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int size, ptr, val;
unsigned char *cp;
unsigned short *sp;
unsigned int *ip;
/* x = poke(addr, size, val);
mask ptr to align with word size */
ptr = Param[0]->Val->Integer;
size = Param[1]->Val->Integer;
val = Param[2]->Val->Integer;
switch (size) {
case 1: // char *
cp = (unsigned char *)ptr;
*cp = (unsigned char)(val & 0x000000FF);
break;
case 2: // short *
sp = (unsigned short *)(ptr & 0xFFFFFFFE);
*sp = (unsigned short)(val & 0x0000FFFF);
break;
case 4: // int *
ip = (unsigned int *)(ptr & 0xFFFFFFFC);
*ip = val;
break;
default: // don't bother with bad value
break;
}
}
void Cencoders(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
unsigned int ix;
ix = encoders(); // read left and right encoders; save data to C globals lcount, rcount
Elcount = (ix >> 16) & 0x0000FFFF;
Ercount = ix & 0x0000FFFF;
}
void Cencoderx(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
int ix;
ix = (unsigned char)Param[0]->Val->Integer;
if ((ix<0) || (ix>7))
ProgramFail(NULL, "encoderx(): invalid channel");
ReturnValue->Val->Integer = encoder_4wd(ix);
}
void Cmotors(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
lspeed = Param[0]->Val->Integer;
if ((lspeed < -100) || (lspeed > 100))
ProgramFail(NULL, "motors(): left motor value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < -100) || (rspeed > 100))
ProgramFail(NULL, "motors(): right motor value out of range");
if (!pwm1_init) {
initPWM();
pwm1_init = 1;
pwm1_mode = PWM_PWM;
base_speed = 50;
}
setPWM(lspeed, rspeed);
}
void Cmotors2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
lspeed2 = Param[0]->Val->Integer;
if ((lspeed2 < -100) || (lspeed2 > 100))
ProgramFail(NULL, "motors2(): left motor value out of range");
rspeed2 = Param[1]->Val->Integer;
if ((rspeed2 < -100) || (rspeed2 > 100))
ProgramFail(NULL, "motors2(): right motor value out of range");
if (!pwm2_init) {
initPWM2();
pwm2_init = 1;
pwm2_mode = PWM_PWM;
base_speed2 = 50;
}
setPWM2(lspeed2, rspeed2);
}
/* motor control for SRV-4WD controller */
void Cmotorx(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
unsigned char ch;
int ls, rs;
ls = Param[0]->Val->Integer;
if ((ls < -100) || (ls > 100))
ProgramFail(NULL, "motors(): left motor value out of range");
ls = (ls * 127) / 100; // scale to full +/-127 range
rs = Param[1]->Val->Integer;
if ((rs < -100) || (rs > 100))
ProgramFail(NULL, "motors(): right motor value out of range");
rs = (rs * 127) / 100; // scale to full +/-127 range
if (xwd_init == 0) {
xwd_init = 1;
init_uart1(115200);
delayMS(10);
}
uart1SendChar('x');
uart1SendChar((char)ls);
uart1SendChar((char)rs);
while (uart1GetChar(&ch)) // flush the receive buffer
continue;
}
void Cservos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int lspeed, rspeed;
lspeed = Param[0]->Val->Integer;
if ((lspeed < 0) || (lspeed > 100))
ProgramFail(NULL, "servos(): TMR2 value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < 0) || (rspeed > 100))
ProgramFail(NULL, "servos()(): TMR3 value out of range");
if (!pwm1_init) {
initPPM1();
pwm1_init = 1;
pwm1_mode = PWM_PPM;
}
setPPM1(lspeed, rspeed);
}
void Cservos2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int lspeed, rspeed;
lspeed = Param[0]->Val->Integer;
if ((lspeed < 0) || (lspeed > 100))
ProgramFail(NULL, "servos2(): TMR6 value out of range");
rspeed = Param[1]->Val->Integer;
if ((rspeed < 0) || (rspeed > 100))
ProgramFail(NULL, "servos2(): TMR7 value out of range");
if (!pwm2_init) {
initPPM2();
pwm2_init = 1;
pwm2_mode = PWM_PPM;
}
setPPM2(lspeed, rspeed);
}
void Claser(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // laser(1) turns them on, laser(0) turns them off
{
*pPORTHIO &= 0xFD7F; // turn off both lasers
switch (Param[0]->Val->Integer) {
case 1:
*pPORTHIO |= 0x0080; // turn on left laser
break;
case 2:
*pPORTHIO |= 0x0200; // turn on right laser
break;
case 3:
*pPORTHIO |= 0x0280; // turn on both lasers
break;
}
}
void Csonar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // read sonar module
{
unsigned int i;
i = Param[0]->Val->Integer;
if ((i<1) || (i>4)) {
ProgramFail(NULL, "sonar(): 1, 2, 3, 4 are only valid selections");
}
sonar();
ReturnValue->Val->Integer = sonar_data[i] / 100;
}
void Crange(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
ReturnValue->Val->Integer = laser_range(0);
}
void Cbattery(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
if (*pPORTHIO & 0x0004)
ReturnValue->Val->Integer = 0; // low battery voltage detected
else
ReturnValue->Val->Integer = 1; // battery voltage okay
}
void Cvcolor(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set color bin -
// vcolor (color, ymin, ymax, umin, umax, vmin, vmax);
{
int ix;
ix = Param[0]->Val->Integer;
ymin[ix] = Param[1]->Val->Integer;
ymax[ix] = Param[2]->Val->Integer;
umin[ix] = Param[3]->Val->Integer;
umax[ix] = Param[4]->Val->Integer;
vmin[ix] = Param[5]->Val->Integer;
vmax[ix] = Param[6]->Val->Integer;
}
void Cvcam(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set camera functions -
// enable/disable AGC(4) / AWB(2) / AEC(1) camera controls
// vcam(7) = AGC+AWB+AEC on vcam(0) = AGC+AWB+AEC off
{
unsigned char cx, i2c_data[2];
cx = (unsigned char)Param[0]->Val->Integer & 0x07;
i2c_data[0] = 0x13;
i2c_data[1] = 0xC0 + cx;
i2cwrite(0x30, (unsigned char *)i2c_data, 1, SCCB_ON); // OV9655
i2cwrite(0x21, (unsigned char *)i2c_data, 1, SCCB_ON); // OV7725
}
void Cvfind(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // set color bin -
// vfind (color, x1, x2, y1, y2);
{
int ix, x1, x2, y1, y2;
ix = Param[0]->Val->Integer;
x1 = Param[1]->Val->Integer;
x2 = Param[2]->Val->Integer;
y1 = Param[3]->Val->Integer;
y2 = Param[4]->Val->Integer;
ReturnValue->Val->Integer = vfind((unsigned char *)FRAME_BUF, ix, x1, x2, y1, y2);
}
void Cvcap(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
grab_frame(); // capture frame for processing
}
void Cvrcap(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
grab_reference_frame(); // capture reference frame for differencing
}
void Cvdiff(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
frame_diff_flag = Param[0]->Val->Integer; // set/clear frame_diff_flag
}
void Cvpix(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int x, y, ix;
x = Param[0]->Val->Integer;
y = Param[1]->Val->Integer;
ix = vpix((unsigned char *)FRAME_BUF, x, y);
Iy1 = ((ix>>16) & 0x000000FF); // Y1
Iu1 = ((ix>>24) & 0x000000FF); // U
Iv1 = ((ix>>8) & 0x000000FF); // V
}
void Cvscan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
int col, thresh, ix;
col = Param[0]->Val->Integer;
if ((col < 1) || (col > 9))
ProgramFail(NULL, "vscan(): number of columns must be between 1 and 9");
thresh = Param[1]->Val->Integer;
if ((thresh < 0) || (thresh > 9999))
ProgramFail(NULL, "vscan(): threshold must be between 0 and 9999");
ix = vscan((unsigned char *)SPI_BUFFER1, (unsigned char *)FRAME_BUF, thresh, (unsigned int)col, (unsigned int *)&ScanVect[0]);
ReturnValue->Val->Integer = ix;
}
void Cvmean(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
vmean((unsigned char *)FRAME_BUF);
Iy1 = mean[0];
Iu1 = mean[1];
Iv1 = mean[2];
}
// search for blob by color, index; return center point X,Y and width Z
void Cvblob(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, iblob, numblob;
ix = Param[0]->Val->Integer;
if (ix > MAX_COLORS)
ProgramFail(NULL, "blob(): invalid color index");
iblob = Param[1]->Val->Integer;
if (iblob > MAX_BLOBS)
ProgramFail(NULL, "blob(): invalid blob index");
numblob = vblob((unsigned char *)FRAME_BUF, (unsigned char *)FRAME_BUF3, ix);
if ((blobcnt[iblob] == 0) || (numblob == -1)) {
Blobcnt = 0;
} else {
Blobcnt = blobcnt[iblob];
Blobx1 = blobx1[iblob];
Blobx2 = blobx2[iblob];
Bloby1 = bloby1[iblob];
Bloby2 = bloby2[iblob];
}
ReturnValue->Val->Integer = numblob;
}
void Cvjpeg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
unsigned int image_size, qual;
unsigned char *output_start, *output_end;
qual = Param[0]->Val->Integer;
if ((qual < 1) || (qual > 8))
ProgramFail(NULL, "vjpeg(): quality parameter out of range");
output_start = (unsigned char *)JPEG_BUF;
output_end = encode_image((unsigned char *)FRAME_BUF, output_start, qual,
FOUR_TWO_TWO, imgWidth, imgHeight);
image_size = (unsigned int)(output_end - output_start);
ReturnValue->Val->Integer = image_size;
}
void Cvsend (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
unsigned int ix, image_size;
unsigned char *cp;
image_size = Param[0]->Val->Integer;
if ((image_size < 0) || (image_size > 200000))
ProgramFail(NULL, "vsend(): image size out of range");
led1_on();
cp = (unsigned char *)JPEG_BUF;
for (ix=0; ix<image_size; ix++)
putchar(*cp++);
led0_on();
}
void Ccompass(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned char i2c_data[2];
unsigned int ix;
i2c_data[0] = 0x41; // read compass twice to clear last reading
i2cread(0x22, (unsigned char *)i2c_data, 2, SCCB_ON);
delayMS(20);
i2c_data[0] = 0x41;
i2cread(0x22, (unsigned char *)i2c_data, 2, SCCB_ON);
ix = ((unsigned int)(i2c_data[0] << 8) + i2c_data[1]) / 10;
ReturnValue->Val->Integer = ix;
}
void Ccompassx(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC5843 I2C compass
{
short x, y, z;
int ix;
ix = (int)read_compass3x(&x, &y, &z);
Cxmin = cxmin;
Cxmax = cxmax;
Cymin = cymin;
Cymax = cymax;
ReturnValue->Val->Integer = ix;
}
void Ccompassxcal(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC5843 I2C compass
{
/* cxmin, cxmax, cymin, cymax */
cxmin = Param[0]->Val->Integer;
cxmax = Param[1]->Val->Integer;
cymin = Param[2]->Val->Integer;
cymax = Param[3]->Val->Integer;
compass_continuous_calibration = Param[4]->Val->Integer; // continuous calibration: off = 0, on = 1
}
void Ctilt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned int ix;
ix = (unsigned int)Param[0]->Val->Integer;
if ((ix<1) || (ix>3))
ProgramFail(NULL, "tilt(): invalid channel");
ReturnValue->Val->Integer = tilt(ix);
}
void Canalog(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
unsigned int ix, channel;
ix = (unsigned char)Param[0]->Val->Integer;
if ((ix<1) || (ix>28))
ProgramFail(NULL, "analog(): invalid channel");
channel = ix % 10;
if ((channel<1) || (channel>8))
ProgramFail(NULL, "analog(): invalid channel");
ReturnValue->Val->Integer = analog(ix);
}
/* read analog channel 0-7 from SRV-4WD (
channel 0 = battery level
channel 1 = 5V gyro
channel 2 = 3.3V gyro
channel 3 = IR1
channel 4 = IR2
channel 6 = IR3
channel 7 = IR4
*/
void Canalogx(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // return reading from HMC6352 I2C compass
{
int ix;
ix = (unsigned char)Param[0]->Val->Integer;
if ((ix<0) || (ix>7))
ProgramFail(NULL, "analogx(): invalid channel");
ReturnValue->Val->Integer = analog_4wd(ix);
}
void Cgps(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
gps_parse();
GPSlat = gps_gga.lat;
GPSlon = gps_gga.lon;
GPSalt = gps_gga.alt;
GPSfix = gps_gga.fix;
GPSsat = gps_gga.sat;
GPSutc = gps_gga.utc;
}
void Creadi2c(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax val = readi2c(device, register);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2cread(i2c_device, (unsigned char *)i2c_data, 1, SCCB_OFF);
ReturnValue->Val->Integer = ((int)i2c_data[0] & 0x000000FF);
}
void Creadi2c2(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax two_byte_val = readi2c(device, register);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2cread(i2c_device, (unsigned char *)i2c_data, 2, SCCB_OFF);
ReturnValue->Val->Integer = (((unsigned int)i2c_data[0] << 8) + i2c_data[1]);
}
void Cwritei2c(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // syntax writei2c(device, register, value);
{
unsigned char i2c_device, i2c_data[2];
i2c_device = (unsigned char)Param[0]->Val->Integer;
i2c_data[0] = (unsigned char)Param[1]->Val->Integer;
i2c_data[1] = (unsigned char)Param[2]->Val->Integer;
i2cwrite(i2c_device, (unsigned char *)i2c_data, 1, SCCB_OFF);
}
void Cabs(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // abs(int)
{
int ix;
ix = Param[0]->Val->Integer; // return absolute value of int
if (ix < 0)
ix = -ix;
ReturnValue->Val->Integer = ix;
}
void Csin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // sin(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = sin(ix);
}
void Ccos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // cos(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = cos(ix);
}
void Ctan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // tan(angle)
{
int ix;
ix = Param[0]->Val->Integer; // input to function is angle in degrees
ReturnValue->Val->Integer = tan(ix);
}
void Casin(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // asin(y,hyp)
{
int y, hyp;
y = Param[0]->Val->Integer;
hyp = Param[1]->Val->Integer;
if (y > hyp)
ProgramFail(NULL, "asin(): opposite greater than hypotenuse");
ReturnValue->Val->Integer = asin(y, hyp);
}
void Cacos(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // acos(x,hyp)
{
int x, hyp;
x = Param[0]->Val->Integer;
hyp = Param[1]->Val->Integer;
if (x > hyp)
ProgramFail(NULL, "acos(): adjacent greater than hypotenuse");
ReturnValue->Val->Integer = acos(x, hyp);
}
void Catan(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // atan(y,x)
{
int x ,y;
y = Param[0]->Val->Integer;
x = Param[1]->Val->Integer;
ReturnValue->Val->Integer = atan(y, x);
}
void Cgps_head(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // gps_head(lat1, lon1, lat2, lon2)
{
int lat1, lon1, lat2, lon2;
lat1 = Param[0]->Val->Integer;
lon1 = Param[1]->Val->Integer;
lat2 = Param[2]->Val->Integer;
lon2 = Param[3]->Val->Integer;
ReturnValue->Val->Integer = gps_head(lat1, lon1, lat2, lon2);
}
void Cgps_dist(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // gps_dist(lat1, lon1, lat2, lon2)
{
int lat1, lon1, lat2, lon2;
lat1 = Param[0]->Val->Integer;
lon1 = Param[1]->Val->Integer;
lat2 = Param[2]->Val->Integer;
lon2 = Param[3]->Val->Integer;
ReturnValue->Val->Integer = gps_dist(lat1, lon1, lat2, lon2);
}
void Csqrt(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) // sqrt(x)
{
int x;
x = Param[0]->Val->Integer;
ReturnValue->Val->Integer = isqrt(x);
}
void Cnnset(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnset(): invalid index");
for (i1=0; i1<8; i1++)
npattern[ix*8 + i1] = (unsigned char)Param[i1+1]->Val->Integer;
}
void Cnnshow(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnshow(): invalid index");
nndisplay(ix);
}
void Cnninit(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
nninit_network();
}
void Cnntrain(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1;
nntrain_network(10000);
for (ix=0; ix<NUM_NPATTERNS; ix++) {
nnset_pattern(ix);
nncalculate_network();
for (i1=0; i1<NUM_OUTPUT; i1++)
printf(" %3d", N_OUT(i1)/10);
printf("\r\n");
}
}
void Cnntest(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1, i2, max;
unsigned char ch;
ix = 0;
for (i1=0; i1<8; i1++) {
ch = (unsigned char)Param[i1]->Val->Integer;
for (i2=0; i2<8; i2++) {
if (ch & nmask[i2])
N_IN(ix++) = 1024;
else
N_IN(ix++) = 0;
}
}
nncalculate_network();
ix = 0;
max = 0;
for (i1=0; i1<NUM_OUTPUT; i1++) {
NNVect[i1] = N_OUT(i1)/10;
if (max < NNVect[i1]) {
ix = i1;
max = NNVect[i1];
}
}
ReturnValue->Val->Integer = ix;
}
void Cnnmatchblob(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, i1, max;
ix = Param[0]->Val->Integer;
if (ix > MAX_BLOBS)
ProgramFail(NULL, "nnmatchblob(): invalid blob index");
if (!blobcnt[ix])
ProgramFail(NULL, "nnmatchblob(): not a valid blob");
/* use data still in blob_buf[] (FRAME_BUF3)
square the aspect ratio of x1, x2, y1, y2
then subsample blob pixels to populate N_IN(0:63) with 0:1024 values
then nncalculate_network() and display the N_OUT() results */
nnscale8x8((unsigned char *)FRAME_BUF3, blobix[ix], blobx1[ix], blobx2[ix],
bloby1[ix], bloby2[ix], imgWidth, imgHeight);
nncalculate_network();
ix = 0;
max = 0;
for (i1=0; i1<NUM_OUTPUT; i1++) {
NNVect[i1] = N_OUT(i1)/10;
if (max < NNVect[i1]) {
ix = i1;
max = NNVect[i1];
}
}
ReturnValue->Val->Integer = ix;
}
void Cnnlearnblob (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix;
ix = Param[0]->Val->Integer;
if (ix > NUM_NPATTERNS)
ProgramFail(NULL, "nnlearnblob(): invalid index");
if (!blobcnt[0])
ProgramFail(NULL, "nnlearnblob(): no blob to grab");
nnscale8x8((unsigned char *)FRAME_BUF3, blobix[0], blobx1[0], blobx2[0],
bloby1[0], bloby2[0], imgWidth, imgHeight);
nnpack8x8(ix);
nndisplay(ix);
}
void Cautorun (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
int ix, t0;
unsigned char ch;
ix = Param[0]->Val->Integer;
t0 = readRTC();
while (readRTC() < (t0 + ix*1000)) { // watch for ESC in 'ix' seconds
if (getchar(&ch)) {
if (ch == 0x1B) { // if ESC found, exit picoC
printf("found ESC\r\n");
PicocExitBuf[40] = 1;
longjmp(PicocExitBuf, 1);
}
}
}
}
void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
ReturnValue->Val->Integer = Parser->Line;
}
void Cerrormsg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) {
PlatformErrorPrefix(Parser);
LibPrintf(Parser, ReturnValue, Param, NumArgs);
}
/* list of all library functions and their prototypes */
struct LibraryFunction PlatformLibrary[] =
{
{ Csignal, "int signal();" },
{ Csignal1, "int signal1();" },
{ Cinput, "int input();" },
{ Cinput1, "int input1();" },
{ Cinit_uart1, "void init_uart1(int);" },
{ Cread_int, "int read_int();" },
{ Cread_str, "int read_str(char *);" },
{ Coutput, "void output(int);" },
{ Coutput1, "void output1(int);" },
{ Cdelay, "void delay(int);" },
{ Crand, "int rand(int);" },
{ Ctime, "int time();" },
{ Ciodir, "void iodir(int);" },
{ Cioread, "int ioread();" },
{ Ciowrite, "void iowrite(int);" },
{ Cpeek, "int peek(int, int);" },
{ Cpoke, "void poke(int, int, int);" },
{ Cmotors, "void motors(int, int);" },
{ Cmotors2, "void motors2(int, int);" },
{ Cmotorx, "void motorx(int, int);" },
{ Cservos, "void servos(int, int);" },
{ Cservos2, "void servos2(int, int);" },
{ Cencoders, "void encoders();" },
{ Cencoderx, "int encoderx(int);" },
{ Claser, "void laser(int);" },
{ Csonar, "int sonar(int);" },
{ Crange, "int range();" },
{ Cbattery, "int battery();" },
{ Cvcolor, "void vcolor(int, int, int, int, int, int, int);" },
{ Cvfind, "int vfind(int, int, int, int, int);" },
{ Cvcam, "void vcam(int);" },
{ Cvcap, "void vcap();" },
{ Cvrcap, "void vrcap();" },
{ Cvdiff, "void vdiff(int);" },
{ Cvpix, "void vpix(int, int);" },
{ Cvscan, "int vscan(int, int);" },
{ Cvmean, "void vmean();" },
{ Cvblob, "int vblob(int, int);" },
{ Cvjpeg, "int vjpeg(int);" },
{ Cvsend, "void vsend(int);" },
{ Ccompass, "int compass();" },
{ Ccompassx, "int compassx();" },
{ Ccompassxcal, "void compassxcal(int, int, int, int, int);" },
{ Canalog, "int analog(int);" },
{ Canalogx, "int analogx(int);" },
{ Ctilt, "int tilt(int);" },
{ Cgps, "void gps();" },
{ Creadi2c, "int readi2c(int, int);" },
{ Creadi2c2, "int readi2c2(int, int);" },
{ Cwritei2c, "void writei2c(int, int, int);" },
{ Cabs, "int abs(int);" },
{ Csin, "int sin(int);" },
{ Ccos, "int cos(int);" },
{ Ctan, "int tan(int);" },
{ Casin, "int asin(int, int);" },
{ Cacos, "int acos(int, int);" },
{ Catan, "int atan(int, int);" },
{ Cgps_head, "int gps_head(int, int, int, int);" },
{ Cgps_dist, "int gps_dist(int, int, int, int);" },
{ Csqrt, "int sqrt(int);" },
{ Cnnshow, "void nnshow(int);" },
{ Cnnset, "void nnset(int, int, int, int, int, int, int, int, int);" },
{ Cnninit, "void nninit();" },
{ Cnntrain, "void nntrain();" },
{ Cnntest, "int nntest(int, int, int, int, int, int, int, int);" },
{ Cnnmatchblob, "int nnmatchblob(int);" },
{ Cnnlearnblob, "void nnlearnblob(int);" },
{ Cautorun, "void autorun(int);" },
{ Clineno, "int lineno();" },
{ Cerrormsg, "void errormsg(char *);" },
{ NULL, NULL }
};

29
platform/library_unix.c Normal file
View File

@ -0,0 +1,29 @@
#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);
}

51
platform/platform_ffox.c Normal file
View File

@ -0,0 +1,51 @@
#include "../interpreter.h"
/* deallocate any storage */
void PlatformCleanup()
{
}
/* get a line of interactive input */
char *PlatformGetLine(char *Buf, int MaxLen)
{
// XXX - unimplemented so far
return NULL;
}
/* get a character of interactive input */
int PlatformGetCharacter()
{
// XXX - unimplemented so far
return 0;
}
/* write a character to the console */
void PlatformPutc(unsigned char OutCh, union OutputStreamInfo *Stream)
{
// XXX - unimplemented so far
}
/* read a file into memory */
char *PlatformReadFile(const char *FileName)
{
// XXX - unimplemented so far
return NULL;
}
/* read and scan a file for definitions */
void PlatformScanFile(const char *FileName)
{
char *SourceStr = PlatformReadFile(FileName);
Parse(FileName, SourceStr, strlen(SourceStr), TRUE);
//free(SourceStr);
}
/* mark where to end the program for platforms which require this */
jmp_buf ExitBuf;
/* exit the program */
void PlatformExit()
{
longjmp(ExitBuf, 1);
}

View File

@ -0,0 +1,71 @@
#include "../interpreter.h"
#include "../picoc.h"
/* mark where to end the program for platforms which require this */
int PicocExitBuf[41];
/* deallocate any storage */
void PlatformCleanup()
{
}
/* get a line of interactive input */
char *PlatformGetLine(char *Buf, int MaxLen, const char *Prompt)
{
int ix;
char ch, *cp;
printf(Prompt);
ix = 0;
cp = 0;
// If the first character is \n or \r, eat it
ch = getch();
if (ch == '\n' || ch == '\r')
{
// And get the next character
ch = getch();
}
while (ix++ < MaxLen) {
if (ch == 0x1B || ch == 0x03) { // ESC character or ctrl-c (to avoid problem with TeraTerm) - exit
printf("Leaving PicoC\n");
return NULL;
}
if (ch == '\n') {
*cp++ = '\n'; // if newline, send newline character followed by null
*cp = 0;
return Buf;
}
*cp++ = ch;
ix++;
ch = getch();
}
return NULL;
}
/* write a character to the console */
void PlatformPutc(unsigned char OutCh, union OutputStreamInfo *Stream)
{
if (OutCh == '\n')
putchar('\r');
putchar(OutCh);
}
/* read a character */
int PlatformGetCharacter()
{
return getch();
}
/* exit the program */
void PlatformExit(int RetVal)
{
PicocExitValue = RetVal;
PicocExitBuf[40] = 1;
longjmp(PicocExitBuf, 1);
}

102
platform/platform_unix.c Normal file
View File

@ -0,0 +1,102 @@
#include "../picoc.h"
#include "../interpreter.h"
#ifdef USE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#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);
}

187
table.c Normal file
View File

@ -0,0 +1,187 @@
#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);
}
}
}

13
tests/00_assignment.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
int a;
a = 42;
printf("%d\n", a);
int b = 64;
printf("%d\n", b);
int c = 12, d = 34;
printf("%d, %d\n", c, d);
void main() {}

View File

@ -0,0 +1,3 @@
42
64
12, 34

10
tests/01_comment.c Normal file
View File

@ -0,0 +1,10 @@
#include <stdio.h>
printf("Hello\n");
printf("Hello\n"); /* this is a comment */ printf("Hello\n");
printf("Hello\n");
// this is also a comment sayhello();
printf("Hello\n");
void main() {}

5
tests/01_comment.expect Normal file
View File

@ -0,0 +1,5 @@
Hello
Hello
Hello
Hello
Hello

13
tests/02_printf.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
printf("Hello world\n");
int Count;
for (Count = -5; Count <= 5; Count++)
printf("Count = %d\n", Count);
printf("String 'hello', 'there' is '%s', '%s'\n", "hello", "there");
printf("Character 'A' is '%c'\n", 65);
printf("Character 'a' is '%c'\n", 'a');
void main() {}

15
tests/02_printf.expect Normal file
View File

@ -0,0 +1,15 @@
Hello world
Count = -5
Count = -4
Count = -3
Count = -2
Count = -1
Count = 0
Count = 1
Count = 2
Count = 3
Count = 4
Count = 5
String 'hello', 'there' is 'hello', 'there'
Character 'A' is 'A'
Character 'a' is 'a'

21
tests/03_struct.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdio.h>
struct fred
{
int boris;
int natasha;
};
struct fred bloggs;
bloggs.boris = 12;
bloggs.natasha = 34;
printf("%d\n", bloggs.boris);
printf("%d\n", bloggs.natasha);
//struct fred jones[2];
//jones[0].boris = 12;
//jones[0].natasha = 34;
void main() {}

2
tests/03_struct.expect Normal file
View File

@ -0,0 +1,2 @@
12
34

10
tests/04_for.c Normal file
View File

@ -0,0 +1,10 @@
#include <stdio.h>
int Count;
for (Count = 1; Count <= 10; Count++)
{
printf("%d\n", Count);
}
void main() {}

10
tests/04_for.expect Normal file
View File

@ -0,0 +1,10 @@
1
2
3
4
5
6
7
8
9
10

16
tests/05_array.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
int Count;
int Array[10];
for (Count = 1; Count <= 10; Count++)
{
Array[Count-1] = Count * Count;
}
for (Count = 0; Count < 10; Count++)
{
printf("%d\n", Array[Count]);
}
void main() {}

10
tests/05_array.expect Normal file
View File

@ -0,0 +1,10 @@
1
4
9
16
25
36
49
64
81
100

24
tests/06_case.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdio.h>
int Count;
for (Count = 0; Count < 4; Count++)
{
printf("%d\n", Count);
switch (Count)
{
case 1:
printf("%d\n", 1);
break;
case 2:
printf("%d\n", 2);
break;
default:
printf("%d\n", 0);
break;
}
}
void main() {}

8
tests/06_case.expect Normal file
View File

@ -0,0 +1,8 @@
0
0
1
1
2
2
3
0

25
tests/07_function.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
int myfunc(int x)
{
return x * x;
}
printf("%d\n", myfunc(3));
printf("%d\n", myfunc(4));
void vfunc(int a)
{
printf("a=%d\n", a);
}
vfunc(1234);
void qfunc()
{
printf("qfunc()\n");
}
qfunc();
void main() {}

4
tests/07_function.expect Normal file
View File

@ -0,0 +1,4 @@
9
16
a=1234
qfunc()

19
tests/08_while.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
int a;
int p;
int t;
a = 1;
p = 0;
t = 0;
while (a < 100)
{
printf("%d\n", a);
t = a;
a = t + p;
p = t;
}
void main() {}

11
tests/08_while.expect Normal file
View File

@ -0,0 +1,11 @@
1
1
2
3
5
8
13
21
34
55
89

20
tests/09_do_while.c Normal file
View File

@ -0,0 +1,20 @@
#include <stdio.h>
int a;
int p;
int t;
a = 1;
p = 0;
t = 0;
do
{
printf("%d\n", a);
t = a;
a = t + p;
p = t;
} while (a < 100);
void main() {}

11
tests/09_do_while.expect Normal file
View File

@ -0,0 +1,11 @@
1
1
2
3
5
8
13
21
34
55
89

37
tests/10_pointer.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdio.h>
int a;
int *b;
int c;
a = 42;
b = &a;
printf("a = %d\n", *b);
struct ziggy
{
int a;
int b;
int c;
} bolshevic;
bolshevic.a = 12;
bolshevic.b = 34;
bolshevic.c = 56;
printf("bolshevic.a = %d\n", bolshevic.a);
printf("bolshevic.b = %d\n", bolshevic.b);
printf("bolshevic.c = %d\n", bolshevic.c);
struct ziggy *tsar = &bolshevic;
printf("tsar->a = %d\n", tsar->a);
printf("tsar->b = %d\n", tsar->b);
printf("tsar->c = %d\n", tsar->c);
/*
b = &(bolshevic.b);
printf("bolshevic.b = %d\n", *b);
*/
void main() {}

7
tests/10_pointer.expect Normal file
View File

@ -0,0 +1,7 @@
a = 42
bolshevic.a = 12
bolshevic.b = 34
bolshevic.c = 56
tsar->a = 12
tsar->b = 34
tsar->c = 56

38
tests/11_precedence.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
int a;
int b;
int c;
int d;
int e;
int f;
int x;
int y;
a = 12;
b = 34;
c = 56;
d = 78;
e = 0;
f = 1;
printf("%d\n", c + d);
printf("%d\n", (y = c + d));
/* printf("%d\n", a ? b+c : c+d);
printf("%d\n", a ? b+c : c+d);
printf("%d\n", a || b ? b+c : c+d); */
printf("%d\n", e || e && f);
printf("%d\n", e || f && f);
printf("%d\n", e && e || f);
printf("%d\n", e && f || f);
printf("%d\n", a && f | f);
printf("%d\n", a | b ^ c & d);
printf("%d, %d\n", a == a, a == b);
printf("%d, %d\n", a != a, a != b);
printf("%d\n", a != b && c != d);
printf("%d\n", a + b * c / f);
printf("%d\n", a + b * c / f);
printf("%d\n", (4 << 4));
printf("%d\n", (64 >> 4));
void main() {}

View File

@ -0,0 +1,15 @@
134
134
0
1
1
1
1
46
1, 0
0, 1
1
1916
1916
64
4

10
tests/12_hashdefine.c Normal file
View File

@ -0,0 +1,10 @@
#include <stdio.h>
#define FRED 12
#define BLOGGS(x) (12*(x))
printf("%d\n", FRED);
printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3));
void main() {}

View File

@ -0,0 +1,2 @@
12
12, 24, 36

View File

@ -0,0 +1,16 @@
#include <stdio.h>
int a = 24680;
int b = 01234567;
int c = 0x2468ac;
int d = 0x2468AC;
int e = 0b010101010101;
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
printf("%d\n", d);
printf("%d\n", e);
void main() {}

View File

@ -0,0 +1,5 @@
24680
342391
2386092
2386092
1365

17
tests/14_if.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
int a = 1;
if (a)
printf("a is true\n");
else
printf("a is false\n");
int b = 0;
if (b)
printf("b is true\n");
else
printf("b is false\n");
void main() {}

2
tests/14_if.expect Normal file
View File

@ -0,0 +1,2 @@
a is true
b is false

16
tests/15_recursion.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
int factorial(int i)
{
if (i < 2)
return i;
else
return i * factorial(i - 1);
}
int Count;
for (Count = 1; Count <= 10; Count++)
printf("%d\n", factorial(Count));
void main() {}

10
tests/15_recursion.expect Normal file
View File

@ -0,0 +1,10 @@
1
2
6
24
120
720
5040
40320
362880
3628800

16
tests/16_nesting.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
int x, y, z;
for (x = 0; x < 2; x++)
{
for (y = 0; y < 3; y++)
{
for (z = 0; z < 3; z++)
{
printf("%d %d %d\n", x, y, z);
}
}
}
void main() {}

18
tests/16_nesting.expect Normal file
View File

@ -0,0 +1,18 @@
0 0 0
0 0 1
0 0 2
0 1 0
0 1 1
0 1 2
0 2 0
0 2 1
0 2 2
1 0 0
1 0 1
1 0 2
1 1 0
1 1 1
1 1 2
1 2 0
1 2 1
1 2 2

24
tests/17_enum.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdio.h>
enum fred
{
a,
b,
c,
d,
e = 54,
f = 73,
g,
h
};
enum fred frod;
printf("%d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h);
printf("%d\n", frod);
frod = 12;
printf("%d\n", frod);
frod = e;
printf("%d\n", frod);
void main() {}

4
tests/17_enum.expect Normal file
View File

@ -0,0 +1,4 @@
0 1 2 3 54 73 74 75
0
12
54

7
tests/18_include.c Normal file
View File

@ -0,0 +1,7 @@
#include <stdio.h>
printf("including\n");
#include "18_include.h"
printf("done\n");
void main() {}

3
tests/18_include.expect Normal file
View File

@ -0,0 +1,3 @@
including
included
done

1
tests/18_include.h Normal file
View File

@ -0,0 +1 @@
printf("included\n");

View File

@ -0,0 +1,24 @@
#include <stdio.h>
int a;
int *b;
int *c;
a = 42;
b = &a;
c = NULL;
printf("%d\n", *b);
if (b == NULL)
printf("b is NULL\n");
else
printf("b is not NULL\n");
if (c == NULL)
printf("c is NULL\n");
else
printf("c is not NULL\n");
void main() {}

View File

@ -0,0 +1,3 @@
42
b is not NULL
c is NULL

View File

@ -0,0 +1,20 @@
#include <stdio.h>
int a;
int b;
int *d;
int *e;
d = &a;
e = &b;
a = 12;
b = 34;
printf("%d\n", *d);
printf("%d\n", *e);
printf("%d\n", d == e);
printf("%d\n", d != e);
d = e;
printf("%d\n", d == e);
printf("%d\n", d != e);
void main() {}

View File

@ -0,0 +1,6 @@
12
34
0
1
1
0

29
tests/21_char_array.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
int x = 'a';
char y = x;
char *a = "hello";
printf("%s\n", a);
int c;
c = *a;
char *b;
for (b = a; *b != 0; b++)
printf("%c: %d\n", *b, *b);
char destarray[10];
char *dest = &destarray[0];
char *src = a;
while (*src != 0)
*dest++ = *src++;
*dest = 0;
printf("copied string is %s\n", destarray);
void main() {}

View File

@ -0,0 +1,7 @@
hello
h: 104
e: 101
l: 108
l: 108
o: 111
copied string is hello

45
tests/22_floating_point.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdio.h>
#include <math.h>
// variables
float a = 12.34 + 56.78;
printf("%f\n", a);
// infix operators
printf("%f\n", 12.34 + 56.78);
printf("%f\n", 12.34 - 56.78);
printf("%f\n", 12.34 * 56.78);
printf("%f\n", 12.34 / 56.78);
// comparison operators
printf("%d %d %d %d %d %d\n", 12.34 < 56.78, 12.34 <= 56.78, 12.34 == 56.78, 12.34 >= 56.78, 12.34 > 56.78, 12.34 != 56.78);
printf("%d %d %d %d %d %d\n", 12.34 < 12.34, 12.34 <= 12.34, 12.34 == 12.34, 12.34 >= 12.34, 12.34 > 12.34, 12.34 != 12.34);
printf("%d %d %d %d %d %d\n", 56.78 < 12.34, 56.78 <= 12.34, 56.78 == 12.34, 56.78 >= 12.34, 56.78 > 12.34, 56.78 != 12.34);
// assignment operators
a = 12.34;
a += 56.78;
printf("%f\n", a);
a = 12.34;
a -= 56.78;
printf("%f\n", a);
a = 12.34;
a *= 56.78;
printf("%f\n", a);
a = 12.34;
a /= 56.78;
printf("%f\n", a);
// prefix operators
printf("%f\n", +12.34);
printf("%f\n", -12.34);
// type coercion
a = 2;
printf("%f\n", a);
printf("%f\n", sin(2));
void main() {}

View File

@ -0,0 +1,16 @@
69.120000
69.120000
-44.440000
700.665200
0.217330
1 1 0 0 0 1
0 1 1 1 0 0
0 0 0 1 1 1
69.120000
-44.440000
700.665200
0.217330
12.340000
-12.340000
2.000000
0.909297

49
tests/23_type_coercion.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdio.h>
void charfunc(char a)
{
printf("char: %c\n", a);
}
void intfunc(int a)
{
printf("int: %d\n", a);
}
void floatfunc(float a)
{
printf("float: %f\n", a);
}
charfunc('a');
charfunc(98);
charfunc(99.0);
intfunc('a');
intfunc(98);
intfunc(99.0);
floatfunc('a');
floatfunc(98);
floatfunc(99.0);
printf("%c %d %f\n", 'a', 'b', 'c');
printf("%c %d %f\n", 97, 98, 99);
printf("%c %d %f\n", 97.0, 98.0, 99.0);
char b = 97;
char c = 97.0;
printf("%d %d\n", b, c);
int d = 'a';
int e = 97.0;
printf("%d %d\n", d, e);
float f = 'a';
float g = 97;
printf("%f %f\n", f, g);
void main() {}

View File

@ -0,0 +1,15 @@
char: a
char: b
char: c
int: 97
int: 98
int: 99
float: 97.000000
float: 98.000000
float: 99.000000
a 98 99.000000
a 98 99.000000
a 98 99.000000
97 97
97 97
97.000000 97.000000

23
tests/24_math_library.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdio.h>
#include <math.h>
printf("%f\n", sin(0.12));
printf("%f\n", cos(0.12));
printf("%f\n", tan(0.12));
printf("%f\n", asin(0.12));
printf("%f\n", acos(0.12));
printf("%f\n", atan(0.12));
printf("%f\n", sinh(0.12));
printf("%f\n", cosh(0.12));
printf("%f\n", tanh(0.12));
printf("%f\n", exp(0.12));
printf("%f\n", fabs(-0.12));
printf("%f\n", log(0.12));
printf("%f\n", log10(0.12));
printf("%f\n", pow(0.12, 0.12));
printf("%f\n", sqrt(0.12));
printf("%f\n", round(12.34));
printf("%f\n", ceil(12.34));
printf("%f\n", floor(12.34));
void main() {}

View File

@ -0,0 +1,18 @@
0.119712
0.992809
0.120579
0.120290
1.450506
0.119429
0.120288
1.007209
0.119427
1.127497
0.120000
-2.120264
-0.920819
0.775357
0.346410
12.000000
13.000000
12.000000

80
tests/25_quicksort.c Normal file
View File

@ -0,0 +1,80 @@
#include <stdio.h>
int array[16];
//Swap integer values by array indexes
void swap(int a, int b)
{
int tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
//Partition the array into two halves and return the
//index about which the array is partitioned
int partition(int left, int right)
{
int pivotIndex = left;
int pivotValue = array[pivotIndex];
int index = left;
int i;
swap(pivotIndex, right);
for(i = left; i < right; i++)
{
if(array[i] < pivotValue)
{
swap(i, index);
index += 1;
}
}
swap(right, index);
return index;
}
//Quicksort the array
void quicksort(int left, int right)
{
if(left >= right)
return;
int index = partition(left, right);
quicksort(left, index - 1);
quicksort(index + 1, right);
}
void main()
{
int i;
array[0] = 62;
array[1] = 83;
array[2] = 4;
array[3] = 89;
array[4] = 36;
array[5] = 21;
array[6] = 74;
array[7] = 37;
array[8] = 65;
array[9] = 33;
array[10] = 96;
array[11] = 38;
array[12] = 53;
array[13] = 16;
array[14] = 74;
array[15] = 55;
for (i = 0; i < 16; i++)
printf("%d ", array[i]);
printf("\n");
quicksort(0, 15);
for (i = 0; i < 16; i++)
printf("%d ", array[i]);
printf("\n");
}

View File

@ -0,0 +1,2 @@
62 83 4 89 36 21 74 37 65 33 96 38 53 16 74 55
4 16 21 33 36 37 38 53 55 62 65 74 74 83 89 96

View File

@ -0,0 +1,13 @@
#include <stdio.h>
printf("%d\n", '\1');
printf("%d\n", '\10');
printf("%d\n", '\100');
printf("%d\n", '\x01');
printf("%d\n", '\x0e');
printf("%d\n", '\x10');
printf("%d\n", '\x40');
printf("test \x407\n");
void main() {}

View File

@ -0,0 +1,8 @@
1
8
64
1
14
16
64
test @7

12
tests/27_sizeof.c Normal file
View File

@ -0,0 +1,12 @@
#include <stdio.h>
char a;
int b;
double c;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(b));
printf("%d\n", sizeof(c));
void main() {}

3
tests/27_sizeof.expect Normal file
View File

@ -0,0 +1,3 @@
1
4
8

41
tests/28_strings.c Normal file
View File

@ -0,0 +1,41 @@
#include <stdio.h>
#include <string.h>
char a[10];
strcpy(a, "hello");
printf("%s\n", a);
strncpy(a, "gosh", 2);
printf("%s\n", a);
printf("%d\n", strcmp(a, "apple") > 0);
printf("%d\n", strcmp(a, "goere") > 0);
printf("%d\n", strcmp(a, "zebra") < 0);
printf("%d\n", strlen(a));
strcat(a, "!");
printf("%s\n", a);
printf("%d\n", strncmp(a, "apple", 2) > 0);
printf("%d\n", strncmp(a, "goere", 2) == 0);
printf("%d\n", strncmp(a, "goerg", 2) == 0);
printf("%d\n", strncmp(a, "zebra", 2) < 0);
printf("%s\n", index(a, 'o'));
printf("%s\n", rindex(a, 'l'));
printf("%d\n", rindex(a, 'x') == NULL);
memset(&a[1], 'r', 4);
printf("%s\n", a);
memcpy(&a[2], a, 2);
printf("%s\n", a);
printf("%d\n", memcmp(a, "apple", 4) > 0);
printf("%d\n", memcmp(a, "grgr", 4) == 0);
printf("%d\n", memcmp(a, "zebra", 4) < 0);
void main() {}

19
tests/28_strings.expect Normal file
View File

@ -0,0 +1,19 @@
hello
gollo
1
1
1
5
gollo!
1
1
1
1
ollo!
lo!
1
grrrr!
grgrr!
1
1
1

8
tests/29_array_address.c Normal file
View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include <string.h>
char a[10];
strcpy(a, "abcdef");
printf("%s\n", &a[1]);
void main() {}

View File

@ -0,0 +1 @@
bcdef

125
tests/30_hanoi.c Normal file
View File

@ -0,0 +1,125 @@
/* example from http://barnyard.syr.edu/quickies/hanoi.c */
/* hanoi.c: solves the tower of hanoi problem. (Programming exercise.) */
/* By Terry R. McConnell (12/2/97) */
/* Compile: cc -o hanoi hanoi.c */
/* This program does no error checking. But then, if it's right,
it's right ... right ? */
/* The original towers of hanoi problem seems to have been originally posed
by one M. Claus in 1883. There is a popular legend that goes along with
it that has been often repeated and paraphrased. It goes something like this:
In the great temple at Benares there are 3 golden spikes. On one of them,
God placed 64 disks increasing in size from bottom to top, at the beginning
of time. Since then, and to this day, the priest on duty constantly transfers
disks, one at a time, in such a way that no larger disk is ever put on top
of a smaller one. When the disks have been transferred entirely to another
spike the Universe will come to an end in a large thunderclap.
This paraphrases the original legend due to DeParville, La Nature, Paris 1884,
Part I, 285-286. For this and further information see: Mathematical
Recreations & Essays, W.W. Rouse Ball, MacMillan, NewYork, 11th Ed. 1967,
303-305.
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define N 4 /* This is the number of "disks" on tower A initially. */
/* Taken to be 64 in the legend. The number of moves
required, in general, is 2^N - 1. For N = 64, this is
18,446,744,073,709,551,615 */
int A[N], B[N], C[N]; /* These are the three towers. For example if the
state of A is 0,1,3,4, that means that there are three discs on A of sizes
1, 3, and 4. (Think of right as being the "down" direction.) */
void Hanoi(int,int*,int*,int*);
/* Print the current configuration of A, B, and C to the screen */
void
PrintAll()
{
int i;
printf("A: ");
for(i=0;i<N;i++)printf(" %d ",A[i]);
printf("\n");
printf("B: ");
for(i=0;i<N;i++)printf(" %d ",B[i]);
printf("\n");
printf("C: ");
for(i=0;i<N;i++)printf(" %d ",C[i]);
printf("\n");
printf("------------------------------------------\n");
return;
}
/* Move the leftmost nonzero element of source to dest, leave behind 0. */
/* Returns the value moved (not used.) */
int Move(int *source, int *dest)
{
int i,j;
while (i<N && (source[i])==0) i++;
while (j<N && (dest[j])==0) j++;
dest[j-1] = source[i];
source[i] = 0;
PrintAll(); /* Print configuration after each move. */
return dest[j-1];
}
/* Moves first n nonzero numbers from source to dest using the rules of Hanoi.
Calls itself recursively.
*/
void
Hanoi(int n,int *source, int *dest, int *spare)
{
int i;
if(n==1){
Move(source,dest);
return;
}
Hanoi(n-1,source,spare,dest);
Move(source,dest);
Hanoi(n-1,spare,dest,source);
return;
}
int
main()
{
int i;
/* initialize the towers */
for(i=0;i<N;i++)A[i]=i+1;
for(i=0;i<N;i++)B[i]=0;
for(i=0;i<N;i++)C[i]=0;
printf("Solution of Tower of Hanoi Problem with %d Disks\n\n",N);
/* Print the starting state */
printf("Starting state:\n");
PrintAll();
printf("\n\nSubsequent states:\n\n");
/* Do it! Use A = Source, B = Destination, C = Spare */
Hanoi(N,A,B,C);
return 0;
}

71
tests/30_hanoi.expect Normal file
View File

@ -0,0 +1,71 @@
Solution of Tower of Hanoi Problem with 4 Disks
Starting state:
A: 1 2 3 4
B: 0 0 0 0
C: 0 0 0 0
------------------------------------------
Subsequent states:
A: 0 2 3 4
B: 0 0 0 0
C: 0 0 0 1
------------------------------------------
A: 0 0 3 4
B: 0 0 0 2
C: 0 0 0 1
------------------------------------------
A: 0 0 3 4
B: 0 0 1 2
C: 0 0 0 0
------------------------------------------
A: 0 0 0 4
B: 0 0 1 2
C: 0 0 0 3
------------------------------------------
A: 0 0 1 4
B: 0 0 0 2
C: 0 0 0 3
------------------------------------------
A: 0 0 1 4
B: 0 0 0 0
C: 0 0 2 3
------------------------------------------
A: 0 0 0 4
B: 0 0 0 0
C: 0 1 2 3
------------------------------------------
A: 0 0 0 0
B: 0 0 0 4
C: 0 1 2 3
------------------------------------------
A: 0 0 0 0
B: 0 0 1 4
C: 0 0 2 3
------------------------------------------
A: 0 0 0 2
B: 0 0 1 4
C: 0 0 0 3
------------------------------------------
A: 0 0 1 2
B: 0 0 0 4
C: 0 0 0 3
------------------------------------------
A: 0 0 1 2
B: 0 0 3 4
C: 0 0 0 0
------------------------------------------
A: 0 0 0 2
B: 0 0 3 4
C: 0 0 0 1
------------------------------------------
A: 0 0 0 0
B: 0 2 3 4
C: 0 0 0 1
------------------------------------------
A: 0 0 0 0
B: 1 2 3 4
C: 0 0 0 0
------------------------------------------

12
tests/31_args.c Normal file
View File

@ -0,0 +1,12 @@
#include <stdio.h>
int main(int argc, char **argv)
{
int Count;
printf("hello world %d\n", argc);
for (Count = 0; Count < argc; Count++)
printf("arg %d: %s\n", Count, argv[Count]);
return 0;
}

6
tests/31_args.expect Normal file
View File

@ -0,0 +1,6 @@
hello world 5
arg 0: -
arg 1: arg1
arg 2: arg2
arg 3: arg3
arg 4: arg4

264
tests/32_led.c Normal file
View File

@ -0,0 +1,264 @@
/* example from http://barnyard.syr.edu/quickies/led.c */
/* led.c: print out number as if on 7 line led display. I.e., write integer
given on command line like this:
_ _ _
| _| _| |_| |_
| |_ _| | _| etc.
We assume the terminal behaves like a classical teletype. So the top
lines of all digits have to be printed first, then the middle lines of
all digits, etc.
By Terry R. McConnell
compile: cc -o led led.c
If you just want to link in the subroutine print_led that does all the
work, compile with -DNO_MAIN, and declare the following in any source file
that uses the call:
extern void print_led(unsigned long x, char *buf);
Bug: you cannot call repeatedly to print more than one number to a line.
That would require curses or some other terminal API that allows moving the
cursor to a previous line.
*/
#include <stdlib.h>
#include <stdio.h>
#define MAX_DIGITS 32
#define NO_MAIN
/* Print the top line of the digit d into buffer.
Does not null terminate buffer. */
void topline(int d, char *p){
*p++ = ' ';
switch(d){
/* all these have _ on top line */
case 0:
case 2:
case 3:
case 5:
case 7:
case 8:
case 9:
*p++ = '_';
break;
default:
*p++=' ';
}
*p++=' ';
}
/* Print the middle line of the digit d into the buffer.
Does not null terminate. */
void midline(int d, char *p){
switch(d){
/* those that have leading | on middle line */
case 0:
case 4:
case 5:
case 6:
case 8:
case 9:
*p++='|';
break;
default:
*p++=' ';
}
switch(d){
/* those that have _ on middle line */
case 2:
case 3:
case 4:
case 5:
case 6:
case 8:
case 9:
*p++='_';
break;
default:
*p++=' ';
}
switch(d){
/* those that have closing | on middle line */
case 0:
case 1:
case 2:
case 3:
case 4:
case 7:
case 8:
case 9:
*p++='|';
break;
default:
*p++=' ';
}
}
/* Print the bottom line of the digit d. Does not null terminate. */
void botline(int d, char *p){
switch(d){
/* those that have leading | on bottom line */
case 0:
case 2:
case 6:
case 8:
*p++='|';
break;
default:
*p++=' ';
}
switch(d){
/* those that have _ on bottom line */
case 0:
case 2:
case 3:
case 5:
case 6:
case 8:
*p++='_';
break;
default:
*p++=' ';
}
switch(d){
/* those that have closing | on bottom line */
case 0:
case 1:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
*p++='|';
break;
default:
*p++=' ';
}
}
/* Write the led representation of integer to string buffer. */
void print_led(unsigned long x, char *buf)
{
int i=0,n;
static int d[MAX_DIGITS];
/* extract digits from x */
n = ( x == 0L ? 1 : 0 ); /* 0 is a digit, hence a special case */
while(x){
d[n++] = (int)(x%10L);
if(n >= MAX_DIGITS)break;
x = x/10L;
}
/* print top lines of all digits */
for(i=n-1;i>=0;i--){
topline(d[i],buf);
buf += 3;
*buf++=' ';
}
*buf++='\n'; /* move teletype to next line */
/* print middle lines of all digits */
for(i=n-1;i>=0;i--){
midline(d[i],buf);
buf += 3;
*buf++=' ';
}
*buf++='\n';
/* print bottom lines of all digits */
for(i=n-1;i>=0;i--){
botline(d[i],buf);
buf += 3;
*buf++=' ';
}
*buf++='\n';
*buf='\0';
}
int main()
{
char buf[5*MAX_DIGITS];
print_led(1234567, buf);
printf("%s\n",buf);
return 0;
}
#ifndef NO_MAIN
int main(int argc, char **argv)
{
int i=0,n;
long x;
static int d[MAX_DIGITS];
char buf[5*MAX_DIGITS];
if(argc != 2){
fprintf(stderr,"led: usage: led integer\n");
return 1;
}
/* fetch argument from command line */
x = atol(argv[1]);
/* sanity check */
if(x<0){
fprintf(stderr,"led: %d must be non-negative\n",x);
return 1;
}
print_led(x,buf);
printf("%s\n",buf);
return 0;
}
#endif

4
tests/32_led.expect Normal file
View File

@ -0,0 +1,4 @@
_ _ _ _
| _| _| |_| |_ |_ |
| |_ _| | _| |_| |

10
tests/33_ternary_op.c Normal file
View File

@ -0,0 +1,10 @@
#include <stdio.h>
int Count;
for (Count = 0; Count < 10; Count++)
{
printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3));
}
void main() {}

View File

@ -0,0 +1,10 @@
0
1
4
9
16
15
18
21
24
27

View File

@ -0,0 +1,18 @@
#include <stdio.h>
int a[4];
a[0] = 12;
a[1] = 23;
a[2] = 34;
a[3] = 45;
printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
int b[4];
b = a;
printf("%d %d %d %d\n", b[0], b[1], b[2], b[3]);
void main() {}

Some files were not shown because too many files have changed in this diff Show More