diff --git a/tests/makeotfexe_data/expected_output/fealib/Attach.ttx b/tests/makeotfexe_data/expected_output/fealib/Attach.ttx
new file mode 100644
index 000000000..d9a6d482f
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/Attach.ttx
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_1.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_1.ttx
new file mode 100644
index 000000000..b6e8d6709
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_1.ttx
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_1_zero.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_1_zero.ttx
new file mode 100644
index 000000000..eb472ac56
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_1_zero.ttx
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_2.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_2.ttx
new file mode 100644
index 000000000..00533d96b
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_2.ttx
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_2b.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_2b.ttx
new file mode 100644
index 000000000..30cca2fa0
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_2b.ttx
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_3.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_3.ttx
new file mode 100644
index 000000000..eac94105b
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_3.ttx
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_4.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_4.ttx
new file mode 100644
index 000000000..635fac4f6
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_4.ttx
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_5.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_5.ttx
new file mode 100644
index 000000000..bebe4a8e5
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_5.ttx
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_6.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_6.ttx
new file mode 100644
index 000000000..c34c01f58
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_6.ttx
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GPOS_8.ttx b/tests/makeotfexe_data/expected_output/fealib/GPOS_8.ttx
new file mode 100644
index 000000000..3585bd048
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GPOS_8.ttx
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GSUB_2.ttx b/tests/makeotfexe_data/expected_output/fealib/GSUB_2.ttx
new file mode 100644
index 000000000..b64a12a1e
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GSUB_2.ttx
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GSUB_3.ttx b/tests/makeotfexe_data/expected_output/fealib/GSUB_3.ttx
new file mode 100644
index 000000000..a19a61918
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GSUB_3.ttx
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GSUB_6.ttx b/tests/makeotfexe_data/expected_output/fealib/GSUB_6.ttx
new file mode 100644
index 000000000..f32e47d9e
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GSUB_6.ttx
@@ -0,0 +1,267 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GSUB_8.ttx b/tests/makeotfexe_data/expected_output/fealib/GSUB_8.ttx
new file mode 100644
index 000000000..573b51e09
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GSUB_8.ttx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/GlyphClassDef.ttx b/tests/makeotfexe_data/expected_output/fealib/GlyphClassDef.ttx
new file mode 100644
index 000000000..7bdead8c6
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/GlyphClassDef.ttx
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByIndex.ttx b/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByIndex.ttx
new file mode 100644
index 000000000..2e34e29fd
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByIndex.ttx
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByPos.ttx b/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByPos.ttx
new file mode 100644
index 000000000..ba4816019
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/LigatureCaretByPos.ttx
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/PairPosSubtable.ttx b/tests/makeotfexe_data/expected_output/fealib/PairPosSubtable.ttx
new file mode 100644
index 000000000..4b76f991f
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/PairPosSubtable.ttx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_horizontal.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_horizontal.ttx
new file mode 100644
index 000000000..91fbfdc4f
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_horizontal.ttx
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_vertical.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_vertical.ttx
new file mode 100644
index 000000000..27c4880ae
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_ChainSinglePos_vertical.ttx
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_horizontal.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_horizontal.ttx
new file mode 100644
index 000000000..73f440d96
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_horizontal.ttx
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_vertical.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_vertical.ttx
new file mode 100644
index 000000000..9881a41b5
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_PairPos_vertical.ttx
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_horizontal.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_horizontal.ttx
new file mode 100644
index 000000000..6a88e69bf
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_horizontal.ttx
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_vertical.ttx b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_vertical.ttx
new file mode 100644
index 000000000..6fa95d383
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ZeroValue_SinglePos_vertical.ttx
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug1307.ttx b/tests/makeotfexe_data/expected_output/fealib/bug1307.ttx
new file mode 100644
index 000000000..4fbcdc0df
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug1307.ttx
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug1459.ttx b/tests/makeotfexe_data/expected_output/fealib/bug1459.ttx
new file mode 100644
index 000000000..ddf036356
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug1459.ttx
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug453.ttx b/tests/makeotfexe_data/expected_output/fealib/bug453.ttx
new file mode 100644
index 000000000..a8d7a4c8b
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug453.ttx
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug457.ttx b/tests/makeotfexe_data/expected_output/fealib/bug457.ttx
new file mode 100644
index 000000000..2aa4dc6e0
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug457.ttx
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug463.ttx b/tests/makeotfexe_data/expected_output/fealib/bug463.ttx
new file mode 100644
index 000000000..96647d4d1
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug463.ttx
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug501.ttx b/tests/makeotfexe_data/expected_output/fealib/bug501.ttx
new file mode 100644
index 000000000..f085cd941
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug501.ttx
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug502.ttx b/tests/makeotfexe_data/expected_output/fealib/bug502.ttx
new file mode 100644
index 000000000..14412ce34
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug502.ttx
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug504.ttx b/tests/makeotfexe_data/expected_output/fealib/bug504.ttx
new file mode 100644
index 000000000..69a499591
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug504.ttx
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug505.ttx b/tests/makeotfexe_data/expected_output/fealib/bug505.ttx
new file mode 100644
index 000000000..dbfb67059
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug505.ttx
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug506.ttx b/tests/makeotfexe_data/expected_output/fealib/bug506.ttx
new file mode 100644
index 000000000..3d42d6102
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug506.ttx
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug509.ttx b/tests/makeotfexe_data/expected_output/fealib/bug509.ttx
new file mode 100644
index 000000000..9f0acf3c1
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug509.ttx
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug512.ttx b/tests/makeotfexe_data/expected_output/fealib/bug512.ttx
new file mode 100644
index 000000000..0b718cbe4
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug512.ttx
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug514.ttx b/tests/makeotfexe_data/expected_output/fealib/bug514.ttx
new file mode 100644
index 000000000..3070311e7
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug514.ttx
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug568.ttx b/tests/makeotfexe_data/expected_output/fealib/bug568.ttx
new file mode 100644
index 000000000..8e943e7dc
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug568.ttx
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/bug633.ttx b/tests/makeotfexe_data/expected_output/fealib/bug633.ttx
new file mode 100644
index 000000000..1c52f0d47
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/bug633.ttx
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/enum.ttx b/tests/makeotfexe_data/expected_output/fealib/enum.ttx
new file mode 100644
index 000000000..36e3c7734
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/enum.ttx
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/feature_aalt.ttx b/tests/makeotfexe_data/expected_output/fealib/feature_aalt.ttx
new file mode 100644
index 000000000..1523ed3ad
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/feature_aalt.ttx
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/ignore_pos.ttx b/tests/makeotfexe_data/expected_output/fealib/ignore_pos.ttx
new file mode 100644
index 000000000..bb7415d13
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/ignore_pos.ttx
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/language_required.ttx b/tests/makeotfexe_data/expected_output/fealib/language_required.ttx
new file mode 100644
index 000000000..5481439e5
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/language_required.ttx
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/lookup.ttx b/tests/makeotfexe_data/expected_output/fealib/lookup.ttx
new file mode 100644
index 000000000..bb6025005
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/lookup.ttx
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/lookupflag.ttx b/tests/makeotfexe_data/expected_output/fealib/lookupflag.ttx
new file mode 100644
index 000000000..cbe084a2d
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/lookupflag.ttx
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/markClass.ttx b/tests/makeotfexe_data/expected_output/fealib/markClass.ttx
new file mode 100644
index 000000000..7369447a8
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/markClass.ttx
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/multiple_feature_blocks.ttx b/tests/makeotfexe_data/expected_output/fealib/multiple_feature_blocks.ttx
new file mode 100644
index 000000000..56ecd5c6c
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/multiple_feature_blocks.ttx
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/name.ttx b/tests/makeotfexe_data/expected_output/fealib/name.ttx
new file mode 100644
index 000000000..856d1b767
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/name.ttx
@@ -0,0 +1,58 @@
+
+
+
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Test8
+
+
+ Test10
+
+
+ Test11
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Test7
+
+
+ Test9
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/omitted_GlyphClassDef.ttx b/tests/makeotfexe_data/expected_output/fealib/omitted_GlyphClassDef.ttx
new file mode 100644
index 000000000..df7647b84
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/omitted_GlyphClassDef.ttx
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/size.ttx b/tests/makeotfexe_data/expected_output/fealib/size.ttx
new file mode 100644
index 000000000..1a12ddfc7
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/size.ttx
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/size2.ttx b/tests/makeotfexe_data/expected_output/fealib/size2.ttx
new file mode 100644
index 000000000..1a12ddfc7
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/size2.ttx
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec10.ttx b/tests/makeotfexe_data/expected_output/fealib/spec10.ttx
new file mode 100644
index 000000000..5db8ac2ff
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec10.ttx
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec4h1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec4h1.ttx
new file mode 100644
index 000000000..a52afcee0
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec4h1.ttx
@@ -0,0 +1,329 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec4h2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec4h2.ttx
new file mode 100644
index 000000000..c02e613bb
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec4h2.ttx
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5d1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5d1.ttx
new file mode 100644
index 000000000..b1ee83b2c
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5d1.ttx
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5d2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5d2.ttx
new file mode 100644
index 000000000..56be99b7d
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5d2.ttx
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_1.ttx
new file mode 100644
index 000000000..d704e201a
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_1.ttx
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_2.ttx
new file mode 100644
index 000000000..8200519a2
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_2.ttx
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_3.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_3.ttx
new file mode 100644
index 000000000..43cea15be
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_3.ttx
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_4.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_4.ttx
new file mode 100644
index 000000000..99f68137a
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5f_ii_4.ttx
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5fi1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5fi1.ttx
new file mode 100644
index 000000000..958d68f52
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5fi1.ttx
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5fi2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5fi2.ttx
new file mode 100644
index 000000000..78afb8758
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5fi2.ttx
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5fi3.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5fi3.ttx
new file mode 100644
index 000000000..2117d5cf0
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5fi3.ttx
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5fi4.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5fi4.ttx
new file mode 100644
index 000000000..7135b418f
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5fi4.ttx
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec5h1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec5h1.ttx
new file mode 100644
index 000000000..6773e53f2
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec5h1.ttx
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6b_ii.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6b_ii.ttx
new file mode 100644
index 000000000..20c1a1acc
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6b_ii.ttx
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6d2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6d2.ttx
new file mode 100644
index 000000000..0233ba902
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6d2.ttx
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6e.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6e.ttx
new file mode 100644
index 000000000..9f1da3bec
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6e.ttx
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6f.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6f.ttx
new file mode 100644
index 000000000..46035caaa
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6f.ttx
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6h_ii.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6h_ii.ttx
new file mode 100644
index 000000000..1c5e1d6ec
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6h_ii.ttx
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_1.ttx
new file mode 100644
index 000000000..bd3a9d3f8
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_1.ttx
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_3d.ttx b/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_3d.ttx
new file mode 100644
index 000000000..2b58b2c16
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec6h_iii_3d.ttx
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec8a.ttx b/tests/makeotfexe_data/expected_output/fealib/spec8a.ttx
new file mode 100644
index 000000000..4f6e03a92
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec8a.ttx
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec8b.ttx b/tests/makeotfexe_data/expected_output/fealib/spec8b.ttx
new file mode 100644
index 000000000..7f7bc519e
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec8b.ttx
@@ -0,0 +1,89 @@
+
+
+
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Mac MinionPro Size Name
+
+
+ Mac MinionPro Size Name
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Win MinionPro Size Name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec8c.ttx b/tests/makeotfexe_data/expected_output/fealib/spec8c.ttx
new file mode 100644
index 000000000..50817f464
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec8c.ttx
@@ -0,0 +1,98 @@
+
+
+
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Feature description for Apple Platform, script Roman, language unspecified
+
+
+ Feature description for Apple Platform, script Japanese, language Japanese
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Feature description for MS Platform, script Unicode, language English
+
+
+ Feature description for MS Platform, script Unicode, language Japanese
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec8d.ttx b/tests/makeotfexe_data/expected_output/fealib/spec8d.ttx
new file mode 100644
index 000000000..95b410972
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec8d.ttx
@@ -0,0 +1,123 @@
+
+
+
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ uilabel simple a
+
+
+ tool tip simple a
+
+
+ sample text simple a
+
+
+ param1 text simple a
+
+
+ param2 text simple a
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ uilabel simple a
+
+
+ tool tip simple a
+
+
+ sample text simple a
+
+
+ param1 text simple a
+
+
+ param2 text simple a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9a.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9a.ttx
new file mode 100644
index 000000000..c6bb896cc
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9a.ttx
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9b.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9b.ttx
new file mode 100644
index 000000000..139872971
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9b.ttx
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9c1.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9c1.ttx
new file mode 100644
index 000000000..e60e0b8ce
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9c1.ttx
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9c2.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9c2.ttx
new file mode 100644
index 000000000..c9d9cbcb9
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9c2.ttx
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9c3.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9c3.ttx
new file mode 100644
index 000000000..65b108321
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9c3.ttx
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9d.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9d.ttx
new file mode 100644
index 000000000..b1be3a000
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9d.ttx
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9e.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9e.ttx
new file mode 100644
index 000000000..d6f036cbd
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9e.ttx
@@ -0,0 +1,49 @@
+
+
+
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Joachim Müller-Lancé
+
+
+ Untitled1
+
+
+ Regular
+
+
+ 1.000;UKWN;Untitled1
+
+
+ Untitled1
+
+
+ Version 1.000;hotconv 1.0.111;makeotfexe 2.5.65597 DEVELOPMENT
+
+
+ Untitled1
+
+
+ Joachim Müller-Lancé
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9f.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9f.ttx
new file mode 100644
index 000000000..03461f574
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9f.ttx
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/expected_output/fealib/spec9g.ttx b/tests/makeotfexe_data/expected_output/fealib/spec9g.ttx
new file mode 100644
index 000000000..cf76246c8
--- /dev/null
+++ b/tests/makeotfexe_data/expected_output/fealib/spec9g.ttx
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/makeotfexe_data/input/fealib/Attach.fea b/tests/makeotfexe_data/input/fealib/Attach.fea
new file mode 100644
index 000000000..86266eeec
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/Attach.fea
@@ -0,0 +1,5 @@
+table GDEF {
+ Attach [a e] 7;
+ Attach a 23;
+ Attach a 23;
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_1.fea b/tests/makeotfexe_data/input/fealib/GPOS_1.fea
new file mode 100644
index 000000000..a550509c6
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_1.fea
@@ -0,0 +1,38 @@
+languagesystem DFLT dflt;
+
+@sevenEightNine = [seven eight nine];
+
+feature kern {
+ pos zero 0;
+
+ pos [one two three] <-80 0 -160 0>;
+ pos A <1 2 3 4 >;
+ pos B <1 2 3 4 >;
+ pos C <1 2 3 4 >;
+ pos four 400;
+ pos four.oldstyle 401;
+ pos five <-80 0 -160 0>;
+ pos six -200;
+ pos @sevenEightNine -100;
+
+ pos P <1 0 800 0>;
+ pos Q <1 0 801 0>;
+ pos R <1 0 802 0>;
+ pos S <1 1 803 0>;
+ pos T <1 1 804 0>;
+ pos U <1 1 805 0>;
+
+ # The AFDKO makeotf tool accepts re-definitions of previously defined
+ # single adjustment positionings, provided the re-definition is using
+ # the same value. We replicate this behavior.
+ pos four 400;
+ pos four <0 0 400 0>;
+ pos nine -100;
+} kern;
+
+# According to the OpenType Feature File specification section 2.e.iv,
+# the following should be interpreted as vertical advance adjustment
+# because -100 (a value record format A) appears within a ‘vkrn’ feature.
+feature vkrn {
+ pos A -100;
+} vkrn;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_1_zero.fea b/tests/makeotfexe_data/input/fealib/GPOS_1_zero.fea
new file mode 100644
index 000000000..2e738e2b5
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_1_zero.fea
@@ -0,0 +1,5 @@
+# https://github.com/fonttools/fonttools/issues/471
+feature test {
+ pos zero 0;
+ pos four 500;
+} test;
\ No newline at end of file
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_2.fea b/tests/makeotfexe_data/input/fealib/GPOS_2.fea
new file mode 100644
index 000000000..2948148bd
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_2.fea
@@ -0,0 +1,30 @@
+languagesystem DFLT dflt;
+
+# Mixes kerning between single glyphs, and class-based kerning.
+# https://github.com/fonttools/fonttools/issues/456
+lookup MixedKerning {
+ pos v v 14;
+ pos [D O Q] [T V W] -26;
+} MixedKerning;
+
+lookup GlyphKerning {
+ pos T one 100;
+ pos T two 200;
+ pos T two.oldstyle 200;
+ pos T three 300;
+ pos T four 400;
+ pos X a 100;
+ pos X b 200;
+ pos Y a 100;
+ pos Y b 200;
+ pos Y c <3 3 3 3>;
+} GlyphKerning;
+
+feature kern {
+ lookup GlyphKerning;
+ lookup MixedKerning;
+} kern;
+
+feature vkrn {
+ pos T one 100;
+} vkrn;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_2b.fea b/tests/makeotfexe_data/input/fealib/GPOS_2b.fea
new file mode 100644
index 000000000..da9fd8453
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_2b.fea
@@ -0,0 +1,9 @@
+@PUNC = [comma semicolon period];
+
+feature kern {
+ pos [A] @PUNC 1;
+ pos [B C] [comma] 2;
+ pos [D E F] [comma] 3;
+ pos [D E F] [semicolon period] 4;
+ pos [G] @PUNC <5 5 5 5>;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_3.fea b/tests/makeotfexe_data/input/fealib/GPOS_3.fea
new file mode 100644
index 000000000..18dabc0a0
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_3.fea
@@ -0,0 +1,12 @@
+languagesystem DFLT dflt;
+
+anchorDef 3 4 contourpoint 2 ANCH342;
+
+feature kern {
+ pos cursive zero ;
+ pos cursive one ;
+ pos cursive two ;
+ pos cursive three ;
+ pos cursive four ;
+# pos cursive five > ;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_4.fea b/tests/makeotfexe_data/input/fealib/GPOS_4.fea
new file mode 100644
index 000000000..cfd2d757c
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_4.fea
@@ -0,0 +1,12 @@
+languagesystem DFLT dflt;
+
+markClass [acute grave] @TOP_MARKS;
+markClass macron @TOP_MARKS;
+markClass [cedilla] @BOTTOM_MARKS;
+markClass [ogonek] @SIDE_MARKS;
+
+feature test {
+ pos base a mark @TOP_MARKS mark @BOTTOM_MARKS;
+ pos base [b c] mark @BOTTOM_MARKS;
+ pos base d mark @SIDE_MARKS;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_5.fea b/tests/makeotfexe_data/input/fealib/GPOS_5.fea
new file mode 100644
index 000000000..b116539aa
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_5.fea
@@ -0,0 +1,18 @@
+markClass [acute grave] @TOP_MARKS;
+markClass macron @TOP_MARKS;
+markClass [cedilla] @BOTTOM_MARKS;
+markClass [ogonek] @OGONEK;
+
+feature test {
+
+ pos ligature [c_t s_t] mark @TOP_MARKS mark @BOTTOM_MARKS
+ ligComponent mark @TOP_MARKS mark @BOTTOM_MARKS mark @OGONEK;
+
+ pos ligature f_l mark @TOP_MARKS mark @BOTTOM_MARKS
+ ligComponent mark @TOP_MARKS mark @BOTTOM_MARKS;
+
+ pos ligature [f_f_l] mark @TOP_MARKS mark @BOTTOM_MARKS
+ ligComponent mark @TOP_MARKS mark @BOTTOM_MARKS
+ ligComponent mark @TOP_MARKS mark @BOTTOM_MARKS;
+
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_6.fea b/tests/makeotfexe_data/input/fealib/GPOS_6.fea
new file mode 100644
index 000000000..37b293659
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_6.fea
@@ -0,0 +1,10 @@
+languagesystem DFLT dflt;
+
+markClass [acute grave] @TOP_MARKS;
+markClass macron @TOP_MARKS;
+markClass [cedilla] @BOTTOM_MARKS;
+
+feature test {
+ pos mark [acute grave macron ogonek] mark @TOP_MARKS mark @BOTTOM_MARKS;
+ pos mark [dieresis caron] mark @TOP_MARKS;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GPOS_8.fea b/tests/makeotfexe_data/input/fealib/GPOS_8.fea
new file mode 100644
index 000000000..2351ee2ce
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GPOS_8.fea
@@ -0,0 +1,22 @@
+languagesystem DFLT dflt;
+
+lookup ChainedSinglePos {
+ pos A one' 1 two' 2 one' -1 two' -2;
+} ChainedSinglePos;
+
+lookup L1 {
+ pos one 100;
+} L1;
+
+lookup L2 {
+ pos two 200;
+} L2;
+
+lookup ChainedContextualPos {
+ pos [A a] [B b] I' lookup L1 N' lookup L2 P' [Y y] [Z z];
+} ChainedContextualPos;
+
+feature test {
+ lookup ChainedSinglePos;
+ lookup ChainedContextualPos;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GSUB_2.fea b/tests/makeotfexe_data/input/fealib/GSUB_2.fea
new file mode 100644
index 000000000..d2a3cb101
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GSUB_2.fea
@@ -0,0 +1,14 @@
+feature f1 {
+ sub c_t by c t;
+ sub f_i by f i;
+ sub f_f_i by f f i;
+} f1;
+
+
+# Even if it has exactly the same content as feature f1,
+# the lookup should not be shared.
+feature f2 {
+ sub c_t by c t;
+ sub f_i by f i;
+ sub f_f_i by f f i;
+} f2;
diff --git a/tests/makeotfexe_data/input/fealib/GSUB_3.fea b/tests/makeotfexe_data/input/fealib/GSUB_3.fea
new file mode 100644
index 000000000..e128305c5
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GSUB_3.fea
@@ -0,0 +1,14 @@
+feature f1 {
+ sub A from [A.alt1 A.alt2];
+ sub B from [B.alt1 B.alt2 B.alt3];
+ sub C from [C.alt1];
+} f1;
+
+
+# Even if it has exactly the same content as feature f1,
+# the lookup should not be shared.
+feature f2 {
+ sub A from [A.alt1 A.alt2];
+ sub B from [B.alt1 B.alt2 B.alt3];
+ sub C from [C.alt1];
+} f2;
diff --git a/tests/makeotfexe_data/input/fealib/GSUB_6.fea b/tests/makeotfexe_data/input/fealib/GSUB_6.fea
new file mode 100644
index 000000000..82fdac250
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GSUB_6.fea
@@ -0,0 +1,28 @@
+lookup ChainedSingleSubst {
+ sub [one two] three A' by A.sc;
+ sub [B-D]' seven [eight nine] by [B.sc-D.sc];
+} ChainedSingleSubst;
+
+lookup ChainedMultipleSubst {
+ sub [A-C a-c] [D d] E c_t' V [W w] [X-Z x-z] by c t;
+} ChainedMultipleSubst;
+
+lookup ChainedAlternateSubst {
+ sub [space comma semicolon] e' from [e e.begin];
+} ChainedAlternateSubst;
+
+lookup ChainedLigatureSubst {
+ sub A [C c]' [T t]' Z by c_t;
+} ChainedLigatureSubst;
+
+lookup ChainedContextualSubst {
+ sub A D E c_t' lookup ChainedMultipleSubst V W X;
+} ChainedContextualSubst;
+
+feature test {
+ lookup ChainedSingleSubst;
+ lookup ChainedMultipleSubst;
+ lookup ChainedAlternateSubst;
+ lookup ChainedLigatureSubst;
+ lookup ChainedContextualSubst;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GSUB_8.fea b/tests/makeotfexe_data/input/fealib/GSUB_8.fea
new file mode 100644
index 000000000..62c7bee4c
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GSUB_8.fea
@@ -0,0 +1,11 @@
+languagesystem DFLT dflt;
+
+feature test {
+ rsub [a A] [b B] [c C] q' [d D] [e E] [f F] by Q;
+ rsub [a A] [b B] [c C] [s-z]' [d D] [e E] [f F] by [S-Z];
+
+ # Having no context for a reverse chaining substitution rule
+ # is a little degenerate (we define a chain without linking it
+ # to anything else), but makeotf accepts this.
+ rsub p by P;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/GlyphClassDef.fea b/tests/makeotfexe_data/input/fealib/GlyphClassDef.fea
new file mode 100644
index 000000000..8e5353647
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/GlyphClassDef.fea
@@ -0,0 +1,5 @@
+table GDEF {
+ GlyphClassDef [a], [b], [c], [d];
+ GlyphClassDef [e], [f], [g], [h];
+ GlyphClassDef [i], [j], [k], [l];
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/LigatureCaretByIndex.fea b/tests/makeotfexe_data/input/fealib/LigatureCaretByIndex.fea
new file mode 100644
index 000000000..5f74fc641
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/LigatureCaretByIndex.fea
@@ -0,0 +1,6 @@
+table GDEF {
+ LigatureCaretByIndex [c_t s_t] 11;
+
+ LigatureCaretByIndex o_f_f_i 66 33;
+ LigatureCaretByIndex o_f_f_i 55;
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/LigatureCaretByPos.fea b/tests/makeotfexe_data/input/fealib/LigatureCaretByPos.fea
new file mode 100644
index 000000000..e799c3c2a
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/LigatureCaretByPos.fea
@@ -0,0 +1,6 @@
+table GDEF {
+ LigatureCaretByPos [c_h c_k] 500;
+
+ LigatureCaretByPos o_f_f_i 700 300;
+ LigatureCaretByPos o_f_f_i 900;
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/PairPosSubtable.fea b/tests/makeotfexe_data/input/fealib/PairPosSubtable.fea
new file mode 100644
index 000000000..cb78801c9
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/PairPosSubtable.fea
@@ -0,0 +1,29 @@
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+
+@group1 = [b o];
+@group2 = [c d];
+@group3 = [v w];
+@group4 = [];
+
+lookup kernlookup {
+ pos A V -34;
+ subtable;
+ pos @group1 @group2 -12;
+ subtable;
+ pos @group1 @group3 -10;
+ pos @group3 @group2 -20;
+ subtable;
+ pos @group4 @group1 -10;
+ pos @group4 @group4 -10;
+} kernlookup;
+
+feature kern {
+ script DFLT;
+ language dflt;
+ lookup kernlookup;
+
+ script latn;
+ language dflt;
+ lookup kernlookup;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_horizontal.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_horizontal.fea
new file mode 100644
index 000000000..480fc76d0
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_horizontal.fea
@@ -0,0 +1,9 @@
+# For contextual positioning statements with in-line single positioning rules,
+# zeroes should get compiled to ValueRecord format 0.
+# https://github.com/fonttools/fonttools/issues/633
+
+# Zero value in a horizontal context.
+feature kern {
+ pos A G' 0 A; # value format A
+ pos B G' <0 0 0 0> B; # value format B
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_vertical.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_vertical.fea
new file mode 100644
index 000000000..a9fb7d1df
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_ChainSinglePos_vertical.fea
@@ -0,0 +1,9 @@
+# For contextual positioning statements with in-line single positioning rules,
+# zeroes should get compiled to ValueRecord format 0.
+# https://github.com/fonttools/fonttools/issues/633
+
+# Zero value in a vertical context.
+feature vkrn {
+ pos A G' 0 A; # value format A
+ pos B G' <0 0 0 0> B; # value format B
+} vkrn;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_horizontal.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_horizontal.fea
new file mode 100644
index 000000000..b5e48f4d9
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_horizontal.fea
@@ -0,0 +1,9 @@
+# For PairPos statements in horizontal compilation contexts,
+# zero values should get compiled to ValueRecord format 4.
+# https://github.com/fonttools/fonttools/issues/633
+feature kern {
+ pos A 0 A 0;
+ pos A 0 B <0 0 0 0>;
+ pos B <0 0 0 0> A 0;
+ pos B <0 0 0 0> B <0 0 0 0>;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_vertical.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_vertical.fea
new file mode 100644
index 000000000..1ab33a903
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_PairPos_vertical.fea
@@ -0,0 +1,9 @@
+# For PairPos statements in vertical compilation contexts,
+# zero values should get compiled to ValueRecord format 8.
+# https://github.com/fonttools/fonttools/issues/633
+feature vkrn {
+ pos A 0 A 0;
+ pos A 0 B <0 0 0 0>;
+ pos B <0 0 0 0> A 0;
+ pos B <0 0 0 0> B <0 0 0 0>;
+} vkrn;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_horizontal.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_horizontal.fea
new file mode 100644
index 000000000..44fe683d3
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_horizontal.fea
@@ -0,0 +1,8 @@
+# For SinglePos statements, zeroes should get compiled to ValueRecord format 0.
+# https://github.com/fonttools/fonttools/issues/633
+
+# Zero value in a horizontal context.
+feature kern {
+ pos A 0; # format A
+ pos B <0 0 0 0>; # format B
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_vertical.fea b/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_vertical.fea
new file mode 100644
index 000000000..3ee9a1bf5
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ZeroValue_SinglePos_vertical.fea
@@ -0,0 +1,8 @@
+# For SinglePos statements, zeroes should get compiled to ValueRecord format 0.
+# https://github.com/fonttools/fonttools/issues/633
+
+# Zero value in a vertical context.
+feature vkrn {
+ pos A 0; # format A
+ pos B <0 0 0 0>; # format B
+} vkrn;
diff --git a/tests/makeotfexe_data/input/fealib/baseClass.fea b/tests/makeotfexe_data/input/fealib/baseClass.fea
new file mode 100644
index 000000000..2a370c142
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/baseClass.fea
@@ -0,0 +1,10 @@
+languagesystem DFLT dflt;
+
+markClass [acute] @TOP_MARKS;
+
+feature test {
+ pos base [a] mark @TOP_MARKS;
+ pos base b mark @TOP_MARKS;
+} test;
+
+
diff --git a/tests/makeotfexe_data/input/fealib/bug1307.fea b/tests/makeotfexe_data/input/fealib/bug1307.fea
new file mode 100644
index 000000000..dbc4ae365
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug1307.fea
@@ -0,0 +1,65 @@
+# Test of features and languagesystems
+
+lookup a {
+ sub a by A;
+} a;
+
+lookup b {
+ sub b by B;
+} b;
+
+lookup c {
+ sub c by C;
+} c;
+
+lookup d {
+ sub d by D;
+} d;
+
+lookup e {
+ sub e by E;
+} e;
+
+lookup f {
+ sub f by F;
+} f;
+
+lookup g {
+ sub g by G;
+} g;
+
+lookup h {
+ sub h by H;
+} h;
+
+lookup i {
+ sub i by I;
+} i;
+
+languagesystem DFLT dflt;
+languagesystem DFLT FRE;
+languagesystem DFLT ABC;
+languagesystem latn dflt;
+languagesystem latn ABC;
+
+feature smcp {
+ lookup a;
+} smcp;
+
+feature liga {
+ lookup b;
+ script DFLT;
+ lookup c;
+ language dflt;
+ lookup d;
+ language FRE;
+ lookup e;
+ script latn;
+ lookup f;
+ language dflt;
+ lookup g;
+ language FRE;
+ lookup h;
+ language DEF exclude_dflt;
+ lookup i;
+} liga;
diff --git a/tests/makeotfexe_data/input/fealib/bug1459.fea b/tests/makeotfexe_data/input/fealib/bug1459.fea
new file mode 100644
index 000000000..1ad688e8a
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug1459.fea
@@ -0,0 +1,7 @@
+# A pair position lookup where only the second glyph has a non-empty valuerecord
+# while the first glyph has a NULL valuerecord. The ValueFormat1 for the first
+# glyph is expected to be 0.
+# https://github.com/fonttools/fonttools/issues/1459
+feature kern {
+ pos A V <-180 0 -90 0>;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/bug453.fea b/tests/makeotfexe_data/input/fealib/bug453.fea
new file mode 100644
index 000000000..486632ee2
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug453.fea
@@ -0,0 +1,11 @@
+# https://github.com/fonttools/fonttools/issues/453
+feature mark {
+ lookup mark1 {
+ markClass [acute] @TOP_MARKS;
+ pos base [e] mark @TOP_MARKS;
+ } mark1;
+ lookup mark2 {
+ markClass [acute] @TOP_MARKS_2;
+ pos base [e] mark @TOP_MARKS_2;
+ } mark2;
+} mark;
diff --git a/tests/makeotfexe_data/input/fealib/bug457.fea b/tests/makeotfexe_data/input/fealib/bug457.fea
new file mode 100644
index 000000000..9ab083b9b
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug457.fea
@@ -0,0 +1,5 @@
+@group = [A \sub \lookup \feature \by \table];
+
+feature liga {
+ sub @group by G;
+} liga;
diff --git a/tests/makeotfexe_data/input/fealib/bug463.fea b/tests/makeotfexe_data/input/fealib/bug463.fea
new file mode 100644
index 000000000..4b1910c13
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug463.fea
@@ -0,0 +1,6 @@
+# https://github.com/fonttools/fonttools/issues/463
+feature ordn {
+ @DIGIT = [zero one two three four five six seven eight nine];
+ sub @DIGIT [A a]' by ordfeminine;
+ sub @DIGIT [O o]' by ordmasculine;
+} ordn;
diff --git a/tests/makeotfexe_data/input/fealib/bug501.fea b/tests/makeotfexe_data/input/fealib/bug501.fea
new file mode 100644
index 000000000..06d91dda0
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug501.fea
@@ -0,0 +1,8 @@
+# https://github.com/fonttools/fonttools/issues/501
+languagesystem DFLT dflt;
+feature test {
+ lookup L {
+ script grek;
+ pos T 100;
+ } L;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug502.fea b/tests/makeotfexe_data/input/fealib/bug502.fea
new file mode 100644
index 000000000..3fcb94e28
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug502.fea
@@ -0,0 +1,7 @@
+# https://github.com/fonttools/fonttools/issues/502
+feature aalt {
+ sub A by A.alt1;
+ sub Eng by Eng.alt1;
+ sub Eng by Eng.alt2;
+ sub Eng by Eng.alt3;
+} aalt;
diff --git a/tests/makeotfexe_data/input/fealib/bug504.fea b/tests/makeotfexe_data/input/fealib/bug504.fea
new file mode 100644
index 000000000..e6920b2b4
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug504.fea
@@ -0,0 +1,5 @@
+# https://github.com/fonttools/fonttools/issues/504
+
+feature test {
+ sub [a b c d] by [T E S T];
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug505.fea b/tests/makeotfexe_data/input/fealib/bug505.fea
new file mode 100644
index 000000000..742ea1189
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug505.fea
@@ -0,0 +1,12 @@
+# https://github.com/fonttools/fonttools/issues/505
+
+languagesystem armn dflt;
+languagesystem avst dflt;
+languagesystem bali dflt;
+languagesystem bamu dflt;
+
+feature test {
+ script linb;
+ script vai;
+ sub T by t;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug506.fea b/tests/makeotfexe_data/input/fealib/bug506.fea
new file mode 100644
index 000000000..2e1e97dee
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug506.fea
@@ -0,0 +1,4 @@
+# https://github.com/fonttools/fonttools/issues/506
+feature test {
+ sub f' i' by f_i;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug509.fea b/tests/makeotfexe_data/input/fealib/bug509.fea
new file mode 100644
index 000000000..b7af056fd
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug509.fea
@@ -0,0 +1,5 @@
+@LETTER_A = [A A.sc A.alt1];
+feature test {
+ ignore sub A;
+ sub @LETTER_A' by a;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug512.fea b/tests/makeotfexe_data/input/fealib/bug512.fea
new file mode 100644
index 000000000..310b2947a
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug512.fea
@@ -0,0 +1,6 @@
+feature test {
+ sub G' by G.swash;
+ sub H' by H.swash;
+ sub G' by g;
+ sub H' by H.swash;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug514.fea b/tests/makeotfexe_data/input/fealib/bug514.fea
new file mode 100644
index 000000000..26da86557
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug514.fea
@@ -0,0 +1,11 @@
+# The many chain targets for this feature should get combined into
+# two separate SinglePos lookups: {A:-40, B:-40, C:-40} and {A:-111}.
+# https://github.com/fonttools/fonttools/issues/514
+#
+# makeotf produces {A:-40, B:-40, C:-40} and {A:-111, B:-40} which
+# is redundant. https://github.com/adobe-type-tools/afdko/issues/169
+feature test {
+ pos X [A-B]' -40 B' -40 A' -40 Y;
+ pos X A' -111 Y;
+ pos X B' -40 A' -111 [A-C]' -40 Y;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/bug568.fea b/tests/makeotfexe_data/input/fealib/bug568.fea
new file mode 100644
index 000000000..d9f56f956
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug568.fea
@@ -0,0 +1,11 @@
+# https://github.com/fonttools/fonttools/issues/568
+
+feature tst1 {
+ script latn;
+ pos T -20;
+} tst1;
+
+feature tst2 {
+ script cyrl;
+ pos T -80;
+} tst2;
diff --git a/tests/makeotfexe_data/input/fealib/bug633.fea b/tests/makeotfexe_data/input/fealib/bug633.fea
new file mode 100644
index 000000000..4f47168cf
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/bug633.fea
@@ -0,0 +1,10 @@
+# https://github.com/fonttools/fonttools/issues/633
+
+@public.kern1.K = [K X];
+@public.kern2.O = [C O];
+@public.kern2.V = [V W];
+
+feature kern {
+ pos @public.kern1.K @public.kern2.O -20;
+ pos @public.kern1.K @public.kern2.V 0;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/enum.fea b/tests/makeotfexe_data/input/fealib/enum.fea
new file mode 100644
index 000000000..124fb6264
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/enum.fea
@@ -0,0 +1,7 @@
+languagesystem DFLT dflt;
+
+feature kern {
+ @Y_LC = [y yacute ydieresis];
+ @SMALL_PUNC = [comma semicolon period];
+ enum pos @Y_LC @SMALL_PUNC -100;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/feature_aalt.fea b/tests/makeotfexe_data/input/fealib/feature_aalt.fea
new file mode 100644
index 000000000..1905ca96b
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/feature_aalt.fea
@@ -0,0 +1,29 @@
+languagesystem DFLT dflt;
+
+feature aalt {
+ feature sups;
+ feature frac;
+ feature ordn;
+} aalt;
+
+feature sups {
+ sub one by onesuperior;
+ sub two by twosuperior;
+ sub three by threesuperior;
+} sups;
+
+feature frac {
+ sub one slash four by onequarter;
+ sub one slash two by onehalf;
+ sub three slash four by threequarters;
+} frac;
+
+feature ordn {
+ sub [zero one two three four five six seven eight nine] [A a]' by ordfeminine;
+ sub [zero one two three four five six seven eight nine] [O o]' by ordmasculine;
+} ordn;
+
+feature liga {
+ sub f i by f_i;
+ sub f l by f_l;
+} liga;
diff --git a/tests/makeotfexe_data/input/fealib/font.pfa b/tests/makeotfexe_data/input/fealib/font.pfa
new file mode 100644
index 000000000..4b9f50ecd
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/font.pfa
@@ -0,0 +1,298 @@
+%!PS-AdobeFont-1.0: Untitled1 001.000
+%%Title: Untitled1
+%Version: 001.000
+%%CreationDate: Wed Sep 4 16:46:25 2019
+%%Creator: Khaled Hosny
+%Copyright: Copyright (c) 2019, Khaled Hosny
+% 2019-9-4: Created with FontForge (http://fontforge.org)
+% Generated by FontForge 20190801 (http://fontforge.sf.net/)
+%%EndComments
+
+10 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /Untitled1 def
+/FontBBox {0 0 0 0 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+ /version (001.000) readonly def
+ /Notice (Copyright \050c\051 2019, Khaled Hosny) readonly def
+ /FullName (Untitled1) readonly def
+ /FamilyName (Untitled1) readonly def
+ /Weight (Regular) readonly def
+ /ItalicAngle 0 def
+ /isFixedPitch true def
+ /UnderlinePosition -100 def
+ /UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+ 0 1 255 { 1 index exch /.notdef put} for
+dup 32/space put
+dup 38/ampersand put
+dup 44/comma put
+dup 46/period put
+dup 47/slash put
+dup 48/zero put
+dup 49/one put
+dup 50/two put
+dup 51/three put
+dup 52/four put
+dup 53/five put
+dup 54/six put
+dup 55/seven put
+dup 56/eight put
+dup 57/nine put
+dup 59/semicolon put
+dup 65/A put
+dup 66/B put
+dup 67/C put
+dup 68/D put
+dup 69/E put
+dup 70/F put
+dup 71/G put
+dup 72/H put
+dup 73/I put
+dup 74/J put
+dup 75/K put
+dup 76/L put
+dup 77/M put
+dup 78/N put
+dup 79/O put
+dup 80/P put
+dup 81/Q put
+dup 82/R put
+dup 83/S put
+dup 84/T put
+dup 85/U put
+dup 86/V put
+dup 87/W put
+dup 88/X put
+dup 89/Y put
+dup 90/Z put
+dup 96/grave put
+dup 97/a put
+dup 98/b put
+dup 99/c put
+dup 100/d put
+dup 101/e put
+dup 102/f put
+dup 103/g put
+dup 104/h put
+dup 105/i put
+dup 106/j put
+dup 107/k put
+dup 108/l put
+dup 109/m put
+dup 110/n put
+dup 111/o put
+dup 112/p put
+dup 113/q put
+dup 114/r put
+dup 115/s put
+dup 116/t put
+dup 117/u put
+dup 118/v put
+dup 119/w put
+dup 120/x put
+dup 121/y put
+dup 122/z put
+dup 168/dieresis put
+dup 170/ordfeminine put
+dup 175/macron put
+dup 178/twosuperior put
+dup 179/threesuperior put
+dup 180/acute put
+dup 184/cedilla put
+dup 185/onesuperior put
+dup 186/ordmasculine put
+dup 188/onequarter put
+dup 189/onehalf put
+dup 190/threequarters put
+dup 223/germandbls put
+dup 253/yacute put
+dup 255/ydieresis put
+readonly def
+currentdict end
+currentfile eexec
+743F8413F3636CA85A9FFEFB50B4BB273023E93DF9BCDBD9D94233FB53F690564BB08DDC
+EBB71CBEB281119D6A53B04B685076931FB3FAC7CCA65C9A76B4734884B4E063CB19F157
+E30150099D9188525ADAEBA3B96F33256F4D5015CEA845E051110AF02A49FCF9922BB024
+6133D07C3F897C434C3239CDC2BC6D33DEE9F02A647F8339E816915FE82CB77DB7812FC1
+3ED9625CF738CE569BD39FF57435C751BE1446E4E766B60D24096DFACC689AE89912967D
+9B602C0366FEA8A786E39D067304A555DC4BE38FE1E3987391AC8AA49C87C895F72DD4BF
+96DD7C1D1409D8A91B30FD08BBC562F3ADCF362100C618BCA821D6589C05E6238F5F9C41
+03722C21B5B64B78D6CF1FA1C1105D4B6EEEA8EF750480F2828A733E030E1579BE5CB0F3
+6D0E00297CE5D1DF01E0BC2CF0A214FAF98F716598C889F62F097C9912EE85DBF5D9538C
+F2DC600029130EEE151A62E8A5AB6015DD343977B687B74D16824F22AE9F904886211CB8
+4AFA7C89E0F0E18CA1D5865308A6266434AD60DFEE6E1096BD15B862AD91D86DA99CCD98
+B6C41EC4A1EE1EE387A4A5624C994B79958BCCA072DCDACB6CF676E983A97D8DEBEA1512
+2F719B89879B2439F0638A780C1659912BB709537B9870E95AA67BB5B70339FB8239DDF6
+06A8DDF9EDBAB6FC759440C75A4BB0B9BD79F6F604F0D74943113A2F05812AFC14EC6E4B
+568034790F141B83746DACE9FE6E045BAAAC4403A087F15BC7079B7A7D99CA3E2B6887AC
+548B5D6FF4613546E363857E16F8B661A560A735C16F81F95BA0334438E5BE80BE4D869D
+1B3105EF7D942E72B94B28B81DFED916A855B31B44244E8CF5EC219956663C74B39E77DA
+FFA35EDCD39A3BAB7351E70BFC66417E5C380CDB49F60B40D0CA65C23284C54FE154C457
+535C6F8D4B70CC98D0A48CC3094EB663525F9A01D96BED33F49CCAB0BE6D7FDB24D5F390
+F6D921EB604FABA7F2D3CCCCA53555822B8369F6829987C0FB82F30C8A53FC6F360EBCA1
+E13E76F0FA3A2CCFA0D1405D036666AD307C3A0039777C0AC2B7E34DE10C72C38934B202
+DA8BCB5E02C7F68625B7C26D953910B07DE3B6C9254FF8A6D23E6601E830F4056C36CBD3
+480EF33321926CE861B3255F44D5B7C2B712B87CCB12B5F16910F66BD95BF03B114260D9
+9BCC0E4713C15629844C2C482264C5FF1E41C2C44123B87F519CCD9F83ED8D97332A0371
+46DDC53B42F75D8EEFD8A18F2EF8E95FCEBA1474121332997EA2CEBC37A65205F44D0DBC
+F9141DAF9B2A4E48B17550494DDB6573D0AA4DE0A59E46A1C9B7EE51EDC4FABBA5191735
+3648880D6F30A4DE93C412ED5DE5C1BBBA17C9FC2365435297679C5DCC0488354D406689
+AF2AB3796AFDC093E109361B475524774FBB45B243975BC8E54B09835FD62F134AEBA280
+D918338A04060912925E0934F1893CF27430951C7B83A14F39329F175BEB31963FEC3E4E
+CF34F9CCD5D2C90A5AD5B8C91A0FDF6A79C34D52BE287703949DB1BA19CB765C6E93E350
+5A1F51688B4573601B0E36407FBABB59FD1F6DE336C5F3989CE6CDF69D99B573F173A6D2
+F13C76218931CB0F3F4AEC4A11468CD22F826F664B25009B20DE36DCC08767C9C33DB80C
+A82B5E284B4270C813276A7319CD5827B3D6F7563F1745AC5326D8DE2CE6EE6A465F72E6
+4AA972D7D16E510693A2F17A0DD0CB9C2410F632932FCC77F097E4590EBA63C738F1B09E
+90738EF0B9805190F65E0D5FCFF50C957510619F5482C57FC137EF2F8FA83723C525A6C7
+85EB85B14A22BE60BABD18590BDAD87F9A109118FA69A269F14483E57CF4990358F0B788
+F8A0B515D3E941A6D27DB5483F5376ECDDF7440C5481CEEEE1509D30BF9C292C4E3F1D21
+C3343D8A7364D012632DB251B96352470B07AE8EE0BA1C353962352D63581A306BE120CE
+31E15269D157D5705708DB87D07994E9B37726D662A4F1A4C4D9B8ACF66D83A179B1E1FC
+4AFEDBDE4670AADB2F22686C5F38F237814F1FF4B1DF0BFC6ABDB98F73041E419EBB5483
+DD1CFCA29B81CF5410DCDFCF3C26347126EAC2E9EE4C05B796B2FC1D7B3C0C1974E3E206
+736F83A86A6D291381BDA7719E558D3F7A346C86DAAD88154CEA8A6C6BFF8FD0F78164C5
+5066A46F2B70FD4149B211A0020C92A168C6D4A168CA62E801FAC32D99C6D7BB4B5DD937
+439FFCE4D598FCEC5A63AECED84C8E66D0DDD78832B08BB0A05609F220F7ABEE3AF32D87
+4054A9ADE8D769AE2F42E76ECF56186BD1F4BF5F676F1AD699199EC11123F7BBC49BFFBA
+E7A17013143CB5CDD2CB4BA1B50E89EBDD645BCC0126DF1E175F63FD1E50CA6990D9435C
+F699B225B8EB35941C0AC12214C9FF0590B0DD79D2A28829D016C58BF77F1CAA52A1F256
+5EA0BC93B9A35C40EC353C2B591ABC463BD8170611B2F50E7A4E1A05A4A13A58A660177D
+69218F396EC538A6CDB746570FFE6B10746CFEAF9C9120F45E2F0B9C023E5FAC4A46735D
+F5C56ECDE2BF0ED9317CA5DB60AC14916C8057FA9F35A15072A79463D7421A82F6CF6633
+2BB5FD913234643E33AC20FA45DFAFC7BA030F789B72FF5C138731D481905C0EC8EF0E06
+A2C7C6662221E140EB2344C8672792B695B6DD2704FE03C16CF47CAA23E27407237491A2
+39711B964F5C594D04D3389E57179FFD538A5A8826314204AE9B2CDCAAF9083AEFBC3CE3
+4446821EBF8818DBF9E434B60463C25687DA630522AE7040A2F85E8878E63E6A9A091325
+A74633477993BD360E19449DB8C0B4B0FD59A3DE21A914AC41589F61A1E0F411917E4650
+2BCE796947C6A92D32FCC9F15A485A1C6CBE7190A9AF22A2A774B618798FC5D264AC42D5
+F68D2074B1D27C23C7B8617B2BC6F9BE09BC8A725DE6A53AE30CA4C04868ED18E7E960CC
+BEC08EAEBA79F3BD4FAED1CFB4FD862C1CF0DBF5AEE1F710374FE992D316F17841FD9018
+75BB9159A6A6B2CE0ABBD0E282EFEB5D50C2046D34980E35860EAC45D5E0FA5FE2BD3157
+0CE59CFDCE3AB27C640B7D4CE03CCF9CC57EEF8B01EC524749F2C5470B7A8A42EBEBD64C
+3310D455D78ED0D84D0E6A82382776242918D7F2C1D12754D6DAB938522D04EE4032086D
+BC5D64588934EDFEE8C194FAF4FCD97C8856049BCC920E2B70C7F4FFDE6CFE80F279F11F
+B513B63BAC5D10597F36CCF6295803F3D19BC53A08B144355B2717A79A6632066FC1B5B3
+9561E229BCD29AD04DD2BFCB4CD0EFB33630FA4EEDDC37B6006A049F7CC96299F5AAD49B
+D7B0EC82E1369F11C64074893F8AE715DC9007F2D4A026F192EA529EF183B396525AC390
+9B233D4578506EE744EC50557BEBD059CFCF6EAAA29935E9CB1C4041F1C1D2436051FCAB
+4CDEE0231D585E856397054FD6775FE2577A7528D484A464DAB6A70D800BD79E34FF447C
+80E3FFEAF6BA470AF1DFB20F3EB489C96FA4BDFDC1B7391028AEBE9C6FB2B84266D347C9
+961503E98FDBB0DD4732C590E5730BE96EFCABF5C289A1E6C1673B19F38E26B9C55A40ED
+03D44B22652DDCB4F44A39E307D0180B3402CD5C73AD8C8919BDE0E8BD04F3F746412D9C
+ABAAB437DDD66EE38A430942B1B8926844D52BDBF6A7C6BF92DD3775283D1D4179DDA613
+8C1E457AE16A60686E736726F765F6AD325581295392980F56A273286E8853CCFADA415A
+787CABC5D6B60FBDB3051486A7801FDCD823DFF43DE5B71E160FCC1C7872E38499037E93
+D67200DF8D837B23716F6C4917D2496F1595460D5F82B84D717BCDA0840B5691D75BCA11
+AC00A61A645169C1D5C233869F04B4493996D66F85E95AB410650B815F79EE50EE5F286E
+A2745005F41D41F8E562AAC3BA126F0B933D6EE72FDD388EEE23243F6D60D04C0242355B
+C99C40A67ED1EB76095A5C340CA9DC79456CF47D9F891C6E3ADBAF2695B95C1560DFB589
+E875F2616FC43458C411751A6C106A852EBFA298E9F179B6ABB98A5DA4E12DBD7B5A3943
+AE31D2CF9740CFA9FCD6755D8F8B295065A7B4D7153E2A2498052C8E05E59C50B78FAD3C
+2960257F783D975D7C886A6E45A50C7EC5139AEB3413D1FD5CCBCF9D9E7F4D67375412B6
+FAB242B27F33F4B8C8B791BECE30E474DB44F1AC9EDF5019EAD8AA5807D81DBE4616D65E
+5F2059571F173D0DFA60E125776195CB552C71B705AF5B5D489851E4CBA3184770BA8745
+B7F9DF9C4D8B5B5089C411CEEFB424F77245F493D29E20788A255A49F65646EA13C726F4
+81AB1B9D3A7440E8808964DC49DD5E31EB066154C198A950178DFBC433873295B6DD2704
+F0019C8D3DEB35A63CC14C6F5D0CFD8FE7A614EC8189F80CF4D34DA0488BD89972EBF801
+4B78ED844219C7B6ABD6A4DB1DBF02525A10C51F887F5A4386F7E1B498F387CC62A19A2E
+C12A72B9B93CBF00EE66EA896A64654C334BD2CEC1C6AC78A4E0774F9354DC3A16178283
+FAB08CA02E401DD536679AB9425BDBAC9FEA3EF3D4DC478F08293BE43D49C925E403DDCD
+1511B0C7B6286B1D9C7B6BA7DFF9FB6595EA32D0D5A2DC41052C2D05B5053419132DD58E
+B1BB7C6A79231CED57FD4CD20CA0529B4EBA2D91A17FDF8D8C51DD234B3F8CD8526D6807
+B61551CD70D1405F7A5081E0BAAF6CB15322B3CD58CA86E647D78A14188B2AB7740402F8
+ABF941279BEBCA23EBCF64AD4C24E57358DECFA3A025BA2A0CCA25A4B65EBC3AFAA15A3E
+77A9B3355FFE11A7BD3F0FEA04C968FF101D3CB4F9A2F204ADA881D5FC1640E312D4B69E
+95EF93B95D6FBFD7861AAA85092B91D993D11E7DB0C658AEDAC741A4D939071128BC48D6
+B9ED909CA1CDAEF5459865F119F31DBE903D6B3F956746CC1358330B29ABD85843FF7C8C
+2743740C2B75EAE1ECC6D6DCE07A9C4B9BCD596E58DBCCEEFA71CE3D511887FFC5189B39
+20C3F9106ADF3E8BE7AB57953E382D49DBA53CE75B4891B6F1F4A4726726049C168E92DC
+9A67370A1B3E09AD841045A286DB8C3BE21FD2F6DE4D9FBF21D8818995C03041CAAFC205
+C828F842BD63C754CDDB7FBC0E37DC03336617FE2C13C88FDAA283EB3C0FB854314DBB96
+4A42587BF9708EF0B256569D0044696D15736C925914BDAC7F7A4C6AE6BEEB314A57DB88
+41787241F4ED758CC2EA6B4FC41F757AB0E412F2F9F5201A1FC7B1229F6C2E764EC597CA
+FFB8B45705B85EB0D96E6999F5638ADF326D7C6D19F25A3D6BE607B9AFB3D375A8E2785D
+6AE74CC0129C4A05058DF0086E907E8409A5B9AF3FEB0A6DFAC34CAE2B664148476D64BD
+52F8BC600DE25BE2EC5A4537C4A549790F949A060A97F3C69912ADC2812D1B7DD968CFA2
+B9EACD20148CC940594166BF6580C6D52F820E5392B705B79F8DDFA997FB2F6AC99F192D
+4B71E5CF768F1E810D5F0BDA566A237BFEE8ED5FD58B585872422F005C0365692F0CA8D2
+5834781CBF0870F0302C59ED043877D0347A79B103CB4F8B786BDCE8DC26D2C34562BC03
+4A13F30B8E663F6551A6835C9D8AAB8E1160017B201F5F9CBFCA2CBD78F972A4FFDFEB71
+B14732F293EBDEA5AA66F0E56FF3BFCB0001D5EFEC55BD900B738522E3C641CA6359EC1A
+9203AB93FB5F4BEFFEFBDF2971B6C8F2F25E1295AE35DDB99D40B124F51A05643B3B3441
+89AA08723580D7E4B5F76F55750F6BE2F876C1C3AB5E3225CD283C97672ACB123E66A155
+F2689E79390D78BB7413DDEA87007DFE2A79EC035DA5353EAA63C277751F0FFF2763FF87
+525C0D82617DA05AF4F3A27299417C042E1826B70DE38337BB983D00F75B3A37EFBE8188
+BEF5D060259759E103D7FD90D954356F0AA988C23D1DD83D6B0C446A15D93C40064C0904
+63460F706DD2A904E993939AE8BF9E9C1B6D199B2E9EC7509903AE3E1AF11490F350D1F7
+7D0F9B720FAF81B932E086AAFDE4A0DCB8A29D22529CCFF613B15E3D9EB92BA902E77DE2
+B4CD1A5CC0F17F57B7231E0FB91D37B141476A88A27874685FAD482EB14B53CF7C1F5654
+9D6E9C27566CB08AF068307A5EF33ED74AC58708A6059D86D1E717F0F6EA8A7D3D06C181
+C1B1474E0C550003B1500A736AC9336DE04D724DDEB4C1D2876EF4319F8E8220126A5414
+B7AB0D870DA568D454AC3102643C1572663020EC4C50F45EBCF1D1C8185A9224EBDB81A5
+CFE3EFA7FA9A803294B895E00DF966CB74B220B9C0C0300A1D3804EDE6218F36E066D4C0
+89C9FFB0430BB45CCE70961F9D0463641299EDB9C23A103A37098D8AADCC4A58CFB91B72
+A8452F7DB1FDC328F842BD63C792FA87E7D16799A92BE6C3A8BB5F2108C6353200E5B115
+8C7AE63EA8C02016BD025E9CC986C05CB8487AA1EAAF16D190C8F50B5EEC2B2812BEB474
+0232D7A1F4A2B28EDFA43D2EB1D7523F9B28000D2B352CBB970ED3D4BB2511BC1904CE57
+453E89DC61158B6D40B6F9CBD3A3D40F89E3243C53002BD49BCA63F20C4033195A7BE2A4
+D8A8E58351AD73EB24A727DF54D4205E39DEDFE07CEC575CC6A596B502D91864CA88AE52
+BE3B608142D7370BC661AD17CBDDC61A782AA434FDAABEF82E9B5846BC431012D31884B1
+FB6DBA5285D7EBFA0D776EFF8CE49E9B566E2A67DBE9739FFA00094599A4742FB8A67A84
+3DC6C11B358FEF5EAB21EA648661E0CD78EC55164B8BF28F282A1381404A393EB51A0641
+52171E900B91A00B499C3C95BBD7A3175AD34BB71BDBED114C52C2375550588FB514F8CD
+F6D864DEDB56AAEF1DF723F127C9F97189245D1AD9AB051F8BBD5D5E6B4A52D1ECFCC7A9
+B214C02ABD4EEA12A5EFE1A38B45960496A6EA81DAC779BAAA7CAF6E98F79720F89E9881
+16F82A38B60372D54A1F7A094FC0FA7940F403C670E2470AD06A2117D00F1A83102041A5
+0CFBBC661612BC929C0D8DED34A9233AF1B83E8B84C944B7A9965A72456FA5B47AF8DB04
+3C0034670486A6A897AC23D0ADFF5C4B88A8F30D3012263124E0EE7CF34B9701AF571363
+C568FAA0CE4E3ACF2EBCE2AABB6AE57A06687E03E89E00F02C35DD02979C4F9FE38B2070
+BA24FF692AE66821E4F583461AF57AE9C1ABFF61D794F485720DC90A73A37D2AF971D0C0
+20403BCD692276BC61A7478E5A7480CE4E9B577E1B1FCA3A704937AAA570C4CF353D2C34
+E80B60192FD5EE1856CE28F270B36710F5C6CC6436E51DCE0DAE8753534B3E546363A80E
+7075055D7AD9954DFA990BA00B7C74919D82CA42DCA9B7CEDCEFC9FCDCB7A24872B629D5
+0434D2C6B020B501089DE051CE0009326221A83DFD33BDAFA9A96DA64CF2B7A02D299F82
+863C5EE961059A557F581D3617433C6B7B69F03DDEBAB2B7567F63435769FE224EC07DC2
+A4923560744C77008B7F5A3B28C632726486A5F3F40E7A92DF917B2666001B03B7135D7A
+92E03F4ED5E6B62B09EC017D57E518D588103F5BDD1B22DCE53737C9DD12E2F48F13400E
+1349182BA2EC437999F768191529EEEA0267638AE4A0BD278FE029E35D7CF1225E55DEF7
+373DABA2B9D198B68FCE74078F08A313ED76568723571E6824A2474A451847DFCD198896
+FEA2249153586646B5ACE95006CFF480E00D8DF8A95C7C765B5E2E7FA2384066915AD646
+0166FEDDDA45B3158750FA879AC7E2CCC6C63CDE831903B7C5191D73C835DA957901A178
+3CD4DC99FE33D5F10E59269BC610304E4EE2BC89B83B54D88971D8512B493D63305FB53D
+A3C066C23E3BBD6164259211A964EB1B58B14E5AD4644A55CE56E2DA71AD64BEF0C6418E
+3235B67F163B9B686747577850D9CE0A53A2BB72A3CBB54553A998FE9FEC7E7D11E8D8B8
+791A5C0A81809DCE2654A5F4222AE52EA0D0E97FDEDC1AAC475AF4382623A28F34EBD00C
+6A89A039735CB943417D8E746200BD6A0E1BD0F5F9D2796AFA1FAC8CDA16DAEA6E76A171
+5BA4BADEE7C529652657757B2CC2E18D58C2DF1D27B5B7410CDEE8B14D4F33731C099DB1
+F0481FF887AE5257E3A798D693615FC30A1900AD11454100623F8AEB6B929593AB5BC516
+1AF3AC71BC28A8989052AE6034EB79692F213E8FD932FF23B2D068AFA3B37D20013BF059
+D3B679B2F7CC772B775BE1DC233313A91A9AA643E73EE25CF0958D8E26C1A13483AD0727
+8B799F6B1D483159A30199B43FF087CF44B975C58954A40EA29B3983297A4009AA790F3A
+2A04065379C70FD0297AEA0E11F976ACB9000EE45C8C056E5F3C898C443A2089327D9C98
+E3429C02EAB52538098B366C1ED7E551BF177D9A460AAF4FA914B3E31E67333A59BC137A
+C1D46ECFF6450DFA41D64FC8D6398B3B196005E223A92C796D6C907B0583C94EF80B1AEF
+CC6BBA1403A43280604688D4C2A71C09BB11049EFEB759DA5C6A761AE1099051E32344BA
+14C603647B63CFF3497421DD0B338F1DB5F84B6C936783A8DC5E2F347A7E728C27DDBD7E
+ED08FFC0E18B224E01FA9FB705E834E3D2921E65B148D02B9D64687D970B01E6ABAF79D5
+FD382B1426805BFAA7B710ADF2EEBC634879627D1A30F8DD8F84D60CC8A90609612C2E65
+F2987CC8858046FE72C61A11057E14316DA7F6212E8BF5E08E936797E01021DAF66A5994
+3368A90F75B2811EDD7390A0A3E0067B566168300FDF366AB219408E16E0A49C4074A1EE
+6199D43EC40D1396DF6C4811EDEF8A1948F2DA3B3DFAAB21170EA1B96D7FE0CADC0262DA
+59D4240B865E25318CD4A3D9761D8E5F55CA68FACCFD8618BC8EAB67A215009196BC1653
+F308063BF5BC53DF6E896CFD87B44B5FF2A279D5CAFA9AA03459CE6FDBBD1EB4D8AB710D
+6DCF95A36C96F3130DAA40733923C535FD502368DBB780185C36F9F1C972A7D912023593
+FDEC9CF456877D7870B20B559D1AADD297143C32CF9E478BFA35B6
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/tests/makeotfexe_data/input/fealib/ignore_pos.fea b/tests/makeotfexe_data/input/fealib/ignore_pos.fea
new file mode 100644
index 000000000..58e217ed8
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/ignore_pos.fea
@@ -0,0 +1,5 @@
+feature test {
+ ignore pos f [a e] d';
+ ignore pos a d' d;
+ pos [a e n] d' -20;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/include0.fea b/tests/makeotfexe_data/input/fealib/include0.fea
new file mode 100644
index 000000000..8f177e17c
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/include0.fea
@@ -0,0 +1 @@
+I0
diff --git a/tests/makeotfexe_data/input/fealib/language_required.fea b/tests/makeotfexe_data/input/fealib/language_required.fea
new file mode 100644
index 000000000..4ee0fbe46
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/language_required.fea
@@ -0,0 +1,23 @@
+languagesystem latn dflt;
+languagesystem latn DEU;
+languagesystem latn FRA;
+languagesystem latn ITA;
+
+feature hlig {
+ script latn;
+ language DEU exclude_dflt required;
+ sub D E U by D.sc;
+
+ language FRA exclude_dflt;
+ sub F R A by F.sc;
+} hlig;
+
+feature liga {
+ script latn;
+ language ITA exclude_dflt required;
+ sub I T A by I.sc;
+} liga;
+
+feature scmp {
+ sub [a-z] by [A.sc-Z.sc];
+} scmp;
diff --git a/tests/makeotfexe_data/input/fealib/lookup.fea b/tests/makeotfexe_data/input/fealib/lookup.fea
new file mode 100644
index 000000000..ad1fb7b7a
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/lookup.fea
@@ -0,0 +1,24 @@
+# Three features. In the output, they should all point to the same lookup.
+
+lookup SomeLookup {
+ sub f f i by f_f_i;
+ sub f i by f_i;
+} SomeLookup;
+
+feature tst1 {
+ lookup SomeLookup;
+} tst1;
+
+feature tst2 {
+ lookup SomeLookup;
+} tst2;
+
+feature tst3 {
+ lookup EmbeddedLookup {
+ sub A by A.sc;
+ } EmbeddedLookup;
+} tst3;
+
+feature tst4 {
+ lookup EmbeddedLookup;
+} tst4;
diff --git a/tests/makeotfexe_data/input/fealib/lookupflag.fea b/tests/makeotfexe_data/input/fealib/lookupflag.fea
new file mode 100644
index 000000000..0362e7aac
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/lookupflag.fea
@@ -0,0 +1,96 @@
+languagesystem DFLT dflt;
+
+@TOP_MARKS = [acute grave macron];
+markClass [cedilla ogonek] @BOTTOM_MARKS;
+@FRENCH_MARKS = [acute grave cedilla dieresis circumflex];
+@MARKS_WITH_DUPLICATES = [breve caron umlaut breve caron umlaut];
+
+lookup A {
+ lookupflag RightToLeft;
+ pos one 1;
+} A;
+
+lookup B {
+ lookupflag IgnoreBaseGlyphs;
+ pos two 2;
+} B;
+
+lookup C {
+ lookupflag IgnoreLigatures;
+ pos four 4;
+} C;
+
+lookup D {
+ lookupflag 7;
+ pos seven 7;
+} D;
+
+lookup E {
+ lookupflag IgnoreMarks;
+ pos eight 8;
+} E;
+
+lookup F {
+ lookupflag MarkAttachmentType @TOP_MARKS;
+ pos F 1;
+} F;
+
+lookup G {
+ lookupflag MarkAttachmentType @BOTTOM_MARKS;
+ pos G 1;
+} G;
+
+lookup H {
+ lookupflag IgnoreLigatures MarkAttachmentType @TOP_MARKS;
+ pos H 1;
+} H;
+
+lookup I {
+ lookupflag UseMarkFilteringSet @TOP_MARKS;
+ pos I 1;
+} I;
+
+lookup J {
+ # @FRENCH_MARKS overlaps with @TOP_MARKS.
+ # Other than with MarkAttachmentType, the same glyph may appear
+ # in multiple glyphsets for UseMarkFilteringSet. Make sure that
+ # our implementation can handle this.
+ lookupflag UseMarkFilteringSet @FRENCH_MARKS;
+ pos J 1;
+} J;
+
+lookup K {
+ lookupflag IgnoreLigatures UseMarkFilteringSet @TOP_MARKS;
+ pos K 1;
+} K;
+
+lookup L {
+ pos L 1;
+} L;
+
+lookup M {
+ lookupflag UseMarkFilteringSet @MARKS_WITH_DUPLICATES;
+ pos M 1;
+} M;
+
+lookup N {
+ lookupflag MarkAttachmentType @MARKS_WITH_DUPLICATES;
+ pos N 1;
+} N;
+
+feature test {
+ lookup A;
+ lookup B;
+ lookup C;
+ lookup D;
+ lookup E;
+ lookup F;
+ lookup G;
+ lookup H;
+ lookup I;
+ lookup J;
+ lookup K;
+ lookup L;
+ lookup M;
+ lookup N;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/markClass.fea b/tests/makeotfexe_data/input/fealib/markClass.fea
new file mode 100644
index 000000000..855de6fa2
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/markClass.fea
@@ -0,0 +1,12 @@
+languagesystem DFLT dflt;
+
+markClass [acute] @TOP_MARKS;
+
+feature foo {
+ markClass [grave] @TOP_MARKS;
+ markClass cedilla @BOTTOM_MARKS;
+} foo;
+
+feature bar {
+ markClass [dieresis breve] @TOP_MARKS;
+} bar;
diff --git a/tests/makeotfexe_data/input/fealib/mini.fea b/tests/makeotfexe_data/input/fealib/mini.fea
new file mode 100644
index 000000000..9cf4b2f31
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/mini.fea
@@ -0,0 +1,19 @@
+# Example file from OpenType Feature File specification, section 1.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+# Script and language coverage
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+
+# Ligature formation
+feature liga {
+ substitute f i by f_i;
+ substitute f l by f_l;
+} liga;
+
+# Kerning
+feature kern {
+ position A Y -100;
+ position a y -80;
+ position s f' <0 0 10 0> t;
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/multiple_feature_blocks.fea b/tests/makeotfexe_data/input/fealib/multiple_feature_blocks.fea
new file mode 100644
index 000000000..2f9902a60
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/multiple_feature_blocks.fea
@@ -0,0 +1,18 @@
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+languagesystem latn TRK;
+
+feature liga {
+ lookup liga_fl {
+ sub f l by f_l;
+ } liga_fl;
+} liga;
+
+feature liga {
+ lookup liga_fi {
+ sub f i by f_i;
+ } liga_fi;
+
+ script latn;
+ language TRK exclude_dflt;
+} liga;
diff --git a/tests/makeotfexe_data/input/fealib/name.fea b/tests/makeotfexe_data/input/fealib/name.fea
new file mode 100644
index 000000000..e242ca342
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/name.fea
@@ -0,0 +1,14 @@
+table name {
+ nameid 1 "Ignored-1";
+ nameid 2 "Ignored-2";
+ nameid 3 "Ignored-3";
+ nameid 4 "Ignored-4";
+ nameid 5 "Ignored-5";
+ nameid 6 "Ignored-6";
+ nameid 7 3 "Test7";
+ nameid 8 1 "Test8";
+ nameid 9 3 1 0x0409 "Test9";
+ nameid 10 1 "Test10";
+ nameid 11 1 0 0 "Test11";
+} name;
+
diff --git a/tests/makeotfexe_data/input/fealib/omitted_GlyphClassDef.fea b/tests/makeotfexe_data/input/fealib/omitted_GlyphClassDef.fea
new file mode 100644
index 000000000..d580e22ad
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/omitted_GlyphClassDef.fea
@@ -0,0 +1,6 @@
+@BASE = [f i];
+@MARKS = [acute grave];
+
+table GDEF {
+ GlyphClassDef @BASE, , @MARKS, ;
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/size.fea b/tests/makeotfexe_data/input/fealib/size.fea
new file mode 100644
index 000000000..9d1b38091
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/size.fea
@@ -0,0 +1,3 @@
+feature size {
+ parameters 10.0 0 0 0;
+} size;
diff --git a/tests/makeotfexe_data/input/fealib/size2.fea b/tests/makeotfexe_data/input/fealib/size2.fea
new file mode 100644
index 000000000..a5a08a571
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/size2.fea
@@ -0,0 +1,3 @@
+feature size {
+ parameters 10.0 0;
+} size;
diff --git a/tests/makeotfexe_data/input/fealib/spec10.fea b/tests/makeotfexe_data/input/fealib/spec10.fea
new file mode 100644
index 000000000..9d1be0247
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec10.fea
@@ -0,0 +1,12 @@
+# OpenType Feature File specification, section 10.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+anon sbit {
+ /* sbit table specifications */
+ 72 % dpi
+ sizes {
+ 10, 12, 14 source {
+ all "Generic/JGeneric"
+ }
+ }
+} sbit;
diff --git a/tests/makeotfexe_data/input/fealib/spec4h1.fea b/tests/makeotfexe_data/input/fealib/spec4h1.fea
new file mode 100644
index 000000000..c4a9d9ac0
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec4h1.fea
@@ -0,0 +1,63 @@
+# OpenType Feature File specification, section 4.h, example 1.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+languagesystem latn DEU;
+languagesystem latn TRK;
+languagesystem cyrl dflt;
+
+feature smcp {
+ sub [a-z] by [A.sc-Z.sc];
+
+ # Since all the rules in this feature are of the same type, they
+ # will be grouped in a single lookup. Since no script or language
+ # keyword has been specified yet, the lookup will be registered
+ # for this feature under all the language systems.
+} smcp;
+
+feature liga {
+ sub f f by f_f;
+ sub f i by f_i;
+ sub f l by f_l;
+
+ # Since all the rules in this feature are of the same type, they
+ # will be grouped in a single lookup. Since no script or language
+ # keyword has been specified yet, the lookup will be registered
+ # for this feature under all the language systems.
+
+ script latn;
+ language dflt;
+ # lookupflag 0; (implicit)
+ sub c t by c_t;
+ sub c s by c_s;
+
+ # The rules above will be placed in a lookup that is registered
+ # for all the specified languages for the script latn, but not any
+ # other scripts.
+
+ language DEU;
+ # script latn; (stays the same)
+ # lookupflag 0; (stays the same)
+ sub c h by c_h;
+ sub c k by c_k;
+
+ # The rules above will be placed in a lookup that is registered
+ # only under the script latn, language DEU.
+
+ language TRK;
+
+ # This will inherit both the top level default rules - the rules
+ # defined before the first 'script' statement, and the
+ # script-level default rules for 'latn': all the lookups of this
+ # feature defined after the 'script latn' statement, and before
+ # the language DEU statement. If TRK were not named here, it
+ # would not inherit the default rules for the script latn.
+} liga;
+
+feature kern {
+ pos a y -150;
+ # [more pos statements]
+ # All the rules in this feature will be grouped in a single lookup
+ # that is is registered under all the language systems.
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/spec4h2.fea b/tests/makeotfexe_data/input/fealib/spec4h2.fea
new file mode 100644
index 000000000..038480486
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec4h2.fea
@@ -0,0 +1,40 @@
+# OpenType Feature File specification, section 4.h, example 2.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+languagesystem latn DEU;
+languagesystem cyrl dflt;
+languagesystem cyrl SRB;
+languagesystem grek dflt;
+
+feature liga {
+ # start of default rules that are applied under all language systems.
+ lookup HAS_I {
+ sub f f i by f_f_i;
+ sub f i by f_i;
+ } HAS_I;
+
+ lookup NO_I {
+ sub f f l by f_f_l;
+ sub f f by f_f;
+ } NO_I;
+
+ # end of default rules that are applied under all language systems.
+
+ script latn;
+ language dflt;
+ # default lookup for latn included under all languages for the latn script
+ sub f l by f_l;
+
+ language DEU;
+ # default lookups included under the DEU language
+ sub s s by germandbls; # This is also included.
+
+ language TRK exclude_dflt; # default lookups are excluded.
+ lookup NO_I; # Only this lookup is included under the TRK language
+
+ script cyrl;
+ language SRB;
+ sub c t by c_t; # this rule will apply only under script cyrl language SRB.
+} liga;
diff --git a/tests/makeotfexe_data/input/fealib/spec5d1.fea b/tests/makeotfexe_data/input/fealib/spec5d1.fea
new file mode 100644
index 000000000..cf7d76f70
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5d1.fea
@@ -0,0 +1,23 @@
+# OpenType Feature File specification, section 5.d, example 1.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+feature F1 {
+ sub [one one.oldstyle] [slash fraction] [two two.oldstyle] by onehalf;
+} F1;
+
+# Since the OpenType specification does not allow ligature substitutions
+# to be specified on target sequences that contain glyph classes, the
+# implementation software will enumerate all specific glyph sequences
+# if glyph classes are detected in . Thus, the above
+# example produces an identical representation in the font as if all
+# the sequences were manually enumerated by the font editor:
+feature F2 {
+ sub one slash two by onehalf;
+ sub one.oldstyle slash two by onehalf;
+ sub one fraction two by onehalf;
+ sub one.oldstyle fraction two by onehalf;
+ sub one slash two.oldstyle by onehalf;
+ sub one.oldstyle slash two.oldstyle by onehalf;
+ sub one fraction two.oldstyle by onehalf;
+ sub one.oldstyle fraction two.oldstyle by onehalf;
+} F2;
diff --git a/tests/makeotfexe_data/input/fealib/spec5d2.fea b/tests/makeotfexe_data/input/fealib/spec5d2.fea
new file mode 100644
index 000000000..7fd7eabca
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5d2.fea
@@ -0,0 +1,22 @@
+# OpenType Feature File specification, section 5.d, example 2.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+# A contiguous set of ligature rules does not need to be ordered in
+# any particular way by the font editor; the implementation software
+# must do the appropriate sorting.
+
+# So:
+feature F1 {
+ sub f f by f_f;
+ sub f i by f_i;
+ sub f f i by f_f_i;
+ sub o f f i by o_f_f_i;
+} F1;
+
+# will produce an identical representation in the font as:
+feature F2 {
+ sub o f f i by o_f_f_i;
+ sub f f i by f_f_i;
+ sub f f by f_f;
+ sub f i by f_i;
+} F2;
diff --git a/tests/makeotfexe_data/input/fealib/spec5f_ii_1.fea b/tests/makeotfexe_data/input/fealib/spec5f_ii_1.fea
new file mode 100644
index 000000000..2d5c0dfb9
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5f_ii_1.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 5.f.ii, example 1
+# "Specifying exceptions to the Chain Sub rule"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+feature test {
+ ignore sub f [a e] d';
+ ignore sub a d' d;
+ sub [a e n] d' by d.alt;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5f_ii_2.fea b/tests/makeotfexe_data/input/fealib/spec5f_ii_2.fea
new file mode 100644
index 000000000..b20a74c3b
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5f_ii_2.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 5.f.ii, example 2
+# "Specifying exceptions to the Chain Sub rule"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+feature test {
+ @LETTER = [a-z];
+ ignore sub @LETTER f' i';
+ sub f' i' by f_i.begin;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5f_ii_3.fea b/tests/makeotfexe_data/input/fealib/spec5f_ii_3.fea
new file mode 100644
index 000000000..5fd19916e
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5f_ii_3.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 5.f.ii, example 3
+# "Specifying exceptions to the Chain Sub rule"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+feature test {
+ @LETTER = [a-z];
+ ignore sub @LETTER a' n' d', a' n' d' @LETTER;
+ sub a' n' d' by a_n_d;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5f_ii_4.fea b/tests/makeotfexe_data/input/fealib/spec5f_ii_4.fea
new file mode 100644
index 000000000..731a1f643
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5f_ii_4.fea
@@ -0,0 +1,23 @@
+# OpenType Feature File specification, section 5.f.ii, example 4
+# "Specifying exceptions to the Chain Sub rule"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+@LETTER = [A-Z a-z];
+
+feature cswh {
+
+ # --- Glyph classes used in this feature:
+ @BEGINNINGS = [A-N P-Z T_h m];
+ @BEGINNINGS_SWASH = [A.swash-N.swash P.swash-Z.swash T_h.swash m.begin];
+ @ENDINGS = [a e z];
+ @ENDINGS_SWASH = [a.end e.end z.end];
+
+ # --- Beginning-of-word swashes:
+ ignore sub @LETTER @BEGINNINGS';
+ sub @BEGINNINGS' by @BEGINNINGS_SWASH;
+
+ # --- End-of-word swashes:
+ ignore sub @ENDINGS' @LETTER;
+ sub @ENDINGS' by @ENDINGS_SWASH;
+
+} cswh;
diff --git a/tests/makeotfexe_data/input/fealib/spec5fi1.fea b/tests/makeotfexe_data/input/fealib/spec5fi1.fea
new file mode 100644
index 000000000..f5de2dc22
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5fi1.fea
@@ -0,0 +1,20 @@
+# OpenType Feature File specification, section 5.f.i, example 1
+# "Specifying a Chain Sub rule and marking sub-runs"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem latn dflt;
+
+lookup CNTXT_LIGS {
+ sub f i by f_i;
+ sub c t by c_t;
+} CNTXT_LIGS;
+
+lookup CNTXT_SUB {
+ sub n by n.end;
+ sub s by s.end;
+} CNTXT_SUB;
+
+feature test {
+ sub [a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB;
+ sub [a e i o u] c' lookup CNTXT_LIGS t' s' lookup CNTXT_SUB;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5fi2.fea b/tests/makeotfexe_data/input/fealib/spec5fi2.fea
new file mode 100644
index 000000000..d5934606c
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5fi2.fea
@@ -0,0 +1,10 @@
+# OpenType Feature File specification, section 5.f.i, example 2
+# "Specifying a Chain Sub rule and marking sub-runs"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem latn dflt;
+
+feature test {
+ lookupflag 7;
+ sub [a e n] d' by d.alt;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5fi3.fea b/tests/makeotfexe_data/input/fealib/spec5fi3.fea
new file mode 100644
index 000000000..e47a6f8aa
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5fi3.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 5.f.i, example 3
+# "Specifying a Chain Sub rule and marking sub-runs"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem latn dflt;
+
+feature test {
+ sub [A-Z] [A.sc-Z.sc]' by [a-z];
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5fi4.fea b/tests/makeotfexe_data/input/fealib/spec5fi4.fea
new file mode 100644
index 000000000..845c56052
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5fi4.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 5.f.i, example 4
+# "Specifying a Chain Sub rule and marking sub-runs"
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem latn dflt;
+
+feature test {
+ sub [e e.begin]' t' c by ampersand;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec5h1.fea b/tests/makeotfexe_data/input/fealib/spec5h1.fea
new file mode 100644
index 000000000..6a28cbebe
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec5h1.fea
@@ -0,0 +1,8 @@
+# OpenType Feature File specification, section 5.h, example 1.
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+
+feature test {
+ reversesub [a e n] d' by d.alt;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6b_ii.fea b/tests/makeotfexe_data/input/fealib/spec6b_ii.fea
new file mode 100644
index 000000000..59fc7d538
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6b_ii.fea
@@ -0,0 +1,12 @@
+# OpenType Feature File specification, section 6.b.ii:
+# [GPOS LookupType 2] Enumerating pairs
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+@Y_LC = [y yacute ydieresis];
+@SMALL_PUNC = [comma semicolon period];
+
+feature kern {
+ enum pos @Y_LC semicolon -80; # specific pairs
+ pos f quoteright 30; # specific pair
+ pos @Y_LC @SMALL_PUNC -100; # class pair
+} kern;
diff --git a/tests/makeotfexe_data/input/fealib/spec6d2.fea b/tests/makeotfexe_data/input/fealib/spec6d2.fea
new file mode 100644
index 000000000..04986260a
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6d2.fea
@@ -0,0 +1,14 @@
+# OpenType Feature File specification, section 6.d, example 1:
+# [GPOS LookupType 4] Mark-to-Base attachment positioning
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+
+markClass [acute grave] @TOP_MARKS;
+markClass [dieresis umlaut] @TOP_MARKS;
+markClass [cedilla] @BOTTOM_MARKS;
+
+feature test {
+ pos base [e o] mark @TOP_MARKS mark @BOTTOM_MARKS;
+ position base [a u] mark @TOP_MARKS mark @BOTTOM_MARKS;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6e.fea b/tests/makeotfexe_data/input/fealib/spec6e.fea
new file mode 100644
index 000000000..ed956c8f3
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6e.fea
@@ -0,0 +1,10 @@
+languagesystem DFLT dflt;
+
+markClass sukun @TOP_MARKS;
+markClass kasratan @BOTTOM_MARKS;
+
+feature test {
+ pos ligature lam_meem_jeem mark @TOP_MARKS # mark above lam
+ ligComponent mark @BOTTOM_MARKS # mark below meem
+ ligComponent ; # jeem has no marks
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6f.fea b/tests/makeotfexe_data/input/fealib/spec6f.fea
new file mode 100644
index 000000000..8d32008cb
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6f.fea
@@ -0,0 +1,6 @@
+languagesystem DFLT dflt;
+
+feature test {
+ markClass damma @MARK_CLASS_1;
+ pos mark hamza mark @MARK_CLASS_1;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6h_ii.fea b/tests/makeotfexe_data/input/fealib/spec6h_ii.fea
new file mode 100644
index 000000000..36a1f032f
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6h_ii.fea
@@ -0,0 +1,21 @@
+# OpenType Feature File specification, section 6.h.ii:
+# Specifying Contextual Positioning with explicit lookup references
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+
+markClass [acute grave] @ALL_MARKS;
+
+lookup CNTXT_PAIR_POS {
+ pos T o -10;
+ pos T c -12;
+} CNTXT_PAIR_POS;
+
+lookup CNTXT_MARK_TO_BASE {
+ pos base o mark @ALL_MARKS;
+ pos base c mark @ALL_MARKS;
+} CNTXT_MARK_TO_BASE;
+
+feature test {
+ pos T' lookup CNTXT_PAIR_POS [o c]' @ALL_MARKS' lookup CNTXT_MARK_TO_BASE;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6h_iii_1.fea b/tests/makeotfexe_data/input/fealib/spec6h_iii_1.fea
new file mode 100644
index 000000000..276fa2f69
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6h_iii_1.fea
@@ -0,0 +1,9 @@
+# OpenType Feature File specification, section 6.h.iii, example 1:
+# Specifying Contextual Positioning with in-line single positioning rules
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+languagesystem DFLT dflt;
+
+feature test {
+ pos [quoteleft quotedblleft] [Y T]' <0 0 20 0> [quoteright quotedblright];
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec6h_iii_3d.fea b/tests/makeotfexe_data/input/fealib/spec6h_iii_3d.fea
new file mode 100644
index 000000000..7b7d8e9f3
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec6h_iii_3d.fea
@@ -0,0 +1,7 @@
+# OpenType Feature File specification, section 6.h.iii, example 3d:
+# Specifying Contextual Positioning with in-line single positioning rules
+# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
+
+feature test {
+ pos L' quoteright' -150;
+} test;
diff --git a/tests/makeotfexe_data/input/fealib/spec8a.fea b/tests/makeotfexe_data/input/fealib/spec8a.fea
new file mode 100644
index 000000000..b4d7dd299
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec8a.fea
@@ -0,0 +1,21 @@
+languagesystem DFLT dflt;
+languagesystem latn dflt;
+languagesystem latn TRK;
+languagesystem cyrl dflt;
+
+feature aalt {
+ feature salt;
+ feature smcp;
+ sub d by d.alt;
+} aalt;
+
+feature smcp {
+ sub [a-c] by [A.sc-C.sc];
+ sub f i by f_i; # not considered for aalt
+} smcp;
+
+feature salt {
+ sub a from [a.alt1 a.alt2 a.alt3];
+ sub e [c d e]' f by [c.mid d.mid e.mid];
+ sub b by b.alt;
+} salt;
diff --git a/tests/makeotfexe_data/input/fealib/spec8b.fea b/tests/makeotfexe_data/input/fealib/spec8b.fea
new file mode 100644
index 000000000..af7925691
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec8b.fea
@@ -0,0 +1,8 @@
+feature size {
+ parameters 10.0 3 80 139;
+# 10.0 - design size, 3 - subfamily identifier, 80 - range start (exclusive, decipoints)
+# 139 - range end (inclusive, decipoints)
+ sizemenuname "Win MinionPro Size Name";
+ sizemenuname 1 "Mac MinionPro Size Name";
+ sizemenuname 1 21 0 "Mac MinionPro Size Name";
+} size;
diff --git a/tests/makeotfexe_data/input/fealib/spec8c.fea b/tests/makeotfexe_data/input/fealib/spec8c.fea
new file mode 100644
index 000000000..b473fe569
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec8c.fea
@@ -0,0 +1,12 @@
+feature ss01 {
+ featureNames {
+ name "Feature description for MS Platform, script Unicode, language English";
+# With no platform ID, script ID, or language ID specified, the implementation assumes (3,1,0x409).
+ name 3 1 0x411 "Feature description for MS Platform, script Unicode, language Japanese";
+ name 1 "Feature description for Apple Platform, script Roman, language unspecified";
+# With only the platform ID specified, the implementation assumes script and language = Latin. For Apple this is (1,0,0).
+ name 1 1 12 "Feature description for Apple Platform, script Japanese, language Japanese";
+ };
+# --- rules for this feature ---
+ sub A by B;
+} ss01;
diff --git a/tests/makeotfexe_data/input/fealib/spec8d.fea b/tests/makeotfexe_data/input/fealib/spec8d.fea
new file mode 100644
index 000000000..3f8dba800
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec8d.fea
@@ -0,0 +1,45 @@
+# The cvParameters block must precede any of the rules in the feature.
+# The ParamUILabelNameID entry may be omitted or repeated as often as needed.
+# The other NameID types may be omitted, or defined only once.
+# The NameID entries must be specified in the order listed below.
+
+# Following the set of NameID entries, a series of 24-bit Unicode values may be specified.
+# These provide Unicode values for the base glyphs referenced by the feature.
+# The developer may specify none, some, or all of the Unicode values for the base glyphs.
+# The Unicode value may be written with either decimal or hexadecimal notation.
+# The value must be preceded by '0x' if it is a hexadecimal value.
+
+# NOTE: The ParamUILabelNameID entries are used when one base glyph is mapped to more than
+# one variant; the font designer may then specify one ParamUILabelNameID for each variant, in
+# order to uniquely describe that variant. If any ParamUILabelNameID entries are specified,
+# the number of ParamUILabelNameID entries must match the number of variants for each base
+# glyph. If the Character Variant feature specifies more than one base glyph, then the set
+# of NameID entries in the parameter block will be used for each base glyph and its variants.
+feature cv01 {
+ cvParameters {
+ FeatUILabelNameID {
+ name 3 1 0x0409 "uilabel simple a"; # English US
+ name 1 0 0 "uilabel simple a"; # Mac English
+ };
+ FeatUITooltipTextNameID {
+ name 3 1 0x0409 "tool tip simple a"; # English US
+ name 1 0 0 "tool tip simple a"; # Mac English
+ };
+ SampleTextNameID {
+ name 3 1 0x0409 "sample text simple a"; # English US
+ name 1 0 0 "sample text simple a"; # Mac English
+ };
+ ParamUILabelNameID {
+ name 3 1 0x0409 "param1 text simple a"; # English US
+ name 1 0 0 "param1 text simple a"; # Mac English
+ };
+ ParamUILabelNameID {
+ name 3 1 0x0409 "param2 text simple a"; # English US
+ name 1 0 0 "param2 text simple a"; # Mac English
+ };
+ Character 10;
+ Character 0x5DDE;
+ };
+# --- rules for this feature ---
+ sub A by B;
+} cv01;
diff --git a/tests/makeotfexe_data/input/fealib/spec9a.fea b/tests/makeotfexe_data/input/fealib/spec9a.fea
new file mode 100644
index 000000000..84cca571d
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9a.fea
@@ -0,0 +1,4 @@
+table BASE {
+ HorizAxis.BaseTagList ideo romn;
+ HorizAxis.BaseScriptList latn romn -120 0, cyrl romn -120 0, grek romn -120 0, hani ideo -120 0, kana ideo -120 0, hang ideo -120 0;
+} BASE;
diff --git a/tests/makeotfexe_data/input/fealib/spec9b.fea b/tests/makeotfexe_data/input/fealib/spec9b.fea
new file mode 100644
index 000000000..c72d3f030
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9b.fea
@@ -0,0 +1,13 @@
+@BASE = [f i];
+@LIGATURES = [c_s c_t f_i f_f_i s_t];
+@MARKS = [acute grave];
+@COMPONENT = [noon.final noon.initial];
+
+table GDEF {
+ GlyphClassDef @BASE, @LIGATURES, @MARKS, @COMPONENT;
+ Attach noon.final 5;
+ Attach noon.initial 4;
+ LigatureCaretByPos f_i 400 380;
+ LigatureCaretByPos [c_t s_t] 500;
+ LigatureCaretByIndex f_f_i 23 46;
+} GDEF;
diff --git a/tests/makeotfexe_data/input/fealib/spec9c1.fea b/tests/makeotfexe_data/input/fealib/spec9c1.fea
new file mode 100644
index 000000000..01cd6084f
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9c1.fea
@@ -0,0 +1,3 @@
+table head {
+ FontRevision 1.1;
+} head;
diff --git a/tests/makeotfexe_data/input/fealib/spec9c2.fea b/tests/makeotfexe_data/input/fealib/spec9c2.fea
new file mode 100644
index 000000000..333fa1674
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9c2.fea
@@ -0,0 +1,3 @@
+table head {
+ FontRevision 1.001;
+} head;
diff --git a/tests/makeotfexe_data/input/fealib/spec9c3.fea b/tests/makeotfexe_data/input/fealib/spec9c3.fea
new file mode 100644
index 000000000..e9433a872
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9c3.fea
@@ -0,0 +1,3 @@
+table head {
+ FontRevision 1.500;
+} head;
diff --git a/tests/makeotfexe_data/input/fealib/spec9d.fea b/tests/makeotfexe_data/input/fealib/spec9d.fea
new file mode 100644
index 000000000..231e7bd3b
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9d.fea
@@ -0,0 +1,6 @@
+table hhea {
+ CaretOffset -50;
+ Ascender 800;
+ Descender 200;
+ LineGap 200;
+} hhea;
diff --git a/tests/makeotfexe_data/input/fealib/spec9e.fea b/tests/makeotfexe_data/input/fealib/spec9e.fea
new file mode 100644
index 000000000..58f59e90f
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9e.fea
@@ -0,0 +1,4 @@
+table name {
+ nameid 9 "Joachim M\00fcller-Lanc\00e9"; # Windows (Unicode)
+ nameid 9 1 "Joachim M\9fller-Lanc\8e"; # Macintosh (Mac Roman)
+} name;
diff --git a/tests/makeotfexe_data/input/fealib/spec9f.fea b/tests/makeotfexe_data/input/fealib/spec9f.fea
new file mode 100644
index 000000000..90cf6d1e4
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9f.fea
@@ -0,0 +1,19 @@
+table OS/2 {
+ FSType 4;
+ Panose 2 15 0 0 2 2 8 2 9 4;
+ TypoAscender 800;
+ TypoDescender -200; # Note that TypoDescender is negative for descent below the baseline.
+ winAscent 832;
+ winDescent 321; # Note that winDescent is positive for descent below the baseline.
+ UnicodeRange 0 1 9 55 59 60;
+# 0 - Basic Latin, 1 - Latin-1 Supplement
+# 9 - Cyrillic, 55 - CJK Compatibility
+# 59 - CJK Unified Ideographs, 60 - Private Use Area
+ CodePageRange 1252 1251 932;
+# 1252 - Latin 1, 1251 - Cyrllic, 932 - JIS/Japan
+ XHeight 400;
+ CapHeight 600;
+ WeightClass 800;
+ WidthClass 3;
+ Vendor "ADBE";
+} OS/2;
diff --git a/tests/makeotfexe_data/input/fealib/spec9g.fea b/tests/makeotfexe_data/input/fealib/spec9g.fea
new file mode 100644
index 000000000..8db9e9712
--- /dev/null
+++ b/tests/makeotfexe_data/input/fealib/spec9g.fea
@@ -0,0 +1,8 @@
+# hack to force makeotfexe to generate vhea table
+feature vrt2 { sub a by a; } vrt2;
+
+table vhea {
+ VertTypoAscender 500;
+ VertTypoDescender -500;
+ VertTypoLineGap 1000;
+} vhea;
diff --git a/tests/makeotfexe_test.py b/tests/makeotfexe_test.py
index 491123a26..e5f5591d6 100644
--- a/tests/makeotfexe_test.py
+++ b/tests/makeotfexe_test.py
@@ -487,3 +487,77 @@ def test_infinite_loop_with_dflt_lookups_bug965():
'