public List<Define> reorderDefines(Collection<Define> defines) {
    List<Define> reordered = new ArrayList<Define>(defines.size());
    HashSet<Identifier> added = new HashSet<Identifier>(), all = new HashSet<Identifier>();

    Map<String, Pair<Define, Set<Identifier>>> pending =
        new HashMap<String, Pair<Define, Set<Identifier>>>();
    for (Define define : defines) {
      Set<Identifier> dependencies = new TreeSet<Identifier>();
      computeVariablesDependencies(define.getValue(), dependencies);
      all.add(ident(define.getName()));
      if (dependencies.isEmpty()) {
        reordered.add(define);
        added.add(ident(define.getName()));
      } else {
        pending.put(define.getName(), new Pair<Define, Set<Identifier>>(define, dependencies));
      }
    }

    boolean progressed;
    do {
      progressed = false;
      for (Iterator<Map.Entry<String, Pair<Define, Set<Identifier>>>> it =
              pending.entrySet().iterator();
          it.hasNext(); ) {
        Map.Entry<String, Pair<Define, Set<Identifier>>> e = it.next();
        Set<Identifier> dependencies = e.getValue().getSecond();
        String name = e.getKey();
        boolean missesDep = false;
        for (Identifier dependency : dependencies) {
          if (!added.contains(dependency)) {
            missesDep = true;
            if (!all.contains(dependency)) {
              it.remove();
              all.remove(name);
            }

            break;
          }
        }
        if (missesDep) continue;

        it.remove();
        reordered.add(e.getValue().getFirst());
        added.add(ident(name));
        progressed = true;
      }
    } while (!pending.isEmpty() && progressed);

    return reordered;
  }
  public void accept(Visitor visitor) {
    for (SourceFile sourceFile : sourceFiles) sourceFile.accept(visitor);

    for (Define define : defines) define.accept(visitor);
  }
  public void convertConstants(
      String library,
      List<Define> defines,
      Element sourcesRoot,
      final Signatures signatures,
      final DeclarationsHolder out,
      final Identifier libraryClassName) {
    // final List<Define> defines = new ArrayList<Define>();
    final Map<String, String> constants = Result.getMap(result.stringConstants, library);
    //
    sourcesRoot.accept(
        new Scanner() {
          //			@Override
          //			public void visitDefine(Define define) {
          //				super.visitDefine(define);
          //				if (elementsFilter.accept(define))
          //					defines.add(define);
          //			}
          @Override
          public void visitVariablesDeclaration(VariablesDeclaration v) {
            super.visitVariablesDeclaration(v);
            // if (!elementsFilter.accept(v))
            //	return;

            if (v.findParentOfType(Struct.class) != null) return;

            if (v.getValueType() instanceof FunctionSignature) return;

            for (Declarator decl : v.getDeclarators()) {
              if (!(decl instanceof DirectDeclarator))
                continue; // TODO provide a mapping of exported values

              TypeRef mutatedType = (TypeRef) decl.mutateTypeKeepingParent(v.getValueType());
              if (mutatedType == null
                  || !mutatedType.getModifiers().contains(ModifierType.Const)
                  || mutatedType.getModifiers().contains(ModifierType.Extern)
                  || decl.getDefaultValue() == null) continue;

              // TypeRef type = v.getValueType();
              String name = decl.resolveName();

              JavaPrim prim = result.typeConverter.getPrimitive(mutatedType, libraryClassName);
              if (prim == null) {
                if (mutatedType.toString().contains("NSString")) {
                  String value = constants.get(name);
                  if (value != null) outputNSString(name, value, out, signatures, v, decl);
                }
                continue;
              }

              try {

                // DirectDeclarator dd = (DirectDeclarator)decl;
                Pair<Expression, TypeRef> val =
                    result.typeConverter.convertExpressionToJava(
                        decl.getDefaultValue(), libraryClassName, true);

                if (!signatures.addVariable(name)) continue;

                // TODO
                TypeRef tr =
                    prim == JavaPrim.NativeLong || prim == JavaPrim.NativeSize
                        ? typeRef("long")
                        : primRef(prim)
                    // result.typeConverter.convertTypeToJNA(mutatedType,
                    // TypeConversion.TypeConversionMode.FieldType, libraryClassName)
                    ;
                VariablesDeclaration vd =
                    new VariablesDeclaration(tr, new DirectDeclarator(name, val.getFirst()));
                if (!result.config.noComments) {
                  vd.setCommentBefore(v.getCommentBefore());
                  vd.addToCommentBefore(decl.getCommentBefore());
                  vd.addToCommentBefore(decl.getCommentAfter());
                  vd.addToCommentBefore(v.getCommentAfter());
                }

                //                        if (result.config.runtime ==
                // JNAeratorConfig.Runtime.BridJ)
                vd.addModifiers(ModifierType.Public, ModifierType.Static, ModifierType.Final);

                out.addDeclaration(vd);
              } catch (UnsupportedConversionException e) {
                out.addDeclaration(skipDeclaration(v, e.toString()));
              }
            }
          }
        });

    if (defines != null) {
      for (Define define : reorderDefines(defines)) {
        if (define.getValue() == null) continue;

        try {
          // System.out.println("Define " + define.getName() + " = " + define.getValue());
          out.addDeclaration(
              outputConstant(
                  define.getName(),
                  define.getValue(),
                  signatures,
                  define.getValue(),
                  "define",
                  libraryClassName,
                  true,
                  false,
                  false));
        } catch (UnsupportedConversionException ex) {
          out.addDeclaration(skipDeclaration(define, ex.toString()));
        }
      }
    }
    for (Map.Entry<String, String> e : constants.entrySet()) {
      outputNSString(e.getKey(), e.getValue(), out, signatures);
    }
  }
 @Override
 public void visitDefine(Define define) {
   super.visitDefine(define);
   defines.put(define.getName(), define);
   getList(definesByLibrary, getLibrary(define)).add(define);
 }