package com.ochafik.lang.jnaerator; import static com.ochafik.lang.jnaerator.parser.ElementsHelper.typeRef; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.ochafik.lang.jnaerator.parser.Declarator; import com.ochafik.lang.jnaerator.parser.Element; import com.ochafik.lang.jnaerator.parser.Modifier; import com.ochafik.lang.jnaerator.parser.ModifierType; import com.ochafik.lang.jnaerator.parser.Scanner; import com.ochafik.lang.jnaerator.parser.TypeRef; import com.ochafik.lang.jnaerator.parser.TypeRef.SimpleTypeRef; import com.nativelibs4java.jalico.Pair; public class UniversalReconciliator { static class DefSeq { List<SimpleTypeRef> simpleTypeRefs = new ArrayList<SimpleTypeRef>(); // List<Identifier> identifiers = new ArrayList<Identifier>(); List<Declarator> declarators = new ArrayList<Declarator>(); boolean matches(DefSeq o) { int n = declarators.size(); if (n != declarators.size()) { return false; } if (simpleTypeRefs.size() != o.simpleTypeRefs.size()) { return false; } for (int i = 0; i < n; i++) { Declarator id = declarators.get(i), oid = declarators.get(i); if (!id.toString().equals(oid.toString())) { return false; } } return true; } } DefSeq extractDefSeq(Element tr) { final DefSeq ret = new DefSeq(); tr.accept(new Scanner() { @Override public void visitDeclarator(Declarator declarator) { super.visitDeclarator(declarator); ret.declarators.add(declarator); } // public void visitIdentifier(Identifier i) { // super.visitIdentifier(i); // ret.identifiers.add(i); // } @Override public void visitSimpleTypeRef(SimpleTypeRef simpleTypeRef) { super.visitSimpleTypeRef(simpleTypeRef); ret.simpleTypeRefs.add(simpleTypeRef); } }); return ret; } public static class ReconciliationException extends Exception { private static final long serialVersionUID = -8197343041734256268L; public ReconciliationException(Element t1, Element t2, Element reason1, Element reason2) { this(t1, t2, "\"" + reason1 + "\" and \"" + reason2 + "\" cannot be matched"); } public ReconciliationException(Element t1, Element t2, String reason) { super("Types \"" + t1 + "\" and \"" + t2 + "\" could not be reconciliated" + (reason == null ? "" : ". Reason = " + reason)); } } public Element reconciliate32bitsAnd64bits(Element tr32, Element tr64) throws ReconciliationException { if (tr32 == null && tr64 == null) { return null; } if ((tr32 == null) != (tr64 == null)) { if (tr32 == null && tr64.toString().matches("id") || tr64 == null && tr32.toString().equals("id")) { return typeRef("id"); } throw new ReconciliationException(tr32, tr64, null); } tr32 = tr32.clone(); DefSeq s32 = extractDefSeq(tr32), s64 = extractDefSeq(tr64); if (!s32.matches(s64)) { throw new ReconciliationException(tr32, tr64, null); } int n = s32.simpleTypeRefs.size(); for (int i = 0; i < n; i++) { TypeRef.SimpleTypeRef t32 = s32.simpleTypeRefs.get(i), t64 = s64.simpleTypeRefs.get(i); if (t32.toString().equals(t64.toString())) { continue; } TypeRef tr = reconciliateSimple32bitsAnd64bits(t32, t64); if (tr == null) { throw new ReconciliationException(tr32, tr64, t32, t64); } if (t32 == tr32) { tr32 = tr; } else { t32.replaceBy(tr); } } // TODO Auto-generated method stub return tr32; } static Map<Pair<String, String>, TypeRef> predefined32_64Reconciliations = new LinkedHashMap<Pair<String, String>, TypeRef>(); static { defRecon("float", "double", typeRef("CGFloat")); defRecon("long", "long long", typeRef("long")); defRecon("int", "long long", typeRef("NSInteger")); defRecon("int", "unsigned long long", typeRef("NSInteger")); defRecon("int", "signed long long", typeRef("NSInteger")); defRecon("long", "unsigned long long", typeRef("NSInteger")); defRecon("long", "signed long long", typeRef("NSInteger")); defRecon("unsigned long", "unsigned long long", typeRef("long").addModifiers(ModifierType.Unsigned)); defRecon("unsigned int", "unsigned long long", typeRef("NSUInteger"));//int").addModifiers(ModifierType.Unsigned)); defRecon("unsigned long", "unsigned int", typeRef("int").addModifiers(ModifierType.Unsigned)); defRecon("signed long", "signed int", typeRef("int").addModifiers(ModifierType.Signed)); defRecon("long", "int", typeRef("int")); defRecon("int", "unsigned int", typeRef("int")); defRecon("signed long", "signed long long", typeRef("long").addModifiers(ModifierType.Signed)); defRecon("signed int", "signed long long", typeRef("NSInteger"));//int").addModifiers(ModifierType.Signed)); } static void defRecon(String s32, String s64, TypeRef sRecon) { predefined32_64Reconciliations.put(new Pair<String, String>(s32, s64), sRecon); } /*static TypeRef cleanClone(TypeRef t) { t = t.clone(); List<Modifier> mods = new ArrayList<Modifier>(t.getModifiers()); mods.remove(ModifierType.Signed); mods.remove(ModifierType.Unsigned); t.setModifiers(mods); return t; }*/ public static TypeRef reconciliateSimple32bitsAnd64bits(TypeRef t32, TypeRef t64) { TypeRef recon = predefined32_64Reconciliations.get(new Pair<String, String>(t32.toString(), t64.toString())); /*if (recon == null) { TypeRef tt32 = cleanClone(t32), tt64 = cleanClone(t64); if (tt32.toString().equals(t64)) return tt32; recon = predefined32_64Reconciliations.get(new Pair<String, String>(tt32.toString(), tt64.toString())); }*/ return recon == null ? null : recon.clone(); } }