diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index 7f92aec6a55b2c2161c0ba787dc38d07d7a947a4..d3e3847e7ed4242a33043016dc45d55937db95ac 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -1477,7 +1477,7 @@ static const char* makefilename_doscanformat(const char *str, t_printtype *typ,
             if (*(str+1) == '\0')
             {
                 str++;
-                sprintf(errormsg, "field type missing after '%%'");
+                sprintf(errormsg, "field type missing");
                 *typ = NONE;
                 return str;
             }
@@ -1495,7 +1495,7 @@ static const char* makefilename_doscanformat(const char *str, t_printtype *typ,
                 infmt = 0;
                 continue;
             }
-            for (i = 0; *str && strchr("-+#0", *str) != 0; str++)
+            for (i = 0; *str && strchr("-+#0", *str) != 0; str++, i++)
             {
                 /* Check for flag chars. While a space is a legal part of this
                    field, Pd's parser would split it off into a separate arg.
@@ -1503,7 +1503,7 @@ static const char* makefilename_doscanformat(const char *str, t_printtype *typ,
                    support spaces here. */
                 /* Since we're dealing with arbitrary input let's keep
                    the total number of flags sane. */
-                if (i > 16)
+                if (i > 15)
                 {
                     sprintf(errormsg, "too many flags");
                     *typ = NONE;
diff --git a/scripts/regression_tests.pd b/scripts/regression_tests.pd
index d691cc83e49212a6574072dc3a9b7d4fa4f4e2bf..2c1fc7815dc8dad9c3e0d06fdfb48f3391c11309 100644
--- a/scripts/regression_tests.pd
+++ b/scripts/regression_tests.pd
@@ -3,7 +3,7 @@
 #X obj 475 326 route 0;
 #X obj 583 470 print failure;
 #X obj 560 336 tgl 28 0 empty empty Print_All_Results 31 11 0 12 -262144
--1 -1 0 1;
+-1 -1 1 1;
 #X obj 159 149 bng 31 250 50 0 empty empty Run_all 39 13 0 12 -262144
 -1 -1;
 #X obj 56 25 r init;
@@ -34,13 +34,19 @@ is handy for some binbuf tests.;
 #X text 536 150 <- we have to escape the arg;
 #X text 556 190 escape it in a comment.;
 #X text 556 170 in bash but we can't;
-#X obj 391 374 spigot;
-#X obj 407 440 route 1;
-#X obj 407 495 print success;
+#X obj 521 374 spigot;
+#X obj 537 440 route 1;
+#X obj 537 495 print success;
 #X obj 145 358 rtest unpost_sanity;
 #X obj 145 414 rtest unpost_error;
 #X obj 145 465 rtest unpost_print;
 #X obj 145 516 rtest unpost_long_message;
+#X obj 145 569 rtest makefilename_double_percent;
+#X obj 145 620 rtest makefilename_code_coverage;
+#N canvas 461 242 450 323 (subpatch) 0;
+#X restore 148 875 pd;
+#X obj 145 671 rtest makefilename_default;
+#X obj 145 722 rtest makefilename_default_bang;
 #X connect 0 0 1 0;
 #X connect 1 0 7 0;
 #X connect 1 1 29 0;
@@ -70,3 +76,7 @@ is handy for some binbuf tests.;
 #X connect 32 0 33 0;
 #X connect 33 0 34 0;
 #X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 37 0;
+#X connect 37 0 39 0;
+#X connect 39 0 40 0;
diff --git a/scripts/regression_tests/makefilename_code_coverage.pd b/scripts/regression_tests/makefilename_code_coverage.pd
new file mode 100644
index 0000000000000000000000000000000000000000..37edc4cb85df85067d2a469d97fcdaf576e5202c
--- /dev/null
+++ b/scripts/regression_tests/makefilename_code_coverage.pd
@@ -0,0 +1,92 @@
+#N canvas 130 60 665 633 12;
+#X obj 41 8 inlet;
+#X msg 41 143 1;
+#X obj 43 1059 outlet;
+#X text 117 8 makefilename is a strange combination of the already
+complicated C format string format specification and Pd's syntax limitations.
+This is especially unfortunate given the object only accepts a single
+substitution variable.;
+#X text 117 88 As a consequence we get an extremely error-prone interface
+subject to all kinds of broken format specifiers settable at runtime
+with arbitrary user-input. All that complexity for an object of impressively
+limited usefulness.;
+#X text 117 168 Here \, we trigger every branch of the format specifier
+parser to make sure a run-time error results instead of a crash and/or
+memory error. We use [unpost] to redirect the error from the console
+to the patch.;
+#X obj 105 782 makefilename;
+#X text 184 664 * todo: add check for [makefilename] with no args to
+make sure it ouputs file%d;
+#X obj 43 782 list;
+#X obj 43 807 route symbol bang;
+#X obj 145 928 list;
+#X obj 43 716 trigger bang anything bang anything;
+#X obj 43 832 b;
+#X obj 43 857 f 1;
+#X obj 100 831 f 0;
+#X obj 43 882 t a b;
+#X obj 43 1018 list append;
+#X msg 145 959 code coverage for error handling of poorly formed format
+specifier: \$@;
+#X text 143 292 too many flags;
+#X text 50 240 no field type;
+#X text 129 414 max width/precision;
+#X text 115 354 variable width or precision field not supported;
+#X text 148 535 unsupported field types;
+#X text 154 600 non-existent field type;
+#X msg 41 265 % \, %0;
+#X obj 43 661 list prepend set;
+#X obj 43 686 list trim;
+#X msg 53 317 %-+#0-+#0-+#0-+#0- \, %-+#0-+#0-+#0-+#0-g;
+#X msg 63 379 %* \, %*s \, %.*s \, %*.*s;
+#X msg 73 439 %9999g \, %.9999g \, %9999.9999g;
+#X msg 83 499 %5.g \, %.g \, %5..g \, %..g;
+#X text 132 477 dot with no digit(s) following it;
+#X obj 66 746 unpost error;
+#X text 168 747 <- if there's an error we'll get it to the left inlet
+in the form of a symbol;
+#X obj 41 168 s \$0-b;
+#X obj 41 213 r \$0-b;
+#X obj 54 291 r \$0-b;
+#X obj 63 348 r \$0-b;
+#X obj 73 409 r \$0-b;
+#X obj 83 467 r \$0-b;
+#X obj 93 530 r \$0-b;
+#X obj 103 584 r \$0-b;
+#X msg 93 559 %a \, %A \, %n \, %m;
+#X msg 103 610 %z;
+#X connect 0 0 1 0;
+#X connect 1 0 34 0;
+#X connect 8 0 9 0;
+#X connect 9 0 12 0;
+#X connect 9 1 14 0;
+#X connect 10 0 17 0;
+#X connect 11 0 8 0;
+#X connect 11 1 32 0;
+#X connect 11 2 8 1;
+#X connect 11 3 10 1;
+#X connect 12 0 13 0;
+#X connect 13 0 15 0;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 15 1 10 0;
+#X connect 16 0 2 0;
+#X connect 17 0 16 1;
+#X connect 24 0 25 0;
+#X connect 25 0 26 0;
+#X connect 26 0 11 0;
+#X connect 27 0 25 0;
+#X connect 28 0 25 0;
+#X connect 29 0 25 0;
+#X connect 30 0 25 0;
+#X connect 32 0 8 1;
+#X connect 32 1 6 0;
+#X connect 35 0 24 0;
+#X connect 36 0 27 0;
+#X connect 37 0 28 0;
+#X connect 38 0 29 0;
+#X connect 39 0 30 0;
+#X connect 40 0 42 0;
+#X connect 41 0 43 0;
+#X connect 42 0 25 0;
+#X connect 43 0 25 0;
diff --git a/scripts/regression_tests/makefilename_default.pd b/scripts/regression_tests/makefilename_default.pd
new file mode 100644
index 0000000000000000000000000000000000000000..ebbb0da0fbf54e276b90bec7ce3513502845b205
--- /dev/null
+++ b/scripts/regression_tests/makefilename_default.pd
@@ -0,0 +1,21 @@
+#N canvas 51 212 538 283 12;
+#X obj 41 28 inlet;
+#X obj 136 153 list prepend 0;
+#X obj 41 249 outlet;
+#X obj 41 98 makefilename;
+#X text 117 28 [makefilename] with no arguments should output the symbol
+`file.` concatenated with the number from the input. The incoming float
+should be cast to an int before concatenation.;
+#X msg 41 73 42.3;
+#X obj 41 123 select file.42;
+#X msg 41 153 1 file.42;
+#X msg 41 187 \$1 default format specifier 'file.%d' with incoming
+float cast to int. Expected output: 'file.42'. Actual output: \$2;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 3 0 6 0;
+#X connect 5 0 3 0;
+#X connect 6 0 7 0;
+#X connect 6 1 1 0;
+#X connect 7 0 8 0;
+#X connect 8 0 2 0;
diff --git a/scripts/regression_tests/makefilename_default_bang.pd b/scripts/regression_tests/makefilename_default_bang.pd
new file mode 100644
index 0000000000000000000000000000000000000000..80dd5bf704f25642a74de41f60557205efddc81d
--- /dev/null
+++ b/scripts/regression_tests/makefilename_default_bang.pd
@@ -0,0 +1,21 @@
+#N canvas 72 248 589 329 12;
+#X obj 41 28 inlet;
+#X obj 136 153 list prepend 0;
+#X obj 41 229 outlet;
+#X obj 41 98 makefilename;
+#X text 117 28 [makefilename] in Pd Vanilla apparently converts an
+incoming bang to zero. Not sure why \, but we check for that default
+here.;
+#X msg 41 73 bang;
+#X obj 41 123 select file.0;
+#X msg 41 153 1 file.0;
+#X msg 41 187 \$1 a bang should bash to zero. Expected output: 'file.0'.
+Actual output: \$2;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 3 0 6 0;
+#X connect 5 0 3 0;
+#X connect 6 0 7 0;
+#X connect 6 1 1 0;
+#X connect 7 0 8 0;
+#X connect 8 0 2 0;
diff --git a/scripts/regression_tests/makefilename_double_percent.pd b/scripts/regression_tests/makefilename_double_percent.pd
new file mode 100644
index 0000000000000000000000000000000000000000..e510160146183a7eb97710cc244949ad7d2a7b7e
--- /dev/null
+++ b/scripts/regression_tests/makefilename_double_percent.pd
@@ -0,0 +1,22 @@
+#N canvas 176 225 538 369 12;
+#X obj 41 28 inlet;
+#X msg 41 73 1;
+#X obj 41 98 makefilename %%s%g;
+#X obj 41 123 select %s1;
+#X obj 108 153 list prepend 0;
+#X msg 41 153 1 %s1;
+#X obj 41 229 outlet;
+#X text 117 28 Double percent signs map to a single literal '%'. Some
+old patches use this feature in conjunction with the 'set' message
+to do string concatenation. So we want to make sure it continues to
+work going forward.;
+#X msg 41 187 \$1 format specifier '%%' should get converted to a single
+'%'. Expected output: '%s1'. Actual output: \$2;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 3 1 4 0;
+#X connect 4 0 8 0;
+#X connect 5 0 8 0;
+#X connect 8 0 6 0;
diff --git a/scripts/regression_tests/makefilename_percent_parsing.pd b/scripts/regression_tests/makefilename_percent_parsing.pd
deleted file mode 100644
index a162f073c0a830748e4ea3b8c4d243bfde86725d..0000000000000000000000000000000000000000
--- a/scripts/regression_tests/makefilename_percent_parsing.pd
+++ /dev/null
@@ -1,18 +0,0 @@
-#N canvas 430 102 538 300 12;
-#X obj 41 28 inlet;
-#X msg 41 53 1;
-#X obj 41 78 makefilename %%s%g;
-#X obj 41 103 select %s1;
-#X obj 108 133 list prepend 0;
-#X msg 41 133 1 %s1;
-#X obj 41 209 outlet;
-#X obj 41 168 list append format specifier '%%' should get converted
-to a single '%'. Expected output: '%s1'. Actual output: \$2;
-#X connect 0 0 1 0;
-#X connect 1 0 2 0;
-#X connect 2 0 3 0;
-#X connect 3 0 5 0;
-#X connect 3 1 4 0;
-#X connect 4 0 7 0;
-#X connect 5 0 7 0;
-#X connect 7 0 6 0;