Merge [1962], [1963], [1971], and [1983] from trunk: NASM2 compatibility
additions.
[1962]: Support oword, do, and reso as aliases for dqword, ddq, and resdq.
[1963], [1971]: Support NASM2 RIP-relative syntax.
The primary difference from NASM2 will be the handling of immediate values
in the "mov reg64, imm" where immediate is unsized; yasm has always
auto-sized this to 32-bit by default, and upsized to 64-bit if necessary
for non-relocated values. NASM2 will default this to 64-bit for all values.
Code expecting to target both with consistent results should explicitly
specify the immediate size.
svn path=/branches/yasm-0.6.x/; revision=1984
diff --git a/Makefile.am b/Makefile.am
index 3eae0cb..67e3bf6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -109,13 +109,6 @@
distclean-local:
-rm -rf results
-if HAVE_PYTHON
- -rm -rf build
-endif
-
-all-local: python-build
-install-exec-hook: python-install
-uninstall-hook: python-uninstall
if BUILD_MAN
MAINTAINERCLEANFILES += $(dist_man_MANS)
diff --git a/Mkfiles/Makefile.dj b/Mkfiles/Makefile.dj
index ffb48fe..09f2a4e 100644
--- a/Mkfiles/Makefile.dj
+++ b/Mkfiles/Makefile.dj
@@ -55,15 +55,15 @@
x86regtmod.o
YASM_MODULES=arch_x86
-MODULES_ARCH_LC3B_OBJS= \
- modules/arch/lc3b/lc3barch.o \
- modules/arch/lc3b/lc3bbc.o \
- lc3bid.o
-YASM_MODULES+=arch_lc3b
+#MODULES_ARCH_LC3B_OBJS= \
+# modules/arch/lc3b/lc3barch.o \
+# modules/arch/lc3b/lc3bbc.o \
+# lc3bid.o
+#YASM_MODULES+=arch_lc3b
MODULES_ARCH_OBJS= \
$(MODULES_ARCH_X86_OBJS) \
- $(MODULES_ARCH_LC3B_OBJS)
+# $(MODULES_ARCH_LC3B_OBJS)
MODULES_DBGFMTS_OBJS= \
modules/dbgfmts/null/null-dbgfmt.o \
diff --git a/Mkfiles/Makefile.flat b/Mkfiles/Makefile.flat
index b138e4b..3541a4d 100644
--- a/Mkfiles/Makefile.flat
+++ b/Mkfiles/Makefile.flat
@@ -58,15 +58,15 @@
x86regtmod.o
YASM_MODULES=arch_x86
-MODULES_ARCH_LC3B_OBJS= \
- modules/arch/lc3b/lc3barch.o \
- modules/arch/lc3b/lc3bbc.o \
- lc3bid.o
-YASM_MODULES+=arch_lc3b
+#MODULES_ARCH_LC3B_OBJS= \
+# modules/arch/lc3b/lc3barch.o \
+# modules/arch/lc3b/lc3bbc.o \
+# lc3bid.o
+#YASM_MODULES+=arch_lc3b
MODULES_ARCH_OBJS= \
$(MODULES_ARCH_X86_OBJS) \
- $(MODULES_ARCH_LC3B_OBJS)
+# $(MODULES_ARCH_LC3B_OBJS)
MODULES_DBGFMTS_OBJS= \
modules/dbgfmts/null/null-dbgfmt.o \
diff --git a/Mkfiles/dj/config.h b/Mkfiles/dj/config.h
index f9faf33..5e7b01f 100644
--- a/Mkfiles/dj/config.h
+++ b/Mkfiles/dj/config.h
@@ -116,22 +116,22 @@
#define PACKAGE_BUGREPORT "bug-yasm@tortall.net"
/* Define to build version of this package. */
-#define PACKAGE_BUILD "HEAD"
+#define PACKAGE_BUILD "BRANCH"
/* Define to internal version of this package. */
-#define PACKAGE_INTVER "0.6.99"
+#define PACKAGE_INTVER "0.6.2"
/* Define to the full name of this package. */
#define PACKAGE_NAME "yasm"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "yasm HEAD"
+#define PACKAGE_STRING "yasm 0.6.x"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "yasm"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "HEAD"
+#define PACKAGE_VERSION "0.6.x"
/* Define if the C compiler supports function prototypes. */
#define PROTOTYPES 1
@@ -155,7 +155,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "HEAD"
+#define VERSION "0.6.x"
/* Define if using the dmalloc debugging malloc package */
/* #undef WITH_DMALLOC */
diff --git a/Mkfiles/vc/config.h b/Mkfiles/vc/config.h
index e78ddf2..244b3ea 100644
--- a/Mkfiles/vc/config.h
+++ b/Mkfiles/vc/config.h
@@ -117,22 +117,22 @@
#define PACKAGE_BUGREPORT "bug-yasm@tortall.net"
/* Define to build version of this package. */
-#define PACKAGE_BUILD "HEAD"
+#define PACKAGE_BUILD "BRANCH"
/* Define to internal version of this package. */
-#define PACKAGE_INTVER "0.6.99"
+#define PACKAGE_INTVER "0.6.2"
/* Define to the full name of this package. */
#define PACKAGE_NAME "yasm"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "yasm HEAD"
+#define PACKAGE_STRING "yasm 0.6.x"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "yasm"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "HEAD"
+#define PACKAGE_VERSION "0.6.x"
/* Define if the C compiler supports function prototypes. */
#define PROTOTYPES 1
@@ -156,7 +156,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "HEAD"
+#define VERSION "0.6.x"
/* Define if using the dmalloc debugging malloc package */
/* #undef WITH_DMALLOC */
diff --git a/Mkfiles/vc8/config.h b/Mkfiles/vc8/config.h
index 50369a0..5cba398 100644
--- a/Mkfiles/vc8/config.h
+++ b/Mkfiles/vc8/config.h
@@ -117,22 +117,22 @@
#define PACKAGE_BUGREPORT "bug-yasm@tortall.net"
/* Define to build version of this package. */
-#define PACKAGE_BUILD "HEAD"
+#define PACKAGE_BUILD "BRANCH"
/* Define to internal version of this package. */
-#define PACKAGE_INTVER "0.6.99"
+#define PACKAGE_INTVER "0.6.2"
/* Define to the full name of this package. */
#define PACKAGE_NAME "yasm"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "yasm HEAD"
+#define PACKAGE_STRING "yasm 0.6.x"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "yasm"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "HEAD"
+#define PACKAGE_VERSION "0.6.x"
/* Define if the C compiler supports function prototypes. */
#define PROTOTYPES 1
@@ -156,7 +156,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "HEAD"
+#define VERSION "0.6.x"
/* Define if using the dmalloc debugging malloc package */
/* #undef WITH_DMALLOC */
diff --git a/configure.ac b/configure.ac
index f539d12..330ff73 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,17 +5,17 @@
# autoconf setup
#
AC_PREREQ(2.53)
-AC_INIT([yasm], [HEAD], [bug-yasm@tortall.net])
+AC_INIT([yasm], [0.6.x], [bug-yasm@tortall.net])
#AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_AUX_DIR(config)
AM_CONFIG_HEADER([config.h])
-AM_INIT_AUTOMAKE(yasm, [HEAD])
+AM_INIT_AUTOMAKE(yasm, [0.6.x])
AM_MAINTAINER_MODE
-AC_DEFINE(PACKAGE_INTVER, ["0.6.99"],
+AC_DEFINE(PACKAGE_INTVER, ["0.6.2"],
[Define to internal version of this package.])
-AC_DEFINE(PACKAGE_BUILD, ["HEAD"], [Define to build version of this package.])
+AC_DEFINE(PACKAGE_BUILD, ["BRANCH"], [Define to build version of this package.])
#
# autoconf command-line options
@@ -61,14 +61,6 @@
*) AC_MSG_ERROR([bad value ${enableval} for --enable-python]) ;;
esac], enable_python="auto")
-AC_ARG_ENABLE(python-bindings,
-AC_HELP_STRING([--enable-python-bindings],[Build Python bindings]),
-[case "${enableval}" in
- yes) enable_python_bindings="yes" ;;
- no) enable_python_bindings="no" ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --enable-python-bindings]) ;;
-esac], enable_python_bindings="auto")
-
#
# Checks for programs.
#
@@ -279,38 +271,7 @@
fi
fi
-# Detect if we can build Python bindings
-# (needs Python, Python headers, and Pyrex)
-if test x$enable_python_bindings = xno; then
- have_python_bindings=no
-else
- AC_MSG_NOTICE([Checking to see if we can build Python bindings])
- have_python_bindings=no
- if test x$have_python = xyes; then
- AC_MSG_CHECKING([for Pyrex >= 0.9.5.1])
- PYREX_CHECK_VERSION(0.9.5.1, [AC_MSG_RESULT(yes)
- have_pyrex=yes],
- [AC_MSG_RESULT(no)
- have_pyrex=no])
-
- AM_CHECK_PYTHON_HEADERS(have_python_headers=yes,have_python_headers=no)
-
- if test x$have_pyrex = xyes -a x$have_python_headers = xyes ; then
- have_python_bindings=yes
- fi
- fi
-
- if test x$have_python_bindings = xno ; then
- if test x$enable_python_bindings = xyes ; then
- AC_MSG_ERROR([Building Python bindings explicitly requested, but can't build Python bindings because either Pyrex, Python headers or a suitable Python version was not found])
- else
- AC_MSG_WARN([Couldn't find either Pyrex, the Python headers or a suitable version of Python, not building Python bindings])
- fi
- fi
-fi
-
AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes)
-AM_CONDITIONAL(HAVE_PYTHON_BINDINGS, test x$have_python_bindings = xyes)
AC_CONFIG_FILES([Makefile
po/Makefile.in
diff --git a/libyasm/intnum.c b/libyasm/intnum.c
index 5fc177b..2820fa2 100644
--- a/libyasm/intnum.c
+++ b/libyasm/intnum.c
@@ -462,14 +462,14 @@
Set_Complement(result, result);
break;
case YASM_EXPR_SHL:
- if (operand->type == INTNUM_L && operand->val.l > 0) {
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
BitVector_Copy(result, op1);
BitVector_Move_Left(result, (N_int)operand->val.l);
} else /* don't even bother, just zero result */
BitVector_Empty(result);
break;
case YASM_EXPR_SHR:
- if (operand->type == INTNUM_L && operand->val.l > 0) {
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
BitVector_Copy(result, op1);
carry = BitVector_msb_(op1);
count = (N_int)operand->val.l;
diff --git a/libyasm/tests/1shl0.asm b/libyasm/tests/1shl0.asm
new file mode 100644
index 0000000..d69930a
--- /dev/null
+++ b/libyasm/tests/1shl0.asm
@@ -0,0 +1 @@
+dd (1<<0)
diff --git a/libyasm/tests/1shl0.hex b/libyasm/tests/1shl0.hex
new file mode 100644
index 0000000..607fb55
--- /dev/null
+++ b/libyasm/tests/1shl0.hex
@@ -0,0 +1,4 @@
+01
+00
+00
+00
diff --git a/libyasm/tests/Makefile.inc b/libyasm/tests/Makefile.inc
index 1528ef6..e0e3d95 100644
--- a/libyasm/tests/Makefile.inc
+++ b/libyasm/tests/Makefile.inc
@@ -9,6 +9,8 @@
TESTS += libyasm/tests/libyasm_test.sh
EXTRA_DIST += libyasm/tests/libyasm_test.sh
+EXTRA_DIST += libyasm/tests/1shl0.asm
+EXTRA_DIST += libyasm/tests/1shl0.hex
EXTRA_DIST += libyasm/tests/absloop-err.asm
EXTRA_DIST += libyasm/tests/absloop-err.errwarn
EXTRA_DIST += libyasm/tests/charconst64.asm
diff --git a/modules/arch/Makefile.inc b/modules/arch/Makefile.inc
index 1a9f905..7dc98df 100644
--- a/modules/arch/Makefile.inc
+++ b/modules/arch/Makefile.inc
@@ -4,7 +4,7 @@
EXTRA_DIST += modules/arch/lc3b/Makefile.inc
include modules/arch/x86/Makefile.inc
-include modules/arch/lc3b/Makefile.inc
+#include modules/arch/lc3b/Makefile.inc
dist_man_MANS += yasm_arch.7
diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c
index 84f188a..152f6f1 100644
--- a/modules/arch/lc3b/lc3barch.c
+++ b/modules/arch/lc3b/lc3barch.c
@@ -82,6 +82,18 @@
return 1;
}
+static int
+lc3b_parse_directive(/*@unused@*/ yasm_arch *arch,
+ /*@unused@*/ const char *name,
+ /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ /*@unused@*/ yasm_object *object,
+ /*@unused@*/ unsigned long line)
+{
+ return 1;
+}
+
static const unsigned char **
lc3b_get_fill(const yasm_arch *arch)
{
@@ -119,21 +131,21 @@
}
static unsigned int
-lc3b_get_reg_size(/*@unused@*/ yasm_arch *arch, /*@unused@*/ uintptr_t reg)
+lc3b_get_reg_size(/*@unused@*/ yasm_arch *arch, /*@unused@*/ unsigned long reg)
{
return 16;
}
-static uintptr_t
+static unsigned long
lc3b_reggroup_get_reg(/*@unused@*/ yasm_arch *arch,
- /*@unused@*/ uintptr_t reggroup,
+ /*@unused@*/ unsigned long reggroup,
/*@unused@*/ unsigned long regindex)
{
return 0;
}
static void
-lc3b_reg_print(/*@unused@*/ yasm_arch *arch, uintptr_t reg, FILE *f)
+lc3b_reg_print(/*@unused@*/ yasm_arch *arch, unsigned long reg, FILE *f)
{
fprintf(f, "r%u", (unsigned int)(reg&7));
}
@@ -151,30 +163,8 @@
static yasm_effaddr *
lc3b_ea_create_expr(yasm_arch *arch, yasm_expr *e)
{
- yasm_effaddr *ea = yasm_xmalloc(sizeof(yasm_effaddr));
- yasm_value_initialize(&ea->disp, e, 0);
- ea->need_nonzero_len = 0;
- ea->need_disp = 1;
- ea->nosplit = 0;
- ea->strong = 0;
- ea->segreg = 0;
- ea->pc_rel = 0;
- ea->not_pc_rel = 0;
- return ea;
-}
-
-void
-yasm_lc3b__ea_destroy(/*@only@*/ yasm_effaddr *ea)
-{
- yasm_value_delete(&ea->disp);
- yasm_xfree(ea);
-}
-
-static void
-lc3b_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
-{
- fprintf(f, "%*sDisp:\n", indent_level, "");
- yasm_value_print(&ea->disp, f, indent_level+1);
+ yasm_expr_destroy(e);
+ return NULL;
}
/* Define lc3b machines -- see arch.h for details */
@@ -187,15 +177,17 @@
yasm_arch_module yasm_lc3b_LTX_arch = {
"LC-3b",
"lc3b",
- NULL,
lc3b_create,
lc3b_destroy,
lc3b_get_machine,
lc3b_get_address_size,
lc3b_set_var,
+ yasm_lc3b__parse_cpu,
yasm_lc3b__parse_check_insnprefix,
yasm_lc3b__parse_check_regtmod,
+ lc3b_parse_directive,
lc3b_get_fill,
+ yasm_lc3b__finalize_insn,
lc3b_floatnum_tobytes,
yasm_lc3b__intnum_tobytes,
lc3b_get_reg_size,
@@ -203,11 +195,9 @@
lc3b_reg_print,
NULL, /*yasm_lc3b__segreg_print*/
lc3b_ea_create_expr,
- yasm_lc3b__ea_destroy,
- lc3b_ea_print,
- yasm_lc3b__create_empty_insn,
lc3b_machines,
"lc3b",
16,
+ 512,
2
};
diff --git a/modules/arch/lc3b/lc3barch.h b/modules/arch/lc3b/lc3barch.h
index 4de0c45..ff7d97e 100644
--- a/modules/arch/lc3b/lc3barch.h
+++ b/modules/arch/lc3b/lc3barch.h
@@ -45,26 +45,29 @@
yasm_value imm; /* immediate or relative value */
lc3b_imm_type imm_type; /* size of the immediate */
+ /* PC origin if needed */
+ /*@null@*/ /*@dependent@*/ yasm_bytecode *origin_prevbc;
+
unsigned int opcode; /* opcode */
} lc3b_insn;
void yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn);
+void yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len);
+
yasm_arch_insnprefix yasm_lc3b__parse_check_insnprefix
- (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
- /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+ (yasm_arch *arch, unsigned long data[4], const char *id, size_t id_len);
yasm_arch_regtmod yasm_lc3b__parse_check_regtmod
- (yasm_arch *arch, const char *id, size_t id_len,
- /*@out@*/ uintptr_t *data);
+ (yasm_arch *arch, unsigned long *data, const char *id, size_t id_len);
+
+void yasm_lc3b__finalize_insn
+ (yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, int num_prefixes,
+ unsigned long **prefixes, int num_segregs, const unsigned long *segregs);
int yasm_lc3b__intnum_tobytes
(yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
int warn);
-
-/*@only@*/ yasm_bytecode *yasm_lc3b__create_empty_insn(yasm_arch *arch,
- unsigned long line);
-
-void yasm_lc3b__ea_destroy(/*@only@*/ yasm_effaddr *ea);
-
#endif
diff --git a/modules/arch/lc3b/lc3bbc.c b/modules/arch/lc3b/lc3bbc.c
index 3596524..e87aa8f 100644
--- a/modules/arch/lc3b/lc3bbc.c
+++ b/modules/arch/lc3b/lc3bbc.c
@@ -37,12 +37,8 @@
static void lc3b_bc_insn_destroy(void *contents);
static void lc3b_bc_insn_print(const void *contents, FILE *f,
int indent_level);
-static int lc3b_bc_insn_calc_len(yasm_bytecode *bc,
- yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
- long new_val, /*@out@*/ long *neg_thres,
- /*@out@*/ long *pos_thres);
+static yasm_bc_resolve_flags lc3b_bc_insn_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
void *d, yasm_output_value_func output_value,
/*@null@*/ yasm_output_reloc_func output_reloc);
@@ -53,8 +49,7 @@
lc3b_bc_insn_destroy,
lc3b_bc_insn_print,
yasm_bc_finalize_common,
- lc3b_bc_insn_calc_len,
- lc3b_bc_insn_expand,
+ lc3b_bc_insn_resolve,
lc3b_bc_insn_tobytes,
0
};
@@ -128,39 +123,56 @@
(unsigned int)insn->opcode);
}
-static int
-lc3b_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
+static yasm_bc_resolve_flags
+lc3b_bc_insn_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
{
lc3b_insn *insn = (lc3b_insn *)bc->contents;
yasm_bytecode *target_prevbc;
+ /*@only@*/ yasm_intnum *num;
+ long rel;
/* Fixed size instruction length */
- bc->len += 2;
+ bc->len = 2;
- /* Only need to worry about out-of-range to PC-relative */
- if (insn->imm_type != LC3B_IMM_9_PC)
- return 0;
+ /* Only need to worry about out-of-range to PC-relative, and only if we're
+ * saving.
+ */
+ if (insn->imm_type != LC3B_IMM_9_PC || !save)
+ return YASM_BC_RESOLVE_MIN_LEN;
- if (insn->imm.rel
- && (!yasm_symrec_get_label(insn->imm.rel, &target_prevbc)
- || target_prevbc->section != bc->section)) {
+ if (!insn->imm.rel)
+ num = yasm_intnum_create_uint(0);
+ else if (!yasm_symrec_get_label(insn->imm.rel, &target_prevbc)
+ || target_prevbc->section != insn->origin_prevbc->section
+ || !(num = calc_bc_dist(insn->origin_prevbc, target_prevbc))) {
/* External or out of segment, so we can't check distance. */
- return 0;
+ return YASM_BC_RESOLVE_MIN_LEN;
}
- /* 9-bit signed, word-multiple displacement */
- add_span(add_span_data, bc, 1, &insn->imm, -512+(long)bc->len,
- 511+(long)bc->len);
- return 0;
-}
+ if (insn->imm.abs) {
+ /*@only@*/ yasm_expr *temp = yasm_expr_copy(insn->imm.abs);
+ /*@dependent@*/ /*@null@*/ yasm_intnum *num2;
+ num2 = yasm_expr_get_intnum(&temp, calc_bc_dist);
+ if (!num2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target too complex"));
+ yasm_expr_destroy(temp);
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+ yasm_intnum_calc(num, YASM_EXPR_ADD, num2);
+ yasm_expr_destroy(temp);
+ }
-static int
-lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
-{
- yasm_error_set(YASM_ERROR_VALUE, N_("jump target out of range"));
- return -1;
+ rel = yasm_intnum_get_int(num);
+ yasm_intnum_destroy(num);
+ rel -= 2;
+ /* 9-bit signed, word-multiple displacement */
+ if (rel < -512 || rel > 511) {
+ yasm_error_set(YASM_ERROR_OVERFLOW, N_("target out of range"));
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+ return YASM_BC_RESOLVE_MIN_LEN;
}
static int
@@ -185,8 +197,7 @@
break;
case LC3B_IMM_5:
insn->imm.size = 5;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, 0, bc, 1, d))
+ if (output_value(&insn->imm, *bufp, 2, 0, bc, -1, d))
return 1;
break;
case LC3B_IMM_6_WORD:
@@ -196,8 +207,7 @@
break;
case LC3B_IMM_6_BYTE:
insn->imm.size = 6;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, 0, bc, 1, d))
+ if (output_value(&insn->imm, *bufp, 2, 0, bc, -1, d))
return 1;
break;
case LC3B_IMM_8:
@@ -218,8 +228,7 @@
yasm_expr_int(delta), bc->line);
insn->imm.size = 9;
- insn->imm.sign = 1;
- if (output_value(&insn->imm, *bufp, 2, 0, bc, 1, d))
+ if (output_value(&insn->imm, *bufp, 2, 0, bc, -1, d))
return 1;
break;
case LC3B_IMM_9:
diff --git a/modules/arch/lc3b/lc3bid.re b/modules/arch/lc3b/lc3bid.re
index bfbf78b..2529664 100644
--- a/modules/arch/lc3b/lc3bid.re
+++ b/modules/arch/lc3b/lc3bid.re
@@ -107,41 +107,22 @@
unsigned int operands[3];
} lc3b_insn_info;
-typedef struct lc3b_id_insn {
- yasm_insn insn; /* base structure */
+/* Define lexer arch-specific data with 0-3 modifiers. */
+#define DEF_INSN_DATA(group, mod) do { \
+ data[0] = (unsigned long)group##_insn; \
+ data[1] = ((mod)<<8) | \
+ ((unsigned char)(sizeof(group##_insn)/sizeof(lc3b_insn_info))); \
+ } while (0)
- /* instruction parse group - NULL if empty instruction (just prefixes) */
- /*@null@*/ const lc3b_insn_info *group;
-
- /* Modifier data */
- unsigned long mod_data;
-
- /* Number of elements in the instruction parse group */
- unsigned int num_info:8;
-} lc3b_id_insn;
-
-static void lc3b_id_insn_destroy(void *contents);
-static void lc3b_id_insn_print(const void *contents, FILE *f, int indent_level);
-static void lc3b_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-
-static const yasm_bytecode_callback lc3b_id_insn_callback = {
- lc3b_id_insn_destroy,
- lc3b_id_insn_print,
- lc3b_id_insn_finalize,
- yasm_bc_calc_len_common,
- yasm_bc_expand_common,
- yasm_bc_tobytes_common,
- YASM_BC_SPECIAL_INSN
-};
+#define RET_INSN(group, mod) do { \
+ DEF_INSN_DATA(group, mod); \
+ return YASM_ARCH_INSN; \
+ } while (0)
/*
* Instruction groupings
*/
-static const lc3b_insn_info empty_insn[] = {
- { 0, 0, 0, {0, 0, 0} }
-};
-
static const lc3b_insn_info addand_insn[] = {
{ MOD_OpHAdd, 0x1000, 3,
{OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Reg|OPA_Imm|OPI_5} },
@@ -188,20 +169,22 @@
{ 0, 0xF000, 1, {OPT_Imm|OPA_Imm|OPI_8, 0, 0} }
};
-static void
-lc3b_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+void
+yasm_lc3b__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
+ yasm_bytecode *prev_bc, const unsigned long data[4],
+ int num_operands,
+ /*@null@*/ yasm_insn_operands *operands,
+ int num_prefixes, unsigned long **prefixes,
+ int num_segregs, const unsigned long *segregs)
{
- lc3b_id_insn *id_insn = (lc3b_id_insn *)bc->contents;
lc3b_insn *insn;
- int num_info = id_insn->num_info;
- const lc3b_insn_info *info = id_insn->group;
- unsigned long mod_data = id_insn->mod_data;
+ int num_info = (int)(data[1]&0xFF);
+ lc3b_insn_info *info = (lc3b_insn_info *)data[0];
+ unsigned long mod_data = data[1] >> 8;
int found = 0;
yasm_insn_operand *op;
int i;
- yasm_insn_finalize(&id_insn->insn);
-
/* Just do a simple linear search through the info array for a match.
* First match wins.
*/
@@ -209,18 +192,17 @@
int mismatch = 0;
/* Match # of operands */
- if (id_insn->insn.num_operands != info->num_operands)
+ if (num_operands != info->num_operands)
continue;
- if (id_insn->insn.num_operands == 0) {
+ if (!operands) {
found = 1; /* no operands -> must have a match here. */
break;
}
/* Match each operand type and size */
- for(i = 0, op = yasm_insn_ops_first(&id_insn->insn);
- op && i<info->num_operands && !mismatch;
- op = yasm_insn_op_next(op), i++) {
+ for(i = 0, op = yasm_ops_first(operands); op && i<info->num_operands &&
+ !mismatch; op = yasm_operand_next(op), i++) {
/* Check operand type */
switch ((int)(info->operands[i] & OPT_MASK)) {
case OPT_Imm:
@@ -256,6 +238,7 @@
insn = yasm_xmalloc(sizeof(lc3b_insn));
yasm_value_initialize(&insn->imm, NULL, 0);
insn->imm_type = LC3B_IMM_NONE;
+ insn->origin_prevbc = NULL;
insn->opcode = info->opcode;
/* Apply modifiers */
@@ -269,9 +252,9 @@
}
/* Go through operands and assign */
- if (id_insn->insn.num_operands > 0) {
- for(i = 0, op = yasm_insn_ops_first(&id_insn->insn);
- op && i<info->num_operands; op = yasm_insn_op_next(op), i++) {
+ if (operands) {
+ for(i = 0, op = yasm_ops_first(operands); op && i<info->num_operands;
+ op = yasm_operand_next(op), i++) {
switch ((int)(info->operands[i] & OPA_MASK)) {
case OPA_None:
@@ -302,8 +285,7 @@
yasm_expr_int(yasm_intnum_create_uint(1)),
op->data.val->line);
if (yasm_value_finalize_expr(&insn->imm,
- op->data.val,
- prev_bc, 0))
+ op->data.val, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("immediate expression too complex"));
break;
@@ -311,7 +293,7 @@
if (yasm_value_finalize_expr(&insn->imm,
yasm_expr_create_ident(yasm_expr_int(
yasm_intnum_create_uint(op->data.reg & 0x7)),
- bc->line), prev_bc, 0))
+ bc->line), 0))
yasm_internal_error(N_("reg expr too complex?"));
break;
default:
@@ -321,12 +303,10 @@
default:
yasm_internal_error(N_("unknown operand action"));
}
-
- /* Clear so it doesn't get destroyed */
- op->type = YASM_INSN__OPERAND_REG;
}
if (insn->imm_type == LC3B_IMM_9_PC) {
+ insn->origin_prevbc = prev_bc;
if (insn->imm.seg_of || insn->imm.rshift > 1
|| insn->imm.curpos_rel)
yasm_error_set(YASM_ERROR_VALUE, N_("invalid jump target"));
@@ -345,9 +325,14 @@
#define YYMARKER marker
#define YYFILL(n) (void)(n)
+void
+yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len)
+{
+}
+
yasm_arch_regtmod
-yasm_lc3b__parse_check_regtmod(yasm_arch *arch, const char *oid, size_t id_len,
- uintptr_t *data)
+yasm_lc3b__parse_check_regtmod(yasm_arch *arch, unsigned long *data,
+ const char *oid, size_t id_len)
{
const YYCTYPE *id = (const YYCTYPE *)oid;
/*const char *marker;*/
@@ -368,28 +353,11 @@
*/
}
-#define RET_INSN(g, m) \
- do { \
- group = g##_insn; \
- mod = m; \
- nelems = NELEMS(g##_insn); \
- goto done; \
- } while(0)
-
yasm_arch_insnprefix
-yasm_lc3b__parse_check_insnprefix(yasm_arch *arch, const char *oid,
- size_t id_len, unsigned long line,
- yasm_bytecode **bc, uintptr_t *prefix)
+yasm_lc3b__parse_check_insnprefix(yasm_arch *arch, unsigned long data[4],
+ const char *oid, size_t id_len)
{
const YYCTYPE *id = (const YYCTYPE *)oid;
- const lc3b_insn_info *group = empty_insn;
- unsigned long mod = 0;
- unsigned int nelems = NELEMS(empty_insn);
- lc3b_id_insn *id_insn;
-
- *bc = (yasm_bytecode *)NULL;
- *prefix = 0;
-
/*const char *marker;*/
/*!re2c
/* instructions */
@@ -439,42 +407,4 @@
return YASM_ARCH_NOTINSNPREFIX;
}
*/
-
-done:
- id_insn = yasm_xmalloc(sizeof(lc3b_id_insn));
- yasm_insn_initialize(&id_insn->insn);
- id_insn->group = group;
- id_insn->mod_data = mod;
- id_insn->num_info = nelems;
- *bc = yasm_bc_create_common(&lc3b_id_insn_callback, id_insn, line);
- return YASM_ARCH_INSN;
-}
-
-static void
-lc3b_id_insn_destroy(void *contents)
-{
- lc3b_id_insn *id_insn = (lc3b_id_insn *)contents;
- yasm_insn_delete(&id_insn->insn, yasm_lc3b__ea_destroy);
- yasm_xfree(contents);
-}
-
-static void
-lc3b_id_insn_print(const void *contents, FILE *f, int indent_level)
-{
- const lc3b_id_insn *id_insn = (const lc3b_id_insn *)contents;
- yasm_insn_print(&id_insn->insn, f, indent_level);
- /*TODO*/
-}
-
-/*@only@*/ yasm_bytecode *
-yasm_lc3b__create_empty_insn(yasm_arch *arch, unsigned long line)
-{
- lc3b_id_insn *id_insn = yasm_xmalloc(sizeof(lc3b_id_insn));
-
- yasm_insn_initialize(&id_insn->insn);
- id_insn->group = empty_insn;
- id_insn->mod_data = 0;
- id_insn->num_info = NELEMS(empty_insn);
-
- return yasm_bc_create_common(&lc3b_id_insn_callback, id_insn, line);
}
diff --git a/modules/arch/lc3b/tests/Makefile.inc b/modules/arch/lc3b/tests/Makefile.inc
index 43b861e..43ffb70 100644
--- a/modules/arch/lc3b/tests/Makefile.inc
+++ b/modules/arch/lc3b/tests/Makefile.inc
@@ -7,8 +7,10 @@
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-basic.errwarn
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-basic.hex
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-br.asm
+EXTRA_DIST += modules/arch/lc3b/tests/lc3b-br.errwarn
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-br.hex
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-ea-err.asm
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-ea-err.errwarn
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-mp22NC.asm
+EXTRA_DIST += modules/arch/lc3b/tests/lc3b-mp22NC.errwarn
EXTRA_DIST += modules/arch/lc3b/tests/lc3b-mp22NC.hex
diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc
index 3bd57e0..8776117 100644
--- a/modules/arch/x86/tests/Makefile.inc
+++ b/modules/arch/x86/tests/Makefile.inc
@@ -55,6 +55,9 @@
EXTRA_DIST += modules/arch/x86/tests/fwdequ64.hex
EXTRA_DIST += modules/arch/x86/tests/genopcode.asm
EXTRA_DIST += modules/arch/x86/tests/genopcode.hex
+EXTRA_DIST += modules/arch/x86/tests/imm64.asm
+EXTRA_DIST += modules/arch/x86/tests/imm64.errwarn
+EXTRA_DIST += modules/arch/x86/tests/imm64.hex
EXTRA_DIST += modules/arch/x86/tests/iret.asm
EXTRA_DIST += modules/arch/x86/tests/iret.hex
EXTRA_DIST += modules/arch/x86/tests/jmp64-1.asm
diff --git a/modules/arch/x86/tests/imm64.asm b/modules/arch/x86/tests/imm64.asm
new file mode 100644
index 0000000..5b41bfa
--- /dev/null
+++ b/modules/arch/x86/tests/imm64.asm
@@ -0,0 +1,35 @@
+bits 64
+default abs
+;extern label1
+label1:
+label2:
+
+mov rax, 0x1000 ; 32-bit imm
+mov rax, 0x1122334455667788 ; 64-bit imm (larger than signed 32-bit)
+;mov rax, 0x80000000 ; 64-bit imm (larger than signed 32-bit)
+mov rax, label1 ; 32-bit imm <--- not 64-bit!
+mov rax, label2 ; 32-bit imm <--- not 64-bit!
+mov rax, qword 0x1000 ; 64-bit imm
+mov rax, qword label1 ; 64-bit imm
+mov rax, qword label2 ; 64-bit imm
+
+mov qword [rax], 0x1000 ; 32-bit imm
+mov qword [rax], 0x1122334455667788 ; 32-bit imm, overflow warning
+;mov qword [rax], 0x80000000 ; 32-bit imm, overflow warning
+mov qword [rax], label1 ; 32-bit imm (matches default above)
+mov qword [rax], label2 ; 32-bit imm (matches default above)
+
+add rax, 0x1000 ; 32-bit imm
+add rax, 0x1122334455667788 ; 32-bit imm, overflow warning
+;add rax, 0x80000000 ; 32-bit imm, overflow warning
+add rax, label1 ; 32-bit imm (matches default above)
+add rax, label2 ; 32-bit imm (matches default above)
+
+mov [0x1000], rax ; 32-bit disp
+mov [abs 0x1122334455667788], rax ; 64-bit disp
+mov [label1], rax ; 32-bit disp
+mov [label2], rax ; 32-bit disp
+mov [qword 0x1000], rax ; 64-bit disp
+mov [qword label1], rax ; 64-bit disp
+mov [qword label2], rax ; 64-bit disp
+
diff --git a/modules/arch/x86/tests/imm64.errwarn b/modules/arch/x86/tests/imm64.errwarn
new file mode 100644
index 0000000..a048735
--- /dev/null
+++ b/modules/arch/x86/tests/imm64.errwarn
@@ -0,0 +1,3 @@
+-:17: warning: value does not fit in 32 bit field
+-:23: warning: value does not fit in 32 bit field
+-:29: warning: value does not fit in 32 bit field
diff --git a/modules/arch/x86/tests/imm64.hex b/modules/arch/x86/tests/imm64.hex
new file mode 100644
index 0000000..af46a71
--- /dev/null
+++ b/modules/arch/x86/tests/imm64.hex
@@ -0,0 +1,175 @@
+48
+c7
+c0
+00
+10
+00
+00
+48
+b8
+88
+77
+66
+55
+44
+33
+22
+11
+48
+c7
+c0
+00
+00
+00
+00
+48
+c7
+c0
+00
+00
+00
+00
+48
+b8
+00
+10
+00
+00
+00
+00
+00
+00
+48
+b8
+00
+00
+00
+00
+00
+00
+00
+00
+48
+b8
+00
+00
+00
+00
+00
+00
+00
+00
+48
+c7
+00
+00
+10
+00
+00
+48
+c7
+00
+88
+77
+66
+55
+48
+c7
+00
+00
+00
+00
+00
+48
+c7
+00
+00
+00
+00
+00
+48
+05
+00
+10
+00
+00
+48
+05
+88
+77
+66
+55
+48
+05
+00
+00
+00
+00
+48
+05
+00
+00
+00
+00
+48
+89
+04
+25
+00
+10
+00
+00
+48
+89
+04
+25
+88
+77
+66
+55
+48
+89
+04
+25
+00
+00
+00
+00
+48
+89
+04
+25
+00
+00
+00
+00
+48
+a3
+00
+10
+00
+00
+00
+00
+00
+00
+48
+a3
+00
+00
+00
+00
+00
+00
+00
+00
+48
+a3
+00
+00
+00
+00
+00
+00
+00
+00
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 34438fa..0eb3eb5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -25,8 +25,8 @@
libyasm/valparam.c
libyasm/value.c
libyasm/xmalloc.c
-modules/arch/lc3b/lc3barch.c
-modules/arch/lc3b/lc3bbc.c
+#modules/arch/lc3b/lc3barch.c
+#modules/arch/lc3b/lc3bbc.c
modules/arch/x86/x86arch.c
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
@@ -55,7 +55,6 @@
modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-token.re
modules/preprocs/cpp/cpp-preproc.c
-modules/preprocs/yapp/yapp-preproc.c
modules/preprocs/nasm/nasm-preproc.c
modules/preprocs/nasm/nasm-pp.c
modules/preprocs/raw/raw-preproc.c
diff --git a/tools/Makefile.inc b/tools/Makefile.inc
index 984578b..dac917d 100644
--- a/tools/Makefile.inc
+++ b/tools/Makefile.inc
@@ -2,8 +2,6 @@
EXTRA_DIST += tools/re2c/Makefile.inc
EXTRA_DIST += tools/genperf/Makefile.inc
-EXTRA_DIST += tools/python-yasm/Makefile.inc
include tools/re2c/Makefile.inc
include tools/genperf/Makefile.inc
-include tools/python-yasm/Makefile.inc
diff --git a/tools/gap/Makefile.inc b/tools/gap/Makefile.inc
new file mode 100644
index 0000000..4457af7
--- /dev/null
+++ b/tools/gap/Makefile.inc
@@ -0,0 +1,34 @@
+# $Id$
+
+# These utility programs have to be built for BUILD host in cross-build.
+# This makes things rather non-standard automake
+
+noinst_PROGRAMS += gap
+
+gap_SOURCES =
+EXTRA_DIST += tools/gap/gap.c
+EXTRA_DIST += tools/gap/perfect.c
+EXTRA_DIST += tools/gap/perfect.h
+EXTRA_DIST += tools/gap/standard.h
+gap_LDADD = gap.$(OBJEXT)
+gap_LDADD += gap-perfect.$(OBJEXT)
+gap_LDADD += gap-phash.$(OBJEXT)
+gap_LDADD += gap-xmalloc.$(OBJEXT)
+gap_LDADD += gap-xstrdup.$(OBJEXT)
+gap_LINK = $(CCLD_FOR_BUILD) -o $@
+
+gap.$(OBJEXT): tools/gap/gap.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -c -o $@ `test -f tools/gap/gap.c || echo '$(srcdir)/'`tools/gap/gap.c
+
+gap-perfect.$(OBJEXT): tools/gap/perfect.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -c -o $@ `test -f tools/gap/perfect.c || echo '$(srcdir)/'`tools/gap/perfect.c
+
+gap-phash.$(OBJEXT): libyasm/phash.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -c -o $@ `test -f libyasm/phash.c || echo '$(srcdir)/'`libyasm/phash.c
+
+gap-xmalloc.$(OBJEXT): libyasm/xmalloc.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -c -o $@ `test -f libyasm/xmalloc.c || echo '$(srcdir)/'`libyasm/xmalloc.c
+
+gap-xstrdup.$(OBJEXT): libyasm/xstrdup.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -c -o $@ `test -f libyasm/xstrdup.c || echo '$(srcdir)/'`libyasm/xstrdup.c
+
diff --git a/tools/gap/gap.c b/tools/gap/gap.c
new file mode 100644
index 0000000..0f135bf
--- /dev/null
+++ b/tools/gap/gap.c
@@ -0,0 +1,854 @@
+/* $Id$
+ *
+ * Generate Arch Parser (GAP): generates ARCHparse.c from ARCHparse.gap.
+ *
+ * Copyright (C) 2006-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include "tools/gap/perfect.h"
+#include "libyasm/compat-queue.h"
+#include "libyasm/coretype.h"
+#include "libyasm/errwarn.h"
+
+typedef STAILQ_HEAD(slist, sval) slist;
+typedef struct sval {
+ STAILQ_ENTRY(sval) link;
+ char *str;
+} sval;
+
+typedef STAILQ_HEAD(dir_list, dir) dir_list;
+typedef struct dir {
+ STAILQ_ENTRY(dir) link;
+ char *name;
+ const char *func;
+ slist args;
+} dir;
+
+typedef STAILQ_HEAD(dir_byp_list, dir_byp) dir_byp_list;
+typedef struct dir_byp {
+ STAILQ_ENTRY(dir_byp) link;
+ /*@null@*/ char *parser;
+ dir_list dirs;
+} dir_byp;
+
+typedef enum {
+ ARCH = 0,
+ PARSERS,
+ INSN,
+ CPU,
+ CPU_ALIAS,
+ CPU_FEATURE,
+ TARGETMOD,
+ PREFIX,
+ REG,
+ REGGROUP,
+ SEGREG,
+ NUM_DIRS
+} dir_type;
+
+typedef struct {
+ void (*parse_insn) (void); /* arch-specific parse_insn */
+ int multi_parser[NUM_DIRS]; /* whether it has an initial parser field */
+} arch_handler;
+
+static void x86_parse_insn(void);
+static const arch_handler arch_x86 = {
+ x86_parse_insn,
+ {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}
+};
+
+static struct {
+ const char *name;
+ const arch_handler *arch;
+} archs[] = {
+ {"x86", &arch_x86},
+};
+
+static char line[1024];
+static unsigned int cur_line = 0, next_line = 1;
+static int errors = 0;
+static const arch_handler *arch = NULL;
+
+/* Lists of directives, keyed by parser name */
+static dir_byp_list insnprefix_byp;
+static dir_byp_list cpu_byp;
+static dir_byp_list regtmod_byp;
+
+static void
+report_error(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%u: ", cur_line);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ errors++;
+}
+
+void
+yasm__fatal(const char *message, ...)
+{
+ abort();
+}
+
+static void
+dup_slist(slist *out, slist *in)
+{
+ sval *sv;
+
+ STAILQ_INIT(out);
+ STAILQ_FOREACH(sv, in, link) {
+ sval *nsv = yasm_xmalloc(sizeof(sval));
+ nsv->str = yasm__xstrdup(sv->str);
+ STAILQ_INSERT_TAIL(out, nsv, link);
+ }
+}
+
+static dir *
+dup_dir(dir *in)
+{
+ dir *out = yasm_xmalloc(sizeof(dir));
+ out->name = yasm__xstrdup(in->name);
+ out->func = in->func;
+ dup_slist(&out->args, &in->args);
+ return out;
+}
+
+static dir_list *
+get_dirs(dir_byp_list *byp, /*@null@*/ const char *parser)
+{
+ dir_list *found = NULL;
+ dir_byp *db;
+
+ if (STAILQ_EMPTY(byp)) {
+ report_error("PARSERS not yet specified");
+ return NULL;
+ }
+
+ STAILQ_FOREACH(db, byp, link) {
+ if ((!parser && !db->parser) ||
+ (parser && db->parser && strcmp(parser, db->parser) == 0)) {
+ found = &db->dirs;
+ break;
+ }
+ }
+
+ return found;
+}
+
+/* Add a keyword/data to a slist of slist keyed by parser name.
+ * Returns nonzero on error.
+ */
+static int
+add_dir(dir_byp_list *byp, /*@null@*/ const char *parser, dir *d)
+{
+ dir_list *found = get_dirs(byp, parser);
+
+ if (found) {
+ STAILQ_INSERT_TAIL(found, d, link);
+ return 0;
+ } else if (!parser) {
+ /* Add separately to all */
+ dir_byp *db;
+ int first = 1;
+ STAILQ_FOREACH(db, byp, link) {
+ if (!first)
+ d = dup_dir(d);
+ first = 0;
+ STAILQ_INSERT_TAIL(&db->dirs, d, link);
+ }
+ return 0;
+ } else {
+ report_error("parser not found");
+ return 1;
+ }
+}
+
+static char *
+check_parser(dir_type type)
+{
+ char *parser = NULL;
+
+ if (arch->multi_parser[type]) {
+ parser = strtok(NULL, " \t\n");
+ if (strcmp(parser, "-") == 0)
+ parser = NULL;
+ }
+
+ return parser;
+}
+
+static void
+parse_args(slist *args)
+{
+ char *tok;
+ sval *sv;
+
+ STAILQ_INIT(args);
+
+ tok = strtok(NULL, " \t\n");
+ if (!tok) {
+ report_error("no args");
+ return;
+ }
+
+ while (tok) {
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(tok);
+ STAILQ_INSERT_TAIL(args, sv, link);
+ tok = strtok(NULL, " \t\n");
+ }
+}
+
+static dir *
+parse_generic(dir_type type, const char *func, dir_byp_list *byp)
+{
+ char *parser = check_parser(type);
+ char *name = strtok(NULL, " \t\n");
+ dir *d = yasm_xmalloc(sizeof(dir));
+
+ d->name = yasm__xstrdup(name);
+ d->func = func;
+ parse_args(&d->args);
+
+ add_dir(byp, parser, d);
+ return d;
+}
+
+static void
+parse_arch(void)
+{
+ size_t i;
+ int found = 0;
+ char *tok = strtok(NULL, " \t\n");
+
+ if (!tok) {
+ report_error("ARCH requires an operand");
+ return;
+ }
+ for (i=0; i<sizeof(archs)/sizeof(archs[0]); i++) {
+ if (strcmp(archs[i].name, tok) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ report_error("unrecognized ARCH");
+ return;
+ }
+
+ arch = archs[i].arch;
+}
+
+static void
+parse_parsers(void)
+{
+ dir_byp *db;
+ char *tok;
+
+ if (!arch) {
+ report_error("ARCH not specified before PARSERS");
+ return;
+ }
+
+ tok = strtok(NULL, " \t\n");
+ if (!tok) {
+ report_error("no PARSERS parameter");
+ return;
+ }
+
+ while (tok) {
+ /* Insert into each slist of slist if broken out by parser */
+ if (arch->multi_parser[INSN] || arch->multi_parser[PREFIX]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(&insnprefix_byp, db, link);
+ }
+ if (arch->multi_parser[CPU] || arch->multi_parser[CPU_ALIAS] ||
+ arch->multi_parser[CPU_FEATURE]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(&cpu_byp, db, link);
+ }
+ if (arch->multi_parser[TARGETMOD] || arch->multi_parser[REG] ||
+ arch->multi_parser[REGGROUP] || arch->multi_parser[SEGREG]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(®tmod_byp, db, link);
+ }
+ tok = strtok(NULL, " \t\n");
+ }
+
+ /* Add NULL (global) versions if not already created */
+ if (STAILQ_EMPTY(&insnprefix_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(&insnprefix_byp, db, link);
+ }
+ if (STAILQ_EMPTY(&cpu_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(&cpu_byp, db, link);
+ }
+ if (STAILQ_EMPTY(®tmod_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ STAILQ_INIT(&db->dirs);
+
+ STAILQ_INSERT_TAIL(®tmod_byp, db, link);
+ }
+}
+
+static void
+x86_parse_insn(void)
+{
+ char *parser = check_parser(INSN);
+ char *bname = strtok(NULL, " \t\n");
+ char *suffix = strtok(NULL, " \t\n");
+ dir *d;
+ slist args;
+ sval *sv;
+
+ if (!suffix) {
+ report_error("INSN requires suffix");
+ return;
+ }
+
+ /* save the remainder of args */
+ parse_args(&args);
+
+ if (suffix[0] != '"') {
+ /* Just one instruction to generate */
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(suffix);
+ STAILQ_INSERT_HEAD(&args, sv, link);
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(bname);
+ d->func = "INSN";
+ d->args = args;
+ add_dir(&insnprefix_byp, parser, d);
+ } else {
+ /* Need to generate with suffixes for gas */
+ char *p;
+ char sufstr[6];
+ size_t bnamelen = strlen(bname);
+
+ strcpy(sufstr, "SUF_X");
+
+ for (p = &suffix[1]; *p != '"'; p++) {
+ sufstr[4] = toupper(*p);
+
+ d = yasm_xmalloc(sizeof(dir));
+
+ d->name = yasm_xmalloc(bnamelen+2);
+ strcpy(d->name, bname);
+ d->name[bnamelen] = tolower(*p);
+ d->name[bnamelen+1] = '\0';
+
+ d->func = "INSN";
+ dup_slist(&d->args, &args);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(sufstr);
+ STAILQ_INSERT_HEAD(&d->args, sv, link);
+
+ add_dir(&insnprefix_byp, "gas", d);
+ }
+
+ /* And finally the version sans suffix */
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("NONE");
+ STAILQ_INSERT_HEAD(&args, sv, link);
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(bname);
+ d->func = "INSN";
+ d->args = args;
+ add_dir(&insnprefix_byp, parser, d);
+ }
+}
+
+static void
+parse_insn(void)
+{
+ if (!arch) {
+ report_error("ARCH not defined prior to INSN");
+ return;
+ }
+ arch->parse_insn();
+}
+
+static void
+parse_cpu(void)
+{
+ dir *d = parse_generic(CPU, "CPU", &cpu_byp);
+ sval *sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_VERBATIM");
+ STAILQ_INSERT_TAIL(&d->args, sv, link);
+}
+
+static void
+parse_cpu_alias(void)
+{
+ char *parser = check_parser(CPU_ALIAS);
+ char *name = strtok(NULL, " \t\n");
+ char *alias = strtok(NULL, " \t\n");
+ dir_list *dirs = get_dirs(&cpu_byp, parser);
+ dir *aliasd, *d;
+
+ if (!alias) {
+ report_error("CPU_ALIAS requires an operand");
+ return;
+ }
+
+ STAILQ_FOREACH(aliasd, dirs, link) {
+ if (strcmp(aliasd->name, alias) == 0)
+ break;
+ }
+ if (!aliasd) {
+ report_error("could not find `%s'", alias);
+ return;
+ }
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(name);
+ d->func = "CPU";
+ dup_slist(&d->args, &aliasd->args);
+
+ add_dir(&cpu_byp, parser, d);
+}
+
+static void
+parse_cpu_feature(void)
+{
+ char *parser = check_parser(CPU_FEATURE);
+ char *name = strtok(NULL, " \t\n");
+ dir *name_dir = yasm_xmalloc(sizeof(dir));
+ dir *noname_dir = yasm_xmalloc(sizeof(dir));
+ sval *sv;
+
+ name_dir->name = yasm__xstrdup(name);
+ name_dir->func = "CPU_FEATURE";
+ parse_args(&name_dir->args);
+
+ noname_dir->name = yasm_xmalloc(strlen(name)+3);
+ strcpy(noname_dir->name, "no");
+ strcat(noname_dir->name, name);
+ noname_dir->func = name_dir->func;
+ dup_slist(&noname_dir->args, &name_dir->args);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_SET");
+ STAILQ_INSERT_TAIL(&name_dir->args, sv, link);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_CLEAR");
+ STAILQ_INSERT_TAIL(&noname_dir->args, sv, link);
+
+ add_dir(&cpu_byp, parser, name_dir);
+ add_dir(&cpu_byp, parser, noname_dir);
+}
+
+static void
+parse_targetmod(void)
+{
+ parse_generic(TARGETMOD, "TARGETMOD", ®tmod_byp);
+}
+
+static void
+parse_prefix(void)
+{
+ parse_generic(PREFIX, "PREFIX", &insnprefix_byp);
+}
+
+static void
+parse_reg(void)
+{
+ parse_generic(REG, "REG", ®tmod_byp);
+}
+
+static void
+parse_reggroup(void)
+{
+ parse_generic(REGGROUP, "REGGROUP", ®tmod_byp);
+}
+
+static void
+parse_segreg(void)
+{
+ parse_generic(SEGREG, "SEGREG", ®tmod_byp);
+}
+
+/* make the c output for the perfect hash tab array */
+static void
+make_c_tab(
+ FILE *f,
+ const char *which,
+ const char *parser,
+ bstuff *tab, /* table indexed by b */
+ ub4 smax, /* range of scramble[] */
+ ub4 blen, /* b in 0..blen-1, power of 2 */
+ ub4 *scramble) /* used in final hash */
+{
+ ub4 i;
+ /* table for the mapping for the perfect hash */
+ if (blen >= USE_SCRAMBLE) {
+ /* A way to make the 1-byte values in tab bigger */
+ if (smax > UB2MAXVAL+1) {
+ fprintf(f, "static const unsigned long %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=4)
+ fprintf(f, "0x%.8lx, 0x%.8lx, 0x%.8lx, 0x%.8lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3]);
+ } else {
+ fprintf(f, "static const unsigned short %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=8)
+ fprintf(f,
+"0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3],
+ scramble[i+4], scramble[i+5], scramble[i+6], scramble[i+7]);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+
+ if (blen > 0) {
+ /* small adjustments to _a_ to make values distinct */
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "static const unsigned char %s_", which);
+ else
+ fprintf(f, "static const unsigned short %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "tab[] = {\n");
+
+ if (blen < 16) {
+ for (i=0; i<blen; ++i)
+ fprintf(f, "%3ld,", scramble[tab[i].val_b]);
+ } else if (blen <= 1024) {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b],
+ scramble[tab[i+8].val_b], scramble[tab[i+9].val_b],
+ scramble[tab[i+10].val_b], scramble[tab[i+11].val_b],
+ scramble[tab[i+12].val_b], scramble[tab[i+13].val_b],
+ scramble[tab[i+14].val_b], scramble[tab[i+15].val_b]);
+ } else if (blen < USE_SCRAMBLE) {
+ for (i=0; i<blen; i+=8)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b]);
+ } else {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n",
+ tab[i+0].val_b, tab[i+1].val_b,
+ tab[i+2].val_b, tab[i+3].val_b,
+ tab[i+4].val_b, tab[i+5].val_b,
+ tab[i+6].val_b, tab[i+7].val_b,
+ tab[i+8].val_b, tab[i+9].val_b,
+ tab[i+10].val_b, tab[i+11].val_b,
+ tab[i+12].val_b, tab[i+13].val_b,
+ tab[i+14].val_b, tab[i+15].val_b);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+}
+
+static void
+perfect_dir(FILE *out, const char *which, const char *parser, dir_list *dirs)
+{
+ ub4 nkeys;
+ key *keys;
+ hashform form;
+ bstuff *tab; /* table indexed by b */
+ hstuff *tabh; /* table indexed by hash value */
+ ub4 smax; /* scramble[] values in 0..smax-1, a power of 2 */
+ ub4 alen; /* a in 0..alen-1, a power of 2 */
+ ub4 blen; /* b in 0..blen-1, a power of 2 */
+ ub4 salt; /* a parameter to the hash function */
+ gencode final; /* code for final hash */
+ ub4 i;
+ ub4 scramble[SCRAMBLE_LEN]; /* used in final hash function */
+ char buf[10][80]; /* buffer for generated code */
+ char *buf2[10]; /* also for generated code */
+ int cpumode = strcmp(which, "cpu") == 0;
+ dir *d;
+
+ /* perfect hash configuration */
+ form.mode = NORMAL_HM;
+ form.hashtype = STRING_HT;
+ form.perfect = MINIMAL_HP;
+ form.speed = SLOW_HS;
+
+ /* set up code for final hash */
+ final.line = buf2;
+ final.used = 0;
+ final.len = 10;
+ for (i=0; i<10; i++)
+ final.line[i] = buf[i];
+
+ /* build list of keys */
+ nkeys = 0;
+ keys = NULL;
+ STAILQ_FOREACH(d, dirs, link) {
+ key *k = yasm_xmalloc(sizeof(key));
+
+ k->name_k = yasm__xstrdup(d->name);
+ k->len_k = (ub4)strlen(d->name);
+ k->next_k = keys;
+ keys = k;
+ nkeys++;
+ }
+
+ /* find the hash */
+ findhash(&tab, &tabh, &alen, &blen, &salt, &final,
+ scramble, &smax, keys, nkeys, &form);
+
+ /* output the dir table: this should loop up to smax for NORMAL_HP,
+ * or up to pakd.nkeys for MINIMAL_HP.
+ */
+ fprintf(out, "static const %s_parse_data %s_", which, which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "pd[%lu] = {\n", nkeys);
+ for (i=0; i<nkeys; i++) {
+ if (tabh[i].key_h) {
+ sval *sv;
+ STAILQ_FOREACH(d, dirs, link) {
+ if (strcmp(d->name, tabh[i].key_h->name_k) == 0)
+ break;
+ }
+ if (!d) {
+ report_error("internal error: could not find `%s'",
+ tabh[i].key_h->name_k);
+ break;
+ }
+ if (cpumode)
+ fprintf(out, "{\"%s\",", d->name);
+ else
+ fprintf(out, "%s(\"%s\",", d->func, d->name);
+ STAILQ_FOREACH(sv, &d->args, link) {
+ fprintf(out, " %s", sv->str);
+ if (STAILQ_NEXT(sv, link))
+ fprintf(out, ",");
+ }
+ fprintf(out, cpumode ? "}" : ")");
+ } else
+ fprintf(out, " { NULL }");
+
+ if (i < nkeys-1)
+ fprintf(out, ",");
+ fprintf(out, "\n");
+ }
+ fprintf(out, "};\n");
+
+ /* output the hash tab[] array */
+ make_c_tab(out, which, parser, tab, smax, blen, scramble);
+
+ /* The hash function */
+ fprintf(out, "#define tab %s_", which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "tab\n");
+ fprintf(out, "static const %s_parse_data *\n%s_", which, which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "find(const char *key, size_t len)\n");
+ fprintf(out, "{\n");
+ fprintf(out, " const %s_parse_data *ret;\n", which);
+ for (i=0; i<final.used; ++i)
+ fprintf(out, final.line[i]);
+ fprintf(out, " if (rsl >= %lu) return NULL;\n", nkeys);
+ fprintf(out, " ret = &%s_", which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "pd[rsl];\n");
+ fprintf(out, " if (strcmp(key, ret->name) != 0) return NULL;\n");
+ fprintf(out, " return ret;\n");
+ fprintf(out, "}\n");
+ fprintf(out, "#undef tab\n\n");
+
+ free(tab);
+ free(tabh);
+}
+
+/* Get an entire "real" line from the input file by combining any
+ * \\\n continuations.
+ */
+static int get_line(FILE *in)
+{
+ char *p = line;
+ cur_line = next_line;
+
+ if (feof(in))
+ return 0;
+
+ while (p < &line[1023-128]) {
+ if (!fgets(p, 128, in))
+ return 1;
+ next_line++;
+ /* if continuation, strip out leading whitespace */
+ if (p > line) {
+ char *p2 = p;
+ while (isspace(*p2)) p2++;
+ if (p2 > p)
+ memmove(p, p2, strlen(p2)+1);
+ }
+ while (*p) p++;
+ if (p[-2] != '\\' || p[-1] != '\n') {
+ if (p[-1] == '\n')
+ p[-1] = '\0';
+ return 1;
+ }
+ p -= 2;
+ }
+ return 0;
+}
+
+static struct {
+ const char *name;
+ int indx;
+ void (*handler) (void);
+} directives[] = {
+ {"ARCH", ARCH, parse_arch},
+ {"PARSERS", PARSERS, parse_parsers},
+ {"INSN", INSN, parse_insn},
+ {"CPU", CPU, parse_cpu},
+ {"CPU_ALIAS", CPU_ALIAS, parse_cpu_alias},
+ {"CPU_FEATURE", CPU_FEATURE, parse_cpu_feature},
+ {"TARGETMOD", TARGETMOD, parse_targetmod},
+ {"PREFIX", PREFIX, parse_prefix},
+ {"REG", REG, parse_reg},
+ {"REGGROUP", REGGROUP, parse_reggroup},
+ {"SEGREG", SEGREG, parse_segreg},
+};
+
+int
+main(int argc, char *argv[])
+{
+ FILE *in, *out;
+ size_t i;
+ char *tok;
+ int count[NUM_DIRS];
+ dir_byp *db;
+
+ for (i=0; i<NUM_DIRS; i++)
+ count[i] = 0;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: gap <in> <out>\n");
+ return EXIT_FAILURE;
+ }
+
+ in = fopen(argv[1], "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s' for reading\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ STAILQ_INIT(&insnprefix_byp);
+ STAILQ_INIT(&cpu_byp);
+ STAILQ_INIT(®tmod_byp);
+
+ /* Parse input file */
+ while (get_line(in)) {
+ int found;
+ /*printf("%s\n", line);*/
+ tok = strtok(line, " \t\n");
+ if (!tok)
+ continue;
+
+ /* Comments start with # as the first thing on a line */
+ if (tok[0] == '#')
+ continue;
+
+ /* Look for directive */
+ found = 0;
+ for (i=0; i<sizeof(directives)/sizeof(directives[0]); i++) {
+ if (strcmp(tok, directives[i].name) == 0) {
+ count[directives[i].indx]++;
+ directives[i].handler();
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ report_error("unknown directive `%s'\n", tok);
+ }
+
+ /* Output some informational statistics */
+ printf("Directives read:\n");
+ for (i=0; i<sizeof(directives)/sizeof(directives[0]); i++)
+ printf("\t%d\t%s\n", count[directives[i].indx], directives[i].name);
+
+ if (errors > 0)
+ return EXIT_FAILURE;
+
+ out = fopen(argv[2], "wt");
+ if (!out) {
+ fprintf(stderr, "Could not open `%s' for writing\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ /* Get perfect hashes for the three lists of directives */
+ STAILQ_FOREACH(db, &insnprefix_byp, link)
+ perfect_dir(out, "insnprefix", db->parser, &db->dirs);
+ STAILQ_FOREACH(db, &cpu_byp, link)
+ perfect_dir(out, "cpu", db->parser, &db->dirs);
+ STAILQ_FOREACH(db, ®tmod_byp, link)
+ perfect_dir(out, "regtmod", db->parser, &db->dirs);
+
+ if (errors > 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/gap/perfect.c b/tools/gap/perfect.c
new file mode 100644
index 0000000..d121804
--- /dev/null
+++ b/tools/gap/perfect.c
@@ -0,0 +1,1189 @@
+/* Modified for use with yasm by Peter Johnson.
+ * $Id$
+ */
+/*
+------------------------------------------------------------------------------
+perfect.c: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996, December 1999
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.c
+
+This generates a minimal perfect hash function. That means, given a
+set of n keys, this determines a hash function that maps each of
+those keys into a value in 0..n-1 with no collisions.
+
+The perfect hash function first uses a normal hash function on the key
+to determine (a,b) such that the pair (a,b) is distinct for all
+keys, then it computes a^scramble[tab[b]] to get the final perfect hash.
+tab[] is an array of 1-byte values and scramble[] is a 256-term array of
+2-byte or 4-byte values. If there are n keys, the length of tab[] is a
+power of two between n/3 and n.
+
+I found the idea of computing distinct (a,b) values in "Practical minimal
+perfect hash functions for large databases", Fox, Heath, Chen, and Daoud,
+Communications of the ACM, January 1992. They found the idea in Chichelli
+(CACM Jan 1980). Beyond that, our methods differ.
+
+The key is hashed to a pair (a,b) where a in 0..*alen*-1 and b in
+0..*blen*-1. A fast hash function determines both a and b
+simultaneously. Any decent hash function is likely to produce
+hashes so that (a,b) is distinct for all pairs. I try the hash
+using different values of *salt* until all pairs are distinct.
+
+The final hash is (a XOR scramble[tab[b]]). *scramble* is a
+predetermined mapping of 0..255 into 0..smax-1. *tab* is an
+array that we fill in in such a way as to make the hash perfect.
+
+First we fill in all values of *tab* that are used by more than one
+key. We try all possible values for each position until one works.
+
+This leaves m unmapped keys and m values that something could hash to.
+If you treat unmapped keys as lefthand nodes and unused hash values
+as righthand nodes, and draw a line connecting each key to each hash
+value it could map to, you get a bipartite graph. We attempt to
+find a perfect matching in this graph. If we succeed, we have
+determined a perfect hash for the whole set of keys.
+
+*scramble* is used because (a^tab[i]) clusters keys around *a*.
+------------------------------------------------------------------------------
+*/
+
+#include <string.h>
+#include "tools/gap/standard.h"
+#include "libyasm/coretype.h"
+#include "libyasm/phash.h"
+#include "tools/gap/perfect.h"
+
+#define CHECKSTATE 8
+
+/*
+------------------------------------------------------------------------------
+Find the mapping that will produce a perfect hash
+------------------------------------------------------------------------------
+*/
+
+/* return the ceiling of the log (base 2) of val */
+ub4 phash_log2(val)
+ub4 val;
+{
+ ub4 i;
+ for (i=0; ((ub4)1<<i) < val; ++i)
+ ;
+ return i;
+}
+
+/* compute p(x), where p is a permutation of 0..(1<<nbits)-1 */
+/* permute(0)=0. This is intended and useful. */
+static ub4 permute(
+ ub4 x, /* input, a value in some range */
+ ub4 nbits) /* input, number of bits in range */
+{
+ int i;
+ int mask = ((ub4)1<<nbits)-1; /* all ones */
+ int const2 = 1+nbits/2;
+ int const3 = 1+nbits/3;
+ int const4 = 1+nbits/4;
+ int const5 = 1+nbits/5;
+ for (i=0; i<20; ++i)
+ {
+ x = (x+(x<<const2)) & mask;
+ x = (x^(x>>const3));
+ x = (x+(x<<const4)) & mask;
+ x = (x^(x>>const5));
+ }
+ return x;
+}
+
+/* initialize scramble[] with distinct random values in 0..smax-1 */
+static void scrambleinit(
+ ub4 *scramble, /* hash is a^scramble[tab[b]] */
+ ub4 smax) /* scramble values should be in 0..smax-1 */
+{
+ ub4 i;
+
+ /* fill scramble[] with distinct random integers in 0..smax-1 */
+ for (i=0; i<SCRAMBLE_LEN; ++i)
+ {
+ scramble[i] = permute(i, phash_log2(smax));
+ }
+}
+
+/*
+ * Check if key1 and key2 are the same.
+ * We already checked (a,b) are the same.
+ */
+static void checkdup(
+ key *key1,
+ key *key2,
+ hashform *form)
+{
+ switch(form->hashtype)
+ {
+ case STRING_HT:
+ if ((key1->len_k == key2->len_k) &&
+ !memcmp(key1->name_k, key2->name_k, (size_t)key1->len_k))
+ {
+ fprintf(stderr, "perfect.c: Duplicates keys! %.*s\n",
+ (int)key1->len_k, key1->name_k);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case INT_HT:
+ if (key1->hash_k == key2->hash_k)
+ {
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx\n", key1->hash_k);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case AB_HT:
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx %.8lx\n",
+ key1->a_k, key1->b_k);
+ exit(EXIT_FAILURE);
+ break;
+ default:
+ fprintf(stderr, "perfect.c: Illegal hash type %ld\n", (ub4)form->hashtype);
+ exit(EXIT_FAILURE);
+ break;
+ }
+}
+
+
+/*
+ * put keys in tabb according to key->b_k
+ * check if the initial hash might work
+ */
+static int inittab(
+ bstuff *tabb, /* output, list of keys with b for (a,b) */
+ ub4 blen, /* length of tabb */
+ key *keys, /* list of keys already hashed */
+ hashform *form, /* user directives */
+ int complete) /* TRUE means to complete init despite collisions */
+{
+ int nocollision = TRUE;
+ key *mykey;
+
+ memset((void *)tabb, 0, (size_t)(sizeof(bstuff)*blen));
+
+ /* Two keys with the same (a,b) guarantees a collision */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ key *otherkey;
+
+ for (otherkey=tabb[mykey->b_k].list_b;
+ otherkey;
+ otherkey=otherkey->nextb_k)
+ {
+ if (mykey->a_k == otherkey->a_k)
+ {
+ nocollision = FALSE;
+ checkdup(mykey, otherkey, form);
+ if (!complete)
+ return FALSE;
+ }
+ }
+ ++tabb[mykey->b_k].listlen_b;
+ mykey->nextb_k = tabb[mykey->b_k].list_b;
+ tabb[mykey->b_k].list_b = mykey;
+ }
+
+ /* no two keys have the same (a,b) pair */
+ return nocollision;
+}
+
+
+/* Do the initial hash for normal mode (use lookup and checksum) */
+static void initnorm(
+ key *keys, /* list of all keys */
+ ub4 alen, /* (a,b) has a in 0..alen-1, a power of 2 */
+ ub4 blen, /* (a,b) has b in 0..blen-1, a power of 2 */
+ ub4 smax, /* maximum range of computable hash values */
+ ub4 salt, /* used to initialize the hash function */
+ gencode *final) /* output, code for the final hash */
+{
+ key *mykey;
+ if (phash_log2(alen)+phash_log2(blen) > UB4BITS)
+ {
+ ub4 initlev = (salt*0x9e3779b9)&0xffffffff; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 i, state[CHECKSTATE];
+ for (i=0; i<CHECKSTATE; ++i) state[i] = initlev;
+ phash_checksum( mykey->name_k, mykey->len_k, state);
+ mykey->a_k = state[0]&(alen-1);
+ mykey->b_k = state[1]&(blen-1);
+ }
+ final->used = 4;
+ sprintf(final->line[0],
+ " unsigned long i,state[CHECKSTATE],rsl;\n");
+ sprintf(final->line[1],
+ " for (i=0; i<CHECKSTATE; ++i) state[i]=0x%lx;\n",initlev);
+ sprintf(final->line[2],
+ " phash_checksum(key, len, state);\n");
+ sprintf(final->line[3],
+ " rsl = ((state[0]&0x%lx)^scramble[tab[state[1]&0x%lx]]);\n",
+ alen-1, blen-1);
+ }
+ else
+ {
+ ub4 loga = phash_log2(alen); /* log based 2 of blen */
+ ub4 initlev = (salt*0x9e3779b9)&0xffffffff; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 hash = phash_lookup(mykey->name_k, mykey->len_k, initlev);
+ mykey->a_k = (loga > 0) ? hash>>(UB4BITS-loga) : 0;
+ mykey->b_k = (blen > 1) ? hash&(blen-1) : 0;
+ }
+ final->used = 2;
+ sprintf(final->line[0],
+ " unsigned long rsl, val = phash_lookup(key, len, 0x%lxUL);\n", initlev);
+ if (smax <= 1)
+ {
+ sprintf(final->line[1], " rsl = 0;\n");
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^tab[val&0x%lx]);\n",
+ UB4BITS-phash_log2(alen), blen-1);
+ }
+ else
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^scramble[tab[val&0x%lx]]);\n",
+ UB4BITS-phash_log2(alen), blen-1);
+ }
+ }
+}
+
+
+
+/* Do initial hash for inline mode */
+static void initinl(
+ key *keys, /* list of all keys */
+ ub4 alen, /* (a,b) has a in 0..alen-1, a power of 2 */
+ ub4 blen, /* (a,b) has b in 0..blen-1, a power of 2 */
+ ub4 smax, /* range of computable hash values */
+ ub4 salt, /* used to initialize the hash function */
+ gencode *final) /* generated code for final hash */
+{
+ key *mykey;
+ ub4 amask = alen-1;
+ ub4 blog = phash_log2(blen);
+ ub4 initval = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ /* It's more important to have b uniform than a, so b is the low bits */
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ ub4 hash = initval;
+ ub4 i;
+ for (i=0; i<mykey->len_k; ++i)
+ {
+ hash = ((ub1)mykey->name_k[i] ^ hash) + ((hash<<(UB4BITS-6))+(hash>>6));
+ }
+ mykey->hash_k = hash;
+ mykey->a_k = (alen > 1) ? (hash & amask) : 0;
+ mykey->b_k = (blen > 1) ? (hash >> (UB4BITS-blog)) : 0;
+ }
+ final->used = 1;
+ if (smax <= 1)
+ {
+ sprintf(final->line[0], " unsigned long rsl = 0;\n");
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " unsigned long rsl = ((val & 0x%lx) ^ tab[val >> %ld]);\n",
+ amask, UB4BITS-blog);
+ }
+ else
+ {
+ sprintf(final->line[0], " unsigned long rsl = ((val & 0x%lx) ^ scramble[tab[val >> %ld]]);\n",
+ amask, UB4BITS-blog);
+ }
+}
+
+
+/*
+ * Run a hash function on the key to get a and b
+ * Returns:
+ * 0: didn't find distinct (a,b) for all keys
+ * 1: found distinct (a,b) for all keys, put keys in tabb[]
+ * 2: found a perfect hash, no need to do any more work
+ */
+static ub4 initkey(
+ key *keys, /* list of all keys */
+ ub4 nkeys, /* total number of keys */
+ bstuff *tabb, /* stuff indexed by b */
+ ub4 alen, /* (a,b) has a in 0..alen-1, a power of 2 */
+ ub4 blen, /* (a,b) has b in 0..blen-1, a power of 2 */
+ ub4 smax, /* range of computable hash values */
+ ub4 salt, /* used to initialize the hash function */
+ hashform *form, /* user directives */
+ gencode *final) /* code for final hash */
+{
+ /* Do the initial hash of the keys */
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ initnorm(keys, alen, blen, smax, salt, final);
+ break;
+ case INLINE_HM:
+ initinl(keys, alen, blen, smax, salt, final);
+ break;
+#if 0
+ case HEX_HM:
+ case DECIMAL_HM:
+ finished = inithex(keys, nkeys, alen, blen, smax, salt, final, form);
+ if (finished) return 2;
+ break;
+#endif
+ default:
+ fprintf(stderr, "fatal error: illegal mode\n");
+ exit(1);
+ }
+
+ if (nkeys <= 1)
+ {
+ final->used = 1;
+ sprintf(final->line[0], " unsigned long rsl = 0;\n");
+ return 2;
+ }
+
+ return inittab(tabb, blen, keys, form, FALSE);
+}
+
+/* Print an error message and exit if there are duplicates */
+static void duplicates(
+ bstuff *tabb, /* array of lists of keys with the same b */
+ ub4 blen, /* length of tabb, a power of 2 */
+ key *keys,
+ hashform *form) /* user directives */
+{
+ ub4 i;
+ key *key1;
+ key *key2;
+
+ (void)inittab(tabb, blen, keys, form, TRUE);
+
+ /* for each b, do nested loops through key list looking for duplicates */
+ for (i=0; i<blen; ++i)
+ for (key1=tabb[i].list_b; key1; key1=key1->nextb_k)
+ for (key2=key1->nextb_k; key2; key2=key2->nextb_k)
+ checkdup(key1, key2, form);
+}
+
+
+/* Try to apply an augmenting list */
+static int apply(
+ bstuff *tabb,
+ hstuff *tabh,
+ qstuff *tabq,
+ ub4 blen,
+ ub4 *scramble,
+ ub4 tail,
+ int rollback) /* FALSE applies augmenting path, TRUE rolls back */
+{
+ ub4 hash;
+ key *mykey;
+ bstuff *pb;
+ ub4 child;
+ ub4 parent;
+ ub4 stabb; /* scramble[tab[b]] */
+
+ /* walk from child to parent */
+ for (child=tail-1; child; child=parent)
+ {
+ parent = tabq[child].parent_q; /* find child's parent */
+ pb = tabq[parent].b_q; /* find parent's list of siblings */
+
+ /* erase old hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (mykey == tabh[hash].key_h)
+ { /* erase hash for all of child's siblings */
+ tabh[hash].key_h = (key *)0;
+ }
+ }
+
+ /* change pb->val_b, which will change the hashes of all parent siblings */
+ pb->val_b = (rollback ? tabq[child].oldval_q : tabq[child].newval_q);
+
+ /* set new hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (rollback)
+ {
+ if (parent == 0) continue; /* root never had a hash */
+ }
+ else if (tabh[hash].key_h)
+ {
+ /* very rare: roll back any changes */
+ apply(tabb, tabh, tabq, blen, scramble, tail, TRUE);
+ return FALSE; /* failure, collision */
+ }
+ tabh[hash].key_h = mykey;
+ }
+ }
+ return TRUE;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+augment(): Add item to the mapping.
+
+Construct a spanning tree of *b*s with *item* as root, where each
+parent can have all its hashes changed (by some new val_b) with
+at most one collision, and each child is the b of that collision.
+
+I got this from Tarjan's "Data Structures and Network Algorithms". The
+path from *item* to a *b* that can be remapped with no collision is
+an "augmenting path". Change values of tab[b] along the path so that
+the unmapped key gets mapped and the unused hash value gets used.
+
+Assuming 1 key per b, if m out of n hash values are still unused,
+you should expect the transitive closure to cover n/m nodes before
+an unused node is found. Sum(i=1..n)(n/i) is about nlogn, so expect
+this approach to take about nlogn time to map all single-key b's.
+-------------------------------------------------------------------------------
+*/
+static int augment(
+ bstuff *tabb, /* stuff indexed by b */
+ hstuff *tabh, /* which key is associated with which hash, indexed by hash */
+ qstuff *tabq, /* queue of *b* values, this is the spanning tree */
+ ub4 blen, /* length of tabb */
+ ub4 *scramble, /* final hash is a^scramble[tab[b]] */
+ ub4 smax, /* highest value in scramble */
+ bstuff *item, /* &tabb[b] for the b to be mapped */
+ ub4 nkeys, /* final hash must be in 0..nkeys-1 */
+ ub4 highwater, /* a value higher than any now in tabb[].water_b */
+ hashform *form) /* TRUE if we should do a minimal perfect hash */
+{
+ ub4 q; /* current position walking through the queue */
+ ub4 tail; /* tail of the queue. 0 is the head of the queue. */
+ ub4 limit=((blen < USE_SCRAMBLE) ? smax : UB1MAXVAL+1);
+ ub4 highhash = ((form->perfect == MINIMAL_HP) ? nkeys : smax);
+ int trans = (form->speed == SLOW_HS || form->perfect == MINIMAL_HP);
+
+ /* initialize the root of the spanning tree */
+ tabq[0].b_q = item;
+ tail = 1;
+
+ /* construct the spanning tree by walking the queue, add children to tail */
+ for (q=0; q<tail; ++q)
+ {
+ bstuff *myb = tabq[q].b_q; /* the b for this node */
+ ub4 i; /* possible value for myb->val_b */
+
+ if (!trans && (q == 1))
+ break; /* don't do transitive closure */
+
+ for (i=0; i<limit; ++i)
+ {
+ bstuff *childb = (bstuff *)0; /* the b that this i maps to */
+ key *mykey; /* for walking through myb's keys */
+
+ for (mykey = myb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ key *childkey;
+ ub4 hash = mykey->a_k^scramble[i];
+
+ if (hash >= highhash) break; /* out of bounds */
+ childkey = tabh[hash].key_h;
+
+ if (childkey)
+ {
+ bstuff *hitb = &tabb[childkey->b_k];
+
+ if (childb)
+ {
+ if (childb != hitb) break; /* hit at most one child b */
+ }
+ else
+ {
+ childb = hitb; /* remember this as childb */
+ if (childb->water_b == highwater) break; /* already explored */
+ }
+ }
+ }
+ if (mykey) continue; /* myb with i has multiple collisions */
+
+ /* add childb to the queue of reachable things */
+ if (childb) childb->water_b = highwater;
+ tabq[tail].b_q = childb;
+ tabq[tail].newval_q = (ub2)i; /* how to make parent (myb) use this hash */
+ tabq[tail].oldval_q = myb->val_b; /* need this for rollback */
+ tabq[tail].parent_q = q;
+ ++tail;
+
+ if (!childb)
+ { /* found an *i* with no collisions? */
+ /* try to apply the augmenting path */
+ if (apply(tabb, tabh, tabq, blen, scramble, tail, FALSE))
+ return TRUE; /* success, item was added to the perfect hash */
+
+ --tail; /* don't know how to handle such a child! */
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/* find a mapping that makes this a perfect hash */
+static int perfect(
+ bstuff *tabb,
+ hstuff *tabh,
+ qstuff *tabq,
+ ub4 blen,
+ ub4 smax,
+ ub4 *scramble,
+ ub4 nkeys,
+ hashform *form)
+{
+ ub4 maxkeys; /* maximum number of keys for any b */
+ ub4 i, j;
+
+ /* clear any state from previous attempts */
+ memset((void *)tabh, 0,
+ (size_t)(sizeof(hstuff)*
+ ((form->perfect == MINIMAL_HP) ? nkeys : smax)));
+ memset((void *)tabq, 0, (size_t)(sizeof(qstuff)*(blen+1)));
+
+ for (maxkeys=0,i=0; i<blen; ++i)
+ if (tabb[i].listlen_b > maxkeys)
+ maxkeys = tabb[i].listlen_b;
+
+ /* In descending order by number of keys, map all *b*s */
+ for (j=maxkeys; j>0; --j)
+ for (i=0; i<blen; ++i)
+ if (tabb[i].listlen_b == j)
+ if (!augment(tabb, tabh, tabq, blen, scramble, smax, &tabb[i], nkeys,
+ i+1, form))
+ {
+ printf("fail to map group of size %ld for tab size %ld\n", j, blen);
+ return FALSE;
+ }
+
+ /* Success! We found a perfect hash of all keys into 0..nkeys-1. */
+ return TRUE;
+}
+
+
+/*
+ * Simple case: user gave (a,b). No more mixing, no guessing alen or blen.
+ * This assumes a,b reside in (key->a_k, key->b_k), and final->form == AB_HK.
+ */
+static void hash_ab(
+ bstuff **tabb, /* output, tab[] of the perfect hash, length *blen */
+ ub4 *alen, /* output, 0..alen-1 is range for a of (a,b) */
+ ub4 *blen, /* output, 0..blen-1 is range for b of (a,b) */
+ ub4 *salt, /* output, initializes initial hash */
+ gencode *final, /* code for final hash */
+ ub4 *scramble, /* input, hash = a^scramble[tab[b]] */
+ ub4 *smax, /* input, scramble[i] in 0..smax-1 */
+ key *keys, /* input, keys to hash */
+ ub4 nkeys, /* input, number of keys being hashed */
+ hashform *form) /* user directives */
+{
+ hstuff *tabh;
+ qstuff *tabq;
+ key *mykey;
+ ub4 i;
+ int used_tab;
+
+ /* initially make smax the first power of two bigger than nkeys */
+ *smax = ((ub4)1<<phash_log2(nkeys));
+ scrambleinit(scramble, *smax);
+
+ /* set *alen and *blen based on max A and B from user */
+ *alen = 1;
+ *blen = 1;
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ while (*alen <= mykey->a_k) *alen *= 2;
+ while (*blen <= mykey->b_k) *blen *= 2;
+ }
+ if (*alen > 2**smax)
+ {
+ fprintf(stderr,
+ "perfect.c: Can't deal with (A,B) having A bigger than twice \n");
+ fprintf(stderr,
+ " the smallest power of two greater or equal to any legal hash.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* allocate working memory */
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc(sizeof(qstuff)*(*blen+1));
+ tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+
+ /* check that (a,b) are distinct and put them in tabb indexed by b */
+ (void)inittab(*tabb, *blen, keys, form, FALSE);
+
+ /* try with smax */
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if (form->perfect == MINIMAL_HP)
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(EXIT_FAILURE);
+ }
+ else
+ {
+ /* try with 2*smax */
+ free((void *)tabh);
+ *smax = *smax * 2;
+ scrambleinit(scramble, *smax);
+ tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ /* check if tab[] was really needed */
+ for (i=0; i<*blen; ++i)
+ {
+ if ((*tabb)[i].val_b != 0) break; /* assumes permute(0) == 0 */
+ }
+ used_tab = (i < *blen);
+
+ /* write the code for the perfect hash */
+ *salt = 1;
+ final->used = 1;
+ if (!used_tab)
+ {
+ sprintf(final->line[0], " unsigned long rsl = a;\n");
+ }
+ else if (*blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " unsigned long rsl = (a ^ tab[b]);\n");
+ }
+ else
+ {
+ sprintf(final->line[0], " unsigned long rsl = (a ^ scramble[tab[b]]);\n");
+ }
+
+ printf("success, found a perfect hash\n");
+
+ free((void *)tabq);
+ free((void *)tabh);
+}
+
+
+/* guess initial values for alen and blen */
+static void initalen(
+ ub4 *alen, /* output, initial alen */
+ ub4 *blen, /* output, initial blen */
+ ub4 *smax,/* input, power of two greater or equal to max hash value */
+ ub4 nkeys, /* number of keys being hashed */
+ hashform *form) /* user directives */
+{
+ /*
+ * Find initial *alen, *blen
+ * Initial alen and blen values were found empirically. Some factors:
+ *
+ * If smax<256 there is no scramble, so tab[b] needs to cover 0..smax-1.
+ *
+ * alen and blen must be powers of 2 because the values in 0..alen-1 and
+ * 0..blen-1 are produced by applying a bitmask to the initial hash function.
+ *
+ * alen must be less than smax, in fact less than nkeys, because otherwise
+ * there would often be no i such that a^scramble[i] is in 0..nkeys-1 for
+ * all the *a*s associated with a given *b*, so there would be no legal
+ * value to assign to tab[b]. This only matters when we're doing a minimal
+ * perfect hash.
+ *
+ * It takes around 800 trials to find distinct (a,b) with nkey=smax*(5/8)
+ * and alen*blen = smax*smax/32.
+ *
+ * Values of blen less than smax/4 never work, and smax/2 always works.
+ *
+ * We want blen as small as possible because it is the number of bytes in
+ * the huge array we must create for the perfect hash.
+ *
+ * When nkey <= smax*(5/8), blen=smax/4 works much more often with
+ * alen=smax/8 than with alen=smax/4. Above smax*(5/8), blen=smax/4
+ * doesn't seem to care whether alen=smax/8 or alen=smax/4. I think it
+ * has something to do with 5/8 = 1/8 * 5. For example examine 80000,
+ * 85000, and 90000 keys with different values of alen. This only matters
+ * if we're doing a minimal perfect hash.
+ *
+ * When alen*blen <= 1<<UB4BITS, the initial hash must produce one integer.
+ * Bigger than that it must produce two integers, which increases the
+ * cost of the hash per character hashed.
+ */
+ if (form->perfect == NORMAL_HP)
+ {
+ if ((form->speed == FAST_HS) && (nkeys > *smax*0.8))
+ {
+ *smax = *smax * 2;
+ }
+
+ *alen = ((form->hashtype==INT_HT) && *smax>131072) ?
+ ((ub4)1<<(UB4BITS-phash_log2(*blen))) : /* distinct keys => distinct (A,B) */
+ *smax; /* no reason to restrict alen to smax/2 */
+ if ((form->hashtype == INT_HT) && *smax < 32)
+ *blen = *smax; /* go for function speed not space */
+ else if (*smax/4 <= (1<<14))
+ *blen = ((nkeys <= *smax*0.56) ? *smax/32 :
+ (nkeys <= *smax*0.74) ? *smax/16 : *smax/8);
+ else
+ *blen = ((nkeys <= *smax*0.6) ? *smax/16 :
+ (nkeys <= *smax*0.8) ? *smax/8 : *smax/4);
+
+ if ((form->speed == FAST_HS) && (*blen < *smax/8))
+ *blen = *smax/8;
+
+ if (*alen < 1) *alen = 1;
+ if (*blen < 1) *blen = 1;
+ }
+ else
+ {
+ switch(phash_log2(*smax))
+ {
+ case 0:
+ *alen = 1;
+ *blen = 1;
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ *alen = (form->perfect == NORMAL_HP) ? *smax : *smax/2;
+ *blen = *smax/2;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/4;
+ }
+ else if (*smax/4 < USE_SCRAMBLE)
+ {
+ *alen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ *blen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ }
+ else
+ {
+ *alen = ((nkeys <= *smax*(5.0/8.0)) ? *smax/8 :
+ (nkeys <= *smax*(3.0/4.0)) ? *smax/4 : *smax/2);
+ *blen = *smax/4; /* always give the small size a shot */
+ }
+ break;
+ case 18:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/2;
+ }
+ else
+ {
+ *alen = *smax/8; /* never require the multiword hash */
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ }
+ break;
+ case 19:
+ case 20:
+ *alen = (nkeys <= *smax*(5.0/8.0)) ? *smax/8 : *smax/2;
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ break;
+ default:
+ *alen = *smax/2; /* just find a hash as quick as possible */
+ *blen = *smax/2; /* we'll be thrashing virtual memory at this size */
+ break;
+ }
+ }
+}
+
+/*
+** Try to find a perfect hash function.
+** Return the successful initializer for the initial hash.
+** Return 0 if no perfect hash could be found.
+*/
+void findhash(
+ bstuff **tabb, /* output, tab[] of the perfect hash, length *blen */
+ hstuff **tabh, /* output, table of keys indexed by hash value */
+ ub4 *alen, /* output, 0..alen-1 is range for a of (a,b) */
+ ub4 *blen, /* output, 0..blen-1 is range for b of (a,b) */
+ ub4 *salt, /* output, initializes initial hash */
+ gencode *final, /* code for final hash */
+ ub4 *scramble, /* input, hash = a^scramble[tab[b]] */
+ ub4 *smax, /* input, scramble[i] in 0..smax-1 */
+ key *keys, /* input, keys to hash */
+ ub4 nkeys, /* input, number of keys being hashed */
+ hashform *form) /* user directives */
+{
+ ub4 bad_initkey; /* how many times did initkey fail? */
+ ub4 bad_perfect; /* how many times did perfect fail? */
+ ub4 trysalt; /* trial initializer for initial hash */
+ ub4 maxalen;
+ qstuff *tabq; /* table of stuff indexed by queue value, used by augment */
+
+ /* The case of (A,B) supplied by the user is a special case */
+ if (form->hashtype == AB_HT)
+ {
+ hash_ab(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form);
+ return;
+ }
+
+ /* guess initial values for smax, alen and blen */
+ *smax = ((ub4)1<<phash_log2(nkeys));
+ initalen(alen, blen, smax, nkeys, form);
+
+ scrambleinit(scramble, *smax);
+
+ maxalen = (form->perfect == MINIMAL_HP) ? *smax/2 : *smax;
+
+ /* allocate working memory */
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc(sizeof(qstuff)*(*blen+1));
+ *tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+
+ /* Actually find the perfect hash */
+ *salt = 0;
+ bad_initkey = 0;
+ bad_perfect = 0;
+ for (trysalt=1; ; ++trysalt)
+ {
+ ub4 rslinit;
+ /* Try to find distinct (A,B) for all keys */
+
+ rslinit = initkey(keys, nkeys, *tabb, *alen, *blen, *smax, trysalt,
+ form, final);
+
+ if (rslinit == 2)
+ { /* initkey actually found a perfect hash, not just distinct (a,b) */
+ *salt = 1;
+ *blen = 0;
+ break;
+ }
+ else if (rslinit == 0)
+ {
+ /* didn't find distinct (a,b) */
+ if (++bad_initkey >= RETRY_INITKEY)
+ {
+ /* Try to put more bits in (A,B) to make distinct (A,B) more likely */
+ if (*alen < maxalen)
+ {
+ *alen *= 2;
+ }
+ else if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(tabq);
+ free(*tabb);
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ }
+ else
+ {
+ duplicates(*tabb, *blen, keys, form); /* check for duplicates */
+ printf("fatal error: Cannot perfect hash: cannot find distinct (A,B)\n");
+ exit(EXIT_FAILURE);
+ }
+ bad_initkey = 0;
+ bad_perfect = 0;
+ }
+ continue; /* two keys have same (a,b) pair */
+ }
+
+ printf("found distinct (A,B) on attempt %ld\n", trysalt);
+
+ /* Given distinct (A,B) for all keys, build a perfect hash */
+ if (!perfect(*tabb, *tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if ((form->hashtype != INT_HT && ++bad_perfect >= RETRY_PERFECT) ||
+ (form->hashtype == INT_HT && ++bad_perfect >= RETRY_HEX))
+ {
+ if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(*tabb);
+ free(tabq);
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ --trysalt; /* we know this salt got distinct (A,B) */
+ }
+ else
+ {
+ printf("fatal error: Cannot perfect hash: cannot build tab[]\n");
+ exit(EXIT_FAILURE);
+ }
+ bad_perfect = 0;
+ }
+ continue;
+ }
+
+ *salt = trysalt;
+ break;
+ }
+
+ printf("built perfect hash table of size %ld\n", *blen);
+
+ /* free working memory */
+ free((void *)tabq);
+}
+
+#if 0
+/*
+------------------------------------------------------------------------------
+Input/output type routines
+------------------------------------------------------------------------------
+*/
+
+/* get the list of keys */
+static void getkeys(keys, nkeys, textroot, keyroot, form)
+key **keys; /* list of all keys */
+ub4 *nkeys; /* number of keys */
+reroot *textroot; /* get space to store key text */
+reroot *keyroot; /* get space for keys */
+hashform *form; /* user directives */
+{
+ key *mykey;
+ char *mytext;
+ mytext = (char *)renew(textroot);
+ *keys = 0;
+ *nkeys = 0;
+ while (fgets(mytext, MAXKEYLEN, stdin))
+ {
+ mykey = (key *)renew(keyroot);
+ if (form->mode == AB_HM)
+ {
+ sscanf(mytext, "%lx %lx ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == ABDEC_HM)
+ {
+ sscanf(mytext, "%ld %ld ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == HEX_HM)
+ {
+ sscanf(mytext, "%lx ", &mykey->hash_k);
+ }
+ else if (form->mode == DECIMAL_HM)
+ {
+ sscanf(mytext, "%ld ", &mykey->hash_k);
+ }
+ else
+ {
+ mykey->name_k = (ub1 *)mytext;
+ mytext = (char *)renew(textroot);
+ mykey->len_k = (ub4)(strlen((char *)mykey->name_k)-1);
+ }
+ mykey->next_k = *keys;
+ *keys = mykey;
+ ++*nkeys;
+ }
+ redel(textroot, mytext);
+}
+
+/* make the .c file */
+static void make_c(tab, smax, blen, scramble, final, form)
+bstuff *tab; /* table indexed by b */
+ub4 smax; /* range of scramble[] */
+ub4 blen; /* b in 0..blen-1, power of 2 */
+ub4 *scramble; /* used in final hash */
+gencode *final; /* code for the final hash */
+hashform *form; /* user directives */
+{
+ ub4 i;
+ FILE *f;
+ f = fopen("phash.c", "w");
+ fprintf(f, "/* table for the mapping for the perfect hash */\n");
+ fprintf(f, "#include \"lookupa.h\"\n");
+ fprintf(f, "\n");
+ if (blen >= USE_SCRAMBLE)
+ {
+ fprintf(f, "/* A way to make the 1-byte values in tab bigger */\n");
+ if (smax > UB2MAXVAL+1)
+ {
+ fprintf(f, "unsigned long scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=4)
+ fprintf(f, "0x%.8lx, 0x%.8lx, 0x%.8lx, 0x%.8lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3]);
+ }
+ else
+ {
+ fprintf(f, "unsigned short scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=8)
+ fprintf(f,
+"0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3],
+ scramble[i+4], scramble[i+5], scramble[i+6], scramble[i+7]);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ if (blen > 0)
+ {
+ fprintf(f, "/* small adjustments to _a_ to make values distinct */\n");
+
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "unsigned char tab[] = {\n");
+ else
+ fprintf(f, "unsigned short tab[] = {\n");
+
+ if (blen < 16)
+ {
+ for (i=0; i<blen; ++i) fprintf(f, "%3d,", scramble[tab[i].val_b]);
+ }
+ else if (blen <= 1024)
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b],
+ scramble[tab[i+8].val_b], scramble[tab[i+9].val_b],
+ scramble[tab[i+10].val_b], scramble[tab[i+11].val_b],
+ scramble[tab[i+12].val_b], scramble[tab[i+13].val_b],
+ scramble[tab[i+14].val_b], scramble[tab[i+15].val_b]);
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ for (i=0; i<blen; i+=8)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b]);
+ }
+ else
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ tab[i+0].val_b, tab[i+1].val_b,
+ tab[i+2].val_b, tab[i+3].val_b,
+ tab[i+4].val_b, tab[i+5].val_b,
+ tab[i+6].val_b, tab[i+7].val_b,
+ tab[i+8].val_b, tab[i+9].val_b,
+ tab[i+10].val_b, tab[i+11].val_b,
+ tab[i+12].val_b, tab[i+13].val_b,
+ tab[i+14].val_b, tab[i+15].val_b);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ fprintf(f, "/* The hash function */\n");
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ fprintf(f, "ub4 phash(key, len)\n");
+ fprintf(f, "char *key;\n");
+ fprintf(f, "int len;\n");
+ break;
+ case INLINE_HM:
+ case HEX_HM:
+ case DECIMAL_HM:
+ fprintf(f, "ub4 phash(val)\n");
+ fprintf(f, "ub4 val;\n");
+ break;
+ case AB_HM:
+ case ABDEC_HM:
+ fprintf(f, "ub4 phash(a,b)\n");
+ fprintf(f, "ub4 a;\n");
+ fprintf(f, "ub4 b;\n");
+ break;
+ }
+ fprintf(f, "{\n");
+ for (i=0; i<final->used; ++i)
+ fprintf(f, final->line[i]);
+ fprintf(f, " return rsl;\n");
+ fprintf(f, "}\n");
+ fprintf(f, "\n");
+ fclose(f);
+}
+
+/*
+------------------------------------------------------------------------------
+Read in the keys, find the hash, and write the .c and .h files
+------------------------------------------------------------------------------
+*/
+static void driver(form)
+hashform *form; /* user directives */
+{
+ ub4 nkeys; /* number of keys */
+ key *keys; /* head of list of keys */
+ bstuff *tab; /* table indexed by b */
+ ub4 smax; /* scramble[] values in 0..smax-1, a power of 2 */
+ ub4 alen; /* a in 0..alen-1, a power of 2 */
+ ub4 blen; /* b in 0..blen-1, a power of 2 */
+ ub4 salt; /* a parameter to the hash function */
+ reroot *textroot; /* MAXKEYLEN-character text lines */
+ reroot *keyroot; /* source of keys */
+ gencode final; /* code for final hash */
+ ub4 i;
+ ub4 scramble[SCRAMBLE_LEN]; /* used in final hash function */
+ char buf[10][80]; /* buffer for generated code */
+ char *buf2[10]; /* also for generated code */
+
+ /* set up memory sources */
+ textroot = remkroot((size_t)MAXKEYLEN);
+ keyroot = remkroot(sizeof(key));
+
+ /* set up code for final hash */
+ final.line = buf2;
+ final.used = 0;
+ final.len = 10;
+ for (i=0; i<10; ++i) final.line[i] = buf[i];
+
+ /* read in the list of keywords */
+ getkeys(&keys, &nkeys, textroot, keyroot, form);
+ printf("Read in %ld keys\n",nkeys);
+
+ /* find the hash */
+ findhash(&tab, &alen, &blen, &salt, &final,
+ scramble, &smax, keys, nkeys, form);
+
+ /* generate the phash.c file */
+ make_c(tab, smax, blen, scramble, &final, form);
+ printf("Wrote phash.c\n");
+
+ /* clean up memory sources */
+ refree(textroot);
+ refree(keyroot);
+ free((void *)tab);
+ printf("Cleaned up\n");
+}
+
+
+/* Interpret arguments and call the driver */
+/* See usage_error for the expected arguments */
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ int mode_given = FALSE;
+ int minimal_given = FALSE;
+ int speed_given = FALSE;
+ hashform form;
+ char *c;
+
+ /* default behavior */
+ form.mode = NORMAL_HM;
+ form.hashtype = STRING_HT;
+ form.perfect = MINIMAL_HP;
+ form.speed = SLOW_HS;
+
+ /* Generate the [minimal] perfect hash */
+ driver(&form);
+
+ return EXIT_SUCCESS;
+}
+#endif
diff --git a/tools/gap/perfect.h b/tools/gap/perfect.h
new file mode 100644
index 0000000..b78d943
--- /dev/null
+++ b/tools/gap/perfect.h
@@ -0,0 +1,132 @@
+/*
+------------------------------------------------------------------------------
+perfect.h: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.h
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+
+#ifndef PERFECT
+#define PERFECT
+
+#define MAXKEYLEN 30 /* maximum length of a key */
+#define USE_SCRAMBLE 4096 /* use scramble if blen >= USE_SCRAMBLE */
+#define SCRAMBLE_LEN ((ub4)1<<16) /* length of *scramble* */
+#define RETRY_INITKEY 2048 /* number of times to try to find distinct (a,b) */
+#define RETRY_PERFECT 1 /* number of times to try to make a perfect hash */
+#define RETRY_HEX 200 /* RETRY_PERFECT when hex keys given */
+
+/* the generated code for the final hash, assumes initial hash is done */
+struct gencode
+{
+ char **line; /* array of text lines, 80 bytes apiece */
+ /*
+ * The code placed here must declare "ub4 rsl"
+ * and assign it the value of the perfect hash using the function inputs.
+ * Later code will be tacked on which returns rsl or manipulates it according
+ * to the user directives.
+ *
+ * This code is at the top of the routine; it may and must declare any
+ * local variables it needs.
+ *
+ * Each way of filling in **line should be given a comment that is a unique
+ * tag. A testcase named with that tag should also be found which tests
+ * the generated code.
+ */
+ ub4 len; /* number of lines available for final hash */
+ ub4 used; /* number of lines used by final hash */
+
+ ub4 lowbit; /* for HEX, lowest interesting bit */
+ ub4 highbit; /* for HEX, highest interesting bit */
+ ub4 diffbits; /* bits which differ for some key */
+ ub4 i,j,k,l,m,n,o; /* state machine used in hexn() */
+};
+typedef struct gencode gencode;
+
+/* user directives: perfect hash? minimal perfect hash? input is an int? */
+struct hashform
+{
+ enum {
+ NORMAL_HM, /* key is a string */
+ INLINE_HM, /* user will do initial hash, we must choose salt for them */
+ HEX_HM, /* key to be hashed is a hexidecimal 4-byte integer */
+ DECIMAL_HM, /* key to be hashed is a decimal 4-byte integer */
+ AB_HM, /* key to be hashed is "A B", where A and B are (A,B) in hex */
+ ABDEC_HM /* like AB_HM, but in decimal */
+ } mode;
+ enum {
+ STRING_HT, /* key is a string */
+ INT_HT, /* key is an integer */
+ AB_HT /* dunno what key is, but input is distinct (A,B) pair */
+ } hashtype;
+ enum {
+ NORMAL_HP, /* just find a perfect hash */
+ MINIMAL_HP /* find a minimal perfect hash */
+ } perfect;
+ enum {
+ FAST_HS, /* fast mode */
+ SLOW_HS /* slow mode */
+ } speed;
+};
+typedef struct hashform hashform;
+
+/* representation of a key */
+struct key
+{
+ char *name_k; /* the actual key */
+ ub4 len_k; /* the length of the actual key */
+ ub4 hash_k; /* the initial hash value for this key */
+ struct key *next_k; /* next key */
+/* beyond this point is mapping-dependent */
+ ub4 a_k; /* a, of the key maps to (a,b) */
+ ub4 b_k; /* b, of the key maps to (a,b) */
+ struct key *nextb_k; /* next key with this b */
+};
+typedef struct key key;
+
+/* things indexed by b of original (a,b) pair */
+struct bstuff
+{
+ ub2 val_b; /* hash=a^tabb[b].val_b */
+ key *list_b; /* tabb[i].list_b is list of keys with b==i */
+ ub4 listlen_b; /* length of list_b */
+ ub4 water_b; /* high watermark of who has visited this map node */
+};
+typedef struct bstuff bstuff;
+
+/* things indexed by final hash value */
+struct hstuff
+{
+ key *key_h; /* tabh[i].key_h is the key with a hash of i */
+};
+typedef struct hstuff hstuff;
+
+/* things indexed by queue position */
+struct qstuff
+{
+ bstuff *b_q; /* b that currently occupies this hash */
+ ub4 parent_q; /* queue position of parent that could use this hash */
+ ub2 newval_q; /* what to change parent tab[b] to to use this hash */
+ ub2 oldval_q; /* original value of tab[b] */
+};
+typedef struct qstuff qstuff;
+
+/* return ceiling(log based 2 of x) */
+ub4 phash_log2(ub4 x);
+
+/* Given the keys, scramble[], and hash mode, find the perfect hash */
+void findhash(bstuff **tabb, hstuff **tabh, ub4 *alen, ub4 *blen, ub4 *salt,
+ gencode *final, ub4 *scramble, ub4 *smax, key *keys, ub4 nkeys,
+ hashform *form);
+
+/* private, but in a different file because it's excessively verbose */
+int inithex(key *keys, ub4 nkeys, ub4 alen, ub4 blen, ub4 smax, ub4 salt,
+ gencode *final, hashform *form);
+
+#endif /* PERFECT */
diff --git a/tools/gap/standard.h b/tools/gap/standard.h
new file mode 100644
index 0000000..596b893
--- /dev/null
+++ b/tools/gap/standard.h
@@ -0,0 +1,35 @@
+/*
+------------------------------------------------------------------------------
+Standard definitions and types, Bob Jenkins
+------------------------------------------------------------------------------
+*/
+#ifndef STANDARD
+#define STANDARD
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+#define UB4BITS 32
+typedef unsigned short int ub2;
+#define UB2MAXVAL 0xffff
+typedef unsigned char ub1;
+#define UB1MAXVAL 0xff
+typedef int word; /* fastest type available */
+
+#define bis(target,mask) ((target) |= (mask))
+#define bic(target,mask) ((target) &= ~(mask))
+#define bit(target,mask) ((target) & (mask))
+#ifndef align
+# define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1)))
+#endif /* align */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#endif /* STANDARD */
diff --git a/tools/python-yasm/Makefile.inc b/tools/python-yasm/Makefile.inc
deleted file mode 100644
index b427558..0000000
--- a/tools/python-yasm/Makefile.inc
+++ /dev/null
@@ -1,81 +0,0 @@
-# $Id$
-
-PYBINDING_DEPS = tools/python-yasm/bytecode.pxi
-PYBINDING_DEPS += tools/python-yasm/errwarn.pxi
-PYBINDING_DEPS += tools/python-yasm/expr.pxi
-PYBINDING_DEPS += tools/python-yasm/floatnum.pxi
-PYBINDING_DEPS += tools/python-yasm/intnum.pxi
-PYBINDING_DEPS += tools/python-yasm/symrec.pxi
-PYBINDING_DEPS += tools/python-yasm/value.pxi
-
-EXTRA_DIST += tools/python-yasm/pyxelator/cparse.py
-EXTRA_DIST += tools/python-yasm/pyxelator/genpyx.py
-EXTRA_DIST += tools/python-yasm/pyxelator/ir.py
-EXTRA_DIST += tools/python-yasm/pyxelator/lexer.py
-EXTRA_DIST += tools/python-yasm/pyxelator/node.py
-EXTRA_DIST += tools/python-yasm/pyxelator/parse_core.py
-EXTRA_DIST += tools/python-yasm/pyxelator/work_unit.py
-EXTRA_DIST += tools/python-yasm/pyxelator/wrap_yasm.py
-EXTRA_DIST += tools/python-yasm/setup.py
-EXTRA_DIST += tools/python-yasm/yasm.pyx
-EXTRA_DIST += $(PYBINDING_DEPS)
-
-if HAVE_PYTHON_BINDINGS
-
-# Use Pyxelator to generate Pyrex function headers.
-_yasm.pxi: ${HEADERS}
- @rm -rf .tmp
- @mkdir .tmp
- $(PYTHON) $(srcdir)/tools/python-yasm/pyxelator/wrap_yasm.py \
- "YASM_DIR=${srcdir}" "CPP=${CPP}" "CPPFLAGS=${CPPFLAGS}"
- @rm -rf .tmp
-
-CLEANFILES += _yasm.pxi
-
-# Need to build a local copy of the main Pyrex input file to include _yasm.pxi
-# from the build directory. Also need to fixup the other .pxi include paths.
-yasm.pyx: $(srcdir)/tools/python-yasm/yasm.pyx
- sed -e 's,^include "\([^_]\),include "${srcdir}/tools/python-yasm/\1,' \
- $(srcdir)/tools/python-yasm/yasm.pyx > $@
-
-CLEANFILES += yasm.pyx
-
-# Actually run Pyrex
-yasm_python.c: yasm.pyx _yasm.pxi $(PYBINDING_DEPS)
- $(PYTHON) -c "from Pyrex.Compiler.Main import main; main(command_line=1)" \
- -o $@ yasm.pyx
-
-CLEANFILES += yasm_python.c
-
-# Now the Python build magic...
-python-setup.txt: Makefile
- echo "includes=${DEFS} ${DEFAULT_INCLUDES} ${INCLUDES} ${AM_CPPFLAGS} ${CPPFLAGS}" > python-setup.txt
- echo "sources=${libyasm_a_SOURCES}" >> python-setup.txt
- echo "srcdir=${srcdir}" >> python-setup.txt
- echo "gcc=${GCC}" >> python-setup.txt
-
-CLEANFILES += python-setup.txt
-
-.python-build: python-setup.txt yasm_python.c ${libyasm_a_SOURCES}
- $(PYTHON) `test -f tools/python-yasm/setup.py || echo '$(srcdir)/'`tools/python-yasm/setup.py build
- touch .python-build
-python-build: .python-build
-
-CLEANFILES += .python-build
-
-python-install: .python-build
- $(PYTHON) `test -f tools/python-yasm/setup.py || echo '$(srcdir)/'`tools/python-yasm/setup.py install "--install-lib=$(DESTDIR)$(pythondir)"
-
-python-uninstall:
- rm -f `$(PYTHON) -c "import sys;sys.path.insert(0, '${DESTDIR}${pythondir}'); import yasm; print yasm.__file__"`
-
-else
-
-python-build:
-python-install:
-python-uninstall:
-
-endif
-
-EXTRA_DIST += tools/python-yasm/tests/Makefile.inc
-include tools/python-yasm/tests/Makefile.inc
diff --git a/tools/python-yasm/bytecode.pxi b/tools/python-yasm/bytecode.pxi
deleted file mode 100644
index 193e3a6..0000000
--- a/tools/python-yasm/bytecode.pxi
+++ /dev/null
@@ -1,107 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for bytecode.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef class Bytecode:
- cdef yasm_bytecode *bc
-
- cdef object __weakref__ # make weak-referenceable
-
- def __new__(self, bc):
- self.bc = NULL
- if PyCObject_Check(bc):
- self.bc = <yasm_bytecode *>__get_voidp(bc, Bytecode)
- else:
- raise NotImplementedError
-
- def __dealloc__(self):
- # Only free if we're not part of a section; if we're part of a section
- # the section takes care of freeing the bytecodes.
- if self.bc.section == NULL:
- yasm_bc_destroy(self.bc)
-
- property len:
- def __get__(self): return self.bc.len
- def __set__(self, value): self.bc.len = value
- property mult_int:
- def __get__(self): return self.bc.mult_int
- def __set__(self, value): self.bc.mult_int = value
- property line:
- def __get__(self): return self.bc.line
- def __set__(self, value): self.bc.line = value
- property offset:
- def __get__(self): return self.bc.offset
- def __set__(self, value): self.bc.offset = value
- property bc_index:
- def __get__(self): return self.bc.bc_index
- def __set__(self, value): self.bc.bc_index = value
- property symbols:
- # Someday extend this to do something modifiable, e.g. return a
- # list-like object.
- def __get__(self):
- cdef yasm_symrec *sym
- cdef int i
- if self.bc.symrecs == NULL:
- return []
- s = []
- i = 0
- sym = self.bc.symrecs[i]
- while sym != NULL:
- s.append(__make_symbol(sym))
- i = i+1
- sym = self.bc.symrecs[i]
- return s
-
-#
-# Keep Bytecode reference paired with bc using weak references.
-# This is broken in Pyrex 0.9.4.1; Pyrex 0.9.5 has a working version.
-#
-
-from weakref import WeakValueDictionary as __weakvaldict
-__bytecode_map = __weakvaldict()
-#__bytecode_map = {}
-
-cdef object __make_bytecode(yasm_bytecode *bc):
- __error_check()
- vptr = PyCObject_FromVoidPtr(bc, NULL)
- data = __bytecode_map.get(vptr, None)
- if data:
- return data
- bcobj = Bytecode(__pass_voidp(bc, Bytecode))
- __bytecode_map[vptr] = bcobj
- return bcobj
-
-# Org bytecode
-def __org__new__(cls, start, value=0, line=0):
- cdef yasm_bytecode *bc
- bc = yasm_bc_create_org(start, line, value)
- obj = Bytecode.__new__(cls, __pass_voidp(bc, Bytecode))
- __bytecode_map[PyCObject_FromVoidPtr(bc, NULL)] = obj
- return obj
-__org__new__ = staticmethod(__org__new__)
-class Org(Bytecode):
- __new__ = __org__new__
-
-
-#cdef class Section:
diff --git a/tools/python-yasm/errwarn.pxi b/tools/python-yasm/errwarn.pxi
deleted file mode 100644
index 9568cc0..0000000
--- a/tools/python-yasm/errwarn.pxi
+++ /dev/null
@@ -1,73 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for errwarn.h
-#
-# Copyright (C) 2006 Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-class YasmError(Exception): pass
-
-cdef int __error_check() except 1:
- cdef yasm_error_class errclass
- cdef unsigned long xrefline
- cdef char *errstr, *xrefstr
-
- # short path for the common case
- if not <int>yasm_error_occurred():
- return 0
-
- # look up our preferred python error, fall back to YasmError
- # Order matters here. Go from most to least specific within a class
- if yasm_error_matches(YASM_ERROR_ZERO_DIVISION):
- exception = ZeroDivisionError
- # Enable these once there are tests that need them.
- #elif yasm_error_matches(YASM_ERROR_OVERFLOW):
- # exception = OverflowError
- #elif yasm_error_matches(YASM_ERROR_FLOATING_POINT):
- # exception = FloatingPointError
- #elif yasm_error_matches(YASM_ERROR_ARITHMETIC):
- # exception = ArithmeticError
- #elif yasm_error_matches(YASM_ERROR_ASSERTION):
- # exception = AssertionError
- #elif yasm_error_matches(YASM_ERROR_VALUE):
- # exception = ValueError # include notabs, notconst, toocomplex
- #elif yasm_error_matches(YASM_ERROR_IO):
- # exception = IOError
- #elif yasm_error_matches(YASM_ERROR_NOT_IMPLEMENTED):
- # exception = NotImplementedError
- #elif yasm_error_matches(YASM_ERROR_TYPE):
- # exception = TypeError
- #elif yasm_error_matches(YASM_ERROR_SYNTAX):
- # exception = SyntaxError #include parse
- else:
- exception = YasmError
-
- # retrieve info (clears error)
- yasm_error_fetch(&errclass, &errstr, &xrefline, &xrefstr)
-
- if xrefline and xrefstr:
- PyErr_Format(exception, "%s: %d: %s", errstr, xrefline, xrefstr)
- else:
- PyErr_SetString(exception, errstr)
-
- if xrefstr: free(xrefstr)
- free(errstr)
- return 1
diff --git a/tools/python-yasm/expr.pxi b/tools/python-yasm/expr.pxi
deleted file mode 100644
index dea75d7..0000000
--- a/tools/python-yasm/expr.pxi
+++ /dev/null
@@ -1,136 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for expr.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef extern from *:
- # Defined as a macro, so not automatically brought in by pyxelator
- cdef yasm_expr *yasm_expr_simplify(yasm_expr *e, int calc_bc_dist)
-
-import operator
-__op = {}
-for ops, operation in [
- ((operator.__add__, operator.add, '+'), YASM_EXPR_ADD),
- ((operator.__and__, operator.and_, '&'), YASM_EXPR_AND),
- ((operator.__div__, operator.div, '/'), YASM_EXPR_SIGNDIV),
- ((operator.__floordiv__, operator.floordiv, '//'), YASM_EXPR_SIGNDIV),
- ((operator.__ge__, operator.ge, '>='), YASM_EXPR_GE),
- ((operator.__gt__, operator.gt, '>'), YASM_EXPR_GT),
- ((operator.__inv__, operator.inv, '~'), YASM_EXPR_NOT),
- ((operator.__invert__, operator.invert), YASM_EXPR_NOT),
- ((operator.__le__, operator.le, '<='), YASM_EXPR_LE),
- ((operator.__lt__, operator.lt, '<'), YASM_EXPR_LT),
- ((operator.__mod__, operator.mod, '%'), YASM_EXPR_SIGNMOD),
- ((operator.__mul__, operator.mul, '*'), YASM_EXPR_MUL),
- ((operator.__neg__, operator.neg), YASM_EXPR_NEG),
- ((operator.__not__, operator.not_, 'not'), YASM_EXPR_LNOT),
- ((operator.__or__, operator.or_, '|'), YASM_EXPR_OR),
- ((operator.__sub__, operator.sub, '-'), YASM_EXPR_SUB),
- ((operator.__xor__, operator.xor, '^'), YASM_EXPR_XOR),
- ]:
- for op in ops:
- __op[op] = operation
-
-del operator, op, ops, operation
-
-cdef object __make_expression(yasm_expr *expr):
- return Expression(__pass_voidp(expr, Expression))
-
-cdef class Expression:
- cdef yasm_expr *expr
-
- def __new__(self, op, *args, **kwargs):
- self.expr = NULL
-
- if isinstance(op, Expression):
- self.expr = yasm_expr_copy((<Expression>op).expr)
- return
- if PyCObject_Check(op):
- self.expr = <yasm_expr *>__get_voidp(op, Expression)
- return
-
- cdef size_t numargs
- cdef unsigned long line
-
- op = __op.get(op, op)
- numargs = len(args)
- line = kwargs.get('line', 0)
-
- if numargs == 0 or numargs > 2:
- raise NotImplementedError
- elif numargs == 2:
- self.expr = yasm_expr_create(op, self.__new_item(args[0]),
- self.__new_item(args[1]), line)
- else:
- self.expr = yasm_expr_create(op, self.__new_item(args[0]), NULL,
- line)
-
- cdef yasm_expr__item* __new_item(self, value) except NULL:
- cdef yasm_expr__item *retval
- if isinstance(value, Expression):
- return yasm_expr_expr(yasm_expr_copy((<Expression>value).expr))
- #elif isinstance(value, Symbol):
- # return yasm_expr_sym((<Symbol>value).sym)
- #elif isinstance(value, Register):
- # return yasm_expr_reg((<Register>value).reg)
- elif isinstance(value, FloatNum):
- return yasm_expr_float(yasm_floatnum_copy((<FloatNum>value).flt))
- elif isinstance(value, IntNum):
- return yasm_expr_int(yasm_intnum_copy((<IntNum>value).intn))
- else:
- try:
- intnum = IntNum(value)
- except:
- raise ValueError("Invalid item value type '%s'" % type(value))
- else:
- retval = yasm_expr_int((<IntNum>intnum).intn)
- (<IntNum>intnum).intn = NULL
- return retval
-
- def __dealloc__(self):
- if self.expr != NULL: yasm_expr_destroy(self.expr)
-
- def simplify(self, calc_bc_dist=False):
- self.expr = yasm_expr_simplify(self.expr, calc_bc_dist)
-
- def extract_segoff(self):
- cdef yasm_expr *retval
- retval = yasm_expr_extract_segoff(&self.expr)
- if retval == NULL:
- raise ValueError("not a SEG:OFF expression")
- return __make_expression(retval)
-
- def extract_wrt(self):
- cdef yasm_expr *retval
- retval = yasm_expr_extract_wrt(&self.expr)
- if retval == NULL:
- raise ValueError("not a WRT expression")
- return __make_expression(retval)
-
- def get_intnum(self, calc_bc_dist=False):
- cdef yasm_intnum *retval
- retval = yasm_expr_get_intnum(&self.expr, calc_bc_dist)
- if retval == NULL:
- raise ValueError("not an intnum expression")
- return __make_intnum(yasm_intnum_copy(retval))
-
diff --git a/tools/python-yasm/floatnum.pxi b/tools/python-yasm/floatnum.pxi
deleted file mode 100644
index 3939056..0000000
--- a/tools/python-yasm/floatnum.pxi
+++ /dev/null
@@ -1,49 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for floatnum.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef class FloatNum:
- cdef yasm_floatnum *flt
- def __new__(self, value):
- self.flt = NULL
- if isinstance(value, FloatNum):
- self.flt = yasm_floatnum_copy((<FloatNum>value).flt)
- return
- if PyCObject_Check(value): # should check Desc
- self.flt = <yasm_floatnum *>PyCObject_AsVoidPtr(value)
- return
-
- if isinstance(value, float): string = str(float)
- else: string = value
- self.flt = yasm_floatnum_create(string)
-
- def __dealloc__(self):
- if self.flt != NULL: yasm_floatnum_destroy(self.flt)
-
- def __neg__(self):
- result = FloatNum(self)
- yasm_floatnum_calc((<FloatNum>result).flt, YASM_EXPR_NEG, NULL)
- return result
- def __pos__(self): return self
-
diff --git a/tools/python-yasm/intnum.pxi b/tools/python-yasm/intnum.pxi
deleted file mode 100644
index f99769e..0000000
--- a/tools/python-yasm/intnum.pxi
+++ /dev/null
@@ -1,170 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for intnum.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef class IntNum
-
-cdef object __intnum_op_ex(object x, yasm_expr_op op, object y):
- value = __intnum_op(x, op, y)
- __error_check()
- return value
-
-cdef object __intnum_op(object x, yasm_expr_op op, object y):
- if isinstance(x, IntNum):
- result = IntNum(x)
- if y is None:
- yasm_intnum_calc((<IntNum>result).intn, op, NULL)
- else:
- # Coerce to intnum if not already
- if isinstance(y, IntNum):
- rhs = y
- else:
- rhs = IntNum(y)
- yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>rhs).intn)
- return result
- elif isinstance(y, IntNum):
- # Reversed operation - x OP y still, just y is intnum, x isn't.
- result = IntNum(x)
- yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>y).intn)
- return result
- else:
- raise NotImplementedError
-
-cdef object __make_intnum(yasm_intnum *intn):
- return IntNum(__pass_voidp(intn, IntNum))
-
-cdef class IntNum:
- cdef yasm_intnum *intn
-
- def __new__(self, value, base=None):
- cdef unsigned char buf[16]
-
- self.intn = NULL
-
- if isinstance(value, IntNum):
- self.intn = yasm_intnum_copy((<IntNum>value).intn)
- return
- if PyCObject_Check(value):
- self.intn = <yasm_intnum *>__get_voidp(value, IntNum)
- return
-
- if isinstance(value, str):
- if base == 2:
- self.intn = yasm_intnum_create_bin(value)
- elif base == 8:
- self.intn = yasm_intnum_create_oct(value)
- elif base == 10 or base is None:
- self.intn = yasm_intnum_create_dec(value)
- elif base == 16:
- self.intn = yasm_intnum_create_hex(value)
- elif base == "nasm":
- self.intn = yasm_intnum_create_charconst_nasm(value)
- else:
- raise ValueError("base must be 2, 8, 10, 16, or \"nasm\"")
- elif isinstance(value, (int, long)):
- _PyLong_AsByteArray(long(value), buf, 16, 1, 1)
- self.intn = yasm_intnum_create_sized(buf, 1, 16, 0)
- else:
- raise ValueError
-
- def __dealloc__(self):
- if self.intn != NULL: yasm_intnum_destroy(self.intn)
-
- def __long__(self):
- cdef unsigned char buf[16]
- yasm_intnum_get_sized(self.intn, buf, 16, 128, 0, 0, 0)
- return _PyLong_FromByteArray(buf, 16, 1, 1)
-
- def __repr__(self):
- return "IntNum(%d)" % self
-
- def __int__(self): return int(self.__long__())
- def __complex__(self): return complex(self.__long__())
- def __float__(self): return float(self.__long__())
-
- def __oct__(self): return oct(int(self.__long__()))
- def __hex__(self): return hex(int(self.__long__()))
-
- def __add__(x, y): return __intnum_op(x, YASM_EXPR_ADD, y)
- def __sub__(x, y): return __intnum_op(x, YASM_EXPR_SUB, y)
- def __mul__(x, y): return __intnum_op(x, YASM_EXPR_MUL, y)
- def __div__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y)
- def __floordiv__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y)
- def __mod__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNMOD, y)
- def __neg__(self): return __intnum_op(self, YASM_EXPR_NEG, None)
- def __pos__(self): return self
- def __abs__(self):
- if yasm_intnum_sign(self.intn) >= 0: return self
- else: return __intnum_op(self, YASM_EXPR_NEG, None)
- def __nonzero__(self): return not yasm_intnum_is_zero(self.intn)
- def __invert__(self): return __intnum_op(self, YASM_EXPR_NOT, None)
- def __lshift__(x, y): return __intnum_op(x, YASM_EXPR_SHL, y)
- def __rshift__(x, y): return __intnum_op(x, YASM_EXPR_SHR, y)
- def __and__(x, y): return __intnum_op(x, YASM_EXPR_AND, y)
- def __or__(x, y): return __intnum_op(x, YASM_EXPR_OR, y)
- def __xor__(x, y): return __intnum_op(x, YASM_EXPR_XOR, y)
-
- cdef object __op(self, yasm_expr_op op, object x):
- if isinstance(x, IntNum):
- rhs = x
- else:
- rhs = IntNum(x)
- yasm_intnum_calc(self.intn, op, (<IntNum>rhs).intn)
- return self
-
- def __iadd__(self, x): return self.__op(YASM_EXPR_ADD, x)
- def __isub__(self, x): return self.__op(YASM_EXPR_SUB, x)
- def __imul__(self, x): return self.__op(YASM_EXPR_MUL, x)
- def __idiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x)
- def __ifloordiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x)
- def __imod__(self, x): return self.__op(YASM_EXPR_MOD, x)
- def __ilshift__(self, x): return self.__op(YASM_EXPR_SHL, x)
- def __irshift__(self, x): return self.__op(YASM_EXPR_SHR, x)
- def __iand__(self, x): return self.__op(YASM_EXPR_AND, x)
- def __ior__(self, x): return self.__op(YASM_EXPR_OR, x)
- def __ixor__(self, x): return self.__op(YASM_EXPR_XOR, x)
-
- def __cmp__(self, x):
- cdef yasm_intnum *t
- t = yasm_intnum_copy(self.intn)
- if isinstance(x, IntNum):
- rhs = x
- else:
- rhs = IntNum(x)
- yasm_intnum_calc(t, YASM_EXPR_SUB, (<IntNum>rhs).intn)
- result = yasm_intnum_sign(t)
- yasm_intnum_destroy(t)
- return result
-
- def __richcmp__(x, y, op):
- cdef yasm_expr_op aop
- if op == 0: aop = YASM_EXPR_LT
- elif op == 1: aop = YASM_EXPR_LE
- elif op == 2: aop = YASM_EXPR_EQ
- elif op == 3: aop = YASM_EXPR_NE
- elif op == 4: aop = YASM_EXPR_GT
- elif op == 5: aop = YASM_EXPR_GE
- else: raise NotImplementedError
- v = __intnum_op(x, aop, y)
- return bool(not yasm_intnum_is_zero((<IntNum>v).intn))
diff --git a/tools/python-yasm/pyxelator/TODO b/tools/python-yasm/pyxelator/TODO
deleted file mode 100644
index cfe1e18..0000000
--- a/tools/python-yasm/pyxelator/TODO
+++ /dev/null
@@ -1,16 +0,0 @@
-
-pyxelator TODO:
-===============
-
-.) callback functions: these are working but it needs to be thought out some more. Exceptions are not propagated from callbacks.
-.) no nice module structure: it's all in one fat module.
-.) extern symbols and macros are a little tricky to wrap, some have been hardcoded (!!) in petscmacros.py.
-.) type checking
-.) upcasting
-.) adapt system memory usage audit: record and check every malloc/free/memcpy/memcmp
- and every memory access using those nasty void* pointers
-
-21/10/05
-
-
-
diff --git a/tools/python-yasm/pyxelator/cparse.py b/tools/python-yasm/pyxelator/cparse.py
deleted file mode 100755
index 53754f8..0000000
--- a/tools/python-yasm/pyxelator/cparse.py
+++ /dev/null
@@ -1,819 +0,0 @@
-#!/usr/bin/env python
-
-"""
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-"""
-
-import sys
-
-from lexer import Lexer
-from parse_core import Symbols, Parser
-import node as node_module
-
-
-class Node(node_module.Node):
-
- def is_typedef(self):
- for x in self:
- if isinstance(x,Node):
- if x.is_typedef():
- return 1
- return 0
-
- #def explain(self):
- #l = []
- #for x in self:
- #if isinstance(x,Node):
- #l.append(x.explain())
- #else:
- #l.append(str(x))
- #return string.join(l," ")
- ##(self.__class__.__name__,string.join(l) )
-
- def psource(self):
- if hasattr(self,'lines'):
- print "# "+string.join(self.lines,"\n# ")+"\n"
-
-
-###################################################################
-#
-###################################################################
-#
-
-
-class BasicType(Node):
- " int char short etc. "
- def __init__(self,name):
- Node.__init__(self,name)
-
-class Qualifier(Node):
- """
- """
- def __init__(self,name):
- Node.__init__(self,name)
- self.name=name
-
-class StorageClass(Node):
- """
- """
- def __init__(self,name):
- Node.__init__(self,name)
- self.name=name
-
-class Typedef(StorageClass):
- """
- """
- def __init__(self,s='typedef'):
- Node.__init__(self,s)
- #def explain(self):
- #return "type"
-
-class Ellipses(Node):
- """
- """
- def __init__(self,s='...'):
- Node.__init__(self,s)
-
-class GCCBuiltin(BasicType):
- """
- """
- pass
-
-
-class Identifier(Node):
- """
- """
- def __init__(self,name="",*items):
- if name or 1:
- Node.__init__(self,name,*items)
- else:
- Node.__init__(self)
- self.name=name
-
-class Function(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
-
- def parse(self,lexer,symbols):
- symbols = Symbols(symbols)
- args = ''
- #lexer.get_token()
- if lexer.tok != ')':
- if not lexer.tok:
- self.parse_error(lexer)
- #lexer.unget_token() # unget start of decl
- while lexer.tok != ')':
- node = ParameterDeclaration()
- node.parse(lexer,symbols)
- self.append( node )
- if lexer.tok != ')' and lexer.tok != ',':
- self.parse_error(lexer)
- if lexer.tok == ',':
- lexer.get_token()
- lexer.get_token()
-
-
-class Pointer(Node):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
-
-class Array(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
-
- def parse(self,lexer,symbols):
- lexer.get_token() # a number or ']'
- # XX
- # HACK HACK: constant c expressions can appear in here:
- # eg. [ 15 * sizeof (int) - 2 * sizeof (void *) ]
- # XX
- toks = []
- while lexer.tok != ']':
- #self.append( lexer.kind )
- toks.append( lexer.tok )
- lexer.get_token()
- child = " ".join(toks)
- if child == "":
- child = None
- self.append( child )
- lexer.get_token() # read past the ']'
-
-class Tag(Node):
- """
- """
- pass
-
-
-class Compound(Node,Parser):
- "Struct or Union"
-
- def __init__(self,*items,**kw):
- Node.__init__(self,*items,**kw)
-
- def parse(self,lexer,symbols):
- symbols = Symbols(symbols)
- tag = "" # anonymous
- if lexer.tok != '{':
- tag = lexer.tok
- if not ( tag[0]=='_' or tag[0].isalpha() ):
- self.parse_error(lexer ,"expected tag, got '%s'"%tag )
- lexer.get_token()
- if tag:
- self.append(Tag(tag))
- else:
- self.append(Tag())
- self.tag = tag
- if lexer.tok == '{':
- fieldlist = []
- lexer.get_token()
- if lexer.tok != '}':
- if not lexer.tok: self.parse_error(lexer)
- while lexer.tok != '}':
- node = StructDeclaration()
- node.parse(lexer,symbols)
- fieldlist.append( node )
- self += fieldlist
- lexer.get_token()
- if self.verbose:
- print "%s.__init__() #<--"%(self)
-
-class Struct(Compound):
- """
- """
- pass
-
-class Union(Compound):
- """
- """
- pass
-
-class Enum(Node,Parser):
- """
- """
- def __init__(self,*items,**kw):
- Node.__init__(self,*items,**kw)
-
- def parse(self,lexer,symbols):
- tag = "" # anonymous
- if lexer.tok != '{':
- tag = lexer.tok
- if not ( tag[0]=='_' or tag[0].isalpha() ):
- self.parse_error(lexer ,"expected tag, got '%s'"%tag )
- lexer.get_token()
- if tag:
- self.append(Tag(tag))
- else:
- self.append(Tag())
- self.tag = tag
- if lexer.tok == '{':
- lexer.get_token()
- if lexer.tok != '}': # XX dopey control flow
- if not lexer.tok: # XX dopey control flow
- self.parse_error(lexer) # XX dopey control flow
- while lexer.tok != '}': # XX dopey control flow
- if lexer.kind is not None:
- self.expected_error(lexer ,"identifier" )
- ident = Identifier(lexer.tok)
- if symbols[ident[0]] is not None:
- self.parse_error(lexer,"%s already defined."%ident[0])
- symbols[ident[0]]=ident
- self.append( ident )
- lexer.get_token()
- if lexer.tok == '=':
- lexer.get_token()
- # ConstantExpr
- # XX hack hack XX
- while lexer.tok!=',' and lexer.tok!='}':
- lexer.get_token()
-# if type( lexer.kind ) is not int:
-# #self.parse_error(lexer ,"expected integer" )
-# # XX hack hack XX
-# while lexer.tok!=',' and lexer.tok!='}':
-# lexer.get_token()
-# else:
-# # put initializer into the Identifier
-# ident.append( lexer.kind )
-# lexer.get_token()
- if lexer.tok != '}':
- if lexer.tok != ',':
- self.expected_error(lexer,"}",",")
- lexer.get_token() # ','
- lexer.get_token()
- if self.verbose:
- print "%s.__init__() #<--"%(self)
-
-
-
-class Declarator(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
- self.ident = None
-
- def parse(self,lexer,symbols):
- #Parser.parse_enter(self,lexer)
- stack = []
- # read up to identifier, pushing tokens onto stack
- self.ident = self.parse_identifier(lexer,symbols,stack)
- self.name = ''
- if self.ident is not None:
- self.append( self.ident )
- self.name = self.ident.name
- # now read outwards from identifier
- self.parse_declarator(lexer,symbols,stack)
- #Parser.parse_leave(self,lexer)
-
- def parse_identifier(self,lexer,symbols,stack):
- if self.verbose:
- print "%s.parse_identifier()"%self
- ident = None
- if lexer.tok != ';':
- while lexer.tok and lexer.kind is not None:
- stack.append( (lexer.tok, lexer.kind) )
- lexer.get_token()
- if lexer.tok:
- ident = Identifier( lexer.tok )
- #stack.append( (ident.name, ident) )
- lexer.get_token()
- if self.verbose:
- print "%s.parse_identifier()=%s"%(self,repr(ident))
- return ident
-
- def parse_declarator(self,lexer,symbols,stack,level=0):
- if self.verbose:
- print " "*level+"%s.parse_declarator(%s) # --->"%\
- (self,stack)
- if lexer.tok == '[':
- while lexer.tok == '[':
- node = Array()
- node.parse(lexer,symbols)
- self.append(node)
- if lexer.tok == '(':
- self.parse_error(lexer ,"array of functions" )
- elif lexer.tok == '(':
- lexer.get_token()
- node = Function()
- node.parse(lexer,symbols)
- self.append( node )
- if lexer.tok == '(':
- self.parse_error(lexer ,"function returns a function" )
- if lexer.tok == '[':
- self.parse_error(lexer ,"function returns an array" )
- while stack:
- tok, kind = stack[-1] # peek
- if tok == '(':
- stack.pop()
- self.consume(lexer,')')
- self.parse_declarator(lexer,symbols,stack,level+1)
- elif tok == '*':
- stack.pop()
- self.append( Pointer() )
- else:
- tok, kind = stack.pop()
- self.append( kind )
- if self.verbose:
- print " "*level+"%s.parse_declarator(%s) # <---"%\
- (self,stack)
-
-
-class AbstractDeclarator(Declarator):
- """ used in ParameterDeclaration; may lack an identifier """
-
- def parse_identifier(self,lexer,symbols,stack):
- if self.verbose:
- print "%s.parse_identifier()"%self
- ident = None
- ident = Identifier()
- while 1:
- if lexer.tok == ';':
- self.parse_error(lexer)
- if lexer.tok == ')':
- break
- if lexer.tok == ',':
- break
- if lexer.tok == '[':
- break
- if lexer.kind is None:
- #print "%s.new identifier"%self
- ident = Identifier( lexer.tok )
- lexer.get_token()
- #stack.append( (ident.name, ident) )
- break
- stack.append( (lexer.tok, lexer.kind) )
- lexer.get_token()
- if self.verbose:
- print "%s.parse_identifier()=%s"%(self,repr(ident))
- return ident
-
-class FieldLength(Node):
- """
- """
- pass
-
-class StructDeclarator(Declarator):
- """
- """
- def parse(self,lexer,symbols):
- if lexer.tok != ':':
- Declarator.parse(self,lexer,symbols)
- if lexer.tok == ':':
- lexer.get_token()
- # ConstantExpr
- length = int(lexer.tok)
- #print "length = ",length
- self.append( FieldLength(length) )
- lexer.get_token()
-
-class DeclarationSpecifiers(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
-
- def __eq__(self,other):
- " unordered (set/bag) equality "
- if not isinstance(other,Node):
- return 0
- for i in range(len(self)):
- if not self[i] in other:
- return 0
- for i in range(len(other)):
- if not other[i] in self:
- return 0
- return 1
-
- def parse(self,lexer,symbols):
- self.parse_spec(lexer,symbols)
- self.reverse()
-
- def parse_spec(self,lexer,symbols):
- typespec = None
- while lexer.tok:
- if isinstance( lexer.kind, TypeAlias ) or\
- isinstance( lexer.kind, BasicType ):
- if typespec is not None:
- self.parse_error(lexer ,"type already specified as %s"\
- %typespec )
- typespec=lexer.kind
- self.append( lexer.kind )
- lexer.get_token()
- elif isinstance( lexer.kind, Qualifier ):
- self.append( lexer.kind )
- lexer.get_token()
- elif isinstance( lexer.kind, StorageClass ):
- self.append( lexer.kind )
- lexer.get_token()
- elif lexer.tok=='struct':
- lexer.get_token()
- self.parse_struct(lexer,symbols)
- break #?
- elif lexer.tok=='union':
- lexer.get_token()
- self.parse_union(lexer,symbols)
- break #?
- elif lexer.tok=='enum':
- lexer.get_token()
- self.parse_enum(lexer,symbols)
- break #?
- elif lexer.kind is None:
- # identifier
- break
- else:
- break
-
- def parse_struct(self,lexer,symbols):
- if self.verbose:
- print "%s.parse_struct()"%(self)
- node = Struct()
- node.parse(lexer,symbols)
- _node = None
- if node.tag:
- _node = symbols.get_tag( node.tag )
- if _node is not None:
- if not isinstance( _node, Struct ):
- self.parse_error(lexer,"tag defined as wrong kind")
- if len(node)>1:
- if len(_node)>1:
- self.parse_error(lexer,"tag already defined as %s"%_node)
- #symbols.set_tag( node.tag, node )
- #else:
- # refer to the previously defined struct
- ##node = _node
- #node = _node.clone()
- if 0:
- # refer to the previously defined struct
- if len(node)==1:
- _node = symbols.deep_get_tag( node.tag )
- if _node is not None:
- node=_node
- # But what about any future reference to the struct ?
- if node.tag:
- symbols.set_tag( node.tag, node )
- self.append( node )
-
- def parse_union(self,lexer,symbols):
- if self.verbose:
- print "%s.parse_union(%s)"%(self,node)
- node = Union()
- node.parse(lexer,symbols)
- _node = None
- if node.tag:
- _node = symbols.get_tag( node.tag )
- if _node is not None:
- if not isinstance( _node, Union ):
- self.parse_error(lexer,"tag %s defined as wrong kind"%repr(node.tag))
- if len(node)>1:
- if len(_node)>1:
- self.parse_error(lexer,"tag already defined as %s"%_node)
- #symbols.set_tag( node.tag, node )
- #else:
- #node = _node
- #if len(node)==1:
- #_node = symbols.deep_get_tag( node.tag )
- #if _node is not None:
- #node=_node
- if node.tag:
- symbols.set_tag( node.tag, node )
- self.append( node )
-
- def parse_enum(self,lexer,symbols):
- if self.verbose:
- print "%s.parse_enum(%s)"%(self,node)
- node = Enum()
- node.parse(lexer,symbols)
- _node = None
- if node.tag:
- _node = symbols.get_tag( node.tag )
- if _node is not None:
- if not isinstance( _node, Enum ):
- self.parse_error(lexer,"tag defined as wrong kind")
- if len(node)>1:
- if len(_node)>1:
- self.parse_error(lexer,"tag already defined as %s"%_node)
- #symbols.set_tag( node.tag, node )
- #else:
- #node = _node
- #if len(node)==1:
- #_node = symbols.deep_get_tag( node.tag )
- #if _node is not None:
- #node=_node
- if node.tag:
- symbols.set_tag( node.tag, node )
- self.append( node )
-
- def is_typedef(self):
- return self.find(Typedef) is not None
-
- def needs_declarator(self):
- for node in self:
- if isinstance( node, Struct ):
- return False
- if isinstance( node, Enum ):
- return False
- if isinstance( node, Union ):
- return False
- return True
-
-
-
-class TypeSpecifiers(DeclarationSpecifiers):
- " used in ParameterDeclaration "
-
- def parse_spec(self,lexer,symbols):
- typespec = None
- while lexer.tok:
- if isinstance( lexer.kind, TypeAlias ) or\
- isinstance( lexer.kind, BasicType ):
- if typespec is not None:
- self.parse_error(lexer ,"type already specified as %s"\
- %typespec )
- typespec=lexer.kind
- self.append( lexer.kind )
- lexer.get_token()
- elif isinstance( lexer.kind, Qualifier ):
- self.append( lexer.kind )
- lexer.get_token()
- elif isinstance( lexer.kind, StorageClass ):
- self.parse_error(lexer ,"'%s' cannot appear here"%lexer.tok )
- elif lexer.tok=='struct':
- lexer.get_token()
- self.parse_struct(lexer,symbols)
- break #?
- elif lexer.tok=='union':
- lexer.get_token()
- self.parse_union(lexer,symbols)
- break #?
- elif lexer.tok=='enum':
- lexer.get_token()
- self.parse_enum(lexer,symbols)
- break #?
- elif lexer.kind is None:
- # identifier
- break
- else:
- break
-
-
-class Initializer(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
-
- def parse(self,lexer,symbols):
- self.parse_error(lexer,"not implemented")
-
-
-class TypeAlias(Node):
- " typedefed things "
-
- def __init__(self,name,decl=None):
- Node.__init__(self,name)#,decl)
- self.name=name
- self.decl=decl
-
-
-class Declaration(Node,Parser):
- """
- """
- def __init__(self,*items):
- Node.__init__(self,*items)
- #self.acted=False
-
- def parse(self,lexer,symbols):
- if not lexer.tok:
- return
- Parser.parse_enter(self,lexer)
- declspec = DeclarationSpecifiers()
- declspec.parse(lexer,symbols)
- if len(declspec)==0:
- if lexer.tok == ';':
- lexer.get_token()
- # empty declaration...
- return
- self.parse_error(lexer,
- "expected specifiers, got '%s'"%lexer.tok )
- self.append(declspec)
- while 1:
- decl = Declarator()
- decl.parse(lexer,symbols)
- if len(decl)==0:
- if declspec.needs_declarator():
- self.parse_error(lexer,
- "expected declarator, got '%s'"%lexer.tok )
- self.append(decl)
- ident = decl.ident
- if ident is not None:
- #if len(ident):
- # install symbol
- node = symbols[ident[0]]
- if node is not None:
- # we allow functions to be defined (as same) again
- #print node.deepstr(),'\n', self.deepstr()
- _node = node.clone()
- _node.delete(Identifier)
- _self = self.clone()
- _self.delete(Identifier)
- if _node != _self:
- self.parse_error(lexer,
- "\n%s\n already defined as \n%s\n"%\
- (self.deepstr(),node.deepstr()))
- else:
- if self.is_typedef():
- #lexer.mktypedef( ident[0], self )
- tp = TypeAlias(ident[0],decl)
- lexer.mktypedef( ident[0], tp )
- else:
- symbols[ident[0]] = self
- if lexer.tok == '=':
- # parse initializer
- lexer.get_token()
- init = Initializer()
- init.parse(lexer,symbols)
- ident.append( init ) # as in Enum
- #else: struct, union or enum
- if lexer.tok == ';':
- # no more declarators
- break
- if lexer.tok == '{':
- # ! ahhh, function body !!!
-# sys.stderr.write(
-# "WARNING: function body found at line %s\n"%lexer.lno )
- bcount = 1
- while bcount:
- lexer.get_brace_token()
- if lexer.tok == '}':
- bcount -= 1
- if lexer.tok == '{':
- bcount += 1
- lexer.get_token()
- Parser.parse_leave(self,lexer)
- return
- self.consume(lexer,',')
- self.consume(lexer,';')
- Parser.parse_leave(self,lexer)
-
- def is_typedef(self):
- spec=self[0]
- assert isinstance(spec,DeclarationSpecifiers), self.deepstr()
- return spec.is_typedef()
-
-
-class ParameterDeclaration(Declaration):
- """
- """
- def parse(self,lexer,symbols):
- typespec = TypeSpecifiers()
- typespec.parse(lexer,symbols)
- self.append(typespec)
- decl = AbstractDeclarator()
- decl.parse(lexer,symbols)
- self.append(decl)
- ident = decl.ident
- if ident is not None and ident[0]:
- node = symbols[ident[0]]
- if node is not None:
- self.parse_error(lexer,
- "%s already defined as %s"%(ident,node))
- else:
- symbols[ident[0]] = self
-
-
-class StructDeclaration(Declaration):
- """
- """
- def parse(self,lexer,symbols):
- if not lexer.tok:
- return
- declspec = DeclarationSpecifiers()
- declspec.parse(lexer,symbols)
- self.append(declspec)
- if len(declspec)==0:
- if lexer.tok == ';':
- lexer.get_token()
- # empty declaration...
- return
- self.parse_error(lexer,
- "expected specifiers, got '%s'"%lexer.tok )
- while 1:
- decl = StructDeclarator()
- decl.parse(lexer,symbols)
- if len(decl)==0:
- self.parse_error(lexer,
- "expected declarator, got '%s'"%lexer.tok )
- self.append(decl)
- ident = decl.ident
- if ident is not None:
- node = symbols[ident[0]]
- if node is not None:
- self.parse_error(lexer ,
- "%s already defined as %s"%(ident,node))
- else:
- if declspec.is_typedef():
- self.parse_error(lexer,"typedef in struct or union")
- else:
- symbols[ident[0]] = self
- if lexer.tok == ';':
- break
- self.consume(lexer,',')
- self.consume(lexer,';')
-
-
-class TransUnit(Node,Parser):
- """
- """
- def __init__(self,*items,**kw):
- Node.__init__(self,*items,**kw)
-
- def parse(self,s,verbose=0):
- self.symbols = Symbols()
- self.lexer = Lexer(s,verbose=verbose) #,host=__module__)
- node = None
- while self.lexer.tok:
- node=Declaration()
- node.parse(self.lexer,self.symbols)
- #sys.stderr.write( "# line %s\n"%self.lexer.lno )
- if node:
- self.append(node)
- #node.psource()
- #print node.deepstr(),'\n'
- #node.act()
-
- def strip(self,files):
- " leave only the declarations from <files> "
- i=0
- while i<len(self):
- if self[i].file in files:
- i=i+1
- else:
- self.pop(i)
-
- def strip_filter(self,cb):
- " leave only the declarations such that cb(file) "
- i=0
- while i<len(self):
- if cb(self[i].file):
- i=i+1
- else:
- self.pop(i)
-
- def assert_no_dups(self):
- check={}
- for node in self.nodes():
- assert not check.has_key(id(node))
- check[id(node)]=1
-
-
-
-try:
- import NoModule
- import psyco
- from psyco.classes import *
-except ImportError:
- class _psyco:
- def jit(self): pass
- def bind(self, f): pass
- def proxy(self, f): return f
- psyco = _psyco()
-psyco.bind( Lexer.get_token )
-psyco.bind( Node )
-
-def run0():
- verbose = 0
- if not sys.argv[1:]:
- s = sys.stdin.read()
- if sys.argv[1:]:
- s = sys.argv[1]
- #if sys.argv[2:]:
- #verbose = int(sys.argv[2])
- if 0:
- import profile
- profile.run('TransUnit(s)','prof.out')
- import pstats
- p=pstats.Stats('prof.out')
- p.strip_dirs().sort_stats(-1).print_stats()
- else:
- node = TransUnit(verbose = 1 )
- node.parse(s)
- node.act(1,1,1)
-
-def run1():
- cstr = "char *(*)() ,"
- node = AbstractDeclarator()
- node.parse( Lexer(cstr,True), Symbols() )
- print node.deepstr()
-
-if __name__=="__main__":
- pass
-
-
diff --git a/tools/python-yasm/pyxelator/genpyx.py b/tools/python-yasm/pyxelator/genpyx.py
deleted file mode 100755
index 00cfa3f..0000000
--- a/tools/python-yasm/pyxelator/genpyx.py
+++ /dev/null
@@ -1,531 +0,0 @@
-#!/usr/bin/env python
-""" genpyx.py - parse c declarations
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-This is a module of mixin classes for ir.py .
-
-Towards the end of ir.py our global class definitions
-are remapped to point to the class definitions in ir.py .
-So, for example, when we refer to Node we get ir.Node .
-
-"""
-
-import sys
-from datetime import datetime
-from sets import Set
-
-# XX use this Context class instead of all those kw dicts !! XX
-class Context(object):
- " just a record (struct) "
- def __init__( self, **kw ):
- for key, value in kw.items():
- setattr( self, key, value )
- def __getattr__( self, name ):
- return None # ?
- def __getitem__( self, name ):
- return getattr(self, name)
-
-class OStream(object):
- def __init__( self, filename=None ):
- self.filename = filename
- self.tokens = []
- self._indent = 0
- def put( self, token="" ):
- assert type(token) is str
- self.tokens.append( token )
- def startln( self, token="" ):
- assert type(token) is str
- self.tokens.append( ' '*self._indent + token )
- def putln( self, ln="" ):
- assert type(ln) is str
- self.tokens.append( ' '*self._indent + ln + '\n')
- def endln( self, token="" ):
- assert type(token) is str
- self.tokens.append( token + '\n')
- def indent( self ):
- self._indent += 1
- def dedent( self ):
- self._indent -= 1
- assert self._indent >= 0, self._indent
- def join( self ):
- return ''.join( self.tokens )
- def close( self ):
- s = ''.join( self.tokens )
- f = open( self.filename, 'w' )
- f.write(s)
-
-#
-###############################################################################
-#
-
-class Node(object):
- """
- tree structure
- """
- _unique_id = 0
- def get_unique_id(cls):
- Node._unique_id += 1
- return Node._unique_id
- get_unique_id = classmethod(get_unique_id)
-
-# XX toks: use a tree of tokens: a list that can be push'ed and pop'ed XX
- def pyxstr(self,toks=None,indent=0,**kw):
- """
- Build a list of tokens; return the joined tokens string
- """
- if toks is None:
- toks = []
- for x in self:
- if isinstance(x,Node):
- x.pyxstr(toks, indent, **kw)
- else:
- toks.insert(0,str(x)+' ')
- s = ''.join(toks)
- return s
-
-#
-#################################################
-
-class Named(object):
- "has a .name property"
- pass
-
-class BasicType(object):
- "float double void char int"
- pass
-
-class Qualifier(object):
- "register signed unsigned short long const volatile inline"
- def pyxstr(self,toks=None,indent=0,**kw):
- if toks is None:
- toks = []
- x = self[0]
- if x not in ( 'const','volatile','inline','register'): # ignore these
- toks.insert(0,str(x)+' ')
- s = ''.join(toks)
- return s
-
-class StorageClass(object):
- "extern static auto"
- def pyxstr(self,toks=None,indent=0,**kw):
- return ""
-
-class Ellipses(object):
- "..."
- pass
-
-class GCCBuiltin(BasicType):
- "things with __builtin prefix"
- pass
-
-class Identifier(object):
- """
- """
- def pyxstr(self,toks=None,indent=0,**kw):
- if toks is None:
- toks=[]
- if self.name:
- toks.append( self.name )
- return " ".join(toks)
-
-class TypeAlias(object):
- """
- typedefed things, eg. size_t
- """
- def pyxstr(self,toks=None,indent=0,cprefix="",**kw):
- if toks is None:
- toks = []
- for x in self:
- if isinstance(x,Node):
- x.pyxstr(toks, indent, cprefix=cprefix, **kw)
- else:
- s = str(x)+' '
- if cprefix:
- s = cprefix+s
- toks.insert(0,s)
- s = ''.join(toks)
- return s
-
-class Function(object):
- """
- """
- def pyxstr(self,toks,indent=0,**kw):
- #print '%s.pyxstr(%s)'%(self,toks)
- _toks=[]
- assert len(self)
- i=0
- while isinstance(self[i],Declarator):
- if not self[i].is_void():
- _toks.append( self[i].pyxstr(indent=indent, **kw) )
- i=i+1
- toks.append( '(%s)'% ', '.join(_toks) )
- while i<len(self):
- self[i].pyxstr(toks, indent=indent, **kw)
- i=i+1
- return " ".join(toks)
-
-class Pointer(object):
- """
- """
- def pyxstr(self,toks,indent=0,**kw):
- assert len(self)
- node=self[0]
- toks.insert(0,'*')
- if isinstance(node,Function):
- toks.insert(0,'(')
- toks.append(')')
- elif isinstance(node,Array):
- toks.insert(0,'(')
- toks.append(')')
- return Node.pyxstr(self,toks,indent, **kw)
-
-class Array(object):
- """
- """
- def pyxstr(self,toks,indent=0,**kw):
- if self.size is None:
- toks.append('[]')
- else:
- try:
- int(self.size)
- toks.append('[%s]'%self.size)
- except:
- toks.append('[]')
- return Node( *self[:-1] ).pyxstr( toks,indent, **kw )
-
-class Tag(object):
- " the tag of a Struct, Union or Enum "
- pass
-
-class Taged(object):
- "Struct, Union or Enum "
- pass
-
-class Compound(Taged):
- "Struct or Union"
- def pyxstr(self,_toks=None,indent=0,cprefix="",shadow_name=True,**kw):
- if _toks is None:
- _toks=[]
- names = kw.get('names',{})
- kw['names'] = names
- tag_lookup = kw.get('tag_lookup')
- if self.tag:
- tag=self.tag.name
- else:
- tag = ''
- if isinstance(self,Struct):
- descr = 'struct'
- elif isinstance(self,Union):
- descr = 'union'
- _node = names.get(self.tag.name,None)
- if ( _node is not None and _node.has_members() ) or \
- ( _node is not None and not self.has_members() ):
- descr = '' # i am not defining myself here
- #print "Compound.pyxstr", tag
- #print self.deepstr()
- if descr:
- if cprefix and shadow_name:
- tag = '%s%s "%s"'%(cprefix,tag,tag)
- elif cprefix:
- tag = cprefix+tag
- toks = [ descr+' '+tag ] # struct foo
- if self.has_members():
- toks.append(':\n')
- for decl in self[1:]: # XX self.members
- toks.append( decl.pyxstr(indent=indent+1, cprefix=cprefix, shadow_name=shadow_name, **kw)+"\n" ) # shadow_name = False ?
- #elif not tag_lookup.get( self.tag.name, self ).has_members():
- # define empty struct here, it's the best we're gonna get
- #pass
- else:
- if cprefix: # and shadow_name:
- tag = cprefix+tag
- toks = [ ' '+tag+' ' ] # foo
- while toks:
- _toks.insert( 0, toks.pop() )
- return "".join( _toks )
-
-class Struct(Compound):
- """
- """
- pass
-
-class Union(Compound):
- """
- """
- pass
-
-
-class Enum(Taged):
- """
- """
- def pyxstr(self,_toks=None,indent=0,cprefix="",shadow_name=True,**kw):
- if _toks is None:
- _toks=[]
- names = kw.get('names',{})
- kw['names'] = names
- if self.tag:
- tag=self.tag.name
- else:
- tag = ''
- _node = names.get(self.tag.name,None)
- if ( _node is not None and _node.has_members() ) or \
- ( _node is not None and not self.has_members() ):
- descr = '' # i am not defining myself here
- else:
- descr = 'enum'
- if descr:
- #if not names.has_key(self.tag.name):
- toks = [ descr+' '+tag ] # enum foo
- toks.append(':\n')
- idents = [ ident for ident in self.members if ident.name not in names ]
- for ident in idents:
- if cprefix and shadow_name:
- ident = ident.clone()
- ident.name = '%s%s "%s"' % ( cprefix, ident.name, ident.name )
- #else: assert 0
- toks.append( ' '+' '*indent + ident.pyxstr(**kw)+"\n" )
- names[ ident.name ] = ident
- if not idents:
- # empty enum def'n !
- #assert 0 # should be handled by parents...
- toks.append( ' '+' '*indent + "pass\n" )
- else:
- toks = [ ' '+tag+' ' ] # foo
- while toks:
- _toks.insert( 0, toks.pop() )
- return "".join( _toks )
-
-class Declarator(object):
- def is_pyxnative( self ):
- # pyrex handles char* too
- # but i don't know if we should make this the default
- # sometimes we want to send a NULL, so ... XX
- self = self.cbasetype() # WARNING: cbasetype may be cached
- if self.is_void():
- return False
- if self.is_primative():
- return True
- if self.enum:
- return True
- #pointer = None
- #if self.pointer:
- #pointer = self.pointer
- #elif self.array:
- #pointer = self.array
- #if pointer and pointer.spec:
- #spec = pointer.spec
- #if BasicType("char") in spec and not Qualifier("unsigned") in spec:
- # char*, const char*
- ##print self.deepstr()
- #return True
- return False
-
- def _pyxstr( self, toks, indent, cprefix, use_cdef, shadow_name, **kw ):
- " this is the common part of pyxstr that gets called from both Declarator and Typedef "
- names = kw.get('names',{}) # what names have been defined ?
- kw['names']=names
- for node in self.nodes(): # depth-first
- if isinstance(node,Taged):
- #print "Declarator.pyxstr", node.cstr()
- if not node.tag.name:
- node.tag.name = "_anon_%s" % Node.get_unique_id()
- _node = names.get(node.tag.name,None)
- #tag_lookup = kw.get('tag_lookup')
- #other = tag_lookup.get(node.tag.name, node)
- #if ((_node is None and (not isinstance(other,Compound) or not other.has_members()))
- # or node.has_members()):
- if _node is None or node.has_members():
- # either i am not defined at all, or this is my _real_ definition
- # emit def'n of this node
- #if isinstance(self,Typedef):
- #toks.append( ' '*indent + 'ctypedef ' + node.pyxstr(indent=indent, cprefix=cprefix, shadow_name=shadow_name, **kw).strip() )
- #else:
- toks.append( ' '*indent + 'cdef ' + node.pyxstr(indent=indent, cprefix=cprefix, shadow_name=shadow_name, **kw).strip() )
- names[ node.tag.name ] = node
- elif isinstance(node,GCCBuiltin) and node[0] not in names:
- #toks.append( ' '*indent + 'ctypedef long ' + node.pyxstr(indent=indent, **kw).strip() + ' # XX ??' ) # XX ??
- toks.append( ' '*indent + 'struct __unknown_builtin ' )
- toks.append( ' '*indent + 'ctypedef __unknown_builtin ' + node.pyxstr(indent=indent, **kw).strip() )
- names[ node[0] ] = node
- for idx, child in enumerate(node):
- if type(child)==Array and not child.has_size():
- # mutate this mystery array into a pointer XX method: Array.to_pointer()
- node[idx] = Pointer()
- node[idx].init_from( child ) # warning: shallow init
- node[idx].pop() # pop the size element
-
- def pyxstr(self,toks=None,indent=0,cprefix="",use_cdef=True,shadow_name=True,**kw):
- " note: i do not check if my name is already in 'names' "
- self = self.clone() # <----- NOTE
- toks=[]
- names = kw.get('names',{}) # what names have been defined ?
- kw['names']=names
-
- self._pyxstr( toks, indent, cprefix, use_cdef, shadow_name, **kw )
-
- if self.name and not names.has_key( self.name ):
- names[ self.name ] = self
- if self.identifier is not None:
- comment = ""
- if self.name in python_kws:
- comment = "#"
- if cprefix and use_cdef and shadow_name:
- # When we are defining this guy, we refer to it using the pyrex shadow syntax.
- self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name )
- cdef = 'cdef '
- if not use_cdef: cdef = '' # sometimes we don't want the cdef (eg. in a cast)
- # this may need shadow_name=False:
- toks.append( ' '*indent + comment + cdef + Node.pyxstr(self,indent=indent, cprefix=cprefix, **kw).strip() ) # + "(cprefix=%s)"%cprefix)
- #else: i am just a struct def (so i already did that) # huh ?? XX bad comment
- return ' \n'.join(toks)
-
- def pyxsym(self, ostream, names=None, tag_lookup=None, cprefix="", modname=None, cobjects=None):
- assert self.name is not None, self.deepstr()
- ostream.putln( '# ' + self.cstr() )
-# This cdef is no good: it does not expose a python object
-# and we can't reliably set a global var
- #ostream.putln( 'cdef %s %s' % ( self.pyx_adaptor_decl(cobjects), self.name ) ) # _CObject
- #ostream.putln( '%s = %s()' % (self.name, self.pyx_adaptor_name(cobjects)) )
- #ostream.putln( '%s.p = <void*>&%s' % (self.name, cprefix+self.name) )
- ## expose a python object:
- #ostream.putln( '%s.%s = %s' % (modname,self.name, self.name) )
- ostream.putln( '%s = %s( addr = <long>&%s )' % (self.name, self.pyx_adaptor_name(cobjects), cprefix+self.name) )
- return ostream
-
-
-class Typedef(Declarator):
- def pyxstr(self,toks=None,indent=0,cprefix="",use_cdef=True,shadow_name=True,**kw): # shadow_name=True
- " warning: i do not check if my name is already in 'names' "
- assert shadow_name == True
- self = self.clone() # <----- NOTE
- toks=[]
- names = kw.get('names',{}) # what names have been defined ?
- kw['names']=names
-
- #if self.tagged and not self.tagged.tag.name:
- ## "typedef struct {...} foo;" => "typedef struct foo {...} foo;"
- ## (to be emitted in the node loop below, and suppressed in the final toks.append)
- #self.tagged.tag = Tag( self.name ) # this is how pyrex does it: tag.name == self.name
- # XX that doesn't work (the resulting c fails to compile) XX
-
- self._pyxstr( toks, indent, cprefix, use_cdef, shadow_name, **kw )
-
- #print self.deepstr()
- if self.name and not names.has_key( self.name ):
- names[ self.name ] = self
- if not (self.tagged and self.name == self.tagged.tag.name):
- comment = ""
- if self.name in python_kws:
- comment = "#"
- #if cprefix:
- # self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name ) # XX pyrex can't do this
- if cprefix: # shadow_name=True
- # My c-name gets this prefix. See also TypeAlias.pyxstr(): it also prepends the cprefix.
- self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name )
- toks.append( ' '*indent + comment + 'ctypedef ' + Node.pyxstr(self,indent=indent, cprefix=cprefix, **kw).strip() )
- return ' \n'.join(toks)
-
-
-class AbstractDeclarator(Declarator):
- """ used in Function; may lack an identifier """
- def pyxstr(self,toks=None,indent=0,**kw):
- if self.name in python_kws:
- # Would be better to do this in __init__, but our subclass doesn't call our __init__.
- self.name = '_' + self.name
- #return ' '*indent + Node.pyxstr(self,toks,indent, **kw).strip()
- return Node.pyxstr(self,toks,indent, **kw).strip()
-
-
-class FieldLength(object):
- """
- """
- def pyxstr(self,toks,indent,**kw):
- pass
-
-
-class StructDeclarator(Declarator): # also used in Union
- """
- """
- def pyxstr(self,toks=None,indent=0,**kw):
- comment = ""
- if self.name in python_kws:
- comment = "#"
- return ' '*indent + comment + Node.pyxstr(self,toks,indent, **kw).strip()
-
-class DeclarationSpecifiers(object):
- """
- """
- pass
-
-class TypeSpecifiers(DeclarationSpecifiers):
- """
- """
- pass
-
-class Initializer(object):
- """
- """
- pass
-
-class Declaration(object):
- """
- """
- pass
-
-class ParameterDeclaration(Declaration):
- """
- """
- pass
-
-class StructDeclaration(Declaration):
- """
- """
- pass
-
-class TransUnit(object):
- """
- Top level node.
- """
- def pyx_decls(self, filenames, modname, macros = {}, names = {}, func_cb=None, cprefix="", **kw):
- # PART 1: emit extern declarations
- ostream = OStream()
- now = datetime.today()
- ostream.putln( now.strftime('# Code generated by pyxelator on %x at %X') + '\n' )
- ostream.putln("# PART 1: extern declarations")
- for filename in filenames:
- ostream.putln( 'cdef extern from "%s":\n pass\n' % filename )
- ostream.putln( 'cdef extern from *:' )
- file = None # current file
- for node in self:
- ostream.putln('')
- ostream.putln(' # ' + node.cstr() )
- assert node.marked
- comment = False
- if node.name and node.name in names:
- comment = True # redeclaration
- #ostream.putln( node.deepstr( comment=True ) )
- s = node.pyxstr(indent=1, names=names, tag_lookup = self.tag_lookup, cprefix=cprefix, **kw)
- if s.split():
- if comment:
- s = "#"+s.replace( '\n', '\n#' ) + " # redeclaration "
- if node.file != file:
- file = node.file
- #ostream.putln( 'cdef extern from "%s":' % file )
- ostream.putln( ' # "%s"' % file )
- ostream.putln( s )
- ostream.putln('\n')
- #s = '\n'.join(toks)
- return ostream.join()
-
-# XX warn when we find a python keyword XX
-python_kws = """
-break continue del def except exec finally pass print raise
-return try global assert lambda yield
-for while if elif else and in is not or import from """.split()
-python_kws = dict( zip( python_kws, (None,)*len(python_kws) ) )
-
-
diff --git a/tools/python-yasm/pyxelator/ir.py b/tools/python-yasm/pyxelator/ir.py
deleted file mode 100755
index cfa9c02..0000000
--- a/tools/python-yasm/pyxelator/ir.py
+++ /dev/null
@@ -1,1163 +0,0 @@
-#!/usr/bin/env python
-""" ir.py - parse c declarations
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-import sys
-#import cPickle as pickle
-import pickle
-
-#from lexer import Lexer
-from parse_core import Symbols #, Parser
-import node as node_module
-import cparse
-import genpyx
-
-class Node(genpyx.Node, node_module.Node):
- """
- tree structure
- """
- def __init__( self, *args, **kw ):
- node_module.Node.__init__( self, *args, **kw )
- self._marked = False
- def get_marked( self ):
- return self._marked
- def set_marked( self, marked ):
-# if marked:
-# print "MARK", self
- self._marked = marked
- marked = property( get_marked, set_marked )
-
-# def __getstate__( self ):
-# return self.__class__, tuple( [ item.__getstate__() for item in self ] )
-# def __setstate__( self, state ):
-# cls, states = state
-# states = list(states)
-# for idx, state in enumerate(states):
-# items[idx] = items[idx].__setstate__(
- def __getstate__(self):
- return str(self)
- def __setstate__(self, state):
- Node.__init__(self)
- self[:] = eval(state)
-
-# _unique_id = 0
-# def get_unique_id(cls):
-# Node._unique_id += 1
-# return Node._unique_id
-# get_unique_id = classmethod(get_unique_id)
-
- def __hash__( self ):
- return hash( tuple([hash(type(self))]+[hash(item) for item in self]) )
-
- def clone(self):
- l = []
- for item in self:
- if isinstance(item,Node):
- item = item.clone()
- l.append(item)
- return self.__class__(*l, **self.__dict__)
-
- def init_from( self, other ): # class method ?
- # Warning: shallow init
- self[:] = other
- self.__dict__.update( other.__dict__ )
- return self
-
-# def is_struct(self):
-# for x in self:
-# if isinstance(x,Node):
-# if x.is_struct():
-# return 1
-# return 0
-
-
- #def explain(self):
- #l = []
- #for x in self:
- #if isinstance(x,Node):
- #l.append(x.explain())
- #else:
- #l.append(str(x))
- #return string.join(l," ")
- ##(self.__class__.__name__,string.join(l) )
-
- def psource(self):
- if hasattr(self,'lines'):
-# print "# "+string.join(self.lines,"\n# ")+"\n"
- print "# "+"\n# ".join(self.lines)+"\n"
-
- def cstr(self,l=None):
- """
- Build a list of tokens; return the joined tokens string
- """
- if l is None:
- l = []
- for x in self:
- if isinstance(x,Node):
- x.cstr(l)
- else:
- l.insert(0,str(x)+' ')
- s = ''.join(l)
- return s
-
- def ctype(self): # anon_clone
- " return clone of self without identifiers "
- #print "%s.ctype()"%self
- l=[]
- for x in self:
- if isinstance(x,Node):
- l.append(x.ctype())
- else:
- l.append(x)
- #print "%s.__class__(*%s)"%(self,l)
- return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
-
- def cbasetype(self):
- " return ctype with all TypeAlias's replaced "
- # WARNING: we cache results (so do not mutate self!!)
- l=[]
- for x in self:
- if isinstance(x,Node):
- l.append(x.cbasetype())
- else:
- l.append(x)
- #print "%s.__class__(*%s)"%(self,l)
- return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
-
- def signature( self, tank=None ):
- if tank is None:
- tank = {}
- for node in self.nodes():
- if not tank.has_key( type(node) ):
- tank[ type(node) ] = {}
- type(node).tank = tank[type(node)]
- shape = tuple( [ type(_node).__name__ for _node in node ] )
- if not tank[type(node)].has_key(shape):
- tank[type(node)][shape] = []
- tank[type(node)][shape].append( node )
- return tank
-
- def psig( self, tank=None ):
- if tank is None:
- tank = {}
- tank = self.signature(tank)
- for key in tank.keys():
- print key.__name__
- for shape in tank[key].keys():
- print " ", shape
-
-#
-#################################################
-
-class Named(genpyx.Named, Node):
- " has a .name property "
- def get_name(self):
- if self:
- assert type(self[0])==str
- return self[0]
- return None
- def set_name(self, name):
- if self:
- self[0] = name
- else:
- self.append(name)
- name = property(get_name,set_name)
-
-
-class BasicType(genpyx.BasicType, Named):
- "float double void char int"
- pass
-
-class Qualifier(genpyx.Qualifier, Named):
- "register signed unsigned short long const volatile inline"
- pass
-
-class StorageClass(genpyx.StorageClass, Named):
- "extern static auto"
- pass
-
-class Ellipses(genpyx.Ellipses, Named):
- "..."
- pass
-
-class GCCBuiltin(genpyx.GCCBuiltin, BasicType):
- "things with __builtin prefix"
- pass
-
-class Identifier(genpyx.Identifier, Named):
- """
- shape = +( str, +ConstExpr )
- """
- #def explain(self):
- #if len(self)==1:
- #return "%s"%self.name
- #else:
- #return "%s initialized to %s"%(self.name,
- #Node(self[1]).explain()) # will handle Initializer
-
-# def ctype(self):
-# return self.__class__(*self[1:]) #.clone() ?
-
-# def get_name(self):
-# if self:
-# return self[0]
-# def set_name(self, name):
-# if self:
-# self[0] = name
-# else:
-# self.append(name)
-# name = property(get_name,set_name)
-
- def cstr(self,l=None):
- if l is None:
- l=[]
- if len(self)>1:
- assert len(self)==2
- l.append( '%s = %s'%(self[0],self[1]) )
- elif len(self)==1:
- l.append( str(self[0]) )
- return " ".join(l)
-
-class TypeAlias(genpyx.TypeAlias, Named):
- """
- typedefed things, eg. size_t
-
- """
- def cbasetype( self ):
- node = self.typedef.cbasetype().get_rest()
- return node
-
-class Function(genpyx.Function, Node):
- """
- """
- #def explain(self):
- #if len(self):
- #return "function (%s), returning"%\
- #", ".join( map(lambda x:x.explain(),self) )
- #else:
- #return "function returning"
-
- def cstr(self,l):
- #print '%s.cstr(%s)'%(self,l)
- _l=[]
- assert len(self)
- i=0
- while isinstance(self[i],Declarator):
- _l.append( self[i].cstr() )
- i=i+1
- l.append( '(%s)'% ', '.join(_l) )
- while i<len(self):
- self[i].cstr(l)
- i=i+1
- return " ".join(l)
-
- def return_type(self):
- node = self[-1]
- #assert isinstance(node,DeclarationSpecifiers)
- return Declarator( Identifier(), node )
- ret = property(return_type)
-
- def get_args(self):
- args = [ arg for arg in self[:-1] if not arg.is_void() ]
- return args
- args = property(get_args)
-
- def arg_types(self):
- return [ AbstractDeclarator().init_from( arg.ctype() ) for arg in self[:-1]]
-
- def is_varargs(self):
- for node in self.nodes():
- if isinstance(node,Ellipses) or 'va_list' in node:
-# print self, 'is_varargs'
- return True
-# print self, 'is_varargs'
- return False
-# return fn.deepfind(Ellipses) or fn.deepfind('va_list')
-
- def ctype(self):
- return Function(*self.arg_types()+[self[-1]]) # XX self[-1].ctype
-
-
-class Pointer(genpyx.Pointer, Node):
- """
- """
- def get_spec(self):
- if type(self[0])==TypeSpecifiers: # isinstance ??
- return self[0]
- spec = property(get_spec)
-
- #def explain(self):
- #return "pointer to"
-
- def cstr(self,l):
- assert len(self)
- node=self[0]
- l.insert(0,'*')
- if isinstance(node,Function):
- l.insert(0,'(')
- l.append(')')
- elif isinstance(node,Array):
- l.insert(0,'(')
- l.append(')')
- return Node.cstr(self,l)
-
-class Array(genpyx.Array, Node):
- """
- """
- #def explain(self):
- #s=''
- #if len(self):
- #if type(self[0])==int:
- #s='0 to %s '%(self[0]-1)
- #return "array %sof"%s
- def has_size(self):
- try:
- int(self.size)
- return True
- except:
- return False
-
- def get_size(self):
- if type(self[-1])==str:
- try: return int(self[-1])
- except: return self[-1]
- return self[-1] # None
- size = property(get_size)
-
- def get_spec(self):
- if type(self[0])==TypeSpecifiers: # isinstance ??
- return self[0]
- spec = property(get_spec)
-
- def to_pointer(self):
- node = Pointer()
- node.init_from( self.clone() )
- node.pop() # pop the size element
- return node
-
- def cstr(self,l):
- if self.size is None:
- l.append('[]')
- else:
- l.append('[%s]'%self.size)
- return Node( *self[:-1] ).cstr( l )
-
-class Tag(genpyx.Tag, Named):
- " the tag of a Struct, Union or Enum "
- pass
-
-class Taged(genpyx.Taged, Node):
- "Struct, Union or Enum "
- def get_tag(self):
- if len(self):
- tag = self[0]
- assert type(tag)==Tag # isinstance ??
- else:
- tag = None
- return tag
- def set_tag(self,tag):
- if len(self):
- self[0] = tag
- else:
- self.append(tag)
- tag = property( get_tag, set_tag )
- def has_members(self):
- return len(self)>1 # more than just a tag
- def get_members(self):
- return self[1:]
- members = property(get_members) # fields ?
-
- def ctype(self):
- if not self.tag.name:
- #print "# WARNING : anonymous struct " # OK i think
- return self.clone()
-# self = self.clone()
-# return self[:1] # just the tag
- return self.__class__( self.tag, **self.__dict__ ) # just the Tag
-# return self.__class__( *self, **self.__dict__ )
-
- def cbasetype(self):
- return self.ctype() # is this enough ???
-# return Node.cbasetype(self) # XX lookup my tag if i am empty ..?
-
-
-class Compound(genpyx.Compound, Taged):
- "Struct or Union"
-
- def cstr(self,_l=None):
- assert isinstance( self[0], Tag )
- tag=''
- if len(self[0]):
- tag=' '+self[0][0]
- if isinstance(self,Struct):
- l=[ 'struct%s '%tag ]
- elif isinstance(self,Union):
- l=[ 'union%s '%tag ]
- if len(self)>1:
- l.append(' { ')
- for decl in self[1:]:
- l.append( decl.cstr()+"; " )
- l.append('} ')
- if _l is None:
- _l=[]
- while l:
- _l.insert( 0, l.pop() )
- # XX empty struct with no tag -> "struct" XX
- return "".join( _l )
-
- def ctype(self):
- tp = Taged.ctype(self)
- for i in range(1,len(tp)):
- tp[i] = StructDeclarator().init_from( tp[i] )
- return tp
-
-class Struct(genpyx.Struct, Compound):
- """
- """
- pass
-
-
-class Union(genpyx.Union, Compound):
- """
- """
- pass
-
-
-class Enum(genpyx.Enum, Taged):
- """
- """
- def cstr(self,_l=None):
- assert isinstance( self[0], Tag )
- tag=''
- if len(self[0]):
- tag=' '+self[0][0]
- l=[ 'enum%s '%tag ]
- if len(self)>1:
- l.append(' { ')
- for node in self[1:]:
- l.append( node.cstr()+', ' )
- l.append('} ')
- if _l is None:
- _l=[]
- while l:
- _l.insert( 0, l.pop() )
- return ''.join( _l )
-
-class Declarator(genpyx.Declarator, Node):
- """
- """
-
- def __eq__(self,other):
- " unordered equality "
- # ordering sometimes gets lost when we do a cbasetype
- if not isinstance(other,Node):
- return False
- a, b = self[:], other[:]
- a.sort()
- b.sort()
- return a == b
-
- def __hash__( self ):
- hs = [hash(item) for item in self]
- hs.sort()
- return hash( tuple([hash(type(self))]+hs) )
-
- def transform(self):
- return
-
- def get_identifier(self):
- if len(self)>1:
- return self[0]
- def set_identifier(self, identifier):
- if len(self)>1:
- self[0] = identifier
- else:
- self.insert(0,identifier)
- identifier = property(get_identifier,set_identifier)
-
- def get_spec(self):
- spec = self[-1]
- if type(spec)==TypeSpecifiers: # isinstance ??
- return spec
- spec = property(get_spec)
-
- def get_type_alias(self):
- if self.spec:
- if isinstance(self.spec[0], TypeAlias):
- return self.spec[0]
- type_alias = property(get_type_alias)
-
- def get_tagged(self):
- if self.spec:
- return self.spec.tagged # i am a tagged
- tagged = property(get_tagged)
-
- def get_compound(self):
- if self.spec:
- return self.spec.compound # i am a compound
- compound = property(get_compound)
-
- def get_struct(self):
- if self.spec:
- return self.spec.struct # i am a struct
- struct = property(get_struct)
-
- def get_union(self):
- if self.spec:
- return self.spec.union # i am a union
- union = property(get_union)
-
- def get_enum(self):
- if self.spec:
- return self.spec.enum # i am an enum
- enum = property(get_enum)
-
- def get_function(self):
- if len(self)>1 and type(self[1])==Function: # isinstance ??
- return self[1]
- function = property(get_function)
-
- def get_pointer(self):
- if len(self)>1 and type(self[1])==Pointer: # isinstance ??
- return self[1]
- pointer = property(get_pointer)
-
- def get_array(self):
- if len(self)>1 and type(self[1])==Array: # isinstance ??
- return self[1]
- array = property(get_array)
-
- def get_name(self):
- if self.identifier:
- return self.identifier.name
- def set_name(self, name):
- assert self.identifier is not None
- self.identifier.name = name
- name = property(get_name, set_name)
-
- def get_rest(self): # XX needs a better name
- if len(self)>1:
- return self[1]
- return self[0]
-
- def pointer_to( self ):
- " return Declarator pointing to self's type "
- decl = Declarator(Identifier(), Pointer(self.get_rest().clone()))
- return decl
-
- def deref( self ):
- " return (clone of) Declarator that self is pointing to "
- node = self.ctype() # clone
- pointer = node.pointer or node.array
- assert pointer, "cannot dereference non-pointer"
- node[1:2] = pointer
- return node
-
- def is_void(self):
- return self.spec and BasicType('void') in self.spec
-
- def is_pointer_to_fn(self):
- return self.pointer and self.deref().function
-
- def is_pointer_to_char(self):
-# return self.ctype() == TransUnit("char *a;").transform()[0].ctype()
- node = self.pointer or self.array
- if node:
- spec = node.spec
- if spec and BasicType('char') in spec and not BasicType('unsigned') in spec:
- return True
- return False
-
- def is_callback(self):
- " i am a pointer to a function whose last arg is void* "
- if self.is_pointer_to_fn():
- fn = self.deref().function
- if fn.args:
- arg = fn.args[-1]
- if arg.pointer and arg.deref().is_void():
- return True
-
- def is_complete( self, tag_lookup ):
- if self.tagged and self.tagged.tag.name in tag_lookup and not tag_lookup[self.tagged.tag.name].has_members():
- return False
- return True
-
- def is_primative( self ):
- "i am a char,short,int,float,double... "
- spec = self.cbasetype().spec
- return spec and spec.find(BasicType)
-
- def is_pyxnative( self ):
- # pyrex handles char* too
- # but i don't know if we should make this the default
- # sometimes we want to send a NULL, so ... XXX
- self = self.cbasetype()
- if self.is_void():
- return False
- if self.is_primative():
- return True
- if self.enum:
- return True
-# pointer = None
-# if self.pointer:
-# pointer = self.pointer
-# elif self.array:
-# pointer = self.array
-# if pointer and pointer.spec:
-# spec = pointer.spec
-# if BasicType("char") in spec and not Qualifier("unsigned") in spec:
-# # char*, const char*
-## print self.deepstr()
-# return True
- return False
-
- def cstr(self,l=None):
- return Node.cstr(self,l).strip()
-
- def ctype(self):
- decl=Declarator()
- decl.init_from( self.clone() )
- decl.identifier = Identifier()
- for i in range(1,len(decl)):
- decl[i]=decl[i].ctype()
- return decl
-
- def cbasetype(self):
- # WARNING: we cache results (so do not mutate self!!)
- try:
- # this cache improves performance by 50%
- return self.__cbasetype.clone()
- except AttributeError:
- pass
- decl = self.ctype() # gets rid of Identifier names
- for i, node in enumerate(decl):
- decl[i] = decl[i].cbasetype()
-# return decl.get_rest()
-
- done = False
- while not done:
- done = True
- nodes = decl.deepfilter( TypeSpecifiers )
- for node in nodes:
- if node.deepfind( TypeSpecifiers ) != node:
- # this node has another TypeSpecifier;
- decl.expose_node( node )
- done = False
- break # start again...
-
- # each TypeSpecifier needs to absorb primitive siblings (StorageClass, BasicType etc.)
- nodes = decl.deepfilter( TypeSpecifiers )
- for node in nodes:
- parent = decl.get_parent(node)
- i = 0
- while i < len(parent):
- assert not type(parent[i]) in (TypeAlias, Enum, Struct, Union)
- if type(parent[i]) in (StorageClass, BasicType, Qualifier):
- node.append( parent.pop(i) )
- else:
- i = i + 1
-
- self.__cbasetype = decl.clone()
- return decl
-
- def invalidate(self):
- # flush cache, etc.
- try:
- del self.__cbasetype
- except AttributeError:
- pass
-
- def declare_str(self,name):
- " return c string declaring name with same type as self "
- tp = self.ctype()
- tp.name = name
- return tp.cstr()+";"
-
-class Typedef(genpyx.Typedef, Declarator):
- def cstr(self,l=None):
- return 'typedef ' + Declarator.cstr(self,l) #.strip()
-
-class AbstractDeclarator(genpyx.AbstractDeclarator, Declarator):
- """ used in Function; may lack an identifier """
-
- #def cstr(self,l=None):
- #return Node.cstr(self,l)
-
-# def ctype(self):
-# # _type_ ignores the name of our identifier
-# return Node.ctype(self)
-
-class FieldLength(genpyx.FieldLength, Node):
- """
- """
- #def explain(self):
- #return ""
-
- def cstr(self,l):
- l.append(':%s'%self[0])
-
-class StructDeclarator(genpyx.StructDeclarator, Declarator): # also used in Union
- """
- """
- #def explain(self):
- #flen = self.find(FieldLength)
- #if flen is not None:
- #i = self.index(flen)
- #self.pop(i)
- #s = Declarator.explain(self)
- #self.insert(i,flen)
- #width = flen[0]
- #if width > 0:
- #return s+" bitfield %s wide"%width
- #else:
- #return s+" alignment bitfield"
- #else:
- #return Declarator.explain(self)
-# def ctype(self):
-# return self
- def get_field_length(self):
- if len(self)>1 and isinstance( self[1], FieldLength ):
- return self[1]
- field_length = property(get_field_length)
-
-
-class DeclarationSpecifiers(genpyx.DeclarationSpecifiers, Node):
-#class TypeSpecifiers(Node):
- """
- """
- def __eq__(self,other):
- " unordered equality "
- if not isinstance(other,Node):
- return False
- a, b = self[:], other[:]
- a.sort()
- b.sort()
- return a == b
-
- def __hash__( self ):
- hs = [hash(item) for item in self]
- hs.sort()
- return hash( tuple([hash(type(self))]+hs) )
-
-# def is_struct(self):
-# return self.find(Struct) is not None
-
-
-class TypeSpecifiers(genpyx.TypeSpecifiers, DeclarationSpecifiers):
- """
- """
- def get_tagged(self):
- if self and isinstance(self[0],Taged):
- return self[0]
- tagged = property(get_tagged)
-
- def get_compound(self):
- if self and isinstance(self[0],Compound):
- return self[0]
- compound = property(get_compound)
-
- def get_struct(self):
- if self and isinstance(self[0],Struct):
- return self[0]
- struct = property(get_struct)
-
- def get_union(self):
- if self and isinstance(self[0],Union):
- return self[0]
- union = property(get_union)
-
- def get_enum(self):
- if self and isinstance(self[0],Enum):
- return self[0]
- enum = property(get_enum)
-
- def cbasetype(self):
- node = Node.cbasetype(self)
-# node.expose( TypeSpecifiers )
-# if node.deepfind(TypeSpecifiers) != node:
- return node
-
-class Initializer(genpyx.Initializer, Node):
- """
- """
- pass
-
-
-
-class Declaration(genpyx.Declaration, Node):
- """
- """
- def do_spec(self):
- " distribute DeclarationSpecifiers over each Declarator "
- spec=self[0]
- assert isinstance(spec,DeclarationSpecifiers), spec.deepstr()
- self.pop(0)
- for declarator in self:
- assert isinstance(declarator,Declarator)
- #if isinstance(declarator,DeclarationSpecifiers #huh?
- ##for node in spec:
- ##declarator.append(node.clone())
- declarator.append(spec)
-
- def transform(self):
- # children go first
- for node in self.nodes():
- if isinstance(node,Declaration):
- node.do_spec()
- node.file = self.file # overkill ?
- self.expose(Declaration)
-
- #def explain(self):
- #return string.join([x.explain() for x in self],", ")
- #return string.join(map(lambda x:x.explain(),self),", ")
-
-
-class ParameterDeclaration(genpyx.ParameterDeclaration, Declaration):
- """
- """
- pass
-
-
-class StructDeclaration(genpyx.StructDeclaration, Declaration):
- """
- """
- pass
-
-
-class TransUnit(genpyx.TransUnit, Node):
- """
- Top level node.
- """
- def __init__( self, item ): # XX __init__ uses different signature ! XX
- if type(item)==str:
- node = cparse.TransUnit()
- node.parse(item)
- else:
- node = item
- assert isinstance( node, cparse.TransUnit ), str(node)
- Node.__init__(self)
- self[:] = [ self.convert(child) for child in node ]
- self.__dict__.update( node.__dict__ )
- assert "name" not in node.__dict__
-
- self.syms = {} # map identifier names to their Declarator's
- self.typedefs = {} # map names to Typedef's
- self.tag_lookup = {} # map struct, union, enum tags to Taged's
-
- # XX should call transform here XX
-
-# print self.deepstr()
- def __getstate__( self ):
- nodes = tuple( [ repr(node) for node in self ] )
- typedefs = tuple( [ (key,repr(val)) for key,val in self.typedefs.items() ] )
- return nodes, typedefs
- def __setstate__( self, state ):
- Node.__init__(self)
- nodes, typedefs = state
- nodes = [ eval(node) for node in nodes ]
- self[:] = nodes
- typedefs = [ (key,eval(val)) for key,val in typedefs ]
- self.typedefs = dict(typedefs)
-
- def convert( self, node ):
-# name = node.__class__.__name__
-# cls = globals()[ name ]
- cls = cls_lookup[ type(node) ]
- _node = cls()
- for child in node:
- if isinstance(child, node_module.Node):
- child = self.convert( child )
- else:
- assert child is None or type(child) in (str, int), type(child)
- _node.append( child )
- _node.__dict__.update( node.__dict__ )
- return _node
-
- def strip(self,files):
- " leave only the declarations from <files> "
- i=0
- while i<len(self):
- if self[i].file in files:
- i=i+1
- else:
- self.pop(i)
-
- def mark(self,cb,verbose=False):
- " mark our child nodes such that cb(node).. mark dependants too. prune unmarked objects. "
- # mark the nodes:
- for node in self:
- node.marked = cb(self, node)
- if verbose and node.marked:
- print '1:', node.cstr()
- # propagate dependancy:
- i=len(self)
- while i:
- i-=1 # we go backwards
- for node in self[i].nodes(): # bottom-up search
- if verbose and self[i].marked and not node.marked:
- print '2:', str(node), '<--', self[i].cstr()
- node.marked = self[i].marked or node.marked
- if type(node)==TypeAlias:
- if verbose and node.marked and not node.typedef.marked:
- print '3:', node.typedef.cstr(), '<--', node.cstr()
- node.typedef.marked = node.typedef.marked or node.marked
- if isinstance(node, Taged):
- if node.tag.name in self.tag_lookup:
- _node = self.tag_lookup[ node.tag.name ] # look-up the def'n
- if verbose and node.marked and not _node.marked:
- print '4:', _node.cstr(), '<--', self[i].cstr()
-# _node.marked = _node.marked or self[i].marked
- _node.marked = _node.marked or node.marked
-# else:
-# # this guy has no tag
-# print "lost tag:", self[i].cstr()
-
- # XX struct defs acquire marks from members, but XX
- # XX ordinary definitions do not XX
-# if node.marked and not self[i].marked:
-# # one of my descendants is marked
-# if verbose:
-# print '5:', self[i].cstr(), '<--', node.cstr()
-# self[i].marked = True
-# if verbose:
-# for node in self:
-# print '-'*79
-# if node.enum:
-# print str(node.marked) + ': ' + node.cstr()
- # prune:
- f = open(".tmp/pruned.txt","w")
- f.write("// This file autogenerated by '%s' .\n"%__file__)
- f.write("// List of functions pruned from parse tree, for various reasons.\n\n")
- i=0
- while i<len(self):
- if not self[i].marked:
- if verbose: print 'pop:', self[i].cstr()
- f.write( self[i].cstr() + "\n" )
- self.pop(i)
-# elif self[i].compound:
-# # XXXX for now, rip out all struct members XXXX
-# self[i].compound[1:] = [] # XX encapsulation
-# i = i + 1
- else:
- i = i + 1
- for key, value in self.syms.items():
- if not value.marked:
- del self.syms[key]
- for key, value in self.typedefs.items():
- if not value.marked:
- del self.typedefs[key]
- for key, value in self.tag_lookup.items():
- if not value.marked:
- del self.tag_lookup[key]
-# sys.exit(1)
-
- def assert_no_dups(self):
- check={}
- for node in self.nodes():
- assert not check.has_key(id(node))
- check[id(node)]=1
-
- def transform(self, verbose=False, test_parse=False, test_types=False ):
- i=0
- while i < len(self):
- if verbose: print "##"*25
- declaration=self[i]
-
- if verbose: declaration.psource()
- if verbose: print declaration.deepstr(),'\n'
- assert isinstance(declaration,Declaration)
- if verbose: print "# expose declarators from declaration"
-
- # STAGE 1
- declaration.transform()
-
- if verbose: print declaration.deepstr(),'\n'
- self[i:i+1] = declaration # expose declarators from declaration
-
- for j in range(len(declaration)):
- declarator=self[i]
-
- assert isinstance(declarator,Declarator)
- if verbose: print "# declarator.transform()"
-
- # STAGE 2
- declarator.transform()
-
- if verbose: print declarator.deepstr(),'\n'
- if verbose: print "# self.visit_declarator(declarator)"
-
- # STAGE 3
- self[i] = declarator = self.visit_declarator(declarator)
-
- # STAGE 4
- if declarator.name:
- if isinstance(declarator, Typedef):
- if verbose: print "# typedef %s" % declarator.name
- self.typedefs[ declarator.name ] = declarator
- else:
- if verbose: print "# sym %s" % declarator.name
- self.syms[ declarator.name ] = declarator
-
- for node in declarator.nodes():
- if isinstance(node,Taged) and node.tag.name:
- assert type(node.tag.name)==str, node.deepstr()
- taged = self.tag_lookup.get( node.tag.name, None )
- if taged is None:
- if verbose: print "# tag lookup %s = %s" % (declarator.name, node.tag.name)
- self.tag_lookup[ node.tag.name ] = node
- elif not taged.has_members():
- # this is (maybe) the definition of this tag
- if verbose: print "# definition %s = %s" % (declarator.name, node.tag.name)
- self.tag_lookup[ node.tag.name ] = node
-
- # Annotate the TypeAlias's
- for node in declarator.deepfilter( TypeAlias ):
- name = node[0]
- assert type( name ) == str
- node.typedef = self.typedefs[ name ]
-
- if verbose: print declarator.deepstr(),'\n'
- #print declarator.ctype().deepstr(),'\n'
- #assert declarator.clone() == declarator
-
- ###################################################
- # TESTS:
- if test_parse:
- # test that parse of cstr gives same answer
- cstr = declarator.cstr()+';\n'
- if verbose: print '# '+cstr.replace('\n','\n# ')
- #print
- if isinstance(declarator,Typedef):
- name = declarator[0][0]
- assert type(name)==str
- self.lexer.rmtypedef( name )
- declaration = cparse.Declaration()
- self.lexer.lex( cstr )
- #print self.lexer.err_string()
- declaration.parse( self.lexer, Symbols() ) # use new name-space
- #declaration.parse( Lexer( cstr ), Symbols() )
- declaration = self.convert(declaration)
- declaration.transform()
- assert len(declaration)==1
- decl=declaration[0]
- decl.transform()
- decl = self.visit_declarator(decl)
- if decl!=declarator:
- if verbose: print "#???????????"
- if verbose: print decl.deepstr(),'\n\n'
- #if verbose: print declaration.deepstr(),'\n\n'
- #assert 0
- elif verbose: print '# OK\n'
-
- if test_types:
- node = declarator.ctype()
- declare_str= node.declare_str("my_name")
- if verbose: print "# declarator.ctype() "
- if verbose: print node.deepstr(),"\n"
- if verbose: print "#",declare_str.replace('\n','\n# '), '\n'
-
- i=i+1
- return self
-
- def visit(self,node):
- #print 'visit(%s)'%node
- for _node in node:
- if isinstance(_node,Declarator):
- _node = self.visit_declarator(_node) # XX replace _node
- elif isinstance(_node,Node):
- _node = self.visit(_node) # XX replace _node
- return node
-
- def visit_declarator(self,decl):
- assert isinstance(decl,Declarator)
-
- # STAGE 3.a
- tp = decl.deepfind(Typedef)
- if tp is not None:
- decl.deeprm(tp)
- tp.init_from( decl ) # warning: shallow init
- decl = tp
-
- # STAGE 3.b
- i=len(decl)
- # accumulate nodes (they become the children of decl)
- children=[]
- while i:
- i=i-1
- node=decl.pop(i)
- if isinstance(node,Declarator):
- node = self.visit_declarator(node) # replace node
- else:
- node = self.visit(node) # replace node
- if isinstance(node,Pointer):
- node+=children
- children=[node]
- elif isinstance(node,Function):
- node+=children
- children=[node]
- elif isinstance(node,Array):
- while children:
- node.insert(0,children.pop())
- children=[node]
- # array size (if any) at end
- #elif isinstance(node,Identifier):
- #node+=children
- #children=[node]
- else:
- # accumulate
- children.insert(0,node)
- decl[:]=children
- return decl
-
- cstr = None
- ctype = None
- cbasetype = None
-
-
-# remap the global class definitions in genpyx to
-# point to the definitions in this module
-gbl = globals()
-for key, val in gbl.items():
- if type(val)==type:
- if issubclass(val,Node):
- setattr( genpyx, key, val )
-assert genpyx.Node == Node
-
-cls_lookup = {
-# Node : Node ,
- cparse.BasicType : BasicType ,
- cparse.Qualifier : Qualifier ,
- cparse.StorageClass : StorageClass ,
- cparse.Ellipses : Ellipses ,
- cparse.GCCBuiltin : GCCBuiltin ,
- cparse.Identifier : Identifier ,
- cparse.TypeAlias : TypeAlias ,
- cparse.Function : Function ,
- cparse.Pointer : Pointer ,
- cparse.Array : Array ,
- cparse.Tag : Tag ,
- cparse.Compound : Compound ,
- cparse.Struct : Struct ,
- cparse.Union : Union ,
- cparse.Enum : Enum ,
- cparse.Declarator : Declarator ,
- cparse.Typedef : Typedef ,
- cparse.AbstractDeclarator : AbstractDeclarator ,
- cparse.FieldLength : FieldLength ,
- cparse.StructDeclarator : StructDeclarator ,
- cparse.DeclarationSpecifiers : TypeSpecifiers ,
- cparse.TypeSpecifiers : TypeSpecifiers ,
- cparse.Initializer : Initializer ,
- cparse.Declaration : Declaration ,
- cparse.ParameterDeclaration : ParameterDeclaration ,
- cparse.StructDeclaration : StructDeclaration ,
- cparse.TransUnit : TransUnit ,
-}
-
-
diff --git a/tools/python-yasm/pyxelator/lexer.py b/tools/python-yasm/pyxelator/lexer.py
deleted file mode 100755
index c161219..0000000
--- a/tools/python-yasm/pyxelator/lexer.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/env python
-""" cdecl.py - parse c declarations
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-import sys
-import string
-import types
-import copy
-
-#from cparse import BasicType, Qualifier, StorageClass, Typedef, Ellipses, GCCBuiltin
-#from cparse import *
-
-import cparse as host
-
-class LexError(Exception):
- pass
-
-class Lexer(object):
- def __init__(self,s="",verbose=0,**kw):
- self.verbose = verbose
- self.lookup = {} # a map for keywords and typedefs
- for t in \
- "float double void char int".split():
- self.lookup[t] = host.BasicType( t )
- for t in \
- "register signed unsigned short long const volatile inline".split(): # inline here ???
- self.lookup[t] = host.Qualifier( t )
- for t in "extern static auto".split():
- self.lookup[t] = host.StorageClass( t )
- self.lookup['typedef'] = host.Typedef()
- #self.lookup['__inline__'] = host.GCCBuiltin('__inline__')
- #self.lookup['__extension__'] = host.Qualifier('__extension__')
- self.lookup['...'] = host.Ellipses()
- if s:
- self.lex(s)
- for key in kw.keys():
- self.__dict__[key] = kw[key]
-
- def lex(self,s):
- self.stack = None
- self.lines = s.splitlines()
- self.set_state("","",0,0)
- self.so_file = ""
- self._newline()
- self.get_token() # start
-
- def mktypedef(self,tok,node):
- if self.verbose:
- print "%s.mktypedef(%s,%s)"%(self,tok,node)
- self.lookup[ tok ] = node
-
- def rmtypedef(self,tok):
- " used in round trip testing "
-# print "# rmtypedef(%s)"%tok
- assert isinstance( self.lookup[ tok ], host.Node ) # existance
- del self.lookup[ tok ]
-
- def _get_kind(self,tok):
- #print '_get_kind(%s)'%tok,self.lookup
- try:
- return self.lookup[tok]
- #return self.lookup[tok].clone()
- except KeyError:
- if tok.startswith("__builtin"):
- node = host.GCCBuiltin(tok)
- self.lookup[tok] = node
- return node
- #elif tok in ( "__extension__", ):
- #node = GCCBuiltin(tok)
- #self.lookup[tok] = node
- #return node
- return None
-
- def _newline(self):
- while self.lno < len(self.lines):
- line = self.lines[self.lno]
- if not line or line[0] != "#":
- break
- l = line.split('"')
- assert len(l)>=2
- self.so_file = l[1]
- #self.so_lno = int( l[0].split()[1] )
- #sys.stderr.write("# %s %s: %s\n"%(so_lno,so_file,l))
- self.lno+=1
-
- def get_brace_token( self ):
- self.push_state()
- ident_chars0 = string.letters+"_"
- ident_chars1 = string.letters+string.digits+"_"
- tok, kind = "", ""
- while self.lno < len(self.lines):
- s = self.lines[self.lno]
- i=self.col
- while i < len(s):
- if s[i] not in '{}':
- i=i+1
- continue
- else:
- tok = s[i]
- kind = tok
- self.col = i+1
- break
- # keep moving
- #sys.stderr.write( "lexer ignoring '%s'\n"%s[i] )
- i=i+1
- if i==len(s):
- # nothing found
- assert tok == ""
- self.col=0
- self.lno+=1
- self._newline()
- else:
- assert tok
- break
- self.set_state(tok,kind,self.lno,self.col)
-
- def get_token(self):
- self.push_state()
- ident_chars0 = string.letters+"_"
- ident_chars1 = string.letters+string.digits+"_"
- tok, kind = "", ""
- while self.lno < len(self.lines):
- s = self.lines[self.lno]
- i=self.col
- while i < len(s):
- if s[i].isspace():
- i=i+1
- continue
- #if s[i] in ident_chars0:
- if s[i].isalpha() or s[i]=='_':
- # identifier
- j=i+1
- while j<len(s):
- if s[j] in ident_chars1:
- j=j+1
- else:
- break
- tok = s[i:j]
- self.col = j
- kind = self._get_kind(tok)
- break
- if s[i].isdigit() or \
- (i+1<len(s) and s[i] in '+-.' and s[i+1].isdigit()):
- # number literal
- is_float = s[i]=='.'
- is_hex = s[i:i+2]=='0x'
- if is_hex:
- i=i+2
- assert s[i].isdigit() or s[i] in "abcdefABCDEF", self.err_string()
- j=i+1
- while j<len(s):
- #print "lex ",repr(s[i]),is_float
- if s[j].isdigit() or (is_hex and s[j] in "abcdefABCDEF"):
- j=j+1
- elif s[j]=='.' and not is_float:
- assert not is_hex
- j=j+1
- is_float=1
- else:
- break
- tok = s[i:j]
- self.col = j
- if is_float:
- kind = float(tok)
- elif is_hex:
- kind = int(tok,16)
- else:
- kind = int(tok)
- break
- if s[i:i+3]=='...':
- # ellipses
- #sys.stderr.write( "ELLIPSES "+str(self.get_state()) )
- tok = s[i:i+3]
- kind = self._get_kind(tok)
- self.col = i+3
- break
- if s[i] in '*/{}()[]:;,=+-~.<>|&':
- tok = s[i]
- kind = tok
- self.col = i+1
- break
- if s[i] == "'":
- j = i+2
- while j<len(s) and s[j]!="'":
- j+=1
- if j==len(s):
- raise LexError( self.err_string() + "unterminated char constant" )
- tok = s[i:j+1]
- self.col = j+1
- kind = s[i:j+1]
- break
- # keep moving
- #sys.stderr.write( "lexer ignoring '%s'\n"%s[i] )
- sys.stderr.write( "lexer ignoring '%s' lno=%d\n"%(s[i],self.lno+1) )
- i=i+1
- # end while i < len(s)
- if i==len(s):
- # nothing found, go to next line
- assert tok == ""
- self.col=0
- self.lno+=1
- self._newline()
- else:
- # we got one
- assert tok
- break
- # end while self.lno < len(self.lines):
- self.set_state(tok,kind,self.lno,self.col)
-
- def err_string(self):
- "Return helpful error string :)"
- return self.lines[self.lno]+"\n"+" "*self.col+"^\n"
-
- def push_state(self):
- self.stack = self.get_state() # a short stack :)
- #self.stack.push( self.get_state() )
-
- def unget_token(self):
- assert self.stack is not None
- self.set_state(*self.stack)
- self.stack = None
-
- def set_state(self,tok,kind,lno,col):
- if self.verbose:
- print "tok,kind,lno,col = ",(tok,kind,lno,col)
- self.tok = tok
- self.kind = kind
- self.lno = lno # line
- self.col = col # column
-
- def get_state(self):
- return self.tok,self.kind,self.lno,self.col
-
- def get_file(self):
- return self.so_file
-
-###################################################################
-#
-###################################################################
-#
-
-
diff --git a/tools/python-yasm/pyxelator/node.py b/tools/python-yasm/pyxelator/node.py
deleted file mode 100755
index 5ce9043..0000000
--- a/tools/python-yasm/pyxelator/node.py
+++ /dev/null
@@ -1,301 +0,0 @@
-#!/usr/bin/env python
-""" cdecl.py - parse c declarations
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-import string
-
-
-class Node(list):
- " A node in a parse tree "
-
- def __init__(self,*items,**kw):
- list.__init__( self, items )
- self.lock1 = 0 # these two should be properties (simplifies serializing)
- self.lock2 = 0
- self.verbose = 0
- for key in kw.keys():
- self.__dict__[key] = kw[key]
-
- def __str__(self):
- attrs = []
- for item in self:
- if isinstance(item,Node):
- attrs.append( str(item) )
- else:
- attrs.append( repr(item) )
- attrs = ','.join(attrs)
- return "%s(%s)"%(self.__class__.__name__,attrs)
-
- def safe_repr( self, tank ):
- tank[ str(self) ] = None
- attrs = []
- for item in self:
- if isinstance(item,Node):
- attrs.append( item.safe_repr(tank) ) # can we use repr here ?
- else:
- attrs.append( repr(item) )
- # this is the dangerous bit:
- for key, val in self.__dict__.items():
- if isinstance(val,Node):
- if str(val) not in tank:
- attrs.append( '%s=%s'%(key,val.safe_repr(tank)) )
- else:
- attrs.append( '%s=%s'%(key,repr(val)) )
- attrs = ','.join(attrs)
- return "%s(%s)"%(self.__class__.__name__,attrs)
-
- def __repr__(self):
- #attrs = ','.join( [repr(item) for item in self] + \
- # [ '%s=%s'%(key,repr(val)) for key,val in self.__dict__.items() ] )
- #return "%s%s"%(self.__class__.__name__,tuple(attrs))
- return self.safe_repr({})
-
- def __eq__(self,other):
- if not isinstance(other,Node):
- return 0
- if len(self)!=len(other):
- return 0
- for i in range(len(self)):
- if not self[i]==other[i]:
- return 0
- return 1
-
- def __ne__(self,other):
- return not self==other
-
- def filter(self,cls):
- return [x for x in self if isinstance(x,cls)]
- #return filter( lambda x:isinstance(x,cls), self )
-
- def deepfilter(self,cls):
- " bottom-up "
- return [x for x in self.nodes() if isinstance(x,cls)]
-
- def find(self,cls):
- for x in self:
- if isinstance(x,cls):
- return x
- return None
-
- def deepfind(self,cls):
- " bottom-up isinstance search "
- for x in self:
- if isinstance(x,Node):
- if isinstance(x,cls):
- return x
- node = x.deepfind(cls)
- if node is not None:
- return node
- if isinstance(self,cls):
- return self
- return None
-
- def leaves(self):
- for i in self:
- if isinstance( i, Node ):
- for j in i.leaves():
- yield j
- else:
- yield i
-
- def nodes(self):
- " bottom-up iteration "
- for i in self:
- if isinstance( i, Node ):
- for j in i.nodes():
- yield j
- yield self
-
- def deeplen(self):
- i=0
- if not self.lock2:
- self.lock2=1
- for item in self:
- i+=1
- if isinstance(item,Node):
- i+=item.deeplen()
- self.lock2=0
- else:
- i+=1
- return i
-
- def deepstr(self,level=0,comment=False,nl='\n',indent=' '):
- if self.deeplen() < 4:
- nl = ""; indent = ""
- #else:
- #nl="\n"; indent = " "
- s = []
- if not self.lock1:
- self.lock1=1
- for item in self:
- if isinstance(item,Node):
- s.append( indent*(level+1)+item.deepstr(level+1,False,nl,indent) )
- else:
- s.append( indent*(level+1)+repr(item) )
- self.lock1=0
- else:
- for item in self:
- if isinstance(item,Node):
- s.append( indent*(level+1)+"<recursion...>" )
- else:
- s.append( indent*(level+1)+"%s"%repr(item) )
- s = "%s(%s)"%(self.__class__.__name__,nl+string.join(s,","+nl))
- if comment:
- s = '#' + s.replace('\n','\n#')
- return s
-
- def clone(self):
- items = []
- for item in self:
- if isinstance(item,Node):
- item = item.clone()
- items.append(item)
- # we skip any attributes...
- return self.__class__(*items)
-
- def fastclone(self):
- # XX is it faster ???
- #print "clone"
- nodes = [self]
- idxs = [0]
- itemss = [ [] ]
- while nodes:
- assert len(nodes)==len(idxs)==len(itemss)
- node = nodes[-1]
- items = itemss[-1]
- assert idxs[-1] == len(items)
- while idxs[-1]==len(node):
- # pop
- _node = node.__class__( *items )
- _node.__dict__.update( node.__dict__ )
- nodes.pop(-1)
- idxs.pop(-1)
- itemss.pop(-1)
- if not nodes:
- #for node0 in self.nodes():
- #for node1 in _node.nodes():
- #assert node0 is not node1
- #assert _node == self
- return _node # Done !!
- node = nodes[-1]
- items = itemss[-1]
- items.append(_node) # set
- idxs[-1] += 1
- assert idxs[-1] == len(items)
- #assert idxs[-1] < len(node), str( (node,nodes,idxs,itemss) )
-
- _node = node[ idxs[-1] ]
- # while idxs[-1]<len(node):
- if isinstance(_node,Node):
- # push
- nodes.append( _node )
- idxs.append( 0 )
- itemss.append( [] )
- else:
- # next
- items.append(_node)
- idxs[-1] += 1
- assert idxs[-1] == len(items)
-
- def expose(self,cls):
- ' expose children of any <cls> instance '
- # children first
- for x in self:
- if isinstance(x,Node):
- x.expose(cls)
- # now the tricky bit
- i=0
- while i < len(self):
- if isinstance(self[i],cls):
- node=self.pop(i)
- for x in node:
- assert not isinstance(x,cls)
- # pass on some attributes
- if hasattr(node,'lines') and not hasattr(x,'lines'):
- x.lines=node.lines
- if hasattr(node,'file') and not hasattr(x,'file'):
- x.file=node.file
- self.insert(i,x) # expose
- i=i+1
- assert i<=len(self)
- else:
- i=i+1
-
- def get_parent( self, item ): # XX 25% CPU time here XX
- assert self != item
- if item in self:
- return self
- for child in self:
- if isinstance(child, Node):
- parent = child.get_parent(item)
- if parent is not None:
- return parent
- return None
-
- def expose_node( self, item ):
- assert self != item
- parent = self.get_parent(item)
- idx = parent.index( item )
- parent[idx:idx+1] = item[:]
-
- def delete(self,cls):
- ' delete any <cls> subtree '
- for x in self:
- if isinstance(x,Node):
- x.delete(cls)
- # now the tricky bit
- i=0
- while i < len(self):
- if isinstance(self[i],cls):
- self.pop(i)
- else:
- i=i+1
-
- def deeprm(self,item):
- ' remove any items matching <item> '
- for x in self:
- if isinstance(x,Node):
- x.deeprm(item)
- # now the tricky bit
- i=0
- while i < len(self):
- if self[i] == item:
- self.pop(i)
- else:
- i=i+1
-
- def idem(self,cls):
- " <cls> is made idempotent "
- # children first
- for x in self:
- if isinstance(x,Node):
- x.idem(cls)
- if isinstance(self,cls):
- # now the tricky bit
- i=0
- while i < len(self):
- if isinstance(self[i],cls):
- node = self.pop(i)
- for x in node:
- assert not isinstance(x,cls)
- self.insert(i,x) # idempotent
- i=i+1
- assert i<=len(self)
- else:
- i=i+1
-
-if __name__=="__main__":
- node = Node( 'a', Node(1,2), Node(Node(Node(),1)) )
-
- print node
- print node.clone()
-
-
-
-
diff --git a/tools/python-yasm/pyxelator/parse_core.py b/tools/python-yasm/pyxelator/parse_core.py
deleted file mode 100755
index 84fb894..0000000
--- a/tools/python-yasm/pyxelator/parse_core.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/env python
-""" cdecl.py - parse c declarations
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-import sys
-
-
-class Symbols(object):
- def __init__(self,parent=None,verbose=False):
- self.verbose = verbose
- self.parent=parent # are we a nested namespace?
- self.lookup = {} # identifiers
- self.tags = {} # struct, union, enum tags
-
- def __str__(self):
- return "Symbols(%s,%s)"%(self.lookup,self.tags)
-
- def __getitem__(self,key):
- try:
- item = self.lookup[key]
- except KeyError:
- item = None
- #if self.parent is not None:
- #item = self.parent[item]
- ## self[key] = item # cache
- #if self.verbose: print "%s.get('%s')='%s'"%(self,key,item)
- return item
-
- def __setitem__(self,key,val):
- #if self.verbose: print "%s.set('%s','%s')"%(self,key,val)
- assert val is not None
- self.lookup[key] = val
-
- def set_tag(self,key,val):
- #if self.verbose: print "%s.set_tag(%s,%s)"%(self,key,val)
- assert len(key)
- self.tags[key] = val
-
- def deep_get_tag(self,key):
- try:
- item = self.tags[key]
- except KeyError:
- item = None
- if self.parent is not None:
- item = self.parent.deep_get_tag(key)
- #if self.verbose: print "%s.get_tag(%s)=%s"%(self,key,item)
- return item
-
- def get_tag(self,key):
- try:
- item = self.tags[key]
- except KeyError:
- item = None
- #if self.verbose: print "%s.get_tag(%s)=%s"%(self,key,item)
- return item
-
-###################################################################
-#
-###################################################################
-#
-
-
-class ParseError(Exception):
- def __init__(self,*e):
- self.e = e
-
- def __str__(self):
- return "".join(map(str,self.e))
-
-
-class Parser(object):
- def parse_error(self,lexer,reason="?",*blah):
- sys.stderr.write( "%s.parse_error()\n"%self.deepstr() )
- sys.stderr.write( "at line %s: %s\n"%(lexer.lno+1,reason) )
- sys.stderr.write( lexer.err_string() )
- raise ParseError(reason,*blah)
-
- def expected_error(self,lexer,*l):
- self.parse_error( lexer, "expected %s, got '%s'"\
- %(" or ".join(map(repr,l)),lexer.tok))
-
- def consume(self,lexer,tok):
- if lexer.tok != tok:
- self.expected_error(lexer, tok)
- lexer.get_token()
-
- def parse_enter(self,lexer):
- #return
- self.start_lno=lexer.lno
- self.file=lexer.so_file
-
- def parse_leave(self,lexer):
- #return
- self.lines = lexer.lines[self.start_lno:max(lexer.lno,self.start_lno+1)]
-
-###################################################################
-#
-###################################################################
-#
-
diff --git a/tools/python-yasm/pyxelator/work_unit.py b/tools/python-yasm/pyxelator/work_unit.py
deleted file mode 100755
index 0d888f8..0000000
--- a/tools/python-yasm/pyxelator/work_unit.py
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/env python
-
-"""
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-
-import sys
-import os
-
-import cparse
-import ir
-
-class WorkUnit(object):
- def __init__(self, files, modname, filename,
- std=False, strip=False, mark_cb=None,
- extradefs="", use_header=None, CC="gcc", CPP="gcc -E",
- CPPFLAGS=""):
- self.files = tuple(files)
- self.modname = modname
- self.filename = filename
- self.CPPFLAGS = CPPFLAGS
- self.CPP = CPP
- if CC == 'g++':
- self.CPPFLAGS += " -D__cplusplus"
- self.std = std
- self.strip = strip
- self.mark_cb = mark_cb
- self.node = None
- self.extradefs = extradefs
- self.CC = CC
- self.use_header = use_header
-
- def mkheader( self ):
- if self.use_header:
- return self.use_header
- tmpname = str(abs(hash( (self.files,self.CPPFLAGS) )))
- name = '.tmp/%s' % tmpname
- ifile = open( name+'.h', "w" )
- ifile.write( """
-#define __attribute__(...)
-#define __const const
-#define __restrict
-#define __extension__
-#define __asm__(...)
-#define __asm(...)
-#define __inline__
-#define __inline
-""" )
- for filename in self.files:
- if self.std:
- line = '#include <%s>\n'%filename
- else:
- line = '#include "%s"\n'%filename
- ifile.write( line )
- print line,
- ifile.close()
- cmd = '%s %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.E')
- sys.stderr.write( "# %s\n" % cmd )
- status = os.system( cmd )
- assert status == 0, "command failed: %s"%cmd
- assert open(name+'.E').read().count('\n') > 10, "failed to run preprocessor"
- cmd = '%s -dM %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.dM')
- sys.stderr.write( "# %s\n" % cmd )
- status = os.system( cmd )
- assert status == 0, "command failed: %s"%cmd
- assert open(name+'.dM').read().count('\n') > 10, "failed to run preprocessor with -dM"
- return name
-
- def parse(self, verbose=False):
- sys.stderr.write( "# parse %s\n" % str(self.files) )
- name = self.mkheader()
- # read macros
- f = open(name+'.dM')
- macros = {}
- for line in f.readlines():
- if line:
- macro = line.split()[1]
- if macro.count('('):
- macro = macro[:macro.index('(')]
- macros[macro] = None
- #keys = macros.keys()
- #keys.sort()
- #for key in keys:
- #print key
- self.macros = macros
- # parse preprocessed code
- f = open(name+'.E')
- s = f.read() + self.extradefs
- self.node = cparse.TransUnit(verbose = verbose)
- sys.stderr.write( "# parsing %s lines\n" % s.count('\n') )
- self.node.parse( s )
- if self.strip:
- self.node.strip(self.files)
-
- def transform(self, verbose=False, test_parse=False, test_types=False):
- sys.stderr.write( "# processing...\n" )
- self.node = ir.TransUnit( self.node )
- self.node.transform(verbose, test_parse, test_types)
- #self.node[0].psource()
- if self.mark_cb is not None:
- self.node.mark(self.mark_cb,verbose=False)
-
- def output( self, func_cb = None ):
- sys.stderr.write( "# pyxstr...\n" )
- decls = self.node.pyx_decls(self.files, self.modname, macros = self.macros, func_cb = func_cb, names={}, cprefix="" )
-
- name = self.filename
- assert name.endswith(".pyx")
-
- pxi = name[:-3]+'pxi'
- file = open( pxi, "w" )
- file.write(decls)
- sys.stderr.write( "# wrote %s, %d lines\n" % (pxi,decls.count('\n')) )
-
- def pprint(self):
- for decl in self.node:
- #decl.psource()
- #cstr = decl.cstr()
- #cstr = cstr.replace( '\n', '\n# ' )
- print
- #print '#', cstr
- print decl.deepstr()
-
-def file_exists(path):
- try:
- os.stat(path)
- return True
- except OSError:
- return False
-
-if sys.platform.count('darwin'):
- shared_ext = '.dylib'
-else:
- shared_ext = '.so'
-
-def get_syms(libs, libdirs):
- # XX write interface to objdump -t XX
- libnames = []
- for lib in libs:
- for ext in shared_ext,'.a':
- libname = 'lib'+lib+ext
- for libdir in libdirs:
- path = libdir+'/'+libname
- if file_exists(path):
- libnames.append(path)
- break
- #else:
- #print "cannot find %s lib as %s in %s" % ( lib, libname, libdir )
- print 'libnames:', libnames
- syms = {}
- accept = [ ' %s '%c for c in 'TVWBCDGRS' ]
- #f = open('syms.out','w')
- for libname in libnames:
- fin, fout = os.popen2( 'nm %s' % libname )
- for line in fout.readlines():
- for acc in accept:
- if line.count(acc):
- left, right = line.split(acc)
- sym = right.strip()
- if sys.platform.count('darwin'):
- if sym[0] == '_':
- sym = sym[1:] # remove underscore prefix
- if sym.endswith('.eh'):
- sym = sym[:-len('.eh')]
- syms[sym] = None
- #f.write( '%s: %s %s\n' % (sym,line[:-1],libname) )
- break
- return syms
-
-
-
diff --git a/tools/python-yasm/pyxelator/wrap_yasm.py b/tools/python-yasm/pyxelator/wrap_yasm.py
deleted file mode 100755
index 58553ab..0000000
--- a/tools/python-yasm/pyxelator/wrap_yasm.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-
-"""
-
-(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
-Released under GNU LGPL license.
-
-version 0.xx
-
-"""
-
-
-import sys
-import os
-
-from work_unit import WorkUnit, get_syms
-import ir
-
-
-def mk_tao(CPPFLAGS = "", CPP = "gcc -E", modname = '_yasm', oname = None, YASM_DIR = ".", **options):
- if oname is None:
- oname = modname+'.pyx'
- CPPFLAGS += " -I"+YASM_DIR
- CPPFLAGS += " -DYASM_PYXELATOR"
- CPPFLAGS += " -DYASM_LIB_INTERNAL"
- CPPFLAGS += " -DYASM_BC_INTERNAL"
- CPPFLAGS += " -DYASM_EXPR_INTERNAL"
- files = [ 'libyasm.h', 'libyasm/assocdat.h', 'libyasm/bitvect.h' ]
-
- syms = get_syms( ['yasm'], [YASM_DIR] )
- def cb(trans_unit, node, *args):
- name, file = node.name, node.file
- return True
- return name in syms
- extradefs = ""
- unit = WorkUnit(files,modname,oname,False,mark_cb=cb,extradefs=extradefs,
- CPPFLAGS=CPPFLAGS, CPP=CPP, **options)
-
-
- unit.parse( False )
- unit.transform(verbose=False, test_parse=False, test_types=False)
- unit.output()
-
-def main():
- options = {}
- for i,arg in enumerate(sys.argv[1:]):
- if arg.count('='):
- key,val = arg.split('=', 1)
- options[key]=val
- mk_tao(**options)
-
-if __name__=="__main__":
- main()
-
-
-
-
diff --git a/tools/python-yasm/setup.py b/tools/python-yasm/setup.py
deleted file mode 100644
index 60e2364..0000000
--- a/tools/python-yasm/setup.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#! /usr/bin/env python
-# Build Python extension with configuration file input
-#
-# Copyright (C) 2006 Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-from distutils.core import setup
-from distutils.extension import Extension
-from Pyrex.Distutils import build_ext
-from os.path import basename, join, exists
-
-def ReadSetup(filename):
- """ReadSetup goes through filename and parses out the values stored
- in the file. Values need to be stored in a
- \"key=value format\""""
- return dict(line.split('=', 1) for line in open(filename))
-
-def ParseCPPFlags(flags):
- """parse the CPPFlags macro"""
- incl_dir = [x[2:] for x in flags.split() if x.startswith("-I")]
- cppflags = [x for x in flags.split() if not x.startswith("-I")]
- cppflags.append("-DYASM_LIB_INTERNAL")
- cppflags.append("-DYASM_BC_INTERNAL")
- cppflags.append("-DYASM_EXPR_INTERNAL")
- return (incl_dir, cppflags)
-
-def ParseSources(src, srcdir):
- """parse the Sources macro"""
- # do the dance of detecting if the source file is in the current
- # directory, and if it's not, prepend srcdir
- sources = []
- for tok in src.split():
- if tok.endswith(".c"):
- fn = tok
- elif tok.endswith(".y"):
- fn = basename(tok)[:-2] + ".c"
- else:
- continue
- if not exists(fn):
- fn = join(srcdir, fn)
- sources.append(fn)
-
- return sources
-
-def RunSetup(incldir, cppflags, sources):
- setup(
- name='yasm',
- version='0.0',
- description='Python bindings for Yasm',
- author='Michael Urman, Peter Johnson',
- url='http://www.tortall.net/projects/yasm',
- ext_modules=[
- Extension('yasm',
- sources=sources,
- extra_compile_args=cppflags,
- include_dirs=incldir,
- library_dirs=['.'],
- libraries=['yasm'],
- ),
- ],
- cmdclass = dict(build_ext=build_ext),
- )
-
-if __name__ == "__main__":
- opts = ReadSetup("python-setup.txt")
- incldir, cppflags = ParseCPPFlags(opts["includes"])
- sources = ParseSources(opts["sources"], opts["srcdir"].strip())
- sources.append('yasm_python.c')
- if opts["gcc"].strip() == "yes":
- cppflags.append('-w')
- RunSetup(incldir, cppflags, sources)
-
diff --git a/tools/python-yasm/symrec.pxi b/tools/python-yasm/symrec.pxi
deleted file mode 100644
index d91fe7f..0000000
--- a/tools/python-yasm/symrec.pxi
+++ /dev/null
@@ -1,285 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for symrec.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef class Symbol:
- cdef yasm_symrec *sym
-
- def __new__(self, symrec):
- self.sym = NULL
- if PyCObject_Check(symrec):
- self.sym = <yasm_symrec *>__get_voidp(symrec, Symbol)
- else:
- raise NotImplementedError
-
- # no deref or destroy necessary
-
- property name:
- def __get__(self): return yasm_symrec_get_name(self.sym)
-
- property status:
- def __get__(self):
- cdef yasm_sym_status status
- s = set()
- status = yasm_symrec_get_status(self.sym)
- if <int>status & <int>SYM_USED: s.add('used')
- if <int>status & <int>SYM_DEFINED: s.add('defined')
- if <int>status & <int>SYM_VALUED: s.add('valued')
- return s
-
- property in_table:
- def __get__(self):
- return bool(<int>yasm_symrec_get_status(self.sym) &
- <int>SYM_NOTINTABLE)
-
- property visibility:
- def __get__(self):
- cdef yasm_sym_vis vis
- s = set()
- vis = yasm_symrec_get_visibility(self.sym)
- if <int>vis & <int>YASM_SYM_GLOBAL: s.add('global')
- if <int>vis & <int>YASM_SYM_COMMON: s.add('common')
- if <int>vis & <int>YASM_SYM_EXTERN: s.add('extern')
- if <int>vis & <int>YASM_SYM_DLOCAL: s.add('dlocal')
- return s
-
- property equ:
- def __get__(self):
- cdef yasm_expr *e
- e = yasm_symrec_get_equ(self.sym)
- if not e:
- raise AttributeError("not an EQU")
- return __make_expression(yasm_expr_copy(e))
-
- property label:
- def __get__(self):
- cdef yasm_symrec_get_label_bytecodep bc
- if yasm_symrec_get_label(self.sym, &bc):
- return None #Bytecode(bc)
- else:
- raise AttributeError("not a label or not defined")
-
- property is_special:
- def __get__(self): return bool(yasm_symrec_is_special(self.sym))
-
- property is_curpos:
- def __get__(self): return bool(yasm_symrec_is_curpos(self.sym))
-
- def get_data(self): pass # TODO
- #return <object>(yasm_symrec_get_data(self.sym, PyYasmAssocData))
-
- def set_data(self, data): pass # TODO
- #yasm_symrec_set_data(self.sym, PyYasmAssocData, data)
-
-#
-# Use associated data mechanism to keep Symbol reference paired with symrec.
-#
-
-cdef void __python_symrec_cb_destroy(void *data):
- Py_DECREF(<object>data)
-cdef void __python_symrec_cb_print(void *data, FILE *f, int indent_level):
- pass
-__python_symrec_cb = __assoc_data_callback(
- PyCObject_FromVoidPtr(&__python_symrec_cb_destroy, NULL),
- PyCObject_FromVoidPtr(&__python_symrec_cb_print, NULL))
-
-cdef object __make_symbol(yasm_symrec *symrec):
- cdef void *data
- __error_check()
- data = yasm_symrec_get_data(symrec,
- (<__assoc_data_callback>__python_symrec_cb).cb)
- if data != NULL:
- return <object>data
- symbol = Symbol(__pass_voidp(symrec, Symbol))
- yasm_symrec_add_data(symrec,
- (<__assoc_data_callback>__python_symrec_cb).cb,
- <void *>symbol)
- Py_INCREF(symbol) # We're keeping a reference on the C side!
- return symbol
-
-cdef class Bytecode
-cdef class SymbolTable
-
-cdef class SymbolTableKeyIterator:
- cdef yasm_symtab_iter *iter
-
- def __new__(self, symtab):
- if not isinstance(symtab, SymbolTable):
- raise TypeError
- self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
-
- def __iter__(self):
- return self
-
- def __next__(self):
- if self.iter == NULL:
- raise StopIteration
- rv = yasm_symrec_get_name(yasm_symtab_iter_value(self.iter))
- self.iter = yasm_symtab_next(self.iter)
- return rv
-
-cdef class SymbolTableValueIterator:
- cdef yasm_symtab_iter *iter
-
- def __new__(self, symtab):
- if not isinstance(symtab, SymbolTable):
- raise TypeError
- self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
-
- def __iter__(self):
- return self
-
- def __next__(self):
- if self.iter == NULL:
- raise StopIteration
- rv = __make_symbol(yasm_symtab_iter_value(self.iter))
- self.iter = yasm_symtab_next(self.iter)
- return rv
-
-cdef class SymbolTableItemIterator:
- cdef yasm_symtab_iter *iter
-
- def __new__(self, symtab):
- if not isinstance(symtab, SymbolTable):
- raise TypeError
- self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
-
- def __iter__(self):
- return self
-
- def __next__(self):
- cdef yasm_symrec *sym
- if self.iter == NULL:
- raise StopIteration
- sym = yasm_symtab_iter_value(self.iter)
- rv = (yasm_symrec_get_name(sym), __make_symbol(sym))
- self.iter = yasm_symtab_next(self.iter)
- return rv
-
-cdef int __parse_vis(vis) except -1:
- if not vis or vis == 'local': return YASM_SYM_LOCAL
- if vis == 'global': return YASM_SYM_GLOBAL
- if vis == 'common': return YASM_SYM_COMMON
- if vis == 'extern': return YASM_SYM_EXTERN
- if vis == 'dlocal': return YASM_SYM_DLOCAL
- msg = "bad visibility value %r" % vis
- PyErr_SetString(ValueError, msg)
- return -1
-
-cdef class SymbolTable:
- cdef yasm_symtab *symtab
-
- def __new__(self):
- self.symtab = yasm_symtab_create()
-
- def __dealloc__(self):
- if self.symtab != NULL: yasm_symtab_destroy(self.symtab)
-
- def use(self, name, line):
- return __make_symbol(yasm_symtab_use(self.symtab, name, line))
-
- def define_equ(self, name, expr, line):
- if not isinstance(expr, Expression):
- raise TypeError
- return __make_symbol(yasm_symtab_define_equ(self.symtab, name,
- yasm_expr_copy((<Expression>expr).expr), line))
-
- def define_label(self, name, precbc, in_table, line):
- if not isinstance(precbc, Bytecode):
- raise TypeError
- return __make_symbol(yasm_symtab_define_label(self.symtab, name,
- (<Bytecode>precbc).bc, in_table, line))
-
- def define_special(self, name, vis):
- return __make_symbol(
- yasm_symtab_define_special(self.symtab, name,
- <yasm_sym_vis>__parse_vis(vis)))
-
- def declare(self, name, vis, line):
- return __make_symbol(
- yasm_symtab_declare(self.symtab, name,
- <yasm_sym_vis>__parse_vis(vis), line))
-
- #
- # Methods to make SymbolTable behave like a dictionary of Symbols.
- #
-
- def __getitem__(self, key):
- cdef yasm_symrec *symrec
- symrec = yasm_symtab_get(self.symtab, key)
- if symrec == NULL:
- raise KeyError
- return __make_symbol(symrec)
-
- def __contains__(self, key):
- cdef yasm_symrec *symrec
- symrec = yasm_symtab_get(self.symtab, key)
- return symrec != NULL
-
- def keys(self):
- cdef yasm_symtab_iter *iter
- l = []
- iter = yasm_symtab_first(self.symtab)
- while iter != NULL:
- l.append(yasm_symrec_get_name(yasm_symtab_iter_value(iter)))
- iter = yasm_symtab_next(iter)
- return l
-
- def values(self):
- cdef yasm_symtab_iter *iter
- l = []
- iter = yasm_symtab_first(self.symtab)
- while iter != NULL:
- l.append(__make_symbol(yasm_symtab_iter_value(iter)))
- iter = yasm_symtab_next(iter)
- return l
-
- def items(self):
- cdef yasm_symtab_iter *iter
- cdef yasm_symrec *sym
- l = []
- iter = yasm_symtab_first(self.symtab)
- while iter != NULL:
- sym = yasm_symtab_iter_value(iter)
- l.append((yasm_symrec_get_name(sym), __make_symbol(sym)))
- iter = yasm_symtab_next(iter)
- return l
-
- def has_key(self, key):
- cdef yasm_symrec *symrec
- symrec = yasm_symtab_get(self.symtab, key)
- return symrec != NULL
-
- def get(self, key, x):
- cdef yasm_symrec *symrec
- symrec = yasm_symtab_get(self.symtab, key)
- if symrec == NULL:
- return x
- return __make_symbol(symrec)
-
- def iterkeys(self): return SymbolTableKeyIterator(self)
- def itervalues(self): return SymbolTableValueIterator(self)
- def iteritems(self): return SymbolTableItemIterator(self)
- def __iter__(self): return SymbolTableKeyIterator(self)
-
diff --git a/tools/python-yasm/tests/Makefile.inc b/tools/python-yasm/tests/Makefile.inc
deleted file mode 100644
index 50c499d..0000000
--- a/tools/python-yasm/tests/Makefile.inc
+++ /dev/null
@@ -1,15 +0,0 @@
-# $Id$
-
-EXTRA_DIST += tools/python-yasm/tests/python_test.sh
-EXTRA_DIST += tools/python-yasm/tests/__init__.py
-EXTRA_DIST += tools/python-yasm/tests/test_bytecode.py
-EXTRA_DIST += tools/python-yasm/tests/test_expr.py
-EXTRA_DIST += tools/python-yasm/tests/test_intnum.py
-EXTRA_DIST += tools/python-yasm/tests/test_symrec.py
-
-if HAVE_PYTHON_BINDINGS
-
-TESTS_ENVIRONMENT += PYTHON=${PYTHON}
-TESTS += tools/python-yasm/tests/python_test.sh
-
-endif
diff --git a/tools/python-yasm/tests/__init__.py b/tools/python-yasm/tests/__init__.py
deleted file mode 100644
index 6d608f2..0000000
--- a/tools/python-yasm/tests/__init__.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Test wrapper from Quod Libet
-# http://www.sacredchao.net/quodlibet/
-# $Id$
-import unittest, sys
-suites = []
-add = registerCase = suites.append
-from unittest import TestCase
-
-class Mock(object):
- # A generic mocking object.
- def __init__(self, **kwargs): self.__dict__.update(kwargs)
-
-import test_intnum
-import test_symrec
-import test_bytecode
-import test_expr
-
-class Result(unittest.TestResult):
-
- separator1 = '=' * 70
- separator2 = '-' * 70
-
- def addSuccess(self, test):
- unittest.TestResult.addSuccess(self, test)
- sys.stdout.write('.')
-
- def addError(self, test, err):
- unittest.TestResult.addError(self, test, err)
- sys.stdout.write('E')
-
- def addFailure(self, test, err):
- unittest.TestResult.addFailure(self, test, err)
- sys.stdout.write('F')
-
- def printErrors(self):
- succ = self.testsRun - (len(self.errors) + len(self.failures))
- v = "%3d" % succ
- count = 50 - self.testsRun
- sys.stdout.write((" " * count) + v + "\n")
- self.printErrorList('ERROR', self.errors)
- self.printErrorList('FAIL', self.failures)
-
- def printErrorList(self, flavour, errors):
- for test, err in errors:
- sys.stdout.write(self.separator1 + "\n")
- sys.stdout.write("%s: %s\n" % (flavour, str(test)))
- sys.stdout.write(self.separator2 + "\n")
- sys.stdout.write("%s\n" % err)
-
-class Runner:
- def run(self, test):
- suite = unittest.makeSuite(test)
- pref = '%s (%d): ' % (test.__name__, len(suite._tests))
- print pref + " " * (25 - len(pref)),
- result = Result()
- suite(result)
- result.printErrors()
- return bool(result.failures + result.errors)
-
-def unit(run = []):
- runner = Runner()
- failures = False
- for test in suites:
- if not run or test.__name__ in run:
- failures |= runner.run(test)
- return failures
-
-if __name__ == "__main__":
- raise SystemExit(unit(sys.argv[1:]))
-
diff --git a/tools/python-yasm/tests/python_test.sh b/tools/python-yasm/tests/python_test.sh
deleted file mode 100755
index 1f3896d..0000000
--- a/tools/python-yasm/tests/python_test.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# Based on _sanity.sh from Quod Libet
-# http://www.sacredchao.net/quodlibet/
-# $Id$
-
-set -e
-
-test -n "${srcdir}" || srcdir=.
-test -n "${PYTHON}" || PYTHON=python
-
-if test "$1" = "--help" -o "$1" = "-h"; then
- echo "Usage: $0 --sanity | [TestName] ..."
- exit 0
-elif [ "$1" = "--sanity" ]; then
- echo "Running static sanity checks."
- grep "except None:" ${srcdir}/tools/python-yasm/tests/*.py
-else
- ${PYTHON} -c "import sys; import glob; sys.path.insert(0, '${srcdir}/tools/python-yasm'); sys.path.insert(0, glob.glob('build/lib.*')[0]); import tests; raise SystemExit(tests.unit('$*'.split()))"
-fi
-
diff --git a/tools/python-yasm/tests/test_bytecode.py b/tools/python-yasm/tests/test_bytecode.py
deleted file mode 100644
index fb6c2a2..0000000
--- a/tools/python-yasm/tests/test_bytecode.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# $Id$
-from tests import TestCase, add
-from yasm import Bytecode, Expression
-
diff --git a/tools/python-yasm/tests/test_expr.py b/tools/python-yasm/tests/test_expr.py
deleted file mode 100644
index 1fb930d..0000000
--- a/tools/python-yasm/tests/test_expr.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# $Id$
-from tests import TestCase, add
-from yasm import Expression
-import operator
-
-class TExpression(TestCase):
- def test_create(self):
- e1 = Expression(operator.add, 1, 2)
- e2 = Expression('+', 1, 2)
-
- self.assertEquals(e1.get_intnum(), e1.get_intnum())
-
- def test_extract(self):
- e1 = Expression('/', 15, 5)
- self.assertEquals(e1.get_intnum(), 3)
- self.assertRaises(ValueError, e1.extract_segoff)
- self.assertRaises(ValueError, e1.extract_wrt)
-
-add(TExpression)
diff --git a/tools/python-yasm/tests/test_intnum.py b/tools/python-yasm/tests/test_intnum.py
deleted file mode 100644
index 65e09ef..0000000
--- a/tools/python-yasm/tests/test_intnum.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# $Id$
-from tests import TestCase, add
-from yasm import IntNum
-
-class TIntNum(TestCase):
- legal_values = [
- 0, 1, -1, 2, -2, 17, -17,
- 2**31-1, -2**31, 2**31, 2**32-1, -2**32,
- 2**63-1, -2**63-1, 2**63, 2**64, -2**64,
- 2**127-1, -2**127
- ]
- overflow_values = [
- 2**127, -2**127-1
- ]
-
- def test_to_from(self):
- for i in self.legal_values:
- self.assertEquals(i, int(IntNum(i)))
- self.assertEquals(i, long(IntNum(i)))
-
- def test_overflow(self):
- for i in self.overflow_values:
- self.assertRaises(OverflowError, IntNum, i)
-
- str_values = [
- "0", "00000", "1234", "87654321", "010101010", "FADCBEEF"
- ]
- base_values = [2, 8, 10, 12, 16, None, "nasm", "foo"]
-
- def test_from_str(self):
- pass
-
- def test_from_str_base(self):
- pass
-
- def test_exceptions(self):
- self.assertRaises(ZeroDivisionError, IntNum(1).__div__, 0)
-
- IntNum(1) / 1 # make sure the above error is cleared
-
- try: IntNum(1) / 0
- except ZeroDivisionError, err:
- self.assertEquals('divide by zero', str(err))
-
- def test_xor(self):
- a = IntNum(-234)
- b = IntNum(432)
- c = a ^ b
- self.assertEquals(a, -234)
- self.assertEquals(b, 432)
- self.assertEquals(c, -234 ^ 432)
-
- def test_ixor(self):
- a = IntNum(-234)
- b = IntNum(432)
- a ^= b; b ^= a; a ^= b
- self.assertEquals(a, 432)
- self.assertEquals(b, -234)
-
- def test_cmp(self):
- a = IntNum(-1)
- b = IntNum(0)
- c = IntNum(1)
- self.assert_(a < b < c)
- self.assert_(a <= b <= c)
- self.assert_(c >= b >= a)
- self.assert_(c > b > a)
- self.assert_(a != b != c)
-
- def test_abs(self):
- a = IntNum(-1)
- b = IntNum(0)
- c = IntNum(1)
-
- self.assertEquals(abs(a), abs(c))
- self.assertEquals(abs(a) - abs(c), abs(b))
-
-add(TIntNum)
diff --git a/tools/python-yasm/tests/test_symrec.py b/tools/python-yasm/tests/test_symrec.py
deleted file mode 100644
index a228eeb..0000000
--- a/tools/python-yasm/tests/test_symrec.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# $Id$
-from tests import TestCase, add
-from yasm import SymbolTable, Expression, YasmError
-
-class TSymbolTable(TestCase):
- def setUp(self):
- self.symtab = SymbolTable()
-
- def test_keys(self):
- self.assertEquals(len(self.symtab.keys()), 0)
- self.symtab.declare("foo", None, 0)
- keys = self.symtab.keys()
- self.assertEquals(len(keys), 1)
- self.assertEquals(keys[0], "foo")
-
- def test_contains(self):
- self.assert_("foo" not in self.symtab)
- self.symtab.declare("foo", None, 0)
- self.assert_("foo" in self.symtab)
-
- def test_exception(self):
- expr = Expression('+', 1, 2)
- self.symtab.define_equ("foo", expr, 0)
- self.assertRaises(YasmError, self.symtab.define_equ, "foo", expr, 0)
- self.symtab.define_equ("bar", expr, 0) # cleared
- self.assertRaises(YasmError, self.symtab.define_special, "bar",
- 'global')
-
- def test_iters(self):
- tab = self.symtab
- tab.declare("foo", None, 0)
- tab.declare("bar", None, 0)
- tab.declare("baz", None, 0)
-
- # while ordering is not known, it must be consistent
- self.assertEquals(list(tab.keys()), list(tab.iterkeys()))
- self.assertEquals(list(tab.values()), list(tab.itervalues()))
- self.assertEquals(list(tab.items()), list(tab.iteritems()))
- self.assertEquals(list(tab.iteritems()), zip(tab.keys(), tab.values()))
-
-add(TSymbolTable)
-
-class TSymbolAttr(TestCase):
- def setUp(self):
- self.symtab = SymbolTable()
- self.declsym = self.symtab.declare("foo", None, 0)
-
- def test_visibility(self):
- sym = self.symtab.declare("local1", None, 0)
- self.assertEquals(sym.visibility, set())
- sym = self.symtab.declare("local2", '', 0)
- self.assertEquals(sym.visibility, set())
- sym = self.symtab.declare("local3", 'local', 0)
- self.assertEquals(sym.visibility, set())
- sym = self.symtab.declare("global", 'global', 0)
- self.assertEquals(sym.visibility, set(['global']))
- sym = self.symtab.declare("common", 'common', 0)
- self.assertEquals(sym.visibility, set(['common']))
- sym = self.symtab.declare("extern", 'extern', 0)
- self.assertEquals(sym.visibility, set(['extern']))
- sym = self.symtab.declare("dlocal", 'dlocal', 0)
- self.assertEquals(sym.visibility, set(['dlocal']))
-
- self.assertRaises(ValueError,
- lambda: self.symtab.declare("extern2", 'foo', 0))
- def test_name(self):
- self.assertEquals(self.declsym.name, "foo")
-
- def test_equ(self):
- self.assertRaises(AttributeError, lambda: self.declsym.equ)
-
- def test_label(self):
- self.assertRaises(AttributeError, lambda: self.declsym.label)
-
- def test_is_special(self):
- self.assertEquals(self.declsym.is_special, False)
-
- def test_is_curpos(self):
- self.assertEquals(self.declsym.is_curpos, False)
-
-add(TSymbolAttr)
diff --git a/tools/python-yasm/value.pxi b/tools/python-yasm/value.pxi
deleted file mode 100644
index f2328dd..0000000
--- a/tools/python-yasm/value.pxi
+++ /dev/null
@@ -1,56 +0,0 @@
-# Python bindings for Yasm: Pyrex input file for value.h
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-cdef class Value:
- cdef yasm_value value
- def __new__(self, value=None, size=None):
- cdef unsigned int sz
- if size is None:
- sz = 0
- else:
- sz = size;
-
- yasm_value_initialize(&self.value, NULL, sz)
- if value is None:
- pass
- elif isinstance(value, Expression):
- yasm_value_initialize(&self.value,
- yasm_expr_copy((<Expression>value).expr), sz)
- elif isinstance(value, Symbol):
- yasm_value_init_sym(&self.value, (<Symbol>value).sym, sz)
- else:
- raise TypeError("Invalid value type '%s'" % type(value))
-
- def __dealloc__(self):
- yasm_value_delete(&self.value)
-
- def finalize(self, precbc=None):
- if precbc is None:
- return yasm_value_finalize(&self.value, NULL)
- elif isinstance(precbc, Bytecode):
- return yasm_value_finalize(&self.value, (<Bytecode>precbc).bc)
- else:
- raise TypeError("Invalid precbc type '%s'" % type(precbc))
-
diff --git a/tools/python-yasm/yasm.pyx b/tools/python-yasm/yasm.pyx
deleted file mode 100644
index f9c6ee4..0000000
--- a/tools/python-yasm/yasm.pyx
+++ /dev/null
@@ -1,137 +0,0 @@
-# Python bindings for Yasm: Main Pyrex input file
-#
-# Copyright (C) 2006 Michael Urman, Peter Johnson
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-"""Interface to the Yasm library.
-
-The Yasm library (aka libyasm) provides the core functionality of the Yasm
-assembler. Classes in this library provide for manipulation of machine
-instructions and object file constructs such as symbol tables and sections.
-
-Expression objects encapsulate complex expressions containing registers,
-symbols, and operations such as SEG.
-
-Bytecode objects encapsulate data or code objects such as data, reserve,
-align, or instructions.
-
-Section objects encapsulate an object file section, including the section
-name, any Bytecode objects contained within that section, and other
-information.
-
-"""
-
-cdef extern from "Python.h":
- cdef object PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
- cdef object PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,
- void (*destr)(void *, void *))
- cdef int PyType_Check(object)
- cdef int PyCObject_Check(object)
- cdef void *PyCObject_AsVoidPtr(object)
- cdef void *PyCObject_GetDesc(object)
-
- cdef object _PyLong_FromByteArray(unsigned char *bytes, unsigned int n,
- int little_endian, int is_signed)
- cdef int _PyLong_AsByteArray(object v, unsigned char *bytes, unsigned int n,
- int little_endian, int is_signed) except -1
-
- cdef void Py_INCREF(object o)
- cdef void Py_DECREF(object o)
-
- cdef void PyErr_SetString(object type, char *message)
- cdef object PyErr_Format(object type, char *format, ...)
-
-cdef extern from "stdlib.h":
- cdef void *malloc(int n)
- cdef void free(void *p)
-
-include "_yasm.pxi"
-
-cdef object __pass_voidp(void *obj, object forclass):
- return PyCObject_FromVoidPtrAndDesc(obj, <void *>forclass, NULL)
-
-cdef void *__get_voidp(object obj, object forclass) except NULL:
- cdef void* desc
-
- if not PyCObject_Check(obj):
- msg = "obj %r is not a CObject" % obj
- PyErr_SetString(TypeError, msg)
- return NULL
-
- desc = PyCObject_GetDesc(obj)
-
- if desc != <void *>forclass:
- if desc == NULL:
- msg = "CObject type is not set (expecting %s)" % forclass
- elif PyType_Check(<object>desc):
- msg = "CObject is for %s not %s" % (<object>desc, forclass)
- else:
- msg = "CObject is incorrect (expecting %s)" % forclass
- PyErr_SetString(TypeError, msg)
- return NULL
-
- return PyCObject_AsVoidPtr(obj)
-
-#
-# Link to associated data mechanism to keep Python references paired with
-# yasm objects.
-#
-cdef class __assoc_data_callback:
- cdef yasm_assoc_data_callback *cb
- def __new__(self, destroy, print_):
- self.cb = <yasm_assoc_data_callback *>malloc(sizeof(yasm_assoc_data_callback))
- self.cb.destroy = <void (*) (void *)>PyCObject_AsVoidPtr(destroy)
- #self.cb.print_ = <void (*) (void *, FILE *, int)>PyCObject_AsVoidPtr(print_)
- def __dealloc__(self):
- free(self.cb)
-
-
-cdef class Register:
- cdef unsigned long reg
- def __new__(self, reg):
- self.reg = reg
-
-include "errwarn.pxi"
-include "intnum.pxi"
-include "floatnum.pxi"
-include "expr.pxi"
-include "symrec.pxi"
-include "value.pxi"
-
-include "bytecode.pxi"
-
-cdef __initialize():
- BitVector_Boot()
- yasm_intnum_initialize()
- yasm_floatnum_initialize()
- yasm_errwarn_initialize()
-
-def __cleanup():
- yasm_floatnum_cleanup()
- yasm_intnum_cleanup()
- yasm_errwarn_cleanup()
- BitVector_Shutdown()
-
-__initialize()
-import atexit
-atexit.register(__cleanup)
-