init
This commit is contained in:
commit
283b2dd167
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.gdb_history
|
||||||
|
fu-shell
|
||||||
|
*.yy.*
|
||||||
|
*.o
|
||||||
|
*.out
|
17
Makefile
Normal file
17
Makefile
Normal 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
9
lisp_balance.h
Normal 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
53
lisp_balance.l
Normal 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
123
main.cpp
Normal 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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user