)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"ee4ea8efe88d54088222183f1039cbb02efd6cfd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"633589f1_d2595723","updated":"2026-03-24 12:12:10.000000000","message":"Thank you for the patch!\n\nUnfortunately there is a minor issue with the current approach -- the port number is duplicated. IMHO this makes the code more complex since these two values need to be kept consistent.\n\nMoreover, the solution does not scale well to the other services (telnet, etc.) since such services are not associated with a target.\n\nIMHO it breaks the object model a little: the port is a property of the service, not a property of the target.\n\nPlease consider an alternative solution -- an `service info` command that will report service independent parameters (`name`, `port`, etc.) from `struct service` and call a `service_driver`-specific helper for `service_driver`-specific info (e.g. target name for a `gdb` service) for each service from the `services` list in `server/server.c`.\nI\u0027d suggest for it to return a list of Tcl-dict-like strings (e.g. \"{{name gdb port 4444 ... gdb.target target1} {name gdb port 4445 ... gdb.target target2} ...}\".\nThis can be guarded by an option (like Git\u0027s `--porcelain`) and by default the command can return a more human-readable output.\nThe idea is similar to `riscv info` command (see `handle_info()` and `riscv013_print_info()`).\n\nIMHO this will be a much more scalable and maintainable solution, though it will require iterating over the list of services to get the port number.\n\nPlease let me know what you think","commit_id":"2418359158b45f8c1edacb0715be89268a85eff6"},{"author":{"_account_id":1002502,"name":"Tim Hutt","email":"tdhutt@gmail.com","username":"Timmmm"},"change_message_id":"d9dd12720b90529fe74d14093d87a51251f75dcd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"1e247e3f_41347a8d","in_reply_to":"633589f1_d2595723","updated":"2026-03-26 10:30:38.000000000","message":"Updated! That was not too hard actually. I called the command \u0027services\u0027, and it just always outputs TCL code rather than having a --porcelain flag - that seemed simpler and it\u0027s not difficult to read anyway.\n\nIf this is ok I\u0027ll update the documentation.","commit_id":"2418359158b45f8c1edacb0715be89268a85eff6"}],"src/helper/command.c":[{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":1375,"context_line":"\t*dst++ \u003d \u0027\"\u0027;"},{"line_number":1376,"context_line":""},{"line_number":1377,"context_line":"\twhile (*src !\u003d \u0027\\0\u0027) {"},{"line_number":1378,"context_line":"\t\tif (*src \u003d\u003d \u0027[\u0027 || *src \u003d\u003d \u0027$\u0027 || *src \u003d\u003d \u0027\"\u0027 || *src \u003d\u003d \u0027\\\\\u0027)"},{"line_number":1379,"context_line":"\t\t\t*dst++ \u003d \u0027\\\\\u0027;"},{"line_number":1380,"context_line":"\t\t*dst++ \u003d *src++;"},{"line_number":1381,"context_line":"\t}"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"2c466d18_e51e54f5","line":1378,"updated":"2026-03-30 13:27:31.000000000","message":"If you like:\n```\nif (strchr(\"[$\\\"\\\\], *src)\n```","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"}],"src/helper/command.h":[{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":541,"context_line":" * escaping a few character. Returns a newly allocated string or"},{"line_number":542,"context_line":" * NULL on OOM. src cannot be NULL."},{"line_number":543,"context_line":" */"},{"line_number":544,"context_line":"char *tcl_escape(const char *src);"},{"line_number":545,"context_line":""},{"line_number":546,"context_line":"#endif /* OPENOCD_HELPER_COMMAND_H */"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"23daae4e_6f01d704","line":544,"updated":"2026-03-30 13:27:31.000000000","message":"Please, mention the fact that the function allocates memory in the name.\nPerhaps something like:\n```\ntcl_escape_alloc(...)\n```","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"}],"src/server/server.c":[{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":832,"context_line":"{"},{"line_number":833,"context_line":"\tswitch (CMD_ARGC) {"},{"line_number":834,"context_line":"\tcase 0:"},{"line_number":835,"context_line":"\t\tcommand_print(CMD, \"{\");"},{"line_number":836,"context_line":"\t\tfor (struct service *s \u003d services; s; s \u003d s-\u003enext) {"},{"line_number":837,"context_line":"\t\t\tstruct sockaddr_in addr_in;"},{"line_number":838,"context_line":"\t\t\taddr_in.sin_port \u003d 0;"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"3fabbdcb_36e3d859","line":835,"updated":"2026-03-30 13:27:31.000000000","message":"You don\u0027t need the outermost \u0027{\u0027/\u0027}\u0027. With the current implementation:\n```\n\u003e openocd \\\n  -c \u0027adapter driver dummy\u0027 \\\n  -c \u0027proc jtag_init {} {}\u0027 \\\n  -c init \\\n  -c \u0027after 100 {echo [lindex [services] 0]; shutdown};\u0027 \\\n  -d0\nOpen On-Chip Debugger 0.12.0+dev-04007-ged461f4b8 (2026-03-30-13:01)\nLicensed under GNU GPL v2\nFor bug reports, read\n\thttp://openocd.org/doc/doxygen/bugs.html\njtag_init\nafter#1\n\n  {name {tcl} port \"6666\" }\n  {name {telnet} port \"4444\" }\n\nshutdown command invoked\n```\nI\u0027d expect:\n```\nOpen On-Chip Debugger 0.12.0+dev-04007-ged461f4b8 (2026-03-30-13:01)\nLicensed under GNU GPL v2\nFor bug reports, read\n\thttp://openocd.org/doc/doxygen/bugs.html\njtag_init\nafter#1\nname {tcl} port \"6666\"\nshutdown command invoked\n```","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":833,"context_line":"\tswitch (CMD_ARGC) {"},{"line_number":834,"context_line":"\tcase 0:"},{"line_number":835,"context_line":"\t\tcommand_print(CMD, \"{\");"},{"line_number":836,"context_line":"\t\tfor (struct service *s \u003d services; s; s \u003d s-\u003enext) {"},{"line_number":837,"context_line":"\t\t\tstruct sockaddr_in addr_in;"},{"line_number":838,"context_line":"\t\t\taddr_in.sin_port \u003d 0;"},{"line_number":839,"context_line":"\t\t\tsocklen_t addr_in_size \u003d sizeof(addr_in);"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"1535b503_b081abb1","line":836,"updated":"2026-03-30 13:27:31.000000000","message":"Please, consider making the service pointer constant.","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":842,"context_line":"\t\t\t\ts-\u003eportnumber \u003d\u003d 0 \u0026\u0026"},{"line_number":843,"context_line":"\t\t\t\tgetsockname(s-\u003efd, (struct sockaddr *)\u0026addr_in, \u0026addr_in_size) \u003d\u003d 0) {"},{"line_number":844,"context_line":"\t\t\t\t/* Note this assumes the name doesn\u0027t contain { or } which is currently the case. */"},{"line_number":845,"context_line":"\t\t\t\tcommand_print_sameline(CMD, \"  {name {%s} port %hu \", s-\u003ename, ntohs(addr_in.sin_port));"},{"line_number":846,"context_line":"\t\t\t} else {"},{"line_number":847,"context_line":"\t\t\t\t/* Need to escape port because it could be a FIFO path which is"},{"line_number":848,"context_line":"\t\t\t\t\t* allowed to contain basically any character. */"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"6ee5608f_4b3dd4cc","line":845,"updated":"2026-03-30 13:27:31.000000000","message":"AFAIU, you don\u0027t need `getsockname()`, you can just do `ntohs(c-\u003esin.sin_port)`.\nAlso, I\u0027d suggest to report the fields of the `service` as-is, without much logic, preserving the names of the fields (mentioning that the output of the command is version-dependent in the docs).\nIMHO this will be much clearer to the end user.","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":848,"context_line":"\t\t\t\t\t* allowed to contain basically any character. */"},{"line_number":849,"context_line":"\t\t\t\tchar *port \u003d tcl_escape(s-\u003eport);"},{"line_number":850,"context_line":"\t\t\t\tif (!port) {"},{"line_number":851,"context_line":"\t\t\t\t\tLOG_ERROR(\"Unable to escape TCL string\");"},{"line_number":852,"context_line":"\t\t\t\t\treturn ERROR_FAIL;"},{"line_number":853,"context_line":"\t\t\t\t}"},{"line_number":854,"context_line":"\t\t\t\tcommand_print_sameline(CMD, \"  {name {%s} port %s \", s-\u003ename, port);"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"aec6b612_cb2038f5","line":851,"updated":"2026-03-30 13:27:31.000000000","message":"[nitpick]\nIt\u0027s Tcl, not TCL.\n\nAlso, please use `command_print` for reporting an error in a command handler.\n\nThe last line printed via `command_print()` or `command_print_sameline()` becomes the result of the execution. If the error code is non-zero, this result is considered an error message.","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"be9d5505e1c52bc5938afa3e6a3792a704aeca76","unresolved":true,"context_lines":[{"line_number":848,"context_line":"\t\t\t\t\t* allowed to contain basically any character. */"},{"line_number":849,"context_line":"\t\t\t\tchar *port \u003d tcl_escape(s-\u003eport);"},{"line_number":850,"context_line":"\t\t\t\tif (!port) {"},{"line_number":851,"context_line":"\t\t\t\t\tLOG_ERROR(\"Unable to escape TCL string\");"},{"line_number":852,"context_line":"\t\t\t\t\treturn ERROR_FAIL;"},{"line_number":853,"context_line":"\t\t\t\t}"},{"line_number":854,"context_line":"\t\t\t\tcommand_print_sameline(CMD, \"  {name {%s} port %s \", s-\u003ename, port);"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"0266fdaa_6d9cff27","line":851,"in_reply_to":"aec6b612_cb2038f5","updated":"2026-03-30 13:47:12.000000000","message":"Correction: it\u0027s not the last line, it\u0027s all the output except for the last newline character (if present).","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":855,"context_line":"\t\t\t\tfree(port);"},{"line_number":856,"context_line":"\t\t\t}"},{"line_number":857,"context_line":"\t\t\tif (s-\u003eservice_info)"},{"line_number":858,"context_line":"\t\t\t\ts-\u003eservice_info(CMD, s);"},{"line_number":859,"context_line":"\t\t\tcommand_print(CMD, \"}\");"},{"line_number":860,"context_line":"\t\t}"},{"line_number":861,"context_line":"\t\tcommand_print(CMD, \"}\");"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"6af6170d_bc329487","line":858,"updated":"2026-03-30 13:27:31.000000000","message":"Please, use `CALL_COMMAND_HANDLER` macro.","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"},{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":861,"context_line":"\t\tcommand_print(CMD, \"}\");"},{"line_number":862,"context_line":"\t\tbreak;"},{"line_number":863,"context_line":"\tdefault:"},{"line_number":864,"context_line":"\t\treturn ERROR_COMMAND_SYNTAX_ERROR;"},{"line_number":865,"context_line":"\t}"},{"line_number":866,"context_line":"\treturn ERROR_OK;"},{"line_number":867,"context_line":"}"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"7188bed6_75036478","line":864,"updated":"2026-03-30 13:27:31.000000000","message":"Wouldn\u0027t an early-exit:\n```\nif (CMD_ARGC \u003e 0)\n    return ERROR_COMMAND_SYNTAX_ERROR;\n```\nbe more convenient?","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"}],"src/server/server.h":[{"author":{"_account_id":1002047,"name":"Evgeniy Naydanov","email":"eugnay@gmail.com","username":"en-sc"},"change_message_id":"093345938d44bd3ceeff0a11ed856f44c9a1be2d","unresolved":true,"context_lines":[{"line_number":85,"context_line":"\tint (*new_connection)(struct connection *connection);"},{"line_number":86,"context_line":"\tint (*input)(struct connection *connection);"},{"line_number":87,"context_line":"\tvoid (*service_dtor)(struct service *service);"},{"line_number":88,"context_line":"\tvoid (*service_info)(struct command_invocation *cmd, struct service *service);"},{"line_number":89,"context_line":"\tint (*connection_closed)(struct connection *connection);"},{"line_number":90,"context_line":"\tvoid (*keep_client_alive)(struct connection *connection);"},{"line_number":91,"context_line":"\tvoid *priv;"}],"source_content_type":"text/x-csrc","patch_set":3,"id":"337d1d3a_552c7816","line":88,"updated":"2026-03-30 13:27:31.000000000","message":"```\nCOMMAND_HELPER((*service_info), const struct service* service);\n```","commit_id":"ed461f4b891d25da02f4c6aa20761c1f3e602169"}]}
