From 05c8e0a31a0d4192c590e833b24393208e1c751f Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Tue, 30 Jun 2026 19:03:25 +0900 Subject: fix: MCPCをvendored fork化しMCP準拠と接続安定性を改善 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Git submoduleを廃止してMCPCを直接管理 - Windowsで254リクエスト付近に発生する切断を修正 - JSON-RPC 2.0エラー応答を標準化 - tool schemaとruntimeの必須・任意引数を一致 - 1000回連続呼び出しの回帰テストを追加 --- third_party/mcpc/tst/.indent.pro | 1 + third_party/mcpc/tst/CMakeLists.txt | 33 ++++ third_party/mcpc/tst/Makefile | 108 +++++++++++ third_party/mcpc/tst/commtst.c | 181 ++++++++++++++++++ third_party/mcpc/tst/commtst.h | 147 +++++++++++++++ .../mcpc/tst/itst-svcalc-req-promptslist-1.json | 1 + .../mcpc/tst/itst-svcalc-req-resourceslist-1.json | 1 + .../mcpc/tst/itst-svcalc-req-toolslist-1.json | 1 + third_party/mcpc/tst/itst-svcalc.c | 207 +++++++++++++++++++++ 9 files changed, 680 insertions(+) create mode 100644 third_party/mcpc/tst/.indent.pro create mode 100644 third_party/mcpc/tst/CMakeLists.txt create mode 100644 third_party/mcpc/tst/Makefile create mode 100644 third_party/mcpc/tst/commtst.c create mode 100644 third_party/mcpc/tst/commtst.h create mode 100644 third_party/mcpc/tst/itst-svcalc-req-promptslist-1.json create mode 100644 third_party/mcpc/tst/itst-svcalc-req-resourceslist-1.json create mode 100644 third_party/mcpc/tst/itst-svcalc-req-toolslist-1.json create mode 100644 third_party/mcpc/tst/itst-svcalc.c (limited to 'third_party/mcpc/tst') diff --git a/third_party/mcpc/tst/.indent.pro b/third_party/mcpc/tst/.indent.pro new file mode 100644 index 0000000..f7bb493 --- /dev/null +++ b/third_party/mcpc/tst/.indent.pro @@ -0,0 +1 @@ +../.indent.pro \ No newline at end of file diff --git a/third_party/mcpc/tst/CMakeLists.txt b/third_party/mcpc/tst/CMakeLists.txt new file mode 100644 index 0000000..d9b5bd5 --- /dev/null +++ b/third_party/mcpc/tst/CMakeLists.txt @@ -0,0 +1,33 @@ + + +add_compile_options(/Dis_win) +add_compile_options(/Dis_wincl) +add_compile_options(/nologo) +add_compile_options(/std:c17) +add_compile_options(/DMCPC_C23PTCH_KW1) +add_compile_options(/DMCPC_C23PTCH_CKD1) +add_compile_options(/DMCPC_C23PTCH_UCHAR1) + + +# --------------------------- Add A Test --------------------------- + +set (CurrTestName server1) + +add_executable (${CurrTestName} ${CurrTestName}.c commtst.c) + +target_include_directories ( + ${CurrTestName} + PRIVATE ${PROJECT_SOURCE_DIR} + PRIVATE ${PROJECT_SOURCE_DIR}/src +) + +target_link_libraries (${CurrTestName} ws2_32) +target_link_libraries (${CurrTestName} mcpc) + +add_test(NAME ${CurrTestName} COMMAND ${CurrTestName}) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/server1-req-initialize-1.json + ${CMAKE_CURRENT_BINARY_DIR}/server1-req-initialize-1.json + COPYONLY +) diff --git a/third_party/mcpc/tst/Makefile b/third_party/mcpc/tst/Makefile new file mode 100644 index 0000000..5951716 --- /dev/null +++ b/third_party/mcpc/tst/Makefile @@ -0,0 +1,108 @@ +include ../mk/step0.mk + +ifneq (,$(is_linux)) + include ../mk/ccdefs-linux.mk +endif +ifneq (,$(is_cygwin)) + include ../mk/ccdefs-cygwin.mk +endif +ifneq (,$(is_mingw)) + include ../mk/ccdefs-mingw.mk +endif +ifneq (,$(is_macos)) + include ../mk/ccdefs-macos.mk +endif +ifneq (,$(is_win)) + include ../mk/ccdefs-win.mk +endif + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +include ../mk/dbgrel.mk + + +ifneq (,$(is_gcclike)) + CFLAGS += -I../src +endif +ifneq (,$(is_cllike)) + CFLAGS += /I..\src +endif + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +default: link utst + +clean: + $(if $(is_cmd) , del *.pdb *.ilk *.o *.out *.a *.so *.dSYM *.obj *.exe *.lib *.dll *.exp *.log ) + $(if $(is_sh) , rm -rf *.pdb *.ilk *.o *.out *.a *.so *.dSYM *.obj *.exe *.lib *.dll *.exp *.log ) + +comp: itst-svcalc_COMP + +link: itst-svcalc_LINKE + +utst: itst-svcalc_EXEC + +itst: itst-svcalc_EXEC + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# itst-svcalc + +itst-svcalc_srcs = +itst-svcalc_srcs += commtst.c +itst-svcalc_srcs += itst-svcalc.c + +itst-svcalc_objs = +ifneq (,$(is_gcclike)) + itst-svcalc_objs = $(patsubst %.c,%.o,$(itst-svcalc_srcs)) +else ifneq (,$(is_cllike)) + itst-svcalc_objs = $(patsubst %.c,%.obj,$(itst-svcalc_srcs)) +endif + +itst-svcalc_ldflags = +ifneq (,$(is_unixar)) + itst-svcalc_ldflags += ../src/libmcpc.a +endif +ifneq (,$(is_manual_pthread)) + itst-svcalc_ldflags += -lpthread +endif +ifneq (,$(is_winlib)) + itst-svcalc_ldflags += ws2_32.lib + itst-svcalc_ldflags += ..\src\mcpc.lib +endif +ifneq (,$(is_winld)) + itst-svcalc_ldflags += -lws2_32 +endif + + +itst-svcalc_COMP: + $(if $(is_gcclike) , $(CC) $(CFLAGS) $(itst-svcalc_srcs) -c ) + $(if $(is_cllike) , $(CC) $(CFLAGS) $(itst-svcalc_srcs) /c ) +itst-svcalc_LINKE: itst-svcalc_COMP + $(if $(is_gcclike) , $(CC) $(itst-svcalc_objs) $(LDFLAGS) $(itst-svcalc_ldflags) -o itst-svcalc.out ) + $(if $(is_cllike) , $(CC) $(itst-svcalc_objs) /link /out:itst-svcalc.exe $(LDFLAGS) $(itst-svcalc_ldflags)) +itst-svcalc_EXEC: itst-svcalc_LINKE + @ echo>>$@.stdout.log; echo>>$@.stderr.log; + $(if $(is_unix) , @ date>>$@.stdout.log; date>>$@.stderr.log; ) + $(if $(is_cmd) , echo ___>>$@.stdout.log; echo ___>>$@.stderr.log; ) + $(if $(is_pkill) , pkill itst-sv || printf "" ) + # itst-svcalc toolslist + $(if $(is_dirsh) , ./itst-svcalc.out iostrm -i itst-svcalc-req-toolslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_cmd) , itst-svcalc.exe iostrm -i itst-svcalc-req-toolslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_cllike)) , ./itst-svcalc.exe iostrm -i itst-svcalc-req-toolslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_gcclike)) , ./itst-svcalc.out iostrm -i itst-svcalc-req-toolslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_valg) , valgrind --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=222 ./itst-svcalc.out iostrm -i itst-svcalc-req-toolslist-1.json 1>/dev/null 2>/dev/null ) + # itst-svcalc promptslist + $(if $(is_dirsh) , ./itst-svcalc.out iostrm -i itst-svcalc-req-promptslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_cmd) , itst-svcalc.exe iostrm -i itst-svcalc-req-promptslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_cllike)) , ./itst-svcalc.exe iostrm -i itst-svcalc-req-promptslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_gcclike)) , ./itst-svcalc.out iostrm -i itst-svcalc-req-promptslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_valg) , valgrind --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=222 ./itst-svcalc.out iostrm -i itst-svcalc-req-promptslist-1.json 1>/dev/null 2>/dev/null ) + # itst-svcalc resourceslist + $(if $(is_dirsh) , ./itst-svcalc.out iostrm -i itst-svcalc-req-resourceslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_cmd) , itst-svcalc.exe iostrm -i itst-svcalc-req-resourceslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_cllike)) , ./itst-svcalc.exe iostrm -i itst-svcalc-req-resourceslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(and $(is_indirsh),$(is_gcclike)) , ./itst-svcalc.out iostrm -i itst-svcalc-req-resourceslist-1.json 1>>$@.stdout.log 2>>$@.stderr.log ) + $(if $(is_valg) , valgrind --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=222 ./itst-svcalc.out iostrm -i itst-svcalc-req-resourceslist-1.json 1>/dev/null 2>/dev/null ) + @echo P A S S E D : $(patsubst %_EXEC,%,$@) diff --git a/third_party/mcpc/tst/commtst.c b/third_party/mcpc/tst/commtst.c new file mode 100644 index 0000000..a2ba8dc --- /dev/null +++ b/third_party/mcpc/tst/commtst.c @@ -0,0 +1,181 @@ +#include "commtst.h" + +#include + +i32_t +fsize (FILE *strm) +{ + fseek (strm, 0, SEEK_SET); + fseek (strm, 0, SEEK_END); + long sz = ftell (strm); + assert (sz > 0); + fseek (strm, 0, SEEK_SET); + return sz; +} + +void +read_atmost (void *src, char *rbuf, const size_t nmost, size_t *nread) +{ +#ifdef is_win + HANDLE *hdlp = (HANDLE *) src; +#else + int *fdp = (int *) src; +#endif + size_t nread_accm = 0; + size_t nleft = nmost; + while (nleft > 0) + { + ssize_t nbuffered = nmost - nleft; +#ifdef is_win + ssize_t nread_cur = 0; + assT (ReadFile + (*hdlp, rbuf + nbuffered, (DWORD)nleft, (LPDWORD) (&nread_cur), + nullptr)); +#else + ssize_t nread_cur = read (*fdp, rbuf + nbuffered, nleft); +#endif + if (nread_cur <= 0) + break; + nread_accm += nread_cur; + nleft -= nread_cur; + } + *nread = nread_accm; +} + +void +recv_atmost ( +#if is_unix + int csock, +#elif is_win + SOCKET csock, +#endif + char *rbuf, const size_t nmost, size_t *nread) +{ + size_t nread_accm = 0; + size_t nleft = nmost; + while (nleft > 0) + { + ssize_t nbuffered = nmost - nleft; + ssize_t nread_cur = recv (csock, rbuf + nbuffered, (int)nleft, 0); + if (nread_cur <= 0) + break; + nread_accm += nread_cur; + nleft -= nread_cur; + } + *nread = nread_accm; +} + +i32_t +read_u8str (const char8_t *const filename, char8_t *const destbuf) +{ + FILE *file; + +#if is_win + fopen_s (&file, (const char*) filename, "rb,ccs=UTF-8"); +#else + file = fopen ((const char*) filename, "rb"); +#endif + assert (file != nullptr); + + i32_t fsz = fsize (file); + + size_t bytes_read = fread (destbuf, 1, fsz, file); + assert (bytes_read > 0); + + // null-terminate the buffer + destbuf[bytes_read] = 0; + // printf("File content: %s\n", destbuf); + + fclose (file); + + return 0; +} + +i32_t +read_u8str_sz (const char8_t *const filename, char8_t *const destbuf, + size_t *nread) +{ + FILE *file; + +#if is_win + fopen_s (&file, (const char*) filename, "rb,ccs=UTF-8"); +#else + file = fopen ((const char*) filename, "rb"); +#endif + assTcb (file != nullptr, + { + fprintf (stderr, "filename:%s\n", filename); + }); + + i32_t fsz = fsize (file); + + size_t bytes_read = fread (destbuf, 1, fsz, file); + assert (bytes_read > 0); + + // null-terminate the buffer + destbuf[bytes_read] = 0; + *nread = bytes_read; + // printf("File content: %s\n", destbuf); + + fclose (file); + + return 0; +} + +void +zero_trailing_white_char (char8_t *buf, const size_t len) +{ + for (size_t i = len - 1; i != 0; i--) // TODO ckd_add + { + if (buf[i] == '\n' || buf[i] == '\r' || buf[i] == '\t' || buf[i] == ' ') + buf[i] = 0; + else + break; + } +} + +void +zero_trailing_white_char2 (char8_t *buf, size_t *len) +{ + for (size_t i = *len - 1; i != 0; i--) // TODO ckd_add + { + if (buf[i] == '\n' || buf[i] == '\r' || buf[i] == '\t' || buf[i] == ' ') + { + buf[i] = 0; + *len -= 1; + } + else + break; + } +} + +#ifdef is_unix +FILE * +unix_fd2strm_r (int fd) +{ + return fdopen (fd, "r"); +} +#endif + +#ifdef is_win +FILE * +win_handle2strm (HANDLE h) +{ + int fd = _open_osfhandle ((intptr_t) h, _O_RDONLY); + assT (fd > 0); + + FILE *file = _fdopen (fd, "r+"); + assT (file != nullptr); + return file; +} +#endif + +#ifdef is_win +int +win_handle2fd (HANDLE h) +{ + int fd = _open_osfhandle ((intptr_t) h, _O_RDONLY); + assT (fd > 0); + return fd; +} +#endif diff --git a/third_party/mcpc/tst/commtst.h b/third_party/mcpc/tst/commtst.h new file mode 100644 index 0000000..49dcc93 --- /dev/null +++ b/third_party/mcpc/tst/commtst.h @@ -0,0 +1,147 @@ +#ifndef h_commtst +#define h_commtst + + +// clang-format off +#ifdef is_unix +#define _POSIX_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifdef is_win + +/* # define _WINSOCKAPI_ */ +#include +#include +#include +/* # include */ +#include +#include +#include "commtst.h" + +#endif +// clang-format on + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ass0(f) \ + do { \ + int ec = (f); \ + if (0 != ec) { \ + fprintf(stderr, \ + "%s:%d,ec:%d syserr:%s\n", \ + __FILE__, \ + __LINE__, \ + ec, \ + strerror(errno)); \ + abort(); \ + } \ + } while (0) + +#define assT(f) \ + do { \ + if (!(f)) { \ + fprintf(stderr, \ + "abort@%s:%d,syserr:%s\n", \ + __FILE__, \ + __LINE__, \ + strerror(errno)); \ + abort(); \ + } \ + } while (0) + +#define assF(f) \ + do { \ + if ((f)) { \ + fprintf(stderr, \ + "abort@%s:%d,syserr:%s\n", \ + __FILE__, \ + __LINE__, \ + strerror(errno)); \ + abort(); \ + } \ + } while (0) + +#define assTcb(f, cb) \ + do { \ + if (!(f)) { \ + { cb }; \ + fprintf(stderr, "abort@%s:%d\n", __FILE__, __LINE__); \ + abort(); \ + } \ + } while (0) + +#define BUFCAP 1024 +#define PORT 8080 + +typedef int8_t i8_t; +typedef uint8_t u8_t; +typedef int16_t i16_t; +typedef uint16_t u16_t; +typedef int32_t i32_t; +typedef uint32_t u32_t; +typedef int64_t i64_t; +typedef uint64_t u64_t; + +typedef char8_t ch8_t; + +typedef size_t sz_t; + +#ifdef is_win +typedef SSIZE_T ssize_t; +#endif + +void read_atmost (void *src, char *rbuf, const size_t nexact, size_t *nread); + +void recv_atmost ( +#ifdef is_unix + int csock, +#elif defined(is_win) + SOCKET cosck, +#endif + char *rbuf, const size_t nmost, size_t *nread); + +int32_t read_u8str (const char8_t * const filename, char8_t * const destbuf); + +int32_t read_u8str_sz (const char8_t * const filename, char8_t * const destbuf, size_t *nread); + +void zero_trailing_white_char (char8_t * buf, const size_t len); + +void zero_trailing_white_char2 (char8_t * buf, size_t *len); + + +#ifdef is_unix +FILE *unix_fd2strm_r (int fd); +#endif + +#ifdef is_win +FILE *win_handle2strm (HANDLE h); +#endif + +#ifdef is_win +int win_handle2fd (HANDLE h); +#endif + + +#endif diff --git a/third_party/mcpc/tst/itst-svcalc-req-promptslist-1.json b/third_party/mcpc/tst/itst-svcalc-req-promptslist-1.json new file mode 100644 index 0000000..2431074 --- /dev/null +++ b/third_party/mcpc/tst/itst-svcalc-req-promptslist-1.json @@ -0,0 +1 @@ +{"jsonrpc": "2.0", "method": "initialize", "params": {"clientInfo": {"name": "Llama Agent", "version": "0.1"}, "protocolVersion": "2024-11-05", "capabilities": { "tools": { "subscribe": true, "listChanged": true }, "resource": { "subscribe": true, "listChanged": true } }}, "id": 1}{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}, "id": 8899}{"id":123,"method":"prompts/list","params":[{"obfsarg":"{\"'}}"}]} diff --git a/third_party/mcpc/tst/itst-svcalc-req-resourceslist-1.json b/third_party/mcpc/tst/itst-svcalc-req-resourceslist-1.json new file mode 100644 index 0000000..cf23347 --- /dev/null +++ b/third_party/mcpc/tst/itst-svcalc-req-resourceslist-1.json @@ -0,0 +1 @@ +{"jsonrpc": "2.0", "method": "initialize", "params": {"clientInfo": {"name": "Llama Agent", "version": "0.1"}, "protocolVersion": "2024-11-05", "capabilities": { "tools": { "subscribe": true, "listChanged": true }, "resource": { "subscribe": true, "listChanged": true } }}, "id": 1}{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}, "id": 8899}{"id":123,"method":"resources/list","params":[{"obfsarg":"{\"'}}"}]} diff --git a/third_party/mcpc/tst/itst-svcalc-req-toolslist-1.json b/third_party/mcpc/tst/itst-svcalc-req-toolslist-1.json new file mode 100644 index 0000000..97be6cf --- /dev/null +++ b/third_party/mcpc/tst/itst-svcalc-req-toolslist-1.json @@ -0,0 +1 @@ +{"jsonrpc": "2.0", "method": "initialize", "params": {"clientInfo": {"name": "Llama Agent", "version": "0.1"}, "protocolVersion": "2024-11-05", "capabilities": { "tools": { "subscribe": true, "listChanged": true }, "resource": { "subscribe": true, "listChanged": true } }}, "id": 1}{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}, "id": 8899}{"id":123,"method":"tools/list","params":[{"obfsarg":"{\"'}}"}]} diff --git a/third_party/mcpc/tst/itst-svcalc.c b/third_party/mcpc/tst/itst-svcalc.c new file mode 100644 index 0000000..3932991 --- /dev/null +++ b/third_party/mcpc/tst/itst-svcalc.c @@ -0,0 +1,207 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +typedef int8_t i8_t; +typedef uint8_t u8_t; +typedef int16_t i16_t; +typedef uint16_t u16_t; +typedef int32_t i32_t; +typedef uint32_t u32_t; +typedef int64_t i64_t; +typedef uint64_t u64_t; + +static void +cb_calc (const mcpc_tool_t *tool, mcpc_ucbr_t *ucbr) +{ + i32_t a = 0; + i32_t b = 0; + char8_t op[64]; + i32_t res = 0; + + assert (0 == mcpc_tool_get_tpropval_i32 (tool, u8c1 ("a"), &a)); + assert (0 == mcpc_tool_get_tpropval_i32 (tool, u8c1 ("b"), &b)); + assert (0 == mcpc_tool_get_tpropval_u8str (tool, u8c1 ("op"), op, sizeof (op), nullptr)); + + if (false) + ; + else if (u8streq (op, u8c1 ("+"))) + { + res = a + b; + } + else if (u8streq (op, u8c1 ("+"))) + { + res = a + b; + } + else if (u8streq (op, u8c1 ("-"))) + { + res = a - b; + } + else if (u8streq (op, u8c1 ("*"))) + { + res = a * b; + } + else if (u8streq (op, u8c1 ("times"))) + { + res = a * b; + } + else if (u8streq (op, u8c1 ("/"))) + { + res = a / b; + } + else if (u8streq (op, u8c1 ("div"))) + { + res = a / b; + } + else + { + mcpc_ucbr_toolcall_add_errmsg_printf8 (ucbr, u8c1 ("not matching \"any\" operator:%s"), op); + return; + } + + mcpc_ucbr_toolcall_add_text_printf8 (ucbr, u8c1 ("%d"), res); +} + +mcpc_tool_t * +new_tool_calc () +{ + const char8_t *name = u8c1 ("calc"); + const char8_t *desc = u8c1 ("simple calculator"); + mcpc_tool_t *tool = mcpc_tool_new2 (name, desc); + + { + const char8_t *name = u8c1 ("a"); + const mcpc_anytype_t type = MCPC_I32; + const char8_t *desc = u8c1 ("the first number(\"a\") to calculate"); + mcpc_toolprop_t *prop = mcpc_toolprop_new2 (name, desc, type); + mcpc_tool_add_toolprop (tool, prop); + } + { + const char8_t *name = u8c1 ("b"); + const mcpc_anytype_t type = MCPC_I32; + const char8_t *desc = u8c1 ("the second number to calculate"); + mcpc_toolprop_t *prop = mcpc_toolprop_new2 (name, desc, type); + mcpc_tool_add_toolprop (tool, prop); + } + { + const char8_t *name = u8c1 ("op"); + const mcpc_anytype_t type = MCPC_U8STR; + const char8_t *desc = // + u8c1 ("the calculating operator, available values " "are: \"+\",'-',\"*\",'/'"); + mcpc_toolprop_t *prop = mcpc_toolprop_new2 (name, desc, type); + mcpc_tool_add_toolprop (tool, prop); + } + + mcpc_tool_set_call_cb (tool, &cb_calc); + + return tool; +} + +int +main_iostrm (int argc, const char *argv[]) +{ + u8_t in_src = 0; // 1stdin 2file + char in_fpath[100]; + + for (int i = 2; i < argc; i++) + { + const char8_t *curr_arg = (const char8_t *) argv[i]; + const char8_t *nex_arg = nullptr; + if (i < argc - 1) + nex_arg = (const char8_t *) argv[i + 1]; + if (nex_arg != nullptr) + { + if (u8streq (curr_arg, u8c1 ("-i"))) + { + if (u8streq (nex_arg, u8c1 ("-"))) + { + in_src = 1; + } + else if (beg_with_alph ((const char8_t *) nex_arg)) + { + // TODO nonascii filename? + /* memcpy (in_fpath, nex_arg, strlen (nex_arg)); */ + strcpy (in_fpath, (const char *) nex_arg); + in_src = 2; + } + } + } + } + + assert (in_src); + + FILE *in_stream = nullptr; + switch (in_src) + { + case 1: + in_stream = stdin; + break; + case 2: + in_stream = fopen (in_fpath, "r"); + if (!in_stream) + { + fprintf (stdout, "file:%s, err:%s", in_fpath, strerror (errno)); + } + break; + } + assert (in_stream); + + mcpc_server_t *server = mcpc_server_new_iostrm (in_stream, stdout); + mcpc_server_capa_enable_prmt (server); + mcpc_server_capa_enable_tool (server); + mcpc_server_capa_enable_rsc (server); + mcpc_server_capa_enable_complt (server); + + mcpc_tool_t *tool = new_tool_calc (); + assert (0 == mcpc_server_add_tool (server, tool)); + + mcpc_errcode_t ec = mcpc_server_start (server); + + mcpc_server_close (server); + fclose (in_stream); + + return ec; +} + +int +main_tcp (int argc, const char *argv[]) +{ + mcpc_server_t *server = mcpc_server_new_tcp (); + mcpc_server_capa_enable_prmt (server); + mcpc_server_capa_enable_tool (server); + mcpc_server_capa_enable_rsc (server); + mcpc_server_capa_enable_complt (server); + + mcpc_tool_t *tool = new_tool_calc (); + assert (0 == mcpc_server_add_tool (server, tool)); + + mcpc_errcode_t ec = mcpc_server_start (server); + + mcpc_server_close (server); + return ec; +} + +int +main (int argc, const char *argv[]) +{ + assert (argc >= 2); + bool as_iostrm = strcmp (argv[1], "iostrm") == 0; + bool as_tcp = strcmp (argv[1], "tcp") == 0; + assert (as_iostrm || as_tcp); + // bool as_iostrm = false; + // bool as_tcp = true; + if (as_tcp) + return main_tcp (argc, argv); + if (as_iostrm) + return main_iostrm (argc, argv); +} -- cgit v1.2.3