src/format.cc

changeset 72
03e4d9db3fd9
child 73
1ee9b312dc18
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/format.cc	Fri Jan 10 21:58:42 2014 +0200
@@ -0,0 +1,94 @@
+#include <cstdio>
+#include "main.h"
+#include "format.h"
+
+static void draw_pos (const string& fmt, int pos)
+{
+	string rep (fmt);
+	rep.replace ("\n", "↵");
+	rep.replace ("\t", "⇥");
+
+	fprintf (stderr, "%s\n", rep.chars());
+
+	for (int x = 0; x < pos; ++x)
+		fprintf (stderr, "-");
+
+	fprintf (stderr, "^\n");
+}
+
+string format_args (const list<format_arg>& args)
+{
+	const string& fmtstr = args[0].as_string();
+	assert (args.size() >= 1);
+
+	if (args.size() == 1)
+		return args[0].as_string();
+
+	string fmt = fmtstr;
+	string out;
+	int pos = 0;
+
+	while ((pos = fmt.first ("%", pos)) != -1)
+	{
+		if (fmt[pos + 1] == '%')
+		{
+			fmt.replace (pos, 2, "%");
+			pos++;
+			continue;
+		}
+
+		int ofs = 1;
+		char mod = '\0';
+
+		// handle modifiers
+		if (fmt[ pos + ofs ] == 's' || fmt[ pos + ofs ] == 'x')
+		{
+			mod = fmt[ pos + ofs ];
+			ofs++;
+		}
+
+		if (!isdigit (fmt[ pos + ofs ]))
+		{
+			fprintf (stderr, "bad format string, expected digit with optional "
+					 "modifier after '%%':\n");
+			draw_pos (fmt, pos);
+			return fmt;
+		}
+
+		int i = fmt[ pos + ofs ]  - '0';
+
+		if (i >= args.size())
+		{
+			fprintf (stderr, "format arg #%d used but not defined: %s\n", i, fmtstr.chars());
+			return fmt;
+		}
+
+		string repl = args[i].as_string();
+
+		if (mod == 's')
+		{
+			repl = (repl == "1") ? "" : "s";
+		}
+
+		elif (mod == 'd')
+		{
+			repl.sprintf ("%d", repl[0]);
+		}
+		elif (mod == 'x')
+		{
+			// modifier x: reinterpret the argument as hex
+			repl.sprintf ("0x%X", strtol (repl.chars(), null, 10));
+		}
+
+		fmt.replace (pos, 1 + ofs, repl);
+		pos += repl.length();
+	}
+
+	return fmt;
+}
+
+void print_args (FILE* fp, const list<format_arg>& args)
+{
+	string out = format_args (args);
+	fprintf (fp, "%s", out.chars());
+}

mercurial