~ubuntu-branches/ubuntu/quantal/hawtjni/quantal

« back to all changes in this revision

Viewing changes to hawtjni-generator/src/main/java/org/fusesource/hawtjni/generator/MacGenerator.java

  • Committer: Bazaar Package Importer
  • Author(s): Miguel Landaeta
  • Date: 2010-08-05 19:40:25 UTC
  • Revision ID: james.westby@ubuntu.com-20100805194025-3004hn889accwu2i
Tags: upstream-1.0~+git0c502e20c4
ImportĀ upstreamĀ versionĀ 1.0~+git0c502e20c4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2009 Progress Software, Inc.
 
3
 * Copyright (c) 2008 IBM Corporation and others.
 
4
 *
 
5
 * All rights reserved. This program and the accompanying materials
 
6
 * are made available under the terms of the Eclipse Public License v1.0
 
7
 * which accompanies this distribution, and is available at
 
8
 * http://www.eclipse.org/legal/epl-v10.html
 
9
 *
 
10
 *******************************************************************************/
 
11
package org.fusesource.hawtjni.generator;
 
12
 
 
13
import java.io.BufferedInputStream;
 
14
import java.io.ByteArrayOutputStream;
 
15
import java.io.File;
 
16
import java.io.FileInputStream;
 
17
import java.io.IOException;
 
18
import java.io.InputStream;
 
19
import java.io.InputStreamReader;
 
20
import java.io.PrintStream;
 
21
import java.util.ArrayList;
 
22
import java.util.Collections;
 
23
import java.util.Comparator;
 
24
import java.util.HashMap;
 
25
import java.util.Iterator;
 
26
import java.util.Map;
 
27
import java.util.Set;
 
28
import java.util.StringTokenizer;
 
29
import java.util.TreeMap;
 
30
import java.util.TreeSet;
 
31
 
 
32
import javax.xml.parsers.DocumentBuilderFactory;
 
33
 
 
34
import org.fusesource.hawtjni.generator.HawtJNI.UsageException;
 
35
import org.fusesource.hawtjni.generator.util.FileSupport;
 
36
import org.w3c.dom.Document;
 
37
import org.w3c.dom.Element;
 
38
import org.w3c.dom.NamedNodeMap;
 
39
import org.w3c.dom.Node;
 
40
import org.w3c.dom.NodeList;
 
41
import org.xml.sax.InputSource;
 
42
 
 
43
/**
 
44
 * 
 
45
 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
 
46
 */
 
47
public class MacGenerator {
 
48
    String[] xmls;
 
49
    Document[] documents;
 
50
    String outputDir, mainClassName;
 
51
    String delimiter = System.getProperty("line.separator");
 
52
    PrintStream out;
 
53
 
 
54
    public MacGenerator() {
 
55
    }
 
56
 
 
57
    static void list(File path, ArrayList<String> list) {
 
58
        if (path == null)
 
59
            return;
 
60
        File[] frameworks = path.listFiles();
 
61
        if (frameworks == null)
 
62
            return;
 
63
        for (int i = 0; i < frameworks.length; i++) {
 
64
            File file = frameworks[i];
 
65
            String name = file.getName();
 
66
            int index = name.lastIndexOf(".");
 
67
            if (index != -1) {
 
68
                String xml = file.getAbsolutePath() + "/Resources/BridgeSupport/" + name.substring(0, index) + "Full.bridgesupport";
 
69
                if (new File(xml).exists()) {
 
70
                    list.add(xml);
 
71
                }
 
72
            }
 
73
        }
 
74
    }
 
75
 
 
76
    int getLevel(Node node) {
 
77
        int level = 0;
 
78
        while (node != null) {
 
79
            level++;
 
80
            node = node.getParentNode();
 
81
        }
 
82
        return level;
 
83
    }
 
84
 
 
85
    void merge(Document document, Document extraDocument) {
 
86
        if (extraDocument == null)
 
87
            return;
 
88
 
 
89
        /* Build a lookup table for extraDocument */
 
90
        HashMap<String, Node> extras = new HashMap<String, Node>();
 
91
        buildLookup(extraDocument, extras);
 
92
 
 
93
        /*
 
94
         * Merge attributes on existing elements building a lookup table for
 
95
         * document
 
96
         */
 
97
        HashMap<String, Node> lookup = new HashMap<String, Node>();
 
98
        merge(document, extras, lookup);
 
99
 
 
100
        /*
 
101
         * Merge new elements. Extras at this point contains only elements that
 
102
         * were not found in the document.
 
103
         */
 
104
        ArrayList<Node> sortedNodes = Collections.list(Collections.enumeration(extras.values()));
 
105
        Collections.sort(sortedNodes, new Comparator<Node>() {
 
106
            public int compare(Node arg0, Node arg1) {
 
107
                int compare = getLevel(arg0) - getLevel(arg1);
 
108
                if (compare == 0) {
 
109
                    return (arg0).getNodeName().compareTo((arg1).getNodeName());
 
110
                }
 
111
                return compare;
 
112
            }
 
113
        });
 
114
        String delimiter = System.getProperty("line.separator");
 
115
        for (Iterator<Node> iterator = sortedNodes.iterator(); iterator.hasNext();) {
 
116
            Node node = iterator.next();
 
117
            String name = node.getNodeName();
 
118
            if ("arg".equals(name) || "retval".equals(name)) {
 
119
                if (!sortedNodes.contains(node.getParentNode()))
 
120
                    continue;
 
121
            }
 
122
            Node parent = lookup.get(getKey(node.getParentNode()));
 
123
            Element element = document.createElement(node.getNodeName());
 
124
            String text = parent.getChildNodes().getLength() == 0 ? delimiter : "";
 
125
            for (int i = 0, level = getLevel(parent) - 1; i < level; i++) {
 
126
                text += "  ";
 
127
            }
 
128
            parent.appendChild(document.createTextNode(text));
 
129
            parent.appendChild(element);
 
130
            parent.appendChild(document.createTextNode(delimiter));
 
131
            NamedNodeMap attributes = node.getAttributes();
 
132
            for (int j = 0, length = attributes.getLength(); j < length; j++) {
 
133
                Node attr = (Node) attributes.item(j);
 
134
                element.setAttribute(attr.getNodeName(), attr.getNodeValue());
 
135
            }
 
136
            lookup.put(getKey(element), element);
 
137
        }
 
138
    }
 
139
 
 
140
    public void generate(ProgressMonitor progress) throws UsageException {
 
141
        if (progress != null) {
 
142
            progress.setTotal(3);
 
143
            progress.setMessage("extra attributes...");
 
144
        }
 
145
        generateExtraAttributes();
 
146
        if (progress != null) {
 
147
            progress.step();
 
148
            progress.setMessage(mainClassName);
 
149
        }
 
150
        generateMainClass();
 
151
        if (progress != null) {
 
152
            progress.step();
 
153
            progress.setMessage("classes...");
 
154
        }
 
155
        generateClasses();
 
156
        if (progress != null) {
 
157
            progress.step();
 
158
            progress.setMessage("Done.");
 
159
        }
 
160
    }
 
161
 
 
162
 
 
163
    String fixDelimiter(String str) {
 
164
        if (delimiter.equals("\n"))
 
165
            return str;
 
166
        int index = 0, length = str.length();
 
167
        StringBuffer buffer = new StringBuffer();
 
168
        while (index != -1) {
 
169
            int start = index;
 
170
            index = str.indexOf('\n', start);
 
171
            if (index == -1) {
 
172
                buffer.append(str.substring(start, length));
 
173
            } else {
 
174
                buffer.append(str.substring(start, index));
 
175
                buffer.append(delimiter);
 
176
                index++;
 
177
            }
 
178
        }
 
179
        return buffer.toString();
 
180
    }
 
181
 
 
182
    void generateMethods(String className, ArrayList<Node> methods) {
 
183
        for (Node method : methods) {
 
184
            NamedNodeMap mthAttributes = method.getAttributes();
 
185
            String sel = mthAttributes.getNamedItem("selector").getNodeValue();
 
186
            out("public ");
 
187
            boolean isStatic = isStatic(method);
 
188
            if (isStatic)
 
189
                out("static ");
 
190
            Node returnNode = getReturnNode(method.getChildNodes());
 
191
            if (getType(returnNode).equals("void"))
 
192
                returnNode = null;
 
193
            String returnType = "", returnType64 = "";
 
194
            if (returnNode != null) {
 
195
                String type = returnType = getJavaType(returnNode), type64 = returnType64 = getJavaType64(returnNode);
 
196
                out(type);
 
197
                if (!type.equals(type64)) {
 
198
                    out(" /*");
 
199
                    out(type64);
 
200
                    out("*/");
 
201
                }
 
202
                out(" ");
 
203
            } else {
 
204
                out("void ");
 
205
            }
 
206
            String methodName = sel;
 
207
            if (isUnique(method, methods)) {
 
208
                int index = methodName.indexOf(":");
 
209
                if (index != -1)
 
210
                    methodName = methodName.substring(0, index);
 
211
            } else {
 
212
                // TODO improve this selector
 
213
                methodName = methodName.replaceAll(":", "_");
 
214
                if (isStatic)
 
215
                    methodName = "static_" + methodName;
 
216
            }
 
217
            out(methodName);
 
218
            out("(");
 
219
            NodeList params = method.getChildNodes();
 
220
            boolean first = true;
 
221
            for (int k = 0; k < params.getLength(); k++) {
 
222
                Node param = params.item(k);
 
223
                if ("arg".equals(param.getNodeName())) {
 
224
                    NamedNodeMap paramAttributes = param.getAttributes();
 
225
                    if (!first)
 
226
                        out(", ");
 
227
                    String type = getJavaType(param), type64 = getJavaType64(param);
 
228
                    out(type);
 
229
                    if (!type.equals(type64)) {
 
230
                        out(" /*");
 
231
                        out(type64);
 
232
                        out("*/");
 
233
                    }
 
234
                    first = false;
 
235
                    out(" ");
 
236
                    String paramName = paramAttributes.getNamedItem("name").getNodeValue();
 
237
                    if (paramName.length() == 0)
 
238
                        paramName = "arg" + paramAttributes.getNamedItem("index").getNodeValue();
 
239
                    if (paramName.equals("boolean"))
 
240
                        paramName = "b";
 
241
                    out(paramName);
 
242
                }
 
243
            }
 
244
            out(") {");
 
245
            outln();
 
246
            if (returnNode != null && isStruct(returnNode)) {
 
247
                out("\t");
 
248
                out(returnType);
 
249
                out(" result = new ");
 
250
                out(returnType);
 
251
                out("();");
 
252
                outln();
 
253
                out("\tOS.objc_msgSend_stret(result, ");
 
254
            } else if (returnNode != null && isBoolean(returnNode)) {
 
255
                out("\treturn ");
 
256
                out("OS.objc_msgSend_bool(");
 
257
            } else if (returnNode != null && isFloatingPoint(returnNode)) {
 
258
                out("\treturn ");
 
259
                if (returnType.equals("float"))
 
260
                    out("(float)");
 
261
                out("OS.objc_msgSend_fpret(");
 
262
            } else if (returnNode != null && isObject(returnNode)) {
 
263
                out("\tint /*long*/ result = OS.objc_msgSend(");
 
264
            } else {
 
265
                if (returnNode != null) {
 
266
                    out("\treturn ");
 
267
                    if ((returnType.equals("int") && returnType64.equals("int")) || !returnType.equals("int")) {
 
268
                        out("(");
 
269
                        out(returnType);
 
270
                        out(")");
 
271
                    }
 
272
                    if (returnType.equals("int") && returnType64.equals("int")) {
 
273
                        out("/*64*/");
 
274
                    }
 
275
                } else {
 
276
                    out("\t");
 
277
                }
 
278
                out("OS.objc_msgSend(");
 
279
            }
 
280
            if (isStatic) {
 
281
                out("OS.class_");
 
282
                out(className);
 
283
            } else {
 
284
                out("this.id");
 
285
            }
 
286
            out(", OS.");
 
287
            out(getSelConst(sel));
 
288
            first = false;
 
289
            for (int k = 0; k < params.getLength(); k++) {
 
290
                Node param = params.item(k);
 
291
                if ("arg".equals(param.getNodeName())) {
 
292
                    NamedNodeMap paramAttributes = param.getAttributes();
 
293
                    if (!first)
 
294
                        out(", ");
 
295
                    first = false;
 
296
                    String paramName = paramAttributes.getNamedItem("name").getNodeValue();
 
297
                    if (paramName.length() == 0)
 
298
                        paramName = "arg" + paramAttributes.getNamedItem("index").getNodeValue();
 
299
                    if (paramName.equals("boolean"))
 
300
                        paramName = "b";
 
301
                    if (isObject(param)) {
 
302
                        out(paramName);
 
303
                        out(" != null ? ");
 
304
                        out(paramName);
 
305
                        out(".id : 0");
 
306
                    } else {
 
307
                        out(paramName);
 
308
                    }
 
309
                }
 
310
            }
 
311
            out(")");
 
312
            out(";");
 
313
            outln();
 
314
            if (returnNode != null && isObject(returnNode)) {
 
315
                if (!isStatic && returnType.equals(className)) {
 
316
                    out("\treturn result == this.id ? this : (result != 0 ? new ");
 
317
                    out(returnType);
 
318
                    out("(result) : null);");
 
319
                } else {
 
320
                    out("\treturn result != 0 ? new ");
 
321
                    NamedNodeMap attributes = returnNode.getAttributes();
 
322
                    Node hawtjni_alloc = attributes.getNamedItem("hawtjni_alloc");
 
323
                    if (hawtjni_alloc != null && hawtjni_alloc.getNodeValue().equals("true")) {
 
324
                        out(className);
 
325
                    } else {
 
326
                        out(returnType);
 
327
                    }
 
328
                    out("(result) : null;");
 
329
                }
 
330
                outln();
 
331
            } else if (returnNode != null && isStruct(returnNode)) {
 
332
                out("\treturn result;");
 
333
                outln();
 
334
            }
 
335
            out("}");
 
336
            outln();
 
337
            outln();
 
338
        }
 
339
    }
 
340
 
 
341
    void generateExtraMethods(String className) {
 
342
        /* Empty constructor */
 
343
        out("public ");
 
344
        out(className);
 
345
        out("() {");
 
346
        outln();
 
347
        out("\tsuper();");
 
348
        outln();
 
349
        out("}");
 
350
        outln();
 
351
        outln();
 
352
        /* pointer constructor */
 
353
        out("public ");
 
354
        out(className);
 
355
        out("(int /*long*/ id) {");
 
356
        outln();
 
357
        out("\tsuper(id);");
 
358
        outln();
 
359
        out("}");
 
360
        outln();
 
361
        outln();
 
362
        /* object constructor */
 
363
        out("public ");
 
364
        out(className);
 
365
        out("(id id) {");
 
366
        outln();
 
367
        out("\tsuper(id);");
 
368
        outln();
 
369
        out("}");
 
370
        outln();
 
371
        outln();
 
372
        /* NSObject helpers */
 
373
        if (className.equals("NSObject")) {
 
374
            out("public NSObject alloc() {");
 
375
            outln();
 
376
            out("\tthis.id = OS.objc_msgSend(objc_getClass(), OS.sel_alloc);");
 
377
            outln();
 
378
            out("\treturn this;");
 
379
            outln();
 
380
            out("}");
 
381
            outln();
 
382
            outln();
 
383
        }
 
384
        /* NSString helpers */
 
385
        if (className.equals("NSString")) {
 
386
            /* Get java string */
 
387
            out("public String getString() {");
 
388
            outln();
 
389
            out("\tchar[] buffer = new char[(int)/*64*/length()];");
 
390
            outln();
 
391
            out("\tgetCharacters(buffer);");
 
392
            outln();
 
393
            out("\treturn new String(buffer);");
 
394
            outln();
 
395
            out("}");
 
396
            outln();
 
397
            outln();
 
398
            /* create NSString */
 
399
            out("public NSString initWithString(String str) {");
 
400
            outln();
 
401
            out("\tchar[] buffer = new char[str.length()];");
 
402
            outln();
 
403
            out("\tstr.getChars(0, buffer.length, buffer, 0);");
 
404
            outln();
 
405
            out("\treturn initWithCharacters(buffer, buffer.length);");
 
406
            outln();
 
407
            out("}");
 
408
            outln();
 
409
            outln();
 
410
            out("public static NSString stringWith(String str) {");
 
411
            outln();
 
412
            out("\tchar[] buffer = new char[str.length()];");
 
413
            outln();
 
414
            out("\tstr.getChars(0, buffer.length, buffer, 0);");
 
415
            outln();
 
416
            out("\treturn stringWithCharacters(buffer, buffer.length);");
 
417
            outln();
 
418
            out("}");
 
419
            outln();
 
420
            outln();
 
421
        }
 
422
    }
 
423
 
 
424
    static class NodeEntry {
 
425
        private final Node parent;
 
426
        private final ArrayList<Node> children;
 
427
 
 
428
        public NodeEntry(Node parent, ArrayList<Node> children) {
 
429
            this.parent = parent;
 
430
            this.children = children;
 
431
        }
 
432
    }
 
433
    
 
434
    TreeMap<String, NodeEntry> getGeneratedClasses() {
 
435
        TreeMap<String, NodeEntry> classes = new TreeMap<String, NodeEntry>();
 
436
        for (int x = 0; x < xmls.length; x++) {
 
437
            Document document = documents[x];
 
438
            if (document == null)
 
439
                continue;
 
440
            NodeList list = document.getDocumentElement().getChildNodes();
 
441
            for (int i = 0; i < list.getLength(); i++) {
 
442
                Node node = list.item(i);
 
443
                if ("class".equals(node.getNodeName()) && getGen(node)) {
 
444
                    ArrayList<Node> methods;
 
445
                    String name = node.getAttributes().getNamedItem("name").getNodeValue();
 
446
                    NodeEntry clazz = classes.get(name);
 
447
                    if (clazz == null) {
 
448
                        methods = new ArrayList<Node>();
 
449
                        classes.put(name, new NodeEntry(node, methods));
 
450
                    } else {
 
451
                        methods = clazz.children;
 
452
                    }
 
453
                    NodeList methodList = node.getChildNodes();
 
454
                    for (int j = 0; j < methodList.getLength(); j++) {
 
455
                        Node method = methodList.item(j);
 
456
                        if ("method".equals(method.getNodeName()) && getGen(method)) {
 
457
                            methods.add(method);
 
458
                        }
 
459
                    }
 
460
                }
 
461
            }
 
462
        }
 
463
        return classes;
 
464
    }
 
465
 
 
466
    void copyClassMethodsDown(final Map<String, NodeEntry> classes) {
 
467
        ArrayList<NodeEntry> sortedClasses = Collections.list(Collections.enumeration(classes.values()));
 
468
        Collections.sort(sortedClasses, new Comparator<NodeEntry>() {
 
469
            int getHierarchyLevel(Node node) {
 
470
                String superclass = getSuperclassName(node);
 
471
                int level = 0;
 
472
                while (!superclass.equals("id")) {
 
473
                    level++;
 
474
                    superclass = getSuperclassName(classes.get(superclass).parent);
 
475
                }
 
476
                return level;
 
477
            }
 
478
 
 
479
            public int compare(NodeEntry arg0, NodeEntry arg1) {
 
480
                return getHierarchyLevel(arg0.parent) - getHierarchyLevel(arg1.parent);
 
481
            }
 
482
        });
 
483
        for (NodeEntry clazz : sortedClasses) {
 
484
            Node node = (Node) clazz.parent;
 
485
            ArrayList<Node> methods = (ArrayList<Node>) clazz.children;
 
486
            NodeEntry superclass = classes.get(getSuperclassName(node));
 
487
            if (superclass != null) {
 
488
                for (Node method : superclass.children) {
 
489
                    if (isStatic(method)) {
 
490
                        methods.add(method);
 
491
                    }
 
492
                }
 
493
            }
 
494
        }
 
495
    }
 
496
 
 
497
    String getSuperclassName(Node node) {
 
498
        NamedNodeMap attributes = node.getAttributes();
 
499
        Node superclass = attributes.getNamedItem("hawtjni_superclass");
 
500
        if (superclass != null) {
 
501
            return superclass.getNodeValue();
 
502
        } else {
 
503
            Node name = attributes.getNamedItem("name");
 
504
            if (name.getNodeValue().equals("NSObject")) {
 
505
                return "id";
 
506
            } else {
 
507
                return "NSObject";
 
508
            }
 
509
        }
 
510
    }
 
511
 
 
512
    void generateClasses() {
 
513
        TreeMap<String, NodeEntry> classes = getGeneratedClasses();
 
514
        copyClassMethodsDown(classes);
 
515
 
 
516
        Set<String> classNames = classes.keySet();
 
517
        for (Iterator<String> iterator = classNames.iterator(); iterator.hasNext();) {
 
518
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
519
            this.out = new PrintStream(out);
 
520
 
 
521
//            out(fixDelimiter(metaData.getCopyright()));
 
522
 
 
523
            String className = iterator.next();
 
524
            NodeEntry clazz = classes.get(className);
 
525
            Node node = clazz.parent;
 
526
            ArrayList<Node> methods = clazz.children;
 
527
            out("package ");
 
528
            String packageName = getPackageName(mainClassName);
 
529
            out(packageName);
 
530
            out(";");
 
531
            outln();
 
532
            outln();
 
533
            out("public class ");
 
534
            out(className);
 
535
            out(" extends ");
 
536
            out(getSuperclassName(node));
 
537
            out(" {");
 
538
            outln();
 
539
            outln();
 
540
            generateExtraMethods(className);
 
541
            generateMethods(className, methods);
 
542
            out("}");
 
543
            outln();
 
544
 
 
545
            String fileName = outputDir + packageName.replace('.', '/') + "/" + className + ".java";
 
546
            try {
 
547
                out.flush();
 
548
                if (out.size() > 0) {
 
549
                    FileSupport.write(out.toByteArray(), new File(fileName));
 
550
                }
 
551
            } catch (Exception e) {
 
552
                System.out.println("Problem");
 
553
                e.printStackTrace(System.out);
 
554
            }
 
555
            out = null;
 
556
        }
 
557
    }
 
558
 
 
559
    void generateExtraAttributes() {
 
560
        Document[] documents = getDocuments();
 
561
        for (int x = 0; x < xmls.length; x++) {
 
562
            Document document = documents[x];
 
563
            if (document == null || !getGen(document.getDocumentElement()))
 
564
                continue;
 
565
            saveExtraAttributes(xmls[x], document);
 
566
        }
 
567
    }
 
568
 
 
569
    void generateMainClass() {
 
570
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
571
        this.out = new PrintStream(out);
 
572
 
 
573
        String header = "", footer = "";
 
574
        String fileName = outputDir + mainClassName.replace('.', '/') + ".java";
 
575
        FileInputStream is = null;
 
576
        try {
 
577
            InputStreamReader input = new InputStreamReader(new BufferedInputStream(is = new FileInputStream(fileName)));
 
578
            StringBuffer str = new StringBuffer();
 
579
            char[] buffer = new char[4096];
 
580
            int read;
 
581
            while ((read = input.read(buffer)) != -1) {
 
582
                str.append(buffer, 0, read);
 
583
            }
 
584
            String section = "/** This section is auto generated */";
 
585
            int start = str.indexOf(section) + section.length();
 
586
            int end = str.indexOf(section, start);
 
587
            header = str.substring(0, start);
 
588
            footer = str.substring(end);
 
589
        } catch (IOException e) {
 
590
        } finally {
 
591
            try {
 
592
                if (is != null)
 
593
                    is.close();
 
594
            } catch (IOException e) {
 
595
            }
 
596
        }
 
597
 
 
598
        out(header);
 
599
        outln();
 
600
        outln();
 
601
 
 
602
        out("/** Custom callbacks */");
 
603
        outln();
 
604
        generateCustomCallbacks();
 
605
        outln();
 
606
        out("/** Classes */");
 
607
        outln();
 
608
        generateClassesConst();
 
609
        outln();
 
610
        out("/** Protocols */");
 
611
        outln();
 
612
        generateProtocolsConst();
 
613
        outln();
 
614
        out("/** Selectors */");
 
615
        outln();
 
616
        generateSelectorsConst();
 
617
        outln();
 
618
        out("/** Constants */");
 
619
        outln();
 
620
        generateEnums();
 
621
        outln();
 
622
        out("/** Globals */");
 
623
        outln();
 
624
        generateConstants();
 
625
        outln();
 
626
        out("/** Functions */");
 
627
        outln();
 
628
        outln();
 
629
        generateFunctions();
 
630
        outln();
 
631
        out("/** Super Sends */");
 
632
        outln();
 
633
        generateSends(true);
 
634
        outln();
 
635
        out("/** Sends */");
 
636
        outln();
 
637
        generateSends(false);
 
638
        outln();
 
639
        generateStructNatives();
 
640
 
 
641
        outln();
 
642
        out(footer);
 
643
        try {
 
644
            out.flush();
 
645
            if (out.size() > 0) {
 
646
                FileSupport.write(out.toByteArray(), new File(fileName));
 
647
                
 
648
            }
 
649
        } catch (Exception e) {
 
650
            System.out.println("Problem");
 
651
            e.printStackTrace(System.out);
 
652
        }
 
653
    }
 
654
 
 
655
    public Document[] getDocuments() {
 
656
        if (documents == null) {
 
657
            String[] xmls = getXmls();
 
658
            documents = new Document[xmls.length];
 
659
            for (int i = 0; i < xmls.length; i++) {
 
660
                String xmlPath = xmls[i];
 
661
                Document document = documents[i] = getDocument(xmlPath);
 
662
                if (document == null)
 
663
                    continue;
 
664
                if (mainClassName != null && outputDir != null) {
 
665
                    String packageName = getPackageName(mainClassName);
 
666
                    String extrasPath = outputDir + packageName.replace('.', '/') + "/" + getFileName(xmlPath) + ".extras";
 
667
                    merge(document, getDocument(extrasPath));
 
668
                }
 
669
            }
 
670
        }
 
671
        return documents;
 
672
    }
 
673
 
 
674
    public String[] getXmls() {
 
675
        if (xmls == null || xmls.length == 0) {
 
676
            ArrayList<String> array = new ArrayList<String>();
 
677
            list(new File("/System/Library/Frameworks"), array);
 
678
            list(new File("/System/Library/Frameworks/CoreServices.framework/Frameworks"), array);
 
679
            list(new File("/System/Library/Frameworks/ApplicationServices.framework/Frameworks"), array);
 
680
            Collections.sort(array, new Comparator<String>() {
 
681
                public int compare(String o1, String o2) {
 
682
                    return new File(o1).getName().compareTo(new File(o2).getName());
 
683
                }
 
684
            });
 
685
            xmls = array.toArray(new String[array.size()]);
 
686
        }
 
687
        return xmls;
 
688
    }
 
689
 
 
690
    void saveExtraAttributes(String xmlPath, Document document) {
 
691
        try {
 
692
            String packageName = getPackageName(mainClassName);
 
693
            String fileName = outputDir + packageName.replace('.', '/') + "/" + getFileName(xmlPath) + ".extras";
 
694
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
695
            DOMWriter writer = new DOMWriter(new PrintStream(out));
 
696
            String[] names = getIDAttributeNames();
 
697
            String[] filter = new String[names.length + 2];
 
698
            filter[0] = "class_method";
 
699
            filter[1] = "hawtjni_.*";
 
700
            System.arraycopy(names, 0, filter, 2, names.length);
 
701
            writer.setAttributeFilter(filter);
 
702
            writer.setNodeFilter("hawtjni_");
 
703
            writer.print(document);
 
704
            if (out.size() > 0) {
 
705
                FileSupport.write(out.toByteArray(), new File(fileName));
 
706
            }
 
707
        } catch (Exception e) {
 
708
            System.out.println("Problem");
 
709
            e.printStackTrace(System.out);
 
710
        }
 
711
    }
 
712
 
 
713
    public void setOutputDir(String dir) {
 
714
        if (dir != null) {
 
715
            if (!dir.endsWith("\\") && !dir.endsWith("/")) {
 
716
                dir += "/";
 
717
            }
 
718
        }
 
719
        this.outputDir = dir;
 
720
    }
 
721
 
 
722
    public void setXmls(String[] xmls) {
 
723
        this.xmls = xmls;
 
724
        this.documents = null;
 
725
    }
 
726
 
 
727
    public void setMainClass(String mainClassName) {
 
728
        this.mainClassName = mainClassName;
 
729
    }
 
730
 
 
731
    Document getDocument(String xmlPath) {
 
732
        try {
 
733
            InputStream is = null;
 
734
            if (xmlPath.indexOf(File.separatorChar) == -1)
 
735
                is = getClass().getResourceAsStream(xmlPath);
 
736
            if (is == null)
 
737
                is = new BufferedInputStream(new FileInputStream(xmlPath));
 
738
            if (is != null)
 
739
                return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(is));
 
740
        } catch (Exception e) {
 
741
            // e.printStackTrace();
 
742
        }
 
743
        return null;
 
744
    }
 
745
 
 
746
    public String[] getExtraAttributeNames(Node node) {
 
747
        String name = node.getNodeName();
 
748
        if (name.equals("method")) {
 
749
            return new String[] { "hawtjni_gen_super_msgSend", "hawtjni_gen_custom_callback" };
 
750
        } else if (name.equals("function")) {
 
751
            NamedNodeMap attribs = node.getAttributes();
 
752
            if (attribs != null && attribs.getNamedItem("variadic") != null) {
 
753
                return new String[] { "hawtjni_variadic_count", "hawtjni_variadic_java_types" };
 
754
            }
 
755
        } else if (name.equals("class")) {
 
756
            return new String[] { "hawtjni_superclass" };
 
757
        } else if (name.equals("retval")) {
 
758
            return new String[] { "hawtjni_java_type", "hawtjni_java_type64", "hawtjni_alloc" };
 
759
        } else if (name.equals("arg")) {
 
760
            return new String[] { "hawtjni_java_type", "hawtjni_java_type64" };
 
761
        }
 
762
        return new String[0];
 
763
    }
 
764
 
 
765
    public String getFileName(String xmlPath) {
 
766
        File file = new File(xmlPath);
 
767
        return file.getName();
 
768
    }
 
769
 
 
770
    String getKey(Node node) {
 
771
        StringBuffer buffer = new StringBuffer();
 
772
        while (node != null) {
 
773
            if (buffer.length() > 0)
 
774
                buffer.append("_");
 
775
            String name = node.getNodeName();
 
776
            StringBuffer key = new StringBuffer(name);
 
777
            Node nameAttrib = getIDAttribute(node);
 
778
            if (nameAttrib != null) {
 
779
                key.append("-");
 
780
                key.append(nameAttrib.getNodeValue());
 
781
            }
 
782
            NamedNodeMap attributes = node.getAttributes();
 
783
            if (attributes != null) {
 
784
                boolean isStatic = attributes.getNamedItem("class_method") != null;
 
785
                if (isStatic)
 
786
                    key.append("-static");
 
787
            }
 
788
            buffer.append(key.reverse());
 
789
            node = node.getParentNode();
 
790
        }
 
791
        buffer.reverse();
 
792
        return buffer.toString();
 
793
    }
 
794
 
 
795
    public Node getIDAttribute(Node node) {
 
796
        NamedNodeMap attributes = node.getAttributes();
 
797
        if (attributes == null)
 
798
            return null;
 
799
        String[] names = getIDAttributeNames();
 
800
        for (int i = 0; i < names.length; i++) {
 
801
            Node nameAttrib = attributes.getNamedItem(names[i]);
 
802
            if (nameAttrib != null)
 
803
                return nameAttrib;
 
804
        }
 
805
        return null;
 
806
    }
 
807
 
 
808
    public String[] getIDAttributeNames() {
 
809
        return new String[] { "name", "selector", "path", };
 
810
    }
 
811
 
 
812
    void merge(Node node, HashMap<String, Node> extras, HashMap<String, Node> docLookup) {
 
813
        NodeList list = node.getChildNodes();
 
814
        for (int i = 0; i < list.getLength(); i++) {
 
815
            Node childNode = list.item(i);
 
816
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 
817
                String key = getKey(childNode);
 
818
                if (docLookup != null && docLookup.get(key) == null) {
 
819
                    docLookup.put(key, childNode);
 
820
                }
 
821
                Node extra = extras.remove(key);
 
822
                if (extra != null) {
 
823
                    NamedNodeMap attributes = extra.getAttributes();
 
824
                    for (int j = 0, length = attributes.getLength(); j < length; j++) {
 
825
                        Node attr = (Node) attributes.item(j);
 
826
                        String name = attr.getNodeName();
 
827
                        if (name.startsWith("hawtjni_")) {
 
828
                            ((Element) childNode).setAttribute(name, attr.getNodeValue());
 
829
                        }
 
830
                    }
 
831
                }
 
832
            }
 
833
            merge(childNode, extras, docLookup);
 
834
        }
 
835
    }
 
836
 
 
837
    void out(String str) {
 
838
        PrintStream out = this.out;
 
839
        if (out == null)
 
840
            out = System.out;
 
841
        out.print(str);
 
842
    }
 
843
 
 
844
    void outln() {
 
845
        PrintStream out = this.out;
 
846
        if (out == null)
 
847
            out = System.out;
 
848
        out.println();
 
849
    }
 
850
 
 
851
    void generateConstants() {
 
852
        for (int x = 0; x < xmls.length; x++) {
 
853
            Document document = documents[x];
 
854
            if (document == null)
 
855
                continue;
 
856
            NodeList list = document.getDocumentElement().getChildNodes();
 
857
            for (int i = 0; i < list.getLength(); i++) {
 
858
                Node node = list.item(i);
 
859
                if ("constant".equals(node.getNodeName())) {
 
860
                    if (getGen(node)) {
 
861
                        NamedNodeMap attributes = node.getAttributes();
 
862
                        String constName = attributes.getNamedItem("name").getNodeValue();
 
863
                        out("/** @method flags=const */");
 
864
                        outln();
 
865
                        out("public static final native ");
 
866
                        String type = getType(node), type64 = getType64(node);
 
867
                        out(type);
 
868
                        if (!type.equals(type64)) {
 
869
                            out(" /*");
 
870
                            out(type64);
 
871
                            out("*/");
 
872
                        }
 
873
                        out(" ");
 
874
                        out(constName);
 
875
                        out("();");
 
876
                        outln();
 
877
                        if (attributes.getNamedItem("declared_type").getNodeValue().equals("NSString*")) {
 
878
                            out("public static final NSString ");
 
879
                            out(constName);
 
880
                            out(" = new NSString(");
 
881
                            out(constName);
 
882
                            out("());");
 
883
                            outln();
 
884
                        }
 
885
                    }
 
886
                }
 
887
            }
 
888
        }
 
889
    }
 
890
 
 
891
    void generateEnums() {
 
892
        for (int x = 0; x < xmls.length; x++) {
 
893
            Document document = documents[x];
 
894
            if (document == null)
 
895
                continue;
 
896
            NodeList list = document.getDocumentElement().getChildNodes();
 
897
            for (int i = 0; i < list.getLength(); i++) {
 
898
                Node node = list.item(i);
 
899
                if ("enum".equals(node.getNodeName())) {
 
900
                    if (getGen(node)) {
 
901
                        NamedNodeMap attributes = node.getAttributes();
 
902
                        Node valueNode = attributes.getNamedItem("value");
 
903
                        if (valueNode != null) {
 
904
                            String value = valueNode.getNodeValue();
 
905
                            out("public static final ");
 
906
                            boolean isLong = false;
 
907
                            if (value.indexOf('.') != -1) {
 
908
                                out("double ");
 
909
                            } else {
 
910
                                try {
 
911
                                    Integer.parseInt(value);
 
912
                                    out("int ");
 
913
                                } catch (NumberFormatException e) {
 
914
                                    isLong = true;
 
915
                                    out("long ");
 
916
                                }
 
917
                            }
 
918
                            out(attributes.getNamedItem("name").getNodeValue());
 
919
                            out(" = ");
 
920
                            out(value);
 
921
                            if (isLong && !value.endsWith("L"))
 
922
                                out("L");
 
923
                            out(";");
 
924
                            outln();
 
925
                        }
 
926
                    }
 
927
                }
 
928
            }
 
929
        }
 
930
    }
 
931
 
 
932
    boolean getGen(Node node) {
 
933
        NamedNodeMap attributes = node.getAttributes();
 
934
        if (attributes == null)
 
935
            return false;
 
936
        Node gen = attributes.getNamedItem("hawtjni_gen");
 
937
        return gen != null && !gen.getNodeValue().equals("false");
 
938
    }
 
939
 
 
940
    boolean getGenSuper(Node node) {
 
941
        NamedNodeMap attributes = node.getAttributes();
 
942
        if (attributes == null)
 
943
            return false;
 
944
        Node gen = attributes.getNamedItem("hawtjni_gen_super_msgSend");
 
945
        return gen != null && !gen.getNodeValue().equals("false");
 
946
    }
 
947
 
 
948
    boolean getGenCallback(Node node) {
 
949
        NamedNodeMap attributes = node.getAttributes();
 
950
        if (attributes == null)
 
951
            return false;
 
952
        Node gen = attributes.getNamedItem("hawtjni_gen_custom_callback");
 
953
        return gen != null && !gen.getNodeValue().equals("false");
 
954
    }
 
955
 
 
956
    boolean isStatic(Node node) {
 
957
        NamedNodeMap attributes = node.getAttributes();
 
958
        Node isStatic = attributes.getNamedItem("class_method");
 
959
        return isStatic != null && isStatic.getNodeValue().equals("true");
 
960
    }
 
961
 
 
962
    boolean isStruct(Node node) {
 
963
        NamedNodeMap attributes = node.getAttributes();
 
964
        String code = attributes.getNamedItem("type").getNodeValue();
 
965
        return code.startsWith("{");
 
966
    }
 
967
 
 
968
    boolean isFloatingPoint(Node node) {
 
969
        NamedNodeMap attributes = node.getAttributes();
 
970
        String code = attributes.getNamedItem("type").getNodeValue();
 
971
        return code.equals("f") || code.equals("d");
 
972
    }
 
973
 
 
974
    boolean isObject(Node node) {
 
975
        NamedNodeMap attributes = node.getAttributes();
 
976
        String code = attributes.getNamedItem("type").getNodeValue();
 
977
        return code.equals("@");
 
978
    }
 
979
 
 
980
    boolean isBoolean(Node node) {
 
981
        NamedNodeMap attributes = node.getAttributes();
 
982
        String code = attributes.getNamedItem("type").getNodeValue();
 
983
        return code.equals("B");
 
984
    }
 
985
 
 
986
    void buildLookup(Node node, HashMap<String, Node> table) {
 
987
        NodeList list = node.getChildNodes();
 
988
        for (int i = 0; i < list.getLength(); i++) {
 
989
            Node childNode = list.item(i);
 
990
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 
991
                String key = getKey(childNode);
 
992
                if (table.get(key) == null)
 
993
                    table.put(key, childNode);
 
994
                buildLookup(childNode, table);
 
995
            }
 
996
        }
 
997
    }
 
998
 
 
999
    boolean isUnique(Node method, ArrayList<Node> methods) {
 
1000
        String methodName = method.getAttributes().getNamedItem("selector").getNodeValue();
 
1001
        String signature = "";
 
1002
        NodeList params = method.getChildNodes();
 
1003
        for (int k = 0; k < params.getLength(); k++) {
 
1004
            Node param = params.item(k);
 
1005
            if ("arg".equals(param.getNodeName())) {
 
1006
                signature += getJavaType(param);
 
1007
            }
 
1008
        }
 
1009
        int index = methodName.indexOf(":");
 
1010
        if (index != -1)
 
1011
            methodName = methodName.substring(0, index);
 
1012
        for (Node node : methods) {
 
1013
            NamedNodeMap attributes = node.getAttributes();
 
1014
            Node otherSel = null;
 
1015
            if (attributes != null)
 
1016
                otherSel = attributes.getNamedItem("selector");
 
1017
            if (node != method && otherSel != null) {
 
1018
                String otherName = otherSel.getNodeValue();
 
1019
                index = otherName.indexOf(":");
 
1020
                if (index != -1)
 
1021
                    otherName = otherName.substring(0, index);
 
1022
                if (methodName.equals(otherName)) {
 
1023
                    NodeList otherParams = node.getChildNodes();
 
1024
                    String otherSignature = "";
 
1025
                    for (int k = 0; k < otherParams.getLength(); k++) {
 
1026
                        Node param = otherParams.item(k);
 
1027
                        if ("arg".equals(param.getNodeName())) {
 
1028
                            otherSignature += getJavaType(param);
 
1029
                        }
 
1030
                    }
 
1031
                    if (signature.equals(otherSignature)) {
 
1032
                        return false;
 
1033
                    }
 
1034
                }
 
1035
            }
 
1036
        }
 
1037
        return true;
 
1038
    }
 
1039
 
 
1040
    void generateSelectorsConst() {
 
1041
        TreeSet<String> set = new TreeSet<String>();
 
1042
        for (int x = 0; x < xmls.length; x++) {
 
1043
            Document document = documents[x];
 
1044
            if (document == null)
 
1045
                continue;
 
1046
            NodeList list = document.getDocumentElement().getChildNodes();
 
1047
            for (int i = 0; i < list.getLength(); i++) {
 
1048
                Node node = list.item(i);
 
1049
                if ("class".equals(node.getNodeName()) || "informal_protocol".equals(node.getNodeName())) {
 
1050
                    if (getGen(node)) {
 
1051
                        NodeList methods = node.getChildNodes();
 
1052
                        for (int j = 0; j < methods.getLength(); j++) {
 
1053
                            Node method = methods.item(j);
 
1054
                            if (getGen(method)) {
 
1055
                                NamedNodeMap mthAttributes = method.getAttributes();
 
1056
                                String sel = mthAttributes.getNamedItem("selector").getNodeValue();
 
1057
                                set.add(sel);
 
1058
                            }
 
1059
                        }
 
1060
                    }
 
1061
                }
 
1062
            }
 
1063
        }
 
1064
        set.add("alloc");
 
1065
        for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
 
1066
            String sel = iterator.next();
 
1067
            String selConst = getSelConst(sel);
 
1068
            out("public static final int /*long*/ ");
 
1069
            out(selConst);
 
1070
            out(" = ");
 
1071
            out("sel_registerName(\"");
 
1072
            out(sel);
 
1073
            out("\");");
 
1074
            outln();
 
1075
        }
 
1076
    }
 
1077
 
 
1078
    void generateStructNatives() {
 
1079
        TreeSet<String> set = new TreeSet<String>();
 
1080
        for (int x = 0; x < xmls.length; x++) {
 
1081
            Document document = documents[x];
 
1082
            if (document == null)
 
1083
                continue;
 
1084
            NodeList list = document.getDocumentElement().getChildNodes();
 
1085
            for (int i = 0; i < list.getLength(); i++) {
 
1086
                Node node = list.item(i);
 
1087
                if ("struct".equals(node.getNodeName()) && getGen(node)) {
 
1088
                    set.add(getIDAttribute(node).getNodeValue());
 
1089
                }
 
1090
            }
 
1091
        }
 
1092
        out("/** Sizeof natives */");
 
1093
        outln();
 
1094
        for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
 
1095
            String struct = iterator.next();
 
1096
            out("public static final native int ");
 
1097
            out(struct);
 
1098
            out("_sizeof();");
 
1099
            outln();
 
1100
        }
 
1101
        outln();
 
1102
        out("/** Memmove natives */");
 
1103
        outln();
 
1104
        outln();
 
1105
        for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
 
1106
            String struct = iterator.next();
 
1107
            out("/**");
 
1108
            outln();
 
1109
            out(" * @param dest cast=(void *),flags=no_in critical");
 
1110
            outln();
 
1111
            out(" * @param src cast=(void *),flags=critical");
 
1112
            // out(" * @param src cast=(void *),flags=no_out critical");
 
1113
            outln();
 
1114
            out(" */");
 
1115
            outln();
 
1116
            out("public static final native void memmove(");
 
1117
            out("int /*long*/ dest, ");
 
1118
            out(struct);
 
1119
            out(" src, int /*long*/ size);");
 
1120
            outln();
 
1121
            out("/**");
 
1122
            outln();
 
1123
            out(" * @param dest cast=(void *),flags=no_in critical");
 
1124
            outln();
 
1125
            out(" * @param src cast=(void *),flags=critical");
 
1126
            // out(" * @param src cast=(void *),flags=no_out critical");
 
1127
            outln();
 
1128
            out(" */");
 
1129
            outln();
 
1130
            out("public static final native void memmove(");
 
1131
            out(struct);
 
1132
            out(" dest, int /*long*/ src, int /*long*/ size);");
 
1133
            outln();
 
1134
        }
 
1135
    }
 
1136
 
 
1137
    String buildSend(Node method, boolean tags, boolean only64, boolean superCall) {
 
1138
        Node returnNode = getReturnNode(method.getChildNodes());
 
1139
        StringBuffer buffer = new StringBuffer();
 
1140
        buffer.append("public static final native ");
 
1141
        if (returnNode != null && isStruct(returnNode)) {
 
1142
            buffer.append("void ");
 
1143
            buffer.append(superCall ? "objc_msgSendSuper_stret" : "objc_msgSend_stret");
 
1144
            buffer.append("(");
 
1145
            buffer.append(getJavaType(returnNode));
 
1146
            buffer.append(" result, ");
 
1147
        } else if (returnNode != null && isFloatingPoint(returnNode)) {
 
1148
            buffer.append("double ");
 
1149
            buffer.append(superCall ? "objc_msgSendSuper_fpret" : "objc_msgSend_fpret");
 
1150
            buffer.append("(");
 
1151
        } else if (returnNode != null && isBoolean(returnNode)) {
 
1152
            buffer.append("boolean ");
 
1153
            buffer.append(superCall ? "objc_msgSendSuper_bool" : "objc_msgSend_bool");
 
1154
            buffer.append("(");
 
1155
        } else {
 
1156
            if (only64) {
 
1157
                buffer.append("long");
 
1158
            } else {
 
1159
                if (tags) {
 
1160
                    buffer.append("int /*long*/");
 
1161
                } else {
 
1162
                    buffer.append("int");
 
1163
                }
 
1164
            }
 
1165
            buffer.append(" ");
 
1166
            buffer.append(superCall ? "objc_msgSendSuper" : "objc_msgSend");
 
1167
            buffer.append("(");
 
1168
        }
 
1169
        if (superCall) {
 
1170
            if (only64) {
 
1171
                buffer.append("objc_super superId, long sel");
 
1172
            } else {
 
1173
                if (tags) {
 
1174
                    buffer.append("objc_super superId, int /*long*/ sel");
 
1175
                } else {
 
1176
                    buffer.append("objc_super superId, int sel");
 
1177
                }
 
1178
            }
 
1179
        } else {
 
1180
            if (only64) {
 
1181
                buffer.append("long id, long sel");
 
1182
            } else {
 
1183
                if (tags) {
 
1184
                    buffer.append("int /*long*/ id, int /*long*/ sel");
 
1185
                } else {
 
1186
                    buffer.append("int id, int sel");
 
1187
                }
 
1188
            }
 
1189
        }
 
1190
        NodeList params = method.getChildNodes();
 
1191
        boolean first = false;
 
1192
        int count = 0;
 
1193
        for (int k = 0; k < params.getLength(); k++) {
 
1194
            Node param = params.item(k);
 
1195
            if ("arg".equals(param.getNodeName())) {
 
1196
                if (!first)
 
1197
                    buffer.append(", ");
 
1198
                if (isStruct(param)) {
 
1199
                    buffer.append(getJavaType(param));
 
1200
                } else {
 
1201
                    String type = getType(param), type64 = getType64(param);
 
1202
                    buffer.append(only64 ? type64 : type);
 
1203
                    if (!only64 && tags && !type.equals(type64)) {
 
1204
                        buffer.append(" /*");
 
1205
                        buffer.append(type64);
 
1206
                        buffer.append("*/");
 
1207
                    }
 
1208
                }
 
1209
                first = false;
 
1210
                buffer.append(" arg");
 
1211
                buffer.append(String.valueOf(count++));
 
1212
            }
 
1213
        }
 
1214
        buffer.append(");");
 
1215
        return buffer.toString();
 
1216
    }
 
1217
 
 
1218
    String getCType(Node node) {
 
1219
        NamedNodeMap attributes = node.getAttributes();
 
1220
        return attributes.getNamedItem("declared_type").getNodeValue();
 
1221
    }
 
1222
 
 
1223
    Node findNSObjectMethod(Node method) {
 
1224
        NamedNodeMap methodAttributes = method.getAttributes();
 
1225
        String selector = methodAttributes.getNamedItem("selector").getNodeValue();
 
1226
        NodeList list = method.getParentNode().getParentNode().getChildNodes();
 
1227
        for (int i = 0; i < list.getLength(); i++) {
 
1228
            Node cls = list.item(i);
 
1229
            if ("class".equals(cls.getNodeName())) {
 
1230
                NamedNodeMap classAttributes = cls.getAttributes();
 
1231
                if ("NSObject".equals(classAttributes.getNamedItem("name").getNodeValue())) {
 
1232
                    NodeList methods = cls.getChildNodes();
 
1233
                    for (int j = 0; j < methods.getLength(); j++) {
 
1234
                        Node mth = methods.item(j);
 
1235
                        if ("method".equals(mth.getNodeName())) {
 
1236
                            NamedNodeMap mthAttributes = mth.getAttributes();
 
1237
                            if (selector.equals(mthAttributes.getNamedItem("selector").getNodeValue())) {
 
1238
                                return mth;
 
1239
                            }
 
1240
                        }
 
1241
                    }
 
1242
                }
 
1243
            }
 
1244
        }
 
1245
        return null;
 
1246
    }
 
1247
 
 
1248
    void generateCustomCallbacks() {
 
1249
        TreeMap<String, Node> set = new TreeMap<String, Node>();
 
1250
        for (int x = 0; x < xmls.length; x++) {
 
1251
            Document document = documents[x];
 
1252
            if (document == null)
 
1253
                continue;
 
1254
            NodeList list = document.getDocumentElement().getChildNodes();
 
1255
            for (int i = 0; i < list.getLength(); i++) {
 
1256
                Node node = list.item(i);
 
1257
                if (("class".equals(node.getNodeName()) || "informal_protocol".equals(node.getNodeName())) && getGen(node)) {
 
1258
                    NodeList methods = node.getChildNodes();
 
1259
                    for (int j = 0; j < methods.getLength(); j++) {
 
1260
                        Node method = methods.item(j);
 
1261
                        if ("method".equals(method.getNodeName()) && getGen(method) && getGenCallback(method)) {
 
1262
                            NamedNodeMap mthAttributes = method.getAttributes();
 
1263
                            String sel = mthAttributes.getNamedItem("selector").getNodeValue();
 
1264
                            set.put(sel, method);
 
1265
                        }
 
1266
                    }
 
1267
                }
 
1268
            }
 
1269
        }
 
1270
        for (Iterator<String> iterator = set.keySet().iterator(); iterator.hasNext();) {
 
1271
            String key = iterator.next();
 
1272
            Node method = set.get(key);
 
1273
            if ("informal_protocol".equals(method.getParentNode().getNodeName())) {
 
1274
                method = findNSObjectMethod(method);
 
1275
                if (method == null)
 
1276
                    continue;
 
1277
            }
 
1278
            String nativeMth = key.replaceAll(":", "_");
 
1279
            out("/** @method callback_types=");
 
1280
            Node returnNode = getReturnNode(method.getChildNodes());
 
1281
            out(returnNode == null ? "void" : getCType(returnNode));
 
1282
            out(";id;SEL;");
 
1283
            NodeList params = method.getChildNodes();
 
1284
            for (int k = 0; k < params.getLength(); k++) {
 
1285
                Node param = params.item(k);
 
1286
                if ("arg".equals(param.getNodeName())) {
 
1287
                    out(getCType(param));
 
1288
                    out(";");
 
1289
                }
 
1290
            }
 
1291
            out(",callback_flags=");
 
1292
            out(returnNode != null && isStruct(returnNode) ? "struct" : "none");
 
1293
            out(";none;none;");
 
1294
            for (int k = 0; k < params.getLength(); k++) {
 
1295
                Node param = params.item(k);
 
1296
                if ("arg".equals(param.getNodeName())) {
 
1297
                    out(isStruct(param) ? "struct" : "none");
 
1298
                    out(";");
 
1299
                }
 
1300
            }
 
1301
            out(" */");
 
1302
            outln();
 
1303
            out("public static final native int /*long*/ CALLBACK_");
 
1304
            out(nativeMth);
 
1305
            out("(int /*long*/ func);");
 
1306
            outln();
 
1307
        }
 
1308
    }
 
1309
 
 
1310
    void generateSends(boolean superCall) {
 
1311
        TreeMap<String, Node> set = new TreeMap<String, Node>();
 
1312
        TreeMap<String, Node> set64 = new TreeMap<String, Node>();
 
1313
        for (int x = 0; x < xmls.length; x++) {
 
1314
            Document document = documents[x];
 
1315
            if (document == null)
 
1316
                continue;
 
1317
            NodeList list = document.getDocumentElement().getChildNodes();
 
1318
            for (int i = 0; i < list.getLength(); i++) {
 
1319
                Node node = list.item(i);
 
1320
                if ("class".equals(node.getNodeName()) && getGen(node)) {
 
1321
                    NodeList methods = node.getChildNodes();
 
1322
                    for (int j = 0; j < methods.getLength(); j++) {
 
1323
                        Node method = methods.item(j);
 
1324
                        if ("method".equals(method.getNodeName()) && getGen(method) && (!superCall || getGenSuper(method))) {
 
1325
                            String code = buildSend(method, false, false, superCall);
 
1326
                            String code64 = buildSend(method, false, true, superCall);
 
1327
                            if (set.get(code) == null) {
 
1328
                                set.put(code, method);
 
1329
                            }
 
1330
                            if (set64.get(code64) == null) {
 
1331
                                set64.put(code64, method);
 
1332
                            }
 
1333
                        }
 
1334
                    }
 
1335
                }
 
1336
            }
 
1337
        }
 
1338
        outln();
 
1339
        TreeMap<String, Node> tagsSet = new TreeMap<String, Node>();
 
1340
        for (Iterator<String> iterator = set.keySet().iterator(); iterator.hasNext();) {
 
1341
            String key = iterator.next();
 
1342
            Node method = set.get(key);
 
1343
            String tagCode = buildSend(method, false, true, superCall);
 
1344
            if (set64.get(tagCode) != null) {
 
1345
                tagsSet.put(key, method);
 
1346
                iterator.remove();
 
1347
                set64.remove(tagCode);
 
1348
            }
 
1349
        }
 
1350
        TreeMap<String, Node> all = new TreeMap<String, Node>();
 
1351
        for (Iterator<String> iterator = tagsSet.keySet().iterator(); iterator.hasNext();) {
 
1352
            String key = iterator.next();
 
1353
            Node method = tagsSet.get(key);
 
1354
            all.put(buildSend(method, true, false, superCall), method);
 
1355
        }
 
1356
        for (Iterator<String> iterator = set.keySet().iterator(); iterator.hasNext();) {
 
1357
            String key = iterator.next();
 
1358
            all.put(key, set.get(key));
 
1359
        }
 
1360
        for (Iterator<String> iterator = set64.keySet().iterator(); iterator.hasNext();) {
 
1361
            String key = iterator.next();
 
1362
            all.put(key, set64.get(key));
 
1363
        }
 
1364
        for (Iterator<String> iterator = all.keySet().iterator(); iterator.hasNext();) {
 
1365
            String key = iterator.next();
 
1366
            Node method = all.get(key);
 
1367
            NodeList params = method.getChildNodes();
 
1368
            ArrayList<String> tags = new ArrayList<String>();
 
1369
            int count = 0;
 
1370
            for (int k = 0; k < params.getLength(); k++) {
 
1371
                Node param = params.item(k);
 
1372
                if ("arg".equals(param.getNodeName())) {
 
1373
                    if (isStruct(param)) {
 
1374
                        tags.add(" * @param arg" + count + " flags=struct");
 
1375
                    }
 
1376
                    count++;
 
1377
                }
 
1378
            }
 
1379
            out("/**");
 
1380
            if (tags.size() > 0) {
 
1381
                outln();
 
1382
                out(" *");
 
1383
            }
 
1384
            out(" @method flags=cast");
 
1385
            if (tags.size() > 0)
 
1386
                outln();
 
1387
            for (String tag : tags) {
 
1388
                out(tag);
 
1389
                outln();
 
1390
            }
 
1391
            out(" */");
 
1392
            outln();
 
1393
            out(key.toString());
 
1394
            outln();
 
1395
        }
 
1396
    }
 
1397
 
 
1398
    String getSelConst(String sel) {
 
1399
        return "sel_" + sel.replaceAll(":", "_");
 
1400
    }
 
1401
 
 
1402
    void generateClassesConst() {
 
1403
        TreeSet<String> set = new TreeSet<String>();
 
1404
        for (int x = 0; x < xmls.length; x++) {
 
1405
            Document document = documents[x];
 
1406
            if (document == null)
 
1407
                continue;
 
1408
            NodeList list = document.getDocumentElement().getChildNodes();
 
1409
            for (int i = 0; i < list.getLength(); i++) {
 
1410
                Node node = list.item(i);
 
1411
                if ("class".equals(node.getNodeName())) {
 
1412
                    if (getGen(node)) {
 
1413
                        NamedNodeMap attributes = node.getAttributes();
 
1414
                        String name = attributes.getNamedItem("name").getNodeValue();
 
1415
                        set.add(name);
 
1416
                    }
 
1417
                }
 
1418
            }
 
1419
        }
 
1420
        for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
 
1421
            String cls = iterator.next();
 
1422
            String clsConst = "class_" + cls;
 
1423
            out("public static final int /*long*/ ");
 
1424
            out(clsConst);
 
1425
            out(" = ");
 
1426
            out("objc_getClass(\"");
 
1427
            out(cls);
 
1428
            out("\");");
 
1429
            outln();
 
1430
        }
 
1431
    }
 
1432
 
 
1433
    void generateProtocolsConst() {
 
1434
        TreeSet<String> set = new TreeSet<String>();
 
1435
        for (int x = 0; x < xmls.length; x++) {
 
1436
            Document document = documents[x];
 
1437
            if (document == null)
 
1438
                continue;
 
1439
            NodeList list = document.getDocumentElement().getChildNodes();
 
1440
            for (int i = 0; i < list.getLength(); i++) {
 
1441
                Node node = list.item(i);
 
1442
                if ("informal_protocol".equals(node.getNodeName())) {
 
1443
                    if (getGen(node)) {
 
1444
                        NamedNodeMap attributes = node.getAttributes();
 
1445
                        String name = attributes.getNamedItem("name").getNodeValue();
 
1446
                        set.add(name);
 
1447
                    }
 
1448
                }
 
1449
            }
 
1450
        }
 
1451
        for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
 
1452
            String cls = iterator.next();
 
1453
            String clsConst = "protocol_" + cls;
 
1454
            out("public static final int /*long*/ ");
 
1455
            out(clsConst);
 
1456
            out(" = ");
 
1457
            out("objc_getProtocol(\"");
 
1458
            out(cls);
 
1459
            out("\");");
 
1460
            outln();
 
1461
        }
 
1462
    }
 
1463
 
 
1464
    String getPackageName(String className) {
 
1465
        int dot = mainClassName.lastIndexOf('.');
 
1466
        if (dot == -1)
 
1467
            return "";
 
1468
        return mainClassName.substring(0, dot);
 
1469
    }
 
1470
 
 
1471
    String getClassName(String className) {
 
1472
        int dot = mainClassName.lastIndexOf('.');
 
1473
        if (dot == -1)
 
1474
            return mainClassName;
 
1475
        return mainClassName.substring(dot + 1);
 
1476
    }
 
1477
 
 
1478
    Node getReturnNode(NodeList list) {
 
1479
        for (int j = 0; j < list.getLength(); j++) {
 
1480
            Node node = list.item(j);
 
1481
            if ("retval".equals(node.getNodeName())) {
 
1482
                return node;
 
1483
            }
 
1484
        }
 
1485
        return null;
 
1486
    }
 
1487
 
 
1488
    String getType(Node node) {
 
1489
        NamedNodeMap attributes = node.getAttributes();
 
1490
        Node javaType = attributes.getNamedItem("hawtjni_java_type");
 
1491
        if (javaType != null)
 
1492
            return javaType.getNodeValue();
 
1493
        String code = attributes.getNamedItem("type").getNodeValue();
 
1494
        return getType(code, attributes, false);
 
1495
    }
 
1496
 
 
1497
    String getType64(Node node) {
 
1498
        NamedNodeMap attributes = node.getAttributes();
 
1499
        Node javaType = attributes.getNamedItem("hawtjni_java_type");
 
1500
        if (javaType != null) {
 
1501
            Node javaType64 = attributes.getNamedItem("hawtjni_java_type64");
 
1502
            return javaType64 != null ? javaType64.getNodeValue() : javaType.getNodeValue();
 
1503
        }
 
1504
        Node attrib = attributes.getNamedItem("type");
 
1505
        String code = attrib.getNodeValue();
 
1506
        Node attrib64 = attributes.getNamedItem("type64");
 
1507
        if (attrib64 != null)
 
1508
            code = attrib64.getNodeValue();
 
1509
        return getType(code, attributes, true);
 
1510
    }
 
1511
 
 
1512
    String getType(String code, NamedNodeMap attributes, boolean is64) {
 
1513
        if (code.equals("c"))
 
1514
            return "byte";
 
1515
        if (code.equals("i"))
 
1516
            return "int";
 
1517
        if (code.equals("s"))
 
1518
            return "short";
 
1519
        if (code.equals("l"))
 
1520
            return "int";
 
1521
        if (code.equals("q"))
 
1522
            return "long";
 
1523
        if (code.equals("C"))
 
1524
            return "byte";
 
1525
        if (code.equals("I"))
 
1526
            return "int";
 
1527
        if (code.equals("S"))
 
1528
            return "short";
 
1529
        if (code.equals("L"))
 
1530
            return "int";
 
1531
        if (code.equals("Q"))
 
1532
            return "long";
 
1533
        if (code.equals("f"))
 
1534
            return "float";
 
1535
        if (code.equals("d"))
 
1536
            return "double";
 
1537
        if (code.equals("B"))
 
1538
            return "boolean";
 
1539
        if (code.equals("v"))
 
1540
            return "void";
 
1541
        if (code.equals("*"))
 
1542
            return is64 ? "long" : "int";
 
1543
        if (code.equals("@"))
 
1544
            return is64 ? "long" : "int";
 
1545
        if (code.equals("#"))
 
1546
            return is64 ? "long" : "int";
 
1547
        if (code.equals(":"))
 
1548
            return is64 ? "long" : "int";
 
1549
        if (code.startsWith("^"))
 
1550
            return is64 ? "long" : "int";
 
1551
        if (code.startsWith("{")) {
 
1552
            return attributes.getNamedItem("declared_type").getNodeValue();
 
1553
        }
 
1554
        return "BAD " + code;
 
1555
    }
 
1556
 
 
1557
    String getJNIType(Node node) {
 
1558
        NamedNodeMap attributes = node.getAttributes();
 
1559
        String code = attributes.getNamedItem("type").getNodeValue();
 
1560
        if (code.equals("c"))
 
1561
            return "B";
 
1562
        if (code.equals("i"))
 
1563
            return "I";
 
1564
        if (code.equals("s"))
 
1565
            return "S";
 
1566
        if (code.equals("l"))
 
1567
            return "I";
 
1568
        if (code.equals("q"))
 
1569
            return "J";
 
1570
        if (code.equals("C"))
 
1571
            return "B";
 
1572
        if (code.equals("I"))
 
1573
            return "I";
 
1574
        if (code.equals("S"))
 
1575
            return "S";
 
1576
        if (code.equals("L"))
 
1577
            return "I";
 
1578
        if (code.equals("Q"))
 
1579
            return "J";
 
1580
        if (code.equals("f"))
 
1581
            return "F";
 
1582
        if (code.equals("d"))
 
1583
            return "D";
 
1584
        if (code.equals("B"))
 
1585
            return "Z";
 
1586
        if (code.equals("v"))
 
1587
            return "V";
 
1588
        if (code.equals("*"))
 
1589
            return "I";
 
1590
        if (code.equals("@"))
 
1591
            return "I";
 
1592
        if (code.equals("#"))
 
1593
            return "I";
 
1594
        if (code.equals(":"))
 
1595
            return "I";
 
1596
        if (code.startsWith("^"))
 
1597
            return "I";
 
1598
        if (code.startsWith("["))
 
1599
            return "BAD " + code;
 
1600
        if (code.startsWith("{")) {
 
1601
            return "BAD " + code;
 
1602
        }
 
1603
        if (code.startsWith("("))
 
1604
            return "BAD " + code;
 
1605
        return "BAD " + code;
 
1606
    }
 
1607
 
 
1608
    String getJavaType(Node node) {
 
1609
        NamedNodeMap attributes = node.getAttributes();
 
1610
        Node javaType = attributes.getNamedItem("hawtjni_java_type");
 
1611
        if (javaType != null)
 
1612
            return javaType.getNodeValue().trim();
 
1613
        String code = attributes.getNamedItem("type").getNodeValue();
 
1614
        return getJavaType(code, attributes, false);
 
1615
    }
 
1616
 
 
1617
    String getJavaType64(Node node) {
 
1618
        NamedNodeMap attributes = node.getAttributes();
 
1619
        Node javaType = attributes.getNamedItem("hawtjni_java_type");
 
1620
        if (javaType != null) {
 
1621
            Node javaType64 = attributes.getNamedItem("hawtjni_java_type64");
 
1622
            return javaType64 != null ? javaType64.getNodeValue() : javaType.getNodeValue();
 
1623
        }
 
1624
        Node attrib = attributes.getNamedItem("type");
 
1625
        String code = attrib.getNodeValue();
 
1626
        Node attrib64 = attributes.getNamedItem("type64");
 
1627
        if (attrib64 != null)
 
1628
            code = attrib64.getNodeValue();
 
1629
        return getJavaType(code, attributes, true);
 
1630
    }
 
1631
 
 
1632
    String getJavaType(String code, NamedNodeMap attributes, boolean is64) {
 
1633
        if (code.equals("c"))
 
1634
            return "byte";
 
1635
        if (code.equals("i"))
 
1636
            return "int";
 
1637
        if (code.equals("s"))
 
1638
            return "short";
 
1639
        if (code.equals("l"))
 
1640
            return "int";
 
1641
        if (code.equals("q"))
 
1642
            return "long";
 
1643
        if (code.equals("C"))
 
1644
            return "byte";
 
1645
        if (code.equals("I"))
 
1646
            return "int";
 
1647
        if (code.equals("S"))
 
1648
            return "short";
 
1649
        if (code.equals("L"))
 
1650
            return "int";
 
1651
        if (code.equals("Q"))
 
1652
            return "long";
 
1653
        if (code.equals("f"))
 
1654
            return "float";
 
1655
        if (code.equals("d"))
 
1656
            return "double";
 
1657
        if (code.equals("B"))
 
1658
            return "boolean";
 
1659
        if (code.equals("v"))
 
1660
            return "void";
 
1661
        if (code.equals("*"))
 
1662
            return is64 ? "long" : "int";
 
1663
        if (code.equals("#"))
 
1664
            return is64 ? "long" : "int";
 
1665
        if (code.equals(":"))
 
1666
            return is64 ? "long" : "int";
 
1667
        if (code.startsWith("^"))
 
1668
            return is64 ? "long" : "int";
 
1669
        if (code.equals("@")) {
 
1670
            String type = attributes.getNamedItem("declared_type").getNodeValue();
 
1671
            int index = type.indexOf('*');
 
1672
            if (index != -1)
 
1673
                type = type.substring(0, index);
 
1674
            index = type.indexOf('<');
 
1675
            if (index != -1)
 
1676
                type = type.substring(0, index);
 
1677
            return type.trim();
 
1678
        }
 
1679
        if (code.startsWith("{")) {
 
1680
            return attributes.getNamedItem("declared_type").getNodeValue().trim();
 
1681
        }
 
1682
        return "BAD " + code;
 
1683
    }
 
1684
 
 
1685
    static String[] split(String str, String separator) {
 
1686
        StringTokenizer tk = new StringTokenizer(str, separator);
 
1687
        ArrayList<Object> result = new ArrayList<Object>();
 
1688
        while (tk.hasMoreElements()) {
 
1689
            result.add(tk.nextElement());
 
1690
        }
 
1691
        return result.toArray(new String[result.size()]);
 
1692
    }
 
1693
 
 
1694
    void generateFunctions() {
 
1695
        for (int x = 0; x < xmls.length; x++) {
 
1696
            Document document = documents[x];
 
1697
            if (document == null)
 
1698
                continue;
 
1699
            NodeList list = document.getDocumentElement().getChildNodes();
 
1700
            for (int i = 0; i < list.getLength(); i++) {
 
1701
                Node node = list.item(i);
 
1702
                if ("function".equals(node.getNodeName())) {
 
1703
                    if (getGen(node)) {
 
1704
                        NamedNodeMap attributes = node.getAttributes();
 
1705
                        String name = attributes.getNamedItem("name").getNodeValue();
 
1706
                        NodeList params = node.getChildNodes();
 
1707
                        int count = 0;
 
1708
                        for (int j = 0; j < params.getLength(); j++) {
 
1709
                            Node param = params.item(j);
 
1710
                            if ("arg".equals(param.getNodeName())) {
 
1711
                                count++;
 
1712
                            }
 
1713
                        }
 
1714
                        if (count > 0) {
 
1715
                            out("/**");
 
1716
                            outln();
 
1717
                        }
 
1718
                        for (int j = 0; j < params.getLength(); j++) {
 
1719
                            Node param = params.item(j);
 
1720
                            if ("arg".equals(param.getNodeName())) {
 
1721
                                NamedNodeMap paramAttributes = param.getAttributes();
 
1722
                                out(" * @param ");
 
1723
                                out(paramAttributes.getNamedItem("name").getNodeValue());
 
1724
                                if (isStruct(param)) {
 
1725
                                    out(" flags=struct");
 
1726
                                } else {
 
1727
                                    out(" cast=");
 
1728
                                    Node declaredType = paramAttributes.getNamedItem("declared_type");
 
1729
                                    String cast = declaredType.getNodeValue();
 
1730
                                    if (!cast.startsWith("("))
 
1731
                                        out("(");
 
1732
                                    out(cast);
 
1733
                                    if (!cast.endsWith(")"))
 
1734
                                        out(")");
 
1735
                                }
 
1736
                                outln();
 
1737
                            }
 
1738
                        }
 
1739
                        if (count > 0) {
 
1740
                            out(" */");
 
1741
                            outln();
 
1742
                        }
 
1743
                        out("public static final native ");
 
1744
                        Node returnNode = getReturnNode(node.getChildNodes());
 
1745
                        if (returnNode != null) {
 
1746
                            String type = getType(returnNode), type64 = getType64(returnNode);
 
1747
                            out(type);
 
1748
                            if (!type.equals(type64)) {
 
1749
                                out(" /*");
 
1750
                                out(type64);
 
1751
                                out("*/");
 
1752
                            }
 
1753
                            out(" ");
 
1754
                        } else {
 
1755
                            out("void ");
 
1756
                        }
 
1757
                        out(name);
 
1758
                        out("(");
 
1759
                        params = node.getChildNodes();
 
1760
                        boolean first = true;
 
1761
                        for (int j = 0; j < params.getLength(); j++) {
 
1762
                            Node param = params.item(j);
 
1763
                            if ("arg".equals(param.getNodeName())) {
 
1764
                                NamedNodeMap paramAttributes = param.getAttributes();
 
1765
                                if (!first)
 
1766
                                    out(", ");
 
1767
                                first = false;
 
1768
                                String type = getType(param), type64 = getType64(param);
 
1769
                                out(type);
 
1770
                                if (!type.equals(type64)) {
 
1771
                                    out(" /*");
 
1772
                                    out(type64);
 
1773
                                    out("*/");
 
1774
                                }
 
1775
                                out(" ");
 
1776
                                out(paramAttributes.getNamedItem("name").getNodeValue());
 
1777
                            }
 
1778
                        }
 
1779
                        generateVariadics(node);
 
1780
                        out(");");
 
1781
                        outln();
 
1782
                    }
 
1783
                }
 
1784
            }
 
1785
        }
 
1786
    }
 
1787
 
 
1788
    void generateVariadics(Node node) {
 
1789
        NamedNodeMap attributes = node.getAttributes();
 
1790
        Node variadicCount = attributes.getNamedItem("hawtjni_variadic_count");
 
1791
        if (variadicCount != null) {
 
1792
            Node variadicTypes = attributes.getNamedItem("hawtjni_variadic_java_types");
 
1793
            String[] types = null;
 
1794
            if (variadicTypes != null) {
 
1795
                types = split(variadicTypes.getNodeValue(), ",");
 
1796
            }
 
1797
            int varCount = 0;
 
1798
            try {
 
1799
                varCount = Integer.parseInt(variadicCount.getNodeValue());
 
1800
            } catch (NumberFormatException e) {
 
1801
            }
 
1802
            for (int j = 0; j < varCount; j++) {
 
1803
                out(", ");
 
1804
                if (types != null && types.length > j && !types[j].equals("*")) {
 
1805
                    out(types[j]);
 
1806
                } else if (types != null && types[types.length - 1].equals("*")) {
 
1807
                    out(types[types.length - 2]);
 
1808
                } else {
 
1809
                    out("int /*long*/");
 
1810
                }
 
1811
                out(" varArg");
 
1812
                out("" + j);
 
1813
            }
 
1814
        }
 
1815
    }
 
1816
 
 
1817
    public static void main(String[] args) {
 
1818
        try {
 
1819
            MacGenerator gen = new MacGenerator();
 
1820
            gen.setXmls(args);
 
1821
            gen.setOutputDir("../org.eclipse.hawtjni/Eclipse SWT PI/cocoa/");
 
1822
            gen.setMainClass("org.eclipse.hawtjni.internal.cocoa.OS");
 
1823
            gen.generate(null);
 
1824
        } catch (Throwable e) {
 
1825
            e.printStackTrace();
 
1826
        }
 
1827
    }
 
1828
}