usable state; organized ok
This commit is contained in:
parent
283b2dd167
commit
35e567190f
5
Makefile
5
Makefile
@ -10,8 +10,9 @@ LDLIBS := $$(pkg-config --cflags --libs readline) -lboost_system
|
|||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
${COMPILE.cpp} $< -o $@
|
${COMPILE.cpp} $< -o $@
|
||||||
|
|
||||||
main: lisp_balance.yy.o main.o
|
main: lisp_balance.yy.o main.o io.o shell.o
|
||||||
${LINK.cpp} -o fu-shell $+ ${LDLIBS}
|
${LINK.cpp} -o fu-shell $+ ${LDLIBS}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o
|
-rm *.yy.*
|
||||||
|
-rm *.o
|
||||||
|
66
io.cpp
Normal file
66
io.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <readline/readline.h>
|
||||||
|
|
||||||
|
inline int fu_fd;
|
||||||
|
inline const char * prompt1;
|
||||||
|
inline const char * prompt2 = " > ";
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void put_response(fu_response_header_t h, const char * const s) {
|
||||||
|
if (!s) {
|
||||||
|
puts("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!h.error_code) {
|
||||||
|
fputs("\033[32m", stdout);
|
||||||
|
} else {
|
||||||
|
fputs("\033[31m", stdout);
|
||||||
|
}
|
||||||
|
fputs(s, stdout);
|
||||||
|
|
||||||
|
fputs("\033[0m\n", stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void fu_transmit(const char * const s) {
|
||||||
|
std::string message = s;
|
||||||
|
message = std::string() + (char)0x47 + (char)(message.size() / 256) + (char)(message.size() % 256) + message;
|
||||||
|
write(fu_fd, message.c_str(), message.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
const char * const fu_recieve(fu_response_header_t &header) {
|
||||||
|
static char buff[MAX_CHUNK];
|
||||||
|
static std::string r;
|
||||||
|
|
||||||
|
const int e = read(fu_fd, (void*)(&header), sizeof(fu_response_header_t));
|
||||||
|
if (e != sizeof(fu_response_header_t)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < header.high; i++) {
|
||||||
|
const int e2 = read(fu_fd, buff, MAX_CHUNK);
|
||||||
|
if (e2 != MAX_CHUNK) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r.append(buff, MAX_CHUNK);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int e3 = read(fu_fd, buff, header.low);
|
||||||
|
if (e3 != header.low) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r.append(buff, header.low);
|
||||||
|
|
||||||
|
return r.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
char * fu_readline(bool is_1) {
|
||||||
|
return readline(is_1 ? prompt1 : prompt2);
|
||||||
|
}
|
41
io.h
Normal file
41
io.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* Reading from and writting to the server.
|
||||||
|
* NOTE: the IO has no clue we are using sockets.
|
||||||
|
*/
|
||||||
|
#ifndef FU_IO_H
|
||||||
|
#define FU_IO_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
struct alignas(1) fu_response_header_t {
|
||||||
|
char magic_byte; // ^G
|
||||||
|
char error_code; // 0 on success
|
||||||
|
char high;
|
||||||
|
char low;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Number of bytes fu_response_header::high and fu_response_header::low encode,
|
||||||
|
* as defined by the script-fu documentation.
|
||||||
|
*/
|
||||||
|
const int MAX_CHUNK = 256;
|
||||||
|
|
||||||
|
/* Socket file descriptor
|
||||||
|
*/
|
||||||
|
extern int fu_fd;
|
||||||
|
|
||||||
|
#define PS1 "> " /* default value for prompt1 */
|
||||||
|
extern const char * prompt1;
|
||||||
|
extern const char * prompt2;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void fu_transmit(const char * const s);
|
||||||
|
const char * const fu_recieve(fu_response_header_t &header);
|
||||||
|
void put_response(fu_response_header_t h, const char * const s);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * fu_readline(bool is_1 = true);
|
||||||
|
|
||||||
|
#endif
|
@ -6,4 +6,6 @@ enum {
|
|||||||
PARTIAL, // the provided statement is not closed
|
PARTIAL, // the provided statement is not closed
|
||||||
BROKEN, // the provided is all fucked'n'shieet
|
BROKEN, // the provided is all fucked'n'shieet
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void lb_set_input(char * const s);
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
%option noyywrap
|
%option noyywrap
|
||||||
%option nodefault
|
%option nodefault
|
||||||
|
%option prefix="lb_"
|
||||||
|
|
||||||
%x LITERAL
|
%x LITERAL
|
||||||
%%
|
%%
|
||||||
|
141
main.cpp
141
main.cpp
@ -1,120 +1,65 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <readline/readline.h>
|
#include <errno.h>
|
||||||
#include <boost/asio.hpp>
|
#include <string>
|
||||||
|
|
||||||
#include "lisp_balance.h"
|
#include <unistd.h>
|
||||||
#include "lisp_balance.yy.h"
|
#include <netdb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
using namespace boost::asio;
|
#include "io.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
#define PS1 "> "
|
#define PORT 10'008 /* default port */
|
||||||
|
|
||||||
io_service hio_service;
|
bool fu_connect(const int port) {
|
||||||
ip::tcp::socket hsocket(hio_service);
|
struct sockaddr_in server_addr;
|
||||||
|
char buffer[1024] = {0};
|
||||||
|
|
||||||
bool fu_connect() {
|
if ((fu_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
ip::tcp::endpoint endpoint(ip::address::from_string("127.0.0.1"), 10008);
|
perror("Socket creation failed");
|
||||||
hsocket.connect(endpoint);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(port);
|
||||||
|
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
if (connect(fu_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
||||||
|
perror("Connection failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * transmit(const char * const s) {
|
bool init(int argc, char * * argv) {
|
||||||
static char reply[1024];
|
|
||||||
try {
|
prompt1 = getenv("FU_PS1");
|
||||||
std::string message = s;
|
if (not prompt1) {
|
||||||
message = std::string() + (char)0x47 + (char)(message.size() / 256) + (char)(message.size() % 256) + message;
|
prompt1 = PS1;
|
||||||
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);
|
const int port =
|
||||||
if (error) {
|
(argc > 1)
|
||||||
throw boost::system::system_error(error);
|
?
|
||||||
}
|
std::stoi(argv[1])
|
||||||
return reply;
|
:
|
||||||
} catch (std::exception& e) {
|
PORT
|
||||||
puts(e.what());
|
;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int special(const char * const l) {
|
if (not fu_connect(port)) {
|
||||||
if (!strcmp(l, ".exit")) {
|
return false;
|
||||||
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;
|
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() {
|
signed main(int argc, char * * argv) {
|
||||||
bool r;
|
if(not init(argc, argv)) {
|
||||||
char * input = readline(PS1);
|
|
||||||
r = fu_judge();
|
|
||||||
|
|
||||||
free(input);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
signed main() {
|
|
||||||
if (not fu_connect()) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
74
shell.cpp
Normal file
74
shell.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "shell.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "lisp_balance.h"
|
||||||
|
#include "lisp_balance.yy.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int fu_shell_meta(const char * const l) {
|
||||||
|
if (!strcmp(l, ".exit")) {
|
||||||
|
return 1;
|
||||||
|
} else if (!strcmp(l, ".connect ")) {
|
||||||
|
} else if (!strcmp(l, ".read ")) {
|
||||||
|
} else if (!strcmp(l, ".ping")) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
bool fu_judge(const char * const input) {
|
||||||
|
bool r;
|
||||||
|
if (fu_shell_meta(input)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * const cpy = strdup(input);
|
||||||
|
lb_set_input(cpy);
|
||||||
|
|
||||||
|
const int p = lb_lex();
|
||||||
|
switch (p) {
|
||||||
|
case FULL: {
|
||||||
|
try {
|
||||||
|
fu_transmit(input);
|
||||||
|
fu_response_header_t h;
|
||||||
|
const char * const m = fu_recieve(h);
|
||||||
|
put_response(h, m);
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
puts(e.what());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r = true;
|
||||||
|
} break;
|
||||||
|
case PARTIAL: {
|
||||||
|
char * b = fu_readline();
|
||||||
|
std::string e = std::string() + input + b;
|
||||||
|
free(b);
|
||||||
|
r = fu_judge(e.c_str());
|
||||||
|
} break;
|
||||||
|
case BROKEN: {
|
||||||
|
puts("Wow budy!");
|
||||||
|
r = true;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(cpy);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
bool fu_interpret() {
|
||||||
|
bool r;
|
||||||
|
char * input = fu_readline(false);
|
||||||
|
r = fu_judge(input);
|
||||||
|
|
||||||
|
free(input);
|
||||||
|
return r;
|
||||||
|
}
|
10
shell.h
Normal file
10
shell.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef FU_SHELL_H
|
||||||
|
#define FU_SHELL_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int fu_shell_meta(const char * const l);
|
||||||
|
bool fu_judge(const char * const input);
|
||||||
|
bool fu_interpret();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user