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
|
||||
${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}
|
||||
|
||||
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
|
||||
BROKEN, // the provided is all fucked'n'shieet
|
||||
};
|
||||
|
||||
void lb_set_input(char * const s);
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
%option noyywrap
|
||||
%option nodefault
|
||||
%option prefix="lb_"
|
||||
|
||||
%x LITERAL
|
||||
%%
|
||||
|
149
main.cpp
149
main.cpp
@ -1,120 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <readline/readline.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <errno.h>
|
||||
#include <string>
|
||||
|
||||
#include "lisp_balance.h"
|
||||
#include "lisp_balance.yy.h"
|
||||
#include <unistd.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;
|
||||
ip::tcp::socket hsocket(hio_service);
|
||||
bool fu_connect(const int port) {
|
||||
struct sockaddr_in server_addr;
|
||||
char buffer[1024] = {0};
|
||||
|
||||
bool fu_connect() {
|
||||
ip::tcp::endpoint endpoint(ip::address::from_string("127.0.0.1"), 10008);
|
||||
hsocket.connect(endpoint);
|
||||
if ((fu_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
perror("Socket creation failed");
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
bool init(int argc, char * * argv) {
|
||||
|
||||
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;
|
||||
prompt1 = getenv("FU_PS1");
|
||||
if (not prompt1) {
|
||||
prompt1 = PS1;
|
||||
}
|
||||
|
||||
const int port =
|
||||
(argc > 1)
|
||||
?
|
||||
std::stoi(argv[1])
|
||||
:
|
||||
PORT
|
||||
;
|
||||
|
||||
if (not fu_connect(port)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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()) {
|
||||
signed main(int argc, char * * argv) {
|
||||
if(not init(argc, argv)) {
|
||||
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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user