[DEV] start a new project from scratch
This commit is contained in:
parent
209d18ed08
commit
9e770c657b
38
eci/Lexer.cpp
Normal file
38
eci/Lexer.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include <eci/Lexer.h>
|
||||
#include <eci/debug.h>
|
||||
|
||||
eci::Lexer::Lexer() {
|
||||
|
||||
}
|
||||
|
||||
eci::Lexer::~Lexer() {
|
||||
|
||||
}
|
||||
|
||||
void eci::Lexer::append(int32_t _tokenId, const std::string& _regularExpression) {
|
||||
m_searchList.insert(std::make_pair(_tokenId, std::regex(_regularExpression)));
|
||||
}
|
||||
|
||||
eci::LexerResult eci::Lexer::interprete(const std::string& _data) {
|
||||
eci::LexerResult result;
|
||||
for (auto &it : m_searchList) {
|
||||
ECI_INFO("Parse RegEx : " << it.first);// << " : '" << it.second.str() << "'");
|
||||
std::sregex_iterator it_search(_data.begin(), _data.end(), it.second);
|
||||
std::sregex_iterator it_end;
|
||||
for (std::sregex_iterator i = it_search; i != it_end; ++i) {
|
||||
std::smatch match = *i;
|
||||
std::string match_str = match.str();
|
||||
ECI_INFO(" " << match_str);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
33
eci/Lexer.h
Normal file
33
eci/Lexer.h
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_LEXER_H__
|
||||
#define __ECI_LEXER_H__
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <etk/stdTools.h>
|
||||
#include <regex>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace eci {
|
||||
using LexerResult = std::vector<std::pair<int32_t, std::string>>;
|
||||
|
||||
class Lexer {
|
||||
private:
|
||||
std::map<int32_t, std::regex> m_searchList;
|
||||
public:
|
||||
Lexer();
|
||||
~Lexer();
|
||||
void append(int32_t _tokenId, const std::string& _regularExpression);
|
||||
LexerResult interprete(const std::string& _data);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
124
eci/clibrary.c
124
eci/clibrary.c
@ -1,124 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#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(ECI_VERSION);
|
||||
VariableDefinePlatformVar(NULL, "ECI_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* _type, IOFILE *_stream) {
|
||||
switch (_type->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;
|
||||
case TypeFP:
|
||||
PrintStr("double", _stream);
|
||||
break;
|
||||
case TypeFunction:
|
||||
PrintStr("function", _stream);
|
||||
break;
|
||||
case TypeMacro:
|
||||
PrintStr("macro", _stream);
|
||||
break;
|
||||
case TypePointer:
|
||||
if (_type->FromType) {
|
||||
PrintType(_type->FromType, _stream);
|
||||
}
|
||||
PrintCh('*', _stream);
|
||||
break;
|
||||
case TypeArray:
|
||||
PrintType(_type->FromType, _stream);
|
||||
PrintCh('[', _stream);
|
||||
if (_type->ArraySize != 0) {
|
||||
PrintSimpleInt(_type->ArraySize, _stream);
|
||||
}
|
||||
PrintCh(']', _stream);
|
||||
break;
|
||||
case TypeStruct:
|
||||
PrintStr("struct ", _stream);
|
||||
PrintStr(_type->Identifier, _stream);
|
||||
break;
|
||||
case TypeUnion:
|
||||
PrintStr("union ", _stream);
|
||||
PrintStr(_type->Identifier, _stream);
|
||||
break;
|
||||
case TypeEnum:
|
||||
PrintStr("enum ", _stream);
|
||||
PrintStr(_type->Identifier, _stream);
|
||||
break;
|
||||
case TypeGotoLabel:
|
||||
PrintStr("goto label ", _stream);
|
||||
break;
|
||||
case Type_Type:
|
||||
PrintStr("type ", _stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_C_LIBRARY_H__
|
||||
#define __ECI_C_LIBRARY_H__
|
||||
|
||||
|
||||
|
||||
void LibraryInit();
|
||||
void LibraryAdd(struct Table* _globalTable, const char* _libraryName, struct LibraryFunction* _funcList);
|
||||
void CLibraryInit();
|
||||
void PrintType(struct ValueType* _type, IOFILE* _stream);
|
||||
|
||||
|
||||
#endif
|
@ -1,101 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* 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 */
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_C_TYPE_H__
|
||||
#define __ECI_C_TYPE_H__
|
||||
|
||||
|
||||
extern struct LibraryFunction StdCtypeFunctions[];
|
||||
|
||||
#endif
|
@ -1,582 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* 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 */
|
@ -1,168 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* stdio.h library for large systems - small embedded systems use clibrary.c instead */
|
||||
#include "../interpreter.h"
|
||||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static double M_EValue = 2.7182818284590452354; /* e */
|
||||
static double M_LOG2EValue = 1.4426950408889634074; /* log_2 e */
|
||||
static double M_LOG10EValue = 0.43429448190325182765; /* log_10 e */
|
||||
static double M_LN2Value = 0.69314718055994530942; /* log_e 2 */
|
||||
static double M_LN10Value = 2.30258509299404568402; /* log_e 10 */
|
||||
static double M_PIValue = 3.14159265358979323846; /* pi */
|
||||
static double M_PI_2Value = 1.57079632679489661923; /* pi/2 */
|
||||
static double M_PI_4Value = 0.78539816339744830962; /* pi/4 */
|
||||
static double M_1_PIValue = 0.31830988618379067154; /* 1/pi */
|
||||
static double M_2_PIValue = 0.63661977236758134308; /* 2/pi */
|
||||
static double M_2_SQRTPIValue = 1.12837916709551257390; /* 2/sqrt(pi) */
|
||||
static double M_SQRT2Value = 1.41421356237309504880; /* sqrt(2) */
|
||||
static double M_SQRT1_2Value = 0.70710678118654752440; /* 1/sqrt(2) */
|
||||
|
||||
|
||||
void MathSin(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = sin(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathCos(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs){
|
||||
_returnValue->Val->FP = cos(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathTan(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = tan(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathAsin(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = asin(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathAcos(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = acos(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathAtan(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = atan(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathAtan2(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = atan2(_param[0]->Val->FP, _param[1]->Val->FP);
|
||||
}
|
||||
|
||||
void MathSinh(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = sinh(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathCosh(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = cosh(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathTanh(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = tanh(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathExp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = exp(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathFabs(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = fabs(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathFmod(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = fmod(_param[0]->Val->FP, _param[1]->Val->FP);
|
||||
}
|
||||
|
||||
void MathFrexp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = frexp(_param[0]->Val->FP, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void MathLdexp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = ldexp(_param[0]->Val->FP, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void MathLog(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = log(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathLog10(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = log10(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathModf(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = modf(_param[0]->Val->FP, _param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void MathPow(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = pow(_param[0]->Val->FP, _param[1]->Val->FP);
|
||||
}
|
||||
|
||||
void MathSqrt(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = sqrt(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathRound(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
/* this awkward definition of "round()" due to it being inconsistently
|
||||
* declared in math.h */
|
||||
_returnValue->Val->FP = ceil(_param[0]->Val->FP - 0.5);
|
||||
}
|
||||
|
||||
void MathCeil(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = ceil(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
void MathFloor(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = floor(_param[0]->Val->FP);
|
||||
}
|
||||
|
||||
/* all math.h functions */
|
||||
struct LibraryFunction MathFunctions[] = {
|
||||
{ MathAcos, "float acos(float);" },
|
||||
{ MathAsin, "float asin(float);" },
|
||||
{ MathAtan, "float atan(float);" },
|
||||
{ MathAtan2, "float atan2(float, float);" },
|
||||
{ MathCeil, "float ceil(float);" },
|
||||
{ MathCos, "float cos(float);" },
|
||||
{ MathCosh, "float cosh(float);" },
|
||||
{ MathExp, "float exp(float);" },
|
||||
{ MathFabs, "float fabs(float);" },
|
||||
{ MathFloor, "float floor(float);" },
|
||||
{ MathFmod, "float fmod(float, float);" },
|
||||
{ MathFrexp, "float frexp(float, int *);" },
|
||||
{ MathLdexp, "float ldexp(float, int);" },
|
||||
{ MathLog, "float log(float);" },
|
||||
{ MathLog10, "float log10(float);" },
|
||||
{ MathModf, "float modf(float, float *);" },
|
||||
{ MathPow, "float pow(float,float);" },
|
||||
{ MathRound, "float round(float);" },
|
||||
{ MathSin, "float sin(float);" },
|
||||
{ MathSinh, "float sinh(float);" },
|
||||
{ MathSqrt, "float sqrt(float);" },
|
||||
{ MathTan, "float tan(float);" },
|
||||
{ MathTanh, "float tanh(float);" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void MathSetupFunc() {
|
||||
VariableDefinePlatformVar(NULL, "M_E", &FPType, (union AnyValue *)&M_EValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_LOG2E", &FPType, (union AnyValue *)&M_LOG2EValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_LOG10E", &FPType, (union AnyValue *)&M_LOG10EValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_LN2", &FPType, (union AnyValue *)&M_LN2Value, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_LN10", &FPType, (union AnyValue *)&M_LN10Value, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_PI", &FPType, (union AnyValue *)&M_PIValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_PI_2", &FPType, (union AnyValue *)&M_PI_2Value, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_PI_4", &FPType, (union AnyValue *)&M_PI_4Value, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_1_PI", &FPType, (union AnyValue *)&M_1_PIValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_2_PI", &FPType, (union AnyValue *)&M_2_PIValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_2_SQRTPI", &FPType, (union AnyValue *)&M_2_SQRTPIValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_SQRT2", &FPType, (union AnyValue *)&M_SQRT2Value, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "M_SQRT1_2", &FPType, (union AnyValue *)&M_SQRT1_2Value, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !BUILTIN_MINI_STDLIB */
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_MATH_H__
|
||||
#define __ECI_MATH_H__
|
||||
|
||||
|
||||
extern struct LibraryFunction MathFunctions[];
|
||||
void MathSetupFunc();
|
||||
|
||||
#endif
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
||||
#include "../interpreter.h"
|
||||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static int trueValue = 1;
|
||||
static int falseValue = 0;
|
||||
|
||||
|
||||
/* structure definitions */
|
||||
const char StdboolDefs[] = "typedef int bool;";
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void StdboolSetupFunc() {
|
||||
/* defines */
|
||||
VariableDefinePlatformVar(NULL, "true", &IntType, (union AnyValue *)&trueValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "false", &IntType, (union AnyValue *)&falseValue, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "__bool_true_false_are_defined", &IntType, (union AnyValue *)&trueValue, FALSE);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_STD_BOOL_H__
|
||||
#define __ECI_STD_BOOL_H__
|
||||
|
||||
|
||||
extern const char StdboolDefs[];
|
||||
void StdboolSetupFunc();
|
||||
|
||||
#endif
|
@ -1,659 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
} else if (ShowType == &FPType) {
|
||||
/* show a floating point number */
|
||||
if (IS_NUMERIC_COERCIBLE(ThisArg)) {
|
||||
StdioFprintfFP(&SOStream, OneFormatBuf, ExpressionCoerceFP(ThisArg));
|
||||
} else {
|
||||
StdioOutPuts("XXX", &SOStream);
|
||||
}
|
||||
} 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
|
@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_STDIO_H__
|
||||
#define __ECI_STDIO_H__
|
||||
|
||||
|
||||
extern const char StdioDefs[];
|
||||
extern struct LibraryFunction StdioFunctions[];
|
||||
void StdioSetupFunc();
|
||||
|
||||
#endif
|
@ -1,120 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* stdlib.h library for large systems - small embedded systems use clibrary.c instead */
|
||||
#include "../interpreter.h"
|
||||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static int ZeroValue = 0;
|
||||
|
||||
void StdlibAtof(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->FP = atof(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void StdlibStrtol(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strtol(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibStrtoul(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strtoul(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibMalloc(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = malloc(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibCalloc(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = calloc(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibRealloc(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = realloc(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibFree(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
free(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StdlibRand(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = rand();
|
||||
}
|
||||
|
||||
void StdlibSrand(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
srand(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibAbort(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
ProgramFail(_parser, "abort");
|
||||
}
|
||||
|
||||
void StdlibExit(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
PlatformExit(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibGetenv(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = getenv(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StdlibSystem(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = system(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StdlibAbs(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = abs(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void StdlibLabs(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = labs(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
/* all stdlib.h functions */
|
||||
struct LibraryFunction StdlibFunctions[] =
|
||||
{
|
||||
{ StdlibAtof, "float atof(char *);" },
|
||||
{ StdlibStrtod, "float strtod(char *,char **);" },
|
||||
{ StdlibAtoi, "int atoi(char *);" },
|
||||
{ StdlibAtol, "int atol(char *);" },
|
||||
{ StdlibStrtol, "int strtol(char *,char **,int);" },
|
||||
{ StdlibStrtoul, "int strtoul(char *,char **,int);" },
|
||||
{ StdlibMalloc, "void *malloc(int);" },
|
||||
{ StdlibCalloc, "void *calloc(int,int);" },
|
||||
{ StdlibRealloc, "void *realloc(void *,int);" },
|
||||
{ StdlibFree, "void free(void *);" },
|
||||
{ StdlibRand, "int rand();" },
|
||||
{ StdlibSrand, "void srand(int);" },
|
||||
{ StdlibAbort, "void abort();" },
|
||||
{ StdlibExit, "void exit(int);" },
|
||||
{ StdlibGetenv, "char *getenv(char *);" },
|
||||
{ StdlibSystem, "int system(char *);" },
|
||||
{ StdlibAbs, "int abs(int);" },
|
||||
{ StdlibLabs, "int labs(int);" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void StdlibSetupFunc() {
|
||||
/* define NULL, TRUE and FALSE */
|
||||
if (!VariableDefined(TableStrRegister("NULL"))) {
|
||||
VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_STD_LIB_H__
|
||||
#define __ECI_STD_LIB_H__
|
||||
|
||||
|
||||
extern struct LibraryFunction StdlibFunctions[];
|
||||
void StdlibSetupFunc();
|
||||
|
||||
#endif
|
@ -1,159 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* string.h library for large systems - small embedded systems use clibrary.c instead */
|
||||
#include "../interpreter.h"
|
||||
|
||||
#ifndef BUILTIN_MINI_STDLIB
|
||||
|
||||
static int ZeroValue = 0;
|
||||
|
||||
void StringStrcpy(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strcpy(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrncpy(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strncpy(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrcmp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strcmp(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrncmp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strncmp(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrcat(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strcat(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrncat(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strncat(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringIndex(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = index(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringRindex(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = rindex(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrlen(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strlen(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringMemset(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = memset(_param[0]->Val->Pointer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringMemcpy(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = memcpy(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringMemcmp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = memcmp(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringMemmove(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = memmove(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringMemchr(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = memchr(_param[0]->Val->Pointer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrchr(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strchr(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrrchr(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strrchr(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrcoll(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strcoll(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrerror(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strerror(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrspn(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strspn(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrcspn(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strcspn(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrpbrk(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strpbrk(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrstr(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strstr(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrtok(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strtok(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrxfrm(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = strxfrm(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void StringStrdup(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strdup(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void StringStrtok_r(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = strtok_r(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Pointer);
|
||||
}
|
||||
|
||||
/* all string.h functions */
|
||||
struct LibraryFunction StringFunctions[] = {
|
||||
{ StringIndex, "char *index(char *,int);" },
|
||||
{ StringRindex, "char *rindex(char *,int);" },
|
||||
{ StringMemcpy, "void *memcpy(void *,void *,int);" },
|
||||
{ StringMemmove, "void *memmove(void *,void *,int);" },
|
||||
{ StringMemchr, "void *memchr(char *,int,int);" },
|
||||
{ StringMemcmp, "int memcmp(void *,void *,int);" },
|
||||
{ StringMemset, "void *memset(void *,int,int);" },
|
||||
{ StringStrcat, "char *strcat(char *,char *);" },
|
||||
{ StringStrncat, "char *strncat(char *,char *,int);" },
|
||||
{ StringStrchr, "char *strchr(char *,int);" },
|
||||
{ StringStrrchr, "char *strrchr(char *,int);" },
|
||||
{ StringStrcmp, "int strcmp(char *,char *);" },
|
||||
{ StringStrncmp, "int strncmp(char *,char *,int);" },
|
||||
{ StringStrcoll, "int strcoll(char *,char *);" },
|
||||
{ StringStrcpy, "char *strcpy(char *,char *);" },
|
||||
{ StringStrncpy, "char *strncpy(char *,char *,int);" },
|
||||
{ StringStrerror, "char *strerror(int);" },
|
||||
{ StringStrlen, "int strlen(char *);" },
|
||||
{ StringStrspn, "int strspn(char *,char *);" },
|
||||
{ StringStrcspn, "int strcspn(char *,char *);" },
|
||||
{ StringStrpbrk, "char *strpbrk(char *,char *);" },
|
||||
{ StringStrstr, "char *strstr(char *,char *);" },
|
||||
{ StringStrtok, "char *strtok(char *,char *);" },
|
||||
{ StringStrxfrm, "int strxfrm(char *,char *,int);" },
|
||||
{ StringStrdup, "char *strdup(char *);" },
|
||||
{ StringStrtok_r, "char *strtok_r(char *,char *,char **);" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void StringSetupFunc() {
|
||||
/* define NULL */
|
||||
if (!VariableDefined(TableStrRegister("NULL"))) {
|
||||
VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !BUILTIN_MINI_STDLIB */
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_STRING_H__
|
||||
#define __ECI_STRING_H__
|
||||
|
||||
|
||||
extern struct LibraryFunction StringFunctions[];
|
||||
void StringSetupFunc();
|
||||
|
||||
#endif
|
@ -1,112 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 *);" },
|
||||
{ StdDifftime, "double difftime(int, int);" },
|
||||
{ StdGmtime, "struct tm *gmtime(int *);" },
|
||||
{ StdGmtime_r, "struct tm *gmtime_r(int *, struct tm *);" },
|
||||
{ StdLocaltime, "struct tm *localtime(int *);" },
|
||||
{ StdMktime, "int mktime(struct tm *ptm);" },
|
||||
{ StdTime, "int time(int *);" },
|
||||
{ StdStrftime, "int strftime(char *, int, char *, struct tm *);" },
|
||||
{ StdStrptime, "char *strptime(char *, char *, struct tm *);" },
|
||||
{ StdTimegm, "int timegm(struct tm *);" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void StdTimeSetupFunc() {
|
||||
/* make a "struct tm" which is the same size as a native tm structure */
|
||||
TypeCreateOpaqueStruct(NULL, TableStrRegister("tm"), sizeof(struct tm));
|
||||
/* define CLK_PER_SEC etc. */
|
||||
VariableDefinePlatformVar(NULL, "CLOCKS_PER_SEC", &IntType, (union AnyValue *)&CLOCKS_PER_SECValue, FALSE);
|
||||
#ifdef CLK_PER_SEC
|
||||
VariableDefinePlatformVar(NULL, "CLK_PER_SEC", &IntType, (union AnyValue *)&CLK_PER_SECValue, FALSE);
|
||||
#endif
|
||||
#ifdef CLK_TCK
|
||||
VariableDefinePlatformVar(NULL, "CLK_TCK", &IntType, (union AnyValue *)&CLK_TCKValue, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_TIME_H__
|
||||
#define __ECI_TIME_H__
|
||||
|
||||
extern const char StdTimeDefs[];
|
||||
extern struct LibraryFunction StdTimeFunctions[];
|
||||
void StdTimeSetupFunc();
|
||||
|
||||
#endif
|
@ -1,381 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void UnistdDup(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = dup(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdDup2(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = dup2(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void Unistd_Exit(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_exit(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFchown(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fchown(_param[0]->Val->Integer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFchdir(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fchdir(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFdatasync(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fdatasync(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFork(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fork();
|
||||
}
|
||||
|
||||
void UnistdFpathconf(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fpathconf(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFsync(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = fsync(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdFtruncate(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = ftruncate(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdGetcwd(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = getcwd(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdGetdtablesize(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getdtablesize();
|
||||
}
|
||||
|
||||
void UnistdGetegid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getegid();
|
||||
}
|
||||
|
||||
void UnistdGeteuid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = geteuid();
|
||||
}
|
||||
|
||||
void UnistdGetgid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getgid();
|
||||
}
|
||||
|
||||
void UnistdGethostid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = gethostid();
|
||||
}
|
||||
|
||||
void UnistdGetlogin(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = getlogin();
|
||||
}
|
||||
|
||||
void UnistdGetlogin_r(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getlogin_r(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdGetpagesize(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getpagesize();
|
||||
}
|
||||
|
||||
void UnistdGetpass(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = getpass(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void UnistdGetpgrp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getpgrp();
|
||||
}
|
||||
|
||||
void UnistdGetpid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getpid();
|
||||
}
|
||||
|
||||
void UnistdGetppid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getppid();
|
||||
}
|
||||
|
||||
void UnistdGetuid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = getuid();
|
||||
}
|
||||
|
||||
void UnistdGetwd(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = getcwd(_param[0]->Val->Pointer, PATH_MAX);
|
||||
}
|
||||
|
||||
void UnistdIsatty(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = isatty(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdLchown(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = lchown(_param[0]->Val->Pointer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdLink(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = link(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void UnistdLockf(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = lockf(_param[0]->Val->Integer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdLseek(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = lseek(_param[0]->Val->Integer, _param[1]->Val->Integer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdNice(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = nice(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdPathconf(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = pathconf(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdPause(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = pause();
|
||||
}
|
||||
|
||||
void UnistdRead(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = read(_param[0]->Val->Integer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdReadlink(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = readlink(_param[0]->Val->Pointer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdRmdir(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = rmdir(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void UnistdSbrk(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = sbrk(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSetgid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setgid(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSetpgid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setpgid(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSetpgrp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setpgrp();
|
||||
}
|
||||
|
||||
void UnistdSetregid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setregid(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSetreuid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setreuid(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSetsid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setsid();
|
||||
}
|
||||
|
||||
void UnistdSetuid(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = setuid(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSleep(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = sleep(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdSymlink(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = symlink(_param[0]->Val->Pointer, _param[1]->Val->Pointer);
|
||||
}
|
||||
|
||||
void UnistdSync(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
sync();
|
||||
}
|
||||
|
||||
void UnistdSysconf(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = sysconf(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdTcgetpgrp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = tcgetpgrp(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdTcsetpgrp(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = tcsetpgrp(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdTruncate(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = truncate(_param[0]->Val->Pointer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdTtyname(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Pointer = ttyname(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdTtyname_r(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = ttyname_r(_param[0]->Val->Integer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdUalarm(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = ualarm(_param[0]->Val->Integer, _param[1]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdUnlink(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = unlink(_param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
void UnistdUsleep(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = usleep(_param[0]->Val->Integer);
|
||||
}
|
||||
|
||||
void UnistdVfork(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = vfork();
|
||||
}
|
||||
|
||||
void UnistdWrite(struct ParseState *_parser, struct Value *_returnValue, struct Value **_param, int _numArgs) {
|
||||
_returnValue->Val->Integer = write(_param[0]->Val->Integer, _param[1]->Val->Pointer, _param[2]->Val->Integer);
|
||||
}
|
||||
|
||||
|
||||
/* handy structure definitions */
|
||||
const char UnistdDefs[] = "\
|
||||
typedef int uid_t; \
|
||||
typedef int gid_t; \
|
||||
typedef int pid_t; \
|
||||
typedef int off_t; \
|
||||
typedef int size_t; \
|
||||
typedef int ssize_t; \
|
||||
typedef int useconds_t;\
|
||||
typedef int intptr_t;\
|
||||
";
|
||||
|
||||
/* all unistd.h functions */
|
||||
struct LibraryFunction UnistdFunctions[] = {
|
||||
{ UnistdAccess, "int access(char *, int);" },
|
||||
{ UnistdAlarm, "unsigned int alarm(unsigned int);" },
|
||||
{ UnistdChdir, "int chdir(char *);" },
|
||||
{ UnistdChroot, "int chroot(char *);" },
|
||||
{ UnistdChown, "int chown(char *, uid_t, gid_t);" },
|
||||
{ UnistdClose, "int close(int);" },
|
||||
{ UnistdConfstr, "size_t confstr(int, char *, size_t);" },
|
||||
{ UnistdCtermid, "char *ctermid(char *);" },
|
||||
{ UnistdDup, "int dup(int);" },
|
||||
{ UnistdDup2, "int dup2(int, int);" },
|
||||
{ Unistd_Exit, "void _exit(int);" },
|
||||
{ UnistdFchown, "int fchown(int, uid_t, gid_t);" },
|
||||
{ UnistdFchdir, "int fchdir(int);" },
|
||||
{ UnistdFdatasync, "int fdatasync(int);" },
|
||||
{ UnistdFork, "pid_t fork(void);" },
|
||||
{ UnistdFpathconf, "long fpathconf(int, int);" },
|
||||
{ UnistdFsync, "int fsync(int);" },
|
||||
{ UnistdFtruncate, "int ftruncate(int, off_t);" },
|
||||
{ UnistdGetcwd, "char *getcwd(char *, size_t);" },
|
||||
{ UnistdGetdtablesize, "int getdtablesize(void);" },
|
||||
{ UnistdGetegid, "gid_t getegid(void);" },
|
||||
{ UnistdGeteuid, "uid_t geteuid(void);" },
|
||||
{ UnistdGetgid, "gid_t getgid(void);" },
|
||||
{ UnistdGethostid, "long gethostid(void);" },
|
||||
{ UnistdGetlogin, "char *getlogin(void);" },
|
||||
{ UnistdGetlogin_r, "int getlogin_r(char *, size_t);" },
|
||||
{ UnistdGetpagesize, "int getpagesize(void);" },
|
||||
{ UnistdGetpass, "char *getpass(char *);" },
|
||||
{ UnistdGetpgrp, "pid_t getpgrp(void);" },
|
||||
{ UnistdGetpid, "pid_t getpid(void);" },
|
||||
{ UnistdGetppid, "pid_t getppid(void);" },
|
||||
{ UnistdGetuid, "uid_t getuid(void);" },
|
||||
{ UnistdGetwd, "char *getwd(char *);" },
|
||||
{ UnistdIsatty, "int isatty(int);" },
|
||||
{ UnistdLchown, "int lchown(char *, uid_t, gid_t);" },
|
||||
{ UnistdLink, "int link(char *, char *);" },
|
||||
{ UnistdLockf, "int lockf(int, int, off_t);" },
|
||||
{ UnistdLseek, "off_t lseek(int, off_t, int);" },
|
||||
{ UnistdNice, "int nice(int);" },
|
||||
{ UnistdPathconf, "long pathconf(char *, int);" },
|
||||
{ UnistdPause, "int pause(void);" },
|
||||
{ UnistdRead, "ssize_t read(int, void *, size_t);" },
|
||||
{ UnistdReadlink, "int readlink(char *, char *, size_t);" },
|
||||
{ UnistdRmdir, "int rmdir(char *);" },
|
||||
{ UnistdSbrk, "void *sbrk(intptr_t);" },
|
||||
{ UnistdSetgid, "int setgid(gid_t);" },
|
||||
{ UnistdSetpgid, "int setpgid(pid_t, pid_t);" },
|
||||
{ UnistdSetpgrp, "pid_t setpgrp(void);" },
|
||||
{ UnistdSetregid, "int setregid(gid_t, gid_t);" },
|
||||
{ UnistdSetreuid, "int setreuid(uid_t, uid_t);" },
|
||||
{ UnistdSetsid, "pid_t setsid(void);" },
|
||||
{ UnistdSetuid, "int setuid(uid_t);" },
|
||||
{ UnistdSleep, "unsigned int sleep(unsigned int);" },
|
||||
{ UnistdSymlink, "int symlink(char *, char *);" },
|
||||
{ UnistdSync, "void sync(void);" },
|
||||
{ UnistdSysconf, "long sysconf(int);" },
|
||||
{ UnistdTcgetpgrp, "pid_t tcgetpgrp(int);" },
|
||||
{ UnistdTcsetpgrp, "int tcsetpgrp(int, pid_t);" },
|
||||
{ UnistdTruncate, "int truncate(char *, off_t);" },
|
||||
{ UnistdTtyname, "char *ttyname(int);" },
|
||||
{ UnistdTtyname_r, "int ttyname_r(int, char *, size_t);" },
|
||||
{ UnistdUalarm, "useconds_t ualarm(useconds_t, useconds_t);" },
|
||||
{ UnistdUnlink, "int unlink(char *);" },
|
||||
{ UnistdUsleep, "int usleep(useconds_t);" },
|
||||
{ UnistdVfork, "pid_t vfork(void);" },
|
||||
{ UnistdWrite, "ssize_t write(int, void *, size_t);" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* creates various system-dependent definitions */
|
||||
void UnistdSetupFunc() {
|
||||
/* define NULL */
|
||||
if (!VariableDefined(TableStrRegister("NULL"))) {
|
||||
VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE);
|
||||
}
|
||||
/* define optarg and friends */
|
||||
VariableDefinePlatformVar(NULL, "optarg", CharPtrType, (union AnyValue *)&optarg, TRUE);
|
||||
VariableDefinePlatformVar(NULL, "optind", &IntType, (union AnyValue *)&optind, TRUE);
|
||||
VariableDefinePlatformVar(NULL, "opterr", &IntType, (union AnyValue *)&opterr, TRUE);
|
||||
VariableDefinePlatformVar(NULL, "optopt", &IntType, (union AnyValue *)&optopt, TRUE);
|
||||
}
|
||||
|
||||
#endif /* !BUILTIN_MINI_STDLIB */
|
||||
|
@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_UNI_STD_H__
|
||||
#define __ECI_UNI_STD_H__
|
||||
|
||||
|
||||
extern const char UnistdDefs[];
|
||||
extern struct LibraryFunction UnistdFunctions[];
|
||||
void UnistdSetupFunc();
|
||||
|
||||
#endif
|
14
eci/debug.cpp
Normal file
14
eci/debug.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include <eci/debug.h>
|
||||
|
||||
int32_t eci::getLogId() {
|
||||
static int32_t g_val = etk::log::registerInstance("eci");
|
||||
return g_val;
|
||||
}
|
52
eci/debug.h
Normal file
52
eci/debug.h
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_DEBUG_H__
|
||||
#define __ECI_DEBUG_H__
|
||||
|
||||
#include <etk/log.h>
|
||||
|
||||
namespace eci {
|
||||
int32_t getLogId();
|
||||
};
|
||||
// TODO : Review this problem of multiple intanciation of "std::stringbuf sb"
|
||||
#define ECI_BASE(info,data) \
|
||||
do { \
|
||||
if (info <= etk::log::getLevel(eci::getLogId())) { \
|
||||
std::stringbuf sb; \
|
||||
std::ostream tmpStream(&sb); \
|
||||
tmpStream << data; \
|
||||
etk::log::logStream(eci::getLogId(), info, __LINE__, __class__, __func__, tmpStream); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ECI_CRITICAL(data) ECI_BASE(1, data)
|
||||
#define ECI_ERROR(data) ECI_BASE(2, data)
|
||||
#define ECI_WARNING(data) ECI_BASE(3, data)
|
||||
#ifdef DEBUG
|
||||
#define ECI_INFO(data) ECI_BASE(4, data)
|
||||
#define ECI_DEBUG(data) ECI_BASE(5, data)
|
||||
#define ECI_VERBOSE(data) ECI_BASE(6, data)
|
||||
#define ECI_TODO(data) ECI_BASE(4, "TODO : " << data)
|
||||
#else
|
||||
#define ECI_INFO(data) do { } while(false)
|
||||
#define ECI_DEBUG(data) do { } while(false)
|
||||
#define ECI_VERBOSE(data) do { } while(false)
|
||||
#define ECI_TODO(data) do { } while(false)
|
||||
#endif
|
||||
|
||||
#define ECI_ASSERT(cond,data) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
ECI_CRITICAL(data); \
|
||||
assert(!#cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
25
eci/eci.cpp
Normal file
25
eci/eci.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include <eci/eci.h>
|
||||
#include <eci/debug.h>
|
||||
#include <eci/lang/ParserCpp.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ECI_INFO("Start Application interpeter languages");
|
||||
if (argc<=1) {
|
||||
ECI_CRITICAL("need the file to parse");
|
||||
return -1;
|
||||
}
|
||||
eci::ParserCpp tmpParser;
|
||||
std::string data = etk::FSNodeReadAllData(argv[1]);
|
||||
tmpParser.parse(data);
|
||||
|
||||
return 0;
|
||||
}
|
@ -6,9 +6,7 @@
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_ERRNO_H__
|
||||
#define __ECI_ERRNO_H__
|
||||
|
||||
void StdErrnoSetupFunc();
|
||||
#ifndef __ECI_H__
|
||||
#define __ECI_H__
|
||||
|
||||
#endif
|
1529
eci/expression.c
1529
eci/expression.c
File diff suppressed because it is too large
Load Diff
@ -1,19 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_EXPRESSION_H__
|
||||
#define __ECI_EXPRESSION_H__
|
||||
|
||||
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 *_value);
|
||||
unsigned long ExpressionCoerceUnsignedInteger(struct Value *_value);
|
||||
double ExpressionCoerceFP(struct Value *_value);
|
||||
|
||||
#endif
|
127
eci/heap.c
127
eci/heap.c
@ -1,127 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
||||
#include "interpreter.h"
|
||||
|
||||
#define FREELIST_BUCKETS 8 /* freelists for 4, 8, 12 ... 32 byte allocs */
|
||||
#define SPLIT_MEM_THRESHOLD 16 /* don't split memory which is close in size */
|
||||
|
||||
static unsigned char *HeapMemory = NULL; /* stack memory since our heap is malloc()ed */
|
||||
static void *HeapBottom = NULL; /* the bottom of the (downward-growing) heap */
|
||||
static void *StackFrame = NULL; /* the current stack frame */
|
||||
void *HeapStackTop = NULL; /* the top of the stack */
|
||||
|
||||
static struct AllocNode *FreeListBucket[FREELIST_BUCKETS]; /* we keep a pool of freelist buckets to reduce fragmentation */
|
||||
static struct AllocNode *FreeListBig; /* free memory which doesn't fit in a bucket */
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
void ShowBigList() {
|
||||
struct AllocNode *LPos;
|
||||
printf("Heap: bottom=0x%lx 0x%lx-0x%lx, big freelist=", (long)HeapBottom, (long)&HeapMemory[0], (long)&HeapMemory[HEAP_SIZE]);
|
||||
for (LPos = FreeListBig; LPos != NULL; LPos = LPos->NextFree) {
|
||||
printf("0x%lx:%d ", (long)LPos, LPos->Size);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialise the stack and heap storage */
|
||||
void HeapInit(int StackOrHeapSize) {
|
||||
int Count;
|
||||
int AlignOffset = 0;
|
||||
HeapMemory = malloc(StackOrHeapSize);
|
||||
while (((unsigned long)&HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0) {
|
||||
AlignOffset++;
|
||||
}
|
||||
StackFrame = &HeapMemory[AlignOffset];
|
||||
HeapStackTop = &HeapMemory[AlignOffset];
|
||||
*(void **)StackFrame = NULL;
|
||||
HeapBottom = &HeapMemory[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset];
|
||||
FreeListBig = NULL;
|
||||
for (Count = 0; Count < FREELIST_BUCKETS; Count++) {
|
||||
FreeListBucket[Count] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HeapCleanup() {
|
||||
free(HeapMemory);
|
||||
}
|
||||
|
||||
/* allocate some space on the stack, in the current stack frame
|
||||
* clears memory. can return NULL if out of stack space */
|
||||
void *HeapAllocStack(int Size) {
|
||||
char *NewMem = HeapStackTop;
|
||||
char *NewTop = (char *)HeapStackTop + MEM_ALIGN(Size);
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("HeapAllocStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop);
|
||||
#endif
|
||||
if (NewTop > (char *)HeapBottom) {
|
||||
return NULL;
|
||||
}
|
||||
HeapStackTop = (void *)NewTop;
|
||||
memset((void *)NewMem, '\0', Size);
|
||||
return NewMem;
|
||||
}
|
||||
|
||||
/* allocate some space on the stack, in the current stack frame */
|
||||
void HeapUnpopStack(int Size) {
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("HeapUnpopStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop);
|
||||
#endif
|
||||
HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(Size));
|
||||
}
|
||||
|
||||
/* free some space at the top of the stack */
|
||||
int HeapPopStack(void *Addr, int Size) {
|
||||
int ToLose = MEM_ALIGN(Size);
|
||||
if (ToLose > ((char *)HeapStackTop - (char *)&HeapMemory[0])) {
|
||||
return FALSE;
|
||||
}
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("HeapPopStack(0x%lx, %ld) back to 0x%lx\n", (unsigned long)Addr, (unsigned long)MEM_ALIGN(Size), (unsigned long)HeapStackTop - ToLose);
|
||||
#endif
|
||||
HeapStackTop = (void *)((char *)HeapStackTop - ToLose);
|
||||
assert(Addr == NULL || HeapStackTop == Addr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* push a new stack frame on to the stack */
|
||||
void HeapPushStackFrame() {
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("Adding stack frame at 0x%lx\n", (unsigned long)HeapStackTop);
|
||||
#endif
|
||||
*(void **)HeapStackTop = StackFrame;
|
||||
StackFrame = HeapStackTop;
|
||||
HeapStackTop = (void *)((char *)HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE)));
|
||||
}
|
||||
|
||||
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
||||
int HeapPopStackFrame() {
|
||||
if (*(void **)StackFrame != NULL) {
|
||||
HeapStackTop = StackFrame;
|
||||
StackFrame = *(void **)StackFrame;
|
||||
#ifdef DEBUG_HEAP
|
||||
printf("Popping stack frame back to 0x%lx\n", (unsigned long)HeapStackTop);
|
||||
#endif
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
||||
void *HeapAllocMem(int Size) {
|
||||
return calloc(Size, 1);
|
||||
}
|
||||
|
||||
/* free some dynamically allocated memory */
|
||||
void HeapFreeMem(void *Mem) {
|
||||
free(Mem);
|
||||
}
|
||||
|
23
eci/heap.h
23
eci/heap.h
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_HEAP_H__
|
||||
#define __ECI_HEAP_H__
|
||||
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
100
eci/include.c
100
eci/include.c
@ -1,100 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#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);
|
||||
IncludeRegister("math.h", &MathSetupFunc, &MathFunctions[0], NULL);
|
||||
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 */
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_INCLUDE_H__
|
||||
#define __ECI_INCLUDE_H__
|
||||
|
||||
|
||||
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(); */
|
||||
|
||||
|
||||
#endif
|
@ -1,354 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_INTERPRETER_H__
|
||||
#define __ECI_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 */
|
||||
#define IS_FP(v) ((v)->Typ->Base == TypeFP)
|
||||
#define FP_VAL(v) ((v)->Val->FP)
|
||||
|
||||
#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
|
||||
TypeFP, //!< floating point
|
||||
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;
|
||||
double FP;
|
||||
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;
|
||||
extern struct ValueType FPType;
|
||||
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;
|
||||
|
||||
#include <eci/lex.h>
|
||||
#include <eci/parse.h>
|
||||
#include <eci/expression.h>
|
||||
|
||||
#include <eci/heap.h>
|
||||
|
||||
#include <eci/table.h>
|
||||
#include <eci/type.h>
|
||||
#include <eci/variable.h>
|
||||
#include <eci/include.h>
|
||||
#include <eci/clibrary.h>
|
||||
#include <eci/platform.h>
|
||||
#include <eci/cstdlib/ctype.h>
|
||||
#include <eci/cstdlib/errno.h>
|
||||
#include <eci/cstdlib/math.h>
|
||||
#include <eci/cstdlib/stdbool.h>
|
||||
#include <eci/cstdlib/stdio.h>
|
||||
#include <eci/cstdlib/stdlib.h>
|
||||
#include <eci/cstdlib/string.h>
|
||||
#include <eci/cstdlib/time.h>
|
||||
#include <eci/cstdlib/unistd.h>
|
||||
|
||||
|
||||
// TODO : Move this ... platform.h:
|
||||
|
||||
/* 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 *_mormat, 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();
|
||||
|
||||
|
||||
#endif
|
30
eci/lang/ParserCpp.cpp
Normal file
30
eci/lang/ParserCpp.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include <eci/lang/ParserCpp.h>
|
||||
|
||||
enum cppTokenList {
|
||||
tokenCppMultilineComment,
|
||||
tokenCppSingleLineComment,
|
||||
|
||||
};
|
||||
|
||||
eci::ParserCpp::ParserCpp() {
|
||||
m_lexer.append(tokenCppMultilineComment, "/\\*.*\\*/");
|
||||
m_lexer.append(tokenCppSingleLineComment, "//$");
|
||||
}
|
||||
|
||||
eci::ParserCpp::~ParserCpp() {
|
||||
|
||||
}
|
||||
|
||||
bool eci::ParserCpp::parse(const std::string& _data) {
|
||||
m_result = m_lexer.interprete(_data);
|
||||
return false;
|
||||
}
|
||||
|
26
eci/lang/ParserCpp.h
Normal file
26
eci/lang/ParserCpp.h
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_PARSER_CPP_H__
|
||||
#define __ECI_PARSER_CPP_H__
|
||||
|
||||
#include <eci/Lexer.h>
|
||||
|
||||
namespace eci {
|
||||
class ParserCpp {
|
||||
private:
|
||||
eci::Lexer m_lexer;
|
||||
eci::LexerResult m_result;
|
||||
public:
|
||||
ParserCpp();
|
||||
~ParserCpp();
|
||||
bool parse(const std::string& _data);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
975
eci/lex.c
975
eci/lex.c
@ -1,975 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
#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 },
|
||||
{ "double", TokenDoubleType, NULL },
|
||||
{ "else", TokenElse, NULL },
|
||||
{ "enum", TokenEnumType, NULL },
|
||||
{ "extern", TokenExternType, NULL },
|
||||
{ "float", TokenFloatType, NULL },
|
||||
{ "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;
|
||||
double FPResult;
|
||||
double FPDiv;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
case TokenFPConstant:
|
||||
LexValue.Typ = &FPType;
|
||||
break;
|
||||
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;
|
||||
}
|
25
eci/lex.h
25
eci/lex.h
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_LEX_H__
|
||||
#define __ECI_LEX_H__
|
||||
|
||||
|
||||
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();
|
||||
|
||||
#endif
|
766
eci/parse.c
766
eci/parse.c
@ -1,766 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#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("Starting eci " ECI_VERSION "\n");
|
||||
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");
|
||||
}
|
22
eci/parse.h
22
eci/parse.h
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_PARSE_H__
|
||||
#define __ECI_PARSE_H__
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
#endif
|
53
eci/picoc.c
53
eci/picoc.c
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
/* include only picoc.h here - should be able to use it with only the external interfaces, no internals from interpreter.h */
|
||||
#include "picoc.h"
|
||||
|
||||
/* platform-dependent code for running programs is in this file */
|
||||
|
||||
#include <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;
|
||||
}
|
45
eci/picoc.h
45
eci/picoc.h
@ -1,45 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_H__
|
||||
#define __ECI_H__
|
||||
|
||||
/* eci version number */
|
||||
#define ECI_VERSION "v0.1"
|
||||
|
||||
/* handy definitions */
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
/* 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
|
221
eci/platform.c
221
eci/platform.c
@ -1,221 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "picoc.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
/* the value passed to exit() */
|
||||
int PicocExitValue = 0;
|
||||
|
||||
/* initialise everything */
|
||||
void PicocInitialise(int StackSize) {
|
||||
BasicIOInit();
|
||||
HeapInit(StackSize);
|
||||
TableInit();
|
||||
VariableInit();
|
||||
LexInit();
|
||||
TypeInit();
|
||||
#ifndef NO_HASH_INCLUDE
|
||||
IncludeInit();
|
||||
#endif
|
||||
LibraryInit();
|
||||
#ifdef BUILTIN_MINI_STDLIB
|
||||
LibraryAdd(&GlobalTable, "c library", &CLibrary[0]);
|
||||
CLibraryInit();
|
||||
#endif
|
||||
PlatformLibraryInit();
|
||||
}
|
||||
|
||||
/* free memory */
|
||||
void PicocCleanup()
|
||||
{
|
||||
PlatformCleanup();
|
||||
#ifndef NO_HASH_INCLUDE
|
||||
IncludeCleanup();
|
||||
#endif
|
||||
ParseCleanup();
|
||||
LexCleanup();
|
||||
VariableCleanup();
|
||||
TypeCleanup();
|
||||
TableStrFree();
|
||||
HeapCleanup();
|
||||
}
|
||||
|
||||
/* platform-dependent code for running programs */
|
||||
|
||||
#define CALL_MAIN_NO_ARGS_RETURN_VOID "main();"
|
||||
#define CALL_MAIN_WITH_ARGS_RETURN_VOID "main(__argc,__argv);"
|
||||
#define CALL_MAIN_NO_ARGS_RETURN_INT "__exit_value = main();"
|
||||
#define CALL_MAIN_WITH_ARGS_RETURN_INT "__exit_value = main(__argc,__argv);"
|
||||
|
||||
void PicocCallMain(int argc, char **argv) {
|
||||
/* check if the program wants arguments */
|
||||
struct Value *FuncValue = NULL;
|
||||
if (!VariableDefined(TableStrRegister("main"))) {
|
||||
ProgramFail(NULL, "main() is not defined");
|
||||
}
|
||||
VariableGet(NULL, TableStrRegister("main"), &FuncValue);
|
||||
if (FuncValue->Typ->Base != TypeFunction) {
|
||||
ProgramFail(NULL, "main is not a function - can't call it");
|
||||
}
|
||||
if (FuncValue->Val->FuncDef.NumParams != 0) {
|
||||
/* define the arguments */
|
||||
VariableDefinePlatformVar(NULL, "__argc", &IntType, (union AnyValue *)&argc, FALSE);
|
||||
VariableDefinePlatformVar(NULL, "__argv", CharPtrPtrType, (union AnyValue *)&argv, FALSE);
|
||||
}
|
||||
if (FuncValue->Val->FuncDef.ReturnType == &VoidType) {
|
||||
if (FuncValue->Val->FuncDef.NumParams == 0) {
|
||||
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE);
|
||||
} else {
|
||||
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE);
|
||||
}
|
||||
} else {
|
||||
VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE);
|
||||
if (FuncValue->Val->FuncDef.NumParams == 0) {
|
||||
PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE);
|
||||
} else {
|
||||
PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintSourceTextErrorLine(const char *FileName, const char *SourceText, int Line, int CharacterPos) {
|
||||
int LineCount;
|
||||
const char *LinePos;
|
||||
const char *CPos;
|
||||
int CCount;
|
||||
if (SourceText != NULL) {
|
||||
/* find the source line */
|
||||
for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++) {
|
||||
if (*LinePos == '\n') {
|
||||
LineCount++;
|
||||
}
|
||||
}
|
||||
/* display the line */
|
||||
for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++) {
|
||||
PrintCh(*CPos, CStdOut);
|
||||
}
|
||||
PrintCh('\n', CStdOut);
|
||||
/* display the error position */
|
||||
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++) {
|
||||
if (*CPos == '\t') {
|
||||
PrintCh('\t', CStdOut);
|
||||
} else {
|
||||
PrintCh(' ', CStdOut);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* assume we're in interactive mode - try to make the arrow match up with the input text */
|
||||
for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++) {
|
||||
PrintCh(' ', CStdOut);
|
||||
}
|
||||
}
|
||||
PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos);
|
||||
}
|
||||
|
||||
/* display the source line and line number to identify an error */
|
||||
void PlatformErrorPrefix(struct ParseState *_parser) {
|
||||
if (_parser != NULL) {
|
||||
PrintSourceTextErrorLine(_parser->FileName, _parser->SourceText, _parser->Line, _parser->CharacterPos);
|
||||
}
|
||||
}
|
||||
|
||||
/* exit with a message */
|
||||
void ProgramFail(struct ParseState *_parser, const char *Message, ...) {
|
||||
va_list Args;
|
||||
PlatformErrorPrefix(_parser);
|
||||
va_start(Args, Message);
|
||||
PlatformVPrintf(Message, Args);
|
||||
va_end(Args);
|
||||
PlatformPrintf("\n");
|
||||
PlatformExit(1);
|
||||
}
|
||||
|
||||
/* like ProgramFail() but gives descriptive error messages for assignment */
|
||||
void AssignFail(struct ParseState *_parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo) {
|
||||
PlatformErrorPrefix(_parser);
|
||||
PlatformPrintf("can't %s ", (FuncName == NULL) ? "assign" : "set");
|
||||
if (Type1 != NULL) {
|
||||
PlatformPrintf(Format, Type1, Type2);
|
||||
} else {
|
||||
PlatformPrintf(Format, Num1, Num2);
|
||||
}
|
||||
if (FuncName != NULL) {
|
||||
PlatformPrintf(" in argument %d of call to %s()", ParamNo, FuncName);
|
||||
}
|
||||
ProgramFail(NULL, "");
|
||||
}
|
||||
|
||||
/* exit lexing with a message */
|
||||
void LexFail(struct LexState *Lexer, const char *Message, ...) {
|
||||
va_list Args;
|
||||
PrintSourceTextErrorLine(Lexer->FileName, Lexer->SourceText, Lexer->Line, Lexer->CharacterPos);
|
||||
va_start(Args, Message);
|
||||
PlatformVPrintf(Message, Args);
|
||||
va_end(Args);
|
||||
PlatformPrintf("\n");
|
||||
PlatformExit(1);
|
||||
}
|
||||
|
||||
/* printf for compiler error reporting */
|
||||
void PlatformPrintf(const char *Format, ...) {
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
PlatformVPrintf(Format, Args);
|
||||
va_end(Args);
|
||||
}
|
||||
|
||||
void PlatformVPrintf(const char *Format, va_list Args) {
|
||||
const char *FPos;
|
||||
for (FPos = Format; *FPos != '\0'; FPos++) {
|
||||
if (*FPos == '%') {
|
||||
FPos++;
|
||||
switch (*FPos) {
|
||||
case 's':
|
||||
PrintStr(va_arg(Args, char *), CStdOut);
|
||||
break;
|
||||
case 'd':
|
||||
PrintSimpleInt(va_arg(Args, int), CStdOut);
|
||||
break;
|
||||
case 'c':
|
||||
PrintCh(va_arg(Args, int), CStdOut);
|
||||
break;
|
||||
case 't':
|
||||
PrintType(va_arg(Args, struct ValueType *), CStdOut);
|
||||
break;
|
||||
case 'f':
|
||||
PrintFP(va_arg(Args, double), CStdOut);
|
||||
break;
|
||||
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);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_PLATFORM_H__
|
||||
#define __ECI_PLATFORM_H__
|
||||
|
||||
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
|
||||
#define ALIGN_TYPE void * /* the default data type to use for alignment */
|
||||
|
||||
#define GLOBAL_TABLE_SIZE 97 /* global variable table */
|
||||
#define STRING_TABLE_SIZE 97 /* shared string table size */
|
||||
#define STRING_LITERAL_TABLE_SIZE 97 /* string literal table size */
|
||||
#define PARAMETER_MAX 16 /* maximum number of parameters to a function */
|
||||
#define LINEBUFFER_MAX 256 /* maximum number of characters on a line */
|
||||
#define LOCAL_TABLE_SIZE 11 /* size of local variable table (can expand) */
|
||||
#define STRUCT_TABLE_SIZE 11 /* size of struct/union member table (can expand) */
|
||||
|
||||
#define INTERACTIVE_PROMPT_STATEMENT "eci> "
|
||||
#define INTERACTIVE_PROMPT_LINE " > "
|
||||
|
||||
/* host platform includes */
|
||||
#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>
|
||||
#include <math.h>
|
||||
|
||||
extern jmp_buf ExitBuf;
|
||||
|
||||
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
#include "../interpreter.h"
|
||||
|
||||
/* list of all library functions and their prototypes */
|
||||
struct LibraryFunction PlatformLibrary[] =
|
||||
{
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void PlatformLibraryInit()
|
||||
{
|
||||
LibraryAdd(&GlobalTable, "platform library", &PlatformLibrary);
|
||||
}
|
||||
|
@ -1,809 +0,0 @@
|
||||
#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);
|
||||
}
|
@ -1,945 +0,0 @@
|
||||
#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 }
|
||||
};
|
||||
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
|
@ -1,71 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "../picoc.h"
|
||||
#include "../interpreter.h"
|
||||
|
||||
/* 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) {
|
||||
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);
|
||||
}
|
164
eci/table.c
164
eci/table.c
@ -1,164 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
struct Table StringTable;
|
||||
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
|
||||
char *StrEmpty = NULL;
|
||||
|
||||
/* initialise the shared string system */
|
||||
void TableInit() {
|
||||
TableInitTable(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE);
|
||||
StrEmpty = TableStrRegister("");
|
||||
}
|
||||
|
||||
/* hash function for strings */
|
||||
static unsigned int TableHash(const char *Key, int Len) {
|
||||
unsigned int Hash = Len;
|
||||
int Offset;
|
||||
int Count;
|
||||
for (Count = 0, Offset = 8; Count < Len; Count++, Offset+=7) {
|
||||
if (Offset > sizeof(unsigned int) * 8 - 7) {
|
||||
Offset -= sizeof(unsigned int) * 8 - 6;
|
||||
}
|
||||
Hash ^= *Key++ << Offset;
|
||||
}
|
||||
return Hash;
|
||||
}
|
||||
|
||||
/* initialise a table */
|
||||
void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap) {
|
||||
Tbl->Size = Size;
|
||||
Tbl->OnHeap = OnHeap;
|
||||
Tbl->HashTable = HashTable;
|
||||
memset((void *)HashTable, '\0', sizeof(struct TableEntry *) * Size);
|
||||
}
|
||||
|
||||
/* check a hash table entry for a key */
|
||||
static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *AddAt) {
|
||||
struct TableEntry *Entry;
|
||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) {
|
||||
if (Entry->p.v.Key == Key) {
|
||||
return Entry; /* found */
|
||||
}
|
||||
}
|
||||
*AddAt = HashValue; /* didn't find it in the chain */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set an identifier to a value. returns FALSE if it already exists.
|
||||
* Key must be a shared string from TableStrRegister() */
|
||||
int TableSet(struct Table *Tbl, char *Key, struct Value *Val, const char *DeclFileName, int DeclLine, int DeclColumn) {
|
||||
int AddAt;
|
||||
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
|
||||
if (FoundEntry == NULL) {
|
||||
/* add it to the table */
|
||||
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
|
||||
NewEntry->DeclFileName = DeclFileName;
|
||||
NewEntry->DeclLine = DeclLine;
|
||||
NewEntry->DeclColumn = DeclColumn;
|
||||
NewEntry->p.v.Key = Key;
|
||||
NewEntry->p.v.Val = Val;
|
||||
NewEntry->Next = Tbl->HashTable[AddAt];
|
||||
Tbl->HashTable[AddAt] = NewEntry;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* find a value in a table. returns FALSE if not found.
|
||||
* Key must be a shared string from TableStrRegister() */
|
||||
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, const char **DeclFileName, int *DeclLine, int *DeclColumn) {
|
||||
int AddAt;
|
||||
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
|
||||
if (FoundEntry == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
*Val = FoundEntry->p.v.Val;
|
||||
if (DeclFileName != NULL) {
|
||||
*DeclFileName = FoundEntry->DeclFileName;
|
||||
*DeclLine = FoundEntry->DeclLine;
|
||||
*DeclColumn = FoundEntry->DeclColumn;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* remove an entry from the table */
|
||||
struct Value *TableDelete(struct Table *Tbl, const char *Key) {
|
||||
struct TableEntry **EntryPtr;
|
||||
int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */
|
||||
for (EntryPtr = &Tbl->HashTable[HashValue]; *EntryPtr != NULL; EntryPtr = &(*EntryPtr)->Next) {
|
||||
if ((*EntryPtr)->p.v.Key == Key) {
|
||||
struct TableEntry *DeleteEntry = *EntryPtr;
|
||||
struct Value *Val = DeleteEntry->p.v.Val;
|
||||
*EntryPtr = DeleteEntry->Next;
|
||||
HeapFreeMem(DeleteEntry);
|
||||
return Val;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check a hash table entry for an identifier */
|
||||
static struct TableEntry *TableSearchIdentifier(struct Table *Tbl, const char *Key, int Len, int *AddAt) {
|
||||
struct TableEntry *Entry;
|
||||
int HashValue = TableHash(Key, Len) % Tbl->Size;
|
||||
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) {
|
||||
if (strncmp(&Entry->p.Key[0], (char *)Key, Len) == 0 && Entry->p.Key[Len] == '\0') {
|
||||
// found
|
||||
return Entry;
|
||||
}
|
||||
}
|
||||
*AddAt = HashValue; /* didn't find it in the chain */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set an identifier and return the identifier. share if possible */
|
||||
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen) {
|
||||
int AddAt;
|
||||
struct TableEntry *FoundEntry = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt);
|
||||
if (FoundEntry != NULL) {
|
||||
return &FoundEntry->p.Key[0];
|
||||
} else {
|
||||
//add it to the table - we economise by not allocating the whole structure here
|
||||
struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1);
|
||||
if (NewEntry == NULL) {
|
||||
ProgramFail(NULL, "out of memory");
|
||||
}
|
||||
strncpy((char *)&NewEntry->p.Key[0], (char *)Ident, IdentLen);
|
||||
NewEntry->p.Key[IdentLen] = '\0';
|
||||
NewEntry->Next = Tbl->HashTable[AddAt];
|
||||
Tbl->HashTable[AddAt] = NewEntry;
|
||||
return &NewEntry->p.Key[0];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* register a string in the shared string store */
|
||||
char *TableStrRegister2(const char *Str, int Len) {
|
||||
return TableSetIdentifier(&StringTable, Str, Len);
|
||||
}
|
||||
|
||||
char *TableStrRegister(const char *Str) {
|
||||
return TableStrRegister2(Str, strlen((char *)Str));
|
||||
}
|
||||
|
||||
/* free all the strings */
|
||||
void TableStrFree() {
|
||||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
int Count;
|
||||
for (Count = 0; Count < StringTable.Size; Count++) {
|
||||
for (Entry = StringTable.HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
HeapFreeMem(Entry);
|
||||
}
|
||||
}
|
||||
}
|
23
eci/table.h
23
eci/table.h
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_TABLE_H__
|
||||
#define __ECI_TABLE_H__
|
||||
|
||||
|
||||
void TableInit();
|
||||
char *TableStrRegister(const char *_str);
|
||||
char *TableStrRegister2(const char *_str, int Len);
|
||||
void TableInitTable(struct Table *_table, struct TableEntry **_hashTable, int _size, int _onHeap);
|
||||
int TableSet(struct Table *_tbl, char *_key, struct Value *_val, const char *_declFileName, int _declLine, int _declColumn);
|
||||
int TableGet(struct Table *_tbl, const char *_key, struct Value **_val, const char **_declFileName, int *_declLine, int *_declColumn);
|
||||
struct Value *TableDelete(struct Table *_tbl, const char *_key);
|
||||
char *TableSetIdentifier(struct Table *_tbl, const char *_ident, int _identLen);
|
||||
void TableStrFree();
|
||||
|
||||
#endif
|
519
eci/type.c
519
eci/type.c
@ -1,519 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
/* some basic types */
|
||||
struct ValueType UberType;
|
||||
struct ValueType IntType;
|
||||
struct ValueType ShortType;
|
||||
struct ValueType CharType;
|
||||
struct ValueType LongType;
|
||||
struct ValueType UnsignedIntType;
|
||||
struct ValueType UnsignedShortType;
|
||||
struct ValueType UnsignedLongType;
|
||||
struct ValueType FPType;
|
||||
struct ValueType VoidType;
|
||||
struct ValueType TypeType;
|
||||
struct ValueType FunctionType;
|
||||
struct ValueType MacroType;
|
||||
struct ValueType EnumType;
|
||||
struct ValueType GotoLabelType;
|
||||
struct ValueType *CharPtrType;
|
||||
struct ValueType *CharPtrPtrType;
|
||||
struct ValueType *CharArrayType;
|
||||
struct ValueType *VoidPtrType;
|
||||
|
||||
static int PointerAlignBytes;
|
||||
static int IntAlignBytes;
|
||||
|
||||
/* add a new type to the set of types we know about */
|
||||
struct ValueType *TypeAdd(struct ParseState *_parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int Sizeof, int AlignBytes) {
|
||||
struct ValueType *NewType = VariableAlloc(_parser, sizeof(struct ValueType), TRUE);
|
||||
NewType->Base = Base;
|
||||
NewType->ArraySize = ArraySize;
|
||||
NewType->Sizeof = Sizeof;
|
||||
NewType->AlignBytes = AlignBytes;
|
||||
NewType->Identifier = Identifier;
|
||||
NewType->Members = NULL;
|
||||
NewType->FromType = ParentType;
|
||||
NewType->DerivedTypeList = NULL;
|
||||
NewType->OnHeap = TRUE;
|
||||
NewType->Next = ParentType->DerivedTypeList;
|
||||
ParentType->DerivedTypeList = NewType;
|
||||
return NewType;
|
||||
}
|
||||
|
||||
/* given a parent type, get a matching derived type and make one if necessary.
|
||||
* Identifier should be registered with the shared string table. */
|
||||
struct ValueType *TypeGetMatching(struct ParseState *_parser, struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates) {
|
||||
int Sizeof;
|
||||
int AlignBytes;
|
||||
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
||||
while ( ThisType != NULL
|
||||
&& ( ThisType->Base != Base
|
||||
|| ThisType->ArraySize != ArraySize
|
||||
|| ThisType->Identifier != Identifier) ) {
|
||||
ThisType = ThisType->Next;
|
||||
}
|
||||
if (ThisType != NULL) {
|
||||
if (AllowDuplicates) {
|
||||
return ThisType;
|
||||
} else {
|
||||
ProgramFail(_parser, "data type '%s' is already defined", Identifier);
|
||||
}
|
||||
}
|
||||
switch (Base) {
|
||||
case TypePointer:
|
||||
Sizeof = sizeof(void *);
|
||||
AlignBytes = PointerAlignBytes;
|
||||
break;
|
||||
case TypeArray:
|
||||
Sizeof = ArraySize * ParentType->Sizeof;
|
||||
AlignBytes = ParentType->AlignBytes;
|
||||
break;
|
||||
case TypeEnum:
|
||||
Sizeof = sizeof(int);
|
||||
AlignBytes = IntAlignBytes;
|
||||
break;
|
||||
default:
|
||||
Sizeof = 0;
|
||||
AlignBytes = 0;
|
||||
break;
|
||||
/* structs and unions will get bigger when we add members to them */
|
||||
}
|
||||
return TypeAdd(_parser, ParentType, Base, ArraySize, Identifier, Sizeof, AlignBytes);
|
||||
}
|
||||
|
||||
/* stack space used by a value */
|
||||
int TypeStackSizeValue(struct Value *Val) {
|
||||
if (Val != NULL && Val->ValOnStack) {
|
||||
return TypeSizeValue(Val, FALSE);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* memory used by a value */
|
||||
int TypeSizeValue(struct Value *Val, int Compact) {
|
||||
if (IS_INTEGER_NUMERIC(Val) && !Compact) {
|
||||
return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */
|
||||
} else if (Val->Typ->Base != TypeArray) {
|
||||
return Val->Typ->Sizeof;
|
||||
} else {
|
||||
return Val->Typ->FromType->Sizeof * Val->Typ->ArraySize;
|
||||
}
|
||||
}
|
||||
|
||||
/* memory used by a variable given its type and array size */
|
||||
int TypeSize(struct ValueType *Typ, int ArraySize, int Compact) {
|
||||
if (IS_INTEGER_NUMERIC_TYPE(Typ) && !Compact) {
|
||||
return sizeof(ALIGN_TYPE); /* allow some extra room for type extension */
|
||||
} else if (Typ->Base != TypeArray) {
|
||||
return Typ->Sizeof;
|
||||
} else {
|
||||
return Typ->FromType->Sizeof * ArraySize;
|
||||
}
|
||||
}
|
||||
|
||||
/* add a base type */
|
||||
void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof, int AlignBytes) {
|
||||
TypeNode->Base = Base;
|
||||
TypeNode->ArraySize = 0;
|
||||
TypeNode->Sizeof = Sizeof;
|
||||
TypeNode->AlignBytes = AlignBytes;
|
||||
TypeNode->Identifier = StrEmpty;
|
||||
TypeNode->Members = NULL;
|
||||
TypeNode->FromType = NULL;
|
||||
TypeNode->DerivedTypeList = NULL;
|
||||
TypeNode->OnHeap = FALSE;
|
||||
TypeNode->Next = UberType.DerivedTypeList;
|
||||
UberType.DerivedTypeList = TypeNode;
|
||||
}
|
||||
|
||||
/* initialise the type system */
|
||||
void TypeInit() {
|
||||
struct IntAlign {
|
||||
char x;
|
||||
int y;
|
||||
} ia;
|
||||
struct ShortAlign {
|
||||
char x;
|
||||
short y;
|
||||
} sa;
|
||||
struct CharAlign {
|
||||
char x;
|
||||
char y;
|
||||
} ca;
|
||||
struct LongAlign {
|
||||
char x;
|
||||
long y;
|
||||
} la;
|
||||
struct DoubleAlign {
|
||||
char x;
|
||||
double y;
|
||||
} da;
|
||||
struct PointerAlign {
|
||||
char x;
|
||||
void *y;
|
||||
} pa;
|
||||
|
||||
IntAlignBytes = (char *)&ia.y - &ia.x;
|
||||
PointerAlignBytes = (char *)&pa.y - &pa.x;
|
||||
|
||||
UberType.DerivedTypeList = NULL;
|
||||
TypeAddBaseType(&IntType, TypeInt, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(&ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x);
|
||||
TypeAddBaseType(&CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x);
|
||||
TypeAddBaseType(&LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x);
|
||||
TypeAddBaseType(&UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes);
|
||||
TypeAddBaseType(&UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x);
|
||||
TypeAddBaseType(&UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x);
|
||||
TypeAddBaseType(&VoidType, TypeVoid, 0, 1);
|
||||
TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(&MacroType, TypeMacro, sizeof(int), IntAlignBytes);
|
||||
TypeAddBaseType(&GotoLabelType, TypeGotoLabel, 0, 1);
|
||||
TypeAddBaseType(&FPType, TypeFP, sizeof(double), (char *)&da.y - &da.x);
|
||||
TypeAddBaseType(&TypeType, Type_Type, sizeof(double), (char *)&da.y - &da.x); /* must be large enough to cast to a double */
|
||||
CharArrayType = TypeAdd(NULL, &CharType, TypeArray, 0, StrEmpty, sizeof(char), (char *)&ca.y - &ca.x);
|
||||
CharPtrType = TypeAdd(NULL, &CharType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||
CharPtrPtrType = TypeAdd(NULL, CharPtrType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||
VoidPtrType = TypeAdd(NULL, &VoidType, TypePointer, 0, StrEmpty, sizeof(void *), PointerAlignBytes);
|
||||
}
|
||||
|
||||
/* deallocate heap-allocated types */
|
||||
void TypeCleanupNode(struct ValueType *Typ) {
|
||||
struct ValueType *SubType;
|
||||
struct ValueType *NextSubType;
|
||||
/* clean up and free all the sub-nodes */
|
||||
for (SubType = Typ->DerivedTypeList; SubType != NULL; SubType = NextSubType) {
|
||||
NextSubType = SubType->Next;
|
||||
TypeCleanupNode(SubType);
|
||||
if (SubType->OnHeap) {
|
||||
/* if it's a struct or union deallocate all the member values */
|
||||
if (SubType->Members != NULL) {
|
||||
VariableTableCleanup(SubType->Members);
|
||||
HeapFreeMem(SubType->Members);
|
||||
}
|
||||
/* free this node */
|
||||
HeapFreeMem(SubType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeCleanup() {
|
||||
TypeCleanupNode(&UberType);
|
||||
}
|
||||
|
||||
/* parse a struct or union declaration */
|
||||
void TypeParseStruct(struct ParseState *_parser, struct ValueType **Typ, int IsStruct) {
|
||||
struct Value *LexValue;
|
||||
struct ValueType *MemberType;
|
||||
char *MemberIdentifier;
|
||||
char *StructIdentifier;
|
||||
struct Value *MemberValue;
|
||||
enum LexToken Token;
|
||||
int AlignBoundary;
|
||||
Token = LexGetToken(_parser, &LexValue, FALSE);
|
||||
if (Token == TokenIdentifier) {
|
||||
LexGetToken(_parser, &LexValue, TRUE);
|
||||
StructIdentifier = LexValue->Val->Identifier;
|
||||
Token = LexGetToken(_parser, NULL, FALSE);
|
||||
} else {
|
||||
static char TempNameBuf[7] = "^s0000";
|
||||
StructIdentifier = PlatformMakeTempName(TempNameBuf);
|
||||
}
|
||||
*Typ = TypeGetMatching(_parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, Token != TokenLeftBrace);
|
||||
Token = LexGetToken(_parser, NULL, FALSE);
|
||||
if (Token != TokenLeftBrace) {
|
||||
/* use the already defined structure */
|
||||
if ((*Typ)->Members == NULL) {
|
||||
ProgramFail(_parser, "structure '%s' isn't defined", LexValue->Val->Identifier);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TopStackFrame != NULL) {
|
||||
ProgramFail(_parser, "struct/union definitions can only be globals");
|
||||
}
|
||||
LexGetToken(_parser, NULL, TRUE);
|
||||
(*Typ)->Members = VariableAlloc(_parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
|
||||
(*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table));
|
||||
TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
|
||||
do {
|
||||
TypeParse(_parser, &MemberType, &MemberIdentifier, NULL);
|
||||
if (MemberType == NULL || MemberIdentifier == NULL) {
|
||||
ProgramFail(_parser, "invalid type in struct");
|
||||
}
|
||||
MemberValue = VariableAllocValueAndData(_parser, sizeof(int), FALSE, NULL, TRUE);
|
||||
MemberValue->Typ = MemberType;
|
||||
if (IsStruct) {
|
||||
/* allocate this member's location in the struct */
|
||||
AlignBoundary = MemberValue->Typ->AlignBytes;
|
||||
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) {
|
||||
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||
}
|
||||
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
||||
(*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE);
|
||||
} else {
|
||||
/* union members always start at 0, make sure it's big enough to hold the largest member */
|
||||
MemberValue->Val->Integer = 0;
|
||||
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof) {
|
||||
(*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE);
|
||||
}
|
||||
}
|
||||
/* make sure to align to the size of the largest member's alignment */
|
||||
if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes) {
|
||||
(*Typ)->AlignBytes = MemberValue->Typ->AlignBytes;
|
||||
}
|
||||
/* define it */
|
||||
if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, _parser->FileName, _parser->Line, _parser->CharacterPos)) {
|
||||
ProgramFail(_parser, "member '%s' already defined", &MemberIdentifier);
|
||||
}
|
||||
if (LexGetToken(_parser, NULL, TRUE) != TokenSemicolon) {
|
||||
ProgramFail(_parser, "semicolon expected");
|
||||
}
|
||||
} while (LexGetToken(_parser, NULL, FALSE) != TokenRightBrace);
|
||||
/* now align the structure to the size of its largest member's alignment */
|
||||
AlignBoundary = (*Typ)->AlignBytes;
|
||||
if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) {
|
||||
(*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1));
|
||||
}
|
||||
LexGetToken(_parser, NULL, TRUE);
|
||||
}
|
||||
|
||||
/* create a system struct which has no user-visible members */
|
||||
struct ValueType *TypeCreateOpaqueStruct(struct ParseState *_parser, const char *StructName, int Size) {
|
||||
struct ValueType *Typ = TypeGetMatching(_parser, &UberType, TypeStruct, 0, StructName, FALSE);
|
||||
/* create the (empty) table */
|
||||
Typ->Members = VariableAlloc(_parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE);
|
||||
Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table));
|
||||
TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE);
|
||||
Typ->Sizeof = Size;
|
||||
return Typ;
|
||||
}
|
||||
|
||||
/* parse an enum declaration */
|
||||
void TypeParseEnum(struct ParseState *_parser, struct ValueType **Typ) {
|
||||
struct Value *LexValue;
|
||||
struct Value InitValue;
|
||||
enum LexToken Token;
|
||||
struct ValueType *EnumType;
|
||||
int EnumValue = 0;
|
||||
char *EnumIdentifier;
|
||||
Token = LexGetToken(_parser, &LexValue, FALSE);
|
||||
if (Token == TokenIdentifier) {
|
||||
LexGetToken(_parser, &LexValue, TRUE);
|
||||
EnumIdentifier = LexValue->Val->Identifier;
|
||||
Token = LexGetToken(_parser, NULL, FALSE);
|
||||
} else {
|
||||
static char TempNameBuf[7] = "^e0000";
|
||||
EnumIdentifier = PlatformMakeTempName(TempNameBuf);
|
||||
}
|
||||
EnumType = TypeGetMatching(_parser, &UberType, TypeEnum, 0, EnumIdentifier, Token != TokenLeftBrace);
|
||||
*Typ = &IntType;
|
||||
if (Token != TokenLeftBrace) {
|
||||
/* use the already defined enum */
|
||||
if ((*Typ)->Members == NULL) {
|
||||
ProgramFail(_parser, "enum '%s' isn't defined", EnumIdentifier);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TopStackFrame != NULL) {
|
||||
ProgramFail(_parser, "enum definitions can only be globals");
|
||||
}
|
||||
LexGetToken(_parser, NULL, TRUE);
|
||||
(*Typ)->Members = &GlobalTable;
|
||||
memset((void *)&InitValue, '\0', sizeof(struct Value));
|
||||
InitValue.Typ = &IntType;
|
||||
InitValue.Val = (union AnyValue *)&EnumValue;
|
||||
do {
|
||||
if (LexGetToken(_parser, &LexValue, TRUE) != TokenIdentifier) {
|
||||
ProgramFail(_parser, "identifier expected");
|
||||
}
|
||||
EnumIdentifier = LexValue->Val->Identifier;
|
||||
if (LexGetToken(_parser, NULL, FALSE) == TokenAssign) {
|
||||
LexGetToken(_parser, NULL, TRUE);
|
||||
EnumValue = ExpressionParseInt(_parser);
|
||||
}
|
||||
VariableDefine(_parser, EnumIdentifier, &InitValue, NULL, FALSE);
|
||||
|
||||
Token = LexGetToken(_parser, NULL, TRUE);
|
||||
if (Token != TokenComma && Token != TokenRightBrace) {
|
||||
ProgramFail(_parser, "comma expected");
|
||||
}
|
||||
EnumValue++;
|
||||
} while (Token == TokenComma);
|
||||
}
|
||||
|
||||
/* parse a type - just the basic type */
|
||||
int TypeParseFront(struct ParseState *_parser, struct ValueType **Typ, int *IsStatic) {
|
||||
struct ParseState Before;
|
||||
struct Value *LexerValue;
|
||||
enum LexToken Token;
|
||||
int Unsigned = FALSE;
|
||||
struct Value *VarValue;
|
||||
int StaticQualifier = FALSE;
|
||||
*Typ = NULL;
|
||||
/* ignore leading type qualifiers */
|
||||
ParserCopy(&Before, _parser);
|
||||
Token = LexGetToken(_parser, &LexerValue, TRUE);
|
||||
while ( Token == TokenStaticType
|
||||
|| Token == TokenAutoType
|
||||
|| Token == TokenRegisterType
|
||||
|| Token == TokenExternType) {
|
||||
if (Token == TokenStaticType) {
|
||||
StaticQualifier = TRUE;
|
||||
}
|
||||
Token = LexGetToken(_parser, &LexerValue, TRUE);
|
||||
}
|
||||
if (IsStatic != NULL) {
|
||||
*IsStatic = StaticQualifier;
|
||||
}
|
||||
/* handle signed/unsigned with no trailing type */
|
||||
if (Token == TokenSignedType || Token == TokenUnsignedType) {
|
||||
enum LexToken FollowToken = LexGetToken(_parser, &LexerValue, FALSE);
|
||||
Unsigned = (Token == TokenUnsignedType);
|
||||
if ( FollowToken != TokenIntType
|
||||
&& FollowToken != TokenLongType
|
||||
&& FollowToken != TokenShortType
|
||||
&& FollowToken != TokenCharType) {
|
||||
if (Token == TokenUnsignedType) {
|
||||
*Typ = &UnsignedIntType;
|
||||
} else {
|
||||
*Typ = &IntType;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
Token = LexGetToken(_parser, &LexerValue, TRUE);
|
||||
}
|
||||
switch (Token) {
|
||||
case TokenIntType:
|
||||
*Typ = Unsigned ? &UnsignedIntType : &IntType;
|
||||
break;
|
||||
case TokenShortType:
|
||||
*Typ = Unsigned ? &UnsignedShortType : &ShortType;
|
||||
break;
|
||||
case TokenCharType:
|
||||
*Typ = &CharType;
|
||||
break;
|
||||
case TokenLongType:
|
||||
*Typ = Unsigned ? &UnsignedLongType : &LongType;
|
||||
break;
|
||||
case TokenFloatType:
|
||||
case TokenDoubleType:
|
||||
*Typ = &FPType;
|
||||
break;
|
||||
case TokenVoidType:
|
||||
*Typ = &VoidType;
|
||||
break;
|
||||
case TokenStructType:
|
||||
case TokenUnionType:
|
||||
if (*Typ != NULL) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
TypeParseStruct(_parser, Typ, Token == TokenStructType);
|
||||
break;
|
||||
case TokenEnumType:
|
||||
if (*Typ != NULL) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
TypeParseEnum(_parser, Typ);
|
||||
break;
|
||||
case TokenIdentifier:
|
||||
/* we already know it's a typedef-defined type because we got here */
|
||||
VariableGet(_parser, LexerValue->Val->Identifier, &VarValue);
|
||||
*Typ = VarValue->Val->Typ;
|
||||
break;
|
||||
default:
|
||||
ParserCopy(_parser, &Before);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* parse a type - the part at the end after the identifier. eg. array specifications etc. */
|
||||
struct ValueType *TypeParseBack(struct ParseState *_parser, struct ValueType *FromType) {
|
||||
enum LexToken Token;
|
||||
struct ParseState Before;
|
||||
ParserCopy(&Before, _parser);
|
||||
Token = LexGetToken(_parser, NULL, TRUE);
|
||||
if (Token == TokenLeftSquareBracket) {
|
||||
/* add another array bound */
|
||||
enum RunMode OldMode = _parser->Mode;
|
||||
int ArraySize;
|
||||
_parser->Mode = RunModeRun;
|
||||
ArraySize = ExpressionParseInt(_parser);
|
||||
_parser->Mode = OldMode;
|
||||
if (LexGetToken(_parser, NULL, TRUE) != TokenRightSquareBracket) {
|
||||
ProgramFail(_parser, "']' expected");
|
||||
}
|
||||
return TypeGetMatching(_parser, TypeParseBack(_parser, FromType), TypeArray, ArraySize, StrEmpty, TRUE);
|
||||
} else {
|
||||
/* the type specification has finished */
|
||||
ParserCopy(_parser, &Before);
|
||||
return FromType;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse a type - the part which is repeated with each identifier in a declaration list */
|
||||
void TypeParseIdentPart(struct ParseState *_parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier) {
|
||||
struct ParseState Before;
|
||||
enum LexToken Token;
|
||||
struct Value *LexValue;
|
||||
int Done = FALSE;
|
||||
*Typ = BasicTyp;
|
||||
*Identifier = StrEmpty;
|
||||
while (!Done) {
|
||||
ParserCopy(&Before, _parser);
|
||||
Token = LexGetToken(_parser, &LexValue, TRUE);
|
||||
switch (Token) {
|
||||
case TokenOpenBracket:
|
||||
if (*Typ != NULL) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
TypeParse(_parser, Typ, Identifier, NULL);
|
||||
if (LexGetToken(_parser, NULL, TRUE) != TokenCloseBracket) {
|
||||
ProgramFail(_parser, "')' expected");
|
||||
}
|
||||
break;
|
||||
case TokenAsterisk:
|
||||
if (*Typ == NULL) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
*Typ = TypeGetMatching(_parser, *Typ, TypePointer, 0, StrEmpty, TRUE);
|
||||
break;
|
||||
case TokenIdentifier:
|
||||
if ( *Typ == NULL
|
||||
|| *Identifier != StrEmpty) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
*Identifier = LexValue->Val->Identifier;
|
||||
Done = TRUE;
|
||||
break;
|
||||
default:
|
||||
ParserCopy(_parser, &Before);
|
||||
Done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*Typ == NULL) {
|
||||
ProgramFail(_parser, "bad type declaration");
|
||||
}
|
||||
if (*Identifier != StrEmpty) {
|
||||
/* parse stuff after the identifier */
|
||||
*Typ = TypeParseBack(_parser, *Typ);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse a type - a complete declaration including identifier */
|
||||
void TypeParse(struct ParseState *_parser, struct ValueType **Typ, char **Identifier, int *IsStatic) {
|
||||
struct ValueType *BasicType;
|
||||
TypeParseFront(_parser, &BasicType, IsStatic);
|
||||
TypeParseIdentPart(_parser, BasicType, Typ, Identifier);
|
||||
}
|
||||
|
24
eci/type.h
24
eci/type.h
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_TYPE_H__
|
||||
#define __ECI_TYPE_H__
|
||||
|
||||
void TypeInit();
|
||||
void TypeCleanup();
|
||||
int TypeSize(struct ValueType *_type, int _arraySize, int _compact);
|
||||
int TypeSizeValue(struct Value *_value, int _compact);
|
||||
int TypeStackSizeValue(struct Value *_value);
|
||||
int TypeLastAccessibleOffset(struct Value *_value);
|
||||
int TypeParseFront(struct ParseState *_parser, struct ValueType **_type, int *_isStatic);
|
||||
void TypeParseIdentPart(struct ParseState *_parser, struct ValueType *_basicTyp, struct ValueType **_type, char **_identifier);
|
||||
void TypeParse(struct ParseState *_parser, struct ValueType **_type, 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);
|
||||
|
||||
#endif
|
361
eci/variable.c
361
eci/variable.c
@ -1,361 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
/* maximum size of a value to temporarily copy while we create a variable */
|
||||
#define MAX_TMP_COPY_BUF 256
|
||||
|
||||
/* the table of global definitions */
|
||||
struct Table GlobalTable;
|
||||
struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE];
|
||||
|
||||
/* the table of string literal values */
|
||||
struct Table StringLiteralTable;
|
||||
struct TableEntry *StringLiteralHashTable[STRING_LITERAL_TABLE_SIZE];
|
||||
|
||||
/* the stack */
|
||||
struct StackFrame *TopStackFrame = NULL;
|
||||
|
||||
|
||||
/* initialise the variable system */
|
||||
void VariableInit() {
|
||||
TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE);
|
||||
TableInitTable(&StringLiteralTable, &StringLiteralHashTable[0], STRING_LITERAL_TABLE_SIZE, TRUE);
|
||||
TopStackFrame = NULL;
|
||||
}
|
||||
|
||||
/* deallocate the contents of a variable */
|
||||
void VariableFree(struct Value *_value) {
|
||||
if (_value->ValOnHeap) {
|
||||
/* free function bodies */
|
||||
if ( _value->Typ == &FunctionType
|
||||
&& _value->Val->FuncDef.Intrinsic == NULL
|
||||
&& _value->Val->FuncDef.Body.Pos != NULL) {
|
||||
HeapFreeMem((void *)_value->Val->FuncDef.Body.Pos);
|
||||
}
|
||||
/* free macro bodies */
|
||||
if (_value->Typ == &MacroType) {
|
||||
HeapFreeMem((void *)_value->Val->MacroDef.Body.Pos);
|
||||
}
|
||||
/* free the value */
|
||||
HeapFreeMem(_value);
|
||||
}
|
||||
}
|
||||
|
||||
/* deallocate the global table and the string literal table */
|
||||
void VariableTableCleanup(struct Table *_hashTable) {
|
||||
struct TableEntry *Entry;
|
||||
struct TableEntry *NextEntry;
|
||||
int Count;
|
||||
for (Count = 0; Count < _hashTable->Size; ++Count) {
|
||||
for (Entry = _hashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry) {
|
||||
NextEntry = Entry->Next;
|
||||
VariableFree(Entry->p.v.Val);
|
||||
/* free the hash table entry */
|
||||
HeapFreeMem(Entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VariableCleanup() {
|
||||
VariableTableCleanup(&GlobalTable);
|
||||
VariableTableCleanup(&StringLiteralTable);
|
||||
}
|
||||
|
||||
/* allocate some memory, either on the heap or the stack and check if we've run out */
|
||||
void *VariableAlloc(struct ParseState *_parser,
|
||||
int _size,
|
||||
int _onHeap) {
|
||||
void *NewValue;
|
||||
if (_onHeap) {
|
||||
NewValue = HeapAllocMem(_size);
|
||||
} else {
|
||||
NewValue = HeapAllocStack(_size);
|
||||
}
|
||||
if (NewValue == NULL) {
|
||||
ProgramFail(_parser, "out of memory");
|
||||
}
|
||||
#ifdef DEBUG_HEAP
|
||||
if (!_onHeap) {
|
||||
printf("pushing %d at 0x%lx\n", _size, (unsigned long)NewValue);
|
||||
}
|
||||
#endif
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value either on the heap or the stack using space dependent on what type we want */
|
||||
struct Value *VariableAllocValueAndData(struct ParseState *_parser,
|
||||
int _dataSize,
|
||||
int _isLValue,
|
||||
struct Value *_lValueFrom,
|
||||
int _onHeap) {
|
||||
struct Value *NewValue = VariableAlloc(_parser, MEM_ALIGN(sizeof(struct Value)) + _dataSize, _onHeap);
|
||||
NewValue->Val = (union AnyValue *)((char *)NewValue + MEM_ALIGN(sizeof(struct Value)));
|
||||
NewValue->ValOnHeap = _onHeap;
|
||||
NewValue->ValOnStack = !_onHeap;
|
||||
NewValue->IsLValue = _isLValue;
|
||||
NewValue->LValueFrom = _lValueFrom;
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value given its type */
|
||||
struct Value *VariableAllocValueFromType(struct ParseState *_parser,
|
||||
struct ValueType *_type,
|
||||
int _isLValue,
|
||||
struct Value *_lValueFrom,
|
||||
int _onHeap) {
|
||||
int Size = TypeSize(_type, _type->ArraySize, FALSE);
|
||||
struct Value *NewValue = VariableAllocValueAndData(_parser, Size, _isLValue, _lValueFrom, _onHeap);
|
||||
assert(Size > 0 || _type == &VoidType);
|
||||
NewValue->Typ = _type;
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */
|
||||
struct Value *VariableAllocValueAndCopy(struct ParseState *_parser,
|
||||
struct Value *_fromValue,
|
||||
int _onHeap) {
|
||||
struct ValueType *DType = _fromValue->Typ;
|
||||
struct Value *NewValue;
|
||||
char TmpBuf[MAX_TMP_COPY_BUF];
|
||||
int CopySize = TypeSizeValue(_fromValue, TRUE);
|
||||
assert(CopySize <= MAX_TMP_COPY_BUF);
|
||||
memcpy((void *)&TmpBuf[0], (void *)_fromValue->Val, CopySize);
|
||||
NewValue = VariableAllocValueAndData(_parser, CopySize, _fromValue->IsLValue, _fromValue->LValueFrom, _onHeap);
|
||||
NewValue->Typ = DType;
|
||||
memcpy((void *)NewValue->Val, (void *)&TmpBuf[0], CopySize);
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value either on the heap or the stack from an existing AnyValue and type */
|
||||
struct Value *VariableAllocValueFromExistingData(struct ParseState *_parser,
|
||||
struct ValueType *_type,
|
||||
union AnyValue *_fromValue,
|
||||
int _isLValue,
|
||||
struct Value *_lValueFrom) {
|
||||
struct Value *NewValue = VariableAlloc(_parser, sizeof(struct Value), FALSE);
|
||||
NewValue->Typ = _type;
|
||||
NewValue->Val = _fromValue;
|
||||
NewValue->ValOnHeap = FALSE;
|
||||
NewValue->ValOnStack = FALSE;
|
||||
NewValue->IsLValue = _isLValue;
|
||||
NewValue->LValueFrom = _lValueFrom;
|
||||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value either on the heap or the stack from an existing Value, sharing the value */
|
||||
struct Value *VariableAllocValueShared(struct ParseState *_parser,
|
||||
struct Value *_fromValue) {
|
||||
return VariableAllocValueFromExistingData(_parser, _fromValue->Typ, _fromValue->Val, _fromValue->IsLValue, _fromValue->IsLValue ? _fromValue : NULL);
|
||||
}
|
||||
|
||||
/* define a variable. Ident must be registered */
|
||||
struct Value *VariableDefine(struct ParseState *_parser,
|
||||
char *_ident,
|
||||
struct Value *_initValue,
|
||||
struct ValueType *_type,
|
||||
int _makeWritable) {
|
||||
struct Value *AssignValue;
|
||||
if (_initValue != NULL) {
|
||||
AssignValue = VariableAllocValueAndCopy(_parser, _initValue, TopStackFrame == NULL);
|
||||
} else {
|
||||
AssignValue = VariableAllocValueFromType(_parser, _type, _makeWritable, NULL, TopStackFrame == NULL);
|
||||
}
|
||||
AssignValue->IsLValue = _makeWritable;
|
||||
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, _ident, AssignValue, _parser ? ((char *)_parser->FileName) : NULL, _parser ? _parser->Line : 0, _parser ? _parser->CharacterPos : 0)) {
|
||||
ProgramFail(_parser, "'%s' is already defined", _ident);
|
||||
}
|
||||
return AssignValue;
|
||||
}
|
||||
|
||||
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */
|
||||
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *_parser,
|
||||
char *_ident,
|
||||
struct ValueType *_type,
|
||||
int _isStatic,
|
||||
int *_firstVisit) {
|
||||
struct Value *ExistingValue;
|
||||
const char *DeclFileName;
|
||||
int DeclLine;
|
||||
int DeclColumn;
|
||||
if (_isStatic) {
|
||||
char MangledName[LINEBUFFER_MAX];
|
||||
char *MNPos = &MangledName[0];
|
||||
char *MNEnd = &MangledName[LINEBUFFER_MAX-1];
|
||||
const char *RegisteredMangledName;
|
||||
/* make the mangled static name (avoiding using sprintf() to minimise library impact) */
|
||||
memset((void *)&MangledName, '\0', sizeof(MangledName));
|
||||
*MNPos++ = '/';
|
||||
strncpy(MNPos, (char *)_parser->FileName, MNEnd - MNPos);
|
||||
MNPos += strlen(MNPos);
|
||||
if (TopStackFrame != NULL) {
|
||||
/* we're inside a function */
|
||||
if (MNEnd - MNPos > 0) {
|
||||
*MNPos++ = '/';
|
||||
}
|
||||
strncpy(MNPos, (char *)TopStackFrame->FuncName, MNEnd - MNPos);
|
||||
MNPos += strlen(MNPos);
|
||||
}
|
||||
if (MNEnd - MNPos > 0) {
|
||||
*MNPos++ = '/';
|
||||
}
|
||||
strncpy(MNPos, _ident, MNEnd - MNPos);
|
||||
RegisteredMangledName = TableStrRegister(MangledName);
|
||||
/* is this static already defined? */
|
||||
if (!TableGet(&GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) {
|
||||
/* define the mangled-named static variable store in the global scope */
|
||||
ExistingValue = VariableAllocValueFromType(_parser, _type, TRUE, NULL, TRUE);
|
||||
TableSet(&GlobalTable, (char *)RegisteredMangledName, ExistingValue, (char *)_parser->FileName, _parser->Line, _parser->CharacterPos);
|
||||
*_firstVisit = TRUE;
|
||||
}
|
||||
/* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */
|
||||
VariableDefinePlatformVar(_parser, _ident, ExistingValue->Typ, ExistingValue->Val, TRUE);
|
||||
return ExistingValue;
|
||||
} else {
|
||||
if ( _parser->Line != 0
|
||||
&& TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, _ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)
|
||||
&& DeclFileName == _parser->FileName
|
||||
&& DeclLine == _parser->Line
|
||||
&& DeclColumn == _parser->CharacterPos) {
|
||||
return ExistingValue;
|
||||
} else {
|
||||
return VariableDefine(_parser, _ident, NULL, _type, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if a variable with a given name is defined. Ident must be registered */
|
||||
int VariableDefined(const char *_ident) {
|
||||
struct Value *FoundValue;
|
||||
if ( TopStackFrame == NULL
|
||||
|| !TableGet(&TopStackFrame->LocalTable, _ident, &FoundValue, NULL, NULL, NULL)) {
|
||||
if (!TableGet(&GlobalTable, _ident, &FoundValue, NULL, NULL, NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* get the value of a variable. must be defined. Ident must be registered */
|
||||
void VariableGet(struct ParseState *_parser,
|
||||
const char *_ident,
|
||||
struct Value **_lValue) {
|
||||
if ( TopStackFrame == NULL
|
||||
|| !TableGet(&TopStackFrame->LocalTable, _ident, _lValue, NULL, NULL, NULL)) {
|
||||
if (!TableGet(&GlobalTable, _ident, _lValue, NULL, NULL, NULL)) {
|
||||
ProgramFail(_parser, "'%s' is undefined", _ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* define a global variable shared with a platform global. Ident will be registered */
|
||||
void VariableDefinePlatformVar(struct ParseState *_parser,
|
||||
char *_ident,
|
||||
struct ValueType *_type,
|
||||
union AnyValue *_fromValue,
|
||||
int _isWritable) {
|
||||
struct Value *SomeValue = VariableAllocValueAndData(NULL, 0, _isWritable, NULL, TRUE);
|
||||
SomeValue->Typ = _type;
|
||||
SomeValue->Val = _fromValue;
|
||||
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(_ident), SomeValue, _parser ? _parser->FileName : NULL, _parser ? _parser->Line : 0, _parser ? _parser->CharacterPos : 0)) {
|
||||
ProgramFail(_parser, "'%s' is already defined", _ident);
|
||||
}
|
||||
}
|
||||
|
||||
/* free and/or pop the top value off the stack. Var must be the top value on the stack! */
|
||||
void VariableStackPop(struct ParseState *_parser,
|
||||
struct Value *_variable) {
|
||||
int Success;
|
||||
#ifdef DEBUG_HEAP
|
||||
if (_variable->ValOnStack) {
|
||||
printf("popping %ld at 0x%lx\n", (unsigned long)(sizeof(struct Value) + TypeSizeValue(_variable, FALSE)), (unsigned long)_variable);
|
||||
}
|
||||
#endif
|
||||
if (_variable->ValOnHeap) {
|
||||
if (_variable->Val != NULL) {
|
||||
HeapFreeMem(_variable->Val);
|
||||
}
|
||||
Success = HeapPopStack(_variable, sizeof(struct Value));
|
||||
/* free from heap */
|
||||
} else if (_variable->ValOnStack) {
|
||||
Success = HeapPopStack(_variable, sizeof(struct Value) + TypeSizeValue(_variable, FALSE)); /* free from stack */
|
||||
} else {
|
||||
Success = HeapPopStack(_variable, sizeof(struct Value)); /* value isn't our problem */
|
||||
}
|
||||
if (!Success) {
|
||||
ProgramFail(_parser, "stack underrun");
|
||||
}
|
||||
}
|
||||
|
||||
/* add a stack frame when doing a function call */
|
||||
void VariableStackFrameAdd(struct ParseState *_parser,
|
||||
const char *_functionName,
|
||||
int _numberParameters) {
|
||||
struct StackFrame *NewFrame;
|
||||
HeapPushStackFrame();
|
||||
NewFrame = HeapAllocStack(sizeof(struct StackFrame) + sizeof(struct Value *) * _numberParameters);
|
||||
if (NewFrame == NULL) {
|
||||
ProgramFail(_parser, "out of memory");
|
||||
}
|
||||
ParserCopy(&NewFrame->ReturnParser, _parser);
|
||||
NewFrame->FuncName = _functionName;
|
||||
NewFrame->Parameter = (_numberParameters > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL;
|
||||
TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
|
||||
NewFrame->PreviousStackFrame = TopStackFrame;
|
||||
TopStackFrame = NewFrame;
|
||||
}
|
||||
|
||||
/* remove a stack frame */
|
||||
void VariableStackFramePop(struct ParseState *_parser) {
|
||||
if (TopStackFrame == NULL) {
|
||||
ProgramFail(_parser, "stack is empty - can't go back");
|
||||
}
|
||||
ParserCopy(_parser, &TopStackFrame->ReturnParser);
|
||||
TopStackFrame = TopStackFrame->PreviousStackFrame;
|
||||
HeapPopStackFrame();
|
||||
}
|
||||
|
||||
/* get a string literal. assumes that Ident is already registered. NULL if not found */
|
||||
struct Value *VariableStringLiteralGet(char *_ident) {
|
||||
struct Value *LVal = NULL;
|
||||
if (TableGet(&StringLiteralTable, _ident, &LVal, NULL, NULL, NULL)) {
|
||||
return LVal;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* define a string literal. assumes that Ident is already registered */
|
||||
void VariableStringLiteralDefine(char *_ident,
|
||||
struct Value *_value) {
|
||||
TableSet(&StringLiteralTable, _ident, _value, NULL, 0, 0);
|
||||
}
|
||||
|
||||
/* check a pointer for validity and dereference it for use */
|
||||
void *VariableDereferencePointer(struct ParseState *_parser,
|
||||
struct Value *_pointerValue,
|
||||
struct Value **_dereferenceValue,
|
||||
int *_dereferenceOffset,
|
||||
struct ValueType **_dereferenceType,
|
||||
int *_dereferenceIsLValue) {
|
||||
if (_dereferenceValue != NULL) {
|
||||
*_dereferenceValue = NULL;
|
||||
}
|
||||
if (_dereferenceType != NULL) {
|
||||
*_dereferenceType = _pointerValue->Typ->FromType;
|
||||
}
|
||||
if (_dereferenceOffset != NULL) {
|
||||
*_dereferenceOffset = 0;
|
||||
}
|
||||
if (_dereferenceIsLValue != NULL) {
|
||||
*_dereferenceIsLValue = TRUE;
|
||||
}
|
||||
return _pointerValue->Val->Pointer;
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_VARIABLE_H__
|
||||
#define __ECI_VARIABLE_H__
|
||||
|
||||
|
||||
void VariableInit();
|
||||
void VariableCleanup();
|
||||
void VariableFree(struct Value* _value);
|
||||
void VariableTableCleanup(struct Table* _hashTable);
|
||||
void *VariableAlloc(struct ParseState* _parser, int _size, int _onHeap);
|
||||
void VariableStackPop(struct ParseState *_parser, struct Value *_value);
|
||||
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 *_type, int _isLValue, struct Value *_lValueFrom, int _onHeap);
|
||||
struct Value *VariableAllocValueFromExistingData(struct ParseState *_parser, struct ValueType *_type, 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 *_type, int _makeWritable);
|
||||
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *_parser, char *_ident, struct ValueType *_type, 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 *_type, 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 *_value);
|
||||
void *VariableDereferencePointer(struct ParseState *_parser, struct Value *_pointerValue, struct Value **_dereferenceVal, int *_dereferenceOffset, struct ValueType **_dereferenceType, int *_derefIsLValue);
|
||||
|
||||
#endif
|
43
lutin_eci.py
43
lutin_eci.py
@ -1,43 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutinModule as module
|
||||
import lutinTools as tools
|
||||
import os
|
||||
import lutinMultiprocess
|
||||
|
||||
def get_desc():
|
||||
return "Ewol C Interpreter"
|
||||
|
||||
def create(target):
|
||||
# module name is 'edn' and type binary.
|
||||
myModule = module.Module(__file__, 'eci', 'BINARY')
|
||||
# add extra compilation flags :
|
||||
myModule.add_extra_compile_flags()
|
||||
# add the file to compile:
|
||||
myModule.add_src_file([
|
||||
'eci/clibrary.c',
|
||||
'eci/expression.c',
|
||||
'eci/heap.c',
|
||||
'eci/include.c',
|
||||
'eci/lex.c',
|
||||
'eci/parse.c',
|
||||
'eci/picoc.c',
|
||||
'eci/platform.c',
|
||||
'eci/table.c',
|
||||
'eci/type.c',
|
||||
'eci/variable.c',
|
||||
'eci/platform/platform_unix.c',
|
||||
'eci/platform/library_unix.c',
|
||||
'eci/cstdlib/ctype.c',
|
||||
'eci/cstdlib/errno.c',
|
||||
'eci/cstdlib/math.c',
|
||||
'eci/cstdlib/stdbool.c',
|
||||
'eci/cstdlib/stdio.c',
|
||||
'eci/cstdlib/stdlib.c',
|
||||
'eci/cstdlib/string.c',
|
||||
'eci/cstdlib/time.c',
|
||||
'eci/cstdlib/unistd.c'
|
||||
])
|
||||
myModule.add_export_path(tools.get_current_path(__file__))
|
||||
# add the currrent module at the
|
||||
return myModule
|
||||
|
25
lutin_eci2.py
Normal file
25
lutin_eci2.py
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/python
|
||||
import lutinModule as module
|
||||
import lutinTools as tools
|
||||
import os
|
||||
import lutinMultiprocess
|
||||
|
||||
def get_desc():
|
||||
return "Ewol C Interpreter"
|
||||
|
||||
def create(target):
|
||||
# module name is 'edn' and type binary.
|
||||
myModule = module.Module(__file__, 'eci2', 'BINARY')
|
||||
# add extra compilation flags :
|
||||
myModule.add_extra_compile_flags()
|
||||
# add the file to compile:
|
||||
myModule.add_src_file([
|
||||
'eci/eci.cpp',
|
||||
'eci/Lexer.cpp',
|
||||
'eci/debug.cpp',
|
||||
'eci/lang/ParserCpp.cpp'
|
||||
])
|
||||
myModule.add_export_path(tools.get_current_path(__file__))
|
||||
myModule.add_module_depend('etk')
|
||||
return myModule
|
||||
|
Loading…
x
Reference in New Issue
Block a user