usable state; organized ok

This commit is contained in:
anon 2024-03-03 13:46:08 +01:00
parent 283b2dd167
commit 35e567190f
8 changed files with 244 additions and 104 deletions

View File

@ -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
View 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
View 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

View File

@ -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

View File

@ -22,6 +22,7 @@
%option noyywrap
%option nodefault
%option prefix="lb_"
%x LITERAL
%%

149
main.cpp
View File

@ -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
View 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
View 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