Major hashing around to restructure the world.
git-svn-id: svn://svn.valgrind.org/vex/trunk@49 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/main/vex_util.c b/priv/main/vex_util.c
new file mode 100644
index 0000000..365eb4b
--- /dev/null
+++ b/priv/main/vex_util.c
@@ -0,0 +1,392 @@
+
+/*---------------------------------------------------------------*/
+/*--- ---*/
+/*--- This file (vex_util.c) is ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
+/*--- ---*/
+/*---------------------------------------------------------------*/
+
+#include "libjit_basictypes.h"
+#include "jit_globals.h"
+#include "vex_util.h"
+
+
+/*---------------------------------------------------------*/
+/*--- Storage ---*/
+/*---------------------------------------------------------*/
+
+#define N_STORAGE_BYTES 10000
+
+static Char storage[N_STORAGE_BYTES];
+static Int storage_used = 0;
+
+/* Exported to library client. */
+
+void* LibVEX_Alloc ( Int nbytes )
+{
+ vassert(vex_initdone);
+ vassert(nbytes > 0);
+ nbytes = (nbytes + 7) & ~8;
+ if (storage_used + nbytes > N_STORAGE_BYTES)
+ vpanic("VEX storage exhausted.\n"
+ "Increase N_STORAGE_BYTES and recompile.");
+ storage_used += nbytes;
+ return (void*)(&storage[storage_used - nbytes]);
+}
+
+/* Exported to library client. */
+
+void LibJIT_Clear ( void )
+{
+ vassert(vex_initdone);
+ storage_used = 0;
+}
+
+
+
+/*---------------------------------------------------------*/
+/*--- Bombing out ---*/
+/*---------------------------------------------------------*/
+
+__attribute__ ((noreturn))
+void vex_assert_fail ( const Char* expr,
+ const Char* file, Int line, const Char* fn )
+{
+ vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
+ file, line, fn, expr );
+ (*vex_failure_exit)();
+}
+
+__attribute__ ((noreturn))
+void panic ( Char* str )
+{
+ vex_printf("\nvex: the `impossible' happened:\n %s\n", str);
+ (*vex_failure_exit)();
+}
+
+
+/*---------------------------------------------------------*/
+/*--- vex_printf ---*/
+/*---------------------------------------------------------*/
+
+/* This should be the only <...> include in the entire VEX library.
+ New code for vex_util.c should go above this point. */
+#include <stdarg.h>
+
+/* ---------------------------------------------------------------------
+ printf implementation. The key function, vg_vprintf(), emits chars
+ into a caller-supplied function. Distantly derived from:
+
+ vprintf replacement for Checker.
+ Copyright 1993, 1994, 1995 Tristan Gingold
+ Written September 1993 Tristan Gingold
+ Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
+
+ (Checker itself was GPL'd.)
+ ------------------------------------------------------------------ */
+
+static Char vex_toupper ( Char c )
+{
+ if (c >= 'a' && c <= 'z')
+ return c + ('A' - 'a');
+ else
+ return c;
+}
+
+static Int vex_strlen ( const Char* str )
+{
+ Int i = 0;
+ while (str[i] != 0) i++;
+ return i;
+}
+
+
+/* Some flags. */
+#define VG_MSG_SIGNED 1 /* The value is signed. */
+#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
+#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
+#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
+#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
+
+/* Copy a string into the buffer. */
+static UInt
+myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
+ Bool capitalise )
+{
+# define MAYBE_TOUPPER(ch) (capitalise ? vex_toupper(ch) : (ch))
+ UInt ret = 0;
+ Int i, extra;
+ Int len = vex_strlen(str);
+
+ if (width == 0) {
+ ret += len;
+ for (i = 0; i < len; i++)
+ send(MAYBE_TOUPPER(str[i]));
+ return ret;
+ }
+
+ if (len > width) {
+ ret += width;
+ for (i = 0; i < width; i++)
+ send(MAYBE_TOUPPER(str[i]));
+ return ret;
+ }
+
+ extra = width - len;
+ if (flags & VG_MSG_LJUSTIFY) {
+ ret += extra;
+ for (i = 0; i < extra; i++)
+ send(' ');
+ }
+ ret += len;
+ for (i = 0; i < len; i++)
+ send(MAYBE_TOUPPER(str[i]));
+ if (!(flags & VG_MSG_LJUSTIFY)) {
+ ret += extra;
+ for (i = 0; i < extra; i++)
+ send(' ');
+ }
+
+# undef MAYBE_TOUPPER
+
+ return ret;
+}
+
+/* Write P into the buffer according to these args:
+ * If SIGN is true, p is a signed.
+ * BASE is the base.
+ * If WITH_ZERO is true, '0' must be added.
+ * WIDTH is the width of the field.
+ */
+static UInt
+myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
+{
+ Char buf[40];
+ Int ind = 0;
+ Int i, nc = 0;
+ Bool neg = False;
+ Char *digits = "0123456789ABCDEF";
+ UInt ret = 0;
+
+ if (base < 2 || base > 16)
+ return ret;
+
+ if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
+ p = - (Long)p;
+ neg = True;
+ }
+
+ if (p == 0)
+ buf[ind++] = '0';
+ else {
+ while (p > 0) {
+ if (flags & VG_MSG_COMMA && 10 == base &&
+ 0 == (ind-nc) % 3 && 0 != ind)
+ {
+ buf[ind++] = ',';
+ nc++;
+ }
+ buf[ind++] = digits[p % base];
+ p /= base;
+ }
+ }
+
+ if (neg)
+ buf[ind++] = '-';
+
+ if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
+ for(; ind < width; ind++) {
+ vassert(ind < 39);
+ buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
+ }
+ }
+
+ /* Reverse copy to buffer. */
+ ret += ind;
+ for (i = ind -1; i >= 0; i--) {
+ send(buf[i]);
+ }
+ if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
+ for(; ind < width; ind++) {
+ ret++;
+ send(' '); // Never pad with zeroes on RHS -- changes the value!
+ }
+ }
+ return ret;
+}
+
+
+/* A simple vprintf(). */
+static
+UInt vprintf_wrk ( void(*send)(Char), const Char *format, va_list vargs )
+{
+ UInt ret = 0;
+ int i;
+ int flags;
+ int width;
+ Bool is_long;
+
+ /* We assume that vargs has already been initialised by the
+ caller, using va_start, and that the caller will similarly
+ clean up with va_end.
+ */
+
+ for (i = 0; format[i] != 0; i++) {
+ if (format[i] != '%') {
+ send(format[i]);
+ ret++;
+ continue;
+ }
+ i++;
+ /* A '%' has been found. Ignore a trailing %. */
+ if (format[i] == 0)
+ break;
+ if (format[i] == '%') {
+ /* `%%' is replaced by `%'. */
+ send('%');
+ ret++;
+ continue;
+ }
+ flags = 0;
+ is_long = False;
+ width = 0; /* length of the field. */
+ if (format[i] == '(') {
+ flags |= VG_MSG_PAREN;
+ i++;
+ }
+ /* If ',' follows '%', commas will be inserted. */
+ if (format[i] == ',') {
+ flags |= VG_MSG_COMMA;
+ i++;
+ }
+ /* If '-' follows '%', justify on the left. */
+ if (format[i] == '-') {
+ flags |= VG_MSG_LJUSTIFY;
+ i++;
+ }
+ /* If '0' follows '%', pads will be inserted. */
+ if (format[i] == '0') {
+ flags |= VG_MSG_ZJUSTIFY;
+ i++;
+ }
+ /* Compute the field length. */
+ while (format[i] >= '0' && format[i] <= '9') {
+ width *= 10;
+ width += format[i++] - '0';
+ }
+ while (format[i] == 'l') {
+ i++;
+ is_long = True;
+ }
+
+ switch (format[i]) {
+ case 'd': /* %d */
+ flags |= VG_MSG_SIGNED;
+ if (is_long)
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, Long)));
+ else
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, Int)));
+ break;
+ case 'u': /* %u */
+ if (is_long)
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, ULong)));
+ else
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, UInt)));
+ break;
+ case 'p': /* %p */
+ ret += 2;
+ send('0');
+ send('x');
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)((UInt)va_arg (vargs, void *)));
+ break;
+ case 'x': /* %x */
+ if (is_long)
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)(va_arg (vargs, ULong)));
+ else
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)(va_arg (vargs, UInt)));
+ break;
+ case 'c': /* %c */
+ ret++;
+ send(va_arg (vargs, int));
+ break;
+ case 's': case 'S': { /* %s */
+ char *str = va_arg (vargs, char *);
+ if (str == (char*) 0) str = "(null)";
+ ret += myvprintf_str(send, flags, width, str, format[i]=='S');
+ break;
+ }
+# if 0
+ case 'y': { /* %y - print symbol */
+ Char buf[100];
+ Char *cp = buf;
+ Addr a = va_arg(vargs, Addr);
+
+ if (flags & VG_MSG_PAREN)
+ *cp++ = '(';
+ if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+ if (flags & VG_MSG_PAREN) {
+ cp += VG_(strlen)(cp);
+ *cp++ = ')';
+ *cp = '\0';
+ }
+ ret += myvprintf_str(send, flags, width, buf, 0);
+ }
+ break;
+ }
+# endif
+ default:
+ break;
+ }
+ }
+ return ret;
+}
+
+
+/* A general replacement for printf(). Note that only low-level
+ debugging info should be sent via here. The official route is to
+ to use vg_message(). This interface is deprecated.
+*/
+static Char myprintf_buf[1000];
+static Int n_myprintf_buf;
+
+static void add_to_myprintf_buf ( Char c )
+{
+ if (c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/ ) {
+ (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
+ n_myprintf_buf = 0;
+ myprintf_buf[n_myprintf_buf] = 0;
+ }
+ myprintf_buf[n_myprintf_buf++] = c;
+ myprintf_buf[n_myprintf_buf] = 0;
+}
+
+UInt vex_printf ( const char *format, ... )
+{
+ UInt ret;
+ va_list vargs;
+ va_start(vargs,format);
+
+ n_myprintf_buf = 0;
+ myprintf_buf[n_myprintf_buf] = 0;
+ ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
+
+ if (n_myprintf_buf > 0) {
+ (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
+ }
+
+ va_end(vargs);
+
+ return ret;
+}
+
+
+/*---------------------------------------------------------------*/
+/*--- end vex_util.c ---*/
+/*---------------------------------------------------------------*/