This commit is contained in:
anon 2024-03-01 22:05:18 +01:00
commit 283b2dd167
5 changed files with 207 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.gdb_history
fu-shell
*.yy.*
*.o
*.out

17
Makefile Normal file
View File

@ -0,0 +1,17 @@
CXXFLAGS := --std=c++17 -ggdb
LDLIBS := $$(pkg-config --cflags --libs readline) -lboost_system
%.yy.c: %.l
flex -o $@ --header-file=$*.yy.h $<
%.yy.o: %.yy.c
${COMPILE.c} $< -o $@
%.o: %.cpp
${COMPILE.cpp} $< -o $@
main: lisp_balance.yy.o main.o
${LINK.cpp} -o fu-shell $+ ${LDLIBS}
clean:
rm *.o

9
lisp_balance.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef LISP_BANALNCE_H
#define LISP_BANALNCE_H
// Return values:
enum {
FULL = 0, // the provided statement seems complete
PARTIAL, // the provided statement is not closed
BROKEN, // the provided is all fucked'n'shieet
};
#endif

53
lisp_balance.l Normal file
View File

@ -0,0 +1,53 @@
%{
#include "lisp_balance.h"
static int paren_stack = 0;
static char * lb_input;
static int len;
static int offset;
void lb_set_input(char * const s) {
lb_input = s;
len = strlen(lb_input);
offset = len;
}
#define YY_INPUT(buf, result, max_size) { \
int cpi = (offset && offset > max_size) ? max_size : offset; \
memcpy(buf, lb_input+(len-offset), cpi); \
result = cpi; \
offset = (cpi > offset) ? 0 : offset - cpi; \
}
%}
%option noyywrap
%option nodefault
%x LITERAL
%%
<INITIAL>{
\( { ++paren_stack; }
\) {
if (paren_stack >= 0) {
--paren_stack;
} else {
return BROKEN;
}
}
\" { BEGIN LITERAL; }
.|\n { ; }
<<EOF>> {
if (paren_stack == 0) {
return FULL;
} else {
return PARTIAL;
}
}
}
<LITERAL>{
\" { BEGIN INITIAL; }
.|\n { ; }
<<EOF>> { return PARTIAL; }
}
%%

123
main.cpp Normal file
View File

@ -0,0 +1,123 @@
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <boost/asio.hpp>
#include "lisp_balance.h"
#include "lisp_balance.yy.h"
using namespace boost::asio;
#define PS1 "> "
io_service hio_service;
ip::tcp::socket hsocket(hio_service);
bool fu_connect() {
ip::tcp::endpoint endpoint(ip::address::from_string("127.0.0.1"), 10008);
hsocket.connect(endpoint);
return true;
}
char * transmit(const char * const s) {
static char reply[1024];
try {
std::string message = s;
message = std::string() + (char)0x47 + (char)(message.size() / 256) + (char)(message.size() % 256) + message;
boost::system::error_code error;
write(hsocket, buffer(message), error);
if (error) {
throw boost::system::system_error(error);
}
size_t reply_length = hsocket.read_some(buffer(reply), error);
if (error) {
throw boost::system::system_error(error);
}
return reply;
} catch (std::exception& e) {
puts(e.what());
return NULL;
}
}
int special(const char * const l) {
if (!strcmp(l, ".exit")) {
return 1;
} else if (!strcmp(l, ".connect ")) {
} else if (!strcmp(l, ".ping")) {
}
return 0;
}
void put_response(const char * const s) {
/* The script-fu server protocol uses leading bytes
* to communicate meta information for clients
* YYY: https://docs.gimp.org/2.10/en/gimp-filters-script-fu.html#plug-in-script-fu-console
*/
enum {
MAGIC_BYTE,
ERROR_CODE,
LEN_HIGH,
LEN_LOW,
LEADING_META_SIZE,
};
const char * const msg = s + LEADING_META_SIZE;
printf("high: %d low: %d", s[LEN_HIGH], s[LEN_LOW]);
if (!s[ERROR_CODE]) {
fputs("\033[32m", stdout);
} else {
fputs("\033[31m", stdout);
}
for (int i = 0, h = s[LEN_HIGH]; i != h; i++) {
puts("f");
fwrite((msg + LEADING_META_SIZE) + (i*256), 256, sizeof(char), stdout);
}
fwrite(msg + (s[LEN_HIGH]*256), s[LEN_LOW], sizeof(char), stdout);
fputs("\033[0m", stdout);
}
bool fu_judge(const char * const input) {
bool r;
if (special(input)) {
return true;
}
char * const cpy = strdup(input);
lb_set_input(input);
const int p = lb_parse();
switch (p) {
default: {
r = false;
};
}
put_response(transmit(input));
free(cpy);
return r;
}
bool fu_interpret() {
bool r;
char * input = readline(PS1);
r = fu_judge();
free(input);
return r;
}
signed main() {
if (not fu_connect()) {
return 1;
}
while(fu_interpret()) { ; }
return 0;
}