Compare commits
No commits in common. "1.0" and "main" have entirely different histories.
13 changed files with 575 additions and 342 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,2 +0,0 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -5,5 +5,8 @@ out
|
|||
*.exe
|
||||
tiny
|
||||
src
|
||||
*.tar.gz
|
||||
*.out
|
||||
*.tar*
|
||||
*.out
|
||||
pkg
|
||||
.*/
|
||||
src
|
||||
41
LICENSE
Normal file
41
LICENSE
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
tiny data format and tiny language
|
||||
Copyright (C) 2025-2026 Kin Fuyuki
|
||||
|
||||
tiny data format and tiny language is free software; You can redistribute it and/or modify it under the terms of:
|
||||
- the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
||||
You don't have to do anything special to accept the license and you don’t have to notify anyone which that you have made that decision.
|
||||
|
||||
tiny data format and tiny language is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See your chosen license for more details.
|
||||
|
||||
You should have received a copy of both licenses along with tiny data format and tiny language.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
There is a strong belief within us that the license we have chosen provides not only the best solution for providing you with the essential freedom necessary to use tiny data format and tiny language within your projects, but also for maintaining enough copyleft strength for us to feel confident and secure with releasing our hard work to the public. For your convenience we've included our own interpretation of the license we chose, which can be seen below.
|
||||
|
||||
Our interpretation of the GNU Affero General Public License version 3: (Quoted words are words in which there exists a definition within the license to avoid ambiguity.)
|
||||
1. You must always provide the source code, copyright and license information of tiny data format and tiny language whenever you "convey" any part of tiny data format and tiny language;
|
||||
be it a verbatim copy or a modified copy.
|
||||
2. tiny data format and tiny language was developed as a library and has therefore been designed without knowledge of your work; as such the following should be implied:
|
||||
a) tiny data format and tiny language was developed without knowledge of your work; as such the following should be implied:
|
||||
i) tiny data format and tiny language should not fall under a work which is "based on" your work.
|
||||
ii) You should be free to use tiny data format and tiny language in a work covered by the:
|
||||
- GNU General Public License version 2
|
||||
- GNU Lesser General Public License version 2.1
|
||||
This is due to those licenses classifying tiny data format and tiny language as a work which would fall under an "aggregate" work by their terms and definitions;
|
||||
as such it should not be covered by their terms and conditions. The relevant passages start at:
|
||||
- Line 129 of the GNU General Public License version 2
|
||||
- Line 206 of the GNU Lesser General Public License version 2.1
|
||||
b) If you have not "modified", "adapted" or "extended" tiny data format and tiny language then your work should not be bound by this license,
|
||||
as you are using tiny data format and tiny language under the definition of an "aggregate" work.
|
||||
c) If you have "modified", "adapted" or "extended" tiny data format and tiny language then any of those modifications/extensions/adaptations which you have made
|
||||
should indeed be bound by this license, as you are using tiny data format and tiny language under the definition of a "based on" work.
|
||||
|
||||
Our hopes is that our own interpretation of license aligns perfectly with your own values and goals for using our work freely and securely. If you have any questions at all about the licensing chosen for tiny data format and tiny language you can email us directly at <project support email> or you can get in touch with the license authors (the Free Software Foundation) at licensing@fsf.org to gain their opinion too.
|
||||
|
||||
Alternatively you can provide feedback and acquire the support you need at our support forum. We'll definitely try and help you as soon as possible, and to the best of our ability; as we understand that user experience is everything, so we want to make you as happy as possible! So feel free to get in touch via our support forum and chat with other users of tiny data format and tiny language here at:
|
||||
https://github.com/kin-fuyuki/tiny-cpp/issues
|
||||
|
||||
Thanks, and we hope you enjoy using tiny data format and tiny language and that it's everything you ever hoped it could be.
|
||||
7
Makefile
Normal file
7
Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
CC=clang++
|
||||
CFLAGS=-std=c++23
|
||||
|
||||
install:
|
||||
rm -rf /usr/include/tiny/
|
||||
mkdir -p /usr/include/tiny/
|
||||
cp inc/*.h /usr/include/tiny/
|
||||
19
PKGBUILD
19
PKGBUILD
|
|
@ -1,19 +0,0 @@
|
|||
Maintainer=kin fuyuki
|
||||
pkgname=tiny
|
||||
pkgver=1.0
|
||||
pkgrel=1
|
||||
pkgdesc="tiny script runner"
|
||||
arch=('any')
|
||||
url="https://crystalsoft.neocities.org"
|
||||
license=('AGPL3')
|
||||
makedepends=('gcc')
|
||||
source=("https://github.com/J-K-Tech/${pkgname}/archive/refs/tags/${pkgver}.tar.gz")
|
||||
sha256sums=('2af3bfa2937e7452f74895db7e12c60b67000dc9c2e9f1aa1e53f7e1537d2636')
|
||||
|
||||
build() {
|
||||
g++ -O3 term.cpp main.cpp -o tiny
|
||||
}
|
||||
|
||||
package() {
|
||||
install -Dm755 tiny "$pkgdir/tiny"
|
||||
}
|
||||
60
README.md
60
README.md
|
|
@ -1,59 +1,3 @@
|
|||
# Tiny
|
||||
# TINY SOFTWARE SUITE
|
||||
|
||||
A tiny command line interpreter for organizing, you can split huge single line commands into lines and even add comments and variables!
|
||||
|
||||
## Features
|
||||
|
||||
Multi-command: You can make multiple commands in same `.tmk` file by having a line that starts with `\n`
|
||||
|
||||
Comments: You can use comments in the file to your peers or future you remember what you done, also useful to separate sections of a command
|
||||
|
||||
Variables: If a line starts with `%` it will get all the name of it until hit the second `%` and to set variables the line has to start with `set`
|
||||
|
||||
Ignore space: Add `\` at the start of the line so it will not add an space before it.
|
||||
|
||||
(all written in this line after the `\n` and `%var%` will be ignored and be seen as comments)
|
||||
|
||||
## example
|
||||
|
||||
```
|
||||
;set variables
|
||||
set flags=-Os
|
||||
;compiler
|
||||
g++
|
||||
%flags%
|
||||
|
||||
;files
|
||||
main.cpp
|
||||
|
||||
;includes
|
||||
-lstdc++
|
||||
|
||||
-I/usr/
|
||||
;to not add space between /usr/ and include, you add \ so it will be "/usr/include" and not "/usr/ include"
|
||||
\include
|
||||
|
||||
;output
|
||||
-o tiny.exe
|
||||
|
||||
;end command
|
||||
\n
|
||||
;run tiny
|
||||
tiny.exe
|
||||
```
|
||||
|
||||
# WARNING, THIS PROGRAM HAS STRICT SYNTAX
|
||||
## The line MUST to have `;`,`set` and `%` as first character to be detected as comment, setter and variable, so you can have it in the command (without being interpreted by Tiny) by adding a space before.
|
||||
|
||||
|
||||
# Roadmap
|
||||
|
||||
- Add variables when loading a Tiny script
|
||||
|
||||
- Create functions
|
||||
|
||||
- Stuff people ask for
|
||||
|
||||
# Compatibility
|
||||
|
||||
This is supposed to run anywhere, if it dont work in a platform please warn me (maybe exotic systems with uncommon headers like master system or whatever might not work out of the box... idk.. if it even has a CLI lol)
|
||||
[visit the wiki](https://github.com/kin-fuyuki/tiny/wiki)
|
||||
20
build.tmk
20
build.tmk
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
clang++ term.cpp main.cpp -m32 --target=i686-w64-mingw32-gcc -O3 -o out/tiny9x.exe -Wl,--major-subsystem-version=4,--minor-subsystem-version=0
|
||||
|
||||
\n
|
||||
clang++ term.cpp main.cpp -m32 --target=i686-w64-mingw32-gcc -O3 -o out/tiny2k.exe -Wl,--major-subsystem-version=5,--minor-subsystem-version=0
|
||||
|
||||
\n
|
||||
clang++ term.cpp main.cpp -m64 --target=x86_64-w64-mingw32-gcc -O3 -o out/tinyxp64.exe -Wl,--major-subsystem-version=5,--minor-subsystem-version=1
|
||||
|
||||
\n
|
||||
clang++ term.cpp main.cpp -m64 --target=x86_64-w64-mingw32-gcc -O3 -o out/tiny.exe -Wl,--major-subsystem-version=10,--minor-subsystem-version=1
|
||||
|
||||
\n
|
||||
clang++ term.cpp main.cpp -O3 -o out/tiny
|
||||
|
||||
\n
|
||||
clang++ term.cpp main.cpp -m32 -O3 -o out/tiny32
|
||||
|
||||
\n
|
||||
;djgpp term.cpp main.cpp -O3 -o out/tiny32
|
||||
412
inc/tdf.h
Normal file
412
inc/tdf.h
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#ifndef TINYDATAFORMAT_H
|
||||
#define TINYDATAFORMAT_H
|
||||
#define TINYDEFINEHEADER "0000_TDF_HEADER_DEFINE"
|
||||
#include "term.h"
|
||||
|
||||
#define GENSTART {int LAST = trimmed.find(' ', 3);if (LAST == std::string::npos) goto FAILTOPARSE;std::string KEY = trimmed.substr(2, LAST - 2);
|
||||
#define GENEND (VALUE)};todelete.push_back(DAT.datapointer); (*current)[KEY]=DAT;break;}
|
||||
#define GENMID ); if (idx != sub.size()) goto FAILTOPARSE;}catch(const std::invalid_argument&){goto FAILTOPARSE;}TDF_DATA DAT={
|
||||
|
||||
#define INTGENSTART GENSTART std::string sub = trimmed.substr(LAST + 1);size_t idx; int VALUE; try{ VALUE=stoi(sub, &idx,
|
||||
#define INTGENEND , new int GENEND
|
||||
|
||||
#define SETSTART value){boost::unordered_map<std::string,TDF_DATA>*current=data;for(size_t i=0;i<path.size();i++){\
|
||||
auto it=current->find(path[i]);if(it==current->end()){if(i==path.size()-1){TDF_DATA DAT={
|
||||
#define SETMID (value)};todelete.push_back(DAT.datapointer);(*current)[path[i]]=DAT;return;}else{\
|
||||
boost::unordered_map<std::string,TDF_DATA>*newmap=new boost::unordered_map<std::string,TDF_DATA>();TDF_DATA DAT={TDF_CLASS,newmap}\
|
||||
;todelete.push_back(DAT.datapointer);(*current)[path[i]]=DAT;current=newmap;}}else{if(i==path.size()-1){if(it->second.type!=
|
||||
#define SETEND *>(it->second.datapointer)=value;return;}if(it->second.type!=TDF_CLASS)throw TDF_ERR(SET_MISMATCH,filepath,path);\
|
||||
current=(boost::unordered_map<std::string,TDF_DATA>*)(it->second.datapointer);}}}
|
||||
|
||||
|
||||
#define GETSTART (std::vector<std::string>path){boost::unordered_map<std::string,TDF_DATA>*current=data;for(size_t i=0;i<path.size();i++){\
|
||||
auto it=current->find(path[i]);if(it==current->end())throw TDF_ERR(PATH_NOT_FOUND,filepath,path);if(i==path.size()-1){if(it->second.type!=
|
||||
#define GETMID )throw TDF_ERR(GET_MISMATCH,filepath,path);return *static_cast<
|
||||
#define GETEND *>(it->second.datapointer);}\
|
||||
if(it->second.type!=TDF_CLASS)throw TDF_ERR(GET_MISMATCH,filepath,path);current=(boost::unordered_map<std::string,TDF_DATA>*)(it->second.datapointer);}\
|
||||
throw TDF_ERR(PATH_NOT_FOUND,filepath,path);}
|
||||
|
||||
#define DEFAULTGET(TYPE_NAME, ACTUAL_TYPE) ACTUAL_TYPE TYPE_NAME(std::vector<std::string> path, ACTUAL_TYPE defaultval) {try { return\
|
||||
TYPE_NAME(path); } catch (TDF_ERR &e) { warning((char*)e.what()); return defaultval; } }
|
||||
|
||||
namespace tiny {
|
||||
enum TDF_ERROR{
|
||||
SET_MISMATCH=1,
|
||||
GET_MISMATCH=2,
|
||||
PATH_NOT_FOUND=3,
|
||||
UNKNOWN_ERROR=-1,
|
||||
FILE_NOT_FOUND=4,
|
||||
FAILED_TO_PARSE=5,
|
||||
NULL_POINTER=6,
|
||||
};
|
||||
class TDF_ERR : public std::exception
|
||||
{
|
||||
public:
|
||||
std::string message;
|
||||
|
||||
explicit TDF_ERR(TDF_ERROR err,std::string file,std::vector<std::string>path) _GLIBCXX_TXN_SAFE{
|
||||
message="TDF ERROR: ";
|
||||
|
||||
switch(err){
|
||||
case SET_MISMATCH:
|
||||
message+="SET TYPE MISMATCH ";
|
||||
break;
|
||||
case GET_MISMATCH:
|
||||
message+="GET TYPE MISMATCH ";
|
||||
break;
|
||||
case PATH_NOT_FOUND:
|
||||
message+="PATH NOT FOUND ";
|
||||
break;
|
||||
case FILE_NOT_FOUND:
|
||||
message+="FILE NOT FOUND "+file;
|
||||
return;
|
||||
case FAILED_TO_PARSE:
|
||||
message+="FAILED TO PARSE "+file+" AT LINE :"+path[0];
|
||||
return;
|
||||
case NULL_POINTER:
|
||||
message+="NULL POINTER of selector "+path[0];
|
||||
message+="FAILED TO PARSE "+file+" AT LINE :"+path[1];
|
||||
return;
|
||||
default:
|
||||
message+="UNKNOWN ERROR ";
|
||||
break;
|
||||
}
|
||||
|
||||
message+=" ON FILE: "+file+" AT PATH: ";
|
||||
for(size_t i=0;i<path.size();i++){
|
||||
message+=path[i];
|
||||
if(i!=path.size()-1)
|
||||
message+=" . ";
|
||||
}
|
||||
}
|
||||
virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW{
|
||||
return message.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
enum TDF_Type : unsigned char {
|
||||
TDF_DEFINES = 10, //bool
|
||||
TDF_BOOL = 3, //bool
|
||||
TDF_CHAR = 1, //char
|
||||
TDF_BINARY = 4, //int
|
||||
TDF_INT = 5, //int
|
||||
TDF_HEX = 7, //int
|
||||
TDF_STR = 0, //string
|
||||
TDF_BLOCK = 200, //string
|
||||
TDF_FLOAT = 6, //float
|
||||
TDF_POINTER = 8, //vector<string>
|
||||
TDF_CLASS = 9, //class
|
||||
};
|
||||
struct TDF_DATA {
|
||||
TDF_Type type;
|
||||
void* datapointer;
|
||||
};
|
||||
struct TDF_FUNCS{
|
||||
boost::unordered_map<char,int>funcs;
|
||||
TDF_DATA(*FUNCS[])(std::string);
|
||||
};
|
||||
struct TDF_FILE{
|
||||
boost::unordered_map<std::string,TDF_DATA>* data=nullptr;
|
||||
char*filepath;
|
||||
TDF_FUNCS FUNCS;
|
||||
std::vector<void*> todelete;
|
||||
void close(){
|
||||
for(size_t i=0;i<todelete.size();i++){
|
||||
delete static_cast<boost::unordered_map<std::string,TDF_DATA>*> (todelete[i]);
|
||||
}
|
||||
}
|
||||
void* read(){
|
||||
char CCHAR=' ';
|
||||
int INDEX=0;
|
||||
std::ifstream file(filepath);
|
||||
|
||||
if (file.is_open()) {
|
||||
if (data!=nullptr)
|
||||
delete data;
|
||||
data=new boost::unordered_map<std::string,TDF_DATA>();
|
||||
todelete.push_back(data);
|
||||
boost::unordered_map<std::string,TDF_DATA>*current=data;
|
||||
|
||||
std::vector<boost::unordered_map<std::string,TDF_DATA>*>stack={};
|
||||
std::vector<std::string>pathvec={};
|
||||
bool textblock=false;
|
||||
std::string BLOCK;
|
||||
std::string BLOCKKEY;
|
||||
std::vector<std::string> *defines=new std::vector<std::string>();
|
||||
TDF_DATA defdat={TDF_DEFINES,defines};
|
||||
(*current)[TINYDEFINEHEADER]=defdat;
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
++INDEX;
|
||||
if (line.length()==0){continue;}
|
||||
if (textblock){
|
||||
std::string blockline = line;
|
||||
size_t lead = blockline.find_first_not_of(' ');
|
||||
if(lead != std::string::npos){
|
||||
blockline = blockline.substr(lead);
|
||||
}
|
||||
if (blockline=="\\"){
|
||||
textblock=false;
|
||||
TDF_DATA DAT={TDF_BLOCK,new std::string(BLOCK)};
|
||||
todelete.push_back(DAT.datapointer);
|
||||
(*current)[BLOCKKEY]=DAT;
|
||||
}else{
|
||||
BLOCK+=line+"\n";
|
||||
}
|
||||
}
|
||||
else{
|
||||
std::string trimmed = line;
|
||||
size_t lead = trimmed.find_first_not_of(' ');
|
||||
if(lead != std::string::npos){
|
||||
trimmed = trimmed.substr(lead);
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
if (trimmed.empty() || trimmed[0]=='#'){continue;}
|
||||
if (trimmed.size() > 1 && trimmed[1]==' '){
|
||||
CCHAR=trimmed[0];
|
||||
switch (CCHAR) {
|
||||
|
||||
case '"':GENSTART std::string VALUE; VALUE=trimmed.substr(LAST + 1); TDF_DATA DAT = { TDF_STR, new std::string GENEND
|
||||
|
||||
|
||||
case 'S':{
|
||||
int LAST = trimmed.find(' ', 2);
|
||||
std::string KEY;
|
||||
if (LAST != std::string::npos){
|
||||
KEY = trimmed.substr(2, LAST - 2);
|
||||
}else{
|
||||
KEY = trimmed.substr(2);
|
||||
}
|
||||
BLOCKKEY=KEY;
|
||||
BLOCK="";
|
||||
textblock=true;
|
||||
break;}
|
||||
|
||||
|
||||
case '\'':GENSTART if (LAST + 1 >= trimmed.size()) goto FAILTOPARSE;char VALUE=trimmed.at(LAST + 1);
|
||||
if (LAST + 2 < trimmed.size()) goto FAILTOPARSE;TDF_DATA DAT = { TDF_CHAR, new char GENEND
|
||||
|
||||
|
||||
case 'i': INTGENSTART 0 GENMID TDF_INT INTGENEND
|
||||
|
||||
|
||||
case 'h':INTGENSTART 16 GENMID TDF_HEX INTGENEND
|
||||
|
||||
|
||||
case 'b':INTGENSTART 2 GENMID TDF_BINARY INTGENEND
|
||||
|
||||
|
||||
case 'B': GENSTART if (LAST + 1 >= trimmed.size()) goto FAILTOPARSE; char c=trimmed.at(LAST + 1);
|
||||
bool VALUE = c=='T'; if (LAST + 2 < trimmed.size()) goto FAILTOPARSE; TDF_DATA DAT={TDF_BOOL,new bool GENEND
|
||||
|
||||
|
||||
case 'f':GENSTART std::string sub = trimmed.substr(LAST + 1);size_t idx;float VALUE; try{VALUE=stof(sub, &idx);
|
||||
if (idx != sub.size()) goto FAILTOPARSE;}catch(std::invalid_argument&){goto FAILTOPARSE;}TDF_DATA DAT={TDF_FLOAT,new float GENEND
|
||||
|
||||
|
||||
case '@':GENSTART
|
||||
std::string VALUE=trimmed.substr(LAST + 1);
|
||||
std::vector<std::string>*ptr=new std::vector<std::string>();
|
||||
size_t pos=0;
|
||||
std::string token;
|
||||
while((pos=VALUE.find('.'))!=std::string::npos){
|
||||
token=VALUE.substr(0,pos);
|
||||
ptr->push_back(token);
|
||||
VALUE.erase(0,pos+1);
|
||||
}
|
||||
ptr->push_back(VALUE);
|
||||
TDF_DATA DAT={TDF_POINTER,ptr};
|
||||
todelete.push_back(DAT.datapointer);
|
||||
(*current)[KEY]=DAT;
|
||||
break;}
|
||||
|
||||
|
||||
case '{':{
|
||||
int LAST = trimmed.find(' ', 3);
|
||||
std::string KEY;
|
||||
if (LAST != std::string::npos){
|
||||
KEY = trimmed.substr(2, LAST - 2);
|
||||
}else{
|
||||
KEY = trimmed.substr(2);
|
||||
}
|
||||
boost::unordered_map<std::string,TDF_DATA>*newmap=new boost::unordered_map<std::string,TDF_DATA>();
|
||||
TDF_DATA DAT={TDF_CLASS,newmap};
|
||||
todelete.push_back(DAT.datapointer);
|
||||
(*current)[KEY]=DAT;
|
||||
std::vector<std::string> *defines=new std::vector<std::string>();
|
||||
TDF_DATA defdat={TDF_DEFINES,defines};
|
||||
(*newmap)[TINYDEFINEHEADER]=defdat;
|
||||
stack.push_back(current);
|
||||
pathvec.push_back(KEY);
|
||||
current=newmap;
|
||||
break;}
|
||||
|
||||
|
||||
default:{
|
||||
try {
|
||||
int PATH=FUNCS.funcs.at(trimmed[0]);
|
||||
int LAST = trimmed.find(' ', 3);
|
||||
if (LAST == std::string::npos)goto FAILTOPARSE;
|
||||
std::string KEY = trimmed.substr(2, LAST - 2);
|
||||
(*current)[KEY]=FUNCS.FUNCS[PATH](trimmed);
|
||||
todelete.push_back((*current)[KEY].datapointer);
|
||||
if ((*current)[KEY].datapointer==nullptr) goto FAILTOPARSE;
|
||||
}catch(const std::out_of_range&){
|
||||
break;
|
||||
}
|
||||
break;}
|
||||
}
|
||||
}else if(trimmed == "}"){
|
||||
if(stack.empty())goto FAILTOPARSE;
|
||||
current=stack.back();
|
||||
stack.pop_back();
|
||||
if(!pathvec.empty())pathvec.pop_back();
|
||||
}else{
|
||||
auto it = current->find(TINYDEFINEHEADER);
|
||||
if (it == current->end() || it->second.type != TDF_DEFINES) goto FAILTOPARSE;
|
||||
std::vector<std::string>* defines = static_cast<std::vector<std::string>*>(it->second.datapointer);
|
||||
defines->push_back(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}else{
|
||||
throw TDF_ERR(FILE_NOT_FOUND,filepath,{});
|
||||
}
|
||||
NULLPOINTER:
|
||||
throw TDF_ERR(NULL_POINTER,filepath,{std::string(1,CCHAR),std::to_string(INDEX)});
|
||||
FAILTOPARSE:
|
||||
throw TDF_ERR(FAILED_TO_PARSE,filepath,{std::to_string(INDEX)});
|
||||
delete data;
|
||||
data=nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
//get
|
||||
|
||||
#define ITSNOT it->second.type!=
|
||||
float getfloat GETSTART ITSNOT TDF_FLOAT GETMID float GETEND DEFAULTGET(getfloat, float)
|
||||
|
||||
bool getbool GETSTART ITSNOT TDF_BOOL GETMID bool GETEND DEFAULTGET(getbool, bool)
|
||||
|
||||
int getint GETSTART (ITSNOT TDF_INT)&&(ITSNOT TDF_HEX)&&(ITSNOT TDF_BINARY) GETMID int GETEND DEFAULTGET(getint, int)
|
||||
|
||||
std::string getstring GETSTART (ITSNOT TDF_STR)&&(ITSNOT TDF_BLOCK) GETMID std::string GETEND DEFAULTGET(getstring, std::string)
|
||||
|
||||
std::vector<std::string> getpointer GETSTART ITSNOT TDF_POINTER GETMID std::vector<std::string> GETEND DEFAULTGET(getpointer, std::vector<std::string>)
|
||||
|
||||
char getchar GETSTART ITSNOT TDF_CHAR GETMID char GETEND DEFAULTGET(getchar, char)
|
||||
|
||||
bool defined(std::vector<std::string>path){
|
||||
boost::unordered_map<std::string,TDF_DATA>*current=data;
|
||||
for(size_t i=0;i<path.size();i++){auto it=current->find(path[i]);
|
||||
if(it==current->end())return false;
|
||||
if(i==path.size()-1)return true;
|
||||
if(it->second.type!=TDF_CLASS)return false;
|
||||
current=(boost::unordered_map<std::string,TDF_DATA>*)it->second.datapointer;}
|
||||
return false;}
|
||||
DEFAULTGET(defined, bool)
|
||||
|
||||
boost::unordered_map<std::string,TDF_DATA>* getclass(std::vector<std::string>path){
|
||||
boost::unordered_map<std::string,TDF_DATA>*current=data;
|
||||
for(size_t i=0;i<path.size();i++){
|
||||
auto it=current->find(path[i]);
|
||||
if(it==current->end())throw TDF_ERR(PATH_NOT_FOUND,filepath,path);
|
||||
if(i==path.size()-1){
|
||||
if(ITSNOT TDF_CLASS)throw TDF_ERR(GET_MISMATCH,filepath,path);
|
||||
return (boost::unordered_map<std::string,TDF_DATA>*)(it->second.datapointer);
|
||||
}
|
||||
if(ITSNOT TDF_CLASS)throw TDF_ERR(GET_MISMATCH,filepath,path);
|
||||
current=(boost::unordered_map<std::string,TDF_DATA>*)(it->second.datapointer);
|
||||
}
|
||||
throw TDF_ERR(PATH_NOT_FOUND,filepath,path);
|
||||
}
|
||||
boost::unordered_map<std::string,TDF_DATA>* getclass(std::vector<std::string>path,boost::unordered_map<std::string,TDF_DATA>* defaultval){
|
||||
try {
|
||||
return getclass(path);}
|
||||
catch(TDF_ERR e) {
|
||||
warning((char*)e.what());
|
||||
return defaultval;
|
||||
}
|
||||
}
|
||||
//set
|
||||
|
||||
void setbool(std::vector<std::string>path, bool SETSTART TDF_BOOL, new bool SETMID TDF_BOOL) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<bool SETEND
|
||||
|
||||
void setint(std::vector<std::string>path, int SETSTART TDF_INT, new int SETMID TDF_INT) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<int SETEND
|
||||
|
||||
void setstring(std::vector<std::string>path, std::string SETSTART TDF_STR, new std::string SETMID TDF_STR) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<std::string SETEND
|
||||
|
||||
void setblock(std::vector<std::string>path, std::string SETSTART TDF_BLOCK, new std::string SETMID TDF_BLOCK) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<std::string SETEND
|
||||
|
||||
void setfloat(std::vector<std::string>path, float SETSTART TDF_FLOAT, new float SETMID TDF_FLOAT) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<float SETEND
|
||||
|
||||
void setchar(std::vector<std::string>path, char SETSTART TDF_CHAR, new char SETMID TDF_CHAR) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<char SETEND
|
||||
|
||||
void setpointer(std::vector<std::string>path, std::vector<std::string> SETSTART TDF_POINTER, new std::vector<std::string> SETMID TDF_POINTER) throw TDF_ERR(SET_MISMATCH, filepath, path); *static_cast<std::vector<std::string> SETEND
|
||||
|
||||
void define(std::vector<std::string>defines,char* name){
|
||||
auto it = data->find(TINYDEFINEHEADER);
|
||||
if (it == data->end() || it->second.type != TDF_DEFINES) {
|
||||
std::vector<std::string>* newdefines = new std::vector<std::string>();
|
||||
TDF_DATA defdat = { TDF_DEFINES, newdefines };
|
||||
(*data)[TINYDEFINEHEADER] = defdat;
|
||||
todelete.push_back(defdat.datapointer);
|
||||
it = data->find(TINYDEFINEHEADER);
|
||||
}
|
||||
std::vector<std::string>* currentdefines = static_cast<std::vector<std::string>*>(it->second.datapointer);
|
||||
for (size_t i = 0; i < defines.size(); i++) {
|
||||
currentdefines->push_back(defines[i]);
|
||||
}
|
||||
currentdefines->push_back(std::string("#define ") + name);
|
||||
}
|
||||
|
||||
void save(){
|
||||
std::ofstream file(filepath, std::ios::out | std::ios::trunc);
|
||||
std::string DATA="";
|
||||
crawl(data,&DATA,"");
|
||||
file<<DATA;
|
||||
file.close();
|
||||
}
|
||||
private:
|
||||
void crawl(boost::unordered_map<std::string,TDF_DATA>*map,std::string*STR,std::string indent){
|
||||
auto it = map->find(TINYDEFINEHEADER);
|
||||
if (it != map->end() && it->second.type == TDF_DEFINES) {
|
||||
std::vector<std::string>* defines = static_cast<std::vector<std::string>*>(it->second.datapointer);
|
||||
for (auto& def : *defines) {
|
||||
*STR += def + "\n";
|
||||
}
|
||||
}
|
||||
for(auto&[key,val]:*map){
|
||||
if(key==TINYDEFINEHEADER)continue;
|
||||
switch(val.type){
|
||||
case TDF_STR:*STR+="\" "+key+" "+*static_cast<std::string*>(val.datapointer)+"\n";break;
|
||||
case TDF_CHAR:*STR+="' "+key+" "+*static_cast<char*>(val.datapointer)+"\n";break;
|
||||
case TDF_BLOCK:*STR+="S "+key+"\n"+*static_cast<std::string*>(val.datapointer)+"\n\\\n";break;
|
||||
case TDF_BOOL:*STR+="B "+key+" "+(*static_cast<bool*>(val.datapointer)?"T":"F")+"\n";break;
|
||||
case TDF_BINARY:*STR+="b "+key+" "+std::to_string(*static_cast<int*>(val.datapointer))+"\n";break;
|
||||
case TDF_INT:*STR+="i "+key+" "+std::to_string(*static_cast<int*>(val.datapointer))+"\n";break;
|
||||
case TDF_FLOAT:*STR+="f "+key+" "+std::to_string(*static_cast<float*>(val.datapointer))+"\n";break;
|
||||
case TDF_HEX:*STR+="h "+key+" "+std::to_string(*static_cast<int*>(val.datapointer))+"\n";break;
|
||||
|
||||
case TDF_POINTER:{std::vector<std::string>*ptr=static_cast<std::vector<std::string>*>(val.datapointer);
|
||||
*STR+="@ "+key+" ";for(size_t i=0;i<ptr->size();i++){*STR+=(*ptr)[i];if(i<ptr->size()-1)*STR+=".";}*STR+="\n";break;}
|
||||
|
||||
case TDF_CLASS:*STR+="{ "+key+"\n";crawl((boost::unordered_map<std::string,TDF_DATA>*)(val.datapointer),STR,"");*STR+="}\n";break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
108
inc/term.h
Normal file
108
inc/term.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#pragma once
|
||||
#ifndef TINYTERM_H
|
||||
#define TINYTERM_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
namespace tiny {
|
||||
|
||||
struct ErrorLevel {
|
||||
int value;
|
||||
ErrorLevel(int var){
|
||||
this->value=var;
|
||||
}
|
||||
void setvalue(int var){
|
||||
this->value=var;
|
||||
}
|
||||
};
|
||||
|
||||
extern tiny::ErrorLevel level;
|
||||
|
||||
inline const char* WHITE = "\033[0m";
|
||||
inline const char* BLACK = "\033[30m";
|
||||
inline const char* RED = "\033[31m";
|
||||
inline const char* GREEN = "\033[32m";
|
||||
inline const char* YELLOW = "\033[33m";
|
||||
inline const char* BLUE = "\033[34m";
|
||||
inline const char* MAGENTA = "\033[35m";
|
||||
inline const char* CYAN = "\033[36m";
|
||||
inline const char* BGRED = "\033[41m";
|
||||
inline const char* BGBLACK = "\033[40m";
|
||||
inline const char* BGGREEN = "\033[42m";
|
||||
inline const char* BGYELLOW = "\033[43m";
|
||||
inline const char* BGBLUE = "\033[44m";
|
||||
inline const char* BGMAGENTA ="\033[45m";
|
||||
inline const char* BGCYAN = "\033[46m";
|
||||
inline const char* BGWHITE = "\033[47m";
|
||||
inline const char* BOLDBLACK = "\033[1m\033[30m";
|
||||
inline const char* BOLDRED = "\033[1m\033[31m";
|
||||
inline const char* BOLDGREEN = "\033[1m\033[32m";
|
||||
inline const char* BOLDYELLOW = "\033[1m\033[33m";
|
||||
inline const char* BOLDBLUE = "\033[1m\033[34m";
|
||||
inline const char* BOLDMAGENTA = "\033[1m\033[35m";
|
||||
inline const char* BOLDCYAN = "\033[1m\033[36m";
|
||||
inline const char* BOLDWHITE = "\033[1m\033[37m";
|
||||
|
||||
#define ending \
|
||||
mixer.append(info); mixer.append("\033[0m\n");\
|
||||
const char * finalinfo=mixer.c_str();\
|
||||
va_start (arg, finalinfo);\
|
||||
vfprintf (stdout, finalinfo, arg);\
|
||||
va_end (arg);
|
||||
|
||||
inline void echo(char * info,...){
|
||||
if (level.value==4)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=info;
|
||||
mixer.append("\n");
|
||||
const char * finalinfo=mixer.c_str();
|
||||
va_start (arg, finalinfo);
|
||||
vfprintf (stdout, finalinfo, arg);
|
||||
va_end (arg);}
|
||||
}
|
||||
inline void warning( char * info,...){
|
||||
if (level.value>=1)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=YELLOW;ending
|
||||
}
|
||||
}
|
||||
inline void fatal( char * info,...){
|
||||
va_list arg;
|
||||
std::string mixer=BOLDWHITE+std::string(BGRED);ending
|
||||
}
|
||||
inline void error( char * info,...){
|
||||
if (level.value>=0)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=BOLDRED;ending
|
||||
}}
|
||||
inline void success(char * info , ...){
|
||||
if (level.value>=2)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=GREEN;ending}
|
||||
}
|
||||
inline void message(char * info , ...){
|
||||
if (level.value>=3)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=BOLDWHITE;ending}
|
||||
}
|
||||
inline void startup(char* game,char*version){
|
||||
int lv=level.value;level.value=6;
|
||||
echo("%s %s",game,version);
|
||||
warning("be warned that");
|
||||
error("ERRORS MIGHT OCCUR!!!");
|
||||
success("but dont worry");
|
||||
message("this is not an error");
|
||||
fatal("I SWEAR");
|
||||
level.value=lv;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
0
inc/tiny.h
Normal file
0
inc/tiny.h
Normal file
132
main.cpp
132
main.cpp
|
|
@ -1,132 +0,0 @@
|
|||
#include <sstream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
std::string get(std::string);
|
||||
std::map<std::string,std::string> variables;
|
||||
std::map<std::string,int> functions;
|
||||
|
||||
#define CALL ""
|
||||
#ifdef _WIN32
|
||||
#undef CALL
|
||||
#define CALL "call"
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
#undef CALL
|
||||
#define CALL "exec"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#undef CALL
|
||||
#define CALL "exec"
|
||||
#endif
|
||||
#include "term.h"
|
||||
int call(
|
||||
std::string lines){
|
||||
std::string com;
|
||||
com.append(CALL);
|
||||
|
||||
success("command:%s\nexecuting\n\n",lines.c_str());
|
||||
com.append(lines.c_str());
|
||||
|
||||
system(com.c_str());
|
||||
success("\n\n");
|
||||
return 0;
|
||||
}
|
||||
ErrorLevel level(1);
|
||||
int set(std::string setter){
|
||||
std::string name=setter.substr(setter.find_first_of(" ")+1,setter.find("=")-4);
|
||||
std::string value=setter.substr(setter.find("=")+1);
|
||||
variables[name]=value;
|
||||
warning("key %s set as value %s\n\n",name.c_str(),value.c_str());
|
||||
//success("\nvar: %s\n",variables[name].c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fn(std::string setter,int pos){
|
||||
std::string name=setter.substr(setter.find_first_of(":")+1);
|
||||
functions[name]=pos;
|
||||
warning("function %s set in position %i\n\n",name.c_str(),pos);
|
||||
//success("\nvar: %s\n",variables[name].c_str());
|
||||
return 0;
|
||||
}
|
||||
std::string get(std::string key){
|
||||
std::string k=key.substr(key.find_first_of('%')+1,key.find_last_of('%')-1);
|
||||
std::string var=variables[k];
|
||||
if (var==""){
|
||||
error("\ncould not get variable with key \"%s\"\n",k.c_str());
|
||||
exit(1);
|
||||
}
|
||||
//success("\ngetting variable \"%s\" with key \"%s\"\n",var.c_str(),k.c_str());
|
||||
return var;
|
||||
}
|
||||
|
||||
#define A lines.append
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
for (int i=2;i<argc;i++){
|
||||
if (argv[i][0]=='-'&&argv[i][1]=='w'){i++;
|
||||
level= std::stoi(argv[i]);
|
||||
}else{
|
||||
std::string key="set ";
|
||||
key.append(std::to_string(i-2)).append("=").append(argv[i]);
|
||||
set(key);
|
||||
}}
|
||||
warning("tiny runner v0.8\n\n\n");
|
||||
std::fstream fileStream;
|
||||
fileStream.open(argv[1]);
|
||||
if (!fileStream.fail()){
|
||||
std::ifstream infile(argv[1]);
|
||||
std::string line;
|
||||
std::string lines;
|
||||
int mode=-1;
|
||||
bool infunc=false;
|
||||
while (std::getline(infile, line))
|
||||
{
|
||||
const char * l=line.c_str();
|
||||
error((char *)l);
|
||||
if (line.length()!=0){
|
||||
switch (l[0])
|
||||
{
|
||||
case '\\':
|
||||
if (l[1]=='n'){
|
||||
call(lines);
|
||||
lines.clear();}
|
||||
else{
|
||||
A(++l);
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
lines.append(get(line));
|
||||
break;
|
||||
|
||||
case ';':
|
||||
break;
|
||||
case 's':
|
||||
if (l[1]=='e'&&l[2]=='t'){
|
||||
call(lines);
|
||||
lines.clear();
|
||||
set(line);}
|
||||
else{
|
||||
A(" "+line);
|
||||
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
fn(line, infile.cur);
|
||||
/* code */
|
||||
|
||||
default:
|
||||
A(" "+line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
call(lines);
|
||||
return 0;
|
||||
}
|
||||
error("could not locate file %s",argv[1]);
|
||||
return 1;
|
||||
}
|
||||
57
term.cpp
57
term.cpp
|
|
@ -1,57 +0,0 @@
|
|||
#include "term.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#define ending \
|
||||
mixer.append(info); mixer.append("\033[0m\n");\
|
||||
const char * finalinfo=mixer.c_str();\
|
||||
va_start (arg, finalinfo);\
|
||||
vfprintf (stdout, finalinfo, arg);\
|
||||
va_end (arg);
|
||||
|
||||
void echo(char * info,...){
|
||||
if (level.value==4)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=info;
|
||||
mixer.append("\n");
|
||||
const char * finalinfo=mixer.c_str();
|
||||
va_start (arg, finalinfo);
|
||||
vfprintf (stdout, finalinfo, arg);
|
||||
va_end (arg);}
|
||||
}
|
||||
void warning( char * info,...){
|
||||
if (level.value>=1)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=YELLOW;ending
|
||||
}
|
||||
}
|
||||
void error( char * info,...){
|
||||
if (level.value>=0)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=BOLDRED;ending
|
||||
}}
|
||||
void success(char * info , ...){
|
||||
if (level.value>=2)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=GREEN;ending}
|
||||
}
|
||||
void message(char * info , ...){
|
||||
if (level.value>=3)
|
||||
{
|
||||
va_list arg;
|
||||
std::string mixer=BOLDWHITE;ending}
|
||||
}
|
||||
void startup(char* game,char*version){
|
||||
|
||||
echo("%s %s",game,version);
|
||||
warning("be warned that");
|
||||
error("ERRORS MIGHT OCCUR!!!");
|
||||
success("but dont worry");
|
||||
message("this is not an error");
|
||||
}
|
||||
52
term.h
52
term.h
|
|
@ -1,52 +0,0 @@
|
|||
#pragma once
|
||||
void echo(char* info,...);
|
||||
void warning( char * info,...);
|
||||
void error( char * info,...);
|
||||
void success(char * info , ...);
|
||||
void message(char * info , ...);
|
||||
void startup(char* game,char*version);
|
||||
struct ErrorLevel {
|
||||
int value;
|
||||
ErrorLevel(int var){
|
||||
|
||||
this->value=var;
|
||||
}
|
||||
void setvalue(int var){
|
||||
this->value=var;
|
||||
}
|
||||
};
|
||||
extern ErrorLevel level;
|
||||
/*
|
||||
-1: none
|
||||
0: error
|
||||
1: success
|
||||
2: warning
|
||||
3: message
|
||||
4: echo
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define WHITE "\033[0m" /* White */
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
#define BLUE "\033[34m" /* Blue */
|
||||
#define MAGENTA "\033[35m" /* Magenta */
|
||||
#define CYAN "\033[36m" /* Cyan */
|
||||
#define WHITE "\033[37m" /* White */
|
||||
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
|
||||
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
|
||||
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
|
||||
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
|
||||
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
|
||||
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
|
||||
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
|
||||
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
|
||||
Loading…
Add table
Add a link
Reference in a new issue