? server/civserver.exe.stackdump ? server/stdinhand.c.new Index: server/console.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/console.c,v retrieving revision 1.10 diff -u -2 -r1.10 console.c --- server/console.c 2001/07/27 23:57:58 1.10 +++ server/console.c 2001/12/29 17:19:40 @@ -26,7 +26,7 @@ #include "log.h" #include "support.h" +#include "plrhand.h" #include "srv_main.h" - #include "console.h" @@ -38,4 +38,82 @@ #endif +#include +#include +#include + +/* can be useful later. maybe. */ +#define L_(Ch) Ch + +/************************************************************************ +Internal function to remove everything but format tokens from a text +string and put the result into another. It is NOT failsafe, but freeciv +authors should know better than to put crap formatting in the game. +stripped should be same size as formatted. Leaves a space at end of +string. - Per +************************************************************************/ +static void con_striptext(const char *formatted, char *stripped) +{ + int i; + while (*formatted != L_('\0')) { + if (*formatted != L_('%')) { + formatted++; /* ignore */ + } else { + /* the TRICKY part follows */ + /* test for %%, which we discard */ + formatted++; + if (*formatted == L_('%')) { + formatted++; + continue; + } + /* start copying token */ + *stripped++ = L_('"'); + *stripped++ = L_('%'); + /* find positional parameter */ + while (isdigit(*formatted)) *stripped++=*formatted++; + /* test for flags */ + i=1; do { + switch(*formatted){ + case L_(' '): + case L_('+'): + case L_('-'): + case L_('#'): + case L_('0'): + case L_('\''): + case L_('I'): + *stripped++=*formatted++; break; + default: + i=0; + } + } while (i); + /* any of the following chars hereafter means we're through */ + /* note that it may well be that we grab some chars that were + not meant to be part of the format info (eg %dkb), but this + doesn't really matter. actually in some cases (like the eg + above) it is a bonus */ + i=1; do { + switch(*formatted){ + case L_(' '): + case L_('\0'): + case L_('%'): + case L_('\n'): + case L_('\r'): + case L_('.'): + case L_(','): + case L_(']'): + case L_(')'): + case L_('?'): + case L_('!'): + i=0; break; + default: + *stripped++=*formatted++; + } + } while (i); + *stripped++ = L_('"'); + *stripped++ = L_(' '); + } + } + *stripped = L_('\0'); +} + /************************************************************************ Function to handle log messages. @@ -66,5 +144,8 @@ } #else - con_dump(C_READY,"> "); + if (console_rfcstyle) + printf("%.d3 > ",C_READY); + else + printf("> "); con_flush(); #endif @@ -83,25 +164,9 @@ /************************************************************************ -Write to console without line-break, don't print prompt. +The real reason for this is because __attribute__ complained +with con_write(C_COMMENT,"") of "warning: zero-length format string" ************************************************************************/ -int con_dump(int i, char *message, ...) -{ - static char buf[MAX_LEN_CONSOLE_LINE]; - va_list args; - - va_start(args, message); - my_vsnprintf(buf, sizeof(buf), message, args); - va_end(args); - - if(console_prompt_is_showing) { - printf("\n"); - } - if ((console_rfcstyle) && (i >= 0)) { - printf("%.3d %s", i, buf); - } else { - printf("%s", buf); - } - console_prompt_is_showing = 0; - return (int) strlen(buf); +void con_newline() { + if (!console_rfcstyle) putchar('\n'); } @@ -109,52 +174,75 @@ Write to console and add line-break, and show prompt if required. ************************************************************************/ -void con_write(int i, char *message, ...) +void con_write(int i, const char *message, ...) { - static char buf[MAX_LEN_CONSOLE_LINE]; va_list args; - va_start(args, message); - my_vsnprintf(buf, sizeof(buf), message, args); + con_output(i,NULL,NULL,NULL,message,args); va_end(args); - - con_puts(i, buf); } /************************************************************************ -Write to console and add line-break, and show prompt if required. -Same as con_write, but without the format string stuff. -The real reason for this is because __attribute__ complained -with con_write(C_COMMENT,"") of "warning: zero-length format string"; -this allows con_puts(C_COMMENT,""); +Console output function - do not nest formatted strings! If caller is not +NULL then cmdname MUST be set. ************************************************************************/ -void con_puts(int i, char *str) +void con_output(int i, struct connection *caller, const char *prefix, + const char *cmdname, const char *message, va_list args) { - if(console_prompt_is_showing) { - printf("\n"); + char buf1[MAX_LEN_CONSOLE_OUT]; + char buf2[MAX_LEN_CONSOLE_OUT]; + char *c0,*c1,*c2; + char bufpreprefix[5]; + + assert(message&&args); + + if ((console_rfcstyle) && (i <= 0)) + return; + + if (console_prompt_is_showing) { + putchar('\n'); } - if ((console_rfcstyle) && (i >= 0)) { - printf("%.3d %s\n", i, str); + + /* ensure sanity */ + if (!prefix) + prefix=""; + + /* prepare string */ + c1 = buf1; c2 = buf2; + mystrlcpy(buf1,message,sizeof(buf1)); /* local copy in buf1 */ + if (console_rfcstyle) { + con_striptext(c1,c2); /* strip unnecessary text */ + my_vsnprintf(buf1,sizeof(buf1),c2,args); /* expand args into buf1 */ + c0 = c1; + my_snprintf(bufpreprefix, sizeof(bufpreprefix), "%.3d ", i); + /* c2 points to available buffer */ } else { - printf("%s\n", str); + my_vsnprintf(buf2,sizeof(buf2),c1,args); /* expand args into buf2 */ + c0 = c2; + c2 = c1; /* buf1 is available buffer, point there */ + bufpreprefix[0] = L_('\0'); } - console_prompt_is_showing = 0; - con_update_prompt(); -} -/************************************************************************ -For rfc-specific information only. -Adds line-break, and shows prompt if required. -************************************************************************/ -void con_rfconly(int i, char *message, ...) -{ - static char buf[MAX_LEN_CONSOLE_LINE]; - va_list args; - - va_start(args, message); - my_vsnprintf(buf, sizeof(buf), message, args); - va_end(args); - - if ((console_rfcstyle) && (i >= 0)) - printf("%.3d %s\n", i, buf); + /* print any multiple lines except last */ + while ((c1=strstr(c0, "\n"))) { + *c1 = '\0'; + if (caller) { + assert(cmdname); + assert(*cmdname); + notify_conn(&caller->self, "/%s: %s%s", cmdname, prefix, c0); + } else { + if (c0!=message) + printf("%s%s\n", bufpreprefix, c0); + else + printf("%s%s%s\n", bufpreprefix, prefix, c0); + } + c0 = c1+1; + } + + /* print last line */ + if (c0!=message) + printf("%s%s\n", bufpreprefix, c0); + else + printf("%s%s%s\n", bufpreprefix, prefix, c0); + console_prompt_is_showing = 0; con_update_prompt(); @@ -176,7 +264,7 @@ console_rfcstyle = i; if (console_rfcstyle) - con_puts(C_OK, _("Ok. RFC-style set.")); + con_write(C_OK, _("Ok. RFC-style set.")); else - con_puts(C_OK, _("Ok. Standard style set.")); + con_write(C_OK, _("Ok. Standard style set.")); } @@ -196,6 +284,6 @@ static int first = 1; if (first) { - con_puts(C_COMMENT, ""); - con_puts(C_COMMENT, _("For introductory help, type 'help'.")); + con_newline(); + con_write(C_COMMENT, _("For introductory help, type 'help'.")); first = 0; } Index: server/console.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/console.h,v retrieving revision 1.4 diff -u -2 -r1.4 console.h --- server/console.h 2001/07/27 23:57:58 1.4 +++ server/console.h 2001/12/29 17:19:40 @@ -17,4 +17,5 @@ #define MAX_LEN_CONSOLE_LINE 512 +#define MAX_LEN_CONSOLE_OUT 4096 /* closing \0 included */ #define C_IGNORE -1 /* never print RFC-style number prefix */ @@ -27,4 +28,5 @@ #define C_DISCONNECTED 102 /* client gone */ #define C_REJECTED 103 /* client rejected */ +#define C_LIST 104 /* unbounded list of results from requested operation */ #define C_FAIL 200 /* failure of requested operation */ #define C_METAERROR 201 /* failure of meta server */ @@ -35,22 +37,23 @@ #define C_READY 999 /* waiting for input */ +struct connection; /* kill warning */ + /* initialize logging via console */ void con_log_init(char *log_message, int log_level); -/* write to console without line-break, don't print prompt */ -int con_dump(int i, char *message, ...) - fc__attribute((format (printf, 2, 3))); - /* write to console and add line-break, and show prompt if required. */ -void con_write(int i, char *message, ...) +void con_write(int i, const char *message, ...) fc__attribute((format (printf, 2, 3))); + +/* main output function - normally you will want to use con_write */ +void con_output(int i, struct connection *caller, const char *prefix, + const char *cmdname, const char *message, va_list args); -/* write to console and add line-break, and show prompt if required. - ie, same as con_write, but without the format string stuff. */ -void con_puts(int i, char *str); - /* ensure timely update */ void con_flush(void); +/* make empty newline; do NOT use con_write(,"") to achieve this */ +void coid_newline(void); + /* initialize prompt; display initial message */ void con_prompt_init(void); @@ -73,8 +76,4 @@ /* return rfc-style */ int con_get_style(void); - -/* for rfc-specific information only */ -void con_rfconly(int i, char *message, ...) - fc__attribute((format (printf, 2, 3))); #endif /* FC__CONSOLE_H */ Index: server/meta.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/meta.c,v retrieving revision 1.39 diff -u -2 -r1.39 meta.c --- server/meta.c 2001/12/11 16:16:47 1.39 +++ server/meta.c 2001/12/29 17:19:40 @@ -183,5 +183,5 @@ static void metaserver_failed(void) { - con_puts(C_METAERROR, _("Not reporting to the metaserver in this game.")); + con_write(C_METAERROR, _("Not reporting to the metaserver in this game.")); con_flush(); } Index: server/srv_main.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v retrieving revision 1.54 diff -u -2 -r1.54 srv_main.c --- server/srv_main.c 2001/12/09 15:50:52 1.54 +++ server/srv_main.c 2001/12/29 17:19:42 @@ -515,9 +515,9 @@ { if(server_state!=PRE_GAME_STATE) { - con_puts(C_SYNTAX, _("The game is already running.")); + con_write(C_SYNTAX, _("The game is already running.")); return; } - con_puts(C_OK, _("Starting game.")); + con_write(C_OK, _("Starting game.")); server_state=SELECT_RACES_STATE; /* loaded ??? */ @@ -1767,14 +1767,14 @@ #ifdef GENERATING_MAC /* mac beta notice */ - con_puts(C_COMMENT, ""); - con_puts(C_COMMENT, "This is an alpha/beta version of MacFreeciv."); - con_puts(C_COMMENT, "Visit http://www.geocities.com/SiliconValley/Orchard/8738/MFC/index.html"); - con_puts(C_COMMENT, "for new versions of this project and information about it."); - con_puts(C_COMMENT, ""); + con_newline(); + con_write(C_COMMENT, "This is an alpha/beta version of MacFreeciv."); + con_write(C_COMMENT, "Visit http://www.geocities.com/SiliconValley/Orchard/8738/MFC/index.html"); + con_write(C_COMMENT, "for new versions of this project and information about it."); + con_newline(); #endif #if IS_BETA_VERSION - con_puts(C_COMMENT, ""); - con_puts(C_COMMENT, beta_message()); - con_puts(C_COMMENT, ""); + con_newline(); + con_write(C_COMMENT, beta_message()); + con_newline(); #endif Index: server/stdinhand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v retrieving revision 1.197 diff -u -2 -r1.197 stdinhand.c --- server/stdinhand.c 2001/12/13 19:13:17 1.197 +++ server/stdinhand.c 2001/12/29 17:19:44 @@ -57,5 +57,4 @@ #include "stdinhand.h" - static enum cmdlevel_id default_access_level = ALLOW_INFO; static enum cmdlevel_id first_access_level = ALLOW_INFO; @@ -1348,50 +1347,4 @@ /************************************************************************** - feedback related to server commands - caller == NULL means console. - No longer duplicate all output to console. - 'console_id' should be one of the C_ identifiers in console.h - - This lowlevel function takes a single line; prefix is prepended to line. -**************************************************************************/ -static void cmd_reply_line(enum command_id cmd, struct connection *caller, - int console_id, const char *prefix, const char *line) -{ - char *cmdname = cmd < CMD_NUM ? commands[cmd].name : - cmd == CMD_AMBIGUOUS ? _("(ambiguous)") : - cmd == CMD_UNRECOGNIZED ? _("(unknown)") : - "(?!?)"; /* this case is a bug! */ - - if (caller) { - notify_conn(&caller->self, "/%s: %s%s", cmdname, prefix, line); - /* cc: to the console - testing has proved it's too verbose - rp - con_write(console_id, "%s/%s: %s%s", caller->name, cmdname, prefix, line); - */ - } else { - con_write(console_id, "%s%s", prefix, line); - } -} -/************************************************************************** - va_list version which allow embedded newlines, and each line is sent - separately. 'prefix' is prepended to every line _after_ the first line. -**************************************************************************/ -static void vcmd_reply_prefix(enum command_id cmd, struct connection *caller, - int console_id, const char *prefix, - const char *format, va_list ap) -{ - char buf[4096]; - char *c0, *c1; - - my_vsnprintf(buf, sizeof(buf), format, ap); - - c0 = buf; - while ((c1=strstr(c0, "\n"))) { - *c1 = '\0'; - cmd_reply_line(cmd, caller, console_id, (c0==buf?"":prefix), c0); - c0 = c1+1; - } - cmd_reply_line(cmd, caller, console_id, (c0==buf?"":prefix), c0); -} -/************************************************************************** var-args version of above duplicate declaration required for attribute to work... @@ -1405,7 +1358,12 @@ const char *format, ...) { + char *cmdname = cmd < CMD_NUM ? commands[cmd].name : \ + cmd == CMD_AMBIGUOUS ? _("(ambiguous)") : \ + cmd == CMD_UNRECOGNIZED ? _("(unknown)") : \ + "(?!?)"; /* this case is a bug! */ + va_list ap; va_start(ap, format); - vcmd_reply_prefix(cmd, caller, console_id, prefix, format, ap); + con_output(console_id, caller, prefix, cmdname, format, ap); va_end(ap); } @@ -1419,7 +1377,12 @@ int console_id, const char *format, ...) { + char *cmdname = cmd < CMD_NUM ? commands[cmd].name : \ + cmd == CMD_AMBIGUOUS ? _("(ambiguous)") : \ + cmd == CMD_UNRECOGNIZED ? _("(unknown)") : \ + "(?!?)"; /* this case is a bug! */ + va_list ap; va_start(ap, format); - vcmd_reply_prefix(cmd, caller, console_id, "", format, ap); + con_output(console_id, caller, NULL, cmdname, format, ap); va_end(ap); } @@ -2119,12 +2082,12 @@ conn_list_iterate(game.est_connections, pconn) { - cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT, "cmdlevel %s %s", + cmd_reply(CMD_CMDLEVEL, caller, C_LIST, "cmdlevel %s %s", cmdlevel_name(pconn->access_level), pconn->name); } conn_list_iterate_end; - cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT, + cmd_reply(CMD_CMDLEVEL, caller, C_OK, _("Command access level for new connections: %s"), cmdlevel_name(default_access_level)); - cmd_reply(CMD_CMDLEVEL, caller, C_COMMENT, + cmd_reply(CMD_CMDLEVEL, caller, C_OK, _("Command access level for first player to take it: %s"), cmdlevel_name(first_access_level)); @@ -2338,8 +2301,8 @@ int i, j; - cmd_reply(help_cmd, caller, C_COMMENT, horiz_line); + cmd_reply(help_cmd, caller, C_IGNORE, horiz_line); cmd_reply(help_cmd, caller, C_COMMENT, _("Explanations are available for the following server options:")); - cmd_reply(help_cmd, caller, C_COMMENT, horiz_line); + cmd_reply(help_cmd, caller, C_IGNORE, horiz_line); if(caller == NULL && con_get_style()) { for (i=0; settings[i].name; i++) { @@ -2361,5 +2324,5 @@ cmd_reply(help_cmd, caller, C_COMMENT, buf); } - cmd_reply(help_cmd, caller, C_COMMENT, horiz_line); + cmd_reply(help_cmd, caller, C_IGNORE, horiz_line); } @@ -3271,6 +3234,5 @@ void show_players(struct connection *caller) { - char buf[MAX_LEN_CONSOLE_LINE], buf2[MAX_LEN_CONSOLE_LINE]; - int i, n; + int i, n, realname=1; cmd_reply(CMD_LIST, caller, C_COMMENT, _("List of players:")); @@ -3290,8 +3252,4 @@ } - /* buf2 contains stuff in brackets after playername: - * [username,] AI/Barbarian/Human [,Dead] [, skill level] [, nation] - */ - buf2[0] = '\0'; if (strlen(pplayer->username) > 0 && strcmp(pplayer->name, pplayer->username) != 0 @@ -3300,50 +3258,40 @@ * civil war leaders - old savegames may contain "UserName"... */ - my_snprintf(buf2, sizeof(buf2), _("username %s, "), pplayer->username); - } - - if (is_barbarian(pplayer)) { - sz_strlcat(buf2, _("Barbarian")); - } else if (pplayer->ai.control) { - sz_strlcat(buf2, _("AI")); - } else { - sz_strlcat(buf2, _("Human")); - } - if (!pplayer->is_alive) { - sz_strlcat(buf2, _(", Dead")); - } - if(pplayer->ai.control) { - cat_snprintf(buf2, sizeof(buf2), _(", difficulty level %s"), - name_of_skill_level(pplayer->ai.skill_level)); + realname = 0; /* use pplayer->username instead */ } - if (!game.is_new_game) { - cat_snprintf(buf2, sizeof(buf2), _(", nation %s"), - get_nation_name_plural(pplayer->nation)); - } - my_snprintf(buf, sizeof(buf), "%s (%s)", pplayer->name, buf2); - + n = conn_list_size(&pplayer->connections); - if (n==1) { - sz_strlcat(buf, _(" 1 connection:")); - } else if (n>1) { - cat_snprintf(buf, sizeof(buf), _(" %d connections:"), n); - } - cmd_reply(CMD_LIST, caller, C_COMMENT, "%s", buf); - + if (is_barbarian(pplayer)) /* Barbarian */ + cmd_reply(CMD_LIST, caller, C_OK, + _("%s (%s, difficulty level %s, nation %s, state %s)"), + realname?pplayer->name:pplayer->username,_("Barbarian"), + name_of_skill_level(pplayer->ai.skill_level), + game.is_new_game?_("n/a"):get_nation_name_plural(pplayer->nation), + pplayer->is_alive?_("Alive"):_("Dead")); + else if (!pplayer->ai.control) /* Human */ + cmd_reply(CMD_LIST, caller, C_OK, + _("%s (%s, nation %s, state %s) %d connections:"), + realname?pplayer->name:pplayer->username,_("Human"), + game.is_new_game?_("n/a"):get_nation_name_plural(pplayer->nation), + pplayer->is_alive?_("Alive"):_("Dead"),n); + else /* AI */ + cmd_reply(CMD_LIST, caller, C_OK, + _("%s (%s, difficulty level %s, nation %s, state %s)"), + realname?pplayer->name:pplayer->username,_("AI"), + name_of_skill_level(pplayer->ai.skill_level), + game.is_new_game?_("n/a"):get_nation_name_plural(pplayer->nation), + pplayer->is_alive?_("Alive"):_("Dead")); + conn_list_iterate(pplayer->connections, pconn) { - my_snprintf(buf, sizeof(buf), - _(" %s from %s (command access level %s), bufsize=%dkb"), - pconn->name, pconn->addr, - cmdlevel_name(pconn->access_level), - (pconn->send_buffer->nsize>>10)); - if (pconn->observer) { - sz_strlcat(buf, _(" (observer mode)")); - } - cmd_reply(CMD_LIST, caller, C_COMMENT, "%s", buf); + cmd_reply(CMD_LIST, caller, C_LIST, + _(" %s from %s (command access level %s), bufsize=%dkb %s"), + pconn->name, pconn->addr, cmdlevel_name(pconn->access_level), + pconn->send_buffer->nsize>>10, + pconn->observer?_(" (observer mode)"):" "); } conn_list_iterate_end; } } - cmd_reply(CMD_LIST, caller, C_COMMENT, horiz_line); + cmd_reply(CMD_LIST, caller, C_IGNORE, horiz_line); } @@ -3356,5 +3304,5 @@ cmd_reply(CMD_LIST, caller, C_COMMENT, _("List of connections to server:")); - cmd_reply(CMD_LIST, caller, C_COMMENT, horiz_line); + cmd_reply(CMD_LIST, caller, C_IGNORE, horiz_line); if (conn_list_size(&game.all_connections) == 0) { @@ -3372,5 +3320,5 @@ conn_list_iterate_end; } - cmd_reply(CMD_LIST, caller, C_COMMENT, horiz_line); + cmd_reply(CMD_LIST, caller, C_IGNORE, horiz_line); }