Browse Source

Bugfix: bfg_snprintf: Handle standard snprintf passthrough type-by-type since va_list cannot be used after passing

Luke Dashjr 12 years ago
parent
commit
c7d701f2a0
2 changed files with 54 additions and 7 deletions
  1. 53 6
      util.c
  2. 1 1
      util.h

+ 53 - 6
util.c

@@ -1475,10 +1475,7 @@ int bfg_vsnprintf(char * const buf, size_t sz, const char *fmt, va_list ap)
 			case '%':
 				if ( (L = (p - fmt)) )
 				{
-					char fmtcp[L+1];
-					memcpy(fmtcp, fmt, L);
-					fmtcp[L] = '\0';
-					_SNP2(vsnprintf, fmtcp, ap);
+					_SNP("%.*s", L, fmt);
 					fmt += L;
 				}
 				if (!fmt[0])
@@ -1541,8 +1538,57 @@ switch (fmt[1])
 					p = fmt - 1;
 					break;
 				}
-				
-				// Pass anything else through vsprintf above
+				else
+				{
+					// Standard printf % conversions
+					// Thanks to va_list passing not being nice, we have to go into detail here :(
+					++p;
+					while (true)
+					{
+						switch (p++[0])
+						{
+							// NOTE: Subset of standard and Windows types
+							case 'd': case 'i': case 'u': case 'x': case 'X': case 'o': case 'e': case 'E': case 'f': case 'g': case 'G': case 'a': case 'A': case 'c': case 's': case 'p': case '%':
+								goto foundend;
+							case '0':
+								// TODO: invalid sequence
+								break;
+						}
+					}
+foundend:
+					L = (p - fmt);
+					char fmtcp[L+1];
+					memcpy(fmtcp, fmt, L);
+					fmtcp[L] = '\0';
+					fmt += L;
+					p = fmt - 1;
+switch (p[0])
+{
+	case 'd': case 'i':
+	case 'u':
+	case 'x': case 'X':
+	case 'o':
+	case 'c':
+		arg_d = va_arg(ap, int);
+		_SNP(fmtcp, arg_d);
+		break;
+	case 'e': case 'E':
+	case 'f':
+	case 'g': case 'G':
+	case 'a': case 'A':
+		arg_f = va_arg(ap, double);
+		_SNP(fmtcp, arg_f);
+		break;
+	case 's':
+	case 'p':
+		arg_p = va_arg(ap, void*);
+		_SNP(fmtcp, arg_p);
+		break;
+	case '%':
+		_SNP(fmtcp, "%%");
+}
+
+				}
 		}
 	}
 }
@@ -1609,6 +1655,7 @@ void test_bfg_snprintf()
 	_test_bfg_sprintf("a%02dbc2", "a44bc2", 44);
 	
 	_test_bfg_sprintf("a%sbc", "axyzbc", "xyz");
+	_test_bfg_sprintf("a%sb%sc", "axyzb123c", "xyz", "123");
 	
 	_test_bfg_sprintf("a%ubc", "a255bc", 255);
 	

+ 1 - 1
util.h

@@ -363,7 +363,7 @@ extern void utf8_test();
 #define _SNP2(fn, ...)  do{  \
 	int __n42 = fn(s, sz, __VA_ARGS__);  \
 	s += __n42;  \
-	sz -= __n42;  \
+	sz = (sz <= __n42) ? 0 : (sz - __n42);  \
 	rv += __n42;  \
 }while(0)