[DEV] basic repo
This commit is contained in:
commit
dd444af28f
55
Makefile
Normal file
55
Makefile
Normal 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
91
README
Normal 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
676
clibrary.c
Normal 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
110
cstdlib/ctype.c
Normal 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
655
cstdlib/errno.c
Normal 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
187
cstdlib/math.c
Normal 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
22
cstdlib/stdbool.c
Normal 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
722
cstdlib/stdio.c
Normal 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
174
cstdlib/stdlib.c
Normal 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
178
cstdlib/string.c
Normal 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
124
cstdlib/time.c
Normal 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
499
cstdlib/unistd.c
Normal 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
1501
expression.c
Normal file
File diff suppressed because it is too large
Load Diff
285
heap.c
Normal file
285
heap.c
Normal 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
110
include.c
Normal 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
499
interpreter.h
Normal 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
971
lex.c
Normal 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
872
parse.c
Normal 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
101
picoc.c
Normal 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
46
picoc.h
Normal 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
236
platform.c
Normal 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
125
platform.h
Normal 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
13
platform/library_ffox.c
Normal 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
809
platform/library_srv1.c
Normal 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
945
platform/library_surveyor.c
Normal 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
29
platform/library_unix.c
Normal 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
51
platform/platform_ffox.c
Normal 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);
|
||||
}
|
||||
|
71
platform/platform_surveyor.c
Normal file
71
platform/platform_surveyor.c
Normal 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
102
platform/platform_unix.c
Normal 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
187
table.c
Normal 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
13
tests/00_assignment.c
Normal 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() {}
|
3
tests/00_assignment.expect
Normal file
3
tests/00_assignment.expect
Normal file
@ -0,0 +1,3 @@
|
||||
42
|
||||
64
|
||||
12, 34
|
10
tests/01_comment.c
Normal file
10
tests/01_comment.c
Normal 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
5
tests/01_comment.expect
Normal file
@ -0,0 +1,5 @@
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
||||
Hello
|
13
tests/02_printf.c
Normal file
13
tests/02_printf.c
Normal 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
15
tests/02_printf.expect
Normal 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
21
tests/03_struct.c
Normal 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
2
tests/03_struct.expect
Normal file
@ -0,0 +1,2 @@
|
||||
12
|
||||
34
|
10
tests/04_for.c
Normal file
10
tests/04_for.c
Normal 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
10
tests/04_for.expect
Normal file
@ -0,0 +1,10 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
16
tests/05_array.c
Normal file
16
tests/05_array.c
Normal 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
10
tests/05_array.expect
Normal file
@ -0,0 +1,10 @@
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
25
|
||||
36
|
||||
49
|
||||
64
|
||||
81
|
||||
100
|
24
tests/06_case.c
Normal file
24
tests/06_case.c
Normal 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
8
tests/06_case.expect
Normal file
@ -0,0 +1,8 @@
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
3
|
||||
0
|
25
tests/07_function.c
Normal file
25
tests/07_function.c
Normal 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
4
tests/07_function.expect
Normal file
@ -0,0 +1,4 @@
|
||||
9
|
||||
16
|
||||
a=1234
|
||||
qfunc()
|
19
tests/08_while.c
Normal file
19
tests/08_while.c
Normal 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
11
tests/08_while.expect
Normal file
@ -0,0 +1,11 @@
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
20
tests/09_do_while.c
Normal file
20
tests/09_do_while.c
Normal 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
11
tests/09_do_while.expect
Normal file
@ -0,0 +1,11 @@
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
37
tests/10_pointer.c
Normal file
37
tests/10_pointer.c
Normal 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
7
tests/10_pointer.expect
Normal 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
38
tests/11_precedence.c
Normal 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() {}
|
15
tests/11_precedence.expect
Normal file
15
tests/11_precedence.expect
Normal 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
10
tests/12_hashdefine.c
Normal 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() {}
|
2
tests/12_hashdefine.expect
Normal file
2
tests/12_hashdefine.expect
Normal file
@ -0,0 +1,2 @@
|
||||
12
|
||||
12, 24, 36
|
16
tests/13_integer_literals.c
Normal file
16
tests/13_integer_literals.c
Normal 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() {}
|
5
tests/13_integer_literals.expect
Normal file
5
tests/13_integer_literals.expect
Normal file
@ -0,0 +1,5 @@
|
||||
24680
|
||||
342391
|
||||
2386092
|
||||
2386092
|
||||
1365
|
17
tests/14_if.c
Normal file
17
tests/14_if.c
Normal 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
2
tests/14_if.expect
Normal file
@ -0,0 +1,2 @@
|
||||
a is true
|
||||
b is false
|
16
tests/15_recursion.c
Normal file
16
tests/15_recursion.c
Normal 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
10
tests/15_recursion.expect
Normal file
@ -0,0 +1,10 @@
|
||||
1
|
||||
2
|
||||
6
|
||||
24
|
||||
120
|
||||
720
|
||||
5040
|
||||
40320
|
||||
362880
|
||||
3628800
|
16
tests/16_nesting.c
Normal file
16
tests/16_nesting.c
Normal 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
18
tests/16_nesting.expect
Normal 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
24
tests/17_enum.c
Normal 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
4
tests/17_enum.expect
Normal file
@ -0,0 +1,4 @@
|
||||
0 1 2 3 54 73 74 75
|
||||
0
|
||||
12
|
||||
54
|
7
tests/18_include.c
Normal file
7
tests/18_include.c
Normal 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
3
tests/18_include.expect
Normal file
@ -0,0 +1,3 @@
|
||||
including
|
||||
included
|
||||
done
|
1
tests/18_include.h
Normal file
1
tests/18_include.h
Normal file
@ -0,0 +1 @@
|
||||
printf("included\n");
|
24
tests/19_pointer_arithmetic.c
Normal file
24
tests/19_pointer_arithmetic.c
Normal 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() {}
|
3
tests/19_pointer_arithmetic.expect
Normal file
3
tests/19_pointer_arithmetic.expect
Normal file
@ -0,0 +1,3 @@
|
||||
42
|
||||
b is not NULL
|
||||
c is NULL
|
20
tests/20_pointer_comparison.c
Normal file
20
tests/20_pointer_comparison.c
Normal 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() {}
|
6
tests/20_pointer_comparison.expect
Normal file
6
tests/20_pointer_comparison.expect
Normal file
@ -0,0 +1,6 @@
|
||||
12
|
||||
34
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
29
tests/21_char_array.c
Normal file
29
tests/21_char_array.c
Normal 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() {}
|
7
tests/21_char_array.expect
Normal file
7
tests/21_char_array.expect
Normal 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
45
tests/22_floating_point.c
Normal 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() {}
|
16
tests/22_floating_point.expect
Normal file
16
tests/22_floating_point.expect
Normal 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
49
tests/23_type_coercion.c
Normal 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() {}
|
15
tests/23_type_coercion.expect
Normal file
15
tests/23_type_coercion.expect
Normal 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
23
tests/24_math_library.c
Normal 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() {}
|
18
tests/24_math_library.expect
Normal file
18
tests/24_math_library.expect
Normal 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
80
tests/25_quicksort.c
Normal 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");
|
||||
}
|
||||
|
2
tests/25_quicksort.expect
Normal file
2
tests/25_quicksort.expect
Normal 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
|
13
tests/26_character_constants.c
Normal file
13
tests/26_character_constants.c
Normal 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() {}
|
8
tests/26_character_constants.expect
Normal file
8
tests/26_character_constants.expect
Normal file
@ -0,0 +1,8 @@
|
||||
1
|
||||
8
|
||||
64
|
||||
1
|
||||
14
|
||||
16
|
||||
64
|
||||
test @7
|
12
tests/27_sizeof.c
Normal file
12
tests/27_sizeof.c
Normal 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
3
tests/27_sizeof.expect
Normal file
@ -0,0 +1,3 @@
|
||||
1
|
||||
4
|
||||
8
|
41
tests/28_strings.c
Normal file
41
tests/28_strings.c
Normal 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
19
tests/28_strings.expect
Normal 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
8
tests/29_array_address.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char a[10];
|
||||
strcpy(a, "abcdef");
|
||||
printf("%s\n", &a[1]);
|
||||
|
||||
void main() {}
|
1
tests/29_array_address.expect
Normal file
1
tests/29_array_address.expect
Normal file
@ -0,0 +1 @@
|
||||
bcdef
|
125
tests/30_hanoi.c
Normal file
125
tests/30_hanoi.c
Normal 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
71
tests/30_hanoi.expect
Normal 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
12
tests/31_args.c
Normal 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
6
tests/31_args.expect
Normal 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
264
tests/32_led.c
Normal 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
4
tests/32_led.expect
Normal file
@ -0,0 +1,4 @@
|
||||
_ _ _ _
|
||||
| _| _| |_| |_ |_ |
|
||||
| |_ _| | _| |_| |
|
||||
|
10
tests/33_ternary_op.c
Normal file
10
tests/33_ternary_op.c
Normal 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() {}
|
10
tests/33_ternary_op.expect
Normal file
10
tests/33_ternary_op.expect
Normal file
@ -0,0 +1,10 @@
|
||||
0
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
15
|
||||
18
|
||||
21
|
||||
24
|
||||
27
|
18
tests/34_array_assignment.c
Normal file
18
tests/34_array_assignment.c
Normal 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
Loading…
x
Reference in New Issue
Block a user