diff --git a/Makefile b/Makefile
index fd841f7..462a9eb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
+ifndef CC
+CC = gcc
+endif
+
BASE_CFLAGS = --std=c99 -Wall -Wextra -Ofast -lm -lreadline -funsigned-char
ifndef OS
-C = gcc
CFLAGS = $(BASE_CFLAGS) -ldl
ifeq ($(shell uname -s), Darwin)
ifeq ($(shell [ -d ~/.brew/opt/readline/include ] && echo true), true)
@@ -27,18 +30,18 @@ else
ifeq ($(shell uname -o), Android)
CFLAGS += -s
else
-CFLAGS += -s -no-pie
+CFLAGS += -g -no-pie
endif
endif
CBITS = $(shell getconf LONG_BIT)
BUILD_TO = clibasic
-BUILD32 = $(C) clibasic.c -m32 $(CFLAGS) -DB32 -o $(BUILD_TO) && chmod +x $(BUILD_TO)
+BUILD32 = $(CC) clibasic.c -m32 $(CFLAGS) -DB32 -o $(BUILD_TO) && chmod +x $(BUILD_TO)
ifeq (,$(CBITS))
BUILD__ = $(BUILD32)
else
-BUILD__ = $(C) clibasic.c $(CFLAGS) -DB$(CBITS) -o $(BUILD_TO) && chmod +x $(BUILD_TO)
+BUILD__ = $(CC) clibasic.c $(CFLAGS) -DB$(CBITS) -o $(BUILD_TO) && chmod +x $(BUILD_TO)
endif
MAN_PATH = docs/clibasic.man
@@ -103,7 +106,7 @@ cross:
ifeq ($(MAKECMDGOALS), cross)
@$(MAKE) cross all
else
- @$(eval C = x86_64-w64-mingw32-gcc)
+ @$(eval CC = x86_64-w64-mingw32-gcc)
@$(eval C32 = i686-w64-mingw32-gcc)
@$(eval CFLAGS = $(BASE_CFLAGS) -s -Ilib)
@$(eval BUILD_TO = clibasic.exe)
@@ -113,7 +116,7 @@ else
ifeq (,$(CBITS))
@$(eval BUILD__ = $(BUILD32))
else
- @$(eval BUILD__ = cp -f lib/win64/*.dll . && $(C) clibasic.c $(CFLAGS) -Llib/win64 -DB$(CBITS) -o $(BUILD_TO) && chmod -x $(BUILD_TO))
+ @$(eval BUILD__ = cp -f lib/win64/*.dll . && $(CC) clibasic.c $(CFLAGS) -Llib/win64 -DB$(CBITS) -o $(BUILD_TO) && chmod -x $(BUILD_TO))
endif
@$(eval RUN = wineconsole .\\$(BUILD_TO))
@$(eval CLEAN = rm -f clibasic.exe *.dll)
@@ -126,19 +129,17 @@ vt:
ifeq (,$(CBITS))
@$(eval BUILD__ = $(BUILD32))
else
- @$(eval BUILD__ = cp -f lib/win64/*.dll . && $(C) clibasic.c $(CFLAGS) -Llib/win64 -DB$(CBITS) -o $(BUILD_TO) && chmod -x $(BUILD_TO))
+ @$(eval BUILD__ = cp -f lib/win64/*.dll . && $(CC) clibasic.c $(CFLAGS) -Llib/win64 -DB$(CBITS) -o $(BUILD_TO) && chmod -x $(BUILD_TO))
endif
@true
else
-C = gcc
-
-CFLAGS = $(BASE_CFLAGS) -Ilib -s -D_CRT_NONSTDC_NO_WARNINGS
+CFLAGS = $(BASE_CFLAGS) -lpthread -Ilib -s -D_CRT_NONSTDC_NO_WARNINGS
BUILD_TO = clibasic.exe
-BUILD64 = xcopy lib\win64\*.dll . /Y && $(C) clibasic.c -m64 $(CFLAGS) -Llib\win64 -DB64 -o $(BUILD_TO)
-BUILD32 = xcopy lib\win32\*.dll . /Y && $(C) clibasic.c -m32 $(CFLAGS) -Llib\win32 -DB32 -o $(BUILD_TO)
+BUILD64 = xcopy lib\win64\*.dll . /Y && $(CC) clibasic.c -m64 $(CFLAGS) -Llib\win64 -DB64 -o $(BUILD_TO)
+BUILD32 = xcopy lib\win32\*.dll . /Y && $(CC) clibasic.c -m32 $(CFLAGS) -Llib\win32 -DB32 -o $(BUILD_TO)
INSTALL_TO = C:\windows\system32
INSTALL = xcopy *.dll $(INSTALL_TO) /Y && xcopy $(BUILD_TO) $(INSTALL_TO) /Y
diff --git a/README.md b/README.md
index 1d3464a..8d33848 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,10 @@ To run, use `make run` or `./clibasic`.
To build then run, use `make` (same as `make all`).
To build CLIBASIC with support for VT escape codes, add `vt` before the rest of the rules.
+---
+### Demo
+[](https://asciinema.org/a/447773)
+
---
### Notes
- On Arch Linux, you can install CLIBASIC by installing either the [`clibasic`](https://aur.archlinux.org/packages/clibasic/) or [`clibasic-bin`](https://aur.archlinux.org/packages/clibasic-bin/) AUR package.
@@ -87,4 +91,3 @@ To build CLIBASIC with support for VT escape codes, add `vt` before the rest of
- CLIBASIC will look for `~/.clibasicrc`, `~/autorun.bas`, then `~/.autorun.bas` in this order in the user's home directory and run the first file found.
- The development scripts are `build.sh` which is for testing if CLIBASIC compiles correctly for Linux and Windows, `package.sh` which creates the zip files for making a CLIBASIC release, `commit.sh` which automates the build and push process, and `release-text.sh` which generates the text for making a CLIBASIC release.
- Include the `clibasic.h` file when making a clibasic extension.
-
diff --git a/clibasic.c b/clibasic.c
index 7784d1b..982a217 100644
--- a/clibasic.c
+++ b/clibasic.c
@@ -39,6 +39,8 @@
/* Fix implicit declaration issues */
#define _POSIX_C_SOURCE 999999L
#define _XOPEN_SOURCE 999999L
+#define _DEFAULT_SOURCE
+#define _GNU_SOURCE
/* Check if the buffer size is usable */
#if (CB_BUF_SIZE < 0)
@@ -94,14 +96,16 @@
// OS-specific includes and definitions
#ifndef _WIN32
+ #include
#include
- #include
#include
- #include
+ #include
+ #include
#else
#include
#include
#include
+ #include
#endif
#ifdef __APPLE__
@@ -118,7 +122,7 @@
// Base defines
-char VER[] = "0.28.1.4";
+char VER[] = "1.0";
#if defined(__linux__)
char OSVER[] = "Linux";
@@ -154,6 +158,9 @@ char VER[] = "0.28.1.4";
#include "clibasic.h"
+char* defaultstr = "";
+char* defaultnum = "0";
+
int progindex = -1;
char** progbuf = NULL;
char** progfn = NULL;
@@ -177,11 +184,6 @@ char gpbuf[CB_BUF_SIZE];
char* cmd = NULL;
int cmdl = 0;
-//char** tmpargs = NULL;
-char** arg = NULL;
-uint8_t* argt = NULL;
-int32_t* argl = NULL;
-int argct = -1;
int cmdpos = 0;
@@ -191,7 +193,7 @@ bool lockpl = false;
typedef struct {
uint8_t type;
uint8_t block;
-} cb_brkinfo;
+} __attribute__((aligned(sizeof(void*)))) cb_brkinfo;
cb_brkinfo brkinfo;
cb_brkinfo* oldbrkinfo = NULL;
@@ -200,7 +202,7 @@ typedef struct {
int pl;
int32_t cp;
cb_brkinfo brkinfo;
-} cb_jump;
+} __attribute__((aligned(sizeof(void*)))) cb_jump;
cb_jump dlstack[CB_PROG_LOGIC_MAX];
bool dldcmd[CB_PROG_LOGIC_MAX];
@@ -228,7 +230,7 @@ typedef struct {
int fnsp;
int itsp;
cb_brkinfo brkinfo;
-} cb_gosub;
+} __attribute__((aligned(sizeof(void*)))) cb_gosub;
cb_gosub gsstack[CB_PROG_LOGIC_MAX];
int gsstackp = -1;
@@ -246,12 +248,14 @@ int cury = 0;
int concp = 0;
int32_t cp = 0;
-bool cmdint = false;
-bool inprompt = false;
+sig_atomic_t cmdint = false;
+sig_atomic_t inprompt = false;
+bool dprompt = false;
bool runfile = false;
bool runc = false;
bool autorun = false;
+bool* autorunstack = NULL;
bool redirection = false;
bool checknl = false;
@@ -265,10 +269,16 @@ bool sh_restoreAttrib = true;
cb_txt txtattrib;
+#ifdef _WIN32
+static __volatile__ bool textlock = false;
+#else
bool textlock = false;
+#endif
bool sneaktextlock = false;
+bool hidecursor = false;
bool keep = false;
+bool keepall = false;
char* homepath = NULL;
char* cwd = NULL;
@@ -291,16 +301,18 @@ bool changedtitlecmd = false;
int retval = 0;
+bool hideerror = false;
+
typedef struct {
+ bool inuse;
int pl;
int32_t cp;
- bool used;
char* name;
int dlsp;
int fnsp;
int itsp;
cb_brkinfo brkinfo;
-} cb_goto;
+} __attribute__((aligned(sizeof(void*)))) cb_goto;
cb_goto* gotodata = NULL;
cb_goto** proggotodata = NULL;
@@ -312,14 +324,23 @@ int filemaxct = 0;
int fileerror = 0;
typedef struct {
+ bool inuse;
char* name;
char* data;
-} cb_sub;
+ uint8_t type;
+} __attribute__((aligned(sizeof(void*)))) cb_sub;
+
+typedef struct {
+ bool insub;
+ uint8_t type;
+} __attribute__((aligned(sizeof(void*)))) cb_subinfo;
cb_sub* subdata = NULL;
int submaxct = 0;
-bool addsub = false;
-int subindex = -1;
+int addsub = -1;
+cb_subinfo subinfo;
+cb_subinfo* oldsubinfo = NULL;
+char* funcret = NULL;
char* rl_tmpptr = NULL;
@@ -334,7 +355,7 @@ typedef struct {
void (*clearGlobals)(void);
void (*promptReady)(void);
bool (*deinit)(void);
-} cb_ext;
+} __attribute__((aligned(sizeof(void*)))) cb_ext;
int extmaxct = 0;
cb_ext* extdata = NULL;
@@ -344,9 +365,9 @@ struct termios term, restore;
struct termios kbhterm, kbhterm2;
struct termios initterm;
-void txtqunlock() {if (textlock || sneaktextlock) {tcsetattr(0, TCSANOW, &restore); textlock = false;}}
+static inline void txtqunlock() {if (textlock || sneaktextlock) {tcsetattr(0, TCSANOW, &restore); textlock = false;}}
-int kbhit() {
+static inline int kbhit() {
int inchar;
ioctl(0, FIONREAD, &inchar);
return inchar;
@@ -416,7 +437,7 @@ static inline void clearGlobals() {
memset(&gsstack[i], 0, sizeof(cb_jump));
}
for (int i = 0; i < gotomaxct; ++i) {
- if (gotodata[i].used) nfree(gotodata[i].name);
+ if (gotodata[i].inuse) nfree(gotodata[i].name);
}
nfree(gotodata);
gotomaxct = 0;
@@ -425,6 +446,8 @@ static inline void clearGlobals() {
extdata[i].clearGlobals();
}
}
+ subinfo.insub = false;
+ subinfo.type = false;
}
static inline void promptReady() {
@@ -552,7 +575,7 @@ static inline void getCurPos();
static inline char* gethome();
static inline void initBaseMem();
static inline void freeBaseMem();
-static inline void printError(int);
+static inline void printError(int, char*, char*);
static inline void seterrstr(char*);
void unloadAllProg();
static inline char* basefilename(char*);
@@ -566,26 +589,12 @@ bool unloadExt(int);
void cleanExit() {
txtqunlock();
- int ret;
- if (inprompt) {
- int i = kbhit();
- if (i) {ret = read(0, &gpbuf, i);}
- getCurPos();
- unloadAllProg();
- cmdint = true;
- putchar('\n');
- history_set_pos(history_length);
- rl_on_new_line();
- rl_replace_line("", 0);
- rl_pending_input = false;
- rl_redisplay();
- return;
- }
setsig(SIGINT, forceExit);
setsig(SIGTERM, forceExit);
fflush(stdout);
unloadAllProg();
closeFile(-1);
+ int ret;
ret = chdir(gethome());
(void)ret;
if (autohist && !runfile) {
@@ -599,11 +608,27 @@ void cleanExit() {
#if defined(CHANGE_TITLE) && !defined(_WIN_NO_VT)
if (esc && changedtitle) fputs("\e[23;0t", stdout);
#endif
- #ifndef _WIN_NO_VT
- if (esc && !keep) fputs("\e[0m", stdout);
- #else
- if (!keep) SetConsoleTextAttribute(hConsole, ocAttrib);
- #endif
+ if (!keep) {
+ #ifndef _WIN_NO_VT
+ if (esc) fputs("\e[0m", stdout);
+ #else
+ SetConsoleTextAttribute(hConsole, ocAttrib);
+ #endif
+ }
+ if (!keepall && hidecursor) {
+ #ifndef _WIN_NO_VT
+ if (esc) {
+ fputs("\e[?25h", stdout);
+ fflush(stdout);
+ }
+ #else
+ CONSOLE_CURSOR_INFO curinfo;
+ GetConsoleCursorInfo(hConsole, &curinfo);
+ curinfo.bVisible = true;
+ SetConsoleCursorInfo(hConsole, &curinfo);
+ #endif
+ hidecursor = false;
+ }
#ifndef _WIN32
int i = kbhit();
while (i > 0) {getchar(); i--;}
@@ -624,22 +649,31 @@ void cleanExit() {
nfree(vardata[i].name);
}
}
+ for (int i = 0; i < submaxct; ++i) {
+ if (subdata[i].inuse) {
+ nfree(subdata[i].data);
+ nfree(subdata[i].name);
+ }
+ }
for (int i = 0; i < gotomaxct; ++i) {
- if (gotodata[i].used) {
+ if (gotodata[i].inuse) {
nfree(gotodata[i].name);
}
}
- for (int i = 0; i < argct; ++i) {
- nfree(arg[i]);
+ for (int i = 1; i < progargc; ++i) {
+ nfree(progargs[i]);
}
+ free(progargs);
+ for (int i = 1; i < newprogargc; ++i) {
+ nfree(newprogargs[i]);
+ }
+ free(newprogargs);
nfree(startcmd);
nfree(rl_tmpptr);
nfree(cmd);
- nfree(arg);
- nfree(argt);
- nfree(argl);
nfree(errstr);
nfree(vardata);
+ nfree(subdata);
if (progindex > -1) {
nfree(progbuf[0]);
nfree(progfn[0]);
@@ -659,17 +693,32 @@ void cleanExit() {
clearGlobals();
unloadExt(-1);
#ifndef _WIN32
- tcsetattr(0, TCSANOW, &initterm);
+ if (!keepall) tcsetattr(0, TCSANOW, &initterm);
#endif
exit(err);
}
void cmdIntHndl() {
- if (cmdint) setsig(SIGINT, cleanExit);
+ if (inprompt) {
+ int i = kbhit();
+ int ret;
+ if (i) {ret = read(0, &gpbuf, i);}
+ (void)ret;
+ getCurPos();
+ unloadAllProg();
+ putchar('\n');
+ history_set_pos(history_length);
+ rl_on_new_line();
+ rl_replace_line("", 0);
+ rl_pending_input = false;
+ rl_redisplay();
+ return;
+ }
+ if (cmdint) {setsig(SIGINT, cleanExit);}
cmdint = true;
}
-void runcmd();
+int runcmd();
#ifdef BUILT_IN_STRING_FUNCS
#define copyStr(b, a) strcpy(a, b)
#define copyStrApnd(b, a) strcat(a, b)
@@ -677,9 +726,9 @@ void runcmd();
static inline void copyStr(char*, char*);
static inline void copyStrApnd(char*, char*);
#endif
-static inline void copyStrApndNoEsc(char*, char*);
static inline void copyStrTo(char*, int32_t, char*);
static inline void copyStrSnip(char*, int32_t, int32_t, char*);
+static inline char* copyStrApndO(char* str1, char* str2);
uint8_t getVal(char*, char*);
static inline void resetTimer();
bool loadProg(char*);
@@ -687,6 +736,7 @@ void unloadProg();
static inline void updateTxtAttrib();
static inline int isFile();
static inline uint64_t usTime();
+static inline void cb_wait(uint64_t);
static inline char* gethome() {
if (!homepath) {
@@ -738,6 +788,78 @@ static inline void ttycheck() {
if (!isatty(STDOUT_FILENO)) {fputs("CLIBASIC does not support STDOUT redirection.\n", stderr); exit(1);}
}
+#ifdef _WIN32
+pthread_t uctHandle;
+pthread_mutex_t uctMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutexattr_t uctMutexA;
+bool uctStatus[2];
+bool uctReady = false;
+void* ucThread(void* data) {
+ bool* status = data;
+ while (1) {
+ pthread_mutex_lock(&uctMutex);
+ status[1] = true;
+ status[0] = false;
+ pthread_mutex_unlock(&uctMutex);
+ bool l1 = true;
+ while (l1) {
+ updatechars();
+ pthread_mutex_lock(&uctMutex);
+ if (status[0]) l1 = false;
+ pthread_mutex_unlock(&uctMutex);
+ //if (l1) cb_wait(5000);
+ }
+ pthread_mutex_lock(&uctMutex);
+ status[1] = false;
+ status[0] = false;
+ pthread_mutex_unlock(&uctMutex);
+ bool l2 = true;
+ while (l2) {
+ //cb_wait(500);
+ pthread_mutex_lock(&uctMutex);
+ if (status[0]) l2 = false;
+ pthread_mutex_unlock(&uctMutex);
+ }
+ }
+}
+void uctStart() {
+ if (!uctReady) return;
+ pthread_mutex_lock(&uctMutex);
+ if (uctStatus[1]) return;
+ uctStatus[0] = true;
+ pthread_mutex_unlock(&uctMutex);
+ bool l = true;
+ while (l) {
+ pthread_mutex_lock(&uctMutex);
+ if (uctStatus[1]) l = false;
+ pthread_mutex_unlock(&uctMutex);
+ //if (l) cb_wait(50);
+ }
+}
+void uctStop() {
+ if (!uctReady) return;
+ pthread_mutex_lock(&uctMutex);
+ if (!uctStatus[1]) return;
+ uctStatus[0] = true;
+ pthread_mutex_unlock(&uctMutex);
+ bool l = true;
+ while (l) {
+ pthread_mutex_lock(&uctMutex);
+ if (!uctStatus[1]) l = false;
+ pthread_mutex_unlock(&uctMutex);
+ //if (l) cb_wait(50);
+ }
+}
+void uctInit() {
+ pthread_mutex_init(&uctMutex, NULL);
+ pthread_mutex_init(&uctMutex, &uctMutexA);
+ pthread_mutex_lock(&uctMutex);
+ pthread_mutex_unlock(&uctMutex);
+ pthread_create(&uctHandle, NULL, ucThread, &uctStatus);
+ uctReady = true;
+}
+#endif
+
static inline void readyTerm() {
ttycheck();
#ifndef _WIN32
@@ -751,6 +873,7 @@ static inline void readyTerm() {
#ifndef _WIN_NO_VT
enablevt();
#endif
+ uctInit();
#endif
if (!gethome()) {
#ifndef _WIN32
@@ -773,6 +896,8 @@ static inline void readyTerm() {
nfree(tmpcwd);
(void)ret;
}
+ #ifdef _WIN32
+ #endif
}
uint8_t roptptr = 1;
@@ -781,6 +906,9 @@ char roptstr[16] = "-";
#define RARG() {fprintf(stderr, "Short option '%c' requires argument(s) and must be last.\n", argv[i][shortopti]);}
#define IACT() {fputs("Incorrect number of arguments passed.\n", stderr);}
#define IOCT() {fputs("Incorrect number of options passed.\n", stderr);}
+#define OHBP() {fprintf(stderr, "Option '%c' has already been passed.\n", argv[i][shortopti]);}
+
+char elfsnip[6];
int main(int argc, char** argv) {
bool pexit = false;
@@ -804,14 +932,12 @@ int main(int argc, char** argv) {
fputs("No long option following dash.\n", stderr); exit(1);
} else if (!strcmp(argv[i], "--version")) {
if (argc > 2) {IOCT(); exit(1);}
- printf("Command Line Interface BASIC version %s (%s %s-bit) using ", VER, OSVER, BVER);
+ printf("Command Line Interface BASIC version %s (%s %s-bit)", VER, OSVER, BVER);
#ifdef _WIN32
- fputs("Windows API calls", stdout);
+ fputs(" using Windows API calls", stdout);
#ifndef _WIN_NO_VT
fputs(" and VT escape codes", stdout);
#endif
- #else
- fputs("VT escape codes", stdout);
#endif
putchar('\n');
puts("Copyright (C) 2021 PQCraft");
@@ -819,13 +945,14 @@ int main(int argc, char** argv) {
pexit = true;
} else if (!strcmp(argv[i], "--help")) {
if (argc > 2) {IOCT(); exit(1);}
- printf("Usage: %s [[-x] FILE [ARG]...]\n", argv[0]);
+ printf("Usage: %s [OPTIONS]... [[-x] FILE [ARG]...]\n", argv[0]);
puts("Options:");
puts(" --help Displays the usage and option information.");
puts(" --version Displays the version and license information.");
puts(" -x, --exec FILE [ARG]... Runs FILE and passes ARGs to FILE.");
puts(" -c, --command COMMAND Runs COMMAND as if in shell mode.");
- puts(" -k, --keep Stops CLIBASIC from resetting text attributes when exiting.");
+ puts(" -k, --keep Stops the text attributes from being reset.");
+ puts(" -K, --keep-all Stops the text attributes and terminal state from being reset.");
puts(" -s, --skip Skips searching for autorun programs.");
puts(" -i, --info Displays an info string when starting in shell mode.");
puts(" -r, --redirection Allows for redirection (this may cause issues).");
@@ -836,60 +963,64 @@ int main(int argc, char** argv) {
} else if (!strcmp(argv[i], "--exec") || (shortopt && argv[i][shortopti] == 'x')) {
if (shortopt && argv[i][shortopti + 1]) {RARG(); exit(1);}
if (runc) {fputs("Cannot run command and file.\n", stderr); exit(1);}
- if (runfile) {unloadProg(); IOCT(); exit(1);}
- ++i;
- if (!argv[i]) {fputs("No filename provided.\n", stderr); exit(1);}
+ if (runfile) {unloadProg(); OHBP(); exit(1);}
+ if (!argv[++i]) {IACT(); exit(1);}
argslater = true;
- if (!loadProg(argv[i])) {printError(cerr); exit(1);}
+ if (!loadProg(argv[i])) {printError(cerr, NULL, NULL); exit(1);}
inProg = true;
runfile = true;
progargs = (char**)malloc((argc - i) * sizeof(char*));
for (progargc = 1; progargc < argc - i; ++progargc) {
- progargs[progargc] = malloc(strlen(argv[i + progargc]) + 1);
- copyStr(argv[i + progargc], progargs[progargc]);
+ progargs[progargc] = strdup(argv[i + progargc]);
}
i = argc;
} else if (!strcmp(argv[i], "--keep") || (shortopt && argv[i][shortopti] == 'k')) {
- if (keep) {IOCT(); exit(1);}
+ if (keep) {OHBP(); exit(1);}
keep = true;
roptstr[roptptr++] = 'k';
if (shortopt) goto chkshortopt;
+ } else if (!strcmp(argv[i], "--keep-all") || (shortopt && argv[i][shortopti] == 'K')) {
+ if (keepall) {OHBP(); exit(1);}
+ keep = true;
+ keepall = true;
+ roptstr[roptptr++] = 'K';
+ if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--skip") || (shortopt && argv[i][shortopti] == 's')) {
- if (skip) {IOCT(); exit(1);}
+ if (skip) {OHBP(); exit(1);}
skip = true;
roptstr[roptptr++] = 's';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--info") || (shortopt && argv[i][shortopti] == 'i')) {
- if (info) {IOCT(); exit(1);}
+ if (info) {OHBP(); exit(1);}
info = true;
roptstr[roptptr++] = 'i';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--redirection") || (shortopt && argv[i][shortopti] == 'r')) {
- if (redirection) {IOCT(); exit(1);}
+ if (redirection) {OHBP(); exit(1);}
redirection = true;
roptstr[roptptr++] = 'r';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--newline") || (shortopt && argv[i][shortopti] == 'n')) {
- if (checknl) {IOCT(); exit(1);}
+ if (checknl) {OHBP(); exit(1);}
checknl = true;
roptstr[roptptr++] = 'n';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--no-escapes") || (shortopt && argv[i][shortopti] == 'e')) {
- if (!esc) {IOCT(); exit(1);}
+ if (!esc) {OHBP(); exit(1);}
esc = false;
roptstr[roptptr++] = 'e';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--no-curpos") || (shortopt && argv[i][shortopti] == 'p')) {
- if (!cpos) {IOCT(); exit(1);}
+ if (!cpos) {OHBP(); exit(1);}
cpos = false;
roptstr[roptptr++] = 'p';
if (shortopt) goto chkshortopt;
} else if (!strcmp(argv[i], "--command") || (shortopt && argv[i][shortopti] == 'c')) {
if (shortopt && argv[i][shortopti + 1]) {RARG(); exit(1);}
if (runfile) {fputs("Cannot run file and command.\n", stderr); exit(1);}
- if (runc) {IOCT(); exit(1);}
+ if (runc) {OHBP(); exit(1);}
i++;
- if (!argv[i]) {fputs( "No command provided.\n", stderr); exit(1);}
+ if (!argv[i]) {IACT(); exit(1);}
runc = true;
runfile = true;
copyStr(argv[i], conbuf);
@@ -902,16 +1033,15 @@ int main(int argc, char** argv) {
}
} else {
if (runc) {fputs("Cannot run command and file.\n", stderr); exit(1);}
- if (runfile) {unloadProg(); IOCT(); exit(1);}
- if (!argv[i]) {fputs("No filename provided.\n", stderr); exit(1);}
+ if (runfile) {unloadProg(); OHBP(); exit(1);}
+ if (!argv[i]) {IACT(); exit(1);}
argslater = true;
- if (!loadProg(argv[i])) {printError(cerr); exit(1);}
+ if (!loadProg(argv[i])) {printError(cerr, NULL, NULL); exit(1);}
inProg = true;
runfile = true;
progargs = (char**)malloc((argc - i) * sizeof(char*));
for (progargc = 1; progargc < argc - i; ++progargc) {
- progargs[progargc] = malloc(strlen(argv[i + progargc]) + 1);
- copyStr(argv[i + progargc], progargs[progargc]);
+ progargs[progargc] = strdup(argv[i + progargc]);
}
i = argc;
}
@@ -1023,10 +1153,8 @@ int main(int argc, char** argv) {
#endif
#endif
}
- cmd = NULL;
- argt = NULL;
- arg = NULL;
- srand(usTime());
+ cmd = (char*)malloc(CB_BUF_SIZE);
+ srand(usTime() + clock());
if (!runfile && gethome()) {
char* tmpcwd = getcwd(NULL, 0);
int ret = chdir(homepath);
@@ -1053,6 +1181,7 @@ int main(int argc, char** argv) {
cp = 0;
if (chkinProg) {inProg = true; chkinProg = false;}
if (!inProg && !runc) {
+ cmdint = false;
if (runfile) cleanExit();
clearGlobals();
promptReady();
@@ -1075,19 +1204,22 @@ int main(int argc, char** argv) {
if (curx > 1) putchar('\n');
#endif
updateTxtAttrib();
- inprompt = true;
#ifdef _WIN32
setsig(SIGINT, rl_sigh);
#endif
conbuf[0] = 0;
- #ifndef _WIN32
- setsig(SIGINT, cleanExit);
- #endif
txtqunlock();
+ #ifdef _WIN32
+ uctStop();
+ #endif
+ inprompt = true;
tmpstr = readline(pstr);
+ inprompt = false;
+ #ifdef _WIN32
+ uctStart();
+ #endif
updateTxtAttrib();
concp = 0;
- inprompt = false;
if (!tmpstr) {err = 0; cleanExit();}
int32_t tmpptr;
if (tmpstr[0] == 0) {nfree(tmpstr); goto brkproccmd;}
@@ -1109,7 +1241,6 @@ int main(int argc, char** argv) {
if (strcmp(tmpstr, cmpstr)) {add_history(tmpstr); copyStr(tmpstr, cmpstr);}
copyStr(tmpstr, conbuf);
nfree(tmpstr);
- cmdint = false;
}
if (runc) runc = false;
cmdl = 0;
@@ -1131,12 +1262,11 @@ int main(int argc, char** argv) {
}
if (lockpl) lockpl = false;
while (progbuf[progindex][cp - cmdl] == ' ' && cmdl > 0) {cmdl--;}
- cmd = (char*)realloc(cmd, cmdl + 1);
cmdpos = cp - cmdl;
copyStrSnip(progbuf[progindex], cp - cmdl, cp, cmd);
cmdl = 0;
- runcmd();
- if (cmdint) {inProg = false; unloadAllProg(); cmdint = false; goto brkproccmd;}
+ if (cmdint) {inProg = false; unloadAllProg(); txtqunlock(); goto brkproccmd;}
+ if (runcmd(cmd)) {cp = -1; concp = -1; chkinProg = inProg = false;}
if (cp == -1) {inProg = false; unloadAllProg(); goto brkproccmd;}
if (cp > -1 && progbuf[progindex][cp] == 0) {
unloadProg();
@@ -1158,12 +1288,11 @@ int main(int argc, char** argv) {
if (conbuf[concp] == '"') {inStr = !inStr; cmdl++;} else
if ((conbuf[concp] == ':' && !inStr) || conbuf[concp] == 0) {
while (conbuf[concp - cmdl] == ' ' && cmdl > 0) {cmdl--;}
- cmd = (char*)realloc(cmd, cmdl + 1);
cmdpos = concp - cmdl;
copyStrSnip(conbuf, concp - cmdl, concp, cmd);
cmdl = 0;
- runcmd();
- if (cmdint) {txtqunlock(); cmdint = false; goto brkproccmd;}
+ if (cmdint) {runc = false; unloadAllProg(); txtqunlock(); goto brkproccmd;}
+ if (runcmd(cmd)) {cp = -1; concp = -1; chkinProg = inProg = false;}
if (concp == -1) goto brkproccmd;
if (concp > -1 && conbuf[concp] == 0) {
goto brkproccmd;
@@ -1175,9 +1304,6 @@ int main(int argc, char** argv) {
}
}
brkproccmd:;
- #ifndef _WIN32
- setsig(SIGINT, cleanExit);
- #endif
txtqunlock();
}
txtqunlock();
@@ -1206,9 +1332,7 @@ static inline void cb_wait(uint64_t d) {
nanosleep(&dts, NULL);
#else
uint64_t t = d + usTime();
- while (t > usTime() && !cmdint) {
- if (!(usTime() % 5000))updatechars();
- }
+ while (t > usTime() && !cmdint) {}
#endif
}
@@ -1295,15 +1419,17 @@ void unloadProg() {
progfn = (char**)realloc(progfn, progindex * sizeof(char*));
progbuf = (char**)realloc(progbuf, progindex * sizeof(char*));
for (int i = 0; i < gotomaxct; ++i) {
- if (gotodata[i].used) nfree(gotodata[i].name);
+ if (gotodata[i].inuse) nfree(gotodata[i].name);
}
nfree(gotodata);
gotodata = proggotodata[progindex];
gotomaxct = proggotomaxct[progindex];
+ if (!subinfo.insub && autorun) autorun = false;
cp = progcp[progindex];
cmdl = progcmdl[progindex];
progLine = proglinebuf[progindex];
brkinfo = oldbrkinfo[progindex];
+ subinfo = oldsubinfo[progindex];
dlstackp = mindlstackp[progindex];
itstackp = minitstackp[progindex];
fnstackp = minfnstackp[progindex];
@@ -1314,44 +1440,21 @@ void unloadProg() {
minitstackp = (int*)realloc(minitstackp, progindex * sizeof(int));
minfnstackp = (int*)realloc(minfnstackp, progindex * sizeof(int));
oldbrkinfo = (cb_brkinfo*)realloc(oldbrkinfo, progindex * sizeof(cb_brkinfo));
+ oldsubinfo = (cb_subinfo*)realloc(oldsubinfo, progindex * sizeof(cb_subinfo));
proggotodata = (cb_goto**)realloc(proggotodata, progindex * sizeof(cb_goto*));
proggotomaxct = (int*)realloc(proggotomaxct, progindex * sizeof(int));
progindex--;
if (progindex < 0) inProg = false;
- if (autorun) autorun = false;
}
void unloadAllProg() {
for (int i = 0; i <= progindex; ++i) {
unloadProg();
}
+ inProg = false;
}
-bool loadProg(char* filename) {
- #if defined(_WIN32) && !defined(_WIN_NO_VT)
- enablevt();
- #endif
- retval = 0;
- seterrstr(filename);
- cerr = 27;
- FILE* prog = fopen(filename, "r");
- if (!prog) {
- if (errno == ENOENT) cerr = 15;
- return false;
- }
- if (!isFile(filename)) {
- fclose(prog);
- cerr = 18;
- return false;
- }
- ++progindex;
- fseek(prog, 0, SEEK_END);
- progfn = (char**)realloc(progfn, (progindex + 1) * sizeof(char*));
- #ifdef _WIN32
- progfn[progindex] = _fullpath(NULL, filename, CB_BUF_SIZE);
- #else
- progfn[progindex] = realpath(filename, NULL);
- #endif
+void prepProgData() {
++progindex;
progbuf = (char**)realloc(progbuf, progindex * sizeof(char*));
progcp = (int32_t*)realloc(progcp, progindex * sizeof(int32_t));
@@ -1360,6 +1463,7 @@ bool loadProg(char* filename) {
mindlstackp = (int*)realloc(mindlstackp, progindex * sizeof(int));
minitstackp = (int*)realloc(minitstackp, progindex * sizeof(int));
oldbrkinfo = (cb_brkinfo*)realloc(oldbrkinfo, progindex * sizeof(cb_brkinfo));
+ oldsubinfo = (cb_subinfo*)realloc(oldsubinfo, progindex * sizeof(cb_subinfo));
minfnstackp = (int*)realloc(minfnstackp, progindex * sizeof(int));
proggotodata = (cb_goto**)realloc(proggotodata, progindex * sizeof(cb_goto*));
proggotomaxct = (int*)realloc(proggotomaxct, progindex * sizeof(int));
@@ -1372,6 +1476,7 @@ bool loadProg(char* filename) {
mindlstackp[progindex] = dlstackp;
minitstackp[progindex] = itstackp;
oldbrkinfo[progindex] = brkinfo;
+ oldsubinfo[progindex] = subinfo;
minfnstackp[progindex] = fnstackp;
proggotodata[progindex] = gotodata;
proggotomaxct[progindex] = gotomaxct;
@@ -1383,6 +1488,68 @@ bool loadProg(char* filename) {
cmdl = 0;
progLine = 1;
memset(&brkinfo, 0, sizeof(brkinfo));
+ memset(&subinfo, 0, sizeof(subinfo));
+}
+
+bool loadSub(char* name, bool func, uint8_t* type) {
+ upCase(name);
+ seterrstr(name);
+ int s = -1;
+ for (int i = 0; i < submaxct; ++i) {
+ if (subdata[i].inuse && !strcmp(subdata[i].name, name)) {s = i; break;}
+ }
+ if (s == -1) {cerr = 37; return false;}
+ uint8_t ntype = 0;
+ if (func) {
+ if (!subdata[s].type) {cerr = 2; return false;}
+ ntype = subdata[s].type;
+ } else {
+ if (subdata[s].type) {cerr = 2; return false;}
+ }
+ ++progindex;
+ prepProgData();
+ if (func) *type = ntype;
+ progfn = (char**)realloc(progfn, (progindex + 1) * sizeof(char*));
+ progfn[progindex] = strdup(name);
+ progbuf[progindex] = strdup(subdata[s].data);
+ if (argslater) {
+ argslater = false;
+ } else {
+ progargc = newprogargc;
+ newprogargc = 0;
+ progargs = newprogargs;
+ newprogargs = NULL;
+ }
+ return true;
+}
+
+bool loadProg(char* filename) {
+ #if defined(_WIN32) && !defined(_WIN_NO_VT)
+ enablevt();
+ #endif
+ retval = 0;
+ seterrstr(filename);
+ cerr = 27;
+ FILE* prog = fopen(filename, "r");
+ if (!prog) {
+ if (errno == ENOENT) cerr = 15;
+ return false;
+ }
+ if (!isFile(filename)) {
+ fclose(prog);
+ cerr = 18;
+ return false;
+ }
+ cerr = 0;
+ ++progindex;
+ fseek(prog, 0, SEEK_END);
+ progfn = (char**)realloc(progfn, (progindex + 1) * sizeof(char*));
+ #ifdef _WIN32
+ progfn[progindex] = _fullpath(NULL, filename, CB_BUF_SIZE);
+ #else
+ progfn[progindex] = realpath(filename, NULL);
+ #endif
+ prepProgData();
if (argslater) {
argslater = false;
} else {
@@ -1413,9 +1580,9 @@ bool loadProg(char* filename) {
return true;
}
-static inline double randNum(double num1, double num2) {
- double range = num2 - num1;
- double div = RAND_MAX / range;
+static inline long double randNum(long double num1, long double num2) {
+ long double range = num2 - num1;
+ long double div = RAND_MAX / range;
return num1 + (rand() / div);
}
@@ -1535,20 +1702,23 @@ static inline void copyStrApnd(char* str1, char* str2) {
}
#endif
-static inline void copyStrApndQ(char* str1, char* str2) {
+#ifdef _WIN32
+static inline void copyStrWinApnd(char* str1, char* str2) {
+ bool spc = (*str2);
while (*str2) {++str2;}
+ if (spc) *str2++ = ' ';
*str2++ = '"';
- for (; *str1; ++str1, ++str2) {*str2 = *str1;}
+ for (; *str1; ++str1, ++str2) {if (*str1 == '\\' || *str1 == '"') {*str2++ = '\\';} *str2 = *str1;}
*str2++ = '"';
*str2 = 0;
}
-static inline void copyStrApndNoEsc(char* str1, char* str2) {
+#endif
+
+static inline char* copyStrApndO(char* str1, char* str2) {
while (*str2) {++str2;}
- for (; *str1; ++str1, ++str2) {
- if ((*str2 = *str1) == '\\') {*str2 = '\\';}
- if (*str1 == '\'') {*str2 = '\\'; *++str2 = '\'';}
- }
+ for (; *str1; ++str1, ++str2) {*str2 = *str1;}
*str2 = 0;
+ return str2;
}
static inline void copyStrSnip(char* str1, int32_t i, int32_t j, char* str2) {
@@ -1594,6 +1764,67 @@ static inline void seterrstr(char* newstr) {
copyStr(newstr, errstr);
}
+#ifndef _WIN32
+typedef pid_t cb_exec_async_t;
+#else
+typedef HANDLE cb_exec_async_t;
+char* cb_exec_async_buf = NULL;
+#endif
+
+static inline cb_exec_async_t cb_exec_async(char** args) {
+ #ifndef _WIN32
+ static bool exec_failed = false;
+ exec_failed = false;
+ pid_t pid = vfork();
+ if (pid == 0) {
+ execvp(args[0], args);
+ exec_failed = true;
+ exit(127);
+ } else if (pid > 0) {
+ if (!exec_failed) return pid;
+ }
+ return 0;
+ #else
+ if (!cb_exec_async_buf) cb_exec_async_buf = malloc(CB_BUF_SIZE);
+ *cb_exec_async_buf = 0;
+ for (; *args; ++args) {
+ copyStrWinApnd(*args, cb_exec_async_buf);
+ }
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ memset(&pi, 0, sizeof(pi));
+ if (!CreateProcess(NULL, cb_exec_async_buf, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) return NULL;
+ else return pi.hProcess;
+ #endif
+}
+
+static inline int16_t cb_exec(char** args) {
+ #ifndef _WIN32
+ pid_t pid = 0;
+ if ((pid = cb_exec_async(args))) {
+ int ecode = 0;
+ while (wait(&ecode) != pid) {}
+ return WEXITSTATUS(ecode);
+ }
+ return -1;
+ #else
+ HANDLE pid = NULL;
+ uctStop();
+ if ((pid = cb_exec_async(args))) {
+ WaitForSingleObject(pid, INFINITE);
+ DWORD tmpret;
+ int ret = GetExitCodeProcess(pid, (LPDWORD)&tmpret);
+ (void)ret;
+ uctStart();
+ return tmpret & 0xFF;
+ }
+ uctStart();
+ return -1;
+ #endif
+}
+
static inline void updateTxtAttrib() {
#ifndef _WIN_NO_VT
if (!esc) return;
@@ -1621,19 +1852,10 @@ static inline void updateTxtAttrib() {
#else
uint8_t tmpfgc, tmpbgc;
if (txtattrib.truecolor) {
- uint8_t a;
- tmpfgc = (((txtattrib.truefgc >> 23) & 1) << 2) | (((txtattrib.truefgc >> 15) & 1) << 1) | ((txtattrib.truefgc >> 7) & 1);
- tmpfgc |= ((((txtattrib.truefgc >> 22) & 1) & ((txtattrib.truefgc >> 21) & 1)) << 2)\
- | ((((txtattrib.truefgc >> 14) & 1) & ((txtattrib.truefgc >> 13) & 1)) << 1)\
- | (((txtattrib.truefgc >> 6) & 1) & ((txtattrib.truefgc >> 5) & 1));
- a = ((((txtattrib.truefgc >> 16) & 0xFF) + ((txtattrib.truefgc >> 8) & 0xFF) + (txtattrib.truefgc & 0xFF)) / 3);
- tmpfgc |= (8 * (a > 84));
- tmpbgc = (((txtattrib.truebgc >> 23) & 1) << 2) | (((txtattrib.truebgc >> 15) & 1) << 1) | ((txtattrib.truebgc >> 7) & 1);
- tmpbgc |= ((((txtattrib.truebgc >> 22) & 1) & ((txtattrib.truebgc >> 21) & 1)) << 2)\
- | ((((txtattrib.truebgc >> 14) & 1) & ((txtattrib.truebgc >> 13) & 1)) << 1)\
- | (((txtattrib.truebgc >> 6) & 1) & ((txtattrib.truebgc >> 5) & 1));
- a = ((((txtattrib.truebgc >> 16) & 0xFF) + ((txtattrib.truebgc >> 8) & 0xFF) + (txtattrib.truebgc & 0xFF)) / 3);
- tmpbgc |= (8 * (a > 84));
+ tmpfgc = ((((txtattrib.truefgc >> 16) & 0xFF) > 85) << 2 | (((txtattrib.truefgc >> 8) & 0xFF) > 85) << 1 | ((txtattrib.truefgc & 0xFF) > 85))\
+ | (((txtattrib.truefgc >> 16) & 0xFF) > 170 || ((txtattrib.truefgc >> 8) & 0xFF) > 170 || (txtattrib.truefgc & 0xFF) > 170) << 3;
+ tmpbgc = ((((txtattrib.truebgc >> 16) & 0xFF) > 85) << 2 | (((txtattrib.truebgc >> 8) & 0xFF) > 85) << 1 | ((txtattrib.truebgc & 0xFF) > 85))\
+ | (((txtattrib.truebgc >> 16) & 0xFF) > 170 || ((txtattrib.truebgc >> 8) & 0xFF) > 170 || (txtattrib.truebgc & 0xFF) > 170) << 3;
} else {
uint8_t b1 = 0, b2 = 0;
b1 = txtattrib.fgc & 1; b2 = (txtattrib.fgc >> 2) & 1; tmpfgc = (b1 ^ b2);
@@ -1641,9 +1863,11 @@ static inline void updateTxtAttrib() {
b1 = txtattrib.bgc & 1; b2 = (txtattrib.bgc >> 2) & 1; tmpbgc = (b1 ^ b2);
tmpbgc = (tmpbgc) | (tmpbgc << 2); tmpbgc = txtattrib.bgc ^ tmpbgc;
}
- if (txtattrib.dim) {tmpfgc %= 8; tmpbgc %= 8;}
+ if (!txtattrib.truecolor && txtattrib.dim) {tmpfgc %= 8; tmpbgc %= 8;}
if (txtattrib.reverse) swap(tmpfgc, tmpbgc);
- SetConsoleTextAttribute(hConsole, (tmpfgc % 16) + ((tmpbgc % 16) << 4));
+ if (!txtattrib.fgce) tmpfgc = (ocAttrib & 0b11110000);
+ if (!txtattrib.bgce) tmpbgc = (ocAttrib & 0b00001111) >> 4;
+ SetConsoleTextAttribute(hConsole, (tmpfgc % 16) | ((tmpbgc % 16) << 4));
#endif
fflush(stdout);
}
@@ -1809,7 +2033,7 @@ uint8_t getFunc(char* inbuf, char* outbuf) {
outbuf[0] = '0' + ret;
outbuf[1] = 0;
goto fexit;
- } else if (!strcmp(farg[0], "EXECA") || !strcmp(farg[0], "EXECA$")) {
+ } else if (!strcmp(farg[0], "EXECA") || !strcmp(farg[0], "EXECA$") || !strcmp(farg[0], "CALLFUNC")) {
skipfargsolve = true;
}
}
@@ -2013,8 +2237,7 @@ bool setVar(char* vn, char* val, uint8_t t, int32_t s) {
if (s == -1) s = 0;
vardata[v].data = (char**)malloc((s + 1) * sizeof(char*));
for (int32_t i = 0; i <= s; ++i) {
- vardata[v].data[i] = (char*)malloc(strlen(val) + 1);
- copyStr(val, vardata[v].data[i]);
+ vardata[v].data[i] = strdup(val);
}
} else {
if (s != -1) {cerr = 25; return false;}
@@ -2066,7 +2289,7 @@ bool delVar(char* vn) {
}
nfree(vardata[v].data);
if (v == varmaxct - 1) {
- while (!vardata[v].inuse && v >= 0) {varmaxct--; v--;}
+ while (v >= 0 && !vardata[v].inuse) {varmaxct--; v--;}
vardata = (cb_var*)realloc(vardata, varmaxct * sizeof(cb_var));
}
}
@@ -2135,327 +2358,195 @@ bool closeFile(int num) {
return true;
}
-static inline bool gvchkchar(char* tmp, int32_t i) {
- if (isSpChar(tmp[i + 1])) {
- if (tmp[i + 1] == '-') {
- if (isSpChar(tmp[i + 2])) {
- cerr = 1; return false;
- }
- } else {
- cerr = 1; return false;
- }
- } else {
- if (i > 0 && isSpChar(tmp[i - 1])) {
- cerr = 1; return false;
- }
- }
- return true;
-}
-
uint16_t getValIndex = 0;
-char* getVal_tmp[4] = {NULL, NULL, NULL, NULL};
+char* getVal_tmp[4] = {NULL, NULL};
+
+typedef struct {
+ char act;
+ bool neg;
+ char* data;
+ long double ndata;
+} __attribute__((aligned(sizeof(void*)))) cb_gvtoken;
+
+cb_gvtoken token[256];
uint8_t getVal(char* inbuf, char* outbuf) {
if (inbuf[0] == 0) {return 255;}
- char* tmp[4];
+ //printf("getVal[%d]: in: {%s}\n", getValIndex, inbuf); uint64_t starttime = usTime();
+ char* tmp[2];
if (getValIndex) {
tmp[0] = malloc(CB_BUF_SIZE);
tmp[1] = malloc(CB_BUF_SIZE);
- tmp[2] = malloc(CB_BUF_SIZE);
- tmp[3] = malloc(CB_BUF_SIZE);
} else {
tmp[0] = getVal_tmp[0];
tmp[1] = getVal_tmp[1];
- tmp[2] = getVal_tmp[2];
- tmp[3] = getVal_tmp[3];
}
getValIndex++;
- int32_t ip = 0, jp = 0;
- uint8_t t = 0;
- uint8_t dt = 0;
- bool inStr = false;
- register double num1 = 0;
- register double num2 = 0;
- register double num3 = 0;
- int numAct;
- bool* seenStr = NULL;
- if ((isSpChar(inbuf[0]) && inbuf[0] != '-') || isSpChar(inbuf[strlen(inbuf) - 1])) {cerr = 1; dt = 0; goto gvreturn;}
+ char* ip = NULL, * jp = NULL;
int pct = 0, bct = 0;
- tmp[0][0] = 0; tmp[1][0] = 0; tmp[2][0] = 0; tmp[3][0] = 0;
+ uint8_t t = 0, dt = 0;
+ bool* seenStr = NULL;
+ bool inStr = false;
seenStr = malloc(sizeof(bool));
seenStr[0] = false;
- for (register int32_t i = 0; inbuf[i]; ++i) {
- switch (inbuf[i]) {
- default:;
- if (inStr) break;
- if (inbuf[i] == ',' || isSpChar(inbuf[i])) seenStr[pct] = false;
- break;
- case '&':;
- if (!inStr && pct > 0) seenStr[pct] = false;
- break;
- case '|':;
- if (!inStr && pct > 0) seenStr[pct] = false;
- break;
- case '"':;
- inStr = !inStr;
- if (inStr && seenStr[pct]) {
- dt = 0;
- cerr = 1;
- goto gvreturn;
- }
- seenStr[pct] = true;
- break;
- case '(':;
- if (inStr) break;
- if (pct == 0) {ip = i;}
- pct++;
- seenStr = (bool*)realloc(seenStr, (pct + 1) * sizeof(bool));
- seenStr[pct] = false;
- break;
- case ')':;
- if (inStr) break;
- pct--;
- if (pct == 0 && (ip == 0 || isSpChar(inbuf[ip - 1]))) {
- int32_t tmplen[2];
- tmplen[0] = strlen(inbuf);
- jp = i;
- copyStrSnip(inbuf, ip + 1, jp, tmp[0]);
- t = getVal(tmp[0], tmp[0]);
- if (t == 0) {dt = 0; goto gvreturn;}
- if (dt == 0) dt = t;
- if (t == 255) {t = 1; dt = 1;}
- if (t != dt) {cerr = 2; dt = 0; goto gvreturn;}
- copyStrFrom(inbuf, jp + 1, tmp[1]);
- inbuf[ip] = 0;
- if (t == 1) copyStrApndQ(tmp[0], inbuf);
- else copyStrApnd(tmp[0], inbuf);
- copyStrApnd(tmp[1], inbuf);
- tmp[0][0] = 0; tmp[1][0] = 0; tmp[2][0] = 0; tmp[3][0] = 0;
- tmplen[1] = strlen(inbuf);
- i -= tmplen[0] - tmplen[1];
+ cb_gvtoken* token = NULL;
+ tmp[0][0] = '+'; tmp[0][1] = 0; tmp[1][0] = 0;
+ int tokens = 0;
+ bool mtoken = false;
+ if (isSpChar(*inbuf) && *inbuf != '-') {cerr = 1; dt = 0; goto gvreturn;}
+ char* t1, * t2;
+ uint8_t sawSpChar = 0;
+ //printf("getVal[%d]: block 0: time: [%ld]\n", getValIndex - 1, usTime() - starttime); starttime = usTime();
+ for (t1 = inbuf, t2 = tmp[0]; *t1; ++t1) {
+ if (!pct && !bct && !inStr) {
+ if (isSpChar(*t2)) {
+ if (*t2 == '-' && sawSpChar) {
+ if (sawSpChar > 1) {dt = 0; cerr = 1; goto gvreturn;}
+ } else if (isSpChar(*t2) && sawSpChar) {
+ dt = 0; cerr = 1; goto gvreturn;
+ } else {
+ ++tokens;
}
- break;
- case '[':;
- if (inStr) break;
- bct++;
- break;
- case ']':;
- if (inStr) break;
- bct--;
- break;
+ ++sawSpChar;
+ } else {
+ sawSpChar = 0;
+ }
+ }
+ *(++t2) = *t1;
+ switch (*t1) {
+ default:; if (inStr) break; if (*t1 == ',' || isSpChar(*t1)) seenStr[pct] = false; break;
+ case '&':; if (!inStr && pct > 0) seenStr[pct] = false; break;
+ case '|':; if (!inStr && pct > 0) seenStr[pct] = false; break;
+ case '"':; if (pct || bct) break; inStr = !inStr; if (inStr && seenStr[pct]) {dt = 0; cerr = 1; goto gvreturn;} seenStr[pct] = true; break;
+ case '(':; if (inStr) break; ++pct; seenStr = (bool*)realloc(seenStr, (pct + 1) * sizeof(bool)); seenStr[pct] = false; break;
+ case ')':; if (inStr) break; --pct; break;
+ case '[':; if (inStr) break; ++bct; break;
+ case ']':; if (inStr) break; --bct; break;
}
}
- if (pct || bct) {cerr = 1; dt = 0; goto gvreturn;}
- ip = 0; jp = 0;
- tmp[0][0] = 0; tmp[1][0] = 0; tmp[2][0] = 0; tmp[3][0] = 0;
- while (1) {
- pct = 0;
- bct = 0;
- while (inbuf[jp]) {
- if (inbuf[jp] == '"') inStr = !inStr;
- if (!inStr) {
- switch (inbuf[jp]) {
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- default:;
- if ((inbuf[jp] != '-' || jp > 0) && isSpChar(inbuf[jp]) && !pct && !bct) goto gvwhileexit1;
- break;
- }
- }
- jp++;
- }
- gvwhileexit1:;
- if (inStr) {dt = 0; cerr = 1; goto gvreturn;}
- copyStrSnip(inbuf, ip, jp, tmp[0]);
- t = getType(tmp[0]);
- if (t == 1) getStr(tmp[0], tmp[0]);
- if (t == 255) {
- t = getVar(tmp[0], tmp[0]);
- if (t == 0) {dt = 0; dt = 0; goto gvreturn;}
- if (t == 1) {
- tmp[3][0] = 0;
- copyStrApndQ(tmp[0], tmp[3]);
- swap(tmp[0], tmp[3]);
- }
+ if (pct || bct || inStr) {cerr = 1; dt = 0; goto gvreturn;}
+ if (isSpChar(*t2)) {cerr = 1; dt = 0; goto gvreturn;}
+ *++t2 = 0;
+ //printf("getVal[%d]: block 1: time: [%ld]\n", getValIndex - 1, usTime() - starttime); starttime = usTime();
+ //printf("tokens: [%d]\n", tokens);
+ token = malloc(tokens * sizeof(cb_gvtoken));
+ mtoken = true;
+ for (int i = 0; i < tokens; ++i) {
+ memset(&token[i], 0, sizeof(cb_gvtoken));
+ }
+ int curtkn = 0;
+ for (t1 = tmp[0]; *t1; ++t1) {
+ switch (*t1) {
+ case '"':; if (pct || bct) break; inStr = !inStr; break;
+ case '(':; if (inStr) break; ++pct; break;
+ case ')':; if (inStr) break; --pct; break;
+ case '[':; if (inStr) break; ++bct; break;
+ case ']':; if (inStr) break; --bct; break;
}
- if (t && dt == 0) {dt = t;} else
- if ((t && t != dt)) {cerr = 2; dt = 0; goto gvreturn;} else
- if (t == 0) {cerr = 1; dt = 0; goto gvreturn;}
- if ((dt == 1 && inbuf[jp] != '+') && inbuf[jp]) {cerr = 1; dt = 0; goto gvreturn;}
- if (t == 1) {copyStrSnip(tmp[0], 1, strlen(tmp[0]) - 1, tmp[2]); copyStrApnd(tmp[2], tmp[1]);} else
- if (t == 2) {
- if (inbuf[jp - 1]) copyStrFrom(inbuf, jp, tmp[1]);
- else tmp[1][0] = 0;
- copyStrApnd(tmp[1], tmp[0]);
- register int32_t p1, p2, p3;
- bool inStr = false;
- pct = 0;
- bct = 0;
- while (1) {
- numAct = 0;
- p1 = 0, p2 = 0, p3 = 0;
- for (register int32_t i = 0; tmp[0][i]; ++i) {
- switch (tmp[0][i]) {
- case '"': if (!pct && !bct) inStr = !inStr; break;
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- case '^':;
- if (!inStr && !pct && !bct) {
- if (!gvchkchar(tmp[0], i)) {dt = 0; goto gvreturn;}
- p2 = i; numAct = 4;
- if (p2) goto foundact;
- }
- break;
- }
- }
- for (register int32_t i = 0; tmp[0][i]; ++i) {
- switch (tmp[0][i]) {
- case '"': if (!pct && !bct) inStr = !inStr; break;
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- case '*':;
- if (!inStr && !pct && !bct) {
- if (!gvchkchar(tmp[0], i)) {dt = 0; goto gvreturn;}
- p2 = i; numAct = 2;
- if (p2) goto foundact;
- }
- break;
- case '/':;
- if (!inStr && !pct && !bct) {
- if (!gvchkchar(tmp[0], i)) {dt = 0; goto gvreturn;}
- p2 = i; numAct = 3;
- if (p2) goto foundact;
- }
- break;
- }
- }
- for (register int32_t i = 0; tmp[0][i]; ++i) {
- switch (tmp[0][i]) {
- case '"': if (!pct && !bct) inStr = !inStr; break;
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- case '+':;
- if (!inStr && !pct && !bct) {
- if (!gvchkchar(tmp[0], i)) {dt = 0; goto gvreturn;}
- p2 = i; numAct = 0;
- if (p2) goto foundact;
- }
- break;
- case '-':;
- if (!inStr && !pct && !bct) {
- if (!gvchkchar(tmp[0], i)) {dt = 0; goto gvreturn;}
- p2 = i; numAct = 1;
- if (p2) goto foundact;
- }
- break;
- }
+ if (!pct && !bct && !inStr) {
+ if (isSpChar(*t1)) {
+ if (!(*t1 == '-' && sawSpChar)) {
+ ip = t1;
}
- foundact:;
- inStr = false;
- pct = 0;
- bct = 0;
- if (p2 == 0) {
- if (p3 == 0) {
- t = getType(tmp[0]);
- if (t == 0) {cerr = 1; dt = 0; goto gvreturn;} else
- if (t == 255) {
- t = getVar(tmp[0], tmp[0]);
- if (t == 0) {dt = 0; goto gvreturn;}
- if (t == 255) {t = 2; tmp[0][0] = '0'; tmp[0][1] = 0;}
- if (t != 2) {cerr = 2; dt = 0; goto gvreturn;}
- }
- }
- swap(tmp[0], tmp[1]);
- goto gvfexit;
- }
- tmp[1][0] = 0; tmp[2][0] = 0; tmp[3][0] = 0;
- for (register int32_t i = p2 - 1; i > 0; --i) {
- if (!pct && !bct && tmp[0][i] == '"') inStr = !inStr;
- if (!inStr) {
- switch (tmp[0][i]) {
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- default:;
- if (isSpChar(tmp[0][i]) && !inStr && !pct && !bct) {p1 = i; goto gvforexit1;}
- break;
- }
+ ++sawSpChar;
+ } else {
+ sawSpChar = 0;
+ if (isSpChar(*(t1 + 1)) || (!*(t1 + 1))) {
+ jp = t1 + 1;
+ token[curtkn].act = *(ip++);
+ if (token[curtkn].act == '+' && *ip == '-') {++ip; token[curtkn].act = '-';}
+ bool q = true;
+ if (*ip == '(') {
+ copyStrTo(ip + 1, jp - ip - 2, tmp[1]);
+ t = getVal(tmp[1], tmp[1]);
+ if (!t) {dt = 0; goto gvreturn;}
+ if (t == 255) {dt = 0; cerr = 1; goto gvreturn;}
+ if (!dt) dt = t;
+ else if (t != dt) {dt = 0; cerr = 2; goto gvreturn;}
+ q = false;
+ } else {
+ copyStrTo(ip, jp - ip, tmp[1]);
+ t = getType(tmp[1]);
+ if (!t) {dt = 0; cerr = 1; goto gvreturn;}
+ if (t == 255) {t = getVar(tmp[1], tmp[1]); q = false;}
+ if (!t) {dt = 0; goto gvreturn;}
+ if (!dt) dt = t;
+ else if (t != dt) {dt = 0; cerr = 2; goto gvreturn;}
}
- }
- gvforexit1:;
- for (register int32_t i = p2 + 1; true; ++i) {
- if (!pct && !bct && tmp[0][i] == '"') inStr = !inStr;
- if (!inStr) {
- switch (tmp[0][i]) {
- case '(': pct++; break;
- case ')': pct--; break;
- case '[': bct++; break;
- case ']': bct--; break;
- case 0: p3 = i; goto gvforexit2;
- default:;
- if (isSpChar(tmp[0][i]) && i != p2 + 1 && !pct && !bct) {p3 = i; goto gvforexit2;}
- break;
+ if (t == 1) {
+ if (token[curtkn].act != '+') {dt = 0; cerr = 1; goto gvreturn;}
+ int32_t tmplen = strlen(tmp[1]) - q;
+ token[curtkn].data = malloc(tmplen + 1);
+ copyStrSnip(tmp[1], q, tmplen, token[curtkn].data);
+ if (q) getStr(token[curtkn].data, token[curtkn].data);
+ } else {
+ token[curtkn].ndata = strtold(tmp[1], NULL);
+ if (q && (token[curtkn].act == '*' || token[curtkn].act == '/') && token[curtkn].ndata < 0) {
+ token[curtkn].neg = true;
+ token[curtkn].ndata = -token[curtkn].ndata;
}
}
+ //printf("added token: {%c} {%c}: {%s}/[%Lf]\n", token[curtkn].act, token[curtkn].neg, token[curtkn].data, token[curtkn].ndata);
+ ++curtkn;
+ jp = ip;
}
- gvforexit2:;
- if (p1 != 0 && isSpChar(tmp[0][p1])) p1++;
- copyStrSnip(tmp[0], p1, p2, tmp[2]);
- t = getType(tmp[2]);
- if (t == 0) {cerr = 1; dt = 0; goto gvreturn;} else
- if (t == 255) {t = getVar(tmp[2], tmp[2]); if (t == 0) {dt = 0; goto gvreturn;} if (t != 2) {cerr = 2; dt = 0; goto gvreturn;}}
- copyStrSnip(tmp[0], p2 + 1, p3, tmp[3]);
- t = getType(tmp[3]);
- if (t == 0) {cerr = 1; dt = 0; goto gvreturn;} else
- if (t == 255) {t = getVar(tmp[3], tmp[3]); if (t == 0) {dt = 0; goto gvreturn;} if (t != 2) {cerr = 2; dt = 0; goto gvreturn;}}
- if (!strcmp(tmp[2], ".")) {cerr = 1; dt = 0; goto gvreturn;}
- num1 = atof(tmp[2]);
- if (!strcmp(tmp[2], ".")) {cerr = 1; dt = 0; goto gvreturn;}
- num2 = atof(tmp[3]);
- switch (numAct) {
- case 0: num3 = num1 + num2; break;
- case 1: num3 = num1 - num2; break;
- case 2: num3 = num1 * num2; break;
- case 3: if (num2 == 0) {cerr = 5; dt = 0; goto gvreturn;} num3 = num1 / num2; break;
- case 4:;
- if (num1 == 0) {if (num2 == 0) {cerr = 5; dt = 0; goto gvreturn;} num3 = 0; break;}
- if (num2 == 0) {num3 = 1; break;}
- num3 = pow(num1, num2);
- break;
- }
- sprintf(tmp[1], "%lf", num3);
- int32_t i = 0, j = strlen(tmp[1]) - 1;
- bool dp = false;
- while (tmp[1][i]) {if (tmp[1][i++] == '.') {dp = true; tmp[1][i + 6] = 0; break;}}
- if (dp) {while (tmp[1][j] == '0') {--j;} if (tmp[1][j] == '.') {--j;}}
- i = (tmp[1][0] == '-'); dp = (bool)i;
- while (tmp[1][i] == '0') {++i;}
- if (!tmp[1][i] || tmp[1][i] == '.') {--i;}
- if (dp) tmp[1][--i] = '-';
- copyStrSnip(tmp[1], i, j + 1, tmp[2]);
- copyStrFrom(tmp[0], p3, tmp[3]);
- if (p1) copyStrTo(tmp[0], p1, tmp[1]);
- else {tmp[1][0] = 0;}
- copyStrApnd(tmp[2], tmp[1]);
- copyStrApnd(tmp[3], tmp[1]);
- swap(tmp[1], tmp[0]);
}
}
- if (inbuf[jp] == 0) {break;}
- jp++;
- ip = jp;
}
- gvfexit:;
+ //printf("getVal[%d] to solve: [%d]:{%s}\n", getValIndex, tokens, tmp[0]);
+ //printf("getVal[%d]: block 2: time: [%ld]\n", getValIndex - 1, usTime() - starttime); starttime = usTime();
if (dt == 2) {
+ if (tokens == 1) goto skipt;
+ for (int i = 1; i < tokens; ++i) {
+ if (token[i].act == '^') {
+ if (token[i - 1].ndata == 0) {if (token[i].ndata == 0) {cerr = 5; dt = 0; goto gvreturn;} token[i - 1].ndata = 0; continue;}
+ if (token[i].ndata == 0) {token[i - 1].ndata = 1; continue;}
+ token[i - 1].ndata = pow(token[i - 1].ndata, token[i].ndata);
+ if (token[i - 1].neg) {token[i - 1].ndata = -token[i - 1].ndata;}
+ token[i - 1].neg = false;
+ token[i].act = 0;
+ }
+ }
+ for (int i = 1; i < tokens; ++i) {
+ if (token[i].act == '*') {
+ int j;
+ for (j = i - 1; j >= 0 && token[j].act == 0; --j) {}
+ if (token[i].neg) {token[i].ndata = -token[i].ndata;}
+ if (token[j].neg) {token[j].ndata = -token[j].ndata;}
+ token[j].ndata = token[j].ndata * token[i].ndata;
+ token[j].neg = false;
+ token[i].act = 0;
+ }
+ if (token[i].act == '/') {
+ int j;
+ for (j = i - 1; j >= 0 && token[j].act == 0; --j) {}
+ if (token[i].neg) {token[i].ndata = -token[i].ndata;}
+ if (token[j].neg) {token[j].ndata = -token[j].ndata;}
+ if (token[i].ndata == 0) {cerr = 5; dt = 0; goto gvreturn;}
+ token[j].ndata = token[j].ndata / token[i].ndata;
+ token[j].neg = false;
+ token[i].act = 0;
+ }
+ }
+ for (int i = 1; i < tokens; ++i) {
+ if (token[i].act == '+') {
+ int j;
+ for (j = i - 1; j >= 0 && token[j].act == 0; --j) {}
+ if (token[j].act == '-') {token[j].ndata = -token[j].ndata; token[j].act = '+';}
+ token[j].ndata = token[j].ndata + token[i].ndata;
+ token[i].act = 0;
+ }
+ if (token[i].act == '-') {
+ int j;
+ for (j = i - 1; j >= 0 && token[j].act == 0; --j) {}
+ if (token[j].act == '-') {token[j].ndata = -token[j].ndata; token[j].act = '+';}
+ token[j].ndata = token[j].ndata - token[i].ndata;
+ token[i].act = 0;
+ }
+ }
+ skipt:;
+ //printf("last token: {%c}:[%Lf]\n", token[0].act, token[0].ndata);
+ sprintf(tmp[1], "%Lf", (token[0].act == '-') ? -token[0].ndata : token[0].ndata);
if (!strcmp(tmp[1], ".")) {cerr = 1; dt = 0; goto gvreturn;}
int32_t i = 0, j = strlen(tmp[1]) - 1;
bool dp = false;
@@ -2469,17 +2560,31 @@ uint8_t getVal(char* inbuf, char* outbuf) {
copyStrSnip(tmp[1], i, j + 1, outbuf);
if (outbuf[0] == '-' && outbuf[1] == '0' && outbuf[2] == 0) {outbuf[0] = '0'; outbuf[1] = 0;}
} else {
- copyStr(tmp[1], outbuf);
+ outbuf[0] = 0;
+ char* oOutbuf = outbuf;
+ for (int i = 0; i < tokens; ++i) {
+ //printf("appending: [%d]:{%s}\n", i, token[i].data);
+ oOutbuf = copyStrApndO(token[i].data, oOutbuf);
+ }
+ //printf("outbuf: {%s}\n", outbuf);
}
+ //printf("getVal[%d]: block 3: time: [%ld]\n", getValIndex - 1, usTime() - starttime); starttime = usTime();
if (outbuf[0] == 0 && dt != 1) {outbuf[0] = '0'; outbuf[1] = 0; dt = 2;}
gvreturn:;
getValIndex--;
nfree(seenStr);
- if (getValIndex) {nfree(tmp[0]); nfree(tmp[1]); nfree(tmp[2]); nfree(tmp[3]);}
+ if (mtoken) {
+ for (int i = 0; i < tokens; ++i) {
+ nfree(token[i].data);
+ }
+ nfree(token);
+ }
+ if (getValIndex) {nfree(tmp[0]); nfree(tmp[1]);}
+ //printf("getVal[%d]: out: [%d]:{%s}, time: [%lu]\n", getValIndex, dt, outbuf, usTime() - starttime);
return dt;
}
-static inline bool solvearg(int i) {
+static inline bool solvearg(char** arg, uint8_t* argt, int32_t* argl, int i) {
if (i == 0) {
argt[0] = 0;
argl[0] = strlen(arg[0]);
@@ -2587,60 +2692,6 @@ static inline int getArgO(int num, char* inbuf, char* outbuf, int32_t i) {
char tmpbuf[2][CB_BUF_SIZE];
-static inline void mkargs() {
- int32_t j = 0;
- while (cmd[j] == ' ') {++j;}
- int32_t h = j;
- bool sccmd = false;
- if (cmd[j] == '$' || cmd[j] == '@' || cmd[j] == '%') {
- int32_t tmpj = j + 1;
- while (cmd[tmpj] == ' ') {++tmpj;}
- if (cmd[tmpj] != '=') sccmd = true;
- }
- if (!sccmd) {
- while (cmd[h] != ' ' && cmd[h] != '=' && cmd[h]) {++h;}
- }
- copyStrFrom(cmd, (cmd[h]) ? h + 1 : h, tmpbuf[0]);
- if (!sccmd) {
- int32_t tmph = h;
- while (cmd[tmph] == ' ' && cmd[tmph]) {++tmph;}
- if (cmd[tmph] == '=') {
- strcpy(tmpbuf[1], "SET ");
- cmd[tmph] = ',';
- copyStrApnd(cmd, tmpbuf[1]);
- cmd = (char*)realloc(cmd, strlen(tmpbuf[1]) + 1);
- copyStr(tmpbuf[1], cmd);
- copyStr(tmpbuf[1], tmpbuf[0]);
- tmpbuf[1][0] = 0;
- h = 3;
- j = 0;
- }
- }
- for (int i = 0; i <= argct; ++i) {
- nfree(arg[i]);
- }
- argct = getArgCt(tmpbuf[0]);
- arg = (char**)realloc(arg, (argct + 1) * sizeof(char*));
- argt = (uint8_t*)realloc(argt, (argct + 1) * sizeof(uint8_t));
- argl = (int32_t*)realloc(argl, (argct + 1) * sizeof(int32_t));
- int32_t gptr = 0;
- copyStrSnip(cmd, j, ((sccmd) ? h + 1 : h), tmpbuf[0]);
- argl[0] = strlen(tmpbuf[0]);
- arg[0] = malloc(argl[0] + 1);
- copyStr(tmpbuf[0], arg[0]);
- copyStrFrom(cmd, (h >= argl[0]) ? argl[0] : h + 1, tmpbuf[0]);
- for (int i = 1; i <= argct; ++i) {
- int32_t ngptr = getArgO(i - 1, tmpbuf[0], tmpbuf[1], gptr);
- if (ngptr == -1) return;
- argl[i] = ngptr - gptr;
- gptr = ngptr;
- arg[i] = malloc(argl[i] + 1);
- copyStr(tmpbuf[1], arg[i]);
- arg[i][argl[i]] = 0;
- }
- if (argct == 1 && arg[1][0] == 0) {argct = 0;}
-}
-
char* lttmp_tmp[3];
int logictestexpr_index = 0;
@@ -2748,44 +2799,44 @@ static inline uint8_t logictestexpr(char* inbuf) {
goto ltreturn;
} else if (!strcmp(lttmp[1], ">")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 > num2;
goto ltreturn;
} else if (!strcmp(lttmp[1], "<")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 < num2;
goto ltreturn;
} else if (!strcmp(lttmp[1], ">=")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 >= num2;
goto ltreturn;
} else if (!strcmp(lttmp[1], "<=")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 <= num2;
goto ltreturn;
} else if (!strcmp(lttmp[1], "=>")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 >= num2;
goto ltreturn;
} else if (!strcmp(lttmp[1], "=<")) {
if (t1 == 1) {cerr = 2; goto ltreturn;}
- double num1, num2;
- sscanf(lttmp[0], "%lf", &num1);
- sscanf(lttmp[2], "%lf", &num2);
+ long double num1, num2;
+ sscanf(lttmp[0], "%Lf", &num1);
+ sscanf(lttmp[2], "%Lf", &num2);
ret = num1 <= num2;
goto ltreturn;
}
@@ -2858,7 +2909,7 @@ uint8_t logictest(char* inbuf) {
char ltmp[2][CB_BUF_SIZE];
-bool runlogic() {
+bool runlogic(char* cmd) {
ltmp[0][0] = 0; ltmp[1][0] = 0;
int32_t i = 0;
while (cmd[i] == ' ') {++i;}
@@ -2871,7 +2922,7 @@ bool runlogic() {
if (isLineNumber(ltmp[0])) {
int tmp = -1;
for (int j = 0; j < gotomaxct; ++j) {
- if (!gotodata[j].used) {tmp = j; break;}
+ if (!gotodata[j].inuse) {tmp = j; break;}
else if (!strcmp(gotodata[j].name, ltmp[0])) {
if (gotodata[j].cp == cmdpos) {goto skiplbl;}
cerr = 28; return true;
@@ -2882,11 +2933,10 @@ bool runlogic() {
++gotomaxct;
gotodata = realloc(gotodata, gotomaxct * sizeof(cb_goto));
}
- gotodata[tmp].name = malloc(strlen(ltmp[0]) + 1);
- copyStr(ltmp[0], gotodata[tmp].name);
+ gotodata[tmp].name = strdup(ltmp[0]);
gotodata[tmp].cp = cmdpos;
gotodata[tmp].pl = progLine;
- gotodata[tmp].used = true;
+ gotodata[tmp].inuse = true;
gotodata[tmp].dlsp = dlstackp;
gotodata[tmp].fnsp = fnstackp;
gotodata[tmp].itsp = itstackp;
@@ -2902,6 +2952,7 @@ bool runlogic() {
j -= i;
i = 0;
}
+ if (addsub > -1) return false;
cerr = 0;
chkCmdPtr = ltmp[0];
#include "logic.c"
@@ -2911,8 +2962,6 @@ bool runlogic() {
static inline void initBaseMem() {
getVal_tmp[0] = malloc(CB_BUF_SIZE);
getVal_tmp[1] = malloc(CB_BUF_SIZE);
- getVal_tmp[2] = malloc(CB_BUF_SIZE);
- getVal_tmp[3] = malloc(CB_BUF_SIZE);
getFunc_gftmp[0] = malloc(CB_BUF_SIZE);
getFunc_gftmp[1] = malloc(CB_BUF_SIZE);
bfnbuf = malloc(CB_BUF_SIZE);
@@ -2926,8 +2975,6 @@ static inline void initBaseMem() {
static inline void freeBaseMem() {
nfree(getVal_tmp[0]);
nfree(getVal_tmp[1]);
- nfree(getVal_tmp[2]);
- nfree(getVal_tmp[3]);
nfree(getFunc_gftmp[0]);
nfree(getFunc_gftmp[1]);
nfree(bfnbuf);
@@ -2938,11 +2985,10 @@ static inline void freeBaseMem() {
nfree(getVarBuf);
}
-static inline void printError(int error) {
+static inline void printError(int error, char* arg0, char* cmd) {
getCurPos();
if (curx != 1) putchar('\n');
- if (inProg) {printf("Error %d on line %d of '%s':\n%s\n", error, progLine, basefilename(progfnstr), cmd);}
- else {printf("Error %d: ", error);}
+ printf("Error %d: ", error);
switch (error) {
default:;
fputs("Unknown", stdout);
@@ -3058,6 +3104,21 @@ static inline void printError(int error) {
case 36:;
printf("Extension already loaded: '%s'", errstr);
break;
+ case 37:;
+ printf("Cannot find subfunction: '%s'", errstr);
+ break;
+ case 38:;
+ printf("Invalid subfunction name: '%s'", errstr);
+ break;
+ case 39:;
+ printf("Subfunction already exists: '%s'", errstr);
+ break;
+ case 40:;
+ fputs("Subfunctions cannot be nested", stdout);
+ break;
+ case 41:;
+ fputs("ENDSUB with no SUB", stdout);
+ break;
case 125:;
printf("Function only valid in program: '%s'", errstr);
break;
@@ -3068,16 +3129,140 @@ static inline void printError(int error) {
printf("Not a function: '%s'", errstr);
break;
case 253:;
- printf("Command only valid in program: '%s'", arg[0]);
+ printf("Command only valid in program: '%s'", arg0);
break;
case 254:;
- printf("Command not valid in program: '%s'", arg[0]);
+ printf("Command not valid in program: '%s'", arg0);
break;
case 255:;
- printf("Not a command: '%s'", arg[0]);
+ printf("Not a command: '%s'", arg0);
break;
}
putchar('\n');
+ if (inProg) {printf("On line %d of '%s':\n%s\n", progLine, basefilename(progfnstr), cmd);}
+}
+
+int runcmd(char* cmd) {
+ if (cmd[0] == 0 || cmdint) return 0;
+ cerr = 0;
+ char** arg = NULL;
+ uint8_t* argt = NULL;
+ int32_t* argl = NULL;
+ int argct = 0;
+ bool lgc = runlogic(cmd);
+ if (lgc) goto cmderr;
+ if (cmd[0] == 0) return 0;
+ int32_t tmpi = 0;
+ while (cmd[tmpi] && cmd[tmpi] != ' ') {tmpi++;}
+ if (!cmd[tmpi]) tmpi = -1;
+ if (tmpi > -1) cmd[tmpi] = 0;
+ if (addsub > -1) {
+ if (tmpi > -1) cmd[tmpi] = 0;
+ if (!strcmp(cmd, "ENDSUB")) {
+ if (tmpi > -1) {
+ if (getArgCt(cmd + tmpi + 1)) {
+ subdata[addsub].inuse = false;
+ free(subdata[addsub].name);
+ free(subdata[addsub].data);
+ subdata[addsub].type = 0;
+ if (addsub == submaxct - 1) {
+ while (addsub >= 0 && !subdata[addsub].inuse) {submaxct--; addsub--;}
+ subdata = (cb_sub*)realloc(subdata, submaxct * sizeof(cb_sub));
+ }
+ addsub = -1;
+ cerr = 3;
+ goto cmderr;
+ }
+ }
+ subdata[addsub].data = realloc(subdata[addsub].data, strlen(subdata[addsub].data) + 1);
+ addsub = -1;
+ }
+ if (tmpi > -1) cmd[tmpi] = ' ';
+ if (addsub < 0) return 0;
+ copyStrApnd(cmd, subdata[addsub].data);
+ strApndChar(subdata[addsub].data, '\n');
+ return 0;
+ }
+ chkCmdPtr = cmd;
+ if (!chkCmd(2, "LABEL", "LBL") && cmd[0] != '@') {
+ if (tmpi > -1) cmd[tmpi] = ' ';
+ if (dlstackp > ((progindex > -1) ? mindlstackp[progindex] : -1)) {if (dldcmd[dlstackp]) return 0;}
+ if (itstackp > ((progindex > -1) ? minitstackp[progindex] : -1)) {if (itdcmd[itstackp]) return 0;}
+ if (fnstackp > ((progindex > -1) ? minfnstackp[progindex] : -1)) {if (fndcmd[fnstackp]) return 0;}
+ }
+ if (tmpi > -1) cmd[tmpi] = ' ';
+ int32_t j = 0;
+ while (cmd[j] == ' ') {++j;}
+ int32_t h = j;
+ bool sccmd = false;
+ if (cmd[j] == '$' || cmd[j] == '@' || cmd[j] == '%' || cmd[j] == '>') {
+ int32_t tmpj = j + 1;
+ while (cmd[tmpj] == ' ') {++tmpj;}
+ if (cmd[tmpj] != '=') sccmd = true;
+ }
+ if (!sccmd) {
+ while (cmd[h] != ' ' && cmd[h] != '=' && cmd[h]) {++h;}
+ }
+ copyStrFrom(cmd, (cmd[h]) ? h + 1 : h, tmpbuf[0]);
+ if (!sccmd) {
+ int32_t tmph = h;
+ while (cmd[tmph] == ' ' && cmd[tmph]) {++tmph;}
+ if (cmd[tmph] == '=') {
+ strcpy(tmpbuf[1], "SET ");
+ cmd[tmph] = ',';
+ copyStrApnd(cmd, tmpbuf[1]);
+ copyStr(tmpbuf[1], cmd);
+ copyStr(tmpbuf[1], tmpbuf[0]);
+ tmpbuf[1][0] = 0;
+ h = 3;
+ j = 0;
+ }
+ }
+ argct = getArgCt(tmpbuf[0]);
+ arg = (char**)malloc((argct + 1) * sizeof(char*));
+ argt = (uint8_t*)malloc((argct + 1) * sizeof(uint8_t));
+ argl = (int32_t*)malloc((argct + 1) * sizeof(int32_t));
+ int32_t gptr = 0;
+ copyStrSnip(cmd, j, ((sccmd) ? h + 1 : h), tmpbuf[0]);
+ argl[0] = strlen(tmpbuf[0]);
+ arg[0] = malloc(argl[0] + 1);
+ copyStr(tmpbuf[0], arg[0]);
+ copyStrFrom(cmd, (h >= argl[0]) ? argl[0] : h + 1, tmpbuf[0]);
+ for (int i = 1; i <= argct; ++i) {
+ int32_t ngptr = getArgO(i - 1, tmpbuf[0], tmpbuf[1], gptr);
+ if (ngptr == -1) goto cmderr;
+ argl[i] = ngptr - gptr;
+ gptr = ngptr;
+ arg[i] = malloc(argl[i] + 1);
+ copyStr(tmpbuf[1], arg[i]);
+ arg[i][argl[i]] = 0;
+ }
+ if (argct == 1 && arg[1][0] == 0) {argct = 0;}
+ if (cerr) goto cmderr;
+ solvearg(arg, argt, argl, 0);
+ cerr = 255;
+ chkCmdPtr = arg[0];
+ #include "commands.c"
+ cmderr:;
+ if (!hideerror) {
+ if (cerr) {
+ err = 0;
+ if (runc || runfile) err = 1;
+ printError(cerr, (arg) ? arg[0] : defaultstr, cmd);
+ return cerr;
+ }
+ } else {
+ hideerror = false;
+ }
+ noerr:;
+ if (lgc) return cerr;
+ for (int i = 0; i <= argct; ++i) {
+ nfree(arg[i]);
+ }
+ nfree(arg);
+ nfree(argt);
+ nfree(argl);
+ return cerr;
}
int loadExt(char* path) {
@@ -3093,8 +3278,7 @@ int loadExt(char* path) {
if (!oextname | !cbext_init) {cerr = 34; goto loadfail;}
if (!oextname[0]) {cerr = 34; goto loadfail;}
int e = -1;
- char* extname = (char*)malloc(strlen(oextname) + 1);
- copyStr(oextname, extname);
+ char* extname = strdup(oextname);
upCase(extname);
for (register int i = 0; i < extmaxct; ++i) {
if (extdata[i].inuse && !strcmp(extname, extdata[i].name)) {
@@ -3115,6 +3299,10 @@ int loadExt(char* path) {
&txtattrib,
&curx, &cury,
startcmd, roptstr,
+ &progLine, &lockpl, &didloop,
+ &inProg, &chkinProg,
+ &cmdl, &cp, &concp,
+ cb_exec,
getCurPos,
gethome,
seterrstr,
@@ -3131,7 +3319,8 @@ int loadExt(char* path) {
getVal,
solvearg,
logictest,
- printError
+ printError,
+ runcmd
};
if (!cbext_init(extargs)) {cerr = 35; goto loadfail;}
if (e == -1) {
@@ -3180,46 +3369,3 @@ bool unloadExt(int e) {
}
return true;
}
-
-void runcmd() {
- if (cmd[0] == 0) return;
- cerr = 0;
- bool lgc = runlogic();
- if (lgc) goto cmderr;
- if (cmd[0] == 0) return;
- int32_t tmpi = 0;
- while (cmd[tmpi] && cmd[tmpi] != ' ') {tmpi++;}
- if (!cmd[tmpi]) tmpi = -1;
- if (tmpi > -1) cmd[tmpi] = 0;
- chkCmdPtr = cmd;
- if (!chkCmd(2, "LABEL", "LBL") && cmd[0] != '@') {
- if (tmpi > -1) cmd[tmpi] = ' ';
- if (dlstackp > ((progindex > -1) ? mindlstackp[progindex] : -1)) {if (dldcmd[dlstackp]) return;}
- if (itstackp > ((progindex > -1) ? minitstackp[progindex] : -1)) {if (itdcmd[itstackp]) return;}
- if (fnstackp > ((progindex > -1) ? minfnstackp[progindex] : -1)) {if (fndcmd[fnstackp]) return;}
- }
- if (tmpi > -1) cmd[tmpi] = ' ';
- mkargs();
- if (cerr) goto cmderr;
- solvearg(0);
- cerr = 255;
- chkCmdPtr = arg[0];
- #include "commands.c"
- cmderr:;
- if (cerr) {
- err = 0;
- if (runc || runfile) err = 1;
- printError(cerr);
- cp = -1;
- concp = -1;
- chkinProg = inProg = false;
- }
- noerr:;
- if (lgc) return;
- for (int i = 0; i <= argct; ++i) {
- nfree(arg[i]);
- }
- argct = 0;
- return;
-}
-
diff --git a/clibasic.h b/clibasic.h
index d96f224..c8846f0 100644
--- a/clibasic.h
+++ b/clibasic.h
@@ -66,17 +66,17 @@ typedef struct {
uint8_t type; // type of the variable, 1 = string, 2 = number
int32_t size; // max index of variable, -1 = normal variable, >= 0 = array, to get the size of the array, add 1
char** data; // array of strings containing the value(s)
-} cb_var;
+} __attribute__((aligned(sizeof(void*)))) cb_var;
typedef struct {
FILE* fptr; // pointer to FILE* struct to read from and write to the file
int32_t size; // file size at open
-} cb_file;
+} __attribute__((aligned(sizeof(void*)))) cb_file;
typedef struct {
int cerr; // error to return
int ftype; // type of the function, 1 = string, 2 = number
-} cb_funcret;
+} __attribute__((aligned(sizeof(void*)))) cb_funcret;
typedef struct {
bool bold; // bold text attribute
@@ -98,54 +98,64 @@ typedef struct {
uint8_t bgc; // 8-bit/standard bgc text attribute
uint32_t truefgc; // 24-bit/truecolor fgc text attribute
uint32_t truebgc; // 24-bit/truecolor bgc text attribute
-} cb_txt;
+} __attribute__((aligned(sizeof(void*)))) cb_txt;
typedef struct {
- char* VER; // CLIBASIC version
- char* BVER; // bits ("64"/"32"/"?")
- char* OSVER; // OS name ("Linux", "Windows", ...)
- int* cerr; // pointer to the variable storing the error number
- int* retval; // pointer to the variable read by the CLIBASIC function _RET()
- int* fileerror; // pointer to the variable read by the CLIBASIC function _FILEERROR()
- int* varmaxct; // pointer to the amount of variable spots allocated
- cb_var* vardata; // pointer to the variable spots
- int* filemaxct; // pointer to the amount of file spots allocated
- cb_file* filedata; // pointer to the file spots
- char** chkCmdPtr; // pointer to a pointer of the char array to be compared by chkCmd()
- cb_txt* txtattrib; // pointer to the struct that stores text attributes
- int* curx; // pointer to the text cursor x position
- int* cury; // pointer to the text cursor y position
- char* startcmd; // full path to the executable that was used to start CLIBASIC
- char* roptstr; // option string to pass when starting a new CLIBASIC executable
- void (*getCurPos)(void); // update the text cursor position
- char* (*gethome)(void); // get the user's home directory
- void (*seterrstr)(char*); // set the error string some errors require
- char* (*basefilename)(char*); // gets the file name off of a file path
- char* (*pathfilename)(char*); // gets the path name off of a file path
- int (*openFile)(char*, char*); // opens a file in a new file spot and returns the position
- bool (*closeFile)(int); // closes a file spot or all if supplied with -1 and returns true if successful, false otherwise
- bool (*cbrm)(char*); // removes a file or directory and returns true if successful, false otherwise
- uint64_t (*usTime)(void); // returns the time in nanoseconds
- uint64_t (*timer)(void); // returns the timer ticks in nanoseconds
- void (*resetTimer)(void); // resets the timer
- void (*cb_wait)(uint64_t); // waits for a certain amount of nanoseconds
- void (*updateTxtAttrib)(void); // reads the text attribute struct and applies the changes
- double (*randNum)(double, double); // returns a random double from within a range
- bool (*chkCmd)(int, ...); // compares chkCmdPtr to strings supplied after the string count and returns true if a match is found, false otherwise
- bool (*isSpChar)(char); // checks if a char is a special character ('+', '-', '*', '\', & '^')
- bool (*isExSpChar)(char); // checks if a char is a special character but with more chars ('=', '>', '<', & ',')
- bool (*isValidVarChar)(char); // checks if a char is valid in a variable name
- bool (*isValidHexChar)(char); // checks if a char is valid in a hexadecimal number (0-F)
- int (*getArgCt)(char*); // returns the argument count of raw input
- int (*getArg)(int, char*, char*); // writes the argument number in argument 1 of raw input from argument 2 into argument 3 and returns the length
- int (*getArgO)(int, char*, char*, int32_t); // writes the argument number in argument 1 of raw input from argument 2 into argument 3 and returns the end, pass this to argument 4 on next call
- void (*getStr)(char*, char*); // returns a string after evaluating any backslash escape codes
- uint8_t (*getType)(char*); // gets the type of raw input ("\"test\"" returns 1 (string), "0" returns 2 (number), and "TEST" returns 255 (variable))
- uint8_t (*getVar)(char*, char*); // puts the value of the variable specified by argument 1 in argument 2 and returns the type (1 = string, 2 = number)
- bool (*setVar)(char*, char*, uint8_t, int32_t); // sets the variable specified by argument 1 to the value specified by argument 2 and sets the type to argument 3 and size to argument 4
- bool (*delVar)(char*); // deletes a variable
- uint8_t (*getVal)(char*, char*); // solves raw input in argument 1, writes the value into argument 2, and returns the type (1 = string, 2 = number, 255 = blank) or 0 on failure
- bool (*solvearg)(int); // solves an argument for commands as some commands may want to read from raw input
- uint8_t (*logictest)(char*); // takes raw input, tests it, and returns -1 on failure, 0 if false, and 1 if true
- void (*printError)(int); // prints a built-in error string
-} cb_extargs;
+ char* VER; // CLIBASIC version
+ char* BVER; // bits ("64"/"32"/"?")
+ char* OSVER; // OS name ("Linux", "Windows", ...)
+ int* cerr; // pointer to the variable storing the error number
+ int* retval; // pointer to the variable read by the CLIBASIC function _RET()
+ int* fileerror; // pointer to the variable read by the CLIBASIC function _FILEERROR()
+ int* varmaxct; // pointer to the amount of variable spots allocated
+ cb_var* vardata; // pointer to the variable spots
+ int* filemaxct; // pointer to the amount of file spots allocated
+ cb_file* filedata; // pointer to the file spots
+ char** chkCmdPtr; // pointer to a pointer of the char array to be compared by chkCmd()
+ cb_txt* txtattrib; // pointer to the struct that stores text attributes
+ int* curx; // pointer to the text cursor x position
+ int* cury; // pointer to the text cursor y position
+ char* startcmd; // full path to the executable that was used to start CLIBASIC
+ char* roptstr; // option string to pass when starting a new CLIBASIC executable
+ int* progLine; // pointer to the current line in the program
+ bool* lockpl; // pointer to a flag to temporarily stop the program line from being incremented
+ bool* didloop; // pointer to a flag indicating that you did some magic with the program position counter
+ bool* inProg; // pointer to a flag indicating if a program is being interpreted
+ bool* chkinProg; // pointer to a flag indicating if you loaded a program
+ int32_t* cmdl; // pointer length of the length of the command string
+ int32_t* cp; // pointer length of the program data position
+ int32_t* concp; // pointer length of the console program data position
+ int16_t (*cb_exec)(char**); // pointer to a function which will start another process using a NULL-terminated string (char*) array
+ void (*getCurPos)(void); // update the text cursor position
+ char* (*gethome)(void); // get the user's home directory
+ void (*seterrstr)(char*); // set the error string some errors require
+ char* (*basefilename)(char*); // gets the file name off of a file path
+ char* (*pathfilename)(char*); // gets the path name off of a file path
+ int (*openFile)(char*, char*); // opens a file in a new file spot and returns the position
+ bool (*closeFile)(int); // closes a file spot or all if supplied with -1 and returns true if successful, false otherwise
+ bool (*cbrm)(char*); // removes a file or directory and returns true if successful, false otherwise
+ uint64_t (*usTime)(void); // returns the time in nanoseconds
+ uint64_t (*timer)(void); // returns the timer ticks in nanoseconds
+ void (*resetTimer)(void); // resets the timer
+ void (*cb_wait)(uint64_t); // waits for a certain amount of nanoseconds
+ void (*updateTxtAttrib)(void); // reads the text attribute struct and applies the changes
+ long double (*randNum)(long double, long double); // returns a random double from within a range
+ bool (*chkCmd)(int, ...); // compares chkCmdPtr to strings supplied after the string count and returns true if a match is found, false otherwise
+ bool (*isSpChar)(char); // checks if a char is a special character ('+', '-', '*', '\', & '^')
+ bool (*isExSpChar)(char); // checks if a char is a special character but with more chars ('=', '>', '<', & ',')
+ bool (*isValidVarChar)(char); // checks if a char is valid in a variable name
+ bool (*isValidHexChar)(char); // checks if a char is valid in a hexadecimal number (0-F)
+ int (*getArgCt)(char*); // returns the argument count of raw input
+ int (*getArg)(int, char*, char*); // writes the argument number in argument 1 of raw input from argument 2 into argument 3 and returns the length
+ int (*getArgO)(int, char*, char*, int32_t); // writes the argument number in argument 1 of raw input from argument 2 into argument 3 and returns the end, pass this to argument 4 on next call
+ void (*getStr)(char*, char*); // returns a string after evaluating any backslash escape codes
+ uint8_t (*getType)(char*); // gets the type of raw input ("\"test\"" returns 1 (string), "0" returns 2 (number), and "TEST" returns 255 (variable))
+ uint8_t (*getVar)(char*, char*); // puts the value of the variable specified by argument 1 in argument 2 and returns the type (1 = string, 2 = number)
+ bool (*setVar)(char*, char*, uint8_t, int32_t); // sets the variable specified by argument 1 to the value specified by argument 2 and sets the type to argument 3 and size to argument 4
+ bool (*delVar)(char*); // deletes a variable
+ uint8_t (*getVal)(char*, char*); // solves raw input in argument 1, writes the value into argument 2, and returns the type (1 = string, 2 = number, 255 = blank) or 0 on failure
+ bool (*solvearg)(char**, uint8_t*, int32_t*, int); // solves an argument for commands as some commands may want to read from raw input
+ uint8_t (*logictest)(char*); // takes raw input, tests it, and returns -1 on failure, 0 if false, and 1 if true
+ void (*printError)(int, char*, char*); // prints a built-in error string
+ int (*runcmd)(char*); // parses and runs a single command and returns an error (0 for none)
+} __attribute__((aligned(sizeof(void*)))) cb_extargs;
diff --git a/commands.c b/commands.c
index 366446c..dfeb4be 100644
--- a/commands.c
+++ b/commands.c
@@ -13,35 +13,43 @@ if (chkCmdPtr[0] == '_') goto _cmd;
if (chkCmd(2, "EXIT", "QUIT")) {
if (argct > 1) {cerr = 3; goto cmderr;}
cerr = 0;
- err = 0;
- if (argct == 1) {
- if (!solvearg(1)) goto cmderr;
- err = atoi(arg[1]);
- if (runfile) {
- retval = err;
+ if (subinfo.insub && subinfo.type > 0) {
+ if (argct == 1) {
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ if (argt[1] != subinfo.type) {cerr = 2; goto cmderr;}
+ funcret = strdup(arg[1]);
}
} else {
err = 0;
+ if (argct) {
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ err = atoi(arg[1]);
+ if (runfile) {
+ retval = err;
+ }
+ } else {
+ err = 0;
+ }
+ if (inProg) {
+ if (progindex > 0) unloadProg();
+ else cmdint = true;
+ retval = err;
+ } else {
+ cleanExit();
+ }
}
- if (inProg) {
- if (progindex > 0) unloadProg();
- else cmdint = true;
- retval = err;
- } else {
- cleanExit();
- }
- goto cmderr;
+ goto noerr;
}
-if (chkCmd(1, "PUT")) {
+if (chkCmd(2, "PUT", ">")) {
cerr = 0;
- for (int i = 1; i <= argct; i++) {if (!solvearg(i)) {goto cmderr;} fputs(arg[i], stdout);}
+ for (int i = 1; i <= argct; i++) {if (!solvearg(arg, argt, argl, i)) {goto cmderr;} fputs(arg[i], stdout);}
fflush(stdout);
goto noerr;
}
if (chkCmd(2, "SET", "LET")) {
if (argct != 2) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (!arg[1][0] || !argt[2]) {cerr = 1; goto cmderr;}
if (!setVar(arg[1], arg[2], argt[2], -1)) goto cmderr;
goto noerr;
@@ -49,8 +57,8 @@ if (chkCmd(2, "SET", "LET")) {
if (chkCmd(1, "DIM")) {
if (argct < 2 || argct > 3) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(2)) goto cmderr;
- if (argct == 3 && !solvearg(3)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
+ if (argct == 3 && !solvearg(arg, argt, argl, 3)) goto cmderr;
if (argt[2] != 2) {cerr = 2; goto cmderr;}
int32_t asize = atoi(arg[2]);
if (asize < 0) {cerr = 16; goto cmderr;}
@@ -60,7 +68,7 @@ if (chkCmd(1, "DIM")) {
val = arg[3];
type = argt[3];
} else {
- val = ((arg[1][argl[1] - 1] == '$') ? "" : "0");
+ val = (arg[1][argl[1] - 1] == '$') ? defaultstr : defaultnum;
type = 2 - (arg[1][argl[1] - 1] == '$');
}
if (!setVar(arg[1], val, type, asize)) goto cmderr;
@@ -69,7 +77,7 @@ if (chkCmd(1, "DIM")) {
if (chkCmd(1, "REDIM")) {
if (argct < 2) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[2] != 2) {cerr = 2; goto cmderr;}
int v = -1;
for (register int i = 0; i < varmaxct; ++i) {
@@ -167,7 +175,7 @@ if (chkCmd(3, "@", "LABEL", "LBL")) {
upCase(arg[1]);
int i = -1;
for (int j = 0; j < gotomaxct; ++j) {
- if (!gotodata[j].used) {i = j; break;}
+ if (!gotodata[j].inuse) {i = j; break;}
else if (!strcmp(gotodata[j].name, arg[1])) {
if (gotodata[j].cp == cmdpos) {goto noerr;}
cerr = 28; goto cmderr;
@@ -178,17 +186,13 @@ if (chkCmd(3, "@", "LABEL", "LBL")) {
++gotomaxct;
gotodata = realloc(gotodata, gotomaxct * sizeof(cb_goto));
}
- gotodata[i].name = malloc(strlen(arg[1]) + 1);
- copyStr(arg[1], gotodata[i].name);
+ gotodata[i].name = strdup(arg[1]);
gotodata[i].cp = cmdpos;
gotodata[i].pl = progLine;
- gotodata[i].used = true;
+ gotodata[i].inuse = true;
gotodata[i].dlsp = dlstackp;
gotodata[i].fnsp = fnstackp;
gotodata[i].itsp = itstackp;
- #ifdef _WIN32
- updatechars();
- #endif
goto noerr;
}
if (chkCmd(3, "%", "GOTO", "GO")) {
@@ -197,7 +201,7 @@ if (chkCmd(3, "%", "GOTO", "GO")) {
upCase(arg[1]);
int i = -1;
for (int j = 0; j < gotomaxct; ++j) {
- if (gotodata[j].used) {
+ if (gotodata[j].inuse) {
if (!strcmp(gotodata[j].name, arg[1])) {i = j;}
}
}
@@ -212,9 +216,9 @@ if (chkCmd(3, "%", "GOTO", "GO")) {
dlstackp = gotodata[i].dlsp;
fnstackp = gotodata[i].fnsp;
itstackp = gotodata[i].itsp;
- gotodata[i].used = false;
+ gotodata[i].inuse = false;
bool r = false;
- while (gotomaxct > 0 && !gotodata[gotomaxct - 1].used) {--gotomaxct; r = true;}
+ while (gotomaxct > 0 && !gotodata[gotomaxct - 1].inuse) {--gotomaxct; r = true;}
if (r) gotodata = realloc(gotodata, gotomaxct * sizeof(cb_goto));
didloop = true;
lockpl = true;
@@ -227,7 +231,7 @@ if (chkCmd(1, "GOSUB")) {
upCase(arg[1]);
int i = -1;
for (int j = 0; j < gotomaxct; ++j) {
- if (gotodata[j].used) {
+ if (gotodata[j].inuse) {
if (!strcmp(gotodata[j].name, arg[1])) {i = j;}
}
}
@@ -246,9 +250,9 @@ if (chkCmd(1, "GOSUB")) {
concp = gotodata[i].cp;
}
progLine = gotodata[i].pl;
- gotodata[i].used = false;
+ gotodata[i].inuse = false;
bool r = false;
- while (gotomaxct > 0 && !gotodata[gotomaxct - 1].used) {--gotomaxct; r = true;}
+ while (gotomaxct > 0 && !gotodata[gotomaxct - 1].inuse) {--gotomaxct; r = true;}
if (r) gotodata = realloc(gotodata, gotomaxct * sizeof(cb_goto));
didloop = true;
lockpl = true;
@@ -273,6 +277,39 @@ if (chkCmd(1, "RETURN")) {
lockpl = true;
goto noerr;
}
+if (chkCmd(2, "DELLABEL", "DELLBL")) {
+ if (argct < 1) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ for (int i = 1; i <= argct; ++i) {
+ upCase(arg[i]);
+ int s = -1;
+ for (int j = 0; j < gotomaxct; ++j) {
+ if (gotodata[j].inuse && !strcmp(gotodata[j].name, arg[i])) {
+ s = j;
+ }
+ }
+ if (s != -1) {
+ gotodata[s].inuse = false;
+ free(gotodata[s].name);
+ if (s == submaxct - 1) {
+ while (s >= 0 && !gotodata[s].inuse) {gotodata--; s--;}
+ gotodata = (cb_goto*)realloc(gotodata, gotomaxct * sizeof(cb_goto));
+ }
+ }
+ }
+ goto noerr;
+}
+if (chkCmd(2, "DEFRAGLBLS", "DEFRAGLABELS")) {
+ cerr = 0;
+ if (argct > 0) {cerr = 3; goto cmderr;}
+ int so = 0;
+ for (register int i = 0; i < submaxct;) {
+ if (!gotodata[i].inuse) {++so; --gotomaxct;}
+ else {++i;}
+ if (so) {gotodata[i] = gotodata[i + so];}
+ }
+ goto noerr;
+}
if (chkCmd(2, "CONTINUE", "BREAK")) {
if (argct) {cerr = 3; goto cmderr;}
cerr = 0;
@@ -287,10 +324,110 @@ if (chkCmd(2, "CONTINUE", "BREAK")) {
brkinfo.type = 1 + !strcmp(arg[0], "BREAK");
goto noerr;
}
+if (chkCmd(3, "SUB", "FUNC", "FUNC$")) {
+ if (subinfo.insub) {cerr = 40; goto cmderr;}
+ if (argct != 1) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ upCase(arg[1]);
+ int i = -1;
+ for (int j = 0; j < submaxct; ++j) {
+ if (!subdata[j].inuse) {i = j; break;}
+ else if (!strcmp(subdata[j].name, arg[1])) {
+ seterrstr(arg[1]); cerr = 39; goto cmderr;
+ }
+ }
+ if (i == -1) {
+ i = submaxct;
+ ++submaxct;
+ subdata = realloc(subdata, submaxct * sizeof(cb_sub));
+ }
+ subdata[i].inuse = true;
+ subdata[i].name = strdup(arg[1]);
+ subdata[i].data = malloc(CB_BUF_SIZE);
+ subdata[i].data[0] = 0;
+ subdata[i].type = (arg[0][0] == 'S') ? 0 : (arg[0][argl[0] - 1] == '$') ? 1 : 2;
+ addsub = i;
+ goto noerr;
+}
+if (chkCmd(1, "ENDSUB")) {
+ if (argct) {cerr = 3; goto cmderr;}
+ cerr = 41;
+ goto cmderr;
+}
+if (chkCmd(1, "CALLSUB")) {
+ if (argct < 1) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ newprogargc = argct;
+ newprogargs = (char**)malloc((argct + 1) * sizeof(char*));
+ for (int i = 1; i < newprogargc; ++i) {
+ newprogargs[i] = NULL;
+ }
+ for (int i = 2; i <= argct; ++i) {
+ if (!solvearg(arg, argt, argl, i)) {
+ for (int j = i - 1; j > 0; --j) {
+ free(newprogargs[j]);
+ }
+ free(newprogargs);
+ goto cmderr;
+ }
+ newprogargs[i - 1] = strdup(arg[i]);
+ }
+ if (!loadSub(arg[1], false, NULL)) goto callsub_err;
+ goto callsub_noerr;
+ callsub_err:;
+ for (int i = 1; i < newprogargc; ++i) {
+ nfree(newprogargs[i]);
+ }
+ nfree(newprogargs);
+ newprogargc = 0;
+ goto cmderr;
+ callsub_noerr:;
+ subinfo.insub = true;
+ subinfo.type = 0;
+ chkinProg = true;
+ cp = 0;
+ didloop = true;
+ goto noerr;
+}
+if (chkCmd(1, "DELSUB")) {
+ if (argct < 1) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ for (int i = 1; i <= argct; ++i) {
+ upCase(arg[i]);
+ int s = -1;
+ for (int j = 0; j < submaxct; ++j) {
+ if (subdata[j].inuse && !strcmp(subdata[j].name, arg[i])) {
+ s = j;
+ }
+ }
+ if (s != -1) {
+ subdata[s].inuse = false;
+ free(subdata[s].name);
+ free(subdata[s].data);
+ subdata[s].type = 0;
+ if (s == submaxct - 1) {
+ while (s >= 0 && !subdata[s].inuse) {submaxct--; s--;}
+ subdata = (cb_sub*)realloc(subdata, submaxct * sizeof(cb_sub));
+ }
+ }
+ }
+ goto noerr;
+}
+if (chkCmd(1, "DEFRAGSUBS")) {
+ cerr = 0;
+ if (argct > 0) {cerr = 3; goto cmderr;}
+ int so = 0;
+ for (register int i = 0; i < submaxct;) {
+ if (!subdata[i].inuse) {++so; --submaxct;}
+ else {++i;}
+ if (so) {subdata[i] = subdata[i + so];}
+ }
+ goto noerr;
+}
if (chkCmd(1, "COLOR")) {
if (argct > 2 || argct < 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
int32_t tmp = 0;
if (argt[1] == 0) {} else
if (argt[1] != 2) {cerr = 2; goto cmderr;}
@@ -313,7 +450,7 @@ if (chkCmd(1, "COLOR")) {
#endif
}
if (argct > 1) {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[2] == 0) {} else
if (argt[2] != 2) {cerr = 2; goto cmderr;}
else {
@@ -342,7 +479,10 @@ if (chkCmd(1, "LOCATE")) {
if (argct > 2 || argct < 1) {cerr = 3; goto cmderr;}
cerr = 0;
int tmp = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ #ifdef _WIN_NO_VT
+ getCurPos();
+ #endif
if (argt[1] == 0) {}
else if (argt[1] != 2) {cerr = 2; goto cmderr;}
else {
@@ -357,7 +497,7 @@ if (chkCmd(1, "LOCATE")) {
}
}
if (argct > 1) {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[1] == 0 && argt[2] == 0) {cerr = 3; goto cmderr;}
else if (argt[2] == 0) {}
else if (argt[2] != 2) {cerr = 2; goto cmderr;}
@@ -388,8 +528,8 @@ if (chkCmd(1, "RLOCATE")) {
if (argct > 2 || argct < 1) {cerr = 3; goto cmderr;}
cerr = 0;
int tmp = 0;
- if (!solvearg(1)) goto cmderr;
- #ifndef _WIN_NO_VT
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ #ifdef _WIN_NO_VT
getCurPos();
#endif
if (argt[1] == 0) {}
@@ -413,7 +553,7 @@ if (chkCmd(1, "RLOCATE")) {
}
}
if (argct > 1) {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[1] == 0 && argt[2] == 0) {cerr = 3; goto cmderr;}
else if (argt[2] == 0) {}
else if (argt[2] != 2) {cerr = 2; goto cmderr;}
@@ -444,36 +584,83 @@ if (chkCmd(1, "RLOCATE")) {
goto noerr;
}
if (chkCmd(1, "CLS")) {
- if (argct > 1) {cerr = 3; goto cmderr;}
+ if (argct > 2) {cerr = 3; goto cmderr;}
cerr = 0;
uint8_t tbgc = txtattrib.bgc;
- #ifndef _WIN_NO_VT
- uint32_t ttbgc = txtattrib.truebgc;
- #endif
+ int32_t ttbgc = txtattrib.truebgc;
+ int line = 0;
if (argct) {
- if (!solvearg(1)) goto cmderr;
- if (argt[1] != 2) {cerr = 2; goto cmderr;}
- #ifndef _WIN_NO_VT
- if (txtattrib.truecolor) {
- ttbgc = (uint32_t)atoi(arg[1]);
- } else {
- tbgc = (uint8_t)atoi(arg[1]);
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ if (argct == 2) {
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
+ if (argt[2]) {
+ if (argt[2] != 2) {cerr = 2; goto cmderr;}
+ line = atoi(arg[2]);
+ if (line < 1) {cerr = 16; goto cmderr;}
+ } else {
+ #ifdef _WIN_NO_VT
+ getCurPos();
+ line = cury;
+ #else
+ line = -1;
+ #endif
+ }
+ }
+ if (argt[1]) {
+ if (argt[1] != 2) {cerr = 2; goto cmderr;}
+ if (txtattrib.truecolor) {
+ ttbgc = atoi(arg[1]);
+ if (ttbgc < 0 || ttbgc > 0xFFFFFF) {cerr = 16; goto cmderr;}
+ } else {
+ tbgc = atoi(arg[1]);
+ if (ttbgc < 0 || ttbgc > 255) {cerr = 16; goto cmderr;}
+ }
}
- #else
- tbgc = (uint8_t)atoi(arg[1]);
- #endif
}
#ifndef _WIN_NO_VT
- if (esc && argct) {
- if (txtattrib.truecolor) printf("\e[48;2;%u;%u;%um", (uint8_t)(ttbgc >> 16), (uint8_t)(ttbgc >> 8), (uint8_t)ttbgc);
- else printf("\e[48;5;%um", tbgc);
+ if (esc) {
+ if (argct && argt[1]) {
+ if (txtattrib.truecolor) printf("\e[48;2;%u;%u;%um", (uint8_t)(ttbgc >> 16), (uint8_t)(ttbgc >> 8), (uint8_t)ttbgc);
+ else printf("\e[48;5;%um", tbgc);
+ }
+ if (line > 0) {
+ printf("\e[s\e[%d;0H\e[2K\e[u", line);
+ } else {
+ if (line == -1) fputs("\e[2K", stdout);
+ else fputs("\e[H\e[2J\e[3J", stdout);
+ }
+ updateTxtAttrib();
+ fflush(stdout);
}
- if (esc) fputs("\e[H\e[2J\e[3J", stdout);
- updateTxtAttrib();
- fflush(stdout);
#else
- SetConsoleTextAttribute(hConsole, (txtattrib.fgc % 16) + (tbgc % 16) * 16);
- system("cls");
+ if (argct && argt[1]) {
+ if (txtattrib.truecolor) {
+ tbgc = ((((ttbgc >> 16) & 0xFF) > 85) << 2 | (((ttbgc >> 8) & 0xFF) > 85) << 1 | ((ttbgc & 0xFF) > 85))\
+ | (((ttbgc >> 16) & 0xFF) > 170 || ((ttbgc >> 8) & 0xFF) > 170 || (ttbgc & 0xFF) > 170) << 3;
+ } else {
+ uint8_t b1 = 0, b2 = 0;
+ uint8_t tmpbgc = tbgc;
+ b1 = tbgc & 1; b2 = (tbgc >> 2) & 1; tmpbgc = (b1 ^ b2);
+ tmpbgc = (tmpbgc) | (tmpbgc << 2); tmpbgc = tbgc ^ tmpbgc;
+ tbgc = tmpbgc;
+ }
+ SetConsoleTextAttribute(hConsole, (txtattrib.fgc % 16) + (tbgc % 16) * 16);
+ }
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ DWORD count;
+ GetConsoleScreenBufferInfo(hConsole, &csbi);
+ DWORD cellCount;
+ bool l = false;
+ if (line > 0) {
+ cellCount = csbi.dwSize.X;
+ --line;
+ l = true;
+ } else {
+ cellCount = csbi.dwSize.X * csbi.dwSize.Y;
+ }
+ FillConsoleOutputCharacter(hConsole, (TCHAR)' ', cellCount, (COORD){0, line}, &count);
+ FillConsoleOutputAttribute(hConsole, csbi.wAttributes, cellCount, (COORD){0, line}, &count);
+ if (!l) SetConsoleCursorPosition(hConsole, (COORD){0, line});
updateTxtAttrib();
#endif
goto noerr;
@@ -481,7 +668,7 @@ if (chkCmd(1, "CLS")) {
if (chkCmd(1, "WAITUS")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
if (arg[1][0] == '-') {cerr = 16; goto cmderr;}
uint64_t d;
@@ -492,22 +679,22 @@ if (chkCmd(1, "WAITUS")) {
if (chkCmd(1, "WAITMS")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
if (arg[1][0] == '-') {cerr = 16; goto cmderr;}
- double d;
- sscanf(arg[1], "%lf", &d);
+ long double d;
+ sscanf(arg[1], "%Lf", &d);
cb_wait(d * 1000);
goto noerr;
}
if (chkCmd(1, "WAIT")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
if (arg[1][0] == '-') {cerr = 16; goto cmderr;}
- double d;
- sscanf(arg[1], "%lf", &d);
+ long double d;
+ sscanf(arg[1], "%Lf", &d);
cb_wait(d * 1000000);
goto noerr;
}
@@ -520,10 +707,10 @@ if (chkCmd(1, "RESETTIMER")) {
if (chkCmd(2, "SRAND", "SRND")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
- double rs;
- sscanf(arg[1], "%lf", &rs);
+ long double rs;
+ sscanf(arg[1], "%Lf", &rs);
srand(rs);
goto noerr;
}
@@ -533,7 +720,7 @@ if (chkCmd(2, "CALL", "CALLA")) {
bool execa = false;
char** tmparg = NULL;
int tmpargct = 0;
- if (!strcmp(arg[0], "CALLA")) {
+ if (arg[0][4] == 'A') {
if (argct != 1) {cerr = 3; goto cmderr;}
execa = true;
int v = -1;
@@ -547,14 +734,14 @@ if (chkCmd(2, "CALL", "CALLA")) {
arg = vardata[v].data - 1;
argct = vardata[v].size + 1;
} else {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
}
newprogargc = argct;
newprogargs = (char**)malloc((argct + 1) * sizeof(char*));
for (int i = 2; i <= argct; ++i) {
if (!execa) {
- if (!solvearg(i)) {
+ if (!solvearg(arg, argt, argl, i)) {
for (int j = i - 1; j > 0; --j) {
free(newprogargs[j]);
}
@@ -565,8 +752,6 @@ if (chkCmd(2, "CALL", "CALLA")) {
newprogargs[i - 1] = malloc(argl[i] + 1);
copyStr(arg[i], newprogargs[i - 1]);
}
- inprompt = !runfile;
- setsig(SIGINT, cleanExit);
if (!loadProg(arg[1])) goto cmderr;
chkinProg = true;
cp = 0;
@@ -583,7 +768,7 @@ if (chkCmd(2, "RUN", "RUNA")) {
bool execa = false;
char** tmparg = NULL;
int tmpargct = 0;
- if (!strcmp(arg[0], "RUNA")) {
+ if (arg[0][3] == 'A') {
if (argct != 1) {cerr = 3; goto cmderr;}
execa = true;
int v = -1;
@@ -597,10 +782,9 @@ if (chkCmd(2, "RUN", "RUNA")) {
arg = vardata[v].data - 1;
argct = vardata[v].size + 1;
} else {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
}
- #ifndef _WIN32
char** runargs = (char**)malloc((argct + 3) * sizeof(char*));
runargs[0] = startcmd;
runargs[1] = roptstr;
@@ -608,42 +792,13 @@ if (chkCmd(2, "RUN", "RUNA")) {
argct += 2;
int argno = 3;
for (; argno < argct; argno++) {
- if (!execa) if (!solvearg(argno - 1)) {free(runargs); goto cmderr;}
+ if (!execa) if (!solvearg(arg, argt, argl, argno - 1)) {free(runargs); goto cmderr;}
runargs[argno] = arg[argno - 1];
}
- argct -= 2;
runargs[argno] = NULL;
- pid_t pid = fork();
- if (pid < 0) cerr = -1;
- else if (pid == 0) {
- execvp(startcmd, runargs);
- exit(0);
- }
- else if (pid > 0) {
- while (wait(&retval) != pid) {}
- retval = WEXITSTATUS(retval);
- }
+ argct -= 2;
+ retval = cb_exec(runargs);
free(runargs);
- #else
- char* tmpcmd = malloc(CB_BUF_SIZE);
- tmpcmd[0] = 0;
- bool nq;
- if ((nq = winArgNeedsQuotes(startcmd))) copyStrApnd(" \"", tmpcmd);
- copyStrApnd(startcmd, tmpcmd);
- if (nq) strApndChar(tmpcmd, '"');
- copyStrApnd(" -x", tmpcmd);
- for (int argno = 1; argno <= argct; ++argno) {
- if (!execa) if (argno > 1) if (!solvearg(argno)) {free(tmpcmd); goto cmderr;}
- strApndChar(tmpcmd, ' ');
- bool nq = winArgNeedsQuotes(arg[argno]);
- if (nq) strApndChar(tmpcmd, '"');
- copyStrApnd(arg[argno], tmpcmd);
- if (nq) strApndChar(tmpcmd, '"');
- }
- int ret = system(tmpcmd);
- (void)ret;
- free(tmpcmd);
- #endif
if (execa) {
argct = tmpargct;
arg = tmparg;
@@ -654,7 +809,7 @@ if (chkCmd(2, "RUN", "RUNA")) {
if (chkCmd(2, "$", "SH")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
#ifndef _WIN_NO_VT
if (esc && sh_clearAttrib) fputs("\e[0m", stdout);
@@ -685,7 +840,7 @@ if (chkCmd(2, "EXEC", "EXECA")) {
bool execa = false;
char** tmparg = NULL;
int tmpargct = 0;
- if (!strcmp(arg[0], "EXECA")) {
+ if (arg[0][4] == 'A') {
if (argct != 1) {cerr = 3; goto cmderr;}
execa = true;
int v = -1;
@@ -699,7 +854,7 @@ if (chkCmd(2, "EXEC", "EXECA")) {
arg = vardata[v].data - 1;
argct = vardata[v].size + 1;
} else {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
}
#ifndef _WIN_NO_VT
@@ -708,12 +863,11 @@ if (chkCmd(2, "EXEC", "EXECA")) {
if (sh_clearAttrib) SetConsoleTextAttribute(hConsole, ocAttrib);
#endif
fflush(stdout);
- #ifndef _WIN32
char** runargs = (char**)malloc((argct + 1) * sizeof(char*));
runargs[0] = arg[1];
int argno = 1;
for (; argno < argct; ++argno) {
- if (!execa) if (!solvearg(argno + 1)) {free(runargs); goto cmderr;}
+ if (!execa) if (!solvearg(arg, argt, argl, argno + 1)) {free(runargs); goto cmderr;}
runargs[argno] = arg[argno + 1];
}
runargs[argno] = NULL;
@@ -725,53 +879,13 @@ if (chkCmd(2, "EXEC", "EXECA")) {
dup2(fd, 1);
dup2(fd, 2);
}
- pid_t pid = fork();
- if (pid < 0) cerr = -1;
- if (pid == 0) {
- execvp(runargs[0], runargs);
- exit(127);
- }
- else if (pid > 0) {
- while (wait(&retval) != pid) {}
- retval = ((retval >> 8) & 0xFF);
- }
- else if (sh_silent) {
+ retval = cb_exec(runargs);
+ if (sh_silent) {
dup2(stdout_dup, 1);
dup2(stderr_dup, 2);
}
getCurPos();
free(runargs);
- #else
- char* tmpcmd = malloc(CB_BUF_SIZE);
- tmpcmd[0] = 0;
- bool winecho = false;
- for (int argno = 1; argno <= argct; ++argno) {
- if (!execa) if (argno > 1) if (!solvearg(argno)) {free(tmpcmd); goto cmderr;};
- strApndChar(tmpcmd, ' ');
- bool nq = winArgNeedsQuotes(arg[argno]);
- if (argno == 1) {
- upCase(arg[argno]);
- winecho = !strcmp(arg[argno], "ECHO");
- }
- if (nq && !winecho) copyStrApnd(" \"", tmpcmd);
- copyStrApnd(arg[argno], tmpcmd);
- if (nq && !winecho) strApndChar(tmpcmd, '"');
- }
- int stdout_dup = 0, stderr_dup = 0;
- if (sh_silent) {
- stdout_dup = dup(1);
- stderr_dup = dup(2);
- int fd = open("NUL", _O_WRONLY | _O_CREAT);
- dup2(fd, 1);
- dup2(fd, 2);
- }
- retval = WEXITSTATUS(system(tmpcmd));
- if (sh_silent) {
- dup2(stdout_dup, 1);
- dup2(stderr_dup, 2);
- }
- free(tmpcmd);
- #endif
if (execa) {
argct = tmpargct;
arg = tmparg;
@@ -783,21 +897,21 @@ if (chkCmd(2, "EXEC", "EXECA")) {
if (chkCmd(1, "BELL")) {
cerr = 0;
int ct = 1;
- double d = 750;
+ long double d = 750;
if (argct > 2) {cerr = 3; goto cmderr;}
if (argct >= 1) {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] == 0) {cerr = 3; goto cmderr;}
if (argt[1] != 2) {cerr = 2; goto cmderr;}
ct = atoi(arg[1]);
if (ct < 1) {cerr = 16; goto cmderr;}
}
if (argct == 2) {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[2] == 0) {cerr = 3; goto cmderr;}
if (argt[2] != 2) {cerr = 2; goto cmderr;}
if (arg[2][0] == '-') {cerr = 16; goto cmderr;}
- sscanf(arg[2], "%lf", &d);
+ sscanf(arg[2], "%Lf", &d);
}
putchar('\a');
fflush(stdout);
@@ -814,7 +928,7 @@ if (chkCmd(1, "FILES")) {
if (argct > 1) {cerr = 3; goto cmderr;}
char* olddn = NULL;
if (argct) {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
int tmpret = isFile(arg[1]);
if (tmpret) {
@@ -873,7 +987,7 @@ if (chkCmd(1, "EXTENSIONS")) {
if (chkCmd(2, "CHDIR", "CD")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
if (chdir(arg[1])) {
seterrstr(arg[1]);
@@ -886,7 +1000,7 @@ if (chkCmd(1, "FCLOSE")) {
cerr = 0;
fileerror = 0;
if (argct != 1) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
if (argt[1] != 2) {cerr = 3; goto cmderr;}
if (!closeFile(atoi(arg[1]))) {cerr = 16; goto cmderr;}
goto noerr;
@@ -895,8 +1009,8 @@ if (chkCmd(1, "FWRITE")) {
cerr = 0;
fileerror = 0;
if (argct != 2) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
- if (!solvearg(2)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 2)) {goto cmderr;}
if (argt[1] != 2 || argt[2] != 1) {cerr = 2; goto cmderr;}
int fnum = atoi(arg[1]);
if (fnum < 0 || fnum >= filemaxct) {
@@ -913,8 +1027,8 @@ if (chkCmd(1, "FSEEK")) {
cerr = 0;
fileerror = 0;
if (argct != 2) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
- if (!solvearg(2)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 2)) {goto cmderr;}
if (argt[1] != 2 || argt[2] != 2) {cerr = 2; goto cmderr;}
int fnum = atoi(arg[1]);
if (fnum < 0 || fnum >= filemaxct) {
@@ -936,7 +1050,7 @@ if (chkCmd(1, "FLUSH")) {
cerr = 0;
fileerror = 0;
if (argct != 1) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
if (argt[1] != 2) {cerr = 2; goto cmderr;}
int fnum = atoi(arg[1]);
if (fnum < 0 || fnum >= filemaxct) {
@@ -952,7 +1066,7 @@ if (chkCmd(2, "MD", "MKDIR")) {
cerr = 0;
fileerror = 0;
if (argct != 1) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
if (argt[1] != 1) {cerr = 2; goto cmderr;}
errno = 0;
#ifndef _WIN32
@@ -967,7 +1081,7 @@ if (chkCmd(2, "RM", "REMOVE")) {
cerr = 0;
fileerror = 0;
if (argct != 1) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
if (argt[1] != 1) {cerr = 2; goto cmderr;}
cbrm(arg[1]);
goto noerr;
@@ -976,8 +1090,8 @@ if (chkCmd(4, "MV", "MOVE", "REN", "RENAME")) {
cerr = 0;
fileerror = 0;
if (argct != 2) {cerr = 3; goto cmderr;}
- if (!solvearg(1)) {goto cmderr;}
- if (!solvearg(2)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 1)) {goto cmderr;}
+ if (!solvearg(arg, argt, argl, 2)) {goto cmderr;}
if (argt[1] != 1 || argt[2] != 1) {cerr = 2; goto cmderr;}
errno = 0;
rename(arg[1], arg[2]);
@@ -988,7 +1102,7 @@ if (chkCmd(1, "LOADEXT")) {
if (argct < 1) {cerr = 3; goto cmderr;}
cerr = 0;
for (int i = 1; i <= argct; i++) {
- if (!solvearg(i) || argt[i] != 1) {cerr = 2; goto cmderr;}
+ if (!solvearg(arg, argt, argl, i) || argt[i] != 1) {cerr = 2; goto cmderr;}
if (loadExt(arg[i]) < 0) {goto cmderr;}
}
goto noerr;
@@ -996,7 +1110,7 @@ if (chkCmd(1, "LOADEXT")) {
if (chkCmd(1, "UNLOADEXT")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] == 1) {
upCase(arg[1]);
for (register int i = 0; i < extmaxct; ++i) {
@@ -1038,7 +1152,7 @@ if (chkCmd(1, "_RESETTITLE")) {
if (chkCmd(1, "_TITLE")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
#ifndef _WIN_NO_VT
if (esc) {
@@ -1058,8 +1172,8 @@ if (chkCmd(1, "_TITLE")) {
if (chkCmd(1, "_SETENV")) {
if (argct != 2) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[1] != 1 || argt[2] != 1) {cerr = 2; goto cmderr;}
#ifndef _WIN32
setenv(arg[1], arg[2], 1);
@@ -1071,7 +1185,7 @@ if (chkCmd(1, "_SETENV")) {
if (chkCmd(1, "_UNSETENV")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
#ifndef _WIN32
unsetenv(arg[1]);
@@ -1085,7 +1199,7 @@ if (chkCmd(1, "_PROMPT")) {
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
copyStr(arg[1], prompt);
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
goto noerr;
}
@@ -1093,7 +1207,7 @@ if (chkCmd(1, "_PROMPTTAB")) {
if (inProg && !autorun) {cerr = 254; goto cmderr;}
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
tab_width = atoi(arg[1]);
goto noerr;
@@ -1110,7 +1224,7 @@ if (chkCmd(1, "_SAVECMDHIST")) {
if (argct > 1) {cerr = 3; goto cmderr;}
cerr = 0;
if (argct) {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
write_history(arg[1]);
} else {
@@ -1131,7 +1245,7 @@ if (chkCmd(1, "_LOADCMDHIST")) {
cerr = 0;
clear_history();
if (argct) {
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 1) {cerr = 2; goto cmderr;}
read_history(arg[1]);
} else {
@@ -1147,7 +1261,7 @@ if (chkCmd(1, "_LIMITCMDHIST")) {
if (inProg && !autorun) {cerr = 254; goto cmderr;}
if (argct != 1) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] != 2) {cerr = 2; goto cmderr;}
int32_t l = atoi(arg[1]);
if (l < -1) {
@@ -1159,6 +1273,40 @@ if (chkCmd(1, "_LIMITCMDHIST")) {
}
goto noerr;
}
+if (chkCmd(1, "_HIDECUR")) {
+ if (argct) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ hidecursor = true;
+ #ifndef _WIN_NO_VT
+ if (esc) {
+ fputs("\e[?25l", stdout);
+ fflush(stdout);
+ }
+ #else
+ CONSOLE_CURSOR_INFO curinfo;
+ GetConsoleCursorInfo(hConsole, &curinfo);
+ curinfo.bVisible = false;
+ SetConsoleCursorInfo(hConsole, &curinfo);
+ #endif
+ goto noerr;
+}
+if (chkCmd(1, "_SHOWCUR")) {
+ if (argct) {cerr = 3; goto cmderr;}
+ cerr = 0;
+ #ifndef _WIN_NO_VT
+ if (esc) {
+ fputs("\e[?25h", stdout);
+ fflush(stdout);
+ }
+ #else
+ CONSOLE_CURSOR_INFO curinfo;
+ GetConsoleCursorInfo(hConsole, &curinfo);
+ curinfo.bVisible = true;
+ SetConsoleCursorInfo(hConsole, &curinfo);
+ #endif
+ hidecursor = false;
+ goto noerr;
+}
if (chkCmd(1, "_TXTLOCK")) {
if (argct) {cerr = 3; goto cmderr;}
cerr = 0;
@@ -1185,7 +1333,7 @@ if (chkCmd(1, "_TXTUNLOCK")) {
if (chkCmd(1, "_TXTATTRIB")) {
if (argct < 1 || argct > 2) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] == 0) {cerr = 3; goto cmderr;}
int attrib = 0;
if (argt[1] == 1) {
@@ -1197,7 +1345,7 @@ if (chkCmd(1, "_TXTATTRIB")) {
if (!strcmp(arg[1], "BOLD")) attrib = 1; else
if (!strcmp(arg[1], "ITALIC")) attrib = 2; else
if (!strcmp(arg[1], "UNDERLINE")) attrib = 3; else
- if (!strcmp(arg[1], "DBL_UNDERLINE") || !strcmp(arg[1], "DOUBLE_UNDERLINE")) attrib = 4; else
+ if (!strcmp(arg[1], "DBL_UNDERLINE") || !strcmp(arg[1], "long double_UNDERLINE")) attrib = 4; else
if (!strcmp(arg[1], "SQG_UNDERLINE") || !strcmp(arg[1], "SQUIGGLY_UNDERLINE")) attrib = 5; else
if (!strcmp(arg[1], "STRIKETHROUGH")) attrib = 6; else
if (!strcmp(arg[1], "OVERLINE")) attrib = 7; else
@@ -1212,7 +1360,7 @@ if (chkCmd(1, "_TXTATTRIB")) {
{cerr = 16; goto cmderr;}
} else {
attrib = atoi(arg[1]);
- if (attrib < 0 || attrib > 12) {cerr = 16; goto cmderr;}
+ if (attrib < 0 || attrib > 15) {cerr = 16; goto cmderr;}
}
int val = 0;
if (attrib == 0) {
@@ -1224,7 +1372,7 @@ if (chkCmd(1, "_TXTATTRIB")) {
if (attrib == 12) {cerr = 16; goto cmderr;}
val = 1;
} else {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (attrib == 12) {
if (argt[2] != 2) {cerr = 2; goto cmderr;}
val = atoi(arg[2]);
@@ -1265,7 +1413,7 @@ if (chkCmd(1, "_TXTATTRIB")) {
if (chkCmd(1, "_SHATTRIB")) {
if (argct < 1 || argct > 2) {cerr = 3; goto cmderr;}
cerr = 0;
- if (!solvearg(1)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 1)) goto cmderr;
if (argt[1] == 0) {cerr = 3; goto cmderr;}
int attrib = 0;
if (argt[1] == 1) {
@@ -1293,7 +1441,7 @@ if (chkCmd(1, "_SHATTRIB")) {
if (attrib == 12) {cerr = 16; goto cmderr;}
val = 1;
} else {
- if (!solvearg(2)) goto cmderr;
+ if (!solvearg(arg, argt, argl, 2)) goto cmderr;
if (argt[2] == 0) {cerr = 3; goto cmderr;}
if (argt[2] == 1) {
upCase(arg[2]);
diff --git a/docs b/docs
index 79193cd..3de3233 160000
--- a/docs
+++ b/docs
@@ -1 +1 @@
-Subproject commit 79193cd786491c2c4ce600839daf68de30c51833
+Subproject commit 3de3233daf721f602f549d39236c35b8ca16890a
diff --git a/examples b/examples
index 94695d1..7cce387 160000
--- a/examples
+++ b/examples
@@ -1 +1 @@
-Subproject commit 94695d1a6d1ed9a36453e366bafd1f79e3ce6fe2
+Subproject commit 7cce387cf803896f99b3d918cfd404ef04774c80
diff --git a/functions.c b/functions.c
index 5767ba9..efd94b6 100644
--- a/functions.c
+++ b/functions.c
@@ -59,20 +59,20 @@ if (chkCmd(1, "CHRAT$")) {
if (chkCmd(2, "RND", "RAND")) {
cerr = 0;
ftype = 2;
- double min = 0;
- double max;
+ long double min = 0;
+ long double max;
if (fargct == 1) {
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- sscanf(farg[1], "%lf", &max);
+ sscanf(farg[1], "%Lf", &max);
} else if (fargct == 2) {
if (fargt[1] + fargt[2] != 4) {cerr = 2; goto fexit;}
- sscanf(farg[1], "%lf", &min);
- sscanf(farg[2], "%lf", &max);
+ sscanf(farg[1], "%Lf", &min);
+ sscanf(farg[2], "%Lf", &max);
} else {
cerr = 3;
goto fexit;
}
- sprintf(outbuf, "%lf", randNum(min, max));
+ sprintf(outbuf, "%Lf", randNum(min, max));
goto fexit;
}
if (chkCmd(1, "TIMERUS")) {
@@ -149,12 +149,12 @@ if (chkCmd(2, "EXEC", "EXECA")) {
bool execa = false;
char** tmpfarg = NULL;
int tmpfargct = 0;
- if (!strcmp(farg[0], "EXECA")) {
+ if (farg[0][4] == 'A') {
if (fargct != 1) {cerr = 3; goto fexit;}
execa = true;
int v = -1;
for (register int i = 0; i < varmaxct; ++i) {
- if (vardata[i].inuse && !strcmp(arg[1], vardata[i].name)) {v = i; break;}
+ if (vardata[i].inuse && !strcmp(farg[1], vardata[i].name)) {v = i; break;}
}
if (v == -1 || vardata[v].size == -1) {cerr = 23; seterrstr(farg[1]); goto fexit;}
if (vardata[v].type != 1) {cerr = 2; goto fexit;}
@@ -170,7 +170,6 @@ if (chkCmd(2, "EXEC", "EXECA")) {
#else
if (sh_clearAttrib) SetConsoleTextAttribute(hConsole, ocAttrib);
#endif
- #ifndef _WIN32
char** runargs = (char**)malloc((fargct + 1) * sizeof(char*));
runargs[0] = farg[1];
int argno = 1;
@@ -178,7 +177,6 @@ if (chkCmd(2, "EXEC", "EXECA")) {
runargs[argno] = farg[argno + 1];
}
runargs[argno] = NULL;
- int status;
int stdout_dup = 0, stderr_dup = 0, fd = 0;
if (sh_silent) {
stdout_dup = dup(1);
@@ -187,51 +185,13 @@ if (chkCmd(2, "EXEC", "EXECA")) {
dup2(fd, 1);
dup2(fd, 2);
}
- pid_t pid = fork();
- if (pid < 0) cerr = -1;
- if (pid == 0) {
- execvp(runargs[0], runargs);
- exit(127);
- }
- else if (pid > 0) {
- while (wait(&status) != pid) {}
- sprintf(outbuf, "%d", (retval = WEXITSTATUS(status)));
- }
- else if (sh_silent) {
+ sprintf(outbuf, "%d", (retval = cb_exec(runargs)));
+ if (sh_silent) {
dup2(stdout_dup, 1);
dup2(stderr_dup, 2);
close(fd);
}
free(runargs);
- #else
- char* tmpcmd = malloc(CB_BUF_SIZE);
- tmpcmd[0] = 0;
- bool winecho = false;
- for (int argno = 1; argno <= fargct; argno++) {
- bool nq = winArgNeedsQuotes(farg[argno]);
- if (argno == 1) {
- upCase(farg[argno]);
- winecho = !strcmp(farg[argno], "ECHO");
- }
- if (nq && !winecho) copyStrApnd(" \"", tmpcmd);
- copyStrApnd(farg[argno], tmpcmd);
- if (nq && !winecho) strApndChar(tmpcmd, '"');
- }
- int stdout_dup = 0, stderr_dup = 0;
- if (sh_silent) {
- stdout_dup = dup(1);
- stderr_dup = dup(2);
- int fd = open("NUL", _O_WRONLY);
- dup2(fd, 1);
- dup2(fd, 2);
- }
- retval = WEXITSTATUS(system(tmpcmd));
- if (sh_silent) {
- dup2(stdout_dup, 1);
- dup2(stderr_dup, 2);
- }
- free(tmpcmd);
- #endif
if (execa) {
fargct = tmpfargct;
farg = tmpfarg;
@@ -265,7 +225,7 @@ if (chkCmd(2, "EXEC$", "EXECA$")) {
bool execa = false;
char** tmpfarg = NULL;
int tmpfargct = 0;
- if (!strcmp(farg[0], "EXECA$")) {
+ if (farg[0][4] == 'A') {
if (fargct != 1) {cerr = 3; goto fexit;}
execa = true;
int v = -1;
@@ -281,7 +241,6 @@ if (chkCmd(2, "EXEC$", "EXECA$")) {
} else {
if (fargt[1] != 1) {cerr = 2; goto fexit;}
}
- #ifndef _WIN32
char** runargs = (char**)malloc((fargct + 1) * sizeof(char*));
runargs[0] = farg[1];
int argno = 1;
@@ -290,60 +249,96 @@ if (chkCmd(2, "EXEC$", "EXECA$")) {
}
runargs[argno] = NULL;
int stdout_dup = 0, stderr_dup = 0, fd[2];
- if (pipe(fd) == -1) {cerr = -1; goto fexit;}
+ #ifndef _WIN32
+ pipe2(fd, O_NONBLOCK);
+ #else
+ _pipe(fd, CB_BUF_SIZE, _O_BINARY);
+ #endif
stdout_dup = dup(1);
stderr_dup = dup(2);
dup2(fd[1], 1);
dup2(fd[1], 2);
- pid_t pid = fork();
- if (pid < 0) cerr = -1;
- else if (pid == 0) {
- execvp(runargs[0], runargs);
- putchar(0);
- exit(127);
- }
- else if (pid > 0) {
- while (wait(&retval) != pid) {}
- retval = WEXITSTATUS(retval);
- outbuf[read(fd[0], outbuf, CB_BUF_SIZE - 1)] = 0;
+ retval = cb_exec(runargs);
+ *outbuf = 0;
+ if (retval >= 0) {
+ #ifndef _WIN32
+ int inchar = 0;
+ ioctl(fd[0], FIONREAD, &inchar);
+ #else
+ DWORD inchar = 0;
+ PeekNamedPipe((HANDLE)_get_osfhandle(fd[0]), NULL, 0, NULL, &inchar, NULL);
+ #endif
+ if (inchar) outbuf[read(fd[0], outbuf, CB_BUF_SIZE - 1)] = 0;
}
dup2(stdout_dup, 1);
dup2(stderr_dup, 2);
close(fd[0]);
close(fd[1]);
free(runargs);
- #else
- char* tmpcmd = malloc(CB_BUF_SIZE);
- tmpcmd[0] = 0;
- bool winecho = false;
- for (int argno = 1; argno <= fargct; argno++) {
- bool nq = winArgNeedsQuotes(farg[argno]);
- if (argno == 1) {
- upCase(farg[argno]);
- winecho = !strcmp(farg[argno], "ECHO");
- }
- if (nq && !winecho) copyStrApnd(" \"", tmpcmd);
- copyStrApnd(farg[argno], tmpcmd);
- if (nq && !winecho) strApndChar(tmpcmd, '"');
- }
- int duperr;
- duperr = dup(2);
- close(2);
- outbuf[0] = 0;
- FILE* p = popen(tmpcmd, "r");
- if (p) {
- outbuf[fread(outbuf, 1, CB_BUF_SIZE, p)] = 0;
- retval = WEXITSTATUS(pclose(p));
- }
- dup2(duperr, 2);
- close(duperr);
- free(tmpcmd);
- #endif
if (execa) {
fargct = tmpfargct;
farg = tmpfarg;
}
- //printf("farg[1]: {%s}\n", farg[1]);
+ goto fexit;
+}
+if (chkCmd(1, "CALLFUNC")) {
+ if (fargct < 1) {cerr = 3; goto fexit;}
+ cerr = 0;
+ ftype = 1;
+ newprogargc = fargct;
+ newprogargs = (char**)malloc((fargct + 1) * sizeof(char*));
+ for (int i = 1; i < newprogargc; ++i) {
+ newprogargs[i] = NULL;
+ }
+ for (int i = 2; i <= fargct; ++i) {
+ newprogargs[i - 1] = malloc(CB_BUF_SIZE);
+ if (!getVal(farg[i], newprogargs[i - 1])) {
+ for (int j = i - 1; j > 0; --j) {
+ free(newprogargs[j]);
+ }
+ free(newprogargs);
+ goto fexit;
+ }
+ newprogargs[i - 1] = realloc(newprogargs[i - 1], strlen(newprogargs[i - 1]) + 1);
+ }
+
+ if (!loadSub(farg[1], true, &subinfo.type)) goto callfunc_err;
+ subinfo.insub = true;
+ ftype = subinfo.type;
+ bool oip = inProg;
+ inProg = true;
+ int ptr1 = 0, ptr2 = 0;
+ char* buf = (char*)malloc(CB_BUF_SIZE);
+ while (1) {
+ while (progbuf[progindex][ptr2] && progbuf[progindex][ptr2] != '\n') {++ptr2;}
+ copyStrSnip(progbuf[progindex], ptr1, ptr2, buf);
+ if ((cerr = runcmd(buf))) {hideerror = true; break;}
+ if (!progbuf[progindex][ptr2]) break;
+ if (!didloop) ++progLine;
+ else didloop = false;
+ ++ptr2;
+ ptr1 = ptr2;
+ }
+ free(buf);
+ inProg = oip;
+ unloadProg();
+ goto callfunc_noerr;
+ callfunc_err:;
+ for (int i = 1; i < newprogargc; ++i) {
+ nfree(newprogargs[i]);
+ }
+ nfree(newprogargs);
+ newprogargc = 0;
+ goto fexit;
+ callfunc_noerr:;
+ if (!cerr) {
+ if (funcret) {
+ copyStr(funcret, outbuf);
+ nfree(funcret);
+ } else {
+ copyStr((ftype == 1) ? defaultstr : defaultnum, outbuf);
+ }
+ }
goto fexit;
}
if (chkCmd(1, "CINT")) {
@@ -351,7 +346,7 @@ if (chkCmd(1, "CINT")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- sprintf(outbuf, "%d", (int)round(atof(farg[1])));
+ sprintf(outbuf, "%d", (int)round(strtold(farg[1], NULL)));
goto fexit;
}
if (chkCmd(1, "INT")) {
@@ -359,8 +354,8 @@ if (chkCmd(1, "INT")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
sprintf(outbuf, "%d", (int)dbl);
int32_t i;
for (i = 0; outbuf[i] != '.' && outbuf[i]; i++) {}
@@ -373,12 +368,7 @@ if (chkCmd(1, "VAL")) {
if (fargct < 1 || fargct > 2) {cerr = 3; goto fexit;}
if (fargt[1] != 1) {cerr = 2; goto fexit;}
if (fargct == 2 && fargt[2] != 2) {cerr = 2; goto fexit;}
- double dbl;
- if (fargct == 1) {
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%lf", dbl);
- goto fexit;
- }
+ long double dbl;
int act = 0;
uint64_t num;
char* tmpstr = NULL;
@@ -388,6 +378,7 @@ if (chkCmd(1, "VAL")) {
switch (act) {
case 0:;
tmplen = strlen(farg[1]);
+ if (!tmplen) {copyStr(defaultstr, outbuf); break;}
for (int32_t i = 0; farg[1][i] == '0' && i < tmplen; i++) {
tmppos++;
}
@@ -398,9 +389,9 @@ if (chkCmd(1, "VAL")) {
outbuf[1] = 0;
break;
}
- sscanf(tmpstr, "%lf", &dbl);
+ sscanf(tmpstr, "%Lf", &dbl);
free(tmpstr);
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
break;
case 1:;
sscanf(farg[1], "%llx", (long long unsigned int*)&num);
@@ -438,10 +429,10 @@ if (chkCmd(1, "MOD")) {
ftype = 2;
if (fargct != 2) {cerr = 3; goto fexit;}
if (fargt[1] != 2 || fargt[2] != 2) {cerr = 2; goto fexit;}
- double dbl1, dbl2;
- sscanf(farg[1], "%lf", &dbl1);
- sscanf(farg[2], "%lf", &dbl2);
- sprintf(outbuf, "%lf", fmod(dbl1, dbl2));
+ long double dbl1, dbl2;
+ sscanf(farg[1], "%Lf", &dbl1);
+ sscanf(farg[2], "%Lf", &dbl2);
+ sprintf(outbuf, "%Lf", fmodl(dbl1, dbl2));
goto fexit;
}
if (chkCmd(1, "PI")) {
@@ -456,7 +447,7 @@ if (chkCmd(1, "ABS")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- sprintf(outbuf, "%lf", fabs(atof(farg[1])));
+ sprintf(outbuf, "%Lf", fabsl(strtold(farg[1], NULL)));
goto fexit;
}
if (chkCmd(1, "SIN")) {
@@ -464,9 +455,9 @@ if (chkCmd(1, "SIN")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%lf", sin(dbl));
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ sprintf(outbuf, "%Lf", sinl(dbl));
goto fexit;
}
if (chkCmd(1, "COS")) {
@@ -474,9 +465,9 @@ if (chkCmd(1, "COS")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%lf", cos(dbl));
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ sprintf(outbuf, "%Lf", cosl(dbl));
goto fexit;
}
if (chkCmd(1, "TAN")) {
@@ -484,9 +475,11 @@ if (chkCmd(1, "TAN")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%lf", tan(dbl));
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ dbl = tanl(dbl);
+ if (!isfinite(dbl)) {cerr = 5; goto fexit;}
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "SINH")) {
@@ -494,11 +487,11 @@ if (chkCmd(1, "SINH")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- dbl = sinh(dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ dbl = sinhl(dbl);
if (!isfinite(dbl)) {cerr = 5; goto fexit;}
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "COSH")) {
@@ -506,11 +499,11 @@ if (chkCmd(1, "COSH")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- dbl = cosh(dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ dbl = coshl(dbl);
if (!isfinite(dbl)) {cerr = 5; goto fexit;}
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "TANH")) {
@@ -518,9 +511,11 @@ if (chkCmd(1, "TANH")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%lf", tanh(dbl));
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
+ dbl = tanhl(dbl);
+ if (!isfinite(dbl)) {cerr = 5; goto fexit;}
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "LOG")) {
@@ -528,11 +523,11 @@ if (chkCmd(1, "LOG")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
dbl = log(dbl);
if (!isfinite(dbl)) {cerr = 5; goto fexit;}
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "LOG10")) {
@@ -540,11 +535,11 @@ if (chkCmd(1, "LOG10")) {
ftype = 2;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
dbl = log10(dbl);
if (!isfinite(dbl)) {cerr = 5; goto fexit;}
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "SHIFT")) {
@@ -612,11 +607,11 @@ if (chkCmd(1, "EXP")) {
cerr = 0;
ftype = 2;
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
dbl = exp(dbl);
if (!isfinite(dbl)) {cerr = 5; goto fexit;}
- sprintf(outbuf, "%lf", dbl);
+ sprintf(outbuf, "%Lf", dbl);
goto fexit;
}
if (chkCmd(1, "INKEY$")) {
@@ -638,9 +633,10 @@ if (chkCmd(1, "INKEY$")) {
}
outbuf[obp] = 0;
#else
- updatechars();
+ uctStop();
copyStr(kbinbuf, outbuf);
kbinbuf[0] = 0;
+ uctStart();
#endif
goto fexit;
}
@@ -727,9 +723,9 @@ if (chkCmd(1, "HEX$")) {
ftype = 1;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
- sprintf(outbuf, "%llx", (long long unsigned int)dbl);
+ uint64_t num;
+ sscanf(farg[1], "%llu", (long long unsigned int *)&num);
+ sprintf(outbuf, "%llx", (long long unsigned int)num);
upCase(outbuf);
goto fexit;
}
@@ -738,8 +734,8 @@ if (chkCmd(1, "OCT$")) {
ftype = 1;
if (fargct != 1) {cerr = 3; goto fexit;}
if (fargt[1] != 2) {cerr = 2; goto fexit;}
- double dbl;
- sscanf(farg[1], "%lf", &dbl);
+ long double dbl;
+ sscanf(farg[1], "%Lf", &dbl);
sprintf(outbuf, "%llo", (long long unsigned int)dbl);
upCase(outbuf);
goto fexit;
@@ -763,27 +759,27 @@ if (chkCmd(1, "RGB")) {
if (chkCmd(1, "LIMIT")) {
cerr = 0;
ftype = 2;
- double num = 0;
+ long double num = 0;
if (fargct < 2 || fargct > 3) {cerr = 3; goto fexit;}
if (fargt[1] != 2 || fargt[2] != 2) {cerr = 2; goto fexit;}
if (fargct == 3 && fargt[3] == 1) {cerr = 2; goto fexit;}
- num = atof(farg[1]);
+ num = strtold(farg[1], NULL);
if (fargct == 2) {
- double max = atof(farg[2]);
+ long double max = strtold(farg[2], NULL);
if (num > max) {num = max;}
} else if (fargct == 3 && fargt[3] == 0) {
- double min = atof(farg[2]);
+ long double min = strtold(farg[2], NULL);
if (num < min) {num = min;}
} else if (fargct == 3) {
- double min = atof(farg[2]);
- double max = atof(farg[3]);
+ long double min = strtold(farg[2], NULL);
+ long double max = strtold(farg[3], NULL);
if (num > max) {num = max;}
else if (num < min) {num = min;}
} else {
cerr = 3;
goto fexit;
}
- sprintf(outbuf, "%lf", num);
+ sprintf(outbuf, "%Lf", num);
goto fexit;
}
if (chkCmd(1, "PAD$")) {
@@ -887,27 +883,24 @@ if (chkCmd(1, "INPUT$")) {
cerr = 0;
ftype = 1;
if (fargct > 1) {cerr = 3; goto fexit;}
- if (fargct == 1 && fargt[1] != 1) {cerr = 2; goto fexit;}
- if (fargct != 1) {
- farg[1] = malloc(4);
- strcpy(farg[1], "?: ");
- }
+ if (fargct && fargt[1] != 1) {cerr = 2; goto fexit;}
+ copyStr((fargct) ? farg[1] : "?: ", gpbuf);
char* tmp = NULL;
- #ifndef _WIN32
+ #ifdef _WIN32
+ uctStop();
+ #else
getCurPos();
- curx--;
- farg[1] = realloc(farg[1], strlen(farg[1]) + curx);
- int32_t ptr = strlen(farg[1]);
- while (curx) {farg[1][ptr] = 22; ptr++; curx--;}
- farg[1][ptr] = 0;
- #endif
- #ifndef _WIN32
+ char* tfarg = gpbuf + strlen(gpbuf);
+ while (--curx) {*tfarg++ = 22;}
+ *tfarg = 0;
__typeof__(rl_getc_function) old_rl_getc_function = rl_getc_function;
rl_getc_function = getc;
#endif
- tmp = readline(farg[1]);
+ tmp = readline(gpbuf);
#ifndef _WIN32
rl_getc_function = old_rl_getc_function;
+ #else
+ uctStart();
#endif
if (tmp != NULL) {
copyStr(tmp, outbuf);
@@ -1510,6 +1503,60 @@ if (chkCmd(1, "_TXTLOCK")) {
sprintf(outbuf, "%d", (int)textlock);
goto fexit;
}
+if (chkCmd(1, "_TXTATTRIB")) {
+ if (fargct != 1) {cerr = 3; goto fexit;}
+ cerr = 0;
+ ftype = 2;
+ if (fargt[1] == 0) {cerr = 3; goto fexit;}
+ int attrib = 0;
+ if (fargt[1] == 1) {
+ for (int32_t i = 0; farg[1][i]; i++) {
+ if (farg[1][i] >= 'a' && farg[1][i] <= 'z') farg[1][i] -= 32;
+ if (farg[1][i] == ' ') farg[1][i] = '_';
+ }
+ if (!strcmp(farg[1], "RESET")) attrib = 0; else
+ if (!strcmp(farg[1], "BOLD")) attrib = 1; else
+ if (!strcmp(farg[1], "ITALIC")) attrib = 2; else
+ if (!strcmp(farg[1], "UNDERLINE")) attrib = 3; else
+ if (!strcmp(farg[1], "DBL_UNDERLINE") || !strcmp(farg[1], "long double_UNDERLINE")) attrib = 4; else
+ if (!strcmp(farg[1], "SQG_UNDERLINE") || !strcmp(farg[1], "SQUIGGLY_UNDERLINE")) attrib = 5; else
+ if (!strcmp(farg[1], "STRIKETHROUGH")) attrib = 6; else
+ if (!strcmp(farg[1], "OVERLINE")) attrib = 7; else
+ if (!strcmp(farg[1], "DIM")) attrib = 8; else
+ if (!strcmp(farg[1], "BLINK")) attrib = 9; else
+ if (!strcmp(farg[1], "HIDDEN")) attrib = 10; else
+ if (!strcmp(farg[1], "REVERSE")) attrib = 11; else
+ if (!strcmp(farg[1], "UNDERLINE_COLOR")) attrib = 12; else
+ if (!strcmp(farg[1], "FGC")) attrib = 13; else
+ if (!strcmp(farg[1], "BGC")) attrib = 14; else
+ if (!strcmp(farg[1], "TRUECOLOR") || !strcmp(farg[1], "TRUE_COLOR") || !strcmp(farg[1], "24BITCOLOR") || !strcmp(farg[1], "24BIT_COLOR")) attrib = 15; else
+ {cerr = 16; goto fexit;}
+ } else {
+ attrib = atoi(farg[1]);
+ if (attrib < 0 || attrib > 15) {cerr = 16; goto fexit;}
+ }
+ int val = 0;
+ switch (attrib) {
+ case 0: val = 0; break;
+ case 1: val = txtattrib.bold; break;
+ case 2: val = txtattrib.italic; break;
+ case 3: val = txtattrib.underln; break;
+ case 4: val = txtattrib.underlndbl; break;
+ case 5: val = txtattrib.underlnsqg; break;
+ case 6: val = txtattrib.strike; break;
+ case 7: val = txtattrib.overln; break;
+ case 8: val = txtattrib.dim; break;
+ case 9: val = txtattrib.blink; break;
+ case 10: val = txtattrib.hidden; break;
+ case 11: val = txtattrib.reverse; break;
+ case 12: val = txtattrib.underlncolor; break;
+ case 13: val = txtattrib.fgce; break;
+ case 14: val = txtattrib.bgce; break;
+ case 15: val = txtattrib.truecolor; break;
+ }
+ sprintf(outbuf, "%d", (int)val);
+ goto fexit;
+}
if (chkCmd(1, "_VER$")) {
cerr = 0;
ftype = 1;
diff --git a/logic.c b/logic.c
index d6cd1ea..f880c3d 100644
--- a/logic.c
+++ b/logic.c
@@ -107,9 +107,6 @@ if (chkCmd(1, "DO")) {
dlstack[dlstackp].pl = progLine;
dlstack[dlstackp].brkinfo = brkinfo;
brkinfo.block = 1;
- #ifdef _WIN32
- updatechars();
- #endif
return true;
}
if (chkCmd(2, "WHILE", "DOWHILE")) {
@@ -133,9 +130,6 @@ if (chkCmd(2, "WHILE", "DOWHILE")) {
dlstack[dlstackp].cp = cmdpos;
dlstack[dlstackp].brkinfo = brkinfo;
brkinfo.block = 1;
- #ifdef _WIN32
- updatechars();
- #endif
}
dldcmd[dlstackp] = !testval;
return true;
@@ -329,9 +323,6 @@ if (chkCmd(1, "FOR")) {
fnstack[fnstackp].cp = cmdpos;
fnstack[fnstackp].pl = progLine;
brkinfo.block = 2;
- #ifdef _WIN32
- updatechars();
- #endif
return true;
}
if (chkCmd(1, "NEXT")) {