send_to_charf, Take 2

From: George Greer (greerga@circlemud.org)
Date: 07/09/01


This was originally sent to the internal CircleMUD developer's list but I
figured people may want to comment on it. Let's see if it's under 200 lines.
-----

Apparently the format and arguments for a varargs function need not be
contiguous so we can make send_to_*() friends both backwards compatible and
accept multiple arguments. The style will run contrary to ever other
varargs function, such as sprintf, though.

diff -u -p -r1.20 act.comm.c
--- act.comm.c  2001/05/18 15:47:37     1.20
+++ act.comm.c  2001/07/07 19:21:30
@@ -45,15 +45,13 @@ ACMD(do_say)
   if (!*argument)
     send_to_char("Yes, but WHAT do you want to say?\r\n", ch);
   else {
-    sprintf(buf, "$n says, '%s'", argument);
-    act(buf, FALSE, ch, 0, 0, TO_ROOM);
+    act("$n says, '%s'", FALSE, ch, 0, 0, TO_ROOM, argument);

     if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
       send_to_char(OK, ch);
     else {
       delete_doubledollar(argument);
-      sprintf(buf, "You say, '%s'\r\n", argument);
-      send_to_char(buf, ch);
+      send_to_char("You say, '%s'\r\n", ch, argument);
     }
   }
 }

//// The prototype

-void   send_to_char(const char *messg, struct char_data *ch);
+void   send_to_char(const char *messg, struct char_data *ch, ...)
+       __attribute__((format (printf, 1, 3)));

//// The implementation

-void send_to_char(const char *messg, struct char_data *ch)
+void send_to_char(const char *messg, struct char_data *ch, ...)
 {
-  if (ch->desc && messg)
-    SEND_TO_Q(messg, ch->desc);
+  if (ch->desc && messg && *messg) {
+    va_list args;
+
+    va_start(args, messg);
+    SEND_TO_Q(ch->desc, messg, args);
+    va_end(args);
+  }
 }

//// The "meat" change

 /* Add a new string to a player's output queue */
-void write_to_output(const char *txt, struct descriptor_data *t)
+void write_to_output(const char *fmt, struct descriptor_data *t, ...)
 {
+  static txt[MAX_STRING_LENGTH];
+  va_list args;
   int size;

   /* if we're in the overflow state already, ignore this new output */
   if (t->bufptr < 0)
     return;

+  va_start(args, fmt);
+  vsnprintf(txt, sizeof(txt), fmt, args);
+  va_end(args);
+
   size = strlen(txt);

////

You'll notice I left the 'txt' static.  That was to preserve the 'spirit'
of the global buffers but avoid their downfall. While that's a good
improvement to have variable arguments and not break the functions, I'd
vote we change the variable ordering instead of leaving the order different
from sprintf().

Compatible:

  send_to_char("%c%s %s\r\n", ch, UPPER(*pers), pers + 1, diagnosis[index].text);

vs. re-ordered:

  send_to_char(ch, "%c%s %s\r\n", UPPER(*pers), pers + 1, diagnosis[index].text);

While we can have 'ch' not be part of the format and still after the text
string, it's rather odd to be there. The only issue becomes act() which
looks rather strange with the text string at the end:

Compatible:

  act("$n says, '%s'", FALSE, ch, 0, 0, TO_ROOM, argument);

vs. re-ordered:

  act(FALSE, ch, 0, 0, TO_ROOM, "$n says, '%s'", argument);

Of course, with proper variable argument support in act() we could try to
get rid of three of those arguments:

  act(FALSE, TO_ROOM, "$n says, '%s'", ch, argument);

--
George Greer
greerga@circlemud.org

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/06/01 PST