Add more G-line length tests. Resolves SF#2985922.
[ircu2.10.12-pk.git] / ircd / s_err.c
index 368df33334a94ce5434eda9a39bbb195ca6fd77f..dc45c2eab768055e98103d27eca55ab7f2986896 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
+ */
+/** @file
+ * @brief Error handling support.
+ * @version $Id$
  */
 #include "config.h"
 
 #include "numeric.h"
+#include "ircd_log.h"
 #include "s_debug.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <string.h>
 
+/** Array of Numeric replies, indexed by numeric. */
 static Numeric replyTable[] = {
 /* 000 */
   { 0 },
@@ -44,15 +48,11 @@ static Numeric replyTable[] = {
 /* 007 */
   { 0 },
 /* 008 */
-  { RPL_SNOMASK, "%d :: Server notice mask (%#x)", "008" },
+  { RPL_SNOMASK, "%u :: Server notice mask (%#x)", "008" },
 /* 009 */
-  { RPL_STATMEMTOT, "%u %u :Bytes Blocks", "009" },
+  { 0 },
 /* 010 */
-#ifdef MEMSIZESTATS
-  { RPL_STATMEM, "%u %u %s %u", "010" },
-#else
-  { RPL_STATMEM, "%u %u %s", "010" },
-#endif
+  { 0 },
 /* 011 */
   { 0 },
 /* 012 */
@@ -62,7 +62,7 @@ static Numeric replyTable[] = {
 /* 014 */
   { 0 },
 /* 015 */
-  { RPL_MAP, ":%s%s%s %s [%i clients]", "015" },
+  { RPL_MAP, ":%s%s%s %s [%u clients]", "015" },
 /* 016 */
   { RPL_MAPMORE, ":%s%s --> *more*", "016" },
 /* 017 */
@@ -92,11 +92,11 @@ static Numeric replyTable[] = {
 /* 029 */
   { 0 },
 /* 030 */
-  { RPL_APASSWARN, ":%s%s%s%s%s", "030" },
+  { RPL_APASSWARN_SET, ":Channel Admin password (+A) set to '%s'.  Are you SURE you want to use this as Admin password? You will NOT be able to change this password anymore once the channel is more than 48 hours old!", "030" },
 /* 031 */
-  { 0 },
+  { RPL_APASSWARN_SECRET, ":Use \"/MODE %s -A %s\" to remove the password and then immediately set a new one.  IMPORTANT: YOU CANNOT RECOVER THIS PASSWORD, EVER; WRITE THE PASSWORD DOWN (don't store this rescue password on disk)! Now set the channel user password (+U).", "031" },
 /* 032 */
-  { 0 },
+  { RPL_APASSWARN_CLEAR, ":WARNING: You removed the channel Admin password (+A). If you disconnect or leave the channel without setting a new password then you will not be able to set it again!  SET A NEW PASSWORD NOW!", "032" },
 /* 033 */
   { 0 },
 /* 034 */
@@ -450,7 +450,7 @@ static Numeric replyTable[] = {
 /* 208 */
   { RPL_TRACENEWTYPE, "<newtype> 0 %s", "208" },
 /* 209 */
-  { RPL_TRACECLASS, "Class %s %d", "209" },
+  { RPL_TRACECLASS, "Class %s %u", "209" },
 /* 210 */
   { 0 },
 /* 211 */
@@ -458,25 +458,25 @@ static Numeric replyTable[] = {
 /* 212 */
   { RPL_STATSCOMMANDS, "%s %u %u", "212" },
 /* 213 */
-  { RPL_STATSCLINE, "%c %s * %s %d %s", "213" },
+  { RPL_STATSCLINE, "C %s * %d %d %s %s", "213" },
 /* 214 */
-  { RPL_STATSNLINE, "%c %s * %s %d %d", "214" },
+  { 0 },
 /* 215 */
-  { RPL_STATSILINE, "%c %s %s %s %d %s", "215" },
+  { RPL_STATSILINE, "I %s%s%s %d %s%s %d %s", "215" },
 /* 216 */
-  { RPL_STATSKLINE, "%c %s \"%s\" %s 0 0", "216" },
+  { RPL_STATSKLINE, "%c %s@%s \"%s\" \"%s\" 0 0", "216" },
 /* 217 */
   { RPL_STATSPLINE, "P %d %d %s %s", "217" },
 /* 218 */
-  { RPL_STATSYLINE, "%c %s %d %d %d %ld %d", "218" },
+  { RPL_STATSYLINE, "%c %s %d %d %u %u %u", "218" },
 /* 219 */
-  { RPL_ENDOFSTATS, "%c :End of /STATS report", "219" },
+  { RPL_ENDOFSTATS, "%s :End of /STATS report", "219" },
 /* 220 */
   { 0 },
 /* 221 */
   { RPL_UMODEIS, "%s", "221" },
 /* 222 */
-  { 0 },
+  { RPL_STATSJLINE, "J %s", "222" },
 /* 223 */
   { 0 },
 /* 224 */
@@ -484,7 +484,7 @@ static Numeric replyTable[] = {
 /* 225 */
   { 0 },
 /* 226 */
-  { 0 },
+  { RPL_STATSALINE, "%s", "226" },
 /* 227 */
   { 0 },
 /* 228 */
@@ -494,55 +494,55 @@ static Numeric replyTable[] = {
 /* 230 */
   { 0 },
 /* 231 */
-  { RPL_SERVICEINFO, 0, "231" },
+  { 0 },
 /* 232 */
-  { RPL_ENDOFSERVICES, 0, "232" },
+  { 0 },
 /* 233 */
-  { RPL_SERVICE, 0, "233" },
+  { 0 },
 /* 234 */
-  { RPL_SERVLIST, 0, "234" },
+  { 0 },
 /* 235 */
-  { RPL_SERVLISTEND, 0, "235" },
+  { 0 },
 /* 236 */
   { RPL_STATSVERBOSE, "V :Sent as explicit", "236" },
 /* 237 */
   { RPL_STATSENGINE, "%s :Event loop engine", "237" },
 /* 238 */
-  { RPL_STATSFLINE, "%c %s %s", "238" },
+  { RPL_STATSFLINE, "F %s %s", "238" },
 /* 239 */
   { 0 },
 /* 240 */
   { 0 },
 /* 241 */
-  { RPL_STATSLLINE, "%c %s * %s %d %d", "241" },
+  { RPL_STATSLLINE, "Module Description EntryPoint", "241" },
 /* 242 */
   { RPL_STATSUPTIME, ":Server Up %d days, %d:%02d:%02d", "242" },
 /* 243 */
-  { RPL_STATSOLINE, "%c %s * %s %d %d", "243" },
+  { RPL_STATSOLINE, "%c %s@%s * %s %s", "243" },
 /* 244 */
-  { RPL_STATSHLINE, "%c %s * %s %d %d", "244" },
+  { 0 },
 /* 245 */
   { 0 },
 /* 246 */
   { RPL_STATSTLINE, "%c %s %s", "246" },
 /* 247 */
-  { RPL_STATSGLINE, "%c %s%s%s %Tu :%s", "247" },
+  { RPL_STATSGLINE, "%c %s%s%s %Tu %Tu %Tu %s%c :%s", "247" },
 /* 248 */
-  { RPL_STATSULINE, "%c %s %s %s %d %d", "248" },
+  { RPL_STATSULINE, "U %s", "248" },
 /* 249 */
   { RPL_STATSDEBUG, 0, "249" },
 /* 250 */
-  { RPL_STATSCONN, ":Highest connection count: %d (%d clients)", "250" },
+  { RPL_STATSCONN, ":Highest connection count: %u (%u clients)", "250" },
 /* 251 */
-  { RPL_LUSERCLIENT, ":There are %d users and %d invisible on %d servers", "251" },
+  { RPL_LUSERCLIENT, ":There are %u users and %u invisible on %u servers", "251" },
 /* 252 */
-  { RPL_LUSEROP, "%d :operator(s) online", "252" },
+  { RPL_LUSEROP, "%u :operator(s) online", "252" },
 /* 253 */
-  { RPL_LUSERUNKNOWN, "%d :unknown connection(s)", "253" },
+  { RPL_LUSERUNKNOWN, "%u :unknown connection(s)", "253" },
 /* 254 */
-  { RPL_LUSERCHANNELS, "%d :channels formed", "254" },
+  { RPL_LUSERCHANNELS, "%u :channels formed", "254" },
 /* 255 */
-  { RPL_LUSERME, ":I have %d clients and %d servers", "255" },
+  { RPL_LUSERME, ":I have %u clients and %u servers", "255" },
 /* 256 */
   { RPL_ADMINME, ":Administrative info about %s", "256" },
 /* 257 */
@@ -554,9 +554,9 @@ static Numeric replyTable[] = {
 /* 260 */
   { 0 },
 /* 261 */
-  { RPL_TRACELOG, "File %s %d", "261" },
+  { 0 },
 /* 262 */
-  { RPL_TRACEPING, "Ping %s %s", "262" },
+  { RPL_TRACEEND, ":End of TRACE", "262" },
 /* 263 */
   { 0 },
 /* 264 */
@@ -574,7 +574,7 @@ static Numeric replyTable[] = {
 /* 270 */
   { RPL_PRIVS, "%s :", "270" },
 /* 271 */
-  { RPL_SILELIST, "%s %s", "271" },
+  { RPL_SILELIST, "%s %s%s", "271" },
 /* 272 */
   { RPL_ENDOFSILELIST, "%s :End of Silence List", "272" },
 /* 273 */
@@ -592,7 +592,7 @@ static Numeric replyTable[] = {
 /* 279 */
   { 0 },
 /* 280 */
-  { RPL_GLIST, "%s%s%s %Tu %%c :%s", "280" },
+  { RPL_GLIST, "%s%s%s %Tu %Tu %Tu %s %s%c :%s", "280" },
 /* 281 */
   { RPL_ENDOFGLIST, ":End of G-line List", "281" },
 /* 282 */
@@ -632,7 +632,7 @@ static Numeric replyTable[] = {
 /* 299 */
   { 0 },
 /* 300 */
-  { RPL_NONE, 0, "300" },
+  { 0 },
 /* 301 */
   { RPL_AWAY, "%s :%s", "301" },
 /* 302 */
@@ -640,7 +640,7 @@ static Numeric replyTable[] = {
 /* 303 */
   { RPL_ISON, ":", "303" },
 /* 304 */
-  { RPL_TEXT, 0, "304" },
+  { 0 },
 /* 305 */
   { RPL_UNAWAY, ":You are no longer marked as being away", "305" },
 /* 306 */
@@ -676,7 +676,7 @@ static Numeric replyTable[] = {
 /* 321 */
   { RPL_LISTSTART, "Channel :Users  Name", "321" },
 /* 322 */
-  { RPL_LIST, "%s %d :%s", "322" },
+  { RPL_LIST, "%s %u :%s", "322" },
 /* 323 */
   { RPL_LISTEND, ":End of /LIST", "323" },
 /* 324 */
@@ -722,7 +722,7 @@ static Numeric replyTable[] = {
 /* 344 */
   { 0 },
 /* 345 */
-  { 0 },
+  { RPL_ISSUEDINVITE, "%s %s %s :%s has been invited by %s", "345" },
 /* 346 */
   { RPL_INVITELIST, ":%s", "346" },
 /* 347 */
@@ -754,13 +754,13 @@ static Numeric replyTable[] = {
 /* 360 */
   { 0 },
 /* 361 */
-  { RPL_KILLDONE, 0, "361" }, /* Not used */
+  { 0 },
 /* 362 */
   { RPL_CLOSING, "%s :Operator enforced Close", "362" },
 /* 363 */
   { RPL_CLOSEEND, "%d :Connections Closed", "363" },
 /* 364 */
-  { RPL_LINKS, "%s %s :%d P%u %s", "364" },
+  { RPL_LINKS, "%s %s :%u P%u %s", "364" },
 /* 365 */
   { RPL_ENDOFLINKS, "%s :End of /LINKS list.", "365" },
 /* 366 */
@@ -778,7 +778,7 @@ static Numeric replyTable[] = {
 /* 372 */
   { RPL_MOTD, ":- %s", "372" },
 /* 373 */
-  { RPL_INFOSTART, ":Server INFO", "373" },
+  { 0 },
 /* 374 */
   { RPL_ENDOFINFO, ":End of /INFO list.", "374" },
 /* 375 */
@@ -800,9 +800,9 @@ static Numeric replyTable[] = {
 /* 383 */
   { 0 },
 /* 384 */
-  { RPL_MYPORTIS, "%d :Port to local server is", "384" }, /* not used */
+  { 0 },
 /* 385 */
-  { RPL_NOTOPERANYMORE, 0, "385" }, /* not used */
+  { 0 },
 /* 386 */
   { 0 },
 /* 387 */
@@ -832,7 +832,7 @@ static Numeric replyTable[] = {
 /* 399 */
   { 0 },
 /* 400 */
-  { ERR_FIRSTERROR, "", "400" },
+  { 0 },
 /* 401 */
   { ERR_NOSUCHNICK, "%s :No such nick", "401" },
 /* 402 */
@@ -852,7 +852,7 @@ static Numeric replyTable[] = {
 /* 409 */
   { ERR_NOORIGIN, ":No origin specified", "409" },
 /* 410 */
-  { 0 },
+  { ERR_UNKNOWNCAPCMD, "%s :Unknown CAP subcommand", "410" },
 /* 411 */
   { ERR_NORECIPIENT, ":No recipient given (%s)", "411" },
 /* 412 */
@@ -866,7 +866,7 @@ static Numeric replyTable[] = {
 /* 416 */
   { ERR_QUERYTOOLONG, "%s :Too many lines in the output, restrict your query", "416" },
 /* 417 */
-  { 0 },
+  { ERR_INPUTTOOLONG, ":Input line was too long", "417" },
 /* 418 */
   { 0 },
 /* 419 */
@@ -986,7 +986,7 @@ static Numeric replyTable[] = {
 /* 476 */
   { ERR_BADCHANMASK, "%s :Bad Channel Mask", "476" },
 /* 477 */
-  { ERR_NEEDREGGEDNICK, "%s :Cannot join channel (+r)", "477" },
+  { ERR_NEEDREGGEDNICK, "%s :Cannot join channel (+r): this channel requires authentication -- you can obtain an account from %s", "477" },
 /* 478 */
   { ERR_BANLISTFULL, "%s %s :Channel ban/ignore list is full", "478" },
 /* 479 */
@@ -1014,7 +1014,7 @@ static Numeric replyTable[] = {
 /* 490 */
   { 0 },
 /* 491 */
-  { ERR_NOOPERHOST, ":No O-lines for your host", "491" },
+  { ERR_NOOPERHOST, ":No Operator block for your host", "491" },
 /* 492 */
   { 0 },
 /* 493 */
@@ -1064,11 +1064,11 @@ static Numeric replyTable[] = {
 /* 515 */
   { ERR_BADEXPIRE, "%Tu :Bad expire time", "515" },
 /* 516 */
-  { ERR_DONTCHEAT, " :Don't Cheat.", "516" },
+  { ERR_DONTCHEAT, "%s :Don't Cheat.", "516" },
 /* 517 */
   { ERR_DISABLED, "%s :Command disabled.", "517" },
 /* 518 */
-  { ERR_LONGMASK, " :Mask is too long", "518" },
+  { ERR_LONGMASK, ":Mask is too long", "518" },
 /* 519 */
   { ERR_TOOMANYUSERS, "%d :Too many users affected by mask", "519" },
 /* 520 */
@@ -1082,7 +1082,7 @@ static Numeric replyTable[] = {
 /* 524 */
   { ERR_QUARANTINED, "%s :Channel is quarantined : %s", "524" },
 /* 525 */
-  { 0 },
+  { ERR_INVALIDKEY, "%s :Key is not well-formed", "525" },
 /* 526 */
   { 0 },
 /* 527 */
@@ -1132,15 +1132,15 @@ static Numeric replyTable[] = {
 /* 549 */
   { 0 },
 /* 550 */
-  { ERR_NOTLOWEROPLEVEL, "%s %s %hu %hu :Cannot %s someone with %s op-level", "550" },
+  { 0 },
 /* 551 */
-  { ERR_NOTMANAGER, "%s :You must be channel Admin to add or remove a password. %s %s %s", "551" },
+  { 0 },
 /* 552 */
-  { ERR_CHANSECURED, "%s :Channel is older than 48 hours and secured. Cannot change Admin pass anymore", "552" },
+  { 0 },
 /* 553 */
-  { ERR_UPASSSET, "%s :Cannot remove Admin pass (+A) while User pass (+u) is still set.  First use /MODE %s -u <userpass>", "553" },
+  { 0 },
 /* 554 */
-  { ERR_UPASSNOTSET, "%s :Cannot set user pass (+u) while Admin pass (+A) is not set.  First use /MODE %s +A <adminpass>", "554" },
+  { 0 },
 /* 555 */
   { 0 },
 /* 556 */
@@ -1152,21 +1152,21 @@ static Numeric replyTable[] = {
 /* 559 */
   { 0 },
 /* 560 */
-  { 0 },
+  { ERR_NOTLOWEROPLEVEL, "%s %s %hu %hu :Cannot %s someone with %s op-level", "560" },
 /* 561 */
-  { 0 },
+  { ERR_NOTMANAGER, "%s :You must be channel Admin to add or remove a password. Use /JOIN %s <AdminPass>.", "561" },
 /* 562 */
-  { 0 },
+  { ERR_CHANSECURED, "%s :Channel is older than 48 hours and secured. Cannot change Admin pass anymore", "562" },
 /* 563 */
-  { 0 },
+  { ERR_UPASSSET, "%s :Cannot remove Admin pass (+A) while User pass (+U) is still set. First use /MODE %s -U <userpass>", "563" },
 /* 564 */
-  { 0 },
+  { ERR_UPASSNOTSET, "%s :Cannot set user pass (+U) until Admin pass (+A) is set. First use /MODE %s +A <adminpass>", "564" },
 /* 565 */
   { 0 },
 /* 566 */
-  { 0 },
+  { ERR_NOMANAGER, "%s :Re-create the channel. The channel must be completely empty for a period of %s before it can be recreated.", "566" },
 /* 567 */
-  { 0 },
+  { ERR_UPASS_SAME_APASS, "%s :Cannot use the same pass for both admin (+A) and user (+U) pass.", "567" },
 /* 568 */
   { 0 },
 /* 569 */
@@ -1233,6 +1233,10 @@ static Numeric replyTable[] = {
   { 0 }
 };
 
+/** Return a pointer to the Numeric for a particular code.
+ * @param n %Numeric to look up.
+ * @return Numeric structure.
+ */
 const struct Numeric* get_error_numeric(int n)
 {
   assert(0 < n);
@@ -1242,243 +1246,13 @@ const struct Numeric* get_error_numeric(int n)
   return &replyTable[n];
 }
 
-static char numbuff[512];
-
-/* *INDENT-OFF* */
-
-static const char atoi_tab[4000] = {
-    '0','0','0',0, '0','0','1',0, '0','0','2',0, '0','0','3',0, '0','0','4',0,
-    '0','0','5',0, '0','0','6',0, '0','0','7',0, '0','0','8',0, '0','0','9',0,
-    '0','1','0',0, '0','1','1',0, '0','1','2',0, '0','1','3',0, '0','1','4',0,
-    '0','1','5',0, '0','1','6',0, '0','1','7',0, '0','1','8',0, '0','1','9',0,
-    '0','2','0',0, '0','2','1',0, '0','2','2',0, '0','2','3',0, '0','2','4',0,
-    '0','2','5',0, '0','2','6',0, '0','2','7',0, '0','2','8',0, '0','2','9',0,
-    '0','3','0',0, '0','3','1',0, '0','3','2',0, '0','3','3',0, '0','3','4',0,
-    '0','3','5',0, '0','3','6',0, '0','3','7',0, '0','3','8',0, '0','3','9',0,
-    '0','4','0',0, '0','4','1',0, '0','4','2',0, '0','4','3',0, '0','4','4',0,
-    '0','4','5',0, '0','4','6',0, '0','4','7',0, '0','4','8',0, '0','4','9',0,
-    '0','5','0',0, '0','5','1',0, '0','5','2',0, '0','5','3',0, '0','5','4',0,
-    '0','5','5',0, '0','5','6',0, '0','5','7',0, '0','5','8',0, '0','5','9',0,
-    '0','6','0',0, '0','6','1',0, '0','6','2',0, '0','6','3',0, '0','6','4',0,
-    '0','6','5',0, '0','6','6',0, '0','6','7',0, '0','6','8',0, '0','6','9',0,
-    '0','7','0',0, '0','7','1',0, '0','7','2',0, '0','7','3',0, '0','7','4',0,
-    '0','7','5',0, '0','7','6',0, '0','7','7',0, '0','7','8',0, '0','7','9',0,
-    '0','8','0',0, '0','8','1',0, '0','8','2',0, '0','8','3',0, '0','8','4',0,
-    '0','8','5',0, '0','8','6',0, '0','8','7',0, '0','8','8',0, '0','8','9',0,
-    '0','9','0',0, '0','9','1',0, '0','9','2',0, '0','9','3',0, '0','9','4',0,
-    '0','9','5',0, '0','9','6',0, '0','9','7',0, '0','9','8',0, '0','9','9',0,
-    '1','0','0',0, '1','0','1',0, '1','0','2',0, '1','0','3',0, '1','0','4',0,
-    '1','0','5',0, '1','0','6',0, '1','0','7',0, '1','0','8',0, '1','0','9',0,
-    '1','1','0',0, '1','1','1',0, '1','1','2',0, '1','1','3',0, '1','1','4',0,
-    '1','1','5',0, '1','1','6',0, '1','1','7',0, '1','1','8',0, '1','1','9',0,
-    '1','2','0',0, '1','2','1',0, '1','2','2',0, '1','2','3',0, '1','2','4',0,
-    '1','2','5',0, '1','2','6',0, '1','2','7',0, '1','2','8',0, '1','2','9',0,
-    '1','3','0',0, '1','3','1',0, '1','3','2',0, '1','3','3',0, '1','3','4',0,
-    '1','3','5',0, '1','3','6',0, '1','3','7',0, '1','3','8',0, '1','3','9',0,
-    '1','4','0',0, '1','4','1',0, '1','4','2',0, '1','4','3',0, '1','4','4',0,
-    '1','4','5',0, '1','4','6',0, '1','4','7',0, '1','4','8',0, '1','4','9',0,
-    '1','5','0',0, '1','5','1',0, '1','5','2',0, '1','5','3',0, '1','5','4',0,
-    '1','5','5',0, '1','5','6',0, '1','5','7',0, '1','5','8',0, '1','5','9',0,
-    '1','6','0',0, '1','6','1',0, '1','6','2',0, '1','6','3',0, '1','6','4',0,
-    '1','6','5',0, '1','6','6',0, '1','6','7',0, '1','6','8',0, '1','6','9',0,
-    '1','7','0',0, '1','7','1',0, '1','7','2',0, '1','7','3',0, '1','7','4',0,
-    '1','7','5',0, '1','7','6',0, '1','7','7',0, '1','7','8',0, '1','7','9',0,
-    '1','8','0',0, '1','8','1',0, '1','8','2',0, '1','8','3',0, '1','8','4',0,
-    '1','8','5',0, '1','8','6',0, '1','8','7',0, '1','8','8',0, '1','8','9',0,
-    '1','9','0',0, '1','9','1',0, '1','9','2',0, '1','9','3',0, '1','9','4',0,
-    '1','9','5',0, '1','9','6',0, '1','9','7',0, '1','9','8',0, '1','9','9',0,
-    '2','0','0',0, '2','0','1',0, '2','0','2',0, '2','0','3',0, '2','0','4',0,
-    '2','0','5',0, '2','0','6',0, '2','0','7',0, '2','0','8',0, '2','0','9',0,
-    '2','1','0',0, '2','1','1',0, '2','1','2',0, '2','1','3',0, '2','1','4',0,
-    '2','1','5',0, '2','1','6',0, '2','1','7',0, '2','1','8',0, '2','1','9',0,
-    '2','2','0',0, '2','2','1',0, '2','2','2',0, '2','2','3',0, '2','2','4',0,
-    '2','2','5',0, '2','2','6',0, '2','2','7',0, '2','2','8',0, '2','2','9',0,
-    '2','3','0',0, '2','3','1',0, '2','3','2',0, '2','3','3',0, '2','3','4',0,
-    '2','3','5',0, '2','3','6',0, '2','3','7',0, '2','3','8',0, '2','3','9',0,
-    '2','4','0',0, '2','4','1',0, '2','4','2',0, '2','4','3',0, '2','4','4',0,
-    '2','4','5',0, '2','4','6',0, '2','4','7',0, '2','4','8',0, '2','4','9',0,
-    '2','5','0',0, '2','5','1',0, '2','5','2',0, '2','5','3',0, '2','5','4',0,
-    '2','5','5',0, '2','5','6',0, '2','5','7',0, '2','5','8',0, '2','5','9',0,
-    '2','6','0',0, '2','6','1',0, '2','6','2',0, '2','6','3',0, '2','6','4',0,
-    '2','6','5',0, '2','6','6',0, '2','6','7',0, '2','6','8',0, '2','6','9',0,
-    '2','7','0',0, '2','7','1',0, '2','7','2',0, '2','7','3',0, '2','7','4',0,
-    '2','7','5',0, '2','7','6',0, '2','7','7',0, '2','7','8',0, '2','7','9',0,
-    '2','8','0',0, '2','8','1',0, '2','8','2',0, '2','8','3',0, '2','8','4',0,
-    '2','8','5',0, '2','8','6',0, '2','8','7',0, '2','8','8',0, '2','8','9',0,
-    '2','9','0',0, '2','9','1',0, '2','9','2',0, '2','9','3',0, '2','9','4',0,
-    '2','9','5',0, '2','9','6',0, '2','9','7',0, '2','9','8',0, '2','9','9',0,
-    '3','0','0',0, '3','0','1',0, '3','0','2',0, '3','0','3',0, '3','0','4',0,
-    '3','0','5',0, '3','0','6',0, '3','0','7',0, '3','0','8',0, '3','0','9',0,
-    '3','1','0',0, '3','1','1',0, '3','1','2',0, '3','1','3',0, '3','1','4',0,
-    '3','1','5',0, '3','1','6',0, '3','1','7',0, '3','1','8',0, '3','1','9',0,
-    '3','2','0',0, '3','2','1',0, '3','2','2',0, '3','2','3',0, '3','2','4',0,
-    '3','2','5',0, '3','2','6',0, '3','2','7',0, '3','2','8',0, '3','2','9',0,
-    '3','3','0',0, '3','3','1',0, '3','3','2',0, '3','3','3',0, '3','3','4',0,
-    '3','3','5',0, '3','3','6',0, '3','3','7',0, '3','3','8',0, '3','3','9',0,
-    '3','4','0',0, '3','4','1',0, '3','4','2',0, '3','4','3',0, '3','4','4',0,
-    '3','4','5',0, '3','4','6',0, '3','4','7',0, '3','4','8',0, '3','4','9',0,
-    '3','5','0',0, '3','5','1',0, '3','5','2',0, '3','5','3',0, '3','5','4',0,
-    '3','5','5',0, '3','5','6',0, '3','5','7',0, '3','5','8',0, '3','5','9',0,
-    '3','6','0',0, '3','6','1',0, '3','6','2',0, '3','6','3',0, '3','6','4',0,
-    '3','6','5',0, '3','6','6',0, '3','6','7',0, '3','6','8',0, '3','6','9',0,
-    '3','7','0',0, '3','7','1',0, '3','7','2',0, '3','7','3',0, '3','7','4',0,
-    '3','7','5',0, '3','7','6',0, '3','7','7',0, '3','7','8',0, '3','7','9',0,
-    '3','8','0',0, '3','8','1',0, '3','8','2',0, '3','8','3',0, '3','8','4',0,
-    '3','8','5',0, '3','8','6',0, '3','8','7',0, '3','8','8',0, '3','8','9',0,
-    '3','9','0',0, '3','9','1',0, '3','9','2',0, '3','9','3',0, '3','9','4',0,
-    '3','9','5',0, '3','9','6',0, '3','9','7',0, '3','9','8',0, '3','9','9',0,
-    '4','0','0',0, '4','0','1',0, '4','0','2',0, '4','0','3',0, '4','0','4',0,
-    '4','0','5',0, '4','0','6',0, '4','0','7',0, '4','0','8',0, '4','0','9',0,
-    '4','1','0',0, '4','1','1',0, '4','1','2',0, '4','1','3',0, '4','1','4',0,
-    '4','1','5',0, '4','1','6',0, '4','1','7',0, '4','1','8',0, '4','1','9',0,
-    '4','2','0',0, '4','2','1',0, '4','2','2',0, '4','2','3',0, '4','2','4',0,
-    '4','2','5',0, '4','2','6',0, '4','2','7',0, '4','2','8',0, '4','2','9',0,
-    '4','3','0',0, '4','3','1',0, '4','3','2',0, '4','3','3',0, '4','3','4',0,
-    '4','3','5',0, '4','3','6',0, '4','3','7',0, '4','3','8',0, '4','3','9',0,
-    '4','4','0',0, '4','4','1',0, '4','4','2',0, '4','4','3',0, '4','4','4',0,
-    '4','4','5',0, '4','4','6',0, '4','4','7',0, '4','4','8',0, '4','4','9',0,
-    '4','5','0',0, '4','5','1',0, '4','5','2',0, '4','5','3',0, '4','5','4',0,
-    '4','5','5',0, '4','5','6',0, '4','5','7',0, '4','5','8',0, '4','5','9',0,
-    '4','6','0',0, '4','6','1',0, '4','6','2',0, '4','6','3',0, '4','6','4',0,
-    '4','6','5',0, '4','6','6',0, '4','6','7',0, '4','6','8',0, '4','6','9',0,
-    '4','7','0',0, '4','7','1',0, '4','7','2',0, '4','7','3',0, '4','7','4',0,
-    '4','7','5',0, '4','7','6',0, '4','7','7',0, '4','7','8',0, '4','7','9',0,
-    '4','8','0',0, '4','8','1',0, '4','8','2',0, '4','8','3',0, '4','8','4',0,
-    '4','8','5',0, '4','8','6',0, '4','8','7',0, '4','8','8',0, '4','8','9',0,
-    '4','9','0',0, '4','9','1',0, '4','9','2',0, '4','9','3',0, '4','9','4',0,
-    '4','9','5',0, '4','9','6',0, '4','9','7',0, '4','9','8',0, '4','9','9',0,
-    '5','0','0',0, '5','0','1',0, '5','0','2',0, '5','0','3',0, '5','0','4',0,
-    '5','0','5',0, '5','0','6',0, '5','0','7',0, '5','0','8',0, '5','0','9',0,
-    '5','1','0',0, '5','1','1',0, '5','1','2',0, '5','1','3',0, '5','1','4',0,
-    '5','1','5',0, '5','1','6',0, '5','1','7',0, '5','1','8',0, '5','1','9',0,
-    '5','2','0',0, '5','2','1',0, '5','2','2',0, '5','2','3',0, '5','2','4',0,
-    '5','2','5',0, '5','2','6',0, '5','2','7',0, '5','2','8',0, '5','2','9',0,
-    '5','3','0',0, '5','3','1',0, '5','3','2',0, '5','3','3',0, '5','3','4',0,
-    '5','3','5',0, '5','3','6',0, '5','3','7',0, '5','3','8',0, '5','3','9',0,
-    '5','4','0',0, '5','4','1',0, '5','4','2',0, '5','4','3',0, '5','4','4',0,
-    '5','4','5',0, '5','4','6',0, '5','4','7',0, '5','4','8',0, '5','4','9',0,
-    '5','5','0',0, '5','5','1',0, '5','5','2',0, '5','5','3',0, '5','5','4',0,
-    '5','5','5',0, '5','5','6',0, '5','5','7',0, '5','5','8',0, '5','5','9',0,
-    '5','6','0',0, '5','6','1',0, '5','6','2',0, '5','6','3',0, '5','6','4',0,
-    '5','6','5',0, '5','6','6',0, '5','6','7',0, '5','6','8',0, '5','6','9',0,
-    '5','7','0',0, '5','7','1',0, '5','7','2',0, '5','7','3',0, '5','7','4',0,
-    '5','7','5',0, '5','7','6',0, '5','7','7',0, '5','7','8',0, '5','7','9',0,
-    '5','8','0',0, '5','8','1',0, '5','8','2',0, '5','8','3',0, '5','8','4',0,
-    '5','8','5',0, '5','8','6',0, '5','8','7',0, '5','8','8',0, '5','8','9',0,
-    '5','9','0',0, '5','9','1',0, '5','9','2',0, '5','9','3',0, '5','9','4',0,
-    '5','9','5',0, '5','9','6',0, '5','9','7',0, '5','9','8',0, '5','9','9',0,
-    '6','0','0',0, '6','0','1',0, '6','0','2',0, '6','0','3',0, '6','0','4',0,
-    '6','0','5',0, '6','0','6',0, '6','0','7',0, '6','0','8',0, '6','0','9',0,
-    '6','1','0',0, '6','1','1',0, '6','1','2',0, '6','1','3',0, '6','1','4',0,
-    '6','1','5',0, '6','1','6',0, '6','1','7',0, '6','1','8',0, '6','1','9',0,
-    '6','2','0',0, '6','2','1',0, '6','2','2',0, '6','2','3',0, '6','2','4',0,
-    '6','2','5',0, '6','2','6',0, '6','2','7',0, '6','2','8',0, '6','2','9',0,
-    '6','3','0',0, '6','3','1',0, '6','3','2',0, '6','3','3',0, '6','3','4',0,
-    '6','3','5',0, '6','3','6',0, '6','3','7',0, '6','3','8',0, '6','3','9',0,
-    '6','4','0',0, '6','4','1',0, '6','4','2',0, '6','4','3',0, '6','4','4',0,
-    '6','4','5',0, '6','4','6',0, '6','4','7',0, '6','4','8',0, '6','4','9',0,
-    '6','5','0',0, '6','5','1',0, '6','5','2',0, '6','5','3',0, '6','5','4',0,
-    '6','5','5',0, '6','5','6',0, '6','5','7',0, '6','5','8',0, '6','5','9',0,
-    '6','6','0',0, '6','6','1',0, '6','6','2',0, '6','6','3',0, '6','6','4',0,
-    '6','6','5',0, '6','6','6',0, '6','6','7',0, '6','6','8',0, '6','6','9',0,
-    '6','7','0',0, '6','7','1',0, '6','7','2',0, '6','7','3',0, '6','7','4',0,
-    '6','7','5',0, '6','7','6',0, '6','7','7',0, '6','7','8',0, '6','7','9',0,
-    '6','8','0',0, '6','8','1',0, '6','8','2',0, '6','8','3',0, '6','8','4',0,
-    '6','8','5',0, '6','8','6',0, '6','8','7',0, '6','8','8',0, '6','8','9',0,
-    '6','9','0',0, '6','9','1',0, '6','9','2',0, '6','9','3',0, '6','9','4',0,
-    '6','9','5',0, '6','9','6',0, '6','9','7',0, '6','9','8',0, '6','9','9',0,
-    '7','0','0',0, '7','0','1',0, '7','0','2',0, '7','0','3',0, '7','0','4',0,
-    '7','0','5',0, '7','0','6',0, '7','0','7',0, '7','0','8',0, '7','0','9',0,
-    '7','1','0',0, '7','1','1',0, '7','1','2',0, '7','1','3',0, '7','1','4',0,
-    '7','1','5',0, '7','1','6',0, '7','1','7',0, '7','1','8',0, '7','1','9',0,
-    '7','2','0',0, '7','2','1',0, '7','2','2',0, '7','2','3',0, '7','2','4',0,
-    '7','2','5',0, '7','2','6',0, '7','2','7',0, '7','2','8',0, '7','2','9',0,
-    '7','3','0',0, '7','3','1',0, '7','3','2',0, '7','3','3',0, '7','3','4',0,
-    '7','3','5',0, '7','3','6',0, '7','3','7',0, '7','3','8',0, '7','3','9',0,
-    '7','4','0',0, '7','4','1',0, '7','4','2',0, '7','4','3',0, '7','4','4',0,
-    '7','4','5',0, '7','4','6',0, '7','4','7',0, '7','4','8',0, '7','4','9',0,
-    '7','5','0',0, '7','5','1',0, '7','5','2',0, '7','5','3',0, '7','5','4',0,
-    '7','5','5',0, '7','5','6',0, '7','5','7',0, '7','5','8',0, '7','5','9',0,
-    '7','6','0',0, '7','6','1',0, '7','6','2',0, '7','6','3',0, '7','6','4',0,
-    '7','6','5',0, '7','6','6',0, '7','6','7',0, '7','6','8',0, '7','6','9',0,
-    '7','7','0',0, '7','7','1',0, '7','7','2',0, '7','7','3',0, '7','7','4',0,
-    '7','7','5',0, '7','7','6',0, '7','7','7',0, '7','7','8',0, '7','7','9',0,
-    '7','8','0',0, '7','8','1',0, '7','8','2',0, '7','8','3',0, '7','8','4',0,
-    '7','8','5',0, '7','8','6',0, '7','8','7',0, '7','8','8',0, '7','8','9',0,
-    '7','9','0',0, '7','9','1',0, '7','9','2',0, '7','9','3',0, '7','9','4',0,
-    '7','9','5',0, '7','9','6',0, '7','9','7',0, '7','9','8',0, '7','9','9',0,
-    '8','0','0',0, '8','0','1',0, '8','0','2',0, '8','0','3',0, '8','0','4',0,
-    '8','0','5',0, '8','0','6',0, '8','0','7',0, '8','0','8',0, '8','0','9',0,
-    '8','1','0',0, '8','1','1',0, '8','1','2',0, '8','1','3',0, '8','1','4',0,
-    '8','1','5',0, '8','1','6',0, '8','1','7',0, '8','1','8',0, '8','1','9',0,
-    '8','2','0',0, '8','2','1',0, '8','2','2',0, '8','2','3',0, '8','2','4',0,
-    '8','2','5',0, '8','2','6',0, '8','2','7',0, '8','2','8',0, '8','2','9',0,
-    '8','3','0',0, '8','3','1',0, '8','3','2',0, '8','3','3',0, '8','3','4',0,
-    '8','3','5',0, '8','3','6',0, '8','3','7',0, '8','3','8',0, '8','3','9',0,
-    '8','4','0',0, '8','4','1',0, '8','4','2',0, '8','4','3',0, '8','4','4',0,
-    '8','4','5',0, '8','4','6',0, '8','4','7',0, '8','4','8',0, '8','4','9',0,
-    '8','5','0',0, '8','5','1',0, '8','5','2',0, '8','5','3',0, '8','5','4',0,
-    '8','5','5',0, '8','5','6',0, '8','5','7',0, '8','5','8',0, '8','5','9',0,
-    '8','6','0',0, '8','6','1',0, '8','6','2',0, '8','6','3',0, '8','6','4',0,
-    '8','6','5',0, '8','6','6',0, '8','6','7',0, '8','6','8',0, '8','6','9',0,
-    '8','7','0',0, '8','7','1',0, '8','7','2',0, '8','7','3',0, '8','7','4',0,
-    '8','7','5',0, '8','7','6',0, '8','7','7',0, '8','7','8',0, '8','7','9',0,
-    '8','8','0',0, '8','8','1',0, '8','8','2',0, '8','8','3',0, '8','8','4',0,
-    '8','8','5',0, '8','8','6',0, '8','8','7',0, '8','8','8',0, '8','8','9',0,
-    '8','9','0',0, '8','9','1',0, '8','9','2',0, '8','9','3',0, '8','9','4',0,
-    '8','9','5',0, '8','9','6',0, '8','9','7',0, '8','9','8',0, '8','9','9',0,
-    '9','0','0',0, '9','0','1',0, '9','0','2',0, '9','0','3',0, '9','0','4',0,
-    '9','0','5',0, '9','0','6',0, '9','0','7',0, '9','0','8',0, '9','0','9',0,
-    '9','1','0',0, '9','1','1',0, '9','1','2',0, '9','1','3',0, '9','1','4',0,
-    '9','1','5',0, '9','1','6',0, '9','1','7',0, '9','1','8',0, '9','1','9',0,
-    '9','2','0',0, '9','2','1',0, '9','2','2',0, '9','2','3',0, '9','2','4',0,
-    '9','2','5',0, '9','2','6',0, '9','2','7',0, '9','2','8',0, '9','2','9',0,
-    '9','3','0',0, '9','3','1',0, '9','3','2',0, '9','3','3',0, '9','3','4',0,
-    '9','3','5',0, '9','3','6',0, '9','3','7',0, '9','3','8',0, '9','3','9',0,
-    '9','4','0',0, '9','4','1',0, '9','4','2',0, '9','4','3',0, '9','4','4',0,
-    '9','4','5',0, '9','4','6',0, '9','4','7',0, '9','4','8',0, '9','4','9',0,
-    '9','5','0',0, '9','5','1',0, '9','5','2',0, '9','5','3',0, '9','5','4',0,
-    '9','5','5',0, '9','5','6',0, '9','5','7',0, '9','5','8',0, '9','5','9',0,
-    '9','6','0',0, '9','6','1',0, '9','6','2',0, '9','6','3',0, '9','6','4',0,
-    '9','6','5',0, '9','6','6',0, '9','6','7',0, '9','6','8',0, '9','6','9',0,
-    '9','7','0',0, '9','7','1',0, '9','7','2',0, '9','7','3',0, '9','7','4',0,
-    '9','7','5',0, '9','7','6',0, '9','7','7',0, '9','7','8',0, '9','7','9',0,
-    '9','8','0',0, '9','8','1',0, '9','8','2',0, '9','8','3',0, '9','8','4',0,
-    '9','8','5',0, '9','8','6',0, '9','8','7',0, '9','8','8',0, '9','8','9',0,
-    '9','9','0',0, '9','9','1',0, '9','9','2',0, '9','9','3',0, '9','9','4',0,
-    '9','9','5',0, '9','9','6',0, '9','9','7',0, '9','9','8',0, '9','9','9',0 };
-
-/* *INDENT-ON* */
-
-/* "inline" */
-#define prepbuf(buffer, num, tail)                      \
-{                                                       \
-  char *s = buffer + 4;                 \
-  const char *ap = atoi_tab + (num << 2);       \
-                                                        \
-  strcpy(buffer, ":%s 000 %s ");                        \
-  *s++ = *ap++;                                         \
-  *s++ = *ap++;                                         \
-  *s = *ap;                                             \
-  strcpy(s + 5, tail);                                  \
-}
-
-char* err_str(int n)
-{
-  Numeric* p;
-
-  assert(0 < n);
-  assert(n < ERR_LASTERROR);
-  assert(0 != replyTable[n].value);
-
-  p = &replyTable[n];
-  prepbuf(numbuff, p->value, p->format);
-
-  return numbuff;
-}
-
+/** Return a format string for a numeric response.
+ * @param n %Numeric to look up.
+ * @return Pointer to a static buffer containing the format string.
+ */
 char* rpl_str(int n)
 {
+  static char numbuff[512];
   Numeric* p;
 
   assert(0 < n);
@@ -1486,7 +1260,13 @@ char* rpl_str(int n)
   assert(0 != replyTable[n].value);
 
   p = &replyTable[n];
-  prepbuf(numbuff, p->value, p->format);
+  strcpy(numbuff, ":%s 000 %s ");
+  if (p->str) {
+    numbuff[4] = p->str[0];
+    numbuff[5] = p->str[1];
+    numbuff[6] = p->str[2];
+    strcpy(numbuff + 11, p->format);
+  }
 
   return numbuff;
 }